Merge "Revert "Introduce RevisionStoreFactory & Tests""
authorjenkins-bot <jenkins-bot@gerrit.wikimedia.org>
Thu, 5 Jul 2018 15:08:36 +0000 (15:08 +0000)
committerGerrit Code Review <gerrit@wikimedia.org>
Thu, 5 Jul 2018 15:08:36 +0000 (15:08 +0000)
72 files changed:
.travis.yml
RELEASE-NOTES-1.32
includes/Block.php
includes/EditPage.php
includes/GlobalFunctions.php
includes/MediaWikiServices.php
includes/OutputPage.php
includes/ServiceWiring.php
includes/Storage/DerivedPageDataUpdater.php
includes/api/i18n/uk.json
includes/cache/MessageCache.php
includes/db/CloneDatabase.php
includes/diff/DifferenceEngine.php
includes/filerepo/file/ArchivedFile.php
includes/filerepo/file/LocalFile.php
includes/filerepo/file/OldLocalFile.php
includes/libs/objectcache/RESTBagOStuff.php
includes/libs/rdbms/database/Database.php
includes/libs/rdbms/database/DatabaseSqlite.php
includes/libs/rdbms/loadbalancer/ILoadBalancer.php
includes/resourceloader/ResourceLoader.php
includes/search/SearchMssql.php
includes/session/SessionProviderInterface.php
includes/shell/Shell.php
includes/specials/pagers/DeletedContribsPager.php
languages/Language.php
languages/i18n/ast.json
languages/i18n/be-tarask.json
languages/i18n/ca.json
languages/i18n/ce.json
languages/i18n/ckb.json
languages/i18n/et.json
languages/i18n/frr.json
languages/i18n/hr.json
languages/i18n/hu.json
languages/i18n/ia.json
languages/i18n/is.json
languages/i18n/mg.json
languages/i18n/mni.json
languages/i18n/my.json
languages/i18n/nb.json
languages/i18n/nl.json
languages/i18n/nn.json
languages/i18n/pt-br.json
languages/i18n/pt.json
languages/i18n/sat.json
languages/i18n/sr-ec.json
languages/i18n/sr-el.json
languages/i18n/te.json
languages/i18n/uk.json
languages/i18n/ur.json
languages/i18n/zh-hant.json
maintenance/Maintenance.php
maintenance/categoryChangesAsRdf.php
maintenance/storage/recompressTracked.php
resources/Resources.php
resources/src/mediawiki.Upload.BookletLayout/BookletLayout.css
resources/src/mediawiki.rcfilters/dm/mw.rcfilters.dm.ItemModel.js
resources/src/mediawiki.rcfilters/ui/mw.rcfilters.ui.FilterTagMultiselectWidget.js
resources/src/mediawiki.rcfilters/ui/mw.rcfilters.ui.MenuSelectWidget.js
resources/src/mediawiki.special.preferences.styles.ooui.css [deleted file]
resources/src/mediawiki.special.preferences.styles.ooui.less [new file with mode: 0644]
resources/src/mediawiki.widgets/mw.widgets.TitleWidget.js
tests/integration/includes/shell/FirejailCommandTest.php
tests/parser/parserTests.txt
tests/phpunit/MediaWikiTestCase.php
tests/phpunit/includes/MediaWikiServicesTest.php
tests/phpunit/includes/Storage/McrWriteBothRevisionStoreDbTest.php
tests/phpunit/includes/Storage/NoContentModelRevisionStoreDbTest.php
tests/phpunit/includes/Storage/PreMcrRevisionStoreDbTest.php
tests/phpunit/includes/db/LoadBalancerTest.php
tests/phpunit/includes/libs/rdbms/database/DatabaseTest.php

index e15fc55..2fc6d64 100644 (file)
@@ -38,8 +38,11 @@ matrix:
     - env: dbtype=mysql dbuser=root
       php: hhvm-3.18
   allow_failures:
-    - php: hhvm-3.24
+    - php: 7.2
+    - env: dbtype=postgres dbuser=travis
+    - php: hhvm-3.18
     - php: hhvm-3.21
+    - php: hhvm-3.24
 
 services:
   - mysql
@@ -80,7 +83,8 @@ notifications:
   email: false
   irc:
     channels:
-      - "chat.freenode.net#mediawiki-feed"
+      - "chat.freenode.net#wikimedia-dev"
+    template:
+      - "%{repository}#%{build_number} (%{branch} - %{commit} %{author}): %{message} - %{build_url}"
     on_success: change
-    on_failure: change
-    skip_join: true
+    on_failure: always
index d0d5eb2..a269629 100644 (file)
@@ -227,6 +227,7 @@ because of Phabricator reports.
 * The 'jquery.hidpi' module (polyfill for IMG srcset) is deprecated.
 * ResourceLoaderStartUpModule::getStartupModules() and ::getLegacyModules()
   are deprecated. These concepts are obsolete and have no replacement.
+* String type for $lang of DifferenceEngine::setTextLanguage is deprecated.
 
 === Other changes in 1.32 ===
 * …
index 9567b06..a7b8035 100644 (file)
@@ -224,7 +224,7 @@ class Block {
                        'ipb_address',
                        'ipb_by',
                        'ipb_by_text',
-                       'ipb_by_actor' => $wgActorTableSchemaMigrationStage > MIGRATION_OLD ? 'ipb_by_actor' : null,
+                       'ipb_by_actor' => $wgActorTableSchemaMigrationStage > MIGRATION_OLD ? 'ipb_by_actor' : 'NULL',
                        'ipb_timestamp',
                        'ipb_auto',
                        'ipb_anon_only',
index 9a8a4a6..de89ab4 100644 (file)
@@ -948,12 +948,7 @@ class EditPage {
                        } else {
                                // If we receive the last parameter of the request, we can fairly
                                // claim the POST request has not been truncated.
-
-                               // TODO: softened the check for cutover.  Once we determine
-                               // that it is safe, we should complete the transition by
-                               // removing the "edittime" clause.
-                               $this->incompleteForm = ( !$request->getVal( 'wpUltimateParam' )
-                                       && is_null( $this->edittime ) );
+                               $this->incompleteForm = !$request->getVal( 'wpUltimateParam' );
                        }
                        if ( $this->incompleteForm ) {
                                # If the form is incomplete, force to preview.
index d9996f4..d0229bc 100644 (file)
@@ -31,6 +31,7 @@ use MediaWiki\MediaWikiServices;
 use MediaWiki\Shell\Shell;
 use Wikimedia\ScopedCallback;
 use Wikimedia\Rdbms\DBReplicationWaitError;
+use Wikimedia\WrappedString;
 
 /**
  * Load an extension
@@ -3103,6 +3104,7 @@ function wfShorthandToInteger( $string = '', $default = -1 ) {
  * @return string The language code which complying with BCP 47 standards.
  */
 function wfBCP47( $code ) {
+       wfDeprecated( __METHOD__, '1.31' );
        return LanguageCode::bcp47( $code );
 }
 
index ce43f0e..a756d50 100644 (file)
@@ -466,6 +466,14 @@ class MediaWikiServices extends ServiceContainer {
                return $this->getService( 'StatsdDataFactory' );
        }
 
+       /**
+        * @since 1.32
+        * @return IBufferingStatsdDataFactory
+        */
+       public function getPerDbNameStatsdDataFactory() {
+               return $this->getService( 'PerDbNameStatsdDataFactory' );
+       }
+
        /**
         * @since 1.27
         * @return EventRelayerGroup
index 0b2ba40..4ce49fd 100644 (file)
@@ -24,6 +24,7 @@ use MediaWiki\Linker\LinkTarget;
 use MediaWiki\Logger\LoggerFactory;
 use MediaWiki\MediaWikiServices;
 use MediaWiki\Session\SessionManager;
+use Wikimedia\Rdbms\IResultWrapper;
 use Wikimedia\RelPath;
 use Wikimedia\WrappedString;
 use Wikimedia\WrappedStringList;
@@ -1337,7 +1338,7 @@ class OutputPage extends ContextSource {
 
        /**
         * @param array $categories
-        * @return bool|ResultWrapper
+        * @return bool|IResultWrapper
         */
        protected function addCategoryLinksToLBAndGetResult( array $categories ) {
                # Add the links to a LinkBatch
index 425b789..6da537d 100644 (file)
@@ -128,6 +128,14 @@ return [
                );
        },
 
+       'PerDbNameStatsdDataFactory' => function ( MediaWikiServices $services ) {
+               $config = $services->getMainConfig();
+               $wiki = $config->get( 'DBname' );
+               return new BufferingStatsdDataFactory(
+                       rtrim( $services->getMainConfig()->get( 'StatsdMetricPrefix' ), '.' ) . $wiki
+               );
+       },
+
        'EventRelayerGroup' => function ( MediaWikiServices $services ) {
                return new EventRelayerGroup( $services->getMainConfig()->get( 'EventRelayerConfig' ) );
        },
index cc72754..8da812a 100644 (file)
@@ -1310,7 +1310,7 @@ class DerivedPageDataUpdater implements IDBAccessObject {
                                        // stale data from REPEATABLE-READ snapshots.
                                        // HACK: But don't use a fresh connection in unit tests, since it would not have
                                        // the fake tables. This should be handled by the LoadBalancer!
-                                       $flags = defined( 'MW_PHPUNIT_TEST' ) ? 0 : $lb::CONN_TRX_AUTO;
+                                       $flags = defined( 'MW_PHPUNIT_TEST' ) ? 0 : $lb::CONN_TRX_AUTOCOMMIT;
                                        $db = $lb->getConnectionRef( $dbIndex, [], $this->getWikiId(), $flags );
 
                                        return 1 + (int)$db->selectField(
index 59616c0..3039ef4 100644 (file)
@@ -16,7 +16,7 @@
                        "Choomaq"
                ]
        },
-       "apihelp-main-extended-description": "<div class=\"hlist plainlinks api-main-links\">\n* [[mw:Special:MyLanguage/API:Main_page|Документація]]\n* [[mw:Special:MyLanguage/API:FAQ|ЧаПи]]\n* [https://lists.wikimedia.org/mailman/listinfo/mediawiki-api Список розсилки]\n* [https://lists.wikimedia.org/mailman/listinfo/mediawiki-api-announce Оголошення API]\n* [https://phabricator.wikimedia.org/maniphest/query/GebfyV4uCaLd/#R Баґи і запити]\n</div>\n<strong>Статус:</strong> Усі функції, вказані на цій сторінці, мають працювати, але API далі перебуває в активній розробці і може змінитися у будь-який момент. Підпишіться на [https://lists.wikimedia.org/pipermail/mediawiki-api-announce/ список розсилки mediawiki-api-announce], щоб помічати оновлення.\n\n<strong>Хибні запити:</strong> Коли до API надсилаються хибні запити, буде відіслано HTTP-шапку з ключем «MediaWiki-API-Error», а тоді і значення шапки, і код помилки, надіслані назад, будуть встановлені з тим же значенням. Більше інформації див. на [[mw:Special:MyLanguage/API:Errors_and_warnings|API: Errors and warnings]].\n\n<strong>Тестування:</strong> Для зручності тестування запитів API, див. [[Special:ApiSandbox]].",
+       "apihelp-main-extended-description": "<div class=\"hlist plainlinks api-main-links\">\n* [[mw:Special:MyLanguage/API:Main_page|Документація]]\n* [[mw:Special:MyLanguage/API:FAQ|ЧаПи]]\n* [https://lists.wikimedia.org/mailman/listinfo/mediawiki-api Список розсилки]\n* [https://lists.wikimedia.org/mailman/listinfo/mediawiki-api-announce Оголошення API]\n* [https://phabricator.wikimedia.org/maniphest/query/GebfyV4uCaLd/#R Баґи і запити]\n</div>\n<strong>Статус:</strong> Усі функції, вказані на цій сторінці, мають працювати, але API далі перебуває в активній розробці і може змінитися у будь-який момент. Підпишіться на [https://lists.wikimedia.org/pipermail/mediawiki-api-announce/ список розсилки mediawiki-api-announce], щоб помічати оновлення.\n\n<strong>Хибні запити:</strong> Коли до API надсилаються хибні запити, буде відіслано HTTP-шапку з ключем «MediaWiki-API-Error», а тоді і значення шапки, і код помилки, надіслані назад, будуть встановлені з тим же значенням. Більше інформації див. на сторінці [[mw:Special:MyLanguage/API:Errors_and_warnings|API: Помилки й попередження]].\n\n<p class=\"mw-apisandbox-link\"><strong>Тестування:</strong> Для зручності тестування запитів API, див. [[Special:ApiSandbox]].</p>",
        "apihelp-main-param-action": "Яку дію виконати.",
        "apihelp-main-param-format": "Формат виводу.",
        "apihelp-main-param-maxlag": "Максимальна затримка може використовуватися, коли MediaWiki інстальовано на реплікований кластер бази даних. Щоб зберегти дії, які спричиняють більшу затримку реплікації, цей параметр може змусити клієнт почекати, поки затримка реплікації не буде меншою за вказане значення. У випадку непомірної затримки, видається код помилки <samp>maxlag</samp> з повідомленням на зразок <samp>Очікування на $host: $lag секунд(и) затримки</samp>.<br />Див. [[mw:Special:MyLanguage/Manual:Maxlag_parameter|Manual: Maxlag parameter]] для детальнішої інформації.",
@@ -67,6 +67,7 @@
        "apihelp-compare-param-fromid": "Перший ID сторінки для порівняння.",
        "apihelp-compare-param-fromrev": "Перша версія для порівняння.",
        "apihelp-compare-param-fromtext": "Використати цей текст замість контенту версії, вказаної через <var>fromtitle</var>, <var>fromid</var> або <var>fromrev</var>.",
+       "apihelp-compare-param-fromsection": "Використовувати лише вказану секцію із заданого вмісту «from».",
        "apihelp-compare-param-frompst": "Зробити трансформацію перед збереженням на <var>fromtext</var>.",
        "apihelp-compare-param-fromcontentmodel": "Контентна модель <var>fromtext</var>. Якщо не вказано, буде використано припущення на основі інших параметрів.",
        "apihelp-compare-param-fromcontentformat": "Формат серіалізації контенту <var>fromtext</var>.",
@@ -75,6 +76,7 @@
        "apihelp-compare-param-torev": "Друга версія для порівняння.",
        "apihelp-compare-param-torelative": "Використати версію, яка стосується версії, визначеної через <var>fromtitle</var>, <var>fromid</var> або <var>fromrev</var>. Усі інші опції 'to' буде проігноровано.",
        "apihelp-compare-param-totext": "Використати цей текст замість контенту версії, вказаної через <var>totitle</var>, <var>toid</var> або <var>torev</var>.",
+       "apihelp-compare-param-tosection": "Використовувати лише вказану секцію із заданого вмісту «to».",
        "apihelp-compare-param-topst": "Виконати трансформацію перед збереженням на <var>totext</var>.",
        "apihelp-compare-param-tocontentmodel": "Контентна модель <var>totext</var>. Якщо не вказано, буде використано припущення на основі інших параметрів.",
        "apihelp-compare-param-tocontentformat": "Формат серіалізації контенту <var>totext</var>.",
        "apihelp-import-extended-description": "Зважте, що HTTP POST має бути виконано як завантаження файлу (тобто з використанням даних різних частин/форм) під час надсилання файлу для параметра <var>xml</var>.",
        "apihelp-import-param-summary": "Підсумок імпорту записів журналу.",
        "apihelp-import-param-xml": "Завантажено XML-файл.",
+       "apihelp-import-param-interwikiprefix": "Для завантажених імпортів: префікс інтервікі, який слід додавати до невідомих імен користувачів (а також відомих користувачів, якщо задано <var>$1assignknownusers</var>).",
+       "apihelp-import-param-assignknownusers": "Прив'язувати редагування до локальних користувачів, якщо користувач із таким іменем існує локально.",
        "apihelp-import-param-interwikisource": "Для інтервікі-імпорту: вікі, з якої імпортувати.",
        "apihelp-import-param-interwikipage": "Для інтервікі-імпорту: сторінки для імпорту.",
        "apihelp-import-param-fullhistory": "Для інтервікі-імпорту: імпортувати повну історію, не лише поточну версію.",
        "apihelp-opensearch-summary": "Шукати у вікі з використанням протоколу OpenSearch.",
        "apihelp-opensearch-param-search": "Рядок пошуку.",
        "apihelp-opensearch-param-limit": "Максимальна кількість результатів для виведення.",
-       "apihelp-opensearch-param-namespace": "Простори назв, у яких шукати.",
+       "apihelp-opensearch-param-namespace": "Простори назв, у яких шукати. Ігнорується, якщо <var>$1search</var> починається з валідного префікса простору назв.",
        "apihelp-opensearch-param-suggest": "Нічого не робити, якщо <var>[[mw:Special:MyLanguage/Manual:$wgEnableOpenSearchSuggest|$wgEnableOpenSearchSuggest]]</var> хибний.",
        "apihelp-opensearch-param-redirects": "Як обробляти перенаправлення:\n;return:Видати саме перенаправлення.\n;resolve:Видати цільову сторінку. Може видати менше, ніж $1limit результат{{PLURAL:$1limit||и|ів}}.\nЗ історичних причин, за замовчуванням стоїть «return» для $1format=json і «resolve» — для інших форматів.",
        "apihelp-opensearch-param-format": "Формат виводу.",
        "apihelp-parse-param-disablepp": "Використати натомість <var>$1disablelimitreport</var>.",
        "apihelp-parse-param-disableeditsection": "Пропустити посилання на редагування розділів на виході аналізу.",
        "apihelp-parse-param-disabletidy": "Не запускайте очищення HTML (e.g. tidy) на виході аналізу.",
+       "apihelp-parse-param-disablestylededuplication": "Не усувайте дублікати вбудованих таблиць стилів на виході парсера.",
        "apihelp-parse-param-generatexml": "Генерувати синтаксичне дерево XML (передбачає модель вмісту <code>$1</code>; замінено на <kbd>$2prop=parsetree</kbd>).",
        "apihelp-parse-param-preview": "Аналізувати у режимі попереднього перегляду.",
        "apihelp-parse-param-sectionpreview": "Аналізувати у режимі попереднього перегляду розділу (також вмикає попередній перегляд).",
        "apihelp-query+filearchive-param-dir": "Напрямок, у якому перелічити.",
        "apihelp-query+filearchive-param-sha1": "SHA1-хеш зображення. Перевизначає $1sha1base36.",
        "apihelp-query+filearchive-param-sha1base36": "SHA1-хеш зображення у base 36 (використано в MediaWiki).",
+       "apihelp-query+filearchive-param-prop": "Інформацію про яке зображення слід отримати:",
        "apihelp-query+filearchive-paramvalue-prop-sha1": "Додає хеш SHA-1 до зображення.",
        "apihelp-query+filearchive-paramvalue-prop-timestamp": "Додає часову мітку завантаженої версії.",
        "apihelp-query+filearchive-paramvalue-prop-user": "Додає користувача, який завантажив версію зображення.",
        "apihelp-query+filearchive-paramvalue-prop-archivename": "Додає до імені версію архіву для неостаточного варіанту файлу.",
        "apihelp-query+filearchive-example-simple": "Показати список усіх вилучених файлів.",
        "apihelp-query+filerepoinfo-summary": "Видати мета-інформацію про репозиторії зображень, налаштовані на вікі.",
-       "apihelp-query+filerepoinfo-param-prop": "Які властивості репозиторію отримати (на деяких вікі може бути більше):\n;apiurl:URL до репозиторію API — корисне для отримання інформації про зображення з хосту.\n;name:Ключ репозиторію — використано в e.g. <var>[[mw:Special:MyLanguage/Manual:$wgForeignFileRepos|$wgForeignFileRepos]]</var> і значення [[Special:ApiHelp/query+imageinfo|imageinfo]].\n;displayname:Людиночита назва репозиторію вікі.\n;rooturl:Корінний URL для шляху зображення.\n;local:Чи репозиторій локальний, чи ні.",
+       "apihelp-query+filerepoinfo-param-prop": "Які властивості репозиторію отримати (доступні властивості можуть варіюватися в інших вікі).",
+       "apihelp-query+filerepoinfo-paramvalue-prop-apiurl": "URL-адреса API репозиторію — корисно для отримання інформації про зображення від хоста.",
+       "apihelp-query+filerepoinfo-paramvalue-prop-articlepath": "<var>[[mw:Special:MyLanguage/Manual:$wgArticlePath|$wgArticlePath]]</var> вікі-сайту репозиторію, або еквівалент.",
+       "apihelp-query+filerepoinfo-paramvalue-prop-canUpload": "Чи можна завантажувати файли в цей репозиторій, напр., через CORS та спільну автентифікацію.",
+       "apihelp-query+filerepoinfo-paramvalue-prop-displayname": "Назва вікі-сайту репозиторію, читабельна для людини.",
        "apihelp-query+filerepoinfo-example-simple": "Отримати інформацію про репозиторії файлів.",
        "apihelp-query+fileusage-summary": "Знайти всі сторінки, що використовують дані файли.",
        "apihelp-query+fileusage-param-prop": "Які властивості отримати:",
index 0854a43..93959db 100644 (file)
@@ -46,14 +46,11 @@ class MessageCache {
        const LOCK_TTL = 30;
 
        /**
-        * Process local cache of loaded messages that are defined in
-        * MediaWiki namespace. First array level is a language code,
-        * second level is message key and the values are either message
-        * content prefixed with space, or !NONEXISTENT for negative
-        * caching.
-        * @var array $mCache
+        * Process cache of loaded messages that are defined in MediaWiki namespace
+        *
+        * @var MapCacheLRU Map of (language code => key => " <MESSAGE>" or "!TOO BIG")
         */
-       protected $mCache;
+       protected $cache;
 
        /**
         * @var bool[] Map of (language code => boolean)
@@ -80,12 +77,6 @@ class MessageCache {
        /** @var Parser */
        protected $mParser;
 
-       /**
-        * Variable for tracking which variables are already loaded
-        * @var array $mLoadedLanguages
-        */
-       protected $mLoadedLanguages = [];
-
        /**
         * @var bool $mInParser
         */
@@ -174,6 +165,8 @@ class MessageCache {
                $this->clusterCache = $clusterCache;
                $this->srvCache = $serverCache;
 
+               $this->cache = new MapCacheLRU( 5 ); // limit size for sanity
+
                $this->mDisable = !$useDB;
                $this->mExpiry = $expiry;
        }
@@ -247,7 +240,7 @@ class MessageCache {
         *
         * @param string $code Language to which load messages
         * @param int $mode Use MessageCache::FOR_UPDATE to skip process cache [optional]
-        * @throws MWException
+        * @throws InvalidArgumentException
         * @return bool
         */
        protected function load( $code, $mode = null ) {
@@ -256,7 +249,7 @@ class MessageCache {
                }
 
                # Don't do double loading...
-               if ( isset( $this->mLoadedLanguages[$code] ) && $mode != self::FOR_UPDATE ) {
+               if ( $this->cache->has( $code ) && $mode != self::FOR_UPDATE ) {
                        return true;
                }
 
@@ -296,8 +289,8 @@ class MessageCache {
                        $staleCache = $cache;
                } else {
                        $where[] = 'got from local cache';
+                       $this->cache->set( $code, $cache );
                        $success = true;
-                       $this->mCache[$code] = $cache;
                }
 
                if ( !$success ) {
@@ -326,7 +319,7 @@ class MessageCache {
                                                $staleCache = $cache;
                                        } else {
                                                $where[] = 'got from global cache';
-                                               $this->mCache[$code] = $cache;
+                                               $this->cache->set( $code, $cache );
                                                $this->saveToCaches( $cache, 'local-only', $code );
                                                $success = true;
                                        }
@@ -347,7 +340,7 @@ class MessageCache {
                                } elseif ( $staleCache ) {
                                        # Use the stale cache while some other thread constructs the new one
                                        $where[] = 'using stale cache';
-                                       $this->mCache[$code] = $staleCache;
+                                       $this->cache->set( $code, $staleCache );
                                        $success = true;
                                        break;
                                } elseif ( $failedAttempts > 0 ) {
@@ -371,13 +364,14 @@ class MessageCache {
                if ( !$success ) {
                        $where[] = 'loading FAILED - cache is disabled';
                        $this->mDisable = true;
-                       $this->mCache = false;
+                       $this->cache->set( $code, null );
                        wfDebugLog( 'MessageCacheError', __METHOD__ . ": Failed to load $code\n" );
                        # This used to throw an exception, but that led to nasty side effects like
                        # the whole wiki being instantly down if the memcached server died
-               } else {
-                       # All good, just record the success
-                       $this->mLoadedLanguages[$code] = true;
+               }
+
+               if ( !$this->cache->has( $code ) ) { // sanity
+                       throw new LogicException( "Process cache for '$code' should be set by now." );
                }
 
                $info = implode( ', ', $where );
@@ -417,7 +411,7 @@ class MessageCache {
                }
 
                $cache = $this->loadFromDB( $code, $mode );
-               $this->mCache[$code] = $cache;
+               $this->cache->set( $code, $cache );
                $saveSuccess = $this->saveToCaches( $cache, 'all', $code );
 
                if ( !$saveSuccess ) {
@@ -473,10 +467,10 @@ class MessageCache {
 
                $mostused = [];
                if ( $wgAdaptiveMessageCache && $code !== $wgLanguageCode ) {
-                       if ( !isset( $this->mCache[$wgLanguageCode] ) ) {
+                       if ( !$this->cache->has( $wgLanguageCode ) ) {
                                $this->load( $wgLanguageCode );
                        }
-                       $mostused = array_keys( $this->mCache[$wgLanguageCode] );
+                       $mostused = array_keys( $this->cache->get( $wgLanguageCode ) );
                        foreach ( $mostused as $key => $value ) {
                                $mostused[$key] = "$value/$code";
                        }
@@ -578,10 +572,10 @@ class MessageCache {
                // (a) Update the process cache with the new message text
                if ( $text === false ) {
                        // Page deleted
-                       $this->mCache[$code][$title] = '!NONEXISTENT';
+                       $this->cache->setField( $code, $title, '!NONEXISTENT' );
                } else {
                        // Ignore $wgMaxMsgCacheEntrySize so the process cache is up to date
-                       $this->mCache[$code][$title] = ' ' . $text;
+                       $this->cache->setField( $code, $title, ' ' . $text );
                }
 
                // (b) Update the shared caches in a deferred update with a fresh DB snapshot
@@ -600,24 +594,27 @@ class MessageCache {
                                }
                                // Load the messages from the master DB to avoid race conditions
                                $cache = $this->loadFromDB( $code, self::FOR_UPDATE );
-                               $this->mCache[$code] = $cache;
-                               // Load the process cache values and set the per-title cache keys
+                               // Check if an individual cache key should exist and update cache accordingly
                                $page = WikiPage::factory( Title::makeTitle( NS_MEDIAWIKI, $title ) );
                                $page->loadPageData( $page::READ_LATEST );
                                $text = $this->getMessageTextFromContent( $page->getContent() );
-                               // Check if an individual cache key should exist and update cache accordingly
                                if ( is_string( $text ) && strlen( $text ) > $wgMaxMsgCacheEntrySize ) {
-                                       $titleKey = $this->bigMessageCacheKey( $this->mCache[$code]['HASH'], $title );
-                                       $this->wanCache->set( $titleKey, ' ' . $text, $this->mExpiry );
+                                       $this->wanCache->set(
+                                               $this->bigMessageCacheKey( $cache['HASH'], $title ),
+                                               ' ' . $text,
+                                               $this->mExpiry
+                                       );
                                }
                                // Mark this cache as definitely being "latest" (non-volatile) so
-                               // load() calls do try to refresh the cache with replica DB data
-                               $this->mCache[$code]['LATEST'] = time();
+                               // load() calls do not try to refresh the cache with replica DB data
+                               $cache['LATEST'] = time();
+                               // Update the process cache
+                               $this->cache->set( $code, $cache );
                                // Pre-emptively update the local datacenter cache so things like edit filter and
                                // blacklist changes are reflected immediately; these often use MediaWiki: pages.
                                // The datacenter handling replace() calls should be the same one handling edits
                                // as they require HTTP POST.
-                               $this->saveToCaches( $this->mCache[$code], 'all', $code );
+                               $this->saveToCaches( $cache, 'all', $code );
                                // Release the lock now that the cache is saved
                                ScopedCallback::consume( $scopedLock );
 
@@ -971,8 +968,8 @@ class MessageCache {
        public function getMsgFromNamespace( $title, $code ) {
                $this->load( $code );
 
-               if ( isset( $this->mCache[$code][$title] ) ) {
-                       $entry = $this->mCache[$code][$title];
+               if ( $this->cache->hasField( $code, $title ) ) {
+                       $entry = $this->cache->getField( $code, $title );
                        if ( substr( $entry, 0, 1 ) === ' ' ) {
                                // The message exists and is not '!TOO BIG'
                                return (string)substr( $entry, 1 );
@@ -984,40 +981,40 @@ class MessageCache {
                        $message = false;
                        Hooks::run( 'MessagesPreLoad', [ $title, &$message, $code ] );
                        if ( $message !== false ) {
-                               $this->mCache[$code][$title] = ' ' . $message;
+                               $this->cache->setField( $code, $title, ' ' . $message );
                        } else {
-                               $this->mCache[$code][$title] = '!NONEXISTENT';
+                               $this->cache->setField( $code, $title, '!NONEXISTENT' );
                        }
 
                        return $message;
                }
 
                // Individual message cache key
-               $titleKey = $this->bigMessageCacheKey( $this->mCache[$code]['HASH'], $title );
+               $bigKey = $this->bigMessageCacheKey( $this->cache->getField( $code, 'HASH' ), $title );
 
                if ( $this->mCacheVolatile[$code] ) {
                        $entry = false;
                        // Make sure that individual keys respect the WAN cache holdoff period too
                        LoggerFactory::getInstance( 'MessageCache' )->debug(
                                __METHOD__ . ': loading volatile key \'{titleKey}\'',
-                               [ 'titleKey' => $titleKey, 'code' => $code ] );
+                               [ 'titleKey' => $bigKey, 'code' => $code ] );
                } else {
                        // Try the individual message cache
-                       $entry = $this->wanCache->get( $titleKey );
+                       $entry = $this->wanCache->get( $bigKey );
                }
 
                if ( $entry !== false ) {
                        if ( substr( $entry, 0, 1 ) === ' ' ) {
-                               $this->mCache[$code][$title] = $entry;
+                               $this->cache->setField( $code, $title, $entry );
                                // The message exists, so make sure a string is returned
                                return (string)substr( $entry, 1 );
                        } elseif ( $entry === '!NONEXISTENT' ) {
-                               $this->mCache[$code][$title] = '!NONEXISTENT';
+                               $this->cache->setField( $code, $title, '!NONEXISTENT' );
 
                                return false;
                        } else {
                                // Corrupt/obsolete entry, delete it
-                               $this->wanCache->delete( $titleKey );
+                               $this->wanCache->delete( $bigKey );
                        }
                }
 
@@ -1040,14 +1037,14 @@ class MessageCache {
                        if ( $content ) {
                                $message = $this->getMessageTextFromContent( $content );
                                if ( is_string( $message ) ) {
-                                       $this->mCache[$code][$title] = ' ' . $message;
-                                       $this->wanCache->set( $titleKey, ' ' . $message, $this->mExpiry, $cacheOpts );
+                                       $this->cache->setField( $code, $title, ' ' . $message );
+                                       $this->wanCache->set( $bigKey, ' ' . $message, $this->mExpiry, $cacheOpts );
                                }
                        } else {
                                // A possibly temporary loading failure
                                LoggerFactory::getInstance( 'MessageCache' )->warning(
                                        __METHOD__ . ': failed to load message page text for \'{titleKey}\'',
-                                       [ 'titleKey' => $titleKey, 'code' => $code ] );
+                                       [ 'titleKey' => $bigKey, 'code' => $code ] );
                                $message = null; // no negative caching
                        }
                } else {
@@ -1056,8 +1053,8 @@ class MessageCache {
 
                if ( $message === false ) {
                        // Negative caching in case a "too big" message is no longer available (deleted)
-                       $this->mCache[$code][$title] = '!NONEXISTENT';
-                       $this->wanCache->set( $titleKey, '!NONEXISTENT', $this->mExpiry, $cacheOpts );
+                       $this->cache->setField( $code, $title, '!NONEXISTENT' );
+                       $this->wanCache->set( $bigKey, '!NONEXISTENT', $this->mExpiry, $cacheOpts );
                }
 
                return $message;
@@ -1192,13 +1189,12 @@ class MessageCache {
         *
         * Mainly used after a mass rebuild
         */
-       function clear() {
+       public function clear() {
                $langs = Language::fetchLanguageNames( null, 'mw' );
                foreach ( array_keys( $langs ) as $code ) {
                        $this->wanCache->touchCheckKey( $this->getCheckKey( $code ) );
                }
-
-               $this->mLoadedLanguages = [];
+               $this->cache->clear();
        }
 
        /**
@@ -1235,12 +1231,12 @@ class MessageCache {
                global $wgContLang;
 
                $this->load( $code );
-               if ( !isset( $this->mCache[$code] ) ) {
+               if ( !$this->cache->has( $code ) ) {
                        // Apparently load() failed
                        return null;
                }
                // Remove administrative keys
-               $cache = $this->mCache[$code];
+               $cache = $this->cache->get( $code );
                unset( $cache['VERSION'] );
                unset( $cache['EXPIRY'] );
                unset( $cache['EXCESSIVE'] );
index edb54ae..64c33df 100644 (file)
@@ -82,10 +82,10 @@ class CloneDatabase {
                        # works correctly across DB engines, we need to change the pre-
                        # fix back and forth so tableName() works right.
 
-                       self::changePrefix( $this->oldTablePrefix );
+                       $this->db->tablePrefix( $this->oldTablePrefix );
                        $oldTableName = $this->db->tableName( $tbl, 'raw' );
 
-                       self::changePrefix( $this->newTablePrefix );
+                       $this->db->tablePrefix( $this->newTablePrefix );
                        $newTableName = $this->db->tableName( $tbl, 'raw' );
 
                        // Postgres: Temp tables are automatically deleted upon end of session
@@ -116,12 +116,12 @@ class CloneDatabase {
         */
        public function destroy( $dropTables = false ) {
                if ( $dropTables ) {
-                       self::changePrefix( $this->newTablePrefix );
+                       $this->db->tablePrefix( $this->newTablePrefix );
                        foreach ( $this->tablesToClone as $tbl ) {
                                $this->db->dropTable( $tbl );
                        }
                }
-               self::changePrefix( $this->oldTablePrefix );
+               $this->db->tablePrefix( $this->oldTablePrefix );
        }
 
        /**
index ff07fe7..a77dab8 100644 (file)
@@ -132,6 +132,8 @@ class DifferenceEngine extends ContextSource {
        }
 
        /**
+        * Get the language of the difference engine, defaults to page content language
+        *
         * @return Language
         */
        public function getDiffLang() {
@@ -1343,11 +1345,14 @@ class DifferenceEngine extends ContextSource {
 
        /**
         * Set the language in which the diff text is written
-        * (Defaults to page content language).
-        * @param Language|string $lang
+        *
+        * @param Language $lang
         * @since 1.19
         */
        public function setTextLanguage( $lang ) {
+               if ( !$lang instanceof Language ) {
+                       wfDeprecated( __METHOD__ . ' with other type than Language for $lang', '1.32' );
+               }
                $this->mDiffLang = wfGetLangObj( $lang );
        }
 
index 65e4345..5589c68 100644 (file)
@@ -248,7 +248,7 @@ class ArchivedFile {
                        'fa_minor_mime',
                        'fa_user',
                        'fa_user_text',
-                       'fa_actor' => $wgActorTableSchemaMigrationStage > MIGRATION_OLD ? 'fa_actor' : null,
+                       'fa_actor' => $wgActorTableSchemaMigrationStage > MIGRATION_OLD ? 'fa_actor' : 'NULL',
                        'fa_timestamp',
                        'fa_deleted',
                        'fa_deleted_timestamp', /* Used by LocalFileRestoreBatch */
index e86f292..7206dce 100644 (file)
@@ -223,7 +223,7 @@ class LocalFile extends File {
                        'img_minor_mime',
                        'img_user',
                        'img_user_text',
-                       'img_actor' => $wgActorTableSchemaMigrationStage > MIGRATION_OLD ? 'img_actor' : null,
+                       'img_actor' => $wgActorTableSchemaMigrationStage > MIGRATION_OLD ? 'img_actor' : 'NULL',
                        'img_timestamp',
                        'img_sha1',
                ] + MediaWikiServices::getInstance()->getCommentStore()->getFields( 'img_description' );
index aa434d0..b5c44f2 100644 (file)
@@ -138,7 +138,7 @@ class OldLocalFile extends LocalFile {
                        'oi_minor_mime',
                        'oi_user',
                        'oi_user_text',
-                       'oi_actor' => $wgActorTableSchemaMigrationStage > MIGRATION_OLD ? 'oi_actor' : null,
+                       'oi_actor' => $wgActorTableSchemaMigrationStage > MIGRATION_OLD ? 'oi_actor' : 'NULL',
                        'oi_timestamp',
                        'oi_deleted',
                        'oi_sha1',
index d3aa9f5..fc3d575 100644 (file)
@@ -1,5 +1,7 @@
 <?php
 
+use Psr\Log\LoggerInterface;
+
 /**
  * Interface to key-value storage behind an HTTP server.
  *
  * @endcode
  */
 class RESTBagOStuff extends BagOStuff {
+       /**
+        * Default connection timeout in seconds. The kernel retransmits the SYN
+        * packet after 1 second, so 1.2 seconds allows for 1 retransmit without
+        * permanent failure.
+        */
+       const DEFAULT_CONN_TIMEOUT = 1.2;
+
+       /**
+        * Default request timeout
+        */
+       const DEFAULT_REQ_TIMEOUT = 3.0;
 
        /**
         * @var MultiHttpClient
@@ -43,18 +56,34 @@ class RESTBagOStuff extends BagOStuff {
                if ( empty( $params['url'] ) ) {
                        throw new InvalidArgumentException( 'URL parameter is required' );
                }
-               parent::__construct( $params );
                if ( empty( $params['client'] ) ) {
-                       $this->client = new MultiHttpClient( [] );
+                       // Pass through some params to the HTTP client.
+                       $clientParams = [
+                               'connTimeout' => $params['connTimeout'] ?? self::DEFAULT_CONN_TIMEOUT,
+                               'reqTimeout' => $params['reqTimeout'] ?? self::DEFAULT_REQ_TIMEOUT,
+                       ];
+                       foreach ( [ 'caBundlePath', 'proxy' ] as $key ) {
+                               if ( isset( $params[$key] ) ) {
+                                       $clientParams[$key] = $params[$key];
+                               }
+                       }
+                       $this->client = new MultiHttpClient( $clientParams );
                } else {
                        $this->client = $params['client'];
                }
+               // The parent constructor calls setLogger() which sets the logger in $this->client
+               parent::__construct( $params );
                // Make sure URL ends with /
                $this->url = rtrim( $params['url'], '/' ) . '/';
                // Default config, R+W > N; no locks on reads though; writes go straight to state-machine
                $this->attrMap[self::ATTR_SYNCWRITES] = self::QOS_SYNCWRITES_QC;
        }
 
+       public function setLogger( LoggerInterface $logger ) {
+               parent::setLogger( $logger );
+               $this->client->setLogger( $logger );
+       }
+
        /**
         * @param string $key
         * @param int $flags Bitfield of BagOStuff::READ_* constants [optional]
@@ -111,7 +140,7 @@ class RESTBagOStuff extends BagOStuff {
                        'body' => serialize( $value )
                ];
                list( $rcode, $rdesc, $rhdrs, $rbody, $rerr ) = $this->client->run( $req );
-               if ( $rcode === 200 || $rcode === 201 ) {
+               if ( $rcode === 200 || $rcode === 201 || $rcode === 204 ) {
                        return true;
                }
                return $this->handleError( "Failed to store $key", $rcode, $rerr );
@@ -129,7 +158,7 @@ class RESTBagOStuff extends BagOStuff {
                        'url' => $this->url . rawurlencode( $key ),
                ];
                list( $rcode, $rdesc, $rhdrs, $rbody, $rerr ) = $this->client->run( $req );
-               if ( $rcode === 200 || $rcode === 204 || $rcode === 205 ) {
+               if ( in_array( $rcode, [ 200, 204, 205, 404, 410 ] ) ) {
                        return true;
                }
                return $this->handleError( "Failed to delete $key", $rcode, $rerr );
index 57e5907..3054156 100644 (file)
@@ -1925,18 +1925,7 @@ abstract class Database implements IDatabase, IMaintainableDatabase, LoggerAware
                }
        }
 
-       public function tableExists( $table, $fname = __METHOD__ ) {
-               $tableRaw = $this->tableName( $table, 'raw' );
-               if ( isset( $this->sessionTempTables[$tableRaw] ) ) {
-                       return true; // already known to exist
-               }
-
-               $table = $this->tableName( $table );
-               $ignoreErrors = true;
-               $res = $this->query( "SELECT 1 FROM $table LIMIT 1", $fname, $ignoreErrors );
-
-               return (bool)$res;
-       }
+       abstract public function tableExists( $table, $fname = __METHOD__ );
 
        public function indexUnique( $table, $index ) {
                $indexInfo = $this->indexInfo( $table, $index );
index 4b925e6..d86c5ce 100644 (file)
@@ -519,6 +519,19 @@ class DatabaseSqlite extends Database {
                return $this->lastAffectedRowCount;
        }
 
+       function tableExists( $table, $fname = __METHOD__ ) {
+               $tableRaw = $this->tableName( $table, 'raw' );
+               if ( isset( $this->sessionTempTables[$tableRaw] ) ) {
+                       return true; // already known to exist
+               }
+
+               $encTable = $this->addQuotes( $tableRaw );
+               $res = $this->query(
+                       "SELECT 1 FROM sqlite_master WHERE type='table' AND name=$encTable" );
+
+               return $res->numRows() ? true : false;
+       }
+
        /**
         * Returns information about an index
         * Returns false if the index does not exist
index 04a553c..4eaa4e8 100644 (file)
@@ -86,8 +86,6 @@ interface ILoadBalancer {
 
        /** @var int DB handle should have DBO_TRX disabled and the caller will leave it as such */
        const CONN_TRX_AUTOCOMMIT = 1;
-       /** @var int Alias for CONN_TRX_AUTOCOMMIT for b/c; deprecated since 1.31 */
-       const CONN_TRX_AUTO = 1;
 
        /** @var string Manager of ILoadBalancer instances is running post-commit callbacks */
        const STAGE_POSTCOMMIT_CALLBACKS = 'stage-postcommit-callbacks';
index 43f294b..80eb598 100644 (file)
@@ -570,8 +570,7 @@ class ResourceLoader implements LoggerAwareInterface {
        }
 
        /**
-        * Return whether the definition of a module corresponds to a simple ResourceLoaderFileModule
-        * or one of its subclasses.
+        * Whether the module is a ResourceLoaderFileModule (including subclasses).
         *
         * @param string $name Module name
         * @return bool
@@ -584,14 +583,13 @@ class ResourceLoader implements LoggerAwareInterface {
                if ( isset( $info['object'] ) ) {
                        return false;
                }
-               if (
-                       isset( $info['class'] ) &&
-                       $info['class'] !== ResourceLoaderFileModule::class &&
-                       !is_subclass_of( $info['class'], ResourceLoaderFileModule::class )
-               ) {
-                       return false;
-               }
-               return true;
+               return (
+                       // The implied default for 'class' is ResourceLoaderFileModule
+                       !isset( $info['class'] ) ||
+                       // Explicit default
+                       $info['class'] === ResourceLoaderFileModule::class ||
+                       is_subclass_of( $info['class'], ResourceLoaderFileModule::class )
+               );
        }
 
        /**
index 43bd3be..30ac92d 100644 (file)
@@ -21,6 +21,8 @@
  * @ingroup Search
  */
 
+use Wikimedia\Rdbms\IResultWrapper;
+
 /**
  * Search engine hook base class for Mssql (ConText).
  * @ingroup Search
@@ -168,7 +170,7 @@ class SearchMssql extends SearchDatabase {
         * @param int $id
         * @param string $title
         * @param string $text
-        * @return bool|ResultWrapper
+        * @return bool|IResultWrapper
         */
        function update( $id, $title, $text ) {
                // We store the column data as UTF-8 byte order marked binary stream
@@ -191,7 +193,7 @@ class SearchMssql extends SearchDatabase {
         *
         * @param int $id
         * @param string $title
-        * @return bool|ResultWrapper
+        * @return bool|IResultWrapper
         */
        function updateTitle( $id, $title ) {
                $table = $this->db->tableName( 'searchindex' );
index 02ae23d..896e62f 100644 (file)
@@ -24,6 +24,7 @@
 namespace MediaWiki\Session;
 
 use Language;
+use Message;
 
 /**
  * This exists to make IDEs happy, so they don't see the
index ee9f1eb..0ddc443 100644 (file)
@@ -110,6 +110,7 @@ class Shell {
        /**
         * Returns a new instance of Command class
         *
+        * @note You should check Shell::isDisabled() before calling this
         * @param string|string[] ...$commands String or array of strings representing the command to
         * be executed, each value will be escaped.
         *   Example:   [ 'convert', '-font', 'font name' ] would produce "'convert' '-font' 'font name'"
@@ -223,6 +224,7 @@ class Shell {
         * Note that $parameters should be a flat array and an option with an argument
         * should consist of two consecutive items in the array (do not use "--option value").
         *
+        * @note You should check Shell::isDisabled() before calling this
         * @param string $script MediaWiki CLI script with full path
         * @param string[] $parameters Arguments and options to the script
         * @param array $options Associative array of options:
index b5ced13..f261b72 100644 (file)
@@ -23,6 +23,7 @@
  * @ingroup Pager
  */
 use MediaWiki\MediaWikiServices;
+use Wikimedia\Rdbms\IDatabase;
 use Wikimedia\Rdbms\IResultWrapper;
 use Wikimedia\Rdbms\FakeResultWrapper;
 
index 1623c36..28469ef 100644 (file)
@@ -220,7 +220,8 @@ class Language {
 
                // Check if there is a language class for the code
                $class = self::classFromCode( $code, $fallback );
-               if ( class_exists( $class ) ) {
+               // LanguageCode does not inherit Language
+               if ( class_exists( $class ) && is_a( $class, 'Language', true ) ) {
                        $lang = new $class;
                        return $lang;
                }
index 4f4aa01..8f248ce 100644 (file)
        "welcomecreation-msg": "Creóse la to cuenta.\nNun t'escaezas de camudar les tos [[Special:Preferences|preferencies de {{SITENAME}}]].",
        "yourname": "Nome d'usuariu:",
        "userlogin-yourname": "Nome d'usuariu",
-       "userlogin-yourname-ph": "Escriba'l so nome d'usuariu",
-       "createacct-another-username-ph": "Escriba'l nome d'usuariu",
+       "userlogin-yourname-ph": "Escribe'l to nome d'usuariu",
+       "createacct-another-username-ph": "Escribe'l nome d'usuariu",
        "yourpassword": "Contraseña:",
        "userlogin-yourpassword": "Contraseña",
-       "userlogin-yourpassword-ph": "Escriba la so contraseña",
-       "createacct-yourpassword-ph": "Escriba una contraseña",
+       "userlogin-yourpassword-ph": "Escribe la contraseña",
+       "createacct-yourpassword-ph": "Escribe una contraseña",
        "yourpasswordagain": "Escribi otra vuelta la contraseña:",
        "createacct-yourpasswordagain": "Confirmar la contraseña",
-       "createacct-yourpasswordagain-ph": "Escriba nuevamente la contraseña",
+       "createacct-yourpasswordagain-ph": "Escribe nuevamente la contraseña",
        "userlogin-remembermypassword": "Caltener abierta la sesión",
        "userlogin-signwithsecure": "Usar una conexón segura",
        "cannotlogin-title": "Nun pudo aniciase sesión",
        "logout": "Salir",
        "userlogout": "Salir",
        "notloggedin": "Nun aniciasti sesión",
-       "userlogin-noaccount": "¿Nun tien una cuenta?",
+       "userlogin-noaccount": "¿Nun tienes una cuenta?",
        "userlogin-joinproject": "Xunise a {{SITENAME}}",
        "createaccount": "Crear una cuenta",
-       "userlogin-resetpassword-link": "¿Escaeció la contraseña?",
+       "userlogin-resetpassword-link": "¿Escaecisti la contraseña?",
        "userlogin-helplink2": "Ayuda del aniciu de sesión",
        "userlogin-loggedin": "Yá anició sesión como {{GENDER:$1|$1}}.\nUtilice'l formulariu de más abaxo p'aniciar sesión como otru usuariu.",
        "userlogin-reauth": "Tienes d'aniciar sesión de nueves pa comprobar que yes {{GENDER:$1|$1}}.",
        "userlogin-createanother": "Crear otra cuenta",
        "createacct-emailrequired": "Direición de corréu electrónicu",
        "createacct-emailoptional": "Direición de corréu electrónicu (opcional)",
-       "createacct-email-ph": "Escriba la so direición de corréu electrónicu",
-       "createacct-another-email-ph": "Escriba la direición de corréu electrónicu",
+       "createacct-email-ph": "Escribe la to direición de corréu electrónicu",
+       "createacct-another-email-ph": "Escribe la direición de corréu electrónicu",
        "createaccountmail": "Usar una contraseña al debalu temporal y unviala a la direición de corréu electrónicu conseñada",
        "createaccountmail-help": "Pue usase pa crear una cuenta pa otra persona ensin saber la contraseña.",
        "createacct-realname": "Nome real (opcional)",
        "createacct-reason": "Motivu",
-       "createacct-reason-ph": "Por qué quier crear otra cuenta",
+       "createacct-reason-ph": "Por qué vas crear otra cuenta",
        "createacct-reason-help": "Mensaxe que s'amuesa nel rexistru de creación de cuentes",
        "createacct-submit": "Crear la cuenta",
        "createacct-another-submit": "Crear una cuenta",
        "createacct-continue-submit": "Siguir cola creación de la cuenta",
        "createacct-another-continue-submit": "Siguir cola creación de la cuenta",
-       "createacct-benefit-heading": "{{SITENAME}} failu xente como vusté.",
+       "createacct-benefit-heading": "Persones como tu son les que construyen {{SITENAME}}.",
        "createacct-benefit-body1": "{{PLURAL:$1|edición|ediciones}}",
        "createacct-benefit-body2": "{{PLURAL:$1|páxina|páxines}}",
        "createacct-benefit-body3": "{{PLURAL:$1|collaborador|collaboradores}} de recién",
        "userexists": "El nome d'usuariu conseñáu yá ta usándose.\nPor favor escueyi un nome diferente.",
        "loginerror": "Error d'aniciu de sesión",
        "createacct-error": "Error de creación de cuenta",
-       "createaccounterror": "Nun se pudo crear la cuenta: $1",
+       "createaccounterror": "Nun pudo crease la cuenta: $1",
        "nocookiesnew": "La cuenta d'usuariu ta creada, pero nun aniciasti sesión.\n{{SITENAME}} usa «cookies» pa identificar a los usuarios.\nTienes les «cookies» desactivaes.\nPor favor actívales y anicia sesión col nuevu nome d'usuariu y contraseña.",
-       "nocookieslogin": "{{SITENAME}} usa «cookies» pa identificar a los usuarios.\nTien les «cookies» desactivaes.\nPor favor activeles y vuelva a intentalo.",
-       "nocookiesfornew": "La cuenta nun se creó porque nun pudimos confirmar l'orixe.\nComprueba que tienes activaes les «cookies», recarga esta páxina y vuelvi a intentalo.",
+       "nocookieslogin": "{{SITENAME}} usa «cookies» pa identificar a los usuarios.\nTien les «cookies» desactivaes.\nPor favor actívales y tenta otra vuelta.",
+       "nocookiesfornew": "La cuenta nun se creó porque nun pudimos confirmar l'orixe.\nComprueba que tienes activaes les «cookies», recarga esta páxina y tenta otra vuelta.",
        "createacct-loginerror": "La cuenta creóse correchamente, pero nun pudo aniciase sesión automáticamente. Sigui col [[Special:UserLogin|accesu manual]].",
        "noname": "Nun conseñasti un nome d'usuariu válidu.",
        "loginsuccesstitle": "Identificáu",
        "nouserspecified": "Has d'especificar un nome d'usuariu.",
        "login-userblocked": "Esti usuariu ta bloquiáu. Nun se permite l'aniciu de sesión.",
        "wrongpassword": "Escribisti un nome d'usuariu o contraseña incorreutu.\nTenta otra vuelta.",
-       "wrongpasswordempty": "La contraseña taba en blanco.\nVuelvi a intentalo.",
+       "wrongpasswordempty": "La contraseña taba en blancu.\nTenta otra vuelta.",
        "passwordtooshort": "Les contraseñes han de tener polo menos {{PLURAL:$1|1 caráuter|$1 caráuteres}}.",
        "passwordtoolong": "Les contraseñes nun puen ser mayores de {{PLURAL:$1|1 caráuter|$1 caráuteres}}.",
        "passwordtoopopular": "Les contraseñes más escoyíes de vezu nun pueden usase. Escueye una contraseña más difícil d'aldovinar.",
        "throttled-mailpassword": "Yá s'unvió un corréu de reaniciu la clave {{PLURAL:$1|na postrer hora|nes postreres $1 hores}}.\nPa evitar abusos, namái s'unviará un corréu de reaniciu cada {{PLURAL:$1|hora|$1 hores}}.",
        "mailerror": "Fallu al unviar el corréu: $1",
        "acct_creation_throttle_hit": "Los visitantes d'esta wiki qu'usen la to direición IP yá crearon {{PLURAL:$1|1 cuenta|$1 cuentes}} nel periodu de $2, que ye'l máximu almitíu nesi tiempu.\nPoro, los visitantes qu'usen esta direición IP nun pueden crear más cuentes pol momentu.",
-       "emailauthenticated": "La so direición de corréu electrónicu confirmóse'l $2 a les $3.",
-       "emailnotauthenticated": "La so direición de corréu electrónicu inda nun se confirmó.\nNun s'unviará corréu pa nenguna de les funciones siguientes.",
+       "emailauthenticated": "La direición de corréu electrónicu confirmóse'l $2 a les $3.",
+       "emailnotauthenticated": "La direición de corréu electrónicu inda nun se confirmó.\nNun s'unviará corréu pa nenguna de les funciones siguientes.",
        "noemailprefs": "Conseña una direición de corréu electrónicu nes tos preferencies pa que funcionen eses carauterístiques.",
        "emailconfirmlink": "Confirmar la direición de corréu electrónicu",
        "invalidemailaddress": "La direición de corréu electrónicu nun pue aceutase yá que paez tener un formatu inválidu.\nPor favor conseña una direición con formatu afayadizu o dexa baleru'l campu.",
        "pt-createaccount": "Crear una cuenta",
        "pt-userlogout": "Salir",
        "php-mail-error-unknown": "Fallu desconocíu na función mail() de PHP.",
-       "user-mail-no-addy": "Intentasti unviar un corréu electrónicu ensin direición de corréu.",
-       "user-mail-no-body": "Trató d'unviar un corréu electrónicu con un cuerpu baleru o curtiu enforma.",
+       "user-mail-no-addy": "Tentasti unviar un corréu electrónicu ensin direición de corréu.",
+       "user-mail-no-body": "Tentasti unviar un corréu electrónicu col cuerpu vaciu o curtiu enforma.",
        "changepassword": "Camudar la contraseña",
-       "resetpass_announce": "P'acabar d'aniciar sesión, tien de definir equí una contraseña nueva.",
+       "resetpass_announce": "P'acabar d'aniciar sesión, tienes de configurar una contraseña nueva.",
        "resetpass_text": "<!-- Amestar testu equí -->",
        "resetpass_header": "Camudar la contraseña de la cuenta",
        "oldpassword": "Contraseña antigua:",
        "retypenew": "Vuelvi a escribir la contraseña nueva:",
        "resetpass_submit": "Configurar la contraseña y aniciar sesión",
        "changepassword-success": "Camudóse la contraseña.",
-       "changepassword-throttled": "Ficisti demasiaos intentos d'aniciu de sesión recientes.\nPor favor espera $1 enantes d'intentalo otra vuelta.",
+       "changepassword-throttled": "Ficisti demasiaos intentos d'aniciar sesión de recien.\nPor favor espera $1 enantes de tentar otra vuelta.",
        "botpasswords": "Contraseñes de bots",
        "botpasswords-summary": "Les <em>contraseñes de bot</em> permiten l'accesu a una cuenta d'usuariu por aciu de la API sin usar les credenciales d'accesu de la cuenta principal. Los permisos d'usuariu disponibles al aniciar sesión con una contraseña de bot puen tar torgaos.\n\nSi nun sabes pa qué val esto, probablemente nun tendríes d'usalo. Naide tendría de pidite nunca que xeneres una d'estes y que-y la deas.",
        "botpasswords-disabled": "Les contraseñes de bot tán desactivaes.",
        "botpasswords-label-delete": "Desaniciar",
        "botpasswords-label-resetpassword": "Reestablecer la contraseña",
        "botpasswords-label-grants": "Permisos aplicables:",
-       "botpasswords-help-grants": "Los permisos dan accesu a los permisos d'usuariu que yá tenga la cuenta. Activar un permisu equí nun da accesu a nengún permisu que la to cuenta nun tenga d'otra miente. Mira la [[Special:ListGrants|tabla de permisos]] pa más información.",
+       "botpasswords-help-grants": "Los permisos dan accesu a los permisos d'usuariu que yá tengas na cuenta. Activar un permisu equí nun da accesu a nengún permisu que la to cuenta nun tenga d'otra miente. Mira la [[Special:ListGrants|tabla de permisos]] pa más información.",
        "botpasswords-label-grants-column": "Permitío",
        "botpasswords-bad-appid": "El nome del bot \"$1\" nun ye válidu.",
        "botpasswords-insert-failed": "Nun pudo amestase'l nome de bot «$1». ¿Taba añadíu yá?",
        "resetpass-temp-emailed": "Anició sesión con un códigu temporal unviáu per corréu electrónicu.\nPa completar l'aniciu de sesión, tien de definir una nueva contraseña equí:",
        "resetpass-temp-password": "Contraseña temporal:",
        "resetpass-abort-generic": "Una estensión encaboxó'l cambiu de la contraseña.",
-       "resetpass-expired": "La so contraseña caducó. Defina una nueva contraseña p'aniciar sesión.",
+       "resetpass-expired": "La to contraseña caducó. Configura una nueva contraseña p'aniciar sesión.",
        "resetpass-expired-soft": "La contraseña caducó y precisa cambiase. Escueye agora una contraseña nueva, o pulsia «{{int:authprovider-resetpass-skip-label}}» pa cambiala sero.",
        "resetpass-validity-soft": "La contraseña nun ye válida: $1\n\nEscueye agora una contraseña nueva, o pulsia «{{int:authprovider-resetpass-skip-label}}» pa cambiala sero.",
        "passwordreset": "Reaniciar contraseña",
-       "passwordreset-text-one": "Complete esti formulariu pa reaniciar la contraseña.",
-       "passwordreset-text-many": "{{PLURAL:$1|Rellene unu de los campos pa recibir una contraseña temporal per corréu.}}",
+       "passwordreset-text-one": "Completa esti formulariu pa recibir per corréu una contraseña temporal.",
+       "passwordreset-text-many": "{{PLURAL:$1|Rellena unu de los campos pa recibir una contraseña temporal per corréu.}}",
        "passwordreset-disabled": "Los reanicios de contraseña tán desactivaos nesta wiki.",
        "passwordreset-emaildisabled": "Les funciones de corréu electrónicu tan desactivaes nesta wiki.",
        "passwordreset-username": "Nome d'usuariu:",
        "passwordreset-domain": "Dominiu:",
        "passwordreset-email": "Direición de corréu electrónicu:",
        "passwordreset-emailtitle": "Detalles de la cuenta en {{SITENAME}}",
-       "passwordreset-emailtext-ip": "Dalguién (seique vusté, dende la direición IP $1)solicitó'l reaniciu de la so contraseña de {{SITENAME}} ($4).\n{{PLURAL:$3|La cuenta d'usuariu siguiente ta asociada|Les cuentes d'usuariu siguientes tán asociaes}}\na esta direición de corréu electrónicu:\n\n$2\n\n{{PLURAL:$3|Esta contraseña provisional caduca|Estes contraseñes provisionales caduquen}} {{PLURAL:$5|nun día|en $5 díes}}.\nTendría d'aniciar sesión y escoyer una contraseña nueva agora. Si esta solicitú la fizo otra persona,\no si recordó la clave orixinal y yá nun quier camudala, pue escaecer esti mensaxe y siguir\nusando la contraseña antigua.",
-       "passwordreset-emailtext-user": "L'usuariu $1 de {{SITENAME}} solicitó un reaniciu de la so contraseña de {{SITENAME}} ($4). {{PLURAL:$3|La cuenta d'usuariu siguiente ta asociada|Les cuentes d'usuariu siguientes tán asociaes}} con esta direición de corréu electrónicu:\n\n$2\n\n{{PLURAL:$3|Esta contraseña provisional caduca|Estes contraseñes provisionales caduquen}} {{PLURAL:$5|nun día|en $5 díes}}.\nTendría d'aniciar sesión y escoyer una contraseña nueva agora. Si esta solicitú la fizo otra persona, o si recordó la clave orixinal y yá nun quier camudala, pue escaecer esti mensaxe y siguir usando la contraseña antigua.",
+       "passwordreset-emailtext-ip": "Dalguién (seique tu, dende la direición IP $1)solicitó'l reaniciu de la contraseña de {{SITENAME}} ($4).\n{{PLURAL:$3|La cuenta d'usuariu siguiente ta asociada|Les cuentes d'usuariu siguientes tán asociaes}}\na esta direición de corréu electrónicu:\n\n$2\n\n{{PLURAL:$3|Esta contraseña provisional caduca|Estes contraseñes provisionales caduquen}} {{PLURAL:$5|nun día|en $5 díes}}.\nTendríes d'aniciar sesión y escoyer una contraseña nueva agora. Si esta solicitú ye d'otra persona,\no si recordasti la clave orixinal y yá nun quies camudala, inora esti mensaxe y sigue\nusando la contraseña antigua.",
+       "passwordreset-emailtext-user": "L'usuariu $1 de {{SITENAME}} solicitó un reaniciu de la contraseña de {{SITENAME}} ($4). {{PLURAL:$3|La cuenta d'usuariu siguiente ta asociada|Les cuentes d'usuariu siguientes tán asociaes}} con esta direición de corréu electrónicu:\n\n$2\n\n{{PLURAL:$3|Esta contraseña provisional caduca|Estes contraseñes provisionales caduquen}} {{PLURAL:$5|nun día|en $5 díes}}.\nTendríes d'aniciar sesión y escoyer una contraseña nueva agora. Si esta solicitú ye d'otra persona, o si recordasti la clave orixinal y yá nun quies camudala, pues inorar esti mensaxe y siguir usando la contraseña antigua.",
        "passwordreset-emailelement": "Nome d'usuariu: \n$1\n\nContraseña temporal: \n$2",
        "passwordreset-emailsentemail": "Si esta direición de corréu electrónicu ta asociada cola to cuenta, unviaráse un corréu pa reaniciar la contraseña.",
        "passwordreset-emailsentusername": "Si hai una direición de corréu electrónicu asociada con esti nome d'usuariu, unviaráse un corréu electrónicu pa reaniciar la contraseña.",
index b23afd3..ae9c950 100644 (file)
        "fileexists-thumbnail-yes": "Верагодна, файл зьяўляецца паменшанай копіяй (<em>мініятурай</em>).\n[[$1|thumb]]\nКалі ласка, праверце файл <strong>[[:$1]]</strong>.\nКалі правераны файл зьяўляецца той жа выявай, то загрузка дадатковай мініятуры ня мае сэнсу.",
        "file-thumbnail-no": "Назва файлу пачынаецца з <strong>$1</strong>.\nВерагодна, гэта паменшаная копія выявы (<em>мініятура</em>).\nКалі вы маеце гэтую выяву ў поўным памеры, загрузіце яе, альбо зьмяніце назву файлу.",
        "fileexists-forbidden": "Файл з такой назвай ужо існуе і ня можа быць перапісаны.\nКалі ласка, вярніцеся назад і загрузіце гэты файл з новай назвай. [[File:$1|thumb|center|$1]]",
-       "fileexists-shared-forbidden": "Файл Ð· Ñ\82акой Ð½Ð°Ð·Ð²Ð°Ð¹ Ñ\83жо Ñ\96Ñ\81нÑ\83е Ñ\9e Ð°Ð³Ñ\83лÑ\8cнÑ\8bм Ñ\81Ñ\85овÑ\96Ñ\88Ñ\87Ñ\8b Ñ\84айлаÑ\9e.\nÐ\9aалÑ\96 Ð\92Ñ\8b Ð¶Ð°Ð´Ð°ÐµÑ\86е Ð·Ð°Ð³Ñ\80Ñ\83зÑ\96Ñ\86Ñ\8c Ð\92аÑ\88 Ñ\84айл, Ð²Ñ\8fÑ\80нÑ\96Ñ\86еÑ\81Ñ\8f Ð½Ð°Ð·Ð°Ð´ Ñ\96 Ð·Ð°Ð³Ñ\80Ñ\83зÑ\96Ñ\86е Ð³Ñ\8dÑ\82Ñ\8b Ñ\84айл Ð· Ð½Ð¾Ð²Ð°Ð¹ Ð½Ð°Ð·Ð²Ð°Ð¹. [[File:$1|thumb|center|$1]]",
+       "fileexists-shared-forbidden": "Файл Ð· Ñ\82акой Ð½Ð°Ð·Ð²Ð°Ð¹ Ñ\83жо Ñ\96Ñ\81нÑ\83е Ñ\9e Ð°Ð³Ñ\83лÑ\8cнÑ\8bм Ñ\81Ñ\85овÑ\96Ñ\88Ñ\87Ñ\8b Ñ\84айлаÑ\9e.\nÐ\9aалÑ\96 Ð²Ñ\8b Ð¶Ð°Ð´Ð°ÐµÑ\86е Ð·Ð°Ð³Ñ\80Ñ\83зÑ\96Ñ\86Ñ\8c Ð²Ð°Ñ\88 Ñ\84айл, Ð²Ñ\8fÑ\80нÑ\96Ñ\86еÑ\81Ñ\8f Ð½Ð°Ð·Ð°Ð´ Ñ\96 Ð·Ð°Ð³Ñ\80Ñ\83зÑ\96Ñ\86е Ð³Ñ\8dÑ\82Ñ\8b Ñ\84айл Ð· Ð½Ð¾Ð²Ð°Ð¹ Ð½Ð°Ð·Ð²Ð°Ð¹.\n[[File:$1|thumb|center|$1]]",
        "fileexists-no-change": "Гэтая загрузка зьяўляецца дакладнай копіяй цяперашняй вэрсіі <strong>[[:$1]]</strong>.",
        "fileexists-duplicate-version": "Гэтая загрузка зьяўляецца дакладнай копіяй {{PLURAL:$2|1=старой вэрсіі|старых вэрсіяў}} файлу <strong>[[:$1]]</strong>.",
        "file-exists-duplicate": "Гэты файл дублюе {{PLURAL:$1|1=наступны файл|наступныя файлы}}:",
-       "file-deleted-duplicate": "Ð\9fадобнÑ\8b Ñ\84айл ([[:$1]]) Ñ\83жо Ð²Ñ\8bдалÑ\8fÑ\9eÑ\81Ñ\8f. Ð\9aалÑ\96 Ð»Ð°Ñ\81ка, Ð¿Ð°Ð³Ð»Ñ\8fдзÑ\96Ñ\86е Ð³Ñ\96Ñ\81Ñ\82оÑ\80Ñ\8bÑ\8e Ð²Ñ\8bдаленÑ\8cнÑ\8fÑ\9e Ð³Ñ\8dÑ\82ага Ñ\84айла перад яго паўторнай загрузкай.",
+       "file-deleted-duplicate": "Ð\86дÑ\8dнÑ\82Ñ\8bÑ\87нÑ\8b Ñ\84айл ([[:$1]]) Ñ\83жо Ñ\80аней Ð²Ñ\8bдалÑ\8fÑ\9eÑ\81Ñ\8f. Ð\92ам Ñ\82Ñ\80Ñ\8dба Ð¿Ð°Ð³Ð»Ñ\8fдзеÑ\86Ñ\8c Ð³Ñ\96Ñ\81Ñ\82оÑ\80Ñ\8bÑ\8e Ð²Ñ\8bдаленÑ\8cнÑ\8fÑ\9e Ð³Ñ\8dÑ\82ага Ñ\84айлÑ\83 перад яго паўторнай загрузкай.",
        "file-deleted-duplicate-notitle": "Файл, ідэнтычны гэтаму файлу, раней ужо быў выдалены, а назва файла была забароненая.\nВам трэба зьвярнуцца да некага з правамі прагляду зьвестак забароненых файлаў, каб прааналізаваць сытуацыю перад тым, як загружаць файл ізноў.",
        "uploadwarning": "Папярэджаньне",
        "uploadwarning-text": "Калі ласка, зьмяніце апісаньне файла ніжэй і паспрабуйце ізноў.",
index 2ea950d..ee7435f 100644 (file)
        "confirm-unwatch-top": "Voleu treure aquesta pàgina de la llista de seguiment?",
        "confirm-rollback-button": "D'acord",
        "confirm-rollback-top": "Voleu revertir les modificacions a la pàgina?",
+       "colon-separator": ":&#32;",
        "quotation-marks": "«$1»",
        "imgmultipageprev": "← pàgina anterior",
        "imgmultipagenext": "pàgina següent →",
index 720e420..ec13f39 100644 (file)
        "timezoneregion-indian": "Индин океан",
        "timezoneregion-pacific": "Тийна океан",
        "allowemail": "Магийта декъашхошна хьайга электронан поштехула кехат кхехьийта",
+       "email-allow-new-users-label": "Магийта керла декъашхошна хьайга электронан поштехула кехат кхехьийта",
        "email-blacklist-label": "ХӀокху декъашхошна электронан пошт соьга яийта бехкам-бе:",
        "prefs-searchoptions": "Лахар",
        "prefs-namespaces": "ЦӀерийн меттигаш",
        "credentialsform-provider": "ДӀаяздарийн тайпа:",
        "credentialsform-account": "Декъашхочун цӀе:",
        "userjsispublic": "Тергам бе: JavaScript бухара агӀонаш чохь къайлаха хаамаш хийла ца беза, уьш массо декъашхойн тӀекхочуш йолу дера.",
-       "usercssispublic": "Тергам бе: CSS бухара агӀонаш чохь къайлаха хаамаш хийла ца беза, уьш массо декъашхойн тӀекхочуш йолу дера."
+       "usercssispublic": "Тергам бе: CSS бухара агӀонаш чохь къайлаха хаамаш хийла ца беза, уьш массо декъашхойн тӀекхочуш йолу дера.",
+       "passwordpolicies": "Паролийн политика",
+       "passwordpolicies-summary": "ХӀокху агӀонгахь гойту декъашхойн паролашна болу бехкам. Декъашхойн юкъабогӀуш болу бакъонийн тобанашка хьажжина бу бехкам.",
+       "passwordpolicies-policy-minimalpasswordlength": "Пароль $1 {{PLURAL:$1|символал}} еха хила еза",
+       "passwordpolicies-policy-passwordcannotmatchusername": "Пароль декъашхочун цӀерах тера хила ца еза",
+       "passwordpolicies-policy-passwordcannotmatchblacklist": "Пароль Ӏаьржачу могӀаман юкъахь йолучарех тера хила ца еза",
+       "passwordpolicies-policy-maximalpasswordlength": "Пароль $1 {{PLURAL:$1|символал}} йоца хила ца еза",
+       "passwordpolicies-policy-passwordcannotbepopular": "Пароль дукха {{PLURAL:$1|лелош йолчарех хила ца еза}}"
 }
index 061f7bc..53337d1 100644 (file)
        "rcfilters-view-tags-help-icon-tooltip": "زیاتر بزانە لەسەر دەستکارییە تاگکراوەکان",
        "rcfilters-liveupdates-button": "نوێکردنەوەی زیندوو",
        "rcnotefrom": "ژێرەوە {{PLURAL:$5|گۆڕانکارییەکەیە|گۆڕانکارییەکانە}} لە <strong>$3، $4</strong>ەوە (ھەتا <strong>$1</strong> نیشان دراوە).",
+       "rclistfromreset": "گەڕاندنەوەی ھەڵبژاردەی بەروار",
        "rclistfrom": "گۆڕانکارییە نوێکان نیشان بدە بە دەستپێکردن لە $3 $2",
        "rcshowhideminor": "دەستکارییە بچووکەکان $1",
        "rcshowhideminor-show": "نیشان بدە",
index 67a228e..ca35efc 100644 (file)
        "rcfilters-activefilters-hide": "Peida",
        "rcfilters-activefilters-show": "Näita",
        "rcfilters-activefilters-hide-tooltip": "Peida aktiivsete filtrite ala",
+       "rcfilters-activefilters-show-tooltip": "Kuva aktiivsete filtrite ala",
        "rcfilters-advancedfilters": "Täpsemad filtrid",
        "rcfilters-limit-title": "Näita nii mitut tulemust",
        "rcfilters-limit-and-date-label": "$1 {{PLURAL:$1|muudatus|muudatust}}, $2",
index 2d03e12..b69d49c 100644 (file)
@@ -12,7 +12,8 @@
                        "Macofe",
                        "Matma Rex",
                        "Nemo bis",
-                       "Fitoschido"
+                       "Fitoschido",
+                       "Tacsipacsi"
                ]
        },
        "tog-underline": "Ferwisangen onerstrik:",
        "category_header": "Sidjen uun kategorii \"$1\"",
        "subcategories": "Onerkategoriin",
        "category-media-header": "Meedien uun kategorii \"$1\"",
-       "category-empty": "\"Uun detdiar kategorii san uun uugenblak nian sidjen of meedien.\"",
+       "category-empty": "<em>Uun detdiar kategorii san uun uugenblak nian sidjen of meedien.</em>",
        "hidden-categories": "{{PLURAL:$1|Ferbürgen kategorii|Ferbürgen kategoriin}}",
        "hidden-category-category": "Ferbürgen kategoriin",
        "category-subcat-count": "{{PLURAL:$2|Detdiar kategorii hää ian onerkategorii.|Uun detdiar kategorii {{PLURAL:$1|stäänt ian onerkategorii|stun $1 onerkategoriin}} faan $2 uun't gehial.}}",
index 55eba4d..2eeb713 100644 (file)
        "rcfilters-other-review-tools": "Ostali alati za pregledavanje:",
        "rcfilters-group-results-by-page": "Grupiranje rezultata po stranici",
        "rcfilters-activefilters": "Aktivni filtri",
+       "rcfilters-activefilters-hide": "Skrij",
+       "rcfilters-activefilters-show": "Pokaži",
        "rcfilters-advancedfilters": "Napredni filtri",
        "rcfilters-limit-title": "Rezultata za prikaz",
        "rcfilters-limit-and-date-label": "{{PLURAL:$1|$1 izmjena|$1 izmjene|$1 izmjena}}, $2",
index 6bd9201..9264fbb 100644 (file)
        "rcfilters-activefilters": "Aktív szűrők",
        "rcfilters-activefilters-hide": "Elrejt",
        "rcfilters-activefilters-show": "Mutat",
+       "rcfilters-activefilters-hide-tooltip": "Aktív szűrők dobozának elrejtése",
+       "rcfilters-activefilters-show-tooltip": "Aktív szűrők dobozának megjelenítése",
        "rcfilters-advancedfilters": "Haladó szűrők",
        "rcfilters-limit-title": "Megjelenítendő találatok száma",
        "rcfilters-limit-and-date-label": "$1 változtatás, $2",
index f632abc..5c9ac57 100644 (file)
        "resetpass-submit-loggedin": "Cambiar contrasigno",
        "resetpass-submit-cancel": "Cancellar",
        "resetpass-wrong-oldpass": "Le contrasigno temporari o actual es invalide.\nEs possibile que tu ha ja cambiate tu contrasigno o requestate un nove contrasigno temporari.",
-       "resetpass-recycled": "Redefini tu contrasigno a un differente del actual, per favor.",
+       "resetpass-recycled": "Cambia tu contrasigno a un differente del actual, per favor.",
        "resetpass-temp-emailed": "Tu ha aperite session con un codice temporari que tu recipeva in e-mail.\nPro completar le accesso, tu debe definir un nove contrasigno hic:",
        "resetpass-temp-password": "Contrasigno temporari:",
        "resetpass-abort-generic": "Le cambio del contrasigno ha essite abortate per un extension.",
        "resetpass-expired": "Le contrasigno ha expirate. Per favor defini un nove contrasigno pro aperir session.",
-       "resetpass-expired-soft": "Le contrasigno ha expirate e debe esser redefinite. Per favor elige un nove contrasigno ora, o clicca sur \"{{int:authprovider-resetpass-skip-label}}\" pro redefinir lo plus tarde.",
-       "resetpass-validity-soft": "Le contrasigno non es valide: $1\n\nPer favor elige un nove contrasigno ora, o clicca sur \"{{int:authprovider-resetpass-skip-label}}\" pro redefinir lo plus tarde.",
+       "resetpass-expired-soft": "Le contrasigno ha expirate e debe esser cambiate. Per favor, elige un nove contrasigno ora, o clicca sur \"{{int:authprovider-resetpass-skip-label}}\" pro cambiar lo plus tarde.",
+       "resetpass-validity-soft": "Le contrasigno non es valide: $1\n\nPer favor, elige un nove contrasigno ora, o clicca sur \"{{int:authprovider-resetpass-skip-label}}\" pro cambiar lo plus tarde.",
        "passwordreset": "Reinitialisar contrasigno",
        "passwordreset-text-one": "Completa iste formulario pro reinitialisar tu contrasigno.",
        "passwordreset-text-many": "{{PLURAL:$1|Completa un de iste campos pro reciper un contrasigno temporari in e-mail.}}",
        "converter-manual-rule-error": "Error detegite in le regula manual de conversion de lingua",
        "undo-success": "Le modification pote esser disfacite.\nPer favor controla le comparation infra pro verificar que tu vole facer isto, e postea salveguarda le modificationes infra pro assi disfacer le modification.",
        "undo-failure": "Le modification non poteva esser annullate a causa de conflicto con modificationes intermedie.",
+       "undo-main-slot-only": "Le modification non poteva esser disfacite perque illo implica contento foras del cannellatura principal.",
        "undo-norev": "Impossibile annullar le modification proque illo non existe o esseva delite.",
        "undo-nochange": "Pare que iste modification ha jam essite disfacite.",
        "undo-summary": "Annullava le version $1 per [[Special:Contributions/$2|$2]] ([[User talk:$2|Discussion]] | [[Special:Contributions/$2|{{MediaWiki:Contribslink}}]])",
        "rcfilters-other-review-tools": "Altere instrumentos de revision",
        "rcfilters-group-results-by-page": "Gruppar resultatos per pagina",
        "rcfilters-activefilters": "Filtros active",
+       "rcfilters-activefilters-hide": "Celar",
+       "rcfilters-activefilters-show": "Monstrar",
+       "rcfilters-activefilters-hide-tooltip": "Celar le area de filtros active",
+       "rcfilters-activefilters-show-tooltip": "Monstrar le area de filtros active",
        "rcfilters-advancedfilters": "Filtros avantiate",
        "rcfilters-limit-title": "Resultatos a monstrar",
        "rcfilters-limit-and-date-label": "$1 modification{{PLURAL:$1||es}}, $2",
        "rcfilters-savedqueries-rename": "Renominar",
        "rcfilters-savedqueries-setdefault": "Predefinir",
        "rcfilters-savedqueries-unsetdefault": "Remover predefinition",
-       "rcfilters-savedqueries-remove": "Remover",
+       "rcfilters-savedqueries-remove": "Deler",
        "rcfilters-savedqueries-new-name-label": "Nomine",
        "rcfilters-savedqueries-new-name-placeholder": "Describe le proposito del filtro",
        "rcfilters-savedqueries-apply-label": "Crear filtro",
        "rcfilters-empty-filter": "Nulle filtro active. Tote le contributiones es monstrate.",
        "rcfilters-filterlist-title": "Filtros",
        "rcfilters-filterlist-whatsthis": "Como functiona istes?",
-       "rcfilters-filterlist-feedbacklink": "Da nos tu opinion sur iste (nove) instrumentos de filtrage",
+       "rcfilters-filterlist-feedbacklink": "Da nos tu opinion sur iste instrumentos de filtrage",
        "rcfilters-highlightbutton-title": "Colorar le resultatos",
        "rcfilters-highlightmenu-title": "Selige un color",
        "rcfilters-highlightmenu-help": "Selige un color pro illuminar iste proprietate",
index 004c604..6d5ce82 100644 (file)
        "customcssprotected": "Þú hefur ekki leyfi að breyta þessari CSS-umbrotsíðu, því hún hefur notandastillingar annars notanda.",
        "customjsprotected": "Þú hefur ekki leyfi til að breyta þessari JavaScript síðu, því hún hefur notandastillingar annars notanda.",
        "mycustomcssprotected": "Þú hefur ekki leyfi til þess að breyta þessari CSS-síðu.",
+       "mycustomjsonprotected": "Þú hefur ekki heimild til að breyta þessari JSON-síðu.",
        "mycustomjsprotected": "Þú hefur ekki leyfi til þess að breyta þessari JavaScript-síðu.",
        "myprivateinfoprotected": "Þú ert ekki með réttindi til að breyta einkaupplýsingunum þínum.",
        "mypreferencesprotected": "Þú ert ekki með réttindi til að breyta kjörstillingunum þínum.",
        "wrongpasswordempty": "Lykilorðsreiturinn var auður. Reyndu aftur.",
        "passwordtooshort": "Lykilorð skal vera að minnsta kosti $1 {{PLURAL:$1|stafur|stafir}}.",
        "passwordtoolong": "Lykilorð geta ekki verið lengri en $1 {{PLURAL:$1|stafur|stafir}}.",
-       "passwordtoopopular": "Ekki má nota algeng lykilorð. Veldu eitthvað alveg sérstakt lykilorð.",
+       "passwordtoopopular": "Ekki má nota títt valin lykilorð. Vinsamlegast velja lykilorð sem erfiðara er að giska á.",
        "password-name-match": "Þarf að lykilorð þitt sé öðruvísi notandanafni þínu",
        "password-login-forbidden": "Notkun þessa notandanafns og lykilorðs er ekki leyfileg.",
        "mailmypassword": "Endurstilla lykilorð",
        "botpasswords-existing": "Fyrirliggjandi lykilorð vélmenna",
        "botpasswords-createnew": "Búa til nýtt lykilorð vélmennis",
        "botpasswords-editexisting": "Breyta fyrirliggjandi lykilorði vélmennis",
+       "botpasswords-label-needsreset": "(lykilorð þarf að endurstilla)",
        "botpasswords-label-appid": "Heiti vélmennis:",
        "botpasswords-label-create": "Búa til",
        "botpasswords-label-update": "Uppfæra",
        "savechanges": "Vista breytingar",
        "publishpage": "Gefa út síðu",
        "publishchanges": "Gefa út breytingar",
+       "savearticle-start": "Vista síðu…",
+       "savechanges-start": "Vista breytingar…",
+       "publishpage-start": "Birta síðu...",
        "publishchanges-start": "Gefa út breytingar...",
        "preview": "Forskoða",
        "showpreview": "Forskoða",
        "anoneditwarning": "<strong>Viðvörun:</strong> Þú ert ekki innskráð(ur). Vistfang þitt verður sýnt opinberlega ef þú gerir einhverjar breytingar. Ef þú <strong>[$1 skráir þig inn]</strong> eða <strong>[$2 stofnar aðgang]</strong> munu breytingarnar þínar vera tengdar við notandanafn þitt, ásamt öðrum kostum.",
        "anonpreviewwarning": "<em>Þú ert ekki skráð(ur) inn. Vistfang þitt skráist í breytingaskrá síðunnar.</em>",
        "missingsummary": "'''Áminning:''' Þú hefur ekki skrifað breytingarágrip.\nEf þú smellir á Vista aftur, verður breyting þín vistuð án þess.",
+       "selfredirect": "<strong>Viðvörun:</strong> Þú ert að vísa þessa síðu á sjálfa sig.\nÞað kann að vera að þú hafir valið vitlausa marksíðu fyrir tilvísunina eða að þú sért að breyta vitlausri síðu.\nEf þú smellir aftur á „$1“ verður tilvísunin samt búin til.",
        "missingcommenttext": "Gerðu svo vel og skrifaðu athugasemd.",
        "missingcommentheader": "<strong>Áminning:</strong> Þú hefur ekki gefið upp umræðuefni.\nEf þú smellir á \"$1\" aftur, verður breyting þín vistuð án þess.",
        "summary-preview": "Forskoða breytingarágrip:",
        "subject-preview": "Forskoðun viðfangsefnis:",
        "previewerrortext": "Óvænt villa kom upp þegar reynt var að forskoða breytingarnar þínar.",
        "blockedtitle": "Notandi er bannaður",
-       "blockedtext": "'''Notandanafn þitt eða vistfang hefur verið bannað.'''\n\nBannið var sett af $1.\nÁstæðan er eftirfarandi: ''$2''.\n\n* Bannið hófst: $8\n* Banninu lýkur: $6\n* Sá sem banna átti: $7\n\nÞú getur haft samband við $1 eða annan [[{{MediaWiki:Grouppage-sysop}}|stjórnanda]] til að ræða bannið.\nÞú getur ekki notað „Senda þessum notanda tölvupóst“ aðgerðina nema gilt netfang sé skráð í [[Special:Preferences|kjörstillingum þínum]] og að þér hafi ekki verið óheimilað það.\nNúverandi vistfang þitt er $3, og bannnúmerið er #$5.\nHafðu með allar þessar upplýsingar hér fyrir ofan í fyrirspurnum þínum.",
-       "autoblockedtext": "Vistfang þitt hefur verið sjálfvirkt bannað því það var notað af öðrum notanda, sem var bannaður af $1.\nÁstæðan er eftirfarandi:\n\n:''$2''\n\n* Bannið hófst: $8\n* Banninu lýkur: $6\n* Sá sem banna átti: $7\n\nÞú getur haft samband við $1 eða annan [[{{MediaWiki:Grouppage-sysop}}|stjórnanda]] til að ræða bannið.\n\nAthugaðu að þú getur ekki notað „Senda þessum notanda tölvupóst“ aðgerðina nema gilt netfang sé skráð í [[Special:Preferences|kjörstillingum þínum]] og að þér hafi ekki verið óheimilað það.\n\nNúverandi vistfang þitt er $3, og bannnúmerið er #$5.\nHafðu með allar þessar upplýsingar hér fyrir ofan í fyrirspurnum þínum.",
+       "blockedtext": "<strong>Þitt notandanafn eða vistfang hefur verið bannað.</strong>\n\nBannið var sett af $1.\nÁstæðan er eftirfarandi: <em>$2</em>.\n\n* Bannið hófst: $8\n* Banninu lýkur: $6\n* Sá sem banna átti: $7\n\nÞú getur haft samband við $1 eða annan [[{{MediaWiki:Grouppage-sysop}}|stjórnanda]] til að ræða bannið.\nÞú getur ekki notað „Senda þessum notanda tölvupóst“ aðgerðina nema gilt netfang sé skráð í [[Special:Preferences|kjörstillingum þínum]] og að þér hafi ekki verið óheimilað það.\nNúverandi vistfang þitt er $3, og bannnúmerið er #$5.\nHafðu með allar þessar upplýsingar hér fyrir ofan í fyrirspurnum þínum.",
+       "autoblockedtext": "Vistfang þitt hefur verið sjálfvirkt bannað því það var notað af öðrum notanda, sem var bannaður af $1.\nÁstæðan er eftirfarandi:\n\n:<em>$2</em>\n\n* Bannið hófst: $8\n* Banninu lýkur: $6\n* Sá sem banna átti: $7\n\nÞú getur haft samband við $1 eða annan [[{{MediaWiki:Grouppage-sysop}}|stjórnanda]] til að ræða bannið.\n\nAthugaðu að þú getur ekki notað „Senda þessum notanda tölvupóst“ aðgerðina nema gilt netfang sé skráð í [[Special:Preferences|kjörstillingum þínum]] og að þér hafi ekki verið óheimilað það.\n\nNúverandi vistfang þitt er $3, og bannnúmerið er #$5.\nHafðu með allar þessar upplýsingar hér fyrir ofan í fyrirspurnum þínum.",
        "systemblockedtext": "Notandanafnið þitt eða IP-vistfangið hafa verið útilokuð sjálfvirkt af MediaWiki.\nUppgefin ástæða er:\n\n:<em>$2</em>\n\n* Upphaf útilokunar: $8\n* Útilokun rennur út: $6\n* Sá sem átti að útiloka: $7\n\nNúverandi IP-vistfang þitt er$3.\nHafðu allar þessar upplýsingar með í öllum þeim fyrirspurnum sem þú gætir gert vegna þessa.",
        "blockednoreason": "engin ástæða gefin",
        "whitelistedittext": "Þú þarft að $1 þig til að breyta síðum.",
        "blocked-notice-logextract": "Þessi notandi er í banni.\nSíðasta færsla notandans úr bannskrá er birt hér fyrir neðan til skýringar:",
        "clearyourcache": "<strong>Athugaðu:</strong> Eftir vistun kann að vera að þú þurfir að komast hjá skyndiminni vafrans þíns til að sjá breytingarnar.\n* <strong>Firefox / Safari:</strong> Haltu <em>Shift</em> samtímis og þú smellir á <em>Endurhlaða (Reload)</em>, eða ýttu á annaðhvort <em>Ctrl-F5</em> eða <em>Ctrl-R</em> (<em>⌘-R</em> á Mac)\n* <strong>Google Chrome:</strong> Ýttu á <em>Ctrl-Shift-R </em>(<em>⌘-Shift-R</em> á Mac)\n* <strong>Internet Explorer:</strong> Haltu <em>Ctrl</em> samtímis og þú smellir á <em>Endurnýja (Refresh)</em>, eða ýttu á <em>Ctrl-F5</em>\n* <strong>Opera:</strong> Farðu í <em>Verkfæri (Tools) → Stillingar (Preferences)</em> og svo <em>Friðhelgi og öryggi (Privacy & security) → Hreinsa vafragögn (Clear browsing data) → Myndir og skrár í skyndiminni (Chached images and files)</em>",
        "usercssyoucanpreview": "'''Ath:''' Hægt er að nota „{{int:showpreview}}“ hnappinn til að prófa CSS-kóða áður en hann er vistaður.",
+       "userjsonyoucanpreview": "<strong>Ath.:</strong> Hægt er að nota hnappinn „{{int:showpreview}}“ til að prófa JSON-kóða áður en hann er vistaður.",
        "userjsyoucanpreview": "'''Ath:''' Hægt er að nota \"{{int:showpreview}}\" hnappinn til að prófa JavaScript-kóða áður en hann er vistaður.",
        "usercsspreview": "'''Mundu að þú ert aðeins að forskoða CSS-kóðann þinn.'''\n'''Hann hefur ekki enn verið vistaður!'''",
        "userjspreview": "'''Mundu að þú ert aðeins að prófa/forskoða JavaScript-kóðann þinn.'''\n'''Hann hefur ekki enn verið vistaður!'''",
        "apisandbox-dynamic-parameters-add-label": "Bæta við viðfangi:",
        "apisandbox-dynamic-parameters-add-placeholder": "Heiti viðfangs",
        "apisandbox-deprecated-parameters": "Úrelt viðföng",
+       "apisandbox-add-multi": "Bæta við",
        "apisandbox-submit-invalid-fields-title": "Sumir reitir eru ógildir",
        "apisandbox-results": "Niðurstöður",
+       "apisandbox-sending-request": "Sendir API-beiðni...",
        "apisandbox-request-url-label": "Slóð á beiðni:",
        "apisandbox-request-format-json-label": "JSON",
        "apisandbox-request-json-label": "JSON beiðni:",
        "revertpage": "Tók aftur breytingar [[Special:Contributions/$2|$2]] ([[User talk:$2|spjall]]), breytt til síðustu útgáfu [[User:$1|$1]]",
        "revertpage-nouser": "Tók aftur breytingar falins notanda til síðustu útgáfu {{GENDER:$1|[[User:$1|$1]]}}",
        "rollback-success": "Tók til baka breytingar eftir {{GENDER:$3|$1}};\nsetti yfir á síðustu útgáfu eftir {{GENDER:$4|$2}}.",
+       "rollback-success-notify": "Tók aftur breytingar $1;\nbreytti í síðustu útgafu $2. [$3 Sýna breytingar]",
        "sessionfailure-title": "Mistök í setu",
        "sessionfailure": "Líklega er vandamál með innskráningarsetuna þína;\nhætt hefur verið við þessa aðgerð sem vörn gegn mögulegu samskiptaráni setunar.\nReyndu að senda upplýsingarnar aftur inn.",
+       "changecontentmodel": "Breyta efnislíkani síðu",
+       "changecontentmodel-legend": "Breyta efnislíkani",
        "changecontentmodel-title-label": "Titill síðu",
+       "changecontentmodel-model-label": "Nýtt efnislíkan",
        "changecontentmodel-reason-label": "Ástæða:",
        "changecontentmodel-submit": "Breyta",
+       "changecontentmodel-success-title": "Efnislíkaninu var breytt",
        "logentry-contentmodel-change-revertlink": "taka aftur",
        "logentry-contentmodel-change-revert": "taka aftur",
        "protectlogpage": "Verndunarskrá",
        "unblocked-id": "Bann $1 hefur verið fjarlægt",
        "unblocked-ip": "[[Special:Contributions/$1|$1]] hefur verið afbannaður.",
        "blocklist": "Bannaðir notendur og vistföng",
+       "autoblocklist": "Sjálfvirk bönn",
        "autoblocklist-submit": "Leita",
+       "autoblocklist-legend": "Sýna sjálfvirk bönn",
+       "autoblocklist-total-autoblocks": "Samanlagður fjöldi sjálfvirkra banna: $1",
+       "autoblocklist-empty": "Listinn yfir sjálfvirk bönn er tómur.",
+       "autoblocklist-otherblocks": "{{PLURAL:$1|Annað sjálfvirkt bann|Önnur sjálfvirk bönn}}",
        "ipblocklist": "Bannaðir notendur og vistföng",
        "ipblocklist-legend": "Finna bannaðan notanda",
        "blocklist-userblocks": "Fela notendabönn",
        "tooltip-ca-nstab-help": "Sýna hjálparsíðuna",
        "tooltip-ca-nstab-category": "Sýna efnisflokkasíðuna",
        "tooltip-minoredit": "Merkja þessa breytingu sem minniháttar",
-       "tooltip-save": "Vista breytingarnar",
-       "tooltip-publish": "Gefa út breytingarnar þínar",
+       "tooltip-save": "Vista breytingar þínar",
+       "tooltip-publish": "Gefa út breytingar þínar",
        "tooltip-preview": "Forskoða breytingarnar þínar. Gerðu þetta áður en þú vistar.",
        "tooltip-diff": "Sýna hvaða breytingar þú gerðir á textanum.",
        "tooltip-compareselectedversions": "Sjá breytingarnar á þessari grein á milli útgáfanna sem þú valdir.",
        "version-specialpages": "Kerfissíður",
        "version-parserhooks": "Tengikrókar þáttara (parser hooks)",
        "version-variables": "Breytur",
+       "version-editors": "Ritstjórar",
        "version-antispam": "Varnir gegn amasendingum",
        "version-api": "API",
        "version-other": "Aðrar",
        "tag-mw-new-redirect": "Ný endurbeining",
        "tag-mw-removed-redirect": "Fjarlægði endurbeiningu",
        "tag-mw-replace": "Skipt út",
+       "tag-mw-rollback": "Afturköllun",
        "tag-mw-undo": "Afturkalla",
        "tags-title": "Merki",
        "tags-intro": "Þessi síða sýnir merkin sem hugbúnaðurinn gæti merkt breytingar með, og hvað þau þýða.",
index 6337ea4..95adaf8 100644 (file)
        "cascadeprotected": "Ankehitriny dia voaaro ity pejy ity satria misy pejy voaaro {{PLURAL:$1|iray|$1}} mampiasa ity pejy ity. Io pejy io dia mampiasa ny fiarovana \"mirihana\":\n\n$2",
        "namespaceprotected": "Tsy manana alalàna manova ny toeran'anarana « '''$1''' » ianao.",
        "customcssprotected": "Tsy afaka manova ity pejy CSS ity ianao satria misy ny safidy manokan'ny mpikambana hafa.",
+       "customjsonprotected": "Tsy manana alalalana manova ity pejy JSON ity ianao satria misy ny safidin'olon-kafa izy ity.",
        "customjsprotected": "Tsy afaka manova ity pejy JavaScript ity inaao satria misy ny safidin'ny mpikambana hafa.",
        "mycustomcssprotected": "Tsy manana ny alalana ahafahana manova ity pejy CSS ity ianao.",
+       "mycustomjsonprotected": "Tsy manana alalana manova ity pejy JSON ity ianao.",
        "mycustomjsprotected": "Tsy manana ny alalana ahafahana manova ity pejy JavaScript ity ianao.",
        "myprivateinfoprotected": "Tsy manana alalana ahafahana manova ny fampahalalana tsy sarababem-bahoakanao ianao.",
        "mypreferencesprotected": "Tsy manana alalana ahafahana manova ny safidinao ianao.",
        "changepassword-success": "Voaova soa aman-tsara ny tenimiafinao!",
        "changepassword-throttled": "Betsaka loatra ny andram-pidirana nataonao.\nAndraso $1 aloha ny mamerina.",
        "botpasswords": "Tenimiafin-drôbô",
+       "botpasswords-summary": "Ny <em>Tenimiafina rôbô</em> dia manome alalana ny mampiasa ny kaontim-pikambana iray amin'ny alalana API ka tsy mila mampiasa ny tenimiafin'ny mpikambana. Ny zom-pikambana ananana rehefa tafiditra amin'ny alalana tenimiafina rôbô dia mety ho voafetra.\n\nRaha tsy fantatrao ny antony hanaovanao izany dia tsy tokony hanao izany ianao. Tsy tokony hisy ny olona hangataka anao hamoaka iray amin'itony ary hanome azy.",
        "botpasswords-disabled": "Tsy ampiasaina ny tenimiafin-drôbô.",
+       "botpasswords-no-central-id": "Raha hampiasa tenimiafina rôbô dia tsy maintsy tafiditra anaty kaonty iombonan-tsehatra ianao.",
        "botpasswords-existing": "Tenimiafin-drôbô efa misy",
        "botpasswords-createnew": "Hamorona tenimiafina rôbô vaovao",
        "botpasswords-editexisting": "Hanova tenimiafina rôbô efa misy",
+       "botpasswords-label-needsreset": "(mila famerenana ny tenimiafina)",
        "botpasswords-label-appid": "Anarana rôbô:",
        "botpasswords-label-create": "Foronina",
        "botpasswords-label-update": "Vaozina",
        "savechanges": "Hitahiry ny fiovana",
        "publishpage": "Hamoaka pejy",
        "publishchanges": "Hamoaka ny fiovana",
+       "savearticle-start": "Hitahiry pejy...",
+       "savechanges-start": "Mitahiry ny fiovana...",
+       "publishpage-start": "Hamoaka ny pejy...",
+       "publishchanges-start": "Hamoaka ny fiovana...",
        "preview": "Topi-maso",
        "showpreview": "Asehoy aloha",
        "showdiff": "Asehoy ny fiovana",
        "anoneditwarning": "<strong>Fampitandremana :</strong> Tsy niditra tamin'ny kaontinao ianao. Ho hitan'ny vahoaka ny adiresy IP-nao raha manova inona na inona ianao. Raha <strong>[$1 miditra amin'ny kaontinao]</strong> ianao dia ho anisan'ny tombontsoa anananao ny fanaovana ny fiovana amin'ny solonanaranao.",
        "anonpreviewwarning": "''Tsy niditra ianao. Hampitahiry ny adiresy IP anao ao amin'ny tantaram-panovan'ity pejy ity ny fitehirizana ny fanovana.''",
        "missingsummary": "'''Hafatra fampantsiahivana''' : tsy mbola nanome ny ambangovangom-panovanao ianao.\nRaha mbola tsindriano fanindroany eo amin'ny bokotra $1, ho voatahiry tsy fanambarana ny fanovanao.",
-       "missingcommenttext": "Ampidiro ny ambangovangony azafady.",
+       "missingcommenttext": "Mampidira ambangovangony azafady.",
        "missingcommentheader": "<strong>Fampatsiahivana: </strong> Tsy nampiditra lohahevitra ho an'ity hafatra ity ianao. Raha tsindrianao fanindroany \"$1\" dia ho tehirizina tsy misy lohahevitra ny hafatrao.",
        "summary-preview": "Topi-mason'ny ambangovangom-panovana :",
        "subject-preview": "Topi-mason-dohahevitra:",
index 4706467..d2860c2 100644 (file)
        "badtitletext": "The requested page title was invalid, empty, or an incorrectly linked inter-language or inter-wiki title.\nIt may contain one or more characters that cannot be used in titles.",
        "title-invalid-empty": "The requested page title is empty or contains only the name of a namespace.",
        "title-invalid-utf8": "The requested page title contains an invalid UTF-8 sequence.",
+       "title-invalid-interwiki": "ꯍꯪꯒꯠꯆꯔꯤꯕꯥ ꯂꯥꯃꯥꯏꯁꯤꯒꯤ ꯃꯃꯤꯡ ꯁꯤ ꯋꯤꯀꯤ ꯒꯥ ꯃꯔꯤ ꯂꯩꯅꯕꯥ ꯁꯝꯅꯐꯝ ꯌꯥꯑꯣ ꯏ ꯃꯗꯨꯗꯤ ꯃꯃꯤꯡ ꯑꯣꯏꯅꯥ ꯁꯤꯖꯤꯟꯅꯕꯥ ꯌꯥꯗꯕꯥ",
        "viewsource": "ꯍꯧꯔꯛꯐꯝ ꯎꯨꯇꯂꯨ",
        "viewsource-title": "$1 ꯒꯤ ꯍꯧꯔꯛꯐꯝ ꯎꯨꯠꯂꯨ",
        "viewsourcetext": "ꯅꯪꯅꯥ ꯌꯦꯡꯕꯥ ꯌꯥꯒꯅꯤ ꯑꯃꯗꯤ ꯃꯁꯤꯒꯤ ꯂꯥꯃꯥꯏꯁꯤꯒꯤ ꯍꯧꯔꯛꯐꯝ ꯁꯤꯟꯇꯣꯛ ꯎ",
+       "mycustomjsonprotected": "ꯅꯪꯅꯥ ꯃꯁꯤ json ꯂꯥꯃꯥꯏꯁꯤ ꯁꯦꯝꯒꯠꯅꯕꯥ ꯑꯌꯥꯕꯥ ꯄꯤꯗꯦ",
+       "mycustomjsprotected": "JavaScript ꯂꯥꯃꯥꯏꯁꯤ ꯅꯪꯅꯥ ꯁꯦꯝꯒꯠꯅꯕꯒꯤ ꯑꯌꯥꯕꯥ ꯄꯤꯗꯦ",
+       "myprivateinfoprotected": "ꯅꯪꯅꯥ ꯅꯪꯒꯤ ꯑꯔꯣꯟꯕꯥ ꯑꯀꯨꯞꯄ ꯋꯥꯔꯣꯜ ꯂꯧꯐꯝ ꯁꯤ ꯁꯦꯝꯒꯠꯅꯕꯒꯤ ꯑꯌꯥꯕꯥ ꯄꯤꯗꯦ",
+       "mypreferencesprotected": "ꯅꯪꯅꯥ ꯅꯪꯒꯤ ꯄꯔꯤꯐꯔꯦꯟꯁ ꯁꯤ ꯁꯦꯝꯒꯠꯅꯕꯒꯤ ꯑꯌꯥꯕꯥ ꯄꯤꯗꯦ",
+       "ns-specialprotected": "ꯑꯈꯟꯅꯕꯥ ꯂꯥꯃꯥꯏꯅꯤ ꯁꯦꯝꯗꯣꯛꯄꯥ ꯌꯥꯗꯦ",
+       "titleprotected": "ꯃꯁꯤꯒꯤ ꯃꯃꯤꯡ ꯁꯤ ꯉꯥꯛꯊꯣꯛꯂꯦ ꯁꯥꯒꯠꯂꯛꯄꯗꯥ [[User:$1|$1]].\nThe reason given is <em>$2</em>.",
+       "filereadonlyerror": "Unable to modify the file \"$1\" because the file repository \"$2\" is in read-only mode.\n\nThe system administrator who locked it offered this explanation: \"$3\".",
+       "invalidtitle-knownnamespace": "Invalid title with namespace \"$2\" and text \"$3\"",
+       "invalidtitle-unknownnamespace": "Invalid title with unknown namespace number $1 and text \"$2\"",
+       "exception-nologin": "ꯂꯦꯒ ꯏꯟ ꯇꯧꯗꯦ",
+       "exception-nologin-text": "ꯆꯥꯟꯕꯤꯗꯨꯅꯥ ꯂꯣꯒ ꯏꯟ ꯇꯧꯁꯤꯟꯂꯨ ꯃꯁꯤꯒꯤ ꯂꯥꯃꯥꯏꯁꯤꯗꯥ ꯆꯪꯁꯤꯟꯅꯕꯥ ꯅꯠꯇꯔꯒꯥ ꯃꯊꯧ ꯄꯥꯡꯊꯣꯛꯅꯕꯥ",
+       "exception-nologin-text-manual": "Please $1 to be able to access this page or action.",
+       "virus-badscanner": "ꯑꯐꯠꯇꯕꯥ ꯀꯟꯐꯤꯒꯨꯔꯦꯁꯟ: Unknown virus scanner: <em>$1</em>",
+       "virus-scanfailed": "ꯁꯦꯡꯗꯣꯛꯄꯥ ꯃꯥꯏꯄꯥꯛꯇꯔꯦ (code $1)",
+       "virus-unknownscanner": "ꯁꯛꯈꯪꯗꯕꯥ ꯑꯦꯟꯇꯤ ꯕꯥꯏꯔꯨꯁ",
+       "logouttext": "<strong>You are now logged out.</strong>\n\nNote that some pages may continue to be displayed as if you were still logged in, until you clear your browser cache.",
+       "cannotlogoutnow-title": "ꯍꯧꯖꯤꯛ ꯂꯣꯒ out ꯇꯧꯕꯥ ꯌꯥꯗꯦ",
+       "cannotlogoutnow-text": "$1 ꯁꯤꯖꯤꯟꯅꯔꯤꯉꯩꯗꯥ ꯂꯣꯒꯒꯤꯡ out ꯁꯤ ꯑꯣꯏꯊꯣꯛꯇꯦ",
+       "welcomeuser": "$1ꯂꯦꯡꯁꯤꯟꯕꯤꯔꯛꯁꯤ",
+       "welcomecreation-msg": "ꯅꯪꯒꯤ ꯑꯦꯀꯥꯎꯟꯇ ꯁꯤ ꯁꯥꯈꯔꯦ\nꯅꯪꯒꯤ ꯑꯄꯥꯝꯕꯒꯤ ꯃꯇꯨꯡ ꯏꯟꯅꯥ ꯍꯣꯡꯗꯣꯛꯄꯥ ꯌꯥꯔꯦ ꯅꯪꯅꯥ {{SITENAME}} [[Special:Preferences|preferences]] ꯅꯪꯒꯤ ꯑꯄꯥꯝꯕꯒꯤ ꯃꯇꯨꯡꯏꯟꯅꯥ.",
+       "yourname": "ꯁꯤꯖꯤꯟꯅꯔꯤꯕꯥ ꯃꯃꯤꯡ",
        "userlogin-yourname": "Username",
        "userlogin-yourname-ph": "Enter your username",
+       "createacct-another-username-ph": "ꯁꯤꯖꯤꯟꯅꯔꯤꯕꯥ ꯃꯃꯤꯡ ꯗꯨ ꯏꯁꯤꯟꯂꯣ",
+       "yourpassword": "ꯆꯪꯁꯤꯟꯅꯕꯥ ꯋꯥꯍꯩ",
        "userlogin-yourpassword": "ꯆꯪꯁꯤꯟꯅꯕꯥ ꯋꯥꯍꯩ",
        "userlogin-yourpassword-ph": "ꯄꯥꯁꯋ꯭ꯇ ꯏꯔꯛ ꯎ",
        "createacct-yourpassword-ph": "ꯄꯥꯁꯋ꯭ꯇ ꯏꯔꯛ ꯎ",
+       "yourpasswordagain": "ꯑꯃꯨꯛꯍꯟꯅꯥ ꯄꯥꯁꯋꯔꯇ ꯅꯝꯃꯨ",
        "createacct-yourpasswordagain": "Confirm password",
        "createacct-yourpasswordagain-ph": "ꯑꯃꯨꯛ ꯍꯟꯅꯥ ꯄꯥꯁꯋ꯭ꯇ ꯏꯌꯨ",
        "userlogin-remembermypassword": "ꯑꯩꯕꯨ ꯑꯗꯨꯝ ꯂꯣꯒ ꯏꯟ ꯇꯧꯍꯟꯂꯨ",
+       "userlogin-signwithsecure": "ꯁꯣꯏꯔꯣꯏꯗꯕꯥ ꯁꯝꯅꯕꯥ  ꯁꯤꯖꯤꯟ ꯅꯧ",
+       "cannotlogin-title": "ꯂꯣꯒ ꯏꯟ ꯌꯥꯗꯦ",
+       "cannotlogin-text": "ꯂꯣꯒ ꯏꯟ ꯁꯤ ꯑꯣꯏꯊꯣꯛꯇꯦ",
+       "cannotloginnow-title": "ꯍꯧꯖꯤꯛ ꯂꯣꯒ ꯏꯟ ꯇꯧꯕꯥ ꯌꯥꯗꯦ",
+       "cannotloginnow-text": "$1 ꯁꯤꯖꯤꯟꯅꯔꯤꯉꯩꯗꯥ ꯂꯣꯒꯒꯤꯡ ꯏꯟ ꯁꯤ ꯑꯣꯏꯊꯣꯛꯇꯦ",
+       "cannotcreateaccount-title": "ꯑꯦꯀꯥꯎꯟ ꯁꯥꯕꯥ ꯌꯥꯗꯦ",
+       "cannotcreateaccount-text": "ꯍꯦꯛꯇꯥ ꯑꯣꯀꯥꯎꯅ ꯁꯥꯕꯥ ꯁꯤ ꯃꯁꯤꯒꯤ ꯋꯤꯀꯤ ꯁꯤ ꯗ ꯌꯥꯍꯟꯗꯦ",
+       "yourdomainname": "ꯅꯪꯒꯤ ꯗꯣꯃꯦꯟ",
+       "password-change-forbidden": "ꯅꯪꯅꯥ ꯃꯁꯤꯒꯤ ꯋꯤꯀꯤ ꯁꯤꯗꯥ ꯄꯥꯁꯋꯔꯇ ꯍꯣꯡꯕꯥ ꯌꯥꯔꯣꯏ",
+       "externaldberror": "There was either an authentication database error or you are not allowed to update your external account.",
        "login": "Chang Sinba",
+       "login-security": "ꯅꯪꯒꯤ ꯁꯛꯑꯣꯡ ꯈꯟꯗꯣꯛꯄꯥ",
+       "nav-login-createaccount": "ꯂꯣꯒ ꯏꯟ/ꯑꯦꯀꯥꯎꯟ ꯁꯥꯕꯥ",
        "logout": "Log out",
        "userlogout": "ꯂꯣꯒ ꯑꯧꯇ",
+       "notloggedin": "ꯂꯦꯒ ꯏꯟ ꯇꯧꯗꯦ",
        "userlogin-noaccount": "ꯑꯦꯀꯥꯎꯟ ꯂꯩꯇꯕꯔꯥ",
        "userlogin-joinproject": "ꯌꯥꯎꯕꯥ {{ꯃꯃꯤꯡ ꯏꯐꯝ}}",
        "createaccount": "ꯑꯩꯒꯤ ꯑꯣꯏꯕꯥ ꯑꯃꯥ ꯁꯦꯝꯕꯥ",
        "userlogin-resetpassword-link": "ꯄꯥꯁꯋꯔꯇ ꯀꯥꯎꯈꯔꯕꯥ",
        "userlogin-helplink2": "ꯂꯣꯒꯒꯤꯡ ꯇꯧꯗꯨꯅꯥ ꯃꯇꯦꯡ ꯄꯥꯡ ꯎ",
+       "userlogin-loggedin": "You are already logged in as {{GENDER:$1|$1}}.\nUse the form below to log in as another user.",
+       "userlogin-reauth": "You must log in again to verify that you are {{GENDER:$1|$1}}.",
+       "userlogin-createanother": "ꯅꯪꯒꯤ ꯑꯇꯣꯞꯄꯥ ꯑꯦꯀꯥꯎꯟꯇ ꯁꯦꯝꯕꯥ",
+       "createacct-emailrequired": "ꯏꯃꯦꯜ ꯂꯥꯐꯝ",
        "createacct-emailoptional": "Email address (ꯑꯇꯣꯞꯄꯥ ꯱)",
        "createacct-email-ph": "Enter your email address",
+       "createacct-another-email-ph": "Enter your email address",
+       "createaccountmail": "Use a temporary random password and send it to the specified email address",
+       "createaccountmail-help": "ꯄꯥꯁꯋꯔꯇ ꯈꯪꯗꯅꯥ ꯑꯇꯣꯞꯄꯒꯤ ꯑꯦꯀꯥꯎꯟ ꯁꯥꯕꯗꯥ ꯁꯤꯖꯤꯟꯅꯕꯥ ꯌꯥꯏ",
+       "createacct-realname": "ꯑꯆꯨꯝꯕꯥ ꯃꯃꯤꯡ(ꯑꯇꯣꯞꯄꯥ ꯱)",
        "createacct-reason": "ꯃꯔꯝ",
+       "createacct-reason-ph": "ꯅꯪꯅꯥ ꯀꯔꯤꯒꯤ ꯑꯇꯣꯞꯄꯥ ꯑꯦꯀꯥꯎꯟ ꯁꯥꯔꯤꯅꯣ",
+       "createacct-reason-help": "ꯄꯥꯎꯖꯦꯜꯁꯤ ꯑꯦꯀꯥꯎꯟ ꯁꯦꯝꯕꯥ ꯂꯣꯒ ꯇꯥ ꯎꯨꯠꯂꯦ",
        "createacct-submit": "ꯅꯪꯒꯤ ꯑꯦꯀꯥꯎꯟꯇ ꯁꯦꯝꯕꯥ",
+       "createacct-another-submit": "ꯑꯩꯒꯤ ꯑꯣꯏꯕꯥ ꯑꯃꯥ ꯁꯦꯝꯕꯥ",
+       "createacct-continue-submit": "ꯃꯈꯥ ꯆꯠꯊꯧ ꯑꯦꯀꯥꯎꯟ ꯁꯦꯝꯕꯗꯨ",
+       "createacct-another-continue-submit": "ꯃꯈꯥ ꯆꯠꯊꯧ ꯑꯦꯀꯥꯎꯟ ꯁꯦꯝꯕꯗꯨ",
        "createacct-benefit-heading": "{{SITENAME}} ꯁꯤ ꯅꯪꯒꯥ ꯃꯥꯟꯅꯕꯥ ꯃꯤꯑꯣꯏꯁꯤꯡꯅꯥ ꯁꯦꯝꯕꯅꯤ",
        "createacct-benefit-body1": "{{PLURAL:$1|edit|edits}}",
        "createacct-benefit-body2": "{{PLURAL:$1|page|pages}}",
        "createacct-benefit-body3": "ꯍꯧꯖꯤꯛꯀꯤ {{PLURAL:$1|contributor|contributors}}",
+       "badretype": "ꯅꯪꯅꯥ ꯏꯔꯤꯕꯥ ꯄꯥꯡꯋꯔꯇ ꯁꯤ ꯆꯥꯟꯅꯗꯔꯦ",
+       "usernameinprogress": "ꯉꯍꯥꯛꯇꯪ ꯉꯥꯏꯕꯤꯈꯣ ꯃꯁꯤꯒꯤ ꯁꯤꯖꯤꯟꯅꯔꯤꯕꯥ ꯃꯃꯤꯡ ꯁꯤ ꯒꯤ ꯑꯦꯀꯥꯎꯟ ꯁꯦꯝꯕꯗꯥ ꯈꯨꯃꯥꯡ ꯆꯥꯎꯁꯤꯟꯂꯦ",
+       "createacct-error": "ꯑꯀꯥꯎꯟ ꯁꯦꯝꯕꯗꯥ ꯑꯁꯣꯏꯕꯥ ꯂꯩꯔꯦ",
+       "createaccounterror": "$1 ꯑꯦꯀꯥꯎꯟ ꯁꯥꯕꯥ ꯌꯥꯗꯔꯦ",
+       "nocookiesnew": "The user account was created, but you are not logged in.\n{{SITENAME}} uses cookies to log in users.\nYou have cookies disabled.\nPlease enable them, then log in with your new username and password.",
+       "nocookieslogin": "{{SITENAME}} uses cookies to log in users.\nYou have cookies disabled.\nPlease enable them and try again.",
+       "loginsuccesstitle": "ꯂꯣꯒ ꯏꯟ",
+       "login-userblocked": "ꯃꯁꯤꯒꯤ ꯁꯤꯖꯤꯟꯅꯔꯤꯕꯥꯁꯤ ꯊꯤꯡꯖꯤꯟꯈꯔꯦ? ꯂꯣꯒ ꯏꯟ ꯌꯥꯔꯥꯔꯣꯏ",
+       "passwordtooshort": "ꯄꯥꯁꯋꯔꯇ ꯁꯤ ꯌꯥꯝꯗꯔꯕꯗꯥ ꯃꯁꯤ ꯈꯔꯥꯁꯤ ꯌꯥꯎꯒꯗꯕꯅꯤ {{PLURAL:$1|1 character|$1 characters}}.",
+       "mailmypassword": "ꯄꯥꯁꯋ꯭ꯇ ꯁꯦꯝꯗꯣꯛꯄꯥ",
+       "passwordremindertitle": " {{SITENAME}} ꯁꯤꯒꯤ ꯑꯅꯧꯕꯥ ꯉꯥꯏꯍꯥꯛꯀꯤ ꯑꯣꯏꯕꯥ ꯄꯥꯁꯋꯔꯇ",
+       "passwordremindertext": "Someone (from IP address $1) requested a new\npassword for {{SITENAME}} ($4). A temporary password for user\n\"$2\" has been created and was set to \"$3\". If this was your\nintent, you will need to log in and choose a new password now.\nYour temporary password will expire in {{PLURAL:$5|one day|$5 days}}.\n\nIf someone else made this request, or if you have remembered your password,\nand you no longer wish to change it, you may ignore this message and\ncontinue using your old password.",
+       "emailconfirmlink": "ꯅꯪꯒꯤ ꯏꯃꯦꯜ ꯑꯦꯗꯔꯦꯁ ꯌꯥꯕꯔꯥ ꯌꯦꯡ ꯎ",
+       "accountcreated": "ꯑꯦꯀꯥꯎꯟ ꯁꯥꯈꯔꯦ",
        "loginlanguagelabel": "$1 ꯂꯣꯟ",
        "pt-login": "Chang Sinba",
        "pt-login-button": "Chang Sinba",
+       "pt-login-continue-button": "ꯂꯣꯘ ꯏꯟ ꯃꯈꯥ ꯆꯠꯊꯧ",
        "pt-createaccount": "ꯑꯩꯒꯤ ꯑꯣꯏꯕꯥ ꯑꯃꯥ ꯁꯦꯝꯕꯥ",
        "pt-userlogout": "Log out",
+       "changepassword": "ꯄꯥꯁꯋ꯭ꯔꯇ ꯍꯣꯡꯗꯣꯛꯄꯥ",
+       "oldpassword": "ꯑꯔꯤꯕꯥ ꯄꯥꯁꯋꯔꯇ",
+       "newpassword": "ꯑꯅꯧꯕꯥ ꯄꯥꯁꯋꯔꯇ",
+       "retypenew": "ꯑꯃꯨꯛꯍꯟꯅꯥ ꯑꯅꯧꯕꯥ  ꯄꯥꯁꯋꯔꯇ ꯅꯝꯃꯨ",
+       "resetpass_submit": "ꯄꯥꯁꯋꯔꯇ ꯁꯦꯝꯃꯨ ꯱ꯗꯤ ꯂꯣꯒ ꯏꯟ",
+       "changepassword-success": "ꯅꯪꯒꯤ ꯄꯥꯁꯋꯔꯇ ꯁꯤ ꯍꯣꯡꯗꯣꯛꯈꯔꯦ",
+       "changepassword-throttled": "You have made too many recent login attempts.\nPlease wait $1 before trying again.",
+       "botpasswords": "ꯕꯣꯇ ꯄꯥꯁꯋꯔꯇ",
+       "botpasswords-summary": "<em>Bot passwords</em> allow access to a user account via the API without using the account's main login credentials. The user rights available when logged in with a bot password may be restricted.\n\nIf you don't know why you might want to do this, you should probably not do it. No one should ever ask you to generate one of these and give it to them.",
+       "botpasswords-disabled": "ꯕꯣꯇ ꯄꯥꯁꯋꯔꯇ ꯌꯥꯉꯟꯗꯕꯥ",
+       "botpasswords-label-create": "ꯁꯥꯕꯥ",
+       "botpasswords-label-update": "ꯅꯧꯊꯣꯛꯍꯟꯕꯥ",
+       "botpasswords-label-cancel": "ꯀꯛꯊꯠꯄꯥ",
+       "botpasswords-label-delete": "ꯃꯥꯡꯍꯟꯕꯥ",
+       "botpasswords-label-resetpassword": "ꯄꯥꯁꯋ꯭ꯇ ꯑꯃꯨꯛ ꯍꯟꯅꯥ ꯁꯦꯝꯗꯣꯛꯄꯥ",
+       "botpasswords-label-grants": "ꯆꯥꯟꯅꯕꯥ ꯌꯥꯕꯥ ꯑꯌꯥꯕ",
+       "botpasswords-help-grants": "Grants allow access to rights already held by your user account. Enabling a grant here does not provide access to any rights that your user account would not otherwise have. See the [[Special:ListGrants|table of grants]] for more information.",
+       "botpasswords-created-title": "ꯕꯣꯠ ꯄꯥꯁꯋ꯭ꯔꯇ ꯁꯥꯈꯔꯦ",
+       "botpasswords-deleted-title": "ꯕꯣꯠ ꯄꯥꯁꯋ꯭ꯔꯇ ꯀꯛꯊꯠꯈꯔꯦ",
+       "resetpass_forbidden": "ꯄꯥꯁꯋ꯭ꯔꯇ ꯍꯣꯡꯗꯣꯧꯄꯥ ꯌꯥꯔꯣꯏ",
+       "resetpass_forbidden-reason": "$1 ꯄꯥꯁꯋ꯭ꯔꯇ ꯍꯣꯡꯗꯣꯧꯄꯥ ꯌꯥꯔꯣꯏ",
+       "resetpass-no-info": "ꯃꯁꯤꯒꯤ ꯂꯥꯃꯥꯏꯁꯤ ꯍꯦꯧꯇꯥ ꯌꯧꯅꯕꯥ ꯅꯪ ꯁꯣꯏꯗꯅꯥ ꯂꯣꯒ ꯏꯟ ꯇꯧꯒꯗꯕꯅꯤ",
+       "resetpass-submit-loggedin": "ꯄꯥꯁꯋ꯭ꯔꯇ ꯍꯣꯡꯗꯣꯛꯄꯥ",
+       "resetpass-submit-cancel": "ꯀꯛꯊꯠꯄꯥ",
+       "resetpass-wrong-oldpass": "ꯃꯇꯝ ꯈꯔꯥꯒꯤ ꯑꯣꯏꯅꯥ ꯀꯔꯤꯝꯇꯥ ꯌꯥꯎꯗꯦ  ꯅꯠꯇꯔꯒꯥ ꯍꯧꯖꯤꯧꯀꯤ ꯄꯥꯁꯋ꯭ꯔꯇ꯫\nꯅꯪꯅꯥ ꯄꯥꯁꯋꯑꯔꯇ ꯍꯥꯟꯅꯗꯒꯤ ꯍꯣꯡꯂꯝꯂꯅꯤ ꯅꯠꯇꯔꯒꯥ ꯍꯪꯒꯠꯂꯨ ꯉꯥꯏꯍꯥꯛꯀꯤ ꯑꯣꯏꯕꯥ ꯄꯥꯁꯋ꯭ꯔꯇ",
+       "resetpass-temp-password": "ꯉꯩꯍꯥꯛꯀꯤ ꯑꯣꯏꯕꯥ ꯄꯥꯁꯋ꯭ꯔꯇ",
        "passwordreset": "ꯄꯥꯁꯋ꯭ꯇ ꯁꯦꯝꯗꯣꯛꯄꯥ",
+       "passwordreset-username": "ꯁꯤꯖꯤꯟꯅꯔꯤꯕꯥ ꯃꯃꯤꯡ",
+       "passwordreset-domain": "ꯗꯣꯃꯦꯟ",
+       "passwordreset-email": "ꯏꯃꯦꯜ ꯂꯥꯐꯝ",
+       "passwordreset-emailtitle": "{{SITENAME}} ꯑꯀꯨꯞꯄꯥ ꯃꯔꯣꯜ",
+       "passwordreset-emailtext-ip": "Someone (probably you, from IP address $1) requested a reset of your\npassword for {{SITENAME}} ($4). The following user {{PLURAL:$3|account is|accounts are}}\nassociated with this email address:\n\n$2\n\n{{PLURAL:$3|This temporary password|These temporary passwords}} will expire in {{PLURAL:$5|one day|$5 days}}.\nYou should log in and choose a new password now. If someone else made this\nrequest, or if you have remembered your original password, and you no longer\nwish to change it, you may ignore this message and continue using your old\npassword.",
+       "passwordreset-emailtext-user": "User $1 on {{SITENAME}} requested a reset of your password for {{SITENAME}}\n($4). The following user {{PLURAL:$3|account is|accounts are}} associated with this email address:\n\n$2\n\n{{PLURAL:$3|This temporary password|These temporary passwords}} will expire in {{PLURAL:$5|one day|$5 days}}.\nYou should log in and choose a new password now. If someone else made this\nrequest, or if you have remembered your original password, and you no longer\nwish to change it, you may ignore this message and continue using your old\npassword.",
+       "passwordreset-emailelement": "$1 ꯁꯤꯖꯤꯟꯅꯔꯤꯕꯥ\n$2 ꯉꯩꯍꯥꯛꯀꯤ ꯑꯣꯏꯕꯥ ꯄꯥꯁꯋꯔꯇ",
+       "changeemail-none": "ꯑꯃꯥꯇꯥ ꯅꯠꯇꯦ",
+       "changeemail-password": "ꯅꯪꯒꯤ {{SITENAME}} ꯄꯥꯁꯋ꯭ꯔꯇ:",
+       "changeemail-submit": "ꯏ-ꯃꯦꯜ ꯍꯣꯡꯕꯥ",
        "bold_sample": "ꯆꯥꯎꯅꯥ ꯏꯕꯥ",
        "bold_tip": "ꯆꯥꯎꯅꯥ ꯏꯕꯥ",
        "italic_sample": "ꯋꯥꯔꯦꯡ ꯐꯆꯅꯥ ꯏꯕꯥ",
        "sig_tip": "ꯃꯇꯝꯒꯤ ꯏꯁꯇꯥꯝꯒꯥ ꯂꯣꯏꯟꯅꯥ ꯅꯪꯒꯤ ꯈꯨꯇꯌꯦꯛ",
        "hr_tip": "ꯐꯩꯅꯥ ꯆꯤꯡꯕꯥ ꯂꯥ ꯏ (ꯃꯔꯤꯛ ꯃꯔꯤꯛ ꯑꯣꯏꯅꯥ ꯁꯤꯖꯤꯟꯅꯧ)",
        "summary": "ꯑꯇꯦꯟꯕꯥ ꯁꯟꯗꯣꯛꯅꯥ ꯇꯥꯛꯄꯥ",
+       "subject": "ꯍꯤꯔꯝ",
        "minoredit": "ꯃꯁꯤ ꯑꯄꯤꯛꯄꯥ ꯁꯦꯝꯒꯠꯄꯅꯤ",
        "watchthis": "ꯃꯁꯤꯒꯤ ꯂꯥꯃꯥꯏꯁꯤ ꯌꯦꯡꯉꯨ",
        "savearticle": "ꯂꯥꯃꯥꯏ ꯇꯨꯪꯁꯤꯟꯕꯥ",
+       "savechanges": "ꯑꯍꯣꯡꯕꯗꯨ ꯇꯨꯪꯁꯤꯟꯂꯨ",
+       "publishpage": "ꯂꯥꯃꯥꯏ ꯐꯣꯡꯗꯣꯛ ꯎ",
+       "publishchanges": "ꯑꯍꯣꯡꯕꯁꯤꯡꯗꯨ ꯐꯣꯡꯗꯣꯛ ꯎ",
+       "savearticle-start": "ꯂꯥꯃꯥꯏ ꯁꯤ ꯇꯨꯡꯁꯤꯜꯂꯨ",
+       "savechanges-start": "ꯑꯍꯣꯡꯕꯁꯤꯡꯗꯨ ꯇꯨꯪꯁꯤꯟꯂꯨ",
+       "publishpage-start": "ꯂꯥꯃꯥꯏ ꯐꯣꯡꯗꯣꯛ ꯎ",
+       "publishchanges-start": "ꯑꯍꯣꯡꯕꯁꯤꯡꯗꯨ ꯐꯣꯡꯗꯣꯛ ꯎ",
+       "preview": "ꯃꯥꯃꯥꯡꯒꯤ",
        "showpreview": "ꯍꯥꯟꯅꯒꯤꯗꯨ ꯎꯨꯇꯂꯨ",
        "showdiff": "ꯑꯍꯣꯡꯕꯗꯨ ꯎꯨꯇꯂꯨ",
+       "blankarticle": "<strong>Warning:</strong> The page you are creating is blank.\nIf you click \"$1\" again, the page will be created without any content.",
        "anoneditwarning": "<strong>Warning:</strong> You are not logged in. Your IP address will be publicly visible if you make any edits. If you <strong>[$1 log in]</strong> or <strong>[$2 create an account]</strong>, your edits will be attributed to your username, along with other benefits.",
        "loginreqlink": "Chang Sinba",
+       "accmailtitle": "ꯄꯥꯁꯋ꯭ꯔꯇ ꯊꯥꯕ",
+       "newarticle": "ꯑꯅꯧꯕꯥ",
        "newarticletext": "You have followed a link to a page that does not exist yet.\nTo create the page, start typing in the box below (see the [$1 help page] for more info).\nIf you are here by mistake, click your browser's <strong>back</strong> button.",
+       "anontalkpagetext": "----\n<em>This is the discussion page for an anonymous user who has not created an account yet, or who does not use it.</em>\nWe therefore have to use the numerical IP address to identify him/her.\nSuch an IP address can be shared by several users.\nIf you are an anonymous user and feel that irrelevant comments have been directed at you, please [[Special:CreateAccount|create an account]] or [[Special:UserLogin|log in]] to avoid future confusion with other anonymous users.",
        "noarticletext": "There is currently no text in this page.\nYou can [[Special:Search/{{PAGENAME}}|search for this page title]] in other pages,\n<span class=\"plainlinks\">[{{fullurl:{{#Special:Log}}|page={{FULLPAGENAMEE}}}} search the related logs],\nor [{{fullurl:{{FULLPAGENAME}}|action=edit}} create this page]</span>.",
        "noarticletext-nopermission": "There is currently no text in this page.\nYou can [[Special:Search/{{PAGENAME}}|search for this page title]] in other pages, or <span class=\"plainlinks\">[{{fullurl:{{#Special:Log}}|page={{FULLPAGENAMEE}}}} search the related logs]</span>, but you do not have permission to create this page.",
+       "missing-revision": "The revision #$1 of the page named \"{{FULLPAGENAME}}\" does not exist.\n\nThis is usually caused by following an outdated history link to a page that has been deleted.\nDetails can be found in the [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} deletion log].",
+       "continue-editing": "ꯁꯦꯝꯒꯠꯄꯒꯤ ꯃꯐꯝꯗꯨꯗꯥ ꯆꯠꯂꯨ",
        "editing": "$1 ꯁꯦꯝꯒꯠꯂꯤ",
        "creating": "Creating $1",
        "editingsection": "Editing $1 (section)",
+       "yourtext": "ꯅꯪꯒꯤ ꯇꯦꯀꯁ",
+       "yourdiff": "ꯈꯦꯠꯅꯕꯥ ꯁꯤꯡ",
+       "copyrightwarning": "Please note that all contributions to {{SITENAME}} are considered to be released under the $2 (see $1 for details).\nIf you do not want your writing to be edited mercilessly and redistributed at will, then do not submit it here.<br />\nYou are also promising us that you wrote this yourself, or copied it from a public domain or similar free resource.\n<strong>Do not submit copyrighted work without permission!</strong>",
        "templatesused": "{{PLURAL:$1|Template|Templates}} used on this page:",
        "template-protected": "ꯉꯥꯛꯊꯣꯛꯂꯕꯥ",
        "template-semiprotected": "ꯇꯪꯈꯥꯏ ꯉꯥꯛꯊꯣꯛꯂꯕꯥ",
        "hiddencategories": "This page is a member of {{PLURAL:$1|1 hidden category|$1 hidden categories}}:",
+       "permissionserrors": "ꯑꯌꯥꯕꯥꯗꯨ ꯁꯣꯏꯔꯦ",
        "permissionserrorstext-withaction": "You do not have permission to $2, for the following {{PLURAL:$1|reason|reasons}}:",
        "moveddeleted-notice": "ꯃꯁꯤꯒꯤ ꯂꯥꯃꯥꯏꯁꯤ ꯀꯛꯊꯠꯈꯔꯦ. \nꯀꯛꯊꯠꯄꯥ, ꯉꯥꯛꯊꯣꯛꯄꯥ ꯑꯃꯗꯤ ꯂꯣꯒ ꯂꯦꯡꯍꯟꯕꯥ ꯂꯥꯃꯥꯏꯒꯤꯗꯃꯛ ꯇꯨ ꯃꯈꯥꯒꯤ ꯁꯤꯗꯥ ꯔꯤꯐꯔꯦꯟꯁ ꯎꯨꯠꯂꯦ",
+       "edit-conflict": "ꯁ‍ꯦꯝꯒꯠꯐꯝꯒꯤ ꯈꯠꯅ ꯆꯩꯅꯕꯥ",
+       "content-json-empty-object": "ꯑꯍꯥꯡꯕꯥ ꯄꯣꯠꯁꯛ",
        "viewpagelogs": "ꯃꯁꯤꯒꯤ ꯂꯥꯃꯥꯏꯁꯤꯒꯤ ꯅꯧꯅ ꯆꯪꯉꯨ",
        "currentrev-asof": "$1 ꯒꯤ ꯅꯧꯅꯥ ꯑꯃꯨꯛꯍꯟꯅꯥ ꯌꯦꯡꯕꯥ ꯃꯤꯠꯌꯦꯡ",
        "revisionasof": "Revision as of $1",
        "currentrevisionlink": "ꯈꯋꯥꯏꯗꯒꯤ ꯅꯧꯅꯥ ꯑꯃꯨꯛ ꯌꯦꯡꯕꯥ",
        "cur": "ꯍꯧ",
        "last": "ꯃꯥꯃꯥꯡꯒꯤ",
+       "page_first": "ꯑꯍꯥꯟꯕ",
+       "page_last": "ꯑꯔꯣꯏꯕ",
        "histlegend": "Diff selection: Mark the radio boxes of the revisions to compare and hit enter or the button at the bottom.<br />\nLegend: <strong>({{int:cur}})</strong> = difference with latest revision, <strong>({{int:last}})</strong> = difference with preceding revision, <strong>{{int:minoreditletter}}</strong> = minor edit.",
        "history-fieldset-title": "ꯊꯤꯋꯨ ꯑꯃꯨꯛ ꯍꯝꯁꯟꯅꯥ ꯌꯦꯡꯅꯕꯥ",
        "histfirst": "ꯈꯋꯥꯏꯗꯒꯤ ꯑꯔꯤꯕꯥ",
        "histlast": "ꯑꯅꯧꯕꯥ",
        "rev-delundel": "ꯑꯍꯣꯡꯕꯥ ꯎꯍꯟꯂꯤꯕꯥ",
+       "revdelete-show-file-submit": "ꯍꯣꯏ",
+       "revdelete-radio-unset": "ꯎꯍꯟꯕ",
        "history-title": "Revision history of \"$1\"",
        "difference-title": "$1 ꯒꯤ ꯑꯃꯨꯛꯍꯟꯕꯥ ꯈꯦꯠꯅꯕꯥꯒꯤ ꯃꯔꯛ",
        "lineno": "ꯂꯥ ꯏ $1",
index c3fc175..e73006f 100644 (file)
        "rev-deleted-user": "(အသုံးပြုသူအမည် ဖယ်ရှားပြီး)",
        "rev-deleted-event": "(အသေးစိတ် မှတ်တမ်း ဖယ်ရှားပြီးပြီ)",
        "rev-deleted-text-permission": "ဤစာမျက်နှာ ရာဇဝင်များသည် <strong>ဖျက်ထားပြီး</strong>ဖြစ်သည်။\nအသေးစိတ်များကို [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} ဖျက်ထားသည့် မှတ်တမ်း]တွင် တွေ့ရှိနိုင်ပါသည်။",
+       "rev-deleted-unhide-diff": "ဤမူကွဲ၏ တည်းဖြတ်မူတစ်ခုအား <strong>ဖျက်ထားသည်</strong>။\nအသေးစိတ်ကို [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} ဖျက်ထားသည့် မှတ်တမ်း]တွင် တွေ့ရှိနိုင်သည်။\nသင့်အနေဖြင့် ဆန္ဒရှိပါက [$1 ဤမူကွဲ]ကို ဆက်လက် ကြည့်ရှုနိုင်သည်။",
+       "rev-deleted-diff-view": "ဤမူကွဲ၏ တည်းဖြတ်မူတစ်ခုအား <strong>ဖျက်ထားသည်</strong>။\nဤမူကွဲကို ကြည့်ရှုနိုင်ပြီး အသေးစိတ်ကို [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} ဖျက်ထားသည့် မှတ်တမ်း]တွင် တွေ့ရှိနိုင်သည်။",
        "rev-delundel": "အမြင်ပုံစံ ပြောင်းလဲရန်",
        "rev-showdeleted": "ပြ",
        "revisiondelete": "မူများကို ဖျက်ရန်/မဖျက်တော့ရန်",
index 80d38b6..17886a4 100644 (file)
        "resetpass-submit-loggedin": "Endre passord",
        "resetpass-submit-cancel": "Avbryt",
        "resetpass-wrong-oldpass": "Ugyldig midlertidig eller aktivt passord.\nDet kan tenkes at allerede har gjennomført et vellykket bytte av passord, eller bedt om et nytt midlertidig passord.",
-       "resetpass-recycled": "Vær vennlig å endre passordet til noe annen enn gjeldende passord.",
+       "resetpass-recycled": "Endre passordet ditt til noe annet enn det nåværende passordet.",
        "resetpass-temp-emailed": "Du logget inn med en midlertidig kode sendt på e-post.\nFor å avslutte innloggingen må du angi et nytt passord her:",
        "resetpass-temp-password": "Midlertidig passord:",
        "resetpass-abort-generic": "Endring av passord har blitt avbrutt av en utvidelse.",
        "resetpass-expired": "Passordet ditt har utløpt. Vær vennlig å angi et nytt passord for å logge inn.",
        "resetpass-expired-soft": "Passordet ditt har utløpt og må endres. Vær vennlig å angi et nytt passord, eller klikk \"{{int:authprovider-resetpass-skip-label}}\" for å endre det senere.",
-       "resetpass-validity-soft": "Ditt passord er ikke gyldig: $1",
+       "resetpass-validity-soft": "Passordet ditt er ikke gyldig: $1\n\nVelg et nytt passord nå, eller klikk på «{{int:authprovider-resetpass-skip-label}}» for å endre det seinere.",
        "passwordreset": "Tilbakestilling av passord",
        "passwordreset-text-one": "Fyll ut skjemaet for å tilbakestille passordet",
        "passwordreset-text-many": "{{PLURAL:$1|Fyll inn ett av datafeltene for å tilbakestille passordet ditt via epost.}}",
        "previewerrortext": "En feil oppsto mens dine endringer skulle forhåndsvises.",
        "blockedtitle": "Brukeren er blokkert",
        "blockedtext": "<strong>Ditt brukernavn eller din IP-adresse har blitt blokkert.</strong>\n\nBlokkeringen ble utført av $1. Grunnen som ble oppgitt var <em>$2</em>.\n\n* Blokkeringen begynte:  $8\n* Blokkeringen opphører: $6\n* Blokkeringen ment for: $7\n\nDu kan kontakte $1 eller en annen [[{{MediaWiki:Grouppage-sysop}}|administrator]] for å diskutere blokkeringen.\nDu kan ikke bruke \"{{int:emailuser}}\"-funksjonen med mindre du har oppgitt en gyldig e-postadresse i [[Special:Preferences|innstillingene dine]] og du ikke har blitt blokkert fra å sende e-post.\nDin nåværende IP-adresse er $3, og blokkerings-ID-en er #$5.\nVennligst ta med all denne informasjonen ved henvendelser.",
-       "autoblockedtext": "Din IP-adresse har blitt automatisk blokkert fordi den ble brukt av en annen bruker som ble blokkert av $1.\nDen oppgitte grunnen var:\n\n:'''$2'''\n\n* Blokkeringen begynte: $8\n* Blokkeringen utgår: $6\n* Blokkeringen er ment for: $7\n\nDu kan kontakte $1 eller en av de andre [[{{MediaWiki:Grouppage-sysop}}|administratorene]] for å diskutere blokkeringen.\n\nMerk at du ikke kan bruke «E-post til denne brukeren»-funksjonen med mindre du har registrert en gyldig e-postadresse i [[Special:Preferences|innstillingene dine]].\n\nDin IP-adresse er $3, og blokkerings-ID-en er #$5.\nVennligst ta med all denne informasjonen ved henvendelser.",
+       "autoblockedtext": "Din IP-adresse har blitt automatisk blokkert fordi den ble brukt av en annen bruker som ble blokkert av $1.\nDen oppgitte grunnen var:\n\n:'''$2'''\n\n* Blokkeringen begynte: $8\n* Blokkeringen utgår: $6\n* Blokkeringen er ment for: $7\n\nDu kan kontakte $1 eller en av de andre [[{{MediaWiki:Grouppage-sysop}}|administratorene]] for å diskutere blokkeringen.\n\nMerk at du ikke kan bruke «{{int:emailuser}}»-funksjonen med mindre du har registrert en gyldig e-postadresse i [[Special:Preferences|innstillingene dine]].\n\nDin IP-adresse er $3, og blokkerings-ID-en er #$5.\nVennligst ta med all denne informasjonen ved henvendelser.",
        "systemblockedtext": "Ditt brukernavn eller IP-adresse har blitt blokkert automatisk av MediaWiki.\n\nBlokkeringen grunnes:\n\n:<em>$2</em>\n\n* Blokkeringen startet: $8\n* Blokkeringen gjelder til: $6\n* Blokkeringen er ment for: $7\n\nDin nåværende IP-adresse er $3.\nVennligst inkluder informasjonen over i alle spørsmål du spør angående dette.",
        "blockednoreason": "ingen grunn gitt",
        "whitelistedittext": "Du må $1 for å redigere artikler.",
        "converter-manual-rule-error": "En feil ble oppdaget i en manuell språkkonverteringsregel",
        "undo-success": "Redigeringen kan omgjøres. Sjekk sammenligningen under for å bekrefte at du vil gjøre dette, og lagre endringene for å fullføre omgjøringen.",
        "undo-failure": "Redigeringen kunne ikke omgjøres på grunn av konflikterende etterfølgende redigeringer.",
+       "undo-main-slot-only": "Redigeringen kunne ikke omgjøres fordi den involverer innhold utenfor hovedspalten.",
        "undo-norev": "Redigeringen kunne ikke fjernes fordi den ikke eksisterer eller ble slettet",
        "undo-nochange": "Det ser ut til at redigeringen allerede er tilbakestilt.",
        "undo-summary": "Fjerner revisjon $1 av [[Special:Contributions/$2|$2]] ([[User talk:$2|diskusjon]])",
        "rcfilters-other-review-tools": "Andre gjennomgangsverktøy",
        "rcfilters-group-results-by-page": "Grupper resultater etter side",
        "rcfilters-activefilters": "Aktive filtre",
+       "rcfilters-activefilters-hide": "Skjul",
+       "rcfilters-activefilters-show": "Vis",
+       "rcfilters-activefilters-hide-tooltip": "Skjul området for aktive filtre",
+       "rcfilters-activefilters-show-tooltip": "Vis området for aktive filtre",
        "rcfilters-advancedfilters": "Avanserte filtre",
        "rcfilters-limit-title": "Antall resultater som skal vises",
        "rcfilters-limit-and-date-label": "$1 {{PLURAL:$1|endring|endringer}}, $2",
        "rcfilters-savedqueries-rename": "Gi nytt navn",
        "rcfilters-savedqueries-setdefault": "Sett som standard",
        "rcfilters-savedqueries-unsetdefault": "Fjern som standard",
-       "rcfilters-savedqueries-remove": "Fjern",
+       "rcfilters-savedqueries-remove": "Slett",
        "rcfilters-savedqueries-new-name-label": "Navn",
        "rcfilters-savedqueries-new-name-placeholder": "Beskriv formålet til filteret",
        "rcfilters-savedqueries-apply-label": "Opprett filter",
        "rcfilters-empty-filter": "Ingen aktive filtre. Alle bidrag vises.",
        "rcfilters-filterlist-title": "Filtre",
        "rcfilters-filterlist-whatsthis": "Hvordan virker dette?",
-       "rcfilters-filterlist-feedbacklink": "Gi tilbakemelding på disse (nye) filterverktøyene",
+       "rcfilters-filterlist-feedbacklink": "Gi tilbakemelding på disse filterverktøyene",
        "rcfilters-highlightbutton-title": "Marker resultater",
        "rcfilters-highlightmenu-title": "Velg en farge",
        "rcfilters-highlightmenu-help": "Velg en farge for å merke denne egenskapen",
index ff9175b..6adf737 100644 (file)
        "expansion-depth-exceeded-warning": "De pagina bevat te veel sjablonen",
        "parser-unstrip-loop-warning": "Er is een \"unstrip\"-lus gedetecteerd",
        "unstrip-depth-warning": "De recursielimiet ($1) voor \"unstrip\" is overschreden",
+       "unstrip-depth-category": "Pagina's waar de \"unstrip\" dieptelimiet is overschreden.",
+       "unstrip-size-warning": "De groottelimiet ($1) voor \"unstrip\" is overschreden",
+       "unstrip-size-category": "Pagina's waar de \"unstrip\" groottelimiet is overschreden",
        "converter-manual-rule-error": "Er is een fout gedetecteerd in een handmatig toegevoegde taalconversieregel.",
        "undo-success": "Deze bewerking kan ongedaan gemaakt worden.\nHieronder staat de tekst waarin de wijziging ongedaan is gemaakt.\nControleer voor het opslaan of het resultaat gewenst is.",
        "undo-failure": "De wijziging kan niet ongedaan gemaakt worden vanwege andere strijdige wijzigingen.",
        "limitreport-cputime-value": "$1 {{PLURAL:$1|seconde|seconden}}",
        "limitreport-walltime": "Werkelijk tijdsgebruik",
        "limitreport-walltime-value": "$1 {{PLURAL:$1|seconde|seconden}}",
-       "limitreport-ppvisitednodes": "Aantal nodes bekeken tijdens de voorverwerking:",
-       "limitreport-ppgeneratednodes": "Aantal nodes aangemaakt tijdens de voorverwerking:",
+       "limitreport-ppvisitednodes": "Aantal nodes bekeken tijdens de voorverwerking",
+       "limitreport-ppgeneratednodes": "Aantal nodes aangemaakt tijdens de voorverwerking",
        "limitreport-postexpandincludesize": "Inclusiegrootte na uitbreiden",
        "limitreport-postexpandincludesize-value": "$1/$2 {{PLURAL:$2|byte|bytes}}",
        "limitreport-templateargumentsize": "Grootte sjabloonparameters",
        "limitreport-templateargumentsize-value": "$1 / $2 {{PLURAL:$2|byte|bytes}}",
        "limitreport-expansiondepth": "Hoogste uitbreidingsdiepte",
        "limitreport-expensivefunctioncount": "Aantal kostbare parserfuncties",
+       "limitreport-unstrip-depth": "\"Unstrip\" recursiediepte",
+       "limitreport-unstrip-size": "\"Unstrip\" grootte na uitbreiden",
        "limitreport-unstrip-size-value": "$1/$2 {{PLURAL:$2|byte|bytes}}",
        "expandtemplates": "Sjablonen substitueren",
        "expand_templates_intro": "Deze speciale pagina leest de opgegeven wikitekst in en substitueert recursief alle sjablonen in de wikitekst.\nHet substitueert ook alle parserfuncties zoals\n<code><nowiki>{{</nowiki>#language:…}}</code> en\nvariabelen als <code><nowiki>{{</nowiki>CURRENTDAY}}</code>.\nVrijwel alles tussen dubbele accolades wordt gesubstitueerd.",
index aa0cf19..be98c41 100644 (file)
        "prefs-diffs": "Skilnader",
        "prefs-help-prefershttps": "Denne innstillinga vil verta verksam neste gongen du loggar inn.",
        "userrights": "Administrering av brukartilgang",
-       "userrights-lookup-user": "Administrer brukargrupper",
+       "userrights-lookup-user": "Vel ein brukar",
        "userrights-user-editname": "Skriv inn brukarnamn:",
-       "editusergroup": "Endre brukargrupper",
+       "editusergroup": "Last inn brukargrupper",
        "editinguser": "Endrar brukarrettane til brukaren '''[[User:$1|$1]]''' $2",
+       "viewinguserrights": "Viser brukarrettane til {{GENDER:$1|brukaren}} <strong>[[User:$1|$1]]</strong> $2",
        "userrights-editusergroup": "Endre brukargrupper",
+       "userrights-viewusergroup": "Sjå {{GENDER:$1|brukargrupper}}",
        "saveusergroups": "Lagre brukargrupper",
        "userrights-groupsmember": "Medlem av:",
        "userrights-groupsmember-auto": "Implisitt medlem av:",
        "booksources-search": "Søk",
        "booksources-text": "Nedanfor finn du ei liste over lenkjer til andre nettstader som sel nye og brukte bøker, og desse kan ha meir informasjon om bøker du leitar etter:",
        "booksources-invalid-isbn": "Det oppgjevne ISBN-nummeret er ugyldig; sjekk med kjelda di om du har oppgjeve det rett.",
+       "magiclink-tracking-rfc": "Sider som nyttar magiske RFC-lenkjer",
+       "magiclink-tracking-pmid": "Sider som nyttar magiske PMID-lenkjer‎",
+       "magiclink-tracking-isbn": "Sider som nyttar magiske ISBN-lenkjer",
        "specialloguserlabel": "Utøvar:",
        "speciallogtitlelabel": "Mål (tittel eller {{ns:user}}:brukarnamn for brukar):",
        "log": "Loggar",
        "trackingcategories-msg": "Sporingskategori",
        "trackingcategories-name": "Meldingsnamn",
        "trackingcategories-desc": "Inkluderingsgrunnlag",
+       "restricted-displaytitle-ignored": "Sider med ignorerte visingstitlar",
+       "restricted-displaytitle-ignored-desc": "Ein <code><nowiki>{{DISPLAYTITLE}}</nowiki></code>-funksjon på denne sida  er sett bort ifrå av di argumentet ikkje svarar til den faktiske tittelen til sida.",
        "noindex-category-desc": "Sida vert ikkje indeksert av robotar av di ho inneheld trylleordet <code><nowiki>__NOINDEX__</nowiki></code> og er i eit namnerom der dette flagget er tillate.",
        "trackingcategories-nodesc": "Inga skilding er tilgjengeleg.",
        "trackingcategories-disabled": "Kategorien er avslegen",
        "watchlisttools-raw": "Endre på overvakingslista i råformat",
        "signature": "[[{{ns:user}}:$1|$2]] ([[{{ns:user_talk}}:$1|diskusjon]])",
        "duplicate-defaultsort": "Åtvaring: Standardsorteringa «$2» tar over for den tidlegare sorteringa «$1».",
+       "restricted-displaytitle": "<strong>Åtvaring:</strong> Visingstittelen «$1» vart sett bort frå sidan han ikkje svarar til den faktiske tittelen til sida.",
        "version": "Versjon",
        "version-extensions": "Installerte utvidingar",
        "version-skins": "Installerte drakter",
index 120b542..23b2f66 100644 (file)
        "removedwatchtext-short": "A página \"$1\" foi removida de sua lista de páginas vigiadas.",
        "watch": "Vigiar",
        "watchthispage": "Vigiar esta página",
-       "unwatch": "Desinteressar-se",
+       "unwatch": "Deixar de vigiar",
        "unwatchthispage": "Parar de vigiar esta página",
        "notanarticle": "Não é uma página de conteúdo",
        "notvisiblerev": "Edição eliminada",
        "sp-contributions-logs": "registros",
        "sp-contributions-talk": "discussão",
        "sp-contributions-userrights": "{{GENDER:$1|gestão}} dos privilégios",
-       "sp-contributions-blocked-notice": "Este usuário atualmente está bloqueado. O registro de bloqueio mais recente é fornecido abaixo para referência:",
+       "sp-contributions-blocked-notice": "{{GENDER:$1|Este usuário atualmente está bloqueado|Esta usuária atualmente está bloqueada|Este(a) usuário(a) atualmente está bloqueado(a)}}. O registro de bloqueio mais recente é fornecido abaixo para referência:",
        "sp-contributions-blocked-notice-anon": "Este endereço IP encontra-se bloqueado.\nSegue, para referência, a entrada mais recente no registro de bloqueios:",
        "sp-contributions-search": "Navegar pelas contribuições",
        "sp-contributions-username": "Endereço de IP ou usuário(a):",
index db51aa6..0220365 100644 (file)
@@ -77,7 +77,8 @@
                        "RadiX",
                        "MokaAkashiyaPT",
                        "Athena in Wonderland",
-                       "Fitoschido"
+                       "Fitoschido",
+                       "Ldacosta"
                ]
        },
        "tog-underline": "Sublinhar hiperligações:",
        "viewhelppage": "Ver página de ajuda",
        "categorypage": "Ver página de categoria",
        "viewtalkpage": "Ver discussão",
-       "otherlanguages": "Noutras línguas",
+       "otherlanguages": "Em outros idiomas",
        "redirectedfrom": "(Redirecionado de $1)",
        "redirectpagesub": "Página de redirecionamento",
        "redirectto": "Redireciona para:",
        "mostinterwikis": "Páginas com mais hiperligações interwikis",
        "mostrevisions": "Páginas com mais revisões",
        "prefixindex": "Todas as páginas iniciadas por",
-       "prefixindex-namespace": "Todas as páginas com prefixo (domínio $1)",
+       "prefixindex-namespace": "Todas as páginas com prefixo (espaço nominal $1)",
        "prefixindex-submit": "Mostrar",
        "prefixindex-strip": "Remover prefixo",
        "shortpages": "Páginas curtas",
        "nowikiemailtext": "Este utilizador optou por não receber correio eletrónico de outros utilizadores.",
        "emailnotarget": "O nome do destinatário não existe ou é inválido.",
        "emailtarget": "Introduza o nome do destinatário",
-       "emailusername": "Utilizador:",
+       "emailusername": "Nome de Utilizador:",
        "emailusernamesubmit": "Enviar",
        "email-legend": "Enviar uma mensagem a outro utilizador da wiki {{SITENAME}}",
        "emailfrom": "De:",
        "removedwatchtext-short": "A página \"$1\" foi removida das suas páginas vigiadas.",
        "watch": "Vigiar",
        "watchthispage": "Vigiar esta página",
-       "unwatch": "Desinteressar-se",
+       "unwatch": "Deixar de vigiar",
        "unwatchthispage": "Parar de vigiar esta página",
        "notanarticle": "Não é uma página de conteúdo",
        "notvisiblerev": "A última revisão feita por um utilizador diferente foi eliminada",
        "sp-contributions-logs": "registos",
        "sp-contributions-talk": "discussão",
        "sp-contributions-userrights": "{{GENDER:$1|gestão}} dos privilégios",
-       "sp-contributions-blocked-notice": "Este utilizador está bloqueado neste momento.\nPara referência é apresentado abaixo o último registo de bloqueio:",
+       "sp-contributions-blocked-notice": "{{GENDER:$1|Este utilizador está bloqueado|Esta utilizadora está bloqueada}} neste momento.\nPara referência é apresentado abaixo o último registo de bloqueio:",
        "sp-contributions-blocked-notice-anon": "Este endereço IP está bloqueado neste momento.\nPara referência é apresentado abaixo o último registo de bloqueio:",
        "sp-contributions-search": "Pesquisar contribuições",
        "sp-contributions-username": "Endereço IP ou nome de utilizador:",
index aa135f8..3d12f42 100644 (file)
        "talk": "ᱜᱟᱞᱢᱟᱨᱟᱣ",
        "views": "ᱧᱮᱞᱚᱜᱚᱜ",
        "toolbox": "ᱦᱟᱹᱛᱭᱟᱹᱨ",
+       "tool-link-userrights": "{{GENDER:$1|ᱵᱮᱵᱷᱟᱨᱤᱭᱟᱹ}} ᱜᱟᱫᱮᱞ ᱵᱚᱫᱚᱞ",
+       "tool-link-userrights-readonly": "{{GENDER:$1|ᱵᱮᱵᱷᱟᱨᱤᱭᱟᱹ}} ᱜᱟᱫᱮᱞ ᱧᱮᱞ",
        "tool-link-emailuser": "ᱤᱢᱮᱞᱟᱭᱢᱮ ᱱᱩᱭ {{GENDER:$1|ᱵᱮᱵᱷᱟᱨᱤᱭᱟᱹ}}",
        "imagepage": "ᱨᱮᱫ ᱥᱟᱦᱴᱟ ᱧᱮᱞᱢᱮ",
        "mediawikipage": "ᱠᱷᱚᱵᱚᱨ ᱥᱟᱦᱴᱟ ᱧᱮᱞᱢᱮ",
        "jumptonavigation": "ᱟᱹᱪᱩᱨᱵᱟᱲᱟ",
        "jumptosearch": "ᱥᱮᱸᱫᱽᱨᱟ",
        "view-pool-error": "Ikạkańmẽ, sarvarre nitoḱ do aḍi cap menaḱa.\nẠḍi aema beoharko noa sakam ńel lạgit́ko kurumuṭueda.\nNãwate noa sakam ńel kurumuṭuy lạgit́te dayakate mit́ghạṛi tạṅgiymẽ.\n$1",
+       "generic-pool-error": "ᱤᱠᱟᱹᱠᱟᱹᱧᱢᱮ, ᱱᱚᱶᱟ ᱥᱚᱨᱵᱷᱚᱨ ᱨᱮ ᱱᱤᱛ ᱟᱹᱰᱤᱜᱟᱱ ᱪᱟᱯ ᱢᱮᱱᱟᱜᱼᱟ ᱾\nᱟᱹᱰᱤ ᱟᱭᱢᱟ ᱵᱮᱵᱷᱟᱨᱤᱭᱟᱹ ᱱᱚᱶᱟ ᱥᱟᱠᱟᱢ ᱧᱮᱞ ᱞᱟᱹᱜᱤᱫ ᱠᱚ ᱨᱤᱠᱟᱹᱭᱮᱫᱼᱟ ᱾\nᱱᱚᱶᱟ ᱥᱟᱠᱟᱢ ᱧᱮᱞ ᱞᱟᱹᱜᱤᱰ ᱱᱟᱥᱮ ᱛᱟᱺᱜᱤ ᱢᱮ ᱾",
        "pool-timeout": "Somoy paromena cạbi lạgit́te tạṅgi hoyoḱkana",
        "pool-queuefull": "Pool queue is full",
        "pool-errorunknown": "ᱵᱟᱝ ᱵᱟᱰᱟᱭ ᱦᱩᱲᱟᱹᱜ",
        "filerenameerror": "\"$1\" ᱨᱮᱫ ᱨᱮᱭᱟᱜ ᱧᱩᱛᱩᱢ ᱵᱚᱫᱚᱞ ᱠᱟᱛᱮ \"$2\" ᱮᱢ ᱵᱟᱝ ᱜᱟᱱᱚᱜ ᱠᱟᱱᱟ᱾",
        "filedeleteerror": "$1 ᱨᱮᱫ ᱫᱚ ᱵᱟᱝ ᱜᱮᱫᱽ ᱜᱤᱰᱤ ᱞᱮᱱᱟ",
        "directorycreateerror": "\"$1\" ᱰᱟᱭᱨᱮᱠᱴᱳᱨᱤ ᱫᱚ ᱵᱟᱝ ᱛᱮᱭᱟᱨᱞᱮᱱᱟ᱾",
+       "directorynotreadableerror": "ᱯᱟᱠᱷᱟ \"$1\" ᱫᱚ ᱯᱟᱲᱦᱟᱣ ᱵᱟᱭ ᱜᱟᱱᱚᱜᱼᱟ ᱾",
        "filenotfound": "\"$1\" ᱨᱮᱫ ᱫᱚ ᱵᱟᱝ ᱧᱟᱢᱞᱮᱱᱟ᱾",
        "unexpected": "ᱵᱟᱝ ᱟᱥᱟᱜ ᱠᱟᱱ ᱢᱟᱹᱱ: \"$1\"=\"$2\".",
        "formerror": "ᱦᱩᱲᱟᱹᱜ: ᱯᱷᱚᱨᱚᱢ ᱫᱚ ᱵᱟᱝ ᱡᱤᱢᱟᱹᱞᱮᱱᱟ᱾",
index 3c3e629..395f324 100644 (file)
        "dellogpage": "Дневник брисања",
        "dellogpagetext": "Испод је списак последњих брисања.",
        "deletionlog": "дневник брисања",
+       "logentry-create-create": "$1 {{GENDER:$2|је направио|је направила}} страницу $3",
        "reverted": "Враћено на ранију измену",
        "deletecomment": "Разлог:",
        "deleteotherreason": "Други/додатни разлог:",
index b1c1bc3..ecc23b6 100644 (file)
        "dellogpage": "Dnevnik brisanja",
        "dellogpagetext": "Ispod je spisak poslednjih brisanja.",
        "deletionlog": "dnevnik brisanja",
+       "logentry-create-create": "$1 {{GENDER:$2|kreirao je|kreirala je}} stranicu $3",
        "reverted": "Vraćeno na raniju izmenu",
        "deletecomment": "Razlog:",
        "deleteotherreason": "Drugi/dodatni razlog:",
index efd014d..416a168 100644 (file)
        "dellogpage": "తొలగింపుల చిట్టా",
        "dellogpagetext": "ఇది ఇటీవలి తుడిచివేతల జాబితా.",
        "deletionlog": "తొలగింపుల చిట్టా",
+       "logentry-create-create": "$3 పేజీని $1 {{GENDER:$2|సృష్టించారు}}",
        "reverted": "పాత కూర్పుకు తీసుకువెళ్ళాం.",
        "deletecomment": "కారణం:",
        "deleteotherreason": "ఇతర/అదనపు కారణం:",
        "newimages-summary": "ఇటీవలే ఎగుమతైన ఫైళ్ళను ఈ ప్రత్యేక పేజీ చూపిస్తుంది.",
        "newimages-legend": "పడపోత",
        "newimages-label": "ఫైలుపేరు (లేదా దానిలోని భాగం):",
+       "newimages-user": "ఐపీ చిరునామా లేదా వాడుకరి పేరు",
+       "newimages-newbies": "కొత్త ఖాతాల రచనలని మాత్రమే చూపించు",
        "newimages-showbots": "బాట్లు చేసిన అప్లోడ్లు చూపించు",
        "newimages-mediatype": "మాధ్యమ రకం:",
        "noimages": "చూసేందుకు ఏమీ లేదు.",
        "compare-title-not-exists": "మీరు పేర్కొన్న శీర్షిక లేనే లేదు.",
        "compare-revision-not-exists": "మీరు పేర్కొన్న కూర్పు లేనే లేదు.",
        "diff-form": "తేడాలు",
+       "permanentlink": "స్థిర లంకె",
        "dberr-problems": "క్షమించండి! ఈ సైటు సాంకేతిక సమస్యలని ఎదుర్కొంటుంది.",
        "dberr-again": "కొన్ని నిమిషాలాగి మళ్ళీ ప్రయత్నించండి.",
        "dberr-info": "(డేటాబేసును చేరలేకున్నాం: $1)",
        "log-action-filter-managetags-delete": "ట్యాగు తొలగింపు",
        "log-action-filter-managetags-activate": "ట్యాగు చేతనం",
        "log-action-filter-managetags-deactivate": "ట్యాగు అచేతనం",
+       "log-action-filter-protect-protect": "సంరక్షణ",
+       "log-action-filter-upload-upload": "కొత్త ఎక్కింపు",
        "authmanager-userdoesnotexist": "వాడుకరి ఖాతా \"$1\" నమోదయి లేదు.",
        "authmanager-userlogin-remembermypassword-help": "సెషను ముగిసిన తరువాత కూడా సంకేతపదాన్ని గుర్తుంచుకోమంటారా",
        "authmanager-username-help": "ధ్రువీకరణ కోసం వాడుకరిపేరు.",
        "restrictionsfield-help": "వరుసకొక్క ఐపీ అడ్రసు లేదా CIDR శ్రేణి. ప్రతీ ఒక్కదాన్నీ చేతనం చేసేందుకు, వాడండి:<pre>0.0.0.0/0\n::/0</pre>",
        "revid": "కూర్పు $1",
        "pageid": "పేజీ ఐడీ $1",
+       "pagedata-bad-title": "చెల్లని శీర్షిక: $1.",
+       "passwordpolicies": "సంకేతపదపు విధానాలు",
+       "passwordpolicies-group": "సమూహం",
        "passwordpolicies-policies": "విధానాలు"
 }
index 2bf9d8c..4dce507 100644 (file)
@@ -76,7 +76,8 @@
                        "Avatar6",
                        "Fitoschido",
                        "Movses",
-                       "Esk78"
+                       "Esk78",
+                       "Vlad5250"
                ]
        },
        "tog-underline": "Підкреслювання посилань:",
        "right-browsearchive": "пошук вилучених сторінок",
        "right-undelete": "відновлення сторінок",
        "right-suppressrevision": "перегляд, приховування та відновлення конкретних змін сторінок від будь-якого користувача",
-       "right-viewsuppressed": "Ð\9fеÑ\80еглÑ\8fд Ð·Ð¼Ñ\96н, Ð¿Ñ\80иÑ\85оваих від усіх користувачів",
+       "right-viewsuppressed": "пеÑ\80еглÑ\8fд Ð·Ð¼Ñ\96н, Ð¿Ñ\80иÑ\85ованих від усіх користувачів",
        "right-suppressionlog": "перегляд приватних журналів",
        "right-block": "заборона редагувань для інших дописувачів",
        "right-blockemail": "блокування користувача від надсилання електронної пошти",
        "right-protect": "зміна рівнів захисту та редагування каскадно захищених сторінок",
        "right-editprotected": "редагування сторінок з рівнем захисту «{{int:protect-level-sysop}}»",
        "right-editsemiprotected": "редагування сторінок з рівнем захисту «{{int:protect-level-autoconfirmed}}»",
-       "right-editcontentmodel": "Редагувати модель вмісту сторінки",
+       "right-editcontentmodel": "редагування моделі вмісту сторінки",
        "right-editinterface": "редагування інтерфейсу користувача",
        "right-editusercss": "редагування CSS-файлів інших користувачів",
        "right-edituserjson": "редагування JSON-файлів інших користувачів",
        "action-viewmywatchlist": "перегляд власного списку спостереження",
        "action-viewmyprivateinfo": "перегляд своєї приватної інформації",
        "action-editmyprivateinfo": "редагування своєї приватної інформації",
-       "action-editcontentmodel": "редагувати модель вмісту сторінки",
+       "action-editcontentmodel": "редагування моделі вмісту сторінки",
        "action-managechangetags": "створення та (де)активування міток",
        "action-applychangetags": "додавання міток разом зі змінами",
        "action-changetags": "додавання або вилучення будь-яких міток для певних версій сторінок або записів журналів",
index 45a3874..af79df3 100644 (file)
        "recreate-moveddeleted-warn": "''' انتباہ: آپ ایک گزشتہ حذف شدہ صفحہ دوبارہ تخلیق کررہے ہیں. '''\n\nآپ کو اِس بات پر غور کرنا چاہئے کہ آیا اِس صفحہ کی تدوین جاری رکھنا موزوں ہے یا نہیں.\nصفحہ کا نوشتۂ حذف شدگی و منتقلی یہاں سہولت کی خاطر مہیّا کیا جارہا ہے:",
        "moveddeleted-notice": "اس صفحہ کو حذف کر دیا گیا ہے۔\nحوالہ کے لیے ذیل میں اس صفحہ کا نوشتہ حذف شدگی اور نوشتہ منتقلی درج ہے۔",
        "moveddeleted-notice-recent": "معذرت، اس صفحہ کو حال ہی میں حذف کیا گیا ہے (گزشتہ چوبیس گھنٹوں میں)۔\nحوالہ کے لیے ذیل میں اس صفحہ کا نوشتہ حذف اور نوشتہ منتقلی موجود ہے۔",
-       "log-fulllog": "پورا نوشتہ دیکھئے",
+       "log-fulllog": "پورا نوشتہ دیکھیے",
        "edit-hook-aborted": "کسی رکاوٹ کی وجہ سے ترمیم کاری منسوخ کر دی گئی ہے۔\nاور کوئی وضاحت نہیں دی گئی۔",
        "edit-gone-missing": "صفحہ تجدید نہیں کیا جاسکتا.\nلگتا ہے یہ حذف ہوچکا ہے.",
        "edit-conflict": "تنازعۂ تدوین.",
        "prefs-email": "برقی خط کے اختیارات",
        "prefs-rendering": "ظاہریت",
        "saveprefs": "محفوظ",
-       "restoreprefs": "تمام ابتدائی ترتیبات کو بحال کریں",
+       "restoreprefs": "تمام ابتدائی ترتیبات (تمام خانوں میں) کو بحال کریں",
        "prefs-editing": "ترمیم کاری",
        "searchresultshead": "تلاش",
        "stub-threshold": "نامکمل ربط کے فارمیٹ کی حد ($1):",
        "prefs-dateformat": "تاریخ کی ترتیب",
        "prefs-timeoffset": "وقت کی ترتیب",
        "prefs-advancedediting": "اعلی اختیارات",
+       "prefs-developertools": "آلات ترقی دہندہ",
        "prefs-editor": "خانہ ترمیم",
        "prefs-preview": "نمائش",
        "prefs-advancedrc": "اضافی اختیارات",
        "recentchangeslinked-feed": "متعلقہ تبدیلیاں",
        "recentchangeslinked-toolbox": "متعلقہ تبدیلیاں",
        "recentchangeslinked-title": "\"$1\" سے متعلقہ تبدیلیاں",
-       "recentchangeslinked-summary": "یہ ان تبدیلیوں کی فہرست ہے جو حال ہی میں کسی مخصوص صفحہ سے مربوط صفحات (یا مخصوص زمرہ کے اراکین) میں کی گئی ہیں۔\n\n[[Special:Watchlist|آپ کی زیر نظر فہرست]] میں یہ صفحات <strong>جلی</strong نظر آئیں گےـ",
+       "recentchangeslinked-summary": "یہ ان تبدیلیوں کی فہرست ہے جو حال ہی میں کسی مخصوص صفحہ سے مربوط صفحات (یا مخصوص زمرہ کے اراکین) میں کی گئی ہیں۔\n\n[[Special:Watchlist|آپ کی زیر نظر فہرست]] میں یہ صفحات <strong>جلی</strong> نظر آئیں گےـ",
        "recentchangeslinked-page": "صفحہ کا نام:",
        "recentchangeslinked-to": "اس کی بجائے درج کردہ صفحہ سے مربوط صفحات کی تبدیلیاں دکھائیں",
        "recentchanges-page-added-to-category": "[[:$1]] کو زمرہ میں شامل کیا گیا",
index f98faa7..e34c4f4 100644 (file)
        "right-override-export-depth": "匯出頁面包含連結內容,深度上限為 5 層",
        "right-sendemail": "傳送電子郵件聯絡其他使用者",
        "right-managechangetags": "建立並自資料庫 (取消) 啟用 [[Special:Tags|標籤]]",
-       "right-applychangetags": "連同某個人的變更一起套用[[Special:Tags|標籤]]",
+       "right-applychangetags": "連同自己的變更一起套用[[Special:Tags|標籤]]",
        "right-changetags": "加入與移除任何於各別修訂與日誌項目的[[Special:Tags|標籤]]",
        "right-deletechangetags": "從資料庫刪除 [[Special:Tags|標籤]]",
        "grant-generic": "\"$1\" 權限組合",
index 245bb47..0015bbe 100644 (file)
@@ -1606,6 +1606,9 @@ abstract class Maintenance {
                if ( wfIsWindows() ) {
                        return $default;
                }
+               if ( Shell::isDisabled() ) {
+                       return $default;
+               }
                // It's possible to get the screen size with VT-100 terminal escapes,
                // but reading the responses is not possible without setting raw mode
                // (unless you want to require the user to press enter), and that
index a12cda7..bf7a22d 100644 (file)
@@ -220,7 +220,7 @@ SPARQL;
        ) {
                $tables = [ 'recentchanges', 'page_props', 'category' ];
                if ( $extra_tables ) {
-                       $tables += $extra_tables;
+                       $tables = array_merge( $tables, $extra_tables );
                }
                $it = new BatchRowIterator( $dbr,
                        $tables,
index 271cbf3..7f36442 100644 (file)
@@ -24,6 +24,7 @@
 
 use MediaWiki\Logger\LegacyLogger;
 use MediaWiki\MediaWikiServices;
+use Wikimedia\Rdbms\IDatabase;
 
 $optionsWithArgs = RecompressTracked::getOptionsWithArgs();
 require __DIR__ . '/../commandLine.inc';
@@ -640,7 +641,7 @@ class RecompressTracked {
        /**
         * Gets a DB master connection for the given external cluster name
         * @param string $cluster
-        * @return Database
+        * @return IDatabase
         */
        function getExtDB( $cluster ) {
                $lbFactory = MediaWikiServices::getInstance()->getDBLoadBalancerFactory();
index cafc1bc..b724306 100644 (file)
@@ -2184,7 +2184,7 @@ return [
        ],
        'mediawiki.special.preferences.styles.ooui' => [
                'targets' => [ 'desktop', 'mobile' ],
-               'styles' => 'resources/src/mediawiki.special.preferences.styles.ooui.css',
+               'styles' => 'resources/src/mediawiki.special.preferences.styles.ooui.less',
        ],
        'mediawiki.special.recentchanges' => [
                'scripts' => 'resources/src/mediawiki.special.recentchanges.js',
index 72ce9f0..cb9c286 100644 (file)
@@ -4,9 +4,11 @@
        background-color: #eaecf0;
        background-size: cover;
        background-position: center center;
-       padding: 1.5em;
-       margin: -1.5em;
-       margin-bottom: 1.5em;
+       /* Same as padding on `.oo-ui-bookletLayout-stackLayout > .oo-ui-panelLayout`,
+        * equals 20px at default font size */
+       padding: 1.42857143em;
+       margin: -1.42857143em;
+       margin-bottom: 1.42857143em;
        position: relative;
 }
 
index d1e40ca..fef5226 100644 (file)
                if ( !this.isHighlightSupported() ) {
                        return;
                }
+               // If the highlight color on the item and in the parameter is null/undefined, return early.
+               if ( !this.highlightColor && !highlightColor ) {
+                       return;
+               }
 
                if ( this.highlightColor !== highlightColor ) {
                        this.highlightColor = highlightColor;
index c7db7c6..6d36c71 100644 (file)
 
        /* Methods */
 
+       /**
+        * Override parent method to avoid unnecessary resize events.
+        */
+       mw.rcfilters.ui.FilterTagMultiselectWidget.prototype.updateIfHeightChanged = function () { };
+
        /**
         * Respond to view select widget choose event
         *
index 04b7709..40b2fcf 100644 (file)
         */
        mw.rcfilters.ui.MenuSelectWidget.prototype.onModelInitialize = function () {
                this.menuInitialized = false;
+               // Set timeout for the menu to lazy build.
+               setTimeout( this.lazyMenuCreation.bind( this ) );
        };
 
        /**
diff --git a/resources/src/mediawiki.special.preferences.styles.ooui.css b/resources/src/mediawiki.special.preferences.styles.ooui.css
deleted file mode 100644 (file)
index 4c5d344..0000000
+++ /dev/null
@@ -1,145 +0,0 @@
-/* Reuses colors from mediawiki.legacy/shared.css */
-.mw-email-not-authenticated .oo-ui-labelWidget,
-.mw-email-none .oo-ui-labelWidget {
-       border: 1px solid #fde29b;
-       background-color: #fdf1d1;
-       color: #000;
-       padding: 0.5em;
-}
-/* Authenticated email field has its own class too. Unstyled by default */
-/*
-.mw-email-authenticated .oo-ui-labelWidget { }
-*/
-
-/* This is needed because add extra buttons in a weird way */
-.mw-prefs-buttons .mw-htmlform-submit-buttons {
-       margin: 0;
-       display: inline;
-}
-
-.mw-prefs-buttons {
-       margin-top: 1em;
-}
-
-#prefcontrol {
-       margin-right: 0.5em;
-}
-
-/*
- * Hide, but keep accessible for screen-readers.
- */
-.client-js .mw-navigation-hint {
-       overflow: hidden;
-       height: 0;
-       zoom: 1;
-}
-
-/* Override OOUI styles so that dropdowns near the bottom of the form don't get clipped,
- * e.g.'Appearance' / 'Threshold for stub link formatting'. This is hacky and bad, it would be
- * better solved by setting overlays for the widgets, but we can't do it from PHP... */
-#preferences .oo-ui-panelLayout {
-       position: static;
-       overflow: visible;
-       -webkit-transform: none;
-       transform: none;
-}
-
-#preferences .oo-ui-menuLayout .oo-ui-panelLayout-framed .oo-ui-panelLayout-framed {
-       border-width: 0;
-       border-radius: 0;
-       box-shadow: none;
-       padding-left: 0;
-       padding-right: 0;
-}
-
-.mw-prefs-faketabs > .oo-ui-menuLayout > .oo-ui-menuLayout-menu a {
-       color: inherit;
-       text-decoration: none;
-}
-
-/* Adjust the borders when JS is disabled: frame each prefsection instead of the
- * whole tabLayout wrapper */
-.client-nojs #preferences .oo-ui-menuLayout .oo-ui-panelLayout-framed .oo-ui-panelLayout-framed {
-       border-color: #c8ccd1;
-       border-width: 1px 0 0;
-}
-
-.client-nojs .mw-prefs-faketabs {
-       border-width: 0;
-       border-radius: 0;
-       box-shadow: none;
-}
-
-.client-nojs .mw-prefs-faketabs > .oo-ui-menuLayout > .oo-ui-menuLayout-content > .oo-ui-stackLayout {
-       margin-bottom: 1em;
-}
-
-/* Hide the tab menu when JS is disabled as we can't use this feature */
-.client-nojs .mw-prefs-faketabs > .oo-ui-menuLayout > .oo-ui-menuLayout-menu {
-       display: none;
-}
-
-.client-nojs #preferences .oo-ui-panelLayout-framed .oo-ui-panelLayout-framed:last-child {
-       padding-bottom: 0;
-       margin-bottom: 0;
-}
-
-/* Hide top level legends when JS is enabled, as they will not be visible
- * when the real tabLayout is built */
-.client-js #preferences .oo-ui-tabPanelLayout > fieldset > legend {
-       display: none;
-}
-
-.client-js #preferences .oo-ui-tabPanelLayout {
-       padding-top: 0.5em;
-}
-
-.client-js #preferences .oo-ui-panelLayout-framed .oo-ui-panelLayout-framed {
-       margin-left: 0;
-       margin-bottom: 0;
-       padding: 0;
-       border-width: 0;
-       border-radius: 0;
-       box-shadow: none;
-}
-
-.client-js #preferences > .oo-ui-panelLayout > .oo-ui-fieldsetLayout > .oo-ui-fieldsetLayout-header {
-       margin-bottom: 1em;
-}
-
-/* Make the "Basic information" section more compact */
-/* OOUI's `align: 'left'` for FieldLayouts sucks, so we do our own */
-#mw-htmlform-info > .oo-ui-fieldLayout-align-top > .oo-ui-fieldLayout-body > .oo-ui-fieldLayout-header {
-       width: 20%;
-       display: inline-block;
-       vertical-align: middle;
-       padding: 0;
-}
-
-#mw-htmlform-info > .oo-ui-fieldLayout-align-top .oo-ui-fieldLayout-help {
-       margin-right: 0;
-}
-
-#mw-htmlform-info > .oo-ui-fieldLayout.oo-ui-fieldLayout-align-top > .oo-ui-fieldLayout-body > .oo-ui-fieldLayout-field {
-       width: 80%;
-       display: inline-block;
-       vertical-align: middle;
-}
-
-/* Expand the dropdown and textfield of "Time zone" field to the */
-/* usual maximum width and display them on separate lines. */
-#wpTimeCorrection .oo-ui-dropdownInputWidget,
-#wpTimeCorrection .oo-ui-textInputWidget {
-       display: block;
-       max-width: 50em;
-}
-
-#wpTimeCorrection .oo-ui-textInputWidget {
-       margin-top: 0.5em;
-}
-
-/* HACK: expand width of gadget descriptions.
- * This should be moved to the Gadgets extension */
-#mw-htmlform-gadgets .oo-ui-fieldLayout.oo-ui-fieldLayout-align-inline > .oo-ui-fieldLayout-body {
-       max-width: none;
-}
diff --git a/resources/src/mediawiki.special.preferences.styles.ooui.less b/resources/src/mediawiki.special.preferences.styles.ooui.less
new file mode 100644 (file)
index 0000000..ecf6887
--- /dev/null
@@ -0,0 +1,159 @@
+@import 'mediawiki.mixins';
+
+/* Reuses colors from mediawiki.legacy/shared.css */
+.mw-email-not-authenticated .oo-ui-labelWidget,
+.mw-email-none .oo-ui-labelWidget {
+       background-color: #fdf1d1;
+       color: #000;
+       border: 1px solid #fde29b;
+       padding: 0.5em;
+}
+/* Authenticated email field has its own class too. Unstyled by default */
+/*
+.mw-email-authenticated .oo-ui-labelWidget { }
+*/
+
+/* This is needed because add extra buttons in a weird way */
+.mw-prefs-buttons .mw-htmlform-submit-buttons {
+       display: inline;
+       margin: 0;
+}
+
+.mw-prefs-buttons {
+       margin-top: 1em;
+}
+
+#prefcontrol {
+       margin-right: 0.5em;
+}
+
+/*
+ * Hide, but keep accessible for screen-readers.
+ */
+.client-js .mw-navigation-hint {
+       overflow: hidden;
+       height: 0;
+       zoom: 1;
+}
+
+/* Override OOUI styles so that dropdowns near the bottom of the form don't get clipped,
+ * e.g.'Appearance' / 'Threshold for stub link formatting'. This is hacky and bad, it would be
+ * better solved by setting overlays for the widgets, but we can't do it from PHP... */
+#preferences .oo-ui-panelLayout {
+       position: static;
+       overflow: visible;
+       .transform( none );
+}
+
+#preferences .oo-ui-menuLayout .oo-ui-panelLayout-framed .oo-ui-panelLayout-framed {
+       border-width: 0;
+       border-radius: 0;
+       padding-left: 0;
+       padding-right: 0;
+       box-shadow: none;
+}
+
+.mw-prefs-faketabs > .oo-ui-menuLayout > .oo-ui-menuLayout-menu a {
+       color: inherit;
+       text-decoration: none;
+}
+
+/* Disabled JavaScript */
+.client-nojs {
+       /* Adjust the borders: frame each prefsection instead of the
+        * whole tabLayout wrapper */
+       #preferences .oo-ui-menuLayout .oo-ui-panelLayout-framed .oo-ui-panelLayout-framed:first-child {
+               border-color: #c8ccd1;
+               border-width: 1px 0 0;
+       }
+
+       #preferences .oo-ui-panelLayout-framed .oo-ui-panelLayout-framed:last-child {
+               padding-bottom: 0;
+               margin-bottom: 0;
+       }
+
+       /* Fake Tabs to address reflow */
+       .mw-prefs-faketabs {
+               border-width: 0;
+               border-radius: 0;
+               .box-shadow( none );
+
+               > .oo-ui-menuLayout > .oo-ui-menuLayout-content > .oo-ui-stackLayout {
+                       margin-bottom: 1em;
+               }
+
+               /* Hide the tab menu when JS is disabled as we can't use this feature */
+               > .oo-ui-menuLayout > .oo-ui-menuLayout-menu {
+                       display: none;
+               }
+       }
+}
+
+/* Enabled JavaScript
+ * Hide top level legends when JS is enabled, as they will not be visible
+ * when the real tabLayout is built */
+.client-js #preferences {
+       .oo-ui-tabPanelLayout {
+               padding-top: 0.5em;
+
+               & > fieldset > legend {
+                       display: none;
+               }
+       }
+
+       .oo-ui-panelLayout-framed .oo-ui-panelLayout-framed {
+               margin-top: 2.286em; /* equals `32px` at `font-size: 14px;` */
+               margin-bottom: 0;
+               border-width: 0;
+               border-radius: 0;
+               padding: 0;
+               box-shadow: none;
+
+               &:first-child {
+                       margin-top: 0.85714286em;
+               }
+       }
+
+       > .oo-ui-panelLayout > .oo-ui-fieldsetLayout > .oo-ui-fieldsetLayout-header {
+               margin-bottom: 1em;
+       }
+}
+
+/* Make the "Basic information" section more compact */
+/* OOUI's `align: 'left'` for FieldLayouts sucks, so we do our own */
+#mw-htmlform-info {
+       > .oo-ui-fieldLayout-align-top > .oo-ui-fieldLayout-body > .oo-ui-fieldLayout-header {
+               display: inline-block;
+               width: 20%;
+               padding: 0;
+               vertical-align: middle;
+       }
+
+       > .oo-ui-fieldLayout-align-top .oo-ui-fieldLayout-help {
+               margin-right: 0;
+       }
+
+       > .oo-ui-fieldLayout.oo-ui-fieldLayout-align-top > .oo-ui-fieldLayout-body > .oo-ui-fieldLayout-field {
+               display: inline-block;
+               width: 80%;
+               vertical-align: middle;
+       }
+}
+
+/* Expand the dropdown and textfield of "Time zone" field to the */
+/* usual maximum width and display them on separate lines. */
+#wpTimeCorrection .oo-ui-dropdownInputWidget,
+#wpTimeCorrection .oo-ui-textInputWidget {
+       display: block;
+       max-width: 50em;
+}
+
+#wpTimeCorrection .oo-ui-textInputWidget {
+       margin-top: 0.5em;
+}
+
+/* HACK: expand width of gadget descriptions.
+ * This should be moved to the Gadgets extension */
+#mw-htmlform-gadgets .oo-ui-fieldLayout.oo-ui-fieldLayout-align-inline > .oo-ui-fieldLayout-body {
+       max-width: none;
+}
index 2bbeabf..2340f9c 100644 (file)
@@ -26,8 +26,8 @@
         * @cfg {boolean} [showMissing=true] Show missing pages
         * @cfg {boolean} [addQueryInput=true] Add exact user's input query to results
         * @cfg {boolean} [excludeCurrentPage] Exclude the current page from suggestions
-        * @cfg {boolean} [validateTitle=true] Whether the input must be a valid title (if set to true,
-        *  the widget will marks itself red for invalid inputs, including an empty query).
+        * @cfg {boolean} [validateTitle=true] Whether the input must be a valid title
+        * @cfg {boolean} [required=false] Whether the input must not be empty
         * @cfg {Object} [cache] Result cache which implements a 'set' method, taking keyed values as an argument
         * @cfg {mw.Api} [api] API object to use, creates a default mw.Api instance if not specified
         */
         * @return {boolean} The query is valid
         */
        mw.widgets.TitleWidget.prototype.isQueryValid = function () {
-               return this.validateTitle ? !!this.getMWTitle() : true;
+               if ( !this.validateTitle ) {
+                       return true;
+               }
+               if ( !this.required && this.getQueryValue() === '' ) {
+                       return true;
+               }
+               return !!this.getMWTitle();
        };
 
 }( jQuery, mediaWiki ) );
index 1e008ee..4730005 100644 (file)
@@ -16,7 +16,9 @@ class FirejailCommandIntegrationTest extends PHPUnit\Framework\TestCase {
 
        public function setUp() {
                parent::setUp();
-               if ( Shell::command( 'which', 'firejail' )->execute()->getExitCode() ) {
+               if ( Shell::isDisabled() ) {
+                       $this->markTestSkipped( 'shelling out is disabled' );
+               } elseif ( Shell::command( 'which', 'firejail' )->execute()->getExitCode() ) {
                        $this->markTestSkipped( 'firejail not installed' );
                } elseif ( wfIsWindows() ) {
                        $this->markTestSkipped( 'test supports POSIX environments only' );
index 0fae63a..0b12c84 100644 (file)
@@ -2272,6 +2272,83 @@ hi
 <link rel="mw:PageProp/Category" href="./Category:Ho" />
 !! end
 
+!! test
+Paragraph wrapping following unclosed table
+!! options
+parsoid=wt2html,html2html
+!! wikitext
+{|
+|-
+
+{|
+| x
+|}
+
+a
+
+b
+
+c
+!! html/php+tidy
+<table>
+
+
+</table><table>
+<tbody><tr>
+<td>x
+</td></tr></tbody></table>
+<p>a
+</p><p>b
+</p><p>c
+</p>
+!! html/parsoid
+<table data-parsoid='{"autoInsertedEnd":true}'>
+<tbody><tr class="mw-empty-elt" data-parsoid='{"startTagSrc":"|-"}'></tr>
+
+</tbody></table><table>
+<tbody><tr data-parsoid='{"autoInsertedStart":true}'><td>x</td></tr>
+</tbody></table>
+
+<p>a</p>
+
+<p>b</p>
+
+<p>c</p>
+!! end
+
+!! test
+Paragraph wrapping suppressed in html p
+!! options
+parsoid=wt2html,html2html
+!! wikitext
+<p>
+
+
+hi
+
+
+
+</p>
+!! html/php+tidy
+<p>
+
+
+hi
+
+
+
+</p>
+!! html/parsoid
+<p data-parsoid='{"stx":"html"}'>
+
+
+hi
+
+
+
+</p>
+!! end
+
 ###
 ### Preformatted text
 ###
 a
 <table></table>
 !! html/parsoid
-<p data-parsoid='{"fostered":true,"autoInsertedEnd":true}'>a</p><table>
-<tbody><tr data-parsoid='{"startTagSrc":"|-","autoInsertedEnd":true}'>
-
-</tr></tbody></table>
+<span data-parsoid='{"fostered":true,"autoInsertedEnd":true,"autoInsertedStart":true}'>
+a
+</span><table>
+<tbody><tr class="mw-empty-elt" data-parsoid='{"startTagSrc":"|-"}'></tr></tbody></table>
 !! end
 
 !! test
@@ -12786,16 +12863,22 @@ Templates: Block Tags: 2. Back-to-back template uses
 
 !!end
 
-# This is an edge case relating to paragraph wrapping.
-!!test
+## This is an edge case relating to paragraph wrapping.
+## Note that Parsoid fails to match Remex because it's using the closing tag
+## as a heuristic to determine if it's in a block, rather than SAX based events.
+!! test
 Templates: Correctly encapsulate templates producing </p> tag without a corresponding <p> tag
 !! wikitext
 {{echo|a
 b</p>}}
+!! html/php+tidy
+<p>a
+</p><p>
+b</p><p class="mw-empty-elt"></p>
 !! html/parsoid
-<p about="#mwt1" typeof="mw:Transclusion" data-mw='{"parts":[{"template":{"target":{"wt":"echo","href":"./Template:Echo"},"params":{"1":{"wt":"a\nb&lt;/p>"}},"i":0}}]}'>a
-b</p>
-!!end
+<p about="#mwt1" typeof="mw:Transclusion" data-mw='{"parts":[{"template":{"target":{"wt":"echo","href":"./Template:Echo"},"params":{"1":{"wt":"a\nb&lt;/p>"}},"i":0}}]}'>a</p><span about="#mwt1">
+</span><span about="#mwt1">b</span><p about="#mwt1" data-parsoid='{"autoInsertedStart":true,"stx":"html"}'></p>
+!! end
 
 !!test
 Templates: Links: 1. Simple example
@@ -13164,13 +13247,13 @@ parsoid=wt2html,wt2wt
 <link rel="mw:PageProp/Category" href="./Category:Bar1"><link rel="mw:PageProp/Category" href="./Category:Bar2"><table><tbody><tr><td>foo</td></tr></tbody></table>
 !!end
 
-!!test
+!! test
 Templates: Wiki Tables: 1a. Fostering of entire template content
 !! wikitext
 {|
 {{echo|a}}
 |}
-!! html
+!! html/php
 <table>
 a
 <tr><td></td></tr></table>
 a
 <table><tbody><tr><td></td></tr></tbody></table>
 !! html/parsoid
-<p about="#mwt2" typeof="mw:Transclusion" data-parsoid='{"fostered":true,"autoInsertedEnd":true,"firstWikitextNode":"TABLE","pi":[[{"k":"1"}]]}' data-mw='{"parts":["{|\n",{"template":{"target":{"wt":"echo","href":"./Template:Echo"},"params":{"1":{"wt":"a"}},"i":0}},"\n|}"]}'>a</p><table about="#mwt2">
+<span about="#mwt2" typeof="mw:Transclusion" data-parsoid='{"fostered":true,"autoInsertedEnd":true,"autoInsertedStart":true,"firstWikitextNode":"TABLE","pi":[[{"k":"1"}]]}' data-mw='{"parts":["{|\n",{"template":{"target":{"wt":"echo","href":"./Template:Echo"},"params":{"1":{"wt":"a"}},"i":0}},"\n|}"]}'>a</span><table about="#mwt2">
 
 </table>
 !! end
@@ -13216,14 +13299,14 @@ foo
 </table>
 !! end
 
-!!test
+!! test
 Templates: Wiki Tables: 2. Fostering of partial template content
 !! wikitext
 {|
 {{echo|a
 <div>b</div>}}
 |}
-!! html
+!! html/php
 <table>
 a
 <div>b</div>
 <div>b</div><table>
 <tbody><tr><td></td></tr></tbody></table>
 !! html/parsoid
-<p about="#mwt2" typeof="mw:Transclusion" data-parsoid='{"fostered":true,"autoInsertedEnd":true,"firstWikitextNode":"TABLE","pi":[[{"k":"1"}]]}' data-mw='{"parts":["{|\n",{"template":{"target":{"wt":"echo","href":"./Template:Echo"},"params":{"1":{"wt":"a\n&lt;div>b&lt;/div>"}},"i":0}},"\n|}"]}'>a</p><div about="#mwt2">b</div><table about="#mwt2">
+<span about="#mwt2" typeof="mw:Transclusion" data-parsoid='{"fostered":true,"autoInsertedEnd":true,"autoInsertedStart":true,"firstWikitextNode":"TABLE","pi":[[{"k":"1"}]]}' data-mw='{"parts":["{|\n",{"template":{"target":{"wt":"echo","href":"./Template:Echo"},"params":{"1":{"wt":"a\n&lt;div>b&lt;/div>"}},"i":0}},"\n|}"]}'>a</span><div about="#mwt2">b</div><table about="#mwt2">
 
 
 </table>
@@ -23415,7 +23498,12 @@ Line two
 
 !! end
 
-# FIXME: Why does/should the blockquote+div combo suppress p-wrapping here?
+## This is a corner case interaction between the paragraph wrapping in the
+## php parser's BlockLevelPass and Remex.  `doBlockLevels` has a notion of
+## some tags which close paragraphs (and thus prevent wrapping on their line),
+## of which "div" is one, but do p-wrapping inside them.  These are referred
+## to as "never suppressing".  Remex, for its part, doesn't traverse into
+## "div"s to p-wrap.  Hence, we only get this partial wrapping.
 !! test
 Paragraphs inside blockquotes/divs (no extra line breaks)
 !! wikitext
index f363d83..e8ab412 100644 (file)
@@ -1043,7 +1043,16 @@ abstract class MediaWikiTestCase extends PHPUnit\Framework\TestCase {
         * @since 1.18
         */
        public function dbPrefix() {
-               return $this->db->getType() == 'oracle' ? self::ORA_DB_PREFIX : self::DB_PREFIX;
+               return self::getTestPrefixFor( $this->db );
+       }
+
+       /**
+        * @param IDatabase $db
+        * @return string
+        * @since 1.32
+        */
+       public static function getTestPrefixFor( IDatabase $db ) {
+               return $db->getType() == 'oracle' ? self::ORA_DB_PREFIX : self::DB_PREFIX;
        }
 
        /**
@@ -1226,33 +1235,95 @@ abstract class MediaWikiTestCase extends PHPUnit\Framework\TestCase {
        }
 
        /**
-        * Setups a database with the given prefix.
+        * Prepares the given database connection for usage in the context of usage tests.
+        * This sets up clones database tables and changes the table prefix as appropriate.
+        * If the database connection already has cloned tables, calling this method has no
+        * effect. The tables are not re-cloned or reset in that case.
+        *
+        * @param IMaintainableDatabase $db
+        */
+       protected function prepareConnectionForTesting( IMaintainableDatabase $db ) {
+               if ( !self::$dbSetup ) {
+                       throw new LogicException(
+                               'Cannot use prepareConnectionForTesting()'
+                               . ' if the test case is not defined to use the database!'
+                       );
+               }
+
+               if ( isset( $db->_originalTablePrefix ) ) {
+                       // The DB connection was already prepared for testing.
+                       return;
+               }
+
+               $testPrefix = self::getTestPrefixFor( $db );
+               $oldPrefix = $db->tablePrefix();
+
+               $tablesCloned = self::listTables( $db );
+
+               if ( $oldPrefix === $testPrefix ) {
+                       // The database connection already has the test prefix, but presumably not
+                       // the cloned tables. This is the typical case, since the LBFactory will
+                       // have the prefix set during testing, but LoadBalancers will still return
+                       // connections that don't have the cloned table structure.
+                       $oldPrefix = self::$oldTablePrefix;
+               }
+
+               $dbClone = new CloneDatabase( $db, $tablesCloned, $testPrefix, $oldPrefix );
+               $dbClone->useTemporaryTables( self::$useTemporaryTables );
+
+               $db->_originalTablePrefix = $oldPrefix;
+
+               if ( ( $db->getType() == 'oracle' || !self::$useTemporaryTables ) && self::$reuseDB ) {
+                       throw new LogicException( 'Cannot clone database tables' );
+               } else {
+                       $dbClone->cloneTableStructure();
+               }
+       }
+
+       /**
+        * Setups a database with cloned tables using the given prefix.
         *
         * If reuseDB is true and certain conditions apply, it will just change the prefix.
         * Otherwise, it will clone the tables and change the prefix.
         *
-        * Clones all tables in the given database (whatever database that connection has
-        * open), to versions with the test prefix.
-        *
         * @param IMaintainableDatabase $db Database to use
-        * @param string $prefix Prefix to use for test tables
+        * @param string $prefix Prefix to use for test tables. If not given, the prefix is determined
+        *        automatically for $db.
         * @return bool True if tables were cloned, false if only the prefix was changed
         */
-       protected static function setupDatabaseWithTestPrefix( IMaintainableDatabase $db, $prefix ) {
-               $tablesCloned = self::listTables( $db );
-               $dbClone = new CloneDatabase( $db, $tablesCloned, $prefix );
-               $dbClone->useTemporaryTables( self::$useTemporaryTables );
-
-               $db->_originalTablePrefix = $db->tablePrefix();
+       protected static function setupDatabaseWithTestPrefix(
+               IMaintainableDatabase $db,
+               $prefix = null
+       ) {
+               if ( $prefix === null ) {
+                       $prefix = self::getTestPrefixFor( $db );
+               }
 
                if ( ( $db->getType() == 'oracle' || !self::$useTemporaryTables ) && self::$reuseDB ) {
-                       CloneDatabase::changePrefix( $prefix );
-
+                       $db->tablePrefix( $prefix );
                        return false;
-               } else {
+               }
+
+               if ( !isset( $db->_originalTablePrefix ) ) {
+                       $oldPrefix = $db->tablePrefix();
+
+                       if ( $oldPrefix === $prefix ) {
+                               // table already has the correct prefix, but presumably no cloned tables
+                               $oldPrefix = self::$oldTablePrefix;
+                       }
+
+                       $db->tablePrefix( $oldPrefix );
+                       $tablesCloned = self::listTables( $db );
+                       $dbClone = new CloneDatabase( $db, $tablesCloned, $prefix, $oldPrefix );
+                       $dbClone->useTemporaryTables( self::$useTemporaryTables );
+
                        $dbClone->cloneTableStructure();
-                       return true;
+
+                       $db->tablePrefix( $prefix );
+                       $db->_originalTablePrefix = $oldPrefix;
                }
+
+               return true;
        }
 
        /**
@@ -1271,6 +1342,10 @@ abstract class MediaWikiTestCase extends PHPUnit\Framework\TestCase {
                if ( self::isUsingExternalStoreDB() ) {
                        self::setupExternalStoreTestDBs( $testPrefix );
                }
+
+               // NOTE: Change the prefix in the LBFactory and $wgDBprefix, to prevent
+               // *any* database connections to operate on live data.
+               CloneDatabase::changePrefix( $testPrefix );
        }
 
        /**
@@ -1325,19 +1400,12 @@ abstract class MediaWikiTestCase extends PHPUnit\Framework\TestCase {
        /**
         * Clones the External Store database(s) for testing
         *
-        * @param string $testPrefix Prefix for test tables
+        * @param string|null $testPrefix Prefix for test tables. Will be determined automatically
+        *        if not given.
         */
-       protected static function setupExternalStoreTestDBs( $testPrefix ) {
+       protected static function setupExternalStoreTestDBs( $testPrefix = null ) {
                $connections = self::getExternalStoreDatabaseConnections();
                foreach ( $connections as $dbw ) {
-                       // Hack: cloneTableStructure sets $wgDBprefix to the unit test
-                       // prefix,.  Even though listTables now uses tablePrefix, that
-                       // itself is populated from $wgDBprefix by default.
-
-                       // We have to set it back, or we won't find the original 'blobs'
-                       // table to copy.
-
-                       $dbw->tablePrefix( self::$oldTablePrefix );
                        self::setupDatabaseWithTestPrefix( $dbw, $testPrefix );
                }
        }
@@ -1716,6 +1784,29 @@ abstract class MediaWikiTestCase extends PHPUnit\Framework\TestCase {
                return $tables;
        }
 
+       /**
+        * Copy test data from one database connection to another.
+        *
+        * This should only be used for small data sets.
+        *
+        * @param IDatabase $source
+        * @param IDatabase $target
+        */
+       public function copyTestData( IDatabase $source, IDatabase $target ) {
+               $tables = self::listOriginalTables( $source, 'unprefixed' );
+
+               foreach ( $tables as $table ) {
+                       $res = $source->select( $table, '*', [], __METHOD__ );
+                       $allRows = [];
+
+                       foreach ( $res as $row ) {
+                               $allRows[] = (array)$row;
+                       }
+
+                       $target->insert( $table, $allRows, __METHOD__, [ 'IGNORE' ] );
+               }
+       }
+
        /**
         * @throws MWException
         * @since 1.18
index dfee8c3..093cb07 100644 (file)
@@ -314,6 +314,8 @@ class MediaWikiServicesTest extends MediaWikiTestCase {
                        'SiteStore' => [ 'SiteStore', SiteStore::class ],
                        'SiteLookup' => [ 'SiteLookup', SiteLookup::class ],
                        'StatsdDataFactory' => [ 'StatsdDataFactory', IBufferingStatsdDataFactory::class ],
+                       'PerDbNameStatsdDataFactory' =>
+                               [ 'PerDbNameStatsdDataFactory', IBufferingStatsdDataFactory::class ],
                        'InterwikiLookup' => [ 'InterwikiLookup', InterwikiLookup::class ],
                        'EventRelayerGroup' => [ 'EventRelayerGroup', EventRelayerGroup::class ],
                        'SearchEngineFactory' => [ 'SearchEngineFactory', SearchEngineFactory::class ],
index c984142..f03d403 100644 (file)
@@ -159,8 +159,8 @@ class McrWriteBothRevisionStoreDbTest extends RevisionStoreDbTestBase {
                                                'role_name' => $db->addQuotes( 'main' ),
                                                'content_size' => 'slots.rev_len',
                                                'content_sha1' => 'slots.rev_sha1',
-                                               'content_address' =>
-                                                       'CONCAT(' . $db->addQuotes( 'tt:' ) . ',slots.rev_text_id)',
+                                               'content_address' => $db->buildConcat( [
+                                                       $db->addQuotes( 'tt:' ), 'slots.rev_text_id' ] ),
                                                'model_name' => 'slots.rev_content_model',
                                        ]
                                ),
index 2337805..1d504de 100644 (file)
@@ -156,7 +156,7 @@ class NoContentModelRevisionStoreDbTest extends RevisionStoreDbTestBase {
                                                'content_size' => 'slots.rev_len',
                                                'content_sha1' => 'slots.rev_sha1',
                                                'content_address' =>
-                                                       'CONCAT(' . $db->addQuotes( 'tt:' ) . ',slots.rev_text_id)',
+                                                       $db->buildConcat( [ $db->addQuotes( 'tt:' ), 'slots.rev_text_id' ] ),
                                                'model_name' => 'NULL',
                                        ]
                                ),
index a27d2bb..7cc3131 100644 (file)
@@ -130,7 +130,7 @@ class PreMcrRevisionStoreDbTest extends RevisionStoreDbTestBase {
                                                'content_size' => 'slots.rev_len',
                                                'content_sha1' => 'slots.rev_sha1',
                                                'content_address' =>
-                                                       'CONCAT(' . $db->addQuotes( 'tt:' ) . ',slots.rev_text_id)',
+                                                       $db->buildConcat( [ $db->addQuotes( 'tt:' ), 'slots.rev_text_id' ] ),
                                                'model_name' => 'slots.rev_content_model',
                                        ]
                                ),
index cf605c1..d6b43e5 100644 (file)
@@ -190,32 +190,38 @@ class LoadBalancerTest extends MediaWikiTestCase {
 
        private function assertWriteAllowed( Database $db ) {
                $table = $db->tableName( 'some_table' );
+               // Trigger a transaction so that rollback() will remove all the tables.
+               // Don't do this for MySQL/Oracle as they auto-commit transactions for DDL
+               // statements such as CREATE TABLE.
+               $useAtomicSection = in_array( $db->getType(), [ 'sqlite', 'postgres', 'mssql' ], true );
                try {
                        $db->dropTable( 'some_table' ); // clear for sanity
+                       $this->assertNotEquals( $db::STATUS_TRX_ERROR, $db->trxStatus() );
 
-                       // Trigger DBO_TRX to create a transaction so the flush below will
-                       // roll everything here back in sqlite. But don't actually do the
-                       // code below inside an atomic section becaue MySQL and Oracle
-                       // auto-commit transactions for DDL statements like CREATE TABLE.
-                       $db->startAtomic( __METHOD__ );
-                       $db->endAtomic( __METHOD__ );
-
+                       if ( $useAtomicSection ) {
+                               $db->startAtomic( __METHOD__ );
+                       }
                        // Use only basic SQL and trivial types for these queries for compatibility
                        $this->assertNotSame(
                                false,
                                $db->query( "CREATE TABLE $table (id INT, time INT)", __METHOD__ ),
                                "table created"
                        );
+                       $this->assertNotEquals( $db::STATUS_TRX_ERROR, $db->trxStatus() );
                        $this->assertNotSame(
                                false,
                                $db->query( "DELETE FROM $table WHERE id=57634126", __METHOD__ ),
                                "delete query"
                        );
+                       $this->assertNotEquals( $db::STATUS_TRX_ERROR, $db->trxStatus() );
                } finally {
-                       // Drop the table to clean up, ignoring any error.
-                       $db->query( "DROP TABLE $table", __METHOD__, true );
-                       // Rollback the DBO_TRX transaction for sqlite's benefit.
+                       if ( !$useAtomicSection ) {
+                               // Drop the table to clean up, ignoring any error.
+                               $db->dropTable( 'some_table' );
+                       }
+                       // Rollback the atomic section for sqlite's benefit.
                        $db->rollback( __METHOD__, 'flush' );
+                       $this->assertNotEquals( $db::STATUS_TRX_ERROR, $db->trxStatus() );
                }
        }
 
index c12882b..8f4aae3 100644 (file)
@@ -440,6 +440,7 @@ class DatabaseTest extends PHPUnit\Framework\TestCase {
                        'numFields', 'numRows',
                        'open',
                        'strencode',
+                       'tableExists'
                ];
                $db = $this->getMockBuilder( Database::class )
                        ->disableOriginalConstructor()