Merge "mediawiki.filewarning: Use 'visibility: hidden' instead of 'display: none'"
authorjenkins-bot <jenkins-bot@gerrit.wikimedia.org>
Sat, 1 Aug 2015 00:00:38 +0000 (00:00 +0000)
committerGerrit Code Review <gerrit@wikimedia.org>
Sat, 1 Aug 2015 00:00:38 +0000 (00:00 +0000)
41 files changed:
autoload.php
composer.json
includes/OutputPage.php
includes/ProtectionForm.php
includes/XmlSelect.php
includes/api/i18n/uk.json
includes/api/i18n/zh-hans.json
includes/clientpool/RedisConnectionPool.php
includes/debug/logger/LegacyLogger.php
includes/debug/logger/monolog/LineFormatter.php [new file with mode: 0644]
includes/filebackend/SwiftFileBackend.php
includes/installer/i18n/ia.json
includes/installer/i18n/uk.json
includes/objectcache/ObjectCacheSessionHandler.php
includes/objectcache/RedisBagOStuff.php
includes/resourceloader/ResourceLoader.php
includes/specials/SpecialMIMEsearch.php
includes/specials/SpecialSearch.php
includes/utils/IP.php
languages/i18n/cv.json
languages/i18n/en.json
languages/i18n/fr.json
languages/i18n/gom-deva.json
languages/i18n/ja.json
languages/i18n/lb.json
languages/i18n/lrc.json
languages/i18n/nl.json
languages/i18n/pl.json
languages/i18n/qqq.json
languages/i18n/scn.json
languages/i18n/sl.json
languages/i18n/uk.json
resources/Resources.php
resources/src/mediawiki.legacy/shared.css
resources/src/mediawiki.widgets/mw.widgets.CalendarWidget.less
resources/src/mediawiki.widgets/mw.widgets.DateInputWidget.js
resources/src/mediawiki.widgets/mw.widgets.DateInputWidget.less
tests/phpunit/LessFileCompilationTest.php
tests/phpunit/includes/OutputPageTest.php
tests/phpunit/includes/debug/logger/monolog/LineFormatterTest.php [new file with mode: 0644]
tests/phpunit/includes/filebackend/SwiftFileBackendTest.php [new file with mode: 0644]

index a8940c4..911c7c8 100644 (file)
@@ -752,6 +752,7 @@ $wgAutoloadLocalClasses = array(
        'MediaWiki\\Logger\\MonologSpi' => __DIR__ . '/includes/debug/logger/MonologSpi.php',
        'MediaWiki\\Logger\\Monolog\\LegacyFormatter' => __DIR__ . '/includes/debug/logger/monolog/LegacyFormatter.php',
        'MediaWiki\\Logger\\Monolog\\LegacyHandler' => __DIR__ . '/includes/debug/logger/monolog/LegacyHandler.php',
+       'MediaWiki\\Logger\\Monolog\\LineFormatter' => __DIR__ . '/includes/debug/logger/monolog/LineFormatter.php',
        'MediaWiki\\Logger\\Monolog\\SyslogHandler' => __DIR__ . '/includes/debug/logger/monolog/SyslogHandler.php',
        'MediaWiki\\Logger\\Monolog\\WikiProcessor' => __DIR__ . '/includes/debug/logger/monolog/WikiProcessor.php',
        'MediaWiki\\Logger\\NullSpi' => __DIR__ . '/includes/debug/logger/NullSpi.php',
index 3d8707d..9095355 100644 (file)
@@ -28,6 +28,7 @@
                "wikimedia/assert": "0.2.2",
                "wikimedia/composer-merge-plugin": "1.2.1",
                "wikimedia/utfnormal": "1.0.2",
+               "wikimedia/wrappedstring": "2.0.0",
                "zordius/lightncandy": "0.21"
        },
        "require-dev": {
index f9f2470..c972045 100644 (file)
@@ -21,6 +21,7 @@
  */
 
 use MediaWiki\Logger\LoggerFactory;
+use WrappedString\WrappedString;
 
 /**
  * This class should be covered by a general architecture document which does
@@ -2778,7 +2779,9 @@ class OutputPage extends ContextSource {
                $modules = (array)$modules;
 
                $links = array(
-                       'html' => '',
+                       // List of html strings
+                       'html' => array(),
+                       // Associative array of module names and their states
                        'states' => array(),
                );
 
@@ -2796,7 +2799,7 @@ class OutputPage extends ContextSource {
                                // Recursively call us for every item
                                foreach ( $modules as $name ) {
                                        $link = $this->makeResourceLoaderLink( $name, $only, $useESI );
-                                       $links['html'] .= $link['html'];
+                                       $links['html'] = array_merge( $links['html'], $link['html'] );
                                        $links['states'] += $link['states'];
                                }
                                return $links;
@@ -2880,15 +2883,14 @@ class OutputPage extends ContextSource {
                                // properly use them as dependencies (bug 30914)
                                if ( $group === 'private' ) {
                                        if ( $only == ResourceLoaderModule::TYPE_STYLES ) {
-                                               $links['html'] .= Html::inlineStyle(
+                                               $links['html'][] = Html::inlineStyle(
                                                        $resourceLoader->makeModuleResponse( $context, $grpModules )
                                                );
                                        } else {
-                                               $links['html'] .= ResourceLoader::makeInlineScript(
+                                               $links['html'][] = ResourceLoader::makeInlineScript(
                                                        $resourceLoader->makeModuleResponse( $context, $grpModules )
                                                );
                                        }
-                                       $links['html'] .= "\n";
                                        continue;
                                }
 
@@ -2945,9 +2947,9 @@ class OutputPage extends ContextSource {
                                }
 
                                if ( $group == 'noscript' ) {
-                                       $links['html'] .= Html::rawElement( 'noscript', array(), $link ) . "\n";
+                                       $links['html'][] = Html::rawElement( 'noscript', array(), $link );
                                } else {
-                                       $links['html'] .= $link . "\n";
+                                       $links['html'][] = $link;
                                }
                        }
                }
@@ -2961,24 +2963,26 @@ class OutputPage extends ContextSource {
         * @return string HTML
         */
        protected static function getHtmlFromLoaderLinks( array $links ) {
-               $html = '';
+               $html = array();
                $states = array();
                foreach ( $links as $link ) {
                        if ( !is_array( $link ) ) {
-                               $html .= $link;
+                               $html[] = $link;
                        } else {
-                               $html .= $link['html'];
+                               $html = array_merge( $html, $link['html'] );
                                $states += $link['states'];
                        }
                }
+               // Filter out empty values
+               $html = array_filter( $html, 'strlen' );
 
                if ( count( $states ) ) {
-                       $html = ResourceLoader::makeInlineScript(
+                       array_unshift( $html, ResourceLoader::makeInlineScript(
                                ResourceLoader::makeLoaderStateScript( $states )
-                       ) . "\n" . $html;
+                       ) );
                }
 
-               return $html;
+               return WrappedString::join( "\n", $html );
        }
 
        /**
@@ -3063,7 +3067,7 @@ class OutputPage extends ContextSource {
                }
 
                // Legacy Scripts
-               $links[] = "\n" . $this->mScripts;
+               $links[] = $this->mScripts;
 
                // Add user JS if enabled
                // This must use TYPE_COMBINED instead of only=scripts so that its request is handled by
@@ -3651,7 +3655,7 @@ class OutputPage extends ContextSource {
                        'noscript' => array()
                );
                $links = array();
-               $otherTags = ''; // Tags to append after the normal <link> tags
+               $otherTags = array(); // Tags to append after the normal <link> tags
                $resourceLoader = $this->getResourceLoader();
 
                $moduleStyles = $this->getModuleStyles( true, 'top' );
@@ -3670,7 +3674,7 @@ class OutputPage extends ContextSource {
                        $link = $this->makeResourceLoaderLink( 'user', ResourceLoaderModule::TYPE_STYLES, false,
                                array( 'excludepage' => $this->getTitle()->getPrefixedDBkey() )
                        );
-                       $otherTags .= $link['html'];
+                       $otherTags = array_merge( $otherTags, $link['html'] );
 
                        // Load the previewed CSS
                        // If needed, Janus it first. This is user-supplied CSS, so it's
@@ -3679,7 +3683,7 @@ class OutputPage extends ContextSource {
                        if ( $this->getLanguage()->getDir() !== $wgContLang->getDir() ) {
                                $previewedCSS = CSSJanus::transform( $previewedCSS, true, false );
                        }
-                       $otherTags .= Html::inlineStyle( $previewedCSS ) . "\n";
+                       $otherTags[] = Html::inlineStyle( $previewedCSS ) . "\n";
                } else {
                        // Load the user styles normally
                        $moduleStyles[] = 'user';
@@ -3720,7 +3724,7 @@ class OutputPage extends ContextSource {
                $links[] = Html::element(
                        'meta',
                        array( 'name' => 'ResourceLoaderDynamicStyles', 'content' => '' )
-               ) . "\n";
+               );
 
                // Add site-specific and user-specific styles
                // 'private' at present only contains user.options, so put that before 'user'
@@ -3732,7 +3736,7 @@ class OutputPage extends ContextSource {
                }
 
                // Add stuff in $otherTags (previewed user CSS if applicable)
-               return self::getHtmlFromLoaderLinks( $links ) . $otherTags;
+               return self::getHtmlFromLoaderLinks( $links ) . implode( '', $otherTags );
        }
 
        /**
index 1443d1c..4cad7b7 100644 (file)
@@ -384,7 +384,12 @@ class ProtectionForm {
                                "mwProtect-$action-expires"
                        );
 
-                       $expiryFormOptions = '';
+                       $expiryFormOptions = new XmlSelect( "wpProtectExpirySelection-$action", "mwProtectExpirySelection-$action", $this->mExpirySelection[$action] );
+                       $expiryFormOptions->setAttribute( 'tabindex', '2' );
+                       if ( $this->disabled ) {
+                               $expiryFormOptions->setAttribute( 'disabled', 'disabled' );
+                       }
+
                        if ( $this->mExistingExpiry[$action] ) {
                                if ( $this->mExistingExpiry[$action] == 'infinity' ) {
                                        $existingExpiryMessage = $context->msg( 'protect-existing-expiry-infinity' );
@@ -394,29 +399,17 @@ class ProtectionForm {
                                        $t = $lang->userTime( $this->mExistingExpiry[$action], $user );
                                        $existingExpiryMessage = $context->msg( 'protect-existing-expiry', $timestamp, $d, $t );
                                }
-                               $expiryFormOptions .=
-                                       Xml::option(
-                                               $existingExpiryMessage->text(),
-                                               'existing',
-                                               $this->mExpirySelection[$action] == 'existing'
-                                       ) . "\n";
+                               $expiryFormOptions->addOption( $existingExpiryMessage->text(), 'existing' );
                        }
 
-                       $expiryFormOptions .= Xml::option(
-                               $context->msg( 'protect-othertime-op' )->text(),
-                               "othertime"
-                       ) . "\n";
+                       $expiryFormOptions->addOption( $context->msg( 'protect-othertime-op' )->text(), 'othertime' );
                        foreach ( explode( ',', $scExpiryOptions ) as $option ) {
                                if ( strpos( $option, ":" ) === false ) {
                                        $show = $value = $option;
                                } else {
                                        list( $show, $value ) = explode( ":", $option );
                                }
-                               $expiryFormOptions .= Xml::option(
-                                       $show,
-                                       htmlspecialchars( $value ),
-                                       $this->mExpirySelection[$action] === $value
-                               ) . "\n";
+                               $expiryFormOptions->addOption( $show, htmlspecialchars( $value ) );
                        }
                        # Add expiry dropdown
                        if ( $showProtectOptions && !$this->disabled ) {
@@ -426,12 +419,7 @@ class ProtectionForm {
                                                        {$mProtectexpiry}
                                                </td>
                                                <td class='mw-input'>" .
-                                                       Xml::tags( 'select',
-                                                               array(
-                                                                       'id' => "mwProtectExpirySelection-$action",
-                                                                       'name' => "wpProtectExpirySelection-$action",
-                                                                       'tabindex' => '2' ) + $this->disabledAttrib,
-                                                               $expiryFormOptions ) .
+                                                       $expiryFormOptions->getHTML() .
                                                "</td>
                                        </tr></table>";
                        }
@@ -576,18 +564,18 @@ class ProtectionForm {
                );
 
                $id = 'mwProtect-level-' . $action;
-               $attribs = array(
-                       'id' => $id,
-                       'name' => $id,
-                       'size' => count( $levels ),
-               ) + $this->disabledAttrib;
 
-               $out = Xml::openElement( 'select', $attribs );
+               $select = new XmlSelect( $id, $id, $selected );
+               $select->setAttribute( 'size', count( $levels ) );
+               if ( $this->disabled ) {
+                       $select->setAttribute( 'disabled', 'disabled' );
+               }
+
                foreach ( $levels as $key ) {
-                       $out .= Xml::option( $this->getOptionLabel( $key ), $key, $key == $selected );
+                       $select->addOption( $this->getOptionLabel( $key ), $key );
                }
-               $out .= Xml::closeElement( 'select' );
-               return $out;
+
+               return $select->getHTML();
        }
 
        /**
index 1cd04ae..e765eed 100644 (file)
@@ -1,6 +1,6 @@
 <?php
 /**
- * Class to generate XML <select>.
+ * Class for generating HTML <select> elements.
  *
  * 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
@@ -21,7 +21,7 @@
  */
 
 /**
- * Module of static functions for generating XML <select> elements
+ * Class for generating HTML <select> elements.
  */
 class XmlSelect {
        protected $options = array();
@@ -51,7 +51,7 @@ class XmlSelect {
 
        /**
         * @param string $name
-        * @param array $value
+        * @param string $value
         */
        public function setAttribute( $name, $value ) {
                $this->attributes[$name] = $value;
@@ -59,7 +59,7 @@ class XmlSelect {
 
        /**
         * @param string $name
-        * @return array|null
+        * @return string|null
         */
        public function getAttribute( $name ) {
                if ( isset( $this->attributes[$name] ) ) {
@@ -70,14 +70,12 @@ class XmlSelect {
        }
 
        /**
-        * @param string $name
-        * @param bool $value
+        * @param string $label
+        * @param string $value If not given, assumed equal to $label
         */
-       public function addOption( $name, $value = false ) {
-               // Stab stab stab
-               $value = $value !== false ? $value : $name;
-
-               $this->options[] = array( $name => $value );
+       public function addOption( $label, $value = false ) {
+               $value = $value !== false ? $value : $label;
+               $this->options[] = array( $label => $value );
        }
 
        /**
@@ -92,12 +90,12 @@ class XmlSelect {
        }
 
        /**
-        * This accepts an array of form
+        * This accepts an array of form:
         * label => value
         * label => ( label => value, label => value )
         *
         * @param array $options
-        * @param bool $default
+        * @param string $default
         * @return string
         */
        static function formatOptions( $options, $default = false ) {
index 4e26ae3..11d27a4 100644 (file)
@@ -3,7 +3,8 @@
                "authors": [
                        "Ата",
                        "A1",
-                       "Ahonc"
+                       "Ahonc",
+                       "Base"
                ]
        },
        "apihelp-main-description": "<div class=\"hlist plainlinks api-main-links\">\n* [[mw:API:Main_page|Документація]]\n* [[mw:API:FAQ|FAQ]]\n* [https://lists.wikimedia.org/mailman/listinfo/mediawiki-api Список розсилки]\n* [https://lists.wikimedia.org/mailman/listinfo/mediawiki-api-announce Оголошення API]\n* [https://phabricator.wikimedia.org/maniphest/query/GebfyV4uCaLd/#R Баґи і запити]\n</div>\n<strong>Статус:</strong> Усі функції, вказані на цій сторінці, мають працювати, але API далі перебуває в активній розробці і може змінитися у будь-який момент. Підпишіться на [https://lists.wikimedia.org/pipermail/mediawiki-api-announce/ список розсилки mediawiki-api-announce], щоб помічати оновлення.\n\n<strong>Хибні запити:</strong> Коли до API надсилаються хибні запити, буде відіслано HTTP-шапку з ключем «MediaWiki-API-Error», а тоді і значення шапки, і код помилки, надіслані назад, будуть встановлені з тим же значенням. Більше інформації див. на [[mw:API:Errors_and_warnings|API: Errors and warnings]].",
        "apihelp-query+filerepoinfo-example-simple": "Отримати інформацію про репозиторії файлів.",
        "apihelp-query+fileusage-description": "Знайти всі сторінки, що використовують дані файли.",
        "apihelp-query+fileusage-param-prop": "Які властивості отримати:\n;pageid:ID кожної сторінки.\n;title:Назва кожної сторінки.\n;redirect:Помітка, якщо сторінка є перенаправленням.",
-       "apihelp-query+fileusage-param-namespace": "Включати сторінки лише в цьому просторі назв.",
+       "apihelp-query+fileusage-param-namespace": "Включати сторінки лише в цих просторах назв.",
        "apihelp-query+fileusage-param-limit": "Скільки результатів виводити.",
        "apihelp-query+fileusage-param-show": "Показати лише елементи, що відповідають цим критеріям:\n;redirect:Показати лише перенаправлення.\n;!redirect:Показати лише не перенаправлення.",
        "apihelp-query+fileusage-example-simple": "Отримати список сторінок, які використовують [[:File:Example.jpg]].",
        "apihelp-query+links-example-namespaces": "Отримати посилання зі сторінки <kbd>Main Page</kbd> у просторах назв {{ns:user}} і {{ns:template}}.",
        "apihelp-query+linkshere-description": "Знайти усі сторінки, що посилаються на подані сторінки.",
        "apihelp-query+linkshere-param-prop": "Які властивості отримати:\n;pageid:ID кожної сторінки.\n;title:Назва кожної сторінки.\n;redirect:Помітка, якщо сторінка є перенаправленням.",
-       "apihelp-query+linkshere-param-namespace": "Включати сторінки лише в цьому просторі назв.",
+       "apihelp-query+linkshere-param-namespace": "Включати сторінки лише в цих просторах назв.",
        "apihelp-query+linkshere-param-limit": "Скільки результатів виводити.",
        "apihelp-query+linkshere-param-show": "Показати лише елементи, що відповідають цим критеріям:\n;redirect:Показати лише перенаправлення.\n;!redirect:Показати лише не перенаправлення.",
        "apihelp-query+linkshere-example-simple": "Отримати список сторінок, що посилаються на [[Main Page]].",
        "apihelp-query+prefixsearch-param-offset": "Кількість результатів, які пропустити.",
        "apihelp-query+prefixsearch-example-simple": "Шукати назви сторінок, які починаються з <kbd>meaning</kbd>.",
        "apihelp-query+protectedtitles-description": "Вивести список усіх назв, захищених від створення.",
-       "apihelp-query+protectedtitles-param-namespace": "Перерахувати назви лише в цьому просторі назв.",
+       "apihelp-query+protectedtitles-param-namespace": "Перерахувати назви лише в цих просторах назв.",
        "apihelp-query+protectedtitles-param-level": "Перерахувати лише назви з цими рівням захисту.",
        "apihelp-query+protectedtitles-param-limit": "Скільки всього сторінок виводити.",
        "apihelp-query+protectedtitles-param-start": "Почати список з цієї часової мітки захисту.",
        "apihelp-query+recentchanges-param-excludeuser": "Не перераховувати зміни, зроблені цим користувачем.",
        "apihelp-query+recentchanges-param-tag": "Перерахувати лише зміни, помічені цим теґом.",
        "apihelp-query+recentchanges-param-prop": "Включити додаткові відомості:\n;user:Додає користувача, відповідального за редагування і мітки, якщо він IP.\n;userid:Додає ID користувача, відповідального за редагування.\n;comment:Додає коментар редагування.\n;parsedcomment:Додає проаналізований коментар редагування.\n;flags:Додає прапорці редагування.\n;timestamp:Додає часову мітку редагування.\n;title:Додає назву сторінки, де було редагування.\n;ids:Додає ID сторінки, ID нещодавніх змін, а також ID нової і старої версій.\n;sizes:Додає нову і стару довжину сторінки в байтах.\n;redirect:Помічає редагування, якщо сторінка є перенаправленням.\n;patrolled:Помічає редагування як відпатрульвані чи невідпатрульовані.\n;loginfo:Додає інформацію журналу (ID журналу, тип журналу тощо) до записів журналу.\n;tags:Виводить мітки запису.\n;sha1:Додає контрольну суму вмісту для записів, пов'язаних з версією.",
+       "apihelp-query+recentchanges-param-token": "Використати натомість <kbd>[[Special:ApiHelp/query+tokens|action=query&meta=tokens]]</kbd>.",
+       "apihelp-query+recentchanges-param-show": "Показати лише елементи, що задовільняють ці критерії. Наприклад, для перегляду лише незначних змін, здійснених користувачами, що увійшли до системи, вкажіть $1show=minor|!anon.",
+       "apihelp-query+recentchanges-param-limit": "Скільки всього змін виводити.",
+       "apihelp-query+recentchanges-param-type": "Які типи змін показувати.",
+       "apihelp-query+recentchanges-param-toponly": "Виводити лише зміни, які є останньою версією.",
+       "apihelp-query+recentchanges-example-simple": "Вивести нещодавні зміни.",
+       "apihelp-query+recentchanges-example-generator": "Отримати інформацію про сторінки з недавніми невідпатрульованими змінами.",
+       "apihelp-query+redirects-description": "Видає усі перенаправлення на дані сторінки.",
+       "apihelp-query+redirects-param-prop": "Які властивості отримати:\n;pageid:Ідентифікатор сторінки кожного перенаправлення.\n;title:Назва кожного перенаправлення.\n;fragment:Фрагмент кожного перенаправлення, якщо є.",
+       "apihelp-query+redirects-param-namespace": "Включити сторінки лише у цих просторах назв.",
+       "apihelp-query+redirects-param-limit": "Скільки перенаправлень повернути.",
        "api-help-datatypes-header": "Типи даних"
 }
index cc7260c..f97b83a 100644 (file)
        "apihelp-parse-paramvalue-prop-modules": "提供在页面中使用的ResourceLoader模块。无论<kbd>jsconfigvars</kbd>还是<kbd>encodedjsconfigvars</kbd>都必须与<kbd>modules</kbd>共同被请求。",
        "apihelp-parse-paramvalue-prop-jsconfigvars": "针对页面提供JavaScript配置变量。",
        "apihelp-parse-paramvalue-prop-encodedjsconfigvars": "针对页面提供JavaScript配置变量为一个JSON字符串。",
+       "apihelp-parse-paramvalue-prop-indicators": "提供页面上使用的页面状态指示器的HTML。",
        "apihelp-parse-paramvalue-prop-iwlinks": "在被解析的wiki文本中提供跨wiki链接。",
        "apihelp-parse-paramvalue-prop-wikitext": "提供被解析的原始wiki文本。",
        "apihelp-parse-paramvalue-prop-limitreportdata": "以结构化的方式提供限制报告。如果<var>$1disablepp</var>被设定则不提供数据。",
        "apihelp-query+pageprops-param-prop": "只列出这些组。在检查某一页面是否使用某一个页面属性时有用。",
        "apihelp-query+pageprops-example-simple": "获取用于页面<kbd>Main Page</kbd>和<kbd>MediaWiki</kbd>的属性。",
        "apihelp-query+pageswithprop-description": "列出所有使用指定页面属性的页面。",
+       "apihelp-query+pageswithprop-param-propname": "要用于列举页面的页面属性。",
        "apihelp-query+pageswithprop-param-prop": "要包含的信息束:\n;ids:添加页面ID。\n;title:添加页面的标题和名字空间ID。\n;value:添加页面属性值。",
        "apihelp-query+pageswithprop-param-limit": "返回页面的最大数量。",
        "apihelp-query+pageswithprop-param-dir": "排序的方向。",
        "apihelp-rollback-example-summary": "回退由IP用户<kbd>192.0.2.5</kbd>对页面<kbd>Main Page</kbd>做出的最近编辑,带编辑摘要<kbd>Reverting vandalism</kbd>,并将这些编辑和回退标记为机器人编辑。",
        "apihelp-rsd-description": "导出一个RSD(Really Simple Discovery)架构。",
        "apihelp-rsd-example-simple": "导出RSD架构。",
-       "apihelp-setnotificationtimestamp-description": "更新用于监视页面的通知时间戳。\n\n这会影响监视列表和历史中已更改页面的高亮度,并且如果“当我的监视列表中的页面被更改时发送电子邮件通知我”的设置被启用的话,也会影响电子邮件的发送。",
+       "apihelp-setnotificationtimestamp-description": "更新用于监视页面的通知时间戳。\n\n这会影响监视列表和历史中已更改页面的高亮度,并且如果“{{int:tog-enotifwatchlistpages}}”设置被启用的话,也会影响电子邮件的发送。",
        "apihelp-setnotificationtimestamp-param-entirewatchlist": "工作于所有已监视页面。",
        "apihelp-setnotificationtimestamp-param-timestamp": "要设置通知时间戳的时间戳。",
        "apihelp-setnotificationtimestamp-param-torevid": "要设置通知时间戳的修订(只限一个页面)。",
index 599fb6a..117bd2d 100644 (file)
@@ -218,7 +218,7 @@ class RedisConnectionPool implements LoggerAwareInterface {
                } else {
                        // TCP connection
                        $hostPort = IP::splitHostAndPort( $server );
-                       if ( !$hostPort ) {
+                       if ( !$server || !$hostPort ) {
                                throw new MWException( __CLASS__ . ": invalid configured server \"$server\"" );
                        }
                        list( $host, $port ) = $hostPort;
index 831ad1b..b6439b8 100644 (file)
@@ -222,7 +222,7 @@ class LegacyLogger extends AbstractLogger {
                        $context['exception'] instanceof Exception
                ) {
                        $text .= MWExceptionHandler::getRedactedTraceAsString(
-                               $context['exception']->getTraceAsString()
+                               $context['exception']
                        ) . "\n";
                }
 
diff --git a/includes/debug/logger/monolog/LineFormatter.php b/includes/debug/logger/monolog/LineFormatter.php
new file mode 100644 (file)
index 0000000..e593d63
--- /dev/null
@@ -0,0 +1,87 @@
+<?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
+ */
+
+namespace MediaWiki\Logger\Monolog;
+
+use Exception;
+use Monolog\Formatter\LineFormatter as MonologLineFormatter;
+use MWExceptionHandler;
+
+/**
+ * Formats incoming records into a one-line string.
+ *
+ * Exceptions that are logged with this formatter will optional have their
+ * stack traces appended. If that is done,
+ * MWExceptionHandler::getRedactedTraceAsString() will be used to redact the
+ * trace information.
+ *
+ * @since 1.26
+ * @author Bryan Davis <bd808@wikimedia.org>
+ * @copyright © 2015 Bryan Davis and Wikimedia Foundation.
+ */
+class LineFormatter extends MonologLineFormatter {
+
+       /**
+        * @param string $format The format of the message
+        * @param string $dateFormat The format of the timestamp: one supported by DateTime::format
+        * @param bool $allowInlineLineBreaks Whether to allow inline line breaks in log entries
+        * @param bool $ignoreEmptyContextAndExtra
+        * @param bool $includeStacktraces
+        */
+       public function __construct(
+               $format = null, $dateFormat = null, $allowInlineLineBreaks = false,
+               $ignoreEmptyContextAndExtra = false, $includeStacktraces = false
+       ) {
+               parent::__construct(
+                       $format, $dateFormat, $allowInlineLineBreaks,
+                       $ignoreEmptyContextAndExtra
+               );
+               $this->includeStacktraces( $includeStacktraces );
+       }
+
+
+       /**
+        * Convert an Exception to a string.
+        *
+        * @param Exception $e
+        * @return string
+        */
+       protected function normalizeException( Exception $e ) {
+               $str = '[Exception ' . get_class( $e ) . '] (' .
+                       $e->getFile() . ':' . $e->getLine() . ') ' .
+                       $e->getMessage();
+
+               $prev = $e->getPrevious();
+               while ( $prev ) {
+                       $str .= ', [Exception ' . get_class( $prev ) . '] (' .
+                               $prev->getFile() . ':' . $prev->getLine() . ') ' .
+                               $prev->getMessage();
+                       $prev = $prev->getPrevious();
+               }
+
+               if ( $this->includeStacktraces ) {
+                       $str .= "\n[stacktrace]\n" .
+                               MWExceptionHandler::getRedactedTraceAsString( $e ) .
+                               "\n";
+               }
+
+               return $str;
+       }
+}
index 3db235b..dca1b4c 100644 (file)
@@ -197,6 +197,7 @@ class SwiftFileBackend extends FileBackendStore {
                // By default, Swift has annoyingly low maximum header value limits
                if ( isset( $headers['content-disposition'] ) ) {
                        $disposition = '';
+                       // @note: assume FileBackend::makeContentDisposition() already used
                        foreach ( explode( ';', $headers['content-disposition'] ) as $part ) {
                                $part = trim( $part );
                                $new = ( $disposition === '' ) ? $part : "{$disposition};{$part}";
index 0e8f597..c8f7262 100644 (file)
        "config-env-bad": "Le ambiente ha essite verificate.\nTu non pote installar MediaWiki.",
        "config-env-php": "PHP $1 es installate.",
        "config-env-hhvm": "HHVM $1 es installate.",
-       "config-unicode-using-utf8": "utf8_normalize.so per Brion Vibber es usate pro le normalisation Unicode.",
        "config-unicode-using-intl": "Le [http://pecl.php.net/intl extension PECL intl] es usate pro le normalisation Unicode.",
        "config-unicode-pure-php-warning": "'''Aviso''': Le [http://pecl.php.net/intl extension PECL intl] non es disponibile pro exequer le normalisation Unicode; le systema recurre al implementation lente in PHP pur.\nSi tu sito ha un alte volumine de traffico, tu deberea informar te un poco super le [//www.mediawiki.org/wiki/Special:MyLanguage/Unicode_normalization_considerations normalisation Unicode].",
        "config-unicode-update-warning": "'''Aviso''': Le version installate del bibliotheca inveloppante pro normalisation Unicode usa un version ancian del bibliotheca del [http://site.icu-project.org/ projecto ICU].\nTu deberea [//www.mediawiki.org/wiki/Special:MyLanguage/Unicode_normalization_considerations actualisar lo] si le uso de Unicode importa a te.",
-       "config-no-db": "Non poteva trovar un driver appropriate pro le base de datos! Es necessari installar un driver de base de datos pro PHP.\nLe sequente typos de base de datos es supportate: $1.\n\nSi tu compilava PHP tu mesme, reconfigura lo con un cliente de base de datos activate, per exemplo usante <code>./configure --with-mysqli</code>.\nSi tu installava PHP ex un pacchetto Debian o Ubuntu, tu debe installar equalmente, per exemplo, le modulo <code>php5-mysql</code>.",
+       "config-no-db": "Non poteva trovar un driver appropriate pro le base de datos! Es necessari installar un driver de base de datos pro PHP.\nLe sequente {{PLURAL:$2|typo|typos}} de base de datos es supportate: $1.\n\nSi tu compilava PHP tu mesme, reconfigura lo con un cliente de base de datos activate, per exemplo, usante <code>./configure --with-mysqli</code>.\nSi tu installava PHP ex un pacchetto Debian o Ubuntu, tu debe etiam installar, per exemplo, le modulo <code>php5-mysql</code>.",
        "config-outdated-sqlite": "'''Attention''': tu ha SQLite $1, que es inferior al version minimal requirite, $2. SQLite essera indisponibile.",
        "config-no-fts3": "'''Attention''': SQLite es compilate sin [//sqlite.org/fts3.html modulo FTS3]; functionalitate de recerca non essera disponibile in iste back-end.",
        "config-register-globals-error": "<strong>Error: Le option <code>[http://php.net/register_globals register_globals]</code> de PHP es active.\nIllo debe esser disactivate pro continuar le installation.</strong>\nVide [https://www.mediawiki.org/wiki/register_globals https://www.mediawiki.org/wiki/register_globals] pro obtener adjuta sur como facer lo.",
        "config-db-install-account": "Conto de usator pro installation",
        "config-db-username": "Nomine de usator del base de datos:",
        "config-db-password": "Contrasigno del base de datos:",
-       "config-db-password-empty": "Per favor entra un contrasigno pro le nove usator del base de datos: $1.\nBen que il es possibile crear usatores sin contrasigno, isto non es secur.",
-       "config-db-username-empty": "Es necessari entrar un valor pro \"{{int:config-db-username}}\".",
        "config-db-install-username": "Entra le nomine de usator que essera usate pro connecter al base de datos durante le processo de installation. Isto non es le nomine de usator del conto MediaWiki; isto es le nomine de usator pro tu base de datos.",
        "config-db-install-password": "Entra le contrasigno que essera usate pro connecter al base de datos durante le processo de installation. Isto non es le contrasigno del conto MediaWiki; isto es le contrasigno pro tu base de datos.",
        "config-db-install-help": "Entra le nomine de usator e contrasigno que essera usate pro connecter al base de datos durante le processo de installation.",
index 73e1764..7e5ad43 100644 (file)
        "config-db-install-account": "Обліковий запис користувача для встановлення",
        "config-db-username": "Ім'я користувача бази даних:",
        "config-db-password": "Пароль бази даних:",
-       "config-db-password-empty": "Будь ласка, введіть пароль для нового користувача бази даних: $1.\nХоча можна створювати користувачів без паролів, це не є безпечним.",
-       "config-db-username-empty": "Ви повинні ввести значення для \"{{int:config-db username}}\"",
        "config-db-install-username": "Введіть ім'я користувача, яке буде використано для підключення до бази даних під час процесу встановлення.\nЦе не ім'я користувача облікового запису MediaWiki; це ім'я користувача для Вашої бази даних.",
        "config-db-install-password": "Введіть пароль, який буде використано для підключення до бази даних під час процесу встановлення.\nЦе не пароль облікового запису MediaWiki; це пароль для Вашої бази даних.",
        "config-db-install-help": "Введіть ім'я користувача і пароль, які буде використано для підключення до бази даних у процесі встановлення.",
        "config-ns-other": "Інше (вкажіть)",
        "config-ns-other-default": "MyWiki",
        "config-project-namespace-help": "За прикладом Вікіпедії, чимало вікі тримають свої сторінки правил окремо від сторінок основного вмісту, у \"'''просторі імен проекту'''\".\nУсі назви сторінок у цьому просторі імен починаються з певного префікса, який Ви можете вказати тут.\nТрадиційно цей префікс виводиться з назви вікі, але не може містити знаки пунктуація, як-то \"#\" чи \":\".",
-       "config-ns-invalid": "Вказаний простір імен \"<nowiki>$1</nowiki>\" не припустимий.\nВкажіть інший простір імен проекту.",
-       "config-ns-conflict": "Вказаний простір імен \"<nowiki>$1</nowiki>\" конфліктує зі стандартним простором імен MediaWiki.\nВкажіть інший простір імен проекту.",
+       "config-ns-invalid": "Вказаний простір назв «<nowiki>$1</nowiki>» не припустимий.\nВкажіть інший простір назв проекту.",
+       "config-ns-conflict": "Вказаний простір назв «<nowiki>$1</nowiki>» конфліктує зі стандартним простором назв MediaWiki.\nВкажіть інший простір назв проекту.",
        "config-admin-box": "Обліковий запис адміністратора",
        "config-admin-name": "Ваше ім'я користувача:",
        "config-admin-password": "Пароль:",
index ae3850f..1430dd8 100644 (file)
@@ -28,8 +28,6 @@
  * @ingroup Cache
  */
 class ObjectCacheSessionHandler {
-       /** @var array Map of (session ID => SHA-1 of the data) */
-       protected static $hashCache = array();
 
        const TTL_REFRESH_WINDOW = 600; // refresh if expiring in 10 minutes
 
@@ -58,7 +56,6 @@ class ObjectCacheSessionHandler {
         */
        protected static function getCache() {
                global $wgSessionCacheType;
-
                return ObjectCache::getInstance( $wgSessionCacheType );
        }
 
@@ -72,14 +69,6 @@ class ObjectCacheSessionHandler {
                return wfMemcKey( 'session', $id );
        }
 
-       /**
-        * @param mixed $data
-        * @return string
-        */
-       protected static function getHash( $data ) {
-               return sha1( serialize( $data ) );
-       }
-
        /**
         * Callback when opening a session.
         *
@@ -109,10 +98,10 @@ class ObjectCacheSessionHandler {
         */
        static function read( $id ) {
                $data = self::getCache()->get( self::getKey( $id ) );
-
-               self::$hashCache = array( $id => self::getHash( $data ) );
-
-               return ( $data === false ) ? '' : $data;
+               if ( $data === false ) {
+                       return '';
+               }
+               return $data;
        }
 
        /**
@@ -124,14 +113,7 @@ class ObjectCacheSessionHandler {
         */
        static function write( $id, $data ) {
                global $wgObjectCacheSessionExpiry;
-
-               // Only issue a write if anything changed (PHP 5.6 already does this)
-               if ( !isset( self::$hashCache[$id] )
-                       || self::getHash( $data ) !== self::$hashCache[$id]
-               ) {
-                       self::getCache()->set( self::getKey( $id ), $data, $wgObjectCacheSessionExpiry );
-               }
-
+               self::getCache()->set( self::getKey( $id ), $data, $wgObjectCacheSessionExpiry );
                return true;
        }
 
index 7e506f0..11dd660 100644 (file)
@@ -372,7 +372,7 @@ class RedisBagOStuff extends BagOStuff {
                        }
                }
 
-               while ( ( $tag = array_shift( $candidates ) ) !== false ) {
+               while ( ( $tag = array_shift( $candidates ) ) !== null ) {
                        $server = $this->serverTagMap[$tag];
                        $conn = $this->redisPool->getConnection( $server );
                        if ( !$conn ) {
index 9b57ff3..b9bc773 100644 (file)
@@ -25,6 +25,7 @@
 use Psr\Log\LoggerAwareInterface;
 use Psr\Log\LoggerInterface;
 use Psr\Log\NullLogger;
+use WrappedString\WrappedString;
 
 /**
  * Dynamic JavaScript and CSS resource loading system.
@@ -204,7 +205,7 @@ class ResourceLoader implements LoggerAwareInterface {
                }
 
                if ( !$options['cache'] ) {
-                       $result = $this->applyFilter( $filter, $data );
+                       $result = self::applyFilter( $filter, $data, $this->config );
                } else {
                        $key = wfGlobalCacheKey( 'resourceloader', 'filter', $filter, self::$filterCacheVersion, md5( $data ) );
                        $cache = wfGetCache( wfIsHHVM() ? CACHE_ACCEL : CACHE_ANYTHING );
@@ -218,7 +219,7 @@ class ResourceLoader implements LoggerAwareInterface {
                                $stats = RequestContext::getMain()->getStats();
                                $statStart = microtime( true );
 
-                               $result = $this->applyFilter( $filter, $data );
+                               $result = self::applyFilter( $filter, $data, $this->config );
 
                                $stats->timing( "resourceloader_cache.$filter.miss", microtime( true ) - $statStart );
                                if ( $options['cacheReport'] ) {
@@ -238,12 +239,12 @@ class ResourceLoader implements LoggerAwareInterface {
                return $result;
        }
 
-       private function applyFilter( $filter, $data ) {
+       private static function applyFilter( $filter, $data, Config $config ) {
                switch ( $filter ) {
                        case 'minify-js':
                                return JavaScriptMinifier::minify( $data,
-                                       $this->config->get( 'ResourceLoaderMinifierStatementsOnOwnLine' ),
-                                       $this->config->get( 'ResourceLoaderMinifierMaxLineLength' )
+                                       $config->get( 'ResourceLoaderMinifierStatementsOnOwnLine' ),
+                                       $config->get( 'ResourceLoaderMinifierMaxLineLength' )
                                );
                        case 'minify-css':
                                return CSSMin::minify( $data );
@@ -1107,7 +1108,14 @@ MESSAGE;
                if ( is_string( $scripts ) ) {
                        // Site and user module are a legacy scripts that run in the global scope (no closure).
                        // Transportation as string instructs mw.loader.implement to use globalEval.
-                       if ( $name !== 'site' && $name !== 'user' ) {
+                       if ( $name === 'site' || $name === 'user' ) {
+                               // Minify manually because the general makeModuleResponse() minification won't be
+                               // effective here due to the script being a string instead of a function. (T107377)
+                               if ( !ResourceLoader::inDebugMode() ) {
+                                       $scripts = self::applyFilter( 'minify-js', $scripts,
+                                               ConfigFactory::getDefaultInstance()->makeConfig( 'main' ) );
+                               }
+                       } else {
                                $scripts = new XmlJsCode( "function ( $, jQuery ) {\n{$scripts}\n}" );
                        }
                } elseif ( !is_array( $scripts ) ) {
@@ -1382,11 +1390,15 @@ MESSAGE;
         * only if the client has adequate support for MediaWiki JavaScript code.
         *
         * @param string $script JavaScript code
-        * @return string HTML
+        * @return WrappedString HTML
         */
        public static function makeInlineScript( $script ) {
                $js = self::makeLoaderConditionalScript( $script );
-               return Html::inlineScript( $js );
+               return new WrappedString(
+                       Html::inlineScript( $js ),
+                       "<script>var RLQ = RLQ || []; RLQ.push( function () {\n",
+                       "\n} );</script>"
+               );
        }
 
        /**
@@ -1463,7 +1475,7 @@ MESSAGE;
         * @param string $source Name of the ResourceLoader source
         * @param ResourceLoaderContext $context
         * @param array $extraQuery
-        * @return string URL to load.php. May be protocol-relative (if $wgLoadScript is procol-relative)
+        * @return string URL to load.php. May be protocol-relative if $wgLoadScript is, too.
         */
        public function createLoaderURL( $source, ResourceLoaderContext $context,
                $extraQuery = array()
@@ -1489,7 +1501,7 @@ MESSAGE;
         * @param bool $printable Printable mode
         * @param bool $handheld Handheld mode
         * @param array $extraQuery Extra query parameters to add
-        * @return string URL to load.php. May be protocol-relative (if $wgLoadScript is procol-relative)
+        * @return string URL to load.php. May be protocol-relative if $wgLoadScript is, too.
         */
        public static function makeLoaderURL( $modules, $lang, $skin, $user = null,
                $version = null, $debug = false, $only = null, $printable = false,
index 6c7133f..64d4982 100644 (file)
@@ -35,7 +35,7 @@ class MIMEsearchPage extends QueryPage {
        }
 
        function isExpensive() {
-               return false;
+               return true;
        }
 
        function isSyndicated() {
index 84077e6..e9c4042 100644 (file)
@@ -447,7 +447,7 @@ class SpecialSearch extends SpecialPage {
                return Html::rawElement(
                        'div',
                        array( 'class' => 'searchdidyoumean' ),
-                       $this->msg( 'search-suggest' )->rawParams( $suggest )->escaped()
+                       $this->msg( 'search-suggest' )->rawParams( $suggest )->parse()
                );
        }
 
index dfcbe78..ae3736a 100644 (file)
@@ -240,7 +240,7 @@ class IP {
         * A bare IPv6 address is accepted despite the lack of square brackets.
         *
         * @param string $both The string with the host and port
-        * @return array
+        * @return array|false Array normally, false on certain failures
         */
        public static function splitHostAndPort( $both ) {
                if ( substr( $both, 0, 1 ) === '[' ) {
index 3c0a78e..7b9a02d 100644 (file)
        "compare-submit": "Танлаштар",
        "htmlform-selectorother-other": "Урăххи",
        "htmlform-no": "Çук",
+       "logentry-delete-delete": "$1 $3 страница {{GENDER:$2|пăсса утрĕ}}",
        "logentry-move-move": "$1 страницă {{GENDER:$2|ятне улăштарчĕ}} $3 - $4",
        "rightsnone": "(çук)",
        "feedback-back": "Каялла",
index 508e254..f59df68 100644 (file)
        "special-characters-title-endash": "en dash",
        "special-characters-title-emdash": "em dash",
        "special-characters-title-minus": "minus sign",
+       "mw-widgets-dateinput-no-date": "No date selected",
        "mw-widgets-titleinput-description-new-page": "page does not exist yet",
        "mw-widgets-titleinput-description-redirect": "redirect to $1"
 }
index 215a21b..1d78005 100644 (file)
        "actionthrottledtext": "Pour lutter contre le spam, l'utilisation de cette action est limitée à un certain nombre de fois dans un laps de temps assez court. Il s'avère que vous avez dépassé cette limite.\nEssayez à nouveau dans quelques minutes.",
        "protectedpagetext": "Cette page a été protégée pour empêcher sa modification ou d'autres actions.",
        "viewsourcetext": "Vous pouvez voir et copier le contenu de cette page.",
-       "viewyourtext": "Vous pouvez voir et copier le contenu de <strong>vos modifications</strong> à cette page§.",
+       "viewyourtext": "Vous pouvez voir et copier le contenu de <strong>vos modifications</strong> à cette page.",
        "protectedinterface": "Cette page fournit du texte d'interface pour le logiciel sur ce wiki, et est protégée pour éviter les abus.\nPour ajouter ou modifier des traductions sur tous les wikis, veuillez utiliser [//translatewiki.net/ translatewiki.net], le projet de localisation de MediaWiki.",
        "editinginterface": "<strong>Attention :</strong> vous êtes en train de modifier une page utilisée pour créer le texte de l’interface du logiciel.\nLes changements sur cette page se répercuteront sur l’apparence de l’interface utilisateur pour les autres utilisateurs de ce wiki.",
        "translateinterface": "Pour ajouter ou modifier des traductions pour tous les wikis, veuillez utiliser [//translatewiki.net/ translatewiki.net], le projet de localisation de MédiaWiki.",
index eb78841..8a86f66 100644 (file)
        "monthsall": "सगळे",
        "watchlisttools-view": "प्रस्तूत बदल पळयात.",
        "watchlisttools-edit": "लक्ष वळेंरी पळय आनी संपादीत करात",
-       "signature": "[[{{ns:user}}:$1|$2]] ([[{{ns:user_talk}}:$1|à¤\89लà¥\8bयात]])",
+       "signature": "[[{{ns:user}}:$1|$2]] ([[{{ns:user_talk}}:$1|उलयात]])",
        "specialpages": "खाशेलीं पानां",
        "tag-filter": "[[Special:Tags|कुर्वेचीट]] गाळणो:",
        "tag-list-wrapper": "([[Special:Tags|{{PLURAL:$1|कुरवेचीट|कुरवेचीटी}}]]: $2)",
index ffadfc3..01d5379 100644 (file)
        "actionthrottled": "操作が速度規制されました",
        "actionthrottledtext": "短時間にこの操作を大量に行ったため、スパム対策として設定されている制限を超えました。\n少し時間をおいてからもう一度操作してください。",
        "protectedpagetext": "このページは編集や他の操作ができないように保護されています。",
-       "viewsourcetext": "このページのソースの閲覧やコピーができます:",
-       "viewyourtext": "このページへの<strong>あなたの編集</strong>のソースの閲覧やコピーができます:",
+       "viewsourcetext": "このページのソースの閲覧やコピーができます",
+       "viewyourtext": "このページへの<strong>あなたの編集</strong>のソースの閲覧やコピーができます",
        "protectedinterface": "このページにはこのウィキのソフトウェアのインターフェイスに使用されるテキストが保存されており、いたずらなどの防止のために保護されています。\nすべてのウィキに対して翻訳を追加/変更する場合は、MediaWiki の地域化プロジェクト [//translatewiki.net/wiki/Main_Page?setlang=ja translatewiki.net] を使用してください。",
        "editinginterface": "<strong>警告:</strong> ソフトウェアのインターフェイスに使用されるテキストのページを編集しています。\nこのページを変更すると、このウィキの他の利用者のユーザーインターフェイスの外観に影響します。",
        "translateinterface": "すべてのウィキに対して翻訳を追加/変更する場合は、MediaWiki の地域化プロジェクト [//translatewiki.net/wiki/Main_Page?setlang=ja translatewiki.net] を使用してください。",
        "watchlistanontext": "ウォッチリストにある項目を閲覧または編集するには、ログインしてください。",
        "watchnologin": "ログインしていません",
        "addwatch": "ウォッチリストに追加",
-       "addedwatchtext": "ã\83\9aã\83¼ã\82¸ã\80\8c[[:$1]]ã\80\8dã\82\92[[Special:Watchlist|ã\82¦ã\82©ã\83\83ã\83\81ã\83ªã\82¹ã\83\88]]ã\81«è¿½å\8a ã\81\97ã\81¾ã\81\97ã\81\9fã\80\82\nã\81\93ã\81®ã\83\9aã\83¼ã\82¸ã\81¾ã\81\9fã\81¯ã\81\9dã\81®ã\83\88ã\83¼ã\82¯ã\83\9aã\83¼ã\82¸ã\81\8cå¤\89æ\9b´ã\81\95ã\82\8cã\82\8bã\81¨ã\80\81ã\82¦ã\82©ã\83\83ã\83\81ã\83ªã\82¹ã\83\88ã\81«è¡¨ç¤ºã\81\95ã\82\8cã\81¾ã\81\99。",
+       "addedwatchtext": "ã\80\8c[[:$1]]ã\80\8dã\81\8aã\82\88ã\81³ä»\98é\9a\8fã\81\99ã\82\8bè­°è«\96ã\83\9aã\83¼ã\82¸ã\82\92ã\80\81[[Special:Watchlist|ã\82¦ã\82©ã\83\83ã\83\81ã\83ªã\82¹ã\83\88]]ã\81«è¿½å\8a ã\81\97ã\81¾ã\81\97ã\81\9f。",
        "addedwatchtext-short": "ページ「$1」をウォッチリストに追加しました。",
        "removewatch": "ウォッチリストから除去",
-       "removedwatchtext": "ã\83\9aã\83¼ã\82¸ã\80\8c[[:$1]]ã\80\8dを[[Special:Watchlist|ウォッチリスト]]から除去しました。",
+       "removedwatchtext": "ã\80\8c[[:$1]]ã\80\8dã\81\8aã\82\88ã\81³ä»\98é\9a\8fã\81\99ã\82\8bè­°è«\96ã\83\9aã\83¼ã\82¸を[[Special:Watchlist|ウォッチリスト]]から除去しました。",
        "removedwatchtext-short": "ページ「$1」をウォッチリストから除去しました。",
        "watch": "ウォッチ",
        "watchthispage": "このページをウォッチする",
        "htmlform-title-badnamespace": "[[:$1]]は、\"{{ns:$2}}\"名前空間にありません。",
        "htmlform-title-not-creatable": "\"$1\" は、作成可能なページ名では、ありません。",
        "htmlform-title-not-exists": "[[:$1]] は存在しません。",
+       "htmlform-user-not-exists": "<strong>$1</strong>は存在しません。",
+       "htmlform-user-not-valid": "<strong>$1</strong>は有効な利用者名ではありません。",
        "sqlite-has-fts": "$1 (全文検索あり)",
        "sqlite-no-fts": "$1 (全文検索なし)",
        "logentry-delete-delete": "$1 がページ「$3」を{{GENDER:$2|削除しました}}",
index aac93fe..b309886 100644 (file)
        "actionthrottled": "Dës Aktioun gouf gebremst",
        "actionthrottledtext": "Fir géint de Spam virzegoen, ass dës Aktioun sou programméiert datt Dir se an enger kuerzer Zäit nëmme limitéiert dacks maache kënnt. Dir hutt dës Limite iwwerschratt. Versicht et w.e.g. an e puer Minutten nach eng Kéier.",
        "protectedpagetext": "Dës Säit ass fir Ännerungen an aner Aktioune gespaart.",
-       "viewsourcetext": "Dir kënnt de Quelltext vun dëser Säit kucken a kopéieren:",
-       "viewyourtext": "Dir kënnt de Quelltext vun '''Ären Ännerungen''' op dëser Säit kucken a kopéieren:",
+       "viewsourcetext": "Dir kënnt de Quelltext vun dëser Säit kucken a kopéieren.",
+       "viewyourtext": "Dir kënnt de Quelltext vun <strong>Ären Ännerungen</strong> op dëser Säit kucken a kopéieren.",
        "protectedinterface": "Op dëser Säit fannt Dir Text fir de Sprooch-Interface vun der Software op dëser Wiki an dofir ass si gespaart fir Mëssbrauch ze verhënneren.\n\nFir Iwwersetzungen fir all Wikien bäizesetzen oder z'änneren gitt w.e.g. op [//translatewiki.net/ translatewiki.net], de MediaWiki-Lokalisatiouns-Projet.",
        "editinginterface": "<strong>Opgepasst:</strong> Dir sidd am Gaang, eng Säit z'änneren, déi do ass, fir Interface-Text fir d'Software ze liwweren. \nÄnnerungen op dëser Säit änneren den Interface-Text, jee no Kontext, op allen oder verschiddene Säiten, déi vun alle Benotzer op dëser Wiki gesi ginn.",
        "translateinterface": "Fir Iwwersetzunge fir all Wikien z'änneren oder dobäizesetze benotzt w.e.g.  [//translatewiki.net/ translatewiki.net], de Projet fir d'Lokalisatioun vu MediaWiki.",
index acdbcad..c84e426 100644 (file)
        "passwordreset-capture-help": "أر شوما ئی جأڤە نئ ڤارئسی بأکیت.أنجومانامە (ڤا رازینە گوڤاردئن موڤأقأتی) جوٙری کئ سی کاریاریا هأنی کئل بییە دیاری میکە.",
        "passwordreset-email": "تیرنئشوٙن أنجومانامە",
        "passwordreset-emailtitle": "جوزئیات حئساڤ ها د {{نوم مالگە}}",
-       "passwordreset-emailtext-ip": "یه کسی(شات خوتو، وا تیرنشون آی پی $1) سی د نو زنه کردن رازینه گواردن تو د {{SITENAME}}  درحاست کرده($4).\nسی کاریار «$2» یه گل رازینه گواردن موقتی دروس بیه و و هؤمبراور «$3» ئه.\nار تمارزو تو یه بیه ایسه باید بیایت وامین سامونه و یه گل رازینه گواردن هنی بهاییت\nرازینه گواردن شما د طیل {{PLURAL:$5|یه رو|$5 رو}} باطل بوئه.\n\nار کس هنی چنی درحاستی کرده یا یه که شما رازینه گواردن دمایی خوتونه د ویر اوردیت و تر نمیهایت ونه آلشت بیئت، می تونیت د ای پیغوم تیه پوشی بکیت و همو رازینه گواردن دمایی نه وه کار به ونیت.",
-       "passwordreset-emailtext-user": "کاریار $1 د {{SITENAME}} د نو زنه کردن رازینه گواردن شمانه د{{SITENAME}} ($4) کرده. {{PLURAL:$3|حساو|حساویا}} کاریاری که هان د هار د وا ای تیرنشون انجومانامه ها د ارتواط:\n\n$2\n\n{{PLURAL:$3|ای رازینه گواردن موقت|ای رازینه گواردنیا موقت}} تا {{PLURAL:$5|یه رو|$5 رو}} باطل بوئه.\nار کس هنی چنی درحاستی کرده یا یه که شما رازینه گواردن دمایی خوتونه د ویر اوردیت و تر نمیهایت ونه آلشت بیئت، می تونیت د ای پیغوم تیه پوشی بکیت و همو رازینه گواردن دمایی نه وه کار به ونیت.",
-       "passwordreset-emailelement": "نوم کاریاری: $1\nرازینه گواردن موقتی: $2",
-       "passwordreset-emailsent": "رازینه گواردن هنی سی انجومانامه کل بیه.",
-       "passwordreset-emailsent-capture": "رازینه گواردن تازه تو د انجومانامه تو که د هار نشو دئه بیه کل بیه",
-       "passwordreset-emailerror-capture": "رازینه گواردن د انجومانامه د نو زنه کننه راس بیه، و وه د هار دیاری می که، اما کل بیین وه د{{GENDER:$2|کاریار}} شکست حرده:$1",
-       "changeemail": "اÙ\86جÙ\88Ù\85اÙ\86اÙ\85Ù\87 ØªÙ\88 Ù\86Ù\87 Ø¢Ù\84شت Ø¨Ú©Û\8cد",
-       "changeemail-text": "اÛ\8c Ù\86Ù\88Ù\85 Ø¨Ù\84Ú¯Ù\87 Ù\86Ù\87 Ø³Û\8c Ø¢Ù\84شت Ø¯Ø¦Ù\86 ØªÛ\8cرÙ\86Ø´Ù\88Ù\86 Ø§Ù\86جÙ\88Ù\85اÙ\86اÙ\85Ù\87 ØªÙ\88 Ù¾Ø± Ø¨Ú©Û\8cت. Ø´Ù\85ا Ø³Û\8c Ù¾Ø´Øª Ø±Ø§Ø³ Ú©Ø±Ø¯Ù\86 Ø§Û\8c Ø¢Ù\84شت Ù\88اس Ø±Ø§Ø²Û\8cÙ\86Ù\87 Ú¯Ù\88اردÙ\86 Ø®Ù\88تÙ\88Ù\86Ù\87 Ù\88ارد Ø¨Ú©یت.",
-       "changeemail-no-info": "Ø´Ù\85ا Ø¨Ø§ Ø¨Û\8cاÛ\8cت Ø¯ Ø³Ø§Ù\85Ù\88Ù\86Ù\87 ØªØ§ Ø¯ Ø§Û\8c Ø¨Ù\84Ú¯Ù\87 Ø¯Ø³Ø±Ø³Û\8c Ø¯Ø§Ø´ØªÙ\88Û\8cت",
-       "changeemail-oldemail": "تÛ\8cرÙ\86Ø´Ù\88Ù\86 Ø§Ù\86جÙ\88Ù\85اÙ\86اÙ\85Ù\87 ØªØ§Ø²Ù\87 Ø¨Ø§Ù\88:",
-       "changeemail-newemail": "تÛ\8cرÙ\86Ø´Ù\88Ù\86 Ø§Ù\86جÙ\88Ù\85اÙ\86اÙ\85Ù\87 ØªØ§Ø²Ù\87:",
+       "passwordreset-emailtext-ip": "یە کئسی(گاسی خوتوٙ، ڤا تیرنئشوٙن آی پی $1) د نۊ زئنە کئردئن رازینە گوڤاردئنئتوٙ د {{SITENAME}} حاستیتە($4).\nسی کاریار «$2» یئ گئل رازینە گوڤاردئن موڤأقتی رأڤأندیاری بییە و هومبأراڤأر «$3» ە.\nأر دالئتوٙ یە بییە ئیسئ ڤاس بیائیت ڤامین ساموٙنە و یئ گئل رازینە گوڤاردئن هأنی بئهایت.\n رازینە گوڤاردئن {{PLURAL:$3|ئی رازینە یا گوڤاردئن موڤأقأتی|ئی رازینە یا گوڤاردئن موڤأقأتی}} شوما د گات {{PLURAL:$5|یئ روٙ|$5 روٙ}} باطئل بوٙە.\n\nأر کأسی هأنی چئن حاستی داشتە یا یە کئ رازینە گوڤاردئن دئمایی شوما د ڤیرئتوٙ ئوٙما و دە نئمیهایت ڤئنە آلئشت کاری بأکیت، می توٙنیت د ئی پئیغوم تیە پوٙشی بأکیت و هأموٙ رازینە گوڤاردئن دئمایی نە بونیت د کار.",
+       "passwordreset-emailtext-user": "کاریار $1 د {{SITENAME}} د نۊ زئنە کئردئن رازینە گوڤاردئن شومانە د{{SITENAME}} ($4) حاستە. {{PLURAL:$3|حئساڤ|حئساڤیا}} کاریاری کئ هان د هار و ڤا ئی تیرنئشوٙن أنجومانامە هان د ئرتئڤاط:\n\n$2\n\n رازینە گوڤاردئن {{PLURAL:$3|ئی رازینە یا گوڤاردئن موڤأقأتی|ئی رازینە یا گوڤاردئن موڤأقأتی}} شوما د گات {{PLURAL:$5|یئ روٙ|$5 روٙ}} باطئل بوٙە.\nأر کأسی هأنی چئن حاستی داشتە یا یە کئ رازینە گوڤاردئن دئمایی شوما د ڤیرئتوٙ ئوٙما و دە نئمیهایت ڤئنە آلئشت کاری بأکیت، می توٙنیت د ئی پئیغوم تیە پوٙشی بأکیت و هأموٙ رازینە گوڤاردئن دئمایی نە بونیت د کار.",
+       "passwordreset-emailelement": "نوم کاریاری: $1\nرازینە گوڤاردئن موڤأقتی: $2",
+       "passwordreset-emailsent": "یئ گئل رازینە گوڤاردئن هأنی سی أنجومانامە کئل بییە.",
+       "passwordreset-emailsent-capture": "رازینە گوڤاردئن تازە توٙ سی أنجومانامە توٙ کئ ها د هار کئل بییە.",
+       "passwordreset-emailerror-capture": "رازینە گوڤاردئن د أنجومانامە د نۊ زئنە کون کئل بییە،و ڤئ د هار دیاری میکە، ڤألی کئل بییئن ڤئ سی {{GENDER:$2|کاریار}} ناخوش سأرنجوم بییە:$1",
+       "changeemail": "Ø£Ù\86جÙ\88Ù\85اÙ\86اÙ\85Û\95 ØªÙ\88Ù\99Ù\86Û\95 Ø¢Ù\84ئشت Ú©Ø§Ø±Û\8c Ø¨Ø£Ú©Û\8cت",
+       "changeemail-text": "ئÛ\8c Ù\86Ù\88Ù\85 Ø¨Ø£Ù\84Ú¯Û\95 Ù\86ئ Ø³Û\8c Ø¢Ù\84ئشت Ø¯Ø£Ø¦Ù\86 ØªÛ\8cرÙ\86ئشÙ\88Ù\99Ù\86 Ø£Ù\86جÙ\88Ù\85اÙ\86اÙ\85Û\95 ØªÙ\88Ù\99 Ù¾Ù\88ر Ø¨Ø£Ú©Û\8cت. Ø´Ù\88Ù\85ا Ø³Û\8c Ù¾Ù\88شت Ø±Ø§Ø³ Ú©Ø§Ø±Û\8c Ø¦Û\8c Ø¢Ù\84ئشت Ø¨Ø§Û\8cأد Ø±Ø§Ø²Û\8cÙ\86Û\95 Ú¯Ù\88ڤاردئÙ\86 Ø®Ù\88تÙ\88Ù\99Ù\86Û\95 Ø¨Ø£Ø²Ø¦Ù\86یت.",
+       "changeemail-no-info": "Ø´Ù\88Ù\85ا Ø³Û\8c Û\8cÛ\95 Ú©Ø¦ Ø¯ Ø¦Û\8c Ø¨Ø£Ù\84Ú¯Û\95 Ø¯Ø£Ø³Ø±Ø¦Ø³Û\8c Ø¯Ø§Ø´ØªÙ\88Ù\99Û\8cÛ\8cت Ø¨Ø§Ø³ Ø¨Û\8cاÛ\8cÛ\8cت Ú¤Ø§Ù\85Û\8cÙ\86.",
+       "changeemail-oldemail": "تÛ\8cرÙ\86ئشÙ\88Ù\99Ù\86 Ø£Ù\86جÙ\88Ù\85اÙ\86اÙ\85Û\95 Ø¦Û\8cسئÙ\86Û\8c:",
+       "changeemail-newemail": "تÛ\8cرÙ\86ئشÙ\88Ù\99Ù\86 Ø£Ù\86جÙ\88Ù\85اÙ\86اÙ\85Û\95 ØªØ§Ø²Û\95:",
        "changeemail-none": "(هيش كوم)",
-       "changeemail-password": "{{SITENAME}} رازینه گواردن شما:",
-       "changeemail-submit": "Ø¢Ù\84شت Ú©Ø±Ø¯Ù\86 Ø§Ù\86جÙ\88Ù\85اÙ\86اÙ\85Ù\87",
-       "changeemail-throttled": "Ø´Ù\85ا Ø§Û\8cسÙ\86Û\8c Ù\81رÙ\87 Ø³Û\8c Ù\88اÙ\85Û\8cÙ\86 Ø§Ù\88Ù\85ائÙ\86 ØªÙ\84اش Ú©Ø±Ø¯Û\8cتÙ\87.\n$1 Ù\84Ø·Ù\81Ù\86 Ø³Û\8c ØªÙ\84اش Ù\87Ù\86Û\8c ØµØ¨Ø± Ø¨Ú©Û\8cد.",
-       "resettokens": "تازه کردن نشونه یا",
-       "resettokens-text": "Ø´Ù\85ا Ø³Û\8c ØµÙ\84ا Ø¯Ø¦Ù\86 Ø¯Ø³Ø±Ø³Û\8c Ù\88Ù\87 Ø±Ø³Û\8cÙ\86Ù\87 Û\8cا Ø®ØµÙ\88صÛ\8c Ú©Ù\87 Ù\87ا Ø¯ Ø­Ø³Ø§Ù\88 Ø§Û\8cÚ\86Ù\86Û\8c ØªÙ\88 Ù\85Û\8c ØªÙ\88Ù\86Û\8cت Ø¯Û\8cارگرÛ\8cا Ù\86Ù\87 Ø¯ Ù\86Ù\88 Ø²Ù\86Ù\87 Ø¨Ú©Û\8cت.\n\nØ´Ù\85ا Ø§Ù\88سÙ\86Û\8c Ù\88اس Ø§Û\8c Ú©Ø§Ø± Ø¨Ú©Û\8cت Ú©Ù\87 Ø±Ø³Û\8cÙ\86Ù\87 Û\8cا Ø´Ù\85ا Ø³Û\8c Û\8cÙ\87 Ú©Ø³Û\8c ØªØ± Ø¨Ø¦Ø± Ø¨Û\8cÙ\87 Û\8cا Ø¯ Ø­Ø³Ø§Ù\88 Ø´Ù\85ا Ú\86Ù\84 Ø¨Û\8cÙ\87.",
-       "resettokens-no-tokens": "Ù\87Û\8cÚ\98 Ù\86Ø´Ù\88Ù\86Ù\87 Ø§Û\8c Ø³Û\8c ØªØ§Ø²Ù\87 Ú©Ø±Ø¯Ù\86 Ù\86ئ.",
+       "changeemail-password": "رازینە گوڤاردئن{{SITENAME}} شوما:",
+       "changeemail-submit": "Ø¢Ù\84ئشت Ø¯Ø£Ø¦Ù\86 Ø£Ù\86جÙ\88Ù\85اÙ\86اÙ\85Û\95",
+       "changeemail-throttled": "Ø´Ù\88Ù\85ا Ø³Û\8c Ú¤Ø§Ù\85Û\8cÙ\86 Ø¦Ù\88Ù\99Ù\85ائÙ\86 Ù\81ئرÛ\95 ØªØ¦Ù\84اش Ú©Ø¦Ø±Ø¯Û\8cتÛ\95.\n$1 Ù\84Ù\88Ø·Ù\81 Ø¨Ø£Ú©Û\8cت Ø³Û\8c ØªØ¦Ù\84اش Ù\87Ø£Ù\86Û\8c Ú¯Ù\88رÛ\8c Ø¨Ø¦Ø³Û\8cت.",
+       "resettokens": "تازە کاری نئشوٙنە یا",
+       "resettokens-text": "Ø´Ù\88Ù\85اس Ø³Û\8c ØµØ¦Ù\84ا Ø¯Ø£Ø¦Ù\86 Ø¯Ø£Ø³Ø±Ø³Û\8c Ú¤Ø¦ Ø¯Ø§Ø¯Û\95 Û\8cا Ø®Ù\88صÙ\88Ù\99صÛ\8c Ú©Ø¦ Ù\87اÙ\86 Ø¯ Ø­Ø¦Ø³Ø§Ú¤ Ø¦Û\8cÚ\86ئÙ\86Û\8c ØªÙ\88Ù\99 Ù\85Û\8c ØªÙ\88Ù\99Ù\86Û\8cت Ø¯Û\8cارگأرÛ\8cا Ù\86Û\95 Ø¯ Ù\86Û\8a Ø²Ø¦Ù\86Û\95 Ø¨Ø£Ú©Û\8cت.\n\nئÙ\88Ù\99سئ Ø´Ù\88Ù\85ا Ø¨Ø§Û\8cأد Ø¦Û\8c Ú©Ø§Ø± Ù\86Û\95 Ø£Ù\86جÙ\88Ù\85 Ø¨Ø¦Û\8cت Ø³Û\8c Û\8cÛ\95 Ú©Ø¦ Ø¯Ø§Ø¯Û\95 Û\8cا Ø´Ù\88Ù\85ا Û\8cا Ú¤Ø§ Ú©Ø¦Ø³Û\8c Ù\87Ø£Ù\86Û\8c Ø¨Ø£Ù\87رکارÛ\8c Ø¨Û\8cÛ\8cÛ\95 Û\8cا Û\8cÛ\95 Ú©Ø¦ Ø¯ Ø­Ø¦Ø³Ø§Ú¤ Ø´Ù\88Ù\85ا Ú\86Ù\88Ù\84 Ø¨Û\8cÛ\8cÛ\95.",
+       "resettokens-no-tokens": "Ù\87Û\8cÚ\86 Ù\86ئشÙ\88Ù\99Ù\86Û\95 Û\8cÛ\8c Ø³Û\8c Ø¯ Ù\86Û\8a Ø²Ø¦Ù\86Û\95 Ú©Ø¦Ø±Ø¯Ø¦Ù\86 Ù\86Û\8c.",
        "resettokens-tokens": "نئشوٙنە یا:",
        "resettokens-token-label": "$1 (أرزایئشت تازە: $2)",
-       "resettokens-watchlist-token": "دÛ\8cارگر Ø³Û\8c Ø­Ø±Ø¯Ù\86Û\8c ØªÙ\88رگÙ\87(اتÙ\85/آر Ø§Ø³ Ø§Ø³) Ø³Û\8c [[Ù\88Û\8cجÙ\87:سÛ\8cÙ\84 Ø¨Ø±Ú¯|Ø¢Ù\84شت Ø¯Ø¦Ù\86 Ø¨Ù\84Ú¯Ù\87 Û\8cا Ø¯ Ø³Û\8cÙ\84 Ø¨Ø±Ú¯ØªÙ\88]]",
-       "resettokens-done": "Ù\86Ø´Ù\88Ù\86Ù\87 Û\8cا ØªØ§Ø²Ù\87 Ø¨Û\8cÙ\87.",
-       "resettokens-resetbutton": "Ù\86Ø´Ù\88Ù\86Ù\87 Û\8cا Ø§Ù\86تخاÙ\88 Ø¨Û\8cÙ\87 ØªØ§Ø²Ù\87 Ø¨Ù\88ئÙ\86",
-       "bold_sample": "نیسسه توپر بیه",
-       "bold_tip": "Ù\86Û\8cسسÙ\87 ØªÙ\88پر Ø¨Ù\8aÙ\87",
-       "italic_sample": "Ù\86Û\8cسسÙ\87 Ù\83ج Ù\83Ù\88Ù\84Ù\87",
-       "italic_tip": "Ù\86Û\8cسسÙ\87 Ù\83ج Ù\83Ù\88Ù\84Ù\87",
+       "resettokens-watchlist-token": "دÛ\8cارگأر Ø³Û\8c Ø­Ù\88ڤاÙ\84 Ø­Ù\88Ù\99Ù\86 ØªÙ\88رگÛ\95(أتÙ\88Ù\85/آر Ø¦Ø³ Ø¦Ø³) Ø³Û\8c [[Special:سئÛ\8cÙ\84 Ø¨Ø£Ø±Ú¯|Ø¢Ù\84ئشت Ø¯Ø£Ø¦Ù\86 Ø¨Ø£Ù\84Ú¯Û\95 Û\8cا Ø¯ Ø³Ø¦Û\8cÙ\84 Ø¨Ø£Ø±Ú¯Ø¦ØªÙ\88Ù\99]]",
+       "resettokens-done": "Ù\86ئشÙ\88Ù\99Ù\86Û\95 Û\8cا ØªØ§Ø²Ù\87 Ø¨Û\8cÛ\8cÙ\86Û\95",
+       "resettokens-resetbutton": "Ù\86ئشÙ\88Ù\99Ù\86Û\95 Ú¯Ù\88Ù\84ئ Ú¤Ù\88رÚ\86Û\8cÛ\95 Ø¯ Ù\86Ù\88Ù\99 Ø²Ø¦Ù\86Û\95 Ø¨Û\8cÙ\86Û\95",
+       "bold_sample": "نیسسە توٙپور",
+       "bold_tip": "Ù\86Û\8cسئسÛ\95 ØªÙ\88Ù\99Ù¾Ù\88ر",
+       "italic_sample": "Ù\86Û\8cسئسÛ\95 Ú©Ø£Ø¬ Ù\88 Ú©Ù\88Ù\84Û\95",
+       "italic_tip": "Ù\86Û\8cسئسÛ\95 Û\8cا Ú©Ø£Ø¬ Ù\88 Ú©Ù\88Ù\84Û\95",
        "link_sample": "داسوٙن هوم پئیڤأند",
        "link_tip": "هوم پئیڤأند مینجایی",
-       "extlink_sample": "http://www.example.com Ø¯Ø§Ø³Ù\88Ù\86 Ù\87Ù\88Ù\85 Ù¾Û\8cÙ\88ند",
-       "extlink_tip": "هوم پیوند خارجی(د ویر داشتو)",
-       "headline_sample": "سرخط Ù\86Û\8cسسÙ\87",
-       "headline_tip": "رÛ\8cرتراز 2 Ø®Ø· Ø³Ø± Ù\88ن",
-       "nowiki_sample": "د Ø§Û\8cÚ\86Ù\87 Û\8cÙ\87 Ú¯Ù\84 Ù\86Û\8cسسÙ\87 Ø¨Û\8c Ø´Ù\84Ú© Ù\88ارد Ø¨Ú©Û\8cد",
-       "nowiki_tip": "Ø´Ù\84Ú© Ù\88Û\8cÚ©Û\8c Ù\86Ù\87 Ù\86دÛ\8cد Ø¨Ú¯Ø±",
+       "extlink_sample": "http://www.example.com Ø¯Ø§Ø³Ù\88Ù\99Ù\86 Ù\87Ù\88Ù\85 Ù¾Ø¦Û\8cڤأند",
+       "extlink_tip": "هوم پئیڤأند خارئجی(د ڤیر داشتوٙئیت)",
+       "headline_sample": "سأرخأط Ù\86Û\8cسئسÛ\95",
+       "headline_tip": "رÛ\8cتئراز 2 Ø®Ø£Ø· Ø³Ø£Ø±Ú¤Ø£ن",
+       "nowiki_sample": "د Ø¦Û\8cÚ\86ئ Û\8cئ Ú¯Ø¦Ù\84 Ù\86Û\8cسئسÛ\95 Ø¨Û\8c Ø´Ø¦Ú©Ù\84 Ú¤Ø§Ø±Ø¦Ø¯ Ø¨Ø£Ú©Û\8cت.",
+       "nowiki_tip": "د Ø´Ø¦Ú©Ù\84 Ú¤Û\8cÚ©Û\8c ØªÛ\8cÛ\95 Ù¾Ù\88Ù\99Ø´Û\8c Ø¨Ø£Ú©",
        "image_sample": "Example.jpg",
        "image_tip": "جانیا چار قئر گئرئتە",
        "media_sample": "Example.ogg",
        "showpreview": "نئشوٙ دأئن پیش سئیل",
        "showdiff": "نئشوٙ دأئن آلئشت کاریا",
        "blankarticle": "<strong>زنئار:</strong> بلگه ای که شما دروس کردیته حالیه.\nار شما د نو ری \"{{int:savearticle}}\" بپورنیت, بلگه وه شکل که هیچ مینونه ای دش نبا دروس بوئه.",
-       "anoneditwarning": "<strong>زئÙ\86ار:</strong> Ø´Ù\85ا Ù\87Ù\86Û\8c Ù\86Û\8cÙ\88Ù\85اتÙ\87 Ù\88اÙ\85Û\8cÙ\86. ØªÛ\8cرÙ\86Ø´Ù\88Ù\86 Ø¢Û\8c Ù¾Û\8c Ø´Ù\85ا Ù\87ر Ú¯Ø§ØªÛ\8c Ú©Ù\87 Ø¢Ù\84شتÛ\8c Ø±Ø§Ø³ Ø¨Ú©Û\8cت Ø³Û\8c Ú©Ù\84 Ø®Ù\84Ú© Ø¯Û\8cارÙ\87. Ø§Ø± <strong>[$1 Ø±Ù\88ئÛ\8cت Ù\88اÙ\85Û\8cÙ\86]</strong> Û\8cا <strong>[$2 Û\8cÙ\87 Ú¯Ù\84 Ø­Ø³Ø§Ù\88 Ú©Ø§Ø±Û\8cارÛ\8c Ø±Ø§Ø³ Ø¨Ú©Û\8cت]</strong>Ø\8c Ù\88Û\8cراÛ\8cشتÛ\8cا Ø´Ù\85ا Ù\88Ù\87 Ù\86Ù\88Ù\85 Ú©Ø§Ø±Û\8cارÛ\8c Ø®Ù\88تÙ\88Ù\86 Ø¯Û\8cارÛ\8c Ù\85Û\8c Ú©Ù\87Ø\8c Ù\88 Ù\88ا Ú\86Û\8cا Ø¨Û\8cتر Ù\87Ù\86Û\8c.",
-       "anonpreviewwarning": "<em>Ø´Ù\85ا Ù\86Û\8cÙ\88Ù\85ائتÙ\87 Ù\88اÙ\85Û\8cÙ\86. ØªÛ\8cرÙ\86Ø´Ù\88Ù\86 Ø¢Û\8c Ù¾Û\8c Ø´Ù\85ا Ø¯ Ù\88Û\8cرگار Ù\88Û\8cراÛ\8cشت Ø§Û\8c Ø¨Ù\84Ú¯Ù\87 Ø§Ù\85اÛ\8cÛ\8cÙ\87 Ø¨Ù\88ئÙ\87.</em>",
-       "missingsummary": "<strong>د ویر ونا:</strong> شما هنی یه گل چکسته ویرایشتی نها اماییه نکردیته.\nار شما د نو د ری\"{{int:savearticle}}\" بپورنیت, ویرایشت شما حالی اماییه بوئه.",
+       "anoneditwarning": "<strong>زئÙ\86ار:</strong> Ø´Ù\88Ù\85ا Ù\87Ø£Ù\86Û\8c Ù\86Û\8cÙ\88Ù\99Ù\85اÛ\8cتÛ\95 Ú¤Ø§Ù\85Û\8cÙ\86. ØªÛ\8cرÙ\86ئشÙ\88Ù\99Ù\86 Ø¢Û\8c Ù¾Û\8c Ø´Ù\88Ù\85ا Ø³Û\8c Ù\87أر Ú¯Ø§ØªÛ\8c Ú©Ø¦ Ø¢Ù\84ئشتکارÛ\8c Ø¨Ø£Ú©Û\8cت Ø³Û\8c Ú©Ù\88Ù\84 Ø®Ø£Ù\84Ú© Ø¯Û\8cارÛ\8c Ù\85Û\8c Ú©Û\95. Ø£Ø± <strong>[$1 Ø±Ù\88ئÛ\8cت Ú¤Ø§Ù\85Û\8cÙ\86]</strong> Û\8cا <strong>[$2 Û\8cئ Ú¯Ø¦Ù\84 Ø­Ø¦Ø³Ø§Ú¤ Ú©Ø§Ø±Û\8cارÛ\8c Ø±Ø§Ø³ Ø¨Ø£Ú©Û\8cت]</strong>Ø\8c Ú¤Û\8cراÛ\8cئشتÛ\8cا Ø´Ù\88Ù\85ا Ú¤Ø¦ Ù\86Ù\88Ù\85 Ú©Ø§Ø±Û\8cارÛ\8c Ø®Ù\88تÙ\88Ù\99 Ø¯Û\8cارÛ\8c Ù\85Û\8c Ú©Û\95 Ù\88 Ø³Û\8c Ø´Ù\88Ù\85ا Ø¨Û\8cتأرÛ\95.",
+       "anonpreviewwarning": "<em>Ø´Ù\88Ù\85ا Ù\86Û\8cÙ\88Ù\99Ù\85اÛ\8cتÛ\95 Ú¤Ø§Ù\85Û\8cÙ\86. ØªÛ\8cرÙ\86ئشÙ\88Ù\99Ù\86 Ø¢Û\8c Ù¾Û\8c Ø´Ù\88Ù\85ا Ø¯ Ú¤Û\8cرگار Ú¤Û\8cراÛ\8cئشت Ø¦Û\8c Ø¨Ø£Ù\84Ú¯Û\95 Ø¦Ù\85اÛ\8cÛ\95 Ø¨Ù\88Ù\99Û\95.</em>",
+       "missingsummary": "<strong>ڤیر دیارکو:</strong> شوما هأنی یئ گئل چئکئسە ڤیرایئشتی نە نئها ئمایە کاری نأکئردیتە.\nأر شوما د نۊ د ری \"{{int:savearticle}}\" بأپوٙرنیت، ڤیرایئشت کاری شوما حالی ئمایە بوٙە.",
        "selfredirect": "<strong>هشدار:</strong> شما د حال و بار آلشت دئن لا بلگه وه خوش هیئن.\nشایت دال اشتوایی سی آلشت دئن لا نه انتخاو کردیته، یا شایت بلگه نه اشتوایی ویرایشت می کیت.\n\nار ری \"{{int:savearticle}}\" دوبار بپورنیت، آلشت دئن لا دروس بوئه.",
        "missingcommenttext": "لطفن د ایچه ویر و باور بیئتو",
        "missingcommentheader": "<strong>د ویر ونا:</strong> شما هنی یه گل موضوع/سرخط سی ای ویر و باور نها اماییه نکردیته.\nار شما د نو د ری\"{{int:savearticle}}\" بپورنیت, ویرایشت شما حالی اماییه بوئه.",
        "summary-preview": "چئکئسە پیش سئیل:",
-       "subject-preview": "پیش سیل موضو سرخط",
+       "subject-preview": "داسوٙن/پیش سئیل سأرخأط:",
        "previewerrortext": "یه گل خطا د گاتی که شما میهاستیت یه گل پیش سیل د آلشتیاتو داشتوین پیش اومائه.",
-       "blockedtitle": "کاریار نهاگری بیه",
+       "blockedtitle": "کاریار نئهاگئری بی",
        "blockedtext": "<strong>نوم کاریاری شما یا تیرنشون آی پی شما قلف بیه.</strong>\n\n\n$1 ونه قلف کرده.\nدلیل ها د ایچه<em>$2</em>.\n\nشرو د قلف بیین:$8\nآخر قلف بیین:$6\nکاریار ورتیه قلف بیه:$7\n\nشما می تونیت وا $1 یا [[{{MediaWiki:Grouppage-sysop}}|دیووندار]] هنی پیوند بئریت و سی قلف کردن چک چنه بزنیت.\nالوت د ویر داشتویت که شما نمی تونیت د خصوصیت انجومانامه کل کردن سی ای کاربر استفاده بکیت مئر  یه گل تیرنشون انجومانامه معتور د [[Special:Preferences|ترجیحیا کاریاری]] خوتو معلوم کرده بویت و باید امکان وه کار بستن وه نه داشتویتو\nتیرنشون آی پی ایسنی شما $3 ئه، و نوم دیارکن قلف کردن #$5 ئه.\nلطفا همه جزئیات نه د هر حاسته ای که داریت بوئیت.",
        "autoblockedtext": "نوم کاریاری شما یا تیرنشون آی پی شما سی یه که یه گل کاریاری هنی وه کارش بسته خودانجومن قلف بیه $1 ونه قلف کرده.\nدلیل ها د ایچه\n\n:<em>$2</em>.\n\nشرو د قلف بیین:$8\nآخر قلف بیین:$6\nکاریار ورتیه قلف بیه:$7\n\nشما می تونیت وا $1 یا [[{{MediaWiki:Grouppage-sysop}}|دیووندار]] هنی پیوند بئریت و سی قلف کردن چک چنه بزنیت.\n\nالوت د ویر داشتویت که شما نمی تونیت د خصوصیت انجومانامه کل کردن سی ای کاربر استفاده بکیت مئر  یه گل تیرنشون انجومانامه معتور د [[Special:Preferences|ترجیحیا کاریاری]] خوتو دیاری کرده بویت و باید امکان وه کار بستن وه نه داشتویت.\n\nتیرنشون آی پی ایسنی شما $3 ئه، و نوم دیارکن قلف کردن #$5 ئه.\nلطفا همه جزئیات نه د هر حاسته ای که داریت بوئیت.",
        "blockednoreason": "هیژ دلیلی دئه نبیه",
        "noarticletext-nopermission": "د تازه یا د ای بلگه نیسسه نی.\nشما می تونیت د [[Special:Search/{{PAGENAME}}|بگردید]] د ای بلگه یا د بلگیا هنی یا <span class=\"plainlinks\">[{{fullurl:{{#Special:Log}}|page={{FULLPAGENAMEE}}}}   د هنی پی جوری بوئه]</span> اما شما حق ناریتو ای بلگه نه راس بکیت.",
        "missing-revision": "وانئیری #$1 د بلگه ای که نومش ونه \"{{FULLPAGENAME}}\" وجود ناره.\n\nشایت بانی جاونه وه وا یه گل ویرگار وه هنگوم نبیه که د یه گل بلگه پاکسا بیه هوم پیوند بیه بوئه.\nشایت جزئیات د   [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} deletion log]  پیدا بوئن.",
        "userpage-userdoesnotexist": "حساو کاریاری\"$1\" ثوت نام نبیه.\nار میهایت ای بلگه نه بسازیتو یا ویرایشت بکیت یه گل وارسی انجوم بئیت.",
-       "userpage-userdoesnotexist-view": "حساÙ\88 Ú©Ø§Ø±Ù\88ر\"$1\" Ø«Ù\88ت Ù\86بÛ\8cÙ\87.",
+       "userpage-userdoesnotexist-view": "حئساڤ Ú©Ø§Ø±Û\8cارÛ\8c \"$1\" Ø«Ø£Ú¤Øª Ù\86أبÛ\8cÛ\8cÛ\95.",
        "blocked-notice-logextract": "ای کاریار ایسنی دسرسی ناره.\nآخری پهرستنومه قلف ورودی د هار ایچه سی سرچشمه آماده بیه:",
        "clearyourcache": "<strong>د ویر داشتویت:</strong> نها اماییه کاری, شات مژبور وه وه کار ونن ویرگه نهو دوارته نیئر خوتو سی دیئن ای آلشتیا بوئیت .\n* <strong>فایرفاکس/ سفری:</strong> بپورنیت ری<em>شیفت</em> اوسه که می پورنیت<em>د نو سوار بوئه</em>یا هنی ری <em>Ctrl-F5</em> بپورنیت یا<em>Ctrl-R</em> (<em>⌘-R</em> د سامونه مک)\n* <strong>گوگل کروم:</ strong>بپورنیت ری <em>Ctrl-Shift-R</em> (<em>⌘-Shift-R</em> یا د سامونه)\n* <strong>اینترنت اکسپلورر:</strong> <em>Ctrl</em> واداریت اوسه که می پورنیت ری <em>Refresh</em>, یل بپورنیت ری<em>Ctrl-F5</em>\n* <strong>اوپرا:</strong> ویرگه نهو نه د <em>اوزاریا→ اولویتیا پاک بکیت</em>",
        "usercssyoucanpreview": "<strong>نکته:</strong> د دگمه \"{{int:showpreview}}\" سی آزماشت کردن سی اس اس تازه دما اماییه کاری وه کار بیئریت.",
        "updated": "(تازه بيه)",
        "note": "'''نیسأنئن:'''",
        "previewnote": "فقط ای پیش سیل د ویرتو با.\nآلشتیاتو هنی اماییه نبیه.",
-       "continue-editing": "رو د راساگه ویرایشت",
+       "continue-editing": "رو د راساگە ڤیرایئشت کاری",
        "previewconflict": "ورگشت پیش سیل د نیسسه د راساگه وارو ویرایشت چی شکل دیار بیین بوئه ار شما وه نه سی اماییه کردن انتخاو بکیت.",
        "session_fail_preview": "<strong>د بدبختی ما سی یه که رسینه یا جلسه مونه د دس دئیمه نمی تونیم کار پردازشت ویرایشت شمانه انجوم بیئمو.</strong>\nلطفن هنی تلاش بکیت.\nار هنی کار وه دروس کار نکرد،[[Special:UserLogout|اومائن وه در]] نه ازمایشت بکیت و د نو بیایت وامین.",
        "session_fail_preview_html": "<strong>د بدبختی ما سی یه که رسینه یا جلسه مونه د دس دئیمه نمی تونیم کار پردازشت ویرایشت شمانه انجوم بیئمو.</strong>\nلطفن هنی تلاش بکیت.\n\n<em>سی یه که {{نوم دیارگه}} یه گل ردیف اچ تی ام ال کنشتگر بیه داره، پیش سیل سی یه که د دس حمله یا جاوا اسکریپ د امون با قام کرده بیه..</em>\n\n<strong>ار وه گات قانونی تلاش سی ویرایشته،لطفا د نو تلاش بکیت.</strong>\nار هنی کار وه دروس کار نکرد،[[Special:UserLogout|اومائن وه در]] نه ازمایشت بکیت و د نو بیایت وامین.",
        "nocreate-loggedin": "شوما صئلا راس کئردئن بألگە تازە نە ناریت.",
        "sectioneditnotsupported-title": "ویرایشت بهرجا حامین داری نبوئه",
        "sectioneditnotsupported-text": "ڤیرایئشت بأرجایی د ئی بألگە نیئش.",
-       "permissionserrors": "خطا Ø§Ø¬Ø§Ø²Ù\87 Ø¯Ø¦Û\8cن",
+       "permissionserrors": "خأطا ØµØ¦Ù\84ا Ø¯Ø£Ø¦ن",
        "permissionserrorstext": "شما حق ناریت ونه انجوم بیئت, سی{{PLURAL:$1|دلیل|دلیلیا}} نهایی:",
        "permissionserrorstext-withaction": "شما سی $2 اجازه ناریت\nسی نهاگری {{PLURAL:$1|دلیل|دلیلیا}}:",
        "recreate-moveddeleted-warn": "'''زنهار شما بلگه ای که وادما پاکسا بیه هنی راس کردیته'''\nشما باید دونسه بایت که آیا هنی سی نها گرتن ویرایشت ای بلگه خوئه.\nپاکسا بیئن و جمشت سی ای بلگه سی فراغتتو آماده بیه:",
index 1fdbd17..b5d8e11 100644 (file)
        "session_fail_preview_html": "'''Uw bewerking is niet verwerkt, omdat de sessiegegevens verloren zijn gegaan.'''\n\n''Omdat in {{SITENAME}} ruwe HTML is ingeschakeld, is een voorvertoning niet mogelijk als bescherming tegen aanvallen met JavaScript.''\n\n'''Als dit een legitieme bewerking is, probeer het dan opnieuw.'''\nAls het dan nog niet lukt, [[Special:UserLogout|meld uzelf dan af]] en vervolgens weer aan.",
        "token_suffix_mismatch": "'''Uw bewerking is geweigerd, omdat uw browser de leestekens in het bewerkingstoken onjuist heeft behandeld.'''\nDe bewerking is geweigerd om verminking van de paginatekst te voorkomen.\nDit gebeurt soms als er een webgebaseerde proxydienst wordt gebruikt die fouten bevat.",
        "edit_form_incomplete": "'''Sommige onderdelen van het bewerkingsformulier hebben de server niet bereikt. Controleer of uw bewerkingen intact zijn en probeer het opnieuw.'''",
-       "editing": "Bezig met bewerken van $1",
+       "editing": "Bewerken van $1",
        "creating": "Bezig met het aanmaken van $1",
        "editingsection": "Bezig met bewerken van $1 (deelpagina)",
        "editingcomment": "Bezig met bewerken van $1 (nieuw kopje)",
        "changecontentmodel-success-title": "Het inhoudsmodel is veranderd",
        "changecontentmodel-success-text": "Het inhoudstype van [[:$1]] is veranderd.",
        "changecontentmodel-cannot-convert": "De inhoud van [[:$1]] kan niet worden omgezet in een type $2.",
-       "changecontentmodel-title-cantexist": "Geen pagina mogelijk op $1.",
        "changecontentmodel-nodirectediting": "Het inhoudsmodel $1 ondersteunt direct bewerken niet",
        "log-name-contentmodel": "Veranderingenlogboek van inhoudsmodel",
        "log-description-contentmodel": "Gebeurtenissen rond het inhoudsmodel van een pagina",
index 9a7c1df..8f51507 100644 (file)
        "actionthrottledtext": "Mechanizm obrony przed spamem ogranicza liczbę wykonań tej czynności w jednostce czasu. Usiłowałeś przekroczyć to ograniczenie. Spróbuj jeszcze raz za kilka minut.",
        "protectedpagetext": "Wyłączono możliwość edycji tej strony.",
        "viewsourcetext": "Tekst źródłowy strony można podejrzeć i skopiować.",
-       "viewyourtext": "Tekst źródłowy '''zmodyfikowanej przez Ciebie''' strony możesz podejrzeć i skopiować.",
+       "viewyourtext": "Tekst źródłowy <strong>zmodyfikowanej przez Ciebie</strong> strony możesz podejrzeć i skopiować.",
        "protectedinterface": "Ta strona zawiera tekst interfejsu oprogramowania wiki i jest zabezpieczona przed nadużyciami.\nBy dodać lub zmienić tłumaczenia wszystkich serwisów wiki, użyj [//translatewiki.net/ translatewiki.net], projektu lokalizacji MediaWiki.",
        "editinginterface": "<strong>Ostrzeżenie:</strong> Edytujesz stronę, która zawiera tekst interfejsu oprogramowania.\nZmiany na tej stronie zmienią wygląd interfejsu dla innych użytkowników tej wiki.",
        "translateinterface": "Aby dodać lub zmienić tłumaczenia wszystkich wiki, użyj [//translatewiki.net/ translatewiki.net], projekt lokalizacji oprogramowania MediaWiki.",
index a0cfab2..53f5828 100644 (file)
        "special-characters-title-endash": "Title tooltip for the en dash character (–); See https://en.wikipedia.org/wiki/Dash",
        "special-characters-title-emdash": "Title tooltip for the em dash character (—); See https://en.wikipedia.org/wiki/Dash",
        "special-characters-title-minus": "Title tooltip for the minus sign character (−), not to be confused with a hyphen",
+       "mw-widgets-dateinput-no-date": "Label of a date input field when no date has been selected.",
        "mw-widgets-titleinput-description-new-page": "Description label for a new page in the title input widget.",
        "mw-widgets-titleinput-description-redirect": "Description label for a redirect in the title input widget."
 }
index 87350a8..ccae3bf 100644 (file)
        "actionthrottled": "Azzioni ritardata",
        "actionthrottledtext": "Comu misura di sicurezza contru lu spam, l'esecuzioni di alcuni azzionu è limitata a nu nùmmuru massimu di voti ni nu determinatu piriudu du tempu, limiti ca ni stu casu fu supiratu. Si prega di ripruvari tra qualchi minutu.",
        "protectedpagetext": "Sta pàggina fu bluccata pi privèniri canciamenti o autri opirazzioni.",
-       "viewsourcetext": "È pussìbbili visualizzari e cupiari lu còdici surgenti di sta pàggina:",
-       "viewyourtext": "È pussibbili visualizzarei cupiari lu còdici surgenti dî '''tò canciamenti''' nti sta pàggina:",
+       "viewsourcetext": "Poi taliari e cupiari lu còdici surgenti di sta pàggina.",
+       "viewyourtext": "Poi taliari e cupiari lu còdici surgenti dî <strong>to canciamenti</strong> nti sta pàggina.",
        "protectedinterface": "Sta pàggina cunteni un elementu ca fà parti dâ nterfaccia utenti dû software eggh'è  prutetta p'evitari pussìbbili abbusi. Pi jùnciri o canciari li traduzzioni pi tutti li wiki usari [//translatewiki.net/translatewiki.net] lu pruggettu di lucalizzazzioni di Mediawiki.",
        "editinginterface": "<strong>Accura:</strong> Lu testu di sta pàggina fà parti di l'interfaccia utenti dû situ.\nTutti li canciamenti appurtati a sta pàggina si riflèttinu supra li missaggi visualizzati pi tutti l'utenti di sta wiki.",
        "translateinterface": "Pi' agghiunciri o canciari traduzzioni pi' tutti i wiki, pi' favuri adupirati [//translatewiki.net/ translatewiki.net], lu pruggettu di lucalizzazzioni di MediaWiki.",
        "search-category": "(catigurìa $1)",
        "search-file-match": "(currispunnenza ntô cuntinutu dûn file)",
        "search-suggest": "Forsi circavutu: $1",
+       "search-rewritten": "Sunnu ammustrati li risurtati pi’ $1. Nveci cerca $2.",
        "search-interwiki-caption": "Pruggetti frati",
        "search-interwiki-default": "Risultati di $1:",
        "search-interwiki-more": "(cchiù)",
        "watchlistanontext": "Pi' vìdiri e canciari li vuci dâ to lista taliata hâ' tràsiri.",
        "watchnologin": "Nun hai trasutu",
        "addwatch": "Agghiunci â lista taliata",
-       "addedwatchtext": "La pàggina \"[[:$1]]\" fu' agghiunciuta â to [[Special:Watchlist|lista taliata]].\nI canciamenti futuri a' sta pàggina e â so pàggina di discussioni venirannu elincati cca.",
+       "addedwatchtext": "La pàggina «[[:$1]]» e la so pàggina di discussioni furu agghiunciuti â to [[Special:Watchlist|lista taliata]].",
        "addedwatchtext-short": "La pàggina \"$1\" fu' agghiunciuta â to lista taliata.",
        "removewatch": "Leva dâ lista taliata",
-       "removedwatchtext": "La pàggina \"[[:$1]]\" fu' livata dâ [[Special:Watchlist|to lista taliata]].",
+       "removedwatchtext": "La pàggina «[[:$1]]» e la so pàggina di discussioni furu livati dâ to [[Special:Watchlist|lista taliata]].",
        "removedwatchtext-short": "La pàggina \"$1\" fu' livata dâ to lista taliata.",
        "watch": "Talìa",
        "watchthispage": "Talìa sta pàggina",
index 91794f4..fb8b79b 100644 (file)
        "actionthrottled": "Dejanje zaustavljeno",
        "actionthrottledtext": "Kot ukrep proti smetju, je število izvajanj tega dejanja v časovnem obdobju omejeno, in vi ste ta limit presegli.\nProsimo, poskusite znova čez nekaj minut.",
        "protectedpagetext": "Ta stran je bila zaklenjena za preprečitev urejanja ali drugih dejanj.",
-       "viewsourcetext": "Vsebino te strani si lahko ogledate in kopirate:",
-       "viewyourtext": "Lahko si ogledate in kopirate vsebino '''vaših urejanj''' te strani:",
+       "viewsourcetext": "Vsebino te strani si lahko ogledate in kopirate.",
+       "viewyourtext": "Lahko si ogledate in kopirate vsebino <strong>vaših urejanj</strong> te strani.",
        "protectedinterface": "Prikazana stran vsebuje besedilo vmesnika programja na tem wikiju in je zaradi preprečevanja zlorab zaščitena.\n\nZa dodajanje ali spreminjanje prevodov vseh wikijev uporabite [//translatewiki.net/ translatewiki.net], projekt za lokalizacijo MediaWiki.",
        "editinginterface": "<strong>Opozorilo:</strong> Urejate stran, ki vsebuje besedilo ali drug element uporabniškega vmesnika programja.\nSpremembe te strani bodo vplivale na podobo uporabniškega vmesnika ostalih uporabnikov na tem wikiju.",
        "translateinterface": "Za dodajanje ali spreminjanje prevodov vseh wikijev uporabite [//translatewiki.net/ translatewiki.net], projekt za lokalizacijo MediaWiki.",
index 6e2544d..3eb7b98 100644 (file)
        "actionthrottled": "Обмеження за швидкістю",
        "actionthrottledtext": "Для боротьби зі спамом встановлено обмеження на повторне застосування цієї дії за короткий час. Ви перевищили це обмеження. Можете спробувати знов за кілька хвилин.",
        "protectedpagetext": "Ця сторінка захищена від редагування та інших дій.",
-       "viewsourcetext": "Ð\92и Ð¼Ð¾Ð¶ÐµÑ\82е Ð¿ÐµÑ\80еглÑ\8fнÑ\83Ñ\82и Ñ\82а Ñ\81копÑ\96Ñ\8eваÑ\82и Ð¿Ð¾Ñ\87аÑ\82ковий текст цієї сторінки:",
-       "viewyourtext": "Ви можете переглянути та скопіювати текст '''ваших редагувань''' на цій сторінці:",
+       "viewsourcetext": "Ð\92и Ð¼Ð¾Ð¶ÐµÑ\82е Ð¿ÐµÑ\80еглÑ\8fнÑ\83Ñ\82и Ñ\82а Ñ\81копÑ\96Ñ\8eваÑ\82и Ð²Ð¸Ñ\85Ñ\96дний текст цієї сторінки:",
+       "viewyourtext": "Ви можете переглянути та скопіювати вихідний текст <strong>Ваших редагувань</strong> на цю сторінку.",
        "protectedinterface": "Ця сторінка містить текст інтерфейсу програмного забезпечення цієї Вікі, захищений від небажаного втручання. Щоб додати або змінити переклади для всіх вікі, перейдіть до [//translatewiki.net/ translatewiki.net], проекту локалізації MediaWiki.",
        "editinginterface": "'''Увага:''' Ви редагуєте сторінку, що є частиною текстового інтерфейсу програм. \nЗміни цієї сторінки спричинять зміну інтерфейсу для інших користувачів цієї Вікі.",
        "translateinterface": "Для того, щоб додати чи змінити переклад повідомлень інтерфейсу для всіх вікі-проектів, скористайтеся будь ласка проектом локалізації MediaWiki: [//translatewiki.net/ translatewiki.net].",
        "uploaded-setting-handler-svg": "SVG, який встановлює атрибут «handler» з віддаленою адресою/даними/сценарієм, заблоковано. У завантаженому SVG-файлі знайдено <code>$1=\"$2\"</code>.",
        "uploaded-remote-url-svg": "SVG, який встановлює будь-який атрибут з віддаленим URL, заблоковано. У завантаженому SVG-файлі знайдено <code>$1=\"$2\"</code>.",
        "uploaded-image-filter-svg": "У завантаженому SVG-файлі знайдено фільтр зображення з URL: <code>&lt;$1 $2=\"$3\"&gt;</code>.",
-       "uploadscriptednamespace": "Цей SVG-файл містить недопустимий простір імен \"$1\"",
+       "uploadscriptednamespace": "Цей SVG-файл містить недопустимий простір назв «$1».",
        "uploadinvalidxml": "Не вдалося проаналізувати XML у завантаженому файлі.",
        "uploadvirus": "Файл містить вірус! Див. $1",
        "uploadjava": "Файл є ZIP-архівом, що містить .class-файл Java.\nЗавантаження Java-файлів не дозволене, бо вони можуть використовуватися для обходу системи безпеки.",
        "listgrouprights-removegroup-self": "Можливість вилучити зі свого облікового запису {{PLURAL:$2|1=групу|групи}}: $1",
        "listgrouprights-addgroup-self-all": "Може додавати всі групи до свого облікового запису",
        "listgrouprights-removegroup-self-all": "може вилучати всі групи зі свого облікового запису",
-       "listgrouprights-namespaceprotection-header": "Обмеження простору імен",
-       "listgrouprights-namespaceprotection-namespace": "Простір імен",
+       "listgrouprights-namespaceprotection-header": "Обмеження простору назв",
+       "listgrouprights-namespaceprotection-namespace": "Простір назв",
        "listgrouprights-namespaceprotection-restrictedto": "Права, що дозволяють учаснику редагувати",
        "trackingcategories": "Відстежувані категорії",
        "trackingcategories-summary": "На цій сторінці перераховані відстежують категорії, які заповнюються автоматично програмним забезпеченням MediaWiki. Їх можна перейменувати, змінивши відповідні системні повідомлення в просторі імен {{ns:8}}.",
        "protect-title": "Встановлення захисту для «$1»",
        "protect-title-notallowed": "Перегляд рівню захисту \"$1\"",
        "prot_1movedto2": "«[[$1]]» перейменована на «[[$2]]»",
-       "protect-badnamespace-title": "Ð\91еззаÑ\85иÑ\81ний Ð¿Ñ\80оÑ\81Ñ\82Ñ\96Ñ\80 Ñ\96мен",
-       "protect-badnamespace-text": "Сторінки у просторі імен не можуть бути захищені.",
+       "protect-badnamespace-title": "Ð\9dезаÑ\85иÑ\89Ñ\83ваний Ð¿Ñ\80оÑ\81Ñ\82Ñ\96Ñ\80 Ð½Ð°Ð·Ð²",
+       "protect-badnamespace-text": "Сторінки у цьому просторі назв не можуть бути захищені.",
        "protect-norestrictiontypes-text": "Цю сторінку не може бути захищено, бо немає ніяких типів обмежень.",
        "protect-norestrictiontypes-title": "Сторінка, яку неможливо захистити",
        "protect-legend": "Підтвердження встановлення захисту",
        "tooltip-invert": "Встановіть цей прапорець, щоб приховати зміни на сторінках, в межах обраного простору імен (і пов'язаних просторів імен, за потреби)",
        "tooltip-whatlinkshere-invert": "Поставте цю галочку, щоб приховати зміни на сторінках із обраного простору назв.",
        "namespace_association": "Пов'язаний простір назв",
-       "tooltip-namespace_association": "Встановіть цей прапорець, щоб додати простір імен обговорень, пов'язаних з обраним простором імен",
+       "tooltip-namespace_association": "Встановіть цей прапорець, щоб додати простір назв обговорень, пов'язаних з обраним простором назв",
        "blanknamespace": "(Основний)",
        "contributions": "Внесок {{GENDER:$1|користувача|користувачки}}",
        "contributions-title": "Внесок користувача $1",
index fb0971e..a0c0744 100644 (file)
@@ -1809,6 +1809,7 @@ return array(
                        'oojs-ui',
                ),
                'messages' => array(
+                       'mw-widgets-dateinput-no-date',
                        'mw-widgets-titleinput-description-new-page',
                        'mw-widgets-titleinput-description-redirect',
                ),
index f995229..27c3841 100644 (file)
@@ -944,6 +944,7 @@ h2:lang(te), h3:lang(te), h4:lang(te), h5:lang(te), h6:lang(te) {
 }
 
 /* Localised ordered list numbering for some languages */
+ol:lang(azb) li,
 ol:lang(bcc) li,
 ol:lang(bgn) li,
 ol:lang(bqi) li,
index 276bc65..582a316 100644 (file)
 }
 
 .mw-widget-calendarWidget-day-today {
-       // Intentionally left blank.
+       border: 1px solid #3787fb;
+       border-radius: ((@calendarHeight / 7) / 2);
+       margin: -1px;
 }
 
 .mw-widget-calendarWidget-item-selected {
        &.mw-widget-calendarWidget-day,
        &.mw-widget-calendarWidget-day-heading {
                border-radius: ((@calendarHeight / 7) / 4);
+               // Hide the border from .mw-widget-calendarWidget-day-today
+               border: 0;
+               margin: 0;
        }
 
        &.mw-widget-calendarWidget-month {
index 1820dda..3888fc7 100644 (file)
@@ -16,8 +16,8 @@
         * @constructor
         * @param {Object} [config] Configuration options
         * @cfg {string} [precision='day'] Date precision to use, 'day' or 'month'
-        * @cfg {string|null} [date=null] Day or month date (depending on `precision`), in the
-        *     format 'YYYY-MM-DD' or 'YYYY-MM'. When null, defaults to current date.
+        * @cfg {string} [value] Day or month date (depending on `precision`), in the format 'YYYY-MM-DD'
+        *     or 'YYYY-MM'. If not given or empty string, no date is selected.
         * @cfg {string} [inputFormat] Date format string to use for the textual input field. Displayed
         *     while the widget is active, and the user can type in a date in this format. Should be short
         *     and easy to type. When not given, defaults to 'YYYY-MM-DD' or 'YYYY-MM', depending on
@@ -75,6 +75,7 @@
                        .addClass( 'mw-widget-dateInputWidget' )
                        .append( this.handle.$element, this.textInput.$element, this.calendar.$element );
                // Set handle label and hide stuff
+               this.updateUI();
                this.deactivate();
        };
 
                        value = this.textInput.getValue();
                this.inTextInput++;
                this.textInput.isValid().done( function ( valid ) {
-                       if ( valid ) {
+                       if ( value === '' ) {
+                               // No date selected
+                               widget.setValue( '' );
+                       } else if ( valid ) {
                                // Well-formed date value, parse and set it
                                var mom = moment( value, widget.getInputFormat() );
                                // Use English locale to avoid number formatting
         * @inheritdoc
         */
        mw.widgets.DateInputWidget.prototype.setValue = function ( value ) {
-               if ( value === undefined || value === null ) {
-                       // Default to today
-                       value = this.calendar.getDate();
-               }
-
                var oldValue = this.value;
 
+               if ( !moment( value, this.getInternalFormat() ).isValid() ) {
+                       value = '';
+               }
+
                mw.widgets.DateInputWidget.parent.prototype.setValue.call( this, value );
 
                if ( this.value !== oldValue ) {
-                       if ( !this.inCalendar ) {
-                               this.calendar.setDate( this.getValue() );
-                       }
-                       if ( !this.inTextInput ) {
-                               this.textInput.setValue( this.getMoment().format( this.getInputFormat() ) );
-                       }
+                       this.updateUI();
                }
 
                return this;
        };
 
        /**
-        * Deactivate this input field for data entry. Opens the calendar and shows the text field.
+        * @inheritdoc
+        */
+       mw.widgets.DateInputWidget.prototype.focus = function () {
+               this.activate();
+               return this;
+       };
+
+       /**
+        * @inheritdoc
+        */
+       mw.widgets.DateInputWidget.prototype.blur = function () {
+               this.deactivate();
+               return this;
+       };
+
+       /**
+        * Update the contents of the label, text input and status of calendar to reflect selected value.
         *
         * @private
         */
-       mw.widgets.DateInputWidget.prototype.deactivate = function () {
-               this.textInput.setValue( this.getMoment().format( this.getInputFormat() ) );
-               this.calendar.setDate( this.getValue() );
-               this.handle.setLabel( this.getMoment().format( this.getDisplayFormat() ) );
+       mw.widgets.DateInputWidget.prototype.updateUI = function () {
+               if ( this.getValue() === '' ) {
+                       this.textInput.setValue( '' );
+                       this.calendar.setDate( null );
+                       this.handle.setLabel( mw.msg( 'mw-widgets-dateinput-no-date' ) );
+                       this.$element.addClass( 'mw-widget-dateInputWidget-empty' );
+               } else {
+                       if ( !this.inTextInput ) {
+                               this.textInput.setValue( this.getMoment().format( this.getInputFormat() ) );
+                       }
+                       if ( !this.inCalendar ) {
+                               this.calendar.setDate( this.getValue() );
+                       }
+                       this.handle.setLabel( this.getMoment().format( this.getDisplayFormat() ) );
+                       this.$element.removeClass( 'mw-widget-dateInputWidget-empty' );
+               }
+       };
 
+       /**
+        * Deactivate this input field for data entry. Closes the calendar and hides the text field.
+        *
+        * @private
+        */
+       mw.widgets.DateInputWidget.prototype.deactivate = function () {
                this.$element.removeClass( 'mw-widget-dateInputWidget-active' );
                this.handle.toggle( true );
                this.textInput.toggle( false );
        };
 
        /**
-        * Activate this input field for data entry. Closes the calendar and hides the text field.
+        * Activate this input field for data entry. Opens the calendar and shows the text field.
         *
         * @private
         */
        mw.widgets.DateInputWidget.prototype.activate = function () {
-               this.setValue( this.getValue() );
+               if ( this.getValue() === '' ) {
+                       // Setting today's date is probably more helpful than leaving the widget empty? We could just
+                       // display the placeholder and leave it there, but it's likely that at least the year will be
+                       // the same as today's.
+
+                       // Use English locale to avoid number formatting
+                       this.setValue( moment().locale( 'en' ).format( this.getInternalFormat() ) );
+               }
 
                this.$element.addClass( 'mw-widget-dateInputWidget-active' );
                this.handle.toggle( false );
 
        /**
         * @private
-        * @param {string} date Date string, must be in 'YYYY-MM-DD' or 'YYYY-MM' format to be valid
+        * @param {string} date Date string, to be valid, must be empty (no date selected) or in
+        *     'YYYY-MM-DD' or 'YYYY-MM' format to be valid
         */
        mw.widgets.DateInputWidget.prototype.validateDate = function ( date ) {
+               if ( date === '' ) {
+                       return true;
+               }
+
                // "Half-strict mode": for example, for the format 'YYYY-MM-DD', 2015-1-3 instead of 2015-01-03
                // is okay, but 2015-01 isn't, and neither is 2015-01-foo. Use Moment's "fuzzy" mode and check
                // parsing flags for the details (stoled from implementation of #isValid).
index 33e3406..f87869c 100644 (file)
@@ -39,7 +39,7 @@
                .oo-ui-box-sizing(border-box);
        }
 
-       &.oo-ui-widget-disabled .oo-ui-dropdownWidget-handle {
+       &.oo-ui-widget-disabled .mw-widget-dateInputWidget-handle {
                cursor: default;
        }
 
                border: 1px solid #ccc;
                border-radius: 0.1em;
                line-height: 1.275em;
-
-               &:hover {
-                       border-color: #347bff;
-               }
        }
 
        > .oo-ui-textInputWidget input {
                }
        }
 
-       &:hover .oo-ui-dropdownWidget-handle {
-               border-color: #aaa;
+       &.oo-ui-widget-enabled {
+               .mw-widget-dateInputWidget-handle:hover {
+                       border-color: #347bff;
+               }
        }
 
        &.oo-ui-widget-disabled {
-               .oo-ui-dropdownWidget-handle {
+               .mw-widget-dateInputWidget-handle {
                        color: #ccc;
                        text-shadow: 0 1px 1px #fff;
                        border-color: #ddd;
                        background-color: #f3f3f3;
                }
        }
+
+       &-empty {
+               .mw-widget-dateInputWidget-handle {
+                       color: #ccc;
+               }
+       }
 }
index df4690a..73fa0b5 100644 (file)
@@ -48,10 +48,6 @@ class LessFileCompilationTest extends ResourceLoaderTestCase {
                $this->assertNotNull( $compiler->compileFile( $this->file ) );
        }
 
-       public function getName( $withDataSet = true ) {
-               return $this->toString();
-       }
-
        public function toString() {
                $moduleName = $this->module->getName();
 
index bee44b9..0b38168 100644 (file)
@@ -145,28 +145,26 @@ class OutputPageTest extends MediaWikiTestCase {
                                        . 'document.write("\u003Cscript src=\"http://127.0.0.1:8080/w/load.php?'
                                        . 'debug=false\u0026amp;lang=en\u0026amp;modules=test.foo\u0026amp;only'
                                        . '=scripts\u0026amp;skin=fallback\u0026amp;*\"\u003E\u003C/script\u003E");'
-                                       . "\n} );</script>\n"
+                                       . "\n} );</script>"
                        ),
                        array(
                                // Don't condition wrap raw modules (like the startup module)
                                array( 'test.raw', ResourceLoaderModule::TYPE_SCRIPTS ),
-                               '<script src="http://127.0.0.1:8080/w/load.php?debug=false&amp;lang=en&amp;modules=test.raw&amp;only=scripts&amp;skin=fallback&amp;*"></script>
-'
+                               '<script src="http://127.0.0.1:8080/w/load.php?debug=false&amp;lang=en&amp;modules=test.raw&amp;only=scripts&amp;skin=fallback&amp;*"></script>'
                        ),
                        // Load module styles only
                        // This also tests the order the modules are put into the url
                        array(
                                array( array( 'test.baz', 'test.foo', 'test.bar' ), ResourceLoaderModule::TYPE_STYLES ),
 
-                               '<link rel=stylesheet href="http://127.0.0.1:8080/w/load.php?debug=false&amp;lang=en&amp;modules=test.bar%2Cbaz%2Cfoo&amp;only=styles&amp;skin=fallback&amp;*">
-'
+                               '<link rel=stylesheet href="http://127.0.0.1:8080/w/load.php?debug=false&amp;lang=en&amp;modules=test.bar%2Cbaz%2Cfoo&amp;only=styles&amp;skin=fallback&amp;*">'
                        ),
                        // Load private module (only=scripts)
                        array(
                                array( 'test.quux', ResourceLoaderModule::TYPE_SCRIPTS ),
                                "<script>var RLQ = RLQ || []; RLQ.push( function () {\n"
                                        . "mw.test.baz({token:123});mw.loader.state({\"test.quux\":\"ready\"});\n"
-                                       . "\n} );</script>\n"
+                                       . "\n} );</script>"
                        ),
                        // Load private module (combined)
                        array(
@@ -174,19 +172,17 @@ class OutputPageTest extends MediaWikiTestCase {
                                "<script>var RLQ = RLQ || []; RLQ.push( function () {\n"
                                        . "mw.loader.implement(\"test.quux\",function($,jQuery){"
                                        . "mw.test.baz({token:123});},{\"css\":[\".mw-icon{transition:none}\\n"
-                                       . "\"]});\n\n} );</script>\n"
+                                       . "\"]});\n\n} );</script>"
                        ),
                        // Load module script with ESI
                        array(
                                array( 'test.foo', ResourceLoaderModule::TYPE_SCRIPTS, true ),
-                               '<script><esi:include src="http://127.0.0.1:8080/w/load.php?debug=false&amp;lang=en&amp;modules=test.foo&amp;only=scripts&amp;skin=fallback&amp;*" /></script>
-'
+                               '<script><esi:include src="http://127.0.0.1:8080/w/load.php?debug=false&amp;lang=en&amp;modules=test.foo&amp;only=scripts&amp;skin=fallback&amp;*" /></script>'
                        ),
                        // Load module styles with ESI
                        array(
                                array( 'test.foo', ResourceLoaderModule::TYPE_STYLES, true ),
-                               '<style><esi:include src="http://127.0.0.1:8080/w/load.php?debug=false&amp;lang=en&amp;modules=test.foo&amp;only=styles&amp;skin=fallback&amp;*" /></style>
-',
+                               '<style><esi:include src="http://127.0.0.1:8080/w/load.php?debug=false&amp;lang=en&amp;modules=test.foo&amp;only=styles&amp;skin=fallback&amp;*" /></style>',
                        ),
                        // Load no modules
                        array(
@@ -196,8 +192,7 @@ class OutputPageTest extends MediaWikiTestCase {
                        // noscript group
                        array(
                                array( 'test.noscript', ResourceLoaderModule::TYPE_STYLES ),
-                               '<noscript><link rel=stylesheet href="http://127.0.0.1:8080/w/load.php?debug=false&amp;lang=en&amp;modules=test.noscript&amp;only=styles&amp;skin=fallback&amp;*"></noscript>
-'
+                               '<noscript><link rel=stylesheet href="http://127.0.0.1:8080/w/load.php?debug=false&amp;lang=en&amp;modules=test.noscript&amp;only=styles&amp;skin=fallback&amp;*"></noscript>'
                        ),
                        // Load two modules in separate groups
                        array(
@@ -207,7 +202,7 @@ class OutputPageTest extends MediaWikiTestCase {
                                        . "\n} );</script>\n"
                                        . "<script>var RLQ = RLQ || []; RLQ.push( function () {\n"
                                        . 'document.write("\u003Cscript src=\"http://127.0.0.1:8080/w/load.php?debug=false\u0026amp;lang=en\u0026amp;modules=test.group.foo\u0026amp;skin=fallback\u0026amp;*\"\u003E\u003C/script\u003E");'
-                                       . "\n} );</script>\n"
+                                       . "\n} );</script>"
                        ),
                );
        }
@@ -275,7 +270,7 @@ class OutputPageTest extends MediaWikiTestCase {
                ) );
                $links = $method->invokeArgs( $out, $args );
                // Strip comments to avoid variation due to wgDBname in WikiID and cache key
-               $actualHtml = preg_replace( '#/\*[^*]+\*/#', '', $links['html'] );
+               $actualHtml = preg_replace( '#/\*[^*]+\*/#', '', implode( "\n", $links['html'] ) );
                $this->assertEquals( $expectedHtml, $actualHtml );
        }
 }
diff --git a/tests/phpunit/includes/debug/logger/monolog/LineFormatterTest.php b/tests/phpunit/includes/debug/logger/monolog/LineFormatterTest.php
new file mode 100644 (file)
index 0000000..05c32a0
--- /dev/null
@@ -0,0 +1,68 @@
+<?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
+ */
+
+namespace MediaWiki\Logger\Monolog;
+
+use InvalidArgumentException;
+use LengthException;
+use LogicException;
+use MediaWikiTestCase;
+use TestingAccessWrapper;
+
+class LineFormatterTest extends MediaWikiTestCase {
+
+       /**
+        * @covers LineFormatter::normalizeException
+        */
+       public function testNormalizeExceptionNoTrace() {
+               $fixture = new LineFormatter();
+               $fixture->includeStacktraces( false );
+               $fixture = TestingAccessWrapper::newFromObject( $fixture );
+               $boom = new InvalidArgumentException( 'boom', 0,
+                       new LengthException( 'too long', 0,
+                               new LogicException( 'Spock wuz here' )
+                       )
+               );
+               $out = $fixture->normalizeException( $boom );
+               $this->assertContains( '[Exception InvalidArgumentException]', $out );
+               $this->assertContains( ', [Exception LengthException]', $out );
+               $this->assertContains( ', [Exception LogicException]', $out );
+               $this->assertNotContains( '[stacktrace]', $out );
+       }
+
+       /**
+        * @covers LineFormatter::normalizeException
+        */
+       public function testNormalizeExceptionTrace() {
+               $fixture = new LineFormatter();
+               $fixture->includeStacktraces( true );
+               $fixture = TestingAccessWrapper::newFromObject( $fixture );
+               $boom = new InvalidArgumentException( 'boom', 0,
+                       new LengthException( 'too long', 0,
+                               new LogicException( 'Spock wuz here' )
+                       )
+               );
+               $out = $fixture->normalizeException( $boom );
+               $this->assertContains( '[Exception InvalidArgumentException', $out );
+               $this->assertContains( ', [Exception LengthException]', $out );
+               $this->assertContains( ', [Exception LogicException]', $out );
+               $this->assertContains( '[stacktrace]', $out );
+       }
+}
diff --git a/tests/phpunit/includes/filebackend/SwiftFileBackendTest.php b/tests/phpunit/includes/filebackend/SwiftFileBackendTest.php
new file mode 100644 (file)
index 0000000..38000f6
--- /dev/null
@@ -0,0 +1,91 @@
+<?php
+
+/**
+ * @group FileRepo
+ * @group FileBackend
+ * @group medium
+ */
+class SwiftFileBackendTest extends MediaWikiTestCase {
+       /** @var SwiftFileBackend */
+       private $backend;
+
+       protected function setUp() {
+               parent::setUp();
+
+               $this->backend = TestingAccessWrapper::newFromObject(
+                       new SwiftFileBackend( array(
+                               'name'             => 'local-swift-testing',
+                               'class'            => 'SwiftFileBackend',
+                               'wikiId'           => 'unit-testing',
+                               'lockManager'      => LockManagerGroup::singleton()->get( 'fsLockManager' ),
+                               'swiftAuthUrl'     => 'http://127.0.0.1:8080/auth', // unused
+                               'swiftUser'        => 'test:tester',
+                               'swiftKey'         => 'testing',
+                               'swiftTempUrlKey'  => 'b3968d0207b54ece87cccc06515a89d4' // unused
+                       ) )
+               );
+       }
+
+       /**
+        * @dataProvider provider_testSanitzeHdrs
+        * @covers SwiftFileBackend::sanitzeHdrs
+        */
+       public function testSanitzeHdrs( $raw, $sanitized ) {
+               $hdrs = $this->backend->sanitizeHdrs( array( 'headers' => $raw ) );
+
+               $this->assertEquals( $hdrs, $sanitized, 'sanitizeHdrs() has expected result' );
+       }
+
+       public static function provider_testSanitzeHdrs() {
+               return array(
+                       array(
+                               array(
+                                       'content-length' => 345,
+                                       'content-type'   => 'image+bitmap/jpeg',
+                                       'content-disposition' => 'inline',
+                                       'content-duration' => 35.6363,
+                                       'content-custom' => 'hello',
+                                       'x-content-custom' => 'hello'
+                               ),
+                               array(
+                                       'content-disposition' => 'inline',
+                                       'content-duration' => 35.6363,
+                                       'content-custom' => 'hello',
+                                       'x-content-custom' => 'hello'
+                               )
+                       ),
+                       array(
+                               array(
+                                       'content-length' => 345,
+                                       'content-type'   => 'image+bitmap/jpeg',
+                                       'content-disposition' => 'inline; filename=xxx; ' . str_repeat( 'o', 1024 ),
+                                       'content-duration' => 35.6363,
+                                       'content-custom' => 'hello',
+                                       'x-content-custom' => 'hello'
+                               ),
+                               array(
+                                       'content-disposition' => 'inline;filename=xxx',
+                                       'content-duration' => 35.6363,
+                                       'content-custom' => 'hello',
+                                       'x-content-custom' => 'hello'
+                               )
+                       ),
+                       array(
+                               array(
+                                       'content-length' => 345,
+                                       'content-type'   => 'image+bitmap/jpeg',
+                                       'content-disposition' => 'filename='. str_repeat( 'o', 1024 ) . ';inline',
+                                       'content-duration' => 35.6363,
+                                       'content-custom' => 'hello',
+                                       'x-content-custom' => 'hello'
+                               ),
+                               array(
+                                       'content-disposition' => '',
+                                       'content-duration' => 35.6363,
+                                       'content-custom' => 'hello',
+                                       'x-content-custom' => 'hello'
+                               )
+                       )
+               );
+       }
+}
\ No newline at end of file