# Editors
*.kate-swp
*~
+\#*#
+.#*
.*.swp
.project
cscope.files
uz, vi.
* Added 'CategoryAfterPageAdded' and 'CategoryAfterPageRemoved' hooks.
* Added 'HistoryRevisionTools' and 'DiffRevisionTools' hooks.
+* Added 'SpecialSearchResultsPrepend' and 'SpecialSearchResultsAppend' hooks.
* (bug 33186) Add image rotation api "imagerotate"
* (bug 34040) Add "User rights management" link on user page toolbox.
* (bug 45526) Add QUnit assertion helper "QUnit.assert.htmlEqual" for asserting
* $wgRedirectScript was removed. It was unused.
* Removed $wgLocalMessageCacheSerialized, it is now always true.
* When $wgUseVFormUserLogin is true, the redesign of Special:UserLogin is
- activated.
+ activated; when $wgUseVFormCreateAccount is true, the redesign of
+ Special:UserLogin/signup is activated.
* $wgVectorUseIconWatch is now enabled by default.
=== New features in 1.22 ===
preference). This feature was moved from the Vector extension, and is now part
of core for all skins. Take care when upgrading that you don't use an older
version of the Vector extension as this feature may conflict.
-* New version of Special:UserLogin form. It is opt-in for now, controlled by
- the $wgUseVFormUserLogin setting or a 'useNew' URL parameter trigger.
-* Added 'SpecialSearchResultsPrepend' and 'SpecialSearchResultsAppend' hooks.
+* New 'mediawiki.ui' CSS module providing mw-ui-* styles for buttons and a
+ compact vertical form layout.
+* New versions of login (Special:UserLogin) and create account
+ (Special:UserLogin/signup) forms. They are opt-in for now, controlled by
+ the $wgUseVFormUserLogin and $wgUseVFormCreateAccount settings or a 'useNew'
+ URL parameter trigger.
* (bug 23343) Implemented ability to apply IP blocks to the contents of X-Forwarded-For headers
by adding a new configuration variable $wgApplyIpBlocksToXff (disabled by default).
* The new hook 'APIGetPossibleErrors' to modify the list of possible errors was
Pager-related WebRequest parameters by default, as this is overwhelmingly
likely to be what was intended by users of the method. If any caller wishes
to use these parameters, the new param 'useRequestParams' may be set to true.
+* mw.util.addPortletLink: Tooltip is no longer required to be plain (without
+ an accesskey in it already). As such it now rountrips. Creating a link with a
+ message as tooltip, grabbing the title attribute and using it to create
+ another portlet will work as expected.
+* (bug 6747) {{ROOTPAGENAME}} introduced, contains the name of the topmost
+ page without namespace.
=== Bug fixes in 1.22 ===
* Disable Special:PasswordReset when $wgEnableEmail. Previously one could still
* (bug 47218) Special:BlockList now handles correctly user names with spaces
when passed as subpage.
* Pager's properly validate which fields are allowed to be sorted on.
+* mw.util.tooltipAccessKeyRegexp: The regex now matches "option-" as well.
+ Support for Mac "option" was added in 1.16, but the regex was never updated.
+* (bug 46768) Usernames of blocking users now display correctly, even if numeric.
=== API changes in 1.22 ===
* (bug 46626) xmldoublequote parameter was removed. Because of a bug, the
longer be), and will no longer choke on booleans.
* action=opensearch no longer silently ignores the format parameter.
* action=opensearch now supports format=jsonfm.
+* list=usercontribs&ucprop=ids will now include the parent revision id.
=== Languages updated in 1.22===
* Calling Linker methods using a skin will now output deprecation warnings.
* (bug 46680) "Return to" links are no longer tagged with rel="next".
* The Special:ActiveUsers special page was removed.
+* BREAKING CHANGE: mw.util.tooltipAccessKeyRegexp: The match group for the
+ accesskey character is now $6 instead of $5.
== Compatibility ==
$this->mode = "post";
}
- switch( $this->mode ) {
+ switch ( $this->mode ) {
case 'get':
$this->func_name = isset( $_GET["rs"] ) ? $_GET["rs"] : '';
if ( ! empty( $_GET["rsargs"] ) ) {
$page = null;
wfRunHooks( 'ArticleFromTitle', array( &$title, &$page ) );
if ( !$page ) {
- switch( $title->getNamespace() ) {
+ switch ( $title->getNamespace() ) {
case NS_FILE:
$page = new ImagePage( $title );
break;
$this->mParserOutput = false;
while ( !$outputDone && ++$pass ) {
- switch( $pass ) {
+ switch ( $pass ) {
case 1:
wfRunHooks( 'ArticleViewHeader', array( &$this, &$outputDone, &$useParserCache ) );
break;
$user = User::newFromName( $rootPart, false /* allow IP users*/ );
$ip = User::isIP( $rootPart );
- if ( !($user && $user->isLoggedIn()) && !$ip ) { # User does not exist
+ if ( !( $user && $user->isLoggedIn() ) && !$ip ) { # User does not exist
$outputPage->wrapWikiMsg( "<div class=\"mw-userpage-userdoesnotexist error\">\n\$1\n</div>",
array( 'userpage-userdoesnotexist-view', wfEscapeWikiText( $rootPart ) ) );
} elseif ( $user->isBlocked() ) { # Show log extract if the user is currently blocked
'ConfEditorToken' => 'includes/ConfEditor.php',
'Cookie' => 'includes/Cookie.php',
'CookieJar' => 'includes/Cookie.php',
- 'MWCryptRand' => 'includes/CryptRand.php',
'CurlHttpRequest' => 'includes/HttpFunctions.php',
'DeferrableUpdate' => 'includes/DeferredUpdates.php',
'DeferredUpdates' => 'includes/DeferredUpdates.php',
'EnhancedChangesList' => 'includes/ChangesList.php',
'ErrorPageError' => 'includes/Exception.php',
'ExplodeIterator' => 'includes/StringUtils.php',
- 'ExternalStore' => 'includes/externalstore/ExternalStore.php',
- 'ExternalStoreDB' => 'includes/externalstore/ExternalStoreDB.php',
- 'ExternalStoreHttp' => 'includes/externalstore/ExternalStoreHttp.php',
- 'ExternalStoreMedium' => 'includes/externalstore/ExternalStoreMedium.php',
- 'ExternalStoreMwstore' => 'includes/externalstore/ExternalStoreMwstore.php',
'FakeTitle' => 'includes/FakeTitle.php',
'Fallback' => 'includes/Fallback.php',
'FatalError' => 'includes/Exception.php',
'Hooks' => 'includes/Hooks.php',
'Html' => 'includes/Html.php',
'HTMLApiField' => 'includes/HTMLForm.php',
+ 'HTMLButtonField' => 'includes/HTMLForm.php',
'HTMLCheckField' => 'includes/HTMLForm.php',
'HTMLCheckMatrix' => 'includes/HTMLForm.php',
'HTMLEditTools' => 'includes/HTMLForm.php',
'Message' => 'includes/Message.php',
'MessageBlobStore' => 'includes/MessageBlobStore.php',
'MimeMagic' => 'includes/MimeMagic.php',
+ 'MWCryptRand' => 'includes/MWCryptRand.php',
'MWException' => 'includes/Exception.php',
'MWExceptionHandler' => 'includes/Exception.php',
'MWFunction' => 'includes/MWFunction.php',
'WikiDiff3' => 'includes/diff/WikiDiff3.php',
'WordLevelDiff' => 'includes/diff/DairikiDiff.php',
+ # includes/externalstore
+ 'ExternalStore' => 'includes/externalstore/ExternalStore.php',
+ 'ExternalStoreDB' => 'includes/externalstore/ExternalStoreDB.php',
+ 'ExternalStoreHttp' => 'includes/externalstore/ExternalStoreHttp.php',
+ 'ExternalStoreMedium' => 'includes/externalstore/ExternalStoreMedium.php',
+ 'ExternalStoreMwstore' => 'includes/externalstore/ExternalStoreMwstore.php',
+
# includes/filebackend
'FileBackendGroup' => 'includes/filebackend/FileBackendGroup.php',
'FileBackend' => 'includes/filebackend/FileBackend.php',
'UserloginTemplate' => 'includes/templates/Userlogin.php',
'UserloginTemplateVForm' => 'includes/templates/UserloginVForm.php',
'UsercreateTemplate' => 'includes/templates/Usercreate.php',
+ 'UsercreateTemplateVForm' => 'includes/templates/UsercreateVForm.php',
# includes/upload
'UploadBase' => 'includes/upload/UploadBase.php',
return false;
}
- switch( $cond[0] ) {
+ switch ( $cond[0] ) {
case APCOND_EMAILCONFIRMED:
if ( Sanitizer::validateEmail( $user->getEmail() ) ) {
if ( $wgEmailAuthentication ) {
# passed by some callers (bug 29116)
if ( $vagueTarget != '' ) {
list( $target, $type ) = self::parseTarget( $vagueTarget );
- switch( $type ) {
+ switch ( $type ) {
case self::TYPE_USER:
# Slightly weird, but who are we to argue?
$conds['ipb_address'][] = (string)$target;
* @return Array
*/
protected function getDatabaseArray( $db = null ) {
- if( !$db ) {
+ if ( !$db ) {
$db = wfGetDB( DB_SLAVE );
}
$expiry = $db->encodeExpiry( $this->mExpiry );
* @return String IP in Hex form
*/
public function getRangeStart() {
- switch( $this->type ) {
+ switch ( $this->type ) {
case self::TYPE_USER:
return '';
case self::TYPE_IP:
* @return String IP in Hex form
*/
public function getRangeEnd() {
- switch( $this->type ) {
+ switch ( $this->type ) {
case self::TYPE_USER:
return '';
case self::TYPE_IP:
* @return Bool
*/
public function prevents( $action, $x = null ) {
- switch( $action ) {
+ switch ( $action ) {
case 'edit':
# For now... <evil laugh>
return true;
* @param Array $block Array of blocks
* @return Block|null the "best" block from the list
*/
- public static function chooseBlock( array $blocks, array $ipChain ) {
+ public static function chooseBlock( array $blocks, array $ipChain ) {
if ( !count( $blocks ) ) {
return null;
} elseif ( count( $blocks ) == 1 ) {
public function setBlocker( $user ) {
$this->blocker = $user;
}
+
+ /**
+ * Get the key and parameters for the corresponding error message.
+ *
+ * @since 1.22
+ * @param IContextSource $context
+ * @return array
+ */
+ public function getPermissionsError( IContextSource $context ) {
+ $blocker = $this->getBlocker();
+ if ( $blocker instanceof User ) { // local user
+ $blockerUserpage = $blocker->getUserPage();
+ $link = "[[{$blockerUserpage->getPrefixedText()}|{$blockerUserpage->getText()}]]";
+ } else { // foreign user
+ $link = $blocker;
+ }
+
+ $reason = $this->mReason;
+ if ( $reason == '' ) {
+ $reason = $context->msg( 'blockednoreason' )->text();
+ }
+
+ /* $ip returns who *is* being blocked, $intended contains who was meant to be blocked.
+ * This could be a username, an IP range, or a single IP. */
+ $intended = $this->getTarget();
+
+ $lang = $context->getLanguage();
+ return array(
+ $this->mAuto ? 'autoblockedtext' : 'blockedtext',
+ $link,
+ $reason,
+ $context->getRequest()->getIP(),
+ $this->getByName(),
+ $this->getId(),
+ $lang->formatExpiry( $this->mExpiry ),
+ (string)$intended,
+ $lang->timeanddate( wfTimestamp( TS_MW, $this->mTimestamp ), true ),
+ );
+ }
}
*/
private function preCacheMessages() {
if ( !isset( $this->message ) ) {
- foreach ( explode( ' ', 'cur diff hist last blocklink history ' .
- 'semicolon-separator pipe-separator' ) as $msg ) {
+ foreach ( array(
+ 'cur', 'diff', 'hist', 'last', 'blocklink', 'history',
+ 'semicolon-separator', 'pipe-separator' ) as $msg
+ ) {
$this->message[$msg] = $this->msg( $msg )->escaped();
}
}
* @return Collation
*/
static function factory( $collationName ) {
- switch( $collationName ) {
+ switch ( $collationName ) {
case 'uppercase':
return new UppercaseCollation;
case 'identity':
$cacheEntry = $cache->get( $cacheKey );
if ( $cacheEntry && isset( $cacheEntry['version'] )
- && $cacheEntry['version'] == self::FIRST_LETTER_VERSION )
- {
+ && $cacheEntry['version'] == self::FIRST_LETTER_VERSION
+ ) {
$this->firstLetterData = $cacheEntry;
return $this->firstLetterData;
}
// Generate data from serialized data file
- if ( isset ( self::$tailoringFirstLetters[$this->locale] ) ) {
+ if ( isset( self::$tailoringFirstLetters[$this->locale] ) ) {
$letters = wfGetPrecompiledData( "first-letters-root.ser" );
// Append additional characters
$letters = array_merge( $letters, self::$tailoringFirstLetters[$this->locale] );
+++ /dev/null
-<?php
-/**
- * A cryptographic random generator class used for generating secret keys
- *
- * This is based in part on Drupal code as well as what we used in our own code
- * prior to introduction of this class.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- * http://www.gnu.org/copyleft/gpl.html
- *
- * @author Daniel Friesen
- * @file
- */
-
-class MWCryptRand {
-
- /**
- * Minimum number of iterations we want to make in our drift calculations.
- */
- const MIN_ITERATIONS = 1000;
-
- /**
- * Number of milliseconds we want to spend generating each separate byte
- * of the final generated bytes.
- * This is used in combination with the hash length to determine the duration
- * we should spend doing drift calculations.
- */
- const MSEC_PER_BYTE = 0.5;
-
- /**
- * Singleton instance for public use
- */
- protected static $singleton = null;
-
- /**
- * The hash algorithm being used
- */
- protected $algo = null;
-
- /**
- * The number of bytes outputted by the hash algorithm
- */
- protected $hashLength = null;
-
- /**
- * A boolean indicating whether the previous random generation was done using
- * cryptographically strong random number generator or not.
- */
- protected $strong = null;
-
- /**
- * Initialize an initial random state based off of whatever we can find
- */
- protected function initialRandomState() {
- // $_SERVER contains a variety of unstable user and system specific information
- // It'll vary a little with each page, and vary even more with separate users
- // It'll also vary slightly across different machines
- $state = serialize( $_SERVER );
-
- // To try vary the system information of the state a bit more
- // by including the system's hostname into the state
- $state .= wfHostname();
-
- // Try to gather a little entropy from the different php rand sources
- $state .= rand() . uniqid( mt_rand(), true );
-
- // Include some information about the filesystem's current state in the random state
- $files = array();
-
- // We know this file is here so grab some info about ourselves
- $files[] = __FILE__;
-
- // We must also have a parent folder, and with the usual file structure, a grandparent
- $files[] = __DIR__;
- $files[] = dirname( __DIR__ );
-
- // The config file is likely the most often edited file we know should be around
- // so include its stat info into the state.
- // The constant with its location will almost always be defined, as WebStart.php defines
- // MW_CONFIG_FILE to $IP/LocalSettings.php unless being configured with MW_CONFIG_CALLBACK (eg. the installer)
- if ( defined( 'MW_CONFIG_FILE' ) ) {
- $files[] = MW_CONFIG_FILE;
- }
-
- foreach ( $files as $file ) {
- wfSuppressWarnings();
- $stat = stat( $file );
- wfRestoreWarnings();
- if ( $stat ) {
- // stat() duplicates data into numeric and string keys so kill off all the numeric ones
- foreach ( $stat as $k => $v ) {
- if ( is_numeric( $k ) ) {
- unset( $k );
- }
- }
- // The absolute filename itself will differ from install to install so don't leave it out
- if ( ( $path = realpath( $file ) ) !== false ) {
- $state .= $path;
- } else {
- $state .= $file;
- }
- $state .= implode( '', $stat );
- } else {
- // The fact that the file isn't there is worth at least a
- // minuscule amount of entropy.
- $state .= '0';
- }
- }
-
- // Try and make this a little more unstable by including the varying process
- // id of the php process we are running inside of if we are able to access it
- if ( function_exists( 'getmypid' ) ) {
- $state .= getmypid();
- }
-
- // If available try to increase the instability of the data by throwing in
- // the precise amount of memory that we happen to be using at the moment.
- if ( function_exists( 'memory_get_usage' ) ) {
- $state .= memory_get_usage( true );
- }
-
- // It's mostly worthless but throw the wiki's id into the data for a little more variance
- $state .= wfWikiID();
-
- // If we have a secret key or proxy key set then throw it into the state as well
- global $wgSecretKey, $wgProxyKey;
- if ( $wgSecretKey ) {
- $state .= $wgSecretKey;
- } elseif ( $wgProxyKey ) {
- $state .= $wgProxyKey;
- }
-
- return $state;
- }
-
- /**
- * Randomly hash data while mixing in clock drift data for randomness
- *
- * @param string $data The data to randomly hash.
- * @return String The hashed bytes
- * @author Tim Starling
- */
- protected function driftHash( $data ) {
- // Minimum number of iterations (to avoid slow operations causing the loop to gather little entropy)
- $minIterations = self::MIN_ITERATIONS;
- // Duration of time to spend doing calculations (in seconds)
- $duration = ( self::MSEC_PER_BYTE / 1000 ) * $this->hashLength();
- // Create a buffer to use to trigger memory operations
- $bufLength = 10000000;
- $buffer = str_repeat( ' ', $bufLength );
- $bufPos = 0;
-
- // Iterate for $duration seconds or at least $minIterations number of iterations
- $iterations = 0;
- $startTime = microtime( true );
- $currentTime = $startTime;
- while ( $iterations < $minIterations || $currentTime - $startTime < $duration ) {
- // Trigger some memory writing to trigger some bus activity
- // This may create variance in the time between iterations
- $bufPos = ( $bufPos + 13 ) % $bufLength;
- $buffer[$bufPos] = ' ';
- // Add the drift between this iteration and the last in as entropy
- $nextTime = microtime( true );
- $delta = (int)( ( $nextTime - $currentTime ) * 1000000 );
- $data .= $delta;
- // Every 100 iterations hash the data and entropy
- if ( $iterations % 100 === 0 ) {
- $data = sha1( $data );
- }
- $currentTime = $nextTime;
- $iterations++;
- }
- $timeTaken = $currentTime - $startTime;
- $data = $this->hash( $data );
-
- wfDebug( __METHOD__ . ": Clock drift calculation " .
- "(time-taken=" . ( $timeTaken * 1000 ) . "ms, " .
- "iterations=$iterations, " .
- "time-per-iteration=" . ( $timeTaken / $iterations * 1e6 ) . "us)\n" );
- return $data;
- }
-
- /**
- * Return a rolling random state initially build using data from unstable sources
- * @return string A new weak random state
- */
- protected function randomState() {
- static $state = null;
- if ( is_null( $state ) ) {
- // Initialize the state with whatever unstable data we can find
- // It's important that this data is hashed right afterwards to prevent
- // it from being leaked into the output stream
- $state = $this->hash( $this->initialRandomState() );
- }
- // Generate a new random state based on the initial random state or previous
- // random state by combining it with clock drift
- $state = $this->driftHash( $state );
- return $state;
- }
-
- /**
- * Decide on the best acceptable hash algorithm we have available for hash()
- * @throws MWException
- * @return String A hash algorithm
- */
- protected function hashAlgo() {
- if ( !is_null( $this->algo ) ) {
- return $this->algo;
- }
-
- $algos = hash_algos();
- $preference = array( 'whirlpool', 'sha256', 'sha1', 'md5' );
-
- foreach ( $preference as $algorithm ) {
- if ( in_array( $algorithm, $algos ) ) {
- $this->algo = $algorithm;
- wfDebug( __METHOD__ . ": Using the {$this->algo} hash algorithm.\n" );
- return $this->algo;
- }
- }
-
- // We only reach here if no acceptable hash is found in the list, this should
- // be a technical impossibility since most of php's hash list is fixed and
- // some of the ones we list are available as their own native functions
- // But since we already require at least 5.2 and hash() was default in
- // 5.1.2 we don't bother falling back to methods like sha1 and md5.
- throw new MWException( "Could not find an acceptable hashing function in hash_algos()" );
- }
-
- /**
- * Return the byte-length output of the hash algorithm we are
- * using in self::hash and self::hmac.
- *
- * @return int Number of bytes the hash outputs
- */
- protected function hashLength() {
- if ( is_null( $this->hashLength ) ) {
- $this->hashLength = strlen( $this->hash( '' ) );
- }
- return $this->hashLength;
- }
-
- /**
- * Generate an acceptably unstable one-way-hash of some text
- * making use of the best hash algorithm that we have available.
- *
- * @param $data string
- * @return String A raw hash of the data
- */
- protected function hash( $data ) {
- return hash( $this->hashAlgo(), $data, true );
- }
-
- /**
- * Generate an acceptably unstable one-way-hmac of some text
- * making use of the best hash algorithm that we have available.
- *
- * @param $data string
- * @param $key string
- * @return String A raw hash of the data
- */
- protected function hmac( $data, $key ) {
- return hash_hmac( $this->hashAlgo(), $data, $key, true );
- }
-
- /**
- * @see self::wasStrong()
- */
- public function realWasStrong() {
- if ( is_null( $this->strong ) ) {
- throw new MWException( __METHOD__ . ' called before generation of random data' );
- }
- return $this->strong;
- }
-
- /**
- * @see self::generate()
- */
- public function realGenerate( $bytes, $forceStrong = false ) {
- wfProfileIn( __METHOD__ );
-
- wfDebug( __METHOD__ . ": Generating cryptographic random bytes for " . wfGetAllCallers( 5 ) . "\n" );
-
- $bytes = floor( $bytes );
- static $buffer = '';
- if ( is_null( $this->strong ) ) {
- // Set strength to false initially until we know what source data is coming from
- $this->strong = true;
- }
-
- if ( strlen( $buffer ) < $bytes ) {
- // If available make use of mcrypt_create_iv URANDOM source to generate randomness
- // On unix-like systems this reads from /dev/urandom but does it without any buffering
- // and bypasses openbasedir restrictions, so it's preferable to reading directly
- // On Windows starting in PHP 5.3.0 Windows' native CryptGenRandom is used to generate
- // entropy so this is also preferable to just trying to read urandom because it may work
- // on Windows systems as well.
- if ( function_exists( 'mcrypt_create_iv' ) ) {
- wfProfileIn( __METHOD__ . '-mcrypt' );
- $rem = $bytes - strlen( $buffer );
- $iv = mcrypt_create_iv( $rem, MCRYPT_DEV_URANDOM );
- if ( $iv === false ) {
- wfDebug( __METHOD__ . ": mcrypt_create_iv returned false.\n" );
- } else {
- $buffer .= $iv;
- wfDebug( __METHOD__ . ": mcrypt_create_iv generated " . strlen( $iv ) . " bytes of randomness.\n" );
- }
- wfProfileOut( __METHOD__ . '-mcrypt' );
- }
- }
-
- if ( strlen( $buffer ) < $bytes ) {
- // If available make use of openssl's random_pseudo_bytes method to attempt to generate randomness.
- // However don't do this on Windows with PHP < 5.3.4 due to a bug:
- // http://stackoverflow.com/questions/1940168/openssl-random-pseudo-bytes-is-slow-php
- // http://git.php.net/?p=php-src.git;a=commitdiff;h=cd62a70863c261b07f6dadedad9464f7e213cad5
- if ( function_exists( 'openssl_random_pseudo_bytes' )
- && ( !wfIsWindows() || version_compare( PHP_VERSION, '5.3.4', '>=' ) )
- ) {
- wfProfileIn( __METHOD__ . '-openssl' );
- $rem = $bytes - strlen( $buffer );
- $openssl_bytes = openssl_random_pseudo_bytes( $rem, $openssl_strong );
- if ( $openssl_bytes === false ) {
- wfDebug( __METHOD__ . ": openssl_random_pseudo_bytes returned false.\n" );
- } else {
- $buffer .= $openssl_bytes;
- wfDebug( __METHOD__ . ": openssl_random_pseudo_bytes generated " . strlen( $openssl_bytes ) . " bytes of " . ( $openssl_strong ? "strong" : "weak" ) . " randomness.\n" );
- }
- if ( strlen( $buffer ) >= $bytes ) {
- // openssl tells us if the random source was strong, if some of our data was generated
- // using it use it's say on whether the randomness is strong
- $this->strong = !!$openssl_strong;
- }
- wfProfileOut( __METHOD__ . '-openssl' );
- }
- }
-
- // Only read from urandom if we can control the buffer size or were passed forceStrong
- if ( strlen( $buffer ) < $bytes && ( function_exists( 'stream_set_read_buffer' ) || $forceStrong ) ) {
- wfProfileIn( __METHOD__ . '-fopen-urandom' );
- $rem = $bytes - strlen( $buffer );
- if ( !function_exists( 'stream_set_read_buffer' ) && $forceStrong ) {
- wfDebug( __METHOD__ . ": Was forced to read from /dev/urandom without control over the buffer size.\n" );
- }
- // /dev/urandom is generally considered the best possible commonly
- // available random source, and is available on most *nix systems.
- wfSuppressWarnings();
- $urandom = fopen( "/dev/urandom", "rb" );
- wfRestoreWarnings();
-
- // Attempt to read all our random data from urandom
- // php's fread always does buffered reads based on the stream's chunk_size
- // so in reality it will usually read more than the amount of data we're
- // asked for and not storing that risks depleting the system's random pool.
- // If stream_set_read_buffer is available set the chunk_size to the amount
- // of data we need. Otherwise read 8k, php's default chunk_size.
- if ( $urandom ) {
- // php's default chunk_size is 8k
- $chunk_size = 1024 * 8;
- if ( function_exists( 'stream_set_read_buffer' ) ) {
- // If possible set the chunk_size to the amount of data we need
- stream_set_read_buffer( $urandom, $rem );
- $chunk_size = $rem;
- }
- $random_bytes = fread( $urandom, max( $chunk_size, $rem ) );
- $buffer .= $random_bytes;
- fclose( $urandom );
- wfDebug( __METHOD__ . ": /dev/urandom generated " . strlen( $random_bytes ) . " bytes of randomness.\n" );
- if ( strlen( $buffer ) >= $bytes ) {
- // urandom is always strong, set to true if all our data was generated using it
- $this->strong = true;
- }
- } else {
- wfDebug( __METHOD__ . ": /dev/urandom could not be opened.\n" );
- }
- wfProfileOut( __METHOD__ . '-fopen-urandom' );
- }
-
- // If we cannot use or generate enough data from a secure source
- // use this loop to generate a good set of pseudo random data.
- // This works by initializing a random state using a pile of unstable data
- // and continually shoving it through a hash along with a variable salt.
- // We hash the random state with more salt to avoid the state from leaking
- // out and being used to predict the /randomness/ that follows.
- if ( strlen( $buffer ) < $bytes ) {
- wfDebug( __METHOD__ . ": Falling back to using a pseudo random state to generate randomness.\n" );
- }
- while ( strlen( $buffer ) < $bytes ) {
- wfProfileIn( __METHOD__ . '-fallback' );
- $buffer .= $this->hmac( $this->randomState(), mt_rand() );
- // This code is never really cryptographically strong, if we use it
- // at all, then set strong to false.
- $this->strong = false;
- wfProfileOut( __METHOD__ . '-fallback' );
- }
-
- // Once the buffer has been filled up with enough random data to fulfill
- // the request shift off enough data to handle the request and leave the
- // unused portion left inside the buffer for the next request for random data
- $generated = substr( $buffer, 0, $bytes );
- $buffer = substr( $buffer, $bytes );
-
- wfDebug( __METHOD__ . ": " . strlen( $buffer ) . " bytes of randomness leftover in the buffer.\n" );
-
- wfProfileOut( __METHOD__ );
- return $generated;
- }
-
- /**
- * @see self::generateHex()
- */
- public function realGenerateHex( $chars, $forceStrong = false ) {
- // hex strings are 2x the length of raw binary so we divide the length in half
- // odd numbers will result in a .5 that leads the generate() being 1 character
- // short, so we use ceil() to ensure that we always have enough bytes
- $bytes = ceil( $chars / 2 );
- // Generate the data and then convert it to a hex string
- $hex = bin2hex( $this->generate( $bytes, $forceStrong ) );
- // A bit of paranoia here, the caller asked for a specific length of string
- // here, and it's possible (eg when given an odd number) that we may actually
- // have at least 1 char more than they asked for. Just in case they made this
- // call intending to insert it into a database that does truncation we don't
- // want to give them too much and end up with their database and their live
- // code having two different values because part of what we gave them is truncated
- // hence, we strip out any run of characters longer than what we were asked for.
- return substr( $hex, 0, $chars );
- }
-
- /** Publicly exposed static methods **/
-
- /**
- * Return a singleton instance of MWCryptRand
- * @return MWCryptRand
- */
- protected static function singleton() {
- if ( is_null( self::$singleton ) ) {
- self::$singleton = new self;
- }
- return self::$singleton;
- }
-
- /**
- * Return a boolean indicating whether or not the source used for cryptographic
- * random bytes generation in the previously run generate* call
- * was cryptographically strong.
- *
- * @return bool Returns true if the source was strong, false if not.
- */
- public static function wasStrong() {
- return self::singleton()->realWasStrong();
- }
-
- /**
- * Generate a run of (ideally) cryptographically random data and return
- * it in raw binary form.
- * You can use MWCryptRand::wasStrong() if you wish to know if the source used
- * was cryptographically strong.
- *
- * @param int $bytes the number of bytes of random data to generate
- * @param bool $forceStrong Pass true if you want generate to prefer cryptographically
- * strong sources of entropy even if reading from them may steal
- * more entropy from the system than optimal.
- * @return String Raw binary random data
- */
- public static function generate( $bytes, $forceStrong = false ) {
- return self::singleton()->realGenerate( $bytes, $forceStrong );
- }
-
- /**
- * Generate a run of (ideally) cryptographically random data and return
- * it in hexadecimal string format.
- * You can use MWCryptRand::wasStrong() if you wish to know if the source used
- * was cryptographically strong.
- *
- * @param int $chars the number of hex chars of random data to generate
- * @param bool $forceStrong Pass true if you want generate to prefer cryptographically
- * strong sources of entropy even if reading from them may steal
- * more entropy from the system than optimal.
- * @return String Hexadecimal random data
- */
- public static function generateHex( $chars, $forceStrong = false ) {
- return self::singleton()->realGenerateHex( $chars, $forceStrong );
- }
-
-}
$wgVectorUseIconWatch = true;
/**
- * Use VForm design for Special:Userlogin. This can be overridden by
- * a useNew bool in the query string. For instance, if it is globally
- * false, you can try it with useNew=1.
+ * Use compact vertical form ("VForm") design for Special:Userlogin. This can
+ * be overridden by a useNew bool in the query string. For instance, if it is
+ * globally false, you can try it with useNew=1.
+ *
+ * @since 1.22
*/
$wgUseVFormUserLogin = false;
+/**
+ * Use compact vertical form ("VForm") design for account creation
+ * (Special:Userlogin?type=signup).
+ *
+ * @since 1.22
+ */
+$wgUseVFormCreateAccount = false;
+
/**
* Display user edit counts in various prominent places.
*/
case self::AS_SUCCESS_NEW_ARTICLE:
$query = $resultDetails['redirect'] ? 'redirect=no' : '';
- $anchor = isset ( $resultDetails['sectionanchor'] ) ? $resultDetails['sectionanchor'] : '';
+ $anchor = isset( $resultDetails['sectionanchor'] ) ? $resultDetails['sectionanchor'] : '';
$wgOut->redirect( $this->mTitle->getFullURL( $query ) . $anchor );
return false;
*/
class UserBlockedError extends ErrorPageError {
public function __construct( Block $block ) {
- global $wgLang, $wgRequest;
-
- $blocker = $block->getBlocker();
- if ( $blocker instanceof User ) { // local user
- $blockerUserpage = $block->getBlocker()->getUserPage();
- $link = "[[{$blockerUserpage->getPrefixedText()}|{$blockerUserpage->getText()}]]";
- } else { // foreign user
- $link = $blocker;
- }
-
- $reason = $block->mReason;
- if ( $reason == '' ) {
- $reason = wfMessage( 'blockednoreason' )->text();
- }
-
- /* $ip returns who *is* being blocked, $intended contains who was meant to be blocked.
- * This could be a username, an IP range, or a single IP. */
- $intended = $block->getTarget();
-
- parent::__construct(
- 'blockedtitle',
- $block->mAuto ? 'autoblockedtext' : 'blockedtext',
- array(
- $link,
- $reason,
- $wgRequest->getIP(),
- $block->getByName(),
- $block->getId(),
- $wgLang->formatExpiry( $block->mExpiry ),
- $intended,
- $wgLang->timeanddate( wfTimestamp( TS_MW, $block->mTimestamp ), true )
- )
- );
+ // @todo FIXME: Implement a more proper way to get context here.
+ $params = $block->getPermissionsError( RequestContext::getMain() );
+ parent::__construct( 'blockedtitle', array_shift( $params ), $params );
}
}
$default = $this->options[$name]['default'];
$type = $this->options[$name]['type'];
- switch( $type ) {
+ switch ( $type ) {
case self::BOOL:
$value = $r->getBool( $name, $default );
break;
}
/**
- * Execute a shell command, with time and memory limits mirrored from the PHP
- * configuration if supported.
- * @param string $cmd Command line, properly escaped for shell.
- * @param &$retval null|Mixed optional, will receive the program's exit code.
- * (non-zero is usually failure)
- * @param array $environ optional environment variables which should be
- * added to the executed command environment.
- * @param array $limits optional array with limits(filesize, memory, time, walltime)
- * this overwrites the global wgShellMax* limits.
- * @return string collected stdout as a string (trailing newlines stripped)
+ * Check if wfShellExec() is effectively disabled via php.ini config
+ * @return bool|string False or one of (safemode,disabled)
+ * @since 1.22
*/
-function wfShellExec( $cmd, &$retval = null, $environ = array(), $limits = array() ) {
- global $IP, $wgMaxShellMemory, $wgMaxShellFileSize, $wgMaxShellTime,
- $wgMaxShellWallClockTime, $wgShellCgroup;
-
- static $disabled;
+function wfShellExecDisabled() {
+ static $disabled = null;
if ( is_null( $disabled ) ) {
$disabled = false;
if ( wfIniGetBool( 'safe_mode' ) ) {
}
}
}
+ return $disabled;
+}
+
+/**
+ * Execute a shell command, with time and memory limits mirrored from the PHP
+ * configuration if supported.
+ * @param string $cmd Command line, properly escaped for shell.
+ * @param &$retval null|Mixed optional, will receive the program's exit code.
+ * (non-zero is usually failure)
+ * @param array $environ optional environment variables which should be
+ * added to the executed command environment.
+ * @param array $limits optional array with limits(filesize, memory, time, walltime)
+ * this overwrites the global wgShellMax* limits.
+ * @return string collected stdout as a string (trailing newlines stripped)
+ */
+function wfShellExec( $cmd, &$retval = null, $environ = array(), $limits = array() ) {
+ global $IP, $wgMaxShellMemory, $wgMaxShellFileSize, $wgMaxShellTime,
+ $wgMaxShellWallClockTime, $wgShellCgroup;
+
+ $disabled = wfShellExecDisabled();
if ( $disabled ) {
$retval = 1;
return $disabled == 'safemode' ?
}
$last = $string[strlen( $string ) - 1];
$val = intval( $string );
- switch( $last ) {
+ switch ( $last ) {
case 'g':
case 'G':
$val *= 1024;
* Add a submit button inline in the form (as opposed to
* HTMLForm::addButton(), which will add it at the end).
*/
-class HTMLSubmitField extends HTMLFormField {
+class HTMLSubmitField extends HTMLButtonField {
+ protected $buttonType = 'submit';
+}
+
+/**
+ * Adds a generic button inline to the form. Does not do anything, you must add
+ * click handling code in JavaScript. Use a HTMLSubmitField if you merely
+ * wish to add a submit button to a form.
+ *
+ * @since 1.22
+ */
+class HTMLButtonField extends HTMLFormField {
+ protected $buttonType = 'button';
public function __construct( $info ) {
$info['nodata'] = true;
public function getInputHTML( $value ) {
$attr = array(
'class' => 'mw-htmlform-submit ' . $this->mClass,
- 'name' => $this->mName,
'id' => $this->mID,
);
$attr['disabled'] = 'disabled';
}
- return Xml::submitButton( $value, $attr );
+ return Html::input(
+ $this->mName,
+ $value,
+ $this->buttonType,
+ $attr
+ );
}
protected function needsLabel() {
/** @var Array (location => (start, end)) */
protected $ring = array();
- const RING_SIZE = 16777216; // 2^24
+ const RING_SIZE = 268435456; // 2^28
/**
* @param array $map (location => weight)
public function getLocations( $item, $limit ) {
$locations = array();
$primaryLocation = null;
- $spot = hexdec( substr( sha1( $item ), 0, 6 ) ); // first 24 bits
+ $spot = hexdec( substr( sha1( $item ), 0, 7 ) ); // first 28 bits
foreach ( $this->ring as $location => $range ) {
if ( count( $locations ) >= $limit ) {
break;
' Http::$httpEngine is set to "curl"' );
}
- switch( Http::$httpEngine ) {
+ switch ( Http::$httpEngine ) {
case 'curl':
return new CurlHttpRequest( $url, $options );
case 'php':
}
$buffer = "";
while ( $this->reader->read() ) {
- switch( $this->reader->nodeType ) {
+ switch ( $this->reader->nodeType ) {
case XmlReader::TEXT:
case XmlReader::SIGNIFICANT_WHITESPACE:
$buffer .= $this->reader->value;
$lookup = array();
foreach ( $xmlReaderConstants as $name ) {
- $lookup[constant("XmlReader::$name")] = $name;
+ $lookup[constant( "XmlReader::$name" )] = $name;
}
}
}
$buffer = "";
while ( $this->read() ) {
- switch( $this->nodeType ) {
+ switch ( $this->nodeType ) {
case XmlReader::TEXT:
case XmlReader::SIGNIFICANT_WHITESPACE:
$buffer .= $this->value;
return Status::newFatal( 'importnofile' );
}
if ( !empty( $upload['error'] ) ) {
- switch( $upload['error'] ) {
+ switch ( $upload['error'] ) {
case 1: # The uploaded file exceeds the upload_max_filesize directive in php.ini.
return Status::newFatal( 'importuploaderrorsize' );
case 2: # The uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the HTML form.
--- /dev/null
+<?php
+/**
+ * A cryptographic random generator class used for generating secret keys
+ *
+ * This is based in part on Drupal code as well as what we used in our own code
+ * prior to introduction of this class.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ *
+ * @author Daniel Friesen
+ * @file
+ */
+
+class MWCryptRand {
+
+ /**
+ * Minimum number of iterations we want to make in our drift calculations.
+ */
+ const MIN_ITERATIONS = 1000;
+
+ /**
+ * Number of milliseconds we want to spend generating each separate byte
+ * of the final generated bytes.
+ * This is used in combination with the hash length to determine the duration
+ * we should spend doing drift calculations.
+ */
+ const MSEC_PER_BYTE = 0.5;
+
+ /**
+ * Singleton instance for public use
+ */
+ protected static $singleton = null;
+
+ /**
+ * The hash algorithm being used
+ */
+ protected $algo = null;
+
+ /**
+ * The number of bytes outputted by the hash algorithm
+ */
+ protected $hashLength = null;
+
+ /**
+ * A boolean indicating whether the previous random generation was done using
+ * cryptographically strong random number generator or not.
+ */
+ protected $strong = null;
+
+ /**
+ * Initialize an initial random state based off of whatever we can find
+ */
+ protected function initialRandomState() {
+ // $_SERVER contains a variety of unstable user and system specific information
+ // It'll vary a little with each page, and vary even more with separate users
+ // It'll also vary slightly across different machines
+ $state = serialize( $_SERVER );
+
+ // To try vary the system information of the state a bit more
+ // by including the system's hostname into the state
+ $state .= wfHostname();
+
+ // Try to gather a little entropy from the different php rand sources
+ $state .= rand() . uniqid( mt_rand(), true );
+
+ // Include some information about the filesystem's current state in the random state
+ $files = array();
+
+ // We know this file is here so grab some info about ourselves
+ $files[] = __FILE__;
+
+ // We must also have a parent folder, and with the usual file structure, a grandparent
+ $files[] = __DIR__;
+ $files[] = dirname( __DIR__ );
+
+ // The config file is likely the most often edited file we know should be around
+ // so include its stat info into the state.
+ // The constant with its location will almost always be defined, as WebStart.php defines
+ // MW_CONFIG_FILE to $IP/LocalSettings.php unless being configured with MW_CONFIG_CALLBACK (eg. the installer)
+ if ( defined( 'MW_CONFIG_FILE' ) ) {
+ $files[] = MW_CONFIG_FILE;
+ }
+
+ foreach ( $files as $file ) {
+ wfSuppressWarnings();
+ $stat = stat( $file );
+ wfRestoreWarnings();
+ if ( $stat ) {
+ // stat() duplicates data into numeric and string keys so kill off all the numeric ones
+ foreach ( $stat as $k => $v ) {
+ if ( is_numeric( $k ) ) {
+ unset( $k );
+ }
+ }
+ // The absolute filename itself will differ from install to install so don't leave it out
+ if ( ( $path = realpath( $file ) ) !== false ) {
+ $state .= $path;
+ } else {
+ $state .= $file;
+ }
+ $state .= implode( '', $stat );
+ } else {
+ // The fact that the file isn't there is worth at least a
+ // minuscule amount of entropy.
+ $state .= '0';
+ }
+ }
+
+ // Try and make this a little more unstable by including the varying process
+ // id of the php process we are running inside of if we are able to access it
+ if ( function_exists( 'getmypid' ) ) {
+ $state .= getmypid();
+ }
+
+ // If available try to increase the instability of the data by throwing in
+ // the precise amount of memory that we happen to be using at the moment.
+ if ( function_exists( 'memory_get_usage' ) ) {
+ $state .= memory_get_usage( true );
+ }
+
+ // It's mostly worthless but throw the wiki's id into the data for a little more variance
+ $state .= wfWikiID();
+
+ // If we have a secret key or proxy key set then throw it into the state as well
+ global $wgSecretKey, $wgProxyKey;
+ if ( $wgSecretKey ) {
+ $state .= $wgSecretKey;
+ } elseif ( $wgProxyKey ) {
+ $state .= $wgProxyKey;
+ }
+
+ return $state;
+ }
+
+ /**
+ * Randomly hash data while mixing in clock drift data for randomness
+ *
+ * @param string $data The data to randomly hash.
+ * @return String The hashed bytes
+ * @author Tim Starling
+ */
+ protected function driftHash( $data ) {
+ // Minimum number of iterations (to avoid slow operations causing the loop to gather little entropy)
+ $minIterations = self::MIN_ITERATIONS;
+ // Duration of time to spend doing calculations (in seconds)
+ $duration = ( self::MSEC_PER_BYTE / 1000 ) * $this->hashLength();
+ // Create a buffer to use to trigger memory operations
+ $bufLength = 10000000;
+ $buffer = str_repeat( ' ', $bufLength );
+ $bufPos = 0;
+
+ // Iterate for $duration seconds or at least $minIterations number of iterations
+ $iterations = 0;
+ $startTime = microtime( true );
+ $currentTime = $startTime;
+ while ( $iterations < $minIterations || $currentTime - $startTime < $duration ) {
+ // Trigger some memory writing to trigger some bus activity
+ // This may create variance in the time between iterations
+ $bufPos = ( $bufPos + 13 ) % $bufLength;
+ $buffer[$bufPos] = ' ';
+ // Add the drift between this iteration and the last in as entropy
+ $nextTime = microtime( true );
+ $delta = (int)( ( $nextTime - $currentTime ) * 1000000 );
+ $data .= $delta;
+ // Every 100 iterations hash the data and entropy
+ if ( $iterations % 100 === 0 ) {
+ $data = sha1( $data );
+ }
+ $currentTime = $nextTime;
+ $iterations++;
+ }
+ $timeTaken = $currentTime - $startTime;
+ $data = $this->hash( $data );
+
+ wfDebug( __METHOD__ . ": Clock drift calculation " .
+ "(time-taken=" . ( $timeTaken * 1000 ) . "ms, " .
+ "iterations=$iterations, " .
+ "time-per-iteration=" . ( $timeTaken / $iterations * 1e6 ) . "us)\n" );
+ return $data;
+ }
+
+ /**
+ * Return a rolling random state initially build using data from unstable sources
+ * @return string A new weak random state
+ */
+ protected function randomState() {
+ static $state = null;
+ if ( is_null( $state ) ) {
+ // Initialize the state with whatever unstable data we can find
+ // It's important that this data is hashed right afterwards to prevent
+ // it from being leaked into the output stream
+ $state = $this->hash( $this->initialRandomState() );
+ }
+ // Generate a new random state based on the initial random state or previous
+ // random state by combining it with clock drift
+ $state = $this->driftHash( $state );
+ return $state;
+ }
+
+ /**
+ * Decide on the best acceptable hash algorithm we have available for hash()
+ * @throws MWException
+ * @return String A hash algorithm
+ */
+ protected function hashAlgo() {
+ if ( !is_null( $this->algo ) ) {
+ return $this->algo;
+ }
+
+ $algos = hash_algos();
+ $preference = array( 'whirlpool', 'sha256', 'sha1', 'md5' );
+
+ foreach ( $preference as $algorithm ) {
+ if ( in_array( $algorithm, $algos ) ) {
+ $this->algo = $algorithm;
+ wfDebug( __METHOD__ . ": Using the {$this->algo} hash algorithm.\n" );
+ return $this->algo;
+ }
+ }
+
+ // We only reach here if no acceptable hash is found in the list, this should
+ // be a technical impossibility since most of php's hash list is fixed and
+ // some of the ones we list are available as their own native functions
+ // But since we already require at least 5.2 and hash() was default in
+ // 5.1.2 we don't bother falling back to methods like sha1 and md5.
+ throw new MWException( "Could not find an acceptable hashing function in hash_algos()" );
+ }
+
+ /**
+ * Return the byte-length output of the hash algorithm we are
+ * using in self::hash and self::hmac.
+ *
+ * @return int Number of bytes the hash outputs
+ */
+ protected function hashLength() {
+ if ( is_null( $this->hashLength ) ) {
+ $this->hashLength = strlen( $this->hash( '' ) );
+ }
+ return $this->hashLength;
+ }
+
+ /**
+ * Generate an acceptably unstable one-way-hash of some text
+ * making use of the best hash algorithm that we have available.
+ *
+ * @param $data string
+ * @return String A raw hash of the data
+ */
+ protected function hash( $data ) {
+ return hash( $this->hashAlgo(), $data, true );
+ }
+
+ /**
+ * Generate an acceptably unstable one-way-hmac of some text
+ * making use of the best hash algorithm that we have available.
+ *
+ * @param $data string
+ * @param $key string
+ * @return String A raw hash of the data
+ */
+ protected function hmac( $data, $key ) {
+ return hash_hmac( $this->hashAlgo(), $data, $key, true );
+ }
+
+ /**
+ * @see self::wasStrong()
+ */
+ public function realWasStrong() {
+ if ( is_null( $this->strong ) ) {
+ throw new MWException( __METHOD__ . ' called before generation of random data' );
+ }
+ return $this->strong;
+ }
+
+ /**
+ * @see self::generate()
+ */
+ public function realGenerate( $bytes, $forceStrong = false ) {
+ wfProfileIn( __METHOD__ );
+
+ wfDebug( __METHOD__ . ": Generating cryptographic random bytes for " . wfGetAllCallers( 5 ) . "\n" );
+
+ $bytes = floor( $bytes );
+ static $buffer = '';
+ if ( is_null( $this->strong ) ) {
+ // Set strength to false initially until we know what source data is coming from
+ $this->strong = true;
+ }
+
+ if ( strlen( $buffer ) < $bytes ) {
+ // If available make use of mcrypt_create_iv URANDOM source to generate randomness
+ // On unix-like systems this reads from /dev/urandom but does it without any buffering
+ // and bypasses openbasedir restrictions, so it's preferable to reading directly
+ // On Windows starting in PHP 5.3.0 Windows' native CryptGenRandom is used to generate
+ // entropy so this is also preferable to just trying to read urandom because it may work
+ // on Windows systems as well.
+ if ( function_exists( 'mcrypt_create_iv' ) ) {
+ wfProfileIn( __METHOD__ . '-mcrypt' );
+ $rem = $bytes - strlen( $buffer );
+ $iv = mcrypt_create_iv( $rem, MCRYPT_DEV_URANDOM );
+ if ( $iv === false ) {
+ wfDebug( __METHOD__ . ": mcrypt_create_iv returned false.\n" );
+ } else {
+ $buffer .= $iv;
+ wfDebug( __METHOD__ . ": mcrypt_create_iv generated " . strlen( $iv ) . " bytes of randomness.\n" );
+ }
+ wfProfileOut( __METHOD__ . '-mcrypt' );
+ }
+ }
+
+ if ( strlen( $buffer ) < $bytes ) {
+ // If available make use of openssl's random_pseudo_bytes method to attempt to generate randomness.
+ // However don't do this on Windows with PHP < 5.3.4 due to a bug:
+ // http://stackoverflow.com/questions/1940168/openssl-random-pseudo-bytes-is-slow-php
+ // http://git.php.net/?p=php-src.git;a=commitdiff;h=cd62a70863c261b07f6dadedad9464f7e213cad5
+ if ( function_exists( 'openssl_random_pseudo_bytes' )
+ && ( !wfIsWindows() || version_compare( PHP_VERSION, '5.3.4', '>=' ) )
+ ) {
+ wfProfileIn( __METHOD__ . '-openssl' );
+ $rem = $bytes - strlen( $buffer );
+ $openssl_bytes = openssl_random_pseudo_bytes( $rem, $openssl_strong );
+ if ( $openssl_bytes === false ) {
+ wfDebug( __METHOD__ . ": openssl_random_pseudo_bytes returned false.\n" );
+ } else {
+ $buffer .= $openssl_bytes;
+ wfDebug( __METHOD__ . ": openssl_random_pseudo_bytes generated " . strlen( $openssl_bytes ) . " bytes of " . ( $openssl_strong ? "strong" : "weak" ) . " randomness.\n" );
+ }
+ if ( strlen( $buffer ) >= $bytes ) {
+ // openssl tells us if the random source was strong, if some of our data was generated
+ // using it use it's say on whether the randomness is strong
+ $this->strong = !!$openssl_strong;
+ }
+ wfProfileOut( __METHOD__ . '-openssl' );
+ }
+ }
+
+ // Only read from urandom if we can control the buffer size or were passed forceStrong
+ if ( strlen( $buffer ) < $bytes && ( function_exists( 'stream_set_read_buffer' ) || $forceStrong ) ) {
+ wfProfileIn( __METHOD__ . '-fopen-urandom' );
+ $rem = $bytes - strlen( $buffer );
+ if ( !function_exists( 'stream_set_read_buffer' ) && $forceStrong ) {
+ wfDebug( __METHOD__ . ": Was forced to read from /dev/urandom without control over the buffer size.\n" );
+ }
+ // /dev/urandom is generally considered the best possible commonly
+ // available random source, and is available on most *nix systems.
+ wfSuppressWarnings();
+ $urandom = fopen( "/dev/urandom", "rb" );
+ wfRestoreWarnings();
+
+ // Attempt to read all our random data from urandom
+ // php's fread always does buffered reads based on the stream's chunk_size
+ // so in reality it will usually read more than the amount of data we're
+ // asked for and not storing that risks depleting the system's random pool.
+ // If stream_set_read_buffer is available set the chunk_size to the amount
+ // of data we need. Otherwise read 8k, php's default chunk_size.
+ if ( $urandom ) {
+ // php's default chunk_size is 8k
+ $chunk_size = 1024 * 8;
+ if ( function_exists( 'stream_set_read_buffer' ) ) {
+ // If possible set the chunk_size to the amount of data we need
+ stream_set_read_buffer( $urandom, $rem );
+ $chunk_size = $rem;
+ }
+ $random_bytes = fread( $urandom, max( $chunk_size, $rem ) );
+ $buffer .= $random_bytes;
+ fclose( $urandom );
+ wfDebug( __METHOD__ . ": /dev/urandom generated " . strlen( $random_bytes ) . " bytes of randomness.\n" );
+ if ( strlen( $buffer ) >= $bytes ) {
+ // urandom is always strong, set to true if all our data was generated using it
+ $this->strong = true;
+ }
+ } else {
+ wfDebug( __METHOD__ . ": /dev/urandom could not be opened.\n" );
+ }
+ wfProfileOut( __METHOD__ . '-fopen-urandom' );
+ }
+
+ // If we cannot use or generate enough data from a secure source
+ // use this loop to generate a good set of pseudo random data.
+ // This works by initializing a random state using a pile of unstable data
+ // and continually shoving it through a hash along with a variable salt.
+ // We hash the random state with more salt to avoid the state from leaking
+ // out and being used to predict the /randomness/ that follows.
+ if ( strlen( $buffer ) < $bytes ) {
+ wfDebug( __METHOD__ . ": Falling back to using a pseudo random state to generate randomness.\n" );
+ }
+ while ( strlen( $buffer ) < $bytes ) {
+ wfProfileIn( __METHOD__ . '-fallback' );
+ $buffer .= $this->hmac( $this->randomState(), mt_rand() );
+ // This code is never really cryptographically strong, if we use it
+ // at all, then set strong to false.
+ $this->strong = false;
+ wfProfileOut( __METHOD__ . '-fallback' );
+ }
+
+ // Once the buffer has been filled up with enough random data to fulfill
+ // the request shift off enough data to handle the request and leave the
+ // unused portion left inside the buffer for the next request for random data
+ $generated = substr( $buffer, 0, $bytes );
+ $buffer = substr( $buffer, $bytes );
+
+ wfDebug( __METHOD__ . ": " . strlen( $buffer ) . " bytes of randomness leftover in the buffer.\n" );
+
+ wfProfileOut( __METHOD__ );
+ return $generated;
+ }
+
+ /**
+ * @see self::generateHex()
+ */
+ public function realGenerateHex( $chars, $forceStrong = false ) {
+ // hex strings are 2x the length of raw binary so we divide the length in half
+ // odd numbers will result in a .5 that leads the generate() being 1 character
+ // short, so we use ceil() to ensure that we always have enough bytes
+ $bytes = ceil( $chars / 2 );
+ // Generate the data and then convert it to a hex string
+ $hex = bin2hex( $this->generate( $bytes, $forceStrong ) );
+ // A bit of paranoia here, the caller asked for a specific length of string
+ // here, and it's possible (eg when given an odd number) that we may actually
+ // have at least 1 char more than they asked for. Just in case they made this
+ // call intending to insert it into a database that does truncation we don't
+ // want to give them too much and end up with their database and their live
+ // code having two different values because part of what we gave them is truncated
+ // hence, we strip out any run of characters longer than what we were asked for.
+ return substr( $hex, 0, $chars );
+ }
+
+ /** Publicly exposed static methods **/
+
+ /**
+ * Return a singleton instance of MWCryptRand
+ * @return MWCryptRand
+ */
+ protected static function singleton() {
+ if ( is_null( self::$singleton ) ) {
+ self::$singleton = new self;
+ }
+ return self::$singleton;
+ }
+
+ /**
+ * Return a boolean indicating whether or not the source used for cryptographic
+ * random bytes generation in the previously run generate* call
+ * was cryptographically strong.
+ *
+ * @return bool Returns true if the source was strong, false if not.
+ */
+ public static function wasStrong() {
+ return self::singleton()->realWasStrong();
+ }
+
+ /**
+ * Generate a run of (ideally) cryptographically random data and return
+ * it in raw binary form.
+ * You can use MWCryptRand::wasStrong() if you wish to know if the source used
+ * was cryptographically strong.
+ *
+ * @param int $bytes the number of bytes of random data to generate
+ * @param bool $forceStrong Pass true if you want generate to prefer cryptographically
+ * strong sources of entropy even if reading from them may steal
+ * more entropy from the system than optimal.
+ * @return String Raw binary random data
+ */
+ public static function generate( $bytes, $forceStrong = false ) {
+ return self::singleton()->realGenerate( $bytes, $forceStrong );
+ }
+
+ /**
+ * Generate a run of (ideally) cryptographically random data and return
+ * it in hexadecimal string format.
+ * You can use MWCryptRand::wasStrong() if you wish to know if the source used
+ * was cryptographically strong.
+ *
+ * @param int $chars the number of hex chars of random data to generate
+ * @param bool $forceStrong Pass true if you want generate to prefer cryptographically
+ * strong sources of entropy even if reading from them may steal
+ * more entropy from the system than optimal.
+ * @return String Hexadecimal random data
+ */
+ public static function generateHex( $chars, $forceStrong = false ) {
+ return self::singleton()->realGenerateHex( $chars, $forceStrong );
+ }
+
+}
'numberofactiveusers',
'numberofpages',
'currentversion',
+ 'rootpagename',
+ 'rootpagenamee',
'basepagename',
'basepagenamee',
'currenttimestamp',
}
/* Look for WebP */
- if ( strncmp( $head, "RIFF", 4 ) == 0 && strncmp( substr( $head, 8, 8), "WEBPVP8 ", 8 ) == 0 ) {
+ if ( strncmp( $head, "RIFF", 4 ) == 0 && strncmp( substr( $head, 8, 8 ), "WEBPVP8 ", 8 ) == 0 ) {
wfDebug( __METHOD__ . ": recognized file as image/webp\n" );
return "image/webp";
}
}
wfDebug( __METHOD__ . ": detected an Open Packaging Conventions archive: $mime\n" );
} elseif ( substr( $header, 0, 8 ) == "\xd0\xcf\x11\xe0\xa1\xb1\x1a\xe1" &&
- ($headerpos = strpos( $tail, "PK\x03\x04" ) ) !== false &&
+ ( $headerpos = strpos( $tail, "PK\x03\x04" ) ) !== false &&
preg_match( $openxmlRegex, substr( $tail, $headerpos + 30 ) ) ) {
if ( substr( $header, 512, 4 ) == "\xEC\xA5\xC1\x00" ) {
$mime = "application/msword";
}
- switch( substr( $header, 512, 6 ) ) {
+ switch ( substr( $header, 512, 6 ) ) {
case "\xEC\xA5\xC1\x00\x0E\x00":
case "\xEC\xA5\xC1\x00\x1C\x00":
case "\xEC\xA5\xC1\x00\x43\x00":
$m = null;
if ( $wgMimeDetectorCommand ) {
- // @todo FIXME: Use wfShellExec
- $fn = wfEscapeShellArg( $file );
- $m = `$wgMimeDetectorCommand $fn`;
+ $args = wfEscapeShellArg( $file );
+ $m = wfShellExec( "$wgMimeDetectorCommand $args" );
} elseif ( function_exists( "finfo_open" ) && function_exists( "finfo_file" ) ) {
# This required the fileinfo extension by PECL,
}
/**
- * Get the result of the work (whatever it is), or false.
+ * Get the result of the work (whatever it is), or the result of the error() function.
+ * This returns the result of the first applicable method that returns a non-false value,
+ * where the methods are checked in the following order:
+ * - a) doWork() : Applies if the work is exclusive or no another process
+ * is doing it, and on the condition that either this process
+ * successfully entered the pool or the pool counter is down.
+ * - b) doCachedWork() : Applies if the work is cacheable and this blocked on another
+ * process which finished the work.
+ * - c) fallback() : Applies for all remaining cases.
+ * If these all fall through (by returning false), then the result of error() is returned.
+ *
* @param $skipcache bool
- * @return bool|mixed
+ * @return mixed
*/
public function execute( $skipcache = false ) {
if ( $this->cacheable && !$skipcache ) {
return ChangesList::showCharacterDifference( $old, $new );
}
+ /**
+ * Purge expired changes from the recentchanges table
+ * @since 1.22
+ */
+ public static function purgeExpiredChanges() {
+ if ( wfReadOnly() ) {
+ return;
+ }
+
+ $method = __METHOD__;
+ $dbw = wfGetDB( DB_MASTER );
+ $dbw->onTransactionIdle( function() use ( $dbw, $method ) {
+ global $wgRCMaxAge;
+
+ $cutoff = $dbw->timestamp( time() - $wgRCMaxAge );
+ $dbw->delete(
+ 'recentchanges',
+ array( 'rc_timestamp < ' . $dbw->addQuotes( $cutoff ) ),
+ $method
+ );
+ } );
+ }
+
private static function checkIPAddress( $ip ) {
global $wgRequest;
if ( $ip ) {
if ( $title->isTalkPage() ) {
$link = $title->getSubjectPage();
- switch( $link->getNamespace() ) {
+ switch ( $link->getNamespace() ) {
case NS_MAIN:
$text = wfMessage( 'articlepage' );
break;
}
function makeSearchButton( $mode, $attrs = array() ) {
- switch( $mode ) {
+ switch ( $mode ) {
case 'go':
case 'fulltext':
$realAttrs = array(
*
* @file
* @ingroup StatCounter
+ * @author Aaron Schulz
*/
/**
$this->deltas = array();
}
+ /**
+ * @param array $deltas
+ * @return void
+ */
protected function sendDeltasUDP( array $deltas ) {
global $wgUDPProfilerHost, $wgUDPProfilerPort, $wgAggregateStatsID;
}
}
+ /**
+ * @param array $deltas
+ * @return void
+ */
protected function sendDeltasMemc( array $deltas ) {
global $wgMemc;
*/
public function getTalkNsText() {
global $wgContLang;
- return( $wgContLang->getNsText( MWNamespace::getTalk( $this->mNamespace ) ) );
+ return $wgContLang->getNsText( MWNamespace::getTalk( $this->mNamespace ) );
}
/**
* @return Bool TRUE or FALSE
*/
public function canTalk() {
- return( MWNamespace::canTalk( $this->mNamespace ) );
+ return MWNamespace::canTalk( $this->mNamespace );
}
/**
*/
public function getSubpageText() {
if ( !MWNamespace::hasSubpages( $this->mNamespace ) ) {
- return( $this->mTextform );
+ return $this->mTextform;
}
$parts = explode( '/', $this->mTextform );
- return( $parts[count( $parts ) - 1] );
+ return $parts[count( $parts ) - 1];
}
/**
public function getSubpageUrlForm() {
$text = $this->getSubpageText();
$text = wfUrlencode( str_replace( ' ', '_', $text ) );
- return( $text );
+ return $text;
}
/**
return $errors;
}
- global $wgContLang, $wgLang, $wgEmailConfirmToEdit;
+ global $wgEmailConfirmToEdit;
if ( $wgEmailConfirmToEdit && !$user->isEmailConfirmed() ) {
$errors[] = array( 'confirmedittext' );
// Don't block the user from editing their own talk page unless they've been
// explicitly blocked from that too.
} elseif ( $user->isBlocked() && $user->mBlock->prevents( $action ) !== false ) {
- $block = $user->getBlock();
-
- // This is from OutputPage::blockedPage
- // Copied at r23888 by werdna
-
- $id = $user->blockedBy();
- $reason = $user->blockedFor();
- if ( $reason == '' ) {
- $reason = wfMessage( 'blockednoreason' )->text();
- }
- $ip = $user->getRequest()->getIP();
-
- if ( is_numeric( $id ) ) {
- $name = User::whoIs( $id );
- } else {
- $name = $id;
- }
-
- $link = '[[' . $wgContLang->getNsText( NS_USER ) . ":{$name}|{$name}]]";
- $blockid = $block->getId();
- $blockExpiry = $block->getExpiry();
- $blockTimestamp = $wgLang->timeanddate( wfTimestamp( TS_MW, $block->mTimestamp ), true );
- if ( $blockExpiry == 'infinity' ) {
- $blockExpiry = wfMessage( 'infiniteblock' )->text();
- } else {
- $blockExpiry = $wgLang->timeanddate( wfTimestamp( TS_MW, $blockExpiry ), true );
- }
-
- $intended = strval( $block->getTarget() );
-
- $errors[] = array( ( $block->mAuto ? 'autoblockedtext' : 'blockedtext' ), $link, $reason, $ip, $name,
- $blockid, $blockExpiry, $intended, $blockTimestamp );
+ // @todo FIXME: Pass the relevant context into this function.
+ $errors[] = $user->getBlock()->getPermissionsError( RequestContext::getMain() );
}
return $errors;
return true; // any interwiki link might be viewable, for all we know
}
- switch( $this->mNamespace ) {
+ switch ( $this->mNamespace ) {
case NS_MEDIA:
case NS_FILE:
// file exists, possibly in a foreign repo
$dbw = wfGetDB( DB_MASTER );
$userid = $this->mId;
$touched = $this->mTouched;
- $dbw->onTransactionIdle( function() use ( $dbw, $userid, $touched ) {
+ $method = __METHOD__;
+ $dbw->onTransactionIdle( function() use ( $dbw, $userid, $touched, $method ) {
// Prevent contention slams by checking user_touched first
$encTouched = $dbw->addQuotes( $dbw->timestamp( $touched ) );
$needsPurge = $dbw->selectField( 'user', '1',
$dbw->update( 'user',
array( 'user_touched' => $dbw->timestamp( $touched ) ),
array( 'user_id' => $userid, 'user_touched < ' . $encTouched ),
- __METHOD__
+ $method
);
}
} );
}
$this->loadGroups();
$this->mGroups[] = $group;
+ // In case loadGroups was not called before, we now have the right twice.
+ // Get rid of the duplicate.
+ $this->mGroups = array_unique( $this->mGroups );
$this->mRights = User::getGroupPermissions( $this->getEffectiveGroups( true ) );
$this->invalidateCache();
* Do a job from the job queue
*/
private function doJobs() {
- global $wgJobRunRate;
+ global $wgJobRunRate, $wgPhpCli, $IP;
if ( $wgJobRunRate <= 0 || wfReadOnly() ) {
return;
$n = intval( $wgJobRunRate );
}
- $group = JobQueueGroup::singleton();
- do {
- $job = $group->pop( JobQueueGroup::USE_CACHE ); // job from any queue
- if ( $job ) {
- $output = $job->toString() . "\n";
- $t = - microtime( true );
- wfProfileIn( __METHOD__ . '-' . get_class( $job ) );
- $success = $job->run();
- wfProfileOut( __METHOD__ . '-' . get_class( $job ) );
- $group->ack( $job ); // done
- $t += microtime( true );
- $t = round( $t * 1000 );
- if ( $success === false ) {
- $output .= "Error: " . $job->getLastError() . ", Time: $t ms\n";
- } else {
- $output .= "Success, Time: $t ms\n";
+ if ( !wfShellExecDisabled() && is_executable( $wgPhpCli ) ) {
+ // Start a background process to run some of the jobs.
+ // This will be asynchronous on *nix though not on Windows.
+ wfProfileIn( __METHOD__ . '-exec' );
+ $retVal = 1;
+ $cmd = wfShellWikiCmd( "$IP/maintenance/runJobs.php", array( '--maxjobs', $n ) );
+ wfShellExec( "$cmd &", $retVal );
+ wfProfileOut( __METHOD__ . '-exec' );
+ } else {
+ // Fallback to running the jobs here while the user waits
+ $group = JobQueueGroup::singleton();
+ do {
+ $job = $group->pop( JobQueueGroup::USE_CACHE ); // job from any queue
+ if ( $job ) {
+ $output = $job->toString() . "\n";
+ $t = - microtime( true );
+ wfProfileIn( __METHOD__ . '-' . get_class( $job ) );
+ $success = $job->run();
+ wfProfileOut( __METHOD__ . '-' . get_class( $job ) );
+ $group->ack( $job ); // done
+ $t += microtime( true );
+ $t = round( $t * 1000 );
+ if ( $success === false ) {
+ $output .= "Error: " . $job->getLastError() . ", Time: $t ms\n";
+ } else {
+ $output .= "Success, Time: $t ms\n";
+ }
+ wfDebugLog( 'jobqueue', $output );
}
- wfDebugLog( 'jobqueue', $output );
- }
- } while ( --$n && $job );
+ } while ( --$n && $job );
+ }
}
}
if ( 0 == mt_rand( 0, 99 ) ) {
// Flush old entries from the `recentchanges` table; we do this on
// random requests so as to avoid an increase in writes for no good reason
- global $wgRCMaxAge;
-
- $dbw = wfGetDB( DB_MASTER );
- $cutoff = $dbw->timestamp( time() - $wgRCMaxAge );
- $dbw->delete(
- 'recentchanges',
- array( 'rc_timestamp < ' . $dbw->addQuotes( $cutoff ) ),
- __METHOD__
- );
+ RecentChange::purgeExpiredChanges();
}
}
}
break;
case 'integer': // Force everything using intval() and optionally validate limits
- $min = isset ( $paramSettings[self::PARAM_MIN] ) ? $paramSettings[self::PARAM_MIN] : null;
- $max = isset ( $paramSettings[self::PARAM_MAX] ) ? $paramSettings[self::PARAM_MAX] : null;
- $enforceLimits = isset ( $paramSettings[self::PARAM_RANGE_ENFORCE] )
+ $min = isset( $paramSettings[self::PARAM_MIN] ) ? $paramSettings[self::PARAM_MIN] : null;
+ $max = isset( $paramSettings[self::PARAM_MAX] ) ? $paramSettings[self::PARAM_MAX] : null;
+ $enforceLimits = isset( $paramSettings[self::PARAM_RANGE_ENFORCE] )
? $paramSettings[self::PARAM_RANGE_ENFORCE] : false;
if ( is_array( $value ) ) {
$requestArray['wpStarttime'] = wfTimestampNow(); // Fake wpStartime
}
- if ( $params['minor'] || ( !$params['notminor'] && $user->getOption( 'minordefault' ) ) ) {
+ if ( $params['minor'] || ( !$params['notminor'] && $user->getOption( 'minordefault' ) ) ) {
$requestArray['wpMinoredit'] = '';
}
$wgRequest = $oldRequest;
global $wgMaxArticleSize;
- switch( $status->value ) {
+ switch ( $status->value ) {
case EditPage::AS_HOOK_ERROR:
case EditPage::AS_HOOK_ERROR_EXPECTED:
$this->dieUsageMsg( 'hookaborted' );
protected function feedItem( $row ) {
$title = Title::makeTitle( intval( $row->page_namespace ), $row->page_title );
- if ( $title ) {
+ if( $title && $title->userCan( 'read' ) ) {
$date = $row->rev_timestamp;
$comments = $title->getTalkPage()->getFullURL();
$revision = Revision::newFromRow( $row );
$this->feedItemAuthor( $revision ),
$comments
);
- } else {
- return null;
}
+ return null;
}
/**
unset( $elemValue[$subElemId] );
} elseif ( is_array( $subElemValue ) ) {
$subElements[$subElemId] = $subElemValue;
- unset ( $elemValue[$subElemId] );
+ unset( $elemValue[$subElemId] );
}
}
$result = $this->getResult();
// Printer may not be initialized if the extractRequestParams() fails for the main module
- if ( !isset ( $this->mPrinter ) ) {
+ if ( !isset( $this->mPrinter ) ) {
// The printer has not been created yet. Try to manually get formatter value.
$value = $this->getRequest()->getVal( 'format', self::API_DEFAULT_FORMAT );
if ( !$this->mModuleMgr->isDefined( $value, 'format' ) ) {
if ( !$isDryRun ) {
// Populate page information with the original user input
- switch( $dataSource ) {
+ switch ( $dataSource ) {
case 'titles':
$this->initFromTitles( $this->mParams['titles'] );
break;
* @return array of raw_prefixed_title (string) => prefixed_title (string)
* @since 1.21
*/
- public function getNormalizedTitlesAsResult( $result = null ) {
+ public function getNormalizedTitlesAsResult( $result = null ) {
$values = array();
foreach ( $this->getNormalizedTitles() as $rawTitleStr => $titleStr ) {
$values[] = array(
$show = array_flip( $params['show'] );
/* Check for conflicting parameters. */
- if ( ( isset ( $show['account'] ) && isset ( $show['!account'] ) )
- || ( isset ( $show['ip'] ) && isset ( $show['!ip'] ) )
- || ( isset ( $show['range'] ) && isset ( $show['!range'] ) )
- || ( isset ( $show['temp'] ) && isset ( $show['!temp'] ) )
+ if ( ( isset( $show['account'] ) && isset( $show['!account'] ) )
+ || ( isset( $show['ip'] ) && isset( $show['!ip'] ) )
+ || ( isset( $show['range'] ) && isset( $show['!range'] ) )
+ || ( isset( $show['temp'] ) && isset( $show['!temp'] ) )
) {
$this->dieUsageMsg( 'show' );
}
$fld_user = isset( $prop['user'] );
$fld_userid = isset( $prop['userid'] );
$fld_comment = isset( $prop['comment'] );
- $fld_parsedcomment = isset ( $prop['parsedcomment'] );
+ $fld_parsedcomment = isset( $prop['parsedcomment'] );
$fld_minor = isset( $prop['minor'] );
$fld_len = isset( $prop['len'] );
$fld_sha1 = isset( $prop['sha1'] );
$this->fld_ids = isset( $prop['ids'] );
$this->fld_title = isset( $prop['title'] );
$this->fld_type = isset( $prop['type'] );
- $this->fld_action = isset ( $prop['action'] );
+ $this->fld_action = isset( $prop['action'] );
$this->fld_user = isset( $prop['user'] );
$this->fld_userid = isset( $prop['userid'] );
$this->fld_timestamp = isset( $prop['timestamp'] );
$this->fld_comment = isset( $prop['comment'] );
- $this->fld_parsedcomment = isset ( $prop['parsedcomment'] );
+ $this->fld_parsedcomment = isset( $prop['parsedcomment'] );
$this->fld_details = isset( $prop['details'] );
$this->fld_tags = isset( $prop['tags'] );
}
return $retval;
}
- switch( $type ) {
+ switch ( $type ) {
case 'edit':
return RC_EDIT;
case 'new':
$prop = array_flip( $params['prop'] );
// Optional fields
- $this->fld_ids = isset ( $prop['ids'] );
+ $this->fld_ids = isset( $prop['ids'] );
// $this->addFieldsIf('rev_text_id', $this->fld_ids); // should this be exposed?
- $this->fld_flags = isset ( $prop['flags'] );
- $this->fld_timestamp = isset ( $prop['timestamp'] );
- $this->fld_comment = isset ( $prop['comment'] );
- $this->fld_parsedcomment = isset ( $prop['parsedcomment'] );
- $this->fld_size = isset ( $prop['size'] );
- $this->fld_sha1 = isset ( $prop['sha1'] );
- $this->fld_contentmodel = isset ( $prop['contentmodel'] );
+ $this->fld_flags = isset( $prop['flags'] );
+ $this->fld_timestamp = isset( $prop['timestamp'] );
+ $this->fld_comment = isset( $prop['comment'] );
+ $this->fld_parsedcomment = isset( $prop['parsedcomment'] );
+ $this->fld_size = isset( $prop['size'] );
+ $this->fld_sha1 = isset( $prop['sha1'] );
+ $this->fld_contentmodel = isset( $prop['contentmodel'] );
$this->fld_userid = isset( $prop['userid'] );
- $this->fld_user = isset ( $prop['user'] );
+ $this->fld_user = isset( $prop['user'] );
$this->token = $params['token'];
if ( !empty( $params['contentformat'] ) ) {
$this->fld_ids = isset( $prop['ids'] );
$this->fld_title = isset( $prop['title'] );
$this->fld_comment = isset( $prop['comment'] );
- $this->fld_parsedcomment = isset ( $prop['parsedcomment'] );
+ $this->fld_parsedcomment = isset( $prop['parsedcomment'] );
$this->fld_size = isset( $prop['size'] );
$this->fld_sizediff = isset( $prop['sizediff'] );
$this->fld_flags = isset( $prop['flags'] );
$this->addFieldsIf( 'rev_comment', $this->fld_comment || $this->fld_parsedcomment );
$this->addFieldsIf( 'rev_len', $this->fld_size || $this->fld_sizediff );
$this->addFieldsIf( 'rev_minor_edit', $this->fld_flags );
- $this->addFieldsIf( 'rev_parent_id', $this->fld_flags || $this->fld_sizediff );
+ $this->addFieldsIf( 'rev_parent_id', $this->fld_flags || $this->fld_sizediff || $this->fld_ids );
$this->addFieldsIf( 'rc_patrolled', $this->fld_patrolled );
if ( $this->fld_tags ) {
$vals['pageid'] = intval( $row->rev_page );
$vals['revid'] = intval( $row->rev_id );
// $vals['textid'] = intval( $row->rev_text_id ); // todo: Should this field be exposed?
+
+ if ( !is_null( $row->rev_parent_id ) ) {
+ $vals['parentid'] = intval( $row->rev_parent_id );
+ }
}
$title = Title::makeTitle( $row->page_namespace, $row->page_title );
),
'ids' => array(
'pageid' => 'integer',
- 'revid' => 'integer'
+ 'revid' => 'integer',
+ 'parentid' => array(
+ ApiBase::PROP_TYPE => 'integer',
+ ApiBase::PROP_NULLABLE => true
+ )
),
'title' => array(
'ns' => 'namespace',
$this->fld_user = isset( $prop['user'] );
$this->fld_userid = isset( $prop['userid'] );
$this->fld_comment = isset( $prop['comment'] );
- $this->fld_parsedcomment = isset ( $prop['parsedcomment'] );
+ $this->fld_parsedcomment = isset( $prop['parsedcomment'] );
$this->fld_timestamp = isset( $prop['timestamp'] );
$this->fld_sizes = isset( $prop['sizes'] );
$this->fld_patrol = isset( $prop['patrol'] );
$show = array_flip( $params['show'] );
/* Check for conflicting parameters. */
- if ( ( isset ( $show['minor'] ) && isset ( $show['!minor'] ) )
- || ( isset ( $show['bot'] ) && isset ( $show['!bot'] ) )
- || ( isset ( $show['anon'] ) && isset ( $show['!anon'] ) )
- || ( isset ( $show['patrolled'] ) && isset ( $show['!patrolled'] ) )
- )
- {
+ if ( ( isset( $show['minor'] ) && isset( $show['!minor'] ) )
+ || ( isset( $show['bot'] ) && isset( $show['!bot'] ) )
+ || ( isset( $show['anon'] ) && isset( $show['!anon'] ) )
+ || ( isset( $show['patrolled'] ) && isset( $show['!patrolled'] ) )
+ ) {
$this->dieUsageMsg( 'show' );
}
global $wgFileExtensions;
// @todo Move them to ApiBase's message map
- switch( $verification['status'] ) {
+ switch ( $verification['status'] ) {
// Recoverable errors
case UploadBase::MIN_LENGTH_PARTNAME:
$this->dieRecoverableError( 'filename-tooshort', 'filename' );
/**
* Run an anonymous function as soon as there is no transaction pending.
* If there is a transaction and it is rolled back, then the callback is cancelled.
+ * Queries in the function will run in AUTO-COMMIT mode unless there are begin() calls.
* Callbacks must commit any transactions that they begin.
*
* This is useful for updates to different systems or when separate transactions are needed.
$arrNum[] = $value;
}
}
- switch( $mode ) {
+ switch ( $mode ) {
case SQLSRV_FETCH_ASSOC:
$ret = $this->mRows[$this->mCursor];
break;
Using uppercase because that's the only way Oracle can handle
quoted tablenames
*/
- switch( $name ) {
+ switch ( $name ) {
case 'user':
$name = 'MWUSER';
break;
function tableName( $name, $format = 'quoted' ) {
# Replace reserved words with better ones
- switch( $name ) {
+ switch ( $name ) {
case 'user':
return $this->realTableName( 'mwuser', $format );
case 'text':
$newline = 1;
$retval = array();
foreach ( $diff->edits as $edit ) {
- switch( $edit->type ) {
+ switch ( $edit->type ) {
case 'add':
foreach ( $edit->closing as $l ) {
$retval[] = array(
}
/**
- * @return bool
+ * @return bool Whether to cache in RepoGroup (this avoids OOMs)
*/
function isCacheable() {
- $this->load();
- return strlen( $this->metadata ) <= self::CACHE_FIELD_MAX_LEN; // avoid OOMs
+ $this->load(); // if loaded from cache, metadata will be null if it didn't fit
+ return $this->metadata !== null && strlen( $this->metadata ) <= self::CACHE_FIELD_MAX_LEN;
}
/**
If your MySQL installation supports InnoDB, it is highly recommended that you choose that instead.
If your MySQL installation does not support InnoDB, maybe it's time for an upgrade.",
+ 'config-mysql-only-myisam-dep' => "'''Warning:''' MyISAM is the only available storage engine for MySQL, which is not recommended for use with MediaWiki, because:
+* it barely supports concurrency due to table locking
+* it is more prone to corruption than other engines
+* the MediaWiki codebase does not always handle MyISAM as it should
+
+Your MySQL installation does not support InnoDB, maybe it's time for an upgrade.",
'config-mysql-engine-help' => "'''InnoDB''' is almost always the best option, since it has good concurrency support.
'''MyISAM''' may be faster in single-user or read-only installations.
MediaWiki bruch Funxjohne en däm Modul un deiht et esu nit.
Wann De <i lang="en">Mandrake</i> aam loufehäs, donn dat Pakätt <code lang="en">php-xml</code> enstalleere.',
'config-pcre' => 'Dem PHP sing Modul för <i lang="en">PCRE</i> schingk ze fähle.
-MediaWiki deiht et nit ohne de Funxjohne för de <i lang="en">Perl-compatible regular expressions</i>.',
+MediaWiki deiht et nit der ohne de Funxjohne för de rejolähre Ußdrök vun dä Zoot, wi <i lang="en">Perl</i> se kännt.',
'config-pcre-no-utf8' => "'''Dä:''' Et PHP-Modul <i lang=\"en\">PCRE</i> schingk ohne de <i lang=\"en\">PCRE_UTF8</i>-Aandeile övversaz ze sin.
MediaWiki bruch dä UTF-8-Krohm ävver, öm ohne Fähler loufe ze künne.",
'config-memory-raised' => 'Der jrühzte zohjelasse Shpeisherbedarf vum PHP, et <code lang="en">memory_limit</code>, shtund op $1 un es op $2 erop jesaz woode.',
/**
* Environment check for setting the preferred PHP file extension.
+ * @return bool
*/
protected function envCheckExtension() {
// @todo FIXME: Detect this properly
}
/**
- * TODO: document
+ * Environment check for preferred locale in shell
* @return bool
*/
protected function envCheckShellLocale() {
}
/**
- * TODO: document
+ * Environment check for the permissions of the uploads directory
* @return bool
*/
protected function envCheckUploadsDirectory() {
}
}
- switch( $this->values['wgMainCacheType'] ) {
+ switch ( $this->values['wgMainCacheType'] ) {
case 'anything':
case 'db':
case 'memcached':
$s .= Xml::openElement( 'div', array(
'id' => 'dbMyisamWarning'
));
- $s .= $this->parent->getWarningBox( wfMessage( 'config-mysql-myisam-dep' )->text() );
+ $myisamWarning = 'config-mysql-myisam-dep';
+ if ( count( $engines ) === 1 ) {
+ $myisamWarning = 'config-mysql-only-myisam-dep';
+ }
+ $s .= $this->parent->getWarningBox( wfMessage( $myisamWarning )->text() );
$s .= Xml::closeElement( 'div' );
if ( $this->getVar( '_MysqlEngine' ) != 'MyISAM' ) {
$title = Title::makeTitleSafe( $row->job_namespace, $row->job_title );
if ( !$title ) {
$dbw->delete( 'job', array( 'job_id' => $row->job_id ), __METHOD__ );
- wfDebugLog( 'JobQueueDB', "Row has invalid title '{$row->job_title}'." );
+ wfDebug( "Row has invalid title '{$row->job_title}'." );
continue; // try again
}
$job = Job::factory( $row->job_cmd, $title,
array( 'job_cmd' => $this->type, 'job_token' => $uuid ), __METHOD__
);
if ( !$row ) { // raced out by duplicate job removal
- wfDebugLog( 'JobQueueDB', "Row deleted as duplicate by another process." );
+ wfDebug( "Row deleted as duplicate by another process." );
}
} else {
break; // nothing to do
*/
private function getCacheKey( $property ) {
list( $db, $prefix ) = wfSplitWikiID( $this->wiki );
- return wfForeignMemcKey( $db, $prefix, 'jobqueue', $this->type, $property );
+ $cluster = is_string( $this->cluster ) ? $this->cluster : 'main';
+ return wfForeignMemcKey( $db, $prefix, 'jobqueue', $cluster, $this->type, $property );
}
/**
$partitionRing = new HashRing( $partitionsTry );
// Because jobs are spread across partitions, per-job de-duplication needs
// to use a consistent hash to avoid allowing duplicate jobs per partition.
- // When inserting a batch of de-duplicated jobs, QoS_Atomic is disregarded.
+ // When inserting a batch of de-duplicated jobs, QOS_ATOMIC is disregarded.
$uJobsByPartition = array(); // (partition name => job list)
foreach ( $jobs as $key => $job ) {
if ( $job->ignoreDuplicates() ) {
}
}
// Get the batches of jobs that are not de-duplicated
- if ( $flags & self::QoS_Atomic ) {
+ if ( $flags & self::QOS_ATOMIC ) {
$nuJobBatches = array( $jobs ); // all or nothing
} else {
// Split the jobs into batches and spread them out over servers if there
// Text of title the action is aimed at.
$target = $entry->getTarget()->getPrefixedText();
$text = null;
- switch( $entry->getType() ) {
+ switch ( $entry->getType() ) {
case 'move':
- switch( $entry->getSubtype() ) {
+ switch ( $entry->getSubtype() ) {
case 'move':
$movesource = $parameters['4::target'];
$text = wfMessage( '1movedto2' )
break;
case 'delete':
- switch( $entry->getSubtype() ) {
+ switch ( $entry->getSubtype() ) {
case 'delete':
$text = wfMessage( 'deletedarticle' )
->rawParams( $target )->inContentLanguage()->escaped();
break;
case 'protect':
- switch( $entry->getSubtype() ) {
+ switch ( $entry->getSubtype() ) {
case 'protect':
$text = wfMessage( 'protectedarticle' )
->rawParams( $target . ' ' . $parameters[0] )->inContentLanguage()->escaped();
break;
case 'newusers':
- switch( $entry->getSubtype() ) {
+ switch ( $entry->getSubtype() ) {
case 'newusers':
case 'create':
$text = wfMessage( 'newuserlog-create-entry' )
break;
case 'upload':
- switch( $entry->getSubtype() ) {
+ switch ( $entry->getSubtype() ) {
case 'upload':
$text = wfMessage( 'uploadedimage' )
->rawParams( $target )->inContentLanguage()->escaped();
} else {
$newgroups = wfMessage( 'rightsnone' )->inContentLanguage()->escaped();
}
- switch( $entry->getSubtype() ) {
+ switch ( $entry->getSubtype() ) {
case 'rights':
$text = wfMessage( 'rightslogentry' )
->rawParams( $target, $oldgroups, $newgroups )->inContentLanguage()->escaped();
protected function formatParameterValue( $type, $value ) {
$saveLinkFlood = $this->linkFlood;
- switch( strtolower( trim( $type ) ) ) {
+ switch ( strtolower( trim( $type ) ) ) {
case 'raw':
$value = Message::rawParam( $value );
break;
return $title->getPrefixedText();
}
- switch( $type ) {
+ switch ( $type ) {
case 'move':
$titleLink = Linker::link(
$title,
$head = fread( $fh, 2 );
fclose( $fh );
- switch( $head ) {
+ switch ( $head ) {
case 'II':
return 'LE'; // II for intel.
case 'MM':
//ComponentsConfiguration should really be an array instead of a string...
//This turns a string of binary numbers into an array of numbers.
- if ( isset ( $this->mFilteredExifData['ComponentsConfiguration'] ) ) {
+ if ( isset( $this->mFilteredExifData['ComponentsConfiguration'] ) ) {
$val = $this->mFilteredExifData['ComponentsConfiguration'];
$ccVals = array();
for ( $i = 0; $i < strlen( $val ); $i++ ) {
//Also change exif tag name from GPSVersion (what php exif thinks it is)
//to GPSVersionID (what the exif standard thinks it is).
- if ( isset ( $this->mFilteredExifData['GPSVersion'] ) ) {
+ if ( isset( $this->mFilteredExifData['GPSVersion'] ) ) {
$val = $this->mFilteredExifData['GPSVersion'];
$newVal = '';
for ( $i = 0; $i < strlen( $val ); $i++ ) {
return true;
}
// Does not work if not typecast
- switch( (string)$etype ) {
+ switch ( (string)$etype ) {
case (string)Exif::BYTE:
$this->debug( $val, __FUNCTION__, $debug );
return $this->isByte( $val );
foreach ( $vals as &$val ) {
- switch( $tag ) {
+ switch ( $tag ) {
case 'Compression':
- switch( $val ) {
+ switch ( $val ) {
case 1: case 2: case 3: case 4:
case 5: case 6: case 7: case 8:
case 32773: case 32946: case 34712:
break;
case 'PhotometricInterpretation':
- switch( $val ) {
+ switch ( $val ) {
case 2: case 6:
$val = self::msg( $tag, $val );
break;
break;
case 'Orientation':
- switch( $val ) {
+ switch ( $val ) {
case 1: case 2: case 3: case 4: case 5: case 6: case 7: case 8:
$val = self::msg( $tag, $val );
break;
break;
case 'PlanarConfiguration':
- switch( $val ) {
+ switch ( $val ) {
case 1: case 2:
$val = self::msg( $tag, $val );
break;
case 'XResolution':
case 'YResolution':
- switch( $resolutionunit ) {
+ switch ( $resolutionunit ) {
case 2:
$val = self::msg( 'XYResolution', 'i', self::formatNum( $val ) );
break;
break;
case 'ColorSpace':
- switch( $val ) {
+ switch ( $val ) {
case 1: case 65535:
$val = self::msg( $tag, $val );
break;
break;
case 'ComponentsConfiguration':
- switch( $val ) {
+ switch ( $val ) {
case 0: case 1: case 2: case 3: case 4: case 5: case 6:
$val = self::msg( $tag, $val );
break;
break;
case 'ExposureProgram':
- switch( $val ) {
+ switch ( $val ) {
case 0: case 1: case 2: case 3: case 4: case 5: case 6: case 7: case 8:
$val = self::msg( $tag, $val );
break;
break;
case 'MeteringMode':
- switch( $val ) {
+ switch ( $val ) {
case 0: case 1: case 2: case 3: case 4: case 5: case 6: case 7: case 255:
$val = self::msg( $tag, $val );
break;
break;
case 'LightSource':
- switch( $val ) {
+ switch ( $val ) {
case 0: case 1: case 2: case 3: case 4: case 9: case 10: case 11:
case 12: case 13: case 14: case 15: case 17: case 18: case 19: case 20:
case 21: case 22: case 23: case 24: case 255:
break;
case 'FocalPlaneResolutionUnit':
- switch( $val ) {
+ switch ( $val ) {
case 2:
$val = self::msg( $tag, $val );
break;
break;
case 'SensingMethod':
- switch( $val ) {
+ switch ( $val ) {
case 1: case 2: case 3: case 4: case 5: case 7: case 8:
$val = self::msg( $tag, $val );
break;
break;
case 'FileSource':
- switch( $val ) {
+ switch ( $val ) {
case 3:
$val = self::msg( $tag, $val );
break;
break;
case 'SceneType':
- switch( $val ) {
+ switch ( $val ) {
case 1:
$val = self::msg( $tag, $val );
break;
break;
case 'CustomRendered':
- switch( $val ) {
+ switch ( $val ) {
case 0: case 1:
$val = self::msg( $tag, $val );
break;
break;
case 'ExposureMode':
- switch( $val ) {
+ switch ( $val ) {
case 0: case 1: case 2:
$val = self::msg( $tag, $val );
break;
break;
case 'WhiteBalance':
- switch( $val ) {
+ switch ( $val ) {
case 0: case 1:
$val = self::msg( $tag, $val );
break;
break;
case 'SceneCaptureType':
- switch( $val ) {
+ switch ( $val ) {
case 0: case 1: case 2: case 3:
$val = self::msg( $tag, $val );
break;
break;
case 'GainControl':
- switch( $val ) {
+ switch ( $val ) {
case 0: case 1: case 2: case 3: case 4:
$val = self::msg( $tag, $val );
break;
break;
case 'Contrast':
- switch( $val ) {
+ switch ( $val ) {
case 0: case 1: case 2:
$val = self::msg( $tag, $val );
break;
break;
case 'Saturation':
- switch( $val ) {
+ switch ( $val ) {
case 0: case 1: case 2:
$val = self::msg( $tag, $val );
break;
break;
case 'Sharpness':
- switch( $val ) {
+ switch ( $val ) {
case 0: case 1: case 2:
$val = self::msg( $tag, $val );
break;
break;
case 'SubjectDistanceRange':
- switch( $val ) {
+ switch ( $val ) {
case 0: case 1: case 2: case 3:
$val = self::msg( $tag, $val );
break;
//The GPS...Ref values are kept for compatibility, probably won't be reached.
case 'GPSLatitudeRef':
case 'GPSDestLatitudeRef':
- switch( $val ) {
+ switch ( $val ) {
case 'N': case 'S':
$val = self::msg( 'GPSLatitude', $val );
break;
case 'GPSLongitudeRef':
case 'GPSDestLongitudeRef':
- switch( $val ) {
+ switch ( $val ) {
case 'E': case 'W':
$val = self::msg( 'GPSLongitude', $val );
break;
break;
case 'GPSStatus':
- switch( $val ) {
+ switch ( $val ) {
case 'A': case 'V':
$val = self::msg( $tag, $val );
break;
break;
case 'GPSMeasureMode':
- switch( $val ) {
+ switch ( $val ) {
case 2: case 3:
$val = self::msg( $tag, $val );
break;
case 'GPSTrackRef':
case 'GPSImgDirectionRef':
case 'GPSDestBearingRef':
- switch( $val ) {
+ switch ( $val ) {
case 'T': case 'M':
$val = self::msg( 'GPSDirection', $val );
break;
break;
case 'GPSSpeedRef':
- switch( $val ) {
+ switch ( $val ) {
case 'K': case 'M': case 'N':
$val = self::msg( 'GPSSpeed', $val );
break;
break;
case 'GPSDestDistanceRef':
- switch( $val ) {
+ switch ( $val ) {
case 'K': case 'M': case 'N':
$val = self::msg( 'GPSDestDistance', $val );
break;
break;
case 'iimCategory':
- switch( strtolower( $val ) ) {
+ switch ( strtolower( $val ) ) {
// See pg 29 of IPTC photo
// metadata standard.
case 'ace': case 'clj':
}
break;
case 'Copyrighted':
- switch( $val ) {
+ switch ( $val ) {
case 'True': case 'False':
$val = self::msg( $tag, $val );
break;
*/
else {
global $wgContLang;
- switch( $type ) {
+ switch ( $type ) {
case 'lang':
// Display default, followed by ContLang,
// followed by the rest in no particular
* this is treated as wikitext not html).
*/
private static function langItem( $value, $lang, $default = false, $noHtml = false ) {
- if ( $lang === false && $default === false) {
+ if ( $lang === false && $default === false ) {
throw new MWException( '$lang and $default cannot both '
. 'be false.' );
}
return $val;
}
$cat = '';
- switch( substr( $val, 0, 2 ) ) {
+ switch ( substr( $val, 0, 2 ) ) {
case '01':
$cat = 'ace';
break;
wfDebugLog( 'iptc', "IPTC tag $tag had only whitespace as its value." );
continue;
}
- switch( $tag ) {
+ switch ( $tag ) {
case '2#120': /*IPTC caption. mapped with exif ImageDescription*/
$data['ImageDescription'] = self::convIPTC( $val, $c );
break;
while ( $keepReading ) {
$tag = $this->reader->localName;
$type = $this->reader->nodeType;
- $isSVG = ($this->reader->namespaceURI == self::NS_SVG);
+ $isSVG = ( $this->reader->namespaceURI == self::NS_SVG );
$this->debug( "$tag" );
&& $this->reader->nodeType == XmlReader::END_ELEMENT ) {
break;
} elseif ( $this->reader->namespaceURI == self::NS_SVG && $this->reader->nodeType == XmlReader::ELEMENT ) {
- switch( $this->reader->localName ) {
+ switch ( $this->reader->localName ) {
case 'script':
// Normally we disallow files with
// <script>, but its possible
throw new MWException( "Hit end element </$elm> but no curItem" );
}
- switch( $this->mode[0] ) {
+ switch ( $this->mode[0] ) {
case self::MODE_IGNORE:
$this->endElementModeIgnore( $elm );
break;
. "encountered <$elm> with no mode" );
}
- switch( $this->mode[0] ) {
+ switch ( $this->mode[0] ) {
case self::MODE_IGNORE:
$this->startElementModeIgnore( $elm );
break;
$conn->setex( $key, $expiry, $value );
}
- $result = $conn->exec();
+ /*
+ * multi()/exec() (transactional mode) allows multiple values to
+ * be set/get at once and will return an array of results, in
+ * the order they were set/get. In this case, we only set 1
+ * value, which should (in case of success) result in true.
+ */
+ $result = ( $conn->exec() == array( true ) );
} catch ( RedisException $e ) {
$result = false;
$this->handleException( $server, $conn, $e );
$parser->setFunctionHook( 'pagenamee', array( __CLASS__, 'pagenamee' ), SFH_NO_HASH );
$parser->setFunctionHook( 'fullpagename', array( __CLASS__, 'fullpagename' ), SFH_NO_HASH );
$parser->setFunctionHook( 'fullpagenamee', array( __CLASS__, 'fullpagenamee' ), SFH_NO_HASH );
+ $parser->setFunctionHook( 'rootpagename', array( __CLASS__, 'rootpagename' ), SFH_NO_HASH );
+ $parser->setFunctionHook( 'rootpagenamee', array( __CLASS__, 'rootpagenamee' ), SFH_NO_HASH );
$parser->setFunctionHook( 'basepagename', array( __CLASS__, 'basepagename' ), SFH_NO_HASH );
$parser->setFunctionHook( 'basepagenamee', array( __CLASS__, 'basepagenamee' ), SFH_NO_HASH );
$parser->setFunctionHook( 'subpagename', array( __CLASS__, 'subpagename' ), SFH_NO_HASH );
if ( is_null( $magicWords ) ) {
$magicWords = new MagicWordArray( array( 'url_path', 'url_query', 'url_wiki' ) );
}
- switch( $magicWords->matchStartToEnd( $arg ) ) {
+ switch ( $magicWords->matchStartToEnd( $arg ) ) {
// Encode as though it's a wiki page, '_' for ' '.
case 'url_wiki':
static function pagesinnamespace( $parser, $namespace = 0, $raw = null ) {
return self::formatRaw( SiteStats::pagesInNs( intval( $namespace ) ), $raw );
}
- static function numberingroup( $parser, $name = '', $raw = null) {
+ static function numberingroup( $parser, $name = '', $raw = null ) {
return self::formatRaw( SiteStats::numberingroup( strtolower( $name ) ), $raw );
}
}
return wfEscapeWikiText( $t->getSubpageUrlForm() );
}
+ static function rootpagename( $parser, $title = null ) {
+ $t = Title::newFromText( $title );
+ if ( is_null( $t ) ) {
+ return '';
+ }
+ return wfEscapeWikiText( $t->getRootText() );
+ }
+ static function rootpagenamee( $parser, $title = null ) {
+ $t = Title::newFromText( $title );
+ if ( is_null( $t ) ) {
+ return '';
+ }
+ return wfEscapeWikiText( wfUrlEncode( str_replace( ' ', '_', $t->getRootText() ) ) );
+ }
static function basepagename( $parser, $title = null ) {
$t = Title::newFromText( $title );
if ( is_null( $t ) ) {
if ( $old === false || $old == $text || $arg ) {
return '';
} else {
- return( '<span class="error">' .
+ return '<span class="error">' .
wfMessage( 'duplicate-defaultsort', $old, $text )->inContentLanguage()->escaped() .
- '</span>' );
+ '</span>';
}
}
}
for ( $i = 1; $i <= self::LAST; $i++ ) {
$this->mSource = $i;
- if ( isset ( $this->rules[$preference][$i] ) ) {
+ if ( isset( $this->rules[$preference][$i] ) ) {
# Specific rules
$this->mTarget = $this->rules[$preference][$i];
- } elseif ( isset ( $this->rules[self::ALL][$i] ) ) {
+ } elseif ( isset( $this->rules[self::ALL][$i] ) ) {
# General rules
$this->mTarget = $this->rules[self::ALL][$i];
} elseif ( $preference ) {
*/
function makeNormalYear( $iso ) {
if ( $iso[0] == '-' ) {
- $text = (intval( substr( $iso, 1 ) ) + 1) . ' BC';
+ $text = ( intval( substr( $iso, 1 ) ) + 1 ) . ' BC';
} else {
$text = intval( $iso );
}
for ( $i = 0; $i < $len; $i++ ) {
$c = $str[$i];
- switch( $state ) {
+ switch ( $state ) {
# (Using the number is a performance hack for common cases)
case 0: # self::COLON_STATE_TEXT:
- switch( $c ) {
+ switch ( $c ) {
case "<":
# Could be either a <start> tag or an </end> tag
$state = self::COLON_STATE_TAGSTART;
break;
case 1: # self::COLON_STATE_TAG:
# In a <tag>
- switch( $c ) {
+ switch ( $c ) {
case ">":
$stack++;
$state = self::COLON_STATE_TEXT;
}
break;
case 2: # self::COLON_STATE_TAGSTART:
- switch( $c ) {
+ switch ( $c ) {
case "/":
$state = self::COLON_STATE_CLOSETAG;
break;
case 'subpagenamee':
$value = wfEscapeWikiText( $this->mTitle->getSubpageUrlForm() );
break;
+ case 'rootpagename':
+ $value = wfEscapeWikiText( $this->mTitle->getRootText() );
+ break;
+ case 'rootpagenamee':
+ $value = wfEscapeWikiText( wfUrlEncode( str_replace( ' ', '_', $this->mTitle->getRootText() ) ) );
+ break;
case 'basepagename':
$value = wfEscapeWikiText( $this->mTitle->getBaseText() );
break;
* @return mixed An expanded string, or false if invalid.
*/
function validateSig( $text ) {
- return( Xml::isWellFormedXmlFragment( $text ) ? $text : false );
+ return Xml::isWellFormedXmlFragment( $text ) ? $text : false;
}
/**
$validated = $handler->validateParam( $paramName, $value );
} else {
# Validate internal parameters
- switch( $paramName ) {
+ switch ( $paramName ) {
case 'manualthumb':
case 'alt':
case 'class':
wfDebugLog( "Preprocessor", "Loaded preprocessor XML from memcached (key $cacheKey)" );
}
}
- }
- if ( $xml === false ) {
- if ( $cacheable ) {
+ if ( $xml === false ) {
wfProfileIn( __METHOD__ . '-cache-miss' );
$xml = $this->preprocessToXml( $text, $flags );
$cacheValue = sprintf( "%08d", self::CACHE_VERSION ) . $xml;
$wgMemc->set( $cacheKey, $cacheValue, 86400 );
wfProfileOut( __METHOD__ . '-cache-miss' );
wfDebugLog( "Preprocessor", "Saved preprocessor XML to memcached (key $cacheKey)" );
- } else {
- $xml = $this->preprocessToXml( $text, $flags );
}
-
+ } else {
+ $xml = $this->preprocessToXml( $text, $flags );
}
+
// Fail if the number of elements exceeds acceptable limits
// Do not attempt to generate the DOM
$this->parser->mGeneratedPPNodeCount += substr_count( $xml, '<' );
* @return Boolean
*/
public function supports( $feature ) {
- switch( $feature ) {
+ switch ( $feature ) {
case 'list-redirects':
return true;
case 'title-suffix-filter':
}
public function supports( $feature ) {
- switch( $feature ) {
+ switch ( $feature ) {
case 'list-redirects':
case 'title-suffix-filter':
return true;
}
if ( !isset( $this->opts['year'] ) ) {
- $this->opts['year'] = '';
+ $this->opts['year'] = gmdate( 'Y' );
}
if ( !isset( $this->opts['month'] ) ) {
$form->addPreText( $this->msg( 'unblockiptext' )->parseAsBlock() );
if ( $form->show() ) {
- switch( $this->type ) {
+ switch ( $this->type ) {
case Block::TYPE_USER:
case Block::TYPE_IP:
$out->addWikiMsg( 'unblocked', wfEscapeWikiText( $this->target ) );
} else {
$fields['Target']['default'] = $target;
$fields['Target']['type'] = 'hidden';
- switch( $type ) {
+ switch ( $type ) {
case Block::TYPE_USER:
case Block::TYPE_IP:
$fields['Name']['default'] = Linker::link(
protected function processVerificationError( $details ) {
global $wgFileExtensions;
- switch( $details['status'] ) {
+ switch ( $details['status'] ) {
/** Statuses that only require name changing **/
case UploadBase::MIN_LENGTH_PARTNAME:
);
}
+ /**
+ * Add a "return to" link or redirect to it.
+ * Extensions can use this to reuse the "return to" logic after
+ * inject steps (such as redirection) into the login process.
+ *
+ * @param $type string, one of the following:
+ * - error: display a return to link ignoring $wgRedirectOnLogin
+ * - success: display a return to link using $wgRedirectOnLogin if needed
+ * - successredirect: send an HTTP redirect using $wgRedirectOnLogin if needed
+ * @param string $returnTo
+ * @param array|string $returnToQuery
+ * @param bool $stickHTTPs Keep redirect link on HTTPs
+ * @since 1.22
+ */
+ public function showReturnToPage(
+ $type, $returnTo = '', $returnToQuery = '', $stickHTTPs = false
+ ) {
+ $this->mReturnTo = $returnTo;
+ $this->mReturnToQuery = $returnToQuery;
+ $this->mStickHTTPS = $stickHTTPs;
+ $this->executeReturnTo( $type );
+ }
+
/**
* Add a "return to" link or redirect to it.
*
* @return Boolean
*/
private function shouldShowVForm() {
- global $wgUseVFormUserLogin;
+ global $wgUseVFormCreateAccount, $wgUseVFormUserLogin;
if ( $this->mType == 'signup' ) {
- return false;
+ return $this->mRequest->getBool( 'useNew', $wgUseVFormCreateAccount );
} else {
return $this->mRequest->getBool( 'useNew', $wgUseVFormUserLogin );
}
}
if ( $this->mType == 'signup' ) {
- $template = new UsercreateTemplate();
+ $out->addModules( 'mediawiki.special.userlogin.signup' );
+ if ( $this->mShowVForm ) {
+ $template = new UsercreateTemplateVForm();
+ $out->addModuleStyles( array(
+ 'mediawiki.ui',
+ 'mediawiki.special.createaccount.vform'
+ ) );
+ // XXX hack pending RL or JS parse() support for complex content messages
+ // https://bugzilla.wikimedia.org/show_bug.cgi?id=25349
+ $out->addJsConfigVars( 'wgCreateacctImgcaptchaHelp',
+ $this->msg( 'createacct-imgcaptcha-help' )->parse() );
+ $out->addModules( 'mediawiki.special.createaccount.vform.js' );
+ } else {
+ $template = new UsercreateTemplate();
+ }
$q = 'action=submitlogin&type=signup';
$linkq = 'type=login';
$linkmsg = 'gotaccount';
- $out->addModules( 'mediawiki.special.userlogin.signup' );
} else {
if ( $this->mShowVForm ) {
$template = new UserloginTemplateVForm();
}
# Make description text.
- $description = isset ( $extension['description'] ) ? $extension['description'] : '';
+ $description = isset( $extension['description'] ) ? $extension['description'] : '';
- if ( isset ( $extension['descriptionmsg'] ) ) {
+ if ( isset( $extension['descriptionmsg'] ) ) {
# Look for a localized description.
$descriptionMsg = $extension['descriptionmsg'];
<td colspan=\"2\"><em>$mainLink $versionText</em></td>";
}
- $author = isset ( $extension['author'] ) ? $extension['author'] : array();
+ $author = isset( $extension['author'] ) ? $extension['author'] : array();
$extDescAuthor = "<td>$description</td>
<td>" . $this->listAuthors( $author, false ) . "</td>
</tr>\n";
$mode = SpecialEditWatchlist::getMode( $request, $par );
if ( $mode !== false ) {
# TODO: localise?
- switch( $mode ) {
+ switch ( $mode ) {
case SpecialEditWatchlist::EDIT_CLEAR:
$mode = 'clear';
break;
$big = 1000; /* The magical big */
if ( $nitems > $big ) {
# Set default cutoff shorter
- $values['days'] = $defaults['days'] = (12.0 / 24.0); # 12 hours...
+ $values['days'] = $defaults['days'] = ( 12.0 / 24.0 ); # 12 hours...
} else {
$values['days'] = $defaults['days']; # default cutoff for shortlisters
}
--- /dev/null
+<?php
+/**
+ * Html form for account creation with new VForm appearance.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ *
+ * @file
+ * @ingroup Templates
+ */
+
+if ( !defined( 'MEDIAWIKI' ) ) {
+ die( -1 );
+}
+
+/**
+ * Html form for create account with new VForm appearance.
+ *
+ * @since 1.22
+ */
+class UsercreateTemplateVForm extends BaseTemplate {
+
+ /**
+ * Extensions (AntiSpoof and TitleBlacklist) call this in response to
+ * UserCreateForm hook to add checkboxes to the create account form.
+ */
+ function addInputItem( $name, $value, $type, $msg, $helptext = false ) {
+ $this->data['extraInput'][] = array(
+ 'name' => $name,
+ 'value' => $value,
+ 'type' => $type,
+ 'msg' => $msg,
+ 'helptext' => $helptext,
+ );
+ }
+
+ function execute() {
+ global $wgCookieExpiration;
+ $expirationDays = ceil( $wgCookieExpiration / ( 3600 * 24 ) );
+?>
+<div class="mw-ui-container">
+ <?php
+ if ( $this->haveData( 'languages' ) ) {
+ ?>
+ <div id="languagelinks">
+ <p><?php $this->html( 'languages' ); ?></p>
+ </div>
+ <?php
+ }
+ ?>
+<div id="userloginForm">
+<h2 class="createaccount-join"><?php $this->msg( 'createacct-join' ); ?></h2>
+<form name="userlogin2" id="userlogin2" class="mw-ui-vform" method="post" action="<?php $this->text( 'action' ); ?>">
+ <section class="mw-form-header">
+ <?php $this->html( 'header' ); /* extensions such as ConfirmEdit add form HTML here */ ?>
+ </section>
+ <?php
+ if ( $this->data['message'] ) {
+?>
+ <div class="<?php $this->text( 'messagetype' ); ?>box">
+ <?php if ( $this->data['messagetype'] == 'error' ) { ?>
+ <strong><?php $this->msg( 'createacct-error' ); ?></strong><br />
+ <?php } ?>
+ <?php $this->html( 'message' ); ?>
+ </div>
+ <?php } ?>
+ <div>
+ <label for='wpName2'>
+ <?php $this->msg( 'userlogin-yourname' ); ?>
+
+ <span class="mw-ui-flush-right"><?php echo $this->getMsg( 'createacct-helpusername-link' )->parse(); ?></span>
+ </label>
+ <?php echo Html::input( 'wpName', $this->data['name'], 'text', array(
+ 'class' => 'mw-input loginText',
+ 'id' => 'wpName2',
+ 'tabindex' => '1',
+ 'size' => '20',
+ 'required',
+ 'placeholder' => $this->getMsg( 'userlogin-yourname-ph' )->text(),
+ 'autofocus'
+ ) ); ?>
+ </div>
+ <div>
+ <?php if ( $this->data['createemail'] ) { ?>
+ <label class="mw-ui-checkbox-label">
+ <input name="wpCreateaccountMail" type="checkbox" value="1" id="wpCreateaccountMail" tabindex="2"
+ <?php if ( $this->data['createemailset'] ) {
+ echo 'checked="checked"';
+ } ?>
+ >
+ <?php $this->msg( 'createaccountmail' ); ?>
+ </label>
+ <?php } ?>
+ </div>
+ <div class="mw-row-password">
+ <label for='wpPassword2'><?php $this->msg( 'userlogin-yourpassword' ); ?></label>
+ <?php echo Html::input( 'wpPassword', null, 'password', array(
+ 'class' => 'mw-input loginPassword',
+ 'id' => 'wpPassword2',
+ 'tabindex' => '3',
+ 'size' => '20',
+ 'required',
+ 'placeholder' => $this->getMsg( 'createacct-yourpassword-ph' )->text()
+ ) + User::passwordChangeInputAttribs() ); ?>
+ </div>
+ <?php if ( $this->data['usedomain'] ) {
+ $doms = "";
+ foreach ( $this->data['domainnames'] as $dom ) {
+ $doms .= "<option>" . htmlspecialchars( $dom ) . "</option>";
+ }
+ ?>
+ <div>
+ <label><?php $this->msg( 'yourdomainname' ); ?></label>
+ <div class="mw-input">
+ <select name="wpDomain" value="<?php $this->text( 'domain' ); ?>"
+ tabindex="4">
+ <?php echo $doms ?>
+ </select>
+ </div>
+ </div>
+ <?php } ?>
+ <div class="mw-row-password">
+ <label for='wpRetype'><?php $this->msg( 'createacct-yourpasswordagain' ); ?></label>
+ <?php
+ echo Html::input( 'wpRetype', null, 'password', array(
+ 'class' => 'mw-input loginPassword',
+ 'id' => 'wpRetype',
+ 'tabindex' => '5',
+ 'size' => '20',
+ 'required',
+ 'placeholder' => $this->getMsg( 'createacct-yourpasswordagain-ph' )->text()
+ ) + User::passwordChangeInputAttribs() );
+ ?>
+ </div>
+ <div>
+ <?php if ( $this->data['useemail'] ) { ?>
+ <label for='wpEmail'>
+ <?php
+ $this->msg( $this->data['emailrequired'] ?
+ 'createacct-emailrequired' :
+ 'createacct-emailoptional'
+ );
+ ?>
+ </label>
+ <?php
+ echo Html::input( 'wpEmail', $this->data['email'], 'email', array(
+ 'class' => 'mw-input loginText',
+ 'id' => 'wpEmail',
+ 'tabindex' => '6',
+ 'size' => '20',
+ 'placeholder' => $this->getMsg( 'createacct-email-ph' )->text()
+ ) + ( $this->data['emailrequired'] ? array() : array( 'required' => '' ) ) );
+ ?>
+ <?php
+ // VForm eliminates the prefsectiontip div tip:
+ // prefs-help-email-required is redundant with the placeholder text
+ // Doesn't show the wordy prefs-help-email
+ // Doesn't show the wordy prefs-help-email-others
+ ?>
+ <?php } ?>
+ </div>
+ <?php if ( $this->data['userealname'] ) { ?>
+ <div>
+ <label for='wpRealName'><?php $this->msg( 'createacct-realname' ); ?></label>
+ <input type='text' class='mw-input loginText' name="wpRealName" id="wpRealName"
+ tabindex="7"
+ value="<?php $this->text( 'realname' ); ?>" size='20' />
+ <div class="prefsectiontip">
+ <?php $this->msgWiki( 'prefs-help-realname' ); ?>
+ </div>
+ </div>
+ <?php }
+ if ( $this->data['usereason'] ) { ?>
+ <div>
+ <label for='wpReason'><?php $this->msg( 'createacct-reason' ); ?></label>
+ <input type='text' class='mw-input loginText' name="wpReason" id="wpReason"
+ tabindex="8"
+ value="<?php $this->text( 'reason' ); ?>" size='20' />
+ </div>
+ <?php }
+ $tabIndex = 9;
+ if ( isset( $this->data['extraInput'] ) && is_array( $this->data['extraInput'] ) ) {
+ foreach ( $this->data['extraInput'] as $inputItem ) { ?>
+ <div>
+ <?php
+ // If it's a checkbox, output the whole thing (assume it has a msg).
+ if ( $inputItem['type'] == 'checkbox' ) {
+ ?>
+ <label class="mw-ui-checkbox-label">
+ <input
+ name="<?php echo htmlspecialchars( $inputItem['name'] ); ?>"
+ id="<?php echo htmlspecialchars( $inputItem['name'] ); ?>"
+ type="checkbox" value="1"
+ tabindex="<?php echo $tabIndex++; ?>"
+ <?php if ( !empty( $inputItem['value'] ) ) {
+ echo 'checked="checked"';
+ } ?>
+ >
+ <?php $this->msg( $inputItem['msg'] ); ?>
+ </label>
+ <?php
+ } else {
+ // Not a checkbox.
+ if ( !empty( $inputItem['msg'] ) ) {
+ // Output the message label
+ ?>
+ <label for="<?php echo htmlspecialchars( $inputItem['name'] ); ?>">
+ <?php $this->msgWiki( $inputItem['msg'] ); ?>
+ </label>
+ <?php
+ }
+ ?>
+ <input
+ type="<?php echo htmlspecialchars( $inputItem['type'] ); ?>"
+ class="mw-input"
+ name="<?php echo htmlspecialchars( $inputItem['name'] ); ?>"
+ tabindex="<?php echo $tabIndex++; ?>"
+ value="<?php echo htmlspecialchars( $inputItem['value'] ); ?>"
+ id="<?php echo htmlspecialchars( $inputItem['name'] ); ?>"
+ />
+ <?php
+ }
+ if ( $inputItem['helptext'] !== false ) {
+ ?>
+ <div class="prefsectiontip">
+ <?php $this->msgWiki( $inputItem['helptext'] ); ?>
+ </div>
+ <?php
+ }
+ ?>
+ </div>
+ <?php
+ }
+ }
+ // JS attempts to move the image CAPTCHA below this part of the form,
+ // so skip one index.
+ $tabIndex++;
+ ?>
+ <div class="mw-submit">
+ <input type='submit' class="mw-ui-button mw-ui-big mw-ui-block mw-ui-primary" name="wpCreateaccount" id="wpCreateaccount"
+ tabindex="<?php echo $tabIndex++; ?>"
+ value="<?php $this->msg( 'createaccount' ); ?>" />
+ </div>
+ <input type="hidden" id="useNew" name="useNew" value="1" />
+<?php if ( $this->haveData( 'uselang' ) ) { ?><input type="hidden" name="uselang" value="<?php $this->text( 'uselang' ); ?>" /><?php } ?>
+<?php if ( $this->haveData( 'token' ) ) { ?><input type="hidden" name="wpCreateaccountToken" value="<?php $this->text( 'token' ); ?>" /><?php } ?>
+</form>
+</div>
+<div class="mw-createacct-benefits-container">
+ <h2><?php $this->msg( 'createacct-benefit-heading' ); ?></h2>
+ <div class="mw-createacct-benefits-list">
+ <div>
+ <div class="mw-benefits-icon <?php $this->msg( 'createacct-benefit-icon1' ); ?>"></div>
+ <div class="mw-number-text">
+ <h3><?php $this->msg( 'createacct-benefit-head1' ); ?></h3>
+ <p><?php $this->msg( 'createacct-benefit-body1' ); ?></p>
+ </div>
+ </div>
+ <div>
+ <div class="mw-benefits-icon <?php $this->msg( 'createacct-benefit-icon2' ); ?>"></div>
+ <div class="mw-number-text">
+ <h3><?php $this->msg( 'createacct-benefit-head2' ); ?></h3>
+ <p><?php $this->msg( 'createacct-benefit-body2' ); ?></p>
+ </div>
+ </div>
+ <div>
+ <div class="mw-benefits-icon <?php $this->msg( 'createacct-benefit-icon3' ); ?>"></div>
+ <div class="mw-number-text">
+ <h3><?php $this->msg( 'createacct-benefit-head3' ); ?></h3>
+ <p><?php $this->msg( 'createacct-benefit-body3' ); ?></p>
+ </div>
+ </div>
+ </div>
+</div>
+</div>
+<?php
+
+ }
+}
?>
<div class="mw-ui-container">
<?php
- // Some extensions including CAPTCHAs add content to header on UserLoginForm hook.
- $this->html( 'header' );
if ( $this->haveData( 'languages' ) ) {
?>
<div id="languagelinks">
?>
<div id="userloginForm">
<form name="userlogin" class="mw-ui-vform" method="post" action="<?php $this->text( 'action' ); ?>">
+ <section class="mw-form-header">
+ <?php $this->html( 'header' ); /* extensions such as ConfirmEdit add form HTML here */ ?>
+ </section>
<?php
if ( $this->data['message'] ) {
}
$start = substr( $str, 0, strlen( $str ) - 2 );
$end = substr( $str, strlen( $str ) - 2 );
- switch( $end ) {
+ switch ( $end ) {
case 'כ':
$str = $start . 'ך';
break;
* @since 1.18
*/
public function formatExpiry( $expiry, $format = true ) {
- static $infinity, $infinityMsg;
+ static $infinity;
if ( $infinity === null ) {
- $infinityMsg = wfMessage( 'infiniteblock' );
$infinity = wfGetDB( DB_SLAVE )->getInfinity();
}
if ( $expiry == '' || $expiry == $infinity ) {
return $format === true
- ? $infinityMsg
+ ? $this->getMessageFromDB( 'infiniteblock' )
: $infinity;
} else {
return $format === true
global $wgLanguageCode;
$text = parent::translate( $text, $toVariant );
- switch( $toVariant ) {
+ switch ( $toVariant ) {
case 'kk-cyrl':
case 'kk-kz':
$letters = KK_L_UC . KK_L_LC . 'ʺʹ#0123456789';
return $text;
}
- switch( $toVariant ) {
+ switch ( $toVariant ) {
case 'kk-arab':
case 'kk-cn':
$letters = KK_C_LC . KK_C_UC/*.KK_L_LC.KK_L_UC*/;
'nov' => 'নৱেম্বৰ:',
'dec' => 'ডিচেম্বৰ:',
+'monday-at' => 'সোমবাৰে $1ত',
+'tuesday-at' => 'মঙ্গলবাৰে $1’ত',
+'wednesday-at' => 'বুধবাৰে $1’ত',
+'thursday-at' => 'বৃহস্পতিবাৰে $1’ত',
+'friday-at' => 'শুক্ৰবাৰে $1’ত',
+'saturday-at' => 'শনিবাৰে $1’ত',
+'sunday-at' => 'দেওবাৰে $1’ত',
+'today-at' => '$1',
+'yesterday-at' => 'কালি $1’ত',
+
# Categories related messages
'pagecategories' => '{{PLURAL:$1|শ্ৰেণী|শ্ৰেণীসমূহ}}',
'category_header' => '"$1" শ্ৰেণীৰ পৃষ্ঠাসমূহ',
'duration-centuries' => '$1 {{PLURAL:$1|শতাব্দী|শতাব্দী}}',
'duration-millennia' => '$1 {{PLURAL:$1|সহস্ৰাব্দ|সহস্ৰাব্দ}}',
+# Unknown messages
+'hours-ago' => '$1 {{PLURAL:$1|ঘন্টা}} আগেয়ে',
+'minutes-ago' => '$1 {{PLURAL:$1|মাহ}} আগেয়ে',
+'seconds-ago' => '$1 {{PLURAL:$1|ছেকেন্ড}} আগতে',
);
'welcomecreation-msg' => 'Иҫәп яҙыуығыҙ яһалды.
Шәхси [[Special:Preferences|{{SITENAME}} көйләүҙәрен]] үҙегеҙгә уңайлы итеп үҙгәртергә онотмағыҙ.',
'yourname' => 'Ҡатнашыусы исеме',
+'userlogin-yourname' => 'Ҡулланыусы исеме',
'yourpassword' => 'Һеҙҙең пароль',
+'userlogin-yourpassword' => 'Пароль',
+'userlogin-yourpassword-ph' => 'Яңы паролде яҙығыҙ',
'yourpasswordagain' => 'Паролде ҡабаттан яҙыу',
'remembermypassword' => 'Был компьютерҙа паролемде иҫләргә ($1 {{PLURAL:$1|көндән|көндән}} күп түгел)',
+'userlogin-remembermypassword' => 'Хәтерҙә ҡалдырырға',
'securelogin-stick-https' => 'Танылғандан һуң HTTPS менән бәйләнеште ҡалдырырға',
'yourdomainname' => 'Һеҙҙең домен',
'password-change-forbidden' => 'Был викила паролегеҙҙе үҙгәртә алмайһығыҙ.',
'nov' => 'ліс',
'dec' => 'сьн',
+'monday-at' => 'Панядзелак, $1',
+'tuesday-at' => 'Аўторак, $1',
+'wednesday-at' => 'Серада, $1',
+'thursday-at' => 'Чацьвер, $1',
+'friday-at' => 'Пятніца, $1',
+'saturday-at' => 'Субота, $1',
+'sunday-at' => 'Нядзеля, $1',
+'today-at' => '$1',
+'yesterday-at' => 'Учора, $1',
+
# Categories related messages
'pagecategories' => '{{PLURAL:$1|Катэгорыя|Катэгорыі|Катэгорыі}}',
'category_header' => 'Старонкі ў катэгорыі «$1»',
# Image rotation
'rotate-comment' => 'Выява павернутая на $1{{PLURAL:$1|°}} па гадзіньнікавай стрэлцы',
+# Unknown messages
+'hours-ago' => '$1 {{PLURAL:$1|гадзіну|гадзіны|гадзінаў}} таму',
+'minutes-ago' => '$1 {{PLURAL:$1|хвіліну|хвіліны|хвілінаў}} таму',
+'seconds-ago' => '$1 {{PLURAL:$1|сэкунду|сэкунды|сэкундаў}} таму',
);
'yourpasswordagain' => 'শব্দচাবিটি (password) আবার লিখুন',
'remembermypassword' => 'একাধিক সেশনের জন্য শব্দচাবি মনে রাখা হোক (সর্বোচ্চ $1 {{PLURAL:$1|দিনের|দিনের}} জন্য)',
'userlogin-remembermypassword' => 'আমাকে মনে রাখো',
+'userlogin-signwithsecure' => 'নিরাপদ সার্ভারের মাধ্যমে লগইন করুন',
'securelogin-stick-https' => 'লগইনের পর এইচটিটিপিএস-এর সাথে সংযোগকৃত থাকুন',
'yourdomainname' => 'আপনার ডোমেইন',
'password-change-forbidden' => 'আপনি এই উইকিতে পাসওয়ার্ড পরিবর্তন করতে পারবেন না।',
'userlogout' => 'প্রস্থান',
'notloggedin' => 'আপনি সংযুক্ত নন',
'userlogin-noaccount' => 'কোনও অ্যাকাউন্ট নেই?',
+'userlogin-joinproject' => '{{SITENAME}}-এ অংশগ্রহন করুন',
'nologin' => "আপনার কি উইকিপিডিয়াতে অ্যাকাউন্ট নেই? তাহলে '''$1'''।",
'nologinlink' => 'অ্যাকাউন্ট তৈরি করুন',
'createaccount' => 'নতুন অ্যাকাউন্ট খুলুন',
'gotaccountlink' => 'প্রবেশ',
'userlogin-resetlink' => 'আপনার লগইনের বিস্তারিত তথ্যাদি ভুলে গেছেন?',
'helplogin-url' => 'Help:প্রবেশ',
+'userlogin-helplink' => '[[{{MediaWiki:helplogin-url}}|লগইন সংক্রান্ত সাহায্য]]',
'createaccountmail' => 'একটি র্যান্ডম পাসওয়ার্ড নির্বাচন করুন এবং নিচের নির্ধারিত ইমেইল ঠিকানায় পাঠিয়ে দিন',
'createaccountreason' => 'কারণ:',
'badretype' => "আপনার প্রবেশ করানো শব্দচাবি'টি মিলছেনা।",
'passwordreset-text' => 'আপনার শব্দচাবি বদলের জন্য নিচের ফর্মটি পূরণ করুন।',
'passwordreset-legend' => 'শব্দচাবি রিসেট',
'passwordreset-disabled' => 'এই উইকিতে শব্দচাবি রিসেটের সুবিধা নিষ্ক্রিয় রয়েছে।',
+'passwordreset-emaildisabled' => 'এই উইকিতে ইমেইল অপশনটি বন্ধ করা হয়েছে।',
'passwordreset-pretext' => '{{PLURAL:$1||নিচে উল্লেখিত ডেটাগুলোর কোনো একটি প্রবেশ করান}}',
'passwordreset-username' => 'ব্যবহারকারী নাম:',
'passwordreset-domain' => 'ডোমেইন:',
অস্থায়ী শব্দচাবি: $2',
'passwordreset-emailsent' => 'শব্দচাবি বদলের একটি ই-মেইল পাঠানো হয়েছে।',
'passwordreset-emailsent-capture' => 'স্মরণ করিয়ে দেয়ার জন্য একটি ইমেইল করা হয়েছে, যা নিচে দেখানো হচ্ছে।',
-'passwordreset-emailerror-capture' => 'স্মরণ করিয়ে দেয়ার জন্য একটি ইমেইল তৈরী করা হয়েছিল, যা নিচে দেখানো হচ্ছে, তবে $1 ব্যবহারকারীকে এটি পাঠানো যায়নি!',
+'passwordreset-emailerror-capture' => 'স্মরণ করিয়ে দেয়ার জন্য একটি ইমেইল তৈরী করা হয়েছিল, যা নিচে দেখানো হচ্ছে, তবে $1 {{GENDER:$2|ব্যবহারকারীকে}} এটি পাঠানো যায়নি!',
# Special:ChangeEmail
'changeemail' => 'ই-মেইল ঠিকানা পরিবর্তন',
'powersearch-togglenone' => 'কিছু নয়',
'search-external' => 'বহিঃস্থ অনুসন্ধান',
'searchdisabled' => '{{SITENAME}} অনুসন্ধান এখন নিষ্ক্রিয় আছে। আপনি গুগলের মাধ্যমে অনুসন্ধান চালাতে পারেন। লক্ষ্য করুন যে {{SITENAME}}-এর বিষয়বস্তুর উপর গুগলের ইন্ডেক্সগুলি হালনাগাদ না-ও করা থাকতে পারে।',
+'search-error' => 'অনুসন্ধানের সময় একটি ত্রুটি হয়েছে: $1',
# Preferences page
'preferences' => 'আমার পছন্দ',
* @author Girdi
* @author Mega programmer
* @author Sasan700
+ * @author Умар
*/
$fallback = 'ru';
'tog-extendwatchlist' => 'Шорбина тlехьажарна могlам, ша беригге а хийцамаш чубогlуш, тlяхьабина боцурш а',
'tog-usenewrc' => 'Лелабе дика могlам керла чу хийцамашна (оьшу JavaScript)',
'tog-numberheadings' => 'Ша шех хlитто терахь корташна',
-'tog-showtoolbar' => 'Ð\93айÑ\82а лакÑ\85аÑ\80а гlиÑ\80Ñ\81ан дакÑ\8aа ниÑ\81йеÑ\88 аÑ\82Ñ\82он оÑ\86 Ñ\80едаккÑ\85ар чохь (JavaScript)',
+'tog-showtoolbar' => 'Ð\93айÑ\82а лакÑ\85аÑ\80а гlиÑ\80Ñ\81ан дакÑ\8aа ниÑ\81йеÑ\88 аÑ\82Ñ\82он оÑ\86 Ñ\82адар чохь (JavaScript)',
'tog-editondblclick' => 'Нисйе агlонаш шозза тlетаlийча (JavaScript)',
'tog-editsection' => 'Гайта хьажориг «нисйе» аьлла хlора агlона',
'tog-editsectiononrightclick' => 'Нисде дакъа шозза бакъехьар дахка тlетаlийча оцу кортан (JavaScript)',
'tog-shownumberswatching' => 'Гайта декъашхойн терахь, агlо латийна болу шай тергаме могlам юкъа',
'tog-oldsig' => 'Хьалххьажар долучу куьгтаlорна:',
'tog-fancysig' => 'Шен вики-къастаман куьгтаlдар (ша шех хьажориг йоцуш)',
-'tog-externaleditor' => 'Лелайан арахьара рéдаккхар (гlулкхдириг леррина нисйина хила йеза, [//www.mediawiki.org/wiki/Manual:External_editors кхин дlа.])',
-'tog-externaldiff' => 'Лелабан арахьара диллагlарам башхо тарйо гlирс (гlулкхдириг леррина нисйина хила йеза, [//www.mediawiki.org/wiki/Manual:External_editors кхин дlа.])',
'tog-showjumplinks' => 'Латайе гlодарна хьажоригаш «дехьа вала оцу»',
'tog-uselivepreview' => 'Лелайа чехка хьалха хьажа (JavaScript, муха ю хьажарна)',
'tog-forceeditsummary' => 'Дага даийта, нагахь нисйарх лаьцна чохь язъйина язахь',
'thu' => 'Еа',
'fri' => 'Пle',
'sat' => 'Шот',
-'january' => 'нажи бутт',
-'february' => 'мархи бутт',
-'march' => 'биÑ\8dкаÑ\80г бÑ\83Ñ\82т',
-'april' => 'тушоли бутт',
-'may_long' => 'сели бутт',
-'june' => 'мангал бÑ\83Ñ\82Ñ\82',
-'july' => 'мÑ\8fÑ\82Ñ\81ел бÑ\83Ñ\82Ñ\82',
-'august' => 'эгиш бутт',
-'september' => 'Ñ\82ав бÑ\83Ñ\82Ñ\82',
-'october' => 'аÑ\80даÑ\80 бÑ\83Ñ\82Ñ\82',
-'november' => 'эрх бутт',
-'december' => 'огой бÑ\83Ñ\82Ñ\82',
-'january-gen' => 'нажи бутт',
-'february-gen' => 'мархи бутт',
-'march-gen' => 'биÑ\8dкаÑ\80г бÑ\83Ñ\82т',
-'april-gen' => 'тушоли бутт',
-'may-gen' => 'сели бутт',
-'june-gen' => 'мангал бÑ\83Ñ\82Ñ\82',
-'july-gen' => 'мÑ\8fÑ\82Ñ\81ел бÑ\83Ñ\82Ñ\82',
-'august-gen' => 'эгиш бутт',
-'september-gen' => 'Ñ\82ав бÑ\83Ñ\82Ñ\82',
-'october-gen' => 'аÑ\80даÑ\80 бÑ\83Ñ\82Ñ\82',
-'november-gen' => 'эрх бутт',
-'december-gen' => 'огой бÑ\83Ñ\82Ñ\82',
-'jan' => 'нажи бутт',
-'feb' => 'мархи бутт',
-'mar' => 'биÑ\8dкаÑ\80г бÑ\83Ñ\82т',
-'apr' => 'тушоли бутт',
-'may' => 'сели бутт',
-'jun' => 'мангал бÑ\83Ñ\82Ñ\82',
-'jul' => 'мÑ\8fÑ\82Ñ\81ел бÑ\83Ñ\82Ñ\82',
-'aug' => 'эгиш бутт',
-'sep' => 'Ñ\82ав бÑ\83Ñ\82Ñ\82',
-'oct' => 'аÑ\80даÑ\80 бÑ\83Ñ\82Ñ\82',
-'nov' => 'эрх бутт',
-'dec' => 'огой бÑ\83Ñ\82Ñ\82',
+'january' => 'январь',
+'february' => 'февраль',
+'march' => 'маÑ\80т',
+'april' => 'апрель',
+'may_long' => 'май',
+'june' => 'иÑ\8eнÑ\8c',
+'july' => 'иÑ\8eлÑ\8c',
+'august' => 'август',
+'september' => 'Ñ\81енÑ\82Ñ\8fбÑ\80Ñ\8c',
+'october' => 'окÑ\82Ñ\8fбÑ\80Ñ\8c',
+'november' => 'ноябрь',
+'december' => 'декабÑ\80Ñ\8c',
+'january-gen' => 'январь',
+'february-gen' => 'февраль',
+'march-gen' => 'маÑ\80т',
+'april-gen' => 'апрель',
+'may-gen' => 'май',
+'june-gen' => 'иÑ\8eнÑ\8c',
+'july-gen' => 'иÑ\8eлÑ\8c',
+'august-gen' => 'август',
+'september-gen' => 'Ñ\81енÑ\82Ñ\8fбÑ\80Ñ\8c',
+'october-gen' => 'окÑ\82Ñ\8fбÑ\80Ñ\8c',
+'november-gen' => 'ноябрь',
+'december-gen' => 'декабÑ\80Ñ\8c',
+'jan' => 'январь',
+'feb' => 'февраль',
+'mar' => 'маÑ\80т',
+'apr' => 'апрель',
+'may' => 'май',
+'jun' => 'иÑ\8eнÑ\8c',
+'jul' => 'иÑ\8eлÑ\8c',
+'aug' => 'август',
+'sep' => 'Ñ\81енÑ\82Ñ\8fбÑ\80Ñ\8c',
+'oct' => 'окÑ\82Ñ\8fбÑ\80Ñ\8c',
+'nov' => 'ноябрь',
+'dec' => 'декабÑ\80Ñ\8c',
# Categories related messages
-'pagecategories' => '{{PLURAL:$1|Кадегар|Кадегарш}}',
-'category_header' => 'Агlонаш оц кадегаршчохь «$1»',
-'subcategories' => 'Бухаркадегарш',
-'category-media-header' => 'Хlумнаш оцу кадегар чохь «$1»',
-'category-empty' => "''Хlара кадегар хlинца йаьсса ю.''",
-'hidden-categories' => '{{PLURAL:$1|Къайлаха кадегар|Къайлаха йолу кадегарш}}',
-'hidden-category-category' => 'Къайлаха йолу кадегарш',
-'category-subcat-count' => '{{PLURAL:$2|Хlокх кадегар чохь ю хlокхуьна бухар кадегар.|{{PLURAL:$1|Гойташ $1 бухар кадегар|Гойту $1 бухар кадегар|Гойту $1 бухар кадегар}} оцу $2.}}',
-'category-subcat-count-limited' => 'Хlокх кадегар чохь {{PLURAL:$1|$1 бухар кадегар|$1 бухар кадегарша|$1 бухар кадегарш}}.',
-'category-article-count' => '{{PLURAL:$2|Хlокх кадегар чохь яц цхьа агlо бе.|{{PLURAL:$1|Гойташ $1 агlо|Гойту $1 агlонаш|Гойту $1 агlонаш}} хlокх кадегарца кху $2.}}',
-'category-article-count-limited' => 'Хlокх кадегар чохь {{PLURAL:$1|$1 агlо|$1 агlонаш|$1 агlонаш}}.',
-'category-file-count' => '{{PLURAL:$2|Хlокх кадегар чохь цхьа хlум бе яц.|{{PLURAL:$1|Гойта $1 хlум|Гойту $1 хlума|Гойту $1 хlумнаш}} хlокх кадегарца кху $2.}}',
-'category-file-count-limited' => 'Хlокх кадегар чохь {{PLURAL:$1|$1 хlум|$1 хlума|$1 хlумнаш}}.',
+'pagecategories' => '{{PLURAL:$1|Категори|Категореш}}',
+'category_header' => 'Агlонаш оц категоречохь «$1»',
+'subcategories' => 'Бухаркатегореш',
+'category-media-header' => 'ХӀумнаш оцу категори чохь «$1»',
+'category-empty' => "''ХӀара категори хӀинца йаьсса ю.''",
+'hidden-categories' => '{{PLURAL:$1|Къайлаха категори|Къайлаха йолу категореш}}',
+'hidden-category-category' => 'Къайлаха йолу категореш',
+'category-subcat-count' => '{{PLURAL:$2|ХӀокх категори чохь ю хӀокхуьна бухар категори.|{{PLURAL:$1|Гойташ $1 бухар категори|Гойту $1 бухар категори|Гойту $1 бухар категори}} оцу $2.}}',
+'category-subcat-count-limited' => 'Хlокх категори чохь {{PLURAL:$1|$1 бухар категори|$1 бухар категореша|$1 бухар категореш}}.',
+'category-article-count' => '{{PLURAL:$2|ХӀокх категори чохь яц цхьа агӀо бе.|{{PLURAL:$1|Гойташ $1 агlо|Гойту $1 агӀонаш|Гойту $1 агӀонаш}} хӀокх категорешца кху $2.}}',
+'category-article-count-limited' => 'Хlокх категори чохь {{PLURAL:$1|$1 агlо|$1 агlонаш|$1 агlонаш}}.',
+'category-file-count' => '{{PLURAL:$2|ХӀокх категори чохь цхьа хӀум бе яц.|{{PLURAL:$1|Гойта $1 хӀум|Гойту $1 хlума|Гойту $1 хlумнаш}} хlокх категорешца кху $2.}}',
+'category-file-count-limited' => 'ХӀокх категори чохь {{PLURAL:$1|$1 файл|$1 хӀума|$1 файлаш}}.',
'listingcontinuesabbrev' => '(кхин дlа)',
'index-category' => 'Меттигтерахьйо агlонаш',
-'noindex-category' => 'Дlахьушйоцу агlонаш',
+'noindex-category' => 'ДӀахьушйоцу агӀонаш',
'linkprefix' => '/^(.*?)([a-zA-Z\\x80-\\xff]+)$/sD',
'article' => 'Яззам',
'newwindow' => '(керлачу корехь)',
'cancel' => 'Цаоьшу',
-'moredotdotdot' => 'Кхин дlа…',
-'mypage' => 'Долахь йолу агlо',
-'mytalk' => 'Сан дийцаре агlо',
-'anontalk' => 'Дийцаре хlара IP-долуметтиг',
+'moredotdotdot' => 'Кхин дӀа…',
+'mypage' => 'Долахь йолу агӀо',
+'mytalk' => 'Сан дийцаре агӀо',
+'anontalk' => 'Дийцаре хӀара IP-долуметтиг',
'navigation' => 'Шавигар',
'and' => ' а',
'vector-simplesearch-preference' => 'Шуьйра лахаран хьехар лата де (декъа «Хьушйерг» кечйарца)',
'vector-view-create' => 'Кхоллар',
'vector-view-edit' => 'Нисйé',
-'vector-view-history' => 'Ð¥Ñ\8cажа иÑ\81Ñ\82оÑ\80е',
+'vector-view-history' => 'Ð¥Ñ\8cажа иÑ\81Ñ\82оÑ\80и',
'vector-view-view' => 'Éшар',
'vector-view-viewsource' => 'Билглонашка хьажа',
'actions' => 'Дийраш',
'searchbutton' => 'Лаха',
'go' => 'Дехьа вала',
'searcharticle' => 'Дехьа вала',
-'history' => 'Ð\98Ñ\81Ñ\82оÑ\80е',
-'history_short' => 'Ð\98Ñ\81Ñ\82оÑ\80е',
+'history' => 'Ð\98Ñ\81Ñ\82оÑ\80и',
+'history_short' => 'Ð\98Ñ\81Ñ\82оÑ\80и',
'updatedmarker' => 'Керла яккхина со чуваьллачултlаьхьа',
'printableversion' => 'Зорба туху варси',
'permalink' => 'Даиман йолу хьажориг',
'nstab-user' => 'Декъашхо',
'nstab-special' => 'Белха агlо',
'nstab-project' => 'Кхолламех',
-'nstab-image' => 'Ð¥lÑ\83м',
+'nstab-image' => 'Файл',
'nstab-mediawiki' => 'Хаам',
-'nstab-template' => 'Куцкеп',
+'nstab-template' => 'Кеп',
'nstab-help' => 'Нисвохаам',
-'nstab-category' => 'Кадегар',
+'nstab-category' => 'Категори',
# Main script and global functions
'nosuchaction' => 'Ишта дийриг дац',
'nowiki_sample' => 'Чудиллийша кхузе барамхlоттонза йоза.',
'nowiki_tip' => 'Тергал ца бо вики-бáрамхlоттор',
'image_sample' => 'Example.jpg',
-'image_tip' => 'ЧоÑ\85Ñ\8c йолÑ\83 Ñ\85lÑ\83м',
+'image_tip' => 'ЧоÑ\85Ñ\8c йолÑ\83 Ñ\84айл',
'media_sample' => 'Example.ogg',
'media_tip' => 'Хьажориг оцу медиа-хlуман',
'sig_tip' => 'Хьан куьгтаlор аъ хlоттина хан',
'preview' => 'Хьалха муха ю хьажа',
'showpreview' => 'Хьалха муха ю хьажар',
'showdiff' => 'Хlоттина болу хийцам',
-'anoneditwarning' => "'''ТеÑ\80гам бе''': Ð\90Ñ\85Ñ\8cа Ñ\85Ñ\8cо вовзиÑ\82ина ваÑ\86 гlиÑ\80Ñ\81ан. Ð¥Ñ\8cан IP-долÑ\83 меÑ\82Ñ\82иг дlаÑ\8fзйина Ñ\85иÑ\80а Ñ\8e Ñ\85lокÑ\85Ñ\83 агlон иÑ\81Ñ\82оÑ\80е чу.",
+'anoneditwarning' => "'''ТеÑ\80гам бе''': Ð\90Ñ\85Ñ\8cа Ñ\85Ñ\8cо вовзиÑ\82ина ваÑ\86 гlиÑ\80Ñ\81ан. Ð¥Ñ\8cан IP-долÑ\83 меÑ\82Ñ\82иг дlаÑ\8fзйина Ñ\85иÑ\80а Ñ\8e Ñ\85lокÑ\85Ñ\83 агlон иÑ\81Ñ\82оÑ\80и чу.",
'summary-preview' => 'Цуьнах лаьцна хирду:',
'blockedtitle' => 'Декъашхо сацийна',
'accmailtitle' => 'Ишар дlаяхьийтина.',
'updated' => '(Карла йаькхина)',
'note' => "'''Билгалдаккхар:'''",
'previewnote' => "'''Хlара хьалх хьажар ду, йоза хlинца язданза ду!'''",
-'editing' => 'РедаккÑ\85ар: $1',
-'editingsection' => 'РедаккÑ\85ар $1 (даакъа)',
-'editingcomment' => 'РедаккÑ\85ар $1 (керла даакъа)',
+'editing' => 'Тадар: $1',
+'editingsection' => 'Тадар $1 (даакъа)',
+'editingcomment' => 'Тадар $1 (керла даакъа)',
'editconflict' => 'Редаккхарна дойнаш: $1',
'yourtext' => 'Хьан йоза',
'yourdiff' => 'Башхаллаш',
'protectedpagewarning' => "'''Дlахьедар. Хlара агlо гlаролла дина ю хийцам цабайта, иза хийца йа нисйа а бакъо йолуш адаманкуьйгалла лелош болу декъашхой бе бац.'''
Лахахьа гойту хаамаш тlаьхьара бина болу хийцамна тептар чура:",
'cascadeprotectedwarning' => "'''Дlахьедар:''' Хlокху агlонна редаккха бакъо йолуш хlара тоба йу «Адаманкуьйгалхой», хlунда аьлча иза латийна {{PLURAL:$1|кхечу агlонца|кхечу агlонашца}} хlоттделлачу гlароллийца:",
-'templatesused' => '{{PLURAL:$1|Куцкеп, лелийна|Куцкепаш, лелош ду}} хlокху агlон башхонца:',
-'templatesusedpreview' => '{{PLURAL:$1|Куцкеп, лелошдолу|Куцкепаш, лелошдолу}} оцу хьалх хьожучу агlонца:',
+'templatesused' => '{{PLURAL:$1|Кеп, лелийна|Кепаш, лелош ду}} хlокху агlон башхонца:',
+'templatesusedpreview' => '{{PLURAL:$1|Кеп, лелошдолу|Кепаш, лелошдолу}} оцу хьалх хьожучу агlонца:',
'template-protected' => '(гlароллийца)',
'template-semiprotected' => '(дуьззина доцуш гlаролла)',
'hiddencategories' => 'Хlара агlо чуйогlуш ю оцу $1 {{PLURAL:$1|къайлаха кадегарчу|къайлаха кадегаршчу|къайлаха кадегаршчу}}:',
# Parser/template warnings
'parser-template-loop-warning' => 'Карийна куцкепаш юкъахь хилла шад: [[$1]]',
-'parser-template-recursion-depth-warning' => 'Дозанал хьалаваьлла кlоргенца йух йуха дина куцкеп ($1)',
+'parser-template-recursion-depth-warning' => 'Дозанал хьалаваьлла кlоргенца йух йуха дина кеп ($1)',
# "Undo" feature
'undo-success' => 'Нисйинарг а тlе цалаца мега. Дехар до, хьажа цхьатерра йуй башхо, тешна хила, баккъалла иза хийцам буйте хьуна безарг, тlакха тlе таlайе «дlайазйе агlо», хийцам хlотта ба.',
'page_last' => 'тlаьххьара',
'histlegend' => "Кхетор: (хlинцлера.) — йолучу башхон къастам; (хьалх.) — хьалхлерачу башхон къастам; '''ж''' — жимо бозалца болу хийцам.",
'history-fieldset-title' => 'Хьажа исцlарерачу',
-'histfirst' => 'къена',
-'histlast' => 'Ñ\85Ñ\8cалÑ\85о',
+'histfirst' => 'ширниш',
+'histlast' => 'Ñ\85Ñ\8cалÑ\85аÑ\80ниÑ\88',
'historyempty' => '(йаьсса)',
# Revision feed
'revertmerge' => 'Йекъа',
# Diffs
-'history-title' => '$1 â\80\94 Ñ\85ийÑ\86аман иÑ\81Ñ\82оÑ\80е',
+'history-title' => '$1 â\80\94 Ñ\85ийÑ\86аман иÑ\81Ñ\82оÑ\80и',
'lineno' => 'Могlа $1:',
'compareselectedversions' => 'Хаьржиначуьна башхо муха ю хьажа',
'showhideselectedversions' => 'Гайта/къайлайаха хаьржина башхонаш',
'prefs-resetpass' => 'Хийца ишар',
'prefs-rendering' => 'Арахьара хатl',
'saveprefs' => 'lалашдан',
-'prefs-editing' => 'РедаккÑ\85ар',
+'prefs-editing' => 'Тадар',
'searchresultshead' => 'Лаха',
'timezonelegend' => 'Сахьатан аса:',
'prefs-searchoptions' => 'Лахарна гlирс нисба',
'rcshowhidemine' => '$1 айхьа нисдинарш',
'rclinks' => 'Гайта тlаьхьара $1 хийцамаш оцу $2 ден<br />$3',
'diff' => 'тейп тайпнара',
-'hist' => 'иÑ\81Ñ\82оÑ\80е',
+'hist' => 'иÑ\81Ñ\82оÑ\80и',
'hide' => 'Къайлаяккха',
'show' => 'Гайта',
'minoreditletter' => 'ж',
'recentchangeslinked-to' => 'Кхечу агlор, гайта хийцамаш агlонашца, хlоттийначу агlонтlе хьажориг йолуш',
# Upload
-'upload' => 'ЧÑ\83йаккÑ\85а Ñ\85lÑ\83м',
-'uploadbtn' => 'ЧÑ\83йаккÑ\85а Ñ\85lÑ\83м',
+'upload' => 'ЧÑ\83йаккÑ\85а Ñ\84айл',
+'uploadbtn' => 'ЧÑ\83йаккÑ\85а Ñ\84айл',
'uploadlogpage' => 'Чуйахаран тéптар',
'uploadlogpagetext' => 'Лахахьа гойтуш бу могlам тlаьххьара чуяхна хlумнаши. Ишта хьажа. [[Special:ImageList|хlумнаши могlам]] йа [[Special:NewImages|галеларе хlумнаши]].',
'filename' => 'Хlуман цlе',
# Special:ListFiles
'listfiles_search_for' => 'Лаха хIуман цIарца:',
-'imgfile' => 'Ñ\85lÑ\83м',
+'imgfile' => 'Ñ\84айл',
'listfiles' => 'Хlумнаши могlам',
'listfiles_name' => 'Хlуман цlе',
'listfiles_user' => 'Декъашхо',
'listfiles_description' => 'Цуьнах лаьцна',
# File description page
-'file-anchor-link' => ' Хlум',
-'filehist' => 'Ð¥lÑ\83ман иÑ\81Ñ\82оÑ\80е',
-'filehist-help' => 'ТlеÑ\82аlаде Ñ\82еÑ\80аÑ\85Ñ\8c/Ñ\85ан, мÑ\83Ñ\85а Ñ\85илла Ñ\85Ñ\8cажаÑ\80на и Ñ\85lÑ\83м.',
+'file-anchor-link' => 'Файл',
+'filehist' => 'Файлан иÑ\81Ñ\82оÑ\80и',
+'filehist-help' => 'ТlеÑ\82аlаде Ñ\82еÑ\80аÑ\85Ñ\8c/Ñ\85ан, мÑ\83Ñ\85а Ñ\85илла Ñ\85Ñ\8cажаÑ\80на и Ñ\84айл.',
'filehist-deleteall' => 'дlадайá массо',
'filehist-deleteone' => 'дlадайá',
'filehist-current' => 'карара',
'filerevert-submit' => 'Юхаяккха',
# File deletion
-'filedelete-legend' => 'Ð\94lайайá и Ñ\85lÑ\83м',
+'filedelete-legend' => 'Ð\94lайайá и Ñ\84айл',
'filedelete-submit' => 'Дlадайá',
'filedelete-otherreason' => 'Кхин бахьан:',
'filedelete-reason-otherlist' => 'Кхин бахьан',
# Miscellaneous special pages
'nbytes' => '$1 {{PLURAL:$1|цlинцl|цlинцlа|цlинацl}}',
-'ncategories' => '$1 {{PLURAL:$1|кадегар|кадегарш|кадегарш}}',
-'nmembers' => '$1 {{PLURAL:$1|Ñ\85lÑ\83м|Ñ\85lÑ\83ма|Ñ\85lÑ\83мнаш}}',
+'ncategories' => '$1 {{PLURAL:$1|категори|категореш|категореш}}',
+'nmembers' => '$1 {{PLURAL:$1|Ñ\84айл|Ñ\84айлана|Ñ\84айлаш}}',
'specialpage-empty' => 'Дехаро хlумма ца елла.',
'lonelypages' => 'Байлахь йисина агIонаш',
-'uncategorizedpages' => 'Кадегар йоцу агIонаш',
-'uncategorizedcategories' => 'Кадегар йоцу кадегарш',
-'uncategorizedimages' => 'Кадегар йоцу хIумнаш',
-'uncategorizedtemplates' => 'Кадегар йоцу куцкепаш',
+'uncategorizedpages' => 'Категори йоцу агIонаш',
+'uncategorizedcategories' => 'Категори йоцу категореш',
+'uncategorizedimages' => 'Категори йоцу хIумнаш',
+'uncategorizedtemplates' => 'Категори йоцу кепаш',
'unusedcategories' => 'Йаьсса кадегарш',
'wantedcategories' => 'Оьшуш йолу кадегарш',
'wantedpages' => 'Оьшуш йолу агIонаш',
'listusers' => 'Декъашхой могlам',
'newpages' => 'Керла агlонаш',
'newpages-username' => 'Декъашхо:',
-'ancientpages' => 'ЯззамаÑ\88 оÑ\86Ñ\83 Ñ\82еÑ\80аÑ\85Ñ\8cÑ\86а Ñ\82Ñ\8fÑ\85Ñ\85Ñ\8cаÑ\80а Ñ\80едаккÑ\85ар дина долу',
+'ancientpages' => 'ЯззамаÑ\88 оÑ\86Ñ\83 Ñ\82еÑ\80аÑ\85Ñ\8cÑ\86а Ñ\82Ñ\8fÑ\85Ñ\85Ñ\8cаÑ\80а Ñ\82адар дина долу',
'move' => 'Цlе хийца',
'movethispage' => 'Хlокху агlон цlе хийца',
'unusedimagestext' => 'Дехар до, тидаме эца, кхин йолу дуьнана машан-меттигаш а лелош хила мега нисса йогlу хьажориг (URL) хlокху хlуман, хlокху могlаме йогlуш ялахь яцахь а иза хила мега жигара лелош.',
'pager-newer-n' => '{{PLURAL:$1|алсамо керла|алсамо керланаш|алсамо керлачарех}} $1',
-'pager-older-n' => '{{PLURAL:$1|алсамо къена|алсамо къенанаш|алсамо къеначарех}} $1',
+'pager-older-n' => '{{PLURAL:$1|алсамо шира|алсамо ширниш|алсамо ширачарех}} $1',
# Book sources
'booksources' => 'Жайнан хьосташ',
# Special:ListUsers
'listusers-submit' => 'Гайта',
-# Special:ActiveUsers
-'activeusers' => 'Жигар декъашхой могlам',
-
# Special:ListGroupRights
'listgrouprights' => 'Декъашхойн тобанаши бакъонаш',
'listgrouprights-group' => 'Тоба',
'listgrouprights-helppage' => 'Help:Тобан бакъонаш',
'listgrouprights-members' => '(тобан могlам)',
-# E-mail user
+# Email user
'emailuser' => 'Декъашхочун хааман кехат',
'defemailsubject' => 'Хаам {{grammar:genitive|{{SITENAME}}}} чура бу',
'emailmessage' => 'Хаам:',
'exbeforeblank' => 'чуьраниг дlацlанйале хьалха: «$1»',
'exblank' => 'агlо йаьсса йара',
'delete-legend' => 'Дlадайáр',
-'confirmdeletetext' => 'Ð¥Ñ\8cан деÑ\85аÑ\80 дÑ\83 Ñ\85lаÑ\80а агlо Ñ\88е бÑ\83Ñ\85Ñ\86и дlабайа аÑ\8cлла (йа Ñ\81Ñ\83Ñ\80Ñ\82) а маÑ\81Ñ\81о Ñ\86Ñ\83Ñ\8cнан иÑ\81Ñ\82оÑ\80е оцу бух чура. Дехар до, бакъде, билгала хьайна иза лаахь, кхеташ хира ву хьо тlаьхьа хир долу чун, иза деш ду ахьа бакъонца догlуш, вахьа дехкина долучу дакъанца [[{{MediaWiki:Policy-url}}]].',
+'confirmdeletetext' => 'Ð¥Ñ\8cан деÑ\85аÑ\80 дÑ\83 Ñ\85lаÑ\80а агlо Ñ\88е бÑ\83Ñ\85Ñ\86и дlабайа аÑ\8cлла (йа Ñ\81Ñ\83Ñ\80Ñ\82) а маÑ\81Ñ\81о Ñ\86Ñ\83Ñ\8cнан иÑ\81Ñ\82оÑ\80и оцу бух чура. Дехар до, бакъде, билгала хьайна иза лаахь, кхеташ хира ву хьо тlаьхьа хир долу чун, иза деш ду ахьа бакъонца догlуш, вахьа дехкина долучу дакъанца [[{{MediaWiki:Policy-url}}]].',
'actioncomplete' => 'Дешдерг кхочушди',
'deletedtext' => '«$1» дlаяккхина йара.
Хьажа. $2 хьажарна оцу тlаьхьара дlадайаран могlаме.',
Нагахь ахьа иза цадинехь, дехар до, хьажа йуйла [[Special:DoubleRedirects|шалгlа]] а [[Special:BrokenRedirects|хадийначу дlасахьажориш]].
Ахьа жоп лур ду кхин дlа а хьажориг хьажийна хилийта, хила йезаче.
-ТеÑ\80гамбеÑ\88 Ñ\85ила, иза агlо '''Ñ\85иÑ\80а Ñ\8fÑ\86''' Ñ\86lе Ñ\85ийÑ\86ина, нагаÑ\85Ñ\8c иза Ñ\86lе йолÑ\83Ñ\88 кеÑ\80ла агlо йалаÑ\85Ñ\8c, Ñ\86Ñ\85Ñ\8cа йолÑ\83 Ñ\85енаÑ\85Ñ\8c, нагаÑ\85Ñ\8c иза йалаÑ\85Ñ\8c Ñ\86Ñ\85Ñ\8cан Ñ\82lе Ñ\85Ñ\8cажийна йа йаÑ\8cÑ\81Ñ\81а а ниÑ\81йаÑ\80Ñ\86а иÑ\81Ñ\82оÑ\80е йоцуш.
+ТеÑ\80гамбеÑ\88 Ñ\85ила, иза агlо '''Ñ\85иÑ\80а Ñ\8fÑ\86''' Ñ\86lе Ñ\85ийÑ\86ина, нагаÑ\85Ñ\8c иза Ñ\86lе йолÑ\83Ñ\88 кеÑ\80ла агlо йалаÑ\85Ñ\8c, Ñ\86Ñ\85Ñ\8cа йолÑ\83 Ñ\85енаÑ\85Ñ\8c, нагаÑ\85Ñ\8c иза йалаÑ\85Ñ\8c Ñ\86Ñ\85Ñ\8cан Ñ\82lе Ñ\85Ñ\8cажийна йа йаÑ\8cÑ\81Ñ\81а а ниÑ\81йаÑ\80Ñ\86а иÑ\81Ñ\82оÑ\80и йоцуш.
Иза бохург ду, хьега хийцалур ю оцу агlон цlе оцу цlарца, хlинц цуьна хилла йолу, нагахь ахьа гlалатонца цlе хийцанехь, йолуш йолу агlо цахууш йа мега хьа.
'''ДlАХЬЕДАР!'''
'export' => 'Яззамаш кхечу меттиган арадахар',
'exporttext' => 'Шуьга далур ду кхечу меттера чудахарш, йоза а хийцаме тептарш билгалла йолу агlонаш йа гулдина йолу агlонаш хlокх XML барамца, йуха тlяхьа чура [[Special:Import|хьаэцалурдолш]] кхечу вики-хьалхен, болх беш йолу хlокху MediaWiki гlирсаца.
-Ð\9aÑ\85еÑ\87Ñ\83 меÑ\82Ñ\82еÑ\80а Ñ\8fззамаÑ\88 Ñ\87Ñ\83йаÑ\85а, Ñ\87Ñ\83Ñ\8fзйе Ñ\86lе Ñ\80едокÑ\85Ñ\87Ñ\83 меÑ\82Ñ\82е, Ñ\86lÑ\85Ñ\8cа могlан Ñ\86lе могlаÑ\80Ñ\88каÑ\85Ñ\8c, йÑ\83Ñ\85а Ñ\85аÑ\80жа лаÑ\8cи Ñ\88Ñ\83на Ð\9aÑ\85еÑ\87Ñ\83 меÑ\82Ñ\82еÑ\80 Ñ\87Ñ\83йаÑ\85а маÑ\81Ñ\81о Ñ\8fззамаÑ\88на иÑ\81Ñ\82оÑ\80е хийцамбарш йа тlяхьаралера яззамна башхо.
+Ð\9aÑ\85еÑ\87Ñ\83 меÑ\82Ñ\82еÑ\80а Ñ\8fззамаÑ\88 Ñ\87Ñ\83йаÑ\85а, Ñ\87Ñ\83Ñ\8fзйе Ñ\86lе Ñ\80едокÑ\85Ñ\87Ñ\83 меÑ\82Ñ\82е, Ñ\86lÑ\85Ñ\8cа могlан Ñ\86lе могlаÑ\80Ñ\88каÑ\85Ñ\8c, йÑ\83Ñ\85а Ñ\85аÑ\80жа лаÑ\8cи Ñ\88Ñ\83на Ð\9aÑ\85еÑ\87Ñ\83 меÑ\82Ñ\82еÑ\80 Ñ\87Ñ\83йаÑ\85а маÑ\81Ñ\81о Ñ\8fззамаÑ\88на иÑ\81Ñ\82оÑ\80и хийцамбарш йа тlяхьаралера яззамна башхо.
Шуьга кхи даландерг, лелаеш йолу меттиг къастаман машан хьажориг кхечу меттер чудаха тlяхьарлера башхон яззамаш. Массала оцу яззамна [[{{MediaWiki:Mainpage}}]] хlара хира йу хьажориг [[{{#Special:Export}}/{{MediaWiki:Mainpage}}]].',
'export-templates' => 'Латадé куцкепаш',
'tooltip-t-permalink' => 'Даимна йолу хьажориг хlокху башха агlонна',
'tooltip-ca-nstab-main' => 'Яззамна чулацам',
'tooltip-ca-nstab-user' => 'Хlора декъашхон долахь йолу агlо',
-'tooltip-ca-nstab-media' => 'Ð\9cедиа-Ñ\85lÑ\83м',
+'tooltip-ca-nstab-media' => 'Ð\9cедиа-Ñ\84айл',
'tooltip-ca-nstab-special' => 'Хlара белха агlо йу, хlара рéдаккхалуш яц',
'tooltip-ca-nstab-project' => 'Кхолламан дакъа',
'tooltip-ca-nstab-image' => 'Хlуман агlо',
# Spam protection
'spamprotectiontitle' => 'Совбиларна литтар',
-# Skin names
-'skinname-standard' => 'Лела ма ярра',
-
# Browsing diffs
'previousdiff' => '← Хьалхдоьда нисдинарг',
'nextdiff' => 'Тlяхьа догlа нисдинарг →',
# Special:FilePath
'filepath' => 'ХIуман тIе болу некъ',
-'filepath-page' => 'Ð¥lÑ\83м:',
+'filepath-page' => 'Файл:',
'filepath-submit' => 'Дехьавала',
# Special:FileDuplicateSearch
'hijri-calendar-m3' => 'ڕەبیعەلئەووەڵ',
'hijri-calendar-m4' => 'ڕەبیعەلئاخیر',
'hijri-calendar-m5' => 'جومادەلئوولا',
-'hijri-calendar-m6' => 'جومادەسسانی',
+'hijri-calendar-m6' => 'جومادەلئاخیر',
'hijri-calendar-m7' => 'ڕەجەب',
'hijri-calendar-m8' => 'شەعبان',
'hijri-calendar-m9' => 'ڕەمەزان',
'nov' => '11.',
'dec' => '12.',
+'monday-at' => 'v pondělí v $1',
+'tuesday-at' => 'v úterý v $1',
+'wednesday-at' => 've středu v $1',
+'thursday-at' => 've čtvrtek v $1',
+'friday-at' => 'v pátek v $1',
+'saturday-at' => 'v sobotu v $1',
+'sunday-at' => 'v neděli v $1',
+'today-at' => '$1',
+'yesterday-at' => 'včera v $1',
+
# Categories related messages
'pagecategories' => '{{PLURAL:$1|Kategorie|Kategorie|Kategorie}}',
'category_header' => 'Stránky v kategorii „$1“',
'ncategories' => '$1 {{PLURAL:$1|kategorie|kategorie|kategorií}}',
'ninterwikis' => '$1 {{PLURAL:$1|mezijazykový odkaz|mezijazykové odkazy|mezijazykových odkazů}}',
'nlinks' => '$1 {{PLURAL:$1|odkaz|odkazy|odkazů}}',
-'nmembers' => '$1 {{PLURAL:$1|stránka|stránky|stránek}}',
+'nmembers' => '$1 {{PLURAL:$1|položka|položky|položek}}',
'nrevisions' => '$1 {{PLURAL:$1|revize|revize|revizí}}',
'nviews' => '$1 {{PLURAL:$1|návšteva|návštevy|návštev}}',
'nimagelinks' => 'Použit na $1 {{PLURAL:$1|stránce|stránkách}}',
# Image rotation
'rotate-comment' => 'Obrázek otočen o $1 {{PLURAL:$1|stupeň|stupně|stupňů}} po směru hodinových ručiček',
+# Unknown messages
+'hours-ago' => 'před $1 {{PLURAL:$1|hodinou|hodinami}}',
+'minutes-ago' => 'před $1 {{PLURAL:$1|minutou|minutami}}',
+'seconds-ago' => 'před $1 {{PLURAL:$1|sekundou|sekundami}}',
);
'watchmethod-list' => 'Tjekker seneste ændringer for sider i din overvågningsliste',
'watchlistcontains' => 'Din overvågningsliste indeholder $1 {{PLURAL:$1|side|sider}}.',
'iteminvalidname' => "Problem med '$1', ugyldigt navn...",
-'wlnote' => "Nedenfor ses {{PLURAL:$1|den seneste ændring|de seneste '''$1''' ændringer}} i {{PLURAL:$2|den sidste time|'''de sidste $2 timer}}''' fra den $3, kl. $4.",
+'wlnote' => "Nedenfor ses {{PLURAL:$1|den seneste ændring|de seneste '''$1''' ændringer}} i {{PLURAL:$2|den sidste time|'''de sidste $2 timer}}''' op til den $3 kl. $4.",
'wlshowlast' => 'Vis de seneste $1 timer $2 dage $3',
'watchlist-options' => 'Indstillinger for overvågningslisten',
'nov' => 'Nov.',
'dec' => 'Dez.',
+'monday-at' => 'Montag um $1',
+'tuesday-at' => 'Dienstag um $1',
+'wednesday-at' => 'Mittwoch um $1',
+'thursday-at' => 'Donnerstag um $1',
+'friday-at' => 'Freitag um $1',
+'saturday-at' => 'Samstag um $1',
+'sunday-at' => 'Sonntag um $1',
+'today-at' => '$1',
+'yesterday-at' => 'Gestern um $1',
+
# Categories related messages
'pagecategories' => '{{PLURAL:$1|Kategorie|Kategorien}}',
'category_header' => 'Seiten in der Kategorie „$1“',
'yourpasswordagain' => 'Passwort wiederholen:',
'remembermypassword' => 'Mit diesem Browser dauerhaft angemeldet bleiben (maximal $1 {{PLURAL:$1|Tag|Tage}})',
'userlogin-remembermypassword' => 'Angemeldet bleiben',
-'userlogin-signwithsecure' => 'Mit dem sicheren Server anmelden',
+'userlogin-signwithsecure' => 'Über den sicheren Server anmelden',
'securelogin-stick-https' => 'Nach dem Anmelden mit HTTPS verbunden bleiben',
'yourdomainname' => 'Deine Domain:',
'password-change-forbidden' => 'Du kannst auf diesem Wiki keine Passwörter ändern.',
'searchprofile-advanced' => 'Erweitert',
'searchprofile-articles-tooltip' => 'Suchen in $1',
'searchprofile-project-tooltip' => 'Suchen in $1',
-'searchprofile-images-tooltip' => 'Nach Bildern suchen',
+'searchprofile-images-tooltip' => 'Nach Dateien suchen',
'searchprofile-everything-tooltip' => 'Gesamten Inhalt durchsuchen (inklusive Diskussionsseiten)',
'searchprofile-advanced-tooltip' => 'Suche in weiteren Namensräumen',
'search-result-size' => '$1 ({{PLURAL:$2|1 Wort|$2 Wörter}})',
'rc-change-size' => '$1 {{PLURAL:$1|Byte|Bytes}}',
'rc-change-size-new' => '$1 {{PLURAL:$1|Byte|Bytes}} nach der Änderung',
'newsectionsummary' => 'Neuer Abschnitt /* $1 */',
-'rc-enhanced-expand' => 'Details anzeigen (benötigt JavaScript)',
-'rc-enhanced-hide' => 'Details verstecken',
+'rc-enhanced-expand' => 'Einzelheiten anzeigen (benötigt JavaScript)',
+'rc-enhanced-hide' => 'Einzelheiten verstecken',
'rc-old-title' => 'ursprünglich erstellt als „$1“',
# Recent changes linked
'minutes' => '{{PLURAL:$1|$1 Minute|$1 Minuten}}',
'hours' => '{{PLURAL:$1|1 Stunde|$1 Stunden}}',
'days' => '{{PLURAL:$1|$1 Tag|$1 Tage}}',
+'weeks' => '{{PLURAL:$1|$1 Woche|$1 Wochen}}',
'months' => '{{PLURAL:$1|1 Monat|$1 Monate}}',
'years' => '{{PLURAL:$1|1 Jahr|$1 Jahre}}',
'ago' => 'vor $1',
# Image rotation
'rotate-comment' => 'Bild um $1 {{PLURAL:$1|Grad}} im Uhrzeigersinn gedreht',
+# Unknown messages
+'hours-ago' => 'vor {{PLURAL:$1|einer Stunde|$1 Stunden}}',
+'minutes-ago' => 'vor {{PLURAL:$1|einer Minute|$1 Minuten}}',
+'seconds-ago' => 'vor {{PLURAL:$1|einer Sekunde|$1 Sekunden}}',
);
$messages = array(
# User preference toggles
-'tog-underline' => 'Bınê gırey de xete bıance:',
+'tog-underline' => 'Bınê gırey de xete bance:',
'tog-justify' => 'Paragrafan eyar ke',
'tog-hideminor' => 'Vurnayışanê şenıkan pela vurnayışanê peyênan de bınımne',
'tog-hidepatrolled' => 'Vurnayışanê qontrolkerdeyan pela vurnayışê peyêni de bınımne',
'tog-newpageshidepatrolled' => 'Pelanê qontrolkerdeyan lista pelanê neweyan de bınımne',
-'tog-extendwatchlist' => 'Lista seyrkerdışi hera bıke ke vurnayışi pêro bıasê, tenya tewr peyêni nê',
+'tog-extendwatchlist' => 'Lista seyrkerdışi hera bıke ke vurnayışi pêro basê, tenya tewr peyêni nê',
'tog-usenewrc' => 'Pele be vurnayışanê grube de vurnayışê peyêni u lista seyrkerdışi (JavaScript lazımo)',
'tog-numberheadings' => 'Sernuşteyan be xo numre cı şane',
'tog-showtoolbar' => 'Goceganê hacetanê vurnayışi bımocne (JavaScript lazımo)',
'tog-previewontop' => 'Verqayti pela nuştışi ser de bımocne',
'tog-previewonfirst' => 'Vurnayışo verên de verqayti tım bımocne',
'tog-nocache' => 'Pelanê cıgeyrayoği meya xo viri',
-'tog-enotifwatchlistpages' => 'Jû pele ya zi dosyaya ke lista mına seyrkerdışi de vurnayê mı rê e-poste bırışe',
+'tog-enotifwatchlistpages' => 'Yew pele ya zi dosyaya ke lista mına seyrkerdışi de vurnayê mı rê e-poste bırışe',
'tog-enotifusertalkpages' => 'Pela mına werênayışi ke vurnayê mı rê e-poste bırışe',
'tog-enotifminoredits' => 'Vurnayışanê qıckekanê pelan u dosyeyan de zi mı rê e-poste bırışe',
'tog-enotifrevealaddr' => 'Adresa e-posteyê mı posteyê xeberan de bımocne',
'tog-watchlisthideminor' => 'Vurnayışanê qıckekan lista mına seyrkerdışi de bınımne',
'tog-watchlisthideliu' => 'Lista seyrkerdışi ra vurnayışanê karberanê cıkewteyan bınımne',
'tog-watchlisthideanons' => 'Lista seyrkerdışi ra vurnayışanê karberanê anoniman bınımne',
-'tog-watchlisthidepatrolled' => 'Lista seyrkerdışi ra vurnayışanê qontrol kerdeyan bınımne',
+'tog-watchlisthidepatrolled' => 'Lista seyrkerdışi ra vurnayışanê qontrolkerdeyan bınımne',
'tog-ccmeonemails' => 'E-posteyanê ke ez karberanê binan rê rışenan, mı rê kopya inan bırışe',
'tog-diffonly' => 'Qıyasê versiyonan de tek ferqan bımocne, pela butıne nê',
-'tog-showhiddencats' => 'Kategoriyanê dızdine bımocne',
+'tog-showhiddencats' => 'Kategoriyanê dızdiye bımocne',
'tog-noconvertlink' => 'Greyê sernami çerx kerdışi bıqefılne',
'tog-norollbackdiff' => 'Peyserardışi ra dıme ferqi caverde',
-'tog-useeditwarning' => 'wexta ke ez pelo nêqeydbiyaye ra veciyaya mı hişyar bıker',
+'tog-useeditwarning' => 'Wexto ke mı yew pela nizami be vurnayışanê nêqeydbiyayeyan caverdê, hay be mı ser de',
'underline-always' => 'Tım',
'underline-never' => 'Qet',
-'underline-default' => 'Cild ya zi cıgeyrayoğo hesıbyaye',
+'underline-default' => 'Cild ya zi cıgeyrayoğo hesebiyaye',
# Font style option in Special:Preferences
'editfont-style' => 'Cayê vurnayışi de terzê nuştışi:',
'brokenredirects-edit' => 'bıvurne',
'brokenredirects-delete' => 'bestere',
-'withoutinterwiki' => 'Peleyê ke zıwanan de bina re gırey cı çınyo',
+'withoutinterwiki' => 'Pelê ke zıwananê binan rê gıreyê cı çıniyo',
'withoutinterwiki-summary' => 'Enê pelî ke versiyonê ziwanî binî ra link nidano.',
'withoutinterwiki-legend' => 'Verole',
'withoutinterwiki-submit' => 'Bımocne',
-'fewestrevisions' => 'Peleyê ke cı sero tewr tayn timaryayış vıraziyayo',
+'fewestrevisions' => 'Pelê be senık çımraviyarnayışi',
# Miscellaneous special pages
'nbytes' => '$1 {{PLURAL:$1|bayt|bayti}}',
'uncategorizedpages' => 'Pelayanê ke kategorî nibiye',
'uncategorizedcategories' => 'Kategoriyê ke bê kategorîyê',
'uncategorizedimages' => 'Dosyayê ke bê kategoriyê',
-'uncategorizedtemplates' => 'Şablonê ke bê kategoriyê',
+'uncategorizedtemplates' => 'Şablonê ke bêkategoriyê',
'unusedcategories' => 'Kategoriyê ke nê xebtênê',
'unusedimages' => 'Dosyeyê ke nê xebtênê',
'popularpages' => 'Pelî ke populer o.',
'wantedcategories' => 'Kategoriye ke waştênê',
'wantedpages' => 'Peleye ke waştênê',
'wantedpages-badtitle' => 'sernuşte meqbul niyo: $1',
-'wantedfiles' => 'Dosyeye ke waştênê',
+'wantedfiles' => 'Dosyeyê cıgeyriyayey',
'wantedfiletext-cat' => 'Dosyaya cêrên karvıstedeya lakin çınya. Mewcud dosyayan de xeriba miyan de liste bena. Xırabiya wınisin dana <del>ateber</del>. Zewbi zi, şırê pela da dosyeyê ke çınyaya [[:$1]].',
'wantedfiletext-nocat' => 'Dosyeyê cêrêni estê lekin karnêvıstê. Dosyeyê xeribi liste benê. bo babeta dano <del>ateber</del>',
-'wantedtemplates' => 'Şablonê ke waştênê',
+'wantedtemplates' => 'Şablonê ke waziyenê',
'mostlinked' => 'Pelî ke tewr zafî lînk bîy.',
'mostlinkedcategories' => 'Kategorî ke tewr zafî lînk bîy.',
'mostlinkedtemplates' => 'Şablonê ke tewr zafî pela re gıre bîye.',
'prefixindex-namespace' => 'Peleyê Veroleyıni ($1 cay nami)',
'shortpages' => 'Pelê kılmeki',
'longpages' => 'Peleyê dergeki',
-'deadendpages' => 'pelê ke pelê binan re gırey nêeşto',
+'deadendpages' => 'Pelê nêgıredayey',
'deadendpagestext' => 'Ena pelan ke {{SITENAME}} de zerrî ey de link çini yo.',
-'protectedpages' => 'Pelayê ke biyê star',
+'protectedpages' => 'Pelê pawıtiyey',
'protectedpages-indef' => 'têna pawıteyê bêmuddeti',
'protectedpages-cascade' => 'Kilit biyaye ke teyna cascadiye',
'protectedpagestext' => 'pelê cêrınî pawiyenê',
'protectedpagesempty' => 'pê ney parametreyan pelê pawiteyi çinî',
-'protectedtitles' => 'Sernameyê ke starênê',
+'protectedtitles' => 'Sernameyê pawıtiyey',
'protectedtitlestext' => 'sernameyê cêrıni pawıte yî',
'protectedtitlesempty' => 'pê ney parametreyan sernuşteyê pawite çinê',
'listusers' => 'Listeyê Karberan',
'restriction-upload' => 'Bar ke',
# Restriction levels
-'restriction-level-sysop' => 'pawıtışê tamamîye',
-'restriction-level-autoconfirmed' => 'nêm-pawıtış',
-'restriction-level-all' => 'seviye ya ke raşt ame',
+'restriction-level-sysop' => 'tam pawiyayo',
+'restriction-level-autoconfirmed' => 'nêm pawiyayo',
+'restriction-level-all' => 'heme yew sewiya',
# Undelete
'undelete' => 'Peleyê ke besterneyayê enê bımocnê',
* Xısusi pelaya normal
* <span class="mw-specialpagerestricted">Xısusi peleyê keı rê ray nê deyaya.</span>
* <strong class="mw-specialpagerestricted">Peleya xısusiya ke grota verhefıza.</strong>',
-'specialpages-group-maintenance' => 'Raporê pak tepiştîşî',
+'specialpages-group-maintenance' => 'Raporê tepıştışi',
'specialpages-group-other' => 'Pelê xasiyê bini',
'specialpages-group-login' => 'Cı kewe / hesab vıraze',
'specialpages-group-changes' => 'Vurnayişê peni u logan',
'specialpages-group-media' => 'Raporê medya u bar kerdîşî',
'specialpages-group-users' => 'Karber u heqqî',
'specialpages-group-highuse' => 'Peleyê ke vêşi karênê',
-'specialpages-group-pages' => 'listeyanê pelan',
+'specialpages-group-pages' => 'Listeyê pelan',
'specialpages-group-pagetools' => 'Haletê pelan',
'specialpages-group-wiki' => 'Melumat u haceti',
'specialpages-group-redirects' => 'Pela xasîyê ke heteneyayê',
'fullpagenamee' => array( 1, 'FULLPAGENAMEE' ),
'subpagename' => array( 1, 'SUBPAGENAME' ),
'subpagenamee' => array( 1, 'SUBPAGENAMEE' ),
+ 'rootpagename' => array( 1, 'ROOTPAGENAME' ),
+ 'rootpagenamee' => array( 1, 'ROOTPAGENAMEE' ),
'basepagename' => array( 1, 'BASEPAGENAME' ),
'basepagenamee' => array( 1, 'BASEPAGENAMEE' ),
'talkpagename' => array( 1, 'TALKPAGENAME' ),
'yourname' => 'Username:',
'userlogin-yourname' => 'Username',
'userlogin-yourname-ph' => 'Enter your username',
+'createacct-helpusername-url' => '{{ns:Project}}:Username_policy',
+'createacct-helpusername-link' => '[[{{MediaWiki:createacct-helpusername-url}}|(help me choose)]]',
'yourpassword' => 'Password:',
'userlogin-yourpassword' => 'Password',
'userlogin-yourpassword-ph' => 'Enter your password',
+'createacct-yourpassword-ph' => 'Enter a password',
'yourpasswordagain' => 'Retype password:',
+'createacct-yourpasswordagain' => 'Confirm password',
+'createacct-yourpasswordagain-ph' => 'Enter password again',
'remembermypassword' => 'Remember my login on this browser (for a maximum of $1 {{PLURAL:$1|day|days}})',
'userlogin-remembermypassword' => 'Remember me',
'userlogin-signwithsecure' => 'Sign in with secure server',
'userlogin-resetlink' => 'Forgotten your login details?',
'helplogin-url' => 'Help:Logging in',
'userlogin-helplink' => '[[{{MediaWiki:helplogin-url}}|Help with logging in]]',
+'createacct-join' => 'Enter your information below.',
+'createacct-emailrequired' => 'Email address',
+'createacct-emailoptional' => 'Email address (optional)',
+'createacct-email-ph' => 'Enter your email address',
'createaccountmail' => 'Use a temporary random password and send it to the email address specified below',
+'createacct-realname' => 'Real name (optional)',
'createaccountreason' => 'Reason:',
+'createacct-reason' => 'Reason',
+'createacct-captcha' => 'Security check',
+'createacct-captcha-help-url' => '{{ns:Project}}:Request an account',
+'createacct-imgcaptcha-help' => 'Can\'t see the image? [[{{MediaWiki:createacct-captcha-help-url}}|Request an account]]',
+'createacct-imgcaptcha-ph' => 'Enter the text you see above',
+'createacct-benefit-heading' => '{{SITENAME}} is made by people like you.',
+'createacct-benefit-icon1' => 'icon-edits',
+'createacct-benefit-head1' => '{{NUMBEROFEDITS}}',
+'createacct-benefit-body1' => 'edits',
+'createacct-benefit-icon2' => 'icon-pages',
+'createacct-benefit-head2' => '{{NUMBEROFARTICLES}}',
+'createacct-benefit-body2' => 'pages',
+'createacct-benefit-icon3' => 'icon-contributors',
+'createacct-benefit-head3' => '{{NUMBEROFACTIVEUSERS}}',
+'createacct-benefit-body3' => 'contributors this month',
'badretype' => 'The passwords you entered do not match.',
'userexists' => 'Username entered already in use.
Please choose a different name.',
'loginerror' => 'Login error',
+'createacct-error' => 'Account creation error',
'createaccounterror' => 'Could not create account: $1',
'nocookiesnew' => 'The user account was created, but you are not logged in.
{{SITENAME}} uses cookies to log in users.
'ago' => '$1 ago',
'just-now' => 'just now',
-'hours-ago' => '$1 {{PLURAL:$1|hour|hours}} ago',
-'minutes-ago' => '$1 {{PLURAL:$1|minute|minutes}} ago',
-'seconds-ago' => '$1 {{PLURAL:$1|seconds|seconds}} ago',
-
-'monday-at' => 'Monday at $1',
-'tuesday-at' => 'Tuesday at $1',
-'wednesday-at' => 'Wednesday at $1',
-'thursday-at' => 'Thursday at $1',
-'friday-at' => 'Friday at $1',
-'saturday-at' => 'Saturday at $1',
-'sunday-at' => 'Sunday at $1',
-
-'today-at' => '$1',
-'yesterday-at' => 'Yesterday at $1',
+# Human-readable timestamps
+'hours-ago' => '$1 {{PLURAL:$1|hour|hours}} ago',
+'minutes-ago' => '$1 {{PLURAL:$1|minute|minutes}} ago',
+'seconds-ago' => '$1 {{PLURAL:$1|seconds|seconds}} ago',
+'monday-at' => 'Monday at $1',
+'tuesday-at' => 'Tuesday at $1',
+'wednesday-at' => 'Wednesday at $1',
+'thursday-at' => 'Thursday at $1',
+'friday-at' => 'Friday at $1',
+'saturday-at' => 'Saturday at $1',
+'sunday-at' => 'Sunday at $1',
+'today-at' => '$1',
+'yesterday-at' => 'Yesterday at $1',
# Bad image list
'bad_image_list' => 'The format is as follows:
'nov' => 'Nov',
'dec' => 'Dec',
+'today-at' => '$1',
+
# Categories related messages
'pagecategories' => '{{PLURAL:$1|Kategorio|Kategorioj}}',
'category_header' => 'Artikoloj en kategorio "$1"',
'welcomecreation-msg' => 'Via konto estas kreita.
Ne forgesu ŝanĝi viajn [[Special:Preferences|{{SITENAME}}-preferojn]]',
'yourname' => 'Salutnomo:',
+'userlogin-yourname' => 'Uzantonomo',
+'userlogin-yourname-ph' => 'Enigu vian uzantonomon',
'yourpassword' => 'Pasvorto:',
+'userlogin-yourpassword' => 'Pasvorto',
+'userlogin-yourpassword-ph' => 'Enigu vian pasvorton',
'yourpasswordagain' => 'Retajpu pasvorton',
'remembermypassword' => 'Memori mian ensalutadon ĉe ĉi tiu komputilo (daŭrante maksimume $1 {{PLURAL:$1|tagon|tagojn}})',
+'userlogin-remembermypassword' => 'Memoru min',
'securelogin-stick-https' => 'Resti konektita al HTTPS post ensalutado',
'yourdomainname' => 'Via domajno',
'password-change-forbidden' => 'Ve ne povas ŝanĝi pasvortojn en ĉi tiu vikio.',
'logout' => 'Elsaluti',
'userlogout' => 'Elsaluti',
'notloggedin' => 'Ne ensalutinta',
+'userlogin-noaccount' => 'Ĉu vi ne havas konton?',
'nologin' => "Ĉu vi ne havas konton? '''$1'''.",
'nologinlink' => 'Krei konton',
'createaccount' => 'Krei novan konton',
'gotaccount' => "Ĉu vi jam havas konton? '''$1'''.",
'gotaccountlink' => 'Ensaluti',
'userlogin-resetlink' => 'Ĉu vi forgesis ensalutajn detalojn?',
+'userlogin-helplink' => '[[{{MediaWiki:helplogin-url}}|Helpo pri ensalutado]]',
'createaccountmail' => 'Uzi provizoran hazardsignan pasvorton kaj sendi ĝin al la retpoŝto suben',
'createaccountreason' => 'Kialo:',
'badretype' => 'La pasvortojn kiujn vi tajpis ne egalas.',
# Email sending
'php-mail-error-unknown' => 'Nekonata eraro en la funkcio mail() de PHP',
'user-mail-no-addy' => 'Provis sendi retpoŝton sen retpoŝtadreso.',
+'user-mail-no-body' => 'Provo sendi malplenan aŭ sensence mallongan retpošton.',
# Change password dialog
'resetpass' => 'Ŝanĝi pasvorton',
# Special:PasswordReset
'passwordreset' => 'Restarigo de pasvorto',
-'passwordreset-text' => 'Plenumigu ĉi tiun formularon por ricevi retpoŝtan memoraĵon de viaj kontaj detaloj.',
+'passwordreset-text' => 'Plenigu ĉi tiun formularon por renovigi vian pasvorton.',
'passwordreset-legend' => 'Refari pasvorton',
'passwordreset-disabled' => 'Pasvortaj restarigoj estis malŝaltitaj en ĉi tiu vikio.',
+'passwordreset-emaildisabled' => 'Retpoŝtaj funkcioj estas malfunkciigitaj en tiu ĉi vikio.',
'passwordreset-pretext' => '{{PLURAL:$1||Enigi unu el la jenaj datenoj}}',
'passwordreset-username' => 'Salutnomo:',
'passwordreset-domain' => 'Domajno:',
ĝin, vi povas ignori ĉi tiun mesaĝon kaj uzi vian malnovan pasvorton.',
'passwordreset-emailelement' => 'Salutnomo: $1
Provizora pasvorto: $2',
-'passwordreset-emailsent' => 'Rememoriga retpoŝto estis sendita.',
-'passwordreset-emailsent-capture' => 'Memoriga retpoŝto estis sendita, kiu estas montrata sube.',
-'passwordreset-emailerror-capture' => 'Memoriga retpoŝto estis generita, montrata sube, sed sendado al uzanto malsukcesis: $1',
+'passwordreset-emailsent' => 'Renovigita pasvorto estis retpoŝte sendita.',
+'passwordreset-emailsent-capture' => 'Retpoŝto kun renovigita pasvorto estis sendita, kiu estas montrata sube.',
+'passwordreset-emailerror-capture' => 'Retpoŝto kun renovigita pasvorto estis generita, montrata sube, sed sendado al uzanto malsukcesis: $1',
# Special:ChangeEmail
'changeemail' => 'Ŝanĝi retpoŝtadreson',
'search-interwiki-default' => '$1 rezultoj:',
'search-interwiki-more' => '(plu)',
'search-relatedarticle' => 'Relataj',
-'mwsuggest-disable' => 'Malŝalti AJAX-sugestojn',
+'mwsuggest-disable' => 'Malŝalti serĉajn sugestojn',
'searcheverything-enable' => 'Traserĉi ĉiujn nomspacojn',
'searchrelated' => 'rilataj',
'searchall' => 'ĉiuj',
'search-external' => 'Ekstera serĉo',
'searchdisabled' => '<p>Oni provizore malŝaltis serĉadon per la plenteksta
indekso pro troŝarĝita servilo. Intertempe, vi povas serĉi per <i>guglo</i> aŭ per <i>jahu!</i>:</p>',
+'search-error' => 'Okazis eraro dum serĉado: $1',
# Preferences page
'preferences' => 'Preferoj',
'prot_1movedto2' => '[[$1]] movita al [[$2]]',
'protect-badnamespace-title' => 'Ne-protektebla nomspaco',
'protect-badnamespace-text' => 'Paĝoj en ĉi tiu datumbazo ne povas esti protektita.',
+'protect-norestrictiontypes-title' => 'Neprotektebla paĝo',
'protect-legend' => 'Konfirmi protektadon',
'protectcomment' => 'Kialo:',
'protectexpiry' => 'Eksvalidiĝas:',
'protect-cascadeon' => 'Ĉi paĝo estas nun protektita kontraŭ redaktado ĉar ĝi estas inkluzivita en {{PLURAL:$1|jena paĝo, kiu mem estas protektita|jenaj paĝoj, kiuj mem estas protektitaj}} per kaskada protekto.
Vi povas ŝanĝi ties protektnivelon, sed tio ne ŝanĝos la kaskadan protekton.',
'protect-default' => 'Permesigi ĉiujn uzantojn',
-'protect-fallback' => 'Rajto "$1" nepras.',
+'protect-fallback' => 'Permesi nur uzantojn kun la rajto "$1"',
'protect-level-autoconfirmed' => 'Bloki novajn kaj neregistritajn uzantojn',
-'protect-level-sysop' => 'Nur administrantoj',
+'protect-level-sysop' => 'Permesi nur administrantojn',
'protect-summary-cascade' => 'kaskada',
'protect-expiring' => 'finiĝas je $1 (UTC)',
'protect-expiring-local' => 'eksdatiĝas $1',
'pageinfo-robot-noindex' => 'Ne indeksebla',
'pageinfo-views' => 'Nombro de rigardoj',
'pageinfo-watchers' => 'Nombro de paĝatentantoj',
+'pageinfo-few-watchers' => 'Malpli ol $1 {{PLURAL:$1|atentanto|atentantoj}}',
'pageinfo-redirects-name' => 'Alidirektoj al ĉi tiu paĝo',
'pageinfo-subpages-name' => 'Subpaĝoj de ĉi tiu paĝo',
'pageinfo-subpages-value' => '$1 ($2 {{PLURAL:$2|alidirektilo|alidirektiloj}}; $3 {{PLURAL:$3|ne-alidirektilo|ne-alidirektiloj}})',
'minutes' => '{{PLURAL:$1|$1 minuto|$1 minutoj}}',
'hours' => '{{PLURAL:$1|$1 horo|$1 horoj}}',
'days' => '{{PLURAL:$1|$1 tago|$1 tagoj}}',
+'weeks' => '{{PLURAL:$1|$1 semajno|$1 semajnoj}}',
'months' => '{{PLURAL:$1|$1 monato|$1 monatoj}}',
'years' => '{{PLURAL:$1|$1 jaro|$1 jaroj}}',
'ago' => 'antaŭ $1',
'htmlform-submit' => 'Ek!',
'htmlform-reset' => 'Malfari ŝanĝojn',
'htmlform-selectorother-other' => 'Alia',
+'htmlform-no' => 'Ne',
+'htmlform-yes' => 'Jes',
# SQLite database support
'sqlite-has-fts' => '$1 kun tut-teksta subteno',
'logentry-delete-restore' => '$1 restarigis paĝon $3',
'logentry-delete-event' => '$1 ŝanĝis videblecon de {{PLURAL:$5|protokola evento|$5 protokolaj eventoj}} je $3: $4',
'logentry-delete-revision' => '$1 ŝanĝis videblecon de {{PLURAL:$5|revizio|$5 reviziojn}} je paĝo $3: $4',
-'logentry-delete-event-legacy' => '$1 ŝanĝis vidiblecon de protokolaj eventoj en $3',
-'logentry-delete-revision-legacy' => '$1 ŝanĝis vidiblecon de revizioj en $3',
+'logentry-delete-event-legacy' => '$1 ŝanĝis videblecon de protokolaj eventoj en $3',
+'logentry-delete-revision-legacy' => '$1 ŝanĝis videblecon de revizioj en $3',
'logentry-suppress-delete' => '$1 kaŝis paĝon $3',
'logentry-suppress-event' => '$1 kaŝite ŝanĝis videblecon de {{PLURAL:$5|protokola evento|$5 protokolaj eventoj}} je $3: $4',
'logentry-suppress-revision' => '$1 kaŝite ŝanĝis videblecon de {{PLURAL:$5|revizio|$5 reviziojn}} je paĝo $3: $4',
-'logentry-suppress-event-legacy' => '$1 kaŝite ŝanĝis vidiblecon de protokolaj eventoj en $3',
-'logentry-suppress-revision-legacy' => '$1 kaŝite ŝanĝis vidiblecon de revizioj en paĝo $3',
+'logentry-suppress-event-legacy' => '$1 kaŝite ŝanĝis videblecon de protokolaj eventoj en $3',
+'logentry-suppress-revision-legacy' => '$1 kaŝite ŝanĝis videblecon de revizioj en paĝo $3',
'revdelete-content-hid' => 'enhavo kaŝita',
'revdelete-summary-hid' => 'resumo de redakto kaŝita',
'revdelete-uname-hid' => 'salutnomo kaŝita',
'revdelete-restricted' => 'aplikis limojn al administrantoj',
'revdelete-unrestricted' => 'forigis limojn por administrantoj',
'logentry-move-move' => '$1 movis paĝon $3 al $4',
-'logentry-move-move-noredirect' => '$1 movis paĝon $3 al $4 sen lasante alidirektilon',
+'logentry-move-move-noredirect' => '$1 movis paĝon $3 al $4 ne lasante alidirektilon',
'logentry-move-move_redir' => '$1 movis paĝon $3 al $4 anstataŭigante alidirektilon',
-'logentry-move-move_redir-noredirect' => '$1 movis paĝon $3 al $4 anstataŭigante alidirektilon sen lasante alidirektilon',
-'logentry-patrol-patrol' => '$1 markis revizion $4 de paĝo $3 kiel patrolita',
-'logentry-patrol-patrol-auto' => '$1 aŭtomate markis revizion $4 de paĝo $3 kiel patrolita',
-'logentry-newusers-newusers' => '$1 kreis konton',
-'logentry-newusers-create' => '$1 kreis konton',
-'logentry-newusers-create2' => '$1 kreis uzanton $3',
-'logentry-newusers-autocreate' => 'Konto $1 estis kreita aŭtomate',
+'logentry-move-move_redir-noredirect' => '$1 movis paĝon $3 al $4 anstataŭigante alidirektilon ne lasante alidirektilon',
+'logentry-patrol-patrol' => '$1 markis revizion $4 de paĝo $3 patrolita',
+'logentry-patrol-patrol-auto' => '$1 aŭtomate markis revizion $4 de paĝo $3 patrolita',
+'logentry-newusers-newusers' => 'Konto de uzanto $1 estis kreita',
+'logentry-newusers-create' => 'Konto de uzanto $1 estis kreita',
+'logentry-newusers-create2' => 'Konto de uzanto $3 estis kreita de $1',
+'logentry-newusers-byemail' => 'Konto de uzanto $3 estis kreita de $1 kaj pasvorto estis sendita per retpoŝto',
+'logentry-newusers-autocreate' => 'Uzantokonto $1 estis kreita aŭtomate',
'logentry-rights-rights' => '$1 ŝanĝis grupan membrecon por $3 de $4 al $5',
'logentry-rights-rights-legacy' => '$1 ŝanĝis grupan membrecon por $3',
'logentry-rights-autopromote' => '$1 estis aŭtomate {{GENDER:$2|altrangigita}} de $4 al $5',
'duration-centuries' => '$1 {{PLURAL:$1|jarcento|jarcentoj}}',
'duration-millennia' => '$1 {{PLURAL:$1|jarmilo|jarmiloj}}',
+# Unknown messages
+'hours-ago' => 'antaŭ $1 {{PLURAL:$1|horo|horoj}}',
+'minutes-ago' => 'antaŭ $1 {{PLURAL:$1|minuto|minutoj}}',
+'seconds-ago' => 'antaŭ $1 {{PLURAL:$1|sekundo|sekundoj}}',
);
'nov' => 'nov',
'dec' => 'dic',
+'monday-at' => 'El lunes a las $1',
+'tuesday-at' => 'El martes a las $1',
+'wednesday-at' => 'El miércoles a las $1',
+'thursday-at' => 'El jueves a las $1',
+'friday-at' => 'El viernes a las $1',
+'saturday-at' => 'El sábado a las $1',
+'sunday-at' => 'El domingo a las $1',
+'today-at' => '$1',
+'yesterday-at' => 'Ayer a las $1',
+
# Categories related messages
'pagecategories' => '{{PLURAL:$1|Categoría|Categorías}}',
'category_header' => 'Artículos en la categoría «$1»',
# Image rotation
'rotate-comment' => 'Imagen girada por $1 {{PLURAL:$1|grado|grados}} en el sentido de las agujas del reloj',
+# Unknown messages
+'hours-ago' => 'hace $1 {{PLURAL:$1|hora|horas}}',
+'minutes-ago' => 'hace {{PLURAL:$1|un minuto|$1 minutos}}',
+'seconds-ago' => 'hace $1 {{PLURAL:$1|segundo|segundos}}',
);
'nov' => 'نوامبر',
'dec' => 'دسامبر',
+'monday-at' => 'دوشنبهٔ $1',
+'tuesday-at' => 'سهشنبهٔ $1',
+'wednesday-at' => 'چهارشنبهٔ $1',
+'thursday-at' => 'پنجشنبهٔ $1',
+'friday-at' => 'جمعهٔ $1',
+'saturday-at' => 'شنبهٔ $1',
+'sunday-at' => 'یکشنبهٔ $1',
+'today-at' => '$1',
+'yesterday-at' => 'دیروز $1',
+
# Categories related messages
'pagecategories' => '{{PLURAL:$1|رده|ردهها}}',
'category_header' => 'صفحههای ردهٔ «$1»',
# Image rotation
'rotate-comment' => 'تصویر به دست $1 {{PLURAL:$1|درجهٔ|درجهٔ}} ساعتگرد چرخانده شد',
+# Unknown messages
+'hours-ago' => '$1 {{PLURAL:$1|ساعت|ساعت}} قبل',
+'minutes-ago' => '$1 {{PLURAL:$1|دقیقه|دقیقه}} قبل',
+'seconds-ago' => '$1 {{PLURAL:$1|ثانیه|ثانیه}} قبل',
);
'nov' => 'nov',
'dec' => 'déc',
+'monday-at' => 'Lundi à $1',
+'tuesday-at' => 'Mardi à $1',
+'wednesday-at' => 'Mercredi à $1',
+'thursday-at' => 'Jeudi à $1',
+'friday-at' => 'Vendredi à $1',
+'saturday-at' => 'Samedi à $1',
+'sunday-at' => 'Dimanche à $1',
+'today-at' => '$1',
+'yesterday-at' => 'Hier à $1',
+
# Categories related messages
'pagecategories' => '{{PLURAL:$1|Catégorie|Catégories}}',
'category_header' => 'Pages dans la catégorie « $1 »',
'vector-simplesearch-preference' => "Activer la barre de recherche simplifiée (seulement pour l'habillage Vector)",
'vector-view-create' => 'Créer',
'vector-view-edit' => 'Modifier',
-'vector-view-history' => "Afficher l'historique",
+'vector-view-history' => 'Afficher l’historique',
'vector-view-view' => 'Lire',
'vector-view-viewsource' => 'Voir la source',
'actions' => 'Actions',
'minutes' => '{{PLURAL:$1|$1 minute|$1 minutes}}',
'hours' => '{{PLURAL:$1|$1 heure|$1 heures}}',
'days' => '{{PLURAL:$1|$1 jour|$1 jours}}',
+'weeks' => '{{PLURAL:$1|$1 semaine|$1 semaines}}',
'months' => '{{PLURAL:$1|$1 mois}}',
'years' => '{{PLURAL:$1|$1 an|$1 ans}}',
'ago' => 'Il y a $1',
# Image rotation
'rotate-comment' => 'Image pivotée de $1 {{PLURAL:$1|degré|degrés}} dans le sens des aiguilles d’une montre',
+# Unknown messages
+'hours-ago' => 'il y a $1 {{PLURAL:$1|heure|heures}}',
+'minutes-ago' => 'il y a $1 {{PLURAL:$1|minute|minutes}}',
+'seconds-ago' => 'il y a $1 {{PLURAL:$1|seconde|secondes}}',
);
'tog-watchmoves' => 'מעקב אחרי דפים וקבצים שהעברתי',
'tog-watchdeletion' => 'מעקב אחרי דפים וקבצים שמחקתי',
'tog-minordefault' => 'הגדרת כל פעולת עריכה כמשנית אם לא צוין אחרת',
-'tog-previewontop' => 'הצגת תצוגה מקדימה לפני תיבת העריכה (או: אחריה)',
+'tog-previewontop' => 'הצגת תצוגה מקדימה לפני תיבת העריכה',
'tog-previewonfirst' => 'הצגת תצוגה מקדימה בעריכה ראשונה',
'tog-nocache' => 'מניעת אחסון הדפים בזיכרון המטמון בדפדפן',
'tog-enotifwatchlistpages' => 'לשלוח אליי דואר אלקטרוני כאשר משתנה דף או קובץ ברשימת המעקב שלי',
'tog-enotifusertalkpages' => 'לשלוח אליי דואר אלקטרוני כאשר נעשה שינוי בדף שיחת המשתמש שלי',
'tog-enotifminoredits' => 'לשלוח אליי דואר אלקטרוני גם על עריכות משניות של דפים וקבצים',
'tog-enotifrevealaddr' => 'חשיפת כתובת הדוא"ל שלך בהודעות דוא"ל',
-'tog-shownumberswatching' => 'הצגת מספר המשתמשים העוקבים אחרי הדף',
-'tog-oldsig' => '×\94×\97ת×\99×\9e×\94 ×\94ק×\99×\99×\9eת:',
+'tog-shownumberswatching' => 'הצגת מספר המשתמשים העוקבים',
+'tog-oldsig' => '×\94×\97ת×\99×\9e×\94 ×\94× ×\95×\9b×\97×\99ת:',
'tog-fancysig' => 'פירוש החתימה כקוד ויקי (ללא קישור אוטומטי)',
-'tog-showjumplinks' => 'הצגת קישורי נגישות מסוג "קפוץ אל"',
+'tog-showjumplinks' => 'הצגת קישורי נגישות מסוג "{{int:jumpto}}"',
'tog-uselivepreview' => 'שימוש בתצוגה מקדימה מהירה (דרוש JavaScript) (ניסיוני)',
'tog-forceeditsummary' => 'הצגת אזהרה בעת הכנסת תקציר עריכה ריק',
-'tog-watchlisthideown' => 'הסתרת עריכות שלי ברשימת המעקב',
-'tog-watchlisthidebots' => 'הסתרת בוטים ברשימת המעקב',
+'tog-watchlisthideown' => '×\94סתרת ×\94ער×\99×\9b×\95ת ש×\9c×\99 ×\91רש×\99×\9eת ×\94×\9eעק×\91',
+'tog-watchlisthidebots' => '×\94סתרת ער×\99×\9b×\95ת ש×\9c ×\91×\95×\98×\99×\9d ×\91רש×\99×\9eת ×\94×\9eעק×\91',
'tog-watchlisthideminor' => 'הסתרת עריכות משניות ברשימת המעקב',
'tog-watchlisthideliu' => 'הסתרת עריכות של משתמשים רשומים ברשימת המעקב',
'tog-watchlisthideanons' => 'הסתרת עריכות של משתמשים אנונימיים ברשימת המעקב',
'nov' => "נוב'",
'dec' => "דצמ'",
+'monday-at' => 'ביום שני בשעה $1',
+'tuesday-at' => 'ביום שלישי בשעה $1',
+'wednesday-at' => 'ביום רביעי בשעה $1',
+'thursday-at' => 'ביום חמישי בשעה $1',
+'friday-at' => 'ביום שישי בשעה $1',
+'saturday-at' => 'בשבת בשעה $1',
+'sunday-at' => 'ביום ראשון בשעה $1',
+'today-at' => '$1',
+'yesterday-at' => 'אתמול בשעה $1',
+
# Categories related messages
'pagecategories' => '{{PLURAL:$1|קטגוריה|קטגוריות}}',
'category_header' => 'דפים בקטגוריה "$1"',
'minutes' => '{{PLURAL:$1|דקה|$1 דקות}}',
'hours' => '{{PLURAL:$1|שעה|שעתיים|$1 שעות}}',
'days' => '{{PLURAL:$1|יום|יומיים|$1 ימים}}',
+'weeks' => '{{PLURAL:$1|שבוע|שבועיים|$1 שבועות}}',
'months' => '{{PLURAL:$1|חודש|חודשיים|$1 חודשים}}',
'years' => '{{PLURAL:$1|שנה|שנתיים|$1 שנים}}',
'ago' => 'לפני $1',
# Image rotation
'rotate-comment' => 'התמונה סובבה {{PLURAL:$1|במעלה אחת|ב֫־$1 מעלות}} בכיוון השעון',
+# Unknown messages
+'hours-ago' => 'לפני {{PLURAL:$1|שעה|שעתיים|$1 שעות}}',
+'minutes-ago' => 'לפני {{PLURAL:$1|דקה|$1 דקות}}',
+'seconds-ago' => 'לפני {{PLURAL:$1|שנייה|$1 שניות}}',
);
'rc-old-title' => 'prěnjotnje wutworjeny jako "$1"',
# Recent changes linked
-'recentchangeslinked' => 'Změny w zwjazanych stronach',
+'recentchangeslinked' => 'Změny na zwjazanych stronach',
'recentchangeslinked-feed' => 'Změny zwjazanych stron',
-'recentchangeslinked-toolbox' => 'Změny w zwjazanych stronach',
+'recentchangeslinked-toolbox' => 'Změny na zwjazanych stronach',
'recentchangeslinked-title' => 'Změny na stronach, kotrež su z „$1“ wotkazane',
'recentchangeslinked-noresult' => 'Njejsu změny zwajzanych stron we wubranej dobje.',
'recentchangeslinked-summary' => "Tuta strona nalistuje poslednje změny na wotkazanych stronach (resp. pola kategorijow na čłonach kategorije).
'nov' => 'nov',
'dec' => 'dec',
+'monday-at' => 'Lunedi a $1',
+'tuesday-at' => 'Martedi a $1',
+'wednesday-at' => 'Mercuridi a $1',
+'thursday-at' => 'Jovedi a $1',
+'friday-at' => 'Venerdi a $1',
+'saturday-at' => 'Sabbato a $1',
+'sunday-at' => 'Dominica a $1',
+'today-at' => '$1',
+'yesterday-at' => 'Heri a $1',
+
# Categories related messages
'pagecategories' => '{{PLURAL:$1|Categoria|Categorias}}',
'category_header' => 'Articulos in le categoria "$1"',
# Image rotation
'rotate-comment' => 'Imagine rotate de $1 {{PLURAL:$1|grado|grados}} in senso horologic',
+# Unknown messages
+'hours-ago' => '$1 {{PLURAL:$1|hora|horas}} retro',
+'minutes-ago' => '$1 {{PLURAL:$1|minuta|minutas}} retro',
+'seconds-ago' => '$1 {{PLURAL:$1|secunda|secundas}} retro',
);
* @author Reedy
* @author Sapral Mikail
* @author Tagir
+ * @author Умар
*/
$fallback = 'ru';
'tog-shownumberswatching' => 'Ший теркама дагарленгах оагӀув чулаьца бола дакъалаьцархой таьрах хьахьокха',
'tog-oldsig' => 'Дола кулгайоазув:',
'tog-fancysig' => 'Ший кулга яздара массахоамбаккхам (ший лоӀаме Ӏинка йоацаш)',
-'tog-externaleditor' => 'Арена гӀалатнийсдарца болх бе (ший болх ховш болачара мара мегаш дац, хьамлоархIара ший-тайпара оттам эша; [//www.mediawiki.org/wiki/Manual:External_editors хьажа эша])',
-'tog-externaldiff' => 'Арена бӀасакхосса болхоагӀувца болх бе (ший болх ховш болачара мара мегаш дац, хьамлоархIара ший-тайпара оттам эша; [//www.mediawiki.org/wiki/Manual:External_editors хьажа эша])',
'tog-showjumplinks' => '"Дехьадала" яха новкъостала Ӏинк хьахьокха',
'tog-uselivepreview' => 'Сиха бӀарахьажар (JavaScript) (Экспериментально)',
'tog-forceeditsummary' => 'Хоам бе, хувцамий лоацам белгал даь деце',
'powersearch-toggleall' => 'Деррига',
'powersearch-togglenone' => 'Цхьаккха',
-# Quickbar
-'qbsettings-none' => 'Цхьаккха',
-
# Preferences page
'preferences' => 'Оттамаш',
'mypreferences' => 'Оттамаш',
# Special:ListGroupRights
'listgrouprights-members' => '(тоабий дагарче)',
-# E-mail user
+# Email user
'emailuser' => 'Дакъалаьцархочоа д-хоамни:',
# Watchlist
'nov' => 'nov',
'dec' => 'dic',
+'monday-at' => 'Lunedì alle $1',
+'tuesday-at' => 'Martedì alle $1',
+'wednesday-at' => 'Mercoledì alle $1',
+'thursday-at' => 'Giovedì alle $1',
+'friday-at' => 'Venerdì alle $1',
+'saturday-at' => 'Sabato alle $1',
+'sunday-at' => 'Domenica alle $1',
+'yesterday-at' => 'Ieri alle $1',
+
# Categories related messages
'pagecategories' => '{{PLURAL:$1|Categoria|Categorie}}',
'category_header' => 'Pagine nella categoria "$1"',
'site-atom-feed' => 'Feed Atom di $1',
'page-rss-feed' => 'Feed RSS per "$1"',
'page-atom-feed' => 'Feed Atom per "$1"',
-'feed-rss' => 'RSS',
'red-link-title' => '$1 (la pagina non esiste)',
'sort-descending' => 'Ordinamento decrescente',
'sort-ascending' => 'Ordinamento crescente',
'minutes' => '{{PLURAL:$1|un minuto|$1 minuti}}',
'hours' => "{{PLURAL:$1|un'ora|$1 ore}}",
'days' => '{{PLURAL:$1|$1 giorno|$1 giorni}}',
+'weeks' => '{{PLURAL:$1|$1 settimana|$1 settimane}}',
'months' => '{{PLURAL:$1|$1 mese|$1 mesi}}',
'years' => '{{PLURAL:$1|$1 anno|$1 anni}}',
'ago' => '$1 fa',
# Image rotation
'rotate-comment' => 'Immagine ruotata di $1 {{PLURAL:$1|grado|gradi}} in senso orario',
+# Unknown messages
+'hours-ago' => '$1 {{PLURAL:$1|ora|ore}} fa',
+'minutes-ago' => '$1 {{PLURAL:$1|minuto|minuti}} fa',
+'seconds-ago' => '$1 {{PLURAL:$1|secondo|secondi}} fa',
);
'nov' => '11月',
'dec' => '12月',
+'monday-at' => '月曜日 $1',
+'tuesday-at' => '火曜日 $1',
+'wednesday-at' => '水曜日 $1',
+'thursday-at' => '木曜日 $1',
+'friday-at' => '金曜日 $1',
+'saturday-at' => '土曜日 $1',
+'sunday-at' => '日曜日 $1',
+'today-at' => '$1',
+'yesterday-at' => '昨日 $1',
+
# Categories related messages
'pagecategories' => '{{PLURAL:$1|カテゴリ}}',
'category_header' => 'カテゴリ「$1」にあるページ',
# Image rotation
'rotate-comment' => '画像を時計回りに $1 {{PLURAL:$1|度}}回転',
+# Unknown messages
+'hours-ago' => '$1 {{PLURAL:$1|時間}}前',
+'minutes-ago' => '$1 {{PLURAL:$1|分}}前',
+'seconds-ago' => '$1 {{PLURAL:$1|秒}}前',
);
'nov' => 'Wam',
'dec' => 'Duj',
+'monday-at' => 'Arim af $1',
+'tuesday-at' => 'Aram af $1',
+'wednesday-at' => 'Ahad af $1',
+'thursday-at' => 'Amhad af $1',
+'friday-at' => 'Sem af $1',
+'saturday-at' => 'Sed af $1',
+'sunday-at' => 'Acer af $1',
+'today-at' => '$1',
+'yesterday-at' => 'Iḍelli af $1',
+
# Categories related messages
'pagecategories' => '{{PLURAL:$1|Taggayt|Taggayin}}',
'category_header' => 'Imagraden deg taggayt "$1"',
'duration-centuries' => '$1 {{PLURAL:$1|timiḍi|timiḍa}}',
'duration-millennia' => '$1 {{PLURAL:$1|agimseggwas|agimseggwasen}}',
+# Unknown messages
+'hours-ago' => '$1 {{PLURAL:$1|asrag|isragen}} aya',
+'minutes-ago' => '$1 {{PLURAL:$1|tamrect|timercin}} aya',
+'seconds-ago' => '$1 {{PLURAL:$1|tasint|tisinin}} aya',
);
'specialpages-group-media' => 'Raporê medya u bar-kerdey',
'specialpages-group-users' => 'Karber u heqi',
'specialpages-group-highuse' => 'Pelê jêdêr gurenaey',
-'specialpages-group-pages' => 'Lista pelun',
+'specialpages-group-pages' => 'Listê pelun',
'specialpages-group-pagetools' => 'Hacetê pele',
'specialpages-group-wiki' => "Daê ''Wiki''y u haceti",
'specialpages-group-redirects' => 'Newe-vırastena pelunê xususiyun',
'nov' => '11',
'dec' => '12',
+'monday-at' => '월요일 $1',
+'tuesday-at' => '화요일 $1',
+'wednesday-at' => '수요일 $1',
+'thursday-at' => '목요일 $1',
+'friday-at' => '금요일 $1',
+'saturday-at' => '토요일 $1',
+'sunday-at' => '일요일 $1',
+'today-at' => '$1',
+'yesterday-at' => '어제 $1',
+
# Categories related messages
'pagecategories' => '{{PLURAL:$1|분류}}',
'category_header' => '"$1" 분류에 속하는 문서',
# Image rotation
'rotate-comment' => '그림을 시계 방향으로 $1{{PLURAL:$1|도}}로 회전함',
+# Unknown messages
+'hours-ago' => '$1{{PLURAL:$1|시간}} 전',
+'minutes-ago' => '$1{{PLURAL:$1|분}} 전',
+'seconds-ago' => '$1{{PLURAL:$1|초}} 전',
);
'userlogin-yourpassword-ph' => 'Donn Ding Paßwood enjävve',
'yourpasswordagain' => 'Noch ens dat Passwood',
'remembermypassword' => 'Op Duur aanmelde (hält {{PLURAL:$1|för eine Daach|bes op $1 Dääsch|bloß för hück}})',
+'userlogin-remembermypassword' => 'Op Duur enlogge',
+'userlogin-signwithsecure' => 'Verschlößeld enlogge',
'securelogin-stick-https' => 'Noh em Enlogge övver HTTPS verbonge blieve.',
'yourdomainname' => 'Ding Domain',
'password-change-forbidden' => 'Do kanns en heh däm Wiki kein Paßwööter ändere.',
'userlogout' => 'Ußlogge',
'notloggedin' => 'Nit enjelogg',
'userlogin-noaccount' => 'Do häß noch keine Zohjang?',
+'userlogin-joinproject' => 'Aanmälde zom Metmaache!',
'nologin' => "Wann De Dich noch nit aanjemeldt häs, dann dun Dich '''$1'''.",
'nologinlink' => 'neu aanmelde',
'createaccount' => 'Aanmelde als ene neue Metmaacher',
'passwordreset-text' => 'Donn dat Fommulaa heh ußfölle, öm e neu Paßwoot faßzelääje.',
'passwordreset-legend' => 'Et Paßwoot zeröck säze',
'passwordreset-disabled' => 'Et Paßwoot zeröck ze säze es heh em Wiki afjeschalldt.',
+'passwordreset-emaildisabled' => 'Heh dat Wiki määt nix met <i lang="en">e-mail</i>!',
'passwordreset-pretext' => '{{PLURAL:$1||Jiff ein vun dä Saache heh dronger enn|}}',
'passwordreset-username' => 'Metmaacher Name:',
'passwordreset-domain' => 'Domähn:',
Eijmohl-Paßwoot: $2',
'passwordreset-emailsent' => 'En <i lang="en">e-mail</i> met Aanjaabe zom neue Paßwoot för der Zohjang heh es verscheck.',
'passwordreset-emailsent-capture' => 'En <i lang="en">e-mail</i> met Aanjaabe zom neue Paßwoot för der Zohjang heh es verscheck woode. Heh dronger kanns De se lässe.',
-'passwordreset-emailerror-capture' => 'En <i lang="en">e-mail</i> met Aanjaabe zom neue Paßwoot för der Zohjang heh sullt verscheck wääde, ävver dat Verschecke hät nit jeflup: $1',
+'passwordreset-emailerror-capture' => 'En <i lang="en">e-mail</i> met Aanjaabe zom neue Paßwoot för der Zohjang heh sullt verscheck wääde, ävver dat Verschecke aan {{GENDER:$2|dä|dat|dä Metmaacher|de|dat}} $2 hät nit jeflup: $1',
# Special:ChangeEmail
'changeemail' => 'Donn Ding Address för de <i lang="en">e-mail</i> ändere',
'version-parser-function-hooks' => 'Parserfunktione',
'version-hook-name' => 'De Schnettstelle ier Name',
'version-hook-subscribedby' => 'Opjeroofe vun',
-'version-version' => '(Version $1)',
+'version-version' => '(Väsjohn $1)',
'version-license' => 'Lėzänz',
'version-poweredby-credits' => "Dat Wiki heh löp met '''[//www.mediawiki.org/ MediaWiki]''', copyright © 2001–$1 $2.",
'version-poweredby-others' => 'sönß wää',
# External image whitelist
'external_image_whitelist' => '# Donn aan dä Reih heh nix ändere<pre>
-# Onge künne Brochstöck fun regular expressions aanjejovve wäde,
+# Onge künne Brochstöke fun rejolähre Ußdrök aanjejovve wäde,
# alsu dä Deil zwesche / und /
# Noh em Verjliische met däm URL vun ene Datei fun ußerhallef:
# Treffer: De Datei weed jezeich odder enjebonge.
'viewsource' => 'Veddi a fonte',
'protectedpagetext' => "'Sta paggina a l'è stæta protezûa pe impedîghe a modiffica.",
'viewsourcetext' => "O l'è poscibbile vedde e copiâ o còddice sorgente de 'sta paggina:",
+'customjsprotected' => "No ti gh'æ i permessi pe cangiâ sta pagina de JavaScript percose a contegne e impostaçioin personæ de 'n atro utente",
'ns-specialprotected' => 'No se pœu modificâ e paggine speciali',
+'titleprotected' => "A creaçion de 'na paggina con sto tittolo a l'è stæta bloccâ da [[User:$1|$1]].
+A raxon a l'è: ''$2''.",
+'exception-nologin' => "No t'ê introu",
+'exception-nologin-text' => "Pe sta paggina ò sta açion ti gh'æ da effettuâ l'accesso inte sta wiki.",
# Virus scanner
'virus-scanfailed' => 'scansion fallia (codice $1)',
'yourpasswordagain' => 'Riscrivi a pòula segrétta:',
'remembermypassword' => 'Aregòrda a mæ login in sto navegatô (pe in mascimo de $1 {{PLURAL:$1|giórno|giórni}})',
'yourdomainname' => 'Indirisso do scito:',
+'password-change-forbidden' => 'No ti peu cangiâ poula segretta in questa wiki.',
'login' => 'Intra',
'nav-login-createaccount' => 'Intra / Registrate',
'loginprompt' => "Pe fâ l'accesso inte {{SITENAME}} ti g'hæ da abilitâ i cookie.",
Se conseggia de fâ l'accesso quanto primma e cangiâ a paròlla d'ordine immediatamente.
Se no ti ê stæto ti a fâ 'sta domanda, oppûre se ti t'hæ ritrovòu a têu paròlla d'ordine e no ti vêu cangiâla ciû, ti pêu ignorâ 'sto messaggio e andâ avanti deuviando a vegia paròlla d'ordine.",
'noemail' => 'No gh\'è nisciûn indirisso e-mail registròu pe l\'ûtente "$1".',
+'noemailcreate' => 'Ti devi dâ un addresso e-mail vallido.',
'passwordsent' => "Ûnn-a nêuva paròlla d'ordine a l'è stæta inviâa a l'indirisso e-mail registròu pe l'ûtente \"\$1\".
Pe piaxei, fa 'n accesso appenn-a ti a ghe reçeivi.",
'blocked-mailpassword' => "O teu indirisso IP o l'è affirmoö, e pe sta razon o non se peu usâ a funscion de remandâ a pòula segretta.",
'eauthentsent' => "'N messaggio e-mail de confermassion o l'è stæto inviòu a l'indirisso indicòu.
Pe abilitâ l'invîo de messaggi e-mail pe quest'accesso, o se deive seguî l'istrûssioîn indicæ, coscì ti confermi che ti t'è o legittimo propietâjo de l'indirisso.",
+'mailerror' => "Errô inte l'invio do messaggio: $1",
'acct_creation_throttle_hit' => "Ne dispiâxe, ma t'hæ zà creòu $1 accesci. No ti pêu creâne ciû!",
'emailauthenticated' => "O teu indirisso de posta elettronica o l'è stæto autenticou o $1.",
'emailconfirmlink' => 'Conferma o teu indirisso de posta elettronega',
'accountcreated' => 'Graçie pe esëte registroö!!!',
'accountcreatedtext' => "Utente $1, ti te guägno l'açeiso!",
+'createaccount-title' => "Creaçion de 'n conto pe {{SITENAME}}",
+'usernamehasherror' => 'O nomme utente o no poeu contegnî di caratteri hash',
+'login-abort-generic' => "O to accesso o no l'ha avuo successo - Abortio",
'loginlanguagelabel' => 'Lengoa: $1',
# Change password dialog
-'resetpass' => 'Reverti a pòula segretta',
-'resetpass_header' => 'Reverti a pòula segretta',
+'resetpass' => 'Cangia a pòula segretta',
+'resetpass_announce' => "T'ê introu co in codiçe temporanio de l'e-mail.Pe completâ l'accesso ti devi çerne 'na neuva poula segretta chì:",
+'resetpass_header' => 'Cangia a pòula segretta do conto',
+'oldpassword' => 'Vegia poula segretta',
+'newpassword' => 'Neuva poula segretta',
'retypenew' => "Ripette a nêuva paròlla d'ordine:",
+'resetpass_submit' => 'Çerni a poula segretta e intra',
'resetpass_forbidden' => "No l'é poscìbile cangiâ e paròlle segrétte",
# Edit page toolbar
'tog-hidepatrolled' => 'Siamţhat venhim tihdanglam thar zingah tilang suh',
'tog-newpageshidepatrolled' => 'Phêk venhim phêk thar tlarah tilang suh',
'tog-extendwatchlist' => 'A thar chauh ni lo, tihdanglamna zawng zawng tilang tùrin ralvèn kapparh rawh',
-'tog-usenewrc' => 'Tihdanglam thar belhchhan hmang rawh (JavaScript a ngai)',
+'tog-usenewrc' => 'Tihdanglam tharte leh ralvente a phêk azir zëlin tlar rawh (JavaScript a ngai)',
'tog-numberheadings' => 'A thupuite amahin nambar inpêktir rawh',
-'tog-showtoolbar' => 'Siamţhatna hmanraw-liang tilang rawh (JavaScript a ngai)',
-'tog-editondblclick' => 'Hmehphìrin phêk siamţha rawh (JavaScript a ngai)',
-'tog-editsection' => 'Hlawm hrang siamţhatna [siamţhatna] zawmna hmangin awmtir rawh',
+'tog-showtoolbar' => 'Siamṭhatna hmanraw-liang tilang rawh (JavaScript a ngai)',
+'tog-editondblclick' => 'Hmehphìrin phêk siamṭha rawh (JavaScript a ngai)',
+'tog-editsection' => 'Hlawm hrang siamṭhatna [siamṭhatna] zawmna hmangin awmtir rawh',
'tog-editsectiononrightclick' => 'Hlawm thupui ding-hmeh hmangin hlawm siamţhat theihna awmtir rawh (JavaScript a ngai)',
'tog-showtoc' => 'A chhunga thu awm te tilang rawh (thupui 3 aia tam phêk tan)',
'tog-rememberpassword' => 'He ka rangpuifannaah hian min hre reng rawh (a rei berah ni $1 {{PLURAL:$1}})',
'friday' => 'Zirtawpni',
'saturday' => 'Inrinni',
'sun' => 'Ptn',
-'mon' => 'Thţ',
+'mon' => 'Thṭ',
'tue' => 'Thl',
'wed' => 'Nil',
'thu' => 'Nng',
'jan' => 'Pkt',
'feb' => 'Rtk',
'mar' => 'Vau',
-'apr' => 'Ţau',
-'may' => 'Ţmr',
+'apr' => 'Ṭau',
+'may' => 'Ṭmr',
'jun' => 'Nkr',
'jul' => 'Vhz',
'aug' => 'Tţn',
# All link text and link target definitions of links into project namespace that get used by other message strings, with the exception of user group pages (see grouppage) and the disambiguation template definition (see disambiguations).
'aboutsite' => 'Tantang {{SITENAME}}',
'aboutpage' => 'Project:Tantang',
-'copyright' => 'Kandungan tasadio dalam $1',
+'copyright' => 'Isi tasadio dalam $1',
'copyrightpage' => '{{ns:project}}:Hak cipta',
'currentevents' => 'Kajadian kini ko',
'currentevents-url' => 'Project:Kajadian kini ko',
'policy-url' => 'Project:Kabijakan',
'portal' => 'Portal komunitas',
'portal-url' => 'Project:Portal komunitas',
-'privacy' => 'Kecipehan privasi',
-'privacypage' => 'Project:Kecipehan privasi',
+'privacy' => 'Kacipehan privasi',
+'privacypage' => 'Project:Kacipehan privasi',
'badaccess' => 'Kasalahan hak akses',
'badaccess-group0' => 'Sanak indak diizinkan untuak malakuan tindakan ko.',
'badaccess-groups' => 'Tindakan nan Sanak nio babateh untuak pangguno dalam {{PLURAL:$2|kalompok}}: $1.',
'versionrequired' => 'Dibutuahan MediaWiki versi $1',
-'versionrequiredtext' => 'MediaWiki versi $1 dibutuahan untuak manggunoan laman ko. Lihek [[Special:Version|versi laman]]',
+'versionrequiredtext' => 'MediaWiki versi $1 dibutuahan untuak manggunoan laman ko. Caliak [[Special:Version|versi laman]]',
'ok' => 'OK',
'pagetitle' => '$1 - {{SITENAME}} bahaso Minang',
'editsectionhint' => 'Suntiang bagian: $1',
'toc' => 'Dafta isi',
'showtoc' => 'tampilkan',
-'hidetoc' => 'suruakkan',
+'hidetoc' => 'suruakan',
'collapsible-collapse' => 'Ketekan',
'collapsible-expand' => 'Kambangan',
'thisisdeleted' => 'Caliak atau kambalian $1?',
'userrights-groupsmember' => 'Anggota dari:',
'userrights-groupsmember-auto' => 'Anggota implisit dari:',
'userrights-groups-help' => 'Sanak dapek mangubah kalompok pangguno ko:
-* Kotak jo tando cek marupoan kalompok pangguno tasabuik
-* Kotak tanpa tando cek bararti pangguno ko bukan anggota kalompok tasabuik
-* Tando * manandoi Sanak indak dapek mambatalan kalompok tasabuik bilo Sanak alah manambahannyo, atau sabaliaknyo.',
+* Kotak jo tando centang marupoan kalompok pangguno tasabuik
+* Kotak indak ado tando centang bararti pangguno ko bukan anggota kalompok tasabuik
+* Tando * manandoan Sanak indak dapek mambatalan kalompok tasabuik bilo Sanak alah manambahannyo, ataupun sabaliaknyo.',
'userrights-reason' => 'Alasan:',
'userrights-no-interwiki' => 'Sanak indak bahak untuak mangubah hak pangguno di wiki lain.',
'userrights-nodatabase' => 'Basis data $1 indak ado atau bukan disiko.',
# What links here
'whatlinkshere' => 'Pautan baliak',
-'whatlinkshere-title' => 'Laman yang bakaik ka "$1"',
+'whatlinkshere-title' => 'Laman nan takaik ka "$1"',
'whatlinkshere-page' => 'Laman:',
'linkshere' => "Laman-laman ko bakaik ka '''[[:$1]]''':",
'nolinkshere' => "Indak ado laman nan punyo tautan ka '''[[:$1]]'''.",
'nov' => 'ное',
'dec' => 'дек',
+'monday-at' => 'понеделникот во $1',
+'tuesday-at' => 'вторникот во $1',
+'wednesday-at' => 'средата во $1',
+'thursday-at' => 'четвртокот во $1',
+'friday-at' => 'петокот во $1',
+'saturday-at' => 'саботата во $1',
+'sunday-at' => 'неделата во $1',
+'today-at' => '$1',
+'yesterday-at' => 'вчера во $1',
+
# Categories related messages
'pagecategories' => '{{PLURAL:$1|Категорија|Категории}}',
'category_header' => 'Статии во категоријата „$1“',
'hidden-category-category' => 'Скриени категории',
'category-subcat-count' => '{{PLURAL:$2|Оваа категорија ја содржи само следнава поткатегорија.|Оваа категорија {{PLURAL:$1|ја содржи следнава поткатегорија|ги содржи следниве $1 поткатегории}} од вкупно $2.}}',
'category-subcat-count-limited' => 'Оваа категорија {{PLURAL:$1|ја содржи следнава поткатегорија|ги содржи следниве $1 поткатегории}}.',
-'category-article-count' => '{{PLURAL:$2|Ð\9aаÑ\82егоÑ\80иÑ\98аÑ\82а Ñ\98а Ñ\81одÑ\80жи Ñ\81амо Ñ\81леднава Ñ\81Ñ\82Ñ\80аниÑ\86а.|Ð\9aаÑ\82егоÑ\80иÑ\98аÑ\82а {{PLURAL:$1|Ñ\98а Ñ\81одÑ\80жи Ñ\81леднава Ñ\81Ñ\82Ñ\80аниÑ\86а|ги Ñ\81одÑ\80жи следниве $1 страници}} од вкупно $2.}}',
+'category-article-count' => '{{PLURAL:$2|Ð\9eваа каÑ\82егоÑ\80иÑ\98а Ñ\98а Ñ\81одÑ\80жи Ñ\81амо Ñ\81леднава Ñ\81Ñ\82Ñ\80аниÑ\86а:|Ð\92о каÑ\82егоÑ\80иÑ\98аÑ\82а Ñ\81е {{PLURAL:$1|Ñ\81одÑ\80жи Ñ\81леднава Ñ\81Ñ\82Ñ\80аниÑ\86а|Ñ\81одÑ\80жаÑ\82 следниве $1 страници}} од вкупно $2.}}',
'category-article-count-limited' => '{{PLURAL:$1|Следната страница е|Следните $1 страници се}} во оваа категорија.',
'category-file-count' => '{{PLURAL:$2|Оваа категорија ја содржи само следната податотека.|{{PLURAL:$1|Следната податотека е|Следните $1 податотеки се}} во оваа категорија, од вкупно $2.}}',
'category-file-count-limited' => '{{PLURAL:$1|Следнава податотека е|Следниве $1 податотеки се}} во оваа категорија.',
'viewhelppage' => 'Погледајте ја страницата за помош',
'categorypage' => 'Погледајте ја страницата за категоријата',
'viewtalkpage' => 'Видете го разговорот',
-'otherlanguages' => 'Ð\94руги јазици',
+'otherlanguages' => 'Ð\9dа други јазици',
'redirectedfrom' => '(Пренасочено од $1)',
'redirectpagesub' => 'Страница за пренасочување',
'lastmodifiedat' => 'Оваа страница последен пат е изменета на $1 во $2 ч.',
'protectedpagetext' => 'Оваа страница е заклучена за уредувања и други дејства.',
'viewsourcetext' => 'Можете да го погледнете и копирате кодот на оваа страница:',
'viewyourtext' => "Можете да го погледнете и копирате кодот на '''вашите уредувања''' на оваа страница:",
-'protectedinterface' => 'Оваа страница содржи текст од посредникот на софтверот на ова вики и е превентивно заштитена поради можна злоупотреба.
+'protectedinterface' => 'Оваа страница содржи текст од посредникот на програмот на ова вики и е превентивно заштитена поради можна злоупотреба.
За да додавате или менувате преводи на сите викија, појдете на [//translatewiki.net/wiki/Main_Page?uselang=mk translatewiki.net] - проектот за локализација на МедијаВики.',
-'editinginterface' => "'''Ð\9fÑ\80едÑ\83пÑ\80едÑ\83ваÑ\9aе:''' УÑ\80едÑ\83ваÑ\82е Ñ\81Ñ\82Ñ\80аниÑ\86а коÑ\98а е дел од коÑ\80иÑ\81ниÑ\87киоÑ\82 поÑ\81Ñ\80едник на Ð\9cедиÑ\98аÐ\92ики Ñ\81оÑ\84Ñ\82веÑ\80оÑ\82.
+'editinginterface' => "'''Ð\9fÑ\80едÑ\83пÑ\80едÑ\83ваÑ\9aе:''' УÑ\80едÑ\83ваÑ\82е Ñ\81Ñ\82Ñ\80аниÑ\86а коÑ\98а е дел од коÑ\80иÑ\81ниÑ\87киоÑ\82 поÑ\81Ñ\80едник на пÑ\80огÑ\80амоÑ\82 Ð\9cедиÑ\98аÐ\92ики.
Промените на оваа страница ќе предизвикаат промени во корисничкиот посредник кај другите корисници на ова вики.
За да додадете или измените превод на сите викија, појдете на [//translatewiki.net/wiki/Main_Page?setlang=mk translatewiki.net] - проектот за локализација на МедијаВики.",
'sqlhidden' => '(Барањето до SQL е скриено)',
'newuserlogpagetext' => 'Ова е дневник на регистрирани корисници.',
# User rights log
-'rightslog' => 'Ð\94невник на менÑ\83ваÑ\9aа на коÑ\80иÑ\81ниÑ\87ки права',
+'rightslog' => 'Ð\94невник на коÑ\80иÑ\81ниÑ\87киÑ\82е права',
'rightslogtext' => 'Ова е дневник на промени на кориснички права.',
# Associated actions - in the sentence "You do not have permission to X"
'uploaddisabledtext' => 'Подигањето на податотеки е оневозможено.',
'php-uploaddisabledtext' => 'Подигањето на податотеки е оневозможено во PHP.
Проверете го нагодувањето file_uploads.',
-'uploadscripted' => 'Податотеката содржи HTML или скриптен код што може да биде погрешно протолкуван од прелистувач.',
+'uploadscripted' => 'Податотеката содржи HTML-код или сценарио што може погрешно да се протолкува во прелистувачот.',
'uploadvirus' => 'Оваа податотека содржи вирус! Повеќе подробности: $1',
'uploadjava' => 'Податотеката е од типот ZIP што содржи податотека со наставка .class за Java.
Подигањето на податотеки за Java не е дозволено, бидејќи со нив можат да се заобиколуваат безбедносните ограничувања.',
'statistics-users-active-desc' => 'Корисници кои имаат извршено некое дејство {{PLURAL:$1|претходниот ден|во претходните $1 дена}}',
'statistics-mostpopular' => 'Најпосетувани страници',
-'disambiguations' => 'Страници што водат до страници за појаснување',
+'disambiguations' => 'Страници што водат до појаснителни страници',
'disambiguationspage' => 'Template:Појаснување',
-'disambiguations-text' => "Следните страници имаат барем по една врска што води до '''страница за појаснување'''.
-Наместо тоа, може да имаат врска до посоодветната тема.<br />
-Една страница се смета за страница за појаснување ако го користи шаблонот што води од [[MediaWiki:Disambiguationspage]]",
+'disambiguations-text' => "Следните страници имаат барем по една врска што води до '''појаснителна страница'''.
+Наместо тоа, може да имаат врска до посоодветна страница.<br />
+Една страница се смета за појаснителна ако го користи шаблонот што води од [[MediaWiki:Disambiguationspage]]",
'pageswithprop' => 'Страници со својство',
'pageswithprop-legend' => 'Страници со својство',
'minutes' => '{{PLURAL:$1|$1 минута|$1 минути}}',
'hours' => '{{PLURAL:$1|$1 час|$1 часа}}',
'days' => '{{PLURAL:$1|$1 ден|$1 дена}}',
+'weeks' => '{{PLURAL:$1|$1 недела|$1 недели}}',
'months' => '{{PLURAL:$1|$1 месец|$1 месеци}}',
'years' => '{{PLURAL:$1|$1 година|$1 години}}',
'ago' => 'пред $1',
# New logging system
'logentry-delete-delete' => '$1 {{GENDER:$2|ја избриша}} страницата $3',
-'logentry-delete-restore' => '$1 {{GENDER:$2|ја врати}} страницата $3',
+'logentry-delete-restore' => '$1 {{GENDER:$2|Ñ\98а повÑ\80аÑ\82и}} Ñ\81Ñ\82Ñ\80аниÑ\86аÑ\82а $3',
'logentry-delete-event' => '$1 {{GENDER:$2|ја измени}} видливоста на {{PLURAL:$5|настан во дневникот|$5 настани во дневникот}} на $3: $4',
'logentry-delete-revision' => '$1 {{GENDER:$2|ја измени}} видливоста на {{PLURAL:$5|ревизија|$5 ревизии}} на страницата $3: $4',
'logentry-delete-event-legacy' => '$1 {{GENDER:$2|ја измени}} видливоста на настаните во дневникот на $3',
# Image rotation
'rotate-comment' => 'Сликата е завртена за $1 {{PLURAL:$1|степен|степени}} вдесно',
+# Unknown messages
+'hours-ago' => 'пред $1 {{PLURAL:$1|час|часа}}',
+'minutes-ago' => 'пред $1 {{PLURAL:$1|минута|минути}}',
+'seconds-ago' => 'пред $1 {{PLURAL:$1|секунда|секунди}}',
);
'nov' => 'നവം.',
'dec' => 'ഡിസം.',
+'monday-at' => 'തിങ്കളാഴ്ച്ച $1-നു്',
+'tuesday-at' => 'ചൊവ്വാഴ്ച്ച $1-നു്',
+'wednesday-at' => 'ബുധനാഴ്ച്ച $1-നു്',
+'thursday-at' => 'വ്യാഴാഴ്ച്ച $1-നു്',
+'friday-at' => 'വെള്ളിയാഴ്ച്ച $1-നു്',
+'saturday-at' => 'ശനിയാഴ്ച്ച $1-നു്',
+'sunday-at' => 'ഞായറാഴ്ച്ച $1-നു്',
+'today-at' => 'ഇന്ന് $1-നു്',
+'yesterday-at' => 'ഇന്നലെ $1-നു്',
+
# Categories related messages
'pagecategories' => '{{PLURAL:$1|വർഗ്ഗം|വർഗ്ഗങ്ങൾ}}',
'category_header' => '"$1" എന്ന വർഗ്ഗത്തിലെ താളുകൾ',
താത്കാലിക രഹസ്യവാക്ക്: $2',
'passwordreset-emailsent' => 'ഒരു രഹസ്യവാക്ക് പുനർസജ്ജീകരണ ഇമെയിൽ അയച്ചിട്ടുണ്ട്.',
'passwordreset-emailsent-capture' => 'രഹസ്യവാക്ക് പുനർസജ്ജീകരണ ഇമെയിൽ അയച്ചിട്ടുണ്ട്, അത് താഴെക്കൊടുക്കുന്നു.',
-'passwordreset-emailerror-capture' => 'താഴàµ\86à´\95àµ\8dà´\95àµ\8aà´\9fàµ\81à´¤àµ\8dതിരിà´\95àµ\8dà´\95àµ\81à´¨àµ\8dà´¨, രഹസàµ\8dയവാà´\95àµ\8dà´\95àµ\8d à´ªàµ\81നർസà´\9càµ\8dà´\9càµ\80à´\95à´°à´£ à´\87à´®àµ\86യിൽ à´¸àµ\83à´·àµ\8dà´\9fà´¿à´\95àµ\8dà´\95ാനായàµ\86à´\99àµ\8dà´\95à´¿à´²àµ\81à´\82, à´\89പയàµ\8bà´\95àµ\8dതാവിനàµ\8d à´\85യയàµ\8dà´\95àµ\8dà´\95ാൻ à´\95à´´à´¿à´\9eàµ\8dà´\9eà´¿à´²àµ\8dà´²: $1',
+'passwordreset-emailerror-capture' => 'താഴàµ\86à´\95àµ\8dà´\95àµ\8aà´\9fàµ\81à´¤àµ\8dതിരിà´\95àµ\8dà´\95àµ\81à´¨àµ\8dà´¨, രഹസàµ\8dയവാà´\95àµ\8dà´\95àµ\8d à´ªàµ\81നർസà´\9càµ\8dà´\9càµ\80à´\95à´°à´£ à´\87à´®àµ\86യിൽ à´¸àµ\83à´·àµ\8dà´\9fà´¿à´\95àµ\8dà´\95ാനായàµ\86à´\99àµ\8dà´\95à´¿à´²àµ\81à´\82, à´\85à´¤àµ\8d {{GENDER:$2|à´\89പയàµ\8bà´\95àµ\8dതാവിനàµ\8d}} à´\85യയàµ\8dà´\95àµ\8dà´\95àµ\81à´¨àµ\8dനതàµ\8d പരാà´\9cയപàµ\8dà´ªàµ\86à´\9fàµ\8dà´\9fàµ\81: $1',
# Special:ChangeEmail
'changeemail' => 'ഇമെയിൽ വിലാസത്തിൽ മാറ്റംവരുത്തുക',
'powersearch-togglenone' => 'ഒന്നുംവേണ്ട',
'search-external' => 'ബാഹ്യ അന്വേഷണം',
'searchdisabled' => '{{SITENAME}} സംരംഭത്തിൽ തിരച്ചിൽ ദുർബലപ്പെടുത്തിയിരിക്കുന്നു. താങ്കൾക്ക് ഗൂഗിൾ ഉപയോഗിച്ച് തത്കാലം തിരച്ചിൽ നടത്താവുന്നതാണ്. പക്ഷെ ഗൂഗിളിൽ {{SITENAME}} സംരംഭത്തിന്റെ സൂചിക കാലഹരണപ്പെട്ടതായിരിക്കാൻ സാദ്ധ്യതയുണ്ട്.',
+'search-error' => 'തിരയുന്നതിനിടെ ഒരു പിഴവുണ്ടായി: $1',
# Preferences page
'preferences' => 'ക്രമീകരണങ്ങൾ',
'proxyblocksuccess' => 'ചെയ്തു കഴിഞ്ഞു.',
'sorbsreason' => '{{SITENAME}} ഉപയോഗിക്കുന്ന DNSBL ൽ താങ്കളുടെ ഐ.പി. വിലാസം ഒരു ഓപ്പൺ പ്രോക്സിയായാണു രേഖപ്പെടുത്തിട്ടുള്ളത്.',
'sorbs_create_account_reason' => '{{SITENAME}} ഉപയോഗിക്കുന്ന DNSBL ൽ താങ്കളുടെ ഐ.പി. വിലാസം ഒരു ഓപ്പൺ പ്രോക്സിയായാണു രേഖപ്പെടുത്തിട്ടുള്ളത്. താങ്കൾക്ക് അംഗത്വമെടുക്കാൻ സാദ്ധ്യമല്ല.',
+'xffblockreason' => 'എക്സ്-ഫോർവേഡഡ്-ഫോർ ഹെഡറിലെ ഒരു ഐ.പി. വിലാസം, താങ്കളുടേതോ താങ്കൾ ഉപയോഗിക്കുന്ന പ്രോക്സി സെർവറിലേതോ ആകാം, തടയപ്പെട്ടിരിക്കുന്നതാണ്. തടയലിന്റെ കാരണം: $1',
'cant-block-while-blocked' => 'താങ്കൾ തടയപ്പെട്ടിരിക്കുമ്പോൾ മറ്റുപയോക്താക്കളെ തടയാൻ താങ്കൾക്ക് സാധിക്കില്ല.',
'cant-see-hidden-user' => 'താങ്കൾ തടയാൻ ശ്രമിക്കുന്ന ഉപയോക്താവ് മുമ്പേ തടയപ്പെടുകയും മറയ്ക്കപ്പെടുകയും ചെയ്യപ്പെട്ടതാണ്. താങ്കൾക്ക് ഉപയോക്താവിനെ മറയ്ക്കാനുള്ള അവകാശം ഇല്ലെങ്കിൽ, ഉപയോക്താവിനെതിരെ ഉള്ള തടയൽ കാണാനോ തിരുത്താനോ കഴിയുന്നതല്ല.',
'ipbblocked' => 'മറ്റുള്ളവരെ തടയാനോ അവരുടെ തടയൽ നീക്കാനോ താങ്കൾക്ക് കഴിയില്ല. കാരണം താങ്കൾ തന്നെ തടയപ്പെട്ടിരിക്കുകയാണ്',
'minutes' => '{{PLURAL:$1|ഒരു മിനിറ്റ്|$1 മിനിറ്റ്}}',
'hours' => '{{PLURAL:$1|ഒരു മണിക്കൂർ|$1 മണിക്കൂർ}}',
'days' => '{{PLURAL:$1|ഒരു ദിവസം|$1 ദിവസം}}',
+'weeks' => '{{PLURAL:$1|ഒരാഴ്ച്ച|$1 ആഴ്ച്ച}}',
'months' => '{{PLURAL:$1|ഒരു മാസം|$1 മാസം}}',
'years' => '{{PLURAL:$1|ഒരു വർഷം|$1 വർഷം}}',
'ago' => '$1 മുമ്പ്',
# Image rotation
'rotate-comment' => 'ചിത്രം പ്രദക്ഷിണദിശയിൽ {{PLURAL:$1|ഒരു ഡിഗ്രി|$1 ഡിഗ്രി}} തിരിച്ചു',
+# Unknown messages
+'hours-ago' => '{{PLURAL:$1|ഒരു മണിക്കൂർ|$1 മണിക്കൂർ}} മുൻപ്',
+'minutes-ago' => '{{PLURAL:$1|ഒരു മിനിറ്റ്|$1 മിനിറ്റ്}} മുൻപ്',
+'seconds-ago' => '{{PLURAL:$1|ഒരു സെക്കന്റ്|$1 സെക്കന്റ്}} മുൻപ്',
);
Kata laluan sementara: $2',
'passwordreset-emailsent' => 'E-mel set semula kata laluan telah dihantar.',
'passwordreset-emailsent-capture' => 'E-mel set semula kata laluan telah dihantar, seperti yang dipaparkan di bawah.',
-'passwordreset-emailerror-capture' => 'E-mel set semula kata laluan telah dihasilkan, seperti yang dipaparkan di bawah, tetapi tidak berjaya dihantar kepada pengguna: $1',
+'passwordreset-emailerror-capture' => 'E-mel set semula kata laluan telah dihasilkan, seperti yang dipaparkan di bawah, tetapi tidak berjaya dihantar kepada {{GENDER:$2|pengguna}} berkenaan: $1',
# Special:ChangeEmail
'changeemail' => 'Tukar alamat e-mel',
Midlertidig passord: $2',
'passwordreset-emailsent' => 'En passordtilbakestillingslenke har blitt sendt per e-post.',
'passwordreset-emailsent-capture' => 'Passordtilbakestillingseposten vist under har blitt sendt ut.',
-'passwordreset-emailerror-capture' => 'En passordtilbakestillingsepost ble laget, men det lyktes ikke å sende denne til brukeren: $1',
+'passwordreset-emailerror-capture' => 'En passordtilbakestillingsepost ble laget, men det lyktes ikke å sende denne til {{GENDER:$2|brukeren}}: $1',
# Special:ChangeEmail
'changeemail' => 'Endre e-postadresse',
'underline-always' => 'Altied',
'underline-never' => 'Nooit',
-'underline-default' => 'Standardinstelling',
+'underline-default' => 'Standard in joew vormgeving of webkieker',
# Font style option in Special:Preferences
'editfont-style' => 'Lettertype veur de tekste t bewarkingsveld:',
'nov' => 'nov',
'dec' => 'des',
+'today-at' => '$1',
+
# Categories related messages
'pagecategories' => '{{PLURAL:$1|Kategorie|Kategorieën}}',
'category_header' => 'Artikels in kategorie $1',
'newwindow' => '(niej vienster)',
'cancel' => 'Aofbreken',
'moredotdotdot' => 'Meer...',
-'mypage' => 'Mien gebrukerszied',
+'morenotlisted' => 'Meer niet in de lieste...',
+'mypage' => 'Gebrukerszied',
'mytalk' => 'Mien overleg',
'anontalk' => 'Overlegzied veur dit IP-adres',
'navigation' => 'Navigasie',
'vector-action-protect' => 'Beveiligen',
'vector-action-undelete' => 'Weerummeplaotsen',
'vector-action-unprotect' => 'Beveiliging wiezigen',
-'vector-simplesearch-preference' => 'Verbeterde zeuksuggesties anzetten (allinnig mit Vector-vormgeving)',
+'vector-simplesearch-preference' => 'Vereenvoudigd zeuken anzetten (allinnig mit Vector-vormgeving)',
'vector-view-create' => 'Anmaken',
'vector-view-edit' => 'Bewarken',
'vector-view-history' => 'Geschiedenisse bekieken',
'namespaces' => 'Naamruumtes',
'variants' => 'Variaanten',
+'navigation-heading' => 'Navigasiemenu',
'errorpagetitle' => 'Foutmelding',
'returnto' => 'Weerumme naor $1.',
'tagline' => 'Van {{SITENAME}}',
'viewsource-title' => 'Bron bekieken van $1',
'actionthrottled' => 'Haandeling tegenehöllen',
'actionthrottledtext' => "As maotregel tegen t plaotsen van ongewunste verwiezingen, is t antal keren da'j disse haandeling in n korte tied uutvoeren kunnen beteund. Je hebben de limiet overschrejen. Probeer t over n antal minuten weer.",
-'protectedpagetext' => 'Disse zied is beveiligd um bewarkingen te veurkoemen.',
+'protectedpagetext' => 'Disse zied is beveiligd. Bewarken of aandere haandelingen bin niet meugelik.',
'viewsourcetext' => 'Je kunnen de brontekste van disse zied bewarken en bekieken:',
'viewyourtext' => "Je kunnen '''joew bewarkingen''' an de brontekste van disse zied bekieken en kopiëren:",
'protectedinterface' => "Op disse zied steet tekste die gebruukt wörden veur systeemteksten van disse wiki. Allinnig beheerders kunnen disse zied bewarken.
Je kunnen {{SITENAME}} noen anoniem gebruken of je eigen <span class='plainlinks'>[$1 opniej anmelden]</span> onder disse of n aandere gebrukersnaam.
t Kan ween dat der wat ziejen bin die weeregeven wörden asof je an-emeld bin totda'j t tussengeheugen van joew webkieker leegmaken.",
+'welcomeuser' => 'Welkom, $1!',
'yourname' => 'Gebrukersnaam',
+'userlogin-yourname' => 'Gebrukersnaam',
+'userlogin-yourname-ph' => 'Geef joew gebrukersnaam op',
'yourpassword' => 'Wachtwoord',
+'userlogin-yourpassword' => 'Wachtwoord',
+'userlogin-yourpassword-ph' => 'Geef joew wachtwoord op',
'yourpasswordagain' => 'Opniej invoeren',
'remembermypassword' => 'Vanzelf anmelden (hooguut $1 {{PLURAL:$1|dag|dagen}})',
+'userlogin-remembermypassword' => 'Vanzelf anmelden',
'securelogin-stick-https' => "Verbunnen blieven via HTTPS naoda'j an-emeld bin",
'yourdomainname' => 'Joew domein',
'password-change-forbidden' => 'Je kunnen joew wachtwoord niet wiezigen op disse wiki.',
'logout' => 'Aofmelden',
'userlogout' => 'Aofmelden',
'notloggedin' => 'Niet an-emeld',
+'userlogin-noaccount' => "He'j nog gien gebrukersnaam?",
+'userlogin-joinproject' => 'Over {{SITENAME}}',
'nologin' => "He'j nog gien gebrukersnaam? '''$1'''.",
'nologinlink' => 'Maak n gebrukersprofiel an',
'createaccount' => 'Niej gebrukersprofiel anmaken',
'gotaccount' => "Stao'j al in-eschreven? '''$1'''.",
'gotaccountlink' => 'Anmelden',
'userlogin-resetlink' => "Bi'j de anmeldgegevens kwiet?",
-'createaccountmail' => 'per netpost',
+'createaccountmail' => 'Gebruuk n tiejelik wachtwoord dat joe netzelde is en stuur t naor t netpostadres dat hieronder steet',
'createaccountreason' => 'Reden:',
'badretype' => "De wachtwoorden die'j in-etikt hebben bin niet liek alleens.",
'userexists' => 'Disse gebrukersnaam is al gebruuk.
'editwarning-warning' => "A'j disse zied aofsluten dan kan t ween dat der wieziging die'j emaakt hebben kwiet raken.
A'j an-emeld bin, dan ku'j disse waorschuwing uutzetten in t tabblad \"Bewarken\" in joew veurkeuren.",
+# Content models
+'content-model-wikitext' => 'wikitekste',
+'content-model-text' => 'tekste zonder opmaak',
+'content-model-javascript' => 'JavaScript',
+'content-model-css' => 'CSS',
+
# Parser/template warnings
'expensive-parserfunction-warning' => 'Waorschuwing: disse zied gebruukt te veule kostbaore parserfunksies.
'search-interwiki-default' => '$1 resultaoten:',
'search-interwiki-more' => '(meer)',
'search-relatedarticle' => 'Verwaant',
-'mwsuggest-disable' => 'Anbevelingen via AJAX uutschakelen',
+'mwsuggest-disable' => 'Zeuksuggesties uutzetten',
'searcheverything-enable' => 'In alle naamruumten zeuken',
'searchrelated' => 'verwaant',
'searchall' => 'alles',
'prefs-emailconfirm-label' => 'Netpostbevestiging:',
'prefs-textboxsize' => 'Aofmetingen bewarkingsscharm',
'youremail' => 'Netpostadres (niet verplicht) *',
-'username' => 'Gebrukersnaam:',
-'uid' => 'Gebrukersnummer:',
+'username' => '{{GENDER:$1|Gebrukersnaam}}:',
+'uid' => '{{GENDER:$1|Gebrukersnummer}}:',
'prefs-memberingroups' => 'Lid van {{PLURAL:$1|groep|groepen}}:',
'prefs-registration' => 'Registrasiedaotum:',
'yourrealname' => 'Echte naam (niet verplicht)',
Feitelik mutten ze rechtstreeks verwiezen naor t juuste onderwarp.<br />
Ziejen wörden ezien as n deurverwieszied, as de mal gebruukt wörden die vermeld steet op [[MediaWiki:Disambiguationspage]].",
+'pageswithprop-submit' => 'Zeuk',
+
'doubleredirects' => 'Dubbele deurverwiezingen',
'doubleredirectstext' => 'Op disse lieste staon alle ziejen die deurverwiezen naor aandere deurverwiezingen.
Op elke regel steet de eerste en de tweede deurverwiezing, daorachter steet de doelzied van de tweede deurverwiezing.
'blanknamespace' => '(Heufdnaamruumte)',
# Contributions
-'contributions' => 'Biedragen van disse gebruker',
+'contributions' => '{{GENDER:$1|Biedragen van disse gebruker}}',
'contributions-title' => 'Biedragen van $1',
'mycontris' => 'Mien biedragen',
'contribsub2' => 'Veur $1 ($2)',
'pageinfo-magic-words' => '{{PLURAL:$1|Magies woord|Magiese woorden}} ($1)',
'pageinfo-hidden-categories' => 'Verbörgen {{PLURAL:$1|kategorie|kategorieën}} ($1)',
'pageinfo-templates' => '{{PLURAL:$1|Gebruukten mal|Gebruukten mallen}} ($1)',
+'pageinfo-toolboxlink' => 'Informasie over disse zied',
+'pageinfo-redirectsto' => 'Verwis deur naor',
+'pageinfo-redirectsto-info' => 'informasie',
+'pageinfo-contentpage' => 'Eteld as zied mit inhoud',
+'pageinfo-contentpage-yes' => 'Ja',
# Skin names
'skinname-cologneblue' => 'Keuls blauw',
'hours' => '{{PLURAL:$1|$1 ure|$1 uren}}',
'days' => '{{PLURAL:$1|$1 dag|$1 dagen}}',
'ago' => '$1 eleen',
+'just-now' => 'onderlest',
# Bad image list
'bad_image_list' => 'De opmaak is as volgt:
'htmlform-submit' => 'Opslaon',
'htmlform-reset' => 'Wiezigingen ongedaonmaken',
'htmlform-selectorother-other' => 'Aanders',
+'htmlform-no' => 'Nee',
+'htmlform-yes' => 'Ja',
# SQLite database support
'sqlite-has-fts' => 'Versie $1 mit ondersteuning veur "full-text" zeuken',
'nov' => 'nov',
'dec' => 'dec',
+'monday-at' => 'Maandag om $1',
+'tuesday-at' => 'Dinsdag om $1',
+'wednesday-at' => 'Woensdag om $1',
+'thursday-at' => 'Donderdag om $1',
+'friday-at' => 'Vrijdag om $1',
+'saturday-at' => 'Zaterdag om $1',
+'sunday-at' => 'Zondag om $1',
+'today-at' => '$1',
+'yesterday-at' => 'Gisteren om $1',
+
# Categories related messages
'pagecategories' => '{{PLURAL:$1|Categorie|Categorieën}}',
'category_header' => 'Pagina’s in categorie "$1"',
# Image rotation
'rotate-comment' => 'Afbeelding gedraaid, $1 {{PLURAL:$1|graad|graden}} met de klok mee',
+# Unknown messages
+'hours-ago' => '$1 {{PLURAL:$1|uur}} geleden',
+'minutes-ago' => '$1 {{PLURAL:$1|minuut|minuten}} geleden',
+'seconds-ago' => '$1 {{PLURAL:$1|seconde|seconden}} geleden',
);
'duration-centuries' => '$1 {{PLURAL:$1|century|centuries}}',
'duration-millennia' => '$1 {{PLURAL:$1|millennium|millennia}}',
+# Unknown messages
+'hours-ago' => '$1 {{PLURAL:$1|ଘଣ୍ଟା}} ଆଗରୁ',
+'minutes-ago' => '$1 {{PLURAL:$1|ମିନିଟ|ମିନିଟ}} ଆଗରୁ',
+'seconds-ago' => '$1 {{PLURAL:$1|ସେକେଣ୍ଡ|ସେକେଣ୍ଡ}} ଆଗରୁ',
);
'tog-usenewrc' => 'ਹਾਲ ’ਚ ਹੋਏ ਬਦਲਾਵ ਅਤੇ ਧਿਆਨਸੂਚੀ ਵਿੱਚ ਪੰਨੇ ਮੁਤਾਬਕ ਬਦਲਾਵ ਦੇ ਗਰੁੱਪ ਬਣਾਓ (ਜਾਵਾਸਕ੍ਰਿਪਟ ਦੀ ਜਰੂਰਤ ਹੈ)',
'tog-numberheadings' => 'ਆਟੋ-ਨੰਬਰ ਹੈਡਿੰਗ',
'tog-showtoolbar' => 'ਸੋਧ ਟੂਲਬਾਰ ਵੇਖੋ (JavaScript ਚਾਹੀਦੀ ਹੈ)',
-'tog-editondblclick' => 'ਦà©\82ਹਰà©\87 à¨\95ਲਿੱà¨\95 â\80\99ਤà©\87 ਪੰਨà©\87 ਨà©\82à©° ਸੰਪਾਦਤ à¨\95ਰà©\8b (à¨\9cਾਵਾਸà¨\95à©\8dਰਿਪà¨\9f ਦà©\80 à¨\9cਰà©\82ਰਤ ਹੈ)',
-'tog-editsection' => '[ਸੰਪਾਦਨ] à¨\95à©\9cà©\80à¨\86à¨\82 ਦà©\81à¨\86ਰਾ à¨\85ਨà©\81à¨à¨¾à¨\97 ਸੰਪਾਦਨ ਸਮਰੱਥਾਵਾਨ à¨\95ਰà©\8b',
+'tog-editondblclick' => 'ਦà©\8b ਵਾਰ à¨\95ਲਿੱà¨\95 à¨\95ਰਨ ਨਾਲ ਸਫ਼à©\87 ਸà©\8bਧà©\8b (à¨\9cਾਵਾਸà¨\95à©\8dਰਿਪà¨\9f à¨\9aਾਹà©\80ਦà©\80 ਹੈ)',
+'tog-editsection' => '[ਸà©\8bਧ] ਲਿੰà¨\95 ਰਾਹà©\80à¨\82 à¨à¨¾à¨\97 ਸà©\8bਧ à¨\95ਰਨਾ à¨\9aਾਲà©\82',
'tog-editsectiononrightclick' => 'ਭਾਗ ਸਿਰਲੇਖਾਂ ਤੇ ਸੱਜੀ ਕਲਿੱਕ ਦੁਆਰਾ ਸੋਧ ਯੋਗ ਕਰੋ (ਜਾਵਾ ਸਕ੍ਰਿਪਟ ਲੋੜੀਂਦੀ ਹੈ)',
'tog-showtoc' => 'ਤਤਕਰਾ ਵੇਖਾਓ (3 ਤੋਂ ਵੱਧ ਸਿਰਲੇਖਾਂ ਵਾਲੇ ਪੰਨਿਆਂ ਲਈ)',
'tog-rememberpassword' => 'ਇਸ ਬਰਾਊਜ਼ਰ ਉੱਤੇ ਮੇਰਾ ਲਾਗਇਨ ਯਾਦ ਰੱਖੋ ($1 {{PLURAL:$1|ਦਿਨ|ਦਿਨਾਂ}} ਲਈ ਵੱਧ ਤੋਂ ਵੱਧ)',
'vector-action-unprotect' => 'ਸੁਰੱਖਿਆ ਬਦਲੋ',
'vector-simplesearch-preference' => 'ਸਧਾਰਨ ਖੋਜ ਸਲਾਹ ਪੱਟੀ ਯੋਗ ਕਰੋ (ਸਿਰਫ਼ ਵਿਕਟਰ ਸਕਿੰਨ ਵਿਚ)',
'vector-view-create' => 'ਬਣਾਓ',
-'vector-view-edit' => 'ਸੰਪਾਦਨ',
-'vector-view-history' => 'à¨\87ਤਿਹਾਸ ਵੇਖੋ',
+'vector-view-edit' => 'ਸà©\8bਧ',
+'vector-view-history' => 'à¨\85ਤà©\80ਤ ਵੇਖੋ',
'vector-view-view' => 'ਪੜ੍ਹੋ',
'vector-view-viewsource' => 'ਸਰੋਤ ਵੇਖੋ',
'actions' => 'ਕਾਰਵਾਈਆਂ',
'searchbutton' => 'ਖੋਜ',
'go' => 'ਜਾਓ',
'searcharticle' => 'ਜਾਓ',
-'history' => 'ਪੰਨà©\87 ਦਾ à¨\87ਤਿਹਾਸ',
-'history_short' => 'à¨\87ਤਿਹਾਸ',
+'history' => 'ਸਫ਼ਾ à¨\85ਤà©\80ਤ',
+'history_short' => 'à¨\85ਤà©\80ਤ',
'updatedmarker' => 'ਮੇਰੀ ਆਖਰੀ ਫੇਰੀ ਤੋਂ ਬਾਅਦ ਦੇ ਅੱਪਡੇਟ',
'printableversion' => 'ਛਪਣਯੋਗ ਵਰਜਨ',
'permalink' => 'ਪੱਕਾ ਲਿੰਕ',
'print' => 'ਛਾਪੋ',
'view' => 'ਵੇਖੋ',
-'edit' => 'ਸੰਪਾਦਨ',
+'edit' => 'ਸà©\8bਧ',
'create' => 'ਬਣਾਓ',
'editthispage' => 'ਇਹ ਸਫ਼ਾ ਸੋਧੋ',
'create-this-page' => 'ਇਹ ਸਫ਼ਾ ਬਣਾਓ',
'otherlanguages' => 'ਹੋਰ ਭਾਸ਼ਾਵਾਂ ਵਿੱਚ',
'redirectedfrom' => '($1 ਤੋਂ ਰੀਡਿਰੈਕਟ)',
'redirectpagesub' => 'ਰੀਡਿਰੈਕਟ ਸਫ਼ਾ',
-'lastmodifiedat' => 'à¨\87ਸ ਪੰਨਾ ਦਾ ਪਿੱà¨\9bਲਾ ਬਦਲਾà¨\85 $1 ਨà©\82à©° $2 ਵà¨\9cà©\87 ਹà©\8bà¨\87à¨\86 ਸà©\80।',
+'lastmodifiedat' => 'à¨\87ਹ ਸਫ਼à©\87 ਵਿੱà¨\9a à¨\86à¨\96ਰà©\80 ਸà©\8bਧ $1 ਨà©\82à©° $2 ਵà¨\9cà©\87 ਹà©\8bà¨\88।',
'viewcount' => 'ਇਹ ਸਫ਼ਾ {{PLURAL:$1|ਇੱਕ ਵਾਰ|$1 ਵਾਰ}} ਵੇਖਿਆ ਗਿਆ।',
'protectedpage' => 'ਸੁਰੱਖਿਅਤ ਪੇਜ',
'jumpto' => 'ਇਸ ’ਤੇ ਜਾਓ:',
'mainpage' => 'ਮੁੱਖ ਸਫ਼ਾ',
'mainpage-description' => 'ਮੁੱਖ ਸਫ਼ਾ',
'policy-url' => 'Project:ਨੀਤੀ',
-'portal' => 'ਸਮਾà¨\9c ਮà©\81ੱà¨\96 ਪੰਨਾ',
+'portal' => 'ਸਮਾà¨\9c ਸੱਥ',
'portal-url' => 'Project:ਸਮਾਜ ਸੱਥ',
'privacy' => 'ਪਰਾਈਵੇਸੀ ਨੀਤੀ',
'privacypage' => 'Project:ਪਰਾਈਵੇਸੀ ਨੀਤੀ',
'newpages-username' => 'ਯੂਜ਼ਰ-ਨਾਂ:',
'ancientpages' => 'ਸਭ ਤੋਂ ਪੁਰਾਣੇ ਪੇਜ',
'move' => 'ਸਥਾਨਾਂਤਰਨ',
-'movethispage' => 'à¨\87ਹ ਪà©\87à¨\9c ਭੇਜੋ',
+'movethispage' => 'à¨\87ਹ ਸਫ਼ਾ ਭੇਜੋ',
'unusedcategoriestext' => 'ਇਹ ਕੈਟੇਗਰੀ ਸਫ਼ੇ ਮੌਜੂਦ ਹਨ ਹਾਲਾਂਕਿ ਕਿਸੇ ਵੀ ਸਫ਼ੇ ਜਾਂ ਕੈਟੇਗਰੀ ਨੇ ਇਹਨਾਂ ਦੀ ਵਰਤੋਂ ਨਹੀਂ ਕੀਤੀ।',
'notargettitle' => 'ਟਾਰਗੇਟ ਨਹੀਂ',
'pager-newer-n' => '{{PLURAL:$1|1 ਨਵਾਂ|$1 ਨਵੇਂ}}',
# Watchlist
'watchlist' => 'ਨਿਗਰਾਨ-ਸੂਚੀ',
-'mywatchlist' => 'ਧਿà¨\86ਨਸੂਚੀ',
+'mywatchlist' => 'ਨਿà¨\97ਰਾਨ-ਸੂਚੀ',
'watchlistfor2' => '$1 $2 ਲਈ',
'nowatchlist' => 'ਤੁਹਾਡੀ ਨਿਗਰਾਨੀ-ਲਿਸਟ ਵਿਚ ਕੋਈ ਚੀਜ਼ ਨਹੀਂ ਹੈ।',
'watchlistanontext' => 'ਆਪਣੀ ਨਿਗਰਾਨੀ-ਲਿਸਟ ਵਿਚਲੀਆਂ ਚੀਜ਼ਾਂ ਵੇਖਣ ਜਾਂ ਸੋਧਣ ਲਈ ਮਿਹਰਬਾਨੀ ਕਰਕੇ $1।',
'wlnote' => "$3, $4 ਮੁਤਾਬਕ ਆਖ਼ਰੀ {{PLURAL:$2|ਘੰਟੇ|'''$2''' ਘੰਟਿਆਂ}} ਵਿਚ {{PLURAL:
$1|ਤਬਦੀਲੀ ਹੋਈ|'''$1''' ਤਬਦੀਲੀਆਂ ਹੋਈਆਂ}}, ਹੇਠਾਂ ਵੇਖੋ।",
'wlshowlast' => 'ਪਿੱਛਲੇ $1 ਘੰਟੇ $2 ਦਿਨ $3 ਵੇਖੋ',
-'watchlist-options' => 'ਧਿà¨\86ਨਸà©\82à¨\9aà©\80 ਵਿà¨\95ਲਪ',
+'watchlist-options' => 'ਨਿà¨\97ਰਾਨ-ਸà©\82à¨\9aà©\80 à¨\9aà©\8bਣਾà¨\82',
# Displayed when you click the "watch" button and it is in the process of watching
'watching' => 'ਨਿਗ੍ਹਾ (ਵਾਚ) ਰੱਖੀ ਜਾ ਰਹੀ ਹੈ...',
'powersearch-field' => 'Suche noch',
'powersearch-togglenone' => 'Kään',
-# Quickbar
-'qbsettings-none' => 'Kään',
-
# Preferences page
'preferences' => 'Optione',
'mypreferences' => 'Oistellunge',
# Special:ListGroupRights
'listgrouprights-members' => '(Midgliederlischd)',
-# E-mail user
+# Email user
'emailuser' => 'E-Mail on de Benutzer',
'emailsend' => 'Abschigge',
'file-info-size' => '$1 × $2 Pixels, Dateigreß: $3, MIME-Type: $4',
'file-nohires' => 'Ke hechere Ufflesung verfiechbar.',
'svg-long-desc' => 'SVG-Datei, Basisgreß $1 × $2 Pixels, Dateigreß: $3',
-'show-big-image' => 'Gsamte Ergebnis',
+'show-big-image' => 'Volli Uflesung',
# Special:NewFiles
'showhidebots' => '(Bots $1)',
'nov' => 'lis',
'dec' => 'gru',
+'monday-at' => 'poniedziałek, $1',
+'tuesday-at' => 'wtorek, $1',
+'wednesday-at' => 'środa, $1',
+'thursday-at' => 'czwartek, $1',
+'friday-at' => 'piątek, $1',
+'saturday-at' => 'sobota, $1',
+'sunday-at' => 'niedziela, $1',
+'today-at' => '$1',
+'yesterday-at' => 'wczoraj, $1',
+
# Categories related messages
'pagecategories' => '{{PLURAL:$1|Kategoria|Kategorie}}',
'category_header' => 'Strony w kategorii „$1”',
Jeśli jesteś anonimowym użytkownikiem i uważasz, że zamieszczone tu komentarze nie są skierowane do Ciebie, [[Special:UserLogin/signup|utwórz konto]] lub [[Special:UserLogin|zaloguj się]] – dzięki temu unikniesz w przyszłości podobnych nieporozumień.''",
'noarticletext' => 'Brak strony o tym tytule.
Możesz [[Special:Search/{{PAGENAME}}|poszukać „{{PAGENAME}}” na innych stronach]],
-<span class="plainlinks">[{{fullurl:{{#Special:Log}}|page={{FULLPAGENAMEE}}}} przeszukać log] lub [{{fullurl:{{FULLPAGENAME}}|action=edit}} utworzyć tę stronę]</span>.',
+<span class="plainlinks">[{{fullurl:{{#Special:Log}}|page={{FULLPAGENAMEE}}}} przeszukać rejestr] lub [{{fullurl:{{FULLPAGENAME}}|action=edit}} utworzyć tę stronę]</span>.',
'noarticletext-nopermission' => 'Ta strona nie posiada jeszcze zawartości.
Możesz [[Special:Search/{{PAGENAME}}|wyszukać ten tytuł]] w treści innych stron
lub <span class="plainlinks">[{{fullurl:{{#Special:Log}}|page={{FULLPAGENAMEE}}}} przeszukać powiązane dzienniki]</span>, ale nie masz uprawnień do utworzenia tej strony',
'minutes' => '{{PLURAL:$1|$1 minuta|$1 minuty|$1 minut}}',
'hours' => '{{PLURAL:$1|$1 godzina|$1 godziny|$1 godzin}}',
'days' => '{{PLURAL:$1|$1 dzień|$1 dni}}',
+'weeks' => '{{PLURAL:$1|$1 tydzień|$1 tygodnie|$1 tygodni}}',
'months' => '{{PLURAL:$1|$1 miesiąc|$1 miesiące|$1 miesięcy}}',
'years' => '{{PLURAL:$1|$1 rok|$1 lata|$1 lat}}',
'ago' => '$1 temu',
# Image rotation
'rotate-comment' => 'Obraz został odwrócony o $1 {{PLURAL:$1|stopień|stopnie|stopni}} (w kierunku zgodnym z ruchem wskazówek zegara)',
+# Unknown messages
+'hours-ago' => '{{PLURAL:$1|przed godziną|$1 godziny temu|$1 godzin temu}}',
+'minutes-ago' => '{{PLURAL:$1|przed minutą|$1 minuty temu|$1 minut temu}}',
+'seconds-ago' => '{{PLURAL:$1|przed sekundą|$1 sekundy temu|$1 sekund temu}}',
);
# Font style option in Special:Preferences
'editfont-style' => "Stil dij caràter ëd l'àrea ëd modìfica:",
'editfont-default' => 'Stàndard dël navigator',
-'editfont-monospace' => 'Font mono-spassià',
-'editfont-sansserif' => 'Font sans-serif',
-'editfont-serif' => 'Font serif',
+'editfont-monospace' => 'Caràter mono-spassià',
+'editfont-sansserif' => 'Caràter sensa piòte',
+'editfont-serif' => 'Caràter con piòte',
# Dates
-'sunday' => 'Dumìnica',
-'monday' => 'Lùn-es',
-'tuesday' => 'Màrtes',
-'wednesday' => 'Merco',
-'thursday' => 'Giòbia',
+'sunday' => 'dumìnica',
+'monday' => 'lùn-es',
+'tuesday' => 'màrtes',
+'wednesday' => 'merco',
+'thursday' => 'giòbia',
'friday' => 'Vënner',
'saturday' => 'Saba',
'sun' => 'Dum',
'nov' => 'Abbreviation of November, the eleventh month of the Gregorian calendar',
'dec' => 'Abbreviation of December, the twelfth month of the Gregorian calendar',
+'monday-at' => 'Phrase for indicating that something occurred at a particular time on the most recent Monday. $1 is the time.',
+'tuesday-at' => 'Phrase for indicating that something occurred at a particular time on the most recent Tuesday. $1 is the time.',
+'wednesday-at' => 'Phrase for indicating that something occurred at a particular time on the most recent Wednesday. $1 is the time.',
+'thursday-at' => 'Phrase for indicating that something occurred at a particular time on the most recent Thursday. $1 is the time.',
+'friday-at' => 'Phrase for indicating that something occurred at a particular time on the most recent Friday. $1 is the time.',
+'saturday-at' => 'Phrase for indicating that something occurred at a particular time on the most recent Saturday. $1 is the time.',
+'sunday-at' => 'Phrase for indicating that something occurred at a particular time on the most recent Sunday. $1 is the time.',
+'today-at' => 'Phrase for indicating that something occurred at a particular time today. $1 is the time.',
+'yesterday-at' => 'Phrase for indicating that something occurred at a particular time yesterday. $1 is the time.',
+
# Categories related messages
'pagecategories' => 'Used in the categories section of pages. Is followed by a colon and a list of categories.',
'category_header' => 'In category description page',
'userlogin-yourname' => 'In new vertical user login & create account forms, label for username field.
{{Identical|Username}}',
'userlogin-yourname-ph' => 'Placeholder text in new userlogin/create account form field.',
+'createacct-helpusername-url' => 'The URL of a page providing username guidance for the wiki.',
+'createacct-helpusername-link' => 'Message in new create account form providing guidance for username.',
'yourpassword' => 'In user preferences
{{Identical|Password}}',
'userlogin-yourpassword' => 'In new vertical user login & create account forms, label for password field.
{{Identical|Password}}',
'userlogin-yourpassword-ph' => 'Placeholder text in new userlogin form for password field.',
+'createacct-yourpassword-ph' => 'Placeholder text in new create account form for password field.',
'yourpasswordagain' => 'In user preferences',
+'createacct-yourpasswordagain' => 'In new create account form, label for field to re-enter password',
+'createacct-yourpasswordagain-ph' => 'Placeholder text in new create account form for re-enter password field.',
'remembermypassword' => 'A check box in [[Special:UserLogin]]
{{Identical|Remember my login on this computer}}',
See also:
* {{msg-mw|Helplogin-url}}',
+'createacct-join' => 'Subheading of vertical-layout create account form encouraging user to join the wiki.',
+'createacct-emailrequired' => 'Label in vertical-layout create account form for email field when it is required.',
+'createacct-emailoptional' => 'Label in vertical-layout create account form for email field when it is optional.',
+'createacct-email-ph' => 'Placeholder in vertical-layout create account form for email field.',
'createaccountmail' => 'Button text for creating a new account and sending the new password to the specified e-mail address directly, as used on [[Special:UserLogin/signup]] if creating accounts by e-mail is allowed.',
+'createacct-realname' => 'In vertical-layout create account form, label for field to enter optional real name.',
'createaccountreason' => '{{Identical|Reason}}',
+'createacct-reason' => 'In vertical-layout create account form, label for field to enter reason to create an account when already logged-in.',
+'createacct-captcha' => 'Label in vertical-layout create account form for CAPTCHA input field when repositioned by JavaScript.',
+'createacct-captcha-help-url' => 'The URL of a page providing CAPTCHA assistance for the wiki.',
+'createacct-imgcaptcha-help' => 'Help text in vertical-layout create account form for image CAPTCHA input field when repositioned by JavaScript.',
+'createacct-imgcaptcha-ph' => 'Placehodler text in vertical-layout create account form for image CAPTCHA input field when repositioned by JavaScript.',
+'createacct-benefit-heading' => 'In vertical-layout create account form, the heading for the section describing the benefits of creating an account.',
+'createacct-benefit-icon1' => 'In vertical-layout create account form, the CSS style for the div next to the first benefit. If you replace this you will need probably need to adjust CSS.',
+'createacct-benefit-head1' => 'In vertical-layout create account form, the text in the heading for the first benefit. Do not edit the magic word; if you replace it you will probably need to adjust CSS.',
+'createacct-benefit-body1' => 'In vertical-layout create account form, the text for the first benefit.',
+'createacct-benefit-icon2' => 'In vertical-layout create account form, the CSS style for the div next to the second benefit. If you replace this you will need probably need to adjust CSS.',
+'createacct-benefit-head2' => 'In vertical-layout create account form, the text in the heading for the second benefit. Do not edit the magic word; if you replace it you will probably need to adjust CSS.',
+'createacct-benefit-body2' => 'In vertical-layout create account form, the text for the second benefit.',
+'createacct-benefit-icon3' => 'In vertical-layout create account form, the CSS style for the div next to the third benefit. If you replace this you will need probably need to adjust CSS.',
+'createacct-benefit-head3' => 'In vertical-layout create account form, the text in the heading for the third benefit. Do not edit the magic word; if you replace it you will probably need to adjust CSS.',
+'createacct-benefit-body3' => 'In vertical-layout create account form, the text for the third benefit.',
'badretype' => 'Used as error message when the new password and its retype do not match.',
'userexists' => 'Used as error message in creating a user account.',
'loginerror' => 'Used as title of error message.
{{Identical|Login error}}',
+'createacct-error' => 'Title of error message in new vertical create account form.',
'createaccounterror' => 'Parameters:
* $1 is an error message',
'nocookiesnew' => "This message is displayed when a new account was successfully created, but the browser doesn't accept cookies.",
Parameters:
* $1 is a user name. This parameter can be used with GENDER.',
-'noemailcreate' => 'Used as error message in [[Special:UserLogin]].',
+'noemailcreate' => 'Used as error message when one user creates an account for another and there is no email.',
'passwordsent' => '* $1 - username',
'blocked-mailpassword' => 'Used as error message in password recovery.',
'eauthentsent' => "This message appears after entering an e-mail address in [[Special:Preferences]] > {{int:prefs-personal}} > {{int:email}}, then clicking on '{{int:saveprefs}}'.",
See also:
* {{msg-mw|Searchprofile-images|message}}
-* {{msg-mw|Searchprofile-images-tooltip|tooltip}}',
+* {{msg-mw|Searchprofile-images-tooltip|tooltip}}
+{{Identical|Muitimedia}}',
'searchprofile-everything' => 'Used as an option in [[Special:Search]].
See also:
'resetprefs' => 'Button for resetting changes in the preferences page.',
'restoreprefs' => 'Used in [[Special:Preferences]]',
'prefs-editing' => 'Title of a tab in [[Special:Preferences]].
-When changing this message, please also update {{msg-mw|vector-editwarning-warning}} which references to this message.',
+When changing this message, please also update {{msg-mw|vector-editwarning-warning}} which references to this message.
+{{Identical|Editing}}',
'prefs-edit-boxsize' => 'Used on [[Special:Preferences]].',
'rows' => 'Used on [[Special:Preferences]], "Editing" section in the "Size of editing window" fieldset',
'columns' => 'Used on [[Special:Preferences]], "Editing" section in the "Size of editing window" fieldset',
* $1 - file title
See also:
* {{msg-mw|Filedelete-intro}}',
-'filedelete-legend' => '{{Identical|Delete}}',
+'filedelete-legend' => 'Used as fieldset label in the "Delete file" form.
+{{Identical|Delete file}}',
'filedelete-intro' => 'Used as introduction for FileDelete form.
See also:
* {{msg-mw|Filedelete|page title}}',
'contribsub2' => 'Contributions for "user" (links)
{{Identical|For $1}}',
'nocontribs' => 'Optional parameter: $1 is the user name',
-'uctop' => 'This message is used in [[Special:Contributions]]. It is used to show that a particular edit was the last made to a page. Example: 09:57, 11 February 2008 (hist) (diff) Pagename (edit summary) (top)',
+'uctop' => 'This message is used in [[Special:Contributions]]. It is used to show that a particular edit was the last made to a page. Example: 09:57, 11 February 2008 (hist) (diff) Pagename (edit summary) (top)
+{{Identical|Top}}',
'month' => 'Used in [[Special:Contributions]] and history pages ([{{fullurl:Sandbox|action=history}} example]), as label for a dropdown box to select a specific month to view the edits made in that month, and the earlier months. See also {{msg-mw|year}}.',
'year' => 'Used in [[Special:Contributions]] and history pages ([{{fullurl:Sandbox|action=history}} example]), as label for an input box to select a specific year to view the edits made in that year, and the earlier years.
Part of variable $1 in {{msg-mw|Ago}}
{{Identical|Day}}',
-'weeks' => 'Full word for "weeks". $1 is the number of weeks.
-
-Part of variable $1 in {{msg-mw|Ago}}',
'months' => 'Full word for "months". $1 is the number of months.
Part of variable $1 in {{msg-mw|Ago}}',
*{{msg-mw|Years}}',
'just-now' => 'Phrase for indicating something happened just now.',
-'hours-ago' => 'Phrase for indicating that something occurred a certain number of hours ago',
-'minutes-ago' => 'Phrase for indicating that something occurred a certain number of minutes ago',
-'seconds-ago' => 'Phrase for indicating that something occurred a certain number of seconds ago',
-
-'monday-at' => 'Phrase for indicating that something occurred at a particular time on the most recent Monday. $1 is the time.',
-'tuesday-at' => 'Phrase for indicating that something occurred at a particular time on the most recent Tuesday. $1 is the time.',
-'wednesday-at' => 'Phrase for indicating that something occurred at a particular time on the most recent Wednesday. $1 is the time.',
-'thursday-at' => 'Phrase for indicating that something occurred at a particular time on the most recent Thursday. $1 is the time.',
-'friday-at' => 'Phrase for indicating that something occurred at a particular time on the most recent Friday. $1 is the time.',
-'saturday-at' => 'Phrase for indicating that something occurred at a particular time on the most recent Saturday. $1 is the time.',
-'sunday-at' => 'Phrase for indicating that something occurred at a particular time on the most recent Sunday. $1 is the time.',
-'today-at' => 'Phrase for indicating that something occurred at a particular time today. $1 is the time.',
-'yesterday-at' => 'Phrase for indicating that something occurred at a particular time yesterday. $1 is the time.',
-
# Bad image list
'bad_image_list' => 'This message only appears to guide administrators to add links with the right format. This will not appear anywhere else in MediaWiki.',
This contains how the information in the picture is stored. This is most commonly Y, Cr, Cb to specify luma, red, blue. RGB is also possible to specify Red, Green, Blue.
{{Related|Exif-componentsconfiguration}}',
'exif-compressedbitsperpixel' => 'Exif is a format for storing metadata in image files. See this [[w:Exchangeable_image_file_format|Wikipedia article]] and the example at the bottom of [[commons:File:Phalacrocorax-auritus-020.jpg|this page on Commons]]. The tags are explained [http://www.awaresystems.be/imaging/tiff/tifftags/privateifd/exif.html briefly] and [http://www.kodak.com/global/plugins/acrobat/en/service/digCam/exifStandard2.pdf in further detail].',
-'exif-pixelydimension' => 'Exif is a format for storing metadata in image files. See this [[w:Exchangeable_image_file_format|Wikipedia article]] and the example at the bottom of [[commons:File:Phalacrocorax-auritus-020.jpg|this page on Commons]]. The tags are explained [http://www.awaresystems.be/imaging/tiff/tifftags/privateifd/exif.html briefly] and [http://www.kodak.com/global/plugins/acrobat/en/service/digCam/exifStandard2.pdf in further detail].',
+'exif-pixelydimension' => 'Exif is a format for storing metadata in image files. See this [[w:Exchangeable_image_file_format|Wikipedia article]] and the example at the bottom of [[commons:File:Phalacrocorax-auritus-020.jpg|this page on Commons]]. The tags are explained [http://www.awaresystems.be/imaging/tiff/tifftags/privateifd/exif.html briefly] and [http://www.kodak.com/global/plugins/acrobat/en/service/digCam/exifStandard2.pdf in further detail].
+{{Identical|Image width}}',
'exif-pixelxdimension' => 'Exif is a format for storing metadata in image files. See this [[w:Exchangeable_image_file_format|Wikipedia article]] and the example at the bottom of [[commons:File:Phalacrocorax-auritus-020.jpg|this page on Commons]]. The tags are explained [http://www.awaresystems.be/imaging/tiff/tifftags/privateifd/exif.html briefly] and [http://www.kodak.com/global/plugins/acrobat/en/service/digCam/exifStandard2.pdf in further detail].',
'exif-usercomment' => "Exif is a format for storing metadata in image files. See this [[w:Exchangeable_image_file_format|Wikipedia article]] and the example at the bottom of [[commons:File:Phalacrocorax-auritus-020.jpg|this page on Commons]]. The tags are explained [http://www.awaresystems.be/imaging/tiff/tifftags/privateifd/exif.html briefly] and [http://www.kodak.com/global/plugins/acrobat/en/service/digCam/exifStandard2.pdf in further detail].
# Image rotation
'rotate-comment' => 'Edit summary for the act of rotating an image.',
+# Unknown messages
+'hours-ago' => 'Phrase for indicating that something occurred a certain number of hours ago',
+'minutes-ago' => 'Phrase for indicating that something occurred a certain number of minutes ago',
+'seconds-ago' => 'Phrase for indicating that something occurred a certain number of seconds ago',
);
'nov' => 'nov',
'dec' => 'dec',
+'monday-at' => 'Luni, la $1',
+'tuesday-at' => 'Marți, la $1',
+'wednesday-at' => 'Miercuri, la $1',
+'thursday-at' => 'Joi,la $1',
+'friday-at' => 'Vineri, la $1',
+'saturday-at' => 'Sâmbătă, la $1',
+'sunday-at' => 'Duminică, la $1',
+'today-at' => '$1',
+'yesterday-at' => 'Ieri, la $1',
+
# Categories related messages
'pagecategories' => '{{PLURAL:$1|Categorie|Categorii}}',
'category_header' => 'Pagini din categoria „$1”',
# Image rotation
'rotate-comment' => 'Imagine rotită în sensul acelor de ceasornic cu $1 {{PLURAL:$1|grad|grade|de grade}}',
+# Unknown messages
+'hours-ago' => 'acum $1 {{PLURAL:$1|oră|ore|de ore}}',
+'minutes-ago' => 'acum $1 {{PLURAL:$1|minut|minute|de minute}}',
+'seconds-ago' => 'acum {{PLURAL:$1|o secundă|$1 secunde|$1 de secunde}}',
);
'nov' => 'Nov',
'dec' => 'Dec',
+'monday-at' => 'Lunedìe a le $1',
+'tuesday-at' => 'Martedìe a le $1',
+'wednesday-at' => 'Mercrudìe a le $1',
+'thursday-at' => 'Sciuvedìe a le $1',
+'friday-at' => 'Venerdìe a le $1',
+'saturday-at' => 'Sabbète a le $1',
+'sunday-at' => 'Dumeneche a le $1',
+'today-at' => '$1',
+'yesterday-at' => 'Aijere a le $1',
+
# Categories related messages
'pagecategories' => '{{PLURAL:$1|Categorije|Categorije}}',
'category_header' => 'Pàggene jndr\'à categorie "$1"',
'minutes' => '{{PLURAL:$1|$1 minute|$1 minute}}',
'hours' => '{{PLURAL: $1|$1ore|$1 ore}}',
'days' => '{{PLURAL: $1|$1 sciurne|$1 sciurne}}',
+'weeks' => '{{PLURAL:$1|$1 sumàne}}',
'months' => '{{PLURAL:$1|$1 mese|$1 mise}}',
'years' => '{{PLURAL:$1|$1 anne}}',
'ago' => '$1 fà',
# Image rotation
'rotate-comment' => 'Immaggine rotate de $1 {{PLURAL:$1|grade}} in sienze orarie',
+# Unknown messages
+'hours-ago' => '$1 {{PLURAL:$1|ore}} fà',
+'minutes-ago' => '$1 {{PLURAL:$1|minute}} fà',
+'seconds-ago' => '$1 {{PLURAL:$1|seconde}} fà',
);
'welcomecreation-msg' => 'Аатыҥ бэлиэтэннэ.
{{SITENAME}} ситим-сиргэ үлэлииргэ табыгастаах буоллун диэн [[Special:Preferences|тус туруорууларгын]] уларытыаххын сөп.',
'yourname' => 'Кыттааччы аатыҥ:',
+'userlogin-yourname' => 'Бэлиэ-аат',
+'userlogin-yourname-ph' => 'Бэлиэ-ааккын киллэр',
'yourpassword' => 'Киирии тыла:',
+'userlogin-yourpassword' => 'Киирии тыл',
+'userlogin-yourpassword-ph' => 'Киирии тылгын суруй',
'yourpasswordagain' => 'Киирии тылгын хатылаа:',
'remembermypassword' => 'Миигин бу көмпүүтэргэ сигээ ($1 {{PLURAL:$1|күн|күнтэн ордуга суох}})',
+'userlogin-remembermypassword' => 'Долоҕойгор хатаа',
+'userlogin-signwithsecure' => 'Бигэ сиэрбэри туһанан киирии',
'securelogin-stick-https' => 'Киирэн баран HTTPS нөҥүө холбонууну салгыырга',
'yourdomainname' => 'Эн дөмүөнүҥ:',
'password-change-forbidden' => 'Бу биикигэ киирии тылы уоарытар табыллыбат.',
'logout' => 'Тахсыы',
'userlogout' => 'Тахсыы',
'notloggedin' => 'Ааккын эппэтиҥ',
+'userlogin-noaccount' => 'Бэлиэтэнэ иликкин дуо?',
+'userlogin-joinproject' => '{{SITENAME}} ситим-сиргэ киирии',
'nologin' => "Бэлиэтэнэ иликкин дуо? '''$1'''.",
'nologinlink' => 'Бэлиэтэнии',
'createaccount' => 'Бэлиэтэнии',
'gotaccount' => "Бэлиэтэммитиҥ дуо? '''$1'''.",
'gotaccountlink' => 'Аатыҥ',
'userlogin-resetlink' => 'Киирэр тылгын умнубуккун дуо?',
+'helplogin-url' => 'Help:Бэлиэ-ааты киллэрии',
+'userlogin-helplink' => '[[{{MediaWiki:helplogin-url}}|Бэлиэтэниигэ көмө]]',
'createaccountmail' => 'Быстах киирии тылы туһаныы уонна ону email-ынан ыытыы',
'createaccountreason' => 'Төрүөтэ:',
'badretype' => 'Киирии тылларыҥ сөп түбэспэтилэр.',
'nov' => 'nov',
'dec' => 'dec',
+'monday-at' => 'v pondelok o $1',
+'tuesday-at' => 'v utorok o $1',
+'wednesday-at' => 'v stredu o $1',
+'thursday-at' => 'vo štvrtok o $1',
+'friday-at' => 'v piatok o $1',
+'saturday-at' => 'v sobotu o $1',
+'sunday-at' => 'v nedeľu o $1',
+'today-at' => '$1',
+'yesterday-at' => 'včera o $1',
+
# Categories related messages
'pagecategories' => '{{PLURAL:$1|Kategória|Kategórie|Kategórie}}',
'category_header' => 'Stránky v kategórii „$1“',
# Image rotation
'rotate-comment' => 'Obrázok otočený o $1 {{PLURAL:$1|stupeň|stupne|stupňov}} v smere hodinových ručičiek',
+# Unknown messages
+'hours-ago' => 'pred $1 {{PLURAL:$1|hodinou|hodinami}}',
+'minutes-ago' => 'pred $1 {{PLURAL:$1|minútou|minútami}}',
+'seconds-ago' => 'pred $1 {{PLURAL:$1|sekundou|sekundami}}',
);
'nov' => 'nov.',
'dec' => 'dec.',
+'monday-at' => 'Ponedeljek ob $1',
+'tuesday-at' => 'Torek ob $1',
+'wednesday-at' => 'Sreda ob $1',
+'thursday-at' => 'Četrtek ob $1',
+'friday-at' => 'Petek ob $1',
+'saturday-at' => 'Sobota ob $1',
+'sunday-at' => 'Nedelja ob $1',
+'today-at' => '$1',
+'yesterday-at' => 'Včeraj ob $1',
+
# Categories related messages
'pagecategories' => '{{PLURAL:$1|Kategorija|Kategoriji|Kategorije}}',
'category_header' => 'Strani v kategoriji »$1«',
Začasno geslo: $2',
'passwordreset-emailsent' => 'Poslali smo e-pošto za postavitev gesla.',
'passwordreset-emailsent-capture' => 'Poslali smo e-pošto za ponastavitev gesla, ki je prikazana spodaj.',
-'passwordreset-emailerror-capture' => 'Ustvarili smo e-pošto za ponastavitev gesla, ki je prikazana spodaj, vendar pa pošiljanje uporabniku ni uspelo: $1',
+'passwordreset-emailerror-capture' => 'Ustvarili smo e-pošto za ponastavitev gesla, ki je prikazana spodaj, vendar pa pošiljanje {{GENDER:$2|uporabniku|uporabnici}} ni uspelo: $1',
# Special:ChangeEmail
'changeemail' => 'Sprememba e-poštnega naslova',
'minutes' => '$1 {{PLURAL:$1|minuta|minuti|minute|minut}}',
'hours' => '$1 {{PLURAL:$1|ura|uri|ure|ur}}',
'days' => '$1 {{PLURAL:$1|dan|dneva|dnevi|dni}}',
+'weeks' => '$1 {{PLURAL:$1|teden|tedna|tedni|tednov}}',
'months' => '$1 {{PLURAL:$1|mesec|meseca|mesece|mesecev}}',
'years' => '$1 {{PLURAL:$1|leto|leti|leta|let}}',
'ago' => 'pred $1',
# Image rotation
'rotate-comment' => 'Slika zavrti s $1 {{PLURAL:$1| degree|degrees}} v smeri urinega kazalca',
+# Unknown messages
+'hours-ago' => 'pred $1 {{PLURAL:$1|uro|urama|urami}}',
+'minutes-ago' => 'pred $1 {{PLURAL:$1|minuto|minutama|minutami}}',
+'seconds-ago' => 'pred $1 {{PLURAL:$1|sekundo|sekundama|sekundami}}',
);
'nov' => 'Kas',
'dec' => 'Ara',
+'monday-at' => '$1 Pazartesi günü',
+'tuesday-at' => '$1 Salı günü',
+'wednesday-at' => '$1 Çarşamba günü',
+'thursday-at' => '$1 Perşembe günü',
+'friday-at' => '$1 Cuma günü',
+'saturday-at' => '$1 Cumartesi günü',
+'sunday-at' => '$1 Pazar günü',
+'today-at' => '$1',
+'yesterday-at' => '$1 dün itibariyle',
+
# Categories related messages
'pagecategories' => '{{PLURAL:$1|Kategori|Kategoriler}}',
'category_header' => '"$1" kategorisindeki sayfalar',
'duration-centuries' => '$1 {{PLURAL:$1|yüzyıl|yüzyıl}}',
'duration-millennia' => '$1 {{PLURAL:$1|bin yıl|bin yıl}}',
+# Unknown messages
+'hours-ago' => '$1 {{PLURAL:$1|saat|saat}} önce',
+'minutes-ago' => '$1 {{PLURAL:$1|dakika|dakika}} önce',
+'seconds-ago' => '$1 {{PLURAL:$1|saniye|saniye}} önce',
);
* @author RLuts
* @author Riwnodennyk
* @author Sodmy
+ * @author Ua2004
* @author Urhixidur
* @author VolodymyrF
* @author Vox
'addedwatchtext' => "Сторінку «[[:$1]]» додано до вашого [[Special:Watchlist|списку спостереження]].
Подальші редагування цієї сторінки (та пов'язаної з нею сторінки обговорення) відображатимуться в цьому списку.",
'removewatch' => 'Видалити зі списку спостереження',
-'removedwatchtext' => 'Сторінка «[[:$1]]» вилучена з вашого [[Special:Watchlist|списку спостереження]].',
+'removedwatchtext' => 'Сторінку «[[:$1]]» вилучено з вашого [[Special:Watchlist|списку спостереження]].',
'watch' => 'Спостерігати',
'watchthispage' => 'Спостерігати за цією сторінкою',
'unwatch' => 'Скас. спостереження',
'nov' => 'tháng 11',
'dec' => 'tháng 12',
+'monday-at' => 'Thứ Hai lúc $1',
+'tuesday-at' => 'Thứ Ba lúc $1',
+'wednesday-at' => 'Thứ Tư lúc $1',
+'thursday-at' => 'Thứ Năm lúc $1',
+'friday-at' => 'Thứ Sáu lúc $1',
+'saturday-at' => 'Thứ Bảy lúc $1',
+'sunday-at' => 'Chủ Nhật lúc $1',
+'today-at' => '$1',
+'yesterday-at' => 'Hôm qua lúc $1',
+
# Categories related messages
'pagecategories' => '{{PLURAL:$1|Thể loại|Thể loại}}',
'category_header' => 'Các trang trong thể loại “$1”',
Mật khẩu tạm: $2',
'passwordreset-emailsent' => 'Đã gửi thư điện tử để tái tạo mật khẩu.',
'passwordreset-emailsent-capture' => 'Thư điện tử để tái tạo mật khẩu đã được gửi, nội dung như sau.',
-'passwordreset-emailerror-capture' => 'Chúng tôi đã tạo thư tái tạo mật khẩu dưới đây, nhưng không thể gửi đến người dùng: $1',
+'passwordreset-emailerror-capture' => 'Chúng tôi đã tạo thư tái tạo mật khẩu dưới đây, nhưng không thể gửi đến {{GENDER:$2}}người dùng: $1',
# Special:ChangeEmail
'changeemail' => 'Đổi địa chỉ thư điện tử',
'minutes' => '$1 phút',
'hours' => '$1 giờ',
'days' => '$1 ngày',
+'weeks' => '{{PLURAL:$1|$1 tuần}}',
'months' => '$1 tháng',
'years' => '$1 năm',
'ago' => 'cách đây $1',
# Image rotation
'rotate-comment' => 'Đã quay hình $1 độ theo chiều kim đồng hồ',
+# Unknown messages
+'hours-ago' => 'Cách đây $1 {{PLURAL:$1|giờ}}',
+'minutes-ago' => 'Cách đây $1 {{PLURAL:$1|phút}}',
+'seconds-ago' => 'Cách đây $1 {{PLURAL:$1|giây}}',
);
'nov' => '11月',
'dec' => '12月',
+'monday-at' => '於星期一$1',
+'tuesday-at' => '於星期二$1',
+'wednesday-at' => '於星期三$1',
+'thursday-at' => '於星期四$1',
+'friday-at' => '於星期五$1',
+'saturday-at' => '於星期六$1',
+'sunday-at' => '於星期日$1',
+'today-at' => '$1',
+'yesterday-at' => '昨天$1',
+
# Categories related messages
'pagecategories' => '$1個分類',
'category_header' => '「$1」分類中的頁面',
'minutes' => '$1分鍾',
'hours' => '$1小時',
'days' => '$1天',
+'weeks' => '{{PLURAL:$1|$1周|$1周}}',
'months' => '{{PLURAL:$1|$1個月|$1個月}}',
'years' => '{{PLURAL:$1|$1年|$1年}}',
'ago' => '$1前',
# Image rotation
'rotate-comment' => '順時針旋轉圖像$1{{PLURAL:$1|度|度}}',
+# Unknown messages
+'hours-ago' => '$1小時前',
+'minutes-ago' => '$1分鐘前',
+'seconds-ago' => '$1秒前',
);
$matches = array();
if ( preg_match( '/^--(.+?)(?:=(.+?)(?::(.+?))?)?$/', $arg, $matches ) ) {
@list( /* $full */ , $opt, $val, $param ) = $matches;
- switch( $opt ) {
+ switch ( $opt ) {
case "plugin":
$this->loadPlugin( $val, $param );
break;
function fatalError( $msg ) {
$this->progress( "$msg\n" );
- die(1);
+ die( 1 );
}
}
$this->infiles = explode( ';', $infile );
$this->reader = new XMLReader();
$infile = array_shift( $this->infiles );
- if (defined( 'LIBXML_PARSEHUGE' ) ) {
+ if ( defined( 'LIBXML_PARSEHUGE' ) ) {
$this->reader->open( $infile, null, LIBXML_PARSEHUGE );
}
else {
}
} else {
$this->close();
- if (count($this->infiles)) {
- $infile = array_shift($this->infiles);
+ if ( count( $this->infiles ) ) {
+ $infile = array_shift( $this->infiles );
$this->reader->open( $infile );
$this->atEnd = false;
}
}
$buffer = "";
while ( $this->reader->read() ) {
- switch( $this->reader->nodeType ) {
+ switch ( $this->reader->nodeType ) {
case XMLReader::TEXT:
// case XMLReader::WHITESPACE:
case XMLReader::SIGNIFICANT_WHITESPACE:
global $IP;
$url = $this->processFileOpt( $val, $param );
- switch( $opt ) {
+ switch ( $opt ) {
case 'prefetch':
require_once "$IP/maintenance/backupPrefetch.inc";
$this->prefetch = new BaseDump( $url );
function processFileOpt( $val, $param ) {
$fileURIs = explode( ';', $param );
foreach ( $fileURIs as $URI ) {
- switch( $val ) {
+ switch ( $val ) {
case "file":
$newURI = $URI;
break;
"}}",
"{{INT:googlesearch|",
"}}",
+ "{{ROOTPAGENAME}}",
"{{BASEPAGENAME}}",
"{{CONTENTLANGUAGE}}",
"{{PAGESINNAMESPACE:}}",
}
$out = null;
- switch( $this->getOption( 'format' ) ) {
+ switch ( $this->getOption( 'format' ) ) {
case 'PHP':
$out = serialize( $res );
break;
public function __construct( array $options ) {
if ( isset( $options['help'] ) ) {
echo $this->help();
- exit(1);
+ exit( 1 );
}
if ( isset( $options['lang'] ) ) {
public function __construct( array $options, $extension ) {
if ( isset( $options['help'] ) ) {
echo $this->help();
- exit(1);
+ exit( 1 );
}
if ( isset( $options['lang'] ) ) {
echo $extension->name() . ":\n";
if ( $this->level > 0 ) {
- switch( $this->output ) {
+ switch ( $this->output ) {
case 'plain':
$this->outputText();
break;
'ipb-default-expiry',
'pageinfo-header',
'pageinfo-footer',
+ 'createacct-benefit-head1',
+ 'createacct-benefit-icon1',
+ 'createacct-benefit-head2',
+ 'createacct-benefit-icon2',
+ 'createacct-benefit-head3',
+ 'createacct-benefit-icon3',
+ 'today-at',
);
/** Optional messages, which may be translated only if changed in the target language. */
'nov',
'dec',
),
- 'human-timestamps' => array(
- 'monday-at',
- 'tuesday-at',
- 'wednesday-at',
- 'thursday-at',
- 'friday-at',
- 'saturday-at',
- 'sunday-at',
- 'today-at',
- 'yesterday-at',
- ),
'categorypages' => array(
'pagecategories',
'pagecategorieslink',
'yourname',
'userlogin-yourname',
'userlogin-yourname-ph',
+ 'createacct-helpusername-url',
+ 'createacct-helpusername-link',
'yourpassword',
'userlogin-yourpassword',
'userlogin-yourpassword-ph',
+ 'createacct-yourpassword-ph',
'yourpasswordagain',
+ 'createacct-yourpasswordagain',
+ 'createacct-yourpasswordagain-ph',
'remembermypassword',
'userlogin-remembermypassword',
'userlogin-signwithsecure',
'userlogin-resetlink',
'helplogin-url',
'userlogin-helplink',
+ 'createacct-join',
+ 'createacct-emailrequired',
+ 'createacct-emailoptional',
+ 'createacct-email-ph',
'createaccountmail',
+ 'createacct-realname',
'createaccountreason',
+ 'createacct-reason',
+ 'createacct-captcha',
+ 'createacct-captcha-help-url',
+ 'createacct-imgcaptcha-help',
+ 'createacct-imgcaptcha-ph',
+ 'createacct-benefit-heading',
+ 'createacct-benefit-icon1',
+ 'createacct-benefit-head1',
+ 'createacct-benefit-body1',
+ 'createacct-benefit-icon2',
+ 'createacct-benefit-head2',
+ 'createacct-benefit-body2',
+ 'createacct-benefit-icon3',
+ 'createacct-benefit-head3',
+ 'createacct-benefit-body3',
'badretype',
'userexists',
'loginerror',
+ 'createacct-error',
'createaccounterror',
'nocookiesnew',
'nocookieslogin',
'ago',
'just-now',
),
+ 'human-timestamps' => array(
+ 'hours-ago',
+ 'minutes-ago',
+ 'seconds-ago',
+ 'monday-at',
+ 'tuesday-at',
+ 'wednesday-at',
+ 'thursday-at',
+ 'friday-at',
+ 'saturday-at',
+ 'sunday-at',
+ 'today-at',
+ 'yesterday-at',
+ ),
'badimagelist' => array(
'bad_image_list',
),
'patrol-log' => 'Patrol log',
'imagedeletion' => 'Image deletion',
'browsediffs' => 'Browsing diffs',
- 'newfiles' => 'Special:NewFiles',
+ 'newfiles' => 'Special:NewFiles',
'video-info' => 'Video information, used by Language::formatTimePeriod() to format lengths in the above messages',
+ 'human-timestamps' => 'Human-readable timestamps',
'badimagelist' => 'Bad image list',
'variantname-zh' => "Short names for language variants used for language conversion links.
Variants for Chinese language",
unset( $file );
if ( is_array( $argv ) ) {
- for ($i = 0; $i < count($argv); $i++ ) {
- switch( $argv[$i] ) {
+ for ( $i = 0; $i < count( $argv ); $i++ ) {
+ switch ( $argv[$i] ) {
case '--all':
$input = 0;
break;
END;
- exit(0);
+ exit( 0 );
break;
}
}
job_namespace NUMBER DEFAULT 0 NOT NULL,
job_title VARCHAR2(255) NOT NULL,
job_timestamp TIMESTAMP(6) WITH TIME ZONE NULL,
- job_params CLOB NOT NULL
- job_random NUMBER NOT NULL default 0,
+ job_params CLOB NOT NULL,
+ job_random NUMBER DEFAULT 0 NOT NULL,
job_token VARCHAR2(32),
job_token_timestamp TIMESTAMP(6) WITH TIME ZONE,
job_sha1 VARCHAR2(32),
- job_attempts NUMBER NOT NULL default 0
+ job_attempts NUMBER DEFAULT 0 NOT NULL
);
ALTER TABLE &mw_prefix.job ADD CONSTRAINT &mw_prefix.job_pk PRIMARY KEY (job_id);
CREATE INDEX &mw_prefix.job_i01 ON &mw_prefix.job (job_cmd, job_namespace, job_title);
si_type VARCHAR2(32) NOT NULL,
si_key VARCHAR2(32) NOT NULL
);
-CREATE UNIQUE INDEX &mw_prefix.site_identifiers_u01 ON &mw_prefix.sites (si_type, si_key);
+CREATE UNIQUE INDEX &mw_prefix.site_identifiers_u01 ON &mw_prefix.site_identifiers (si_type, si_key);
CREATE INDEX &mw_prefix.site_identifiers_i01 ON &mw_prefix.site_identifiers (si_site);
CREATE INDEX &mw_prefix.site_identifiers_i02 ON &mw_prefix.site_identifiers (si_key);
function importRevision( &$revision, &$importer ) {
$id = $revision->getID();
- $text = $revision->getText();
+ $content = $revision->getContent( Revision::RAW );
+ $id = $id ? $id : '';
+
+ if ( $content === null ) {
+ echo "Revision $id is broken, we have no content available\n";
+ return;
+ }
+
+ $text = $content->serialize();
if ( $text === '' ) {
// This is what happens if the revision was broken at the time the
// dump was made. Unfortunately, it also happens if the revision was
// legitimately blank, so there's no way to tell the difference. To
// be safe, we'll skip it and leave it broken
- $id = $id ? $id : '';
+
echo "Revision $id is blank in the dump, may have been broken before export\n";
return;
}
),
'position' => 'top',
),
+ 'mediawiki.special.createaccount.vform' => array(
+ 'styles' => array(
+ 'resources/mediawiki.special/mediawiki.special.vforms.css',
+ 'resources/mediawiki.special/mediawiki.special.createAccount.vform.css',
+ ),
+ 'position' => 'top',
+ ),
+ 'mediawiki.special.createaccount.vform.js' => array(
+ 'scripts' => 'resources/mediawiki.special/mediawiki.special.createAccount.vform.js',
+ 'messages' => array(
+ 'createacct-captcha',
+ 'createacct-imgcaptcha-ph'
+ ),
+ 'dependencies' => 'mediawiki.jqueryMsg',
+ 'position' => 'top',
+ ),
'mediawiki.special.javaScriptTest' => array(
'scripts' => 'resources/mediawiki.special/mediawiki.special.javaScriptTest.js',
'messages' => array_merge( Skin::getSkinNameMessages(), array(
--- /dev/null
+/* Disable the underline that Vector puts on h2 headings, and bold them. */
+.mw-ui-container h2 {
+ border: 0;
+ font-weight: bold;
+}
+
+/* shuffled CAPTCHA */
+#wpCaptchaWord {
+ margin-top: 6px;
+}
+
+.mw-createacct-captcha-container {
+ background-color: #f8f8f8;
+ border: 1px solid #c9c9c9;
+ padding: 10px;
+ text-align: center;
+}
+
+.mw-createacct-captcha-image-container {
+ background-color: #fff;
+ min-height: 95px;
+}
+
+.mw-createacct-captcha-assisted {
+ display: block;
+ margin-top: 0.5em;
+}
+
+.mw-createacct-captcha-and-reload {
+ border: 1px solid #c9c9c9;
+ display: table-cell;
+ width: 270px;
+ background-color: #FFF;
+}
+
+.mw-createacct-captcha-and-reload .confirmedit-captcha-reload {
+ display: block;
+ float: right;
+}
+
+/* Benefits column CSS to the right (if it fits) of the form. */
+.mw-ui-container #userloginForm {
+ float: left;
+}
+
+div.mw-createacct-benefits-container {
+ float: left
+}
+
+div.mw-createacct-benefits-container h2 {
+ margin-bottom: 30px;
+}
+
+div.mw-benefits-icon {
+ display: inline-block;
+ padding: 0;
+ float: left;
+ width: 80px;
+ height: 75px;
+ margin-right: 15px;
+ border: 0;
+}
+
+.mw-benefits-icon.icon-edits {
+ /* @embed */
+ background: url(images/icon-edits.png) no-repeat right;
+}
+
+.mw-benefits-icon.icon-pages {
+ /* @embed */
+ background: url(images/icon-pages.png) no-repeat right;
+}
+
+.mw-benefits-icon.icon-contributors {
+ /* @embed */
+ background: url(images/icon-contributors.png) no-repeat right;
+}
+
+/* Special font for numbers in benefits*/
+div.mw-number-text h3 {
+ top: 0;
+ margin: 0;
+ padding: 0;
+ color: #252525;
+ font-family: 'Georgia', serif;
+ font-weight: normal;
+ font-size: 2.2em;
+ line-height: 1.2;
+ text-align: center;
+}
+
+div.mw-number-text {
+ display: block;
+ font-size: 1.2em;
+ color: #444;
+ margin-top: 1em;
+ text-align: center;
+}
--- /dev/null
+/**
+ * JavaScript for Create account form (Special:UserLogin?type=signup).
+ */
+( function ( mw, $ ) {
+
+ $( document ).ready( function( $ ) {
+ var $content = $( '#mw-content-text' ),
+ $submit = $content.find( '#wpCreateaccount' ),
+ tabIndex,
+ $captchaStuff,
+ helpMsg = mw.config.get( 'wgCreateacctImgcaptchaHelp' ),
+ captchaImage;
+
+ /*
+ * CAPTCHA
+ * The CAPTCHA is in a div style="captcha" at the top of the form.
+ * If it's a FancyCaptcha, then we remove it and insert it lower down,
+ * in a customized div with just what we need (e.g. no
+ * fancycaptcha-createaccount message).
+ */
+ if ( !$submit.length) {
+ return;
+ }
+ tabIndex = $submit.prop( 'tabindex' ) - 1;
+ $captchaStuff = $content.find ( '.captcha' );
+
+ if ( $captchaStuff.length ) {
+
+ // The FancyCaptcha image has this class in the ConfirmEdit extension
+ // after 2013-04-18.
+ captchaImage = $captchaStuff.find( 'img.fancycaptcha-image' );
+ if ( captchaImage.length !== 1 ) {
+ return;
+ }
+
+ $captchaStuff.remove();
+
+ // Insert another div before the submit button.
+ $submit.closest( 'div' )
+ .before( [
+ '<div>',
+ '<label for="wpCaptchaWord">' + mw.message( 'createacct-captcha' ).escaped() + '</label>',
+ '<div class="mw-createacct-captcha-container">',
+ '<div class="mw-createacct-captcha-and-reload">',
+ '<div class="mw-createacct-captcha-image-container">',
+ '<img id="mw-createacct-captcha" alt="PLACEHOLDER">',
+ '</div>',
+ '</div>',
+ '<input id="wpCaptchaWord" name="wpCaptchaWord" type="text" placeholder="' +
+ mw.message( 'createacct-imgcaptcha-ph' ).escaped() +
+ '" tabindex="' + tabIndex + '" autocapitalize="off" autocorrect="off">',
+ '<small class="mw-createacct-captcha-assisted">' + helpMsg + '</small>',
+ '</div>',
+ '</div>'
+ ].join( '' )
+ );
+
+ // Replace the placeholder img with the img from the old CAPTCHA.
+ captchaImage.replaceAll( $content.find( '#mw-createacct-captcha' ) );
+
+ // Append CAPTCHA reload, if any.
+ $( '.mw-createacct-captcha-and-reload' ).append( $captchaStuff.find( '.confirmedit-captcha-reload' ) );
+
+ // Find the input field, add the text (if any) of the existing CAPTCHA
+ // field (although usually it's blanked out on every redisplay),
+ // and after it move over the hidden field that tells the CAPTCHA
+ // what to do.
+ $content.find( '#wpCaptchaWord' )
+ .val( $captchaStuff.find( '#wpCaptchaWord' ).val() )
+ .after( $captchaStuff.find( '#wpCaptchaId' ) );
+ }
+
+ });
+
+}( mediaWiki, jQuery ) );
font-size: 0.8em;
}
+/* Put some space under template's header, which may contain CAPTCHA HTML.*/
+section.mw-form-header {
+ margin-bottom: 10px;
+}
+
/*
* Besides errorbox there could be warningbox, successbox, msgbox, though
* spage has never seen these in practice.
text-shadow: 0 1px #fae3e3;
word-wrap: break-word;
}
+
+/*
+ * Override the right margin of the form to give space in case a benefits
+ * column appears to the side.
+ *
+ */
+.mw-ui-container #userloginForm {
+ margin-right: 100px;
+}
padding: 0;
width: 100%;
}
-/* line 28, sourcefiles/scss/components/default/_forms.scss */
+/* line 27, sourcefiles/scss/components/default/_forms.scss */
.mw-ui-vform > div input,
-.mw-ui-vform > div label,
.mw-ui-vform > div .mw-ui-button {
display: block;
-webkit-box-sizing: border-box;
margin: 0;
width: 100%;
}
-/* line 35, sourcefiles/scss/components/default/_forms.scss */
+/* line 34, sourcefiles/scss/components/default/_forms.scss */
.mw-ui-vform > div input {
outline: 0;
border-style: solid;
box-shadow: #4091ed 0px 0px 5px;
border-color: #4091ed;
}
-/* line 39, sourcefiles/scss/components/default/_forms.scss */
+/* line 38, sourcefiles/scss/components/default/_forms.scss */
.mw-ui-vform > div label {
+ display: block;
+ -webkit-box-sizing: border-box;
+ -moz-box-sizing: border-box;
+ box-sizing: border-box;
font-size: 0.9em;
color: #7d7d7d;
width: auto;
padding: 0;
width: 100%;
}
-/* line 28, sourcefiles/scss/components/default/_forms.scss */
+/* line 27, sourcefiles/scss/components/default/_forms.scss */
.mw-ui-vform > div input,
-.mw-ui-vform > div label,
.mw-ui-vform > div .mw-ui-button {
display: block;
-webkit-box-sizing: border-box;
margin: 0;
width: 100%;
}
-/* line 35, sourcefiles/scss/components/default/_forms.scss */
+/* line 34, sourcefiles/scss/components/default/_forms.scss */
.mw-ui-vform > div input {
outline: 0;
border-style: solid;
box-shadow: #4091ed 0px 0px 5px;
border-color: #4091ed;
}
-/* line 39, sourcefiles/scss/components/default/_forms.scss */
+/* line 38, sourcefiles/scss/components/default/_forms.scss */
.mw-ui-vform > div label {
+ display: block;
+ -webkit-box-sizing: border-box;
+ -moz-box-sizing: border-box;
+ box-sizing: border-box;
font-size: 0.9em;
color: #7d7d7d;
width: auto;
// MW currently doesn't use the type attribute everywhere on inputs.
input,
- label,
.mw-ui-button {
display: block;
@include box-sizing(border-box);
}
label {
+ display: block;
+ @include box-sizing(border-box);
@include agora-label-styling;
-
width: auto;
margin: 0 0 0.2em 0;
padding: 0;
/**
* @property {RegExp}
* Regex to match accesskey tooltips.
+ *
+ * Should match:
+ *
+ * - "ctrl-option-"
+ * - "alt-shift-"
+ * - "ctrl-alt-"
+ * - "ctrl-"
+ *
+ * The accesskey is matched in group $6.
*/
- tooltipAccessKeyRegexp: /\[(ctrl-)?(alt-)?(shift-)?(esc-)?(.)\]$/,
+ tooltipAccessKeyRegexp: /\[(ctrl-)?(option-)?(alt-)?(shift-)?(esc-)?(.)\]$/,
/**
* Add the appropriate prefix to the accesskey shown in the tooltip.
}
$nodes.attr( 'title', function ( i, val ) {
- if ( val && util.tooltipAccessKeyRegexp.exec( val ) ) {
+ if ( val && util.tooltipAccessKeyRegexp.test( val ) ) {
return val.replace( util.tooltipAccessKeyRegexp,
- '[' + util.tooltipAccessKeyPrefix + '$5]' );
+ '[' + util.tooltipAccessKeyPrefix + '$6]' );
}
return val;
} );
if ( id ) {
$item.attr( 'id', id );
}
- if ( accesskey ) {
- $link.attr( 'accesskey', accesskey );
- tooltip += ' [' + accesskey + ']';
+
+ if ( tooltip ) {
+ // Trim any existing accesskey hint and the trailing space
+ tooltip = $.trim( tooltip.replace( util.tooltipAccessKeyRegexp, '' ) );
+ if ( accesskey ) {
+ tooltip += ' [' + accesskey + ']';
+ }
$link.attr( 'title', tooltip );
+ if ( accesskey ) {
+ util.updateTooltipAccessKeys( $link );
+ }
}
- if ( accesskey && tooltip ) {
- util.updateTooltipAccessKeys( $link );
+
+ if ( accesskey ) {
+ $link.attr( 'accesskey', accesskey );
}
// Where to put our node ?
// - nextnode is a DOM element (was the only option before MW 1.17, in wikibits.js)
if ( nextnode && nextnode.parentNode === $ul[0] ) {
- $(nextnode).before( $item );
+ $( nextnode ).before( $item );
// - nextnode is a CSS selector for jQuery
} else if ( typeof nextnode === 'string' && $ul.find( nextnode ).length !== 0 ) {
<?php } ?>
<?php if ( $this->data['newtalk'] ) { ?>
<!-- newtalk -->
- <div class="usermessage"><?php $this->html( 'newtalk' ) ?></div>
+ <div class="usermessage"><?php $this->html( 'newtalk' ) ?></div>
<!-- /newtalk -->
<?php } ?>
<?php if ( $this->data['showjumplinks'] ) { ?>
}
echo "\n<!-- {$name} -->\n";
- switch( $name ) {
+ switch ( $name ) {
case 'SEARCH':
break;
case 'TOOLBOX':
// Render elements
foreach ( $elements as $name => $element ) {
echo "\n<!-- {$name} -->\n";
- switch( $element ) {
+ switch ( $element ) {
case 'NAMESPACES':
?>
<div id="p-namespaces" role="navigation" class="vectorTabs<?php if ( count( $this->data['namespace_urls'] ) == 0 ) { echo ' emptyPortlet'; } ?>">
}
protected function stopServer() {
- if ( !isset ( $this->serverManager ) ) {
+ if ( !isset( $this->serverManager ) ) {
echo ( "Warning: Request to stop Selenium Server, but it was " .
"not stared by RunSeleniumTests\n" .
"RunSeleniumTests cannot stop a Selenium Server it " .
'DbTestPreviewer' => "$testDir/testHelpers.inc",
'DbTestRecorder' => "$testDir/testHelpers.inc",
'DelayedParserTest' => "$testDir/testHelpers.inc",
+ 'ParserTestResult' => "$testDir/parser/ParserTestResult.php",
'TestFileIterator' => "$testDir/testHelpers.inc",
'TestRecorder' => "$testDir/testHelpers.inc",
--- /dev/null
+<?php
+/**
+ * @copyright Copyright © 2013, Antoine Musso
+ * @copyright Copyright © 2013, Wikimedia Foundation Inc.
+ * @license GNU GPL v2
+ *
+ * @file
+ */
+
+/**
+ * Represent the result of a parser test.
+ *
+ * @since 1.22
+ */
+class ParserTestResult {
+ /**
+ * Description of the parser test.
+ *
+ * This is usually the text used to describe a parser test in the .txt
+ * files. It is initialized on a construction and you most probably
+ * never want to change it.
+ */
+ public $description;
+ /** Text that was expected */
+ public $expected;
+ /** Actual text rendered */
+ public $actual;
+
+ /**
+ * @param $description string A short text describing the parser test
+ * usually the text in the parser test .txt file. The description
+ * is later available using the property $description.
+ */
+ public function __construct( $description ) {
+ $this->description = $description;
+ }
+
+ /** Whether the test passed */
+ public function isSuccess() {
+ return ($this->expected === $this->actual);
+ }
+}
}
$this->teardownGlobals();
- return $this->showTestResult( $desc, $result, $out );
+
+ $testResult = new ParserTestResult( $desc );
+ $testResult->expected = $result;
+ $testResult->actual = $out;
+
+ return $this->showTestResult( $testResult );
}
/**
- *
+ * Refactored in 1.22 to use ParserTestResult
*/
- function showTestResult( $desc, $result, $out ) {
- if ( $result === $out ) {
- $this->showSuccess( $desc );
+ function showTestResult( ParserTestResult $testResult ) {
+ if ( $testResult->isSuccess() ) {
+ $this->showSuccess( $testResult );
return true;
} else {
- $this->showFailure( $desc, $result, $out );
+ $this->showFailure( $testResult );
return false;
}
}
/**
* Print a happy success message.
*
- * @param $desc String: the test name
+ * Refactored in 1.22 to use ParserTestResult
+ *
+ * @param $testResult ParserTestResult
* @return Boolean
*/
- protected function showSuccess( $desc ) {
+ protected function showSuccess( ParserTestResult $testResult ) {
if ( $this->showProgress ) {
print $this->term->color( '1;32' ) . 'PASSED' . $this->term->reset() . "\n";
}
* Print a failure message and provide some explanatory output
* about what went wrong if so configured.
*
- * @param $desc String: the test name
- * @param $result String: expected HTML output
- * @param $html String: actual HTML output
+ * Refactored in 1.22 to use ParserTestResult
+ *
+ * @param $testResult ParserTestResult
* @return Boolean
*/
- protected function showFailure( $desc, $result, $html ) {
+ protected function showFailure( ParserTestResult $testResult ) {
if ( $this->showFailure ) {
if ( !$this->showProgress ) {
# In quiet mode we didn't show the 'Testing' message before the
# test, in case it succeeded. Show it now:
- $this->showTesting( $desc );
+ $this->showTesting( $testResult->description );
}
print $this->term->color( '31' ) . 'FAILED!' . $this->term->reset() . "\n";
if ( $this->showOutput ) {
- print "--- Expected ---\n$result\n--- Actual ---\n$html\n";
+ print "--- Expected ---\n{$testResult->expected}\n";
+ print "--- Actual ---\n{$testResult->actual}\n";
}
if ( $this->showDiffs ) {
- print $this->quickDiff( $result, $html );
- if ( !$this->wellFormed( $html ) ) {
+ print $this->quickDiff( $testResult->expected, $testResult->actual );
+ if ( !$this->wellFormed( $testResult->actual ) ) {
print "XML error: $this->mXmlError\n";
}
}
</p>
!! end
+!! test
+Link containing an equals sign
+!! input
+[[Special:BookSources/isbn=4-00-026157-6]]
+!! result
+<p><a href="/wiki/Special:BookSources/isbn%3D4-00-026157-6" title="Special:BookSources/isbn=4-00-026157-6">Special:BookSources/isbn=4-00-026157-6</a>
+</p>
+!! end
+
+!! article
+Foo~bar
+!! text
+Just a test of an article title containing a tilde.
+!! endarticle
+
+# note that links containing signatures, like [[Foo~~~~]], are
+# massaged by the pre-save transform (PST) and so the tildes are never
+# seen by the parser.
+!! test
+Link containing a tilde
+!! input
+[[Foo~bar]]
+!! result
+<p><a href="/wiki/Foo%7Ebar" title="Foo~bar">Foo~bar</a>
+</p>
+!! end
+
!! test
Link containing double-single-quotes '' (bug 4598)
!! input
</p>
!! end
+!! article
+Söfnuður
+!! text
+Test.
+!! endarticle
+
+!! test
+Internal link with is linkprefix
+!! options
+language=is
+!! input
+Aðrir mótmælenda[[söfnuður|söfnuðir]] og
+!! result
+<p>Aðrir <a href="/wiki/S%C3%B6fnu%C3%B0ur" title="Söfnuður">mótmælendasöfnuðir</a> og
+</p>
+!! end
+
!! test
Parsoid-centric test: Whitespace in ext- and wiki-links should be preserved
!! input
* {{BASEPAGENAME}}
* {{SUBPAGENAME}}
* {{SUBPAGENAMEE}}
+* {{ROOTPAGENAME}}
+* {{ROOTPAGENAMEE}}
* {{BASEPAGENAME}}
* {{BASEPAGENAMEE}}
* {{TALKPAGENAME}}
</li><li> Parser_test
</li><li> Parser test
</li><li> Parser_test
+</li><li> Parser test
+</li><li> Parser_test
</li><li> Talk:Parser test
</li><li> Talk:Parser_test
</li><li> Parser test
"\$wgContLang->getCode() (" . $wgContLang->getCode() . ")" );
}
+ // HACK: Call getLanguage() so the real $wgContLang is cached as the user language
+ // rather than our fake one. This is to avoid breaking other, unrelated tests.
+ RequestContext::getMain()->getLanguage();
+
$langCode = 'en'; # For mainpage to be 'Main Page'
$langObj = Language::factory( $langCode );
foreach ( self::$additionalOptions as $option => $default ) {
$this->longOptions[$option] = $option . 'Handler';
}
-
}
public static function main( $exit = true ) {
EOT;
}
-
}
protected function getNewTempFile() {
$fname = tempnam( wfTempDir(), 'MW_PHPUnit_' . get_class( $this ) . '_' );
$this->tmpfiles[] = $fname;
+
return $fname;
}
// where temporary directory creation is bundled and can be improved
unlink( $fname );
$this->assertTrue( wfMkdirParents( $fname ) );
+
return $fname;
}
* Stub. If a test needs to add additional data to the database, it should
* implement this method and do so
*/
- function addDBData() {}
+ function addDBData() {
+ }
private function addCoreDBData() {
# disabled for performance
'page_touched' => $this->db->timestamp(),
'page_latest' => 0,
'page_len' => 0 ), __METHOD__, array( 'IGNORE' ) );
-
}
User::resetIdByNameCache();
$user->saveSettings();
}
-
//Make 1 page with 1 revision
$page = WikiPage::factory( Title::newFromText( 'UTPage' ) );
if ( !$page->getId() == 0 ) {
if ( ( $db->getType() == 'oracle' || !self::$useTemporaryTables ) && self::$reuseDB ) {
CloneDatabase::changePrefix( $prefix );
+
return;
} else {
$dbClone->cloneTableStructure();
private static function unprefixTable( $tableName ) {
global $wgDBprefix;
+
return substr( $tableName, strlen( $wgDBprefix ) );
}
unset( $tables['searchindex_segments'] );
$tables = array_flip( $tables );
}
+
return $tables;
}
if ( isset( MediaWikiPHPUnitCommand::$additionalOptions[$offset] ) ) {
return MediaWikiPHPUnitCommand::$additionalOptions[$offset];
}
-
}
public function setCliArg( $offset, $value ) {
MediaWikiPHPUnitCommand::$additionalOptions[$offset] = $value;
-
}
/**
) {
$wikitextNS = $ns;
+
return $wikitextNS;
}
}
if ( !$loaded ) {
$this->markTestSkipped( "PHP extension '$extName' is not loaded, skipping." );
}
+
return $loaded;
}
$this->assertInstanceOf( $expected, $pokemons, $message );
}
-
}
You are running these tests directly from phpunit. You may not have all globals correctly set.
Running phpunit.php instead is recommended.
EOF;
- require_once ( __DIR__ . "/phpunit.php" );
+ require_once( __DIR__ . "/phpunit.php" );
}
// Output a notice when running with older versions of PHPUnit
$wgContLang = Language::factory( 'es' );
$wgLang = Language::factory( 'fr' );
- $status = $page->doEditContent( new WikitextContent( '{{:{{int:history}}}}' ), 'Test code for bug 14404', 0, false, $user );
+ $page->doEditContent( new WikitextContent( '{{:{{int:history}}}}' ), 'Test code for bug 14404', 0, false, $user );
$templates1 = $title->getTemplateLinksFrom();
$wgLang = Language::factory( 'de' );
$page->mPreparedEdit = false; // In order to force the rerendering of the same wikitext
// We need an edit, a purge is not enough to regenerate the tables
- $status = $page->doEditContent( new WikitextContent( '{{:{{int:history}}}}' ), 'Test code for bug 14404', EDIT_UPDATE, false, $user );
+ $page->doEditContent( new WikitextContent( '{{:{{int:history}}}}' ), 'Test code for bug 14404', EDIT_UPDATE, false, $user );
$templates2 = $title->getTemplateLinksFrom();
$this->assertEquals( $templates1, $templates2 );
$this->assertEquals( $templates1[0]->getFullText(), 'Historial' );
}
-
}
* debug function : dump the ipblocks table
*/
function dumpBlocks() {
- $v = $this->db->query( 'SELECT * FROM unittest_ipblocks' );
+ $v = $this->db->select( 'ipblocks', '*' );
print "Got " . $v->numRows() . " rows. Full dump follow:\n";
foreach ( $v as $row ) {
print_r( $row );
$this->assertTrue( $this->block->equals( Block::newFromTarget( 'UTBlockee' ) ), "newFromTarget() returns the same block as the one that was made" );
$this->assertTrue( $this->block->equals( Block::newFromID( $this->blockId ) ), "newFromID() returns the same block as the one that was made" );
-
}
/**
// delta to stop one-off errors when things happen to go over a second mark.
$delta = abs( $this->madeAt - $this->block->mTimestamp );
$this->assertLessThan( 2, $delta, "If no timestamp is specified, the block is recorded as time()" );
-
}
/**
$u->addToDatabase();
unset( $u );
-
// Sanity check
$this->assertNull(
Block::newFromTarget( $username ),
$this->cdbAssert( "PHP error", $key, $v1, $value );
$this->cdbAssert( "DBA error", $key, $v2, $value );
}
-
}
private function randomString() {
for ( $j = 0; $j < $len; $j++ ) {
$s .= chr( mt_rand( 0, 255 ) );
}
+
return $s;
}
array( 'en', 'A', 'Aꦲ' ),
);
}
+
/**
* Opposite of testIsPrefix
*
$col = Collation::factory( $collation );
$this->assertEquals( $firstLetter, $col->getFirstLetter( $string ) );
}
+
function firstLetterProvider() {
return array(
array( 'uppercase', 'Abc', 'A' ),
protected function setUp() {
if ( !extension_loaded( 'xdiff' ) ) {
$this->markTestSkipped( 'The xdiff extension is not available' );
+
return;
}
if ( !function_exists( 'xdiff_string_rabdiff' ) ) {
$this->markTestSkipped( 'The version of xdiff extension is lower than 1.5.0' );
+
return;
}
if ( !extension_loaded( 'hash' ) && !extension_loaded( 'mhash' ) ) {
$this->markTestSkipped( 'Neither the hash nor mhash extension is available' );
+
return;
}
parent::setUp();
$this->object->getOptions()
);
}
-
}
$sampleUTF = "Östergötland_coat_of_arms.png";
-
//mb_substr
$substr_params = array(
array( 0, 0 ),
);
}
-
//mb_strlen
$this->assertEquals(
mb_strlen( $sampleUTF ),
'Fallback mb_strlen'
);
-
//mb_str(r?)pos
$strpos_params = array(
//array( 'ter' ),
'Fallback mb_strrpos with params ' . implode( ', ', $old_param_set )
);
}
-
}
$old_wgDebugTimestamps = $wgDebugTimestamps;
$wgDebugTimestamps = false;
-
wfDebug( "This is a normal string" );
$this->assertEquals( "This is a normal string", file_get_contents( $wgDebugLogFile ) );
unlink( $wgDebugLogFile );
$this->assertEquals( "This is nöt an ASCII string", file_get_contents( $wgDebugLogFile ) );
unlink( $wgDebugLogFile );
-
wfDebug( "\00305This has böth UTF and control chars\003" );
$this->assertEquals( " 05This has böth UTF and control chars ", file_get_contents( $wgDebugLogFile ) );
unlink( $wgDebugLogFile );
$this->assertGreaterThan( 5000000, preg_replace( '/\D/', '', file_get_contents( $wgDebugLogFile ) ) );
unlink( $wgDebugLogFile );
-
$wgDebugLogFile = $old_log_file;
$wgDebugTimestamps = $old_wgDebugTimestamps;
}
$this->assertEquals( $var1, 2, 'var1 is swapped' );
$this->assertEquals( $var2, 1, 'var2 is swapped' );
-
}
function testWfPercentTest() {
array( "$p//nds-nl.wikipedia.org", array( 'nl.wikipedia.org' ), true, "Substrings of domains match while they shouldn't, $pDesc URL" ),
) );
}
+
return $a;
}
public static function provideWfShellMaintenanceCmdList() {
global $wgPhpCli;
+
return array(
array( 'eval.php', array( '--help', '--test' ), array(),
"'$wgPhpCli' 'eval.php' '--help' '--test'",
public static function provideWfIsBadImageList() {
$blacklist = '* [[File:Bad.jpg]] except [[Nasty page]]';
+
return array(
array( 'Bad.jpg', false, $blacklist, true,
'Called on a bad image' ),
$url .= '#' . $fragment;
}
-
$cases[] = array(
$parts,
$url,
$x[] = array( $base, $str );
}
+
return $x;
}
}
}
}
+
return $retval;
}
}
if ( $n > 0 ) {
return self::intermediateFunction( $level, $n - 1 );
}
+
return wfGetCaller( $level );
}
array( '1k', 1024, 'One kb lowercased' ),
);
}
-
}
public static function provideNormalTimestamps() {
$t = gmmktime( 12, 34, 56, 1, 15, 2001 );
+
return array(
// TS_UNIX
array( $t, TS_MW, '20010115123456', 'TS_UNIX to TS_MW' ),
public static function provideHooks() {
$i = new NothingClass();
+
return array(
array( 'Object and method', array( $i, 'someNonStatic' ), 'changed-nonstatic', 'changed-nonstatic' ),
array( 'Object and no method', array( $i ), 'changed-onevent', 'original' ),
array( 'Class::method static call', array( 'NothingClass::someStatic' ), 'changed-static', 'original' ),
array( 'Global function', array( 'NothingFunction' ), 'changed-func', 'original' ),
array( 'Global function with data', array( 'NothingFunctionData', 'data' ), 'data', 'original' ),
- array( 'Closure', array( function( &$foo, $bar ) {
- $foo = 'changed-closure';
- return true;
- } ), 'changed-closure', 'original' ),
- array( 'Closure with data', array( function( $data, &$foo, $bar ) {
- $foo = $data;
- return true;
- }, 'data' ), 'data', 'original' )
+ array( 'Closure', array( function ( &$foo, $bar ) {
+ $foo = 'changed-closure';
+
+ return true;
+ } ), 'changed-closure', 'original' ),
+ array( 'Closure with data', array( function ( $data, &$foo, $bar ) {
+ $foo = $data;
+
+ return true;
+ }, 'data' ), 'data', 'original' )
);
}
}
public function testFalseReturn() {
- Hooks::register( 'MediaWikiHooksTest001', function( &$foo ) { return false; } );
- Hooks::register( 'MediaWikiHooksTest001', function( &$foo ) { $foo = 'test'; return true; } );
+ Hooks::register( 'MediaWikiHooksTest001', function ( &$foo ) {
+ return false;
+ } );
+ Hooks::register( 'MediaWikiHooksTest001', function ( &$foo ) {
+ $foo = 'test';
+
+ return true;
+ } );
$foo = 'original';
Hooks::run( 'MediaWikiHooksTest001', array( &$foo ) );
$this->assertSame( 'original', $foo, 'Hooks continued processing after a false return.' );
* @expectedException FatalError
*/
public function testFatalError() {
- Hooks::register( 'MediaWikiHooksTest001', function() { return 'test'; } );
+ Hooks::register( 'MediaWikiHooksTest001', function () {
+ return 'test';
+ } );
Hooks::run( 'MediaWikiHooksTest001', array() );
}
}
function NothingFunction( &$foo, &$bar ) {
$foo = 'changed-func';
+
return true;
}
function NothingFunctionData( $data, &$foo, &$bar ) {
$foo = $data;
+
return true;
}
public static function someStatic( &$foo, &$bar ) {
$foo = 'changed-static';
+
return true;
}
$this->calls++;
$foo = 'changed-nonstatic';
$bar = 'changed-nonstatic';
+
return true;
}
public function onMediaWikiHooksTest001( &$foo, &$bar ) {
$this->calls++;
$foo = 'changed-onevent';
+
return true;
}
public function someNonStaticWithData( $data, &$foo, &$bar ) {
$this->calls++;
$foo = $data;
+
return true;
}
}
foreach ( $types as $type ) {
$cases[] = array( $type );
}
+
return $cases;
}
isset( $case[3] ) ? $case[3] : ''
);
}
+
return $ret;
}
'Allow special case "step=any".'
);
}
-
}
throw new MWException( __METHOD__ . ': allow_url_fopen needs to be enabled for pure PHP' .
' http requests to work. If possible, curl should be used instead. See http://php.net/curl.' );
}
+
return new PhpHttpRequestTester( $url, $options );
default:
}
'tg' => new ReplacementArray()
);
}
-
}
class LanguageToTest extends Language {
$po->addImage( "Foo.png" );
-
$this->assertLinksUpdate( $t, $po, 'imagelinks', 'il_to', 'il_from = 111', array(
array( 'Foo.png' ),
) );
$po->addLanguageLink( Title::newFromText( "en:Foo" )->getFullText() );
-
$this->assertLinksUpdate( $t, $po, 'langlinks', 'll_lang, ll_title', 'll_from = 111', array(
array( 'En', 'Foo' ),
) );
public static function someMethod() {
return func_get_args();
}
-
}
class MWBlankClass {
public function testGetAssociated() {
$this->assertEquals( NS_TALK, MWNamespace::getAssociated( NS_MAIN ) );
$this->assertEquals( NS_MAIN, MWNamespace::getAssociated( NS_TALK ) );
-
}
### Exceptions with getAssociated()
NS_SPECIAL, NS_MEDIA,
"NS_SPECIAL and NS_MEDIA are different subject namespaces"
);
-
}
/**
'$wgContentNamespaces is an array with only NS_MAIN by default'
);
-
# test !is_array( $wgcontentNamespaces )
$wgContentNamespaces = '';
$this->assertEquals( NS_MAIN, MWNamespace::getContentNamespaces() );
$matches = $router->parse( "/wiki/Foo" );
$this->assertEquals( $matches, array( 'title' => 'bar%20$1' ) );
}
-
}
, $this->context
, $preferences
);
+
return $preferences;
}
}
for ( $i = 1; $i <= $num; $i++ ) {
$ret[] = array( $i );
}
+
return $ret;
}
$ret[] = array( $day[0], $month[0] );
}
}
+
return $ret;
}
}
$context->setTitle( $curTitle );
$this->assertTrue( $curTitle->equals( $context->getWikiPage()->getTitle() ),
"When a title is updated the WikiPage should be purged and recreated on-demand with the new title." );
-
}
public function testImportScopedSession() {
$this->assertEquals( $sinfo['userId'], $context->getUser()->getId(), "Correct context user ID." );
$this->assertEquals( 'UnitTestContextUser', $context->getUser()->getName(), "Correct context user name." );
- unset ( $sc ); // restore previous context
+ unset( $sc ); // restore previous context
$info = $context->exportSession();
$this->assertEquals( $oInfo['ip'], $info['ip'], "Correct initial IP address." );
*/
public static function resourceLoaderRegisterModules( &$resourceLoader ) {
self::$resourceLoaderRegisterModulesHook = true;
+
return true;
}
self::$resourceLoaderRegisterModulesHook = false;
$resourceLoader = new ResourceLoader();
$this->assertTrue( self::$resourceLoaderRegisterModulesHook );
+
return $resourceLoader;
}
/* Stubs */
-class ResourceLoaderTestModule extends ResourceLoaderModule {}
+class ResourceLoaderTestModule extends ResourceLoaderModule {
+}
/* Hooks */
global $wgHooks;
$this->assertTrue( true ); // ok
}
}
-
}
// for immutable content like wikitext, this should be the same object
$this->assertSame( $content, $content2 );
}
-
}
class RevisionTestModifyableContent extends TextContent {
public function setText( $text ) {
$this->mText = $text;
}
-
}
class RevisionTestModifyableContentHandler extends TextContentHandler {
array( array( 'foo.' => 'baz' ), 'foo.=baz', 'A . is allowed as last character' ),
array( array( 'foo6' => 'baz' ), 'foo6=baz', 'Numbers are allowed' ),
-
# This bit is more relaxed than XML rules, but some extensions use
# it, like ProofreadPage (see bug 27539)
array( array( '1foo' => 'baz' ), '1foo=baz', 'Leading numbers are allowed' ),
$message
);
}
-
}
break;
}
}
+
return array(
'suffix' => $site,
'lang' => $lang,
$escaped .= $char;
}
}
+
return $escaped;
}
$user = new User();
$user->mRights = array( 'createpage', 'edit', 'purge' );
- $status = $page->doEditContent( new WikitextContent( '{{Categorising template}}' ), 'Create a page with a template', 0, false, $user );
+ $page->doEditContent( new WikitextContent( '{{Categorising template}}' ), 'Create a page with a template', 0, false, $user );
$this->assertEquals(
array()
, $title->getParentCategories()
);
$template = WikiPage::factory( Title::newFromText( 'Template:Categorising template' ) );
- $status = $template->doEditContent( new WikitextContent( '[[Category:Solved bugs]]' ), 'Add a category through a template', 0, false, $user );
+ $template->doEditContent( new WikitextContent( '[[Category:Solved bugs]]' ), 'Add a category through a template', 0, false, $user );
// Run the job queue
JobQueueGroup::destroySingletons();
, $title->getParentCategories()
);
}
-
}
}
}
$this->user->saveSettings();
-
}
}
* @expectedException TimestampException
*/
function testInvalidParse() {
- $timestamp = new MWTimestamp( "This is not a timestamp." );
+ new MWTimestamp( "This is not a timestamp." );
}
/**
$title = Title::newFromText( $title );
$this->assertEquals( $expectedBool, $title->isWikitextPage() );
}
-
}
$this->user = $this->userUser;
}
-
}
function setUserPerm( $perm ) {
$this->title->userCan( $action, $this->user, true ) );
$this->assertEquals( $check[$action][3],
$this->title->quickUserCan( $action, $this->user ) );
-
# count( User::getGroupsWithPermissions( $action ) ) < 1
}
}
$this->title->userCan( 'edit', $this->user ) );
$this->assertEquals( array(),
$this->title->getUserPermissionsErrors( 'edit', $this->user ) );
-
}
function testActionPermissions() {
$this->assertEquals( true,
$this->title->userCan( 'create', $this->user ) );
-
$this->setUserPerm( array( 'createpage' ) );
$this->assertEquals( array( array( 'titleprotected', 'Useruser', 'test' ) ),
$this->title->getUserPermissionsErrors( 'create', $this->user ) );
$this->title->getUserPermissionsErrors( 'move-target', $this->user ) );
$this->assertEquals( false,
$this->title->userCan( 'move-target', $this->user ) );
-
}
function testUserBlock() {
global $wgLocalTZoffset;
$wgLocalTZoffset = -60;
$this->user->mBlockedby = $this->user->getName();
- $this->user->mBlock = new Block( '127.0.8.1', 0, 1, 'no reason given', $now, 0, 10 );
+ $this->user->mBlock = new Block( '127.0.8.1', 0, $this->user->getId(),
+ 'no reason given', $now, 0, 10 );
$this->assertEquals( array( array( 'blockedtext',
'[[User:Useruser|Useruser]]', 'no reason given', '127.0.0.1',
'Useruser', null, '23:00, 31 December 1969', '127.0.8.1',
$wgLang->timeanddate( wfTimestamp( TS_MW, $now ), true ) ) ),
$this->title->getUserPermissionsErrors( 'move-target', $this->user ) );
-
# $action != 'read' && $action != 'createaccount' && $user->isBlockedFrom( $this )
# $user->blockedFor() == ''
# $user->mBlock->mExpiry == 'infinity'
foreach ( $errors as $error ) {
$result[] = $error[0];
}
+
return $result;
}
$text = preg_replace( '!\s*(</p>)!sm', '\1', $text ); # don't let tidy confuse us
$this->assertEquals( $expectedHtml, $text );
+
return $po;
}
$this->assertEquals( $expected, $text );
}
-
}
$page = new WikiPage( $page->getTitle() );
$this->assertEquals( 'WikitextContentHandler', get_class( $page->getContentHandler() ) );
}
-
}
$token = $a['token'];
// Finally create the account
- $ret = $this->doApiRequest( array(
- 'action' => 'createaccount',
- 'name' => 'Apitestnew',
- 'password' => $password,
- 'token' => $token,
- 'email' => 'test@domain.test',
- 'realname' => 'Test Name' ), $ret[2]
+ $ret = $this->doApiRequest(
+ array(
+ 'action' => 'createaccount',
+ 'name' => 'Apitestnew',
+ 'password' => $password,
+ 'token' => $token,
+ 'email' => 'test@domain.test',
+ 'realname' => 'Test Name'
+ ),
+ $ret[2]
);
$result = $ret[0];
* @expectedException UsageException
*/
function testNoName() {
- $ret = $this->doApiRequest( array(
+ $this->doApiRequest( array(
'action' => 'createaccount',
'token' => LoginForm::getCreateaccountToken(),
'password' => 'password',
* @expectedException UsageException
*/
function testNoPassword() {
- $ret = $this->doApiRequest( array(
+ $this->doApiRequest( array(
'action' => 'createaccount',
'name' => 'testName',
'token' => LoginForm::getCreateaccountToken(),
* @group medium
*/
class ApiBlockTest extends ApiTestCase {
-
protected function setUp() {
parent::setUp();
$this->doLogin();
* previously always considered valid (bug 34212).
*/
function testMakeNormalBlock() {
-
$data = $this->getTokens();
$user = User::newFromName( 'UTApiBlockee' );
$key = array_pop( $keys );
$pageinfo = $data[0]['query']['pages'][$key];
- $data = $this->doApiRequest( array(
+ $this->doApiRequest( array(
'action' => 'block',
'user' => 'UTApiBlockee',
'reason' => 'Some reason',
$this->assertEquals( 'UTApiBlockee', (string)$block->getTarget() );
$this->assertEquals( 'Some reason', $block->mReason );
$this->assertEquals( 'infinity', $block->mExpiry );
-
}
/**
if ( $text !== null ) {
if ( $text === '' ) {
// can't create an empty page, so create it with some content
- list( $re, , ) = $this->doApiRequestWithToken( array(
+ $this->doApiRequestWithToken( array(
'action' => 'edit',
'title' => $name,
'text' => '(dummy)', ) );
}
- list( $re, , ) = $this->doApiRequestWithToken( array(
+ list( $re ) = $this->doApiRequestWithToken( array(
'action' => 'edit',
'title' => $name,
'text' => $text, ) );
}
// -- try append/prepend --------------------------------------------
- list( $re, , ) = $this->doApiRequestWithToken( array(
+ list( $re ) = $this->doApiRequestWithToken( array(
'action' => 'edit',
'title' => $name,
$op . 'text' => $append, ) );
// try to save edit, expect conflict
try {
- list( $re, , ) = $this->doApiRequestWithToken( array(
+ $this->doApiRequestWithToken( array(
'action' => 'edit',
'title' => $name,
'text' => 'nix bar!',
// try again, without following the redirect. Should fail.
try {
- list( $re, , ) = $this->doApiRequestWithToken( array(
+ $this->doApiRequestWithToken( array(
'action' => 'edit',
'title' => $rname,
'text' => 'nix bar!',
$mapping[$key] = 'unused';
}
}
+
return $mapping;
}
'optionname' => null,
'optionvalue' => null,
);
+
return array_merge( $request, $custom );
}
private function executeQuery( $request ) {
$this->mContext->setRequest( new FauxRequest( $request, true, $this->mSession ) );
$this->mTested->execute();
+
return $this->mTested->getResult()->getData();
}
} catch ( UsageException $e ) {
$this->assertEquals( 'notloggedin', $e->getCodeString() );
$this->assertEquals( 'Anonymous users cannot change preferences', $e->getMessage() );
+
return;
}
$this->fail( "UsageException was not thrown" );
} catch ( UsageException $e ) {
$this->assertEquals( 'nooptionname', $e->getCodeString() );
$this->assertEquals( 'The optionname parameter must be set', $e->getMessage() );
+
return;
}
$this->fail( "UsageException was not thrown" );
} catch ( UsageException $e ) {
$this->assertEquals( 'nochanges', $e->getCodeString() );
$this->assertEquals( 'No changes were requested', $e->getMessage() );
+
return;
}
$this->fail( "UsageException was not thrown" );
$somePage = mt_rand();
try {
- $data = $this->doApiRequest( array(
+ $this->doApiRequest( array(
'action' => 'parse',
'page' => $somePage ) );
"Parse request for nonexistent page must give 'missingtitle' error: " . var_export( $ex->getMessageArray(), true ) );
}
}
-
}
$this->assertArrayHasKey( $pages[$v['title']], $v );
}
}
-
}
protected function editPage( $pageName, $text, $summary = '', $defaultNs = NS_MAIN ) {
$title = Title::newFromText( $pageName, $defaultNs );
$page = WikiPage::factory( $title );
+
return $page->doEditContent( ContentHandler::makeContent( $text, $title ), $summary );
}
$session['wsEditToken'] = $session['wsToken'];
// add token to request parameters
$params['token'] = md5( $session['wsToken'] ) . User::EDIT_TOKEN_SUFFIX;
+
return $this->doApiRequest( $params, $session, false, $user );
} else {
throw new Exception( "request data not in right format" );
'titles' => 'Main Page',
'intoken' => 'edit|delete|protect|move|block|unblock|watch',
'prop' => 'info' ), $session, false, $user->user );
+
return $data;
}
}
class MockApi extends ApiBase {
- public function execute() {}
+ public function execute() {
+ }
- public function getVersion() {}
+ public function getVersion() {
+ }
- public function __construct() {}
+ public function __construct() {
+ }
public function getAllowedParams() {
return array(
if ( $user !== null ) {
$context->setUser( $user );
}
+
return $context;
}
}
// see if it now doesn't exist; reload
$title = Title::newFromText( $title->getText(), NS_FILE );
}
+
return !( $title && $title instanceof Title && $title->exists() );
}
foreach ( $dupes as $dupe ) {
$success &= $this->deleteFileByTitle( $dupe->getTitle() );
}
+
return $success;
}
);
return true;
-
}
function fakeUploadChunk( $fieldName, $fileName, $type, & $chunkData ) {
function clearFakeUploads() {
$_FILES = array();
}
-
}
* This is pretty sucky... needs to be prettified.
*/
class ApiUploadTest extends ApiTestCaseUpload {
-
/**
* Testing login
* XXX this is a funny way of getting session context
$this->assertArrayHasKey( 'lgtoken', $result['login'] );
$this->assertNotEmpty( $session, 'API Login must return a session' );
- return $session;
+ return $session;
}
/**
$this->deleteFileByFileName( $fileName );
$this->deleteFileByContent( $filePath );
-
if ( !$this->fakeUploadFile( 'file', $fileName, $mimeType, $filePath ) ) {
$this->markTestIncomplete( "Couldn't upload file!\n" );
}
$exception = false;
try {
- list( $result, $request, $session ) = $this->doApiRequestWithToken( $params, $session,
+ list( $result, , $session ) = $this->doApiRequestWithToken( $params, $session,
self::$users['uploader']->user );
} catch ( UsageException $e ) {
$exception = true;
$this->assertEquals( 'Success', $result['upload']['result'] );
$this->assertFalse( $exception );
-
// second upload with the same content (but different name)
if ( !$this->fakeUploadFile( 'file', $fileNames[1], $mimeType, $filePaths[0] ) ) {
$exception = false;
try {
- list( $result, $request, $session ) = $this->doApiRequestWithToken( $params, $session,
+ list( $result ) = $this->doApiRequestWithToken( $params, $session,
self::$users['uploader']->user ); // FIXME: leaks a temporary file
} catch ( UsageException $e ) {
$exception = true;
unlink( $filePaths[0] );
}
-
/**
* @depends testLogin
*/
$exception = false;
try {
- list( $result, $request, $session ) = $this->doApiRequestWithToken( $params, $session,
+ list( $result, , $session ) = $this->doApiRequestWithToken( $params, $session,
self::$users['uploader']->user ); // FIXME: leaks a temporary file
} catch ( UsageException $e ) {
$exception = true;
$this->clearFakeUploads();
$exception = false;
try {
- list( $result, $request, $session ) = $this->doApiRequestWithToken( $params, $session,
+ list( $result ) = $this->doApiRequestWithToken( $params, $session,
self::$users['uploader']->user );
} catch ( UsageException $e ) {
$exception = true;
if ( !$chunkSessionKey ) {
// Upload fist chunk ( and get the session key )
try {
- list( $result, $request, $session ) = $this->doApiRequestWithToken( $params, $session,
+ list( $result, , $session ) = $this->doApiRequestWithToken( $params, $session,
self::$users['uploader']->user );
} catch ( UsageException $e ) {
$this->markTestIncomplete( $e->getMessage() );
$this->assertEquals( $resultOffset, $params['offset'] );
// Upload current chunk
try {
- list( $result, $request, $session ) = $this->doApiRequestWithToken( $params, $session,
+ list( $result, , $session ) = $this->doApiRequestWithToken( $params, $session,
self::$users['uploader']->user );
} catch ( UsageException $e ) {
$this->markTestIncomplete( $e->getMessage() );
$this->clearFakeUploads();
$exception = false;
try {
- list( $result, $request, $session ) = $this->doApiRequestWithToken( $params, $session,
+ list( $result ) = $this->doApiRequestWithToken( $params, $session,
self::$users['uploader']->user );
} catch ( UsageException $e ) {
$exception = true;
* @todo This test suite is severly broken and need a full review
*/
class ApiWatchTest extends ApiTestCase {
-
protected function setUp() {
parent::setUp();
$this->doLogin();
/**
*/
function testGetRollbackToken() {
-
- $pageinfo = $this->getTokens();
+ $this->getTokens();
if ( !Title::newFromText( 'Help:UTPage' )->exists() ) {
$this->markTestSkipped( "The article [[Help:UTPage]] does not exist" ); //TODO: just create it?
$this->assertArrayHasKey( 'delete', $data[0] );
$this->assertArrayHasKey( 'title', $data[0]['delete'] );
- $data = $this->doApiRequest( array(
+ $this->doApiRequest( array(
'action' => 'query',
'list' => 'watchlist' ) );
foreach ( $filenames as $filename ) {
$this->{$imageWriteMethod}( $this->getImageSpec(), $format, $filename );
}
+
return $filenames;
}
}
return $filenames;
-
}
array( 'x' => $originX, 'y' => $originY - $radius )
);
$draws[] = $draw;
-
}
$spec['draws'] = $draws;
foreach ( $shape as $point ) {
$points[] = $point['x'] . ',' . $point['y'];
}
+
return join( " ", $points );
}
}
$tSpec['draws'][] = $tDraw;
}
+
return $tSpec;
}
$command = wfEscapeShellArg( $wgImageMagickConvertCommand ) . " " . implode( " ", $args );
$retval = null;
wfShellExec( $command, $retval );
+
return ( $retval === 0 );
}
for ( $i = 0; $i <= 2; $i++ ) {
$components[] = mt_rand( 0, 255 );
}
+
return 'rgb(' . join( ', ', $components ) . ')';
}
for ( $i = 0; $i < $count; $i += 2 ) {
$pairs[] = array( $lines[$i], $lines[$i + 1] );
}
+
return $pairs;
}
return $lines;
}
-
}
$this->assertInternalType( 'array', unserialize( $data ) );
$this->assertGreaterThan( 0, count( (array)$data ) );
-
}
-
}
// put 'continue' params at the end - lazy method
$a = strpos( $a, 'continue' ) !== false ? 'zzz ' . $a : $a;
$b = strpos( $b, 'continue' ) !== false ? 'zzz ' . $b : $b;
+
return strcmp( $a, $b );
} );
$reqStr = http_build_query( $request );
if ( $expectedCount > $count ) {
print "***** $id Finished early in $count turns. $expectedCount was expected\n";
}
+
return $result;
} elseif ( !$useContinue ) {
$this->assertFalse( 'Non-smart query must be requested all at once' );
'action' => 'query',
'titles' => 'Project:articleA|article_B' ) );
-
$this->assertArrayHasKey( 'query', $data[0] );
$this->assertArrayHasKey( 'normalized', $data[0]['query'] );
),
$data[0]['query']['normalized'][1]
);
-
}
function testTitlesAreRejectedIfInvalid() {
$this->assertArrayHasKey( 'missing', $data[0]['query']['pages'][-2] );
$this->assertArrayHasKey( 'invalid', $data[0]['query']['pages'][-1] );
}
-
}
* @file
*/
-
/** This class has some common functionality for testing query module
*/
abstract class ApiQueryTestBase extends ApiTestCase {
$request = array_merge_recursive( $request, $req );
$this->mergeExpected( $expected, $exp );
}
+
return array( $request, $expected );
}
$this->assertArrayHasKey( 1, $v, self::PARAM_ASSERT );
$this->assertType( 'array', $v[0], self::PARAM_ASSERT );
$this->assertType( 'array', $v[1], self::PARAM_ASSERT );
+
return $v;
}
for ( $i = $firstKey; $i <= $lastKey; $i++ ) {
$expected["cache-key-$i"] = array( "prop-$i" => "value-$i" );
}
+
return $expected;
}
* @expectedException MWException
*/
function testConstructorGivenInvalidValue( $maxSize ) {
- $c = new ProcessCacheLRUTestable( $maxSize );
+ new ProcessCacheLRUTestable( $maxSize );
}
/**
$cache->getCache(),
"Filling a $cacheMaxEntries entries cache with $entryToFill entries"
);
-
}
/**
),
$cache->getCache()
);
-
}
-
}
/**
*/
public function unserializeContent( $blob, $format = null ) {
$d = unserialize( $blob );
+
return new DummyContentForTesting( $d );
}
public function testEquals( Content $a, Content $b = null, $equal = false ) {
$this->assertEquals( $equal, $a->equals( $b ) );
}
-
}
array( new JavaScriptContent( "hallo" ), new JavaScriptContent( "HALLO" ), false ),
);
}
-
}
$this->assertEquals( $expectedNative, $converted->getNativeData() );
}
}
-
}
/*
public function testGetUndoContent( Revision $current, Revision $undo, Revision $undoafter = null ) {}
*/
-
}
),
"DELETE FROM table " .
"WHERE field IN (" .
- "SELECT field_join FROM table_join WHERE alias = 'text'" .
+ "SELECT field_join FROM table_join WHERE alias = 'text'" .
")"
),
array(
),
"DELETE FROM table " .
"WHERE field IN (" .
- "SELECT field_join FROM table_join " .
+ "SELECT field_join FROM table_join " .
")"
),
);
"INSERT IGNORE INTO table " .
"(field,field2) " .
"VALUES " .
- "('text','2')," .
- "('multi','3')"
+ "('text','2')," .
+ "('multi','3')"
),
);
}
"INSERT INTO insert_table " .
"(field_insert,field) " .
"SELECT field_select,field2 " .
- "FROM select_table"
+ "FROM select_table"
),
array(
array(
"INSERT INTO insert_table " .
"(field_insert,field) " .
"SELECT field_select,field2 " .
- "FROM select_table " .
- "WHERE field = '2'"
+ "FROM select_table " .
+ "WHERE field = '2'"
),
array(
array(
"INSERT IGNORE INTO insert_table " .
"(field_insert,field) " .
"SELECT field_select,field2 " .
- "FROM select_table " .
- "WHERE field = '2' " .
- "ORDER BY field"
+ "FROM select_table " .
+ "WHERE field = '2' " .
+ "ORDER BY field"
),
);
}
"DELETE FROM replace_table " .
"WHERE ( field='text' ); " .
"INSERT INTO replace_table " .
- "(field,field2) " .
- "VALUES ('text','text2')"
+ "(field,field2) " .
+ "VALUES ('text','text2')"
),
array(
array(
"DELETE FROM module_deps " .
"WHERE ( md_module='module' AND md_skin='skin' ); " .
"INSERT INTO module_deps " .
- "(md_module,md_skin,md_deps) " .
- "VALUES ('module','skin','deps')"
+ "(md_module,md_skin,md_deps) " .
+ "VALUES ('module','skin','deps')"
),
array(
array(
"DELETE FROM module_deps " .
"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 " .
+ "(md_module,md_skin,md_deps) " .
+ "VALUES ('module','skin','deps'); " .
+ "DELETE FROM module_deps " .
"WHERE ( md_module='module2' AND md_skin='skin2' ); " .
"INSERT INTO module_deps " .
- "(md_module,md_skin,md_deps) " .
- "VALUES ('module2','skin2','deps2')"
+ "(md_module,md_skin,md_deps) " .
+ "VALUES ('module2','skin2','deps2')"
),
array(
array(
"DELETE FROM module_deps " .
"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 " .
+ "(md_module,md_skin,md_deps) " .
+ "VALUES ('module','skin','deps'); " .
+ "DELETE FROM module_deps " .
"WHERE ( md_module='module2' ) OR ( md_skin='skin2' ); " .
"INSERT INTO module_deps " .
- "(md_module,md_skin,md_deps) " .
- "VALUES ('module2','skin2','deps2')"
+ "(md_module,md_skin,md_deps) " .
+ "VALUES ('module2','skin2','deps2')"
),
array(
array(
function query( $sql, $fname = '', $tempIgnore = false ) {
$this->lastQuery = $sql;
+
return true;
}
$db->sourceFile( "$IP/tests/phpunit/data/db/sqlite/tables-$version.sql" );
$updater = DatabaseUpdater::newForDB( $db, false, $maint );
$updater->doUpdates( array( 'core' ) );
+
return $db;
}
}
$list = array_flip( $list );
sort( $list );
+
return $list;
}
$cols[$col->name] = $col;
}
ksort( $cols );
+
return $cols;
}
$indexes[$index->name] = $index;
}
ksort( $indexes );
+
return $indexes;
}
public function getLastSqls() {
$lastSqls = implode( '; ', $this->lastSqls );
$this->lastSqls = array();
+
return $lastSqls;
}
public function tableExists( $table, $fname = __METHOD__ ) {
$this->checkFunctionName( $fname );
+
return in_array( $table, (array)$this->tablesExists );
}
*/
protected function getRowInstance( array $data, $loadDefaults ) {
$class = $this->getRowClass();
+
return new $class( $this->getTableInstance(), $data, $loadDefaults );
}
*/
public function getTable() {
$class = $this->getTableClass();
+
return $class::singleton();
}
$db->ignoreErrors( false );
}
-
}
/**
'blob' => new stdClass()
);
}
-
}
-class TestORMRow extends ORMRow {}
+class TestORMRow extends ORMRow {
+}
class TestORMTable extends ORMTable {
protected function getFieldPrefix() {
return 'test_';
}
-
-
}
"Source file $source does not exist ($backendName)." );
$this->assertEquals( false, $this->backend->fileExists( array( 'src' => $dest ) ),
"Destination file $dest does not exist ($backendName)." );
+
return; // done
}
"Source file $source does not exist ($backendName)." );
$this->assertEquals( false, $this->backend->fileExists( array( 'src' => $dest ) ),
"Destination file $dest does not exist ($backendName)." );
+
return; // done
}
public static function provider_testPrepareAndClean() {
$base = self::baseStorePath();
+
return array(
array( "$base/unittest-cont1/e/a/z/some_file1.txt", true ),
array( "$base/unittest-cont2/a/z/some_file2.txt", true ),
// test helper wrapper for backend prepare() function
private function create( array $params ) {
$params['op'] = 'create';
+
return $this->backend->doQuickOperations( array( $params ) );
}
<?php
class FileRepoTest extends MediaWikiTestCase {
-
/**
* @expectedException MWException
*/
function testFileRepoConstructionOptionCanNotBeNull() {
- $f = new FileRepo();
+ new FileRepo();
}
/**
* @expectedException MWException
*/
function testFileRepoConstructionOptionCanNotBeAnEmptyArray() {
- $f = new FileRepo( array() );
+ new FileRepo( array() );
}
/**
* @expectedException MWException
*/
function testFileRepoConstructionOptionNeedNameKey() {
- $f = new FileRepo( array(
+ new FileRepo( array(
'backend' => 'foobar'
) );
}
* @expectedException MWException
*/
function testFileRepoConstructionOptionNeedBackendKey() {
- $f = new FileRepo( array(
+ new FileRepo( array(
'name' => 'foobar'
) );
}
$result = $this->repo->store( $srcPath, 'temp', $dstRel, $flags );
$result->value = $this->repo->getVirtualUrl( 'temp' ) . '/' . $dstUrlRel;
$this->createdFiles[] = $result->value;
+
return $result;
}
if ( !( $this->$q instanceof JobQueueDB ) ) {
$this->$q->setTestingPrefix( 'unittests-' . wfRandomString( 32 ) );
}
- } catch ( MWException $e ) {}; // unsupported? (@TODO: what if it was another error?)
+ } catch ( MWException $e ) {
+ }; // unsupported? (@TODO: what if it was another error?)
}
}
$jobs = iterator_to_array( $queue->getAllQueuedJobs() );
$this->assertEquals( 2, count( $jobs ), "Queue iterator size is correct ($desc)" );
-
$job1 = $queue->pop();
$this->assertFalse( $queue->isEmpty(), "Queue is not empty ($desc)" );
strtolower( FormatJson::encode( "\xf0\xa0\x80\x80" ) ),
'Test encoding an broken json_encode character (U+20000)'
);
-
}
public function testDecodeReturnType() {
$cases[] = array( $from, '"' . ( $leaveUnescaped ? $from : $to ) . '"' );
}
}
+
return $cases;
}
}
*/
protected function getNew( array $elements = array() ) {
$class = $this->getInstanceClass();
+
return new $class( $elements );
}
public function testOffsetSet( array $elements ) {
if ( $elements === array() ) {
$this->assertTrue( true );
+
return;
}
$this->assertArrayEquals( $list, $copy, true, true );
}
-
}
$res = $handler->getTiffByteOrder( $this->filePath . 'test.tiff' );
$this->assertEquals( 'LE', $res );
}
-
}
);
$this->assertEquals( $expected, $data );
}
-
-
}
$res = IPTC::Parse( $iptcData );
$this->assertEquals( array( '¼' ), $res['Keywords'] );
}
-
}
// encoded as just \xA9.
$expected = "© 2010 Bawolff";
-
$this->assertArrayHasKey( 'text', $meta );
$meta = $meta['text'];
$this->assertArrayHasKey( 'Copyright', $meta );
'greyscale-na-png.png' );
$this->assertEquals( 'greyscale', $meta['colorType'] );
}
-
}
$r = new XMLReader();
if ( !method_exists( $r, 'readInnerXML' ) ) {
$this->markTestSkipped( 'XMLReader::readInnerXML() does not exist (libxml >2.6.20 needed).' );
+
return;
}
$this->assertMetadata( $infile, $expected );
public static function provideSvgFiles() {
$base = __DIR__ . '/../../data/media';
+
return array(
array(
"$base/Wikimedia-logo.svg",
include( $xmpPath . $file[0] . '.result.php' );
$data[] = array( $xmp, $result, '[' . $file[0] . '.xmp] ' . $file[1] );
}
+
return $data;
}
$this->assertEquals( $expected, $actual );
}
-
}
array( '2001-05-12T15', null ),
array( '2001-12T15:13', null ),
);
-
}
-
}
$name = $this->getCliArg( 'use-bagostuff=' );
$this->cache = ObjectCache::newFromId( $name );
-
} else {
// no type defined - use simple hash
$this->cache = new HashBagOStuff;
$parserTester = new $parserTestClassName( $testsName );
$suite->addTestSuite( new ReflectionClass ( $parserTester ) );
}
+
return $suite;
}
}
$tmpGlobals['wgStyleDirectory'] = "$IP/skins";
}
-
foreach ( $tmpGlobals as $var => $val ) {
if ( array_key_exists( $var, $GLOBALS ) ) {
$this->savedInitialGlobals[$var] = $GLOBALS[$var];
// wfDebug( "Creating upload directory $dir\n" );
if ( file_exists( $dir ) ) {
wfDebug( "Already exists!\n" );
+
return $dir;
}
global $wgParserTestFiles;
$this->file = $wgParserTestFiles[0];
}
+
return new TestFileIterator( $this->file, $this );
}
}
$id++;
-
}
}
}
}
}
+
return $opts;
}
if ( substr( $opt, 0, 2 ) == '[[' ) {
return substr( $opt, 2, -2 );
}
+
return $opt;
}
'text' => '<pre style="margin-left: 1.6em">foo</pre>',
), $ret, 'callParserFunction works for {{#tag:pre|foo|style=margin-left: 1.6em}}' );
}
-
// TODO: Add tests for cleanSig() / cleanSigInSig(), getSection(), replaceSection(), getPreloadText()
}
# sort them numerically so we will compare simply that we received
# the expected matches.
sort( $matches );
+
return $matches;
}
$this->fetchIds( $this->search->searchTitle( 'smithee' ) ),
"Title power search failed" );
}
-
}
function update( $text, $title = 'Test', $id = 1 ) {
$u = new SearchUpdate( $id, $title, $text );
$u->doUpdate();
+
return array( MockSearch::$title, MockSearch::$text );
}
$this->assertContains( $path, $site->getPageUrl() );
$this->assertContains( $expected, $site->getPageUrl( $page ) );
}
-
}
$this->assertTrue( $copy->hasInternalId( $site->getInternalId() ) );
}
}
-
}
$sites = $store->getSites();
$this->assertEquals( 0, $sites->count() );
}
-
}
$this->assertEquals( $serialization, serialize( $newInstance ) );
}
-
}
$sitesTable->clear();
$sitesTable->saveSites( TestSites::getSites() );
}
-
}
/** return false if condition begin with 'rc_timestamp ' */
private static function filterOutRcTimestampCondition( $var ) {
return ( false === strpos( $var, 'rc_timestamp ' ) );
-
}
public function testRcNsFilter() {
array( NS_TALK, NS_MAIN ),
);
}
-
}
)
, $message
);
-
}
public static function provideSearchOptionsTests() {
foreach ( $opt as $name => $value ) {
$u->setOption( $name, $value );
}
+
return $u;
}
$pageTitle,
"Search term '{$term}' should not be expanded in Special:Search <title>"
);
-
}
}
* @group Database
*/
class UploadFromUrlTest extends ApiTestCase {
-
protected function setUp() {
parent::setUp();
$module->execute();
wfSetupSession( $sessionId );
+
return array( $module->getResultData(), $req );
}
$this->user->addGroup( 'users' );
-
$data = $this->doAsyncUpload( $token );
$this->assertEquals( $data[0]['upload']['result'], 'Warning' );
$this->assertFalse( (bool)$talk->getArticleID( Title::GAID_FOR_UPDATE ), 'User talk does not exist' );
- $data = $this->doApiRequest( array(
+ $this->doApiRequest( array(
'action' => 'upload',
'filename' => 'UploadFromUrlTest.png',
'url' => 'http://bits.wikimedia.org/skins-1.5/common/images/poweredby_mediawiki_88x31.png',
$exception = false;
try {
- $data = $this->doApiRequest( array(
+ $this->doApiRequest( array(
'action' => 'upload',
'filename' => 'UploadFromUrlTest.png',
'url' => 'http://bits.wikimedia.org/skins-1.5/common/images/poweredby_mediawiki_88x31.png',
$this->assertFalse( $job );
return;
-
/*
// Broken until using leavemessage with ignorewarnings is supported
$job->run();
return $data;
}
-
/**
*
*/
}
class UploadTestHandler extends UploadBase {
- public function initializeFromRequest( &$request ) {}
+ public function initializeFromRequest( &$request ) {
+ }
public function testTitleValidation( $name ) {
$this->mTitle = false;
$this->mDesiredDestName = $name;
$this->mTitleError = UploadBase::OK;
$this->getTitle();
+
return $this->mTitleError;
}
-
-
}
unset( $this->languageObject );
parent::tearDown();
}
-
}
'formatTimePeriod() rounding, recursion, (>48h)'
),
);
-
}
function testTruncate() {
array( 'n', 'just n' ),
array( 'n is in 5', 'is in' ),
);
+
return $tests;
}
-
}
return true;
}
}
+
return false;
}
return true;
}
}
+
return false;
}
$this->assertTextNode( "title", $name );
$this->assertTextNode( "ns", $ns );
$this->assertTextNode( "id", $id );
-
}
/**
* @param $parentid int|false: (optional) id of the parent revision
*/
protected function assertRevision( $id, $summary, $text_id, $text_bytes, $text_sha1, $text = false, $parentid = false,
- $model = CONTENT_MODEL_WIKITEXT, $format = CONTENT_FORMAT_WIKITEXT ) {
-
+ $model = CONTENT_MODEL_WIKITEXT, $format = CONTENT_FORMAT_WIKITEXT
+ ) {
$this->assertNodeStart( "revision" );
$this->skipWhitespace();
public function execute() {
$this->testCase->fail( __METHOD__ . " called unexpectedly" );
}
-
}
class MaintenanceTest extends MediaWikiTestCase {
// test.*Intermittent.* tests), the objective of these tests is not to describe
// consistent behavior, but rather currently existing behavior.
-
function testOutputEmpty() {
$this->m->output( "" );
$this->assertOutputPrePostShutdown( "", false );
$m2->simulateShutdown();
$this->assertOutputPrePostShutdown( "foobar\n\n", false );
}
-
-
}
private function assertPrefetchEquals( $expected, $page, $revision ) {
$this->assertEquals( $expected, $this->dump->prefetch( $page, $revision ),
"Prefetch of page $page revision $revision" );
-
}
function testSequential() {
</siteinfo>
';
-
// An array holding the pages that are available for prefetch
$available_pages = array();
return $fname;
}
-
}
// DumpTestCase
$this->exceptionFromAddDBData = $e;
}
-
}
protected function setUp() {
array( $this->pageId2, $this->pageId3, $this->pageId4 ),
array( $this->pageId1 + 1, $this->pageId2 + 1, $this->pageId3 + 1 ),
"Page ids increasing without holes" );
-
}
function testPlain() {
$this->assertPageEnd();
$this->assertDumpEnd();
-
}
/**
$minDuration = 2; // We want the dump to take at least this many seconds
$checkpointAfter = 0.5; // Generate checkpoint after this many seconds
-
// Until a dump takes at least $minDuration seconds, perform a dump and check
// duration. If the dump did not take long enough increase the iteration
// count, to generate a bigger stub file next time.
$content .= $tail;
$this->assertEquals( strlen( $content ), file_put_contents(
$fname, $content ), "Length of prepared stub" );
+
return $fname;
}
}
if ( $parameters !== null ) {
$logEntry->setParameters( $parameters );
}
+
return $logEntry->insert();
}
$user2, NS_MAIN, "PageA", "SomeOtherComment",
array( 'key1' => 1, 3 => 'value3' ) );
$this->assertGreaterThan( 0, $this->logId3 );
-
} catch ( Exception $e ) {
// We'd love to pass $e directly. However, ... see
// documentation of exceptionFromAddDBData in
// DumpTestCase
$this->exceptionFromAddDBData = $e;
}
-
}
// the following statement to catch good output
$this->expectOutputString( '' );
}
-
}
// DumpTestCase
$this->exceptionFromAddDBData = $e;
}
-
}
protected function setUp() {
array( $this->pageId2, $this->pageId3, $this->pageId4 ),
array( $this->pageId1 + 1, $this->pageId2 + 1, $this->pageId3 + 1 ),
"Page ids increasing without holes" );
-
}
function testFullTextPlain() {
$this->expectETAOutput();
}
-
-
}
return fopen( 'data://text/plain,' . $this->mockStdinText, 'r' );
}
-
}
/**
$this->textId3 . "\n23\nFetchTextTestPage2Text2"
) ) );
}
-
}
$this->expectOutputRegex( "/^[[:space:]]*\[wgDBprefix\][[:space:]]*=> "
. $wgDBprefix . "$/m" );
}
-
-
}
unset( $_SERVER['argv'][$key] ); // the option
unset( $_SERVER['argv'][$key + 1] ); // its value
$_SERVER['argv'] = array_values( $_SERVER['argv'] );
-
}
}
$property = $reflectedModule->getProperty( $propName );
$property->setAccessible( true );
$lists = $property->getValue( $module );
- foreach ( $lists as $group => $list ) {
+ foreach ( $lists as $list ) {
foreach ( $list as $key => $value ) {
// We need the same filter as for 'lists',
// due to 'skinStyles'.
$file,
);
}
-
}
// Restore settings
return $cases;
}
-
}
** http://valid.no.desc.org/
'
);
-
}
/**
$wgNamespaceAliases['Image'] = NS_FILE;
$wgNamespaceAliases['Image_talk'] = NS_FILE_TALK;
-
$wgEnableParserCache = false;
DeferredUpdates::clearPendingUpdates();
$wgMemc = wfGetMainCache();
if ( file_exists( $dir ) ) {
wfDebug( "Already exists!\n" );
+
return $dir;
}
// the UploadFromUrlTest class
class_exists( 'UploadFromUrlTest' );
$suite = new UploadFromUrlTestSuite( 'UploadFromUrlTest' );
+
return $suite;
}
}
( function ( mw, $ ) {
- QUnit.module( 'mediawiki.util', QUnit.newMwEnvironment() );
+ QUnit.module( 'mediawiki.util', QUnit.newMwEnvironment( {
+ setup: function () {
+ this.taPrefix = mw.util.tooltipAccessKeyPrefix;
+ mw.util.tooltipAccessKeyPrefix = 'ctrl-alt-';
+ },
+ teardown: function () {
+ mw.util.tooltipAccessKeyPrefix = this.taPrefix;
+ }
+ } ) );
QUnit.test( 'rawurlencode', 1, function ( assert ) {
assert.equal( mw.util.rawurlencode( 'Test:A & B/Here' ), 'Test%3AA%20%26%20B%2FHere' );
assert.strictEqual( mw.util.getParamValue( 'TEST', url ), 'a b+c d', 'Bug 30441: getParamValue must understand "+" encoding of space (multiple spaces)' );
} );
- QUnit.test( 'tooltipAccessKey', 3, function ( assert ) {
- assert.equal( typeof mw.util.tooltipAccessKeyPrefix, 'string', 'mw.util.tooltipAccessKeyPrefix must be a string' );
- assert.ok( mw.util.tooltipAccessKeyRegexp instanceof RegExp, 'mw.util.tooltipAccessKeyRegexp instance of RegExp' );
- assert.ok( mw.util.updateTooltipAccessKeys, 'mw.util.updateTooltipAccessKeys' );
+ QUnit.test( 'tooltipAccessKey', 4, function ( assert ) {
+ assert.equal( typeof mw.util.tooltipAccessKeyPrefix, 'string', 'tooltipAccessKeyPrefix must be a string' );
+ assert.equal( $.type( mw.util.tooltipAccessKeyRegexp ), 'regexp', 'tooltipAccessKeyRegexp is a regexp' );
+ assert.ok( mw.util.updateTooltipAccessKeys, 'updateTooltipAccessKeys is non-empty' );
+
+ 'Example [a]'.replace( mw.util.tooltipAccessKeyRegexp, function ( sub, m1, m2, m3, m4, m5, m6 ) {
+ assert.equal( m6, 'a', 'tooltipAccessKeyRegexp finds the accesskey hint' );
+ } );
} );
QUnit.test( '$content', 2, function ( assert ) {
* Previously, test elements where invisible to the selector since only
* one element can have a given id.
*/
- QUnit.test( 'addPortletLink', 8, function ( assert ) {
+ QUnit.test( 'addPortletLink', 10, function ( assert ) {
var pTestTb, pCustom, vectorTabs, tbRL, cuQuux, $cuQuux, tbMW, $tbMW, tbRLDM, caFoo;
pTestTb = '\
$( '#qunit-fixture' ).append( pTestTb, pCustom, vectorTabs );
tbRL = mw.util.addPortletLink( 'p-test-tb', '//mediawiki.org/wiki/ResourceLoader',
- 'ResourceLoader', 't-rl', 'More info about ResourceLoader on MediaWiki.org ', 'l' );
+ 'ResourceLoader', 't-rl', 'More info about ResourceLoader on MediaWiki.org ', 'l'
+ );
assert.ok( $.isDomElement( tbRL ), 'addPortletLink returns a valid DOM Element according to $.isDomElement' );
'MediaWiki.org', 't-mworg', 'Go to MediaWiki.org ', 'm', tbRL );
$tbMW = $( tbMW );
+ assert.propEqual(
+ $tbMW.getAttrs(),
+ {
+ id: 't-mworg'
+ },
+ 'Validate attributes of created element'
+ );
+
+ assert.propEqual(
+ $tbMW.find( 'a' ).getAttrs(),
+ {
+ href: '//mediawiki.org/',
+ title: 'Go to MediaWiki.org [ctrl-alt-m]',
+ accesskey: 'm'
+ },
+ 'Validate attributes of anchor tag in created element'
+ );
- assert.equal( $tbMW.attr( 'id' ), 't-mworg', 'Link has correct ID set' );
assert.equal( $tbMW.closest( '.portlet' ).attr( 'id' ), 'p-test-tb', 'Link was inserted within correct portlet' );
assert.equal( $tbMW.next().attr( 'id' ), 't-rl', 'Link is in the correct position (by passing nextnode)' );
- cuQuux = mw.util.addPortletLink( 'p-test-custom', '#', 'Quux' );
+ cuQuux = mw.util.addPortletLink( 'p-test-custom', '#', 'Quux', null, 'Example [shift-x]', 'q' );
$cuQuux = $( cuQuux );
+ assert.equal( $cuQuux.find( 'a' ).attr( 'title' ), 'Example [ctrl-alt-q]', 'Existing accesskey is stripped and updated' );
+
assert.equal(
$( '#p-test-custom #c-barmenu ul li' ).length,
1,
// Add level 2 headline and verify output in the preview
public function testAddLevel2HeadLine() {
- $blnElementPresent = false;
- $blnTextPresent = false;
$this->getExistingPage();
$this->clickEditLink();
$this->loadWikiEditor();
* @ingroup Testing
*/
-class TestRecorder {
+/**
+ * Interface to record parser test results.
+ *
+ * The ITestRecorder is a very simple interface to record the result of
+ * MediaWiki parser tests. One should call start() before running the
+ * full parser tests and end() once all the tests have been finished.
+ * After each test, you should use record() to keep track of your tests
+ * results. Finally, report() is used to generate a summary of your
+ * test run, one could dump it to the console for human consumption or
+ * register the result in a database for tracking purposes.
+ *
+ * @since 1.22
+ */
+interface ITestRecorder {
+
+ /** Called at beginning of the parser test run */
+ public function start();
+
+ /** Called after each test */
+ public function record( $test, $result );
+
+ /** Called before finishing the test run */
+ public function report();
+
+ /** Called at the end of the parser test run */
+ public function end();
+
+}
+
+class TestRecorder implements ITestRecorder {
var $parent;
var $term;
return true;
}
- if ( isset ( $this->sectionData[$this->section] ) ) {
+ if ( isset( $this->sectionData[$this->section] ) ) {
throw new MWException( "duplicate section '$this->section' at line {$this->lineNum} of $this->file\n" );
}