Merge "Prepare for REL1_31 cut, labelling master as 1.32-alpha"
authorjenkins-bot <jenkins-bot@gerrit.wikimedia.org>
Tue, 17 Apr 2018 21:28:04 +0000 (21:28 +0000)
committerGerrit Code Review <gerrit@wikimedia.org>
Tue, 17 Apr 2018 21:28:04 +0000 (21:28 +0000)
27 files changed:
StartProfiler.sample [deleted file]
includes/DefaultSettings.php
includes/Setup.php
includes/api/i18n/es.json
includes/api/i18n/pt.json
includes/api/i18n/sv.json
includes/deferred/TransactionRoundDefiningUpdate.php
includes/installer/i18n/pt.json
includes/jobqueue/Job.php
includes/jobqueue/JobRunner.php
includes/jobqueue/jobs/RecentChangesUpdateJob.php
includes/libs/rdbms/loadbalancer/LoadBalancer.php
languages/i18n/be-tarask.json
languages/i18n/bn.json
languages/i18n/cs.json
languages/i18n/diq.json
languages/i18n/he.json
languages/i18n/ko.json
languages/i18n/li.json
languages/i18n/pt.json
languages/i18n/sv.json
languages/i18n/szl.json
languages/i18n/th.json
languages/i18n/tr.json
languages/i18n/vec.json
tests/phpunit/autoload.ide.php
tests/qunit/suites/resources/mediawiki/mediawiki.loader.test.js

diff --git a/StartProfiler.sample b/StartProfiler.sample
deleted file mode 100644 (file)
index bdf2139..0000000
+++ /dev/null
@@ -1,38 +0,0 @@
-<?php
-
-/**
- * To use a profiler, copy this file to StartProfiler.php and add:
- *  $wgProfiler['class'] = 'ProfilerXhprof';
- *
- * For output, set the 'output' key to an array of class names, one for each
- * output type you want the profiler to generate. For example:
- *  $wgProfiler['output'] = array( 'ProfilerOutputText' );
- *
- * The output classes available to you by default are ProfilerOutputDb,
- * ProfilerOutputDump, ProfilerOutputStats, ProfilerOutputText, and
- * ProfilerOutputUdp.
- *
- * ProfilerOutputStats outputs profiling data as StatsD metrics. It expects
- * that you have set the $wgStatsdServer configuration variable to the host (or
- * host:port) of your statsd server.
- *
- * ProfilerOutputText will output profiling data in the page body as a comment.
- * You can make the profiling data in HTML render as part of the page content
- * by setting the 'visible' configuration flag:
- *  $wgProfiler['visible'] = true;
- *
- * 'ProfilerOutputDb' expects a database table that can be created by applying
- * maintenance/archives/patch-profiling.sql to your database.
- *
- * 'ProfilerOutputDump' expects a $wgProfiler['outputDir'] telling it where to
- * write dump files. The files produced are compatible with the XHProf gui.
- * For a rudimentary sampling profiler:
- *   $wgProfiler['class'] = 'ProfilerXhprof';
- *   $wgProfiler['output'] = array( 'ProfilerOutputDb' );
- *   $wgProfiler['sampling'] = 50; // one every 50 requests
- * This will use ProfilerStub for non-sampled cases.
- *
- * For performance, the profiler is always disabled for CLI scripts as they
- * could be long running and the data would accumulate. Use the '--profiler'
- * parameter of maintenance scripts to override this.
- */
index 1db3f9f..6d7962c 100644 (file)
@@ -6061,7 +6061,7 @@ $wgUseTeX = false;
 /************************************************************************//**
  * @name   Profiling, testing and debugging
  *
- * To enable profiling, edit StartProfiler.php
+ * See $wgProfiler for how to enable profiling.
  *
  * @{
  */
@@ -6306,6 +6306,66 @@ $wgDevelopmentWarnings = false;
  */
 $wgDeprecationReleaseLimit = false;
 
+/**
+ * Profiler configuration.
+ *
+ * To use a profiler, set $wgProfiler in LocalSetings.php.
+ * For backwards-compatibility, it is also allowed to set the variable from
+ * a separate file called StartProfiler.php, which MediaWiki will include.
+ *
+ * Example:
+ *
+ * @code
+ *  $wgProfiler['class'] = ProfilerXhprof::class;
+ * @endcode
+ *
+ * For output, set the 'output' key to an array of class names, one for each
+ * output type you want the profiler to generate. For example:
+ *
+ * @code
+ *  $wgProfiler['output'] = [ ProfilerOutputText::class ];
+ * @endcode
+ *
+ * The output classes available to you by default are ProfilerOutputDb,
+ * ProfilerOutputDump, ProfilerOutputStats, ProfilerOutputText, and
+ * ProfilerOutputUdp.
+ *
+ * ProfilerOutputStats outputs profiling data as StatsD metrics. It expects
+ * that you have set the $wgStatsdServer configuration variable to the host (or
+ * host:port) of your statsd server.
+ *
+ * ProfilerOutputText will output profiling data in the page body as a comment.
+ * You can make the profiling data in HTML render as part of the page content
+ * by setting the 'visible' configuration flag:
+ *
+ * @code
+ *  $wgProfiler['visible'] = true;
+ * @endcode
+ *
+ * 'ProfilerOutputDb' expects a database table that can be created by applying
+ * maintenance/archives/patch-profiling.sql to your database.
+ *
+ * 'ProfilerOutputDump' expects a $wgProfiler['outputDir'] telling it where to
+ * write dump files. The files produced are compatible with the XHProf gui.
+ * For a rudimentary sampling profiler:
+ *
+ * @code
+ *   $wgProfiler['class'] = 'ProfilerXhprof';
+ *   $wgProfiler['output'] = array( 'ProfilerOutputDb' );
+ *   $wgProfiler['sampling'] = 50; // one every 50 requests
+ * @endcode
+ *
+ * When using the built-in `sampling` option, the `class` will changed to
+ * ProfilerStub for non-sampled cases.
+ *
+ * For performance, the profiler is always disabled for CLI scripts as they
+ * could be long running and the data would accumulate. Use the '--profiler'
+ * parameter of maintenance scripts to override this.
+ *
+ * @since 1.17.0
+ */
+$wgProfiler = [];
+
 /**
  * Only record profiling info for pages that took longer than this
  * @deprecated since 1.25: set $wgProfiler['threshold'] instead.
index cc6915a..ac47b6f 100644 (file)
@@ -37,12 +37,6 @@ if ( !defined( 'MEDIAWIKI' ) ) {
  * Pre-config setup: Before loading LocalSettings.php
  */
 
-// Get profiler configuraton
-$wgProfiler = [];
-if ( file_exists( "$IP/StartProfiler.php" ) ) {
-       require "$IP/StartProfiler.php";
-}
-
 // Start the autoloader, so that extensions can derive classes from core files
 require_once "$IP/includes/AutoLoader.php";
 
@@ -85,6 +79,11 @@ MediaWiki\HeaderCallback::register();
  * Load LocalSettings.php
  */
 
+if ( is_readable( "$IP/StartProfiler.php" ) ) {
+       // @deprecated since 1.31: Use LocalSettings.php instead.
+       require "$IP/StartProfiler.php";
+}
+
 if ( defined( 'MW_CONFIG_CALLBACK' ) ) {
        call_user_func( MW_CONFIG_CALLBACK );
 } else {
index 0a17df2..0816ed7 100644 (file)
        "apierror-promised-nonwrite-api": "La cabecera HTTP <code>Promise-Non-Write-API-Action</code> no se puede enviar a módulos de la API en modo escritura.",
        "apierror-protect-invalidaction": "Tipo de protección «$1» no válido.",
        "apierror-protect-invalidlevel": "Nivel de protección «$1» no válido.",
+       "apierror-ratelimited": "Has excedido tu límite de frecuencia. Aguarda unos minutos y vuelve a intentarlo.",
        "apierror-readapidenied": "Necesitas permiso de lectura para utilizar este módulo.",
        "apierror-readonly": "El wiki está actualmente en modo de solo lectura.",
        "apierror-reauthenticate": "No te has autentificado recientemente en esta sesión. Por favor, vuelve a autentificarte.",
index 6288830..2a81d29 100644 (file)
        "apihelp-query+alllinks-example-B": "Listar os títulos para os quais existem ligações, incluindo títulos em falta, com os identificadores das páginas que contêm as respetivas ligações, começando pela letra <kbd>B</kbd>.",
        "apihelp-query+alllinks-example-unique": "Listar os títulos únicos para os quais existem hiperligações.",
        "apihelp-query+alllinks-example-unique-generator": "Obtém todos os títulos para os quais existem hiperligações, marcando aqueles em falta.",
-       "apihelp-query+alllinks-example-generator": "Obtém as páginas que contêm as ligações.",
+       "apihelp-query+alllinks-example-generator": "Obtém as páginas que contêm as hiperligações.",
        "apihelp-query+allmessages-summary": "Devolver as mensagens deste sítio.",
        "apihelp-query+allmessages-param-messages": "Mensagens a serem produzidas no resultado. <kbd>*</kbd> (o valor por omissão) significa todas as mensagens.",
        "apihelp-query+allmessages-param-prop": "As propriedades a serem obtidas:",
        "apihelp-query+imageusage-param-dir": "A direção de listagem.",
        "apihelp-query+imageusage-param-filterredir": "Como filtrar redirecionamentos. Se definido como <kbd>nonredirects</kbd> quando <var>$1redirect</var> está ativado, isto só é aplicado ao segundo nível.",
        "apihelp-query+imageusage-param-limit": "O número total de páginas a serem devolvidas. Se <var>$1redirect</var> estiver ativado, o nível aplica-se a cada nível em separado (o que significa que até 2 * <var>$1limit</var> resultados podem ser devolvidos).",
-       "apihelp-query+imageusage-param-redirect": "Se a página que contém a ligação é um redirecionamento, procurar também todas as páginas que contêm ligações para esse redirecionamento. O limite máximo é reduzido para metade.",
+       "apihelp-query+imageusage-param-redirect": "Se a página que contém a hiperligação é um redirecionamento, procurar também todas as páginas que contêm hiperligações para esse redirecionamento. O limite máximo é reduzido para metade.",
        "apihelp-query+imageusage-example-simple": "Mostrar as páginas que usam [[:File:Albert Einstein Head.jpg]].",
        "apihelp-query+imageusage-example-generator": "Obter informações sobre as páginas que usam o ficheiro [[:File:Albert Einstein Head.jpg]].",
        "apihelp-query+info-summary": "Obter a informação básica da página.",
index ebb0b45..5c0a12e 100644 (file)
        "apihelp-query+imageusage-example-simple": "Visa sidor med hjälp av [[:File:Albert Einstein Head.jpg]].",
        "apihelp-query+imageusage-example-generator": "Hämta information om sidor med hjälp av [[:File:Albert Einstein Head.jpg]].",
        "apihelp-query+info-summary": "Få grundläggande sidinformation.",
+       "apihelp-query+info-paramvalue-prop-varianttitles": "Ger visningstiteln i alla variationer på webbplatsens innehållsspråk.",
        "apihelp-query+iwbacklinks-param-limit": "Hur många sidor att returnera totalt.",
        "apihelp-query+iwbacklinks-param-dir": "Riktningen att lista mot.",
        "apihelp-query+iwlinks-param-dir": "Riktningen att lista mot.",
index 65baec5..a32d4a0 100644 (file)
@@ -1,8 +1,7 @@
 <?php
 
 /**
- * Deferrable update for closure/callback updates that need LBFactory and Database
- * to be outside any active transaction round.
+ * Deferrable update that must run outside of any explicit LBFactory transaction round
  *
  * @since 1.31
  */
index 433b567..21410c8 100644 (file)
        "config-install-extension-tables": "A criar as tabelas das extensões ativadas",
        "config-install-mainpage-failed": "Não foi possível inserir a página principal: $1",
        "config-install-done": "<strong>Parabéns!</strong>\nTerminou a instalação do MediaWiki.\n\nO instalador gerou um ficheiro <code>LocalSettings.php</code>.\nEste ficheiro contém todas as configurações.\n\nPrecisa de descarregar o ficheiro e colocá-lo no diretório de raiz da sua instalação (o mesmo diretório onde está o ficheiro index.php). Este descarregamento deverá ter sido iniciado automaticamente.\n\nSe o descarregamento não foi iniciado, ou se o cancelou, pode recomeçá-lo clicando na hiperligação abaixo:\n\n$3\n\n<strong>Nota</strong>: Se não o descarregar agora, o ficheiro que foi gerado deixará de estar disponível quando sair do processo de instalação.\n\nDepois de terminar o passo anterior, pode <strong>[$2 entrar na wiki]</strong>.",
-       "config-install-done-path": "<strong>Parabéns!</strong>\nTerminou a instalação do MediaWiki.\n\nO instalador gerou um ficheiro <code>LocalSettings.php</code>.\nEste ficheiro contém todas as configurações.\n\nPrecisa de descarregar o ficheiro e colocá-lo no diretório <code>$4</code>. Este descarregamento deverá ter sido iniciado automaticamente.\n\nSe o descarregamento não foi iniciado, ou se o cancelou, pode recomeçá-lo clicando na ligação abaixo:\n\n$3\n\n<strong>Nota</strong>: Se não fizer o descarregamento agora, o ficheiro que foi gerado deixará de estar disponível quando sair do processo de instalação.\n\nDepois de terminar o passo anterior, pode <strong>[$2 entrar na wiki]</strong>.",
+       "config-install-done-path": "<strong>Parabéns!</strong>\nTerminou a instalação do MediaWiki.\n\nO instalador gerou um ficheiro <code>LocalSettings.php</code>.\nEste ficheiro contém todas as configurações.\n\nPrecisa de descarregar o ficheiro e colocá-lo no diretório <code>$4</code>. Este descarregamento deverá ter sido iniciado automaticamente.\n\nSe o descarregamento não foi iniciado, ou se o cancelou, pode recomeçá-lo clicando a hiperligação abaixo:\n\n$3\n\n<strong>Nota</strong>: Se não fizer o descarregamento agora, o ficheiro que foi gerado deixará de estar disponível quando sair do processo de instalação.\n\nDepois de terminar o passo anterior, pode <strong>[$2 entrar na wiki]</strong>.",
        "config-install-success": "O MediaWiki foi instalado. Já pode visitar <$1$2> para ver a sua wiki.\nSe tiver dúvidas, veja a nossa lista de perguntas frequentes,\n<https://www.mediawiki.org/wiki/Manual:FAQ/pt>, ou utilize um dos fóruns de suporte indicados nessa página.",
        "config-download-localsettings": "Descarregar <code>LocalSettings.php</code>",
        "config-help": "ajuda",
index 8508861..f9c416f 100644 (file)
@@ -50,6 +50,12 @@ abstract class Job implements IJobSpecification {
        /** @var callable[] */
        protected $teardownCallbacks = [];
 
+       /** @var int Bitfield of JOB_* class constants */
+       protected $executionFlags = 0;
+
+       /** @var int Job must not be wrapped in the usual explicit LBFactory transaction round */
+       const JOB_NO_EXPLICIT_TRX_ROUND = 1;
+
        /**
         * Run the job
         * @return bool Success
@@ -108,6 +114,15 @@ abstract class Job implements IJobSpecification {
                }
        }
 
+       /**
+        * @param int $flag JOB_* class constant
+        * @return bool
+        * @since 1.31
+        */
+       public function hasExecutionFlag( $flag ) {
+               return ( $this->executionFlags && $flag ) === $flag;
+       }
+
        /**
         * Batch-insert a group of jobs into the queue.
         * This will be wrapped in a transaction with a forced commit.
index fa7d605..977fbda 100644 (file)
@@ -290,7 +290,9 @@ class JobRunner implements LoggerAwareInterface {
                $jobStartTime = microtime( true );
                try {
                        $fnameTrxOwner = get_class( $job ) . '::run'; // give run() outer scope
-                       $lbFactory->beginMasterChanges( $fnameTrxOwner );
+                       if ( !$job->hasExecutionFlag( $job::JOB_NO_EXPLICIT_TRX_ROUND ) ) {
+                               $lbFactory->beginMasterChanges( $fnameTrxOwner );
+                       }
                        $status = $job->run();
                        $error = $job->getLastError();
                        $this->commitMasterChanges( $lbFactory, $job, $fnameTrxOwner );
index 77daca7..8f50828 100644 (file)
@@ -35,6 +35,7 @@ class RecentChangesUpdateJob extends Job {
                        throw new Exception( "Missing 'type' parameter." );
                }
 
+               $this->executionFlags |= self::JOB_NO_EXPLICIT_TRX_ROUND;
                $this->removeDuplicates = true;
        }
 
@@ -127,124 +128,118 @@ class RecentChangesUpdateJob extends Job {
                $window = $wgActiveUserDays * 86400;
 
                $dbw = wfGetDB( DB_MASTER );
-               // JobRunner uses DBO_TRX, but doesn't call begin/commit itself;
-               // onTransactionIdle() will run immediately since there is no trx.
-               $dbw->onTransactionIdle(
-                       function () use ( $dbw, $days, $window ) {
-                               $factory = MediaWikiServices::getInstance()->getDBLoadBalancerFactory();
-                               $ticket = $factory->getEmptyTransactionTicket( __METHOD__ );
-                               // Avoid disconnect/ping() cycle that makes locks fall off
-                               $dbw->setSessionOptions( [ 'connTimeout' => 900 ] );
-
-                               $lockKey = wfWikiID() . '-activeusers';
-                               if ( !$dbw->lock( $lockKey, __METHOD__, 0 ) ) {
-                                       // Exclusive update (avoids duplicate entries)… it's usually fine to just drop out here,
-                                       // if the Job is already running.
-                                       return;
-                               }
+               $factory = MediaWikiServices::getInstance()->getDBLoadBalancerFactory();
+               $ticket = $factory->getEmptyTransactionTicket( __METHOD__ );
 
-                               $nowUnix = time();
-                               // Get the last-updated timestamp for the cache
-                               $cTime = $dbw->selectField( 'querycache_info',
-                                       'qci_timestamp',
-                                       [ 'qci_type' => 'activeusers' ]
-                               );
-                               $cTimeUnix = $cTime ? wfTimestamp( TS_UNIX, $cTime ) : 1;
-
-                               // Pick the date range to fetch from. This is normally from the last
-                               // update to till the present time, but has a limited window for sanity.
-                               // If the window is limited, multiple runs are need to fully populate it.
-                               $sTimestamp = max( $cTimeUnix, $nowUnix - $days * 86400 );
-                               $eTimestamp = min( $sTimestamp + $window, $nowUnix );
-
-                               // Get all the users active since the last update
-                               $actorQuery = ActorMigration::newMigration()->getJoin( 'rc_user' );
-                               $res = $dbw->select(
-                                       [ 'recentchanges' ] + $actorQuery['tables'],
-                                       [
-                                               'rc_user_text' => $actorQuery['fields']['rc_user_text'],
-                                               'lastedittime' => 'MAX(rc_timestamp)'
-                                       ],
-                                       [
-                                               $actorQuery['fields']['rc_user'] . ' > 0', // actual accounts
-                                               'rc_type != ' . $dbw->addQuotes( RC_EXTERNAL ), // no wikidata
-                                               'rc_log_type IS NULL OR rc_log_type != ' . $dbw->addQuotes( 'newusers' ),
-                                               'rc_timestamp >= ' . $dbw->addQuotes( $dbw->timestamp( $sTimestamp ) ),
-                                               'rc_timestamp <= ' . $dbw->addQuotes( $dbw->timestamp( $eTimestamp ) )
-                                       ],
-                                       __METHOD__,
-                                       [
-                                               'GROUP BY' => [ 'rc_user_text' ],
-                                               'ORDER BY' => 'NULL' // avoid filesort
-                                       ],
-                                       $actorQuery['joins']
-                               );
-                               $names = [];
-                               foreach ( $res as $row ) {
-                                       $names[$row->rc_user_text] = $row->lastedittime;
-                               }
+               $lockKey = wfWikiID() . '-activeusers';
+               if ( !$dbw->lock( $lockKey, __METHOD__, 0 ) ) {
+                       // Exclusive update (avoids duplicate entries)… it's usually fine to just
+                       // drop out here, if the Job is already running.
+                       return;
+               }
 
-                               // Find which of the recently active users are already accounted for
-                               if ( count( $names ) ) {
-                                       $res = $dbw->select( 'querycachetwo',
-                                               [ 'user_name' => 'qcc_title' ],
-                                               [
-                                                       'qcc_type' => 'activeusers',
-                                                       'qcc_namespace' => NS_USER,
-                                                       'qcc_title' => array_keys( $names ),
-                                                       'qcc_value >= ' . $dbw->addQuotes( $nowUnix - $days * 86400 ), // TS_UNIX
-                                                ],
-                                               __METHOD__
-                                       );
-                                       // Note: In order for this to be actually consistent, we would need
-                                       // to update these rows with the new lastedittime.
-                                       foreach ( $res as $row ) {
-                                               unset( $names[$row->user_name] );
-                                       }
-                               }
+               // Long-running queries expected
+               $dbw->setSessionOptions( [ 'connTimeout' => 900 ] );
 
-                               // Insert the users that need to be added to the list
-                               if ( count( $names ) ) {
-                                       $newRows = [];
-                                       foreach ( $names as $name => $lastEditTime ) {
-                                               $newRows[] = [
-                                                       'qcc_type' => 'activeusers',
-                                                       'qcc_namespace' => NS_USER,
-                                                       'qcc_title' => $name,
-                                                       'qcc_value' => wfTimestamp( TS_UNIX, $lastEditTime ),
-                                                       'qcc_namespacetwo' => 0, // unused
-                                                       'qcc_titletwo' => '' // unused
-                                               ];
-                                       }
-                                       foreach ( array_chunk( $newRows, 500 ) as $rowBatch ) {
-                                               $dbw->insert( 'querycachetwo', $rowBatch, __METHOD__ );
-                                               $factory->commitAndWaitForReplication( __METHOD__, $ticket );
-                                       }
-                               }
+               $nowUnix = time();
+               // Get the last-updated timestamp for the cache
+               $cTime = $dbw->selectField( 'querycache_info',
+                       'qci_timestamp',
+                       [ 'qci_type' => 'activeusers' ]
+               );
+               $cTimeUnix = $cTime ? wfTimestamp( TS_UNIX, $cTime ) : 1;
+
+               // Pick the date range to fetch from. This is normally from the last
+               // update to till the present time, but has a limited window for sanity.
+               // If the window is limited, multiple runs are need to fully populate it.
+               $sTimestamp = max( $cTimeUnix, $nowUnix - $days * 86400 );
+               $eTimestamp = min( $sTimestamp + $window, $nowUnix );
+
+               // Get all the users active since the last update
+               $actorQuery = ActorMigration::newMigration()->getJoin( 'rc_user' );
+               $res = $dbw->select(
+                       [ 'recentchanges' ] + $actorQuery['tables'],
+                       [
+                               'rc_user_text' => $actorQuery['fields']['rc_user_text'],
+                               'lastedittime' => 'MAX(rc_timestamp)'
+                       ],
+                       [
+                               $actorQuery['fields']['rc_user'] . ' > 0', // actual accounts
+                               'rc_type != ' . $dbw->addQuotes( RC_EXTERNAL ), // no wikidata
+                               'rc_log_type IS NULL OR rc_log_type != ' . $dbw->addQuotes( 'newusers' ),
+                               'rc_timestamp >= ' . $dbw->addQuotes( $dbw->timestamp( $sTimestamp ) ),
+                               'rc_timestamp <= ' . $dbw->addQuotes( $dbw->timestamp( $eTimestamp ) )
+                       ],
+                       __METHOD__,
+                       [
+                               'GROUP BY' => [ 'rc_user_text' ],
+                               'ORDER BY' => 'NULL' // avoid filesort
+                       ],
+                       $actorQuery['joins']
+               );
+               $names = [];
+               foreach ( $res as $row ) {
+                       $names[$row->rc_user_text] = $row->lastedittime;
+               }
+
+               // Find which of the recently active users are already accounted for
+               if ( count( $names ) ) {
+                       $res = $dbw->select( 'querycachetwo',
+                               [ 'user_name' => 'qcc_title' ],
+                               [
+                                       'qcc_type' => 'activeusers',
+                                       'qcc_namespace' => NS_USER,
+                                       'qcc_title' => array_keys( $names ),
+                                       'qcc_value >= ' . $dbw->addQuotes( $nowUnix - $days * 86400 ), // TS_UNIX
+                                ],
+                               __METHOD__
+                       );
+                       // Note: In order for this to be actually consistent, we would need
+                       // to update these rows with the new lastedittime.
+                       foreach ( $res as $row ) {
+                               unset( $names[$row->user_name] );
+                       }
+               }
+
+               // Insert the users that need to be added to the list
+               if ( count( $names ) ) {
+                       $newRows = [];
+                       foreach ( $names as $name => $lastEditTime ) {
+                               $newRows[] = [
+                                       'qcc_type' => 'activeusers',
+                                       'qcc_namespace' => NS_USER,
+                                       'qcc_title' => $name,
+                                       'qcc_value' => wfTimestamp( TS_UNIX, $lastEditTime ),
+                                       'qcc_namespacetwo' => 0, // unused
+                                       'qcc_titletwo' => '' // unused
+                               ];
+                       }
+                       foreach ( array_chunk( $newRows, 500 ) as $rowBatch ) {
+                               $dbw->insert( 'querycachetwo', $rowBatch, __METHOD__ );
+                               $factory->commitAndWaitForReplication( __METHOD__, $ticket );
+                       }
+               }
+
+               // If a transaction was already started, it might have an old
+               // snapshot, so kludge the timestamp range back as needed.
+               $asOfTimestamp = min( $eTimestamp, (int)$dbw->trxTimestamp() );
+
+               // Touch the data freshness timestamp
+               $dbw->replace( 'querycache_info',
+                       [ 'qci_type' ],
+                       [ 'qci_type' => 'activeusers',
+                               'qci_timestamp' => $dbw->timestamp( $asOfTimestamp ) ], // not always $now
+                       __METHOD__
+               );
+
+               $dbw->unlock( $lockKey, __METHOD__ );
 
-                               // If a transaction was already started, it might have an old
-                               // snapshot, so kludge the timestamp range back as needed.
-                               $asOfTimestamp = min( $eTimestamp, (int)$dbw->trxTimestamp() );
-
-                               // Touch the data freshness timestamp
-                               $dbw->replace( 'querycache_info',
-                                       [ 'qci_type' ],
-                                       [ 'qci_type' => 'activeusers',
-                                               'qci_timestamp' => $dbw->timestamp( $asOfTimestamp ) ], // not always $now
-                                       __METHOD__
-                               );
-
-                               $dbw->unlock( $lockKey, __METHOD__ );
-
-                               // Rotate out users that have not edited in too long (according to old data set)
-                               $dbw->delete( 'querycachetwo',
-                                       [
-                                               'qcc_type' => 'activeusers',
-                                               'qcc_value < ' . $dbw->addQuotes( $nowUnix - $days * 86400 ) // TS_UNIX
-                                       ],
-                                       __METHOD__
-                               );
-                       },
+               // Rotate out users that have not edited in too long (according to old data set)
+               $dbw->delete( 'querycachetwo',
+                       [
+                               'qcc_type' => 'activeusers',
+                               'qcc_value < ' . $dbw->addQuotes( $nowUnix - $days * 86400 ) // TS_UNIX
+                       ],
                        __METHOD__
                );
        }
index be7d021..01589ae 100644 (file)
@@ -369,7 +369,7 @@ class LoadBalancer implements ILoadBalancer {
                // Scale the configured load ratios according to each server's load and state
                $this->getLoadMonitor()->scaleLoads( $loads, $domain );
 
-               // Pick a server to use, accounting for weights, load, lag, and mWaitForPos
+               // Pick a server to use, accounting for weights, load, lag, and "waitForPos"
                list( $i, $laggedReplicaMode ) = $this->pickReaderIndex( $loads, $domain );
                if ( $i === false ) {
                        // Replica DB connection unsuccessful
@@ -379,7 +379,7 @@ class LoadBalancer implements ILoadBalancer {
                if ( $this->waitForPos && $i != $this->getWriterIndex() ) {
                        // Before any data queries are run, wait for the server to catch up to the
                        // specified position. This is used to improve session consistency. Note that
-                       // when LoadBalancer::waitFor() sets mWaitForPos, the waiting triggers here,
+                       // when LoadBalancer::waitFor() sets "waitForPos", the waiting triggers here,
                        // so update laggedReplicaMode as needed for consistency.
                        if ( !$this->doWait( $i ) ) {
                                $laggedReplicaMode = true;
@@ -424,7 +424,7 @@ class LoadBalancer implements ILoadBalancer {
                        } else {
                                $i = false;
                                if ( $this->waitForPos && $this->waitForPos->asOfTime() ) {
-                                       // ChronologyProtecter sets mWaitForPos for session consistency.
+                                       // ChronologyProtecter sets "waitForPos" for session consistency.
                                        // This triggers doWait() after connect, so it's especially good to
                                        // avoid lagged servers so as to avoid excessive delay in that method.
                                        $ago = microtime( true ) - $this->waitForPos->asOfTime();
@@ -1140,7 +1140,7 @@ class LoadBalancer implements ILoadBalancer {
                                $context
                        );
 
-                       // If all servers were busy, mLastError will contain something sensible
+                       // If all servers were busy, "lastError" will contain something sensible
                        throw new DBConnectionError( null, $this->lastError );
                }
        }
index c66fbc1..15b54ab 100644 (file)
        "rcfilters-filtergroup-reviewstatus": "Статус праверкі",
        "rcfilters-filter-reviewstatus-unpatrolled-description": "Рэдагаваньні, якія не былі пазначаныя як патруляваныя, уручную ці аўтаматычна.",
        "rcfilters-filter-reviewstatus-unpatrolled-label": "Неправераныя",
+       "rcfilters-filter-reviewstatus-manual-description": "Рэдагаваньні, уручную пазначаныя як патруляваныя.",
        "rcfilters-filtergroup-significance": "Значэньне",
        "rcfilters-filter-minor-label": "Дробныя праўкі",
        "rcfilters-filter-minor-description": "Праўкі, якія аўтар пазначыў як дробныя.",
index da0544f..9385e48 100644 (file)
        "emailnotarget": "প্রাপকের ব্যবহারকারী নাম সঠিক নয় অথবা এই নামের ব্যবহারকারী নেই।",
        "emailtarget": "ব্যবহারকারী নাম অথবা প্রাপকের নাম প্রবেশ করান",
        "emailusername": "ব্যবহারকারী নাম:",
-       "emailusernamesubmit": "à¦\9cমা à¦¦à¦¾à¦\93",
+       "emailusernamesubmit": "à¦\9cমা à¦¦à¦¿à¦¨",
        "email-legend": "অন্য একজন {{SITENAME}} ব্যবহারকারীকে ই-মেইল পাঠান",
        "emailfrom": "প্রেরক:",
        "emailto": "প্রাপক:",
        "feedback-error4": "ত্রুটি: প্রতিক্রিয়ায় দেয়া শিরোনামে প্রকাশ অক্ষম",
        "feedback-message": "বার্তা:",
        "feedback-subject": "বিষয়:",
-       "feedback-submit": "à¦\9cমা à¦¦à¦¾à¦\93",
+       "feedback-submit": "à¦\9cমা à¦¦à¦¿à¦¨",
        "feedback-terms": "আমি বুঝেছি যে আমার প্রতিক্রিয়ার পাশাপাশি আমার যথাযথ ব্রাউজার এবং অপারেটিং সিস্টেম সংস্করণের তথ্যসহ ব্যবহারকারী এজেন্ট সর্বজনীনভাবে ভাগ করা হবে।",
        "feedback-termsofuse": "আমি ব্যবহারের শর্তাবলী অনুসারে প্রতিক্রিয়া জানাতে সম্মত।",
        "feedback-thanks": "ধন্যবাদ! আপনার প্রতিক্রিয়া \"[$2 $1]\" পাতায় পোস্ট করা হয়েছে।",
index 45c2c31..013b8e2 100644 (file)
        "uploadstash-bad-path": "Cesta neexistuje.",
        "uploadstash-bad-path-invalid": "Cesta není platná.",
        "uploadstash-bad-path-unknown-type": "Neznámý typ „$1“.",
-       "uploadstash-bad-path-bad-format": "Klíč \"$1\" není správně naformátovaný.",
+       "uploadstash-bad-path-bad-format": "Klíč „$1‟ nemá správný formát.",
        "uploadstash-file-not-found-no-thumb": "Nepodařilo se získat náhled.",
        "uploadstash-file-not-found-no-object": "Nepodařilo se vytvořit objekt lokálního souboru pro náhled.",
        "uploadstash-file-not-found-no-remote-thumb": "Načtení náhledu se nepodařilo: $1\nURL = $2",
index 74ee879..dab8908 100644 (file)
        "pool-errorunknown": "Xeta nêzanıtiye",
        "pool-servererror": "Amordoğa xızmeti ya istifade nëbena $1",
        "poolcounter-usage-error": "Xırab karyayış:$1",
-       "aboutsite": "Heqa {{SITENAME}} dı",
+       "aboutsite": "Heqa {{SITENAME}} de",
        "aboutpage": "Project:Heqa",
        "copyright": "Zerrekacı $1 bındı not biya.",
        "copyrightpage": "{{ns:project}}:Heqa telifi",
index d7bb1f8..f854dce 100644 (file)
        "revdelete-edit-reasonlist": "עריכת סיבות ההסתרה",
        "revdelete-offender": "מחבר הגרסה:",
        "suppressionlog": "יומן העלמות",
-       "suppressionlogtext": "×\9c×\94×\9c×\9f ×¨×©×\99×\9eת ×\94×\9e×\97×\99ק×\95ת ×\95×\94×\97ס×\99×\9e×\95ת ×\94×\9b×\95×\9c×\9c×\95ת ×ª×\95×\9b×\9f ×\94×\9e×\95סתר ×\9e×\9eפע×\99×\9c×\99 ×\94×\9eער×\9bת.\nר×\90×\95 ×\90ת [[Special:BlockList|רשימת החסומים]] לרשימת החסימות הפעילות כעת.",
+       "suppressionlogtext": "×\9c×\94×\9c×\9f ×¨×©×\99×\9eת ×\94×\9e×\97×\99ק×\95ת ×\95×\94×\97ס×\99×\9e×\95ת ×\94×\9b×\95×\9c×\9c×\95ת ×ª×\95×\9b×\9f ×\94×\9e×\95סתר ×\9e×\9eפע×\99×\9c×\99 ×\94×\9eער×\9bת.\n× ×\99ת×\9f ×\9c×¢×\99×\99×\9f ×\91[[Special:BlockList|רשימת החסומים]] לרשימת החסימות הפעילות כעת.",
        "mergehistory": "מיזוג גרסאות של דפים",
        "mergehistory-header": "דף זה מאפשר לך למזג גרסאות מתוך היסטוריית גרסאות של דף אחד (דף המקור) לתוך דף חדש.\nיש לוודא שהמיזוג לא יפגע בהמשכיות השינויים בדף הישן.",
        "mergehistory-box": "מיזוג גרסאות של שני דפים:",
        "mergehistory-from": "דף המקור:",
        "mergehistory-into": "דף היעד:",
        "mergehistory-list": "היסטוריית עריכות בת מיזוג",
-       "mergehistory-merge": "× ×\99ת×\9f ×\9c×\9e×\96×\92 ×\90ת ×\94×\92רס×\90×\95ת ×\94×\91×\90×\95ת ×©×\9c [[:$1]] ×\9cת×\95×\9a [[:$2]].\n×\99ש ×\9c×\94שת×\9eש ×\91×\9c×\97צנ×\99 ×\94×\90פשר×\95ת ×\9b×\93×\99 ×\9c×\91×\97×\95ר ×\96×\9e×\9f ×©×¨×§ ×\92רס×\90×\95ת ×©× ×\95צר×\95 ×\91×\95 ×\95×\9cפנ×\99×\95 ×\99×\9e×\95×\96×\92×\95.\nשימוש בקישורי הניווט יאפס עמודה זו.",
+       "mergehistory-merge": "× ×\99ת×\9f ×\9c×\9e×\96×\92 ×\90ת ×\94×\92רס×\90×\95ת ×\94×\91×\90×\95ת ×©×\9c [[:$1]] ×\9cת×\95×\9a [[:$2]].\n×\99ש ×\9c×\94שת×\9eש ×\91×\9c×\97צנ×\99 ×\94×\90פשר×\95ת ×\9b×\93×\99 ×\9c×\91×\97×\95ר ×\96×\9e×\9f ×©×¨×§ ×\92רס×\90×\95ת ×©× ×\95צר×\95 ×\91×\95 ×\95×\9cפנ×\99×\95 ×ª×\9e×\95×\96×\92× ×\94.\nשימוש בקישורי הניווט יאפס עמודה זו.",
        "mergehistory-go": "הצגת עריכות בנות מיזוג",
-       "mergehistory-submit": "מיזוג",
+       "mergehistory-submit": "מיזוג הגרסאות",
        "mergehistory-empty": "אין גרסאות למיזוג.",
-       "mergehistory-done": "{{PLURAL:$3|×\92רס×\94 ×\90×\97ת|$3 ×\92רס×\90×\95ת}} ×©×\9c $1 {{PLURAL:$3|×\9e×\95×\96×\92×\94\9e×\95×\96×\92×\95}} ×\91×\94צ×\9c×\97×\94 ×\9cת×\95×\9a [[:$2]].",
+       "mergehistory-done": "{{PLURAL:$3|גרסה אחת|$3 גרסאות}} של $1 {{PLURAL:$3|מוזגה|מוזגו}} לתוך [[:$2]].",
        "mergehistory-fail": "לא ניתן לבצע את מיזוג הגרסאות, יש לבדוק שנית את הגדרות הדף והזמן.",
        "mergehistory-fail-bad-timestamp": "התאריך והשעה אינם תקינים.",
        "mergehistory-fail-invalid-source": "דף המקור אינו תקין.",
        "mergehistory-invalid-destination": "דף היעד חייב להיות בעל כותרת תקינה.",
        "mergehistory-autocomment": "הדף [[:$1]] מוזג לתוך הדף [[:$2]]",
        "mergehistory-comment": "הדף [[:$1]] מוזג לתוך הדף [[:$2]]: $3",
-       "mergehistory-same-destination": "×\93פ×\99 ×\94×\9eק×\95ר ×\95×\94×\99×¢×\93 זהים",
+       "mergehistory-same-destination": "×\93×£ ×\94×\9eק×\95ר ×\95×\93×£ ×\94×\99×¢×\93 ×\9c×\90 ×\99×\9b×\95×\9c×\99×\9d ×\9c×\94×\99×\95ת זהים",
        "mergehistory-reason": "סיבה:",
        "mergelog": "יומן מיזוגים",
        "revertmerge": "ביטול המיזוג",
index 4c31b99..14c1709 100644 (file)
        "tag-mw-blank": "비우기",
        "tag-mw-blank-description": "문서를 비운 편집",
        "tag-mw-replace": "대체됨",
-       "tag-mw-replace-description": "문서 내용 중 90% 보다 많은 내용을 제거한 편집",
+       "tag-mw-replace-description": "문서 내용의 90% 이상을 제거한 편집",
        "tag-mw-rollback": "되돌리기",
        "tag-mw-rollback-description": "되돌리기 링크를 사용하여 이전 편집으로 전부 되돌린 편집",
        "tag-mw-undo": "편집 취소",
index 5ec8fb6..f713b72 100644 (file)
        "tags-delete-submit": "Haol dit label eweg zónger det 't kan waere trögkgedrejd",
        "tags-delete-not-allowed": "Labeles die waere bepaoldj door 'n oetbreijing kónne neet waeren eweggehaold, behauve wen de oetbreijing dit specefiek tousteit.",
        "tags-delete-not-found": "'t Label \"$1\" besteit neet.",
+       "tags-delete-no-permission": "Doe höbs gein rechte veur verangeringslabels eweg te haole.",
+       "tags-activate-title": "Aktiveer label",
+       "tags-activate-question": "Doe geis zo 't label \"$1\" aktivere.",
+       "tags-activate-reason": "Raeje:",
+       "tags-activate-not-allowed": "'t Is neet meugelik 't label \"$1\" te aktivere.",
+       "tags-activate-not-found": "'t Label \"$1\" besteit neet.",
+       "tags-activate-submit": "Aktiveer",
+       "tags-deactivate-title": "Deaktiveer label",
+       "tags-deactivate-question": "Doe geis zo 't label \"$1\" deaktivere.",
        "tags-deactivate-reason": "Raeje:",
+       "tags-deactivate-not-allowed": "'t Is neet meugelik 't label \"$1\" te deaktivere.",
        "tags-deactivate-submit": "Deaktiveer",
+       "tags-apply-no-permission": "Doe höbs gein rechte veur verangeringslabels tou te veuge aan dien verangeringe.",
        "comparepages": "Vergeliek pazjena's",
        "compare-page1": "Paasj 1",
        "compare-page2": "Paasj 2",
index 789eaeb..f1bf26e 100644 (file)
        "linksearch-ns": "Domínio:",
        "linksearch-ok": "Pesquisar",
        "linksearch-text": "É possível usar caracteres de substituição ''(wildcards)'', tais como \"*.wikipedia.org\".\nÉ necessário, pelo menos, um domínio de topo, por exemplo \"*.org\".<br />\n{{PLURAL:$2|Protocolo suportado|Protocolos suportados}}: $1 (será utilizado http:// se não for especificado um protocolo).",
-       "linksearch-line": "Ligação para $1 na página $2",
+       "linksearch-line": "Hiperligação para $1 na página $2",
        "linksearch-error": "Caracteres de substituição ''(wildcards)'' só podem ser usados no início do endereço.",
        "listusersfrom": "Mostrar utilizadores começados por:",
        "listusers-submit": "Mostrar",
        "sp-contributions-submit": "Pesquisar",
        "sp-contributions-outofrange": "Não é possível mostrar nenhum resultado. A gama de endereços IP pedida é maior do que o limite /$1 do intervalo CIDR.",
        "whatlinkshere": "Páginas afluentes",
-       "whatlinkshere-title": "Páginas com ligações para \"$1\"",
+       "whatlinkshere-title": "Páginas com hiperligações para \"$1\"",
        "whatlinkshere-page": "Página:",
        "linkshere": "As seguintes páginas têm hiperligações para <strong>[[:$1]]</strong>:",
        "nolinkshere": "Não existem afluentes para <strong>[[:$1]]</strong> com as condições especificadas.",
        "whatlinkshere-hideredirs": "$1 redirecionamentos",
        "whatlinkshere-hidetrans": "$1 transclusões",
        "whatlinkshere-hidelinks": "$1 hiperligações",
-       "whatlinkshere-hideimages": "$1 ligações para ficheiros",
+       "whatlinkshere-hideimages": "$1 hiperligações para ficheiros",
        "whatlinkshere-filters": "Filtros",
        "whatlinkshere-submit": "Continuar",
        "autoblockid": "Bloqueio automático nº $1",
        "tooltip-n-recentchanges": "Uma lista de mudanças recentes nesta wiki",
        "tooltip-n-randompage": "Carregar página aleatória",
        "tooltip-n-help": "Um local reservado para auxílio.",
-       "tooltip-t-whatlinkshere": "Lista de todas as páginas que contêm ligações para esta",
+       "tooltip-t-whatlinkshere": "Lista de todas as páginas que contêm hiperligações para esta",
        "tooltip-t-recentchangeslinked": "Mudanças recentes nas páginas para as quais esta contém hiperligações",
        "tooltip-feed-rss": "''Feed'' RSS desta página",
        "tooltip-feed-atom": "''Feed'' Atom desta página",
        "spamprotectiontext": "O texto que pretendia gravar foi bloqueado pelo filtro de spam.\nEste bloqueio foi provavelmente causado por uma hiperligação para um sítio externo que está na lista negra.",
        "spamprotectionmatch": "O seguinte texto ativou o filtro de <i>spam</i>: $1",
        "spambot_username": "MediaWiki limpeza de spam",
-       "spam_reverting": "A reverter para a última revisão que não contém ligação para $1",
+       "spam_reverting": "A reverter para a última revisão que não contém hiperligações para $1",
        "spam_blanking": "Todas as revisões continham hiperligações para $1; a esvaziar",
        "spam_deleting": "Todas as revisões continham hiperligações para $1; a eliminar",
        "simpleantispam-label": "Verificação contra spam.\n<strong>Não</strong> preencha isto!",
index 7f8f65d..1887c6e 100644 (file)
        "tog-watchlisthideminor": "Dölj mindre ändringar i bevakningslistan",
        "tog-watchlisthideliu": "Visa inte redigeringar av inloggade användare i bevakningslistan",
        "tog-watchlistreloadautomatically": "Uppdatera bevakningslistan automatiskt när ett filter ändras (JavaScript krävs)",
-       "tog-watchlistunwatchlinks": "Lägg till länkar för att bevaka och sluta bevaka artiklar i bevakningslistan (JavaScript krävs)",
+       "tog-watchlistunwatchlinks": "Lägg till länkar för att bevaka och sluta bevaka ({{int:Watchlist-unwatch}}/{{int:Watchlist-unwatch-undo}}) artiklar i bevakningslistan (JavaScript krävs)",
        "tog-watchlisthideanons": "Dölj redigeringar av anonyma användare i bevakningslistan",
        "tog-watchlisthidepatrolled": "Dölj patrullerade redigeringar i bevakningslistan",
        "tog-watchlisthidecategorization": "Dölj kategorisering av sidor",
        "rcfilters-filter-humans-label": "Mänskliga (inte bot)",
        "rcfilters-filter-humans-description": "Redigeringar gjorda av mänskliga redigerare.",
        "rcfilters-filtergroup-reviewstatus": "Granskningsstatus",
+       "rcfilters-filter-reviewstatus-unpatrolled-description": "Redigeringar som inte är manuellt eller automatiskt märkta som patrullerade.",
        "rcfilters-filter-reviewstatus-unpatrolled-label": "Inte patrullerade",
+       "rcfilters-filter-reviewstatus-manual-description": "Redigeringar som är manuellt markerade som patrullerade.",
+       "rcfilters-filter-reviewstatus-manual-label": "Patrullerad manuellt",
+       "rcfilters-filter-reviewstatus-auto-description": "Redigeringar av avancerade användare vars verk är automatiskt märkta som patrullerade.",
        "rcfilters-filter-reviewstatus-auto-label": "Autopatrullerad",
        "rcfilters-filtergroup-significance": "Betydelse",
        "rcfilters-filter-minor-label": "Mindre redigeringar",
index 2fa107f..5441099 100644 (file)
@@ -18,7 +18,8 @@
                        "Timpul",
                        "아라",
                        "Macofe",
-                       "Uostofchuodnego"
+                       "Uostofchuodnego",
+                       "Przem(1)s"
                ]
        },
        "tog-underline": "Podsztrychńyńcy linkůw:",
        "faq": "FAQ",
        "actions": "Akcyje",
        "namespaces": "Raumy mjan",
-       "variants": "Warjanty",
+       "variants": "Ôpcyje",
        "navigation-heading": "Menu nawigacyje",
        "errorpagetitle": "Feler",
        "returnto": "Nazod do zajty $1.",
        "tagline": "Ze {{GRAMMAR:D.lp|{{SITENAME}}}}",
        "help": "Půmoc",
-       "search": "Sznupej",
-       "searchbutton": "Sznupej",
+       "search": "Szukej",
+       "searchbutton": "Szukej",
        "go": "Przyńdź",
-       "searcharticle": "Przyńdź",
+       "searcharticle": "Pōdź",
        "history": "Gyszichta zajty",
        "history_short": "Gyszichta",
        "updatedmarker": "pomjyńane uod uostatńij wizyty",
-       "printableversion": "Wersyjo do druku",
+       "printableversion": "Wersyjŏ do durku",
        "permalink": "Link do tyj wersyje zajty",
        "print": "Drukuj",
        "view": "Podglůnd",
        "view-foreign": "Uobejrzij we {{grammar:MS.lp|$1}}",
-       "edit": "Sprowjej",
+       "edit": "Edytuj",
        "create": "Stwůrz",
        "create-local": "Wkludź lokalny uopis",
        "delete": "Wyćep",
        "talkpagelinktext": "dyskusyjŏ",
        "specialpage": "Szpecyjolno zajta",
        "personaltools": "Perzōnŏlne",
-       "talk": "Dyskusyjo",
-       "views": "Ôbocz",
-       "toolbox": "Werkcojg",
+       "talk": "Dyskusyjŏ",
+       "views": "Ôbŏcz",
+       "toolbox": "Nŏczynia",
        "imagepage": "Uobejrz zajta pliku",
        "mediawikipage": "Zajta komuńikata",
        "templatepage": "Zajta mustra",
        "lastmodifiedat": "Ta zajta bůła uostatńo sprowjano $2, $1.",
        "viewcount": "W ta zajta filowano {{PLURAL:$1|tylko roz|$1 rozůw}}.",
        "protectedpage": "Zajta zawarto",
-       "jumpto": "Przyńdź do:",
-       "jumptonavigation": "nawigacyjo",
-       "jumptosearch": "sznupaniy",
+       "jumpto": "Pōdź do:",
+       "jumptonavigation": "nawigacyjŏ",
+       "jumptosearch": "szukej",
        "view-pool-error": "Felerńe, syrwyry sům przećůnżone.\n\n$1",
        "pool-timeout": "Za dugi czas uoczekiwańo na blokada",
        "pool-queuefull": "Kolyjność zadań je pełno",
        "site-atom-feed": "Kanŏł Atom {{GRAMMAR:D.lp|$1}}",
        "page-rss-feed": "Kanoł RSS \"$1\"",
        "page-atom-feed": "Kanoł Atom \"$1\"",
-       "red-link-title": "$1 (ńy ma zajty)",
+       "red-link-title": "$1 (niy ma zajty)",
        "sort-descending": "Sortuj pomńijszajůnco",
        "sort-ascending": "Sortuj rosnůnco",
        "nstab-main": "Zajta",
        "createacct-another-realname-tip": "Wszkryflańy twojigo mjana a nazwiska ńy je końyczne.\nKej bydźesz chćoł je podoć, bydům użyte, coby dokůmyntowoć Twoje autorstwo.",
        "pt-login": "Zaloguj śe",
        "pt-login-button": "Zaloguj śe",
-       "pt-createaccount": "Twōrz nowe konto",
+       "pt-createaccount": "Twōrz nowe kōnto",
        "pt-userlogout": "Uodloguj śe",
        "php-mail-error-unknown": "Ńyznany feler we funkcyji mail()",
        "user-mail-no-addy": "Průba posłańo e‐brifa bez adresu uodbjorcy",
        "newpageletter": "N",
        "boteditletter": "b",
        "number_of_watching_users_pageview": "[$1 {{PLURAL:$1|dowajůncy pozůr užytkowńik|dowajůncych pozůr užytkowńikůw}}]",
-       "rc-change-size-new": "$1 {{PLURAL:$1|bajt|bajty|bajtůw}} po půmjyÅ\84\84u",
+       "rc-change-size-new": "$1 {{PLURAL:$1|bajt|bajty|bajtÅ\8dw}} po pÅ\8dmianie",
        "newsectionsummary": "/* $1 */ nowo tajla",
        "rc-enhanced-expand": "Pokoż szczygůły",
        "rc-enhanced-hide": "Schrůń detajle",
        "blocklink": "blokuj",
        "unblocklink": "uodymknij",
        "change-blocklink": "půmjyń zawarće uod sprowjyń",
-       "contribslink": "ajnzace",
+       "contribslink": "wkłŏd",
        "autoblocker": "Zawarto Ci sprowjyńo autůmatyczńy, bez tůż co używosz tygo samygo adresu IP, co używocz „[[User:$1|$1]]”.\nPowůd zawarća $1 to: „$2”",
        "blocklogpage": "Gyszichta zawjyrańo",
        "blocklogentry": "zawarto [[$1]], bydźe uodymkńynty: $2 $3",
        "tooltip-ca-watch": "Przidej artikel na pozůrlista",
        "tooltip-ca-unwatch": "Wyciep tyn artikel ze pozůrlisty",
        "tooltip-search": "Sznupej we serwisie {{SITENAME}}",
-       "tooltip-search-go": "Przyńdź na zajtã ô gynał takij titli, eli sam je",
+       "tooltip-search-go": "Pōdź na zajtã ô gynau takij titli, eli sam je",
        "tooltip-search-fulltext": "Sznupej wciepany tekst na zajcie",
-       "tooltip-p-logo": "Przodnio zajta",
+       "tooltip-p-logo": "Przodniŏ zajta",
        "tooltip-n-mainpage": "Przelyź na przodńo zajta",
        "tooltip-n-mainpage-description": "Przelyź na przodńo zajta",
        "tooltip-n-portal": "Uo projekće, co mogesz robić, kaj mogesz nolyźć informacyje",
        "tooltip-n-currentevents": "Informacyje uo aktualnych przitrefjyńach",
-       "tooltip-n-recentchanges": "Lista ńydowno půmjyńanych we wiki",
+       "tooltip-n-recentchanges": "Spisek niydŏwnych pōmian we wiki",
        "tooltip-n-randompage": "Ukoż cufalno zajta",
        "tooltip-n-help": "Sam śe mogesz moc przewjedźeć",
        "tooltip-t-whatlinkshere": "Ukoż zajty, kere sam linkujům",
        "tooltip-t-contributions": "Ukoż ajnzace tygo używocza",
        "tooltip-t-emailuser": "Wyślij e-brif do tygo użytkowńika",
        "tooltip-t-upload": "Wćepej plik na serwer",
-       "tooltip-t-specialpages": "Lista wszeckich ekstra zajt",
+       "tooltip-t-specialpages": "Spisek wszyjskich szpecyjalnych zajt",
        "tooltip-t-print": "Wersyjo do durku",
        "tooltip-t-permalink": "Pewny link do tyj wersyje zajty",
        "tooltip-ca-nstab-main": "Uobźyrej zajta artikla",
index ea6a295..a1bda46 100644 (file)
        "filereadonlyerror": "ไม่สามารถแก้ไขไฟล์ \"$1\" เพราะที่เก็บไฟล์ \"$2\" อยู่ในภาวะอ่านอย่างเดียว\n\nผู้ดูแลระบบที่ล็อกให้คำอธิบายว่า: \"$3\"",
        "invalidtitle-knownnamespace": "ชื่อเรื่องที่มีเนมสเปซ \"$2\" กับข้อความ \"$3\" ไม่ถูกต้อง",
        "invalidtitle-unknownnamespace": "ชื่อเรื่องที่ไม่ทราบเนมสเปซหมายเลข $1 กับข้อความ \"$2\" ไม่ถูกต้อง",
-       "exception-nologin": "ยัà¸\87à¹\84มà¹\88ลà¸\87à¸\8aืà¹\88อà¹\80à¸\82à¹\89า",
+       "exception-nologin": "ยัà¸\87à¹\84มà¹\88à¹\84à¸\94à¹\89à¹\80à¸\82à¹\89าสูà¹\88ระà¸\9aà¸\9a",
        "exception-nologin-text": "โปรดล็อกอินเพื่อสามารถเข้าถึงหน้าหรือปฏิบัติการนี้",
        "exception-nologin-text-manual": "โปรด$1เพื่อสามารถเข้าถึงหน้าหรือปฏิบัติการนี้",
        "virus-badscanner": "โครงแบบผิดพลาด: ไม่รู้จักตัวสแกนไวรัส: <em>$1</em>",
        "yourdomainname": "โดเมนของคุณ:",
        "password-change-forbidden": "คุณไม่สามารถเปลี่ยนรหัสผ่านบนวิกินี้",
        "externaldberror": "มีข้อผิดพลาดของฐานข้อมูลการพิสูจน์ตัวจริง หรือคุณไม่ได้รับอนุญาตให้ปรับบัญชีภายนอกของคุณ",
-       "login": "ลà¸\87à¸\8aืà¹\88อà¹\80à¸\82à¹\89า",
+       "login": "à¹\80à¸\82à¹\89าสูà¹\88ระà¸\9aà¸\9a",
        "login-security": "ยืนยันตัวตนของคุณ",
        "nav-login-createaccount": "ล็อกอิน / สร้างบัญชี",
-       "logout": "ลà¸\87à¸\8aืà¹\88อออà¸\81",
-       "userlogout": "ลà¸\87à¸\8aืà¹\88อออà¸\81",
-       "notloggedin": "ยัà¸\87à¹\84มà¹\88ลà¸\87à¸\8aืà¹\88อà¹\80à¸\82à¹\89า",
+       "logout": "ออà¸\81à¸\88าà¸\81ระà¸\9aà¸\9a",
+       "userlogout": "ออà¸\81à¸\88าà¸\81ระà¸\9aà¸\9a",
+       "notloggedin": "ยัà¸\87à¹\84มà¹\88à¹\84à¸\94à¹\89à¹\80à¸\82à¹\89าสูà¹\88ระà¸\9aà¸\9a",
        "userlogin-noaccount": "ไม่มีบัญชีหรือ",
        "userlogin-joinproject": "เข้าร่วมกับ{{SITENAME}}",
        "createaccount": "สร้างบัญชี",
        "nocookiesfornew": "บัญชีผู้ใช้ไม่ถูกสร้าง เนื่องจากเราไม่สามารถยืนยันต้นทาง\nกรุณาทำให้แน่ใจว่าคุณได้เปิดใช้งานคุกกี้ โหลดหน้านี้ใหม่และลองอีกครั้ง",
        "createacct-loginerror": "บัญชีผู้ใช้ถูกสร้างสำเร็จแล้ว แต่คุณไม่สามารถเข้าสู่ระบบได้โดยอัตโนมัติ โปรด[[Special:UserLogin|เข้าสู่ระบบด้วยตนเอง]]",
        "noname": "คุณไม่ได้ใส่ชื่อผู้ใช้ที่ถูกต้อง",
-       "loginsuccesstitle": "ลà¸\87à¸\8aืà¹\88อà¹\80à¸\82à¹\89าแล้ว",
+       "loginsuccesstitle": "à¹\80à¸\82à¹\89าสูà¹\88ระà¸\9aà¸\9aแล้ว",
        "loginsuccess": "<strong>ขณะนี้คุณล็อกอินสู่ {{SITENAME}} ในชื่อ \"$1\"</strong>",
        "nosuchuser": "ไม่มีผู้ใช้ชื่อ \"$1\"\nชื่อผู้ใช้นั้นไวต่ออักษรใหญ่เล็ก\nกรุณาตรวจการสะกดอีกครั้ง หรือ[[Special:CreateAccount|สร้างบัญชีใหม่]]",
        "nosuchusershort": "ไม่มีผู้ใช้ชื่อ \"$1\" \nกรุณาตรวจสอบการสะกด",
        "loginlanguagelabel": "ภาษา: $1",
        "suspicious-userlogout": "คำขอล็อกเอาต์ของคุณถูกปฏิเสธเพราะดูเหมือนส่งมาจากเบราว์เซอร์หรือพร็อกซีแคชที่เสีย",
        "createacct-another-realname-tip": "ไม่จำเป็นต้องใส่ชื่อจริง\nหากคุณเลือกใส่ชื่อจริง จะใช้เพื่อแสดงที่มาสำหรับงานของตน",
-       "pt-login": "ลà¸\87à¸\8aืà¹\88อà¹\80à¸\82à¹\89า",
-       "pt-login-button": "ลà¸\87à¸\8aืà¹\88อà¹\80à¸\82à¹\89า",
-       "pt-login-continue-button": "ลà¸\87à¸\8aืà¹\88อà¹\80à¸\82à¹\89าต่อ",
+       "pt-login": "à¹\80à¸\82à¹\89าสูà¹\88ระà¸\9aà¸\9a",
+       "pt-login-button": "à¹\80à¸\82à¹\89าสูà¹\88ระà¸\9aà¸\9a",
+       "pt-login-continue-button": "à¹\80à¸\82à¹\89าสูà¹\88ระà¸\9aà¸\9aต่อ",
        "pt-createaccount": "สร้างบัญชี",
-       "pt-userlogout": "ลà¸\87à¸\8aืà¹\88อออà¸\81",
+       "pt-userlogout": "ออà¸\81à¸\88าà¸\81ระà¸\9aà¸\9a",
        "php-mail-error-unknown": "เกิดข้อผิดพลาดไม่ทราบสาเหตุในฟังก์ชัน mail() ของพีเอชพี",
        "user-mail-no-addy": "พยายามส่งอีเมลโดยไม่มีที่อยู่อีเมล",
        "user-mail-no-body": "พยายามส่งอีเมลที่มีเนื้อหาว่างหรือสั้นอย่างไร้เหตุผล",
        "nosuchsectiontitle": "ไม่พบส่วน",
        "nosuchsectiontext": "คุณพยายามแก้ไขส่วนที่ไม่มีอยู่ \nส่วนดังกล่าวอาจถูกย้ายหรือลบขณะที่คุณดูหน้าอยู่",
        "loginreqtitle": "ต้องล็อกอิน",
-       "loginreqlink": "ลà¸\87à¸\8aืà¹\88อà¹\80à¸\82à¹\89า",
+       "loginreqlink": "à¹\80à¸\82à¹\89าสูà¹\88ระà¸\9aà¸\9a",
        "loginreqpagetext": "กรุณา$1เพื่อดูหน้าอื่น",
        "accmailtitle": "ส่งรหัสผ่านแล้ว",
        "accmailtext": "ส่งรหัสผ่านแบบสุ่มของ [[User talk:$1|$1]] ไป $2 แล้ว สามารถเปลี่ยนรหัสผ่านในหน้า<em>[[Special:ChangePassword|เปลี่ยนรหัสผ่าน]]</em> หลังล็อกอิน",
        "reuploaddesc": "ยกเลิกการอัปโหลดและกลับไปแบบอัปโหลด",
        "upload-tryagain": "ส่งคำอธิบายไฟล์ที่ดัดแปรแล้ว",
        "upload-tryagain-nostash": "ส่งไฟล์ที่อัปโหลดใหม่และคำอธิบายที่ดัดแปรแล้ว",
-       "uploadnologin": "ยัà¸\87à¹\84มà¹\88ลà¸\87à¸\8aืà¹\88อà¹\80à¸\82à¹\89า",
+       "uploadnologin": "ยัà¸\87à¹\84มà¹\88à¹\84à¸\94à¹\89à¹\80à¸\82à¹\89าสูà¹\88ระà¸\9aà¸\9a",
        "uploadnologintext": "โปรด$1เพื่ออัปโหลดไฟล์",
        "upload_directory_missing": "สารบบอัปโหลด ($1) หาย และเว็บเซิร์ฟเวอร์ไม่สามารถสร้างได้",
        "upload_directory_read_only": "เว็บเซิร์ฟเวอร์ไม่สามารถเขียนสารบบอัปโหลด ($1)",
        "watchlistfor2": "สำหรับ $1 $2",
        "nowatchlist": "ไม่มีรายการในรายการเฝ้าดูของคุณ",
        "watchlistanontext": "โปรดลงชื่อเข้าเพื่อดูหรือแก้ไขรายการในรายการเฝ้าดูของคุณ",
-       "watchnologin": "ยัà¸\87à¹\84มà¹\88ลà¸\87à¸\8aืà¹\88อà¹\80à¸\82à¹\89า",
+       "watchnologin": "ยัà¸\87à¹\84มà¹\88à¹\84à¸\94à¹\89à¹\80à¸\82à¹\89าสูà¹\88ระà¸\9aà¸\9a",
        "addwatch": "เพิ่มเข้ารายการเฝ้าดู",
        "addedwatchtext": "เพิ่มหน้า \"[[:$1]]\" และหน้าอภิปรายเข้า[[Special:Watchlist|รายการเฝ้าดู]]ของคุณแล้ว",
        "addedwatchtext-talk": "เพิ่ม \"[[:$1]]\" และหน้าที่สัมพันธ์เข้า[[Special:Watchlist|รายการเฝ้าดู]]ของคุณแล้ว",
        "tooltip-pt-anoncontribs": "รายการการแก้ไขจากเลขที่อยู่ไอพีนี้",
        "tooltip-pt-login": "สนับสนุนให้คุณล็อกอิน แต่ไม่บังคับ",
        "tooltip-pt-login-private": "คุณต้องล็อกอินจึงจะใช้วิกินี้ได้",
-       "tooltip-pt-logout": "ลà¸\87à¸\8aืà¹\88อออà¸\81",
+       "tooltip-pt-logout": "ออà¸\81à¸\88าà¸\81ระà¸\9aà¸\9a",
        "tooltip-pt-createaccount": "สนับสนุนให้คุณสร้างบัญชีและล็อกอิน แต่ไม่บังคับ",
        "tooltip-ca-talk": "อภิปรายเกี่ยวกับหน้าเนื้อหา",
        "tooltip-ca-edit": "แก้ไขหน้านี้",
index 3f08748..c6c018e 100644 (file)
        "tag-mw-new-redirect": "Yeni yönlendirme",
        "tag-mw-removed-redirect": "Yönlendirme kaldırıldı",
        "tag-mw-changed-redirect-target": "Yönlendirme hedefi değiştirildi",
+       "tag-mw-blank": "Boşaltma",
+       "tag-mw-replace": "Değiştirme",
        "tag-mw-rollback": "Geri döndürme",
        "tag-mw-undo": "Geri alma",
        "tags-title": "Etiketler",
index 5c6403f..4c953f1 100644 (file)
                        "Macofe",
                        "Matma Rex",
                        "V6rg",
-                       "C.R."
+                       "C.R.",
+                       "Cusolotto"
                ]
        },
        "tog-underline": "Sotołinea i cołegamenti:",
        "tog-hideminor": "Scondi i canbiamenti picenini in tei \"Ultimi canbiamenti\"",
        "tog-hidepatrolled": "Scondi i canbiamenti verificà in tei \"Ultimi canbiamenti\"",
        "tog-newpageshidepatrolled": "Scondi łe pajine verifegae da l'elenco de łe pajine pì resenti",
+       "tog-hidecategorization": "Nascondi le categorixasion de la pagina",
        "tog-extendwatchlist": "Mostra tute łe modifeghe a i oservai spesałi, no soło l'ultima",
        "tog-usenewrc": "Ragrupa ƚe modifeghe par pàgina inte i ultemi canbiamenti e inte ƚe tegnùe d'òcio",
        "tog-numberheadings": "Numerasion automatega de i titołi de sesion",
@@ -38,6 +40,8 @@
        "tog-watchdefault": "Xonta łe pàjine e i file modifegai a łe tegnùe d'ocio",
        "tog-watchmoves": "Xonta łe pàjine e i file spostai a łe tegnùe d'ocio",
        "tog-watchdeletion": "Xonta łe pàjine e i file scansełai a łe tegnùe d'ocio",
+       "tog-watchuploads": "Xonta en novo file che cargo a i oservatori speciali",
+       "tog-watchrollback": "Xonta a i vardatori speciali le pagine ndo go fato na modifica su na mia watchlist",
        "tog-minordefault": "Segna ogni canbiamento come picenin (solo come predefinìo)",
        "tog-previewontop": "Mostra l'anteprima sora ła caseła de modifega e no soto",
        "tog-previewonfirst": "Mostra l'anteprima par ła prima modifega",
        "tog-enotifminoredits": "Avìxeme par e-mail anca pa' i canbiamenti picenini de pàjine e file",
        "tog-enotifrevealaddr": "Fà védar el me indirisso e-mail in tei messagi de aviso",
        "tog-shownumberswatching": "Mostra el numaro de utenti che i ga ła pajina en oservasion",
-       "tog-oldsig": "Anteprima de ła firma:",
+       "tog-oldsig": "La to firma:",
        "tog-fancysig": "Interpreta i comandi wiki in te la firma (sensa colegamento automatego)",
-       "tog-uselivepreview": "Intaca l'anteprima dal vivo",
+       "tog-uselivepreview": "Varda anteprima sensa ricargar la pagina",
        "tog-forceeditsummary": "Chiedi conferma se l'ozeto de ła modifega el xé vodo",
        "tog-watchlisthideown": "Scondi łe me modifeghe ne i oservai spesałi",
        "tog-watchlisthidebots": "Scondi łe modifeghe de i bot ne i oservai spesałi",
        "tog-watchlisthideminor": "Scondi łe modifeghe picenine ne i oservai spesałi",
        "tog-watchlisthideliu": "Scondi łe modifeghe de i utenti rejistrà ne i oservai spesałi",
+       "tog-watchlistreloadautomatically": "Ricarga en automatico l'elenco dei vardatori speciali ogni olta che se modifica en filtro (serve JavaScript)",
        "tog-watchlisthideanons": "Scondi łe modifeghe de i utenti anonimi ne i oservai spesałi",
        "tog-watchlisthidepatrolled": "Scondi łe modifeghe verifegae ne i oservai spesałi",
+       "tog-watchlisthidecategorization": "Nascondi le categorixasion de la pagina",
        "tog-ccmeonemails": "Inviame na copia de i mesaji spedii a i altri utenti",
        "tog-diffonly": "No visuałisar el contenuo de ła pajina dopo el confronto tra version",
        "tog-showhiddencats": "Mostra łe categorie sconte",
-       "tog-norollbackdiff": "No mostrare el confronto tra version dopo aver efetuà on rollback",
+       "tog-norollbackdiff": "No mostrare el confronto tra version dopo aver efetuà el rollback",
        "tog-useeditwarning": "Dime se sto lassando na pagina de modifica sensa aver salvà",
+       "tog-prefershttps": "Utilixa senpre na conesion sicura cuqndo te entre",
        "underline-always": "Senpre",
        "underline-never": "Mai",
        "underline-default": "Mantien łe inpostasion del browser o de ła skin",
        "october-date": "$1 de otobre",
        "november-date": "$1 de novenbre",
        "december-date": "$1 de desenbre",
+       "period-am": "Matina",
+       "period-pm": "Pomerigio",
        "pagecategories": "{{PLURAL:$1|Categoria|Categorie}}",
        "category_header": "Pagine in te la categoria \"$1\"",
        "subcategories": "Sotocategorie",
        "newwindow": "(se verze in te na finestra nova)",
        "cancel": "Lassa star",
        "moredotdotdot": "Altro...",
-       "morenotlisted": "Sta lista no xe conpleta.",
+       "morenotlisted": "Sta lista no l'è conpleta.",
        "mypage": "Pàjina",
        "mytalk": "Discussion",
        "anontalk": "Discussion",
        "tagline": "Da {{SITENAME}}",
        "help": "Ajuto",
        "search": "Serca",
+       "search-ignored-headings": " #<!-- l'asa sta riga come te l'è catà --> <pre>\n# Elenco de le intestasioni che le sarà ignorè da la ricerca.\n# Chel che te modifiche su sta pagijna le se vedarà subi.\n# Te pol sforsar la re-indicizazion di una pagina effettuando una modifica nula.\n# Te dovreste scriver cosita:\n#   * Tuto dal carattere \"#\" a la fine de la riga l'è en comento\n#   * Tute le righe non ude iè le intestasioni juste da no vardar, maiuscolo/minuscolo e tuto\nNote\nVoci corelate\nColegamenti foraia\n #</pre> <!-- lasa sta riga come te l'è catà -->",
        "searchbutton": "Serca",
        "go": "Va",
        "searcharticle": "Và",
        "history": "Storia de la pagina",
        "history_short": "Storia",
+       "history_small": "Storia",
        "updatedmarker": "modifegà da ła me ultema visita",
        "printableversion": "Version par la stanpa",
        "permalink": "Link parmanente",
        "talk": "Discussion",
        "views": "Visite",
        "toolbox": "Strumenti",
+       "tool-link-userrights": "Modifica grupi {{GENDER:$1|utente}}",
+       "tool-link-userrights-readonly": "Visualisa {{GENDER:$1|}} grupi",
+       "tool-link-emailuser": "Scrivi na e-mail a {{GENDER:$1|sto|sta}} utente",
        "imagepage": "Varda la pagina del file",
        "mediawikipage": "Varda el mesajo",
        "templatepage": "Varda el modeło",
        "pool-timeout": "Timeout durante l'atesa de lo sbloco",
        "pool-queuefull": "La cóa de laorassion la xe piena",
        "pool-errorunknown": "Eror sconossùo",
+       "poolcounter-usage-error": "Erore de l'utilixo: $1",
        "aboutsite": "Se parla de {{SITENAME}}",
        "aboutpage": "Project:Se parla de",
-       "copyright": "Contenui sojeti a licensa d'uso $1.",
+       "copyright": "Contenui sogeti a licensa d'uso $1.",
        "copyrightpage": "{{ns:project}}:Copyright",
        "currentevents": "Atuałità",
        "currentevents-url": "Project:Atuałità",
        "nospecialpagetext": "<strong>La pagina speciale che te serchi no la ghe xe.</strong>\n\nL'elenco de le pagine speciali te lo cati su [[Special:SpecialPages|{{int:specialpages}}]].",
        "error": "Erore",
        "databaseerror": "Erore del database",
+       "databaseerror-text": "Sè verificà en eror en del database.\nEl podaria eser en bug del software.",
+       "databaseerror-textcl": "Sè verificà en eror en del database.",
+       "databaseerror-query": "Query: $1",
        "databaseerror-function": "Funsion: $1",
        "databaseerror-error": "Eror: $1",
+       "transaction-duration-limit-exceeded": "Par evitar n'alto ritardo de replica, sta operasion l'è sta interrota parché ea durata del tenpo de scritura ($1) l'ha superà el limite de $2 {{PLURAL:$2|secondo|secondi}}.\nSe te se drio modificar tanti elementi en na sola olta, proa a far più operasioni co pochi elementi.",
        "laggedslavemode": "'''Atension:''' ła pajina podaria no riportare i azornamenti pì resenti.",
        "readonly": "Database blocà",
        "enterlockreason": "Indicare el motivo del bloco, spesifegando el momento in cui xè presumibiłe che el venga rimoso",
        "readonly_lag": "El database xè sta blocà automaticamente par consentire a i server co i database slave de sincronizarse con el master",
        "internalerror": "Erore interno",
        "internalerror_info": "Erore interno: $1",
+       "internalerror-fatal-exception": "Bruto error de tipo $1",
        "filecopyerror": "Inposibiłe copiare el file \"$1\" en \"$2\".",
        "filerenameerror": "Inposibiłe rinominare el file \"$1\" en \"$2\".",
        "filedeleteerror": "Inposibiłe scansełare el file \"$1\".",
        "directorycreateerror": "Inposibiłe creare ła directory \"$1\".",
+       "directoryreadonlyerror": "L'elenco \"$1\" te pol solo lexerlo.",
+       "directorynotreadableerror": "L'elenco \"$1\" no l'è mia legibile.",
        "filenotfound": "File \"$1\" no trovà.",
        "unexpected": "Vałore inprevisto: \"$1\"=\"$2\".",
        "formerror": "Erore: inposibiłe inviare el moduło",
        "cannotdelete": "No xè sta posibiłe scansełare el file \"$1\".\nPodaria esare sta zà scansełà da qualcun altro.",
        "cannotdelete-title": "Inposibiłe ełiminare ła pajina \"$1\"",
        "delete-hook-aborted": "Modifega abortìa da parte del hook.\nNo xe stà dà nisuna spiegasion in merito.",
+       "no-null-revision": "Non l'è mia sta posibile crear na version nula par la pagina $1.",
        "badtitle": "Titoło mia justo",
        "badtitletext": "El titoło de ła pajina richiesta xè vodo, erà o con carateri no amesi opure el deriva da n'erore ne i cołegamenti tra siti wiki diversi o version en łengue diverse de ło steso sito.",
+       "title-invalid-empty": "El titolo de la pagina che te serche l'è udo o el contiene solo el nome.",
+       "title-invalid-utf8": "El titolo de la pagina el contenie na sequensa UTF-8 mia valida.",
+       "title-invalid-interwiki": "El titolo de la pagina che se serche la contenie en colegamente interwiki che nol pol mia eser meso nei titoli.",
+       "title-invalid-talk-namespace": "El titolo de la pagina che se serche la fa riferimento a na pagina de discusion che no la ghe.",
+       "title-invalid-characters": "El titolo de la pagina che te serche la contenie carateri mia validi: \"$1\".",
+       "title-invalid-relative": "El titolo che tè indicà el contenie en percorso relativo (., ../). Sti titoli no iè mia validi parchè no iè mia speso ragiungibili quando gestii da browser dell'utente.",
+       "title-invalid-magic-tilde": "El titolo de la pagina che te serchè no l'è mia valido parchè la ga la sucesion special di tilde (<nowiki>~~~</nowiki>).",
        "perfcached": "Sti dati vien tiradi fora da na copia \"cache\" del database e łi podarìa no esare ajornadi. Inte ła cache xe {{PLURAL:$1|disponibiłe un rixultado|xe disponibiłi $1 rixultadi}}.",
        "perfcachedts": "Sti dati cua xe stà ajornadi l'ultima volta el $1. Inte ła cache xe disponibiłe al masimo {{PLURAL:$4|on rexultado|$4 rexultadi}}.",
        "querypage-no-updates": "L'azornamento periodico de sta pagina el xe sospeso. \nI dati che ghè qua drento no i xe azornà.",
        "password-login-forbidden": "Sto nome utente e/o password i xè stai proibìi",
        "mailmypassword": "Rinposta ła password",
        "passwordremindertitle": "Servisio Password Reminder de {{SITENAME}}",
-       "passwordremindertext": "Qualcheduni (probabilmente ti, da l'indirizo IP $1) el gà domandà che ghe vegna mandà na nova password par {{SITENAME}} ($4).\nNa password tenporànea par l'utente \"$2\" la xe stà creà e inpostà a \"$3\".\nSe xe questo che te voléi far, desso te podi entrar co' sta password tenporanea e inpostar na password nova.\nLa to password tenporànea la scade in {{PLURAL:$5|un zorno|$5 zorni}}.\n\nSe no te sì mìa stà ti a far la domanda, opure t'è vegnù in mente la password e no te vol più canbiarla, te pol ignorar sto mesagio e continuar a doparar la vecia password.",
+       "passwordremindertext": "Cualcheduni (probabilmente ti, da l'indirizo IP $1) el gà domandà che ghe vegna mandà na nova password par {{SITENAME}} ($4).\nNa password tenporànea par l'utente \"$2\" la xe stà creà e inpostà a \"$3\".\nSe xe questo che te voléi far, deso te podi entrar co' sta password tenporanea e inpostar na password nova.\nLa to password tenporànea la scade in {{PLURAL:$5|en dì|$5 dì}}.\n\nSe no te sì mìa stà ti a far la domanda, opure t'è vegnù in mente la password e no te vol più canbiarla, te pol ignorar sto mesagio e continuar a doparar la vecia password.",
        "noemail": "Nissuna casela e-mail la risulta registrà par l'Utente \"$1\".",
        "noemailcreate": "Te ghè da fornir un indirisso e-mail vàlido",
        "passwordsent": "Na password nova la xe stà mandà a la casela e-mail registrà per l'Utente \"$1\".\nPar piaser, fà subito un login 'pena che la te riva.",
        "retypenew": "Riscrivi la password nova:",
        "resetpass_submit": "Inposta la password e acedi al sito",
        "changepassword-success": "La password la xe stà modificà!",
+       "botpasswords-label-appid": "Nome bot:",
+       "botpasswords-label-create": "Crea",
+       "botpasswords-label-update": "Agiorna",
+       "botpasswords-label-cancel": "Anùla",
+       "botpasswords-label-delete": "Scanseła",
+       "botpasswords-label-resetpassword": "Rinposta ła password",
+       "botpasswords-label-grants": "Asegnasioni aplicabili:",
+       "botpasswords-label-grants-column": "Asegnasioni",
+       "botpasswords-created-title": "Password bot creata",
        "resetpass_forbidden": "No se pol modificar le password",
        "resetpass-no-info": "Te ghè da ver fato l'acesso per poder entrar in sta pàxena.",
        "resetpass-submit-loggedin": "Cànbia password",
        "longpageerror": "'''Erore: el testo invià xe grando {{PLURAL:$1|1|$1}} kilobyte, che xe de pì deła dimension masima consentìa de {{PLURAL:$2|1|$2}} kilobyte.'''\nEl testo no połe esare salvà.",
        "readonlywarning": "'''OCIO: El database el xe stà blocà par manutension, cuindi nó se pol salvar łe modifeghe in sto momento.'''\nPar nó pèrdarle, te pol copiar tuto chel che te ghè inserìo fin deso inte ła caxeła de modifega, incołarlo inte un programa de elaborasion de testi e salvarlo, intanto che te speti che i sbloca el database.\n\nL'aministrador che gà blocà el database el gà dato ła seguente spiegasion: $1",
        "protectedpagewarning": "'''Ocio:''' Sta pajina ła xe sta proteta in maniera che soło i aministradori i posa canbiarla. Sta qua ła xe l'ultima operasion catà sul registro de ła pajina:",
-       "semiprotectedpagewarning": "'''Ocio:''' Sta pajina ła xe stà proteta in maniera che soło i utenti rexistrài i posa canbiarla. Sta qua ła xe l'ultima operasion catà sul registro de ła pajina:",
+       "semiprotectedpagewarning": "<strong>Ocio:</strong> Sta pajina ła xe stà proteta in maniera che soło i utenti rexistrài i poda canbiarla. Sta qua ła xe l'ultima operasion catà sul registro de ła pajina:",
        "cascadeprotectedwarning": "'''Ocio:''' Sta pajina ła xe stà proteta in maniera che soło i utenti co priviłegi de aministrador i posa canbiarla. Questo sucede parché ła pajina ła xe inclusa {{PLURAL:$1|'nte ła pajina indicà de seguito, che ła xe stà proteta|ne le pagine indicà de seguito, che łe xe stae protete}} sełesionando ła protesion \"ricorsiva\":",
        "titleprotectedwarning": "'''Ocio:''' Sta pajina ła xe stà proteta in modo che soło i utenti co [[Special:ListGroupRights|serti privilègi]] i ła posa crear. Sta qua ła xe l'ultima operasion catà sul registro de ła pajina:",
        "templatesused": "{{PLURAL:$1|Modèl doparà|Modèi doparà}} su sta pagina:",
        "recentchanges-label-plusminus": "La dimension de la pagina la xe canbià de sto nùmaro de byte",
        "recentchanges-legend-heading": "<strong>Legenda:</strong>",
        "recentchanges-legend-newpage": "{{int:recentchanges-label-newpage}} (varda anca [[Special:NewPages|l'elenco de le pagine nove]])",
+       "rcfilters-filter-reviewstatus-manual-label": "Verificà manualmente",
+       "rcfilters-filter-reviewstatus-auto-label": "Verificà en automatico.",
        "rcnotefrom": "Qui di seguito sono elencate le modifiche da '''$2''' (fino a '''$1''').",
        "rclistfrom": "Mostra i canbiamenti fati da ƚe $2 del $3",
        "rcshowhideminor": "$1 i canbiamenti picenini",
        "suppress": "Supervision",
        "querypage-disabled": "Sta pàjina speciałe ła xe dixativà par motivi de prestasion.",
        "apihelp-no-such-module": "Modulo \"$1\" mia catà.",
+       "apisandbox-add-multi": "Xonta",
        "booksources": "Fonti librarie",
        "booksources-search-legend": "Riserca de fonti librarie",
        "booksources-search": "Serca",
        "version-specialpages": "Pagine speciali",
        "version-parserhooks": "Hook del parser",
        "version-variables": "Variabili",
+       "version-editors": "Contributor",
        "version-antispam": "Prevension del spam",
        "version-other": "Altro",
        "version-mediahandlers": "Gestori de contenuti multimediài",
index 4b0b187..f8a745e 100644 (file)
@@ -37,12 +37,6 @@ $maintenance->setup();
 // We used to call this variable $self, but it was moved
 // to $maintenance->mSelf. Keep that here for b/c
 $self = $maintenance->getName();
-global $IP;
-# Get profiler configuraton
-$wgProfiler = [];
-if ( file_exists( "$IP/StartProfiler.php" ) ) {
-       require "$IP/StartProfiler.php";
-}
 # Start the autoloader, so that extensions can derive classes from core files
 require_once "$IP/includes/AutoLoader.php";
 
index 0b05ac1..42bc0a7 100644 (file)
@@ -1,5 +1,5 @@
 ( function ( mw, $ ) {
-       QUnit.module( 'mediawiki (mw.loader)', QUnit.newMwEnvironment( {
+       QUnit.module( 'mediawiki.loader', QUnit.newMwEnvironment( {
                setup: function ( assert ) {
                        mw.loader.store.enabled = false;
 
                        }
                        // Remove any remaining temporary statics
                        // exposed for cross-file mocks.
-                       if ( 'testCallback' in mw.loader ) {
-                               delete mw.loader.testCallback;
-                       }
-                       if ( 'testFail' in mw.loader ) {
-                               delete mw.loader.testFail;
-                       }
+                       delete mw.loader.testCallback;
+                       delete mw.loader.testFail;
                }
        } ) );
 
                );
        }
 
-       QUnit.test( 'Basic', function ( assert ) {
-               var isAwesomeDone;
-
+       QUnit.test( '.using( .., Function callback ) Promise', function ( assert ) {
+               var script = 0, callback = 0;
                mw.loader.testCallback = function () {
-                       assert.strictEqual( isAwesomeDone, undefined, 'Implementing module is.awesome: isAwesomeDone should still be undefined' );
-                       isAwesomeDone = true;
+                       script++;
                };
+               mw.loader.implement( 'test.promise', [ QUnit.fixurl( mw.config.get( 'wgScriptPath' ) + '/tests/qunit/data/mwLoaderTestCallback.js' ) ] );
 
-               mw.loader.implement( 'test.callback', [ QUnit.fixurl( mw.config.get( 'wgScriptPath' ) + '/tests/qunit/data/mwLoaderTestCallback.js' ) ] );
-
-               return mw.loader.using( 'test.callback', function () {
-                       assert.strictEqual( isAwesomeDone, true, 'test.callback module should\'ve caused isAwesomeDone to be true' );
-               }, function () {
-                       assert.ok( false, 'Error callback fired while loader.using "test.callback" module' );
+               return mw.loader.using( 'test.promise', function () {
+                       callback++;
+               } ).then( function () {
+                       assert.strictEqual( script, 1, 'module script ran' );
+                       assert.strictEqual( callback, 1, 'using() callback ran' );
                } );
        } );
 
-       QUnit.test( 'Object method as module name', function ( assert ) {
-               var isAwesomeDone;
-
+       QUnit.test( 'Prototype method as module name', function ( assert ) {
+               var call = 0;
                mw.loader.testCallback = function () {
-                       assert.strictEqual( isAwesomeDone, undefined, 'Implementing module hasOwnProperty: isAwesomeDone should still be undefined' );
-                       isAwesomeDone = true;
+                       call++;
                };
-
                mw.loader.implement( 'hasOwnProperty', [ QUnit.fixurl( mw.config.get( 'wgScriptPath' ) + '/tests/qunit/data/mwLoaderTestCallback.js' ) ], {}, {} );
 
                return mw.loader.using( 'hasOwnProperty', function () {
-                       assert.strictEqual( isAwesomeDone, true, 'hasOwnProperty module should\'ve caused isAwesomeDone to be true' );
-               }, function () {
-                       assert.ok( false, 'Error callback fired while loader.using "hasOwnProperty" module' );
+                       assert.strictEqual( call, 1, 'module script ran' );
                } );
        } );
 
-       QUnit.test( '.using( .. ) Promise', function ( assert ) {
-               var isAwesomeDone;
-
-               mw.loader.testCallback = function () {
-                       assert.strictEqual( isAwesomeDone, undefined, 'Implementing module is.awesome: isAwesomeDone should still be undefined' );
-                       isAwesomeDone = true;
-               };
-
-               mw.loader.implement( 'test.promise', [ QUnit.fixurl( mw.config.get( 'wgScriptPath' ) + '/tests/qunit/data/mwLoaderTestCallback.js' ) ] );
-
-               return mw.loader.using( 'test.promise' )
-                       .done( function () {
-                               assert.strictEqual( isAwesomeDone, true, 'test.promise module should\'ve caused isAwesomeDone to be true' );
-                       } )
-                       .fail( function () {
-                               assert.ok( false, 'Error callback fired while loader.using "test.promise" module' );
-                       } );
-       } );
-
        // Covers mw.loader#sortDependencies (with native Set if available)
-       QUnit.test( '.using() Error: Circular dependency [StringSet default]', function ( assert ) {
+       QUnit.test( '.using() Error: Circular dependency [StringSet default]', function ( assert ) {
                var done = assert.async();
 
                mw.loader.register( [
        } );
 
        // @covers mw.loader#sortDependencies (with fallback shim)
-       QUnit.test( '.using() Error: Circular dependency [StringSet shim]', function ( assert ) {
+       QUnit.test( '.using() Error: Circular dependency [StringSet shim]', function ( assert ) {
                var done = assert.async();
 
                if ( !window.Set ) {
                mw.loader.load( 'test.implement.d' );
        } );
 
+       QUnit.test( '.implement( messages before script )', function ( assert ) {
+               mw.loader.implement(
+                       'test.implement.order',
+                       function () {
+                               assert.equal( mw.loader.getState( 'test.implement.order' ), 'executing', 'state during script execution' );
+                               assert.equal( mw.msg( 'test-foobar' ), 'Hello Foobar, $1!', 'messages load before script execution' );
+                       },
+                       {},
+                       {
+                               'test-foobar': 'Hello Foobar, $1!'
+                       }
+               );
+
+               return mw.loader.using( 'test.implement.order' ).then( function () {
+                       assert.equal( mw.loader.getState( 'test.implement.order' ), 'ready', 'final success state' );
+               } );
+       } );
+
        // @import (T33676)
-       QUnit.test( '.implement( styles has @import )', function ( assert ) {
-               var isJsExecuted, $element,
+       QUnit.test( '.implement( styles with @import )', function ( assert ) {
+               var $element,
                        done = assert.async();
 
                mw.loader.implement(
                        'test.implement.import',
                        function () {
-                               assert.strictEqual( isJsExecuted, undefined, 'script not executed multiple times' );
-                               isJsExecuted = true;
-
-                               assert.equal( mw.loader.getState( 'test.implement.import' ), 'executing', 'module state during implement() script execution' );
-
                                $element = $( '<div class="mw-test-implement-import">Foo bar</div>' ).appendTo( '#qunit-fixture' );
 
-                               assert.equal( mw.msg( 'test-foobar' ), 'Hello Foobar, $1!', 'messages load before script execution' );
-
                                assertStyleAsync( assert, $element, 'float', 'right', function () {
                                        assert.equal( $element.css( 'text-align' ), 'center',
                                                'CSS styles after the @import rule are working'
                                                + '\');\n'
                                                + '.mw-test-implement-import { text-align: center; }'
                                ]
-                       },
-                       {
-                               'test-foobar': 'Hello Foobar, $1!'
                        }
                );
 
-               mw.loader.using( 'test.implement.import' ).always( function () {
-                       assert.strictEqual( isJsExecuted, true, 'script executed' );
-                       assert.equal( mw.loader.getState( 'test.implement.import' ), 'ready', 'module state after script execution' );
-               } );
+               return mw.loader.using( 'test.implement.import' );
        } );
 
        QUnit.test( '.implement( dependency with styles )', function ( assert ) {
 
                return mw.loader.using( 'test.implement.msgs', function () {
                        assert.ok( mw.messages.exists( 'T31107' ), 'T31107: messages-only module should implement ok' );
-               }, function () {
-                       assert.ok( false, 'Error callback fired while implementing "test.implement.msgs" module' );
                } );
        } );
 
                ] );
 
                function verifyModuleStates() {
-                       assert.equal( mw.loader.getState( 'testMissing' ), 'missing', 'Module not known to server must have state "missing"' );
-                       assert.equal( mw.loader.getState( 'testUsesMissing' ), 'error', 'Module with missing dependency must have state "error"' );
-                       assert.equal( mw.loader.getState( 'testUsesNestedMissing' ), 'error', 'Module with indirect missing dependency must have state "error"' );
+                       assert.equal( mw.loader.getState( 'testMissing' ), 'missing', 'Module "testMissing" state' );
+                       assert.equal( mw.loader.getState( 'testUsesMissing' ), 'error', 'Module "testUsesMissing" state' );
+                       assert.equal( mw.loader.getState( 'testUsesNestedMissing' ), 'error', 'Module "testUsesNestedMissing" state' );
                }
 
                mw.loader.using( [ 'testUsesNestedMissing' ],
                        [ 'testUsesSkippable', '1', [ 'testSkipped', 'testNotSkipped' ], null, 'testloader' ]
                ] );
 
-               function verifyModuleStates() {
-                       assert.equal( mw.loader.getState( 'testSkipped' ), 'ready', 'Module is ready when skipped' );
-                       assert.equal( mw.loader.getState( 'testNotSkipped' ), 'ready', 'Module is ready when not skipped but loaded' );
-                       assert.equal( mw.loader.getState( 'testUsesSkippable' ), 'ready', 'Module is ready when skippable dependencies are ready' );
-               }
-
-               return mw.loader.using( [ 'testUsesSkippable' ],
+               return mw.loader.using( [ 'testUsesSkippable' ] ).then(
                        function () {
-                               assert.ok( true, 'Success handler should be invoked.' );
-                               assert.ok( true ); // Dummy to match error handler and reach QUnit expect()
-
-                               verifyModuleStates();
+                               assert.equal( mw.loader.getState( 'testSkipped' ), 'ready', 'Skipped module' );
+                               assert.equal( mw.loader.getState( 'testNotSkipped' ), 'ready', 'Regular module' );
+                               assert.equal( mw.loader.getState( 'testUsesSkippable' ), 'ready', 'Regular module with skippable dependency' );
                        },
                        function ( e, badmodules ) {
-                               assert.ok( false, 'Error handler should not be invoked.' );
-                               assert.deepEqual( badmodules, [], 'Bad modules as expected.' );
-
-                               verifyModuleStates();
+                               // Should not fail and QUnit would already catch this,
+                               // but add a handler anyway to report details from 'badmodules
+                               assert.deepEqual( badmodules, [], 'Bad modules' );
                        }
                );
        } );
        } );
 
        QUnit.test( 'Stale response caching - backcompat', function ( assert ) {
-               var count = 0;
+               var script = 0;
                mw.loader.store.enabled = true;
                mw.loader.register( 'test.stalebc', 'v2' );
                assert.strictEqual( mw.loader.store.get( 'test.stalebc' ), false, 'Not in store' );
 
                mw.loader.implement( 'test.stalebc', function () {
-                       count++;
+                       script++;
                } );
 
                return mw.loader.using( 'test.stalebc' )
                        .then( function () {
-                               assert.strictEqual( count, 1 );
+                               assert.strictEqual( script, 1, 'module script ran' );
                                assert.strictEqual( mw.loader.getState( 'test.stalebc' ), 'ready' );
                                assert.ok( mw.loader.store.get( 'test.stalebc' ), 'In store' );
                        } )
                        } catch ( e ) {
                                assert.equal( null, String( e ), 'require works asynchrously in debug mode' );
                        }
-               }, function () {
-                       assert.ok( false, 'Error callback fired while loader.using "test.require.callback" module' );
                } );
        } );
 
        QUnit.test( 'Implicit dependencies', function ( assert ) {
-               var ranUser = false,
-                       userSeesSite = false,
-                       ranSite = false;
+               var user = 0,
+                       site = 0,
+                       siteFromUser = 0;
 
                mw.loader.implement(
                        'site',
                        function () {
-                               ranSite = true;
+                               site++;
                        }
                );
                mw.loader.implement(
                        'user',
                        function () {
-                               userSeesSite = ranSite;
-                               ranUser = true;
+                               user++;
+                               siteFromUser = site;
                        }
                );
 
-               assert.strictEqual( ranSite, false, 'verify site module not yet loaded' );
-               assert.strictEqual( ranUser, false, 'verify user module not yet loaded' );
                return mw.loader.using( 'user', function () {
-                       assert.strictEqual( ranSite, true, 'ran site module' );
-                       assert.strictEqual( ranUser, true, 'ran user module' );
-                       assert.strictEqual( userSeesSite, true, 'ran site before user module' );
-
+                       assert.strictEqual( site, 1, 'site module' );
+                       assert.strictEqual( user, 1, 'user module' );
+                       assert.strictEqual( siteFromUser, 1, 'site ran before user' );
+               } ).always( function () {
                        // Reset
                        mw.loader.moduleRegistry[ 'site' ].state = 'registered';
                        mw.loader.moduleRegistry[ 'user' ].state = 'registered';