=== New features in 1.20 ===
* Added TitleIsAlwaysKnown hook which gets called when determining if a page exists.
+* Added NamespaceIsMovable hook which gets called when determining if pages in a
+ certain namespace can be moved.
* (bug 32341) Add upload by URL domain limitation.
* &useskin=default will now always display the default skin. Useful for users with a
preference for the non-default skin to look at something using the default skin.
mail().
== Updates ==
+
The correct way for updating a wiki is to update the files and then run from
command line the maintenance/update.php script (with appropriate parameters if
files were moved). It will perform all the needed steps to update the database
BaseTemplate::makeListItem for details on the format of individual
items inside of this array
+'NamespaceIsMovable': Called when determining if it is possible to pages in a namespace.
+$index: Integer; the index of the namespace being checked.
+$result: Boolean; whether MediaWiki currently thinks that pages in this namespace are movable.
+Hooks may change this value to override the return value of MWNamespace::isMovable()
+
'NewRevisionFromEditComplete': called when a revision was inserted
due to an edit
$article: the WikiPage edited
'DerivativeRequest' => 'includes/WebRequest.php',
'DeviceDetection' => 'includes/DeviceDetection.php',
'DiffHistoryBlob' => 'includes/HistoryBlob.php',
-
'DoubleReplacer' => 'includes/StringUtils.php',
'DummyLinker' => 'includes/Linker.php',
'Dump7ZipOutput' => 'includes/Export.php',
'RevisionList' => 'includes/RevisionList.php',
'RSSFeed' => 'includes/Feed.php',
'Sanitizer' => 'includes/Sanitizer.php',
- 'SecondaryDataUpdate' => 'includes/SecondaryDataUpdate.php',
- 'SecondaryDBDataUpdate' => 'includes/SecondaryDBDataUpdate.php',
+ 'DataUpdate' => 'includes/DataUpdate.php',
+ 'SqlDataUpdate' => 'includes/SqlDataUpdate.php',
'ScopedPHPTimeout' => 'includes/ScopedPHPTimeout.php',
'SiteConfiguration' => 'includes/SiteConfiguration.php',
'SiteStats' => 'includes/SiteStats.php',
'ApiFormatDump' => 'includes/api/ApiFormatDump.php',
'ApiFormatFeedWrapper' => 'includes/api/ApiFormatBase.php',
'ApiFormatJson' => 'includes/api/ApiFormatJson.php',
- 'ApiFormatNone' => 'includes/api/ApiFormatNone.php',
'ApiFormatPhp' => 'includes/api/ApiFormatPhp.php',
'ApiFormatRaw' => 'includes/api/ApiFormatRaw.php',
'ApiFormatTxt' => 'includes/api/ApiFormatTxt.php',
'HashBagOStuff' => 'includes/objectcache/HashBagOStuff.php',
'MediaWikiBagOStuff' => 'includes/objectcache/SqlBagOStuff.php',
'MemCachedClientforWiki' => 'includes/objectcache/MemcachedClient.php',
+ 'MemcachedBagOStuff' => 'includes/objectcache/MemcachedBagOStuff.php',
+ 'MemcachedPeclBagOStuff' => 'includes/objectcache/MemcachedPeclBagOStuff.php',
'MemcachedPhpBagOStuff' => 'includes/objectcache/MemcachedPhpBagOStuff.php',
'MultiWriteBagOStuff' => 'includes/objectcache/MultiWriteBagOStuff.php',
'MWMemcached' => 'includes/objectcache/MemcachedClient.php',
--- /dev/null
+<?php
+/**
+ * See docs/deferred.txt
+ *
+ * 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
+ *
+ * Abstract base class for update jobs that do something with some secondary
+ * data extracted from article.
+ */
+abstract class DataUpdate implements DeferrableUpdate {
+
+ /**
+ * Constructor
+ */
+ public function __construct( ) {
+ # noop
+ }
+
+ /**
+ * Begin an appropriate transaction, if any.
+ * This default implementation does nothing.
+ */
+ public function beginTransaction() {
+ //noop
+ }
+
+ /**
+ * Commit the transaction started via beginTransaction, if any.
+ * This default implementation does nothing.
+ */
+ public function commitTransaction() {
+ //noop
+ }
+
+ /**
+ * Abort / roll back the transaction started via beginTransaction, if any.
+ * This default implementation does nothing.
+ */
+ public function rollbackTransaction() {
+ //noop
+ }
+
+ /**
+ * Convenience method, calls doUpdate() on every DataUpdate in the array.
+ *
+ * This methods supports transactions logic by first calling beginTransaction()
+ * on all updates in the array, then calling doUpdate() on each, and, if all goes well,
+ * then calling commitTransaction() on each update. If an error occurrs,
+ * rollbackTransaction() will be called on any update object that had beginTranscation()
+ * called but not yet commitTransaction().
+ *
+ * This allows for limited transactional logic across multiple backends for storing
+ * secondary data.
+ *
+ * @static
+ * @param $updates array a list of DataUpdate instances
+ */
+ public static function runUpdates( $updates ) {
+ if ( empty( $updates ) ) return; # nothing to do
+
+ $open_transactions = array();
+ $exception = null;
+
+ /**
+ * @var $update StorageUpdate
+ * @var $trans StorageUpdate
+ */
+
+ try {
+ // begin transactions
+ foreach ( $updates as $update ) {
+ $update->beginTransaction();
+ $open_transactions[] = $update;
+ }
+
+ // do work
+ foreach ( $updates as $update ) {
+ $update->doUpdate();
+ }
+
+ // commit transactions
+ while ( count( $open_transactions ) > 0 ) {
+ $trans = array_pop( $open_transactions );
+ $trans->commitTransaction();
+ }
+ } catch ( Exception $ex ) {
+ $exception = $ex;
+ wfDebug( "Caught exception, will rethrow after rollback: " . $ex->getMessage() );
+ }
+
+ // rollback remaining transactions
+ while ( count( $open_transactions ) > 0 ) {
+ $trans = array_pop( $open_transactions );
+ $trans->rollbackTransaction();
+ }
+
+ if ( $exception ) {
+ throw $exception; // rethrow after cleanup
+ }
+ }
+
+}
'xcache' => array( 'class' => 'XCacheBagOStuff' ),
'wincache' => array( 'class' => 'WinCacheBagOStuff' ),
'memcached-php' => array( 'class' => 'MemcachedPhpBagOStuff' ),
+ 'memcached-pecl' => array( 'class' => 'MemcachedPeclBagOStuff' ),
'hash' => array( 'class' => 'HashBagOStuff' ),
);
} elseif ( $this->history & WikiExporter::RANGE ) {
# Dump of revisions within a specified range
$join['revision'] = array( 'INNER JOIN', 'page_id=rev_page' );
- $opts['ORDER BY'] = 'rev_page ASC, rev_id ASC';
+ $opts['ORDER BY'] = array( 'rev_page ASC', 'rev_id ASC' );
} else {
# Uknown history specification parameter?
wfProfileOut( __METHOD__ );
<?php
+/**
+ * Fake title class that triggers an error if any members are called.
+ *
+ * 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
+ */
/**
* Fake title class that triggers an error if any members are called
<?php
-
/**
+ * Fallback functions for PHP installed without mbstring support.
+ *
* 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
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
* http://www.gnu.org/copyleft/gpl.html
*
+ * @file
*/
/**
<?php
+/**
+ * Helper functions for feeds.
+ *
+ * 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 Feed
+ */
/**
* Helper functions for feeds
<?php
+/**
+ * File deletion user interface.
+ *
+ * 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
+ * @author Rob Church <robchur@gmail.com>
+ * @ingroup Media
+ */
/**
* File deletion user interface
*
* @ingroup Media
- * @author Rob Church <robchur@gmail.com>
*/
class FileDeleteForm {
<?php
+/**
+ * Class for managing forking command line scripts.
+ *
+ * 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
+ */
/**
* Class for managing forking command line scripts.
<?php
/**
* Helper class to keep track of options when mixing links and form elements.
- * @todo This badly need some examples and tests :-)
*
* Copyright © 2008, Niklas Laxstiröm
- *
* Copyright © 2011, Antoine Musso
*
+ * 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
* @author Niklas Laxström
* @author Antoine Musso
*/
+/**
+ * Helper class to keep track of options when mixing links and form elements.
+ *
+ * @todo This badly need some examples and tests :-)
+ */
class FormOptions implements ArrayAccess {
/** @name Type constants
* Used internally to map an option value to a WebRequest accessor
* of anyone working on large branches in git to setup config that show up only
* when specific branches are currently checked out.
*
+ * 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
*/
<?php
/**
- * Global functions used everywhere
+ * Global functions used everywhere.
+ *
+ * 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
*/
<?php
+/**
+ * HTML form generation and submission handling.
+ *
+ * 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
+ */
+
/**
* Object handling generic submission, CSRF protection, layout and
* other logic for UI forms. in a reusable manner.
<?php
-
+/**
+ * Efficient concatenated text storage.
+ *
+ * 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
+ */
+
/**
* Base class for general text storage via the "object" flag in old_flags, or
* two-part external storage URLs. Used for represent efficient concatenated
<?php
+/**
+ * Class alias kept for backward compatibility.
+ *
+ * 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 HTTP
+ */
/**
* HttpRequest was renamed to MWHttpRequest in order
<?php
+/**
+ * Various HTTP related functions.
+ *
+ * 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 HTTP
+ */
+
/**
* @defgroup HTTP HTTP
*/
*
* @todo document (e.g. one-sentence top-level class description).
*/
-class LinksUpdate extends SecondaryDBDataUpdate {
+class LinksUpdate extends SqlDataUpdate {
- /**@{{
- * @private
- */
- var $mId, //!< Page ID of the article linked from
+ // @todo: make members protected, but make sure extensions don't break
+
+ public $mId, //!< Page ID of the article linked from
$mTitle, //!< Title object of the article linked from
- $mParserOutput, //!< Whether to queue jobs for recursive update
+ $mParserOutput, //!< Parser output
$mLinks, //!< Map of title strings to IDs for the links in the document
$mImages, //!< DB keys of the images used, in the array key only
$mTemplates, //!< Map of title strings to IDs for the template references, including broken ones
$mInterlangs, //!< Map of language codes to titles
$mProperties, //!< Map of arbitrary name to value
$mRecursive; //!< Whether to queue jobs for recursive updates
- /**@}}*/
/**
* Constructor
function __construct( $title, $parserOutput, $recursive = true ) {
parent::__construct( );
- if ( !is_object( $title ) ) {
+ if ( !( $title instanceof Title ) ) {
throw new MWException( "The calling convention to LinksUpdate::LinksUpdate() has changed. " .
"Please see Article::editUpdates() for an invocation example.\n" );
}
- if ( !is_object( $parserOutput ) ) {
+ if ( !( $parserOutput instanceof ParserOutput ) ) {
throw new MWException( "The calling convention to LinksUpdate::__construct() has changed. " .
"Please see WikiPage::doEditUpdates() for an invocation example.\n" );
}
/**
* Update object handling the cleanup of links tables after a page was deleted.
**/
-class LinksDeletionUpdate extends SecondaryDBDataUpdate {
+class LinksDeletionUpdate extends SqlDataUpdate {
- /**@{{
- * @private
- */
- var $mWikiPage; //!< WikiPage the wikipage that was deleted
- /**@}}*/
+ protected $mPage; //!< WikiPage the wikipage that was deleted
/**
* Constructor
if ( !$this->mDb->cleanupTriggers() ) {
# Clean up recentchanges entries...
$this->mDb->delete( 'recentchanges',
- array( 'rc_type != ' . RC_LOG,
- 'rc_namespace' => $title->getNamespace(),
- 'rc_title' => $title->getDBkey() ),
- __METHOD__ );
+ array( 'rc_type != ' . RC_LOG,
+ 'rc_namespace' => $title->getNamespace(),
+ 'rc_title' => $title->getDBkey() ),
+ __METHOD__ );
$this->mDb->delete( 'recentchanges',
- array( 'rc_type != ' . RC_LOG, 'rc_cur_id' => $id ),
- __METHOD__ );
+ array( 'rc_type != ' . RC_LOG, 'rc_cur_id' => $id ),
+ __METHOD__ );
}
}
}
*/
public static function isMovable( $index ) {
global $wgAllowImageMoving;
- return !( $index < NS_MAIN || ( $index == NS_FILE && !$wgAllowImageMoving ) || $index == NS_CATEGORY );
+
+ $result = !( $index < NS_MAIN || ( $index == NS_FILE && !$wgAllowImageMoving ) || $index == NS_CATEGORY );
+
+ /**
+ * @since 1.20
+ */
+ wfRunHooks( 'NamespaceIsMovable', array( $index, &$result ) );
+
+ return $result;
}
/**
$join_conds = isset( $info['join_conds'] ) ? $info['join_conds'] : array();
$sortColumns = array_merge( array( $this->mIndexField ), $this->mExtraSortFields );
if ( $descending ) {
- $options['ORDER BY'] = implode( ',', $sortColumns );
+ $options['ORDER BY'] = $sortColumns;
$operator = '>';
} else {
$orderBy = array();
foreach ( $sortColumns as $col ) {
$orderBy[] = $col . ' DESC';
}
- $options['ORDER BY'] = implode( ',', $orderBy );
+ $options['ORDER BY'] = $orderBy;
$operator = '<';
}
if ( $offset != '' ) {
$options = isset( $query['options'] ) ? (array)$query['options'] : array();
$join_conds = isset( $query['join_conds'] ) ? (array)$query['join_conds'] : array();
if ( count( $order ) ) {
- $options['ORDER BY'] = implode( ', ', $order );
+ $options['ORDER BY'] = $order;
}
if ( $limit !== false ) {
$options['LIMIT'] = intval( $limit );
+++ /dev/null
-<?php
-/**
- * See docs/deferred.txt
- *
- * 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
- *
- * Abstract base class for update jobs that put some secondary data extracted
- * from article content into the database.
- *
- * @since WD.1
- */
-abstract class SecondaryDBDataUpdate extends SecondaryDataUpdate {
-
- /**@{{
- * @private
- */
- var $mDb, //!< Database connection reference
- $mOptions, //!< SELECT options to be used (array)
- $mHasTransaction;//!< bool whether a transaction is open on this object (internal use only!)
- /**@}}*/
-
- /**
- * Constructor
- **/
- public function __construct( ) {
- global $wgAntiLockFlags;
-
- parent::__construct( );
-
- if ( $wgAntiLockFlags & ALF_NO_LINK_LOCK ) {
- $this->mOptions = array();
- } else {
- $this->mOptions = array( 'FOR UPDATE' );
- }
- $this->mDb = wfGetDB( DB_MASTER );
- $this->mHasTransaction = false;
- }
-
- /**
- * Begin a database transaction.
- *
- * Because nested transactions are not supportred by the Database class, this implementation
- * checked Database::trxLevel() and only opens a transaction if none is yet active.
- *
- * @since WD.1
- */
- public function beginTransaction() {
- // NOTE: nested transactions are not supported, only start a transaction if none is open
- if ( $this->mDb->trxLevel() === 0 ) {
- $this->mDb->begin( get_class( $this ) . '::beginTransaction' );
- $this->mHasTransaction = true;
- }
- }
-
- /**
- * Commit the database transaction started via beginTransaction (if any).
- *
- * @since WD.1
- */
- public function commitTransaction() {
- if ( $this->mHasTransaction ) {
- $this->mDb->commit( get_class( $this ) . '::commitTransaction' );
- }
- }
-
- /**
- * Abort the database transaction started via beginTransaction (if any).
- *
- * @since WD.1
- */
- public function abortTransaction() {
- if ( $this->mHasTransaction ) {
- $this->mDb->rollback( get_class( $this ) . '::abortTransaction' );
- }
- }
-
- /**
- * Invalidate the cache of a list of pages from a single namespace.
- * This is intended for use by subclasses.
- *
- * @since WD.1
- *
- * @param $namespace Integer
- * @param $dbkeys Array
- */
- protected function invalidatePages( $namespace, $dbkeys ) {
- if ( !count( $dbkeys ) ) {
- return;
- }
-
- /**
- * Determine which pages need to be updated
- * This is necessary to prevent the job queue from smashing the DB with
- * large numbers of concurrent invalidations of the same page
- */
- $now = $this->mDb->timestamp();
- $ids = array();
- $res = $this->mDb->select( 'page', array( 'page_id' ),
- array(
- 'page_namespace' => $namespace,
- 'page_title IN (' . $this->mDb->makeList( $dbkeys ) . ')',
- 'page_touched < ' . $this->mDb->addQuotes( $now )
- ), __METHOD__
- );
- foreach ( $res as $row ) {
- $ids[] = $row->page_id;
- }
- if ( !count( $ids ) ) {
- return;
- }
-
- /**
- * Do the update
- * We still need the page_touched condition, in case the row has changed since
- * the non-locking select above.
- */
- $this->mDb->update( 'page', array( 'page_touched' => $now ),
- array(
- 'page_id IN (' . $this->mDb->makeList( $ids ) . ')',
- 'page_touched < ' . $this->mDb->addQuotes( $now )
- ), __METHOD__
- );
- }
-
-}
+++ /dev/null
-<?php
-/**
- * See docs/deferred.txt
- *
- * 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
- *
- * Abstract base class for update jobs that do something with some secondary
- * data extracted from article.
- *
- * @todo: add support for transactions
- *
- * @since WD.1
- */
-abstract class SecondaryDataUpdate implements DeferrableUpdate {
-
- /**
- * Constructor
- */
- public function __construct( ) {
- # noop
- }
-
- /**
- * Begin an appropriate transaction, if any.
- * This default implementation does nothing.
- *
- * @since WD.1
- */
- public function beginTransaction() {
- //noop
- }
-
- /**
- * Commit the transaction started via beginTransaction, if any.
- * This default implementation does nothing.
- *
- * @since WD.1
- */
- public function commitTransaction() {
- //noop
- }
-
- /**
- * Abort / roll back the transaction started via beginTransaction, if any.
- * This default implementation does nothing.
- *
- * @since WD.1
- */
- public function rollbackTransaction() {
- //noop
- }
-
- /**
- * Conveniance method, calls doUpdate() on every SecondaryDataUpdate in the array.
- *
- * This methods supports transactions logic by first calling beginTransaction()
- * on all updates in the array, then calling doUpdate() on each, and, if all goes well,
- * then calling commitTransaction() on each update. If an error occurrs,
- * rollbackTransaction() will be called on any update object that had beginTranscation()
- * called but not yet commitTransaction().
- *
- * This allows for limited transactional logic across multiple baceknds for storing
- * secondary data.
- *
- * @since WD.1
- *
- * @static
- * @param $updates array a list of SecondaryDataUpdate instances
- */
- public static function runUpdates( $updates ) {
- if ( empty( $updates ) ) return; # nothing to do
-
- $open_transactions = array();
- $exception = null;
-
- /**
- * @var $update SecondaryDataUpdate
- * @var $trans SecondaryDataUpdate
- */
-
- try {
- // begin transactions
- foreach ( $updates as $update ) {
- $update->beginTransaction();
- $open_transactions[] = $update;
- }
-
- // do work
- foreach ( $updates as $update ) {
- $update->doUpdate();
- }
-
- // commit transactions
- while ( count( $open_transactions ) > 0 ) {
- $trans = array_pop( $open_transactions );
- $trans->commitTransaction();
- }
- } catch ( Exception $ex ) {
- $exception = $ex;
- wfDebug( "Caught exception, will rethrow after rollback: " . $ex->getMessage() );
- }
-
- // rollback remaining transactions
- while ( count( $open_transactions ) > 0 ) {
- $trans = array_pop( $open_transactions );
- $trans->rollbackTransaction();
- }
-
- if ( $exception ) {
- throw $exception; // rethrow after cleanup
- }
- }
-
-}
--- /dev/null
+<?php
+/**
+ * See docs/deferred.txt
+ *
+ * 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
+ *
+ * Abstract base class for update jobs that put some secondary data extracted
+ * from article content into the database.
+ */
+abstract class SqlDataUpdate extends DataUpdate {
+
+ protected $mDb; //!< Database connection reference
+ protected $mOptions; //!< SELECT options to be used (array)
+
+ private $mHasTransaction; //!< bool whether a transaction is open on this object (internal use only!)
+
+ /**
+ * Constructor
+ **/
+ public function __construct( ) {
+ global $wgAntiLockFlags;
+
+ parent::__construct( );
+
+ if ( $wgAntiLockFlags & ALF_NO_LINK_LOCK ) {
+ $this->mOptions = array();
+ } else {
+ $this->mOptions = array( 'FOR UPDATE' );
+ }
+
+ // @todo: get connection only when it's needed? make sure that doesn't break anything, especially transactions!
+ $this->mDb = wfGetDB( DB_MASTER );
+ $this->mHasTransaction = false;
+ }
+
+ /**
+ * Begin a database transaction.
+ *
+ * Because nested transactions are not supportred by the Database class, this implementation
+ * checkes Database::trxLevel() and only opens a transaction if none is yet active.
+ */
+ public function beginTransaction() {
+ // NOTE: nested transactions are not supported, only start a transaction if none is open
+ if ( $this->mDb->trxLevel() === 0 ) {
+ $this->mDb->begin( get_class( $this ) . '::beginTransaction' );
+ $this->mHasTransaction = true;
+ }
+ }
+
+ /**
+ * Commit the database transaction started via beginTransaction (if any).
+ */
+ public function commitTransaction() {
+ if ( $this->mHasTransaction ) {
+ $this->mDb->commit( get_class( $this ) . '::commitTransaction' );
+ }
+ }
+
+ /**
+ * Abort the database transaction started via beginTransaction (if any).
+ */
+ public function abortTransaction() {
+ if ( $this->mHasTransaction ) {
+ $this->mDb->rollback( get_class( $this ) . '::abortTransaction' );
+ }
+ }
+
+ /**
+ * Invalidate the cache of a list of pages from a single namespace.
+ * This is intended for use by subclasses.
+ *
+ * @param $namespace Integer
+ * @param $dbkeys Array
+ */
+ protected function invalidatePages( $namespace, Array $dbkeys ) {
+ if ( !count( $dbkeys ) ) {
+ return;
+ }
+
+ /**
+ * Determine which pages need to be updated
+ * This is necessary to prevent the job queue from smashing the DB with
+ * large numbers of concurrent invalidations of the same page
+ */
+ $now = $this->mDb->timestamp();
+ $ids = array();
+ $res = $this->mDb->select( 'page', array( 'page_id' ),
+ array(
+ 'page_namespace' => $namespace,
+ 'page_title' => $dbkeys,
+ 'page_touched < ' . $this->mDb->addQuotes( $now )
+ ), __METHOD__
+ );
+ foreach ( $res as $row ) {
+ $ids[] = $row->page_id;
+ }
+ if ( !count( $ids ) ) {
+ return;
+ }
+
+ /**
+ * Do the update
+ * We still need the page_touched condition, in case the row has changed since
+ * the non-locking select above.
+ */
+ $this->mDb->update( 'page', array( 'page_touched' => $now ),
+ array(
+ 'page_id' => $ids,
+ 'page_touched < ' . $this->mDb->addQuotes( $now )
+ ), __METHOD__
+ );
+ }
+
+}
# Proxy blocking
if ( !$block instanceof Block && $ip !== null && !$this->isAllowed( 'proxyunbannable' )
- && !in_array( $ip, $wgProxyWhitelist ) )
+ && !in_array( $ip, $wgProxyWhitelist ) )
{
# Local list
if ( self::isLocallyBlockedProxy( $ip ) ) {
$this->mTouched = self::newTouchedTimestamp();
$dbw = wfGetDB( DB_MASTER );
- $dbw->update( 'user',
- array( 'user_touched' => $dbw->timestamp( $this->mTouched ) ),
- array( 'user_id' => $this->mId ),
- __METHOD__ );
+
+ // Prevent contention slams by checking user_touched first
+ $now = $dbw->timestamp( $this->mTouched );
+ $needsPurge = $dbw->selectField( 'user', '1',
+ array( 'user_id' => $this->mId, 'user_touched < ' . $dbw->addQuotes( $now ) )
+ );
+ if ( $needsPurge ) {
+ $dbw->update( 'user',
+ array( 'user_touched' => $now ),
+ array( 'user_id' => $this->mId, 'user_touched < ' . $dbw->addQuotes( $now ) ),
+ __METHOD__
+ );
+ }
$this->clearSharedCache();
}
*/
public function getPageRenderingHash() {
wfDeprecated( __METHOD__, '1.17' );
-
+
global $wgUseDynamicDates, $wgRenderHashAppend, $wgLang, $wgContLang;
if( $this->mHash ){
return $this->mHash;
# Update the links tables and other secondary data
$updates = $editInfo->output->getSecondaryDataUpdates( $this->mTitle );
- SecondaryDataUpdate::runUpdates( $updates );
+ DataUpdate::runUpdates( $updates );
wfRunHooks( 'ArticleEditUpdates', array( &$this, &$editInfo, $options['changed'] ) );
DeferredUpdates::addUpdate( new SiteStatsUpdate( 0, 1, - (int)$this->isCountable(), -1 ) );
# remove secondary indexes, etc
- $handler = $this->getContentHandler();
- $updates = $handler->getDeletionUpdates( $this );
- SecondaryDataUpdate::runUpdates( $updates );
+ $updates = $this->getDeletionUpdates( );
+ DataUpdate::runUpdates( $updates );
# Clear caches
WikiPage::onArticleDelete( $this->mTitle );
if ( count( $templates_diff ) > 0 ) {
# Whee, link updates time.
- # Note: we are only interested in links here. We don't need to get other SecondaryDataUpdate items from the parser output.
+ # Note: we are only interested in links here. We don't need to get other DataUpdate items from the parser output.
$u = new LinksUpdate( $this->mTitle, $parserOutput, false );
$u->doUpdate();
}
global $wgUser;
return $this->isParserCacheUsed( ParserOptions::newFromUser( $wgUser ), $oldid );
}
+
+ public function getDeletionUpdates() {
+ $updates = array(
+ new LinksDeletionUpdate( $this ),
+ );
+
+ //@todo: make a hook to add update objects
+ //NOTE: deletion updates will be determined by the ContentHandler in the future
+ return $updates;
+ }
}
class PoolWorkArticleView extends PoolCounterWork {
true, true, $page->getLatest() ); #FIXME: content!
# Update the links tables
- $updates = $p_result->getSecondaryDataUpdates( $title );
- SecondaryDataUpdate::runUpdates( $updates );
+ $updates = $p_result->getSecondaryDataUpdates( $title );
+ DataUpdate::runUpdates( $updates );
$r['linkupdate'] = '';
* @return void
*/
final protected function deleteContainerCache( $container ) {
- for ( $attempts=1; $attempts <= 3; $attempts++ ) {
- if ( $this->memCache->delete( $this->containerCacheKey( $container ) ) ) {
- return; // done!
- }
+ if ( !$this->memCache->delete( $this->containerCacheKey( $container ) ) ) {
+ trigger_error( "Unable to delete stat cache for container $container." );
}
- trigger_error( "Unable to delete stat cache for container $container." );
}
/**
* @return void
*/
final protected function deleteFileCache( $path ) {
- for ( $attempts=1; $attempts <= 3; $attempts++ ) {
- if ( $this->memCache->delete( $this->fileCacheKey( $path ) ) ) {
- return; // done!
- }
+ if ( !$this->memCache->delete( $this->fileCacheKey( $path ) ) ) {
+ trigger_error( "Unable to delete stat cache for file $path." );
}
- trigger_error( "Unable to delete stat cache for file $path." );
}
/**
wfProfileOut( __METHOD__.'-parse' );
wfProfileIn( __METHOD__.'-update' );
- $updates = $parserOutput->getSecondaryDataUpdates( $this->title, false );
- SecondaryDataUpdate::runUpdates( $updates );
+ $updates = $parserOutput->getSecondaryDataUpdates( $this->title, false );
+ DataUpdate::runUpdates( $updates );
- wfProfileOut( __METHOD__.'-update' );
+ wfProfileOut( __METHOD__.'-update' );
wfProfileOut( __METHOD__ );
return true;
}
wfProfileOut( __METHOD__.'-parse' );
wfProfileIn( __METHOD__.'-update' );
- $updates = $parserOutput->getSecondaryDataUpdates( $title, false );
- SecondaryDataUpdate::runUpdates( $updates );
+ $updates = $parserOutput->getSecondaryDataUpdates( $title, false );
+ DataUpdate::runUpdates( $updates );
wfProfileOut( __METHOD__.'-update' );
wfWaitForSlaves();
--- /dev/null
+<?php
+/**
+ * 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 Cache
+ */
+
+/**
+ * Base class for memcached clients.
+ *
+ * @ingroup Cache
+ */
+class MemcachedBagOStuff extends BagOStuff {
+ protected $client;
+
+ /**
+ * Fill in the defaults for any parameters missing from $params, using the
+ * backwards-compatible global variables
+ */
+ protected function applyDefaultParams( $params ) {
+ if ( !isset( $params['servers'] ) ) {
+ $params['servers'] = $GLOBALS['wgMemCachedServers'];
+ }
+ if ( !isset( $params['debug'] ) ) {
+ $params['debug'] = $GLOBALS['wgMemCachedDebug'];
+ }
+ if ( !isset( $params['persistent'] ) ) {
+ $params['persistent'] = $GLOBALS['wgMemCachedPersistent'];
+ }
+ if ( !isset( $params['compress_threshold'] ) ) {
+ $params['compress_threshold'] = 1500;
+ }
+ if ( !isset( $params['timeout'] ) ) {
+ $params['timeout'] = $GLOBALS['wgMemCachedTimeout'];
+ }
+ if ( !isset( $params['connect_timeout'] ) ) {
+ $params['connect_timeout'] = 0.1;
+ }
+ return $params;
+ }
+
+ /**
+ * @param $key string
+ * @return Mixed
+ */
+ public function get( $key ) {
+ return $this->client->get( $this->encodeKey( $key ) );
+ }
+
+ /**
+ * @param $key string
+ * @param $value
+ * @param $exptime int
+ * @return bool
+ */
+ public function set( $key, $value, $exptime = 0 ) {
+ return $this->client->set( $this->encodeKey( $key ), $value,
+ $this->fixExpiry( $exptime ) );
+ }
+
+ /**
+ * @param $key string
+ * @param $time int
+ * @return bool
+ */
+ public function delete( $key, $time = 0 ) {
+ return $this->client->delete( $this->encodeKey( $key ), $time );
+ }
+
+ /**
+ * @param $key string
+ * @param $value int
+ * @return Mixed
+ */
+ public function add( $key, $value, $exptime = 0 ) {
+ return $this->client->add( $this->encodeKey( $key ), $value,
+ $this->fixExpiry( $exptime ) );
+ }
+
+ /**
+ * @param $key string
+ * @param $value int
+ * @param $exptime
+ * @return Mixed
+ */
+ public function replace( $key, $value, $exptime = 0 ) {
+ return $this->client->replace( $this->encodeKey( $key ), $value,
+ $this->fixExpiry( $exptime ) );
+ }
+
+ /**
+ * Get the underlying client object. This is provided for debugging
+ * purposes.
+ */
+ public function getClient() {
+ return $this->client;
+ }
+
+ /**
+ * Encode a key for use on the wire inside the memcached protocol.
+ *
+ * We encode spaces and line breaks to avoid protocol errors. We encode
+ * the other control characters for compatibility with libmemcached
+ * verify_key. We leave other punctuation alone, to maximise backwards
+ * compatibility.
+ * @return string
+ */
+ public function encodeKey( $key ) {
+ return preg_replace_callback( '/[\x00-\x20\x25\x7f]+/',
+ array( $this, 'encodeKeyCallback' ), $key );
+ }
+
+ protected function encodeKeyCallback( $m ) {
+ return rawurlencode( $m[0] );
+ }
+
+ /**
+ * TTLs higher than 30 days will be detected as absolute TTLs
+ * (UNIX timestamps), and will result in the cache entry being
+ * discarded immediately because the expiry is in the past.
+ * Clamp expiries >30d at 30d, unless they're >=1e9 in which
+ * case they are likely to really be absolute (1e9 = 2011-09-09)
+ */
+ function fixExpiry( $expiry ) {
+ if ( $expiry > 2592000 && $expiry < 1000000000 ) {
+ $expiry = 2592000;
+ }
+ return $expiry;
+ }
+
+ /**
+ * Decode a key encoded with encodeKey(). This is provided as a convenience
+ * function for debugging.
+ *
+ * @param $key string
+ *
+ * @return string
+ */
+ public function decodeKey( $key ) {
+ return urldecode( $key );
+ }
+
+ /**
+ * Send a debug message to the log
+ */
+ protected function debugLog( $text ) {
+ global $wgDebugLogGroups;
+ if( !isset( $wgDebugLogGroups['memcached'] ) ) {
+ # Prefix message since it will end up in main debug log file
+ $text = "memcached: $text";
+ }
+ if ( substr( $text, -1 ) !== "\n" ) {
+ $text .= "\n";
+ }
+ wfDebugLog( 'memcached', $text );
+ }
+}
+
* @access private
*/
function _hashfunc( $key ) {
- # Hash function must on [0,0x7ffffff]
+ # Hash function must be in [0,0x7ffffff]
# We take the first 31 bits of the MD5 hash, which unlike the hash
# function used in a previous version of this client, works
return hexdec( substr( md5( $key ), 0, 8 ) ) & 0x7fffffff;
$this->stats[$cmd] = 1;
}
- // TTLs higher than 30 days will be detected as absolute TTLs
- // (UNIX timestamps), and will result in the cache entry being
- // discarded immediately because the expiry is in the past.
- // Clamp expiries >30d at 30d, unless they're >=1e9 in which
- // case they are likely to really be absolute (1e9 = 2011-09-09)
- if ( $exp > 2592000 && $exp < 1000000000 ) {
- $exp = 2592000;
- }
-
$flags = 0;
if ( !is_scalar( $val ) ) {
--- /dev/null
+<?php
+
+/**
+ * A wrapper class for the PECL memcached client
+ *
+ * @ingroup Cache
+ */
+class MemcachedPeclBagOStuff extends MemcachedBagOStuff {
+
+ /**
+ * Constructor
+ *
+ * Available parameters are:
+ * - servers: The list of IP:port combinations holding the memcached servers.
+ * - persistent: Whether to use a persistent connection
+ * - compress_threshold: The minimum size an object must be before it is compressed
+ * - timeout: The read timeout in microseconds
+ * - connect_timeout: The connect timeout in seconds
+ * - serializer: May be either "php" or "igbinary". Igbinary produces more compact
+ * values, but serialization is much slower unless the php.ini option
+ * igbinary.compact_strings is off.
+ */
+ function __construct( $params ) {
+ $params = $this->applyDefaultParams( $params );
+
+ if ( $params['persistent'] ) {
+ $this->client = new Memcached( __CLASS__ );
+ } else {
+ $this->client = new Memcached;
+ }
+
+ if ( !isset( $params['serializer'] ) ) {
+ $params['serializer'] = 'php';
+ }
+
+ // The compression threshold is an undocumented php.ini option for some
+ // reason. There's probably not much harm in setting it globally, for
+ // compatibility with the settings for the PHP client.
+ ini_set( 'memcached.compression_threshold', $params['compress_threshold'] );
+
+ // Set timeouts
+ $this->client->setOption( Memcached::OPT_CONNECT_TIMEOUT, $params['connect_timeout'] * 1000 );
+ $this->client->setOption( Memcached::OPT_SEND_TIMEOUT, $params['timeout'] );
+ $this->client->setOption( Memcached::OPT_RECV_TIMEOUT, $params['timeout'] );
+ $this->client->setOption( Memcached::OPT_POLL_TIMEOUT, $params['timeout'] / 1000 );
+
+ // Set libketama mode since it's recommended by the documentation and
+ // is as good as any. There's no way to configure libmemcached to use
+ // hashes identical to the ones currently in use by the PHP client, and
+ // even implementing one of the libmemcached hashes in pure PHP for
+ // forwards compatibility would require MWMemcached::get_sock() to be
+ // rewritten.
+ $this->client->setOption( Memcached::OPT_LIBKETAMA_COMPATIBLE, true );
+
+ // Set the serializer
+ switch ( $params['serializer'] ) {
+ case 'php':
+ $this->client->setOption( Memcached::OPT_SERIALIZER, Memcached::SERIALIZER_PHP );
+ break;
+ case 'igbinary':
+ if ( !extension_loaded( 'igbinary' ) ) {
+ throw new MWException( __CLASS__.': the igbinary extension is not loaded ' .
+ 'but igbinary serialization was requested.' );
+ }
+ $this->client->setOption( Memcached::OPT_SERIALIZER, Memcached::SERIALIZER_IGBINARY );
+ break;
+ default:
+ throw new MWException( __CLASS__.': invalid value for serializer parameter' );
+ }
+ foreach ( $params['servers'] as $host ) {
+ list( $ip, $port ) = IP::splitHostAndPort( $host );
+ $this->client->addServer( $ip, $port );
+ }
+ }
+
+ /**
+ * @param $key string
+ * @return Mixed
+ */
+ public function get( $key ) {
+ $this->debugLog( "get($key)" );
+ return $this->checkResult( $key, parent::get( $key ) );
+ }
+
+ /**
+ * @param $key string
+ * @param $value
+ * @param $exptime int
+ * @return bool
+ */
+ public function set( $key, $value, $exptime = 0 ) {
+ $this->debugLog( "set($key)" );
+ return $this->checkResult( $key, parent::set( $key, $value, $exptime ) );
+ }
+
+ /**
+ * @param $key string
+ * @param $time int
+ * @return bool
+ */
+ public function delete( $key, $time = 0 ) {
+ $this->debugLog( "delete($key)" );
+ return $this->checkResult( $key, parent::delete( $key, $time ) );
+ }
+
+ /**
+ * @param $key string
+ * @param $value int
+ * @return Mixed
+ */
+ public function add( $key, $value, $exptime = 0 ) {
+ $this->debugLog( "add($key)" );
+ return $this->checkResult( $key, parent::add( $key, $value, $exptime ) );
+ }
+
+ /**
+ * @param $key string
+ * @param $value int
+ * @param $exptime
+ * @return Mixed
+ */
+ public function replace( $key, $value, $exptime = 0 ) {
+ $this->debugLog( "replace($key)" );
+ return $this->checkResult( $key, parent::replace( $key, $value, $exptime ) );
+ }
+
+ /**
+ * @param $key string
+ * @param $value int
+ * @return Mixed
+ */
+ public function incr( $key, $value = 1 ) {
+ $this->debugLog( "incr($key)" );
+ $result = $this->client->increment( $key, $value );
+ return $this->checkResult( $key, $result );
+ }
+
+ /**
+ * @param $key string
+ * @param $value int
+ * @return Mixed
+ */
+ public function decr( $key, $value = 1 ) {
+ $this->debugLog( "decr($key)" );
+ $result = $this->client->decrement( $key, $value );
+ return $this->checkResult( $key, $result );
+ }
+
+ /**
+ * Check the return value from a client method call and take any necessary
+ * action. Returns the value that the wrapper function should return. At
+ * present, the return value is always the same as the return value from
+ * the client, but some day we might find a case where it should be
+ * different.
+ *
+ * @param $key The key used by the caller, or false if there wasn't one.
+ * @param $result The return value
+ */
+ protected function checkResult( $key, $result ) {
+ if ( $result !== false ) {
+ return $result;
+ }
+ switch ( $this->client->getResultCode() ) {
+ case Memcached::RES_SUCCESS:
+ break;
+ case Memcached::RES_DATA_EXISTS:
+ case Memcached::RES_NOTSTORED:
+ case Memcached::RES_NOTFOUND:
+ $this->debugLog( "result: " . $this->client->getResultMessage() );
+ break;
+ default:
+ $msg = $this->client->getResultMessage();
+ if ( $key !== false ) {
+ $server = $this->client->getServerByKey( $key );
+ $serverName = "{$server['host']}:{$server['port']}";
+ $msg = "Memcached error for key \"$key\" on server \"$serverName\": $msg";
+ } else {
+ $msg = "Memcached error: $msg";
+ }
+ wfDebugLog( 'memcached-serious', $msg );
+ }
+ return $result;
+ }
+
+ /**
+ * @param $keys Array
+ * @return Array
+ */
+ public function getBatch( array $keys ) {
+ $this->debugLog( 'getBatch(' . implode( ', ', $keys ) . ')' );
+ $callback = array( $this, 'encodeKey' );
+ $result = $this->client->getMulti( array_map( $callback, $keys ) );
+ return $this->checkResult( false, $result );
+ }
+
+ /* NOTE: there is no cas() method here because it is currently not supported
+ * by the BagOStuff interface and other BagOStuff subclasses, such as
+ * SqlBagOStuff.
+ */
+}
*
* @ingroup Cache
*/
-class MemcachedPhpBagOStuff extends BagOStuff {
-
- /**
- * @var MemCachedClientforWiki
- */
- protected $client;
+class MemcachedPhpBagOStuff extends MemcachedBagOStuff {
/**
* Constructor.
* @param $params array
*/
function __construct( $params ) {
- if ( !isset( $params['servers'] ) ) {
- $params['servers'] = $GLOBALS['wgMemCachedServers'];
- }
- if ( !isset( $params['debug'] ) ) {
- $params['debug'] = $GLOBALS['wgMemCachedDebug'];
- }
- if ( !isset( $params['persistent'] ) ) {
- $params['persistent'] = $GLOBALS['wgMemCachedPersistent'];
- }
- if ( !isset( $params['compress_threshold'] ) ) {
- $params['compress_threshold'] = 1500;
- }
- if ( !isset( $params['timeout'] ) ) {
- $params['timeout'] = $GLOBALS['wgMemCachedTimeout'];
- }
- if ( !isset( $params['connect_timeout'] ) ) {
- $params['connect_timeout'] = 0.1;
- }
+ $params = $this->applyDefaultParams( $params );
$this->client = new MemCachedClientforWiki( $params );
$this->client->set_servers( $params['servers'] );
$this->client->set_debug( $debug );
}
- /**
- * @param $key string
- * @return Mixed
- */
- public function get( $key ) {
- return $this->client->get( $this->encodeKey( $key ) );
- }
-
/**
* @param $keys Array
* @return Array
return $this->client->get_multi( array_map( $callback, $keys ) );
}
- /**
- * @param $key string
- * @param $value
- * @param $exptime int
- * @return bool
- */
- public function set( $key, $value, $exptime = 0 ) {
- return $this->client->set( $this->encodeKey( $key ), $value, $exptime );
- }
-
- /**
- * @param $key string
- * @param $time int
- * @return bool
- */
- public function delete( $key, $time = 0 ) {
- return $this->client->delete( $this->encodeKey( $key ), $time );
- }
-
/**
* @param $key
* @param $timeout int
public function unlock( $key ) {
return $this->client->unlock( $this->encodeKey( $key ) );
}
-
- /**
- * @param $key string
- * @param $value int
- * @return Mixed
- */
- public function add( $key, $value, $exptime = 0 ) {
- return $this->client->add( $this->encodeKey( $key ), $value, $exptime );
- }
-
- /**
- * @param $key string
- * @param $value int
- * @param $exptime
- * @return Mixed
- */
- public function replace( $key, $value, $exptime = 0 ) {
- return $this->client->replace( $this->encodeKey( $key ), $value, $exptime );
- }
-
+
/**
* @param $key string
* @param $value int
public function decr( $key, $value = 1 ) {
return $this->client->decr( $this->encodeKey( $key ), $value );
}
-
- /**
- * Get the underlying client object. This is provided for debugging
- * purposes.
- *
- * @return MemCachedClientforWiki
- */
- public function getClient() {
- return $this->client;
- }
-
- /**
- * Encode a key for use on the wire inside the memcached protocol.
- *
- * We encode spaces and line breaks to avoid protocol errors. We encode
- * the other control characters for compatibility with libmemcached
- * verify_key. We leave other punctuation alone, to maximise backwards
- * compatibility.
- * @return string
- */
- public function encodeKey( $key ) {
- return preg_replace_callback( '/[\x00-\x20\x25\x7f]+/',
- array( $this, 'encodeKeyCallback' ), $key );
- }
-
- protected function encodeKeyCallback( $m ) {
- return rawurlencode( $m[0] );
- }
-
- /**
- * Decode a key encoded with encodeKey(). This is provided as a convenience
- * function for debugging.
- *
- * @param $key string
- *
- * @return string
- */
- public function decodeKey( $key ) {
- return urldecode( $key );
- }
}
/**
* Factory function that creates a memcached client object.
- * The idea of this is that it might eventually detect and automatically
- * support the PECL extension, assuming someone can get it to compile.
+ *
+ * This always uses the PHP client, since the PECL client has a different
+ * hashing scheme and a different interpretation of the flags bitfield, so
+ * switching between the two clients randomly would be disasterous.
*
* @param $params array
*
$mProperties = array(), # Name/value pairs to be cached in the DB
$mTOCHTML = '', # HTML of the TOC
$mTimestamp; # Timestamp of the revision
+ private $mIndexPolicy = ''; # 'index' or 'noindex'? Any other value will result in no change.
+ private $mAccessedOptions = array(); # List of ParserOptions (stored in the keys)
/**
- * 'index' or 'noindex'? Any other value will result in no change.
- *
- * @var string
- */
- protected $mIndexPolicy = '';
-
- /**
- * List of ParserOptions (stored in the keys)
- *
- * @var array
- */
- protected $mAccessedOptions = array();
-
- /**
- * List of instances of SecondaryDataObject(), used to cause some information extracted from the page in a custom place.
+ * List of instances of DataUpdate(), used to cause some information extracted from the page in a custom place.
* @since WD.1
- * @var array of SecondaryDataObject
+ * @var array of DataUpdate
*/
protected $mSecondaryDataUpdates = array();
$this->mAccessedOptions[$option] = true;
}
- /**
- * Adds an update job to the output. Any update jobs added to the output will eventually bexecuted in order to
- * store any secondary information extracted from the page's content.
- *
- * @since WD.1
+ /**
+ * Adds an update job to the output. Any update jobs added to the output will eventually bexecuted in order to
+ * store any secondary information extracted from the page's content.
*
- * @param SecondaryDataUpdate $update
- */
- public function addSecondaryDataUpdate( SecondaryDataUpdate $update ) {
- $this->mSecondaryDataUpdates[] = $update;
- }
-
- /**
- * Returns any SecondaryDataUpdate jobs to be executed in order to store secondary information
- * extracted from the page's content, includingt a LinksUpdate object for all links stopred in
- * this ParserOutput object.
- *
- * @since WD.1
+ * @param StorageUpdate $update
+ */
+ public function addSecondaryDataUpdate( DataUpdate $update ) {
+ $this->mSecondaryDataUpdates[] = $update;
+ }
+
+ /**
+ * Returns any DataUpdate jobs to be executed in order to store secondary information
+ * extracted from the page's content, including a LinksUpdate object for all links stored in
+ * this ParserOutput object.
*
- * @param $title Title of the page we're updating. If not given, a title object will be created based on $this->getTitleText()
- * @param $recursive Boolean: queue jobs for recursive updates?
- *
- * @return array an array of instances of SecondaryDataUpdate
- */
- public function getSecondaryDataUpdates( Title $title = null, $recursive = true ) {
- if ( is_null( $title ) ) {
- $title = Title::newFromText( $this->getTitleText() );
- }
-
- return array_merge(
- $this->mSecondaryDataUpdates,
- array( new LinksUpdate( $title, $this, $recursive ) )
- );
- }
+ * @param $title Title of the page we're updating. If not given, a title object will be created based on $this->getTitleText()
+ * @param $recursive Boolean: queue jobs for recursive updates?
+ *
+ * @return Array. An array of instances of DataUpdate
+ */
+ public function getSecondaryDataUpdates( Title $title = null, $recursive = true ) {
+ if ( !$title ) {
+ $title = Title::newFromText( $this->getTitleText() );
+ }
+
+ $linksUpdate = new LinksUpdate( $title, $this, $recursive );
+
+ if ( !$this->mSecondaryDataUpdates ) {
+ return array( $linksUpdate );
+ } else {
+ $updates = array_merge( $this->mSecondaryDataUpdates, array( $linksUpdate ) );
+ }
+
+ return $updates;
+ }
}
}
/**
- * @param $args
+ * @param $args array
* @return PPCustomFrame_DOM
*/
function newCustomFrame( $args ) {
}
/**
- * @param $args
+ * @param $args array
* @return PPCustomFrame_Hash
*/
function newCustomFrame( $args ) {
const CACHE_VERSION = 1;
+ /**
+ * @param $parser Parser
+ */
function __construct( $parser ) {
$this->parser = $parser;
}
}
/**
- * @param $args
+ * @param $args array
* @return PPCustomFrame_HipHop
*/
function newCustomFrame( array $args ) {
* cache may be implemented at a later date which takes further advantage of these strict
* dependency requirements.
*
+ * @throws MWException
* @return PPNode_HipHop_Tree
*/
function preprocessToObj( string $text, int $flags = 0 ) {
* @ingroup Parser
*/
class PPDStackElement_HipHop {
- var $open, // Opening character (\n for heading)
- $close, // Matching closing character
+ var $open, // Opening character (\n for heading)
+ $close, // Matching closing character
$count, // Number of opening characters found (number of "=" for heading)
$parts, // Array of PPDPart objects describing pipe-separated parts.
$lineStart; // True if the open char appeared at the start of the input line. Not set for headings.
+ /**
+ * @param $obj PPDStackElement_HipHop
+ * @return PPDStackElement_HipHop
+ */
static function cast( PPDStackElement_HipHop $obj ) {
return $obj;
}
+ /**
+ * @param $data array
+ */
function __construct( $data = array() ) {
$this->parts = array( new PPDPart_HipHop );
}
}
+ /**
+ * @return PPDAccum_HipHop
+ */
function getAccum() {
return PPDAccum_HipHop::cast( $this->parts[count($this->parts) - 1]->out );
}
+ /**
+ * @param $s string
+ */
function addPart( $s = '' ) {
$this->parts[] = new PPDPart_HipHop( $s );
}
+ /**
+ * @return PPDPart_HipHop
+ */
function getCurrentPart() {
return PPDPart_HipHop::cast( $this->parts[count($this->parts) - 1] );
}
/**
* Get the accumulator that would result if the close is not found.
*
+ * @param $openingCount bool
* @return PPDAccum_HipHop
*/
function breakSyntax( $openingCount = false ) {
* Create a new child frame
* $args is optionally a multi-root PPNode or array containing the template arguments
*
- * @param $args PPNode_HipHop_Array|array
- * @param $title Title|false
+ * @param $args PPNode_HipHop_Array|array|bool
+ * @param $title Title|bool
*
+ * @throws MWException
* @return PPTemplateFrame_HipHop
*/
function newChild( $args = false, $title = false ) {
/**
* Implode with no flags specified
* This previously called implodeWithFlags but has now been inlined to reduce stack depth
+ * @param $sep
* @return string
*/
function implode( $sep /*, ... */ ) {
* Makes an object that, when expand()ed, will be the same as one obtained
* with implode()
*
+ * @param $sep
* @return PPNode_HipHop_Array
*/
function virtualImplode( $sep /*, ... */ ) {
/**
* Virtual implode with brackets
*
+ * @param $start
+ * @param $sep
+ * @param $end
* @return PPNode_HipHop_Array
*/
function virtualBracketedImplode( $start, $sep, $end /*, ... */ ) {
var $numberedExpansionCache, $namedExpansionCache;
/**
- * @param $preprocessor
- * @param $parent
+ * @param $preprocessor Preprocessor_HipHop
+ * @param $parent bool
* @param $numberedArgs array
* @param $namedArgs array
- * @param $title Title
+ * @param $title Title|bool
*/
function __construct( $preprocessor, $parent = false, $numberedArgs = array(), $namedArgs = array(), $title = false ) {
parent::__construct( $preprocessor );
return $this->nextSibling;
}
+ /**
+ * @param $name string
+ * @return array
+ */
function getChildrenOfType( $name ) {
$children = array();
for ( $child = $this->firstChild; $child; $child = $child->nextSibling ) {
* index String index
* value PPNode value
*
+ * @throws MWException
* @return array
*/
function splitArg() {
* Split an <ext> node into an associative array containing name, attr, inner and close
* All values in the resulting array are PPNodes. Inner and close are optional.
*
+ * @throws MWException
* @return array
*/
function splitExt() {
/**
* Split an <h> node
*
+ * @throws MWException
* @return array
*/
function splitHeading() {
'MAX(ipb_user) AS blocked'
),
'options' => array(
- 'GROUP BY' => 'rc_user_text, user_id',
+ 'GROUP BY' => array( 'rc_user_text', 'user_id' ),
'USE INDEX' => array( 'recentchanges' => 'rc_user_text' )
),
'join_conds' => array(
array( 'wl_namespace', 'wl_title' ),
array( 'wl_user' => $this->getUser()->getId() ),
__METHOD__,
- array( 'ORDER BY' => 'wl_namespace, wl_title' )
+ array( 'ORDER BY' => array( 'wl_namespace', 'wl_title' ) )
);
$lb = new LinkBatch();
// useful to remove this. People _do_ create pages
// and never revise them, they aren't necessarily
// redirects.
- 'GROUP BY' => 'page_namespace, page_title, page_is_redirect' )
+ 'GROUP BY' => array( 'page_namespace', 'page_title', 'page_is_redirect' ) )
);
}
if( $dbr->implicitGroupby() ) {
$options = array( 'GROUP BY' => 'img_name' );
} else {
- $columnlist = implode( ',',
- preg_grep( '/^img/', array_keys( $this->getFieldNames() ) ) );
- $options = array( 'GROUP BY' => "img_user, $columnlist" );
+ $columnlist = preg_grep( '/^img/', array_keys( $this->getFieldNames() ) );
+ $options = array( 'GROUP BY' => array_merge( array( 'img_user' ), $columnlist ) );
}
$join_conds = array( 'oldimage' => array( 'LEFT JOIN', 'oi_name = img_name' ) );
}
'COUNT(*) AS value' ),
'conds' => array ( 'page_namespace' => MWNamespace::getContentNamespaces() ),
'options' => array ( 'HAVING' => 'COUNT(*) > 1',
- 'GROUP BY' => 'page_namespace, page_title' ),
+ 'GROUP BY' => array( 'page_namespace', 'page_title' ) ),
'join_conds' => array ( 'page' => array ( 'LEFT JOIN',
'page_id = cl_from' ) )
);
'COUNT(*) AS value',
'page_namespace' ),
'options' => array ( 'HAVING' => 'COUNT(*) > 1',
- 'GROUP BY' => 'pl_namespace, pl_title, '.
- 'page_namespace' ),
+ 'GROUP BY' => array( 'pl_namespace', 'pl_title',
+ 'page_namespace' ) ),
'join_conds' => array ( 'page' => array ( 'LEFT JOIN',
array ( 'page_namespace = pl_namespace',
'page_title = pl_title' ) ) )
'tl_title AS title',
'COUNT(*) AS value' ),
'conds' => array ( 'tl_namespace' => NS_TEMPLATE ),
- 'options' => array( 'GROUP BY' => 'tl_namespace, tl_title' )
+ 'options' => array( 'GROUP BY' => array( 'tl_namespace', 'tl_title' ) )
);
}
$condition,
__METHOD__,
array(
- 'GROUP BY' => 'ar_namespace,ar_title',
- 'ORDER BY' => 'ar_namespace,ar_title',
+ 'GROUP BY' => array( 'ar_namespace', 'ar_title' ),
+ 'ORDER BY' => array( 'ar_namespace', 'ar_title' ),
'LIMIT' => 100,
)
)
),
'options' => array(
'HAVING' => "COUNT(*) > $count",
- 'GROUP BY' => 'pl_namespace, pl_title'
+ 'GROUP BY' => array( 'pl_namespace', 'pl_title' )
),
'join_conds' => array(
'pg1' => array(
'conds' => array ( 'page_title IS NULL',
'tl_namespace' => NS_TEMPLATE ),
'options' => array (
- 'GROUP BY' => 'tl_namespace, tl_title' ),
+ 'GROUP BY' => array( 'tl_namespace', 'tl_title' ) ),
'join_conds' => array ( 'page' => array ( 'LEFT JOIN',
array ( 'page_namespace = tl_namespace',
'page_title = tl_title' ) ) )
'revdelete-uname-hid' => 'скрито потребителско име',
'revdelete-restricted' => 'добавени ограничения за администраторите',
'revdelete-unrestricted' => 'премахнати ограничения за администраторите',
-'logentry-move-move' => '$1 премести страницата $3 към заглавие $4',
-'logentry-move-move-noredirect' => '$1 премести страницата $3 към заглавие $4 без да оставя пренасочване',
+'logentry-move-move' => '$1 премести „$3“ като „$4“',
+'logentry-move-move-noredirect' => '$1 премести „$3“ като „$4“ без пренасочване',
'logentry-move-move_redir' => '$1 премести страницата $3 като $4 (върху пренасочване)',
-'logentry-move-move_redir-noredirect' => '$1 премести върху пренасочване страницата $3 към заглавие $4 (без пренасочване)',
+'logentry-move-move_redir-noredirect' => '$1 премести върху пренасочване „$3“ като „$4“ без пренасочване',
'logentry-patrol-patrol' => '$1 отбеляза като патрулирана версия $4 на страницата „$3“',
'logentry-patrol-patrol-auto' => '$1 автоматично отбеляза като патрулирана версия $4 на страницата $3',
'logentry-newusers-newusers' => '$1 създаде потребителска сметка',
'parser-template-loop-warning' => 'Rekursiva ŝablono estis trovita: [[$1]]',
'parser-template-recursion-depth-warning' => 'Limo de ŝablona profundeco pligrandiĝis ($1)',
'language-converter-depth-warning' => 'Profundo de lingvo-konvertilo preterpasis limon ($1)',
-'node-count-exceeded-category' => 'Paĝoj kie la nombro da nodoj estis preterpasita',
+'node-count-exceeded-category' => 'Paĝoj kie la nombro da nodoj estas preterpasita',
'node-count-exceeded-warning' => 'Paĝo preterpasis la nombron da nodoj.',
-'expansion-depth-exceeded-category' => 'Paĝoj en kiuj la ekpansiprofundo estis preterpasita.',
+'expansion-depth-exceeded-category' => 'Paĝoj en kiuj la ekpansiprofundo estas preterpasita',
'expansion-depth-exceeded-warning' => 'Paĝo preterpasis la ekpansiprofundon.',
# "Undo" feature
'userrights-groups-help' => 'Puedes modificar los grupos a los que pertenece {{GENDER:$1|este usuario|esta usuaria}}:
* Un recuadro marcado significa que {{GENDER:$1|el usuario|la usuaria}} está en ese grupo.
* Un recuadro no marcado significa que {{GENDER:$1|el usuario|la usuaria}} no está en ese grupo.
-* Un * indica que no podrás retirar el grupo una vez que lo concedas, o viceversa.',
+* Un * indica que no podrás eliminar el grupo una vez que lo agregues, o viceversa.',
'userrights-reason' => 'Motivo:',
'userrights-no-interwiki' => 'No tienes permiso para editar los grupos a los que pertenece un usuario en otros wikis.',
'userrights-nodatabase' => 'La base de datos $1 no existe o no es local.',
'subject' => 'Bedrååwet:',
'minoredit' => 'Bloot kleenihäide wörden feränred',
'watchthis' => 'Kiike eefter jüdeer sid',
-'savearticle' => 'Sid spikre',
+'savearticle' => 'Sidj seekre',
'preview' => 'Forlök',
'showpreview' => 'Forlök wise',
'showlivepreview' => 'Live-forkiik',
'tooltip-ca-nstab-help' => 'Heelpsid wise',
'tooltip-ca-nstab-category' => 'Kategoriisid wise',
'tooltip-minoredit' => 'Jüdeer änring as latj markiire.',
-'tooltip-save' => 'Änringe spikre',
+'tooltip-save' => 'Feranerangen seekre',
'tooltip-preview' => 'Forlök foon da änringe bai jüdeer sid. Hål for dåt spikern brüke!',
'tooltip-diff' => 'Änringe bai di täkst wise',
'tooltip-compareselectedversions' => 'Ferschääl twasche tou ütwäälde färsjoone foon jüdeer sid wise.',
Estes argumentos foron omitidos.",
'post-expand-template-argument-category' => 'Páxinas que conteñen argumentos de modelo omitidos',
'parser-template-loop-warning' => 'Detectouse un modelo en bucle: [[$1]]',
-'parser-template-recursion-depth-warning' => 'Excedeuse o límite da profundidade do recurso do modelo ($1)',
+'parser-template-recursion-depth-warning' => 'Excedeuse o límite de profundidade de recursión do modelo ($1)',
'language-converter-depth-warning' => 'Excedeuse o límite de profundidade do convertedor de lingua ($1)',
'node-count-exceeded-category' => 'Páxinas nas que se supera o número de nodos',
'node-count-exceeded-warning' => 'Páxina que supera o número de nodos',
'expansion-depth-exceeded-category' => 'Páxinas nas que se supera a profundidade de expansión',
'expansion-depth-exceeded-warning' => 'Páxina que supera a profundidade de expansión',
+'parser-unstrip-loop-warning' => 'Detectouse un bucle inamovible',
+'parser-unstrip-recursion-limit' => 'Excedeuse o límite de recursión inamovible ($1)',
# "Undo" feature
'undo-success' => 'A edición pódese desfacer.
# Diffs
'history-title' => 'Historial de revisións de "$1"',
+'difference-title' => 'Diferenzas entre revisións de "$1"',
+'difference-title-multipage' => 'Diferenzas entre as páxinas "$1" e "$2"',
'difference-multipage' => '(Diferenzas entre páxinas)',
'lineno' => 'Liña $1:',
'compareselectedversions' => 'Comparar as versións seleccionadas',
'updated' => '(Ažurirano)',
'note' => "'''Napomena:'''",
'previewnote' => "'''Ne zaboravite da je ovo samo pregled kako će stranica izgledati i da stranica još nije snimljena!'''",
+'continue-editing' => 'Nastavi uređivati',
'previewconflict' => 'Ovaj pregled odražava stanje u gornjem polju za unos koje će biti sačuvano
ako pritisnete "Sačuvaj stranicu".',
'session_fail_preview' => "'''Ispričavamo se! Nismo mogli obraditi Vašu izmjenu zbog gubitka podataka o prijavi.
'summary-preview' => "Anteprima dell'oggetto:",
'subject-preview' => 'Anteprima oggetto/intestazione:',
'blockedtitle' => 'Utente bloccato.',
-'blockedtext' => "'''Questo nome utente o indirizzo IP sono stati bloccati.'''
+'blockedtext' => "'''Il tuo nome utente o indirizzo IP è stato bloccato.'''
Il blocco è stato imposto da $1. La motivazione del blocco è la seguente: ''$2''
# Diffs
'history-title' => 'Cronologia delle modifiche di "$1"',
-'difference-title' => 'Differenza tra le revisioni di " $1 "',
-'difference-title-multipage' => 'Differenza tra le pagine " $1 "e" $2 "',
+'difference-title' => 'Differenza tra le versioni di "$1"',
+'difference-title-multipage' => 'Differenza tra le pagine "$1" e "$2"',
'difference-multipage' => '(Differenze fra le pagine)',
'lineno' => 'Riga $1:',
'compareselectedversions' => 'Confronta le versioni selezionate',
IP アドレスは複数の利用者で共有されている場合があります。
もし、あなたが匿名利用者であり、自分に関係のないコメントが寄せられている考えられる場合は、[[Special:UserLogin/signup|アカウントを作成する]]か[[Special:UserLogin|ログインして]]他の匿名利用者と間違えられないようにしてください。''",
'noarticletext' => '現在このページには内容がありません。
-他のページ内で[[Special:Search/{{PAGENAME}}|このページ名を検索する]]か、
+他のページ内で[[Special:Search/{{PAGENAME}}|このページ名を検索]]するか、
<span class="plainlinks">[{{fullurl:{{#Special:Log}}|page={{FULLPAGENAMEE}}}} 関連する記録を検索]するか、
-あるいは、[{{fullurl:{{FULLPAGENAME}}|action=edit}} このページを編集]</span>できます。',
+[{{fullurl:{{FULLPAGENAME}}|action=edit}} このページを編集]</span>することができます。',
'noarticletext-nopermission' => '現在このページには内容がありません。他のページに含まれる[[Special:Search/{{PAGENAME}}|このページ名を検索する]]か、もしくは<span class="plainlinks">[{{fullurl:{{#Special:Log}}|page={{FULLPAGENAMEE}}}} 関連記録を検索する]</span>ことができます。',
'userpage-userdoesnotexist' => '「$1」という利用者アカウントは登録されていません。
このページの作成/編集が適切かどうか確認してください。',
'mywatchlist' => 'ウォッチリスト',
'watchlistfor2' => '利用者: $1 $2',
'nowatchlist' => 'ウォッチリストに項目がありません。',
-'watchlistanontext' => 'ウォッチリストに入っている項目を表示または編集するには、$1してください。',
+'watchlistanontext' => 'ウォッチリストにある項目を閲覧または編集するには、$1してください。',
'watchnologin' => 'ログインしていません',
'watchnologintext' => 'ウォッチリストを変更するためには、[[Special:UserLogin|ログイン]]している必要があります。',
'addwatch' => 'ウォッチリストに追加',
'tooltip-n-mainpage' => 'メインページに移動',
'tooltip-n-mainpage-description' => 'メインページに移動する',
'tooltip-n-portal' => 'このプロジェクトについて、できること、情報を入手する場所',
-'tooltip-n-currentevents' => 'æ\9c\80è¿\91ã\81®å\87ºæ\9d¥äº\8bã\81«ã\81¤ã\81\84ã\81¦äº\88å\82\99ç\9f¥è\98ã\82\92å¾\97る',
+'tooltip-n-currentevents' => 'æ\9c\80è¿\91ã\81®å\87ºæ\9d¥äº\8bã\81®è\83\8cæ\99¯ã\82\92ç\9f¥る',
'tooltip-n-recentchanges' => 'このウィキにおける最近の更新の一覧',
-'tooltip-n-randompage' => '無作為に抽出されたページの読み込み',
+'tooltip-n-randompage' => '無作為に選ばれたページを読み込む',
'tooltip-n-help' => '情報を得る場所',
'tooltip-t-whatlinkshere' => 'ここにリンクしている全ウィキページの一覧',
'tooltip-t-recentchangeslinked' => 'このページからリンクしているページの最近の更新',
'minoreditletter' => 't',
'newpageletter' => 'T',
'boteditletter' => 'k',
+'newsectionsummary' => '/* $1 */ hläwm thar',
'rc-enhanced-expand' => 'Tilang kim rawh (JavaScript a ngai)',
'rc-enhanced-hide' => 'Thup ţhenna',
'rc-old-title' => 'Atìra "&1" tih hming pú-a siam.',
'upload-recreate-warning' => "'''Vaukhànna: Hemi hming pu taksa hi sawn tawh emaw paih tawh a ni.'''
I ràwnah paihna leh sawnna chhinchhiahna thuziak kan rawn chhawpchhuak e:",
+'uploadtext' => "Taksa hlankai nan a hnuaia lehkha hi hmang rawh.
+Ahmaa taksa hlankaisaho en tùr emaw zawng tùr chuan [[Special:FileList|taksa hlankai tawh zawng zawng tlarna]] tihah hian kal rawh; hlankai (nawn)ho pawh [[Special:Log/upload|hlankai chhinchhiahna]]-ah vawnfel an ni a, paih tawhho pawh [[Special:Log/delete|paihho chhinchhiahna]]-ah chhinchhiah fel vek an ni.
+
+Phêka taksa hmang tùrin ahnuaia tihphung engemaw ni ber hmang khuan zawmna i siam thei ang:
+*A taksa pumpui hmang tùr chuan '''<tt><nowiki>[[</nowiki>{{ns:file}}<nowiki>:File.jpg]]</nowiki></tt>''' tiin. Heti hi chuan taksa hi i sezawl chhuah a ni.
+*Phêk veilam síra 'Sawifiahna' hmanga 200px-a liana i tàrlan duh chuan '''<tt><nowiki>[[</nowiki>{{ns:file}}<nowiki>:File.png|200px|thumb|left|Sawifiahna]]</nowiki></tt>''' tiin.
+*A taksa tárlang lova zawm ringawt i duh chuan '''<tt><nowiki>[[</nowiki>{{ns:media}}<nowiki>:File.ogg]]</nowiki></tt>''' tiin.",
'upload-permitted' => 'Taksa phal chiho: $1.',
'upload-preferred' => 'Taksa duh deuh bîk: $1.',
'upload-prohibited' => 'Taksa khap: $1.',
-'uploadlog' => 'chanchin hlankaina',
+'uploadlog' => 'hlankai chhinchhiahna',
'uploadlogpage' => 'Hlankai chhinchhiahna',
+'uploadlogpagetext' => 'Taksa hlankai thar deuh deuh kan rawn tlar chhuak e.
+A aia hmuhnawm deuh zâwka i thlìr duh chuan [[Special:NewFiles|taksa hlankai thar tàrhmunpui]]-ah i kal thei ang.',
'filename' => 'Taksahming',
-'filedesc' => 'Laktawi',
-'fileuploadsummary' => 'Kaihtawi:',
+'filedesc' => 'Sawifiahna täwi',
+'fileuploadsummary' => 'Sawifiahna täwi:',
'filereuploadsummary' => 'Taksa tihdanglamna:',
-'filestatus' => 'Copyright dinhmun:',
+'filestatus' => 'Lâkchhàwn phalphung dinhmun:',
'filesource' => 'Hnar:',
'uploadedfiles' => 'Taksa hlankai tawhte',
'ignorewarning' => 'Vaukhanna ngaihthah la taksa dahţha lui rawh',
A hming thlâk la bei ţha leh rawh.',
'filename-toolong' => 'Taksahming 240 bytes aiin a sei tùr a ni lo.',
'badfilename' => 'Taksahming "$1"-ah thlâk a ni.',
-'filetype-missing' => 'Taksa in tawpna a nei lo (entirna ".jpg").',
+'filetype-missing' => 'Taksain tawpna a nei lo (entirna ".jpg").',
'empty-file' => 'I taksa thehluh kha a ruak.',
'file-too-large' => 'A lian leh lutuk.',
'filename-tooshort' => 'Taksahming a sawi leh lutuk.',
'illegal-filename' => 'Taksahming phal loh.',
'overwrite' => 'Taksa awmsa ziah hnan khap a ni.',
'unknown-error' => 'Dikhlelhna hriat loh a lo thleng.',
+'tmp-create-error' => 'Taksa lailâwk a siam theih loh.',
+'tmp-write-error' => 'Taksa lailâwk ziah a tlawlh',
+'large-file' => 'Taksa rëng rëng $1 aia lian lo tùra duh a ni;
+he taksa hi $2 lái a ni.',
+'largefileserver' => 'Hë taksa hi rawngbawltu phaltir zât aia ritsak a ni.',
+'windows-nonascii-filename' => 'Hë wiki hian taksahminga chhinchhiahna bîk tel a pawm thei lo.',
+'savefile' => 'Taksa dahṭhatna',
'uploadedimage' => 'hlankai: "[[$1]]"',
+'upload-source' => 'Hnar taksa',
+'sourcefilename' => 'Hnar taksahming:',
+'sourceurl' => 'Hnar URL:',
+'destfilename' => 'Tumhmun taksahming:',
+'upload-maxfilesize' => 'Taksa lenzáwng bituk: $1 aia lian lo.',
+'upload-description' => 'Taksa sawifiahna',
+'upload-options' => 'Hlankai duhdàn thlanna',
+'watchthisupload' => 'Hë taksa hi vil rawh',
+'filewasdeleted' => 'He hming pu taksa hi ahmaah lo hlankai tawh a ni a, paihbo leh nghâl a ni.
+Hlankai leh i tum hmain $1 i thlïthläi deuh dawn nia.',
+'upload-success-subj' => 'Hlawhtling taka hlankai a ni',
+'upload-success-msg' => '[$2] aṭangin i hlangkai hlawhtling ta e. Hetah hian hman theihin a awm ta: [[:{{ns:file}}:$1]]',
+'upload-failure-subj' => 'Hlankai rokhawlhna',
+'upload-failure-msg' => '[$2] aṭanga i hlankai tumnaah rokhawlhna a awm tlat:
+
+$1',
+'upload-warning-subj' => 'Hlankai vauhkhànna',
+'upload-warning-msg' => '[$2] aṭanga i hlankaiah rokhawlhna a awm tlat. [[Special:Upload/stash/$1|Hlankaina lehkha]]-ah chingfel tùrin i lêt leh thei ang.',
-'license' => 'Phalna:',
-'license-header' => 'Phalna:',
+'upload-proto-error' => 'Inpawhphung dikhlel',
+'upload-file-error' => 'Chhúnglam dik lohna',
+
+'license' => 'Phalphung:',
+'license-header' => 'Phalphung:',
+'nolicense' => 'I la thlang lo',
+'license-nopreview' => '(Endik chhin theih loh)',
+'upload_source_url' => '(URL tláng pawh theih, nung bawk)',
+'upload_source_file' => '(i khawlthlûakneia mi taksa)',
# Special:ListFiles
-'imgfile' => 'taksa (file)',
+'listfiles-summary' => 'Hë vohbîk phêk hian taksa hlankai tawh zawng zawng a pholang.
+Hmangtu azira i thliarhran erawh chuan a hmangtuina a hlankai hnuhnüng ber taksa chauh pholan a ni.',
+'listfiles_search_for' => 'Media hming zawnna:',
+'imgfile' => 'taksa',
'listfiles' => 'Taksa tlarna',
'listfiles_thumb' => 'Kutbï',
'listfiles_date' => 'Ni',
'filehist-missing' => 'Taksa a awm lo',
'imagelinks' => 'Bungraw hmanna',
'linkstoimage' => 'A hnuai {{PLURAL:$1|phek 1|phek $1-te}} hian he taksa hi a hmang:',
+'linkstoimage-more' => 'Hë taksa hi phêk {{PLURAL:$1||}} $1 aia tamin a zawm/hmang.
+Ahnuaih hian {{PLURAL:$1|zawmtu hmasa ber|zawmtu hmasa $1-te}} kan rawn tlar chhuak e.
+Zawmtu zawng zawng [[Special:WhatLinksHere/$2|tlarchhuahna hetah hian a awm]] e.',
'nolinkstoimage' => 'He taksa zawmtu/hmanna phêk pakhat mah a awm lo.',
+'morelinkstoimage' => 'Hemi taksa zawmpui dang [[Special:WhatLinksHere/$1|enna}}.',
+'linkstoimage-redirect' => '$1 (taksa hruailuhna) $2',
+'sharedupload' => 'Hë taksa hi $1-a mi a ni a, hna-hmachhawp dangin a hmang vè mai thei.',
+'sharedupload-desc-there' => 'Hë taksa hi $1-a mi a ni a, hna-hmachhawp dangin a hmang ve mai thei.
+Hriattirna dang chu [$2 taksa sawifiahna phêk]-ah hian i en thei ang.',
'sharedupload-desc-here' => 'He taksa hi $1-a mi a ni a, hna-hmachhawp dangin an hmang ve mai thei.
[Taksa sawifiahna phek $2]-a sawifiahna lang hetah hian kan rawh chhawp chhuak e.',
+'sharedupload-desc-edit' => 'Hë taksa hi $1-a mi a ni a, hna-hmachhawp dangin a hmang vè mai thei.
+Taksa sawifiahna hi i siamṭha duh a nih chuan [$2 taksa sawifiahna phêk] aṭang hian i siamṭha thei ang.',
'filepage-nofile' => 'He hmingpu taksa a awm lo',
'filepage-nofile-link' => 'He hming pu taksa hi a awm lo va, mahsé i [$1 hlangkai thei] ang.',
'uploadnewversion-linktext' => 'He taksa chhuah thar hi hlangkai rawh',
# Statistics
'statistics' => 'Lepsena',
'statistics-pages' => 'Phekte',
-
+'statistics-pages-desc' => 'Hë wiki-a phêk awm zawng zawng, sawihona phêk, hruailuhna phêk ladt. tel vekin.',
+'statistics-files' => 'Taksa hlankaite',
+'statistics-edits' => '{{SITENAME}} din achina phêk khawih danglam zât',
+'statistics-edits-average' => 'Phêk khat zëla siamṭhat zât chawhrual',
+'statistics-views-total' => 'Tlawh zât',
+'statistics-views-total-desc' => 'Phêk awm lo leh phêk vohbîkte tlawhna chu chhiar tel a ni lo',
+'statistics-views-peredit' => 'Siamṭhat pakhat zël tlawh zât',
+'statistics-users' => '[[Special:ListUsers|Hmangtu]] inziaklût zât',
+'statistics-users-active' => 'Hmangtu aktif zât',
+'statistics-users-active-desc' => 'Ni {{PLURAL:$1|khat|$1}} kaltâ chhunga thiltih nei hmangtuho',
+'statistics-mostpopular' => 'Phêk thlir zin deuh deuhte',
+
+'disambiguations' => 'Thliarfelna phêk zawmtu phêkte',
'disambiguationspage' => 'Template:thliar',
+'doubleredirects' => 'Hruailuhna phír',
+'double-redirect-fixed-move' => '[[$1]] sawn a ni ta.
+[[$2]] lama hruailuhna siam nghâl a ni.',
+'double-redirect-fixed-maintenance' => '[[$1]] aṭanga [[$2]] hruailuhna phír chinfel.',
+'double-redirect-fixer' => 'Hruailuhna chingfeltu',
+
+'brokenredirects' => 'Hruailuhna kehchhia',
+'brokenredirectstext' => 'Ahnuaia hruailuhnate hian phêk awm lova hruailuh an tum:',
'brokenredirects-edit' => 'siamţhatna',
'brokenredirects-delete' => 'paihna',
# Miscellaneous special pages
'nbytes' => 'Bait {{PLURAL:$1||}} $1',
-'nmembers' => 'Tel (a chhunga awm) {{PLURAL:$1||$1}}',
+'nmembers' => 'A chhungah {{PLURAL:$1||$1}} a awm.',
+'nrevisions' => 'siamṭhatna $1 {{PLURAL:$1||}}',
+'nviews' => 'vawi $1 {{PLURAL:$1||}} ràwn a ni tawh.',
+'nimagelinks' => 'Phêk $1-ah {{PLURAL:$1||}} hman a ni.',
+'ntransclusions' => 'phêk $1-ah {{PLURAL:$1||}} hman a ni.',
+'specialpage-empty' => 'Thuhawn a awm lo tlat.',
+'lonelypages' => 'Phêk fahrahte',
+'uncategorizedpages' => 'Páwl nei lo phêkte',
+'uncategorizedcategories' => 'Páwl nei lo páwlte',
+'uncategorizedimages' => 'Páwl nei lo taksate',
+'uncategorizedtemplates' => 'Páwl nei lo siamsâte',
+'unusedcategories' => 'Páwl hman lohte',
+'unusedimages' => 'Taksa hman hlawh lote',
'popularpages' => 'Phêk lärte',
-'prefixindex' => 'Hmabet nei phek zawng zawng',
+'wantedcategories' => 'Páwl mamawhte',
+'wantedpages' => 'Phêk mamawhte',
+'wantedpages-badtitle' => 'Phêk hming dik lo: $1',
+'wantedfiles' => 'Taksa mamawhte',
+'wantedtemplates' => 'Siamsa mamawhte',
+'mostlinked' => 'Phêk zawm hlawh berte',
+'mostlinkedcategories' => 'Pawl zawm hlawh berte',
+'mostlinkedtemplates' => 'Siamsa hman hlawh berte',
+'mostcategories' => 'Telna páwl ngah ber phêkte',
+'mostimages' => 'Taksa hman hlawh berte',
+'mostrevisions' => 'Phêk siam danglam zin berte',
+'prefixindex' => 'Hemi hmabet nei phek zawng zawng',
+'prefixindex-namespace' => 'Hemi ($1 hminghmun) hmabeta neih phêk zawng zawngte',
+'shortpages' => 'Phêk täwite',
+'longpages' => 'Phêk seite',
+'deadendpages' => 'Phêk ralthümte',
+'protectedpages' => 'Phêk vènhimte',
+'protectedpages-indef' => 'Phêk vènhim kumhlunho chauh',
+'protectedpagestext' => 'A hnuaia phêkte hi sawn emaw siam danglam theih loh tùra vènhim an ni',
+'protectedtitles' => 'Hming vènhimte',
+'listusers' => 'Hmangtu tlarna',
+'listusers-editsonly' => 'Siam danglam nei hmangtu chauh pholang rawh',
+'listusers-creationsort' => 'Siam ni indawtin tlar rawh',
+'usereditcount' => 'Siam danglam {{PLURAL:||}} $1',
'usercreated' => '{{GENDER:$3|}} Ni $1, dar $2-a siam',
'newpages' => 'Phek tharte',
'newpages-username' => 'Hmangtu hming:',
'ancientpages' => 'Phek hluiho',
'move' => 'Sawnna',
+'movethispage' => 'Hë phêk hi sawn rawh',
+'notargettitle' => 'Tumhmun nei lo',
+'nopagetitle' => 'Hetiang tumhmun phêk hi a awm lo',
+'nopagetext' => 'I tumhmun sawi kher kha a awm lo niin a lang.',
'pager-newer-n' => '{{PLURAL:$1|thar zawk 1|thar zawk $1}}',
'pager-older-n' => '{{PLURAL:$1|hlui 1|hlui $1}}',
+'suppress' => 'Hmuh hmaih',
# Book sources
'booksources' => 'Lehkhabu rawnte',
'booksources-go' => 'Kal rawh le',
# Special:Log
+'specialloguserlabel' => 'Buatsaihtu:',
+'speciallogtitlelabel' => 'Tumhmun (hming emaw hmangtu):',
'log' => 'Chanchin-ziak',
+'all-logs-page' => 'Chanchin-ziak vàntlang thilte:',
+'log-title-wildcard' => 'Hë thüa inṭan hmingte hi zawng rawh',
# Special:AllPages
'allpages' => 'Phek zawng zawngte',
-'alphaindexline' => '$1 aţanga $2',
+'alphaindexline' => '$1 aṭanga $2',
'nextpage' => 'Phek dawt ($1)',
'prevpage' => 'Phêk hmasa ($1)',
+'allpagesfrom' => 'Hemi aṭanga inṭan hian pholang rawh:',
+'allpagesto' => 'Hemi chin thleng hian:',
'allarticles' => 'Phek zawng zawngte',
'allinnamespace' => 'Phêk zawng zawng (hminghmun $1-a mi)',
'allnotinnamespace' => 'Phêk zawng zawng (hminghmun $1-a awm lo)',
'allpagesprefix' => 'Hemi thuhmabeta neih zawng hi pholang rawh:',
'allpagesbadtitle' => 'Phêk hming dik lo emaw ţawng dang/wiki dang thuhmabet a hmang palh a nih hmel.
Phêk hminga hman awih loh hawrawp a hmang palh a ni mai thei bawk.',
+'allpages-bad-ns' => '{{SITENAME}} hian "$1" tih hminghmun a nei lo.',
+'allpages-hide-redirects' => 'Hruailuhna phêkho thup rawh',
+
+# SpecialCachedPage
+'cachedspecial-refresh-now' => 'A thar ber thlirna.',
# Special:Categories
'categories' => 'Pawlte',
+'categoriespagetext' => 'A hnuaia pawl{{PLURAL:$1||te}} hian phêk emaw media a{{PLURAL:$1||n}} nei.
+Hetah hian [[Special:UnusedCategories|pawl hman lohho]] pholan tel a ni lo.
+[[Special:WantedCategories|Pawl mamawhho]] en bawk la.',
+'categoriesfrom' => 'Hemi-a inṭan pawlho hi pholang rawh:',
+'special-categories-sort-count' => 'a chhúnga thil awm zât azirin thliar rawh',
'special-categories-sort-abc' => 'a-aw-b indawtin',
# Special:DeletedContributions
+'deletedcontributions' => 'Hmangtu kutthawhna paihbo tawhte',
+'deletedcontributions-title' => 'Hmangtu kutthawhna paihbo tawhte',
'sp-deletedcontributions-contribs' => 'kutthawhnate',
# Special:LinkSearch
+'linksearch' => 'Zawmchhuahna zawnna',
+'linksearch-pat' => 'Thu zawn:',
'linksearch-ns' => 'Hminghmun:',
-'linksearch-ok' => 'Zawng rawh',
+'linksearch-ok' => 'Zawng rawh le',
'linksearch-line' => '$1 hi $2 aţanga thlunzawm a ni',
+# Special:ListUsers
+'listusersfrom' => 'Hemi-a inṭanin hmangtuho pholang rawh:',
+'listusers-submit' => 'Pholanna',
+'listusers-noresult' => 'Hmangtu an awm lo.',
+'listusers-blocked' => '(danbeh)',
+
+# Special:ActiveUsers
+'activeusers' => 'Hmangtu hlun tlarna',
+'activeusers-hidebots' => 'Khawlmi thupna',
+'activeusers-hidesysops' => 'Roreltu thupna',
+'activeusers-noresult' => 'Hmangtu awm lo.',
+
# Special:Log/newusers
'newuserlogpage' => 'Hmangtu siamna chanchin-ziak',
+'newuserlogpagetext' => 'Hei hi hmangtu siangchan siam chhinchhiahna a ni.',
# Special:ListGroupRights
+'listgrouprights' => 'Hmangtu pawl dikna-chanvote',
+'listgrouprights-key' => '* <span class="listgrouprights-granted">Dikna-chanvo phalsak</span>
+* <span class="listgrouprights-revoked">Dikna-chanvo hnuhkirsak</span>',
+'listgrouprights-group' => 'Pawl',
+'listgrouprights-rights' => 'Dikna-chanvo',
+'listgrouprights-helppage' => 'Help:Pawl dikna-chanvo',
'listgrouprights-members' => '(tel zawng zawng)',
+'listgrouprights-addgroup' => '{{PLURAL:$2|Pawl|Pawl}} belhna: $1',
# E-mail user
'emailuser' => 'He hmangtu hi e-lehkha thawn rawh',
'unwatch' => 'Vil tihtawpna',
'unwatchthispage' => 'Vil tihtawpna',
'notanarticle' => 'Phêk dikdawh a ni lo.',
+'notvisiblerev' => 'Hmangtu dang tihdanglamna thar paihbo a ni.',
'watchnochange' => 'I hun sawi chhungah khan i ralvèn khawih buai a ni lo.',
'watchlist-details' => 'I ralvèn zing aţanga {{PLURAL:$1| phêk $1 |phêk $1}}, sawihona phêk chhiar lohvin.',
'wlheader-enotif' => '*E-lehkha inhriattirna tihnun a ni.',
Chu tlara zawmna dang awm reng reng chu bîk-thil-a ngaih a ni ang; tlar chhunga taksa awmna tùr phek kan tihna a nih chu.',
# Metadata
-'metadata' => 'Nepnawi (metadata)',
-'metadata-help' => 'He taksa hian hriatna dang a keng tel, thlalakna emaw ami siamna sekrek ilo aţanga lo awm a ni mai thei.
-He taksa hi a tira a nihphung tihdanglam tawh a nih chuan a chanchin ziah khuan a danglam hnu chanchin a huam tel lo mai thei.',
+'metadata' => 'Nepnawi',
+'metadata-help' => 'He taksa hian hriatna dang a keng tel; thlalakna emaw thlachhuina amah siamna sekrek ilo aṭanga lo awm a ni mai thei.
+He taksa hi a tira a nihphung tihdanglam tawh a nih chuan a chanchin ziah khuan a danglam hnu chanchin a hril kim lo mai thei.',
+'metadata-expand' => 'Chanchin kimchang tihlanna',
+'metadata-collapse' => 'Chanchin kimchang thup ṭhenna',
'metadata-fields' => 'Thlalâk chanchin nepnawi he thuthawna tihlante hi thlalâk phek pholan huna chanchin nepnawi dawhkan thleh a nihin tihlan a ni ang.
A bak zawng chu thuhrûk sa vek a ni ang.
* make
* gpsaltitude',
# EXIF tags
+'exif-imagewidth' => 'Zàuzáwng',
+'exif-imagelength' => 'Sànzáwng',
+'exif-bitspersample' => 'Péng khata mal(bit) awm zât',
+'exif-compression' => 'Sàwrtêtphung',
+'exif-photometricinterpretation' => 'Rawng inpawlhphung',
+'exif-orientation' => 'Hawizáwng',
+'exif-samplesperpixel' => 'Péng zât',
+'exif-planarconfiguration' => 'Hriatna inremphung',
+'exif-ycbcrsubsampling' => 'Y leh C inthlauhbï',
+'exif-ycbcrpositioning' => 'Y leh C ṭhuthmun',
+'exif-xresolution' => 'Pheizáwnga tihfiahphung',
+'exif-yresolution' => 'Tungzáwnga tihfiahphung',
+'exif-stripoffsets' => 'Thlalâk hriattirna awmna',
+'exif-rowsperstrip' => 'Ṭhuang khata tlar zât',
+'exif-stripbytecounts' => 'Ṭhuang zàwr zìmtina byte awm zât',
+'exif-jpeginterchangeformat' => 'JPEG SOI dahhmun',
+'exif-jpeginterchangeformatlength' => 'JPEG hriattirna lenzawng (Byte-in)',
+'exif-whitepoint' => 'Hmun vár rawng nihphung',
+'exif-primarychromaticities' => 'Rawng bulbälte nihphung',
+'exif-datetime' => 'Taksa tihdanglam hun leh ni',
+'exif-imagedescription' => 'Lem hming',
+'exif-make' => 'Thlalâkna siamtu',
+'exif-model' => 'Thlalâkna sìamphung',
+'exif-software' => 'Khawlthlûak hman',
+'exif-artist' => 'Buatsaihtu',
+'exif-copyright' => 'Phalna kawltu',
+'exif-exifversion' => 'EXIF chhuah',
+'exif-flashpixversion' => 'Flashpix chhuah chhawmdàwl theih',
+'exif-colorspace' => 'Rawng hmun',
+'exif-componentsconfiguration' => 'Péngtinte awmzia',
+'exif-compressedbitsperpixel' => 'Lem sàwrzìmphung',
+'exif-pixelydimension' => 'Lem zauzáwng',
+'exif-pixelxdimension' => 'Lem sànzáwng',
+'exif-usercomment' => 'Hmangtu kamchhuak',
+'exif-relatedsoundfile' => 'Ritaksa laichinte',
+'exif-datetimeoriginal' => 'Hriattirna siamchhuah hun leh ni',
+'exif-datetimedigitized' => 'Tihkhàwl hun leh ní',
+'exif-subsectime' => 'Tihdanglam hun leh ni',
+'exif-exposuretime' => 'Phochhuah hun',
+'exif-fnumber' => 'F zât',
'exif-source' => 'Hnar:',
'exif-writer' => 'Ziaktu',
'exif-languagecode' => 'Ţawng',
* @author Kaganer
* @author Lajsikonik
* @author Lampak
+ * @author Lazowik
* @author Leinad
* @author Maikking
* @author Marcin Łukasz Kiejzik
# Diffs
'history-title' => 'Historia edycji „$1”',
+'difference-title' => 'Różnica pomiędzy wersjami strony "$1"',
+'difference-title-multipage' => 'Różnica pomiędzy stronami "$1" i "$2"',
'difference-multipage' => '(Różnica między stronami)',
'lineno' => 'Linia $1:',
'compareselectedversions' => 'porównaj wybrane wersje',
'blocklog-showsuppresslog' => 'Este utilizador foi bloqueado e ocultado anteriomente.
O registo de supressão é fornecido abaixo para referência:',
'blocklogentry' => 'bloqueou "[[$1]]" $3. O bloqueio expira em $2.',
-'reblock-logentry' => 'modificou parâmetros de bloqueio de [[$1]] $3. O bloqueio expira em $2.',
+'reblock-logentry' => 'modificou parâmetros de bloqueio de [[$1]] com expiração em $2. $3',
'blocklogtext' => 'Este é um registo de ações de bloqueio e desbloqueio.
Endereços IP sujeitos a bloqueio automático não estão listados.
Consulte a [[Special:BlockList|lista de bloqueios]] para obter a lista de bloqueios e banimentos atualmente válidos.',
'blocklog-showsuppresslog' => 'O usuário foi bloqueado e ocultado anteriormente.
O registro de supressão é fornecido abaixo para referência:',
'blocklogentry' => 'bloqueou "[[$1]]" por $2. $3',
-'reblock-logentry' => 'modificou parâmetros de bloqueio de [[$1]] $3. O bloqueio expira em $2.',
+'reblock-logentry' => 'modificou parâmetros de bloqueio de [[$1]] com expiração em $2. $3',
'blocklogtext' => 'Este é um registro de ações de bloqueio e desbloqueio.
Endereços IP sujeitos a bloqueio automático não são listados.
Consulte a [[Special:BlockList|lista de bloqueios]] para obter a lista de bloqueios e banimentos em efeito neste momento.',
* @author Albinus
* @author David Baskey
* @author Ghonokuashabaskey
+ * @author Joseph Mardy
* @author Nipon087
* @author Salvator
* @author Samar88
$messages = array(
# User preference toggles
'tog-hideminor' => 'Nitaḱ bodolaḱre huḍiṅ kạmi danaṅme',
+'tog-extendwatchlist' => 'Khạli nitoḱ bodolko do baṅ, joto bodolkodo ńeloḱ tạlikare phaylaomẽ.',
'tog-showtoc' => 'Ṭibilre menaḱako ńel ( sakamkore 3 khon jạti hedlayenko)',
'tog-watchcreations' => 'Sakamko songe Ińaḱ ńelok tạlikare benao',
'tog-watchdefault' => 'Sakam tońgey me Iń do ińaḱ ńeloḱ tạlikare joṛaokeda',
'hidetoc' => 'uku, Danaṅ',
'collapsible-collapse' => 'Murchạo caba',
'collapsible-expand' => 'Phaylao',
-'thisisdeleted' => 'N̕el se doho ruạṛ',
+'thisisdeleted' => 'Ńel se nãwã aroe hoyuka?',
'viewdeleted' => '$1 Ńelme',
'feedlinks' => 'Jom oco',
+'site-rss-feed' => 'RSS jom oco',
'site-atom-feed' => ' $1 Jom oco',
'page-atom-feed' => '"$1" khon khudri jom',
'red-link-title' => '$1 (niạ sakamdo bạnuḱa)',
'filereadonlyerror' => 'Nebolo možné modifikovať súbor „$1“, pretože úložisko „$2“ je momentálne v režime len na čítanie.
Správca, ktorý ho zamkol ponúkol toto vysvetlenie: „$3“.',
+'invalidtitle-knownnamespace' => 'Neplatný názov s menným priestorom „$2“ a textom „$3“',
+'invalidtitle-unknownnamespace' => 'Neplatný názov s neznámym číslom menného priestoru „$1“ a textom „$2“',
# Virus scanner
'virus-badscanner' => "Chybná konfigurácia: neznámy antivírus: ''$1''",
'node-count-exceeded-warning' => 'Stránka prekročila povolený počet uzlov',
'expansion-depth-exceeded-category' => 'Stránky s priveľkou hĺbkou expanzie',
'expansion-depth-exceeded-warning' => 'Stránka prekročila povolenú hĺbku expanzie',
+'parser-unstrip-loop-warning' => 'Zistené zacyklenie volania rozširovacej značky',
+'parser-unstrip-recursion-limit' => 'Prektočený limit rekurzie volania rozširovacej značky ($1)',
# "Undo" feature
'undo-success' => 'Úpravu je možné vrátiť. Prosím skontrolujte tento rozdiel, čím overíte, že táto úprava je tá, ktorú chcete, a následne uložte zmeny, čím ukončíte vrátenie.',
# Diffs
'history-title' => 'História revízií „$1“',
+'difference-title' => 'Rozdiel medzi revíziami „$1“',
+'difference-title-multipage' => 'Rozdiel medzi stránkami „$1“ a „$2“',
'difference-multipage' => '(Rozdiel medzi stránkami)',
'lineno' => 'Riadok $1:',
'compareselectedversions' => 'Porovnať označené verzie',
'http-curl-error' => 'Chyba pri sťahovaní URL: $1',
'http-host-unreachable' => 'URL nie je dostupný',
'http-bad-status' => 'Počas požiadavky HTTP nastal problém: $1 $2',
+'http-truncated-body' => 'Telo požiadavky bolo prijaté iba čiastočne.',
# Some likely curl errors. More could be added from <http://curl.haxx.se/libcurl/c/libcurl-errors.html>
'upload-curl-error6' => 'Nedostupný URL',
'vector.css' => '/* Tu umiestnené CSS bude ovplyvňovať používateľov štýlu Vector */',
'print.css' => '/* Tu umiestnené CSS bude ovplyvňovať tlačový výstup */',
'handheld.css' => '/* Tu umiestnené CSS bude ovplyvňovať prenosné zariadenia vychádzajúceho zo štýlu nastaveného v $wgHandheldStyle */',
+'noscript.css' => '/* Tu umiestnené CSS bude ovplyvňovať používateľov s vypnutým JavaScriptom */',
+'group-autoconfirmed.css' => '/* Tu umiestnené CSS bude ovplyvňovať iba používateľov s overenou emailovou adresou */',
+'group-bot.css' => '/* Tu umiestnené CSS bude ovplyvňovať iba robotov */',
+'group-sysop.css' => '/* Tu umiestnené CSS bude ovplyvňovať iba správcov */',
+'group-bureaucrat.css' => '/* Tu umiestnené CSS bude ovplyvňovať iba byrokratov */',
# Scripts
'common.js' => '/* Tu uvedený JavaScript sa nahrá všetkým používateľom pri každom nahraní stránky. */',
'simple.js' => '/* Tu sa nachádzajúci JavaScript sa načíta používateľom vzhľadu Jednoduchý */',
'modern.js' => '/* Tu sa nachádzajúci JavaScript sa načíta používateľom vzhľadu Moderný */',
'vector.js' => '/* Tu sa nachádzajúci JavaScript sa načíta používateľom vzhľadu Vector */',
+'group-autoconfirmed.js' => '/* Tu sa nachádzajúci JavaScript sa načíta používateľom s potvrdenou emailovou adresou */',
+'group-bot.js' => '/* Tu sa nachádzajúci JavaScript sa načíta len robotom */',
+'group-sysop.js' => '/* Tu sa nachádzajúci JavaScript sa načíta len správcom */',
+'group-bureaucrat.js' => '/* Tu sa nachádzajúci JavaScript sa načíta len byrokratom */',
# Metadata
'notacceptable' => 'Wiki server nedokáže poskytovať dáta vo formáte, v akom ich váš klient vie čítať.',
'skinname-chick' => 'Kuriatko',
'skinname-simple' => 'Jednoduchý',
'skinname-modern' => 'Moderný',
+'skinname-vector' => 'Vector',
# Patrolling
'markaspatrolleddiff' => 'Označiť ako stráženú',
# Diffs
'history-title' => 'Lịch sử sửa đổi của “$1”',
+'difference-title' => 'Khác biệt giữa các bản “$1”',
+'difference-title-multipage' => 'Khác biệt giữa các trang “$1” và “$2”',
'difference-multipage' => '(Khác biệt giữa các trang)',
'lineno' => 'Dòng $1:',
'compareselectedversions' => 'So sánh các bản đã chọn',