From: jenkins-bot Date: Fri, 2 Feb 2018 19:46:37 +0000 (+0000) Subject: Merge "Add tablesUsed to RevisionStoreDbTest" X-Git-Tag: 1.31.0-rc.0~721 X-Git-Url: https://git.heureux-cyclage.org/?p=lhc%2Fweb%2Fwiklou.git;a=commitdiff_plain;h=689c847a32e7fe8a0b3a559a88a627a252c5018e;hp=1c65dd29a3c77173625b9a0f8b59ea1c1c12fc2c Merge "Add tablesUsed to RevisionStoreDbTest" --- diff --git a/.mailmap b/.mailmap index c2337c8be6..08e1aaa15f 100644 --- a/.mailmap +++ b/.mailmap @@ -197,7 +197,7 @@ Jack Phoenix Jackmcbarn Jackmcbarn jagori -James Forrester +James D. Forrester Jaime Crespo Jan Gerber Jan Luca Naumann diff --git a/CREDITS b/CREDITS index a8ca294142..95d6a6cfa6 100644 --- a/CREDITS +++ b/CREDITS @@ -281,7 +281,7 @@ The following list can be found parsed under Special:Version/Credits --> * Jaime Crespo * Jakub Vrana * James Earl Douglas -* James Forrester +* James D. Forrester * Jan Berkel * Jan Drewniak * Jan Gerber diff --git a/RELEASE-NOTES-1.31 b/RELEASE-NOTES-1.31 index 264113e18a..20bea0bd2a 100644 --- a/RELEASE-NOTES-1.31 +++ b/RELEASE-NOTES-1.31 @@ -50,7 +50,7 @@ production. ==== 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. @@ -190,6 +190,15 @@ changes to languages because of Phabricator reports. * 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, diff --git a/autoload.php b/autoload.php index 6fb2cc425b..168998e152 100644 --- a/autoload.php +++ b/autoload.php @@ -197,6 +197,7 @@ $wgAutoloadLocalClasses = [ 'BenchmarkLruHash' => __DIR__ . '/maintenance/benchmarks/benchmarkLruHash.php', 'BenchmarkParse' => __DIR__ . '/maintenance/benchmarks/benchmarkParse.php', 'BenchmarkPurge' => __DIR__ . '/maintenance/benchmarks/benchmarkPurge.php', + 'BenchmarkSanitizer' => __DIR__ . '/maintenance/benchmarks/benchmarkSanitizer.php', 'BenchmarkTidy' => __DIR__ . '/maintenance/benchmarks/benchmarkTidy.php', 'Benchmarker' => __DIR__ . '/maintenance/benchmarks/Benchmarker.php', 'BitmapHandler' => __DIR__ . '/includes/media/Bitmap.php', diff --git a/composer.json b/composer.json index 4596c4c05b..1730942f49 100644 --- a/composer.json +++ b/composer.json @@ -49,7 +49,7 @@ "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", diff --git a/docs/extension.schema.v2.json b/docs/extension.schema.v2.json index 51f9417d30..e13129bb56 100644 --- a/docs/extension.schema.v2.json +++ b/docs/extension.schema.v2.json @@ -669,7 +669,7 @@ }, "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", diff --git a/includes/DefaultSettings.php b/includes/DefaultSettings.php index 2b2695cdf7..4a625cbf77 100644 --- a/includes/DefaultSettings.php +++ b/includes/DefaultSettings.php @@ -1004,15 +1004,15 @@ $wgParserTestMediaHandlers = [ */ $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, ]; /** @@ -1817,7 +1817,7 @@ $wgDBtype = 'mysql'; * 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. */ @@ -1827,7 +1827,7 @@ $wgDBssl = false; * 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. */ @@ -1998,7 +1998,7 @@ $wgDBservers = false; * 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 @@ -2142,7 +2142,7 @@ $wgExternalStores = []; * ]; * @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 = []; @@ -2310,34 +2310,34 @@ $wgLanguageConverterCacheType = CACHE_ANYTHING; * 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 ], ]; /** @@ -2374,13 +2374,13 @@ $wgMainWANCache = 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' ] ] @@ -2527,7 +2527,7 @@ $wgAdaptiveMessageCache = false; * Use maintenance/rebuildLocalisationCache.php instead. */ $wgLocalisationCacheConf = [ - 'class' => 'LocalisationCache', + 'class' => LocalisationCache::class, 'store' => 'detect', 'storeClass' => false, 'storeDirectory' => false, @@ -3783,10 +3783,11 @@ $wgResourceLoaderValidateStaticJS = 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', ]; @@ -4166,8 +4167,8 @@ $wgInvalidRedirectTargets = [ 'Filepath', 'Mypage', 'Mytalk', 'Redirect' ]; * an extension setup function. */ $wgParserConf = [ - 'class' => 'Parser', - # 'preprocessorClass' => 'Preprocessor_Hash', + 'class' => Parser::class, + # 'preprocessorClass' => Preprocessor_Hash::class, ]; /** @@ -4471,7 +4472,7 @@ $wgActiveUserDays = 30; * @since 1.27 */ $wgCentralIdLookupProviders = [ - 'local' => [ 'class' => 'LocalIdLookup' ], + 'local' => [ 'class' => LocalIdLookup::class ], ]; /** @@ -4759,7 +4760,7 @@ $wgPasswordDefault = 'pbkdf2'; * An advanced example: * @code * $wgPasswordConfig['bcrypt-peppered'] = [ - * 'class' => 'EncryptedPassword', + * 'class' => EncryptedPassword::class, * 'underlying' => 'bcrypt', * 'secrets' => [], * 'cipher' => MCRYPT_RIJNDAEL_256, @@ -4772,31 +4773,31 @@ $wgPasswordDefault = 'pbkdf2'; */ $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', @@ -6106,7 +6107,7 @@ $wgDebugComments = false; * 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. */ @@ -6211,7 +6212,7 @@ $wgDebugLogGroups = []; * * @par To completely disable logging: * @code - * $wgMWLoggerDefaultSpi = [ 'class' => '\\MediaWiki\\Logger\\NullSpi' ]; + * $wgMWLoggerDefaultSpi = [ 'class' => \MediaWiki\Logger\NullSpi::class ]; * @endcode * * @since 1.25 @@ -6219,7 +6220,7 @@ $wgDebugLogGroups = []; * @see MwLogger */ $wgMWLoggerDefaultSpi = [ - 'class' => '\\MediaWiki\\Logger\\LegacySpi', + 'class' => \MediaWiki\Logger\LegacySpi::class, ]; /** @@ -6771,7 +6772,7 @@ $wgRCLinkDays = [ 1, 3, 7, 14, 30 ]; * 'omit_bots' => true, * ]; * @example $wgRCFeeds['example'] = [ - * 'class' => 'ExampleRCFeed', + * 'class' => ExampleRCFeed::class, * ]; * @since 1.22 */ @@ -6783,8 +6784,8 @@ $wgRCFeeds = []; * @since 1.22 */ $wgRCEngines = [ - 'redis' => 'RedisPubSubFeedEngine', - 'udp' => 'UDPRCFeedEngine', + 'redis' => RedisPubSubFeedEngine::class, + 'udp' => UDPRCFeedEngine::class, ]; /** @@ -6908,8 +6909,8 @@ $wgOverrideSiteFeed = []; * $wgOut->isSyndicated() is true. */ $wgFeedClasses = [ - 'rss' => 'RSSFeed', - 'atom' => 'AtomFeed', + 'rss' => RSSFeed::class, + 'atom' => AtomFeed::class, ]; /** @@ -7436,24 +7437,24 @@ $wgServiceWiringFiles = [ * 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, ]; /** @@ -7502,7 +7503,7 @@ $wgJobSerialCommitThreshold = false; * These settings should be global to all wikis. */ $wgJobTypeConf = [ - 'default' => [ 'class' => 'JobQueueDB', 'order' => 'random', 'claimTTL' => 3600 ], + 'default' => [ 'class' => JobQueueDB::class, 'order' => 'random', 'claimTTL' => 3600 ], ]; /** @@ -7510,7 +7511,7 @@ $wgJobTypeConf = [ * These settings should be global to all wikis. */ $wgJobQueueAggregator = [ - 'class' => 'JobQueueAggregatorNull' + 'class' => JobQueueAggregatorNull::class ]; /** @@ -7531,7 +7532,7 @@ $wgJobQueueIncludeInMaxLagFactor = false; * Expensive Querypages are already updated. */ $wgSpecialPageCacheUpdates = [ - 'Statistics' => [ 'SiteStatsUpdate', 'cacheUpdate' ] + 'Statistics' => [ SiteStatsUpdate::class, 'cacheUpdate' ] ]; /** @@ -7721,42 +7722,42 @@ $wgLogActions = []; * @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, ]; /** @@ -7887,7 +7888,7 @@ $wgActions = [ 'credits' => true, 'delete' => true, 'edit' => true, - 'editchangetags' => 'SpecialPageAction', + 'editchangetags' => SpecialPageAction::class, 'history' => true, 'info' => true, 'markpatrolled' => true, @@ -7896,7 +7897,7 @@ $wgActions = [ 'raw' => true, 'render' => true, 'revert' => true, - 'revisiondelete' => 'SpecialPageAction', + 'revisiondelete' => SpecialPageAction::class, 'rollback' => true, 'submit' => true, 'unprotect' => true, @@ -8045,12 +8046,12 @@ $wgDebugAPI = false; * @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 * @@ -8473,7 +8474,7 @@ $wgRedirectOnLogin = null; * @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 @@ -8485,7 +8486,7 @@ $wgRedirectOnLogin = null; * @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 @@ -8559,7 +8560,7 @@ $wgTextModelsToParse = [ * @since 1.20 */ $wgSiteTypes = [ - 'mediawiki' => 'MediaWikiSite', + 'mediawiki' => MediaWikiSite::class, ]; /** @@ -8633,7 +8634,7 @@ $wgPageLanguageUseDB = false; * Auto-mounting example for Parsoid: * * $wgVirtualRestConfig['paths']['/parsoid/'] = [ - * 'class' => 'ParsoidVirtualRESTService', + * 'class' => ParsoidVirtualRESTService::class, * 'options' => [ * 'url' => 'http://localhost:8000', * 'prefix' => 'enwiki', @@ -8730,7 +8731,7 @@ $wgMaxJobDBWriteDuration = false; */ $wgEventRelayerConfig = [ 'default' => [ - 'class' => 'EventRelayerNull', + 'class' => EventRelayerNull::class, ] ]; diff --git a/includes/EditPage.php b/includes/EditPage.php index d49f2051e9..6bf3c89213 100644 --- a/includes/EditPage.php +++ b/includes/EditPage.php @@ -2472,12 +2472,22 @@ ERROR; $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' ) + ); } /** diff --git a/includes/HistoryBlob.php b/includes/HistoryBlob.php index 075b48d225..26a6d45bf8 100644 --- a/includes/HistoryBlob.php +++ b/includes/HistoryBlob.php @@ -707,7 +707,7 @@ if ( false ) { // 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' ); } diff --git a/includes/Message.php b/includes/Message.php index e55eaaf646..fac9a59893 100644 --- a/includes/Message.php +++ b/includes/Message.php @@ -1245,7 +1245,14 @@ class Message implements MessageSpecifier, Serializable { ); return $out instanceof ParserOutput - ? $out->getText( [ 'enableSectionEditLinks' => false ] ) + ? $out->getText( [ + 'enableSectionEditLinks' => false, + // Wrapping messages in an extra
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; } diff --git a/includes/Preferences.php b/includes/Preferences.php index f65b2ce15e..26e28baf47 100644 --- a/includes/Preferences.php +++ b/includes/Preferences.php @@ -267,7 +267,7 @@ class Preferences { public static function getFormObject( $user, IContextSource $context, - $formClass = 'PreferencesForm', + $formClass = PreferencesForm::class, array $remove = [] ) { $preferencesFactory = self::getDefaultPreferencesFactory(); diff --git a/includes/Setup.php b/includes/Setup.php index 3e37c9c9c1..c9fe8d0fe8 100644 --- a/includes/Setup.php +++ b/includes/Setup.php @@ -249,12 +249,12 @@ $wgNamespaceAliases['Image_talk'] = NS_FILE_TALK; */ $wgLockManagers[] = [ 'name' => 'fsLockManager', - 'class' => 'FSLockManager', + 'class' => FSLockManager::class, 'lockDirectory' => "{$wgUploadDirectory}/lockdir", ]; $wgLockManagers[] = [ 'name' => 'nullLockManager', - 'class' => 'NullLockManager', + 'class' => NullLockManager::class, ]; /** @@ -276,7 +276,7 @@ $wgGalleryOptions += [ */ if ( !$wgLocalFileRepo ) { $wgLocalFileRepo = [ - 'class' => 'LocalRepo', + 'class' => LocalRepo::class, 'name' => 'local', 'directory' => $wgUploadDirectory, 'scriptDirUrl' => $wgScriptPath, @@ -295,7 +295,7 @@ if ( !$wgLocalFileRepo ) { if ( $wgUseSharedUploads ) { if ( $wgSharedUploadDBname ) { $wgForeignFileRepos[] = [ - 'class' => 'ForeignDBRepo', + 'class' => ForeignDBRepo::class, 'name' => 'shared', 'directory' => $wgSharedUploadDirectory, 'url' => $wgSharedUploadPath, @@ -315,7 +315,7 @@ if ( $wgUseSharedUploads ) { ]; } else { $wgForeignFileRepos[] = [ - 'class' => 'FileRepo', + 'class' => FileRepo::class, 'name' => 'shared', 'directory' => $wgSharedUploadDirectory, 'url' => $wgSharedUploadPath, @@ -329,7 +329,7 @@ if ( $wgUseSharedUploads ) { } 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', @@ -349,7 +349,7 @@ if ( !isset( $wgLocalFileRepo['backend'] ) ) { $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'] ) ) { @@ -538,16 +538,16 @@ if ( $wgNewUserLog ) { $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' ) { @@ -698,7 +698,7 @@ if ( $wgMainWANCache === false ) { // 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' ] ]; @@ -736,20 +736,22 @@ if ( !$wgDBerrorLogTZ ) { // 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 ) { diff --git a/includes/SiteStats.php b/includes/SiteStats.php index ce87596a5f..f10e6a2d40 100644 --- a/includes/SiteStats.php +++ b/includes/SiteStats.php @@ -33,7 +33,6 @@ class SiteStats { /** @var bool */ private static $loaded = false; - /** @var int[] */ private static $pageCount = []; @@ -55,14 +54,6 @@ class SiteStats { 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; } @@ -84,20 +75,27 @@ class SiteStats { } } - 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; @@ -108,15 +106,7 @@ class SiteStats { * @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__ ); } /** @@ -248,6 +238,21 @@ class SiteStats { 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? * @@ -404,6 +409,21 @@ class SiteStatsInit { } } + /** + * 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 */ diff --git a/includes/WebRequest.php b/includes/WebRequest.php index cd62737c56..7bfb5a43e4 100644 --- a/includes/WebRequest.php +++ b/includes/WebRequest.php @@ -956,7 +956,7 @@ class WebRequest { 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; diff --git a/includes/api/ApiMain.php b/includes/api/ApiMain.php index 5056b6def7..2c2dd9ab23 100644 --- a/includes/api/ApiMain.php +++ b/includes/api/ApiMain.php @@ -55,72 +55,72 @@ class ApiMain extends ApiBase { * 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, ]; /** diff --git a/includes/api/ApiModuleManager.php b/includes/api/ApiModuleManager.php index 2619a7c858..e02c862778 100644 --- a/includes/api/ApiModuleManager.php +++ b/includes/api/ApiModuleManager.php @@ -78,12 +78,12 @@ class ApiModuleManager extends ContextSource { * @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 * diff --git a/includes/api/ApiPageSet.php b/includes/api/ApiPageSet.php index 30611b630f..48303a5748 100644 --- a/includes/api/ApiPageSet.php +++ b/includes/api/ApiPageSet.php @@ -1528,7 +1528,7 @@ class ApiPageSet extends ApiBase { $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; } } diff --git a/includes/api/ApiParse.php b/includes/api/ApiParse.php index cf1fd1ede9..2839ab9453 100644 --- a/includes/api/ApiParse.php +++ b/includes/api/ApiParse.php @@ -344,6 +344,7 @@ class ApiParse extends ApiBase { $result_array['text'] = $p_result->getText( [ 'allowTOC' => !$params['disabletoc'], 'enableSectionEditLinks' => !$params['disableeditsection'], + 'unwrap' => $params['wrapoutputclass'] === '', ] ); $result_array[ApiResult::META_BC_SUBELEMENTS][] = 'text'; } @@ -538,9 +539,9 @@ class ApiParse extends ApiBase { if ( $params['disabletidy'] ) { $popts->setTidy( false ); } - $popts->setWrapOutputClass( - $params['wrapoutputclass'] === '' ? false : $params['wrapoutputclass'] - ); + if ( $params['wrapoutputclass'] !== '' ) { + $popts->setWrapOutputClass( $params['wrapoutputclass'] ); + } $reset = null; $suppressCache = false; diff --git a/includes/api/ApiQuery.php b/includes/api/ApiQuery.php index 5bbd21176e..e49024d1ed 100644 --- a/includes/api/ApiQuery.php +++ b/includes/api/ApiQuery.php @@ -40,26 +40,26 @@ class ApiQuery extends ApiBase { * @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, ]; /** @@ -67,41 +67,41 @@ class ApiQuery extends ApiBase { * @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, ]; /** @@ -109,12 +109,12 @@ class ApiQuery extends ApiBase { * @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, ]; /** diff --git a/includes/api/ApiQueryInfo.php b/includes/api/ApiQueryInfo.php index 23a327b15a..5294b1d8e7 100644 --- a/includes/api/ApiQueryInfo.php +++ b/includes/api/ApiQueryInfo.php @@ -103,15 +103,15 @@ class ApiQueryInfo extends ApiQueryBase { } $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 ] ); @@ -314,7 +314,7 @@ class ApiQueryInfo extends ApiQueryBase { $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 diff --git a/includes/api/ApiQueryRecentChanges.php b/includes/api/ApiQueryRecentChanges.php index 4549987434..517cf1f860 100644 --- a/includes/api/ApiQueryRecentChanges.php +++ b/includes/api/ApiQueryRecentChanges.php @@ -61,7 +61,7 @@ class ApiQueryRecentChanges extends ApiQueryGeneratorBase { } $this->tokenFunctions = [ - 'patrol' => [ 'ApiQueryRecentChanges', 'getPatrolToken' ] + 'patrol' => [ self::class, 'getPatrolToken' ] ]; Hooks::run( 'APIQueryRecentChangesTokens', [ &$this->tokenFunctions ] ); diff --git a/includes/api/ApiQueryRevisions.php b/includes/api/ApiQueryRevisions.php index aa9a39c1cb..ef0223aae5 100644 --- a/includes/api/ApiQueryRevisions.php +++ b/includes/api/ApiQueryRevisions.php @@ -56,7 +56,7 @@ class ApiQueryRevisions extends ApiQueryRevisionsBase { } $this->tokenFunctions = [ - 'rollback' => [ 'ApiQueryRevisions', 'getRollbackToken' ] + 'rollback' => [ self::class, 'getRollbackToken' ] ]; Hooks::run( 'APIQueryRevisionsTokens', [ &$this->tokenFunctions ] ); diff --git a/includes/api/ApiQuerySiteinfo.php b/includes/api/ApiQuerySiteinfo.php index acae8899e5..f924736de0 100644 --- a/includes/api/ApiQuerySiteinfo.php +++ b/includes/api/ApiQuerySiteinfo.php @@ -848,7 +848,7 @@ class ApiQuerySiteinfo extends ApiQueryBase { 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' ); diff --git a/includes/api/ApiQueryUsers.php b/includes/api/ApiQueryUsers.php index 9261003bc7..6de512b878 100644 --- a/includes/api/ApiQueryUsers.php +++ b/includes/api/ApiQueryUsers.php @@ -73,7 +73,7 @@ class ApiQueryUsers extends ApiQueryBase { } $this->tokenFunctions = [ - 'userrights' => [ 'ApiQueryUsers', 'getUserrightsToken' ], + 'userrights' => [ self::class, 'getUserrightsToken' ], ]; Hooks::run( 'APIQueryUsersTokens', [ &$this->tokenFunctions ] ); diff --git a/includes/api/ApiTokens.php b/includes/api/ApiTokens.php index 606967d64c..ff1914c870 100644 --- a/includes/api/ApiTokens.php +++ b/includes/api/ApiTokens.php @@ -62,11 +62,11 @@ class ApiTokens extends ApiBase { 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 ] ); diff --git a/includes/api/ApiUpload.php b/includes/api/ApiUpload.php index e8a2061e9a..93e432b951 100644 --- a/includes/api/ApiUpload.php +++ b/includes/api/ApiUpload.php @@ -724,26 +724,26 @@ class ApiUpload extends ApiBase { */ 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: diff --git a/includes/api/i18n/de.json b/includes/api/i18n/de.json index 218454d5a1..4da95097d5 100644 --- a/includes/api/i18n/de.json +++ b/includes/api/i18n/de.json @@ -22,7 +22,7 @@ "Tacsipacsi" ] }, - "apihelp-main-extended-description": "
\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
\nStatus: 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\nFehlerhafte Anfragen: 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\nTesten: Zum einfachen Testen von API-Anfragen, siehe [[Special:ApiSandbox]].", + "apihelp-main-extended-description": "
\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
\nStatus: 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\nFehlerhafte Anfragen: 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

Testen: Zum einfachen Testen von API-Anfragen, siehe [[Special:ApiSandbox]].

", "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 maxlag zurückgegeben mit einer Nachricht wie Waiting for $host: $lag seconds lagged.
Siehe [[mw:Special:MyLanguage/Manual:Maxlag_parameter|Handbuch: Maxlag parameter]] für weitere Informationen.", diff --git a/includes/api/i18n/en.json b/includes/api/i18n/en.json index a897f06658..729c4c75f5 100644 --- a/includes/api/i18n/en.json +++ b/includes/api/i18n/en.json @@ -7,7 +7,7 @@ }, "apihelp-main-summary": "", - "apihelp-main-extended-description": "
\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
\nStatus: 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\nErroneous requests: 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\nTesting: For ease of testing API requests, see [[Special:ApiSandbox]].", + "apihelp-main-extended-description": "
\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
\nStatus: 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\nErroneous requests: 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

Testing: For ease of testing API requests, see [[Special:ApiSandbox]].

", "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 maxlag is returned with a message like Waiting for $host: $lag seconds lagged.
See [[mw:Special:MyLanguage/Manual:Maxlag_parameter|Manual: Maxlag parameter]] for more information.", diff --git a/includes/api/i18n/fa.json b/includes/api/i18n/fa.json index 5af3bda008..a799d00f7d 100644 --- a/includes/api/i18n/fa.json +++ b/includes/api/i18n/fa.json @@ -191,6 +191,7 @@ "apihelp-opensearch-param-suggest": "کاری نکنید اگر [[mw:Manual:$wgEnableOpenSearchSuggest|$wgEnableOpenSearchSuggest]] false است.", "apihelp-opensearch-param-format": "فرمت خروجی.", "apihelp-opensearch-example-te": "یافتن صفحه‌هایی که با Te آغاز می‌شوند", + "apihelp-options-summary": "تغییر ترجیحات کاربر جاری", "apihelp-options-param-reset": "ترجیحات را به مقادیر پیش فرض سایت بازمی گرداند.", "apihelp-options-example-reset": "بازنشانی همه تنظیمات.", "apihelp-paraminfo-param-helpformat": "ساختار راهنمای رشته‌ها", diff --git a/includes/api/i18n/fr.json b/includes/api/i18n/fr.json index 2f27b58110..d72b218359 100644 --- a/includes/api/i18n/fr.json +++ b/includes/api/i18n/fr.json @@ -33,7 +33,7 @@ "Kenjiraw" ] }, - "apihelp-main-extended-description": "
\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
\nÉtat : 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\nRequêtes erronées : 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\nTest : Pour faciliter le test des requêtes de l’API, voyez [[Special:ApiSandbox]].", + "apihelp-main-extended-description": "
\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
\nÉtat : 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\nRequêtes erronées : 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

Test : Pour faciliter le test des requêtes de l’API, voyez [[Special:ApiSandbox]].

", "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 maxlag est renvoyé avec un message tel que Attente de $host : $lag secondes de délai.
Voyez [[mw:Special:MyLanguage/Manual:Maxlag_parameter|Manuel: Maxlag parameter]] pour plus d’information.", diff --git a/includes/api/i18n/hu.json b/includes/api/i18n/hu.json index 02915a743a..7c03097460 100644 --- a/includes/api/i18n/hu.json +++ b/includes/api/i18n/hu.json @@ -10,7 +10,7 @@ "Dj" ] }, - "apihelp-main-extended-description": "
\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
\nStátusz: 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\nHibás kérések: 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\nTesztelés: Az API-kérések könnyebb teszteléséhez használható az [[Special:ApiSandbox|API-homokozó]].", + "apihelp-main-extended-description": "
\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
\nStátusz: 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\nHibás kérések: 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

Tesztelés: Az API-kérések könnyebb teszteléséhez használható az [[Special:ApiSandbox|API-homokozó]].

", "apihelp-main-param-action": "Milyen műveletet hajtson végre.", "apihelp-main-param-format": "A kimenet formátuma.", "apihelp-main-param-smaxage": "Az s-maxage 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.", diff --git a/includes/api/i18n/it.json b/includes/api/i18n/it.json index 568203622f..25da0e6e4b 100644 --- a/includes/api/i18n/it.json +++ b/includes/api/i18n/it.json @@ -19,7 +19,7 @@ "Margherita.mignanelli" ] }, - "apihelp-main-extended-description": "
\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
\nStato: 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\nIstruzioni sbagliate: 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\nTest: per testare facilmente le richieste API, vedi [[Special:ApiSandbox]].", + "apihelp-main-extended-description": "
\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
\nStato: 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\nIstruzioni sbagliate: 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

Test: per testare facilmente le richieste API, vedi [[Special:ApiSandbox]].

", "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 user, o che abbia i permessi di bot se si è impostato bot.", diff --git a/includes/api/i18n/ja.json b/includes/api/i18n/ja.json index 094c406164..f51b03fe0c 100644 --- a/includes/api/i18n/ja.json +++ b/includes/api/i18n/ja.json @@ -15,7 +15,7 @@ "Omotecho" ] }, - "apihelp-main-extended-description": "
\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
\n状態: このページに表示されている機能は全て動作するはずですが、この API は未だ活発に開発されており、変更される可能性があります。アップデートの通知を受け取るには、[https://lists.wikimedia.org/pipermail/mediawiki-api-announce/ the mediawiki-api-announce メーリングリスト]に参加してください。\n\n誤ったリクエスト: 誤ったリクエストが API に送られた場合、\"MediaWiki-API-Error\" HTTP ヘッダーが送信され、そのヘッダーの値と送り返されるエラーコードは同じ値にセットされます。より詳しい情報は [[mw:Special:MyLanguage/API:Errors_and_warnings|API: Errors and warnings]] を参照してください。\n\nテスト: API のリクエストのテストは、[[Special:ApiSandbox]]で簡単に行えます。", + "apihelp-main-extended-description": "
\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
\n状態: このページに表示されている機能は全て動作するはずですが、この API は未だ活発に開発されており、変更される可能性があります。アップデートの通知を受け取るには、[https://lists.wikimedia.org/pipermail/mediawiki-api-announce/ the mediawiki-api-announce メーリングリスト]に参加してください。\n\n誤ったリクエスト: 誤ったリクエストが API に送られた場合、\"MediaWiki-API-Error\" HTTP ヘッダーが送信され、そのヘッダーの値と送り返されるエラーコードは同じ値にセットされます。より詳しい情報は [[mw:Special:MyLanguage/API:Errors_and_warnings|API: Errors and warnings]] を参照してください。\n\n

テスト: API のリクエストのテストは、[[Special:ApiSandbox]]で簡単に行えます。

", "apihelp-main-param-action": "実行する操作です。", "apihelp-main-param-format": "出力する形式です。", "apihelp-main-param-smaxage": "s-maxage HTTP キャッシュ コントロール ヘッダー に、この秒数を設定します。エラーがキャッシュされることはありません。", diff --git a/includes/api/i18n/pt.json b/includes/api/i18n/pt.json index f4a4662c63..aa697fbdb9 100644 --- a/includes/api/i18n/pt.json +++ b/includes/api/i18n/pt.json @@ -8,13 +8,14 @@ "Hamilton Abreu", "Mansil", "Felipe L. Ewald", - "Athena in Wonderland" + "Athena in Wonderland", + "Waldir" ] }, - "apihelp-main-extended-description": "
\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
\nEstado: 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\nPedidos incorretos: 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\nTestes: Para testar facilmente pedidos à API, visite [[Special:ApiSandbox|Testes da API]].", + "apihelp-main-extended-description": "
\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
\nEstado: 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\nPedidos incorretos: 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

\nTestes: Para testar facilmente pedidos à API, visite [[Special:ApiSandbox|Testes da API]].\n

", "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 maxlag é devolvido com uma mensagem como À espera do servidor $host: $lag segundos de atraso.
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 maxlag é devolvido com uma mensagem como À espera do servidor $host: $lag segundos de atraso.
Consulte [[mw:Special:MyLanguage/Manual:Maxlag_parameter|Manual: Parâmetro maxlag]] para mais informações.", "apihelp-main-param-smaxage": "Definir no cabeçalho HTTP s-maxage 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 max-age 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 user, verificar que o utilizador está autenticado. Se definido com o valor bot, verificar que o utilizador tem o privilégio de conta robô.", @@ -303,7 +304,7 @@ "apihelp-opensearch-example-te": "Encontrar as páginas que começam por Te.", "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 userjs- (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 $1reset 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 (|), 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 $1optionvalue.", @@ -401,7 +402,7 @@ "apihelp-purge-example-simple": "Purgar as páginas Main Page e API.", "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.", @@ -410,7 +411,7 @@ "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 query-continue 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 Main Page.", + "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 Main Page.", "apihelp-query-example-allpages": "Obter as revisões das páginas que começam por API/.", "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.", @@ -490,7 +491,7 @@ "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. * (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.).", @@ -719,7 +720,7 @@ "apihelp-query+embeddedin-example-simple": "Mostrar as páginas que transcluem Template:Stub.", "apihelp-query+embeddedin-example-generator": "Obter informação sobre as páginas que transcluem Template:Stub.", "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 $1query está definido, o protocolo é http. Deixe este parâmetro e $1query 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.", @@ -839,7 +840,7 @@ "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 Main Page.", "apihelp-query+info-example-protection": "Obter informação geral e de proteção sobre a página Main Page.", - "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 $1blprefix.", @@ -884,10 +885,10 @@ "apihelp-query+langlinks-example-simple": "Obter as hiperligações interlínguas da página Main Page.", "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 Main Page.", + "apihelp-query+links-example-simple": "Obter as hiperligações da página Main Page.", "apihelp-query+links-example-generator": "Obter informação sobre as páginas ligadas na página Main Page.", "apihelp-query+links-example-namespaces": "Obter as hiperligações da página Main Page 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.", @@ -1083,14 +1084,14 @@ "apihelp-query+search-example-simple": "Pesquisar meaning.", "apihelp-query+search-example-text": "Pesquisar meaning nos textos.", "apihelp-query+search-example-generator": "Obter informação sobre as páginas devolvidas por uma pesquisa do termo meaning.", - "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 $1inlanguagecode).", "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.", @@ -1106,14 +1107,14 @@ "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 [[mw:Special:MyLanguage/Manual:$wgHooks|$wgHooks]]).", "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.", diff --git a/includes/api/i18n/zh-hans.json b/includes/api/i18n/zh-hans.json index bb87dd1781..c081ffc69c 100644 --- a/includes/api/i18n/zh-hans.json +++ b/includes/api/i18n/zh-hans.json @@ -26,7 +26,7 @@ "NeverBehave" ] }, - "apihelp-main-extended-description": "
\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
\n状态信息:本页所展示的所有特性都应正常工作,但是API仍在开发当中,将会随时变化。请订阅[https://lists.wikimedia.org/pipermail/mediawiki-api-announce/ mediawiki-api-announce 邮件列表]以便获得更新通知。\n\n错误请求:当API收到错误请求时,HTTP header将会返回一个包含\"MediaWiki-API-Error\"的值,随后header的值与error code将会送回并设置为相同的值。详细信息请参阅[[mw:Special:MyLanguage/API:Errors_and_warnings|API:错误与警告]]。\n\n测试中:测试API请求的易用性,请参见[[Special:ApiSandbox]]。", + "apihelp-main-extended-description": "
\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
\n状态信息:本页所展示的所有特性都应正常工作,但是API仍在开发当中,将会随时变化。请订阅[https://lists.wikimedia.org/pipermail/mediawiki-api-announce/ mediawiki-api-announce 邮件列表]以便获得更新通知。\n\n错误请求:当API收到错误请求时,HTTP header将会返回一个包含\"MediaWiki-API-Error\"的值,随后header的值与error code将会送回并设置为相同的值。详细信息请参阅[[mw:Special:MyLanguage/API:Errors_and_warnings|API:错误与警告]]。\n\n

测试中:测试API请求的易用性,请参见[[Special:ApiSandbox]]。

", "apihelp-main-param-action": "要执行的操作。", "apihelp-main-param-format": "输出的格式。", "apihelp-main-param-maxlag": "最大延迟可被用于MediaWiki安装于数据库复制集中。要保存导致更多网站复制延迟的操作,此参数可使客户端等待直到复制延迟少于指定值时。万一发生过多延迟,错误代码maxlag会返回消息,例如等待$host中:延迟$lag秒。
参见[[mw:Special:MyLanguage/Manual:Maxlag_parameter|手册:Maxlag参数]]以获取更多信息。", diff --git a/includes/cache/MessageCache.php b/includes/cache/MessageCache.php index 48721866aa..63c03af25b 100644 --- a/includes/cache/MessageCache.php +++ b/includes/cache/MessageCache.php @@ -193,7 +193,6 @@ class MessageCache { $po = ParserOptions::newFromAnon(); $po->setEditSection( false ); $po->setAllowUnsafeRawHtml( false ); - $po->setWrapOutputClass( false ); return $po; } @@ -203,11 +202,6 @@ class MessageCache { // from malicious sources. As a precaution, disable // the parser tag when parsing messages. $this->mParserOptions->setAllowUnsafeRawHtml( false ); - // Wrapping messages in an extra
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; @@ -1126,7 +1120,7 @@ class MessageCache { $wgParser->firstCallInit(); # Clone it and store it $class = $wgParserConf['class']; - if ( $class == 'ParserDiffTest' ) { + if ( $class == ParserDiffTest::class ) { # Uncloneable $this->mParser = new $class( $wgParserConf ); } else { diff --git a/includes/cache/localisation/LocalisationCache.php b/includes/cache/localisation/LocalisationCache.php index 5e0a688e81..26382aab1e 100644 --- a/includes/cache/localisation/LocalisationCache.php +++ b/includes/cache/localisation/LocalisationCache.php @@ -199,22 +199,22 @@ class LocalisationCache { 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: diff --git a/includes/changes/CategoryMembershipChange.php b/includes/changes/CategoryMembershipChange.php index 6fa6907007..f095b64f82 100644 --- a/includes/changes/CategoryMembershipChange.php +++ b/includes/changes/CategoryMembershipChange.php @@ -71,7 +71,7 @@ class CategoryMembershipChange { $this->timestamp = $revision->getTimestamp(); } $this->revision = $revision; - $this->newForCategorizationCallback = [ 'RecentChange', 'newForCategorization' ]; + $this->newForCategorizationCallback = [ RecentChange::class, 'newForCategorization' ]; } /** diff --git a/includes/changetags/ChangeTags.php b/includes/changetags/ChangeTags.php index 95848ea085..7e4dd006ac 100644 --- a/includes/changetags/ChangeTags.php +++ b/includes/changetags/ChangeTags.php @@ -408,19 +408,24 @@ class ChangeTags { 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; diff --git a/includes/changetags/ChangeTagsList.php b/includes/changetags/ChangeTagsList.php index afbbb2bf5b..1559e1d6f7 100644 --- a/includes/changetags/ChangeTagsList.php +++ b/includes/changetags/ChangeTagsList.php @@ -43,10 +43,10 @@ abstract class ChangeTagsList extends RevisionListBase { ) { 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" ); diff --git a/includes/db/DatabaseOracle.php b/includes/db/DatabaseOracle.php index e2feb1fa7c..90fabaf5c4 100644 --- a/includes/db/DatabaseOracle.php +++ b/includes/db/DatabaseOracle.php @@ -354,7 +354,7 @@ class DatabaseOracle extends Database { return $e['code']; } - function affectedRows() { + protected function fetchAffectedRowCount() { return $this->mAffectedRows; } diff --git a/includes/db/MWLBFactory.php b/includes/db/MWLBFactory.php index aa1918d51f..5c79117f78 100644 --- a/includes/db/MWLBFactory.php +++ b/includes/db/MWLBFactory.php @@ -46,7 +46,7 @@ abstract class MWLBFactory { $lbConf += [ 'localDomain' => new DatabaseDomain( $mainConfig->get( 'DBname' ), - null, + $mainConfig->get( 'DBmwschema' ), $mainConfig->get( 'DBprefix' ) ), 'profiler' => Profiler::instance(), @@ -64,7 +64,7 @@ abstract class MWLBFactory { // 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' ) ) ) { @@ -132,7 +132,7 @@ abstract class MWLBFactory { 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' ); diff --git a/includes/debug/logger/LegacySpi.php b/includes/debug/logger/LegacySpi.php index 8e750cab25..cb0e066cd2 100644 --- a/includes/debug/logger/LegacySpi.php +++ b/includes/debug/logger/LegacySpi.php @@ -26,7 +26,7 @@ namespace MediaWiki\Logger; * Usage: * @code * $wgMWLoggerDefaultSpi = [ - * 'class' => '\\MediaWiki\\Logger\\LegacySpi', + * 'class' => \MediaWiki\Logger\LegacySpi::class, * ]; * @endcode * diff --git a/includes/debug/logger/MonologSpi.php b/includes/debug/logger/MonologSpi.php index 197b269b0a..645eca9d35 100644 --- a/includes/debug/logger/MonologSpi.php +++ b/includes/debug/logger/MonologSpi.php @@ -40,7 +40,7 @@ use ObjectFactory; * default SPI provider: * @code * $wgMWLoggerDefaultSpi = [ - * 'class' => '\\MediaWiki\\Logger\\MonologSpi', + * 'class' => \MediaWiki\Logger\MonologSpi::class, * 'args' => [ [ * 'loggers' => [ * '@default' => [ @@ -54,29 +54,29 @@ use ObjectFactory; * ], * '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 ); @@ -88,7 +88,7 @@ use ObjectFactory; * 'buffer' => true, * ], * 'udp2log' => [ - * 'class' => '\\MediaWiki\\Logger\\Monolog\\LegacyHandler', + * 'class' => \MediaWiki\Logger\Monolog\LegacyHandler::class, * 'args' => [ * 'udp://127.0.0.1:8420/mediawiki * ], @@ -97,10 +97,10 @@ use ObjectFactory; * ], * '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 ], * ], * ], diff --git a/includes/debug/logger/NullSpi.php b/includes/debug/logger/NullSpi.php index 4862157d8c..d65c185133 100644 --- a/includes/debug/logger/NullSpi.php +++ b/includes/debug/logger/NullSpi.php @@ -29,7 +29,7 @@ use Psr\Log\NullLogger; * Usage: * * $wgMWLoggerDefaultSpi = [ - * 'class' => '\\MediaWiki\\Logger\\NullSpi', + * 'class' => \MediaWiki\Logger\NullSpi::class, * ]; * * @see \MediaWiki\Logger\LoggerFactory diff --git a/includes/deferred/MWCallableUpdate.php b/includes/deferred/MWCallableUpdate.php index 5b822af492..9803b7a491 100644 --- a/includes/deferred/MWCallableUpdate.php +++ b/includes/deferred/MWCallableUpdate.php @@ -14,14 +14,18 @@ class MWCallableUpdate implements DeferrableUpdate, DeferrableCallback { /** * @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 ); + } } } diff --git a/includes/diff/DifferenceEngine.php b/includes/diff/DifferenceEngine.php index 7e05be6675..e76bffcace 100644 --- a/includes/diff/DifferenceEngine.php +++ b/includes/diff/DifferenceEngine.php @@ -650,6 +650,12 @@ class DifferenceEngine extends ContextSource { } } + /** + * @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() ); diff --git a/includes/exception/MWException.php b/includes/exception/MWException.php index 6d95919a87..16f226c78f 100644 --- a/includes/exception/MWException.php +++ b/includes/exception/MWException.php @@ -55,7 +55,7 @@ class MWException extends Exception { global $wgLang; foreach ( $this->getTrace() as $frame ) { - if ( isset( $frame['class'] ) && $frame['class'] === 'LocalisationCache' ) { + if ( isset( $frame['class'] ) && $frame['class'] === LocalisationCache::class ) { return false; } } diff --git a/includes/exception/MWExceptionHandler.php b/includes/exception/MWExceptionHandler.php index d863a2bb58..205ec77773 100644 --- a/includes/exception/MWExceptionHandler.php +++ b/includes/exception/MWExceptionHandler.php @@ -300,7 +300,7 @@ TXT; $logger = LoggerFactory::getInstance( 'fatal' ); $logger->error( $msg, [ 'fatal_exception' => [ - 'class' => 'ErrorException', + 'class' => ErrorException::class, 'message' => "PHP Fatal Error: {$message}", 'code' => $level, 'file' => $file, diff --git a/includes/exception/MWExceptionRenderer.php b/includes/exception/MWExceptionRenderer.php index b22e87bf4a..dc8dfd0b3e 100644 --- a/includes/exception/MWExceptionRenderer.php +++ b/includes/exception/MWExceptionRenderer.php @@ -90,7 +90,7 @@ class MWExceptionRenderer { 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; } } diff --git a/includes/filebackend/FileBackendGroup.php b/includes/filebackend/FileBackendGroup.php index 8182d62ec6..9239c6cc34 100644 --- a/includes/filebackend/FileBackendGroup.php +++ b/includes/filebackend/FileBackendGroup.php @@ -91,7 +91,7 @@ class FileBackendGroup { // Get the FS backend configuration $autoBackends[] = [ 'name' => $backendName, - 'class' => 'FSFileBackend', + 'class' => FSFileBackend::class, 'lockManager' => 'fsLockManager', 'containerPaths' => [ "{$repoName}-public" => "{$directory}", @@ -155,7 +155,7 @@ class FileBackendGroup { $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. @@ -190,9 +190,9 @@ class FileBackendGroup { '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' ), @@ -202,7 +202,7 @@ class FileBackendGroup { 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; } diff --git a/includes/filebackend/lockmanager/LockManagerGroup.php b/includes/filebackend/lockmanager/LockManagerGroup.php index e6f992c321..5d79dac0c2 100644 --- a/includes/filebackend/lockmanager/LockManagerGroup.php +++ b/includes/filebackend/lockmanager/LockManagerGroup.php @@ -116,7 +116,7 @@ class LockManagerGroup { 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'] ); diff --git a/includes/filerepo/FileRepo.php b/includes/filerepo/FileRepo.php index 5d22b8d80d..6b32953449 100644 --- a/includes/filerepo/FileRepo.php +++ b/includes/filerepo/FileRepo.php @@ -124,7 +124,7 @@ class FileRepo { 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 */ @@ -132,6 +132,13 @@ class FileRepo { /** @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 @@ -159,7 +166,7 @@ class FileRepo { $optionalSettings = [ 'descBaseUrl', 'scriptDirUrl', 'articleUrl', 'fetchDescription', 'thumbScriptUrl', 'pathDisclosureProtection', 'descriptionCacheExpiry', - 'scriptExtension', 'favicon' + 'scriptExtension', 'favicon', 'thumbProxyUrl', 'thumbProxySecret' ]; foreach ( $optionalSettings as $var ) { if ( isset( $info[$var] ) ) { @@ -611,6 +618,24 @@ class FileRepo { 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 * @@ -1722,7 +1747,7 @@ class FileRepo { * @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; diff --git a/includes/filerepo/ForeignAPIRepo.php b/includes/filerepo/ForeignAPIRepo.php index 45a5c8247f..5a37701285 100644 --- a/includes/filerepo/ForeignAPIRepo.php +++ b/includes/filerepo/ForeignAPIRepo.php @@ -29,7 +29,7 @@ use MediaWiki\Logger\LoggerFactory; * Example config: * * $wgForeignFileRepos[] = [ - * 'class' => 'ForeignAPIRepo', + * 'class' => ForeignAPIRepo::class, * 'name' => 'shared', * 'apibase' => 'https://en.wikipedia.org/w/api.php', * 'fetchDescription' => true, // Optional @@ -53,7 +53,7 @@ class ForeignAPIRepo extends FileRepo { '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) diff --git a/includes/filerepo/ForeignDBRepo.php b/includes/filerepo/ForeignDBRepo.php index bce3005c67..7879448bb6 100644 --- a/includes/filerepo/ForeignDBRepo.php +++ b/includes/filerepo/ForeignDBRepo.php @@ -58,9 +58,9 @@ class ForeignDBRepo extends LocalRepo { 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 diff --git a/includes/filerepo/ForeignDBViaLBRepo.php b/includes/filerepo/ForeignDBViaLBRepo.php index bcd253fb4a..249cd27cfe 100644 --- a/includes/filerepo/ForeignDBViaLBRepo.php +++ b/includes/filerepo/ForeignDBViaLBRepo.php @@ -37,10 +37,10 @@ class ForeignDBViaLBRepo extends LocalRepo { 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; diff --git a/includes/filerepo/LocalRepo.php b/includes/filerepo/LocalRepo.php index f5b83ae5cc..1bf534649f 100644 --- a/includes/filerepo/LocalRepo.php +++ b/includes/filerepo/LocalRepo.php @@ -34,17 +34,17 @@ use Wikimedia\Rdbms\IDatabase; */ 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 ); diff --git a/includes/filerepo/file/File.php b/includes/filerepo/file/File.php index 4e79de2d56..cfbd062a35 100644 --- a/includes/filerepo/file/File.php +++ b/includes/filerepo/file/File.php @@ -148,7 +148,7 @@ abstract class File implements IDBAccessObject { 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 = []; diff --git a/includes/filerepo/file/ForeignAPIFile.php b/includes/filerepo/file/ForeignAPIFile.php index 16c154f788..8dcb289abd 100644 --- a/includes/filerepo/file/ForeignAPIFile.php +++ b/includes/filerepo/file/ForeignAPIFile.php @@ -33,7 +33,7 @@ class ForeignAPIFile extends File { /** @var array */ private $mInfo = []; - protected $repoClass = 'ForeignApiRepo'; + protected $repoClass = ForeignApiRepo::class; /** * @param Title|string|bool $title diff --git a/includes/filerepo/file/LocalFile.php b/includes/filerepo/file/LocalFile.php index 4248f953e1..7be8f06246 100644 --- a/includes/filerepo/file/LocalFile.php +++ b/includes/filerepo/file/LocalFile.php @@ -84,7 +84,7 @@ class LocalFile extends File { protected $deleted; /** @var string */ - protected $repoClass = 'LocalRepo'; + protected $repoClass = LocalRepo::class; /** @var int Number of line to return by nextHistoryLine() (constructor) */ private $historyLine; diff --git a/includes/gallery/ImageGalleryBase.php b/includes/gallery/ImageGalleryBase.php index 700c8ee50f..318329726a 100644 --- a/includes/gallery/ImageGalleryBase.php +++ b/includes/gallery/ImageGalleryBase.php @@ -113,12 +113,12 @@ abstract class ImageGalleryBase extends ContextSource { 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 ] ); diff --git a/includes/htmlform/HTMLForm.php b/includes/htmlform/HTMLForm.php index 296c4b3bb9..afb815f2d4 100644 --- a/includes/htmlform/HTMLForm.php +++ b/includes/htmlform/HTMLForm.php @@ -128,44 +128,44 @@ 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; diff --git a/includes/htmlform/HTMLFormElement.php b/includes/htmlform/HTMLFormElement.php index 66d6143329..2830b9c258 100644 --- a/includes/htmlform/HTMLFormElement.php +++ b/includes/htmlform/HTMLFormElement.php @@ -1,7 +1,7 @@ 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 ) ] ); diff --git a/includes/htmlform/HTMLFormField.php b/includes/htmlform/HTMLFormField.php index 9c301e6aa7..aab881129b 100644 --- a/includes/htmlform/HTMLFormField.php +++ b/includes/htmlform/HTMLFormField.php @@ -673,7 +673,7 @@ abstract class HTMLFormField { } /** - * 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. * @@ -686,7 +686,7 @@ abstract class HTMLFormField { /** * 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[] */ diff --git a/includes/htmlform/fields/HTMLMultiSelectField.php b/includes/htmlform/fields/HTMLMultiSelectField.php index 09bacadb69..e8a7e992ca 100644 --- a/includes/htmlform/fields/HTMLMultiSelectField.php +++ b/includes/htmlform/fields/HTMLMultiSelectField.php @@ -102,7 +102,7 @@ class HTMLMultiSelectField extends HTMLFormField implements HTMLNestedFilterable 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 ) . ' ' . diff --git a/includes/htmlform/fields/HTMLRadioField.php b/includes/htmlform/fields/HTMLRadioField.php index c98e1ec07b..f3bcc0e1eb 100644 --- a/includes/htmlform/fields/HTMLRadioField.php +++ b/includes/htmlform/fields/HTMLRadioField.php @@ -78,7 +78,7 @@ class HTMLRadioField extends HTMLFormField { $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 ) { diff --git a/includes/http/MWHttpRequest.php b/includes/http/MWHttpRequest.php index fff72ec09f..ac16032ca3 100644 --- a/includes/http/MWHttpRequest.php +++ b/includes/http/MWHttpRequest.php @@ -181,7 +181,7 @@ abstract class MWHttpRequest implements LoggerAwareInterface { * @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 ); diff --git a/includes/import/WikiImporter.php b/includes/import/WikiImporter.php index 5978550c54..8991f5ef4d 100644 --- a/includes/import/WikiImporter.php +++ b/includes/import/WikiImporter.php @@ -65,7 +65,7 @@ class WikiImporter { $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 ); diff --git a/includes/installer/DatabaseUpdater.php b/includes/installer/DatabaseUpdater.php index 176d0af7f5..2083500ed0 100644 --- a/includes/installer/DatabaseUpdater.php +++ b/includes/installer/DatabaseUpdater.php @@ -1072,7 +1072,7 @@ abstract class DatabaseUpdater { "maintenance/populateLogUsertext.php.\n" ); - $task = $this->maintenance->runChild( 'PopulateLogUsertext' ); + $task = $this->maintenance->runChild( PopulateLogUsertext::class ); $task->execute(); $this->output( "done.\n" ); } @@ -1088,7 +1088,7 @@ abstract class DatabaseUpdater { "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" ); } @@ -1128,7 +1128,7 @@ abstract class DatabaseUpdater { } $this->output( "Updating category collations..." ); - $task = $this->maintenance->runChild( 'UpdateCollation' ); + $task = $this->maintenance->runChild( UpdateCollation::class ); $task->execute(); $this->output( "...done.\n" ); } @@ -1139,7 +1139,7 @@ abstract class DatabaseUpdater { */ 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" ); } @@ -1177,7 +1177,9 @@ abstract class DatabaseUpdater { /** * @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(); @@ -1224,7 +1226,7 @@ abstract class DatabaseUpdater { "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" ); } @@ -1236,7 +1238,7 @@ abstract class DatabaseUpdater { */ 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" ); } diff --git a/includes/installer/Installer.php b/includes/installer/Installer.php index 5ea9bfea32..e42146d51b 100644 --- a/includes/installer/Installer.php +++ b/includes/installer/Installer.php @@ -364,7 +364,7 @@ abstract class Installer { // disable (problematic) object cache types explicitly, preserving all other (working) ones // bug T113843 - $emptyCache = [ 'class' => 'EmptyBagOStuff' ]; + $emptyCache = [ 'class' => EmptyBagOStuff::class ]; $objectCaches = [ CACHE_NONE => $emptyCache, @@ -447,7 +447,6 @@ abstract class Installer { $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' ) ); } @@ -689,6 +688,7 @@ abstract class Installer { $out = $wgParser->parse( $text, $this->parserTitle, $this->parserOptions, $lineStart ); $html = $out->getText( [ 'enableSectionEditLinks' => false, + 'unwrap' => true, ] ); } catch ( MediaWiki\Services\ServiceDisabledException $e ) { $html = ' ' . htmlspecialchars( $text ); @@ -1677,7 +1677,7 @@ abstract class Installer { // implementation that won't stomp on PHP's cookies. $GLOBALS['wgSessionProviders'] = [ [ - 'class' => 'InstallerSessionProvider', + 'class' => InstallerSessionProvider::class, 'args' => [ [ 'priority' => 1, ] ] diff --git a/includes/installer/InstallerOverrides.php b/includes/installer/InstallerOverrides.php index eba3a20d6c..c9154b9a86 100644 --- a/includes/installer/InstallerOverrides.php +++ b/includes/installer/InstallerOverrides.php @@ -30,9 +30,9 @@ class InstallerOverrides { 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; diff --git a/includes/installer/MysqlUpdater.php b/includes/installer/MysqlUpdater.php index 44086a125e..bce540557d 100644 --- a/includes/installer/MysqlUpdater.php +++ b/includes/installer/MysqlUpdater.php @@ -432,7 +432,7 @@ class MysqlUpdater extends DatabaseUpdater { } protected function doOldLinksUpdate() { - $cl = $this->maintenance->runChild( 'ConvertLinks' ); + $cl = $this->maintenance->runChild( ConvertLinks::class ); $cl->execute(); } @@ -942,7 +942,7 @@ class MysqlUpdater extends DatabaseUpdater { $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(); } @@ -965,7 +965,7 @@ class MysqlUpdater extends DatabaseUpdater { "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" ); } @@ -977,7 +977,7 @@ class MysqlUpdater extends DatabaseUpdater { "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(); } } diff --git a/includes/installer/SqliteInstaller.php b/includes/installer/SqliteInstaller.php index d5909f4e1f..31718fefa0 100644 --- a/includes/installer/SqliteInstaller.php +++ b/includes/installer/SqliteInstaller.php @@ -321,7 +321,7 @@ EOT; return "# SQLite-specific settings \$wgSQLiteDataDir = \"{$dir}\"; \$wgObjectCaches[CACHE_DB] = [ - 'class' => 'SqlBagOStuff', + 'class' => SqlBagOStuff::class, 'loggroup' => 'SQLBagOStuff', 'server' => [ 'type' => 'sqlite', diff --git a/includes/installer/i18n/de.json b/includes/installer/i18n/de.json index 9a79e344cd..bd944f14e9 100644 --- a/includes/installer/i18n/de.json +++ b/includes/installer/i18n/de.json @@ -234,7 +234,7 @@ "config-license-cc-0": "''Creative Commons'' „Zero“ (Gemeinfreiheit)", "config-license-gfdl": "GNU-Lizenz für freie Dokumentation 1.3 oder höher", "config-license-pd": "Gemeinfreiheit", - "config-license-cc-choose": "Eine benutzerdefinierte Creative-Commons-Lizenz auswählen", + "config-license-cc-choose": "Eine andere Creative-Commons-Lizenz auswählen", "config-license-help": "Viele öffentliche Wikis publizieren alle Beiträge unter einer [http://freedomdefined.org/Definition/De freien Lizenz.]\nDies trägt dazu bei, ein Gefühl von Gemeinschaft zu schaffen, und ermutigt zu längerfristiger Mitarbeit.\nHingegen ist im Allgemeinen eine freie Lizenz auf geschlossenen Wikis nicht notwendig.\n\nSofern man Texte aus der Wikipedia verwenden möchte und umgekehrt, sollte die Lizenz {{int:config-license-cc-by-sa}} gewählt werden.\n\nDie Wikipedia nutzte vormals die GNU-Lizenz für freie Dokumentation (GFDL).\nDie GFDL ist eine gültige Lizenz, die allerdings schwer zu verstehen ist.\nEs ist zudem schwierig, gemäß dieser Lizenz lizenzierte Inhalte wiederzuverwenden.", "config-email-settings": "E-Mail-Einstellungen", "config-enable-email": "Ausgehende E-Mails ermöglichen", diff --git a/includes/installer/i18n/fa.json b/includes/installer/i18n/fa.json index 97a09a3e9c..75252b7bb9 100644 --- a/includes/installer/i18n/fa.json +++ b/includes/installer/i18n/fa.json @@ -317,6 +317,7 @@ "config-install-mainpage-failed": "قادر به درج صفحهٔ اصلی نمی‌باشد:$1", "config-install-done": "'''تبریک!'''\nبا موفقیت مدیاویکی را نصب کردید.\nبرنامه نصب‌کننده پرونده LocalSettings.php را درست کرد.\nکه شامل تمام تنظیمات می‌باشد.\n\nشما نیاز به دریافت آن دارید و آن را در پایهٔ نصب ویکی قرار دهید (همان پوشهٔ index.php). دریافت باید به صورت خودکار شروع شده‌باشد.\n\nاگر دریافت شروع نشد یا اگر آن را لغو کردید با کلیک روی پیوند زیر می‌توانید آن را دریافت کنید:\n\n$3\n\n'''توجه داشته باشید:''' اگر این را الآن انجام ندهید، این پرونده تولیدشده در صورتی که نصب را بدون دریافت آن تمام کردید بعداً در اختیار شما قرار نخواهد گرفت.\n\nوقتی انجام شد شما می‌توانید '''[$2 وارد ویکی شوید]'''.", "config-install-done-path": "تبریک!\nمدیاویکی با موفقیت نصب گردید.\nبرنامه نصب‌کننده یک پرونده LocalSettings.php ایجاد کرده است که شامل تمام تنظیمات می‌باشد.\n\nلازم است شما آن را دریافت کرده و در $4 قرار دهید. اِن دریافت می باِست به صورت خودکار شروع شده‌باشد.\n\nاگر دریافت شروع نشده بود و یا آن را لغو کرده اید با کلیک روی پیوند زیر می‌توانید آن را دریافت کنید:\n\n$3\n\nتوجه: اگر این کار را هم اکنون انجام ندهید و بدون دریافت آن از برنامه نصب خارج شويد، این پرونده تنظیمات تولیدشده در آینده در اختیار شما قرار نخواهد داشت.\n\nوقتی که آن کار را انجام داديد، می‌توانید [$2 وارد ويکی خودتان شويد].", + "config-install-success": "مدیاویکی به صورت موفقیت‌آمیز نصب شد. شما می‌توانید\nاز <$1$2> برای دیدن ویکی‌تان بازدید کنید.\nاگر پرسشی داشتید، فهرست سوال‌های متداول ما را مطالعه کنید:\n یا از یکی از انجمن‌های پشیبانی ما که در آن صفحه فهرست شده‌اند استفاده کنید.", "config-download-localsettings": "دریافت LocalSettings.php", "config-help": "راهنما", "config-help-tooltip": "برای گسترش کلیک کنید", diff --git a/includes/installer/i18n/pt.json b/includes/installer/i18n/pt.json index 760986d01d..228064452a 100644 --- a/includes/installer/i18n/pt.json +++ b/includes/installer/i18n/pt.json @@ -67,7 +67,7 @@ "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": "Aviso: 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": "Aviso: 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": "Aviso: 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 ./configure --with-mysqli.\nSe instalou o PHP a partir de um pacote Debian ou Ubuntu, então precisa de instalar também, por exemplo, o pacote php5-mysql.", "config-outdated-sqlite": "Aviso: Tem a versão $1 do SQLite, que é anterior à versão mínima necessária, a $2. O SQLite não estará disponível.", @@ -193,7 +193,7 @@ "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", @@ -261,13 +261,13 @@ "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)", diff --git a/includes/installer/i18n/sr-ec.json b/includes/installer/i18n/sr-ec.json index b492208bb8..2e65c8764f 100644 --- a/includes/installer/i18n/sr-ec.json +++ b/includes/installer/i18n/sr-ec.json @@ -83,7 +83,7 @@ "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": "ГНУ-ова лиценца за слободну документацију верзија 1.3 или новија верзија", + "config-license-gfdl": "ГНУ-ова лиценца за слободну документацију издање 1.3 или новије", "config-license-pd": "Јавно власништво", "config-email-settings": "Подешавања имејла", "config-cc-not-chosen": "Одаберите која Кријејтив комонс лиценца вам одговара и потврдите.", @@ -103,5 +103,5 @@ "config-skins-screenshots": "„$1” (снимци екрана: $2)", "config-screenshot": "снимак екрана", "mainpagetext": "Медијавики је успешно инсталиран.", - "mainpagedocfooter": "Погледајте [https://www.mediawiki.org/wiki/Special:MyLanguage/Help:Contents кориснички водич] за коришћење програма.\n\n== Увод ==\n* [https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:Configuration_settings Помоћ у вези са подешавањима]\n* [https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:FAQ Често постављена питања]\n* [https://lists.wikimedia.org/mailman/listinfo/mediawiki-announce Дописна листа о издањима Медијавикија]\n* [https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:Combating_spam Научите како да се борете против спама на Вашој вики]" + "mainpagedocfooter": "Погледајте [https://www.mediawiki.org/wiki/Special:MyLanguage/Help:Contents кориснички водич] за коришћење програма.\n\n== Увод ==\n* [https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:Configuration_settings Помоћ у вези са подешавањима]\n* [https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:FAQ Често постављена питања]\n* [https://lists.wikimedia.org/mailman/listinfo/mediawiki-announce Дописни списак о издањима Медијавикија]\n* [https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:Combating_spam Научите како да се борите против спама на Вашој вики]" } diff --git a/includes/installer/i18n/uk.json b/includes/installer/i18n/uk.json index 54339c3b3d..a5b630a3fd 100644 --- a/includes/installer/i18n/uk.json +++ b/includes/installer/i18n/uk.json @@ -12,7 +12,8 @@ "아라", "Amire80", "Piramidion", - "Macofe" + "Macofe", + "Movses" ] }, "config-desc": "Інсталятор MediaWiki", @@ -314,6 +315,7 @@ "config-install-mainpage-failed": "Не вдається вставити головну сторінку: $1", "config-install-done": "Вітаємо!\nВи успішно встановили MediaWiki.\n\nІнсталятор згенерував файл LocalSettings.php, який містить усі Ваші налаштування.\n\nВам необхідно завантажити його і помістити у кореневу папку Вашої вікі (туди ж, де index.php). Завантаження мало початись автоматично.\n\nЯкщо завантаження не почалось або Ви його скасували, можете заново його почати, натиснувши на посилання внизу:\n\n$3\n\nПримітка: Якщо Ви не зробите цього зараз, цей файл не буде доступним пізніше, коли Ви вийдете з встановлення, не скачавши його.\n\nПісля виконання дій, описаних вище, Ви зможете [$2 увійти у свою вікі].", "config-install-done-path": "Вітаємо!\nВи встановили Медіавікі.\n\nІнсталятор створив файл LocalSettings.php.\nУ ньому містяться всі Ваші налаштування.\n\nВам потрібно завантажити його й помістити в $4. Завантаження повинно було автоматично розпочатись.\n\nЯкщо завантаження не було запропоновано, або Ви його скасували, Ви можете перезапустити завантаження натиснувши на посилання нижче:\n\n$3\n\nЗверніть увагу: Якщо Ви не зробите це зараз, цей згенерований файл налаштувань не буде доступним для Вас пізніше якщо Ви вийдете зі встановлення не завантаживши його.\n\nКоли це було зроблено Ви можете [$2 зайти до своєї вікі].", + "config-install-success": "Mediawiki успішно встановлено. Зараз ви можете перейти до <$1$2>, щоб переглянути свою вікі. Якщо у вас є питання, ознайомтеся з нашим FAQ: або використовуйте один з форумів підтримки, які вказано на цій сторінці.", "config-download-localsettings": "Завантажити LocalSettings.php", "config-help": "допомога", "config-help-tooltip": "натисніть, щоб розгорнути", diff --git a/includes/libs/MultiHttpClient.php b/includes/libs/MultiHttpClient.php index 16168e6b59..3282ae2054 100644 --- a/includes/libs/MultiHttpClient.php +++ b/includes/libs/MultiHttpClient.php @@ -421,9 +421,14 @@ class MultiHttpClient implements LoggerAwareInterface { /** * @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 ); diff --git a/includes/libs/XhprofData.php b/includes/libs/XhprofData.php index 8762446a03..5af22ed5b2 100644 --- a/includes/libs/XhprofData.php +++ b/includes/libs/XhprofData.php @@ -209,14 +209,14 @@ class XhprofData { foreach ( $this->inclusive as $func => $stats ) { foreach ( $stats as $name => $value ) { if ( $value instanceof RunningStat ) { - $total = $value->m1 * $value->n; + $total = $value->getMean() * $value->getCount(); $percent = ( isset( $main[$name] ) && $main[$name] ) ? 100 * $total / $main[$name] : 0; $this->inclusive[$func][$name] = [ 'total' => $total, 'min' => $value->min, - 'mean' => $value->m1, + 'mean' => $value->getMean(), 'max' => $value->max, 'variance' => $value->m2, 'percent' => $percent, diff --git a/includes/libs/filebackend/FileBackend.php b/includes/libs/filebackend/FileBackend.php index 51308c1371..08f960a646 100644 --- a/includes/libs/filebackend/FileBackend.php +++ b/includes/libs/filebackend/FileBackend.php @@ -175,7 +175,7 @@ abstract class FileBackend implements LoggerAwareInterface { : 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'] : ''; @@ -1597,7 +1597,7 @@ abstract class FileBackend implements LoggerAwareInterface { 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(); } diff --git a/includes/libs/filebackend/FileBackendStore.php b/includes/libs/filebackend/FileBackendStore.php index b8eec3f01d..da8b4ce9da 100644 --- a/includes/libs/filebackend/FileBackendStore.php +++ b/includes/libs/filebackend/FileBackendStore.php @@ -1008,13 +1008,13 @@ abstract class FileBackendStore extends FileBackend { */ 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 diff --git a/includes/libs/lockmanager/MemcLockManager.php b/includes/libs/lockmanager/MemcLockManager.php index aecdf60cda..6274d60518 100644 --- a/includes/libs/lockmanager/MemcLockManager.php +++ b/includes/libs/lockmanager/MemcLockManager.php @@ -69,10 +69,10 @@ class MemcLockManager extends QuorumLockManager { $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." ); } diff --git a/includes/libs/objectcache/WANObjectCache.php b/includes/libs/objectcache/WANObjectCache.php index 409f507969..d9398196f5 100644 --- a/includes/libs/objectcache/WANObjectCache.php +++ b/includes/libs/objectcache/WANObjectCache.php @@ -47,17 +47,23 @@ use Psr\Log\NullLogger; * 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. @@ -87,6 +93,12 @@ class WANObjectCache implements IExpiringStore, LoggerAwareInterface { 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 */ @@ -200,6 +212,16 @@ class WANObjectCache implements IExpiringStore, LoggerAwareInterface { * 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 /// key prefixes as routes. This + * requires that "region" and "cluster" are both set above. [optional] */ public function __construct( array $params ) { $this->cache = $params['cache']; @@ -209,6 +231,10 @@ class WANObjectCache implements IExpiringStore, LoggerAwareInterface { $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; @@ -419,6 +445,12 @@ class WANObjectCache implements IExpiringStore, LoggerAwareInterface { * * 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 ); @@ -535,6 +567,10 @@ class WANObjectCache implements IExpiringStore, LoggerAwareInterface { * * 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. @@ -1769,9 +1805,18 @@ class WANObjectCache implements IExpiringStore, LoggerAwareInterface { * @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 ); @@ -1800,8 +1845,12 @@ class WANObjectCache implements IExpiringStore, LoggerAwareInterface { * @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( [ diff --git a/includes/libs/rdbms/TransactionProfiler.php b/includes/libs/rdbms/TransactionProfiler.php index a828cd3f1c..c353a224c6 100644 --- a/includes/libs/rdbms/TransactionProfiler.php +++ b/includes/libs/rdbms/TransactionProfiler.php @@ -177,7 +177,7 @@ class TransactionProfiler implements LoggerAwareInterface { 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 ), @@ -206,7 +206,7 @@ class TransactionProfiler implements LoggerAwareInterface { $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() ); } @@ -271,7 +271,7 @@ class TransactionProfiler implements LoggerAwareInterface { 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; } @@ -317,7 +317,7 @@ class TransactionProfiler implements LoggerAwareInterface { 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 ] ); @@ -336,7 +336,7 @@ class TransactionProfiler implements LoggerAwareInterface { return; } - $this->logger->info( + $this->logger->warning( "Expectation ({measure} <= {max}) by {by} not met (actual: {actual}):\n{query}\n" . ( new RuntimeException() )->getTraceAsString(), [ diff --git a/includes/libs/rdbms/database/Database.php b/includes/libs/rdbms/database/Database.php index 1efa9a1f2e..f3877fbe1e 100644 --- a/includes/libs/rdbms/database/Database.php +++ b/includes/libs/rdbms/database/Database.php @@ -126,6 +126,8 @@ abstract class Database implements IDatabase, IMaintainableDatabase, LoggerAware 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. @@ -1002,8 +1004,7 @@ abstract class Database implements IDatabase, IMaintainableDatabase, LoggerAware } /** - * 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 @@ -1029,7 +1030,9 @@ abstract class Database implements IDatabase, IMaintainableDatabase, LoggerAware 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 ); } @@ -2238,51 +2241,49 @@ abstract class Database implements IDatabase, IMaintainableDatabase, LoggerAware } 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; } /** @@ -2347,6 +2348,7 @@ abstract class Database implements IDatabase, IMaintainableDatabase, LoggerAware $where = false; } + $affectedRowCount = 0; $useTrx = !$this->mTrxLevel; if ( $useTrx ) { $this->begin( $fname, self::TRANSACTION_INTERNAL ); @@ -2355,11 +2357,13 @@ abstract class Database implements IDatabase, IMaintainableDatabase, LoggerAware # 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 ); @@ -2369,6 +2373,7 @@ abstract class Database implements IDatabase, IMaintainableDatabase, LoggerAware if ( $useTrx ) { $this->commit( $fname, self::FLUSHING_INTERNAL ); } + $this->affectedRowCount = $affectedRowCount; return $ok; } @@ -3187,6 +3192,17 @@ abstract class Database implements IDatabase, IMaintainableDatabase, LoggerAware } } + 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 diff --git a/includes/libs/rdbms/database/DatabaseMssql.php b/includes/libs/rdbms/database/DatabaseMssql.php index 53beb65f9a..832ed9e11e 100644 --- a/includes/libs/rdbms/database/DatabaseMssql.php +++ b/includes/libs/rdbms/database/DatabaseMssql.php @@ -353,7 +353,7 @@ class DatabaseMssql extends Database { /** * @return int */ - public function affectedRows() { + protected function fetchAffectedRowCount() { return $this->mAffectedRows; } diff --git a/includes/libs/rdbms/database/DatabaseMysqlBase.php b/includes/libs/rdbms/database/DatabaseMysqlBase.php index 305a056900..6a545ceb2d 100644 --- a/includes/libs/rdbms/database/DatabaseMysqlBase.php +++ b/includes/libs/rdbms/database/DatabaseMysqlBase.php @@ -63,6 +63,8 @@ abstract class DatabaseMysqlBase extends Database { /** @var string|null */ private $serverVersion = null; + /** @var bool|null */ + private $insertSelectIsSafe = null; /** * Additional $params include: @@ -75,6 +77,7 @@ abstract class DatabaseMysqlBase extends Database { * 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] @@ -98,6 +101,8 @@ abstract class DatabaseMysqlBase extends Database { } $this->sqlMode = isset( $params['sqlMode'] ) ? $params['sqlMode'] : ''; $this->utf8Mode = !empty( $params['utf8Mode'] ); + $this->insertSelectIsSafe = isset( $params['insertSelectIsSafe'] ) + ? (bool)$params['insertSelectIsSafe'] : null; parent::__construct( $params ); } @@ -501,6 +506,56 @@ abstract class DatabaseMysqlBase extends Database { 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 @@ -834,8 +889,10 @@ abstract class DatabaseMysqlBase extends Database { 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)" ); @@ -855,14 +912,17 @@ abstract class DatabaseMysqlBase extends Database { // 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 diff --git a/includes/libs/rdbms/database/DatabaseMysqli.php b/includes/libs/rdbms/database/DatabaseMysqli.php index c1a56988d5..09ea66cac8 100644 --- a/includes/libs/rdbms/database/DatabaseMysqli.php +++ b/includes/libs/rdbms/database/DatabaseMysqli.php @@ -172,7 +172,7 @@ class DatabaseMysqli extends DatabaseMysqlBase { /** * @return int */ - function affectedRows() { + protected function fetchAffectedRowCount() { $conn = $this->getBindingHandle(); return $conn->affected_rows; diff --git a/includes/libs/rdbms/database/DatabasePostgres.php b/includes/libs/rdbms/database/DatabasePostgres.php index 8c21d726b0..5bf845b1af 100644 --- a/includes/libs/rdbms/database/DatabasePostgres.php +++ b/includes/libs/rdbms/database/DatabasePostgres.php @@ -384,7 +384,7 @@ class DatabasePostgres extends Database { } } - public function affectedRows() { + protected function fetchAffectedRowCount() { if ( !is_null( $this->mAffectedRows ) ) { // Forced result for simulated queries return $this->mAffectedRows; diff --git a/includes/libs/rdbms/database/DatabaseSqlite.php b/includes/libs/rdbms/database/DatabaseSqlite.php index 2b0660707c..01772cf809 100644 --- a/includes/libs/rdbms/database/DatabaseSqlite.php +++ b/includes/libs/rdbms/database/DatabaseSqlite.php @@ -56,6 +56,9 @@ class DatabaseSqlite extends Database { /** @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 @@ -82,16 +85,7 @@ class DatabaseSqlite extends Database { 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'] ); } } @@ -302,6 +296,14 @@ class DatabaseSqlite extends Database { 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 * @@ -494,7 +496,7 @@ class DatabaseSqlite extends Database { /** * @return int */ - function affectedRows() { + protected function fetchAffectedRowCount() { return $this->mAffectedRows; } @@ -1033,6 +1035,17 @@ class DatabaseSqlite extends Database { 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 } diff --git a/includes/libs/rdbms/database/IDatabase.php b/includes/libs/rdbms/database/IDatabase.php index 85b3481fe3..0964dd55fe 100644 --- a/includes/libs/rdbms/database/IDatabase.php +++ b/includes/libs/rdbms/database/IDatabase.php @@ -1255,6 +1255,11 @@ interface IDatabase { * 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. diff --git a/includes/libs/rdbms/database/resultwrapper/MssqlResultWrapper.php b/includes/libs/rdbms/database/resultwrapper/MssqlResultWrapper.php index 298ec61934..4b79044655 100644 --- a/includes/libs/rdbms/database/resultwrapper/MssqlResultWrapper.php +++ b/includes/libs/rdbms/database/resultwrapper/MssqlResultWrapper.php @@ -15,7 +15,7 @@ class MssqlResultWrapper extends ResultWrapper { $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 { diff --git a/includes/libs/rdbms/lbfactory/LBFactorySingle.php b/includes/libs/rdbms/lbfactory/LBFactorySingle.php index cd998c3e7b..587ab23c02 100644 --- a/includes/libs/rdbms/lbfactory/LBFactorySingle.php +++ b/includes/libs/rdbms/lbfactory/LBFactorySingle.php @@ -102,6 +102,8 @@ class LBFactorySingle extends LBFactory { * @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 ) ); + } } } diff --git a/includes/libs/rdbms/loadbalancer/LoadBalancer.php b/includes/libs/rdbms/loadbalancer/LoadBalancer.php index ee3c86f1ee..864e6f0a3c 100644 --- a/includes/libs/rdbms/loadbalancer/LoadBalancer.php +++ b/includes/libs/rdbms/loadbalancer/LoadBalancer.php @@ -825,7 +825,7 @@ class LoadBalancer implements ILoadBalancer { // 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'." ); @@ -926,7 +926,7 @@ class LoadBalancer implements ILoadBalancer { $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; @@ -969,18 +969,19 @@ class LoadBalancer implements ILoadBalancer { * 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") @@ -1698,7 +1699,7 @@ class LoadBalancer implements ILoadBalancer { $oldDomain = $this->localDomain->getId(); $this->setLocalDomain( new DatabaseDomain( $this->localDomain->getDatabase(), - null, + $this->localDomain->getSchema(), $prefix ) ); diff --git a/includes/libs/rdbms/loadbalancer/LoadBalancerSingle.php b/includes/libs/rdbms/loadbalancer/LoadBalancerSingle.php index c73756330a..be80cc5eab 100644 --- a/includes/libs/rdbms/loadbalancer/LoadBalancerSingle.php +++ b/includes/libs/rdbms/loadbalancer/LoadBalancerSingle.php @@ -72,9 +72,9 @@ class LoadBalancerSingle extends LoadBalancer { 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' ); diff --git a/includes/page/CategoryPage.php b/includes/page/CategoryPage.php index 2d7e8f24fd..491726bedd 100644 --- a/includes/page/CategoryPage.php +++ b/includes/page/CategoryPage.php @@ -27,7 +27,7 @@ */ class CategoryPage extends Article { # Subclasses can change this to override the viewer class. - protected $mCategoryViewerClass = 'CategoryViewer'; + protected $mCategoryViewerClass = CategoryViewer::class; /** * @var WikiCategoryPage diff --git a/includes/parser/Parser.php b/includes/parser/Parser.php index 831c1fff46..b2d8511de8 100644 --- a/includes/parser/Parser.php +++ b/includes/parser/Parser.php @@ -270,15 +270,15 @@ class Parser { $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" ); } diff --git a/includes/parser/ParserOptions.php b/includes/parser/ParserOptions.php index f99089b895..ca8e739f9a 100644 --- a/includes/parser/ParserOptions.php +++ b/includes/parser/ParserOptions.php @@ -65,7 +65,6 @@ class ParserOptions { 'stubthreshold' => true, 'printable' => true, 'userlang' => true, - 'wrapclass' => true, ]; /** @@ -780,13 +779,17 @@ class ParserOptions { /** * 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 ); } @@ -1059,8 +1062,8 @@ class ParserOptions { 'printable' => false, 'allowUnsafeRawHtml' => true, 'wrapclass' => 'mw-parser-output', - 'currentRevisionCallback' => [ 'Parser', 'statelessFetchRevision' ], - 'templateCallback' => [ 'Parser', 'statelessFetchTemplate' ], + 'currentRevisionCallback' => [ Parser::class, 'statelessFetchRevision' ], + 'templateCallback' => [ Parser::class, 'statelessFetchTemplate' ], 'speculativeRevIdCallback' => null, ]; diff --git a/includes/parser/ParserOutput.php b/includes/parser/ParserOutput.php index 153a7708f4..e2efaff40f 100644 --- a/includes/parser/ParserOutput.php +++ b/includes/parser/ParserOutput.php @@ -23,10 +23,11 @@ */ 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 @@ -266,29 +267,47 @@ class ParserOutput extends CacheTime { * 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, diff --git a/includes/parser/Preprocessor_DOM.php b/includes/parser/Preprocessor_DOM.php index 79021dda23..4db2855570 100644 --- a/includes/parser/Preprocessor_DOM.php +++ b/includes/parser/Preprocessor_DOM.php @@ -823,7 +823,7 @@ class PPDStack { */ public $top; public $out; - public $elementClass = 'PPDStackElement'; + public $elementClass = PPDStackElement::class; public static $false = false; @@ -931,7 +931,7 @@ class PPDStackElement { */ public $lineStart; - public $partClass = 'PPDPart'; + public $partClass = PPDPart::class; public function __construct( $data = [] ) { $class = $this->partClass; diff --git a/includes/parser/Preprocessor_Hash.php b/includes/parser/Preprocessor_Hash.php index 468b009aa9..c4c0c5ada4 100644 --- a/includes/parser/Preprocessor_Hash.php +++ b/includes/parser/Preprocessor_Hash.php @@ -792,7 +792,7 @@ class Preprocessor_Hash extends Preprocessor { class PPDStack_Hash extends PPDStack { public function __construct() { - $this->elementClass = 'PPDStackElement_Hash'; + $this->elementClass = PPDStackElement_Hash::class; parent::__construct(); $this->rootAccum = []; } @@ -805,7 +805,7 @@ class PPDStack_Hash extends PPDStack { class PPDStackElement_Hash extends PPDStackElement { public function __construct( $data = [] ) { - $this->partClass = 'PPDPart_Hash'; + $this->partClass = PPDPart_Hash::class; parent::__construct( $data ); } @@ -1766,12 +1766,12 @@ class PPNode_Hash_Tree implements PPNode { $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' ); diff --git a/includes/parser/Sanitizer.php b/includes/parser/Sanitizer.php index b570a43c06..de7a6fa501 100644 --- a/includes/parser/Sanitizer.php +++ b/includes/parser/Sanitizer.php @@ -1171,7 +1171,9 @@ class Sanitizer { # Stupid hack $encValue = preg_replace_callback( '/((?i)' . wfUrlProtocols() . ')/', - [ 'Sanitizer', 'armorLinksCallback' ], + function ( $matches ) { + return str_replace( ':', ':', $matches[1] ); + }, $encValue ); return $encValue; } @@ -1416,15 +1418,6 @@ class Sanitizer { 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, @@ -1549,7 +1542,7 @@ class Sanitizer { static function normalizeCharReferences( $text ) { return preg_replace_callback( self::CHAR_REFS_REGEX, - [ 'Sanitizer', 'normalizeCharReferencesCallback' ], + [ self::class, 'normalizeCharReferencesCallback' ], $text ); } @@ -1649,7 +1642,7 @@ class Sanitizer { public static function decodeCharReferences( $text ) { return preg_replace_callback( self::CHAR_REFS_REGEX, - [ 'Sanitizer', 'decodeCharReferencesCallback' ], + [ self::class, 'decodeCharReferencesCallback' ], $text ); } @@ -1667,7 +1660,7 @@ class Sanitizer { global $wgContLang; $text = preg_replace_callback( self::CHAR_REFS_REGEX, - [ 'Sanitizer', 'decodeCharReferencesCallback' ], + [ self::class, 'decodeCharReferencesCallback' ], $text, -1, //limit $count diff --git a/includes/password/PasswordFactory.php b/includes/password/PasswordFactory.php index 3383fe385e..bc37b48404 100644 --- a/includes/password/PasswordFactory.php +++ b/includes/password/PasswordFactory.php @@ -41,7 +41,7 @@ final class PasswordFactory { * @see Setup.php */ private $types = [ - '' => [ 'type' => '', 'class' => 'InvalidPassword' ], + '' => [ 'type' => '', 'class' => InvalidPassword::class ], ]; /** diff --git a/includes/preferences/DefaultPreferencesFactory.php b/includes/preferences/DefaultPreferencesFactory.php index a23d6446a1..c1e9a59cec 100644 --- a/includes/preferences/DefaultPreferencesFactory.php +++ b/includes/preferences/DefaultPreferencesFactory.php @@ -205,7 +205,7 @@ class DefaultPreferencesFactory implements PreferencesFactory { // 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 = []; @@ -219,7 +219,7 @@ class DefaultPreferencesFactory implements PreferencesFactory { // 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; @@ -799,7 +799,7 @@ class DefaultPreferencesFactory implements PreferencesFactory { } $defaultPreferences['timecorrection'] = [ - 'class' => 'HTMLSelectOrOtherField', + 'class' => \HTMLSelectOrOtherField::class, 'label-message' => 'timezonelegend', 'options' => $tzOptions, 'default' => $tzSetting, @@ -1401,7 +1401,7 @@ class DefaultPreferencesFactory implements PreferencesFactory { public function getForm( User $user, IContextSource $context, - $formClass = 'PreferencesForm', + $formClass = PreferencesForm::class, array $remove = [] ) { $formDescriptor = $this->getFormDescriptor( $user, $context ); diff --git a/includes/preferences/PreferencesFactory.php b/includes/preferences/PreferencesFactory.php index 35237be478..685f78caaf 100644 --- a/includes/preferences/PreferencesFactory.php +++ b/includes/preferences/PreferencesFactory.php @@ -62,7 +62,7 @@ interface PreferencesFactory { public function getForm( User $user, IContextSource $contextSource, - $formClass = 'PreferencesForm', + $formClass = \PreferencesForm::class, array $remove = [] ); diff --git a/includes/profiler/Profiler.php b/includes/profiler/Profiler.php index 81449be1f6..9021652958 100644 --- a/includes/profiler/Profiler.php +++ b/includes/profiler/Profiler.php @@ -64,7 +64,7 @@ abstract class Profiler { global $wgProfiler, $wgProfileLimit; $params = [ - 'class' => 'ProfilerStub', + 'class' => ProfilerStub::class, 'sampling' => 1, 'threshold' => $wgProfileLimit, 'output' => [], @@ -76,7 +76,7 @@ abstract class Profiler { $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'] ) ) { diff --git a/includes/profiler/ProfilerSectionOnly.php b/includes/profiler/ProfilerSectionOnly.php index 41260a8388..a7bc1375e9 100644 --- a/includes/profiler/ProfilerSectionOnly.php +++ b/includes/profiler/ProfilerSectionOnly.php @@ -22,7 +22,7 @@ * Profiler that only tracks explicit profiling sections * * @code - * $wgProfiler['class'] = 'ProfilerSectionOnly'; + * $wgProfiler['class'] = ProfilerSectionOnly::class; * $wgProfiler['output'] = 'text'; * $wgProfiler['visible'] = true; * @endcode diff --git a/includes/profiler/ProfilerXhprof.php b/includes/profiler/ProfilerXhprof.php index 09191ee51d..ffa441ed87 100644 --- a/includes/profiler/ProfilerXhprof.php +++ b/includes/profiler/ProfilerXhprof.php @@ -22,14 +22,14 @@ * 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 diff --git a/includes/resourceloader/ResourceLoader.php b/includes/resourceloader/ResourceLoader.php index 36bf6567b9..830dbb4a55 100644 --- a/includes/resourceloader/ResourceLoader.php +++ b/includes/resourceloader/ResourceLoader.php @@ -553,7 +553,7 @@ class ResourceLoader implements LoggerAwareInterface { $object->setLogger( $this->logger ); } else { if ( !isset( $info['class'] ) ) { - $class = 'ResourceLoaderFileModule'; + $class = ResourceLoaderFileModule::class; } else { $class = $info['class']; } @@ -586,8 +586,8 @@ class ResourceLoader implements LoggerAwareInterface { } 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; } @@ -1227,7 +1227,11 @@ MESSAGE; $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.' ); } diff --git a/includes/resourceloader/ResourceLoaderUserOptionsModule.php b/includes/resourceloader/ResourceLoaderUserOptionsModule.php index a15d310bcd..ffa55c08ac 100644 --- a/includes/resourceloader/ResourceLoaderUserOptionsModule.php +++ b/includes/resourceloader/ResourceLoaderUserOptionsModule.php @@ -51,7 +51,9 @@ class ResourceLoaderUserOptionsModule extends ResourceLoaderModule { * @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() ); diff --git a/includes/resourceloader/ResourceLoaderUserTokensModule.php b/includes/resourceloader/ResourceLoaderUserTokensModule.php index e933f1f34d..ae4fb67b8d 100644 --- a/includes/resourceloader/ResourceLoaderUserTokensModule.php +++ b/includes/resourceloader/ResourceLoaderUserTokensModule.php @@ -48,19 +48,16 @@ class ResourceLoaderUserTokensModule extends ResourceLoaderModule { } /** - * 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; + ); } /** diff --git a/includes/revisiondelete/RevisionDeleter.php b/includes/revisiondelete/RevisionDeleter.php index 76fa590d03..7b2147a5e5 100644 --- a/includes/revisiondelete/RevisionDeleter.php +++ b/includes/revisiondelete/RevisionDeleter.php @@ -29,11 +29,11 @@ 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 */ diff --git a/includes/search/SearchEngineFactory.php b/includes/search/SearchEngineFactory.php index 613d33ca09..8cdca571ae 100644 --- a/includes/search/SearchEngineFactory.php +++ b/includes/search/SearchEngineFactory.php @@ -49,17 +49,17 @@ class SearchEngineFactory { 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; } } } diff --git a/includes/shell/Command.php b/includes/shell/Command.php index 4f65e4d392..d6f95783f0 100644 --- a/includes/shell/Command.php +++ b/includes/shell/Command.php @@ -404,11 +404,20 @@ class Command { $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 @@ -465,14 +474,17 @@ class Command { } 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 ) { diff --git a/includes/site/SiteList.php b/includes/site/SiteList.php index a94aa0b93b..b942d6e4fe 100644 --- a/includes/site/SiteList.php +++ b/includes/site/SiteList.php @@ -63,7 +63,7 @@ class SiteList extends GenericArrayObject { * @return string */ public function getObjectType() { - return 'Site'; + return Site::class; } /** diff --git a/includes/skins/QuickTemplate.php b/includes/skins/QuickTemplate.php index d1be4bb0df..19b41ba969 100644 --- a/includes/skins/QuickTemplate.php +++ b/includes/skins/QuickTemplate.php @@ -91,10 +91,14 @@ abstract class QuickTemplate { } /** + * @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; } diff --git a/includes/skins/SkinApi.php b/includes/skins/SkinApi.php index a14afe0715..6966ff71be 100644 --- a/includes/skins/SkinApi.php +++ b/includes/skins/SkinApi.php @@ -30,7 +30,7 @@ */ class SkinApi extends SkinTemplate { public $skinname = 'apioutput'; - public $template = 'SkinApiTemplate'; + public $template = SkinApiTemplate::class; public function setupSkinUserCss( OutputPage $out ) { parent::setupSkinUserCss( $out ); diff --git a/includes/skins/SkinFallback.php b/includes/skins/SkinFallback.php index 96ff228520..d5f764c6e4 100644 --- a/includes/skins/SkinFallback.php +++ b/includes/skins/SkinFallback.php @@ -14,7 +14,7 @@ class SkinFallback extends SkinTemplate { public $skinname = 'fallback'; - public $template = 'SkinFallbackTemplate'; + public $template = SkinFallbackTemplate::class; /** * Add CSS via ResourceLoader diff --git a/includes/skins/SkinTemplate.php b/includes/skins/SkinTemplate.php index 8b698e8f76..45875334bc 100644 --- a/includes/skins/SkinTemplate.php +++ b/includes/skins/SkinTemplate.php @@ -46,7 +46,7 @@ class SkinTemplate extends Skin { * @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; diff --git a/includes/specialpage/AuthManagerSpecialPage.php b/includes/specialpage/AuthManagerSpecialPage.php index 95729f3c56..b9745de1c6 100644 --- a/includes/specialpage/AuthManagerSpecialPage.php +++ b/includes/specialpage/AuthManagerSpecialPage.php @@ -609,7 +609,7 @@ abstract class AuthManagerSpecialPage extends SpecialPage { } elseif ( array_key_exists( 'type', $definition ) ) { $class = HTMLForm::$typeMappings[$definition['type']]; } - if ( $class !== 'HTMLInfoField' ) { + if ( $class !== HTMLInfoField::class ) { $definition['tabindex'] = $i; $i++; } diff --git a/includes/specialpage/QueryPage.php b/includes/specialpage/QueryPage.php index 33b9ccb12d..b20f22214b 100644 --- a/includes/specialpage/QueryPage.php +++ b/includes/specialpage/QueryPage.php @@ -69,40 +69,40 @@ abstract class QueryPage extends SpecialPage { 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 ] ); } diff --git a/includes/specialpage/SpecialPageFactory.php b/includes/specialpage/SpecialPageFactory.php index 4433ddb7d6..af688e225e 100644 --- a/includes/specialpage/SpecialPageFactory.php +++ b/includes/specialpage/SpecialPageFactory.php @@ -50,143 +50,143 @@ class SpecialPageFactory { */ 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; @@ -237,27 +237,27 @@ class SpecialPageFactory { 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 diff --git a/includes/specials/SpecialBotPasswords.php b/includes/specials/SpecialBotPasswords.php index dfdbb067c0..f76c318e26 100644 --- a/includes/specials/SpecialBotPasswords.php +++ b/includes/specials/SpecialBotPasswords.php @@ -146,7 +146,7 @@ class SpecialBotPasswords extends FormSpecialPage { ]; $fields['restrictions'] = [ - 'class' => 'HTMLRestrictionsField', + 'class' => HTMLRestrictionsField::class, 'required' => true, 'default' => $this->botPassword->getRestrictions(), ]; diff --git a/includes/specials/SpecialDiff.php b/includes/specials/SpecialDiff.php index 28cd0d195a..b27a8b4dfd 100644 --- a/includes/specials/SpecialDiff.php +++ b/includes/specials/SpecialDiff.php @@ -78,7 +78,7 @@ class SpecialDiff extends RedirectSpecialPage { ], 'diff' => [ 'name' => 'diff', - 'class' => 'HTMLTextField', + 'class' => HTMLTextField::class, 'label-message' => 'diff-form-revid', ], ], $this->getContext(), 'diff-form' ); diff --git a/includes/specials/SpecialEditWatchlist.php b/includes/specials/SpecialEditWatchlist.php index 09ea9ea6ac..e3c5d8c4a6 100644 --- a/includes/specials/SpecialEditWatchlist.php +++ b/includes/specials/SpecialEditWatchlist.php @@ -573,7 +573,7 @@ class SpecialEditWatchlist extends UnlistedSpecialPage { // 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", ]; diff --git a/includes/specials/SpecialExpandTemplates.php b/includes/specials/SpecialExpandTemplates.php index 0c18a483bc..73ca76bb97 100644 --- a/includes/specials/SpecialExpandTemplates.php +++ b/includes/specials/SpecialExpandTemplates.php @@ -164,7 +164,6 @@ class SpecialExpandTemplates extends SpecialPage { 'size' => 60, 'default' => $title, 'autofocus' => true, - 'cssclass' => 'mw-ui-input-inline', ], 'input' => [ 'type' => 'textarea', diff --git a/includes/specials/SpecialExport.php b/includes/specials/SpecialExport.php index 78f92532a4..4b5dedf781 100644 --- a/includes/specials/SpecialExport.php +++ b/includes/specials/SpecialExport.php @@ -238,7 +238,7 @@ class SpecialExport extends SpecialPage { $formDescriptor += [ 'textarea' => [ - 'class' => 'HTMLTextAreaField', + 'class' => HTMLTextAreaField::class, 'name' => 'pages', 'label-message' => 'export-manual', 'nodata' => true, diff --git a/includes/specials/SpecialProtectedpages.php b/includes/specials/SpecialProtectedpages.php index ac34996283..d693b99007 100644 --- a/includes/specials/SpecialProtectedpages.php +++ b/includes/specials/SpecialProtectedpages.php @@ -97,7 +97,7 @@ class SpecialProtectedpages extends SpecialPage { ) { $formDescriptor = [ 'namespace' => [ - 'class' => 'HTMLSelectNamespace', + 'class' => HTMLSelectNamespace::class, 'name' => 'namespace', 'id' => 'namespace', 'cssclass' => 'namespaceselector', @@ -125,7 +125,7 @@ class SpecialProtectedpages extends SpecialPage { 'id' => 'noredirect', ], 'sizelimit' => [ - 'class' => 'HTMLSizeFilterField', + 'class' => HTMLSizeFilterField::class, 'name' => 'size', ] ]; diff --git a/includes/specials/SpecialTags.php b/includes/specials/SpecialTags.php index 605ee008d8..6b0598cefc 100644 --- a/includes/specials/SpecialTags.php +++ b/includes/specials/SpecialTags.php @@ -441,7 +441,7 @@ class SpecialTags extends SpecialPage { $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() ) { diff --git a/includes/specials/SpecialUserrights.php b/includes/specials/SpecialUserrights.php index fd066ac7f3..e62731fbf4 100644 --- a/includes/specials/SpecialUserrights.php +++ b/includes/specials/SpecialUserrights.php @@ -873,6 +873,10 @@ class UserrightsPage extends SpecialPage { } 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 .= "
\n"; } else { $expiryHtml = Xml::element( 'span', null, diff --git a/includes/specials/forms/UploadForm.php b/includes/specials/forms/UploadForm.php index 44d91a8a26..eacdace18a 100644 --- a/includes/specials/forms/UploadForm.php +++ b/includes/specials/forms/UploadForm.php @@ -159,7 +159,7 @@ class UploadForm extends HTMLForm { } $descriptor['UploadFile'] = [ - 'class' => 'UploadSourceField', + 'class' => UploadSourceField::class, 'section' => 'source', 'type' => 'file', 'id' => 'wpUploadFile', @@ -174,7 +174,7 @@ class UploadForm extends HTMLForm { if ( $canUploadByUrl ) { $this->mMaxUploadSize['url'] = UploadBase::getMaxUploadSize( 'url' ); $descriptor['UploadFileURL'] = [ - 'class' => 'UploadSourceField', + 'class' => UploadSourceField::class, 'section' => 'source', 'id' => 'wpUploadFileURL', 'radio-id' => 'wpSourceTypeurl', @@ -322,7 +322,7 @@ class UploadForm extends HTMLForm { } else { $descriptor['License'] = [ 'type' => 'select', - 'class' => 'Licenses', + 'class' => Licenses::class, 'section' => 'description', 'id' => 'wpLicense', 'label-message' => 'license', diff --git a/includes/specials/pagers/UsersPager.php b/includes/specials/pagers/UsersPager.php index 4efe92d743..09d4b5e3eb 100644 --- a/includes/specials/pagers/UsersPager.php +++ b/includes/specials/pagers/UsersPager.php @@ -277,7 +277,7 @@ class UsersPager extends AlphabeticPager { $formDescriptor = [ 'user' => [ - 'class' => 'HTMLUserTextField', + 'class' => HTMLUserTextField::class, 'label' => $this->msg( 'listusersfrom' )->text(), 'name' => 'username', 'default' => $this->requestedUser, @@ -286,7 +286,7 @@ class UsersPager extends AlphabeticPager { 'label' => $this->msg( 'group' )->text(), 'name' => 'group', 'default' => $this->requestedGroup, - 'class' => 'HTMLSelectField', + 'class' => HTMLSelectField::class, 'options' => $groupOptions, ], 'editsOnly' => [ @@ -311,7 +311,7 @@ class UsersPager extends AlphabeticPager { 'default' => $this->mDefaultDirection ], 'limithiddenfield' => [ - 'class' => 'HTMLHiddenField', + 'class' => HTMLHiddenField::class, 'name' => 'limit', 'default' => $this->mLimit ] @@ -322,14 +322,14 @@ class UsersPager extends AlphabeticPager { if ( $beforeSubmitButtonHookOut !== '' ) { $formDescriptior[ 'beforeSubmitButtonHookOut' ] = [ - 'class' => 'HTMLInfoField', + 'class' => HTMLInfoField::class, 'raw' => true, 'default' => $beforeSubmitButtonHookOut ]; } $formDescriptor[ 'submit' ] = [ - 'class' => 'HTMLSubmitField', + 'class' => HTMLSubmitField::class, 'buttonlabel-message' => 'listusers-submit', ]; @@ -338,7 +338,7 @@ class UsersPager extends AlphabeticPager { if ( $beforeClosingFieldsetHookOut !== '' ) { $formDescriptior[ 'beforeClosingFieldsetHookOut' ] = [ - 'class' => 'HTMLInfoField', + 'class' => HTMLInfoField::class, 'raw' => true, 'default' => $beforeClosingFieldsetHookOut ]; diff --git a/includes/user/User.php b/includes/user/User.php index 5bab87642f..97035c2dab 100644 --- a/includes/user/User.php +++ b/includes/user/User.php @@ -3100,7 +3100,7 @@ class User implements IDBAccessObject, UserIdentity { $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; @@ -3114,7 +3114,7 @@ class User implements IDBAccessObject, UserIdentity { $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; diff --git a/includes/watcheditem/WatchedItemStore.php b/includes/watcheditem/WatchedItemStore.php index c68d6d7fdf..d6d9ff0eb9 100644 --- a/includes/watcheditem/WatchedItemStore.php +++ b/includes/watcheditem/WatchedItemStore.php @@ -74,8 +74,8 @@ class WatchedItemStore implements WatchedItemStoreInterface, StatsdAwareInterfac $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' ]; } /** diff --git a/languages/i18n/ast.json b/languages/i18n/ast.json index de3b6af810..10c3855ba1 100644 --- a/languages/i18n/ast.json +++ b/languages/i18n/ast.json @@ -370,7 +370,7 @@ "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''", @@ -408,7 +408,7 @@ "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", @@ -711,6 +711,7 @@ "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", @@ -1302,7 +1303,7 @@ "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", @@ -1479,7 +1480,7 @@ "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).", @@ -1540,7 +1541,7 @@ "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.", @@ -1640,7 +1641,7 @@ "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.", @@ -1831,7 +1832,7 @@ "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 tachaes 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:", @@ -2319,7 +2320,7 @@ "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 \"$1\" del $2 a les $3?", + "undelete-show-file-confirm": "¿Tas seguru de que quies ver la versión desaniciada del ficheru «$1» del $2 a les $3?", "undelete-show-file-submit": "Sí", "namespace": "Espaciu de nomes:", "invert": "Invertir seleición", @@ -2339,7 +2340,7 @@ "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", @@ -2362,7 +2363,7 @@ "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 [[:$1]] nel espaciu de nomes escoyíu.", "isredirect": "páxina de redireición", "istemplate": "tresclusión", "isimage": "enllaz al ficheru", @@ -2372,7 +2373,7 @@ "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", @@ -2385,7 +2386,7 @@ "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", @@ -2396,7 +2397,7 @@ "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}}.
\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?", @@ -2442,9 +2443,9 @@ "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", @@ -2459,54 +2460,54 @@ "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
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.
\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", @@ -2515,9 +2516,9 @@ "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": "Avisu: 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 nun 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.", @@ -2525,20 +2526,20 @@ "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": "«$1» treslladóse a «$2»", "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.", @@ -2549,20 +2550,20 @@ "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:", @@ -2571,24 +2572,24 @@ "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": "----\nNota: 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 $wgUseDatabaseMessages.", "allmessages-filter-legend": "Peñerar", "allmessages-filter": "Peñerar por estáu de personalización:", "allmessages-filter-unmodified": "Ensin cambeos", @@ -2599,16 +2600,16 @@ "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", @@ -2633,24 +2634,24 @@ "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: $1", "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).", @@ -2662,14 +2663,14 @@ "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", @@ -2688,7 +2689,7 @@ "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", @@ -2716,11 +2717,11 @@ "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", @@ -2733,7 +2734,7 @@ "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.", @@ -2828,7 +2829,7 @@ "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.", @@ -2839,13 +2840,13 @@ "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.", @@ -2871,7 +2872,7 @@ "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", diff --git a/languages/i18n/be-tarask.json b/languages/i18n/be-tarask.json index 9b0dc5a07f..6f0bd53c31 100644 --- a/languages/i18n/be-tarask.json +++ b/languages/i18n/be-tarask.json @@ -711,6 +711,7 @@ "postedit-confirmation-created": "Старонка была створаная.", "postedit-confirmation-restored": "Старонка была адноўленая.", "postedit-confirmation-saved": "Вашая праўка была захаваная.", + "postedit-confirmation-published": "Вашая праўка была апублікаваная.", "edit-already-exists": "Немагчыма стварыць новую старонку.\nЯна ўжо існуе.", "defaultmessagetext": "Перадвызначаны тэкст паведамленьня", "content-failed-to-parse": "Зьмест «$2» не адпавядае мадэлі $1: $3.", @@ -1117,12 +1118,12 @@ "right-read": "Прагляд старонак", "right-edit": "Рэдагаваньне старонак", "right-createpage": "Стварэньне старонак (акрамя старонак абмеркаваньняў)", - "right-createtalk": "стварэньне старонак абмеркаваньня", - "right-createaccount": "стварэньне новых рахункаў удзельніка", + "right-createtalk": "Стварэньне старонак абмеркаваньня", + "right-createaccount": "Стварэньне новых рахункаў удзельнікаў", "right-autocreateaccount": "Аўтаматычны ўваход з вонкавага рахунку ўдзельніка", - "right-minoredit": "пазначэньне рэдагаваньняў як дробныя", - "right-move": "перанос старонак", - "right-move-subpages": "перанос старонак разам зь іх падстаронкамі", + "right-minoredit": "Пазначэньне рэдагаваньняў як дробных", + "right-move": "Перанос старонак", + "right-move-subpages": "Перанос старонак разам зь іх падстаронкамі", "right-move-rootuserpages": "перанос карэнных старонак удзельнікаў", "right-move-categorypages": "перанос старонак катэгорыяў", "right-movefile": "перайменаваньне файлаў", @@ -1638,7 +1639,7 @@ "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.", @@ -3965,6 +3966,7 @@ "restrictionsfield-label": "Дазволеныя IP-дыяпазоны:", "restrictionsfield-help": "Адзін IP-адрас ці CIDR-дыяпазон на радок. Каб дазволіць усё, ужывайце:
0.0.0.0/0\n::/0
", "edit-error-short": "Памылка: $1", + "edit-error-long": "Памылкі:\n\n$1", "revid": "вэрсія $1", "pageid": "Ідэнтыфікатар старонкі $1", "rawhtml-notallowed": "<html>-тэгі ня могуць быць выкарыстаныя па-за звычайнымі старонкамі.", diff --git a/languages/i18n/bg.json b/languages/i18n/bg.json index a569fc9972..e8f0f45c1a 100644 --- a/languages/i18n/bg.json +++ b/languages/i18n/bg.json @@ -1561,7 +1561,7 @@ "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": "Изчистване на скритите качвания", @@ -1719,7 +1719,7 @@ "doubleredirects": "Двойни пренасочвания", "doubleredirectstext": "Тази страница съдържа списък със страници, които пренасочват към друга пренасочваща страница.\nВсеки ред съдържа препратки към първото и второто пренасочване, както и целта на второто пренасочване, която обикновено е „истинската“ целева страница, към която първото пренасочване би трябвало да сочи.\nЗадрасканите записи са коригирани.", "double-redirect-fixed-move": "Страница [[$1]] беше преместена.\nБеше автоматично обновена и сега пренасочва към [[$2]].", - "double-redirect-fixed-maintenance": "Автоматично коригиране на двойно пренасочване от [[$1]] към [[$2]] при извършване на техническо обслужване.", + "double-redirect-fixed-maintenance": "Автоматично коригиране на двойно пренасочване от [[$1]] към [[$2]] при извършване на техническо обслужване", "double-redirect-fixer": "Коректор на пренасочвания", "brokenredirects": "Невалидни пренасочвания", "brokenredirectstext": "Следните пренасочващи страници сочат към несъществуващи страници:", @@ -3468,7 +3468,7 @@ "expandtemplates": "Разгръщане на шаблони", "expand_templates_intro": "Тази специална страница взима текст и рекурсивно разгръща всички шаблони в нея.\nТя разгръща и всички поддържани парсерни функции като\n{{#language:…}} и променливи като\n{{CURRENTDAY}}.\nНа практика тя разгръща почти всичко в двойни скоби.", "expand_templates_title": "Заглавие на страницата (напр. за {{FULLPAGENAME}}):", - "expand_templates_input": "Входящ текст:", + "expand_templates_input": "Входящ уикитекст:", "expand_templates_output": "Резултат", "expand_templates_xml_output": "Изход на XML", "expand_templates_ok": "ОК", diff --git a/languages/i18n/bho.json b/languages/i18n/bho.json index 0898cd32c4..bf30b6910c 100644 --- a/languages/i18n/bho.json +++ b/languages/i18n/bho.json @@ -609,7 +609,7 @@ "anonpreviewwarning": "''रउआँ खाता में प्रवेश नइखीं भइल। सहेजब तब ए पन्ना के संपादन इतिहास में राउर आईपी पता दर्ज हो जाई।\"", "missingsummary": "'''याद दियावल जात बा:'''रउआँ एगो संपादन सारांश नइखीं दिहले। अगर फिर \"$1\" पर क्लिक करब, त राउर संपादन एकरे बिना सहेजा जाई।", "selfredirect": "चेतावनी: आप ई पन्ना के खुदे एही पर अनुप्रेषण क रहल बानी।\nया त आप अनुप्रेषण खातिर गलत लक्ष्य देत बानी, या आप गलत पन्ना के संपादन करत बानी।\nएक बेर अउरी \"$1\" क्लिक करब त, ओइसहूँ ई अनुप्रेषण बना दिहल जाई।", - "missingcommenttext": "नीचे एगो टिप्पणी भरीं।", + "missingcommenttext": "एगो टिप्पणी भरीं।", "missingcommentheader": "'''याद दियावल जात बा:''' रउआँ एह कमेंट खातिर कौनों बिसय नइखीं दिहले। अगर आप \"$1\" पर क्लिक करब तब राउर संपादन एकरे बिना सहेजा जाई।", "summary-preview": "संपादन सारांश क झलक:", "subject-preview": "बिसय के झलक:", @@ -1477,11 +1477,25 @@ "watching": "ध्यानसूची में जाते हुए", "unwatching": "ध्यानसूची से हटते हुए", "enotif_reset": "सगरी पन्ना सभ देखल चिन्हित करीं", + "enotif_impersonal_salutation": "{{SITENAME}} प्रयोगकर्ता", + "enotif_subject_deleted": "$2 पन्ना $1 के हटा {{GENDER:$2|दिहलें|दिहली}}", + "enotif_minoredit": "ई एगो छोट संपादन बा", "created": "बनावल गईल", + "deletepage": "पन्ना हटाईं", + "confirm": "कन्फर्म", + "excontent": "सामग्री रहल: \"$1\"", + "exbeforeblank": "खाली करे से पहिले सामग्री: \"$1\"", + "delete-confirm": "$1 के हटाईं", + "delete-legend": "हटाईं", "actioncomplete": "काम पुरा भइल", "dellogpage": "हटवले के लिस्ट", "rollbacklink": "रोलबैक", "rollbacklinkcount": "रोलबैक $1 {{PLURAL:$1|संपादन|संपादन सब}}", + "changecontentmodel-title-label": "पन्ना टाइटिल", + "changecontentmodel-model-label": "नया बिसयसूची माडल", + "changecontentmodel-reason-label": "कारण:", + "changecontentmodel-submit": "बदलीं", + "logentry-contentmodel-change-revertlink": "वापस लीं", "protectlogpage": "सुरक्षा लॉग", "protectlogtext": "नीचे पन्ना सुरक्षा में भइल बदलावकुल के सूची बा।\nहाल में सुरक्षित पन्नन के सूची खातिर [[Special:ProtectedPages|सुरक्षित पन्नन के सूची]] देखीं।", "protectedarticle": "\"[[$1]]\" सुरक्षित कइल गइल", @@ -1728,6 +1742,7 @@ "imgmultigo": "जाईं!", "imgmultigoto": "$1 पन्ना पर जाईं", "autoredircomment": "पन्ना [[$1]] पर अनुप्रेषित कइल गइल", + "autosumm-new": "पन्ना बनावल गइल \"$1\" के साथ", "watchlisttools-clear": "धियानसूची साफ करीं", "watchlisttools-view": "प्रासंगिक बदलाव देखीं", "watchlisttools-edit": "धियानसूची देखीं आ संपादित करीं", @@ -1754,6 +1769,7 @@ "specialpages-group-wiki": "डेटा अउर औजार", "tag-filter": "[[Special:Tags|टैग]] छननी:", "tag-list-wrapper": "([[Special:Tags|{{PLURAL:$1|टैग|टैग कुल}}]]: $2)", + "tag-mw-new-redirect": "नाया अनुप्रेषण", "tags-active-yes": "हँऽ", "tags-active-no": "ना", "tags-hitcount": "$1 {{PLURAL:$1|बदलाव}}", diff --git a/languages/i18n/bs.json b/languages/i18n/bs.json index 1780f90411..27151181f4 100644 --- a/languages/i18n/bs.json +++ b/languages/i18n/bs.json @@ -151,9 +151,9 @@ "category-empty": "Ova kategorija trenutno ne sadrži članke ni medije.", "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.", diff --git a/languages/i18n/ca.json b/languages/i18n/ca.json index b63d3fbbf7..5657fb207a 100644 --- a/languages/i18n/ca.json +++ b/languages/i18n/ca.json @@ -762,6 +762,7 @@ "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", @@ -1874,7 +1875,7 @@ "uncategorizedimages": "Fitxers sense categoria", "uncategorizedtemplates": "Plantilles sense categoria", "uncategorized-categories-exceptionlist": " # Conté una llista de categories no no s'haurien de mencionar a Special:UncategorizedCategories. Una per línia, començant amb «*». Les línies que comencin amb un altre caràcter (incloent l'espai en blanc) són ignorades. Utilitzeu «#» per a comentaris.", - "unusedcategories": "Categories sense cap ús", + "unusedcategories": "Categories no utilitzades", "unusedimages": "Fitxers no utilitzats", "wantedcategories": "Categories demanades", "wantedpages": "Pàgines demanades", @@ -3896,6 +3897,8 @@ "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ó.", @@ -3931,6 +3934,7 @@ "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]'''", diff --git a/languages/i18n/ce.json b/languages/i18n/ce.json index 0e9bed7b0c..14e189c38b 100644 --- a/languages/i18n/ce.json +++ b/languages/i18n/ce.json @@ -2123,7 +2123,7 @@ "movepage-moved-noredirect": "ДӀасхьажорг кхоллар дохина.", "articleexists": "ХӀарасанна цӀе йолу агӀо йолуш ю йа ахьа гойтуш йолу цӀе магош яц.\nДехар до, харжа кхин цӀе.", "movetalk": "Цуьнца йогӀуш йолу дийцаре агӀон цӀе хийцар", - "move-subpages": "ЦӀерш хийца бухара агӀонийн ($1 кхаччалц)", + "move-subpages": "Бухара агӀонийн цӀерш хийца($1 кхаччалц)", "move-talk-subpages": "ЦӀе хийца бухара агӀонийн а, агӀонийн дийцаре а ($1 кхаччалц)", "movepage-page-exists": "Агӏо $1 йолуш ю цундела и ша юху дӏаязъян йиш яц.", "movepage-page-moved": "АгӀона $1 цӀе хийцина → $2.", diff --git a/languages/i18n/cs.json b/languages/i18n/cs.json index fa1f3db329..afaa232b72 100644 --- a/languages/i18n/cs.json +++ b/languages/i18n/cs.json @@ -36,7 +36,8 @@ "Martin Urbanec", "Marek Pavlica", "Asmen", - "Meliganai" + "Meliganai", + "Ilimanaq29" ] }, "tog-underline": "Podtrhávat odkazy:", @@ -733,6 +734,7 @@ "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", @@ -1662,7 +1664,7 @@ "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.", diff --git a/languages/i18n/de.json b/languages/i18n/de.json index 492d0cd43c..3a018c8d1a 100644 --- a/languages/i18n/de.json +++ b/languages/i18n/de.json @@ -788,6 +788,7 @@ "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", @@ -1721,7 +1722,7 @@ "lockmanager-fail-closelock": "Die Sperrdatei für „$1“ konnte nicht geschlossen werden.", "lockmanager-fail-deletelock": "Die Sperrdatei für „$1“ konnte nicht gelöscht werden.", "lockmanager-fail-acquirelock": "Die Sperre für „$1“ konnte nicht abgerufen werden.", - "lockmanager-fail-openlock": "Die Sperrdatei für „$1“ konnte nicht geöffnet werden.", + "lockmanager-fail-openlock": "Die Sperrdatei für „$1“ konnte nicht geöffnet werden. Stelle sicher, dass dein Hochladerepositorium korrekt konfiguriert ist und dein Webserver eine Berechtigung zum Beschreiben dieses Repositoriums hat. Siehe https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:$wgUploadDirectory für weitere Informationen.", "lockmanager-fail-releaselock": "Die Sperre für „$1“ konnte nicht freigegeben werden.", "lockmanager-fail-db-bucket": "Es konnte mit Sammelabruf $1 keine ausreichende Anzahl an Verbindungen zu Sperrdatenbanken hergestellt werden.", "lockmanager-fail-db-release": "Die Sperren auf Datenbank $1 konnten nicht freigegeben werden.", diff --git a/languages/i18n/diq.json b/languages/i18n/diq.json index 745a4323ae..ca5672d5ea 100644 --- a/languages/i18n/diq.json +++ b/languages/i18n/diq.json @@ -2523,7 +2523,7 @@ "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", diff --git a/languages/i18n/en.json b/languages/i18n/en.json index 3726ae9ed5..a638833acf 100644 --- a/languages/i18n/en.json +++ b/languages/i18n/en.json @@ -745,6 +745,7 @@ "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": "", diff --git a/languages/i18n/es.json b/languages/i18n/es.json index a43d383c5d..64c62c9efe 100644 --- a/languages/i18n/es.json +++ b/languages/i18n/es.json @@ -865,6 +865,7 @@ "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", @@ -1793,7 +1794,7 @@ "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\".", + "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.", @@ -1945,7 +1946,7 @@ "listduplicatedfiles": "Lista de archivos con duplicados", "listduplicatedfiles-summary": "Esta es una lista de archivos donde la versión más reciente es un duplicado de la versión más reciente de un archivo con otro nombre. Solo se tienen en cuenta archivos locales.", "listduplicatedfiles-entry": "[[:File:$1|$1]] tiene [[$3|{{PLURAL:$2|un duplicado|$2 duplicados}}]].", - "unusedtemplates": "Plantillas sin uso", + "unusedtemplates": "Plantillas no utilizadas", "unusedtemplatestext": "Aquí se enumeran todas las páginas en el espacio de nombres {{ns:template}} que no están incluidas en otras páginas. Recuerda mirar lo que enlaza a las plantillas antes de borrarlas.", "unusedtemplateswlh": "otros enlaces", "randompage": "Página aleatoria", @@ -2012,8 +2013,8 @@ "uncategorizedimages": "Archivos sin categorizar", "uncategorizedtemplates": "Plantillas sin categorizar", "uncategorized-categories-exceptionlist": "# Contiene una lista de categorías que no deberían figurar en Special:UncategorizedCategories. Una categoría por línea, empezando por «*». Las líneas que empiecen por otro carácter (espacios en blanco incluidos) se ignorarán. Usa «#» para añadir comentarios.", - "unusedcategories": "Categorías sin uso", - "unusedimages": "Archivos sin uso", + "unusedcategories": "Categorías no utilizadas", + "unusedimages": "Archivos no utilizados", "wantedcategories": "Categorías requeridas", "wantedpages": "Páginas requeridas", "wantedpages-summary": "Lista de páginas inexistentes con el mayor número de enlaces a ellas, excluyendo páginas que son solo redirecciones a ellas. Para ver una lista de páginas inexistentes con redirecciones apuntando a ellas, consulta [[{{#special:BrokenRedirects}}|la lista de redirecciones rotas]].", @@ -2422,7 +2423,7 @@ "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:", @@ -4091,8 +4092,8 @@ "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", diff --git a/languages/i18n/et.json b/languages/i18n/et.json index 706d8ba333..3030d0a37c 100644 --- a/languages/i18n/et.json +++ b/languages/i18n/et.json @@ -726,6 +726,7 @@ "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", @@ -1653,7 +1654,7 @@ "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.", @@ -2834,6 +2835,7 @@ "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", diff --git a/languages/i18n/eu.json b/languages/i18n/eu.json index a92336b4ae..de219536dc 100644 --- a/languages/i18n/eu.json +++ b/languages/i18n/eu.json @@ -1653,7 +1653,7 @@ "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.", @@ -3978,6 +3978,8 @@ "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
0.0.0.0/0\n::/0
", + "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.", diff --git a/languages/i18n/fa.json b/languages/i18n/fa.json index e668234982..b4d1e23637 100644 --- a/languages/i18n/fa.json +++ b/languages/i18n/fa.json @@ -1335,6 +1335,7 @@ "recentchanges-noresult": "در فاصله زمانی ارائه شده هیچ تغییری با این معیارهای صورت نگرفته است", "recentchanges-timeout": "این جستجو زمانش تمام شد. اگر مایلید کلیدواژه‌های دیگری را جستجو کنید.", "recentchanges-network": "به دلیل خطای فنی، نتیجه‌ای بدست نیامد. لطفاً برای تازه‌سازی صفحخ مجدداُ تلاش کنید.", + "recentchanges-notargetpage": "نام صفحه را در بالا وارد کنید تا تغییرات مرتبط با آن صفحه را مشاهده کنید.", "recentchanges-feed-description": "آخرین تغییرات ویکی را در این خوراک پی‌گیری کنید.", "recentchanges-label-newpage": "این ویرایش صفحه‌ای تازه ایجاد کرد", "recentchanges-label-minor": "این یک ویرایش جزئی است", @@ -1353,6 +1354,7 @@ "rcfilters-advancedfilters": "پالایه‌‌های پیشرفته", "rcfilters-limit-title": "تعداد تغییرات برای نمایش", "rcfilters-limit-and-date-label": "$1 {{PLURAL:$1|تغییر|تغییر}}, $2", + "rcfilters-date-popup-title": "دوره زمانی برای جستجو", "rcfilters-days-title": "روزهای اخیر", "rcfilters-hours-title": "ساعت‌های اخیر", "rcfilters-days-show-days": "$1 {{PLURAL:$1|روز|روز}}", @@ -1466,6 +1468,11 @@ "rcfilters-watchlist-showupdated": "تغییرات صفحاتی که شما بازدید نکردید از زمانی که تغییرات رخ داده به صورت پررنگ، با نشانگر توپر.", "rcfilters-preference-label": "مخفی کردن نسخه بهبود یافته تغییرات اخیر", "rcfilters-preference-help": "تغییرات رابط کاربری که در سال ۲۰۱۷ اضافه شده است را بر می‌گرداند.", + "rcfilters-filter-showlinkedfrom-label": "نمایش تغییرات صفحاتی که پیوند شده‌اند", + "rcfilters-filter-showlinkedfrom-option-label": "صفحات پیوند به صفحهٔ انتخاب شده", + "rcfilters-filter-showlinkedto-label": "نمایش تغییرات در صفحاتی که در ون این صفحه پیوند شده‌اند", + "rcfilters-filter-showlinkedto-option-label": "صفحات پیوند شده درون صفحهٔ انتخاب شده", + "rcfilters-target-page-placeholder": "وارد کردن نام صفحه (یا رده)", "rcnotefrom": "در زیر تغییرات از $3, $4 (تا $1 {{PLURAL:$5|نشان داده شده‌است|نشان داده شده‌اند}}).", "rclistfromreset": "از نو کردن انتخاب تاریخ", "rclistfrom": "نمایش تغییرات تازه با شروع از $3 $2", @@ -1874,7 +1881,7 @@ "doubleredirects": "تغییرمسیرهای دوتایی", "doubleredirectstext": "این صفحه فهرستی از صفحه‌های تغییرمسیری را ارائه می‌کند که به صفحهٔ تغییرمسیر دیگری اشاره می‌کنند.\nهر سطر دربردارندهٔ پیوندهایی به تغییرمسیر اول و دوم و همچنین مقصد تغییرمسیر دوم است، که معمولاً صفحهٔ مقصد واقعی است و نخستین تغییرمسیر باید به آن اشاره کند.\nموارد خط خورده درست شده‌اند.", "double-redirect-fixed-move": "[[$1]] انتقال داده شده‌است.\n\nبه صورت خودکار به‌روز شده‌است و تغییرمسیری به [[$2]] داده شد.", - "double-redirect-fixed-maintenance": "رفع خودکار تغییرمسیر دوتایی از [[$1]] به [[$2]] در روند نگهداری.", + "double-redirect-fixed-maintenance": "رفع خودکار تغییرمسیر دوتایی از [[$1]] به [[$2]] در روند نگهداری", "double-redirect-fixer": "تعمیرکار تغییرمسیرها", "brokenredirects": "تغییرمسیرهای خراب", "brokenredirectstext": "تغییرمسیرهای زیر به یک صفحهٔ ناموجود پیوند دارند:", @@ -2431,7 +2438,7 @@ "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", @@ -2670,6 +2677,7 @@ "import-mapping-subpage": "درون‌ریزی به عنوان زیرصفحهٔ صفحهٔ:", "import-upload-filename": "نام پرونده:", "import-upload-username-prefix": "پیشوند میان‌ویکی:", + "import-assign-known-users": "نسبت دادن ویرایش‌ها به کاربران محلی در صورتی که نام به صورت محلی وجود دارد", "import-comment": "توضیح:", "importtext": "لطفاً پرونده را از ویکی منبع با کمک [[Special:Export|ابزار برون‌بری]] دریافت کنید.\nسپس آن را روی دستگاه‌تان ذخیره کنید و اینجا بارگذاری نمایید.", "importstart": "در حال درون‌ریزی صفحات...", @@ -2678,6 +2686,7 @@ "imported-log-entries": "$1 {{PLURAL:$1|مورد سیاهه|مورد سیاهه}} درون ریزی شد.", "importfailed": "درون‌ریزی صفحات شکست خورد: $1", "importunknownsource": "نوع مأخذ درون‌ریزی معلوم نیست", + "importnoprefix": "پیشوند میان‌ویکی پشتیبانی نمی‌شود", "importcantopen": "پروندهٔ درون‌ریزی صفحات باز نشد", "importbadinterwiki": "پیوند میان‌ویکی نادرست", "importsuccess": "درون‌ریزی با موفقیت انجام شد!", @@ -2852,6 +2861,7 @@ "pageinfo-category-subcats": "تعداد زیررده‌ها", "pageinfo-category-files": "تعداد پرونده‌ها", "pageinfo-user-id": "شناسه کاربر", + "pageinfo-file-hash": "مقدار هش", "markaspatrolleddiff": "برچسب گشت بزن", "markaspatrolledtext": "به این صفحه برچسب گشت بزن", "markaspatrolledtext-file": "انتخاب این نسخهٔ پرونده به عنوان گشت خورده", @@ -3357,6 +3367,7 @@ "autosumm-replace": "جایگزینی صفحه با '$1'", "autoredircomment": "تغییرمسیر به [[$1]]", "autosumm-removed-redirect": "تغییرمسیر به [[$1]] حذف شد", + "autosumm-changed-redirect-target": "تغییر هدف تغییرمسیر از [[$1]] به [[$2]]", "autosumm-new": "صفحه‌ای تازه حاوی «$1» ایجاد کرد", "autosumm-newblank": "ایجاد صفحه خالی", "size-bytes": "$1 {{PLURAL:$1|بایت}}", @@ -4053,6 +4064,8 @@ "restrictionsfield-badip": "نشانی یا بازهٔ آی‌پی نامعتبر: $1", "restrictionsfield-label": "بازه‌های آی‌پی مجاز:", "restrictionsfield-help": "یک نشانی آی‌پی یا بازهٔ سی‌آی‌دی‌ار در هر خط وارد کنید. برای فعال کردن همه‌چیز، این مقدار را استفاده کنید: 0.0.0.0/0
::/0", + "edit-error-short": "خطا: $1", + "edit-error-long": "خطاها:\n\n$1", "revid": "نسخهٔ $1", "pageid": "شناسهٔ صفحهٔ $1", "rawhtml-notallowed": "برچسب‌های <html> را نمی‌توان خارج از صفحه‌های معمولی استفاده کرد.", diff --git a/languages/i18n/fr.json b/languages/i18n/fr.json index 7ca5b4c50a..a5f95979ac 100644 --- a/languages/i18n/fr.json +++ b/languages/i18n/fr.json @@ -867,6 +867,7 @@ "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", @@ -1804,7 +1805,7 @@ "lockmanager-fail-closelock": "Impossible de fermer le fichier de verrou pour « $1 ».", "lockmanager-fail-deletelock": "Impossible de supprimer le fichier de verrou pour « $1 ».", "lockmanager-fail-acquirelock": "Impossible d'obtenir le verrou pour « $1 ».", - "lockmanager-fail-openlock": "Impossible d'ouvrir le fichier de verrou pour « $1» .", + "lockmanager-fail-openlock": "Impossible d’ouvrir le fichier de verrou pour « $1 » . Assurez-vous que votre répertoire de téléchargement est configuré correctement et que votre serveur web a le droit d’y écrire. Voyez https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:$wgUploadDirectory pour plus d’information.", "lockmanager-fail-releaselock": "Impossible de relâcher le verrou pour « $1 ».", "lockmanager-fail-db-bucket": "Impossible de contacter suffisamment de bases de données de verrouillage dans le godet $1.", "lockmanager-fail-db-release": "Impossible de relâcher les verrous sur la base de données $1.", diff --git a/languages/i18n/he.json b/languages/i18n/he.json index 92f695020e..e309eec65c 100644 --- a/languages/i18n/he.json +++ b/languages/i18n/he.json @@ -183,7 +183,7 @@ "mytalk": "שיחה", "anontalk": "שיחה", "navigation": "ניווט", - "and": " וגם", + "and": " ו", "faq": "שאלות ותשובות", "actions": "פעולות", "namespaces": "מרחבי שם", @@ -734,6 +734,7 @@ "postedit-confirmation-created": "הדף נוצר.", "postedit-confirmation-restored": "הדף שוחזר.", "postedit-confirmation-saved": "העריכה שלך נשמרה.", + "postedit-confirmation-published": "העריכה שלך פורסמה.", "edit-already-exists": "לא ניתן ליצור דף חדש.\nהוא כבר קיים.", "defaultmessagetext": "טקסט ההודעה המקורי", "content-failed-to-parse": "פענוח $2 כתוכן מסוג $1 נכשל: $3", @@ -1663,7 +1664,7 @@ "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.", diff --git a/languages/i18n/hi.json b/languages/i18n/hi.json index c51d106ae2..fd014098d2 100644 --- a/languages/i18n/hi.json +++ b/languages/i18n/hi.json @@ -93,8 +93,8 @@ "Innocentbunny" ] }, - "tog-underline": "लिंक रेखांकित करें:", - "tog-hideminor": "हाल में हुए परिवर्तनों में छोटे बदलाव छिपाएँ", + "tog-underline": "कड़ी रेखांकन:", + "tog-hideminor": "हाल में हुए परिवर्तनों में लघु परिवर्तन छिपाएँ", "tog-hidepatrolled": "हाल में हुए परिवर्तनों में परीक्षित बदलाव छिपाएँ", "tog-newpageshidepatrolled": "नये पृष्ठ की सूची में परीक्षित पृष्ठों को छिपाएँ", "tog-hidecategorization": "पृष्ठों का श्रेणीकरण छिपाएं", @@ -3515,7 +3515,7 @@ "version-poweredby-others": "अन्य", "version-poweredby-translators": "translatewiki.net अनुवादक", "version-credits-summary": "हम निम्न व्यक्तियों द्वारा [[Special:Version|मीडियाविकि]] में किये गए योगदानों को सराहते हैं।", - "version-license-info": "मीडियाविकि मुक्त सॉफ़्टवेयर है; आप उसका पुनः वितरण कर सकते हैं और/या उसे संशोधित कर सकते हैं जैसा कि जे०एन०यू० साधारण सार्वजनिक लाइसेंस के अंतरगत फ़्री लाइसेंस फ़ाउन्डेशन द्वारा प्रकाशित किया गया था; या तो लाइसेंस का अवतरण २, या (आपके विकल्प के अनुसार) कोई और अवतरण।\n\nमीडियाविकि इस आशा के साथ वितरित किया गया है कि यह उपयुक्त है, पर वारंटी के बिना; जिसमें व्यापारिक मापदंड वाली वारंटी भी नहीं है और न ही किसी लक्ष्य के लिए पर्याप्त होने का प्रावधान है। और जानकारी के लिए देखिए जे०एन०यू० साधारण सार्वजनिक लाइसेंस।\n\nआपको इस प्रोग्राम के साथ [{{SERVER}}{{SCRIPTPATH}}/COPYING जे०एन०यू० साधारण सार्वजनिक लाइसेंस की एक प्रति] मिल चुकी होगी; यदि नहीं तो सम्पर्क कीजिए फ़्री लाइसेंस फ़ाउन्डेशन, इंक., 51 फ़्रैंकलिन स्ट्रीट, पाँचवीं मंज़िल, बोस्टन, एम०ए० 02110-1301, यू०एस०ए० या [//www.gnu.org/licenses/old-licenses/gpl-2.0.html इसे ऑनलाइन पढ़ें].", + "version-license-info": "मीडियाविकि मुक्त सॉफ़्टवेयर है; आप उसका पुनः वितरण कर सकते हैं और/अथवा उसे जे०एन०यू० साधारण सार्वजनिक लाइसेंस के अंतरगत संशोधित कर सकते हैं, जैसा की फ़्री लाइसेंस फ़ाउन्डेशन द्वारा प्रकाशित किया गया था; या तो लाइसेंस का अवतरण २, या (आपके विकल्प के अनुसार) उसके बाद के कोई भी अन्य अवतरण।\n\nमीडियाविकि इस आशा के साथ वितरित किया गया है कि यह उपयुक्त है, पर वारंटी के बिना; जिसमें व्यापारिक मापदंड वाली वारंटी भी नहीं है और न ही किसी लक्ष्य के लिए पर्याप्त होने का प्रावधान है। अधिक जानकारी के लिए जे०एन०यू० साधारण सार्वजनिक लाइसेंस देखिये।\n\nआपको इस प्रोग्राम के साथ [{{SERVER}}{{SCRIPTPATH}}/COPYING जे०एन०यू० साधारण सार्वजनिक लाइसेंस की एक प्रति] मिल चुकी होगी; यदि नहीं तो सम्पर्क कीजिए फ़्री लाइसेंस फ़ाउन्डेशन, इंक., 51 फ़्रैंकलिन स्ट्रीट, पाँचवीं मंज़िल, बॉस्टन, एम०ए० 02110-1301, यू०एस०ए० या [//www.gnu.org/licenses/old-licenses/gpl-2.0.html इसे ऑनलाइन पढ़ें].", "version-software": "इन्स्टॉल की हुई प्रणाली", "version-software-product": "प्रोडक्ट", "version-software-version": "अवतरण", @@ -3572,7 +3572,7 @@ "tag-list-wrapper": "([[Special:Tags|{{PLURAL:$1|टैग}}]]: $2)", "tag-mw-contentmodelchange": "सामग्री मॉडल परिवर्तन", "tag-mw-contentmodelchange-description": "पृष्ठ [https://www.mediawiki.org/wiki/Special:MyLanguage/Help:ChangeContentModel सामग्री मॉडल को परिवर्तित करें] के संपादन।", - "tag-mw-new-redirect": "नया पुन्नः प्रेषित लक्ष्य", + "tag-mw-new-redirect": "नया अनुप्रेषण", "tag-mw-new-redirect-description": "बदलाव जो एक नया रीडायरेक्ट बनाते हैं या पुनर्निर्देशन के लिए एक पृष्ठ बदलते हैं", "tag-mw-removed-redirect": "हटाया गया पुनर्निर्देशन", "tag-mw-removed-redirect-description": "संपादन जो किसी मौजूदा रीडायरेक्ट को गैर रीडायरेक्ट में बदलता है", @@ -3584,7 +3584,7 @@ "tag-mw-replace-description": "संपादन जिसने 90% से अधिक पृष्ट की सामग्री को हटा दिया", "tag-mw-rollback": "प्रत्यापन्न", "tag-mw-rollback-description": "संपादन जो रोलबैक लिंक का उपयोग करके पिछला संपादन वापस रोल करता है", - "tag-mw-undo": "किए हुए कार्य को पूर्वत करना", + "tag-mw-undo": "किए हुए कार्य को पूर्ववत करना", "tag-mw-undo-description": "संपादन जो पिछले लिंक का उपयोग करके पिछले संपादन को पूर्वत करता है", "tags-title": "चिप्पियाँ", "tags-intro": "यह पृष्ठ अर्थ सहित वह चिप्पियाँ दर्शाता है जिनका कोई तंत्रांश किसी संपादन पर निशान लगाने के लिए इस्तेमाल कर सकता है।", @@ -3855,9 +3855,9 @@ "limitreport-expansiondepth": "उच्चतम विस्तार गहराई", "limitreport-expensivefunctioncount": "महंगे पार्सर फंक्शनों की संख्या", "expandtemplates": "साँचा विस्तार", - "expand_templates_intro": "यह विशेष पृष्ठ पाठ इनपुट लेता है और सभी साँचों को विस्तृत करता है।\nयह {{#language:…}} जैसे पार्सर फंक्शनों और\n{{CURRENTDAY}} जैसे वेरियेबलों को भी विस्तृत करता है।\nयह दोहरे कोष्ठकों में दिया लगभग सब कुछ विस्तृत करता है।", + "expand_templates_intro": "यह विशेष पृष्ठ विकिपाठ्य इनपुट लेता है और उसके भीतर के सभी साँचों को विस्तृत करता है।\nयह {{#language:…}} जैसे पार्सर फ़ंक्शन्स और\n{{CURRENTDAY}} जैसे परिवर्तनशील मानों का भी विस्त्रण करता है।\nयह दोहरे कोष्ठकों में प्रेषित लगभग सब कुछ विस्तृत करता है।", "expand_templates_title": "कन्टेक्स्ट शीर्षक, जैसे {{FULLPAGENAME}} आदि के लिए:", - "expand_templates_input": "इनपुट पाठ:", + "expand_templates_input": "विकिपाठ्य इनपुट करें:", "expand_templates_output": "परिणाम", "expand_templates_xml_output": "XML आउटपुट", "expand_templates_html_output": "सीधे-साधा एचटीएमएल आउटपुट", @@ -3869,7 +3869,7 @@ "expand_templates_preview": "झलक", "expand_templates_preview_fail_html": "अगर यह वैध पूर्ववावलोकन प्रयास है, तो फिर से प्रयास कीजिए।\nअगर इससे काम न बने तो [[Special:UserLogout|सत्रांत होकर]] पुनः से लॉग इन करें और जाँच करें की आपका ब्राउज़र इस साइट पर कुकीज को अनुमत करता है।", "expand_templates_preview_fail_html_anon": "चूँकि {{SITENAME}} सीधे-साधे रूप से एचटीएमएल-सक्षम है और आप लॉग्ड इन नहीं है, पूर्वावलोकन छिपा हुआ है ताकि सम्भावित जावास्क्रिप्ट हमले को रोका सके।\n\nअगर यह वैध पूर्वावलोकन प्रयास है तो कृपया [[Special:UserLogin|लॉग इन करके]] फिर से प्रयास कीजिए।", - "expand_templates_input_missing": "आपको कम से कम कुछ पाठ्य प्रदान करने पड़ेंगे।", + "expand_templates_input_missing": "आपको कम से कम कुछ विकीपाठ्य प्रदान करने पड़ेंगे।", "pagelanguage": "पृष्ठ भाषा बदलें", "pagelang-name": "पृष्ठ", "pagelang-language": "भाषा", diff --git a/languages/i18n/hr.json b/languages/i18n/hr.json index 03dbd4990a..060c444bb3 100644 --- a/languages/i18n/hr.json +++ b/languages/i18n/hr.json @@ -1979,7 +1979,7 @@ "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", @@ -3467,7 +3467,7 @@ "logentry-import-interwiki": "$1 {{GENDER:$2|uvezao|uvezla}} je $3 s drugog wikija", "logentry-import-interwiki-details": "$1 {{GENDER:$2|uvezao|uvezla}} je $3 sa $5 ($4 {{PLURAL:$4|izmjena|izmjene|izmjena}})", "logentry-merge-merge": "$1 je {{GENDER:$2|spojio|spojila}} $3 s $4 (izmjene do $5)", - "logentry-move-move": "$1 je {{GENDER:$2|premjestio|premjestila}} stranicu $3 na $4", + "logentry-move-move": "$1 {{GENDER:$2|premjestio|premjestila}} je stranicu $3 na $4", "logentry-move-move-noredirect": "$1 je {{GENDER:$2|premjestio|premjestila}} stranicu $3 na $4 bez preusmjeravanja", "logentry-move-move_redir": "$1 je {{GENDER:$2|premjestio|premjestila}} stranicu $3 na $4 preko preusmjeravanja", "logentry-move-move_redir-noredirect": "$1 je {{GENDER:$2|premjestio|premjestila}} stranicu $3 na $4 preko preusmjeravanja bez ostavljanja preusmjeravanja", diff --git a/languages/i18n/hu.json b/languages/i18n/hu.json index 1a1353d416..082760f9f0 100644 --- a/languages/i18n/hu.json +++ b/languages/i18n/hu.json @@ -747,6 +747,7 @@ "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", @@ -989,7 +990,7 @@ "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:", @@ -1675,7 +1676,7 @@ "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.", diff --git a/languages/i18n/ia.json b/languages/i18n/ia.json index 110935f27f..fbd62a3e63 100644 --- a/languages/i18n/ia.json +++ b/languages/i18n/ia.json @@ -1861,8 +1861,8 @@ "uncategorized-categories-exceptionlist": " # Contine un lista de categorias que non debe esser mentionate sur Special:UncategorizedCategories. Un per linea, comenciante con \"*\". Lineas que comencia con un altere character (incluse spatios) es ignorate. Usa \"#\" for commentos.", "unusedcategories": "Categorias non usate", "unusedimages": "Imagines non usate", - "wantedcategories": "Categorias plus demandate", - "wantedpages": "Paginas plus demandate", + "wantedcategories": "Categorias desirate", + "wantedpages": "Paginas desirate", "wantedpages-summary": "Lista del paginas non existente con le major numero de ligamines verso illos, excludente le paginas verso le quales solmente redirectiones liga. Pro un lista del paginas non existente verso le quales redirectiones liga, vide [[{{#special:BrokenRedirects}}|le lista de redirectiones rupte]].", "wantedpages-badtitle": "Titulo invalide in le gruppo de resultatos: $1", "wantedfiles": "Files desirate", diff --git a/languages/i18n/inh.json b/languages/i18n/inh.json index 9c7e5fd0ed..f4fe4cd664 100644 --- a/languages/i18n/inh.json +++ b/languages/i18n/inh.json @@ -983,6 +983,7 @@ "exif-languagecode": "Мотт", "exif-iimcategory": "Категори", "exif-orientation-1": "гIаьхьа", + "exif-exposureprogram-1": "Кара", "exif-scenecapturetype-1": "Ландшафт", "exif-scenecapturetype-2": "Сага сурт", "exif-iimcategory-edu": "Дешарца Iомадар", diff --git a/languages/i18n/is.json b/languages/i18n/is.json index 340ab40168..8aeac3c540 100644 --- a/languages/i18n/is.json +++ b/languages/i18n/is.json @@ -958,6 +958,7 @@ "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ð", @@ -1533,7 +1534,7 @@ "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.", @@ -1554,6 +1555,8 @@ "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", @@ -1705,7 +1708,7 @@ "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 á.\nYfirstrikaðar 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:", @@ -2679,6 +2682,7 @@ "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", diff --git a/languages/i18n/it.json b/languages/i18n/it.json index b843b77bdc..88a605bda8 100644 --- a/languages/i18n/it.json +++ b/languages/i18n/it.json @@ -140,7 +140,7 @@ "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)", @@ -561,8 +561,8 @@ "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.", @@ -571,7 +571,7 @@ "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.", @@ -592,7 +592,7 @@ "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.", @@ -676,7 +676,7 @@ "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.", @@ -810,6 +810,7 @@ "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", @@ -1735,7 +1736,7 @@ "lockmanager-fail-closelock": "Non riuscita chiusura del file di blocco per \"$1\".", "lockmanager-fail-deletelock": "Non riuscita cancellazione del file di blocco per \"$1\".", "lockmanager-fail-acquirelock": "Non riuscita acquisizione blocco per \"$1\".", - "lockmanager-fail-openlock": "Non riuscita apertura del file di blocco per \"$1\".", + "lockmanager-fail-openlock": "Non riuscita apertura del file di blocco per \"$1\". Assicurati che la cartella per i caricamenti sia configurata correttamente e il web server abbia i permessi per scriverci. Vedi https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:$wgUploadDirectory per ulteriori informazioni.", "lockmanager-fail-releaselock": "Non riuscito rilascio del blocco per \"$1\".", "lockmanager-fail-db-bucket": "Impossibile contattare i necessari database di blocco nel bucket $1.", "lockmanager-fail-db-release": "Impossibile revocare i blocchi sul database $1.", @@ -2161,8 +2162,8 @@ "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", @@ -3346,14 +3347,14 @@ "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", @@ -3539,7 +3540,7 @@ "tag-mw-blank-description": "Modifiche che svuotano una pagina", "tag-mw-replace": "Sostituito", "tag-mw-replace-description": "Modifiche che rimuovono oltre il 90% del contenuto di una pagina", - "tag-mw-rollback": "Atmesti", + "tag-mw-rollback": "Rollback", "tag-mw-rollback-description": "Modifiche che ripristinano le versioni precedenti utilizzando il collegamento di rollback", "tag-mw-undo": "Annulla", "tag-mw-undo-description": "Modifiche che annullano le modifiche precedenti utilizzando il collegamento \"Annulla\"", diff --git a/languages/i18n/ja.json b/languages/i18n/ja.json index a50f7bc55d..6be5b5db88 100644 --- a/languages/i18n/ja.json +++ b/languages/i18n/ja.json @@ -1554,7 +1554,7 @@ "recentchangeslinked-feed": "関連ページの更新状況", "recentchangeslinked-toolbox": "関連ページの更新状況", "recentchangeslinked-title": "「$1」と関連する変更", - "recentchangeslinked-summary": "これは指定したページからリンクされている (または指定したカテゴリに含まれている) ページの最近の変更の一覧です。\n[[Special:Watchlist|自分のウォッチリスト]]にあるページは太字で表示されます。", + "recentchangeslinked-summary": "ページ名を入力すると、リンク関係 (そのページのリンク先もしくは他のページからのリンク) の最近の変更を調べることができます。 (下位カテゴリを参照するには、カテゴリ:カテゴリ名 (Category:Name of category) を入力)。[[Special:Watchlist|自分のウォッチリスト]]にあるページの変更は太字で表示されます。", "recentchangeslinked-page": "ページ名:", "recentchangeslinked-to": "このページへのリンク元での変更の表示に切り替え", "recentchanges-page-added-to-category": "[[:$1]]をカテゴリに追加", @@ -1636,7 +1636,7 @@ "uploaded-script-svg": "アップロードされたSVGファイルにスクリプト可能な要素「$1」が見つかりました。", "uploaded-hostile-svg": "アップロードされたSVGファイルのスタイル要素に安全ではないCSSが見つかりました。", "uploaded-event-handler-on-svg": "イベントハンドラをセットする属性 $1=\"$2\" は、SVGファイルを許可されていません。", - "uploaded-href-attribute-svg": "SVG ファイルの href 属性が http:// または https:// のターゲットのみにリンクする <$1 $2=\"$3\"> が見つかりました。", + "uploaded-href-attribute-svg": " 要素では、データ (埋め込みファイル)、http://、https://、フラグメント (#、ID 属性など) のターゲットにのみリンクできます。 などの他の要素では、データとフラグメントのみが使用できます。SVG をエクスポートする際は画像を埋め込むようにしてください。アップロードされたファイルには <$1 $2=\"$3\"> が含まれています。", "uploaded-href-unsafe-target-svg": "アップロードされた SVG ファイルの、安全ではないデータ URI にターゲット <$1 $2=\"$3\"> の href が見つかりました。", "uploaded-animate-svg": "アップロードされたSVGファイルに、「from」属性 <$1 $2=\"$3\"> を使用した、href を変更させる可能性がある「animate」タグが見つかりました。", "uploaded-setting-event-handler-svg": "アップロードされたSVGファイルに、ブロックされているイベントハンドラ属性が設定された <$1 $2=\"$3\"> が見つかりました。", @@ -1726,7 +1726,7 @@ "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 上のロックを解放できませんでした。", @@ -1745,6 +1745,12 @@ "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": "アクセスが拒否されました", @@ -2693,6 +2699,7 @@ "import-mapping-namespace": "名前空間へインポート:", "import-mapping-subpage": "次のページの下位ページとしてインポート:", "import-upload-filename": "ファイル名:", + "import-upload-username-prefix": "インターウィキ接頭辞:", "import-comment": "コメント:", "importtext": "元のウィキで[[Special:Export|書き出し機能]]を使用してファイルに書き出してください。\nそれをコンピューターに保存した後、こちらへアップロードしてください。", "importstart": "ページを取り込み中...", @@ -2889,6 +2896,7 @@ "pageinfo-category-subcats": "下位カテゴリ数", "pageinfo-category-files": "ファイル数", "pageinfo-user-id": "利用者 ID", + "pageinfo-file-hash": "ハッシュ値", "markaspatrolleddiff": "巡回済みにする", "markaspatrolledtext": "このページを巡回済みにする", "markaspatrolledtext-file": "このファイルの版を巡回済みにする", @@ -3970,9 +3978,9 @@ "limitreport-expensivefunctioncount": "高負荷パーサー関数の数", "limitreport-expensivefunctioncount-value": "$1/$2", "expandtemplates": "テンプレートを展開", - "expand_templates_intro": "この特別ページは、入力したテキストに含まれるすべてのテンプレートを再帰的に展開します。\n{{#language:…}} のようなパーサー関数や、\n{{CURRENTDAY}} のような変数も展開します。\nつまり、二重中括弧で囲まれたものほぼすべてを展開します。", + "expand_templates_intro": "この特別ページは、入力したウィキテキストに含まれるすべてのテンプレートを再帰的に展開します。\n{{#language:…}} のようなパーサー関数や、\n{{CURRENTDAY}} のような変数も展開します。\nつまり、二重中括弧で囲まれたものほぼすべてを展開します。", "expand_templates_title": "{{FULLPAGENAME}} などで使用するページ名:", - "expand_templates_input": "展開するテキスト:", + "expand_templates_input": "展開するウィキテキスト:", "expand_templates_output": "展開結果", "expand_templates_xml_output": "XML 出力", "expand_templates_html_output": "出力される HTML ソース", @@ -3984,7 +3992,7 @@ "expand_templates_preview": "プレビュー", "expand_templates_preview_fail_html": "{{SITENAME}} ではHTMLソースが有効になっており、セッションデータの損失が生じているので、JavaScript の攻撃に対する予防措置としてプレビューは表示されません。\n\nこれが合法的なプレビューの試みである場合には、もう一度試してください。\nそれでも動作しない場合は、[[Special:UserLogout|ログアウト]]してからログインし直し、現在使用しているブラウザでこのサイトからのクッキーが許可されていることを確認してください。", "expand_templates_preview_fail_html_anon": "{{SITENAME}} ではHTMLソースが有効になっており、ログインしていないため、JavaScript の攻撃に対する予防措置としてプレビューは表示されません。\n\nこれが合法的なプレビューの試みである場合には、[[Special:UserLogin|ログイン]]してもう一度試してください。", - "expand_templates_input_missing": "文章を入力してください。", + "expand_templates_input_missing": "ウィキテキストを入力してください。", "pagelanguage": "ページ言語の変更", "pagelang-name": "ページ", "pagelang-language": "言語", @@ -4208,7 +4216,7 @@ "restrictionsfield-label": "許可する IP の範囲:", "restrictionsfield-help": "一行につき、単一の IP アドレス、もしくは CIDR による範囲。全帯域からの接続を許可する場合:
0.0.0.0/0\n::/0
", "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>タグは通常ページ以外では使用できません。", diff --git a/languages/i18n/jv.json b/languages/i18n/jv.json index 500e25ef78..9bb875aa37 100644 --- a/languages/i18n/jv.json +++ b/languages/i18n/jv.json @@ -279,7 +279,7 @@ "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", @@ -297,7 +297,7 @@ "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": "Panjenengan nyuwun kaca mirunggan sing ora sah.\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.", @@ -869,7 +869,7 @@ "showingresults": "Ing ngisor iki dituduhaké {{PLURAL:$1|'''1''' kasil|'''$1''' kasil}}, wiwitané saking #$2.", "showingresultsinrange": "Nuduhaké nganti {{PLURAL:$1|1 kasil|$1 kasil}} sajeroning penthangan #$2 tekan #$3.", "search-showingresults": "{{PLURAL:$4|Asil $1 saka $3|Asil $1 – $2 saka $3}}", - "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:", @@ -1198,7 +1198,7 @@ "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", @@ -1343,7 +1343,7 @@ "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]] dikandeli.", "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", @@ -1899,7 +1899,7 @@ "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é.", @@ -2397,7 +2397,7 @@ "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.", @@ -2451,7 +2451,7 @@ "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", @@ -2653,7 +2653,7 @@ "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", @@ -2994,7 +2994,7 @@ "scarytranscludetoolong": "[URL-é kedawan]", "deletedwhileediting": "Pélik: 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", @@ -3108,7 +3108,7 @@ "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", @@ -3295,7 +3295,7 @@ "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é}}", diff --git a/languages/i18n/lb.json b/languages/i18n/lb.json index 93677c0746..3b5714e50b 100644 --- a/languages/i18n/lb.json +++ b/languages/i18n/lb.json @@ -403,7 +403,7 @@ "password-change-forbidden": "Dir däerft op dëser Wiki Passwierder net änneren.", "externaldberror": "Entweder ass e Feeler bei der externer Authentifizéierung geschitt, oder Dir däerft Ären externe Benotzerkont net aktualiséieren.", "login": "Aloggen", - "login-security": "Iwwerpréift Är Idnetitéit", + "login-security": "Iwwerpréift Är Identitéit", "nav-login-createaccount": "Aloggen / Benotzerkont uleeën", "logout": "Ofmellen", "userlogout": "Ausloggen", @@ -702,6 +702,7 @@ "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", @@ -1743,7 +1744,7 @@ "doubleredirects": "Duebel Viruleedungen", "doubleredirectstext": "Op dëser Säit stinn déi Säiten déi op aner Viruleedungssäite viruleeden.\nAn all Rei sti Linken zur éischter an zweeter Viruleedung, souwéi d'Zil vun der zweeter Viruleedung, déi normalerweis déi \"richteg\" Zilsäit ass, op déi déi éischt Viruleedung hilinke soll.\nDuerchgestrachen Linke goufe scho sou verännert datt déi duebel Viruleedung opgeléist ass.", "double-redirect-fixed-move": "[[$1]] gouf geréckelt.\nD'Säit gouf automatesch aktualiséiert an et ass elo eng Viruleedung op [[$2]].", - "double-redirect-fixed-maintenance": "Duebel Viruleedung vu(n) [[$1]] op [[$2]] gouf automatesch an engem 'maintenance job' gefléckt.", + "double-redirect-fixed-maintenance": "Duebel Viruleedung vu(n) [[$1]] op [[$2]] gouf automatesch an engem 'maintenance job' gefléckt", "double-redirect-fixer": "Verbesserung vu Viruleedungen", "brokenredirects": "Futtis Viruleedungen", "brokenredirectstext": "Dës Viruleedunge linken op Säiten déi et net gëtt.", diff --git a/languages/i18n/lij.json b/languages/i18n/lij.json index 5736d877ae..171b989877 100644 --- a/languages/i18n/lij.json +++ b/languages/i18n/lij.json @@ -152,7 +152,7 @@ "about": "Informaçioìn", "article": "Vôxe", "newwindow": "(O s'arve inte 'n âtro barcon)", - "cancel": "Scancella", + "cancel": "Scancélla", "moredotdotdot": "Âtro...", "morenotlisted": "Questa lista a poriæ ese incompleta.", "mypage": "Pàgina", @@ -174,7 +174,7 @@ "searchbutton": "Riçèrca", "go": "Vanni", "searcharticle": "Vanni", - "history": "Stöia da pàgina", + "history": "Cronologîa da pàgina", "history_short": "Stöia", "history_small": "Stoia", "updatedmarker": "modificâ da-a mæ urtima vixita", @@ -207,7 +207,7 @@ "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)", @@ -280,7 +280,7 @@ "site-atom-feed": "Feed Atom de $1", "page-rss-feed": "Feed RSS pe \"$1\"", "page-atom-feed": "Feed Atom pe \"$1\"", - "red-link-title": "$1 (ancon da scrîve)", + "red-link-title": "$1 (a pàgina no esiste)", "sort-descending": "Ordine decrescente", "sort-ascending": "Ordine crescente", "nstab-main": "Pàgina", @@ -346,7 +346,7 @@ "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.", @@ -381,11 +381,11 @@ "welcomeuser": "Benvegnuo, $1!", "welcomecreation-msg": "L'utensa a l'è stæta creâ correttamente.\nSe ti veu ti peu personalizzâ e [[Special:Preferences|preferençe de {{SITENAME}}]].", "yourname": "Nomme", - "userlogin-yourname": "Nómme uténte:", - "userlogin-yourname-ph": "Scrivi o teu nomme utente", + "userlogin-yourname": "Nómme uténte", + "userlogin-yourname-ph": "Inserisci o teu nómme uténte", "createacct-another-username-ph": "Scrivi o teu nomme utente", "yourpassword": "Pòula segretta:", - "userlogin-yourpassword": "Pòula segretta:", + "userlogin-yourpassword": "Ciâve", "userlogin-yourpassword-ph": "Scrivi a tu poula segretta.", "createacct-yourpassword-ph": "Scrivi 'na poula segretta.", "yourpasswordagain": "Riscrivi a pòula segrétta:", @@ -410,7 +410,7 @@ "notloggedin": "No t'ê introu", "userlogin-noaccount": "No ti t'ê ancon registrou?", "userlogin-joinproject": "Registrite insce {{SITENAME}}", - "createaccount": "Crea 'n nêuvo account", + "createaccount": "Registrati", "userlogin-resetpassword-link": "T'hæ miga ascordou a teu poula segretta?", "userlogin-helplink2": "Agiutto pe intrâ", "userlogin-loggedin": "Ti t'ê zà connesso comme {{GENDER:$1|$1}}.\nUsa o formulaio sottostante pe accede comme 'n atro utente.", @@ -426,14 +426,14 @@ "createacct-reason": "Raxon", "createacct-reason-ph": "Perché t'ê apreuvo a creâ un'atra utensa", "createacct-reason-help": "Messaggio vixualizou into registro da creaçion de l'utença", - "createacct-submit": "Crea a to utensa", + "createacct-submit": "Crea a teu utensa", "createacct-another-submit": "Crea utensa", "createacct-continue-submit": "Continnoa a creaçion de l'utença", "createacct-another-continue-submit": "Continnoa a creaçion de l'utença", "createacct-benefit-heading": "{{SITENAME}} o l'è realizzou da de gente comme ti.", "createacct-benefit-body1": "{{PLURAL:$1|modìfica|modìfiche}}", "createacct-benefit-body2": "{{PLURAL:$1|pàgina|pàgine}}", - "createacct-benefit-body3": "{{PLURAL:$1|contribuiou|contribuioei}}", + "createacct-benefit-body3": "{{PLURAL:$1|contribûtô recénte|contribûtoî recénti}}", "badretype": "E paròlle d'ordine che t'hæ scrîo son despægie.", "usernameinprogress": "A creassion de 'n utensa con questo nomme a l'è zà in corso.\nSe prega de aspêtâ.", "userexists": "O nomme ûtente inserîo o l'è za doeuviao.
\nÇernine 'n âtro.", @@ -546,7 +546,7 @@ "resetpass-expired": "A to poula segretta a l'è descheita. Pe piaxei impòstine un-a neuva pe intrâ.", "resetpass-expired-soft": "A to poula segretta a l'è descheita e a g'ha da ese reimpostâ. Pe piaxei çèrnine un-a neuva òua ò clicca in sce \"{{int:authprovider-resetpass-skip-label}}\" pe reimpostâla ciu tardi.", "resetpass-validity-soft": "A to poula segretta a no l'è vallida: $1\n\nPe piaxei çèrnine un-a neuva òua, ò clicca in sce \"{{int:authprovider-resetpass-skip-label}}\" pe reimpostala ciu tardi.", - "passwordreset": "Reimposta a poula segretta", + "passwordreset": "Reimposta ciâve", "passwordreset-text-one": "Compilla sto formulaio pe riçeive a teu poula segretta temporannia via e-mail.", "passwordreset-text-many": "{{PLURAL:$1|Compilla un di campi pe riçeive una poula segretta temporannia via e-mail.}}", "passwordreset-disabled": "A reimpostaçion de poule segrette a l'è stæta disabilitâ in sce sta wiki", @@ -602,7 +602,7 @@ "media_tip": "Ingancio a file moltimediâ", "sig_tip": "Firma con dæta e ôa", "hr_tip": "Linnia orizontâ", - "summary": "Oggetto:", + "summary": "Ògetto:", "subject": "Sogetto:", "minoredit": "Quésta a l'é 'na modìfica minô", "watchthis": "Metti sotta oservaçion", @@ -611,8 +611,8 @@ "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": "Atençión: 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": "Attension: No t'ê introu. Se ti fæ di cangi o teu adresso IP o saiâ vixibile pubbricamente. Se [$1 ti intri] ò [$2 ti crei un'utensa], 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", @@ -756,7 +756,7 @@ "undo-summary-username-hidden": "Anullou a modiffica $1 de un utente ascoso", "cantcreateaccount-text": "A registrassion da questo addresso IP ($1) 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 $1, ch'o l'includde o teu ($4), a l'è stæta bloccâ da [[User:$3|$3]].\n\nA raxon dæta da $3 a l'è $2", - "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", @@ -1270,7 +1270,7 @@ "action-purge": "aggiornâ questa paggina", "nchanges": "$1 {{PLURAL:$1|modiffica|modiffiche}}", "enhancedrc-since-last-visit": "$1 {{PLURAL:$1|da l'urtima vixita}}", - "enhancedrc-history": "cronologia", + "enhancedrc-history": "cronologîa", "recentchanges": "Ùrtime modìfiche", "recentchanges-legend": "Opçioin di ùrtimi cangiaménti", "recentchanges-summary": "Questa pagina a te mostra i cangiamenti ciu reçenti a-i contegnui do scito.", @@ -1282,7 +1282,7 @@ "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": "Legenda:", - "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çæ", @@ -1424,7 +1424,7 @@ "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", @@ -1440,7 +1440,7 @@ "uploadlogpage": "Log di file caregæ", "uploadlogpagetext": "De sotta gh'è una lista di urtimi file caregæ.\nConsultâ a [[Special:NewFiles|galleria di noeuvi file]] pe 'na vixon d'insemme.", "filename": "Nomme do file", - "filedesc": "Detaggi", + "filedesc": "Detàggi", "fileuploadsummary": "Detaggi do file:", "filereuploadsummary": "Cangiamenti a-o file:", "filestatus": "Informaçioin in sciô copyright:", @@ -1627,8 +1627,8 @@ "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)", @@ -1906,7 +1906,7 @@ "magiclink-tracking-isbn-desc": "Sta paggina a l'adoeuvia di inganci maggichi ISBN. Amia [https://www.mediawiki.org/wiki/Special:MyLanguage/Help:Magic_links mediawiki.org] sciu comme exeguî a migraçion.", "specialloguserlabel": "Açion effettuâ da:", "speciallogtitlelabel": "Açion effettuâ sciu (tittolo da paggina ò {{ns:user}}:Nomme utente):", - "log": "Log", + "log": "Regìstri", "logeventslist-submit": "Mostra", "all-logs-page": "Tùtti i regìstri pùblici", "alllogstext": "Presentaçion combinaa de tutti i registri de {{SITENAME}}.\nL'è poscibile restrenze i critei de riçerca seleçionando o tipo de registro, l'utente ch'o l'ha eseguio l'açion, e/ò a pagina interessâ (entrambi i campi son senscibbili a-o maiuscolo/minuscolo).", @@ -2026,8 +2026,8 @@ "emailuserfooter": "Questa email a l'è stæta {{GENDER:$1|inviâ}} da $1 a {{GENDER:$2|$2}} a traverso a fonçion \"{{int:emailuser}}\" insce {{SITENAME}}. Se {{GENDER:$2|ti ghe rispondi}}, a to email de risposta a saiâ spedia direttamente {{GENDER:$1|a-o|a-a}} mittente originâ, rivelando{{GENDER:$1|ghe}} o {{GENDER:$2|to}} adresso de posta elettronica.", "usermessage-summary": "Messaggio de scistema", "usermessage-editor": "Messaggê de scistema", - "watchlist": "Sotta osservassion", - "mywatchlist": "Sotta oservaçion", + "watchlist": "Òservòi speciâli", + "mywatchlist": "òservòi speciâli", "watchlistfor2": "Pe $1 $2", "nowatchlist": "A lista di öservæ speciali a l'è voeua.", "watchlistanontext": "Pe vixualizzâ e modificâ l'elenco di öservæ l'è necessaio eseguî l'accesso.", @@ -2152,7 +2152,7 @@ "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.", @@ -2201,9 +2201,9 @@ "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}}'''''.", @@ -2246,8 +2246,8 @@ "blanknamespace": "(Prinçipâ)", "contributions": "Contribuçioin {{GENDER:$1|utente}}", "contributions-title": "Contribuçioìn de $1", - "mycontris": "Contribuçioin", - "anoncontribs": "Contribuçioin", + "mycontris": "contribûti", + "anoncontribs": "contribûti", "contribsub2": "Pe {{GENDER:$3|$1}} ($2)", "contributions-userdoesnotexist": "L'utença \"$1\" a no l'è registrâ.", "nocontribs": "Cangi che soddisfan i critei de riçerca no se n'è atrovou.", @@ -2257,7 +2257,7 @@ "sp-contributions-newbies": "Fanni védde sôlo e contribuçioìn di nêuvi utenti", "sp-contributions-newbies-sub": "Pe i nêuvi ûtenti", "sp-contributions-newbies-title": "Contribuçioin di noeuvi utenti", - "sp-contributions-blocklog": "Blòcchi", + "sp-contributions-blocklog": "blòcchi", "sp-contributions-suppresslog": "contributi {{GENDER:$1|utente}} soppresci", "sp-contributions-deleted": "contributi {{GENDER:$1|utente}} scassæ", "sp-contributions-uploads": "caregaménti", @@ -2362,7 +2362,7 @@ "blocklist-nousertalk": "o no poeu modificâ a proppia pagina de discuscion", "ipblocklist-empty": "A lista di blocchi a l'è veua.", "ipblocklist-no-results": "L'adreçço IP ô o nomme utente domandou o no l'è bloccou.", - "blocklink": "Blocca", + "blocklink": "blòcca", "unblocklink": "sblòcca", "change-blocklink": "càngia blòcco", "contribslink": "Contribuçioìn", @@ -2577,7 +2577,7 @@ "javascripttest": "Sperimentaçion JavaScript", "javascripttest-pagetext-unknownaction": "Açion sconosciua \"$1\".", "javascripttest-qunit-intro": "Amia insce mediawiki.org a [$1 documentaçion riguardante i test].", - "tooltip-pt-userpage": "A {{GENDER:|to}} pagina utente", + "tooltip-pt-userpage": "A {{GENDER:|teu}} pàgina uténte", "tooltip-pt-anonuserpage": "A paggina utente de questo adreçço IP che t'ê aproeuvo a modificâ comme", "tooltip-pt-mytalk": "A {{GENDER:|teu}} pàgina de discusción", "tooltip-pt-anontalk": "Discuscioin insce e modiffiche fæte da questo adreçço IP", @@ -2625,14 +2625,14 @@ "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-category": "Veddi a paggina da categorîa", + "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", "tooltip-publish": "Pubbrica e to modiffiche", @@ -2671,7 +2671,7 @@ "pageinfo-not-current": "Spiaxente, ma l'è imposcibbile fornî quest'informaçion pe de vege verscioin.", "pageinfo-header-basic": "Informaçion de base", "pageinfo-header-edits": "Cronologia de modiffiche", - "pageinfo-header-restrictions": "Proteçion da paggina", + "pageinfo-header-restrictions": "Proteçión da pàgina", "pageinfo-header-properties": "Propiêtæ da pàgina", "pageinfo-display-title": "Tittolo vixualizzou", "pageinfo-default-sort": "Criteio d'ordenamento predefinio", @@ -2693,7 +2693,7 @@ "pageinfo-subpages-value": "$1 ($2 {{PLURAL:$2|redirect}}; $3 {{PLURAL:$3|non redirect}})", "pageinfo-firstuser": "Creatô da pàgina", "pageinfo-firsttime": "Dæta de creaçion da paggina", - "pageinfo-lastuser": "Urtimo contributô", + "pageinfo-lastuser": "Ùrtimo contributô", "pageinfo-lasttime": "Dæta de l'urtima modiffica", "pageinfo-edits": "Nummero totale de modiffiche", "pageinfo-authors": "Nummero totale di aotoî distinti", @@ -3235,8 +3235,8 @@ "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", diff --git a/languages/i18n/lt.json b/languages/i18n/lt.json index 7d22c96696..4617b6af4d 100644 --- a/languages/i18n/lt.json +++ b/languages/i18n/lt.json @@ -718,7 +718,7 @@ "permissionserrorstext": "Jūs neturite teisių tai daryti dėl {{PLURAL:$1|šios priežasties|šių priežasčių}}:", "permissionserrorstext-withaction": "Jūs neturite leidimo $2 dėl {{PLURAL:$1|šios priežasties|šių priežasčių}}:", "contentmodelediterror": "Jūs negalite redaguoti šios versijos, nes jos turinio modelis yra $1, kuris skiriasi nuo dabartinio puslapio turinio modelio, kuris yra $2.", - "recreate-moveddeleted-warn": "'''Dėmesio: Jūs atkuriate puslapį, kuris anksčiau buvo ištrintas.'''\n\nTurėtumėte nuspręsti, ar reikėtų toliau redaguoti šį puslapį.\nJūsų patogumui čia pateikiamas šio puslapio šalinimų ir perkėlimų sąrašas:", + "recreate-moveddeleted-warn": "Dėmesio: Jūs atkuriate puslapį, kuris anksčiau buvo ištrintas.\n\nTurėtumėte nuspręsti, ar reikėtų toliau redaguoti šį puslapį.\nJūsų patogumui čia pateikiamas šio puslapio šalinimų ir perkėlimų sąrašas:", "moveddeleted-notice": "Šis puslapis buvo ištrintas.\nŽemiau pateikiamas puslapio šalinimų, apsaugojimų, ir pervadinimų sąrašas.", "moveddeleted-notice-recent": "Atsiprašome, šis puslapis buvo neseniai ištrintas (per pastarąsias 24 valandas). Žemiau pateikiama detali puslapio ištrynimo, rakinimo ir perkėlimo istorija.", "log-fulllog": "Rodyti visą istoriją", @@ -1795,7 +1795,7 @@ "doubleredirects": "Dvigubi peradresavimai", "doubleredirectstext": "Šiame puslapyje yra puslapių, kurie nukreipia į kitus peradresavimo puslapius, sąrašas.\nKiekvienoje eilutėje yra nuorodos į pirmąjį ir antrąjį peradresavimą, taip pat antrojo peradresavimo paskirtis, kuris paprastai yra „tikrasis“ paskirties puslapis, į kurį pirmasis peradresavimas ir turėtų rodyti.\nIšbraukti įrašai yra išspręsti.", "double-redirect-fixed-move": "[[$1]] buvo pervardytas; dabar tai peradresavimas į [[$2]].", - "double-redirect-fixed-maintenance": "Tvarkomas dvigubas peradresavimas iš [[$1]] į [[$2]].", + "double-redirect-fixed-maintenance": "Tvarkomas dvigubas peradresavimas iš [[$1]] į [[$2]]", "double-redirect-fixer": "Peradresavimų tvarkyklė", "brokenredirects": "Peradresavimai į niekur", "brokenredirectstext": "Šie peradresavimo puslapiai nurodo į neegzistuojančius puslapius:", @@ -2295,7 +2295,7 @@ "sp-contributions-uploads": "įkėlimai", "sp-contributions-logs": "specialiųjų veiksmų sąrašas", "sp-contributions-talk": "aptarimas", - "sp-contributions-userrights": "naudotojų teisių valdymas", + "sp-contributions-userrights": "{{GENDER:$1|naudotojų}} teisių valdymas", "sp-contributions-blocked-notice": "Šis naudotojas šiuo metu užblokuotas.\nPateikiamas paskutinis blokavimo istorijos įrašas.", "sp-contributions-blocked-notice-anon": "Šis IP adresas yra užblokuotas.\nPaskutinis blokavimo įrašas pateikiamas žemiau:", "sp-contributions-search": "Ieškoti įnašų", @@ -2679,7 +2679,7 @@ "lastmodifiedatby": "Šį puslapį paskutinį kartą redagavo $2, $1, $3.", "othercontribs": "Paremta $1 darbu.", "others": "kiti", - "siteusers": "{{SITENAME}} {{PLURAL:$2|naudotojas|naudotojai}} $1", + "siteusers": "{{SITENAME}} {{PLURAL:$2|{{GENDER:$1|naudotojas|naudotoja}}|naudotojai}} $1", "anonusers": "{{SITENAME}} {{PLURAL:$2|anoniminis naudotojas|anoniminiai naudotojai}} $1", "creditspage": "Puslapio kūrėjai", "nocredits": "Kūrėjų informacija negalima šiam puslapiui.", @@ -3579,7 +3579,7 @@ "feedback-thanks": "Ačiū! Jūsų atsiliepimas buvo užregistruotas puslapyje „[$2 $1]“.", "feedback-thanks-title": "Ačiū!", "feedback-useragent": "Vartotojo veiksnys:", - "searchsuggest-search": "Ieškoti", + "searchsuggest-search": "Ieškoti {{SITENAME}}", "searchsuggest-containing": "turintys", "api-error-badtoken": "Vidinė klaida: blogai atpažinimo ženklas.", "api-error-emptypage": "Kurti naujus, tuščius puslapius neleidžiama.", @@ -3611,7 +3611,7 @@ "limitreport-expansiondepth": "Didžiausias plėtimosi gylis", "limitreport-expensivefunctioncount": "Brangaus analizatoriaus funkcijos skaičius", "expandtemplates": "Išplėsti šablonus", - "expand_templates_intro": "Šis specialus puslapis pasirenką tekstą ir išplečia visus rekursyviai.\nJis taip pat išplečia palaikomas analizatoriaus funkcijas kaip\n{{#language:…}} ir kintamuosius kaip\n{{CURRENTDAY}}.\nTiesą sakant, jis išplečia beveik viską dvigubuose skliaustuose.", + "expand_templates_intro": "Šis specialus puslapis pasirenką vikitekstą ir išplečia visus rekursyviai.\nJis taip pat išplečia palaikomas analizatoriaus funkcijas kaip\n{{#language:…}} ir kintamuosius kaip\n{{CURRENTDAY}}.\nTiesą sakant, jis išplečia beveik viską dvigubuose skliaustuose.", "expand_templates_title": "Aplinkybės pavadinimas, {{FULLPAGENAME}} ir pan.:", "expand_templates_input": "Įvesti vikitekstą:", "expand_templates_output": "Rezultatas", diff --git a/languages/i18n/lv.json b/languages/i18n/lv.json index bd140096d8..1c9649557d 100644 --- a/languages/i18n/lv.json +++ b/languages/i18n/lv.json @@ -643,6 +643,7 @@ "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", @@ -987,6 +988,7 @@ "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", @@ -1502,7 +1504,7 @@ "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ā.\nNosvītrotie 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:", diff --git a/languages/i18n/mk.json b/languages/i18n/mk.json index 57ba371d89..342a1afbac 100644 --- a/languages/i18n/mk.json +++ b/languages/i18n/mk.json @@ -723,6 +723,7 @@ "postedit-confirmation-created": "Страницата е создадена.", "postedit-confirmation-restored": "Страницата е повратена.", "postedit-confirmation-saved": "Вашето уредување е зачувано.", + "postedit-confirmation-published": "Вашето уредување е објавено.", "edit-already-exists": "Не може да се создаде нова страница.\nИстата веќе постои.", "defaultmessagetext": "Текст на пораката по основно", "content-failed-to-parse": "Не успеав да ја предадам содржината од типот $2 за моделот $1: $3", @@ -1654,7 +1655,7 @@ "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", diff --git a/languages/i18n/mwl.json b/languages/i18n/mwl.json index cbaa2e5314..6729c105a3 100644 --- a/languages/i18n/mwl.json +++ b/languages/i18n/mwl.json @@ -698,7 +698,7 @@ "recentchangeslinked-feed": "Altaraçones relacionadas", "recentchangeslinked-toolbox": "Altaraçones relacionadas", "recentchangeslinked-title": "Altaraçones que ténen a ber cun \"$1\"", - "recentchangeslinked-summary": "Esta páigina special amostra las redadeiras altaraçones de páiginas que téngan ua lhigaçon a outra (ó de nembros dua catadorie speceficada).\nLas páiginas que steian ne ls [[Special:Watchlist|tous begiados]] son amostradas an negrito.", + "recentchangeslinked-summary": "Scriba l nome dua páigina pa ber las altaraçones an todas las páiginas que téngan lhigaçones pa eilha ó pa las quales la páigina oufrecida ténen lhigaçones (pa ber ls nembros dua catadorie, scriba Catadorie:Nome de la catadorie). Las mudanças na sue [[Special:Watchlist|lhista de páiginas begiadas]] son amostradas an negro.", "recentchangeslinked-page": "Nome de la páigina:", "recentchangeslinked-to": "Amostrar antes altaraçones a páiginas que téngan a ber cula páigina dada", "upload": "Cargar fexeiro", diff --git a/languages/i18n/nap.json b/languages/i18n/nap.json index 5a330c6624..61e4403b25 100644 --- a/languages/i18n/nap.json +++ b/languages/i18n/nap.json @@ -13,7 +13,8 @@ "Candalua", "Macofe", "V6rg", - "Nemo bis" + "Nemo bis", + "S4b1nuz E.656" ] }, "tog-underline": "Sottolinia 'e jonte:", @@ -3404,7 +3405,7 @@ "feedback-thanks": "Grazie! 'O feedback vuosto s'è mpizzato dint' 'a paggena \"[$2 $1]\".", "feedback-thanks-title": "Ve ringraziammo!", "feedback-useragent": "Aggente utente:", - "searchsuggest-search": "Truova", + "searchsuggest-search": "Truova dint'ô {{SITENAME}}", "searchsuggest-containing": "tène...", "api-error-badtoken": "Errore interno: 'O token nun è buono.", "api-error-emptypage": "'A criazione 'e paggene nuove abbacante nun è permessa.", diff --git a/languages/i18n/nb.json b/languages/i18n/nb.json index d330d90517..e399720612 100644 --- a/languages/i18n/nb.json +++ b/languages/i18n/nb.json @@ -1677,7 +1677,7 @@ "lockmanager-fail-closelock": "Kunne ikke lukke låsefilen for «$1».", "lockmanager-fail-deletelock": "Kunne ikke slette låsefilen for «$1».", "lockmanager-fail-acquirelock": "Kunne ikke skaffe lås for «$1».", - "lockmanager-fail-openlock": "Kunne ikke åpne låsefilen for «$1».", + "lockmanager-fail-openlock": "Kunne ikke åpne låsefilen for «$1». Sjekk at opplastingsmappa er konfigurert riktig og at nettjeneren din har tillatelse til å skrive til den mappa. Se https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:$wgUploadDirectory for mer informasjon.", "lockmanager-fail-releaselock": "Kunne ikke frigi låsen for «$1».", "lockmanager-fail-db-bucket": "Kunne ikke kontakte nok låsedatabaser i bøtten $1.", "lockmanager-fail-db-release": "Kunne ikke frigi låser på databasen $1.", @@ -1868,7 +1868,7 @@ "doubleredirects": "Doble omdirigeringer", "doubleredirectstext": "Denne siden lister opp de sidene som er omdirigeringer til andre omdirigeringssider.\nHver rad inneholder lenker til første og andre omdirigering, samt målet for den andre omdirigeringen, som vanligvis er den «virkelige» målsiden som den første omdirigeringen burde peke til.\nGjennomstrøkne sider har blitt fikset.", "double-redirect-fixed-move": "[[$1]] har blitt flyttet.\nDen ble automatisk oppdatert og er nå en omdirigering til [[$2]].", - "double-redirect-fixed-maintenance": "Fikser automatisk dobbel omdirigering fra [[$1]] til [[$2]] som en del av en vedlikeholdsoppgave.", + "double-redirect-fixed-maintenance": "Fikser automatisk dobbel omdirigering fra [[$1]] til [[$2]] som en del av en vedlikeholdsoppgave", "double-redirect-fixer": "Omdirigeringsfikser", "brokenredirects": "Brutte omdirigeringer", "brokenredirectstext": "Følgende omdirigeringer peker til ikkeeksisterende sider:", diff --git a/languages/i18n/ne.json b/languages/i18n/ne.json index 268ff300a9..c922fa3365 100644 --- a/languages/i18n/ne.json +++ b/languages/i18n/ne.json @@ -1172,7 +1172,7 @@ "action-unwatchedpages": "अवलोकन नगरिएका पृष्ठहरूको सूची हेर्ने", "action-mergehistory": "यस पृष्ठको इतिहासलाई मिसाउने", "action-userrights": "सबै प्रयोगकर्ताका अधिकारहरू सम्पादन गर्ने", - "action-userrights-interwiki": "अरु विकिका प्रयोगकर्ताहरूको प्रयोगकर्ता अधिकारलाई सम्पादन गर्ने", + "action-userrights-interwiki": "अरू विकीका प्रयोगकर्ताहरूको प्रयोगकर्ता अधिकारलाई सम्पादन गर्ने", "action-siteadmin": "डेटाबेस बन्दगर्ने वा खोल्ने", "action-sendemail": "इमेलहरु पठाउने", "action-editmywatchlist": "तपाईंको निगरानी सूची सम्पादन गर्नुहोस्", @@ -1188,7 +1188,7 @@ "enhancedrc-history": "इतिहास", "recentchanges": "नयाँ परिवर्तनहरू", "recentchanges-legend": "हालैको परिवर्तन विकल्पहरू", - "recentchanges-summary": "विकिका भर्खरका परिवर्तनहरूलाई यस पृष्ठमा पहिल्याउने", + "recentchanges-summary": "विकीका भर्खरका परिवर्तनहरूलाई यस पृष्ठमा हेर्न सकिन्छ", "recentchanges-noresult": "दिइएको मापदण्ड अवधिमा मिल्दो कुनै परिवर्तन छैन।", "recentchanges-feed-description": "यो फिडमा रहेको विकीको सवैभन्दा अन्तिम परिवर्तनहरुको जानकारी राख्नुहोस्", "recentchanges-label-newpage": "यो सम्पादनले नयाँ पृष्ठ निर्माण गरेको छ", @@ -1534,7 +1534,7 @@ "statistics-header-hooks": "अन्य तथ्याङ्कहरू", "statistics-articles": "सामग्री पृष्ठहरू", "statistics-pages": "पृष्ठहरू", - "statistics-pages-desc": "विकिका सबै पृष्ठहरू, वार्तापका पृष्ठहरूसमेत, रिडाइरेक्ट, इत्यादि ।", + "statistics-pages-desc": "विकीका सबै पृष्ठहरू, वार्तापका पृष्ठहरूसमेत, रिडाइरेक्ट, इत्यादि।", "statistics-files": "उर्ध्वभरण गरिएका फाइलहरू", "statistics-edits": "{{SITENAME}} स्थापना भए देखिको पृष्ठ सम्पादन", "statistics-edits-average": "प्रतिपृष्ठ औसत सम्पादन", diff --git a/languages/i18n/nl.json b/languages/i18n/nl.json index 5e983bd0cd..8fa9c61981 100644 --- a/languages/i18n/nl.json +++ b/languages/i18n/nl.json @@ -785,6 +785,7 @@ "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.", @@ -1714,7 +1715,7 @@ "lockmanager-fail-closelock": "Het was niet mogelijk het vergrendelingsbestand voor \"$1\" te sluiten.", "lockmanager-fail-deletelock": "Het was niet mogelijk het vergrendelingsbestand voor \"$1\" te verwijderen.", "lockmanager-fail-acquirelock": "Het was niet mogelijk \"$1\" te vergrendelen.", - "lockmanager-fail-openlock": "Het was niet mogelijk het vergrendelingsbestand voor \"$1\" te openen.", + "lockmanager-fail-openlock": "Het was niet mogelijk het vergrendelingsbestand voor \"$1\" te openen. Verzeker uzelf ervan dat de uploadmap goed ingesteld is en uw webserver toestemming heeft om naar die map the schrijven. Zie https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:$wgUploadDirectory voor meer informatie.", "lockmanager-fail-releaselock": "Het was niet mogelijk vergrendeling van \"$1\" op te heffen.", "lockmanager-fail-db-bucket": "Het was niet mogelijk om in contact te komen met voldoende vergrendelingsdatabases in de bucket $1.", "lockmanager-fail-db-release": "Het was niet mogelijk om de vergrendeling voor de database $1 op te heffen.", @@ -3171,11 +3172,14 @@ "exif-compression-2": "CCITT Groep 3 1-dimensionale aangepaste \"Huffman run length\"-codering", "exif-compression-3": "CCITT Groep 3 faxcodering", "exif-compression-4": "CCITT Groep 4 faxcodering", + "exif-compression-6": "JPEG (oud)", "exif-copyrighted-true": "Auteursrechtelijk beschermd", "exif-copyrighted-false": "Auteursrechtelijke status niet ingesteld", "exif-photometricinterpretation-0": "Zwart en wit (Wit is 0)", "exif-photometricinterpretation-1": "Zwart-wit (zwart is 0)", "exif-photometricinterpretation-3": "Palet", + "exif-photometricinterpretation-4": "Transparantiemasker", + "exif-photometricinterpretation-5": "Gescheiden (waarschijnlijk CMYK)", "exif-unknowndate": "Datum onbekend", "exif-orientation-1": "Normaal", "exif-orientation-2": "Horizontaal gespiegeld", @@ -4052,6 +4056,8 @@ "restrictionsfield-badip": "Ongeldig IP-adres of range: $1", "restrictionsfield-label": "Toegestane IP-ranges:", "restrictionsfield-help": "Een IP-adres of CIDR bereik per lijn. Om alles toe te staan, gebruik:
0.0.0.0/0\n::/0
", + "edit-error-short": "Fout: $1", + "edit-error-long": "Fouten:\n\n$1", "revid": "versie $1", "pageid": "Pagina-ID $1", "rawhtml-notallowed": "<html> tags kunnen alleen op normale pagina's geplaatst worden.", diff --git a/languages/i18n/nn.json b/languages/i18n/nn.json index d4a3aa58c9..bf46ac3ea8 100644 --- a/languages/i18n/nn.json +++ b/languages/i18n/nn.json @@ -692,6 +692,7 @@ "undo-success": "Endringa kan angrast.\nSjå på samanlikninga under for å stadfesta at dette er det du ynskjer å gjera. Deretter kan du lagra desse endringane for å fullføra angringa.", "undo-failure": "Endringa kunne ikkje attenderullast grunna konflikt med endringar som er gjorde i mellomtida.", "undo-norev": "Endringa kunne ikkje fjernast fordi han ikkje finst eller vart sletta", + "undo-nochange": "Det ser ut til at endringa alt er fjerna.", "undo-summary": "Rullar attende versjon $1 av [[Special:Contributions/$2|$2]] ([[User talk:$2|diskusjon]])", "cantcreateaccount-text": "Kontooppretting frå denne IP-adressa ('''$1''') er blokkert av [[User:$3|$3]].\n\nGrunnen som vart gjeven av $3 er ''$2''", "viewpagelogs": "Vis loggane for sida", @@ -1848,7 +1849,7 @@ "exbeforeblank": "innhaldet før sida vart tømd var: «$1»", "delete-confirm": "Slett «$1»", "delete-legend": "Slett", - "historywarning": "Åtvaring: Sida du held på å slette har ein historikk med $1 {{PLURAL:$1|versjon|versjonar}}:", + "historywarning": "Åtvaring: Sida du held på å slette har ein historikk med $1 {{PLURAL:$1|versjon|versjonar}}:", "historyaction-submit": "Vis", "confirmdeletetext": "Du held på å varig slette ei side eller eit bilete saman med heile den tilhøyrande historikken frå databasen. Stadfest at du verkeleg vil gjere dette, at du skjønar konsekvensane, og at du gjer dette i tråd med [[{{MediaWiki:Policy-url}}|retningslinene]].", "actioncomplete": "Ferdig", diff --git a/languages/i18n/pt-br.json b/languages/i18n/pt-br.json index 1bf0c8ebfa..3820aa88d6 100644 --- a/languages/i18n/pt-br.json +++ b/languages/i18n/pt-br.json @@ -813,6 +813,7 @@ "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", @@ -1742,7 +1743,7 @@ "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 obter uma referência de bloqueio para \"$1\".", - "lockmanager-fail-openlock": "Não foi possível abrir a referência de bloqueio para \"$1\".", + "lockmanager-fail-openlock": "Não foi possível abrir a referência de bloqueio para \"$1\". Certifique-se de que seu diretório de upload esteja configurado corretamente e seu servidor web tenha permissão para gravar nesse diretório. Veja https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:$wgUploadDirectory para maiores informações.", "lockmanager-fail-releaselock": "Não foi possível liberar o bloqueio para \"$1\".", "lockmanager-fail-db-bucket": "Não foi possível contatar suficientemente bloqueio das bases de dados no bucket $1 .", "lockmanager-fail-db-release": "Não foi possível liberar os bloqueios para \"$1\".", diff --git a/languages/i18n/pt.json b/languages/i18n/pt.json index a4e13c659d..15d950f91a 100644 --- a/languages/i18n/pt.json +++ b/languages/i18n/pt.json @@ -545,7 +545,7 @@ "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}}", @@ -730,8 +730,8 @@ "previewnote": "Lembre-se de que esta é apenas uma antevisão do resultado.\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. 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.", - "session_fail_preview_html": "Desculpe! Não foi possível processar a edição devido à perda de dados da sua sessão.\n\nComo a wiki {{SITENAME}} possibilita o uso de HTML puro, a antevisão está oculta por precaução contra ataques com JavaScript.\n\nSe esta é uma tentativa legítima de edição 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.", + "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. 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.", + "session_fail_preview_html": "Desculpe! Não foi possível processar a edição devido à perda de dados da sua sessão.\n\nComo a wiki {{SITENAME}} possibilita o uso de HTML puro, a antevisão está oculta por precaução contra ataques com JavaScript.\n\nSe esta é uma tentativa legítima de edição 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.", "token_suffix_mismatch": "A edição foi rejeitada porque o seu navegador alterou os sinais de pontuação no editor.\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": "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.", "editing": "A editar $1", @@ -781,6 +781,7 @@ "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", @@ -1015,7 +1016,7 @@ "showingresultsinrange": "Apresenta-se abaixo {{PLURAL:$1|1 resultado|até $1 resultados}} no intervalo #$2 a #$3.", "search-showingresults": "{{PLURAL:$4|Resultado $1 de $3|Resultados $1 - $2 de $3}}", "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:", @@ -1094,7 +1095,7 @@ "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)}}:", @@ -1716,7 +1717,7 @@ "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.", @@ -1773,9 +1774,9 @@ "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", @@ -2006,7 +2007,7 @@ "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 API operacional do MediaWiki.\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.", @@ -2055,9 +2056,9 @@ "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):", @@ -2724,7 +2725,7 @@ "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.", @@ -2831,7 +2832,7 @@ "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 spam: $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", @@ -3345,8 +3346,8 @@ "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]", @@ -3631,7 +3632,7 @@ "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)", @@ -3809,7 +3810,7 @@ "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": "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.\n\nSe esta é uma tentativa legítima de visionamento, por favor tente novamente.\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": "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.\n\nSe esta é uma tentativa legítima de visionamento, por favor tente novamente.\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": "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.\n\nSe esta é uma tentativa legítima de visionamento, por favor [[Special:UserLogin|inicie uma sessão]] e tente novamente.", "expand_templates_input_missing": "Necessita de fornecer pelo menos algum texto wiki de entrada.", "pagelanguage": "Alterar a língua da página", @@ -4037,7 +4038,7 @@ "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", diff --git a/languages/i18n/qqq.json b/languages/i18n/qqq.json index e29bcad8bc..a4f1d64592 100644 --- a/languages/i18n/qqq.json +++ b/languages/i18n/qqq.json @@ -940,6 +940,7 @@ "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}}", diff --git a/languages/i18n/ru.json b/languages/i18n/ru.json index 4f48b67a84..d7c8990957 100644 --- a/languages/i18n/ru.json +++ b/languages/i18n/ru.json @@ -119,7 +119,8 @@ "Helpau", "Staspotanin2", "Edible Melon", - "Adam-Yourist" + "Adam-Yourist", + "MaksimPinigin" ] }, "tog-underline": "Подчёркивание ссылок:", @@ -127,7 +128,7 @@ "tog-hidepatrolled": "Скрывать патрулированные правки в списке свежих правок", "tog-newpageshidepatrolled": "Скрывать отпатрулированные страницы в списке новых страниц", "tog-hidecategorization": "Скрывать категоризацию страниц", - "tog-extendwatchlist": "Расширить список наблюдения, включающая все изменения, а не только последние (они могут быть сгруппированы настройкой на вкладке «[[Служебная:Настройки#mw-prefsection-rc|Свежие правки]]»)", + "tog-extendwatchlist": "Расширить список наблюдения, включая все изменения, а не только последние (они могут быть сгруппированы настройкой на вкладке «[[Служебная:Настройки#mw-prefsection-rc|Свежие правки]]»)", "tog-usenewrc": "Группировать изменения в свежих правках и списке наблюдения", "tog-numberheadings": "Автоматически нумеровать заголовки", "tog-showtoolbar": "Показывать панель инструментов при редактировании", @@ -821,6 +822,7 @@ "postedit-confirmation-created": "Страница создана.", "postedit-confirmation-restored": "Страница была восстановлена.", "postedit-confirmation-saved": "Ваша правка сохранена.", + "postedit-confirmation-published": "Ваша правка была опубликована.", "edit-already-exists": "Невозможно создать новую страницу.\nОна уже существует.", "defaultmessagetext": "Текст по умолчанию", "content-failed-to-parse": "Содержимое $2 не соответствует типу $1: $3.", @@ -1752,7 +1754,7 @@ "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 .", @@ -4179,7 +4181,7 @@ "restrictionsfield-label": "Разрешённые диапазоны IP-адресов:", "restrictionsfield-help": "По одному IP-адресу или CIDR-диапазону в строке. Чтобы разрешить всё, используйте:
0.0.0.0/0\n::/0
", "edit-error-short": "Ошибка: $1", - "edit-error-long": "Ошибки: $1", + "edit-error-long": "Ошибки:\n\n$1", "revid": "версия $1", "pageid": "ID страницы $1", "rawhtml-notallowed": "<html> теги могут быть использованы только в пределах обычных страниц.", diff --git a/languages/i18n/sah.json b/languages/i18n/sah.json index cc5fb1c771..55494e24b8 100644 --- a/languages/i18n/sah.json +++ b/languages/i18n/sah.json @@ -711,6 +711,7 @@ "postedit-confirmation-created": "Сирэй оҥоһулунна.", "postedit-confirmation-restored": "Сирэй сөргүтүлүннэ.", "postedit-confirmation-saved": "Көннөрүүҥ бигэргэннэ.", + "postedit-confirmation-published": "Уларытыыҥ олоххо киирдэ.", "edit-already-exists": "Саҥа сирэйи оҥорор табыллыбат.\nМаннык сирэй баар эбит.", "defaultmessagetext": "Туспа этиллибэтэҕинэ суруллар тиэкис", "content-failed-to-parse": "$2 иһинээҕитэ $1 көрүҥэр сөп түбэспэт: $3.", @@ -1380,7 +1381,9 @@ "rcfilters-filter-watchlist-notwatched-description": "Кэтэбил тиһилигэр киирбит ыстатыйалары уларытыыттан уратыны барытын.", "rcfilters-filtergroup-watchlistactivity": "Кэтэбил тиһилигин көҕө", "rcfilters-filter-watchlistactivity-unseen-label": "Көрүллэ илик уларытыылар", + "rcfilters-filter-watchlistactivity-unseen-description": "Тиһэх киирииҥ кэнниттэн оҥоһуллубут уларытыылар.", "rcfilters-filter-watchlistactivity-seen-label": "Көрүллүбүт уларытыылар", + "rcfilters-filter-watchlistactivity-seen-description": "Тиһэх киирииҥ иннинэ оҥоһуллубут уларытыылар.", "rcfilters-filtergroup-changetype": "Уларытыы көрүҥэ", "rcfilters-filter-pageedits-label": "Сирэй уларытыылара", "rcfilters-filter-pageedits-description": "Ис хоһоонун, ырытыылары, категорияны ойуулааһыны эҥин уларытыы...", @@ -2099,7 +2102,7 @@ "emailccsubject": "Эн суругуҥ куоппуйата $1: $2", "emailsent": "Сурук барда", "emailsenttext": "Эн суругуҥ ыытылынна.", - "emailuserfooter": "Бу сурук {{GENDER:$2|$2}} кыттааччыга {{GENDER:$1|$1}} кыттааччыттан «Сурукта ыыт» (\"{{int:emailuser}}\") диэн тэрил көмөтүнэн {{SITENAME}} ситим-сиртэн ыытыллыбыт. {{GENDER:$2|Эн}} электрон аадырыһыҥ ыыппыт {{GENDER:$1|киһигэр}} көстүөҕэ.", + "emailuserfooter": "Бу сурук {{GENDER:$2|$2}} кыттааччыга {{GENDER:$1|$1}} кыттааччыттан «Сурукта ыыт» (\"{{int:emailuser}}\") диэн тэрил көмөтүнэн {{SITENAME}} ситим-сиртэн ыытыллыбыт. Өскөтө {{GENDER:$2|Эн}} киниэхэ суруйдаххына, электрон аадырыһыҥ {{GENDER:$1|киһигэр}} көстүөҕэ.", "usermessage-summary": "Тиһилик биллэриитин хааллар.", "usermessage-editor": "Тиһилик биллэрээччитэ", "watchlist": "Кэтэбилим тиһигэ", @@ -2153,7 +2156,7 @@ "enotif_body_intro_moved": "$PAGEEDITDATE «{{SITENAME}}» бырайыак «$1» ааттаах сирэйин бу {{gender:$2|кыттааччы|кыттааччы}} аатын уларыппыт - $2, билиҥҥи барылын манна көр: $3", "enotif_body_intro_restored": "$PAGEEDITDATE «{{SITENAME}}» бырайыак «$1» ааттаах сирэйин бу {{gender:$2|кыттааччы|кыттааччы}} соппут - $2, билиҥҥи барылын манна көр: $3", "enotif_body_intro_changed": "$PAGEEDITDATE «{{SITENAME}}» бырайыак «$1» ааттаах сирэйин бу {{gender:$2|кыттааччы|кыттааччы}} айбыт - $2, билиҥҥи барылын манна көр: $3", - "enotif_lastvisited": "Бутэһик киирииҥ кэнниттэн оҥоһуллубут уларыйыылары барытын көрөргө манна киир: $1.", + "enotif_lastvisited": "Бүтэһик киирииҥ кэнниттэн оҥоһуллубут уларыйыылары барытын көрөргө манна киир: $1.", "enotif_lastdiff": "Уларытыыны манна көр: $1", "enotif_anon_editor": "ааттамматах кыттааччы $1", "enotif_body": "Аламай күн сырдыгынан, $WATCHINGUSERNAME!\n\n$PAGEINTRO $NEWPAGE\n\nУларытыы кылгас ис хоһооно: $PAGESUMMARY $PAGEMINOREDIT\n\nУларыппыт киһиэхэ суруйуоххун сөп:\nэл. почта: $PAGEEDITOR_EMAIL\nбиики: $PAGEEDITOR_WIKI\n\nБу сирэйи бэлиэтэммит ааккынан киирэн көрбөтөххүнэ уларыйбытын туһунан биллэриилэр кэлиэхтэрэ суоҕа. Биллэриилэри аналлаах сирэйгэ отой арааран кэбиһиэххин эмиэ сөп.\n\n Бары үтүөнү кытта, {{SITENAME}} биллэрэр тиһигэ\n\n--\nБиллэрии кэлэрин салайыы\n{{canonicalurl:{{#special:Preferences}}}}\n\nКэтиир тиһиги уларытыы\n{{canonicalurl:{{#special:EditWatchlist}}}}\n\nКэтиир тиһиктэн сирэйдэри сотуу\n$UNWATCHURL\n\nКөмө\n$HELPPAGE", @@ -2216,7 +2219,7 @@ "changecontentmodel-emptymodels-title": "Ис хоһоононун холобура суох", "changecontentmodel-emptymodels-text": "[[:$1]] иһинээҕитэ ханнык да атын көрүҥҥэ уларыйар кыаҕа суох эбит.", "log-name-contentmodel": "Иһинээҕитин киэбин уларытыы сурунаала", - "log-description-contentmodel": "Сирэй иһинээҕитин киэбин кытта ситимнээх", + "log-description-contentmodel": "Манна сирэй иһинээҕитин киэбин уларыйыытын кытта ситимнээх уларытыылар көстөллөр.", "logentry-contentmodel-new": "$1 $3 диэн сирэйи маны туһанан «$5» {{GENDER:$2|айбыт}}", "logentry-contentmodel-change": "$1 кыттааччы $3 сирэй иһинээҕитин мадьыалын мантан «$4» манна «$5» {{GENDER:$2|уларыппыт}}", "logentry-contentmodel-change-revertlink": "төннөрүү", @@ -2546,7 +2549,7 @@ "delete_and_move_text": "==Сотуохха наада==\n\nМаннык ааттаах сирэй [[:$1|«$1»]] бэлиэр баар. Эн ону суох гынан баран аатын уларытаары гынаҕын дуо?", "delete_and_move_confirm": "Сөп, бу сирэйи суох гын", "delete_and_move_reason": "Аатын уларытаары сотулунна \"[[$1]]\"", - "selfmove": "Аатын уларытар сатаммат. Эргэ уонна саҥа аата биирдэр.", + "selfmove": "Аатын уларытар сатаммата; \nэргэ уонна саҥа аата биирдэр.", "immobile-source-namespace": "\"$1\" аат далыгар баар сирэйдэр ааттарын уларытар кыах суох.", "immobile-target-namespace": "\"$1\" аат далыгар сирэйи көһөрөр кыах суох", "immobile-target-namespace-iw": "Интервики сигэтэ ааты уларытыыга туһаныллыбат.", @@ -2644,7 +2647,7 @@ "import-nonewrevisions": "Биир да уларытыы импортаммата (бу иннинэ таҥастаммыттар, биитэр алҕастаах буолан көтүтүллүбүттэр).", "xml-error-string": "$1 - $2 строка, $3 колонка ($4 байт): $5", "import-upload": "XML-дааннайдары киллэр", - "import-token-mismatch": "Арахсан хаалбыт. \n\nБаҕар тахсан хаалбытыҥ буолуо. Бэлиэтэммит ааккынан киирэн олороргун тургутан баран хатылаан көр..\nӨскөтө син биир көмөлөспөтөҕүнэ [[Special:UserLogout|тахсан баран]] төттөрү киирэн көр уонна браузерыҥ куукалары ыларын тургут.", + "import-token-mismatch": "Арахсан хаалбыт. \n\nБаҕар тахсан хаалбытыҥ буолуо. Бэлиэтэммит ааккынан киирэн олороргун тургутан баран хатылаан көр..\nӨскөтө син биир сатамматаҕына [[Special:UserLogout|тахсан баран]] төттөрү киирэн көр уонна браузерыҥ кууканы ыларын тургут.", "import-invalid-interwiki": "Бу биикиттэн импорт оҥорор сатаммат(а).", "import-error-edit": "«$1» сирэй көһөрүллүбэтэ, тоҕо диэтэххэ кинини уларытарыҥ көҥүллэммэт эбит.", "import-error-create": "«$1» сирэй киллэриллибэтэ, тоҕо диэтэххэ кинини айарыҥ сатаммат эбит.", @@ -3302,8 +3305,8 @@ "autosumm-blank": "Бу сирэй ыраастаныллыбыт", "autosumm-replace": "Сирэй иһэ уларытыллыбыт: '$1'", "autoredircomment": "Утаарыы: [[$1]]", - "autosumm-removed-redirect": "Сотуллубут утаарыы: $1", - "autosumm-changed-redirect-target": "Утаарыы мантан $1 манна $2 уларыйда", + "autosumm-removed-redirect": "Сотуллубут утаарыы: [[$1]]", + "autosumm-changed-redirect-target": "Утаарыы мантан [[$1]] манна [[$2]] уларыйда", "autosumm-new": "'$1' ыйааһыннаах саҥа сирэй оҥоһулунна", "autosumm-newblank": "Кураанах сирэй оҥоһулунна", "size-bytes": "$1 байт", @@ -3372,7 +3375,7 @@ "version-poweredby-others": "атыттар", "version-poweredby-translators": "translatewiki.net тылбаасчыттара", "version-credits-summary": "[[Special:Version|MediaWiki]] сайдыытыгар үлэлэрин иһин манна ахтыллыбыт дьоҥҥо махтанабыт.", - "version-license-info": "MediaWiki көҥүл тарҕанар бырагырааммаларга киирэр, кинини көмпүүтэр аһаҕас бырагырааммаларын пуондатын GNU General Public License усулуобуйатынан көҥүл тарҕатаргыт уонна/эбэтэр уларытаргыт көҥүллэнэр; иккис эбэтэр онтон хойукку ханнык баҕарар барылыттан саҕалаан.\n\nMediaWiki туһалаах буоллун диэн тарҕатыллар, ол эрээри АТЫЫЛАНАР СЫАННАҺА эбэтэр ХАННЫК ЭРЭ ЧОПЧУ СОРУККА СӨП ТҮБЭҺИИТЭ бигэргэтиллибэт (гарантията суох). Сиһилии GNU General Public License усулуобуйатын көрүҥ.\n\n[{{SERVER}}{{SCRIPTPATH}}/COPYING GNU General Public License копиятын] бу бырагыраамманы кытта ылыахтаах этигит, ол сатамматах буоллаҕына Free Software Foundation, Inc. тэрилтэҕэ сурукта суруйуҥ, бу аадырыска: 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA эбэтэр [//www.gnu.org/licenses/old-licenses/gpl-2.0.html саайка киирэн ааҕыҥ].", + "version-license-info": "MediaWiki көҥүл тарҕанар бырагыраама. Онон GNU General Public License (иккис эбэтэр онтон хойукку ханнык баҕарар барылыттан саҕалаан) усулуобуйатынан көҥүл тарҕатар уонна/эбэтэр уларытар көҥүллэнэр.\n\nMediaWiki туһалаах буоллун диэн тарҕатыллар, ол эрээри АТЫЫЛАНАР СЫАННАҺА эбэтэр ХАННЫК ЭРЭ ЧОПЧУ СОРУККА СӨП ТҮБЭҺИИТЭ бигэргэтиллибэт (гарантията суох). Сиһилии GNU General Public License усулуобуйатын көр.\n\n[{{SERVER}}{{SCRIPTPATH}}/COPYING GNU General Public License куопуйатын] бу бырагырааманы кытта ылыахтаах этиҥ, ол сатамматах буоллаҕына Free Software Foundation, Inc. тэрилтэҕэ сурукта суруй, бу аадырыска: 51 Franklin Street, 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": "Барыл (торум)", diff --git a/languages/i18n/sd.json b/languages/i18n/sd.json index 31abcc07f7..7bd0919c22 100644 --- a/languages/i18n/sd.json +++ b/languages/i18n/sd.json @@ -691,6 +691,7 @@ "search-showingresults": "{{PLURAL:$4|نتيجو $1 of $3|نتيجا $1 - $2 of $3}}", "search-nonefound": "توھان جي ڳولا جي نتيجي ۾ ڪجھہ بہ نہ لڌو.", "powersearch-legend": "اعليٰ ڳولا", + "powersearch-ns": "نالن لاءِ ڇڏين وڇوٽين ۾ ڳولھيو (سرچ اِن نيم اسپيسز)", "powersearch-togglelabel": "چڪاسيو:", "powersearch-toggleall": "سڀ", "powersearch-togglenone": "ڪو بہ نہ", @@ -1201,7 +1202,7 @@ "nrevisions": "$1 {{PLURAL:$1|مسودو|مسودا}}", "nimagelinks": "$1 {{PLURAL:$1|صفحي|صفحن}} ۾ استعمال ٿيل", "ntransclusions": "$1 {{PLURAL:$1|صفحي|صفحن}} ۾ استعمال ٿيل", - "specialpage-empty": "ھن رپورٽ لاءِ ڪي-بہ نتيجا ناھن.", + "specialpage-empty": "ھن رپورٽ لاءِ ڪي بہ نتيجا ناھن.", "lonelypages": "يتيم صفحا", "uncategorizedpages": "اڻ زمريل صفحا", "uncategorizedcategories": "اڻزمرايل زمرا", @@ -1416,7 +1417,7 @@ "restriction-level-sysop": "مڪمل طور تحفظيل", "restriction-level-autoconfirmed": "نيم تحفظيل", "viewdeletedpage": "ڊاٺل صفحا ڏسو", - "undelete-nodiff": "ڪوبہ پويون مسودو نہ لڌو", + "undelete-nodiff": "ڪوبہ اڳيون مسودو نہ لڌو", "undeletebtn": "بحاليو", "undeleteviewlink": "ڏسو", "undeletecomment": "سبب:", @@ -1838,6 +1839,7 @@ "version-libraries-description": "تشريح", "version-libraries-authors": "ليکڪ", "redirect-submit": "ھلو", + "redirect-lookup": "ڏسو:", "redirect-value": "قدر:", "redirect-user": "واپرائيندڙ آءِڊي", "redirect-page": "صفحي جي آءِڊي", diff --git a/languages/i18n/sl.json b/languages/i18n/sl.json index 05a1229a97..2fd189248f 100644 --- a/languages/i18n/sl.json +++ b/languages/i18n/sl.json @@ -712,6 +712,7 @@ "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", @@ -1641,7 +1642,7 @@ "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.", diff --git a/languages/i18n/sr-ec.json b/languages/i18n/sr-ec.json index d312b8a9a3..f1e57fa2e7 100644 --- a/languages/i18n/sr-ec.json +++ b/languages/i18n/sr-ec.json @@ -40,8 +40,8 @@ ] }, "tog-underline": "Подвлачење веза:", - "tog-hideminor": "Сакриј мање измене у списку скорашњих измена", - "tog-hidepatrolled": "Сакриј патролиране измене у списку скорашњих измена", + "tog-hideminor": "Сакриј мање измене са списка скорашњих измена", + "tog-hidepatrolled": "Сакриј патролиране измене са списка скорашњих измена", "tog-newpageshidepatrolled": "Сакриј патролиране странице са списка нових страница", "tog-hidecategorization": "Сакриј категоризацију страница", "tog-extendwatchlist": "Прошири списак надгледања за приказ свих измена, не само скорашњих", @@ -50,41 +50,41 @@ "tog-showtoolbar": "Прикажи траку с алаткама за уређивање", "tog-editondblclick": "Уређивање страница двоструким кликом", "tog-editsectiononrightclick": "Уређивање одељака десним кликом на њихове наслове", - "tog-watchcreations": "Додај странице које направим и датотеке које пошаљем у списак надгледања", - "tog-watchdefault": "Додај странице и датотеке које изменим у списак надгледања", - "tog-watchmoves": "Додај странице и датотеке које преместим у списак надгледања", - "tog-watchdeletion": "Додај странице и датотеке које обришем у списак надгледања", - "tog-watchuploads": "Додај датотеке које отпремим у списак надгледања", - "tog-watchrollback": "Додај странице на којима сам вратио измене у списак надгледања", + "tog-watchcreations": "Додај странице које направим и датотеке које пошаљем у мој списак надгледања", + "tog-watchdefault": "Додај странице и датотеке које изменим у мој списак надгледања", + "tog-watchmoves": "Додај странице и датотеке које преместим у мој списак надгледања", + "tog-watchdeletion": "Додај странице и датотеке које обришем у мој списак надгледања", + "tog-watchuploads": "Додај датотеке које отпремим у мој списак надгледања", + "tog-watchrollback": "Додај странице на којима сам вратио измене у мој списак надгледања", "tog-minordefault": "Означавај све измене као мање", - "tog-previewontop": "Прикажи преглед пре оквира за уређивање", + "tog-previewontop": "Прикажи претпреглед пре оквира за уређивање", "tog-previewonfirst": "Прикажи преглед на првој измени", - "tog-enotifwatchlistpages": "Пошаљи ми имејл када се промени страница/датотека коју надгледам", - "tog-enotifusertalkpages": "Пошаљи ми имејл када се промени моја страница за разговор", + "tog-enotifwatchlistpages": "Пошаљи ми имејл када се страница или датотека коју надгледам измени", + "tog-enotifusertalkpages": "Пошаљи ми имејл када се моја страница за разговор измени", "tog-enotifminoredits": "Пошаљи ми имејл и за мање измене у страницама и датотекама", "tog-enotifrevealaddr": "Прикажи моју имејл адресу у порукама обавештења", "tog-shownumberswatching": "Прикажи број корисника који надгледају", - "tog-oldsig": "Текући потпис:", + "tog-oldsig": "Ваш тренутни потпис:", "tog-fancysig": "Сматрај потпис као викитекст (без самоповезивања)", - "tog-uselivepreview": "Прикажи преглед без освежавања стране", + "tog-uselivepreview": "Прикажи претпреглед без освежавања стране", "tog-forceeditsummary": "Упозори ме када не унесем опис измене", "tog-watchlisthideown": "Сакриј моје измене са списка надгледања", "tog-watchlisthidebots": "Сакриј измене ботова са списка надгледања", "tog-watchlisthideminor": "Сакриј мање измене са списка надгледања", "tog-watchlisthideliu": "Сакриј измене пријављених корисника са списка надгледања", "tog-watchlistreloadautomatically": "Аутоматски освежи списак надгледања кад год се филтер измени (потребан JavaScript)", - "tog-watchlistunwatchlinks": "Додај дугме за укључење/искључење надгледања свакој страни на списку надгледања (потребан Јаваскрипт за ефекат укључи/искључи)", + "tog-watchlistunwatchlinks": "Додај везе за директно додавање/уклањање ставки са списка надгледања (потребан ЈаваСкрипт)", "tog-watchlisthideanons": "Сакриј измене анонимних корисника са списка надгледања", "tog-watchlisthidepatrolled": "Сакриј патролиране измене са списка надгледања", "tog-watchlisthidecategorization": "Сакриј категоризацију страница", "tog-ccmeonemails": "Пошаљи ми копије имејлова које пошаљем другим корисницима", "tog-diffonly": "Не приказуј садржај странице испод разлика", - "tog-showhiddencats": "Скривене категорије", + "tog-showhiddencats": "Прикажи скривене категорије", "tog-norollbackdiff": "Не приказуј разлику након извршеног враћања", - "tog-useeditwarning": "Упозори ме када напуштам страницу са несачуваним променама", + "tog-useeditwarning": "Упозори ме када напуштам страницу са несачуваним изменама", "tog-prefershttps": "Увек користи сигурну конекцију када сам пријављен.", - "underline-always": "Увек подвлачи", - "underline-never": "Никад не подвлачи", + "underline-always": "Увек", + "underline-never": "Никад", "underline-default": "Према теми или прегледачу", "editfont-style": "Изглед фонта у уређивачком оквиру:", "editfont-monospace": "Сразмерно широк фонт", @@ -169,14 +169,14 @@ "category-file-count-limited": "{{PLURAL:$1|1=Следећа датотека је|Следеће $1 датотеке су|Следећих $1 датотека је}} у овој категорији.", "listingcontinuesabbrev": "наст.", "index-category": "Пописане странице", - "noindex-category": "Неиндексиране странице", + "noindex-category": "Непописане странице", "broken-file-category": "Странице с неисправним везама до датотека", "about": "О нама", "article": "Страница са садржајем", "newwindow": "(отвара се у новом прозору)", "cancel": "Откажи", "moredotdotdot": "Више…", - "morenotlisted": "Овај списак није комплетан.", + "morenotlisted": "Овај списак можда није потпун.", "mypage": "Страница", "mytalk": "Разговор", "anontalk": "Разговор", @@ -189,9 +189,9 @@ "navigation-heading": "Навигациони мени", "errorpagetitle": "Грешка", "returnto": "Назад на $1.", - "tagline": "Извор: {{SITENAME}}", + "tagline": "Из {{SITENAME}}", "help": "Помоћ", - "search": "Претрага", + "search": "Претражи", "searchbutton": "Претражи", "go": "Иди", "searcharticle": "Иди", @@ -221,14 +221,14 @@ "talk": "Разговор", "views": "Прегледи", "toolbox": "Алатке", - "tool-link-userrights": "Уреди {{GENDER:$1|корисничке}} групе", - "tool-link-userrights-readonly": "{{GENDER:$1|Корисничке}} групе", - "tool-link-emailuser": "Пошаљи {{GENDER:$1|имејл}}", + "tool-link-userrights": "Промени {{GENDER:$1|корисничке}} групе", + "tool-link-userrights-readonly": "Погледај {{GENDER:$1|корисничке}} групе", + "tool-link-emailuser": "Пошаљи имејл {{GENDER:$1|кориснику|корисници}}", "imagepage": "Погледај страницу датотеке", "mediawikipage": "Погледај страницу поруке", "templatepage": "Погледај страницу шаблона", "viewhelppage": "Погледај страницу помоћи", - "categorypage": "Погледај страницу категорија", + "categorypage": "Погледај страницу категорије", "viewtalkpage": "Погледај разговор", "otherlanguages": "На другим језицима", "redirectedfrom": "(преусмерено са $1)", @@ -245,7 +245,7 @@ "pool-timeout": "Истек времена чека на закључавање", "pool-queuefull": "Ред је пун захтева", "pool-errorunknown": "Непозната грешка", - "pool-servererror": "Услуга бројача пула није доступна ($1).", + "pool-servererror": "Услуга бројача редова није доступна ($1).", "poolcounter-usage-error": "Грешка при употреби: $1", "aboutsite": "О пројекту {{SITENAME}}", "aboutpage": "Project:О нама", @@ -362,7 +362,7 @@ "title-invalid-utf8": "Тражени назив странице садржи неважећи UTF-8 знак.", "title-invalid-interwiki": "Тражени наслов странице садржи унутрашњу вики везу која не може бити кориштена у насловима.", "title-invalid-talk-namespace": "Тражени наслов странице се односи на страницу за разговор која не може постојати.", - "title-invalid-characters": "Тражени наслов има неважеће карактере: „$1“.", + "title-invalid-characters": "Тражени наслов има неважеће знакове: „$1“.", "title-invalid-relative": "Наслов има релативну путању. Релативни наслови страница (./, ../) нису важећи јер ће често бити недоступни у корисничком прегледачу.", "title-invalid-magic-tilde": "Тражени наслов странице садржи неважећи след магичног знака тилда (~~~).", "title-invalid-too-long": "Тражени назив странице је предугачак. Не сме бити дужи од $1 {{PLURAL:$1|бајта|бајтова}} у UTF-8 кодирању.", @@ -376,14 +376,14 @@ "actionthrottledtext": "У циљу борбе против непожељних порука, ограничене су вам измене у одређеном времену, а управо сте прешли то ограничење. Покушајте поново за неколико минута.", "protectedpagetext": "Ова страница је закључана за измене и друге радње.", "viewsourcetext": "Можете читати и копирати изворник ове странице.", - "viewyourtext": "Можете да погледате и копирате изворни текст ваших измена на овој страници.", + "viewyourtext": "Можете да погледате и копирате изворник ваших измена на овој страници.", "protectedinterface": "Ова страница садржи текст интерфејса за софтвер на овом викију и заштићена је ради спречавања злоупотребе.\nДа бисте додали или изменили преводе било којег викија, посетите [https://translatewiki.net/ translatewiki.net], пројекат за локализацију Медијавикија.", "editinginterface": "Упозорење: уређујете страницу која се користи за приказивање текста корисничког окружења.\nИзмене на овој страници ће утицати на све кориснике овог викија.", "translateinterface": "Да додате или промените преводе за све викије, посетите [https://translatewiki.net/ Транслејтвики], пројекат за локализацију Медијавикија.", "cascadeprotected": "Ова страница је закључана јер садржи {{PLURAL:$1|следећу страницу која је заштићена|следеће странице које су заштићене}} „преносивом“ заштитом:\n$2", - "namespaceprotected": "Немате дозволу да уређујете странице у именском простору $1.", + "namespaceprotected": "Немате дозволу да уређујете странице у именском простору: $1.", "customcssprotected": "Немате дозволу да мењате ову CSS страницу јер садржи лична подешавања другог корисника.", - "customjsprotected": "Немате дозволу да мењате ову страницу јаваскрипта јер садржи личне поставке другог корисника.", + "customjsprotected": "Немате дозволу да мењате ову страницу JavaScript јер садржи лична подешавања другог корисника.", "mycustomcssprotected": "Немате дозволу за мењање ове CSS странице.", "mycustomjsprotected": "Немате дозволу за мењање ове JavaScript странице.", "myprivateinfoprotected": "Немате дозволу за мењање ваших личних информација.", @@ -396,10 +396,10 @@ "exception-nologin": "Нисте пријављени", "exception-nologin-text": "Пријавите се да бисте приступили овој страници или радњи.", "exception-nologin-text-manual": "Морате бити $1 да бисте приступили овој страници или радњи.", - "virus-badscanner": "Неисправна поставка: непознати скенер за вирусе: ''$1''", + "virus-badscanner": "Неисправно подешавање: непознати скенер за вирусе: $1", "virus-scanfailed": "неуспешно скенирање (код $1)", "virus-unknownscanner": "непознати антивирус:", - "logouttext": "Одјављени сте.\n\nИмајте на уму да неке странице могу наставити да се приказују као да сте још пријављени, све док не очистите привремену меморију свог прегледача.", + "logouttext": "Одјављени сте.\n\nИмајте на уму да неке странице могу наставити да се приказују као да сте још пријављени, све док не очистите привремену меморију Вашег прегледача.", "cannotlogoutnow-title": "Одјава тренутно није могућа", "cannotlogoutnow-text": "Одјава није могућа током употребе $1.", "welcomeuser": "Добро дошли, $1!", @@ -412,9 +412,9 @@ "userlogin-yourpassword": "Лозинка", "userlogin-yourpassword-ph": "Унесите вашу лозинку", "createacct-yourpassword-ph": "Унесите лозинку", - "yourpasswordagain": "Потврда лозинке:", - "createacct-yourpasswordagain": "Потврдите лозинку", - "createacct-yourpasswordagain-ph": "Унесите лозинку још једном", + "yourpasswordagain": "Поново унеси лозинку:", + "createacct-yourpasswordagain": "Потврди лозинку", + "createacct-yourpasswordagain-ph": "Унесите лозинку поново", "userlogin-remembermypassword": "Остави ме пријављеног/у", "userlogin-signwithsecure": "Користите сигурну конекцију", "cannotlogin-title": "Пријава није могућа", @@ -440,7 +440,7 @@ "userlogin-reauth": "Морате се поново пријавити да би верификовали да сте {{GENDER:$1|$1}}.", "userlogin-createanother": "Отвори још један налог", "createacct-emailrequired": "Имејл адреса", - "createacct-emailoptional": "Адреса е-поште (необавезно)", + "createacct-emailoptional": "Имејл адреса (необавезно)", "createacct-email-ph": "Унесите Вашу имејл адресу", "createacct-another-email-ph": "Унесите имејл адресу", "createaccountmail": "Користите привремену, случајно створену лозинку и пошаљите на наведену имејл адресу", @@ -456,7 +456,7 @@ "createacct-benefit-body2": "{{PLURAL:$1|страница|странице|страница}}", "createacct-benefit-body3": "недавно {{PLURAL:$1|активни корисник|активна корисника|активних корисника}}", "badretype": "Унете лозинке се не поклапају.", - "usernameinprogress": "Налог за ово корисничко име се већ прави, молимо сачекајте.", + "usernameinprogress": "Налог за ово корисничко име се већ прави, сачекајте.", "userexists": "Корисничко име је заузето. Изаберите друго.", "loginerror": "Грешка при пријављивању", "createacct-error": "Дошло је до грешке при отварању налога", @@ -467,7 +467,7 @@ "nocookiesforlogin": "{{int:nocookieslogin}}", "noname": "Унели сте неисправно корисничко име.", "loginsuccesstitle": "Успешно пријављивање", - "loginsuccess": "'''Пријављени сте као „$1“.'''", + "loginsuccess": "Пријављени сте на {{SITENAME}} као „$1”.", "nosuchuser": "Не постоји корисник с именом „$1“.\nКорисничка имена су осетљива на мала и велика слова.\nПроверите да ли сте га добро унели или [[Special:CreateAccount|отворите нови налог]].", "nosuchusershort": "Корисник с именом „$1“ не постоји.\nПроверите да ли сте правилно написали.", "nouserspecified": "Морате навести корисничко име.", @@ -481,7 +481,7 @@ "password-login-forbidden": "Коришћење овог корисничког имена и лозинке је забрањено.", "mailmypassword": "Ресетуј лозинку", "passwordremindertitle": "{{SITENAME}} — привремена лозинка", - "passwordremindertext": "Неко, вероватно ви, са ИП адресе $1 је затражио нову лозинку на викију {{SITENAME}} ($4).\nСтворена је привремена лозинка за {{GENDER:$2|корисника|корисницу|корисника}} $2 која гласи $3.\nУколико је ово ваш захтев, сада се пријавите и поставите нову лозинку.\nПривремена лозинка истиче за {{PLURAL:$5|један дан|$5 дана|$5 дана}}.\n\nАко је неко други затражио промену лозинке, или сте се сетили ваше лозинке и не желите да је мењате, занемарите ову поруку.", + "passwordremindertext": "Неко, вероватно ви, са IP адресе $1 је затражио нову лозинку на викију {{SITENAME}} ($4).\nСтворена је привремена лозинка за {{GENDER:$2|корисника|корисницу|корисника}} $2 која гласи $3.\nУколико је ово ваш захтев, сада се пријавите и поставите нову лозинку.\nПривремена лозинка истиче за {{PLURAL:$5|један дан|$5 дана}}.\n\nАко је неко други затражио промену лозинке, или сте се сетили ваше лозинке и не желите да је мењате, занемарите ову поруку.", "noemail": "Не постоји имејл адреса за {{GENDER:$1|корисника|корисницу}} $1.", "noemailcreate": "Морате навести исправну имејл адресу.", "passwordsent": "Нова лозинка је послата на имејл адресу {{GENDER:$1|корисника|кориснице|корисника}} $1.\nПријавите се пошто је примите.", @@ -491,7 +491,7 @@ "mailerror": "Грешка при слању поруке: $1", "acct_creation_throttle_hit": "Посетиоци овог викија који користе вашу IP адресу су већ отворили {{PLURAL:$1|1=један налог|$1 налога}} претходни $2, што је највећи дозвољени број у том временском периоду.\nЗбог тога посетиоци с ове IP адресе тренутно не могу отворити више налога.", "emailauthenticated": "Ваша имејл адреса је потврђена $2 у $3.", - "emailnotauthenticated": "Ваша имејл адреса још није потврђена.\nИмејл неће бити послат ни у једном од следећих случајева.", + "emailnotauthenticated": "Ваша имејл адреса још увек није потврђена.\nИмејл неће бити послат ни у једном од следећих случајева.", "noemailprefs": "Унесите имејл адресу како би ове могућности радиле.", "emailconfirmlink": "Потврдите своју имејл адресу", "invalidemailaddress": "Имејл адреса не може бити прихваћена јер је неисправног облика.\nУнесите исправну адресу или оставите празно поље.", @@ -537,7 +537,7 @@ "botpasswords-label-delete": "Обриши", "botpasswords-label-resetpassword": "Ресетуј лозинку", "botpasswords-label-grants-column": "Одобрено", - "botpasswords-bad-appid": "„$1” није валидан назив бота.", + "botpasswords-bad-appid": "„$1” није исправан назив бота.", "botpasswords-insert-failed": "Неуспешно додавање бота \"$1\". Да ли је већ додат?", "botpasswords-update-failed": "Није могуће ажурирати бота \"$1\". Да ли је обрисан?", "botpasswords-created-title": "Направљена лозинка бота", @@ -559,7 +559,7 @@ "resetpass-abort-generic": "Промену лозинке је спречио додатак.", "resetpass-expired": "Ваша лозинка је истекла. Поставите нову лозинку да бисте се пријавили.", "resetpass-expired-soft": "Ваша лозинка је истекла и морате поставити нову. Поставите нову лозинку или кликните „{{int:authprovider-resetpass-skip-label}}“ да је поставите касније.", - "resetpass-validity-soft": "Ваша лозинка није ваљана: $1\n\nМолимо изаберите нову или кликните „{{int:authprovider-resetpass-skip-label}}“ да ресетујете касније.", + "resetpass-validity-soft": "Ваша лозинка није исправна: $1\n\nМолимо изаберите нову или кликните „{{int:authprovider-resetpass-skip-label}}“ да ресетујете касније.", "passwordreset": "Обнављање лозинке", "passwordreset-text-one": "Попуните овај образац да бисте добили привремену лозинку на имејл.", "passwordreset-text-many": "{{PLURAL:$1|Испуните једно од поља како бисте добили привремену лозинку на имејл.}}", @@ -569,7 +569,7 @@ "passwordreset-domain": "Домен:", "passwordreset-email": "Имејл адреса:", "passwordreset-emailtitle": "Детаљи налога на викију {{SITENAME}}", - "passwordreset-emailtext-ip": "Неко (вероватно Ви, са ИП адресе $1) је затражио нову лозинку на викију {{SITENAME}} ($4).\nСледећи {{PLURAL:$3|кориснички налог је повезан|кориснички налози су повезани}} с овом имејл адресом:\n\n$2\n\n{{PLURAL:$3|Привремена лозинка истиче|Привремене лозинке истичу}} за {{PLURAL:$5|један дан|$5 дана}}.\nПријавите се и изаберите нову лозинку. Ако је неко други захтевао ову радњу или сте се сетили лозинке и не желите да је мењате, занемарите ову поруку и наставите користити стару лозинку.", + "passwordreset-emailtext-ip": "Неко (вероватно Ви, са IP адресе $1) је затражио нову лозинку на викију {{SITENAME}} ($4).\nСледећи {{PLURAL:$3|кориснички налог је повезан|кориснички налози су повезани}} с овом имејл адресом:\n\n$2\n\n{{PLURAL:$3|Привремена лозинка истиче|Привремене лозинке истичу}} за {{PLURAL:$5|један дан|$5 дана}}.\nПријавите се и изаберите нову лозинку. Ако је неко други захтевао ову радњу или сте се сетили лозинке и не желите да је мењате, занемарите ову поруку и наставите користити стару лозинку.", "passwordreset-emailtext-user": "{{GENDER:$1|Корисник је затражио|Корисница је затражила}} подсетник о подацима за пријаву на викију {{SITENAME}} ($4).\nСледећи {{PLURAL:$3|кориснички налог је повезан|кориснички налози су повезани}} с овом имејл адресом:\n\n$2\n\n{{PLURAL:$3|Привремена лозинка истиче|Привремене лозинке истичу}} за {{PLURAL:$5|један дан|$5 дана}}.\nПријавите се и изаберите нову лозинку. Ако је неко други захтевао ову радњу или сте се сетили лозинке и не желите да је мењате, занемарите ову поруку.", "passwordreset-emailelement": "Корисничко име: \n$1\n\nПривремена лозинка: \n$2", "passwordreset-emailsentemail": "Ако је ово имејл адреса повезана са Вашим налогом, подсетник о лозинци ће бити послат на имејл.", @@ -593,27 +593,27 @@ "resettokens-no-tokens": "Нема жетона за ресетовање.", "resettokens-tokens": "Жетони:", "resettokens-token-label": "$1 (тренутна вредност: $2)", - "resettokens-watchlist-token": "Жетон за веб довод (Atom/RSS) вашег [[Special:Watchlist|списка надгледања]]", + "resettokens-watchlist-token": "Жетон за веб довод (Atom/RSS) [[Special:Watchlist|измена на страницама у вашем списку надгледања]]", "resettokens-done": "Жетони су ресетовани", "resettokens-resetbutton": "Ресетуј изабране жетоне", "bold_sample": "Подебљан текст", "bold_tip": "Подебљан текст", - "italic_sample": "Искошени текст", - "italic_tip": "Искошени текст", + "italic_sample": "Искошен текст", + "italic_tip": "Искошен текст", "link_sample": "Наслов везе", "link_tip": "Унутрашња веза", - "extlink_sample": "http://www.example.com/ наслов везе", + "extlink_sample": "http://www.пример.com наслов везе", "extlink_tip": "Спољашња веза (с префиксом http://)", "headline_sample": "Текст наслова", "headline_tip": "Поднаслов (ниво 2)", "nowiki_sample": "Убаците необликован текст овде", "nowiki_tip": "Занемари вики обликовање", "image_sample": "Пример.jpg", - "image_tip": "Уграђивање датотеке", + "image_tip": "Убацивање датотеке", "media_sample": "Пример.ogg", "media_tip": "Веза", "sig_tip": "Ваш потпис са тренутним временом", - "hr_tip": "Водоравна линија (користити ретко)", + "hr_tip": "Водоравна линија (користите ретко)", "summary": "Опис измене:", "subject": "Тема:", "minoredit": "Ово је мања измена", @@ -625,13 +625,13 @@ "preview": "Претпреглед", "showpreview": "Прикажи претпреглед", "showdiff": "Прикажи измене", - "blankarticle": "Упозорење: Страница коју правите је празна.\nАко још једном притиснете „$1”, страница ће бити направљена без икаквог садржаја.", - "anoneditwarning": "Упозорење: Нисте пријављени. Ако објавите страницу, Ваша IP адреса ће бити јавно видљива у њеној историји измена и другде. Ако се [$1 пријавите] или [$2 отворите налог], поред осталих погодности које добијате Ваше измене ће бити приписиване Вашем корисничком имену.", + "blankarticle": "Упозорење: страница коју правите је празна.\nАко још једном притиснете „$1”, страница ће бити направљена без икаквог садржаја.", + "anoneditwarning": "Упозорење: нисте пријављени. Ако објавите страницу, Ваша IP адреса ће бити јавно видљива у њеној историји измена и другде. Ако се [$1 пријавите] или [$2 отворите налог], поред осталих погодности које добијате Ваше измене ће бити приписиване Вашем корисничком имену.", "anonpreviewwarning": "Нисте пријављени. Ако објавите страницу, Ваша IP адреса ће бити јавно видљива у њеној историји измена и другде.", - "missingsummary": "'''Подсетник:''' Нисте унели опис измене.\nАко поново кликнете на „$1”, Ваша измена ће бити сачувана без описа.", - "selfredirect": "Упозорење: Преусмеравате ову страницу на њу саму.\nМожда вам је одредишна страница за преусмерење погрешна или уређујете погрешну страницу.\nАко још једном притиснете „$1”, преусмерење ће свеједно бити направљено.", + "missingsummary": "Подсетник: нисте унели опис измене.\nАко поново кликнете на „$1”, Ваша измена ће бити сачувана без описа.", + "selfredirect": "Упозорење: преусмеравате ову страницу на њу саму.\nМожда вам је одредишна страница за преусмерење погрешна или уређујете погрешну страницу.\nАко још једном притиснете „$1”, преусмерење ће свеједно бити направљено.", "missingcommenttext": "Молимо унесите коментар.", - "missingcommentheader": "Напомена: Нисте унели наслов теме овог коментара.\nАко поново кликнете на „$1”, измена ће бити сачувана без наслова.", + "missingcommentheader": "Напомена: нисте унели наслов теме овог коментара.\nАко поново кликнете на „$1”, измена ће бити сачувана без наслова.", "summary-preview": "Преглед описа измене:", "subject-preview": "Преглед теме:", "previewerrortext": "Догодила се грешка приликом приказивања ваших измена.", @@ -650,49 +650,49 @@ "accmailtext": "Лозинка за {{GENDER:$1|корисника|корисницу}} [[User talk:$1|$1]] је послата на $2. Након пријаве, лозинка се може променити [[Special:ChangePassword|овде]].", "newarticle": "(нови)", "newarticletext": "Дошли сте на страницу која још не постоји.\nДа бисте је направили, почните да куцате у прозор испод овог текста (погледајте [$1 страницу за помоћ]).\nАко сте овде дошли грешком, вратите се на претходну страницу.", - "anontalkpagetext": "----\nОво је страница за разговор с анонимним корисником који још нема налог или га не користи.\nЗбог тога морамо да користимо бројчану ИП адресу како бисмо га препознали.\nТакву адресу може делити више корисника.\nАко сте анонимни корисник и мислите да су вам упућене примедбе, [[Special:CreateAccount|отворите налог]] или се [[Special:UserLogin|пријавите]] да бисте избегли будућу забуну с осталим анонимним корисницима.", + "anontalkpagetext": "----\nОво је страница за разговор с анонимним корисником који још нема налог или га не користи.\nЗбог тога морамо да користимо бројчану IP адресу како бисмо га препознали.\nТакву адресу може делити више корисника.\nАко сте анонимни корисник и мислите да су вам упућене примедбе, [[Special:CreateAccount|отворите налог]] или се [[Special:UserLogin|пријавите]] да бисте избегли будућу забуну с осталим анонимним корисницима.", "noarticletext": "На овој страници тренутно нема садржаја.\nМожете [[Special:Search/{{PAGENAME}}|потражити овај наслов]] на другим страницама,\n[{{fullurl:{{#Special:Log}}|page={{FULLPAGENAMEE}}}} претражити сродне извештаје] или [{{fullurl:{{FULLPAGENAME}}|action=edit}} направити ову страницу].", "noarticletext-nopermission": "На овој страници тренутно нема садржаја.\nМожете [[Special:Search/{{PAGENAME}}|потражити овај наслов]] на другим страницама или [{{fullurl:{{#Special:Log}}|page={{FULLPAGENAMEE}}}} претражити сродне дневнике], али немате дозволу да направите ову страницу.", "missing-revision": "Не могу да пронађем измену бр. $1 на страници под називом „{{FULLPAGENAME}}“.\n\nОво се обично дешава када пратите застарелу везу до странице која је обрисана.\nВише информација можете пронаћи у [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} дневнику брисања].", "userpage-userdoesnotexist": "Кориснички налог „$1“ није отворен.\nРазмислите да ли заиста желите да направите/уредите ову страницу.", "userpage-userdoesnotexist-view": "Кориснички налог „$1“ није отворен.", "blocked-notice-logextract": "Овај корисник је тренутно блокиран.\nИзвештај о последњем блокирању можете погледати испод:", - "clearyourcache": "Напомена: након чувања, можда ћете морати да очистите кеш прегледача како бисте видели промене.\n* Фајерфокс / Сафари: држите Shift и кликните на Освежи, или притисните Ctrl-F5 или Ctrl-R (⌘-R на Меку)\n* Гугл кроум: притисните Ctrl-Shift-R (⌘-Shift-R на Меку)\n* Интернет експлорер: држите Ctrl и кликните на Освежи или притисните Ctrl-F5\n* Опера: идите на Алатке → Подешавања (Опера → Поставке на Меку) и затим Приватност и безбедност → Очистите податке о прегледима → Кеширане слике и датотеке.", - "usercssyoucanpreview": "'''Савет:''' кориситите дугме „{{int:showpreview}}“ да испробате свој нови CSS пре него што га сачувате.", - "userjsyoucanpreview": "'''Савет:''' кориситите дугме „{{int:showpreview}}“ да испробате свој нови јаваскрипт пре него што га сачувате.", - "usercsspreview": "'''Ово је само преглед CSS-а.'''\n'''Страница још није сачувана!'''", - "userjspreview": "'''Ово је само преглед јаваскрипта.'''\n'''Страница још није сачувана!'''", - "sitecsspreview": "'''Ово је само преглед CSS-а.'''\n'''Страница још није сачувана!'''", - "sitejspreview": "'''Ово је само преглед јаваскрипта.'''\n'''Страница још није сачувана!'''", + "clearyourcache": "Напомена: након чувања, можда ћете морати да очистите кеш прегледача како бисте видели измене.\n* Фајерфокс / Сафари: држите Shift и кликните на Освежи, или притисните Ctrl-F5 или Ctrl-R (⌘-R на Меку)\n* Гугл кроум: притисните Ctrl-Shift-R (⌘-Shift-R на Меку)\n* Интернет експлорер: држите Ctrl и кликните на Освежи или притисните Ctrl-F5\n* Опера: идите на Алатке → Подешавања (Опера → Поставке на Меку) и затим Приватност и безбедност → Очистите податке о прегледима → Кеширане слике и датотеке.", + "usercssyoucanpreview": "Савет: кориситите дугме „{{int:showpreview}}“ да испробате свој нови CSS пре него што га сачувате.", + "userjsyoucanpreview": "Савет: кориситите дугме „{{int:showpreview}}“ да испробате свој нови јаваскрипт пре него што га сачувате.", + "usercsspreview": "Ово је само преглед CSS-а.\nСтраница још није сачувана!", + "userjspreview": "Ово је само преглед јаваскрипта.\nСтраница још није сачувана!", + "sitecsspreview": "Ово је само преглед CSS-а.\nСтраница још није сачувана!", + "sitejspreview": "Ово је само преглед јаваскрипта.\nСтраница још није сачувана!", "userinvalidcssjstitle": "Упозорење: не постоји тема „$1“.\nПрилагођене странице CSS и јаваскрипт почињу малим словом, нпр. {{ns:user}}:Foo/vector.css, а не {{ns:user}}:Foo/Vector.css.", - "updated": "(Ажурирано)", + "updated": "(ажурирано)", "note": "Напомена:", "previewnote": "Не заборавите да је ово само претпреглед.\nВаше измене још нису сачуване!", "continue-editing": "Иди на уређивачки оквир", - "previewconflict": "Овај преглед осликава како ће текст у текстуалном оквиру изгледати.", - "session_fail_preview": "Извињавамо се! Нисмо могли да обрадимо Вашу измену због губитка података сесије.\n\nМожда сте одјављени. Проверите да ли сте пријављени и покушајте поново.\nАко и даље не ради, покушајте да се [[Special:UserLogout|одјавите]] и поново пријавите, те проверите да ли су на Вашем претраживачу дозвољени колачићи са овог сајта.", + "previewconflict": "Овај преглед осликава како ће изгледати текст у текстуалном оквиру.", + "session_fail_preview": "Нисмо могли да обрадимо Вашу измену због губитка података сесије.\n\nМожда сте одјављени. Проверите да ли сте пријављени и покушајте поново.\nАко и даље не ради, покушајте да се [[Special:UserLogout|одјавите]] и поново пријавите, те проверите да ли су на Вашем прегледачу дозвољени колачићи са овог сајта.", "session_fail_preview_html": "Нисмо могли да обрадимо вашу измену због губитка података сесије.\n\nБудући да је на овом викију омогућен унос HTML ознака, преглед је сакривен као мера предострожности против напада преко јаваскрипта.\n\nАко сте покушали да направите праву измену, покушајте поново.\nАко и даље не ради, покушајте да се [[Special:UserLogout|одјавите]] и поново пријавите и проверите да ли Ваш прегледач дозвољава колачиће са овог сајта.", - "token_suffix_mismatch": "'''Ваша измена је одбачена јер је ваш прегледач убацио знакове интерпункције у новчић уређивања.\nТо се понекад догађа када се користи неисправан посредник.'''", + "token_suffix_mismatch": "Ваша измена је одбачена јер је ваш прегледач убацио знакове интерпункције у новчић уређивања.\nТо се понекад догађа када се користи неисправан посредник.", "edit_form_incomplete": "Неки делови обрасца за уређивање нису стигли до сервера. Проверите да ли су ваше измене непромењене и покушајте поново.", "editing": "Уређујете $1", "creating": "Прављење странице $1", "editingsection": "Уређујете $1 (одељак)", "editingcomment": "Уређујете $1 (нови одељак)", "editconflict": "Сукобљене измене: $1", - "explainconflict": "Неко други је у међувремену променио ову страницу.\nГорњи оквир садржи садашњи текст странице.\nВаше измене су приказане у доњем оквиру.\nМораћете да унесете своје промене у садашњи текст странице.\nСамо ће текст у горњем оквиру за уређивање бити сачуван када кликнете на „$1”.", + "explainconflict": "Неко други је у међувремену променио ову страницу.\nГорњи оквир садржи садашњи текст странице.\nВаше измене су приказане у доњем оквиру.\nМораћете да унесете своје измене у садашњи текст странице.\nСамо ће текст у горњем оквиру за уређивање бити сачуван када кликнете на „$1”.", "yourtext": "Ваш текст", "storedversion": "Ускладиштена измена", "editingold": "Упозорење: уређујете застарелу измену ове странице.\nАко је сачувате, све новије измене ће бити изгубљене.", "yourdiff": "Разлике", - "copyrightwarning": "Имајте на уму да се сви доприноси на овом викију сматрају као објављени под лиценцом $2 (више на $1).\nАко не желите да се ваши текстови мењају и размењују без ограничења, онда их не шаљите овде.
\nИсто тако обећавате да сте ви аутор текста, или да сте га умножили с извора који је у јавном власништву.\nНе шаљите радове заштићене ауторским правима без дозволе!", + "copyrightwarning": "Имајте на уму да се сви доприноси на овом викију сматрају као објављени под лиценцом $2 (више на $1).\nАко не желите да се ваши текстови мењају и размењују без ограничења, онда их не шаљите овде.
\nИсто тако обећавате да сте Ви аутор текста, или да сте га умножили с извора који је у јавном власништву.\nНе шаљите радове заштићене ауторским правима без дозволе!", "copyrightwarning2": "Имајте на уму да се сви доприноси на овом викију могу мењати, враћати или брисати од других корисника.\nАко не желите да се ваши текстови слободно мењају и расподељују, не шаљите их овде.
\nИсто тако обећавате да сте ви аутор текста, или да сте га умножили с извора који је у јавном власништву (више на $1).\nНе шаљите радове заштићене ауторским правима без дозволе!", "editpage-cannot-use-custom-model": "Модел садржаја ове странице се не може променити.", - "longpageerror": "'''Грешка: текст који сте унели је величине {{PLURAL:$1|један килобајт|$1 килобајта|$1 килобајта}}, што је веће од {{PLURAL:$2|дозвољеног једног килобајта|дозвољена $2 килобајта|дозвољених $2 килобајта}}.'''\nСтраница не може бити сачувана.", + "longpageerror": "Грешка: текст који сте унели је величине {{PLURAL:$1|један килобајт|$1 килобајта}}, што је веће од {{PLURAL:$2|дозвољеног једног килобајта|дозвољена $2 килобајта|дозвољених $2 килобајта}}.\nСтраница не може бити сачувана.", "readonlywarning": "Упозорење: база података је закључана ради одржавања, тако да тренутно нећете моћи да сачувате измене.\nМожда бисте желели сачувати текст за касније у некој текстуалној датотеци.\n\nСистемски администратор је навео следеће објашњење: $1", "protectedpagewarning": "Упозорење: ова страница је заштићена, тако да само администратори могу да је мењају.\nПоследњи запис у дневнику је приказан испод:", - "semiprotectedpagewarning": "Напомена: Ова страница је заштићена, тако да само регистровани корисници могу да је уређују.\nПоследњи запис у дневнику приказан је испод као референца:", + "semiprotectedpagewarning": "Напомена: Ова страница је заштићена, тако да само регистровани корисници могу да је уређују.\nПоследњи запис у дневнику је приказан испод:", "cascadeprotectedwarning": "Упозорење: Ова страница је заштићена тако да је могу уређивати само корисници са [[Special:ListGroupRights|одређеним правима]] (администратори), јер је иста укључена у {{PLURAL:$1|следећу страницу која је заштићена|следеће странице које су заштићене}} „преносивом” заштитом:", - "titleprotectedwarning": "Упозорење: ову страницу могу направити само корисници [[Special:ListGroupRights|с одређеним правима]].\nИспод су наведени последњи записи у дневнику:", + "titleprotectedwarning": "Упозорење: ову страницу могу направити само корисници [[Special:ListGroupRights|с одређеним правима]].\nПоследњи запис у дневнику је приказан испод:", "templatesused": "{{PLURAL:$1|Шаблон|Шаблони}} на овој страници:", "templatesusedpreview": "{{PLURAL:$1|Шаблон|Шаблони}} у овом претпрегледу:", "templatesusedsection": "{{PLURAL:$1|Шаблон|Шаблони}} у овом одељку:", @@ -710,7 +710,7 @@ "permissionserrorstext-withaction": "Немате дозволу за $2 из {{PLURAL:$1|следећег|следећих}} разлога:", "recreate-moveddeleted-warn": "Упозорење: поново правите страницу која је претходно обрисана.\n\nРазмотрите да ли је прикладно да наставите с уређивањем ове странице.\nОвде је наведена историја брисања и премештања с образложењем:", "moveddeleted-notice": "Ова страница је обрисана.\nИсторија њеног брисања, заштите и премештања налази се испод:", - "moveddeleted-notice-recent": "Жао нам је, ова страница је недавно обрисана (у последњих 24 сата).\nОвде је наведена историја брисања и премештања с образложењем.", + "moveddeleted-notice-recent": "Жао нам је, ова страница је недавно обрисана (у последњих 24 сата).\nИсторија њеног брисања, заштите и премештања налази се испод:", "log-fulllog": "Погледај целу историју", "edit-hook-aborted": "Измену је прекинула кука.\nНије дато никакво образложење.", "edit-gone-missing": "Не могу да ажурирам страницу.\nИзгледа да је обрисана.", @@ -736,14 +736,14 @@ "content-model-json": "JSON", "content-json-empty-object": "Празан објекат", "content-json-empty-array": "Празан низ", - "deprecated-self-close-category": "Странице које користе невалидне самозатварајуће HTML тагове", + "deprecated-self-close-category": "Странице које користе неисправне самозатварајуће HTML тагове", "duplicate-args-warning": "Упозорење: [[:$1]] позива [[:$2]] са више од једне вредности за параметар „$3“. Само последња наведена вредност ће бити коришћена.", "duplicate-args-category": "Странице с дуплираним аргументима код позива шаблона", "duplicate-args-category-desc": "Страница садржи позиве шаблона који користе двоструке аргументе, као што су {{foo|bar=1|bar=2}} или {{foo|bar|1=baz}}.", - "expensive-parserfunction-warning": "'''Упозорење:''' ова страница садржи превише позива за рашчлањивање.\n\nТребало би да има мање од $2 {{PLURAL:$2|позив|позива|позива}}, а сада има $1.", + "expensive-parserfunction-warning": "Упозорење: ова страница садржи превише позива за рашчлањивање.\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": "Упозорење: величина обухваћеног шаблона је превелика.\nНеки шаблони неће бити обухваћени.", + "post-expand-template-inclusion-category": "Странице где су обухваћени превелики шаблони", "post-expand-template-argument-warning": "'''Упозорење:''' ова страница садржи најмање један аргумент у шаблону који има превелику величину.\nОвакве аргументе би требало избегавати.", "post-expand-template-argument-category": "Странице које садрже изостављене аргументе у шаблону", "parser-template-loop-warning": "Откривена је петља шаблона: [[$1]]", @@ -875,8 +875,8 @@ "mergehistory-done": "$3 {{PLURAL:$3|измена странице $1 је спојена|измене странице $1 су спојене|измена странице $1 је спојено}} у [[:$2]].", "mergehistory-fail": "Не могу да спојим историје. Проверите страницу и временске параметре.", "mergehistory-fail-bad-timestamp": "Временска ознака није исправна.", - "mergehistory-fail-invalid-source": "Изворна страница није валидна.", - "mergehistory-fail-invalid-dest": "Одредишна страница није валидна.", + "mergehistory-fail-invalid-source": "Изворна страница није исправна.", + "mergehistory-fail-invalid-dest": "Одредишна страница није исправна.", "mergehistory-fail-permission": "Немате овлашћење за спајање историје.", "mergehistory-fail-self-merge": "Изворна и одредишна страница не могу бити исте.", "mergehistory-fail-toobig": "Није могуће спојити историје јер више од $1 {{PLURAL:$1|измене ће бити премештене|измена ће бити премештено}}.", @@ -983,7 +983,7 @@ "prefs-resetpass": "Промени лозинку", "prefs-changeemail": "Промени или уклони имејл адресу", "prefs-setemail": "Постави имејл адресу", - "prefs-email": "Поставке имејла", + "prefs-email": "Подешавања имејла", "prefs-rendering": "Изглед", "saveprefs": "Сачувај", "restoreprefs": "Врати све на подразумевано (у свим одељцима)", @@ -996,7 +996,7 @@ "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": "Временска зона:", @@ -1025,7 +1025,7 @@ "prefs-custom-css": "Прилагођени CSS", "prefs-custom-js": "Прилагођени јаваскрипт", "prefs-common-css-js": "Дељени CSS/Јаваскрипт за све теме:", - "prefs-reset-intro": "Можете користити ову страницу да поништите своје поставке на подразумеване вредности.\nОва радња се не може вратити.", + "prefs-reset-intro": "Можете користити ову страницу да поништите своја подешавања на подразумеване вредности.\nОва радња се не може вратити.", "prefs-emailconfirm-label": "Потврда имејла:", "youremail": "Имејл:", "username": "{{GENDER:$1|Корисничко име}}:", @@ -1060,13 +1060,13 @@ "prefs-advancedediting": "Главна подешавања", "prefs-editor": "Уређивач", "prefs-preview": "Претпреглед", - "prefs-advancedrc": "Напредне поставке", + "prefs-advancedrc": "Напредна подешавања", "prefs-opt-out": "Онемогућавање побољшања", - "prefs-advancedrendering": "Напредне поставке", - "prefs-advancedsearchoptions": "Напредне поставке", - "prefs-advancedwatchlist": "Напредне поставке", - "prefs-displayrc": "Поставке приказа", - "prefs-displaywatchlist": "Поставке приказа", + "prefs-advancedrendering": "Напредна подешавања", + "prefs-advancedsearchoptions": "Напредна подешавања", + "prefs-advancedwatchlist": "Напредна подешавања", + "prefs-displayrc": "Подешавања приказа", + "prefs-displaywatchlist": "Подешавања приказа", "prefs-tokenwatchlist": "Жетон", "prefs-diffs": "Разлике", "prefs-help-prefershttps": "Ова подешавања ће ступити на снагу при следећој пријави.", @@ -1169,8 +1169,8 @@ "right-editmyuserjs": "уређивање сопствених JavaScript датотека", "right-viewmywatchlist": "види сопствени списак надгледања", "right-editmywatchlist": "уређивање сопственог списка надгледања; неке предузете радње ће свеједно додати странице на списак и без овог права", - "right-viewmyprivateinfo": "Видите своје личне податке (нпр. имејл адресу, право име)", - "right-editmyprivateinfo": "Уређивање сопствених личних података (нпр. имејл адреса, право име)", + "right-viewmyprivateinfo": "видите своје личне податке (нпр. имејл адресу, право име)", + "right-editmyprivateinfo": "уређивање сопствених личних података (нпр. имејл адреса, право име)", "right-editmyoptions": "уређивање сопствених подешавања", "right-rollback": "брзо враћање измена последњег корисника који је мењао одређену страницу", "right-markbotedits": "означавање враћених измена као измене бота", @@ -1313,13 +1313,13 @@ "rcfilters-savedqueries-apply-label": "Направи филтер", "rcfilters-savedqueries-apply-and-setdefault-label": "Направи подразумевани филтер", "rcfilters-savedqueries-cancel-label": "Откажи", - "rcfilters-savedqueries-add-new-title": "Сачувај тренутне поставке филтера", + "rcfilters-savedqueries-add-new-title": "Сачувај тренутна подешавања филтера", "rcfilters-savedqueries-already-saved": "Ови филтери су већ упамћени. Измените Ваша подешавања како бисте направили нове сачуване филтере.", "rcfilters-restore-default-filters": "Враћање подразумеваних филтера", "rcfilters-clear-all-filters": "Уклони све филтере", "rcfilters-show-new-changes": "Погледајте најновије измене", "rcfilters-search-placeholder": "Филтрирај скорашње измене (употребите мени или потражите име филтра)", - "rcfilters-invalid-filter": "Невалидан филтер", + "rcfilters-invalid-filter": "Неисправан филтер", "rcfilters-empty-filter": "Нема активних филтера. Сви доприноси су приказани.", "rcfilters-filterlist-title": "Филтери", "rcfilters-filterlist-whatsthis": "Како ово функционише?", @@ -1547,7 +1547,7 @@ "destfilename": "Назив:", "upload-maxfilesize": "Максимална величина датотеке: $1", "upload-description": "Опис датотеке", - "upload-options": "Поставке отпремања", + "upload-options": "Подешавања отпремања", "watchthisupload": "Надгледај ову датотеку", "filewasdeleted": "Датотека с овим називом је раније послата, али је обрисана.\nПроверите $1 пре него што наставите с поновним слањем.", "filename-bad-prefix": "Назив датотеке коју шаљете почиње са „$1“, а њега обично додељују дигитални фотоапарати.\nИзаберите назив датотеке који описује њен садржај.", @@ -1624,7 +1624,7 @@ "uploadstash-errclear": "Чишћење датотека није успело.", "uploadstash-refresh": "Освежи списак датотека", "uploadstash-bad-path": "Путања не постоји.", - "uploadstash-bad-path-invalid": "Путање није валидна.", + "uploadstash-bad-path-invalid": "Путања није исправна.", "uploadstash-bad-path-unknown-type": "Непознат тип „$1“.", "invalid-chunk-offset": "Неисправна полазна тачка", "img-auth-accessdenied": "Приступ је одбијен", @@ -1715,7 +1715,7 @@ "filerevert-submit": "Врати", "filerevert-success": "Датотека '''[[Media:$1|$1]]''' је враћена на [$4 издање од $2; $3].", "filerevert-badversion": "Не постоји раније локално издање датотеке с наведеним временским подацима.", - "filerevert-identical": "Тренутна верзија датотеке индентична је изабраној.", + "filerevert-identical": "Тренутна измена датотеке индентична је изабраној.", "filedelete": "Обриши $1", "filedelete-legend": "Обриши датотеку", "filedelete-intro": "Бришете датотеку '''[[Media:$1|$1]]''' заједно с њеном историјом.", @@ -1778,7 +1778,7 @@ "doubleredirects": "Двострука преусмерења", "doubleredirectstext": "Ова страница приказује странице које преусмеравају на друга преусмерења.\nСваки ред садржи везе према првом и другом преусмерењу, као и одредишну страницу другог преусмерења која је обично „прави“ чланак на кога прво преусмерење треба да упућује.\nПрецртани уноси су већ решени.", "double-redirect-fixed-move": "[[$1]] је премештен.\nАутоматски је ажурирано и сада преусмерава на [[$2]].", - "double-redirect-fixed-maintenance": "Аутоматски исправља двострука преусмерења из [[$1]] у [[$2]]. Као део одржавања.", + "double-redirect-fixed-maintenance": "Аутоматски исправља двострука преусмерења из [[$1]] у [[$2]] као део одржавања", "double-redirect-fixer": "Исправљач преусмерења", "brokenredirects": "Покварена преусмерења", "brokenredirectstext": "Следећа преусмерења упућују на непостојеће странице:", @@ -1895,7 +1895,7 @@ "apisandbox-dynamic-error-exists": "Параметар под називом \"$1\" већ постоји.", "apisandbox-deprecated-parameters": "Застарели параметри", "apisandbox-fetch-token": "Аутоматски попуни токен", - "apisandbox-submit-invalid-fields-title": "Нека поља нису валидна", + "apisandbox-submit-invalid-fields-title": "Нека поља нису исправна", "apisandbox-submit-invalid-fields-message": "Молимо Вас поправите означена поља и покушајте поново.", "apisandbox-results": "Резултати", "apisandbox-sending-request": "Слање API захтева...", @@ -2059,7 +2059,7 @@ "wlshowhidepatr": "патролиране измене", "wlshowhidemine": "моје измене", "wlshowhidecategorization": "категоризацију страница", - "watchlist-options": "Поставке списка надгледања", + "watchlist-options": "Подешавања списка надгледања", "watching": "Надгледање…", "unwatching": "Уклањање са списка надгледања...", "watcherrortext": "Дошло је до грешке при промени поставки вашег списка надгледања за „$1“.", @@ -2078,7 +2078,7 @@ "enotif_lastvisited": "За све измене од ваше последње посете, погледајте $1.", "enotif_lastdiff": "Да видите ову измену, погледајте $1.", "enotif_anon_editor": "анониман корисник $1", - "enotif_body": "Поштовани $WATCHINGUSERNAME,\n \t\n$PAGEINTRO $NEWPAGE\n\nОпис: $PAGESUMMARY $PAGEMINOREDIT\n\nКонтакт:\nмејл: $PAGEEDITOR_EMAIL\nвики: $PAGEEDITOR_WIKI\n\nНеће бити других обавештења у случају даљих измена уколико не посетите ову страницу када сте пријављени.\nМожете и да поништите поставке обавештења за све странице у вашем списку надгледања.\n\nСрдачан поздрав, {{SITENAME}}\n\n--\nДа бисте променили поставке имејл обавештења, посетите\n{{canonicalurl:{{#special:Preferences}}}}\n\nДа бисте променили поставке списка надгледања, посетите\n{{canonicalurl:{{#special:EditWatchlist}}}}\n\nДа бисте уклонили ову страницу са списка надгледања, посетите\n$UNWATCHURL\n\nПодршка и даља помоћ:\n$HELPPAGE", + "enotif_body": "Поштовани $WATCHINGUSERNAME,\n \t\n$PAGEINTRO $NEWPAGE\n\nОпис: $PAGESUMMARY $PAGEMINOREDIT\n\nКонтакт:\nмејл: $PAGEEDITOR_EMAIL\nвики: $PAGEEDITOR_WIKI\n\nНеће бити других обавештења у случају даљих измена уколико не посетите ову страницу када сте пријављени.\nМожете и да поништите подешавања обавештења за све странице у вашем списку надгледања.\n\nСрдачан поздрав, {{SITENAME}}\n\n--\nДа бисте променили подешавања имејл обавештења, посетите\n{{canonicalurl:{{#special:Preferences}}}}\n\nДа бисте променили подешавања списка надгледања, посетите\n{{canonicalurl:{{#special:EditWatchlist}}}}\n\nДа бисте уклонили ову страницу са списка надгледања, посетите\n$UNWATCHURL\n\nПодршка и даља помоћ:\n$HELPPAGE", "enotif_minoredit": "Ово је мања измена", "created": "направљена", "changed": "измењена", @@ -2153,16 +2153,16 @@ "protect-badnamespace-text": "Странице у овом именском простору се не могу заштитити.", "protect-norestrictiontypes-text": "Ова страница се не може заштитити јер нема доступних врста ограничења.", "protect-norestrictiontypes-title": "Незаштитљива страна", - "protect-legend": "Поставке заштите", + "protect-legend": "Подешавања заштите", "protectcomment": "Разлог:", "protectexpiry": "Истиче:", "protect_expiry_invalid": "Време истека је неисправно.", "protect_expiry_old": "Време истека је старије од тренутног времена.", - "protect-unchain-permissions": "Откључај даљње поставке заштите", + "protect-unchain-permissions": "Откључај даљња подешавања заштите", "protect-text": "Овде можете да погледате и промените степен заштите за страницу '''$1'''.", - "protect-locked-blocked": "Не можете мењати степене заштите док сте блокирани.\nОво су тренутне поставке странице '''$1''':", - "protect-locked-dblock": "Степени заштите се не могу мењати јер је активна база података закључана.\nОво су поставке странице '''$1''':", - "protect-locked-access": "Немате овлашћења за мењање степена заштите странице.\nОво су тренутне поставке странице '''$1''':", + "protect-locked-blocked": "Не можете мењати степене заштите док сте блокирани.\nОво су тренутна подешавања странице '''$1''':", + "protect-locked-dblock": "Степени заштите се не могу мењати јер је активна база података закључана.\nОво су подешавања странице '''$1''':", + "protect-locked-access": "Немате овлашћења за мењање степена заштите странице.\nОво су тренутна подешавања странице '''$1''':", "protect-cascadeon": "Ова страница је тренутно заштићена јер се налази на {{PLURAL:$1|страници која има|страницама које имају}} преносиву заштиту.\nМожете да промените степен заштите, али то неће утицати на преносиву заштиту.", "protect-default": "Допуштено свим корисницима", "protect-fallback": "Дозвољено само корисницима са дозволом „$1“", @@ -2288,7 +2288,7 @@ "unblock": "Деблокирање корисника", "blockip": "Блокирај {{GENDER:$1|корисника|корисницу}}", "blockiptext": "Користите доњи образац да бисте забранили приступ за писање с одређене IP адресе или корисничког имена.\nОво би требало да вршите само ради спречавања вандализма, у складу са [[{{MediaWiki:Policy-url}}|смерницама]].\nИзаберите конкретан разлог испод (пример: навођење конкретних страница које су вандализоване). Можете блокирати опсеге IP адреса помоћу [https://en.wikipedia.org/wiki/Classless_Inter-Domain_Routing CIDR] синтаксе, највећи дозвољени опсег за IPv4 је /$1 односно /$2 за IPv6.", - "ipaddressorusername": "ИП адреса или корисничко име:", + "ipaddressorusername": "IP адреса или корисничко име:", "ipbexpiry": "Истиче:", "ipbreason": "Разлог:", "ipbreason-dropdown": "*Најчешћи разлози за блокирање\n** Уношење лажних информација\n** Уклањање садржаја са страница\n** Постављање веза до спољашњих сајтова\n** Уношење бесмислица у странице\n** Непристојно понашање\n** Употреба више налога\n** Неприхватљиво корисничко име", @@ -2353,7 +2353,7 @@ "emailblock": "имејл је онемогућен", "blocklist-nousertalk": "забрањено уређивање сопствене странице за разговор", "ipblocklist-empty": "Списак блокирања је празан.", - "ipblocklist-no-results": "Тражена ИП адреса или корисничко име није блокирано.", + "ipblocklist-no-results": "Тражена IP адреса или корисничко име није блокирано.", "blocklink": "блокирај", "unblocklink": "деблокирај", "change-blocklink": "промени блокаду", @@ -2383,8 +2383,8 @@ "ipb-otherblocks-header": "{{PLURAL:$1|Друге блокаде}}", "unblock-hideuser": "Не можете деблокирати овог корисника јер је његово корисничко име сакривено.", "ipb_cant_unblock": "Грешка: блокада $1 не постоји. Можда је корисник деблокиран.", - "ipb_blocked_as_range": "Грешка: ИП адреса $1 није директно блокирана и не може да се деблокира.\nОна је блокирана као део блокаде $2, која може бити деблокирана.", - "ip_range_invalid": "Неисправан распон ИП адреса.", + "ipb_blocked_as_range": "Грешка: IP адреса $1 није директно блокирана и не може да се деблокира.\nОна је блокирана као део блокаде $2, која може бити деблокирана.", + "ip_range_invalid": "Неисправан распон IP адреса.", "ip_range_toolarge": "Опсежна блокирања већа од /$1 нису дозвољена.", "proxyblocker": "Блокер посредника", "proxyblockreason": "Ваша ИП адреса је блокирана јер представља отворени посредник.\nОбратите се вашем добављачу интернет услуга или техничку подршку и обавестите их о овом озбиљном безбедносном проблему.", @@ -2506,7 +2506,7 @@ "thumbnail_invalid_params": "Неисправни параметри за минијатуру", "thumbnail_dest_directory": "Не могу да направим одредишну фасциклу", "thumbnail_image-type": "Врста слике није подржана", - "thumbnail_gd-library": "Недовршене поставке графичке библиотеке: недостаје функција $1", + "thumbnail_gd-library": "Недовршена подешавања графичке библиотеке: недостаје функција $1", "thumbnail_image-missing": "Датотека недостаје: $1", "import": "Увоз страница", "importinterwiki": "Увоз са другог викија", @@ -2628,7 +2628,7 @@ "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", @@ -3366,7 +3366,7 @@ "duplicate-defaultsort": "Упозорење: Подразумевани кључ сврставања „$2“ мења ранији подразумевани кључ сврставања „$1“.", "duplicate-displaytitle": "Упозорење: наслов за приказ „$2“ замениће постојећи „$1“.", "restricted-displaytitle": "Упозорење: Наслов за приказ „$1” је игнорисан пошто није еквивалентан стварном наслову странице.", - "version": "Верзија", + "version": "Издање", "version-extensions": "Инсталирана проширења", "version-skins": "Инсталиране теме", "version-specialpages": "Посебне странице", @@ -3387,7 +3387,7 @@ "version-ext-license": "Лиценца", "version-ext-colheader-name": "Екстензија", "version-skin-colheader-name": "Тема", - "version-ext-colheader-version": "Верзија", + "version-ext-colheader-version": "Издање", "version-ext-colheader-license": "Лиценца", "version-ext-colheader-description": "Опис", "version-ext-colheader-credits": "Аутори", @@ -3400,24 +3400,24 @@ "version-license-info": "Медијавики је слободан софтвер можете га редистрибуирати и/или модификовати под условима ГНУ-ове опште јавне лиценце верзија 2 или сваке следеће коју објави Задужбина за слободан софтвер.\n\nМедијавики се редистрибуира у нади да ће бити од користи, али БЕЗ ИКАКВЕ ГАРАНЦИЈЕ чак и без ПОДРАЗУМЕВАНЕ ГАРАНЦИЈЕ ФУНКЦИОНАЛНОСТИ или ПРИКЛАДНОСТИ ЗА ОДРЕЂЕНЕУ НАМЕНУ. Погледајте ГНУ-ову општу јавну лиценцу за више информација.\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": "Верзија", + "version-software-version": "Издање", "version-entrypoints": "Адресе улазне тачке", "version-entrypoints-header-entrypoint": "Улазна тачка", "version-entrypoints-header-url": "Адреса", "version-libraries": "Инсталиране библиотеке", "version-libraries-library": "Библиотека", - "version-libraries-version": "Верзија", + "version-libraries-version": "Издање", "version-libraries-license": "Лиценца", "version-libraries-description": "Опис", "version-libraries-authors": "Аутори", "redirect": "Преусмерење на датотеку, корисника, страницу, измену или дневник (ID)", - "redirect-summary": "Ова специјална страница преусмерава до датотеке (са датим именом датотеке), странице (са датим ID-ом измене или ID-ом странице), корисничке странице (са датим нумеричким корисничким ID-ом), или уноса у дневнику (са датим дневничким ID-ом). Употреба: [[{{#Special:Redirect}}/file/Example.jpg]], [[{{#Special:Redirect}}/page/64308]], [[{{#Special:Redirect}}/revision/328429]], [[{{#Special:Redirect}}/user/101]], or [[{{#Special:Redirect}}/logid/186]].", + "redirect-summary": "Ова посебна страница преусмерава до датотеке (са датим именом датотеке), странице (са датим ID-ом измене или ID-ом странице), корисничке странице (са датим нумеричким корисничким ID-ом), или уноса у дневнику (са датим дневничким ID-ом). Употреба: [[{{#Special:Redirect}}/file/Example.jpg]], [[{{#Special:Redirect}}/page/64308]], [[{{#Special:Redirect}}/revision/328429]], [[{{#Special:Redirect}}/user/101]], or [[{{#Special:Redirect}}/logid/186]].", "redirect-submit": "Иди", "redirect-lookup": "Тип вредности:", "redirect-value": "Вредност:", "redirect-user": "Кориснички ID", "redirect-page": "ID странице", - "redirect-revision": "Верзија странице", + "redirect-revision": "Измена странице", "redirect-file": "Назив датотеке", "redirect-not-exists": "Вредност није пронађена", "fileduplicatesearch": "Претрага дупликата", @@ -3527,6 +3527,7 @@ "compare-title-not-exists": "Наведени наслов не постоји.", "compare-revision-not-exists": "Наведена измена не постоји.", "diff-form": "Разлике", + "diff-form-submit": "Прикажи разлике", "permanentlink": "Стална веза", "dberr-problems": "Дошло је до техничких проблема.", "dberr-again": "Сачекајте неколико минута и поново учитајте страницу.", @@ -3602,7 +3603,7 @@ "logentry-newusers-create2": "$1 је {{GENDER:$2|отворио|отворила}} кориснички налог $3", "logentry-newusers-byemail": "$1 је {{GENDER:$2|отворио|отворила}} кориснички налог $3 и лозинка је послата на имејл", "logentry-newusers-autocreate": "Кориснички налог $1 је аутоматски {{GENDER:$2|отворен}}", - "logentry-protect-move_prot": "$1 је {{GENDER:$2|преместио|преместила}} поставке заштите са $4 на $3", + "logentry-protect-move_prot": "$1 је {{GENDER:$2|преместио|преместила}} подешавања заштите са $4 на $3", "logentry-protect-unprotect": "$1 je {{GENDER:$2|скинуо|скинула}} заштиту са странице $3", "logentry-protect-protect": "$1 је {{GENDER:$2|заштитио|заштитила}} $3 $4", "logentry-protect-protect-cascade": "$1 је {{GENDER:$2|заштитио|заштитила}} $3 $4 [преносива заштита]", @@ -3631,7 +3632,7 @@ "feedback-bugornote": "Ако сте спремни да детаљно опишете технички проблем, онда [$1 пријавите грешку].\nУ супротном, послужите се једноставним обрасцем испод. Ваш коментар ће стајати на страници „[$3 $2]“, заједно с корисничким именом и прегледачем који користите.", "feedback-cancel": "Откажи", "feedback-close": "Урађено", - "feedback-external-bug-report-button": "Пријави баг", + "feedback-external-bug-report-button": "Пријави грешку", "feedback-dialog-title": "Пошаљи повратну информацију", "feedback-error1": "Грешка: непрепознат резултат од АПИ-ја", "feedback-error2": "Грешка: уређивање није успело", @@ -3676,7 +3677,7 @@ "expandtemplates": "Замена шаблона", "expand_templates_intro": "Ова посебна страница узима викитекст и мења све шаблоне у њему рекурзивно.\nТакође мења функције парсера као што је {{#language:…}} и променљиве као што је {{CURRENTDAY}}. \nЗаправо практично све што се налази између витичастих заграда.", "expand_templates_title": "Назив контекста; за {{СТРАНИЦА}} итд.:", - "expand_templates_input": "Унос:", + "expand_templates_input": "Унос викитекста:", "expand_templates_output": "Резултат", "expand_templates_xml_output": "XML излаз", "expand_templates_html_output": "Сиров HTML излаз", @@ -3740,6 +3741,7 @@ "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": "До датума:", @@ -3783,9 +3785,13 @@ "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": "Уклањање акредитива", @@ -3793,9 +3799,12 @@ "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": "Одабрани наслов је невалидан.", + "gotointerwiki-invalid": "Одабрани наслов је неисправан.", "gotointerwiki-external": "Управо ћете да напустите пројекат {{SITENAME}} да бисте на засебном веб-сајту посетили [[$2]].\n\n'''[$1 Продужи на $1]'''", "undelete-cantedit": "Не можете повратити ову страницу јер немате дозволу да је уређујете.", "undelete-cantcreate": "Не можете повратити ову страницу јер нема постојеће странице са овим именом и немате дозволу да направите ову страницу.", diff --git a/languages/i18n/sr-el.json b/languages/i18n/sr-el.json index a4baeb5a4e..467e68b0a0 100644 --- a/languages/i18n/sr-el.json +++ b/languages/i18n/sr-el.json @@ -28,7 +28,8 @@ "Obsuser", "Zoranzoki21", "Prevodim", - "Bugoslav" + "Bugoslav", + "Acamicamacaraca" ] }, "tog-underline": "Podvlačenje veza:", @@ -1088,8 +1089,8 @@ "right-editmyuserjs": "uređivanje sopstvenih JavaScript datoteka", "right-viewmywatchlist": "vidi sopstveni spisak nadgledanja", "right-editmywatchlist": "uređivanje sopstvenog spiska nadgledanja; neke preduzete radnje će svejedno dodati stranice na spisak i bez ovog prava", - "right-viewmyprivateinfo": "Vidite svoje lične podatke (npr. imejl adresu, pravo ime)", - "right-editmyprivateinfo": "Уređivanje sopstvenih ličnih podataka (npr. imejl adresa, pravo ime)", + "right-viewmyprivateinfo": "vidite svoje lične podatke (npr. imejl adresu, pravo ime)", + "right-editmyprivateinfo": "uređivanje sopstvenih ličnih podataka (npr. imejl adresa, pravo ime)", "right-editmyoptions": "uređivanje sopstvenih podešavanja", "right-rollback": "brzo vraćanje izmena poslednjeg korisnika koji je menjao određenu stranicu", "right-markbotedits": "označavanje vraćenih izmena kao izmene bota", diff --git a/languages/i18n/sty.json b/languages/i18n/sty.json new file mode 100644 index 0000000000..9b40b5cdc2 --- /dev/null +++ b/languages/i18n/sty.json @@ -0,0 +1,630 @@ +{ + "@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": "Сес сураған ҡесмәт пит йуҡ.\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": "Саҡлыҡ! Сес сайтта теркәлмәтегес. Әгәр тә сес төрлө төсәтеүләр ҡылсағыс, сеснеңке IP-адресығыс пашҡаларға күренеп торор. Әгәр тә Сес [$1 керсәгез] йә [$2 ҡулланыуцы йасманы пултырсағыс], сеснең төсәтеүләр ҡулланыуцы йасмағысҡа пәйле пулыр, шалай уҡ пашҡа өстөннөкләр тыуыр.", + "blockedtext": "Сеснең исәп йасмағыс йә IP адресығыс тыйылған.\n* Тыйған администратор: $1.\nКүргәселгән сәбәп: $2.\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Пы уйлап ҡарау пит исәп йасыуны ҡылтырмаған йә аны ҡулланмайтығын аноним ҡатнашыуцыныңҡы пите. Ҡулланыуцыны таныу өцөн аныңҡы IP-адресы ҡулланылаты. Әгәр сес аноним ҡулланыуцы пулсағыс, сескә йебәрелмәгән ҡатлар алтым тисәгес (пер IP-адрес кән ҡулланыуцыларта пулғалы мөмкин), пашҡа мынтайын аңнашылмауцылыҡлар килеп цыҡмасын өцөн, системаға керең йә теркәлең.", + "noarticletext": "Ҡәсерге уаҡытта пы питтә текст йуҡ. Сес [[Special:Search/{{PAGENAME}}|пы исем кергән пашҡа мәҡәләләрне]], [{{fullurl:{{#Special:Log}}|page={{FULLPAGENAMEE}}}} туры килгән йасмаларны] таба йә '''[{{fullurl:{{FULLPAGENAME}}|action=edit}} шантайын уҡ исемле йаңа питне ҡыла]''' аласыс.", + "noarticletext-nopermission": "Ҡәсерге уаҡытта пы питтә текст йуҡ. Сес пашҡа питләртә [[Special:Search/{{PAGENAME}}|пы исемне]] йә [{{fullurl:{{#Special:Log}}|page={{FULLPAGENAMEE}}}} журналтағы йасмаларны] эстәй аласыс. Сескә пит йасағалы рөҡсәт пирелмәгән.", + "userpage-userdoesnotexist-view": "«$1» исемле исәп йасма йуҡ.", + "clearyourcache": "Искәрмә: Питне саҡлағаннан суң пашҡартыуларығыс күренер өцөн, браузерығысныңҡы кэшын тасартҡалы кәрәк пулыр.\n* Firefox / Safari: Shift төймәгә пасып, йебәрмәйен, Йаңартҡалы төймәгә пасың, йә Ctrl-F5 йә Ctrl-R (Mac-та ⌘-R) төймәләргә пасың\n* Google Chrome: Ctrl-Shift-R төймәгә пасың (Mac-та ⌘-Shift-R)\n* Internet Explorer: Ctrl төймәгә пасып, йебәрмәйен, Йаңартҡалытөймәгә пасың, йә Ctrl-F5 төймәгә пасың\n* Opera: Ҡораллар → Ҡоролошлар (Mac-та Opera → Ҡоролошлар) пүлеккә күцең, суңынан Ҡауапсыслыҡ → Кереүләр тариҡны тасартыу → Рәсемнәр кэшлау менюта кэш тасартыуны сайлаң", + "previewnote": "Онотмаң, пы алттан ҡарап цығыу ғына.\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}}.
-ға пасың. Аңнатмалар: ({{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": "«[[:$1]]» Вики-проектта пит йасағалы! {{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|$3 нәтижәтән $1| $3 нәтижәләртән $1 — $2}}", + "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": "Аңнатма:", + "recentchanges-legend-newpage": "{{int:recentchanges-label-newpage}} (шалай уҡ [[Special:NewPages|йаңа питләр күцермәлеген]] ҡараң)", + "rcfilters-filterlist-title": "Фильтрлар", + "rcfilters-filterlist-noresults": "Иц фильтр табылматы", + "rcnotefrom": "Астта $3, $4 -ға туры килгән {{PLURAL:$5|пашҡартыулар күргәселгән}} ($1 артыҡ түгел).", + "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": "Сеснең суңҡы пашҡартыулартан суң пашҡарған питләр ҡалын шрифт пелән күргәселгән.", + "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": "Спамҡа ҡаршы тикшереү. Мыны ТУЛТЫРМАҢ!", + "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": "Көтөлмәгән тамыр пит" +} diff --git a/languages/i18n/sv.json b/languages/i18n/sv.json index 0143b9fe34..c5855eae79 100644 --- a/languages/i18n/sv.json +++ b/languages/i18n/sv.json @@ -1896,7 +1896,7 @@ "doubleredirects": "Dubbla omdirigeringar", "doubleredirectstext": "Det här är en lista över sidor som omdirigerar till andra omdirigeringssidor. \nVarje rad innehåller länkar till den första och andra omdirigeringssidan, samt till målet för den andra omdirigeringen. Målet för den andra omdirigeringen är ofta den \"riktiga\" sidan som den första omdirigeringen egentligen ska leda till.\nÖverstrukna poster har åtgärdats.", "double-redirect-fixed-move": "[[$1]] har flyttats.\nDen uppdaterades automatiskt och är nu en omdirigering till [[$2]].", - "double-redirect-fixed-maintenance": "Fixar automatiskt dubbel omdirigering från [[$1]] till [[$2]] i ett underhållsjobb.", + "double-redirect-fixed-maintenance": "Fixar automatiskt dubbel omdirigering från [[$1]] till [[$2]] i ett underhållsjobb", "double-redirect-fixer": "Omdirigeringsrättaren", "brokenredirects": "Trasiga omdirigeringar", "brokenredirectstext": "Följande omdirigeringar länkar till ej existerande sidor:", @@ -3630,7 +3630,7 @@ "diff-form": "Skillnader", "diff-form-oldid": "Gammalt versions-ID (valfritt)", "diff-form-revid": "Versions-ID för diff", - "diff-form-submit": "Visa differenser", + "diff-form-submit": "Visa skillnad", "permanentlink": "Permanent länk", "permanentlink-revid": "Sidversions-ID", "permanentlink-submit": "Gå till sidversion", diff --git a/languages/i18n/te.json b/languages/i18n/te.json index 372ae46d1d..696bcfc502 100644 --- a/languages/i18n/te.json +++ b/languages/i18n/te.json @@ -388,7 +388,7 @@ "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": "మీ వాడుకరి పేరును ఇవ్వండి", diff --git a/languages/i18n/tg-cyrl.json b/languages/i18n/tg-cyrl.json index c9845d6699..82a51cda13 100644 --- a/languages/i18n/tg-cyrl.json +++ b/languages/i18n/tg-cyrl.json @@ -223,7 +223,7 @@ "currentevents": "Рӯйдодҳои кунунӣ", "currentevents-url": "Лоиҳа:Рӯйдодҳои кунунӣ", "disclaimers": "Такзибнома", - "disclaimerpage": "Project:Такзибномаи умумӣ", + "disclaimerpage": "Википедия:Такзибномаи умумӣ", "edithelp": "Роҳнамои вироиш", "mainpage": "Саҳифаи аслӣ", "mainpage-description": "Саҳифаи аслӣ", diff --git a/languages/i18n/th.json b/languages/i18n/th.json index 9ba7104687..b9bb62b8c2 100644 --- a/languages/i18n/th.json +++ b/languages/i18n/th.json @@ -3379,6 +3379,18 @@ "duration-decades": "$1 ทศวรรษ", "duration-centuries": "$1 ศตวรรษ", "duration-millennia": "$1 สหัสวรรษ", + "limitreport-title": "ข้อมูลบันทึกตัวแจงส่วน:", + "limitreport-cputime": "การใช้เวลาของซีพียู", + "limitreport-cputime-value": "$1 วินาที", + "limitreport-walltime": "การใช้เวลาจริง", + "limitreport-walltime-value": "$1 วินาที", + "limitreport-ppvisitednodes": "จำนวนปมที่เข้าชมแล้วของตัวประมวลก่อน", + "limitreport-ppgeneratednodes": "จำนวนปมที่สร้างแล้วของตัวประมวลก่อน", + "limitreport-postexpandincludesize": "ขนาดเมื่อรวมขยายแล้ว", + "limitreport-postexpandincludesize-value": "$1/$2 ไบต์", + "limitreport-templateargumentsize": "ขนาดอาร์กิวเมนต์แม่แบบ", + "limitreport-templateargumentsize-value": "$1/$2 ไบต์", + "limitreport-expansiondepth": "ความลึกการขยายสูงสุด", "expandtemplates": "ขยายแม่แบบ", "expand_templates_output": "ผลลัพธ์", "expand_templates_ok": "ตกลง", @@ -3479,6 +3491,8 @@ "log-action-filter-suppress-event": "การระงับปูม", "log-action-filter-upload-upload": "อัปโหลดใหม่", "log-action-filter-upload-overwrite": "อัปโหลดใหม่", + "edit-error-short": "ข้อผิดพลาด: $1", + "edit-error-long": "ข้อผิดพลาด: $1", "revid": "รุ่นแก้ไข $1", "pageid": "เลขประจำหน้า $1", "gotointerwiki": "กำลังออกจาก {{SITENAME}}", diff --git a/languages/i18n/tl.json b/languages/i18n/tl.json index 8269f94c27..2e8b8e99e5 100644 --- a/languages/i18n/tl.json +++ b/languages/i18n/tl.json @@ -25,7 +25,7 @@ "LR Guanzon" ] }, - "tog-underline": "Pagsasalungguhit ng link:", + "tog-underline": "Pagsasalungguhit ng kawing:", "tog-hideminor": "Itago ang mga maliliit na pagbabago mula sa mga huling pagbabago", "tog-hidepatrolled": "Itago ang mga napatrolyang pagbabago mula sa mga huling pagbabago", "tog-newpageshidepatrolled": "Itago ang mga napatrolyang pahina mula talaan ng bagong pahina", @@ -188,7 +188,7 @@ "history_small": "kasaysayan", "updatedmarker": "isinapanahon mula noong huli kong pagdalaw", "printableversion": "Bersiyong maililimbag", - "permalink": "Permanenteng link", + "permalink": "Permanenteng kawing", "print": "Ilimbag", "view": "Tingnan", "view-foreign": "Tingnan sa $1", @@ -261,10 +261,10 @@ "pagetitle": "$1 - {{SITENAME}}", "pagetitle-view-mainpage": "{{SITENAME}}", "backlinksubtitle": "← $1", - "retrievedfrom": "Ikinuha mula sa \"$1\"", - "youhavenewmessages": "Mayroon kang $1 ($2).", - "youhavenewmessagesfromusers": "{{PLURAL:$4|Mayroon kang}} $1 magmula sa {{PLURAL:$3|ibang tagagamit|$3 mga tagagamit}} ($2).", - "youhavenewmessagesmanyusers": "Mayroon kang $1 magmula sa maraming mga tagagamit ($2).", + "retrievedfrom": "Kinuha mula sa \"$1\"", + "youhavenewmessages": "{{PLURAL:$3|Mayroon kang}} $1 ($2).", + "youhavenewmessagesfromusers": "{{PLURAL:$4|Mayroon kang}} $1 mula sa {{PLURAL:$3|ibang tagagamit|$3 mga tagagamit}} ($2).", + "youhavenewmessagesmanyusers": "Mayroon kang $1 mula sa maraming tagagamit ($2).", "newmessageslinkplural": "{{PLURAL:$1|isang bagong mensahe|999=bagong mensahe}}", "newmessagesdifflinkplural": "huling {{PLURAL:$1|pagbabago|999=mga pagbabago}}", "youhavenewmessagesmulti": "Mayroon kang mga bagong mensahe sa $1", @@ -466,7 +466,7 @@ "nosuchusershort": "Walang tagagamit na may pangalang \"$1\".\nPakitingnan ang iyong pagbabaybay.", "nouserspecified": "Kailangang tukuyin mo ang isang pangalang pantagagamit.", "login-userblocked": "Hinarang ang tagagamit na ito. Hindi pinahihintulutan ang paglalagda.", - "wrongpassword": "Mali ang ipinasok na password.\nPakisubok muli.", + "wrongpassword": "Mali ang ipinasok na password o pangalan ng tagagamit.\nPakisubok muli.", "wrongpasswordempty": "Walang laman ang ipinasok na password.\nPakisubok muli.", "passwordtooshort": "Ang mga password ay dapat mayroong {{PLURAL:$1|1 panitik|$1 panitik}} (karakter).", "passwordtoolong": "Ang mga password ay hindi maaaring mas mahaba sa {{PLURAL:$1|1 panitik|$1 panitik}}.", @@ -590,7 +590,7 @@ "anoneditwarning": "Babala:
Hindi ka nakalagda.\nMakikita ng publiko ang iyong IP address kung gagawa ka ng mga pagbabago. Kung [$1 mag-login] ka o [$2 lumikha ng account], maiuugnay ang iyong mga pagbabago sa iyong account, kasama ang ibang pakinabang.", "anonpreviewwarning": "''Hindi ka nakalagda. Itatala sa inyong pagtatala ang inyong direksiyong IP sa kasaysayan ng pagbabago ng pahinang ito.''", "missingsummary": "'''Paalala:''' Hindi ka nagbigay ng buod ng pagbabago.\nKapag pinindot mo uli ang Sagip, masasagip ang pagbabago mo na wala nito.", - "missingcommenttext": "Magbigay ng isang kumento/puna sa ibaba.", + "missingcommenttext": "Maaaring magbigay ng komento.", "missingcommentheader": "'''Paalala:''' Hindi ka nagbigay ng isang paksa/paulo para sa punang ito.\nKapag pinindot mo uli ang \"$1\", masasagip ang pagbabago mo na wala nito.", "summary-preview": "Paunang tingin sa buod:", "subject-preview": "Paunang tingin sa paksa:", @@ -630,7 +630,7 @@ "continue-editing": "Pumunta sa pook ng pamamatnugot", "previewconflict": "Ipinamamalas ng paunang tinging ito ang teksto sa loob ng pangitaas na pook-patnugutan ng teksto ayon sa lilitaw na anyo nito kapag pinili mo ang pagsagip.", "session_fail_preview": "Paumanhin! Hindi namin maproseso ang iyong pagbabago hinggil sa pagkawala ng datos ng sesyon.\n\nIkaw ay maaaring nailagda palabas. Maaaring patunayan na ikaw ay nakalagda pa rin at subukang muli.\nKung hindi ito gumana, subukang [[Special:UserLogout|umalis sa pagkalagda]] at bumalik muli, at tingnan kung ang iyong browser ay pumapayag sa mga cookie mula sa site na ito.", - "session_fail_preview_html": "'''Paumanhin! Hindi namin maproseso ang iyong pagbabago hinggil sa pagkawala ng datos ng sesyon.'''\n\n''Dahil naka-andar ang hilaw na HTML sa {{SITENAME}}, nakatago ang paunang tingin bilang pag-iingat sa mga paglusob ng JavaScript.''\n\n'''Kung lehitimong pagbabago ito, paki-ulit muli.'''\nKung hindi pa rin ito gumagana, subukang [[Special:UserLogout|mag-logout]] at mag-login muli.", + "session_fail_preview_html": "Paumanhin! Hindi namin maproseso ang iyong pagbabago hinggil sa pagkawala ng datos ng sesyon.\n\nDahil naka-andar ang hilaw na HTML sa {{SITENAME}}, nakatago ang paunang tingin bilang pag-iingat sa mga paglusob ng JavaScript.\n\nKung lehitimong pagbabago ito, paki-ulit muli.\nKung hindi pa rin ito gumagana, subukang [[Special:UserLogout|mag-logout]] at mag-login muli, at pakitingnan kung pinapayagan ng iyong browser ang mga cookie mula sa site na ito.", "token_suffix_mismatch": "'''Hindi tinanggap ang iyong pagbabago dahil sinira ng kliyente ang mga karakter na bantas sa ''token'' ng mamatnugot.\nTinanggihan ang pagbabago upang maiwasan ang korapsyon ng teksto ng artikulo.\nKadalasang nangyayari ito kapag gumagamit ka ng masurot na serbisyo ng hindi-nakikilalang apoderadong (''anonymous proxy'') nasa web.", "edit_form_incomplete": "'''Ilan sa mga bahagi ng pormularyong pampatnugot ay hindi nakarating sa tagapaghain; suriing muli na ang iyong mga pagbabago ay buo at subukang muli.'''", "editing": "Binabago ang $1", diff --git a/languages/i18n/tr.json b/languages/i18n/tr.json index aaf61f63bc..d0d8ceb5d4 100644 --- a/languages/i18n/tr.json +++ b/languages/i18n/tr.json @@ -539,7 +539,7 @@ "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.", @@ -1261,19 +1261,23 @@ "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", @@ -1287,8 +1291,10 @@ "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", @@ -1333,9 +1339,16 @@ "recentchanges-legend-heading": "Gösterge:", "recentchanges-legend-newpage": "{{int:recentchanges-label-newpage}} (ayrıca [[Special:NewPages|yeni sayfalar listesine]] bakınız)", "recentchanges-submit": "Göster", + "rcfilters-other-review-tools": "Diğer inceleme araçları", "rcfilters-group-results-by-page": "Sayfalandırılmış grup sonuçları", "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.", @@ -1370,8 +1383,8 @@ "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", @@ -1393,6 +1406,9 @@ "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...", diff --git a/languages/i18n/wa.json b/languages/i18n/wa.json index 26fdfb2f75..3b13ff3041 100644 --- a/languages/i18n/wa.json +++ b/languages/i18n/wa.json @@ -19,19 +19,21 @@ "tog-extendwatchlist": "Ragrandi l' djivêye po mostrer tos les candjmints, nén seulmint les dierins", "tog-usenewrc": "Relére par pådje dins les dierins candjmints et l' djivêye des shuvous (i fåt JavaScript)", "tog-numberheadings": "Limerotaedje otomatike des tites", - "tog-showtoolbar": "Mostrer l' bår d' usteyes e môde candjmint (JavaScript)", - "tog-editondblclick": "Candjî les pådjes avou on dobe-clitch (JavaScript)", - "tog-editsectiononrightclick": "Candjî les seccions avou on dobe-clitch sol tite (JavaScript)", - "tog-watchcreations": "Mete les pådjes ki dj' askepeye dins l' djivêye des pådjes shuvowes", - "tog-watchdefault": "Shuve les årtikes ki dj' fwai ou ki dj' candje", - "tog-watchmoves": "Radjouter a m' djivêye des shuvous les pådjes ki dji displaece", - "tog-watchdeletion": "Radjouter a m' djivêye des shuvous les pådjes ki dji disface", + "tog-showtoolbar": "Mostrer l' bår d' usteyes e môde candjmint", + "tog-editondblclick": "Candjî les pådjes avou on dobe-clitch", + "tog-editsectiononrightclick": "Candjî les seccions avou on dobe-clitch so les tites", + "tog-watchcreations": "Radjouter a m' djivêye des shuvous les pådjes ki dj' askepeye et les fitchîs ki dj' eberwete", + "tog-watchdefault": "Radjouter a m' djivêye des shuvous les pådjes et les fitchîs ki dj' candje", + "tog-watchmoves": "Radjouter a m' djivêye des shuvous les pådjes et les fitchîs ki dji displaece", + "tog-watchdeletion": "Radjouter a m' djivêye des shuvous les pådjes et les fitchîs ki dji disface", + "tog-watchuploads": "Radjouter a m' djivêye des shuvous les fitchîs ki dj' eberwete", + "tog-watchrollback": "Radjouter a m' djivêye des shuvous les pådjes wice ki dj' a disfé on candjmint", "tog-minordefault": "Prémete mes candjmints come mineurs", "tog-previewontop": "Prévey l' årtike å dzeu del boesse d' aspougnaedje", "tog-previewonfirst": "Prévey l' årtike å prumî candjmint", - "tog-enotifwatchlistpages": "M' emiler cwand ene pådje shuvowe candje", - "tog-enotifusertalkpages": "M' emiler cwand l' pådje di copene da minne candje", - "tog-enotifminoredits": "M' emiler eto po les ptits candjmints", + "tog-enotifwatchlistpages": "M' emiler cwand ene pådje u on fitchî d' èm djivêye des shuvous candje", + "tog-enotifusertalkpages": "M' emiler cwand m' pådje di copene da minne candje", + "tog-enotifminoredits": "M' emiler eto po les ptits candjmints des pådjes u des fitchîs", "tog-enotifrevealaddr": "Mostrer mi adresse emile dins les emiles di notifiaedje", "tog-shownumberswatching": "Mostrer l' nombe d' uzeus ki shuvèt l' pådje", "tog-oldsig": "Siné pol moumint:", @@ -284,6 +286,7 @@ "welcomeuser": "Bénvnowe, $1!", "yourname": "Vosse no d' elodjaedje:", "userlogin-yourname": "No d' uzeu", + "userlogin-yourname-ph": "Tapez vosse no d' uzeu", "yourpassword": "Vosse sicret", "userlogin-yourpassword": "Sicret", "yourpasswordagain": "Ritapez vosse sicret", @@ -732,7 +735,7 @@ "rightslog": "Djournå des droets des uzeus", "rightslogtext": "Çouchal, c' est on djournå des candjmints des droets des uzeus.", "action-read": "lére cisse pådje ci", - "action-edit": "candjî l' pådje", + "action-edit": "candjî cisse pådje ci", "action-createpage": "ahiver des pådjes", "action-createtalk": "ahiver des pådjes di copinaedje", "action-createaccount": "ahiver ci conte d' uzeu ci", @@ -757,6 +760,7 @@ "action-protect": "candjî les liveas d' protedjaedje del pådje", "action-autopatrol": "aveur vosse candjmint marké come ricoridjî", "nchanges": "$1 {{PLURAL:$1|candjmint|candjmints}}", + "enhancedrc-history": "Istwere", "recentchanges": "Dierins candjmints", "recentchanges-legend": "Tchuzes po les dierins candjmints", "recentchanges-summary": "Shuvoz chal les dierins candjmints k' i gn a yeu dsu {{SITENAME}}.", @@ -885,6 +889,7 @@ "uploadnewversion-linktext": "Eberweter ene nouve modêye di ci fitchî ci", "shared-repo-from": "vént d' $1", "shared-repo": "on depot pårtaedjî", + "upload-disallowed-here": "Vos n' ploz nén språtchî ci fitchî ci.", "filerevert": "Rimete come divant $1", "filerevert-legend": "Rapexhî l' fitchî", "filerevert-intro": "Vos estoz k' alez rapexhî l' fitchî [[Media:$1|$1]] al [$4 modêye do $3, a $2].", @@ -1163,6 +1168,7 @@ "contributions": "Ovraedjes di l' {{GENDER:$1|uzeu|uzeuse}}", "contributions-title": "Djivêye des ovraedjes di l' {{GENDER:$1|uzeu|uzeuse}} $1", "mycontris": "Mi ovraedje", + "anoncontribs": "Mi ovraedje", "contribsub2": "Po l' uzeu $1 ($2)", "nocontribs": "Nou candjmint di trové ki corespondreut a ç' critere la.", "uctop": "(dierinne)", @@ -1640,7 +1646,7 @@ "feedback-message": "Messaedje", "feedback-subject": "Sudjet", "feedback-submit": "Evoyî", - "searchsuggest-search": "Cweri", + "searchsuggest-search": "Cweri so {{SITENAME}}", "searchsuggest-containing": "ki contént...", "api-error-emptypage": "C' est nén permetou d' ahiver ene novele pådje et l' leyî vude.", "api-error-stashfailed": "Aroke divintrinne : li sierveu a pierdou les dnêyes provizweres", diff --git a/languages/i18n/yi.json b/languages/i18n/yi.json index d3fa9bea22..5ccc507b65 100644 --- a/languages/i18n/yi.json +++ b/languages/i18n/yi.json @@ -3049,6 +3049,8 @@ "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": "טאַג נאָמען", diff --git a/languages/i18n/zh-hans.json b/languages/i18n/zh-hans.json index dfcb1a3daf..a28c4577a4 100644 --- a/languages/i18n/zh-hans.json +++ b/languages/i18n/zh-hans.json @@ -796,6 +796,7 @@ "postedit-confirmation-created": "页面已创建。", "postedit-confirmation-restored": "页面已恢复。", "postedit-confirmation-saved": "您的编辑已保存。", + "postedit-confirmation-published": "您的编辑已发布。", "edit-already-exists": "不可以建立一个新页面。\n它已经存在。", "defaultmessagetext": "默认消息文本", "content-failed-to-parse": "未能将 $2 内容转换为 $1:$3", @@ -1725,7 +1726,7 @@ "lockmanager-fail-closelock": "无法关闭“$1”的锁文件。", "lockmanager-fail-deletelock": "无法删除“$1”的锁文件。", "lockmanager-fail-acquirelock": "无法为“$1”获取锁。", - "lockmanager-fail-openlock": "无法打开“$1”的锁文件。", + "lockmanager-fail-openlock": "无法打开“$1”的锁定文件。请确保您的上传目录正确配置,并且您的web服务器有权限写入至那个目录。参见https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:$wgUploadDirectory获取更多信息。", "lockmanager-fail-releaselock": "无法为“$1”释放锁。", "lockmanager-fail-db-bucket": "不能在$1池中联系到足够锁数据库。", "lockmanager-fail-db-release": "不能在数据库$1上释放锁。", diff --git a/maintenance/benchmarks/Benchmarker.php b/maintenance/benchmarks/Benchmarker.php index ffb8cb353f..e1eef07e07 100644 --- a/maintenance/benchmarks/Benchmarker.php +++ b/maintenance/benchmarks/Benchmarker.php @@ -26,6 +26,8 @@ * @ingroup Benchmark */ +use Wikimedia\RunningStat; + // @codeCoverageIgnoreStart require_once __DIR__ . '/../Maintenance.php'; // @codeCoverageIgnoreEnd @@ -68,7 +70,7 @@ abstract class Benchmarker extends Maintenance { } // Run benchmarks - $times = []; + $stat = new RunningStat(); for ( $i = 0; $i < $count; $i++ ) { $t = microtime( true ); call_user_func_array( $bench['function'], $bench['args'] ); @@ -76,20 +78,8 @@ abstract class Benchmarker extends Maintenance { if ( $verbose ) { $this->verboseRun( $i ); } - $times[] = $t; - } - - // Collect metrics - sort( $times, SORT_NUMERIC ); - $min = $times[0]; - $max = end( $times ); - if ( $count % 2 ) { - $median = $times[ ( $count - 1 ) / 2 ]; - } else { - $median = ( $times[$count / 2] + $times[$count / 2 - 1] ) / 2; + $stat->addObservation( $t ); } - $total = array_sum( $times ); - $mean = $total / $count; // Name defaults to name of called function if ( is_string( $key ) ) { @@ -108,12 +98,13 @@ abstract class Benchmarker extends Maintenance { $this->addResult( [ 'name' => $name, - 'count' => $count, - 'total' => $total, - 'min' => $min, - 'median' => $median, - 'mean' => $mean, - 'max' => $max, + 'count' => $stat->getCount(), + // Get rate per second from mean (in ms) + 'rate' => $stat->getMean() == 0 ? INF : ( 1.0 / ( $stat->getMean() / 1000.0 ) ), + 'total' => $stat->getMean() * $stat->getCount(), + 'mean' => $stat->getMean(), + 'max' => $stat->max, + 'stddev' => $stat->getStdDev(), 'usage' => [ 'mem' => memory_get_usage( true ), 'mempeak' => memory_get_peak_usage( true ), @@ -137,12 +128,15 @@ abstract class Benchmarker extends Maintenance { public function addResult( $res ) { $ret = sprintf( "%s\n %' 6s: %d\n", $res['name'], - 'times', + 'count', $res['count'] ); - - foreach ( [ 'total', 'min', 'median', 'mean', 'max' ] as $metric ) { - $ret .= sprintf( " %' 6s: %6.2fms\n", + $ret .= sprintf( " %' 6s: %8.1f/s\n", + 'rate', + $res['rate'] + ); + foreach ( [ 'total', 'mean', 'max', 'stddev' ] as $metric ) { + $ret .= sprintf( " %' 6s: %8.2fms\n", $metric, $res[$metric] ); diff --git a/maintenance/benchmarks/benchmarkSanitizer.php b/maintenance/benchmarks/benchmarkSanitizer.php new file mode 100644 index 0000000000..c264750b6d --- /dev/null +++ b/maintenance/benchmarks/benchmarkSanitizer.php @@ -0,0 +1,99 @@ +addDescription( 'Benchmark for Sanitizer methods.' ); + $this->addOption( 'method', 'One of "validateEmail", "encodeAttribute", ' + . '"safeEncodeAttribute", "removeHTMLtags", or "stripAllTags". ' + . 'Default: (All)', false, true ); + } + + public function execute() { + $textWithHtmlSm = 'Before and another word.'; + $textWithHtmlLg = str_repeat( + // 28K (28 chars * 1000) + wfRandomString( 3 ) . ' ' . wfRandomString( 5 ) . ' ' . wfRandomString( 7 ), + 1000 + ); + + $method = $this->getOption( 'method' ); + $benches = []; + + if ( !$method || $method === 'validateEmail' ) { + $benches['Sanitizer::validateEmail (valid)'] = function () { + Sanitizer::validateEmail( 'user@example.org' ); + }; + $benches['Sanitizer::validateEmail (invalid)'] = function () { + Sanitizer::validateEmail( 'username@example! org' ); + }; + } + if ( !$method || $method === 'encodeAttribute' ) { + $benches['Sanitizer::encodeAttribute (simple)'] = function () { + Sanitizer::encodeAttribute( 'simple' ); + }; + $benches['Sanitizer::encodeAttribute (special)'] = function () { + Sanitizer::encodeAttribute( ":'\"\n https://example" ); + }; + } + if ( !$method || $method === 'safeEncodeAttribute' ) { + $benches['Sanitizer::safeEncodeAttribute (simple)'] = function () { + Sanitizer::safeEncodeAttribute( 'simple' ); + }; + $benches['Sanitizer::safeEncodeAttribute (special)'] = function () { + Sanitizer::safeEncodeAttribute( ":'\"\n https://example" ); + }; + } + if ( !$method || $method === 'removeHTMLtags' ) { + $sm = strlen( $textWithHtmlSm ); + $lg = round( strlen( $textWithHtmlLg ) / 1000 ) . 'K'; + $benches["Sanitizer::removeHTMLtags (input: $sm)"] = function () use ( $textWithHtmlSm ) { + Sanitizer::removeHTMLtags( $textWithHtmlSm ); + }; + $benches["Sanitizer::removeHTMLtags (input: $lg)"] = function () use ( $textWithHtmlLg ) { + Sanitizer::removeHTMLtags( $textWithHtmlLg ); + }; + } + if ( !$method || $method === 'stripAllTags' ) { + $sm = strlen( $textWithHtmlSm ); + $lg = round( strlen( $textWithHtmlLg ) / 1000 ) . 'K'; + $benches["Sanitizer::stripAllTags (input: $sm)"] = function () use ( $textWithHtmlSm ) { + Sanitizer::stripAllTags( $textWithHtmlSm ); + }; + $benches["Sanitizer::stripAllTags (input: $lg)"] = function () use ( $textWithHtmlLg ) { + Sanitizer::stripAllTags( $textWithHtmlLg ); + }; + } + + $this->bench( $benches ); + } +} + +$maintClass = BenchmarkSanitizer::class; +require_once RUN_MAINTENANCE_IF_MAIN; diff --git a/maintenance/cleanupPreferences.php b/maintenance/cleanupPreferences.php index a55b539c67..a21bc73704 100644 --- a/maintenance/cleanupPreferences.php +++ b/maintenance/cleanupPreferences.php @@ -1,6 +1,6 @@ + * @author Chad * @see https://phabricator.wikimedia.org/T32976 * @ingroup Maintenance */ @@ -26,25 +27,132 @@ 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__ ); + } + } } } diff --git a/maintenance/cleanupTitles.php b/maintenance/cleanupTitles.php index 8c782d9964..5b441f90f1 100644 --- a/maintenance/cleanupTitles.php +++ b/maintenance/cleanupTitles.php @@ -137,7 +137,8 @@ class TitleCleanup extends TableCleanup { || $title->getInterwiki() || !$title->canExist() ) { - if ( $title->getInterwiki() || !$title->canExist() ) { + $titleImpossible = $title->getInterwiki() || !$title->canExist(); + if ( $titleImpossible ) { $prior = $title->getPrefixedDBkey(); } else { $prior = $title->getDBkey(); @@ -155,7 +156,12 @@ class TitleCleanup extends TableCleanup { $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; diff --git a/maintenance/resources/update-oojs-ui.sh b/maintenance/resources/update-oojs-ui.sh index 799af4ca47..d1e6496dce 100755 --- a/maintenance/resources/update-oojs-ui.sh +++ b/maintenance/resources/update-oojs-ui.sh @@ -1,6 +1,6 @@ #!/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 @@ -20,7 +20,7 @@ git checkout composer.json 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 @@ -31,10 +31,10 @@ else 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 @@ -68,15 +68,15 @@ rm -rf "$NPM_DIR" cd $REPO_DIR COMMITMSG=$(cat < [ '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' => [ @@ -50,16 +50,16 @@ return [ ], // 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 */ @@ -105,7 +105,7 @@ return [ ], // 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' ], @@ -832,7 +832,7 @@ return [ /* MediaWiki */ 'mediawiki' => [ - 'class' => 'ResourceLoaderRawFileModule', + 'class' => ResourceLoaderRawFileModule::class, // Keep in sync with maintenance/jsduck/eg-iframe.html 'scripts' => [ 'resources/src/mediawiki/mediawiki.js', @@ -1017,7 +1017,7 @@ return [ ], 'mediawiki.ForeignApi' => [ 'targets' => [ 'desktop', 'mobile' ], - 'class' => 'ResourceLoaderForeignApiModule', + 'class' => ResourceLoaderForeignApiModule::class, // Additional dependencies generated dynamically 'dependencies' => 'mediawiki.ForeignApi.core', ], @@ -1227,7 +1227,7 @@ return [ ] ], 'mediawiki.ForeignStructuredUpload.config' => [ - 'class' => 'ResourceLoaderUploadDialogModule', + 'class' => ResourceLoaderUploadDialogModule::class, ], 'mediawiki.ForeignStructuredUpload' => [ 'scripts' => 'resources/src/mediawiki/mediawiki.ForeignStructuredUpload.js', @@ -1366,7 +1366,7 @@ return [ ] ], 'mediawiki.util' => [ - 'class' => 'ResourceLoaderMediaWikiUtilModule', + 'class' => ResourceLoaderMediaWikiUtilModule::class, 'scripts' => 'resources/src/mediawiki/mediawiki.util.js', 'dependencies' => [ 'jquery.accessKeyLabel', @@ -1391,7 +1391,7 @@ return [ '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', @@ -1508,6 +1508,7 @@ return [ 'postedit-confirmation-created', 'postedit-confirmation-restored', 'postedit-confirmation-saved', + 'postedit-confirmation-published', ], ], 'mediawiki.action.view.redirect' => [ @@ -1596,7 +1597,7 @@ return [ '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', @@ -1616,10 +1617,10 @@ return [ ) ], - 'mediawiki.language.names' => [ 'class' => 'ResourceLoaderLanguageNamesModule' ], + 'mediawiki.language.names' => [ 'class' => ResourceLoaderLanguageNamesModule::class ], 'mediawiki.language.specialCharacters' => [ - 'class' => 'ResourceLoaderSpecialCharacterDataModule' + 'class' => ResourceLoaderSpecialCharacterDataModule::class ], /* MediaWiki Libs */ @@ -2724,7 +2725,7 @@ return [ // 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', @@ -2744,7 +2745,7 @@ return [ ], // 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 @@ -2754,7 +2755,7 @@ return [ ], // 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' => [ @@ -2779,7 +2780,7 @@ return [ ], // Toolbar and tools module. 'oojs-ui-toolbars' => [ - 'class' => 'ResourceLoaderOOUIFileModule', + 'class' => ResourceLoaderOOUIFileModule::class, 'scripts' => 'resources/lib/oojs-ui/oojs-ui-toolbars.js', 'themeStyles' => 'toolbars', 'dependencies' => [ @@ -2795,7 +2796,7 @@ return [ ], // Windows and dialogs module. 'oojs-ui-windows' => [ - 'class' => 'ResourceLoaderOOUIFileModule', + 'class' => ResourceLoaderOOUIFileModule::class, 'scripts' => 'resources/lib/oojs-ui/oojs-ui-windows.js', 'themeStyles' => 'windows', 'dependencies' => [ @@ -2814,71 +2815,71 @@ return [ ], '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', ], ]; diff --git a/resources/src/jquery/jquery.textSelection.js b/resources/src/jquery/jquery.textSelection.js index 522e95b871..394b42f0d9 100644 --- a/resources/src/jquery/jquery.textSelection.js +++ b/resources/src/jquery/jquery.textSelection.js @@ -2,66 +2,11 @@ * 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 @@ -80,21 +25,16 @@ 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 ); } @@ -115,7 +55,7 @@ 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; @@ -168,55 +108,7 @@ 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 } ); @@ -276,14 +168,10 @@ /** * 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 @@ -291,90 +179,9 @@ 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; } @@ -389,7 +196,6 @@ */ 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 ) { @@ -403,22 +209,6 @@ 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 ) { } } } } ); @@ -487,41 +277,15 @@ 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' ); @@ -554,7 +318,6 @@ // 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( { @@ -567,7 +330,6 @@ 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( { @@ -587,19 +349,7 @@ 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; }; diff --git a/resources/src/mediawiki.action/mediawiki.action.view.postEdit.js b/resources/src/mediawiki.action/mediawiki.action.view.postEdit.js index e0ab45a109..5e859ac8a0 100644 --- a/resources/src/mediawiki.action/mediawiki.action.view.postEdit.js +++ b/resources/src/mediawiki.action/mediawiki.action.view.postEdit.js @@ -38,7 +38,12 @@ 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 = $( '
' ).addClass( 'postedit-icon postedit-icon-checkmark postedit-content' ); diff --git a/resources/src/mediawiki.language/specialcharacters.json b/resources/src/mediawiki.language/specialcharacters.json index 1c9294c564..afa7799281 100644 --- a/resources/src/mediawiki.language/specialcharacters.json +++ b/resources/src/mediawiki.language/specialcharacters.json @@ -3,7 +3,7 @@ "Á", "á", "À", "à", "Â", "â", "Ä", "ä", "Ã", "ã", "Ǎ", "ǎ", "Ā", "ā", "Ă", "ă", "Ą", "ą", "Å", "å", "Ć", "ć", "Ĉ", "ĉ", "Ç", "ç", "Č", "č", "Ċ", "ċ", "Đ", "đ", "Ď", "ď", "É", "é", "È", "è", "Ê", "ê", "Ë", "ë", "Ě", "ě", "Ē", "ē", "Ĕ", "ĕ", "Ė", "ė", "Ę", "ę", "Ĝ", "ĝ", "Ģ", "ģ", "Ğ", "ğ", "Ġ", "ġ", "Ĥ", "ĥ", "Ħ", "ħ", "Í", "í", "Ì", "ì", "Î", "î", "Ï", "ï", "Ĩ", "ĩ", "Ǐ", "ǐ", "Ī", "ī", "Ĭ", "ĭ", "İ", "ı", "Į", "į", "Ĵ", "ĵ", "Ķ", "ķ", "Ĺ", "ĺ", "Ļ", "ļ", "Ľ", "ľ", "Ł", "ł", "Ń", "ń", "Ñ", "ñ", "Ņ", "ņ", "Ň", "ň", "Ó", "ó", "Ò", "ò", "Ô", "ô", "Ö", "ö", "Õ", "õ", "Ǒ", "ǒ", "Ō", "ō", "Ŏ", "ŏ", "Ǫ", "ǫ", "Ő", "ő", "Ŕ", "ŕ", "Ŗ", "ŗ", "Ř", "ř", "Ś", "ś", "Ŝ", "ŝ", "Ş", "ş", "Š", "š", "Ș", "ș", "Ț", "ț", "Ť", "ť", "Ú", "ú", "Ù", "ù", "Û", "û", "Ü", "ü", "Ũ", "ũ", "Ů", "ů", "Ǔ", "ǔ", "Ū", "ū", "ǖ", "ǘ", "ǚ", "ǜ", "Ŭ", "ŭ", "Ų", "ų", "Ű", "ű", "Ŵ", "ŵ", "Ý", "ý", "Ŷ", "ŷ", "Ÿ", "ÿ", "Ȳ", "ȳ", "Ź", "ź", "Ž", "ž", "Ż", "ż", "Æ", "æ", "Ǣ", "ǣ", "Ø", "ø", "Œ", "œ", "ß", "Ð", "ð", "Þ", "þ", "Ə", "ə" ], "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̯", "ã", "ɐ", "ɐ̯", "ɐ̃", "ɑ", "ɑ̯", "ɑ̃", "ɒ", "ɒ̯", "ɒ̃", "ˈ", "ˌ", "ː", "ˑ", "˘", ".", "‿", "|", "‖", "ɚ", "ɝ" diff --git a/resources/src/mediawiki.legacy/commonPrint.css b/resources/src/mediawiki.legacy/commonPrint.css index 58e00f92af..df5aa0fe90 100644 --- a/resources/src/mediawiki.legacy/commonPrint.css +++ b/resources/src/mediawiki.legacy/commonPrint.css @@ -126,9 +126,8 @@ pre, 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 */ diff --git a/resources/src/mediawiki.less/mediawiki.ui/variables.less b/resources/src/mediawiki.less/mediawiki.ui/variables.less index 0c897dc91e..731bd2d352 100644 --- a/resources/src/mediawiki.less/mediawiki.ui/variables.less +++ b/resources/src/mediawiki.less/mediawiki.ui/variables.less @@ -1,3 +1,25 @@ +/** + * 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. diff --git a/resources/src/mediawiki.rcfilters/styles/mw.rcfilters.less b/resources/src/mediawiki.rcfilters/styles/mw.rcfilters.less index db439e3c58..413d45bc8c 100644 --- a/resources/src/mediawiki.rcfilters/styles/mw.rcfilters.less +++ b/resources/src/mediawiki.rcfilters/styles/mw.rcfilters.less @@ -132,6 +132,11 @@ 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 { diff --git a/resources/src/mediawiki.rcfilters/ui/mw.rcfilters.ui.FilterTagMultiselectWidget.js b/resources/src/mediawiki.rcfilters/ui/mw.rcfilters.ui.FilterTagMultiselectWidget.js index 070ecf8bd9..953df5b802 100644 --- a/resources/src/mediawiki.rcfilters/ui/mw.rcfilters.ui.FilterTagMultiselectWidget.js +++ b/resources/src/mediawiki.rcfilters/ui/mw.rcfilters.ui.FilterTagMultiselectWidget.js @@ -299,7 +299,7 @@ mw.hook( 'RcFilters.popup.open' ).fire(); - if ( !this.getMenu().getSelectedItem() ) { + if ( !this.getMenu().findSelectedItem() ) { // If there are no selected items, scroll menu to top // This has to be in a setTimeout so the menu has time // to be positioned and fixed diff --git a/resources/src/mediawiki.rcfilters/ui/mw.rcfilters.ui.MenuSelectWidget.js b/resources/src/mediawiki.rcfilters/ui/mw.rcfilters.ui.MenuSelectWidget.js index 07d8c88430..cbb4350357 100644 --- a/resources/src/mediawiki.rcfilters/ui/mw.rcfilters.ui.MenuSelectWidget.js +++ b/resources/src/mediawiki.rcfilters/ui/mw.rcfilters.ui.MenuSelectWidget.js @@ -299,7 +299,7 @@ */ mw.rcfilters.ui.MenuSelectWidget.prototype.onKeyDown = function ( e ) { var nextItem, - currentItem = this.findHighlightedItem() || this.getSelectedItem(); + currentItem = this.findHighlightedItem() || this.findSelectedItem(); // Call parent mw.rcfilters.ui.MenuSelectWidget.parent.prototype.onKeyDown.call( this, e ); diff --git a/resources/src/mediawiki.special/mediawiki.special.apisandbox.css b/resources/src/mediawiki.special/mediawiki.special.apisandbox.css index acb39989dd..7ef0263385 100644 --- a/resources/src/mediawiki.special/mediawiki.special.apisandbox.css +++ b/resources/src/mediawiki.special/mediawiki.special.apisandbox.css @@ -7,6 +7,10 @@ padding: 0.5em; } +#mw-apisandbox-ui .mw-apisandbox-link { + display: none; +} + .mw-apisandbox-popup .oo-ui-popupWidget-body > .oo-ui-widget { vertical-align: middle; } diff --git a/resources/src/mediawiki.special/mediawiki.special.userlogin.login.css b/resources/src/mediawiki.special/mediawiki.special.userlogin.login.css index cf77a96970..fe013bc845 100644 --- a/resources/src/mediawiki.special/mediawiki.special.userlogin.login.css +++ b/resources/src/mediawiki.special/mediawiki.special.userlogin.login.css @@ -8,7 +8,7 @@ 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; diff --git a/resources/src/mediawiki.widgets.datetime/DateTimeInputWidget.js b/resources/src/mediawiki.widgets.datetime/DateTimeInputWidget.js index 9233eef271..05180fd9b6 100644 --- a/resources/src/mediawiki.widgets.datetime/DateTimeInputWidget.js +++ b/resources/src/mediawiki.widgets.datetime/DateTimeInputWidget.js @@ -3,7 +3,7 @@ /** * 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. * @@ -12,7 +12,7 @@ * 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 diff --git a/resources/src/mediawiki.widgets.datetime/mediawiki.widgets.datetime.definitions.less b/resources/src/mediawiki.widgets.datetime/mediawiki.widgets.datetime.definitions.less index fa45d5ac2d..a9c2dd2f7b 100644 --- a/resources/src/mediawiki.widgets.datetime/mediawiki.widgets.datetime.definitions.less +++ b/resources/src/mediawiki.widgets.datetime/mediawiki.widgets.datetime.definitions.less @@ -1,6 +1,6 @@ /*! - * 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 ) { diff --git a/resources/src/mediawiki/api/category.js b/resources/src/mediawiki/api/category.js index 04462e3e1d..85df90e912 100644 --- a/resources/src/mediawiki/api/category.js +++ b/resources/src/mediawiki/api/category.js @@ -16,12 +16,16 @@ 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 } ); }, @@ -67,13 +71,17 @@ 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; } diff --git a/resources/src/mediawiki/htmlform/autoinfuse.js b/resources/src/mediawiki/htmlform/autoinfuse.js index f2e0f4dd2c..c39e43aaa8 100644 --- a/resources/src/mediawiki/htmlform/autoinfuse.js +++ b/resources/src/mediawiki/htmlform/autoinfuse.js @@ -1,6 +1,6 @@ /* * 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, $ ) { diff --git a/resources/src/mediawiki/htmlform/htmlform.Element.js b/resources/src/mediawiki/htmlform/htmlform.Element.js index 4f672fc786..01108e6573 100644 --- a/resources/src/mediawiki/htmlform/htmlform.Element.js +++ b/resources/src/mediawiki/htmlform/htmlform.Element.js @@ -3,7 +3,7 @@ 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(). * diff --git a/resources/src/mediawiki/mediawiki.feedback.js b/resources/src/mediawiki/mediawiki.feedback.js index bfd5c06045..ca4d239606 100644 --- a/resources/src/mediawiki/mediawiki.feedback.js +++ b/resources/src/mediawiki/mediawiki.feedback.js @@ -57,6 +57,7 @@ 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/'; @@ -85,12 +86,14 @@ * 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' ) { @@ -101,10 +104,10 @@ title: mw.msg( 'feedback-thanks-title' ), message: $( '' ).msg( 'feedback-thanks', - this.feedbackPageTitle.getNameText(), + feedbackPageName, $( '' ).attr( { target: '_blank', - href: this.feedbackPageTitle.getUrl() + href: feedbackPageUrl } ) ), actions: [ @@ -150,6 +153,7 @@ this.constructor.static.dialog, { title: mw.msg( this.dialogTitleMessageKey ), + foreignApi: this.foreignApi, settings: { messagePosterPromise: this.messagePosterPromise, title: this.feedbackPageTitle, @@ -305,6 +309,24 @@ */ 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; @@ -319,7 +341,6 @@ this.setBugReportLink( settings.bugsTaskSubmissionLink ); this.feedbackPageTitle = settings.title; this.feedbackPageName = settings.title.getNameText(); - this.feedbackPageUrl = settings.title.getUrl(); // Useragent checkbox if ( settings.useragentCheckbox.show ) { diff --git a/resources/src/oojs-ui-local.css b/resources/src/oojs-ui-local.css index 148c4c7285..b98ba13d6a 100644 --- a/resources/src/oojs-ui-local.css +++ b/resources/src/oojs-ui-local.css @@ -1,4 +1,4 @@ -/* 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) */ diff --git a/resources/src/oojs-ui-local.js b/resources/src/oojs-ui-local.js index dffa863de9..0c65512b4a 100644 --- a/resources/src/oojs-ui-local.js +++ b/resources/src/oojs-ui-local.js @@ -1,9 +1,9 @@ ( 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 ); diff --git a/tests/integration/includes/http/MWHttpRequestTestCase.php b/tests/integration/includes/http/MWHttpRequestTestCase.php index 3b02e28b44..cc769d7ee8 100644 --- a/tests/integration/includes/http/MWHttpRequestTestCase.php +++ b/tests/integration/includes/http/MWHttpRequestTestCase.php @@ -195,6 +195,11 @@ abstract class MWHttpRequestTestCase extends PHPUnit_Framework_TestCase { $this->assertSame( 401, $request->getStatus() ); } + public function testFactoryDefaults() { + $request = MWHttpRequest::factory( 'http://acme.test' ); + $this->assertInstanceOf( MWHttpRequest::class, $request ); + } + // -------------------- /** @@ -242,4 +247,5 @@ abstract class MWHttpRequestTestCase extends PHPUnit_Framework_TestCase { $this->assertArrayNotHasKey( strtolower( $name ), array_change_key_case( $cookieJar->cookie, CASE_LOWER ) ); } + } diff --git a/tests/parser/ParserTestRunner.php b/tests/parser/ParserTestRunner.php index 9b5897c89e..4dd4bc67d2 100644 --- a/tests/parser/ParserTestRunner.php +++ b/tests/parser/ParserTestRunner.php @@ -811,10 +811,6 @@ class ParserTestRunner { $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' ); @@ -854,7 +850,8 @@ class ParserTestRunner { } 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 ); diff --git a/tests/phpunit/MediaWikiTestCase.php b/tests/phpunit/MediaWikiTestCase.php index fe8c917564..3f4c8c0c88 100644 --- a/tests/phpunit/MediaWikiTestCase.php +++ b/tests/phpunit/MediaWikiTestCase.php @@ -1080,6 +1080,8 @@ abstract class MediaWikiTestCase extends PHPUnit_Framework_TestCase { } } + SiteStatsInit::doPlaceholderInit(); + User::resetIdByNameCache(); // Make sysop user diff --git a/tests/phpunit/includes/ExtraParserTest.php b/tests/phpunit/includes/ExtraParserTest.php index aaa135d8a0..75ebd31a21 100644 --- a/tests/phpunit/includes/ExtraParserTest.php +++ b/tests/phpunit/includes/ExtraParserTest.php @@ -26,7 +26,6 @@ class ExtraParserTest extends MediaWikiTestCase { // 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(); @@ -41,9 +40,8 @@ class ExtraParserTest extends MediaWikiTestCase { $title = Title::newFromText( 'Unit test' ); $options = ParserOptions::newFromUser( new User() ); - $options->setWrapOutputClass( false ); $this->assertEquals( "

$longLine

", - $this->parser->parse( $longLine, $title, $options )->getText() ); + $this->parser->parse( $longLine, $title, $options )->getText( [ 'unwrap' => true ] ) ); } /** @@ -55,7 +53,7 @@ class ExtraParserTest extends MediaWikiTestCase { $parserOutput = $this->parser->parse( "Test\n{{Foo}}\n{{Bar}}", $title, $this->options ); $this->assertEquals( "

Test\nContent of Template:Foo\nContent of Template:Bar\n

", - $parserOutput->getText() + $parserOutput->getText( [ 'unwrap' => true ] ) ); } diff --git a/tests/phpunit/includes/GlobalFunctions/wfArrayFilterTest.php b/tests/phpunit/includes/GlobalFunctions/wfArrayFilterTest.php index 388aee79d1..8adb55fc14 100644 --- a/tests/phpunit/includes/GlobalFunctions/wfArrayFilterTest.php +++ b/tests/phpunit/includes/GlobalFunctions/wfArrayFilterTest.php @@ -1,5 +1,10 @@ 1, 'b' => 2, 'c' => 3 ]; diff --git a/tests/phpunit/includes/LinkerTest.php b/tests/phpunit/includes/LinkerTest.php index 7f42254102..f9e2cc1733 100644 --- a/tests/phpunit/includes/LinkerTest.php +++ b/tests/phpunit/includes/LinkerTest.php @@ -5,7 +5,6 @@ use MediaWiki\MediaWikiServices; /** * @group Database */ - class LinkerTest extends MediaWikiLangTestCase { /** diff --git a/tests/phpunit/includes/WikiReferenceTest.php b/tests/phpunit/includes/WikiReferenceTest.php index 227dd87da5..dc2e9ae412 100644 --- a/tests/phpunit/includes/WikiReferenceTest.php +++ b/tests/phpunit/includes/WikiReferenceTest.php @@ -3,7 +3,6 @@ /** * @covers WikiReference */ - class WikiReferenceTest extends PHPUnit_Framework_TestCase { use MediaWikiCoversValidator; diff --git a/tests/phpunit/includes/db/DatabaseTestHelper.php b/tests/phpunit/includes/db/DatabaseTestHelper.php index d19d998146..fa9898d1cd 100644 --- a/tests/phpunit/includes/db/DatabaseTestHelper.php +++ b/tests/phpunit/includes/db/DatabaseTestHelper.php @@ -174,7 +174,7 @@ class DatabaseTestHelper extends Database { return false; } - function affectedRows() { + function fetchAffectedRowCount() { return -1; } diff --git a/tests/phpunit/includes/deferred/MWCallableUpdateTest.php b/tests/phpunit/includes/deferred/MWCallableUpdateTest.php index 088ab4f544..6977aef1a2 100644 --- a/tests/phpunit/includes/deferred/MWCallableUpdateTest.php +++ b/tests/phpunit/includes/deferred/MWCallableUpdateTest.php @@ -29,8 +29,54 @@ class MWCallableUpdateTest extends PHPUnit_Framework_TestCase { // 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 ); } + } diff --git a/tests/phpunit/includes/installer/OracleInstallerTest.php b/tests/phpunit/includes/installer/OracleInstallerTest.php index bd1412ebc1..2811a9cf41 100644 --- a/tests/phpunit/includes/installer/OracleInstallerTest.php +++ b/tests/phpunit/includes/installer/OracleInstallerTest.php @@ -6,7 +6,6 @@ * @group Database * @group Installer */ - class OracleInstallerTest extends MediaWikiTestCase { /** diff --git a/tests/phpunit/includes/libs/ArrayUtilsTest.php b/tests/phpunit/includes/libs/ArrayUtilsTest.php index 76b4ee17be..88312657d4 100644 --- a/tests/phpunit/includes/libs/ArrayUtilsTest.php +++ b/tests/phpunit/includes/libs/ArrayUtilsTest.php @@ -4,7 +4,6 @@ * * @group Database */ - class ArrayUtilsTest extends PHPUnit_Framework_TestCase { use MediaWikiCoversValidator; diff --git a/tests/phpunit/includes/libs/IPTest.php b/tests/phpunit/includes/libs/IPTest.php index 8a120eaab0..a36b259300 100644 --- a/tests/phpunit/includes/libs/IPTest.php +++ b/tests/phpunit/includes/libs/IPTest.php @@ -8,7 +8,6 @@ * @todo Test methods in this call should be split into a method and a * dataprovider. */ - class IPTest extends PHPUnit_Framework_TestCase { use MediaWikiCoversValidator; diff --git a/tests/phpunit/includes/libs/objectcache/WANObjectCacheTest.php b/tests/phpunit/includes/libs/objectcache/WANObjectCacheTest.php index a2c3bdcdbb..ca78f6500c 100644 --- a/tests/phpunit/includes/libs/objectcache/WANObjectCacheTest.php +++ b/tests/phpunit/includes/libs/objectcache/WANObjectCacheTest.php @@ -1481,7 +1481,10 @@ class WANObjectCacheTest extends PHPUnit_Framework_TestCase { $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; @@ -1498,6 +1501,60 @@ class WANObjectCacheTest extends PHPUnit_Framework_TestCase { $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() diff --git a/tests/phpunit/includes/libs/rdbms/TransactionProfilerTest.php b/tests/phpunit/includes/libs/rdbms/TransactionProfilerTest.php index 54706d55c4..25613fed6b 100644 --- a/tests/phpunit/includes/libs/rdbms/TransactionProfilerTest.php +++ b/tests/phpunit/includes/libs/rdbms/TransactionProfilerTest.php @@ -12,7 +12,7 @@ class TransactionProfilerTest extends PHPUnit_Framework_TestCase { 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 ); @@ -27,7 +27,7 @@ class TransactionProfilerTest extends PHPUnit_Framework_TestCase { 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 ); @@ -42,7 +42,7 @@ class TransactionProfilerTest extends PHPUnit_Framework_TestCase { 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 ); @@ -56,7 +56,7 @@ class TransactionProfilerTest extends PHPUnit_Framework_TestCase { 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 ); @@ -69,7 +69,7 @@ class TransactionProfilerTest extends PHPUnit_Framework_TestCase { 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 ); @@ -81,7 +81,7 @@ class TransactionProfilerTest extends PHPUnit_Framework_TestCase { 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 ); @@ -95,7 +95,7 @@ class TransactionProfilerTest extends PHPUnit_Framework_TestCase { 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 ); @@ -112,7 +112,7 @@ class TransactionProfilerTest extends PHPUnit_Framework_TestCase { 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 ); @@ -126,7 +126,7 @@ class TransactionProfilerTest extends PHPUnit_Framework_TestCase { 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 ); diff --git a/tests/phpunit/includes/libs/rdbms/database/DatabaseMysqlBaseTest.php b/tests/phpunit/includes/libs/rdbms/database/DatabaseMysqlBaseTest.php index a23a2a0096..caf1281e65 100644 --- a/tests/phpunit/includes/libs/rdbms/database/DatabaseMysqlBaseTest.php +++ b/tests/phpunit/includes/libs/rdbms/database/DatabaseMysqlBaseTest.php @@ -53,6 +53,9 @@ class FakeDatabaseMysqlBase extends DatabaseMysqlBase { protected function doQuery( $sql ) { } + protected function fetchAffectedRowCount() { + } + // From DatabaseMysqli protected function mysqlConnect( $realServer ) { } diff --git a/tests/phpunit/includes/libs/rdbms/database/DatabaseSQLTest.php b/tests/phpunit/includes/libs/rdbms/database/DatabaseSQLTest.php index 23f7865058..d8ebeff170 100644 --- a/tests/phpunit/includes/libs/rdbms/database/DatabaseSQLTest.php +++ b/tests/phpunit/includes/libs/rdbms/database/DatabaseSQLTest.php @@ -560,7 +560,7 @@ class DatabaseSQLTest extends PHPUnit_Framework_TestCase { 'rows' => [ 'field' => 'text', 'field2' => 'text2' ], ], "DELETE FROM replace_table " . - "WHERE ( field='text' ); " . + "WHERE (field = 'text'); " . "INSERT INTO replace_table " . "(field,field2) " . "VALUES ('text','text2')" @@ -576,7 +576,7 @@ class DatabaseSQLTest extends PHPUnit_Framework_TestCase { ], ], "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')" @@ -598,12 +598,12 @@ class DatabaseSQLTest extends PHPUnit_Framework_TestCase { ], ], "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')" @@ -625,12 +625,12 @@ class DatabaseSQLTest extends PHPUnit_Framework_TestCase { ], ], "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')" diff --git a/tests/phpunit/includes/libs/rdbms/database/DatabaseTest.php b/tests/phpunit/includes/libs/rdbms/database/DatabaseTest.php index 4a0a7e71df..e131506729 100644 --- a/tests/phpunit/includes/libs/rdbms/database/DatabaseTest.php +++ b/tests/phpunit/includes/libs/rdbms/database/DatabaseTest.php @@ -322,7 +322,7 @@ class DatabaseTest extends PHPUnit_Framework_TestCase { */ private function getMockDB( $methods = [] ) { static $abstractMethods = [ - 'affectedRows', + 'fetchAffectedRowCount', 'closeConnection', 'dataSeek', 'doQuery', diff --git a/tests/phpunit/includes/parser/ParserOptionsTest.php b/tests/phpunit/includes/parser/ParserOptionsTest.php index 93ab35c424..d55372c61f 100644 --- a/tests/phpunit/includes/parser/ParserOptionsTest.php +++ b/tests/phpunit/includes/parser/ParserOptionsTest.php @@ -21,7 +21,6 @@ class ParserOptionsTest extends MediaWikiTestCase { 'stubthreshold' => true, 'printable' => true, 'userlang' => true, - 'wrapclass' => true, ]; } @@ -62,11 +61,14 @@ class ParserOptionsTest extends MediaWikiTestCase { '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, ] ], @@ -102,7 +104,7 @@ class ParserOptionsTest extends MediaWikiTestCase { } public static function provideOptionsHash() { - $used = [ 'wrapclass', 'printable' ]; + $used = [ 'thumbsize', 'printable' ]; $classWrapper = TestingAccessWrapper::newFromClass( ParserOptions::class ); $classWrapper->getDefaults(); @@ -116,9 +118,9 @@ class ParserOptionsTest extends MediaWikiTestCase { '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, ] ], @@ -213,7 +215,7 @@ class ParserOptionsTest extends MediaWikiTestCase { $wgHooks['ParserOptionsRegister'] = []; $this->assertSame( [ 'dateformat', 'numberheadings', 'printable', 'stubthreshold', - 'thumbsize', 'userlang', 'wrapclass', + 'thumbsize', 'userlang' ], ParserOptions::allCacheVaryingOptions() ); self::clearCache(); @@ -231,7 +233,7 @@ class ParserOptionsTest extends MediaWikiTestCase { }; $this->assertSame( [ 'dateformat', 'foo', 'numberheadings', 'printable', 'stubthreshold', - 'thumbsize', 'userlang', 'wrapclass', + 'thumbsize', 'userlang' ], ParserOptions::allCacheVaryingOptions() ); } diff --git a/tests/phpunit/includes/parser/ParserOutputTest.php b/tests/phpunit/includes/parser/ParserOutputTest.php index 9642bbc0fb..efcc4e079e 100644 --- a/tests/phpunit/includes/parser/ParserOutputTest.php +++ b/tests/phpunit/includes/parser/ParserOutputTest.php @@ -105,6 +105,8 @@ class ParserOutputTest extends MediaWikiTestCase { 'wgScriptPath' => '/w', 'wgScript' => '/w/index.php', ] ); + $this->hideDeprecated( 'ParserOutput stateful allowTOC' ); + $this->hideDeprecated( 'ParserOutput stateful enableSectionEditLinks' ); $po = new ParserOutput( $text ); @@ -125,7 +127,7 @@ class ParserOutputTest extends MediaWikiTestCase { public static function provideGetText() { // phpcs:disable Generic.Files.LineLength $text = <<Test document. +

Test document.

Contents

    @@ -150,13 +152,13 @@ class ParserOutputTest extends MediaWikiTestCase {

    Section 3Section 3

    Three -

    +

EOF; return [ 'No stateless options, default state' => [ [], [], $text, <<Test document. +

Test document.

EOF ], 'No stateless options, TOC statefully disabled' => [ [], [ 'mTOCEnabled' => false ], $text, <<Test document. +

Test document.

Section 1[edit]

@@ -200,12 +202,12 @@ EOF

Section 3[edit]

Three -

+

EOF ], 'No stateless options, section edits statefully disabled' => [ [], [ 'mEditSectionTokens' => false ], $text, <<Test document. +

Test document.

Contents

    @@ -230,14 +232,14 @@ EOF

    Section 3

    Three -

    +

EOF ], 'Stateless options override stateful settings' => [ [ 'allowTOC' => true, 'enableSectionEditLinks' => true ], [ 'mTOCEnabled' => false, 'mEditSectionTokens' => false ], $text, <<Test document. +

Test document.

Contents

    @@ -262,12 +264,12 @@ EOF

    Section 3[edit]

    Three -

    +

EOF ], 'Statelessly disable section edit links' => [ [ 'enableSectionEditLinks' => false ], [], $text, <<Test document. +

Test document.

Contents

    @@ -292,13 +294,43 @@ EOF

    Section 3

    Three -

    +

EOF ], 'Statelessly disable TOC' => [ [ 'allowTOC' => false ], [], $text, <<

Test document. +

+ +

Section 1[edit]

+

One +

+

Section 2[edit]

+

Two +

+

Section 2.1[edit]

+

Two point one +

+

Section 3[edit]

+

Three +

+EOF + ], + 'Statelessly unwrap text' => [ + [ 'unwrap' => true ], [], $text, <<Test document.

+

Section 1[edit]

One @@ -314,6 +346,9 @@ EOF

EOF ], + 'Unwrap without a mw-parser-output wrapper' => [ + [ 'unwrap' => true ], [], '
Content
', '
Content
' + ], ]; // phpcs:enable } diff --git a/tests/phpunit/includes/parser/TagHooksTest.php b/tests/phpunit/includes/parser/TagHooksTest.php index 7e31cba60f..2fdaa1892f 100644 --- a/tests/phpunit/includes/parser/TagHooksTest.php +++ b/tests/phpunit/includes/parser/TagHooksTest.php @@ -46,7 +46,6 @@ class TagHooksTest extends MediaWikiTestCase { private function getParserOptions() { global $wgContLang; $popt = ParserOptions::newFromUserAndLang( new User, $wgContLang ); - $popt->setWrapOutputClass( false ); return $popt; } @@ -63,7 +62,7 @@ class TagHooksTest extends MediaWikiTestCase { Title::newFromText( 'Test' ), $this->getParserOptions() ); - $this->assertEquals( "

FooOneBaz\n

", $parserOutput->getText() ); + $this->assertEquals( "

FooOneBaz\n

", $parserOutput->getText( [ 'unwrap' => true ] ) ); $parser->mPreprocessor = null; # Break the Parser <-> Preprocessor cycle } @@ -98,7 +97,7 @@ class TagHooksTest extends MediaWikiTestCase { Title::newFromText( 'Test' ), $this->getParserOptions() ); - $this->assertEquals( "

FooOneBaz\n

", $parserOutput->getText() ); + $this->assertEquals( "

FooOneBaz\n

", $parserOutput->getText( [ 'unwrap' => true ] ) ); $parser->mPreprocessor = null; # Break the Parser <-> Preprocessor cycle } diff --git a/tests/phpunit/includes/session/SessionBackendTest.php b/tests/phpunit/includes/session/SessionBackendTest.php index 88f58cf06b..e460960c3e 100644 --- a/tests/phpunit/includes/session/SessionBackendTest.php +++ b/tests/phpunit/includes/session/SessionBackendTest.php @@ -2,6 +2,7 @@ namespace MediaWiki\Session; +use Config; use MediaWikiTestCase; use User; use Wikimedia\TestingAccessWrapper; @@ -14,9 +15,16 @@ 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; @@ -25,6 +33,7 @@ class SessionBackendTest extends MediaWikiTestCase { * 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 ) { @@ -149,7 +158,7 @@ class SessionBackendTest extends MediaWikiTestCase { $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, diff --git a/tests/phpunit/includes/session/SessionManagerTest.php b/tests/phpunit/includes/session/SessionManagerTest.php index 6c989f3cda..e042f7655a 100644 --- a/tests/phpunit/includes/session/SessionManagerTest.php +++ b/tests/phpunit/includes/session/SessionManagerTest.php @@ -14,7 +14,14 @@ use Wikimedia\TestingAccessWrapper; */ 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(); diff --git a/tests/phpunit/includes/session/TestBagOStuff.php b/tests/phpunit/includes/session/TestBagOStuff.php index bac2088d9a..f9e30f06ab 100644 --- a/tests/phpunit/includes/session/TestBagOStuff.php +++ b/tests/phpunit/includes/session/TestBagOStuff.php @@ -14,53 +14,44 @@ class TestBagOStuff extends \CachedBagOStuff { /** * @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 ); } diff --git a/tests/phpunit/includes/skins/SkinTemplateTest.php b/tests/phpunit/includes/skins/SkinTemplateTest.php index 5b3fbfac89..06b0667738 100644 --- a/tests/phpunit/includes/skins/SkinTemplateTest.php +++ b/tests/phpunit/includes/skins/SkinTemplateTest.php @@ -7,7 +7,6 @@ * * @author Bene* < benestar.wikimedia@gmail.com > */ - class SkinTemplateTest extends MediaWikiTestCase { /** * @dataProvider makeListItemProvider diff --git a/tests/phpunit/includes/specials/ImageListPagerTest.php b/tests/phpunit/includes/specials/ImageListPagerTest.php index 22bdefdff3..10c6d04c9e 100644 --- a/tests/phpunit/includes/specials/ImageListPagerTest.php +++ b/tests/phpunit/includes/specials/ImageListPagerTest.php @@ -8,7 +8,6 @@ * * @group Database */ - class ImageListPagerTest extends MediaWikiTestCase { /** * @expectedException MWException diff --git a/tests/qunit/data/testrunner.js b/tests/qunit/data/testrunner.js index 59432945c2..06c146c298 100644 --- a/tests/qunit/data/testrunner.js +++ b/tests/qunit/data/testrunner.js @@ -6,18 +6,21 @@ /** * 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; } /** @@ -73,13 +76,16 @@ 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' ) { @@ -98,49 +104,17 @@ }; } - 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 ); @@ -154,23 +128,11 @@ 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 ); }; }() ); @@ -239,98 +201,101 @@ } 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; }; }() ); @@ -657,4 +622,31 @@ } ); } ); + 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 ) ); diff --git a/tests/qunit/suites/resources/mediawiki.api/mediawiki.api.category.test.js b/tests/qunit/suites/resources/mediawiki.api/mediawiki.api.category.test.js index 8ad1290016..50fa6d1509 100644 --- a/tests/qunit/suites/resources/mediawiki.api/mediawiki.api.category.test.js +++ b/tests/qunit/suites/resources/mediawiki.api/mediawiki.api.category.test.js @@ -22,4 +22,93 @@ ); } ); } ); + + 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 ) ); diff --git a/tests/selenium/pageobjects/usermessage.page.js b/tests/selenium/pageobjects/usermessage.page.js deleted file mode 100644 index 7faf34725e..0000000000 --- a/tests/selenium/pageobjects/usermessage.page.js +++ /dev/null @@ -1,7 +0,0 @@ -'use strict'; -const Page = require( './page' ); - -class UserMessagePage extends Page { - get usermessage() { return browser.element( 'div.usermessage' ); } -} -module.exports = new UserMessagePage(); diff --git a/tests/selenium/specs/user.js b/tests/selenium/specs/user.js index 102acd6fa4..3f3872dc7d 100644 --- a/tests/selenium/specs/user.js +++ b/tests/selenium/specs/user.js @@ -2,9 +2,7 @@ const assert = require( 'assert' ), CreateAccountPage = require( '../pageobjects/createaccount.page' ), PreferencesPage = require( '../pageobjects/preferences.page' ), - UserLoginPage = require( '../pageobjects/userlogin.page' ), - UserMessagePage = require( '../pageobjects/usermessage.page' ), - EditPage = require( '../pageobjects/edit.page' ); + UserLoginPage = require( '../pageobjects/userlogin.page' ); describe( 'User', function () { @@ -68,24 +66,4 @@ describe( 'User', function () { } ); - it( 'should be able to view new message banner', function () { - - // create user - browser.call( function () { - return CreateAccountPage.apiCreateAccount( username, password ); - } ); - - // create talk page with content - browser.call( function () { - return EditPage.apiEdit( 'User_talk:' + username, Math.random().toString() ); - } ); - - // log in - UserLoginPage.login( username, password ); - - // check - assert.equal( UserMessagePage.usermessage.getText(), 'You have a new message (last change).' ); - - } ); - } ); diff --git a/thumb.php b/thumb.php index 02ac0b024d..c4b40dc76f 100644 --- a/thumb.php +++ b/thumb.php @@ -337,7 +337,16 @@ function wfStreamThumb( array $params ) { 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 */ @@ -377,6 +386,43 @@ function wfStreamThumb( array $params ) { } } +/** + * 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 *