Merge "Use json extension for .stylelintrc"
authorjenkins-bot <jenkins-bot@gerrit.wikimedia.org>
Fri, 18 Aug 2017 18:06:57 +0000 (18:06 +0000)
committerGerrit Code Review <gerrit@wikimedia.org>
Fri, 18 Aug 2017 18:06:57 +0000 (18:06 +0000)
64 files changed:
includes/db/MWLBFactory.php
includes/installer/i18n/fa.json
includes/installer/i18n/ko.json
includes/jobqueue/JobQueueDB.php
includes/jobqueue/jobs/RefreshLinksJob.php
includes/libs/rdbms/database/DBConnRef.php
includes/libs/rdbms/database/DatabaseMysqlBase.php
includes/libs/rdbms/lbfactory/ILBFactory.php
includes/libs/rdbms/lbfactory/LBFactory.php
includes/libs/rdbms/loadbalancer/ILoadBalancer.php
includes/libs/rdbms/loadbalancer/LoadBalancer.php
includes/libs/rdbms/loadmonitor/ILoadMonitor.php
includes/libs/rdbms/loadmonitor/LoadMonitor.php
includes/libs/rdbms/loadmonitor/LoadMonitorMySQL.php
includes/libs/rdbms/loadmonitor/LoadMonitorNull.php
includes/objectcache/SqlBagOStuff.php
includes/skins/SkinTemplate.php
includes/specials/SpecialNewpages.php
languages/i18n/af.json
languages/i18n/ar.json
languages/i18n/ast.json
languages/i18n/ba.json
languages/i18n/be-tarask.json
languages/i18n/bg.json
languages/i18n/bn.json
languages/i18n/ca.json
languages/i18n/ckb.json
languages/i18n/cs.json
languages/i18n/cy.json
languages/i18n/de.json
languages/i18n/en.json
languages/i18n/et.json
languages/i18n/fa.json
languages/i18n/fr.json
languages/i18n/frr.json
languages/i18n/gl.json
languages/i18n/got.json
languages/i18n/gu.json
languages/i18n/he.json
languages/i18n/hi.json
languages/i18n/ia.json
languages/i18n/it.json
languages/i18n/kab.json
languages/i18n/ko.json
languages/i18n/lki.json
languages/i18n/lv.json
languages/i18n/mk.json
languages/i18n/nb.json
languages/i18n/nl.json
languages/i18n/pl.json
languages/i18n/pt-br.json
languages/i18n/pt.json
languages/i18n/qqq.json
languages/i18n/ru.json
languages/i18n/shi.json
languages/i18n/skr-arab.json
languages/i18n/sl.json
languages/i18n/sv.json
languages/i18n/uk.json
languages/i18n/zh-hans.json
languages/i18n/zh-hant.json
resources/src/mediawiki.rcfilters/dm/mw.rcfilters.dm.FilterGroup.js
resources/src/mediawiki/page/watch.js
tests/phpunit/includes/db/LoadBalancerTest.php [new file with mode: 0644]

index 464a918..5196ac2 100644 (file)
@@ -149,7 +149,7 @@ abstract class MWLBFactory {
                }
                $cCache = ObjectCache::getLocalClusterInstance();
                if ( $cCache->getQoS( $cCache::ATTR_EMULATION ) > $cCache::QOS_EMULATION_SQL ) {
-                       $lbConf['memCache'] = $cCache;
+                       $lbConf['memStash'] = $cCache;
                }
                $wCache = MediaWikiServices::getInstance()->getMainWANObjectCache();
                if ( $wCache->getQoS( $wCache::ATTR_EMULATION ) > $wCache::QOS_EMULATION_SQL ) {
index b23fd6c..97a09a3 100644 (file)
        "config-db-account-oracle-warn": "برای نصب برنامهٔ اوراکل به عنوان پایگاه اطلاعاتی در بخش گذشته،سه سناریو پشتیبانی شده است:\nاگر مایل به ایجاد حساب پایگاه اطلاعاتی به عنوان بخشی از روند نصب هستید، لطفاً یک حساب با نقش اس‌وای‌اس‌دی‌بی‌ای به عنوان حساب پایگاه اطلاعاتی برای نصب تهیه کنید و اعتبارنامه‌های مطلوبی را برای حساب دردسترس شبکه تعیین کنید، به عبارتی دیگر یا می‌توانید حساب دردسترس شبکه را به طور دستی ایجاد کنید و تنها آن حساب را تهیه کنید (اگر مستلزم مجوزهایی برای ایجاد موضوعات طرح کلی باشد) یا دو حساب دیگر تهیه کنید،یکی با ایجاد مزایا و یک حساب محدود برای دسترسی شبکه.\nمتنی برای ایجاد یک حساب با مزایای لازم بنویسید که می‌تواند در فهرست\"نگهداری/برنامهٔ اوراکل\" این نصب یافت شود. به یاد داشته باشید که استفاده از یک حساب محدود،همهٔ قابلیت‌های نگهداری با حساب پیش‌فرض را غیرفعال خواهد کرد.",
        "config-db-install-account": "حساب کاربری برای نصب",
        "config-db-username": "نام کاربری پایگاه اطلاعات:",
-       "config-db-password": "گذرواژه پایگاه داده‌ها:",
+       "config-db-password": "گذرواژه پایگاه‌های داده:",
        "config-db-install-username": "نام کاربری را وارد کنید که برای اتصال به پایگاه اطلاعاتی در طول روند نصب استفاده خواهد‌شد.\nاین نام کاربری حساب مدیاویکی نیست; نام کاربری برای پایگاه اطلاعاتی شما است.",
        "config-db-install-password": "رمز عبوری را وارد کنید که برای اتصال به پایگاه اطلاعاتی در طول روند نصب استفاده خواهد‌شد.\nاین رمز عبور برای حساب مدیاویکی نیست;رمز عبور برای پایگاه اطلاعاتی شما است.",
        "config-db-install-help": "نام کاربری و رمز عبوری را وارد کنید که برای اتصال به پایگاه اطلاعاتی در طول روند نصب استفاده خواهد‌ٰشد.",
index ee01751..66f095a 100644 (file)
        "config-help-tooltip": "확장하려면 클릭",
        "config-nofile": "\"$1\" 파일을 찾을 수 없습니다. 이미 삭제되었나요?",
        "config-extension-link": "당신의 위키가 [https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:Extensions 확장 기능]을 지원한다는 것을 알고 계십니까?\n\n[https://www.mediawiki.org/wiki/Special:MyLanguage/Category:Extensions_by_category 분류별 확장 기능]을 찾아보실 수 있습니다.",
+       "config-skins-screenshots": "$1 (스크린샷: $2)",
        "config-screenshot": "스크린샷",
        "mainpagetext": "<strong>미디어위키가 설치되었습니다.</strong>",
        "mainpagedocfooter": "[https://www.mediawiki.org/wiki/Special:MyLanguage/Help:Contents 이곳]에서 위키 소프트웨어에 대한 정보를 얻을 수 있습니다.\n\n== 시작하기 ==\n\n* [https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:Configuration_settings 설정하기 목록]\n* [https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:FAQ 미디어위키 FAQ]\n* [https://lists.wikimedia.org/mailman/listinfo/mediawiki-announce 미디어위키 릴리스 메일링 리스트]\n* [https://www.mediawiki.org/wiki/Special:MyLanguage/Localisation#Translation_resources 내 언어로 미디어위키 지역화]\n* [https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:Combating_spam 당신의 위키에서 스팸에 대처하는 법을 배우세요]"
index b7cc133..b5f331b 100644 (file)
@@ -184,15 +184,22 @@ class JobQueueDB extends JobQueue {
         * @return void
         */
        protected function doBatchPush( array $jobs, $flags ) {
-               DeferredUpdates::addUpdate(
-                       new AutoCommitUpdate(
-                               $this->getMasterDB(),
-                               __METHOD__,
-                               function ( IDatabase $dbw, $fname ) use ( $jobs, $flags ) {
-                                       $this->doBatchPushInternal( $dbw, $jobs, $flags, $fname );
-                               }
-                       ),
-                       DeferredUpdates::PRESEND
+               $dbw = $this->getMasterDB();
+               // In general, there will be two cases here:
+               // a) sqlite; DB connection is probably a regular round-aware handle.
+               // If the connection is busy with a transaction, then defer the job writes
+               // until right before the main round commit step. Any errors that bubble
+               // up will rollback the main commit round.
+               // b) mysql/postgres; DB connection is generally a separate CONN_TRX_AUTO handle.
+               // No transaction is active nor will be started by writes, so enqueue the jobs
+               // now so that any errors will show up immediately as the interface expects. Any
+               // errors that bubble up will rollback the main commit round.
+               $fname = __METHOD__;
+               $dbw->onTransactionPreCommitOrIdle(
+                       function () use ( $dbw, $jobs, $flags, $fname ) {
+                               $this->doBatchPushInternal( $dbw, $jobs, $flags, $fname );
+                       },
+                       $fname
                );
        }
 
@@ -771,7 +778,12 @@ class JobQueueDB extends JobQueue {
                        ? $lbFactory->getExternalLB( $this->cluster )
                        : $lbFactory->getMainLB( $this->wiki );
 
-               return $lb->getConnectionRef( $index, [], $this->wiki );
+               return ( $lb->getServerType( $lb->getWriterIndex() ) !== 'sqlite' )
+                       // Keep a separate connection to avoid contention and deadlocks;
+                       // However, SQLite has the opposite behavior due to DB-level locking.
+                       ? $lb->getConnectionRef( $index, [], $this->wiki, $lb::CONN_TRX_AUTO )
+                       // Jobs insertion will be defered until the PRESEND stage to reduce contention.
+                       : $lb->getConnectionRef( $index, [], $this->wiki );
        }
 
        /**
index 02bb829..0c84a13 100644 (file)
@@ -279,6 +279,10 @@ class RefreshLinksJob extends Job {
 
                InfoAction::invalidateCache( $title );
 
+               // Commit any writes here in case this method is called in a loop.
+               // In that case, the scoped lock will fail to be acquired.
+               $lbFactory->commitAndWaitForReplication( __METHOD__, $ticket );
+
                return true;
        }
 
index eb0e954..ef2953e 100644 (file)
@@ -23,16 +23,17 @@ class DBConnRef implements IDatabase {
        const FLD_INDEX = 0;
        const FLD_GROUP = 1;
        const FLD_DOMAIN = 2;
+       const FLD_FLAGS = 3;
 
        /**
         * @param ILoadBalancer $lb Connection manager for $conn
-        * @param Database|array $conn New connection handle or (server index, query groups, domain)
+        * @param Database|array $conn Database handle or (server index, query groups, domain, flags)
         */
        public function __construct( ILoadBalancer $lb, $conn ) {
                $this->lb = $lb;
                if ( $conn instanceof Database ) {
                        $this->conn = $conn; // live handle
-               } elseif ( count( $conn ) >= 3 && $conn[self::FLD_DOMAIN] !== false ) {
+               } elseif ( count( $conn ) >= 4 && $conn[self::FLD_DOMAIN] !== false ) {
                        $this->params = $conn;
                } else {
                        throw new InvalidArgumentException( "Missing lazy connection arguments." );
@@ -41,8 +42,8 @@ class DBConnRef implements IDatabase {
 
        function __call( $name, array $arguments ) {
                if ( $this->conn === null ) {
-                       list( $db, $groups, $wiki ) = $this->params;
-                       $this->conn = $this->lb->getConnection( $db, $groups, $wiki );
+                       list( $db, $groups, $wiki, $flags ) = $this->params;
+                       $this->conn = $this->lb->getConnection( $db, $groups, $wiki, $flags );
                }
 
                return call_user_func_array( [ $this->conn, $name ], $arguments );
index 991e0c6..692ddb7 100644 (file)
@@ -778,6 +778,8 @@ abstract class DatabaseMysqlBase extends Database {
         * @see https://www.percona.com/doc/percona-toolkit/2.1/pt-heartbeat.html
         */
        protected function getHeartbeatData( array $conds ) {
+               // Query time and trip time are not counted
+               $nowUnix = microtime( true );
                // Do not bother starting implicit transactions here
                $this->clearFlag( self::DBO_TRX, self::REMEMBER_PRIOR );
                try {
@@ -793,7 +795,7 @@ abstract class DatabaseMysqlBase extends Database {
                        $this->restoreFlags();
                }
 
-               return [ $row ? $row->ts : null, microtime( true ) ];
+               return [ $row ? $row->ts : null, $nowUnix ];
        }
 
        protected function getApproximateLagStatus() {
index 117df68..ff6635d 100644 (file)
@@ -44,7 +44,7 @@ interface ILBFactory {
         *  - localDomain: A DatabaseDomain or domain ID string.
         *  - readOnlyReason : Reason the master DB is read-only if so [optional]
         *  - srvCache : BagOStuff object for server cache [optional]
-        *  - memCache : BagOStuff object for cluster memory cache [optional]
+        *  - memStash : BagOStuff object for cross-datacenter memory storage [optional]
         *  - wanCache : WANObjectCache object [optional]
         *  - hostname : The name of the current server [optional]
         *  - cliMode: Whether the execution context is a CLI script. [optional]
index 919f103..c891fb6 100644 (file)
@@ -55,7 +55,7 @@ abstract class LBFactory implements ILBFactory {
        /** @var BagOStuff */
        protected $srvCache;
        /** @var BagOStuff */
-       protected $memCache;
+       protected $memStash;
        /** @var WANObjectCache */
        protected $wanCache;
 
@@ -93,7 +93,7 @@ abstract class LBFactory implements ILBFactory {
                }
 
                $this->srvCache = isset( $conf['srvCache'] ) ? $conf['srvCache'] : new EmptyBagOStuff();
-               $this->memCache = isset( $conf['memCache'] ) ? $conf['memCache'] : new EmptyBagOStuff();
+               $this->memStash = isset( $conf['memStash'] ) ? $conf['memStash'] : new EmptyBagOStuff();
                $this->wanCache = isset( $conf['wanCache'] )
                        ? $conf['wanCache']
                        : WANObjectCache::newEmpty();
@@ -435,7 +435,7 @@ abstract class LBFactory implements ILBFactory {
                }
 
                $this->chronProt = new ChronologyProtector(
-                       $this->memCache,
+                       $this->memStash,
                        [
                                'ip' => $this->requestInfo['IPAddress'],
                                'agent' => $this->requestInfo['UserAgent'],
index fc50961..22a5805 100644 (file)
@@ -76,14 +76,17 @@ use InvalidArgumentException;
  * @ingroup Database
  */
 interface ILoadBalancer {
-       /** @var integer Request a replica DB connection */
+       /** @var int Request a replica DB connection */
        const DB_REPLICA = -1;
-       /** @var integer Request a master DB connection */
+       /** @var int Request a master DB connection */
        const DB_MASTER = -2;
 
        /** @var string Domain specifier when no specific database needs to be selected */
        const DOMAIN_ANY = '';
 
+       /** @var int DB handle should have DBO_TRX disabled and the caller will leave it as such */
+       const CONN_TRX_AUTO = 1;
+
        /**
         * Construct a manager of IDatabase connection objects
         *
@@ -94,7 +97,6 @@ interface ILoadBalancer {
         *  - readOnlyReason : Reason the master DB is read-only if so [optional]
         *  - waitTimeout : Maximum time to wait for replicas for consistency [optional]
         *  - srvCache : BagOStuff object for server cache [optional]
-        *  - memCache : BagOStuff object for cluster memory cache [optional]
         *  - wanCache : WANObjectCache object [optional]
         *  - chronologyProtector: ChronologyProtector object [optional]
         *  - hostname : The name of the current server [optional]
@@ -169,14 +171,17 @@ interface ILoadBalancer {
        /**
         * Get a connection by index
         *
+        * Avoid using CONN_TRX_AUTO with sqlite (e.g. check getServerType() first)
+        *
         * @param int $i Server index or DB_MASTER/DB_REPLICA
         * @param array|string|bool $groups Query group(s), or false for the generic reader
         * @param string|bool $domain Domain ID, or false for the current domain
+        * @param int $flags Bitfield of CONN_* class constants
         *
         * @throws DBError
         * @return Database
         */
-       public function getConnection( $i, $groups = [], $domain = false );
+       public function getConnection( $i, $groups = [], $domain = false, $flags = 0 );
 
        /**
         * Mark a foreign connection as being available for reuse under a different DB domain
@@ -194,42 +199,51 @@ interface ILoadBalancer {
         *
         * The handle's methods simply wrap those of a Database handle
         *
+        * Avoid using CONN_TRX_AUTO with sqlite (e.g. check getServerType() first)
+        *
         * @see ILoadBalancer::getConnection() for parameter information
         *
         * @param int $i Server index or DB_MASTER/DB_REPLICA
         * @param array|string|bool $groups Query group(s), or false for the generic reader
         * @param string|bool $domain Domain ID, or false for the current domain
+        * @param int $flags Bitfield of CONN_* class constants (e.g. CONN_TRX_AUTO)
         * @return DBConnRef
         */
-       public function getConnectionRef( $i, $groups = [], $domain = false );
+       public function getConnectionRef( $i, $groups = [], $domain = false, $flags = 0 );
 
        /**
         * Get a database connection handle reference without connecting yet
         *
         * The handle's methods simply wrap those of a Database handle
         *
+        * Avoid using CONN_TRX_AUTO with sqlite (e.g. check getServerType() first)
+        *
         * @see ILoadBalancer::getConnection() for parameter information
         *
         * @param int $i Server index or DB_MASTER/DB_REPLICA
         * @param array|string|bool $groups Query group(s), or false for the generic reader
         * @param string|bool $domain Domain ID, or false for the current domain
+        * @param int $flags Bitfield of CONN_* class constants (e.g. CONN_TRX_AUTO)
         * @return DBConnRef
         */
-       public function getLazyConnectionRef( $i, $groups = [], $domain = false );
+       public function getLazyConnectionRef( $i, $groups = [], $domain = false, $flags = 0 );
 
        /**
         * Get a maintenance database connection handle reference for migrations and schema changes
         *
         * The handle's methods simply wrap those of a Database handle
         *
+        * Avoid using CONN_TRX_AUTO with sqlite (e.g. check getServerType() first)
+        *
         * @see ILoadBalancer::getConnection() for parameter information
         *
         * @param int $db Server index or DB_MASTER/DB_REPLICA
         * @param array|string|bool $groups Query group(s), or false for the generic reader
         * @param string|bool $domain Domain ID, or false for the current domain
+        * @param int $flags Bitfield of CONN_* class constants (e.g. CONN_TRX_AUTO)
         * @return MaintainableDBConnRef
         */
-       public function getMaintenanceConnectionRef( $db, $groups = [], $domain = false );
+       public function getMaintenanceConnectionRef( $db, $groups = [], $domain = false, $flags = 0 );
 
        /**
         * Open a connection to the server given by the specified index
@@ -237,14 +251,17 @@ interface ILoadBalancer {
         * The index must be an actual index into the array. If a connection to the server is
         * already open and not considered an "in use" foreign connection, this simply returns it.
         *
+        * Avoid using CONN_TRX_AUTO with sqlite (e.g. check getServerType() first)
+        *
         * @note If disable() was called on this LoadBalancer, this method will throw a DBAccessError.
         *
         * @param int $i Server index (does not support DB_MASTER/DB_REPLICA)
         * @param string|bool $domain Domain ID, or false for the current domain
+        * @param int $flags Bitfield of CONN_* class constants (e.g. CONN_TRX_AUTO)
         * @return Database|bool Returns false on errors
         * @throws DBAccessError
         */
-       public function openConnection( $i, $domain = false );
+       public function openConnection( $i, $domain = false, $flags = 0 );
 
        /**
         * @return int
@@ -254,7 +271,7 @@ interface ILoadBalancer {
        /**
         * Returns true if the specified index is a valid server index
         *
-        * @param string $i
+        * @param int $i
         * @return bool
         */
        public function haveIndex( $i );
@@ -262,7 +279,7 @@ interface ILoadBalancer {
        /**
         * Returns true if the specified index is valid and has non-zero load
         *
-        * @param string $i
+        * @param int $i
         * @return bool
         */
        public function isNonZeroLoad( $i );
@@ -276,12 +293,21 @@ interface ILoadBalancer {
 
        /**
         * Get the host name or IP address of the server with the specified index
-        * Prefer a readable name if available.
-        * @param string $i
-        * @return string
+        *
+        * @param int $i
+        * @return string Readable name if available or IP/host otherwise
         */
        public function getServerName( $i );
 
+       /**
+        * Get DB type of the server with the specified index
+        *
+        * @param int $i
+        * @return string One of (mysql,postgres,sqlite,...) or "unknown" for bad indexes
+        * @since 1.30
+        */
+       public function getServerType( $i );
+
        /**
         * Return the server info structure for a given index, or false if the index is invalid.
         * @param int $i
index 72217da..1665a5e 100644 (file)
@@ -41,7 +41,7 @@ use Exception;
 class LoadBalancer implements ILoadBalancer {
        /** @var array[] Map of (server index => server config array) */
        private $mServers;
-       /** @var Database[][][] Map of local/foreignUsed/foreignFree => server index => IDatabase[] */
+       /** @var Database[][][] Map of (connection category => server index => IDatabase[]) */
        private $mConns;
        /** @var float[] Map of (server index => weight) */
        private $mLoads;
@@ -62,8 +62,6 @@ class LoadBalancer implements ILoadBalancer {
        private $chronProt;
        /** @var BagOStuff */
        private $srvCache;
-       /** @var BagOStuff */
-       private $memCache;
        /** @var WANObjectCache */
        private $wanCache;
        /** @var object|string Class name or object With profileIn/profileOut methods */
@@ -130,11 +128,22 @@ class LoadBalancer implements ILoadBalancer {
        const KEY_FOREIGN_FREE = 'foreignFree';
        const KEY_FOREIGN_INUSE = 'foreignInUse';
 
+       const KEY_LOCAL_NOROUND = 'localAutoCommit';
+       const KEY_FOREIGN_FREE_NOROUND = 'foreignFreeAutoCommit';
+       const KEY_FOREIGN_INUSE_NOROUND = 'foreignInUseAutoCommit';
+
        public function __construct( array $params ) {
                if ( !isset( $params['servers'] ) ) {
                        throw new InvalidArgumentException( __CLASS__ . ': missing servers parameter' );
                }
                $this->mServers = $params['servers'];
+               foreach ( $this->mServers as $i => $server ) {
+                       if ( $i == 0 ) {
+                               $this->mServers[$i]['master'] = true;
+                       } else {
+                               $this->mServers[$i]['replica'] = true;
+                       }
+               }
 
                $this->localDomain = isset( $params['localDomain'] )
                        ? DatabaseDomain::newFromId( $params['localDomain'] )
@@ -152,9 +161,14 @@ class LoadBalancer implements ILoadBalancer {
 
                $this->mReadIndex = -1;
                $this->mConns = [
+                       // Connection were transaction rounds may be applied
                        self::KEY_LOCAL => [],
                        self::KEY_FOREIGN_INUSE => [],
-                       self::KEY_FOREIGN_FREE => []
+                       self::KEY_FOREIGN_FREE => [],
+                       // Auto-committing counterpart connections that ignore transaction rounds
+                       self::KEY_LOCAL_NOROUND => [],
+                       self::KEY_FOREIGN_INUSE_NOROUND => [],
+                       self::KEY_FOREIGN_FREE_NOROUND => []
                ];
                $this->mLoads = [];
                $this->mWaitForPos = false;
@@ -187,11 +201,6 @@ class LoadBalancer implements ILoadBalancer {
                } else {
                        $this->srvCache = new EmptyBagOStuff();
                }
-               if ( isset( $params['memCache'] ) ) {
-                       $this->memCache = $params['memCache'];
-               } else {
-                       $this->memCache = new EmptyBagOStuff();
-               }
                if ( isset( $params['wanCache'] ) ) {
                        $this->wanCache = $params['wanCache'];
                } else {
@@ -244,7 +253,7 @@ class LoadBalancer implements ILoadBalancer {
                        }
 
                        $this->loadMonitor = new $class(
-                               $this, $this->srvCache, $this->memCache, $this->loadMonitorConfig );
+                               $this, $this->srvCache, $this->wanCache, $this->loadMonitorConfig );
                        $this->loadMonitor->setLogger( $this->replLogger );
                }
 
@@ -608,16 +617,7 @@ class LoadBalancer implements ILoadBalancer {
                return $ok;
        }
 
-       /**
-        * @see ILoadBalancer::getConnection()
-        *
-        * @param int $i
-        * @param array $groups
-        * @param bool $domain
-        * @return Database
-        * @throws DBConnectionError
-        */
-       public function getConnection( $i, $groups = [], $domain = false ) {
+       public function getConnection( $i, $groups = [], $domain = false, $flags = 0 ) {
                if ( $i === null || $i === false ) {
                        throw new InvalidArgumentException( 'Attempt to call ' . __METHOD__ .
                                ' with invalid server index' );
@@ -664,7 +664,7 @@ class LoadBalancer implements ILoadBalancer {
                }
 
                # Now we have an explicit index into the servers array
-               $conn = $this->openConnection( $i, $domain );
+               $conn = $this->openConnection( $i, $domain, $flags );
                if ( !$conn ) {
                        // Throw an exception
                        $this->reportConnectionError();
@@ -714,20 +714,29 @@ class LoadBalancer implements ILoadBalancer {
                        return; // DBConnRef handle probably survived longer than the LoadBalancer
                }
 
+               if ( $conn->getLBInfo( 'autoCommitOnly' ) ) {
+                       $connFreeKey = self::KEY_FOREIGN_FREE_NOROUND;
+                       $connInUseKey = self::KEY_FOREIGN_INUSE_NOROUND;
+               } else {
+                       $connFreeKey = self::KEY_FOREIGN_FREE;
+                       $connInUseKey = self::KEY_FOREIGN_INUSE;
+               }
+
                $domain = $conn->getDomainID();
-               if ( !isset( $this->mConns[self::KEY_FOREIGN_INUSE][$serverIndex][$domain] ) ) {
+               if ( !isset( $this->mConns[$connInUseKey][$serverIndex][$domain] ) ) {
                        throw new InvalidArgumentException( __METHOD__ .
                                ": connection $serverIndex/$domain not found; it may have already been freed." );
-               } elseif ( $this->mConns[self::KEY_FOREIGN_INUSE][$serverIndex][$domain] !== $conn ) {
+               } elseif ( $this->mConns[$connInUseKey][$serverIndex][$domain] !== $conn ) {
                        throw new InvalidArgumentException( __METHOD__ .
                                ": connection $serverIndex/$domain mismatched; it may have already been freed." );
                }
+
                $conn->setLBInfo( 'foreignPoolRefCount', --$refCount );
                if ( $refCount <= 0 ) {
-                       $this->mConns[self::KEY_FOREIGN_FREE][$serverIndex][$domain] = $conn;
-                       unset( $this->mConns[self::KEY_FOREIGN_INUSE][$serverIndex][$domain] );
-                       if ( !$this->mConns[self::KEY_FOREIGN_INUSE][$serverIndex] ) {
-                               unset( $this->mConns[ self::KEY_FOREIGN_INUSE ][$serverIndex] ); // clean up
+                       $this->mConns[$connFreeKey][$serverIndex][$domain] = $conn;
+                       unset( $this->mConns[$connInUseKey][$serverIndex][$domain] );
+                       if ( !$this->mConns[$connInUseKey][$serverIndex] ) {
+                               unset( $this->mConns[$connInUseKey][$serverIndex] ); // clean up
                        }
                        $this->connLogger->debug( __METHOD__ . ": freed connection $serverIndex/$domain" );
                } else {
@@ -736,33 +745,26 @@ class LoadBalancer implements ILoadBalancer {
                }
        }
 
-       public function getConnectionRef( $db, $groups = [], $domain = false ) {
+       public function getConnectionRef( $db, $groups = [], $domain = false, $flags = 0 ) {
                $domain = ( $domain !== false ) ? $domain : $this->localDomain;
 
-               return new DBConnRef( $this, $this->getConnection( $db, $groups, $domain ) );
+               return new DBConnRef( $this, $this->getConnection( $db, $groups, $domain, $flags ) );
        }
 
-       public function getLazyConnectionRef( $db, $groups = [], $domain = false ) {
+       public function getLazyConnectionRef( $db, $groups = [], $domain = false, $flags = 0 ) {
                $domain = ( $domain !== false ) ? $domain : $this->localDomain;
 
-               return new DBConnRef( $this, [ $db, $groups, $domain ] );
+               return new DBConnRef( $this, [ $db, $groups, $domain, $flags ] );
        }
 
-       public function getMaintenanceConnectionRef( $db, $groups = [], $domain = false ) {
+       public function getMaintenanceConnectionRef( $db, $groups = [], $domain = false, $flags = 0 ) {
                $domain = ( $domain !== false ) ? $domain : $this->localDomain;
 
-               return new MaintainableDBConnRef( $this, $this->getConnection( $db, $groups, $domain ) );
+               return new MaintainableDBConnRef(
+                       $this, $this->getConnection( $db, $groups, $domain, $flags ) );
        }
 
-       /**
-        * @see ILoadBalancer::openConnection()
-        *
-        * @param int $i
-        * @param bool $domain
-        * @return bool|Database
-        * @throws DBAccessError
-        */
-       public function openConnection( $i, $domain = false ) {
+       public function openConnection( $i, $domain = false, $flags = 0 ) {
                if ( $this->localDomain->equals( $domain ) || $domain === $this->localDomainIdAlias ) {
                        $domain = false; // local connection requested
                }
@@ -774,26 +776,38 @@ class LoadBalancer implements ILoadBalancer {
                        $this->chronProt->initLB( $this );
                }
 
+               // Check if an auto-commit connection is being requested. If so, it will not reuse the
+               // main set of DB connections but rather its own pool since:
+               // a) those are usually set to implicitly use transaction rounds via DBO_TRX
+               // b) those must support the use of explicit transaction rounds via beginMasterChanges()
+               $autoCommit = ( ( $flags & self::CONN_TRX_AUTO ) == self::CONN_TRX_AUTO );
+
                if ( $domain !== false ) {
-                       $conn = $this->openForeignConnection( $i, $domain );
-               } elseif ( isset( $this->mConns[self::KEY_LOCAL][$i][0] ) ) {
-                       $conn = $this->mConns[self::KEY_LOCAL][$i][0];
+                       // Connection is to a foreign domain
+                       $conn = $this->openForeignConnection( $i, $domain, $flags );
                } else {
-                       if ( !isset( $this->mServers[$i] ) || !is_array( $this->mServers[$i] ) ) {
-                               throw new InvalidArgumentException( "No server with index '$i'." );
-                       }
-                       // Open a new connection
-                       $server = $this->mServers[$i];
-                       $server['serverIndex'] = $i;
-                       $conn = $this->reallyOpenConnection( $server, false );
-                       $serverName = $this->getServerName( $i );
-                       if ( $conn->isOpen() ) {
-                               $this->connLogger->debug( "Connected to database $i at '$serverName'." );
-                               $this->mConns[self::KEY_LOCAL][$i][0] = $conn;
+                       // Connection is to the local domain
+                       $connKey = $autoCommit ? self::KEY_LOCAL_NOROUND : self::KEY_LOCAL;
+                       if ( isset( $this->mConns[$connKey][$i][0] ) ) {
+                               $conn = $this->mConns[$connKey][$i][0];
                        } else {
-                               $this->connLogger->warning( "Failed to connect to database $i at '$serverName'." );
-                               $this->errorConnection = $conn;
-                               $conn = false;
+                               if ( !isset( $this->mServers[$i] ) || !is_array( $this->mServers[$i] ) ) {
+                                       throw new InvalidArgumentException( "No server with index '$i'." );
+                               }
+                               // Open a new connection
+                               $server = $this->mServers[$i];
+                               $server['serverIndex'] = $i;
+                               $server['autoCommitOnly'] = $autoCommit;
+                               $conn = $this->reallyOpenConnection( $server, false );
+                               $host = $this->getServerName( $i );
+                               if ( $conn->isOpen() ) {
+                                       $this->connLogger->debug( "Connected to database $i at '$host'." );
+                                       $this->mConns[$connKey][$i][0] = $conn;
+                               } else {
+                                       $this->connLogger->warning( "Failed to connect to database $i at '$host'." );
+                                       $this->errorConnection = $conn;
+                                       $conn = false;
+                               }
                        }
                }
 
@@ -806,6 +820,10 @@ class LoadBalancer implements ILoadBalancer {
                        $conn = false;
                }
 
+               if ( $autoCommit && $conn instanceof IDatabase ) {
+                       $conn->clearFlag( $conn::DBO_TRX ); // auto-commit mode
+               }
+
                return $conn;
        }
 
@@ -827,27 +845,37 @@ class LoadBalancer implements ILoadBalancer {
         *
         * @param int $i Server index
         * @param string $domain Domain ID to open
+        * @param integer $flags Class CONN_* constant bitfield
         * @return Database
         */
-       private function openForeignConnection( $i, $domain ) {
+       private function openForeignConnection( $i, $domain, $flags = 0 ) {
                $domainInstance = DatabaseDomain::newFromId( $domain );
                $dbName = $domainInstance->getDatabase();
                $prefix = $domainInstance->getTablePrefix();
+               $autoCommit = ( ( $flags & self::CONN_TRX_AUTO ) == self::CONN_TRX_AUTO );
 
-               if ( isset( $this->mConns[self::KEY_FOREIGN_INUSE][$i][$domain] ) ) {
-                       // Reuse an in-use connection for the same domain that is not in-use
-                       $conn = $this->mConns[self::KEY_FOREIGN_INUSE][$i][$domain];
+               if ( $autoCommit ) {
+                       $connFreeKey = self::KEY_FOREIGN_FREE_NOROUND;
+                       $connInUseKey = self::KEY_FOREIGN_INUSE_NOROUND;
+               } else {
+                       $connFreeKey = self::KEY_FOREIGN_FREE;
+                       $connInUseKey = self::KEY_FOREIGN_INUSE;
+               }
+
+               if ( isset( $this->mConns[$connInUseKey][$i][$domain] ) ) {
+                       // Reuse an in-use connection for the same domain
+                       $conn = $this->mConns[$connInUseKey][$i][$domain];
                        $this->connLogger->debug( __METHOD__ . ": reusing connection $i/$domain" );
-               } elseif ( isset( $this->mConns[self::KEY_FOREIGN_FREE][$i][$domain] ) ) {
-                       // Reuse a free connection for the same domain that is not in-use
-                       $conn = $this->mConns[self::KEY_FOREIGN_FREE][$i][$domain];
-                       unset( $this->mConns[self::KEY_FOREIGN_FREE][$i][$domain] );
-                       $this->mConns[self::KEY_FOREIGN_INUSE][$i][$domain] = $conn;
+               } elseif ( isset( $this->mConns[$connFreeKey][$i][$domain] ) ) {
+                       // Reuse a free connection for the same domain
+                       $conn = $this->mConns[$connFreeKey][$i][$domain];
+                       unset( $this->mConns[$connFreeKey][$i][$domain] );
+                       $this->mConns[$connInUseKey][$i][$domain] = $conn;
                        $this->connLogger->debug( __METHOD__ . ": reusing free connection $i/$domain" );
-               } elseif ( !empty( $this->mConns[self::KEY_FOREIGN_FREE][$i] ) ) {
-                       // Reuse a connection from another domain
-                       $conn = reset( $this->mConns[self::KEY_FOREIGN_FREE][$i] );
-                       $oldDomain = key( $this->mConns[self::KEY_FOREIGN_FREE][$i] );
+               } elseif ( !empty( $this->mConns[$connFreeKey][$i] ) ) {
+                       // Reuse a free connection from another domain
+                       $conn = reset( $this->mConns[$connFreeKey][$i] );
+                       $oldDomain = key( $this->mConns[$connFreeKey][$i] );
                        // The empty string as a DB name means "don't care".
                        // DatabaseMysqlBase::open() already handle this on connection.
                        if ( strlen( $dbName ) && !$conn->selectDB( $dbName ) ) {
@@ -857,8 +885,8 @@ class LoadBalancer implements ILoadBalancer {
                                $conn = false;
                        } else {
                                $conn->tablePrefix( $prefix );
-                               unset( $this->mConns[self::KEY_FOREIGN_FREE][$i][$oldDomain] );
-                               $this->mConns[self::KEY_FOREIGN_INUSE][$i][$domain] = $conn;
+                               unset( $this->mConns[$connFreeKey][$i][$oldDomain] );
+                               $this->mConns[$connInUseKey][$i][$domain] = $conn;
                                $this->connLogger->debug( __METHOD__ .
                                        ": reusing free connection from $oldDomain for $domain" );
                        }
@@ -871,6 +899,7 @@ class LoadBalancer implements ILoadBalancer {
                        $server['serverIndex'] = $i;
                        $server['foreignPoolRefCount'] = 0;
                        $server['foreign'] = true;
+                       $server['autoCommitOnly'] = $autoCommit;
                        $conn = $this->reallyOpenConnection( $server, $dbName );
                        if ( !$conn->isOpen() ) {
                                $this->connLogger->warning( __METHOD__ . ": connection error for $i/$domain" );
@@ -878,7 +907,7 @@ class LoadBalancer implements ILoadBalancer {
                                $conn = false;
                        } else {
                                $conn->tablePrefix( $prefix );
-                               $this->mConns[self::KEY_FOREIGN_INUSE][$i][$domain] = $conn;
+                               $this->mConns[$connInUseKey][$i][$domain] = $conn;
                                $this->connLogger->debug( __METHOD__ . ": opened new connection for $i/$domain" );
                        }
                }
@@ -1037,6 +1066,10 @@ class LoadBalancer implements ILoadBalancer {
                return ( $name != '' ) ? $name : 'localhost';
        }
 
+       public function getServerType( $i ) {
+               return isset( $this->mServers[$i]['type'] ) ? $this->mServers[$i]['type'] : 'unknown';
+       }
+
        /**
         * @deprecated Since 1.30, no alternative
         */
@@ -1090,8 +1123,11 @@ class LoadBalancer implements ILoadBalancer {
 
                $this->mConns = [
                        self::KEY_LOCAL => [],
-                       self::KEY_FOREIGN_FREE => [],
                        self::KEY_FOREIGN_INUSE => [],
+                       self::KEY_FOREIGN_FREE => [],
+                       self::KEY_LOCAL_NOROUND => [],
+                       self::KEY_FOREIGN_INUSE_NOROUND => [],
+                       self::KEY_FOREIGN_FREE_NOROUND => []
                ];
                $this->connsOpened = 0;
        }
@@ -1172,7 +1208,7 @@ class LoadBalancer implements ILoadBalancer {
                        if ( $limit > 0 && $time > $limit ) {
                                throw new DBTransactionSizeError(
                                        $conn,
-                                       "Transaction spent $time second(s) in writes, exceeding the $limit limit.",
+                                       "Transaction spent $time second(s) in writes, exceeding the limit of $limit.",
                                        [ $time, $limit ]
                                );
                        }
@@ -1311,6 +1347,10 @@ class LoadBalancer implements ILoadBalancer {
         * @param IDatabase $conn
         */
        private function applyTransactionRoundFlags( IDatabase $conn ) {
+               if ( $conn->getLBInfo( 'autoCommitOnly' ) ) {
+                       return; // transaction rounds do not apply to these connections
+               }
+
                if ( $conn->getFlag( $conn::DBO_DEFAULT ) ) {
                        // DBO_TRX is controlled entirely by CLI mode presence with DBO_DEFAULT.
                        // Force DBO_TRX even in CLI mode since a commit round is expected soon.
@@ -1325,6 +1365,10 @@ class LoadBalancer implements ILoadBalancer {
         * @param IDatabase $conn
         */
        private function undoTransactionRoundFlags( IDatabase $conn ) {
+               if ( $conn->getLBInfo( 'autoCommitOnly' ) ) {
+                       return; // transaction rounds do not apply to these connections
+               }
+
                if ( $conn->getFlag( $conn::DBO_DEFAULT ) ) {
                        $conn->restoreFlags( $conn::RESTORE_PRIOR );
                }
index 4f6701f..fba5e13 100644 (file)
@@ -25,6 +25,7 @@ namespace Wikimedia\Rdbms;
 
 use Psr\Log\LoggerAwareInterface;
 use BagOStuff;
+use WANObjectCache;
 
 /**
  * An interface for database load monitoring
@@ -37,11 +38,11 @@ interface ILoadMonitor extends LoggerAwareInterface {
         *
         * @param ILoadBalancer $lb LoadBalancer this instance serves
         * @param BagOStuff $sCache Local server memory cache
-        * @param BagOStuff $cCache Local cluster memory cache
+        * @param WANObjectCache $wCache Local cluster memory cache
         * @param array $options Options map
         */
        public function __construct(
-               ILoadBalancer $lb, BagOStuff $sCache, BagOStuff $cCache, array $options = []
+               ILoadBalancer $lb, BagOStuff $sCache, WANObjectCache $wCache, array $options = []
        );
 
        /**
index 4300e9f..d4e73c9 100644 (file)
@@ -25,6 +25,7 @@ use Psr\Log\LoggerInterface;
 use Psr\Log\NullLogger;
 use Wikimedia\ScopedCallback;
 use BagOStuff;
+use WANObjectCache;
 
 /**
  * Basic DB load monitor with no external dependencies
@@ -37,8 +38,8 @@ class LoadMonitor implements ILoadMonitor {
        protected $parent;
        /** @var BagOStuff */
        protected $srvCache;
-       /** @var BagOStuff */
-       protected $mainCache;
+       /** @var WANObjectCache */
+       protected $wanCache;
        /** @var LoggerInterface */
        protected $replLogger;
 
@@ -48,11 +49,11 @@ class LoadMonitor implements ILoadMonitor {
        const VERSION = 1; // cache key version
 
        public function __construct(
-               ILoadBalancer $lb, BagOStuff $srvCache, BagOStuff $cache, array $options = []
+               ILoadBalancer $lb, BagOStuff $srvCache, WANObjectCache $wCache, array $options = []
        ) {
                $this->parent = $lb;
                $this->srvCache = $srvCache;
-               $this->mainCache = $cache;
+               $this->wanCache = $wCache;
                $this->replLogger = new NullLogger();
 
                $this->movingAveRatio = isset( $options['movingAveRatio'] )
@@ -109,7 +110,7 @@ class LoadMonitor implements ILoadMonitor {
                $staleValue = $value ?: false;
 
                # (b) Check the shared cache and backfill APC
-               $value = $this->mainCache->get( $key );
+               $value = $this->wanCache->get( $key );
                if ( $value && $value['timestamp'] > ( microtime( true ) - $ttl ) ) {
                        $this->srvCache->set( $key, $value, $staleTTL );
                        $this->replLogger->debug( __METHOD__ . ": got lag times ($key) from main cache" );
@@ -119,12 +120,12 @@ class LoadMonitor implements ILoadMonitor {
                $staleValue = $value ?: $staleValue;
 
                # (c) Cache key missing or expired; regenerate and backfill
-               if ( $this->mainCache->lock( $key, 0, 10 ) ) {
-                       # Let this process alone update the cache value
-                       $cache = $this->mainCache;
+               if ( $this->srvCache->lock( $key, 0, 10 ) ) {
+                       # Let only this process update the cache value on this server
+                       $sCache = $this->srvCache;
                        /** @noinspection PhpUnusedLocalVariableInspection */
-                       $unlocker = new ScopedCallback( function () use ( $cache, $key ) {
-                               $cache->unlock( $key );
+                       $unlocker = new ScopedCallback( function () use ( $sCache, $key ) {
+                               $sCache->unlock( $key );
                        } );
                } elseif ( $staleValue ) {
                        # Could not acquire lock but an old cache exists, so use it
@@ -196,7 +197,7 @@ class LoadMonitor implements ILoadMonitor {
                        'weightScales' => $weightScales,
                        'timestamp' => microtime( true )
                ];
-               $this->mainCache->set( $key, $value, $staleTTL );
+               $this->wanCache->set( $key, $value, $staleTTL );
                $this->srvCache->set( $key, $value, $staleTTL );
                $this->replLogger->info( __METHOD__ . ": re-calculated lag times ($key)" );
 
index ff72dbc..f8ad329 100644 (file)
@@ -22,6 +22,7 @@
 namespace Wikimedia\Rdbms;
 
 use BagOStuff;
+use WANObjectCache;
 
 /**
  * Basic MySQL load monitor with no external dependencies
@@ -34,9 +35,9 @@ class LoadMonitorMySQL extends LoadMonitor {
        private $warmCacheRatio;
 
        public function __construct(
-               ILoadBalancer $lb, BagOStuff $srvCache, BagOStuff $cache, array $options = []
+               ILoadBalancer $lb, BagOStuff $srvCache, WANObjectCache $wCache, array $options = []
        ) {
-               parent::__construct( $lb, $srvCache, $cache, $options );
+               parent::__construct( $lb, $srvCache, $wCache, $options );
 
                $this->warmCacheRatio = isset( $options['warmCacheRatio'] )
                        ? $options['warmCacheRatio']
index 8bbf9e5..6dae8cc 100644 (file)
@@ -23,10 +23,11 @@ namespace Wikimedia\Rdbms;
 
 use Psr\Log\LoggerInterface;
 use BagOStuff;
+use WANObjectCache;
 
 class LoadMonitorNull implements ILoadMonitor {
        public function __construct(
-               ILoadBalancer $lb, BagOStuff $sCache, BagOStuff $cCache, array $options = []
+               ILoadBalancer $lb, BagOStuff $sCache, WANObjectCache $wCache, array $options = []
        ) {
        }
 
index 3cce530..2cfd2a1 100644 (file)
@@ -145,27 +145,11 @@ class SqlBagOStuff extends BagOStuff {
                $this->replicaOnly = !empty( $params['slaveOnly'] );
        }
 
-       protected function getSeparateMainLB() {
-               global $wgDBtype;
-
-               if ( $this->usesMainDB() && $wgDBtype !== 'sqlite' ) {
-                       if ( !$this->separateMainLB ) {
-                               // We must keep a separate connection to MySQL in order to avoid deadlocks
-                               $lbFactory = MediaWikiServices::getInstance()->getDBLoadBalancerFactory();
-                               $this->separateMainLB = $lbFactory->newMainLB();
-                       }
-                       return $this->separateMainLB;
-               } else {
-                       // However, SQLite has an opposite behavior due to DB-level locking
-                       return null;
-               }
-       }
-
        /**
         * Get a connection to the specified database
         *
         * @param int $serverIndex
-        * @return IDatabase
+        * @return Database
         * @throws MWException
         */
        protected function getDB( $serverIndex ) {
@@ -181,8 +165,8 @@ class SqlBagOStuff extends BagOStuff {
                                throw $this->connFailureErrors[$serverIndex];
                        }
 
-                       # If server connection info was given, use that
                        if ( $this->serverInfos ) {
+                               // Use custom database defined by server connection info
                                $info = $this->serverInfos[$serverIndex];
                                $type = isset( $info['type'] ) ? $info['type'] : 'mysql';
                                $host = isset( $info['host'] ) ? $info['host'] : '[unknown]';
@@ -190,17 +174,22 @@ class SqlBagOStuff extends BagOStuff {
                                // Use a blank trx profiler to ignore expections as this is a cache
                                $info['trxProfiler'] = new TransactionProfiler();
                                $db = Database::factory( $type, $info );
-                               $db->clearFlag( DBO_TRX );
+                               $db->clearFlag( DBO_TRX ); // auto-commit mode
                        } else {
+                               // Use the main LB database
+                               $lb = MediaWikiServices::getInstance()->getDBLoadBalancer();
                                $index = $this->replicaOnly ? DB_REPLICA : DB_MASTER;
-                               if ( $this->getSeparateMainLB() ) {
-                                       $db = $this->getSeparateMainLB()->getConnection( $index );
-                                       $db->clearFlag( DBO_TRX ); // auto-commit mode
+                               if ( $lb->getServerType( $lb->getWriterIndex() ) !== 'sqlite' ) {
+                                       // Keep a separate connection to avoid contention and deadlocks
+                                       $db = $lb->getConnection( $index, [], false, $lb::CONN_TRX_AUTO );
+                                       // @TODO: Use a blank trx profiler to ignore expections as this is a cache
                                } else {
-                                       $db = wfGetDB( $index );
-                                       // Can't mess with transaction rounds (DBO_TRX) :(
+                                       // However, SQLite has the opposite behavior due to DB-level locking.
+                                       // Stock sqlite MediaWiki installs use a separate sqlite cache DB instead.
+                                       $db = $lb->getConnection( $index );
                                }
                        }
+
                        $this->logger->debug( sprintf( "Connection %s will be used for SqlBagOStuff", $db ) );
                        $this->conns[$serverIndex] = $db;
                }
@@ -812,9 +801,7 @@ class SqlBagOStuff extends BagOStuff {
                        return true;
                }
 
-               $lb = $this->getSeparateMainLB()
-                       ?: MediaWikiServices::getInstance()->getDBLoadBalancer();
-
+               $lb = MediaWikiServices::getInstance()->getDBLoadBalancer();
                if ( $lb->getServerCount() <= 1 ) {
                        return true; // no replica DBs
                }
index f49d46c..cbffe1e 100644 (file)
@@ -306,8 +306,8 @@ class SkinTemplate extends Skin {
                $tpl->set( 'pagetitle', $out->getHTMLTitle() );
                $tpl->set( 'displaytitle', $out->mPageLinkTitle );
 
-               $tpl->setRef( 'thispage', $this->thispage );
-               $tpl->setRef( 'titleprefixeddbkey', $this->thispage );
+               $tpl->set( 'thispage', $this->thispage );
+               $tpl->set( 'titleprefixeddbkey', $this->thispage );
                $tpl->set( 'titletext', $title->getText() );
                $tpl->set( 'articleid', $title->getArticleID() );
 
@@ -336,32 +336,32 @@ class SkinTemplate extends Skin {
                                        'href' => $link
                                ];
                        }
-                       $tpl->setRef( 'feeds', $feeds );
+                       $tpl->set( 'feeds', $feeds );
                } else {
                        $tpl->set( 'feeds', false );
                }
 
-               $tpl->setRef( 'mimetype', $wgMimeType );
-               $tpl->setRef( 'jsmimetype', $wgJsMimeType );
+               $tpl->set( 'mimetype', $wgMimeType );
+               $tpl->set( 'jsmimetype', $wgJsMimeType );
                $tpl->set( 'charset', 'UTF-8' );
-               $tpl->setRef( 'wgScript', $wgScript );
-               $tpl->setRef( 'skinname', $this->skinname );
+               $tpl->set( 'wgScript', $wgScript );
+               $tpl->set( 'skinname', $this->skinname );
                $tpl->set( 'skinclass', static::class );
-               $tpl->setRef( 'skin', $this );
-               $tpl->setRef( 'stylename', $this->stylename );
+               $tpl->set( 'skin', $this );
+               $tpl->set( 'stylename', $this->stylename );
                $tpl->set( 'printable', $out->isPrintable() );
                $tpl->set( 'handheld', $request->getBool( 'handheld' ) );
-               $tpl->setRef( 'loggedin', $this->loggedin );
+               $tpl->set( 'loggedin', $this->loggedin );
                $tpl->set( 'notspecialpage', !$title->isSpecialPage() );
                $tpl->set( 'searchaction', $this->escapeSearchLink() );
                $tpl->set( 'searchtitle', SpecialPage::getTitleFor( 'Search' )->getPrefixedDBkey() );
                $tpl->set( 'search', trim( $request->getVal( 'search' ) ) );
-               $tpl->setRef( 'stylepath', $wgStylePath );
-               $tpl->setRef( 'articlepath', $wgArticlePath );
-               $tpl->setRef( 'scriptpath', $wgScriptPath );
-               $tpl->setRef( 'serverurl', $wgServer );
-               $tpl->setRef( 'logopath', $wgLogo );
-               $tpl->setRef( 'sitename', $wgSitename );
+               $tpl->set( 'stylepath', $wgStylePath );
+               $tpl->set( 'articlepath', $wgArticlePath );
+               $tpl->set( 'scriptpath', $wgScriptPath );
+               $tpl->set( 'serverurl', $wgServer );
+               $tpl->set( 'logopath', $wgLogo );
+               $tpl->set( 'sitename', $wgSitename );
 
                $userLang = $this->getLanguage();
                $userLangCode = $userLang->getHtmlCode();
@@ -374,8 +374,8 @@ class SkinTemplate extends Skin {
                $tpl->set( 'capitalizeallnouns', $userLang->capitalizeAllNouns() ? ' capitalize-all-nouns' : '' );
                $tpl->set( 'showjumplinks', true ); // showjumplinks preference has been removed
                $tpl->set( 'username', $this->loggedin ? $this->username : null );
-               $tpl->setRef( 'userpage', $this->userpage );
-               $tpl->setRef( 'userpageurl', $this->userpageUrlDetails['href'] );
+               $tpl->set( 'userpage', $this->userpage );
+               $tpl->set( 'userpageurl', $this->userpageUrlDetails['href'] );
                $tpl->set( 'userlang', $userLangCode );
 
                // Users can have their language set differently than the
@@ -1080,7 +1080,12 @@ class SkinTemplate extends Skin {
                                                ),
                                                // uses 'watch' or 'unwatch' message
                                                'text' => $this->msg( $mode )->text(),
-                                               'href' => $title->getLocalURL( [ 'action' => $mode ] )
+                                               'href' => $title->getLocalURL( [ 'action' => $mode ] ),
+                                               // Set a data-mw=interface attribute, which the mediawiki.page.ajax
+                                               // module will look for to make sure it's a trusted link
+                                               'data' => [
+                                                       'mw' => 'interface',
+                                               ],
                                        ];
                                }
                        }
index 6a79714..e3b73a9 100644 (file)
@@ -494,17 +494,22 @@ class SpecialNewpages extends IncludableSpecialPage {
        }
 
        protected function feedItemDesc( $row ) {
-               $revision = $this->revisionFromRcResult( $row );
-               if ( $revision ) {
-                       // XXX: include content model/type in feed item?
-                       return '<p>' . htmlspecialchars( $revision->getUserText() ) .
-                               $this->msg( 'colon-separator' )->inContentLanguage()->escaped() .
-                               htmlspecialchars( FeedItem::stripComment( $revision->getComment() ) ) .
-                               "</p>\n<hr />\n<div>" .
-                               nl2br( htmlspecialchars( $revision->getContent()->serialize() ) ) . "</div>";
+               $revision = Revision::newFromId( $row->rev_id );
+               if ( !$revision ) {
+                       return '';
                }
 
-               return '';
+               $content = $revision->getContent();
+               if ( $content === null ) {
+                       return '';
+               }
+
+               // XXX: include content model/type in feed item?
+               return '<p>' . htmlspecialchars( $revision->getUserText() ) .
+                       $this->msg( 'colon-separator' )->inContentLanguage()->escaped() .
+                       htmlspecialchars( FeedItem::stripComment( $revision->getComment() ) ) .
+                       "</p>\n<hr />\n<div>" .
+                       nl2br( htmlspecialchars( $content->serialize() ) ) . "</div>";
        }
 
        protected function getGroupName() {
index 0affa8c..ab9746f 100644 (file)
@@ -23,7 +23,8 @@
                        "Macofe",
                        "Fwolff",
                        "Oesjaar",
-                       "Matma Rex"
+                       "Matma Rex",
+                       "Biggs ZA"
                ]
        },
        "tog-underline": "Onderstreep skakels.",
        "actionthrottled": "Outo-rem op aksie uitgevoer",
        "actionthrottledtext": "As 'n teen-strooi aksie, word u beperk om hierdie aksie te veel keer in 'n kort tyd uit te voer, en u het hierdie limiet oorskry.\nProbeer asseblief weer oor 'n paar minute.",
        "protectedpagetext": "Hierdie bladsy is beskerm om wysigings en ander aksies te verhoed.",
-       "viewsourcetext": "U mag die bronteks van hierdie bladsy lees en kopieer.",
+       "viewsourcetext": "U het toestemming om die bronteks te bekyk en te kopieer.",
        "viewyourtext": "U kan '''u wysigings''' aan die bronteks van hierdie bladsy bekyk en kopieer:",
        "protectedinterface": "Hierdie bladsy verskaf teks vir die koppelvlak van die sagteware, en is beskerm om misbruik te voorkom.\nGebruik asseblief [https://translatewiki.net/ translatewiki.net] om vertalings by te voeg of te wysig.",
        "editinginterface": "'''Waarskuwing:''' U is besig om 'n bladsy te redigeer wat koppelvlakinligting aan die programmatuur voorsien. Wysigings aan hierdie bladsy sal die voorkoms van die gebruikerskoppelvlak vir ander gebruikers beïnvloed. Vir vertalings, oorweeg om eerder [https://translatewiki.net/wiki/Main_Page?setlang=af translatewiki.net] (die vertalingsprojek vir MediaWiki) te gebruik.",
        "page_first": "eerste",
        "page_last": "laaste",
        "histlegend": "Byskrif: (huidige) = verskil van huidige weergawe,\n(vorige) = verskil van vorige weergawe, M = klein wysiging",
-       "history-fieldset-title": "Soek vir wysigings",
+       "history-fieldset-title": "Soek na wysigings",
        "history-show-deleted": "Slegs geskrapte",
        "histfirst": "oudste",
        "histlast": "nuutste",
        "compare-invalid-title": "Die titel wat u verskaf het is ongeldig.",
        "compare-title-not-exists": "Die titel wat u verskaf het bestaan ​​nie.",
        "compare-revision-not-exists": "Die hersiening wat u verskaf het bestaan ​​nie.",
+       "diff-form": "'n '''vorm'''",
        "dberr-problems": "Jammer! Die webwerf ondervind op die oomblik tegniese probleme.",
        "dberr-again": "Wag 'n paar minute en probeer dan weer.",
        "dberr-info": "(Kan nie die databasisbediener kontak nie: $1)",
index e776ba1..a00d2a7 100644 (file)
        "rcfilters-restore-default-filters": "استرجاع المرشحات الافتراضية",
        "rcfilters-clear-all-filters": "مسح كل المرشحات",
        "rcfilters-show-new-changes": "عرض أحدث التغييرات",
-       "rcfilters-previous-changes-label": "تغييرات تم عرضها سابقًا",
        "rcfilters-search-placeholder": "رشح أحدث التغييرات (تصفح أو ابدأ الكتابة)",
        "rcfilters-invalid-filter": "مرشح غير صحيح",
        "rcfilters-empty-filter": "لا مرشحات فعالة. كل المساهمات معروضة.",
index cd7a962..4e7ca5a 100644 (file)
        "rcfilters-restore-default-filters": "Restaurar los filtros predeterminaos",
        "rcfilters-clear-all-filters": "Borrar tolos filtros",
        "rcfilters-show-new-changes": "Ver los cambeos más recién",
-       "rcfilters-previous-changes-label": "Cambeos vistos anteriormente",
        "rcfilters-search-placeholder": "Filtriar los cambeos recién (restola o empieza a escribir)",
        "rcfilters-invalid-filter": "Filtru inválidu",
        "rcfilters-empty-filter": "Nun hai filtros activos. Amuésense toles contribuciones.",
index 41c15c0..68f80d1 100644 (file)
        "rcfilters-restore-default-filters": "Фильтрҙарҙың һүҙһеҙ үтәлгәнен кире ҡуйырға",
        "rcfilters-clear-all-filters": "Бөтә фильтрҙарҙы ла таҙартырға",
        "rcfilters-show-new-changes": "Һуңғы үҙгәртеүҙәрҙе ҡарап сығырға",
-       "rcfilters-previous-changes-label": "Элек ҡаралған үҙгәртеүҙәр",
        "rcfilters-search-placeholder": "Фильтрҙарҙың һуңғы үҙгәрештәре (ҡарап сығығыҙ йәки индерә башлағыҙ)",
        "rcfilters-invalid-filter": "Ярамаған фильтр",
        "rcfilters-empty-filter": "Әүҙем фильтрҙар юҡ. Бөтә үҙгәртеүҙәр ҙә күрһәтелә.",
index db4caf2..d2e4192 100644 (file)
        "rcfilters-restore-default-filters": "Аднавіць фільтры па змоўчаньні",
        "rcfilters-clear-all-filters": "Ачысьціць усе фільтры",
        "rcfilters-show-new-changes": "Праглядзець найноўшыя зьмены",
-       "rcfilters-previous-changes-label": "Раней прагледжаныя зьмены",
        "rcfilters-search-placeholder": "Фільтар апошніх зьменаў (праглядзець або пачніце друкаваць)",
        "rcfilters-invalid-filter": "Няслушны фільтар",
        "rcfilters-empty-filter": "Няма актыўных фільтраў. Паказаны ўвесь унёсак.",
index f7ccc4d..c51f1ac 100644 (file)
        "watchlist-details": "{{PLURAL:$1|Една наблюдавана страница|$1 наблюдавани страници}} от списъка Ви за наблюдение (без беседи).",
        "wlheader-enotif": "Известяването по е-поща е включено.",
        "wlheader-showupdated": "Страниците, които са били променени след последния път, когато сте ги посетили, са показани в '''получер'''.",
-       "wlnote": "{{PLURAL:$1|Показана е последната промяна|Показани са последните <strong>$1</strong> промени}} през {{PLURAL:$2|последния час|последните <strong>$2</strong> часа}}, започвайки от от $3, $4.",
+       "wlnote": "{{PLURAL:$1|Показана е последната промяна|Показани са последните <strong>$1</strong> промени}} през {{PLURAL:$2|последния час|последните <strong>$2</strong> часа}}, започвайки от $3, $4.",
        "wlshowlast": "Показване на последните $1 часа $2 дни",
        "watchlist-hide": "Скриване",
        "watchlist-submit": "Показване",
        "compare-invalid-title": "Посоченото заглавие е невалидно.",
        "compare-title-not-exists": "Посоченото заглавие не съществува.",
        "compare-revision-not-exists": "Посочената версия не съществува.",
+       "diff-form": "'''формуляр'''",
        "dberr-problems": "Съжаляваме! Сайтът изпитва технически затруднения.",
        "dberr-again": "Изчакайте няколко минути и опитайте да презаредите.",
        "dberr-info": "(Няма достъп до базата от данни: $1)",
index 5d02661..28755d8 100644 (file)
        "contentmodelediterror": "আপনি এই পুনর্বিবেচনা সম্পাদনা করতে পারবেন না কারণ এর বিষয়বস্তু মডেল <code>$1</code>, যা বর্তমান বিষয়বস্তু মডেল <code>$2</code>-এর থেকে ভিন্ন।",
        "recreate-moveddeleted-warn": "'''সতর্কীকরণ: আপনি এমন একটি পাতা পুনরায় তৈরি করছেন যা পূর্বে অপসারণ করা হয়েছিল।'''\n\nআপনি পাতাটি সম্পাদনা চালিয়ে যাওয়া ঠিক হবে কিনা, তা বিবেচনা করুন।\nআপনার সুবিধার্থে পাতাটির অপলুপ্তি লগ এখানে দেয়া হলো:",
        "moveddeleted-notice": "এই পাতাটি অপসারণ করা হয়েছে।\nসূত্র হিসেবে নিচে এ পাতার অবলুপ্তি লগ দেওয়া হলো।",
-       "moveddeleted-notice-recent": "দুঃখিত, এই পাতাটি সাম্প্রতি অপসারিত হয়েছে (সর্বশেষ ২৪ ঘণ্টায়)।\nসূত্র হিসেবে নিচে এই পাতা অপসারণ ও স্থানান্তর লগ দেয়া হয়েছে।",
+       "moveddeleted-notice-recent": "দুঃখিত, এই পাতাটি সাম্প্রতি অপসারিত হয়েছে (সর্বশেষ ২৪ ঘণ্টায়)।\nসূত্র হিসেবে নিচে এই পাতা অপসারণ, সুরক্ষা ও স্থানান্তর লগ দেয়া হয়েছে।",
        "log-fulllog": "সম্পূর্ণ লগ দেখুন",
        "edit-hook-aborted": "হূক দ্বারা সম্পাদনা পরিত্যক্ত হয়েছে।\nএর কোন ব্যাখ্যা নাই।",
        "edit-gone-missing": "পাতাটি হালনাগাদ হয়নি।\nসম্ভবতঃ পাতাটি মুছে ফেলা হয়েছে।",
index c6c91c5..d1acb7b 100644 (file)
@@ -86,7 +86,7 @@
        "tog-shownumberswatching": "Mostra el nombre d'usuaris que hi vigilen",
        "tog-oldsig": "La vostra signatura actual:",
        "tog-fancysig": "Tractar la signatura com a text wiki (sense enllaç automàtic)",
-       "tog-uselivepreview": "Utilitza la previsualització automàtica",
+       "tog-uselivepreview": "Mostra previsualitzacions sense recarregar la pàgina",
        "tog-forceeditsummary": "Avisa'm en deixar el resum de la modificació en blanc",
        "tog-watchlisthideown": "Amaga les meues edicions de la llista de seguiment",
        "tog-watchlisthidebots": "Amaga de la llista de seguiment les edicions fetes per usuaris bots",
        "permissionserrorstext-withaction": "No teniu permís per a $2, {{PLURAL:$1|pel motiu següent|pels motius següents}}:",
        "contentmodelediterror": "No podeu modificar aquesta revisió perquè el seu model de contingut és <code>$1</code>, que difereix del model de contingut actual de la pàgina <code>$2</code>.",
        "recreate-moveddeleted-warn": "'''Avís: esteu creant una pàgina que s'ha suprimit prèviament.'''\n\nHauríeu de considerar si és realment necessari continuar editant aquesta pàgina.\nA continuació s'ofereix el registre de supressions i de reanomenaments de la pàgina:",
-       "moveddeleted-notice": "S'ha suprimit aquesta pàgina.\nA continuació us mostrem com a referència el registre d'esborraments i reanomenaments de la pàgina.",
-       "moveddeleted-notice-recent": "S’ha suprimit aquesta pàgina recentment (en les últimes 24 hores).\nA continuació us mostrem com a referència el registre de supressions i reanomenaments de la pàgina.",
+       "moveddeleted-notice": "S'ha suprimit aquesta pàgina.\nA continuació us mostrem com a referència el registre d'esborraments, proteccions i reanomenaments de la pàgina.",
+       "moveddeleted-notice-recent": "S’ha suprimit aquesta pàgina recentment (en les últimes 24 hores).\nA continuació us mostrem com a referència el registre de supressions, proteccions i reanomenaments de la pàgina.",
        "log-fulllog": "Veure tot el registre",
        "edit-hook-aborted": "Modificació avortada pel hook.\nNo s'ha donat cap explicació.",
        "edit-gone-missing": "No s'ha pogut actualitzar la pàgina.\nSembla haver estat esborrada.",
        "prefs-editwatchlist-clear": "Neteja la llista de seguiment",
        "prefs-watchlist-days": "Nombre de dies per mostrar en la llista de seguiment:",
        "prefs-watchlist-days-max": "Màxim $1 {{PLURAL:$1|dia|dies}}",
-       "prefs-watchlist-edits": "Nombre de modificacions a mostrar en una llista estesa de seguiment:",
+       "prefs-watchlist-edits": "Nombre màxim de modificacions a mostrar en la llista de seguiment:",
        "prefs-watchlist-edits-max": "Nombre màxim: 1000",
        "prefs-watchlist-token": "Testimoni de llista de seguiment:",
        "prefs-misc": "Altres preferències",
        "recentchanges-legend-newpage": "{{int:recentchanges-label-newpage}} (vegeu també la [[Special:NewPages|llista de pàgines noves]])",
        "recentchanges-legend-plusminus": "(''±123'')",
        "recentchanges-submit": "Mostra",
+       "rcfilters-legend-heading": "<strong>Llista d'abreviatures:</strong>",
+       "rcfilters-other-review-tools": "<strong>Altres eines de supervisió</strong>",
        "rcfilters-group-results-by-page": "Agrupa els resultats per pàgina",
+       "rcfilters-grouping-title": "Agrupació",
        "rcfilters-activefilters": "Filtres actius",
+       "rcfilters-advancedfilters": "Filtres avançats",
+       "rcfilters-days-title": "Darrers dies",
        "rcfilters-hours-title": "Hores recents",
+       "rcfilters-days-show-days": "$1 {{PLURAL:$1|dia|dies}}",
+       "rcfilters-days-show-hours": "$1 {{PLURAL:$1|hora|hores}}",
        "rcfilters-quickfilters": "Filtres desats",
        "rcfilters-quickfilters-placeholder-title": "Encara no s’ha desat cap enllaç",
        "rcfilters-savedqueries-defaultlabel": "Filtres desats",
        "rcfilters-savedqueries-setdefault": "Defineix per defecte",
        "rcfilters-savedqueries-remove": "Suprimeix",
        "rcfilters-savedqueries-new-name-label": "Nom",
+       "rcfilters-savedqueries-new-name-placeholder": "Descriviu el propòsit del filtre",
        "rcfilters-savedqueries-apply-label": "Crea un filtre",
        "rcfilters-savedqueries-cancel-label": "Cancel·la",
        "rcfilters-savedqueries-add-new-title": "Desa els paràmetres de filtres actuals",
        "rcfilters-invalid-filter": "Filtre no vàlid",
        "rcfilters-empty-filter": "No hi ha cap filtre actiu. Es mostren totes les contribucions.",
        "rcfilters-filterlist-title": "Filtres",
-       "rcfilters-filterlist-whatsthis": "Què és això?",
+       "rcfilters-filterlist-whatsthis": "Com funciona això?",
        "rcfilters-highlightbutton-title": "Ressalta els resultats",
        "rcfilters-highlightmenu-title": "Selecciona un color",
        "rcfilters-highlightmenu-help": "Seleccioneu un color per ressaltar la propietat",
        "rcfilters-filter-categorization-description": "Registres de pàgines afegides o suprimides de les categories.",
        "rcfilters-filter-logactions-label": "Accions registrades",
        "rcfilters-filter-logactions-description": "Accions administratives, creacions de comptes, eliminacions de pàgines, càrregues…",
-       "rcfilters-filtergroup-lastRevision": "Darrera revisió",
+       "rcfilters-filtergroup-lastRevision": "Darreres revisions",
        "rcfilters-filter-lastrevision-label": "Darrera revisió",
        "rcfilters-filter-lastrevision-description": "El canvi més recent a una pàgina.",
        "rcfilters-filter-previousrevision-label": "Revisions anteriors",
index e6c038a..b22898c 100644 (file)
        "compare-rev2": "پێداچوونەوەی ٢",
        "compare-submit": "ھەڵسەنگاندن",
        "compare-invalid-title": "ئەم سەردێڕە دەستنیشانت کردووە نادروستە.",
+       "diff-form": "یەک '''فۆرم'''",
        "dberr-problems": "ببورە! ئەم ماڵپەڕە ئێستا خەریک ئەزموونێکی کێشەی تەکنیکیە.",
        "dberr-again": "چەن خولک ڕاوەستە و نوێی بکەوە.",
        "dberr-info": "(ناتوانیت بگەیت بە بنکەدراو: $1)",
        "logentry-rights-rights": "$1 ئەندامێتیی {{GENDER:$6|$3}}ی لە $4 بۆ $5 {{GENDER:$2|گۆڕی}}",
        "logentry-upload-upload": "$1 $3ی {{GENDER:$2|بار کرد}}",
        "logentry-upload-overwrite": "$1 وەشانێکی نوێی $3ی {{GENDER:$2|بار کرد}}",
+       "logentry-managetags-create": "$1 تاگی \"$4\"ی دروست کرد",
        "rightsnone": "(ھیچ)",
        "feedback-back": "گەڕانەوە",
        "feedback-cancel": "ھەڵوەشاندنەوە",
index ac75826..a4b923f 100644 (file)
        "rcfilters-restore-default-filters": "Obnovit výchozí filtry",
        "rcfilters-clear-all-filters": "Zrušit všechny filtry",
        "rcfilters-show-new-changes": "Zobrazit nejnovější změny",
-       "rcfilters-previous-changes-label": "Dříve prohlédnuté změny",
        "rcfilters-search-placeholder": "Filtrovat nedávné změny (prohlížejte nebo začněte psát)",
        "rcfilters-invalid-filter": "Neplatný filtr",
        "rcfilters-empty-filter": "Žádné aktivní filtry. Zobrazeny jsou všechny příspěvky.",
index 890d933..85449b7 100644 (file)
        "page_last": "olaf",
        "histlegend": "Cymharu dau fersiwn: marciwch y cylchoedd ar y ddau fersiwn i'w cymharu, yna pwyswch ar 'return' neu'r botwm 'Cymharer y fersiynau dewisedig'.<br />\nEglurhad: '''({{int:cur}})''' = gwahaniaethau rhyngddo a'r fersiwn cyfredol,\n'''({{int:last}})''' = gwahaniaethau rhyngddo a'r fersiwn cynt, '''({{int:minoreditletter}})''' = golygiad bychan",
        "history-fieldset-title": "Chwilio drwy'r hanes",
-       "history-show-deleted": "Y rhai a ddilëwyd yn unig",
+       "history-show-deleted": "Yr ddalen a adolygwyd yn unig a ddilëwyd",
        "histfirst": "cynharaf",
        "histlast": "diweddaraf",
        "historysize": "({{PLURAL:$1|$1 beit|$1 beit|$1 feit|$1 beit|$1 beit|$1 beit}})",
        "apihelp-no-such-module": "Ni chafwyd hyd i fodiwl \"$1\".",
        "apisandbox": "Pwll tywod API",
        "apisandbox-fullscreen": "Ehangu'r panel",
+       "apisandbox-fullscreen-tooltip": "Engangu'r blwch tywod i lenwi ffenest y porwr",
        "apisandbox-unfullscreen": "Dangos y ddalen",
+       "apisandbox-unfullscreen-tooltip": "Lleihau'r blwch tywod, er mwyn gweld y dolennau fforio (''navigation links'')",
        "apisandbox-submit": "Gwnewch gais",
        "apisandbox-reset": "Clirio",
        "apisandbox-retry": "Ailgeisio",
        "apisandbox-helpurls": "Dolennau cymorth",
        "apisandbox-examples": "Engreifftiau",
+       "apisandbox-dynamic-parameters": "Paramedrau ychwanegol",
+       "apisandbox-dynamic-parameters-add-label": "Ychwanegu paramedrau",
+       "apisandbox-dynamic-parameters-add-placeholder": "Enw'r paramedr",
        "apisandbox-results": "Canlyniadau",
        "apisandbox-continue": "Parhau",
        "apisandbox-continue-clear": "Clirio",
        "lockedbyandtime": "(gan {{GENDER:$1|$1}} at $2 am $3)",
        "move-page": "Symud $1",
        "move-page-legend": "Symud tudalen",
-       "movepagetext": "Drwy ddefnyddio'r ffurflen isod, byddwch yn ailenwi tudalen, ac felly yn symud ei holl hanes i'r dudalen a'r enw newydd.\nCaiff y dudalen a'r hen deitl ei throi'n dudalen sy'n ailgyfeirio i'r teitl newydd.\nGallwch ddiweddaru tudalennau ailgyfeirio sy'n cyfeirio at y teitl gwreiddiol yn awtomatig.\nOs ydych yn dewis peidio â gwneud hyn, gwiriwch [[Special:DoubleRedirects|dudalennau ailgyfeirio dwbl]] neu \n[[Special:BrokenRedirects|dudalennau ailgyfeirio nad ydynt yn ailgyfeirio]].\nChi sy'n gyfrifol am sicrhau bod cysylltiadau yn cyfeirio at y tudalennau cywir.\n\nSylwer '''na''' chaiff y dudalen ei symud os oes tudalen a'r enw newydd ar gael yn barod, oni bai bod y dudalen a'r enw newydd yn dudalen ailgyfeirio ac nad oes hanes golygu ganddi.\nMae hyn yn golygu y gallwch ailenwi tudalen yn ôl i'w henw gwreiddiol os ydych yn gwneud camgymeriad, ond na allwch drosysgrifo tudalen sy'n bodoli'n barod.\n\n'''Rhybudd!'''\nGall hwn fod yn newid mawr ac annisgwyl i dudalen boblogaidd;\ngwnewch yn siŵr eich bod yn deall canlyniadau'r broses hon cyn i chi barhau.",
+       "movepagetext": "Drwy ddefnyddio'r ffurflen isod, byddwch yn ailenwi dalen, ac felly yn symud ei holl hanes i'r ddalen a'r enw newydd.\nCaiff y ddalen a'r hen deitl ei throi'n ddalen sy'n ailgyfeirio i'r teitl newydd.\nGallwch ddiweddaru dalennau ailgyfeirio sy'n cyfeirio at y teitl gwreiddiol yn awtomatig.\nOs ydych yn dewis peidio â gwneud hyn, gwiriwch [[Special:DoubleRedirects|dudalennau ailgyfeirio dwbl]] neu \n[[Special:BrokenRedirects|ddalennau ailgyfeirio nad ydynt yn ailgyfeirio]].\nChi sy'n gyfrifol am sicrhau bod cysylltiadau yn cyfeirio at y dalennau cywir.\n\nSylwer <strong>na</strong> chaiff y ddalen ei symud os oes tudalen a'r enw newydd ar gael yn barod, oni bai bod y dudalen a'r enw newydd yn dudalen ailgyfeirio ac nad yw wedi'i golygu.\n\nGallwch, felly, ailenwi tudalen yn ôl i'w henw gwreiddiol os ydych yn gwneud camgymeriad, ond na allwch drosysgrifo dalen sy'n bodoli'n barod.\n\n'''Rhybudd!'''\nGall hwn fod yn newid mawr ac annisgwyl i dudalen boblogaidd;\ngwnewch yn siŵr eich bod yn deall canlyniadau'r broses hon cyn i chi barhau.",
        "movepagetext-noredirectfixer": "Wrth ddefnyddio'r ffurflen isod byddwch yn ail-enwi tudalen, gan symud ei hanes gyfan i'r enw newydd.\nBydd yr hen deitl yn troi'n dudalen ailgyfeirio i'r teitl newydd.\nByddwch gystal â thrwsio [[Special:DoubleRedirects|ailgyfeiriadau dwbl]] ac [[Special:BrokenRedirects|ailgyfeiriadau tor]].\nEich cyfrifoldeb chi yw sicrhau bod cysylltiadau wici'n dal i arwain at y man iawn.\n\nSylwch '''na fydd''' y dudalen yn symud os oes yna dudalen o'r enw newydd ar gael yn barod (heblaw ei bod hi'n wag neu'n ailgyfeiriad heb unrhyw hanes golygu).\nFelly, os y gwnewch gamgymeriad wrth ail-enwi tudalen dylai fod yn bosibl ei hail-enwi eto ar unwaith wrth yr enw gwreiddiol. \nHefyd, mae'n amhosibl ysgrifennu dros ben tudalen sydd yn bodoli'n barod.\n\n'''Dalier Sylw!'''\nGall hwn fod yn newid sydyn a llym i dudalen boblogaidd;\ngwnewch yn siwr eich bod chi'n deall y canlyniadau cyn mynd ati.",
-       "movepagetalktext": "Bydd y dudalen sgwrs yn symud gyda'r dudalen hon '''onibai:'''\n*bod tudalen sgwrs wrth yr enw newydd yn bodoli'n barod\n*bod y blwch isod heb ei farcio.\n\nOs felly, gallwch symud y dudalen sgwrs neu ei gyfuno ar ôl symud y dudalen ei hun.",
+       "movepagetalktext": "Bydd y ddalen sgwrs yn symud gyda'r ddalen hon '''onibai:'''\n*bod dalen sgwrs wrth yr enw newydd yn bodoli'n barod\n*bod y blwch isod heb ei farcio.\n\nOs felly, gallwch symud y ddalen sgwrs neu ei gyfuno ar ôl symud y ddalen ei hun.",
        "moveuserpage-warning": "'''Sylwer:''' Yr ydych ar fin symud tudalen defnyddiwr. Sylwch mai'r dudalen yn unig a gaiff ei symud ac ''na fydd'' y defnyddiwr yn cael ei ail-enwi.",
        "movecategorypage-warning": "<strong>Rhybudd:</strong> Rydych ar fin dileu categori. Sylwch mai dim ond y dudalen a gaiff ei symud, a bydd y tudalennau o fewn yr hen gategori yn aros fel ag yr oeddent.",
        "movenologintext": "Mae'n rhaid bod yn ddefnyddiwr cofrestredig a'ch bod wedi [[Special:UserLogin|mewngofnodi]] cyn medru symud tudalen.",
        "cant-move-to-user-page": "Nid yw'r gallu ganddoch i symud tudalen i dudalen defnyddiwr (heblaw am i isdudalen defnyddiwr).",
        "cant-move-category-page": "Nid oes gennych yr hawl i symud categoriau.",
        "cant-move-to-category-page": "Nid oes gennych yr hawl i droi tudalen yn gategori.",
+       "cant-move-subpages": "Nid oes gennych yr hawl i symud isddalennau.",
        "newtitle": "Teitl newydd:",
        "move-watch": "Gwylier y dudalen hon",
        "movepagebtn": "Symud y dudalen",
        "movenosubpage": "Nid oes isdudalennau i gael i'r dudalen hon.",
        "movereason": "Rheswm:",
        "revertmove": "symud nôl",
-       "delete_and_move_text": "==Angen dileu==\n\nMae'r erthygl \"[[:$1]]\" yn bodoli'n barod. Ydych chi am ddileu'r erthygl er mwyn cwblhau'r symudiad?",
+       "delete_and_move_text": "==Angen dileu==\n\nMae'r erthygl \"[[:$1]]\" yn bodoli'n barod. Ydych chi am ddileu'r erthygl er mwyn paratoi lle?",
        "delete_and_move_confirm": "Ie, dileu'r dudalen",
        "delete_and_move_reason": "Wedi'i dileu er mwyn gallu symud y dudalen \"[[$1]]\" i gymryd ei lle",
        "selfmove": "Mae'r teitlau hen a newydd yn union yr un peth;\nnid yw'n bosib cyflawnu'r symud.",
        "move-leave-redirect": "Creu tudalen ail-gyfeirio â'r teitl gwreiddiol",
        "protectedpagemovewarning": "'''Sylwer:''' Clowyd y dudalen ac felly dim ond defnyddwyr a galluoedd gweinyddu ganddynt sy'n gallu ei symud.\nDyma'r cofnod lòg diweddaraf, er gwybodaeth:",
        "semiprotectedpagemovewarning": "'''Sylwer:''' Clowyd y dudalen ac felly dim ond defnyddwyr mewngofnodedig sy'n gallu ei symud.\nDyma'r cofnod lòg diweddaraf, er gwybodaeth:",
-       "move-over-sharedrepo": "== Y ffeil ar gael ==\nMae'r ffeil [[:$1]] ar gael mewn storfa gyfrannol. Pe byddech yn symud y ffeil i'r teitl hwn, yna byddai'r ffeil o'r storfa gyfrannol yn cael ei disodli.",
+       "move-over-sharedrepo": "Mae'r ffeil [[:$1]] ar gael mewn storfa gyfrannol. Pe byddech yn symud y ffeil i'r teitl hwn, yna byddai'r ffeil o'r storfa gyfrannol yn cael ei disodli.",
        "file-exists-sharedrepo": "Mae'r enw y dewisoch ar y ffeil yn cael ei ddefnyddio'n barod ar storfa gyfrannol.\nDewiswch enw arall os gwelwch yn dda.",
        "export": "Allforio tudalennau",
        "exporttext": "Gallwch allforio testun a hanes golygu tudalen penodol neu set o dudalennau wedi'u lapio mewn côd XML. Gall hwn wedyn gael ei fewnforio i wici arall sy'n defnyddio meddalwedd MediaWiki, trwy ddefnyddio'r [[Special:Import|dudalen mewnforio]].\n\nI allforio tudalennau, teipiwch y teitlau yn y bocs testun isod, bobi linell i'r teitlau; a dewis p'un ai ydych chi eisiau'r diwygiad presennol a'r holl fersiynnau blaenorol, gyda hanes y dudalen; ynteu a ydych am y diwygiad presennol a'r wybodaeth am y golygiad diweddaraf yn unig.\n\nYn achos yr ail ddewis, mae modd defnyddio cyswllt, e.e. [[{{#Special:Export}}/{{MediaWiki:Mainpage}}]] ar gyfer y dudalen \"[[{{MediaWiki:Mainpage}}]]\".",
        "import-nonewrevisions": "Ni fewnforwyd unrhyw ddiwygiadau (y cwbl eisoes yn bresennol, neu wedi eu hepgor oherwydd eu bod yn wallus).",
        "xml-error-string": "$1 ar linell $2, col $3 (beit $4): $5",
        "import-upload": "Uwchlwytho data XML",
-       "import-token-mismatch": "Collwyd y data.\n\nEfallai i chi allgofnodi (logio allan).<strong>Cadarnhewch eich bod yn dal wedi mewngofnodi a cheisiwch eto</strong>\nOs yw'n parhau i fethu, ceisiwch [[Special:UserLogout|allgofnodi]] a mewngofnodwch drachefn, a gwirwch fod eich porwr yn caniatau cwcis o'r wefan hon.",
+       "import-token-mismatch": "Collwyd y data.\n\nEfallai i chi allgofnodi. '''Cadarnhewch eich bod yn dal wedi mewngofnodi a cheisiwch eto'''.\nOs yw'n parhau i fethu, ceisiwch [[Special:UserLogout|allgofnodi]] a mewngofnodwch drachefn, a gwirwch fod eich porwr yn caniatau cwcis o'r wefan hon.",
        "import-invalid-interwiki": "Ni ellir uwchlwytho o'r wici dewisedig.",
        "import-error-edit": "Ni fewnforiwyd y dudalen \"$1\" oherwydd nad yw'r gallu i'w golygu gennych.",
        "import-error-create": "Ni fewnforiwyd y dudalen \"$1\" oherwydd nad yw'r hawl i'w chreu gennych.",
        "tooltip-pt-preferences": "Eich dewisiadau",
        "tooltip-pt-watchlist": "Rydych yn dilyn hynt y tudalennau sydd ar y rhestr hon",
        "tooltip-pt-mycontris": "Rhestr o'ch cyfraniadau",
+       "tooltip-pt-anoncontribs": "Rhestr golygiadau o'r cyfeiriad IP hwn",
        "tooltip-pt-login": "Fe'ch anogir i fewngofnodi, er nad oes rhaid gwneud.",
+       "tooltip-pt-login-private": "Mae'n rhaid i chi fewngofnodi i ddefnyddio'r wici hwn",
        "tooltip-pt-logout": "Allgofnodi",
        "tooltip-pt-createaccount": "Rydym yn argymell eich bod yn creu cyfri ac yn menwgofnodi. Fodd bynnag, dydy hyn ddim yn orfodol",
        "tooltip-ca-talk": "Sgwrsio am y dudalen",
        "lastmodifiedatby": "Newidiwyd y dudalen hon ddiwethaf am $2, $1 gan $3.",
        "othercontribs": "Yn seiliedig ar waith gan $1.",
        "others": "eraill",
-       "siteusers": "y {{PLURAL:$2|defnyddiwr|defnyddiwr|defnyddwyr|defnyddwyr|defnyddwyr|defnyddwyr}} {{SITENAME}} $1",
+       "siteusers": "{{SITENAME}} {{PLURAL:$2|{{GENDER:$1|defnyddiwr}}|defnyddwyr}} $1",
        "anonusers": "{{PLURAL:$2|defnyddiwr|defnyddiwr|defnyddwyr|defnyddwyr|defnyddwyr|defnyddwyr}} {{SITENAME}} anhysbys $1",
        "creditspage": "Cydnabyddiaethau'r dudalen",
        "nocredits": "Does dim cydnabyddiaethau i'r dudalen hon.",
        "pageinfo-length": "Hyd y dudalen (beitiau)",
        "pageinfo-article-id": "ID y dudalen",
        "pageinfo-language": "Iaith cynnwys y dudalen",
+       "pageinfo-language-change": "newid",
        "pageinfo-content-model": "Ffurf cynnwys y dudalen",
+       "pageinfo-content-model-change": "newid",
        "pageinfo-robot-policy": "Rhestrwyd gan robot",
        "pageinfo-robot-index": "Caniateir",
        "pageinfo-robot-noindex": "Gwrthodedig",
        "pageinfo-watchers": "Nifer gwylwyr y dudalen",
+       "pageinfo-visiting-watchers": "Nifer y golygyddion sy'n gwylio'r ddalen, sydd hefyd wedi ymweld a'r golygiadau diweddaraf",
        "pageinfo-few-watchers": "Llai na $1 {{PLURAL:$1|gwyliwr|gwyliwr|wyliwr|gwyliwr|o wylwyr}}",
        "pageinfo-redirects-name": "Nifer yr ailgyfeiriadau i'r dudalen hon",
        "pageinfo-subpages-name": "Nifer yr is-dudalennau i'r dudalen hon",
        "pageinfo-protect-cascading-yes": "Oes",
        "pageinfo-protect-cascading-from": "Mae'r diogelu sgydol yn dechrau ar",
        "pageinfo-category-info": "Gwybodaeth am y categori",
+       "pageinfo-category-total": "Cyfanswm yr aelodau",
        "pageinfo-category-pages": "Nifer y tudalennau",
        "pageinfo-category-subcats": "Nifer yr is-gategorïau",
        "pageinfo-category-files": "Nifer y ffeiliau",
+       "pageinfo-user-id": "ID'r defnyddiwr",
        "markaspatrolleddiff": "Marcio ei bod wedi derbyn ymweliad patrôl",
        "markaspatrolledtext": "Marcio bod y dudalen wedi derbyn ymweliad patrôl",
        "markaspatrolledtext-file": "Marcio fod fersiwn y ffeil wedi cael ymweliad",
        "patrol-log-page": "Lòg patrolio",
        "patrol-log-header": "Mae'r lòg hwn yn dangos y golygiadau sydd wedi derbyn ymweliad patrôl.",
        "log-show-hide-patrol": "$1 lòg patrolio",
+       "confirm-markpatrolled-button": "Iawn",
+       "confirm-markpatrolled-top": "Nodi fod diwygiad $3 o $2 wedi cael sêl-bendith golygydd?",
        "deletedrevision": "Wedi dileu hen ddiwygiad $1.",
        "filedeleteerror-short": "Gwall wrth ddileu'r ffeil: $1",
        "filedeleteerror-long": "Cafwyd gwallau wrth ddileu'r ffeil:\n\n$1",
        "svg-long-error": "Ffeil SVG annilys: $1",
        "show-big-image": "Y ffeil gwreiddiol",
        "show-big-image-preview": "Maint y rhagolwg: $1.",
+       "show-big-image-preview-differ": "Maint rhagolwg $3 o ffeil $2 yw: $1.",
        "show-big-image-other": "{{PLURAL:$2|Datrysiad arall|Datrysiad arall|Datrysiadau eraill|Datrysiadau eraill|Datrysiadau eraill|Datrysiadau eraill}}: $1.",
        "show-big-image-size": "$1 × $2 picsel",
        "file-info-gif-looped": "dolennog",
        "newimages-summary": "Mae'r dudalen arbennig hon yn dangos y ffeiliau a uwchlwythwyd yn ddiweddar.",
        "newimages-legend": "Hidlo",
        "newimages-label": "Enw'r ffeil (neu ran ohono):",
+       "newimages-user": "Cyfeiriad IP neu enw defnyddiwr",
+       "newimages-newbies": "Dangos cyfraniadau cyfrifon newydd yn unig",
        "newimages-showbots": "Dangoswch uwchlwythiadau'r botiaid",
+       "newimages-hidepatrolled": "Cuddio uwchlwythiadau gwaith a ddilyswyd gan olygydd profiadol",
+       "newimages-mediatype": "Math o gyfrwng:",
        "noimages": "Does dim byd i'w weld.",
+       "gallery-slideshow-toggle": "Toglwch y cipluniau",
        "ilsubmit": "Chwilio",
        "bydate": "yn ôl dyddiad",
        "sp-newimages-showfrom": "Dangos ffeiliau sy'n newydd ers: $2, $1",
        "exif-compression-4": "Amgodio ffacs Grŵp 4 CCITT",
        "exif-copyrighted-true": "Hawlfraint",
        "exif-copyrighted-false": "Statws yr hawlfraint heb ei osod",
+       "exif-photometricinterpretation-1": "Du a gwyn (du yw 0)",
        "exif-unknowndate": "Dyddiad anhysbys",
        "exif-orientation-1": "Normal",
        "exif-orientation-2": "Wedi troi tu chwith ar lorwedd",
        "confirmemail_body_set": "Mae rhywun (chi, yn fwy na thebyg, o'r cyfeiriad IP $1) wedi gosod cyfeiriad e-bost y cyfrif \"$2\" ar {{SITENAME}} i'r cyfeiriad e-bost hwn.\n\nI gadarnhau mai chi yn wir yw perchennog y cyfrif hwn, ac i alluogi nodweddion e-bost ar {{SITENAME}}, agorwch y cyswllt hwn yn eich porwr:\n\n$3\n\nOs *nad* chi sydd berchen y cyfrif hwn, dilynwch y cyswllt hwn er mwyn diddymu cadarnhad y cyfeiriad e-bost:\n\n$5\n\nBydd y côd cadarnhau yn dod i ben am $4.",
        "confirmemail_invalidated": "Diddymwyd y weithred o gadarnhau'r cyfeiriad e-bost",
        "invalidateemail": "Diddymu cadarnhad y cyfeiriad e-bost.",
+       "notificationemail_subject_changed": "Mae cyfeiriad ebost {{SITENAME}} wedi'i newid",
+       "notificationemail_subject_removed": "Mae cyfeiriad ebost {{SITENAME}} wedi'i ddileu",
+       "notificationemail_body_changed": "Mae rhywun, efallai chi, o gyfeiriad IP $1,\nwedi newid cyfeiriad ebost cyfrif \"$2\" i \"$3\" ar {{SITENAME}}.\n\nOs nad y chi sy'n gyfrifol am hyn, yna cysylltwch ag un o'r Gweinyddwyr ar unwaith.",
+       "notificationemail_body_removed": "Mae rhywun, efallai chi, o gyfeiriad IP $1,\nwedi dileu cyfeiriad ebost cyfrif \"$2\" ar {{SITENAME}}.\n\nOs nad y chi sy'n gyfrifol am hyn, yna cysylltwch ag un o'r Gweinyddwyr ar unwaith.",
        "scarytranscludedisabled": "[Analluogwyd cynhwysiad rhyng-wici]",
        "scarytranscludefailed": "[Methwyd nôl y nodyn ar gyfer $1]",
        "scarytranscludefailed-httpstatus": "[Methwyd nôl y nodyn ar gyfer $1: HTTP $2]",
        "scarytranscludetoolong": "[Mae'r URL yn rhy hir]",
        "deletedwhileediting": "'''Rhybudd''': Dilëwyd y dudalen wedi i chi ddechrau ei golygu!",
-       "confirmrecreate": "Mae'r defnyddiwr [[User:$1|$1]] ([[User talk:$1|Sgwrs]]) wedi dileu'r dudalen hon ers i chi ddechrau ei golygu. Y rheswm a roddwyd yw:\n: ''$2''\nCadarnhewch eich bod chi wir am ail-greu'r dudalen.",
-       "confirmrecreate-noreason": "Dileodd y defnyddiwr [[User:$1|$1]] ([[User talk:$1|sgwrs]]) y dudalen hon wedi i chi ddechrau ei golygu. Cadarnhewch eich bod chi wir am ail-greu'r dudalen hon.",
+       "confirmrecreate": "Mae defnyddiwr [[User:$1|$1]] ([[User talk:$1|Sgwrs]]) wedi dileu'r ddalen hon ers i chi ddechrau ei golygu. Y rheswm a roddwyd yw:\n: <em>$2</em>\nCadarnhewch eich bod chi am ail-greu'r dudalen.",
+       "confirmrecreate-noreason": "Dileodd y defnyddiwr [[User:$1|$1]] ([[User talk:$1|sgwrs]]) y ddalen hon wedi i chi ddechrau ei golygu. Cadarnhewch eich bod chi am ail-greu'r ddalen hon.",
        "recreate": "Ail-greu",
        "confirm-purge-title": "Ailgyrchu'r ddalen",
        "confirm_purge_button": "Iawn",
        "timezone-local": "Lleol",
        "duplicate-defaultsort": "Rhybudd: Mae'r allwedd trefnu diofyn \"$2\" yn gwrthwneud yr allwedd trefnu diofyn blaenorol \"$1\".",
        "duplicate-displaytitle": "<strong>Gofal:</strong> Mae arddangos \"$2\" yn clirio'r arddangosiadau cynharach \"$1\".",
+       "restricted-displaytitle": "<strong>Rhybudd:</strong> Mae'n rhaid i'r teitl a anrddangosir \"$1\" fod yn hafal i union deitl y ddalen; anwybyddwyd y cais i'w newid.",
        "invalid-indicator-name": "<strong>Gan bwyll:</strong> Ni ddylid gadael y man nodi statws  <code>name</code> yn wag.",
        "version": "Fersiwn",
        "version-extensions": "Estyniadau gosodedig",
        "redirect-page": "ID tudalennau",
        "redirect-revision": "Rhifau diwygiadau tudalennau",
        "redirect-file": "Enwau ffeiliau",
+       "redirect-logid": "Log yr ID",
        "redirect-not-exists": "Heb lwyddo i'w ganfod",
        "fileduplicatesearch": "Chwilio am ffeiliau dyblyg",
        "fileduplicatesearch-summary": "Chwilier am ffeiliau dyblyg ar sail ei werth stwnsh.",
        "fileduplicatesearch-noresults": "Ni ddaethpwyd o hyd i ffeil o'r enw \"$1\".",
        "specialpages": "Tudalennau arbennig",
        "specialpages-note-top": "Allwedd",
+       "specialpages-note-restricted": "* Tudalennau arbennig agored.\n* <span class=\"mw-specialpagerestricted\">Tudalennau arbennig a gyfyngir.</span>",
        "specialpages-group-maintenance": "Adroddiadau cynnal a chadw",
        "specialpages-group-other": "Eraill",
        "specialpages-group-login": "Mewngofnodi / creu cyfrif",
        "tags-create-reason": "Rheswm:",
        "tags-create-submit": "Dechrau",
        "tags-create-no-name": "Mae'n rhaid nodi tag enw.",
+       "tags-create-already-exists": "Mae tag \"$1\" yn bodoli'n barod.",
+       "tags-delete-title": "Dileu tag",
        "comparepages": "Cymharu tudalennau",
        "compare-page1": "Tudalen 1",
        "compare-page2": "Tudalen 2",
        "feedback-bugornote": "Os ydych yn barod i ddisgrifio problem technegol yn fanwl gallwch [$1 gyflwyno adroddiad am y bỳg]. Fel arall, gallwch ddefnyddio'r ffurflen syml isod. Fe roddir eich sylwadau ar y dudalen \"[$3 $2]\", ynghyd â'ch enw defnyddiwr ac enw'r gweinydd sydd ar waith gennych.",
        "feedback-cancel": "Diddymer",
        "feedback-close": "Yn barod",
+       "feedback-dialog-title": "Rhowch adborth",
        "feedback-error1": "Gwall: Canlyniad anhysbys o'r API",
        "feedback-error2": "Gwall: Methodd y golygu",
        "feedback-error3": "Gwall: Dim ymateb gan yr API",
        "special-characters-title-endash": "heiffen en",
        "special-characters-title-emdash": "heiffen em",
        "special-characters-title-minus": "arwydd minws",
+       "mw-widgets-dateinput-no-date": "Ni ddewisiwyd dyddiad",
        "mw-widgets-dateinput-placeholder-day": "BBBB-MM-DD",
        "mw-widgets-dateinput-placeholder-month": "BBBB-MM",
+       "mw-widgets-mediasearch-input-placeholder": "Chwiliwch am gyfryngau",
+       "mw-widgets-mediasearch-noresults": "Dim canlyniad.",
+       "mw-widgets-titleinput-description-new-page": "nid yw'r ddalen wedi'i chreu eto",
+       "mw-widgets-titleinput-description-redirect": "ailgyfeiriwyd i $1",
        "mw-widgets-categoryselector-add-category-placeholder": "Ychwanega gategori...",
        "mw-widgets-usersmultiselect-placeholder": "Ychwanega ragor...",
        "date-range-from": "O'r dyddiad:",
        "log-action-filter-block-reblock": "Newid y bloc",
        "log-action-filter-block-unblock": "Dadflocio",
        "log-action-filter-delete-delete": "Dileu dalennau",
+       "authmanager-retype-help": "Rhowch eich cyfrinair eto, i gadarnhau.",
        "authmanager-email-label": "Ebost",
        "authmanager-email-help": "Cyfeiriadau ebyst",
        "authmanager-realname-label": "Enw cywir",
        "authmanager-realname-help": "Enw cywir y defnyddiwr",
+       "authmanager-provider-temporarypassword": "Cyfrinair dros-dro",
        "credentialsform-account": "Enw'r cyfri:"
 }
index 8b1f023..59c3b26 100644 (file)
        "rcfilters-restore-default-filters": "Standardfilter wiederherstellen",
        "rcfilters-clear-all-filters": "Alle Filter löschen",
        "rcfilters-show-new-changes": "Neueste Änderungen ansehen",
-       "rcfilters-previous-changes-label": "Zuletzt angesehene Änderungen",
        "rcfilters-search-placeholder": "Letzte Änderungen filtern (durchsuchen oder beginne mit der Eingabe)",
        "rcfilters-invalid-filter": "Ungültiger Filter",
        "rcfilters-empty-filter": "Keine aktiven Filter. Es werden alle Beiträge angezeigt.",
index 223cff4..3497d80 100644 (file)
        "rcfilters-filterlist-noresults": "No filters found",
        "rcfilters-noresults-conflict": "No results found because the search criteria are in conflict",
        "rcfilters-state-message-subset": "This filter has no effect because its results are included with those of the following, broader {{PLURAL:$2|filter|filters}} (try highlighting to distinguish it): $1",
-       "rcfilters-state-message-fullcoverage": "Selecting all filters in a group is the same as selecting none, so this filter has no effect. Group includes: $1",
+       "rcfilters-state-message-fullcoverage": "Selecting all filters in this group is the same as selecting none, so this filter has no effect. Group includes: $1",
        "rcfilters-filtergroup-authorship": "Contribution authorship",
        "rcfilters-filter-editsbyself-label": "Changes by you",
        "rcfilters-filter-editsbyself-description": "Your own contributions.",
index c67bf08..07e100c 100644 (file)
        "rcfilters-activefilters": "Aktiivsed filtrid",
        "rcfilters-advancedfilters": "Täpsemad filtrid",
        "rcfilters-limit-title": "Näita nii mitut muudatust",
-       "rcfilters-limit-shownum": "Näita viimast {{PLURAL:$1|$1}} muudatust",
+       "rcfilters-limit-shownum": "Näita viimast $1 muudatust",
        "rcfilters-days-title": "Viimased päevad",
        "rcfilters-hours-title": "Viimased tunnid",
        "rcfilters-days-show-days": "$1 {{PLURAL:$1|päev|päeva}}",
        "rcfilters-restore-default-filters": "Taasta vaikefiltrid",
        "rcfilters-clear-all-filters": "Eemalda kõik filtrid",
        "rcfilters-show-new-changes": "Vaata uusimaid muudatusi",
-       "rcfilters-previous-changes-label": "Varem vaadatud muudatused",
        "rcfilters-search-placeholder": "Filtri viimaseid muudatusi (sirvi või alusta tippimist)",
        "rcfilters-invalid-filter": "Vigane filter",
        "rcfilters-empty-filter": "Aktiivsed filtrid puuduvad. Näidatakse kogu kaastööd.",
index 1afd0c0..60cbd83 100644 (file)
        "nospecialpagetext": "<strong>شما یک صفحهٔ ویژهٔ نامجاز را درخواست کرده‌اید.</strong>\n\nفهرستی از صفحه‌های ویژهٔ مجاز در [[Special:SpecialPages|{{int:specialpages}}]] وجود دارد.",
        "error": "خطا",
        "databaseerror": "خطای پایگاه داده",
-       "databaseerror-text": "مشکلی در پایگاه‌داده‌ها رخ داد. \nاین ممکن است نشان‌دهندهٔ ایرادی در نرم‌افزار باشد.",
+       "databaseerror-text": "مشکلی در پایگاه‌های داده رخ داد. \nاین ممکن است نشان‌دهندهٔ ایرادی در نرم‌افزار باشد.",
        "databaseerror-textcl": "یک خطا در پرسمان پایگاه داده رخ داد.",
        "databaseerror-query": "پرسمان: $1",
        "databaseerror-function": "تابع: $1",
        "right-mergehistory": "ادغام تاریخچهٔ صفحات",
        "right-userrights": "ویرایش تمام اختیارات کاربرها",
        "right-userrights-interwiki": "ویرایش اختیارات کاربرهای ویکی‌های دیگر",
-       "right-siteadmin": "قفل‌کردن و بازکردن پایگاه داده‌ها",
+       "right-siteadmin": "قفل‌کردن و بازکردن پایگاه‌های داده",
        "right-override-export-depth": "برون‌بری صفحه‌ها شامل صفحه‌های پیوند شده تا عمق ۵",
        "right-sendemail": "ارسال ایمیل به دیگر کاربران",
        "right-managechangetags": "ایجاد و غیرفعال کردن [[Special:Tags|برچسب‌ها]]",
        "action-mergehistory": "ادغام تاریخچهٔ این صفحه",
        "action-userrights": "ویرایش همهٔ اختیارات کاربری",
        "action-userrights-interwiki": "ویرایش اختیارات کاربری کاربران یک ویکی دیگر",
-       "action-siteadmin": "قفل‌کردن و بازکردن پایگاه داده‌ها",
+       "action-siteadmin": "قفل‌کردن و بازکردن پایگاه‌های داده",
        "action-sendemail": "ارسال ایمیل",
        "action-editmyoptions": "ویرایش ترجیحاتتان",
        "action-editmywatchlist": "فهرست پیگیری‌های خود را ویرایش کنید",
        "rcfilters-restore-default-filters": "بازگردانی پالایه‌های پیش‌فرض",
        "rcfilters-clear-all-filters": "پاک‌کردن تمام پالایه‌ها",
        "rcfilters-show-new-changes": "دیدن جدیدترین تغییرات",
-       "rcfilters-previous-changes-label": "تغییرات قبلاً دیده شده",
        "rcfilters-search-placeholder": "پالایش تغییرات اخیر (جستجو یا شروع به تایپ)",
        "rcfilters-invalid-filter": "پالایهٔ نامعتبر",
        "rcfilters-empty-filter": "پالایه‌ای فعال نیست. همهٔ مشارکت‌های دیده می‌شوند.",
        "delete-legend": "حذف",
        "historywarning": "<strong>هشدار:</strong> صفحه‌ای که در حال پاک کردن آن هستید دارای یک تاریخچه همراه با $1 {{PLURAL:$1|بازبینی|بازبینی}} است:",
        "historyaction-submit": "نمایش",
-       "confirmdeletetext": "شما در حال حذف کردن یک صفحه یا تصویر از پایگاه داده‌ها همراه با تمام تاریخچهٔ آن هستید.\nلطفاً این عمل را تأیید کنید و اطمینان حاصل کنید که عواقب این کار را می‌دانید و این عمل را مطابق با [[{{MediaWiki:Policy-url}}|سیاست‌ها]] انجام می‌دهید.",
+       "confirmdeletetext": "شما در حال حذف کردن یک صفحه یا تصویر از پایگاه‌های داده همراه با تمام تاریخچهٔ آن هستید.\nلطفاً این عمل را تأیید کنید و اطمینان حاصل کنید که عواقب این کار را می‌دانید و این عمل را مطابق با [[{{MediaWiki:Policy-url}}|سیاست‌ها]] انجام می‌دهید.",
        "actioncomplete": "عمل انجام شد",
        "actionfailed": "عمل ناموفق بود",
        "deletedtext": "«$1» حذف شد.\nبرای سابقهٔ حذف‌های اخیر به $2 مراجعه کنید.",
index 1b93fde..80ff2e5 100644 (file)
        "rcfilters-restore-default-filters": "Rétablir les filtres par défaut",
        "rcfilters-clear-all-filters": "Effacer tous les filtres",
        "rcfilters-show-new-changes": "Afficher les modifications les plus récentes",
-       "rcfilters-previous-changes-label": "Modifications précédemment affichées",
        "rcfilters-search-placeholder": "Filtrer les modifications récentes (naviguer ou commencer à saisir)",
        "rcfilters-invalid-filter": "Filtre non valide",
        "rcfilters-empty-filter": "Aucun filtre actif. Toutes les contributions sont affichées.",
index f2fe856..8802a8e 100644 (file)
        "excontentauthor": "Diar sted: „$1“, an di iansagst bewerker wiar: [[Special:Contributions/$2|$2]] ([[User talk:$2|Diskuschuun]])",
        "exbeforeblank": "diar sted föör't leesag maagin: „$1“",
        "delete-confirm": "Strik \"$1\"",
-       "delete-legend": "Strike",
+       "delete-legend": "Strik",
        "historywarning": "<strong>Paase üüb:</strong> Det sidj, wat dü strik wel, hää $1 {{PLURAL:$1|werjuun|werjuunen}}:",
        "confirmdeletetext": "Dü wel en sidj mä aal sin werjuunen strik. Dü skel gudkään, dat dü witjst, wat dü dääst an dat din dun mä a [[{{MediaWiki:Policy-url}}|brükerreegeln]] auerian stemet.",
        "actioncomplete": "Klaar",
index 78c96e0..0278da5 100644 (file)
@@ -61,6 +61,7 @@
        "tog-watchlisthideminor": "Agochar as edicións pequenas na lista de vixilancia",
        "tog-watchlisthideliu": "Agochar as edicións dos usuarios rexistrados na lista de vixilancia",
        "tog-watchlistreloadautomatically": "Recargar a lista de vixilancia automaticamente cando se produza un cambio nun filtro (necesítase JavaScript)",
+       "tog-watchlistunwatchlinks": "Engadir ligazóns directos para vixiar ou deixar de vixiar as entradas da lista de páxinas vixiadas (é necesario JavaScript para activar a funcionalidade)",
        "tog-watchlisthideanons": "Agochar as edicións dos usuarios anónimos na lista de vixilancia",
        "tog-watchlisthidepatrolled": "Agochar as edicións patrulladas na lista de vixilancia",
        "tog-watchlisthidecategorization": "Agochar a categorización das páxinas",
        "permissionserrorstext-withaction": "Non ten os permisos necesarios para $2, {{PLURAL:$1|pola seguinte razón|polas seguintes razóns}}:",
        "contentmodelediterror": "Non pode editar esta revisión porque o seu modelo de contido é \"<code>$1</code>\", o cal difire do modelo de contido \"<code>$2</code>\", que é o actual da páxina.",
        "recreate-moveddeleted-warn": "'''Atención: Vai volver crear unha páxina que xa foi eliminada anteriormente.'''\n\nDebería considerar se é apropiado continuar a editar esta páxina.\nVelaquí están o rexistro de borrados e mais o de traslados desta páxina, por se quere consultalos:",
-       "moveddeleted-notice": "Esta páxina foi borrada.\nA continuación pódese ver o rexistro de borrados e traslados desta páxina, por se quere consultalos.",
+       "moveddeleted-notice": "Esta páxina foi borrada.\nO rexistro de borrados, protección e traslados desta páxina amósase abaixo, por se quere consultalos.",
        "moveddeleted-notice-recent": "Sentímolo, borrouse esta páxina recentemente (nas últimas 24 horas).\nVelaquí están o rexistro de borrados, proteccións e traslados da páxina, por se os quere consultar.",
        "log-fulllog": "Ver o rexistro completo",
        "edit-hook-aborted": "A edición foi abortada polo asociador.\nEste non deu ningunha explicación.",
        "rcfilters-restore-default-filters": "Restaurar os filtros por defecto",
        "rcfilters-clear-all-filters": "Borrar todos os filtros",
        "rcfilters-show-new-changes": "Mostrar os cambios máis recentes",
-       "rcfilters-previous-changes-label": "Modificacións vistas anteriormente",
        "rcfilters-search-placeholder": "Filtrar os cambios recentes (ollar ou comezar a escribir)",
        "rcfilters-invalid-filter": "Filtro no válido",
        "rcfilters-empty-filter": "Non hai filtros activos. Móstranse tódalas contribucións.",
index 1242ffd..c317226 100644 (file)
@@ -8,8 +8,7 @@
                        "Sajasazi (on got.wikipedia.org)",
                        "Zylbath",
                        "Espreon",
-                       "Gothicspeaker",
-                       "Ooswesthoesbes"
+                       "Gothicspeaker"
                ]
        },
        "tog-previewontop": "𐌰𐌽𐌳𐌷𐌿𐌻𐌴𐌹 𐍆𐌰𐌿𐍂𐌰𐍃𐌹𐌿𐌽 𐍆𐌰𐌿𐍂𐌰 𐌹𐌽𐌼𐌰𐌹𐌳𐌴𐌹𐌽𐌹𐌰𐍂𐌺𐌰",
        "logentry-move-move": "$1 {{GENDER:$2|𐌼𐌹𐌸𐍃𐌰𐍄𐌹𐌳𐌰}} 𐌻𐌰𐌿𐍆 $3 𐌳𐌿 $4",
        "logentry-newusers-create": "𐌱𐍂𐌿𐌺𐌾𐌰𐌺𐌰𐍅𐍄𐍃𐌾𐍉 $1 𐍅𐌰𐍃 {{{{GENDER:$2|𐌲𐌰𐍃𐌺𐌰𐍀𐌰𐌽𐌰}}",
        "rightsnone": "(𐌽𐌹)",
-       "searchsuggest-search": "𐍃𐍉𐌺𐌴𐌹 {{SITENAME}}"
+       "searchsuggest-search": "𐍃𐍉𐌺𐌴𐌹"
 }
index 1d9f503..6bfcda3 100644 (file)
        "recentchanges-legend-heading": "<strong>કળ:</strong>",
        "recentchanges-legend-newpage": "{{int:recentchanges-label-newpage}} ([[Special:NewPages|નવા પાનાઓની યાદી]] પણ જુઓ)",
        "recentchanges-submit": "બતાવો",
+       "rcfilters-legend-heading": "<strong>સંક્ષેપોની યાદી:</strong>",
        "rcfilters-other-review-tools": "<strong>અન્ય ચકાસણી સાધનો</strong>",
+       "rcfilters-activefilters": "સક્રિય ગાળકો",
+       "rcfilters-limit-title": "દર્શાવવાના ફેરફારો",
+       "rcfilters-limit-shownum": "છેલ્લા {{PLURAL:$1|ફેરફાર|$1 ફેરફારો}} દર્શાવો",
+       "rcfilters-days-title": "તાજેતરના દિવસો",
+       "rcfilters-hours-title": "તાજેતરના કલાકો",
        "rcfilters-savedqueries-cancel-label": "રદ કરો",
+       "rcfilters-show-new-changes": "તાજેતરના ફેરફારો દર્શાવો",
        "rcnotefrom": "નીચે <strong>$3, $4</strong> થી {{PLURAL:$5|ફેરફાર|ફેરફારો}} દર્શાવેલ છે (<strong>$1</strong> સુધી દર્શાવેલ છે).",
        "rclistfrom": "$3 $2 બાદ થયેલા નવા ફેરફારો બતાવો",
        "rcshowhideminor": "નાના ફેરફારો $1",
index a36f13f..1a99d33 100644 (file)
        "rcfilters-restore-default-filters": "שחזור למסנני ברירת המחדל",
        "rcfilters-clear-all-filters": "מחיקת כל המסננים",
        "rcfilters-show-new-changes": "הצגת השינויים החדשים ביותר",
-       "rcfilters-previous-changes-label": "שינויים שהוצגו בעבר",
        "rcfilters-search-placeholder": "סינון שינויים אחרונים (עיינו או התחילו להקליד)",
        "rcfilters-invalid-filter": "מסנן בלתי־תקין",
        "rcfilters-empty-filter": "אין מסננים פעילים. כל התרומות מוצגות.",
        "rcfilters-filterlist-noresults": "לא נמצאו מסננים",
        "rcfilters-noresults-conflict": "לא נמצאו תוצאות משום שקריטריוני החיפוש מתנגשים",
        "rcfilters-state-message-subset": "המסנן הזה אינו משפיע כי התוצאות שלו כלולות {{PLURAL:$2|במסנן הרחב יותר הבא|במסננים הרחבים יותר הבאים}} (נסו להדגיש כדי להבדיל ביניהם): $1",
-       "rcfilters-state-message-fullcoverage": "בחירת כל המסננים בקבוצה זהה לביטול כל הבחירות, אז למסנן הזה אין השפעה. הקבוצה כוללת: $1",
+       "rcfilters-state-message-fullcoverage": "×\91×\97×\99רת ×\9b×\9c ×\94×\9eסננ×\99×\9d ×\91ק×\91×\95צ×\94 ×\96×\95 ×\96×\94×\94 ×\9c×\91×\99×\98×\95×\9c ×\9b×\9c ×\94×\91×\97×\99ר×\95ת, ×\90×\96 ×\9c×\9eסנ×\9f ×\94×\96×\94 ×\90×\99×\9f ×\94שפע×\94. ×\94ק×\91×\95צ×\94 ×\9b×\95×\9c×\9cת: $1",
        "rcfilters-filtergroup-authorship": "מבצעי התרומה",
        "rcfilters-filter-editsbyself-label": "שינויים שלך",
        "rcfilters-filter-editsbyself-description": "תרומות שביצעת בעצמך.",
index 214a764..c33df5a 100644 (file)
        "rcfilters-restore-default-filters": "मूलभूत फिल्टर पुनर्स्थापित करे",
        "rcfilters-clear-all-filters": "सभी फिल्टर हटाएँ",
        "rcfilters-show-new-changes": "नवीनतम बदलाव दिखाएँ",
-       "rcfilters-previous-changes-label": "पिछले देखे बदलाव",
        "rcfilters-search-placeholder": "हाल में हुए बदलाव फ़िल्टर (ब्राउज़ या टाइप करना आरंभ करें)",
        "rcfilters-invalid-filter": "अमान्य फ़िल्टर",
        "rcfilters-empty-filter": "कोई सक्रिय फिल्टर नहीं। सभी योगदान दिखाए गए है।",
index 1954d09..5480a2e 100644 (file)
        "rcfilters-restore-default-filters": "Restaurar filtros predefinite",
        "rcfilters-clear-all-filters": "Rader tote le filtros",
        "rcfilters-show-new-changes": "Vider le modificationes le plus recente",
-       "rcfilters-previous-changes-label": "Modificationes vidite previemente",
        "rcfilters-search-placeholder": "Filtrar le modificationes recente (naviga o comencia a scriber)",
        "rcfilters-invalid-filter": "Filtro non valide",
        "rcfilters-empty-filter": "Nulle filtro active. Tote le contributiones es monstrate.",
index 8f47121..58bcb4b 100644 (file)
        "rcfilters-restore-default-filters": "Ripristina i filtri predefiniti",
        "rcfilters-clear-all-filters": "Pulisci tutti i filtri",
        "rcfilters-show-new-changes": "Visualizza le modifiche più recenti",
-       "rcfilters-previous-changes-label": "Modifiche visualizzate precedentemente",
        "rcfilters-search-placeholder": "Filtra le ultime modifiche (naviga o inizia a digitare)",
        "rcfilters-invalid-filter": "Filtro non valido",
        "rcfilters-empty-filter": "Nessun filtro attivo. Sono mostrati tutti i contributi.",
index 580d6e6..0f94874 100644 (file)
        "rcfilters-restore-default-filters": "Err-f imzizdigen imezwar",
        "rcfilters-clear-all-filters": "Sfeḍ akk imzizdigen",
        "rcfilters-show-new-changes": "Skev asnifel aneggaru",
-       "rcfilters-previous-changes-label": "Asnifel yettwaseknen yakan",
        "rcfilters-filterlist-title": "Imzizdigen",
        "rcfilters-filterlist-whatsthis": "Amek iteddu?",
        "rcfilters-highlightbutton-title": "Sebṛureq igmaḍ",
index 3064b90..3da04a1 100644 (file)
        "rcfilters-restore-default-filters": "기본 필터 복구",
        "rcfilters-clear-all-filters": "필터 모두 지우기",
        "rcfilters-show-new-changes": "최신 변경사항 보기",
-       "rcfilters-previous-changes-label": "이전에 표시된 변경사항",
        "rcfilters-search-placeholder": "필터 최근 바뀜 (찾아보거나 입력을 시작하십시오)",
        "rcfilters-invalid-filter": "유효하지 않은 필터",
        "rcfilters-empty-filter": "활성화된 필터가 없습니다. 모든 기여가 표시됩니다.",
index 82e71fd..581e409 100644 (file)
@@ -9,7 +9,8 @@
                        "Huji",
                        "Miladrahimi",
                        "Ebraminio",
-                       "Process cq"
+                       "Process cq",
+                       "Alirezaaa"
                ]
        },
        "tog-underline": "خط کیشائن ژێر پیوندەل:",
        "anontalk": "گەپ(قسە)",
        "navigation": "ناوبری",
        "and": "&#32;و",
-       "qbfind": "آدئین(پێاکرن)",
-       "qbbrowse": "مِنِی -گۀشتن",
-       "qbedit": "دسکاری",
-       "qbpageoptions": "ئێ وەڵگە",
-       "qbmyoptions": "وەڵگەل ووِژم",
        "faq": "پرسش‌های متداول",
-       "faqpage": "Project:پرسش‌های متداول",
        "actions": "کارۀل",
        "namespaces": "فضای نامۀل",
        "variants": "قصۀ کِرۀل",
        "edit-local": "ویرایش توضیحات محلی",
        "create": "دؤِرس کردن/سازین",
        "create-local": "افزودن توضیحات محلی",
-       "editthispage": "اێ وەڵگە دەسکاری کەن",
-       "create-this-page": " اێ وەڵگە دؤرِس کە",
        "delete": "حۀذف کردن/پاک کردن",
-       "deletethispage": "حذف این صفحه",
-       "undeletethispage": "واگردانی(گلآدائن)ئێ وەڵگە",
        "undelete_short": "زِنێ آکرن(احیا) {{PLURAL:$1|یگلە دەسکاری|$1 دەسکاری}}",
        "viewdeleted_short": "نمایش {{PLURAL:$1|یک ویرایش حذف‌شده|$1 ویرایش حذف‌شده}}",
        "protect": "پروژۀ",
        "protect_change": "گؤەڕانن/تغییر",
-       "protectthispage": "پڵۆم کردن اێ وەڵگە",
        "unprotect": "پڵۆم کردن بگؤەڕِن(تغییر ده)",
-       "unprotectthispage": "گؤەڕانن(تغییر)پڵۆم کردن اێ وەڵگە",
        "newpage": "وةڵگة  تازۀ",
-       "talkpage": "دەربارە ئێ وەڵگە گەپ بووشن",
        "talkpagelinktext": "گەپ(قسە)",
        "specialpage": "وةڵگة/پةرة  ویژة",
        "personaltools": "ابزارەل ووژی(شخصی)",
-       "articlepage": "نمایش مةقاڵة",
        "talk": "گەپ قسە",
        "views": "دیین/سئرکردن",
        "toolbox": "ابزارەل",
        "tool-link-userrights": "گروهه‌ل {{GENDER:$1|کاربر}} تغییر بکه",
        "tool-link-userrights-readonly": "گروه {{GENDER:$1|کاربر}} نشون بده",
        "tool-link-emailuser": "ای-میل {{GENDER:$1|کاربر}}ئه",
-       "userpage": "وةڵگة کاربۀر بؤین",
-       "projectpage": "وةڵگة پروژۀ بوین",
        "imagepage": "وةڵگة پرونده بؤین",
        "mediawikipage": "نمایش وةڵگة پیغام",
        "templatepage": "نمایش وةڵگة الگو",
        "nospecialpagetext": "<strong>شما یک صفحهٔ ویژهٔ نامجاز را درخواست کرده‌اید.</strong>\n\nفهرستی از صفحه‌های ویژهٔ مجاز در [[Special:SpecialPages|{{int:specialpages}}]] وجود دارد.",
        "error": "خطا",
        "databaseerror": "خطای پایگاه داده",
-       "databaseerror-text": "مشکلی در پایگاه‌داده‌ها رخ داده است. \nاین ممکن است نشان‌دهندهٔ ایرادی در نرم‌افزار باشد.",
+       "databaseerror-text": "مشکلی در پایگاه‌های داده رخ داده است. \nاین ممکن است نشان‌دهندهٔ ایرادی در نرم‌افزار باشد.",
        "databaseerror-textcl": "یک خطای پرس‌وجوی پایگاه داده‌های رخ داده است.",
        "databaseerror-query": "پرس‌ و جو: $1",
        "databaseerror-function": "تابع: $1",
        "right-mergehistory": "ادغام تاریخچهٔ صفحات",
        "right-userrights": "ویرایش تمام اختیارات کاربرها",
        "right-userrights-interwiki": "ویرایش اختیارات کاربرهای ویکی‌های دیگر",
-       "right-siteadmin": "قفل‌کردن و بازکردن پایگاه داده‌ها",
+       "right-siteadmin": "قفل‌کردن و بازکردن پایگاه‌های داده",
        "right-override-export-depth": "برون‌بری صفحه‌ها شامل صفحه‌های پیوند شده تا عمق ۵",
        "right-sendemail": "ارسال ایمیل به دیگر کاربران",
        "right-managechangetags": "ایجاد و حذف [[Special:Tags|برچسب‌ها]] از پایگاه داده",
        "action-mergehistory": "ادغام تاریخچهٔ این صفحه",
        "action-userrights": "ادغام تاریخچهٔ این صفحه",
        "action-userrights-interwiki": "ویرایش اختیارات کاربری کاربران یک ویکی دیگر",
-       "action-siteadmin": "قفل‌کردن و بازکردن پایگاه داده‌ها",
+       "action-siteadmin": "قفل‌کردن و بازکردن پایگاه‌های داده",
        "action-sendemail": "ایمیل کِل کۀ",
        "action-editmywatchlist": "فهرست پیگیری‌های خود را ویرایش کنید",
        "action-viewmywatchlist": "فهرست پیگیری‌های خود را ببینید",
        "delete-legend": "حۀذف کردن/پاک کردن",
        "historywarning": "<strong>هشدار:</strong> صفحه‌ای که در حال پاک‌کردن آن هستید دارای یک تاریخچه همراه $1 {{PLURAL:$1|بازبینی|بازبینی}} است:",
        "historyaction-submit": "نیشان دائن",
-       "confirmdeletetext": "شما در حال حذف کردن یک صفحه یا تصویر از پایگاه داده‌ها همراه با تمام تاریخچهٔ آن هستید.\nلطفاً این عمل را تأیید کنید و اطمینان حاصل کنید که عواقب این کار را می‌دانید و این عمل را مطابق با [[{{MediaWiki:Policy-url}}|سیاست‌ها]] انجام می‌دهید.",
+       "confirmdeletetext": "شما در حال حذف کردن یک صفحه یا تصویر از پایگاه‌های داده همراه با تمام تاریخچهٔ آن هستید.\nلطفاً این عمل را تأیید کنید و اطمینان حاصل کنید که عواقب این کار را می‌دانید و این عمل را مطابق با [[{{MediaWiki:Policy-url}}|سیاست‌ها]] انجام می‌دهید.",
        "actioncomplete": "عملكرد كامل بيه",
        "actionfailed": "عمل ناموفق بود",
        "deletedtext": "«$1» حذف شد.\nبرای سابقهٔ حذف‌های اخیر به $2 مراجعه کنید.",
        "fileduplicatesearch-noresults": "پرونده‌ای با نام «$1» أ دی نؤی /پئا نؤی.",
        "specialpages": "وەڵگەل(پەڕەل)ویژە",
        "specialpages-note-top": "شرح علائم",
-       "specialpages-note": "* صفحه‌های ویژهٔ عادی.\n* <span class=\"mw-specialpagerestricted\">صفحه‌های ویژهٔ محدودشده.</span>",
        "specialpages-group-maintenance": "گزارش‌های نگهداری",
        "specialpages-group-other": "سایر وةڵگةل ویژه",
        "specialpages-group-login": " إ نؤم هةتن سیستم/ حساوو کاربةری سازین",
index 6e04c57..0cb08f3 100644 (file)
        "search-interwiki-caption": "Rezultāti no citiem projektiem",
        "search-interwiki-default": "Rezultāti no $1:",
        "search-interwiki-more": "(vairāk)",
+       "search-interwiki-more-results": "vairāk rezultātu",
        "search-relatedarticle": "Saistītais",
        "searchrelated": "saistītais",
        "searchall": "viss",
        "grant-group-email": "Sūtīt e-pastu",
        "grant-group-high-volume": "Veikt liela apjoma aktivitātes",
        "grant-group-administration": "Veikt administratīvās darbības",
+       "grant-group-private-information": "Piekļūt privātiem datiem par tevi",
        "grant-blockusers": "Bloķēt un atbloķēt dalībniekus",
        "grant-createaccount": "Izveidot kontu",
        "grant-createeditmovepage": "Izveidot, labot un pārvietot lapas",
        "grant-editprotected": "Labot aizsargātās lapas",
        "grant-highvolume": "Liela apjoma labošana",
        "grant-patrol": "Patrulēt lapu izmaiņas",
+       "grant-privateinfo": "Piekļūt privātai informācijai",
        "grant-uploadfile": "Augšupielādēt jaunus failus",
        "grant-basic": "Pamattiesības",
        "grant-viewdeleted": "Skatīt dzēstos failus un lapas",
        "recentchanges-legend-heading": "<strong>Apzīmējumi:</strong>",
        "recentchanges-legend-newpage": "{{int:recentchanges-label-newpage}} (skatīt arī [[Special:NewPages|jaunās lapas]])",
        "recentchanges-submit": "Rādīt",
+       "rcfilters-other-review-tools": "<strong>Citi pārskatīšanas rīki</strong>",
        "rcfilters-group-results-by-page": "Grupēt rezultātus pēc lapas",
        "rcfilters-grouping-title": "Grupēšana",
        "rcfilters-activefilters": "Aktīvie filtri",
        "rcfilters-restore-default-filters": "Atjaunot noklusētos filtrus",
        "rcfilters-clear-all-filters": "Noņemt visus filtrus",
        "rcfilters-show-new-changes": "Rādīt jaunās izmaiņas",
-       "rcfilters-previous-changes-label": "Iepriekš skatītās izmaiņas",
        "rcfilters-search-placeholder": "Filtrēt pēdējās izmaiņas (pārlūko vai sāc rakstīt)",
        "rcfilters-invalid-filter": "Nederīgs filtrs",
        "rcfilters-empty-filter": "Nav aktīvu filtru. Tiek rādītas visas izmaiņas.",
        "rcfilters-filter-user-experience-level-unregistered-label": "Nereģistrēti",
        "rcfilters-filter-user-experience-level-unregistered-description": "Nepieslēgušies redaktori.",
        "rcfilters-filter-user-experience-level-newcomer-label": "Jaunpienācēji",
-       "rcfilters-filter-user-experience-level-newcomer-description": "Mazāk nekā 10 labojumi un 4 aktīvas dienas.",
+       "rcfilters-filter-user-experience-level-newcomer-description": "Reģistrēti lietotāji ar mazāk nekā 10 labojumiem un 4 dienu aktivitāti.",
        "rcfilters-filter-user-experience-level-learner-label": "Mācekļi",
        "rcfilters-filter-user-experience-level-learner-description": "Vairāk pieredzes nekā \"Jaunpienācējiem\", bet mazāk nekā \"Pieredzējušiem dalībniekiem\".",
        "rcfilters-filter-user-experience-level-experienced-label": "Pieredzējuši dalībnieki",
        "sp-contributions-search": "Meklēt lietotāju veiktās izmaiņas",
        "sp-contributions-username": "IP adrese vai dalībnieka vārds:",
        "sp-contributions-toponly": "Rādīt tikai labojumus, kas ir jaunākās versijas",
+       "sp-contributions-newonly": "Rādīt tikai labojumus, kas ir lapu veidošana",
        "sp-contributions-hideminor": "Paslēpt maznozīmīgos labojumus",
        "sp-contributions-submit": "Meklēt",
        "whatlinkshere": "Norādes uz šo rakstu",
        "watchlistedit-raw-added": "{{PLURAL:$1|$1 lapas tika pievienotas|$1 lapa tika pievienota|$1 lapas tika pievienotas}}:",
        "watchlistedit-raw-removed": "{{PLURAL:$1|$1 lapas tika noņemtas|1 lapa tika noņemta|$1 lapas tika noņemtas}}:",
        "watchlistedit-clear-titles": "Nosaukumi:",
+       "watchlisttools-clear": "Notīrīt uzraugāmo rakstu sarakstu",
        "watchlisttools-view": "Skatīt atbilstošās izmaiņas",
        "watchlisttools-edit": "Apskatīt un izmainīt uzraugāmo rakstu sarakstu",
        "watchlisttools-raw": "Izmainīt uzraugāmo rakstu saraksta kodu",
index 1f47ba3..35da0cb 100644 (file)
        "rcfilters-restore-default-filters": "Поврати основни филтри",
        "rcfilters-clear-all-filters": "Тргни ги сите филтри",
        "rcfilters-show-new-changes": "Погл. најнови промени",
-       "rcfilters-previous-changes-label": "Претходно прегледани промени",
        "rcfilters-search-placeholder": "Филтрирај скорешни промени (прелстајте или почнете да пишувате)",
        "rcfilters-invalid-filter": "Неважечки филтер",
        "rcfilters-empty-filter": "Нема активни филтри. Прикажани се сите придонеси.",
index e9a0d20..adcbb80 100644 (file)
        "rcfilters-restore-default-filters": "Gjenopprett standardfiltre",
        "rcfilters-clear-all-filters": "Nullstill alle filtre",
        "rcfilters-show-new-changes": "Vis de nyeste endringene",
-       "rcfilters-previous-changes-label": "Endringer som har blitt vist tidligere",
        "rcfilters-search-placeholder": "Filtrer siste endringer (søk eller begyn å skrive)",
        "rcfilters-invalid-filter": "Ugyldig filter",
        "rcfilters-empty-filter": "Ingen aktive filtre. Alle bidrag vises.",
index a05c860..8b59ac1 100644 (file)
        "rcfilters-restore-default-filters": "Standaard filters terugzetten",
        "rcfilters-clear-all-filters": "Alle filters verwijderen",
        "rcfilters-show-new-changes": "Toon nieuwste wijzigingen",
-       "rcfilters-previous-changes-label": "Eerder bekeken wijzigingen",
        "rcfilters-search-placeholder": "Filter recente wijzigingen (blader of begin met intypen)",
        "rcfilters-invalid-filter": "Ongeldig filter",
        "rcfilters-empty-filter": "Geen actieve filters. Alle bijdragen worden weergeven.",
index b87a5bb..d2eca86 100644 (file)
        "rcfilters-restore-default-filters": "Przywróć domyślne filtry",
        "rcfilters-clear-all-filters": "Wyczyść filtry",
        "rcfilters-show-new-changes": "Zobacz nowsze zmiany",
-       "rcfilters-previous-changes-label": "Poprzednio wyświetlane zmiany",
        "rcfilters-search-placeholder": "Filtruj ostatnie zmiany (przeglądaj lub zacznij wpisywać)",
        "rcfilters-invalid-filter": "Nieprawidłowy filtr",
        "rcfilters-empty-filter": "Brak aktywnych filtrów. Wyświetlane są wszystkie zmiany.",
index 5f04466..4d7606d 100644 (file)
        "rcfilters-restore-default-filters": "Restaurar filtros padrão",
        "rcfilters-clear-all-filters": "Limpar todos os filtros",
        "rcfilters-show-new-changes": "Veja as novas mudanças",
-       "rcfilters-previous-changes-label": "Mudanças vistas anteriormente",
        "rcfilters-search-placeholder": "Filtrar mudanças recentes (procurar ou começar a digitar)",
        "rcfilters-invalid-filter": "Filtro inválido",
        "rcfilters-empty-filter": "Nenhum filtro ativo. Todas as contribuições são mostradas.",
index 1f33b42..3b76197 100644 (file)
        "rcfilters-restore-default-filters": "Restaurar os filtros padrão",
        "rcfilters-clear-all-filters": "Limpar todos os filtros",
        "rcfilters-show-new-changes": "Mostrar as mudanças mais recentes",
-       "rcfilters-previous-changes-label": "Mudanças vistas anteriormente",
        "rcfilters-search-placeholder": "Filtrar mudanças recentes (navegue ou começe a escrever)",
        "rcfilters-invalid-filter": "Filtro inválido",
        "rcfilters-empty-filter": "Não há filtros ativos. São mostradas todas as contribuições.",
index f7b176c..eeb0e7a 100644 (file)
        "rcfilters-restore-default-filters": "Label for the button that resets filters to defaults",
        "rcfilters-clear-all-filters": "Title for the button that clears all filters",
        "rcfilters-show-new-changes": "Label for the button to show new changes.",
-       "rcfilters-previous-changes-label": "Label to indicate the changes below have been previously viewed.",
        "rcfilters-search-placeholder": "Placeholder for the filter search input.",
        "rcfilters-invalid-filter": "A label for an invalid filter.",
        "rcfilters-empty-filter": "Placeholder for the filter list when no filters were chosen.",
index 7960de5..4ba7dd6 100644 (file)
        "rcfilters-restore-default-filters": "Восстановить фильтры по умолчанию",
        "rcfilters-clear-all-filters": "Очистить все фильтры",
        "rcfilters-show-new-changes": "Последние изменения",
-       "rcfilters-previous-changes-label": "Ранее просмотренные изменения",
        "rcfilters-search-placeholder": "Последние изменения фильтров (просмотрите или начните вводить)",
        "rcfilters-invalid-filter": "Недопустимый фильтр",
        "rcfilters-empty-filter": "Нет активных фильтров. Показываются все правки.",
index 575a1bd..9d1f190 100644 (file)
@@ -67,9 +67,9 @@
        "fri": "Asimwas",
        "sat": "Asidyas",
        "january": "ⵉⵏⵏⴰⵢⵔ",
-       "february": "brayr",
+       "february": "ⴼⴱⵔⴰⵢⵔ",
        "march": "ⵎⴰⵔⵚ",
-       "april": "Ibrir",
+       "april": "ⴰⴱⵔⵉⵍ",
        "may_long": "ⵎⴰⵢⵢⵓ",
        "june": "ⵢⵓⵏⵢⵓ",
        "july": "ⵢⵓⵍⵢⵓⵣ",
@@ -79,7 +79,7 @@
        "november": "ⵏⵓⵡⴰⵏⴱⵉⵔ",
        "december": "ⴷⵓⵊⴰⵏⴱⵉⵔ",
        "january-gen": "ⵉⵏⵏⴰⵢⵔ",
-       "february-gen": "Brayr",
+       "february-gen": "ⴼⴱⵔⴰⵢⵔ",
        "march-gen": "ⵎⴰⵔⵚ",
        "april-gen": "Ibrir",
        "may-gen": "ⵎⴰⵢⵢⵓ",
@@ -93,7 +93,7 @@
        "jan": "ⵉⵏⵏ",
        "feb": "brayr",
        "mar": "ⵎⴰⵔ",
-       "apr": "Ibrir",
+       "apr": "ⴰⴱⵔ",
        "may": "ⵎⴰⵢ",
        "jun": "ⵢⵓⵏ",
        "jul": "ⵢⵓⵍ",
        "october-date": "$1 ⴽⵜⵓⴱⵔ",
        "november-date": "$1 ⵏⵓⵡⴰⵏⴱⵉⵔ",
        "december-date": "$1 ⴷⵓⵊⴰⵏⴱⵉⵔ",
-       "pagecategories": "{{PLURAL:$1|â´°âµ\99âµ\8eâµ\89âµ\8d|âµ\89âµ\99âµ\8eâµ\89âµ\8dⵏ}}",
-       "category_header": "âµ\9câ´°âµ\99âµ\8fâµ\89ⵡâµ\89âµ\8f â´³ âµ\93âµ\99âµ\8eâµ\89âµ\8d \"$1\"",
+       "pagecategories": "{{PLURAL:$1|âµ\9cⴰⴳⴳⴰⵢâµ\9c|âµ\9cⴰⴳⴳⴰⵢâµ\89ⵏ}}",
+       "category_header": "âµ\9câ´°âµ\99âµ\8fâµ\89ⵡâµ\89âµ\8f âµ\96 âµ\9cⴰⴳⴳⴰⵢâµ\9c \"$1\"",
        "subcategories": "ⵉⴷⵓⵙⵎⵉⵍⵏ",
        "category-media-header": "Asdaw multimedya ɣ taggayt \"$1\"",
        "category-empty": "Taggayt ad ur gis kra n tasna, du-taggayt niɣd asddaw multimidya",
-       "hidden-categories": "{{PLURAL:$1|â´°âµ\99âµ\8eâµ\89âµ\8d âµ\89âµ\8fâµ\9câµ\8dâµ\8f|âµ\89âµ\99âµ\8eâµ\89âµ\8dⵏ ⵏⵜⵍⵏⵉⵏ}}",
+       "hidden-categories": "{{PLURAL:$1|âµ\9cⴰⴳⴳⴰⵢâµ\9c âµ\89âµ\8fâµ\9câµ\8dâµ\8f|âµ\9cⴰⴳⴳⴰⵢâµ\89ⵏ ⵏⵜⵍⵏⵉⵏ}}",
        "hidden-category-category": "ⵉⵙⵎⵉⵍⵏ ⵏⵜⵍⵏⵉⵏ",
        "category-subcat-count": "Taggayt ad gis {{PLURAL:$2|ddu taggayt|$2 ddu taggayin, lli ɣ tlla {{PLURAL:$1|ɣta|ɣti $1}}}} γu flla nna.",
        "category-subcat-count-limited": "Taggayt ad illa gis {{PLURAL:$1|ddu taggayt| $1 ddu taggayyin}} ɣid ɣ uzddar.",
        "listingcontinuesabbrev": "Attfr",
        "index-category": "Tisniwin su umatar",
        "noindex-category": "Tisniwin bla amatar",
-       "broken-file-category": "Tisniwin ɣ llan izdayn rzanin",
+       "broken-file-category": "ⵜⴰⵙⵏⵉⵡⵉⵏ ⵖ ⵍⵍⴰⵏ ⵉⵍⵉⵏⴽⵏ ⵔⵥⴰⵏⵉⵏ",
        "about": "ⵅⴼ",
        "article": "ⵜⴰⵙⵏⴰ ⵏ ⵜⵓⵎⴰⵢⵜ",
        "newwindow": "(ⵉⵜⵜⵏⵓⵔⵥⵓⵎ ⴷⴳ ⵓⵙⴽⵙⵍ ⴰⵎⴰⵢⵏⵓ)",
        "specialpage": "ⵜⴰⵙⵏⴰ ⵉⵥⵍⵉⵏ",
        "personaltools": "ⵉⵎⴰⵙⵙⵏ ⵉⵏⵉⵎⴰⵏⴻⵏ",
        "talk": "ⴰⵎⵙⴰⵡⴰⵍ",
-       "views": "Ẓr.. (Mel)",
+       "views": "ⵜⴰⵏⵏⴰⵢⵉⵏ",
        "toolbox": "ⵉⵎⴰⵙⵙⵏ",
        "imagepage": "Ẓr tasna n-usddaw",
        "mediawikipage": "Ẓr tasna n tabrat",
        "otherlanguages": "ⵙ ⵜⵓⵜⵍⴰⵢⵉⵏ ⵢⴰⴹⵏ",
        "redirectedfrom": "(Tmmuttid z $1)",
        "redirectpagesub": "Tasna n-usmmattay",
-       "lastmodifiedat": "â´°âµ\99âµ\8fâ´¼âµ\8d âµ\89ⴳⴳⵯâµ\94â´°âµ\8f â´³ ⵜⴰⵙⵏⴰ ⴰⴷ ⵉⵜⵜⵢⵓⵙⴽⵔ ⴰⵙⵙ ⵏ $1 ⴳ $2.",
+       "lastmodifiedat": "â´°âµ\99âµ\8fâ´¼âµ\8d âµ\89ⴳⴳⵯâµ\94â´°âµ\8f âµ\96 ⵜⴰⵙⵏⴰ ⴰⴷ ⵉⵜⵜⵢⵓⵙⴽⵔ ⴰⵙⵙ ⵏ $1 ⴳ $2.",
        "viewcount": "Tmmurzm tasna yad {{PLURAL:$1|yat twalt|$1 mnnawt twal}}.",
        "protectedpage": "Tasnayat iqn ugdal nes.",
        "jumpto": "ⴷⴷⵓ ⵙ:",
        "pool-timeout": "Tzrit tizi n uql lli yak ittuykfan. Ggutn midn lli iran ad iẓr tasna yad. Urrid yan imik..",
        "pool-queuefull": "Umuɣ n twuri iẓun (iεmr)",
        "pool-errorunknown": "Anzri (error) ur ittuyssan.",
-       "aboutsite": "âµ\85â´¼ {{SITENAME}}",
-       "aboutpage": "Project:âµ\85ⴼ",
+       "aboutsite": "ⴼ {{SITENAME}}",
+       "aboutpage": "Project:âµ\96ⴼ",
        "copyright": "Mayllan gis illa ɣ ddu $1.",
-       "copyrightpage": "{{ns:project}}:Izrfan n umgay",
+       "copyrightpage": "{{ns:project}}:ⵉⵣⵔⴼⴰⵏ ⵏ ⵓⵎⴳⴰⵢ",
        "currentevents": "Immussutn n ɣila",
        "currentevents-url": "Project:Immussutn n ɣilad",
        "disclaimers": "ⵉⵙⵎⵉⴳⵍⵏ",
        "editold": "ⵙⵏⴼⵍ",
        "viewsourceold": "Mel aɣbalu",
        "editlink": "ⵙⵏⴼⵍ",
-       "viewsourcelink": "Mel aɣbalu",
+       "viewsourcelink": "ⵥⵔ ⴰⵙⴰⴳⵎ",
        "editsectionhint": "ⵙⵏⴼⵍ ⵜⵉⴳⵣⵎⵉ: $1",
        "toc": "ⵜⵓⵎⴰⵢⵉⵏ",
        "showtoc": "Mel",
        "site-atom-feed": "$1 lqm n' atom",
        "page-rss-feed": "\"$1\" tlqim RSS",
        "page-atom-feed": "$1 azday atom",
-       "red-link-title": "$1 (tasna yad ur tlli)",
+       "red-link-title": "$1 (ⵜⴰⵙⵏⴰ ⵓⵔ ⵉⵍⵍⵉⵏ)",
        "nstab-main": "ⵜⴰⵙⵏⴰ",
        "nstab-user": "ⵜⴰⵙⵏⴰ ⵏ {{GENDER:{{ROOTPAGENAME}}|ⵓⵙⵎⵔⴰⵙ|ⵜⵙⵎⵔⴰⵙⵜ}}",
        "nstab-media": "Tasnat Ntuzumt",
        "nstab-mediawiki": "ⵜⵓⵣⵉⵏⵜ",
        "nstab-template": "Talɣa",
        "nstab-help": "ⵜⴰⵙⵏⴰ ⵏ ⵜⵡⵉⵙⵉ",
-       "nstab-category": "â´°âµ\99âµ\8eâµ\89âµ\8d",
+       "nstab-category": "âµ\9cⴰⴳⴳⴰⵢâµ\9c",
        "mainpage-nstab": "ⵜⴰⵙⵏⴰ ⵏ ⵓⵙⵏⵓⴱⴳ",
        "nosuchaction": "ⵓⵔ ⵜⵍⵍⵉ ⵜⵉⴳⴰⵡⵜ ⴰⴷ",
        "nosuchactiontext": "Mytuskarn ɣu tansa yad ur tti tgi.\n\nIrwas is turit tansa  skra mani yaḍnin, ulla azday ur igi amya.\n\nTzdar attili tamukrist ɣ {{SITENAME}}.",
        "italic_sample": "Aḍṛiṣ iknan",
        "italic_tip": "Aḍṛiṣ iknan",
        "link_sample": "Azwl n uzday",
-       "link_tip": "Azday uwgns",
-       "extlink_sample": "http://www.example.com azwl n uzday",
-       "extlink_tip": "Azday n brra (af ur ttut amzwir http://prefix)",
+       "link_tip": "ⴰⵍⵉⵏⴽ ⴰⴳⵯⵏⵙⴰⵏ",
+       "extlink_sample": "http://www.example.com ⴰⵣⵡⵍ ⵏ ⵓⵍⵉⵏⴽ",
+       "extlink_tip": "ⴰⵍⵉⵏⴽ ⴰⴱⵔⵔⴰⵏ (ⴰⴷ ⵓⵔ ⵜⴻⵜⵜⵓⵜ ⴰⵣⵡⵉⵔ http://)",
        "headline_sample": "Aḍṛiṣ n ddu uzwl",
        "headline_tip": "Ddu-uzwl taskfalt 2",
        "nowiki_sample": "Kcm aḍṛiṣ li ur imzln ɣid",
        "accmailtitle": "awal ihdan hatin yuznak nnit",
        "newarticle": "(ⴰⵎⴰⵢⵏⵓ)",
        "newarticletext": "Tfrt yan uzday s yat tasna lli ur ta jju illan [{{fullurl:Special:Log|type=delete&page={{FULLPAGENAMEE}}}} ttuykkas].\nIɣ rast daɣ tskrt skcm atṛiṣ nk ɣ tanaka  yad (Tẓḍaṛt an taggt γi [$1 tasna u usaws] iɣ trit inɣmisn yaḍn).\nIvd tlkmt {{GENDER:||e|(e)}} ɣis bla trit, klikki f tajrrayt n '''urrir''' n iminig nk (navigateur).",
-       "noarticletext": "ɣilad ur illa walu may ityuran  f tasnatad ad, tzdart at [[Special:Search/{{PAGENAME}}|search for this page title]] in other pages,\n<span class=\"plainlinks\">[{{fullurl:{{#Special:Log}}|page={{FULLPAGENAMEE}}}} search the related logs],\nulla cabba  [{{fullurl:{{FULLPAGENAME}}|action=edit}} edit this page]</span>.",
+       "noarticletext": "ⵓⵔ ⵖⵉⵍⴰⴷ ⵉⵍⵍⵉ ⴽⵔⴰ ⵏ ⵓⴹⵔⵉⵙ ⵖ ⵜⴰⵙⵏⴰ ⴰⴷ.\nⵜⵥⴹⴰⵔⵜ [[Special:Search/{{PAGENAME}}|ⴰⴷ ⵜⵙⵉⴳⴳⵍⵜ ⴰⵣⵡⵍ ⴰⴷ]] ⵖ ⵜⴰⵙⵏⵉⵡⵉⵏ ⵢⴰⴹⵏ,\n<span class=\"plainlinks\">[{{fullurl:{{#Special:Log}}|page={{FULLPAGENAMEE}}}} search the related logs],\nⵏⵖ [{{fullurl:{{FULLPAGENAME}}|action=edit}} ⴰⴷ ⵜⵙⵏⵓⵍⴼⵓⵜ ⵜⴰⵙⵏⴰ ⴰⴷ]</span>.",
        "noarticletext-nopermission": "Ur illa may itt yuran ɣ tasna tad.\nẒr [[Special:Search/{{PAGENAME}}|search for this page title]] ɣ tisnatin yaḍnin,\nulla <span class=\"plainlinks\">[{{fullurl:{{#Special:Log}}|page={{FULLPAGENAMEE}}}}search the related logs]</span>.",
        "updated": "(mohdata)",
        "note": "'''molahada:'''",
        "copyrightwarning": "ikhssak atst izd kolchi tikkin noun ɣ {{SITENAME}} llan ɣdo $2 (zr $1 iɣ trit ztsnt uggar).\niɣ ortrit ayg ɣayli torit ḥor artisbadal wnna ka-iran, attid ortgt ɣid.<br />\nikhssak ola kiyi ador tnqilt ɣtamani yadni.\n'''ador tgat ɣid ɣayli origan ḥor iɣzark orilli lidn nbab-ns!'''",
        "templatesused": "{{PLURAL:$1|Tamuḍimt lli nsxdm|Timuḍimin}} ɣ tasna yad:",
        "templatesusedpreview": "{{PLURAL:$1|Tamuḍimt llis nskar |Timuḍam lli sa nskar }} ɣ iẓriyad amzwaru :",
-       "template-protected": "Agdal",
+       "template-protected": "(ⵉⵜⵜⵢⵓⴼⵔⴰⴳ)",
        "template-semiprotected": "Azin-ugdal",
        "hiddencategories": "{{PLURAL:$1|Taggayt iḥban|Taggayin ḥbanin}} lli ɣtlla tasba yad :",
        "permissionserrors": "ⵜⴰⵣⴳⵍⵜ ⵖ ⵜⵓⵔⴰⴳⵜ",
        "showhideselectedversions": "Ml/Ḥbu ilqmn lli ittuystayn",
        "editundo": "Urri",
        "diff-multi-manyusers": "({{PLURAL:$1|yan ulqm n gratsn|$1 ilqmn ngratsn}} zdar mnnaw {{PLURAL:$2|amcgr |n $2 imcgrn}} {{PLURAL:$1|iḥba|lli iḥban}})",
-       "searchresults": "Mad akkan icnubcn",
-       "searchresults-title": "âµ\9câµ\89ⵢⴰⴼâµ\93âµ\9câµ\89âµ\8f âµ\8f âµ\93âµ\94ⵣⵣâµ\93 âµ\85â´¼ \"$1\"",
+       "searchresults": "ⵜⵉⵢⴰⴼⵓⵜⵉⵏ ⵏ ⵓⵔⵣⵣⵓ",
+       "searchresults-title": "ⵜⵉⵢⴰⴼⵓⵜⵉⵏ ⵏ ⵓⵔⵣⵣⵓ ⴼ \"$1\"",
        "titlematches": "Assaɣ n tasna iga zund",
        "textmatches": "Aṭṛiṣ n tasna iga zund",
        "notextmatches": "Ur ittyufa kra nu uṭṛiṣ igan zund ɣwad",
        "searchmenu-exists": "\"'Tlla yat tasna lli ilan assaɣ « [[:$1]] » ɣ wiki yad",
        "searchmenu-new": "<strong>ⵙⵏⵓⵍⴼⵓ ⵜⴰⵙⵏⴰ \"[[:$1]]\" ⴳ ⵓⵡⵉⴽⵉ ⴰⴷ!</strong> {{PLURAL:$2|0=|See also the page found with your search.|See also the search results found.}}",
        "searchprofile-articles": "ⵜⴰⵙⵏⵉⵡⵉⵏ ⵏ ⵜⵓⵎⴰⵢⵜ",
-       "searchprofile-images": "Multimedia",
+       "searchprofile-images": "ⴰⴳⵜⵎⵉⴷⵢⴰ",
        "searchprofile-everything": "ⴰⴽⴽⵯ",
-       "searchprofile-advanced": "motaqqadim",
+       "searchprofile-advanced": "Advanced",
        "searchprofile-articles-tooltip": "ⵙⵉⴳⴳⵍ ⵖ $1",
        "searchprofile-images-tooltip": "ⵙⵉⴳⴳⵍ ⵉⴼⴰⵢⵍⵓⵜⵏ",
        "searchprofile-everything-tooltip": "ⵙⵉⴳⴳⵍ ⵖ ⵜⵓⵎⴰⵢⵜ ⴽⵓⵍⵍⵓ ⵜⵜ (ⵓⵍⴰ ⵖ ⵜⴰⵙⵏⵉⵡⵉⵏ ⵏ ⵓⵎⵙⴰⵡⴰⵍ)",
-       "searchprofile-advanced-tooltip": "Cabba ɣ igmmaḍn li tuyzlaynin",
+       "searchprofile-advanced-tooltip": "ⵙⵉⴳⴳⵍ ⵖ custom namespaces",
        "search-result-size": "$1 ({{PLURAL:$2|1 ⵜⴳⵓⵔⵉ|$2 ⵜⴳⵓⵔⵉⵡⵉⵏ}})",
        "search-result-category-size": "$1 {{PLURAL:$1|ⵓⴳⵎⴰⵎ|ⵉⴳⵎⴰⵎⵏ}} ($2 {{PLURAL:$2|ⵡⴰⴷⵓⵎⵙⵉⵍ|ⵉⴷⵓⵎⵙⵉⵍⵏ}}, $3 {{PLURAL:$3|ⵓⴼⴰⵢⵍⵓ|ⵉⴼⴰⵢⵍⵓⵜⵏ}})",
        "search-redirect": "(Asmmati $1)",
        "number_of_watching_users_pageview": "[$1 iżŗi {{PLURAL:$1|amsqdac|imsqdacn}}]",
        "rc_categories_any": "wanna",
        "rc-change-size": "$1",
-       "rc-change-size-new": "$1 {{PLURAL:$1|ⴱⴰⵢⵜ|ⵉⴷ ⴱⴰⵢⵜ}} ⴷⴼⴼⵉⵔ ⵓⵙⵏⴼⵍ",
+       "rc-change-size-new": "$1 {{PLURAL:$1|ⴱⴰⵢâµ\9c|âµ\89â´· â´±â´°âµ¢âµ\9c}} â´·â´¼â´¼âµ\89âµ\94 âµ\8f âµ\93âµ\99âµ\8fâ´¼âµ\8d",
        "newsectionsummary": "/* $1 */ ⵜⵉⴳⵣⵎⵉ ⵜⴰⵎⴰⵢⵏⵓⵜ",
        "rc-enhanced-expand": "Ml ifruriyn (ira JavaScript)",
        "rc-enhanced-hide": "Ĥbu ifruriyn",
        "recentchangeslinked-feed": "Imbddeln zund ɣwid",
        "recentchangeslinked-toolbox": "Imbddeln zund ɣwid",
        "recentchangeslinked-title": "ⵉⵙⵏⴼⵉⵍⵏ ⵇⵇⵏⵏⵉⵏ ⵙ \"$1\"",
-       "recentchangeslinked-summary": "Ɣid umuɣ iymbddeln li ittyskarnin tigira yad ɣ tisniwin li ittuyzdayn d kra n tasna (ulla i igmamn n kra taggayt ittuyzlayn). Tisniwin  ɣ [[Special:Watchlist|Umuɣ n tisniwin li ttsaggat]].",
+       "recentchangeslinked-summary": "ⵉⵙⵏⴼⵉⵍⵏ ⵜⵜⵢⵓⵙⴽⴰⵔⵏⵉⵏ ⵜⵉⴳⵉⵔⴰ ⴰⴷ ⵉ ⵜⴰⵙⵏⵉⵡⵉⵏ ⵏⵏⴰ ⵙⵔⵙⵏⵜ ⵜⴻⵜⵜⴰⵡⵉ ⴽⵔⴰ ⵏ ⵜⴰⵙⵏⴰ ⵉⵥⵍⵉⵏ (ⵏⵖ ⵉ ⵉⴳⵎⴰⵎⵏ ⵏ ⴽⵔⴰ ⵏ ⵜⴰⴳⴳⴰⵢⵜ ⵉⵥⵍⵉⵏ).\nⵜⴰⵙⵏⵉⵡⵉⵏ ⵍⵍⴰⵏⵉⵏ ⵖ [[Special:Watchlist|ⵜⵍⴳⴰⵎⵜ ⵏⵏⴽ/ⵎ ⵏ ⵓⴹⴼⴼⵓⵔ]] ⵍⵍⴰⵏⵜ ⵙ ⵜⵉⵔⵔⴰ ⵣⵓⵔⵏⵉⵏ.",
        "recentchangeslinked-page": "ⵉⵙⵎ ⵏ ⵜⴰⵙⵏⴰ:",
        "recentchangeslinked-to": "ⵎⵍ ⵉⵙⵏⴼⵉⵍⵏ ⵏ ⵜⴰⵙⵏⵉⵡⵉⵏ ⵇⵇⵏⵏⵉⵏ ⵙ ⵜⴰⵙⵏⴰ instead",
        "upload": "ⵙⴽⵜⵔ ⴽⵔⴰ ⵏ ⵓⴼⴰⵢⵍⵓ",
        "filehist-user": "ⴰⵙⵎⵔⴰⵙ",
        "filehist-dimensions": "ⵉⵎⵏⴰⴷⵏ",
        "filehist-comment": "ⴰⵅⴼⴰⵡⴰⵍ",
-       "imagelinks": "Izdayn n usdaw",
+       "imagelinks": "ⴰⵙⵇⴷⵛ ⵏ ⵓⴼⴰⵢⵍⵓ",
        "linkstoimage": "Tasna yad {{PLURAL:$1|izdayn n tasna|$1 azday n tasniwin}} s usdaw:",
-       "nolinkstoimage": "Ḥtta kra n tasna ur tra asdaw ad",
+       "nolinkstoimage": "ⵓⵔ ⵜⵍⵍⵉ ⴽⵔⴰ ⵏ ⵜⴰⵙⵏⴰ ⵉⵏⴰⵡⵍⵏ ⴰⴼⴰⵢⵍⵓ ⴰⴷ.",
        "sharedupload": "Asdawad z $1 tẓḍart at tsxdmt gr iswirn yaḍnin",
        "sharedupload-desc-here": "ⴰⴼⴰⵢⵍⵓ ⴰⴷ ⵉⴽⴽⴰ ⴷ $1 ⴷ ⵉⵥⴹⴰⵔ ⴰⴷ ⵢⵉⵍⵉ ⵉⵜⵜⵢⴰⵡⵙⵅⴷⴰⵎ ⵖ ⵉⵙⵏⴼⴰⵔⵏ ⵢⴰⴹⵏ.\nⴰⴳⵍⴰⵎ ⵉⵍⵍⴰⵏ ⵖ [$2 ⵜⴰⵙⵏⴰ ⵏⵏⵙ ⵏ ⵓⴳⵍⴰⵎ] ⵀⴰ ⵜ ⴷⴷⴰⵡ ⴰⵙ.",
        "uploadnewversion-linktext": "ⵙⴽⵜⵔ ⴽⵔⴰ ⵏ ⵜⵓⵏⵖⵉⵍⵜ ⵜⴰⵎⴰⵢⵏⵓⵜ ⵏ ⵓⴼⴰⵢⵍⵓ ⴰⴷ",
        "booksources-search-legend": "Acnubc s iɣbula n idlisn",
        "booksources-isbn": "ISBN:",
        "booksources-search": "ⵙⵉⴳⴳⵍ",
-       "specialloguserlabel": "Amsqdac",
+       "specialloguserlabel": "ⴰⵎⴳⴰⵢ:",
        "speciallogtitlelabel": "Azwl",
        "log": "Immussutn ittyuran",
        "all-logs-page": "Immussutn ittyuran immurzmn i kullu..",
        "sp-contributions-submit": "ⵙⵉⴳⴳⵍ",
        "sp-contributions-explain": "↓",
        "whatlinkshere": "ⵎⴰⴷ ⵉⵇⵇⵏⴻⵏ ⵙ ⵖⵉⴷ",
-       "whatlinkshere-title": "Tisniwin li izdayn d \"$1\"",
+       "whatlinkshere-title": "ⵜⴰⵙⵏⵉⵡⵉⵏ ⵜⵜⴰⵡⵉⵏⵉⵏ ⵙ \"$1\"",
        "whatlinkshere-page": "ⵜⴰⵙⵏⴰ:",
        "linkshere": "Tasnawinad ar slkamnt i '''[[:$1]]''':",
-       "nolinkshere": "Ur llant tasniwin li izdin d '''[[:$1]]'''.",
+       "nolinkshere": "ⵓⵍⴰ ⴽⵔⴰ ⵏ ⵜⴰⵙⵏⴰ ⵓⵔ ⴰⵔ ⵜⴻⵜⵜⴰⵡⵉ ⵙ <strong>[[:$1]]</strong>.",
        "nolinkshere-ns": "Ur tlla kra n tasna izdin d  '''[[:$1]]''' ɣ tɣult l-ittuystayn.",
        "isredirect": "Tasna immutin",
        "istemplate": "Illa gis",
-       "isimage": "Azday s usdaw",
+       "isimage": "ⴰⵍⵉⵏⴽ ⵏ ⵓⴼⴰⵢⵍⵓ",
        "whatlinkshere-prev": "{{PLURAL:$1|amzwaru|amzwaru $1}}",
        "whatlinkshere-next": "{{PLURAL:$1|wali d yuckan|wali d yuckan $1}}",
-       "whatlinkshere-links": "← izdayn",
+       "whatlinkshere-links": "← ⵉⵍⵉⵏⴽⵏ",
        "whatlinkshere-hideredirs": "$1 Ismmattayn",
        "whatlinkshere-hidetrans": "$1 mayllan gis",
-       "whatlinkshere-hidelinks": "$1 izdayn",
+       "whatlinkshere-hidelinks": "$1 ⵉⵍⵉⵏⴽⵏ",
        "whatlinkshere-hideimages": "$1 izdayn awlaf",
        "whatlinkshere-filters": "Istayn",
        "blockip": "ⴳⴷⵍ {{GENDER:$1|ⴰⵙⵎⵔⴰⵙ|ⵜⴰⵙⵎⵔⴰⵙⵜ}}",
        "tooltip-ca-unwatch": "ⵙⵉⵜⵜⵉ ⵜⴰⵙⵏⴰ ⴰⴷ ⵣⵖ ⵜⵍⴳⴰⵎⵜ {{GENDER:|ⵏⵏⴽ|ⵏⵏⵎ}} ⵏ ⵓⴹⴼⴼⵓⵔ",
        "tooltip-search": "ⵙⵉⴳⴳⵍ ⵖ {{SITENAME}}",
        "tooltip-search-go": "Ftu s tasna s w-assaɣ znd ɣ-wad  iɣ tlla",
-       "tooltip-search-fulltext": "Cnubc aṭṛiṣad ɣ tisnatin",
+       "tooltip-search-fulltext": "ⵙⵉⴳⴳⵍ ⴰⴹⵔⵉⵙ ⴰⴷ ⵖ ⵜⴰⵙⵏⵉⵡⵉⵏ",
        "tooltip-p-logo": "ⴽⴽ ⴷ ⵜⴰⵙⵏⴰ ⵏ ⵓⵙⵏⵓⴱⴳ",
        "tooltip-n-mainpage": "ⴽⴽ ⴷ ⵜⴰⵙⵏⴰ ⵏ ⵓⵙⵏⵓⴱⴳ",
        "tooltip-n-mainpage-description": "ⴽⴽ ⴷ ⵜⴰⵙⵏⴰ ⵏ ⵓⵙⵏⵓⴱⴳ",
-       "tooltip-n-portal": "f' usenfar, matzdart atitskrt, maniɣrattaft ɣayli trit",
+       "tooltip-n-portal": "ⴼ ⵓⴱⵔⵓⵊⵉ, ⵎⴰⴷ ⵜⵥⴹⴰⵔⵜ ⴰⴷ ⵜ ⵜⵙⴽⵔⵜ, ⵎⴰⵏⵉ ⵔⴰⴷ ⵜⴰⴼⵜ ⵓⵎⵍⴰⵏ",
        "tooltip-n-currentevents": "Tiɣri izrbn i kullu maɣid immusn",
        "tooltip-n-recentchanges": "ⵜⴰⵍⴳⴰⵎⵜ ⵏ ⵉⵙⵏⴼⵉⵍⵏ ⴳⴳⵯⵔⴰⵏⵉⵏ ⵖ ⵓⵡⵉⴽⵉ",
-       "tooltip-n-randompage": "Srbu yat tasna ɣik nna ka tga",
+       "tooltip-n-randompage": "ⵣⴷⵎ ⴷ ⴽⵔⴰ ⵏ ⵜⴰⵙⵏⴰ ⵙ ⵓⴷⵀⵎⴰⵙ",
        "tooltip-n-help": "Adɣar n w-aws",
        "tooltip-t-whatlinkshere": "Umuɣ n kullu tisnatin n Wiki lid ilkkmn ɣid",
-       "tooltip-t-recentchangeslinked": "Imbddln imaynutn n tisnatin li ittylkamn s tasna yad",
+       "tooltip-t-recentchangeslinked": "ⵉⵙⵏⴼⵉⵍⵏ ⴳⴳⵯⵔⴰⵏⵉⵏ ⵖ ⵜⴰⵙⵏⵉⵡⵉⵏ ⵏⵏⴰ ⵙⵔⵙⵏ ⵜⴻⵜⵜⴰⵡⵉ ⵜⴰⵙⵏⴰ ⴰⴷ",
        "tooltip-feed-rss": "Usuddm (Flux) n tasna yad",
        "tooltip-feed-atom": "Usuddm Atum n tasna yad",
        "tooltip-t-contributions": "ⵜⴰⵍⴳⴰⵎⵜ ⵏ ⵜⵓⵎⵓⵜⵉⵏ ⵏ {{GENDER:$1|ⵓⵙⵎⵔⴰⵙ|ⵜⵙⵎⵔⴰⵙⵜ}} ⴰⴷ",
        "tooltip-t-emailuser": "Ṣafd tabrat umsqdac ad",
        "tooltip-t-upload": "ⵙⴽⵜⵔ ⵉⴼⴰⵢⵍⵓⵜⵏ",
-       "tooltip-t-specialpages": "âµ\9câ´°âµ\8dⴳⴰâµ\8eâµ\9c âµ\8f âµ\9câ´°âµ\99âµ\8fâµ\89ⵡâµ\89âµ\8f âµ¥âµ\8dâµ\89âµ\8fâµ\89âµ\8f â´°â´½â´½âµ¯",
+       "tooltip-t-specialpages": "âµ\9câ´°âµ\8dⴳⴰâµ\8eâµ\9c âµ\8f â´½âµ\93âµ\8dâµ\8dâµ\93 âµ\9câ´°âµ\99âµ\8fâµ\89ⵡâµ\89âµ\8f âµ¥âµ\8dâµ\89âµ\8fâµ\89âµ\8f",
        "tooltip-t-print": "Lqim uziggz n tasna yad",
        "tooltip-t-permalink": "Azday bdda i lqim n tasna yad",
-       "tooltip-ca-nstab-main": "Ẓr mayllan ɣ tasna",
+       "tooltip-ca-nstab-main": "ⵥⵔ ⵜⴰⵙⵏⴰ ⵏ ⵜⵓⵎⴰⵢⵜ",
        "tooltip-ca-nstab-user": "Ẓr tasna n useqdac",
        "tooltip-ca-nstab-media": "Iẓri n tasna n midya",
        "tooltip-ca-nstab-special": "ⵜⴰⴷ ⵜⴳⴰ ⵢⴰⵜ ⵜⴰⵙⵏⴰ ⵉⵥⵍⵉⵏ, ⴷ ⵓⵔ ⵉⵎⴽⵉⵏ ⴰⴷ ⵜⵜ ⵜⵙⵏⴼⵍⵜ",
        "tooltip-ca-nstab-project": "Żr tasna n twwuri",
-       "tooltip-ca-nstab-image": "Źr tasna n usdaw",
+       "tooltip-ca-nstab-image": "ⵥⵔ ⵜⴰⵙⵏⴰ ⵏ ⵓⴼⴰⵢⵍⵓ",
        "tooltip-ca-nstab-mediawiki": "Żr tabrat nu-nagraw.",
        "tooltip-ca-nstab-template": "Żr tamudemt",
        "tooltip-ca-nstab-help": "Źr tasna nu-saws",
-       "tooltip-ca-nstab-category": "Źr tasna nu-stay",
+       "tooltip-ca-nstab-category": "ⵥⵔ ⵜⴰⵙⵏⴰ ⵏ ⵜⴰⴳⴳⴰⵢⵜ",
        "tooltip-minoredit": "ⵔⵛⵎ ⴰⵢⴰ ⵎⴰⵙ ⵉⴳⴰ ⴰⵙⵏⴼⵍ ⵓⵎⵥⵉⵢ",
        "tooltip-save": "Ḥbu imbddel nek",
        "tooltip-preview": "Mel(fsr) imbddeln nek, urat tḥibit matskert",
        "previousdiff": "Imbddln imzwura",
        "nextdiff": "Ambdl d ittfrn  →",
        "widthheightpage": "$1 × $2, $3 {{PLURAL:$3|ⵜⴰⵙⵏⴰ|ⵜⴰⵙⵏⵉⵡⵉⵏ}}",
-       "file-info-size": "$1 × $2 piksil, asdaw tugut: $3, MIME anaw: $4",
+       "file-info-size": "$1 × $2 ⴱⵉⴽⵙⵉⵍ, ⵜⵉⴷⴷⵉ ⵏ ⵓⴼⴰⵢⵍⵓ: $3, ⴰⵏⴰⵡ MIME: $4",
        "file-nohires": "↓Ur tlli tabudut tamqrant.",
        "svg-long-desc": "Asdaw SVG, Tabadut n $1 × $2 ifrdan, Tiddi : $3",
        "show-big-image": "ⴰⴼⴰⵢⵍⵓ ⴰⵏⵚⵍⵉ",
        "specialpages-group-spam": "ladawat n spam",
        "blankpage": "tawriqt orgiss walo",
        "external_image_whitelist": "# Ajji aṣṭtar nna ɣiklli iga. <pre>\n# Ml igzman n tannayin (ɣir imi lli illan gr//) ɣ uzddar ɣid.\n# Rad tmiqqirn d tansiwin URL n tiwlaf n brra.\n# Tilli dis tmiqqirnin rad baynt zund tiwlaf, niɣd yan uzday s tawlaft arad ibayn.\n# Isṭṭarn lli ittizwirn s # rad gin zund iwnnan.\n# Tasna yad tfta d ugmmaḍ ad\n\n# Gatn igzman n iwnnan ɣ uflla n usṭṭar ad. Ajji yataṣṭṭar amggaru ɣiklli iga. </pre>",
-       "tag-filter": "Astay n [[Special:Tags|balises]] :",
+       "tag-filter": "ⵜⴰⵙⵜⵜⴰⵢⵜ ⵏ [[Special:Tags|ⵜⵔⵛⴰⵎⵉⵏ]]:",
        "tag-filter-submit": "Istayn",
        "tags-title": "imarkiwn",
        "tags-source-header": "ⴰⵙⴰⴳⵎ",
index 1783eba..a2c15f7 100644 (file)
        "and": "&#32;تے",
        "faq": "عام طور تے پچھے ونڄݨ آلے سوال",
        "actions": "کم",
-       "namespaces": "Ù\86اں Ø¯Û\8cاں Ø¬Û\81اÙ\88اں",
+       "namespaces": "Ù\86اں Ø¬Ø§Û\81Û\8cں",
        "variants": "قسماں",
        "navigation-heading": "فہرست رہنمائی",
        "errorpagetitle": "نقص",
        "timezoneregion-indian": "بحر ہند",
        "timezoneregion-pacific": "بحر الکاہل",
        "prefs-searchoptions": "ڳولو",
-       "prefs-namespaces": "Ù\86اں Ø¯Û\8cاں Ø¬Û\81اÙ\88اں",
+       "prefs-namespaces": "Ù\86اں Ø¬Ø§Û\81Û\8cں",
        "default": "پہلے کنوں طے تھیا ہویا",
        "prefs-files": "فائلاں",
        "prefs-custom-css": "کسٹم سی ایس ایس",
index 0f5b47c..e3f91eb 100644 (file)
        "rcfilters-restore-default-filters": "Obnovi privzete filtre",
        "rcfilters-clear-all-filters": "Počisti vse filtre",
        "rcfilters-show-new-changes": "Ogled najnovejših sprememb",
-       "rcfilters-previous-changes-label": "Predhodno videne spremembe",
        "rcfilters-search-placeholder": "Zadnje spremembe filtrov (prebrskajte ali začnite vnašati)",
        "rcfilters-invalid-filter": "Neveljaven filter",
        "rcfilters-empty-filter": "Ni dejavnih filtrov. Prikazani so vsi prispevki.",
index 5d0f971..5671525 100644 (file)
        "rcfilters-restore-default-filters": "Återställ standardfilter",
        "rcfilters-clear-all-filters": "Rensa alla filter",
        "rcfilters-show-new-changes": "Visa nyaste ändringarna",
-       "rcfilters-previous-changes-label": "Ändringar som visades tidigare",
        "rcfilters-search-placeholder": "Filtrera senaste ändringar (bläddra eller börja skriva)",
        "rcfilters-invalid-filter": "Ogiltigt filter",
        "rcfilters-empty-filter": "Inga aktiva filter. Alla bidrag visas.",
index 03bbe0b..cb1e5c8 100644 (file)
        "rcfilters-restore-default-filters": "Відновити стандартні фільтри",
        "rcfilters-clear-all-filters": "Очистити фільтри",
        "rcfilters-show-new-changes": "Переглянути найновіші зміни",
-       "rcfilters-previous-changes-label": "Раніше переглянуті зміни",
        "rcfilters-search-placeholder": "Фільтруйте нові редагування (переглядайте або почніть вводити)",
        "rcfilters-invalid-filter": "Недійсний фільтр",
        "rcfilters-empty-filter": "Без фільтрів. Показано всі зміни.",
index 041a7e1..3ad8e1f 100644 (file)
        "rcfilters-restore-default-filters": "恢复默认过滤器",
        "rcfilters-clear-all-filters": "清空所有过滤器",
        "rcfilters-show-new-changes": "显示最新更改",
-       "rcfilters-previous-changes-label": "之前查看过的更改",
        "rcfilters-search-placeholder": "过滤器最近更改(浏览或开始输入)",
        "rcfilters-invalid-filter": "无效过滤器",
        "rcfilters-empty-filter": "没有激活的过滤器。已显示所有贡献。",
index f0612f4..342ccef 100644 (file)
        "rcfilters-savedqueries-add-new-title": "儲存目前的過濾器設定",
        "rcfilters-restore-default-filters": "還原預設過濾條件",
        "rcfilters-clear-all-filters": "清除所有過濾條件",
+       "rcfilters-show-new-changes": "顯示最新更改",
        "rcfilters-search-placeholder": "過濾條件近期變更 (瀏覽或開始輸入)",
        "rcfilters-invalid-filter": "無效的過濾條件",
        "rcfilters-empty-filter": "沒有使用中的過濾條件。已顯示所有的貢獻。",
index 6acc44d..4dc86f6 100644 (file)
        mw.rcfilters.dm.FilterGroup.prototype.onFilterItemUpdate = function ( item ) {
                // Update state
                var changed = false,
-                       active = this.areAnySelected();
-
-               if (
-                       item.isSelected() &&
-                       this.getType() === 'single_option' &&
-                       this.currSelected &&
-                       this.currSelected !== item
-               ) {
-                       this.currSelected.toggleSelected( false );
-               }
-
-               // For 'single_option' groups, check if we just unselected all
-               // items. This should never be the result. If we did unselect
-               // all (like resetting all filters to false) then this group
-               // must choose its default item or the first item in the group
-               if (
-                       this.getType() === 'single_option' &&
-                       !this.getItems().some( function ( filterItem ) {
-                               return filterItem.isSelected();
-                       } )
-               ) {
-                       // Single option means there must be a single option
-                       // selected, so we have to either select the default
-                       // or select the first option
-                       this.currSelected = this.getItemByParamName( this.defaultParams[ this.getName() ] ) ||
-                               this.getItems()[ 0 ];
-                       this.currSelected.toggleSelected( true );
-                       changed = true;
+                       active = this.areAnySelected(),
+                       model = this;
+
+               if ( this.getType() === 'single_option' ) {
+                       // This group must have one item selected always
+                       // and must never have more than one item selected at a time
+                       if ( this.getSelectedItems().length === 0 ) {
+                               // Nothing is selected anymore
+                               // Select the default or the first item
+                               this.currSelected = this.getItemByParamName( this.defaultParams[ this.getName() ] ) ||
+                                       this.getItems()[ 0 ];
+                               this.currSelected.toggleSelected( true );
+                               changed = true;
+                       } else if ( this.getSelectedItems().length > 1 ) {
+                               // There is more than one item selected
+                               // This should only happen if the item given
+                               // is the one that is selected, so unselect
+                               // all items that is not it
+                               this.getSelectedItems().forEach( function ( itemModel ) {
+                                       // Note that in case the given item is actually
+                                       // not selected, this loop will end up unselecting
+                                       // all items, which would trigger the case above
+                                       // when the last item is unselected anyways
+                                       var selected = itemModel.getName() === item.getName() &&
+                                               item.isSelected();
+
+                                       itemModel.toggleSelected( selected );
+                                       if ( selected ) {
+                                               model.currSelected = itemModel;
+                                       }
+                               } );
+                               changed = true;
+                       }
                }
 
                if (
index 6322ccd..e56e807 100644 (file)
        );
 
        $( function () {
-               var $links = $( '.mw-watchlink a, a.mw-watchlink' );
-               // Restrict to core interfaces, ignore user-generated content
-               $links = $links.filter( ':not( #bodyContent *, #content * )' );
+               var $links = $( '.mw-watchlink a[data-mw="interface"], a.mw-watchlink[data-mw="interface"]' );
+               if ( !$links.length ) {
+                       // Fallback to the class-based exclusion method for backwards-compatibility
+                       $links = $( '.mw-watchlink a, a.mw-watchlink' );
+                       // Restrict to core interfaces, ignore user-generated content
+                       $links = $links.filter( ':not( #bodyContent *, #content * )' );
+               }
 
                $links.click( function ( e ) {
                        var mwTitle, action, api, $link;
diff --git a/tests/phpunit/includes/db/LoadBalancerTest.php b/tests/phpunit/includes/db/LoadBalancerTest.php
new file mode 100644 (file)
index 0000000..f8ab7f4
--- /dev/null
@@ -0,0 +1,135 @@
+<?php
+
+use Wikimedia\Rdbms\LoadBalancer;
+
+/**
+ * Holds tests for LoadBalancer MediaWiki class.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ *
+ * @group Database
+ * @file
+ */
+class LoadBalancerTest extends MediaWikiTestCase {
+       public function testLBSimpleServer() {
+               global $wgDBserver, $wgDBname, $wgDBuser, $wgDBpassword, $wgDBtype, $wgSQLiteDataDir;
+
+               $servers = [
+                       [
+                               'host'        => $wgDBserver,
+                               'dbname'      => $wgDBname,
+                               'user'        => $wgDBuser,
+                               'password'    => $wgDBpassword,
+                               'type'        => $wgDBtype,
+                               'dbDirectory' => $wgSQLiteDataDir,
+                               'load'        => 0,
+                               'flags'       => DBO_TRX // REPEATABLE-READ for consistency
+                       ],
+               ];
+
+               $lb = new LoadBalancer( [
+                       'servers' => $servers,
+                       'localDomain' => wfWikiID()
+               ] );
+
+               $dbw = $lb->getConnection( DB_MASTER );
+               $this->assertTrue( $dbw->getLBInfo( 'master' ), 'master shows as master' );
+               $this->assertTrue( $dbw->getFlag( $dbw::DBO_TRX ), "DBO_TRX set on master" );
+
+               $dbr = $lb->getConnection( DB_REPLICA );
+               $this->assertTrue( $dbr->getLBInfo( 'master' ), 'DB_REPLICA also gets the master' );
+               $this->assertTrue( $dbw->getFlag( $dbw::DBO_TRX ), "DBO_TRX set on replica" );
+
+               $dbwAuto = $lb->getConnection( DB_MASTER, [], false, $lb::CONN_TRX_AUTO );
+               $this->assertFalse( $dbwAuto->getFlag( $dbw::DBO_TRX ), "No DBO_TRX with CONN_TRX_AUTO" );
+               $this->assertTrue( $dbw->getFlag( $dbw::DBO_TRX ), "DBO_TRX still set on master" );
+               $this->assertNotEquals( $dbw, $dbwAuto, "CONN_TRX_AUTO uses separate connection" );
+
+               $dbrAuto = $lb->getConnection( DB_REPLICA, [], false, $lb::CONN_TRX_AUTO );
+               $this->assertFalse( $dbrAuto->getFlag( $dbw::DBO_TRX ), "No DBO_TRX with CONN_TRX_AUTO" );
+               $this->assertTrue( $dbr->getFlag( $dbw::DBO_TRX ), "DBO_TRX still set on replica" );
+               $this->assertNotEquals( $dbr, $dbrAuto, "CONN_TRX_AUTO uses separate connection" );
+
+               $dbwAuto2 = $lb->getConnection( DB_MASTER, [], false, $lb::CONN_TRX_AUTO );
+               $this->assertEquals( $dbwAuto2, $dbwAuto, "CONN_TRX_AUTO reuses connections" );
+
+               $lb->closeAll();
+       }
+
+       public function testLBSimpleServers() {
+               global $wgDBserver, $wgDBname, $wgDBuser, $wgDBpassword, $wgDBtype, $wgSQLiteDataDir;
+
+               $servers = [
+                       [ // master
+                               'host'        => $wgDBserver,
+                               'dbname'      => $wgDBname,
+                               'user'        => $wgDBuser,
+                               'password'    => $wgDBpassword,
+                               'type'        => $wgDBtype,
+                               'dbDirectory' => $wgSQLiteDataDir,
+                               'load'        => 0,
+                               'flags'       => DBO_TRX // REPEATABLE-READ for consistency
+                       ],
+                       [ // emulated slave
+                               'host'        => $wgDBserver,
+                               'dbname'      => $wgDBname,
+                               'user'        => $wgDBuser,
+                               'password'    => $wgDBpassword,
+                               'type'        => $wgDBtype,
+                               'dbDirectory' => $wgSQLiteDataDir,
+                               'load'        => 100,
+                               'flags'       => DBO_TRX // REPEATABLE-READ for consistency
+                       ]
+               ];
+
+               $lb = new LoadBalancer( [
+                       'servers' => $servers,
+                       'localDomain' => wfWikiID(),
+                       'loadMonitorClass' => 'LoadMonitorNull'
+               ] );
+
+               $dbw = $lb->getConnection( DB_MASTER );
+               $this->assertTrue( $dbw->getLBInfo( 'master' ), 'master shows as master' );
+               $this->assertEquals(
+                       ( $wgDBserver != '' ) ? $wgDBserver : 'localhost',
+                       $dbw->getLBInfo( 'clusterMasterHost' ),
+                       'cluster master set' );
+               $this->assertTrue( $dbw->getFlag( $dbw::DBO_TRX ), "DBO_TRX set on master" );
+
+               $dbr = $lb->getConnection( DB_REPLICA );
+               $this->assertTrue( $dbr->getLBInfo( 'replica' ), 'slave shows as slave' );
+               $this->assertEquals(
+                       ( $wgDBserver != '' ) ? $wgDBserver : 'localhost',
+                       $dbr->getLBInfo( 'clusterMasterHost' ),
+                       'cluster master set' );
+               $this->assertTrue( $dbw->getFlag( $dbw::DBO_TRX ), "DBO_TRX set on replica" );
+
+               $dbwAuto = $lb->getConnection( DB_MASTER, [], false, $lb::CONN_TRX_AUTO );
+               $this->assertFalse( $dbwAuto->getFlag( $dbw::DBO_TRX ), "No DBO_TRX with CONN_TRX_AUTO" );
+               $this->assertTrue( $dbw->getFlag( $dbw::DBO_TRX ), "DBO_TRX still set on master" );
+               $this->assertNotEquals( $dbw, $dbwAuto, "CONN_TRX_AUTO uses separate connection" );
+
+               $dbrAuto = $lb->getConnection( DB_REPLICA, [], false, $lb::CONN_TRX_AUTO );
+               $this->assertFalse( $dbrAuto->getFlag( $dbw::DBO_TRX ), "No DBO_TRX with CONN_TRX_AUTO" );
+               $this->assertTrue( $dbr->getFlag( $dbw::DBO_TRX ), "DBO_TRX still set on replica" );
+               $this->assertNotEquals( $dbr, $dbrAuto, "CONN_TRX_AUTO uses separate connection" );
+
+               $dbwAuto2 = $lb->getConnection( DB_MASTER, [], false, $lb::CONN_TRX_AUTO );
+               $this->assertEquals( $dbwAuto2, $dbwAuto, "CONN_TRX_AUTO reuses connections" );
+
+               $lb->closeAll();
+       }
+}