Merge "Names.php: Remove U+200E after autonym of language 'lki'"
authorjenkins-bot <jenkins-bot@gerrit.wikimedia.org>
Fri, 18 May 2018 16:42:47 +0000 (16:42 +0000)
committerGerrit Code Review <gerrit@wikimedia.org>
Fri, 18 May 2018 16:42:47 +0000 (16:42 +0000)
109 files changed:
RELEASE-NOTES-1.32
includes/actions/InfoAction.php
includes/api/ApiBase.php
includes/api/ApiCSPReport.php
includes/api/ApiHelp.php
includes/api/ApiMain.php
includes/api/ApiParamInfo.php
includes/api/i18n/ar.json
includes/api/i18n/cs.json
includes/api/i18n/de.json
includes/api/i18n/en.json
includes/api/i18n/fr.json
includes/api/i18n/he.json
includes/api/i18n/it.json
includes/api/i18n/ko.json
includes/api/i18n/pt-br.json
includes/api/i18n/pt.json
includes/api/i18n/qqq.json
includes/api/i18n/ru.json
includes/api/i18n/zh-hans.json
includes/api/i18n/zh-hant.json
includes/htmlform/HTMLFormField.php
includes/libs/CSSMin.php
includes/libs/ReplacementArray.php
includes/libs/objectcache/BagOStuff.php
includes/libs/rdbms/ChronologyProtector.php
includes/specials/SpecialAllPages.php
includes/specials/SpecialApiSandbox.php
includes/specials/SpecialComparePages.php
includes/specials/SpecialEditTags.php
includes/specials/SpecialMovepage.php
includes/specials/SpecialPagesWithProp.php
includes/specials/SpecialPrefixindex.php
includes/specials/SpecialUpload.php
includes/specials/SpecialWatchlist.php
includes/specials/forms/UploadForm.php
includes/title/MediaWikiTitleCodec.php
languages/i18n/ast.json
languages/i18n/be-tarask.json
languages/i18n/cs.json
languages/i18n/cu.json
languages/i18n/de.json
languages/i18n/en.json
languages/i18n/eu.json
languages/i18n/fi.json
languages/i18n/fr.json
languages/i18n/he.json
languages/i18n/hu.json
languages/i18n/inh.json
languages/i18n/ko.json
languages/i18n/lv.json
languages/i18n/mk.json
languages/i18n/nds-nl.json
languages/i18n/nl.json
languages/i18n/pl.json
languages/i18n/pms.json
languages/i18n/pt-br.json
languages/i18n/pt.json
languages/i18n/qqq.json
languages/i18n/ru.json
languages/i18n/sat.json
languages/i18n/sl.json
languages/i18n/sv.json
languages/i18n/yo.json
maintenance/resources/update-ooui.sh
resources/Resources.php
resources/src/jquery.spinner/images/spinner-large.gif [new file with mode: 0644]
resources/src/jquery.spinner/images/spinner.gif [new file with mode: 0644]
resources/src/jquery.spinner/spinner.css [new file with mode: 0644]
resources/src/jquery.spinner/spinner.js [new file with mode: 0644]
resources/src/jquery/images/spinner-large.gif [deleted file]
resources/src/jquery/images/spinner.gif [deleted file]
resources/src/jquery/jquery.spinner.css [deleted file]
resources/src/jquery/jquery.spinner.js [deleted file]
resources/src/mediawiki.Title/Title.js
resources/src/mediawiki.special.apisandbox.styles.css [deleted file]
resources/src/mediawiki.special.apisandbox/apisandbox.js
resources/src/mediawiki.special.changeslist.enhanced.css
resources/src/mediawiki.special.changeslist.visitedstatus.js [deleted file]
resources/src/mediawiki.special.comparepages.styles.less [deleted file]
resources/src/mediawiki.special.edittags.styles.css [deleted file]
resources/src/mediawiki.special.movePage.css [deleted file]
resources/src/mediawiki.special.pagesWithProp.css [deleted file]
resources/src/mediawiki.special.preferences/timezone.js
resources/src/mediawiki.special.upload.styles.css [deleted file]
resources/src/mediawiki.special.watchlist.js [deleted file]
resources/src/mediawiki.special.watchlist.styles.css [deleted file]
resources/src/mediawiki.special.watchlist/visitedstatus.js [new file with mode: 0644]
resources/src/mediawiki.special.watchlist/watchlist.js [new file with mode: 0644]
resources/src/mediawiki.special/apisandbox.css [new file with mode: 0644]
resources/src/mediawiki.special/comparepages.less [new file with mode: 0644]
resources/src/mediawiki.special/edittags.css [new file with mode: 0644]
resources/src/mediawiki.special/mediawiki.special.css [deleted file]
resources/src/mediawiki.special/mediawiki.special.userrights.css [deleted file]
resources/src/mediawiki.special/movePage.css [new file with mode: 0644]
resources/src/mediawiki.special/pagesWithProp.css [new file with mode: 0644]
resources/src/mediawiki.special/special.css [new file with mode: 0644]
resources/src/mediawiki.special/upload.css [new file with mode: 0644]
resources/src/mediawiki.special/userrights.css [new file with mode: 0644]
resources/src/mediawiki.special/watchlist.css [new file with mode: 0644]
tests/parser/parserTests.txt
tests/phan/config.php
tests/phpunit/includes/api/ApiBaseTest.php
tests/phpunit/includes/libs/CSSMinTest.php
tests/phpunit/includes/resourceloader/ResourceLoaderLessVarFileModuleTest.php
tests/phpunit/includes/title/MediaWikiTitleCodecTest.php
tests/phpunit/structure/ApiStructureTest.php
tests/qunit/suites/resources/jquery/jquery.makeCollapsible.test.js
tests/qunit/suites/resources/mediawiki/mediawiki.Title.test.js

index 4c56eec..4663751 100644 (file)
@@ -43,10 +43,20 @@ production.
 * …
 
 === Action API changes in 1.32 ===
-* …
+* Added templated parameters.
+  * A module can define a templated parameter like "{fruit}-quantity", where
+    the actual parameters recognized correspond to the values of a multi-valued
+    parameter. Then clients can make requests like
+    "fruits=apples|bananas&apples-quantity=1&bananas-quantity=5".
+  * action=paraminfo will return templated parameter definitions separately
+    from normal parameters. All parameter definitions now include an "index"
+    key to allow clients to maintain parameter ordering when merging normal and
+    templated parameters.
 
 === Action API internal changes in 1.32 ===
 * Added 'ApiParseMakeOutputPage' hook.
+* Parameter names may no longer contain '{' or '}', as these are now used for
+  templated parameters.
 
 === Languages updated in 1.32 ===
 MediaWiki supports over 350 languages. Many localisations are updated regularly.
@@ -101,6 +111,10 @@ because of Phabricator reports.
   instead.
 
 === Other changes in 1.32 ===
+* Soft hyphens (U+00AD) are now automatically removed from titles; these
+  characters can accidentally end up in copy-and-pasted titles.
+* Strip Unicode 6.3.0 directional formatting characters (U+061C, U+2066,
+  U+2067, U+2068, U+2069) from the title.
 * …
 
 == Compatibility ==
index 0988f73..0a4eae8 100644 (file)
@@ -195,9 +195,14 @@ class InfoAction extends FormlessAction {
        }
 
        /**
-        * Returns page information in an easily-manipulated format. Array keys are used so extensions
-        * may add additional information in arbitrary positions. Array values are arrays with one
-        * element to be rendered as a header, arrays with two elements to be rendered as a table row.
+        * Returns an array of info groups (will be rendered as tables), keyed by group ID.
+        * Group IDs are arbitrary and used so that extensions may add additional information in
+        * arbitrary positions (and as message keys for section headers for the tables, prefixed
+        * with 'pageinfo-').
+        * Each info group is a non-associative array of info items (rendered as table rows).
+        * Each info item is an array with two elements: the first describes the type of
+        * information, the second the value for the current page. Both can be strings (will be
+        * interpreted as raw HTML) or messages (will be interpreted as plain text and escaped).
         *
         * @return array
         */
index 7fafa1f..0802e16 100644 (file)
@@ -226,6 +226,24 @@ abstract class ApiBase extends ContextSource {
         */
        const PARAM_MAX_CHARS = 24;
 
+       /**
+        * (array) Indicate that this is a templated parameter, and specify replacements. Keys are the
+        * placeholders in the parameter name and values are the names of (unprefixed) parameters from
+        * which the replacement values are taken.
+        *
+        * For example, a parameter "foo-{ns}-{title}" could be defined with
+        * PARAM_TEMPLATE_VARS => [ 'ns' => 'namespaces', 'title' => 'titles' ]. Then a query for
+        * namespaces=0|1&titles=X|Y would support parameters foo-0-X, foo-0-Y, foo-1-X, and foo-1-Y.
+        *
+        * All placeholders must be present in the parameter's name. Each target parameter must have
+        * PARAM_ISMULTI true. If a target is itself a templated parameter, its PARAM_TEMPLATE_VARS must
+        * be a subset of the referring parameter's, mapping the same placeholders to the same targets.
+        * A parameter cannot target itself.
+        *
+        * @since 1.32
+        */
+       const PARAM_TEMPLATE_VARS = 25;
+
        /**@}*/
 
        const ALL_DEFAULT_STRING = '*';
@@ -749,15 +767,78 @@ abstract class ApiBase extends ContextSource {
        public function extractRequestParams( $parseLimit = true ) {
                // Cache parameters, for performance and to avoid T26564.
                if ( !isset( $this->mParamCache[$parseLimit] ) ) {
-                       $params = $this->getFinalParams();
+                       $params = $this->getFinalParams() ?: [];
                        $results = [];
-
-                       if ( $params ) { // getFinalParams() can return false
-                               foreach ( $params as $paramName => $paramSettings ) {
+                       $warned = [];
+
+                       // Process all non-templates and save templates for secondary
+                       // processing.
+                       $toProcess = [];
+                       foreach ( $params as $paramName => $paramSettings ) {
+                               if ( isset( $paramSettings[self::PARAM_TEMPLATE_VARS] ) ) {
+                                       $toProcess[] = [ $paramName, $paramSettings[self::PARAM_TEMPLATE_VARS], $paramSettings ];
+                               } else {
                                        $results[$paramName] = $this->getParameterFromSettings(
-                                               $paramName, $paramSettings, $parseLimit );
+                                               $paramName, $paramSettings, $parseLimit
+                                       );
+                               }
+                       }
+
+                       // Now process all the templates by successively replacing the
+                       // placeholders with all client-supplied values.
+                       // This bit duplicates JavaScript logic in
+                       // ApiSandbox.PageLayout.prototype.updateTemplatedParams().
+                       // If you update this, see if that needs updating too.
+                       while ( $toProcess ) {
+                               list( $name, $targets, $settings ) = array_shift( $toProcess );
+
+                               foreach ( $targets as $placeholder => $target ) {
+                                       if ( !array_key_exists( $target, $results ) ) {
+                                               // The target wasn't processed yet, try the next one.
+                                               // If all hit this case, the parameter has no expansions.
+                                               continue;
+                                       }
+                                       if ( !is_array( $results[$target] ) || !$results[$target] ) {
+                                               // The target was processed but has no (valid) values.
+                                               // That means it has no expansions.
+                                               break;
+                                       }
+
+                                       // Expand this target in the name and all other targets,
+                                       // then requeue if there are more targets left or put in
+                                       // $results if all are done.
+                                       unset( $targets[$placeholder] );
+                                       $placeholder = '{' . $placeholder . '}';
+                                       foreach ( $results[$target] as $value ) {
+                                               if ( !preg_match( '/^[^{}]*$/', $value ) ) {
+                                                       // Skip values that make invalid parameter names.
+                                                       $encTargetName = $this->encodeParamName( $target );
+                                                       if ( !isset( $warned[$encTargetName][$value] ) ) {
+                                                               $warned[$encTargetName][$value] = true;
+                                                               $this->addWarning( [
+                                                                       'apiwarn-ignoring-invalid-templated-value',
+                                                                       wfEscapeWikiText( $encTargetName ),
+                                                                       wfEscapeWikiText( $value ),
+                                                               ] );
+                                                       }
+                                                       continue;
+                                               }
+
+                                               $newName = str_replace( $placeholder, $value, $name );
+                                               if ( !$targets ) {
+                                                       $results[$newName] = $this->getParameterFromSettings( $newName, $settings, $parseLimit );
+                                               } else {
+                                                       $newTargets = [];
+                                                       foreach ( $targets as $k => $v ) {
+                                                               $newTargets[$k] = str_replace( $placeholder, $value, $v );
+                                                       }
+                                                       $toProcess[] = [ $newName, $newTargets, $settings ];
+                                               }
+                                       }
+                                       break;
                                }
                        }
+
                        $this->mParamCache[$parseLimit] = $results;
                }
 
@@ -771,9 +852,7 @@ abstract class ApiBase extends ContextSource {
         * @return mixed Parameter value
         */
        protected function getParameter( $paramName, $parseLimit = true ) {
-               $paramSettings = $this->getFinalParams()[$paramName];
-
-               return $this->getParameterFromSettings( $paramName, $paramSettings, $parseLimit );
+               return $this->extractRequestParams( $parseLimit )[$paramName];
        }
 
        /**
index 42d1093..82a7cce 100644 (file)
@@ -47,7 +47,7 @@ class ApiCSPReport extends ApiBase {
 
                $this->verifyPostBodyOk();
                $report = $this->getReport();
-               $flags = $this->getFlags( $report );
+               $flags = $this->getFlags( $report, $userAgent );
 
                $warningText = $this->generateLogLine( $flags, $report );
                $this->logReport( $flags, $warningText, [
@@ -81,9 +81,10 @@ class ApiCSPReport extends ApiBase {
         * Get extra notes about the report.
         *
         * @param array $report The CSP report
+        * @param string $userAgent
         * @return array
         */
-       private function getFlags( $report ) {
+       private function getFlags( $report, $userAgent ) {
                $reportOnly = $this->getParameter( 'reportonly' );
                $source = $this->getParameter( 'source' );
                $falsePositives = $this->getConfig()->get( 'CSPFalsePositiveUrls' );
@@ -137,7 +138,7 @@ class ApiCSPReport extends ApiBase {
        /**
         * Get the report from post body and turn into associative array.
         *
-        * @return Array
+        * @return array
         */
        private function getReport() {
                $postBody = $this->getRequest()->getRawInput();
index 8d24859..bccb338 100644 (file)
@@ -466,6 +466,20 @@ class ApiHelp extends ApiBase {
                                                }
                                        }
 
+                                       // Templated?
+                                       if ( !empty( $settings[ApiBase::PARAM_TEMPLATE_VARS] ) ) {
+                                               $vars = [];
+                                               $msg = 'api-help-param-templated-var-first';
+                                               foreach ( $settings[ApiBase::PARAM_TEMPLATE_VARS] as $k => $v ) {
+                                                       $vars[] = $context->msg( $msg, $k, $module->encodeParamName( $v ) );
+                                                       $msg = 'api-help-param-templated-var';
+                                               }
+                                               $info[] = $context->msg( 'api-help-param-templated' )
+                                                       ->numParams( count( $vars ) )
+                                                       ->params( Message::listParam( $vars ) )
+                                                       ->parse();
+                                       }
+
                                        // Type documentation
                                        if ( !isset( $settings[ApiBase::PARAM_TYPE] ) ) {
                                                $dflt = isset( $settings[ApiBase::PARAM_DFLT] )
index b7b13c5..914d8e9 100644 (file)
@@ -1888,6 +1888,7 @@ class ApiMain extends ApiBase {
                        $help[$k] = $v;
                }
                $help['datatypes'] = '';
+               $help['templatedparams'] = '';
                $help['credits'] = '';
 
                // Fill 'permissions'
@@ -1920,7 +1921,7 @@ class ApiMain extends ApiBase {
                $help['permissions'] .= Html::closeElement( 'dl' );
                $help['permissions'] .= Html::closeElement( 'div' );
 
-               // Fill 'datatypes' and 'credits', if applicable
+               // Fill 'datatypes', 'templatedparams', and 'credits', if applicable
                if ( empty( $options['nolead'] ) ) {
                        $level = $options['headerlevel'];
                        $tocnumber = &$options['tocnumber'];
@@ -1954,6 +1955,35 @@ class ApiMain extends ApiBase {
                                ];
                        }
 
+                       $header = $this->msg( 'api-help-templatedparams-header' )->parse();
+
+                       $id = Sanitizer::escapeIdForAttribute( 'main/templatedparams', Sanitizer::ID_PRIMARY );
+                       $idFallback = Sanitizer::escapeIdForAttribute( 'main/templatedparams', Sanitizer::ID_FALLBACK );
+                       $headline = Linker::makeHeadline( min( 6, $level ),
+                               ' class="apihelp-header">',
+                               $id,
+                               $header,
+                               '',
+                               $idFallback
+                       );
+                       // Ensure we have a sane anchor
+                       if ( $id !== 'main/templatedparams' && $idFallback !== 'main/templatedparams' ) {
+                               $headline = '<div id="main/templatedparams"></div>' . $headline;
+                       }
+                       $help['templatedparams'] .= $headline;
+                       $help['templatedparams'] .= $this->msg( 'api-help-templatedparams' )->parseAsBlock();
+                       if ( !isset( $tocData['main/templatedparams'] ) ) {
+                               $tocnumber[$level]++;
+                               $tocData['main/templatedparams'] = [
+                                       'toclevel' => count( $tocnumber ),
+                                       'level' => $level,
+                                       'anchor' => 'main/templatedparams',
+                                       'line' => $header,
+                                       'number' => implode( '.', $tocnumber ),
+                                       'index' => false,
+                               ];
+                       }
+
                        $header = $this->msg( 'api-credits-header' )->parse();
                        $id = Sanitizer::escapeIdForAttribute( 'main/credits', Sanitizer::ID_PRIMARY );
                        $idFallback = Sanitizer::escapeIdForAttribute( 'main/credits', Sanitizer::ID_FALLBACK );
index bfd3d61..b8a32ae 100644 (file)
@@ -305,16 +305,25 @@ class ApiParamInfo extends ApiBase {
                }
 
                $ret['parameters'] = [];
+               $ret['templatedparameters'] = [];
                $params = $module->getFinalParams( ApiBase::GET_VALUES_FOR_HELP );
                $paramDesc = $module->getFinalParamDescription();
+               $index = 0;
                foreach ( $params as $name => $settings ) {
                        if ( !is_array( $settings ) ) {
                                $settings = [ ApiBase::PARAM_DFLT => $settings ];
                        }
 
                        $item = [
-                               'name' => $name
+                               'index' => ++$index,
+                               'name' => $name,
                        ];
+
+                       if ( !empty( $settings[ApiBase::PARAM_TEMPLATE_VARS] ) ) {
+                               $item['templatevars'] = $settings[ApiBase::PARAM_TEMPLATE_VARS];
+                               ApiResult::setIndexedTagName( $item['templatevars'], 'var' );
+                       }
+
                        if ( isset( $paramDesc[$name] ) ) {
                                $this->formatHelpMessages( $item, 'description', $paramDesc[$name], true );
                        }
@@ -507,9 +516,11 @@ class ApiParamInfo extends ApiBase {
                                ApiResult::setIndexedTagName( $item['info'], 'i' );
                        }
 
-                       $ret['parameters'][] = $item;
+                       $key = empty( $settings[ApiBase::PARAM_TEMPLATE_VARS] ) ? 'parameters' : 'templatedparameters';
+                       $ret[$key][] = $item;
                }
                ApiResult::setIndexedTagName( $ret['parameters'], 'param' );
+               ApiResult::setIndexedTagName( $ret['templatedparameters'], 'param' );
 
                $dynamicParams = $module->dynamicParameterDocumentation();
                if ( $dynamicParams !== null ) {
index f07c6e2..574c94b 100644 (file)
        "apihelp-main-extended-description": "<div class=\"hlist plainlinks api-main-links\">\n* [[mw:Special:MyLanguage/API:Main_page|Documentation]]\n* [[mw:Special:MyLanguage/API:FAQ|FAQ]]\n* [https://lists.wikimedia.org/mailman/listinfo/mediawiki-api Mailing list]\n* [https://lists.wikimedia.org/mailman/listinfo/mediawiki-api-announce API Announcements]\n* [https://phabricator.wikimedia.org/maniphest/query/GebfyV4uCaLd/#R Bugs & requests]\n</div>\n<strong>Status:</strong> يجب أن تعمل جميع الميزات المعروضة في هذه الصفحة، إلا أن واجهة برمجة التطبيقات لا تزال قيد التطوير النشط، وقد تتغير في أي وقت. الاشتراك في\n<strong>Erroneous requests:</strong>عند إرسال طلبات خاطئة إلى api, فالـHTTP سيتم إرسال رأس مع المفتاح \"MediaWiki-API-Error\" ومن ثم سيتم تعيين قيمة رأس ورمز الخطأ المرسل مرة أخرى إلى نفس القيمة. لمزيد من المعلومات، راجع  [[mw:Special:MyLanguage/API:Errors_and_warnings|API: Errors and warnings]].\n<p class=\"mw-apisandbox-link\"><strong>Testing:</strong> لسهولة إختبار طلبات API، انظر [[Special:ApiSandbox]].</p>",
        "apihelp-main-param-action": "أي فعل للعمل.",
        "apihelp-main-param-format": "صيغة الخرج.",
+       "apihelp-main-param-maxlag": "يمكن استخدام التأخر الأقصى عند تثبيت ميدياويكي على قاعدة بيانات مكررة، لحفظ الإجراءات التي تتسبب في أي تأخير أكثر في النسخ المتماثل للموقع; يمكن أن يجعل هذا الوسيط العميل ينتظر حتى يكون تأخر النسخ المتماثل أقل من القيمة المحددة، في حالة التأخير المفرط، يتم إرجاع رمز الخطأ <samp>maxlag</samp> برسالة مثل <samp>Waiting for $host: $lag seconds lagged</samp>،<br />انظر [[mw:Special:MyLanguage/Manual:Maxlag_parameter|دليل: الوسيط maxlag]] لمزيد من المعلومات.",
+       "apihelp-main-param-smaxage": "تعيين رأس التحكم في ذاكرة التخزين المؤقت HTTP <code>s-maxage</code> إلى هذه الثواني العديدة، لا يتم تخزين الأخطاء مؤقتا أبدا.",
+       "apihelp-main-param-maxage": "تعيين رأس التحكم في ذاكرة التخزين المؤقت HTTP <code>max-age</code> إلى هذه الثواني العديدة، لا يتم تخزين الأخطاء مؤقتا أبدا.",
+       "apihelp-main-param-assert": "تحقق من تسجيل دخول المستخدم إذا كان مضبوطا على <kbd>user</kbd>، أو إذا كان لديه صلاحية البوت إذا <kbd>bot</kbd>.",
        "apihelp-main-param-assertuser": "التحقق من أن المستخدم الحالي هو المستخدم المسمى.",
        "apihelp-main-param-requestid": "سيتم إدراج أي قيمة معينة هنا في الاستجابة. يمكن أن تُستخدَم لتمييز الطلبات.",
        "apihelp-main-param-servedby": "تتضمن اسم المضيف الذي الخدم طلب في النتائج.",
        "apihelp-main-param-curtimestamp": "تشمل الطابع الزمني الحالي في النتيجة.",
        "apihelp-main-param-responselanginfo": "تشمل اللغات المستخدمة لأجل <var>uselang</var> and <var>errorlang</var> في النتيجة.",
+       "apihelp-main-param-origin": "عند الوصول إلى API باستخدام طلب AJAX عبر النطاقات (CORS)، اضبطها على النطاق الأصلي، يجب تضمين هذا في أي طلب ما قبل الطيران، وبالتالي يجب أن يكون جزءا من طلب URI (وليس جسم POST). \n\nبالنسبة للطلبات المصادقة، يجب أن يتطابق هذا مع أحد المصادر الموجودة في الرأس<code>Origin</code> بالضبط; لذا يجب تعيينه على شيء مثل<kbd>https://en.wikipedia.org</kbd> أو <kbd>https://meta.wikimedia.org</kbd>، إذا لم يتطابق هذا الوسيط مع الرأس<code>Origin</code>، فسيتم إرجاع استجابة 403، إذا كان هذا الوسيط مطابقا للرأس <code>Origin</code>، ستتم إضافة الأصل إلى القائمة البيضاء، سيتم تعيين الرؤوس <code>Access-Control-Allow-Origin</code> و<code>Access-Control-Allow-Credentials</code>.\n\nبالنسبة للطلبات غير المصادقة، حدد القيمة <kbd>*</kbd>، سيؤدي ذلك إلى تعيين الرأس <code>Access-Control-Allow-Origin</code>، ولكن <code>Access-Control-Allow-Credentials</code> سيكون <code>false</code> وسيتم تقييد كل البيانات الخاصة بالمستخدم.",
+       "apihelp-main-param-uselang": "اللغة المستخدمة لترجمة الرسائل. <kbd>[[Special:ApiHelp/query+siteinfo|action=query&meta=siteinfo]]</kbd> بـ<kbd>siprop=languages</kbd> يقوم بإرجاع قائمة أكواد اللغة، أو تحديد <kbd>user</kbd> لاستخدام تفضيل اللغة للمستخدم الحالي، أو تحديد <kbd>content</kbd> لاستخدام لغة محتوى الويكي هذا.",
+       "apihelp-main-param-errorlang": "لغة لاستخدامها في التحذيرات والأخطاء. <kbd>[[Special:ApiHelp/query+siteinfo|action=query&meta=siteinfo]]</kbd> بـ<kbd>siprop=languages</kbd> يقوم بإرجاع قائمة أكواد اللغة، أو تحديد <kbd>content</kbd> لاستخدام لغة محتوى الويكي هذا، أو تحديد <kbd>uselang</kbd> لاستخدام نفس القيمة كوسيط <var>uselang</var>.",
        "apihelp-main-param-errorsuselocal": "إذا ما أعطيت، النصوص الخطأ ستستخدم الرسائل المخصصة محليا من نطاق {{ns:MediaWiki}}.",
        "apihelp-block-summary": "منع مستخدم.",
        "apihelp-block-param-user": "اسم المستخدم، أو عنوان IP أو نطاق عنوان IP لمنعه. لا يمكن أن يُستخدَم جنبا إلى جنب مع <var>$1userid</var>",
        "apihelp-block-param-userid": "معرف المستخدم لمنعه، لا يمكن أن يُستخدَم جنبا إلى جنب مع <var>$1user</var>",
+       "apihelp-block-param-expiry": "وقت انتهاء الصلاحية، قد يكون نسبيا (على سبيل المثال <kbd>5 months</kbd> أو <kbd>2 weeks</kbd>) أو مطلق (على سبيل المثال <kbd>2014-09-18T12:34:56Z</kbd>)، إذا تم التعيين على <kbd>infinite</kbd> أو <kbd>indefinite</kbd> أو <kbd>never</kbd> فلن تنتهي صلاحية المنع مطلقا.",
        "apihelp-block-param-reason": "السبب للمنع.",
        "apihelp-block-param-anononly": "منع المستخدمين المجهولين فقط (أي تعطيل تعديلات المجهولين من  عنوان IP هذا).",
        "apihelp-block-param-nocreate": "امنع إنشاء الحسابات.",
        "apihelp-compare-param-fromtitle": "العنوان الأول للمقارنة.",
        "apihelp-compare-param-fromid": "رقم الصفحة الأول للمقارنة.",
        "apihelp-compare-param-fromrev": "أول مراجعة للمقارنة.",
+       "apihelp-compare-param-fromtext": "استخدم هذا النص بدلا من محتوى المراجعة المحدد بواسطة <var>fromtitle</var>، <var>fromid</var> أو <var>fromrev</var>.",
+       "apihelp-compare-param-fromsection": "استخدم فقط القسم المحدد في المحتوى 'من' المحدد.",
+       "apihelp-compare-param-frompst": "قم بإجراء تحويل ما قبل الحفظ على <var>fromtext</var>.",
+       "apihelp-compare-param-fromcontentmodel": "نموذج محتوى <var>fromtext</var>، إذا لم يتم توفيره، فسيتم تخمينه استنادا إلى الوسائط الأخرى.",
+       "apihelp-compare-param-fromcontentformat": "تنسيق محتوى تسلسل <var>fromtext</var>.",
        "apihelp-compare-param-totitle": "العنوان الثاني للمقارنة.",
        "apihelp-compare-param-toid": "رقم الصفحة الثاني للمقارنة.",
        "apihelp-compare-param-torev": "المراجعة الثانية للمقارنة.",
+       "apihelp-compare-param-torelative": "استخدم مراجعة متعلقة بالمراجعة المحددة من <var>fromtitle</var> أو <var>fromid</var> أو <var>fromrev</var>، سيتم تجاهل جميع خيارات 'إلى' الأخرى.",
+       "apihelp-compare-param-totext": "استخدم هذا النص بدلا من محتوى المراجعة المحدد بواسطة <var>totitle</var> أو <var>toid</var> أو <var>torev</var>.",
+       "apihelp-compare-param-tosection": "استخدم فقط القسم المحدد في المحتوى 'إلى' المحدد.",
+       "apihelp-compare-param-topst": "قم بإجراء تحويل ما قبل الحفظ على <var>totext</var>.",
+       "apihelp-compare-param-tocontentmodel": "نموذج محتوى <var>totext</var>، إذا لم يتم توفيره، فسيتم تخمينه استنادا إلى الوسائط الأخرى.",
+       "apihelp-compare-param-tocontentformat": "تنسيق محتوى تسلسل <var>totext</var>.",
+       "apihelp-compare-param-prop": "أية قطعة من المعلومات للحصول عليها.",
+       "apihelp-compare-paramvalue-prop-diff": "HTML الفرق.",
+       "apihelp-compare-paramvalue-prop-diffsize": "حجم HTML الفرق، بالبايت.",
+       "apihelp-compare-paramvalue-prop-rel": "معرفات المراجعة السابقة للمراجعة السابقة من 'من' وبعد 'إلى'، إن وُجِدت.",
+       "apihelp-compare-paramvalue-prop-ids": "معرفات الصفحة والمراجعة للمراجعات 'من' و'إلى'.",
+       "apihelp-compare-paramvalue-prop-title": "عناوين صفحات المراجعات 'من' و'إلى'.",
+       "apihelp-compare-paramvalue-prop-user": "المعرف واسم المستخدم للمراجعات 'من' و'إلى'.",
+       "apihelp-compare-paramvalue-prop-comment": "التعليق على المراجعات 'من' و'إلى'.",
+       "apihelp-compare-paramvalue-prop-parsedcomment": "التعليق المحلل على المراجعات 'من' و'إلى'.",
+       "apihelp-compare-paramvalue-prop-size": "حجم المراجعات 'من' و'إلى'.",
        "apihelp-compare-example-1": "إنشاء فرق بين المراجعة 1 و2.",
        "apihelp-createaccount-summary": "انشاء حساب مستخدم جديد",
+       "apihelp-createaccount-param-preservestate": "إذا تم عرض <kbd>[[Special:ApiHelp/query+authmanagerinfo|action=query&meta=authmanagerinfo]]</kbd> بشكل صحيح لـ<samp>hasprimarypreservedstate</samp>، فقد تم تعليم طلبات <samp>primary-required</samp> لكي يجب حذفها، إذا عرضت قيمة غير فارغة لـ<samp>preservedusername</samp> فيجب استخدام اسم المستخدم هذا للوسيط <var>username</var>.",
        "apihelp-createaccount-example-create": "بدء عملية إنشاء المستخدم <kbd>Example</kbd> بكلمة المرور <kbd>ExamplePassword</kbd>.",
        "apihelp-createaccount-param-name": "اسم المستخدم.",
+       "apihelp-createaccount-param-password": "كلمة المرور (يتم تجاهلها إذا تم تعيين <var>$1mailpassword</var>).",
        "apihelp-createaccount-param-domain": "مجال للمصادقة الخارجية (اختياري).",
        "apihelp-createaccount-param-token": "حصلت على رمز إنشاء حساب في الطلب الأول.",
        "apihelp-createaccount-param-email": "عنوان البريد الإلكتروني للمستخدم (اختياري).",
        "apihelp-createaccount-example-mail": "إنشاء مستخدم <kbd>testmailuser</kbd> وأرسل كلمة المرور بالبريد الإلكتروني بشكل عشوائي.",
        "apihelp-cspreport-summary": "مستخدمة من قبل المتصفحات للإبلاغ عن انتهاكات سياسة أمن المحتوى. لا ينبغي أبدا أن تستخدم هذه الوحدة، إلا عند استخدامها تلقائيا باستخدام متصفح ويب CSP متوافق.",
        "apihelp-cspreport-param-reportonly": "علم على أنه تقرير عن سياسة الرصد، وليس فرض سياسة",
+       "apihelp-cspreport-param-source": "ماذا أنشأ رأس CSP الذي تسبب في هذا التقرير",
        "apihelp-delete-summary": "حذف صفحة.",
        "apihelp-delete-param-title": "عنوان الصفحة للحذف. لا يمكن أن يُستخدَم جنبا إلى جنب مع <var>$1pageid</var",
        "apihelp-delete-param-pageid": "معرف الصفحة للحذف. لا يمكن أن يُستخدَم جنبا إلى جنب مع <var>$1pageid</var",
        "apihelp-delete-param-reason": "سبب الحذف. إذا لم يُحدَّد، سوف تُستخدَم أحد الأسباب التي تنشأ تلقائيا.",
        "apihelp-delete-param-tags": "تغيير وسوم لتطبيق الإدخال في سجل الحذف.",
        "apihelp-delete-param-watch": "أضف الصفحة إلى لائحة مراقبة المستعمل الحالي",
+       "apihelp-delete-param-watchlist": "إضافة أو إزالة الصفحة من قائمة مراقبة المستخدم الحالي أو استخدام التفضيلات أو عدم تغيير المراقبة بدون شروط.",
        "apihelp-delete-param-unwatch": "إزالة الصفحة من قائمة المراقبة للمستخدم الحالي.",
        "apihelp-delete-param-oldimage": "اسم الصورة القديمة لحذفها كما هو منصوص عليه [[Special:ApiHelp/query+imageinfo|action=query&prop=imageinfo&iiprop=archivename]].",
        "apihelp-delete-example-simple": "حذف <kbd>Main Page</kbd>.",
        "apihelp-edit-param-nocreate": "يحدث خطأ إذا كانت الصفحة غير موجودة.",
        "apihelp-edit-param-watch": "أضف الصفحة إلى لائحة مراقبة المستعمل الحالي",
        "apihelp-edit-param-unwatch": "إزالة الصفحة من قائمة المراقبة للمستخدم الحالي.",
+       "apihelp-edit-param-watchlist": "إضافة أو إزالة الصفحة من قائمة مراقبة المستخدم الحالي أو استخدام التفضيلات أو عدم تغيير المراقبة بدون شروط.",
+       "apihelp-edit-param-md5": "رمز الرقم MD5 للوسيط $1text، أو الوسائط $1prependtext و$1appendtext متسلسلة، في حالة التعيين، لن يتم التعديل ما لم يكن رمز الرقم صحيحا.",
        "apihelp-edit-param-prependtext": "إضافة هذا النص إلى بداية الصفحة. تجاوز $1text.",
        "apihelp-edit-param-appendtext": "إضافة هذا النص إلى بداية الصفحة. تجاوز $1text.\n\nاستخدم $1section=جديد لحاق القسم الجديد، بدلا من هذا الوسيط.",
        "apihelp-edit-param-undo": "التراجع عن هذه المراجعة. تجاوز $1text, $1prependtext و$1appendtext.",
        "apihelp-edit-param-undoafter": "التراجع عن جميع المراجعات من $1undo لهذه. إذا لم يتم التغيير، تراجع عن تعديل واحد فقط.",
        "apihelp-edit-param-redirect": "حل التحويلات تلقائيا.",
+       "apihelp-edit-param-contentformat": "نسق المحتوى التسلسلي المستخدم لنص المدخلات.",
        "apihelp-edit-param-contentmodel": "نموذج المحتوى للمحتوى الجديد.",
        "apihelp-edit-param-token": "ينبغي دائما أن يُرسَل الرمز كوسيط أخير، أو على الأقل بعد الوسيط $1text.",
        "apihelp-edit-example-edit": "عدل صفحة.",
        "apihelp-expandtemplates-param-title": "عنوان الصفحة.",
        "apihelp-expandtemplates-param-text": "نص ويكي للتحويل.",
        "apihelp-expandtemplates-param-revid": "معرف المراجعة، ل<code><nowiki>{{REVISIONID}}</nowiki></code> والمتغيرات مماثلة.",
+       "apihelp-expandtemplates-param-prop": "أية قطعة من المعلومات للحصول عليها،\n\nلاحظ أنه في حالة عدم تحديد أية قيم، فإن النتيجة ستحتوي على نص ويكي، ولكن سيكون الإخراج بتنسيق موقوف.",
        "apihelp-expandtemplates-paramvalue-prop-wikitext": "نص الويكي الموسع",
+       "apihelp-expandtemplates-paramvalue-prop-categories": "أية تصنيفات موجودة في المدخلات غير ممثلة في مخرجات نص الويكي.",
        "apihelp-expandtemplates-paramvalue-prop-properties": "خصائص الصفحة التي تحددها الكلمات السحرية الموسعة في نص الويكي.",
        "apihelp-expandtemplates-paramvalue-prop-volatile": "إذا كان الإخراج سريع التأثر، ينبغي عدم استخدامه في أي مكان آخر داخل الصفحة.",
+       "apihelp-expandtemplates-paramvalue-prop-ttl": "الحد الأقصى للوقت الذي يجب بعده إبطال ذاكرة التخزين المؤقت للنتيجة.",
        "apihelp-expandtemplates-paramvalue-prop-jsconfigvars": "يعطي متغيرات تكوين جافا سكريبت الخاصة بهذه الصفحة.",
        "apihelp-expandtemplates-paramvalue-prop-encodedjsconfigvars": "يعطي متغيرات تكوين جافا سكريبت الخاصة بهذه الصفحة كسلسلة JSON.",
        "apihelp-expandtemplates-paramvalue-prop-parsetree": "شجرة تحليل XML للمدخلات.",
        "apihelp-feedcontributions-param-newonly": "أظهر إنشاء الصفحات فقط",
        "apihelp-feedcontributions-param-hideminor": "إخفاء التعديلات الطفيفة.",
        "apihelp-feedcontributions-param-showsizediff": "عرض حجم الفرق بين النسخ.",
+       "apihelp-feedcontributions-example-simple": "عودة المساهمات للمستخدم <kbd>Example</kbd>.",
+       "apihelp-feedrecentchanges-summary": "عرض خلاصة أحدث التغييرات.",
        "apihelp-feedrecentchanges-param-feedformat": "هيئة التلقيم.",
        "apihelp-feedrecentchanges-param-namespace": "نطاق لتقييد النتائج.",
        "apihelp-feedrecentchanges-param-invert": "جميع النطاقات عدا المختار.",
        "apihelp-feedwatchlist-summary": "إرجاع تغذية قائمة المراقبة.",
        "apihelp-feedwatchlist-param-feedformat": "هيئة التلقيم.",
        "apihelp-feedwatchlist-param-hours": "صفحات قائمة معدلة ضمن عدة ساعات من الآن.",
+       "apihelp-feedwatchlist-param-linktosections": "الربط مباشرةً بالأقسام التي تم تغييرها إن أمكن.",
        "apihelp-feedwatchlist-example-default": "عرض تغذية قائمة المراقبة.",
        "apihelp-feedwatchlist-example-all6hrs": "اظهر كل التغييرات في اخر 6 ساعات",
        "apihelp-filerevert-summary": "استرجع الملف لنسخة قديمة.",
        "apihelp-filerevert-param-filename": "اسم الملف المستهدف، دون البادئة ملف:.",
        "apihelp-filerevert-param-comment": "تعليق الرفع.",
+       "apihelp-filerevert-param-archivename": "اسم أرشيف المراجعة للعودة إليه.",
        "apihelp-filerevert-example-revert": "استرجاع <kbd>Wiki.png</kbd> لنسحة <kbd>2011-03-05T15:27:40Z</kbd>.",
        "apihelp-help-summary": "عرض مساعدة لوحدات محددة.",
        "apihelp-help-param-modules": "وحدات لعرض مساعدة لها (قيم وسائط <var>action</var> و<var>format</var> أو<kbd>main</kbd>). يمكن تحديد الوحدات الفرعية ب <kbd>+</kbd>.",
        "apihelp-help-example-query": "مساعدة لوحدتي استعلام فرعيتين.",
        "apihelp-imagerotate-summary": "تدوير صورة واحدة أو أكثر.",
        "apihelp-imagerotate-param-rotation": "درجة تدوير الصورة في اتجاه عقارب الساعة.",
+       "apihelp-imagerotate-param-tags": "تنطبق الوسوم على الإدخال في سجل الرفع.",
        "apihelp-imagerotate-example-simple": "تدوير <kbd>File:Example.png</kbd> بمقدار <kbd>90</kbd> درجة.",
        "apihelp-imagerotate-example-generator": "تدوير جميع الصور في <kbd>Category:Flip</kbd> بمقدار <kbd>180</kbd> درجة.",
+       "apihelp-import-summary": "استيراد صفحة من موقع ويكي آخر أو من ملف XML.",
        "apihelp-import-param-summary": "ملخص إدخال سجل الاستيراد.",
        "apihelp-import-param-xml": "ملف XML مرفوع.",
+       "apihelp-import-param-interwikiprefix": "بالنسبة للواردات المرفوعة: بادئة إنترويكي لتطبيقها على أسماء مستخدمين غير معروفة (والمستخدمين المعروفين إذا تم تعيين <var>$1assignknownusers</var>).",
+       "apihelp-import-param-assignknownusers": "تعيين تعديلات للمستخدمين المحليين حيث يوجد المستخدم المحدد محليا.",
        "apihelp-import-param-interwikisource": "بالنسبة لواردات الإنترويكي: ويكي للاستيراد منه.",
        "apihelp-import-param-interwikipage": "بالنسبة لواردات الإنترويكي: صفحة لاستيرادها.",
        "apihelp-import-param-fullhistory": "بالنسبة لواردات الإنترويكي: استيراد التاريخ كاملا، وليست النسخة الحالية فقط.",
        "apihelp-import-param-templates": "بالنسبة لواردات الإنترويكي: الإستيراد شمل كافة القوالب كذلك.",
        "apihelp-import-param-namespace": "استيراد إلى هذا النطاق. لا يمكن أن يُستخدَم إلى جانب <var>$1rootpage</var>.",
        "apihelp-import-param-rootpage": "استيراد كصفحة فرعية لهذه الصفحة. لا يمكن أن يُستخدَم إلى جانب <var>$1rootpage</var>.",
+       "apihelp-import-param-tags": "تغيير الوسوم لتطبيقها على الإدخال في سجل الاستيراد وعلى المراجعة الخالية في الصفحات المستوردة.",
        "apihelp-import-example-import": "استيراد [[meta:Help:ParserFunctions]] للنطاق 100 بالتاريخ الكامل.",
        "apihelp-linkaccount-summary": "ربط حساب من موفر طرف ثالث للمستخدم الحالي.",
        "apihelp-linkaccount-example-link": "بدء عملية ربط حساب من <kbd>Example</kbd>.",
index 90af65f..c69f267 100644 (file)
        "api-help-param-required": "Tento parametr je povinný.",
        "api-help-datatypes-header": "Datové typy",
        "api-help-datatypes": "Vstupem do MediaWiki by mělo být UTF-8 normalizované do NFC. Jiný vstup se MediaWiki může pokusit převést, ale tím se může stát, že některé operace (např. [[Special:ApiHelp/edit|editace]] s kontrolou MD5) selžou.\n\nNěkteré typy parametrů v API potřebují bližší vysvětlení:\n;boolean\n:Booleovské parametry fungují jako zaškrtávací políčka v HTML: pokud je parametr uveden, bez ohledu na hodnotu, je považován za pravdivý. Pro nepravdivou hodnotu parametr zcela vynechte.\n;časová značka\n:Časové značky lze uvádět v několika formátech. Doporučuje se datum a čas podle ISO 8601. Všechny časy jsou v UTC a obsažené časové pásmo je ignorováno.\n:* Datum a čas podle ISO 8601, <kbd><var>2001</var>-<var>01</var>-<var>15</var>T<var>14</var>:<var>56</var>:<var>00</var>Z</kbd> (interpunkce a <kbd>Z</kbd> jsou nepovinné)\n:* Datum a čas podle ISO 8601 s (ignorovaným) zlomkem sekundy, <kbd><var>2001</var>-<var>01</var>-<var>15</var>T<var>14</var>:<var>56</var>:<var>00</var>.<var>00001</var>Z</kbd> (pomlčky, dvojtečky a <kbd>Z</kbd> jsou nepovinné)\n:* Formát MediaWiki, <kbd><var>2001</var><var>01</var><var>15</var><var>14</var><var>56</var><var>00</var></kbd>\n:* Obecný číselný formát, <kbd><var>2001</var>-<var>01</var>-<var>15</var> <var>14</var>:<var>56</var>:<var>00</var></kbd> (nepovinné časové pásmo <kbd>GMT</kbd>, <kbd>+<var>##</var></kbd> nebo <kbd>-<var>##</var></kbd> se ignoruje)\n:* Formát EXIF, <kbd><var>2001</var>:<var>01</var>:<var>15</var> <var>14</var>:<var>56</var>:<var>00</var></kbd>\n:* Formát podle RFC 2822 (časové pásmo lze vynechat), <kbd><var>Mon</var>, <var>15</var> <var>Jan</var> <var>2001</var> <var>14</var>:<var>56</var>:<var>00</var></kbd>\n:* Formát podle RFC 850 (časové pásmo lze vynechat), <kbd><var>Monday</var>, <var>15</var>-<var>Jan</var>-<var>2001</var> <var>14</var>:<var>56</var>:<var>00</var></kbd>\n:* Formát podle céčkové funkce ctime, <kbd><var>Mon</var> <var>Jan</var> <var>15</var> <var>14</var>:<var>56</var>:<var>00</var> <var>2001</var></kbd>\n:* Sekundy od 1970-01-01T00:00:00Z jako celé číslo o 1–13 číslicích (s výjimkou <kbd>0</kbd>)\n:* Řetězec <kbd>now</kbd>\n;alternativní oddělovač vícenásobných hodnot\n:Parametry, které přijímají několik hodnot, se zpravidla předávají s hodnotami oddělenými svislítkem, např. <kbd>param=hodnota1|hodnota2</kbd> nebo <kbd>param=hodnota1%7Chodnota2</kbd>. Pokud musí hodnota obsahovat svislítko, použijte jako oddělovač znak U+001F (Unit Separator) ''a'' před hodnotu přidejte U+001F, např. <kbd>param=%1Fhodnota1%1Fhodnota2</kbd>.",
+       "api-help-templatedparams-header": "Šablonované parametry",
+       "api-help-templatedparams": "Šablonované parametry umožňují situace, kdy modul API potřebuje hodnotu pro každou hodnotu nějakého jiného parametru. Pokud by například existoval modul API pro získání ovoce, mohl by mít parametr <var>ovoce</var>, kterým se určí požadované druhy ovoce, a šablonovaný parametr <var>{ovoce}-počet</var>, kterým se určí požadované počty jednotlivých druhů. Klient API, který by chtěl 1 jablko, 5 banánů a 20 jahod, by mohl vytvořit požadavek <kbd>ovoce=jablka|banány|jahody&jablka-počet=1&banány-počet=5&jahody-počet=20</kbd>.",
        "api-help-param-type-integer": "Typ: {{PLURAL:$1|1=celé číslo|2=seznam celých čísel}}",
        "api-help-param-type-boolean": "Typ: boolean ([[Special:ApiHelp/main#main/datatypes|podrobnosti]])",
        "api-help-param-list": "{{PLURAL:$1|1=Jedna z následujících hodnot|2=Hodnoty (oddělené <kbd>{{!}}</kbd> nebo [[Special:ApiHelp/main#main/datatypes|alternativou]].)}}: $2",
index b1eee12..86a22e6 100644 (file)
        "apihelp-query+iwbacklinks-paramvalue-prop-iwtitle": "Ergänzt den Titel des Interwikis.",
        "apihelp-query+iwbacklinks-param-dir": "Die Auflistungsrichtung.",
        "apihelp-query+iwbacklinks-example-simple": "Ruft Seiten ab, die auf [[wikibooks:Test]] verlinken.",
+       "apihelp-query+iwlinks-summary": "Gibt alle Interwikilinks der angegebenen Seiten zurück.",
        "apihelp-query+iwlinks-param-prop": "Zusätzlich zurückzugebende Eigenschaften jedes Interlanguage-Links:",
        "apihelp-query+iwlinks-paramvalue-prop-url": "Ergänzt die vollständige URL.",
        "apihelp-query+iwlinks-param-limit": "Wie viele Interwiki-Links zurückgegeben werden sollen.",
        "api-help-parameters": "{{PLURAL:$1|Parameter}}:",
        "api-help-param-deprecated": "Veraltet.",
        "api-help-param-required": "Dieser Parameter ist erforderlich.",
+       "api-help-param-templated": "Dies ist ein [[Special:ApiHelp/main#main/templatedparams|Vorlagenparameter]]. Bei der Erstellung der Anfrage $2.",
+       "api-help-param-templated-var-first": "<var>&#x7B;$1&#x7D;</var> im Parameternamen sollte mit Werten von <var>$2</var> ersetzt werden",
+       "api-help-param-templated-var": "<var>&#x7B;$1&#x7D;</var> mit Werten von <var>$2</var>",
        "api-help-datatypes-header": "Datentypen",
+       "api-help-templatedparams-header": "Vorlagenparameter",
        "api-help-param-type-limit": "Typ: Ganzzahl oder <kbd>max</kbd>",
        "api-help-param-type-integer": "Typ: {{PLURAL:$1|1=Ganzzahl|2=Liste von Ganzzahlen}}",
        "api-help-param-type-boolean": "Typ: boolesch ([[Special:ApiHelp/main#main/datatypes|Einzelheiten]])",
        "apierror-unknownerror-nocode": "Unbekannter Fehler.",
        "apierror-unknownerror": "Unbekannter Fehler: „$1“.",
        "apierror-unknownformat": "Nicht erkanntes Format „$1“.",
+       "apiwarn-ignoring-invalid-templated-value": "Ignorieren des Wertes <kbd>$2</kbd> in <var>$1</var> bei der Verarbeitung von Vorlagenparametern.",
        "apiwarn-invalidcategory": "„$1“ ist keine Kategorie.",
        "apiwarn-invalidtitle": "„$1“ ist kein gültiger Titel.",
        "apiwarn-notfile": "„$1“ ist keine Datei.",
index 6838e54..573d37c 100644 (file)
        "api-help-parameters": "{{PLURAL:$1|Parameter|Parameters}}:",
        "api-help-param-deprecated": "Deprecated.",
        "api-help-param-required": "This parameter is required.",
+       "api-help-param-templated": "This is a [[Special:ApiHelp/main#main/templatedparams|templated parameter]]. When making the request, $2.",
+       "api-help-param-templated-var-first": "<var>&#x7B;$1&#x7D;</var> in the parameter's name should be replaced with values of <var>$2</var>",
+       "api-help-param-templated-var": "<var>&#x7B;$1&#x7D;</var> with values of <var>$2</var>",
        "api-help-datatypes-header": "Data types",
        "api-help-datatypes": "Input to MediaWiki should be NFC-normalized UTF-8. MediaWiki may attempt to convert other input, but this may cause some operations (such as [[Special:ApiHelp/edit|edits]] with MD5 checks) to fail.\n\nSome parameter types in API requests need further explanation:\n;boolean\n:Boolean parameters work like HTML checkboxes: if the parameter is specified, regardless of value, it is considered true. For a false value, omit the parameter entirely.\n;timestamp\n:Timestamps may be specified in several formats. ISO 8601 date and time is recommended. All times are in UTC, any included timezone is ignored.\n:* ISO 8601 date and time, <kbd><var>2001</var>-<var>01</var>-<var>15</var>T<var>14</var>:<var>56</var>:<var>00</var>Z</kbd> (punctuation and <kbd>Z</kbd> are optional)\n:* ISO 8601 date and time with (ignored) fractional seconds, <kbd><var>2001</var>-<var>01</var>-<var>15</var>T<var>14</var>:<var>56</var>:<var>00</var>.<var>00001</var>Z</kbd> (dashes, colons, and <kbd>Z</kbd> are optional)\n:* MediaWiki format, <kbd><var>2001</var><var>01</var><var>15</var><var>14</var><var>56</var><var>00</var></kbd>\n:* Generic numeric format, <kbd><var>2001</var>-<var>01</var>-<var>15</var> <var>14</var>:<var>56</var>:<var>00</var></kbd> (optional timezone of <kbd>GMT</kbd>, <kbd>+<var>##</var></kbd>, or <kbd>-<var>##</var></kbd> is ignored)\n:* EXIF format, <kbd><var>2001</var>:<var>01</var>:<var>15</var> <var>14</var>:<var>56</var>:<var>00</var></kbd>\n:*RFC 2822 format (timezone may be omitted), <kbd><var>Mon</var>, <var>15</var> <var>Jan</var> <var>2001</var> <var>14</var>:<var>56</var>:<var>00</var></kbd>\n:* RFC 850 format (timezone may be omitted), <kbd><var>Monday</var>, <var>15</var>-<var>Jan</var>-<var>2001</var> <var>14</var>:<var>56</var>:<var>00</var></kbd>\n:* C ctime format, <kbd><var>Mon</var> <var>Jan</var> <var>15</var> <var>14</var>:<var>56</var>:<var>00</var> <var>2001</var></kbd>\n:* Seconds since 1970-01-01T00:00:00Z as a 1 to 13 digit integer (excluding <kbd>0</kbd>)\n:* The string <kbd>now</kbd>\n;alternative multiple-value separator\n:Parameters that take multiple values are normally submitted with the values separated using the pipe character, e.g. <kbd>param=value1|value2</kbd> or <kbd>param=value1%7Cvalue2</kbd>. If a value must contain the pipe character, use U+001F (Unit Separator) as the separator ''and'' prefix the value with U+001F, e.g. <kbd>param=%1Fvalue1%1Fvalue2</kbd>.",
+       "api-help-templatedparams-header": "Templated parameters",
+       "api-help-templatedparams": "Templated parameters support cases where an API module needs a value for each value of some other parameter. For example, if there were an API module to request fruit, it might have a parameter <var>fruits</var> to specify which fruits are being requested and a templated parameter <var>{fruit}-quantity</var> to specify how many of each fruit to request. An API client that wants 1 apple, 5 bananas, and 20 strawberries could then make a request like <kbd>fruits=apples|bananas|strawberries&apples-quantity=1&bananas-quantity=5&strawberries-quantity=20</kbd>.",
        "api-help-param-type-limit": "Type: integer or <kbd>max</kbd>",
        "api-help-param-type-integer": "Type: {{PLURAL:$1|1=integer|2=list of integers}}",
        "api-help-param-type-boolean": "Type: boolean ([[Special:ApiHelp/main#main/datatypes|details]])",
        "apiwarn-difftohidden": "Couldn't diff to r$1: content is hidden.",
        "apiwarn-errorprinterfailed": "Error printer failed. Will retry without params.",
        "apiwarn-errorprinterfailed-ex": "Error printer failed (will retry without params): $1",
+       "apiwarn-ignoring-invalid-templated-value": "Ignoring value <kbd>$2</kbd> in <var>$1</var> when processing templated parameters.",
        "apiwarn-invalidcategory": "\"$1\" is not a category.",
        "apiwarn-invalidtitle": "\"$1\" is not a valid title.",
        "apiwarn-invalidxmlstylesheetext": "Stylesheet should have <code>.xsl</code> extension.",
index 5ce2331..ab3f430 100644 (file)
        "api-help-parameters": "{{PLURAL:$1|Paramètre|Paramètres}} :",
        "api-help-param-deprecated": "Désuet.",
        "api-help-param-required": "Ce paramètre est obligatoire.",
+       "api-help-param-templated": "Ceci est un [[Special:ApiHelp/main#main/templatedparams|paramètre de modèle]]. En faisant une requête, $2.",
+       "api-help-param-templated-var-first": "<var>&#x7B;$1&#x7D;</var> dans le nom du paramètre doit être remplacé par des valeurs de <var>$2</var>",
+       "api-help-param-templated-var": "<var>&#x7B;$1&#x7D;</var> par les valeurs de <var>$2</var>",
        "api-help-datatypes-header": "Type de données",
        "api-help-datatypes": "Les entrées dans MédiaWiki doivent être en UTF-8 à la norme NFC. MédiaWiki peut tenter de convertir d’autres types d’entrée, mais cela peut faire échouer certaines opérations (comme les [[Special:ApiHelp/edit|modifications]] avec contrôles MD5) to fail.\n\nCertains types de paramètre dans les requêtes de l’API nécessitent plus d’explication :\n;boolean\n:Les paramètres booléens fonctionnent comme des cases à cocher HTML : si le paramètre est spécifié, quelle que soit sa valeur, il est considéré comme vrai. Pour une valeur fausse, enlever complètement le paramètre.\n;timestamp\n:Les horodatages peuvent être spécifiés sous différentes formes. Date et heure ISO 8601 est recommandé. Toutes les heures sont en UTC, tout fuseau horaire inclus est ignoré.\n:* Date et heure ISO 8601, <kbd><var>2001</var>-<var>01</var>-<var>15</var>T<var>14</var>:<var>56</var>:<var>00</var>Z</kbd> (la ponctuation et <kbd>Z</kbd> sont facultatifs)\n:* Date et heure ISO 8601 avec fractions de seconde (ignorées), <kbd><var>2001</var>-<var>01</var>-<var>15</var>T<var>14</var>:<var>56</var>:<var>00</var>.<var>00001</var>Z</kbd> (tirets, deux-points et <kbd>Z</kbd> sont facultatifs)\n:* Format MédiaWiki, <kbd><var>2001</var><var>01</var><var>15</var><var>14</var><var>56</var><var>00</var></kbd>\n:* Format numérique générique, <kbd><var>2001</var>-<var>01</var>-<var>15</var> <var>14</var>:<var>56</var>:<var>00</var></kbd> (fuseau horaire facultatif en <kbd>GMT</kbd>, <kbd>+<var>##</var></kbd>, ou <kbd>-<var>##</var></kbd> sont ignorés)\n:* Format EXIF, <kbd><var>2001</var>:<var>01</var>:<var>15</var> <var>14</var>:<var>56</var>:<var>00</var></kbd>\n:*Format RFC 2822 (le fuseau horaire est facultatif), <kbd><var>Mon</var>, <var>15</var> <var>Jan</var> <var>2001</var> <var>14</var>:<var>56</var>:<var>00</var></kbd>\n:* Format RFC 850 (le fuseau horaire est facultatif), <kbd><var>Monday</var>, <var>15</var>-<var>Jan</var>-<var>2001</var> <var>14</var>:<var>56</var>:<var>00</var></kbd>\n:* Format ctime C, <kbd><var>Mon</var> <var>Jan</var> <var>15</var> <var>14</var>:<var>56</var>:<var>00</var> <var>2001</var></kbd>\n:* Secondes depuis 1970-01-01T00:00:00Z sous forme d’entier de 1 à 13 chiffres (sans <kbd>0</kbd>)\n:* La chaîne <kbd>now</kbd>",
+       "api-help-templatedparams-header": "Paramètres de modèle",
+       "api-help-templatedparams": "Les paramètres de modèle supportent les cas où un module d’API a besoin d’une valeur pour chaque valeur d’un autre paramètre quelconque. Par exemple, s’il y avait un module d’API pour demander un fruit, il pourrait avoir un paramètre <var>fruits</var> pour spécifier quels fruits sont demandés et un paramètre de modèle <var>{fruit}-quantité</var> pour spécifier combien de chaque fruit demander. Un client de l’API qui voudrait une pomme, cinq bananes et vingt fraises pourrait alors faire une requête comme <kbd>fruits=pommes|bananes|fraises&pommes-quantité=1&bananes-quantité=5&fraises-quantité=20</kbd>.",
        "api-help-param-type-limit": "Type : entier ou <kbd>max</kbd>",
        "api-help-param-type-integer": "Type : {{PLURAL:$1|1=entier|2=liste d’entiers}}",
        "api-help-param-type-boolean": "Type : booléen ([[Special:ApiHelp/main#main/datatypes|détails]])",
        "apiwarn-difftohidden": "Impossible de faire un diff avec r$1 : le contenu est masqué.",
        "apiwarn-errorprinterfailed": "Erreur échec imprimante. Nouvel essai sans paramètres.",
        "apiwarn-errorprinterfailed-ex": "Erreur d’échec de l’impression (réessayera sans paramètres) : $1",
+       "apiwarn-ignoring-invalid-templated-value": "Ignorer la valeur <kbd>$2</kbd> dans <var>$1</var> en traitant les paramètres de modèle.",
        "apiwarn-invalidcategory": "« $1 » n'est pas une catégorie.",
        "apiwarn-invalidtitle": "« $1 » n’est pas un titre valide.",
        "apiwarn-invalidxmlstylesheetext": "Une feuille de style doit avoir une extension <code>.xsl</code>.",
index d044ecb..911ac2f 100644 (file)
        "api-help-parameters": "{{PLURAL:$1|פרמטר|פרמטרים}}:",
        "api-help-param-deprecated": "מיושן.",
        "api-help-param-required": "פרמטר זה נדרש.",
+       "api-help-param-templated": "זהו  [[Special:ApiHelp/main#main/templatedparams|פרמטר בתבנית]]. בעת ביצוע הבקשה, $2.",
+       "api-help-param-templated-var-first": "יש להחליף את הטקסט <var>&#x7B;$1&#x7D;</var> (בשם הפרמטר) עם הערכים של הפרמטר <var>$2</var>",
+       "api-help-param-templated-var": "<var>&#x7B;$1&#x7D;</var> עם הערכים של הפרמטר <var>$2</var>",
        "api-help-datatypes-header": "סוגי נתונים",
        "api-help-datatypes": "קלט למדיה־ויקי צריך להיות בקידוד UTF-8 מנורמל ב־NFC. מדיה־ויקי יכולה לנסות להמיר קלט אחר, אבל זה עלול לגרום לפעולות מסוימות (כגון [[Special:ApiHelp/edit|עריכות]] עם בדיקות MD5) להיכשל.\n\nחלק מסוגי הפרמטרים בבקשות API דורשים הסבר נוסף:\n;בוליאני (boolean)\n:פרמטרים בוליאניים עובדים כמו תיבות סימון של HTML: אם הפרמטר צוין, בלי קשר לערך שלו, הוא אמת (true). בשביל ערך שקר (false), יש להשמיט את הפרמטר לגמרי.\n;חותם־זמן (timestamp)\n:אפשר לכתוב חותמי־זמן במספר תסדירים. תאריך ושעה לפי ISO 8601 הוא הדבר המומלת. כל הזמנים מצוינים ב־ UTC, לא תהיה השפעה לשום אזור זמן שיצוין.\n:* תאריך ושעה לפי ISO 8601‏, <kbd><var>2001</var>-<var>01</var>-<var>15</var>T<var>14</var>:<var>56</var>:<var>00</var>Z</kbd> (לא חובה לכתוב פיסוק ו־<kbd>Z</kbd>)\n:* תאריך ושעה לפי ISO 8601 עם חלקי שנייה (שלא תהיה להם שום השפעה), <kbd><var>2001</var>-<var>01</var>-<var>15</var>T<var>14</var>:<var>56</var>:<var>00</var>.<var>00001</var>Z</kbd> (לא חובה לכתוב קווים מפרידים, נקודתיים ו־<kbd>Z</kbd>)\n:* תסדיר MediaWiki‏, <kbd><var>2001</var><var>01</var><var>15</var><var>14</var><var>56</var><var>00</var></kbd>\n:* תסדיר מספרי כללי, <kbd><var>2001</var>-<var>01</var>-<var>15</var> <var>14</var>:<var>56</var>:<var>00</var></kbd> (לאזור זמן אופציונלי של <kbd>GMT</kbd>‏, <kbd dir=\"ltr\">+<var>##</var></kbd>, או <kbd dir=\"ltr\">-<var>##</var></kbd> אין השפעה)\n:* תסדיר EXIF‏, <kbd><var>2001</var>:<var>01</var>:<var>15</var> <var>14</var>:<var>56</var>:<var>00</var></kbd>\n:* תסדיר RFC 2822 (אפשר להשמיט את אזור הזמן), <kbd><var>Mon</var>, <var>15</var> <var>Jan</var> <var>2001</var> <var>14</var>:<var>56</var>:<var>00</var></kbd>\n:* תסדיר RFC 850 (אפשר להשמיט את אזור הזמן), <kbd><var>Monday</var>, <var>15</var>-<var>Jan</var>-<var>2001</var> <var>14</var>:<var>56</var>:<var>00</var></kbd>\n:* תסדיר C ctime‏, <kbd><var>Mon</var> <var>Jan</var> <var>15</var> <var>14</var>:<var>56</var>:<var>00</var> <var>2001</var></kbd>\n:* שניות מאז 1970-01-01T00:00:00Z בתור מספר שלך בין 1 ל־13 (לא כולל <kbd>0</kbd>)\n:* המחרוזת <kbd>now</kbd>\n;מפריד ערכים מרובים חלופי\n:פרמטרים שלוקחים ערכים מרובים בדרך־כלל נשלחים עם הערכים מופרדים באמצעות תו מקל, למשל <kbd>param=value1|value2</kbd> או <kbd>param=value1%7Cvalue2</kbd>. אם הערך צריך להכיל את תו המקל, יש להשתמש ב־U+001F (מפריד יחידות) בתור המפריד ''וגם'' להוסיף לתחילת הערך U+001F, למשל <kbd>param=%1Fvalue1%1Fvalue2</kbd>.",
+       "api-help-templatedparams-header": "פרמטרים בתבניות",
+       "api-help-templatedparams": "התכונה \"פרמטרים בתבניות\" תומכת במקרים שבהם מודול של API זקוק לערך כלשהו עבור ערכים של פרמטרים אחרים. למשל, אם היה מודול API לבקשת פרי, ייתכן שהוא היה זקוק לפרמטר בשם <var>פירות</var> על־מנת לציין מהם הפירות המבוקשים, ולפרמטר בתבנית בשם <var>{פרי}-כמות</var> על־מנת לציין את הכמות של כל פרי עבור הבקשה. לשם כך, לקוח API שמעוניין לקבל תפוח אחד, 5 בננות ו־20 תותים יכול היה ליצור בקשה בסגנון <kbd>פירות=תפוחים|בננות|תותים&תפוחים-כמות=1&בננות-כמות=5&תותים-כמות=20</kbd>.",
        "api-help-param-type-limit": "סוג: מספר שלם או <kbd>max</kbd>",
        "api-help-param-type-integer": "סוג: {{PLURAL:$1|1=מספר שלם|2=רשימת מספרים שלמים}}",
        "api-help-param-type-boolean": "סוג: בוליאני ([[Special:ApiHelp/main#main/datatypes|פרטים]])",
        "apiwarn-difftohidden": "לא היה אפשר לעשות השוואה עם גרסה $1: התוכן מוסתר.",
        "apiwarn-errorprinterfailed": "מדפיס השגיאות לא עבד. ינסה שוב ללא פרמטרים.",
        "apiwarn-errorprinterfailed-ex": "מדפיס השגיאות לא עבד (ינסה שוב ללא פרמטרים): $1",
+       "apiwarn-ignoring-invalid-templated-value": "לא ייעשה שימוש בערך <kbd>$2</kbd> שבפרמטר <var>$1</var> בעת עיבוד הפרמטרים בתבנית.",
        "apiwarn-invalidcategory": "\"$1\" אינה קטגוריה.",
        "apiwarn-invalidtitle": "\"$1\" אינה כותרת תקינה.",
        "apiwarn-invalidxmlstylesheetext": "לגיליון הסגנונות אמורה להיות הסיומת <code dir=\"ltr\">.xsl</code>.",
index 38d2901..8811177 100644 (file)
        "api-help-parameters": "{{PLURAL:$1|Parametro|Parametri}}:",
        "api-help-param-deprecated": "Deprecato.",
        "api-help-param-required": "Questo parametro è obbligatorio.",
+       "api-help-param-templated-var": "<var>&#x7B;$1&#x7D;</var> con valori di <var>$2</var>",
        "api-help-datatypes-header": "Tipi di dato",
+       "api-help-templatedparams-header": "Parametri template",
        "api-help-param-type-limit": "Tipo: intero o <kbd>max</kbd>",
        "api-help-param-type-integer": "Tipo: {{PLURAL:$1|1=intero|2=elenco di interi}}",
        "api-help-param-type-boolean": "Tipo: booleano ([[Special:ApiHelp/main#main/datatypes|dettagli]])",
index 354e75c..79a33ae 100644 (file)
        "api-help-param-required": "이 변수는 필수 입력 사항입니다.",
        "api-help-datatypes-header": "데이터 유형",
        "api-help-datatypes": "API 요청 내 몇몇 매개변수형에 대해 더 자세히 설명해보겠습니다:\n;boolean\n:Boolean 매개변수들은 HTML 체크박스처럼 동작합니다: 만약 매개변수가 지정되었다면, 값에 상관없이 참의 값으로 여겨집니다. 거짓값은 매개변수 전체를 생략하세요.\n;timestamp\n:타임스탬프들은 여러 형식으로 표현될 수 있으나 ISO 8601 날짜와 시간이 추천됩니다. 모든 시간은 UTC이어야 하며, 포함된 시간대는 모두 무시됩니다.\n:* ISO 8601 날짜와 시간, <kbd><var>2001</var>-<var>01</var>-<var>15</var>T<var>14</var>:<var>56</var>:<var>00</var>Z</kbd> (구두점과 <kbd>Z</kbd>는 선택입니다.)\n:* ISO 8601 날짜와 시간과 (무시되는) 소수 초, <kbd><var>2001</var>-<var>01</var>-<var>15</var>T<var>14</var>:<var>56</var>:<var>00</var>.<var>00001</var>Z</kbd> (대시, 콜론과 <kbd>Z</kbd>는 선택입니다.)\n:* 미디어위키 형식, <kbd><var>2001</var><var>01</var><var>15</var><var>14</var><var>56</var><var>00</var></kbd>\n:* 일반적인 수 형식 <kbd><var>2001</var>-<var>01</var>-<var>15</var> <var>14</var>:<var>56</var>:<var>00</var></kbd> (<kbd>GMT</kbd>, <kbd>+<var>##</var></kbd>, 또는 <kbd>-<var>##</var></kbd>와 같은 선택적 시간대는 무시됩니다)\n:*RFC 2822 형식 (시간대는 생략될 수 있음), <kbd><var>Mon</var>, <var>15</var> <var>Jan</var> <var>2001</var> <var>14</var>:<var>56</var>:<var>00</var></kbd>\n:* RFC 850 형식 (시간대는 생략될 수 있음), <kbd><var>Monday</var>, <var>15</var>-<var>Jan</var>-<var>2001</var> <var>14</var>:<var>56</var>:<var>00</var></kbd>\n:* C ctime 형식, <kbd><var>Mon</var> <var>Jan</var> <var>15</var> <var>14</var>:<var>56</var>:<var>00</var> <var>2001</var></kbd>\n:* 1부터 13자리까지의 숫자로 표현된 1970-01-01T00:00:00Z부터 흐른 시간(초) (<kbd>0</kbd>을 제외)\n:* 문자열 <kbd>now</kbd>",
+       "api-help-templatedparams-header": "틀 변수",
        "api-help-param-type-limit": "유형: 정수 또는 <kbd>max</kbd>",
        "api-help-param-type-integer": "유형: {{PLURAL:$1|1=정수|2=정수 목록}}",
        "api-help-param-type-boolean": "유형: 불리언 ([[Special:ApiHelp/main#main/datatypes|자세한 정보]])",
index 1445647..df7ea51 100644 (file)
        "api-help-parameters": "{{PLURAL:$1|Parâmetro|Parâmetros}}:",
        "api-help-param-deprecated": "Obsoleto.",
        "api-help-param-required": "Este parâmetro é obrigatório.",
+       "api-help-param-templated": "Este parâmetro é um [[Special:ApiHelp/main#main/templatedparams|parâmetro de predefinição]]. Ao fazer o pedido, $2.",
+       "api-help-param-templated-var-first": "<var>&#x7B;$1&#x7D;</var> no nome do parâmetro deve ser substituído com os valores de <var>$2</var>",
+       "api-help-param-templated-var": "<var>&#x7B;$1&#x7D;</var> com valores de <var>$2</var>",
        "api-help-datatypes-header": "Tipos de dados",
        "api-help-datatypes": "A entrada para MediaWiki deve ser UTF-8 normalizada pelo NFC. O MediaWiki pode tentar converter outra entrada, mas isso pode causar a falha de algumas operações (como [[Special:ApiHelp/edit|editar]] com verificações MD5).\n\nAlguns tipos de parâmetros em solicitações de API precisam de uma explicação adicional:\n;boolean\n:Os parâmetros booleanos funcionam como caixas de seleção HTML: se o parâmetro for especificado, independentemente do valor, é considerado verdadeiro. Para um valor falso, omita o parâmetro inteiramente.\n;timestamp\n: As marcas de tempo podem ser especificadas em vários formatos. É recomendada a data e a hora ISO 8601. Todos os horários estão em UTC, qualquer fuso horário incluído é ignorado.\n:* Data e hora ISO 8601, <kbd><var>2001</var>-<var>01</var>-<var>15</var>T<var>14</var>:<var>56</var>:<var>00</var>Z</kbd> (pontuação e <kbd>Z</kbd> são opcionais)\n:* ISO 8601 data e hora com segundos fracionados (ignorados), <kbd><var>2001</var>-<var>01</var>-<var>15</var>T<var>14</var>:<var>56</var>:<var>00</var>.<var>00001</var>Z</kbd> (traços, dois pontos e <kbd>Z</kbd> são opcionais)\n:* Formato MediaWiki, <kbd><var>2001</var><var>01</var><var>15</var><var>14</var><var>56</var><var>00</var></kbd>\n:* Formato numérico genérico, <kbd><var>2001</var>-<var>01</var>-<var>15</var> <var>14</var>:<var>56</var>:<var>00</var></kbd> (fuso horário opcional de <kbd>GMT</kbd>, <kbd>+<var>##</var></kbd> ou <kbd>-<var>##</var></kbd> é ignorado)\n:* Formato EXIF, <kbd><var>2001</var>:<var>01</var>:<var>15</var> <var>14</var>:<var>56</var>:<var>00</var></kbd>\n:* Formato RFC 2822 (o fuso horário pode ser omitido), <kbd><var>Mon</var>, <var>15</var> <var>Jan</var> <var>2001</var> <var>14</var>:<var>56</var>:<var>00</var></kbd>\n:* Formato RFC 850 (fuso horário Pode ser omitido), <kbd><var>Monday</var>, <var>15</var>-<var>Jan</var>-<var>2001</var> <var>14</var>:<var>56</var>:<var>00</var></kbd>\n:* C ctime format, <kbd><var>Mon</var> <var>Jan</var> <var>15</var> <var>14</var>:<var>56</var>:<var>00</var> <var>2001</var></kbd>\n:* Segundos desde 1970-01-01T00:00:00Z como um inteiro de 1 a 13 dígitos (excluindo <kbd>0</kbd>)\n:* A string <kbd>now</kbd>\n; valor múltiplo alternativo separador\n: Os parâmetros que levam vários valores são normalmente enviados com os valores separados usando o caractere do pipe, por exemplo <kbd>param=value1|value2</kbd> ou <kbd>param=value1%7Cvalue2</kbd>. Se um valor deve conter o caractere de pipe, use U+001F (separador de unidade) como o separador ''and'' prefixa o valor com U+001F, por exemplo, <kbd>param=%1Fvalue1%1Fvalue2</kbd>.",
+       "api-help-templatedparams-header": "Parâmetros da predefinição",
+       "api-help-templatedparams": "Os parâmetros modelados usam-se nos casos em que um módulo da API necessita de um valor para cada valor de um outro parâmetro. Por exemplo, se existisse um módulo da API para encomendar fruta, poderia ter um parâmetro <var>frutas</var> para especificar as frutas que estão a ser encomendadas e um parâmetro modelado <var>quantidade-de-{fruta}</var> para especificar quanto de cada fruta. Um cliente da API que pretenda 1 maçã, 5 bananas e 20 morangos pode então fazer um pedido como <kbd>frutas=maçãs|bananas|morangos&quantidade-de-maçãs=1&quantidade-de-bananas=5&quantidade-de-morangos=20</kbd>.",
        "api-help-param-type-limit": "Tipo: inteiro ou <kbd>max</kbd>",
        "api-help-param-type-integer": "Tipo: {{PLURAL:$1|1=inteiro|2=lista de inteiros}}",
        "api-help-param-type-boolean": "Tipo: boleano ([[Special:ApiHelp/main#main/datatypes|details]])",
        "apiwarn-difftohidden": "Não foi possível diferenciar r$1: o conteúdo está oculto.",
        "apiwarn-errorprinterfailed": "Falha na impressora de erro. Repetirá sem parâmetros.",
        "apiwarn-errorprinterfailed-ex": "Falha na impressora de erro (repetirá sem parâmetros): $1",
+       "apiwarn-ignoring-invalid-templated-value": "Ignorando o valor <kbd>$2</kbd> em <var>$1</var> ao processar parâmetros de predefinição.",
        "apiwarn-invalidcategory": "\"$1\" não é uma categoria.",
        "apiwarn-invalidtitle": "\"$1\" não é um título válido.",
        "apiwarn-invalidxmlstylesheetext": "Stylesheet deve ter extensão <code>.xsl</code>.",
index 2a81d29..9adb8b9 100644 (file)
        "api-help-parameters": "{{PLURAL:$1|Parâmetro|Parâmetros}}:",
        "api-help-param-deprecated": "Obsoleto.",
        "api-help-param-required": "Este parâmetro é obrigatório.",
+       "api-help-param-templated": "Este parâmetro é um [[Special:ApiHelp/main#main/templatedparams|parâmetro modelado]]. Ao fazer o pedido, $2.",
+       "api-help-param-templated-var-first": "<var>&#x7B;$1&#x7D;</var> no nome do parâmetro deve ser substituído com os valores de <var>$2</var>",
+       "api-help-param-templated-var": "<var>&#x7B;$1&#x7D;</var> com valores de <var>$2</var>",
        "api-help-datatypes-header": "Tipo de dados",
        "api-help-datatypes": "O formato de entrada para o MediaWiki deve ser UTF-8, normalizado de acordo com a norma NFC. O MediaWiki pode converter outros tipos de entrada, mas esta conversão pode originar a falha de algumas operações (tais como as [[Special:ApiHelp/edit|edições]] com verificações MD5).\n\nAlguns tipos de parâmetros nos pedidos à API necessitam de mais explicações:\n;boolean\n:Os parâmetros booleanos funcionam como as caixas de seleção HTML: se o parâmetro for especificado, independentemente do seu valor, é considerado verdadeiro. Para um valor falso, omitir o parâmetro completo.\n;timestamp\n:As datas e horas podem ser especificadas em vários formatos. É recomendado o formato ISO 8601. Todas as horas estão em UTC, qualquer inclusão do fuso horário é ignorada.\n:* Data e hora ISO 8601, <kbd><var>2001</var>-<var>01</var>-<var>15</var>T<var>14</var>:<var>56</var>:<var>00</var>Z</kbd> (pontuação e <kbd>Z</kbd> são opcionais)\n:* Data e hora ISO 8601 com segundos fracionários (estes são ignorados), <kbd><var>2001</var>-<var>01</var>-<var>15</var>T<var>14</var>:<var>56</var>:<var>00</var>.<var>00001</var>Z</kbd> (traços, dois pontos e <kbd>Z</kbd> são opcionais)\n:* Formato do MediaWiki, <kbd><var>2001</var><var>01</var><var>15</var><var>14</var><var>56</var><var>00</var></kbd>\n:* Formato numérico genérico, <kbd><var>2001</var>-<var>01</var>-<var>15</var> <var>14</var>:<var>56</var>:<var>00</var></kbd> (fuso horário opcional <kbd>GMT</kbd>, <kbd>+<var>##</var></kbd>, ou <kbd>-<var>##</var></kbd> são ignorados)\n:* Formato EXIF, <kbd><var>2001</var>:<var>01</var>:<var>15</var> <var>14</var>:<var>56</var>:<var>00</var></kbd>\n:*Formato RFC 2822 (o fuso horário pode ser omitido), <kbd><var>Mon</var>, <var>15</var> <var>Jan</var> <var>2001</var> <var>14</var>:<var>56</var>:<var>00</var></kbd>\n:* Formato RFC 850 (o fuso horário pode ser omitido), <kbd><var>Monday</var>, <var>15</var>-<var>Jan</var>-<var>2001</var> <var>14</var>:<var>56</var>:<var>00</var></kbd>\n:* Formato C ctime, <kbd><var>Mon</var> <var>Jan</var> <var>15</var> <var>14</var>:<var>56</var>:<var>00</var> <var>2001</var></kbd>\n:* Segundos desde 1970-01-01T00:00:00Z como um inteiro de 1 a 13 algarismos (excluindo <kbd>0</kbd>)\n:* O texto <kbd>now</kbd>\n;separador alternativo de valores múltiplos\n:Os parâmetros que aceitam vários valores são normalmente fornecidos com os valores separados por uma barra vertical (''pipe''), por exemplo <kbd>parâmetro=valor1|valor2</kbd> ou <kbd>parâmetro=valor1%7Cvalor2</kbd>. Se um valor contém a barra vertical, use como separador o U+001F (Separador de Unidades) ''e'' prefixe o valor com U+001F, isto é, <kbd>parâmetro=%1Fvalor1%1Fvalor2</kbd>.",
+       "api-help-templatedparams-header": "Parâmetros modelados",
+       "api-help-templatedparams": "Os parâmetros modelados usam-se nos casos em que um módulo da API necessita de um valor para cada valor de um outro parâmetro. Por exemplo, se existisse um módulo da API para encomendar fruta, poderia ter um parâmetro <var>frutas</var> para especificar as frutas que estão a ser encomendadas e um parâmetro modelado <var>quantidade-de-{fruta}</var> para especificar quanto de cada fruta. Um cliente da API que pretenda 1 maçã, 5 bananas e 20 morangos pode então fazer um pedido como <kbd>frutas=maçãs|bananas|morangos&quantidade-de-maçãs=1&quantidade-de-bananas=5&quantidade-de-morangos=20</kbd>.",
        "api-help-param-type-limit": "Tipo: inteiro ou <kbd>max</kbd>",
        "api-help-param-type-integer": "Tipo: {{PLURAL:$1|1=inteiro|2=lista de números inteiros}}",
        "api-help-param-type-boolean": "Tipo: booleano ([[Special:ApiHelp/main#main/datatypes|detalhes]])",
        "apiwarn-difftohidden": "Não foi possível criar uma lista das diferenças em relação à r$1: o conteúdo está ocultado.",
        "apiwarn-errorprinterfailed": "A impressora de erros falhou. Será feita nova tentativa sem parâmetros.",
        "apiwarn-errorprinterfailed-ex": "A impressora de erros falhou (será feita nova tentativa sem parâmetros): $1",
+       "apiwarn-ignoring-invalid-templated-value": "A ignorar o valor <kbd>$2</kbd> em <var>$1</var> ao processar parâmetros modelados.",
        "apiwarn-invalidcategory": "\"$1\" não é uma categoria.",
        "apiwarn-invalidtitle": "\"$1\" não é um título válido.",
        "apiwarn-invalidxmlstylesheetext": "Uma folha de estilos deve ter a extensão <code>.xsl</code>.",
index 594bf8e..086e74b 100644 (file)
        "api-help-parameters": "Label for the API help parameters section\n\nParameters:\n* $1 - Number of parameters to be displayed\n{{Identical|Parameter}}",
        "api-help-param-deprecated": "Displayed in the API help for any deprecated parameter\n{{Identical|Deprecated}}",
        "api-help-param-required": "Displayed in the API help for any required parameter",
+       "api-help-param-templated": "Displayed in the API help for any templated parameter.\n\nParameters:\n* $1 - Count of template variables in the parameter name.\n* $2 - A list, composed using {{msg-mw|comma-separator}} and {{msg-mw|and}}, of the template variables in the parameter name. The first is formatted using {{msg-mw|api-help-param-templated-var-first|notext=1}} and the rest use {{msg-mw|api-help-param-templated-var|notext=1}}.\n\nSee also:\n* {{msg-mw|api-help-param-templated-var-first}}\n* {{msg-mw|api-help-param-templated-var}}",
+       "api-help-param-templated-var-first": "Used with {{msg-mw|api-help-param-templated|notext=1}} to display templated parameter replacement variables. See that message for context.\n\nParameters:\n* $1 - Variable.\n* $2 - Parameter from which values are taken.\n\nSee also:\n* {{msg-mw|api-help-param-templated}}\n* {{msg-mw|api-help-param-templated-var}}",
+       "api-help-param-templated-var": "Used with {{msg-mw|api-help-param-templated|notext=1}} to display templated parameter replacement variables. See that message for context.\n\nParameters:\n* $1 - Variable.\n* $2 - Parameter from which values are taken.\n\nSee also:\n* {{msg-mw|api-help-param-templated}}\n* {{msg-mw|api-help-param-templated-var-first}}",
        "api-help-datatypes-header": "Header for the data type section in the API help output",
        "api-help-datatypes": "{{technical}} {{doc-important|Do not translate or reformat dates inside <nowiki><kbd></kbd></nowiki> or <nowiki><var></var></nowiki> tags}} Documentation of certain API data types\nSee also:\n* [[Special:PrefixIndex/MediaWiki:api-help-param-type]]",
+       "api-help-templatedparams-header": "Header for the \"templated parameters\" section in the API help output.",
+       "api-help-templatedparams": "{{technical}} {{doc-important|Unlike in other API messages, feel free to localize the words \"fruit\", \"fruits\", \"quantity\", \"apples\", \"bananas\", and \"strawberries\" in this message even when inside <nowiki><kbd></kbd></nowiki> or <nowiki><var></var></nowiki> tags. Do not change the punctuation, only the words.}} Documentation for the \"templated parameters\" feature.",
        "api-help-param-type-limit": "{{technical}} {{doc-important|Do not translate text inside &lt;kbd&gt; tags}} Used to indicate that a parameter is a \"limit\" type. Parameters:\n* $1 - Always 1.\nSee also:\n* {{msg-mw|api-help-datatypes}}\n* [[Special:PrefixIndex/MediaWiki:api-help-param-type]]",
        "api-help-param-type-integer": "{{technical}} Used to indicate that a parameter is an integer or list of integers. Parameters:\n* $1 - 1 if the parameter takes one value, 2 if the parameter takes a list of values.\nSee also:\n* {{msg-mw|api-help-datatypes}}\n* [[Special:PrefixIndex/MediaWiki:api-help-param-type]]",
        "api-help-param-type-boolean": "{{technical}} {{doc-important|Do not translate <code>Special:ApiHelp</code> in this message.}} Used to indicate that a parameter is a boolean. Parameters:\n* $1 - Always 1.\nSee also:\n* {{msg-mw|api-help-datatypes}}\n* [[Special:PrefixIndex/MediaWiki:api-help-param-type]]",
        "apiwarn-difftohidden": "{{doc-apierror}}\n\nParameters:\n* $1 - Revision ID number.\n\n\"r\" is short for \"revision\". You may translate it.",
        "apiwarn-errorprinterfailed": "{{doc-apierror}}",
        "apiwarn-errorprinterfailed-ex": "{{doc-apierror}}\n\nParameters:\n* $1 - Exception message, which may already end in punctuation. Probably in English.",
+       "apiwarn-ignoring-invalid-templated-value": "{{doc-apierror}}\n\nParameters:\n* $1 - Target parameter having a bad value.\n* $2 - The bad value being ignored.",
        "apiwarn-invalidcategory": "{{doc-apierror}}\n\nParameters:\n* $1 - Supplied category name.",
        "apiwarn-invalidtitle": "{{doc-apierror}}\n\nParameters:\n* $1 - Supplied title.",
        "apiwarn-invalidxmlstylesheetext": "{{doc-apierror}}",
index 7c8c169..db93d47 100644 (file)
        "apihelp-query+info-paramvalue-prop-readable": "Может ли участник просматривать эту страницу.",
        "apihelp-query+info-paramvalue-prop-preload": "Текст, возвращённый EditFormPreloadText.",
        "apihelp-query+info-paramvalue-prop-displaytitle": "Возвращает стиль отображения заголовка страницы.",
+       "apihelp-query+info-paramvalue-prop-varianttitles": "Выдаёт отображаемый заголовок во всех вариантах языка контента сайта.",
        "apihelp-query+info-param-testactions": "Проверить, может ли текущий участник провести указанные действия над страницей.",
        "apihelp-query+info-param-token": "Вместо этого используйте [[Special:ApiHelp/query+tokens|action=query&meta=tokens]].",
        "apihelp-query+info-example-simple": "Получить информацию о странице <kbd>Main Page</kbd>.",
index fba891b..f335890 100644 (file)
@@ -23,7 +23,8 @@
                        "Myy730",
                        "D41D8CD98F",
                        "Umherirrender",
-                       "NeverBehave"
+                       "NeverBehave",
+                       "Wbxshiori"
                ]
        },
        "apihelp-main-extended-description": "<div class=\"hlist plainlinks api-main-links\">\n* [[mw:Special:MyLanguage/API:Main_page|文档]]\n* [[mw:Special:MyLanguage/API:FAQ|常见问题]]\n* [https://lists.wikimedia.org/mailman/listinfo/mediawiki-api 邮件列表]\n* [https://lists.wikimedia.org/mailman/listinfo/mediawiki-api-announce API公告]\n* [https://phabricator.wikimedia.org/maniphest/query/GebfyV4uCaLd/#R 程序错误与功能请求]\n</div>\n<strong>状态信息:</strong>MediaWiki API是一个成熟稳定的,不断受到支持和改进的界面。尽管我们尽力避免,但偶尔也需要作出重大更新;请订阅[https://lists.wikimedia.org/pipermail/mediawiki-api-announce/ mediawiki-api-announce 邮件列表]以便获得更新通知。\n\n<strong>错误请求:</strong>当API收到错误请求时,HTTP header将会返回一个包含\"MediaWiki-API-Error\"的值,随后header的值与error code将会送回并设置为相同的值。详细信息请参阅[[mw:Special:MyLanguage/API:Errors_and_warnings|API:错误与警告]]。\n\n<p class=\"mw-apisandbox-link\"><strong>测试中:</strong>测试API请求的易用性,请参见[[Special:ApiSandbox]]。</p>",
        "api-help-parameters": "{{PLURAL:$1|参数}}:",
        "api-help-param-deprecated": "已弃用。",
        "api-help-param-required": "这个参数是必须的。",
+       "api-help-param-templated": "这是一个[[Special:ApiHelp/main#main/templatedparams|模板参数]]。当做出请求时,$2。",
+       "api-help-param-templated-var-first": "参数名中的<var>&#x7B;$1&#x7D;</var>应替换为<var>$2</var>的值",
+       "api-help-param-templated-var": "<var>&#x7B;$1&#x7D;</var>与<var>$2</var>的值",
        "api-help-datatypes-header": "数据类型",
        "api-help-datatypes": "至MediaWiki的输入应为NFC标准化的UTF-8。MediaWiki可以尝试转换其他输入,但这可能导致一些操作失败(例如带MD5校验[[Special:ApiHelp/edit|编辑]])。\n\n一些在API请求中的参数类型需要更进一步解释:\n;boolean\n:布尔参数就像HTML复选框一样工作:如果指定参数,无论何值都被认为是真。如果要假值,则可完全忽略参数。\n;timestamp\n:时间戳可被指定为很多格式。推荐使用ISO 8601日期和时间标准。所有时间为UTC时间,包含的任何时区会被忽略。\n:* ISO 8601日期和时间,<kbd><var>2001</var>-<var>01</var>-<var>15</var>T<var>14</var>:<var>56</var>:<var>00</var>Z</kbd>(标点和<kbd>Z</kbd>是可选项)\n:* 带小数秒(会被忽略)的ISO 8601日期和时间,<kbd><var>2001</var>-<var>01</var>-<var>15</var>T<var>14</var>:<var>56</var>:<var>00</var>.<var>00001</var>Z</kbd>(破折号、冒号和<kbd>Z</kbd>是可选的)\n:* MediaWiki格式,<kbd><var>2001</var><var>01</var><var>15</var><var>14</var><var>56</var><var>00</var></kbd>\n:* 一般数字格式,<kbd><var>2001</var>-<var>01</var>-<var>15</var> <var>14</var>:<var>56</var>:<var>00</var></kbd>(<kbd>GMT</kbd>、<kbd>+<var>##</var></kbd>或<kbd>-<var>##</var></kbd>的可选时区会被忽略)\n:* EXIF格式,<kbd><var>2001</var>:<var>01</var>:<var>15</var> <var>14</var>:<var>56</var>:<var>00</var></kbd>\n:* RFC 2822格式(时区可省略),<kbd><var>Mon</var>, <var>15</var> <var>Jan</var> <var>2001</var> <var>14</var>:<var>56</var>:<var>00</var></kbd>\n:* RFC 850格式(时区可省略),<kbd><var>Monday</var>, <var>15</var>-<var>Jan</var>-<var>2001</var> <var>14</var>:<var>56</var>:<var>00</var></kbd>\n:* C ctime格式,<kbd><var>Mon</var> <var>Jan</var> <var>15</var> <var>14</var>:<var>56</var>:<var>00</var> <var>2001</var></kbd>\n:* 从1970-01-01T00:00:00Z开始的秒数,作为1到13位数的整数(除了<kbd>0</kbd>)\n:* 字符串<kbd>now</kbd>\n;替代多值分隔符\n:使用多个值的参数通常会与管道符号分隔的值一起提交,例如<kbd>param=value1|value2</kbd>或<kbd>param=value1%7Cvalue2</kbd>。如果值必须包含管道符号,使用U+001F(单位分隔符)作为分隔符,''并''在值前加前缀U+001F,例如<kbd>param=%1Fvalue1%1Fvalue2</kbd>。",
+       "api-help-templatedparams-header": "模板参数",
+       "api-help-templatedparams": "模板参数支持API模块需要为每个其他参数赋值的情况。例如如果有API模块请求水果,它会有参数<var>水果</var>指定请求的水果,以及模板参数<var>{水果}-数量</var>以指定每种水果请求多少。需要1个苹果、5个香蕉和20个草莓的API客户端可以做出类似<kbd>水果=苹果|香蕉|草莓&苹果-数量=1&香蕉-数量=5&草莓-数量=20</kbd>的请求。",
        "api-help-param-type-limit": "类型:整数或<kbd>max</kbd>",
        "api-help-param-type-integer": "类型:{{PLURAL:$1|1=整数|2=整数列表}}",
        "api-help-param-type-boolean": "类型:布尔值([[Special:ApiHelp/main#main/datatypes|详细信息]])",
        "api-help-authmanager-general-usage": "使用此模块的一般程序是:\n# 通过<kbd>amirequestsfor=$4</kbd>取得来自<kbd>[[Special:ApiHelp/query+authmanagerinfo|action=query&meta=authmanagerinfo]]</kbd>的可用字段,和来自<kbd>[[Special:ApiHelp/query+tokens|action=query&meta=tokens]]</kbd>的<kbd>$5</kbd>令牌。\n# 向用户显示字段,并获得其提交的内容。\n# 发送(POST)至此模块,提供<var>$1returnurl</var>及任何相关字段。\n# 在响应中检查<samp>status</samp>。\n#* 如果您收到了<samp>PASS</samp>(成功)或<samp>FAIL</samp>(失败),则认为操作结束。成功与否如上句所示。\n#* 如果您收到了<samp>UI</samp>,向用户显示新字段,并再次获取其提交的内容。然后再次使用<var>$1continue</var>,向本模块提交相关字段,并重复第四步。\n#* 如果您收到了<samp>REDIRECT</samp>,将用户指向<samp>redirecttarget</samp>中的目标,等待其返回<var>$1returnurl</var>。然后再次使用<var>$1continue</var>,向本模块提交返回URL中提供的一切字段,并重复第四步。\n#* 如果您收到了<samp>RESTART</samp>,这意味着身份验证正常运作,但我们没有链接的用户账户。您可以将此看做<samp>UI</samp>或<samp>FAIL</samp>。",
        "api-help-authmanagerhelper-requests": "只使用这些身份验证请求,通过返回自<kbd>[[Special:ApiHelp/query+authmanagerinfo|action=query&meta=authmanagerinfo]]</kbd>的<samp>id</samp>与<kbd>amirequestsfor=$1</kbd>,或来自此模块之前的响应。",
        "api-help-authmanagerhelper-request": "使用此身份验证请求,通过返回自<kbd>[[Special:ApiHelp/query+authmanagerinfo|action=query&meta=authmanagerinfo]]</kbd>的<samp>id</samp>与<kbd>amirequestsfor=$1</kbd>。",
-       "api-help-authmanagerhelper-messageformat": "返回消息使用的格式。",
+       "api-help-authmanagerhelper-messageformat": "用于返回消息的格式。",
        "api-help-authmanagerhelper-mergerequestfields": "合并用于所有身份验证请求的字段信息至一个数组中。",
        "api-help-authmanagerhelper-preservestate": "从之前失败的登录尝试中保持状态,如果可能。",
        "api-help-authmanagerhelper-returnurl": "为第三方身份验证流返回URL,必须为绝对值。需要此值或<var>$1continue</var>两者之一。\n\n在接收<samp>REDIRECT</samp>响应时,您将代表性的打开浏览器或web视图到特定用于第三方身份验证流的<samp>redirecttarget</samp> URL。当它完成时,第三方将发生浏览器或web视图至此URL。您应当提取任何来自URL的查询或POST参数,并作为<var>$1continue</var>请求传递至此API模块。",
        "apiwarn-difftohidden": "不能与r$1做差异比较:内容被隐藏。",
        "apiwarn-errorprinterfailed": "错误打印失败。将在没有参数的前提下重试。",
        "apiwarn-errorprinterfailed-ex": "错误打印失败(将在没有参数的前提下重试):$1",
+       "apiwarn-ignoring-invalid-templated-value": "当处理模板参数时,忽略<var>$1</var>中的值<kbd>$2</kbd>。",
        "apiwarn-invalidcategory": "“$1”不是一个分类。",
        "apiwarn-invalidtitle": "“$1”不是一个有效的标题。",
        "apiwarn-invalidxmlstylesheetext": "样式表应拥有<code>.xsl</code>扩展名。",
index 03f3e82..2f9b693 100644 (file)
        "apihelp-xmlfm-summary": "使用 XML 格式輸出資料 (使用 HTML 格式顯示)。",
        "api-format-title": "MediaWiki API 結果",
        "api-format-prettyprint-header": "這是$1格式的HTML呈現。HTML適合用於除錯,但不適合應用程式使用。\n\n指定<var>format</var>參數以更改輸出格式。要檢視$1格式的非HTML呈現,設定<kbd>format=$2</kbd>。\n\n參考 [[mw:Special:MyLanguage/API|完整說明文件]] 或 [[Special:ApiHelp/main|API說明]] 以取得更多資訊。",
+       "api-format-prettyprint-header-only-html": "這是用來除錯的HTML呈現,不適合實際應用。\n\n參見[[mw:Special:MyLanguage/API|完整文件]]或[[Special:ApiHelp/main|API幫助]]以取得更多資訊。",
+       "api-format-prettyprint-status": "此回應將會傳回HTTP狀態$1 $2。",
        "api-pageset-param-titles": "要使用的標題清單。",
        "api-pageset-param-pageids": "要使用的頁面 ID 清單。",
        "api-pageset-param-revids": "要使用的修訂 ID 清單。",
        "api-help-lead": "此頁為自動產生的 MediaWiki API 說明文件頁面。\n\n說明文件與範例:https://www.mediawiki.org/wiki/API",
        "api-help-main-header": "主要模組",
        "api-help-flag-deprecated": "此模組已停用。",
+       "api-help-flag-internal": "<strong>此模組是內部的或不穩定的。</strong>它的操作可能更改而不另行通知。",
        "api-help-flag-readrights": "此模組需要讀取權限。",
        "api-help-flag-writerights": "此模組需要寫入權限。",
        "api-help-flag-mustbeposted": "此模組僅接受 POST 請求。",
+       "api-help-flag-generator": "此模組可作為產生器使用。",
+       "api-help-license": "協定:[[$1|$2]]",
+       "api-help-license-noname": "協定:[[$1|查看連結]]",
+       "api-help-license-unknown": "協定:<span class=\"apihelp-unknown\">未知</span>",
        "api-help-parameters": "{{PLURAL:$1|參數}}:",
        "api-help-param-deprecated": "已停用。",
        "api-help-param-required": "此參數為必填。",
+       "api-help-datatypes-header": "資料類型",
+       "api-help-datatypes": "至MediaWiki的輸入值應為NFC標準化的UTF-8。MediaWiki可以嘗試轉換其他輸入值,但這可能導致一些操作失敗(例如附帶MD5檢查的[[Special:ApiHelp/edit|編輯]])。\n\n一些在API請求中的參數類型需要更進一步解釋:\n;boolean\n:布林參數產生作用就像HTML複選框一樣:如果參數被指定,無論何值都被視為真(true)。如果要假值(false),則必須省略參數。\n;timestamp\n:時間戳記可被指定為多種格式。推荐使用ISO 8601日期和時間標準。所有時間為UTC時間,包含的任何時區都會被忽略。\n:* ISO 8601日期和時間,<kbd><var>2001</var>-<var>01</var>-<var>15</var>T<var>14</var>:<var>56</var>:<var>00</var>Z</kbd>(標點和<kbd>Z</kbd>為選用)\n:* 帶小數秒(會被忽略)的ISO 8601日期和時間,<kbd><var>2001</var>-<var>01</var>-<var>15</var>T<var>14</var>:<var>56</var>:<var>00</var>.<var>00001</var>Z</kbd>(破折號、冒號和<kbd>Z</kbd>為選用)\n:* MediaWiki格式,<kbd><var>2001</var><var>01</var><var>15</var><var>14</var><var>56</var><var>00</var></kbd>\n:* 一般數字格式,<kbd><var>2001</var>-<var>01</var>-<var>15</var> <var>14</var>:<var>56</var>:<var>00</var></kbd>(<kbd>GMT</kbd>、<kbd>+<var>##</var></kbd>或<kbd>-<var>##</var></kbd>的選用時區會被忽略)\n:* EXIF格式,<kbd><var>2001</var>:<var>01</var>:<var>15</var> <var>14</var>:<var>56</var>:<var>00</var></kbd>\n:* RFC 2822格式(時區可省略),<kbd><var>Mon</var>, <var>15</var> <var>Jan</var> <var>2001</var> <var>14</var>:<var>56</var>:<var>00</var></kbd>\n:* RFC 850格式(時區可省略),<kbd><var>Monday</var>, <var>15</var>-<var>Jan</var>-<var>2001</var> <var>14</var>:<var>56</var>:<var>00</var></kbd>\n:* C ctime格式,<kbd><var>Mon</var> <var>Jan</var> <var>15</var> <var>14</var>:<var>56</var>:<var>00</var> <var>2001</var></kbd>\n:* 從1970-01-01T00:00:00Z開始的秒數,作為1到13位數的整數(除了<kbd>0</kbd>)\n:* 字串<kbd>now</kbd>\n;替代多值分隔符號\n:使用多個值的參數通常會與垂直線符號(|)分隔的值一起提交,例如<kbd>param=value1|value2</kbd>或<kbd>param=value1%7Cvalue2</kbd>。如果值必須包含垂直線符號,使用U+001F(單位分隔符號)作為分隔符號,''並且''在值前加前綴U+001F,例如<kbd>param=%1Fvalue1%1Fvalue2</kbd>。",
+       "api-help-param-type-limit": "類型:整數或<kbd>max</kbd>",
+       "api-help-param-type-integer": "類型:{{PLURAL:$1|1=整數|2=整數列表}}",
+       "api-help-param-type-boolean": "類型:布林值([[Special:ApiHelp/main#main/datatypes|詳細資訊]])",
+       "api-help-param-type-timestamp": "類型:{{PLURAL:$1|1=時間戳記|2=時間戳記列表}}([[Special:ApiHelp/main#main/datatypes|允許格式]])",
+       "api-help-param-type-user": "類型:{{PLURAL:$1|1=使用者名稱|2=使用者名稱列表}}",
        "api-help-param-list": "{{PLURAL:$1|1=單值|2=多值 (以 <kbd>{{!}}</kbd> 或 [[Special:ApiHelp/main#main/datatypes|alternative]] 分隔)}}:$2",
        "api-help-param-list-can-be-empty": "{{PLURAL:$1|0=必須空白|可以空白,或 $2}}",
        "api-help-param-limit": "不允許超過 $1。",
        "api-help-param-upload": "必須使用 multipart/form-data 以檔案上傳的方式傳送。",
        "api-help-param-multi-separate": "將幾個值以 <kbd>|</kbd> 或 [[Special:ApiHelp/main#main/datatypes|alternative]] 分隔。",
        "api-help-param-multi-max": "上限值為 {{PLURAL:$1|$1}} (機器人為 {{PLURAL:$2|$2}})。",
+       "api-help-param-multi-all": "要指定所有值,請使用<kbd>$1</kbd>。",
        "api-help-param-default": "預設值:$1",
        "api-help-param-default-empty": "預設值:<span class=\"apihelp-empty\">(空)</span>",
        "api-help-param-token": "自 [[Special:ApiHelp/query+tokens|action=query&meta=tokens]] 接收的 \"$1\" 密鑰。",
+       "api-help-param-token-webui": "為顧及相容性,web UI中使用的代碼(Token)也是可接受的。",
+       "api-help-param-disabled-in-miser-mode": "因[[mw:Special:MyLanguage/Manual:$wgMiserMode|miser模式]]而被停用。",
+       "api-help-param-limited-in-miser-mode": "<strong>注意:</strong>因[[mw:Special:MyLanguage/Manual:$wgMiserMode|miser模式]],使用這個可能導致繼續以前傳回少於<var>$1limit</var>筆結果;極端情況下可能不會傳回任何结果。",
+       "api-help-param-direction": "列舉的方向:\n;newer:最舊的優先。注意:$1start應在$1end之前。\n;older:最新的優先(預設)。注意:$1start應在$1end之後。",
+       "api-help-param-continue": "當有更多結果可用時,使用這個繼續。",
        "api-help-param-no-description": "<span class=\"apihelp-empty\">(無描述)</span>",
        "api-help-examples": "{{PLURAL:$1|範例}}:",
        "api-help-permissions": "{{PLURAL:$1|權限}}:",
        "api-help-permissions-granted-to": "{{PLURAL:$1|已授權給}}: $2",
+       "api-help-open-in-apisandbox": "<small>[在沙盒中開啟]</small>",
        "api-help-authmanager-general-usage": "使用此模組的一般程式是:\n# 通過<kbd>amirequestsfor=$4</kbd>取得來自<kbd>[[Special:ApiHelp/query+authmanagerinfo|action=query&meta=authmanagerinfo]]</kbd>的可用欄位,和來自<kbd>[[Special:ApiHelp/query+tokens|action=query&meta=tokens]]</kbd>的<kbd>$5</kbd>令牌。\n# 向用戶顯示欄位,並獲得其提交的內容。\n# 提交(POST)至此模組,提供<var>$1returnurl</var>及任何相關欄位。\n# 在回应中檢查<samp>status</samp>。\n#* 如果您收到了<samp>PASS</samp>(成功)或<samp>FAIL</samp>(失敗),則認為操作結束。成功與否如上句所示。\n#* 如果您收到了<samp>UI</samp>,向用戶顯示新欄位,並再次獲取其提交的內容。然後再次使用<var>$1continue</var>,向本模組提交相關欄位,並重復第四步。\n#* 如果您收到了<samp>REDIRECT</samp>,將使用者指向<samp>redirecttarget</samp>中的目標,等待其返回<var>$1returnurl</var>。然後再次使用<var>$1continue</var>,向本模組提交返回URL中提供的一切欄位,並重復第四步。\n#* 如果您收到了<samp>RESTART</samp>,這意味著身份驗證正常運作,但我們沒有連結的使用者賬戶。您可以將此看做<samp>UI</samp>或<samp>FAIL</samp>。",
+       "api-help-authmanagerhelper-requests": "只使用這些身份驗證請求,透過自<kbd>[[Special:ApiHelp/query+authmanagerinfo|action=query&meta=authmanagerinfo]]</kbd>回傳的<samp>id</samp>與<kbd>amirequestsfor=$1</kbd>,或來自此模組之前的回應。",
+       "api-help-authmanagerhelper-request": "使用此身份驗證請求,透過自<kbd>[[Special:ApiHelp/query+authmanagerinfo|action=query&meta=authmanagerinfo]]</kbd>回傳的<samp>id</samp>與<kbd>amirequestsfor=$1</kbd>。",
+       "api-help-authmanagerhelper-messageformat": "用於回傳訊息的格式。",
+       "api-help-authmanagerhelper-mergerequestfields": "將用於所有身份驗證請求的欄位資訊合併至一個陣列中。",
+       "api-help-authmanagerhelper-preservestate": "從之前失敗的登入嘗試中保持狀態,如果可能。",
+       "api-help-authmanagerhelper-returnurl": "為第三方身份驗證流程傳回URL,必須為絕對值。需要此值或<var>$1continue</var>兩者之一。\n\n在接收<samp>REDIRECT</samp>回應時,一般狀況下您將打開瀏覽器或網站瀏覽功能到特定的<samp>redirecttarget</samp> URL以進行第三方身份驗證流程。當它完成時,第三方會將瀏覽器或網站瀏覽功能送至此URL。您應當提取任何來自URL的查詢或POST參數,並將之作為<var>$1continue</var>請求傳遞至此API模組。",
+       "api-help-authmanagerhelper-continue": "此請求是在先前的<samp>UI</samp>或<samp>REDIRECT</samp>回應之後的後續動作。必須為此值或<var>$1returnurl</var>。",
+       "api-help-authmanagerhelper-additional-params": "此模組允許額外參數,取決於可用的身份驗證請求。使用<kbd>[[Special:ApiHelp/query+authmanagerinfo|action=query&meta=authmanagerinfo]]</kbd>与<kbd>amirequestsfor=$1</kbd>(或之前來自此模組的回應,如果合適)以決定可用請求及其使用的欄位。",
        "apierror-missingparam": "<var>$1</var>參數必須被設定。",
        "apierror-mustbeloggedin-changeauth": "必須登入,才能變更身分核對資取。",
        "apierror-mustbeloggedin-removeauth": "必須登入,才能移除身分核對資取。",
index aab8811..5066f28 100644 (file)
@@ -17,6 +17,9 @@ abstract class HTMLFormField {
        protected $mVFormClass = '';
        protected $mHelpClass = false;
        protected $mDefault;
+       /**
+        * @var array|bool|null
+        */
        protected $mOptions = false;
        protected $mOptionsLabelsNotFromMessage = false;
        protected $mHideIf = null;
index a6014b1..454fd41 100644 (file)
@@ -40,7 +40,7 @@ class CSSMin {
        const EMBED_REGEX = '\/\*\s*\@embed\s*\*\/';
        const COMMENT_REGEX = '\/\*.*?\*\/';
 
-       /** @var array List of common image files extensions and MIME-types */
+       /** @var string[] List of common image files extensions and MIME-types */
        protected static $mimeTypes = [
                'gif' => 'image/gif',
                'jpe' => 'image/jpeg',
@@ -58,7 +58,7 @@ class CSSMin {
         *
         * @param string $source CSS stylesheet source to process
         * @param string $path File path where the source was read from
-        * @return array List of local file references
+        * @return string[] List of local file references
         */
        public static function getLocalFileReferences( $source, $path ) {
                $stripped = preg_replace( '/' . self::COMMENT_REGEX . '/s', '', $source );
@@ -100,7 +100,7 @@ class CSSMin {
         * @param bool $ie8Compat By default, a data URI will only be produced if it can be made short
         *     enough to fit in Internet Explorer 8 (and earlier) URI length limit (32,768 bytes). Pass
         *     `false` to remove this limitation.
-        * @return string|bool Image contents encoded as a data URI or false.
+        * @return string|false Image contents encoded as a data URI or false.
         */
        public static function encodeImageAsDataURI( $file, $type = null, $ie8Compat = true ) {
                // Fast-fail for files that definitely exceed the maximum data URI length
@@ -128,7 +128,7 @@ class CSSMin {
         * @param string $contents File contents to encode.
         * @param string $type File's MIME type.
         * @param bool $ie8Compat See encodeImageAsDataURI().
-        * @return string|bool Image contents encoded as a data URI or false.
+        * @return string|false Image contents encoded as a data URI or false.
         */
        public static function encodeStringAsDataURI( $contents, $type, $ie8Compat = true ) {
                // Try #1: Non-encoded data URI
@@ -173,13 +173,13 @@ class CSSMin {
 
        /**
         * Serialize a string (escape and quote) for use as a CSS string value.
-        * https://www.w3.org/TR/2016/WD-cssom-1-20160317/#serialize-a-string
+        * https://drafts.csswg.org/cssom/#serialize-a-string
         *
         * @param string $value
         * @return string
         */
        public static function serializeStringValue( $value ) {
-               $value = strtr( $value, [ "\0" => "\\fffd ", '\\' => '\\\\', '"' => '\\"' ] );
+               $value = strtr( $value, [ "\0" => "\xEF\xBF\xBD", '\\' => '\\\\', '"' => '\\"' ] );
                $value = preg_replace_callback( '/[\x01-\x1f\x7f]/', function ( $match ) {
                        return '\\' . base_convert( ord( $match[0] ), 10, 16 ) . ' ';
                }, $value );
@@ -387,10 +387,7 @@ class CSSMin {
         * @return bool
         */
        protected static function isLocalUrl( $maybeUrl ) {
-               if ( $maybeUrl !== '' && $maybeUrl[0] === '/' && !self::isRemoteUrl( $maybeUrl ) ) {
-                       return true;
-               }
-               return false;
+               return isset( $maybeUrl[1] ) && $maybeUrl[0] === '/' && $maybeUrl[1] !== '/';
        }
 
        /**
@@ -511,7 +508,7 @@ class CSSMin {
                                                return $data;
                                        }
                                }
-                               if ( method_exists( 'OutputPage', 'transformFilePath' ) ) {
+                               if ( class_exists( OutputPage::class ) ) {
                                        $url = OutputPage::transformFilePath( $remote, $local, $file );
                                } else {
                                        // Add version parameter as the first five hex digits
index 4512a4b..46f9358 100644 (file)
  * Wrapper around strtr() that holds replacements
  */
 class ReplacementArray {
-       private $data = false;
+       private $data = [];
 
        /**
         * Create an object with the specified replacement array
         * The array should have the same form as the replacement array for strtr()
         * @param array $data
         */
-       public function __construct( $data = [] ) {
+       public function __construct( array $data = [] ) {
                $this->data = $data;
        }
 
@@ -44,12 +44,12 @@ class ReplacementArray {
         * Set the whole replacement array at once
         * @param array $data
         */
-       public function setArray( $data ) {
+       public function setArray( array $data ) {
                $this->data = $data;
        }
 
        /**
-        * @return array|bool
+        * @return array
         */
        public function getArray() {
                return $this->data;
index 8420f11..8a88581 100644 (file)
@@ -33,14 +33,25 @@ use Wikimedia\ScopedCallback;
 use Wikimedia\WaitConditionLoop;
 
 /**
- * interface is intended to be more or less compatible with
- * the PHP memcached client.
+ * Class representing a cache/ephemeral data store
  *
- * backends for local hash array and SQL table included:
- * @code
- *   $bag = new HashBagOStuff();
- *   $bag = new SqlBagOStuff(); # connect to db first
- * @endcode
+ * This interface is intended to be more or less compatible with the PHP memcached client.
+ *
+ * Instances of this class should be created with an intended access scope, such as:
+ *   - a) A single PHP thread on a server (e.g. stored in a PHP variable)
+ *   - b) A single application server (e.g. stored in APC or sqlite)
+ *   - c) All application servers in datacenter (e.g. stored in memcached or mysql)
+ *   - d) All application servers in all datacenters (e.g. stored via mcrouter or dynomite)
+ *
+ * Callers should use the proper factory methods that yield BagOStuff instances. Site admins
+ * should make sure the configuration for those factory methods matches their access scope.
+ * BagOStuff subclasses have widely varying levels of support for replication features.
+ *
+ * For any given instance, methods like lock(), unlock(), merge(), and set() with WRITE_SYNC
+ * should semantically operate over its entire access scope; any nodes/threads in that scope
+ * should serialize appropriately when using them. Likewise, a call to get() with READ_LATEST
+ * from one node in its access scope should reflect the prior changes of any other node its access
+ * scope. Any get() should reflect the changes of any prior set() with WRITE_SYNC.
  *
  * @ingroup Cache
  */
@@ -165,7 +176,7 @@ abstract class BagOStuff implements IExpiringStore, LoggerAwareInterface {
        /**
         * Get an item with the given key
         *
-        * If the key includes a determistic input hash (e.g. the key can only have
+        * If the key includes a deterministic input hash (e.g. the key can only have
         * the correct value) or complete staleness checks are handled by the caller
         * (e.g. nothing relies on the TTL), then the READ_VERIFIED flag should be set.
         * This lets tiered backends know they can safely upgrade a cached value to
index 90e697e..186014b 100644 (file)
@@ -190,13 +190,14 @@ class ChronologyProtector implements LoggerAwareInterface {
                        implode( ', ', array_keys( $this->shutdownPositions ) ) . "\n"
                );
 
-               // CP-protected writes should overwhemingly go to the master datacenter, so get DC-local
-               // lock to merge the values. Use a DC-local get() and a synchronous all-DC set(). This
-               // makes it possible for the BagOStuff class to write in parallel to all DCs with one RTT.
+               // CP-protected writes should overwhelmingly go to the master datacenter, so use a
+               // DC-local lock to merge the values. Use a DC-local get() and a synchronous all-DC
+               // set(). This makes it possible for the BagOStuff class to write in parallel to all
+               // DCs with one RTT. The use of WRITE_SYNC avoids needing READ_LATEST for the get().
                if ( $store->lock( $this->key, 3 ) ) {
                        if ( $workCallback ) {
-                               // Let the store run the work before blocking on a replication sync barrier. By the
-                               // time it's done with the work, the barrier should be fast if replication caught up.
+                               // Let the store run the work before blocking on a replication sync barrier.
+                               // If replication caught up while the work finished, the barrier will be fast.
                                $store->addBusyCallback( $workCallback );
                        }
                        $ok = $store->set(
index f9c917d..ef05dd1 100644 (file)
@@ -126,7 +126,7 @@ class SpecialAllPages extends IncludableSpecialPage {
                                'id' => 'namespace',
                                'label-message' => 'namespace',
                                'all' => null,
-                               'value' => $namespace,
+                               'default' => $namespace,
                        ],
                        'hideredirects' => [
                                'type' => 'check',
@@ -141,7 +141,9 @@ class SpecialAllPages extends IncludableSpecialPage {
                        unset( $fields['hideredirects'] );
                }
 
-               $form = HTMLForm::factory( 'table', $fields, $this->getContext() );
+               $context = new DerivativeContext( $this->getContext() );
+               $context->setTitle( $this->getPageTitle() ); // Remove subpage
+               $form = HTMLForm::factory( 'table', $fields, $context );
                $form->setMethod( 'get' )
                        ->setWrapperLegendMsg( 'allpages' )
                        ->setSubmitTextMsg( 'allpagessubmit' )
index c000d54..034e569 100644 (file)
@@ -37,7 +37,7 @@ class SpecialApiSandbox extends SpecialPage {
 
                $out->addJsConfigVars( 'apihighlimits', $this->getUser()->isAllowed( 'apihighlimits' ) );
                $out->addModuleStyles( [
-                       'mediawiki.special.apisandbox.styles',
+                       'mediawiki.special',
                ] );
                $out->addModules( [
                        'mediawiki.special.apisandbox',
index 35cc6b8..28f04fa 100644 (file)
@@ -49,7 +49,7 @@ class SpecialComparePages extends SpecialPage {
        public function execute( $par ) {
                $this->setHeaders();
                $this->outputHeader();
-               $this->getOutput()->addModuleStyles( 'mediawiki.special.comparepages.styles' );
+               $this->getOutput()->addModuleStyles( 'mediawiki.special' );
 
                $form = HTMLForm::factory( 'ooui', [
                        'Page1' => [
index 60d5fd7..3db7eda 100644 (file)
@@ -76,7 +76,7 @@ class SpecialEditTags extends UnlistedSpecialPage {
                $this->outputHeader();
 
                $this->getOutput()->addModules( [ 'mediawiki.special.edittags',
-                       'mediawiki.special.edittags.styles' ] );
+                       'mediawiki.special' ] );
 
                $this->submitClicked = $request->wasPosted() && $request->getBool( 'wpSubmit' );
 
index d30ff43..0069ea1 100644 (file)
@@ -143,8 +143,8 @@ class MovePageForm extends UnlistedSpecialPage {
 
                $out = $this->getOutput();
                $out->setPageTitle( $this->msg( 'move-page', $this->oldTitle->getPrefixedText() ) );
+               $out->addModuleStyles( 'mediawiki.special' );
                $out->addModules( 'mediawiki.special.movePage' );
-               $out->addModuleStyles( 'mediawiki.special.movePage.styles' );
                $this->addHelpLink( 'Help:Moving a page' );
 
                $out->addWikiMsg( $this->getConfig()->get( 'FixDoubleRedirects' ) ?
index 34fcc78..46ad31c 100644 (file)
@@ -60,7 +60,7 @@ class SpecialPagesWithProp extends QueryPage {
        public function execute( $par ) {
                $this->setHeaders();
                $this->outputHeader();
-               $this->getOutput()->addModuleStyles( 'mediawiki.special.pagesWithProp' );
+               $this->getOutput()->addModuleStyles( 'mediawiki.special' );
 
                $request = $this->getRequest();
                $propname = $request->getVal( 'propname', $par );
index 2f285c9..3ca3a85 100644 (file)
@@ -128,7 +128,7 @@ class SpecialPrefixindex extends SpecialAllPages {
                ];
                $context = new DerivativeContext( $this->getContext() );
                $context->setTitle( $this->getPageTitle() ); // Remove subpage
-               $htmlForm = new HTMLForm( $formDescriptor, $context );
+               $htmlForm = HTMLForm::factory( 'ooui', $formDescriptor, $context );
                $htmlForm
                        ->setMethod( 'get' )
                        ->setWrapperLegendMsg( 'prefixindex' )
index f7cb654..2eeafe6 100644 (file)
@@ -387,7 +387,7 @@ class SpecialUpload extends SpecialPage {
                }
 
                // Add styles for the warning, reused from the live preview
-               $this->getOutput()->addModuleStyles( 'mediawiki.special.upload.styles' );
+               $this->getOutput()->addModuleStyles( 'mediawiki.special' );
 
                $linkRenderer = $this->getLinkRenderer();
                $warningHtml = '<h2>' . $this->msg( 'uploadwarning' )->escaped() . "</h2>\n"
index dda1dac..ea73347 100644 (file)
@@ -60,11 +60,10 @@ class SpecialWatchlist extends ChangesListSpecialPage {
                $output = $this->getOutput();
                $request = $this->getRequest();
                $this->addHelpLink( 'Help:Watching pages' );
+               $output->addModuleStyles( [ 'mediawiki.special' ] );
                $output->addModules( [
-                       'mediawiki.special.changeslist.visitedstatus',
                        'mediawiki.special.watchlist',
                ] );
-               $output->addModuleStyles( [ 'mediawiki.special.watchlist.styles' ] );
 
                $mode = SpecialEditWatchlist::getMode( $request, $subpage );
                if ( $mode !== false ) {
index e561fe5..8ab6f29 100644 (file)
@@ -79,7 +79,7 @@ class UploadForm extends HTMLForm {
 
                # Add a link to edit MediaWiki:Licenses
                if ( $this->getUser()->isAllowed( 'editinterface' ) ) {
-                       $this->getOutput()->addModuleStyles( 'mediawiki.special.upload.styles' );
+                       $this->getOutput()->addModuleStyles( 'mediawiki.special' );
                        $licensesLink = $linkRenderer->makeKnownLink(
                                $this->msg( 'licenses' )->inContentLanguage()->getTitle(),
                                $this->msg( 'licenses-edit' )->text(),
index 890a870..7c2d393 100644 (file)
@@ -275,10 +275,15 @@ class MediaWikiTitleCodec implements TitleFormatter, TitleParser {
                        'user_case_dbkey' => $dbkey,
                ];
 
-               # Strip Unicode bidi override characters.
+               # Strip soft hyphens (U+00AD) and Unicode directional formatting characters (U+061C, U+200E,
+               # U+200F, U+202A. U+202B, U+202C, U+202D, U+202E, U+2066, U+2067, U+2068, U+2069).
                # Sometimes they slip into cut-n-pasted page titles, where the
-               # override chars get included in list displays.
-               $dbkey = preg_replace( '/\xE2\x80[\x8E\x8F\xAA-\xAE]/S', '', $dbkey );
+               # soft hyphens or override chars get included in list displays.
+               $dbkey = preg_replace(
+                       '/\xC2\xAD|\xD8\x9C|\xE2\x80[\x8E\x8F\xAA-\xAE]|\xE2\x81[\xA6-\xA9]/S',
+                       '',
+                       $dbkey
+               );
 
                # Clean up whitespace
                # Note: use of the /u option on preg_replace here will cause
index b688b16..911a627 100644 (file)
        "botpasswords-existing": "Contraseñes de bots esistentes",
        "botpasswords-createnew": "Crear una contraseña nueva de bot",
        "botpasswords-editexisting": "Editar una contraseña de bot esistiente",
+       "botpasswords-label-needsreset": "(la contraseña tien de reaniciase)",
        "botpasswords-label-appid": "Nome del bot:",
        "botpasswords-label-create": "Crear",
        "botpasswords-label-update": "Anovar",
        "botpasswords-restriction-failed": "Hai torgues de contraseña de bot que torgaron esti aniciu de sesión.",
        "botpasswords-invalid-name": "El nome d'usuariu especificáu nun contien el separador de contraseña de bot («$1»).",
        "botpasswords-not-exist": "L'usuariu «$1» nun tien una contraseña de bot llamada «$2».",
+       "botpasswords-needs-reset": "Tien de reniciase la contraseña del robot «$2», propiedá {{GENDER:$1|del usuariu|de la usuaria}} «$1».",
        "resetpass_forbidden": "Nun puen camudase les contraseñes",
        "resetpass_forbidden-reason": "Les contraseñes nun pueden camudase: $1",
        "resetpass-no-info": "Tienes d'aniciar sesión pa entrar direutamente a esta páxina.",
        "subject-preview": "Vista previa del asuntu:",
        "previewerrortext": "Hebo un error al intentar entever los cambios.",
        "blockedtitle": "L'usuariu ta bloquiáu",
-       "blockedtext": "'''El to nome d'usuariu o direición IP ta bloquiáu.'''\n\nEl bloquéu fexolu $1.\nEl motivu conseñáu ye ''$2''.\n\n* Principiu del bloquéu: $8\n* Caducidá del bloquéu: $6\n* Usuariu a bloquiar: $7\n\nPues ponete'n contautu con $1 o con otru [[{{MediaWiki:Grouppage-sysop}}|alministrador]] p'aldericar sobre'l bloquéu.\nNun pues usar la función 'manda-y un corréu electrónicu a esti usuariu' a nun ser que tea especificada una direición de\ncorréu electrónicu válida nes tos [[Special:Preferences|preferencies de cuenta]] y que nun tengas torgao usala.\nLa to direición IP actual ye $3, y la ID del bloquéu ye #$5.\nPor favor, incluye tolos detalles anteriores nes consultes que faigas.",
-       "autoblockedtext": "La to direición IP bloquióse automáticamente porque usóla otru usuariu que foi bloquiáu por $1.\nEl motivu conseñáu ye:\n\n:''$2''\n\n* Principiu del bloquéu: $8\n* Caducidá del bloquéu: $6\n* Usuariu a bloquiar: $7\n\nPues ponete'n contautu con $1 o con otru de los [[{{MediaWiki:Grouppage-sysop}}|alministradores]] p'aldericar sobre'l bloquéu.\n\nTen en cuenta que nun pues usar la función «manda-y un corréu electrónicu a esti usuariu» a nun ser que tengas rexistrada una direición de corréu electrónicu válida nes [[Special:Preferences|preferencies d'usuariu]] y que nun tengas torgao usala.\n\nLa to direición IP actual ye $3, y la ID del bloquéu ye #$5.\nPor favor, incluye tolos detalles anteriores nes consultes que faigas.",
+       "blockedtext": "<strong>El to nome d'usuariu o direición IP ta bloquiáu.</strong>\n\nEl bloquéu fexolu $1.\nEl motivu conseñáu ye <em>$2</em>.\n\n* Principiu del bloquéu: $8\n* Caducidá del bloquéu: $6\n* Usuariu a bloquiar: $7\n\nPuedes comunicate con $1 o con otru [[{{MediaWiki:Grouppage-sysop}}|alministrador]] p'aldericar sobre'l bloquéu.\nNun puedes usar la función «{{int:emailuser}}» a nun ser que tea especificada una direición de corréu electrónicu válida nes tos [[Special:Preferences|preferencies de cuenta]] y que nun tengas torgao usala.\nLa to direición IP actual ye $3, y la ID del bloquéu ye #$5.\nPor favor, incluye tolos detalles anteriores nes consultes que faigas.",
+       "autoblockedtext": "La to direición IP bloquióse automáticamente porque usóla otru usuariu que foi bloquiáu por $1.\nEl motivu conseñáu ye:\n\n:<em>$2</em>\n\n* Principiu del bloquéu: $8\n* Caducidá del bloquéu: $6\n* Usuariu a bloquiar: $7\n\nPues ponete'n contautu con $1 o con otru de los [[{{MediaWiki:Grouppage-sysop}}|alministradores]] p'aldericar sobre'l bloquéu.\n\nTen en cuenta que nun pues usar la función «{{int:emailuser}}» a nun ser que tengas rexistrada una direición de corréu electrónicu válida nes [[Special:Preferences|preferencies d'usuariu]] y que nun tengas torgao usala.\n\nLa to direición IP actual ye $3, y la ID del bloquéu ye #$5.\nPor favor, incluye tolos detalles anteriores nes consultes que faigas.",
        "systemblockedtext": "El to nome d'usuariu o dirección IP bloquióse automáticamente pol software MediaWiki.\nEl motivu dau ye:\n\n:<em>$2</em>\n\n* Entamu del bloquéu: $8\n* Caducidá de bloquéu: $6\n* Destinatariu del bloquéu: $7\n\nLa to dirección IP actual ye $3.\nPor favor, incluye tolos anteriores en cualquier consulta que faigas.",
        "blockednoreason": "nun se dio nengún motivu",
        "whitelistedittext": "Tienes d'$1 pa editar páxines.",
        "recentchangeslinked-feed": "Cambios rellacionaos",
        "recentchangeslinked-toolbox": "Cambios rellacionaos",
        "recentchangeslinked-title": "Cambios rellacionaos con \"$1\"",
-       "recentchangeslinked-summary": "Esscribe'l nome d'una páxina pa ver los cambios nes páxines enllazaes a o dende esa páxina. (Pa ver los miembros d'una categoría, escribe Categoría:Nome de la categoría). Los cambios nes páxines de [[Special:Watchlist|la to llista de siguimientu]] tán en <strong>negrina</strong>.",
+       "recentchangeslinked-summary": "Esscribe'l nome d'una páxina pa ver los cambios nes páxines enllazaes a o dende esa páxina. (Pa ver los miembros d'una categoría, escribe {{ns:category}}:Nome de la categoría). Los cambios nes páxines de [[Special:Watchlist|la to llista de siguimientu]] tán en <strong>negrina</strong>.",
        "recentchangeslinked-page": "Nome de la páxina:",
        "recentchangeslinked-to": "Amosar los cambios de les páxines qu'enllacen en cuenta de los de la páxina dada",
        "recentchanges-page-added-to-category": "[[:$1]] amestóse a la categoría",
        "pagedata-title": "Datos de la páxina",
        "pagedata-text": "Esta páxina ufre una interfaz de datos pa les páxines. Escribe'l títulu de la páxina na URL, usando la sintaxis de subpáxina.\n* Aplícase la negociación de conteníu en base a la testera Accept del to cliente. Esto significa que los datos de la páxina van dase nel formatu que prefiera'l to cliente.",
        "pagedata-not-acceptable": "Nun s'alcontró nengún formatu que coincidiera. Tipos MIME soportaos: $1",
-       "pagedata-bad-title": "Títulu inválidu: $1."
+       "pagedata-bad-title": "Títulu inválidu: $1.",
+       "unregistered-user-config": "Por motivos de seguridá, les subpáxines d'usuariu JavaScript, CSS y JSON nun pueden cargase pa usuarios ensin rexistrar."
 }
index d97b2d0..d6730e8 100644 (file)
        "apisandbox-dynamic-parameters-add-label": "Дадаць парамэтар:",
        "apisandbox-dynamic-parameters-add-placeholder": "Назва парамэтру",
        "apisandbox-dynamic-error-exists": "Парамэтар з назвай «$1» ужо існуе.",
+       "apisandbox-templated-parameter-reason": "Гэты [[Special:ApiHelp/main#main/templatedparams|шаблённы парамэтар]] прапануецца паводле {{PLURAL:$1|1=значэньня|значэньняў}} $2.",
        "apisandbox-deprecated-parameters": "Састарэлыя парамэтры",
        "apisandbox-fetch-token": "Аўтазапаўненьне токену",
        "apisandbox-add-multi": "Дадаць",
index 1fe1fda..113a994 100644 (file)
        "apisandbox-dynamic-parameters-add-label": "Přidat parametr:",
        "apisandbox-dynamic-parameters-add-placeholder": "Jméno parametru",
        "apisandbox-dynamic-error-exists": "Parametr s názvem „$1“ již existuje.",
+       "apisandbox-templated-parameter-reason": "Tento [[Special:ApiHelp/main#main/templatedparams|šablonovaný parametr]] se nabízí na základě {{PLURAL:$1|hodnoty|hodnot}} parametru $2.",
        "apisandbox-deprecated-parameters": "Zavržené parametry",
        "apisandbox-fetch-token": "Automaticky naplnit token",
        "apisandbox-add-multi": "Přidat",
index 949cd98..4343b61 100644 (file)
        "subcategories": "подъкатигорїѩ",
        "category-media-header": "катигорїѩ ⁖ $1 ⁖ дѣла",
        "category-empty": "''сѥи катигорїи нꙑнѣ страницѧ и дѣлъ нѣстъ''",
-       "hidden-categories": "{{PLURAL:$1|съкрꙑта катигорїꙗ|съкрꙑти катигорїи|съкрꙑтꙑ катигорїѩ}}",
+       "hidden-categories": "{{PLURAL:$1|съкрꙑта катигорїꙗ|съкрꙑтѣ катигорїи|съкрꙑтꙑ катигорїѩ}}",
        "hidden-category-category": "съкрꙑтꙑ катигорїѩ",
        "category-subcat-count": "{{PLURAL:$2|1=Сѥи катигорїи тъкъмо сꙗ подъкатигорїꙗ ѥстъ|Сѥи катигорїи {{PLURAL:$1|1=ѥдина подъкатигорїꙗ ѥстъ|2 подъкатигорїи ѥстє|$1 подъкатигорїѩ сѫтъ}} · а вьсѩ жє подъкатигорїѩ число $2 ѥстъ}}",
        "listingcontinuesabbrev": "· вѧщє",
+       "broken-file-category": "страницѧ ѩжє блаꙁничьнꙑ свѧꙁи съ дѣла имѫтъ",
        "about": "опьсаниѥ",
        "article": "члѣнъ",
        "newwindow": "(въ иномь окънѣ)",
        "aboutsite": "{{grammar:genitive|{{SITENAME}}}} опьсаниѥ",
        "aboutpage": "Project:О сѥмь опꙑтьствовании",
        "copyright": "подъ прощєниѥмь $1 пьсано ѥстъ · ащє ино нє каꙁано ѥстъ",
-       "copyrightpage": "{{ns:project}}:ТвоÑ\80Ñ\8cÑ\86Ñ\8a права",
-       "currentevents": "сѫщѧѩ вѣщи",
-       "currentevents-url": "Project:Сѫщѧѩ вѣщи",
+       "copyrightpage": "{{ns:project}}:ТвоÑ\80Ñ\8cÑ\86Ñ\8c права",
+       "currentevents": "сѫщѧѩ вѣщиѥ",
+       "currentevents-url": "Project:Сѫщѧѩ вѣщиѥ",
        "disclaimers": "отърицаниꙗ",
        "disclaimerpage": "Project:Главьно отърицаниѥ",
        "edithelp": "помощь по исправлѥниѭ",
        "createacct-benefit-heading": "{{SITENAME}} съꙁьдаѥтъ сѧ чьловѣкꙑ · ижє ꙗко тꙑ сѫтъ",
        "createacct-benefit-body1": "{{PLURAL:$1|мѣна|мѣнꙑ|мѣнъ}}",
        "createacct-benefit-body2": "{{PLURAL:$1|страница|страници|страницѧ}}",
+       "createacct-benefit-body3": "{{PLURAL:$1|послѣдьн҄ь дѣтєл҄ь|послѣдьнꙗ дѣтєлꙗ|послѣдьни дѣтєлє}}",
        "userexists": "сѫщє польꙃєватєлꙗ имѧ пьса ⁙\nбѫди добръ · ино сѥ иꙁобрѧщи",
        "loginerror": "въхода блаꙁна",
        "createacct-error": "мѣста сътворѥниꙗ блаꙁна",
        "link_tip": "вънѫтрьнꙗ съвѧꙁь",
        "extlink_sample": "http://www.example.com съвѧꙁи имѧ",
        "extlink_tip": "вънѣщьнꙗ съвѧꙁь (помьни о http://)",
+       "headline_sample": "тїтла напьсаниѥ",
+       "headline_tip": "тїтлъ рѧда В҃",
        "media_tip": "дѣла съвѧꙁь",
        "sig_tip": "твои аѵтографъ и нꙑнѣшьна врѣмѧ и дьнь",
        "summary": "опьсаниѥ :",
        "minoredit": "малаꙗ мѣна",
        "watchthis": "сѥѩ страницѧ блюдєниѥ",
        "savearticle": "съхранѥниѥ",
-       "showpreview": "мѣнꙑ поꙁьрѣниѥ (бєꙁ съхранѥниꙗ)",
+       "showpreview": "мѣнꙑ поꙁьрѣниѥ (бєс съхранѥниꙗ)",
+       "showdiff": "раꙁьницѧ поꙁьрѣниѥ",
        "blockedtitle": "польꙃєватєл҄ь ꙁаграждєнъ ѥстъ",
        "loginreqlink": "въниди",
        "newarticle": "(новъ)",
        "postedit-confirmation-created": "страница сътворѥна ѥстъ",
        "postedit-confirmation-saved": "твоꙗ мѣна съхранѥна ѥстъ",
        "viewpagelogs": "сѥѩ страницѧ їсторїѩ",
+       "revisionasof": "обраꙁъ отъ $1",
+       "revision-info": "страницѧ обраꙁъ отъ $1 ижє {{GENDER:$6|$2}}$7 сътвори",
+       "previousrevision": "← прѣждьн҄ь обраꙁъ",
+       "currentrevisionlink": "послѣдьн҄ь обраꙁъ",
        "cur": "нꙑ҃н",
        "last": "пс҃лд",
        "page_first": "прьва страница",
        "editundo": "отъмѣтаниѥ",
        "searchresults": "исканиꙗ слѣдьствиѥ",
        "searchresults-title": "исканиꙗ ⁖ $1 ⁖ слѣдьствиѥ",
+       "prevn": "прѣждьнѩ {{PLURAL:$1|$1}}",
        "viewprevnext": "виждь ($1 {{int:pipe-separator}} $2) ($3)",
        "searchmenu-exists": "'''страница имєньмь ⁖ [[:$1]] ⁖ ѥстъ створѥна ю'''",
        "searchmenu-new": "<strong>страницѫ \"⁖ [[:$1]] ⁖\" сътворити можєши</strong> {{PLURAL:$2|0=|ꙁъри такождє страница ижє по искании авлєна ѥстъ|ꙁьри такождє исканиꙗ слѣдьствиꙗ}}",
        "searchprofile-articles-tooltip": "ищи въ $1",
        "searchprofile-images-tooltip": "исканиѥ дѣлъ",
        "searchprofile-everything-tooltip": "ищи вьсѩ страницѧ въкоупомь съ бѣсєдꙑ",
-       "search-result-size": "$1 ({{PLURAL:$2|$2 слово|$2 слова|$2 словєсъ}})",
+       "search-result-size": "$1 ({{PLURAL:$2|$2 слово|$2 словєсѣ|$2 словєсъ}})",
        "search-redirect": "(прѣнаправлєниѥ отъ $1)",
        "search-section": "(чѧсть $1)",
        "search-suggest": "⁖ $1 ⁖ мьниши ли",
        "undelete-show-file-submit": "да",
        "namespace": "имєнъ просторъ:",
        "invert": "обрати иꙁборъ",
-       "namespace_association": "съвѧꙁанꙑ имєнъ просторꙑ",
+       "namespace_association": "съвѧꙁани имєнъ простори",
        "blanknamespace": "(главьно)",
        "contributions": "{{GENDER:$1|польꙃєватєлꙗ|польꙃєватєлицѧ}} добродѣꙗниꙗ",
        "contributions-title": "польꙃєватєлꙗ ⁖ $1 ⁖ добродѣꙗниꙗ",
        "mycontris": "добродѣꙗниꙗ",
        "anoncontribs": "добродѣꙗниꙗ",
-       "contribsub2": "польꙃєватєлꙗ имѧ ⁖ {{GENDER:$3|$1}} ⁖ ѥстъ ($2)",
+       "contribsub2": "{{GENDER:$3|польꙃєватєлꙗ|польꙃєватєлицѧ}} имѧ ⁖ $1 ⁖ ѥстъ ($2)",
        "uctop": "(нꙑнѣщьн҄ь обраꙁъ)",
        "month": "отъ мѣсѧца и давѣѥ :",
-       "year": "отъ лѣта и давѣѥ :",
+       "year": "отъ лѣта и давѣи :",
        "sp-contributions-blocklog": "ꙁаграждєниꙗ їсторїꙗ",
        "sp-contributions-deleted": "{{GENDER:$1|поꙁєватєлꙗ|польꙃєватєлицѧ}} поничьжєнꙑ добродѣꙗниꙗ",
        "sp-contributions-uploads": "положєнꙑ дѣла",
        "sp-contributions-talk": "бєсѣда",
        "sp-contributions-username": "IP число или польꙃєватєлꙗ имѧ :",
        "sp-contributions-submit": "ищи",
-       "whatlinkshere": "дос҄ьдєщьнѩ съвѧꙁи",
+       "whatlinkshere": "дос҄ьдєщьнѩ съвѧꙁиѥ",
        "whatlinkshere-title": "страницѧ ижє съ ⁖ $1 ⁖ съвѧꙁи имѫтъ",
        "whatlinkshere-page": "страница :",
+       "linkshere": "сѩ страницѧ съ <strong>[[:$1]]</strong> съвѧꙁи имѫтъ :",
        "isredirect": "прѣнаправлѥниѥ",
        "istemplate": "внѫтри страницѧ",
        "isimage": "дѣла съвѧꙁь",
-       "whatlinkshere-links": "← съвѧꙁи",
+       "whatlinkshere-links": "← съвѧꙁиѥ",
        "whatlinkshere-hideredirs": "$1 прѣнаправлѥниꙗ",
        "whatlinkshere-hidelinks": "$1 съвѧꙁиѥ",
-       "whatlinkshere-filters": "сит",
+       "whatlinkshere-filters": "сита",
        "block": "ꙁагради польꙃєватєл҄ь",
        "blockip": "ꙁагради {{GENDER:$1|польꙃєватєл҄ь}}",
        "ipaddressorusername": "IP число или польꙃєватєлꙗ имѧ :",
        "blocklink": "ꙁагради",
        "contribslink": "добродѣꙗниꙗ",
        "blocklogpage": "ꙁаграждєниꙗ їсторїꙗ",
-       "blocklogentry": "ꙁаградилъ [[$1]] на врѣмѧ $2 $3",
+       "blocklogentry": "ꙁагради [[$1]] на врѣмѧ $2 $3",
        "block-log-flags-anononly": "тъкъмо анѡнѷмьнꙑ польꙃєватєлє",
        "block-log-flags-nocreate": "сътворѥниѥ мѣстъ ꙁабранєно ѥстъ",
        "ipb_already_blocked": "⁖ $1 ⁖ ю ꙁаграждєнъ ѥстъ",
        "tooltip-pt-userpage": "{{GENDER:|твоꙗ польꙃєватєл҄ьска}} страница",
        "tooltip-pt-mytalk": "{{GENDER:|твоꙗ}} бєсѣдꙑ страница",
        "tooltip-pt-preferences": "{{GENDER:|твои}} строи",
-       "tooltip-pt-watchlist": "страницѧ ижє ихъжє иꙁмѣнѥниꙗ подъ твоимь блюдєниѥмь сѫтъ",
+       "tooltip-pt-watchlist": "страницѧ ѩжє ихъжє иꙁмѣнѥниꙗ подъ твоимь блюдєниѥмь сѫтъ",
        "tooltip-pt-mycontris": "{{GENDER:|твоѩ}} добродѣꙗнии каталогъ",
        "tooltip-pt-logout": "ис̾ходъ",
        "tooltip-ca-talk": "сѥѩ страницѧ бєсѣда",
        "tooltip-ca-edit": "сѥѩ страницѧ исправлѥниѥ",
        "tooltip-ca-viewsource": "си страница ꙁабранєна ѥстъ ⁙\nѥѩ источьнъ обраꙁъ видєти можєши",
+       "tooltip-ca-history": "сѥѩ страницѧ прѣждьни обраꙁи",
        "tooltip-ca-protect": "сѥѩ страницѧ ꙁабранєниѥ",
        "tooltip-ca-delete": "сѥѩ страницѧ поничьжєниѥ",
        "tooltip-ca-move": "сѥѩ страницѧ прѣимєнованиѥ",
        "tooltip-search-go": "прѣиди къ страницѧ съ симь имєньмь ащє жє та страница ѥстъ",
        "tooltip-search-fulltext": "исканиѥ страницѧ ижє сѥ напьсаниѥ дрьжатъ",
        "tooltip-p-logo": "главьна страница",
-       "tooltip-n-mainpage": "виждь главьноу страницѫ",
-       "tooltip-n-mainpage-description": "виждь главьноу страницѫ",
+       "tooltip-n-mainpage": "виждь главьнѫ страницѫ",
+       "tooltip-n-mainpage-description": "виждь главьнѫ страницѫ",
        "tooltip-n-recentchanges": "послѣдьн҄ь мѣнъ каталогъ",
-       "tooltip-t-whatlinkshere": "страницѧ ижє съвѧꙁи дос҄ьдє имѫтъ",
+       "tooltip-n-randompage": "виждь страницѫ въ нєꙁаапѫ",
+       "tooltip-t-whatlinkshere": "страницѧ ѩжє съвѧꙁи дос҄ьдє имѫтъ",
        "tooltip-t-contributions": "{{GENDER:$1|польꙃєватєлꙗ|польꙃєватєлицѧ}} добродѣꙗнии каталогъ",
        "tooltip-t-upload": "положєниѥ дѣлъ",
        "tooltip-t-specialpages": "вьсѣѩ нарочьнъ страницѧ каталогъ",
        "tooltip-t-print": "сѥѩ страницѧ пєчатьнъ обраꙁъ",
+       "tooltip-t-permalink": "вѣчьна съвѧꙁь съ симь страницѧ обраꙁомь",
        "tooltip-ca-nstab-user": "виждь польꙃєватєлꙗ страницѫ",
        "tooltip-ca-nstab-special": "сѥ нарочьна страница ѥстъ · ѥѩжє иꙁмѣнꙗти нє можєши",
        "tooltip-ca-nstab-image": "виждь дѣла страницѫ",
        "tags-deactivate-reason": "какъ съмꙑслъ :",
        "htmlform-no": "нѣтъ",
        "htmlform-yes": "да",
-       "logentry-delete-delete": "$1 {{GENDER:$2|поничьжилъ|поничьжила}} страницѫ ⁖ $3 ⁖",
+       "logentry-delete-delete": "$1 {{GENDER:$2|поничьжи}} страницѫ ⁖ $3 ⁖",
        "logentry-block-block": "$1 {{GENDER:$2|ꙁаградилъ|ꙁаградила}} {{GENDER:$4|$3}} на врѣмѧ $5 $6",
        "logentry-suppress-block": "$1 {{GENDER:$2|ꙁаграждєнъ|ꙁаграждєна}} ѥстъ {{GENDER:$4|$3}} врѣмєньмь $5 $6",
        "logentry-move-move": "$1 {{GENDER:$2|нарєчє}} страницѫ ⁖ $3 ⁖ имєньмь ⁖ $4 ⁖",
index e36758d..6b212c9 100644 (file)
        "apisandbox-dynamic-parameters-add-label": "Parameter hinzufügen:",
        "apisandbox-dynamic-parameters-add-placeholder": "Name des Parameters",
        "apisandbox-dynamic-error-exists": "Ein Parameter mit dem Namen „$1“ ist bereits vorhanden.",
+       "apisandbox-templated-parameter-reason": "Diese [[Special:ApiHelp/main#main/templatedparams|Vorlagenparameter]] werden basierend auf {{PLURAL:$1|dem Wert|den Werten}} von $2 angeboten.",
        "apisandbox-deprecated-parameters": "Veraltete Parameter",
        "apisandbox-fetch-token": "Den Token automatisch ausfüllen",
        "apisandbox-add-multi": "Hinzufügen",
index 215b356..236d6e5 100644 (file)
        "apisandbox-dynamic-parameters-add-label": "Add parameter:",
        "apisandbox-dynamic-parameters-add-placeholder": "Parameter name",
        "apisandbox-dynamic-error-exists": "A parameter named \"$1\" already exists.",
+       "apisandbox-templated-parameter-reason": "This [[Special:ApiHelp/main#main/templatedparams|templated parameter]] is offered based on the {{PLURAL:$1|value|values}} of $2.",
        "apisandbox-deprecated-parameters": "Deprecated parameters",
        "apisandbox-fetch-token": "Auto-fill the token",
        "apisandbox-add-multi": "Add",
index f100487..3933655 100644 (file)
        "savechanges": "Aldaketak gorde",
        "publishpage": "Orrialdea argitaratu",
        "publishchanges": "Aldaketak argitaratu",
+       "savearticle-start": "Gorde orria...",
        "savechanges-start": "Aldaketak gorde...",
        "publishpage-start": "Orrialdea argitaratu...",
        "publishchanges-start": "Aldaketak argitaratu...",
index 3c5ef67..7a24fe7 100644 (file)
        "recentchangeslinked-feed": "Linkitettyjen sivujen muutokset",
        "recentchangeslinked-toolbox": "Linkitettyjen sivujen muutokset",
        "recentchangeslinked-title": "Sivulta $1 linkitettyjen sivujen muutokset",
-       "recentchangeslinked-summary": "Kirjoita sivun nimi nähdäksesi muutokset sivuihin jotka on linkitetty tai ovat tältä sivulta. (Nähdäksesi luokan jäsenet, kirjoita {{ns:category}}:Luokan nimi). Muutokset sivuihin [[Special:Watchlist|tarkkailulistallasi]] on <strong>lihavoitu</strong>.",
+       "recentchangeslinked-summary": "Kirjoita sivun nimi nähdäksesi muutokset sivuihin, joista on linkki tähän sivuun tai joihin on linkki tältä sivulta. (Luokan sisällön saat näkyviin kirjoittamalla {{ns:category}}:Luokan nimen). Muutokset [[Special:Watchlist|tarkkailulistallasi]] oleviin sivuihin on <strong>lihavoitu</strong>.",
        "recentchangeslinked-page": "Sivun nimi:",
        "recentchangeslinked-to": "Näytä sen sijaan muutokset sivuihin, joista on linkki tähän sivuun",
        "recentchanges-page-added-to-category": "[[:$1]] lisätty luokkaan",
index 0ffdbd4..cd80060 100644 (file)
        "apisandbox-dynamic-parameters-add-label": "Ajout du paramètre:",
        "apisandbox-dynamic-parameters-add-placeholder": "Nom du paramètre",
        "apisandbox-dynamic-error-exists": "Un paramètre nommé \"$1\" existe déjà.",
+       "apisandbox-templated-parameter-reason": "Ce [[Special:ApiHelp/main#main/templatedparams|paramètre de modèle]] est offert d’après {{PLURAL:$1|la valeur|les valeurs}} de $2.",
        "apisandbox-deprecated-parameters": "Paramètres désuets",
        "apisandbox-fetch-token": "Auto-remplissage du jeton",
        "apisandbox-add-multi": "Ajouter",
        "pagedata-title": "Données de page",
        "pagedata-text": "Cette page fournit une interface de données aux pages. Veuillez fournir le titre de la page dans l’URL en utilisant la syntaxe de sous-page.\n* La négociation de contenu s’applique d’après l’entête Accept de votre client. Cela veut dire que les données de la page seront fournies dans le format préféré par votre client.",
        "pagedata-not-acceptable": "Aucun format correspondant trouvé. Types MIME pris en charge : $1",
-       "pagedata-bad-title": "Titre non valide : $1."
+       "pagedata-bad-title": "Titre non valide : $1.",
+       "unregistered-user-config": "Pour des raisons de sécurité, les sous-pages utilisateur JavaScript, CSS et JSON ne peuvent pas être chargées pour des utilisateurs non inscrits."
 }
index 80da07e..31b7caa 100644 (file)
        "apisandbox-dynamic-parameters-add-label": "הוספת פרמטר:",
        "apisandbox-dynamic-parameters-add-placeholder": "שם הפרמטר",
        "apisandbox-dynamic-error-exists": "פרמטר בשם \"$1\" כבר קיים.",
+       "apisandbox-templated-parameter-reason": "[[Special:ApiHelp/main#main/templatedparams|פרמטר התבנית]] הזה מוצע בהתבסס על {{PLURAL:$1|הערך של השדה|הערכים של השדות}} $2.",
        "apisandbox-deprecated-parameters": "פרמטרים מיושנים",
        "apisandbox-fetch-token": "מילוי אוטומטי של האסימון",
        "apisandbox-add-multi": "הוספה",
        "addwatch": "הוספה לרשימת המעקב",
        "addedwatchtext": "הדף \"[[:$1]]\" ודף השיחה שלו נוספו ל[[Special:Watchlist|רשימת המעקב]] שלך.",
        "addedwatchtext-talk": "הדף \"[[:$1]]\" ודף התוכן המשויך אליו נוספו ל[[Special:Watchlist|רשימת המעקב]] שלך.",
-       "addedwatchtext-short": "הדף \"$1\" נוסף לרשימת המעקב.",
+       "addedwatchtext-short": "הדף \"$1\" נוסף לרשימת המעקב שלך.",
        "removewatch": "הסרה מרשימת המעקב",
        "removedwatchtext": "הדף \"[[:$1]]\" ודף השיחה שלו הוסרו מ[[Special:Watchlist|רשימת המעקב]] שלך.",
        "removedwatchtext-talk": "הדף \"[[:$1]]\" ודף התוכן המשויך אליו הוסרו מ[[Special:Watchlist|רשימת המעקב]] שלך.",
-       "removedwatchtext-short": "הדף \"$1\" הוסר מרשימת המעקב.",
+       "removedwatchtext-short": "הדף \"$1\" הוסר מרשימת המעקב שלך.",
        "watch": "מעקב",
        "watchthispage": "מעקב אחרי דף זה",
        "unwatch": "הפסקת מעקב",
        "unwatchthispage": "הפסקת המעקב אחרי דף זה",
        "notanarticle": "זהו אינו דף תוכן",
        "notvisiblerev": "הגרסה האחרונה שנוצרה על־ידי משתמש אחר נמחקה",
-       "watchlist-details": "ברשימת המעקב שלך יש {{PLURAL:$1|דף אחד|$1 דפים}} (ובנוסף להם, דפי שיחה).",
+       "watchlist-details": "ברשימת המעקב שלך יש {{PLURAL:$1|דף אחד|$1 דפים}} (ובנוסף {{PLURAL:$1|אליו, דף|להם, דפי}} שיחה).",
        "wlheader-enotif": "הודעות דוא\"ל מאופשרות.",
-       "wlheader-showupdated": "דפים שהשתנו מאז ביקורך האחרון בהם מוצגים ב'''הדגשה'''.",
+       "wlheader-showupdated": "דפים שהשתנו מאז ביקורך האחרון בהם מוצגים ב<strong>הדגשה</strong>.",
        "wlnote": "להלן {{PLURAL:$1|השינוי האחרון|<strong>$1</strong> השינויים האחרונים}} {{PLURAL:$2|בשעה האחרונה|בשעתיים האחרונות|ב־<strong>$2</strong> השעות האחרונות}}, עד $4, $3.",
        "wlshowlast": "הצגת $1 שעות אחרונות $2 ימים אחרונים",
        "watchlist-hide": "הסתרת",
        "enotif_subject_moved": "הדף \"$1\" ב{{grammar:תחילית|{{SITENAME}}}} הועבר על־ידי $2",
        "enotif_subject_restored": "הדף \"$1\" ב{{grammar:תחילית|{{SITENAME}}}} שוחזר על־ידי $2",
        "enotif_subject_changed": "הדף \"$1\" ב{{grammar:תחילית|{{SITENAME}}}} שוּנה על־ידי $2",
-       "enotif_body_intro_deleted": "×\94×\93×£ \"$1\" ×\91×\90תר {{SITENAME}} × ×\9e×\97ק ×\91Ö¾$PAGEEDITDATE ×¢×\9cÖ¾×\99×\93×\99 $2; ×¨×\90×\95 $3.",
+       "enotif_body_intro_deleted": "×\94×\93×£ \"$1\" ×\91×\90תר {{SITENAME}} × ×\9e×\97ק ×\91Ö¾$PAGEEDITDATE ×¢×\9cÖ¾×\99×\93×\99 $2; ×\9c×\94×\9c×\9f ×\94ק×\99ש×\95ר ×\9c×\93×£: $3.",
        "enotif_body_intro_created": "הדף \"$1\" באתר {{SITENAME}} נוצר ב־$PAGEEDITDATE על־ידי $2; ראו $3 לגרסה הנוכחית של הדף.",
        "enotif_body_intro_moved": "הדף \"$1\" באתר {{SITENAME}} הועבר ב־$PAGEEDITDATE על־ידי $2; ראו $3 לגרסה הנוכחית של הדף.",
        "enotif_body_intro_restored": "הדף \"$1\" באתר {{SITENAME}} שוחזר ב־$PAGEEDITDATE על־ידי $2; ראו $3 לגרסה הנוכחית של הדף.",
index 8f660b0..804e1ff 100644 (file)
        "subject-preview": "Tárgy előnézete:",
        "previewerrortext": "Hiba történt a változások előnézetének megjelenítése során.",
        "blockedtitle": "A szerkesztő blokkolva van",
-       "blockedtext": "<strong>A szerkesztőnevedet vagy az IP-címedet blokkoltuk.</strong>\n\nA blokkolást $1 végezte el.\nAz általa felhozott indok: <em>$2.</em>\n\n* A blokk kezdete: $8\n* A blokk lejárata: $6\n* Blokkolt szerkesztő: $7\n\nKapcsolatba léphetsz $1 szerkesztőnkkel vagy egy másik [[{{MediaWiki:Grouppage-sysop}}|adminisztrátorral]], és megbeszélheted vele a blokkolást.\nAz „{{int:emailuser}}” funkciót csak akkor használhatod, ha érvényes e-mail címet adtál meg [[Special:Preferences|fiókbeállításaidban]], és nem blokkolták a használatát.\nJelenlegi IP-címed: $3, a blokkolás azonosítószáma: #$5.\nKérjük, hogy érdeklődés esetén minden fenti részletet adj meg.",
+       "blockedtext": "<strong>A szerkesztőnevedet vagy az IP-címedet blokkoltuk.</strong>\n\nA blokkolást $1 végezte el.\nAz általa felhozott indok: <em>$2.</em>\n\n* A blokk kezdete: $8\n* A blokk lejárata: $6\n* Blokkolt szerkesztő: $7\n\nKapcsolatba léphetsz $1 szerkesztőnkkel vagy egy másik [[{{MediaWiki:Grouppage-sysop}}|adminisztrátorral]], és megbeszélheted vele a blokkolást.\nAz „{{int:emailuser}}” funkciót csak akkor használhatod, ha érvényes e-mail-címet adtál meg [[Special:Preferences|fiókbeállításaidban]], és nem blokkolták a használatát.\nJelenlegi IP-címed: $3, a blokkolás azonosítószáma: #$5.\nKérjük, hogy érdeklődés esetén minden fenti részletet adj meg.",
        "autoblockedtext": "Az IP-címed automatikusan blokkolva lett, mert korábban egy olyan szerkesztő használta, akit $1 blokkolt, az alábbi indoklással:\n\n:''$2''\n\n*A blokk kezdete: '''$8'''\n*A blokk lejárata: '''$6'''\n*Blokkolt szerkesztő: '''$7'''\n\nKapcsolatba léphetsz $1 szerkesztőnkkel, vagy egy másik [[{{MediaWiki:Grouppage-sysop}}|adminisztrátorral]], és megbeszélheted vele a blokkolást.\n\nAz „{{int:emailuser}}” funkciót csak akkor használhatod, ha érvényes e-mail címet adtál meg\n[[Special:Preferences|fiókbeállításaidban]], és nem blokkolták a használatát.\n\nJelenlegi IP-címed: $3, a blokkolás azonosítószáma: #$5.\nKérjük, hogy érdeklődés esetén mindkettőt add meg.",
        "systemblockedtext": "A felhasználónevedet vagy IP-címedet automatikusan blokkolta a MediaWiki.\nA blokkolás indoka:\n\n:<em>$2</em>\n\n* A blokk kezdete: $8\n* A blokk lejárata: $6\n* Blokkolt szerkesztő: $7\n\nA jelenlegi IP-címed: $3.\nKérjük, hogy érdeklődés esetén minden fenti részletet adj meg.",
        "blockednoreason": "nem adott meg okot",
index a5b2319..126ac40 100644 (file)
        "mergehistory-reason": "Бахьан:",
        "mergelog": "ВIашагIтеха хиннарий тептар",
        "revertmerge": "Дéкъа",
-       "history-title": "\"$1\" — хувцамай истори",
+       "history-title": "«$1» яхача оагIон хувцамаш",
        "difference-title": "$1 — эршашта юкъе йола башхало",
        "lineno": "МугI $1:",
        "compareselectedversions": "ВIаши йиста хержа версеш",
index 1b89991..09164d8 100644 (file)
        "pagedata-title": "문서 데이터",
        "pagedata-text": "이 문서는 문서에 대한 데이터 인터페이스를 제공합니다. 하위 문서 문법을 사용하여 URL에 문서 제목을 지정해 주십시오.\n* 클라이언트의 Accept 헤더에 기반하여 내용이 절충됩니다. 즉, 문서 데이터는 클라이언트가 선호하는 형식으로 제공됩니다.",
        "pagedata-not-acceptable": "일치하는 형식을 찾을 수 없습니다. 지원하는 MIME 형식: $1",
-       "pagedata-bad-title": "유효하지 않은 제목: $1."
+       "pagedata-bad-title": "유효하지 않은 제목: $1.",
+       "unregistered-user-config": "보안을 이유로 자바스크립트, CSS, JSON 사용자 하위 문서들은 비등록 사용자에게는 불러올 수 없습니다."
 }
index 5987559..6f4154e 100644 (file)
        "user-mail-no-addy": "Mēģināja sūtīt e-pastu bez e-pasta adreses.",
        "user-mail-no-body": "Mēģināja sūtīt e-pastu ar tukšu vai nepamatoti īsu pamata daļu.",
        "changepassword": "Mainīt paroli",
+       "resetpass_announce": "Lai pabeigtu pieslēgšanos, tev ir jāuzstāda jauna parole.",
        "resetpass_header": "Mainīt konta paroli",
        "oldpassword": "Vecā parole",
        "newpassword": "Jaunā parole",
        "retypenew": "Atkārto jauno paroli",
        "resetpass_submit": "Uzstādīt paroli un ieiet",
        "changepassword-success": "Tava parole tika nomainīta!",
+       "changepassword-throttled": "Jūs esat veicis pārāk daudz pieslēgšanās mēģinājumus.\nLūdzu, uzgaidiet $1 pirms mēģiniet vēlreiz.",
        "botpasswords": "Botu paroles",
        "botpasswords-disabled": "Botu paroles ir atspējotas.",
        "botpasswords-no-central-id": "Lai izmantotu botu paroles, tev jāpieslēdzas centralizētajam kontam.",
        "history-feed-description": "Šīs wiki lapas versiju hronoloģija",
        "history-feed-item-nocomment": "$1 : $2",
        "history-feed-empty": "Pieprasītā lapa nepastāv.\nIespējams, tā ir izdzēsta vai pārdēvēta.\nMēģiniet [[Special:Search|meklēt]], lai atrastu saistītas lapas!",
+       "history-edit-tags": "Labot iezīmes izvēlētajām versijām",
        "rev-deleted-comment": "(labojuma kopsavilkums dzēsts)",
        "rev-deleted-user": "(lietotāja vārds nodzēsts)",
        "rev-deleted-event": "(reģistra detaļas noņemtas)",
        "search-category": "(kategorija $1)",
        "search-file-match": "(atbilst faila saturam)",
        "search-suggest": "Vai jūs domājāt: $1",
+       "search-rewritten": "Rāda rezultātus frāzei \"$1\". Meklēt pēc \"$2\".",
        "search-interwiki-caption": "Rezultāti no citiem projektiem",
        "search-interwiki-default": "Rezultāti no $1:",
        "search-interwiki-more": "(vairāk)",
        "default": "pēc noklusējuma",
        "prefs-files": "Faili",
        "prefs-custom-css": "Personīgais CSS",
+       "prefs-custom-json": "Pielāgots JSON",
        "prefs-custom-js": "Personīgais JS",
        "prefs-common-config": "Koplietojams CSS/JavaScript visās apdarēs:",
        "prefs-emailconfirm-label": "E-pasta statuss:",
        "right-editcontentmodel": "Labot lapas satura modeli",
        "right-editinterface": "Izmainīt dalībnieka interfeisu",
        "right-editusercss": "Izmainīt citu dalībnieku CSS failus",
+       "right-edituserjson": "Izmainīt citu dalībnieku JSON failus",
        "right-edituserjs": "Izmainīt citu dalībnieku JS failus",
        "right-editmyusercss": "Rediģējiet savus dalībnieka CSS failus",
+       "right-editmyuserjson": "Izmainīt savus dalībnieka JSON failus",
        "right-editmyuserjs": "Rediģējiet savus dalībnieka JavaScript failus",
        "right-viewmywatchlist": "Apskatīt savu uzraugāmo rakstu sarakstu",
        "right-viewmyprivateinfo": "Skatit savus privātos datus (piemēram, e-pasta adresi, īsto vārdu)",
        "uploadstash-errclear": "Failu tīrīšana neizdevās.",
        "uploadstash-refresh": "Atsvaidzināt failu sarakstu",
        "uploadstash-thumbnail": "aplūkot sīkbildi",
+       "uploadstash-bad-path": "Ceļš nepastāv.",
+       "uploadstash-bad-path-invalid": "Ceļš nav derīgs.",
        "uploadstash-bad-path-unknown-type": "Nezināms tips \"$1\".",
        "uploadstash-bad-path-unrecognized-thumb-name": "Neatpazīts sīktēla nosaukums.",
        "uploadstash-file-not-found-no-thumb": "Nevarēja iegūt sīkbildi.",
        "randompage": "Nejauša lapa",
        "randomincategory": "Nejauša lapa kategorijā",
        "randomincategory-invalidcategory": "\"$1\" nav derīgs kategorijas nosaukums.",
+       "randomincategory-nopages": "Kategorijā [[:Category:$1|$1]] nav lapu.",
        "randomincategory-category": "Kategorija:",
        "randomincategory-legend": "Nejauša lapa kategorijā",
        "randomincategory-submit": "Aiziet!",
        "statistics-users": "Reģistrēti dalībnieki",
        "statistics-users-active": "Aktīvi lietotāji",
        "statistics-users-active-desc": "Lietotāji, kas ir veikuši jebkādu darbību {{PLURAL:$1|iepriekšējās $1 dienās|iepriekšējā $1 dienā|iepriekšējās $1 dienās}}",
+       "pageswithprop": "Lapas ar lapas īpašību",
+       "pageswithprop-legend": "Lapas ar lapas īpašību",
+       "pageswithprop-text": "Šajā lapā uzskaitītas lapas ar konkrētu lapas īpašību.",
        "pageswithprop-prop": "Īpašības nosaukums:",
+       "pageswithprop-reverse": "Kārtot apgrieztā secībā",
+       "pageswithprop-sortbyvalue": "Kārtot pēc īpašības vērības",
        "pageswithprop-submit": "Aiziet",
        "doubleredirects": "Divkāršas pāradresācijas lapas",
        "doubleredirectstext": "Šajā lapā ir uzskaitītas pāradresācijas lapas, kuras pāradresē uz citām pāradresācijas lapām.\nKatrā rindiņā ir saites uz pirmo un otro pāradresācijas lapu, kā arī pirmā rindiņa no otrās pāradresācijas lapas teksta, kas parasti ir faktiskā \"gala\" lapa, uz kuru vajadzētu būt saitei pirmajā lapā.\n<del>Nosvītrotie</del> ieraksti jau ir tikuši salaboti.",
        "listgrouprights-namespaceprotection-header": "Vārdtelpas ierobežojumi",
        "listgrouprights-namespaceprotection-namespace": "Vārdtelpa",
        "listgrants-rights": "Tiesības",
+       "trackingcategories": "Izsekošanas kategorijas",
+       "trackingcategories-msg": "Izsekošanas kategorija",
        "trackingcategories-nodesc": "Apraksts nav pieejams.",
        "trackingcategories-disabled": "Kategorija ir atslēgta",
        "mailnologin": "Nav adreses, uz kuru sūtīt",
        "import-interwiki-submit": "Importēt",
        "import-mapping-namespace": "Importēt vārdtelpā:",
        "import-upload-filename": "Faila nosaukums:",
+       "import-upload-username-prefix": "Starpviki prefikss:",
        "import-comment": "Komentārs:",
        "importstart": "Importē lapas...",
        "import-revision-count": "$1 {{PLURAL:$1|versijas|versija|versijas}}",
        "tags-create-already-exists": "Iezīme \"$1\" jau pastāv.",
        "tags-delete-title": "Dzēst iezīmi",
        "tags-delete-reason": "Iemesls:",
+       "tags-delete-not-found": "Iezīme \"$1\" nepastāv.",
        "tags-delete-no-permission": "Tev nav atļaujas dzēst izmaiņu iezīmes.",
        "tags-activate-title": "Aktivizēt iezīmi",
        "tags-activate-reason": "Iemesls:",
+       "tags-activate-not-found": "Iezīme \"$1\" nepastāv.",
        "tags-activate-submit": "Aktivizēt",
        "tags-deactivate-title": "Deaktivizēt iezīmi",
        "tags-deactivate-reason": "Iemesls:",
        "logentry-newusers-create": "Lietotāja konts $1 tika {{GENDER:$2|izveidots}}",
        "logentry-newusers-create2": "$1 {{GENDER:$2|izveidoja}} lietotāja kontu $3",
        "logentry-newusers-autocreate": "Lietotaja konts $1 tika {{GENDER:$2|izveidots}} automātiski",
+       "logentry-protect-unprotect": "$1 {{GENDER:$2|noņēma}} aizsardzību no $3",
        "logentry-protect-protect": "$1 {{GENDER:$2|aizsargāja}} $3 $4",
        "logentry-upload-upload": "$1 {{GENDER:$2|augšupielādēja}} $3",
        "logentry-upload-overwrite": "$1 augšupielādēja jaunu $3 versiju",
        "duration-centuries": "$1 {{PLURAL:$1|gadsimti|gadsimts|gadsimti}}",
        "duration-millennia": "$1 {{PLURAL:$1|tūkstošgades|tūkstošgade|tūkstošgades}}",
        "limitreport-title": "Parsētāja profilēšanas dati:",
+       "limitreport-cputime": "CPU laika lietojums",
        "limitreport-cputime-value": "$1 {{PLURAL:$1|sekundes|sekunde|sekundes}}",
+       "limitreport-walltime": "Reālā laika lietojums",
        "limitreport-walltime-value": "$1 {{PLURAL:$1|sekundes|sekunde|sekundes}}",
        "limitreport-postexpandincludesize-value": "$1/$2 {{PLURAL:$2|baiti|baits|baiti}}",
        "limitreport-templateargumentsize": "Veidnes argumenta izmērs",
        "special-characters-group-persian": "Persiešu",
        "special-characters-group-hebrew": "Ebreju",
        "special-characters-group-bangla": "Bengāļu",
+       "special-characters-group-tamil": "Tamilu",
        "special-characters-group-telugu": "Telugu",
        "special-characters-group-sinhala": "Singāļu",
        "special-characters-group-gujarati": "Gudžarati",
        "sessionprovider-generic": "$1 sesijas",
        "randomrootpage": "Nejauša saknes lapa",
        "log-action-filter-suppress": "Cenzēšanas veids:",
+       "log-action-filter-upload": "Augšupielādes veids:",
+       "log-action-filter-block-unblock": "Atbloķēšana",
        "log-action-filter-delete-delete": "Lapas dzēšana",
        "log-action-filter-managetags-create": "Iezīmes izveide",
        "log-action-filter-managetags-delete": "Iezīmes dzēšana",
index 975ba61..fc259b2 100644 (file)
        "apisandbox-dynamic-parameters-add-label": "Додај параметар:",
        "apisandbox-dynamic-parameters-add-placeholder": "Назив на параметарот",
        "apisandbox-dynamic-error-exists": "Праметарот по име „$1“ веќе постои.",
+       "apisandbox-templated-parameter-reason": "Овој [[Special:ApiHelp/main#main/templatedparams|шаблонизиран параметар]] се нуди според {{PLURAL:$1|вредноста|вредностите}} на $2.",
        "apisandbox-deprecated-parameters": "Застарени параметри",
        "apisandbox-fetch-token": "Самопополни ја шифрата",
        "apisandbox-add-multi": "Додај",
index c023aac..d394c0c 100644 (file)
        "confirm-purge-title": "Herny disse syde",
        "confirm_purge_button": "Bevestig",
        "confirm-purge-top": "Klik up 'bevestig' üm et tüskengehöägen van disse syde te leagen.",
-       "confirm-purge-bottom": "Et leagmaken van et tüskengehöägen sörgt dervöär dat jy de lätste versy van een syde te syn krygen.",
+       "confirm-purge-bottom": "Et leagmaken van et tüskengehöägen sörgt dervöär dat jy de lätste versy van een syde te seen krygen.",
        "confirm-watch-button": "Oké",
        "confirm-watch-top": "Disse zied op joew volglieste zetten?",
        "confirm-unwatch-button": "Oké",
index a412a59..83e855f 100644 (file)
        "pagedata-title": "Paginagegevens",
        "pagedata-text": "Deze pagina biedt een data-interface voor pagina's. Geef een paginatitel op door deze in de URL op te nemen, op de manier van een deelpagina.\n* De inhoud wordt afgestemd op de door de client meegestuurde Accept Header. Dit betekent dat de gegevens voor de pagina worden aangeboden in het voorkeursformaat van uw client.",
        "pagedata-not-acceptable": "Er is geen overeenkomende indeling gevonden. Ondersteunde MIME-typen: $1",
-       "pagedata-bad-title": "Ongeldige titel: $1."
+       "pagedata-bad-title": "Ongeldige titel: $1.",
+       "unregistered-user-config": "Vanwege veiligheidsredenen wordt worden gebruikersdeelpagina's met JavaScript, CSS en JSON niet langer geladen voor gebruikers die niet zijn geregistreerd."
 }
index ab4d43a..38ab558 100644 (file)
        "recentchangescount": "Domyślna liczba wyświetlanych edycji w ostatnich zmianach, historii i rejestrach:",
        "prefs-help-recentchangescount": "Maksymalna liczba: 1000",
        "prefs-help-watchlist-token2": "To jest tajny klucz umożliwiający dostęp do kanału internetowego zmian w obserwowanych przez ciebie stronach.\nKażdy, kto go zna, będzie mógł je zobaczyć, więc zachowaj go dla siebie.\n[[Special:ResetTokens|Kliknij tu, jeśli chcesz go zresetować]].",
-       "prefs-help-tokenmanagement": "Możesz zobaczyć i zresetować sekretny klucz przypisany do konta, służący do uzyskania dostępu do kanału internetowego zmian w obserwowanych przez ciebie stronach. Każdy, kto go zna, będzie mógł je zobaczyć, więc nie udostępniaj go.",
+       "prefs-help-tokenmanagement": "Możesz zobaczyć i zresetować tajny klucz przypisany do Twojego konta, służący do uzyskania dostępu do kanału internetowego zmian w obserwowanych przez ciebie stronach. Każdy, kto go zna, będzie mógł je zobaczyć, więc nie udostępniaj go.",
        "savedprefs": "Twoje preferencje zostały zapisane.",
        "savedrights": "Zapisano grupy {{GENDER:$1|użytkownika $1|użytkowniczki $1}}.",
        "timezonelegend": "Strefa czasowa:",
index 0b9c96a..5cd407a 100644 (file)
@@ -18,7 +18,8 @@
                        "Purodha",
                        "Macofe",
                        "Matma Rex",
-                       "Fitoschido"
+                       "Fitoschido",
+                       "Paolo Castellina"
                ]
        },
        "tog-underline": "Anliure con la sotliniadura",
@@ -46,7 +47,7 @@
        "tog-shownumberswatching": "Smon-e ël nùmer d'utent che as ten-o la pàgina sot-euj",
        "tog-oldsig": "Firma esistenta:",
        "tog-fancysig": "Traté la firma com dël test wiki (sensa n'anliura automàtica)",
-       "tog-uselivepreview": "Dovré la fonsion ''Preuva dal viv''",
+       "tog-uselivepreview": "Dovré la fonsion ''Preuva dal viv'' sensa carié la pàgina",
        "tog-forceeditsummary": "Ciamé conferma se ël resumé dla modìfica a l'é veujd",
        "tog-watchlisthideown": "Stërmé mie modìfiche ant la ròba che im ten-o sot-euj",
        "tog-watchlisthidebots": "Stërmé le modìfiche fàite daj trigomiro ant la lista dle ròbe che im ten-o sot-euj",
@@ -59,7 +60,7 @@
        "tog-showhiddencats": "Smon-e le categorìe stërmà",
        "tog-norollbackdiff": "Fé nen vëdde le diferense apress d'avèj ripristinà",
        "tog-useeditwarning": "Aviseme quand che i chito na pàgina ëd modìfiche con dle modìfiche nen salvà",
-       "tog-prefershttps": "Dovré sempe na conession sigura pr'ësté andrinta al sistema",
+       "tog-prefershttps": "Dovré sempe na conession sicura quand ch'a l'é intrà ant ël sistema",
        "underline-always": "Sempe",
        "underline-never": "Mai",
        "underline-default": "Stàndard dël navigator o dël tema",
        "newwindow": "(as deurb ant na fnestra neuva)",
        "cancel": "Anulé",
        "moredotdotdot": "Ëd pì...",
-       "morenotlisted": "Costa lista a l'é nen completa.",
+       "morenotlisted": "Costa lista a podrìa esse nen completa.",
        "mypage": "Pàgina",
        "mytalk": "Ciaciarade",
-       "anontalk": "Ciaciarade për st'adrëssa IP-sì",
+       "anontalk": "Discussion",
        "navigation": "Navigassion",
        "and": "&#32;e",
        "faq": "Chestion frequente",
        "searcharticle": "Andé",
        "history": "Version pì veje",
        "history_short": "Stòria",
+       "history_small": "stòria",
        "updatedmarker": "agiornà da l'ùltima vira che i son passà",
        "printableversion": "Version bon-a për stampé",
        "permalink": "Anliura fissa",
        "redirectedfrom": "(Ridiression da $1)",
        "redirectpagesub": "Pàgina ëd ridiression",
        "redirectto": "Ridiression a:",
-       "lastmodifiedat": "Modificà l'ùltima vira ai $1 a $2.",
+       "lastmodifiedat": "Modificà l'ùltima vira dël $1, al $2.",
        "viewcount": "St'artìcol-sì a l'é stàit lesù {{PLURAL:$1|na vira|$1 vire}}.",
        "protectedpage": "Pàgina proteta",
        "jumpto": "Andé a:",
        "viewsource": "Vardé la sorgiss",
        "viewsource-title": "Vëdde la sorgiss ëd $1",
        "actionthrottled": "Assion limità",
-       "actionthrottledtext": "Për evité che 'd gent ò 'd màchine an carìo dla rumenta, st'assion-sì as peul nen fesse tròp ëd soèns, e chiel a l'ha arpetula tròpe vire. Ch'a sia gentil, ch'a preuva torna antra dontré minute.",
+       "actionthrottledtext": "Për evité che 'd gent ò 'd màchine an carìo dla rumenta, st'assion-sì as peul nen fesse tròp ëd soèns, e ti 't l'has arpetula tròpe vire. Sie gentil, preuva torna antra dontré minute.",
        "protectedpagetext": "Sta pàgina-sì a l'è stàita blocà për evité 'd modìfiche o d'àutre assion.",
        "viewsourcetext": "A peul vardé e copié la sorgiss dë sta pàgina.",
        "viewyourtext": "A peul vëdde e copié la sorgiss ëd <strong>soe modìfiche</strong> a costa pàgina-sì.",
        "createacct-reason": "Rason",
        "createacct-reason-ph": "Përchè a crea n'àutr cont",
        "createacct-submit": "Ch'a crea sò cont",
-       "createacct-another-submit": "Creé n'àutr cont",
+       "createacct-another-submit": "Creé un cont",
        "createacct-benefit-heading": "{{SITENAME}} a l'é fàit da 'd gent coma chiel.",
        "createacct-benefit-body1": "{{PLURAL:$1|modìfica|modìfiche}}",
        "createacct-benefit-body2": "{{PLURAL:$1|pàgina|pàgine}}",
        "noname": "A l'ha nen ëspessificà në stranòm vàlid.",
        "loginsuccesstitle": "Compliment! A l'é pen-a rintrà ant ël sistema.",
        "loginsuccess": "'''Adess a l'é colegà a {{SITENAME}} con lë stranòm «$1».'''",
-       "nosuchuser": "A-i é pa gnun utent con lë stranòm «$1».\nJë stranòm ëd j'utent a son sensìbij a le majùscole.\nCh'a contròla ël nòm che a l'ha batù, o [[Special:CreateAccount|ch'a crea un neuv cont]].",
+       "nosuchuser": "A-i é pa gnun utent con lë stranòm «$1».\nJë stranòm ëd j'utent a son sensìbij a le majùscole.\nContròla ël nòm ch'it l'has batù, o [[Special:CreateAccount|crea un cont neuv]].",
        "nosuchusershort": "A-i é pa gnun utent che as ciama «$1». Për piasì, che a contròla se a l'ha scrit tut giust.",
        "nouserspecified": "A venta che a specìfica në stranòm d'utent",
        "login-userblocked": "St'utent-sì a l'é blocà. A peul pa intré ant ël sistema.",
        "eauthentsent": "A l'adrëssa che a l'ha dane i l'oma mandaje un mëssagi ëd pòsta eletrònica për conferma.\nAnans che qualsëssìa àutr messagi ëd pòsta a ven-a mandà a 's cont-sì, a venta che a a fasa coma che a-j diso dë fé ant ël mëssagi, për confermé che ës cont a l'é da bon sò.",
        "throttled-mailpassword": "Na ciav neuva a l'é gia stàita mandà da manch che {{PLURAL:$1|n'ora|$1 ore}}. Për evité dj'abus, mach un mëssagi ëd ri-inissialisassion ëd ciav a sarà mandà minca {{PLURAL:$1|ora|$1 ore}}.",
        "mailerror": "Eror ën mandand via un mëssagi ëd pòsta eletrònica: $1",
-       "acct_creation_throttle_hit": "Dij visitador ëd costa wiki, an dovrand soa adrëssa IP a l'han creà {{PLURAL:$1|1 cont|$1 cont}} ant l'ùltim di, che a l'é tut lòn che as peul fesse ant cost temp.\nËd conseguensa, ij visitador che a deuvro costa adrëssa IP a peulo pì nen fé dij cont al moment.",
+       "acct_creation_throttle_hit": "Dij visitador ëd costa wiki, an dovrand soa adrëssa IP a l'han creà {{PLURAL:$1|1 cont|$1 cont}} ant l'ùltim $2, che a l'é tut lòn che as peul fesse ant cost temp.\nËd conseguensa, ij visitador che a deuvro costa adrëssa IP a peulo pì nen fé dij cont al moment.",
        "emailauthenticated": "Soa adrëssa ëd pòsta eletrònica a l'é stàita confirmà ël $2 a $3.",
        "emailnotauthenticated": "Soa adrëssa ëd pòsta eletrònica a l'é pa ancó stàita confirmà.\nPër qualsëssìa ëd coste funsion a sarà mandà gnun mëssagi.",
        "noemailprefs": "Che a specìfica n'adrëssa ëd pòsta eletrònica se a veul dovré coste funsion-sì.",
        "createaccount-title": "Creassion d'un cont për {{SITENAME}}",
        "createaccount-text": "Cheidun a l'ha duvertà un cont për soa adrëssa ëd pòsta eletrònica ansima a {{SITENAME}} ($4) butand da stranòm «$2» e da ciav «$3». A dovrìa rintré ant ël sistema e cambiesse soa ciav pì ampressa ch'a peul.\n\nSe sòn a l'é rivà për eror, a peul lassé perde e fé gnente sensa problema.",
        "login-throttled": "A l'ha fàit tròpi tentativ recent d'intré ant ël sistema.\nPër piasì, ch'a speta $1 prima ëd prové torna.",
-       "login-abort-generic": "Sò tentitiv d'intré ant ël sistema a l'é falì - Abortì",
+       "login-abort-generic": "Sò tentativ d'intré ant ël sistema a l'é falì - Abortì",
        "login-migrated-generic": "Sò cont a l'ha emigrà, e sò stranòm a esist pi nen su costa wiki.",
        "loginlanguagelabel": "Lenga: $1",
        "suspicious-userlogout": "Soa arcesta ëd seurte dal sistema a l'é stàita arfudà përchè a smija com s'a fussa stàita mandà da 'n navigador rot o da l'archiviassion an local d'un prëstanòm.",
        "passwordreset-emailtext-user": "L'utent $1 ansima a {{SITENAME}} a l'ha ciamà na riampostassion ëd soa ciav për {{SITENAME}} ($4). {{PLURAL:$3|Ël cont utent sì-sota a l'é|Ij cont utent sì-sota a son}} associà a st'adrëssa ëd pòsta eletrònica:\n\n$2\n\n{{PLURAL:$3|Costa ciav provisòria|Coste ciav provisòrie}} a scadran da-sì {{PLURAL:$5|un di|$5 di}}.\nA dovrìa intré ant ël sistema e serne na ciav neuva adess. Se quaidun d'àutr a l'ha fàit costa arcesta, o s'a l'é arcordasse soa ciav original, e a veul pa pi cangela, a peul ignoré ës mëssagi e continué a dovré soa veja ciav.",
        "passwordreset-emailelement": "Stranòm: \n$1\n\nCiav provisòria: \n$2",
        "passwordreset-emailsentemail": "Un mëssagi ëd riampostassion ëd la ciav a l'é stàit spedì.",
-       "changeemail": "Cangé l'adrëssa ëd pòsta eletrònica",
+       "changeemail": "Cangé o dëscancelé l'adrëssa ëd pòsta eletrònica",
        "changeemail-header": "Cangé l'adrëssa ëd pòsta eletrònica dël cont",
        "changeemail-no-info": "A dev esse intrà ant ël sistema për andé diretament a costa pàgina.",
        "changeemail-oldemail": "Adrëssa ëd pòsta eletrònica atual:",
        "anonpreviewwarning": "''A l'é nen rintrà ant ël sistema. An salvand a sarà memorisà soa adrëssa IP ant la stòria dle modìfiche ëd sa pàgina.''",
        "missingsummary": "'''Nòta:''' a l'ha butà gnun resumé dla modìfica. Se a sgnaca «$1» n'àutra vira, soa modìfica a resterà salvà sensa resumé.",
        "selfredirect": "<strong>Atension:</strong> A l'é an camin ch'a ridiression-a sa pàgina a chila-midema.\nMiraco a l'ha spessificà ël bërsaj sbalià për la ridiression, opura a l'é an camin ch'a modìfica la pàgina sbalià.\nS'a sgnaca torna ansima a «$1», la ridiression a sarà creà istess.",
-       "missingcommenttext": "Për piasì, che a buta un coment sì-sota.",
+       "missingcommenttext": "Për piasì, buta un coment sì-sota.",
        "missingcommentheader": "'''Ch'a ten-a da ment:''' A l'ha pa dàit ëd soget o d'intestassion për cost coment.\nSe a sgnaca torna «$1», soa modìfica a sarà salvà sensa gnun-a intestassion.",
-       "summary-preview": "Preuva dël resumé:",
-       "subject-preview": "Preuva dl'oget/intestassion:",
+       "summary-preview": "Preuva dla compilassion dël resumé:",
+       "subject-preview": "Previsualisassion dl'oget:",
        "previewerrortext": "A l'é rivaje n'eror durant ël tentativ ëd previsualisassion ëd soe modìfiche.",
        "blockedtitle": "L'utent a l'é blocà.",
        "blockedtext": "'''Sò stranòm ò pura adrëssa IP a l'é stàit blocà.'''\n\nËl blocagi a l'é stàit fàit da $1.\nComa rason a l'ha butà ''$2''.\n\n* Blocà a parte dal: $8\n* Fin al: $6\n* As veul blochesse: $7\n\nA peul butesse an contat con $1 ò pura n'àotr [[{{MediaWiki:Grouppage-sysop}}|aministrator]] për discute ëd sò blocagi.\nCh'a ten-a present ch'a podrà dovré la fonsion «mandeje un messagi ëd pòsta eletrònica a l'utent» mach s'a l'ha specificà n'adrëssa ëd vàlida ant [[Special:Preferences|sò gust]] e se sta fonsion a l'é nen ëstàita blocà 'cò chila.\nSoa adrëssa IP corenta a l'é $3, e l'identificativ dël blocagi a l'é #$5.\nPër piasì, ch'a-j buta tut e doj ant soe comunicassion ant sta question-sì.",
        "search-file-match": "(a corëspond al contnù d'archivi)",
        "search-suggest": "Vorìi-lo pa dì: $1",
        "search-rewritten": "Visualisassion dj'arzultà për $1. Sërché nopà $2.",
-       "search-interwiki-caption": "Proget frej",
+       "search-interwiki-caption": "Arzultà dij proget frej",
        "search-interwiki-default": "Arzultà da $1:",
        "search-interwiki-more": "(ëd pì)",
        "search-relatedarticle": "Corelà",
        "prefs-watchlist-token": "Geton ëd lòn che as ten sot euj:",
        "prefs-misc": "Sòn e lòn",
        "prefs-resetpass": "Cangé la ciav",
-       "prefs-changeemail": "Cangé l'adrëssa ëd pòsta eletrònica",
+       "prefs-changeemail": "Cangé o dëscancelé l'adrëssa ëd pòsta eletrònica",
        "prefs-setemail": "Amposté n'adrëssa ëd pòsta eletrònica",
        "prefs-email": "Opsion ëd pòsta eletrònica",
        "prefs-rendering": "Sembiansa",
        "group-bot": "Trigomiro",
        "group-sysop": "Aministrator",
        "group-bureaucrat": "Mangiapapé",
-       "group-suppress": "Supervisor",
+       "group-suppress": "Ancarià dle sopression",
        "group-all": "(utent)",
        "group-user-member": "{{GENDER:$1|utent}}",
        "group-autoconfirmed-member": "{{GENDER:$1|utent ch'a l'é convalidasse daspërchiel|utent ch'a l'é convalidasse daspërchila}}",
        "group-bot-member": "{{GENDER:$1|trigomiro}}",
        "group-sysop-member": "{{GENDER:$1|aministrator|aministratris}}",
        "group-bureaucrat-member": "{{GENDER:$1|mangiapapé}}",
-       "group-suppress-member": "{{GENDER:$1|supervisor}}",
+       "group-suppress-member": "{{GENDER:$1|ancarià dle sopression}}",
        "grouppage-user": "{{ns:project}}:Utent",
        "grouppage-autoconfirmed": "{{ns:project}}:Utent ch'a son convalidasse daspërlor",
        "grouppage-bot": "{{ns:project}}:Trigomiro",
        "grouppage-sysop": "{{ns:project}}:Aministrator",
        "grouppage-bureaucrat": "{{ns:project}}:Mangiapapé",
-       "grouppage-suppress": "{{ns:project}}:Supervisor",
+       "grouppage-suppress": "{{ns:project}}:Fà la sopression",
        "right-read": "Lese le pàgine",
        "right-edit": "Modifiché le pàgine",
        "right-createpage": "Creé dle pàgine (che a son pa dle pàgine ëd discussion)",
index 7818961..43b0032 100644 (file)
        "apisandbox-dynamic-parameters-add-label": "Parâmetro adicional",
        "apisandbox-dynamic-parameters-add-placeholder": "Nome do parâmetro",
        "apisandbox-dynamic-error-exists": "Um parâmetro chamado \"$1\" já existe.",
+       "apisandbox-templated-parameter-reason": "Este [[Special:ApiHelp/main#main/templatedparams|parâmetro de predefinição]] é oferecido com base {{PLURAL:$1|no valor|nos valores}} de $2.",
        "apisandbox-deprecated-parameters": "Parâmetros obsoletos",
        "apisandbox-fetch-token": "Preencher automaticamente o token",
        "apisandbox-add-multi": "Adicionar",
index 0fc67f8..85ad5b4 100644 (file)
        "apisandbox-dynamic-parameters-add-label": "Adicionar parâmetro:",
        "apisandbox-dynamic-parameters-add-placeholder": "Nome do parâmetro",
        "apisandbox-dynamic-error-exists": "Um parâmetro com o nome \"$1\" já existe.",
+       "apisandbox-templated-parameter-reason": "Este [[Special:ApiHelp/main#main/templatedparams|parâmetro modelado]] é oferecido com base {{PLURAL:$1|no valor|nos valores}} de $2.",
        "apisandbox-deprecated-parameters": "Parâmetros obsoletos",
        "apisandbox-fetch-token": "Auto-preencher o token",
        "apisandbox-add-multi": "Adicionar",
index 97ac807..0947db2 100644 (file)
        "apisandbox-dynamic-parameters-add-label": "JavaScript label for the widget to add a new arbitrary parameter.",
        "apisandbox-dynamic-parameters-add-placeholder": "JavaScript text field placeholder for the widget to add a new arbitrary parameter.",
        "apisandbox-dynamic-error-exists": "Displayed as an error message from JavaScript when trying to add a new arbitrary parameter with a name that already exists. Parameters:\n* $1 - Parameter name that failed.",
+       "apisandbox-templated-parameter-reason": "Displayed (from JavaScript) on each instance of a templated parameter.\n\nParameters:\n* $1 - Number of fields in $2.\n* $2 - List of targeted fields, combined using {{msg-mw|comma-separator}} and {{msg-mw|and}}.",
        "apisandbox-deprecated-parameters": "JavaScript button label and fieldset legend for separating deprecated parameters in the UI.",
        "apisandbox-fetch-token": "Label for the button that fetches a CSRF token.",
        "apisandbox-add-multi": "Label for the button to add another value to a field that accepts multiple values\n{{Identical|Add}}",
index abf6b3c..f80a820 100644 (file)
        "apisandbox-dynamic-parameters-add-label": "Добавить параметр:",
        "apisandbox-dynamic-parameters-add-placeholder": "Имя параметра",
        "apisandbox-dynamic-error-exists": "Параметр с именем «$1» уже существует.",
+       "apisandbox-templated-parameter-reason": "Этот [[Special:ApiHelp/main#main/templatedparams|шаблонный параметр]] предлагается на основе {{PLURAL:$1|значения|значений}} $2.",
        "apisandbox-deprecated-parameters": "Устаревшие параметры",
        "apisandbox-fetch-token": "Автозаполнение токена",
        "apisandbox-add-multi": "Добавить",
index 65f27f6..81537a0 100644 (file)
        "userlogin-helplink2": "ᱵᱚᱞᱚᱜ ᱠᱷᱟᱹᱛᱤᱨ ᱜᱚᱸᱲᱚᱸ",
        "userlogin-createanother": "ᱮᱴᱟᱜ ᱠᱷᱟᱛᱟ ᱛᱮᱭᱟᱨᱢᱮ",
        "createacct-emailrequired": "ᱤᱢᱮᱞ ᱵᱩᱴᱟᱹ",
-       "createacct-emailoptional": "Email ᱴᱷᱤᱠᱱᱟ (ᱵᱟᱹᱲᱛᱤᱛᱮ)",
-       "createacct-email-ph": "ᱟᱢᱟᱜ email ᱴᱷᱤᱠᱱᱟ ᱵᱚᱞᱚᱭᱢᱮ",
+       "createacct-emailoptional": "ᱤᱢᱮᱞ ᱴᱷᱤᱠᱱᱟ (ᱟᱢᱠᱩᱥᱤ)",
+       "createacct-email-ph": "ᱟᱢᱟᱜ ᱤᱢᱮᱞ ᱵᱩᱴᱟᱹ ᱟᱫᱮᱨᱢᱮ",
        "createacct-another-email-ph": "ᱤᱢᱮᱞ ᱵᱩᱴᱟᱹ ᱟᱫᱮᱨᱢᱮ",
        "createaccountmail": "E-mail hotete",
        "createacct-realname": "ᱥᱚᱛ ᱧᱩᱛᱩᱢ (ᱚᱯᱥᱱᱟᱞ)",
        "createacct-another-submit": "ᱠᱷᱟᱛᱟ ᱛᱮᱭᱟᱨᱢᱮ",
        "createacct-continue-submit": "ᱠᱷᱟᱛᱟ ᱛᱮᱭᱟᱨ ᱛᱚᱝᱜᱮᱢᱮ",
        "createacct-another-continue-submit": "ᱠᱷᱟᱛᱟ ᱛᱮᱭᱟᱨ ᱛᱚᱝᱜᱮᱢᱮ",
-       "createacct-benefit-heading": "{{SITENAME}} ᱟᱢ ᱞᱮᱠᱟᱱ ᱦᱚᱲ ᱦᱚᱛᱮᱛᱮ ᱛᱮᱭᱟᱨ ᱟᱠᱟᱱ᱾",
+       "createacct-benefit-heading": "{{SITENAME}} á±«á±\9a á±\9fá±¢ á±\9eᱮᱠá±\9fá±± á±¦á±\9aá±² á±¦á±\9aá±\9bá±®á±\9bá±® á±\9bᱮᱭá±\9fᱨ á±\9fá± á±\9fᱱ᱾",
        "createacct-benefit-body1": "{{PLURAL:$1|ᱥᱟᱯᱲᱟᱣ|ᱥᱟᱯᱲᱟᱣᱠᱚ}}",
        "createacct-benefit-body2": "{{PLURAL:$1|ᱥᱟᱦᱴᱟ|ᱥᱟᱦᱴᱟᱠᱳ}}",
        "createacct-benefit-body3": "ᱱᱮᱛᱟᱨ {{PLURAL:$1|ᱮᱱᱮᱢᱤᱭᱟᱹ|ᱮᱱᱮᱢᱤᱭᱟᱹᱠᱚ}}",
        "summary-preview": "ᱜᱩᱴ ᱠᱟᱛᱷᱟ ᱩᱱᱩᱫᱩᱜ:",
        "subject-preview": "ᱜᱩᱴᱠᱟᱛᱷᱟ ᱩᱱᱩᱫᱩᱜ:",
        "blockedtitle": "ᱵᱮᱵᱷᱟᱨᱤᱡ ᱫᱚ ᱮᱥᱮᱫ ᱚᱪᱚᱣᱟᱠᱟᱱᱟᱭ",
-       "blockedtext": "<strong>ᱟᱢᱟᱜ ᱵᱮᱵᱷᱟᱨᱤᱭᱟᱹ ᱧᱩᱛᱩᱢ ᱟᱨᱵᱟᱝ IP ᱵᱩᱴᱟᱹ ᱫᱚ ᱵᱚᱸᱫᱽ ᱟᱠᱟᱱᱟ ᱾ </strong>\n\nᱱᱚᱶᱟ ᱵᱚᱸᱫᱽ ᱫᱚ $1 ᱫᱟᱨᱟᱭᱛᱮ ᱦᱩᱭᱟᱠᱱᱟ ᱾\nᱱᱚᱶᱟ ᱨᱮᱱᱟᱜ ᱚᱡᱮ ᱫᱚ ᱮᱢᱮᱱᱟ <em>$2</em>.\n\n* ᱵᱚᱸᱫᱽ ᱮᱦᱚᱵ: $8\n* ᱵᱚᱸᱫᱽ ᱢᱩᱪᱟᱹᱫ: $6\n* ᱟᱥᱟᱦᱟᱱ ᱵᱚᱸᱫᱽᱠᱚ: $7\n\nᱟᱢ $1 ᱮᱢ ᱥᱟᱹᱜᱟᱹᱭ ᱫᱟᱲᱮᱭᱟᱭᱟ ᱵᱟᱝᱠᱷᱟᱱ ᱮᱴᱟᱜ [[{{MediaWiki:Grouppage-sysop}}|ᱟᱰᱢᱤᱱᱤᱥᱴᱨᱮᱴᱚᱨ]] ᱵᱚᱸᱫᱽ ᱵᱟᱵᱚᱫᱽ ᱛᱮ ᱜᱟᱞᱚᱪ ᱞᱟᱹᱜᱤᱫ ᱾\nᱟᱢ ᱵᱟᱢ ᱵᱮᱵᱷᱟᱨ ᱫᱟᱲᱮᱭᱟᱜ \"email this user\" ᱥᱩᱵᱤᱫᱷᱟ ᱡᱚᱛᱷᱟᱛ ᱤᱢᱮᱞ ᱵᱩᱴᱟᱹ ᱛᱟᱢ ᱵᱟᱝ ᱛᱟᱦᱮᱸᱱ ᱠᱷᱟᱱ ᱟᱨ ᱱᱚᱶᱟ ᱫᱚ ᱪᱤᱱᱦᱟᱹᱣ-ᱟ [[Special:Preferences|ᱠᱷᱟᱛᱟ ᱧᱮᱞᱚᱚᱜ]] ᱠᱷᱚᱱ ᱟᱨ ᱟᱢ ᱫᱚ ᱵᱟᱢ ᱵᱚᱸᱫᱽ ᱟᱠᱟᱱᱟ ᱱᱚᱶᱟ ᱵᱮᱵᱷᱟᱨ ᱠᱷᱚᱱ ᱾\nᱟᱢᱟᱜ ᱱᱤᱛᱚᱜᱟᱜ IP ᱵᱩᱴᱟᱹ ᱫᱚ $3, ᱟᱨ ᱵᱚᱸᱫᱽ ID ᱫᱚ #$5  \nᱫᱟᱭᱟᱠᱟᱛᱮ ᱥᱮᱞᱮᱫᱽ ᱢᱮ ᱪᱮᱛᱟᱱᱟᱜ ᱠᱟᱛᱷᱟᱠᱚ ᱡᱚᱛᱚ ᱞᱮᱠᱟᱱ ᱠᱩᱠᱞᱤ ᱨᱮ ᱾",
+       "blockedtext": "<strong>ᱟᱢᱟᱜ ᱵᱮᱵᱷᱟᱨᱤᱭᱟᱹ ᱧᱩᱛᱩᱢ ᱟᱨᱵᱟᱝ IP ᱵᱩᱴᱟᱹ ᱫᱚ ᱵᱚᱸᱫᱽ ᱟᱠᱟᱱᱟ ᱾ </strong>\n\nᱱᱚᱶᱟ ᱵᱚᱸᱫᱽ ᱫᱚ $1 ᱫᱟᱨᱟᱭᱛᱮ ᱦᱩᱭᱟᱠᱱᱟ ᱾\nᱱᱚᱶᱟ ᱨᱮᱱᱟᱜ ᱚᱡᱮ ᱫᱚ ᱮᱢᱮᱱᱟ <em>$2</em>.\n\n* ᱵᱚᱸᱫᱽ ᱮᱦᱚᱵ: $8\n* ᱵᱚᱸᱫᱽ ᱢᱩᱪᱟᱹᱫ: $6\n* ᱟᱥᱟᱦᱟᱱ ᱵᱚᱸᱫᱽᱠᱚ: $7\n\nᱟᱢ $1 ᱮᱢ ᱥᱟᱹᱜᱟᱹᱭ ᱫᱟᱲᱮᱭᱟᱭᱟ ᱵᱟᱝᱠᱷᱟᱱ ᱮᱴᱟᱜ [[{{MediaWiki:Grouppage-sysop}}|ᱟᱰᱢᱤᱱᱤᱥᱴᱨᱮᱴᱚᱨ]] ᱵᱚᱸᱫᱽ ᱵᱟᱵᱚᱫᱽ ᱛᱮ ᱜᱟᱞᱚᱪ ᱞᱟᱹᱜᱤᱫ ᱾\nᱟᱢ ᱵᱟᱢ ᱵᱮᱵᱷᱟᱨ ᱫᱟᱲᱮᱭᱟᱜ \"{{int:emailuser}}\" ᱥᱩᱵᱤᱫᱷᱟ ᱡᱚᱛᱷᱟᱛ ᱤᱢᱮᱞ ᱵᱩᱴᱟᱹ ᱛᱟᱢ ᱵᱟᱝ ᱛᱟᱦᱮᱸᱱ ᱠᱷᱟᱱ ᱟᱨ ᱱᱚᱶᱟ ᱫᱚ ᱪᱤᱱᱦᱟᱹᱣ-ᱟ [[Special:Preferences|ᱠᱷᱟᱛᱟ ᱧᱮᱞᱚᱚᱜ]] ᱠᱷᱚᱱ ᱟᱨ ᱟᱢ ᱫᱚ ᱵᱟᱢ ᱵᱚᱸᱫᱽ ᱟᱠᱟᱱᱟ ᱱᱚᱶᱟ ᱵᱮᱵᱷᱟᱨ ᱠᱷᱚᱱ ᱾\nᱟᱢᱟᱜ ᱱᱤᱛᱚᱜᱟᱜ IP ᱵᱩᱴᱟᱹ ᱫᱚ $3, ᱟᱨ ᱵᱚᱸᱫᱽ ID ᱫᱚ #$5  \nᱫᱟᱭᱟᱠᱟᱛᱮ ᱥᱮᱞᱮᱫᱽ ᱢᱮ ᱪᱮᱛᱟᱱᱟᱜ ᱠᱟᱛᱷᱟᱠᱚ ᱡᱚᱛᱚ ᱞᱮᱠᱟᱱ ᱠᱩᱠᱞᱤ ᱨᱮ ᱾",
        "blockednoreason": "ᱡᱟᱸᱦᱟᱸᱱ ᱚᱡᱮ ᱵᱟᱝ ᱮᱢᱠᱟᱱᱟ",
        "whitelistedittext": "ᱥᱟᱦᱴᱟ ᱥᱟᱯᱲᱟᱣ ᱞᱟᱹᱜᱤᱛ $1 ᱮᱢ ᱦᱩᱭᱩᱜ-ᱟ᱾",
        "nosuchsectiontitle": "ᱛᱷᱚᱠ ᱵᱟᱝ ᱧᱟᱢᱞᱮᱱᱟ",
        "newarticle": "(ᱱᱟᱣᱟᱱᱟᱜ)",
        "newarticletext": "ᱟᱢ ᱚᱠᱟ ᱥᱟᱦᱴᱟ ᱨᱮᱱᱟᱜ ᱡᱚᱱᱟᱲᱮᱢ ᱯᱟᱸᱡᱟᱸ ᱟᱹᱜᱩᱭᱫᱟ ᱚᱱᱚ ᱫᱚ ᱵᱟᱱᱩᱜ-ᱟ᱾\nᱚᱱᱟ ᱥᱟᱦᱴᱟ ᱛᱮᱭᱟᱨ ᱞᱟᱹᱜᱤᱛ ᱛᱮ, ᱞᱟᱛᱟᱨ ᱵᱟᱠᱥᱚ ᱵᱷᱤᱛᱨᱤᱨᱮ ᱚᱞ ᱮᱦᱚᱵ ᱢᱮ (ᱟᱨᱦᱚᱸ ᱡᱟᱹᱥᱛᱤ ᱵᱟᱰᱟᱭ ᱞᱟᱹᱜᱤᱛᱴᱮ [$1 ᱜᱚᱸᱲᱚᱸ ᱥᱟᱦᱴᱟ] ᱯᱟᱸᱡᱚᱸᱭᱢᱮ)᱾\nᱟᱢ ᱵᱷᱩᱞᱛᱮ ᱱᱚᱸᱰᱮᱢ ᱦᱮᱡ ᱟᱠᱟᱱ ᱠᱷᱟᱡ, ᱟᱢᱟᱜ ᱵᱨᱟᱣᱡᱟᱨ ᱨᱮᱱᱟᱜ '''ᱛᱟᱭᱚᱢ''' ᱵᱟᱴᱚᱱ ᱞᱤᱱᱢᱮ᱾",
        "anontalkpagetext": "----\n\n<em>ᱱᱚᱶᱟ ᱫᱚ ᱜᱟᱞᱚᱪ ᱥᱟᱦᱴᱟ ᱠᱟᱱᱟ ᱩᱠᱩᱧᱩᱛᱩᱢ ᱵᱮᱵᱷᱟᱨᱤᱭᱟᱹ ᱠᱚᱣᱟᱜ ᱡᱟᱦᱟᱸᱭ ᱫᱚ ᱠᱷᱟᱛᱟ ᱵᱟᱭ ᱛᱮᱭᱟᱨ ᱟᱠᱟᱫᱟ ᱱᱤᱛ ᱦᱟᱹᱵᱤᱡ, ᱟᱨᱵᱟᱝ ᱡᱟᱦᱟᱸᱭ ᱵᱮᱵᱷᱟᱨ ᱟᱠᱟᱫᱟ ᱱᱚᱶᱟ ᱾</em>\nᱚᱱᱟᱛᱮ ᱟᱞᱮ ᱮᱞᱮᱞ IP ᱞᱮ ᱵᱮᱵᱷᱟᱨᱮᱜ-ᱟ ᱩᱱᱤ ᱪᱤᱱᱦᱟᱹᱣ ᱞᱟᱹᱜᱤᱫ ᱾\nᱚᱱᱠᱟᱱ IP ᱵᱩᱴᱟᱹ ᱫᱚ ᱦᱟᱹᱴᱤᱧ ᱫᱟᱲᱮᱭᱟᱜ-ᱟ ᱛᱤᱢᱤᱱ ᱵᱮᱵᱷᱟᱨᱤᱭᱟᱹ ᱫᱟᱨᱟᱭᱛᱮ ᱾\nᱡᱩᱫᱤ ᱟᱢ ᱩᱠᱩᱧᱩᱛᱩᱢ ᱵᱮᱵᱷᱟᱨᱤᱭᱟᱹ ᱠᱟᱱᱟᱢ ᱟᱨ ᱵᱷᱟᱹᱵᱤᱭᱮᱜ-ᱟᱢ ᱵᱟᱝ ᱡᱚᱲᱟᱣᱟᱱ ᱠᱟᱛᱷᱟ ᱟᱢᱮ ᱩᱫᱩᱜᱢᱮ ᱠᱟᱱᱟ, ᱮᱱᱠᱷᱟᱱ  [[Special:CreateAccount|ᱠᱷᱟᱛᱟ ᱛᱮᱭᱟᱨᱢᱮ]] ᱟᱨᱵᱟᱝ [[Special:UserLogin|ᱞᱚᱜᱤᱱ]] ᱢᱮ ᱫᱟᱨᱟᱭ ᱵᱷᱮᱣᱱᱟ ᱠᱚ ᱥᱟᱦᱟᱭ ᱞᱟᱹᱜᱤᱫ ᱮᱴᱟᱜ ᱩᱠᱩᱧᱩᱛᱩᱢ ᱵᱮᱵᱷᱟᱨᱤᱭᱟᱹ ᱠᱚ ᱥᱟᱶ ᱾",
-       "noarticletext": "ᱱᱮᱛᱚᱜ ᱱᱚᱣᱟ ᱥᱟᱦᱴᱟᱨᱮ ᱪᱮᱫᱜᱮ ᱵᱟᱹᱱᱩᱜ-ᱟ᱾\nᱮᱴᱟᱜ ᱥᱟᱦᱴᱟᱨᱮᱢ [[Special:Search/{{PAGENAME}}|search for this page title]],\n<span class=\"plainlinks\">[{{fullurl:{{#Special:Log}}|page={{FULLPAGENAMEE}}}} search the related logs],\nor [{{fullurl:{{FULLPAGENAME}}|action=edit}} edit this page]</span>.",
+       "noarticletext": "ᱱᱮᱛᱚᱜ ᱱᱚᱣᱟ ᱥᱟᱦᱴᱟᱨᱮ ᱪᱮᱫᱜᱮ ᱵᱟᱹᱱᱩᱜ-ᱟ᱾\nᱮᱴᱟᱜ ᱥᱟᱦᱴᱟᱨᱮᱢ [[Special:Search/{{PAGENAME}}|ᱱᱚᱶᱟ ᱥᱟᱦᱴᱟ ᱧᱩᱛᱩᱢ ᱥᱮᱸᱫᱽᱨᱟᱭ ᱢᱮ]],\n<span class=\"plainlinks\">[{{fullurl:{{#Special:Log}}|page={{FULLPAGENAMEE}}}} ᱡᱚᱲᱟᱣᱟᱱ ᱞᱚᱜᱽ ᱠᱚ ᱥᱮᱸᱫᱽᱨᱟᱭ ᱢᱮ],\nor [{{fullurl:{{FULLPAGENAME}}|action=edit}} ᱱᱚᱶᱟ ᱥᱟᱦᱴᱟ ᱥᱟᱯᱲᱟᱣ ᱢᱮ]</span>.",
        "noarticletext-nopermission": "ᱱᱚᱣᱟ ᱥᱟᱦᱴᱟᱨᱮ ᱱᱤᱛᱚᱜ ᱪᱮᱫᱜᱮ ᱚᱞ ᱵᱟᱹᱱᱩᱜ-ᱟ᱾\n\nᱟᱢ [[Special:Search/{{PAGENAME}}|ᱱᱚᱭᱟ ᱥᱟᱦᱴᱟᱨᱮᱱᱟᱜ ᱧᱤᱛᱩᱢᱮᱢ ᱥᱮᱸᱫᱽᱨᱟ ᱫᱟᱲᱮᱭᱟᱜ-ᱟ]] ᱮᱴᱟᱜ ᱥᱟᱦᱴᱟ ᱠᱚᱨᱮᱦᱚᱸ,\nᱟᱨᱵᱟᱝ <span class=\"plainlinks\">[{{fullurl:{{#Special:Log}}|page={{FULLPAGENAMEE}}}} search the related logs]</span>.",
        "userpage-userdoesnotexist": "\"<nowiki>$1</nowiki>\" ńutuman jahãe beoharićaḱ ekaunṭ do baṅ resṭri hoeakana. Daya kate biḍạo katet́ ńelmẽ noa sakam do benoa/sompadonem menet́ kana se baṅ.",
        "userpage-userdoesnotexist-view": "ᱵᱮᱵᱦᱟᱨᱤᱭᱟᱜ \"$1\" ᱮᱠᱟᱣᱱᱴ ᱫᱚ ᱵᱟᱝ ᱨᱮᱥᱴᱨᱤ ᱟᱠᱟᱱᱟ᱾",
        "searchrelated": "ᱥᱟᱹᱜᱟᱹᱭᱟᱱᱠᱩ",
        "searchall": "ᱡᱚᱛᱚ",
        "search-showingresults": "{{PLURAL:$4|ᱚᱨᱡᱚ <strong>$1</strong> ᱨᱮᱱᱟᱜ <strong>$3</strong>|ᱚᱨᱡᱚᱠᱚ <strong>$1 - $2</strong> ᱨᱮᱱᱟᱜ <strong>$3</strong>}}",
-       "search-nonefound": "ᱠᱩᱠá±\9eᱤ á±¥á±\9fᱶá±\9bá±® á±¯á±·á±\9aá±\9e á±µá±\9fá±\9d á±¢á±¤á±\9eá±\9fᱹᱮ ᱞᱮᱱᱟ᱾",
+       "search-nonefound": "ᱠᱩᱠá±\9eᱤ á±¥á±\9fᱶá±\9bá±® á±\9aᱨᱡá±\9a á±µá±\9fá±\9d á±¯á±\9aá±²á±\9bá±\9f ᱞᱮᱱᱟ᱾",
        "powersearch-ns": "ᱨᱟᱠᱷᱟ ᱧᱩᱛᱩᱢ ᱨᱮ ᱥᱮᱸᱫᱽᱨᱟ",
        "powersearch-togglelabel": "ᱠᱷᱚᱸᱡᱽ:",
        "powersearch-toggleall": "ᱡᱚᱛᱚ",
        "recentchangeslinked-feed": "ᱥᱟᱹᱜᱟᱹᱭᱟᱱ ᱵᱚᱫᱚᱞᱠᱚ",
        "recentchangeslinked-toolbox": "ᱥᱟᱹᱜᱟᱹᱭᱟᱱ ᱵᱚᱫᱚᱞᱠᱚ",
        "recentchangeslinked-title": "ᱵᱚᱫᱚᱞᱟᱜ ᱠᱚᱫᱚ \"$1\" ᱥᱟᱶᱛᱮ ᱡᱚᱲᱟᱣ ᱜᱮᱭᱟ",
-       "recentchangeslinked-summary": "á±±á±\9aá±£á±\9f á±«á±\9a á±\9aá±±á±\9f á±\9bá±\9fá±¹á±\9eá± á±\9fá±¹ á± á±\9fá±±á±\9f á±\9aá± á±\9f á±«á±\9f á±±á±®á±µá±®á±\9bá±\9fᱨá±\9cá±® á±µá±\9aᱫá±\9aá±\9e á±¦á±©á±­ á±\9fá± á±\9fá±±á±\9f á±\9aá± á±\9f á±«á±\9a á±\9bá±·á±\9aá±  á±¦á±\9fá±\9bá±\9fá±£ á±\9fá± á±\9fá±± á±¥á±\9fá± á±\9fá±¢ á± á±·á±\9aᱱ᱾\n\n[[Special:Watchlist|á±\9fá±¢á±\9fá±\9c á±§á±®á±\9e á±\9eᱤᱥᱴᱤ]] á±¨á±®á±­ᱟᱜ ᱥᱟᱦᱴᱟ ᱫᱚ <strong>ᱢᱚᱴᱟ ᱛᱮ</strong> ᱚᱞ ᱟᱠᱟᱱᱟ ᱾",
+       "recentchangeslinked-summary": "á±¥á±\9fᱦᱴá±\9f á±¨á±®á±±á±\9fá±\9c á±§á±©á±\9bᱩᱢ á±\9fᱫᱮᱨᱢᱮ á±¡á±\9fᱦá±\9fᱸ á± á±·á±\9aá±± á±¡á±\9aá±±á±\9aá±²á±\9fá±£ á±\9fᱨᱵá±\9fá±\9d á±¥á±\9fᱦᱴá±\9f á±µá±\9aᱫá±\9aá±\9e á±§á±®á±\9e á±\9eá±\9fá±¹á±\9cᱤᱫ á±¾ (á±\9bá±·á±\9aá±  á±¨á±®á±±á±\9fá±\9c á±¥á±\9aᱦᱮᱫ á±§á±®á±\9e á±\9eá±\9fá±¹á±\9cᱤᱫ, á±\9fᱫᱮᱨᱢᱮ {{ns:category}}:á±\9bá±·á±\9aá±  á±§á±©á±\9bᱩᱢ) á±¾ [[Special:Watchlist|á±\9fá±¢á±\9fá±\9c á±§á±®á±\9e á±\9eᱤᱥᱴᱤ]] á±¨á±®á±±á±\9fá±\9c á±µá±\9aá±±á±\9aᱫá±\9aá±\9eᱟᱜ ᱥᱟᱦᱴᱟ ᱫᱚ <strong>ᱢᱚᱴᱟ ᱛᱮ</strong> ᱚᱞ ᱟᱠᱟᱱᱟ ᱾",
        "recentchangeslinked-page": "ᱥᱟᱦᱴᱟ ᱧᱤᱛᱩᱢ :",
        "recentchangeslinked-to": "ᱡᱚᱱᱚᱲ ᱥᱟᱦᱴᱟᱨᱮ ᱧᱮᱞ ᱚᱪᱚᱭ ᱢᱮ ᱮᱢᱟᱜ ᱥᱟᱦᱴᱟ ᱵᱟᱹᱜᱤ ᱠᱟᱛᱮ",
        "upload": "ᱨᱮᱫ ᱞᱟᱫᱮᱢᱮ",
        "filehist-thumb": "ᱴᱤᱯ",
        "filehist-thumbtext": "Thumbnail for version as of $1",
        "filehist-nothumb": "ᱵᱟᱹᱱᱩᱜ-ᱟ ᱴᱤᱯ-ᱨᱟᱢᱟ",
-       "filehist-user": "ᱵᱮᱵᱦᱟᱨᱤᱡ",
+       "filehist-user": "ᱵᱮᱵᱷᱟᱨᱤᱡ",
        "filehist-dimensions": "ᱡᱚᱠᱷᱟ",
        "filehist-filesize": "ᱨᱮᱫ ᱥᱟᱭᱤᱡᱽ",
        "filehist-comment": "ᱠᱟᱛᱷᱟ",
        "movethispage": "ᱱᱚᱶᱟ ᱥᱟᱦᱴᱟ ᱥᱟᱦᱟᱭᱢᱮ",
        "pager-newer-n": "{{PLURAL:$1|1 ᱱᱟᱣᱟᱱᱟᱜ | ᱱᱟᱣᱟᱱᱟᱜ $1}}",
        "pager-older-n": "{{PLURAL:$1|ᱢᱟᱨᱮᱭᱟᱜ 1|ᱢᱟᱨᱮᱭᱟᱜ $1}}",
-       "booksources": "ᱯá±\9aá±\9bá±\9aá±µ á±¯á±·á±®á±°á±\9fá±\9b á±¦á±\9aᱨᱠá±\9f",
+       "booksources": "ᱯá±\9aá±\9bá±\9aá±µ á±¯á±·á±®á±°á±\9fá±\9b á± á±\9a",
        "booksources-search-legend": "ᱯᱚᱛᱚᱵ ᱨᱮᱭᱟᱜ ᱯᱷᱮᱰᱟᱛ ᱦᱚᱨ ᱞᱟᱹᱜᱤᱛ ᱥᱮᱸᱫᱽᱨᱟ",
        "booksources-search": "ᱥᱮᱸᱫᱽᱨᱟ",
        "specialloguserlabel": "ᱠᱟᱹᱢᱤᱭᱟᱹ:",
        "sp-contributions-submit": "ᱥᱮᱸᱫᱽᱨᱟ",
        "whatlinkshere": "ᱱᱚᱸᱰᱮ ᱫᱚ ᱪᱮᱫ ᱡᱚᱱᱚᱲ ᱠᱳ",
        "whatlinkshere-title": "ᱚᱠᱟ ᱥᱟᱦᱴᱟ ᱠᱚᱫᱚ \"$1\" ᱨᱮ ᱡᱚᱱᱚᱲ ᱢᱮᱱᱟᱜ-ᱟ",
-       "whatlinkshere-page": "ᱥᱟᱦᱴᱟ",
-       "linkshere": "ᱞᱟᱛᱟᱨ ᱨᱮᱭᱟᱜ ᱥᱟᱦᱴᱟᱠᱚ ᱫᱚ '''[[:$1]]''' ᱡᱚᱱᱚᱲ ᱢᱮᱱᱟᱜ-ᱟ :",
+       "whatlinkshere-page": "ᱥᱟᱦᱴᱟ:",
+       "linkshere": "ᱞᱟᱛᱟᱨ ᱨᱮᱭᱟᱜ ᱥᱟᱦᱴᱟᱠᱚ ᱫᱚ <strong>[[:$1]]</strong> ᱥᱟᱶ ᱡᱚᱱᱚᱲ ᱢᱮᱱᱟᱜ-ᱟ :",
        "nolinkshere": "ᱥᱟᱦᱴᱟ ᱡᱚᱱᱚᱲ ᱵᱟᱱᱩᱜ-ᱟ ᱱᱤᱭᱟᱹ <strong>[[:$1]]</strong>.",
        "isredirect": "ᱵᱟᱝ ᱥᱚᱡᱽᱦᱮ ᱥᱟᱦᱴᱟ",
        "istemplate": "ᱥᱮᱞᱮᱫ",
        "tooltip-ca-history": "ᱱᱚᱭᱟ ᱥᱟᱦᱴᱟ ᱨᱮᱱᱟᱜ ᱮᱱᱟᱝ ᱱᱟᱝ ᱧᱮᱞ ᱨᱩᱟᱹᱲ",
        "tooltip-ca-protect": "ᱱᱚᱣᱟ ᱥᱟᱦᱴᱟ ᱨᱩᱠᱷᱤᱭᱟᱹᱭ ᱢᱮ",
        "tooltip-ca-delete": "ᱱᱚᱣᱟ ᱥᱟᱦᱴᱟ ᱜᱮᱫᱽ ᱢᱮ",
-       "tooltip-ca-move": "á±±á±\9aᱣᱲ á±¥á±\9fᱦᱴá±\9f á± á±©á±\9eᱢᱮ",
+       "tooltip-ca-move": "á±±á±\9aá±£á±\9f á±¥á±\9fᱦᱴá±\9f á±©á±ªá±\9fᱹᱲᱢᱮ",
        "tooltip-ca-watch": "ᱱᱚᱭᱟ ᱥᱟᱦᱴᱟ ᱫᱚ ᱟᱢᱟᱜ ᱧᱮᱞᱚᱜ ᱛᱟᱹᱞᱠᱟᱹᱨᱮ ᱡᱚᱲᱟᱣᱢᱮ",
        "tooltip-ca-unwatch": "ᱟᱢᱟᱜ ᱧᱮᱞ ᱛᱟᱹᱞᱠᱟᱹ ᱠᱷᱚᱡ ᱱᱚᱣᱟ ᱥᱟᱦᱴᱟ ᱫᱚ ᱚᱪᱚᱜᱽ ᱢᱮ",
        "tooltip-search": "ᱥᱮᱸᱫᱽᱨᱟ {{SITENAME}}",
        "tooltip-n-help": "ᱥᱮᱸᱫᱽᱨᱟ ᱧᱟᱢ ᱨᱮᱭᱟᱜ ᱡᱟᱜᱟ",
        "tooltip-t-whatlinkshere": "ᱥᱟᱱᱟᱢ ᱩᱤᱠᱤ ᱥᱟᱦᱴᱟ ᱨᱮᱱᱟᱜ ᱛᱟᱹᱞᱠᱟᱹ ᱟᱨ ᱡᱚᱱᱚᱲ ᱫᱚ ᱱᱚᱸᱰᱮ",
        "tooltip-t-recentchangeslinked": "ᱱᱚᱭᱟ ᱥᱟᱦᱴᱟ ᱨᱮ ᱨᱚᱠᱟ ᱵᱚᱫᱚᱞ ᱟᱠᱟᱱ ᱥᱟᱦᱴᱟ ᱨᱮᱱᱟᱜ ᱡᱚᱱᱚᱲ",
-       "tooltip-feed-atom": "á±±á±\9aá±£á±\9f á±¥á±\9fᱦᱴá±\9f á±\9eá±\9fá±¹á±\9cᱤá±\9b Atom feed",
+       "tooltip-feed-atom": "á±±á±\9aá±£á±\9f á±¥á±\9fᱦᱴá±\9f á±\9eá±\9fá±¹á±\9cᱤᱫ á±\9fá±´á±\9aá±¢ á±¯á±·á±¤á±°",
        "tooltip-t-contributions": "ᱮᱱᱮᱢ ᱨᱮᱱᱟᱜ ᱛᱟᱹᱞᱠᱟᱹ {{GENDER:$1|ᱱᱩᱭ ᱵᱮᱵᱷᱟᱨᱤᱭᱟᱹ}}",
        "tooltip-t-emailuser": "ᱢᱤᱫ ᱤᱢᱮᱞ ᱠᱩᱞᱟᱭᱢᱮ {{GENDER:$1|ᱱᱩᱭ ᱵᱮᱵᱷᱟᱨᱤᱭᱟᱹ}}",
        "tooltip-t-upload": "ᱨᱮᱫ ᱠᱚ ᱞᱟᱫᱮᱢᱮ",
        "widthheightpage": "$1 × $2, $3 {{PLURAL:$3|ᱥᱟᱦᱴᱟ|ᱥᱟᱦᱴᱟᱠᱚ}}",
        "file-info-size": "$1 x $2 pixels, file size: $3, MIME type: $4",
        "file-info-size-pages": "$1 × $2 ᱯᱤᱠᱥᱮᱞ, ᱨᱮᱫ ᱥᱚᱝ: $3, MIME ᱞᱮᱠᱟᱱ: $4, $5 {{PLURAL:$5|ᱥᱟᱦᱴᱟ|ᱥᱟᱦᱴᱟᱠᱚ}}",
-       "file-nohires": "á±\9fá±­á±¢ᱟ ᱨᱮᱡᱩᱞᱮᱥᱚᱱ ᱵᱟᱱᱩᱜ-ᱟ᱾",
+       "file-nohires": "ᱥᱮᱬᱟ ᱨᱮᱡᱩᱞᱮᱥᱚᱱ ᱵᱟᱱᱩᱜ-ᱟ᱾",
        "svg-long-desc": "SVG ᱨᱮᱫ, ᱱᱚᱨᱢᱟᱞᱛᱮ $1 x $2 pixels, ᱨᱮᱫ ᱡᱟᱜᱟ: $3",
        "show-big-image": "ᱟᱥᱚᱞ ᱨᱮᱫ",
        "show-big-image-preview": "ᱧᱮᱞᱡᱚᱝ ᱨᱮᱱᱟᱜ ᱟᱠᱟᱨ:$1",
index f314ca4..c5a1874 100644 (file)
        "pagedata-title": "Podatki strani",
        "pagedata-text": "Ta stran nudi podatkovni vmesnik do strani. Prosimo, navedite naslov strani v URL-ju z uporabo skladnje podstrani.\n* Pogajanje o vsebini se nanaša na glavo Accept vašega odjemalca. To pomeni, da bomo podatke strani posredovali v obliki, ki vašemu odjemalcu bolj ustreza.",
        "pagedata-not-acceptable": "Nismo našli ujemajoče oblike. Podprte vrste MIME: $1",
-       "pagedata-bad-title": "Neveljaven naslov: $1."
+       "pagedata-bad-title": "Neveljaven naslov: $1.",
+       "unregistered-user-config": "Iz varnostnih razlogov uporabniških podstrani JavaScript, CSS in JSON ne moremo naložiti neregistriranim uporabnikom."
 }
index 45028e8..6bf1e4f 100644 (file)
        "pagedata-title": "Siddata",
        "pagedata-text": "Denna sida tillhandahåller ett datagränssnitt till sidor. Ange sidans titel i webbadressen med hjälp av undersidesyntax.\n* Innehållsförhandling gäller baserat på att din klients Accept-header. Detta innebär att siddatan kommer att tillhandahållas i det format som din klient föredrar.",
        "pagedata-not-acceptable": "Inga matchande format finns. MIME-typer som stöds:$1",
-       "pagedata-bad-title": "Ogiltig titel: $1."
+       "pagedata-bad-title": "Ogiltig titel: $1.",
+       "unregistered-user-config": "Av säkerhetsskäl kan inte undersidor med JavaScript, CSS och JSON läsas in för oregistrerade användare."
 }
index e86700b..38f7e62 100644 (file)
        "recentchangeslinked-feed": "Àtúnṣe tó báramu",
        "recentchangeslinked-toolbox": "Àtúnṣe tó báramu",
        "recentchangeslinked-title": "Àtúnṣe tó báramu mọ́ \"$1\"",
-       "recentchangeslinked-summary": "Àkójọ àwọn àtúnṣe tí a sẹ̀sẹ̀ ṣe sí àwọn ojúewé tó jápọ̀ wá láti ojúewé pàtó kan (tàbí sí ìkan nìnú ẹ̀ka pàtó kan).\nÀwọn ojúewé inú [[Special:Watchlist|ìmójútó yín]] jẹ́ '''kedere'''.",
+       "recentchangeslinked-summary": "Ẹ tẹ orúkọ ojúewé láti rí àwọn àtúnṣe lórí àwọn ojúewé tí wọ́n jápọ̀ sí tàbí jápọ̀ wá láti ọ̀dọ̀ ojúewé nà. (Láti rí àwọn ojúewé inú ẹ̀ka, ẹ tẹ {{ns:category}}:Orúkọ ẹ̀ka).\nÀwọn àtúnṣe ojúewé inú [[Special:Watchlist|Ìtòjọ àmójútó yín]] ni àwọn tó hàn <strong>kedere</strong>.",
        "recentchangeslinked-page": "Orúkọ ojúewé:",
        "recentchangeslinked-to": "Àfihàn àwọn àtúnṣe sí àwọn ojúewé tójápọ̀ mọ́ ojúewé ọ̀hún dípò",
        "upload": "Ìrùsókè fáìlì",
index 231001d..889ab42 100755 (executable)
@@ -43,15 +43,15 @@ rm -r "$REPO_DIR/$TARGET_DIR"
 
 # Core and thematic code and styling
 mkdir -p "$REPO_DIR/$TARGET_DIR"
-cp ./node_modules/oojs-ui/dist/oojs-ui-core.js{,.map} "$REPO_DIR/$TARGET_DIR"
+cp ./node_modules/oojs-ui/dist/oojs-ui-core.js{,.map.json} "$REPO_DIR/$TARGET_DIR"
 cp ./node_modules/oojs-ui/dist/oojs-ui-core-{wikimediaui,apex}.css "$REPO_DIR/$TARGET_DIR"
-cp ./node_modules/oojs-ui/dist/oojs-ui-widgets.js{,.map} "$REPO_DIR/$TARGET_DIR"
+cp ./node_modules/oojs-ui/dist/oojs-ui-widgets.js{,.map.json} "$REPO_DIR/$TARGET_DIR"
 cp ./node_modules/oojs-ui/dist/oojs-ui-widgets-{wikimediaui,apex}.css "$REPO_DIR/$TARGET_DIR"
-cp ./node_modules/oojs-ui/dist/oojs-ui-toolbars.js{,.map} "$REPO_DIR/$TARGET_DIR"
+cp ./node_modules/oojs-ui/dist/oojs-ui-toolbars.js{,.map.json} "$REPO_DIR/$TARGET_DIR"
 cp ./node_modules/oojs-ui/dist/oojs-ui-toolbars-{wikimediaui,apex}.css "$REPO_DIR/$TARGET_DIR"
-cp ./node_modules/oojs-ui/dist/oojs-ui-windows.js{,.map} "$REPO_DIR/$TARGET_DIR"
+cp ./node_modules/oojs-ui/dist/oojs-ui-windows.js{,.map.json} "$REPO_DIR/$TARGET_DIR"
 cp ./node_modules/oojs-ui/dist/oojs-ui-windows-{wikimediaui,apex}.css "$REPO_DIR/$TARGET_DIR"
-cp ./node_modules/oojs-ui/dist/oojs-ui-{wikimediaui,apex}.js{,.map} "$REPO_DIR/$TARGET_DIR"
+cp ./node_modules/oojs-ui/dist/oojs-ui-{wikimediaui,apex}.js{,.map.json} "$REPO_DIR/$TARGET_DIR"
 
 # i18n
 mkdir -p "$REPO_DIR/$TARGET_DIR/i18n"
index d0bc1ba..77391a8 100644 (file)
@@ -303,8 +303,8 @@ return [
                'targets' => [ 'desktop', 'mobile' ],
        ],
        'jquery.spinner' => [
-               'scripts' => 'resources/src/jquery/jquery.spinner.js',
-               'styles' => 'resources/src/jquery/jquery.spinner.css',
+               'scripts' => 'resources/src/jquery.spinner/spinner.js',
+               'styles' => 'resources/src/jquery.spinner/spinner.css',
                'targets' => [ 'desktop', 'mobile' ],
        ],
        'jquery.jStorage' => [
@@ -1994,15 +1994,18 @@ return [
        ],
        'mediawiki.special' => [
                'styles' => [
-                       'resources/src/mediawiki.special/mediawiki.special.css',
-                       'resources/src/mediawiki.special/mediawiki.special.userrights.css',
+                       'resources/src/mediawiki.special/special.css',
+                       'resources/src/mediawiki.special/apisandbox.css',
+                       'resources/src/mediawiki.special/comparepages.less',
+                       'resources/src/mediawiki.special/edittags.css',
+                       'resources/src/mediawiki.special/movePage.css',
+                       'resources/src/mediawiki.special/pagesWithProp.css',
+                       'resources/src/mediawiki.special/upload.css',
+                       'resources/src/mediawiki.special/userrights.css',
+                       'resources/src/mediawiki.special/watchlist.css',
                ],
                'targets' => [ 'desktop', 'mobile' ],
        ],
-       'mediawiki.special.apisandbox.styles' => [
-               'targets' => [ 'desktop', 'mobile' ],
-               'styles' => 'resources/src/mediawiki.special.apisandbox.styles.css',
-       ],
        'mediawiki.special.apisandbox' => [
                'styles' => 'resources/src/mediawiki.special.apisandbox/apisandbox.css',
                'scripts' => 'resources/src/mediawiki.special.apisandbox/apisandbox.js',
@@ -2034,6 +2037,7 @@ return [
                        'apisandbox-dynamic-parameters-add-label',
                        'apisandbox-dynamic-parameters-add-placeholder',
                        'apisandbox-dynamic-error-exists',
+                       'apisandbox-templated-parameter-reason',
                        'apisandbox-deprecated-parameters',
                        'apisandbox-no-parameters',
                        'api-help-param-limit',
@@ -2070,6 +2074,9 @@ return [
                        'apisandbox-multivalue-all-values',
                        'api-format-prettyprint-status',
                        'blanknamespace',
+                       'comma-separator',
+                       'word-separator',
+                       'and'
                ],
        ],
        'mediawiki.special.block' => [
@@ -2112,12 +2119,6 @@ return [
                ],
                'targets' => [ 'desktop', 'mobile' ],
        ],
-       'mediawiki.special.changeslist.visitedstatus' => [
-               'scripts' => 'resources/src/mediawiki.special.changeslist.visitedstatus.js',
-       ],
-       'mediawiki.special.comparepages.styles' => [
-               'styles' => 'resources/src/mediawiki.special.comparepages.styles.less',
-       ],
        'mediawiki.special.contributions' => [
                'scripts' => 'resources/src/mediawiki.special.contributions.js',
                'dependencies' => [
@@ -2136,9 +2137,6 @@ return [
                        'tags-edit-chosen-no-results',
                ],
        ],
-       'mediawiki.special.edittags.styles' => [
-               'styles' => 'resources/src/mediawiki.special.edittags.styles.css',
-       ],
        'mediawiki.special.import' => [
                'scripts' => 'resources/src/mediawiki.special.import.js',
        ],
@@ -2149,18 +2147,12 @@ return [
                        'mediawiki.widgets',
                ],
        ],
-       'mediawiki.special.movePage.styles' => [
-               'styles' => 'resources/src/mediawiki.special.movePage.css',
-       ],
        'mediawiki.special.pageLanguage' => [
                'scripts' => 'resources/src/mediawiki.special.pageLanguage.js',
                'dependencies' => [
                        'oojs-ui-core',
                ],
        ],
-       'mediawiki.special.pagesWithProp' => [
-               'styles' => 'resources/src/mediawiki.special.pagesWithProp.css',
-       ],
        'mediawiki.special.preferences' => [
                'targets' => [ 'desktop', 'mobile' ],
                'scripts' => [
@@ -2307,7 +2299,7 @@ return [
                        'prefs-editing',
                ],
                'dependencies' => [
-                       'mediawiki.special.upload.styles',
+                       'mediawiki.special',
                        'jquery.spinner',
                        'mediawiki.jqueryMsg',
                        'mediawiki.api',
@@ -2319,9 +2311,6 @@ return [
                        'user.options',
                ],
        ],
-       'mediawiki.special.upload.styles' => [
-               'styles' => 'resources/src/mediawiki.special.upload.styles.css',
-       ],
        'mediawiki.special.userlogin.common.styles' => [
                'targets' => [ 'desktop', 'mobile' ],
                'skinStyles' => [
@@ -2360,7 +2349,10 @@ return [
                ],
        ],
        'mediawiki.special.watchlist' => [
-               'scripts' => 'resources/src/mediawiki.special.watchlist.js',
+               'scripts' => [
+                       'resources/src/mediawiki.special.watchlist/watchlist.js',
+                       'resources/src/mediawiki.special.watchlist/visitedstatus.js',
+               ],
                'messages' => [
                        'addedwatchtext',
                        'addedwatchtext-talk',
@@ -2380,9 +2372,6 @@ return [
                        'user.options',
                ],
        ],
-       'mediawiki.special.watchlist.styles' => [
-               'styles' => 'resources/src/mediawiki.special.watchlist.styles.css',
-       ],
        'mediawiki.special.version' => [
                'styles' => 'resources/src/mediawiki.special.version.css',
        ],
diff --git a/resources/src/jquery.spinner/images/spinner-large.gif b/resources/src/jquery.spinner/images/spinner-large.gif
new file mode 100644 (file)
index 0000000..72203fd
Binary files /dev/null and b/resources/src/jquery.spinner/images/spinner-large.gif differ
diff --git a/resources/src/jquery.spinner/images/spinner.gif b/resources/src/jquery.spinner/images/spinner.gif
new file mode 100644 (file)
index 0000000..6146be4
Binary files /dev/null and b/resources/src/jquery.spinner/images/spinner.gif differ
diff --git a/resources/src/jquery.spinner/spinner.css b/resources/src/jquery.spinner/spinner.css
new file mode 100644 (file)
index 0000000..9c819a6
--- /dev/null
@@ -0,0 +1,36 @@
+.mw-spinner {
+       background-color: transparent;
+       background-position: center center;
+       background-repeat: no-repeat;
+}
+
+.mw-spinner-small {
+       /* @embed */
+       background-image: url( images/spinner.gif );
+       height: 20px;
+       width: 20px;
+       /* Avoid issues with .mw-spinner-block when floated without width. */
+       min-width: 20px;
+}
+
+.mw-spinner-large {
+       /* @embed */
+       background-image: url( images/spinner-large.gif );
+       height: 32px;
+       width: 32px;
+       /* Avoid issues with .mw-spinner-block when floated without width. */
+       min-width: 32px;
+}
+
+.mw-spinner-block {
+       display: block;
+       /* This overrides width from .mw-spinner-large / .mw-spinner-small,
+        * This is where the min-width kicks in.
+        */
+       width: 100%;
+}
+
+.mw-spinner-inline {
+       display: inline-block;
+       vertical-align: middle;
+}
diff --git a/resources/src/jquery.spinner/spinner.js b/resources/src/jquery.spinner/spinner.js
new file mode 100644 (file)
index 0000000..9079cc0
--- /dev/null
@@ -0,0 +1,114 @@
+/**
+ * jQuery Spinner
+ *
+ * Simple jQuery plugin to create, inject and remove spinners.
+ *
+ * @class jQuery.plugin.spinner
+ */
+( function ( $ ) {
+
+       // Default options for new spinners,
+       // stored outside the function to share between calls.
+       var defaults = {
+               id: undefined,
+               size: 'small',
+               type: 'inline'
+       };
+
+       $.extend( {
+               /**
+                * Create a spinner element
+                *
+                * The argument is an object with options used to construct the spinner (see below).
+                *
+                * It is a good practice to keep a reference to the created spinner to be able to remove it
+                * later. Alternatively, one can use the 'id' option and #removeSpinner (but make sure to choose
+                * an id that's unlikely to cause conflicts, e.g. with extensions, gadgets or user scripts).
+                *
+                * CSS classes used:
+                *
+                * - .mw-spinner for every spinner
+                * - .mw-spinner-small / .mw-spinner-large for size
+                * - .mw-spinner-block / .mw-spinner-inline for display types
+                *
+                * Example:
+                *
+                *     // Create a large spinner reserving all available horizontal space.
+                *     var $spinner = $.createSpinner( { size: 'large', type: 'block' } );
+                *     // Insert above page content.
+                *     $( '#mw-content-text' ).prepend( $spinner );
+                *
+                *     // Place a small inline spinner next to the "Save" button
+                *     var $spinner = $.createSpinner( { size: 'small', type: 'inline' } );
+                *     // Alternatively, just `$.createSpinner();` as these are the default options.
+                *     $( '#wpSave' ).after( $spinner );
+                *
+                *     // The following two are equivalent:
+                *     $.createSpinner( 'magic' );
+                *     $.createSpinner( { id: 'magic' } );
+                *
+                * @static
+                * @inheritable
+                * @param {Object|string} [opts] Options. If a string is given, it will be treated as the value
+                *   of the `id` option. If an object is given, the possible option keys are:
+                * @param {string} [opts.id] If given, spinner will be given an id of "mw-spinner-{id}".
+                * @param {string} [opts.size='small'] 'small' or 'large' for a 20-pixel or 32-pixel spinner.
+                * @param {string} [opts.type='inline'] 'inline' or 'block'. Inline creates an inline-block with
+                *   width and height equal to spinner size. Block is a block-level element with width 100%,
+                *   height equal to spinner size.
+                * @return {jQuery}
+                */
+               createSpinner: function ( opts ) {
+                       var $spinner;
+
+                       if ( opts !== undefined && $.type( opts ) !== 'object' ) {
+                               opts = {
+                                       id: opts
+                               };
+                       }
+
+                       opts = $.extend( {}, defaults, opts );
+
+                       $spinner = $( '<div>' ).addClass( 'mw-spinner' ).attr( 'title', '...' );
+                       if ( opts.id !== undefined ) {
+                               $spinner.attr( 'id', 'mw-spinner-' + opts.id );
+                       }
+
+                       $spinner.addClass( opts.size === 'large' ? 'mw-spinner-large' : 'mw-spinner-small' );
+                       $spinner.addClass( opts.type === 'block' ? 'mw-spinner-block' : 'mw-spinner-inline' );
+
+                       return $spinner;
+               },
+
+               /**
+                * Remove a spinner element
+                *
+                * @static
+                * @inheritable
+                * @param {string} id Id of the spinner, as passed to #createSpinner
+                * @return {jQuery} The (now detached) spinner element
+                */
+               removeSpinner: function ( id ) {
+                       return $( '#mw-spinner-' + id ).remove();
+               }
+       } );
+
+       /**
+        * Inject a spinner after each element in the collection
+        *
+        * Inserts spinner as siblings (not children) of the target elements.
+        * Collection contents remain unchanged.
+        *
+        * @param {Object|string} [opts] See #createSpinner
+        * @return {jQuery}
+        */
+       $.fn.injectSpinner = function ( opts ) {
+               return this.after( $.createSpinner( opts ) );
+       };
+
+       /**
+        * @class jQuery
+        * @mixins jQuery.plugin.spinner
+        */
+
+}( jQuery ) );
diff --git a/resources/src/jquery/images/spinner-large.gif b/resources/src/jquery/images/spinner-large.gif
deleted file mode 100644 (file)
index 72203fd..0000000
Binary files a/resources/src/jquery/images/spinner-large.gif and /dev/null differ
diff --git a/resources/src/jquery/images/spinner.gif b/resources/src/jquery/images/spinner.gif
deleted file mode 100644 (file)
index 6146be4..0000000
Binary files a/resources/src/jquery/images/spinner.gif and /dev/null differ
diff --git a/resources/src/jquery/jquery.spinner.css b/resources/src/jquery/jquery.spinner.css
deleted file mode 100644 (file)
index 6c7bd0e..0000000
+++ /dev/null
@@ -1,40 +0,0 @@
-.mw-spinner {
-       background-color: transparent;
-       background-position: center center;
-       background-repeat: no-repeat;
-}
-
-.mw-spinner-small {
-       /* @embed */
-       background-image: url( images/spinner.gif );
-       height: 20px;
-       width: 20px;
-       /* Avoid issues with .mw-spinner-block when floated without width. */
-       min-width: 20px;
-}
-
-.mw-spinner-large {
-       /* @embed */
-       background-image: url( images/spinner-large.gif );
-       height: 32px;
-       width: 32px;
-       /* Avoid issues with .mw-spinner-block when floated without width. */
-       min-width: 32px;
-}
-
-.mw-spinner-block {
-       display: block;
-       /* This overrides width from .mw-spinner-large / .mw-spinner-small,
-        * This is where the min-width kicks in.
-        */
-       width: 100%;
-}
-
-.mw-spinner-inline {
-       display: inline-block;
-       vertical-align: middle;
-
-       /* IE < 8 */
-       zoom: 1;
-       *display: inline; /* stylelint-disable-line declaration-block-no-duplicate-properties */
-}
diff --git a/resources/src/jquery/jquery.spinner.js b/resources/src/jquery/jquery.spinner.js
deleted file mode 100644 (file)
index 9079cc0..0000000
+++ /dev/null
@@ -1,114 +0,0 @@
-/**
- * jQuery Spinner
- *
- * Simple jQuery plugin to create, inject and remove spinners.
- *
- * @class jQuery.plugin.spinner
- */
-( function ( $ ) {
-
-       // Default options for new spinners,
-       // stored outside the function to share between calls.
-       var defaults = {
-               id: undefined,
-               size: 'small',
-               type: 'inline'
-       };
-
-       $.extend( {
-               /**
-                * Create a spinner element
-                *
-                * The argument is an object with options used to construct the spinner (see below).
-                *
-                * It is a good practice to keep a reference to the created spinner to be able to remove it
-                * later. Alternatively, one can use the 'id' option and #removeSpinner (but make sure to choose
-                * an id that's unlikely to cause conflicts, e.g. with extensions, gadgets or user scripts).
-                *
-                * CSS classes used:
-                *
-                * - .mw-spinner for every spinner
-                * - .mw-spinner-small / .mw-spinner-large for size
-                * - .mw-spinner-block / .mw-spinner-inline for display types
-                *
-                * Example:
-                *
-                *     // Create a large spinner reserving all available horizontal space.
-                *     var $spinner = $.createSpinner( { size: 'large', type: 'block' } );
-                *     // Insert above page content.
-                *     $( '#mw-content-text' ).prepend( $spinner );
-                *
-                *     // Place a small inline spinner next to the "Save" button
-                *     var $spinner = $.createSpinner( { size: 'small', type: 'inline' } );
-                *     // Alternatively, just `$.createSpinner();` as these are the default options.
-                *     $( '#wpSave' ).after( $spinner );
-                *
-                *     // The following two are equivalent:
-                *     $.createSpinner( 'magic' );
-                *     $.createSpinner( { id: 'magic' } );
-                *
-                * @static
-                * @inheritable
-                * @param {Object|string} [opts] Options. If a string is given, it will be treated as the value
-                *   of the `id` option. If an object is given, the possible option keys are:
-                * @param {string} [opts.id] If given, spinner will be given an id of "mw-spinner-{id}".
-                * @param {string} [opts.size='small'] 'small' or 'large' for a 20-pixel or 32-pixel spinner.
-                * @param {string} [opts.type='inline'] 'inline' or 'block'. Inline creates an inline-block with
-                *   width and height equal to spinner size. Block is a block-level element with width 100%,
-                *   height equal to spinner size.
-                * @return {jQuery}
-                */
-               createSpinner: function ( opts ) {
-                       var $spinner;
-
-                       if ( opts !== undefined && $.type( opts ) !== 'object' ) {
-                               opts = {
-                                       id: opts
-                               };
-                       }
-
-                       opts = $.extend( {}, defaults, opts );
-
-                       $spinner = $( '<div>' ).addClass( 'mw-spinner' ).attr( 'title', '...' );
-                       if ( opts.id !== undefined ) {
-                               $spinner.attr( 'id', 'mw-spinner-' + opts.id );
-                       }
-
-                       $spinner.addClass( opts.size === 'large' ? 'mw-spinner-large' : 'mw-spinner-small' );
-                       $spinner.addClass( opts.type === 'block' ? 'mw-spinner-block' : 'mw-spinner-inline' );
-
-                       return $spinner;
-               },
-
-               /**
-                * Remove a spinner element
-                *
-                * @static
-                * @inheritable
-                * @param {string} id Id of the spinner, as passed to #createSpinner
-                * @return {jQuery} The (now detached) spinner element
-                */
-               removeSpinner: function ( id ) {
-                       return $( '#mw-spinner-' + id ).remove();
-               }
-       } );
-
-       /**
-        * Inject a spinner after each element in the collection
-        *
-        * Inserts spinner as siblings (not children) of the target elements.
-        * Collection contents remain unchanged.
-        *
-        * @param {Object|string} [opts] See #createSpinner
-        * @return {jQuery}
-        */
-       $.fn.injectSpinner = function ( opts ) {
-               return this.after( $.createSpinner( opts ) );
-       };
-
-       /**
-        * @class jQuery
-        * @mixins jQuery.plugin.spinner
-        */
-
-}( jQuery ) );
index 2b76187..dcaae3e 100644 (file)
                rWhitespace = /[ _\u00A0\u1680\u180E\u2000-\u200A\u2028\u2029\u202F\u205F\u3000]+/g,
 
                // From MediaWikiTitleCodec::splitTitleString() in PHP
-               rUnicodeBidi = /[\u200E\u200F\u202A-\u202E]/g,
+               rStripCharacters = /[\u00AD\u061C\u200E\u200F\u202A-\u202E\u2066-\u2069]/g,
 
                /**
                 * Slightly modified from Flinfo. Credit goes to Lupo and Flominator.
                        namespace = defaultNamespace === undefined ? NS_MAIN : defaultNamespace;
 
                        title = title
-                               // Strip Unicode bidi override characters
-                               .replace( rUnicodeBidi, '' )
+                               // Strip soft hyphens and Unicode directional formatting characters
+                               .replace( rStripCharacters, '' )
                                // Normalise whitespace to underscores and remove duplicates
                                .replace( rWhitespace, '_' )
                                // Trim underscores
diff --git a/resources/src/mediawiki.special.apisandbox.styles.css b/resources/src/mediawiki.special.apisandbox.styles.css
deleted file mode 100644 (file)
index 4dc4c27..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-.client-js .mw-apisandbox-nojs {
-       display: none;
-}
index 523a62e..f936658 100644 (file)
                        }
                }
 
+               widget.connect( this, {
+                       change: [ this.emit, 'change' ]
+               } );
+
                this.$cover.on( 'click', this.onOverlayClick.bind( this ) );
 
                this.$element
@@ -75,6 +79,7 @@
                this.widget.setDisabled( this.isDisabled() );
                this.checkbox.setSelected( !this.isDisabled() );
                this.$cover.toggle( this.isDisabled() );
+               this.emit( 'change' );
                return this;
        };
 
                },
 
                tagWidget: {
+                       parseApiValue: function ( v ) {
+                               if ( v === undefined || v === '' || v === '\x1f' ) {
+                                       return [];
+                               } else {
+                                       v = String( v );
+                                       if ( v[ 0 ] !== '\x1f' ) {
+                                               return v.split( '|' );
+                                       } else {
+                                               return v.substr( 1 ).split( '\x1f' );
+                                       }
+                               }
+                       },
+                       getApiValueForTemplates: function () {
+                               return this.isDisabled() ? this.parseApiValue( this.paramInfo[ 'default' ] ) : this.getValue();
+                       },
                        getApiValue: function () {
                                var items = this.getValue();
                                if ( items.join( '' ).indexOf( '|' ) === -1 ) {
                                }
                        },
                        setApiValue: function ( v ) {
-                               if ( v === undefined || v === '' || v === '\x1f' ) {
-                                       this.setValue( [] );
-                               } else {
-                                       v = String( v );
-                                       if ( v.indexOf( '\x1f' ) !== 0 ) {
-                                               this.setValue( v.split( '|' ) );
-                                       } else {
-                                               this.setValue( v.substr( 1 ).split( '\x1f' ) );
-                                       }
+                               if ( v === undefined ) {
+                                       v = this.paramInfo[ 'default' ];
                                }
+                               this.setValue( this.parseApiValue( v ) );
                        },
                        apiCheckValid: function () {
                                var ok = true,
                                        finalWidget.getSubmodules = widget.getSubmodules.bind( widget );
                                        finalWidget.on( 'disable', function () { setTimeout( ApiSandbox.updateUI ); } );
                                }
+                               if ( widget.getApiValueForTemplates ) {
+                                       finalWidget.getApiValueForTemplates = widget.getApiValueForTemplates.bind( widget );
+                               }
                                finalWidget.setDisabled( true );
                        }
 
                this.apiIsValid = true;
                this.loadFromQueryParams = null;
                this.widgets = {};
+               this.itemsFieldset = null;
+               this.deprecatedItemsFieldset = null;
+               this.templatedItemsCache = {};
                this.tokenWidget = null;
                this.indentLevel = config.indentLevel ? config.indentLevel : 0;
                ApiSandbox.PageLayout[ 'super' ].call( this, config.key, config );
                );
        };
 
+       function widgetLabelOnClick() {
+               var f = this.getField();
+               if ( $.isFunction( f.setDisabled ) ) {
+                       f.setDisabled( false );
+               }
+               if ( $.isFunction( f.focus ) ) {
+                       f.focus();
+               }
+       }
+
+       /**
+        * Create a widget and the FieldLayouts it needs
+        * @private
+        * @param {Object} ppi API paraminfo data for the parameter
+        * @param {string} name API parameter name
+        * @return {Object}
+        * @return {OO.ui.Widget} return.widget
+        * @return {OO.ui.FieldLayout} return.widgetField
+        * @return {OO.ui.FieldLayout} return.helpField
+        */
+       ApiSandbox.PageLayout.prototype.makeWidgetFieldLayouts = function ( ppi, name ) {
+               var j, l, widget, descriptionContainer, tmp, flag, count, button, widgetField, helpField, layoutConfig;
+
+               widget = Util.createWidgetForParameter( ppi );
+               if ( ppi.tokentype ) {
+                       this.tokenWidget = widget;
+               }
+               if ( this.paramInfo.templatedparameters.length ) {
+                       widget.on( 'change', this.updateTemplatedParameters, [ null ], this );
+               }
+
+               descriptionContainer = $( '<div>' );
+
+               tmp = Util.parseHTML( ppi.description );
+               tmp.filter( 'dl' ).makeCollapsible( {
+                       collapsed: true
+               } ).children( '.mw-collapsible-toggle' ).each( function () {
+                       var $this = $( this );
+                       $this.parent().prev( 'p' ).append( $this );
+               } );
+               descriptionContainer.append( $( '<div>' ).addClass( 'description' ).append( tmp ) );
+
+               if ( ppi.info && ppi.info.length ) {
+                       for ( j = 0; j < ppi.info.length; j++ ) {
+                               descriptionContainer.append( $( '<div>' )
+                                       .addClass( 'info' )
+                                       .append( Util.parseHTML( ppi.info[ j ] ) )
+                               );
+                       }
+               }
+               flag = true;
+               count = Infinity;
+               switch ( ppi.type ) {
+                       case 'namespace':
+                               flag = false;
+                               count = mw.config.get( 'wgFormattedNamespaces' ).length;
+                               break;
+
+                       case 'limit':
+                               if ( ppi.highmax !== undefined ) {
+                                       descriptionContainer.append( $( '<div>' )
+                                               .addClass( 'info' )
+                                               .append(
+                                                       Util.parseMsg(
+                                                               'api-help-param-limit2', ppi.max, ppi.highmax
+                                                       ),
+                                                       ' ',
+                                                       Util.parseMsg( 'apisandbox-param-limit' )
+                                               )
+                                       );
+                               } else {
+                                       descriptionContainer.append( $( '<div>' )
+                                               .addClass( 'info' )
+                                               .append(
+                                                       Util.parseMsg( 'api-help-param-limit', ppi.max ),
+                                                       ' ',
+                                                       Util.parseMsg( 'apisandbox-param-limit' )
+                                               )
+                                       );
+                               }
+                               break;
+
+                       case 'integer':
+                               tmp = '';
+                               if ( ppi.min !== undefined ) {
+                                       tmp += 'min';
+                               }
+                               if ( ppi.max !== undefined ) {
+                                       tmp += 'max';
+                               }
+                               if ( tmp !== '' ) {
+                                       descriptionContainer.append( $( '<div>' )
+                                               .addClass( 'info' )
+                                               .append( Util.parseMsg(
+                                                       'api-help-param-integer-' + tmp,
+                                                       Util.apiBool( ppi.multi ) ? 2 : 1,
+                                                       ppi.min, ppi.max
+                                               ) )
+                                       );
+                               }
+                               break;
+
+                       default:
+                               if ( Array.isArray( ppi.type ) ) {
+                                       flag = false;
+                                       count = ppi.type.length;
+                               }
+                               break;
+               }
+               if ( Util.apiBool( ppi.multi ) ) {
+                       tmp = [];
+                       if ( flag && !( widget instanceof OO.ui.TagMultiselectWidget ) &&
+                               !(
+                                       widget instanceof OptionalWidget &&
+                                       widget.widget instanceof OO.ui.TagMultiselectWidget
+                               )
+                       ) {
+                               tmp.push( mw.message( 'api-help-param-multi-separate' ).parse() );
+                       }
+                       if ( count > ppi.lowlimit ) {
+                               tmp.push(
+                                       mw.message( 'api-help-param-multi-max', ppi.lowlimit, ppi.highlimit ).parse()
+                               );
+                       }
+                       if ( tmp.length ) {
+                               descriptionContainer.append( $( '<div>' )
+                                       .addClass( 'info' )
+                                       .append( Util.parseHTML( tmp.join( ' ' ) ) )
+                               );
+                       }
+               }
+               if ( 'maxbytes' in ppi ) {
+                       descriptionContainer.append( $( '<div>' )
+                               .addClass( 'info' )
+                               .append( Util.parseMsg( 'api-help-param-maxbytes', ppi.maxbytes ) )
+                       );
+               }
+               if ( 'maxchars' in ppi ) {
+                       descriptionContainer.append( $( '<div>' )
+                               .addClass( 'info' )
+                               .append( Util.parseMsg( 'api-help-param-maxchars', ppi.maxchars ) )
+                       );
+               }
+               if ( ppi.usedTemplateVars && ppi.usedTemplateVars.length ) {
+                       tmp = $();
+                       for ( j = 0, l = ppi.usedTemplateVars.length; j < l; j++ ) {
+                               tmp = tmp.add( $( '<var>' ).text( ppi.usedTemplateVars[ j ] ) );
+                               if ( j === l - 2 ) {
+                                       tmp = tmp.add( mw.message( 'and' ).parseDom() );
+                                       tmp = tmp.add( mw.message( 'word-separator' ).parseDom() );
+                               } else if ( j !== l - 1 ) {
+                                       tmp = tmp.add( mw.message( 'comma-separator' ).parseDom() );
+                               }
+                       }
+                       descriptionContainer.append( $( '<div>' )
+                               .addClass( 'info' )
+                               .append( Util.parseMsg(
+                                       'apisandbox-templated-parameter-reason',
+                                       ppi.usedTemplateVars.length,
+                                       tmp
+                               ) )
+                       );
+               }
+
+               helpField = new OO.ui.FieldLayout(
+                       new OO.ui.Widget( {
+                               $content: '\xa0',
+                               classes: [ 'mw-apisandbox-spacer' ]
+                       } ), {
+                               align: 'inline',
+                               classes: [ 'mw-apisandbox-help-field' ],
+                               label: descriptionContainer
+                       }
+               );
+
+               layoutConfig = {
+                       align: 'left',
+                       classes: [ 'mw-apisandbox-widget-field' ],
+                       label: name
+               };
+
+               if ( ppi.tokentype ) {
+                       button = new OO.ui.ButtonWidget( {
+                               label: mw.message( 'apisandbox-fetch-token' ).text()
+                       } );
+                       button.on( 'click', widget.fetchToken, [], widget );
+
+                       widgetField = new OO.ui.ActionFieldLayout( widget, button, layoutConfig );
+               } else {
+                       widgetField = new OO.ui.FieldLayout( widget, layoutConfig );
+               }
+
+               // We need our own click handler on the widget label to
+               // turn off the disablement.
+               widgetField.$label.on( 'click', widgetLabelOnClick.bind( widgetField ) );
+
+               // Don't grey out the label when the field is disabled,
+               // it makes it too hard to read and our "disabled"
+               // isn't really disabled.
+               widgetField.onFieldDisable( false );
+               widgetField.onFieldDisable = $.noop;
+
+               widgetField.apiParamIndex = ppi.index;
+
+               return {
+                       widget: widget,
+                       widgetField: widgetField,
+                       helpField: helpField
+               };
+       };
+
+       /**
+        * Update templated parameters in the page
+        * @private
+        * @param {Object} [params] Query parameters for initializing the widgets
+        */
+       ApiSandbox.PageLayout.prototype.updateTemplatedParameters = function ( params ) {
+               var p, toProcess, doProcess, tmp, toRemove,
+                       that = this,
+                       pi = this.paramInfo,
+                       prefix = that.prefix + pi.prefix;
+
+               if ( !pi || !pi.templatedparameters.length ) {
+                       return;
+               }
+
+               if ( !$.isPlainObject( params ) ) {
+                       params = null;
+               }
+
+               toRemove = {};
+               $.each( this.templatedItemsCache, function ( k, el ) {
+                       if ( el.widget.isElementAttached() ) {
+                               toRemove[ k ] = el;
+                       }
+               } );
+
+               // This bit duplicates the PHP logic in ApiBase::extractRequestParams().
+               // If you update this, see if that needs updating too.
+               toProcess = pi.templatedparameters.map( function ( p ) {
+                       return {
+                               name: prefix + p.name,
+                               info: p,
+                               vars: $.extend( {}, p.templatevars ),
+                               usedVars: []
+                       };
+               } );
+               doProcess = function ( placeholder, target ) {
+                       var values, container, index, usedVars, done;
+
+                       target = prefix + target;
+
+                       if ( !that.widgets[ target ] ) {
+                               // The target wasn't processed yet, try the next one.
+                               // If all hit this case, the parameter has no expansions.
+                               return true;
+                       }
+
+                       if ( !that.widgets[ target ].getApiValueForTemplates ) {
+                               // Not a multi-valued widget, so it can't have expansions.
+                               return false;
+                       }
+
+                       values = that.widgets[ target ].getApiValueForTemplates();
+                       if ( !Array.isArray( values ) || !values.length ) {
+                               // The target was processed but has no (valid) values.
+                               // That means it has no expansions.
+                               return false;
+                       }
+
+                       // Expand this target in the name and all other targets,
+                       // then requeue if there are more targets left or create the widget
+                       // and add it to the form if all are done.
+                       delete p.vars[ placeholder ];
+                       usedVars = p.usedVars.concat( [ target ] );
+                       placeholder = '{' + placeholder + '}';
+                       done = $.isEmptyObject( p.vars );
+                       if ( done ) {
+                               container = Util.apiBool( p.info.deprecated ) ? that.deprecatedItemsFieldset : that.itemsFieldset;
+                               index = container.getItems().findIndex( function ( el ) {
+                                       return el.apiParamIndex !== undefined && el.apiParamIndex > p.info.index;
+                               } );
+                               if ( index < 0 ) {
+                                       index = undefined;
+                               }
+                       }
+                       values.forEach( function ( value ) {
+                               var name, newVars;
+
+                               if ( !/^[^{}]*$/.exec( value ) ) {
+                                       // Skip values that make invalid parameter names
+                                       return;
+                               }
+
+                               name = p.name.replace( placeholder, value );
+                               if ( done ) {
+                                       if ( that.templatedItemsCache[ name ] ) {
+                                               tmp = that.templatedItemsCache[ name ];
+                                       } else {
+                                               tmp = that.makeWidgetFieldLayouts(
+                                                       $.extend( {}, p.info, { usedTemplateVars: usedVars } ), name
+                                               );
+                                               that.templatedItemsCache[ name ] = tmp;
+                                       }
+                                       delete toRemove[ name ];
+                                       if ( !tmp.widget.isElementAttached() ) {
+                                               that.widgets[ name ] = tmp.widget;
+                                               container.addItems( [ tmp.widgetField, tmp.helpField ], index );
+                                               if ( index !== undefined ) {
+                                                       index += 2;
+                                               }
+                                       }
+                                       if ( params ) {
+                                               tmp.widget.setApiValue( params.hasOwnProperty( name ) ? params[ name ] : undefined );
+                                       }
+                               } else {
+                                       newVars = {};
+                                       $.each( p.vars, function ( k, v ) {
+                                               newVars[ k ] = v.replace( placeholder, value );
+                                       } );
+                                       toProcess.push( {
+                                               name: name,
+                                               info: p.info,
+                                               vars: newVars,
+                                               usedVars: usedVars
+                                       } );
+                               }
+                       } );
+                       return false;
+               };
+               while ( toProcess.length ) {
+                       p = toProcess.shift();
+                       $.each( p.vars, doProcess );
+               }
+
+               toRemove = $.map( toRemove, function ( el, name ) {
+                       delete that.widgets[ name ];
+                       return [ el.widgetField, el.helpField ];
+               } );
+               if ( toRemove.length ) {
+                       this.itemsFieldset.removeItems( toRemove );
+                       this.deprecatedItemsFieldset.removeItems( toRemove );
+               }
+       };
+
        /**
         * Fetch module information for this page's module, then create UI
         */
 
                Util.fetchModuleInfo( this.apiModule )
                        .done( function ( pi ) {
-                               var prefix, i, j, descriptionContainer, widget, layoutConfig, button, widgetField, helpField, tmp, flag, count,
+                               var prefix, i, j, tmp,
                                        items = [],
                                        deprecatedItems = [],
                                        buttons = [],
                                        filterFmModules = function ( v ) {
                                                return v.substr( -2 ) !== 'fm' ||
                                                        !availableFormats.hasOwnProperty( v.substr( 0, v.length - 2 ) );
-                                       },
-                                       widgetLabelOnClick = function () {
-                                               var f = this.getField();
-                                               if ( $.isFunction( f.setDisabled ) ) {
-                                                       f.setDisabled( false );
-                                               }
-                                               if ( $.isFunction( f.focus ) ) {
-                                                       f.focus();
-                                               }
                                        };
 
                                // This is something of a hack. We always want the 'format' and
                                if ( pi.parameters.length ) {
                                        prefix = that.prefix + pi.prefix;
                                        for ( i = 0; i < pi.parameters.length; i++ ) {
-                                               widget = Util.createWidgetForParameter( pi.parameters[ i ] );
-                                               that.widgets[ prefix + pi.parameters[ i ].name ] = widget;
-                                               if ( pi.parameters[ i ].tokentype ) {
-                                                       that.tokenWidget = widget;
-                                               }
-
-                                               descriptionContainer = $( '<div>' );
-
-                                               tmp = Util.parseHTML( pi.parameters[ i ].description );
-                                               tmp.filter( 'dl' ).makeCollapsible( {
-                                                       collapsed: true
-                                               } ).children( '.mw-collapsible-toggle' ).each( function () {
-                                                       var $this = $( this );
-                                                       $this.parent().prev( 'p' ).append( $this );
-                                               } );
-                                               descriptionContainer.append( $( '<div>' ).addClass( 'description' ).append( tmp ) );
-
-                                               if ( pi.parameters[ i ].info && pi.parameters[ i ].info.length ) {
-                                                       for ( j = 0; j < pi.parameters[ i ].info.length; j++ ) {
-                                                               descriptionContainer.append( $( '<div>' )
-                                                                       .addClass( 'info' )
-                                                                       .append( Util.parseHTML( pi.parameters[ i ].info[ j ] ) )
-                                                               );
-                                                       }
-                                               }
-                                               flag = true;
-                                               count = 1e100;
-                                               switch ( pi.parameters[ i ].type ) {
-                                                       case 'namespace':
-                                                               flag = false;
-                                                               count = mw.config.get( 'wgFormattedNamespaces' ).length;
-                                                               break;
-
-                                                       case 'limit':
-                                                               if ( pi.parameters[ i ].highmax !== undefined ) {
-                                                                       descriptionContainer.append( $( '<div>' )
-                                                                               .addClass( 'info' )
-                                                                               .append(
-                                                                                       Util.parseMsg(
-                                                                                               'api-help-param-limit2', pi.parameters[ i ].max, pi.parameters[ i ].highmax
-                                                                                       ),
-                                                                                       ' ',
-                                                                                       Util.parseMsg( 'apisandbox-param-limit' )
-                                                                               )
-                                                                       );
-                                                               } else {
-                                                                       descriptionContainer.append( $( '<div>' )
-                                                                               .addClass( 'info' )
-                                                                               .append(
-                                                                                       Util.parseMsg( 'api-help-param-limit', pi.parameters[ i ].max ),
-                                                                                       ' ',
-                                                                                       Util.parseMsg( 'apisandbox-param-limit' )
-                                                                               )
-                                                                       );
-                                                               }
-                                                               break;
-
-                                                       case 'integer':
-                                                               tmp = '';
-                                                               if ( pi.parameters[ i ].min !== undefined ) {
-                                                                       tmp += 'min';
-                                                               }
-                                                               if ( pi.parameters[ i ].max !== undefined ) {
-                                                                       tmp += 'max';
-                                                               }
-                                                               if ( tmp !== '' ) {
-                                                                       descriptionContainer.append( $( '<div>' )
-                                                                               .addClass( 'info' )
-                                                                               .append( Util.parseMsg(
-                                                                                       'api-help-param-integer-' + tmp,
-                                                                                       Util.apiBool( pi.parameters[ i ].multi ) ? 2 : 1,
-                                                                                       pi.parameters[ i ].min, pi.parameters[ i ].max
-                                                                               ) )
-                                                                       );
-                                                               }
-                                                               break;
-
-                                                       default:
-                                                               if ( Array.isArray( pi.parameters[ i ].type ) ) {
-                                                                       flag = false;
-                                                                       count = pi.parameters[ i ].type.length;
-                                                               }
-                                                               break;
-                                               }
-                                               if ( Util.apiBool( pi.parameters[ i ].multi ) ) {
-                                                       tmp = [];
-                                                       if ( flag && !( widget instanceof OO.ui.TagMultiselectWidget ) &&
-                                                               !(
-                                                                       widget instanceof OptionalWidget &&
-                                                                       widget.widget instanceof OO.ui.TagMultiselectWidget
-                                                               )
-                                                       ) {
-                                                               tmp.push( mw.message( 'api-help-param-multi-separate' ).parse() );
-                                                       }
-                                                       if ( count > pi.parameters[ i ].lowlimit ) {
-                                                               tmp.push(
-                                                                       mw.message( 'api-help-param-multi-max',
-                                                                               pi.parameters[ i ].lowlimit, pi.parameters[ i ].highlimit
-                                                                       ).parse()
-                                                               );
-                                                       }
-                                                       if ( tmp.length ) {
-                                                               descriptionContainer.append( $( '<div>' )
-                                                                       .addClass( 'info' )
-                                                                       .append( Util.parseHTML( tmp.join( ' ' ) ) )
-                                                               );
-                                                       }
-                                               }
-                                               if ( 'maxbytes' in pi.parameters[ i ] ) {
-                                                       descriptionContainer.append( $( '<div>' )
-                                                               .addClass( 'info' )
-                                                               .append( Util.parseMsg( 'api-help-param-maxbytes', pi.parameters[ i ].maxbytes ) )
-                                                       );
-                                               }
-                                               if ( 'maxchars' in pi.parameters[ i ] ) {
-                                                       descriptionContainer.append( $( '<div>' )
-                                                               .addClass( 'info' )
-                                                               .append( Util.parseMsg( 'api-help-param-maxchars', pi.parameters[ i ].maxchars ) )
-                                                       );
-                                               }
-                                               helpField = new OO.ui.FieldLayout(
-                                                       new OO.ui.Widget( {
-                                                               $content: '\xa0',
-                                                               classes: [ 'mw-apisandbox-spacer' ]
-                                                       } ), {
-                                                               align: 'inline',
-                                                               classes: [ 'mw-apisandbox-help-field' ],
-                                                               label: descriptionContainer
-                                                       }
-                                               );
-
-                                               layoutConfig = {
-                                                       align: 'left',
-                                                       classes: [ 'mw-apisandbox-widget-field' ],
-                                                       label: prefix + pi.parameters[ i ].name
-                                               };
-
-                                               if ( pi.parameters[ i ].tokentype ) {
-                                                       button = new OO.ui.ButtonWidget( {
-                                                               label: mw.message( 'apisandbox-fetch-token' ).text()
-                                                       } );
-                                                       button.on( 'click', widget.fetchToken, [], widget );
-
-                                                       widgetField = new OO.ui.ActionFieldLayout( widget, button, layoutConfig );
-                                               } else {
-                                                       widgetField = new OO.ui.FieldLayout( widget, layoutConfig );
-                                               }
-
-                                               // We need our own click handler on the widget label to
-                                               // turn off the disablement.
-                                               widgetField.$label.on( 'click', widgetLabelOnClick.bind( widgetField ) );
-
-                                               // Don't grey out the label when the field is disabled,
-                                               // it makes it too hard to read and our "disabled"
-                                               // isn't really disabled.
-                                               widgetField.onFieldDisable( false );
-                                               widgetField.onFieldDisable = $.noop;
-
+                                               tmp = that.makeWidgetFieldLayouts( pi.parameters[ i ], prefix + pi.parameters[ i ].name );
+                                               that.widgets[ prefix + pi.parameters[ i ].name ] = tmp.widget;
                                                if ( Util.apiBool( pi.parameters[ i ].deprecated ) ) {
-                                                       deprecatedItems.push( widgetField, helpField );
+                                                       deprecatedItems.push( tmp.widgetField, tmp.helpField );
                                                } else {
-                                                       items.push( widgetField, helpField );
+                                                       items.push( tmp.widgetField, tmp.helpField );
                                                }
                                        }
                                }
 
                                that.$element.empty();
 
-                               new OO.ui.FieldsetLayout( {
+                               that.itemsFieldset = new OO.ui.FieldsetLayout( {
                                        label: that.displayText
-                               } ).addItems( items )
-                                       .$element.appendTo( that.$element );
+                               } );
+                               that.itemsFieldset.addItems( items );
+                               that.itemsFieldset.$element.appendTo( that.$element );
 
                                if ( Util.apiBool( pi.dynamicparameters ) ) {
                                        dynamicFieldset = new OO.ui.FieldsetLayout();
                                                .appendTo( that.$element );
                                }
 
-                               if ( deprecatedItems.length ) {
-                                       tmp = new OO.ui.FieldsetLayout().addItems( deprecatedItems ).toggle( false );
-                                       $( '<fieldset>' )
-                                               .append(
-                                                       $( '<legend>' ).append(
-                                                               new OO.ui.ToggleButtonWidget( {
-                                                                       label: mw.message( 'apisandbox-deprecated-parameters' ).text()
-                                                               } ).on( 'change', tmp.toggle, [], tmp ).$element
-                                                       ),
-                                                       tmp.$element
-                                               )
-                                               .appendTo( that.$element );
-                               }
+                               that.deprecatedItemsFieldset = new OO.ui.FieldsetLayout().addItems( deprecatedItems ).toggle( false );
+                               tmp = $( '<fieldset>' )
+                                       .toggle( !that.deprecatedItemsFieldset.isEmpty() )
+                                       .append(
+                                               $( '<legend>' ).append(
+                                                       new OO.ui.ToggleButtonWidget( {
+                                                               label: mw.message( 'apisandbox-deprecated-parameters' ).text()
+                                                       } ).on( 'change', that.deprecatedItemsFieldset.toggle, [], that.deprecatedItemsFieldset ).$element
+                                               ),
+                                               that.deprecatedItemsFieldset.$element
+                                       )
+                                       .appendTo( that.$element );
+                               that.deprecatedItemsFieldset.on( 'add', function () {
+                                       this.toggle( !that.deprecatedItemsFieldset.isEmpty() );
+                               }, [], tmp );
+                               that.deprecatedItemsFieldset.on( 'remove', function () {
+                                       this.toggle( !that.deprecatedItemsFieldset.isEmpty() );
+                               }, [], tmp );
 
                                // Load stored params, if any, then update the booklet if we
                                // have subpages (or else just update our valid-indicator).
                                that.loadFromQueryParams = null;
                                if ( $.isPlainObject( tmp ) ) {
                                        that.loadQueryParams( tmp );
+                               } else {
+                                       that.updateTemplatedParameters();
                                }
                                if ( that.getSubpages().length > 0 ) {
                                        ApiSandbox.updateUI( tmp );
                                var v = params.hasOwnProperty( name ) ? params[ name ] : undefined;
                                widget.setApiValue( v );
                        } );
+                       this.updateTemplatedParameters( params );
                }
        };
 
index cb11332..275004f 100644 (file)
@@ -37,17 +37,6 @@ table.mw-enhanced-rc td.mw-enhanced-rc-nested {
        display: none;
 }
 
-/*
- * And if it's enabled, let's optimize the collapsing a little: hide the rows
- * that would be hidden by jquery.makeCollapsible with CSS to save us some
- * reflows and repaints. This doesn't work on browsers that don't fully support
- * CSS2 (IE6), but it's okay, this will be done in JavaScript with old degraded
- * performance instead.
- */
-.client-js table.mw-enhanced-rc.mw-collapsed tr + tr {
-       display: none;
-}
-
 .mw-enhancedchanges-arrow {
        padding-top: 2px;
 }
diff --git a/resources/src/mediawiki.special.changeslist.visitedstatus.js b/resources/src/mediawiki.special.changeslist.visitedstatus.js
deleted file mode 100644 (file)
index 6b25327..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-/*!
- * JavaScript for Special:Watchlist
- */
-( function ( $ ) {
-       $( function () {
-               $( '.mw-changeslist-line-watched .mw-title a' ).on( 'click', function () {
-                       $( this )
-                               .closest( '.mw-changeslist-line-watched' )
-                               .removeClass( 'mw-changeslist-line-watched' );
-               } );
-       } );
-}( jQuery ) );
diff --git a/resources/src/mediawiki.special.comparepages.styles.less b/resources/src/mediawiki.special.comparepages.styles.less
deleted file mode 100644 (file)
index 87b7a8b..0000000
+++ /dev/null
@@ -1,19 +0,0 @@
-@import 'mediawiki.mixins';
-
-.mw-special-ComparePages .mw-htmlform-ooui-wrapper {
-       width: 100%;
-}
-
-.mw-special-ComparePages .oo-ui-layout.oo-ui-panelLayout.oo-ui-panelLayout-padded.oo-ui-panelLayout-framed {
-       float: left;
-       width: 49%;
-       .box-sizing( border-box );
-}
-
-.mw-special-ComparePages .oo-ui-layout.oo-ui-panelLayout.oo-ui-panelLayout-padded.oo-ui-panelLayout-framed:nth-of-type( 2 ) {
-       margin-left: 2%;
-}
-
-.mw-special-ComparePages .mw-htmlform-submit-buttons {
-       clear: both;
-}
diff --git a/resources/src/mediawiki.special.edittags.styles.css b/resources/src/mediawiki.special.edittags.styles.css
deleted file mode 100644 (file)
index 204009c..0000000
+++ /dev/null
@@ -1,15 +0,0 @@
-/*!
- * Styling for Special:EditTags and action=editchangetags
- */
-#mw-edittags-tags-selector td {
-       vertical-align: top;
-}
-
-#mw-edittags-tags-selector-multi td {
-       vertical-align: top;
-       padding-right: 1.5em;
-}
-
-#mw-edittags-tag-list {
-       min-width: 20em;
-}
diff --git a/resources/src/mediawiki.special.movePage.css b/resources/src/mediawiki.special.movePage.css
deleted file mode 100644 (file)
index 9428fed..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-/*!
- * Styles for Special:MovePage
- */
-
-.movepage-wrapper {
-       width: 50em;
-}
diff --git a/resources/src/mediawiki.special.pagesWithProp.css b/resources/src/mediawiki.special.pagesWithProp.css
deleted file mode 100644 (file)
index 7ef75d0..0000000
+++ /dev/null
@@ -1,4 +0,0 @@
-/* Distinguish actual data from information about it being hidden visually */
-.prop-value-hidden {
-       font-style: italic;
-}
index a6ffae9..f938bcf 100644 (file)
@@ -18,8 +18,8 @@
                                timezoneWidget = null;
                        }
                } else {
-                       $tzSelect = $( '#mw-input-wptimecorrection' );
-                       $tzTextbox = $( '#mw-input-wptimecorrection-other' );
+                       $tzSelect = $( '#wpTimeCorrection' );
+                       $tzTextbox = $( '#wpTimeCorrection-other' );
                }
 
                $localtimeHolder = $( '#wpLocalTime' );
diff --git a/resources/src/mediawiki.special.upload.styles.css b/resources/src/mediawiki.special.upload.styles.css
deleted file mode 100644 (file)
index 626a7e8..0000000
+++ /dev/null
@@ -1,15 +0,0 @@
-/*!
- * Styling for Special:Upload
- */
-.mw-destfile-warning {
-       border: 1px solid #fde29b;
-       padding: 0.5em 1em;
-       margin-bottom: 1em;
-       color: #705000;
-       background-color: #fdf1d1;
-}
-
-p.mw-upload-editlicenses {
-       font-size: 90%;
-       text-align: right;
-}
diff --git a/resources/src/mediawiki.special.watchlist.js b/resources/src/mediawiki.special.watchlist.js
deleted file mode 100644 (file)
index 565ed2c..0000000
+++ /dev/null
@@ -1,158 +0,0 @@
-/*!
- * JavaScript for Special:Watchlist
- */
-( function ( mw, $, OO ) {
-       $( function () {
-               var api = new mw.Api(), $progressBar, $resetForm = $( '#mw-watchlist-resetbutton' );
-
-               // If the user wants to reset their watchlist, use an API call to do so (no reload required)
-               // Adapted from a user script by User:NQ of English Wikipedia
-               // (User:NQ/WatchlistResetConfirm.js)
-               $resetForm.submit( function ( event ) {
-                       var $button = $resetForm.find( 'input[name=mw-watchlist-reset-submit]' );
-
-                       event.preventDefault();
-
-                       // Disable reset button to prevent multiple concurrent requests
-                       $button.prop( 'disabled', true );
-
-                       if ( !$progressBar ) {
-                               $progressBar = new OO.ui.ProgressBarWidget( { progress: false } ).$element;
-                               $progressBar.css( {
-                                       position: 'absolute', width: '100%'
-                               } );
-                       }
-                       // Show progress bar
-                       $resetForm.append( $progressBar );
-
-                       // Use action=setnotificationtimestamp to mark all as visited,
-                       // then set all watchlist lines accordingly
-                       api.postWithToken( 'csrf', {
-                               formatversion: 2, action: 'setnotificationtimestamp', entirewatchlist: true
-                       } ).done( function () {
-                               // Enable button again
-                               $button.prop( 'disabled', false );
-                               // Hide the button because further clicks can not generate any visual changes
-                               $button.css( 'visibility', 'hidden' );
-                               $progressBar.detach();
-                               $( '.mw-changeslist-line-watched' )
-                                       .removeClass( 'mw-changeslist-line-watched' )
-                                       .addClass( 'mw-changeslist-line-not-watched' );
-                       } ).fail( function () {
-                               // On error, fall back to server-side reset
-                               // First remove this submit listener and then re-submit the form
-                               $resetForm.off( 'submit' ).submit();
-                       } );
-               } );
-
-               // if the user wishes to reload the watchlist whenever a filter changes
-               if ( mw.user.options.get( 'watchlistreloadautomatically' ) ) {
-                       // add a listener on all form elements in the header form
-                       $( '#mw-watchlist-form input, #mw-watchlist-form select' ).on( 'change', function () {
-                               // submit the form when one of the input fields is modified
-                               $( '#mw-watchlist-form' ).submit();
-                       } );
-               }
-
-               if ( mw.user.options.get( 'watchlistunwatchlinks' ) ) {
-                       // Watch/unwatch toggle link:
-                       // If a page is on the watchlist, a '×' is shown which, when clicked, removes the page from the watchlist.
-                       // After unwatching a page, the '×' becomes a '+', which if clicked re-watches the page.
-                       // Unwatched page entries are struck through and have lowered opacity.
-                       $( '.mw-changeslist' ).on( 'click', '.mw-unwatch-link, .mw-watch-link', function ( event ) {
-                               var $unwatchLink = $( this ), // EnhancedChangesList uses <table> for each row, while OldChangesList uses <li> for each row
-                                       $watchlistLine = $unwatchLink.closest( 'li, table' )
-                                               .find( '[data-target-page]' ),
-                                       pageTitle = $watchlistLine.data( 'targetPage' ),
-                                       isTalk = mw.Title.newFromText( pageTitle ).getNamespaceId() % 2 === 1;
-
-                               // Utility function for looping through each watchlist line that matches
-                               // a certain page or its associated page (e.g. Talk)
-                               function forEachMatchingTitle( title, callback ) {
-
-                                       var titleObj = mw.Title.newFromText( title ),
-                                               pageNamespaceId = titleObj.getNamespaceId(),
-                                               isTalk = pageNamespaceId % 2 === 1,
-                                               associatedTitle = mw.Title.makeTitle( isTalk ? pageNamespaceId - 1 : pageNamespaceId + 1,
-                                                       titleObj.getMainText() ).getPrefixedText();
-                                       $( '.mw-changeslist-line' ).each( function () {
-                                               var $this = $( this ), $row, $unwatchLink;
-
-                                               $this.find( '[data-target-page]' ).each( function () {
-                                                       var $this = $( this ), rowTitle = $this.data( 'targetPage' );
-                                                       if ( rowTitle === title || rowTitle === associatedTitle ) {
-
-                                                               // EnhancedChangesList groups log entries by performer rather than target page. Therefore...
-                                                               // * If using OldChangesList, use the <li>
-                                                               // * If using EnhancedChangesList and $this is part of a grouped log entry, use the <td> sub-entry
-                                                               // * If using EnhancedChangesList and $this is not part of a grouped log entry, use the <table> grouped entry
-                                                               $row =
-                                                                       $this.closest(
-                                                                               'li, table.mw-collapsible.mw-changeslist-log td[data-target-page], table' );
-                                                               $unwatchLink = $row.find( '.mw-unwatch-link, .mw-watch-link' );
-
-                                                               callback( rowTitle, $row, $unwatchLink );
-                                                       }
-                                               } );
-                                       } );
-                               }
-
-                               // Preload the notification module for mw.notify
-                               mw.loader.load( 'mediawiki.notification' );
-
-                               // Depending on whether we are watching or unwatching, for each entry of the page (and its associated page i.e. Talk),
-                               // change the text, tooltip, and non-JS href of the (un)watch button, and update the styling of the watchlist entry.
-                               if ( $unwatchLink.hasClass( 'mw-unwatch-link' ) ) {
-                                       api.unwatch( pageTitle )
-                                               .done( function () {
-                                                       forEachMatchingTitle( pageTitle,
-                                                               function ( rowPageTitle, $row, $rowUnwatchLink ) {
-                                                                       $rowUnwatchLink
-                                                                               .text( mw.msg( 'watchlist-unwatch-undo' ) )
-                                                                               .attr( 'title', mw.msg( 'tooltip-ca-watch' ) )
-                                                                               .attr( 'href',
-                                                                                       mw.util.getUrl( rowPageTitle, { action: 'watch' } ) )
-                                                                               .removeClass( 'mw-unwatch-link loading' )
-                                                                               .addClass( 'mw-watch-link' );
-                                                                       $row.find(
-                                                                               '.mw-changeslist-line-inner, .mw-enhanced-rc-nested' )
-                                                                               .addBack( '.mw-enhanced-rc-nested' ) // For matching log sub-entry
-                                                                               .addClass( 'mw-changelist-line-inner-unwatched' );
-                                                               } );
-
-                                                       mw.notify(
-                                                               mw.message( isTalk ? 'removedwatchtext-talk' : 'removedwatchtext',
-                                                                       pageTitle ), { tag: 'watch-self' } );
-                                               } );
-                               } else {
-                                       api.watch( pageTitle )
-                                               .then( function () {
-                                                       forEachMatchingTitle( pageTitle,
-                                                               function ( rowPageTitle, $row, $rowUnwatchLink ) {
-                                                                       $rowUnwatchLink
-                                                                               .text( mw.msg( 'watchlist-unwatch' ) )
-                                                                               .attr( 'title', mw.msg( 'tooltip-ca-unwatch' ) )
-                                                                               .attr( 'href',
-                                                                                       mw.util.getUrl( rowPageTitle, { action: 'unwatch' } ) )
-                                                                               .removeClass( 'mw-watch-link loading' )
-                                                                               .addClass( 'mw-unwatch-link' );
-                                                                       $row.find( '.mw-changelist-line-inner-unwatched' )
-                                                                               .addBack( '.mw-enhanced-rc-nested' )
-                                                                               .removeClass( 'mw-changelist-line-inner-unwatched' );
-                                                               } );
-
-                                                       mw.notify(
-                                                               mw.message( isTalk ? 'addedwatchtext-talk' : 'addedwatchtext',
-                                                                       pageTitle ), { tag: 'watch-self' } );
-                                               } );
-                               }
-
-                               event.preventDefault();
-                               event.stopPropagation();
-                               $unwatchLink.blur();
-                       } );
-               }
-       } );
-
-}( mediaWiki, jQuery, OO )
-);
diff --git a/resources/src/mediawiki.special.watchlist.styles.css b/resources/src/mediawiki.special.watchlist.styles.css
deleted file mode 100644 (file)
index c9861c2..0000000
+++ /dev/null
@@ -1,15 +0,0 @@
-/*!
- * Styling for elements generated by JavaScript on Special:Watchlist
- */
-.mw-changelist-line-inner-unwatched {
-       text-decoration: line-through;
-       opacity: 0.5;
-}
-
-span.mw-changeslist-line-prefix {
-       display: inline-block;
-}
-/* This can be either a span or a table cell */
-.mw-changeslist-line-prefix {
-       width: 1.25em;
-}
diff --git a/resources/src/mediawiki.special.watchlist/visitedstatus.js b/resources/src/mediawiki.special.watchlist/visitedstatus.js
new file mode 100644 (file)
index 0000000..6b25327
--- /dev/null
@@ -0,0 +1,12 @@
+/*!
+ * JavaScript for Special:Watchlist
+ */
+( function ( $ ) {
+       $( function () {
+               $( '.mw-changeslist-line-watched .mw-title a' ).on( 'click', function () {
+                       $( this )
+                               .closest( '.mw-changeslist-line-watched' )
+                               .removeClass( 'mw-changeslist-line-watched' );
+               } );
+       } );
+}( jQuery ) );
diff --git a/resources/src/mediawiki.special.watchlist/watchlist.js b/resources/src/mediawiki.special.watchlist/watchlist.js
new file mode 100644 (file)
index 0000000..565ed2c
--- /dev/null
@@ -0,0 +1,158 @@
+/*!
+ * JavaScript for Special:Watchlist
+ */
+( function ( mw, $, OO ) {
+       $( function () {
+               var api = new mw.Api(), $progressBar, $resetForm = $( '#mw-watchlist-resetbutton' );
+
+               // If the user wants to reset their watchlist, use an API call to do so (no reload required)
+               // Adapted from a user script by User:NQ of English Wikipedia
+               // (User:NQ/WatchlistResetConfirm.js)
+               $resetForm.submit( function ( event ) {
+                       var $button = $resetForm.find( 'input[name=mw-watchlist-reset-submit]' );
+
+                       event.preventDefault();
+
+                       // Disable reset button to prevent multiple concurrent requests
+                       $button.prop( 'disabled', true );
+
+                       if ( !$progressBar ) {
+                               $progressBar = new OO.ui.ProgressBarWidget( { progress: false } ).$element;
+                               $progressBar.css( {
+                                       position: 'absolute', width: '100%'
+                               } );
+                       }
+                       // Show progress bar
+                       $resetForm.append( $progressBar );
+
+                       // Use action=setnotificationtimestamp to mark all as visited,
+                       // then set all watchlist lines accordingly
+                       api.postWithToken( 'csrf', {
+                               formatversion: 2, action: 'setnotificationtimestamp', entirewatchlist: true
+                       } ).done( function () {
+                               // Enable button again
+                               $button.prop( 'disabled', false );
+                               // Hide the button because further clicks can not generate any visual changes
+                               $button.css( 'visibility', 'hidden' );
+                               $progressBar.detach();
+                               $( '.mw-changeslist-line-watched' )
+                                       .removeClass( 'mw-changeslist-line-watched' )
+                                       .addClass( 'mw-changeslist-line-not-watched' );
+                       } ).fail( function () {
+                               // On error, fall back to server-side reset
+                               // First remove this submit listener and then re-submit the form
+                               $resetForm.off( 'submit' ).submit();
+                       } );
+               } );
+
+               // if the user wishes to reload the watchlist whenever a filter changes
+               if ( mw.user.options.get( 'watchlistreloadautomatically' ) ) {
+                       // add a listener on all form elements in the header form
+                       $( '#mw-watchlist-form input, #mw-watchlist-form select' ).on( 'change', function () {
+                               // submit the form when one of the input fields is modified
+                               $( '#mw-watchlist-form' ).submit();
+                       } );
+               }
+
+               if ( mw.user.options.get( 'watchlistunwatchlinks' ) ) {
+                       // Watch/unwatch toggle link:
+                       // If a page is on the watchlist, a '×' is shown which, when clicked, removes the page from the watchlist.
+                       // After unwatching a page, the '×' becomes a '+', which if clicked re-watches the page.
+                       // Unwatched page entries are struck through and have lowered opacity.
+                       $( '.mw-changeslist' ).on( 'click', '.mw-unwatch-link, .mw-watch-link', function ( event ) {
+                               var $unwatchLink = $( this ), // EnhancedChangesList uses <table> for each row, while OldChangesList uses <li> for each row
+                                       $watchlistLine = $unwatchLink.closest( 'li, table' )
+                                               .find( '[data-target-page]' ),
+                                       pageTitle = $watchlistLine.data( 'targetPage' ),
+                                       isTalk = mw.Title.newFromText( pageTitle ).getNamespaceId() % 2 === 1;
+
+                               // Utility function for looping through each watchlist line that matches
+                               // a certain page or its associated page (e.g. Talk)
+                               function forEachMatchingTitle( title, callback ) {
+
+                                       var titleObj = mw.Title.newFromText( title ),
+                                               pageNamespaceId = titleObj.getNamespaceId(),
+                                               isTalk = pageNamespaceId % 2 === 1,
+                                               associatedTitle = mw.Title.makeTitle( isTalk ? pageNamespaceId - 1 : pageNamespaceId + 1,
+                                                       titleObj.getMainText() ).getPrefixedText();
+                                       $( '.mw-changeslist-line' ).each( function () {
+                                               var $this = $( this ), $row, $unwatchLink;
+
+                                               $this.find( '[data-target-page]' ).each( function () {
+                                                       var $this = $( this ), rowTitle = $this.data( 'targetPage' );
+                                                       if ( rowTitle === title || rowTitle === associatedTitle ) {
+
+                                                               // EnhancedChangesList groups log entries by performer rather than target page. Therefore...
+                                                               // * If using OldChangesList, use the <li>
+                                                               // * If using EnhancedChangesList and $this is part of a grouped log entry, use the <td> sub-entry
+                                                               // * If using EnhancedChangesList and $this is not part of a grouped log entry, use the <table> grouped entry
+                                                               $row =
+                                                                       $this.closest(
+                                                                               'li, table.mw-collapsible.mw-changeslist-log td[data-target-page], table' );
+                                                               $unwatchLink = $row.find( '.mw-unwatch-link, .mw-watch-link' );
+
+                                                               callback( rowTitle, $row, $unwatchLink );
+                                                       }
+                                               } );
+                                       } );
+                               }
+
+                               // Preload the notification module for mw.notify
+                               mw.loader.load( 'mediawiki.notification' );
+
+                               // Depending on whether we are watching or unwatching, for each entry of the page (and its associated page i.e. Talk),
+                               // change the text, tooltip, and non-JS href of the (un)watch button, and update the styling of the watchlist entry.
+                               if ( $unwatchLink.hasClass( 'mw-unwatch-link' ) ) {
+                                       api.unwatch( pageTitle )
+                                               .done( function () {
+                                                       forEachMatchingTitle( pageTitle,
+                                                               function ( rowPageTitle, $row, $rowUnwatchLink ) {
+                                                                       $rowUnwatchLink
+                                                                               .text( mw.msg( 'watchlist-unwatch-undo' ) )
+                                                                               .attr( 'title', mw.msg( 'tooltip-ca-watch' ) )
+                                                                               .attr( 'href',
+                                                                                       mw.util.getUrl( rowPageTitle, { action: 'watch' } ) )
+                                                                               .removeClass( 'mw-unwatch-link loading' )
+                                                                               .addClass( 'mw-watch-link' );
+                                                                       $row.find(
+                                                                               '.mw-changeslist-line-inner, .mw-enhanced-rc-nested' )
+                                                                               .addBack( '.mw-enhanced-rc-nested' ) // For matching log sub-entry
+                                                                               .addClass( 'mw-changelist-line-inner-unwatched' );
+                                                               } );
+
+                                                       mw.notify(
+                                                               mw.message( isTalk ? 'removedwatchtext-talk' : 'removedwatchtext',
+                                                                       pageTitle ), { tag: 'watch-self' } );
+                                               } );
+                               } else {
+                                       api.watch( pageTitle )
+                                               .then( function () {
+                                                       forEachMatchingTitle( pageTitle,
+                                                               function ( rowPageTitle, $row, $rowUnwatchLink ) {
+                                                                       $rowUnwatchLink
+                                                                               .text( mw.msg( 'watchlist-unwatch' ) )
+                                                                               .attr( 'title', mw.msg( 'tooltip-ca-unwatch' ) )
+                                                                               .attr( 'href',
+                                                                                       mw.util.getUrl( rowPageTitle, { action: 'unwatch' } ) )
+                                                                               .removeClass( 'mw-watch-link loading' )
+                                                                               .addClass( 'mw-unwatch-link' );
+                                                                       $row.find( '.mw-changelist-line-inner-unwatched' )
+                                                                               .addBack( '.mw-enhanced-rc-nested' )
+                                                                               .removeClass( 'mw-changelist-line-inner-unwatched' );
+                                                               } );
+
+                                                       mw.notify(
+                                                               mw.message( isTalk ? 'addedwatchtext-talk' : 'addedwatchtext',
+                                                                       pageTitle ), { tag: 'watch-self' } );
+                                               } );
+                               }
+
+                               event.preventDefault();
+                               event.stopPropagation();
+                               $unwatchLink.blur();
+                       } );
+               }
+       } );
+
+}( mediaWiki, jQuery, OO )
+);
diff --git a/resources/src/mediawiki.special/apisandbox.css b/resources/src/mediawiki.special/apisandbox.css
new file mode 100644 (file)
index 0000000..4dc4c27
--- /dev/null
@@ -0,0 +1,3 @@
+.client-js .mw-apisandbox-nojs {
+       display: none;
+}
diff --git a/resources/src/mediawiki.special/comparepages.less b/resources/src/mediawiki.special/comparepages.less
new file mode 100644 (file)
index 0000000..87b7a8b
--- /dev/null
@@ -0,0 +1,19 @@
+@import 'mediawiki.mixins';
+
+.mw-special-ComparePages .mw-htmlform-ooui-wrapper {
+       width: 100%;
+}
+
+.mw-special-ComparePages .oo-ui-layout.oo-ui-panelLayout.oo-ui-panelLayout-padded.oo-ui-panelLayout-framed {
+       float: left;
+       width: 49%;
+       .box-sizing( border-box );
+}
+
+.mw-special-ComparePages .oo-ui-layout.oo-ui-panelLayout.oo-ui-panelLayout-padded.oo-ui-panelLayout-framed:nth-of-type( 2 ) {
+       margin-left: 2%;
+}
+
+.mw-special-ComparePages .mw-htmlform-submit-buttons {
+       clear: both;
+}
diff --git a/resources/src/mediawiki.special/edittags.css b/resources/src/mediawiki.special/edittags.css
new file mode 100644 (file)
index 0000000..204009c
--- /dev/null
@@ -0,0 +1,15 @@
+/*!
+ * Styling for Special:EditTags and action=editchangetags
+ */
+#mw-edittags-tags-selector td {
+       vertical-align: top;
+}
+
+#mw-edittags-tags-selector-multi td {
+       vertical-align: top;
+       padding-right: 1.5em;
+}
+
+#mw-edittags-tag-list {
+       min-width: 20em;
+}
diff --git a/resources/src/mediawiki.special/mediawiki.special.css b/resources/src/mediawiki.special/mediawiki.special.css
deleted file mode 100644 (file)
index 0676bfc..0000000
+++ /dev/null
@@ -1,136 +0,0 @@
-/* Special:AllMessages */
-#mw-allmessagestable .allmessages-customised .am_default {
-       background-color: #fcffc4;
-}
-
-#mw-allmessagestable .allmessages-customised:hover .am_default {
-       background-color: #faff90;
-}
-
-#mw-allmessagestable .am_actual {
-       background-color: #e2ffe2;
-}
-
-#mw-allmessagestable .allmessages-customised:hover + .allmessages-customised .am_actual {
-       background-color: #b1ffb1;
-}
-
-/* Common for Special:Allpages and Special:PrefixIndex */
-.mw-allpages-body,
-.mw-prefixindex-body {
-       columns: 22em 3;
-       -moz-columns: 22em 3;
-       -webkit-columns: 22em 3;
-       break-inside: avoid-column;
-       page-break-inside: avoid;
-       -webkit-column-break-inside: avoid;
-}
-
-.mw-allpages-chunk,
-.mw-prefixindex-list {
-       margin-top: 0;
-       margin-bottom: 0;
-}
-
-.allpagesredirect {
-       font-style: italic;
-}
-
-/* Special:Block */
-.mw-ipb-conveniencelinks {
-       font-size: 90%;
-       text-align: right;
-}
-
-.mw-block-hideuser,
-.mw-block-confirm {
-       font-weight: bold;
-}
-
-#mw-input-wpReason .oo-ui-dropdownInputWidget,
-#mw-input-wpReason .oo-ui-textInputWidget {
-       display: block;
-       max-width: 50em;
-}
-
-#mw-input-wpReason .oo-ui-textInputWidget {
-       margin-top: 0.5em;
-}
-
-/* Special:BlockList */
-.mw-blocklist .mw-usertoollinks,
-.mw-blocklist-actions {
-       white-space: nowrap;
-       font-size: 90%;
-}
-
-/* Special:Contributions */
-.mw-uctop {
-       font-weight: bold;
-}
-.mw-contributions-form select {
-       vertical-align: middle;
-}
-
-/* Special:EditWatchlist */
-.watchlistredir {
-       font-style: italic;
-}
-
-/* Special:EmailUser */
-#mw-emailuser-sender,
-#mw-emailuser-recipient {
-       font-weight: bold;
-}
-
-/* Special:FileDuplicateSearch */
-#mw-fileduplicatesearch-icon {
-       float: right;
-}
-
-/* Special:ListGroupRights */
-.mw-listgrouprights-table tr {
-       vertical-align: top;
-}
-.listgrouprights-revoked {
-       text-decoration: line-through;
-}
-
-/* Special:RevisionDelete */
-.mw-revdel-editreasons {
-       font-size: 90%;
-       text-align: right;
-}
-
-/* Special:Specialpages */
-.mw-specialpagerestricted {
-       font-weight: bold;
-}
-
-.mw-specialpages-list {
-       -webkit-columns: 16em 2;
-       -moz-columns: 16em 2;
-       columns: 16em 2;
-}
-
-.mw-specialpages-list ul {
-       margin-top: 0;
-       margin-bottom: 0;
-}
-
-/* Special:Statistics */
-.mw-statistics-numbers {
-       text-align: right;
-}
-
-/* Special:ProtectedPages */
-.mw-protectedpages .mw-usertoollinks,
-.mw-protectedpages-length,
-.mw-protectedpages-actions {
-       white-space: nowrap;
-       font-size: 90%;
-}
-.mw-protectedpages-unknown {
-       color: #72777d;
-       font-size: 90%;
-}
diff --git a/resources/src/mediawiki.special/mediawiki.special.userrights.css b/resources/src/mediawiki.special/mediawiki.special.userrights.css
deleted file mode 100644 (file)
index 1ffdf70..0000000
+++ /dev/null
@@ -1,35 +0,0 @@
-/*!
- * Styling for Special:UserRights
- */
-.mw-userrights-nested {
-       margin-left: 1.2em;
-}
-
-.mw-userrights-nested span {
-       margin-left: 0.3em;
-       display: inline-block;
-       vertical-align: middle;
-}
-
-.mw-userrights-disabled {
-       color: #72777d;
-}
-.mw-userrights-groups * td,
-.mw-userrights-groups * th {
-       padding-right: 1.5em;
-}
-
-.mw-userrights-groups * th {
-       text-align: left;
-}
-
-/* Dynamically show/hide the expiry selection underneath each checkbox */
-input.mw-userrights-groupcheckbox:not( :checked ) ~ .mw-userrights-nested {
-       display: none;
-}
-
-/* Initial hide the expiry fields to prevent a FOUC on loading */
-/* The input fields gets unhidden by JavaScript when needed */
-.client-js .mw-userrights-expiryfield {
-       display: none;
-}
diff --git a/resources/src/mediawiki.special/movePage.css b/resources/src/mediawiki.special/movePage.css
new file mode 100644 (file)
index 0000000..9428fed
--- /dev/null
@@ -0,0 +1,7 @@
+/*!
+ * Styles for Special:MovePage
+ */
+
+.movepage-wrapper {
+       width: 50em;
+}
diff --git a/resources/src/mediawiki.special/pagesWithProp.css b/resources/src/mediawiki.special/pagesWithProp.css
new file mode 100644 (file)
index 0000000..7ef75d0
--- /dev/null
@@ -0,0 +1,4 @@
+/* Distinguish actual data from information about it being hidden visually */
+.prop-value-hidden {
+       font-style: italic;
+}
diff --git a/resources/src/mediawiki.special/special.css b/resources/src/mediawiki.special/special.css
new file mode 100644 (file)
index 0000000..0676bfc
--- /dev/null
@@ -0,0 +1,136 @@
+/* Special:AllMessages */
+#mw-allmessagestable .allmessages-customised .am_default {
+       background-color: #fcffc4;
+}
+
+#mw-allmessagestable .allmessages-customised:hover .am_default {
+       background-color: #faff90;
+}
+
+#mw-allmessagestable .am_actual {
+       background-color: #e2ffe2;
+}
+
+#mw-allmessagestable .allmessages-customised:hover + .allmessages-customised .am_actual {
+       background-color: #b1ffb1;
+}
+
+/* Common for Special:Allpages and Special:PrefixIndex */
+.mw-allpages-body,
+.mw-prefixindex-body {
+       columns: 22em 3;
+       -moz-columns: 22em 3;
+       -webkit-columns: 22em 3;
+       break-inside: avoid-column;
+       page-break-inside: avoid;
+       -webkit-column-break-inside: avoid;
+}
+
+.mw-allpages-chunk,
+.mw-prefixindex-list {
+       margin-top: 0;
+       margin-bottom: 0;
+}
+
+.allpagesredirect {
+       font-style: italic;
+}
+
+/* Special:Block */
+.mw-ipb-conveniencelinks {
+       font-size: 90%;
+       text-align: right;
+}
+
+.mw-block-hideuser,
+.mw-block-confirm {
+       font-weight: bold;
+}
+
+#mw-input-wpReason .oo-ui-dropdownInputWidget,
+#mw-input-wpReason .oo-ui-textInputWidget {
+       display: block;
+       max-width: 50em;
+}
+
+#mw-input-wpReason .oo-ui-textInputWidget {
+       margin-top: 0.5em;
+}
+
+/* Special:BlockList */
+.mw-blocklist .mw-usertoollinks,
+.mw-blocklist-actions {
+       white-space: nowrap;
+       font-size: 90%;
+}
+
+/* Special:Contributions */
+.mw-uctop {
+       font-weight: bold;
+}
+.mw-contributions-form select {
+       vertical-align: middle;
+}
+
+/* Special:EditWatchlist */
+.watchlistredir {
+       font-style: italic;
+}
+
+/* Special:EmailUser */
+#mw-emailuser-sender,
+#mw-emailuser-recipient {
+       font-weight: bold;
+}
+
+/* Special:FileDuplicateSearch */
+#mw-fileduplicatesearch-icon {
+       float: right;
+}
+
+/* Special:ListGroupRights */
+.mw-listgrouprights-table tr {
+       vertical-align: top;
+}
+.listgrouprights-revoked {
+       text-decoration: line-through;
+}
+
+/* Special:RevisionDelete */
+.mw-revdel-editreasons {
+       font-size: 90%;
+       text-align: right;
+}
+
+/* Special:Specialpages */
+.mw-specialpagerestricted {
+       font-weight: bold;
+}
+
+.mw-specialpages-list {
+       -webkit-columns: 16em 2;
+       -moz-columns: 16em 2;
+       columns: 16em 2;
+}
+
+.mw-specialpages-list ul {
+       margin-top: 0;
+       margin-bottom: 0;
+}
+
+/* Special:Statistics */
+.mw-statistics-numbers {
+       text-align: right;
+}
+
+/* Special:ProtectedPages */
+.mw-protectedpages .mw-usertoollinks,
+.mw-protectedpages-length,
+.mw-protectedpages-actions {
+       white-space: nowrap;
+       font-size: 90%;
+}
+.mw-protectedpages-unknown {
+       color: #72777d;
+       font-size: 90%;
+}
diff --git a/resources/src/mediawiki.special/upload.css b/resources/src/mediawiki.special/upload.css
new file mode 100644 (file)
index 0000000..626a7e8
--- /dev/null
@@ -0,0 +1,15 @@
+/*!
+ * Styling for Special:Upload
+ */
+.mw-destfile-warning {
+       border: 1px solid #fde29b;
+       padding: 0.5em 1em;
+       margin-bottom: 1em;
+       color: #705000;
+       background-color: #fdf1d1;
+}
+
+p.mw-upload-editlicenses {
+       font-size: 90%;
+       text-align: right;
+}
diff --git a/resources/src/mediawiki.special/userrights.css b/resources/src/mediawiki.special/userrights.css
new file mode 100644 (file)
index 0000000..1ffdf70
--- /dev/null
@@ -0,0 +1,35 @@
+/*!
+ * Styling for Special:UserRights
+ */
+.mw-userrights-nested {
+       margin-left: 1.2em;
+}
+
+.mw-userrights-nested span {
+       margin-left: 0.3em;
+       display: inline-block;
+       vertical-align: middle;
+}
+
+.mw-userrights-disabled {
+       color: #72777d;
+}
+.mw-userrights-groups * td,
+.mw-userrights-groups * th {
+       padding-right: 1.5em;
+}
+
+.mw-userrights-groups * th {
+       text-align: left;
+}
+
+/* Dynamically show/hide the expiry selection underneath each checkbox */
+input.mw-userrights-groupcheckbox:not( :checked ) ~ .mw-userrights-nested {
+       display: none;
+}
+
+/* Initial hide the expiry fields to prevent a FOUC on loading */
+/* The input fields gets unhidden by JavaScript when needed */
+.client-js .mw-userrights-expiryfield {
+       display: none;
+}
diff --git a/resources/src/mediawiki.special/watchlist.css b/resources/src/mediawiki.special/watchlist.css
new file mode 100644 (file)
index 0000000..c9861c2
--- /dev/null
@@ -0,0 +1,15 @@
+/*!
+ * Styling for elements generated by JavaScript on Special:Watchlist
+ */
+.mw-changelist-line-inner-unwatched {
+       text-decoration: line-through;
+       opacity: 0.5;
+}
+
+span.mw-changeslist-line-prefix {
+       display: inline-block;
+}
+/* This can be either a span or a table cell */
+.mw-changeslist-line-prefix {
+       width: 1.25em;
+}
index 05afefa..d17fbbe 100644 (file)
@@ -28805,7 +28805,7 @@ foo {{echo|<span>bar</span> [[Category:baz]]}} bar
 # of the categories in wikitext
 # Do not remove these characters in edits.
 #
-# As part of the serialization, these bidi characters will get stripped.
+# As part of the serialization, these Unicode directional formatting characters will get stripped.
 !! test
 RTL (\u200f) and LTR (\u200e) markers around category tags should be stripped
 !! options
@@ -30811,3 +30811,27 @@ header
 *foo
 footer
 !! end
+
+!! test
+Check soft hyphens as entities (&shy;) in displaytitle (T66528)
+!! options
+showtitle
+title=[[Lopadotemachoselachogaleokranioleipsanodrimhypotrimmatosilphioparaomelitokatakechymenokichlepikossyphophattoperisteralektryonoptekephalliokigklopeleiolagoiosiraiobaphetraganopterygon]]
+!! wikitext
+{{DISPLAYTITLE:Lopado&shy;temacho&shy;selacho&shy;galeo&shy;kranio&shy;leipsano&shy;drim&shy;hypo&shy;trimmato&shy;silphio&shy;parao&shy;melito&shy;katakechy&shy;meno&shy;kichl&shy;epi&shy;kossypho&shy;phatto&shy;perister&shy;alektryon&shy;opte&shy;kephallio&shy;kigklo&shy;peleio&shy;lagoio&shy;siraio&shy;baphe&shy;tragano&shy;pterygon}}
+!! html/php
+Lopado&#173;temacho&#173;selacho&#173;galeo&#173;kranio&#173;leipsano&#173;drim&#173;hypo&#173;trimmato&#173;silphio&#173;parao&#173;melito&#173;katakechy&#173;meno&#173;kichl&#173;epi&#173;kossypho&#173;phatto&#173;perister&#173;alektryon&#173;opte&#173;kephallio&#173;kigklo&#173;peleio&#173;lagoio&#173;siraio&#173;baphe&#173;tragano&#173;pterygon
+
+!! end
+
+!! test
+Check soft hyphens as Unicode characters (U+00AD) in displaytitle (T66528)
+!! options
+showtitle
+title=[[Lopadotemachoselachogaleokranioleipsanodrimhypotrimmatosilphioparaomelitokatakechymenokichlepikossyphophattoperisteralektryonoptekephalliokigklopeleiolagoiosiraiobaphetraganopterygon]]
+!! wikitext
+{{DISPLAYTITLE:Lopado­temacho­selacho­galeo­kranio­leipsano­drim­hypo­trimmato­silphio­parao­melito­katakechy­meno­kichl­epi­kossypho­phatto­perister­alektryon­opte­kephallio­kigklo­peleio­lagoio­siraio­baphe­tragano­pterygon}}
+!! html/php
+Lopado­temacho­selacho­galeo­kranio­leipsano­drim­hypo­trimmato­silphio­parao­melito­katakechy­meno­kichl­epi­kossypho­phatto­perister­alektryon­opte­kephallio­kigklo­peleio­lagoio­siraio­baphe­tragano­pterygon
+
+!! end
index 5ea72b2..bd0461a 100644 (file)
@@ -317,8 +317,6 @@ return [
                "PhanParamSignatureRealMismatchTooFewParameters",
                // approximate error count: 125
                "PhanParamTooMany",
-               // approximate error count: 1
-               "PhanParamTooManyCallable",
                // approximate error count: 3
                "PhanParamTooManyInternal",
                // approximate error count: 1
@@ -329,10 +327,6 @@ return [
                "PhanTypeComparisonFromArray",
                // approximate error count: 2
                "PhanTypeComparisonToArray",
-               // approximate error count: 3
-               "PhanTypeInvalidRightOperand",
-               // approximate error count: 1
-               "PhanTypeMagicVoidWithReturn",
                // approximate error count: 218
                "PhanTypeMismatchArgument",
                // approximate error count: 13
@@ -341,8 +335,6 @@ return [
                "PhanTypeMismatchDeclaredParam",
                // approximate error count: 111
                "PhanTypeMismatchDeclaredParamNullable",
-               // approximate error count: 1
-               "PhanTypeMismatchDefault",
                // approximate error count: 5
                "PhanTypeMismatchDimAssignment",
                // approximate error count: 2
@@ -355,12 +347,8 @@ return [
                "PhanTypeMismatchProperty",
                // approximate error count: 74
                "PhanTypeMismatchReturn",
-               // approximate error count: 11
-               "PhanTypeMissingReturn",
                // approximate error count: 5
                "PhanTypeNonVarPassByRef",
-               // approximate error count: 1
-               "PhanUndeclaredClassInCallable",
                // approximate error count: 32
                "PhanUndeclaredConstant",
                // approximate error count: 233
@@ -369,10 +357,6 @@ return [
                "PhanUndeclaredProperty",
                // approximate error count: 3
                "PhanUndeclaredStaticMethod",
-               // approximate error count: 11
-               "PhanUndeclaredTypeReturnType",
-               // approximate error count: 27
-               "PhanUndeclaredVariable",
                // approximate error count: 58
                "PhanUndeclaredVariableDim",
        ],
index 4bffc74..e7db68e 100644 (file)
@@ -1272,4 +1272,99 @@ class ApiBaseTest extends ApiTestCase {
                }
        }
 
+       /**
+        * @covers ApiBase::extractRequestParams
+        */
+       public function testExtractRequestParams() {
+               $request = new FauxRequest( [
+                       'xxexists' => 'exists!',
+                       'xxmulti' => 'a|b|c|d|{bad}',
+                       'xxempty' => '',
+                       'xxtemplate-a' => 'A!',
+                       'xxtemplate-b' => 'B1|B2|B3',
+                       'xxtemplate-c' => '',
+                       'xxrecursivetemplate-b-B1' => 'X',
+                       'xxrecursivetemplate-b-B3' => 'Y',
+                       'xxrecursivetemplate-b-B4' => '?',
+                       'xxemptytemplate-' => 'nope',
+                       'foo' => 'a|b|c',
+                       'xxfoo' => 'a|b|c',
+                       'errorformat' => 'raw',
+               ] );
+               $context = new DerivativeContext( RequestContext::getMain() );
+               $context->setRequest( $request );
+               $main = new ApiMain( $context );
+
+               $mock = $this->getMockBuilder( ApiBase::class )
+                       ->setConstructorArgs( [ $main, 'test', 'xx' ] )
+                       ->setMethods( [ 'getAllowedParams' ] )
+                       ->getMockForAbstractClass();
+               $mock->method( 'getAllowedParams' )->willReturn( [
+                       'notexists' => null,
+                       'exists' => null,
+                       'multi' => [
+                               ApiBase::PARAM_ISMULTI => true,
+                       ],
+                       'empty' => [
+                               ApiBase::PARAM_ISMULTI => true,
+                       ],
+                       'template-{m}' => [
+                               ApiBase::PARAM_ISMULTI => true,
+                               ApiBase::PARAM_TEMPLATE_VARS => [ 'm' => 'multi' ],
+                       ],
+                       'recursivetemplate-{m}-{t}' => [
+                               ApiBase::PARAM_TEMPLATE_VARS => [ 't' => 'template-{m}', 'm' => 'multi' ],
+                       ],
+                       'emptytemplate-{m}' => [
+                               ApiBase::PARAM_ISMULTI => true,
+                               ApiBase::PARAM_TEMPLATE_VARS => [ 'm' => 'empty' ],
+                       ],
+                       'badtemplate-{e}' => [
+                               ApiBase::PARAM_TEMPLATE_VARS => [ 'e' => 'exists' ],
+                       ],
+                       'badtemplate2-{e}' => [
+                               ApiBase::PARAM_TEMPLATE_VARS => [ 'e' => 'badtemplate2-{e}' ],
+                       ],
+                       'badtemplate3-{x}' => [
+                               ApiBase::PARAM_TEMPLATE_VARS => [ 'x' => 'foo' ],
+                       ],
+               ] );
+
+               $this->assertEquals( [
+                       'notexists' => null,
+                       'exists' => 'exists!',
+                       'multi' => [ 'a', 'b', 'c', 'd', '{bad}' ],
+                       'empty' => [],
+                       'template-a' => [ 'A!' ],
+                       'template-b' => [ 'B1', 'B2', 'B3' ],
+                       'template-c' => [],
+                       'template-d' => null,
+                       'recursivetemplate-a-A!' => null,
+                       'recursivetemplate-b-B1' => 'X',
+                       'recursivetemplate-b-B2' => null,
+                       'recursivetemplate-b-B3' => 'Y',
+               ], $mock->extractRequestParams() );
+
+               $used = TestingAccessWrapper::newFromObject( $main )->getParamsUsed();
+               sort( $used );
+               $this->assertEquals( [
+                       'xxempty',
+                       'xxexists',
+                       'xxmulti',
+                       'xxnotexists',
+                       'xxrecursivetemplate-a-A!',
+                       'xxrecursivetemplate-b-B1',
+                       'xxrecursivetemplate-b-B2',
+                       'xxrecursivetemplate-b-B3',
+                       'xxtemplate-a',
+                       'xxtemplate-b',
+                       'xxtemplate-c',
+                       'xxtemplate-d',
+               ], $used );
+
+               $warnings = $mock->getResult()->getResultData( 'warnings', [ 'Strip' => 'all' ] );
+               $this->assertCount( 1, $warnings );
+               $this->assertSame( 'ignoring-invalid-templated-value', $warnings[0]['code'] );
+       }
+
 }
index dabf66b..354dae2 100644 (file)
@@ -35,7 +35,7 @@ class CSSMinTest extends MediaWikiTestCase {
        public static function provideSerializeStringValue() {
                return [
                        [ 'Hello World!', '"Hello World!"' ],
-                       [ "Null\0Null", "\"Null\\fffd Null\"" ],
+                       [ "Null\0Null", "\"Null\xEF\xBF\xBDNull\"" ],
                        [ '"', '"\\""' ],
                        [ "'", '"\'"' ],
                        [ "\\", '"\\\\"' ],
@@ -199,6 +199,9 @@ class CSSMinTest extends MediaWikiTestCase {
                        [ true, '//example.org/x.y.z/image.png' ],
                        [ true, '//localhost/styles.css?query=yes' ],
                        [ true, 'data:image/gif;base64,R0lGODlhAQABAIAAAP8AADAAACwAAAAAAQABAAACAkQBADs=' ],
+                       [ false, '' ],
+                       [ false, '/' ],
+                       [ true, '//' ],
                        [ false, 'x.gif' ],
                        [ false, '/x.gif' ],
                        [ false, './x.gif' ],
@@ -217,6 +220,9 @@ class CSSMinTest extends MediaWikiTestCase {
 
        public static function provideIsLocalUrls() {
                return [
+                       [ false, '' ],
+                       [ false, '/' ],
+                       [ false, '//' ],
                        [ false, 'x.gif' ],
                        [ true, '/x.gif' ],
                        [ false, './x.gif' ],
index a42e4be..bb51de0 100644 (file)
@@ -38,6 +38,6 @@ class ResourceLoaderLessVarFileModuleTest extends ResourceLoaderTestCase {
        public function testEscapeMessage( $msg, $expected ) {
                $method = new ReflectionMethod( ResourceLoaderLessVarFileModule::class, 'wrapAndEscapeMessage' );
                $method->setAccessible( true );
-               $this->assertEquals( $expected, $method->invoke( ResourceLoaderLessVarFileModule::class, $msg ) );
+               $this->assertEquals( $expected, $method->invoke( null, $msg ) );
        }
 }
index e1b98ec..c272551 100644 (file)
@@ -104,6 +104,13 @@ class MediaWikiTitleCodecTest extends MediaWikiTestCase {
                        // names ending in "a" to be female.
                        [ NS_USER, 'Lisa_Müller', '', '', 'de', 'Benutzerin:Lisa Müller' ],
                        [ NS_MAIN, 'FooBar', '', 'remotetestiw', 'en', 'remotetestiw:FooBar' ],
+                       // Strip soft hyphen and Unicode directional formatting characters
+                       [ NS_MAIN, "Foo\xC2\xAD\xD8\x9C\xE2\x80\x8E\xE2\x80\x8F\xE2\x80\xAA\xE2\x80\xAB" .
+                               "\xE2\x80\xAC\xE2\x80\xAD\xE2\x80\xAE\xE2\x81\xA6\xE2\x81\xA7" .
+                               "\xE2\x81\xA8\xE2\x81\xA9bar", '', '', 'en',
+                               "Foo\xC2\xAD\xD8\x9C\xE2\x80\x8E\xE2\x80\x8F\xE2\x80\xAA\xE2\x80\xAB" .
+                               "\xE2\x80\xAC\xE2\x80\xAD\xE2\x80\xAE\xE2\x81\xA6\xE2\x81\xA7" .
+                               "\xE2\x81\xA8\xE2\x81\xA9bar", 'Foobar' ],
                ];
        }
 
index 77d6e74..692bd73 100644 (file)
@@ -60,6 +60,7 @@ class ApiStructureTest extends MediaWikiTestCase {
                ApiBase::PARAM_ISMULTI_LIMIT2 => [ 'integer' ],
                ApiBase::PARAM_MAX_BYTES => [ 'integer' ],
                ApiBase::PARAM_MAX_CHARS => [ 'integer' ],
+               ApiBase::PARAM_TEMPLATE_VARS => [ 'array' ],
        ];
 
        // param => [ other param that must be present => required value or null ]
@@ -422,6 +423,45 @@ class ApiStructureTest extends MediaWikiTestCase {
                                                "$param: PARAM_MAX_BYTES cannot be less than PARAM_MAX_CHARS"
                                        );
                                }
+
+                               if ( isset( $config[ApiBase::PARAM_TEMPLATE_VARS] ) ) {
+                                       $this->assertNotSame( [], $config[ApiBase::PARAM_TEMPLATE_VARS],
+                                               "$param: PARAM_TEMPLATE_VARS cannot be empty" );
+                                       foreach ( $config[ApiBase::PARAM_TEMPLATE_VARS] as $key => $target ) {
+                                               $this->assertRegExp( '/^[^{}]+$/', $key,
+                                                       "$param: PARAM_TEMPLATE_VARS key may not contain '{' or '}'" );
+
+                                               $this->assertContains( '{' . $key . '}', $param,
+                                                       "$param: Name must contain PARAM_TEMPLATE_VARS key {" . $key . "}" );
+                                               $this->assertArrayHasKey( $target, $params,
+                                                       "$param: PARAM_TEMPLATE_VARS target parameter '$target' does not exist" );
+                                               $config2 = $params[$target];
+                                               $this->assertTrue( !empty( $config2[ApiBase::PARAM_ISMULTI] ),
+                                                       "$param: PARAM_TEMPLATE_VARS target parameter '$target' must have PARAM_ISMULTI = true" );
+
+                                               if ( isset( $config2[ApiBase::PARAM_TEMPLATE_VARS] ) ) {
+                                                       $this->assertNotSame( $param, $target,
+                                                               "$param: PARAM_TEMPLATE_VARS cannot target itself" );
+
+                                                       $this->assertArraySubset(
+                                                               $config2[ApiBase::PARAM_TEMPLATE_VARS],
+                                                               $config[ApiBase::PARAM_TEMPLATE_VARS],
+                                                               true,
+                                                               "$param: PARAM_TEMPLATE_VARS target parameter '$target': "
+                                                               . "the target's PARAM_TEMPLATE_VARS must be a subset of the original."
+                                                       );
+                                               }
+                                       }
+
+                                       $keys = implode( '|',
+                                               array_map( 'preg_quote', array_keys( $config[ApiBase::PARAM_TEMPLATE_VARS] ) )
+                                       );
+                                       $this->assertRegExp( '/^(?>[^{}]+|\{(?:' . $keys . ')\})+$/', $param,
+                                               "$param: Name may not contain '{' or '}' other than as defined by PARAM_TEMPLATE_VARS" );
+                               } else {
+                                       $this->assertRegExp( '/^[^{}]+$/', $param,
+                                               "$param: Name may not contain '{' or '}' without PARAM_TEMPLATE_VARS" );
+                               }
                        }
                }
        }
index d51dc37..d3f6533 100644 (file)
 
                $clone.find( '.mw-collapsible-toggle a' ).trigger( 'click' );
        } );
+
+       QUnit.test( 'T168689 - nested collapsible divs should keep independent state', function ( assert ) {
+               var $collapsible1 = prepareCollapsible(
+                               '<div class="mw-collapsible">' + loremIpsum + '</div>'
+                       ),
+                       $collapsible2 = prepareCollapsible(
+                               '<div class="mw-collapsible">' + loremIpsum + '</div>'
+                       );
+
+               $collapsible1
+                       .append( $collapsible2 )
+                       .appendTo( '#qunit-fixture' ).makeCollapsible();
+
+               $collapsible1.on( 'afterCollapse.mw-collapsible', function () {
+                       assert.assertTrue( $collapsible1.hasClass( 'mw-collapsed' ), 'after collapsing: parent is collapsed' );
+                       assert.assertFalse( $collapsible2.hasClass( 'mw-collapsed' ), 'after collapsing: child is not collapsed' );
+                       assert.assertTrue( $collapsible1.find( '> .mw-collapsible-toggle' ).hasClass( 'mw-collapsible-toggle-collapsed' ) );
+                       assert.assertFalse( $collapsible2.find( '> .mw-collapsible-toggle' ).hasClass( 'mw-collapsible-toggle-collapsed' ) );
+               } ).find( '> .mw-collapsible-toggle a' ).trigger( 'click' );
+       } );
 }( jQuery ) );
index d6fe744..e8db4e1 100644 (file)
                title = new mw.Title( 'Foo \u00A0\u1680\u180E\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200A\u2028\u2029\u202F\u205F\u3000 bar' );
                assert.equal( title.getMain(), 'Foo_bar', 'Merge multiple types of whitespace/underscores into a single underscore' );
 
-               title = new mw.Title( 'Foo\u200E\u200F\u202A\u202B\u202C\u202D\u202Ebar' );
-               assert.equal( title.getMain(), 'Foobar', 'Strip Unicode bidi override characters' );
+               title = new mw.Title( 'Foo\u00AD\u061C\u200E\u200F\u202A\u202B\u202C\u202D\u202E\u2066\u2067\u2068\u2069bar' );
+               assert.equal( title.getMain(), 'Foobar', 'Strip soft hyphen and Unicode directional formatting characters' );
 
                // Regression test: Previously it would only detect an extension if there is no space after it
                title = new mw.Title( 'Example.js  ' );
                                },
                                {
                                        fileName: 'BI\u200EDI.jpg',
-                                       typeOfName: 'Name containing BIDI overrides',
+                                       typeOfName: 'Name containing Unicode directional formatting characters',
                                        nameText: 'BIDI',
                                        prefixedText: 'File:BIDI.jpg'
                                },