Merge "API: Use ConvertibleTimestamp::setFakeTime for testing curtimestamp"
authorjenkins-bot <jenkins-bot@gerrit.wikimedia.org>
Fri, 27 Sep 2019 12:01:55 +0000 (12:01 +0000)
committerGerrit Code Review <gerrit@wikimedia.org>
Fri, 27 Sep 2019 12:01:55 +0000 (12:01 +0000)
39 files changed:
.pipeline/blubber.yaml [new file with mode: 0644]
.pipeline/config.yaml [new file with mode: 0644]
.pipeline/dev_prereq.sh [new file with mode: 0755]
RELEASE-NOTES-1.34
includes/DefaultSettings.php
includes/Html.php
includes/Revision/RevisionStore.php
includes/ServiceWiring.php
includes/api/ApiQueryBacklinksprop.php
includes/api/ApiQueryBase.php
includes/api/i18n/ja.json
includes/db/MWLBFactory.php
includes/filebackend/FileBackendGroup.php
includes/filerepo/FileRepo.php
includes/installer/MysqlUpdater.php
includes/installer/WebInstaller.php
includes/installer/i18n/de.json
includes/installer/i18n/ja.json
includes/installer/i18n/uk.json
includes/libs/objectcache/wancache/WANObjectCache.php
includes/page/Article.php
includes/specialpage/QueryPage.php
languages/i18n/diq.json
languages/i18n/en.json
languages/i18n/hu.json
languages/i18n/ja.json
languages/i18n/khw.json
languages/i18n/lzh.json
languages/i18n/nap.json
languages/i18n/nqo.json
languages/i18n/qqq.json
maintenance/archives/patch-drop-archive-ar_usertext_timestamp.sql [new file with mode: 0644]
maintenance/archives/patch-drop-archive-usertext_timestamp.sql [new file with mode: 0644]
maintenance/archives/patch-drop-user-fields.sql
maintenance/archives/patch-rename-mysql-user_newtalk-indexes.sql [new file with mode: 0644]
maintenance/storage/recompressTracked.php
maintenance/updateSpecialPages.php
tests/phpunit/includes/Revision/RevisionStoreDbTestBase.php
tests/phpunit/includes/libs/objectcache/WANObjectCacheTest.php

diff --git a/.pipeline/blubber.yaml b/.pipeline/blubber.yaml
new file mode 100644 (file)
index 0000000..13ad966
--- /dev/null
@@ -0,0 +1,14 @@
+version: v4
+base: docker-registry.wikimedia.org/dev/stretch-php72-fpm-apache2
+
+lives:
+  in: /var/www/html
+
+variants:
+  dev:
+    runs:
+      insecurely: true
+    builder:
+      command: [.pipeline/dev_prereq.sh]
+      requirements: [.pipeline, .pipeline/dev_prereq.sh, composer.json]
+    copies: [local]
diff --git a/.pipeline/config.yaml b/.pipeline/config.yaml
new file mode 100644 (file)
index 0000000..08f1db8
--- /dev/null
@@ -0,0 +1,9 @@
+pipelines:
+  publish:
+    blubberfile: blubber.yaml
+    stages:
+      - name: dev
+        build: dev
+        publish:
+          image: true
+          tags: [dev]
diff --git a/.pipeline/dev_prereq.sh b/.pipeline/dev_prereq.sh
new file mode 100755 (executable)
index 0000000..a1f4bd0
--- /dev/null
@@ -0,0 +1,16 @@
+#!/bin/sh
+
+mkdir /tmp/php
+mkdir -p extensions
+
+git clone --depth 1 https://gerrit.wikimedia.org/r/mediawiki/extensions/VisualEditor.git /var/www/html/extensions/VisualEditor
+git clone --depth 1 https://gerrit.wikimedia.org/r/mediawiki/skins/Vector /var/www/html/skins/Vector
+cd /var/www/html/extensions/VisualEditor
+git submodule update --depth 1 --init
+
+cd /var/www/html
+composer install
+cat <<PHP > LocalSettings.php
+<?php
+require_once '/var/config/LocalSettings.php';
+PHP
index 8d9b06e..0d6f1e1 100644 (file)
@@ -576,6 +576,8 @@ because of Phabricator reports.
 * Specifying a SpecialPage object for the list of special pages (either through
   the SpecialPage_initList hook or by adding to $wgSpecialPages) is now
   deprecated.
+* WebInstaller::getInfoBox(), getWarningBox() and getErrorBox() are deprecated.
+  Use Html::errorBox() or Html::warningBox() instead.
 * Use of ActorMigration with 'ar_user', 'img_user', 'oi_user', 'fa_user',
   'rc_user', 'log_user', and 'ipb_by' is deprecated. Queries should be adjusted
   to use the corresponding actor fields directly. Note that use with
index 29b628c..31cb7ae 100644 (file)
@@ -7937,6 +7937,7 @@ $wgAllowSpecialInclusion = true;
 /**
  * Set this to an array of special page names to prevent
  * maintenance/updateSpecialPages.php from updating those pages.
+ * Mapping each special page name to an run mode like 'periodical' if a cronjob is set up.
  */
 $wgDisableQueryPageUpdate = false;
 
index a8f3496..ea2ce07 100644 (file)
@@ -1011,7 +1011,7 @@ class Html {
        /**
         * Get HTML for an information message box with an icon.
         *
-        * @internal For use by the WebInstaller class.
+        * @internal For use by the WebInstaller class only.
         * @param string $rawHtml HTML
         * @param string $icon Path to icon file (used as 'src' attribute)
         * @param string $alt Alternate text for the icon
index a5cf840..a1aeccb 100644 (file)
@@ -1928,7 +1928,10 @@ class RevisionStore
                $titlesByPageId = [];
                foreach ( $rows as $row ) {
                        if ( isset( $rowsByRevId[$row->rev_id] ) ) {
-                               throw new InvalidArgumentException( "Duplicate rows in newRevisionsFromBatch {$row->rev_id}" );
+                               $result->warning(
+                                       'internalerror',
+                                       "Duplicate rows in newRevisionsFromBatch, rev_id {$row->rev_id}"
+                               );
                        }
                        if ( $title && $row->rev_page != $title->getArticleID() ) {
                                throw new InvalidArgumentException(
index ab51eab..83847d8 100644 (file)
@@ -207,10 +207,7 @@ return [
                );
                $class = MWLBFactory::getLBFactoryClass( $lbConf );
 
-               $instance = new $class( $lbConf );
-               MWLBFactory::setSchemaAliases( $instance, $mainConfig->get( 'DBtype' ) );
-
-               return $instance;
+               return new $class( $lbConf );
        },
 
        'EventRelayerGroup' => function ( MediaWikiServices $services ) : EventRelayerGroup {
index b8672ee..022fd9b 100644 (file)
@@ -286,6 +286,8 @@ class ApiQueryBacklinksprop extends ApiQueryGeneratorBase {
                $res = $this->select( __METHOD__ );
 
                if ( is_null( $resultPageSet ) ) {
+                       $this->executeGenderCacheFromResultWrapper( $res, __METHOD__ );
+
                        $count = 0;
                        foreach ( $res as $row ) {
                                if ( ++$count > $params['limit'] ) {
index 8d9cb48..059c438 100644 (file)
@@ -20,6 +20,7 @@
  * @file
  */
 
+use MediaWiki\MediaWikiServices;
 use Wikimedia\Rdbms\IDatabase;
 use Wikimedia\Rdbms\IResultWrapper;
 
@@ -569,6 +570,42 @@ abstract class ApiQueryBase extends ApiBase {
                );
        }
 
+       /**
+        * Preprocess the result set to fill the GenderCache with the necessary information
+        * before using self::addTitleInfo
+        *
+        * @param IResultWrapper $res Result set to work on.
+        *  The result set must have _namespace and _title fields with the provided field prefix
+        * @param string $fname The caller function name, always use __METHOD__
+        * @param string $fieldPrefix Prefix for fields to check gender for
+        */
+       protected function executeGenderCacheFromResultWrapper(
+               IResultWrapper $res, $fname = __METHOD__, $fieldPrefix = 'page'
+       ) {
+               if ( !$res->numRows() ) {
+                       return;
+               }
+
+               $services = MediaWikiServices::getInstance();
+               $nsInfo = $services->getNamespaceInfo();
+               $namespaceField = $fieldPrefix . '_namespace';
+               $titleField = $fieldPrefix . '_title';
+
+               $usernames = [];
+               foreach ( $res as $row ) {
+                       if ( $nsInfo->hasGenderDistinction( $row->$namespaceField ) ) {
+                               $usernames[] = $row->$titleField;
+                       }
+               }
+
+               if ( $usernames === [] ) {
+                       return;
+               }
+
+               $genderCache = $services->getGenderCache();
+               $genderCache->doQuery( $usernames, $fname );
+       }
+
        /** @} */
 
        /************************************************************************//**
index acdb05c..eb588c2 100644 (file)
        "apihelp-edit-param-summary": "編集の要約。$1section=new で $1sectiontitle が設定されていない場合は節名としても利用されます。",
        "apihelp-edit-param-tags": "この版に適用する変更タグ。",
        "apihelp-edit-param-minor": "この編集に細部の変更の印を付ける",
-       "apihelp-edit-param-notminor": "細部の編集ではない。",
+       "apihelp-edit-param-notminor": "利用者設定で「{{int:tog-minordefault}}」を指定してあっても、細部の編集とマークしないでください。",
        "apihelp-edit-param-bot": "この編集をボットの編集としてマークする。",
        "apihelp-edit-param-basetimestamp": "編集前の版のタイムスタンプ。編集競合を検出するために使用されます。\n[[Special:ApiHelp/query+revisions|action=query&prop=revisions&rvprop=timestamp]] で取得できます。",
        "apihelp-edit-param-starttimestamp": "編集作業を開始したときのタイムスタンプ。編集競合を検出するために使用されます。適切な値は <var>[[Special:ApiHelp/main|curtimestamp]]</var> を使用して編集作業を開始するとき (たとえば、編集するページの本文を読み込んだとき) に取得できます。",
        "apihelp-options-example-change": "<kbd>skin</kbd> および <kbd>hideminor</kbd> の個人設定を変更する。",
        "apihelp-options-example-complex": "すべての個人設定を初期化し、<kbd>skin</kbd> および <kbd> nickname </kbd> を設定する。",
        "apihelp-paraminfo-summary": "API モジュールに関する情報を取得します。",
-       "apihelp-paraminfo-param-modules": "モジュールの名前のリスト (<var>action</var> および <var>format</var> パラメーターの値, または <kbd>main</kbd>). <kbd>+</kbd> を使用して下位モジュールを指定できます。",
+       "apihelp-paraminfo-param-modules": "モジュール名のリスト (<var>action</var> および <var>format</var> パラメーターまたは <kbd>main</kbd>の値)。特定の下位モジュールの指定は<kbd>+</kbd> 、全下位モジュールの指定は<kbd>+*</kbd>を使い、あるいは<kbd>+**</kbd>ですべての下位モジュールを再帰的に指定します。",
        "apihelp-paraminfo-param-helpformat": "ヘルプ文字列の形式。",
        "apihelp-paraminfo-param-querymodules": "クエリモジュール名のリスト (<var>prop</var>, <var>meta</var> or <var>list</var> パラメータの値)。<kbd>$1querymodules=foo</kbd> の代わりに <kbd>$1modules=query+foo</kbd> を使用してください。",
        "apihelp-paraminfo-example-1": "<kbd>[[Special:ApiHelp/parse|action=parse]]</kbd>, <kbd>[[Special:ApiHelp/jsonfm|format=jsonfm]]</kbd>, <kbd>[[Special:ApiHelp/query+allpages|action=query&list=allpages]]</kbd>, and <kbd>[[Special:ApiHelp/query+siteinfo|action=query&meta=siteinfo]]</kbd> に関する情報を表示する。",
        "apihelp-parse-paramvalue-prop-revid": "構文解析されたページの版IDを追加します。",
        "apihelp-parse-paramvalue-prop-displaytitle": "構文解析されたウィキテキストのタイトルを追加します。",
        "apihelp-parse-paramvalue-prop-headitems": "ページの <code>&lt;head&gt;</code> の中に入れてアイテムを提供します。",
-       "apihelp-parse-paramvalue-prop-headhtml": "ページの解析された <code>&lt;head&gt;</code> を与える。",
+       "apihelp-parse-paramvalue-prop-headhtml": "ページの<code>&lt;html&gt;</code>と<code>&lt;head&gt;</code>の要素を開いて<code>&lt;body&gt;</code>を開示し、Doctype を解析する。",
        "apihelp-parse-paramvalue-prop-jsconfigvars": "ページに固有のJavaScriptの設定変数を提供します。適用するには、<code>mw.config.set()</code>を使用します。",
        "apihelp-parse-paramvalue-prop-encodedjsconfigvars": "JSON文字列としてページに固有のJavaScriptの設定変数を提供します。",
        "apihelp-parse-paramvalue-prop-indicators": "ページ上で使用されるページのステータスインジケータのHTMLを提供します。",
index 1803009..63b320e 100644 (file)
@@ -23,7 +23,6 @@
 
 use MediaWiki\Config\ServiceOptions;
 use MediaWiki\Logger\LoggerFactory;
-use Wikimedia\Rdbms\LBFactory;
 use Wikimedia\Rdbms\DatabaseDomain;
 
 /**
@@ -359,35 +358,6 @@ abstract class MWLBFactory {
                return $class;
        }
 
-       /**
-        * @param LBFactory $lbFactory
-        * @param string $dbType 'mysql', 'sqlite', etc.
-        * @internal For use with service wiring
-        */
-       public static function setSchemaAliases( LBFactory $lbFactory, $dbType ) {
-               if ( $dbType === 'mysql' ) {
-                       /**
-                        * When SQLite indexes were introduced in r45764, it was noted that
-                        * SQLite requires index names to be unique within the whole database,
-                        * not just within a schema. As discussed in CR r45819, to avoid the
-                        * need for a schema change on existing installations, the indexes
-                        * were implicitly mapped from the new names to the old names.
-                        *
-                        * This mapping can be removed if DB patches are introduced to alter
-                        * the relevant tables in existing installations. Note that because
-                        * this index mapping applies to table creation, even new installations
-                        * of MySQL have the old names (except for installations created during
-                        * a period where this mapping was inappropriately removed, see
-                        * T154872).
-                        */
-                       $lbFactory->setIndexAliases( [
-                               'ar_usertext_timestamp' => 'usertext_timestamp',
-                               'un_user_id' => 'user_id',
-                               'un_user_ip' => 'user_ip',
-                       ] );
-               }
-       }
-
        /**
         * Log a database deprecation warning
         * @param string $msg Deprecation message
index 9e04d09..f369f00 100644 (file)
@@ -123,8 +123,28 @@ class FileBackendGroup {
                        }
                        $class = $config['class'];
 
-                       // @FIXME: ideally this would default to the DB domain (which includes the schema)
-                       $config['domainId'] = $config['domainId'] ?? ( $config['wikiId'] ?? wfWikiID() );
+                       if ( isset( $config['domainId'] ) ) {
+                               $domainId = $config['domainId'];
+                       } elseif ( isset( $config['wikiId'] ) ) {
+                               $domainId = $config['wikiId']; // b/c
+                       } else {
+                               // Only use the raw database/prefix for backwards compatibility
+                               $ld = WikiMap::getCurrentWikiDbDomain();
+                               $domainId = strlen( $ld->getTablePrefix() )
+                                       ? "{$ld->getDatabase()}-{$ld->getTablePrefix()}"
+                                       : $ld->getDatabase();
+                               // If the local wiki ID and local domain ID do not match, probably due to a
+                               // non-default schema, issue a warning. A non-default schema indicates that
+                               // it might be used to disambiguate different wikis.
+                               $wikiId = WikiMap::getWikiIdFromDbDomain( $ld );
+                               if ( $ld->getSchema() !== null && $domainId !== $wikiId ) {
+                                       wfWarn(
+                                               "\$wgFileBackend entry '$name' should have 'domainId' set.\n" .
+                                               "Legacy default 'domainId' is '$domainId' but wiki ID is '$wikiId'."
+                                       );
+                               }
+                       }
+                       $config['domainId'] = $domainId;
                        $config['readOnly'] = $config['readOnly'] ?? $readOnlyReason;
 
                        unset( $config['class'] ); // backend won't need this
index ff8f056..f095066 100644 (file)
@@ -838,7 +838,11 @@ class FileRepo {
        /**
         * Store a file to a given destination.
         *
-        * @param string $srcPath Source file system path, storage path, or virtual URL
+        * Using FSFile/TempFSFile can improve performance via caching.
+        * Using TempFSFile can further improve performance by signalling that it is safe
+        * to touch the source file or write extended attribute metadata to it directly.
+        *
+        * @param string|FSFile $srcPath Source file system path, storage path, or virtual URL
         * @param string $dstZone Destination zone
         * @param string $dstRel Destination relative path
         * @param int $flags Bitwise combination of the following flags:
@@ -862,6 +866,8 @@ class FileRepo {
        /**
         * Store a batch of files
         *
+        * @see FileRepo::store()
+        *
         * @param array $triplets (src, dest zone, dest rel) triplets as per store()
         * @param int $flags Bitwise combination of the following flags:
         *   self::OVERWRITE         Overwrite an existing destination file instead of failing
@@ -884,11 +890,18 @@ class FileRepo {
                $operations = [];
                // Validate each triplet and get the store operation...
                foreach ( $triplets as $triplet ) {
-                       list( $srcPath, $dstZone, $dstRel ) = $triplet;
+                       list( $src, $dstZone, $dstRel ) = $triplet;
+                       $srcPath = ( $src instanceof FSFile ) ? $src->getPath() : $src;
                        wfDebug( __METHOD__
                                . "( \$src='$srcPath', \$dstZone='$dstZone', \$dstRel='$dstRel' )\n"
                        );
-
+                       // Resolve source path
+                       if ( $src instanceof FSFile ) {
+                               $op = 'store';
+                       } else {
+                               $src = $this->resolveToStoragePathIfVirtual( $src );
+                               $op = FileBackend::isStoragePath( $src ) ? 'copy' : 'store';
+                       }
                        // Resolve destination path
                        $root = $this->getZonePath( $dstZone );
                        if ( !$root ) {
@@ -904,13 +917,10 @@ class FileRepo {
                                return $this->newFatal( 'directorycreateerror', $dstDir );
                        }
 
-                       // Resolve source to a storage path if virtual
-                       $srcPath = $this->resolveToStoragePathIfVirtual( $srcPath );
-
                        // Copy the source file to the destination
                        $operations[] = [
-                               'op' => FileBackend::isStoragePath( $srcPath ) ? 'copy' : 'store',
-                               'src' => $srcPath, // storage path (copy) or local file path (store)
+                               'op' => $op,
+                               'src' => $src, // storage path (copy) or local file path (store)
                                'dst' => $dstPath,
                                'overwrite' => ( $flags & self::OVERWRITE ) ? true : false,
                                'overwriteSame' => ( $flags & self::OVERWRITE_SAME ) ? true : false,
@@ -970,6 +980,10 @@ class FileRepo {
         * This function can be used to write to otherwise read-only foreign repos.
         * This is intended for copying generated thumbnails into the repo.
         *
+        * Using FSFile/TempFSFile can improve performance via caching.
+        * Using TempFSFile can further improve performance by signalling that it is safe
+        * to touch the source file or write extended attribute metadata to it directly.
+        *
         * @param string|FSFile $src Source file system path, storage path, or virtual URL
         * @param string $dst Virtual URL or storage path
         * @param array|string|null $options An array consisting of a key named headers
@@ -981,39 +995,14 @@ class FileRepo {
                return $this->quickImportBatch( [ [ $src, $dst, $options ] ] );
        }
 
-       /**
-        * Purge a file from the repo. This does no locking nor journaling.
-        * This function can be used to write to otherwise read-only foreign repos.
-        * This is intended for purging thumbnails.
-        *
-        * @param string $path Virtual URL or storage path
-        * @return Status
-        */
-       final public function quickPurge( $path ) {
-               return $this->quickPurgeBatch( [ $path ] );
-       }
-
-       /**
-        * Deletes a directory if empty.
-        * This function can be used to write to otherwise read-only foreign repos.
-        *
-        * @param string $dir Virtual URL (or storage path) of directory to clean
-        * @return Status
-        */
-       public function quickCleanDir( $dir ) {
-               $status = $this->newGood();
-               $status->merge( $this->backend->clean(
-                       [ 'dir' => $this->resolveToStoragePathIfVirtual( $dir ) ] ) );
-
-               return $status;
-       }
-
        /**
         * Import a batch of files from the local file system into the repo.
         * This does no locking nor journaling and overrides existing files.
         * This function can be used to write to otherwise read-only foreign repos.
         * This is intended for copying generated thumbnails into the repo.
         *
+        * @see FileRepo::quickImport()
+        *
         * All path parameters may be a file system path, storage path, or virtual URL.
         * When "headers" are given they are used as HTTP headers if supported.
         *
@@ -1046,7 +1035,7 @@ class FileRepo {
 
                        $operations[] = [
                                'op' => $op,
-                               'src' => $src,
+                               'src' => $src, // storage path (copy) or local path/FSFile (store)
                                'dst' => $dst,
                                'headers' => $headers
                        ];
@@ -1057,6 +1046,33 @@ class FileRepo {
                return $status;
        }
 
+       /**
+        * Purge a file from the repo. This does no locking nor journaling.
+        * This function can be used to write to otherwise read-only foreign repos.
+        * This is intended for purging thumbnails.
+        *
+        * @param string $path Virtual URL or storage path
+        * @return Status
+        */
+       final public function quickPurge( $path ) {
+               return $this->quickPurgeBatch( [ $path ] );
+       }
+
+       /**
+        * Deletes a directory if empty.
+        * This function can be used to write to otherwise read-only foreign repos.
+        *
+        * @param string $dir Virtual URL (or storage path) of directory to clean
+        * @return Status
+        */
+       public function quickCleanDir( $dir ) {
+               $status = $this->newGood();
+               $status->merge( $this->backend->clean(
+                       [ 'dir' => $this->resolveToStoragePathIfVirtual( $dir ) ] ) );
+
+               return $status;
+       }
+
        /**
         * Purge a batch of files from the repo.
         * This function can be used to write to otherwise read-only foreign repos.
@@ -1169,6 +1185,10 @@ class FileRepo {
         * Returns a Status object. On success, the value contains "new" or
         * "archived", to indicate whether the file was new with that name.
         *
+        * Using FSFile/TempFSFile can improve performance via caching.
+        * Using TempFSFile can further improve performance by signalling that it is safe
+        * to touch the source file or write extended attribute metadata to it directly.
+        *
         * Options to $options include:
         *   - headers : name/value map of HTTP headers to use in response to GET/HEAD requests
         *
@@ -1199,6 +1219,8 @@ class FileRepo {
        /**
         * Publish a batch of files
         *
+        * @see FileRepo::publish()
+        *
         * @param array $ntuples (source, dest, archive) triplets or
         *   (source, dest, archive, options) 4-tuples as per publish().
         * @param int $flags Bitfield, may be FileRepo::DELETE_SOURCE to indicate
@@ -1277,7 +1299,7 @@ class FileRepo {
                        } else {
                                $operations[] = [
                                        'op' => 'store',
-                                       'src' => $src, // FSFile (preferred) or local file path
+                                       'src' => $src, // storage path (copy) or local path/FSFile (store)
                                        'dst' => $dstPath,
                                        'overwrite' => true, // replace current
                                        'headers' => $headers
index ea88411..a53a72b 100644 (file)
@@ -386,7 +386,11 @@ class MysqlUpdater extends DatabaseUpdater {
                        [ 'modifyTable', 'job', 'patch-job-params-mediumblob.sql' ],
 
                        // 1.34
+                       [ 'dropIndex', 'archive', 'ar_usertext_timestamp',
+                               'patch-drop-archive-ar_usertext_timestamp.sql' ],
+                       [ 'dropIndex', 'archive', 'usertext_timestamp', 'patch-drop-archive-usertext_timestamp.sql' ],
                        [ 'dropField', 'logging', 'log_user', 'patch-drop-user-fields.sql' ],
+                       [ 'addIndex', 'user_newtalk', 'un_user_ip', 'patch-rename-mysql-user_newtalk-indexes.sql' ],
                ];
        }
 
index 21ad210..d9cd6de 100644 (file)
@@ -638,34 +638,40 @@ class WebInstaller extends Installer {
        /**
         * Get HTML for an error box with an icon.
         *
+        * @deprecated since 1.34 Use Html::errorBox() instead.
         * @param string $text Wikitext, get this with wfMessage()->plain()
         *
         * @return string
         */
        public function getErrorBox( $text ) {
+               wfDeprecated( __METHOD__, '1.34' );
                return $this->getInfoBox( $text, 'critical-32.png', 'config-error-box' );
        }
 
        /**
         * Get HTML for a warning box with an icon.
         *
+        * @deprecated since 1.34 Use Html::warningBox() instead.
         * @param string $text Wikitext, get this with wfMessage()->plain()
         *
         * @return string
         */
        public function getWarningBox( $text ) {
+               wfDeprecated( __METHOD__, '1.34' );
                return $this->getInfoBox( $text, 'warning-32.png', 'config-warning-box' );
        }
 
        /**
         * Get HTML for an information message box with an icon.
         *
+        * @deprecated since 1.34.
         * @param string|HtmlArmor $text Wikitext to be parsed (from Message::plain) or raw HTML.
         * @param string|bool $icon Icon name, file in mw-config/images. Default: false
         * @param string|bool $class Additional class name to add to the wrapper div. Default: false.
         * @return string HTML
         */
        public function getInfoBox( $text, $icon = false, $class = false ) {
+               wfDeprecated( __METHOD__, '1.34' );
                $html = ( $text instanceof HtmlArmor ) ?
                        HtmlArmor::getHtml( $text ) :
                        $this->parse( $text, true );
index 4039391..866c3f5 100644 (file)
@@ -58,7 +58,7 @@
        "config-restart": "Ja, erneut starten",
        "config-welcome": "=== Prüfung der Installationsumgebung ===\nDie Basisprüfungen werden jetzt durchgeführt, um festzustellen, ob die Installationsumgebung für MediaWiki geeignet ist.\nNotiere diese Informationen und gib sie an, sofern du Hilfe beim Installieren benötigst.",
        "config-welcome-section-copyright": "=== Lizenz und Nutzungsbedingungen ===\n\n$1\n\nDieses Programm ist freie Software, d. h. es kann, gemäß den Bedingungen der von der Free Software Foundation veröffentlichten ''GNU General Public License'', weiterverteilt und/oder modifiziert werden. Dabei kann die Version 2, oder nach eigenem Ermessen, jede neuere Version der Lizenz verwendet werden.\n\nDieses Programm wird in der Hoffnung verteilt, dass es nützlich sein wird, allerdings '''ohne jegliche Garantie''' und sogar ohne die implizierte Garantie einer '''Marktgängigkeit''' oder '''Eignung für einen bestimmten Zweck'''. Hierzu sind weitere Hinweise in der ''GNU General Public License'' enthalten.\n\nEine [$2 Kopie der GNU General Public License] sollte zusammen mit diesem Programm verteilt worden sein. Sofern dies nicht der Fall war, kann eine Kopie bei der Free Software Foundation Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA, schriftlich angefordert oder auf deren Website [https://www.gnu.org/copyleft/gpl.html online gelesen] werden.",
-       "config-sidebar": "* [https://www.mediawiki.org/wiki/MediaWiki/de Website von MediaWiki]\n* [https://www.mediawiki.org/wiki/Special:MyLanguage/Help:Contents/de Benutzer­anleitung]\n* [https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:Contents/de Administratoren­anleitung]\n* [https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:FAQ/de Häufig gestellte Fragen]\n----\n* <doclink href=Readme>Lies mich</doclink>\n* <doclink href=ReleaseNotes>Versions­informationen</doclink>\n* <doclink href=Copying>Lizenz­bestimmungen</doclink>\n* <doclink href=UpgradeDoc>Aktualisierung</doclink>",
+       "config-sidebar": "* [https://www.mediawiki.org/wiki/MediaWiki/de Website von MediaWiki]\n* [https://www.mediawiki.org/wiki/Special:MyLanguage/Help:Contents/de Benutzer­anleitung]\n* [https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:Contents/de Administratoren­anleitung]\n* [https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:FAQ/de Häufig gestellte Fragen]",
        "config-sidebar-readme": "Lies mich",
        "config-sidebar-relnotes": "Veröffentlichungsinformationen",
        "config-sidebar-license": "Kopieren",
@@ -95,7 +95,7 @@
        "config-uploads-not-safe": "'''Warnung:''' Das Standardverzeichnis für hochgeladene Dateien <code>$1</code> ist für die willkürliche Ausführung von Skripten anfällig.\nObwohl MediaWiki die hochgeladenen Dateien auf Sicherheitsrisiken überprüft, wird dennoch dringend empfohlen, diese [https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:Security#Upload_security Sicherheitslücke] zu schließen, bevor das Hochladen von Dateien aktiviert wird.",
        "config-no-cli-uploads-check": "'''Warnung''': Das Standardverzeichnis für hochgeladene Dateien (<code>$1</code>) wird, während der Installation über die Kommandozeile, nicht auf Sicherheitsanfälligkeiten hinsichtlich willkürlicher Skriptausführungen geprüft.",
        "config-brokenlibxml": "Das System nutzt eine Kombination aus PHP- und libxml2-Versionen, die fehleranfällig ist und versteckte Datenfehler bei MediaWiki und anderen Webanwendungen verursachen kann.\nAktualisiere auf libxml2 2.7.3 oder später, um das Problem zu lösen. Installationsabbruch ([https://bugs.php.net/bug.php?id=45996 siehe hierzu die Fehlermeldung bei PHP]).",
-       "config-suhosin-max-value-length": "Suhosin ist installiert und beschränkt die Länge des GET-Parameters auf $1 Bytes.\nDer ResouceLoader von MediaWiki wird zwar unter diesen Bedingungen funktionieren, allerdings nur mit verminderter Leistungsfähigkeit.\nSofern möglich, sollte der Parameter <code>suhosin.get.max_value_length</code> in der Datei <code>php.ini</code> auf 1024 oder höher festgelegt werden.\nGleichzeitig muss der Parameter <code>$wgResourceLoaderMaxQueryLength</code> in der Datei <code>LocalSettings.php</code> auf den selben Wert eingestellt werden.",
+       "config-suhosin-max-value-length": "Suhosin ist installiert und beschränkt die Länge des GET-Parameters auf $1 Bytes.\nMediaWiki wird nur funktionieren, wenn code>suhosin.get.max_value_length</code> $2 oder höher ist. Deaktiviere diese Einstellung oder ändere sie in <code>php.ini</code> zu $3.",
        "config-using-32bit": "<strong>Warnung:</strong> Es scheint, als ob dein System mit 32-Bit-Ganzzahlen läuft. Dies wird [https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:32-bit nicht empfohlen].",
        "config-db-type": "Datenbanksystem:",
        "config-db-host": "Datenbankserver:",
index 511b0da..7a614e8 100644 (file)
        "config-extension-not-found": "拡張機能「$1」の登録ファイルは見つかりませんでした",
        "config-extension-dependency": "拡張機能「$1」のインストール中に依存関係エラーが発生しました: $2",
        "mainpagetext": "<strong>MediaWiki はインストール済みです。</strong>",
-       "mainpagedocfooter": "ウィキソフトウェアの使い方に関する情報は[https://www.mediawiki.org/wiki/Special:MyLanguage/Help:Contents 利用者案内]を参照してください。\n\n== はじめましょう ==\n* [https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:Configuration_settings/ja 設定の一覧]\n* [https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:FAQ/ja MediaWiki よくある質問と回答]\n* [https://lists.wikimedia.org/mailman/listinfo/mediawiki-announce MediaWiki リリース情報メーリングリスト]\n* [https://www.mediawiki.org/wiki/Special:MyLanguage/Localisation/ja MediaWiki のあなたの言語へのローカライズ]\n* [https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:Combating_spam あなたのウィキでスパムと戦う方法を学ぶ]"
+       "mainpagedocfooter": "ウィキソフトウェアの使い方に関する情報は[https://www.mediawiki.org/wiki/Special:MyLanguage/Help:Contents 利用者案内]を参照してください。\n\nウィキソフトウェアの使い方に関する情報は[https://www.mediawiki.org/wiki/Special:MyLanguage/Help:Contents 利用者案内]を参照してください。\n\n== はじめましょう ==\n* [https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:Configuration_settings/ja 設定の一覧]\n* [https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:FAQ/ja MediaWiki よくある質問]\n* [https://lists.wikimedia.org/mailman/listinfo/mediawiki-announce MediaWiki リリース情報メーリングリスト]\n* [https://www.mediawiki.org/wiki/Special:MyLanguage/Localisation/ja MediaWiki をご使用の言語へ地域化]\n* [https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:Combating_spam ご使用のウィキでスパムと戦う方法を学ぶ]"
 }
index 938f199..e9d578b 100644 (file)
@@ -93,7 +93,7 @@
        "config-uploads-not-safe": "'''Увага:''' Ваша типова папка для завантажень <code>$1</code> вразлива до виконання довільних скриптів.\nХоча MediaWiki перевіряє усі завантажені файли на наявність загроз, наполегливо рекомендується [https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:Security#Upload_security закрити дану вразливість] перед тим, як дозволяти завантаження файлів.",
        "config-no-cli-uploads-check": "'''Увага:''' Ваша типова папка для завантажень (<code>$1</code>) не перевірялась на вразливість до виконання довільних скриптів під час встановлення CLI.",
        "config-brokenlibxml": "У Вашій системі невдале поєднання версій PHP і libxml2, яке може спричинити пошкодження прихованих даних у MediaWiki та інших веб-застосунках.\nОновіть libxml2 до версії 2.7.3 або пізнішої  ([https://bugs.php.net/bug.php?id=45996 відомості про помилку]).\nВстановлення перервано.",
-       "config-suhosin-max-value-length": "Suhosin Ð²Ñ\81Ñ\82ановлено Ñ\96 Ð¾Ð±Ð¼ÐµÐ¶Ñ\83Ñ\94 Ð¿Ð°Ñ\80амеÑ\82Ñ\80а GET  <code>length</code> Ð´Ð¾ $1 Ð±Ð°Ð¹Ñ\82а. Ð\9aомпоненÑ\82 MediaWiki ResourceLoader Ð±Ñ\83де Ð¾Ð±Ñ\85одиÑ\82и Ñ\86е Ð¾Ð±Ð¼ÐµÐ¶ÐµÐ½Ð½Ñ\8f, Ð¾Ð´Ð½Ð°Ðº Ñ\86е Ð·Ð¼ÐµÐ½Ñ\88иÑ\82Ñ\8c Ð¿Ñ\80одÑ\83кÑ\82ивнÑ\96Ñ\81Ñ\82Ñ\8c. Ð¯ÐºÑ\89о Ñ\86е Ð¼Ð¾Ð¶Ð»Ð¸Ð²Ð¾, Ð\92ам Ð²Ð°Ñ\80Ñ\82о Ð²Ñ\81Ñ\82ановиÑ\82и Ð·Ð½Ð°Ñ\87еннÑ\8f <code>suhosin.get.max_value_length</code> Ñ\8fк 1024 Ñ\96 Ð±Ñ\96лÑ\8cÑ\88е Ñ\83 <code>php.ini</code> Ñ\96 Ð²Ñ\81Ñ\82ановиÑ\82и Ñ\82аке Ð¶ Ð·Ð½Ð°Ñ\87еннÑ\8f <code>$wgResourceLoaderMaxQueryLength</code> Ñ\83 LocalSettings.php .",
+       "config-suhosin-max-value-length": "Suhosin Ð²Ñ\81Ñ\82ановлено Ñ\96 Ð²Ñ\96н Ð¾Ð±Ð¼ÐµÐ¶Ñ\83Ñ\94 GET-паÑ\80амеÑ\82Ñ\80 <code>length</code> Ð´Ð¾ $1 {{PLURAL:$1|байÑ\82|байÑ\82а|байÑ\82}}.   Ð\94лÑ\8f MediaWiki Ð¿Ð¾Ñ\82Ñ\80Ñ\96бно, Ñ\89об Ð·Ð½Ð°Ñ\87еннÑ\8f <code>suhosin.get.max_value_length</code> Ð±Ñ\83ло Ñ\85оÑ\87а Ð± $2. Ð\92имкнÑ\96Ñ\82Ñ\8c Ñ\86е Ð½Ð°Ð»Ð°Ñ\88Ñ\82Ñ\83ваннÑ\8f, Ð°Ð±Ð¾ Ð·Ð±Ñ\96лÑ\8cÑ\88Ñ\96Ñ\82Ñ\8c Ð·Ð½Ð°Ñ\87еннÑ\8f Ñ\83 <code>php.ini</code> Ð´Ð¾ $3.",
        "config-using-32bit": "<strong>Попередження:</strong> схоже, що Ваша система працює з 32-бітними цілими числами. Таке [https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:32-bit не рекомендується].",
        "config-db-type": "Тип бази даних:",
        "config-db-host": "Хост бази даних:",
index 70f3553..2f44a55 100644 (file)
@@ -1269,7 +1269,7 @@ class WANObjectCache implements IExpiringStore, IStoreKeyEncoder, LoggerAwareInt
                // Nested callback process cache use is not lag-safe with regard to HOLDOFF_TTL since
                // process cached values are more lagged than persistent ones as they are not purged.
                if ( $pCache && $this->callbackDepth == 0 ) {
-                       $cached = $pCache->get( $this->getProcessCacheKey( $key, $version ), INF, false );
+                       $cached = $pCache->get( $this->getProcessCacheKey( $key, $version ), $pcTTL, false );
                        if ( $cached !== false ) {
                                return $cached;
                        }
@@ -2545,6 +2545,9 @@ class WANObjectCache implements IExpiringStore, IStoreKeyEncoder, LoggerAwareInt
                if ( !isset( $this->processCaches[$group] ) ) {
                        list( , $size ) = explode( ':', $group );
                        $this->processCaches[$group] = new MapCacheLRU( (int)$size );
+                       if ( $this->wallClockOverride !== null ) {
+                               $this->processCaches[$group]->setMockTime( $this->wallClockOverride );
+                       }
                }
 
                return $this->processCaches[$group];
@@ -2641,5 +2644,8 @@ class WANObjectCache implements IExpiringStore, IStoreKeyEncoder, LoggerAwareInt
        public function setMockTime( &$time ) {
                $this->wallClockOverride =& $time;
                $this->cache->setMockTime( $time );
+               foreach ( $this->processCaches as $pCache ) {
+                       $pCache->setMockTime( $time );
+               }
        }
 }
index 4b37181..b6e366e 100644 (file)
@@ -1668,7 +1668,7 @@ class Article implements Page {
                }
 
                // the outer div is need for styling the revision info and nav in MobileFrontend
-               $outputPage->addSubtitle( "<div class=\"mw-revision\">" . $revisionInfo .
+               $outputPage->addSubtitle( "<div class=\"mw-revision warningbox\">" . $revisionInfo .
                        "<div id=\"mw-revision-nav\">" . $cdel .
                        $context->msg( 'revision-nav' )->rawParams(
                                $prevdiff, $prevlink, $lnk, $curdiff, $nextlink, $nextdiff
index b7eb3c0..6ed5e12 100644 (file)
@@ -118,6 +118,30 @@ abstract class QueryPage extends SpecialPage {
                return $qp;
        }
 
+       /**
+        * Get a list of query pages disabled and with it's run mode
+        * @param Config $config
+        * @return string[]
+        */
+       public static function getDisabledQueryPages( Config $config ) {
+               $disableQueryPageUpdate = $config->get( 'DisableQueryPageUpdate' );
+
+               if ( !is_array( $disableQueryPageUpdate ) ) {
+                       return [];
+               }
+
+               $pages = [];
+               foreach ( $disableQueryPageUpdate as $name => $runMode ) {
+                       if ( is_int( $name ) ) {
+                               // The run mode may be omitted
+                               $pages[$runMode] = 'disabled';
+                       } else {
+                               $pages[$name] = $runMode;
+                       }
+               }
+               return $pages;
+       }
+
        /**
         * A mutator for $this->listoutput;
         *
@@ -632,13 +656,21 @@ abstract class QueryPage extends SpecialPage {
 
                                # If updates on this page have been disabled, let the user know
                                # that the data set won't be refreshed for now
-                               if ( is_array( $this->getConfig()->get( 'DisableQueryPageUpdate' ) )
-                                       && in_array( $this->getName(), $this->getConfig()->get( 'DisableQueryPageUpdate' ) )
-                               ) {
-                                       $out->wrapWikiMsg(
-                                               "<div class=\"mw-querypage-no-updates\">\n$1\n</div>",
-                                               'querypage-no-updates'
-                                       );
+                               $disabledQueryPages = self::getDisabledQueryPages( $this->getConfig() );
+                               if ( isset( $disabledQueryPages[$this->getName()] ) ) {
+                                       $runMode = $disabledQueryPages[$this->getName()];
+                                       if ( $runMode === 'disabled' ) {
+                                               $out->wrapWikiMsg(
+                                                       "<div class=\"mw-querypage-no-updates\">\n$1\n</div>",
+                                                       'querypage-no-updates'
+                                               );
+                                       } else {
+                                               // Messages used here: querypage-updates-periodical
+                                               $out->wrapWikiMsg(
+                                                       "<div class=\"mw-querypage-updates-" . $runMode . "\">\n$1\n</div>",
+                                                       'querypage-updates-' . $runMode
+                                               );
+                                       }
                                }
                        }
                }
index 67cdbad..ecddb15 100644 (file)
        "sp-contributions-userrights": "idareyê heqanê {{GENDER:$1|karberan}}",
        "sp-contributions-blocked-notice": "Eno karber/ena karbere emanet blokekerdeyo/blokekerdiya.\nCıkewtışo tewr peyêno ke bloke biyo, cêr seba referansi belikerdeyo:",
        "sp-contributions-blocked-notice-anon": "Eno adresê IPi bloke biyo.\nCıkewtışo tewr peyêno ke bloke biyo, cêr seba referansi belikerdeyo:",
-       "sp-contributions-search": "Dekerdena cı geyrê",
+       "sp-contributions-search": "İştırakan cı geyrê",
        "sp-contributions-username": "Adresa IPy ya zi nameyê karberi:",
        "sp-contributions-toponly": "Tenya tewr çım ra viyarnayışanê peyniyan bımocne",
        "sp-contributions-newonly": "Tenya vurnayışanê pelevıraştışi bımocne",
index 7944a37..8092bf6 100644 (file)
        "perfcached": "The following data is cached and may not be up to date. A maximum of {{PLURAL:$1|one result is|$1 results are}} available in the cache.",
        "perfcachedts": "The following data is cached, and was last updated $1. A maximum of {{PLURAL:$4|one result is|$4 results are}} available in the cache.",
        "querypage-no-updates": "Updates for this page are currently disabled.\nData here will not presently be refreshed.",
+       "querypage-updates-periodical": "Updates for this page are run periodically.",
        "viewsource": "View source",
        "viewsource-title": "View source for $1",
        "actionthrottled": "Action throttled",
index a346ed2..0ecff4f 100644 (file)
        "oct": "okt",
        "nov": "nov",
        "dec": "dec",
-       "january-date": "Január $1",
-       "february-date": "Február $1",
-       "march-date": "Március $1",
-       "april-date": "Ã\81prilis $1",
-       "may-date": "Május $1",
-       "june-date": "Június $1",
-       "july-date": "Július $1",
-       "august-date": "Augusztus $1",
-       "september-date": "Szeptember $1",
-       "october-date": "Október $1",
-       "november-date": "November $1",
-       "december-date": "December $1",
+       "january-date": "január $1",
+       "february-date": "február $1",
+       "march-date": "március $1",
+       "april-date": "április $1",
+       "may-date": "május $1",
+       "june-date": "június $1",
+       "july-date": "július $1",
+       "august-date": "augusztus $1",
+       "september-date": "szeptember $1",
+       "october-date": "október $1",
+       "november-date": "november $1",
+       "december-date": "december $1",
        "period-am": "de.",
        "period-pm": "du.",
        "pagecategories": "{{PLURAL:$1|Kategória|Kategória}}",
        "category_header": "A(z) „$1” kategóriába tartozó lapok",
        "subcategories": "Alkategóriák",
        "category-media-header": "A(z) „$1” kategóriába tartozó médiafájlok",
-       "category-empty": "''Ebben a kategóriában pillanatnyilag egyetlen lap vagy médiafájl sem szerepel.''",
+       "category-empty": "<em>Ebben a kategóriában pillanatnyilag egyetlen lap vagy médiafájl sem szerepel.</em>",
        "hidden-categories": "{{PLURAL:$1|Rejtett kategória|Rejtett kategóriák}}",
        "hidden-category-category": "Rejtett kategóriák",
        "category-subcat-count": "{{PLURAL:$2|Ennek a kategóriának csak egyetlen alkategóriája van.|Ez a kategória az alábbi {{PLURAL:$1|alkategóriával|$1 alkategóriával}} rendelkezik (összesen $2 alkategóriája van).}}",
index 20e2bb7..ff33e2e 100644 (file)
        "botpasswords-insert-failed": "ボット「$1」の追加に失敗しました。既に追加されていないか確認してください。",
        "botpasswords-update-failed": "ボット「$1」の更新に失敗しました。削除されていないか確認してください。",
        "botpasswords-created-title": "ボット用パスワードが作成されました",
-       "botpasswords-created-body": "利用者「$2」のボット名「$1」のためのパスワードが作成されました。",
+       "botpasswords-created-body": "{{GENDER:$2|利用者}}「$2」のボット「$1」のパスワードが作成されました。",
        "botpasswords-updated-title": "ボット用パスワードが更新されました",
-       "botpasswords-updated-body": "利用者「$2」のボット名「$1」のためのパスワードが更新されました。",
+       "botpasswords-updated-body": "{{GENDER:$2|利用者}}「$2」のボット「$1」のパスワードが更新されました。",
        "botpasswords-deleted-title": "ボット用パスワードが削除されました",
-       "botpasswords-deleted-body": "利用者「$2」のボット名「$1」のためのパスワードが削除されました。",
+       "botpasswords-deleted-body": "{{GENDER:$2|利用者}}「$2」のボット「$1」のパスワードが削除されました。",
        "botpasswords-newpassword": "<strong>$1</strong>用の新しいパスワードは<strong>$2</strong>です。<em>後で参照するために、この情報を控えておいてください。</em><br />(古いボットの制約などでログイン名と利用者名が同じでなければならない場合は、<strong>$3</strong>を利用者名とし、<strong>$4</strong>をパスワードとしてください。)",
        "botpasswords-no-provider": "BotPasswordsSessionProvider が有効ではありません。",
        "botpasswords-restriction-failed": "ボットパスワード制限によりログインできません。",
        "tags-delete-not-allowed": "拡張機能によって定義されているタグは削除できません(ただし拡張機能が明示的に削除を許可している場合を除く)。",
        "tags-delete-not-found": "タグ「$1」は存在しません。",
        "tags-delete-too-many-uses": "タグ「$1」は少なくとも$2版に付与されており、削除できません。",
-       "tags-delete-warnings-after-delete": "ã\82¿ã\82°ã\80\8c$1ã\80\8dã\81®å\89\8aé\99¤ã\81\97ã\81¾ã\81\97ã\81\9fã\81\8c、以下の{{PLURAL:$2|警告}}が発生しました:",
+       "tags-delete-warnings-after-delete": "ã\82¿ã\82°ã\80\8c$1ã\80\8dã\82\92å\89\8aé\99¤ã\81\97ã\81\9fã\81¨ã\81\93ã\82\8d、以下の{{PLURAL:$2|警告}}が発生しました:",
        "tags-delete-no-permission": "変更タグを削除する権限がありません。",
        "tags-activate-title": "タグの有効化",
        "tags-activate-question": "タグ「$1」を有効化しようとしています。",
index 4153130..56175e9 100644 (file)
@@ -7,7 +7,8 @@
                        "Macofe",
                        "Saraiki",
                        "BukhariSaeed",
-                       "Fitoschido"
+                       "Fitoschido",
+                       "Amire80"
                ]
        },
        "tog-underline": "ربطو خط کشیدگی",
index 659bbec..bf2ca77 100644 (file)
        "showpreview": "示覽",
        "showdiff": "示異",
        "anoneditwarning": "'''警示:'''子未登簿,若確纂,IP將誌。茍[$1 登]或[$2 開戶口],是纂欲存以子名,及他效。",
-       "anonpreviewwarning": "''子未登簿,IP將誌。''",
+       "anonpreviewwarning": "子未登簿,IP將誌。",
        "missingsummary": "'''醒示:'''子未概之,復「$1」則文倍焉。",
        "missingcommenttext": "請贊之",
        "missingcommentheader": "'''醒示:'''子未概標之,復「$1」則文倍焉。",
index 14235e1..105f3d3 100644 (file)
        "errorpagetitle": "Sbaglio",
        "returnto": "Torna a $1.",
        "tagline": "'A {{SITENAME}}.",
-       "help": "Ajùto",
+       "help": "Ajuto",
        "help-mediawiki": "Ajuto ncopp' 'a MediaWiki",
-       "search": "Truova",
+       "search": "Cerca",
        "search-ignored-headings": " #<!-- lassa sta linea comme sta --> <pre>\n# Testate ca se sarranno gnurate int' 'a ricerca.\n# Cagnamiente a chesto addeventarranno affettive quanno 'a paggena sarrà innecizzata.\n# Vuje putite forzà 'a reinnecezzazzione d' 'a paggena facenno nu cagnamiento abbacante.\n# 'A sintasse è 'a seguente:\n#   * Ogneccosa 'a 'o carattere \"#\" 'nzegna 'a fine d' 'a linea è 'nu cummanno\n#   * Ogne linea chiena è 'o titolo esatto 'a gnurà, case e tutteccose\nRiferimente\nJonte 'e fore\nVide pure\n #</pre> <!-- lassa sta linea comme sta  -->",
-       "searchbutton": "Truova",
+       "searchbutton": "Cerca",
        "go": "Vàje",
-       "searcharticle": "Vàje",
+       "searcharticle": "Vaje",
        "history": "Verziune 'e primma",
        "history_short": "Cronologgia",
        "history_small": "cronologgia",
        "updatedmarker": "cagnamiénte 'e ll'urdema visita d' 'a mia",
-       "printableversion": "Verzione pe' stampa",
+       "printableversion": "Verzione p''a stampa",
        "permalink": "Jonta permanente",
        "print": "Stampà",
        "view": "Vire",
        "view-foreign": "Vide ncopp'a $1",
-       "edit": "Càgna",
+       "edit": "Cagna",
        "edit-local": "Càgna descrizione lucale",
        "create": "Crèa",
        "create-local": "Azzecca descrizione lucale",
        "protect_change": "càgna",
        "unprotect": "Càgna prutezzione",
        "newpage": "Paggena nova",
-       "talkpagelinktext": "Chiàcchiera",
+       "talkpagelinktext": "chiacchiera",
        "specialpage": "Paggena speciàle",
-       "personaltools": "Strumiente perzonale",
-       "talk": "Chiàcchiera",
+       "personaltools": "Strumente perzonale",
+       "talk": "Chiacchiera",
        "views": "Visite",
-       "toolbox": "Strumiente",
+       "toolbox": "Strumente",
        "tool-link-userrights": "Càgna gruppe {{GENDER:$1|utente}}",
        "tool-link-userrights-readonly": "Vire gruppe {{GENDER:$1|utente}}",
        "tool-link-emailuser": "Manna na masciata email a st'{{GENDER:$1|utente}}",
        "viewcount": "Chesta paggena è stata liggiùta {{PLURAL:$1|una vòta|$1 vòte}}.",
        "protectedpage": "Paggena prutetta",
        "jumpto": "Vaje a:",
-       "jumptonavigation": "navigazione",
-       "jumptosearch": "truova",
+       "jumptonavigation": "navigazzione",
+       "jumptosearch": "cerca",
        "view-pool-error": "Ve cercammo scusa, 'e servers hanno troppo carico mo'.\nTroppe utente stanno cercanno 'e veré sta paggena.\nPe' piacere, aspettate nu poco primma 'e turnà a carrecà sta paggena.\n\n$1",
        "generic-pool-error": "Ve cercammo scusa, 'e servers hanno troppo carico mo'.\nTroppe utente stanno cercanno 'e veré sta risorsa.\nPe' piacere, aspettate nu poco primma 'e turnà a carrecà sta risorsa.",
        "pool-timeout": "Tiempo pe' s'aspettà ô blocco",
        "pool-errorunknown": "Errore scanusciuto",
        "pool-servererror": "'O servizio contatore d''e fatiche nun è a disposizióne ($1).",
        "poolcounter-usage-error": "Errore d'uso: $1",
-       "aboutsite": "'Nfrummazione ncòpp'a {{SITENAME}}",
-       "aboutpage": "Project:'Nfrummazione",
+       "aboutsite": "'Nfurmazzione ncòpp''a {{SITENAME}}",
+       "aboutpage": "Project:'Nfurmazzione",
        "copyright": "Cuntenute suggiette a licienza 'e auso $1 se nun fuje ritto atro.",
        "copyrightpage": "{{ns:project}}:Copyrights",
        "currentevents": "Nuvità",
        "currentevents-url": "Project:Novità",
-       "disclaimers": "Avvertimiènte",
-       "disclaimerpage": "Project:Avvertimiènte generale",
+       "disclaimers": "Avvertimiente",
+       "disclaimerpage": "Project:Avvertimiente generale",
        "edithelp": "Guida",
        "helppage-top-gethelp": "Ajùto",
        "mainpage": "Paggena prencepale",
        "mainpage-description": "Paggena prencepale",
        "policy-url": "Project:Policy",
-       "portal": "Porta d’'a commonetà",
-       "portal-url": "Project:Porta d''a commonetà",
-       "privacy": "'Nformazzione ppe a privacy",
-       "privacypage": "Project:'Nfrummazione ncopp'â privacy",
+       "portal": "Porta d''a communetà",
+       "portal-url": "Project:Porta d''a communetà",
+       "privacy": "'Nfurmazzione p''a privacy",
+       "privacypage": "Project:'Nfurmazzione p''a privacy",
        "badaccess": "Nun aie bastante licenzia",
        "badaccess-group0": "Nun tiene 'a licenzia pe ffà l'azione richiesta.",
        "badaccess-groups": "L'azione ch'ê addemmannato 'a pô ffà sulamente ll'utente ca stanno dint'a {{PLURAL:$2|'o gruppo|uno d' 'e gruppe}}: $1.",
        "newmessageslinkplural": "{{PLURAL:$1|na mmasciata nova|999=mmasciate nnove}}",
        "newmessagesdifflinkplural": "{{PLURAL:$1|urdemo cagnamiento|999=urdeme cagnamiente}}",
        "youhavenewmessagesmulti": "Tiene nuove mmasciate $1",
-       "editsection": "càgna",
+       "editsection": "cagna",
        "editold": "càgna",
        "viewsourceold": "vire sorgente",
        "editlink": "càgna",
        "site-atom-feed": "Feed Atom 'e $1",
        "page-rss-feed": "Feed RSS pe' \"$1\"",
        "page-atom-feed": "Feed Atom ppe \"$1\"",
-       "red-link-title": "$1 ('a paggena nun esiste)",
+       "red-link-title": "$1 (sta paggena nun esiste)",
        "sort-descending": "Urdinamento dicriscente",
        "sort-ascending": "Urdinamento criscente",
        "nstab-main": "Articulo",
        "loginlanguagelabel": "Lengua: $1",
        "suspicious-userlogout": "'A richiesta 'e disconnessione d' 'a toja è stata negate pecché pare ca fosse mannata 'a nu navigatóre rutto o nu proxy 'e \"caching\".",
        "createacct-another-realname-tip": "'O nomme overo vuosto è ozzionale.\nSi sciglite 'e nzertà 'o nomme overo, chesto s'ausarrà pe' dà l'utente l'attribuzione d' 'a fatica fatta.",
-       "pt-login": "Tràse",
+       "pt-login": "Trase",
        "pt-login-button": "Tràse",
        "pt-login-continue-button": "Và annanze e tràse",
-       "pt-createaccount": "Crèa nu cunto nuovo",
+       "pt-createaccount": "Crea 'nu cunto nuovo",
        "pt-userlogout": "Jèsce",
        "php-mail-error-unknown": "Errore scanusciuto dint'a funzione PHP mail()",
        "user-mail-no-addy": "Avite cercato 'e mannà na mmasciata e-mail senza indirizzo.",
        "nchanges": "$1 {{PLURAL:$1|cagnamiento|cagnamiente}}",
        "enhancedrc-since-last-visit": "$1 {{PLURAL:$1|'a ll'urdema visita}}",
        "enhancedrc-history": "cronologgia",
-       "recentchanges": "Urdeme nove",
+       "recentchanges": "Urdeme cagnamiente",
        "recentchanges-legend": "Opzione urdeme cagnamiénte",
        "recentchanges-summary": "Ncopp'a chesta paggena song' appresentate ll'urdeme cagnamiente fatte ê cuntenute d\"o sito.",
        "recentchanges-noresult": "Nisciuno cagnamiento dint'o periodo dato ca soddisfà sti criterie.",
        "minoreditletter": "m",
        "newpageletter": "N",
        "boteditletter": "b",
-       "rc-change-size-new": "$1 {{PLURAL:$1|byte|byte}} aropp'ô cagnamiento",
+       "rc-change-size-new": "$1 {{PLURAL:$1|byte}} aropp''o cagnamiento",
        "newsectionsummary": "/* $1 */ sezziona nnova",
        "rc-enhanced-expand": "Fa vede dettaglie",
        "rc-enhanced-hide": "Annascunne dettaglie",
        "recentchanges-page-removed-from-category": "[[:$1]] luvato d' 'a categurìa",
        "recentchanges-page-removed-from-category-bundled": "[[:$1]]  luvate 'e categurìa, [[Special:WhatLinksHere/$1|sta paggena è azzeccata dint'a n'ati paggene]]",
        "autochange-username": "Cagnamiento automateco MediaWiki",
-       "upload": "Carreca file",
+       "upload": "Careca 'na fiùra",
        "uploadbtn": "Carreca file",
        "reuploaddesc": "Torna a 'o modulo pe ffà 'a carreca",
        "upload-tryagain": "Manna 'a descrizione d' 'o file cagnato",
        "sp-contributions-newonly": "Sulamente 'e contribbute ca songo criazione 'e paggene",
        "sp-contributions-hideminor": "Annascunne cagnamiénte piccerille",
        "sp-contributions-submit": "Truova",
-       "whatlinkshere": "Paggene ca cullegano a chesta",
+       "whatlinkshere": "Paggene ca se cullegano a chesta",
        "whatlinkshere-title": "Paggene ca cullegano a $1",
        "whatlinkshere-page": "Paggena:",
        "linkshere": "'E ppaggene ccà abbascio teneno jonte a <strong>$2</strong>.",
        "tooltip-pt-watchlist": "'A lista d' 'e paggene ca state a cuntrullà",
        "tooltip-pt-mycontris": "N'elenco 'e cuntribbute {{GENDER:|vòste}}",
        "tooltip-pt-anoncontribs": "N'elenco 'e cagnamiente fatte 'a st'indirizzo IP",
-       "tooltip-pt-login": "A reggistrazione è cunsigliata",
+       "tooltip-pt-login": "Ve cunsigliamme 'e trasì dint'o cunto vostro, ma nun l'avite a ffà pe' fforza",
        "tooltip-pt-logout": "Jésce (logout)",
-       "tooltip-pt-createaccount": "Pigliateve curaggio e criate n'utente e trasìte; eziamme ca chisto nun s'avesse 'a ffà pe' fforza",
-       "tooltip-ca-talk": "Vide 'e chiacchere rilative a chesta paggena",
+       "tooltip-pt-createaccount": "Ve cunsigliamme 'e ve reggistrà 'nu cunte e trasì, ma nun l'avite a ffà pe' fforza",
+       "tooltip-ca-talk": "Vide 'e chiacchere 'e chesta paggena",
        "tooltip-ca-edit": "Cagna sta paggena",
        "tooltip-ca-addsection": "Cummincia 'na nova sezzione",
        "tooltip-ca-viewsource": "Chista paggena è prutetta, ma può verè 'o codice sorgente",
-       "tooltip-ca-history": "Vversione 'e primma 'e chesta paggena",
+       "tooltip-ca-history": "Verzione 'e primma 'e chesta paggena",
        "tooltip-ca-protect": "Prutegge chesta paggena",
        "tooltip-ca-unprotect": "Càgna 'a prutezzione 'e chesta paggena",
        "tooltip-ca-delete": "Scancèlla chesta paggena",
        "tooltip-ca-move": "Mòve sta paggena",
        "tooltip-ca-watch": "Azzecca sta paggena int' 'a lista 'e paggene cuntrullate vuosta",
        "tooltip-ca-unwatch": "Lèva sta paggena d' 'a lista 'e paggene cuntrullate vuosta",
-       "tooltip-search": "Truova dint'a {{SITENAME}}",
-       "tooltip-search-go": "Vaje â paggena cu stu nomme si esiste",
-       "tooltip-search-fulltext": "Ascià 'o testo indicato dint'e paggene",
+       "tooltip-search": "Cerca dint''a {{SITENAME}}",
+       "tooltip-search-go": "Vaje a 'na paggena cu stu nomme, si ce sta",
+       "tooltip-search-fulltext": "Cerca chistu testo dint''e paggene",
        "tooltip-p-logo": "Visita a paggena prencepale",
        "tooltip-n-mainpage": "Visita a paggena prencepale",
        "tooltip-n-mainpage-description": "Visita a paggena prencepale",
-       "tooltip-n-portal": "Descrizione d' 'o prugietto, che po' ffa, addò truvà 'e ccose",
+       "tooltip-n-portal": "Descrizione d''o prugietto, che putite fà e addò putite truvà 'e ccose",
        "tooltip-n-currentevents": "Ascìa 'e nfurmaziune ncopp' 'e fatte succiesse mo mmo",
-       "tooltip-n-recentchanges": "Ennece dde urdeme cagnamiénte d' 'o sito",
-       "tooltip-n-randompage": "Na paggena qualsiase",
-       "tooltip-n-help": "Paggena 'e ajùto",
-       "tooltip-t-whatlinkshere": "'Na lista 'e tutte e paggene ca song cullegate a chista",
+       "tooltip-n-recentchanges": "Ennece 'e ll'urdeme cagnamiente d''o sito",
+       "tooltip-n-randompage": "Careca 'na paggena qualonca",
+       "tooltip-n-help": "Paggena 'e ajuto",
+       "tooltip-t-whatlinkshere": "Ennece 'e tutte e paggene ca so' cullegate a chesta",
        "tooltip-t-recentchangeslinked": "Urdeme cagnamiénte dde paggene ca cullegano a chesta",
        "tooltip-feed-rss": "RSS feed pe sta pàggena",
        "tooltip-feed-atom": "Atom feed pe sta pàggena",
        "tooltip-t-contributions": "Lista dde contributte fatte 'a {{GENDER:$1|chist'utente}}",
        "tooltip-t-emailuser": "Manna 'nu email a {{GENDER:$1|chist'utente}}",
        "tooltip-t-info": "Cchiù nfurmaziune ncopp'a sta paggena",
-       "tooltip-t-upload": "Carreca file",
-       "tooltip-t-specialpages": "Lista 'e tutte e paggene speciale",
-       "tooltip-t-print": "Vversione pe stampà 'a chesta paggena",
+       "tooltip-t-upload": "Careca cchiù fiùre",
+       "tooltip-t-specialpages": "Lista 'e tutte 'e paggene speciale",
+       "tooltip-t-print": "Verzione p''a stampa 'e chesta paggena",
        "tooltip-t-permalink": "Jonta permanente a chesta vversione dda paggena",
        "tooltip-ca-nstab-main": "Vire 'a paggena 'e contenuto",
        "tooltip-ca-nstab-user": "Vire 'a paggena utente",
        "pageinfo-hidden-categories": "{{PLURAL:$1|Categurìa annascunnuta|Categurìe annascunnute}} ($1)",
        "pageinfo-templates": "Template {{PLURAL:$1|appennuto|appennute}} ($1)",
        "pageinfo-transclusions": "{{PLURAL:$1|Paggena appennuta|Paggene appennute}} ncopp'a ($1)",
-       "pageinfo-toolboxlink": "Nfurmaziune d' 'a paggena",
+       "pageinfo-toolboxlink": "'Nfurmazzione d''a paggena",
        "pageinfo-redirectsto": "Reindirizza a",
        "pageinfo-redirectsto-info": "nfurmaziune",
        "pageinfo-contentpage": "Cuntata comme na paggena 'e cuntenute",
        "feedback-thanks": "Grazie! 'O feedback vuosto s'è mpizzato dint' 'a paggena \"[$2 $1]\".",
        "feedback-thanks-title": "Ve ringraziammo!",
        "feedback-useragent": "Aggente utente:",
-       "searchsuggest-search": "Truova dint'a {{SITENAME}}",
+       "searchsuggest-search": "Cerca dint''a {{SITENAME}}",
        "searchsuggest-containing": "tène...",
        "api-error-badtoken": "Errore interno: 'O token nun è buono.",
        "api-error-emptypage": "'A criazione 'e paggene nuove abbacante nun è permessa.",
index eb628a8..41bccb3 100644 (file)
        "createaccountmail": "ߓߍ߲߬ߛߋ߲߬ߡߊ߬ ߕߊߡߌ߲ߞߊ߲ ߕߎ߬ߡߊ߬ߞߎ߲߬ߡߊ ߟߊߓߊ߯ߙߊ߫ ߞߊ߬ ߓߊ߲߫ ߞߵߊ߬ ߗߋ߫ ߢߎߡߍߙߋ߲߫ ߞߏ߲ߘߏ߫ ߓߟߏߡߊߞߊ߬ߣߍ߲ ߡߊ߬.",
        "createaccountmail-help": "ߊ߬ ߕߍ߫ ߛߐ߲߬ ߠߊߓߊ߯ߙߊ߫ ߟߊ߫߸ ߞߊ߬ ߡߐ߰ ߜߘߍ߫ ߟߊ߫ ߖߊ߬ߕߋ߬ߘߊ ߛߌ߲ߘߌ߫߸ ߣߴߌ ߡߊ߫ ߕߊ߬ߡߌ߲߬ߞߊ߲ ߞߊ߬ߙߊ߲߬.",
        "createacct-realname": "ߕߐ߮ ߓߘߍ (ߛߎߥߊ߲ߘߟߌ)",
-       "createacct-reason": "ß\8a߬ ß\9bß\8aß\93ß\8eß«",
+       "createacct-reason": "ß\8a߬ ß\9eß\8e߲߭",
        "createacct-reason-ph": "ߡߎ߲߬ߠߊ߫ ߌ ߦߋ߫ ߖߊ߬ߕߋ߬ߘߊ߰ ߜߘߍ߫ ߛߌ߲ߘߌ߫ ߟߊ߫",
        "createacct-reason-help": "ߗߋߛߓߍ ߦߌ߬ߘߊ߬ ߖߊ߬ߕߋ߬ߘߊ ߛߌ߲ߘߟߌ ߘߊ߲ߖߐ ߘߐ߫",
        "createacct-submit": "ߖߊ߬ߕߋ߬ߘߊ ߘߏ߫ ߘߊߦߟߍ߬",
        "newarticle": "(ߞߎߘߊ)",
        "newarticletext": "ߌ ߓߘߊ߫ ߛߘߌ߬ߜߋ߲ ߘߏ߫ ߟߊߓߊ߬ߕߏ߬ ߞߐߜߍ ߘߏ߫ ߘߐ߫߸ ߡߍ߲ ߕߴߦߋ߲߬ ߡߎߣߎ߲߬.\nߣߵߌ ߦߴߊ߬ ߝߍ߫ ߞߊ߬ ߞߐߜߍ ߘߏ߫ ߟߊߘߊ߲߫߸ ߛߓߍߟߌ ߘߊߡߌ߬ߣߊ߬ ߘߎ߰ߟߊ߬ߘߐ߫ ߞߏ߲ߘߏ ߘߐ߫ (ߞߊ߬ [$1 ߘߍ߬ߡߍ߲߬ߠߌ߲ ߞߐߜߍ] ߦߋ߫߸ ߖߐ߲߬ߛߊ߬ ߌ ߘߌ߫ ߞߌ߬ߓߊ߬ߙߏ߬ ߖߐ߲ߖߐ߲ ߛߐ߬ߘߐ߲߬). ߣߵߌ ߘߏ߲߬ ߞߍ߫ ߘߊ߫ ߦߊ߲߬ ߝߎ߬ߕߎ߲߬ߕߌ߬ ߓߟߏߡߊ߬߸ ߌ ߟߊ߫ ߛߏ߲߯ߓߊߟߊ߲ <strong>back</strong> ߛߐ߲߬ߞߌ߲߫.",
        "anontalkpagetext": "----\n<em>ߓߊ߬ߘߏ߬ ߞߐߜߍ ߣߌ߲߬ ߦߋ߫ ߟߊߓߊ߯ߙߟߊ߫ ߟߐ߲ߓߊߟߌ ߟߋ߬ ߓߟߏ߫ ߡߍ߲ ߡߊ߫ ߖߊ߬ߕߋ߬ߘߊ߬ ߛߌ߲ߘߌ߫ ߡߎߣߎ߲߬ ߥߟߴߊ߬ ߕߍ߫ ߖߊ߬ߕߋ߬ߘߊ ߏ߬ ߟߊߓߊ߯ߙߊ߫ ߟߊ߫;</em>\nߏ߬ ߞߏߛߐ߲߬ ߊ߲ ߞߊ߫ ߞߊ߲߫ ߞߵߊ߬ ߟߊ߫ ߓߡ (ߓߟߐߟߐ ߡߛߍ߬ߞߍ߬ߡߛߍߞߍ) ߛߊ߲߬ߓߊ߬ߕߐ߮ ߟߊߓߊ߯ߙߴߊ߬ ߡߊߟߐ߲߫ ߞߊߡߊ߬߸ ߟߊߓߊ߯ߙߟߊ߫ ߛߌߦߊߡߊ߲߫ ߓߴߛߋ߫ ߞߊ߬ ߘߍ߬ ߓߡ ߛߊ߲߬ߓߊ߬ߕߐ߮ ߣߌ߲߬ ߢߐ߲߰ ߠߊ߫.\nߣߴߌ ߞߍ߫ ߘߊ߫ ߟߊߓߊ߯ߙߟߊ߫ ߡߊߝߟߌ߬ߣߍ߲߫ ߘߌ߫ ߞߵߊ߬ ߛߏ߬ߓߌ߬ ߞߏ߫ ߌ ߟߊ߫ ߞߊ߲߬ߞߎߡߊ ߟߎ߬ ߕߴߌ ߕߊ߫ ߘߌ߫ ߊ߬ ߘߌ߫ ߟߐ߬ ߌ ߡߊ߬ ߌߞߘߐ߫߸ ߌ ߖߏ߫ ߞߊ߬ [[Special:CreateAccount|ߖߊ߬ߕߋ߬ߘߊ ߘߏ߫ ߘߊߦߟߍ߬]] ߥߟߊ߫ [[Special:UserLogin|ߞߊ߬ ߘߏ߲߬ߕߐ߰ߟߊ߬ߘߏ߲ ߞߍ߫]] ߖߐ߲߬ߛߊ߫ ߟߏ߲ߘߐ߬ ߓߊߛߌ߯ߓߊߟߌߦߊ ߘߌ߫ ߡߟߊ߫ ߟߊߓߊ߯ߙߟߊ߫ ߡߊߟߐ߲ߓߊߟߌ߫ ߜߘߍ ߟߎ߬ ߓߟߏ߫.",
-       "noarticletext": "ß\9bß\93ß\8dß\9fß\8cß« ß\9bß\8cß« ß\95ß\8dß« ß\9eß\90ß\9cß\8d ß£ß\8c߲߭ ß\9eß\8a߲߬ ß\95ß\8b߲߫. ß\8c ß\98ß\8cß« ß\9bß\8bß« ß\9eß\90ß\9cß\8d ß£ß\8c߲߬ \n [[Special:Search/{{PAGENAME}}|search for this page title]] ß\95ß\90ß® ß¢ß\8cߣß\8c߲߫ ß ß\8aß« ß\9eß\90ß\9cß\8d ß\95ß\90ß­ ß\9fß\8e߬ ß\98ß\90ß«߸  \n<span class=\"plainlinks\">[{{fullurl:{{#Special:Log}}|page={{FULLPAGENAMEE}}}} search the related logs],\nor [{{fullurl:{{FULLPAGENAME}}|action=edit}} create this page]</span>.",
+       "noarticletext": "ß\9bß\93ß\8dß\9fß\8cß« ß\9bß\8cß« ß\95ß\8dß« ß\9eß\90ß\9cß\8d ß£ß\8c߲߭ ß\9eß\8a߲߬ ß\95ß\8b߲߬. ß\8c ß\98ß\8cß« ß\9bß\8bß« ß\9eß\90ß\9cß\8d ß£ß\8c߲߬.\n[[Special:Search/{{PAGENAME}}|search for this page title]] ß\95ß\90ß® ß¢ß\8cߣß\8c߲߫ ß ß\8aß« ß\9eß\90ß\9cß\8d ß\95ß\90ß­ ß\9fß\8e߬ ß¢ß\8aß\9dß\8d߬߸  \n<span class=\"plainlinks\">[{{fullurl:{{#Special:Log}}|page={{FULLPAGENAMEE}}}} search the related logs],\nor [{{fullurl:{{FULLPAGENAME}}|action=edit}} create this page]</span>.",
        "noarticletext-nopermission": "ߛߓߍߟߌ߫ ߛߌ߫ ߕߍ߫ ߞߐߜߍ ߣߌ߲߭ ߞߊ߲߬ ߕߋ߲߫.\nߌ ߘߌ߫ ߛߋ߫ [[Special:Search/{{PAGENAME}}|search for this page title]] ߢߌߣߌ߲߫ ߠߊ߫ ߞߐߜߍ ߕߐ߭ ߟߎ߬ ߘߐ߫߸ ߥߟߊ߫ <span class=\"plainlinks\">[{{fullurl:{{#Special:Log}}|page={{FULLPAGENAMEE}}}} search the related logs]</span> ߞߏ߬ߣߌ߲߬ ߘߌ߬ߢߍ߬ ߞߍߣߍ߲߫ ߕߴߌ ߡߊ߬ ߞߐߜߍ߫ ߣߌ߲߬ ߠߊߞߊ߭ ߘߐ߫.",
        "userpage-userdoesnotexist": "ߖߊ߬ߕߋ߬ߘߊ߬ ߟߊߓߊ߯ߙߕߊ \"$1\" ߛߌ߲ߘߌߣߍ߲߫ ߕߍ߫. \nߝߛߍ߬ߝߛߍ߬ߟߌ ߞߍ߫߸ ߣߴߌ ߦߴߊ߬ ߝߍ߬ ߞߊ߬ ߞߐߜߍ ߣߌ߲߬ ߛߌ߲ߘߌ߫/ߡߊߦߟߍ߬ߡߊ߲߫.",
        "userpage-userdoesnotexist-view": "ߟߊ߬ߓߊ߰ߙߊ߬ ߖߊߕߋߘߊ \"$1\" ߟߊߞߎ߲߬ߘߎ߬ߣߍ߲߫ ߕߍ߫.",
        "recentchanges-label-unpatrolled": "ߡߊ߬ߦߟߍ߬ߡߊ߲߬ߠߌ߲ ߣߌ߲߬ ߡߊ߫ ߓߍ߬ߙߍ߲߬ߓߍ߬ߙߍ߲߬ ߡߎߣߎ߲߬",
        "recentchanges-label-plusminus": "ߞߐߜߍ ߢߊ߲ߞߊ߲ ߓߘߊ߫ ߡߊߦߟߍ߬ߡߊ߲߫ ߞߵߊ߬ ߝߌ߬ߘߊ߲ ߦߙߌߞߊ ߣߌ߲߬ ߘߌ߫",
        "recentchanges-legend-heading": "<strong>ߡߊ߬ߛߙߋ:</strong>",
-       "recentchanges-legend-newpage": "{{int:recentchanges-label-newpage}} (ߣß\8c߲߬ ß\9dߣß\8aß« ß¦ß\8bß« \n[[Special:NewPages|list of new pages]])",
+       "recentchanges-legend-newpage": "{{int:recentchanges-label-newpage}} (ߣß\8c߲߬ ß\9dߣß\8aß« ß\93ߴߦß\8b߲߬ [[Special:NewPages|list of new pages]])",
        "recentchanges-submit": "ߊ߬ ߦߌ߬ߘߊ߬",
        "rcfilters-tag-remove": "$1 ߛߋ߲߬ߓߐ߫",
        "rcfilters-legend-heading": "<strong>ߟߊ߬ߘߛߏ߬ߟߌ ߛߙߍߘߍ</strong>",
index afbfd94..6b141f9 100644 (file)
        "perfcached": "Like {{msg-mw|perfcachedts}} but used when we do not know how long ago page was cached (unlikely to happen).\n\nParameters:\n* $1 - the max result cut off ($wgQueryCacheLimit)",
        "perfcachedts": "Used on pages that list page lists for which the displayed data is cached. Parameters:\n* $1 - a time stamp (date and time combined)\n* $2 - a date (optional)\n* $3 - a time (optional)\n* $4 - the cut off limit for cached results ($wgQueryCacheLimit). If there are more then this many results for the query, only the first $4 of those will be listed on the page. Usually $4 is about 1000.",
        "querypage-no-updates": "Text on some special pages, e.g. [[Special:FewestRevisions]].",
+       "querypage-updates-periodical": "Text on some special pages which are configurated with a periodical run of a maintenance script.\n\nSee also {{msg-mw|querypage-no-updates}}.",
        "viewsource": "The text displayed in place of the {{msg-mw|Edit}} tab when the user has no permission to edit the page.\n\nSee also:\n* {{msg-mw|Viewsource}}\n* {{msg-mw|Accesskey-ca-viewsource}}\n* {{msg-mw|Tooltip-ca-viewsource}}\n{{Identical|View source}}",
        "viewsource-title": "Page title shown when trying to edit a protected page. Parameters:\n* $1 - the name of the page",
        "actionthrottled": "This is the title of an error page. Read it in combination with {{msg-mw|actionthrottledtext}}.",
diff --git a/maintenance/archives/patch-drop-archive-ar_usertext_timestamp.sql b/maintenance/archives/patch-drop-archive-ar_usertext_timestamp.sql
new file mode 100644 (file)
index 0000000..158d9ae
--- /dev/null
@@ -0,0 +1,7 @@
+-- T233221: The index on `archive` variously known as `ar_usertext_timestamp`
+-- and `usertext_timestamp` has a long and sordid history. We're dropping the
+-- `ar_user_text` column entirely now (see patch-drop-user-fields.sql), but
+-- this index needs special care thanks to said history.
+
+-- Do not use the /*i*/ thing here!
+DROP INDEX ar_usertext_timestamp ON /*_*/archive;
diff --git a/maintenance/archives/patch-drop-archive-usertext_timestamp.sql b/maintenance/archives/patch-drop-archive-usertext_timestamp.sql
new file mode 100644 (file)
index 0000000..f409e97
--- /dev/null
@@ -0,0 +1,7 @@
+-- T233221: The index on `archive` variously known as `ar_usertext_timestamp`
+-- and `usertext_timestamp` has a long and sordid history. We're dropping the
+-- `ar_user_text` column entirely now (see patch-drop-user-fields.sql), but
+-- this index needs special care thanks to said history.
+
+-- Do not use the /*i*/ thing here!
+DROP INDEX usertext_timestamp ON /*_*/archive;
index 7faa593..1d0b057 100644 (file)
@@ -4,7 +4,6 @@
 -- T188327. Drop old xx_user and xx_user_text fields, and defaults from xx_actor fields.
 
 ALTER TABLE /*_*/archive
-  DROP INDEX /*i*/ar_usertext_timestamp,
   DROP COLUMN ar_user,
   DROP COLUMN ar_user_text,
   ALTER COLUMN ar_actor DROP DEFAULT;
diff --git a/maintenance/archives/patch-rename-mysql-user_newtalk-indexes.sql b/maintenance/archives/patch-rename-mysql-user_newtalk-indexes.sql
new file mode 100644 (file)
index 0000000..3177b4d
--- /dev/null
@@ -0,0 +1,10 @@
+-- T233240: The indexes on `user_newtalk` may be named `un_user_id`/`un_user_ip`
+-- or `user_id`/`user_ip`. At least it won't be both or mixed. Rename them to
+-- the former.
+
+-- Do not use the /*i*/ hack here!
+ALTER TABLE /*_*/user_newtalk
+       DROP INDEX user_id,
+       DROP INDEX user_ip,
+       ADD INDEX un_user_id (user_id),
+       ADD INDEX un_user_ip (user_ip);
index 9f20e67..4c75de8 100644 (file)
@@ -63,10 +63,10 @@ class RecompressTracked {
        public $numProcs = 1;
        public $numBatches = 0;
        public $pageBlobClass, $orphanBlobClass;
-       public $replicaPipes, $replicaProcs, $prevReplicaId;
+       public $childPipes, $childProcs, $prevChildId;
        public $copyOnly = false;
        public $isChild = false;
-       public $replicaId = false;
+       public $childId = false;
        public $noCount = false;
        public $debugLog, $infoLog, $criticalLog;
        /** @var ExternalStoreDB */
@@ -74,7 +74,7 @@ class RecompressTracked {
 
        private static $optionsWithArgs = [
                'procs',
-               'replica-id',
+               'child-id',
                'debug-log',
                'info-log',
                'critical-log'
@@ -85,7 +85,7 @@ class RecompressTracked {
                'procs' => 'numProcs',
                'copy-only' => 'copyOnly',
                'child' => 'isChild',
-               'replica-id' => 'replicaId',
+               'child-id' => 'childId',
                'debug-log' => 'debugLog',
                'info-log' => 'infoLog',
                'critical-log' => 'criticalLog',
@@ -114,8 +114,8 @@ class RecompressTracked {
                $this->store = $esFactory->getStore( 'DB' );
                if ( !$this->isChild ) {
                        $GLOBALS['wgDebugLogPrefix'] = "RCT M: ";
-               } elseif ( $this->replicaId !== false ) {
-                       $GLOBALS['wgDebugLogPrefix'] = "RCT {$this->replicaId}: ";
+               } elseif ( $this->childId !== false ) {
+                       $GLOBALS['wgDebugLogPrefix'] = "RCT {$this->childId}: ";
                }
                $this->pageBlobClass = function_exists( 'xdiff_string_bdiff' ) ?
                        DiffHistoryBlob::class : ConcatenatedGzipHistoryBlob::class;
@@ -145,8 +145,8 @@ class RecompressTracked {
 
        function logToFile( $msg, $file ) {
                $header = '[' . date( 'd\TH:i:s' ) . '] ' . wfHostname() . ' ' . posix_getpid();
-               if ( $this->replicaId !== false ) {
-                       $header .= "({$this->replicaId})";
+               if ( $this->childId !== false ) {
+                       $header .= "({$this->childId})";
                }
                $header .= ' ' . WikiMap::getCurrentWikiDbDomain()->getId();
                LegacyLogger::emit( sprintf( "%-50s %s\n", $header, $msg ), $file );
@@ -184,10 +184,10 @@ class RecompressTracked {
                }
 
                $this->syncDBs();
-               $this->startReplicaProcs();
+               $this->startChildProcs();
                $this->doAllPages();
                $this->doAllOrphans();
-               $this->killReplicaProcs();
+               $this->killChildProcs();
        }
 
        /**
@@ -217,12 +217,12 @@ class RecompressTracked {
         * This necessary because text recompression is slow: loading, compressing and
         * writing are all slow.
         */
-       function startReplicaProcs() {
+       function startChildProcs() {
                $wiki = WikiMap::getWikiIdFromDbDomain( WikiMap::getCurrentWikiDbDomain() );
 
                $cmd = 'php ' . Shell::escape( __FILE__ );
                foreach ( self::$cmdLineOptionMap as $cmdOption => $classOption ) {
-                       if ( $cmdOption == 'replica-id' ) {
+                       if ( $cmdOption == 'child-id' ) {
                                continue;
                        } elseif ( in_array( $cmdOption, self::$optionsWithArgs ) && isset( $this->$classOption ) ) {
                                $cmd .= " --$cmdOption " . Shell::escape( $this->$classOption );
@@ -234,7 +234,7 @@ class RecompressTracked {
                        ' --wiki ' . Shell::escape( $wiki ) .
                        ' ' . Shell::escape( ...$this->destClusters );
 
-               $this->replicaPipes = $this->replicaProcs = [];
+               $this->childPipes = $this->childProcs = [];
                for ( $i = 0; $i < $this->numProcs; $i++ ) {
                        $pipes = [];
                        $spec = [
@@ -243,28 +243,28 @@ class RecompressTracked {
                                [ 'file', 'php://stderr', 'w' ]
                        ];
                        Wikimedia\suppressWarnings();
-                       $proc = proc_open( "$cmd --replica-id $i", $spec, $pipes );
+                       $proc = proc_open( "$cmd --child-id $i", $spec, $pipes );
                        Wikimedia\restoreWarnings();
                        if ( !$proc ) {
-                               $this->critical( "Error opening replica DB process: $cmd" );
+                               $this->critical( "Error opening child process: $cmd" );
                                exit( 1 );
                        }
-                       $this->replicaProcs[$i] = $proc;
-                       $this->replicaPipes[$i] = $pipes[0];
+                       $this->childProcs[$i] = $proc;
+                       $this->childPipes[$i] = $pipes[0];
                }
-               $this->prevReplicaId = -1;
+               $this->prevChildId = -1;
        }
 
        /**
         * Gracefully terminate the child processes
         */
-       function killReplicaProcs() {
-               $this->info( "Waiting for replica DB processes to finish..." );
+       function killChildProcs() {
+               $this->info( "Waiting for child processes to finish..." );
                for ( $i = 0; $i < $this->numProcs; $i++ ) {
-                       $this->dispatchToReplica( $i, 'quit' );
+                       $this->dispatchToChild( $i, 'quit' );
                }
                for ( $i = 0; $i < $this->numProcs; $i++ ) {
-                       $status = proc_close( $this->replicaProcs[$i] );
+                       $status = proc_close( $this->childProcs[$i] );
                        if ( $status ) {
                                $this->critical( "Warning: child #$i exited with status $status" );
                        }
@@ -273,24 +273,24 @@ class RecompressTracked {
        }
 
        /**
-        * Dispatch a command to the next available replica DB.
-        * This may block until a replica DB finishes its work and becomes available.
+        * Dispatch a command to the next available child process.
+        * This may block until a child process finishes its work and becomes available.
         * @param array|string ...$args
         */
        function dispatch( ...$args ) {
-               $pipes = $this->replicaPipes;
+               $pipes = $this->childPipes;
                $x = [];
                $y = [];
                $numPipes = stream_select( $x, $pipes, $y, 3600 );
                if ( !$numPipes ) {
-                       $this->critical( "Error waiting to write to replica DBs. Aborting" );
+                       $this->critical( "Error waiting to write to child process. Aborting" );
                        exit( 1 );
                }
                for ( $i = 0; $i < $this->numProcs; $i++ ) {
-                       $replicaId = ( $i + $this->prevReplicaId + 1 ) % $this->numProcs;
-                       if ( isset( $pipes[$replicaId] ) ) {
-                               $this->prevReplicaId = $replicaId;
-                               $this->dispatchToReplica( $replicaId, $args );
+                       $childId = ( $i + $this->prevChildId + 1 ) % $this->numProcs;
+                       if ( isset( $pipes[$childId] ) ) {
+                               $this->prevChildId = $childId;
+                               $this->dispatchToChild( $childId, $args );
 
                                return;
                        }
@@ -300,14 +300,14 @@ class RecompressTracked {
        }
 
        /**
-        * Dispatch a command to a specified replica DB
-        * @param int $replicaId
+        * Dispatch a command to a specified child process
+        * @param int $childId
         * @param array|string $args
         */
-       function dispatchToReplica( $replicaId, $args ) {
+       function dispatchToChild( $childId, $args ) {
                $args = (array)$args;
                $cmd = implode( ' ', $args );
-               fwrite( $this->replicaPipes[$replicaId], "$cmd\n" );
+               fwrite( $this->childPipes[$childId], "$cmd\n" );
        }
 
        /**
index 5d756e8..7e57f67 100644 (file)
@@ -42,12 +42,13 @@ class UpdateSpecialPages extends Maintenance {
        }
 
        public function execute() {
-               global $wgQueryCacheLimit, $wgDisableQueryPageUpdate;
+               global $wgQueryCacheLimit;
 
                $dbw = $this->getDB( DB_MASTER );
 
                $this->doSpecialPageCacheUpdates( $dbw );
 
+               $disabledQueryPages = QueryPage::getDisabledQueryPages( $this->getConfig() );
                foreach ( QueryPage::getPages() as $page ) {
                        list( , $special ) = $page;
                        $limit = $page[2] ?? null;
@@ -59,7 +60,7 @@ class UpdateSpecialPages extends Maintenance {
                        }
 
                        if ( !$this->hasOption( 'override' )
-                               && $wgDisableQueryPageUpdate && in_array( $special, $wgDisableQueryPageUpdate )
+                               && isset( $disabledQueryPages[$special] )
                        ) {
                                $this->output( sprintf( "%-30s [QueryPage] disabled\n", $special ) );
                                continue;
index 4040ffc..6bf219d 100644 (file)
@@ -2076,8 +2076,10 @@ abstract class RevisionStoreDbTestBase extends MediaWikiTestCase {
                /** @var Revision $rev1 */
                $rev1 = $editStatus->getValue()['revision'];
 
-               $this->setExpectedException( InvalidArgumentException::class );
-               MediaWikiServices::getInstance()->getRevisionStore()
+               $status = MediaWikiServices::getInstance()->getRevisionStore()
                        ->newRevisionsFromBatch( [ $this->revisionToRow( $rev1 ), $this->revisionToRow( $rev1 ) ] );
+
+               $this->assertFalse( $status->isGood() );
+               $this->assertTrue( $status->hasMessage( 'internalerror' ) );
        }
 }
index 7c4c9bf..72ac567 100644 (file)
@@ -128,6 +128,32 @@ class WANObjectCacheTest extends PHPUnit\Framework\TestCase {
                $this->assertFalse( $this->cache->get( $key ), "Stale set() value ignored" );
        }
 
+       /**
+        * @covers WANObjectCache::getWithSetCallback
+        */
+       public function testProcessCacheTTL() {
+               $cache = $this->cache;
+               $mockWallClock = 1549343530.2053;
+               $cache->setMockTime( $mockWallClock );
+
+               $key = "mykey-" . wfRandomString();
+
+               $hits = 0;
+               $callback = function ( $oldValue, &$ttl, &$setOpts ) use ( &$hits ) {
+                       ++$hits;
+                       return 42;
+               };
+
+               $cache->getWithSetCallback( $key, 100, $callback, [ 'pcTTL' => 5 ] );
+               $cache->delete( $key, $cache::HOLDOFF_NONE ); // clear persistent cache
+               $cache->getWithSetCallback( $key, 100, $callback, [ 'pcTTL' => 5 ] );
+               $this->assertEquals( 1, $hits, "Value process cached" );
+
+               $mockWallClock += 6;
+               $cache->getWithSetCallback( $key, 100, $callback, [ 'pcTTL' => 5 ] );
+               $this->assertEquals( 2, $hits, "Value expired in process cache" );
+       }
+
        /**
         * @covers WANObjectCache::getWithSetCallback
         */