Merge "ApiBase: Use prefixed parameter name for 'missingparam' error"
authorjenkins-bot <jenkins-bot@gerrit.wikimedia.org>
Wed, 25 Jul 2018 05:29:12 +0000 (05:29 +0000)
committerGerrit Code Review <gerrit@wikimedia.org>
Wed, 25 Jul 2018 05:29:12 +0000 (05:29 +0000)
54 files changed:
RELEASE-NOTES-1.32
includes/DefaultSettings.php
includes/GlobalFunctions.php
includes/OutputPage.php
includes/PathRouter.php
includes/WebRequest.php
includes/api/ApiQuerySiteinfo.php
includes/api/i18n/zh-hans.json
includes/installer/i18n/it.json
includes/installer/i18n/vi.json
includes/libs/objectcache/BagOStuff.php
includes/logging/LogEventsList.php
includes/logging/LogPager.php
includes/page/PageArchive.php
includes/resourceloader/ResourceLoaderLanguageDataModule.php
languages/FakeConverter.php
languages/LanguageCode.php
languages/LanguageConverter.php
languages/data/Names.php
languages/i18n/af.json
languages/i18n/be-tarask.json
languages/i18n/de.json
languages/i18n/es.json
languages/i18n/fr.json
languages/i18n/it.json
languages/i18n/ko.json
languages/i18n/kw.json
languages/i18n/mg.json
languages/i18n/mk.json
languages/i18n/mr.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/sl.json
languages/i18n/sr-ec.json
languages/i18n/sw.json
languages/i18n/te.json
languages/i18n/vi.json
languages/i18n/zh-hans.json
languages/i18n/zh-hant.json
languages/i18n/zh-hk.json
resources/src/mediawiki.language/mediawiki.language.init.js
resources/src/mediawiki.language/mediawiki.language.js
tests/phpunit/includes/GlobalFunctions/wfExpandUrlTest.php
tests/phpunit/includes/MediaWikiTest.php
tests/phpunit/includes/PathRouterTest.php
tests/phpunit/includes/api/format/ApiFormatBaseTest.php
tests/phpunit/includes/htmlform/HTMLFormTest.php
tests/phpunit/languages/LanguageCodeTest.php
tests/phpunit/languages/LanguageConverterTest.php
tests/qunit/suites/resources/mediawiki/mediawiki.language.test.js

index 9589c19..7ac5479 100644 (file)
@@ -195,9 +195,6 @@ because of Phabricator reports.
   CapsuleMultiselectWidget. The following methods may no longer be used:
   * setItemsFromData: Use setValue instead
   * getItemsData: Use getItems instead and get the data property
-* LanguageCode::bcp47() now always returns a valid BCP 47 code.  This means
-  that some MediaWiki-specific language codes, such as `simple`, are mapped
-  into valid BCP 47 codes (eg `en-simple`).
 
 === Deprecations in 1.32 ===
 * Use of a StartProfiler.php file is deprecated in favour of placing
index 2811613..84131f0 100644 (file)
@@ -8669,9 +8669,14 @@ $wgSiteTypes = [
 $wgPagePropsHaveSortkey = true;
 
 /**
- * Port where you have HTTPS running
- * Supports HTTPS on non-standard ports
- * @see T67184
+ * For installations where the canonical server is HTTP but HTTPS is optionally
+ * supported, you can specify a non-standard HTTPS port here. $wgServer should
+ * be a protocol-relative URL.
+ *
+ * If HTTPS is always used, just specify the port number in $wgServer.
+ *
+ * @see https://phabricator.wikimedia.org/T67184
+ *
  * @since 1.24
  */
 $wgHttpsPort = 443;
index eec4216..aa8aee5 100644 (file)
@@ -548,17 +548,24 @@ function wfExpandUrl( $url, $defaultProto = PROTO_CURRENT ) {
        } elseif ( substr( $url, 0, 1 ) == '/' ) {
                // If $serverUrl is protocol-relative, prepend $defaultProtoWithoutSlashes,
                // otherwise leave it alone.
-               $url = ( $serverHasProto ? '' : $defaultProtoWithoutSlashes ) . $serverUrl . $url;
+               if ( $serverHasProto ) {
+                       $url = $serverUrl . $url;
+               } else {
+                       // If an HTTPS URL is synthesized from a protocol-relative $wgServer, allow the
+                       // user to override the port number (T67184)
+                       if ( $defaultProto === PROTO_HTTPS && $wgHttpsPort != 443 ) {
+                               if ( isset( $bits['port'] ) ) {
+                                       throw new Exception( 'A protocol-relative $wgServer may not contain a port number' );
+                               }
+                               $url = $defaultProtoWithoutSlashes . $serverUrl . ':' . $wgHttpsPort . $url;
+                       } else {
+                               $url = $defaultProtoWithoutSlashes . $serverUrl . $url;
+                       }
+               }
        }
 
        $bits = wfParseUrl( $url );
 
-       // ensure proper port for HTTPS arrives in URL
-       // https://phabricator.wikimedia.org/T67184
-       if ( $defaultProto === PROTO_HTTPS && $wgHttpsPort != 443 ) {
-               $bits['port'] = $wgHttpsPort;
-       }
-
        if ( $bits && isset( $bits['path'] ) ) {
                $bits['path'] = wfRemoveDotSegments( $bits['path'] );
                return wfAssembleUrl( $bits );
@@ -574,6 +581,19 @@ function wfExpandUrl( $url, $defaultProto = PROTO_CURRENT ) {
        return false;
 }
 
+/**
+ * Get the wiki's "server", i.e. the protocol and host part of the URL, with a
+ * protocol specified using a PROTO_* constant as in wfExpandUrl()
+ *
+ * @since 1.32
+ * @param string|int|null $proto One of the PROTO_* constants.
+ * @return string The URL
+ */
+function wfGetServerUrl( $proto ) {
+       $url = wfExpandUrl( '/', $proto );
+       return substr( $url, 0, -1 );
+}
+
 /**
  * This function will reassemble a URL parsed with wfParseURL.  This is useful
  * if you need to edit part of a URL and put it back together.
index 5965cbe..4e7c0bb 100644 (file)
@@ -55,9 +55,8 @@ class OutputPage extends ContextSource {
        protected $mCanonicalUrl = false;
 
        /**
-        * @var string Should be private - has getter and setter. Contains
-        *   the HTML title */
-       public $mPagetitle = '';
+        * @var string The contents of <h1> */
+       private $mPageTitle = '';
 
        /**
         * @var string Contains all of the "<body>" content. Should be private we
@@ -992,7 +991,7 @@ class OutputPage extends ContextSource {
                # change "<script>foo&bar</script>" to "&lt;script&gt;foo&amp;bar&lt;/script&gt;"
                # but leave "<i>foobar</i>" alone
                $nameWithTags = Sanitizer::normalizeCharReferences( Sanitizer::removeHTMLtags( $name ) );
-               $this->mPagetitle = $nameWithTags;
+               $this->mPageTitle = $nameWithTags;
 
                # change "<i>foo&amp;bar</i>" to "foo&bar"
                $this->setHTMLTitle(
@@ -1007,7 +1006,7 @@ class OutputPage extends ContextSource {
         * @return string
         */
        public function getPageTitle() {
-               return $this->mPagetitle;
+               return $this->mPageTitle;
        }
 
        /**
index f24e298..faf4db4 100644 (file)
@@ -240,6 +240,28 @@ class PathRouter {
                // matches are tested first
                $this->sortByWeight();
 
+               $matches = $this->internalParse( $path );
+               if ( is_null( $matches ) ) {
+                       // Try with the normalized path (T100782)
+                       $path = wfRemoveDotSegments( $path );
+                       $path = preg_replace( '#/+#', '/', $path );
+                       $matches = $this->internalParse( $path );
+               }
+
+               // We know the difference between null (no matches) and
+               // array() (a match with no data) but our WebRequest caller
+               // expects array() even when we have no matches so return
+               // a array() when we have null
+               return is_null( $matches ) ? [] : $matches;
+       }
+
+       /**
+        * Match a path against each defined pattern
+        *
+        * @param string $path
+        * @return array|null
+        */
+       protected function internalParse( $path ) {
                $matches = null;
 
                foreach ( $this->patterns as $pattern ) {
@@ -248,12 +270,7 @@ class PathRouter {
                                break;
                        }
                }
-
-               // We know the difference between null (no matches) and
-               // array() (a match with no data) but our WebRequest caller
-               // expects array() even when we have no matches so return
-               // a array() when we have null
-               return is_null( $matches ) ? [] : $matches;
+               return $matches;
        }
 
        /**
index f3edebc..e31d3f9 100644 (file)
@@ -856,7 +856,7 @@ class WebRequest {
         * @return string
         */
        public function getFullRequestURL() {
-               return wfExpandUrl( $this->getRequestURL(), PROTO_CURRENT );
+               return wfGetServerUrl( PROTO_CURRENT ) .  $this->getRequestURL();
        }
 
        /**
index f23c6a6..4b408fc 100644 (file)
@@ -705,10 +705,7 @@ class ApiQuerySiteinfo extends ApiQueryBase {
                $data = [];
 
                foreach ( $langNames as $code => $name ) {
-                       $lang = [
-                               'code' => $code,
-                               'bcp47' => LanguageCode::bcp47( $code ),
-                       ];
+                       $lang = [ 'code' => $code ];
                        ApiResult::setContentValue( $lang, 'name', $name );
                        $data[] = $lang;
                }
index 1cc7c5c..155d563 100644 (file)
        "apihelp-purge-example-simple": "刷新<kbd>Main Page</kbd>和<kbd>API</kbd>页面。",
        "apihelp-purge-example-generator": "刷新主名字空间的前10个页面。",
        "apihelp-query-summary": "取得来自并有关MediaWiki的数据。",
-       "apihelp-query-extended-description": "所有数据修改将首先不得不使用查询来获得令牌,以阻止来自恶意网站的滥用行为。",
+       "apihelp-query-extended-description": "所有数据修改须首先使用查询来获得令牌,以阻止来自恶意网站的滥用行为。",
        "apihelp-query-param-prop": "要为已查询页面获取的属性。",
        "apihelp-query-param-list": "要获取的列表。",
        "apihelp-query-param-meta": "要获取的元数据。",
index bea4607..b8db489 100644 (file)
        "config-sqlite-dir-help": "SQLite memorizza tutti i dati in un unico file.\n\nLa directory che indicherai deve essere scrivibile dal server web durante l'installazione.\n\nDovrebbe essere <strong>non accessibile via web</strong>, è per questo che non la stiamo mettendo dove ci sono i file PHP.\n\nL'installatore scriverà insieme ad essa un file <code>.htaccess</code>, ma se il tentativo fallisse qualcuno potrebbe avere accesso al database grezzo.\nQuesto include dati utente grezzi (indirizzi, password cifrate) così come versioni eliminate e altri dati ad accesso limitato del wiki.\n\nConsidera l'opportunità di sistemare allo stesso tempo il database da qualche altra parte, per esempio in <code>/var/lib/mediawiki/tuowiki</code>.",
        "config-oracle-def-ts": "Tablespace di default:",
        "config-oracle-temp-ts": "Tablespace temporaneo:",
-       "config-type-mysql": "MySQL (o compatibile)",
+       "config-type-mysql": "MariaDB, MySQL o compatibile",
        "config-type-mssql": "Microsoft SQL Server",
        "config-support-info": "MediaWiki supporta i seguenti sistemi di database:\n\n$1\n\nSe fra quelli elencati qui sotto non vedi il sistema di database che vorresti utilizzare, seguire le istruzioni linkate sopra per abilitare il supporto.",
-       "config-dbsupport-mysql": "* [{{int:version-db-mysql-url}} MySQL] è la configurazione preferibile per MediaWiki ed è quella meglio supportata. MediaWiki funziona anche con [{{int:version-db-mariadb-url}} MariaDB] e [{{int:version-db-percona-url}} Percona Server], che sono compatibili con MySQL.([https://secure.php.net/manual/en/mysqli.installation.php Come compilare PHP con supporto MySQL])",
+       "config-dbsupport-mysql": "* [{{int:version-db-mariadb-url}} MariaDB] è la configurazione preferibile per MediaWiki ed è quella meglio supportata. MediaWiki funziona anche con [{{int:version-db-mysql-url}} MySQL] e [{{int:version-db-percona-url}} Percona Server], che sono compatibili con MariaDB.([https://secure.php.net/manual/en/mysqli.installation.php Come compilare PHP con supporto MySQL])",
        "config-dbsupport-postgres": "* [{{int:version-db-postgres-url}} PostgreSQL] è un popolare sistema di database open source come alternativa a MySQL. ([https://secure.php.net/manual/en/pgsql.installation.php Come compilare PHP con supporto PostgreSQL])",
        "config-dbsupport-sqlite": "* [{{int:version-db-sqlite-url}} SQLite]  è un sistema di database leggero, che è supportato molto bene. ([https://secure.php.net/manual/en/pdo.installation.php Come compilare PHP con supporto SQLite], utilizza PDO)",
        "config-dbsupport-oracle": "* [{{int:version-db-oracle-url}} Oracle] è un database di un'impresa commerciale. ([https://secure.php.net/manual/en/oci8.installation.php Come compilare PHP con supporto OCI8])",
index 7b3462d..ca87d60 100644 (file)
        "config-sqlite-dir-help": "SQLite lưu tất cả các dữ liệu trong một tập tin duy nhất.\n\nThư mục mà bạn cung cấp phải cho phép máy chủ Web ghi vào khi cài đặt.\n\n<strong>Không</strong> nên làm cho nó truy cập được qua Web; đây là lý do chúng tôi không đặt nó vào cùng thư mục với các tập tin PHP của bạn.\n\nTrình cài đặt sẽ ghi một tập tin <code>.htaccess</code> đi kèm, nhưng nếu thất bại người nào đó có thể truy cập vào cơ sở dữ liệu thô của bạn.\nĐiều đó bao gồm dữ liệu người dùng thô (địa chỉ thư điện tử, mật khẩu được băm) cũng như các phiên bản bị xóa và dữ liệu bị hạn chế khác trên wiki.\n\nXem xét đặt cơ sở dữ liệu tại nơi nào khác hẳn, ví dụ trong <code>/var/lib/mediawiki/wiki_cua_ban</code>.",
        "config-oracle-def-ts": "Không gian bảng mặc định:",
        "config-oracle-temp-ts": "Không gian bảng tạm:",
-       "config-type-mysql": "MySQL (hoặc tương hợp)",
+       "config-type-mysql": "MariaDB, MySQL, hoặc tương hợp",
        "config-type-mssql": "Microsoft SQL Server",
        "config-support-info": "MediaWiki hỗ trợ các hệ thống cơ sở dữ liệu sau đây:\n\n$1\n\nNếu bạn không thấy hệ thống cơ sở dữ liệu mà bạn đang muốn sử dụng được liệt kê dưới đây, thì hãy theo chỉ dẫn được liên kết ở trên để kích hoạt tính năng hỗ trợ.",
-       "config-dbsupport-mysql": "* [{{int:version-db-mysql-url}} MySQL] là mục tiêu chính cho MediaWiki và được hỗ trợ tốt nhất. MediaWiki cũng làm việc với [{{int:version-db-mariadb-url}} MariaDB] và [{{int:version-db-percona-url}} Percona Server], là những cơ sở dữ liệu tương thích với MySQL. ([https://secure.php.net/manual/en/mysqli.installation.php Làm thế nào để biên dịch PHP với sự hỗ trợ của MySQL])",
+       "config-dbsupport-mysql": "* [{{int:version-db-mariadb-url}} MariaDB] là mục tiêu chính cho MediaWiki và được hỗ trợ tốt nhất. MediaWiki cũng làm việc với [{{int:version-db-mysql-url}} MySQL] và [{{int:version-db-percona-url}} Percona Server], là những cơ sở dữ liệu tương thích với MariaDB. ([https://secure.php.net/manual/en/mysqli.installation.php Làm thế nào để biên dịch PHP với sự hỗ trợ của MySQL])",
        "config-dbsupport-postgres": "* [{{int:version-db-postgres-url}} PostgreSQL] là một hệ thống cơ sở dữ liệu mã nguồn mở phổ biến như là một thay thế cho MySQL. ([https://secure.php.net/manual/en/pgsql.installation.php Làm thế nào để biên dịch PHP với sự hỗ trợ của PostgreSQL])",
        "config-dbsupport-sqlite": "* [{{int:version-db-sqlite-url}} SQLite] là một hệ thống cơ sở dữ liệu dung lượng nhẹ được hỗ trợ rất tốt. ([https://secure.php.net/manual/en/pdo.installation.php Làm thế nào để biên dịch PHP với sự hỗ trợ của SQLite], sử dụng PDO)",
        "config-dbsupport-oracle": "* [{{int:version-db-oracle-url}} Oracle] là một cơ sở dữ liệu doanh nghiệp thương mại. ([https://secure.php.net/manual/en/oci8.installation.php Làm thế nào để biên dịch PHP với sự hỗ trợ của OCI8])",
        "config-dbsupport-mssql": "* [{{int:version-db-mssql-url}} Microsoft SQL Server] là một cơ sở dữ liệu doanh nghiệp thương mại cho Windows. ([https://secure.php.net/manual/en/sqlsrv.installation.php Làm thế nào để biên dịch PHP với sự hỗ trợ của SQLSRV])",
-       "config-header-mysql": "Thiết lập MySQL",
+       "config-header-mysql": "Thiết lập MariaDB/MySQL",
        "config-header-postgres": "Thiết lập PostgreSQL",
        "config-header-sqlite": "Thiết lập SQLite",
        "config-header-oracle": "Thiết lập Oracle",
        "config-db-web-create": "Mở tài khoản nếu chưa tồn tại",
        "config-db-web-no-create-privs": "Tài khoản mà bạn xác định để cài đặt không có đủ quyền để tạo một tài khoản. Tài khoản mà bạn chỉ ra ở đây phải thực sự tồn tại trước đó.",
        "config-mysql-engine": "Máy lưu trữ:",
-       "config-mysql-innodb": "InnoDB",
+       "config-mysql-innodb": "InnoDB (khuyến khích)",
        "config-mysql-myisam": "MyISAM",
        "config-mysql-myisam-dep": "<strong>Cảnh báo:</strong> Bạn đã chọn MyISAM làm động cơ lưu trữ cho MySQL, điều này không được khuyến khích sử dụng với MediaWiki, bởi vì:\n* Nó ít hỗ trợ đồng thời do việc khóa bảng\n* Nó dễ bị lỗi hơn so với các động cơ khác\n* Kho mã nguồn của MediaWiki không phải khi nào cũng xử lý MyISAM như mong muốn\n\nNếu cài đặt MySQL của bạn hỗ trợ InnoDB, đặc biệt khuyến cáo bạn nên chọn để thay thế.\nNếu cài đặt MySQL của bạn không hỗ trợ InnoDB, có lẽ đã đến lúc để nâng cấp.",
        "config-mysql-only-myisam-dep": "<strong>Cảnh báo:</strong> MyISAM chỉ là công cụ lưu trữ có sẵn cho MySQL trên máy tính này, và điều này không được khuyến khích sử dụng với MediaWiki, bởi vì:\n* Nó ít hỗ trợ đồng thời do việc khóa khóa\n* Nó là dễ bị hư hỏng hơn các engine khác\n* Codebase MediaWiki không phải khi nào cũng xử lý MyISAM như mong muốn\n\nCài đặt MySQL của bạn không hỗ trợ InnoDB, có lẽ đã đến lúc để nâng cấp.",
index 782f4c6..e03645f 100644 (file)
@@ -133,7 +133,7 @@ abstract class BagOStuff implements IExpiringStore, LoggerAwareInterface {
 
        /**
         * @param LoggerInterface $logger
-        * @return null
+        * @return void
         */
        public function setLogger( LoggerInterface $logger ) {
                $this->logger = $logger;
@@ -308,6 +308,11 @@ abstract class BagOStuff implements IExpiringStore, LoggerAwareInterface {
                        $this->reportDupes = $reportDupes;
 
                        if ( $this->getLastError() ) {
+                               $this->logger->warning(
+                                       __METHOD__ . ' failed due to I/O error on get() for {key}.',
+                                       [ 'key' => $key ]
+                               );
+
                                return false; // don't spam retries (retry only on races)
                        }
 
@@ -325,6 +330,11 @@ abstract class BagOStuff implements IExpiringStore, LoggerAwareInterface {
                                $success = $this->cas( $casToken, $key, $value, $exptime );
                        }
                        if ( $this->getLastError() ) {
+                               $this->logger->warning(
+                                       __METHOD__ . ' failed due to I/O error for {key}.',
+                                       [ 'key' => $key ]
+                               );
+
                                return false; // IO error; don't spam retries
                        }
                } while ( !$success && --$attempts );
@@ -352,6 +362,11 @@ abstract class BagOStuff implements IExpiringStore, LoggerAwareInterface {
                if ( $casToken === $curCasToken ) {
                        $success = $this->set( $key, $value, $exptime );
                } else {
+                       $this->logger->info(
+                               __METHOD__ . ' failed due to race condition for {key}.',
+                               [ 'key' => $key ]
+                       );
+
                        $success = false; // mismatched or failed
                }
 
@@ -388,6 +403,11 @@ abstract class BagOStuff implements IExpiringStore, LoggerAwareInterface {
                $this->reportDupes = $reportDupes;
 
                if ( $this->getLastError() ) {
+                       $this->logger->warning(
+                               __METHOD__ . ' failed due to I/O error on get() for {key}.',
+                               [ 'key' => $key ]
+                       );
+
                        $success = false;
                } else {
                        // Derive the new value from the old value
@@ -443,13 +463,19 @@ abstract class BagOStuff implements IExpiringStore, LoggerAwareInterface {
                        }
                }
 
+               $fname = __METHOD__;
                $expiry = min( $expiry ?: INF, self::TTL_DAY );
                $loop = new WaitConditionLoop(
-                       function () use ( $key, $timeout, $expiry ) {
+                       function () use ( $key, $timeout, $expiry, $fname ) {
                                $this->clearLastError();
                                if ( $this->add( "{$key}:lock", 1, $expiry ) ) {
                                        return true; // locked!
                                } elseif ( $this->getLastError() ) {
+                                       $this->logger->warning(
+                                               $fname . ' failed due to I/O error for {key}.',
+                                               [ 'key' => $key ]
+                                       );
+
                                        return WaitConditionLoop::CONDITION_ABORTED; // network partition?
                                }
 
@@ -458,9 +484,15 @@ abstract class BagOStuff implements IExpiringStore, LoggerAwareInterface {
                        $timeout
                );
 
-               $locked = ( $loop->invoke() === $loop::CONDITION_REACHED );
+               $code = $loop->invoke();
+               $locked = ( $code === $loop::CONDITION_REACHED );
                if ( $locked ) {
                        $this->locks[$key] = [ 'class' => $rclass, 'depth' => 1 ];
+               } elseif ( $code === $loop::CONDITION_TIMED_OUT ) {
+                       $this->logger->warning(
+                               "$fname failed due to timeout for {key}.",
+                               [ 'key' => $key, 'timeout' => $timeout ]
+                       );
                }
 
                return $locked;
@@ -476,7 +508,15 @@ abstract class BagOStuff implements IExpiringStore, LoggerAwareInterface {
                if ( isset( $this->locks[$key] ) && --$this->locks[$key]['depth'] <= 0 ) {
                        unset( $this->locks[$key] );
 
-                       return $this->delete( "{$key}:lock" );
+                       $ok = $this->delete( "{$key}:lock" );
+                       if ( !$ok ) {
+                               $this->logger->warning(
+                                       __METHOD__ . ' failed to release lock for {key}.',
+                                       [ 'key' => $key ]
+                               );
+                       }
+
+                       return $ok;
                }
 
                return true;
@@ -511,7 +551,10 @@ abstract class BagOStuff implements IExpiringStore, LoggerAwareInterface {
                        $latency = 0.050; // latency skew (err towards keeping lock present)
                        $age = ( $this->getCurrentTime() - $lSince + $latency );
                        if ( ( $age + $latency ) >= $expiry ) {
-                               $this->logger->warning( "Lock for $key held too long ($age sec)." );
+                               $this->logger->warning(
+                                       "Lock for {key} held too long ({age} sec).",
+                                       [ 'key' => $key, 'age' => $age ]
+                               );
                                return; // expired; it's not "safe" to delete the key
                        }
                        $this->unlock( $key );
@@ -573,6 +616,7 @@ abstract class BagOStuff implements IExpiringStore, LoggerAwareInterface {
         * @return bool Success
         */
        public function add( $key, $value, $exptime = 0 ) {
+               // @note: avoid lock() here since that method uses *this* method by default
                if ( $this->get( $key ) === false ) {
                        return $this->set( $key, $value, $exptime );
                }
@@ -586,7 +630,7 @@ abstract class BagOStuff implements IExpiringStore, LoggerAwareInterface {
         * @return int|bool New value or false on failure
         */
        public function incr( $key, $value = 1 ) {
-               if ( !$this->lock( $key ) ) {
+               if ( !$this->lock( $key, 1 ) ) {
                        return false;
                }
                $n = $this->get( $key );
@@ -624,14 +668,15 @@ abstract class BagOStuff implements IExpiringStore, LoggerAwareInterface {
         * @since 1.24
         */
        public function incrWithInit( $key, $ttl, $value = 1, $init = 1 ) {
+               $this->clearLastError();
                $newValue = $this->incr( $key, $value );
-               if ( $newValue === false ) {
+               if ( $newValue === false && !$this->getLastError() ) {
                        // No key set; initialize
                        $newValue = $this->add( $key, (int)$init, $ttl ) ? $init : false;
-               }
-               if ( $newValue === false ) {
-                       // Raced out initializing; increment
-                       $newValue = $this->incr( $key, $value );
+                       if ( $newValue === false && !$this->getLastError() ) {
+                               // Raced out initializing; increment
+                               $newValue = $this->incr( $key, $value );
+                       }
                }
 
                return $newValue;
index 73aaa4f..db97364 100644 (file)
@@ -110,8 +110,6 @@ class LogEventsList extends ContextSource {
        public function showOptions( $types = [], $user = '', $page = '', $pattern = false, $year = 0,
                $month = 0, $day = 0, $filter = null, $tagFilter = '', $action = null
        ) {
-               $title = SpecialPage::getTitleFor( 'Log' );
-
                // For B/C, we take strings, but make sure they are converted...
                $types = ( $types === '' ) ? [] : (array)$types;
 
@@ -120,7 +118,7 @@ class LogEventsList extends ContextSource {
                // Basic selectors
                $formDescriptor['type'] = $this->getTypeMenuDesc( $types );
                $formDescriptor['user'] = $this->getUserInputDesc( $user );
-               $formDescriptor['page'] = $this->getTitleInputDesc( $title );
+               $formDescriptor['page'] = $this->getTitleInputDesc( $page );
 
                // Add extra inputs if any
                // This could either be a form descriptor array or a string with raw HTML.
@@ -170,7 +168,9 @@ class LogEventsList extends ContextSource {
                        $formDescriptor['subtype'] = $this->getActionSelectorDesc( $types, $action );
                }
 
-               $htmlForm = new HTMLForm( $formDescriptor, $this->getContext() );
+               $context = new DerivativeContext( $this->getContext() );
+               $context->setTitle( SpecialPage::getTitleFor( 'Log' ) ); // Remove subpage
+               $htmlForm = new HTMLForm( $formDescriptor, $context );
                $htmlForm
                        ->setSubmitText( $this->msg( 'logeventslist-submit' )->text() )
                        ->setMethod( 'get' )
@@ -203,7 +203,7 @@ class LogEventsList extends ContextSource {
                        }
                        $options[ $message->text() ] = $type;
 
-                       if ( $val === 0 ) {
+                       if ( $val === false ) {
                                $default[] = $type;
                        }
                }
index 2efb462..e7096c4 100644 (file)
@@ -107,12 +107,17 @@ class LogPager extends ReverseChronologicalPager {
                        return $filters;
                }
 
-               $request_filters = $this->getRequest()->getArray( "wpfilters" );
-               $request_filters = $request_filters === null ? [] : $request_filters;
+               $wpfilters = $this->getRequest()->getArray( "wpfilters" );
+               $request_filters = $wpfilters === null ? [] : $wpfilters;
 
                foreach ( $wgFilterLogTypes as $type => $default ) {
                        $hide = !in_array( $type, $request_filters );
 
+                       // Back-compat: Check old URL params if the new param wasn't passed
+                       if ( $wpfilters === null ) {
+                               $hide = $this->getRequest()->getBool( "hide_{$type}_log", $default );
+                       }
+
                        $filters[$type] = $hide;
                        if ( $hide ) {
                                $this->mConds[] = 'log_type != ' . $this->mDb->addQuotes( $type );
index aa34dd2..dfc7c02 100644 (file)
@@ -767,7 +767,7 @@ class PageArchive {
                                        0,
                                        $this->title,
                                        [
-                                               'page' => $pageId,
+                                               'page_id' => $pageId,
                                                'deleted' => $unsuppress ? 0 : $row->ar_deleted
                                        ]
                                );
index f718e5f..4b24081 100644 (file)
@@ -46,7 +46,6 @@ class ResourceLoaderLanguageDataModule extends ResourceLoaderFileModule {
                        'pluralRules' => $language->getPluralRules(),
                        'digitGroupingPattern' => $language->digitGroupingPattern(),
                        'fallbackLanguages' => $language->getFallbackLanguages(),
-                       'bcp47Map' => LanguageCode::getNonstandardLanguageCodeMapping(),
                ];
        }
 
index 6d98920..22377c2 100644 (file)
@@ -116,10 +116,6 @@ class FakeConverter {
        }
 
        function validateVariant( $variant = null ) {
-               if ( $variant === null ) {
-                       return null;
-               }
-               $variant = strtolower( $variant );
                return $variant === $this->mLang->getCode() ? $variant : null;
        }
 
index 54d7fbe..f50c55f 100644 (file)
@@ -30,85 +30,22 @@ class LanguageCode {
        /**
         * Mapping of deprecated language codes that were used in previous
         * versions of MediaWiki to up-to-date, current language codes.
-        * These may or may not be valid BCP 47 codes; they are included here
-        * because MediaWiki remapped these particular codes at some point.
         *
         * @var array Mapping from language code to language code
         *
         * @since 1.30
-        * @see https://meta.wikimedia.org/wiki/Special_language_codes
         */
        private static $deprecatedLanguageCodeMapping = [
                // Note that als is actually a valid ISO 639 code (Tosk Albanian), but it
                // was previously used in MediaWiki for Alsatian, which comes under gsw
-               'als' => 'gsw', // T25215
-               'bat-smg' => 'sgs', // T27522
-               'be-x-old' => 'be-tarask', // T11823
-               'fiu-vro' => 'vro', // T31186
-               'roa-rup' => 'rup', // T17988
-               'zh-classical' => 'lzh', // T30443
-               'zh-min-nan' => 'nan', // T30442
-               'zh-yue' => 'yue', // T30441
-       ];
-
-       /**
-        * Mapping of non-standard language codes used in MediaWiki to
-        * standardized BCP 47 codes.  These are not deprecated (yet?):
-        * IANA may eventually recognize the subtag, in which case the `-x-`
-        * infix could be removed, or else we could rename the code in
-        * MediaWiki, in which case they'd move up to the above mapping
-        * of deprecated codes.
-        *
-        * As a rule, we preserve all distinctions made by MediaWiki
-        * internally.  For example, `de-formal` becomes `de-x-formal`
-        * instead of just `de` because MediaWiki distinguishes `de-formal`
-        * from `de` (for example, for interface translations).  Similarly,
-        * BCP 47 indicates that `kk-Cyrl` SHOULD not be used because it
-        * "typically does not add information", but in our case MediaWiki
-        * LanguageConverter distinguishes `kk` (render content in a mix of
-        * Kurdish variants) from `kk-Cyrl` (convert content to be uniformly
-        * Cyrillic).  As the BCP 47 requirement is a SHOULD not a MUST,
-        * `kk-Cyrl` is a valid code, although some validators may emit
-        * a warning note.
-        *
-        * @var array Mapping from nonstandard codes to BCP 47 codes
-        *
-        * @since 1.32
-        * @see https://meta.wikimedia.org/wiki/Special_language_codes
-        * @see https://phabricator.wikimedia.org/T125073
-        */
-       private static $nonstandardLanguageCodeMapping = [
-               // All codes returned by Language::fetchLanguageNames() validated
-               // against IANA registry at
-               //   https://www.iana.org/assignments/language-subtag-registry/language-subtag-registry
-               // with help of validator at
-               //   http://schneegans.de/lv/
-               'cbk-zam' => 'cbk', // T124657
-               'de-formal' => 'de-x-formal',
-               'eml' => 'egl', // T36217
-               'en-rtl' => 'en-x-rtl',
-               'es-formal' => 'es-x-formal',
-               'hu-formal' => 'hu-x-formal',
-               'map-bms' => 'jv-x-bms', // [[en:Banyumasan_dialect]] T125073
-               'mo' => 'ro-MD', // T125073
-               'nrm' => 'nrf', // [[en:Norman_language]] T25216
-               'nl-informal' => 'nl-x-informal',
-               'roa-tara' => 'nap-x-tara', // [[en:Tarantino_dialect]]
-               'simple' => 'en-simple',
-               'sr-ec' => 'sr-Cyrl', // T117845
-               'sr-el' => 'sr-Latn', // T117845
-
-               // Although these next codes aren't *wrong* per se, including
-               // both the script and the country code helps compatibility with
-               // other BCP 47 users. Note that MW also uses `zh-Hans`/`zh-Hant`,
-               // without a country code, and those should be left alone.
-               // (See $variantfallbacks in LanguageZh.php for Hans/Hant id.)
-               'zh-cn' => 'zh-Hans-CN',
-               'zh-sg' => 'zh-Hans-SG',
-               'zh-my' => 'zh-Hans-MY',
-               'zh-tw' => 'zh-Hant-TW',
-               'zh-hk' => 'zh-Hant-HK',
-               'zh-mo' => 'zh-Hant-MO',
+               'als' => 'gsw',
+               'bat-smg' => 'sgs',
+               'be-x-old' => 'be-tarask',
+               'fiu-vro' => 'vro',
+               'roa-rup' => 'rup',
+               'zh-classical' => 'lzh',
+               'zh-min-nan' => 'nan',
+               'zh-yue' => 'yue',
        ];
 
        /**
@@ -127,29 +64,6 @@ class LanguageCode {
                return self::$deprecatedLanguageCodeMapping;
        }
 
-       /**
-        * Returns a mapping of non-standard language codes used by
-        * (current and previous version of) MediaWiki, mapped to standard
-        * BCP 47 names.
-        *
-        * This array is exported to JavaScript to ensure
-        * mediawiki.language.bcp47 stays in sync with LanguageCode::bcp47().
-        *
-        * @return string[]
-        *
-        * @since 1.32
-        */
-       public static function getNonstandardLanguageCodeMapping() {
-               $result = [];
-               foreach ( self::$deprecatedLanguageCodeMapping as $code => $ignore ) {
-                       $result[$code] = self::bcp47( $code );
-               }
-               foreach ( self::$nonstandardLanguageCodeMapping as $code => $ignore ) {
-                       $result[$code] = self::bcp47( $code );
-               }
-               return $result;
-       }
-
        /**
         * Replace deprecated language codes that were used in previous
         * versions of MediaWiki to up-to-date, current language codes.
@@ -173,15 +87,11 @@ class LanguageCode {
         * See mediawiki.language.bcp47 for the JavaScript implementation.
         *
         * @param string $code The language code.
-        * @return string A language code complying with BCP 47 standards.
+        * @return string The language code which complying with BCP 47 standards.
         *
         * @since 1.31
         */
        public static function bcp47( $code ) {
-               $code = self::replaceDeprecatedCodes( strtolower( $code ) );
-               if ( isset( self::$nonstandardLanguageCodeMapping[$code] ) ) {
-                       $code = self::$nonstandardLanguageCodeMapping[$code];
-               }
                $codeSegment = explode( '-', $code );
                $codeBCP = [];
                foreach ( $codeSegment as $segNo => $seg ) {
index 494280c..dcc2cf3 100644 (file)
@@ -175,13 +175,11 @@ class LanguageConverter {
                        $req = $this->validateVariant( $wgDefaultLanguageVariant );
                }
 
-               $req = $this->validateVariant( $req );
-
                // This function, unlike the other get*Variant functions, is
                // not memoized (i.e. there return value is not cached) since
                // new information might appear during processing after this
                // is first called.
-               if ( $req ) {
+               if ( $this->validateVariant( $req ) ) {
                        return $req;
                }
                return $this->mMainLanguageCode;
@@ -217,25 +215,9 @@ class LanguageConverter {
         * @return mixed Returns the variant if it is valid, null otherwise
         */
        public function validateVariant( $variant = null ) {
-               if ( $variant === null ) {
-                       return null;
-               }
-               // Our internal variants are always lower-case; the variant we
-               // are validating may have mixed case.
-               $variant = LanguageCode::replaceDeprecatedCodes( strtolower( $variant ) );
-               if ( in_array( $variant, $this->mVariants ) ) {
+               if ( $variant !== null && in_array( $variant, $this->mVariants ) ) {
                        return $variant;
                }
-               // Browsers are supposed to use BCP 47 standard in the
-               // Accept-Language header, but not all of our internal
-               // mediawiki variant codes are BCP 47.  Map BCP 47 code
-               // to our internal code.
-               foreach ( $this->mVariants as $v ) {
-                       // Case-insensitive match (BCP 47 is mixed case)
-                       if ( strtolower( LanguageCode::bcp47( $v ) ) === $variant ) {
-                               return $v;
-                       }
-               }
                return null;
        }
 
@@ -311,7 +293,7 @@ class LanguageConverter {
                        return $this->mHeaderVariant;
                }
 
-               // See if some supported language variant is set in the
+               // see if some supported language variant is set in the
                // HTTP header.
                $languages = array_keys( $wgRequest->getAcceptLang() );
                if ( empty( $languages ) ) {
@@ -563,18 +545,17 @@ class LanguageConverter {
                $convTable = $convRule->getConvTable();
                $action = $convRule->getRulesAction();
                foreach ( $convTable as $variant => $pair ) {
-                       $v = $this->validateVariant( $variant );
-                       if ( !$v ) {
+                       if ( !$this->validateVariant( $variant ) ) {
                                continue;
                        }
 
                        if ( $action == 'add' ) {
                                // More efficient than array_merge(), about 2.5 times.
                                foreach ( $pair as $from => $to ) {
-                                       $this->mTables[$v]->setPair( $from, $to );
+                                       $this->mTables[$variant]->setPair( $from, $to );
                                }
                        } elseif ( $action == 'remove' ) {
-                               $this->mTables[$v]->removeArray( $pair );
+                               $this->mTables[$variant]->removeArray( $pair );
                        }
                }
        }
index 67da06b..277bd02 100644 (file)
@@ -82,7 +82,7 @@ class Names {
                'ba' => 'башҡортса', # Bashkir
                'ban' => 'Basa Bali', # Balinese
                'bar' => 'Boarisch', # Bavarian (Austro-Bavarian and South Tyrolean)
-               'bat-smg' => 'žemaitėška', # Samogitian (deprecated code, 'sgs' in ISO 639-3 since 2010-06-30 )
+               'bat-smg' => 'žemaitėška', # Samogitian (deprecated code, 'sgs' in ISO 693-3 since 2010-06-30 )
                'bbc' => 'Batak Toba', # Batak Toba (falls back to bbc-latn)
                'bbc-latn' => 'Batak Toba', # Batak Toba
                'bcc' => 'جهلسری بلوچی', # Southern Balochi
@@ -287,7 +287,7 @@ class Names {
                'lzh' => '文言', # Literary Chinese, T10217
                'lzz' => 'Lazuri', # Laz
                'mai' => 'मैथिली', # Maithili
-               'map-bms' => 'Basa Banyumasan', # Banyumasan ('jv-x-bms')
+               'map-bms' => 'Basa Banyumasan', # Banyumasan
                'mdf' => 'мокшень', # Moksha
                'mg' => 'Malagasy', # Malagasy
                'mh' => 'Ebon', # Marshallese
@@ -298,7 +298,7 @@ class Names {
                'ml' => 'മലയാളം', # Malayalam
                'mn' => 'монгол', # Halh Mongolian (Cyrillic) (ISO 639-3: khk)
                'mni' => 'মেইতেই লোন্', # Manipuri/Meitei
-               'mo' => 'молдовеняскэ', # Moldovan, deprecated (ISO 639-2: ro-MD)
+               'mo' => 'молдовеняскэ', # Moldovan, deprecated
                'mr' => 'मराठी', # Marathi
                'mrj' => 'кырык мары', # Hill Mari
                'ms' => 'Bahasa Melayu', # Malay
@@ -309,7 +309,7 @@ class Names {
                'myv' => 'эрзянь', # Erzya
                'mzn' => 'مازِرونی', # Mazanderani
                'na' => 'Dorerin Naoero', # Nauruan
-               'nah' => 'Nāhuatl', # Nahuatl (added to ISO 639-3 on 2006-10-31)
+               'nah' => 'Nāhuatl', # Nahuatl (not in ISO 639-3)
                'nan' => 'Bân-lâm-gú', # Min-nan, T10217
                'nap' => 'Napulitano', # Neapolitan, T45793
                'nb' => 'norsk bokmål', # Norwegian (Bokmal)
@@ -324,7 +324,7 @@ class Names {
                'nn' => 'norsk nynorsk', # Norwegian (Nynorsk)
                'no' => 'norsk', # Norwegian macro language (falls back to nb).
                'nov' => 'Novial', # Novial
-               'nrm' => 'Nouormand', # Norman (invalid code; 'nrf' in ISO 639 since 2014)
+               'nrm' => 'Nouormand', # Norman
                'nso' => 'Sesotho sa Leboa', # Northern Sotho
                'nv' => 'Diné bizaad', # Navajo
                'ny' => 'Chi-Chewa', # Chichewa
@@ -360,8 +360,8 @@ class Names {
                'rmy' => 'Romani', # Vlax Romany
                'rn' => 'Kirundi', # Rundi/Kirundi/Urundi
                'ro' => 'română', # Romanian
-               'roa-rup' => 'armãneashti', # Aromanian (deprecated code, 'rup' exists in ISO 639-3)
-               'roa-tara' => 'tarandíne', # Tarantino ('nap-x-tara')
+               'roa-rup' => 'armãneashti', # Aromanian (deprecated code, 'rup' exists in ISO 693-3)
+               'roa-tara' => 'tarandíne', # Tarantino
                'ru' => 'русский', # Russian
                'rue' => 'русиньскый', # Rusyn
                'rup' => 'armãneashti', # Aromanian
@@ -437,7 +437,7 @@ class Names {
                'tt-cyrl' => 'татарча', # Tatar (Cyrillic script) (default)
                'tt-latn' => 'tatarça', # Tatar (Latin script)
                'tum' => 'chiTumbuka', # Tumbuka
-               'tw' => 'Twi', # Twi
+               'tw' => 'Twi', # Twi, (FIXME!)
                'ty' => 'reo tahiti', # Tahitian
                'tyv' => 'тыва дыл', # Tyvan
                'tzm' => 'ⵜⴰⵎⴰⵣⵉⵖⵜ', # Tamazight
index 744400a..dc6ed48 100644 (file)
        "timezoneregion-indian": "Indiese Oseaan",
        "timezoneregion-pacific": "Stille Oseaan",
        "allowemail": "Laat e-pos van ander toe",
+       "email-blacklist-label": "Verbied hierdie gebruikers om my te e-pos:",
        "prefs-searchoptions": "Soek",
        "prefs-namespaces": "Naamruimtes",
        "default": "verstek",
        "rcfilters-view-tags-tooltip": "Filter resultate volgens wysigingsetikette",
        "rcfilters-liveupdates-button": "Monitor bywerkings",
        "rcfilters-liveupdates-button-title-off": "Wys nuwe wysigings soos hulle inrol.",
-       "rcfilters-preference-label": "Versteek die verbeter weergawe van 'Onlangse wysigings'",
+       "rcfilters-preference-label": "Versteek die verbeterde weergawe van 'Onlangse wysigings'",
+       "rcfilters-watchlist-preference-label": "Versteek die verbeterde weergawe van die dophoulys.",
        "rcnotefrom": "{{PLURAL:$5|Wysiging|Wysigings}} sedert <strong>$3 om $4</strong> (maksimum van <strong>$1</strong> word gewys).",
        "rclistfrom": "Vertoon wysigings vanaf $3 $2",
        "rcshowhideminor": "$1 klein wysigings",
index fbb51f1..dbbffdc 100644 (file)
        "sourceurl": "URL-адрас крыніцы:",
        "destfilename": "Канчатковая назва файлу:",
        "upload-maxfilesize": "Максымальны памер файлу: $1",
-       "upload-description": "Апісаньне файла",
+       "upload-description": "Апісаньне файлу",
        "upload-options": "Налады загрузкі",
        "watchthisupload": "Назіраць за гэтым файлам",
        "filewasdeleted": "Файл з такой назвай загружаўся, але быў выдалены.\nВам трэба праверыць $1 перад новай загрузкай.",
        "http-timed-out": "Скончыўся час чаканьня HTTP-запыту.",
        "http-curl-error": "Памылка выбаркі URL-адрасу: $1",
        "http-bad-status": "Адбылася памылка пад час выкананьня HTTP-запыту: $1 $2",
+       "http-internal-error": "Унутраная памылка HTTP.",
        "upload-curl-error6": "Немагчыма дасягнуць URL-адрас",
        "upload-curl-error6-text": "Немагчыма адкрыць пазначаны URL-адрас.\nКалі ласка, упэўніцеся, што адрас слушны і сайт працуе.",
        "upload-curl-error28": "Ліміт часу загрузкі скончыўся",
index 5c67e95..7fb78b2 100644 (file)
        "http-timed-out": "Zeitüberschreitung bei der HTTP-Anfrage.",
        "http-curl-error": "Fehler beim Abruf der URL: $1",
        "http-bad-status": "Während der HTTP-Anfrage ist ein Fehler aufgetreten: $1 $2",
+       "http-internal-error": "Interner HTTP-Fehler.",
        "upload-curl-error6": "URL ist nicht erreichbar",
        "upload-curl-error6-text": "Die angegebene URL ist nicht erreichbar. Prüfe sowohl die URL auf Fehler als auch den Online-Status der Seite.",
        "upload-curl-error28": "Zeitüberschreitung beim Hochladen",
index 8e830ba..8de9c0b 100644 (file)
        "watchlistedit-raw-removed": "{{PLURAL:$1|Una página ha sido borrada|$1 páginas han sido borradas}}:",
        "watchlistedit-clear-title": "Vaciar la lista de seguimiento",
        "watchlistedit-clear-legend": "Vaciar la lista de seguimiento",
-       "watchlistedit-clear-explain": "Todos los títulos serán eliminados de tu lista de seguimiento",
+       "watchlistedit-clear-explain": "Se quitarán todos los títulos de la lista de seguimiento",
        "watchlistedit-clear-titles": "Títulos:",
        "watchlistedit-clear-submit": "Vaciar la lista de seguimiento (¡permanente!)",
        "watchlistedit-clear-done": "Se ha vaciado tu lista de seguimiento.",
index b36e898..f7baf07 100644 (file)
        "http-timed-out": "La requête HTTP a expiré.",
        "http-curl-error": "Erreur lors de la récupération de l'URL : $1",
        "http-bad-status": "Il y a eu un problème lors de la requête HTTP : $1 $2",
+       "http-internal-error": "Erreur interne HTTP.",
        "upload-curl-error6": "URL injoignable",
        "upload-curl-error6-text": "L’URL fournie ne peut pas être atteinte. \nVeuillez vérifier que l’URL est correcte et que le site est en ligne.",
        "upload-curl-error28": "Dépassement du délai lors de l'import",
index f18538b..153d249 100644 (file)
        "http-timed-out": "Richiesta HTTP scaduta.",
        "http-curl-error": "Errore durante il recupero dell'URL: $1",
        "http-bad-status": "Si è verificato un problema durante la richiesta HTTP: $1 $2",
+       "http-internal-error": "Errore interno HTTP.",
        "upload-curl-error6": "URL non raggiungibile",
        "upload-curl-error6-text": "Impossibile raggiungere la URL specificata. Verificare che la URL sia scritta correttamente e che il sito in questione sia attivo.",
        "upload-curl-error28": "Tempo scaduto per l'upload",
        "speciallogtitlelabel": "Azione effettuata su (titolo della pagina o {{ns:user}}:Nome utente):",
        "log": "Registri",
        "logeventslist-submit": "Mostra",
-       "logeventslist-more-filters": "Altri filtri:",
+       "logeventslist-more-filters": "Mostra registri aggiuntivi:",
        "logeventslist-patrol-log": "Modifiche verificate",
        "logeventslist-tag-log": "Etichette",
        "all-logs-page": "Tutti i registri pubblici",
index 0a4000a..e87831c 100644 (file)
        "http-timed-out": "HTTP 요청 시간 초과입니다.",
        "http-curl-error": "URL 열기 오류: $1",
        "http-bad-status": "HTTP 요청 중 오류 발생: $1 $2",
+       "http-internal-error": "HTTP 내부 오류.",
        "upload-curl-error6": "URL 접근 불가",
        "upload-curl-error6-text": "URL에 접근할 수 없습니다.\nURL이 맞고 해당 웹사이트가 작동하는지 확인해주세요.",
        "upload-curl-error28": "올리기 시간 초과",
index 6c41f42..f385c44 100644 (file)
        "viewhelppage": "Gweles an folen weres",
        "categorypage": "Gweles folen an klass",
        "viewtalkpage": "Gweles an dadhlow",
-       "otherlanguages": "Yn yethow erel",
-       "redirectedfrom": "(Daskedyes dhyworth $1)",
+       "otherlanguages": "Yn tavosow erel",
+       "redirectedfrom": "(Daskevarwodhys dhyworth $1)",
        "redirectpagesub": "Folen dhaskedya",
-       "lastmodifiedat": "Gwrys veu diwettha chanj an folen ma an $1, dhe $2.",
+       "lastmodifiedat": "Diwettha chanj an folen ma a veu an $1, dhe $2.",
        "protectedpage": "Folen dhifresys",
        "jumpto": "Lamma dhe:",
        "jumptonavigation": "kevrennow lewya",
        "disclaimers": "Avisyansow",
        "disclaimerpage": "Project:Avisyans ollgemmyn",
        "edithelp": "Gweres ow chanjya",
-       "mainpage": "Dynnargh",
-       "mainpage-description": "Dynnargh",
+       "mainpage": "Folen dre",
+       "mainpage-description": "Folen dre",
        "policy-url": "Project:Polici",
        "portal": "Porth an gemeneth",
        "portal-url": "Project:Porth an gemeneth",
        "site-atom-feed": "Feed Atom $1",
        "page-rss-feed": "Feed RSS \"$1\"",
        "page-atom-feed": "Feed Atom \"$1\"",
-       "red-link-title": "$1 (nyns eus folen henwys yndelma)",
+       "red-link-title": "$1 (nyns eus an folen ma)",
        "nstab-main": "Folen",
        "nstab-user": "Folen dhevnydhyer",
        "nstab-media": "Folen media",
        "nstab-template": "Skantlyn",
        "nstab-help": "Gweres",
        "nstab-category": "Klass",
+       "mainpage-nstab": "Folen dre",
        "error": "Gwall",
        "databaseerror": "Gwall database",
        "readonly": "Alhwedhys yw an database",
        "accmailtitle": "Ger-tremena danvenys.",
        "newarticle": "(Nowyth)",
        "newarticletext": "Hwi re holyas kevren dhe folen nag yw gwruthys hwath.\nRag gwruthyl an folen, dallethewgh jynnskrifa y'n gist a-woles (gwelewgh an [$1 folen weres] rag moy kedhlow).\nMar teuthowgh omma yn kamm, klyckyewgh boton '''war-dhelergh''' agas peurell.",
-       "noarticletext": "Nyns eus tekst y'n folen ma a-lemmyn.\nHwi a yll [[Special:Search/{{PAGENAME}}|hwilas titel an folen ma]] yn folennow erel,\n<span class=\"plainlinks\">[{{fullurl:{{#Special:Log}}|page={{FULLPAGENAMEE}}}} hwilas y'n kovnotennow kelmys],\npo [{{fullurl:{{FULLPAGENAME}}|action=edit}} chanjya an folen ma]</span>.",
+       "noarticletext": "Nyns eus tekst y'n folen ma a-lemmyn.\nHwi a yll [[Special:Search/{{PAGENAME}}|hwilas titel an folen ma]] yn folennow erel,\n<span class=\"plainlinks\">[{{fullurl:{{#Special:Log}}|page={{FULLPAGENAMEE}}}} hwilas y'n kovnotennow kelmys],\npo [{{fullurl:{{FULLPAGENAME}}|action=edit}} gwruthyl an folen ma]</span>.",
        "noarticletext-nopermission": "Nyns eus tekst y'n folen ma a-lemmyn.\nHwi a yll [[Special:Search/{{PAGENAME}}|hwilas titel an folen ma]] yn folennow erel, po <span class=\"plainlinks\">[{{fullurl:{{#Special:Log}}|page={{FULLPAGENAMEE}}}} hwilas y'n kovnotennow kelmys]</span>, mes ny'gas beus kummyas dhe wruthyl an folen ma.",
        "userpage-userdoesnotexist": "Nyns yw kovskrifys an akont devnydhyer \"$1\".\nCheckyewgh mar pleg mara'gas beus hwans dhe wruthyl/dhe janjya an folen-ma.",
        "userpage-userdoesnotexist-view": "Nyns yw kovskrifys an akont devnydhyer \"$1\".",
        "viewpagelogs": "Gweles kovnotennow an folen ma",
        "currentrev": "Amendyans diwettha",
        "currentrev-asof": "An amendyans diwettha a-dhia $1",
-       "revisionasof": "Versyon an folen a-dhia $1",
+       "revisionasof": "Versyon a-dhia $1",
        "revision-info": "Amendyans a-dhia $1 gans {{GENDER:$6|$2}}$7",
        "previousrevision": "← Amendyans kottha",
        "nextrevision": "Amendyans nowyttha →",
        "compareselectedversions": "Keheveli an amendyansow dewisyes",
        "showhideselectedversions": "Diskwedhes/kudha amendyansow dewisyes",
        "editundo": "diswul",
-       "searchresults": "Sewyansow an hwilans",
-       "searchresults-title": "Sewyansow an hwilans rag \"$1\"",
+       "searchresults": "Sewyansow hwilas",
+       "searchresults-title": "Sewyansow hwilas rag \"$1\"",
        "notextmatches": "Nyns eus tekst folen vyth owth omdhesedha",
        "prevn": "{{PLURAL:$1|$1}} kyns",
        "nextn": "nessa {{PLURAL:$1|$1}}",
        "prevn-title": "$1 {{PLURAL:$1|sewyans}} kyns",
        "nextn-title": "$1 {{PLURAL:$1|sewyans}} nessa",
-       "shown-title": "Diskwedhes $1 {{PLURAL:$1|sewyans}} yn folen",
+       "shown-title": "Diskwedhes $1 {{PLURAL:$1|sewyans}} war pub folen",
        "viewprevnext": "Gweles ($1 {{int:pipe-separator}} $2) ($3)",
        "searchmenu-exists": "''Yma folen henwys \"[[:$1]]\" war an wiki-ma'''",
        "searchmenu-new": "<strong>Gwrewgh an folen \"[[:$1]]\" war an wiki ma!</strong> {{PLURAL:$2|0=|Gweler ynwegh an folen a veu kevys yn unn hwilas.|Gweler ynwedh an sewyans hwilas kevys.}}",
        "searchprofile-advanced-tooltip": "Hwilas yn spasys hanow personelhes",
        "search-result-size": "$1 ({{PLURAL:$2|1 ger|$2 ger}})",
        "search-result-category-size": "{{PLURAL:$1|1 esel|$1 esel}} ({{PLURAL:$2|1 isglass|$2 isglass}}, {{PLURAL:$3|1 restren|$3 restren}})",
-       "search-redirect": "(daskedyans $1)",
+       "search-redirect": "(daskevarwodhyans a $1)",
        "search-section": "(tregh $1)",
        "search-suggest": "Esewgh hwi ow menya: $1",
        "search-interwiki-caption": "Ragdresow hwor",
        "searchrelated": "kelmys",
        "searchall": "oll",
        "search-showingresults": "{{PLURAL:$4|Sewyans <strong>$1</strong> a <strong>$3</strong>|Sewyansow <strong>$1 - $2</strong> a <strong>$3</strong>}}",
-       "search-nonefound": "Nyns esa sewyans vyth owth omdhesedha orth an govyn.",
+       "search-nonefound": "Ny veu sewyans vyth par dhe'n govyn.",
        "powersearch-legend": "Hwilans avonsys",
        "powersearch-ns": "Hwilas yn spasys-hanow:",
        "powersearch-togglelabel": "Dewis:",
        "nchanges": "$1 {{PLURAL:$1|chanj|chanj}}",
        "enhancedrc-history": "istori",
        "recentchanges": "Chanjyow a-dhiwedhes",
-       "recentchanges-legend": "Etholyow an chanjyow a-dhiwedhes",
+       "recentchanges-legend": "Dewisyow an chanjyow a-dhiwedhes",
        "recentchanges-summary": "War an folen-ma y hyllir helerghi an chanjyow diwettha eus gwrys dhe'n wiki.",
        "recentchanges-noresult": "Nyns eus chanj vyth dres an termyn res a omdhesedh orth an etholyow-ma.",
        "recentchanges-feed-description": "Y hyllir helerhi an chanjyow diwettha gwrys dhe'n wiki y'n feed-ma.",
-       "recentchanges-label-newpage": "Gans an chanj ma y feu gwruthys folen nowydh",
+       "recentchanges-label-newpage": "Folen nowydh a veu gwrys der an chanj ma",
        "recentchanges-label-minor": "Chanj byghan yw hemma",
        "recentchanges-label-bot": "Gwrys veu an chanj ma gans bott",
        "recentchanges-label-unpatrolled": "Ny veu an chanj ma patrolyes hwath",
        "recentchanges-legend-heading": "<strong>Alhwedh:</strong>",
        "recentchanges-legend-newpage": "{{int:recentchanges-label-newpage}} (gweler ynwedh an [[Special:NewPages|rol a folennow nowydh]])",
-       "rclistfrom": "Diskwedhes chanjyow nowydh yn unn dhalleth dhyworth $3 $2",
+       "rclistfrom": "Diskwedhes chanjyow nowydh a-dhia $3 $2",
        "rcshowhideminor": "$1 chanjyow byghan",
        "rcshowhideminor-hide": "Kudha",
        "rcshowhidebots": "$1 bottow",
        "rcshowhidemine": "$1 ow chanjyow",
        "rcshowhidemine-hide": "Kudha",
        "rclinks": "Diskwedhes an $1 chanj diwettha gwrys y'n $2 dydh diwettha",
-       "diff": "dyffrans",
+       "diff": "dihevelepter",
        "hist": "istori",
        "hide": "Kudha",
        "show": "Diskwedhes",
        "listfiles_count": "Versyons",
        "file-anchor-link": "Restren",
        "filehist": "Istori an restren",
-       "filehist-help": "Klyckyewgh war dhedhyans/eur rag gweles an folen dell omdhiskwedhas nena.",
+       "filehist-help": "Klyckyewgh war dhedhyans/eur rag gweles an folen dell o an termyn na.",
        "filehist-deleteall": "dilea oll",
        "filehist-deleteone": "dilea",
        "filehist-revert": "gorthtreylya",
        "filehist-current": "a-lemmyn",
        "filehist-datetime": "Dedhyans/Eur",
        "filehist-thumb": "Skeusennik",
-       "filehist-thumbtext": "Skeusennik rag an versyon a-dhia $1",
+       "filehist-thumbtext": "Skeusennik an versyon a-dhia $1",
        "filehist-nothumb": "Nyns eus skeusennik",
        "filehist-user": "Devnydhyer",
        "filehist-dimensions": "Mynsow",
        "filehist-filesize": "Mens an restren",
-       "filehist-comment": "Kampoll",
+       "filehist-comment": "Kampol",
        "imagelinks": "Devnydh an restren",
        "linkstoimage": "Yma an {{PLURAL:$1|folen|$1 folen}} a syw ow kevrenna dhe'n restren ma:",
        "linkstoimage-more": "Yma moy es $1 {{PLURAL:$1|folen}} ow kevrenna dhe'n restren-ma.\nNy dhiskwa an rol a syw marnas an {{PLURAL:$1|kynsa kevren folen|kynsa $1 kevren folen}} dhe'n restren-ma.\nYma [[Special:WhatLinksHere/$2|rol leun]] kavadow.",
        "nolinkstoimage": "Nyns eus folen vyth ow kevrenna dhe'n restren-ma.",
        "morelinkstoimage": "Gweles [[Special:WhatLinksHere/$1|moy kevrennow]] dhe'n restren-ma.",
        "sharedupload": "Yma an folen-ma ow tos dhyworth $1 ha hy a alsa bos yn-dann devnydh gans ragdresow erel.",
-       "sharedupload-desc-here": "Yma an restren ma dhe $1 ha ragdresow erel a allsa bos orth hy devnydhya.\nDiskwedhys a-woles yw an deskrifans war hy [$2 folen dheskrifans] ena.",
+       "sharedupload-desc-here": "Yma an restren ma dhe $1 ha ragdresow erel a allsa bos orth hy devnydhya.\nDiskwedhys a-woles yma an deskrifans war hy [$2 folen dheskrifans] ena.",
        "uploadnewversion-linktext": "Ughkarga versyon nowyth a'n restren-ma",
        "filedelete": "Dilea $1",
        "filedelete-legend": "Dilea an restren",
        "listredirects": "Rol an daswedyansow",
        "unusedtemplates": "Skantlyns heb devnydh",
        "unusedtemplateswlh": "kevrennow erel",
-       "randompage": "Folen dre happ",
+       "randompage": "Folen jonsus",
        "statistics": "Statystygyon",
        "statistics-pages": "Folennow",
        "brokenredirects-edit": "chanjya",
        "sp-contributions-username": "Trigva IP po hanow devnydhyer:",
        "sp-contributions-toponly": "Diskwedhes yn unnik chanjyow yw amendyansow diwettha",
        "sp-contributions-submit": "Hwilas",
-       "whatlinkshere": "Pyth a gevren dhe omma",
+       "whatlinkshere": "Folennow kevrennys",
        "whatlinkshere-title": "Folennow ow kevrenna dhe \"$1\"",
        "whatlinkshere-page": "Folen:",
        "linkshere": "Yma an folennow a syw ow kevrenna dhe '''$2''':",
        "tooltip-pt-preferences": "Agas dewisyow",
        "tooltip-pt-watchlist": "Rol a folennow esowgh ow kolya rag chanjyow",
        "tooltip-pt-mycontris": "Rol a'gas kevrohow",
-       "tooltip-pt-login": "Ni a gomend hwi dhe omgelmi, mes nyns yw besi",
+       "tooltip-pt-login": "Ni a gomend hwi dhe omgelmi, mes nyns yw bysi",
        "tooltip-pt-logout": "Digelmi",
-       "tooltip-pt-createaccount": "Ni a gomend hwi dhe wruthyl akont hag omgelmi; byttegyns nyns yw besi",
+       "tooltip-pt-createaccount": "Ni a gomend hwi dhe wruthyl akont hag omgelmi; byttegyns nyns yw bysi",
        "tooltip-ca-talk": "Dadhlow a-dro dhe'n folen",
        "tooltip-ca-edit": "Chanjya an folen ma",
        "tooltip-ca-addsection": "Dalleth tregh nowydh",
        "tooltip-ca-protect": "Difres an folen-ma",
        "tooltip-ca-delete": "Dilea an folen-ma",
        "tooltip-ca-move": "Gwaya an folen ma",
-       "tooltip-ca-watch": "Keworra an folen ma dhe'gas rol wolya",
+       "tooltip-ca-watch": "Keworra an folen ma dh'agas rol wolya",
        "tooltip-ca-unwatch": "Dilea an folen-ma dhyworth agas rol wolya",
        "tooltip-search": "Hwilas yn {{SITENAME}}",
        "tooltip-search-go": "Mos dhe folen dhedhi an keth hanow ma, mars eus",
        "tooltip-search-fulltext": "Hwilas an tekst ma y'n folennow",
-       "tooltip-p-logo": "Mos dhe'n folen dynnargh",
-       "tooltip-n-mainpage": "Mos dhe'n folen dynnargh",
-       "tooltip-n-mainpage-description": "Mos dhe'n folen dynnargh",
-       "tooltip-n-portal": "A-dro dhe'n ragdres, an pyth a yllowgh gul, ple hyllir kavos taklow",
+       "tooltip-p-logo": "Mos dhe'n folen dre",
+       "tooltip-n-mainpage": "Mos dhe'n folen dre",
+       "tooltip-n-mainpage-description": "Mos dhe'n folen dre",
+       "tooltip-n-portal": "A-dro dhe'n ragdres, pyth a yllowgh gul, ple hyllir kavos taklow",
        "tooltip-n-currentevents": "Kavos kedhlow a-dro dhe hwarvosow a-lemmyn",
        "tooltip-n-recentchanges": "Rol a janjyow a-dhiwedhes y'n wiki",
        "tooltip-n-randompage": "Karga folen dre happ",
        "tooltip-n-help": "Gweres",
-       "tooltip-t-whatlinkshere": "Rol a bub folen wiki a gevren dhe omma",
-       "tooltip-t-recentchangeslinked": "Chanjyow a-dhiwedhes yn folennow a gevren an folen ma dhedha",
+       "tooltip-t-whatlinkshere": "Rol a bub folen wiki kevrennys dhe'n folen ma",
+       "tooltip-t-recentchangeslinked": "Chanjyow a-dhiwedhes yn folennow kevrennys dhyworth an folen ma",
        "tooltip-feed-rss": "Feed RSS rag an folen-ma",
        "tooltip-feed-atom": "Feed Atom rag an folen ma",
        "tooltip-t-contributions": "Gweles rol a gevrohow an devnydhyer ma",
        "tooltip-t-permalink": "Kevren fast dhe'n amendyans ma a'n folen",
        "tooltip-ca-nstab-main": "Gweles an folen",
        "tooltip-ca-nstab-user": "Gweles an folen dhevnydhyer",
-       "tooltip-ca-nstab-special": "Folen arbennek yw homma; ny yllowgh chanjya an folen hy honan.",
+       "tooltip-ca-nstab-special": "Folen arbennek yw homma; ny yllir hy chanjya",
        "tooltip-ca-nstab-project": "Gweles folen an wiki",
        "tooltip-ca-nstab-image": "Gweles folen an restren",
        "tooltip-ca-nstab-template": "Gweles an skantlyn",
        "tooltip-diff": "Diskwedhes an chanjyow a wrussowgh dhe'n tekst",
        "tooltip-compareselectedversions": "Gweles an dyffransow ynter dew amendyansow dewisyes an folen-ma",
        "tooltip-watch": "Keworra an folen-ma dhe'gas rol wolya",
-       "tooltip-rollback": "\"Revya war-dhelergh\" a worthtreyl chanjyow an diwettha devnydhyer der unn glyck",
+       "tooltip-rollback": "\"Revya war-dhelergh\" a worthtreyl chanj(yow) an diwettha devnydhyer der unn glyck",
        "tooltip-undo": "\"Diswul\" a worthtreyl an chanj ma hag ygeri an furvlen janjya y'n modh ragweles. Y hyllir keworra acheson y'n berrskrif.",
-       "tooltip-summary": "Entrewgh berrskrif",
+       "tooltip-summary": "Keworrewgh berrskrif",
        "siteuser": "devnydhyer {{SITENAME}} $1",
        "lastmodifiedatby": "Chanj diwettha an folen-ma o dhe $2, $1 gans $3.",
        "siteusers": "{{PLURAL:$2|devnydhyer|devnydhyoryon}} {{SITENAME}} $1",
index 264389c..8d0cf62 100644 (file)
        "recentchanges-legend-newpage": "{{int:recentchanges-label-newpage}} (jereo koa ny [[Special:NewPage|lisitry ny pejy vaovao]])",
        "recentchanges-submit": "Aseho",
        "rcfilters-activefilters": "Sivana miasa",
+       "rcfilters-activefilters-hide-tooltip": "Hanafina ny faritry ny sivana miasa",
        "rcfilters-advancedfilters": "Sivana havanana kokoa",
        "rcfilters-quickfilters": "Sivana notehirizina",
        "rcfilters-quickfilters-placeholder-title": "Tsy mbola misy sivana notehirizina",
        "rcfilters-savedqueries-defaultlabel": "Sivana voatahiry",
        "rcfilters-savedqueries-rename": "Hanova ny anarana",
+       "rcfilters-savedqueries-setdefault": "Ampiasaina ho solon'ny tsy misy",
        "rcfilters-savedqueries-remove": "Esorina",
        "rcfilters-savedqueries-new-name-label": "Anarana",
+       "rcfilters-savedqueries-new-name-placeholder": "Visavisao eto ny tanjon'ilay sivana",
        "rcfilters-savedqueries-apply-label": "Hamorona rohy haingana",
+       "rcfilters-savedqueries-apply-and-setdefault-label": "Hamorona sivana solon'ny tsy misy",
        "rcfilters-savedqueries-cancel-label": "Avela",
+       "rcfilters-savedqueries-already-saved": "Efa voatahiry ireo sivana ireo. Ovay ny parametatra hamoronana sivana voatahiry vaovao.",
        "rcfilters-restore-default-filters": "Hamerina sivana ampiasaina raha tsy misy",
        "rcfilters-clear-all-filters": "Hamafa ny sivana rehetra",
        "rcfilters-search-placeholder": "Hanivana ny fiovana farany (tetezo na manomboha manoratra)",
        "rcfilters-filter-excluded": "Foanana",
        "rcfilters-tag-prefix-namespace-inverted": "<strong>:not</strong> $1",
        "rcfilters-view-tags": "Fiovam-pejy voamarika",
+       "rcfilters-view-namespaces-tooltip": "Hanasivana ny valiny araka ny anaran-tsehatra",
+       "rcfilters-view-return-to-default-tooltip": "Hiverina amin'ny menion'ny sivana",
        "rcfilters-liveupdates-button": "Fihavaozana mivantana",
        "rcnotefrom": "Eo ambany dia ahitana ireo fiovana{{PLURAL:$5}} hatry ny <strong>$3, $4</strong> (naseho hatramin'ny <strong>$1</strong>).",
        "rclistfrom": "Asehoy izay vao niova manomboka ny $3 $2",
index f347dc0..4580593 100644 (file)
        "http-timed-out": "HTTP-барањето истече.",
        "http-curl-error": "Грешка при добивањето на URL: $1",
        "http-bad-status": "Се појави проблем во текот на обработката на HTTP-барањето: $1 $2",
+       "http-internal-error": "Внатрешна грешка со HTTP.",
        "upload-curl-error6": "Не може да се пристапи до URL-то",
        "upload-curl-error6-text": "Наведеното URL не е достапно.\nПроверете дали URL-то е исправно и достапно.",
        "upload-curl-error28": "Истече времето за подигање",
index 6d5b727..57e3609 100644 (file)
        "prefs-dateformat": "दिनांक प्रारुपण",
        "prefs-timeoffset": "वेळ बरोबरी",
        "prefs-advancedediting": "सर्वसामान्य पर्याय",
+       "prefs-developertools": "विकसक उपकरण",
        "prefs-editor": "संपादक",
        "prefs-preview": "झलक",
        "prefs-advancedrc": "प्रगत पर्याय",
index 3613d2d..297b2bb 100644 (file)
        "http-timed-out": "Timeout bij het HTTP-verzoek.",
        "http-curl-error": "Fout bij het ophalen van URL: $1",
        "http-bad-status": "Er is een probleem opgetreden bij het HTTP-verzoek: $1 $2",
+       "http-internal-error": "HTTP interne fout.",
        "upload-curl-error6": "Kon de URL niet bereiken",
        "upload-curl-error6-text": "De opgegeven URL is niet bereikbaar.\nControleer of de URL juist is, en of de website beschikbaar is.",
        "upload-curl-error28": "Uploadtime-out",
index 7e4b640..ecfb2e5 100644 (file)
        "http-timed-out": "Przekroczony czas żądania HTTP.",
        "http-curl-error": "Błąd pobierania z adresu $1",
        "http-bad-status": "Wystąpił problem z realizacją żądania HTTP $1 $2",
+       "http-internal-error": "Błąd wewnętrzny HTTP.",
        "upload-curl-error6": "Adres URL jest nieosiągalny",
        "upload-curl-error6-text": "Podany adres URL jest nieosiągalny. Upewnij się, czy podany adres URL jest prawidłowy i czy dana strona jest dostępna.",
        "upload-curl-error28": "Upłynął limit czasu odpowiedzi",
index 22b8b89..07604da 100644 (file)
        "http-timed-out": "Esgotado o tempo de espera da requisição HTTP.",
        "http-curl-error": "Erro ao requisitar a URL: $1",
        "http-bad-status": "Ocorreu um problema durante a requisição HTTP: $1 $2",
+       "http-internal-error": "Erro interno do HTTP.",
        "upload-curl-error6": "Não foi possível acessar a URL",
        "upload-curl-error6-text": "Não foi possível acessar o endereço (URL) fornecido. Por gentileza, se certifique que o endereço foi fornecido corretamente e de que o site esteja acessível.",
        "upload-curl-error28": "Tempo limite para o envio do arquivo excedido",
index 6b39aec..27ebcb8 100644 (file)
        "http-timed-out": "O pedido HTTP expirou.",
        "http-curl-error": "Ocorreu um erro ao aceder ao URL: $1",
        "http-bad-status": "Ocorreu um problema durante o pedido HTTP: $1 $2",
+       "http-internal-error": "Erro interno do HTTP.",
        "upload-curl-error6": "Não foi possível aceder ao URL",
        "upload-curl-error6-text": "Não foi possível aceder ao URL.\nVerifique se o endereço está correto e o sítio disponível, por favor.",
        "upload-curl-error28": "Tempo limite para o envio do ficheiro excedido",
index e7e9e40..02d8b27 100644 (file)
        "variantname-gan-hans": "{{Optional}}\n\nVariant option for wikis with variants conversion enabled.",
        "variantname-gan-hant": "{{Optional}}\n\nVariant option for wikis with variants conversion enabled.",
        "variantname-gan": "{{Optional}}\n\nVariant option for wikis with variants conversion enabled.",
-       "variantname-sr-ec": "{{optional}}\nVariant Option for wikis with variants conversion enabled.\n\nNote that <code>sr-ec</code> is not a conforming BCP 47 language tag. Wikis should be migrated by:\n* allowing it only as a legacy alias of the preferred tag <code>sr-cyrl</code> (possibly insert a tracking category in templates as long as they must support the legacy tag),\n* making the new tag the default to look first, before looking for the old tag,\n* moving the translations to the new code by renaming them,\n* checking links in source pages still using the legacy tag to change it to the new tag,\n* possibly cleanup the redirect pages.",
-       "variantname-sr-el": "{{optional}}\nVariant Option for wikis with variants conversion enabled.\n\nNote that <code>sr-el</code> is not a conforming BCP 47 language tag. Wikis should be migrated by:\n* allowing it only as a legacy alias of the preferred tag <code>sr-latn</code> (possibly insert a tracking category in templates as long as they must support the legacy tag),\n* making the new tag the default to look first, before looking for the old tag,\n* moving the translations to the new code by renaming them,\n* checking links in source pages still using the legacy tag to change it to the new tag,\n* possibly cleanup the redirect pages.",
+       "variantname-sr-ec": "{{optional}}\nVariant Option for wikis with variants conversion enabled.\n\nNote that <code>sr-ec</code> is not a conforming BCP47 language tag. Wikis should be migrated by:\n* allowing it only as a legacy alias of the preferred tag <code>sr-cyrl</code> (possibly insert a tracking category in templates as long as they must support the legacy tag),\n* making the new tag the default to look first, before looking for the old tag,\n* moving the translations to the new code by renaming them,\n* checking links in source pages still using the legacy tag to change it to the new tag,\n* possibly cleanup the redirect pages.",
+       "variantname-sr-el": "{{optional}}\nVariant Option for wikis with variants conversion enabled.\n\nNote that <code>sr-el</code> is not a conforming BCP47 language tag. Wikis should be migrated by:\n* allowing it only as a legacy alias of the preferred tag <code>sr-latn</code> (possibly insert a tracking category in templates as long as they must support the legacy tag),\n* making the new tag the default to look first, before looking for the old tag,\n* moving the translations to the new code by renaming them,\n* checking links in source pages still using the legacy tag to change it to the new tag,\n* possibly cleanup the redirect pages.",
        "variantname-sr": "{{optional}}\nVariant Option for wikis with variants conversion enabled.",
        "variantname-kk-kz": "{{optional}}\nVariant Option for wikis with variants conversion enabled.",
        "variantname-kk-tr": "{{optional}}\nVariant Option for wikis with variants conversion enabled.",
index a3bdc44..bd66ad8 100644 (file)
        "http-timed-out": "Истекло время ожидания HTTP-запроса.",
        "http-curl-error": "Ошибка обращения к URL: $1",
        "http-bad-status": "Во время обработки HTTP-запроса обнаружена проблема: $1 $2",
+       "http-internal-error": "Внутренняя ошибка HTTP.",
        "upload-curl-error6": "Невозможно обратить по указанному адресу.",
        "upload-curl-error6-text": "Невозможно обратить по указанному адресу. Пожалуйста, проверьте, что адрес верен, а сайт доступен.",
        "upload-curl-error28": "Время, отведённое на загрузку, истекло",
index 64c315b..f30b990 100644 (file)
        "http-timed-out": "Zahteva HTTP je potekla.",
        "http-curl-error": "Napaka pri doseganju URL: $1",
        "http-bad-status": "Med zahtevo HTTP je prišlo do težave: $1 $2",
+       "http-internal-error": "Notranja napaka HTTP.",
        "upload-curl-error6": "Ni možno doseči URL",
        "upload-curl-error6-text": "Navedenega naslova URL ni mogoče doseči.\nProsimo, ponovno preverite pravilnost URL-a in delovanje strani.",
        "upload-curl-error28": "Časovna prekinitev nalaganja",
index 38a8149..03df866 100644 (file)
        "botpasswords-label-resetpassword": "Ресетуј лозинку",
        "botpasswords-label-grants": "Применљиве дозволе:",
        "botpasswords-label-grants-column": "Одобрено",
-       "botpasswords-bad-appid": "Име бота „$1” није ваљано.",
+       "botpasswords-bad-appid": "Име бота „$1” није валидно.",
        "botpasswords-insert-failed": "Неуспешно додавање бота \"$1\". Да ли је већ додат?",
        "botpasswords-update-failed": "Није могуће ажурирати бота \"$1\". Да ли је обрисан?",
        "botpasswords-created-title": "Направљена лозинка бота",
        "headline-anchor-title": "Веза до овог одељка",
        "special-characters-group-latin": "Латиница",
        "special-characters-group-latinextended": "Проширена латиница",
-       "special-characters-group-ipa": "Ð\98Ð\9fА",
+       "special-characters-group-ipa": "Ð\9cФА",
        "special-characters-group-symbols": "Симболи",
        "special-characters-group-greek": "Грчки",
        "special-characters-group-greekextended": "Проширени грчки",
index 38f8e66..083df6b 100644 (file)
@@ -19,7 +19,8 @@
                        "Kwisha",
                        "Macofe",
                        "Muddyb",
-                       "Fitoschido"
+                       "Fitoschido",
+                       "Rance"
                ]
        },
        "tog-underline": "Wekea mstari viungo:",
        "editundo": "tengua",
        "diff-empty": "(Hakuna tofauti)",
        "searchresults": "Matokeo ya utafutaji",
+       "search-filter-title-prefix": "Kutafuta katika kurasa zenye kichwa kianzacho na \"$1\" pekee",
+       "search-filter-title-prefix-reset": "Tafuta kurasa zote",
        "searchresults-title": "Matokeo ya utafutaji kwa ajili ya \"$1\"",
        "titlematches": "Kurasa zinazo majina yenye maneno ya ulizo",
        "textmatches": "Kurasa zinazo maandishi yenye maneno ya ulizo",
        "specialloguserlabel": "Mtendaji:",
        "speciallogtitlelabel": "Kusudio (jina la ukurasa au mtumiaji):",
        "log": "Kumbukumbu",
+       "logeventslist-more-filters": "Onyesha taarifa za ziada",
        "all-logs-page": "Kumbukumbu zote zilizo wazi",
        "alllogstext": "Hapa panaonyeshwa kumbukumbu zote za {{SITENAME}} kwa pamoja.\nUnaweza kuona baadhi yao tu kwa kuchagua aina fulani ya kumbukumbu, jina la mtumiaji fulani (zingatia herufi kubwa na ndogo), au jina la ukurasa fulani (zingatia herufi kubwa na ndogo).",
        "logempty": "Vitu vyenye vipengele hivi havipo kwenye kumbukumbu.",
index 142c68a..f5bcaf8 100644 (file)
        "permissionserrorstext-withaction": "ఈ క్రింది {{PLURAL:$1|కారణం|కారణాల}} వల్ల, $2 అనుమతి మీకు లేదు:",
        "recreate-moveddeleted-warn": "<strong>హెచ్చరిక: ఇంతకు మునుపు ఒకసారి తొలగించిన పేజీని మళ్లీ సృష్టిద్దామని మీరు ప్రయత్నిస్తున్నారు.</strong>\n\nఈ పేజీపై మార్పులు చేసేముందు, అవి ఇక్కడ ఉండతగినవేనా కాదా అని ఒకసారి ఆలోచించండి.\nమీ సౌలభ్యం కొరకు ఈ పేజీ యొక్క తొలగింపు మరియు తరలింపు చిట్టా ఇక్కడ ఇచ్చాము:",
        "moveddeleted-notice": "ఈ పేజీని తొలగించారు.\nఈ పేజీ యొక్క తొలగింపు, సంరక్షణ, తరలింపు చిట్టాను క్రింద ఇచ్చాం.",
+       "moveddeleted-notice-recent": "సారీ, ఈ పేజీని ఈమధ్యే తొలగించారు (గత 24 గంటల్లో).\nఈ పేజీకి సంబంధించిన తొలగింపు, సంరక్షణ, తరలింపు లాగ్‌లను కింద ఇచ్చాం.",
        "log-fulllog": "పూర్తి చిట్టాని చూడండి",
        "edit-hook-aborted": "కొక్కెం ఈ మార్పుని విచ్ఛిన్నం చేసింది.\nఅది ఎటువంటి వివరణా ఇవ్వలేదు.",
        "edit-gone-missing": "పేజీని తాజాకరించలేకపోయాం.\nదాన్ని తొలగించినట్టున్నారు.",
        "content-model-css": "CSS",
        "content-json-empty-object": "ఖాళీ అంశం",
        "content-json-empty-array": "ఖాళీ అరే",
+       "duplicate-args-warning": "<strong>హెచ్చరిక:</strong> [[:$1]], \"$3\" పరామితికి ఒకటి కంటే ఎక్కువ విలువలు ఇచ్చి [[:$2]] ను పిలుస్తోంది. చిట్టచివరిగా ఇచ్చిన విలువను మాత్రమే వాడుతాం.",
+       "duplicate-args-category-desc": "ఈ పేజీ డూప్లికేట్ ఆర్గ్యుమెంట్లను ఇచ్చి మూసలను పిలుస్తోంది, ఇలా: <code><nowiki>{{foo|bar=1|bar=2}}</nowiki></code> లేదా ఇలా: <code><nowiki>{{foo|bar|1=baz}}</nowiki></code>.",
        "expensive-parserfunction-warning": "<strong>హెచ్చరిక:</strong> ఈ పేజీలో ఖరీదైన పార్సరు పిలుపులు చాలా ఉన్నాయి.\n\nపార్సరు {{PLURAL:$2|పిలుపు|పిలుపులు}} $2 కంటే తక్కువ ఉండాలి,  ప్రస్తుతం {{PLURAL:$1|$1 పిలుపు ఉంది|$1  పిలుపులు ఉన్నాయి}}.",
        "expensive-parserfunction-category": "పార్సరు సందేశాలు అధికంగా ఉన్న పేజీలు",
        "post-expand-template-inclusion-warning": "<strong>హెచ్చరిక:</strong> మూస ఇముడ్పు సైజు చాలా పెద్దదిగా ఉంది.\nకొన్ని మూసలు ఇమడ్చబడవు.",
index 77e9851..a40a8ff 100644 (file)
        "diff-paragraph-moved-toold": "Đoạn văn được chuyển từ vị trí khác. Nhấn chuột để nhảy tới vị trí cũ.",
        "difference-missing-revision": "Không tìm thấy {{PLURAL:$2|một phiên bản|$2 phiên bản}} trong khác biệt này ($1).\n\nLỗi này thường xuất hiện đối khi theo dõi liên kết lỗi thời đến khác biệt giữa các bản của trang đã bị xóa.\nXem chi tiết trong [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} nhật trình xóa].",
        "searchresults": "Kết quả tìm kiếm",
+       "search-filter-title-prefix": "Chỉ có tìm trong các trang có tên bắt đầu với “$1”",
+       "search-filter-title-prefix-reset": "Tìm kiếm tất cả các trang",
        "searchresults-title": "Kết quả tìm kiếm “$1”",
        "titlematches": "Đề mục tương tự",
        "textmatches": "Câu chữ tương tự",
        "prefs-editor": "Trình soạn",
        "prefs-preview": "Xem trước",
        "prefs-advancedrc": "Tùy chọn nâng cao",
+       "prefs-opt-out": "Quyết định không sử dụng các cải thiện",
        "prefs-advancedrendering": "Tùy chọn nâng cao",
        "prefs-advancedsearchoptions": "Tùy chọn nâng cao",
        "prefs-advancedwatchlist": "Tùy chọn nâng cao",
        "rcfilters-activefilters": "Bộ lọc hiện hành",
        "rcfilters-activefilters-hide": "Ẩn",
        "rcfilters-activefilters-show": "Hiện",
+       "rcfilters-activefilters-hide-tooltip": "Ẩn phần Bộ lọc kích hoạt",
+       "rcfilters-activefilters-show-tooltip": "Hiện phần Bộ lọc kích hoạt",
        "rcfilters-advancedfilters": "Bộ lọc nâng cao",
        "rcfilters-limit-title": "Số kết quả hiển thị",
        "rcfilters-limit-and-date-label": "$1 thay đổi, $2",
        "rcfilters-savedqueries-apply-and-setdefault-label": "Tạo bộ lọc mặc định",
        "rcfilters-savedqueries-cancel-label": "Hủy bỏ",
        "rcfilters-savedqueries-add-new-title": "Lưu thiết lập bộ lọc hiện tại",
+       "rcfilters-savedqueries-already-saved": "Đã lưu các bộ lọc này rồi. Thay đổi tùy chọn để tạo một Bộ lọc đã lưu mới.",
        "rcfilters-restore-default-filters": "Mặc định lại các bộ lọc",
        "rcfilters-clear-all-filters": "Xóa sạch các bộ lọc",
        "rcfilters-show-new-changes": "Xem các thay đổi mới nhất",
        "rcfilters-watchlist-edit-watchlist-button": "Sửa danh sách trang theo dõi",
        "rcfilters-watchlist-showupdated": "Thay đổi mới trên các trang kể lần cuối bạn xem trang được in <strong>đậm</strong> và có dấu tô màu.",
        "rcfilters-preference-label": "Ẩn phiên bản cải tiến của trang Thay đổi Gần đây",
+       "rcfilters-preference-help": "Hủy bỏ thiết kế lại giao diện năm 2017 và tất cả các công cụ được thêm từ lúc đó trở về nay.",
+       "rcfilters-watchlist-preference-label": "Ẩn danh sách theo dõi cải thiện",
+       "rcfilters-watchlist-preference-help": "Hủy bỏ thiết kế lại giao diện năm 2017 và tất cả các công cụ được thêm từ lúc đó trở về nay.",
        "rcfilters-filter-showlinkedfrom-label": "Xem các thay đổi tại trang có liên kết từ",
        "rcfilters-filter-showlinkedfrom-option-label": "<strong>Trang có liên kết từ</strong> trang được chọn",
        "rcfilters-filter-showlinkedto-label": "Xem các thay đổi tại trang có liên kết đến",
        "uploadbtn": "Tải tập tin lên",
        "reuploaddesc": "Hủy tác vụ tải và quay lại mẫu tải tập tin lên",
        "upload-tryagain": "Lưu miêu tả tập tin được sửa đổi",
+       "upload-tryagain-nostash": "Gửi lại tập tin được tải lên lại và miêu tả được sửa đổi",
        "uploadnologin": "Chưa đăng nhập",
        "uploadnologintext": "Bạn phải $1 để tải tập tin lên.",
        "upload_directory_missing": "Thư mục tải lên ($1) không có hoặc máy chủ web không thể tạo được.",
        "uploadstash-bad-path-invalid": "Đường dẫn không hợp lệ.",
        "uploadstash-bad-path-unknown-type": "Loại không xác định \"$1\".",
        "uploadstash-bad-path-unrecognized-thumb-name": "Tên hình thu nhỏ không nhận dạng được.",
+       "uploadstash-bad-path-no-handler": "Không tìm thấy trình xử lý kiểu MIME $1 của tập tin $2.",
        "uploadstash-bad-path-bad-format": "Chìa khóa “$1” không tuân theo định dạng.",
        "uploadstash-file-not-found-no-thumb": "Không thể tải hình thu nhỏ.",
+       "uploadstash-file-not-found-no-local-path": "Không tìm thấy đường dẫn trên máy cho hình nhỏ.",
        "uploadstash-file-not-found-no-object": "Không tạo được đối tượng tập tin cục bộ cho hình thu nhỏ.",
        "uploadstash-file-not-found-no-remote-thumb": "Nạp hình thu nhỏ thất bại: $1\nURL = $2",
        "uploadstash-file-not-found-missing-content-type": "Thiếu đầu đề kiểu-nội-dung (content-type).",
+       "uploadstash-file-not-found-not-exists": "Không tìm thấy đường dẫn hoặc không phải là tập tin thuần túy.",
+       "uploadstash-file-too-large": "Không thể phục vụ tập tin lớn hơn $1 byte.",
        "uploadstash-not-logged-in": "Người dùng chưa đăng nhập, các tập tin phải do người dùng đã đăng nhập tải lên.",
+       "uploadstash-wrong-owner": "Tập tin này ($1) không phải do người dùng hiện tại tải lên.",
        "uploadstash-no-such-key": "Khóa không tồn tại ($1), không thể xóa.",
+       "uploadstash-no-extension": "Phần mở rộng không có giá trị.",
        "uploadstash-zero-length": "Tập tin có dung lượng bằng không.",
        "invalid-chunk-offset": "Khúc lệch (chunk offset) không hợp lệ",
        "img-auth-accessdenied": "Không cho phép truy cập",
        "http-timed-out": "Hết thời gian yêu cầu HTTP.",
        "http-curl-error": "Có lỗi khi truy xuất URL: $1",
        "http-bad-status": "Có vấn đề khi yêu cầu HTTP: $1 $2",
+       "http-internal-error": "Lỗi nội bộ HTTP.",
        "upload-curl-error6": "Không thể truy cập URL",
        "upload-curl-error6-text": "Không thể truy cập URL mà bạn đưa vào. Xin hãy kiểm tra xem URL có đúng không và website vẫn còn hoạt động.",
        "upload-curl-error28": "Quá thời gian tải lên cho phép",
        "speciallogtitlelabel": "Mục tiêu (tiêu đề hoặc {{ns:user}}:Tên-người-dùng đối với người dùng):",
        "log": "Nhật trình",
        "logeventslist-submit": "Xem",
+       "logeventslist-more-filters": "Hiện thêm nhật trình:",
+       "logeventslist-patrol-log": "Nhật trình tuần tra",
+       "logeventslist-tag-log": "Nhật trình thẻ đánh dấu",
        "all-logs-page": "Tất cả các nhật trình công khai",
        "alllogstext": "Hiển thị tất cả các nhật trình đang có của {{SITENAME}} chung với nhau.\nBạn có thể thu hẹp kết quả bằng cách chọn loại nhật trình, tên thành viên (phân biệt chữ hoa-chữ thường), hoặc các trang bị ảnh hưởng (cũng phân biệt chữ hoa-chữ thường).",
        "logempty": "Không có mục nào khớp với từ khóa.",
        "uctop": "(hiện tại)",
        "month": "Từ tháng (trở về trước):",
        "year": "Từ năm (trở về trước):",
+       "date": "Từ ngày (trở về trước):",
        "sp-contributions-newbies": "Chỉ hiển thị đóng góp của tài khoản mới",
        "sp-contributions-newbies-sub": "Các thành viên mới",
        "sp-contributions-newbies-title": "Đóng góp của các thành viên mới",
        "sp-contributions-newonly": "Chỉ hiện các sửa đổi tạo trang",
        "sp-contributions-hideminor": "Ẩn các sửa đổi nhỏ",
        "sp-contributions-submit": "Tìm kiếm",
+       "sp-contributions-outofrange": "Không thể hiển thị kết quả cho dải địa chỉ IP quá giới hạn CIDR là /$1.",
        "whatlinkshere": "Các liên kết đến đây",
        "whatlinkshere-title": "Các trang liên kết đến “$1”",
        "whatlinkshere-page": "Trang:",
        "ipb_blocked_as_range": "Lỗi: Địa chỉ IP $1 không bị cấm trực tiếp và do đó không thể bỏ cấm. Tuy nhiên, nó bị cấm do là một bộ phận của dải IP $2, bạn có thể bỏ cấm dải này.",
        "ip_range_invalid": "Dải IP không hợp lệ.",
        "ip_range_toolarge": "Không được phép cấm dải IP lớn hơn /$1.",
+       "ip_range_exceeded": "Dải địa chỉ IP này vượt quá dải tối đa. Dải được cho phép: /$1.",
+       "ip_range_toolow": "Không cho phép dải địa chỉ IP trên thực tế.",
        "proxyblocker": "Cấm proxy",
        "proxyblockreason": "Địa chỉ IP của bạn đã bị cấm vì là proxy mở. Xin hãy liên hệ nhà cung cấp dịch vụ Internet hoặc bộ phận hỗ trợ kỹ thuật của bạn và thông báo với họ về vấn đề an ninh nghiêm trọng này.",
        "sorbsreason": "Địa chỉ IP của bạn bị liệt kê là một proxy mở trong DNSBL mà {{SITENAME}} đang sử dụng.",
index 9cf1da9..1d2dad0 100644 (file)
                        "A2093064",
                        "EagerLin",
                        "Deathkon",
-                       "RyRubyy"
+                       "RyRubyy",
+                       "Wxyveronica"
                ]
        },
        "tog-underline": "链接下划线:",
        "http-timed-out": "HTTP请求已过时。",
        "http-curl-error": "撷取URL时出错:$1",
        "http-bad-status": "进行HTTP请求时出现问题:$1 $2",
+       "http-internal-error": "HTTP内部错误。",
        "upload-curl-error6": "无法访问URL",
        "upload-curl-error6-text": "无法访问提供的URL。请检查该URL是否正确,及其网站是否在线。",
        "upload-curl-error28": "上传超时",
index 51bb659..b649940 100644 (file)
        "http-timed-out": "HTTP 請求已逾時。",
        "http-curl-error": "擷取 URL 時錯誤:$1",
        "http-bad-status": "進行 HTTP 請求發生問題:$1 $2",
+       "http-internal-error": "HTTP 內部錯誤。",
        "upload-curl-error6": "無法連線至 URL",
        "upload-curl-error6-text": "無法連線至指定的 URL 。\n請重新檢查 URL 是否正確,且確認網站是否正常運作。",
        "upload-curl-error28": "上傳逾時",
        "undeletehistory": "若您還原該頁面,所有的修訂歷史也會一併還原。\n若刪除之後已有使用相同名稱建立的新頁面,還原的修訂歷史會出現在此頁面之前的歷史中。",
        "undeleterevdel": "若最新頁面或檔案修訂被部份刪除,將無法執行取消刪除的動作。\n這種情況您必須取消勾選或取消隱藏已刪除的最新修訂。",
        "undeletehistorynoadmin": "已刪除此頁面。\n以下摘要顯示刪除原因與刪除前所有編輯過此頁面的使用者詳細資料。\n這些已刪除的實際文字修訂僅對管理員可用。",
-       "undelete-revision": "被 $3 刪除的 $1 (於 $4 $5) 修訂:",
+       "undelete-revision": "$1由$3(於$4 $5)所編輯的已刪除修訂版本",
        "undeleterevision-missing": "無效或遺失的修訂。\n您可能使用了錯誤的連結,或該修訂已從封存中還原或刪除。",
        "undeleterevision-duplicate-revid": "無法還原 {{PLURAL:$1|1 個修訂|$1 修訂}},因{{PLURAL:$1|修訂的|修訂的}} <code>rev_id</code> 已在使用中。",
        "undelete-nodiff": "查無先前的修訂。",
index 9955e95..4b15837 100644 (file)
@@ -15,7 +15,8 @@
                        "LNDDYL",
                        "Liuxinyu970226",
                        "Quest for Truth",
-                       "Wxyveronica"
+                       "Wxyveronica",
+                       "和平至上"
                ]
        },
        "tog-watchlisthidebots": "隱藏監視清單中機械人的編輯",
        "tooltip-t-specialpages": "特殊頁面總清單",
        "tooltip-t-print": "這個頁面的可打印版本",
        "tooltip-ca-nstab-user": "檢視用戶頁面",
-       "pageinfo-toolboxlink": "頁面咨詢",
+       "pageinfo-toolboxlink": "頁面資訊",
        "newimages-showbots": "顯示機械人上傳的檔案",
        "exif-rowsperstrip": "每帶行數",
        "redirect-user": "用戶 ID",
index 83525f2..34add28 100644 (file)
@@ -37,8 +37,6 @@
                 *  - `pluralRules`
                 *  - `digitGroupingPattern`
                 *  - `fallbackLanguages`
-                *  - `bcp47Map`
-                *  - `languageNames`
                 *
                 * @property
                 */
index 808f347..45863a3 100644 (file)
                },
 
                /**
-                * Formats language tags according the BCP 47 standard.
+                * Formats language tags according the BCP47 standard.
                 * See LanguageCode::bcp47 for the PHP implementation.
                 *
                 * @param {string} languageTag Well-formed language tag
                 * @return {string}
                 */
                bcp47: function ( languageTag ) {
-                       var bcp47Map,
-                               formatted,
-                               segments,
+                       var formatted,
                                isFirstSegment = true,
-                               isPrivate = false;
+                               isPrivate = false,
+                               segments = languageTag.split( '-' );
 
-                       languageTag = languageTag.toLowerCase();
-
-                       bcp47Map = mw.language.getData( mw.config.get( 'wgUserLanguage' ), 'bcp47Map' );
-                       if ( bcp47Map && Object.prototype.hasOwnProperty.call( bcp47Map, languageTag ) ) {
-                               languageTag = bcp47Map[ languageTag ];
-                       }
-
-                       segments = languageTag.split( '-' );
                        formatted = segments.map( function ( segment ) {
                                var newSegment;
 
index 1cd320f..159e4ad 100644 (file)
@@ -8,13 +8,14 @@ class WfExpandUrlTest extends MediaWikiTestCase {
         * @dataProvider provideExpandableUrls
         */
        public function testWfExpandUrl( $fullUrl, $shortUrl, $defaultProto,
-               $server, $canServer, $httpsMode, $message
+               $server, $canServer, $httpsMode, $httpsPort, $message
        ) {
                // Fake $wgServer, $wgCanonicalServer and $wgRequest->getProtocol()
                $this->setMwGlobals( [
                        'wgServer' => $server,
                        'wgCanonicalServer' => $canServer,
-                       'wgRequest' => new FauxRequest( [], false, null, $httpsMode ? 'https' : 'http' )
+                       'wgRequest' => new FauxRequest( [], false, null, $httpsMode ? 'https' : 'http' ),
+                       'wgHttpsPort' => $httpsPort
                ] );
 
                $this->assertEquals( $fullUrl, wfExpandUrl( $shortUrl, $defaultProto ), $message );
@@ -49,14 +50,14 @@ class WfExpandUrlTest extends MediaWikiTestCase {
                                        foreach ( $defaultProtos as $protoDesc => $defaultProto ) {
                                                $retval[] = [
                                                        'http://example.com', 'http://example.com',
-                                                       $defaultProto, $server, $canServer, $httpsMode,
+                                                       $defaultProto, $server, $canServer, $httpsMode, 443,
                                                        "Testing fully qualified http URLs (no need to expand) "
                                                                . "(defaultProto: $protoDesc , wgServer: $server, "
                                                                . "wgCanonicalServer: $canServer, current request protocol: $mode )"
                                                ];
                                                $retval[] = [
                                                        'https://example.com', 'https://example.com',
-                                                       $defaultProto, $server, $canServer, $httpsMode,
+                                                       $defaultProto, $server, $canServer, $httpsMode, 443,
                                                        "Testing fully qualified https URLs (no need to expand) "
                                                                . "(defaultProto: $protoDesc , wgServer: $server, "
                                                                . "wgCanonicalServer: $canServer, current request protocol: $mode )"
@@ -64,7 +65,7 @@ class WfExpandUrlTest extends MediaWikiTestCase {
                                                # Would be nice to support this, see fixme on wfExpandUrl()
                                                $retval[] = [
                                                        "wiki/FooBar", 'wiki/FooBar',
-                                                       $defaultProto, $server, $canServer, $httpsMode,
+                                                       $defaultProto, $server, $canServer, $httpsMode, 443,
                                                        "Test non-expandable relative URLs (defaultProto: $protoDesc, "
                                                                . "wgServer: $server, wgCanonicalServer: $canServer, "
                                                                . "current request protocol: $mode )"
@@ -91,7 +92,7 @@ class WfExpandUrlTest extends MediaWikiTestCase {
 
                                                $retval[] = [
                                                        "$p//wikipedia.org", '//wikipedia.org',
-                                                       $defaultProto, $server, $canServer, $httpsMode,
+                                                       $defaultProto, $server, $canServer, $httpsMode, 443,
                                                        "Test protocol-relative URL (defaultProto: $protoDesc, "
                                                                . "wgServer: $server, wgCanonicalServer: $canServer, "
                                                                . "current request protocol: $mode )"
@@ -103,6 +104,7 @@ class WfExpandUrlTest extends MediaWikiTestCase {
                                                        $server,
                                                        $canServer,
                                                        $httpsMode,
+                                                       443,
                                                        "Testing expanding URL beginning with / (defaultProto: $protoDesc, "
                                                                . "wgServer: $server, wgCanonicalServer: $canServer, "
                                                                . "current request protocol: $mode )"
@@ -112,6 +114,39 @@ class WfExpandUrlTest extends MediaWikiTestCase {
                        }
                }
 
+               // Don't add HTTPS port to foreign URLs
+               $retval[] = [
+                       'https://foreign.example.com/foo',
+                       'https://foreign.example.com/foo',
+                       PROTO_HTTPS,
+                       '//wiki.example.com',
+                       'http://wiki.example.com',
+                       'https',
+                       111,
+                       "Don't add HTTPS port to foreign URLs"
+               ];
+               $retval[] = [
+                       'https://foreign.example.com:222/foo',
+                       'https://foreign.example.com:222/foo',
+                       PROTO_HTTPS,
+                       '//wiki.example.com',
+                       'http://wiki.example.com',
+                       'https',
+                       111,
+                       "Don't overwrite HTTPS port of foreign URLs"
+               ];
+               // Do add HTTPS port to local URLs
+               $retval[] = [
+                       'https://wiki.example.com:111/foo',
+                       '/foo',
+                       PROTO_HTTPS,
+                       '//wiki.example.com',
+                       'http://wiki.example.com',
+                       'https',
+                       111,
+                       "Do add HTTPS port to protocol-relative URLs"
+               ];
+
                return $retval;
        }
 }
index 7d7e637..d79d2cf 100644 (file)
@@ -1,6 +1,8 @@
 <?php
 
 class MediaWikiTest extends MediaWikiTestCase {
+       private $oldServer, $oldGet, $oldPost;
+
        protected function setUp() {
                parent::setUp();
 
@@ -11,6 +13,18 @@ class MediaWikiTest extends MediaWikiTestCase {
                        'wgArticlePath' => '/wiki/$1',
                        'wgActionPaths' => [],
                ] );
+
+               // phpcs:disable MediaWiki.Usage.SuperGlobalsUsage.SuperGlobals
+               $this->oldServer = $_SERVER;
+               $this->oldGet = $_GET;
+               $this->oldPost = $_POST;
+       }
+
+       protected function tearDown() {
+               parent::tearDown();
+               $_SERVER = $this->oldServer;
+               $_GET = $this->oldGet;
+               $_POST = $this->oldPost;
        }
 
        public static function provideTryNormaliseRedirect() {
@@ -113,6 +127,13 @@ class MediaWikiTest extends MediaWikiTestCase {
                                'title' => 'Foo_Bar',
                                'redirect' => false,
                        ],
+                       [
+                               // Path with double slash prefix (T100782)
+                               'url' => 'http://example.org//wiki/Double_slash',
+                               'query' => [],
+                               'title' => 'Double_slash',
+                               'redirect' => false,
+                       ],
                ];
        }
 
@@ -122,11 +143,13 @@ class MediaWikiTest extends MediaWikiTestCase {
         */
        public function testTryNormaliseRedirect( $url, $query, $title, $expectedRedirect = false ) {
                // Set SERVER because interpolateTitle() doesn't use getRequestURL(),
-               // whereas tryNormaliseRedirect does().
+               // whereas tryNormaliseRedirect does(). Also, using WebRequest allows
+               // us to test some quirks in that class.
                $_SERVER['REQUEST_URI'] = $url;
+               $_POST = [];
+               $_GET = $query;
+               $req = new WebRequest;
 
-               $req = new FauxRequest( $query );
-               $req->setRequestURL( $url );
                // This adds a virtual 'title' query parameter. Normally called from Setup.php
                $req->interpolateTitle();
 
index 15c4791..d891675 100644 (file)
@@ -145,6 +145,58 @@ class PathRouterTest extends MediaWikiTestCase {
                                [ 'title' => "Title_With Space" ]
                        ],
 
+                       // Double slash and dot expansion
+                       'Double slash in prefix' => [
+                               '/wiki/$1',
+                               '//wiki/Foo',
+                               [ 'title' => 'Foo' ]
+                       ],
+                       'Double slash at start of $1' => [
+                               '/wiki/$1',
+                               '/wiki//Foo',
+                               [ 'title' => '/Foo' ]
+                       ],
+                       'Double slash in middle of $1' => [
+                               '/wiki/$1',
+                               '/wiki/.hack//SIGN',
+                               [ 'title' => '.hack//SIGN' ]
+                       ],
+                       'Dots removed 1' => [
+                               '/wiki/$1',
+                               '/x/../wiki/Foo',
+                               [ 'title' => 'Foo' ]
+                       ],
+                       'Dots removed 2' => [
+                               '/wiki/$1',
+                               '/./wiki/Foo',
+                               [ 'title' => 'Foo' ]
+                       ],
+                       'Dots retained 1' => [
+                               '/wiki/$1',
+                               '/wiki/../wiki/Foo',
+                               [ 'title' => '../wiki/Foo' ]
+                       ],
+                       'Dots retained 2' => [
+                               '/wiki/$1',
+                               '/wiki/./Foo',
+                               [ 'title' => './Foo' ]
+                       ],
+                       'Triple slash' => [
+                               '/wiki/$1',
+                               '///wiki/Foo',
+                               [ 'title' => 'Foo' ]
+                       ],
+                       // '..' only traverses one slash, see e.g. RFC 3986
+                       'Dots traversing double slash 1' => [
+                               '/wiki/$1',
+                               '/a//b/../../wiki/Foo',
+                               []
+                       ],
+                       'Dots traversing double slash 2' => [
+                               '/wiki/$1',
+                               '/a//b/../../../wiki/Foo',
+                               [ 'title' => 'Foo' ]
+                       ],
                ];
 
                // Make sure the router doesn't break on special characters like $ used in regexp replacements
index d4aa805..03359f8 100644 (file)
@@ -10,6 +10,13 @@ class ApiFormatBaseTest extends ApiFormatTestBase {
 
        protected $printerName = 'mockbase';
 
+       protected function setUp() {
+               parent::setUp();
+               $this->setMwGlobals( [
+                       'wgServer' => 'http://example.org'
+               ] );
+       }
+
        public function getMockFormatter( ApiMain $main = null, $format, $methods = [] ) {
                if ( $main === null ) {
                        $context = new RequestContext;
@@ -352,7 +359,7 @@ class ApiFormatBaseTest extends ApiFormatTestBase {
        public function testHtmlHeader( $post, $registerNonHtml, $expect ) {
                $context = new RequestContext;
                $request = new FauxRequest( [ 'a' => 1, 'b' => 2 ], $post );
-               $request->setRequestURL( 'http://example.org/wx/api.php' );
+               $request->setRequestURL( '/wx/api.php' );
                $context->setRequest( $request );
                $context->setLanguage( 'qqx' );
                $main = new ApiMain( $context );
index 06772e5..d7dc411 100644 (file)
@@ -5,7 +5,6 @@
  *
  * @license GPL-2.0-or-later
  * @author Gergő Tisza
- * @author Thiemo Mättig
  */
 class HTMLFormTest extends MediaWikiTestCase {
 
index f14d2ce..544a063 100644 (file)
@@ -54,18 +54,14 @@ class LanguageCodeTest extends PHPUnit\Framework\TestCase {
         * @dataProvider provideLanguageCodes()
         */
        public function testBcp47( $code, $expected ) {
-               $this->assertEquals( $expected, LanguageCode::bcp47( $code ),
-                       "Applying BCP 47 standard to '$code'"
-               );
-
                $code = strtolower( $code );
                $this->assertEquals( $expected, LanguageCode::bcp47( $code ),
-                       "Applying BCP 47 standard to lower case '$code'"
+                       "Applying BCP47 standard to lower case '$code'"
                );
 
                $code = strtoupper( $code );
                $this->assertEquals( $expected, LanguageCode::bcp47( $code ),
-                       "Applying BCP 47 standard to upper case '$code'"
+                       "Applying BCP47 standard to upper case '$code'"
                );
        }
 
@@ -159,41 +155,6 @@ class LanguageCodeTest extends PHPUnit\Framework\TestCase {
                        // de-419-DE
                        // a-DE
                        // ar-a-aaa-b-bbb-a-ccc
-
-                       # Non-standard and deprecated language codes used by MediaWiki
-                       [ 'als', 'gsw' ],
-                       [ 'bat-smg', 'sgs' ],
-                       [ 'be-x-old', 'be-tarask' ],
-                       [ 'fiu-vro', 'vro' ],
-                       [ 'roa-rup', 'rup' ],
-                       [ 'zh-classical', 'lzh' ],
-                       [ 'zh-min-nan', 'nan' ],
-                       [ 'zh-yue', 'yue' ],
-                       [ 'cbk-zam', 'cbk' ],
-                       [ 'de-formal', 'de-x-formal' ],
-                       [ 'eml', 'egl' ],
-                       [ 'en-rtl', 'en-x-rtl' ],
-                       [ 'es-formal', 'es-x-formal' ],
-                       [ 'hu-formal', 'hu-x-formal' ],
-                       [ 'kk-Arab', 'kk-Arab' ],
-                       [ 'kk-Cyrl', 'kk-Cyrl' ],
-                       [ 'kk-Latn', 'kk-Latn' ],
-                       [ 'map-bms', 'jv-x-bms' ],
-                       [ 'mo', 'ro-MD' ],
-                       [ 'nrm', 'nrf' ],
-                       [ 'nl-informal', 'nl-x-informal' ],
-                       [ 'roa-tara', 'nap-x-tara' ],
-                       [ 'simple', 'en-simple' ],
-                       [ 'sr-ec', 'sr-Cyrl' ],
-                       [ 'sr-el', 'sr-Latn' ],
-                       [ 'zh-cn', 'zh-Hans-CN' ],
-                       [ 'zh-sg', 'zh-Hans-SG' ],
-                       [ 'zh-my', 'zh-Hans-MY' ],
-                       [ 'zh-tw', 'zh-Hant-TW' ],
-                       [ 'zh-hk', 'zh-Hant-HK' ],
-                       [ 'zh-mo', 'zh-Hant-MO' ],
-                       [ 'zh-hans', 'zh-Hans' ],
-                       [ 'zh-hant', 'zh-Hant' ],
                ];
        }
 
index b5db2ec..82ab7de 100644 (file)
@@ -20,9 +20,7 @@ class LanguageConverterTest extends MediaWikiLangTestCase {
                $this->lang = new LanguageToTest();
                $this->lc = new TestConverter(
                        $this->lang, 'tg',
-                       # Adding 'sgs' as a variant to ensure we handle deprecated codes
-                       # adding 'simple' as a variant to ensure we handle non BCP 47 codes
-                       [ 'tg', 'tg-latn', 'sgs', 'simple' ]
+                       [ 'tg', 'tg-latn' ]
                );
        }
 
@@ -40,39 +38,6 @@ class LanguageConverterTest extends MediaWikiLangTestCase {
                $this->assertEquals( 'tg', $this->lc->getPreferredVariant() );
        }
 
-       /**
-        * @covers LanguageConverter::getPreferredVariant
-        * @covers LanguageConverter::getURLVariant
-        */
-       public function testGetPreferredVariantUrl() {
-               global $wgRequest;
-               $wgRequest->setVal( 'variant', 'tg-latn' );
-
-               $this->assertEquals( 'tg-latn', $this->lc->getPreferredVariant() );
-       }
-
-       /**
-        * @covers LanguageConverter::getPreferredVariant
-        * @covers LanguageConverter::getURLVariant
-        */
-       public function testGetPreferredVariantUrlDeprecated() {
-               global $wgRequest;
-               $wgRequest->setVal( 'variant', 'bat-smg' );
-
-               $this->assertEquals( 'sgs', $this->lc->getPreferredVariant() );
-       }
-
-       /**
-        * @covers LanguageConverter::getPreferredVariant
-        * @covers LanguageConverter::getURLVariant
-        */
-       public function testGetPreferredVariantUrlBCP47() {
-               global $wgRequest;
-               $wgRequest->setVal( 'variant', 'en-simple' );
-
-               $this->assertEquals( 'simple', $this->lc->getPreferredVariant() );
-       }
-
        /**
         * @covers LanguageConverter::getPreferredVariant
         * @covers LanguageConverter::getHeaderVariant
@@ -84,17 +49,6 @@ class LanguageConverterTest extends MediaWikiLangTestCase {
                $this->assertEquals( 'tg-latn', $this->lc->getPreferredVariant() );
        }
 
-       /**
-        * @covers LanguageConverter::getPreferredVariant
-        * @covers LanguageConverter::getHeaderVariant
-        */
-       public function testGetPreferredVariantHeadersBCP47() {
-               global $wgRequest;
-               $wgRequest->setHeader( 'Accept-Language', 'en-simple' );
-
-               $this->assertEquals( 'simple', $this->lc->getPreferredVariant() );
-       }
-
        /**
         * @covers LanguageConverter::getPreferredVariant
         * @covers LanguageConverter::getHeaderVariant
@@ -144,38 +98,6 @@ class LanguageConverterTest extends MediaWikiLangTestCase {
                $this->assertEquals( 'tg-latn', $this->lc->getPreferredVariant() );
        }
 
-       /**
-        * @covers LanguageConverter::getPreferredVariant
-        */
-       public function testGetPreferredVariantUserOptionDeprecated() {
-               global $wgUser;
-
-               $wgUser = new User;
-               $wgUser->load(); // from 'defaults'
-               $wgUser->mId = 1;
-               $wgUser->mDataLoaded = true;
-               $wgUser->mOptionsLoaded = true;
-               $wgUser->setOption( 'variant', 'bat-smg' );
-
-               $this->assertEquals( 'sgs', $this->lc->getPreferredVariant() );
-       }
-
-       /**
-        * @covers LanguageConverter::getPreferredVariant
-        */
-       public function testGetPreferredVariantUserOptionBCP47() {
-               global $wgUser;
-
-               $wgUser = new User;
-               $wgUser->load(); // from 'defaults'
-               $wgUser->mId = 1;
-               $wgUser->mDataLoaded = true;
-               $wgUser->mOptionsLoaded = true;
-               $wgUser->setOption( 'variant', 'en-simple' );
-
-               $this->assertEquals( 'simple', $this->lc->getPreferredVariant() );
-       }
-
        /**
         * @covers LanguageConverter::getPreferredVariant
         * @covers LanguageConverter::getUserVariant
@@ -194,42 +116,6 @@ class LanguageConverterTest extends MediaWikiLangTestCase {
                $this->assertEquals( 'tg-latn', $this->lc->getPreferredVariant() );
        }
 
-       /**
-        * @covers LanguageConverter::getPreferredVariant
-        * @covers LanguageConverter::getUserVariant
-        */
-       public function testGetPreferredVariantUserOptionForForeignLanguageDeprecated() {
-               global $wgContLang, $wgUser;
-
-               $wgContLang = Language::factory( 'en' );
-               $wgUser = new User;
-               $wgUser->load(); // from 'defaults'
-               $wgUser->mId = 1;
-               $wgUser->mDataLoaded = true;
-               $wgUser->mOptionsLoaded = true;
-               $wgUser->setOption( 'variant-tg', 'bat-smg' );
-
-               $this->assertEquals( 'sgs', $this->lc->getPreferredVariant() );
-       }
-
-       /**
-        * @covers LanguageConverter::getPreferredVariant
-        * @covers LanguageConverter::getUserVariant
-        */
-       public function testGetPreferredVariantUserOptionForForeignLanguageBCP47() {
-               global $wgContLang, $wgUser;
-
-               $wgContLang = Language::factory( 'en' );
-               $wgUser = new User;
-               $wgUser->load(); // from 'defaults'
-               $wgUser->mId = 1;
-               $wgUser->mDataLoaded = true;
-               $wgUser->mOptionsLoaded = true;
-               $wgUser->setOption( 'variant-tg', 'en-simple' );
-
-               $this->assertEquals( 'simple', $this->lc->getPreferredVariant() );
-       }
-
        /**
         * @covers LanguageConverter::getPreferredVariant
         * @covers LanguageConverter::getUserVariant
@@ -259,26 +145,6 @@ class LanguageConverterTest extends MediaWikiLangTestCase {
                $this->assertEquals( 'tg-latn', $this->lc->getPreferredVariant() );
        }
 
-       /**
-        * @covers LanguageConverter::getPreferredVariant
-        */
-       public function testGetPreferredVariantDefaultLanguageVariantDeprecated() {
-               global $wgDefaultLanguageVariant;
-
-               $wgDefaultLanguageVariant = 'bat-smg';
-               $this->assertEquals( 'sgs', $this->lc->getPreferredVariant() );
-       }
-
-       /**
-        * @covers LanguageConverter::getPreferredVariant
-        */
-       public function testGetPreferredVariantDefaultLanguageVariantBCP47() {
-               global $wgDefaultLanguageVariant;
-
-               $wgDefaultLanguageVariant = 'en-simple';
-               $this->assertEquals( 'simple', $this->lc->getPreferredVariant() );
-       }
-
        /**
         * @covers LanguageConverter::getPreferredVariant
         * @covers LanguageConverter::getURLVariant
@@ -326,8 +192,6 @@ class TestConverter extends LanguageConverter {
 
        function loadDefaultTables() {
                $this->mTables = [
-                       'sgs' => new ReplacementArray(),
-                       'simple' => new ReplacementArray(),
                        'tg-latn' => new ReplacementArray( $this->table ),
                        'tg' => new ReplacementArray()
                ];
index af5433a..9ea3c11 100644 (file)
                // # Tags that use extensions
                [ 'en-us-u-islamcal', 'en-US-u-islamcal' ],
                [ 'zh-cn-a-myext-x-private', 'zh-CN-a-myext-x-private' ],
-               [ 'en-a-myext-b-another', 'en-a-myext-b-another' ],
+               [ 'en-a-myext-b-another', 'en-a-myext-b-another' ]
 
                // # Invalid:
                // de-419-DE
                // a-DE
                // ar-a-aaa-b-bbb-a-ccc
-
-               // Non-standard and deprecated language codes used by MediaWiki
-               [ 'als', 'gsw' ],
-               [ 'bat-smg', 'sgs' ],
-               [ 'be-x-old', 'be-tarask' ],
-               [ 'fiu-vro', 'vro' ],
-               [ 'roa-rup', 'rup' ],
-               [ 'zh-classical', 'lzh' ],
-               [ 'zh-min-nan', 'nan' ],
-               [ 'zh-yue', 'yue' ],
-               [ 'cbk-zam', 'cbk' ],
-               [ 'de-formal', 'de-x-formal' ],
-               [ 'eml', 'egl' ],
-               [ 'en-rtl', 'en-x-rtl' ],
-               [ 'es-formal', 'es-x-formal' ],
-               [ 'hu-formal', 'hu-x-formal' ],
-               [ 'kk-Arab', 'kk-Arab' ],
-               [ 'kk-Cyrl', 'kk-Cyrl' ],
-               [ 'kk-Latn', 'kk-Latn' ],
-               [ 'map-bms', 'jv-x-bms' ],
-               [ 'mo', 'ro-MD' ],
-               [ 'nrm', 'nrf' ],
-               [ 'nl-informal', 'nl-x-informal' ],
-               [ 'roa-tara', 'nap-x-tara' ],
-               [ 'simple', 'en-simple' ],
-               [ 'sr-ec', 'sr-Cyrl' ],
-               [ 'sr-el', 'sr-Latn' ],
-               [ 'zh-cn', 'zh-Hans-CN' ],
-               [ 'zh-sg', 'zh-Hans-SG' ],
-               [ 'zh-my', 'zh-Hans-MY' ],
-               [ 'zh-tw', 'zh-Hant-TW' ],
-               [ 'zh-hk', 'zh-Hant-HK' ],
-               [ 'zh-mo', 'zh-Hant-MO' ],
-               [ 'zh-hans', 'zh-Hans' ],
-               [ 'zh-hant', 'zh-Hant' ]
        ];
 
        QUnit.test( 'mw.language.bcp47', function ( assert ) {
-               mw.language.data = this.liveLangData;
                bcp47Tests.forEach( function ( data ) {
                        var input = data[ 0 ],
                                expected = data[ 1 ];
                        assert.strictEqual( mw.language.bcp47( input ), expected );
-                       assert.strictEqual( mw.language.bcp47( input.toLowerCase() ), expected );
-                       assert.strictEqual( mw.language.bcp47( input.toUpperCase() ), expected );
                } );
        } );
 }( mediaWiki, jQuery ) );