Merge "Fix doc in maintenance/findHooks.php"
authorjenkins-bot <jenkins-bot@gerrit.wikimedia.org>
Wed, 22 May 2019 19:58:51 +0000 (19:58 +0000)
committerGerrit Code Review <gerrit@wikimedia.org>
Wed, 22 May 2019 19:58:51 +0000 (19:58 +0000)
72 files changed:
RELEASE-NOTES-1.34
autoload.php
docs/extension.schema.v1.json
docs/extension.schema.v2.json
includes/DefaultSettings.php
includes/EditPage.php
includes/ServiceWiring.php
includes/Setup.php
includes/api/i18n/fr.json
includes/changes/ChangesList.php
includes/content/ContentHandler.php
includes/db/MWLBFactory.php
includes/diff/DifferenceEngine.php
includes/diff/TextSlotDiffRenderer.php
includes/externalstore/ExternalStoreDB.php
includes/import/WikiRevision.php
includes/installer/i18n/vi.json
includes/libs/objectcache/APCBagOStuff.php
includes/libs/objectcache/APCUBagOStuff.php
includes/libs/objectcache/RESTBagOStuff.php
includes/libs/rdbms/TransactionProfiler.php
includes/libs/rdbms/database/Database.php
includes/libs/rdbms/database/IDatabase.php
includes/libs/rdbms/database/utils/GeneralizedSql.php [new file with mode: 0644]
includes/libs/rdbms/exception/DBQueryDisconnectedError.php [new file with mode: 0644]
includes/media/BitmapHandler.php
includes/page/WikiPage.php
includes/parser/Parser.php
includes/parser/ParserFactory.php
includes/resourceloader/ResourceLoaderModule.php
includes/skins/Skin.php
includes/specials/SpecialWatchlist.php
includes/specials/forms/PreferencesFormOOUI.php
includes/title/NamespaceInfo.php
includes/watcheditem/WatchedItemQueryService.php
languages/i18n/ban.json
languages/i18n/be-tarask.json
languages/i18n/bjn.json
languages/i18n/bn.json
languages/i18n/ee.json
languages/i18n/eo.json
languages/i18n/eu.json
languages/i18n/exif/vi.json
languages/i18n/fr.json
languages/i18n/fy.json
languages/i18n/hr.json
languages/i18n/ia.json
languages/i18n/ja.json
languages/i18n/ko.json
languages/i18n/lb.json
languages/i18n/mk.json
languages/i18n/nds-nl.json
languages/i18n/nqo.json
languages/i18n/pt-br.json
languages/i18n/pt.json
languages/i18n/ro.json
languages/i18n/ru.json
languages/i18n/sh.json
languages/i18n/sr-ec.json
languages/i18n/sr-el.json
languages/i18n/th.json
languages/i18n/uk.json
languages/i18n/vi.json
resources/src/jquery.tablesorter.styles/jquery.tablesorter.styles.less
tests/phpunit/MediaWikiTestCase.php
tests/phpunit/includes/EditPageTest.php
tests/phpunit/includes/diff/TextSlotDiffRendererTest.php
tests/phpunit/includes/objectcache/RESTBagOStuffTest.php
tests/phpunit/includes/parser/ParserFactoryTest.php
tests/phpunit/includes/parser/ParserTest.php [new file with mode: 0644]
tests/phpunit/includes/title/NamespaceInfoTest.php
tests/selenium/wdio.conf.js

index d9ac7bf..7a74427 100644 (file)
@@ -38,7 +38,9 @@ For notes on 1.33.x and older releases, see HISTORY.
 * …
 
 ==== Removed configuration ====
-* …
+* $wgWikiDiff2MovedParagraphDetectionCutoff — If you still want a custom change
+  size threshold, please specify in php.ini, using the configuration variable
+  wikidiff2.moved_paragraph_detection_cutoff.
 
 === New user-facing features in 1.34 ===
 * …
@@ -173,6 +175,8 @@ because of Phabricator reports.
 * The LegacyHookPreAuthenticationProvider class, deprecated since its creation
   in 1.27, has been removed.
 * IP::isValidBlock(), deprecated in 1.30, has been removed.
+* WikiPage::prepareContentForEdit now doesn't accept an integer for $revision,
+  was deprecated in 1.25.
 * …
 
 === Deprecations in 1.34 ===
@@ -211,6 +215,8 @@ because of Phabricator reports.
 * The Block class is separated into Block (for blocks stored in the database),
   and SystemBlock (for temporary blocks created by the system). SystemBlock
   should be used when creating any temporary blocks.
+* Parser::$mConf is deprecated. It will be removed entirely in a later version.
+* Constructing Parser directly is deprecated. Obtain one from ParserFactory.
 
 === Other changes in 1.34 ===
 * …
index 275d20e..4c8f5a4 100644 (file)
@@ -1636,6 +1636,7 @@ $wgAutoloadLocalClasses = [
        'Wikimedia\\Rdbms\\DBError' => __DIR__ . '/includes/libs/rdbms/exception/DBError.php',
        'Wikimedia\\Rdbms\\DBExpectedError' => __DIR__ . '/includes/libs/rdbms/exception/DBExpectedError.php',
        'Wikimedia\\Rdbms\\DBMasterPos' => __DIR__ . '/includes/libs/rdbms/database/position/DBMasterPos.php',
+       'Wikimedia\\Rdbms\\DBQueryDisconnectedError' => __DIR__ . '/includes/libs/rdbms/exception/DBQueryDisconnectedError.php',
        'Wikimedia\\Rdbms\\DBQueryError' => __DIR__ . '/includes/libs/rdbms/exception/DBQueryError.php',
        'Wikimedia\\Rdbms\\DBQueryTimeoutError' => __DIR__ . '/includes/libs/rdbms/exception/DBQueryTimeoutError.php',
        'Wikimedia\\Rdbms\\DBReadOnlyError' => __DIR__ . '/includes/libs/rdbms/exception/DBReadOnlyError.php',
@@ -1654,6 +1655,7 @@ $wgAutoloadLocalClasses = [
        'Wikimedia\\Rdbms\\DatabaseSqlite' => __DIR__ . '/includes/libs/rdbms/database/DatabaseSqlite.php',
        'Wikimedia\\Rdbms\\FakeResultWrapper' => __DIR__ . '/includes/libs/rdbms/database/resultwrapper/FakeResultWrapper.php',
        'Wikimedia\\Rdbms\\Field' => __DIR__ . '/includes/libs/rdbms/field/Field.php',
+       'Wikimedia\\Rdbms\\GeneralizedSql' => __DIR__ . '/includes/libs/rdbms/database/utils/GeneralizedSql.php',
        'Wikimedia\\Rdbms\\IBlob' => __DIR__ . '/includes/libs/rdbms/encasing/IBlob.php',
        'Wikimedia\\Rdbms\\IDatabase' => __DIR__ . '/includes/libs/rdbms/database/IDatabase.php',
        'Wikimedia\\Rdbms\\ILBFactory' => __DIR__ . '/includes/libs/rdbms/lbfactory/ILBFactory.php',
index 36e2fe2..32946d3 100644 (file)
@@ -81,7 +81,7 @@
                                                "^ext-": {
                                                        "type": "string",
                                                        "description": "Required PHP extension.",
-                                                       "const": "*"
+                                                       "enum": ["*"]
                                                }
                                        }
                                },
index ed903f8..42b34b7 100644 (file)
@@ -88,7 +88,7 @@
                                                "^ext-": {
                                                        "type": "string",
                                                        "description": "Required PHP extension.",
-                                                       "const": "*"
+                                                       "enum": ["*"]
                                                }
                                        }
                                },
index 69da9c7..9efcfb4 100644 (file)
@@ -8497,6 +8497,7 @@ $wgExternalDiffEngine = false;
  * See $wgExternalDiffEngine.
  *
  * @since 1.30
+ * @deprecated since 1.34
  */
 $wgWikiDiff2MovedParagraphDetectionCutoff = 0;
 
index 7908fcc..47a8b5b 100644 (file)
@@ -1483,8 +1483,9 @@ class EditPage {
 
                $user = $this->context->getUser();
                $title = Title::newFromText( $preload );
+
                # Check for existence to avoid getting MediaWiki:Noarticletext
-               if ( $title === null || !$title->exists() || !$title->userCan( 'read', $user ) ) {
+               if ( !$this->isPageExistingAndViewable( $title, $user ) ) {
                        // TODO: somehow show a warning to the user!
                        return $handler->makeEmptyContent();
                }
@@ -1493,7 +1494,7 @@ class EditPage {
                if ( $page->isRedirect() ) {
                        $title = $page->getRedirectTarget();
                        # Same as before
-                       if ( $title === null || !$title->exists() || !$title->userCan( 'read', $user ) ) {
+                       if ( !$this->isPageExistingAndViewable( $title, $user ) ) {
                                // TODO: somehow show a warning to the user!
                                return $handler->makeEmptyContent();
                        }
@@ -1526,6 +1527,21 @@ class EditPage {
                return $content->preloadTransform( $title, $parserOptions, $params );
        }
 
+       /**
+        * Verify if a given title exists and the given user is allowed to view it
+        *
+        * @see EditPage::getPreloadedContent()
+        * @param Title|null $title
+        * @param User $user
+        * @return bool
+        * @throws Exception
+        */
+       private function isPageExistingAndViewable( $title, User $user ) {
+               $permissionManager = MediaWikiServices::getInstance()->getPermissionManager();
+
+               return $title && $title->exists() && $permissionManager->userCan( 'read', $user, $title );
+       }
+
        /**
         * Make sure the form isn't faking a user's credentials.
         *
@@ -1988,6 +2004,8 @@ ERROR;
                        }
                }
 
+               $permissionManager = MediaWikiServices::getInstance()->getPermissionManager();
+
                $changingContentModel = false;
                if ( $this->contentModel !== $this->mTitle->getContentModel() ) {
                        if ( !$config->get( 'ContentHandlerUseDB' ) ) {
@@ -2001,10 +2019,19 @@ ERROR;
                        // Make sure the user can edit the page under the new content model too
                        $titleWithNewContentModel = clone $this->mTitle;
                        $titleWithNewContentModel->setContentModel( $this->contentModel );
-                       if ( !$titleWithNewContentModel->userCan( 'editcontentmodel', $user )
-                               || !$titleWithNewContentModel->userCan( 'edit', $user )
+
+                       $canEditModel = $permissionManager->userCan(
+                               'editcontentmodel',
+                               $user,
+                               $titleWithNewContentModel
+                       );
+
+                       if (
+                               !$canEditModel
+                               || !$permissionManager->userCan( 'edit', $user, $titleWithNewContentModel )
                        ) {
                                $status->setResult( false, self::AS_NO_CHANGE_CONTENT_MODEL );
+
                                return $status;
                        }
 
@@ -2048,7 +2075,7 @@ ERROR;
 
                if ( $new ) {
                        // Late check for create permission, just in case *PARANOIA*
-                       if ( !$this->mTitle->userCan( 'create', $user ) ) {
+                       if ( !$permissionManager->userCan( 'create', $user, $this->mTitle ) ) {
                                $status->fatal( 'nocreatetext' );
                                $status->value = self::AS_NO_CREATE_PERMISSION;
                                wfDebug( __METHOD__ . ": no create permission\n" );
@@ -2672,7 +2699,7 @@ ERROR;
        protected function showCustomIntro() {
                if ( $this->editintro ) {
                        $title = Title::newFromText( $this->editintro );
-                       if ( $title instanceof Title && $title->exists() && $title->userCan( 'read' ) ) {
+                       if ( $this->isPageExistingAndViewable( $title, $this->context->getUser() ) ) {
                                // Added using template syntax, to take <noinclude>'s into account.
                                $this->context->getOutput()->addWikiTextAsContent(
                                        '<div class="mw-editintro">{{:' . $title->getFullText() . '}}</div>',
index 9b064ce..c9db5a8 100644 (file)
@@ -416,13 +416,22 @@ return [
        },
 
        'ParserFactory' => function ( MediaWikiServices $services ) : ParserFactory {
-               return new ParserFactory(
+               $options = new ServiceOptions( Parser::$constructorOptions,
+                       // 'class' and 'preprocessorClass'
                        $services->getMainConfig()->get( 'ParserConf' ),
+                       // Make sure to have defaults in case someone overrode ParserConf with something silly
+                       [ 'class' => Parser::class,
+                               'preprocessorClass' => Parser::getDefaultPreprocessorClass() ],
+                       // Plus a buch of actual config options
+                       $services->getMainConfig()
+               );
+
+               return new ParserFactory(
+                       $options,
                        $services->getMagicWordFactory(),
                        $services->getContentLanguage(),
                        wfUrlProtocols(),
                        $services->getSpecialPageFactory(),
-                       $services->getMainConfig(),
                        $services->getLinkRendererFactory(),
                        $services->getNamespaceInfo()
                );
index 071b7c6..a51cb83 100644 (file)
@@ -605,20 +605,6 @@ if ( $wgDebugToolbar && !$wgCommandLineMode ) {
 // re-created while taking into account any custom settings and extensions.
 MediaWikiServices::resetGlobalInstance( new GlobalVarConfig(), 'quick' );
 
-if ( $wgSharedDB && $wgSharedTables ) {
-       // Apply $wgSharedDB table aliases for the local LB (all non-foreign DB connections)
-       MediaWikiServices::getInstance()->getDBLoadBalancer()->setTableAliases(
-               array_fill_keys(
-                       $wgSharedTables,
-                       [
-                               'dbname' => $wgSharedDB,
-                               'schema' => $wgSharedSchema,
-                               'prefix' => $wgSharedPrefix
-                       ]
-               )
-       );
-}
-
 // Define a constant that indicates that the bootstrapping of the service locator
 // is complete.
 define( 'MW_SERVICE_BOOTSTRAP_COMPLETE', 1 );
@@ -694,6 +680,20 @@ if ( $wgMainWANCache === false ) {
        ];
 }
 
+if ( $wgSharedDB && $wgSharedTables ) {
+       // Apply $wgSharedDB table aliases for the local LB (all non-foreign DB connections)
+       MediaWikiServices::getInstance()->getDBLoadBalancer()->setTableAliases(
+               array_fill_keys(
+                       $wgSharedTables,
+                       [
+                               'dbname' => $wgSharedDB,
+                               'schema' => $wgSharedSchema,
+                               'prefix' => $wgSharedPrefix
+                       ]
+               )
+       );
+}
+
 Profiler::instance()->scopedProfileOut( $ps_default2 );
 
 $ps_misc = Profiler::instance()->scopedProfileIn( $fname . '-misc' );
index 51e17ff..6a41057 100644 (file)
@@ -35,7 +35,7 @@
                        "Epok"
                ]
        },
-       "apihelp-main-extended-description": "<div class=\"hlist plainlinks api-main-links\">\n* [[mw:Special:MyLanguage/API:Main_page|Documentation]]\n* [[mw:Special:MyLanguage/API:FAQ|FAQ]]\n* [https://lists.wikimedia.org/mailman/listinfo/mediawiki-api Liste de diffusion]\n* [https://lists.wikimedia.org/mailman/listinfo/mediawiki-api-announce Annonces de l’API]\n* [https://phabricator.wikimedia.org/maniphest/query/GebfyV4uCaLd/#R Bogues et demandes]\n</div>\n<strong>État :</strong> L’API MediaWiki est une interface stable et mature qui est supportée et améliorée de façon active. Bien que nous essayions de l’éviter, nous pouvons avoir parfois besoin de faire des modifications impactantes ; inscrivez-vous à [https://lists.wikimedia.org/pipermail/mediawiki-api-announce/ la liste de diffusion mediawiki-api-announce] pour être informé des mises à jour.\n\n<strong>Requêtes erronées :</strong> Si des requêtes erronées sont envoyées à l’API, un entête HTTP sera renvoyé avec la clé « MediaWiki-API-Error ». La valeur de cet entête et le code d’erreur renvoyé prendront la même valeur. Pour plus d’information, voyez [[mw:Special:MyLanguage/API:Errors_and_warnings|API: Errors and warnings]].\n\n<p class=\"mw-apisandbox-link\"><strong>Test :</strong> Pour faciliter le test des requêtes à l’API, voyez [[Special:ApiSandbox]].</p>",
+       "apihelp-main-extended-description": "<div class=\"hlist plainlinks api-main-links\">\n* [[mw:Special:MyLanguage/API:Main_page|Documentation]]\n* [[mw:Special:MyLanguage/API:FAQ|FAQ]]\n* [https://lists.wikimedia.org/mailman/listinfo/mediawiki-api Liste de diffusion]\n* [https://lists.wikimedia.org/mailman/listinfo/mediawiki-api-announce Annonces de l’API]\n* [https://phabricator.wikimedia.org/maniphest/query/GebfyV4uCaLd/#R Bogues et demandes]\n</div>\n<strong>État :</strong> L’API MediaWiki est une interface stable et mature qui est supportée et améliorée de façon active. Bien que nous essayions de l’éviter, nous pouvons avoir parfois besoin de faire des modifications impactantes ; inscrivez-vous à [https://lists.wikimedia.org/pipermail/mediawiki-api-announce/ la liste de diffusion mediawiki-api-announce] pour être informé des mises à jour.\n\n<strong>Requêtes erronées :</strong> Si des requêtes erronées sont envoyées à l’API, un entête HTTP sera renvoyé avec la clé « MediaWiki-API-Error ». La valeur de cet entête et le code d’erreur renvoyé prendront la même valeur. Pour plus d’information, voyez [[mw:Special:MyLanguage/API:Errors_and_warnings|API:Errors and warnings]].\n\n<p class=\"mw-apisandbox-link\"><strong>Test :</strong> Pour faciliter le test des requêtes à l’API, voyez [[Special:ApiSandbox]].</p>",
        "apihelp-main-param-action": "Quelle action effectuer.",
        "apihelp-main-param-format": "Le format de sortie.",
        "apihelp-main-param-maxlag": "La latence maximale peut être utilisée quand MédiaWiki est installé sur un cluster de base de données répliqué. Pour éviter des actions provoquant un supplément de latence de réplication de site, ce paramètre peut faire attendre le client jusqu’à ce que la latence de réplication soit inférieure à une valeur spécifiée. En cas de latence excessive, le code d’erreur <samp>maxlag</samp> est renvoyé avec un message tel que <samp>Attente de $host : $lag secondes de délai</samp>.<br />Voyez [[mw:Special:MyLanguage/Manual:Maxlag_parameter|Manuel: paramètre Maxlag]] pour plus d’information.",
index 37a49be..85035bc 100644 (file)
@@ -192,7 +192,7 @@ class ChangesList extends ContextSource {
         * @param RecentChange|RCCacheEntry $rc
         * @param string|bool $watched Optionally timestamp for adding watched class
         *
-        * @return array of classes
+        * @return string[] List of CSS class names
         */
        protected function getHTMLClasses( $rc, $watched ) {
                $classes = [ self::CSS_CLASS_PREFIX . 'line' ];
index b62737d..65a7b7d 100644 (file)
@@ -646,9 +646,6 @@ abstract class ContentHandler {
                $slotDiffRenderer->setStatsdDataFactory( $statsdDataFactory );
                // XXX using the page language would be better, but it's unclear how that should be injected
                $slotDiffRenderer->setLanguage( $contentLanguage );
-               $slotDiffRenderer->setWikiDiff2MovedParagraphDetectionCutoff(
-                       $context->getConfig()->get( 'WikiDiff2MovedParagraphDetectionCutoff' )
-               );
 
                $engine = DifferenceEngine::getEngine();
                if ( $engine === false ) {
index be4f6ba..5b62984 100644 (file)
@@ -56,6 +56,7 @@ abstract class MWLBFactory {
                'DBuser',
                'DBWindowsAuthentication',
                'DebugDumpSql',
+               'DebugLogFile',
                'ExternalServers',
                'SQLiteDataDir',
                'SQLMode',
@@ -206,6 +207,7 @@ abstract class MWLBFactory {
 
                $flags = DBO_DEFAULT;
                $flags |= $options->get( 'DebugDumpSql' ) ? DBO_DEBUG : 0;
+               $flags |= $options->get( 'DebugLogFile' ) ? DBO_DEBUG : 0;
                if ( $server['type'] === 'oracle' ) {
                        $flags |= $options->get( 'DBOracleDRCP' ) ? DBO_PERSISTENT : 0;
                }
index 1ab1246..f7658fc 100644 (file)
@@ -1172,7 +1172,6 @@ class DifferenceEngine extends ContextSource {
 
                if ( $engine === 'wikidiff2' ) {
                        $params[] = phpversion( 'wikidiff2' );
-                       $params[] = $this->getConfig()->get( 'WikiDiff2MovedParagraphDetectionCutoff' );
                }
 
                if ( !$this->isSlotDiffRenderer ) {
index bb965e1..510465b 100644 (file)
@@ -51,14 +51,6 @@ class TextSlotDiffRenderer extends SlotDiffRenderer {
        /** @var Language|null The language this content is in. */
        private $language;
 
-       /**
-        * Number of paragraph moves the algorithm should attempt to detect.
-        * Only used with the wikidiff2 engine.
-        * @var int
-        * @see $wgWikiDiff2MovedParagraphDetectionCutoff
-        */
-       private $wikiDiff2MovedParagraphDetectionCutoff = 0;
-
        /** @var string One of the ENGINE_* constants. */
        private $engine = self::ENGINE_PHP;
 
@@ -86,15 +78,6 @@ class TextSlotDiffRenderer extends SlotDiffRenderer {
                $this->language = $language;
        }
 
-       /**
-        * @param int $cutoff
-        * @see $wgWikiDiff2MovedParagraphDetectionCutoff
-        */
-       public function setWikiDiff2MovedParagraphDetectionCutoff( $cutoff ) {
-               Assert::parameterType( 'integer', $cutoff, '$cutoff' );
-               $this->wikiDiff2MovedParagraphDetectionCutoff = $cutoff;
-       }
-
        /**
         * Set which diff engine to use.
         * @param string $type One of the ENGINE_* constants.
@@ -205,7 +188,7 @@ class TextSlotDiffRenderer extends SlotDiffRenderer {
                                        $oldText,
                                        $newText,
                                        2,
-                                       $this->wikiDiff2MovedParagraphDetectionCutoff
+                                       0
                                );
                        } else {
                                // Don't pass the 4th parameter introduced in version 1.5.0 and removed in version 1.8.0
index 75f7ccd..cac16b6 100644 (file)
@@ -106,7 +106,9 @@ class ExternalStoreDB extends ExternalStoreMedium {
        }
 
        public function isReadOnly( $location ) {
-               return ( $this->getLoadBalancer( $location )->getReadOnlyReason() !== false );
+               $lb = $this->getLoadBalancer( $location );
+               $domainId = $this->getDomainId( $lb->getServerInfo( $lb->getWriterIndex() ) );
+               return ( $lb->getReadOnlyReason( $domainId ) !== false );
        }
 
        /**
@@ -166,7 +168,7 @@ class ExternalStoreDB extends ExternalStoreMedium {
         * @return string|bool Database domain ID or false
         */
        private function getDomainId( array $server ) {
-               if ( isset( $this->params['wiki'] ) ) {
+               if ( isset( $this->params['wiki'] ) && $this->params['wiki'] !== false ) {
                        return $this->params['wiki']; // explicit domain
                }
 
index 96b43d6..c006874 100644 (file)
@@ -54,14 +54,6 @@ class WikiRevision implements ImportableUploadRevision, ImportableOldRevision {
         */
        public $timestamp = "20010115000000";
 
-       /**
-        * @since 1.2
-        * @var int
-        * @deprecated in 1.29. Unused.
-        * @note Introduced in 436a028086fb3f01c4605c5ad2964d56f9306aca, unused there, unused now.
-        */
-       public $user = 0;
-
        /**
         * @since 1.2
         * @var string
index 890f996..cedcee1 100644 (file)
@@ -69,9 +69,9 @@
        "config-wincache": "[https://www.iis.net/downloads/microsoft/wincache-extension WinCache] đã được cài đặt",
        "config-no-cache-apcu": "<strong>Cảnh báo:</strong> Không tìm thấy [https://www.php.net/apcu APCu] hoặc [https://www.iis.net/downloads/microsoft/wincache-extension WinCache].\nVùng nhớ đệm đối tượng không được kích hoạt.",
        "config-mod-security": "<strong>Cảnh báo:</strong> [https://modsecurity.org/ mod_security]/mod_security2 đã được kích hoạt trên máy chủ Web của bạn. Nhiều cấu hình phổ biến của phần mềm này sẽ gây vấn đề cho MediaWiki và những phần mềm khác cho phép người dùng đăng các nội dung tùy tiện.\nNếu có thể, bạn nên vô hiệu nó. Còn không, tra cứu [https://modsecurity.org/documentation/ tài liệu mod_security] hoặc liên hệ với nhà cung cấp hỗ trợ cho máy chủ nếu bạn gặp những lỗi ngẫu nhiên nào đó.",
-       "config-diff3-bad": "Không tìm thấy GNU diff3.",
+       "config-diff3-bad": "Không tìm thấy tiện ích so sánh văn bản GNU diff3. Bạn có thể bỏ qua vấn đề này bây giờ, nhưng các mâu thuẫn sửa đổi có thể xảy ra thường xuyên hơn.",
        "config-git": "Đã tìm thấy phần mềm điều khiển phiên bản Git: <code>$1</code>.",
-       "config-git-bad": "Không tìm thấy phần mềm điều khiển phiên bản Git.",
+       "config-git-bad": "Không tìm thấy phần mềm điều khiển phiên bản Git. Bạn có thể bỏ qua vấn đề này bây giờ. Lưu ý rằng Đặc biệt:Phiên bản sẽ không hiển thị các số băm chuyển giao.",
        "config-imagemagick": "Đã tìm thấy ImageMagick: <code>$1</code>.\nChức năng thu nhỏ hình ảnh sẽ được kích hoạt nếu bạn cho phép tải lên.",
        "config-gd": "Đã tìm thấy thư viện đồ họa GD đi kèm.\nChức năng thu nhỏ hình ảnh sẽ được kích hoạt nếu bạn cho phép tải lên.",
        "config-no-scaling": "Không thể tìm thấy thư viện GD hoặc ImageMagic. Chức năng thu nhỏ hình ảnh sẽ bị vô hiệu.",
        "config-using-32bit": "<strong>Cảnh báo:</strong> Máy của bạn hình như sử dụng các số nguyên 32 bit. Chế độ này [https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:32-bit không được khuyên khích].",
        "config-db-type": "Kiểu cơ sở dữ liệu:",
        "config-db-host": "Máy chủ của cơ sở dữ liệu:",
-       "config-db-host-help": "Nếu máy chủ cơ sở dữ liệu của bạn nằm trên máy chủ khác, hãy điền tên hoặc địa chỉ IP của máy chủ vào đây.\n\nNếu bạn đang dùng Web hosting chia sẻ, tài liệu của nhà cung cấp hosting của bạn sẽ có tên chính xác của máy chủ.\n\nNếu bạn đang cài đặt trên một máy chủ Windows và sử dụng MySQL, việc dùng “localhost” có thể không hợp với tên máy chủ. Nếu bị như vậy, hãy thử “127.0.0.1” tức địa chỉ IP địa phương.\n\nNếu bạn đang dùng PostgreSQL, hãy để trống mục này để kết nối với một ổ cắm Unix.",
+       "config-db-host-help": "Nếu máy chủ cơ sở dữ liệu của bạn nằm trên máy chủ khác, hãy điền tên hoặc địa chỉ IP của máy chủ vào đây.\n\nNếu bạn đang dùng Web hosting chia sẻ, tài liệu của nhà cung cấp hosting của bạn sẽ có tên chính xác của máy chủ.\n\nNếu bạn đang sử dụng MySQL, việc dùng “localhost” có thể không hợp với tên máy chủ. Nếu bị như vậy, hãy thử “127.0.0.1” tức địa chỉ IP địa phương.\n\nNếu bạn đang dùng PostgreSQL, hãy để trống mục này để kết nối với một ổ cắm Unix.",
        "config-db-host-oracle": "TNS cơ sở dữ liệu:",
        "config-db-host-oracle-help": "Nhập một [http://download.oracle.com/docs/cd/B28359_01/network.111/b28317/tnsnames.htm Tên Kết nối Địa phương] hợp lệ; một tập tin tnsnames.ora phải được hiển thị đối với cài đặt này.<br />Nếu bạn đang sử dụng các thư viện trình khách 10g trở lên, bạn cũng có thể sử dụng phương pháp đặt tên [http://download.oracle.com/docs/cd/E11882_01/network.112/e10836/naming.htm Easy Connect].",
        "config-db-wiki-settings": "Dữ liệu để nhận ra wiki này",
-       "config-db-name": "Tên cơ sở dữ liệu:",
+       "config-db-name": "Tên cơ sở dữ liệu (không có dấu gạch ngang):",
        "config-db-name-help": "Chọn một tên để chỉ thị wiki của bạn.\nKhông nên đưa dấu cách vào tên này.\n\nNếu bạn đang sử dụng Web hosting chia sẻ, nhà cung cấp hosting của bạn hoặc là sẽ cung cấp cho bạn một tên cơ sở dữ liệu cụ thể để sử dụng hoặc là sẽ cho phép bạn tạo ra các cơ sở dữ liệu thông qua một bảng điều khiển.",
        "config-db-name-oracle": "Giản đồ cơ sở dữ liệu:",
        "config-db-account-oracle-warn": "Có ba trường hợp được hỗ trợ để cài đặt Oracle làm cơ sở dữ liệu phía sau:\n\nNếu bạn muốn tạo tài khoản cơ sở dữ liệu trong quá trình cài đặt, xin vui lòng cung cấp một tài khoản với vai trò SYSDBA là tài khoản cơ sở dữ liệu để cài đặt và xác định định danh mong muốn cho tài khoản truy cập Web, nếu không bạn có thể tạo tài khoản truy cập Web thủ công và chỉ cung cấp tài khoản đó (nếu nó có các quyền yêu cầu để tạo ra các đối tượng giản đồ) hoặc cung cấp hai tài khoản riêng, một có quyền tạo ra và một bị hạn chế có quyền truy cập Web.\n\nMột kịch bản để tạo một tài khoản với quyền yêu cầu có sẵn trong thư mục cài đặt “maintenance/oracle/”. Hãy nhớ rằng việc sử dụng một tài khoản bị hạn chế sẽ vô hiệu hóa tất cả các khả năng bảo trì với tài khoản mặc định.",
        "config-db-account-lock": "Sử dụng cùng tên người dùng và mật khẩu trong quá trình hoạt động bình thường",
        "config-db-wiki-account": "Tài khoản người dùng để hoạt động bình thường",
        "config-db-wiki-help": "Nhập tên người dùng và mật khẩu sẽ được sử dụng để kết nối với cơ sở dữ liệu trong quá trình hoạt động bình thường của wiki.\nNếu tài khoản không tồn tại và tài khoản cài đặt có đủ quyền hạn, tài khoản người dùng này sẽ được tạo ra với những đặc quyền tối thiểu cần thiết để vận hành wiki.",
-       "config-db-prefix": "Tiền tố bảng cơ sở dữ liệu:",
+       "config-db-prefix": "Tiền tố bảng cơ sở dữ liệu (không có dấu gạch ngang):",
        "config-db-prefix-help": "Nếu bạn cần phải chia sẻ một cơ sở dữ liệu chung với nhiều wiki, hay giữa MediaWiki và một ứng dụng Web, bạn có thể quyết định thêm một tiền tố cho tất cả các tên bảng để tránh xung đột.\nKhông sử dụng dấu cách.\n\nTrường này thường được bỏ trống.",
        "config-mysql-old": "Cần MySQL $1 trở lên; bạn có $2.",
        "config-db-port": "Cổng cơ sở dữ liệu:",
-       "config-db-schema": "Giản đồ cho MediaWiki:",
+       "config-db-schema": "Giản đồ cho MediaWiki (không có dấu gạch ngang):",
        "config-db-schema-help": "Giản đồ này thường làm việc tốt.\nChỉ thay đổi nó nếu bạn biết cần phải làm như vậy.",
        "config-pg-test-error": "Không thể kết nối với cơ sở dữ liệu '''$1''': $2",
        "config-sqlite-dir": "Thư mục dữ liệu SQLite:",
        "config-invalid-db-server-oracle": "Cơ sở dữ liệu TNS không hợp lệ “$1”.\nHoặc sử dụng “TNS Name” hoặc một chuỗi “Easy Connect” ([http://docs.oracle.com/cd/E11882_01/network.112/e10836/naming.htm Phương pháp đặt tên Oracle]).",
        "config-invalid-db-name": "Tên cơ sở dữ liệu không hợp lệ “$1”.\nChỉ sử dụng các chữ cái ASCII (a–z, A–Z), số (0–9), dấu gạch dưới (_) và dấu gạch ngang (-).",
        "config-invalid-db-prefix": "Tiền tố cơ sở dữ liệu không hợp lệ “$1”.\nChỉ sử dụng các chữ cái ASCII (a–z, A–Z), số (0–9), dấu gạch dưới (_) và dấu gạch ngang (-).",
-       "config-connection-error": "$1.\n\nKiểm tra máy chủ, tên người dùng, và mật khẩu và thử lại lần nữa.",
+       "config-connection-error": "$1.\n\nKiểm tra máy chủ, tên người dùng, và mật khẩu và thử lại lần nữa. Nếu sử dụng “localhost” làm máy chủ cơ sở dữ liệu, hãy thử sử dụng “127.0.0.1” thay thế (hoặc ngược lại).",
        "config-invalid-schema": "Giản đồ “$1” không hợp lệ cho MediaWiki.\nHãy chỉ sử dụng các chữ cái ASCII (a–z, A–Z), chữ số (0–9), và dấu gạch dưới (_).",
        "config-db-sys-create-oracle": "Trình cài đặt chỉ hỗ trợ sử dụng một tài khoản SYSDBA để tạo một tài khoản mới.",
        "config-db-sys-user-exists-oracle": "Tài khoản người dùng “$1” đã tồn tại. SYSDBA chỉ có thể được sử dụng để tạo một tài khoản mới!",
        "config-sqlite-cant-create-db": "Không thể tạo ra tập tin cơ sở dữ liệu <code>$1</code>.",
        "config-sqlite-fts3-downgrade": "PHP thiếu sự hỗ trợ cho FTS3; đang giáng cấp các bảng",
        "config-can-upgrade": "Cơ sở dữ liệu này có bảng MediaWiki.\nĐể nâng cấp các bảng đến MediaWiki $1, bấm <strong>Tiếp tục</strong>.",
+       "config-upgrade-error": "Xuất hiện lỗi khi nâng cấp các bảng MediaWiki trong cơ sở dữ liệu của bạn.\n\nĐể tìm hiểu thêm, xem lại nhật trình bên trên. Để thử lại, bấm <strong>Tiếp tục</strong>.",
        "config-upgrade-done": "Nâng cấp đã hoàn thành.\n\nBạn có thể [$1 bắt đầu sử dụng wiki của bạn] ngay bây giờ.\n\nNếu bạn muốn tạo lại tập tin <code>LocalSettings.php</code> của bạn, bấm nút bên dưới.\nĐiều này <strong>không được khuyến khích</strong>, trừ khi bạn đang gặp vấn đề với wiki của bạn.",
        "config-upgrade-done-no-regenerate": "Nâng cấp đã hoàn thành.\n\nBạn có thể [$1 bắt đầu sử dụng wiki của bạn] ngay bây giờ.",
        "config-regenerate": "Tạo lại LocalSettings.php →",
        "config-install-schema": "Đang tạo giản đồ",
        "config-install-pg-schema-not-exist": "Lược đồ PostgreSQL không tồn tại.",
        "config-install-pg-schema-failed": "Thất bại khi tạo các bảng.\nHãy chắc chắn rằng người dùng “$1” có thể ghi vào giản đồ “$2”.",
-       "config-install-pg-commit": "Đang gửi các thay đổi",
+       "config-install-pg-commit": "Đang chuyển giao các thay đổi",
        "config-install-pg-plpgsql": "Tìm ngôn ngữ PL/pgSQL",
        "config-pg-no-plpgsql": "Bạn cần phải cài đặt ngôn ngữ PL/pgSQL vào cơ sở dữ liệu $1",
        "config-pg-no-create-privs": "Tài khoản bạn xác định để cài đặt không đủ quyền hạn để tạo một tài khoản.",
        "config-install-done": "<strong>Xin chúc mừng!</strong>\nBạn đã cài đặt MediaWiki.\n\nBộ cài đặt đã tạo ra một tập tin <code>LocalSettings.php</code>.\nTập tin này chứa tất cả các cấu hình của bạn.\n\nBạn sẽ cần phải tải nó về và đặt nó trong thư mục cài đặt wiki của bạn (cùng thư mục với index.php). Việc tải về có lẽ sẽ được khởi động tự động.\n\nNếu bản tải về không được cung cấp, hoặc nếu bạn hủy bỏ nó, bạn có thể khởi động lại tải về bằng cách nhấn vào liên kết dưới đây:\n\n$3\n\n<strong>Lưu ý:</strong> Nếu bạn không làm điều này ngay bây giờ, điều này sẽ tạo ra tập tin cấu hình sẽ không có giá trị cho bạn sau này nếu bạn thoát khỏi trình cài đặt mà không tải nó về.\n\nKhi đã việc tải về đã hoàn thành, bạn có thể <strong>[$2 truy cập trang wiki của bạn]</strong>.",
        "config-install-done-path": "<strong>Xin chúc mừng!</strong>\nBạn đã cài đặt MediaWiki.\n\nBộ cài đặt đã tạo ra một tập tin <code>LocalSettings.php</code>.\nTập tin này chứa tất cả các cấu hình của bạn.\n\nBạn sẽ cần phải tải nó về và đặt nó tại <code>$4</code>. Việc tải về có lẽ sẽ được khởi động tự động.\n\nNếu bản tải về không được cung cấp, hoặc nếu bạn hủy bỏ nó, bạn có thể khởi động lại tải về bằng cách nhấn vào liên kết dưới đây:\n\n$3\n\n<strong>Lưu ý:</strong> Nếu bạn không làm điều này ngay bây giờ, điều này sẽ tạo ra tập tin cấu hình sẽ không có giá trị cho bạn sau này nếu bạn thoát khỏi trình cài đặt mà không tải nó về.\n\nKhi đã việc tải về đã hoàn thành, bạn có thể <strong>[$2 truy cập trang wiki của bạn]</strong>.",
        "config-install-success": "MediaWiki đã được cài đặt thành công. Bây giờ bạn có thể mở <$1$2> để xem wiki của bạn.\nNếu bạn có thắc mắc, hãy đọc các câu thường hỏi:\n<https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:FAQ> hoặc ghé vào một diễn đàn hỗ trợ được liệt kê tại trang đó.",
+       "config-install-db-success": "Cơ sở dữ liệu được thiết lập thành công",
        "config-download-localsettings": "Tải về <code>LocalSettings.php</code>",
        "config-help": "Trợ giúp",
        "config-help-tooltip": "nhấn chuột để mở rộng",
index 9a5a433..5a36c65 100644 (file)
  * @ingroup Cache
  */
 class APCBagOStuff extends BagOStuff {
+       /** @var bool Whether to trust the APC implementation to serialization */
+       private $nativeSerialize;
+
        /**
         * @var string String to append to each APC key. This may be changed
         *  whenever the handling of values is changed, to prevent existing code
         *  from encountering older values which it cannot handle.
         */
-       const KEY_SUFFIX = ':3';
+       const KEY_SUFFIX = ':4';
+
+       public function __construct( array $params = [] ) {
+               parent::__construct( $params );
+               // The extension serializer is still buggy, unlike "php" and "igbinary"
+               $this->nativeSerialize = ( ini_get( 'apc.serializer' ) !== 'default' );
+       }
 
        protected function doGet( $key, $flags = 0, &$casToken = null ) {
                $casToken = null;
 
                $blob = apc_fetch( $key . self::KEY_SUFFIX );
-               $value = $this->unserialize( $blob );
+               $value = $this->nativeSerialize ? $blob : $this->unserialize( $blob );
                if ( $value !== false ) {
                        $casToken = $blob; // don't bother hashing this
                }
@@ -56,7 +65,7 @@ class APCBagOStuff extends BagOStuff {
        public function set( $key, $value, $exptime = 0, $flags = 0 ) {
                apc_store(
                        $key . self::KEY_SUFFIX,
-                       $this->serialize( $value ),
+                       $this->nativeSerialize ? $value : $this->serialize( $value ),
                        $exptime
                );
 
@@ -66,7 +75,7 @@ class APCBagOStuff extends BagOStuff {
        public function add( $key, $value, $exptime = 0, $flags = 0 ) {
                return apc_add(
                        $key . self::KEY_SUFFIX,
-                       $this->serialize( $value ),
+                       $this->nativeSerialize ? $value : $this->serialize( $value ),
                        $exptime
                );
        }
index eba0af5..0d9822a 100644 (file)
@@ -46,7 +46,7 @@ class APCUBagOStuff extends BagOStuff {
 
        public function __construct( array $params = [] ) {
                parent::__construct( $params );
-               // The extension serialize is still buggy, unlike "php" and "igbinary"
+               // The extension serializer is still buggy, unlike "php" and "igbinary"
                $this->nativeSerialize = ( ini_get( 'apc.serializer' ) !== 'default' );
        }
 
index 4d8ae59..a10d1a4 100644 (file)
@@ -7,26 +7,42 @@ use Psr\Log\LoggerInterface;
  *
  * Uses URL of the form "baseURL/{KEY}" to store, fetch, and delete values.
  *
- * E.g., when base URL is `/v1/sessions/`, then the store would do:
+ * E.g., when base URL is `/sessions/v1`, then the store would do:
  *
- * `PUT /v1/sessions/12345758`
+ * `PUT /sessions/v1/12345758`
  *
  * and fetch would do:
  *
- * `GET /v1/sessions/12345758`
+ * `GET /sessions/v1/12345758`
  *
  * delete would do:
  *
- * `DELETE /v1/sessions/12345758`
+ * `DELETE /sessions/v1/12345758`
  *
- * Configure with:
+ * Minimal generic configuration:
  *
  * @code
  * $wgObjectCaches['sessions'] = array(
  *     'class' => 'RESTBagOStuff',
- *     'url' => 'http://localhost:7231/wikimedia.org/v1/sessions/'
+ *     'url' => 'http://localhost:7231/wikimedia.org/somepath/'
  * );
  * @endcode
+ *
+ * Configuration for Kask (session storage):
+ * @code
+ * $wgObjectCaches['sessions'] = array(
+ *     'class' => 'RESTBagOStuff',
+ *     'url' => 'https://kaskhost:1234/sessions/v1/',
+ *     'httpParams' => [
+ *             'readHeaders' => [],
+ *             'writeHeaders' => [ 'content-type' => 'application/octet-stream' ],
+ *             'deleteHeaders' => [],
+ *             'writeMethod' => 'POST',
+ *     ],
+ *     'extendedErrorBodyFields' => [ 'type', 'title', 'detail', 'instance' ]
+ * );
+ * $wgSessionCacheType = 'sessions';
+ * @endcode
  */
 class RESTBagOStuff extends BagOStuff {
        /**
@@ -52,10 +68,21 @@ class RESTBagOStuff extends BagOStuff {
         */
        private $url;
 
+       /**
+        * @var array http parameters: readHeaders, writeHeaders, deleteHeaders, writeMethod
+        */
+       private $httpParams;
+
+       /**
+        * @var array additional body fields to log on error, if possible
+        */
+       private $extendedErrorBodyFields;
+
        public function __construct( $params ) {
                if ( empty( $params['url'] ) ) {
                        throw new InvalidArgumentException( 'URL parameter is required' );
                }
+
                if ( empty( $params['client'] ) ) {
                        // Pass through some params to the HTTP client.
                        $clientParams = [
@@ -71,10 +98,19 @@ class RESTBagOStuff extends BagOStuff {
                } else {
                        $this->client = $params['client'];
                }
+
+               $this->httpParams['writeMethod'] = $params['httpParams']['writeMethod'] ?? 'PUT';
+               $this->httpParams['readHeaders'] = $params['httpParams']['readHeaders'] ?? [];
+               $this->httpParams['writeHeaders'] = $params['httpParams']['writeHeaders'] ?? [];
+               $this->httpParams['deleteHeaders'] = $params['httpParams']['deleteHeaders'] ?? [];
+               $this->extendedErrorBodyFields = $params['extendedErrorBodyFields'] ?? [];
+
                // 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;
        }
@@ -90,12 +126,13 @@ class RESTBagOStuff extends BagOStuff {
                $req = [
                        'method' => 'GET',
                        'url' => $this->url . rawurlencode( $key ),
+                       'headers' => $this->httpParams['readHeaders'],
                ];
 
                list( $rcode, $rdesc, $rhdrs, $rbody, $rerr ) = $this->client->run( $req );
                if ( $rcode === 200 ) {
                        if ( is_string( $rbody ) ) {
-                               $value = unserialize( $rbody );
+                               $value = $this->decodeBody( $rbody );
                                /// @FIXME: use some kind of hash or UUID header as CAS token
                                $casToken = ( $value !== false ) ? $rbody : null;
 
@@ -104,7 +141,7 @@ class RESTBagOStuff extends BagOStuff {
                        return false;
                }
                if ( $rcode === 0 || ( $rcode >= 400 && $rcode != 404 ) ) {
-                       return $this->handleError( "Failed to fetch $key", $rcode, $rerr );
+                       return $this->handleError( "Failed to fetch $key", $rcode, $rerr, $rhdrs, $rbody );
                }
                return false;
        }
@@ -113,15 +150,17 @@ class RESTBagOStuff extends BagOStuff {
                // @TODO: respect WRITE_SYNC (e.g. EACH_QUORUM)
                // @TODO: respect $exptime
                $req = [
-                       'method' => 'PUT',
+                       'method' => $this->httpParams['writeMethod'],
                        'url' => $this->url . rawurlencode( $key ),
-                       'body' => serialize( $value )
+                       'body' => $this->encodeBody( $value ),
+                       'headers' => $this->httpParams['writeHeaders'],
                ];
+
                list( $rcode, $rdesc, $rhdrs, $rbody, $rerr ) = $this->client->run( $req );
                if ( $rcode === 200 || $rcode === 201 || $rcode === 204 ) {
                        return true;
                }
-               return $this->handleError( "Failed to store $key", $rcode, $rerr );
+               return $this->handleError( "Failed to store $key", $rcode, $rerr, $rhdrs, $rbody );
        }
 
        public function add( $key, $value, $exptime = 0, $flags = 0 ) {
@@ -138,12 +177,14 @@ class RESTBagOStuff extends BagOStuff {
                $req = [
                        'method' => 'DELETE',
                        'url' => $this->url . rawurlencode( $key ),
+                       'headers' => $this->httpParams['deleteHeaders'],
                ];
+
                list( $rcode, $rdesc, $rhdrs, $rbody, $rerr ) = $this->client->run( $req );
                if ( in_array( $rcode, [ 200, 204, 205, 404, 410 ] ) ) {
                        return true;
                }
-               return $this->handleError( "Failed to delete $key", $rcode, $rerr );
+               return $this->handleError( "Failed to delete $key", $rcode, $rerr, $rhdrs, $rbody );
        }
 
        public function incr( $key, $value = 1 ) {
@@ -158,18 +199,65 @@ class RESTBagOStuff extends BagOStuff {
                return false;
        }
 
+       /**
+        * Processes the response body.
+        *
+        * @param string $body request body to process
+        * @return mixed|bool the processed body, or false on error
+        */
+       private function decodeBody( $body ) {
+               $value = json_decode( $body, true );
+               return ( json_last_error() === JSON_ERROR_NONE ) ? $value : false;
+       }
+
+       /**
+        * Prepares the request body (the "value" portion of our key/value store) for transmission.
+        *
+        * @param string $body request body to prepare
+        * @return string the prepared body, or an empty string on error
+        * @throws LogicException
+        */
+       private function encodeBody( $body ) {
+               $value = json_encode( $body );
+               if ( $value === false ) {
+                       throw new InvalidArgumentException( __METHOD__ . ": body could not be encoded." );
+               }
+               return $value;
+       }
+
        /**
         * Handle storage error
         * @param string $msg Error message
         * @param int $rcode Error code from client
         * @param string $rerr Error message from client
+        * @param array $rhdrs Response headers
+        * @param string $rbody Error body from client (if any)
         * @return false
         */
-       protected function handleError( $msg, $rcode, $rerr ) {
-               $this->logger->error( "$msg : ({code}) {error}", [
+       protected function handleError( $msg, $rcode, $rerr, $rhdrs, $rbody ) {
+               $message = "$msg : ({code}) {error}";
+               $context = [
                        'code' => $rcode,
                        'error' => $rerr
-               ] );
+               ];
+
+               if ( $this->extendedErrorBodyFields !== [] ) {
+                       $body = $this->decodeBody( $rbody );
+                       if ( $body ) {
+                               $extraFields = '';
+                               foreach ( $this->extendedErrorBodyFields as $field ) {
+                                       if ( isset( $body[$field] ) ) {
+                                               $extraFields .= " : ({$field}) {$body[$field]}";
+                                       }
+                               }
+                               if ( $extraFields !== '' ) {
+                                       $message .= " {extra_fields}";
+                                       $context['extra_fields'] = $extraFields;
+                               }
+                       }
+               }
+
+               $this->logger->error( $message, $context );
                $this->setLastError( $rcode === 0 ? self::ERR_UNREACHABLE : self::ERR_UNEXPECTED );
                return false;
        }
index e4dad01..c89820d 100644 (file)
@@ -218,7 +218,7 @@ class TransactionProfiler implements LoggerAwareInterface {
         *
         * This assumes that all queries are synchronous (non-overlapping)
         *
-        * @param string $query Function name or generalized SQL
+        * @param string|GeneralizedSql $query Function name or generalized SQL
         * @param float $sTime Starting UNIX wall time
         * @param bool $isWrite Whether this is a write query
         * @param int $n Number of affected/read rows
@@ -229,11 +229,11 @@ class TransactionProfiler implements LoggerAwareInterface {
 
                if ( $isWrite && $n > $this->expect['maxAffected'] ) {
                        $this->logger->warning(
-                               "Query affected $n row(s):\n" . $query . "\n" .
+                               "Query affected $n row(s):\n" . self::queryString( $query ) . "\n" .
                                ( new RuntimeException() )->getTraceAsString() );
                } elseif ( !$isWrite && $n > $this->expect['readQueryRows'] ) {
                        $this->logger->warning(
-                               "Query returned $n row(s):\n" . $query . "\n" .
+                               "Query returned $n row(s):\n" . self::queryString( $query ) . "\n" .
                                ( new RuntimeException() )->getTraceAsString() );
                }
 
@@ -341,7 +341,8 @@ class TransactionProfiler implements LoggerAwareInterface {
                        $trace = '';
                        foreach ( $this->dbTrxMethodTimes[$name] as $i => $info ) {
                                list( $query, $sTime, $end ) = $info;
-                               $trace .= sprintf( "%d\t%.6f\t%s\n", $i, ( $end - $sTime ), $query );
+                               $trace .= sprintf(
+                                       "%d\t%.6f\t%s\n", $i, ( $end - $sTime ), self::queryString( $query ) );
                        }
                        $this->logger->warning( "Sub-optimal transaction on DB(s) [{dbs}]: \n{trace}", [
                                'dbs' => implode( ', ', array_keys( $this->dbTrxHoldingLocks[$name]['conns'] ) ),
@@ -354,7 +355,7 @@ class TransactionProfiler implements LoggerAwareInterface {
 
        /**
         * @param string $expect
-        * @param string $query
+        * @param string|GeneralizedSql $query
         * @param string|float|int $actual
         */
        protected function reportExpectationViolated( $expect, $query, $actual ) {
@@ -370,8 +371,16 @@ class TransactionProfiler implements LoggerAwareInterface {
                                'max' => $this->expect[$expect],
                                'by' => $this->expectBy[$expect],
                                'actual' => $actual,
-                               'query' => $query
+                               'query' => self::queryString( $query )
                        ]
                );
        }
+
+       /**
+        * @param GeneralizedSql|string $query
+        * @return string
+        */
+       private static function queryString( $query ) {
+               return $query instanceof GeneralizedSql ? $query->stringify() : $query;
+       }
 }
index 1e7180d..de9ea55 100644 (file)
@@ -71,12 +71,13 @@ abstract class Database implements IDatabase, IMaintainableDatabase, LoggerAware
        /** @var int New Database instance will already be connected when returned */
        const NEW_CONNECTED = 1;
 
-       /** @var string SQL query */
-       protected $lastQuery = '';
+       /** @var string The last SQL query attempted */
+       private $lastQuery = '';
        /** @var float|bool UNIX timestamp of last write query */
-       protected $lastWriteTime = false;
+       private $lastWriteTime = false;
        /** @var string|bool */
-       protected $phpError = false;
+       private $lastPhpError = false;
+
        /** @var string Server that this instance is currently connected to */
        protected $server;
        /** @var string User that this instance is currently connected under the name of */
@@ -874,7 +875,7 @@ abstract class Database implements IDatabase, IMaintainableDatabase, LoggerAware
         * Set a custom error handler for logging errors during database connection
         */
        protected function installErrorHandler() {
-               $this->phpError = false;
+               $this->lastPhpError = false;
                $this->htmlErrors = ini_set( 'html_errors', '0' );
                set_error_handler( [ $this, 'connectionErrorLogger' ] );
        }
@@ -897,8 +898,8 @@ abstract class Database implements IDatabase, IMaintainableDatabase, LoggerAware
         * @return string|bool Last PHP error for this DB (typically connection errors)
         */
        protected function getLastPHPError() {
-               if ( $this->phpError ) {
-                       $error = preg_replace( '!\[<a.*</a>\]!', '', $this->phpError );
+               if ( $this->lastPhpError ) {
+                       $error = preg_replace( '!\[<a.*</a>\]!', '', $this->lastPhpError );
                        $error = preg_replace( '!^.*?:\s?(.*)$!', '$1', $error );
 
                        return $error;
@@ -915,7 +916,7 @@ abstract class Database implements IDatabase, IMaintainableDatabase, LoggerAware
         * @param string $errstr
         */
        public function connectionErrorLogger( $errno, $errstr ) {
-               $this->phpError = $errstr;
+               $this->lastPhpError = $errstr;
        }
 
        /**
@@ -1197,7 +1198,6 @@ abstract class Database implements IDatabase, IMaintainableDatabase, LoggerAware
 
                $priorTransaction = $this->trxLevel;
                $priorWritesPending = $this->writesOrCallbacksPending();
-               $this->lastQuery = $sql;
 
                if ( $this->isWriteQuery( $sql ) ) {
                        # In theory, non-persistent writes are allowed in read-only mode, but due to things
@@ -1290,7 +1290,7 @@ abstract class Database implements IDatabase, IMaintainableDatabase, LoggerAware
        private function attemptQuery( $sql, $commentedSql, $isEffectiveWrite, $fname ) {
                $this->beginIfImplied( $sql, $fname );
 
-               # Keep track of whether the transaction has write queries pending
+               // Keep track of whether the transaction has write queries pending
                if ( $isEffectiveWrite ) {
                        $this->lastWriteTime = microtime( true );
                        if ( $this->trxLevel && !$this->trxDoneWrites ) {
@@ -1300,25 +1300,15 @@ abstract class Database implements IDatabase, IMaintainableDatabase, LoggerAware
                        }
                }
 
-               if ( $this->getFlag( self::DBO_DEBUG ) ) {
-                       $this->queryLogger->debug( "{$this->getDomainID()} {$commentedSql}" );
-               }
-
-               $isMaster = !is_null( $this->getLBInfo( 'master' ) );
-               # generalizeSQL() will probably cut down the query to reasonable
-               # logging size most of the time. The substr is really just a sanity check.
-               if ( $isMaster ) {
-                       $queryProf = 'query-m: ' . substr( self::generalizeSQL( $sql ), 0, 255 );
-               } else {
-                       $queryProf = 'query: ' . substr( self::generalizeSQL( $sql ), 0, 255 );
-               }
-
-               # Include query transaction state
-               $queryProf .= $this->trxShortId ? " [TRX#{$this->trxShortId}]" : "";
+               $prefix = !is_null( $this->getLBInfo( 'master' ) ) ? 'query-m: ' : 'query: ';
+               $generalizedSql = new GeneralizedSql( $sql, $this->trxShortId, $prefix );
 
                $startTime = microtime( true );
-               $ps = $this->profiler ? ( $this->profiler )( $queryProf ) : null;
+               $ps = $this->profiler
+                       ? ( $this->profiler )( $generalizedSql->stringify() )
+                       : null;
                $this->affectedRowCount = null;
+               $this->lastQuery = $sql;
                $ret = $this->doQuery( $commentedSql );
                $this->affectedRowCount = $this->affectedRows();
                unset( $ps ); // profile out (if set)
@@ -1337,16 +1327,24 @@ abstract class Database implements IDatabase, IMaintainableDatabase, LoggerAware
                }
 
                $this->trxProfiler->recordQueryCompletion(
-                       $queryProf,
+                       $generalizedSql,
                        $startTime,
                        $isEffectiveWrite,
                        $isEffectiveWrite ? $this->affectedRows() : $this->numRows( $ret )
                );
-               $this->queryLogger->debug( $sql, [
-                       'method' => $fname,
-                       'master' => $isMaster,
-                       'runtime' => $queryRuntime,
-               ] );
+
+               // Avoid the overhead of logging calls unless debug mode is enabled
+               if ( $this->getFlag( self::DBO_DEBUG ) ) {
+                       $this->queryLogger->debug(
+                               "{method} [{runtime}s]: $sql",
+                               [
+                                       'method' => $fname,
+                                       'db_host' => $this->getServer(),
+                                       'domain' => $this->getDomainID(),
+                                       'runtime' => round( $queryRuntime, 3 )
+                               ]
+                       );
+               }
 
                return $ret;
        }
@@ -1546,11 +1544,11 @@ abstract class Database implements IDatabase, IMaintainableDatabase, LoggerAware
         * @param int $errno
         * @param string $sql
         * @param string $fname
-        * @param bool $ignoreErrors
+        * @param bool $ignore
         * @throws DBQueryError
         */
-       public function reportQueryError( $error, $errno, $sql, $fname, $ignoreErrors = false ) {
-               if ( $ignoreErrors ) {
+       public function reportQueryError( $error, $errno, $sql, $fname, $ignore = false ) {
+               if ( $ignore ) {
                        $this->queryLogger->debug( "SQL ERROR (ignored): $error\n" );
                } else {
                        $exception = $this->getQueryExceptionAndLog( $error, $errno, $sql, $fname );
@@ -1580,9 +1578,10 @@ abstract class Database implements IDatabase, IMaintainableDatabase, LoggerAware
                        ] )
                );
                $this->queryLogger->debug( "SQL ERROR: " . $error . "\n" );
-               $wasQueryTimeout = $this->wasQueryTimeout( $error, $errno );
-               if ( $wasQueryTimeout ) {
+               if ( $this->wasQueryTimeout( $error, $errno ) ) {
                        $e = new DBQueryTimeoutError( $this, $error, $errno, $sql, $fname );
+               } elseif ( $this->wasConnectionError( $errno ) ) {
+                       $e = new DBQueryDisconnectedError( $this, $error, $errno, $sql, $fname );
                } else {
                        $e = new DBQueryError( $this, $error, $errno, $sql, $fname );
                }
@@ -2033,36 +2032,6 @@ abstract class Database implements IDatabase, IMaintainableDatabase, LoggerAware
                return $this->selectRowCount( $table, '*', $conds, $fname, $options, $join_conds );
        }
 
-       /**
-        * Removes most variables from an SQL query and replaces them with X or N for numbers.
-        * It's only slightly flawed. Don't use for anything important.
-        *
-        * @param string $sql A SQL Query
-        *
-        * @return string
-        */
-       protected static function generalizeSQL( $sql ) {
-               # This does the same as the regexp below would do, but in such a way
-               # as to avoid crashing php on some large strings.
-               # $sql = preg_replace( "/'([^\\\\']|\\\\.)*'|\"([^\\\\\"]|\\\\.)*\"/", "'X'", $sql );
-
-               $sql = str_replace( "\\\\", '', $sql );
-               $sql = str_replace( "\\'", '', $sql );
-               $sql = str_replace( "\\\"", '', $sql );
-               $sql = preg_replace( "/'.*'/s", "'X'", $sql );
-               $sql = preg_replace( '/".*"/s', "'X'", $sql );
-
-               # All newlines, tabs, etc replaced by single space
-               $sql = preg_replace( '/\s+/', ' ', $sql );
-
-               # All numbers => N,
-               # except the ones surrounded by characters, e.g. l10n
-               $sql = preg_replace( '/-?\d+(,-?\d+)+/s', 'N,...,N', $sql );
-               $sql = preg_replace( '/(?<![a-zA-Z])-?\d+(?![a-zA-Z])/s', 'N', $sql );
-
-               return $sql;
-       }
-
        public function fieldExists( $table, $field, $fname = __METHOD__ ) {
                $info = $this->fieldInfo( $table, $field );
 
index 7452278..aeefacd 100644 (file)
@@ -247,8 +247,8 @@ interface IDatabase {
        public function implicitOrderby();
 
        /**
-        * Return the last query that went through IDatabase::query()
-        * @return string
+        * Return the last query that sent on account of IDatabase::query()
+        * @return string SQL text or empty string if there was no such query
         */
        public function lastQuery();
 
diff --git a/includes/libs/rdbms/database/utils/GeneralizedSql.php b/includes/libs/rdbms/database/utils/GeneralizedSql.php
new file mode 100644 (file)
index 0000000..db5c639
--- /dev/null
@@ -0,0 +1,95 @@
+<?php
+/**
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ *
+ * @file
+ * @ingroup Profiler
+ */
+
+namespace Wikimedia\Rdbms;
+
+/**
+ * Lazy-loaded wrapper for simplification and scrubbing of SQL queries for profiling
+ *
+ * @since 1.34
+ */
+class GeneralizedSql {
+       /** @var string */
+       private $rawSql;
+       /** @var string */
+       private $trxId;
+       /** @var string */
+       private $prefix;
+
+       /** @var string|null */
+       private $genericSql;
+
+       /**
+        * @param string $rawSql
+        * @param string $trxId
+        * @param string $prefix
+        */
+       public function __construct( $rawSql, $trxId, $prefix ) {
+               $this->rawSql = $rawSql;
+               $this->trxId = $trxId;
+               $this->prefix = $prefix;
+       }
+
+       /**
+        * Removes most variables from an SQL query and replaces them with X or N for numbers.
+        * It's only slightly flawed. Don't use for anything important.
+        *
+        * @param string $sql A SQL Query
+        *
+        * @return string
+        */
+       private static function generalizeSQL( $sql ) {
+               # This does the same as the regexp below would do, but in such a way
+               # as to avoid crashing php on some large strings.
+               # $sql = preg_replace( "/'([^\\\\']|\\\\.)*'|\"([^\\\\\"]|\\\\.)*\"/", "'X'", $sql );
+
+               $sql = str_replace( "\\\\", '', $sql );
+               $sql = str_replace( "\\'", '', $sql );
+               $sql = str_replace( "\\\"", '', $sql );
+               $sql = preg_replace( "/'.*'/s", "'X'", $sql );
+               $sql = preg_replace( '/".*"/s', "'X'", $sql );
+
+               # All newlines, tabs, etc replaced by single space
+               $sql = preg_replace( '/\s+/', ' ', $sql );
+
+               # All numbers => N,
+               # except the ones surrounded by characters, e.g. l10n
+               $sql = preg_replace( '/-?\d+(,-?\d+)+/s', 'N,...,N', $sql );
+               $sql = preg_replace( '/(?<![a-zA-Z])-?\d+(?![a-zA-Z])/s', 'N', $sql );
+
+               return $sql;
+       }
+
+       /**
+        * @return string
+        */
+       public function stringify() {
+               if ( $this->genericSql !== null ) {
+                       return $this->genericSql;
+               }
+
+               $this->genericSql = $this->prefix .
+                       substr( self::generalizeSQL( $this->rawSql ), 0, 255 ) .
+                       ( $this->trxId ? " [TRX#{$this->trxId}]" : "" );
+
+               return $this->genericSql;
+       }
+}
diff --git a/includes/libs/rdbms/exception/DBQueryDisconnectedError.php b/includes/libs/rdbms/exception/DBQueryDisconnectedError.php
new file mode 100644 (file)
index 0000000..a142b4a
--- /dev/null
@@ -0,0 +1,30 @@
+<?php
+/**
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ *
+ * @file
+ * @ingroup Database
+ */
+
+namespace Wikimedia\Rdbms;
+
+/**
+ * @ingroup Database
+ * @since 1.34
+ */
+class DBQueryDisconnectedError extends DBQueryError {
+
+}
index 2d1c3b2..e07b166 100644 (file)
@@ -110,7 +110,7 @@ class BitmapHandler extends TransformationalImageHandler {
         * Get ImageMagick subsampling factors for the target JPEG pixel format.
         *
         * @param string $pixelFormat one of 'yuv444', 'yuv422', 'yuv420'
-        * @return array of string keys
+        * @return string[] List of sampling factors
         */
        protected function imageMagickSubsampling( $pixelFormat ) {
                switch ( $pixelFormat ) {
index 8f39650..863a3f3 100644 (file)
@@ -1962,9 +1962,7 @@ class WikiPage implements Page, IDBAccessObject {
         * @deprecated since 1.32, use getDerivedDataUpdater instead.
         *
         * @param Content $content
-        * @param Revision|RevisionRecord|int|null $revision Revision object.
-        *        For backwards compatibility, a revision ID is also accepted,
-        *        but this is deprecated.
+        * @param Revision|RevisionRecord|null $revision Revision object.
         *        Used with vary-revision or vary-revision-id.
         * @param User|null $user
         * @param string|null $serialFormat IGNORED
@@ -1987,19 +1985,13 @@ class WikiPage implements Page, IDBAccessObject {
                        $user = $wgUser;
                }
 
-               if ( !is_object( $revision ) ) {
-                       $revid = $revision;
-                       // This code path is deprecated, and nothing is known to
-                       // use it, so performance here shouldn't be a worry.
-                       if ( $revid !== null ) {
-                               wfDeprecated( __METHOD__ . ' with $revision = revision ID', '1.25' );
-                               $store = $this->getRevisionStore();
-                               $revision = $store->getRevisionById( $revid, Revision::READ_LATEST );
-                       } else {
-                               $revision = null;
+               if ( $revision !== null ) {
+                       if ( $revision instanceof Revision ) {
+                               $revision = $revision->getRevisionRecord();
+                       } elseif ( !( $revision instanceof RevisionRecord ) ) {
+                               throw new InvalidArgumentException(
+                                       __METHOD__ . ': invalid $revision argument type ' . gettype( $revision ) );
                        }
-               } elseif ( $revision instanceof Revision ) {
-                       $revision = $revision->getRevisionRecord();
                }
 
                $slots = RevisionSlotsUpdate::newFromContent( [ SlotRecord::MAIN => $content ] );
index b4caff2..27c34a6 100644 (file)
@@ -20,6 +20,7 @@
  * @file
  * @ingroup Parser
  */
+use MediaWiki\Config\ServiceOptions;
 use MediaWiki\Linker\LinkRenderer;
 use MediaWiki\Linker\LinkRendererFactory;
 use MediaWiki\Linker\LinkTarget;
@@ -169,8 +170,15 @@ class Parser {
         * @var MagicWordArray
         */
        public $mSubstWords;
+
+       /**
+        * @deprecated since 1.34, there should be no need to use this
+        * @var array
+        */
+       public $mConf;
+
        # Initialised in constructor
-       public $mConf, $mExtLinkBracketedRegex, $mUrlProtocols;
+       public $mExtLinkBracketedRegex, $mUrlProtocols;
 
        # Initialized in getPreprocessor()
        /** @var Preprocessor */
@@ -269,8 +277,14 @@ class Parser {
        /** @var SpecialPageFactory */
        private $specialPageFactory;
 
-       /** @var Config */
-       private $siteConfig;
+       /**
+        * This is called $svcOptions instead of $options like elsewhere to avoid confusion with
+        * $mOptions, which is public and widely used, and also with the local variable $options used
+        * for ParserOptions throughout this file.
+        *
+        * @var ServiceOptions
+        */
+       private $svcOptions;
 
        /** @var LinkRendererFactory */
        private $linkRendererFactory;
@@ -279,45 +293,84 @@ class Parser {
        private $nsInfo;
 
        /**
-        * @param array $parserConf See $wgParserConf documentation
+        * TODO Make this a const when HHVM support is dropped (T192166)
+        *
+        * @var array
+        * @since 1.33
+        */
+       public static $constructorOptions = [
+               // See $wgParserConf documentation
+               'class',
+               'preprocessorClass',
+               // See documentation for the corresponding config options
+               'ArticlePath',
+               'EnableScaryTranscluding',
+               'ExtraInterlanguageLinkPrefixes',
+               'FragmentMode',
+               'LanguageCode',
+               'MaxSigChars',
+               'MaxTocLevel',
+               'MiserMode',
+               'ScriptPath',
+               'Server',
+               'ServerName',
+               'ShowHostnames',
+               'Sitename',
+               'StylePath',
+               'TranscludeCacheExpiry',
+       ];
+
+       /**
+        * Constructing parsers directly is deprecated! Use a ParserFactory.
+        *
+        * @param ServiceOptions|null $svcOptions
         * @param MagicWordFactory|null $magicWordFactory
         * @param Language|null $contLang Content language
         * @param ParserFactory|null $factory
         * @param string|null $urlProtocols As returned from wfUrlProtocols()
         * @param SpecialPageFactory|null $spFactory
-        * @param Config|null $siteConfig
         * @param LinkRendererFactory|null $linkRendererFactory
         * @param NamespaceInfo|null $nsInfo
         */
        public function __construct(
-               array $parserConf = [], MagicWordFactory $magicWordFactory = null,
+               $svcOptions = null, MagicWordFactory $magicWordFactory = null,
                Language $contLang = null, ParserFactory $factory = null, $urlProtocols = null,
-               SpecialPageFactory $spFactory = null, Config $siteConfig = null,
-               LinkRendererFactory $linkRendererFactory = null,
-               NamespaceInfo $nsInfo = null
+               SpecialPageFactory $spFactory = null, $linkRendererFactory = null, $nsInfo = null
        ) {
-               $this->mConf = $parserConf;
+               $services = MediaWikiServices::getInstance();
+               if ( !$svcOptions || is_array( $svcOptions ) ) {
+                       // Pre-1.34 calling convention is the first parameter is just ParserConf, the seventh is
+                       // Config, and the eighth is LinkRendererFactory.
+                       $this->mConf = (array)$svcOptions;
+                       if ( empty( $this->mConf['class'] ) ) {
+                               $this->mConf['class'] = self::class;
+                       }
+                       if ( empty( $this->mConf['preprocessorClass'] ) ) {
+                               $this->mConf['preprocessorClass'] = self::getDefaultPreprocessorClass();
+                       }
+                       $this->svcOptions = new ServiceOptions( self::$constructorOptions,
+                               $this->mConf,
+                               func_num_args() > 6 ? func_get_arg( 6 ) : $services->getMainConfig()
+                       );
+                       $linkRendererFactory = func_num_args() > 7 ? func_get_arg( 7 ) : null;
+                       $nsInfo = func_num_args() > 8 ? func_get_arg( 8 ) : null;
+               } else {
+                       // New calling convention
+                       $svcOptions->assertRequiredOptions( self::$constructorOptions );
+                       // $this->mConf is public, so we'll keep those two options there as well for
+                       // compatibility until it's removed
+                       $this->mConf = [
+                               'class' => $svcOptions->get( 'class' ),
+                               'preprocessorClass' => $svcOptions->get( 'preprocessorClass' ),
+                       ];
+                       $this->svcOptions = $svcOptions;
+               }
+
                $this->mUrlProtocols = $urlProtocols ?? wfUrlProtocols();
                $this->mExtLinkBracketedRegex = '/\[(((?i)' . $this->mUrlProtocols . ')' .
                        self::EXT_LINK_ADDR .
                        self::EXT_LINK_URL_CLASS . '*)\p{Zs}*([^\]\\x00-\\x08\\x0a-\\x1F\\x{FFFD}]*?)\]/Su';
-               if ( isset( $parserConf['preprocessorClass'] ) ) {
-                       $this->mPreprocessorClass = $parserConf['preprocessorClass'];
-               } elseif ( wfIsHHVM() ) {
-                       # Under HHVM Preprocessor_Hash is much faster than Preprocessor_DOM
-                       $this->mPreprocessorClass = Preprocessor_Hash::class;
-               } elseif ( extension_loaded( 'domxml' ) ) {
-                       # PECL extension that conflicts with the core DOM extension (T15770)
-                       wfDebug( "Warning: you have the obsolete domxml extension for PHP. Please remove it!\n" );
-                       $this->mPreprocessorClass = Preprocessor_Hash::class;
-               } elseif ( extension_loaded( 'dom' ) ) {
-                       $this->mPreprocessorClass = Preprocessor_DOM::class;
-               } else {
-                       $this->mPreprocessorClass = Preprocessor_Hash::class;
-               }
-               wfDebug( __CLASS__ . ": using preprocessor: {$this->mPreprocessorClass}\n" );
 
-               $services = MediaWikiServices::getInstance();
                $this->magicWordFactory = $magicWordFactory ??
                        $services->getMagicWordFactory();
 
@@ -325,9 +378,7 @@ class Parser {
 
                $this->factory = $factory ?? $services->getParserFactory();
                $this->specialPageFactory = $spFactory ?? $services->getSpecialPageFactory();
-               $this->siteConfig = $siteConfig ?? $services->getMainConfig();
-               $this->linkRendererFactory =
-                       $linkRendererFactory ?? $services->getLinkRendererFactory();
+               $this->linkRendererFactory = $linkRendererFactory ?? $services->getLinkRendererFactory();
                $this->nsInfo = $nsInfo ?? $services->getNamespaceInfo();
        }
 
@@ -366,6 +417,28 @@ class Parser {
                Hooks::run( 'ParserCloned', [ $this ] );
        }
 
+       /**
+        * Which class should we use for the preprocessor if not otherwise specified?
+        *
+        * @since 1.34
+        * @return string
+        */
+       public static function getDefaultPreprocessorClass() {
+               if ( wfIsHHVM() ) {
+                       # Under HHVM Preprocessor_Hash is much faster than Preprocessor_DOM
+                       return Preprocessor_Hash::class;
+               }
+               if ( extension_loaded( 'domxml' ) ) {
+                       # PECL extension that conflicts with the core DOM extension (T15770)
+                       wfDebug( "Warning: you have the obsolete domxml extension for PHP. Please remove it!\n" );
+                       return Preprocessor_Hash::class;
+               }
+               if ( extension_loaded( 'dom' ) ) {
+                       return Preprocessor_DOM::class;
+               }
+               return Preprocessor_Hash::class;
+       }
+
        /**
         * Do various kinds of initialisation on the first call of the parser
         */
@@ -597,7 +670,7 @@ class Parser {
                Hooks::run( 'ParserLimitReportPrepare', [ $this, $this->mOutput ] );
 
                $limitReport = "NewPP limit report\n";
-               if ( $this->siteConfig->get( 'ShowHostnames' ) ) {
+               if ( $this->svcOptions->get( 'ShowHostnames' ) ) {
                        $limitReport .= 'Parsed by ' . wfHostname() . "\n";
                }
                $limitReport .= 'Cached time: ' . $this->mOutput->getCacheTime() . "\n";
@@ -648,7 +721,7 @@ class Parser {
                $this->mOutput->setLimitReportData( 'limitreport-timingprofile', $profileReport );
 
                // Add other cache related metadata
-               if ( $this->siteConfig->get( 'ShowHostnames' ) ) {
+               if ( $this->svcOptions->get( 'ShowHostnames' ) ) {
                        $this->mOutput->setLimitReportData( 'cachereport-origin', wfHostname() );
                }
                $this->mOutput->setLimitReportData( 'cachereport-timestamp',
@@ -969,7 +1042,7 @@ class Parser {
         */
        public function getPreprocessor() {
                if ( !isset( $this->mPreprocessor ) ) {
-                       $class = $this->mPreprocessorClass;
+                       $class = $this->svcOptions->get( 'preprocessorClass' );
                        $this->mPreprocessor = new $class( $this );
                }
                return $this->mPreprocessor;
@@ -2386,7 +2459,7 @@ class Parser {
                                if (
                                        $iw && $this->mOptions->getInterwikiMagic() && $nottalk && (
                                                Language::fetchLanguageName( $iw, null, 'mw' ) ||
-                                               in_array( $iw, $this->siteConfig->get( 'ExtraInterlanguageLinkPrefixes' ) )
+                                               in_array( $iw, $this->svcOptions->get( 'ExtraInterlanguageLinkPrefixes' ) )
                                        )
                                ) {
                                        # T26502: filter duplicates
@@ -2718,7 +2791,7 @@ class Parser {
                                break;
                        case 'revisionid':
                                if (
-                                       $this->siteConfig->get( 'MiserMode' ) &&
+                                       $this->svcOptions->get( 'MiserMode' ) &&
                                        !$this->mOptions->getInterfaceMessage() &&
                                        // @TODO: disallow this word on all namespaces
                                        $this->nsInfo->isContent( $this->mTitle->getNamespace() )
@@ -2882,21 +2955,21 @@ class Parser {
                                $value = SpecialVersion::getVersion();
                                break;
                        case 'articlepath':
-                               return $this->siteConfig->get( 'ArticlePath' );
+                               return $this->svcOptions->get( 'ArticlePath' );
                        case 'sitename':
-                               return $this->siteConfig->get( 'Sitename' );
+                               return $this->svcOptions->get( 'Sitename' );
                        case 'server':
-                               return $this->siteConfig->get( 'Server' );
+                               return $this->svcOptions->get( 'Server' );
                        case 'servername':
-                               return $this->siteConfig->get( 'ServerName' );
+                               return $this->svcOptions->get( 'ServerName' );
                        case 'scriptpath':
-                               return $this->siteConfig->get( 'ScriptPath' );
+                               return $this->svcOptions->get( 'ScriptPath' );
                        case 'stylepath':
-                               return $this->siteConfig->get( 'StylePath' );
+                               return $this->svcOptions->get( 'StylePath' );
                        case 'directionmark':
                                return $pageLang->getDirMark();
                        case 'contentlanguage':
-                               return $this->siteConfig->get( 'LanguageCode' );
+                               return $this->svcOptions->get( 'LanguageCode' );
                        case 'pagelanguage':
                                $value = $pageLang->getCode();
                                break;
@@ -3838,7 +3911,7 @@ class Parser {
         * @return string
         */
        public function interwikiTransclude( $title, $action ) {
-               if ( !$this->siteConfig->get( 'EnableScaryTranscluding' ) ) {
+               if ( !$this->svcOptions->get( 'EnableScaryTranscluding' ) ) {
                        return wfMessage( 'scarytranscludedisabled' )->inContentLanguage()->text();
                }
 
@@ -3858,7 +3931,7 @@ class Parser {
                                ( $wikiId !== false ) ? $wikiId : 'external',
                                sha1( $url )
                        ),
-                       $this->siteConfig->get( 'TranscludeCacheExpiry' ),
+                       $this->svcOptions->get( 'TranscludeCacheExpiry' ),
                        function ( $oldValue, &$ttl ) use ( $url, $fname, $cache ) {
                                $req = MWHttpRequest::factory( $url, [], $fname );
 
@@ -4230,7 +4303,7 @@ class Parser {
 
                $headlines = $numMatches !== false ? $matches[3] : [];
 
-               $maxTocLevel = $this->siteConfig->get( 'MaxTocLevel' );
+               $maxTocLevel = $this->svcOptions->get( 'MaxTocLevel' );
                foreach ( $headlines as $headline ) {
                        $isTemplate = false;
                        $titleText = false;
@@ -4684,7 +4757,7 @@ class Parser {
 
                $nickname = $nickname == null ? $username : $nickname;
 
-               if ( mb_strlen( $nickname ) > $this->siteConfig->get( 'MaxSigChars' ) ) {
+               if ( mb_strlen( $nickname ) > $this->svcOptions->get( 'MaxSigChars' ) ) {
                        $nickname = $username;
                        wfDebug( __METHOD__ . ": $username has overlong signature.\n" );
                } elseif ( $fancySig !== false ) {
@@ -6005,7 +6078,7 @@ class Parser {
        }
 
        private function makeLegacyAnchor( $sectionName ) {
-               $fragmentMode = $this->siteConfig->get( 'FragmentMode' );
+               $fragmentMode = $this->svcOptions->get( 'FragmentMode' );
                if ( isset( $fragmentMode[1] ) && $fragmentMode[1] === 'legacy' ) {
                        // ForAttribute() and ForLink() are the same for legacy encoding
                        $id = Sanitizer::escapeIdForAttribute( $sectionName, Sanitizer::ID_FALLBACK );
index cddacf4..0446d9c 100644 (file)
@@ -18,6 +18,8 @@
  * @file
  * @ingroup Parser
  */
+
+use MediaWiki\Config\ServiceOptions;
 use MediaWiki\Linker\LinkRendererFactory;
 use MediaWiki\MediaWikiServices;
 use MediaWiki\Special\SpecialPageFactory;
@@ -26,8 +28,8 @@ use MediaWiki\Special\SpecialPageFactory;
  * @since 1.32
  */
 class ParserFactory {
-       /** @var array */
-       private $parserConf;
+       /** @var ServiceOptions */
+       private $svcOptions;
 
        /** @var MagicWordFactory */
        private $magicWordFactory;
@@ -41,9 +43,6 @@ class ParserFactory {
        /** @var SpecialPageFactory */
        private $specialPageFactory;
 
-       /** @var Config */
-       private $siteConfig;
-
        /** @var LinkRendererFactory */
        private $linkRendererFactory;
 
@@ -51,31 +50,61 @@ class ParserFactory {
        private $nsInfo;
 
        /**
-        * @param array $parserConf See $wgParserConf documentation
+        * Old parameter list, which we support for backwards compatibility, were:
+        *   array $parserConf See $wgParserConf documentation
+        *   MagicWordFactory $magicWordFactory
+        *   Language $contLang Content language
+        *   string $urlProtocols As returned from wfUrlProtocols()
+        *   SpecialPageFactory $spFactory
+        *   Config $siteConfig
+        *   LinkRendererFactory $linkRendererFactory
+        *   NamespaceInfo|null $nsInfo
+        *
+        * Some type declarations were intentionally omitted so that the backwards compatibility code
+        * would work. When backwards compatibility is no longer required, we should remove it, and
+        * and add the omitted type declarations.
+        *
+        * @param ServiceOptions|array $svcOptions
         * @param MagicWordFactory $magicWordFactory
         * @param Language $contLang Content language
         * @param string $urlProtocols As returned from wfUrlProtocols()
         * @param SpecialPageFactory $spFactory
-        * @param Config $siteConfig
         * @param LinkRendererFactory $linkRendererFactory
-        * @param NamespaceInfo|null $nsInfo
+        * @param NamespaceInfo|LinkRendererFactory|null $nsInfo
         * @since 1.32
         */
        public function __construct(
-               array $parserConf, MagicWordFactory $magicWordFactory, Language $contLang, $urlProtocols,
-               SpecialPageFactory $spFactory, Config $siteConfig,
-               LinkRendererFactory $linkRendererFactory, NamespaceInfo $nsInfo = null
+               $svcOptions, MagicWordFactory $magicWordFactory, Language $contLang,
+               $urlProtocols, SpecialPageFactory $spFactory, $linkRendererFactory,
+               $nsInfo = null
        ) {
+               // @todo Do we need to retain compat for constructing this class directly?
                if ( !$nsInfo ) {
                        wfDeprecated( __METHOD__ . ' with no NamespaceInfo argument', '1.34' );
                        $nsInfo = MediaWikiServices::getInstance()->getNamespaceInfo();
                }
-               $this->parserConf = $parserConf;
+               if ( $linkRendererFactory instanceof Config ) {
+                       // Old calling convention had an array in the format of $wgParserConf as the first
+                       // parameter, and a Config as the sixth, with LinkRendererFactory as the seventh.
+                       wfDeprecated( __METHOD__ . ' with Config parameter', '1.34' );
+                       $svcOptions = new ServiceOptions( Parser::$constructorOptions,
+                               $svcOptions,
+                               [ 'class' => Parser::class,
+                                       'preprocessorClass' => Parser::getDefaultPreprocessorClass() ],
+                               func_get_arg( 5 )
+                       );
+                       $linkRendererFactory = func_get_arg( 6 );
+                       $nsInfo = func_num_args() > 7 ? func_get_arg( 7 ) : null;
+               }
+               $svcOptions->assertRequiredOptions( Parser::$constructorOptions );
+
+               wfDebug( __CLASS__ . ": using preprocessor: {$svcOptions->get( 'preprocessorClass' )}\n" );
+
+               $this->svcOptions = $svcOptions;
                $this->magicWordFactory = $magicWordFactory;
                $this->contLang = $contLang;
                $this->urlProtocols = $urlProtocols;
                $this->specialPageFactory = $spFactory;
-               $this->siteConfig = $siteConfig;
                $this->linkRendererFactory = $linkRendererFactory;
                $this->nsInfo = $nsInfo;
        }
@@ -85,8 +114,8 @@ class ParserFactory {
         * @since 1.32
         */
        public function create() : Parser {
-               return new Parser( $this->parserConf, $this->magicWordFactory, $this->contLang, $this,
-                       $this->urlProtocols, $this->specialPageFactory, $this->siteConfig,
-                       $this->linkRendererFactory, $this->nsInfo );
+               return new Parser( $this->svcOptions, $this->magicWordFactory, $this->contLang, $this,
+                       $this->urlProtocols, $this->specialPageFactory, $this->linkRendererFactory,
+                       $this->nsInfo );
        }
 }
index aca5c73..53ed133 100644 (file)
@@ -182,7 +182,7 @@ abstract class ResourceLoaderModule implements LoggerAwareInterface {
        /**
         * Takes named templates by the module and returns an array mapping.
         *
-        * @return array of templates mapping template alias to content
+        * @return string[] Array of templates mapping template alias to content
         */
        public function getTemplates() {
                // Stub, override expected.
index d355db6..f45596f 100644 (file)
@@ -216,6 +216,7 @@ abstract class Skin extends ContextSource {
                // Preload jquery.tablesorter for mediawiki.page.ready
                if ( strpos( $out->getHTML(), 'sortable' ) !== false ) {
                        $modules['content'][] = 'jquery.tablesorter';
+                       $modules['styles']['content'][] = 'jquery.tablesorter.styles';
                }
 
                // Preload jquery.makeCollapsible for mediawiki.page.ready
index 56f5c8f..2443470 100644 (file)
@@ -880,7 +880,7 @@ class SpecialWatchlist extends ChangesListSpecialPage {
        private function getLatestNotificationTimestamp( RecentChange $rc ) {
                return $this->watchStore->getLatestNotificationTimestamp(
                        $rc->getAttribute( 'wl_notificationtimestamp' ),
-                       $rc->getPerformer(),
+                       $this->getUser(),
                        $rc->getTitle()
                );
        }
index 8358cd2..9b86812 100644 (file)
@@ -195,7 +195,7 @@ class PreferencesFormOOUI extends OOUIHTMLForm {
 
        /**
         * Get the keys of each top level preference section.
-        * @return array of section keys
+        * @return string[] List of section keys
         */
        function getPreferenceSections() {
                return array_keys( array_filter( $this->mFieldTree, 'is_array' ) );
index 7cfadc0..cdb8f25 100644 (file)
@@ -524,9 +524,15 @@ class NamespaceInfo {
                        return $levels;
                }
 
-               // First, get the list of groups that can edit this namespace.
-               $namespaceGroups = [];
-               $combine = 'array_merge';
+               // $wgNamespaceProtection can require one or more rights to edit the namespace, which
+               // may be satisfied by membership in multiple groups each giving a subset of those rights.
+               // A restriction level is redundant if, for any one of the namespace rights, all groups
+               // giving that right also give the restriction level's right. Or, conversely, a
+               // restriction level is not redundant if, for every namespace right, there's at least one
+               // group giving that right without the restriction level's right.
+               //
+               // First, for each right, get a list of groups with that right.
+               $namespaceRightGroups = [];
                foreach ( (array)$this->options->get( 'NamespaceProtection' )[$index] as $right ) {
                        if ( $right == 'sysop' ) {
                                $right = 'editprotected'; // BC
@@ -535,15 +541,11 @@ class NamespaceInfo {
                                $right = 'editsemiprotected'; // BC
                        }
                        if ( $right != '' ) {
-                               $namespaceGroups = call_user_func( $combine, $namespaceGroups,
-                                       User::getGroupsWithPermission( $right ) );
-                               $combine = 'array_intersect';
+                               $namespaceRightGroups[$right] = User::getGroupsWithPermission( $right );
                        }
                }
 
-               // Now, keep only those restriction levels where there is at least one
-               // group that can edit the namespace but would be blocked by the
-               // restriction.
+               // Now, go through the protection levels one by one.
                $usableLevels = [ '' ];
                foreach ( $this->options->get( 'RestrictionLevels' ) as $level ) {
                        $right = $level;
@@ -553,9 +555,19 @@ class NamespaceInfo {
                        if ( $right == 'autoconfirmed' ) {
                                $right = 'editsemiprotected'; // BC
                        }
-                       if ( $right != '' && ( !$user || $user->isAllowed( $right ) ) &&
-                               array_diff( $namespaceGroups, User::getGroupsWithPermission( $right ) )
+
+                       if ( $right != '' &&
+                               !isset( $namespaceRightGroups[$right] ) &&
+                               ( !$user || $user->isAllowed( $right ) )
                        ) {
+                               // Do any of the namespace rights imply the restriction right? (see explanation above)
+                               foreach ( $namespaceRightGroups as $groups ) {
+                                       if ( !array_diff( $groups, User::getGroupsWithPermission( $right ) ) ) {
+                                               // Yes, this one does.
+                                               continue 2;
+                                       }
+                               }
+                               // No, keep the restriction level
                                $usableLevels[] = $level;
                        }
                }
index 30e3cbe..b134bfe 100644 (file)
@@ -132,7 +132,7 @@ class WatchedItemQueryService {
         *                                 id fields ('rc_cur_id', 'rc_this_oldid', 'rc_last_oldid')
         *                                 if false (default)
         * @param array|null &$startFrom Continuation value: [ string $rcTimestamp, int $rcId ]
-        * @return array of pairs ( WatchedItem $watchedItem, string[] $recentChangeInfo ),
+        * @return array[] Array of pairs ( WatchedItem $watchedItem, string[] $recentChangeInfo ),
         *         where $recentChangeInfo contains the following keys:
         *         - 'rc_id',
         *         - 'rc_namespace',
index 9679cb2..a8cf5bd 100644 (file)
        "confirmable-no": "Nénten",
        "site-atom-feed": "$1 \"atom feed\"",
        "page-atom-feed": "$1 \"atom feed\"",
-       "red-link-title": "$1 (laman tan wénten)",
+       "red-link-title": "$1 (laman ten wénten)",
        "nstab-main": "Kaca",
        "nstab-user": "sane nganggo",
        "nstab-special": "lembar sane kautamayang",
index e634a37..8bcf065 100644 (file)
        "noemailtitle": "Адрас электроннай пошты адсутнічае",
        "noemailtext": "Гэты ўдзельнік не пазначыў слушны адрас электроннай пошты.",
        "nowikiemailtext": "Гэты ўдзельнік не дазволіў атрымліваць лісты па электроннай пошце ад іншых удзельнікаў.",
-       "emailnotarget": "Неіснуючае ці няслушнае імя атрымальніка.",
+       "emailnotarget": "Няіснае ці няслушнае імя атрымальніка.",
        "emailtarget": "Увядзіце імя атрымальніка",
        "emailusername": "Імя ўдзельніка:",
        "emailusernamesubmit": "Даслаць",
index 7fd8b98..4af0bd4 100644 (file)
        "nov": "Nup",
        "dec": "Dis",
        "pagecategories": "{{PLURAL:$1|Tumbung}}",
-       "category_header": "Tungkaran dalam tumbung \"$1\"",
+       "category_header": "Halaman dalam pilah \"$1\"",
        "subcategories": "Sub-tumbung",
        "category-media-header": "Média dalam pilah \"$1\"",
        "category-empty": "\"Kada tahaga tulisan maupun média dalam pilah ngini.\"",
        "hidden-category-category": "Tumbung tasungkup",
        "category-subcat-count": "{{PLURAL:$2|Tumbung ngini baisi asa sub-tumbung nangkaya ngini.|Pilih ngini baisi {{PLURAL:$1|sub-tumbung|$1 sub-tumbung}}, matan sabarataan $2.}}",
        "category-subcat-count-limited": "Tumbung ini baisi {{PLURAL:$1|sub-tumbung|$1 sub-tutumbung}} barikut.",
-       "category-article-count": "{{PLURAL:$2|Tumbung ngini baisi {{PLURAL:$1|$1 tungkaran}}, tumatan jumlah $2.}}",
+       "category-article-count": "{{PLURAL:$2|Pilah ngini baisi {{PLURAL:$1|$1 halaman}}, tumatan jumlah $2.}}",
        "category-article-count-limited": "Tumbung ini baisi {{PLURAL:$1|asa tungkaran|$1 tutungkaran}} barikut.",
        "category-file-count": "{{PLURAL:$2|Pilah ngini baisi {{PLURAL:$1|$1 barakas}}, matan jumlah $2.}}",
        "category-file-count-limited": "Tumbung ngini baisi {{PLURAL:$1|barakas|$1 barakas}} barikut.",
        "searchbutton": "Kikih",
        "go": "Tulak",
        "searcharticle": "Tulak",
-       "history": "Sajarah tungkaran",
+       "history": "Riwayat halaman",
        "history_short": "Sajarah",
        "history_small": "riwayat",
        "updatedmarker": "Dihanyari tumatan ilangan pauncitan ulun",
        "protect": "Lindungi",
        "protect_change": "ubah",
        "unprotect": "Palindungan",
-       "newpage": "Tungkaran hanyar",
+       "newpage": "Halaman hanyar",
        "talkpagelinktext": "pandir",
        "specialpage": "Tungkaran istimiwa",
        "personaltools": "Pakakas saurang",
        "edithelp": "Patulung mambabak",
        "helppage-top-gethelp": "Patulung",
        "mainpage": "Tungkaran Tatambaian",
-       "mainpage-description": "Tungkaran tatambaian",
+       "mainpage-description": "Halaman tatambaian",
        "policy-url": "Project:Kaaripan",
        "portal": "Lawang bubuhan",
        "portal-url": "Project:Lawang bubuhan",
        "red-link-title": "$1 (halaman baluman ada)",
        "sort-descending": "Surtir baturun",
        "sort-ascending": "Surtir banaik",
-       "nstab-main": "Tungkaran",
+       "nstab-main": "Halaman",
        "nstab-user": "Pamakai",
        "nstab-media": "Média",
-       "nstab-special": "Tungkaran istimiwa",
-       "nstab-project": "Tungkaran rangka gawian",
+       "nstab-special": "Halaman istimiwa",
+       "nstab-project": "Halaman rangka gawian",
        "nstab-image": "Barakas",
        "nstab-mediawiki": "Pasan",
        "nstab-template": "Citakan",
        "nstab-help": "Patulung",
        "nstab-category": "Tumbung",
-       "mainpage-nstab": "Tungkaran tatambaian",
+       "mainpage-nstab": "Halaman tatambaian",
        "nosuchaction": "Kadada palakuan nangkaitu",
        "nosuchactiontext": "Tindakan nang diminta URL kada sah.\nPian tagasnya salah katik URL, atawa maumpati sabuting tautan nang kada bujur.\nNgini jua bisa ai ada bug di parangkat lunak nang dipuruk {{SITENAME}}.",
-       "nosuchspecialpage": "Kadada tungkaran istimiwa nangitu",
-       "nospecialpagetext": "<strong>Pian maminta tungkaran istimiwa nang kada sah.</strong>\nDaptar tungkaran istimiwa sah kawa diugai pada [[Special:SpecialPages|{{int:specialpages}}]].",
+       "nosuchspecialpage": "Kadada halaman istimiwa nangitu",
+       "nospecialpagetext": "<strong>Pian maminta halaman istimiwa nang kada sah.</strong>\nDaptar halaman istimiwa sah kawa diugai pada [[Special:SpecialPages|{{int:specialpages}}]].",
        "error": "Kasalahan",
        "databaseerror": "Kasalahan Basisdata",
        "laggedslavemode": "'''Paringatan:''' Tungkaran ngini tagasnya kada baisi paubahan pahanyarnya.",
        "cannotdelete-title": "Kada kawa mahapus tungkaran \"$1\"",
        "delete-hook-aborted": "Pahapusan diwalangakan ulih kait parser.\nKadada katarangan.",
        "badtitle": "Judul buruk",
-       "badtitletext": "Judul tungkaran nang diminta kada sah, kada baisi, atawa kada pasnya tautan judul antar-basa atawa antar-wiki.\nNangini kawa baisi sabuting atawa labih hurup nang saharusnya kadada di judul.",
+       "badtitletext": "Judul halaman nang diminta kada sah, puang, atawa judul antarbasa atawa antarwiki nang salah sambung.",
        "perfcached": "Data barikut adalah timbuluk wan pina kada mutakhir. A maximum of {{PLURAL:$1|one result is|$1 results are}} available in the cache.",
        "perfcachedts": "Data nang dudi ni adalah timbuluk, wan tauncit dihahanyari pada $1. A maximum of {{PLURAL:$4|one result is|$4 results are}} available in the cache.",
        "querypage-no-updates": "Pamugaan matan tungkaran ngini rahat dipajahkan. Data nang ada di sia wayahini kada akan dimuat ulang.",
        "actionthrottled": "Kalakuan dikiripi",
        "actionthrottledtext": "Pian dibatasi gasan manggawi tindakan ngini talalu banyak dalam waktu handap, wan Pian sudah limpua batas nang dibarii. Silahkan cuba baasa imbah babarapa manit.",
        "protectedpagetext": "Tungkaran ngini sudah disunduk gasan mancagah babakan.",
-       "viewsourcetext": "Pian kawa maniringi wan manyalin asal-mula tungkaran ngini.",
+       "viewsourcetext": "Pian kawa manjanaki wan manyalin asal-mula halaman ngini.",
        "viewyourtext": "Pian kawa maniringi wan manyalin asalmula matan '''babakan pian''' ka tungkaran ngini:",
        "protectedinterface": "Tungkaran ngini manyadiakan naskah antarmuha gasan parangkat lunak, wan dilindungi tahadap panyalahpakaian. Gasan manambah atawa mambabak tarjamahan pada sabarataan wiki, muhun pakai [https://translatewiki.net translatewiki.net], pruyik palukalan MediaWiki.",
        "editinginterface": "'''Paringatan:''' Pian mambabak sabuting tungkaran nang dipuruk hagan manyadiakan naskah antarmuha gasan parangkat lunak.\nPaubahan ka tungkaran ngini akan bapangaruh matan tampaian antarmuha gasan pamakai lain.\nGasan tarjamahan, muhun pakai [https://translatewiki.net/wiki/Main_Page?setlang=bjn translatewiki.net], rangka gawian palokalan MediaWiki.",
        "createacct-submit": "Ulah akun Pian",
        "createacct-benefit-heading": "{{SITENAME}} diulah ulih urang-urang nangkaya Pian.",
        "createacct-benefit-body1": "{{PLURAL:$1|babakan}}",
-       "createacct-benefit-body2": "{{PLURAL:$1|tungkaran}}",
+       "createacct-benefit-body2": "{{PLURAL:$1|halaman}}",
        "createacct-benefit-body3": "{{PLURAL:$1|sumbangan}} pahabisnya",
        "badretype": "Katasunduk nang Pian buati kada pas.",
        "userexists": "Ngaran pamakai nang dibuati hudah dipuruk urang lain.\nMuhun pilih sabuting ngaran lain.",
        "summary": "Kasimpulan:",
        "subject": "Parihal:",
        "minoredit": "Ngini adalah babakan sapalih",
-       "watchthis": "Itihi tungkaran ngini",
-       "savearticle": "Simpan tungkaran",
+       "watchthis": "Itihi halaman ngini",
+       "savearticle": "Simpan halaman",
        "preview": "Tilik",
        "showpreview": "Tampaiakan titilikan",
        "showdiff": "Tampaiakan paubahan",
        "accmailtitle": "Katasunduk takirim.",
        "accmailtext": "Sabuting katasunduk babarang gasan [[User talk:$1|$1]] sudah dikirim ka $2.\n\nKatasunduk gasan pamakai hanyar nangini kawa diubah di tungkaran ''[[Special:ChangePassword|ubah katasunduk]]'' imbah babuat log.",
        "newarticle": "(Hanyar)",
-       "newarticletext": "Pian maumpati tautan ka tungkaran nang balum tasadia.Amun handak maulah tungkaran itu, katiklah isi tungkaran di kutak di bawah ngini (janaki [$1 tungkaran patulung] gasan maklumat labih lanjut). Amun pian kada bakurinah sampai ka tungkaran ngini, kalik picikan <strong>back</strong> di panjalajah wéb Pian.",
+       "newarticletext": "Pian maumpati tautan ka halaman nang balum tasadia. Amun handak maulah halaman itu, katiklah isi halaman di kutak di bawah ngini (janaki [$1 halaman patulung] gasan maklumat labih lanjut). Amun pian kada bakurinah sampai ka halaman ngini, kalik picikan <strong>back</strong> di panjalajah wéb Pian.",
        "anontalkpagetext": "----''Ngini adalah tungkaran pamandiran gasan pamakai kada bangaran nang baluman ma-ulah akun pulang, atawa  kada mamakainya. Kami tapaksa mamakai numurik alamat IP hagan maminanduinya.\nAlamat IP nangkaini kawaai dipuruk ulih babarapa pamakai.\nAmun Pian adalah pamakai kada bangaran wan marasa kumin nang kada pas ta ka Pian, muhun [[Special:CreateAccount|ulah sabuah akun]] atawa [[Special:UserLogin|babuat log]] gasan mahindari kabingungan awan pamakai kada bangaran lain kaina.",
-       "noarticletext": "Damini kadada naskah di tungkaran ngini.\nPian kawa [[Special:Search/{{PAGENAME}}|manggagai gasan judul tungkaran ngini]] di tutungkaran lain, <span class=\"plainlinks\">[{{fullurl:{{#Special:Log}}|page={{FULLPAGENAMEE}}}} mancari log tarait], atawa [{{fullurl:{{FULLPAGENAME}}|action=edit}} maulah tungkaran ngini]</span>.",
-       "noarticletext-nopermission": "Wayahini kadada naskah di tungkaran ngini.\nPian kawa [[Special:Search/{{PAGENAME}}|manggagai gasan judul tungkaran ngini]] di tutungkaran lain, atawa <span class=\"plainlinks\">[{{fullurl:{{#Special:Log}}|page={{FULLPAGENAMEE}}}} manggagai log tarait]</span>, tagal Pian kada baisi ijin gasan maulah tungkaran ngini",
+       "noarticletext": "Damini kadada naskah di halaman ngini.\nPian kawa [[Special:Search/{{PAGENAME}}|mangikihi gasan judul halaman ngini]] di halaman lain, <span class=\"plainlinks\">[{{fullurl:{{#Special:Log}}|page={{FULLPAGENAMEE}}}} mancari log tarait], atawa [{{fullurl:{{FULLPAGENAME}}|action=edit}} maulah halaman ngini]</span>.",
+       "noarticletext-nopermission": "Wayahini kadada naskah di halaman ngini.\nPian kawa [[Special:Search/{{PAGENAME}}|manggagai gasan judul halaman ngini]] di halaman lain, atawa <span class=\"plainlinks\">[{{fullurl:{{#Special:Log}}|page={{FULLPAGENAMEE}}}} manggagai log tarait]</span>, tagal Pian kada baisi ijin gasan maulah halaman ngini.",
        "userpage-userdoesnotexist": "Akun pamakai \"<nowiki>$1</nowiki>\" kada tadaptar.\nMuhun pariksa/ditukui amun Pian handak maulah/mambabak tungkaran ngini.",
        "userpage-userdoesnotexist-view": "Akun pamakai \"$1\" kada tadaptar.",
        "blocked-notice-logextract": "Pamakai nangini parhatan diblukir.\nLog blukir pahabisannya tasadia di bawah ngini gasan rujukan:",
        "semiprotectedpagewarning": "'''Catatan:''' Tungkaran ngini sudah dilindungi nang akibatnya pamakai tadaptar haja nang kawa mambabak.\nLog masuk pauncitnya disadiakan di bawah gasan rujukan:",
        "cascadeprotectedwarning": "<strong>Paringatan:</strong> Tungkaran ngini dilindungi jadinya pamakai lawan [[Special:ListGroupRights|hak aksis batantu] wara nang kawa mambabaknya maraga ditransklusiakan dalam {{PLURAL:$1|tungkaran|tungkaran-tungkaran}} nang dilindungi barinting.",
        "titleprotectedwarning": "'''Paringatan: Tungkaran ngini sudah dilindungi nang akibatnya [[Special:ListGroupRights|hak khas]] diparluakan hagan maulah ngini.'''\nLog masuk pauncitnya disadiakan di bawah gasan rujukan:",
-       "templatesused": "{{PLURAL:$1|Citakan|Cicitakan}} nang dipakai di tungkaran ngini:",
+       "templatesused": "{{PLURAL:$1|Citakan|Citakan}} nang dipakai di halaman ngini:",
        "templatesusedpreview": "{{PLURAL:$1|Citakan|Cicitakan}} nang dipakai di titilikan ngini:",
        "templatesusedsection": "{{PLURAL:$1|Citakan|Cicitakan}} nang diguna'akan di hagian ini:",
        "template-protected": "(dilindungi)",
        "permissionserrorstext": "Pian kada baisi ijin gasan malakuakan itu, karana {{PLURAL:$1|alasan|alasan}} ini:",
        "permissionserrorstext-withaction": "Pian kada baisi ijin gasan $2, karana {{PLURAL:$1|alasan|alasan}} ini:",
        "recreate-moveddeleted-warn": "'''Paringatan: Pian maulah pulang sabuah tungkaran nang sabalumnya dihapus.'''\n\nPian partimbangakan dahulu sasuaikah hagan manarusakan pambabakan tungkaran ini.\nLog pahapusan wan paugahan gasan tungkaran ini disadiakan di sia:",
-       "moveddeleted-notice": "Tungkaran ini sudah dihapus.\nLog pahapusan, palindungan, wan pamindahan matan tungkaran itu tasadia di bawah ini sabagai rujukan.",
+       "moveddeleted-notice": "Halaman ini sudah dihapus.\nLog pahapusan, palindungan, wan pamindahan matan halaman itu tasadia di bawah ini sabagai rujukan.",
        "log-fulllog": "Tiringi samunyaan log",
        "edit-hook-aborted": "Babakan ditinggalakan ulih kakait parser.\nIni kadada panjalasan.",
        "edit-gone-missing": "Kada kawa mamutakhirakan tungkaran ini.\nIni cungul pinanya sudah tahapus.",
        "undo-norev": "Babakan kada kawa diwalangi karana ini kadada atawa tahapus.",
        "undo-summary": "←Mawalangakan ralatan $1 ulih [[Special:Contributions/$2|$2]] ([[User talk:$2|Pandir]])",
        "cantcreateaccount-text": "Paulahan akun matan alamat IP ('''$1''') sudah diblukir ulih [[User:$3|$3]].\n\nAlasan nang dibari ulih $3 adalah ''$2''",
-       "viewpagelogs": "Janaki log tungkaran ini",
+       "viewpagelogs": "Janaki log halaman ngini",
        "nohistory": "Kadada halam babakan gasan tungkaran ini.",
        "currentrev": "Ralatan pahabisannya",
        "currentrev-asof": "Ralatan pahanyarnya pada $1",
        "nextn": "{{PLURAL:$1|$1}} imbahnya",
        "prevn-title": "Tadahulu $1 {{PLURAL:$1|kulihan|kulihan-kulihan}}",
        "nextn-title": "$1 {{PLURAL:$1|kulihan|kulihan-kulihan}} imbahnya",
-       "shown-title": "Tampaiakan $1 {{PLURAL:$1|kulihan|kukulihan}} par tungkaran",
+       "shown-title": "Tampaiakan $1 {{PLURAL:$1|kulihan}} par halaman",
        "viewprevnext": "Tiringi ($1 {{int:pipe-separator}} $2) ($3)",
        "searchmenu-exists": "'''Ada tungkaran bangaran \"[[:$1]]\" dalam wiki ini.'''",
-       "searchmenu-new": "<strong>Ulah tungkaran \"[[:$1]]\" di wiki ngini!</strong> {{PLURAL:$2|0=|Itihi jua tungkaran nang didapatakan matan panggagaian Pian.|Itihi jua hasil panggagaian nang didapatakan.}}",
-       "searchprofile-articles": "Tungkaran isi",
+       "searchmenu-new": "<strong>Ulah halaman \"[[:$1]]\" di wiki ngini!</strong> {{PLURAL:$2|0=|Itihi jua halaman nang dihagaakan matan pangikihan Pian.|Itihi jua kulihan pangikihan nang dihagaakan.}}",
+       "searchprofile-articles": "Halaman isi",
        "searchprofile-images": "Multimadia",
        "searchprofile-everything": "Samunyaan",
        "searchprofile-advanced": "Haratan",
        "rightslog": "Log paubahan hak masuk",
        "rightslogtext": "Nangini sabuting log paubahan ka hak pamakai.",
        "action-read": "baca tungkaran ini",
-       "action-edit": "babak tungkaran ini",
+       "action-edit": "babak halaman ini",
        "action-createpage": "ulah tutungkaran",
        "action-createtalk": "ulah tutungkaran pamandiran",
        "action-createaccount": "ulah akun pamakai ini",
        "enhancedrc-history": "sajarah",
        "recentchanges": "Paubahan pahanyarnya",
        "recentchanges-legend": "Pilihan paubahan pahanyarnya",
-       "recentchanges-summary": "Jajak paubahan wiki pahanyarnya pada tungkaran ngini",
+       "recentchanges-summary": "Jajak paubahan wiki pahanyarnya pada halaman ngini",
        "recentchanges-noresult": "Kadada paubahan dalam rantang waktu ngini nang rasuk lawan syarat.",
        "recentchanges-feed-description": "Susuri paubahan pahanyarnya dalam wiki di kitihan ini",
-       "recentchanges-label-newpage": "Babakan ngini maulah sabuting tungkaran hanyar",
+       "recentchanges-label-newpage": "Babakan ngini maulah sabuting halaman hanyar",
        "recentchanges-label-minor": "Ngini babakan sapalih",
        "recentchanges-label-bot": "Babakan ngini digawi ulih bot",
        "recentchanges-label-unpatrolled": "Babakan ngini baluman ta'awasi",
-       "recentchanges-label-plusminus": "Paubahan ukuran tungkaran dalam bita",
+       "recentchanges-label-plusminus": "Paubahan ukuran halaman dalam bita",
        "recentchanges-legend-heading": "<strong>Katarangan:</strong>",
-       "recentchanges-legend-newpage": "{{int:recentchanges-label-newpage}} (tiringi jua [[Special:NewPages|daptar tungkaran hanyar]])",
+       "recentchanges-legend-newpage": "{{int:recentchanges-label-newpage}} (janaki jua [[Special:NewPages|daptar halaman hanyar]])",
        "rcnotefrom": "Di bawah ngini adalah {{PLURAL:$5|paubahan}} tumatan <strong>$3, $4</strong> (ditampaiakan sampai <strong>$1</strong> paubahan).",
        "rclistfrom": "Tampaiakan paubahan pahanyarnya matan $3 $2",
        "rcshowhideminor": "$1 pambabakan sapalih",
        "recentchangeslinked-feed": "Paubahan tarait",
        "recentchangeslinked-toolbox": "Paubahan tarait",
        "recentchangeslinked-title": "Paubahan nang tarait lawan \"$1\"",
-       "recentchangeslinked-summary": "Masukakan ngaran halaman gasan malihat paubahan pada tungkaran tarait matan atawa ka tungkaran ngintu (amun handak malihat angguta sabuting tumbung, masukakan {{ns:category}}). Paubahan pada [[Special:Watchlist|daptar itihan Pian]] talihat <strong>dicitak kandal</strong>.",
-       "recentchangeslinked-page": "Ngaran tungkaran:",
-       "recentchangeslinked-to": "Tampaiakan paubahan matan tutungkaran nang barait lawan tungkaran nang disurungakan",
+       "recentchangeslinked-summary": "Masukakan ngaran halaman gasan malihat paubahan pada halaman tarait matan atawa ka halaman ngintu (amun handak malihat angguta sabuting pilah, masukakan {{ns:category}}). Paubahan pada [[Special:Watchlist|daptar itihan Pian]] talihat <strong>dicitak kandal</strong>.",
+       "recentchangeslinked-page": "Ngaran halaman:",
+       "recentchangeslinked-to": "Tampaiakan paubahan matan halaman nang barait lawan halaman nang disurungakan",
        "upload": "Unggah barakas",
        "uploadbtn": "Hunggahakan barakas",
        "reuploaddesc": "Babulik ka furmulir paunggahan",
        "filehist-filesize": "Ukuran barakas",
        "filehist-comment": "Ulasan",
        "imagelinks": "Tautan barakas",
-       "linkstoimage": "{{PLURAL:$1|Tungkaran|$1 tungkaran}} nangini mamakai barakas ngini:",
+       "linkstoimage": "{{PLURAL:$1|Halaman|$1 halaman}} nangini mamakai barakas ngini:",
        "linkstoimage-more": "Labih daripada $1 {{PLURAL:$1|pamakaian tungkaran|pamakaian tutungkaran}} ka barakas ngini.\nDaptar barikut manampaiakan {{PLURAL:$1|tungkaran panambaian|$1 tungkaran panambaiam}} nang mamakai barakas ngini haja.\nSabuah [[Special:WhatLinksHere/$2|daptar hibak]] tasadia.",
        "nolinkstoimage": "Kadada tutungkaran nang mamakai barakas ngini.",
        "morelinkstoimage": "Tiringi [[Special:WhatLinksHere/$1|tautan lagi]] ka barakas ngini.",
        "duplicatesoffile": "Barikut {{PLURAL:$1|barakas panggandaan|$1 babarakas panggandaan}} matan barakas ngini ([[Special:FileDuplicateSearch/$2|rarincian labih]]):",
        "sharedupload": "Barakas ini matan $1 wan mungkin dipuruk rangka-rangka gawian lain.",
        "sharedupload-desc-there": "Barakas ngini matan $1 wan pina dipuruk ulih rarangka-gawi lain.\nMuhun janaki [$2 tungkaran diskripsi barakas] gasan panjalasan labih.",
-       "sharedupload-desc-here": "Barakas ngini matan $1 wan pina dipakai ulih rarangka-gawi lain.\nDiskripsi ngini [$2 tungkaran diskripsi barakas] ditampaiakan di bawah.",
+       "sharedupload-desc-here": "Barakas ngini matan $1 wan pinanya dipakai ulih rangka-gawi lain.\nPamaparan ngini [$2 halaman diskripsi barakas] ditampaiakan di bawah.",
        "filepage-nofile": "Kadada barakas bangaran ngini.",
        "filepage-nofile-link": "Kadada barakas bangaran ngini tasadia, tagal Pian kawa [$1 mahunggah ngini].",
        "uploadnewversion-linktext": "Buatakan bantuk nang labih hanyar matan barakas ini",
        "unusedtemplates": "Citakan nang kada dipuruk",
        "unusedtemplatestext": "Daptar barikut adalah samua tungkaran pada ngaran kamar {{ns:template}} nang kada dipuruk di tungkaran manapun.\nPariksa 'hulu tautan lain ka citakan itu sabalum mahapusnya.",
        "unusedtemplateswlh": "tautan lain",
-       "randompage": "Tungkaran babarang",
+       "randompage": "Halaman babarang",
        "randompage-nopages": "Kadada tungkaran pada {{PLURAL:$2||}}kamar ngaran ini: $1.",
        "randomredirect": "Paugahan babarang",
        "randomredirect-nopages": "Kada tadapat paugahan pada ngaran kamar \"$1\".",
        "listusers-creationsort": "Susun ulih tanggal paulahan",
        "usereditcount": "$1 {{PLURAL:$1|babakan|bababakan}}",
        "usercreated": "{{GENDER:$3|Diulah}} pada $1 pukul $2",
-       "newpages": "Tungkaran hanyar",
+       "newpages": "Halaman hanyar",
        "newpages-username": "Ngaran pamakai:",
        "ancientpages": "Tutungkaran panuhanya",
        "move": "Pindahakan",
        "prevpage": "Tungkaran sabalumnya ($1)",
        "allpagesfrom": "Manampaiakan tungkaran mulai matan:",
        "allpagesto": "Manampaiakan ujung pahabisan tungkaran:",
-       "allarticles": "Samunyaan tungkaran",
+       "allarticles": "Samunyaan halaman",
        "allinnamespace": "Sabarataan tutungkaran (ngaran-kamar $1)",
        "allpagessubmit": "Tulak",
        "allpagesprefix": "Tampilakan tutungkaran bamula lawan:",
        "sp-contributions-newonly": "Hanya tampaiakan babakan nang barupa paulahan tungkaran",
        "sp-contributions-submit": "Kikih",
        "whatlinkshere": "Tautan balik",
-       "whatlinkshere-title": "Tungkaran-tungkaran nang batautan ka ''$1''",
-       "whatlinkshere-page": "Tungkaran:",
-       "linkshere": "Tungkaran-tungkaran barikut batautan ka <strong>$2</strong>:",
+       "whatlinkshere-title": "Halaman nang batautan ka ''$1''",
+       "whatlinkshere-page": "Halaman:",
+       "linkshere": "Halaman nangini batautan ka <strong>$2</strong>:",
        "nolinkshere": "Kadada tutungkaran tataut ka '''$2'''.",
        "nolinkshere-ns": "Kadada tutungkaran tataut ka '''$2''' dalam ruang-ngaran nang dipilih.",
-       "isredirect": "tungkaran paugahan",
+       "isredirect": "halaman paugahan",
        "istemplate": "transklusi",
        "isimage": "tautan barakas",
        "whatlinkshere-prev": "$1 {{PLURAL:$1|sabalumnya|sabalumnya}}",
        "semiprotectedpagemovewarning": "'''Catatan:''' Tungkaran ngini sudah dilindungi laluai pamuruk tadaptar haja nang kawa mamindahakan ngini.\nLog masuk pauncitan disadiakan di bawah gasan rujukan:",
        "move-over-sharedrepo": "==Barakas ada==\n[[:$1]] ada pintangan panyimpanan babagi. Mamindahakan sabuah barakas ka judul ngini akan manulis-tindih barakas babagi.",
        "file-exists-sharedrepo": "Ngaran barakas nang dipilih sudah dipuruk pintangan panyimpanan babagi.\nMuhun pilih ngaran lain.",
-       "export": "Kirimi tungkaran ka luar",
+       "export": "Kirimi halaman ka luar",
        "exporttext": "Pian kawa ma-ikspur naskah wan halam babakan matan sabuah tungkaran tartantu atawa sarangkai tutungkaran tabungkus dalam bantuk XML.\nNgini kawa di-impur dalam wiki lain mamuruk MediaWiki lung [[Special:Import|tungkaran impur]].\n\nHagan ma-ikspur tutungkaran, buati judul dalam kutak naskah di bawah, asa judul par garis, wan pilihi nang mana Pian handak ralatan tadamini nangkaitu jua samunyaan raralatan lawas, awan garis tungkaran halam, atawa ralatan tadamini awan panjalasan pasal babakan ta-uncit.\n\nDalam kasus pahanyarnya Pian kawa jua mamuruk sabuah tautanm gasan cuntuh [[{{#Special:Export}}/{{MediaWiki:Mainpage}}]] gasan tungkaran \"[[{{MediaWiki:Mainpage}}]]\".",
        "exportall": "Ekspor samunyaan tungkaran.",
        "exportcuronly": "Tamasuk ralatan tadamini haja, kada sahibakan halam",
        "import-logentry-upload-detail": "$1 {{PLURAL:$1|ralatan|raralatan}}",
        "import-logentry-interwiki-detail": "$1 {{PLURAL:$1|ralatan|raralatan}} matan $2",
        "javascripttest": "Mantis JavaScript",
-       "tooltip-pt-userpage": "Tungkaran {{GENDER:|pamakai Pian}}",
+       "tooltip-pt-userpage": "Halaman {{GENDER:|pamakai Pian}}",
        "tooltip-pt-anonuserpage": "Tungkaran pamakai IP Pian",
-       "tooltip-pt-mytalk": "Tungkaran {{GENDER:|pamandiran Pian}}",
+       "tooltip-pt-mytalk": "Halaman {{GENDER:|pamandiran Pian}}",
        "tooltip-pt-anontalk": "Pamandiran pasal bababakan matan alamat IP ngini",
        "tooltip-pt-preferences": "Kakatujuan {{GENDER:|Pian}}",
-       "tooltip-pt-watchlist": "Daptar tungkaran-tungkaran nang Pian itihi paubahannya",
+       "tooltip-pt-watchlist": "Daptar halaman nang Pian itihi paubahannya",
        "tooltip-pt-mycontris": "Daptar sumbangan {{GENDER:|Pian}}",
        "tooltip-pt-login": "Pian sabaiknya babuat ka dalam log; tagal ngini kada kawajiban pang",
        "tooltip-pt-logout": "Kaluar log",
        "tooltip-pt-createaccount": "Pian dianjurakan gasan maulah akun wan babuat log; tagal, hal ngintu kada wajib",
-       "tooltip-ca-talk": "Pamandiran pasal isi tungkaran",
-       "tooltip-ca-edit": "Babak tungkaran ngini",
+       "tooltip-ca-talk": "Pamandiran pasal isi halaman",
+       "tooltip-ca-edit": "Babak halaman ngini",
        "tooltip-ca-addsection": "Mulai hagian hanyar",
-       "tooltip-ca-viewsource": "Tungkaran ngini dilindungi. Pian kawa maniring asal mulanya.",
-       "tooltip-ca-history": "Ralatan bahari tungkaran ngini",
+       "tooltip-ca-viewsource": "Halaman ngini dilindungi. Pian kawa manjanaki asal mulanya.",
+       "tooltip-ca-history": "Ralatan bahari halaman ngini",
        "tooltip-ca-protect": "Lindungi tungkaran ini",
        "tooltip-ca-unprotect": "Ganti parlindungan tungkaran ngini",
        "tooltip-ca-delete": "Hapus tungkaran ini",
        "tooltip-ca-undelete": "Bulikakan babakan ka tungkaran ini sabalum tungkaran ini dihapus",
-       "tooltip-ca-move": "Pindahakan tungkaran ngini",
-       "tooltip-ca-watch": "Tambahi tungkaran ngini ka daptar itihan Pian",
+       "tooltip-ca-move": "Pindahakan halaman ngini",
+       "tooltip-ca-watch": "Tambahi halaman ngini ka daptar itihan Pian",
        "tooltip-ca-unwatch": "Buang tungkaran ngini matan daptar itihan Pian",
        "tooltip-search": "Gagai di {{SITENAME}}",
        "tooltip-search-go": "Tulak ka sabuting halaman bangaran sama amun sudah ada",
-       "tooltip-search-fulltext": "Gagai tungkaran nang baisi naskah nang kaya ngini",
-       "tooltip-p-logo": "Ilangi tungkaran tatambaian",
-       "tooltip-n-mainpage": "Ilangi tungkaran tatambaian",
-       "tooltip-n-mainpage-description": "Ilangi tungkaran tatambaian",
+       "tooltip-search-fulltext": "Gagai halaman nang baisi naskah nang kaya ngini",
+       "tooltip-p-logo": "Ilangi halaman tatambaian",
+       "tooltip-n-mainpage": "Ilangi halaman tatambaian",
+       "tooltip-n-mainpage-description": "Ilangi halaman tatambaian",
        "tooltip-n-portal": "Pasal rangka-gawian, apa nang kawa pian gawi, di mana gasan manggagai sasuatu",
        "tooltip-n-currentevents": "Gagai panjalasan pasal garamaan",
        "tooltip-n-recentchanges": "Daptar paubahan pahanyarnya dalam wiki",
-       "tooltip-n-randompage": "Tampaiakan babarang tungkaran",
+       "tooltip-n-randompage": "Tampaiakan babarang halaman",
        "tooltip-n-help": "Wadah manggagai patulung",
-       "tooltip-t-whatlinkshere": "Daptar samunyaan tungkaran wiki nang ada tautan ka sini",
-       "tooltip-t-recentchangeslinked": "Paubahan pahanyarnya dalam tungkaran nang baisi tautan tumatan tungkaran ngini",
+       "tooltip-t-whatlinkshere": "Daptar samunyaan halaman wiki nang ada tautan ka sini",
+       "tooltip-t-recentchangeslinked": "Paubahan pahanyarnya dalam halaman nang baisi tautan tumatan halaman ngini",
        "tooltip-feed-rss": "Kitihan RSS gasan tungkaran ini",
        "tooltip-feed-atom": "Kitihan Atum gasan tungkaran ngini",
        "tooltip-t-contributions": "Daptar sumbangan {{GENDER:$1|pamakai ngini}}",
        "tooltip-t-emailuser": "Kirimi suril ka {{GENDER:$1|pamakai ngini}}",
        "tooltip-t-upload": "Unggah barakas",
-       "tooltip-t-specialpages": "Daptar samunyaan tungkaran istimiwa",
-       "tooltip-t-print": "Vérsi citak tungkaran ngini",
-       "tooltip-t-permalink": "Tautan tatap ka ralatan tungkaran ngini",
-       "tooltip-ca-nstab-main": "Tiring tungkaran isi",
-       "tooltip-ca-nstab-user": "Tiring tungkaran pamakai",
+       "tooltip-t-specialpages": "Daptar samunyaan halaman istimiwa",
+       "tooltip-t-print": "Vérsi citak halaman ngini",
+       "tooltip-t-permalink": "Tautan tatap ka ralatan halaman ngini",
+       "tooltip-ca-nstab-main": "Janaki halaman isi",
+       "tooltip-ca-nstab-user": "Janaki halaman pamakai",
        "tooltip-ca-nstab-media": "Tiringi tungkaran media",
-       "tooltip-ca-nstab-special": "Ngini tungkaran istimiwa, kada kawa dibabak.",
-       "tooltip-ca-nstab-project": "Janaki tungkaran rangka gawian",
-       "tooltip-ca-nstab-image": "Tiringi tungkaran barakas",
+       "tooltip-ca-nstab-special": "Ngini halaman istimiwa, kada kawa dibabak.",
+       "tooltip-ca-nstab-project": "Janaki halaman rangka gawian",
+       "tooltip-ca-nstab-image": "Janaki halaman barakas",
        "tooltip-ca-nstab-mediawiki": "Janaki pasan sistem",
        "tooltip-ca-nstab-template": "Janaki citakan",
        "tooltip-ca-nstab-help": "Tiringi tungkaran patulung",
-       "tooltip-ca-nstab-category": "Tiring tungkaran tumbung",
+       "tooltip-ca-nstab-category": "Janaki halaman pilah",
        "tooltip-minoredit": "Tandai ngini sabagai sabutik pambabakan sapalih",
        "tooltip-save": "Simpan paubahan Pian",
        "tooltip-preview": "Tilik paubahan Pian. Muhun pakai ngini sabalum manyimpan.",
        "tooltip-watchlistedit-raw-submit": "Hanyari daptar itihan",
        "tooltip-recreate": "Ulah pulang tungkaran biar gin suah dihapus",
        "tooltip-upload": "Mulai pangunggahan",
-       "tooltip-rollback": "\"Pambulik\" mawalang babakan-babakan di tungkaran ngini ka panyumbang pahabisan dalam satu kali kalik.",
+       "tooltip-rollback": "\"Pambulik\" mamasahakan babakan-babakan di halaman ngini ka panyumbang pahabisan dalam satu kali kalik.",
        "tooltip-undo": "\"Bulikakan\" mawalangi ralatan ngini wan mambuka kutak pambabakan lawan mode tilik. Alasan kawa ditambahakan di kutak kasimpulan.",
        "tooltip-preferences-save": "Simpan kakatujuan",
        "tooltip-summary": "Buati sabuting kasimpulan handap",
        "pageinfo-hidden-categories": "{{PLURAL:$1|Pilah|Pilah}} tatukup ($1)",
        "pageinfo-templates": "{{PLURAL:$1|Citakan|Cicitakan}} nang ditransklusi ($1)",
        "pageinfo-transclusions": "{{PLURAL:$1|Tungkaran|Tutungkaran}} ditransklusikan pada ( $1 )",
-       "pageinfo-toolboxlink": "Panjalasan tungkaran",
+       "pageinfo-toolboxlink": "Panjalasan halaman",
        "pageinfo-redirectsto": "Ba-ugah ka",
        "pageinfo-redirectsto-info": "Maklumat",
        "pageinfo-contentpage": "Dirikin sabagai tungkaran isi",
        "metadata-help": "Barakas ngini mangandung panjalasan tambahan, mungkin ditambahakan ulih kudakan atawa paundai nang dipakai gasan maulah atawa digitalisasi barakas. Amun barakas ngini sudah diubah, parincian nang ada mungkin kada sapanuhnya sasuai lawan barakas nang diubah.",
        "metadata-expand": "Tampaiakan tambahan rincian",
        "metadata-collapse": "Sungkupakan tambahan rincian",
-       "metadata-fields": "Pancitraan metadata tadaptar dalam pasan ngini akan masuk dalam tungkaran pancitraan wayah tabel metadata tasungkup. Nang lainnya cagaran babaku tasungkup.\n* make\n* model\n* datetimeoriginal\n* exposuretime\n* fnumber\n* isospeedratings\n* focallength\n* artist\n* copyright\n* imagedescription\n* gpslatitude\n* gpslongitude\n* gpsaltitude",
+       "metadata-fields": "Pancitraan metadata tadaptar dalam pasan ngini akan masuk dalam halaman pancitraan wayah tabel metadata tatukup. Nang lainnya cagaran babaku tatukup.\n* make\n* model\n* datetimeoriginal\n* exposuretime\n* fnumber\n* isospeedratings\n* focallength\n* artist\n* copyright\n* imagedescription\n* gpslatitude\n* gpslongitude\n* gpsaltitude",
        "namespacesall": "samunyaan",
        "monthsall": "samunyaan",
        "confirmemail": "Yakinakan alamat suril",
        "fileduplicatesearch-result-1": "Barakas ''$1'' kada baisi panggandaan parsis.",
        "fileduplicatesearch-result-n": "Barakas ''$1'' baisi {{PLURAL:$2|1 panggandaan parsis|$2 papanggandaan parsis}}.",
        "fileduplicatesearch-noresults": "Kadada barakas bangaran ''$1'' taugai.",
-       "specialpages": "Tungkaran istimiwa",
+       "specialpages": "Halaman istimiwa",
        "specialpages-note-restricted": "* Tutungkaran istimiwa normal\n* <span class=\"mw-specialpagerestricted\">Tutungkaran istimiwa tabatas.</span>\n* <span class=\"mw-specialpagecached\">Tutungkaran istimiwa timbuluk (pinanya bakulat).</span>",
        "specialpages-group-maintenance": "Lapuran pamaliharaan",
        "specialpages-group-other": "Tungkaran istimiwa lainnya",
        "htmlform-submit": "Kirim",
        "htmlform-reset": "Bulikakan paubahan",
        "htmlform-selectorother-other": "Lain-lain",
-       "logentry-delete-delete": "$1 {{GENDER:$2|mahapus}} tungkaran $3",
-       "logentry-delete-restore": "$1 {{GENDER:$2|mambulikakan}}tungkaran $3 ($4)",
+       "logentry-delete-delete": "$1 {{GENDER:$2|mahapus}} halaman $3",
+       "logentry-delete-restore": "$1 {{GENDER:$2|mambulikakan}} tungkaran $3 ($4)",
        "logentry-delete-event": "$1 mangganti kakawaan dijanaki {{PLURAL:$5|sabuah log kajadian|$5 log kajadian}} pintangan $3: $4",
        "logentry-delete-revision": "$1 {{GENDER:$2|maubah}} tampaian {{PLURAL:$5|$5 ralatan}} di tungkaran $3: $4",
        "logentry-delete-event-legacy": "$1 mangganti kakawaan dijanaki log kajadian pintangan $3",
        "revdelete-uname-unhid": "ngaran pamakai kada disungkupakan",
        "revdelete-restricted": "Talamar pambatasan hagan pambakal-pambakal",
        "revdelete-unrestricted": "Buang pambatasan gasan pambakal-pambakal",
-       "logentry-move-move": "$1 {{GENDER:$2|mamindahakan}} tungkaran $3 ka $4",
+       "logentry-move-move": "$1 {{GENDER:$2|mamindahakan}} halaman $3 ka $4",
        "logentry-move-move-noredirect": "$1 {{GENDER:$2|mamindahakan}} tungkaran $3 ka $4 kada pakai maulah paugahan",
        "logentry-move-move_redir": "$1 {{GENDER:$2|mamindahakan}} tungkaran $3 ka $4 manimpa paugahan lawas",
        "logentry-move-move_redir-noredirect": "$1 diugah tungkaran $3 ka $4 lung sabuah paugahan awan-kada maninggalakan sabuah paugahan",
index c5f501e..f3a4d8d 100644 (file)
        "ipb-confirm": "বাধা নিশ্চিতকরণ",
        "ipb-sitewide": "সাইটব্যাপী",
        "ipb-partial": "আংশিক",
+       "ipb-sitewide-help": "উইকিতে সব পাতা ও অন্যান্য সব অবদানে বাধা।",
+       "ipb-partial-help": "নির্দিষ্ট পাতা ও নামস্থানসমূহ।",
        "ipb-pages-label": "পাতা",
        "ipb-namespaces-label": "নামস্থানসমূহ",
        "badipaddress": "আইপি (IP) ঠিকানাটি অগ্রহনযোগ্য",
index 74b255a..9a10b4f 100644 (file)
@@ -6,7 +6,8 @@
                        "아라",
                        "Aguve",
                        "Latercio2000",
-                       "Hello903hello"
+                       "Hello903hello",
+                       "Enock4seth"
                ]
        },
        "tog-underline": "Flitete ɖe kadodo te:",
        "period-pm": "ŊDƆ",
        "pagecategories": "{{PLURAL:$1|Hatsotso|Hatsotsowo}}",
        "category_header": "Axa siwo le hatsotso \"$1\"",
-       "hidden-categories": "{{PLURAL:$1||Hatsotso ɣaɣla|Hatsotso ɣaɣla}}",
+       "hidden-categories": "{{PLURAL:$1|Hatsotso ɣaɣla|Hatsotso ɣaɣlawo}}",
        "listingcontinuesabbrev": "yi edzi",
        "about": "Eŋunya",
        "newwindow": "(eʋua fesre yeye)",
index d350c34..2acc89c 100644 (file)
        "virus-scanfailed": "skanado malsukcesis (kun kodo $1)",
        "virus-unknownscanner": "nekonata kontraŭvirusilo:",
        "logouttext": "<strong>Vi nun estas elsalutinta.</strong>\n\nNotu ke por iuj paĝoj eble ŝajnos kvazaŭ vi ankoraŭ estus ensalutinta, ĝis kiam vi vakigos la kaŝmemoron de via retumilo.",
+       "logging-out-notify": "Vi estas elsalutanta; bonvolu atendi.",
+       "logout-failed": "Vi ne povas elsaluti nun: $1",
        "cannotlogoutnow-title": "Nuntempe ne eblas elsaluti",
        "cannotlogoutnow-text": "Ne eblas elsaluti dum uzado de $1.",
        "welcomeuser": "Bonvenon, $1!",
        "resetpass-abort-generic": "La ŝanĝo de pasvorto estas nuligita de kromprogramo.",
        "resetpass-expired": "Via pasvorto eksvalidiĝis. Bonvolu starigi novan pasvorton por ensaluti.",
        "resetpass-expired-soft": "Via pasvorto eksvalidiĝis kaj devas esti ŝanĝata. Bonvolu nun elekti novan pasvorton, aŭ alklaki \"{{int:authprovider-resetpass-skip-label}}\" por ŝanĝi ĝin poste.",
+       "resetpass-validity": "Via pasvorto ne estas valida: $1\n\nBonvolu fari novan pasvorton por ensaluti.",
        "resetpass-validity-soft": "Via pasvorto ne estas valida: $1\n\nBonvolu elekti novan pasvorton nun, aŭ alklaku \"{{int:authprovider-resetpass-skip-label}}\" por ŝanĝi ĝin poste.",
        "passwordreset": "Restarigo de la pasvorto",
        "passwordreset-text-one": "Plenigu ĉi tiun formularon por ricevi provizoran pasvorton per retpoŝto.",
        "localtime": "Loka tempo:",
        "timezoneuseserverdefault": "Uzi implicitaĵon de servilo ($1)",
        "timezoneuseoffset": "Alia (Enigu diferencon)",
+       "timezone-useoffset-placeholder": "Ekzemplaj valoroj: \"-07:00\" aŭ \"01:00\"",
        "servertime": "Servila tempo:",
        "guesstimezone": "Plenigita el la foliumilo",
        "timezoneregion-africa": "Afriko",
        "grant-editmycssjs": "Redakti viajn personajn CSS-kodon / JSON / Ĝavoskripton",
        "grant-editmyoptions": "Redakti viajn personajn agordojn",
        "grant-editmywatchlist": "Redakti vian atentaron",
+       "grant-editsiteconfig": "Redakti CSS- aŭ JavaScript-dosierojn de kaj retejo kaj uzantoj",
        "grant-editpage": "Redakti ekzistantajn paĝojn",
        "grant-editprotected": "Redakti protektitajn paĝojn",
        "grant-highvolume": "Ampleksega redaktado",
        "rcfilters-quickfilters-placeholder-title": "Ankoraŭ neniuj filtriloj estas konservitaj",
        "rcfilters-savedqueries-defaultlabel": "Konservitaj filtriloj",
        "rcfilters-savedqueries-rename": "Alinomi",
+       "rcfilters-savedqueries-setdefault": "Farigi implicito",
+       "rcfilters-savedqueries-unsetdefault": "Forigi implicitan valoron",
        "rcfilters-savedqueries-remove": "Forigi",
        "rcfilters-savedqueries-new-name-label": "Nomo",
        "rcfilters-savedqueries-new-name-placeholder": "Priskribas la celon de la filtrilo",
        "rcfilters-savedqueries-add-new-title": "Konservi la nunajn filtrilajn agordojn",
        "rcfilters-restore-default-filters": "Restarigi defaŭltajn filtrilojn",
        "rcfilters-clear-all-filters": "Nuligi ĉiujn filtrilojn",
-       "rcfilters-show-new-changes": "Vidi la plej novajn ŝanĝojn",
+       "rcfilters-show-new-changes": "Vidi la novajn ŝanĝojn ekde $1",
        "rcfilters-search-placeholder": "Filtri lastajn ŝanĝojn (vi povas elekti aŭ ekskribi)",
        "rcfilters-invalid-filter": "Nevalida filtrilo",
        "rcfilters-empty-filter": "Ekzistas neniuj aktivaj filtriloj. Ĉiuj kontribuaĵoj estas montritaj.",
        "rcfilters-filter-bots-description": "Redaktoj farita de aŭtomatigitaj iloj.",
        "rcfilters-filter-humans-label": "Homa (ne robota)",
        "rcfilters-filter-humans-description": "Redaktoj farita de homaj redaktantoj.",
+       "rcfilters-filtergroup-reviewstatus": "Reviziiteco",
        "rcfilters-filter-reviewstatus-unpatrolled-label": "Ne patrolita",
        "rcfilters-filter-reviewstatus-manual-description": "Redaktoj mane markita kiel patrolita.",
        "rcfilters-filter-reviewstatus-manual-label": "Mane patrolita",
        "rcfilters-filter-previousrevision-label": "Ne la lasta revizio",
        "rcfilters-filter-previousrevision-description": "Ĉiuj ŝanĝoj kiu ne estas la \"lasta revizio\".",
        "rcfilters-filter-excluded": "Ekskludita",
+       "rcfilters-tag-prefix-namespace-inverted": "<strong>:ne</strong> $1",
        "rcfilters-exclude-button-off": "Ekskludi la elektitajn",
        "rcfilters-exclude-button-on": "Ekskludante la elektitajn",
        "rcfilters-view-tags": "Redaktoj kun etikedoj",
        "uploadstash-bad-path-invalid": "Vojo ne estas valida.",
        "uploadstash-bad-path-unknown-type": "Nekonata tipo \"$1\".",
        "uploadstash-bad-path-unrecognized-thumb-name": "Nerekonita miniatura nomo.",
+       "uploadstash-bad-path-bad-format": "Ŝlosilo \"$1\" ne estas valide aranĝita",
        "uploadstash-no-extension": "Dosiersufikso estas nula.",
        "uploadstash-zero-length": "Longo de dosiero estas nul.",
        "invalid-chunk-offset": "Malvalida deŝovo de dosierpeco",
        "apisandbox-loading-results": "Ricevas APIajn rezultojn…",
        "apisandbox-results-error": "Eraro okazis dum ŝutis la APIan petan respondon: $1.",
        "apisandbox-request-url-label": "Mendi URL-on.",
+       "apisandbox-request-json-label": "Peti JSON-objekton:",
        "apisandbox-request-time": "Tempo de peto:{{PLURAL:$1|$1 ms}}",
        "apisandbox-results-fixtoken": "Korekti ĵetonon kaj resendi",
        "apisandbox-results-fixtoken-fail": "Malsukcese venigis ĵetonon je \"$1\".",
        "speciallogtitlelabel": "Celo (titolo aŭ  {{ns:user}}:salutnomo por uzanto):",
        "log": "Protokoloj",
        "logeventslist-submit": "Montri",
+       "logeventslist-more-filters": "Montri pliajn protokolojn:",
        "logeventslist-patrol-log": "Patrolprotokolo",
        "logeventslist-tag-log": "Protokolo de etikedoj",
        "all-logs-page": "Ĉiuj publikaj protokoloj",
        "mycontris": "Kontribuoj",
        "anoncontribs": "Kontribuoj",
        "contribsub2": "De {{GENDER:$3|$1}} ($2)",
+       "contributions-subtitle": "Por {{GENDER:$3|$1}}",
        "contributions-userdoesnotexist": "Uzanto-konto \"$1\" ne estas registrita.",
        "nocontribs": "Trovis neniajn redaktojn laŭ tiu kriterio.",
        "uctop": "nuna",
        "thumbnail_dest_directory": "Ne povas krei destinan dosierujon",
        "thumbnail_image-type": "Tia bildo ne subtenata",
        "thumbnail_gd-library": "Nekompleta GD-biblioteka konfiguro: mankas funkcio $1",
+       "thumbnail_image-size-zero": "Grando de bilda dosiero estas ŝajne nul.",
        "thumbnail_image-missing": "Dosiero verŝajne estas foriga: $1",
        "thumbnail_image-failure-limit": "Lastatempe estis tro multaj malsukcesaj provoj ($1 aŭ pli) por bildigi tiun ĉi miniaturon. Bonvolu reprovi poste.",
        "import": "Enporti paĝojn",
        "pageinfo-category-subcats": "Nombro de subkategorioj",
        "pageinfo-category-files": "Nombro de dosieroj",
        "pageinfo-user-id": "Identigilo de uzanto",
+       "pageinfo-file-hash": "Haketa valoro",
+       "pageinfo-view-protect-log": "Vidi la protekdadan protkolon por ĉi tiu paĝo.",
        "markaspatrolleddiff": "Marki kiel patrolitan",
        "markaspatrolledtext": "Marki ĉi tiun paĝon patrolita",
        "markaspatrolledtext-file": "Marki ĉi tiu versio de dosiero kiel patrolita",
        "newimages-legend": "Dosiernomo",
        "newimages-label": "Dosiernomo (aŭ parto de ĝi):",
        "newimages-user": "IP-adreso aŭ uzantnomo",
+       "newimages-newbies": "Montri nur kotribuojn de novaj kontoj",
        "newimages-showbots": "Montri alŝutojn per robotoj",
        "newimages-hidepatrolled": "Malvidigi la patrolitajn alŝutitojn",
        "noimages": "Nenio videbla.",
        "logentry-delete-delete": "$1 forigis paĝon $3",
        "logentry-delete-delete_redir": "$1 {{GENDER:$2|forigis}} alidirektitan $3 per anstataŭigado",
        "logentry-delete-restore": "$1 {{GENDER:$2|restarigis}} paĝon $3 ($4)",
+       "logentry-delete-restore-nocount": "$1 {{GENDER:$2|restarigis}} paĝon $3",
+       "restore-count-revisions": "{{PLURAL:$1|1 revizio|$1 revizioj}}",
+       "restore-count-files": "{{PLURAL:$1|1 dosiero|$1 dosieroj}}",
        "logentry-delete-event": "$1 ŝanĝis videblecon de {{PLURAL:$5|protokola evento|$5 protokolaj eventoj}} je $3: $4",
        "logentry-delete-revision": "$1 {{GENDER:$2|ŝanĝis}} videblecon de {{PLURAL:$5|revizio|$5 reviziojn}} je paĝo $3: $4",
        "logentry-delete-event-legacy": "$1 {{GENDER:$2|ŝanĝis}} videblecon de protokolaj eventoj en $3",
        "logentry-block-block": "$1 {{GENDER:$2|forbaris}} la {{GENDER:$4|uzanton $3}} por daŭro de $5 $6",
        "logentry-block-unblock": "$1 {{GENDER:$2|malforbaris}} la {{GENDER:$4|uzanton $3}}",
        "logentry-block-reblock": "$1 {{GENDER:$2|ŝanĝis}} agordojn de forbaro por la {{GENDER:$4|uzanto $3}} por daŭro de $5 $6",
+       "logentry-partialblock-block-page": "la {{PLURAL:$1|paĝo|paĝoj}} $2",
+       "logentry-partialblock-block-ns": "la {{PLURAL:$1|nomspaco|nomspacoj}} $2",
        "logentry-suppress-block": "$1 {{GENDER:$2|forbaris}} la {{GENDER:$4|uzanton $3}} por daŭro de $5 $6",
        "logentry-suppress-reblock": "$1 {{GENDER:$2|ŝanĝis}} agordojn de forbaro por la {{GENDER:$4|uzanto $3}} por daŭro de $5 $6",
        "logentry-import-upload": "$1 {{GENDER:$2|importis}} $3 per dosiera alŝuto",
        "edit-error-long": "Eraroj:\n\n$1",
        "revid": "revizio $1",
        "pageid": "Identigilo de paĝo $1",
+       "rawhtml-notallowed": "etikedo &lt;html&gt; ne povas esti uzata ekster ordinaraj paĝoj.",
        "gotointerwiki": "Elirante retejon {{SITENAME}}",
+       "gotointerwiki-invalid": "La specifita titolo ne estas valida.",
        "pagedata-title": "Paĝaj datumoj",
        "pagedata-bad-title": "Nevalida titolo: \"$1\".",
        "passwordpolicies": "Reguloj pri pasvortoj",
        "passwordpolicies-group": "Grupo",
        "passwordpolicies-policies": "Politiko",
        "passwordpolicies-policy-minimalpasswordlength": "Pasvortoj devas esti longaj almenaŭ  $1 {{PLURAL:$1|1 signon|$1 signojn}}.",
-       "passwordpolicies-policy-passwordcannotmatchusername": "La pasvorto ne povas esti la sama kiel la uzantnomo"
+       "passwordpolicies-policy-passwordcannotmatchusername": "La pasvorto ne povas esti la sama kiel la uzantnomo",
+       "passwordpolicies-policyflag-forcechange": "devas ŝanĝi dum ensaluto",
+       "passwordpolicies-policyflag-suggestchangeonlogin": "sugesti ŝanĝadon dum ensaluto",
+       "userlogout-continue": "Se vi vola elsaluti, bonvolu  [$1 iri al la elsaluta paĝo].",
+       "userlogout-sessionerror": "Elsalutado malsukcesis pro sesia eraro. Bonvolu [$1 reprovi]."
 }
index b5924e2..c6ca43e 100644 (file)
        "pageinfo-file-hash": "Hash balioa",
        "pageinfo-view-protect-log": "Erregistro babesak ikusi orrialde honetarako",
        "markaspatrolleddiff": "Patruilatutzat markatu",
-       "markaspatrolledtext": "Artikulu hau patruilatutzat markatu",
+       "markaspatrolledtext": "Markatu orri hau patruilatutzat",
        "markaspatrolledtext-file": "Fitxategi honen bertsioa patruilatutzat markatu",
        "markedaspatrolled": "Patruilatutzat markatu da",
        "markedaspatrolledtext": "[[:$1]]-(r)en bertsio hautatua patruilatutzat markatu da.",
index 411ed3e..941d15f 100644 (file)
        "exif-photometricinterpretation-3": "Bảng màu",
        "exif-photometricinterpretation-4": "Mặt nạ trong suốt",
        "exif-photometricinterpretation-5": "Riêng rẽ (có lẽ CMYK)",
+       "exif-photometricinterpretation-8": "CIE L*a*b*",
        "exif-photometricinterpretation-9": "CIE L*a*b* (mã hóa Hiệp hội Màu sắc Quốc tế)",
        "exif-photometricinterpretation-10": "CIE L*a*b* (mã hóa Liên minh Viễn thông Quốc tế)",
        "exif-photometricinterpretation-32803": "Dãy bộ lọc màu sắc",
index 9c48490..eda37f9 100644 (file)
        "toc": "Sommaire",
        "showtoc": "afficher",
        "hidetoc": "masquer",
-       "collapsible-collapse": "Réduire",
-       "collapsible-expand": "Développer",
+       "collapsible-collapse": "masquer",
+       "collapsible-expand": "afficher",
        "confirmable-confirm": "Êtes-vous sûr{{GENDER:$1||e}} ?",
        "confirmable-yes": "Oui",
        "confirmable-no": "Non",
index 736df63..b67abb2 100644 (file)
@@ -68,7 +68,7 @@
        "tog-showrollbackconfirmation": "Befêstigingsdialooch sjen litte by it klikken op 'weromdraaie'",
        "underline-always": "Altyd",
        "underline-never": "Nea",
-       "underline-default": "Webblêder-standert",
+       "underline-default": "Foarmjouwing- as webblêderstandert",
        "editfont-style": "Lettertypestyl bewurkingsfjild",
        "editfont-monospace": "Net-proporsjoneel lettertype",
        "editfont-sansserif": "Skreefleas lettertype",
        "mypreferences": "Foarkarren",
        "prefs-edits": "Tal bewurkings:",
        "prefsnologintext2": "Jo moatte jo oanmelde om jo ynstellings wizigje te kinnen.",
-       "prefs-skin": "Side-oansjen",
+       "prefs-skin": "Foarmjouwing",
        "skin-preview": "Proefbyld",
        "datedefault": "Gjin foarkar",
        "prefs-user-pages": "Meidoggersiden",
index c5718b9..4e8d0e8 100644 (file)
        "blocklink": "blokiraj",
        "unblocklink": "deblokiraj",
        "change-blocklink": "promijeni blokiranje",
+       "empty-username": "(suradničko ime nije dostupno)",
        "contribslink": "doprinosi",
        "emaillink": "pošalji e-poruku",
        "autoblocker": "Automatski ste blokirani jer je Vašu IP adresu nedavno koristio \"[[User:$1|$1]]\".\nRazlog koji je dan za blokiranje $1 bio je \"$2\".",
        "tooltip-summary": "Unesite kratki sažetak",
        "common.css": "/** Uređivanje ove CSS datoteke će se odraziti na sve skinove */",
        "common.js": "/* JavaScript kod na ovoj stranici će biti izvršen kod svakog suradnika pri svakom učitavanju svake stranice wikija. */",
-       "anonymous": "Neprijavljeni {{PLURAL:$1|suradnik|suradnici}} projekta {{SITENAME}}",
+       "anonymous": "{{PLURAL:$1|anonimnoga suradnika/suradnice|$1 anonimna suradnika|$1 anonimnih suradnika}} projekta {{SITENAME}}",
        "siteuser": "Suradnik $1 na projektu {{SITENAME}}",
        "anonuser": "{{SITENAME}} anonimni suradnik $1",
        "lastmodifiedatby": "Ova stranica posljednji je put uređena u $2, dana $1 a uređivao/la je $3.",
-       "othercontribs": "Temelji se na doprinosu suradnika $1.",
+       "othercontribs": "Temelji se na radu $1.",
        "others": "drugih",
        "siteusers": "{{SITENAME}} {{PLURAL:$2|{{GENDER:$1|suradnik|suradnica}}|suradnici}} $1",
        "anonusers": "{{SITENAME}} {{PLURAL:$2|anonimni suradnik|anonimni suradnici}} $1",
index 1b95b4e..cce94a9 100644 (file)
        "virus-scanfailed": "scannamento fallite (codice $1)",
        "virus-unknownscanner": "antivirus non cognoscite:",
        "logouttext": "'''Tu ha claudite le session.'''\n\nNota que alcun paginas pote continuar a apparer como si tu esserea ancora authenticate. Pro remediar isto, tu pote vacuar le cache de tu navigator.",
+       "logging-out-notify": "Le session se claude, un momento…",
+       "logout-failed": "Impossibile clauder session ora: $1",
        "cannotlogoutnow-title": "Impossibile clauder session ora",
        "cannotlogoutnow-text": "Non es possibile clauder le session usante $1.",
        "welcomeuser": "Benvenite, $1!",
index 65ff3d0..82a4ccc 100644 (file)
        "virus-scanfailed": "スキャンに失敗しました (コード $1)",
        "virus-unknownscanner": "不明なウイルス対策ソフトウェア:",
        "logouttext": "<strong>ログアウトしました。</strong>\n\nページによっては、ブラウザーのキャッシュをクリアするまで、ログインしているかのように表示され続ける場合があるためご注意ください。",
+       "logging-out-notify": "ログアウト中です。お待ちください。",
+       "logout-failed": "今はログアウトできません: $1",
        "cannotlogoutnow-title": "今はログアウトできません",
        "cannotlogoutnow-text": "$1 使用中には、ログアウトは不可能です。",
        "welcomeuser": "ようこそ、$1さん!",
        "edit-gone-missing": "ページを更新できませんでした。\n既に削除されているようです。",
        "edit-conflict": "編集が競合。",
        "edit-no-change": "文章が変更されていないため、編集は無視されました。",
+       "edit-slots-cannot-add": "次の{{PLURAL:$1|スロット}}は、ここではサポートされません: $2。",
+       "edit-slots-cannot-remove": "次の{{PLURAL:$1|スロット}}は必須のため取り除くことができません: $2。",
+       "edit-slots-missing": "次の{{PLURAL:$1|スロット}}がありません。: $2。",
        "postedit-confirmation-created": "ページを作成しました。",
        "postedit-confirmation-restored": "ページを復元しました。",
        "postedit-confirmation-saved": "編集を保存しました。",
        "action-ipblock-exempt": "IPブロック、自動ブロック、広域ブロックの回避",
        "action-unblockself": "自分に対するブロックの解除",
        "action-reupload-own": "自分がアップロードした既存のファイルへの上書き",
+       "action-markbotedits": "巻き戻しをボットの編集として扱う",
        "action-patrolmarks": "最近の更新での巡回済み印の閲覧",
        "action-override-export-depth": "リンク先ページの5階層まで含めた書き出し",
        "action-suppressredirect": "転送ページの作成を伴わないページの移動",
        "deleting-backlinks-warning": "<strong>警告:</strong> 削除しようとしているページは、[[Special:WhatLinksHere/{{FULLPAGENAME}}|他のページ]]からリンクまたは参照読み込みされています。",
        "deleting-subpages-warning": "<strong>警告:</strong> 削除しようとしているページには、[[Special:PrefixIndex/{{FULLPAGENAME}}/|{{PLURAL:$1|下位ページ|$1 件の下位ページ|51=50 件以上の下位ページ}}]]があります。",
        "rollback": "編集を巻き戻し",
+       "rollback-confirmation-confirm": "ご確認ください:",
        "rollback-confirmation-yes": "巻き戻し",
        "rollback-confirmation-no": "キャンセル",
        "rollbacklink": "巻き戻し",
        "blocklink": "ブロック",
        "unblocklink": "ブロック解除",
        "change-blocklink": "設定を変更",
+       "empty-username": "(使用可能な利用者名がありません)",
        "contribslink": "投稿記録",
        "emaillink": "メールを送信",
        "autoblocker": "この IP アドレスを「[[User:$1|$1]]」が最近使用したため、自動ブロックされています。\n$1 のブロックの理由は「$2」です。",
index 8fdb8ed..3e40e6f 100644 (file)
        "virus-scanfailed": "검사 실패 (코드 $1)",
        "virus-unknownscanner": "알 수 없는 안티 바이러스:",
        "logouttext": "<strong>이제 로그아웃했습니다.</strong>\n\n브라우저 캐시를 지울 때까지 일부 문서에서 아직 로그인이 되어 있는 것처럼 보일 수 있음에 유의하세요.",
+       "logging-out-notify": "로그아웃 중이니 기다려 주십시오.",
+       "logout-failed": "지금 로그아웃할 수 없습니다: $1",
        "cannotlogoutnow-title": "지금 로그아웃할 수 없습니다",
        "cannotlogoutnow-text": "$1 사용 중에는 로그아웃이 불가능합니다.",
        "welcomeuser": "$1님, 환영합니다!",
index e8b26fc..58e076a 100644 (file)
        "rcfilters-view-tags-help-icon-tooltip": "Méi iwwer Ännerunge mat Markéierunge gewuer ginn",
        "rcfilters-liveupdates-button": "Live-Aktualiséierungen",
        "rcfilters-liveupdates-button-title-on": "Live-Aktualiséierungen ausschalten",
-       "rcfilters-liveupdates-button-title-off": "Nei Ännerunge weisen esoubal wéi se gemaach ginn",
+       "rcfilters-liveupdates-button-title-off": "Nei Ännerunge weise soubal wéi se gemaach ginn",
        "rcfilters-watchlist-markseen-button": "All Ännerungen als gesi markéieren",
        "rcfilters-watchlist-edit-watchlist-button": "Ännert Är Lëscht vun iwwerwaachte Säiten",
        "rcfilters-watchlist-showupdated": "Ännerungen op Säiten déi Dir net besicht hutt zanter d'Ännerunge gemaach goufen si <strong>fett</strong> geschriwwen.",
        "ipb-hardblock": "Verhënneren datt ageloggt Benotzer vun dëser IP-Adress aus Ännerunge maache kënnen",
        "ipbcreateaccount": "Benotzerkont opmaachen",
        "ipbemailban": "E-Maile verschécken",
-       "ipbenableautoblock": "Automatesch déi lescht IP-Adress spären déi vun dësem Benotzer benotzt gouf, an all IP-Adresse vun denen dëse Benotzer versicht Ännerunge virzehuelen",
+       "ipbenableautoblock": "Automatesch déi lescht IP-Adress spären déi vun dësem Benotzer benotzt gouf, an all IP-Adresse vun denen dëse Benotzer versicht Ännerungen ze maachen",
        "ipbsubmit": "Dës IP-Adress resp dëse Benotzer spären",
        "ipbother": "Aner Dauer:",
        "ipboptions": "2 Stonnen:2 hours,1 Dag:1 day,3 Deeg:3 days,1 Woch:1 week,2 Wochen:2 weeks,1 Mount:1 month,3 Méint:3 months,6 Méint:6 months,1 Joer:1 year,onbegrenzt:infinite",
index c2a267d..82bc6cb 100644 (file)
        "expand_templates_generate_rawhtml": "Прикажувај сиров HTML",
        "expand_templates_preview": "Преглед",
        "expand_templates_preview_fail_html": "<em>Бидејќи {{SITENAME}} има овозможено сиров HTML и се јави губиток на седнички податоци, прегледот е скриен како мерка на претпазливост против напади со JavaScript.</em>\n\n<strong>Ако ова е е легитимен обид за преглед, тогаш обидете се повторно.</strong>\nАко не работи и тогаш, [[Special:UserLogout|одјавете се]] и повторно најавете се и проверете дали прелистувачот дозволува колачиња од ова мрежно место.",
-       "expand_templates_preview_fail_html_anon": "<em>Ð\91идеÑ\98Ñ\9cи {{SITENAME}} Ð¸Ð¼Ð° Ð¾Ð²Ð¾Ð·Ð¼Ð¾Ð¶ÐµÐ½Ð¾ Ñ\81иÑ\80ов HTML, Ð° Ð²Ð¸Ðµ Ð½Ðµ Ñ\81Ñ\82е Ð½Ð°Ñ\98авени, Ð¿Ñ\80егледоÑ\82 Ðµ Ñ\81кÑ\80иен ÐºÐ°ÐºÐ¾ Ð¼ÐµÑ\80ка Ð½Ð° Ð¿Ñ\80еÑ\82пазливоÑ\81Ñ\82 Ð¿Ñ\80оÑ\82ив Ð½Ð°Ð¿Ð°Ð´Ð¸ Ñ\81о JavaScript.</em>\n\n<strong>Ð\90ко Ð¾Ð²Ð° Ðµ Ðµ Ð»ÐµÐ³Ð¸Ñ\82имен Ð¾Ð±Ð¸Ð´ Ð·Ð° Ð¿Ñ\80еглед, Ñ\82огаÑ\88 Ð¾Ð±Ð¸Ð´ÐµÑ\82е Ñ\81е Ð¿Ð¾Ð²Ñ\82оÑ\80но.</strong>\nÐ\90ко Ð½Ðµ Ñ\80абоÑ\82и Ð¸ Ñ\82огаÑ\88, [[Special:UserLogout|одÑ\98авеÑ\82е Ñ\81е]] Ð¸ Ð¿Ð¾Ð²Ñ\82оÑ\80но Ð½Ð°Ñ\98авеÑ\82е Ñ\81е.",
+       "expand_templates_preview_fail_html_anon": "<em>Ð\91идеÑ\98Ñ\9cи {{SITENAME}} Ð¸Ð¼Ð° Ð¾Ð²Ð¾Ð·Ð¼Ð¾Ð¶ÐµÐ½Ð¾ Ñ\81иÑ\80ов HTML, Ð° Ð²Ð¸Ðµ Ð½Ðµ Ñ\81Ñ\82е Ð½Ð°Ñ\98авени, Ð¿Ñ\80егледоÑ\82 Ðµ Ñ\81кÑ\80иен ÐºÐ°ÐºÐ¾ Ð¼ÐµÑ\80ка Ð½Ð° Ð¿Ñ\80еÑ\82пазливоÑ\81Ñ\82 Ð¿Ñ\80оÑ\82ив Ð½Ð°Ð¿Ð°Ð´Ð¸ Ñ\81о JavaScript.</em>\n\n<strong>Ð\90ко Ð¾Ð²Ð° Ðµ Ð»ÐµÐ³Ð¸Ñ\82имен Ð¾Ð±Ð¸Ð´ Ð·Ð° Ð¿Ñ\80еглед, [[Special:UserLogin|наÑ\98авеÑ\82е Ñ\81е]] Ð¸ Ð¾Ð±Ð¸Ð´ÐµÑ\82е Ñ\81е Ð¿Ð¾Ð²Ñ\82оÑ\80но.</strong>",
        "expand_templates_input_missing": "Треба да внесете некаков викитекст.",
        "pagelanguage": "Менување јазик на страница",
        "pagelang-name": "Страница",
index 01d9425..ae24786 100644 (file)
        "history": "Geschiedenisse",
        "history_short": "Geschiedenisse",
        "updatedmarker": "bie-ewörken sinds mien leste bezeuk",
-       "printableversion": "Ofdrukbåre versy",
+       "printableversion": "Afdrukbåre versy",
        "permalink": "Vaste verwysing",
        "print": "Aofdrokken",
        "view": "Leasen",
        "page_first": "eerste",
        "page_last": "leste",
        "histlegend": "Verklaoring aofkortingen: (noen) = verschil mit de op-esleugen versie, (veurige) = verschil mit de veurige versie, K = kleine wieziging",
-       "history-fieldset-title": "Deur de geschiedenisse blaojen",
+       "history-fieldset-title": "Versys filteren",
        "history-show-deleted": "Allinnig vortedaon",
        "histfirst": "Eerste",
        "histlast": "Leste",
        "recentchanges-summary": "Up disse syde kün jy de lätste wysigingen van disse wiki bekyken.",
        "recentchanges-noresult": "Der waren in disse periode gien wiezigingen die an de kriteria voldoon.",
        "recentchanges-feed-description": "Zeuk naor de alderleste wiezingen op disse wiki in disse voer.",
-       "recentchanges-label-newpage": "Mid disse bewarking is een nye syde anemaked",
+       "recentchanges-label-newpage": "Mid disse bewarking is een nye syde emaked",
        "recentchanges-label-minor": "Dit is een kleine wysiging",
        "recentchanges-label-bot": "Disse bewarking is uutevoord döär een bot",
        "recentchanges-label-unpatrolled": "Disse bewarking is noch neet nå-ekeaken",
-       "recentchanges-label-plusminus": "Disse sydegroutte is mid dit antal bytes ewysigd",
+       "recentchanges-label-plusminus": "Disse sydgroutte is mid dit antal bytes ewysigd",
        "recentchanges-legend-heading": "<strong>Legenda:</strong>",
        "recentchanges-legend-newpage": "{{int:recentchanges-label-newpage}}<br />(see ouk de [[Special:NewPages|lyste mid nye syden]])",
        "recentchanges-submit": "Bekiek",
        "rcfilters-hours-title": "De leste uren",
        "rcfilters-days-show-days": "$1 {{PLURAL:$1|dag|dagen}}",
        "rcfilters-days-show-hours": "$1 {{PLURAL:$1|uur|uren}}",
-       "rcfilters-quickfilters": "Up-eslöägen filters",
+       "rcfilters-quickfilters": "Upeslöägen filters",
        "rcfilters-quickfilters-placeholder-title": "Noch geen filters up-eslöägen",
        "rcfilters-quickfilters-placeholder-description": "Üm juuw filterinstellingen up te slån en et låter te gebruken, klik up et bladwyserikoon underan by \"Aktive filters\".",
        "rcfilters-savedqueries-apply-label": "Instellingen opslaon",
        "rcfilters-filter-watchlist-notwatched-label": "Niet op de volglieste",
        "rcfilters-filter-watchlist-notwatched-description": "Alles behalve wiezigingen an ziejen die op joew volglieste staon.",
        "rcfilters-filtergroup-changetype": "Soort wysiging",
-       "rcfilters-filter-pageedits-label": "Sydebewarkingen",
+       "rcfilters-filter-pageedits-label": "Sydbewarkingen",
        "rcfilters-filter-pageedits-description": "Wysigingen an de wiki-inhold, diskussys, kategorybeskryvingen…",
        "rcfilters-filter-newpages-label": "Nye syden",
        "rcfilters-filter-newpages-description": "Bewarkingen wårmead jy een nye syde anmaken.",
        "rcfilters-filter-categorization-label": "Kategorywysigingen",
        "rcfilters-filter-categorization-description": "Upgave van syden dee to-evoogd of vordedån wörden uut kategoryen.",
        "rcfilters-filter-logactions-label": "Eregistreerde aktys",
-       "rcfilters-filter-logactions-description": "Administrative handelingen, nye kontos, et vortdoon van syden, upstüren van bestanden…",
+       "rcfilters-filter-logactions-description": "Administrative handelingen, nye kontos, vordedåne syden, upladingen…",
        "rcfilters-filtergroup-lastrevision": "Lätste versys",
        "rcfilters-filter-lastrevision-label": "Lätste versy",
        "rcfilters-filter-lastrevision-description": "Allinnig de lätste wysiging an een syde.",
        "rcfilters-view-tags-tooltip": "Filter resultåten döär gebruuk te maken van bewarkingsetiketten",
        "rcfilters-liveupdates-button": "Rechtstreakse aktualisering",
        "rcfilters-liveupdates-button-title-off": "Nye wysigingen voorddalik låten seen",
-       "rcnotefrom": "Dit bin de wiezigingen sinds <strong>$2</strong> (maximum van <strong>$1</strong> wiezigingen).",
+       "rcnotefrom": "Wysigingen sinds <strong>$3, $4</strong> (maximaal <strong>$1</strong> {{PLURAL:$1|wysiging|wysigingen}}).",
        "rclistfrom": "Bekiek wiezigingen vanaof $3 $2",
        "rcshowhideminor": "$1 kleine wiezigingen",
        "rcshowhideminor-show": "Bekiek",
        "recentchanges-page-removed-from-category": "[[:$1]] is vortedaon uut kategorie",
        "recentchanges-page-removed-from-category-bundled": "[[:$1]] vortedaon uut kategorie, [[Special:WhatLinksHere/$1|disse zied zit in aandere ziejen in-esleuten]]",
        "autochange-username": "Automatiese wieziging van MediaWiki",
-       "upload": "Bestand upstüren",
-       "uploadbtn": "Bestand upstüren",
+       "upload": "Holder upladen",
+       "uploadbtn": "Holder upladen",
        "reuploaddesc": "Weerumme naor de opstuurzied",
        "upload-tryagain": "Bestaandsbeschrieving biewarken",
        "uploadnologin": "Neet an-emelded",
        "imagelinks": "Bestaandsgebruuk",
        "linkstoimage": "Dit bestaand wörden gebruukt op de volgende {{PLURAL:$1|zied|$1 ziejen}}:",
        "linkstoimage-more": "Der {{PLURAL:$2|is|bin}} meer as $1 {{PLURAL:$1|verwiezing|verwiezingen}} naor dit bestaand.\nDe volgende lieste gif allinnig de eerste {{PLURAL:$1|verwiezing|$1 verwiezingen}} naor dit bestaand weer.\nDe [[Special:WhatLinksHere/$2|hele lieste]] is oek beschikbaor.",
-       "nolinkstoimage": "Bestaand is niet in gebruuk.",
+       "nolinkstoimage": "Geen enkelde syde gebrüükt disse holder.",
        "morelinkstoimage": "[[Special:WhatLinksHere/$1|Meer verwiezingen]] naor dit bestaand bekieken.",
        "linkstoimage-redirect": "$1 (bestaandsdeurverwiezing) $2",
        "duplicatesoffile": "{{PLURAL:$1|t Volgende bestaand is|De volgende $1 bestaanden bin}} gelieke an dit bestaand ([[Special:FileDuplicateSearch/$2|meer informasie]]):",
        "pageinfo-hidden-categories": "Verbörgen {{PLURAL:$1|kategorie|kategorieën}} ($1)",
        "pageinfo-templates": "{{PLURAL:$1|Gebruukten mal|Gebruukten mallen}} ($1)",
        "pageinfo-transclusions": "{{PLURAL:$1|Zied|Ziejen}} in-evoegd op ($1)",
-       "pageinfo-toolboxlink": "Sydegegeavens",
+       "pageinfo-toolboxlink": "Sydgegeavens",
        "pageinfo-redirectsto": "Verwis deur naor",
        "pageinfo-redirectsto-info": "informasie",
        "pageinfo-contentpage": "Eteld as zied mit inhoud",
index 79a8397..3148cf1 100644 (file)
@@ -10,6 +10,9 @@
                        "Babamamadidiane"
                ]
        },
+       "tog-hidecategorization": "ߞߐߜߍ ߟߎ߬ ߦߌߟߡߊߦߊߟߌ ߢߡߊߘߏ߲߰",
+       "tog-numberheadings": "ߕߍ߰ߟߌ ߡߐ߬ߟߐ߲ ߠߎ߬ ߝߙߍߕߍ߫ ߞߍ߲ߖߘߍߡߊߓߟߏߡߊ߬",
+       "tog-editondblclick": "ߞߏߜߍ ߟߎ߬ ߡߊߦߟߍ߬ߡߊ߲߫ ߛߐ߲߬ߞߌ߲߬ߠߌ߲߬ߞߏ ߝߌ߬ߟߊ߬ ߟߊ߫",
        "underline-always": "ߕߎ߬ߡߊ߬ ߓߍ߯",
        "underline-never": "ߡߎ߰ߡߍ߫",
        "sunday": "ߞߊ߯ߙߌߟߏ߲",
        "jan": "ߓߌ߲ߠߊߥߎߟߋ߲",
        "feb": "ߞߏ߲ߞߏߜߍ",
        "mar": "ߕߙߊߓߊ",
-       "apr": "ߞߏ߲ߞߏߘߓߌ",
+       "apr": "ß\9eß\8fß²ß\9eß\8fß\98ß\8c߬ß\93ß\8c",
        "may": "ߘߓߊ߬ߕߊ",
        "jun": "ߥߊ߬ߛߌ߬ߥߙߊ",
        "jul": "ߞߊ߬ߙߌ߬ߝߐ",
        "aug": "ߘߓߊ߬ߓߌߟߊ",
        "sep": "ߕߎߟߊߝߌ߲",
-       "oct": "ß\9eß\8fß²ß\93ß\8cß\95ß\8cß±",
+       "oct": "ß\9eß\8fß²ß\93ß\8cß\95ß\8cß®",
        "nov": "ߣߍߣߍߓߊ",
        "dec": "ߞߏߟߌ߲ߞߏߟߌ߲",
        "january-date": "ߓߌ߲ߠߊߥߎߟߋ߲$1",
@@ -79,7 +82,8 @@
        "subcategories": "ߝߊ߬ߓߏ߲߬ ߘߋ߬ߣߍ߲ ߠߎ߬",
        "category-media-header": "ߟߊߛߋߢߊ ߦߌߟߡߊ ߣߌ߲߬ ߘߐ߫ \"$1\"",
        "category-empty": "<em>ߞߐߜߍ߫ ߥߟߊ߫ ߟߊߛߋߢߊ߫ ߝߏߌ߫ ߕߍ߫ ߦߌߟߡߊ ߣߌ߲߬ ߞߣߐ߫ ߕߋ߲߬ߕߋ߲߬.</em>",
-       "hidden-categories": "{{PLURAL:$1|ߦߌߟߡߊ߫ ߘߏ߲߰ߣߍ߲|ߦߌߟߡߊ߫ ߘߏ߲߰ߣߍ߲ ߠߎ߬}}",
+       "hidden-categories": "{{PLURAL:$1|ߦߌߟߡߊ߫ ߢߡߘߏ߲߰ߣߍ߲|ߦߌߟߡߊ߫ ߢߡߊߘߏ߲߰ߣߍ߲ ߠߎ߬}}",
+       "hidden-category-category": "ߦߌߟߡߊ߫ ߢߡߊߘߏ߲߰ߣߍ߲ ߠߎ߬",
        "category-subcat-count": "{{PLURAL:$2|ߦߟߊߡߊߙߋ߲ ߣߌ߲߬ ߠߎ߫ ߜߊ߲߰ߛߊ߲ ߠߋ߫ ߦߋ߫ ߦߌߟߡߊ ߣߌ߲߬ ߘߐ߫.|ߦߌߟߡߊ ߣߊ߬ߕߐ ߟߎ߬ ߘߐ߫߸ {{PLURAL:$1|ߦߌߟߡߊߙߋ߲|$1 ߦߌߟߡߊߙߋ߲ ߠߎ߬}} ߟߋ߬ ߦߴߊ߬ ߘߐ߫߸ ߞߙߎߞߙߍ ߟߎ߬ ߞߐߞߊ߲߬ $2}}",
        "category-article-count": "{{PLURAL:$2|ߞߐߜߍ ߣߌ߲߬ ߘߐߙߐ߲߫ ߠߋ߬ ߦߋ߫ ߦߌߟߡߊ ߣߌ߲߬ ߘߐ߫.|ߖߡߊ߬ߦߊ߫ ߕߐ߮ ߣߊ߬ߕߊ {{PLURAL:$1|ߞߐߜߍ ߦߋ߫|$1 ߞߐߜߍ ߦߋ߫}} ߟߋ߬ ߦߋ߫ ߦߌߟߡߊ߫ ߘߌ߫߸ ߞߙߎߞߙߍ $2 ߞߐߞߊ߲߬}}",
        "category-file-count": "{{PLURAL:$2||ߞߐߕߐ߮ ߣߌ߲߬ ߜߊ߲߰ߛߊ߲ ߠߋ߫ ߦߋ߫ ߦߌߟߡߊ ߣߌ߲߬ ߘߐ߫.ߡߍ߲ ߠߎ߬ ߦߋ߫ ߣߌ߲߬ |{{PLURAL:$1||ߞߐߕߐ߮ ߦߋ߫|$1 ߞߐߕߐ߮ ߟߎ߬ ߦߋ߫}} ߦߌߟߡߊ ߣߌ߲߬ ߘߐ߫߸ ߞߙߎߞߙߍ ߣߌ߲߬ ߕߴߊ߬ ߘߐ߫2$.}}",
        "navigation": "ߛߏ߲߯ߓߊߟߌ",
        "and": "&#32;ߊ߬ ߣߌ߫",
        "actions": "ߞߍߟߌ ߟߎ߬",
-       "namespaces": "ß\95ß\90ß® ߞߣߍ",
-       "variants": "ß\9eß\8aß²ß\93ß\8fß\9fß\8fß² ß ߎ߬",
-       "navigation-heading": "ß\9bß\8f߲߯ß\93ß\8aß\9fß\8cß« ß\93ß\8fß\9fß\8fß²ß\98ߊ",
+       "namespaces": "ß\95ß\90߯ ß\9bß\93ß\8d ߞߣߍ",
+       "variants": "ߦß\9fß\8d߬ߡß\8a߲߬ߦß\9fß\8d߬ߡß\8a߲߬ߠß\8a ß\9fߎ߬",
+       "navigation-heading": "ß\9bß\8f߲߯ß\93ß\8aß\9fß\8cß« ß\9fß\90߬ߥß\9fߊ",
        "errorpagetitle": "ߝߎ߬ߕߎ߲߬ߕߌ",
        "returnto": "ߌ ߞߐߛߊ߬ߦߌ߲߬ ߦߊ߲߬ ߡߊ߬ $1.",
        "tagline": "ߞߊ߬ ߝߘߊ߫ {{SITENAMEP}}",
-       "help": "ߘߍ߬ߡߍ߲߬ߠߌ",
+       "help": "ß¡ß\8a߬ß\98ß\8d߬ߡß\8d߲߬ߠß\8c",
        "help-mediawiki": "ߘߍ߬ߡߍ߲߬ߠߌ߲ ߞߊ߬ ߓߍ߲߬ ߥߞߌ-ߟߊߛߋߢߊߥߙߍ ߡߊ߬",
-       "search": "ߢߌߣߌ߲ߠߌ",
-       "searchbutton": "ߢߌߣߌ߲ߠߌ",
+       "search": "ߢߌߣߌ߲ߠߌ߲",
+       "searchbutton": "ߢߌߣߌ߲ߠߌ߲",
        "go": "ߊ߬ ߢߌߣߌ߲߫",
        "searcharticle": "ߥߊ߫/ߕߊ߯",
        "history": "ߘߐߜߍ ߘߐ߬ߝߐ",
-       "history_short": "ß\98ß\90߬ß\9dß\90",
+       "history_short": "ß\95ß\8e߬ߡß\8a߬ß\98ß\8a",
        "history_small": "ߕߊ߬ߡߌ߲߬ߣߍ߲",
-       "printableversion": "ß\9bß\8cß°ß\98ß\8a߫ ߜߌ߬ߙߌ߲߬ߘߌ߬ߕߊ",
+       "printableversion": "ß\93ß\90ß\9eß\8fߣß\8aß²߫ ߜߌ߬ߙߌ߲߬ߘߌ߬ߕߊ",
        "permalink": "ߛߘߌ߬ߜߋ߲߬ ߓߟߏߕߍ߰ߓߊߟߌ",
        "print": "ߜߌ߬ߙߌ߲߬ߘߌ߬ߟߌ",
-       "view": "ß\8a߬ ß\98ß\90ß\9cß\8dß«",
+       "view": "ß\8a߬ ß\98ß\90ß\9eß\8a߬ß\99ß\8a߲߬",
        "view-foreign": "ߊ߬ ߦߋ߫ ߦߊ߲߬ $1",
-       "edit": "ß\8a߬ ß¡ß\8aߦß\9fß\8d߬ߡß\8a߲߬",
+       "edit": "ß\8a߬ ß¢ß\9fß\8aß\9eß\8eß\98ߦß\8aß«",
        "create": "ߟߊ߬ߘߊ߲߬ߠߌ",
        "create-local": "ߕߌ߲߬ߞߎߘߎ߲ ߞߊ߲߬ߛߓߍ߬ߟߌ ߟߊߘߏ߲߬",
        "delete": "ߊ߬ ߖߐ߬ߛߌ߬",
        "protect_change": "ߊ߬ ߡߊߦߟߍ߬ߡߊ߲߫",
        "unprotect": "ߟߊ߬ߞߊ߲߬ߘߊ߬ߟߌ ߡߊߝߊ߬ߟߋ߲߬ߠߌ",
        "newpage": "ߘߐߜߍ߫ ߞߎߘߊ",
-       "talkpagelinktext": "ß\93ß\8a߬ß\98ß\8f",
+       "talkpagelinktext": "ß\9eß\8eß¡ß\8aß«",
        "specialpage": "ߞߐߜߍ߫ ߞߙߍߞߙߍߣߍ߲",
-       "personaltools": "ߘߎ߲߬ߘߎ߬ߡߊ߬ ߖߐ߯ߙߊ ߠߎ߬",
+       "personaltools": "ߘߎ߲߬ߘߎ߬ߡߊ߬ ߖߐ߯ߙߊ߲ ߠߎ߬",
        "talk": "ߓߊ߬ߘߏ߬ߓߊ߬ߘߌߦߊ",
        "views": "ߦߌ߬ߘߊ߬ߟߌ",
        "toolbox": "ߖߐ߯ߙߊ߲ ߠߎ߬",
        "redirectedfrom": "(ߌ ߟߊߞߎ߲߬ߛߌ߲߬ߣߍ߲߫ ߞߊ߬ ߓߐ߫ $1)",
        "redirectpagesub": "ߞߐߜߍ߫ ߟߊߞߎ߲߬ߛߌ߲߬ߣߍ߲",
        "redirectto": "ߌ ߓߘߊ߫ ߟߊߞߎ߲߬ߛߌ߲߫ ߦߊ߲߬ ߠߊ߫:",
-       "lastmodifiedat": "ߞߐߜߍ ߣߌ߲߬ ߡߊߦߟߍ߬ߡߊ߲߬ ߟߊߓߊ߲ ߞߍ߫ ߘߊ߫ $1߸ $2",
+       "lastmodifiedat": "ߞߐߜߍ ߣߌ߲߬ ߡߊߦߟߍ߬ߡߊ߲߬ ߟߊߓߊ߲ ߞߍ߫ ߘߊ߫ $1߸ ߟߋ߬ ߟߊ߫ $2",
        "protectedpage": "ߞߐߜߍ߫ ߡߊߞߊ߲ߞߊ߲ߣߍ߲",
-       "jumpto": "ß\8c ß\9cß\8a߲߫ ß\9eß\8a߬ ß\95ß\8a߯:",
+       "jumpto": "ß\95ß\8a߯ ß\9eß\8aß\95ß\99ß\8d߬:",
        "jumptonavigation": "ߛߏ߲߯ߓߊߟߌ",
-       "jumptosearch": "ß\8a߬ ß\95ß\8cß\99ߌ߲߫",
+       "jumptosearch": "ß\8a߬ ß¢ß\8cߣߌ߲߫",
        "pool-timeout": "ߘߊߕߎ߲߯ߠߌ߲ ߡߊ߬ߞߐ߬ߣߐ߲߬ߠߌ߲߬ ߕߎߡߊ ߓߘߊ߫ ߕߊ߬ߡߌ߲߬",
        "pool-errorunknown": "ߝߌ߬ߟߌ߬ ߛߎ߲߫ ߟߐ߲ߓߊߟߌ",
        "poolcounter-usage-error": "ߟߊߓߊ߯ߙߊߟߌ߫ ߝߟߌ $1",
-       "aboutsite": "ߞߊ߬ ߓߍ߲߬ {{SITENAME}}",
-       "aboutpage": "Project:ߞߊ߬ ߓߍ߲߬",
+       "aboutsite": "ߞߊ߬ ߓߍ߲߬ {{SITENAME}} ߞߏ ߡߊ߬",
+       "aboutpage": "Project:ߟߊ߫ ߞߏ ߡߊ߬",
+       "copyright": "ߞߣߐߘߐ ߦߋ߫ ߓߟߏߞߘߐ߫ ߟߊ߬ߘߌ߬ߢߍ߬ߟߌ ߣߌ߲߬ ߕߐ߮ ߞߘߐ߫ $1 ߣߌ߫ ߏ߬ ߡߊߝߘߏ߬ ߡߊ߫ ߟߊߞߏߟߐ߲߫.",
        "copyrightpage": "{{ns:project}}:ߛߓߍߦߟߊ ߤߊߞߍ",
-       "currentevents": "ß\9eß\8dß\9eß\8eß\98ß\8a ß¡ß\8dß² ß ß\8eß« ß\9bß\8b߲߬ߠß\8aß«",
-       "currentevents-url": "Project:ß\9eß\8dß\9eß\8eß\98ß\8a ß¡ß\8dß² ß ß\8eß« ß\9bß\8b߲߬ߠß\8aß«",
-       "disclaimers": "ß\96ß\8a߲߬ß\98ß\90߬ß\93ß\8c߬ß\9fß\8a߬ß\9fß\8c ß\9fß\8e߬",
-       "disclaimerpage": "Project:ß\96ß\8a߲߬ß\98ß\90߬ß\93ß\8c߬ß\9fß\8a߬ß\9fß\8c ß¡ß\8eß°ß¡ß\8d",
+       "currentevents": "ß\9bß\8b߲߬ߠß\8a߬ ß\9eß\8dß\9eß\8eß\98ß\8a ß\9fß\8e߬",
+       "currentevents-url": "Project:ß\9bß\8b߲߬ߠß\8a߬ ß\9eß\8dß\9eß\8eß\98ß\8a ß\9fß\8e߬",
+       "disclaimers": "ß\96ß\8a߬ß\9bß\99ß\8b߬ߡß\8a߬ß\9fß\8a",
+       "disclaimerpage": "Project:ß\96ß\8a߬ß\9bß\99ß\8b߬ߡß\8a߬ß\9fß\8aß« ß\9dß\98ß\8f߬ß\93ß\8a߬ߡß\8a",
        "edithelp": "ߡߊ߬ߦߟߍ߬ߢߊ߲߬ߠߌ߲ ߘߍ߬ߡߍ߲߬ߠߌ߲",
        "helppage-top-gethelp": "ߘߍ߬ߡߍ߲߬ߠߌ",
        "mainpage": "ߓߏ߬ߟߏ߲߬ߘߊ",
        "mainpage-description": "ߓߏ߬ߟߏ߲߬ߘߊ",
-       "policy-url": "Projet:ß\93ß\98ß\8d߬ß\93ß\98ß\8d߬ß\9fß\8c",
-       "portal": "ß\9fß\8a߬ß\9bߣß\8d߬ß\9fß\8c ß\93ß\8f߬ß\9fß\8f߲߬ß\98ߊ",
-       "portal-url": "Project:ß\9fß\8a߬ß\9bߣß\8d߬ß\9fß\8c ß\93ß\8f߬ß\9fߏ߲߬ߘߊ",
-       "privacy": "ß\98ß\8e߲߬ß\98ß\8e߬ߡß\8a߬ ß¤ß\8aß\9eß\8d",
-       "privacypage": "Project:ß\9eß\8a߬ ß\93ß\8d߲߬ ß\98ß\8e߲߬ß\98ß\8e߬ߡß\8a߬ ß¤ß\8aß\9eß\8d ß¡ß\8a߬",
+       "policy-url": "Projet:ß\9eß\8e߬ß\99ß\8e߲߬ß\98ß\8e",
+       "portal": "ß\98ß\8d߬ß\98ß\8a ß\98ß\8f߲߬ß\98ß\8a߬ß\93ߊ",
+       "portal-url": "Project:ß\98ß\8d߬ß\98ß\8a ß\9fß\8e߬ ß\98ߏ߲߬ߘߊ",
+       "privacy": "ß\98ß\8e߲߬ß\98ß\8e߬ߡß\8a߬ ß\93ß\98ß\8dß\93ß\98ß\8dß\9fß\8c",
+       "privacypage": "Project:ß\98ß\8e߲߬ß\98ß\8e߬ߡß\8a߬ ß\93ß\98ß\8d߬ß\93ß\98ß\8d߬ß\9fß\8c",
        "ok": "ߏ߬ߞߍ߫",
-       "retrievedfrom": "ß\8a߬ ß\9fß\8aß\9bß\90߬ß\98ß\90߲߬ ߦߊ߲߬ \"$1\"",
+       "retrievedfrom": "ß\8a߬ ß\9fß\8aß\9bß\90߬ß\98ß\90߲߫ ߦߊ߲߬ \"$1\"",
        "youhavenewmessages": "{{PLURAL:$3|ߌ ߓߘߊ߫ ߗߋߛߓߍ߫ ߞߎߘߊ ߛߐ߬ߘߐ߲߬$1  $2 }}",
        "youhavenewmessagesfromusers": "{{PLURAL:$4|ߟߋ߬ ߦߴߌ ߓߟߏ߫}} $1 ߞߊ߬ ߓߐ߫ {{PLURAL:$3|ߟߊ߬ߓߊ߰ߙߊ߬ߟߊ߬ ߜߘߍ߫|$3ߟߊ߬ߓߊ߰ߙߊ߬ߟߊ ߟߎ߬}} ($2)",
        "newmessageslinkplural": "{{PLURAL:$1|ߗߋߛߓߍ߫ ߞߎߘߊ߫|999=ߗߋߛߓߍ߫ ߞߎߘߊ߫ ߟߎ߫}}",
        "newmessagesdifflinkplural": "{{PLURAL:$1|ߡߝߊ߬ߟߋ߲߬ߠߌ߲|999=ߡߝߊ߬ߟߋ߲߬ߠߌ߲ ߠߎ߬}} ߞߐ߯ߟߕߊ.",
        "youhavenewmessagesmulti": "ߌ ߓߘߊ߫ ߗߋߛߓߍ߫ ߞߎߘߊ ߛߐ߬ߘߐ߲߬ $1 ߞߣߐ߫",
-       "editsection": "ß\8a߬ ß¡ß\8aߦß\9fß\8d߬ߡß\8aß²߫",
+       "editsection": "ß\8a߬ ß¢ß\9fß\8aß\9eß\8eß\98ߦß\8a߫",
        "editold": "ߡߊߦߟߍ߬ߡߊ߲߬",
        "viewsourceold": "ߊ߬ ߛߎ߲ ߘߐߜߍ߫",
        "editlink": "ߊ߬ ߡߊߦߟߍ߬ߡߊ߲߬",
-       "viewsourcelink": "ß\8a߬ ß\9bß\8eß² ß ß\8aß\93ß\8a߯ß\99ß\8a߫",
-       "editsectionhint": "ߦß\8cß\9fß¡ߊ ߡߊߝߊ߬ߟߋ߲߬ߠߌ:$1",
+       "viewsourcelink": "ß\8a߬ ß\93ß\90ß\9bß\8eß² ß¡ß\8aß\9dß\9fß\8d߫",
+       "editsectionhint": "ß\9bß\8cß°ß\98ߊ ߡߊߝߊ߬ߟߋ߲߬ߠߌ:$1",
        "toc": "ߞߣߐߘߐ",
        "showtoc": "ߦߌ߬ߘߊ߬ߟߌ",
        "hidetoc": "ߢߡߊߘߏ߲߯ߠߌ",
        "viewdeleted": "ߦߌ߬ߘߊ߬ߟߌ ߓߊ߬ $1؟",
        "site-atom-feed": "$1 ߝߕߌ ߓߊߟߏ",
        "page-atom-feed": "$1 ߝߕߌ ߓߊߟߏ",
-       "red-link-title": "ß\9eß\90ß\9cß\8dß« ß\95ß\8dß« ߦߋ߲߬ $1",
+       "red-link-title": "ß\9eß\90ß\9cß\8dß« ß\95ß´ߦߋ߲߬ $1",
        "sort-descending": "ߛߙߊߛߌ߰ߟߌ ߖߌ߰ߟߌ߬ ߓߟߏߡߊ߬",
        "sort-ascending": "ߛߙߊߛߌ߰ߟߌ ߦߟߍ߬ ߓߟߏߡߊ߬",
        "nstab-main": "ߞߐߜߍ",
        "nstab-user": "ߞߐߜߍ߫ ߟߊߓߊ߯ߙߕߊ",
        "nstab-media": "ߟߊߛߋߢߊ߫ ߞߐߜߍ",
-       "nstab-special": "ß\98ß\90ß\9cß\8dß« ß\93ß\9fß\8fß¡ß\8aß\9eß\8a߬ߣߍ߲",
+       "nstab-special": "ß\98ß\90ß\9cß\8dß« ß\9eß\99ß\8dß\9eß\99ß\8dߣߍ߲",
        "nstab-project": "ߖߊ߬ߕߋ߬ߘߐ߬ߛߌ߰ ߞߐߜߍ",
        "nstab-image": "ߞߐߕߐ߮",
        "nstab-mediawiki": "ߗߋߛߓߍ",
        "blockedtext": "<strong>ߌ ߟߊ߫ ߟߊ߬ߓߊ߰ߙߊ߬ ߕߐ߮ ߥߟߊ߫ IP ߛߊ߲߬ߓߊ߬ߕߐ߮ ߓߘߊ߫ ߓߊ߬ߟߊ߲߬߸</strong>\n\nߌ ߓߊ߬ߟߊ߲߬ߣߍ߲߬ ߦߋ߫ $1 ߟߋ߬ ߓߟߏ߫.\nߞߎ߲߭ ߡߍ߲ ߦߴߊ߬ ߟ߫ߊ߫ <em>$2</em>.\n\n•ߓߊ߬ߟߊ߲߬ߠߌ߲ ߘߊߡߌ߬ߣߊ: $8\n•ߓߊ߬ߟߊ߲߬ߠߌ߲ ߛߕߊ ߝߊ: $6\n•ߓߊ߬ߟߊ߲߬ߠߌ߲ ߘߊ߬ߟߎ: $7 \n\nߌ ߘߌ߫ ߛߋ߫ ߗߋߛߓߍ ߗߋ߫ ߟߊ߫ $1 ߡߊ߬ ߥߟߊ߫ ߡߐ߰ ߜߘߍ߫ \n[[{{MediaWiki:Grouppage-sysop}}|administrator]] ߞߊ߬ ߘߊߘߐߖߊߥߏ ߞߍ߫ ߓߊ߬ߟߊ߲߬ߠߌ߲ ߞߊ߲߬.\nߌ ߕߍ߫ ߣߊ߬ ߛߋ߫ ߟߊ߫  \"{{int:emailuser}}\" ߟߊߓߊ߯ߙߊ߫ ߟߊ߫߸ ߟߊ߬ߓߊ߰ߙߊ߬ߢߊ߬ ߖߐ߲ߖߐ߲ ߡߍ߲ ߦߋ߫ ߦߋ߲߬߸ ߢߎߡߍߙߋ߲߫ ߞߏ߲ߘߏ߫ ߖߐ߲ߖߐ߲߫ ߓߟߏߡߊߞߊ߬ߣߍ߲ ߘߏ߫ ߦߴߌ ߟߊ߫ [[Special:Preferences|account preferences]] ߘߐ߫߸ ߊ߬ ߣߴߌ ߡߊ߫ ߓߊ߬ߟߊ߲߬ ߊ߬ ߟߊߓߊ߯ߙߊ ߞߏߛߐ߲߬ ߘߋ߫. ߌ ߟߊ߫ IP ߛߊ߲߬ߓߊ߬ߕߐ߮ ߦߋ߫ $3 ߟߋ߬ ߘߌ߫ ߕߊ߲߬߸ ߊ߬ ߣߴߌ ߟߊ߫ ߛߊ߲߬ߓߊ߬ߕߐ߮ ߓߊ߬ߟߊ߲߬ߣߍ߲ ߦߋ߫ #$5 ߟߋ߬ ߘߌ߫.\nߖߊ߰ߣߌ߲߬ ߌ ߦߋ߫ ߛߊ߲ߝߍ߫ ߝߊߙߊ߲ߝߊ߯ߛߌ ߣߌ߲߬ ߓߍ߯ ߟߊߘߏ߲߬ ߌ ߟߊ߫ ߢߌ߬ߣߌ߲߬ߞߊ߬ߟߌ ߘߐ߫.",
        "loginreqlink": "ߌ ߜߊ߲߬ߞߎ߲߬",
        "newarticletext": "ߌ ߓߘߊ߫ ߛߘߌ߬ߜߋ߲ ߘߏ߫ ߟߊߓߊ߬ߕߏ߬ ߞߐߜߍ ߘߏ߫ ߘߐ߫߸ ߡߍ߲ ߕߴߦߋ߲߬ ߡߎߣߎ߲߬.\nߣߵߌ ߦߴߊ߬ ߝߍ߫ ߞߊ߬ ߞߐߜߍ ߘߏ߫ ߟߊߘߊ߲߫߸ ߛߓߍߟߌ ߘߊߡߌ߬ߣߊ߬ ߘߎ߰ߟߊ߬ߘߐ߫ ߞߏ߲ߘߏ ߘߐ߫ (ߞߊ߬ [$1 ߘߍ߬ߡߍ߲߬ߠߌ߲ ߞߐߜߍ] ߦߋ߫߸ ߖߐ߲߬ߛߊ߬ ߌ ߘߌ߫ ߞߌ߬ߓߊ߬ߙߏ߬ ߖߐ߲ߖߐ߲ ߛߐ߬ߘߐ߲߬). ߣߵߌ ߘߏ߲߬ ߞߍ߫ ߘߊ߫ ߦߊ߲߬ ߝߎ߬ߕߎ߲߬ߕߌ߬ ߓߟߏߡߊ߬߸ ߌ ߟߊ߫ ߛߏ߲߯ߓߊߟߊ߲ <strong>back</strong> ߛߐ߲߬ߞߌ߲߫.",
+       "anontalkpagetext": "----\n<em>ߓߊ߬ߘߏ߬ ߞߐߜߍ ߣߌ߲߬ ߦߋ߫ ߟߊߓߊ߯ߙߟߊ߫ ߟߐ߲ߓߊߟߌ ߟߋ߬ ߓߟߏ߫ ߡߍ߲ ߡߊ߫ ߖߊ߬ߕߋ߬ߘߊ߬ ߛߌ߲ߘߌ߫ ߡߎߣߎ߲߬ ߥߟߴߊ߬ ߕߍ߫ ߖߊ߬ߕߋ߬ߘߊ ߏ߬ ߟߊߓߊ߯ߙߊ߫ ߟߊ߫;</em>\nߏ߬ ߞߏߛߐ߲߬ ߊ߲ ߞߊ߫ ߞߊ߲߫ ߞߵߊ߬ ߟߊ߫ ߓߡ (ߓߟߐߟߐ ߡߛߍ߬ߞߍ߬ߡߛߍߞߍ) ߛߊ߲߬ߓߊ߬ߕߐ߮ ߟߊߓߊ߯ߙߴߊ߬ ߡߊߟߐ߲߫ ߞߊߡߊ߬߸ ߟߊߓߊ߯ߙߟߊ߫ ߛߌߦߊߡߊ߲߫ ߓߴߛߋ߫ ߞߊ߬ ߘߍ߬ ߓߡ ߛߊ߲߬ߓߊ߬ߕߐ߮ ߣߌ߲߬ ߢߐ߲߰ ߠߊ߫.\nߣߴߌ ߞߍ߫ ߘߊ߫ ߟߊߓߊ߯ߙߟߊ߫ ߡߊߝߟߌ߬ߣߍ߲߫ ߘߌ߫ ߞߵߊ߬ ߛߏ߬ߓߌ߬ ߞߏ߫ ߌ ߟߊ߫ ߞߊ߲߬ߞߎߡߊ ߟߎ߬ ߕߴߌ ߕߊ߫ ߘߌ߫ ߊ߬ ߘߌ߫ ߟߐ߬ ߌ ߡߊ߬ ߌߞߘߐ߫߸ ߌ ߖߏ߫ ߞߊ߬ [[Special:CreateAccount|ߖߊ߬ߕߋ߬ߘߊ ߘߏ߫ ߘߊߦߟߍ߬]] ߥߟߊ߫ [[Special:UserLogin|ߞߊ߬ ߘߏ߲߬ߕߐ߰ߟߊ߬ߘߏ߲ ߞߍ߫]] ߖߐ߲߬ߛߊ߫ ߟߏ߲ߘߐ߬ ߓߊߛߌ߯ߓߊߟߌߦߊ ߘߌ߫ ߡߟߊ߫ ߟߊߓߊ߯ߙߟߊ߫ ߡߊߟߐ߲ߓߊߟߌ߫ ߜߘߍ ߟߎ߬ ߓߟߏ߫.",
        "noarticletext": "ߛߓߍߟߌ߫ ߛߌ߫ ߕߍ߫ ߞߐߜߍ ߣߌ߲߭ ߞߊ߲߬ ߕߋ߲߫. ߌ ߘߌ߫ ߛߋ߫ ߞߐߜߍ ߣߌ߲߬ \n [[Special:Search/{{PAGENAME}}|search for this page title]] ߕߐ߮ ߢߌߣߌ߲߫ ߠߊ߫ ߞߐߜߍ ߕߐ߭ ߟߎ߬ ߘߐ߫߸  \n<span class=\"plainlinks\">[{{fullurl:{{#Special:Log}}|page={{FULLPAGENAMEE}}}} search the related logs],\nor [{{fullurl:{{FULLPAGENAME}}|action=edit}} create this page]</span>.",
        "noarticletext-nopermission": "ߛߓߍߟߌ߫ ߛߌ߫ ߕߍ߫ ߞߐߜߍ ߣߌ߲߭ ߞߊ߲߬ ߕߋ߲߫.\nߌ ߘߌ߫ ߛߋ߫ [[Special:Search/{{PAGENAME}}|search for this page title]] ߢߌߣߌ߲߫ ߠߊ߫ ߞߐߜߍ ߕߐ߭ ߟߎ߬ ߘߐ߫߸ ߥߟߊ߫ <span class=\"plainlinks\">[{{fullurl:{{#Special:Log}}|page={{FULLPAGENAMEE}}}} search the related logs]</span> ߞߏ߬ߣߌ߲߬ ߘߌ߬ߢߍ߬ ߞߍߣߍ߲߫ ߕߴߌ ߡߊ߬ ߞߐߜߍ߫ ߣߌ߲߬ ߠߊߞߊ߭ ߘߐ߫.",
        "userpage-userdoesnotexist-view": "ߟߊ߬ߓߊ߰ߙߊ߬ ߖߊߕߋߘߊ \"$1\" ߟߊߞߎ߲߬ߘߎ߬ߣߍ߲߫ ߕߍ߫.",
+       "clearyourcache": "<strong>ߖߊ߲߬ߕߏ߬ߒߘߐ:</strong> ߞߎ߲߬ߘߎ߬ߟߌ ߞߐ߫، ߌ ߓߍߣߊ߬ ߢߌߣߌ߲߫ ߌ ߟߊ߫ ߓߟߐߟߐߞߐߜߍ ߞߙߏ ߘߐߞߊ߭ ߡߊ߬ ߞߊ߬ ߡߝߊ߬ߟߋ߲߬ߠߌ߲ ߠߎ߬ ߦߋ߫. * <strong>ߝߦߊߝߐߞߛ / ߛߝߊߙߌ:</strong> ߊ߬ ߡߌ߬ߣߊ߬ <em>Shift</em> ߘߌ߯ߟߌ߫ ߕߎߡߊ <em>Reload</em>، ߥߟߊ߫ ߞߵߊ߬ ߛߐ߲߬ߞߌ߲߫ ߥߟߊ߫ <em>Ctrl-F5</em> ߤߊߡߊ߲߫ <em>Ctrl-R</em> (<em>⌘-R</em> ߡߊߞߌ ߞߊ߲߬) * <strong>ߜ߭ߎߜ߭ߐߟ ߞߊ߲߬:</strong> ߊ߬ ߛߐ߲߬ߞߌ߲߫ <em>Ctrl-Shift-R</em> (<em>⌘-Shift-R</em> ߡߊߞߌ ߞߊ߲߬) * <strong>ߍ߲ߕߍߙߑߣߍߕ ߍߞߛߌߔߟߏߙߊ ߞߊ߲߬:</strong> ߊ߬ ߡߌ߬ߣߊ߬ <em>Ctrl</em> ߊ߬ ߛߐ߲߬ߞߌ߲߬ ߕߎߡߊ <em>Refresh</em>، ߥߟߊ߫ ߞߵߊ߬ ߛߐ߲߬ߞߌ߲߫ <em>Ctrl-F5</em> * <strong>ߏߔߋߙߊ:</strong> ߕߊ߯ ߞߊߕߙߍ߬ <em>Menu → ߟߊ߬ߓߍ߲߬ߢߐ߲߰ߡߦߊ߬ߘߊ</em> (<em>Opera → ߞߐߡߊߛߙߋ</em> ߡߊߞߌ ߟߊ߫) ߞߊ߬ ߕߊ߯ ߏ߬ ߞߐ߫ <em>ߘߎ߲߬ߘߎ߬ߡߊ߬ & ߞߎ߲߬ߠߊ߬ߝߎߟߋ߲ → ߓߟߐߟߞߐߜߍߦߊ ߟߐ߲ߕߊ ߟߎ߫ ߖߏ߬ߛߌ߫ → ߖߌ߬ߦߊ߬ߓߍ ߟߎ߬ ߣߌ߫ ߞߐߕߐ߯ ߢߡߊߘߏ߲߰ߣߍ߲ ߠߎ߬</em>.",
        "previewnote": "<strong>ߌ ߖߊ߲߬ߓߌ߬ߟߊ߬ ߞߏ߫ ߣߌ߲߬ ߦߋ߫ ߢߍߝߟߍߟߌ ߘߐߙߐ߲߫ ߠߋ߬ ߘߌ߫.</strong>\nߌ ߟߊ߫ ߡߝߊ߬ߟߋ߲߬ߠߌ ߟߎ߫ ߡߊ߫ ߟߊߞߎ߲߬ߘߎ߬ ߝߟߐ߫ ߘߋ߬߹",
        "continue-editing": "ߥߊ߫ ߡߊ߬ߦߟߍ߬ߡߊ߲߬ߠߌ߬ ߞߣߍ ߞߊ߲߬",
        "editing": "ߡߊ߬ߦߟߍ߬ߡߊ߲߬ߠߌ߲ ߦߋ߫ ߛߋ߲߬ߠߊ߫ $1",
        "editingsection": "(ߛߌ߰ߘߊ߬) $1 ߡߊߦߟߍ߬ߡߊ߲ ߦߋ߫ ߛߋ߲߬ߠߊ߫",
        "templatesused": "{{PLURAL:$1|ߞߙߊߞߏ|ߞߙߊߞߏ ߟߎ߫}} ߟߎ߫ ߟߊߓߊ߯ߙߊ߫ ߘߊ߫ ߞߐߜߍ ߣߌ߲߬ ߘߐ߫",
        "templatesusedpreview": "{{PLURAL:$1|ߞߙߊߞߏ|ߞߙߊߞߏ ߟߎ߬}} ߟߋ߬ ߟߊߓߊ߯ߙߊ߫ ߣߍ߲߫ ߢߍߦߋߟߌ ߣߌ߲߬ ߘߐ߫",
-       "template-protected": "(ß\8a߬ ß\9fß\8aß\9eß\8aß²ß\98ß\8aߣß\8dß² ߠߋ߬)",
+       "template-protected": "(ß\8a߬ ß¡ß\8aß\9eß\8aß²ß\9eß\8a߲ߣß\8d߲߫ ߠߋ߬)",
        "template-semiprotected": "(ߟߊ߬ߞߊ߲߬ߘߊ߬ߟߌ-ߝߊ߲߬ߞߋ߬ߟߋ߲߬ߡߊ)",
        "hiddencategories": "ߞߐߜߍ ߣߌ߲߬ ߦߋ߫ ߢߌ߲߬ ߠߎ߫ ߛߌ߲߬ߝߏ߲ ߠߋ߬ ߘߌ߫{{PLURAL:$1|}}",
        "permissionserrors": "ߝߌ߬ߟߌ߫ ߘߌ߬ߢߍ߬ߒߧߋ",
        "currentrev-asof": "$1 ߟߊ߫ ߡߊ߬ߦߟߍ߬ߡߊ߲߬ߠߌ߲ ߕߊ߬ߡߌ߲߬ߣߍ߲",
        "revisionasof": "ߊ߬ ߡߊߛߊ߬ߦߌ߲ ߦߊ߲߬ ߓߊ߫ 1$",
        "revision-info": "ߡߊ߬ߦߟߍ߬ߡߊ߲߬ߣߍ߲߫ $1 ߟߋ߬ ߓߟߏ߫ {{GENDER:$6|$2}}$7",
-       "previousrevision": "→ ߡߊ߬ߛߊ߬ߦߌ߲߬ߠߌ߲ ߞߘߐ߬ߡߊ߲",
+       "previousrevision": "→ ߡߊ߬ߛߊ߬ߦߌ߲߬ߠߌ߲߬ ߞߘߐߞߘߐ",
        "nextrevision": "ߡߊ߬ߛߋ߬ߦߌ߲߬ߣߍ߲߬ ߞߎߘߊ ←",
        "currentrevisionlink": "ߡߊ߬ߛߊ߬ߦߌ߲߬ߠߌ߲ ߕߊ߬ߡߌ߲߬ߣߍ߲",
        "cur": "ߞߍߞߎߘߊ",
        "last": "ߢߍߕߊ",
+       "histlegend": "ߝߘߏ߬ߢߐ߲߰ߡߊ ߡߊߡߌ߬ߘߊ: ߓߊߓߌߟߊߟߌ߫ ߞߏ߲ߘߏ ߡߊߡߌ߬ߘߊ߬ ߟߊߢߐ߲߯ߡߊ߫ ߞߊߡߊ߬߸ ߊ߬ ߣߌ߫ ߞߊ߬ ߟߊߢߐ߲߯ߡߊ߫ ߞߘߎ ߛߐ߲߬ߞߌ߲߫ ߊ߬ ߣߌ߫ ߓߊ߫ ߡߊߡߌ߬ߣߊ߬ߣߍ߲ ߕߍ߫ ߥߟߊ߫ ߞߎ߬ߘߎ ߡߍ߲ ߦߋ߫ ߘߎ߰ߟߊ߫. < br/> Legend: ({{int: cur}}) = ߓߐߢߐ߲߯ߡߊ ߡߍ߲ ߦߋ߫ ߕߋ߲߬ߕߋ߲߬ ߓߊ ߟߊ߫߸ ({{int: ߟߊߓߊ߲}}) = ߓߐߢߐ߲߯ߡߊ ߡߍ߲ ߦߋ߫ ߓߊ߫ ߕߊ߬ߡߌ߲߬ߣߍ߲ ߝߍ߬߸ {{int: ߢߟߊߞߎߘߦߊ߫ ߞߏߘߋߞߏߘߋ}} = ߛߊߞߍߟߌ߫ ߝߕߌߣߍ߲߫.",
        "history-fieldset-title": "ߣߐ߬ߡߊ߬ߛߊߦߌ߲ ߠߎ߬ ߛߍ߲ߛߍ߲߫",
        "histfirst": "ߞߘߐ߬ߡߊ߲ ߠߎ߬",
        "histlast": "ߞߎߘߊ ߟߎ߬",
        "difference-title": "ߘߊ߲߬ߝߘߊ߬ߓߐ ߡߍ߲ ߦߋ߫ ߡߛߊ߬ߦߌ߲߬ߠߌ߲ $1 ߕߍ߫",
        "lineno": "$1 ߛߌ߬ߕߊߙߌ:",
        "compareselectedversions": "ߘߟߊߡߌߘߊ߫ ߛߎߥߊ߲ߘߌߣߍ߲ ߠߎ߬ ߟߊߢߐ߲߯ߡߊ߫",
-       "editundo": "ߊ߬ ߘߐߛߊ߬߸ ߊ߬ ߓߟߏߞߊ߬߸ ߊ߬ ߓߙߐߕߐ߫",
+       "editundo": "ߊ߬ ߘߐߛߊ߬",
        "diff-empty": "(ߝߊߙߊ߲ߝߊ߯ߛߌ߫ ߕߴߊ߬ߟߎ߬ ߕߍ߫)",
        "diff-multi-sameuser": "({{PLURAL:$1|One intermediate revision|$1 intermediate revisions}} ߟߊ߬ߓߊ߰ߙߊ߬ ߞߋߟߋ߲ ߓߟߏ߫߸ ߏ߬ ߡߊ߫ ߦߌ߬ߘߊ߬)",
-       "diff-multi-otherusers": "({{PLURAL:$1|ß\95ß\8d߯ß\9fß\8aß\98ß\90ß« ß¡ß\9bß\8aߦß\8c߲ߠß\8c߲߫ ß\9eß\8bß\9fß\8b߲߫|ß\95ß\8d߯ß\9fß\8aß\98ß\90ß« ß¡ß\9bß\8aߦß\8c߲ߠß\8cß²}} {{PLURAL:$2|ß\9fß\8a߬ß\93ß\8aß°ß\99ß\8a߬ß\9fß\8aß« ß\98ß\8fß« ß\9cß\98ß\8dß«|ß\9fß\8a߬ß\93ß\8aß°ß\99ß\8a߬ß\9fß\8a ß\9fß\8e߬}} ß\93ß\9fß\8f߫߸ ß\8f߬ ß¡ß\8aß« ß¦ß\8c߬ß\98ß\8a߬)",
+       "diff-multi-otherusers": "({{PLURAL:$1|ß\95ß\8dß\9fß\90 ß¡ß\8aß\9bß\8aߦß\8c߲߬ß\9eß\8f߬ ß\9eß\8bß\9fß\8b߲߫|ß\95ß\8dß\9fß\90 ß¡ß\8aß\9bß\8a߬ߦß\8cß²}} {{PLURAL:$2|ß\9fß\8aß\93ß\8a߯ß\99ß\9fß\8aß« ß\98ß\8fß« ß\9cß\98ß\8dß«|ß\9fß\8aß\93ß\8a߯ß\99ß\9fß\8a ß\9fß\8e߬}} ß\8f߬ ß¡ß\8aß« ß\9fß\8aß²ß\9eߣß\8dß¡ß\8aß«)",
        "searchresults": "ߢߌߣߌ߲ߠߌ߲ ߞߐߝߟߌ ߟߎ߬",
-       "searchresults-title": "ߢß\8cߣß\8c߲ߠß\8cß² ß\9eß\90ß\96ß\8bß\93ß\8c \"$1\"",
+       "searchresults-title": "ߣß\8c߲߬ \"$1\" ß¢ß\8cߣß\8c߲ߠß\8cß² ß\9eß\90ß\9dß\9fß\8c",
        "prevn": "ߕߊ߬ߡߌ߲߬ߣߍ߲ ߠߎ߬ {{PLURAL:$1|$1}}",
        "nextn": "$1{{PLURAL:$1|ߟߊߕߎ߲߰ߠߊ}}",
        "prevn-title": "ߢߝߍߕߊ $1 {{PLURAL:$1|result|results}}",
        "nextn-title": "ߢߍߕߊ $1 {{PLURAL:$1|ߞߐߖߋߓߌ}}",
-       "shown-title": "ߦß\8cß\98ß\8aß\9eß\8a߬ $1{{PLURAL:$1|ß\9eß\90ß\9dß\9fß\8c |ß\9eß\90ß\9dß\9fß\8c ß\9fß\8e߬ }} ß\9eß\90ß\9cß\8dß« ß\9eß\8b߬ß\9fß\8b߲߬ß\9eß\8b߬ß\9fß\8b߲߬ߠß\8a",
+       "shown-title": "ß\9eß\90ß\9cß\8dß« ß\9eß\8b߬ß\9fß\8b߲߬ß\9eß\8b߬ß\9fß\8b߲߬ߠß\8a $1{{PLURAL:$1|ß\9eß\90ß\9dß\9fß\8c |ß\9eß\90ß\9dß\9fß\8c ß\9fß\8e߬ }} ß¦ß\8cß\98ß\8aß\9eß\8a߬",
        "viewprevnext": "($1 {{int:pipe-separator}} $2) ($3) ߦߋ߫",
        "searchmenu-exists": "</strong> ߞߐߜߍ ߘߏ߫ ߕߐ߯ ߦߋ߫ ߞߏ߫  \"[[:$1]]\" ߥߞߌ ߣߌ߲߬ ߘߐ߫.</strong> {{PLURAL:$2|0=|See also the other search results found.}}",
        "searchmenu-new": "<strong>ߞߐߜߍ ߘߏ߫ ߟߊߘߊ߲߫ \"[[:$1]]\" ߥߞߌ ߣߌ߲߬ ߘߐ߫߹</strong>  {{PLURAL:$2|0=|ߣߌ߲߬ ߝߣߊ߫ ߘߐߜߍ߫ the page found with your search.|ߣߌ߲߬ ߝߣߊ߫ ߘߐߜߍ߫ the search results found.}}",
        "recentchanges-summary": "ߥߞߌ ߡߊ߬ߦߟߍ߬ߡߊ߲߬ߠߌ߲߬ ߞߎ߲ߓߊ ߡߍ߲ ߠߎ߬ ߞߍߣߍ߲߫ ߞߐߜߍ ߣߌ߲߬ ߞߊ߲߬߸ ߏ߬ ߟߎ߫ ߣߐ߬ߣߐ߬.",
        "recentchanges-noresult": "ߡߊ߬ߦߟߍ߬ߡߊ߲߬ߠߌ߬ ߛߌ߫ ߓߍ߲߬ߢߐ߲߰ߦߊ߬ߣߍ߲߬ ߕߍ߫ ߛߎߡߊ߲ߡߕߊ ߢߌ߲߬ ߠߎ߫ ߡߊ߬ ߕߎ߬ߡߊ߬ ߟߊߕߍ߰ߣߍ߲ ߦߌ߬ߘߊ ߘߐ߫.",
        "recentchanges-label-newpage": "ߡߊ߬ߦߟߍ߬ߡߊ߲߬ߠߌ߲ ߣߌ߲߬ ߓߘߊ߫ ߘߐߜߍ߫ ߞߎߘߊ ߟߊߘߊ߲߫",
-       "recentchanges-label-minor": "ß¡ß\8a߬ߦß\9fß\8d߬ߡß\8a߲߬ߠß\8c߲߬ ß\98ß\8b߬ߣß\8dß² ß ß\8bß« ß¦ß\8bß«",
+       "recentchanges-label-minor": "ߢß\9fß\8aß\9eß\8eß\98ߦß\8aß« ß\9dß\95ß\8cߣß\8dß² ß ß\8b߬",
        "recentchanges-label-bot": "ߡߐ߰ߡߐ߮ ߟߋ߫ ߣߐ߬ ߡߊ߬ߦߟߍ߬ߡߊ߲߬ߠߌ ߣߌ߲߬ ߞߍ߫ ߟߊ߫",
        "recentchanges-label-unpatrolled": "ߡߊ߬ߦߟߍ߬ߡߊ߲߬ߠߌ߲ ߣߌ߲߬ ߡߊ߫ ߓߍ߬ߙߍ߲߬ߓߍ߬ߙߍ߲߬ ߡߎߣߎ߲߬",
        "recentchanges-label-plusminus": "ߞߐߜߍ ߢߊ߲ߞߊ߲ ߓߘߊ߫ ߡߊߦߟߍ߬ߡߊ߲߫ ߞߵߊ߬ ߝߌ߬ߘߊ߲ ߦߙߌߞߊ ߣߌ߲߬ ߘߌ߫",
        "rcshowhidemine-show": "ߊ߬ ߦߌ߬ߘߊ߬",
        "rcshowhidemine-hide": "ߊ߬ ߦߡߊߘߏ߲߰",
        "rclinks": "ߕߋ߬ߟߋ $2 ߕߊ߬ߡߌ߲߬ߣߍ߲ ߣߌ߲߬ ߡߝߊ߬ߟߋ߲߬ߠߌ߲߬ ߟߊ߬ߓߊ߲ $1 ߦߌ߬ߘߊ߬",
-       "diff": "ß\98ß\8a߲߬ß\9dß\98ß\8a߬ß\93ß\90",
-       "hist": "ß\95ß\8a߬ߡß\8c߲߬ߣß\8dß²",
+       "diff": "ß\9dß\98ß\8f߬ߢß\90߲߰ߡß\8a",
+       "hist": "ß\9eß\8a߬ß\9eß\98ß\90",
        "hide": "ߊ߬ ߢߡߊߘߏ߲߰",
        "show": "ߊ߬ ߦߌ߬ߘߊ߬",
        "minoreditletter": "ߡ",
        "newpageletter": "ߞ",
        "boteditletter": "ߓ",
-       "rc-change-size-new": "$1 {{PLURAL:$1|byte|bytes}}  ߡߊ߬ߝߊ߬ߟߋ߲߬ߠߌ߲ ߞߐ߫",
+       "rc-change-size-new": "$1 {{PLURAL:$1|ߝߌ߬ߘߊ߲|ߝߌ߬ߘߊ߲ ߠߎ߬}} ߢߟߊߞߎߘߦߊ ߞߐ߫",
        "rc-old-title": "ߊ߬ ߓߊߞߘߐ ߟߊߘߊ߲߫ ߣߍ߲߫ ߦߋ߫ ߕߊ߲߬ ߠߋ߫ \"$1\"",
        "recentchangeslinked": "ߡߊ߬ߦߟߍ߬ߡߊ߲߬ߠߌ߲ ߜߋ߲߬ߞߘߎ߬ߢߐ߲߰ߡߊ ߟߎ߬",
-       "recentchangeslinked-toolbox": "ß¡ß\8a߬ߦß\9fß\8d߬ߡß\8a߲߬ߠß\8cß« ß\93ß\8c߬ß\9fß\8a߬ߢß\90߲߰ߡß\8a",
+       "recentchangeslinked-toolbox": "ߢß\9fß\8aß\9eß\8eß\98ߦß\8aß\9fß\8cß« ß\9cß\8b߲߬ß\9eß\98ß\8e߬ߡß\8a ß\9fß\8e߬",
        "recentchangeslinked-title": "ߊ߬ ߟߌ߬ߤߟߊ ߡߊߦߟߍ߬ߡߊ߲߫ ߦߊ߲߬ \"$1\"",
        "recentchangeslinked-summary": "ߞߐߜߍ ߕߐ߮ ߟߊߘߏ߲߬߸ ߞߊ߬ ߞߐߜߍ ߛߘߌ߬ߜߋ߲ ߡߊ߬ߦߟߍ߬ߡߊ߲߬ߠߌ߲ ߦߋ߫߸ ߥߟߊ߫ \nߞߊ߬ ߝߘߊ߫ ߞߐߜߍ ߣߌ߲߬ ߠߊ߫. (ߖߐ߲߬ߛߊ߬ ߌ ߘߌ߫ ߦߌߟߡߊ ߛߌ߲߬ߝߏ߲ ߠߎ߬ ߦߋ߫߸ ߣߌ߲߬ ߠߊߘߏ߲߬ {{ns:category}}: ߦߌߟߡߊ ߕߐ߮). ߦߟߍ߬ߡߊ߲߬ ߡߍ߲ ߦߋ߫ ߞߐߜߍ ߣߌ߲߬ [[Special:Watchlist|your Watchlist]] ߘߐ߫߸ ߏ߬ ߦߋ߫ <strong>ߛߓߍߘߋ߲߫ ߞߎ߲ߓߊ</strong> ߟߋ߬ ߘߐ߫.",
        "recentchangeslinked-page": "ߘߐߜߍ ߕߐ߮:",
        "recentchangeslinked-to": "ߞߐߜߍ ߛߘߌ߬ߜߋ߲ ߠߎ߬ ߦߌ߬ߘߊ߬߸ ߞߊ߬ ߞߐߜߍ ߣߌ߬ ߞߋߟߋ߲ߘߌ߫",
-       "upload": "ߞߐߕߐ߮ ߟߊߦߟߍ߬",
+       "upload": "ߞߐߕߐ߮ ߟߊߦߟߍ",
        "uploadlogpage": "ߜߊ߲߬ߞߎ߲߬ߠߌ߲ ߘߏ߫ ߟߊߦߟߍ߬",
        "filedesc": "ߟߊߘߛߏߣߍ߲",
        "license": "ߟߊ߬ߘߌ߬ߢߍ߬ߟߌ ߦߴߌ ߘߐ߫:",
        "imgfile": "ߞߐߕߐ߮",
        "listfiles": "ߞߐߕߐ߮ ߛߙߍߘߍ",
        "file-anchor-link": "ߞߐߕߐ߮",
-       "filehist": "ß\9eß\90ß\95ß\90ß® ß\9fß\8aß« ß\98ß\90߬ß\9dß\90",
+       "filehist": "ß\9eß\90ß\95ß\90ß® ß\95ß\8e߬ߡß\8a߬ß\98ß\8a",
        "filehist-help": "ߕߎ߬ߡߊ߬ߘߊ/ߕߎ߬ߡߊ ߛߐ߲߬ߞߌ߲߬ ߓߊ߫߸ ߞߊ߬ ߕߎ߬ߡߊ߬ߘߊ ߞߐߕߐ߮ ߟߎ߬ ߦߋ߫.",
        "filehist-revert": "ߊ߬ ߟߊߢߊ߬",
        "filehist-current": "ߞߍߛߊ߲ߞߏ",
        "filehist-datetime": "ߕߎ߬ߡߊ߬ߘߊ/ߕߎ߬ߡߊ߬ߟߊ߲",
        "filehist-thumb": "ߞߝߊ߬ߟߋ߲ߛߋ߲",
-       "filehist-thumbtext": "ß¡ß\8a߬ߦß\9fß\8d߬ߡß\8a߲߬ߠß\8cß² ß ß\8aß\98ß\90߯ߦß\8aߣß\8dß² ß¡ß\8dß² ß¦ß\8bß« $1",
+       "filehist-thumbtext": "ß¡ß\8a߬ߦß\9fß\8d߬ߡß\8a߲߬ߠß\8cß² ß ß\8aß\98ß\90߯ߦß\8aߣß\8dß² ß\95ß\8e߬ߡß\8a߬ß\98ß\8a ß£ß\8c߲߬ $1 ß ß\8aß«",
        "filehist-nothumb": "ߖߌ߬ߦߊ߬ ߘߐ߯ߡߊ߲߫ ߕߴߦߋ߲߬",
        "filehist-user": "ߟߊ߬ߓߊ߰ߙߊ߬ߟߊ",
        "filehist-dimensions": "ߛߎߡߊ߲ߘߐ",
        "sharedupload-desc-here": "ߘߐ߬ߛߙߋ ߣߌ߲߬ ߦߋ߫ ߦߊ߲߬ ߠߋ߫ $1 ߖߊ߬ߕߋ߬ߘߐ߬ߛߌ߮ ߕߐ߭ ߟߎ߬ ߞߏ߬ߣߌ߲ ߘߌ߫ ߛߴߊ߬ ߟߊߓߊ߯ߙߊ߫ ߟߊ߫. ߊ߬ ߕߐ߯ ߛߓߍߟߌ ߦߙߐ [$2 ߞߐߕߐ߮ ߞߊ߲߬ߛߓߍߟߌ ߞߐߜߍ] ߟߋ߬ ߦߋ߫ ߘߎ߰ߟߊ ߘߐ߫ ߣߌ߲߬.",
        "filepage-nofile": "ߕߐ߮ ߣߌ߲߬ ߞߐߕߐ߯ ߛߎ߯ ߕߍ߫ ߦߋ߲߬",
        "upload-disallowed-here": "ߌ ߕߍߣߊ߬ ߞߐߜߍ ߣߌ߲߬ ߞߊ߲߬ߛߓߍ߫ ߟߊ߫.",
-       "randompage": "ß\93ß\8d߲߬ß\9bß\8b߲߬ߡß\8a߬ ߞߐߜߍ",
+       "randompage": "ß\9eß\8e߲߬ß\9dß\8d߬ ߞߐߜߍ",
        "statistics": "ߖߊ߬ߕߋ߬ߛߎ߬ߓߐ ߟߎ߬",
        "double-redirect-fixer": "ߟߊ߬ߞߎ߲߬ߛߌ߲߬ߠߌ߲ ߘߐߓߍ߲߬ߟߊ߲",
-       "nbytes": "$1 {{PLURAL:$1|byte|bytes}}",
+       "nbytes": "$1 {{PLURAL:$1|ߝߌ߬ߘߊ|ߝߌ߬ߘߊ߲ ߠߎ߬}}",
        "nmembers": "$1 {{PLURAL:$1|ߛߌ߲߬ߝߏ߲ |ߛߌ߲߬ߝߏ߲ ߠߎ߬}}",
        "prefixindex": "ߞߐߜߍ ߡߍ߲ ߠߎ߬ ߓߍ߯ ߟߊߝߟߐߣߍ߲߫",
        "listusers": "ߟߊ߬ߓߊ߰ߙߊ߬ߟߊ ߛߙߍߘߍ",
-       "newpages": "ß\98ß\90ß\9cß\8dß« ß\9eß\8eß\98ß\8a",
+       "newpages": "ß\9eß\90ß\9cß\8dß« ß\9eß\8eß\98ß\8a ß\9fß\8e߬",
        "move": "ߊ߬ ߛߋ߲߬ߓߐ߫",
        "pager-newer-n": "{{PLURAL:$1|ߞߎߘߡߊ1|ߞߎߘߡߊ$1}}",
        "pager-older-n": "{{PLURAL:$1|ߞߘߐ߬ߡߊ߲ ߁|ߞߘߐ߬ߡߊ߲ ߠߎ߬ $1}}",
        "speciallogtitlelabel": "ߞߏ߲߭ (ߞߎ߲߬ߕߐ߮ ߥߟߊ߫  {{ns:user}}: ߟߊ߬ߓߊ߰ߙߊ߬ߟߊ ߟߊ߫ ߟߊ߬ߓߊ߰ߙߊ߬ ߕߐ߮):",
        "log": "ߘߏ߲߬",
        "all-logs-page": "ߝߘߏ߬ߓߊ߬ ߜߊ߲ߞߎ߲ߠߌ߲ ߠߎ߬ ߓߍ߯",
-       "logempty": "ߦߙߍߞߍߟߌ߫ ߛߌ߫ ߓߍ߲߬ߢߐ߲߰ߦߊ߬ߣߍ߲߬ ߕߍ߫ ߝߐ߰ߓߍ ߟߎ߬ ߘߐ߫.",
+       "alllogstext": "ߓߟߏߞߘߐ߫ ߘߐߛߙߋ ߡߎ߰ߡߍ ߦߌ߬ߘߊ߬ߟߌ ߣߌ߲߬ ߞߣߐ߫ {{SITENAME}}.\nߌ ߘߌ߫ ߛߋ߫ ߛߙߍߘߍ ߘߊ߲߬ߠߊߕߍ߰ ߟߊ߫ ߓߘߍߞߍ߭ ߞߊ߬ ߢߊ߬߸ ߏ߬ ߛߋ߲߬ߝߍ߬ ߞߊ߬ ߘߐ߬ߛߙߋ ߛߎ߯ߦߊ ߡߊߡߌ߬ߘߊ߬߸ ߊ߬ ߣߌ߫ ߟߊߓߊ߯ߙߟߊ ߕߐ߮ (ߛߏ߬ߓߌ߬ߟߊ߲߬ߘߌ ߟߋ߬ ߛߓߍߘߋ߲ ߗߏ߯ߦߊ ߝߍ߬)߸ ߥߟߴߊ߬ ߥߟߏߣߍ߲߫ ߞߐߜߍ ߡߍ߲ ߞߊ߲߬ (ߛߏ߬ߓߌ߬ߟߊ߲߬ߘߌ ߟߋ߬ ߝߣߊ߫ ߛߓߍߘߋ߲ ߠߎ߬ ߗߏ߯ߦߊ ߝߍ߬).",
+       "logempty": "ߞߍߞߏ ߛߌ߫ ߣߌ߫ ߘߐ߬ߛߙߋ ߡߊ ߓߍ߲߬ ߢߐ߲߮ ߡߊ߬.",
        "allpages": "ߞߐߜߍ ߟߎ߬ ߓߍ߯",
        "allarticles": "ߞߐߜߍ ߟߎ߬ ߓߍ߯",
        "allpagessubmit": "ߥߊ߫",
        "watchlist-options": "ߞߣߐ߬ߜߍ߲߬ ߛߙߍߘߍ ߢߣߊߕߐߡߐ߲ ߠߎ߬",
        "enotif_reset": "ߞߐߜߍ߫ ߞߎ߲ߝߊ߲ߓߐߣߍ߲ ߠߎ߬ ߓߍ߯ ߕߐ߰ߡߊ߬ߛߙߋ߫",
        "dellogpage": "ߜߊ߲߬ߞߎ߲߬ߠߌ߲ ߖߏ߬ߛߌ߬ߣߍ߲",
-       "rollbacklink": "ß\8c ß\9eß\90ß\9bß\8a߬ߦß\8c߲߬ ß\8c ß£ß\90ß­ß¡ß\8a߬",
+       "rollbacklink": "ß\9fß\8aß\9eß\90ß\9bß\8a߬ߦß\8c߬",
        "rollbacklinkcount": "ߛߋ߬ߦߌ߲߬ ߌ ߣߐ߭ߡߊ߬ $1 {{PLURAL:$1|ߡߊߦߟߍ߬ߡߊ߲߫|ߟߎ߬ ߡߊߦߟߍ߬ߡߊ߲߫}}",
        "protectlogpage": "ߜߊ߲߬ߞߎ߲߬ߠߌ߲߬ ߠߊߞߊ߲ߘߊߣߍ߲",
        "protectedarticle": "ߟߊ߬ߞߊ߲߬ߘߊ߬ߣߍ߲ \"[[$1]]\"",
        "tooltip-invert": "ߞߏ߲߬ߘߏ ߣߌ߲߬ ߘߐߜߍ߫߸ ߞߊ߬ ߡߊ߬ߦߟߍ߬ߡߊ߲߬ߠߌ߲ ߠߎ߬ ߢߡߊߘߏ߲߰ ߞߐߜߍ ߟߎ߬ ߕߐ߯ ߞߣߍ߫ ߓߊߓߌ߬ߟߊ߬ߣߍ߲ ߘߐ߫ (ߊ߬ ߣߌ߫ ߕߐ߯ ߞߣߍ߫ ߓߟߏߘߏ߲߬ߣߍ߲ ߘߐߜߍߣߍ߲ ߠߎ߬)",
        "namespace_association": "ߕߐ߯ ߓߟߏߘߏ߲߬ߣߍ߲߫ ߢߐ߲߰ߓߟߏ",
        "tooltip-namespace_association": "ߞߏ߲߬ߘߏ ߣߌ߲߬ ߡߊߝߍߣߍ߲߫ ߓߊ߫ ߞߊ߬ ߓߊ߬ߘߏ߬ߓߊ߬ߘߌߦߊ ߥߟߊ߫ ߝߐߡߊ ߕߐ߮ ߞߣߍ ߡߍ߲ ߓߟߏߘߏ߲߬ߣߍ߲߫ ߦߋ߫ ߞߐߜߍ߫ ߓߊߕߐ߬ߡߐ߲߬ߣߍ߲ ߣߌ߲߬ ߘߐ߫߸ ߞߵߏ߬ ߟߊߘߏ߲߬.",
-       "blanknamespace": "(ߓߊߖߎ)",
+       "blanknamespace": "(ߓߊߖߎߡߊ)",
        "contributions": "ߓߟߏߡߊߜߍ߲ ߠߎ߬ {{GENDER:$1|ߟߊߓߊ߯ߙߟߊ}}",
        "contributions-title": "ߟߊ߬ߓߊ߰ߙߊ߬ߟߊ ߟߊ߫ ߓߟߏߓߌߟߊߢߐ߲߯ߞߊ߲ ߡߍ߲ ߦߋ߫$1",
        "mycontris": "ߓߟߏߓߌߟߊߢߐ߲߯ߞߊ߲",
        "ipboptions": "ߕߎ߬ߡߊ߬ߙߋ߲ ߂:2 hours, ߕߟߋ߬ ߁:1 day, ߕߋ߬ߟߋ ߃:3 days,ߞߎ߲߬ߢߐ߰ ߁:1 week, ߞߎ߲߬ߢߐ߮ ߂:2 weeks, ߞߊߙߏ߫ ߁:1 month, ߞߊߙߏ߫ ߃:3 months, ߞߊߙߏ߫ ߆:6 months,ߛߊ߲߬ ߁:1 year,ߤߊ߲߯ ߤߌ߲߯:infinite",
        "infiniteblock": "ߘߊ߲߬ߓߊߟߌ",
        "blocklink": "ߟߊ߬ߢߊ߬ߙߊ߲߬ߠߌ",
-       "contribslink": "ß¡ß\8aß\9bß\90߯ß\9fß\8c",
+       "contribslink": "ß\93ß\9fß\8fß¡ß\8aß\9cß\8dß²",
        "blocklogpage": "ߜߊ߲߬ߞߎ߲߬ߠߌ߲ ߓߊ߬ߟߊ߲߬ߠߌ",
        "blocklogentry": "ߊ߬ ߓߊ߬ߟߊ߲߬ߣߍ߲߬ ߦߋ߫ [[$1]] ߊ߬ ߕߎ߬ߡߊ ߕߊ߬ߡߌ߲ ߠߋ߬ ߞߏߛߐ߲߬ $2 $3",
        "reblock-logentry": "ߣߌ߲߬ ߓߊ߬ߟߊ߲߬ߠߌ߲ ߟߊ߬ߓߍ߲߬ߢߐ߲߰ߡߊ ߡߊߦߟߍ߬ߡߊ߲߬  [[$1]] ߊ߬ ߕߎ߬ߡߊ ߛߕߊ ߝߊ ߕߎߡߊ ߟߊ߫ $2 $3",
        "proxyblocker": "ߟߐ߲߬ߞߋ߬ߟߊ ߓߊ߬ߟߊ߲߬ߟߊ߲",
        "movelogpage": "ߜߊ߲߬ߞߎ߲ ߓߐ߫ ߊ߬ ߡߊ߬",
        "export": "ߞߐߜߍ ߟߎ߬ ߟߊߝߏ߬ߦߌ߬",
-       "thumbnail-more": "ß\8a߬ ß\9fß\8aß\9eß\8e߲߬ß\93ߦß\8a߬",
+       "thumbnail-more": "ß\8a߬ ß\9fß\8aß\9eß\8e߲߬ß\93ß\8a߬ߦß\8aß«",
        "importlogpage": "ߟߊ߬ߛߣߍ߬ߟߌ ߞߣߍ",
        "tooltip-pt-userpage": "{{GENDER:|ߌ ߟߊ߫ ߟߊ߬ߓߊ߰ߙߊ߬ߟߌ߬}} ߞߐߜߍ",
        "tooltip-pt-mytalk": "{{GENDER:|ߌ ߟߊ߫}} ߞߎߡߊ߫ ߞߐߜߍ߫",
        "tooltip-pt-preferences": "{{GENDER:|ߌ ߟߊ߫}} ߤߣߍߕߊ ߟߎ߬",
        "tooltip-pt-watchlist": "ߌ ߟߊ߫ ߞߐߜߍ߫ ߡߊߦߟߍ߬ߡߊ߲߬ߕߊ ߜߋ߬ߟߎ߲߬ߣߍ߲ ߠߎ߬ ߛߙߍߘߍ",
        "tooltip-pt-mycontris": "{{GENDER:|ߌ ߟߊ߫}} ߓߟߏߡߊߜߍ߲߫ ߛߙߍߘߍ ߟߎ߬",
-       "tooltip-pt-login": "ß\8c ß¡ß\8aß\98ß\8cߦß\8aߣß\8d߲߫ ß¦ß´ß\8c ß\9cß\8a߲߬ß\9eß\8e߲߫ ß¸ ß\98ß\8cߦß\8aß\9cß\8fߦß\8aß« ß\9eß\8f߬ߣß\8c߲߬ ߕߍ߫",
+       "tooltip-pt-login": "ß\8c ß\98ß\90ß\9bß\8eߣß\8d߲߫ ß\9cß\8a߲߬ß\9eß\8e߲߬ߠß\8cß² ß¡ß\8a߬߸ ß\9eß\8f߬ߣß\8c߲߬ ß\98ß\8cߦß\8aß\9cß\8fߦß\8aß« ߕߍ߫",
        "tooltip-pt-logout": "ߌ ߜߊ߲߬ߞߎ߲߬ ߓߐ߫",
-       "tooltip-pt-createaccount": "ß\8c ß¡ß\8aß\98ß\8cߦß\8aߣß\8d߲߫ ß¦ß\8bß« ß\96ß\8a߬ß\95ß\8b߬ß\98ß\8aß« ß\9fß\8aß\9eß\8a߬ ß\9eßµß\8c ß\9cß\8a߲߬ß\9eß\8e߲߫ ß¸ ß\93ß\8a߬ß\99ß\8c߬ ß\8c ß\98ß\8cߦß\8aß\9cß\8fߦß\8aߣß\8d߲߫ ß\95ß\8dß«",
-       "tooltip-ca-talk": "ß\98ß\90߬ß\9eß\95ß\8c߬ß\9fß\8c ß\9eß\8a߬ ß\93ß\8d߲߬ ß\9eß\90ß\9cß\8d ß\9eߣß\90ß\98ß\90 ß¡ß\8a߬",
+       "tooltip-pt-createaccount": "ß\8aß² ß§ß´ß\8c ß\98ß\90ß\9bß\8eß« ß\9fß\8aß« ß\96ß\8a߬ß\95ß\8b߬ß\98ß\8a߬ß\9eß\8f ß¡ß\8a߬ ß\8a߬ ß£ß\8cß« ß\98ß\8f߲߬ß\95ß\90ß°ß\9fß\8a߬ß\98ß\8f߲߸ ß\9eß\8f߬ߣß\8c߲߬ ß¢ß\8a߬ß\92߬ß\9eß\90߬ß\93ß\8aß\9fß\8cß« ß\95ß\8dß« ß¢ß\8aß« ß\9bß\8cß« ß\9eß\8a߲߬",
+       "tooltip-ca-talk": "ß\9eߣß\90ß\98ß\90 ß\9eß\90ß\9cß\8d ß\9eß\8fߢß\8a ß\98ß\90ߢß\8cß¡ß\8c߲ߠß\8cß²",
        "tooltip-ca-edit": "ߞߐߜߍ ߣߌ߲߬ ߡߊߦߟߍ߬ߡߊ߲߬",
        "tooltip-ca-addsection": "ߛߌ߰ߘߊ߬ ߞߎߘߊ߫ ߘߊߡߌ߬ߣߊ߬",
        "tooltip-ca-viewsource": "ߞߐߜߍ ߣߌ߲߬ ߠߊߞߊ߲ߘߊߣߍ߲߫ ߠߋ߬.\nߌ ߘߌ߫ ߛߴߊ߬ ߛߎ߲ ߘߐߜߍ߫ ߟߊ߫",
-       "tooltip-ca-history": "ß\9eß\90ß\9cß\8d ß£ß\8c߲߬ ß\9bß\8aß\9eß\8dß\9fß\8cß« ß\95ß\8a߬ߡß\8c߲߬ߣß\8dß² ß ß\8eß« ß\98ß\90ß\9cß\8dß«",
+       "tooltip-ca-history": "ß\9eß\90ß\9cß\8d ß£ß\8c߲߬ ß\9bß\8aß\9eß\8dß\9fß\8cß« ß\9eß\98ß\90 ß\9fß\8e߬",
        "tooltip-ca-protect": "ߞߐߜߍ ߣߌ߲߬ ߠߊߞߊ߲ߘߊ߫",
        "tooltip-ca-delete": "ߞߐߜߍ ߣߌ߲߬ ߖߏ߰ߛߌ߫",
        "tooltip-ca-move": "ߘߐߜߍ ߣߌ߲߬ ߛߋ߲߬ߓߐ߫",
-       "tooltip-ca-watch": "ß\9eß\90ß\9cß\8d ß£ß\8c߲߬ ß\9dß\99ß\8a߬ ß\8c ß\9fß\8aß« ß\9fß\8aß\9eß\99ß\90߬ß\9bß\8c߬ß\95ß\8a߬ ß\9bß\99ß\8dß\98ß\8d ß\9fß\8eß« ߞߊ߲߬",
+       "tooltip-ca-watch": "ß\9eß\90ß\9cß\8d ß£ß\8c߲߬ ß\9dß\99ß\8a߬ ß\8c ß\9fß\8aß« ß\9eß\99ß\90߬ß\9bß\8c߬ß\95ß\8a ß\9fß\8e߬ ß\9bß\99ß\8dß\98ß\8d ߞߊ߲߬",
        "tooltip-ca-unwatch": "ߞߐߜߍ ߣߌ߲߬ ߛߋ߲߬ߓߐ߫ ߌ ߟߊ߫ ߟߊߞߙߐ߬ߛߌ߬ߕߊ߬ ߛߙߍߘߍ ߘߐ߫",
-       "tooltip-search": "ß\8a߬ ß¢ß\8cߣß\8c߲߫ {{SITENAME}} ß\98ߐ߫",
-       "tooltip-search-go": "ß\95ß\90ß® ß£ß\8c߲߬ ß¢ß\8cߣß\8c߲߫ ß\9eß\90ß\9cß\8dß« ß\9eߣß\90߫ ߣߴߊ߬ ߞߍ߫ ߘߊ߫ ߦߋ߲߬",
-       "tooltip-search-fulltext": "ߞߎߡߊߘߋ߲߫ ߣߌ߲߬ ߞߐߜߍ߫ ߟߎ߫ ߢߌߣߌ߲߫",
-       "tooltip-p-logo": "ß\9eß\90ß\9cß\8dß« ß\93ß\8fß\9fß\8fß²ß\98ß\8a ß¡ß\8aß\9dß\8dߣß\8d߲߫",
-       "tooltip-n-mainpage": "ß\9eß\90ß\9cß\8dß« ß\93ß\8fß\9fß\8fß²ß\98ß\8a ß¡ß\8aß\9dß\8dߣß\8d߲߫",
-       "tooltip-n-mainpage-description": "ß\9eß\90ß\9cß\8dß« ß\93ß\8fß\9fß\8fß²ß\98ß\8a ß¡ß\8aß\9dß\8dߣß\8d߲߫",
-       "tooltip-n-portal": "ß\9eß\8a߬ ß\93ß\8d߲߬ ß£ß\95ß\8a߬ß\98ß\90߬ß\9bß\8c ß¡ß\8a߬ ß¸ ß\8c ß\98ß´ß\9bß\8bß« ß¡ß\8e߲߬ ß\9eß\8dß« ß\9fß\8aß« ß¸ ß\9dß\8bß² ß ß\8eß« ߦߋ߫ ߛߐ߬ߘߐ߲߬ ߠߊ߫ ߡߌ߲߫",
-       "tooltip-n-currentevents": "ß\8c ß\9fß\8aß« ß\9eß\8e߲߬ߠß\8a߬ß\9dß\8eß\9fß\8bß² ß¡ß\8aß\9eß\8a߬ß\9dß\8f߬ ß\9eß\8a߬ ß\93ß\8d߲߬ ß\9eß\8dß\95ß\8a ß¡ß\8dß² ß ß\8eß« ß¦ß\8bß« ß\9bß\8b߲߬ߠß\8aß«",
-       "tooltip-n-recentchanges": "ß\98ß\90߬ß\9dß\8a߬ß\9fß\8b߲߬ߠß\8c߬ ß\9eß\8eß\98ß\8a ß\9fß\8e߬ ß\9bß\99ß\8dß\98ß\8d ß¥ß\9eß\8cß« ß\9eߣß\90ß«",
-       "tooltip-n-randompage": "ß\93ß\8d߲߬ß\9bß\8b߲߬ߡß\8a߬ ß\9eß\90ß\9cß\8d ß\98ß\8fß« ß¦ß\8c߬ß\98ß\8a߬",
-       "tooltip-n-help": "ß\8a߬ ß¢ß\8cߣß\8c߲߫ ߦߙߐ",
-       "tooltip-t-whatlinkshere": "ߥß\9eß\8cß« ß\9eß\90ß\9cß\8d ß\93ß\8d߯ ß\9bß\98ß\8c߬ß\9cß\8bß² ß ß\8b߬ ß¦ß\8bß« ß¦ß\8aß²߬",
-       "tooltip-t-recentchangeslinked": "ß¡ß\8a߬ߦß\9fß\8d߬ߡß\8a߲߬ߠß\8c߬ ß\9eß\8eß\98ß\8a ß\9fß\8e߬ ß\9eß\90ß\9cß\8dß« ß\98ß\90ß« ß¡ß\8dß² ß£ß\8cß« ß\9eß\90ß\9cß\8d ß£ß\8c߲߬ ß\95ß\8e߲߰ߣß\8dß²߫",
+       "tooltip-search": "ß\8a߬ ß¢ß\8cߣß\8c߲߫ {{SITENAME}} ß\9eߣߐ߫",
+       "tooltip-search-go": "ߥß\8aß« ß\9eß\90ß\9cß\8d ß£ß\8c߲߬ ß\9eß\8a߬ ß\8a߬ß\9fß\8b߬ ß\95ß\90߯ ß\9eß\8bß\9fß\8bß² ß\98ß\8c߫ ߣߴߊ߬ ߞߍ߫ ߘߊ߫ ߦߋ߲߬",
+       "tooltip-search-fulltext": "ߞߎߡߊߘߋ߲ ߣߌ߲߬ ߢߌߣߌ߲߫ ߞߐߜߍ ߟߎ߬ ߞߣߐ߫",
+       "tooltip-p-logo": "ß\95ß\8a߯ ß\93ß\90ß« ß\93ß\8f߬ß\9fß\8f߲߬ß\98ß\8a߬ ß\9eß\90ß\9cß\8d ß¡ß\8a߬",
+       "tooltip-n-mainpage": "ß\95ß\8a߯ ß\93ß\90ß« ß\93ß\8f߬ß\9fß\8f߲߬ß\98ß\8a߬ ß\9eß\90ß\9cß\8d ß¡ß\8a߬",
+       "tooltip-n-mainpage-description": "ß\95ß\8a߯ ß\93ß\90ß« ß\93ß\8f߬ß\9fß\8f߲߬ß\98ß\8a ß\9eß\90ß\9cß\8d ß¡ß\8a߬",
+       "tooltip-n-portal": "ß\9eß\8a߬ ß\93ß\8d߲߬ ß\96ß\8a߬ß\95ß\8b߬ß\98ß\90߬ß\9bß\8cß® ß¡ß\8a߬߸ ß¡ß\8e߲߬ ß\98ß\8cß« ß\9bß\8bß« ß\9eß\8dß« ß\9fß\8a߫߸ ß\9eß\8e߲߬ߠß\8a߬ß\9dß\8eß\9fß\8bß² ß ß\8e߬ ߦߋ߫ ߛߐ߬ߘߐ߲߬ ߠߊ߫ ߡߌ߲߫",
+       "tooltip-n-currentevents": "ß\9eß\8e߲߬ߠß\8a߬ß\9dß\8e߬ß\9fß\8b߲߬ ß¡ß\8a߬ß\9eß\8aß\9dß\8f ß\9fß\8e߬ ß¡ß\8aß\9dß\9fß\8dß« ß\9eß\8dß\9eß\8eß\98ß\8aß« ß\9bß\8b߲߬ߠß\8a߬ß\95ß\8a ß\9fß\8eß« ß\9dß\8d߬",
+       "tooltip-n-recentchanges": "ߥß\9eß\8c ß¡ß\8a߬ߦß\9fß\8d߬ߡß\8a߲߬ߠß\8c߲߬ ß\9eß\8eß\98ß\8a ß\9fß\8e߬ ß\9bß\99ß\8dß\98ß\8d",
+       "tooltip-n-randompage": "ß\9eß\90ß\9cß\8d ß\98ß\8fß« ß¡ß\8aߦß\9fß\8d߬ߡß\8a߲߬ ß\9eß\8e߲߬ß\9dß\8d߬ß\9eß\8f ß\98ß\90ß«",
+       "tooltip-n-help": "ß\98ß\8d߬ߡß\8d߲߬ ߦߙߐ",
+       "tooltip-t-whatlinkshere": "ß\9eß\90ß\9cß\8d ß\9fß\8eß« ß\9bß\98ß\8c߬ß\9cß\8bß² ß\9bß\99ß\8dß\98ß\8d߸ ß¡ß\8dß² ß ß\8eß« ß\93ß\8c߬ß\9fß\8a߬ߣß\8d߲߫ ß¦ß\8a߲߬ ß¡ß\8a߬",
+       "tooltip-t-recentchangeslinked": "ß¡ß\8a߬ߦß\9fß\8d߬ߡß\8a߲߬ߠß\8c߲߬ ß ß\8a߬ß\93ß\8aß² ß¡ß\8dß² ß ß\8e߬ ß¦ß\8bß« ß\9eß\90ß\9cß\8d ß£ß\8c߲߬ ß\9bß\98ß\8c߬ß\9cß\8bß² ß ß\8e߬ ß\98ß\90߫",
        "tooltip-feed-atom": "ߞߐߜߍ ߣߌ߲߬ ߝߕߌ߫ ߓߊߟߏ",
        "tooltip-t-contributions": "{{GENDER:$1|ߟߊ߬ߓߊ߰ߙߊ߬ߟߊ}} ߟߊ߫ ߓߟߏߓߌߟߊߢߐ߲߮ߞߊ߲ ߛߙߍߘߍ",
        "tooltip-t-emailuser": "ߢߎߡߍߙߋ߲ߞߏ߲ߘߏ ߟߊߕߊ߯ ߟߊߓߊ߯ߙߟߊ ߣߌ߲߬ ߡߊ߬{{GENDER:$1|ߟߊߓߊ߯ߙߟߊ}}",
-       "tooltip-t-upload": "ß\9eß\90ß\95ß\90ß® ß\9fß\8eß« ߟߊߦߟߍ߬",
-       "tooltip-t-specialpages": "ߘߎ߲߬ߘߎ߬ߡߊ߬ ߞߐߜߍ߫ ߟߎ߫ ߛߙߍߘߍ",
-       "tooltip-t-print": " ߞߐߜߍ ߣߌ߲߬  ߜߌ߬ߙߌ߲߬ߘߌ߬ߕߊ߬ߡߊ ߛߎ߮",
-       "tooltip-t-permalink": "ß\9eß\90ß\9cß\8d ß£ß\8c߲߬ ß¡ß\9bß\8a߬ߦß\8c߲߬ߠß\8c߲߬ ß\9bß\98ß\8c߬ß\9cß\8b߲߬ ß\93ß\9fß\8fß\95ß\8dß°ß\93ß\8aß\9fߌ",
+       "tooltip-t-upload": "ß\9eß\90ß\95ß\90ß® ß\9fß\8e߬ ߟߊߦߟߍ߬",
+       "tooltip-t-specialpages": "ߘߎ߲߬ߘߎ߬ߡߊ߬ ߞߐߜߍ ߞߋ߬ߟߋ߲߬ߞߋ߬ߟߋ߲߬ߠߊ ߟߎ߬ ߛߙߍߘߍ",
+       "tooltip-t-print": "\nߞߐߜߍ ߣߌ߲߬ ߓߐߞߏߣߊ߲߫ ߜߌߙߌ߲ߘߌߕߊ",
+       "tooltip-t-permalink": "ß\9eß\90ß\9cß\8d ß£ß\8c߲߬ ß¡ß\9bß\8a߬ߦß\8c߲߬ߠß\8c߲߬ ß\9bß\98ß\8c߬ß\9cß\8b߲߬ ß\9eß\8eß\98ß\8aߦߌ",
        "tooltip-ca-nstab-main": "ߞߐߜߍ ߞߣߐߘߐ ߘߐߜߍ߫",
        "tooltip-ca-nstab-user": "ߞߐߜߍ߫ ߟߊߓߊ߯ߙߕߊ ߘߐߜߍ߫",
-       "tooltip-ca-nstab-special": "ߣß\8c߲߬ ß¦ß\8bß« ß\98ß\90ß\9cß\8dß« ß\93ß\9fß\8fß¡ß\8aß\9eß\8a߬ߣß\8dß² ß ß\8b߬ ß\98ß\8c߫߸ ß\8a߬ ß\95ß\8dß« ß\9bß\8bß« ß¡ß\8aߦß\9fß\8d߬ߡß\8a߲߬ ß ߊ߫",
+       "tooltip-ca-nstab-special": "ߣß\8c߲߬ ß¦ß\8bß« ß\98ß\90ß\9cß\8dß« ß\93ß\9fß\8fß¡ß\8aß\9eß\8a߬ߣß\8dß² ß ß\8b߬ ß\98ß\8c߫߸ ß\8a߬ ß\95ß\8dß« ß\9bß\8bß« ß¢ß\9fß\8aß\9eß\8eß\98ߦß\8aß« ß\9fߊ߫",
        "tooltip-ca-nstab-project": "ߖߊ߬ߕߋ߬ߘߐ߬ߛߌ߰ ߞߐߜߍ ߘߐߜߍ߫",
        "tooltip-ca-nstab-image": "ߞߐߕߐ߮ ߞߐߜߍ ߟߎ߫ ߘߐߜߍ߫",
        "tooltip-ca-nstab-mediawiki": "ߞߊ߲ߞߋ ߗߋߛߓߍ ߘߐߜߍ߫",
        "tooltip-diff": "ߌ ߟߊ߫ ߛߓߍߟߌ߫ ߡߊߦߟߍ߬ߣߍ߲ ߦߌ߬ߘߊ߬",
        "tooltip-compareselectedversions": "ߘߊ߲߬ߝߘߊ߬ߓߐ ߡߍ߲ ߦߋ߫ ߡߊ߬ߛߊ߬ߦߌ߲߬ߠߌ߲ ߓߊߕߐ߬ߡߐ߲߬ߣߍ߲ ߝߌ߬ߟߊ ߟߎ߬ ߕߍ߫ ߞߐߜߍ ߣߌ߲߬ ߘߐ߫߸ ߏ߬ ߦߋ߫",
        "tooltip-watch": "ߞߐߜߍ ߣߌ߲߬ ߓߌ߬ߟߊ߬ ߌ ߟߊ߫ ߜߋ߬ߟߎ߬ߠߌ߲߬ ߛߙߍߘߍ ߘߐ߫",
-       "tooltip-rollback": "\"ß\98ß\90ß\9bßµß\8a߬ ß¡ß\8a߬\" ß\93ß\9fß\8fß\93ß\8cß\9fß\8aߢß\90߲߯ß\9eß\8a߲ߠß\8a ß\9fß\8aß\93ß\8aß² ß ß\8aß« ß¡ß\8a߬ߦß\9fß\8d߬ߡß\8a߲߬ߠß\8cß² ß¡ß\8aß\9bß\8a߬ߦß\8c߬ ß\9eß\90ß\9cß\8d ß£ß\8c߲߬ ß\98ß\90ß« ß\9bß\90߲߬ß\9eß\8c߲߬ߠß\8c߲߬ ß\9eß\8bß\9fß\8b߲߫ ß\98ß\90߫",
+       "tooltip-rollback": "\"ß\9fß\8a߬ß\9eß\90߬ß\9bß\8a߬ߦß\8c߬ß\9fß\8c\" ß\93ß\9fß\8fß¡ß\8aß\9cß\8d߲ߠß\8a ß\9fß\8aß« ß¢ß\9fß\8aß\9eß\8eß\98ߦß\8aß« ß\9fß\8aß\93ß\8aß² (ß ß\8e߬) ß¦ß\8bß« ß\9fß\8aß\9eß\90ß\9bß\8a߬ߦß\8c߬ ß\9fß\8aß« ß\9eß\90ß\9cß\8d ß£ß\8c߲߬ ß\9eߣß\90ß« ß\9bß\90߲߬ß\9eß\8c߲߬ß\9eß\8f߬ ß\9eß\8bß\9fß\8b߲߫ ß\94ß\8bß« ß\9fß\8b߬ ß\9fß\8a߫",
        "tooltip-undo": "\"ߊ߬ ߘߐߛߊ߬\" ߡߊ߬ߦߟߍ߬ߡߊ߲߬ߠߌ߲ ߣߌ߲߬ ߞߐߛߊ߬ߦߌ߬ ߞߊ߬ ߡߊ߬ߦߟߍ߬ߡߊ߲߬ߠߌ߲ ߝߊ߬ߘߌ ߟߊߞߊ߬ ߢߍߦߋߟߌ ߝߊ߬ߘߌ ߘߐ߫. ߊ߬ ߘߌ߫ ߖߡߊ߬ߙߌ߬ߦߊ ߘߌ߫ ߟߊ߬ߘߛߏ߬ߟߌ ߡߊ߬ߦߟߍ߬ߡߊ߲߬ߠߌ߲ ߡߊ߬.",
        "tooltip-summary": "ߟߊ߬ߘߛߏ߬ߣߍ߲߬ ߛߎ߬ߘߎ߲߬ߣߍ߲ ߘߏ߫ ߟߊߘߏ߲߬",
        "simpleantispam-label": "ߛߑߔߊߡ ߛߌ߬ߣߊ ߡߊ߬ߝߍ߬ߣߍ߲߬ߠߌ߲.\nߊ߬ ߞߍ߫ <strong>not</strong> ߣߌ߲߬ ߠߝߊ߫߹",
        "pageinfo-recent-authors": "ߞߐߛߊ߲߫ ߛߓߍߦߟߊ߫ ߓߐߣߍ߲ߢߐ߲߰ߡߊ ߟߎ߫ ߖߊ߬ߕߋ",
        "pageinfo-magic-words": "ߛߎߓߊ߯ߦߊ߫ {{PLURAL:$1|ߞߎߡߊߘߋ߲|ߞߎߡߊߘߋ߲ ߠߎ߬ }}($1)",
        "pageinfo-hidden-categories": "ߢߡߊߘߏ߲߰ߠߌ߲ {{PLURAL:$1|ߦߌߟߡߊ|ߦߌߟߡߊ ߟߎ߬(1$)}}",
-       "pageinfo-templates": "ß\95ß\8dß\98ß\90ß\98ß\9bß\8fߣß\8dß² {{PLURAL:$1|ߞߙߊ߬ߞߏ|ߞߙߊ߬ߞߏ ߟߎ߬}} $1",
-       "pageinfo-toolboxlink": "ß\9eß\90ß\9cß\8d ß\9eß\8c߬ß\93ß\8a߬ß\99ß\8f߬ߦß\8a",
+       "pageinfo-templates": "ß\9eß\90߬ߣß\90ß¡ß\8a߬-ß\95ß\8dß\9fß\90 {{PLURAL:$1|ߞߙߊ߬ߞߏ|ߞߙߊ߬ߞߏ ߟߎ߬}} $1",
+       "pageinfo-toolboxlink": "ß\9eß\90ß\9cß\8d ß£ß\8c߲߬ ß\9eß\8e߲߬ߠß\8a߬ß\9dß\8eß\9fß\8bß²",
        "pageinfo-contentpage": "ߊ߬ ߖߊ߬ߕߋ߬ ߞߣߐߘߐ߫ ߞߐߜߍ ߘߏ߫ ߘߌ߫",
        "pageinfo-contentpage-yes": "ߐ߲߬ߤߐ߲߫",
        "patrol-log-page": "ߜߊ߲߬ߞߎ߲߬ߠߌ߲ ߓߍ߬ߙߍ߲߬ߓߍ߬ߙߍ߲߬",
        "show-big-image": "ߞߐߕߐ߮ ߓߊߛߎ߲",
        "show-big-image-preview": "ߊ߬ ߢߍߦߋߟߌ ߢߊ߲ߞߊ߲: $1.",
        "show-big-image-other": "{{PLURAL:$2|ߢߊߓߐߟߌ|ߢߊߓߐߟߌ ߟߎ߬}} ߕߐ߬ߡߊ $1.",
-       "show-big-image-size": "$1 × $2 ߖߌ߬ߦߊ߬ߘߊ߲ߕߊ",
-       "metadata": "ß¡ß\8bß\95ß\8aß\98ß\8a߯ß\95ß\8aß«",
+       "show-big-image-size": "ߖߌ߬ߦߊ߬ߙߋ߲ $1 × $2",
+       "metadata": "ß\9fß\90ß²ß\95ß\8aß\9eß\90 ß\9fß\8e߬",
        "metadata-help": "ߞߌ߬ߓߊ߬ߙߏ߬ߦߊ߬ߟߌ߬ ߜߘߍ߫ ߟߎ߫ ߦߋ߫ ߞߐߕߐ߮ ߣߌ߲߬ ߘߐ߫߸ ߊ߬ ߟߊߘߏ߲߬ߣߍ߲߬ ߦߋ߫ ߞߍ߫ ߟߊ߫ ߞߍߟߊ߲߫ ߡߍ߲ߛߍ߲ߡߊ ߟߋ߫ ߟߊ߫ ߥߟߊ߫ ߖߌ߬ߦߊ߬ߕߍ߬ߟߊ߲߸ ߞߵߊ߬ ߟߊߓߊ߯ߙߊ߫ ߥߟߊ߫ ߞߵߊ߬ ߡߍ߲ߛߍ߲ߡߊ.\nߣߴߊ߬ ߡߊߦߟߍ߬ߡߊ߲߬ ߣߍ߲߬ ߞߍ߫ ߘߊ߫ ߞߊ߬ ߓߴߊ߬ ߛߎ߲ߞߎ߲ ߡߊ߬߸ ߞߌ߬ߓߊ߬ߙߏ߬ߦߊ ߘߏ߫ ߟߎ߫ ߕߍ߫ ߣߊ߬ ߟߊߞߊ߲߬ߘߏ߬ ߟߊ߫ ߞߐߕߐ߯ ߡߊߦߟߍ߬ߡߊ߲߬ߣߍ߲ ߘߐ߫.",
-       "metadata-fields": "ß¡ß\8bß\95ß\8aß\98ß\95ß\8a ß\96ß\8c߬ߦß\8a߬ß\93ß\8d ß\9eߣß\8d ß¡ß\8dß² ß¦ß\8bß« ß\97ß\8bß\9bß\93ß\8d ß£ß\8c߲߬ ß\98ß\90߫߸ ß\8f߬ ß\98ß\8cß« ß£ßµß\8a߬ ß\9eß\8e߲߬ß\93ß\90ß« ß\96ß\8c߬ߦß\8a߬ß\93ß\8d ß\9eß\90ß\9cß\8d ß\98ß\90ß« ß£ß\8cß« ß¡ß\8bß\95ß\8aß\98ß\95ß\8a ß¥ß\9fß\8a߬ß\9fß\8bß² ß ß\8aß\98ß\90߯ߦß\8aß« ß\98ß\8aß«.ß\8a߬ ß\95ß\90ß­ ß\9fß\8e߬ ß¢ß¡ß\8aß\98ß\8f߲߰ߣß\8dß² ß\98ß\8cß« ß\95ß\8fß« ß\9dß\8dß­ ß\9eß\8fß\9bß\90߲߬.\nâ\80¢ß\8a߬ ß\9eß\8dß« \nâ\80¢ß\9bß\8e߯ߦß\8a \nâ\80¢ß\95ß\8e߬ߡß\8a߬ß\98ß\8a ß£ß\8cß« ß\95ß\8e߬ߡß\8a߬ß\99ß\8bß² ß\93ß\90ß\9bß\8e߲ߡß\8a \nâ\80¢ß\9fß\8a߬ß\9dß\8fߦß\8c ß\95ß\8e߬ߡß\8a߬ß\98ß\8a߬ ß\96ß\90ß²ß\96ß\90ß² \nâ\80¢ß\9e ß\9dß\99ß\8dß\95ß\8d \nâ\80¢ß¡.ß\9b\9b ß\9eß\8aß\9fß\8cߦß\8a ß¡ß\90߬ß\9fß\90߲߬ߦß\8a߬ß\9fß\8c \nâ\80¢ß\95ß\8aß\9eß\8e߲ߡß\8a ß¥ß\8a߲߬ߥß\8aß² \nâ\80¢ß\9eß\8e߬ß\9bß\8aß² \nâ\80¢ß\93ß\8aߦß\9fß\8dß¡ß\8aß² ß¤ß\8aß\9eß\8d \nâ\80¢ß\96ß\8c߬ߦß\8a߬ß\93ß\8d ß\9eß\8a߲߬ß\9bß\93ß\8dß\9fß\8c \nGPS ß\98ß\9fß\8aß\95ß\8dß® \nGPS ß\98ß\8eß°ß\95ß\8dß\9fß\8dß² \nGPS ß\9eß\90ß\93ß\8b",
+       "metadata-fields": "ß\9fß\90ß²ß\95ß\8aß\9eß\90ß« ß\96ß\8c߬ߦß\8a߬ß\93ß\8d ß\9eߣß\8d ß¡ß\8dß² ß¦ß\8bß« ß\97ß\8bß\9bß\93ß\8d ß£ß\8c߲߬ ß\98ß\90߫߸ ß\8f߬ ß\98ß\8cß« ß£ß\8a߬ ß¥ß\9fß\8fß« ß\96ß\8c߬ߦß\8a߬ß\93ß\8d ß\9eß\90ß\9cß\8d ß\98ß\90ß« ß£ß\8cß« ß\9fß\90ß²ß\95ß\8aß\9eß\90ß« ß¥ß\9fß\8a߬ß\9fß\8bß² ß ß\8aß\98ß\90߯ߦß\8aß« ß\98ß\8aß«. ß\8a߬ ß\95ß\90ß­ ß\9fß\8e߬ ß¢ß¡ß\8aß\98ß\8f߲߰ߣß\8dß² ß\98ß\8cß« ß\95ß\8fß« ß\9dß\8dß­ ß\9eß\8fß\9bß\90߲߬.\nâ\80¢ß\8a߬ ß\9eß\8dß« \nâ\80¢ß\9bß\8e߯ߦß\8a \nâ\80¢ß\95ß\8e߬ߡß\8a߬ß\98ß\8a ß£ß\8cß« ß\95ß\8e߬ߡß\8a߬ß\99ß\8b߲߫ ß\93ß\90ß\9bß\8e߲ߡß\8a \nâ\80¢ß\9fß\8a߬ß\9dß\8fߦß\8c ß\95ß\8e߬ߡß\8a߬ß\98ß\8a߬ ß\96ß\90ß²ß\96ß\90ß² \nâ\80¢ß\9e ß\9dß\99ß\8dß\95ß\8d \nâ\80¢ß¡.ß\9b\9b ß\9eß\8aß\9fß\8cߦß\8a ß¡ß\90߬ß\9fß\90߲߬ߦß\8a߬ß\9fß\8c \nâ\80¢ß\95ß\8aß\9eß\8e߲ߡß\8a ß¥ß\8a߲߬ߥß\8aß² \nâ\80¢ß\9eß\8e߬ß\9bß\8aß² \nâ\80¢ß\93ß\8aߦß\9fß\8dß¡ß\8aß² ß¤ß\8aß\9eß\8d  ß\98ß\9eß\96 \nâ\80¢ß\96ß\8c߬ߦß\8a߬ß\93ß\8d ß\9eß\8a߲߬ß\9bß\93ß\8d\nâ\80¢ß\98ß\9fß\8aß\95ß\8dß® ß\98ß\9eß\96 (ß\98ß\8a߲߬ߠß\8a߬ß\95ß\8dß° ß\9eß\8aß²ß\9eß\8bß« ß\96ß\8a߯ß\93ß¡ß\8a)\nâ\80¢ß\98ß\8eß°ß\95ß\8dß\9fß\8dß² ß\98ß\9eß\96 (ß\98ß\8a߲߬ߠß\8a߬ß\95ß\8dß° ß\9eß\8aß²ß\9eß\8bß« ß\96ß\8a߯ß\93ß¡ß\8a)\nâ\80¢ß\9eß\90ß\93ß\8b ß\98ß\9eß\96 (ß\98ß\8a߲߬ߠß\8a߬ß\95ß\8dß° ß\9eß\8aß²ß\9eß\8bß« ß\96ß\8a߯ß\93ß¡ß\8a)",
        "namespacesall": "ߊ߬ ߓߍ߯",
        "monthsall": "ߡߎ߰ߡߍ",
        "imgmultipagenext": "ߞߐߜߍ ߣߊ߬ߕߐ ←",
        "redirect-file": "ߞߐߕߐ߯ ߕߐ߮",
        "specialpages": "ߘߎ߲߬ߘߎ߬ߡߊ߬ ߞߐߜߍ ߟߎ߬",
        "tag-filter": "[[Special:Tags|ߞߊ߲ߠߊߛߓߍ]] ߢߡߊߘߏ߲߰ߣߍ߲",
-       "tag-list-wrapper": "[[Special:Tags|{{PLURAL:$1|Tag|Tags}}]]: $2",
+       "tag-list-wrapper": "[[Special:Tags|{{PLURAL:$1|ߡߊ߬ߛߙߋ |ߡߊ߬ߛߙߋ ߟߎ߬ }}]]: $2",
        "tags-active-yes": "ߐ߲߬ߐ߲߬ߐ߲߫",
        "tags-active-no": "ߍ߲߬ߍ߲ߍ߲߬",
        "tags-hitcount": "{{PLURAL:$1|ߦߟߍ߬ߡߊ߲߬ߠߌ|$1 ߦߟߍ߬ߡߊ߲߬ߠߌ ߠߎ߬}}",
        "logentry-newusers-autocreate": "ߟߊߓߊ߯ߙߊߟߊ ߟߊ߫ ߖߊ߬ߕߋ߬ߘߊ $1{{GENDER:$2|ߟߊߘߊ߲߫ ߘߊ߫ }} ߞߍߒߖߘߍߦߋ߫ ߓߟߏߡߊ߬",
        "logentry-upload-upload": "$1 {{GENDER:$2|ߟߊ߬ߦߟߍ߬ߟߌ߬ߣߐ ߟߋ߬}} $3",
        "logentry-upload-overwrite": "$1 {{GENDER:$2|ߓߘߊ߫ ߟߊ߬ߦߟߍ߬ߟߌ ߞߍ߫}} ߞߊ߲ߦߟߍߡߊ߲߫ ߞߎߘߊ߫ ߣߌ߲߬ ߠߊ߫ $3",
-       "searchsuggest-search": "{{SITENAME}} ߊ߬ ߢߌߣߌ߲߫",
+       "searchsuggest-search": "ߊ߬ ߢߌߣߌ߲߫ ߣߌ߲߬{{SITENAME}} ߞߣߐ߫",
        "duration-days": "$1 {{PLURAL:$1|ߟߏ߲|ߟߏ߲ ߠߎ߬}}",
        "randomrootpage": "ߓߍ߲߬ߛߋ߲߬ߡߊ߬ ߞߐߜߍ ߓߏ߬ߞߊߘߌ"
 }
index 0bf3cbe..e911b3c 100644 (file)
                        "Matěj Suchánek",
                        "Didifelisberto",
                        "Tks4Fish",
-                       "Luig"
+                       "Luig",
+                       "Piotrex43"
                ]
        },
        "tog-underline": "Ligação sublinhada:",
        "virus-unknownscanner": "antivírus desconhecido:",
        "logouttext": "'''Agora você encontra-se desautenticado.'''\n\nNote que algumas páginas podem continuar sendo exibidas como se você ainda estivesse autenticado até que você limpe a ''cache'' do seu navegador.",
        "logging-out-notify": "Você está sendo desconectado, por favor aguarde.",
-       "logout-failed": "Não é possível encerrar a sessão agora",
+       "logout-failed": "Não é possível sair agora: $1",
        "cannotlogoutnow-title": "Não é possível encerrar a sessão agora",
        "cannotlogoutnow-text": "Não é possível sair usando $1.",
        "welcomeuser": "Bem-vindo, $1!",
        "recentchangeslinked-summary": "Introduza o nome de uma página para ver as mudanças a todas as páginas que contêm hiperligações para ela ou para as quais a página fornecida contém hiperligações (para ver as que pertencem a uma categoria, introduza {{ns:category}}:Nome da categoria). As mudanças às suas [[Special:Watchlist|páginas vigiadas]] aparecem a <strong>negrito</strong>.",
        "recentchangeslinked-page": "Nome da página:",
        "recentchangeslinked-to": "Inversamente, mostrar mudanças nas páginas que contêm ligações para esta",
-       "recentchanges-page-added-to-category": "[[:$1]]adicionada à categoria",
+       "recentchanges-page-added-to-category": "[[:$1]] adicionada à categoria",
        "recentchanges-page-added-to-category-bundled": "[[:$1]] adicionado à categoria, [[Special:WhatLinksHere/$1|esta página é incluída em outras páginas]]",
        "recentchanges-page-removed-from-category": "[[:$1]] removida da categoria",
        "recentchanges-page-removed-from-category-bundled": "[[:$1]] removido da categoria, [[Special:WhatLinksHere/$1|esta página é incluída em outras páginas]]",
index b550dd1..ab6e350 100644 (file)
        "virus-scanfailed": "a verificação falhou (código $1)",
        "virus-unknownscanner": "antivírus desconhecido:",
        "logouttext": "<strong>Já não está autenticado.</strong>\n\nTenha em atenção que algumas páginas poderão continuar a ser apresentadas como se ainda estivesse autenticado até limpar a ''cache'' do seu navegador.",
+       "logging-out-notify": "A sua sessão está a ser terminada; aguarde, por favor.",
+       "logout-failed": "Não é possível terminar a sessão agora: $1",
        "cannotlogoutnow-title": "Não é possível encerrar a sessão agora",
        "cannotlogoutnow-text": "Não pode encerrar a sessão quando utilizar $1.",
        "welcomeuser": "Bem-vindo, $1!",
index 40900a3..edb642a 100644 (file)
        "virus-scanfailed": "scanare eșuată (cod $1)",
        "virus-unknownscanner": "antivirus necunoscut:",
        "logouttext": "'''Acum sunteți deconectat.'''\n\nȚineți minte că anumite pagini pot fi în continuare afișate ca și când ați fi autentificat până când curățați memoria cache a navigatorului.",
+       "logging-out-notify": "Sunteți în curs de dezautentificare, așteptați.",
+       "logout-failed": "Nu se poate face dezautentificarea acum: $1",
        "cannotlogoutnow-title": "Nu se poate deconecta acum",
        "cannotlogoutnow-text": "Deconectarea nu este posibilă când se utilizează $1.",
        "welcomeuser": "Bun venit, $1!",
index 9e617e9..e5c8899 100644 (file)
        "virus-scanfailed": "ошибка сканирования (код $1)",
        "virus-unknownscanner": "неизвестный антивирус:",
        "logouttext": "<strong>Вы завершили сеанс работы.</strong>\n\nНекоторые страницы могут продолжить отображаться так, как будто вы все ещё не завершили сеанс, пока вы не обновите кэш браузера.",
+       "logging-out-notify": "Вы выходите из системы, пожалуйста, подождите.",
+       "logout-failed": "Невозможно выйти прямо сейчас: $1",
        "cannotlogoutnow-title": "Невозможно выйти прямо сейчас",
        "cannotlogoutnow-text": "Нельзя выйти во время использования $1.",
        "welcomeuser": "Добро пожаловать, $1!",
index 826c164..879cc2e 100644 (file)
        "virus-scanfailed": "skeniranje nije uspjelo (code $1)",
        "virus-unknownscanner": "nepoznati anti-virus program:",
        "logouttext": "'''Sad ste odjavljeni.'''\n\nObratite pažnju da neke stranice mogu nastaviti da se prikazuju kao da ste još uvijek prijavljeni, dok ne očistite keš svog preglednika.",
+       "logging-out-notify": "Odjavljujem Vas. Sačekajte.",
+       "logout-failed": "Trenutno Vas ne mogu odjaviti: $1",
        "cannotlogoutnow-title": "Odjava trenutno nije moguća",
        "cannotlogoutnow-text": "Odjava nije moguća tijekom uporabe $1.",
        "welcomeuser": "Dobro došli, $1!",
        "rcfilters-filter-categorization-description": "Zapisi iz stavljanja stranica u kategorije ili njihovo uklanjanje iz njih.",
        "rcfilters-filter-logactions-label": "Zapisane radnje",
        "rcfilters-filter-logactions-description": "Administrativni postupci, pravljenje računa, brisanje stranica, otpremanje...",
+       "rcfilters-hideminor-conflicts-typeofchange-global": "Filter „Manje izmjene” je u sukobu sa jednim ili više filtera vrste izmjena, zato što određene vrste ne mogu da se označe kao manje. Sukobljeni filteri su označeni u području Aktivni filteri iznad.",
+       "rcfilters-hideminor-conflicts-typeofchange": "Određene vrste promjena ne mogu da se označe kao „manje”, tako da je ovaj filter u sukobu sa sljedećim filterima vrste promjena: $1",
+       "rcfilters-typeofchange-conflicts-hideminor": "Ovaj filter vrste promjene je u sukobu sa filterom „Manje izmjene”. Određeni vrste promjena ne mogu da se označe kao „manje”.",
        "rcfilters-filtergroup-lastrevision": "Posljednje revizije",
        "rcfilters-filter-lastrevision-label": "Posljednja revizija",
        "rcfilters-filter-lastrevision-description": "Samo najnovije revizije u stranici.",
        "upload-dialog-button-upload": "Postavi",
        "upload-form-label-infoform-title": "Detalji",
        "upload-form-label-infoform-name": "Ime",
+       "upload-form-label-infoform-name-tooltip": "Kratki i jedinstveni naslov datoteke, koji će poslužiti kao njen naziv. Možete koristiti čist jezik s međuprostorom, ali nemojte pisati proširenje datoteke.",
        "upload-form-label-infoform-description": "Opis",
+       "upload-form-label-infoform-description-tooltip": "Ukratko opišite sve što je važno za posao. Ako je fotografija, navedite glavne stvari koje su prikazane na njemu, događaju ili mjestu.",
        "upload-form-label-usage-title": "Korištenje",
        "upload-form-label-usage-filename": "Ime datoteke",
        "upload-form-label-own-work": "Ovo je moje djelo",
        "blocklink": "blokiraj",
        "unblocklink": "Odblokiraj / Одблокирај",
        "change-blocklink": "promijeni blokadu",
+       "empty-username": "(nedostupno korisničko ime)",
        "contribslink": "doprinosi",
        "emaillink": "pošalji e-mail",
        "autoblocker": "Automatski ste blokirani jer je vašu IP adresu nedavno koristio \"[[User:$1|$1]]\". Razlog za blokiranje $1 je: \"'''$2'''\"",
        "limitreport-unstrip-size": "Unstrip veličina nakon proširenja",
        "limitreport-unstrip-size-value": "$1/$2 {{PLURAL:$2|bajt|bajta|bajtova}}",
        "expandtemplates": "Proširi šablone",
+       "expand_templates_intro": "Ova posebna stranica uzima jedan wikitekst i rekurzivno proširuje sve šablone u njemu.\nTakođer proširuje parserske funkcije poput\n<code><nowiki>{{</nowiki>#language:…}}</code> i varijable poput\n<code><nowiki>{{</nowiki>CURRENTDAY}}</code>.\nU principu, proširuje gotovo sve između dvostrukih vitičastih zagrada.",
        "expand_templates_title": "Naslov konteksta, za {{FULLPAGENAME}} itd.:",
        "expand_templates_input": "Ulazni wikitekst:",
        "expand_templates_output": "Izvod",
        "expand_templates_generate_xml": "Prikaži XML stablo za raščlanjivanje",
        "expand_templates_generate_rawhtml": "Prikazivaj neobrađeni HTML",
        "expand_templates_preview": "Pregled",
+       "expand_templates_preview_fail_html": "<em>Budući da {{SITENAME}} ima uključen sirov HTML, te je bilo gubitka sesijskih podataka, pregled je sakriven kao mjera predostrožnosti protiv napada preko JavaScripta.</em>\n\n<strong>Ako je je ovo legitiman pokušaj pretpregleda, tada pokušajte ponovo.</strong>\nAko i dalje ne bude radilo, [[Special:UserLogout|odjavite se]], i ponovo prijavite se i provjerite dozvoljava li Vaš preglednik kolačiće s ovog sajta.",
+       "expand_templates_preview_fail_html_anon": "<em>Budući da {{SITENAME}} ima uključen sirov HTML, te je bilo gubitka sesijskih podataka, pregled je sakriven kao mjera predostrožnosti protiv napada preko JavaScripta.</em>\n\n<strong>Ako je ovo legitiman pokušaj pretpregleda, [[Special:UserLogin|odjavite se]] i pokušajte ponovo.</strong>",
        "expand_templates_input_missing": "Morate unjeti neki wikitekst.",
        "pagelanguage": "Promena jezika stranice",
        "pagelang-name": "Stranica",
        "log-description-pagelang": "Ovo je evidencija promjena jezika stranica.",
        "logentry-pagelang-pagelang": "$1 {{GENDER:$2|smijenio je|smijenila je}} jezik stranice $3 iz $4 u $5.",
        "default-skin-not-found": "Nažalost, predodređena tema vašeg wikija ddefinirana u <code dir=\"ltr\">$wgDefaultSkin</code> kao <code>$1</code> nije dostupna.\n\nVaša uspostava sadrži {{PLURAL:$4|sljedeću temu|sljedeće teme}}. Pogledajte [https://www.mediawiki.org/wiki/Manual:Skin_configuration Priručnik: Podešavanje tema] da biste saznali kako ih uključiti i kako odabrati osnovnu.\n\n$2\n\n; Ako ste upravo uspostavili MediaWiki:\n: Vjerovatno ste je uspostavili sa gita, ili pak neposredno sa izvornog koda koristeći se nekom drugom metodom. Ovo je za očekivati. Pokušajte uspostaviti neku temu sa [https://www.mediawiki.org/wiki/Category:All_skins kataloga tema] tako što ćete:\n:* Sa preuzimanjem [https://www.mediawiki.org/wiki/Download tarball-uspostavljača], koji sami sadrži nekoliko tema i proširenja. Možete prekopirati folder <code>skins/</code> iz njega.\n:* Preuzimanje tarball-i za teme sa [https://www.mediawiki.org/wiki/Special:SkinDistributor mediawiki.org]. \n:* [https://www.mediawiki.org/wiki/Download_from_Git#Using_Git_to_download_MediaWiki_skins Koristeći Git kako biste preuzeli teme].\n: Ovo ne bi trebalo utjecati na vaše git skladište ako ste MediaWiki razvijatelj.\n\n; Ako ste upravo nadogradili MediaWiki:\n: MediaWiki 1.24 i više verzije više ne automatski uključuju uspostavljene teme (pogl. [https://www.mediawiki.org/wiki/Manual:Skin_autodiscovery Priručni: Samoistraživanje tema]). Možete prekopirati {{PLURAL:$5|sljedeći red kǒda|sljedeće redove kǒda}} u <code>LocalSettings.php</code> kako biste uključili {{PLURAL:$5|uspostavljenu temu|sve uspostavljene teme}}:\n\n<pre dir=\"ltr\">$3</pre>\n\n; Ako ste upravo izmijenili datoteku <code>LocalSettings.php</code>:\n: Provjerite je li ispravno napisani nazivi tema.",
+       "default-skin-not-found-no-skins": "Nažalost, predodređena tema vašeg wikija, definirana u <code dir=\"ltr\">$wgDefaultSkin</code> kao <code>$1</code>, nije dostupna.\n\nNemate uspostavljenih tema.\n\n; Ako ste upravo uspostavili ili nadogradili MediaWiki:\n: Vjerovatno ste je uspostavili sa git-a, ili sa izvornog koda nekim drugim načinom. Ovo je za očekivati. MediaWiki 1.24 i novije vrezije ne sadržavaju teme u glavnom skladištu. Pokušajte uspostaviti neku temu sa [https://www.mediawiki.org/wiki/Category:All_skins kataloga tema] tako što ćete:\n:* Preuzimanjem [https://www.mediawiki.org/wiki/Download tarball uspostavljačku datoteku] koji sadrži nekoliko tema i proširenja. Možete prekopirati folder <code>skins/</code> iz nje.\n:* Preuzeti zasebne uspostavljačke tarball datoteke sa stranice [https://www.mediawiki.org/wiki/Special:SkinDistributor mediawiki.org]. \n:* [https://www.mediawiki.org/wiki/Download_from_Git#Using_Git_to_download_MediaWiki_skins Koristiti Git kako biste preuzeli teme].\n: To ne bi trebalo ometati vaše git-skladište ako ste programer MediaWiki-ja. Pogledajte [https://www.mediawiki.org/wiki/Manual:Skin_configuration \nPriručnik: Postavljanje tema] kako biste saznali kako ih uključiti i kako odabrati osnovnu.",
        "default-skin-not-found-row-enabled": "* <code>$1</code> / $2 (uključena)",
        "default-skin-not-found-row-disabled": "* <code>$1</code> / $2 (<strong>isključena</strong>)",
        "mediastatistics": "Statistike za slike i snimke",
        "authmanager-provider-password": "Verifikacija lozinkom",
        "authmanager-provider-password-domain": "Verifikacija lozinkom i domenom",
        "authmanager-provider-temporarypassword": "Privremena lozinka",
+       "authprovider-confirmlink-message": "Na temelju nedavnih pokušaja prijave, s vašim računom mogu se povezati sljedeći računi. Povezivanje će vam omogućiti da se prijavite s tim računima. Odaberite one s kojima se želite povezati.",
        "authprovider-confirmlink-request-label": "Računi koji se trebaju povezati",
        "authprovider-confirmlink-success-line": "$1: Uspješno povezano.",
        "authprovider-confirmlink-failed": "Povezivanje računa nije uspjelo u potpunosti: $1",
        "authpage-cannot-link-continue": "Ne mogu nastaviti sa spajanjem računa. Najvjerovatnije vaša sesija je istekla.",
        "cannotauth-not-allowed-title": "Pristup je odbijen",
        "cannotauth-not-allowed": "Nije vam dozvoljeno da koristite ovu stranicu",
+       "changecredentials": "Promjena akreditiva",
+       "changecredentials-submit": "Promijeni akreditive",
+       "changecredentials-invalidsubpage": "$1 ne predstavlja ispravni tip akreditiva.",
+       "changecredentials-success": "Vaši akreditivi su smijenjeni.",
+       "removecredentials": "Uklanjanje akreditiva",
+       "removecredentials-submit": "Ukloni akreditive",
+       "removecredentials-invalidsubpage": "$1 ne predstavlja ispravni tip akreditiva.",
+       "removecredentials-success": "Vaši akreditivi su uklonjeni.",
+       "credentialsform-provider": "Tip akreditiva:",
+       "credentialsform-account": "Ime računa:",
+       "cannotlink-no-provider-title": "Nema spojivih računa",
+       "cannotlink-no-provider": "Nema spojivih računa.",
+       "linkaccounts": "Spajanje računa",
+       "linkaccounts-success-text": "Račun je spojen.",
+       "linkaccounts-submit": "Spoji račune",
+       "unlinkaccounts": "Razdvajanje računa",
+       "unlinkaccounts-success": "Račun je razdvojen.",
        "userjsispublic": "Napomena: podstranice s JavaScriptom ne bi trebale sadržavati povjerljive podatke budući da ih drugi korisnici mogu vidjeti.",
        "userjsonispublic": "Imajte na umu: Podstranice s JSONom ne bi trebale sadržavati povjerljive podatke budući da su vidljive drugim korisnicima.",
        "usercssispublic": "Napomena: podstranice s CSS-om ne bi trebale sadržavati povjerljive podatke budući da ih drugi korisnici mogu vidjeti.",
index 3cd2e59..0dfdb07 100644 (file)
@@ -40,7 +40,8 @@
                        "BadDog",
                        "Fitoschido",
                        "Stalker",
-                       "Vlad5250"
+                       "Vlad5250",
+                       "Петар Петковић"
                ]
        },
        "tog-underline": "Подвлачење веза:",
        "ipb-confirm": "Потврди блокирање",
        "ipb-sitewide": "На целом сајту",
        "ipb-partial": "Делимично",
+       "ipb-sitewide-help": "Свака страница на викију и све остале уређивачке радње.",
+       "ipb-partial-help": "Одређене стране или простори имена.",
        "ipb-pages-label": "Странице",
        "ipb-namespaces-label": "Именски простори",
        "badipaddress": "Неважећа IP адреса",
        "emaillink": "пошаљи е-поруку",
        "autoblocker": "Аутоматски сте блокирани јер делите IP адресу с корисником/цом [[User:$1|$1]].\nРазлог блокирања корисника/це $1 је „$2“",
        "blocklogpage": "Дневник блокирања",
-       "blocklog-showlog": "{{GENDER:$1|Овај корисник је раније блокиран|Ова корисница је раније блокирана}}.\nДневник блокирања је наведен испод као референца:",
-       "blocklog-showsuppresslog": "{{GENDER:$1|Овај корисник је раније блокиран и сакривен|Ова корисница је раније блокирана и сакривена}}.\nДневник сакривања је наведен испод као референца:",
+       "blocklog-showlog": "{{GENDER:$1|Овај корисник је раније блокиран|Ова корисница је раније блокирана}}.\nДневник блокирања је наведен испод:",
+       "blocklog-showsuppresslog": "{{GENDER:$1|Овај корисник је раније блокиран и сакривен|Ова корисница је раније блокирана и сакривена}}.\nДневник сакривања је наведен испод:",
        "blocklogentry": "је блокирао [[$1]] са временом истицања од $2 $3",
        "reblock-logentry": "је {{GENDER:|променио|променила}} подешавања блокирања за {{GENDER:$1|корисника|корисницу}} [[$1]] са временом истека од $2 ($3)",
        "blocklogtext": "Ово је евиденција радњи блокирања и деблокирања корисника.\nАутоматски блокиране IP адресе нису наведене.\nПогледајте [[Special:BlockList|листу блокирања]] за тренутно оперативне забране и блокирања.",
        "ipb_hide_partial": "Блокирања сакривених корисничких имена морају бити на нивоу сајта.",
        "ipb_already_blocked": "„$1“ је већ блокиран.",
        "ipb-needreblock": "$1 је већ блокиран. Желите ли да промените подешавања?",
-       "ipb-otherblocks-header": "{{PLURAL:$1|Друга блокада|Друге блокаде}}",
+       "ipb-otherblocks-header": "{{PLURAL:$1|1=Друга блокада|Друге блокаде}}",
        "unblock-hideuser": "Не можете деблокирати овог корисника јер је његово корисничко име сакривено.",
        "ipb_cant_unblock": "Грешка: блокада $1 не постоји. Можда је корисник деблокиран.",
        "ipb_blocked_as_range": "Грешка: IP адреса $1 није директно блокирана и не може да се деблокира.\nОна је блокирана као део блокаде $2, која може да се деблокира.",
index ac8efbb..836f8ad 100644 (file)
        "lastmodifiedatby": "Ovu stranicu je poslednji put {{GENDER:$4|uredio|uredila|uredio}} $3, na datum $1 u $2 č.",
        "othercontribs": "Zasnovano na radu korisnika $1.",
        "others": "drugi",
-       "siteusers": "{{PLURAL:$2|1={{GENDER:$1|korisnik|korisnica}}|korisnici}} na projektu {{SITENAME}} $1",
+       "siteusers": "{{PLURAL:$2|1={{GENDER:$1|suradnika|suradnice}}|suradnica i suradnika}} na projektu {{SITENAME}} $1",
        "anonusers": "{{PLURAL:$2|anoniman korisnik|anonimni korisnici}} na projektu {{SITENAME}} $1",
        "creditspage": "Autori stranice",
        "nocredits": "Ne postoje podaci o autoru ove stranice.",
index a13fe24..2b2d98b 100644 (file)
        "virus-scanfailed": "การสแกนล้มเหลว (รหัส $1)",
        "virus-unknownscanner": "โปรแกรมป้องกันไวรัสที่ไม่รู้จัก:",
        "logouttext": "<strong>คุณออกจากระบบแล้ว</strong>\n\nสังเกตว่าบางหน้าอาจยังแสดงผลเสมือนว่าคุณยังเข้าสู่ระบบอยู่ จนกว่าคุณจะล้างแคชเบราว์เซอร์ของคุณ",
+       "logging-out-notify": "คุณกำลังออกจากระบบ โปรดรอสักครู่",
+       "logout-failed": "ไม่สามารถออกจากระบบได้ในขณะนี้: $1",
        "cannotlogoutnow-title": "ไม่สามารถออกจากระบบได้ตอนนี้",
        "cannotlogoutnow-text": "ไม่สามารถออกจากระบบได้เมื่อกำลังใช้ $1",
        "welcomeuser": "ยินดีต้อนรับ $1!",
index 66236b4..b3f6ced 100644 (file)
        "virus-scanfailed": "помилка сканування (код $1)",
        "virus-unknownscanner": "невідомий антивірус:",
        "logouttext": "'''Ви вийшли з системи.'''\n\nДеякі сторінки можуть відображатися, ніби Ви ще в системі, аж поки Ви не оновите кеш браузера.",
+       "logging-out-notify": "Ви виходите із системи, будь ласка, зачекайте.",
+       "logout-failed": "Неможливо вийти прямо зараз: $1",
        "cannotlogoutnow-title": "Неможливо вийти прямо зараз",
        "cannotlogoutnow-text": "Неможливо вийти із системи під час використання $1.",
        "welcomeuser": "Вітаємо, $1!",
index 9d2fabd..d799a17 100644 (file)
@@ -91,6 +91,7 @@
        "tog-norollbackdiff": "Bỏ qua bản so sánh sau khi lùi sửa",
        "tog-useeditwarning": "Cảnh báo khi tôi thoát trang sửa đổi mà chưa lưu trang",
        "tog-prefershttps": "Luôn sử dụng kết nối an toàn khi đã đăng nhập",
+       "tog-showrollbackconfirmation": "Yêu cầu xác nhận khi bấm nút lùi hàng loạt sửa đổi",
        "underline-always": "Luôn luôn",
        "underline-never": "Không bao giờ",
        "underline-default": "Mặc định của giao diện hoặc trình duyệt",
        "virus-scanfailed": "quét thất bại (mã $1)",
        "virus-unknownscanner": "không nhận ra phần mềm diệt virus:",
        "logouttext": "'''Bạn đã đăng xuất.'''\n\nXin lưu ý rằng một vài trang có thể vẫn hiển thị như khi bạn còn đăng nhập, cho đến khi bạn xóa vùng nhớ đệm (''cache'') của trình duyệt.",
+       "logging-out-notify": "Đang đăng xuất, xin chờ đợi.",
+       "logout-failed": "Không thể đăng xuất lúc này: $1",
        "cannotlogoutnow-title": "Không thể đăng xuất lúc này",
        "cannotlogoutnow-text": "Không thể đăng xuất khi đang dùng $1.",
        "welcomeuser": "Hoan nghênh, $1!",
        "page_first": "đầu",
        "page_last": "cuối",
        "histlegend": "Chọn so sánh: Đánh dấu để chọn các phiên bản để so sánh rồi nhấn Enter hoặc nút ở dưới.<br />\nChú giải: '''({{int:cur}})''' = khác với phiên bản hiện hành, '''({{int:last}})''' = khác với phiên bản trước, '''{{int:minoreditletter}}''' = sửa đổi nhỏ.",
-       "history-fieldset-title": "Tìm trong lịch sử trang",
+       "history-fieldset-title": "Lọc phiên bản",
        "history-show-deleted": "Chỉ những sửa đổi bị xóa",
        "histfirst": "cũ nhất",
        "histlast": "mới nhất",
        "historysize": "({{PLURAL:$1|1 byte|$1 byte}})",
-       "historyempty": "(trống)",
+       "historyempty": "trống",
        "history-feed-title": "Lịch sử thay đổi",
        "history-feed-description": "Lịch sử thay đổi của trang này ở wiki",
        "history-feed-item-nocomment": "$1 vào lúc $2",
        "right-reupload-own": "Tải đè tập tin cũ do chính mình tải lên",
        "right-reupload-shared": "Ghi đè lên kho hình ảnh dùng chung",
        "right-upload_by_url": "Tải tập tin từ địa chỉ URL",
-       "right-purge": "Tẩy bộ đệm của trang mà không có trang xác nhận",
+       "right-purge": "Tẩy sạch vùng nhớ đệm của trang",
        "right-autoconfirmed": "Không bị ảnh hưởng bởi mức giới hạn tần suất sử dụng theo địa chỉ IP",
        "right-bot": "Được đối xử như tác vụ tự động",
        "right-nominornewtalk": "Không báo về tin nhắn mới khi trang thảo luận chỉ được sửa đổi nhỏ",
        "action-changetags": "thêm và loại bỏ các thẻ tùy ý trên các phiên bản riêng và các mục nhật trình",
        "action-deletechangetags": "Xóa thẻ khỏi cơ sở dữ liệu",
        "action-purge": "làm mới trang này",
+       "action-apihighlimits": "có giới hạn truy cập API cao hơn",
+       "action-autoconfirmed": "không bị ảnh hưởng bởi mức giới hạn tần suất sử dụng theo địa chỉ IP",
+       "action-bigdelete": "xóa trang có lịch sử lớn",
+       "action-blockemail": "cấm người dùng gửi thư điện tử",
+       "action-bot": "được đối xử như tác vụ tự động",
+       "action-editprotected": "sửa trang khóa ở mức “{{int:protect-level-sysop}}”",
+       "action-editsemiprotected": "sửa trang khóa ở mức “{{int:protect-level-autoconfirmed}}”",
+       "action-editinterface": "sửa giao diện người dùng",
+       "action-editusercss": "sửa tập tin CSS của người dùng khác",
+       "action-edituserjson": "sửa tập tin JSON của người dùng khác",
+       "action-edituserjs": "sửa đổi tập tin JavaScript của người dùng khác",
+       "action-editsitecss": "sửa đổi CSS toàn trang",
+       "action-editsitejson": "sửa đổi JSON toàn trang",
+       "action-editsitejs": "sửa đổi JavaScript toàn trang",
+       "action-editmyusercss": "sửa đổi tập tin CSS cá nhân của mình",
+       "action-editmyuserjson": "sửa đổi tập tin JSON cá nhân của mình",
+       "action-editmyuserjs": "sửa đổi tập tin JavaScript cá nhân của mình",
+       "action-viewsuppressed": "xem các phiên bản được ẩn mà mọi người khác không thấy được",
+       "action-hideuser": "cấm thành viên, rồi ẩn nó đi",
+       "action-ipblock-exempt": "bỏ qua tác vụ cấm, tự động cấm, và cấm dải địa chỉ IP",
+       "action-unblockself": "tự bỏ cấm",
+       "action-noratelimit": "không bị ảnh hưởng bởi mức giới hạn tần suất sử dụng",
+       "action-reupload-own": "tải đè tập tin cũ do chính mình tải lên",
+       "action-nominornewtalk": "không báo về tin nhắn mới khi trang thảo luận chỉ được sửa đổi nhỏ",
+       "action-markbotedits": "đánh dấu lùi sửa là sửa đổi bot",
+       "action-patrolmarks": "xem dấu tuần tra thay đổi gần đây",
+       "action-override-export-depth": "xuất trang kèm theo các trang được liên kết đến với độ sâu tối đa là 5",
+       "action-suppressredirect": "không tạo đổi hướng từ tên cũ khi di chuyển trang",
        "nchanges": "$1 thay đổi",
        "enhancedrc-since-last-visit": "$1 {{PLURAL:$1|sau lần truy cập vừa rồi}}",
        "enhancedrc-history": "lịch sử",
        "rcfilters-savedqueries-already-saved": "Đã lưu các bộ lọc này rồi. Thay đổi tùy chọn để tạo một Bộ lọc đã lưu mới.",
        "rcfilters-restore-default-filters": "Mặc định lại các bộ lọc",
        "rcfilters-clear-all-filters": "Xóa sạch các bộ lọc",
-       "rcfilters-show-new-changes": "Xem các thay đổi mới nhất",
+       "rcfilters-show-new-changes": "Xem các thay đổi mới từ $1 trở về sau",
        "rcfilters-search-placeholder": "Lọc các thay đổi gần đây (sử dụng trình đơn hoặc tìm tên bộ lọc)",
        "rcfilters-invalid-filter": "Bộ lọc không hợp lệ",
        "rcfilters-empty-filter": "Không có bộ lọc hiện hành. Tất cả các đóng góp được hiển thị.",
        "delete-confirm": "Xóa “$1”",
        "delete-legend": "Xóa",
        "historywarning": "<strong>Cảnh báo:</strong> Trang bạn sắp xóa đã có lịch sử $1 phiên bản:",
-       "historyaction-submit": "Xem",
+       "historyaction-submit": "Xem các phiên bản",
        "confirmdeletetext": "Bạn đang chuẩn bị xóa một trang cùng với tất cả lịch sử của nó.\nXin xác nhận việc bạn định làm, và hiểu rõ những hệ lụy của nó, và bạn thực hiện nó theo đúng đúng [[{{MediaWiki:Policy-url}}|quy định]].",
        "actioncomplete": "Đã thực hiện xong",
        "actionfailed": "Tác động bị thất bại",
        "deleting-backlinks-warning": "<strong>Cảnh báo:</strong> Có [[Special:WhatLinksHere/{{FULLPAGENAME}}|trang khác]] liên kết đến hoặc nhúng trang mà bạn sắp xóa.",
        "deleting-subpages-warning": "<strong>Cảnh báo:</strong> Bạn sắp sửa xóa trang có [[Special:PrefixIndex/{{FULLPAGENAME}}/|{{PLURAL:$1|trang con|$1 trang con|51=hơn 50 trang con}}]].",
        "rollback": "Lùi tất cả sửa đổi",
+       "rollback-confirmation-confirm": "Xin hãy xác nhận:",
+       "rollback-confirmation-yes": "Lùi hàng loạt",
+       "rollback-confirmation-no": "Hủy bỏ",
        "rollbacklink": "lùi tất cả",
        "rollbacklinkcount": "lùi tất cả $1 sửa đổi",
        "rollbacklinkcount-morethan": "lùi tất cả hơn $1 sửa đổi",
        "mycontris": "Đóng góp",
        "anoncontribs": "Đóng góp",
        "contribsub2": "Của {{GENDER:$3}}$1 ($2)",
+       "contributions-subtitle": "Của {{GENDER:$3}}$1",
        "contributions-userdoesnotexist": "Chưa có tài khoản với tên “$1”.",
        "negative-namespace-not-supported": "Không gian tên với giá trị âm không được hỗ trợ.",
        "nocontribs": "Không tìm thấy thay đổi nào khớp với yêu cầu.",
        "ipb-confirm": "Xác nhận cấm",
        "ipb-sitewide": "Toàn website",
        "ipb-partial": "Một phần",
+       "ipb-sitewide-help": "Tất cả các trang tại wiki và tất cả các tác vụ đóng góp khác.",
+       "ipb-partial-help": "Các trang hoặc không gian tên cụ thể.",
        "ipb-pages-label": "Các trang",
        "ipb-namespaces-label": "Không gian tên",
        "badipaddress": "Địa chỉ IP không hợp lệ",
        "blocklist-userblocks": "Ẩn tác vụ cấm tài khoản",
        "blocklist-tempblocks": "Ẩn tác vụ cấm có thời hạn",
        "blocklist-addressblocks": "Ẩn tác vụ cấm địa chỉ IP dứt khoát",
+       "blocklist-type": "Kiểu:",
+       "blocklist-type-opt-all": "Tất cả",
+       "blocklist-type-opt-sitewide": "Toàn trang",
+       "blocklist-type-opt-partial": "Một phần",
        "blocklist-rangeblocks": "Ẩn tác vụ cấm hàng loạt",
        "blocklist-timestamp": "Thời gian",
        "blocklist-target": "Người dùng",
        "blocklist-editing-page": "trang",
        "blocklist-editing-ns": "không gian tên",
        "ipblocklist-empty": "Danh sách cấm hiện đang trống.",
-       "ipblocklist-no-results": "Địa chỉ IP hoặc tên thành viên này hiện không bị cấm.",
+       "ipblocklist-no-results": "Không tìm thấy tác vụ cấm trùng khớp với địa chỉ IP hoặc tên thành viên được yêu cầu.",
        "blocklink": "cấm",
        "unblocklink": "bỏ cấm",
        "change-blocklink": "đổi mức cấm",
+       "empty-username": "(tên người dùng không có sẵn)",
        "contribslink": "đóng góp",
        "emaillink": "gửi thư điện tử",
        "autoblocker": "Bạn bị tự động cấm vì địa chỉ IP của bạn vừa rồi đã được “[[User:$1|$1]]” sử dụng. Lý do đưa ra cho việc cấm $1 là ”$2”",
        "confirm-unwatch-top": "Bạn có muốn gỡ trang này khỏi danh sách theo dõi của bạn?",
        "confirm-rollback-button": "OK",
        "confirm-rollback-top": "Có muốn lùi lại các sửa đổi trong trang này?",
+       "confirm-rollback-bottom": "Điều này sẽ lùi lại các sửa đổi được chọn tại trang này ngay lập tức.",
        "confirm-mcrrestore-title": "Phục hồi phiên bản",
        "confirm-mcrundo-title": "Lùi thay đổi",
        "mcrundofailed": "Lùi sửa bị thất bại",
        "logentry-rights-autopromote": "$1 {{GENDER:$2}}đã được tự động phong cấp từ $4 đến $5",
        "logentry-upload-upload": "$1 {{GENDER:$2}}đã tải lên $3",
        "logentry-upload-overwrite": "$1 {{GENDER:$2}}đã tải lên một phiên bản mới của $3",
-       "logentry-upload-revert": "$1 {{GENDER:$2}}đã tải lên $3",
+       "logentry-upload-revert": "$1 {{GENDER:$2}}đã phục hồi một phiên bản cũ của $3",
        "log-name-managetags": "Danh sách quản lý thẻ",
        "log-description-managetags": "Trang này có các công việc quản lý [[Special:Tags|thẻ]]. Nhật trình chỉ bao gồm các tác vụ do bảo quản viên thực hiện thủ công; phần mềm wiki có thể tạo hoặc xóa thẻ mà không ghi tác vụ vào nhật trình này.",
        "logentry-managetags-create": "$1 {{GENDER:$2}}đã tạo thẻ “$4”",
        "passwordpolicies-policy-maximalpasswordlength": "Mật khẩu không thể vượt quá $1 ký tự",
        "passwordpolicies-policy-passwordcannotbepopular": "Mật khẩu không thể {{PLURAL:$1|là mật khẩu phổ biến nhất|xuất hiện trong danh sách $1 mật khẩu phổ biến nhất}}",
        "passwordpolicies-policy-passwordnotinlargeblacklist": "Mật khẩu không được nằm tròn danh sách 100.000 mật khẩu phổ biến nhất.",
+       "passwordpolicies-policyflag-forcechange": "phải thay khi đăng nhập",
+       "passwordpolicies-policyflag-suggestchangeonlogin": "khuyên thay khi đăng nhập",
        "easydeflate-invaliddeflate": "Nội dung được cung cấp không được giải nén đúng cách",
-       "unprotected-js": "Vì lý do an toàn JavaScript sẽ không được tải tại các trang không được khóa. Xin vui lòng chỉ tạo javascript tại không gian tên MediaWiki: hoặc tại trang con của trang Thành viên"
+       "unprotected-js": "Vì lý do an toàn JavaScript sẽ không được tải tại các trang không được khóa. Xin vui lòng chỉ tạo javascript tại không gian tên MediaWiki: hoặc tại trang con của trang Thành viên",
+       "userlogout-continue": "Nếu bạn muốn đăng xuất, xin hãy [$1 mở trang đăng xuất].",
+       "userlogout-sessionerror": "Thất bại khi đăng xuất vì lỗi phiên làm việc. Xin hãy [$1 thử lại]."
 }
index 7ff7c11..b926454 100644 (file)
@@ -4,7 +4,13 @@
 
 /* Table Sorting */
 
-.client-js .sortable:not( .jquery-tablesorter ) > thead > :last-of-type > th:not( .unsortable ),
+// Reserve space for table sortable controls
+// This selector is not perfect as it will not correctly handle cases with
+// merged header cells, so ensure it is removed after the JS has run by using
+// the :not( .jquery-tablesorter ) selector.
+// It will still prevent a visible jump in the majority of simpler cases.
+// The second selector in this rule is for after the JS has run.
+.client-js .sortable:not( .jquery-tablesorter ) > * > tr:first-child > th:not( .unsortable ),
 .jquery-tablesorter th.headerSort {
        .background-image-svg( 'images/sort_both.svg', 'images/sort_both.png' );
        cursor: pointer;
index 999813f..486b16d 100644 (file)
@@ -954,6 +954,8 @@ abstract class MediaWikiTestCase extends PHPUnit\Framework\TestCase {
                        $newInstance->redefineService( $name, $callback );
                }
 
+               self::resetGlobalParser();
+
                return $newInstance;
        }
 
@@ -1018,6 +1020,9 @@ abstract class MediaWikiTestCase extends PHPUnit\Framework\TestCase {
                );
 
                MediaWikiServices::forceGlobalInstance( $newServices );
+
+               self::resetGlobalParser();
+
                return $newServices;
        }
 
@@ -1046,9 +1051,26 @@ abstract class MediaWikiTestCase extends PHPUnit\Framework\TestCase {
                MediaWikiServices::forceGlobalInstance( self::$originalServices );
                $currentServices->destroy();
 
+               self::resetGlobalParser();
+
                return true;
        }
 
+       /**
+        * If $wgParser has been unstubbed, replace it with a fresh one so it picks up any config
+        * changes. $wgParser is deprecated, but we still support it for now.
+        */
+       private static function resetGlobalParser() {
+               // phpcs:ignore MediaWiki.Usage.DeprecatedGlobalVariables.Deprecated$wgParser
+               global $wgParser;
+               if ( $wgParser instanceof StubObject ) {
+                       return;
+               }
+               $wgParser = new StubObject( 'wgParser', function () {
+                       return MediaWikiServices::getInstance()->getParser();
+               } );
+       }
+
        /**
         * @since 1.27
         * @param string|Language $lang
index f5fef61..d2540f6 100644 (file)
@@ -693,14 +693,6 @@ hello
         * @covers EditPage
         */
        public function testCheckDirectEditingDisallowed_forNonTextContent() {
-               $title = Title::newFromText( 'Dummy:NonTextPageForEditPage' );
-               $page = WikiPage::factory( $title );
-
-               $article = new Article( $title );
-               $article->getContext()->setTitle( $title );
-               $ep = new EditPage( $article );
-               $ep->setContextTitle( $title );
-
                $user = $GLOBALS['wgUser'];
 
                $edit = [
@@ -711,15 +703,79 @@ hello
                        'wpUnicodeCheck' => EditPage::UNICODE_CHECK,
                ];
 
-               $req = new FauxRequest( $edit, true );
-               $ep->importFormData( $req );
-
                $this->setExpectedException(
                        MWException::class,
                        'This content model is not supported: testing'
                );
 
-               $ep->internalAttemptSave( $result, false );
+               $this->doEditDummyNonTextPage( $edit );
+       }
+
+       /** @covers EditPage */
+       public function testShouldPreventChangingContentModelWhenUserCannotChangeModelForTitle() {
+               $this->setTemporaryHook( 'getUserPermissionsErrors',
+                       function ( Title $page, $user, $action, &$result ) {
+                               if ( $action === 'editcontentmodel' &&
+                                        $page->getContentModel() === CONTENT_MODEL_WIKITEXT ) {
+                                       $result = false;
+
+                                       return false;
+                               }
+                       } );
+
+               $user = $GLOBALS['wgUser'];
+
+               $status = $this->doEditDummyNonTextPage( [
+                       'wpTextbox1' => 'some text',
+                       'wpEditToken' => $user->getEditToken(),
+                       'wpEdittime' => '',
+                       'wpStarttime' => wfTimestampNow(),
+                       'wpUnicodeCheck' => EditPage::UNICODE_CHECK,
+                       'model' => CONTENT_MODEL_WIKITEXT,
+                       'format' => CONTENT_FORMAT_WIKITEXT,
+               ] );
+
+               $this->assertFalse( $status->isOK() );
+               $this->assertEquals( EditPage::AS_NO_CHANGE_CONTENT_MODEL, $status->getValue() );
        }
 
+       /** @covers EditPage */
+       public function testShouldPreventChangingContentModelWhenUserCannotEditTargetTitle() {
+               $this->setTemporaryHook( 'getUserPermissionsErrors',
+                       function ( Title $page, $user, $action, &$result ) {
+                               if ( $action === 'edit' && $page->getContentModel() === CONTENT_MODEL_WIKITEXT ) {
+                                       $result = false;
+                                       return false;
+                               }
+                       } );
+
+               $user = $GLOBALS['wgUser'];
+
+               $status = $this->doEditDummyNonTextPage( [
+                       'wpTextbox1' => 'some text',
+                       'wpEditToken' => $user->getEditToken(),
+                       'wpEdittime' => '',
+                       'wpStarttime' => wfTimestampNow(),
+                       'wpUnicodeCheck' => EditPage::UNICODE_CHECK,
+                       'model' => CONTENT_MODEL_WIKITEXT,
+                       'format' => CONTENT_FORMAT_WIKITEXT,
+               ] );
+
+               $this->assertFalse( $status->isOK() );
+               $this->assertEquals( EditPage::AS_NO_CHANGE_CONTENT_MODEL, $status->getValue() );
+       }
+
+       private function doEditDummyNonTextPage( array $edit ): Status {
+               $title = Title::newFromText( 'Dummy:NonTextPageForEditPage' );
+
+               $article = new Article( $title );
+               $article->getContext()->setTitle( $title );
+               $ep = new EditPage( $article );
+               $ep->setContextTitle( $title );
+
+               $req = new FauxRequest( $edit, true );
+               $ep->importFormData( $req );
+
+               return $ep->internalAttemptSave( $result, false );
+       }
 }
index e08efac..c523561 100644 (file)
@@ -84,7 +84,6 @@ class TextSlotDiffRendererTest extends MediaWikiTestCase {
                $slotDiffRenderer = new TextSlotDiffRenderer();
                $slotDiffRenderer->setStatsdDataFactory( new NullStatsdDataFactory() );
                $slotDiffRenderer->setLanguage( Language::factory( 'en' ) );
-               $slotDiffRenderer->setWikiDiff2MovedParagraphDetectionCutoff( 0 );
                $slotDiffRenderer->setEngine( TextSlotDiffRenderer::ENGINE_PHP );
                return $slotDiffRenderer;
        }
index 66754fc..dfbca70 100644 (file)
@@ -28,9 +28,10 @@ class RESTBagOStuffTest extends MediaWikiTestCase {
        public function testGet() {
                $this->client->expects( $this->once() )->method( 'run' )->with( [
                        'method' => 'GET',
-                       'url' => 'http://test/rest/42xyz42'
+                       'url' => 'http://test/rest/42xyz42',
+                       'headers' => []
                        // list( $rcode, $rdesc, $rhdrs, $rbody, $rerr )
-               ] )->willReturn( [ 200, 'OK', [], 's:8:"somedata";', 0 ] );
+               ] )->willReturn( [ 200, 'OK', [], '"somedata"', 0 ] );
                $result = $this->bag->get( '42xyz42' );
                $this->assertEquals( 'somedata', $result );
        }
@@ -38,7 +39,8 @@ class RESTBagOStuffTest extends MediaWikiTestCase {
        public function testGetNotExist() {
                $this->client->expects( $this->once() )->method( 'run' )->with( [
                        'method' => 'GET',
-                       'url' => 'http://test/rest/42xyz42'
+                       'url' => 'http://test/rest/42xyz42',
+                       'headers' => []
                        // list( $rcode, $rdesc, $rhdrs, $rbody, $rerr )
                ] )->willReturn( [ 404, 'Not found', [], 'Nothing to see here', 0 ] );
                $result = $this->bag->get( '42xyz42' );
@@ -48,7 +50,8 @@ class RESTBagOStuffTest extends MediaWikiTestCase {
        public function testGetBadClient() {
                $this->client->expects( $this->once() )->method( 'run' )->with( [
                        'method' => 'GET',
-                       'url' => 'http://test/rest/42xyz42'
+                       'url' => 'http://test/rest/42xyz42',
+                       'headers' => []
                        // list( $rcode, $rdesc, $rhdrs, $rbody, $rerr )
                ] )->willReturn( [ 0, '', [], '', 'cURL has failed you today' ] );
                $result = $this->bag->get( '42xyz42' );
@@ -59,7 +62,8 @@ class RESTBagOStuffTest extends MediaWikiTestCase {
        public function testGetBadServer() {
                $this->client->expects( $this->once() )->method( 'run' )->with( [
                        'method' => 'GET',
-                       'url' => 'http://test/rest/42xyz42'
+                       'url' => 'http://test/rest/42xyz42',
+                       'headers' => []
                        // list( $rcode, $rdesc, $rhdrs, $rbody, $rerr )
                ] )->willReturn( [ 500, 'Too busy', [], 'Server is too busy', '' ] );
                $result = $this->bag->get( '42xyz42' );
@@ -71,7 +75,8 @@ class RESTBagOStuffTest extends MediaWikiTestCase {
                $this->client->expects( $this->once() )->method( 'run' )->with( [
                        'method' => 'PUT',
                        'url' => 'http://test/rest/42xyz42',
-                       'body' => 's:8:"postdata";'
+                       'body' => '"postdata"',
+                       'headers' => []
                        // list( $rcode, $rdesc, $rhdrs, $rbody, $rerr )
                ] )->willReturn( [ 200, 'OK', [], 'Done', 0 ] );
                $result = $this->bag->set( '42xyz42', 'postdata' );
@@ -82,6 +87,7 @@ class RESTBagOStuffTest extends MediaWikiTestCase {
                $this->client->expects( $this->once() )->method( 'run' )->with( [
                        'method' => 'DELETE',
                        'url' => 'http://test/rest/42xyz42',
+                       'headers' => []
                        // list( $rcode, $rdesc, $rhdrs, $rbody, $rerr )
                ] )->willReturn( [ 200, 'OK', [], 'Done', 0 ] );
                $result = $this->bag->delete( '42xyz42' );
index f37bdfc..048256d 100644 (file)
@@ -22,9 +22,11 @@ class ParserFactoryTest extends MediaWikiTestCase {
        public function testAllArgumentsWerePassed() {
                $factoryConstructor = new ReflectionMethod( 'ParserFactory', '__construct' );
                $mocks = [];
-               foreach ( $factoryConstructor->getParameters() as $param ) {
+               foreach ( $factoryConstructor->getParameters() as $index => $param ) {
                        $type = (string)$param->getType();
-                       if ( $type === 'array' ) {
+                       if ( $index === 0 ) {
+                               $val = $this->createMock( 'MediaWiki\Config\ServiceOptions' );
+                       } elseif ( $type === 'array' ) {
                                $val = [ 'porcupines will tell me your secrets' . count( $mocks ) ];
                        } elseif ( class_exists( $type ) || interface_exists( $type ) ) {
                                $val = $this->createMock( $type );
@@ -52,4 +54,54 @@ class ParserFactoryTest extends MediaWikiTestCase {
                $this->assertCount( 0, $mocks, 'Not all arguments to the ParserFactory constructor were ' .
                        'found in Parser member variables' );
        }
+
+       public function provideConstructorArguments() {
+               // Create a mock Config object that will satisfy ServiceOptions::__construct
+               $mockConfig = $this->createMock( 'Config' );
+               $mockConfig->method( 'has' )->willReturn( true );
+               $mockConfig->method( 'get' )->willReturn( 'I like otters.' );
+
+               $mocks = [
+                       [ 'the plural of platypus...' ],
+                       $this->createMock( 'MagicWordFactory' ),
+                       $this->createMock( 'Language' ),
+                       '...is platypodes',
+                       $this->createMock( 'MediaWiki\Special\SpecialPageFactory' ),
+                       $mockConfig,
+                       $this->createMock( 'MediaWiki\Linker\LinkRendererFactory' ),
+               ];
+
+               yield 'args_without_namespace_info' => [
+                       $mocks,
+               ];
+               yield 'args_with_namespace_info' => [
+                       array_merge( $mocks, [ $this->createMock( 'NamespaceInfo' ) ] ),
+               ];
+       }
+
+       /**
+        * @dataProvider provideConstructorArguments
+        * @covers ParserFactory::__construct
+        */
+       public function testBackwardsCompatibleConstructorArguments( $args ) {
+               $this->hideDeprecated( 'ParserFactory::__construct with Config parameter' );
+               $factory = new ParserFactory( ...$args );
+               $parser = $factory->create();
+
+               // It is expected that these are not present on the parser.
+               unset( $args[5] );
+               unset( $args[0] );
+
+               foreach ( ( new ReflectionObject( $parser ) )->getProperties() as $prop ) {
+                       $prop->setAccessible( true );
+                       foreach ( $args as $idx => $mockTest ) {
+                               if ( $prop->getValue( $parser ) === $mockTest ) {
+                                       unset( $args[$idx] );
+                               }
+                       }
+               }
+
+               $this->assertCount( 0, $args, 'Not all arguments to the ParserFactory constructor were ' .
+                       'found in Parser member variables' );
+       }
 }
diff --git a/tests/phpunit/includes/parser/ParserTest.php b/tests/phpunit/includes/parser/ParserTest.php
new file mode 100644 (file)
index 0000000..19341f5
--- /dev/null
@@ -0,0 +1,98 @@
+<?php
+
+/**
+ * @covers Parser::__construct
+ */
+class ParserTest extends MediaWikiTestCase {
+       public function provideConstructorArguments() {
+               // Create a mock Config object that will satisfy ServiceOptions::__construct
+               $mockConfig = $this->createMock( 'Config' );
+               $mockConfig->method( 'has' )->willReturn( true );
+               $mockConfig->method( 'get' )->willReturn( 'I like otters.' );
+
+               $newArgs = [
+                       $this->createMock( 'MediaWiki\Config\ServiceOptions' ),
+                       $this->createMock( 'MagicWordFactory' ),
+                       $this->createMock( 'Language' ),
+                       $this->createMock( 'ParserFactory' ),
+                       'a snail can sleep for three years',
+                       $this->createMock( 'MediaWiki\Special\SpecialPageFactory' ),
+                       $this->createMock( 'MediaWiki\Linker\LinkRendererFactory' ),
+                       $this->createMock( 'NamespaceInfo' )
+               ];
+
+               $oldArgs = [
+                       [],
+                       $this->createMock( 'MagicWordFactory' ),
+                       $this->createMock( 'Language' ),
+                       $this->createMock( 'ParserFactory' ),
+                       'a snail can sleep for three years',
+                       $this->createMock( 'MediaWiki\Special\SpecialPageFactory' )
+               ];
+
+               yield 'current_args_without_namespace_info' => [
+                       $newArgs,
+               ];
+
+               yield 'backward_compatible_args_minimal' => [
+                       array_merge( $oldArgs ),
+               ];
+
+               yield 'backward_compatible_args_with_config' => [
+                       array_merge( $oldArgs, [ $mockConfig ] ),
+               ];
+
+               yield 'backward_compatible_args_with_link_renderer' => [
+                       array_merge( $oldArgs, [
+                               $mockConfig,
+                               $this->createMock( 'MediaWiki\Linker\LinkRendererFactory' )
+                       ] ),
+               ];
+
+               yield 'backward_compatible_args_with_ns_info' => [
+                       array_merge( $oldArgs, [
+                               $mockConfig,
+                               $this->createMock( 'MediaWiki\Linker\LinkRendererFactory' ),
+                               $this->createMock( 'NamespaceInfo' )
+                       ] ),
+               ];
+       }
+
+       /**
+        * @dataProvider provideConstructorArguments
+        * @covers Parser::__construct
+        */
+       public function testBackwardsCompatibleConstructorArguments( $args ) {
+               $parser = new Parser( ...$args );
+
+               $refObject = new ReflectionObject( $parser );
+
+               // If testing backwards compatibility, test service options separately
+               if ( is_array( $args[0] ) ) {
+                       $svcOptionsProp = $refObject->getProperty( 'svcOptions' );
+                       $svcOptionsProp->setAccessible( true );
+                       $this->assertType( 'MediaWiki\Config\ServiceOptions',
+                               $svcOptionsProp->getValue( $parser )
+                       );
+                       unset( $args[0] );
+
+                       // If a Config is passed, the fact that we were able to create a ServiceOptions
+                       // instance without error from it proves that this argument works.
+                       if ( isset( $args[6] ) ) {
+                               unset( $args[6] );
+                       }
+               }
+
+               foreach ( $refObject->getProperties() as $prop ) {
+                       $prop->setAccessible( true );
+                       foreach ( $args as $idx => $mockTest ) {
+                               if ( $prop->getValue( $parser ) === $mockTest ) {
+                                       unset( $args[$idx] );
+                               }
+                       }
+               }
+
+               $this->assertCount( 0, $args, 'Not all arguments to the Parser constructor were ' .
+                       'found on the Parser object' );
+       }
+}
index 4e376e8..b1262a3 100644 (file)
@@ -1300,11 +1300,7 @@ class NamespaceInfoTest extends MediaWikiTestCase {
                        'No namespace restriction' => [ [ '', 'autoconfirmed', 'sysop' ], NS_TALK ],
                        'Restricted to autoconfirmed' => [ [ '', 'sysop' ], NS_MAIN ],
                        'Restricted to sysop' => [ [ '' ], NS_USER ],
-                       // @todo Bug -- 'sysop' protection should be allowed in this case. Someone who's
-                       // autoconfirmed and also privileged can edit this namespace, and would be blocked by
-                       // the sysop protection.
-                       'Restricted to someone in two groups' => [ [ '' ], 101 ],
-
+                       'Restricted to someone in two groups' => [ [ '', 'sysop' ], 101 ],
                        'No special permissions' => [ [ '' ], NS_TALK, $this->getMockUser() ],
                        'autoconfirmed' => [
                                [ '', 'autoconfirmed' ],
index 5b4a9d5..56e4934 100644 (file)
@@ -65,6 +65,8 @@ exports.config = {
        // Patterns to exclude
        exclude: [
                relPath( './extensions/CirrusSearch/tests/selenium/specs/**/*.js' ),
+               // Disabled because these tests modify LocalSettings.php, see T199116 for the long-term fix.
+               relPath( './extensions/FileImporter/tests/selenium/specs/**/*.js' ),
                // Disabled per T222517
                relPath( './skins/MinervaNeue/tests/selenium/specs/**/*.js' )
        ],