Merge "Implement OO.ui.isMobile"
authorjenkins-bot <jenkins-bot@gerrit.wikimedia.org>
Tue, 10 Jan 2017 19:24:55 +0000 (19:24 +0000)
committerGerrit Code Review <gerrit@wikimedia.org>
Tue, 10 Jan 2017 19:24:55 +0000 (19:24 +0000)
153 files changed:
Gemfile
Gemfile.lock
RELEASE-NOTES-1.29
autoload.php
docs/hooks.txt
includes/DefaultSettings.php
includes/DummyLinker.php
includes/Linker.php
includes/MagicWord.php
includes/OutputPage.php
includes/Preferences.php
includes/WatchedItemQueryService.php
includes/api/ApiBase.php
includes/api/ApiHelp.php
includes/api/ApiImageRotate.php
includes/api/ApiMain.php
includes/api/ApiParamInfo.php
includes/api/ApiQueryAllLinks.php
includes/api/ApiQueryBacklinks.php
includes/api/ApiQueryBacklinksprop.php
includes/api/ApiQueryLinks.php
includes/api/ApiQueryLogEvents.php
includes/api/ApiQueryRecentChanges.php
includes/api/ApiQuerySiteinfo.php
includes/api/ApiQueryUserContributions.php
includes/api/ApiRevisionDelete.php
includes/api/ApiSetPageLanguage.php [new file with mode: 0755]
includes/api/ApiTag.php
includes/api/i18n/bn.json
includes/api/i18n/br.json
includes/api/i18n/de.json
includes/api/i18n/en.json
includes/api/i18n/es.json
includes/api/i18n/fr.json
includes/api/i18n/he.json
includes/api/i18n/ia.json
includes/api/i18n/it.json
includes/api/i18n/ko.json
includes/api/i18n/lb.json
includes/api/i18n/nl.json
includes/api/i18n/qqq.json
includes/api/i18n/ru.json
includes/api/i18n/zh-hans.json
includes/collation/CollationFa.php
includes/diff/DiffEngine.php
includes/import/ImportStreamSource.php
includes/installer/i18n/it.json
includes/jobqueue/jobs/RefreshLinksJob.php
includes/json/FormatJson.php
includes/libs/objectcache/WANObjectCache.php
includes/libs/redis/RedisConnectionPool.php
includes/parser/Parser.php
includes/parser/ParserOutput.php
includes/registration/ExtensionRegistry.php
includes/revisiondelete/RevDelList.php
includes/search/SearchHighlighter.php
includes/specialpage/LoginSignupSpecialPage.php
includes/specials/SpecialChangeContentModel.php
includes/specials/SpecialPageLanguage.php
includes/specials/SpecialRecentchanges.php
includes/specials/SpecialSearch.php
includes/title/MediaWikiTitleCodec.php
includes/user/User.php
includes/widget/search/FullSearchResultWidget.php [new file with mode: 0644]
includes/widget/search/SearchResultWidget.php [new file with mode: 0644]
includes/widget/search/SimpleSearchResultWidget.php [new file with mode: 0644]
languages/Language.php
languages/i18n/ar.json
languages/i18n/arn.json
languages/i18n/arz.json
languages/i18n/ba.json
languages/i18n/be-tarask.json
languages/i18n/bn.json
languages/i18n/bqi.json
languages/i18n/br.json
languages/i18n/ca.json
languages/i18n/ce.json
languages/i18n/cs.json
languages/i18n/de.json
languages/i18n/diq.json
languages/i18n/el.json
languages/i18n/en.json
languages/i18n/eo.json
languages/i18n/es.json
languages/i18n/fi.json
languages/i18n/fr.json
languages/i18n/gl.json
languages/i18n/he.json
languages/i18n/hif-latn.json
languages/i18n/hr.json
languages/i18n/hy.json
languages/i18n/ia.json
languages/i18n/io.json
languages/i18n/it.json
languages/i18n/ja.json
languages/i18n/ko.json
languages/i18n/ku-latn.json
languages/i18n/lb.json
languages/i18n/lo.json
languages/i18n/lv.json
languages/i18n/mk.json
languages/i18n/mr.json
languages/i18n/my.json
languages/i18n/nb.json
languages/i18n/nl.json
languages/i18n/or.json
languages/i18n/pl.json
languages/i18n/ps.json
languages/i18n/pt-br.json
languages/i18n/pt.json
languages/i18n/qqq.json
languages/i18n/ru.json
languages/i18n/sah.json
languages/i18n/sgs.json
languages/i18n/sl.json
languages/i18n/sv.json
languages/i18n/udm.json
languages/i18n/yue.json
languages/i18n/zh-hans.json
languages/i18n/zh-hant.json
languages/messages/MessagesEn.php
languages/messages/MessagesRup.php [new file with mode: 0644]
maintenance/namespaceDupes.php
maintenance/populateInterwiki.php
resources/Resources.php
resources/src/jquery/jquery.accessKeyLabel.js
resources/src/mediawiki.rcfilters/dm/mw.rcfilters.dm.FilterItem.js [new file with mode: 0644]
resources/src/mediawiki.rcfilters/dm/mw.rcfilters.dm.FiltersViewModel.js [new file with mode: 0644]
resources/src/mediawiki.rcfilters/mw.rcfilters.Controller.js [new file with mode: 0644]
resources/src/mediawiki.rcfilters/mw.rcfilters.init.js [new file with mode: 0644]
resources/src/mediawiki.rcfilters/mw.rcfilters.js [new file with mode: 0644]
resources/src/mediawiki.rcfilters/styles/mw.rcfilters.less [new file with mode: 0644]
resources/src/mediawiki.rcfilters/styles/mw.rcfilters.ui.FilterCapsuleMultiselectWidget.less [new file with mode: 0644]
resources/src/mediawiki.rcfilters/styles/mw.rcfilters.ui.FilterGroupWidget.less [new file with mode: 0644]
resources/src/mediawiki.rcfilters/styles/mw.rcfilters.ui.FilterItemWidget.less [new file with mode: 0644]
resources/src/mediawiki.rcfilters/styles/mw.rcfilters.ui.FilterWrapperWidget.less [new file with mode: 0644]
resources/src/mediawiki.rcfilters/styles/mw.rcfilters.ui.FiltersListWidget.less [new file with mode: 0644]
resources/src/mediawiki.rcfilters/ui/mw.rcfilters.ui.FilterCapsuleMultiselectWidget.js [new file with mode: 0644]
resources/src/mediawiki.rcfilters/ui/mw.rcfilters.ui.FilterGroupWidget.js [new file with mode: 0644]
resources/src/mediawiki.rcfilters/ui/mw.rcfilters.ui.FilterItemWidget.js [new file with mode: 0644]
resources/src/mediawiki.rcfilters/ui/mw.rcfilters.ui.FilterWrapperWidget.js [new file with mode: 0644]
resources/src/mediawiki.rcfilters/ui/mw.rcfilters.ui.FiltersListWidget.js [new file with mode: 0644]
resources/src/mediawiki/mediawiki.ForeignStructuredUpload.BookletLayout.js
resources/src/mediawiki/mediawiki.Upload.BookletLayout.js
tests/parser/parserTests.txt
tests/phan/config.php
tests/phpunit/includes/filerepo/StoreBatchTest.php
tests/phpunit/includes/interwiki/InterwikiTest.php
tests/phpunit/includes/media/MediaWikiMediaTestCase.php
tests/phpunit/includes/user/UserTest.php
tests/qunit/QUnitTestResources.php
tests/qunit/suites/resources/jquery/jquery.accessKeyLabel.test.js
tests/qunit/suites/resources/mediawiki.rcfilters/dm.FiltersViewModel.test.js [new file with mode: 0644]

diff --git a/Gemfile b/Gemfile
index 8a349bf..8bbd00f 100644 (file)
--- a/Gemfile
+++ b/Gemfile
@@ -1,5 +1,5 @@
 source 'https://rubygems.org'
 
-gem 'mediawiki_selenium', '~> 1.7', '>= 1.7.2'
+gem 'mediawiki_selenium', '~> 1.7', '>= 1.7.4'
 gem 'rake', '~> 11.1', '>= 11.1.1'
 gem 'rubocop', '~> 0.32.1', require: false
index 982619a..8243874 100644 (file)
@@ -13,55 +13,58 @@ GEM
       gherkin (~> 2.12)
       multi_json (>= 1.7.5, < 2.0)
       multi_test (>= 0.1.2)
-    data_magic (0.22)
+    data_magic (1.0)
       faker (>= 1.1.2)
       yml_reader (>= 0.6)
     diff-lcs (1.2.5)
-    domain_name (0.5.20160615)
+    domain_name (0.5.20161129)
       unf (>= 0.0.5, < 1.0.0)
-    faker (1.6.6)
+    faker (1.7.1)
       i18n (~> 0.5)
-    faraday (0.9.2)
+    faraday (0.10.0)
       multipart-post (>= 1.2, < 3)
     faraday-cookie_jar (0.0.6)
       faraday (>= 0.7.4)
       http-cookie (~> 1.0.0)
-    faraday_middleware (0.10.0)
-      faraday (>= 0.7.4, < 0.10)
+    faraday_middleware (0.10.1)
+      faraday (>= 0.7.4, < 1.0)
     ffi (1.9.14)
     gherkin (2.12.2)
       multi_json (~> 1.3)
-    headless (2.2.3)
-    http-cookie (1.0.2)
+    headless (2.3.1)
+    http-cookie (1.0.3)
       domain_name (~> 0.5)
     i18n (0.7.0)
-    json (1.8.3)
+    json (2.0.2)
     mediawiki_api (0.7.0)
       faraday (~> 0.9, >= 0.9.0)
       faraday-cookie_jar (~> 0.0, >= 0.0.6)
       faraday_middleware (~> 0.10, >= 0.10.0)
-    mediawiki_selenium (1.7.2)
+    mediawiki_selenium (1.7.4)
       cucumber (~> 1.3, >= 1.3.20)
       headless (~> 2.0, >= 2.1.0)
-      json (~> 1.8, >= 1.8.1)
+      json (~> 2.0, >= 2.0.2)
       mediawiki_api (~> 0.7, >= 0.7.0)
       page-object (~> 1.0)
       rest-client (~> 1.6, >= 1.6.7)
       rspec-core (~> 2.14, >= 2.14.4)
       rspec-expectations (~> 2.14, >= 2.14.4)
+      selenium-webdriver (< 3)
       syntax (~> 1.2, >= 1.2.0)
       thor (~> 0.19, >= 0.19.1)
-    mime-types (2.99.2)
+    mime-types (2.99.3)
     multi_json (1.12.1)
     multi_test (0.1.2)
     multipart-post (2.0.0)
+    net-http-persistent (2.9.4)
     netrc (0.11.0)
-    page-object (1.2.0)
+    page-object (1.2.2)
+      net-http-persistent (~> 2.9.4)
       page_navigation (>= 0.9)
-      selenium-webdriver (>= 2.44.0)
-      watir-webdriver (>= 0.6.11)
-    page_navigation (0.9)
-      data_magic (>= 0.14)
+      selenium-webdriver (>= 2.53.0)
+      watir-webdriver (>= 0.6.11, < 0.9.9)
+    page_navigation (0.10)
+      data_magic (>= 0.22)
     parser (2.2.2.6)
       ast (>= 1.1, < 3.0)
     powerpack (0.1.1)
@@ -87,7 +90,7 @@ GEM
       rubyzip (~> 1.0)
       websocket (~> 1.0)
     syntax (1.2.1)
-    thor (0.19.1)
+    thor (0.19.4)
     unf (0.1.4)
       unf_ext
     unf_ext (0.0.7.2)
@@ -100,6 +103,9 @@ PLATFORMS
   ruby
 
 DEPENDENCIES
-  mediawiki_selenium (~> 1.7, >= 1.7.2)
+  mediawiki_selenium (~> 1.7, >= 1.7.4)
   rake (~> 11.1, >= 11.1.1)
   rubocop (~> 0.32.1)
+
+BUNDLED WITH
+   1.13.7
index 72c82de..e66b9ce 100644 (file)
@@ -6,8 +6,8 @@ MediaWiki 1.29 is an alpha-quality branch and is not recommended for use in
 production.
 
 === Configuration changes in 1.29 ===
-* Default cookie expiration time has been reduced to 30 days. Login cookie expiration time is
-  kept at 180 days.
+* Default cookie expiration time has been reduced to 30 days. Login cookie
+  expiration time is kept at 180 days.
 * A new configuration variable has been added: $wgCookieSetOnAutoblock. This
   determines whether to set a cookie when a user is autoblocked. Doing so means
   that a blocked user, even after logging out and moving to a new IP address,
@@ -22,21 +22,28 @@ production.
   code for ApiBase::parseMsg() will no longer work.
 * ApiBase::$messageMap is no longer public. Code attempting to access it will
   result in a PHP fatal error.
-* $wgUserEmailUseReplyTo is now true by default to work around restrictive DMARC policies.
+* $wgUserEmailUseReplyTo is now true by default to work around restrictive DMARC
+  policies.
 * Subpages are now enabled by default in the Template namespace. Set
   $wgNamespacesWithSubpages[NS_TEMPLATE] to false to keep the old behavior.
 * $wgRunJobsAsync is now false by default (T142751). This change only affects
   wikis with $wgJobRunRate > 0.
 
 === New features in 1.29 ===
-* (T5233) A cookie can now be set when a user is autoblocked, to track that user if
-  they move to a new IP address. This is disabled by default.
+* (T5233) A cookie can now be set when a user is autoblocked, to track that user
+  if they move to a new IP address. This is disabled by default.
 * Added ILocalizedException interface to standardize the use of localized
   exceptions, largely so the API can handle them more sensibly.
 * Blocks created automatically by MediaWiki, such as for configured proxies or
   dnsbls, are now indicated as such and use a new i18n message when displayed.
 * Added new $wgHTTPImportTimeout setting. Sets timeout for
   downloading the XML dump during a transwiki import in seconds.
+* Parser limit report is now available in machine-readable format to JavaScript
+  via mw.config.get('wgPageParseReport').
+* Added $wgSoftBlockRanges, to allow for automatically blocking anonymous edits
+  from certain IP ranges (e.g. private IPs).
+* (T59603) Added new magic word {{PAGELANGUAGE}} which returns the language code
+  of the page being parsed.
 
 === External library changes in 1.29 ===
 
@@ -137,7 +144,7 @@ changes to languages because of Phabricator reports.
 * Xml::escapeJsString() (deprecated in 1.21) was removed.
 * Article::getText() and Article::prepareTextForEdit() (deprecated in 1.21)
   were removed.
-* Article::getAutosummary() and WikiPage::getAutosummary (deprecated in 1.21)
+* Article::getAutosummary() and WikiPage::getAutosummary() (deprecated in 1.21)
   were removed.
 * Hooks ArticleViewCustom, EditPageGetDiffText and ShowRawCssJs (deprecated in 1.21)
   were removed.
@@ -148,16 +155,20 @@ changes to languages because of Phabricator reports.
 * User::getPassword() (deprecated in 1.27) was removed.
 * User::getTemporaryPassword() (deprecated in 1.27) was removed.
 * User::isPasswordReminderThrottled() (deprecated in 1.27) was removed.
-* FSRepo (deprecated in 1.19) was removed.
+* Class FSRepo (deprecated in 1.19) was removed.
 * WebRequest::checkSessionCookie() (deprecated in 1.27) was removed. Use
-\MediaWiki\Session\SessionManager::singleton()->getPersistedSessionId() instead.
+  \MediaWiki\Session\SessionManager::singleton()->getPersistedSessionId() instead.
 * Class ImageGallery (deprecated in 1.22) was removed.
   Use ImageGalleryBase::factory instead.
 * Title::moveNoAuth() (deprecated in 1.25) was removed. Use MovePage class instead.
-* Hook UnknownAction (deprecated in 1.19) was actually deprecated (it will now emit warnings).
-  Create a subclass of Action, and add it to $wgActions instead.
-* WikiRevision:getText() (deprecated since 1.21) is no longer marked deprecated.
-
+* Hook UnknownAction (deprecated in 1.19) was actually deprecated (it will now
+  emit warnings). Create a subclass of Action and add it to $wgActions instead.
+* WikiRevision::getText() (deprecated since 1.21) is no longer marked deprecated.
+* Linker::getInterwikiLinkAttributes() (deprecated since 1.25) was removed.
+* Linker::getInternalLinkAttributes() (deprecated since 1.25) was removed.
+* Linker::getInternalLinkAttributesObj() (deprecated since 1.25) was removed.
+* Linker::getLinkAttributesInternal() (deprecated since 1.25) was removed.
+* RedisConnectionPool::handleException (deprecated since 1.23) was removed.
 == Compatibility ==
 
 MediaWiki 1.29 requires PHP 5.5.9 or later. There is experimental support for
index cdbdf1f..c8033cf 100644 (file)
@@ -139,6 +139,7 @@ $wgAutoloadLocalClasses = [
        'ApiRsd' => __DIR__ . '/includes/api/ApiRsd.php',
        'ApiSerializable' => __DIR__ . '/includes/api/ApiSerializable.php',
        'ApiSetNotificationTimestamp' => __DIR__ . '/includes/api/ApiSetNotificationTimestamp.php',
+       'ApiSetPageLanguage' => __DIR__ . '/includes/api/ApiSetPageLanguage.php',
        'ApiStashEdit' => __DIR__ . '/includes/api/ApiStashEdit.php',
        'ApiTag' => __DIR__ . '/includes/api/ApiTag.php',
        'ApiTokens' => __DIR__ . '/includes/api/ApiTokens.php',
@@ -931,6 +932,9 @@ $wgAutoloadLocalClasses = [
        'MediaWiki\\Widget\\DateTimeInputWidget' => __DIR__ . '/includes/widget/DateTimeInputWidget.php',
        'MediaWiki\\Widget\\NamespaceInputWidget' => __DIR__ . '/includes/widget/NamespaceInputWidget.php',
        'MediaWiki\\Widget\\SearchInputWidget' => __DIR__ . '/includes/widget/SearchInputWidget.php',
+       'MediaWiki\\Widget\\Search\\FullSearchResultWidget' => __DIR__ . '/includes/widget/search/FullSearchResultWidget.php',
+       'MediaWiki\\Widget\\Search\\SearchResultWidget' => __DIR__ . '/includes/widget/search/SearchResultWidget.php',
+       'MediaWiki\\Widget\\Search\\SimpleSearchResultWidget' => __DIR__ . '/includes/widget/search/SimpleSearchResultWidget.php',
        'MediaWiki\\Widget\\TitleInputWidget' => __DIR__ . '/includes/widget/TitleInputWidget.php',
        'MediaWiki\\Widget\\UserInputWidget' => __DIR__ . '/includes/widget/UserInputWidget.php',
        'MemCachedClientforWiki' => __DIR__ . '/includes/compat/MemcachedClientCompat.php',
index 2f99fff..1da39cf 100644 (file)
@@ -2877,7 +2877,7 @@ $terms: Search terms, for highlighting
   function returned false.
 
 'ShowSearchHitTitle': Customise display of search hit title/link.
-&$title: Title to link to
+$title: Title to link to
 &$text: Text to use for the link
 $result: The search result
 $terms: The search terms entered
index 449e1c2..ffa5c21 100644 (file)
@@ -443,7 +443,6 @@ $wgImgAuthUrlPathMap = [];
  * Properties required for all repos:
  *   - class            The class name for the repository. May come from the core or an extension.
  *                      The core repository classes are FileRepo, LocalRepo, ForeignDBRepo.
- *                      FSRepo is also supported for backwards compatibility.
  *
  *   - name             A unique name for the repository (but $wgLocalFileRepo should be 'local').
  *                      The name should consist of alpha-numeric characters.
@@ -4817,6 +4816,7 @@ $wgDefaultUserOptions = [
        'previewonfirst' => 0,
        'previewontop' => 1,
        'rcdays' => 7,
+       'rcenhancedfilters' => 0,
        'rclimit' => 50,
        'rows' => 25,
        'showhiddencats' => 0,
@@ -4851,7 +4851,9 @@ $wgDefaultUserOptions = [
 /**
  * An array of preferences to not show for the user
  */
-$wgHiddenPrefs = [];
+$wgHiddenPrefs = [
+       'rcenhancedfilters',
+];
 
 /**
  * Characters to prevent during new account creations.
@@ -5512,6 +5514,15 @@ $wgDnsBlacklistUrls = [ 'http.dnsbl.sorbs.net.' ];
  */
 $wgProxyWhitelist = [];
 
+/**
+ * IP ranges that should be considered soft-blocked (anon-only, account
+ * creation allowed). The intent is to use this to prevent anonymous edits from
+ * shared resources such as Wikimedia Labs.
+ * @since 1.29
+ * @var string[]
+ */
+$wgSoftBlockRanges = [];
+
 /**
  * Whether to look at the X-Forwarded-For header's list of (potentially spoofed)
  * IPs and apply IP blocks to them. This allows for IP blocks to work with correctly-configured
index fc94a63..9aa6aeb 100644 (file)
@@ -5,48 +5,6 @@
  */
 class DummyLinker {
 
-       /**
-        * @deprecated since 1.27
-        */
-       public function getInterwikiLinkAttributes( $title, $unused = null, $class = 'external' ) {
-               wfDeprecated( __METHOD__, '1.27' );
-               return Linker::getInterwikiLinkAttributes(
-                       $title,
-                       $unused,
-                       $class
-               );
-       }
-
-       /**
-        * @deprecated since 1.27
-        */
-       public function getInternalLinkAttributes( $title, $unused = null, $class = '' ) {
-               wfDeprecated( __METHOD__, '1.27' );
-               return Linker::getInternalLinkAttributes(
-                       $title,
-                       $unused,
-                       $class
-               );
-       }
-
-       /**
-        * @deprecated since 1.27
-        */
-       public function getInternalLinkAttributesObj(
-               $nt,
-               $unused = null,
-               $class = '',
-               $title = false
-       ) {
-               wfDeprecated( __METHOD__, '1.27' );
-               return Linker::getInternalLinkAttributesObj(
-                       $nt,
-                       $unused,
-                       $class,
-                       $title
-               );
-       }
-
        /**
         * @deprecated since 1.28, use LinkRenderer::getLinkClasses() instead
         */
index d3d1f38..794e2e9 100644 (file)
@@ -38,102 +38,6 @@ class Linker {
        const TOOL_LINKS_NOBLOCK = 1;
        const TOOL_LINKS_EMAIL = 2;
 
-       /**
-        * Get the appropriate HTML attributes to add to the "a" element of an interwiki link.
-        *
-        * @since 1.16.3
-        * @deprecated since 1.25
-        *
-        * @param string $title The title text for the link, URL-encoded (???) but
-        *   not HTML-escaped
-        * @param string $unused Unused
-        * @param string $class The contents of the class attribute; if an empty
-        *   string is passed, which is the default value, defaults to 'external'.
-        * @return string
-        */
-       static function getInterwikiLinkAttributes( $title, $unused = null, $class = 'external' ) {
-               global $wgContLang;
-
-               wfDeprecated( __METHOD__, '1.25' );
-
-               # @todo FIXME: We have a whole bunch of handling here that doesn't happen in
-               # getExternalLinkAttributes, why?
-               $title = urldecode( $title );
-               $title = $wgContLang->checkTitleEncoding( $title );
-               $title = preg_replace( '/[\\x00-\\x1f]/', ' ', $title );
-
-               return self::getLinkAttributesInternal( $title, $class );
-       }
-
-       /**
-        * Get the appropriate HTML attributes to add to the "a" element of an internal link.
-        *
-        * @since 1.16.3
-        * @deprecated since 1.25
-        *
-        * @param string $title The title text for the link, URL-encoded (???) but
-        *   not HTML-escaped
-        * @param string $unused Unused
-        * @param string $class The contents of the class attribute, default none
-        * @return string
-        */
-       static function getInternalLinkAttributes( $title, $unused = null, $class = '' ) {
-               wfDeprecated( __METHOD__, '1.25' );
-
-               $title = urldecode( $title );
-               $title = strtr( $title, '_', ' ' );
-               return self::getLinkAttributesInternal( $title, $class );
-       }
-
-       /**
-        * Get the appropriate HTML attributes to add to the "a" element of an internal
-        * link, given the Title object for the page we want to link to.
-        *
-        * @since 1.16.3
-        * @deprecated since 1.25
-        *
-        * @param Title $nt
-        * @param string $unused Unused
-        * @param string $class The contents of the class attribute, default none
-        * @param string|bool $title Optional (unescaped) string to use in the title
-        *   attribute; if false, default to the name of the page we're linking to
-        * @return string
-        */
-       static function getInternalLinkAttributesObj( $nt, $unused = null, $class = '', $title = false ) {
-               wfDeprecated( __METHOD__, '1.25' );
-
-               if ( $title === false ) {
-                       $title = $nt->getPrefixedText();
-               }
-               return self::getLinkAttributesInternal( $title, $class );
-       }
-
-       /**
-        * Common code for getLinkAttributesX functions
-        *
-        * @since 1.16.3
-        * @deprecated since 1.25
-        *
-        * @param string $title
-        * @param string $class
-        *
-        * @return string
-        */
-       private static function getLinkAttributesInternal( $title, $class ) {
-               wfDeprecated( __METHOD__, '1.25' );
-
-               $title = htmlspecialchars( $title );
-               $class = htmlspecialchars( $class );
-               $r = '';
-               if ( $class != '' ) {
-                       $r .= " class=\"$class\"";
-               }
-               if ( $title != '' ) {
-                       $r .= " title=\"$title\"";
-               }
-               return $r;
-       }
-
        /**
         * Return the CSS colour of a known link
         *
index 391e05a..5968e87 100644 (file)
@@ -169,6 +169,7 @@ class MagicWord {
                'localtimestamp',
                'directionmark',
                'contentlanguage',
+               'pagelanguage',
                'numberofadmins',
                'cascadingsources',
        ];
index f140f54..211f44b 100644 (file)
@@ -299,6 +299,9 @@ class OutputPage extends ContextSource {
         */
        private $copyrightUrl;
 
+       /** @var array Profiling data */
+       private $limitReportJSData = [];
+
        /**
         * Constructor for OutputPage. This should not be called directly.
         * Instead a new RequestContext should be created and it will implicitly create
@@ -1804,11 +1807,16 @@ class OutputPage extends ContextSource {
                        }
                }
 
-               // enable OOUI if requested via ParserOutput
+               // Enable OOUI if requested via ParserOutput
                if ( $parserOutput->getEnableOOUI() ) {
                        $this->enableOOUI();
                }
 
+               // Include parser limit report
+               if ( !$this->limitReportJSData ) {
+                       $this->limitReportJSData = $parserOutput->getLimitReportJSData();
+               }
+
                // Link flags are ignored for now, but may in the future be
                // used to mark individual language links.
                $linkFlags = [];
@@ -3005,6 +3013,14 @@ class OutputPage extends ContextSource {
                        }
                }
 
+               if ( $this->limitReportJSData ) {
+                       $chunks[] = ResourceLoader::makeInlineScript(
+                               ResourceLoader::makeConfigSetScript(
+                                       [ 'wgPageParseReport' => $this->limitReportJSData ]
+                               )
+                       );
+               }
+
                return self::combineWrappedStrings( $chunks );
        }
 
index cf8e7b8..263ff5b 100644 (file)
@@ -696,19 +696,23 @@ class Preferences {
                $tzOptions = self::getTimezoneOptions( $context );
 
                $tzSetting = $tzOffset;
-               if ( count( $tz ) > 1 && $tz[0] == 'Offset' ) {
-                       $minDiff = $tz[1];
-                       $tzSetting = sprintf( '%+03d:%02d', floor( $minDiff / 60 ), abs( $minDiff ) % 60 );
-               } elseif ( count( $tz ) > 1 && $tz[0] == 'ZoneInfo' &&
+               if ( count( $tz ) > 1 && $tz[0] == 'ZoneInfo' &&
                        !in_array( $tzOffset, HTMLFormField::flattenOptions( $tzOptions ) )
                ) {
-                       # Timezone offset can vary with DST
-                       $userTZ = timezone_open( $tz[2] );
-                       if ( $userTZ !== false ) {
-                               $minDiff = floor( timezone_offset_get( $userTZ, date_create( 'now' ) ) / 60 );
+                       // Timezone offset can vary with DST
+                       try {
+                               $userTZ = new DateTimeZone( $tz[2] );
+                               $minDiff = floor( $userTZ->getOffset( new DateTime( 'now' ) ) / 60 );
                                $tzSetting = "ZoneInfo|$minDiff|{$tz[2]}";
+                       } catch ( Exception $e ) {
+                               // User has an invalid time zone set. Fall back to just using the offset
+                               $tz[0] = 'Offset';
                        }
                }
+               if ( count( $tz ) > 1 && $tz[0] == 'Offset' ) {
+                       $minDiff = $tz[1];
+                       $tzSetting = sprintf( '%+03d:%02d', floor( $minDiff / 60 ), abs( $minDiff ) % 60 );
+               }
 
                $defaultPreferences['timecorrection'] = [
                        'class' => 'HTMLSelectOrOtherField',
@@ -1391,6 +1395,24 @@ class Preferences {
                $data = explode( '|', $tz, 3 );
                switch ( $data[0] ) {
                        case 'ZoneInfo':
+                               $valid = false;
+
+                               if ( count( $data ) === 3 ) {
+                                       // Make sure this timezone exists
+                                       try {
+                                               new DateTimeZone( $data[2] );
+                                               // If the constructor didn't throw, we know it's valid
+                                               $valid = true;
+                                       } catch ( Exception $e ) {
+                                               // Not a valid timezone
+                                       }
+                               }
+
+                               if ( !$valid ) {
+                                       // If the supplied timezone doesn't exist, fall back to the encoded offset
+                                       return 'Offset|' . intval( $tz[1] );
+                               }
+                               return $tz;
                        case 'System':
                                return $tz;
                        default:
@@ -1409,7 +1431,7 @@ class Preferences {
                                # Max is +14:00 and min is -12:00, see:
                                # https://en.wikipedia.org/wiki/Timezone
                                $minDiff = min( $minDiff, 840 );  # 14:00
-                               $minDiff = max( $minDiff, - 720 ); # -12:00
+                               $minDiff = max( $minDiff, -720 ); # -12:00
                                return 'Offset|' . $minDiff;
                }
        }
index cd78b49..c80e4a5 100644 (file)
@@ -471,7 +471,7 @@ class WatchedItemQueryService {
        }
 
        private function getStartEndConds( IDatabase $db, array $options ) {
-               if ( !isset( $options['start'] ) && ! isset( $options['end'] ) ) {
+               if ( !isset( $options['start'] ) && !isset( $options['end'] ) ) {
                        return [];
                }
 
index 063d661..b8dd464 100644 (file)
@@ -180,6 +180,12 @@ abstract class ApiBase extends ContextSource {
         */
        const PARAM_ALL = 17;
 
+       /**
+        * (int[]) When PARAM_TYPE is 'namespace', include these as additional possible values.
+        * @since 1.29
+        */
+       const PARAM_EXTRA_NAMESPACES = 18;
+
        /**@}*/
 
        const ALL_DEFAULT_STRING = '*';
@@ -899,6 +905,34 @@ abstract class ApiBase extends ContextSource {
                return $pageObj;
        }
 
+       /**
+        * Get a Title object from a title or pageid param, if possible.
+        * Can die, if no param is set or if the title or page id is not valid.
+        *
+        * @since 1.29
+        * @param array $params
+        * @return Title
+        */
+       public function getTitleFromTitleOrPageId( $params ) {
+               $this->requireOnlyOneParameter( $params, 'title', 'pageid' );
+
+               $titleObj = null;
+               if ( isset( $params['title'] ) ) {
+                       $titleObj = Title::newFromText( $params['title'] );
+                       if ( !$titleObj || $titleObj->isExternal() ) {
+                               $this->dieWithError( [ 'apierror-invalidtitle', wfEscapeWikiText( $params['title'] ) ] );
+                       }
+                       return $titleObj;
+               } elseif ( isset( $params['pageid'] ) ) {
+                       $titleObj = Title::newFromID( $params['pageid'] );
+                       if ( !$titleObj ) {
+                               $this->dieWithError( [ 'apierror-nosuchpageid', $params['pageid'] ] );
+                       }
+               }
+
+               return $titleObj;
+       }
+
        /**
         * Return true if we're to watch the page, false if not, null if no change.
         * @param string $watchlist Valid values: 'watch', 'unwatch', 'preferences', 'nochange'
@@ -953,44 +987,41 @@ abstract class ApiBase extends ContextSource {
                // Some classes may decide to change parameter names
                $encParamName = $this->encodeParamName( $paramName );
 
+               // Shorthand
                if ( !is_array( $paramSettings ) ) {
-                       $default = $paramSettings;
-                       $multi = false;
-                       $type = gettype( $paramSettings );
-                       $dupes = false;
-                       $deprecated = false;
-                       $required = false;
-                       $allowAll = false;
-               } else {
-                       $default = isset( $paramSettings[self::PARAM_DFLT] )
-                               ? $paramSettings[self::PARAM_DFLT]
-                               : null;
-                       $multi = isset( $paramSettings[self::PARAM_ISMULTI] )
-                               ? $paramSettings[self::PARAM_ISMULTI]
-                               : false;
-                       $type = isset( $paramSettings[self::PARAM_TYPE] )
-                               ? $paramSettings[self::PARAM_TYPE]
-                               : null;
-                       $dupes = isset( $paramSettings[self::PARAM_ALLOW_DUPLICATES] )
-                               ? $paramSettings[self::PARAM_ALLOW_DUPLICATES]
-                               : false;
-                       $deprecated = isset( $paramSettings[self::PARAM_DEPRECATED] )
-                               ? $paramSettings[self::PARAM_DEPRECATED]
-                               : false;
-                       $required = isset( $paramSettings[self::PARAM_REQUIRED] )
-                               ? $paramSettings[self::PARAM_REQUIRED]
-                               : false;
-                       $allowAll = isset( $paramSettings[self::PARAM_ALL] )
-                               ? $paramSettings[self::PARAM_ALL]
-                               : false;
-
-                       // When type is not given, and no choices, the type is the same as $default
-                       if ( !isset( $type ) ) {
-                               if ( isset( $default ) ) {
-                                       $type = gettype( $default );
-                               } else {
-                                       $type = 'NULL'; // allow everything
-                               }
+                       $paramSettings = [
+                               self::PARAM_DFLT => $paramSettings,
+                       ];
+               }
+
+               $default = isset( $paramSettings[self::PARAM_DFLT] )
+                       ? $paramSettings[self::PARAM_DFLT]
+                       : null;
+               $multi = isset( $paramSettings[self::PARAM_ISMULTI] )
+                       ? $paramSettings[self::PARAM_ISMULTI]
+                       : false;
+               $type = isset( $paramSettings[self::PARAM_TYPE] )
+                       ? $paramSettings[self::PARAM_TYPE]
+                       : null;
+               $dupes = isset( $paramSettings[self::PARAM_ALLOW_DUPLICATES] )
+                       ? $paramSettings[self::PARAM_ALLOW_DUPLICATES]
+                       : false;
+               $deprecated = isset( $paramSettings[self::PARAM_DEPRECATED] )
+                       ? $paramSettings[self::PARAM_DEPRECATED]
+                       : false;
+               $required = isset( $paramSettings[self::PARAM_REQUIRED] )
+                       ? $paramSettings[self::PARAM_REQUIRED]
+                       : false;
+               $allowAll = isset( $paramSettings[self::PARAM_ALL] )
+                       ? $paramSettings[self::PARAM_ALL]
+                       : false;
+
+               // When type is not given, and no choices, the type is the same as $default
+               if ( !isset( $type ) ) {
+                       if ( isset( $default ) ) {
+                               $type = gettype( $default );
+                       } else {
+                               $type = 'NULL'; // allow everything
                        }
                }
 
@@ -1034,6 +1065,11 @@ abstract class ApiBase extends ContextSource {
 
                        if ( isset( $value ) && $type == 'namespace' ) {
                                $type = MWNamespace::getValidNamespaces();
+                               if ( isset( $paramSettings[self::PARAM_EXTRA_NAMESPACES] ) &&
+                                       is_array( $paramSettings[self::PARAM_EXTRA_NAMESPACES] )
+                               ) {
+                                       $type = array_merge( $type, $paramSettings[self::PARAM_EXTRA_NAMESPACES] );
+                               }
                                // By default, namespace parameters allow ALL_DEFAULT_STRING to be used to specify
                                // all namespaces.
                                $allowAll = true;
index 9a0d3ff..e347a9f 100644 (file)
@@ -547,6 +547,12 @@ class ApiHelp extends ApiBase {
 
                                                                case 'namespace':
                                                                        $namespaces = MWNamespace::getValidNamespaces();
+                                                                       if ( isset( $settings[ApiBase::PARAM_EXTRA_NAMESPACES] ) &&
+                                                                               is_array( $settings[ApiBase::PARAM_EXTRA_NAMESPACES] )
+                                                                       ) {
+                                                                               $namespaces = array_merge( $namespaces, $settings[ApiBase::PARAM_EXTRA_NAMESPACES] );
+                                                                       }
+                                                                       sort( $namespaces );
                                                                        $count = count( $namespaces );
                                                                        $info[] = $context->msg( 'api-help-param-list' )
                                                                                ->params( $multi ? 2 : 1 )
index 72fb16d..71bda6d 100644 (file)
@@ -42,6 +42,14 @@ class ApiImageRotate extends ApiBase {
                        'invalidTitles', 'special', 'missingIds', 'missingRevIds', 'interwikiTitles',
                ] );
 
+               // Check if user can add tags
+               if ( count( $params['tags'] ) ) {
+                       $ableToTag = ChangeTags::canAddTagsAccompanyingChange( $params['tags'], $this->getUser() );
+                       if ( !$ableToTag->isOK() ) {
+                               $this->dieStatus( $ableToTag );
+                       }
+               }
+
                foreach ( $pageSet->getTitles() as $title ) {
                        $r = [];
                        $r['id'] = $title->getArticleID();
@@ -104,8 +112,16 @@ class ApiImageRotate extends ApiBase {
                                $comment = wfMessage(
                                        'rotate-comment'
                                )->numParams( $rotation )->inContentLanguage()->text();
-                               $status = $file->upload( $dstPath,
-                                       $comment, $comment, 0, false, false, $this->getUser() );
+                               $status = $file->upload(
+                                       $dstPath,
+                                       $comment,
+                                       $comment,
+                                       0,
+                                       false,
+                                       false,
+                                       $this->getUser(),
+                                       $params['tags'] ?: []
+                               );
                                if ( $status->isGood() ) {
                                        $r['result'] = 'Success';
                                } else {
@@ -157,6 +173,10 @@ class ApiImageRotate extends ApiBase {
                        'continue' => [
                                ApiBase::PARAM_HELP_MSG => 'api-help-param-continue',
                        ],
+                       'tags' => [
+                               ApiBase::PARAM_TYPE => 'tags',
+                               ApiBase::PARAM_ISMULTI => true,
+                       ],
                ];
                if ( $flags ) {
                        $result += $this->getPageSet()->getFinalParams( $flags );
index 4220fb8..52f1d95 100644 (file)
@@ -106,6 +106,7 @@ class ApiMain extends ApiBase {
                'managetags' => 'ApiManageTags',
                'tag' => 'ApiTag',
                'mergehistory' => 'ApiMergeHistory',
+               'setpagelanguage' => 'ApiSetPageLanguage',
        ];
 
        /**
index 46ba34b..67983e7 100644 (file)
@@ -426,6 +426,15 @@ class ApiParamInfo extends ApiBase {
                                        ( is_array( $item['type'] ) || $item['type'] === 'namespace' ) ) {
                                        $item['allspecifier'] = $allSpecifier;
                                }
+
+                               if ( $item['type'] === 'namespace' &&
+                                       isset( $settings[ApiBase::PARAM_EXTRA_NAMESPACES] ) &&
+                                       is_array( $settings[ApiBase::PARAM_EXTRA_NAMESPACES] )
+                               ) {
+                                       $item['extranamespaces'] = $settings[ApiBase::PARAM_EXTRA_NAMESPACES];
+                                       ApiResult::setArrayType( $item['extranamespaces'], 'array' );
+                                       ApiResult::setIndexedTagName( $item['extranamespaces'], 'ns' );
+                               }
                        }
                        if ( isset( $settings[ApiBase::PARAM_MAX] ) ) {
                                $item['max'] = $settings[ApiBase::PARAM_MAX];
index c3636c6..3b24e37 100644 (file)
@@ -263,7 +263,8 @@ class ApiQueryAllLinks extends ApiQueryGeneratorBase {
                        ],
                        'namespace' => [
                                ApiBase::PARAM_DFLT => $this->dfltNamespace,
-                               ApiBase::PARAM_TYPE => 'namespace'
+                               ApiBase::PARAM_TYPE => 'namespace',
+                               ApiBase::PARAM_EXTRA_NAMESPACES => [ NS_MEDIA, NS_SPECIAL ],
                        ],
                        'limit' => [
                                ApiBase::PARAM_DFLT => 10,
index 4c32320..613589e 100644 (file)
@@ -344,7 +344,7 @@ class ApiQueryBacklinks extends ApiQueryGeneratorBase {
                        $this->validateLimit( 'limit', $this->params['limit'], 1, $userMax, $botMax );
                }
 
-               $this->rootTitle = $this->getTitleOrPageId( $this->params )->getTitle();
+               $this->rootTitle = $this->getTitleFromTitleOrPageId( $this->params );
 
                // only image titles are allowed for the root in imageinfo mode
                if ( !$this->hasNS && $this->rootTitle->getNamespace() !== NS_FILE ) {
index ef7b9af..4ed7f52 100644 (file)
@@ -104,6 +104,13 @@ class ApiQueryBacklinksprop extends ApiQueryGeneratorBase {
                $titles = $pageSet->getGoodAndMissingTitles();
                $map = $pageSet->getGoodAndMissingTitlesByNamespace();
 
+               // Add in special pages, they can theoretically have backlinks too.
+               // (although currently they only do for prop=redirects)
+               foreach ( $pageSet->getSpecialTitles() as $id => $title ) {
+                       $titles[] = $title;
+                       $map[$title->getNamespace()][$title->getDBkey()] = $id;
+               }
+
                // Determine our fields to query on
                $p = $settings['prefix'];
                $hasNS = !isset( $settings['to_namespace'] );
@@ -220,8 +227,9 @@ class ApiQueryBacklinksprop extends ApiQueryGeneratorBase {
                $this->addFieldsIf( 'page_namespace', $miser_ns !== null );
 
                if ( $hasNS ) {
-                       $lb = new LinkBatch( $titles );
-                       $this->addWhere( $lb->constructSet( $p, $db ) );
+                       // Can't use LinkBatch because it throws away Special titles.
+                       // And we already have the needed data structure anyway.
+                       $this->addWhere( $db->makeWhereFrom2d( $map, $bl_namespace, $bl_title ) );
                } else {
                        $where = [];
                        foreach ( $titles as $t ) {
index e9ae132..4556e29 100644 (file)
@@ -182,7 +182,8 @@ class ApiQueryLinks extends ApiQueryGeneratorBase {
                return [
                        'namespace' => [
                                ApiBase::PARAM_TYPE => 'namespace',
-                               ApiBase::PARAM_ISMULTI => true
+                               ApiBase::PARAM_ISMULTI => true,
+                               ApiBase::PARAM_EXTRA_NAMESPACES => [ NS_MEDIA, NS_SPECIAL ],
                        ],
                        'limit' => [
                                ApiBase::PARAM_DFLT => 10,
index 2dcd0b4..4d84aad 100644 (file)
@@ -435,7 +435,8 @@ class ApiQueryLogEvents extends ApiQueryBase {
                        ],
                        'title' => null,
                        'namespace' => [
-                               ApiBase::PARAM_TYPE => 'namespace'
+                               ApiBase::PARAM_TYPE => 'namespace',
+                               ApiBase::PARAM_EXTRA_NAMESPACES => [ NS_MEDIA, NS_SPECIAL ],
                        ],
                        'prefix' => [],
                        'tag' => null,
index 8d14927..2c76e97 100644 (file)
@@ -617,7 +617,8 @@ class ApiQueryRecentChanges extends ApiQueryGeneratorBase {
                        ],
                        'namespace' => [
                                ApiBase::PARAM_ISMULTI => true,
-                               ApiBase::PARAM_TYPE => 'namespace'
+                               ApiBase::PARAM_TYPE => 'namespace',
+                               ApiBase::PARAM_EXTRA_NAMESPACES => [ NS_MEDIA, NS_SPECIAL ],
                        ],
                        'user' => [
                                ApiBase::PARAM_TYPE => 'user'
index 6fc6aa3..5093608 100644 (file)
@@ -23,6 +23,7 @@
  *
  * @file
  */
+use MediaWiki\MediaWikiServices;
 
 /**
  * A query action to return meta information about the wiki site.
@@ -388,7 +389,7 @@ class ApiQuerySiteinfo extends ApiQueryBase {
                $langCode = isset( $params['inlanguagecode'] ) ? $params['inlanguagecode'] : '';
                $langNames = Language::fetchLanguageNames( $langCode );
 
-               $getPrefixes = Interwiki::getAllPrefixes( $local );
+               $getPrefixes = MediaWikiServices::getInstance()->getInterwikiLookup()->getAllPrefixes( $local );
                $extraLangPrefixes = $this->getConfig()->get( 'ExtraInterlanguageLinkPrefixes' );
                $localInterwikis = $this->getConfig()->get( 'LocalInterwikis' );
                $data = [];
index b6d871b..31a9238 100644 (file)
@@ -65,18 +65,36 @@ class ApiQueryContributions extends ApiQueryBase {
                // TODO: if the query is going only against the revision table, should this be done?
                $this->selectNamedDB( 'contributions', DB_REPLICA, 'contributions' );
 
+               $this->requireOnlyOneParameter( $this->params, 'userprefix', 'userids', 'user' );
+
                $this->idMode = false;
                if ( isset( $this->params['userprefix'] ) ) {
                        $this->prefixMode = true;
                        $this->multiUserMode = true;
                        $this->userprefix = $this->params['userprefix'];
+               } elseif ( isset( $this->params['userids'] ) ) {
+                       $this->userids = [];
+
+                       if ( !count( $this->params['userids'] ) ) {
+                               $encParamName = $this->encodeParamName( 'userids' );
+                               $this->dieWithError( [ 'apierror-paramempty', $encParamName ], "paramempty_$encParamName" );
+                       }
+
+                       foreach ( $this->params['userids'] as $uid ) {
+                               if ( $uid <= 0 ) {
+                                       $this->dieWithError( [ 'apierror-invaliduserid', $uid ], 'invaliduserid' );
+                               }
+
+                               $this->userids[] = $uid;
+                       }
+
+                       $this->prefixMode = false;
+                       $this->multiUserMode = ( count( $this->params['userids'] ) > 1 );
+                       $this->idMode = true;
                } else {
                        $anyIPs = false;
                        $this->userids = [];
                        $this->usernames = [];
-                       if ( !is_array( $this->params['user'] ) ) {
-                               $this->params['user'] = [ $this->params['user'] ];
-                       }
                        if ( !count( $this->params['user'] ) ) {
                                $encParamName = $this->encodeParamName( 'user' );
                                $this->dieWithError(
@@ -84,7 +102,7 @@ class ApiQueryContributions extends ApiQueryBase {
                                );
                        }
                        foreach ( $this->params['user'] as $u ) {
-                               if ( is_null( $u ) || $u === '' ) {
+                               if ( $u === '' ) {
                                        $encParamName = $this->encodeParamName( 'user' );
                                        $this->dieWithError(
                                                [ 'apierror-paramempty', $encParamName ], "paramempty_$encParamName"
@@ -495,6 +513,10 @@ class ApiQueryContributions extends ApiQueryBase {
                                ApiBase::PARAM_TYPE => 'user',
                                ApiBase::PARAM_ISMULTI => true
                        ],
+                       'userids' => [
+                               ApiBase::PARAM_TYPE => 'integer',
+                               ApiBase::PARAM_ISMULTI => true
+                       ],
                        'userprefix' => null,
                        'dir' => [
                                ApiBase::PARAM_DFLT => 'older',
index 763aef5..4896e7e 100644 (file)
@@ -46,6 +46,14 @@ class ApiRevisionDelete extends ApiBase {
                        $this->dieWithError( [ 'apierror-paramempty', 'ids' ], 'paramempty_ids' );
                }
 
+               // Check if user can add tags
+               if ( count( $params['tags'] ) ) {
+                       $ableToTag = ChangeTags::canAddTagsAccompanyingChange( $params['tags'], $user );
+                       if ( !$ableToTag->isOK() ) {
+                               $this->dieStatus( $ableToTag );
+                       }
+               }
+
                $hide = $params['hide'] ?: [];
                $show = $params['show'] ?: [];
                if ( array_intersect( $hide, $show ) ) {
@@ -90,9 +98,12 @@ class ApiRevisionDelete extends ApiBase {
                $list = RevisionDeleter::createList(
                        $params['type'], $this->getContext(), $targetObj, $params['ids']
                );
-               $status = $list->setVisibility(
-                       [ 'value' => $bitfield, 'comment' => $params['reason'], 'perItemStatus' => true ]
-               );
+               $status = $list->setVisibility( [
+                       'value' => $bitfield,
+                       'comment' => $params['reason'],
+                       'perItemStatus' => true,
+                       'tags' => $params['tags']
+               ] );
 
                $result = $this->getResult();
                $data = $this->extractStatusInfo( $status );
@@ -165,6 +176,10 @@ class ApiRevisionDelete extends ApiBase {
                                ApiBase::PARAM_DFLT => 'nochange',
                        ],
                        'reason' => null,
+                       'tags' => [
+                               ApiBase::PARAM_TYPE => 'tags',
+                               ApiBase::PARAM_ISMULTI => true,
+                       ],
                ];
        }
 
diff --git a/includes/api/ApiSetPageLanguage.php b/includes/api/ApiSetPageLanguage.php
new file mode 100755 (executable)
index 0000000..3ff99f1
--- /dev/null
@@ -0,0 +1,149 @@
+<?php
+/**
+ *
+ *
+ * Created on January 1, 2017
+ *
+ * Copyright © 2017 Justin Du "<justin.d128@gmail.com>"
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ *
+ * @file
+ */
+
+/**
+ * API module that facilitates changing the language of a page.
+ * The API equivalent of SpecialPageLanguage.
+ * Requires API write mode to be enabled.
+ *
+ * @ingroup API
+ */
+class ApiSetPageLanguage extends ApiBase {
+       // Check if change language feature is enabled
+       protected function getDescriptionMessage() {
+               if ( !$this->getConfig()->get( 'PageLanguageUseDB' ) ) {
+                       return 'apihelp-setpagelanguage-description-disabled';
+               }
+               return parent::getDescriptionMessage();
+       }
+
+       /**
+        * Extracts the title and language from the request parameters and invokes
+        * the static SpecialPageLanguage::changePageLanguage() function with these as arguments.
+        * If the language change succeeds, the title, old language, and new language
+        * of the article changed, as well as the performer of the language change
+        * are added to the result object.
+        */
+       public function execute() {
+               // Check if change language feature is enabled
+               if ( !$this->getConfig()->get( 'PageLanguageUseDB' ) ) {
+                       $this->dieWithError( 'apierror-pagelang-disabled' );
+               }
+
+               // Check if the user has permissions
+               $this->checkUserRightsAny( 'pagelang' );
+
+               $this->useTransactionalTimeLimit();
+
+               $params = $this->extractRequestParams();
+
+               $pageObj = $this->getTitleOrPageId( $params, 'fromdbmaster' );
+               if ( !$pageObj->exists() ) {
+                       $this->dieWithError( 'apierror-missingtitle' );
+               }
+
+               $titleObj = $pageObj->getTitle();
+               $user = $this->getUser();
+
+               // Check that the user is allowed to edit the page
+               $this->checkTitleUserPermissions( $titleObj, 'edit' );
+
+               // If change tagging was requested, check that the user is allowed to tag,
+               // and the tags are valid
+               if ( count( $params['tags'] ) ) {
+                       $tagStatus = ChangeTags::canAddTagsAccompanyingChange( $params['tags'], $user );
+                       if ( !$tagStatus->isOK() ) {
+                               $this->dieStatus( $tagStatus );
+                       }
+               }
+
+               $status = SpecialPageLanguage::changePageLanguage(
+                       $this,
+                       $titleObj,
+                       $params['lang'],
+                       $params['reason'] === null ? '' : $params['reason'],
+                       $params['tags'] ?: []
+               );
+
+               if ( !$status->isOK() ) {
+                       $this->dieStatus( $status );
+               }
+
+               $r = [
+                       'title' => $titleObj->getPrefixedText(),
+                       'oldlanguage' => $status->value->oldLanguage,
+                       'newlanguage' => $status->value->newLanguage,
+                       'logid' => $status->value->logId
+               ];
+               $this->getResult()->addValue( null, $this->getModuleName(), $r );
+       }
+
+       public function mustBePosted() {
+               return true;
+       }
+
+       public function isWriteMode() {
+               return true;
+       }
+
+       public function getAllowedParams() {
+               return [
+                       'title' => null,
+                       'pageid' => [
+                               ApiBase::PARAM_TYPE => 'integer'
+                       ],
+                       'lang' => [
+                               ApiBase::PARAM_TYPE => array_merge(
+                                       [ 'default' ],
+                                       array_keys( Language::fetchLanguageNames( null, 'mwfile' ) )
+                               ),
+                               ApiBase::PARAM_REQUIRED => true,
+                       ],
+                       'reason' => null,
+                       'tags' => [
+                               ApiBase::PARAM_TYPE => 'tags',
+                               ApiBase::PARAM_ISMULTI => true,
+                       ],
+               ];
+       }
+
+       public function needsToken() {
+               return 'csrf';
+       }
+
+       protected function getExamplesMessages() {
+               return [
+                       'action=setpagelanguage&title=Main%20Page&lang=eu&token=123ABC'
+                               => 'apihelp-setpagelanguage-example-language',
+                       'action=setpagelanguage&pageid=123&lang=default&token=123ABC'
+                               => 'apihelp-setpagelanguage-example-default',
+               ];
+       }
+
+       public function getHelpUrls() {
+               return 'https://www.mediawiki.org/wiki/API:SetPageLanguage';
+       }
+}
index b142900..7470ff3 100644 (file)
@@ -36,6 +36,14 @@ class ApiTag extends ApiBase {
                        $this->dieBlocked( $user->getBlock() );
                }
 
+               // Check if user can add tags
+               if ( count( $params['tags'] ) ) {
+                       $ableToTag = ChangeTags::canAddTagsAccompanyingChange( $params['tags'], $user );
+                       if ( !$ableToTag->isOk() ) {
+                               $this->dieStatus( $ableToTag );
+                       }
+               }
+
                // validate and process each revid, rcid and logid
                $this->requireAtLeastOneParameter( $params, 'revid', 'rcid', 'logid' );
                $ret = [];
@@ -116,6 +124,10 @@ class ApiTag extends ApiBase {
                                ApiResult::setIndexedTagName( $idResult['added'], 't' );
                                $idResult['removed'] = $status->value->removedTags;
                                ApiResult::setIndexedTagName( $idResult['removed'], 't' );
+
+                               if ( $params['tags'] ) {
+                                       ChangeTags::addTags( $params['tags'], null, null, $status->value->logId );
+                               }
                        }
                }
                return $idResult;
@@ -154,6 +166,10 @@ class ApiTag extends ApiBase {
                        'reason' => [
                                ApiBase::PARAM_DFLT => '',
                        ],
+                       'tags' => [
+                               ApiBase::PARAM_TYPE => 'tags',
+                               ApiBase::PARAM_ISMULTI => true,
+                       ],
                ];
        }
 
index d26d1d4..fe93ebe 100644 (file)
@@ -22,5 +22,7 @@
        "apihelp-edit-example-edit": "একটি পাতা সম্পাদনা করুন",
        "apihelp-edit-example-prepend": "একটি পৃষ্ঠার পূর্বে <kbd>_&#95;NOTOC_&#95;</kbd> লিখুন।",
        "apihelp-login-example-login": "প্রবেশ",
+       "apihelp-setpagelanguage-param-reason": "পরিবর্তনের কারণ।",
+       "apierror-invaliduserid": "ব্যবহারকারী আইডি <var>$1</var> বৈধ নয়।",
        "apierror-nosuchuserid": "$1 আইডি যুক্ত কোন ব্যবহারকারী নেই।"
 }
index 72933fe..a8f4dd8 100644 (file)
@@ -30,5 +30,6 @@
        "apihelp-login-example-login": "Kevreañ.",
        "apihelp-move-description": "Dilec'hiañ ur bajenn.",
        "apihelp-move-param-noredirect": "Chom hep krouiñ un adkas.",
-       "apihelp-protect-example-protect": "Gwareziñ ur bajenn."
+       "apihelp-protect-example-protect": "Gwareziñ ur bajenn.",
+       "apihelp-rollback-param-tags": "Tikedennoù da lakaat e talvoud war an distroioù."
 }
index c019d98..3e570e5 100644 (file)
        "apihelp-help-example-query": "Hilfe für zwei Abfrage-Submodule",
        "apihelp-imagerotate-description": "Ein oder mehrere Bilder drehen.",
        "apihelp-imagerotate-param-rotation": "Anzahl der Grad, um die das Bild im Uhrzeigersinn gedreht werden soll.",
+       "apihelp-imagerotate-param-tags": "Auf den Eintrag im Datei-Logbuch anzuwendende Markierungen",
        "apihelp-imagerotate-example-simple": "<kbd>Datei:Beispiel.png</kbd> um <kbd>90</kbd> Grad drehen.",
        "apihelp-imagerotate-example-generator": "Alle Bilder in der <kbd>Kategorie:Flip</kbd> um <kbd>180</kbd> Grad drehen.",
        "apihelp-import-description": "Importiert eine Seite aus einem anderen Wiki oder von einer XML-Datei.\n\nBitte beachte, dass der HTTP-POST-Vorgang als Dateiupload ausgeführt werden muss (z.B. durch multipart/form-data), um eine Datei über den <var>xml</var>-Parameter zu senden.",
        "apihelp-query+usercontribs-param-limit": "Die maximale Anzahl der zurückzugebenden Beiträge.",
        "apihelp-query+usercontribs-param-start": "Der zurückzugebende Start-Zeitstempel.",
        "apihelp-query+usercontribs-param-end": "Der zurückzugebende End-Zeitstempel.",
-       "apihelp-query+usercontribs-param-user": "Die Benutzer, für die Beiträge abgerufen werden sollen.",
+       "apihelp-query+usercontribs-param-user": "Die Benutzer, für die Beiträge abgerufen werden sollen. Kann nicht zusammen mit <var>$1userids</var> oder <var>$1userprefix</var> verwendet werden.",
+       "apihelp-query+usercontribs-param-userprefix": "Ruft Beiträge für alle Benutzer ab, deren Namen mit diesem Wert beginnt. Kann nicht zusammen mit <var>$1user</var> oder <var>$1userids</var> verwendet werden.",
+       "apihelp-query+usercontribs-param-userids": "Die Benutzerkennungen, für die die Beiträge abgerufen werden sollen. Kann nicht zusammen mit <var>$1user</var> oder <var>$1userprefix</var> verwendet werden.",
        "apihelp-query+usercontribs-paramvalue-prop-ids": "Fügt die Seiten- und Versionskennung hinzu.",
        "apihelp-query+usercontribs-paramvalue-prop-timestamp": "Ergänzt den Zeitstempel der Bearbeitung.",
        "apihelp-query+usercontribs-paramvalue-prop-comment": "Fügt den Kommentar der Bearbeitung hinzu.",
        "apihelp-revisiondelete-description": "Löscht und stellt Versionen wieder her.",
        "apihelp-revisiondelete-param-hide": "Was für jede Version versteckt werden soll.",
        "apihelp-revisiondelete-param-show": "Was für jede Version wieder eingeblendet werden soll.",
+       "apihelp-revisiondelete-param-tags": "Auf den Eintrag im Lösch-Logbuch anzuwendende Markierungen.",
        "apihelp-rsd-description": "Ein RSD-Schema (Really Simple Discovery) exportieren.",
        "apihelp-rsd-example-simple": "Das RSD-Schema exportieren",
        "apihelp-setnotificationtimestamp-param-entirewatchlist": "An allen beobachteten Seiten arbeiten.",
+       "apihelp-setpagelanguage-description": "Ändert die Sprache einer Seite.",
+       "apihelp-setpagelanguage-description-disabled": "Das Ändern der Sprache von Seiten ist auf diesem Wiki nicht erlaubt.\n\nAktiviere <var>[[mw:Manual:$wgPageLanguageUseDB|$wgPageLanguageUseDB]]</var>, um diese Aktion zu verwenden.",
+       "apihelp-setpagelanguage-param-title": "Titel der Seite, deren Sprache du ändern möchtest. Kann nicht zusammen mit <var>$1pageid</var> verwendet werden.",
+       "apihelp-setpagelanguage-param-pageid": "Kennung der Seite, deren Sprache du ändern möchtest. Kann nicht zusammen mit <var>$1title</var> verwendet werden.",
+       "apihelp-setpagelanguage-param-lang": "Code der Sprache, auf den die Seite geändert werden soll. Verwende <kbd>default</kbd>, um die Seite auf die Standardinhaltssprache des Wikis zurückzusetzen.",
+       "apihelp-setpagelanguage-param-reason": "Grund für die Änderung.",
+       "apihelp-setpagelanguage-param-tags": "Auf den Logbucheintrag anzuwendende Änderungsmarkierungen, die sich aus dieser Aktion ergeben.",
+       "apihelp-setpagelanguage-example-language": "Ändert die Sprache von <kbd>Hauptseite</kbd> auf Baskisch.",
+       "apihelp-setpagelanguage-example-default": "Ändert die Sprache der Seite mit der Kennung 123 auf die Standardinhaltssprache des Wikis.",
        "apihelp-stashedit-param-sectiontitle": "Der Titel für einen neuen Abschnitt.",
        "apihelp-stashedit-param-text": "Seiteninhalt.",
        "apihelp-stashedit-param-stashedtexthash": "Stattdessen zu verwendende Prüfsumme des Seiteninhalts von einem vorherigen Speicher.",
        "apihelp-stashedit-param-contentmodel": "Inhaltsmodell des neuen Inhalts.",
        "apihelp-stashedit-param-summary": "Änderungszusammenfassung.",
        "apihelp-tag-param-reason": "Grund für die Änderung.",
+       "apihelp-tag-param-tags": "Auf den Logbucheintrag anzuwendende Markierungen, die als Ergebnis dieser Aktion erstellt wurden.",
        "apihelp-tokens-param-type": "Abzufragende Tokentypen.",
        "apihelp-tokens-example-edit": "Ruft einen Bearbeitungstoken ab (Standard).",
        "apihelp-tokens-example-emailmove": "Ruft einen E-Mail- und Verschiebungstoken ab.",
        "api-help-right-apihighlimits": "Höhere Beschränkungen in API-Anfragen verwenden (langsame Anfragen: $1; schnelle Anfragen: $2). Die Beschränkungen für langsame Anfragen werden auch auf Mehrwertparameter angewandt.",
        "api-help-open-in-apisandbox": "<small>[in Spielwiese öffnen]</small>",
        "api-help-authmanagerhelper-messageformat": "Zu verwendendes Format zur Rückgabe von Nachrichten.",
+       "apierror-invaliduserid": "Die Benutzerkennung <var>$1</var> ist nicht gültig.",
        "apierror-nosuchuserid": "Es gibt keinen Benutzer mit der Kennung $1.",
+       "apierror-pagelang-disabled": "Das Ändern der Sprache von Seiten ist auf diesem Wiki nicht erlaubt.",
        "apierror-stashinvalidfile": "Ungültige gespeicherte Datei.",
+       "apierror-stashnosuchfilekey": "Kein derartiger Dateischlüssel: $1.",
+       "apierror-stashwrongowner": "Falscher Besitzer: $1",
        "apierror-systemblocked": "Du wurdest von MediaWiki automatisch gesperrt.",
+       "apierror-unknownerror-nocode": "Unbekannter Fehler.",
+       "apierror-unknownerror": "Unbekannter Fehler: „$1“.",
+       "apiwarn-invalidcategory": "„$1“ ist keine Kategorie.",
+       "apiwarn-invalidtitle": "„$1“ ist kein gültiger Titel.",
+       "apiwarn-notfile": "„$1“ ist keine Datei.",
+       "api-feed-error-title": "Fehler ($1)",
+       "api-usage-docref": "Siehe $1 zur Verwendung der API.",
        "api-credits-header": "Danksagungen",
        "api-credits": "API-Entwickler:\n* Roan Kattouw (Hauptentwickler von September 2007 bis 2009)\n* Victor Vasiliev\n* Bryan Tong Minh\n* Sam Reed\n* Yuri Astrakhan (Autor, Hauptentwickler von September 2006 bis September 2007)\n* Brad Jorsch (Hauptentwickler seit 2013)\n\nBitte sende deine Kommentare, Vorschläge und Fragen an mediawiki-api@lists.wikimedia.org\noder reiche einen Fehlerbericht auf https://phabricator.wikimedia.org/ ein."
 }
index bc9fbf6..8ac11d0 100644 (file)
 
        "apihelp-imagerotate-description": "Rotate one or more images.",
        "apihelp-imagerotate-param-rotation": "Degrees to rotate image clockwise.",
+       "apihelp-imagerotate-param-tags": "Tags to apply to the entry in the upload log.",
        "apihelp-imagerotate-example-simple": "Rotate <kbd>File:Example.png</kbd> by <kbd>90</kbd> degrees.",
        "apihelp-imagerotate-example-generator": "Rotate all images in <kbd>Category:Flip</kbd> by <kbd>180</kbd> degrees.",
 
        "apihelp-query+usercontribs-param-limit": "The maximum number of contributions to return.",
        "apihelp-query+usercontribs-param-start": "The start timestamp to return from.",
        "apihelp-query+usercontribs-param-end": "The end timestamp to return to.",
-       "apihelp-query+usercontribs-param-user": "The users to retrieve contributions for.",
-       "apihelp-query+usercontribs-param-userprefix": "Retrieve contributions for all users whose names begin with this value. Overrides $1user.",
+       "apihelp-query+usercontribs-param-user": "The users to retrieve contributions for. Cannot be used with <var>$1userids</var> or <var>$1userprefix</var>.",
+       "apihelp-query+usercontribs-param-userprefix": "Retrieve contributions for all users whose names begin with this value. Cannot be used with <var>$1user</var> or <var>$1userids</var>.",
+       "apihelp-query+usercontribs-param-userids": "The user IDs to retrieve contributions for. Cannot be used with <var>$1user</var> or <var>$1userprefix</var>.",
        "apihelp-query+usercontribs-param-namespace": "Only list contributions in these namespaces.",
        "apihelp-query+usercontribs-param-prop": "Include additional pieces of information:",
        "apihelp-query+usercontribs-paramvalue-prop-ids": "Adds the page ID and revision ID.",
        "apihelp-revisiondelete-param-show": "What to unhide for each revision.",
        "apihelp-revisiondelete-param-suppress": "Whether to suppress data from administrators as well as others.",
        "apihelp-revisiondelete-param-reason": "Reason for the deletion or undeletion.",
+       "apihelp-revisiondelete-param-tags": "Tags to apply to the entry in the deletion log.",
        "apihelp-revisiondelete-example-revision": "Hide content for revision <kbd>12345</kbd> on the page <kbd>Main Page</kbd>.",
        "apihelp-revisiondelete-example-log": "Hide all data on log entry <kbd>67890</kbd> with the reason <kbd>BLP violation</kbd>.",
 
        "apihelp-setnotificationtimestamp-example-pagetimestamp": "Set the notification timestamp for <kbd>Main page</kbd> so all edits since 1 January 2012 are unviewed.",
        "apihelp-setnotificationtimestamp-example-allpages": "Reset the notification status for pages in the <kbd>{{ns:user}}</kbd> namespace.",
 
+       "apihelp-setpagelanguage-description": "Change the language of a page.",
+       "apihelp-setpagelanguage-description-disabled": "Changing the language of a page is not allowed on this wiki.\n\nEnable <var>[[mw:Manual:$wgPageLanguageUseDB|$wgPageLanguageUseDB]]</var> to use this action.",
+       "apihelp-setpagelanguage-param-title": "Title of the page whose language you wish to change. Cannot be used together with <var>$1pageid</var>.",
+       "apihelp-setpagelanguage-param-pageid": "Page ID of the page whose language you wish to change. Cannot be used together with <var>$1title</var>.",
+       "apihelp-setpagelanguage-param-lang": "Language code of the language to change the page to. Use <kbd>default</kbd> to reset the page to the wiki's default content language.",
+       "apihelp-setpagelanguage-param-reason": "Reason for the change.",
+       "apihelp-setpagelanguage-param-tags": "Change tags to apply to the log entry resulting from this action.",
+       "apihelp-setpagelanguage-example-language": "Change the language of <kbd>Main Page</kbd> to Basque.",
+       "apihelp-setpagelanguage-example-default": "Change the language of the page with ID 123 to the wiki's default content language.",
+
        "apihelp-stashedit-description": "Prepare an edit in shared cache.\n\nThis is intended to be used via AJAX from the edit form to improve the performance of the page save.",
        "apihelp-stashedit-param-title": "Title of the page being edited.",
        "apihelp-stashedit-param-section": "Section number. <kbd>0</kbd> for the top section, <kbd>new</kbd> for a new section.",
        "apihelp-tag-param-add": "Tags to add. Only manually defined tags can be added.",
        "apihelp-tag-param-remove": "Tags to remove. Only tags that are either manually defined or completely undefined can be removed.",
        "apihelp-tag-param-reason": "Reason for the change.",
+       "apihelp-tag-param-tags": "Tags to apply to the log entry that will be created as a result of this action.",
        "apihelp-tag-example-rev": "Add the <kbd>vandalism</kbd> tag to revision ID 123 without specifying a reason",
        "apihelp-tag-example-log": "Remove the <kbd>spam</kbd> tag from log entry ID 123 with the reason <kbd>Wrongly applied</kbd>",
 
        "apierror-invalidtitle": "Bad title \"$1\".",
        "apierror-invalidurlparam": "Invalid value for <var>$1urlparam</var> (<kbd>$2=$3</kbd>).",
        "apierror-invaliduser": "Invalid username \"$1\".",
+       "apierror-invaliduserid": "User ID <var>$1</var> is not valid.",
        "apierror-maxlag-generic": "Waiting for a database server: $1 {{PLURAL:$1|second|seconds}} lagged.",
        "apierror-maxlag": "Waiting for $2: $1 {{PLURAL:$1|second|seconds}} lagged.",
        "apierror-mimesearchdisabled": "MIME search is disabled in Miser Mode.",
        "apierror-opensearch-json-warnings": "Warnings cannot be represented in OpenSearch JSON format.",
        "apierror-pagecannotexist": "Namespace doesn't allow actual pages.",
        "apierror-pagedeleted": "The page has been deleted since you fetched its timestamp.",
+       "apierror-pagelang-disabled": "Changing the language of a page is not allowed on this wiki.",
        "apierror-paramempty": "The parameter <var>$1</var> may not be empty.",
        "apierror-parsetree-notwikitext": "<kbd>prop=parsetree</kbd> is only supported for wikitext content.",
        "apierror-parsetree-notwikitext-title": "<kbd>prop=parsetree</kbd> is only supported for wikitext content. $1 uses content model $2.",
index 916f8b7..f39e770 100644 (file)
@@ -45,6 +45,8 @@
        "apihelp-main-param-origin": "Cuando se accede a la API usando una petición AJAX de distinto dominio (CORS), se establece este valor al dominio de origen. Debe ser incluido en cualquier petición pre-vuelo, y por lo tanto debe ser parte de la URI de la petición (no del cuerpo POST).\n\nEn las peticiones con autenticación, debe coincidir exactamente con uno de los orígenes de la cabecera <code>Origin</code>, por lo que debería ser algo como <kbd>https://en.wikipedia.org</kbd> o <kbd>https://meta.wikimedia.org</kbd>. Si este parámetro no coincide con la cabecera <code>Origin</code>, se devolverá una respuesta 403. Si este parámetro coincide con la cabecera <code>Origin</code> y el origen está en la lista blanca, se creará una cabecera <code>Access-Control-Allow-Origin</code>.\n\nEn las peticiones sin autenticación, introduce el valor <kbd>*</kbd>. Esto creará una cabecera <code>Access-Control-Allow-Origin</code>, pero el valor de <code>Access-Control-Allow-Credentials</code> será <code>false</code> y todos los datos que dependan del usuario estarán restringidos.",
        "apihelp-main-param-uselang": "El idioma que se utilizará para las traducciones de mensajes. <kbd>[[Special:ApiHelp/query+siteinfo|action=query&meta=siteinfo]]</kbd> con <kbd>siprop=languages</kbd> devuelve una lista de códigos de idiomas. También puedes introducir <kbd>user</kbd> para usar la preferencia de idioma del usuario actual, o <kbd>content</kbd> para usar el idioma de contenido de este wiki.",
        "apihelp-main-param-errorformat": "Formato utilizado para la salida de texto de avisos y errores.\n; plaintext: Wikitexto en el que se han eliminado las etiquetas HTML y reemplazado las entidades.\n; wikitext: Wikitexto sin analizar.\n; html: HTML.\n; raw: Clave del mensaje y parámetros.\n; none: Ninguna salida de texto, solo códigos de error.\n; bc: Formato empleado en versiones de MediaWiki anteriores a la 1.29. No se tienen en cuenta <var>errorlang</var> y <var>errorsuselocal</var>.",
+       "apihelp-main-param-errorlang": "Idioma empleado para advertencias y errores. <kbd>[[Special:ApiHelp/query+siteinfo|action=query&meta=siteinfo]]</kbd> con <kbd>siprop=languages</kbd> devuelve una lista de códigos de idioma. Puedes especificar <kbd>content</kbd> para utilizar el idioma del contenido de este wiki o <kbd>uselang</kbd> para utilizar el valor del parámetro <var>uselang</var>.",
+       "apihelp-main-param-errorsuselocal": "Si se da, los textos de error emplearán mensajes localmente personalizados del espacio de nombres {{ns:MediaWiki}}.",
        "apihelp-block-description": "Bloquear a un usuario.",
        "apihelp-block-param-user": "Nombre de usuario, dirección IP o intervalo de IP que quieres bloquear. No se puede utilizar junto con <var>$1userid</var>",
        "apihelp-block-param-userid": "ID de usuario para bloquear. No se puede utilizar junto con <var>$1user</var>.",
        "apihelp-query-param-meta": "Qué metadatos obtener.",
        "apihelp-query-param-indexpageids": "Incluir una sección de ID de páginas adicional en la que se muestran todas las ID de páginas.",
        "apihelp-query-param-export": "Exportar las revisiones actuales de las páginas dadas o generadas.",
+       "apihelp-query-param-exportnowrap": "Devuelve el XML de exportación sin envolverlo en un resultado XML (mismo formato que [[Special:Export]]). Solo se puede usar junto con $1export.",
        "apihelp-query-param-iwurl": "Si la URL completa si el título es un interwiki.",
+       "apihelp-query-param-rawcontinue": "Devuelve los datos <samp>query-continue</samp> en bruto para continuar.",
        "apihelp-query-example-allpages": "Obtener revisiones de páginas que comiencen por <kbd>API/</kbd>.",
        "apihelp-query+allcategories-description": "Enumerar todas las categorías.",
        "apihelp-query+allcategories-param-from": "La categoría para comenzar la enumeración",
        "apihelp-query+allcategories-paramvalue-prop-size": "Añade el número de páginas en la categoría.",
        "apihelp-query+allcategories-paramvalue-prop-hidden": "Etiqueta las categorías que están ocultas con <code>_&#95;HIDDENCAT_&#95;</code>.",
        "apihelp-query+allcategories-example-size": "Lista las categorías con información sobre el número de páginas de cada una.",
+       "apihelp-query+allcategories-example-generator": "Recupera la información sobre la propia página de categoría para las categorías que empiezan por <kbd>List</kbd>.",
        "apihelp-query+alldeletedrevisions-description": "Listar todas las revisiones eliminadas por un usuario o en un espacio de nombres.",
        "apihelp-query+alldeletedrevisions-paraminfo-useronly": "Solo puede usarse con <var>$3user</var>.",
        "apihelp-query+alldeletedrevisions-paraminfo-nonuseronly": "No puede utilizarse con <var>$3user</var>.",
        "apihelp-query+allfileusages-param-from": "El título del archivo para comenzar la enumeración.",
        "apihelp-query+allfileusages-param-to": "El título del archivo para detener la enumeración.",
        "apihelp-query+allfileusages-param-prefix": "Buscar todos los títulos de los archivos que comiencen con este valor.",
+       "apihelp-query+allfileusages-param-unique": "Mostrar solo títulos únicos de archivo. No se puede usar junto con $1prop=ids. Cuando se use como generador, devuelve páginas de destino en vez de páginas de origen.",
        "apihelp-query+allfileusages-param-prop": "Qué piezas de información incluir:",
        "apihelp-query+allfileusages-paramvalue-prop-title": "Agrega el título del archivo.",
        "apihelp-query+allfileusages-param-limit": "Cuántos elementos en total se devolverán.",
        "apihelp-query+allimages-param-maxsize": "Limitar a imágenes con como mucho este número de bytes.",
        "apihelp-query+allimages-param-sha1": "Suma SHA1 de la imagen. Invalida $1sha1base36.",
        "apihelp-query+allimages-param-sha1base36": "Suma SHA1 de la imagen en base 36 (usada en MediaWiki).",
+       "apihelp-query+allimages-param-user": "Devolver solo los archivos subidos por este usuario. Solo se puede usar con $1tipo=timestamp. No se puede usar junto con $1filterbots.",
+       "apihelp-query+allimages-param-filterbots": "Cómo filtrar archivos subidos por bots. Solo se puede usar con $1sort=timestamp. No se puede usar junto con $1user.",
        "apihelp-query+allimages-param-mime": "Tipos MIME que buscar, como, por ejemplo, <kbd>image/jpeg</kbd>.",
        "apihelp-query+allimages-param-limit": "Cuántas imágenes en total se devolverán.",
        "apihelp-query+allimages-example-B": "Mostrar una lista de archivos que empiecen por la letra <kbd>B</kbd>.",
        "apihelp-query+alllinks-param-from": "El título del enlace para comenzar la enumeración.",
        "apihelp-query+alllinks-param-to": "El título del enlace para detener la enumeración.",
        "apihelp-query+alllinks-param-prefix": "Buscar todos los títulos vinculados que comiencen con este valor.",
+       "apihelp-query+alllinks-param-unique": "Mostrar solo títulos únicos enlazados. No se puede usar junto con $1prop=ids. Cuando se use como generador, devuelve páginas de destino en vez de páginas de origen.",
        "apihelp-query+alllinks-param-prop": "Qué piezas de información incluir:",
        "apihelp-query+alllinks-paramvalue-prop-title": "Añade el título del enlace.",
        "apihelp-query+alllinks-param-namespace": "El espacio de nombres que enumerar.",
        "apihelp-query+allpages-param-minsize": "Limitar a páginas con al menos este número de bytes.",
        "apihelp-query+allpages-param-maxsize": "Limitar a páginas con este número máximo de bytes.",
        "apihelp-query+allpages-param-prtype": "Limitar a páginas protegidas.",
+       "apihelp-query+allpages-param-prlevel": "Filtrar protecciones según el nivel de protección (se debe usar junto con el parámetro $1prtype= ).",
+       "apihelp-query+allpages-param-prfiltercascade": "Filtrar protecciones según la protección en cascada (se ignora cuando $1prtype no está fijado).",
        "apihelp-query+allpages-param-limit": "Cuántas páginas en total se devolverán.",
        "apihelp-query+allpages-param-dir": "La dirección en la que se listará.",
        "apihelp-query+allpages-param-filterlanglinks": "Filtrar en función de si una página tiene langlinks. Tenga en cuenta que esto no puede considerar langlinks agregados por extensiones.",
        "apihelp-query+allredirects-param-from": "El título de la redirección para iniciar la enumeración.",
        "apihelp-query+allredirects-param-to": "El título de la redirección para detener la enumeración.",
        "apihelp-query+allredirects-param-prefix": "Buscar todas las páginas de destino que empiecen con este valor.",
+       "apihelp-query+allredirects-param-unique": "Mostrar solo títulos únicos de páginas de destino. No se puede usar junto con $1prop=ids|fragment|interwiki. Cuando se use como generador, devuelve páginas de destino en vez de páginas de origen.",
        "apihelp-query+allredirects-param-prop": "Qué piezas de información incluir:",
        "apihelp-query+allredirects-paramvalue-prop-title": "Añade el título de la redirección.",
        "apihelp-query+allredirects-param-namespace": "El espacio de nombres a enumerar.",
        "apihelp-query+mystashedfiles-paramvalue-prop-size": "Buscar el tamaño del archivo y las dimensiones de la imagen.",
        "apihelp-query+mystashedfiles-paramvalue-prop-type": "Obtener el tipo MIME y tipo multimedia del archivo.",
        "apihelp-query+mystashedfiles-param-limit": "Cuántos archivos obtener.",
+       "apihelp-query+alltransclusions-description": "Mostrar todas las transclusiones (páginas integradas mediante &#123;&#123;x&#125;&#125;), incluidas las inexistentes.",
        "apihelp-query+alltransclusions-param-from": "El título de la transclusión por la que empezar la enumeración.",
        "apihelp-query+alltransclusions-param-to": "El título de la transclusión por la que terminar la enumeración.",
        "apihelp-query+alltransclusions-param-prefix": "Buscar todos los títulos transcluidos que comiencen con este valor.",
+       "apihelp-query+alltransclusions-param-unique": "Mostrar solo títulos únicos transcluidos. No se puede usar junto con $1prop=ids. Cuando se use como generador, devuelve páginas de destino en vez de páginas de origen.",
        "apihelp-query+alltransclusions-param-prop": "Qué piezas de información incluir:",
        "apihelp-query+alltransclusions-paramvalue-prop-title": "Añade el título de la transclusión.",
        "apihelp-query+alltransclusions-param-namespace": "El espacio de nombres que enumerar.",
        "apihelp-query+blocks-paramvalue-prop-reason": "Añade la razón dada para el bloqueo.",
        "apihelp-query+blocks-paramvalue-prop-range": "Añade la gama de direcciones de IP afectó por el bloque.",
        "apihelp-query+blocks-paramvalue-prop-flags": "Etiquetas la prohibición con (autoblock, anononly, etc.).",
+       "apihelp-query+blocks-param-show": "Muestra solamente los elementos que cumplen estos criterios.\nPor ejemplo, para mostrar solamente los bloqueos indefinidos a direcciones IP, introduce <kbd>$1show=ip|!temp</kbd>.",
        "apihelp-query+blocks-example-simple": "Listar bloques.",
        "apihelp-query+categories-description": "Enumera todas las categorías a las que pertenecen las páginas.",
        "apihelp-query+categories-param-prop": "Qué propiedades adicionales obtener para cada categoría:",
        "apihelp-query+deletedrevisions-param-tag": "Listar solo las revisiones con esta etiqueta.",
        "apihelp-query+deletedrevisions-param-user": "Listar solo las revisiones de este usuario.",
        "apihelp-query+deletedrevisions-param-excludeuser": "No listar las revisiones de este usuario.",
+       "apihelp-query+deletedrevisions-example-revids": "Mostrar la información de la revisión borrada <kbd>123456</kbd>.",
        "apihelp-query+deletedrevs-paraminfo-modes": "{{PLURAL:$1|Modo|Modos}}: $2",
        "apihelp-query+deletedrevs-param-start": "Marca de tiempo por la que empezar la enumeración.",
        "apihelp-query+deletedrevs-param-end": "Marca de tiempo por la que terminar la enumeración.",
        "apihelp-query+duplicatefiles-example-generated": "Buscar duplicados en todos los archivos.",
        "apihelp-query+embeddedin-description": "Encuentra todas las páginas que transcluyen el título dado.",
        "apihelp-query+embeddedin-param-title": "Título a buscar. No puede usarse en conjunto con $1pageid.",
+       "apihelp-query+embeddedin-param-pageid": "Identificador de página que buscar. No se puede usar junto con $1title.",
        "apihelp-query+embeddedin-param-namespace": "El espacio de nombres que enumerar.",
        "apihelp-query+embeddedin-param-dir": "La dirección en que ordenar la lista.",
        "apihelp-query+embeddedin-param-filterredir": "Cómo filtrar las redirecciones.",
        "apihelp-query+images-param-limit": "Cuántos archivos se devolverán.",
        "apihelp-query+images-param-dir": "La dirección en que ordenar la lista.",
        "apihelp-query+images-example-simple": "Obtener una lista de los archivos usados en la [[Main Page|Portada]].",
+       "apihelp-query+images-example-generator": "Obtener información sobre todos los archivos empleados en [[Main Page]].",
        "apihelp-query+imageusage-param-title": "Título a buscar. No puede usarse en conjunto con $1pageid.",
        "apihelp-query+imageusage-param-pageid": "ID de página a buscar. No puede usarse con $1title.",
        "apihelp-query+imageusage-param-namespace": "El espacio de nombres que enumerar.",
        "apihelp-query+info-description": "Obtener información básica de la página.",
        "apihelp-query+info-param-prop": "Qué propiedades adicionales se obtendrán:",
        "apihelp-query+info-paramvalue-prop-protection": "Listar el nivel de protección de cada página.",
+       "apihelp-query+info-paramvalue-prop-talkid": "El identificador de la página de discusión correspondiente a cada página que no es de discusión.",
        "apihelp-query+info-paramvalue-prop-subjectid": "La ID de página de la página principal de cada página de discusión.",
        "apihelp-query+info-paramvalue-prop-readable": "Si el usuario puede leer esta página.",
        "apihelp-query+info-paramvalue-prop-displaytitle": "Proporciona la manera en que se muestra realmente el título de la página",
        "apihelp-query+links-param-namespace": "Mostrar solo los enlaces en estos espacios de nombres.",
        "apihelp-query+links-param-limit": "Cuántos enlaces se devolverán.",
        "apihelp-query+links-param-dir": "La dirección en que ordenar la lista.",
+       "apihelp-query+links-example-simple": "Obtener los enlaces de la página <kbd>Main Page</kbd>",
        "apihelp-query+linkshere-param-prop": "Qué propiedades se obtendrán:",
        "apihelp-query+linkshere-paramvalue-prop-pageid": "Identificador de cada página.",
        "apihelp-query+linkshere-paramvalue-prop-title": "Título de cada página.",
        "apihelp-query+logevents-paramvalue-prop-parsedcomment": "Añade el comentario analizado del evento de registro.",
        "apihelp-query+logevents-param-start": "Marca de tiempo por la que empezar la enumeración.",
        "apihelp-query+logevents-param-end": "Marca de tiempo por la que terminar la enumeración.",
+       "apihelp-query+pagepropnames-description": "Mostrar todos los nombres de propiedades de página utilizados en el wiki.",
        "apihelp-query+pageprops-description": "Obtener diferentes propiedades de página definidas en el contenido de la página.",
        "apihelp-query+pageprops-param-prop": "Sólo listar estas propiedades de página (<kbd>[[Special:ApiHelp/query+pagepropnames|action=query&list=pagepropnames]]</kbd> devuelve los nombres de las propiedades de página en uso). Útil para comprobar si las páginas usan una determinada propiedad de página.",
+       "apihelp-query+pageprops-example-simple": "Obtener las propiedades de las páginas <kbd>Main Page</kbd> y <kbd>MediaWiki</kbd>.",
        "apihelp-query+pageswithprop-param-propname": "Propiedad de página para la cual enumerar páginas (<kbd>[[Special:ApiHelp/query+pagepropnames|action=query&list=pagepropnames]]</kbd> devuelve los nombres de las propiedades de página en uso).",
        "apihelp-query+pageswithprop-param-prop": "Qué piezas de información incluir:",
        "apihelp-query+pageswithprop-paramvalue-prop-ids": "Añade el identificador de página.",
        "apihelp-query+prefixsearch-param-limit": "Número máximo de resultados que devolver.",
        "apihelp-query+prefixsearch-param-offset": "Número de resultados que omitir.",
        "apihelp-query+prefixsearch-example-simple": "Buscar títulos de páginas que empiecen con <kbd>meaning</kbd>.",
+       "apihelp-query+prefixsearch-param-profile": "Perfil de búsqueda que utilizar.",
+       "apihelp-query+protectedtitles-description": "Mostrar todos los títulos protegidos contra creación.",
        "apihelp-query+protectedtitles-param-namespace": "Listar solo los títulos en estos espacios de nombres.",
        "apihelp-query+protectedtitles-param-level": "Listar solo títulos con estos niveles de protección.",
        "apihelp-query+protectedtitles-param-limit": "Cuántas páginas se devolverán.",
        "apihelp-query+querypage-param-page": "El nombre de la página especial. Recuerda, es sensible a mayúsculas y minúsculas.",
        "apihelp-query+querypage-param-limit": "Número de resultados que se devolverán.",
        "apihelp-query+querypage-example-ancientpages": "Devolver resultados de [[Special:Ancientpages]].",
+       "apihelp-query+random-param-limit": "Limita el número de páginas aleatorias que se devolverán.",
+       "apihelp-query+random-param-redirect": "Usa <kbd>$1filterredir=redirects</kbd> en su lugar.",
        "apihelp-query+random-param-filterredir": "Cómo filtrar las redirecciones.",
+       "apihelp-query+random-example-simple": "Devuelve dos páginas aleatorias del espacio de nombres principal.",
+       "apihelp-query+random-example-generator": "Devuelve la información de dos páginas aleatorias del espacio de nombres principal.",
        "apihelp-query+recentchanges-description": "Enumerar cambios recientes.",
        "apihelp-query+recentchanges-param-start": "El sello de tiempo para comenzar la enumeración.",
        "apihelp-query+recentchanges-param-end": "El sello de tiempo para finalizar la enumeración.",
+       "apihelp-query+recentchanges-param-namespace": "Filtrar cambios solamente a los espacios de nombres dados.",
        "apihelp-query+recentchanges-param-user": "Listar solo los cambios de este usuario.",
        "apihelp-query+recentchanges-param-excludeuser": "No listar cambios de este usuario.",
        "apihelp-query+recentchanges-param-tag": "Listar solo los cambios con esta etiqueta.",
        "apihelp-query+recentchanges-param-prop": "Incluir piezas adicionales de información:",
+       "apihelp-query+recentchanges-paramvalue-prop-userid": "Añade el identificador del usuario responsable de la edición.",
        "apihelp-query+recentchanges-paramvalue-prop-comment": "Añade el comentario de la edición.",
        "apihelp-query+recentchanges-paramvalue-prop-parsedcomment": "Añade el comentario analizado para la edición.",
        "apihelp-query+recentchanges-paramvalue-prop-flags": "Añade marcas para la edición.",
        "apihelp-query+recentchanges-paramvalue-prop-sizes": "Añade la longitud antigua y la longitud nueva de la página en bytes.",
        "apihelp-query+recentchanges-paramvalue-prop-redirect": "Etiqueta la edición si la página es una redirección.",
        "apihelp-query+recentchanges-paramvalue-prop-patrolled": "Etiqueta ediciones verificables como verificadas o no verificadas.",
+       "apihelp-query+recentchanges-paramvalue-prop-loginfo": "Añade información de registro (identificador de registro, tipo de registro, etc.) a las entradas de registro.",
+       "apihelp-query+recentchanges-paramvalue-prop-tags": "Muestra las etiquetas de la entrada.",
        "apihelp-query+recentchanges-param-token": "Usa <kbd>[[Special:ApiHelp/query+tokens|action=query&meta=tokens]]</kbd> en su lugar.",
        "apihelp-query+recentchanges-param-limit": "Cuántos cambios en total se devolverán.",
        "apihelp-query+recentchanges-param-type": "Cuántos tipos de cambios se mostrarán.",
        "apihelp-query+revisions+base-paramvalue-prop-content": "Texto de la revisión.",
        "apihelp-query+revisions+base-paramvalue-prop-tags": "Etiquetas para la revisión.",
        "apihelp-query+revisions+base-param-limit": "Limitar la cantidad de revisiones que se devolverán.",
+       "apihelp-query+search-param-namespace": "Buscar sólo en estos espacios de nombres.",
+       "apihelp-query+search-param-what": "Tipo de búsqueda que realizar.",
        "apihelp-query+search-param-info": "Qué metadatos devolver.",
        "apihelp-query+search-param-prop": "Qué propiedades se devolverán:",
        "apihelp-query+search-paramvalue-prop-size": "Añade el tamaño de la página en bytes.",
        "apihelp-query+transcludedin-param-namespace": "Incluir solo las páginas en estos espacios de nombres.",
        "apihelp-query+transcludedin-param-limit": "Cuántos se devolverán.",
        "apihelp-query+transcludedin-example-simple": "Obtener una lista de páginas transcluyendo <kbd>Main Page</kbd>.",
+       "apihelp-query+transcludedin-example-generator": "Obtener información sobre las páginas que transcluyen <kbd>Main Page</kbd>.",
        "apihelp-query+usercontribs-description": "Obtener todas las ediciones realizadas por un usuario.",
        "apihelp-query+usercontribs-param-limit": "Número máximo de contribuciones que se devolverán.",
        "apihelp-query+usercontribs-param-prop": "Incluir piezas adicionales de información:",
        "apihelp-query+watchlist-paramvalue-type-external": "Cambios externos.",
        "apihelp-query+watchlist-paramvalue-type-new": "Creaciones de páginas.",
        "apihelp-query+watchlist-paramvalue-type-log": "Entradas del registro.",
+       "apihelp-query+watchlist-param-owner": "Utilizado junto con $1token para acceder a la lista de seguimiento de otro usuario.",
+       "apihelp-query+watchlistraw-description": "Obtener todas las páginas de la lista de seguimiento del usuario actual.",
+       "apihelp-query+watchlistraw-param-namespace": "Mostrar solamente las páginas de los espacios de nombres dados.",
        "apihelp-query+watchlistraw-param-limit": "Número de resultados que devolver en cada petición.",
        "apihelp-query+watchlistraw-param-prop": "Qué propiedades adicionales se obtendrán:",
        "apihelp-query+watchlistraw-param-show": "Sólo listar los elementos que cumplen estos criterios.",
+       "apihelp-query+watchlistraw-param-owner": "Utilizado junto con $1token para acceder a la lista de seguimiento de otro usuario.",
        "apihelp-query+watchlistraw-param-dir": "La dirección en la que se listará.",
        "apihelp-query+watchlistraw-param-fromtitle": "Título (con el prefijo de espacio de nombres) desde el que se empezará a enumerar.",
        "apihelp-query+watchlistraw-param-totitle": "Título (con el prefijo de espacio de nombres) desde el que se dejará de enumerar.",
        "apihelp-query+watchlistraw-example-simple": "Listar las páginas de la lista de seguimiento del usuario actual.",
+       "apihelp-removeauthenticationdata-description": "Elimina los datos de autentificación del usuario actual.",
        "apihelp-resetpassword-description": "Enviar un email de reinicialización de la contraseña a un usuario.",
        "apihelp-revisiondelete-description": "Eliminar y restaurar revisiones",
        "apihelp-revisiondelete-param-hide": "Qué ocultar en cada revisión.",
        "apihelp-revisiondelete-param-show": "Qué mostrar en cada revisión.",
        "apihelp-revisiondelete-param-reason": "Motivo de la eliminación o restauración.",
+       "apihelp-revisiondelete-example-revision": "Ocultar el contenido de la revisión <kbd>12345</kbd> de la página <kbd>Main Page</kbd>.",
+       "apihelp-revisiondelete-example-log": "Ocultar todos los datos de la entrada de registro <kbd>67890</kbd> con el motivo <kbd>BLP violation</kbd>.",
+       "apihelp-rollback-description": "Deshacer la última edición de la página.\n\nSi el último usuario que editó la página hizo varias ediciones consecutivas, todas ellas serán revertidas.",
        "apihelp-rollback-param-summary": "Resumen de edición personalizado. Si se deja vacío se utilizará el predeterminado.",
        "apihelp-rsd-description": "Exportar un esquema RSD (Really Simple Discovery; Descubrimiento Muy Simple).",
        "apihelp-rsd-example-simple": "Exportar el esquema RSD.",
+       "apihelp-setpagelanguage-description": "Cambiar el idioma de una página.",
+       "apihelp-setpagelanguage-description-disabled": "En este wiki no se permite modificar el idioma de las páginas.\n\nActiva <var>[[mw:Manual:$wgPageLanguageUseDB|$wgPageLanguageUseDB]]</var> para utilizar esta acción.",
+       "apihelp-setpagelanguage-param-title": "Título de la página cuyo idioma deseas cambiar. No se puede usar junto con <var>$1pageid</var>.",
+       "apihelp-setpagelanguage-param-pageid": "Identificador de la página cuyo idioma deseas cambiar. No se puede usar junto con <var>$1title</var>.",
+       "apihelp-setpagelanguage-param-lang": "Código del idioma al que se desea cambiar la página. Usa <kbd>default</kbd> para restablecer la página al idioma predeterminado para el contenido del wiki.",
+       "apihelp-setpagelanguage-param-reason": "Motivo del cambio.",
+       "apihelp-setpagelanguage-example-language": "Cambiar el idioma de <kbd>Main Page</kbd> al euskera.",
+       "apihelp-setpagelanguage-example-default": "Cambiar el idioma de la página con identificador 123 al idioma predeterminado para el contenido del wiki.",
        "apihelp-stashedit-param-title": "Título de la página que se está editando.",
        "apihelp-stashedit-param-section": "Número de la sección. <kbd>0</kbd> para una sección superior, <kbd>new</kbd> para una sección nueva.",
        "apihelp-stashedit-param-sectiontitle": "El título de una sección nueva.",
        "apihelp-userrights-param-add": "Agregar el usuario a estos grupos.",
        "apihelp-userrights-param-remove": "Eliminar el usuario de estos grupos.",
        "apihelp-userrights-param-reason": "Motivo del cambio.",
+       "apihelp-userrights-param-tags": "Cambia las etiquetas que aplicar a la entrada del registro de derechos del usuario.",
        "apihelp-userrights-example-user": "Agregar al usuario <kbd>FooBot</kbd> al grupo <kbd>bot</kbd> y eliminarlo de los grupos <kbd>sysop</kbd> y <kbd>bureaucrat</kbd>.",
        "apihelp-watch-example-watch": "Vigilar la página <kbd>Main Page</kbd>.",
        "apihelp-watch-example-unwatch": "Dejar de vigilar la <kbd>Main Page</kbd>.",
        "apihelp-xml-param-xslt": "Si se especifica, añade la página nombrada como una hoja de estilo XSL. El valor debe ser un título en el espacio de nombres {{ns:MediaWiki}} que termine en <code>.xsl</code>.",
        "apihelp-xml-param-includexmlnamespace": "Si se especifica, añade un espacio de nombres XML.",
        "api-format-title": "Resultado de la API de MediaWiki",
+       "api-format-prettyprint-header": "Esta es la representación en HTML del formato $1. HTML es adecuado para realizar tareas de depuración, pero no para utilizarlo en aplicaciones.\n\nUtiliza el parámetro <var>format</var> para modificar el formato de salida. Para ver la representación no HTML del formato $1, emplea <kbd>format=$2</kbd>.\n\nPara obtener más información, consulta la [[mw:API|documentación completa]] o la [[Special:ApiHelp/main|ayuda de API]].",
        "api-format-prettyprint-status": "Esta respuesta se devolvería con el estado HTTP $1 $2.",
        "api-help-title": "Ayuda de la API de MediaWiki",
        "api-help-lead": "Esta es una página de documentación autogenerada de la API de MediaWiki.\n\nDocumentación y ejemplos: https://www.mediawiki.org/wiki/API",
        "apierror-invalidsha1hash": "El hash SHA1 proporcionado no es válido.",
        "apierror-invalidtitle": "Título incorrecto \"$1\".",
        "apierror-invaliduser": "Nombre de usuario «$1» no válido.",
+       "apierror-invaliduserid": "El identificador de usuario <var>$1</var> no es válido.",
        "apierror-missingparam-at-least-one-of": "{{PLURAL:$2|El parámetro|Al menos uno de los parámetros}} $1 es necesario.",
        "apierror-missingparam-one-of": "{{PLURAL:$2|El parámetro|Uno de los parámetros}} $1 es necesario.",
        "apierror-missingparam": "Se debe establecer el parámetro <var>$1</var>.",
        "apierror-noedit-anon": "Los usuarios anónimos no pueden editar páginas.",
        "apierror-noedit": "No tienes permiso para editar páginas.",
        "apierror-nosuchuserid": "No hay ningún usuario con ID $1.",
+       "apierror-pagelang-disabled": "En este wiki no se puede cambiar el idioma de una página.",
        "apierror-paramempty": "El parámetro <var>$1</var> no puede estar vacío.",
        "apierror-permissiondenied": "No tienes permiso para $1.",
        "apierror-permissiondenied-generic": "Permiso denegado.",
index cb88c55..89c8768 100644 (file)
        "apihelp-help-example-query": "Aide pour deux sous-modules de recherche",
        "apihelp-imagerotate-description": "Faire pivoter une ou plusieurs images.",
        "apihelp-imagerotate-param-rotation": "Degrés de rotation de l’image dans le sens des aiguilles d’une montre.",
+       "apihelp-imagerotate-param-tags": "Balises à appliquer à l’entrée dans le journal de téléchargement.",
        "apihelp-imagerotate-example-simple": "Faire pivoter <kbd>File:Example.png</kbd> de <kbd>90</kbd> degrés.",
        "apihelp-imagerotate-example-generator": "Faire pivoter toutes les images de <kbd>Category:Flip</kbd> de <kbd>180</kbd> degrés.",
        "apihelp-import-description": "Importer une page depuis un autre wiki, ou depuis un fichier XML.\n\nNoter que le POST HTTP doit être effectué comme un import de fichier (c’est-à-dire en utilisant multipart/form-data) lors de l’envoi d’un fichier pour le paramètre <var>xml</var>.",
        "apihelp-query+usercontribs-param-limit": "Le nombre maximal de contributions à renvoyer.",
        "apihelp-query+usercontribs-param-start": "L’horodatage auquel démarrer le retour.",
        "apihelp-query+usercontribs-param-end": "L’horodatage auquel arrêter le retour.",
-       "apihelp-query+usercontribs-param-user": "Les utilisateurs pour lesquels récupérer les contributions.",
-       "apihelp-query+usercontribs-param-userprefix": "Récupérer les contributions pour tous les utilisateurs dont les noms commencent par cette valeur. Écrase $1user.",
+       "apihelp-query+usercontribs-param-user": "Utilisateurs pour lesquels il faut récupérer les contributions.   Ne peut pas être utilisé avec <var>$1userid</var> ou <var>$1userprefix</var>.",
+       "apihelp-query+usercontribs-param-userprefix": "Récupérer les contributions pour tous les utilisateurs dont les noms commencent par cette valeur. Ne peut pas être utilisé avec <var>$1user</var> ou <var>$1userids</var>.",
+       "apihelp-query+usercontribs-param-userids": "Utilisateurs pour lesquels il faut récupérer les contributions.   Ne peut pas être utilisé avec <var>$1user</var> ou <var>$1userprefix</var>.",
        "apihelp-query+usercontribs-param-namespace": "Lister uniquement les contributions dans ces espaces de nom.",
        "apihelp-query+usercontribs-param-prop": "Inclure des informations supplémentaires:",
        "apihelp-query+usercontribs-paramvalue-prop-ids": "Ajoute l’ID de page et l’ID de révision.",
        "apihelp-revisiondelete-param-show": "Quoi démasquer pour chaque révision",
        "apihelp-revisiondelete-param-suppress": "S’il faut supprimer les données aux administrateurs comme aux autres.",
        "apihelp-revisiondelete-param-reason": "Motif de suppression ou d’annulation de suppression.",
+       "apihelp-revisiondelete-param-tags": "Balises à appliquer à l’entrée dans le journal de suppression.",
        "apihelp-revisiondelete-example-revision": "Masquer le contenu de la révision <kbd>12345</kbd> de la page <kbd>Main Page</kbd>",
        "apihelp-revisiondelete-example-log": "Masquer toutes les données de l’entrée de journal <kbd>67890</kbd> avec le motif <kbd>Violation de Biographie de Personne Vivante</kbd>.",
        "apihelp-rollback-description": "Annuler la dernière modification de la page.\n\nSi le dernier utilisateur à avoir modifié la page a fait plusieurs modifications sur une ligne, elles seront toutes annulées.",
        "apihelp-setnotificationtimestamp-example-page": "Réinitialiser l’état de notification pour la <kbd>Page principale<kbd>.",
        "apihelp-setnotificationtimestamp-example-pagetimestamp": "Fixer l’horodatage de notification pour <kbd>Page principale</kbd> afin que toutes les modifications depuis le 1 janvier 2012 soient non vues",
        "apihelp-setnotificationtimestamp-example-allpages": "Réinitialiser l’état de notification sur les pages dans l’espace de noms <kbd>{{ns:user}}</kbd>.",
+       "apihelp-setpagelanguage-description": "Modifier la langue d’une page.",
+       "apihelp-setpagelanguage-description-disabled": "Il n’est pas possible de modifier la langue d’une page sur ce wiki.\n\nActiver <var>[[mw:Manual:$wgPageLanguageUseDB|$wgPageLanguageUseDB]]</var> pour utiliser cette action.",
+       "apihelp-setpagelanguage-param-title": "Titre de la page dont vous souhaitez modifier la langue. Ne peut pas être utilisé avec <var>$1pageid</var>.",
+       "apihelp-setpagelanguage-param-pageid": "Identifiant (ID) de la page dont vous souhaitez modifier la langue. Ne peut être utilisé avec <var>$1title</var>.",
+       "apihelp-setpagelanguage-param-lang": "Code de langue vers lequel la page doit être changée. Utiliser <kbd>defaut</kbd> pour réinitialiser la page sur la langue par défaut du contenu du wiki.",
+       "apihelp-setpagelanguage-param-reason": "Motif de la modification.",
+       "apihelp-setpagelanguage-param-tags": "Modifier les balises à appliquer à l'entrée du journal résultant de cette action.",
+       "apihelp-setpagelanguage-example-language": "Changer la langue de la <kbd>page principale</kbd> en basque.",
+       "apihelp-setpagelanguage-example-default": "Remplacer la langue de la page ayant l'ID 123 par la langue par défaut du contenu du wiki.",
        "apihelp-stashedit-description": "Préparer une modification dans le cache partagé.\n\nCeci a pour but d’être utilisé via AJAX depuis le formulaire d’édition pour améliorer la performance de la sauvegarde de la page.",
        "apihelp-stashedit-param-title": "Titre de la page en cours de modification.",
        "apihelp-stashedit-param-section": "Numéro de section. <kbd>0</kbd> pour la section du haut, <kbd>new</kbd> pour une nouvelle section.",
        "apihelp-tag-param-add": "Balises à ajouter. Seules les balises définies manuellement peuvent être ajoutées.",
        "apihelp-tag-param-remove": "Balises à supprimer. Seules les balises qui sont soit définies manuellement soit pas du tout définies peuvent être supprimées.",
        "apihelp-tag-param-reason": "Motif de la modification.",
+       "apihelp-tag-param-tags": "Balises à appliquer à l’entrée de journal qui sera créée en résultat de cette action.",
        "apihelp-tag-example-rev": "Ajoute la balise <kbd>vandalism</kbd> à partir de l’ID de révision 123 sans indiquer de motif",
        "apihelp-tag-example-log": "Supprimer la balise <kbd>spam</kbd> à partir de l’ID d’entrée de journal 123 avec le motif <kbd>Wrongly applied</kbd>",
        "apihelp-tokens-description": "Obtenir les jetons pour les actions modifiant les données.\n\nCe module est obsolète, remplacé par [[Special:ApiHelp/query+tokens|action=query&meta=tokens]].",
        "apierror-invalidtitle": "Mauvais titre « $1 ».",
        "apierror-invalidurlparam": "Valeur non valide pour <var>$1urlparam</var> (<kbd>$2=$3</kbd>).",
        "apierror-invaliduser": "Nom d'utilisateur invalide \"$1\".",
+       "apierror-invaliduserid": "L'ID d'utilisateur <var>$1</var> n'est pas valide.",
        "apierror-maxlag-generic": "Attente d’un serveur de base de données : $1 {{PLURAL:$1|seconde|secondes}} de délai.",
        "apierror-maxlag": "Attente de $2 : $1 {{PLURAL:$1|seconed|secondes}} de délai.",
        "apierror-mimesearchdisabled": "La recherche MIME est désactivée en mode Misère.",
        "apierror-opensearch-json-warnings": "Les avertissements ne peuvent pas être représentés dans le format JSON OpenSearch.",
        "apierror-pagecannotexist": "L’espace de noms ne permet pas de pages réelles.",
        "apierror-pagedeleted": "La page a été supprimée depuis que vous avez récupéré son horodatage.",
+       "apierror-pagelang-disabled": "Il n'est pas possible de modifier la langue d'une page sur ce wiki.",
        "apierror-paramempty": "Le paramètre <var>$1</var> ne peut pas être vide.",
        "apierror-parsetree-notwikitext": "<kbd>prop=parsetree</kbd> n’est supporté que pour le contenu wikitexte.",
        "apierror-parsetree-notwikitext-title": "<kbd>prop=parsetree</kbd> n’est supporté que pour le contenu wikitexte. $1 utilise le modèle de contenu $2.",
index dcbeceb..5d658d5 100644 (file)
        "apihelp-help-example-query": "עזרה לשתי תת־יחידות של שאילתה.",
        "apihelp-imagerotate-description": "סיבוב של תמונה אחת או יותר.",
        "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-description": "לייבא דף מוויקי אחר או מקובץ XML.\n\nיש לשים לב לכך שפעולת HTTP POST צריכה להיעשות בתור העלאת קובץ (כלומר, עם multipart/form-data) בזמן שליחת קובץ לפרמטר <var>xml</var>.",
        "apihelp-query+usercontribs-param-limit": "המספר המרבי של התרומות להחזיר.",
        "apihelp-query+usercontribs-param-start": "באיזה חותם־הזמן להתחיל.",
        "apihelp-query+usercontribs-param-end": "באיזה חותם־הזמן לסיים",
-       "apihelp-query+usercontribs-param-user": "עבור אילו משתמשים לאחזר תרומות.",
-       "apihelp-query+usercontribs-param-userprefix": "×\90×\97×\96×\95ר ×ª×¨×\95×\9e×\95ת ×¢×\91×\95ר ×\9b×\9c ×\94×\9eשת×\9eש×\99×\9d ×©×\94ש×\9e×\95ת ×©×\9c×\94×\9d ×\9eת×\97×\99×\9c×\99×\9d ×\91ער×\9a ×\94×\96×\94. ×\93×\95רס ×\90ת $1user.",
+       "apihelp-query+usercontribs-param-user": "עבור אילו משתמשים לאחזר תרומות. לא יכול לשמש עם <var>$1userids</var> או <var>$1userprefix</var>.",
+       "apihelp-query+usercontribs-param-userprefix": "×\90×\97×\96×\95ר ×ª×¨×\95×\9e×\95ת ×¢×\91×\95ר ×\9b×\9c ×\94×\9eשת×\9eש×\99×\9d ×©×\94ש×\9e×\95ת ×©×\9c×\94×\9d ×\9eת×\97×\99×\9c×\99×\9d ×\91ער×\9a ×\94×\96×\94. ×\9c×\90 ×\99×\9b×\95×\9c ×\9cש×\9eש ×¢×\9d <var>$1user</var> ×\90×\95 <var>$1userids</var>.",
        "apihelp-query+usercontribs-param-namespace": "לרשום רק תרומות במרחבי השם האלה.",
        "apihelp-query+usercontribs-param-prop": "לכלול פריטי מידע נוספים:",
        "apihelp-query+usercontribs-paramvalue-prop-ids": "הוספת מזהה הדף ומזהה הגרסה.",
        "apihelp-revisiondelete-param-show": "הסתרה של מה לבטל עבור כל גרסה.",
        "apihelp-revisiondelete-param-suppress": "האם להעלים נתונים ממפעילים ומאחרים.",
        "apihelp-revisiondelete-param-reason": "סיבה למחיקה או לשחזור ממחיקה.",
+       "apihelp-revisiondelete-param-tags": "אילו תגים להחיל על העיול ביומן המחיקה.",
        "apihelp-revisiondelete-example-revision": "הסתרת התוכן של הגרסה <kbd>12345</kbd> בדף <kbd>Main Page</kbd>.",
        "apihelp-revisiondelete-example-log": "הסתרת כל הנתוהים על עיול היומן <kbd>67890</kbd> עם הסיבה <kbd>BLP violation</kbd>.",
        "apihelp-rollback-description": "ביטול העריכה האחרונה לדף.\n\nאם המשמש האחרון שערך את הדף עשה מספר עריכות זו אחר זו, הן תשוחזרנה.",
        "apihelp-setnotificationtimestamp-example-page": "אתחול מצב ההודעה עבור <kbd>Main Page</kbd>.",
        "apihelp-setnotificationtimestamp-example-pagetimestamp": "הגדרת חותם־הזמן להודעה ל־<kbd>Main page</kbd> כך שכל העריכות מאז 1 בינואר 2012 מוגדרות בתור כאלה שלא נצפו.",
        "apihelp-setnotificationtimestamp-example-allpages": "אתחול מצב ההודעה עבור דפים במרחב השם <kbd>{{ns:user}}</kbd>.",
+       "apihelp-setpagelanguage-param-tags": "אילו תגי שינוי להחיל על העיול ביומן שמתבצע כתוצאה מהפעולה הזאת.",
        "apihelp-stashedit-description": "הכנת עריכה במטמון משותף.\n\nזה מיועד לשימוש דרך AJAX מתוך ערך כדי לשפר את הביצועים של שמירת הדף.",
        "apihelp-stashedit-param-title": "כותרת הדף הנערך.",
        "apihelp-stashedit-param-section": "מספר הפסקה. <kbd>0</kbd> עבור הפסקה הראשונה, <kbd>new</kbd> עבור פסקה חדשה.",
        "apihelp-tag-param-add": "התגים להוספה. אפשר להוסיף רק תגים קיימים.",
        "apihelp-tag-param-remove": "תגים להסרה. רק תגים שהוגדרו ידנית או שאינם מוגדרים כלל יכולים להיות מוסרים.",
        "apihelp-tag-param-reason": "סיבה לשינוי.",
+       "apihelp-tag-param-tags": "אילו תגים להחיל על עיול היומן שייווצר כתוצאה מהפעולה הזאת.",
        "apihelp-tag-example-rev": "הוספת התג <kbd>vandalism</kbd> לגרסה עם המזהה 123 בלי לציין סיבה",
        "apihelp-tag-example-log": "הסרת התג <kbd>spam</kbd> מעיול עם המזהה 123 עם הסיבה <kbd>Wrongly applied</kbd>",
        "apihelp-tokens-description": "קבלת אסימונים לפעולות שמשנות נתונים.\n\nהיחידה הזאת הוכרזה בתור מיושנת לטובת [[Special:ApiHelp/query+tokens|action=query&meta=tokens]].",
        "apierror-nodeleteablefile": "אין גרסה ישנה כזאת של הקובץ.",
        "apierror-no-direct-editing": "עריכה ישירה דרך ה־API אינה נתמכת עבור דגם התוכן $1 שמשמש ב{{GRAMMAR:תחילית|$2}}.",
        "apierror-noedit-anon": "משתמשים אלמוניים אינם יכולים לערוך דפים.",
+       "apierror-nosuchlogid": "אין עיול יומן עם המזהה $1.",
+       "apierror-stashinvalidfile": "קובץ מוסלק בלתי־תקין.",
        "apierror-stashnosuchfilekey": "אין מפתח קובץ כזה: $1.",
+       "apierror-stashpathinvalid": "מפתח קובץ מתסדיר בלתי־הולם או בלתי־תקין באופן אחר: $1.",
+       "apierror-stashwrongowner": "בעלים בלתי־תקין: $1",
+       "apierror-stashzerolength": "קובץ באורך אפס, ואל יכול משוחזר בסליק: $1.",
+       "apierror-systemblocked": "נחסמת אוטומטית על־ידי מדיה־ויקי.",
        "apierror-unknownerror-nocode": "שגיאה בלתי־ידועה.",
        "apierror-unknownerror": "שגיאה בלתי ידועה: \"$1\".",
        "apierror-unknownformat": "תסדיר בלתי־ידוע \"$1\".",
index e6320cc..dad298f 100644 (file)
@@ -1,7 +1,8 @@
 {
        "@metadata": {
                "authors": [
-                       "McDutchie"
+                       "McDutchie",
+                       "Rafaneta"
                ]
        },
        "apihelp-main-description": "<div class=\"hlist plainlinks api-main-links\">\n* [[mw:API:Main_page|Documentation]]\n* [[mw:API:FAQ|FAQ]]\n* [https://lists.wikimedia.org/mailman/listinfo/mediawiki-api Listas de diffusion]\n* [https://lists.wikimedia.org/mailman/listinfo/mediawiki-api-announce Annuncios sur le API]\n* [https://phabricator.wikimedia.org/maniphest/query/GebfyV4uCaLd/#R Bugs & demandas]\n</div>\n<strong>Stato:</strong> Tote le functiones monstrate in iste pagina deberea functionar, sed le API es ancora in disveloppamento active e pote cambiar a omne momento. Subscribe te al [https://lists.wikimedia.org/pipermail/mediawiki-api-announce/ lista de diffusion mediawiki-api-announce] pro esser informate de actualisationes.\n\n<strong>Requestas erronee:</strong> Quando requestas erronee se invia al API, un capite HTTP essera inviate con le clave \"MediaWiki-API-Error\". Le valor de iste capite e le codice de error reinviate essera identic. Pro plus information vide [[mw:API:Errors_and_warnings|API: Errores e avisos]].\n\n<strong>Tests:</strong> Pro facilitar le test de requestas API, vide [[Special:ApiSandbox]].",
        "apihelp-main-param-smaxage": "Fixar le capite de controlo de cache HTTP <code>s-maxage</code> a iste numero de secundas. Errores nunquam es mittite in cache.",
        "apihelp-main-param-maxage": "Fixar le capite de controlo de cache HTTP <code>max-age</code> a iste numero de secundas. Errores nunquam es mittite in cache.",
        "apihelp-main-param-assert": "Verificar si le usator ha aperite session si mittite a <kbd>user</kbd>, o si ha le derecto de usator robot si <kbd>bot</kbd>.",
+       "apihelp-main-param-assertuser": "Verificar que le usator currente es le usator nominate.",
        "apihelp-main-param-requestid": "Omne valor fornite hic essera includite in le responsa. Pote esser usate pro distinguer requestas.",
        "apihelp-main-param-servedby": "Includer in le resultato le nomine del host que ha servite le requesta.",
        "apihelp-main-param-curtimestamp": "Includer le data e hora actual in le resultato.",
+       "apihelp-main-param-responselanginfo": "Includer le linguas usate pro <var>uselang</var> e <var>errorlang</var> in le resultato.",
        "apihelp-main-param-origin": "Quando se accede al API usante un requesta AJAX inter-dominios (CORS), mitte le dominio de origine in iste parametro. Illo debe esser includite in omne requesta pre-flight, e dunque debe facer parte del URI del requesta (e non del corpore POST).\n\nPro requestas authenticate, isto debe corresponder exactemente a un del origines in le capite <code>Origin</code>, dunque debe esser mittite a qualcosa como <kbd>http://ia.wikipedia.org</kbd> o <kbd>https://meta.wikimedia.org</kbd>. Si iste parametro non corresponde al capite <code>Origin</code>, un responsa 403 essera retornate. Si iste parametro corresponde al capite <code>Origin</code> e le origine es in le lista blanc, le capites <code>Access-Control-Allow-Origin</code> e <code>Access-Control-Allow-Credentials</code> essera inserite.\n\nPro requestas non authenticate, specifica le valor <kbd>*</kbd>. Isto causara le insertion del capite <code>Access-Control-Allow-Origin</code>, ma <code>Access-Control-Allow-Credentials</code> essera mittite a <code>false</code> e tote le datos specific al usator essera restringite.",
        "apihelp-main-param-uselang": "Lingua a usar pro traductiones de messages <kbd>[[Special:ApiHelp/query+siteinfo|action=query&meta=siteinfo]]</kbd> con <kbd>siprop=languages</kbd> retorna un lista de codices de lingua, o specifica <kbd>user</kbd> pro usar le preferentia de lingua del usator actual, o specifica <kbd>content</kbd> pro usar le lingua de contento de iste wiki.",
        "apihelp-block-description": "Blocar un usator.",
index 71b1763..b543bb8 100644 (file)
        "apihelp-revisiondelete-param-hide": "Cosa nascondere per ogni versione.",
        "apihelp-revisiondelete-param-show": "Cosa mostrare per ogni versione.",
        "apihelp-revisiondelete-param-reason": "Motivo per l'eliminazione o il ripristino.",
+       "apihelp-setpagelanguage-description": "Cambia la lingua di una pagina.",
+       "apihelp-setpagelanguage-param-reason": "Motivo per la modifica.",
        "apihelp-stashedit-param-title": "Titolo della pagina che si sta modificando.",
        "apihelp-stashedit-param-sectiontitle": "Il titolo per una nuova sezione.",
        "apihelp-stashedit-param-text": "Contenuto della pagina.",
        "api-help-authmanagerhelper-returnurl": "URL di ritorno per i flussi di autenticazione di terze parti, deve essere assoluto. E' necessario fornirlo, oppure va fornito <var>$1continue</var>.\n\nAlla ricezione di una risposta <samp>REDIRECT</samp>, in genere si apre un browser o una vista web all'URL specificato <samp>redirecttarget</samp> per un flusso di autenticazione di terze parti. Quando questo è completato, la terza parte invierà il browser o la vista web a questo URL. Dovresti estrarre qualsiasi parametro POST o della richiesta dall'URL e passarli come un request <var>$1continue</var> a questo modulo API.",
        "api-help-authmanagerhelper-continue": "Questa richiesta è una continuazione dopo una precedente risposta <samp>UI</samp> o <samp>REDIRECT</samp>. È necessario fornirlo, oppure fornire <var>$1returnurl</var>.",
        "api-help-authmanagerhelper-additional-params": "Questo modulo accetta parametri aggiuntivi a seconda delle richieste di autenticazione disponibili. Utilizza <kbd>[[Special:ApiHelp/query+authmanagerinfo|action=query&meta=authmanagerinfo]]</kbd> con <kbd>amirequestsfor=$1</kbd> (o una precedente risposta da questo modulo, se applicabile) per determinare le richieste disponibili e i campi usati da queste.",
+       "apierror-invaliduserid": "L'ID utente <var>$1</var> non è valido.",
        "apierror-nosuchuserid": "Non c'è alcun utente con ID $1.",
        "api-credits-header": "Crediti"
 }
index 908f860..1531586 100644 (file)
                        "Priviet",
                        "Ykhwong",
                        "Jonghaya",
-                       "Jerrykim306"
+                       "Jerrykim306",
+                       "코코아"
                ]
        },
-       "apihelp-main-description": "<div class=\"hlist plainlinks api-main-links\">\n* [[mw:API:Main_page|ì\84¤ëª\85문ì\84\9c]]\n* [[mw:API:FAQ|FAQ]]\n* [https://lists.wikimedia.org/mailman/listinfo/mediawiki-api ë©\94ì\9d¼ë§\81 ë¦¬ì\8a¤í\8a¸]\n* [https://lists.wikimedia.org/mailman/listinfo/mediawiki-api-announce API ì\95\8c림 ì\82¬í\95­]\n* [https://phabricator.wikimedia.org/maniphest/query/GebfyV4uCaLd/#R ë²\84ê·¸ ë°\8f ì\9a\94ì²­]\n</div>\n<strong>ì\83\81í\83\9c:</strong> ì\9d´ í\8e\98ì\9d´ì§\80ì\97\90 ë³´ì\9d´ë\8a\94 ëª¨ë\93  ê¸°ë\8a¥ì\9d\80 ì \95ì\83\81ì \81ì\9c¼ë¡\9c ì\9e\91ë\8f\99í\95\98ì§\80ë§\8c, APIë\8a\94 ì\97¬ì \84í\9e\88 í\99\9cë°\9cí\95\98ê²\8c ê°\9cë°\9cë\90\98ê³  ì\9e\88ì\9c¼ë©°, ì\96¸ì \9cë\93 ì§\80 ë³\80ê²½ë\90  ì\88\98 ì\9e\88ì\8aµë\8b\88ë\8b¤. ì\97\85ë\8d°ì\9d´í\8a¸ ê³µì§\80를 ë°\9bì\95\84보려면 [https://lists.wikimedia.org/pipermail/mediawiki-api-announce/ mediawiki-api-announce ë©\94ì\9d¼ë§\81 ë¦¬ì\8a¤í\8a¸]를 êµ¬ë\8f\85í\95\98ì\8b­ì\8b\9cì\98¤.\n\n<strong>ì\9e\98못ë\90\9c ì\9a\94ì²­:</strong> APIì\97\90 ì\9e\98못ë\90\9c ì\9a\94ì²­ì\9d´ ì \84ì\86¡ë\90\98ë©´ \"MediaWiki-API-Error\" í\82¤ê°\80 í\8f¬í\95¨ë\90\9c HTTP í\97¤ë\8d\94ê°\80 ì \84ì\86¡ë\90\98ë©° ë°\98í\99\98ë\90\98ë\8a\94 í\97¤ë\8d\94ì\99\80 ì\98¤ë¥\98 ì½\94ë\93\9cì\9d\98 ê°\92ì\9d\80 ë\8f\99ì\9d¼í\95\9c ê°\92ì\9c¼ë¡\9c ì\84¤ì \95ë\90©ë\8b\88ë\8b¤. ì\9e\90ì\84¸í\95\9c ì \95ë³´ì\97\90 ë\8c\80í\95´ì\84\9cë\8a\94 [[mw:API:Errors_and_warnings|API:오류와 경고]]를 참조하십시오.\n\n<strong>테스트하기:</strong> API 요청 테스트를 용이하게 하려면, [[Special:ApiSandbox]]를 보십시오.",
+       "apihelp-main-description": "<div class=\"hlist plainlinks api-main-links\">\n* [[mw:API:Main_page|ì\84¤ëª\85문ì\84\9c]]\n* [[mw:API:FAQ|FAQ]]\n* [https://lists.wikimedia.org/mailman/listinfo/mediawiki-api ë©\94ì\9d¼ë§\81 ë¦¬ì\8a¤í\8a¸]\n* [https://lists.wikimedia.org/mailman/listinfo/mediawiki-api-announce API ì\95\8c림 ì\82¬í\95­]\n* [https://phabricator.wikimedia.org/maniphest/query/GebfyV4uCaLd/#R ë²\84ê·¸ ë°\8f ì\9a\94ì²­]\n</div>\n<strong>ì\83\81í\83\9c:</strong> ì\9d´ í\8e\98ì\9d´ì§\80ì\97\90 ë³´ì\9d´ë\8a\94 ëª¨ë\93  ê¸°ë\8a¥ì\9d\80 ì \95ì\83\81ì \81ì\9c¼ë¡\9c ì\9e\91ë\8f\99í\95\98ì§\80ë§\8c, APIë\8a\94 ì\97¬ì \84í\9e\88 í\99\9cë°\9cí\95\98ê²\8c ê°\9cë°\9cë\90\98ê³  ì\9e\88ì\9c¼ë©°, ì\96¸ì \9cë\93 ì§\80 ë³\80ê²½ë\90  ì\88\98 ì\9e\88ì\8aµë\8b\88ë\8b¤. ì\97\85ë\8d°ì\9d´í\8a¸ ê³µì§\80를 ë°\9bì\95\84보려면 [https://lists.wikimedia.org/pipermail/mediawiki-api-announce/ mediawiki-api-announce ë©\94ì\9d¼ë§\81 ë¦¬ì\8a¤í\8a¸]를 êµ¬ë\8f\85í\95\98ì\8b­ì\8b\9cì\98¤.\n\n<strong>ì\9e\98못ë\90\9c ì\9a\94ì²­:</strong> APIì\97\90 ì\9e\98못ë\90\9c ì\9a\94ì²­ì\9d´ ì \84ì\86¡ë\90\98ë©´ \"MediaWiki-API-Error\" í\82¤ê°\80 í\8f¬í\95¨ë\90\9c HTTP í\97¤ë\8d\94ê°\80 ì \84ì\86¡ë\90\98ë©° ë°\98í\99\98ë\90\98ë\8a\94 í\97¤ë\8d\94ì\99\80 ì\98¤ë¥\98 ì½\94ë\93\9cì\9d\98 ê°\92ì\9d\80 ëª¨ë\91\90 ë\8f\99ì\9d¼í\95\9c ê°\92ì\9c¼ë¡\9c ì\84¤ì \95ë\90©ë\8b\88ë\8b¤. ì\9e\90ì\84¸í\95\9c ì \95ë³´ì\97\90 ë\8c\80í\95´ì\84\9cë\8a\94 [[mw:API:Errors and warnings/ko|API:오류와 경고]]를 참조하십시오.\n\n<strong>테스트하기:</strong> API 요청 테스트를 용이하게 하려면, [[Special:ApiSandbox]]를 보십시오.",
        "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:Manual:Maxlag_parameter|매뉴얼: Maxlag 변수]] 에서 더 많은 정보를 얻을 수 있습니다.",
        "apihelp-main-param-requestid": "주어진 요청 값은 응답에 포함됩니다. 요청을 구분하기 위해 사용될 수 있습니다.",
        "apihelp-main-param-servedby": "결과에 요청을 처리한 호스트네임을 포함합니다.",
        "apihelp-main-param-curtimestamp": "결과의 타임스탬프를 포함합니다.",
+       "apihelp-main-param-responselanginfo": "<var>uselang</var> 및 <var>errorlang</var>에 사용되는 언어를 결과에 포함합니다.",
+       "apihelp-main-param-origin": "크로스 도메인 AJAX 요청 (CORS)을 사용하여 API에 접근할 때, 이것을 발신 도메인으로 설정하십시오. 모든 pre-flight 요청에 포함되어야 하며, 이에 따라 (POST 본문이 아닌) 요청 URI의 일부여야 합니다.\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-errorformat": "경고 및 오류 텍스트 출력을 위해 사용할 형식입니다.\n; plaintext: HTML 태그가 제거되고 엔티티가 치환된 위키텍스트입니다.\n; wikitext: 구문 분석되지 않은 위키텍스트입니다.\n; html: HTML입니다.\n; raw: 메시지 키와 변수입니다.\n; none: 텍스트 없이 오류 코드만 출력합니다.\n; bc: 미디어위키 1.29 이전에 사용된 형식입니다. <var>errorlang</var> 및 <var>errorsuselocal</var>은 무시됩니다.",
+       "apihelp-main-param-errorlang": "경고와 오류를 위해 사용할 언어입니다. <kbd>siprop=languages</kbd>가 포함된 <kbd>[[Special:ApiHelp/query+siteinfo|action=query&meta=siteinfo]]</kbd>는 언어 코드의 목록을 반환하고, <kbd>content</kbd>를 지정하면 이 위키의 내용 상의 언어를 사용하며, <kbd>uselang</kbd>을 지정하면 <var>uselang</var> 변수와 동일한 값을 사용합니다.",
+       "apihelp-main-param-errorsuselocal": "지정하면 오류 텍스트가 {{ns:MediaWiki}} 이름공간에서 지역적으로 정의된 메시지를 사용합니다.",
        "apihelp-block-description": "사용자를 차단합니다.",
        "apihelp-block-param-user": "차단할 사용자 이름, IP 주소, 또는 IP 주소 대역입니다. <var>$1userid</var>와(과) 함께 사용할 수 없습니다.",
        "apihelp-block-param-userid": "차단할 사용자 ID입니다. <var>$1user</var>와(과) 함께 사용할 수 없습니다.",
@@ -56,6 +61,7 @@
        "apihelp-clearhasmsg-example-1": "현재 계정의 <code>hasmsg</code> 플래그를 삭제합니다.",
        "apihelp-clientlogin-description": "상호작용 플로우를 이용하여 위키에 로그인합니다.",
        "apihelp-clientlogin-example-login": "사용자 <kbd>Example</kbd>, 비밀번호 <kbd>ExamplePassword</kbd>로 위키 로그인 과정을 시작합니다.",
+       "apihelp-clientlogin-example-login2": "<kbd>987654</kbd>의 <var>OATHToken</var>을 지정하여 2요소 인증을 위한 <samp>UI</samp> 응답 이후에 로그인을 계속합니다.",
        "apihelp-compare-description": "두 문서 간의 차이를 가져옵니다.\n\n대상이 되는 두 문서의 판 번호나 문서 제목 또는 문서 ID를 지정해야 합니다.",
        "apihelp-compare-param-fromtitle": "비교할 첫 이름.",
        "apihelp-compare-param-fromid": "비교할 첫 문서 ID.",
        "apihelp-protect-param-reason": "보호 또는 보호 해제의 이유.",
        "apihelp-protect-example-protect": "문서 보호",
        "apihelp-purge-param-forcelinkupdate": "링크 테이블을 업데이트합니다.",
+       "apihelp-query-param-prop": "조회된 페이지에 대해 가져올 속성입니다.",
+       "apihelp-query-param-list": "가져올 목록입니다.",
+       "apihelp-query-param-meta": "가져올 메타데이터입니다.",
+       "apihelp-query-param-indexpageids": "반환된 모든 페이지 ID를 나열하는 부가적인 페이지 ID 섹션을 포함합니다.",
+       "apihelp-query-param-export": "기존의 페이지나 생성된 페이지들 전체의 현재 판들을 내보냅니다.",
+       "apihelp-query-param-exportnowrap": "XML 결과물로 래핑하지 않고 엑스포트 XML을 반환합니다. $1export와만 같이 사용할 수 있습니다.",
+       "apihelp-query-param-iwurl": "제목이 인터위키 링크인 경우 전체 URL을 가져올지의 여부입니다.",
+       "apihelp-query-param-rawcontinue": "계속하기 위해 순수 <samp>query-continue</samp> 데이터를 반환합니다.",
        "apihelp-query+allcategories-description": "모든 분류를 열거합니다.",
        "apihelp-query+allcategories-param-prefix": "이 값으로 시작하는 모든 분류 제목을 검색합니다.",
        "apihelp-query+allcategories-param-dir": "정렬 방향.",
        "apihelp-query+allfileusages-example-unique-generator": "모든 파일 제목을 가져오되, 존재하지 않는 항목을 표시합니다.",
        "apihelp-query+allfileusages-example-generator": "파일을 포함하는 문서를 가져옵니다.",
        "apihelp-query+allimages-description": "모든 그림을 순차적으로 열거합니다.",
+       "apihelp-query+allimages-example-recent": "최근 업로드된 파일 보이기, [[Special:NewFiles]]와 유사함.",
        "apihelp-query+alllinks-paramvalue-prop-title": "링크의 제목을 추가합니다.",
        "apihelp-query+alllinks-param-namespace": "열거할 이름공간.",
        "apihelp-query+alllinks-param-limit": "반환할 총 항목 수입니다.",
        "apihelp-query+search-paramvalue-prop-timestamp": "문서가 마지막으로 편집된 시기의 타임스탬프를 추가합니다.",
        "apihelp-query+search-example-simple": "<kbd>meaning</kbd>을 검색합니다.",
        "apihelp-query+search-example-text": "<kbd>meaning</kbd>의 텍스트를 검색합니다.",
+       "apihelp-query+siteinfo-description": "사이트의 전반적인 정보를 반환합니다.",
        "apihelp-query+siteinfo-param-prop": "가져올 정보:",
-       "apihelp-query+siteinfo-paramvalue-prop-general": "전반적인 시스템 정보.",
+       "apihelp-query+siteinfo-paramvalue-prop-general": "전반적인 시스템 정보입니다.",
+       "apihelp-query+siteinfo-paramvalue-prop-namespaces": "등록된 이름공간 및 기본 이름의 목록입니다.",
+       "apihelp-query+siteinfo-paramvalue-prop-namespacealiases": "등록된 이름공간 별칭의 목록입니다.",
+       "apihelp-query+siteinfo-paramvalue-prop-specialpagealiases": "특수 문서의 별칭 목록입니다.",
+       "apihelp-query+siteinfo-paramvalue-prop-magicwords": "매직 워드와 별칭의 목록입니다.",
        "apihelp-query+siteinfo-paramvalue-prop-statistics": "사이트 통계를 반환합니다.",
        "apihelp-query+siteinfo-paramvalue-prop-interwikimap": "인터위키 맵을 반환합니다. (<var>$1inlanguagecode</var>를 사용하여 필터링 및 지역화 선택 가능)",
+       "apihelp-query+siteinfo-paramvalue-prop-dbrepllag": "반복 지연이 가장 높은 데이터베이스 서버를 반환합니다.",
        "apihelp-query+siteinfo-paramvalue-prop-usergroups": "사용자 그룹 및 관련 권한을 반환합니다.",
        "apihelp-query+siteinfo-paramvalue-prop-libraries": "위키에 설치된 라이브러리를 반환합니다.",
        "apihelp-query+siteinfo-paramvalue-prop-extensions": "위키에 설치된 확장 기능을 반환합니다.",
        "apihelp-query+siteinfo-paramvalue-prop-skins": "사용 중인 모든 스킨의 목록을 반환합니다. (<var>$1inlanguagecode</var>를 사용하여 지역화 선택이 가능하며, 이를 사용하지 않으면 본문의 언어를 사용함)",
        "apihelp-query+siteinfo-paramvalue-prop-extensiontags": "파서 확장 태그의 목록을 반환합니다.",
        "apihelp-query+siteinfo-paramvalue-prop-functionhooks": "파서 함수 훅의 목록을 반환합니다.",
+       "apihelp-query+siteinfo-paramvalue-prop-showhooks": "예약된 모든 훅(<var>[[mw:Manual:$wgHooks|$wgHooks]]</var>의 내용)의 목록을 반환합니다.",
        "apihelp-query+siteinfo-paramvalue-prop-variables": "변수 ID의 목록을 반환합니다.",
        "apihelp-query+siteinfo-paramvalue-prop-protocols": "외부 링크에 허용된 프로토콜의 목록을 반환합니다.",
        "apihelp-query+siteinfo-paramvalue-prop-defaultoptions": "사용자 환경 설정의 기본값을 반환합니다.",
        "apihelp-query+siteinfo-paramvalue-prop-uploaddialog": "업로드 대화 상자 구성을 반환합니다.",
+       "apihelp-query+siteinfo-param-filteriw": "인터위키 맵의 로컬 또는 로컬이 아닌 항목만 반환합니다.",
+       "apihelp-query+siteinfo-param-showalldb": "가장 지연이 심한 서버뿐 아니라, 모든 데이터베이스 서버를 나열합니다.",
        "apihelp-query+siteinfo-param-numberingroup": "사용자 그룹의 사용자 수를 나열합니다.",
+       "apihelp-query+siteinfo-param-inlanguagecode": "지역화된 언어 이름 (가능한 경우) 및 스킨 이름의 언어 코드입니다.",
        "apihelp-query+siteinfo-example-simple": "사이트 정보를 가져옵니다.",
        "apihelp-query+siteinfo-example-interwiki": "로컬 인터위키 접두사 목록을 가져옵니다.",
+       "apihelp-query+siteinfo-example-replag": "현재의 반복 지연을 검사합니다.",
        "apihelp-query+tags-param-limit": "나열할 태그의 최대 수.",
        "apihelp-query+tags-paramvalue-prop-name": "태그의 이름을 추가합니다.",
        "apihelp-query+tags-paramvalue-prop-description": "태그의 설명을 추가합니다.",
        "apihelp-query+tags-paramvalue-prop-hitcount": "판의 수와 이 판을 가진 로그 엔트리를 추가합니다.",
        "apihelp-query+templates-param-limit": "반환할 틀 수.",
        "apihelp-query+tokens-param-type": "요청할 토큰의 종류.",
+       "apihelp-query+tokens-example-simple": "csrf 토큰을 가져옵니다. (기본값)",
        "apihelp-query+transcludedin-paramvalue-prop-pageid": "각 문서의 페이지 ID.",
        "apihelp-query+transcludedin-paramvalue-prop-title": "각 문서의 제목.",
        "apihelp-query+transcludedin-paramvalue-prop-redirect": "문서가 넘겨주기이면 표시합니다.",
        "apihelp-revisiondelete-description": "판을 삭제하거나 되살립니다.",
        "apihelp-revisiondelete-param-reason": "삭제 또는 복구 이유.",
        "apihelp-rollback-param-tags": "되돌리기를 적용하기 위해 태그합니다.",
+       "apihelp-setpagelanguage-description": "문서의 언어를 변경합니다.",
+       "apihelp-setpagelanguage-description-disabled": "이 위키에서 문서의 언어 변경은 허용되지 않습니다.\n\n이 동작을 사용하려면 <var>[[mw:Manual:$wgPageLanguageUseDB|$wgPageLanguageUseDB]]</var>을 활성화하십시오.",
+       "apihelp-setpagelanguage-param-reason": "변경 이유.",
+       "apihelp-setpagelanguage-example-language": "<kbd>Main Page</kbd>의 언어를 바스크어로 변경합니다.",
        "apihelp-stashedit-param-sectiontitle": "새 문단을 위한 제목.",
        "apihelp-stashedit-param-text": "문서 내용.",
        "apihelp-stashedit-param-contentmodel": "새 콘텐츠의 콘텐츠 모델.",
        "apihelp-userrights-param-userid": "사용자 ID.",
        "apihelp-validatepassword-param-email": "계정 생성을 테스트할 때 사용할 이메일 주소입니다.",
        "apihelp-validatepassword-param-realname": "계정 생성을 테스트할 때 사용할 실명입니다.",
-       "apihelp-rawfm-description": "출력 데이터, 디버깅 요소를 포함, (HTML에 포함된)JSON형식.",
+       "apihelp-json-description": "데이터를 JSON 형식으로 출력합니다.",
+       "apihelp-json-param-formatversion": "출력 형식:\n;1:하위 호환 포맷 (XML 스타일 불린, 콘텐츠 노드를 위한 <samp>*</samp> 키 등).\n;2:실험적인 모던 포맷. 상세 내용은 바뀔 수 있습니다!\n;latest:최신 포맷(현재 <kbd>2</kbd>)을 이용하지만 경고 없이 바뀔 수 있습니다.",
+       "apihelp-jsonfm-description": "데이터를 JSON 포맷으로 출력합니다. (HTML의 가독성 증가)",
+       "apihelp-rawfm-description": "디버깅 요소를 포함하여 데이터를 JSON 형식으로 출력합니다. (HTML의 가독성 증가)",
        "apihelp-xml-param-includexmlnamespace": "지정하면 XML 이름공간을 추가합니다.",
        "api-format-title": "미디어위키 API 결과",
+       "api-pageset-param-titles": "작업할 제목의 목록입니다.",
+       "api-pageset-param-pageids": "작업할 페이지 ID의 목록입니다.",
+       "api-pageset-param-revids": "작업할 판 ID의 목록입니다.",
+       "api-pageset-param-generator": "특정 쿼리 모듈을 실행함으로써 작업할 페이지의 목록입니다.\n\n<strong>참고:</strong> 발생기 변수명은 \"g\"로 시작해야 합니다. 예시를 참고하십시오.",
        "api-help-title": "미디어위키 API 도움말",
        "api-help-lead": "이 페이지는 자동으로 생성된 미디어위키 API 도움말 문서입니다.\n\n설명 문서 및 예시: https://www.mediawiki.org/wiki/API",
        "api-help-main-header": "메인 모듈",
        "api-help-param-integer-min": "{{PLURAL:$1|1=값|2=값들}}은 $2 이상이어야 합니다.",
        "api-help-param-integer-max": "{{PLURAL:$1|1=값|2=값들}}은 $3 이하여야 합니다.",
        "api-help-param-integer-minmax": "{{PLURAL:$1|1=값|2=값들}}은 $2와 $3 사이여야 합니다.",
+       "api-help-param-multi-separate": "<kbd>|</kbd> 또는 [[Special:ApiHelp/main#main/datatypes|대안]]으로 값을 구분합니다.",
        "api-help-param-multi-max": "값들의 최대 수는 {{PLURAL:$1|$1}}입니다. (봇의 경우 {{PLURAL:$2|$2}})",
        "api-help-param-default": "기본값: $1",
        "api-help-param-default-empty": "기본값: <span class=\"apihelp-empty\">(비어 있음)</span>",
+       "api-help-param-token": "\"$1\" 토큰은 [[Special:ApiHelp/query+tokens|action=query&meta=tokens]]에서 가져옵니다",
        "api-help-param-token-webui": "호환성을 위해, 웹 UI에 사용된 토큰도 허용합니다.",
        "api-help-param-continue": "더 많은 결과를 이용할 수 있을 때, 계속하려면 이것을 사용하십시오.",
        "api-help-param-no-description": "<span class=\"apihelp-empty\">(설명 없음)</span>",
        "api-help-permissions-granted-to": "{{PLURAL:$1|다음 그룹에 부여됨}}: $2",
        "api-help-right-apihighlimits": "API 쿼리에서 더 높은 제한 사용 (느린 쿼리: $1, 빠른 쿼리: $2) 느린 쿼리에 대한 제한은 다중값 매개변수에도 적용됩니다.",
        "api-help-open-in-apisandbox": "<small>[연습장에서 열기]</small>",
+       "api-help-authmanagerhelper-request": "<kbd>amirequestsfor=$1</kbd>을(를) 지정하여 <kbd>[[Special:ApiHelp/query+authmanagerinfo|action=query&meta=authmanagerinfo]]</kbd>가 반환한 <samp>id</samp>를 통해 이 인증 요청을 사용합니다.",
        "api-help-authmanagerhelper-messageformat": "반환 메시지에 사용할 형식.",
+       "api-help-authmanagerhelper-additional-params": "이 모듈은 사용 가능한 인증 요청에 따라 추가 변수를 허용합니다. 사용 가능한 요청 및 사용되는 필드를 결정하려면 <kbd>amirequestsfor=$1</kbd>(또는 해당되는 경우 이 모듈의 과거 응답)과 함께 <kbd>[[Special:ApiHelp/query+authmanagerinfo|action=query&meta=authmanagerinfo]]</kbd>을(를) 사용하십시오.",
        "apierror-articleexists": "작성하려는 문서가 이미 만들어져 있습니다.",
        "apierror-autoblocked": "사용자의 IP 주소는 차단된 사용자에 의해 사용되었으므로 자동으로 차단된 상태입니다.",
        "apierror-badgenerator-unknown": "알 수 없는 <kbd>generator=$1</kbd>.",
        "apierror-invalidsha1hash": "제공된 SHA1 해시가 유효하지 않습니다.",
        "apierror-invalidtitle": "잘못된 제목 \"$1\".",
        "apierror-invaliduser": "잘못된 사용자 이름 \"$1\".",
+       "apierror-invaliduserid": "<var>$1</var> 사용자 ID는 유효하지 않습니다.",
        "apierror-maxlag-generic": "데이터베이스 서버 대기 중: $1 {{PLURAL:$1|초}} 지연되었습니다.",
        "apierror-maxlag": "$2 대기 중: $1 {{PLURAL:$1|초}} 지연되었습니다.",
        "apierror-missingparam": "<var>$1</var> 변수는 설정해야 합니다.",
        "apierror-nosuchuserid": "ID $1에 해당하는 사용자가 없습니다.",
        "apierror-notarget": "이 작업을 위한 유효한 대상을 지정하지 않았습니다.",
        "apierror-pagecannotexist": "이름공간은 실제 페이지를 허용하지 않습니다.",
+       "apierror-pagelang-disabled": "이 위키에서 문서의 언어 변경은 허용되지 않습니다.",
        "apierror-permissiondenied": "$1에 대한 권한이 없습니다.",
        "apierror-permissiondenied-generic": "권한이 없습니다.",
        "apierror-permissiondenied-unblock": "사용자의 차단을 해제할 권한이 없습니다.",
index 4a98f4a..a803645 100644 (file)
        "apihelp-revisiondelete-description": "Versioune läschen a restauréieren.",
        "apihelp-revisiondelete-param-reason": "Grond fir ze Läschen oder ze Restauréieren.",
        "apihelp-rsd-example-simple": "Den RSD-Schema exportéieren",
+       "apihelp-setpagelanguage-description": "D'Sprooch vun enger Säit änneren",
+       "apihelp-setpagelanguage-param-reason": "Grond fir d'Ännerung.",
+       "apihelp-setpagelanguage-example-language": "Ännert d'Sprooch vun der <kbd>Main Page</kbd> op baskesch.",
        "apihelp-stashedit-param-title": "Titel vun der Säit déi geännert gëtt.",
        "apihelp-stashedit-param-sectiontitle": "Den Titel fir en neien Abschnitt.",
        "apihelp-stashedit-param-text": "Inhalt vun der Säit",
        "apierror-import-unknownerror": "Onbekannte Feeler beim Import: $1\nf",
        "apierror-invalidcategory": "Den Numm vun der Kategorie deen Dir aginn hutt ass net valabel.",
        "apierror-invalidtitle": "Schlechten Titel \"$1\".",
+       "apierror-invaliduserid": "Benotzer ID <var>$1</var> ass net valabel.",
        "apierror-missingtitle": "D'Säit déi Dir spezifizéiert hutt gëtt et net.",
        "apierror-missingtitle-byname": "D'Säit $1 gëtt et net.",
        "apierror-moduledisabled": "De(n) <kbd>$1</kbd> Modul gouf ausgeschalt.",
        "apierror-notarget": "Dir hutt kee valabelt Zil fir dës Aktioun spezifizéiert.",
        "apierror-notpatrollable": "D'Versioun r$1 kann net nogekuckt gi well se ze al ass.",
        "apierror-pagecannotexist": "Nummraum erlaabt keng aktuell Säiten.",
+       "apierror-pagelang-disabled": "D'Ännere vun der Sprooch vun enger Säit ass op dëser Wiki net erlaabt.",
        "apierror-permissiondenied-generic": "Autorisatioun refuséiert.",
        "apierror-permissiondenied-unblock": "Dir hutt net d'Recht fir d'Spär vu Benotzer opzehiewen.",
        "apierror-readonly": "D'Wiki kann elo just geliest ginn.",
index c1a71a4..732991a 100644 (file)
@@ -35,6 +35,7 @@
        "apihelp-block-param-anononly": "Alleen anonieme gebruikers blokkeren (uitschakelen van anonieme bewerkingen via dit IP-adres)",
        "apihelp-block-param-nocreate": "Voorkom registeren van accounts.",
        "apihelp-block-param-autoblock": "Blokkeer automatisch het laatst gebruikte IP-adres en ieder volgend IP-adres van waaruit ze proberen aan te melden.",
+       "apihelp-block-param-hidename": "Verberg de gebruikersnaam uit het blokkeerlogboek. (Vereist het <code>hideuser</code> recht).",
        "apihelp-block-param-reblock": "De huidige blokkade aanpassen als de gebruiker al geblokkeerd is.",
        "apihelp-block-param-watchuser": "De gebruikerspagina en overlegpagina van de gebruiker of het IP-adres volgen.",
        "apihelp-block-example-ip-simple": "Het IP-adres <kbd>192.0.2.5</kbd> voor drie dagen blokkeren met <kbd>First strike</kbd> als opgegeven reden.",
@@ -49,6 +50,7 @@
        "apihelp-createaccount-param-name": "Gebruikersnaam.",
        "apihelp-createaccount-param-email": "E-mailadres van de gebruiker (optioneel).",
        "apihelp-createaccount-param-realname": "Echte naam van de gebruiker (optioneel).",
+       "apihelp-createaccount-param-language": "Taalcode om als standaard in te stellen voor de gebruiker (optioneel, standaard de inhoudstaal).",
        "apihelp-createaccount-example-pass": "Maak gebruiker <kbd>testuser</kbd> aan met wachtwoord <kbd>test123</kbd>.",
        "apihelp-createaccount-example-mail": "Maak gebruiker <kbd>testmailuser</kbd> aan en e-mail een willekeurig gegenereerd wachtwoord.",
        "apihelp-delete-description": "Een pagina verwijderen.",
index 9d467cc..85e24e4 100644 (file)
        "apihelp-help-example-query": "{{doc-apihelp-example|help}}",
        "apihelp-imagerotate-description": "{{doc-apihelp-description|imagerotate}}",
        "apihelp-imagerotate-param-rotation": "{{doc-apihelp-param|imagerotate|rotation}}",
+       "apihelp-imagerotate-param-tags": "{{doc-apihelp-param|imagerotate|tags}}",
        "apihelp-imagerotate-example-simple": "{{doc-apihelp-example|imagerotate}}",
        "apihelp-imagerotate-example-generator": "{{doc-apihelp-example|imagerotate}}",
        "apihelp-import-description": "{{doc-apihelp-description|import}}",
        "apihelp-query+usercontribs-param-end": "{{doc-apihelp-param|query+usercontribs|end}}",
        "apihelp-query+usercontribs-param-user": "{{doc-apihelp-param|query+usercontribs|user}}",
        "apihelp-query+usercontribs-param-userprefix": "{{doc-apihelp-param|query+usercontribs|userprefix}}",
+       "apihelp-query+usercontribs-param-userids": "{{doc-apihelp-param|query+usercontribs|userids}}",
        "apihelp-query+usercontribs-param-namespace": "{{doc-apihelp-param|query+usercontribs|namespace}}",
        "apihelp-query+usercontribs-param-prop": "{{doc-apihelp-param|query+usercontribs|prop|paramvalues=1}}",
        "apihelp-query+usercontribs-paramvalue-prop-ids": "{{doc-apihelp-paramvalue|query+usercontribs|prop|ids}}",
        "apihelp-revisiondelete-param-show": "{{doc-apihelp-param|revisiondelete|show}}",
        "apihelp-revisiondelete-param-suppress": "{{doc-apihelp-param|revisiondelete|suppress}}",
        "apihelp-revisiondelete-param-reason": "{{doc-apihelp-param|revisiondelete|reason}}",
+       "apihelp-revisiondelete-param-tags": "{{doc-apihelp-param|revisiondelete|tags}}",
        "apihelp-revisiondelete-example-revision": "{{doc-apihelp-example|revisiondelete}}",
        "apihelp-revisiondelete-example-log": "{{doc-apihelp-example|revisiondelete}}",
        "apihelp-rollback-description": "{{doc-apihelp-description|rollback}}",
        "apihelp-setnotificationtimestamp-example-page": "{{doc-apihelp-example|setnotificationtimestamp}}",
        "apihelp-setnotificationtimestamp-example-pagetimestamp": "{{doc-apihelp-example|setnotificationtimestamp}}",
        "apihelp-setnotificationtimestamp-example-allpages": "{{doc-apihelp-example|setnotificationtimestamp}}",
+       "apihelp-setpagelanguage-description": "{{doc-apihelp-description|setpagelanguage}}",
+       "apihelp-setpagelanguage-description-disabled": "{{doc-apihelp-description|setpagelanguage|info=This message is used when changing the language of a page is not allowed on the wiki because <var>[[mw:Manual:$wgPageLanguageUseDB|$wgPageLanguageUseDB]]</var> is not enabled.|seealso={{msg-mw|apihelp-setpagelanguage-description}}}}",
+       "apihelp-setpagelanguage-param-title": "{{doc-apihelp-param|setpagelanguage|title}}",
+       "apihelp-setpagelanguage-param-pageid": "{{doc-apihelp-param|setpagelanguage|pageid}}",
+       "apihelp-setpagelanguage-param-lang": "{{doc-apihelp-param|setpagelanguage|lang}}",
+       "apihelp-setpagelanguage-param-reason": "{{doc-apihelp-param|setpagelanguage|reason}}",
+       "apihelp-setpagelanguage-param-tags": "{{doc-apihelp-param|setpagelanguage|tags}}",
+       "apihelp-setpagelanguage-example-language": "{{doc-apihelp-example|setpagelanguage}}",
+       "apihelp-setpagelanguage-example-default": "{{doc-apihelp-example|setpagelanguage}}",
        "apihelp-stashedit-description": "{{doc-apihelp-description|stashedit}}",
        "apihelp-stashedit-param-title": "{{doc-apihelp-param|stashedit|title}}",
        "apihelp-stashedit-param-section": "{{doc-apihelp-param|stashedit|section}}",
        "apihelp-tag-param-add": "{{doc-apihelp-param|tag|add}}",
        "apihelp-tag-param-remove": "{{doc-apihelp-param|tag|remove}}",
        "apihelp-tag-param-reason": "{{doc-apihelp-param|tag|reason}}",
+       "apihelp-tag-param-tags": "{{doc-apihelp-param|tag|tags}}",
        "apihelp-tag-example-rev": "{{doc-apihelp-example|tag}}",
        "apihelp-tag-example-log": "{{doc-apihelp-example|tag}}",
        "apihelp-tokens-description": "{{doc-apihelp-description|tokens}}",
        "apierror-invalidtitle": "{{doc-apierror}}\n\nParameters:\n* $1 - Title that is invalid",
        "apierror-invalidurlparam": "{{doc-apierror}}\n\nParameters:\n* $1 - Module parameter prefix, e.g. \"bl\".\n* $2 - Key\n* $3 - Value.",
        "apierror-invaliduser": "{{doc-apierror}}\n\nParameters:\n* $1 - User name that is invalid.",
+       "apierror-invaliduserid": "{{doc-apierror}}",
        "apierror-maxlag-generic": "{{doc-apierror}}\n\nParameters:\n* $1 - Database is lag in seconds.",
        "apierror-maxlag": "{{doc-apierror}}\n\nParameters:\n* $1 - Database lag in seconds.\n* $2 - Database server that is lagged.",
        "apierror-mimesearchdisabled": "{{doc-apierror}}",
        "apierror-opensearch-json-warnings": "{{doc-apierror}}",
        "apierror-pagecannotexist": "{{doc-apierror}}",
        "apierror-pagedeleted": "{{doc-apierror}}",
+       "apierror-pagelang-disabled": "{{doc-apierror}}",
        "apierror-paramempty": "{{doc-apierror}}\n\nParameters:\n* $1 - Parameter name.",
        "apierror-parsetree-notwikitext": "{{doc-apierror}}",
        "apierror-parsetree-notwikitext-title": "{{doc-apierror}}\n\nParameters:\n* $1 - Page title.\n* $2 - Content model.",
index c012bef..a078f1b 100644 (file)
@@ -21,7 +21,8 @@
                        "Irus",
                        "MaxBioHazard",
                        "Kareyac",
-                       "Mailman"
+                       "Mailman",
+                       "Ping08"
                ]
        },
        "apihelp-main-description": "<div class=\"hlist plainlinks api-main-links\">\n* [[mw:API:Main_page|Документация]]\n* [[mw:API:FAQ|ЧаВО]]\n* [https://lists.wikimedia.org/mailman/listinfo/mediawiki-api Почтовая рассылка]\n* [https://lists.wikimedia.org/mailman/listinfo/mediawiki-api-announce Новости API]\n* [https://phabricator.wikimedia.org/maniphest/query/GebfyV4uCaLd/#R Ошибки и запросы]\n</div>\n<strong>Статус:</strong> Все отображаемые на этой странице функции должны работать, однако API находится в статусе активной разработки и может измениться в любой момент. Подпишитесь на [https://lists.wikimedia.org/pipermail/mediawiki-api-announce/ почтовую рассылку mediawiki-api-announce], чтобы быть в курсе обновлений.\n\n<strong>Ошибочные запросы:</strong> Если API получает запрос с ошибкой, вернётся заголовок HTTP с ключом «MediaWiki-API-Error», после чего значение заголовка и код ошибки будут отправлены обратно и установлены в то же значение. Более подробную информацию см. [[mw:API:Errors_and_warnings|API: Ошибки и предупреждения]].\n\n<strong>Тестирование:</strong> для удобства тестирования API-запросов, см. [[Special:ApiSandbox]].",
        "api-help-permissions-granted-to": "{{PLURAL:$1|Granted to}}: $2",
        "apierror-integeroutofrange-abovemax": "<var>$1</var> не может быть более $2 (на $3) для пользователей.",
        "apierror-nosuchuserid": "Нет пользователя с ID $1.",
+       "apierror-pagelang-disabled": "Меняется язык страницы не допускается в этой Вики.",
        "apierror-protect-invalidaction": "Недопустимый тип защиты \"$1\".",
        "apierror-systemblocked": "Вы были заблокированы автоматически Медиавики.",
        "apierror-unknownformat": "Неизвестный Формат \"$1\".",
        "apierror-urlparamnormal": "Не могли нормализовать параметры изображения для $1.",
+       "api-feed-error-title": "Ошибка ($1)",
        "api-credits-header": "Создатели"
 }
index 60299ca..4ba61a9 100644 (file)
        "apihelp-help-example-query": "两个查询子模块的帮助。",
        "apihelp-imagerotate-description": "旋转一幅或多幅图像。",
        "apihelp-imagerotate-param-rotation": "顺时针旋转图像的度数。",
+       "apihelp-imagerotate-param-tags": "要在上传日志中应用到实体的标签。",
        "apihelp-imagerotate-example-simple": "<kbd>90</kbd>度旋转<kbd>File:Example.png</kbd>。",
        "apihelp-imagerotate-example-generator": "将<kbd>Category:Flip</kbd>之中的所有图像旋转<kbd>180</kbd>度。",
        "apihelp-import-description": "从另一个wiki或从一个XML文件导入页面。\n\n注意当发送一个用于<var>xml</var>参数的文件时,HTTP POST必须作为一次文件上传完成(也就是使用multipart/form-data)。",
        "apihelp-query+usercontribs-param-limit": "返回贡献的最大数量。",
        "apihelp-query+usercontribs-param-start": "返回的起始时间戳。",
        "apihelp-query+usercontribs-param-end": "返回的最终时间戳。",
-       "apihelp-query+usercontribs-param-user": "要检索贡献的用户。",
-       "apihelp-query+usercontribs-param-userprefix": "取得所有用户名以这个值开头的用户的贡献。覆盖$1user。",
+       "apihelp-query+usercontribs-param-user": "要检索贡献的用户。不能与<var>$1userids</var>或<var>$1userprefix</var>一起使用。",
+       "apihelp-query+usercontribs-param-userprefix": "取得所有用户名以这个值开头的用户的贡献。不能与<var>$1user</var>或<var>$1userids</var>一起使用。",
+       "apihelp-query+usercontribs-param-userids": "要检索贡献的用户ID。不能与<var>$1user</var>或<var>$1userprefix</var>一起使用。",
        "apihelp-query+usercontribs-param-namespace": "只列出这些名字空间的贡献。",
        "apihelp-query+usercontribs-param-prop": "包含额外的信息束:",
        "apihelp-query+usercontribs-paramvalue-prop-ids": "添加页面ID和修订ID。",
        "apihelp-revisiondelete-param-show": "每次修订要恢复显示的东西。",
        "apihelp-revisiondelete-param-suppress": "是否对管理员及其他人禁止数据。",
        "apihelp-revisiondelete-param-reason": "删除或恢复的原因。",
+       "apihelp-revisiondelete-param-tags": "要在删除日志中应用到实体的标签。",
        "apihelp-revisiondelete-example-revision": "隐藏<kbd>首页</kbd>的修订版本<kbd>12345</kbd>的内容。",
        "apihelp-revisiondelete-example-log": "隐藏日志记录<kbd>67890</kbd>上的所有数据,原因<kbd>BLP violation</kbd>。",
        "apihelp-rollback-description": "撤销对页面的最近编辑。\n\n如果最近编辑页面的用户在一行中进行多次编辑,所有编辑将被回退。",
        "apihelp-setnotificationtimestamp-example-page": "重置用于<kbd>Main page</kbd>的通知状态。",
        "apihelp-setnotificationtimestamp-example-pagetimestamp": "设置<kbd>Main page</kbd>的通知时间戳,这样所有从2012年1月1日起的编辑都会是未复核的。",
        "apihelp-setnotificationtimestamp-example-allpages": "重置在<kbd>{{ns:user}}</kbd>名字空间中的页面的通知状态。",
+       "apihelp-setpagelanguage-description": "更改页面的语言。",
+       "apihelp-setpagelanguage-description-disabled": "此wiki不允许更改页面的语言。\n\n启用<var>[[mw:Manual:$wgPageLanguageUseDB|$wgPageLanguageUseDB]]</var>以使用此操作。",
+       "apihelp-setpagelanguage-param-title": "您希望更改语言的页面标题。不能与<var>$1pageid</var>一起使用。",
+       "apihelp-setpagelanguage-param-pageid": "您希望更改语言的页面ID。不能与<var>$1title</var>一起使用。",
+       "apihelp-setpagelanguage-param-lang": "更改页面的目标语言的语言代码。使用<kbd>default</kbd>以重置页面为wiki的默认内容语言。",
+       "apihelp-setpagelanguage-param-reason": "更改原因。",
+       "apihelp-setpagelanguage-param-tags": "要应用到此操作导致的日志记录的更改标签。",
+       "apihelp-setpagelanguage-example-language": "更改<kbd>Main Page</kbd>的语言为巴斯克语。",
+       "apihelp-setpagelanguage-example-default": "更改ID为123的页面的语言为wiki的默认内容语言。",
        "apihelp-stashedit-description": "在分享的缓存中准备一次编辑。\n\n这是为了从编辑表单中通过AJAX使用,以改进页面保存的性能。",
        "apihelp-stashedit-param-title": "已开始编辑的页面标题。",
        "apihelp-stashedit-param-section": "段落数。<kbd>0</kbd>用于首段,<kbd>new</kbd>用于新的段落。",
        "apihelp-tag-param-add": "要添加的标签。只有手动定义的标签可以添加。",
        "apihelp-tag-param-remove": "要移除的标签。只有手动定义或完全不明确的标签可以被移除。",
        "apihelp-tag-param-reason": "更改原因。",
+       "apihelp-tag-param-tags": "要应用到将被创建为此操作结果的日志实体的标签。",
        "apihelp-tag-example-rev": "将<kbd>vandalism</kbd>标签添加至修订ID 123,而不指定原因",
        "apihelp-tag-example-log": "从日志记录ID 123移除<kbd>spam</kbd>标签,原因为<kbd>Wrongly applied</kbd>",
        "apihelp-tokens-description": "获取可修改数据的操作的令牌。\n\n此模块被弃用以有利于[[Special:ApiHelp/query+tokens|action=query&meta=tokens]]。",
        "apierror-invalidtitle": "错误标题“$1”。",
        "apierror-invalidurlparam": "<var>$1urlparam</var>的值无效(<kbd>$2=$3</kbd>)。",
        "apierror-invaliduser": "无效用户名“$1”。",
+       "apierror-invaliduserid": "用户ID<var>$1</var>无效。",
        "apierror-maxlag-generic": "正在等待数据库服务器:已延迟$1{{PLURAL:$1|秒}}。",
        "apierror-maxlag": "正在等待$2:已延迟$1{{PLURAL:$1|秒}}。",
        "apierror-mimesearchdisabled": "MIME搜索在Miser模式中被禁用。",
        "apierror-opensearch-json-warnings": "警告不能以OpenSearch JSON格式表示。",
        "apierror-pagecannotexist": "名字空间不允许实际页面。",
        "apierror-pagedeleted": "在您取得页面时间戳以来,页面已被删除。",
+       "apierror-pagelang-disabled": "此wiki不允许更改页面的语言。",
        "apierror-paramempty": "参数<var>$1</var>不能为空。",
        "apierror-parsetree-notwikitext": "<kbd>prop=parsetree</kbd>只支持wiki文本内容。",
        "apierror-parsetree-notwikitext-title": "<kbd>prop=parsetree</kbd>只支持wiki文本内容。$1使用内容模型$2。",
        "apierror-ratelimited": "您已超过您的速率限制。请等待一段时间再试。",
        "apierror-readapidenied": "您需要读取权限以使用此模块。",
        "apierror-readonly": "此wiki目前为只读模式。",
+       "apierror-reauthenticate": "您在该会话中尚未经过验证,请重新验证。",
        "apierror-revdel-mutuallyexclusive": "同一字段不能同时用于<var>hide</var>和<var>show</var>。",
        "apierror-revdel-needtarget": "此修订版本删除类型需要目标标题。",
        "apierror-revdel-paramneeded": "需要<var>hide</var>和/或<var>show</var>的至少一个值。",
        "apierror-sectionreplacefailed": "不能合并更新的章节。",
        "apierror-sectionsnotsupported": "内容模型$1不支持章节。",
        "apierror-sectionsnotsupported-what": "章节不被$1所支持。",
+       "apierror-show": "不正确的参数——不可提供互斥值。",
        "apierror-siteinfo-includealldenied": "除非<var>$wgShowHostNames</var>为真,否则不能查看所有服务器的信息。",
        "apierror-sizediffdisabled": "大小差异在Miser模式中被禁用。",
        "apierror-spamdetected": "您的编辑被拒绝,因为它包含破坏性碎片:<code>$1</code>。",
index b7e45cc..9cce087 100644 (file)
  */
 
 /**
- * Temporary workaround for incorrect collation of Persian language ('fa') in ICU (bug T139110).
+ * Temporary workaround for incorrect collation of Persian language ('fa') in ICU 52 (bug T139110).
  *
- * 'ا' and 'و' should not be considered the same letter for the purposes of collation in Persian.
+ * All of the following will be considered separate letters for category headings in Persian:
+ *  - Characters 'و' 'ا' (often appear at the beginning of words)
+ *  - Characters 'ٲ' 'ٳ' (may appear at the beginning of words in loanwords)
+ *  - Characters 'ء' 'ئ' (don't appear at the beginning of words, but it's easier to implement)
  *
  * @since 1.29
  */
@@ -34,11 +37,14 @@ class CollationFa extends IcuCollation {
        }
 
        public function getPrimarySortKey( $string ) {
-               $firstLetter = mb_substr( $string, 0, 1 );
-               if ( $firstLetter === 'و' || $firstLetter === 'ا' ) {
+               $primary = parent::getPrimarySortKey( $string );
+               // We have to use a tertiary sortkey for everything with the primary sortkey of 2627.
+               // Otherwise, the "Remove duplicate prefixes" logic in IcuCollation would remove them.
+               // This matches sortkeys for the following characters: ء ئ ا و ٲ ٳ
+               if ( substr( $primary, 0, 2 ) === "\x26\x27" ) {
+                       wfDebug( "Using tertiary sortkey for '$string'\n" );
                        return $this->tertiaryCollator->getSortKey( $string );
                }
-
-               return parent::getPrimarySortKey( $string );
+               return $primary;
        }
 }
index babd00b..25d50d3 100644 (file)
@@ -182,7 +182,7 @@ class DiffEngine {
                        }
 
                        while ( $i < $len && !$changed[$i] ) {
-                               assert( $j < $other_len && ! $other_changed[$j] );
+                               assert( $j < $other_len && !$other_changed[$j] );
                                $i++;
                                $j++;
                                while ( $j < $other_len && $other_changed[$j] ) {
@@ -247,7 +247,7 @@ class DiffEngine {
                                                $i++;
                                        }
 
-                                       assert( $j < $other_len && ! $other_changed[$j] );
+                                       assert( $j < $other_len && !$other_changed[$j] );
                                        $j++;
                                        if ( $j < $other_len && $other_changed[$j] ) {
                                                $corresponding = $i;
index 0c12ebb..8034400 100644 (file)
@@ -23,6 +23,7 @@
  * @file
  * @ingroup SpecialPage
  */
+use MediaWiki\MediaWikiServices;
 
 /**
  * Imports a XML dump from a file (either from file upload, files on disk, or HTTP)
@@ -148,7 +149,8 @@ class ImportStreamSource implements ImportSource {
                # Look up the first interwiki prefix, and let the foreign site handle
                # subsequent interwiki prefixes
                $firstIwPrefix = strtok( $interwiki, ':' );
-               $firstIw = Interwiki::fetch( $firstIwPrefix );
+               $interwikiLookup = MediaWikiServices::getInstance()->getInterwikiLookup();
+               $firstIw = $interwikiLookup->fetch( $firstIwPrefix );
                if ( !$firstIw ) {
                        return Status::newFatal( 'importbadinterwiki' );
                }
index cedccd1..b3b7850 100644 (file)
        "config-profile": "Profilo dei diritti utente:",
        "config-profile-wiki": "Wiki aperto",
        "config-profile-no-anon": "Creazione utenza obbligatoria",
-       "config-profile-fishbowl": "Solo editori autorizzati",
+       "config-profile-fishbowl": "Solo utenti autorizzati",
        "config-profile-private": "Wiki privato",
        "config-profile-help": "I wiki funzionano meglio se si permette a molte persone di poterli modificare.\nIn MediaWiki, è semplice controllare le ultime modifiche, e ripristinare i danni causati da utenti inesperti o malintenzionati.\n\nTuttavia, molti hanno trovato MediaWiki essere utile in un'ampia varietà di ruoli, e a volte non è facile convincere tutti dei vantaggi della modalità wiki.\nPerciò, fa' la tua scelta.\n\nIl modello <strong>{{int:config-profile-wiki}}</strong> consente a chiunque di modificare, anche senza effettuare l'accesso.\nUn wiki con <strong>{{int:config-profile-no-anon}}</strong> offre una maggiore responsabilità, ma potrebbe scoraggiare i contributori occasionali.\n\nLo scenario <strong>{{int:config-profile-fishbowl}}</strong> consente agli utenti autorizzati di modificare, ma il pubblico può visualizzare le pagine, compresa la cronologia.\nUn <strong>{{int:config-profile-private}}</strong> consente solo agli utenti autorizzati di visualizzare le pagine, lo stesso gruppo può modificarle.\n\nConfigurazioni di diritti utente più complesse sono disponibili dopo l'installazione, vedi la  [https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:User_rights parte relativa del manuale].",
        "config-license": "Copyright e licenza:",
index 5f33ae0..651a332 100644 (file)
@@ -247,6 +247,11 @@ class RefreshLinksJob extends Job {
                        $parserOutput
                );
 
+               // For legacy hook handlers doing updates via LinksUpdateConstructed, make sure
+               // any pending writes they made get flushed before the doUpdate() calls below.
+               // This avoids snapshot-clearing errors in LinksUpdate::acquirePageLock().
+               $lbFactory->commitAndWaitForReplication( __METHOD__, $ticket );
+
                foreach ( $updates as $key => $update ) {
                        // FIXME: This code probably shouldn't be here?
                        // Needed by things like Echo notifications which need
index 41541ef..0c77a7b 100644 (file)
@@ -216,7 +216,7 @@ class FormatJson {
                        $count = 0;
                        $value =
                                preg_replace( '/,([ \t]*[}\]][^"\r\n]*([\r\n]|$)|[ \t]*[\r\n][ \t\r\n]*[}\]])/', '$1',
-                                       $value, - 1, $count );
+                                       $value, -1, $count );
                        if ( $count > 0 ) {
                                $result = json_decode( $value, $assoc );
                                if ( JSON_ERROR_NONE === json_last_error() ) {
index 8d3c6d9..01a9149 100644 (file)
@@ -275,8 +275,8 @@ class WANObjectCache implements IExpiringStore, LoggerAwareInterface {
                $checkKeysForAll = [];
                $checkKeysByKey = [];
                $checkKeysFlat = [];
-               foreach ( $checkKeys as $i => $keys ) {
-                       $prefixed = self::prefixCacheKeys( (array)$keys, self::TIME_KEY_PREFIX );
+               foreach ( $checkKeys as $i => $checkKeyGroup ) {
+                       $prefixed = self::prefixCacheKeys( (array)$checkKeyGroup, self::TIME_KEY_PREFIX );
                        $checkKeysFlat = array_merge( $checkKeysFlat, $prefixed );
                        // Is this check keys for a specific cache key, or for all keys being fetched?
                        if ( is_int( $i ) ) {
index 49d09a9..7f43436 100644 (file)
@@ -319,21 +319,6 @@ class RedisConnectionPool implements LoggerAwareInterface {
                }
        }
 
-       /**
-        * The redis extension throws an exception in response to various read, write
-        * and protocol errors. Sometimes it also closes the connection, sometimes
-        * not. The safest response for us is to explicitly destroy the connection
-        * object and let it be reopened during the next request.
-        *
-        * @param string $server
-        * @param RedisConnRef $cref
-        * @param RedisException $e
-        * @deprecated since 1.23
-        */
-       public function handleException( $server, RedisConnRef $cref, RedisException $e ) {
-               $this->handleError( $cref, $e );
-       }
-
        /**
         * The redis extension throws an exception in response to various read, write
         * and protocol errors. Sometimes it also closes the connection, sometimes
index 1ca9dac..79fc172 100644 (file)
@@ -547,18 +547,32 @@ class Parser {
                        $limitReport = str_replace( [ '-', '&' ], [ '‐', '&amp;' ], $limitReport );
                        $text .= "\n<!-- \n$limitReport-->\n";
 
-                       // Add on template profiling data
+                       // Add on template profiling data in human/machine readable way
                        $dataByFunc = $this->mProfiler->getFunctionStats();
                        uasort( $dataByFunc, function ( $a, $b ) {
                                return $a['real'] < $b['real']; // descending order
                        } );
-                       $profileReport = "Transclusion expansion time report (%,ms,calls,template)\n";
+                       $profileReport = [];
                        foreach ( array_slice( $dataByFunc, 0, 10 ) as $item ) {
-                               $profileReport .= sprintf( "%6.2f%% %8.3f %6d - %s\n",
+                               $profileReport[] = sprintf( "%6.2f%% %8.3f %6d %s",
                                        $item['%real'], $item['real'], $item['calls'],
                                        htmlspecialchars( $item['name'] ) );
                        }
-                       $text .= "\n<!-- \n$profileReport-->\n";
+                       $text .= "<!--\nTransclusion expansion time report (%,ms,calls,template)\n";
+                       $text .= implode( "\n", $profileReport ) . "\n-->\n";
+
+                       $this->mOutput->setLimitReportData( 'limitreport-timingprofile', $profileReport );
+
+                       // Add other cache related metadata
+                       if ( $wgShowHostnames ) {
+                               $this->mOutput->setLimitReportData( 'cachereport-origin', wfHostname() );
+                       }
+                       $this->mOutput->setLimitReportData( 'cachereport-timestamp',
+                               $this->mOutput->getCacheTime() );
+                       $this->mOutput->setLimitReportData( 'cachereport-ttl',
+                               $this->mOutput->getCacheExpiry() );
+                       $this->mOutput->setLimitReportData( 'cachereport-transientcontent',
+                               $this->mOutput->hasDynamicContent() );
 
                        if ( $this->mGeneratedPPNodeCount > $this->mOptions->getMaxGeneratedPPNodeCount() / 10 ) {
                                wfDebugLog( 'generated-pp-node-count', $this->mGeneratedPPNodeCount . ' ' .
@@ -2798,6 +2812,9 @@ class Parser {
                        case 'contentlanguage':
                                global $wgLanguageCode;
                                return $wgLanguageCode;
+                       case 'pagelanguage':
+                               $value = $pageLang->getCode();
+                               break;
                        case 'cascadingsources':
                                $value = CoreParserFunctions::cascadingsources( $this );
                                break;
@@ -4990,7 +5007,7 @@ class Parser {
                        $descQuery = false;
                        Hooks::run( 'BeforeParserFetchFileAndTitle',
                                [ $this, $title, &$options, &$descQuery ] );
-                       # Don't register it now, as ImageGallery does that later.
+                       # Don't register it now, as TraditionalImageGallery does that later.
                        $file = $this->fetchFileNoRegister( $title, $options );
                        $handler = $file ? $file->getHandler() : false;
 
@@ -5258,7 +5275,7 @@ class Parser {
                                                case 'framed':
                                                case 'thumbnail':
                                                        // use first appearing option, discard others.
-                                                       $validated = ! $seenformat;
+                                                       $validated = !$seenformat;
                                                        $seenformat = true;
                                                        break;
                                                default:
index bfaa4f7..7bf848f 100644 (file)
@@ -193,6 +193,9 @@ class ParserOutput extends CacheTime {
         */
        private $mLimitReportData = [];
 
+       /** @var array Parser limit report data for JSON */
+       private $mLimitReportJSData = [];
+
        /**
         * @var array $mParseStartTime Timestamps for getTimeSinceStart().
         */
@@ -411,6 +414,10 @@ class ParserOutput extends CacheTime {
                return $this->mLimitReportData;
        }
 
+       public function getLimitReportJSData() {
+               return $this->mLimitReportJSData;
+       }
+
        public function getTOCEnabled() {
                return $this->mTOCEnabled;
        }
@@ -1010,6 +1017,26 @@ class ParserOutput extends CacheTime {
         */
        public function setLimitReportData( $key, $value ) {
                $this->mLimitReportData[$key] = $value;
+
+               if ( is_array( $value ) ) {
+                       if ( array_keys( $value ) === [ 0, 1 ]
+                               && is_numeric( $value[0] )
+                               && is_numeric( $value[1] )
+                       ) {
+                               $data = [ 'value' => $value[0], 'limit' => $value[1] ];
+                       } else {
+                               $data = $value;
+                       }
+               } else {
+                       $data = $value;
+               }
+
+               if ( strpos( $key, '-' ) ) {
+                       list( $ns, $name ) = explode( '-', $key, 2 );
+                       $this->mLimitReportJSData[$ns][$name] = $data;
+               } else {
+                       $this->mLimitReportJSData[$key] = $data;
+               }
        }
 
        /**
index c5b2150..344dd8f 100644 (file)
@@ -40,11 +40,6 @@ class ExtensionRegistry {
         */
        const MERGE_STRATEGY = '_merge_strategy';
 
-       /**
-        * @var BagOStuff
-        */
-       protected $cache;
-
        /**
         * Array of loaded things, keyed by name, values are credits information
         *
@@ -90,16 +85,6 @@ class ExtensionRegistry {
                return self::$instance;
        }
 
-       public function __construct() {
-               // We use a try/catch because we don't want to fail here
-               // if $wgObjectCaches is not configured properly for APC setup
-               try {
-                       $this->cache = MediaWikiServices::getInstance()->getLocalServerObjectCache();
-               } catch ( MWException $e ) {
-                       $this->cache = new EmptyBagOStuff();
-               }
-       }
-
        /**
         * @param string $path Absolute path to the JSON file
         */
@@ -144,12 +129,19 @@ class ExtensionRegistry {
                        'mediawiki' => $wgVersion
                ];
 
+               // We use a try/catch because we don't want to fail here
+               // if $wgObjectCaches is not configured properly for APC setup
+               try {
+                       $cache = MediaWikiServices::getInstance()->getLocalServerObjectCache();
+               } catch ( MWException $e ) {
+                       $cache = new EmptyBagOStuff();
+               }
                // See if this queue is in APC
                $key = wfMemcKey(
                        'registration',
                        md5( json_encode( $this->queued + $versions ) )
                );
-               $data = $this->cache->get( $key );
+               $data = $cache->get( $key );
                if ( $data ) {
                        $this->exportExtractedData( $data );
                } else {
@@ -159,7 +151,7 @@ class ExtensionRegistry {
                        // did that, but it should be cached
                        $data['globals']['wgAutoloadClasses'] += $data['autoload'];
                        unset( $data['autoload'] );
-                       $this->cache->set( $key, $data, 60 * 60 * 24 );
+                       $cache->set( $key, $data, 60 * 60 * 24 );
                }
                $this->queued = [];
        }
index 674846d..833e38b 100644 (file)
@@ -97,8 +97,9 @@ abstract class RevDelList extends RevisionListBase {
         *
         * @param array $params Associative array of parameters. Members are:
         *     value:         ExtractBitParams() bitfield array
-        *     comment:       The log comment.
+        *     comment:       The log comment
         *     perItemStatus: Set if you want per-item status reports
+        *     tags:          The array of change tags to apply to the log entry
         * @return Status
         * @since 1.23 Added 'perItemStatus' param
         */
@@ -269,7 +270,8 @@ abstract class RevDelList extends RevisionListBase {
                                'comment' => $comment,
                                'ids' => $idsForLog,
                                'authorIds' => $authorIds,
-                               'authorIPs' => $authorIPs
+                               'authorIPs' => $authorIPs,
+                               'tags' => isset( $params['tags'] ) ? $params['tags'] : [],
                        ]
                );
 
@@ -327,6 +329,7 @@ abstract class RevDelList extends RevisionListBase {
         *     comment:         The log comment
         *     authorsIds:      The array of the user IDs of the offenders
         *     authorsIPs:      The array of the IP/anon user offenders
+        *     tags:            The array of change tags to apply to the log entry
         * @throws MWException
         */
        private function updateLog( $logType, $params ) {
@@ -349,6 +352,8 @@ abstract class RevDelList extends RevisionListBase {
                        'target_author_id' => $params['authorIds'],
                        'target_author_ip' => $params['authorIPs'],
                ] );
+               // Apply change tags to the log entry
+               $logEntry->setTags( $params['tags'] );
                $logId = $logEntry->insert();
                $logEntry->publish( $logId );
        }
index dd41a6e..d0e3a24 100644 (file)
@@ -75,10 +75,10 @@ class SearchHighlighter {
                        if ( preg_match( $spat, $text, $matches, PREG_OFFSET_CAPTURE, $start ) ) {
                                $epat = '';
                                foreach ( $matches as $key => $val ) {
-                                       if ( $key > 0 && $val[1] != - 1 ) {
+                                       if ( $key > 0 && $val[1] != -1 ) {
                                                if ( $key == 2 ) {
                                                        // see if this is an image link
-                                                       $ns = substr( $val[0], 2, - 1 );
+                                                       $ns = substr( $val[0], 2, -1 );
                                                        if ( $wgContLang->getNsIndex( $ns ) != NS_FILE ) {
                                                                break;
                                                        }
@@ -252,10 +252,10 @@ class SearchHighlighter {
 
                // $snippets = array_map( 'htmlspecialchars', $extended );
                $snippets = $extended;
-               $last = - 1;
+               $last = -1;
                $extract = '';
                foreach ( $snippets as $index => $line ) {
-                       if ( $last == - 1 ) {
+                       if ( $last == -1 ) {
                                $extract .= $line; // first line
                        } elseif ( $last + 1 == $index
                                && $offsets[$last] + strlen( $snippets[$last] ) >= strlen( $all[$last] )
index 540ce4b..c3ee321 100644 (file)
@@ -1088,13 +1088,13 @@ abstract class LoginSignupSpecialPage extends AuthManagerSpecialPage {
                        // B/C for old extensions that haven't been converted to AuthManager (or have been
                        // but somebody is using the old version) and still use templates via the
                        // UserCreateForm/UserLoginForm hook.
-                       // 'header' used by ConfirmEdit, CondfirmAccount, Persona, WikimediaIncubator, SemanticSignup
+                       // 'header' used by ConfirmEdit, ConfirmAccount, Persona, WikimediaIncubator, SemanticSignup
                        // 'formheader' used by MobileFrontend
                        $fieldDefinitions['header'] = [
                                'type' => 'info',
                                'raw' => true,
                                'default' => $template->get( 'header' ) ?: $template->get( 'formheader' ),
-                               'weight' => - 110,
+                               'weight' => -110,
                        ];
                }
                if ( $this->mEntryError ) {
index 87276a1..a36b414 100644 (file)
@@ -33,6 +33,18 @@ class SpecialChangeContentModel extends FormSpecialPage {
                }
        }
 
+       protected function postText() {
+               $text = '';
+               if ( $this->title ) {
+                       $contentModelLogPage = new LogPage( 'contentmodel' );
+                       $text = Xml::element( 'h2', null, $contentModelLogPage->getName()->text() );
+                       $out = '';
+                       LogEventsList::showLogExtract( $out, 'contentmodel', $this->title );
+                       $text .= $out;
+               }
+               return $text;
+       }
+
        protected function getDisplayFormat() {
                return 'ooui';
        }
index 61b6a8c..d4cd2ac 100644 (file)
@@ -89,6 +89,12 @@ class SpecialPageLanguage extends FormSpecialPage {
                        'default' => $this->getConfig()->get( 'LanguageCode' ),
                ];
 
+               // Allow user to enter a comment explaining the change
+               $page['reason'] = [
+                       'type' => 'text',
+                       'label-message' => 'pagelang-reason'
+               ];
+
                return $page;
        }
 
@@ -111,68 +117,108 @@ class SpecialPageLanguage extends FormSpecialPage {
        /**
         *
         * @param array $data
-        * @return bool
+        * @return Status
         */
        public function onSubmit( array $data ) {
-               $title = Title::newFromText( $data['pagename'] );
+               $pageName = $data['pagename'];
+
+               // Check if user wants to use default language
+               if ( $data['selectoptions'] == 1 ) {
+                       $newLanguage = 'default';
+               } else {
+                       $newLanguage = $data['language'];
+               }
 
-               // Check if title is valid
-               if ( !$title ) {
-                       return false;
+               try {
+                       $title = Title::newFromTextThrow( $pageName );
+               } catch ( MalformedTitleException $ex ) {
+                       return Status::newFatal( $ex->getMessageObject() );
                }
 
+               // Url to redirect to after the operation
+               $this->goToUrl = $title->getFullURL();
+
+               return self::changePageLanguage(
+                       $this->getContext(),
+                       $title,
+                       $newLanguage,
+                       $data['reason'] === null ? '' : $data['reason']
+               );
+       }
+
+       /**
+        * @param IContextSource $context
+        * @param Title $title
+        * @param string $newLanguage Language code
+        * @param string $reason Reason for the change
+        * @param array $tags Change tags to apply to the log entry
+        * @return Status
+        */
+       public static function changePageLanguage( IContextSource $context, Title $title,
+               $newLanguage, $reason, array $tags = [] ) {
                // Get the default language for the wiki
-               $defLang = $this->getConfig()->get( 'LanguageCode' );
+               $defLang = $context->getConfig()->get( 'LanguageCode' );
 
                $pageId = $title->getArticleID();
 
                // Check if article exists
                if ( !$pageId ) {
-                       return false;
+                       return Status::newFatal(
+                               'pagelang-nonexistent-page',
+                               wfEscapeWikiText( $title->getPrefixedText() )
+                       );
                }
 
                // Load the page language from DB
                $dbw = wfGetDB( DB_MASTER );
-               $langOld = $dbw->selectField(
+               $oldLanguage = $dbw->selectField(
                        'page',
                        'page_lang',
                        [ 'page_id' => $pageId ],
                        __METHOD__
                );
 
-               // Url to redirect to after the operation
-               $this->goToUrl = $title->getFullURL();
-
-               // Check if user wants to use default language
-               if ( $data['selectoptions'] == 1 ) {
-                       $langNew = null;
-               } else {
-                       $langNew = $data['language'];
+               // Check if user wants to use the default language
+               if ( $newLanguage === 'default' ) {
+                       $newLanguage = null;
                }
 
                // No change in language
-               if ( $langNew === $langOld ) {
-                       return false;
+               if ( $newLanguage === $oldLanguage ) {
+                       // Check if old language does not exist
+                       if ( !$oldLanguage ) {
+                               return Status::newFatal( ApiMessage::create(
+                                       [
+                                               'pagelang-unchanged-language-default',
+                                               wfEscapeWikiText( $title->getPrefixedText() )
+                                       ],
+                                       'pagelang-unchanged-language'
+                               ) );
+                       }
+                       return Status::newFatal(
+                               'pagelang-unchanged-language',
+                               wfEscapeWikiText( $title->getPrefixedText() ),
+                               $oldLanguage
+                       );
                }
 
                // Hardcoded [def] if the language is set to null
-               $logOld = $langOld ? $langOld : $defLang . '[def]';
-               $logNew = $langNew ? $langNew : $defLang . '[def]';
+               $logOld = $oldLanguage ? $oldLanguage : $defLang . '[def]';
+               $logNew = $newLanguage ? $newLanguage : $defLang . '[def]';
 
                // Writing new page language to database
-               $dbw = wfGetDB( DB_MASTER );
                $dbw->update(
                        'page',
-                       [ 'page_lang' => $langNew ],
+                       [ 'page_lang' => $newLanguage ],
                        [
                                'page_id' => $pageId,
-                               'page_lang' => $langOld
+                               'page_lang' => $oldLanguage
                        ],
                        __METHOD__
                );
 
                if ( !$dbw->affectedRows() ) {
-                       return false;
+                       return Status::newFatal( 'pagelang-db-failed' );
                }
 
                // Logging change of language
@@ -181,9 +227,11 @@ class SpecialPageLanguage extends FormSpecialPage {
                        '5::newlanguage' => $logNew
                ];
                $entry = new ManualLogEntry( 'pagelang', 'pagelang' );
-               $entry->setPerformer( $this->getUser() );
+               $entry->setPerformer( $context->getUser() );
                $entry->setTarget( $title );
                $entry->setParameters( $logParams );
+               $entry->setComment( $reason );
+               $entry->setTags( $tags );
 
                $logid = $entry->insert();
                $entry->publish( $logid );
@@ -191,7 +239,11 @@ class SpecialPageLanguage extends FormSpecialPage {
                // Force re-render so that language-based content (parser functions etc.) gets updated
                $title->invalidateCache();
 
-               return true;
+               return Status::newGood( (object)[
+                       'oldLanguage' => $logOld,
+                       'newLanguage' => $logNew,
+                       'logId' => $logid,
+               ] );
        }
 
        public function onSuccess() {
index 1ce61e3..b2e5674 100644 (file)
@@ -526,6 +526,14 @@ class SpecialRecentChanges extends ChangesListSpecialPage {
                parent::addModules();
                $out = $this->getOutput();
                $out->addModules( 'mediawiki.special.recentchanges' );
+               if ( $this->getUser()->getOption(
+                               'rcenhancedfilters',
+                               /*default=*/ null,
+                               /*ignoreHidden=*/ true
+                       )
+               ) {
+                       $out->addModules( 'mediawiki.rcfilters.filters' );
+               }
        }
 
        /**
index 727179a..255e618 100644 (file)
@@ -740,8 +740,12 @@ class SpecialSearch extends SpecialPage {
                }
 
                $out .= "<ul class='mw-search-results'>\n";
+               $widget = new \MediaWiki\Widget\Search\FullSearchResultWidget(
+                       $this,
+                       $this->getLinkRenderer()
+               );
                while ( $result ) {
-                       $out .= $this->showHit( $result, $terms, $pos++ );
+                       $out .= $widget->render( $result, $terms, $pos++ );
                        $result = $matches->next();
                }
                $out .= "</ul>\n";
@@ -752,181 +756,6 @@ class SpecialSearch extends SpecialPage {
                return $out;
        }
 
-       /**
-        * Format a single hit result
-        *
-        * @param SearchResult $result
-        * @param array $terms Terms to highlight
-        * @param int $position Position within the search results, including offset.
-        *
-        * @return string
-        */
-       protected function showHit( SearchResult $result, $terms, $position ) {
-               if ( $result->isBrokenTitle() ) {
-                       return '';
-               }
-
-               $title = $result->getTitle();
-
-               $titleSnippet = $result->getTitleSnippet();
-
-               if ( $titleSnippet == '' ) {
-                       $titleSnippet = null;
-               }
-
-               $link_t = clone $title;
-               $query = [];
-
-               Hooks::run( 'ShowSearchHitTitle',
-                       [ &$link_t, &$titleSnippet, $result, $terms, $this, &$query ] );
-
-               $linkRenderer = $this->getLinkRenderer();
-
-               if ( $titleSnippet !== null ) {
-                       $titleSnippet = new HtmlArmor( $titleSnippet );
-               }
-
-               $link = $linkRenderer->makeKnownLink(
-                       $link_t,
-                       $titleSnippet,
-                       [ 'data-serp-pos' => $position ], // HTML attributes
-                       $query
-               );
-
-               // If page content is not readable, just return the title.
-               // This is not quite safe, but better than showing excerpts from non-readable pages
-               // Note that hiding the entry entirely would screw up paging.
-               if ( !$title->userCan( 'read', $this->getUser() ) ) {
-                       return "<li>{$link}</li>\n";
-               }
-
-               // If the page doesn't *exist*... our search index is out of date.
-               // The least confusing at this point is to drop the result.
-               // You may get less results, but... oh well. :P
-               if ( $result->isMissingRevision() ) {
-                       return '';
-               }
-
-               // format redirects / relevant sections
-               $redirectTitle = $result->getRedirectTitle();
-               $redirectText = $result->getRedirectSnippet();
-               $sectionTitle = $result->getSectionTitle();
-               $sectionText = $result->getSectionSnippet();
-               $categorySnippet = $result->getCategorySnippet();
-
-               $redirect = '';
-               if ( !is_null( $redirectTitle ) ) {
-                       if ( $redirectText == '' ) {
-                               $redirectText = null;
-                       }
-
-                       if ( $redirectText !== null ) {
-                               $redirectText = new HtmlArmor( $redirectText );
-                       }
-
-                       $redirect = "<span class='searchalttitle'>" .
-                               $this->msg( 'search-redirect' )->rawParams(
-                                       $linkRenderer->makeKnownLink( $redirectTitle, $redirectText ) )->text() .
-                               "</span>";
-               }
-
-               $section = '';
-               if ( !is_null( $sectionTitle ) ) {
-                       if ( $sectionText == '' ) {
-                               $sectionText = null;
-                       }
-
-                       if ( $sectionText !== null ) {
-                               $sectionText = new HtmlArmor( $sectionText );
-                       }
-
-                       $section = "<span class='searchalttitle'>" .
-                               $this->msg( 'search-section' )->rawParams(
-                                       $linkRenderer->makeKnownLink( $sectionTitle, $sectionText ) )->text() .
-                               "</span>";
-               }
-
-               $category = '';
-               if ( $categorySnippet ) {
-                       $category = "<span class='searchalttitle'>" .
-                               $this->msg( 'search-category' )->rawParams( $categorySnippet )->text() .
-                               "</span>";
-               }
-
-               // format text extract
-               $extract = "<div class='searchresult'>" . $result->getTextSnippet( $terms ) . "</div>";
-
-               $lang = $this->getLanguage();
-
-               // format description
-               $byteSize = $result->getByteSize();
-               $wordCount = $result->getWordCount();
-               $timestamp = $result->getTimestamp();
-               $size = $this->msg( 'search-result-size', $lang->formatSize( $byteSize ) )
-                       ->numParams( $wordCount )->escaped();
-
-               if ( $title->getNamespace() == NS_CATEGORY ) {
-                       $cat = Category::newFromTitle( $title );
-                       $size = $this->msg( 'search-result-category-size' )
-                               ->numParams( $cat->getPageCount(), $cat->getSubcatCount(), $cat->getFileCount() )
-                               ->escaped();
-               }
-
-               $date = $lang->userTimeAndDate( $timestamp, $this->getUser() );
-
-               $fileMatch = '';
-               // Include a thumbnail for media files...
-               if ( $title->getNamespace() == NS_FILE ) {
-                       $img = $result->getFile();
-                       $img = $img ?: wfFindFile( $title );
-                       if ( $result->isFileMatch() ) {
-                               $fileMatch = "<span class='searchalttitle'>" .
-                                       $this->msg( 'search-file-match' )->escaped() . "</span>";
-                       }
-                       if ( $img ) {
-                               $thumb = $img->transform( [ 'width' => 120, 'height' => 120 ] );
-                               if ( $thumb ) {
-                                       $desc = $this->msg( 'parentheses' )->rawParams( $img->getShortDesc() )->escaped();
-                                       // Float doesn't seem to interact well with the bullets.
-                                       // Table messes up vertical alignment of the bullets.
-                                       // Bullets are therefore disabled (didn't look great anyway).
-                                       return "<li>" .
-                                               '<table class="searchResultImage">' .
-                                               '<tr>' .
-                                               '<td style="width: 120px; text-align: center; vertical-align: top;">' .
-                                               $thumb->toHtml( [ 'desc-link' => true ] ) .
-                                               '</td>' .
-                                               '<td style="vertical-align: top;">' .
-                                               "{$link} {$redirect} {$category} {$section} {$fileMatch}" .
-                                               $extract .
-                                               "<div class='mw-search-result-data'>{$desc} - {$date}</div>" .
-                                               '</td>' .
-                                               '</tr>' .
-                                               '</table>' .
-                                               "</li>\n";
-                               }
-                       }
-               }
-
-               $html = null;
-
-               $score = '';
-               $related = '';
-               if ( Hooks::run( 'ShowSearchHit', [
-                       $this, $result, $terms,
-                       &$link, &$redirect, &$section, &$extract,
-                       &$score, &$size, &$date, &$related,
-                       &$html
-               ] ) ) {
-                       $html = "<li><div class='mw-search-result-heading'>" .
-                               "{$link} {$redirect} {$category} {$section} {$fileMatch}</div> {$extract}\n" .
-                               "<div class='mw-search-result-data'>{$size} - {$date}</div>" .
-                               "</li>\n";
-               }
-
-               return $html;
-       }
-
        /**
         * Extract custom captions from search-interwiki-custom message
         */
@@ -948,17 +777,13 @@ class SpecialSearch extends SpecialPage {
         * Show results from other wikis
         *
         * @param SearchResultSet|array $matches
-        * @param string $query
+        * @param string $terms
         *
         * @return string
         */
-       protected function showInterwiki( $matches, $query ) {
+       protected function showInterwiki( $matches, $terms ) {
                global $wgContLang;
 
-               $out = "<div id='mw-search-interwiki'><div id='mw-search-interwiki-caption'>" .
-                       $this->msg( 'search-interwiki-caption' )->text() . "</div>\n";
-               $out .= "<ul class='mw-search-iwresults'>\n";
-
                // work out custom project captions
                $this->getCustomCaptions();
 
@@ -966,107 +791,72 @@ class SpecialSearch extends SpecialPage {
                        $matches = [ $matches ];
                }
 
+               $iwResults = [];
                foreach ( $matches as $set ) {
-                       $prev = null;
                        $result = $set->next();
                        while ( $result ) {
-                               $out .= $this->showInterwikiHit( $result, $prev, $query );
-                               $prev = $result->getInterwikiPrefix();
+                               if ( !$result->isBrokenTitle() ) {
+                                       $iwResults[$result->getTitle()->getInterwiki()][] = $result;
+                               }
                                $result = $set->next();
                        }
                }
 
-               // @todo Should support paging in a non-confusing way (not sure how though, maybe via ajax)..
-               $out .= "</ul></div>\n";
+               $out = '';
+               $widget = new MediaWiki\Widget\Search\SimpleSearchResultWidget(
+                       $this,
+                       $this->getLinkRenderer()
+               );
+               foreach ( $iwResults as $iwPrefix => $results ) {
+                       $out .= $this->iwHeaderHtml( $iwPrefix, $terms );
+                       $out .= "<ul class='mw-search-iwresults'>";
+                       foreach ( $results as $result ) {
+                               // This makes the bold asumption interwiki results are never paginated.
+                               // That's currently true, but could change at some point?
+                               $out .= $widget->render( $result, $terms, 0 );
+                       }
+                       $out .= "</ul>";
+               }
 
-               // convert the whole thing to desired language variant
-               $out = $wgContLang->convert( $out );
+               $out =
+                       "<div id='mw-search-interwiki'>" .
+                               "<div id='mw-search-interwiki-caption'>" .
+                                       $this->msg( 'search-interwiki-caption' )->escaped() .
+                               "</div>" .
+                               $out .
+                       "</div>";
 
-               return $out;
+               // convert the whole thing to desired language variant
+               return $wgContLang->convert( $out );
        }
 
        /**
-        * Show single interwiki link
-        *
-        * @param SearchResult $result
-        * @param string $lastInterwiki
-        * @param string $query
-        *
-        * @return string
+        * @param string $iwPrefix The interwiki prefix to render a header for
+        * @param string $terms The user-provided search terms
         */
-       protected function showInterwikiHit( $result, $lastInterwiki, $query ) {
-               if ( $result->isBrokenTitle() ) {
-                       return '';
-               }
-
-               $linkRenderer = $this->getLinkRenderer();
-
-               $title = $result->getTitle();
-
-               $titleSnippet = $result->getTitleSnippet();
-
-               if ( $titleSnippet == '' ) {
-                       $titleSnippet = null;
-               }
-
-               if ( $titleSnippet !== null ) {
-                       $titleSnippet = new HtmlArmor( $titleSnippet );
-               }
-
-               $link = $linkRenderer->makeKnownLink(
-                       $title,
-                       $titleSnippet
+       protected function iwHeaderHtml( $iwPrefix, $terms ) {
+               if ( isset( $this->customCaptions[$iwPrefix] ) ) {
+                       $caption = $this->customCaptions[$iwPrefix];
+               } else {
+                       $iwLookup = MediaWiki\MediaWikiServices::getInstance()->getInterwikiLookup();
+                       $interwiki = $iwLookup->fetch( $iwPrefix );
+                       $parsed = wfParseUrl( wfExpandUrl( $interwiki ? $interwiki->getURL() : '/' ) );
+                       $caption = $this->msg( 'search-interwiki-default', $parsed['host'] )->text();
+               }
+               $searchLink = Linker::linkKnown(
+                       Title::newFromText( "$iwPrefix:Special:Search" ),
+                       $this->msg( 'search-interwiki-more' )->text(),
+                       [],
+                       [
+                               'search' => $terms,
+                               'fulltext' => 1,
+                       ]
                );
-
-               // format redirect if any
-               $redirectTitle = $result->getRedirectTitle();
-               $redirectText = $result->getRedirectSnippet();
-               $redirect = '';
-               if ( !is_null( $redirectTitle ) ) {
-                       if ( $redirectText == '' ) {
-                               $redirectText = null;
-                       }
-
-                       if ( $redirectText !== null ) {
-                               $redirectText = new HtmlArmor( $redirectText );
-                       }
-
-                       $redirect = "<span class='searchalttitle'>" .
-                               $this->msg( 'search-redirect' )->rawParams(
-                                       $linkRenderer->makeKnownLink( $redirectTitle, $redirectText ) )->text() .
-                               "</span>";
-               }
-
-               $out = "";
-               // display project name
-               if ( is_null( $lastInterwiki ) || $lastInterwiki != $title->getInterwiki() ) {
-                       if ( array_key_exists( $title->getInterwiki(), $this->customCaptions ) ) {
-                               // captions from 'search-interwiki-custom'
-                               $caption = $this->customCaptions[$title->getInterwiki()];
-                       } else {
-                               // default is to show the hostname of the other wiki which might suck
-                               // if there are many wikis on one hostname
-                               $parsed = wfParseUrl( $title->getFullURL() );
-                               $caption = $this->msg( 'search-interwiki-default', $parsed['host'] )->text();
-                       }
-                       // "more results" link (special page stuff could be localized, but we might not know target lang)
-                       $searchTitle = Title::newFromText( $title->getInterwiki() . ":Special:Search" );
-                       $searchLink = $linkRenderer->makeKnownLink(
-                               $searchTitle,
-                               $this->msg( 'search-interwiki-more' )->text(),
-                               [],
-                               [
-                                       'search' => $query,
-                                       'fulltext' => 'Search'
-                               ]
-                       );
-                       $out .= "</ul><div class='mw-search-interwiki-project'><span class='mw-search-interwiki-more'>
-                               {$searchLink}</span>{$caption}</div>\n<ul>";
-               }
-
-               $out .= "<li>{$link} {$redirect}</li>\n";
-
-               return $out;
+               return
+                       "<div class='mw-search-interwiki-project'>" .
+                               "<span class='mw-search-interwiki-more'>{$searchLink}</span>" .
+                               $caption .
+                       "</div>";
        }
 
        /**
index a937e75..1bf05d9 100644 (file)
@@ -21,6 +21,7 @@
  * @license GPL 2+
  * @author Daniel Kinzler
  */
+use MediaWiki\MediaWikiServices;
 use MediaWiki\Linker\LinkTarget;
 
 /**
@@ -309,6 +310,7 @@ class MediaWikiTitleCodec implements TitleFormatter, TitleParser {
                        if ( preg_match( $prefixRegexp, $dbkey, $m ) ) {
                                $p = $m[1];
                                $ns = $this->language->getNsIndex( $p );
+                               $interwikiLookup = MediaWikiServices::getInstance()->getInterwikiLookup();
                                if ( $ns !== false ) {
                                        # Ordinary namespace
                                        $dbkey = $m[2];
@@ -318,13 +320,13 @@ class MediaWikiTitleCodec implements TitleFormatter, TitleParser {
                                                if ( $this->language->getNsIndex( $x[1] ) ) {
                                                        # Disallow Talk:File:x type titles...
                                                        throw new MalformedTitleException( 'title-invalid-talk-namespace', $text );
-                                               } elseif ( Interwiki::isValidInterwiki( $x[1] ) ) {
+                                               } elseif ( $interwikiLookup->isValidInterwiki( $x[1] ) ) {
                                                        // TODO: get rid of global state!
                                                        # Disallow Talk:Interwiki:x type titles...
                                                        throw new MalformedTitleException( 'title-invalid-talk-namespace', $text );
                                                }
                                        }
-                               } elseif ( Interwiki::isValidInterwiki( $p ) ) {
+                               } elseif ( $interwikiLookup->isValidInterwiki( $p ) ) {
                                        # Interwiki link
                                        $dbkey = $m[2];
                                        $parts['interwiki'] = $this->language->lc( $p );
index 562f0d1..fed64c2 100644 (file)
@@ -301,7 +301,8 @@ class User implements IDBAccessObject {
        protected $queryFlagsUsed = self::READ_NORMAL;
 
        /** @var string Indicates type of block (used for eventlogging)
-        * Permitted values: 'cookie-block', 'proxy-block', 'openproxy-block', 'xff-block'
+        * Permitted values: 'cookie-block', 'proxy-block', 'openproxy-block', 'xff-block',
+        * 'config-block'
         */
        public $blockTrigger = false;
 
@@ -1581,7 +1582,7 @@ class User implements IDBAccessObject {
         *   Check when actually saving should be done against master.
         */
        private function getBlockedStatus( $bFromSlave = true ) {
-               global $wgProxyWhitelist, $wgUser, $wgApplyIpBlocksToXff;
+               global $wgProxyWhitelist, $wgUser, $wgApplyIpBlocksToXff, $wgSoftBlockRanges;
 
                if ( -1 != $this->mBlockedby ) {
                        return;
@@ -1680,6 +1681,21 @@ class User implements IDBAccessObject {
                        }
                }
 
+               if ( !$block instanceof Block
+                       && $ip !== null
+                       && $this->isAnon()
+                       && IP::isInRanges( $ip, $wgSoftBlockRanges )
+               ) {
+                       $block = new Block( [
+                               'address' => $ip,
+                               'byText' => 'MediaWiki default',
+                               'reason' => wfMessage( 'softblockrangesreason', $ip )->text(),
+                               'anonOnly' => true,
+                               'systemBlock' => 'wgSoftBlockRanges',
+                       ] );
+                       $this->blockTrigger = 'config-block';
+               }
+
                if ( $block instanceof Block ) {
                        wfDebug( __METHOD__ . ": Found block.\n" );
                        $this->mBlock = $block;
diff --git a/includes/widget/search/FullSearchResultWidget.php b/includes/widget/search/FullSearchResultWidget.php
new file mode 100644 (file)
index 0000000..a93e1fc
--- /dev/null
@@ -0,0 +1,284 @@
+<?php
+
+namespace MediaWiki\Widget\Search;
+
+use Category;
+use Hooks;
+use HtmlArmor;
+use MediaWiki\Linker\LinkRenderer;
+use SearchResult;
+use SpecialSearch;
+use Title;
+
+/**
+ * Renders a 'full' multi-line search result with metadata.
+ *
+ *  The Title
+ *  some *highlighted* *text* about the search result
+ *  5KB (651 words) - 12:40, 6 Aug 2016
+ */
+class FullSearchResultWidget implements SearchResultWidget {
+       /** @var SpecialSearch */
+       protected $specialPage;
+       /** @var LinkRenderer */
+       protected $linkRenderer;
+
+       public function __construct( SpecialSearch $specialPage, LinkRenderer $linkRenderer ) {
+               $this->specialPage = $specialPage;
+               $this->linkRenderer = $linkRenderer;
+       }
+
+       /**
+        * @param SearchResult $result The result to render
+        * @param string $terms Terms to be highlighted (@see SearchResult::getTextSnippet)
+        * @param int $position The result position, including offset
+        * @return string HTML
+        */
+       public function render( SearchResult $result, $terms, $position ) {
+               // If the page doesn't *exist*... our search index is out of date.
+               // The least confusing at this point is to drop the result.
+               // You may get less results, but... on well. :P
+               if ( $result->isBrokenTitle() || $result->isMissingRevision() ) {
+                       return '';
+               }
+
+               $link = $this->generateMainLinkHtml( $result, $terms, $position );
+               // If page content is not readable, just return ths title.
+               // This is not quite safe, but better than showing excerpts from
+               // non-readable pages. Note that hiding the entry entirely would
+               // screw up paging (really?).
+               if ( !$result->getTitle()->userCan( 'read', $this->specialPage->getUser() ) ) {
+                       return "<li>{$link}</li>";
+               }
+
+               $redirect = $this->generateRedirectHtml( $result );
+               $section = $this->generateSectionHtml( $result );
+               $category = $this->generateCategoryHtml( $result );
+               $date = $this->specialPage->getLanguage()->userTimeAndDate(
+                       $result->getTimestamp(),
+                       $this->specialPage->getUser()
+               );
+               list( $file, $desc, $thumb ) = $this->generateFileHtml( $result );
+               $snippet = $result->getTextSnippet( $terms );
+               if ( $snippet ) {
+                       $extract = "<div class='searchresult'>$snippet</div>";
+               } else {
+                       $extract = '';
+               }
+
+               if ( $thumb === null ) {
+                       // If no thumb, then the description is about size
+                       $desc = $this->generateSizeHtml( $result );
+
+                       // Let hooks do their own final construction if desired.
+                       // FIXME: Not sure why this is only for results without thumbnails,
+                       // but keeping it as-is for now to prevent breaking hook consumers.
+                       $html = null;
+                       $score = '';
+                       $related = '';
+                       if ( !Hooks::run( 'ShowSearchHit', [
+                               $this->specialPage, $result, $terms,
+                               &$link, &$redirect, &$section, &$extract,
+                               &$score, &$size, &$date, &$related, &$html
+                       ] ) ) {
+                               return $html;
+                       }
+               }
+
+               // All the pieces have been collected. Now generate the final HTML
+               $joined = "{$link} {$redirect} {$category} {$section} {$file}";
+               $meta = $this->buildMeta( $desc, $date );
+
+               if ( $thumb === null ) {
+                       $html =
+                               "<div class='mw-search-result-heading'>{$joined}</div>" .
+                               "{$extract} {$meta}";
+               } else {
+                       $html =
+                               "<table class='searchResultImage'>" .
+                                       "<tr>" .
+                                               "<td style='width: 120px; text-align: center; vertical-align: top'>" .
+                                                       $thumb .
+                                               "</td>" .
+                                               "<td style='vertical-align: top'>" .
+                                                       "{$joined} {$extract} {$meta}" .
+                                               "</td>" .
+                                       "</tr>" .
+                               "</table>";
+               }
+
+               return "<li>{$html}</li>";
+       }
+
+       /**
+        * Generates HTML for the primary call to action. It is
+        * typically the article title, but the search engine can
+        * return an exact snippet to use (typically the article
+        * title with highlighted words).
+        *
+        * @param SearchResult $result
+        * @param string $terms
+        * @param int $position
+        * @return string HTML
+        */
+       protected function generateMainLinkHtml( SearchResult $result, $terms, $position ) {
+               $snippet = $result->getTitleSnippet();
+               if ( $snippet === '' ) {
+                       $snippet = null;
+               } else {
+                       $snippet = new HtmlArmor( $snippet );
+               }
+
+               // clone to prevent hook from changing the title stored inside $result
+               $title = clone $result->getTitle();
+               $queryString = [];
+
+               Hooks::run( 'ShowSearchHitTitle',
+                       [ $title, &$snippet, $result, $terms, $this->specialPage, &$queryString ] );
+
+               $link = $this->linkRenderer->makeLink(
+                       $title,
+                       $snippet,
+                       [ 'data-serp-pos' => $position ],
+                       $queryString
+               );
+
+               return $link;
+       }
+
+       /**
+        * Generates an alternate title link, such as (redirect from <a>Foo</a>).
+        *
+        * @param string $msgKey i18n message  used to wrap title
+        * @param Title|null $title The title to link to, or null to generate
+        *  the message without a link. In that case $text must be non-null.
+        * @param string|null $text The text snippet to display, or null
+        *  to use the title
+        * @return string HTML
+        */
+       protected function generateAltTitleHtml( $msgKey, Title $title = null, $text ) {
+               $inner = $title === null
+                       ? $text
+                       : $this->linkRenderer->makeLink( $title, $text ? new HtmlArmor( $text ) : null );
+
+               return "<span class='searchalttitle'>" .
+                               $this->specialPage->msg( $msgKey )->rawParams( $inner )->text()
+                       . "</span>";
+       }
+
+       /**
+        * @param SearchResult $result
+        * @return string HTML
+        */
+       protected function generateRedirectHtml( SearchResult $result ) {
+               $title = $result->getRedirectTitle();
+               return $title === null
+                       ? ''
+                       : $this->generateAltTitleHtml( 'search-redirect', $title, $result->getRedirectSnippet() );
+       }
+
+       /**
+        * @param SearchResult $result
+        * @return string HTML
+        */
+       protected function generateSectionHtml( SearchResult $result ) {
+               $title = $result->getSectionTitle();
+               return $title === null
+                       ? ''
+                       : $this->generateAltTitleHtml( 'search-section', $title, $result->getSectionSnippet() );
+       }
+
+       /**
+        * @param SearchResult $result
+        * @return string HTML
+        */
+       protected function generateCategoryHtml( SearchResult $result ) {
+               $snippet = $result->getCategorySnippet();
+               return $snippet
+                       ? $this->generateAltTitleHtml( 'search-category', null, $snippet )
+                       : '';
+       }
+
+       /**
+        * @param SearchResult $result
+        * @return string HTML
+        */
+       protected function generateSizeHtml( SearchResult $result ) {
+               $title = $result->getTitle();
+               if ( $title->getNamespace() === NS_CATEGORY ) {
+                       $cat = Category::newFromTitle( $title );
+                       return $this->specialPage->msg( 'search-result-category-size' )
+                               ->numParams( $cat->getPageCount(), $cat->getSubcatCount(), $cat->getFileCount() )
+                               ->escaped();
+               // TODO: This is a bit odd...but requires changing the i18n message to fix
+               } elseif ( $result->getByteSize() !== null || $result->getWordCount() > 0 ) {
+                       $lang = $this->specialPage->getLanguage();
+                       $bytes = $lang->formatSize( $result->getByteSize() );
+                       $words = $result->getWordCount();
+
+                       return $this->specialPage->msg( 'search-result-size', $bytes )
+                               ->numParams( $words )
+                               ->escaped();
+               }
+
+               return '';
+       }
+
+       /**
+        * @param SearchResult $result
+        * @return array Three element array containing the main file html,
+        *  a text description of the file, and finally the thumbnail html.
+        *  If no thumbnail is available the second and third will be null.
+        */
+       protected function generateFileHtml( SearchResult $result ) {
+               $title = $result->getTitle();
+               if ( $title->getNamespace() !== NS_FILE ) {
+                       return [ '', null, null ];
+               }
+
+               if ( $result->isFileMatch() ) {
+                       $html = "<span class='searchalttitle'>" .
+                                       $this->specialPage->msg( 'search-file-match' )->escaped() .
+                               "</span>";
+               } else {
+                       $html = '';
+               }
+
+               $descHtml = null;
+               $thumbHtml = null;
+
+               $img = $result->getFile() ?: wfFindFile( $title );
+               if ( $img ) {
+                       $thumb = $img->transform( [ 'width' => 120, 'height' => 120 ] );
+                       if ( $thumb ) {
+                               $descHtml = $this->specialPage->msg( 'parentheses' )
+                                       ->rawParams( $img->getShortDesc() )
+                                       ->escaped();
+                               $thumbHtml = $thumb->toHtml( [ 'desc-link' => true ] );
+                       }
+               }
+
+               return [ $html, $descHtml, $thumbHtml ];
+       }
+
+       /**
+        * @param string $desc HTML description of result, ex: size in bytes, or empty string
+        * @param string $date HTML representation of last edit date, or empty string
+        * @return string HTML A div combining $desc and $date with a separator in a <div>.
+        *  If either is missing only one will be represented. If both are missing an empty
+        *  string will be returned.
+        */
+       protected function buildMeta( $desc, $date ) {
+               if ( $desc && $date ) {
+                       $meta = "{$desc} - {$date}";
+               } elseif ( $desc ) {
+                       $meta = $desc;
+               } elseif ( $date ) {
+                       $meta = $date;
+               } else {
+                       return '';
+               }
+
+               return "<div class='mw-search-result-data'>{$meta}</div>";
+       }
+}
diff --git a/includes/widget/search/SearchResultWidget.php b/includes/widget/search/SearchResultWidget.php
new file mode 100644 (file)
index 0000000..b53cd5d
--- /dev/null
@@ -0,0 +1,18 @@
+<?php
+
+namespace MediaWiki\Widget\Search;
+
+use SearchResult;
+
+/**
+ * Renders a single search result to HTML
+ */
+interface SearchResultWidget {
+       /**
+        * @param SearchResult $result The result to render
+        * @param string $terms Terms to be highlighted (@see SearchResult::getTextSnippet)
+        * @param int $position The result position, including offset
+        * @return string HTML
+        */
+       public function render( SearchResult $result, $terms, $position );
+}
diff --git a/includes/widget/search/SimpleSearchResultWidget.php b/includes/widget/search/SimpleSearchResultWidget.php
new file mode 100644 (file)
index 0000000..9fe816a
--- /dev/null
@@ -0,0 +1,61 @@
+<?php
+
+namespace MediaWiki\Widget\Search;
+
+use HtmlArmor;
+use MediaWiki\Linker\LinkRenderer;
+use SearchResult;
+use SpecialSearch;
+use Title;
+
+/**
+ * Renders a simple one-line result
+ */
+class SimpleSearchResultWidget implements SearchResultWidget {
+       /** @var SpecialSearch */
+       protected $specialSearch;
+       /** @var LinkRenderer */
+       protected $linkRenderer;
+
+       public function __construct( SpecialSearch $specialSearch, LinkRenderer $linkRenderer ) {
+               $this->specialSearch = $specialSearch;
+               $this->linkRenderer = $linkRenderer;
+       }
+
+       /**
+        * @param SearchResult $result The result to render
+        * @param string $terms Terms to be highlighted (@see SearchResult::getTextSnippet)
+        * @param int $position The result position, including offset
+        * @return string HTML
+        */
+       public function render( SearchResult $result, $terms, $position ) {
+               $title = $result->getTitle();
+               $titleSnippet = $result->getTitleSnippet();
+               if ( $titleSnippet ) {
+                       $titleSnippet = new HtmlArmor( $titleSnippet );
+               } else {
+                       $titleSnippet = null;
+               }
+
+               $link = $this->linkRenderer->makeLink( $title, $titleSnippet );
+
+               $redirectTitle = $result->getRedirectTitle();
+               $redirect = '';
+               if ( $redirectTitle !== null ) {
+                       $redirectText = $result->getRedirectSnippet();
+                       if ( $redirectText ) {
+                               $redirectText = new HtmlArmor( $redirectText );
+                       } else {
+                               $redirectText = null;
+                       }
+                       $redirect =
+                               "<span class='searchalttitle'>" .
+                                       $this->specialSearch->msg( 'search-redirect' )->rawParams(
+                                               $this->linkRenderer->makeLink( $redirectTitle, $redirectText )
+                                       )->text() .
+                               "</span>";
+               }
+
+               return "<li>{$link} {$redirect}</li>";
+       }
+}
index ac8d4cb..5bce76b 100644 (file)
@@ -2100,17 +2100,15 @@ class Language {
                $data = explode( '|', $tz, 3 );
 
                if ( $data[0] == 'ZoneInfo' ) {
-                       MediaWiki\suppressWarnings();
-                       $userTZ = timezone_open( $data[2] );
-                       MediaWiki\restoreWarnings();
-                       if ( $userTZ !== false ) {
-                               $date = date_create( $ts, timezone_open( 'UTC' ) );
-                               date_timezone_set( $date, $userTZ );
-                               $date = date_format( $date, 'YmdHis' );
-                               return $date;
+                       try {
+                               $userTZ = new DateTimeZone( $data[2] );
+                               $date = new DateTime( $ts, new DateTimeZone( 'UTC' ) );
+                               $date->setTimezone( $userTZ );
+                               return $date->format( 'YmdHis' );
+                       } catch ( Exception $e ) {
+                               // Unrecognized timezone, default to 'Offset' with the stored offset.
+                               $data[0] = 'Offset';
                        }
-                       # Unrecognized timezone, default to 'Offset' with the stored offset.
-                       $data[0] = 'Offset';
                }
 
                if ( $data[0] == 'System' || $tz == '' ) {
index c085628..600dc2c 100644 (file)
        "recentchanges-legend-heading": "<strong>شرح:</strong>",
        "recentchanges-legend-newpage": "{{int:recentchanges-label-newpage}} (راجع أيضا [[Special:NewPages|قائمة الصفحات الجديدة]])",
        "recentchanges-submit": "أظهر",
+       "rcfilters-activefilters": "المرشحات النشطة",
+       "rcfilters-search-placeholder": "رشح أحدث التغييرات (تصفح أو ابدأ الكتابة)",
+       "rcfilters-invalid-filter": "مرشح غير صحيح",
+       "rcfilters-filterlist-title": "مرشحات",
+       "rcfilters-filterlist-noresults": "لم يتم العثور على مرشحات",
+       "rcfilters-filtergroup-authorship": "ملكية التعديلات",
+       "rcfilters-filter-editsbyself-label": "تعديلاتك الشخصية",
+       "rcfilters-filter-editsbyself-description": "التعديلات بواسطتك.",
+       "rcfilters-filter-editsbyother-label": "التعديلات بواسطة الآخرين",
+       "rcfilters-filter-editsbyother-description": "التعديلات المنشأة بواسطة المستخدمين الآخرين (ليس أنت.)",
+       "rcfilters-filtergroup-userExpLevel": "مستوى خبرة المستخدم",
+       "rcfilters-filter-userExpLevel-newcomer-label": "القادمون الجدد",
+       "rcfilters-filter-userExpLevel-newcomer-description": "المستخدمون الجدد جدا: أقل من 10 تعديلات و4 أيام من النشاط.",
+       "rcfilters-filter-userExpLevel-learner-label": "المتعلمون",
+       "rcfilters-filter-userExpLevel-learner-description": "المزيد من أيام النشاط والتعديلات أكثر من 'القادمين الجدد' ولكن أقل من 'المستخدمين ذوي الخبرة.'",
+       "rcfilters-filter-userExpLevel-experienced-label": "المستخدمون ذوو الخبرة",
+       "rcfilters-filter-userExpLevel-experienced-description": "أكثر من 30 يوما من النشاط و500 تعديل.",
        "rcnotefrom": "بالأسفل {{PLURAL:$5|التغيير|التغييرات}} منذ <strong>$2</strong> (إلى <strong>$1</strong> معروضة).",
        "rclistfrom": "أظهر التغييرات بدء من $3 $2",
        "rcshowhideminor": "$1 التعديلات الطفيفة",
        "apisandbox-sending-request": "إرسال طلب API ...",
        "apisandbox-loading-results": "استقبال طلبات API ...",
        "apisandbox-results-error": "حدث خطأ أثناء تحميل رد استعدلام الAPI: $1.",
+       "apisandbox-request-params-json": "معاملات JSON:",
        "apisandbox-request-url-label": "مسار الطلب:",
        "apisandbox-request-time": "وقت الطلب: {{PLURAL:$1|$1 ms}}",
        "apisandbox-results-fixtoken": "رمز الصحيح وإعادة الموافقة",
        "changecontentmodel-emptymodels-title": "لا موديلات محتوى متوفرة",
        "changecontentmodel-emptymodels-text": "المحتوى على[[:$1]] لا يمكن تغييره لأي نوع.",
        "log-name-contentmodel": "سجل تغيير نموذج المحتوى",
-       "log-description-contentmodel": "الأحداث المرتبطة بنماذج المحتوى لصفحة",
+       "log-description-contentmodel": "هذه الصفحة تعرض التغييرات لموديل المحتوى للصفحات، والصفحات التي تم إنشاؤها بموديل محتوى يختلف عن الافتراضي",
        "logentry-contentmodel-new": "$1 {{GENDER:$2|أنشأ|أنشأت}} الصفحة $3 باستخدام موديل محتوى غير قياسي \"$5\"",
        "logentry-contentmodel-change": "$1 {{GENDER:$2|غير|غيرت}} موديل المحتوى للصفحة $3 من \"$4\" إلى \"$5\"",
        "logentry-contentmodel-change-revertlink": "استرجع",
        "pagelang-use-default": "استخدام اللغة الافتراضية",
        "pagelang-select-lang": "اختر اللغة",
        "pagelang-submit": "إرسال",
+       "pagelang-nonexistent-page": "الصفحة $1 غير موجودة.",
+       "pagelang-unchanged-language": "الصفحة $1 مضبوطة فعلا للغة $2.",
+       "pagelang-unchanged-language-default": "الصفحة $1 مضبوطة فعلا للغة المحتوى الافتراضية الخاصة بالويكي.",
+       "pagelang-db-failed": "قاعدة البيانات فشلت في تغيير لغة الصفحة.",
        "right-pagelang": "تغيير لغة الصفحة",
        "action-pagelang": "تغيير لغة الصفحة",
        "log-name-pagelang": "سجل تغيير اللغة",
        "log-action-filter-block-reblock": "منع التعديل",
        "log-action-filter-block-unblock": "رفع المنع",
        "log-action-filter-contentmodel-change": "تغيير موديل المحتوى",
-       "log-action-filter-contentmodel-new": "إنشاء صفحة بموديل محتوى غير قياسي",
+       "log-action-filter-contentmodel-new": "إنشاء صفحة بموديل محتوى غير افتراضي",
        "log-action-filter-delete-delete": "حذف الصفحات",
        "log-action-filter-delete-delete_redir": "إعادة الكتابة فوق التحويلة",
        "log-action-filter-delete-restore": "استرجاع الصفحات",
index dd96161..6a9ed15 100644 (file)
@@ -11,7 +11,7 @@
                ]
        },
        "tog-underline": "Miñcewirilpe lasun",
-       "tog-showtoolbar": "Pengelün kümeelün ñi chemkün",
+       "tog-showtoolbar": "Pengelün kümeelkünun ñi chemkün",
        "tog-editondblclick": "Wirin pakina epu klik mew",
        "underline-always": "Rumel",
        "underline-never": "Turpu",
@@ -89,7 +89,7 @@
        "and": "&#32;ka",
        "qbfind": "Kintupe",
        "qbbrowse": "Kintun",
-       "qbedit": "Pepikape",
+       "qbedit": "Kümelkünun",
        "qbpageoptions": "Tüfachi wülngiñ",
        "qbmyoptions": "tañi nütramkawe",
        "faq": "Rumelfemkelu ramtun",
        "permalink": "Mülekalelu lasun",
        "print": "Wirinentupe",
        "view": "Pen",
-       "edit": "Kümeelün",
+       "edit": "Kümelkünun",
        "create": "Dewman",
-       "editthispage": "Wirin tüfachi wülngiñ",
+       "editthispage": "Kümelkünufinge tüfachi wirin zungu",
        "create-this-page": "Llitun tüfachi pakina",
        "delete": "Liftun",
        "deletethispage": "Ñamümün tüfachi pakina",
        "currentevents-url": "Project:Fantepu chemkün",
        "disclaimers": "Tukuldungun ñi pin ley",
        "disclaimerpage": "Project:Katrütuwün ñi llowdüngun",
-       "edithelp": "Kellü wirin",
+       "edithelp": "Kellun kümeelkünuam",
        "mainpage": "Ñidol Wülngiñ",
        "mainpage-description": "Ñidol Wülngiñ",
        "portal": "Lofche ñi wülngiñ",
        "youhavenewmessages": "Nieymi $1 ($2).",
        "newmessagesdifflinkplural": "we {{PLURAL:$1|kalekünuy|kalekünuy}}",
        "youhavenewmessagesmulti": "Nieymi we yefalzugu $1 mew.",
-       "editsection": "Wirin",
+       "editsection": "Kümeelkünun",
        "editold": "kümeelün",
        "viewsourceold": "Kimam chew küpan chi wirin",
-       "editlink": "kümeelün",
+       "editlink": "kümeelkünun",
        "viewsourcelink": "kimam chew küpan chi wirin",
-       "editsectionhint": "Kümeelan katrüntuku: $1",
+       "editsectionhint": "Kümeelkünun trokiñ: $1",
        "toc": "Trokiñdungu",
        "showtoc": "pegelpe",
        "hidetoc": "ellkangepe",
        "hr_tip": "Kakül wif (Pünengelayafuy rumel)",
        "summary": "Pichi trokiñündungu:",
        "subject": "Dungu/üy:",
-       "minoredit": "Tüfachi ta kiñe pichi wirin",
+       "minoredit": "Püchin kümeelkünungey",
        "watchthis": "Llaytun tüfachi pakina",
        "savearticle": "Eltukawün wülngiñ",
        "preview": "Pen chum müley",
        "noarticletext": "Iney no rume wirilay tüfachi wülngiñ mew. Eymi [[Special:Search/{{PAGENAME}}|pepikintuymi tüfachi üy]] kake wülngiñ mew,\n<span class=\"plainlinks\">[{{fullurl:{{#Special:Log}}|page={{FULLPAGENAMEE}}}} kintuymi koneltuyelelu wirintukun],\nkam [{{fullurl:{{FULLPAGENAME}}|action=edit}} kümeelaymi tüfachi wülngiñ]</span>.",
        "noarticletext-nopermission": "Iney no rume wirilay tüfachi wülngiñ mew. \nEymi [[Special:Search/{{PAGENAME}}|pepikintuymi tüfachi üy]] kake wülngiñ mew,\nkam <span class=\"plainlinks\">[{{fullurl:{{#Special:Log}}|page={{FULLPAGENAMEE}}}} kintuymi koneltuyelelu wirintukun]</span>.",
        "previewnote": "'''Ngüneduamimi tüfachi wüne pen petu eltukawam!'''\nEltukawlelay feychi kalekünun!",
-       "editing": "Kümeelngey $1",
+       "editing": "Kümeelngekey $1",
        "editingsection": "Wirin $1 (Dungu)",
        "editingcomment": "Wirin $1 (we dungu)",
        "yourtext": "Tami wirin",
        "randompage": "Tuchi wülngiñ rume",
        "statistics": "Chuntelen",
        "statistics-pages": "Pakina",
-       "brokenredirects-edit": "pepikan",
+       "brokenredirects-edit": "Kümeelkünun",
        "brokenredirects-delete": "ñamümün",
        "withoutinterwiki-submit": "Pegelpe",
        "nbytes": "$1 {{PLURAL:$1 byte}}",
        "protect-level-sysop": "Pu ngünefe müṯen",
        "protect-summary-cascade": "Trayengko",
        "protect-expiry-options": "1 ora:1 hour,1 aṉtü:1 day,1 semana:1 week,2 semanas:2 weeks,1 küyeṉ:1 month,3 küyeṉ:3 months,6 küyeṉ:6 months,1 tripantu:1 year,Rumel:infinite",
-       "restriction-edit": "Pepiwelukay",
+       "restriction-edit": "Kümeelkünun",
        "restriction-move": "Pepiwiñami",
        "restriction-create": "Llitun",
        "viewdeletedpage": "Pen pakina ñamümüngelu",
        "siteuser": "Kellufe $1 {{SITENAME}}",
        "others": "fill",
        "siteusers": "{{PLURAL:$2|Kellufe|Kellufe}} $1 {{SITENAME}}",
-       "previousdiff": "← Füta wirin",
+       "previousdiff": "← Kuyfi kümeelkünun wirin",
        "nextdiff": "We wirin →",
        "file-info-size": "$1 × $2 adentun piküsel, eltukawün ñi tunte ngen: $3, MIME ñi chumngen: $4",
        "file-nohires": "Pepiduamngefalay chum pengeam.",
index e58456d..50a5601 100644 (file)
        "sp-contributions-blocked-notice": "اليوزر ده ممنوع دلوقتى.\nآخر عمليه منع في السجل موجوده تحت كمرجع:",
        "sp-contributions-search": "دور على مساهمات",
        "sp-contributions-username": "عنوان أيبى أو اسم يوزر:",
-       "sp-contributions-toponly": "اظÙ\87ر Ø§Ø®ØªÙ\8aر ØªØ¹Ø¯Ù\8aÙ\84  Ø¨Ø³",
+       "sp-contributions-toponly": "اظهر اخر تعديل  بس",
        "sp-contributions-submit": "تدوير",
        "whatlinkshere": "ايه بيوصل هنا",
        "whatlinkshere-title": "الصفحات اللى بتوصل لـ \"$1\"",
index ce5b1f9..e1ba17d 100644 (file)
        "views": "Ҡарауҙар",
        "toolbox": "Ҡоралдар",
        "tool-link-userrights": "{{GENDER:$1|Ҡатнашыусы}} төркөмдәрен үҙгәртергә",
+       "tool-link-userrights-readonly": "{{GENDER:$1|ҡатнашыусылар}} төркөмөн ҡарарға",
        "tool-link-emailuser": "{{GENDER:$1|Ҡатнашыусыға}} хат яҙырға",
        "userpage": "Ҡулланыусы битен ҡарарға",
        "projectpage": "Проект битен ҡарарға",
        "createacct-yourpasswordagain-ph": "Серһүҙҙе тағы бер тапҡыр яҙығыҙ",
        "userlogin-remembermypassword": "Системала ҡалырға",
        "userlogin-signwithsecure": "Һаҡланыулы тоташыу",
+       "cannotlogin-title": "инеп булмай",
+       "cannotlogin-text": "Инеү мөмкин түгел",
        "cannotloginnow-title": "Хәҙер үк инеп булмай",
        "cannotloginnow-text": "$1 файҙалланған ваҡытта инергә ярамай",
+       "cannotcreateaccount-title": "Иҫәп яҙмаһын булдырып булмай",
+       "cannotcreateaccount-text": "Был викила иҫәп яҙмаһын булдырыу ҡаралмаған.",
        "yourdomainname": "Һеҙҙең домен",
        "password-change-forbidden": "Был викиҙа серһүҙегеҙҙе үҙгәртә алмайһығыҙ.",
        "externaldberror": "Тышҡы мәғлүмәт базаһы менән танылғанда хата барлыҡҡа килде йәки тышҡы үҙ көйләүҙәрегеҙҙе үҙгәртер өсөн хоҡуҡтарығыҙ етәрле түгел.",
        "eauthentsent": "Күрһәтелгән электрон почта адресына адресты үҙгәртеүҙе раҫлауығыҙ өсөн хат ебәрелде. Хатта был адрес һеҙҙеке булғанын раҫлау өсөн ниндәй ғәмәлдәрҙе үтәү кәрәклеге тураһында мәғлүмәт бар.",
        "throttled-mailpassword": "Серһүҙҙе иҫләтеү ғәмәле {{PLURAL:$1|һуңғы $1 сәғәт}} эсенде ҡулланылды инде.\nНасар ниәтле ҡулланыуҙарға ҡаршы, Серһүҙ иҫләтеү ғәмәлен {{PLURAL:$1|1=сәғәт|$1 сәғәт}} эсендә бер тапҡыр ғына ҡулланырға була.",
        "mailerror": "Хат ебәреү хатаһы: $1",
-       "acct_creation_throttle_hit": "Һеҙҙең IP-адрестан бер тәүлек эсендә {{PLURAL:$1|$1 иҫәп яҙыуы}} яһалды инде, был һан был ваҡыт аралығы өсөн максимум һан. Шул сәбәпле, был IP-адресына эйә ҡулланыусылар, хәҙерге ваҡытта яңы иҫәп яҙыуы яһай алмайҙар.",
+       "acct_creation_throttle_hit": "Һеҙҙең IP-адрестан бер тәүлек эсендә {{PLURAL:$1|$1 иҫәп яҙыуы}} яһалды инде, был һан был ваҡыт аралығы өсөн максимум һан. Шул сәбәпле, был IP-адресына эйә ҡулланыусылар, хәҙерге ваҡытта яңы иҫәп яҙыуы яһай алмайҙар. Был ваҡыт эсендә $2 тапҡыр инеп була.",
        "emailauthenticated": "Электрон почта адресығыҙ раҫланды: $3, $2.",
        "emailnotauthenticated": "Электрон почта адресығыҙ раҫланмаған әле. Киләһе ғәмәлдәр өсөн электрон почта эшләмәйәсәк.",
        "noemailprefs": "Электрон почта адресығыҙ күрһәтелмәгән, шул сәбәпле викиның электрон почта функциялары ябыҡ.",
        "botpasswords-updated-body": "$1 роботы өсөн $2 ҡулланыусыһы серһүҙе яңыртылды.",
        "botpasswords-deleted-title": "Робот серһүҙе юйылды.",
        "botpasswords-deleted-body": "$1 роботы өсөн $2 ҡулланыусыһы серһүҙе юйылды.",
-       "botpasswords-newpassword": "Инеү өсөн яңы серһүҙ <strong>$1</strong> — <strong>$2</strong>. <em>Артабан ҡулланыу өсөн яһып алығыҙ.</em>",
+       "botpasswords-newpassword": "Инеү өсөн яңы серһүҙ <strong>$1</strong> — <strong>$2</strong>. <em>Артабан ҡулланыу өсөн яһып алығыҙ.</em><strong>$3</strong> ҡатнашыусы исеме <strong>$4</strong> пароль сифаты)",
        "botpasswords-no-provider": "BotPasswordsSessionProvider ғәмәлдә түгел.",
        "botpasswords-restriction-failed": "Робот серһүҙе менән бәйле сәбәптәр булғанға инеү башҡарылманы.",
        "botpasswords-invalid-name": "Күрһәтелгән ҡулланыусы исемендә робот $1 серһүҙен бүлеүсе тамға юҡ.",
index 0736ee2..355c23f 100644 (file)
        "duplicate-args-category-desc": "Старонкі, якія ўтрымліваюць шаблёны з парамэтрамі-дублікатамі, напрыклад, <code><nowiki>{{foo|bar=1|bar=2}}</nowiki></code> або <code><nowiki>{{foo|bar|1=baz}}</nowiki></code>.",
        "expensive-parserfunction-warning": "Папярэджаньне: гэтая старонка ўтрымлівае зашмат працаёмістых зваротаў да функцыяў парсэра.\n\nПавінна быць ня болей за $2 {{PLURAL:$2|зварот|звароты|зваротаў}}, а цяпер ўтрымліваецца {{PLURAL:$1|$1 зварот|$1 звароты|$1 зваротаў}}.",
        "expensive-parserfunction-category": "Старонкі, якія ўтрымліваюць зашмат працаёмістых зваротаў да функцыяў парсэра",
-       "post-expand-template-inclusion-warning": "Папярэджаньне: Памер уключаемых шаблёнаў занадта вялікі.\nНекаторыя шаблёны ня будуць уключаныя.",
+       "post-expand-template-inclusion-warning": "<strong>Папярэджаньне</strong>: памер выкарыстаных шаблёнаў занадта вялікі.\nНекаторыя шаблёны ня будуць уключаныя.",
        "post-expand-template-inclusion-category": "Старонкі, у якіх перавышаны дапушчальны памер уключаных шаблёнаў",
-       "post-expand-template-argument-warning": "Увага: Гэтая старонка ўтрымлівае прынамсі адзін парамэтар шаблёна, які мае занадта вялікі выгляд у разгорнутым выглядзе.\nГэтыя парамэтры былі прапушчаныя.",
+       "post-expand-template-argument-warning": "<strong>Увага</strong>: гэтая старонка ўтрымлівае прынамсі адзін парамэтар шаблёну, які мае занадта вялікі выгляд у разгорнутым выглядзе.\nГэтыя парамэтры былі прапушчаныя.",
        "post-expand-template-argument-category": "Старонкі, у якіх прапушчаныя парамэтры шаблёнаў",
        "parser-template-loop-warning": "Выяўлены цыкль у шаблёнах: [[$1]]",
        "parser-template-recursion-depth-warning": "Перавышана мяжа глыбіні рэкурсіі шаблёнаў ($1)",
        "recentchanges-legend-heading": "<strong>Легенда:</strong>",
        "recentchanges-legend-newpage": "{{int:recentchanges-label-newpage}} (глядзіце таксама [[Special:NewPages|сьпіс новых старонак]])",
        "recentchanges-submit": "Паказаць",
+       "rcfilters-activefilters": "Актыўныя фільтры",
+       "rcfilters-search-placeholder": "Фільтар апошніх зьменаў (праглядзець або пачніце друкаваць)",
+       "rcfilters-invalid-filter": "Няслушны фільтар",
+       "rcfilters-filterlist-title": "Фільтры",
+       "rcfilters-filterlist-noresults": "Фільтры ня знойдзеныя",
+       "rcfilters-filtergroup-authorship": "Рэдагаваць аўтарства",
+       "rcfilters-filter-editsbyself-label": "Вашыя праўкі",
+       "rcfilters-filter-editsbyself-description": "Праўкі, зробленыя вамі",
+       "rcfilters-filter-editsbyother-label": "Праўкі іншых удзельнікаў",
+       "rcfilters-filter-editsbyother-description": "Праўкі, зробленыя іншымі ўдзельнікамі (ня вамі)",
        "rcnotefrom": "Ніжэй {{PLURAL:$5|знаходзіцца зьмена|знаходзяцца зьмены}} з <strong>$4 $3</strong> (да <strong>$1</strong> на старонку).",
        "rclistfrom": "Паказаць зьмены з $2 $3",
        "rcshowhideminor": "$1 дробныя праўкі",
index 17c49d2..b3532a1 100644 (file)
        "resetpass-submit-cancel": "বাতিল",
        "resetpass-wrong-oldpass": "ভুল অস্থায়ী অথবা বর্তমান পাসওয়ার্ড।\nসম্ভবতঃ আপনি ইতোমধ্যেই আপনার পাসওয়ার্ডটি পরিবর্তন করেছেন অথবা একটি নতুন অস্থায়ী পাসওয়ার্ডের জন্য অনুরোধ করেছেন।",
        "resetpass-recycled": "অনুগ্রহ করে বর্তমানে ব্যবহার করছেন এমন পাসওয়ার্ডের পরিবর্তে নতুন একটি পাসওয়ার্ড নির্ধারণ করুন।",
-       "resetpass-temp-emailed": "à¦\86পনি à¦\87মà§\87à¦\87লà¦\95à§\83ত à¦¸à¦¾à¦®à¦¯à¦¼à¦¿à¦\95 à¦\95à§\8bড à¦¦à¦¿à¦¯à¦¼à§\87 à¦ªà§\8dরবà§\87শ à¦\95রà§\87à¦\9bà§\87ন।\nপà§\8dরবà§\87শ à¦\95রার à¦\9cনà§\8dয à¦\86পনাà¦\95à§\87 à¦\85বশà§\8dযà¦\87 à¦\8fà¦\95à¦\9fি à¦¨à¦¤à§\81ন à¦ªà¦¾à¦¸à¦\93য়ারà§\8dড à¦¨à¦¿à¦°à§\8dধারন করতে হবে:",
+       "resetpass-temp-emailed": "à¦\86পনি à¦\87মà§\87à¦\87লà¦\95à§\83ত à¦¸à¦¾à¦®à¦¯à¦¼à¦¿à¦\95 à¦\95à§\8bড à¦¦à¦¿à¦¯à¦¼à§\87 à¦ªà§\8dরবà§\87শ à¦\95রà§\87à¦\9bà§\87ন।\nপà§\8dরবà§\87শ à¦\95রার à¦\9cনà§\8dয à¦\86পনাà¦\95à§\87 à¦\85বশà§\8dযà¦\87 à¦\8fà¦\95à¦\9fি à¦¨à¦¤à§\81ন à¦ªà¦¾à¦¸à¦\93য়ারà§\8dড à¦¨à¦¿à¦°à§\8dধারণ করতে হবে:",
        "resetpass-temp-password": "অস্থায়ী পাসওয়ার্ড:",
        "resetpass-abort-generic": "পাসওয়ার্ড পরিবর্তন একটি এক্সটেনশনের কারণে স্থগিত করা হয়েছে।",
        "resetpass-expired": "আপনার পাসওয়ার্ডের মেয়াদ উত্তীর্ণ হয়েছে। অনুগ্রহ করে নতুন পাসওয়ার্ড নির্ধারণ করুন।",
        "resetpass-expired-soft": "আপনার পাসওয়ার্ডের মেয়াদ উত্তীর্ণ হয়েছে এবং আপনাকে একটি নতুন পাসওয়ার্ড নির্ধারণ করতে হবে। অনুগ্রহ করে এখনই একটি নতুন পাসওয়ার্ড নির্ধারণ করুন অথবা পরে পরিবর্তন করতে চাইলে \"{{int:authprovider-resetpass-skip-label}}\" বাটনে ক্লিক করুন।",
        "resetpass-validity-soft": "আপনার পাসওয়ার্ড বৈধ নয়: $1\n\nদয়া করে একটি নতুন পাসওয়ার্ড নির্ধারণ করুন অথবা পরে করার জন্য \"{{int:authprovider-resetpass-skip-label}}\" ক্লিক করুন।",
        "passwordreset": "পাসওয়ার্ড রিসেট",
-       "passwordreset-text-one": "à¦\86পনার à¦ªà¦¾à¦¸à¦\93য়ারà§\8dড à¦ªà§\81নরায় à¦¸à§\87à¦\9f à¦\95রতà§\87 à¦\8fà¦\87 à¦«à¦°à§\8dমà¦\9fি পূরণ করুন।",
+       "passwordreset-text-one": "à¦\87মà§\87à¦\87লà§\87র à¦®à¦¾à¦§à§\8dযমà§\87 à¦\8fà¦\95à¦\9fি à¦\85সà§\8dথায়à§\80 à¦ªà¦¾à¦¸à¦\93য়ারà§\8dড à¦ªà§\87তà§\87 à¦\8fà¦\87 à¦«à¦°à¦® পূরণ করুন।",
        "passwordreset-text-many": "{{PLURAL:$1|ইমেইলের মাধ্যমে একটি অস্থায়ী পাসওয়ার্ড পেতে ঘরগুলির একটি পূরণ করুন।}}",
        "passwordreset-disabled": "এই উইকিতে পাসওয়ার্ড রিসেটের সুবিধা নিষ্ক্রিয় রয়েছে।",
        "passwordreset-emaildisabled": "এই উইকিতে ইমেইল অপশনটি বন্ধ করা হয়েছে।",
        "revdelete-modify-missing": "$1 আইডি সম্বলিত তথ্যটি সম্পাদনা করা যাচ্ছে না: এটি ডাটাবেজ থেকে হারিয়ে গিয়েছে!",
        "revdelete-no-change": "'''সতর্কতা:''' $2, $1 তারিখ সম্বলিত তথ্যটিতে পূর্বেই অনুরোধকৃত সেটিংস রয়েছে।",
        "revdelete-concurrent-change": "$2, $1 তারিখ সম্বলিত তথ্যটি সম্পাদনা করা যাচ্ছে না: আপনার সম্পাদনা শুরুর আগে কেউ এটির অবস্থা পরিবর্তন করেছেন।\nঅনুগ্রহ করে লগ দেখুন।",
-       "revdelete-only-restricted": "$2, $1 à¦¤à¦¾à¦°à¦¿à¦\96 à¦¸à¦®à§\8dবলিত à¦¤à¦¥à§\8dযà¦\9fি à¦²à§\81à¦\95ানà§\8b à¦¯à¦¾à¦\9aà§\8dà¦\9bà§\87 à¦¨à¦¾: à¦¤à¦¥à§\8dয à¦ªà§\8dরদরà§\8dশনà§\87র à¦\85নà§\8dযানà§\8dয à¦\85পশনà¦\97à§\81লà§\8b à¦¨à¦¿à¦°à§\8dধারন করা ব্যতিত আপনি এটি শুধুমাত্র প্রশাসকদের জন্য দেখার উপযোগী করতে পারবেন না।",
+       "revdelete-only-restricted": "$2, $1 à¦¤à¦¾à¦°à¦¿à¦\96 à¦¸à¦®à§\8dবলিত à¦¤à¦¥à§\8dযà¦\9fি à¦²à§\81à¦\95ানà§\8b à¦¯à¦¾à¦\9aà§\8dà¦\9bà§\87 à¦¨à¦¾: à¦¤à¦¥à§\8dয à¦ªà§\8dরদরà§\8dশনà§\87র à¦\85নà§\8dযানà§\8dয à¦¬à¦¿à¦\95লà§\8dপà¦\97à§\81লি à¦¨à¦¿à¦°à§\8dধারণ করা ব্যতিত আপনি এটি শুধুমাত্র প্রশাসকদের জন্য দেখার উপযোগী করতে পারবেন না।",
        "revdelete-reason-dropdown": "*সাধারণ অপসারণের কারণসমূহ\n** কপিরাইট লঙ্ঘন\n** অনুপযুক্ত ব্যক্তিগত তথ্য\n** অনুপযুক্ত ব্যবহারকারী নাম\n** সম্ভাব্য ক্ষতিকারক তথ্য",
        "revdelete-otherreason": "অন্য/বাড়তি কারণ:",
        "revdelete-reasonotherlist": "অন্য কারণ",
        "recentchangesdays-max": "সর্বোচ্চ $1 {{PLURAL:$1|দিন|দিন}}",
        "recentchangescount": "সাম্প্রতিক পরিবর্তনে প্রদর্শিত সম্পাদনার সংখ্যা:",
        "prefs-help-recentchangescount": "এতে সাম্প্রতিক পরিবর্তনসমূহ, পাতার ইতিহাস এবং লগ অন্তর্ভুক্ত।",
-       "prefs-help-watchlist-token2": "à¦\8fà¦\9fি à¦\86পনার à¦¨à¦\9cরতালিà¦\95ার à¦\93য়à§\87ব à¦«à¦¿à¦¡à§\87র à¦\97à§\8bপন à¦\9aাবি। à¦¯à§\87 à¦\95à§\87à¦\89 à¦¯à¦¿à¦¨à¦¿ à¦\8fà¦\9fা à¦\9cানà§\87ন à¦¤à¦¿à¦¨à¦¿ à¦\86পনার à¦¨à¦\9cরতালিà¦\95া à¦ªà¦¡à¦¼à¦¤à§\87 à¦¸à¦\95à§\8dষম à¦¹à¦¬à§\87ন, à¦¤à¦¾à¦\87 à¦\8fà¦\9fি à¦ªà§\8dরà¦\95াশ à¦\95রবà§\87ন à¦¨à¦¾à¥¤ [[Special:ResetTokens|à¦\86পনার à¦\8fà¦\9fি à¦ªà§\81নরায় à¦¸à§\87à¦\9f করার প্রয়োজন হলে এখানে ক্লিক করুন]]।",
+       "prefs-help-watchlist-token2": "à¦\8fà¦\9fি à¦\86পনার à¦¨à¦\9cরতালিà¦\95ার à¦\93য়à§\87ব à¦«à¦¿à¦¡à§\87র à¦\97à§\8bপন à¦\9aাবি। à¦¯à§\87 à¦\95à§\87à¦\89 à¦¯à¦¿à¦¨à¦¿ à¦\8fà¦\9fা à¦\9cানà§\87ন à¦¤à¦¿à¦¨à¦¿ à¦\86পনার à¦¨à¦\9cরতালিà¦\95া à¦ªà¦¡à¦¼à¦¤à§\87 à¦¸à¦\95à§\8dষম à¦¹à¦¬à§\87ন, à¦¤à¦¾à¦\87 à¦\8fà¦\9fি à¦ªà§\8dরà¦\95াশ à¦\95রবà§\87ন à¦¨à¦¾à¥¤ [[Special:ResetTokens|à¦\86পনার à¦\8fà¦\9fি à¦ªà§\81নà¦\83নিরà§\8dধারণ করার প্রয়োজন হলে এখানে ক্লিক করুন]]।",
        "savedprefs": "আপনার পছন্দগুলো সংরক্ষণ করা হয়েছে।",
        "savedrights": "{{GENDER:$1|$1}}-এর ব্যবহারকারী দল সংরক্ষিত হয়েছে।",
        "timezonelegend": "সময়স্থান:",
        "recentchanges-legend-newpage": "{{int:recentchanges-label-newpage}} (আরও দেখুন [[Special:NewPages|নতুন পাতার তালিকা]])",
        "recentchanges-legend-plusminus": "(''±১২৩'')",
        "recentchanges-submit": "দেখাও",
+       "rcfilters-filter-editsbyself-label": "আপনার নিজস্ব সম্পাদনা",
+       "rcfilters-filter-editsbyself-description": "আপনার দ্বারা সম্পাদনা।",
+       "rcfilters-filter-editsbyother-label": "অন্যদের দ্বারা সম্পাদনা",
+       "rcfilters-filter-editsbyother-description": "অন্য ব্যবহারকারীদের দ্বারা করা সম্পাদনা (আপনার না)।",
+       "rcfilters-filtergroup-userExpLevel": "ব্যবহারকারীর অভিজ্ঞতা স্তর",
+       "rcfilters-filter-userExpLevel-newcomer-label": "নতুন আগত",
+       "rcfilters-filter-userExpLevel-learner-label": "শিক্ষার্থী",
+       "rcfilters-filter-userExpLevel-experienced-label": "অভিজ্ঞ ব্যবহারকারী",
        "rcnotefrom": "<strong>$2</strong>টা থেকে সংঘটিত পরিবর্তনগুলি (সর্বোচ্চ <strong>$1টি</strong> দেখানো হয়েছে)।",
        "rclistfrom": "$2, $3 তারিখের পর সংঘটিত নতুন পরিবর্তনগুলো দেখাও",
        "rcshowhideminor": "অনুল্লেখ্য পরিবর্তনগুলো $1",
        "apisandbox-results": "ফলাফল",
        "apisandbox-sending-request": "API অনুরোধ পাঠানো হচ্ছে...",
        "apisandbox-loading-results": "API ফলাফল গ্রহণ করা হচ্ছে...",
+       "apisandbox-request-params-json": "JSON প্যারামিটার:",
        "apisandbox-request-url-label": "অনুরোধের URL:",
        "apisandbox-request-time": "অনুরোধের সময়: {{PLURAL:$1|$1 মি.সে.}}",
        "apisandbox-results-fixtoken": "টোকেন সংশোধন ও পুনরায় জমা",
        "ipboptions": "২ ঘণ্টা:2 hours,১ দিন:1 day,৩ দিন:3 days,১ সপ্তাহ:1 week,২ সপ্তাহ:2 weeks,১ মাস:1 month,৩ মাস:3 months,৬ মাস:6 months,১ বছর:1 year,অসীম:infinite",
        "ipbhidename": "সম্পাদনা ও তালিকা থেকে ব্যবহারকারী নাম লুকিয়ে রাখা হোক",
        "ipbwatchuser": "এই ব্যবহাকারীর পাতা এবং আলাপের পাতা নজরতালিকায় রাখো",
-       "ipb-disableusertalk": "à¦\8fà¦\87 à¦¬à§\8dযবহারà¦\95ারà§\80à¦\95à§\87 à¦¬à¦¾à¦§à¦¾à¦¦à¦¾à¦¨à¦\95à§\83ত à¦\85বসà§\8dথায় à¦¨à¦¿à¦\9aের আলাপ পাতায় সম্পাদনা করা থেকে বিরত রাখো",
+       "ipb-disableusertalk": "à¦\8fà¦\87 à¦¬à§\8dযবহারà¦\95ারà§\80à¦\95à§\87 à¦¬à¦¾à¦§à¦¾à¦¦à¦¾à¦¨à¦\95à§\83ত à¦\85বসà§\8dথায় à¦¨à¦¿à¦\9cের আলাপ পাতায় সম্পাদনা করা থেকে বিরত রাখো",
        "ipb-change-block": "এই একই সেটিংসসহ ব্যবহারকারীকে আবারও বাধা প্রদান করো",
        "ipb-confirm": "বাধা নিশ্চিতকরণ",
        "badipaddress": "আইপি (IP) ঠিকানাটি অগ্রহনযোগ্য",
        "pagelang-language": "ভাষা",
        "pagelang-use-default": "ডিফল্ট ভাষা ব্যবহার করুন",
        "pagelang-select-lang": "ভাষা নির্বাচন করুন",
+       "pagelang-reason": "কারণ",
        "pagelang-submit": "জমা দাও",
        "right-pagelang": "পাতার ভাষা পরিবর্তন করুন",
        "action-pagelang": "পাতার ভাষা পরিবর্তন করুন",
index cf50e95..a0d4c05 100644 (file)
        "about": "درباره",
        "newwindow": "(پنجره تازه واز کن)",
        "cancel": "لغو",
+       "moredotdotdot": "بيشدر",
        "mypage": "بألگأ",
        "mytalk": "چأک چنأ",
        "anontalk": "چأک چنأ",
        "qbbrowse": "قأرز کردن",
        "qbedit": "اصلاح",
        "qbpageoptions": "اي بألگأ",
+       "qbmyoptions": "بألگإ آ مو",
        "faq": "اف ای کیو",
        "faqpage": "Project:اف ای کیو",
        "namespaces": "نوم ڤأرگأ آ",
        "help": "راهنما",
        "search": "پئی جوٙری",
        "searchbutton": "پئی جوٙری",
+       "go": "رۉ",
        "searcharticle": "برو",
        "history": "گزارش صفحه",
        "history_short": "گزارش تاریخی",
        "disclaimers": "تیە پوٙشنا",
        "disclaimerpage": "Project: تیە پوشنیدٙئنئ کولی",
        "edithelp": "کمک برای اصلاح",
+       "helppage-top-gethelp": "هومیاري",
        "mainpage": "سأرآسوٙنە",
        "mainpage-description": "صفحه اصلی",
        "policy-url": "Project:خط مشی",
        "toc": "محتواها",
        "showtoc": "نمایش",
        "hidetoc": "قایم",
+       "collapsible-expand": "گأپ کلۈن کردن",
        "confirmable-yes": "هرإ",
        "confirmable-no": "نأ",
        "thisisdeleted": "دیدن یا اعاده $1?",
        "wrongpassword": "رمز وارد وابیده درست نه.\nلطفا دوباره سعی کنین.",
        "wrongpasswordempty": "رمز وارد وابیده عقیم یامبهم بی.\nلطفا دوباره سعی کنین.",
        "passwordtooshort": "رمز ایسا غیر معتبر یا کوتاه هده.\nآن وا داشته بوه حداقل {{PLURAL:$1|1 کاراکتر|$1 کاراکترها}} همچنین وا زه نام کاربریتو متفاوت بوه.",
-       "mailmypassword": "اÙ\85Û\8cÙ\84 Ø±Ù\85ز ØªØ§Ø²Ù\87",
+       "mailmypassword": "ز Ù\86Û\89 Ø¯Ø§Ú\8cÙ\86 Ø±Ø§Ø²Ù\8aÙ\86Ø¥ Ú¯Ù\88أرتÙ\86",
        "passwordremindertitle": "رمز موقتی تازه سی {{SITENAME}}",
        "passwordremindertext": "یه نفر (شاید خودتو, زه نشانی آی پی$1) درخواست یه رمز تازه کرده سی {{SITENAME}} ($4). یه رمز موقتی سی کاربر\n\"$2\" درست شده وگذاشته وابیده به\"$3\". ایر مطابق میل ایسا بوه, نیازه که داخل سیستم بوین ویه رمز تازه انتخاب کنین.\n\nایر آن فرد همچنین درخواست کرده بوه  یونه, یا ایر ایسا رمزتو را به خاط داشته این ,\nوسی مدت طولانی نه خوین هونه تغییر بدین, ایسا وا نادیده بگیرین ای پیام  را وهمچنان زه رمز قدیمی خوتو استفاده کنین",
        "noemail": "وجود نداره نشانی امیل ضبط وابده زه کاریر \"$1\".",
        "pt-createaccount": "راسد کردن هساڤ کارياري",
        "pt-userlogout": "ز سامۈنإ درأڤوڌن",
        "retypenew": "تایپ دوباره رمز:",
+       "botpasswords-label-create": "راس كردن",
+       "botpasswords-label-cancel": "أنجومشيڤ کردن",
+       "botpasswords-label-delete": "پاکسا کردن",
+       "botpasswords-label-resetpassword": "ز نۉ داڌن رازينإ گوأرتن",
+       "resetpass-submit-cancel": "أنجومشيڤ کردن",
        "passwordreset": "ز نۉ داڌن رازينإ گوأرتن",
+       "passwordreset-username": "نوم کارياري",
+       "passwordreset-domain": "پوشگر",
+       "passwordreset-email": "تيرنشۈن أنجومانامأ",
+       "changeemail-none": "(هيش كوم)",
        "bold_sample": "متن گپ نما",
        "bold_tip": "متن گپ نما",
        "italic_sample": "متن شکسته",
        "sig_tip": "امضای ایسا و برچسب زمان",
        "hr_tip": "خط افقی (کم استفاده کنین)",
        "summary": "خلاصه:",
-       "subject": "موضوع/سرخط:",
+       "subject": "داسۈن",
        "minoredit": "ای یه اصلاح ریزه-رز",
        "watchthis": "پیگیری ای صفحه",
        "savearticle": "صفحه ضبط بوه",
        "template-semiprotected": "(نیمه حمایت وابیده)",
        "nocreatetext": "{{SITENAME}}قابلیت درست کردن صفحات تازه را محدود کرده‌. ترین برگردین و صفحه‌ موجود را اصلاح کنین یا اینکه  [[Special:UserLogin|به سیستم داخل بوین یا حساب کاربری درست کنین]].",
        "recreate-moveddeleted-warn": "'''هشدار: ایسا در حال درست کردن دوباره صفحه‌ای هدین که قبلاً حذف وابیده '''در نظر داشته بوین که ادامه اصلاح ای صفحه کار درستی هده یا نه. نمایه حذف مربوط به ای صفحه سی راحتی کار در ادامه اویده",
+       "content-model-wikitext": "ڤيکي تکست",
+       "content-model-javascript": "جاڤا إسکريپت",
        "viewpagelogs": "نشودادن نمایه ها سی ای صفحه",
        "currentrev": "نسخه جاری",
        "currentrev-asof": "آخرين ڤانيأري جۈر $1",
        "nextrevision": "نسخه بعدی →",
        "currentrevisionlink": "نسخه جاری",
        "cur": "فعلی",
+       "next": "نيایي",
        "last": "قبلی",
        "page_first": "اولین",
        "page_last": "آخری",
        "histlegend": "انتخاب متفاوت: علامت بنین رو رادیو جعبه ها زه آن نسخه ها سی مقایسه وامتیاز دادن ویا داخل تکمه های زیر سی مسابقه بوین  .<br />\n'شرح: (فعلی) = تفاوت با نسخه جاری\n(قبلی) = تفاوت با نسخه قبلی، جز = ویرایش جزئی',",
-       "histfirst": "کهنه ترین",
-       "histlast": "تازه ترین",
+       "histfirst": "دينداتري",
+       "histlast": "تازإترين",
+       "historyempty": "(هالي)",
        "history-feed-item-nocomment": "$1 در $2",
        "rev-delundel": "آلشد هال و بال ديإن",
+       "rev-showdeleted": "دياري کردن",
+       "revdelete-show-file-submit": "هأرإ",
        "history-title": "دڤارتإ دیئن ڤيرگار $1",
        "difference-title": "فرخ مإنجقا ڤانإیريا \"$1\"",
        "lineno": "سطر $1:",
        "recentchanges-label-minor": "یو یه ويرايشت کوچيره",
        "recentchanges-label-bot": "اي ڤيرایشد نأ یأ بوت أنجوم داڌإ",
        "recentchanges-label-unpatrolled": "ای ويرايشت هنی تيه واداشت نوابيه",
+       "recentchanges-label-plusminus": "أندازإ بألگأ ب شومار اي بایتا آلشد کردإ.",
        "recentchanges-legend-heading": "<strong>میراث:</strong>",
+       "recentchanges-legend-newpage": "{{int:recentchanges-label-newpage}} (همچنو سإیل کونين ب[[Special:بألگإیل تازأ|نومگأ بإلگإیل تازأ]])",
        "rcnotefrom": "در زیر تغییرات زه تاریخ <b>$2</b> آمده‌اند (تا <b>$1</b> مورد نشو داده ابوه).",
        "rclistfrom": "نشودادن تغییرات تازه با شروع زه $3 $2",
        "rcshowhideminor": "اصلاحات کوچیک $1",
        "undeletebtn": "بازیافت",
        "namespace": "فضای نام:",
        "invert": "انتخاب برعکس بوه",
+       "tooltip-invert": "ز ري اي جأڤأ بپۈرنين و آلشدایي نأ کإ مإنجقا نوم ڤأرگأ إنتخاڤ ڤابيڌن أنجوم داڌإ ڤابيڌنإ قام کونين.",
        "namespace_association": "نوم جایل یأکاگرهڌأ",
+       "tooltip-namespace_association": "اي جأڤإ نأ ڤارسي کونين اي جأڤأ د ڤأرگرهڌإ چأک چنإ آ داسۈن نوم ڤأرگأ شريکي و نوم ڤأرگأ گولإڤورچينإ.",
        "blanknamespace": "(اصلی)",
        "contributions": "{{GENDER:$1|کاریار}} هومیاریا",
        "mycontris": "هومياریا",
        "tooltip-upload": "شروع آپلود",
        "tooltip-rollback": "\"اعاده\" برگرداندن به وضع اولیه سی ای صفحه که بخاطر مشارکت  آخر اصلاح وابیده بایک کلیک",
        "tooltip-summary": "یأ چکسدأ کۈچير ڤارڌ کونين",
+       "simpleantispam-label": "Anti-spam check.\nپور<strong>نکنين</strong> ايچو نأ!",
        "pageinfo-toolboxlink": "دونسمندیا بلگه",
        "previousdiff": "← اصلاح قدیمی",
        "nextdiff": "تفاوت بعدی→",
index 3ca7f21..fc16576 100644 (file)
@@ -36,6 +36,7 @@
        "tog-watchmoves": "Ouzhpennañ ar pajennoù dilec'hiet ganin da'm roll evezhiañ",
        "tog-watchdeletion": "Ouzhpennañ ar pajennoù diverket ganin da'm roll evezhiañ",
        "tog-watchuploads": "Ouzhpennañ em roll-evezhiañ ar restroù nevez a enporzhian.",
+       "tog-watchrollback": "Ouzhpennañ ar pajennoù ma'z on distro war ma roll evezhiañ.",
        "tog-minordefault": "Sellet ouzh ar c'hemmoù degaset ganin<br /> evel kemmoù dister dre ziouer",
        "tog-previewontop": "Rakwelet tres ar bajenn a-us ar prenestr skridaozañ",
        "tog-previewonfirst": "Rakwelet tres ar bajenn kerkent hag an aozadenn gentañ",
        "tog-enotifminoredits": "Kas ur postel din, ha pa vije evit kemenn kemmoù dister",
        "tog-enotifrevealaddr": "Lakaat ma chomlec'h postel war wel er posteloù kemenn-diwall",
        "tog-shownumberswatching": "Diskouez an niver a lennerien",
-       "tog-oldsig": "Ar sinadur zo evit poent :",
+       "tog-oldsig": "Ho sinadur evit poent :",
        "tog-fancysig": "Ober gant ar sinadur evel pa vefe wikitestenn (hep liamm emgefre)",
-       "tog-uselivepreview": "Implijout Rakwelet prim (taol-arnod)",
+       "tog-uselivepreview": "Ober gant ar Rakwel prim",
        "tog-forceeditsummary": "Kemenn din pa ne skrivan netra er stern diverrañ",
        "tog-watchlisthideown": "Kuzhat ma c'hemmoù er rollad evezhiañ",
        "tog-watchlisthidebots": "Kuzhat kemmoù ar botoù er rollad evezhiañ",
        "tog-watchlisthideminor": "Kuzhat ar c'hemmoù dister er rollad evezhiañ",
        "tog-watchlisthideliu": "Er roll evezhiañ, kuzhat kemmoù an implijerien kevreet.",
+       "tog-watchlistreloadautomatically": "Adkargañ ar roll-evezhiañ bep tro ma vez cheñchet ur sil (rekis eo kaout JavaScript)",
        "tog-watchlisthideanons": "Er roll evezhiañ, kuzhat kemmoù an implijerien dianav",
        "tog-watchlisthidepatrolled": "Kuzhat ar c'hemmoù evezhiet diouzh ar roll evezhiañ",
+       "tog-watchlisthidecategorization": "Kuzhat rummatadur ar pajennoù",
        "tog-ccmeonemails": "Kas din un eilskrid eus ar posteloù a gasan da implijerien all",
        "tog-diffonly": "Arabat diskouez danvez ar pennadoù dindan an diforc'hioù",
        "tog-showhiddencats": "Diskouez ar rummadoù kuzhet",
-       "tog-norollbackdiff": "Na ziskouez an diff goude un distaoladenn",
+       "tog-norollbackdiff": "Na ziskouez an diforc'hioù goude un distro",
        "tog-useeditwarning": "Kas keloù din pa guitaan ur bajenn degaset kemmoù enni hep enrollañ",
        "tog-prefershttps": "Implijout bepred ur c'hevreadur suraet pa vezit kevreet",
        "underline-always": "Atav",
        "newwindow": "(digeriñ en ur prenestr nevez)",
        "cancel": "Nullañ",
        "moredotdotdot": "Ha muioc'h c'hoazh...",
-       "morenotlisted": "N'eo ket klok ar roll-mañ.",
+       "morenotlisted": "Marteze eo diglok ar roll-mañ.",
        "mypage": "Ma zammig pajenn",
        "mytalk": "Ma c'haozeadennoù",
-       "anontalk": "Kaozeal gant ar chomlec'h IP-mañ",
+       "anontalk": "Kaozeal",
        "navigation": "Merdeiñ",
        "and": "&#32;ha(g)",
        "qbfind": "Klask",
        "talk": "Kaozeadenn",
        "views": "Gweladennoù",
        "toolbox": "Ostilhoù",
+       "tool-link-userrights": "Kemmañ strolladoù an {{GENDER:$1|implijer|implijerez}}",
+       "tool-link-emailuser": "Kas ur postel d'an {{PLURAL:$1|an implijer-mañ|an implijerez-mañ}}",
        "userpage": "Pajenn implijer",
        "projectpage": "Pajenn meta",
        "imagepage": "Gwelet pajenn ar restr",
        "laggedslavemode": "Diwallit : marteze a-walc'h n'emañ ket ar c'hemmoù diwezhañ war ar bajenn-mañ",
        "readonly": "Hizivadurioù stanket war ar bank roadennoù",
        "enterlockreason": "Merkit perak eo stanket hag istimit pegeit e chomo evel-henn",
-       "readonlytext": "Evit poent n'haller ket ouzhpennañ pe gemmañ netra er bank roadennoù mui. Un tamm kempenn boutin d'ar bank moarvat. goude-se e vo plaen an traoù en-dro.\n\nSetu displegadenn ar merour bet prennet ar bank gantañ : $1",
+       "readonlytext": "Evit poent n'haller ket ouzhpennañ pe gemmañ netra en diaz roadennoù mui. Un tamm kempenn boutin d'an diaz moarvat. Goude-se e vo plaen an traoù en-dro.\n\nSetu displegadenn ar merour bet prennet an diaz gantañ : $1",
        "missing-article": "N'eo ket bet kavet gant an diaz titouroù testenn ur bajenn en dije dleet kavout hag anvet \"$1\" $2.\n\nPeurliesañ e c'hoarvez evit bezañ heuliet liamm dispredet un diforc'h pe an istor war-du ur bajenn bet diverket abaoe.\n\nMard ned eo ket se eo, hoc'h eus marteze kavet un draen er meziant.\nKasit keloù d'ur [[Special:ListUsers/sysop|merer]], en ur verkañ dezhañ chomlec'h an URL.",
        "missingarticle-rev": "(adweladenn # : $1)",
        "missingarticle-diff": "(Dif : $1, $2)",
        "createaccount-text": "Unan bennak en deus krouet ur gont gant ho chomlec'h postel war {{SITENAME}} ($4) zo e anv \"$2\" hag a ra gant ar ger-tremen \"$3\".\nMat e vefe deoc'h kevreañ ha cheñch ho ker-tremen bremañ.\n\nNa daolit ket evezh ouzh ar c'hemenn-mañ m'eo bet krouet ar gont dre fazi.",
        "login-throttled": "Betek re oc'h heus klasket kevreañ en aner.\nGortozit $1, mar plij, a-raok esaeañ en-dro.",
        "login-abort-generic": "Dibosupl ho kevreañ - Dilezet",
+       "login-migrated-generic": "Dilec'hiet eo bet ho kont ha n'eus ket eus hoc'h anv implijer war ar wiki-mañ ken.",
        "loginlanguagelabel": "Yezh : $1",
        "suspicious-userlogout": "Distaolet eo bet ho koulenn digevreañ rak kaset e oa bet gant ur merdeer direizhet pe krubuilhadenn ur proksi, evit doare.",
        "createacct-another-realname-tip": "Diret eo skrivañ hoc'h anv gwir. Ma skrivit anezhañ e vo implijet evit lakaat war wel ar pezh a vo bet degaset ganeoc'h.",
        "newpassword": "Ger-tremen nevez :",
        "retypenew": "Adskrivañ ar ger-tremen nevez :",
        "resetpass_submit": "Cheñch ar ger-tremen ha kevreañ",
-       "changepassword-success": "Cheñchet eo bet ho ker-tremen !",
+       "changepassword-success": "Cheñchet eo bet ho ker-tremen ervat !",
        "changepassword-throttled": "Betek re hoc'h heus klasket kevreañ en aner.\nGortozit $1, mar plij, a-raok esaeañ en-dro.",
+       "botpasswords": "Gerioù-tremen ar botoù",
+       "botpasswords-summary": "Aotren a ra <em>gerioù-tremen ar botoù</em> implijout kont un implijer dre an API hep ober gant titouroù-kred pennañ ar gont. Ur wech kevreet dre ger-tremen ur bot e c'hall gwirioù an implijer bezañ strishaet.\n\nMa n'ouzit ket mat perak e c'hallfec'h kaout c'hoant d'ober se, eo furoc'h chom hep en ober. Den ebet ne zlefe goulenn diganeoc'h biken genel unan hag e reiñ dezhañ.",
+       "botpasswords-disabled": "Diweredekaet eo gerioù-tremen ar botoù.",
+       "botpasswords-existing": "Gerioù-tremen botoù a zo anezho",
+       "botpasswords-createnew": "Krouiñ ur ger-tremen bot nevez",
+       "botpasswords-editexisting": "Cheñch ger-tremen ur bot a zo anezhañ c'hoazh",
        "botpasswords-label-appid": "Anv ar robot",
        "botpasswords-label-create": "Krouiñ",
        "botpasswords-label-update": "Hizivaat",
        "botpasswords-label-cancel": "Nullañ",
        "botpasswords-label-delete": "Dilemel",
        "botpasswords-label-resetpassword": "Adderaouekaat ar ger-tremen",
+       "botpasswords-label-grants": "Aotreoù a c'haller ober ganto :",
        "botpasswords-label-grants-column": "Aotreet",
        "botpasswords-bad-appid": "N'eo ket reizh anv ar robot « $1 »",
        "botpasswords-insert-failed": "C'hwitet eo ouzhpennadenn ar robot « $1 ». Hag ouzhpennet eo bet ?",
        "botpasswords-newpassword": "<strong>\"$2\"</strong> eo ar ger-tremen evit kevreañ gant <strong>$1</strong>. Enrollit anezhañ, par plij, evit ober dave dezhañ diwezhatoc'h.</em>",
        "botpasswords-no-provider": "N'eo ket hegerz BotPasswordsSessionProvider.",
        "resetpass_forbidden": "N'haller ket cheñch ar gerioù-termen",
+       "resetpass_forbidden-reason": "N'haller ket cheñch ar gerioù-termen : $1",
        "resetpass-no-info": "Ret eo deoc'h bezañ kevreet a-benn mont d'ar bajenn-se war-eeun.",
        "resetpass-submit-loggedin": "Cheñch ger-tremen",
        "resetpass-submit-cancel": "Nullañ",
-       "resetpass-wrong-oldpass": "Direizh eo ar ger-tremen a-vremañ pe da c'hortoz.",
+       "resetpass-wrong-oldpass": "Direizh eo ar ger-tremen dibad pe an hini a-vremañ. Moarvat ez eus bet cheñchet ger-tremen ganeoc'h c'hoazh pe goulennet ur ger-tremen dibad nevez.",
        "resetpass-recycled": "Ret eo d'ho ker-tremen nevez bezañ disheñvel diouzh ho ker-tremen a vremañ.",
        "resetpass-temp-emailed": "Kevreet e oac'h bet gant ur c'hod dibad kaset deoc'h dre bostel.\nEvit echuiñ kevreañ e rankit lakaat ur ger-tremen nevez amañ :",
        "resetpass-temp-password": "Ger-tremen da c'hortoz :",
        "passwordreset-emailtext-user": "Goulennet en deus an implijer $1 war  {{SITENAME}} e vefe degaset soñj dezhañ eus titouroù e gont evit {{SITENAME}} ($4). Emañ liammet {{PLURAL:$3|ar gont implijer|ar c'hontoù implijer}} da-heul gant ar chomlec'h postel-mañ :\n\n$2\n\nMont a raio da get {{PLURAL:$3|ar ger-tremen da c'hortoz|ar gerioù-tremen da c'hortoz}} a-benn {{PLURAL:$5|un devezh|$5 deiz}}.\nMat e vefe deoc'h kevreañ ha dibab ur ger-tremen nevez bremañ. Mard eo bet goulennet kement-se gant unan bennak all pe m'hoc'h eus soñj eus ho ker-tremen orin ha mar ne fell ket deoc'h e cheñch ken, na daolit ket evezh ouzh ar gemennadenn-mañ ha dalc'hit d'ober gant ho ker-tremen kozh.",
        "passwordreset-emailelement": "Anv implijer :           \n$1\n\nGer-tremen da c'hortoz : \n$2",
        "passwordreset-emailsentemail": "Kaset ez eus bet ur postel deoc'h da adderaouekaat ho ker-tremen.",
+       "passwordreset-nocaller": "Ret eo merkañ anv ur galver",
+       "passwordreset-nosuchcaller": "N'eus ket eus ar galver : $1",
        "passwordreset-invalidemail": "Chomlec'h postel direizh",
        "changeemail": "Kemmañ ar chomlec'h postel",
        "changeemail-header": "Kemmañ chomlec'h postel ar gont",
        "changeemail-password": "Ho ker-tremen war {{SITENAME}}:",
        "changeemail-submit": "Cheñch chomlec'h postel",
        "changeemail-throttled": "Betek re hoc'h heus klasket kevreañ en aner.\nGortozit $1, mar plij, a-raok esaeañ en-dro.",
+       "changeemail-nochange": "Merkit ur chomlec'h postel all.",
        "resettokens": "Adderaouekaat ar jedoueroù",
        "resettokens-no-tokens": "N'eus jedouer ebet da adderaouekaat.",
        "resettokens-tokens": "Jedoueroù :",
        "content-model-javascript": "Javascript",
        "content-model-css": "CSS",
        "content-json-empty-object": "Elfenn goullo",
+       "content-json-empty-array": "Taolenn c'houllo",
        "expensive-parserfunction-warning": "Diwallit : Re a c'halvoù koustus e-keñver an arc'hwelioù parser zo gant ar bajenn-mañ.\n\nDleout a rafe bezañ nebeutoc'h eget $2 {{PLURAL:$2|galv|galv}}, ha {{PLURAL:$1|$1 galv|$1 galv}} zo.",
        "expensive-parserfunction-category": "Pagjennoù enno re a c'halvoù koustus e-keñver an arc'hwelioù parser.",
        "post-expand-template-inclusion-warning": "Diwallit : re a batromoù zo war ar bajenn-mañ.\nLod anezho a vo lakaet a-gostez.",
        "prefs-watchlist-token": "Jedouer evit ar roll evezhiañ :",
        "prefs-misc": "Penndibaboù liesseurt",
        "prefs-resetpass": "Cheñch ar ger-tremen",
-       "prefs-changeemail": "Cheñch chomlec'h postel",
+       "prefs-changeemail": "Cheñch ar chomlec'h postel pe dilemel anezhañ",
        "prefs-setemail": "Termeniñ ur chomlec'h postel",
        "prefs-email": "Dibarzhioù postel",
        "prefs-rendering": "Neuz",
        "columns": "Bannoù",
        "searchresultshead": "Klask",
        "stub-threshold": "Bevenn uhelañ evit al liammoù war-du an danvez pennadoù ($1) :",
+       "stub-threshold-sample-link": "skouer",
        "stub-threshold-disabled": "Diweredekaet",
        "recentchangesdays": "Niver a zevezhioù da ziskouez er c'hemmoù diwezhañ :",
        "recentchangesdays-max": "D'ar muiañ $1 {{PLURAL:$1|deiz|deiz}}",
        "prefs-help-prefershttps": "Efediñ a ray an dibarzh-mañ kentañ gwech ma kevreoc'h.",
        "prefs-tabs-navigation-hint": "Titourig : Gallout a rit implijout an touchennoù bir kleiz ha bir dehoù evit merdeiñ etre an ivinelloù e roll an ivinelloù.",
        "userrights": "Merañ statud an implijerien",
-       "userrights-lookup-user": "Merañ strolladoù an implijer",
+       "userrights-lookup-user": "Diuzañ un implijer",
        "userrights-user-editname": "Lakait un anv implijer :",
-       "editusergroup": "Kemmañ ar strolladoù implijerien",
-       "editinguser": "Kemmañ gwirioù an implijer '''[[User:$1|$1]]''' $2",
+       "editusergroup": "Kargañ strolladoù implijerien",
+       "editinguser": "O kemmañ gwirioù an {{GENDER:$1|implijer|implijerez}} <strong>[[User:$1|$1]]</strong> $2",
        "userrights-editusergroup": "Kemmañ strolladoù an implijer",
        "userrights-viewusergroup": "Gwelet ar strolladoù implijerien",
        "saveusergroups": "Enrollañ strolladoù an {{GENDER:$1|implijer|implijerez}}",
        "grant-blockusers": "Stankañ ha distankañ implijerien",
        "grant-createaccount": "Krouiñ kontoù",
        "grant-createeditmovepage": "Krouiñ, aozañ ha dilec'hiañ pajennoù",
-       "grant-editmywatchlist": "Aozañ ho roll evezhiañ",
-       "grant-editpage": "Aoañ pajennoù a zo anezho dija",
-       "grant-editprotected": "Aozañ pajennoù gwarezet",
+       "grant-editmyoptions": "Kemmañ ho penndibaboù implijer.",
+       "grant-editmywatchlist": "Kemmañ ho roll evezhiañ",
+       "grant-editpage": "Kemmañ pajennoù a zo anezho c'hoazh",
+       "grant-editprotected": "Kemmañ pajennoù gwarezet",
+       "grant-protect": "Gwareziñ ha diwareziñ pajennoù",
+       "grant-rollback": "Distreiñ war ar c'hemmoù er pajennoù",
        "grant-sendemail": "Kas ur postel d'an implijerien all",
+       "grant-uploadfile": "Enporzhiañ restroù nevez",
        "grant-basic": "Gwirioù diazez",
-       "grant-viewdeleted": "Gwelet an titouroù dilamet",
+       "grant-viewdeleted": "Gwelet ar restroù ha pajennoù dilamet",
        "grant-viewmywatchlist": "Gwelet ho roll evezhiañ",
        "newuserlogpage": "Marilh ar c'hontoù krouet",
        "newuserlogpagetext": "Marilh krouiñ ar c'hontoù implijer.",
        "rightslogtext": "Setu marilh ar c'hemmoù statud bet c'hoarvezet d'an implijerien.",
        "action-read": "lenn ar bajenn-mañ",
        "action-edit": "kemmañ ar bajenn-mañ",
-       "action-createpage": "krouiñ pajennoù",
+       "action-createpage": "krouiñ ar bajenn-mañ",
        "action-createtalk": "krouiñ pajennoù kaozeal",
        "action-createaccount": "krouiñ ar gont implijer-mañ",
        "action-history": "gwelet istor ar bajenn-mañ",
        "action-userrights-interwiki": "Kemmañ gwirioù an implijerien war wikioù all",
        "action-siteadmin": "Prennañ pe dibrennañ ar bank roadennoù",
        "action-sendemail": "Kas posteloù",
+       "action-editmyoptions": "Kemmañ ho penndibaboù",
        "action-editmywatchlist": "kemmañ ho roll evezhiañ",
        "action-viewmywatchlist": "gwelet ho roll evezhiañ",
        "action-viewmyprivateinfo": "Gwelet ho titouroù prevez",
        "action-editmyprivateinfo": "aozañ ho titouroù prevez",
        "action-deletechangetags": "Diverkañ tikedennoù a-ziwar an diaz-roadennoù",
+       "action-purge": "spurjañ ar bajenn-mañ",
        "nchanges": "$1 {{PLURAL:$1|kemm|kemm}}",
        "enhancedrc-since-last-visit": "$1 {{PLURAL:$1|abaoe ho kweladenn diwezhañ}}",
        "enhancedrc-history": "istor",
        "recentchanges-legend-heading": "<strong>Alc'hwez :</strong>",
        "recentchanges-legend-newpage": "{{int:recentchanges-label-newpage}} (gwelet ivez [[Special:NewPages|roll ar pajennoù nevez]])",
        "recentchanges-submit": "Diskouez",
-       "rcnotefrom": "Setu aze roll ar c'hemmoù c'hoarvezet abaoe an <strong>$2</strong> (<strong>$1</strong> d'ar muiañ).",
+       "rcfilters-activefilters": "Siloù oberiant",
+       "rcfilters-invalid-filter": "Sil direizh",
+       "rcfilters-filterlist-title": "Siloù",
+       "rcfilters-filterlist-noresults": "N'eus bet kavet sil ebet",
+       "rcfilters-filter-editsbyself-label": "Kemmet ganeoc'h",
+       "rcfilters-filter-editsbyself-description": "Kemmet ganeoc'h",
+       "rcfilters-filter-editsbyother-label": "Kemmet gant tud all",
+       "rcfilters-filter-editsbyother-description": "Kemmoù graet gant implijerien all (ket ganeoc'h).",
+       "rcfilters-filtergroup-userExpLevel": "Live skiant-prenañ an implijer",
+       "rcfilters-filter-userExpLevel-newcomer-label": "Tud nevez-deuet",
+       "rcfilters-filter-userExpLevel-learner-label": "Deskarded",
+       "rcfilters-filter-userExpLevel-experienced-label": "Implijerien arroutet",
+       "rcfilters-filter-userExpLevel-experienced-description": "Ouzhpenn 30 devezh oberiantiz ha 500 kemm.",
+       "rcnotefrom": "Setu aze {{PLURAL:$5|ar c'hemm|ar c'hemmoù}} c'hoarvezet abaoe an <strong>$3, $4</strong> (<strong>$1</strong> d'ar muiañ).",
        "rclistfrom": "Diskouez ar c'hemmoù diwezhañ abaoe an/ar $3 $2",
        "rcshowhideminor": "$1 ar c'hemmoù dister",
        "rcshowhideminor-show": "Diskouez",
        "recentchangeslinked-summary": "Rollet eo war ar bajenn dibar-mañ ar c'hemmoù diwezhañ bet degaset war ar pajennoù liammet ouzh ur bajenn lakaet (pe ouzh izili ur rummad lakaet).\nE '''tev''' emañ ar pajennoù zo war ho [[Special:Watchlist|roll evezhiañ]].",
        "recentchangeslinked-page": "Anv ar bajenn :",
        "recentchangeslinked-to": "Diskouez ar c'hemmoù war-du ar pajennoù liammet kentoc'h eget re ar bajenn lakaet",
+       "recentchanges-page-added-to-category": "[[:$1]] ouzhpennet d'ar rummad",
        "recentchanges-page-removed-from-category": "Diverket eo bet [[$1]] diouzh ar rummad",
        "upload": "Kargañ war ar servijer",
        "uploadbtn": "Kargañ ur restr",
        "upload-form-label-infoform-description": "Deskrivadur",
        "upload-form-label-usage-title": "Implij",
        "upload-form-label-usage-filename": "Anv ar restr",
+       "upload-form-label-own-work": "Setu aze ma zammig labour din-me",
        "upload-form-label-infoform-categories": "Rummadoù",
        "upload-form-label-infoform-date": "Deiziad",
        "backend-fail-stream": "Dibosupl eo lenn ar restr $1.",
        "apisandbox-dynamic-parameters-add-label": "Ouzhpennañ un arventenn:",
        "apisandbox-dynamic-parameters-add-placeholder": "Anv an arventenn",
        "apisandbox-results": "Disoc'hoù",
+       "apisandbox-request-params-json": "Arventennoù JSON :",
        "apisandbox-request-url-label": "Goulenn URL :",
        "apisandbox-request-time": "Pad ar goulenn: $1",
        "apisandbox-continue": "Kenderc'hel",
        "apisandbox-continue-clear": "Riñsañ",
+       "apisandbox-multivalue-all-values": "$1 (An holl dalvoudoù)",
        "booksources": "Oberennoù dave",
        "booksources-search-legend": "Klask en oberennoù dave",
        "booksources-isbn": "ISBN :",
        "booksources-search": "Klask",
        "booksources-text": "Ur roll liammoù a gas da lec'hiennoù all ma werzher levrioù kozh ha nevez a gavot a-is; marteze e kavot eno titouroù pelloc'h war al levrioù a glaskit :",
        "booksources-invalid-isbn": "Evit doare n'eo ket reizh an ISBN merket; gwiriit ha n'oc'h ket faziet en ur eilañ adal ar vammenn orin.",
+       "magiclink-tracking-isbn": "Pajennoù a ra gant liammoù burzhudus ISBN",
        "specialloguserlabel": "Implijer :",
        "speciallogtitlelabel": "Bukadenn (titl pe implijer) :",
        "log": "Marilhoù",
        "confirm-unwatch-button": "Mat eo",
        "confirm-unwatch-top": "Lemel ar bajenn-mañ a-ziwar ho roll evezhiañ",
        "confirm-rollback-button": "Mat eo",
+       "confirm-rollback-top": "Disteurel ar c'hemmoù graet er bajenn-mañ ?",
        "quotation-marks": "« $1 »",
        "imgmultipageprev": "&larr; pajenn gent",
        "imgmultipagenext": "pajenn war-lerc'h &rarr;",
        "watchlistedit-raw-done": "Nevesaet eo bet ho roll evezhiañ.",
        "watchlistedit-raw-added": "Ouzhpennet ez eus bet {{PLURAL:$1|1 pajenn|$1 pajenn}} :",
        "watchlistedit-raw-removed": "Tennet ez eus bet {{PLURAL:$1|1 pajenn|$1 pajenn}} :",
-       "watchlistedit-clear-title": "Roll evezhiañ goulloet",
+       "watchlistedit-clear-title": "Diverkañ ar roll-evezhiañ",
        "watchlistedit-clear-legend": "Diverkañ ar roll-evezhiañ",
        "watchlistedit-clear-explain": "Lamet e vo an holl ditloù eus ho roll evezhiañ",
        "watchlistedit-clear-titles": "Titloù :",
        "log-action-filter-protect-protect": "Gwarez",
        "log-action-filter-protect-unprotect": "Diwarez",
        "log-action-filter-rights-autopromote": "Kemm emgefre",
+       "authmanager-authn-no-primary": "N'eus ket bet gallet gwiriañ an titouroù kred lakaet.",
+       "authmanager-authn-no-local-user-link": "Reizh eo an titouroù kred lakaet met n'int ket liammet ouzh implijer ebet eus ar wiki-mañ. Ma kevreit en ur mod all pe ma krouit ur gont implijer nevez e c'hallot liammañ ho titouroù kred kent ouzh ar gont-mañ.",
+       "authmanager-change-not-supported": "N'haller ket cheñch an titouroù kred rak netra na rafe ganto.",
+       "authmanager-create-no-primary": "N'eus ket bet gallet implijout an titouroù kred lakaet evit krouiñ ur gont.",
        "authmanager-authplugin-setpass-failed-title": "C'hwitet eo bet ar cheñchamant ger-tremen",
        "authmanager-authplugin-setpass-bad-domain": "Domani direizh.",
        "authmanager-userdoesnotexist": "N'eo ket enrollet ar gont implijer \"$1\".",
        "authpage-cannot-create": "N'haller ket kregiñ da grouiñ ar gont.",
        "cannotauth-not-allowed-title": "Aotre nac'het",
        "cannotauth-not-allowed": "N'oc'h ket aotreet d'ober gant ar bajenn-mañ",
+       "changecredentials": "Kemmañ an titouroù kred",
+       "changecredentials-submit": "Kemmañ an titouroù kred",
+       "changecredentials-invalidsubpage": "N'eo ket $1 ur seurt titour kred reizh.",
+       "removecredentials": "Lemel an titouroù kred",
+       "removecredentials-submit": "Lemel an aotreoù",
+       "removecredentials-invalidsubpage": "N'eo ket $1 ur seurt titour kred reizh.",
+       "credentialsform-provider": "Seurt titouroù kred :",
        "credentialsform-account": "Anv ar gont :",
        "cannotlink-no-provider-title": "N'eus kont ebet da liammañ",
        "cannotlink-no-provider": "N'eus kont ebet da liammañ.",
index c02cb2d..e42972d 100644 (file)
        "recentchanges-legend-newpage": "{{int:recentchanges-label-newpage}} (vegeu també la [[Special:NewPages|llista de pàgines noves]])",
        "recentchanges-legend-plusminus": "(''±123'')",
        "recentchanges-submit": "Mostra",
+       "rcfilters-activefilters": "Filtres actius",
+       "rcfilters-search-placeholder": "Canvis recents dels filtres (navegueu o comenceu a escriure)",
+       "rcfilters-invalid-filter": "Filtre no vàlid",
+       "rcfilters-filterlist-title": "Filtres",
+       "rcfilters-filterlist-noresults": "No s'ha trobat cap filtre",
+       "rcfilters-filtergroup-authorship": "Modifica l'autoria",
+       "rcfilters-filter-editsbyself-label": "Les vostres modificacions",
+       "rcfilters-filter-editsbyself-description": "Modificacions vostres.",
+       "rcfilters-filter-editsbyother-label": "Modificacions d'altres",
+       "rcfilters-filter-editsbyother-description": "Modificacions creades per altres usuaris (no vostres)",
        "rcnotefrom": "A sota hi ha {{PLURAL:$5|el canvi|els canvis}} a partir de <strong>$3, $4</strong> (fins a <strong>$1</strong>).",
        "rclistfrom": "Mostra els canvis nous des de $3, $2",
        "rcshowhideminor": "$1 edicions menors",
        "apisandbox-sending-request": "S'està enviant una sol·licitud API...",
        "apisandbox-loading-results": "S'estan reben els resultats de l'API...",
        "apisandbox-results-error": "S'ha produït un error en carregar la resposta de la consulta de l'API: $1.",
+       "apisandbox-request-params-json": "Paràmetres JSON:",
        "apisandbox-request-url-label": "Sol·licita URL:",
        "apisandbox-request-time": "Temps de sol·licitud: {{PLURAL:$1|$1 ms}}",
        "apisandbox-results-fixtoken": "Corregeix el testimoni i torna-ho a enviar",
        "modifiedarticleprotection": "ha canviat el nivell de protecció de «[[$1]]»",
        "unprotectedarticle": "ha desprotegit \"[[$1]]\"",
        "movedarticleprotection": "ha traslladat els ajustaments de protecció des de «[[$2]]» a «[[$1]]»",
+       "protectedarticle-comment": "{{GENDER:$2|Ha protegit}} «[[$1]]»",
+       "modifiedarticleprotection-comment": "{{GENDER:$2|Ha canviat el nivell de protecció}} de «[[$1]]»",
+       "unprotectedarticle-comment": "{{GENDER:$2|Ha suprimit la protecció}} de «[[$1]]»",
        "protect-title": "Canviant la protecció de «$1»",
        "protect-title-notallowed": "Mostra el nivell de protecció de \" $1 \"",
        "prot_1movedto2": "[[$1]] mogut a [[$2]]",
        "cant-move-to-user-page": "No teniu permís per a moure una pàgina a una pàgina d'usuari (independentment de poder fer-ho cap a una subpàgina d'usuari).",
        "cant-move-category-page": "No teniu permisos per a moure pàgines de categoria.",
        "cant-move-to-category-page": "No teniu permisos per a moure una pàgina a una pàgina de categoria.",
+       "namespace-nosubpages": "L'espai de noms «$1» no permet subpàgines.",
        "newtitle": "Títol nou:",
        "move-watch": "Vigila aquesta pàgina",
        "movepagebtn": "Reanomena la pàgina",
        "log-show-hide-patrol": "$1 el registre de patrulla",
        "log-show-hide-tag": "$1 el registre d’etiquetes",
        "confirm-markpatrolled-button": "D'acord",
+       "confirm-markpatrolled-top": "Voleu marcar la revisió $3 de $2 com a patrullada?",
        "deletedrevision": "S'ha eliminat la revisió antiga $1.",
        "filedeleteerror-short": "Error en suprimir el fitxer: $1",
        "filedeleteerror-long": "S'han produït errors en suprimir el fitxer:\n\n$1",
        "pagelang-use-default": "Utilitza l'idioma per defecte",
        "pagelang-select-lang": "Selecciona un idioma",
        "pagelang-submit": "Envia",
+       "pagelang-nonexistent-page": "La pàgina $1 no existeix.",
+       "pagelang-unchanged-language": "La pàgina $1 ja està configurada en la llengua: $2.",
+       "pagelang-unchanged-language-default": "La pàgina $1 ja està configurada en la llengua de contingut per defecte del wiki.",
+       "pagelang-db-failed": "La base de dades no ha pogut canviar la llengua de la pàgina.",
        "right-pagelang": "Canvia l'idioma de la pàgina",
        "action-pagelang": "canvia l'idioma de la pàgina",
        "log-name-pagelang": "Registre de canvi de llengua",
        "log-action-filter-delete-restore": "Restauració de pàgines",
        "log-action-filter-delete-event": "Registre de supressió",
        "log-action-filter-delete-revision": "Supressió de revisions",
+       "log-action-filter-import-upload": "Importació mitjançant càrrega d'XML",
        "log-action-filter-managetags-create": "Creació de l'etiqueta",
        "log-action-filter-managetags-delete": "Supressió de l'etiqueta",
        "log-action-filter-managetags-activate": "Activació de l'etiqueta",
        "cannotauth-not-allowed": "No teniu permisos per utilitzar la pàgina",
        "changecredentials": "Canvi de dades credencials",
        "changecredentials-submit": "Canvia les dades credencials",
+       "changecredentials-success": "Les vostres credencials han estat canviades.",
        "removecredentials": "Suprimeix les credencials",
        "removecredentials-submit": "Suprimeix les credencials",
        "removecredentials-invalidsubpage": "$1 no és un tipus de credencial vàlid.",
index eecc893..78e430e 100644 (file)
        "undelete-show-file-submit": "ХӀаъ",
        "namespace": "ЦӀерийн меттигаш:",
        "invert": "Хаьржинарг къайлаяккха",
-       "tooltip-invert": "ХӀоттае хӀара билгало, хаьржинчу цӀерийн анан агӀонийн хийцамаш къайлабаха (кхин дихкина цӀерийн анаш, гайтина елахь)",
+       "tooltip-invert": "ХӀоттае хӀара билгало, хаьржинчу цӀерийн меттигийн агӀонийн хийцамаш къайлабаха (кхин дихкина цӀерийн анаш, гайтина елахь)",
+       "tooltip-whatlinkshere-invert": "ХӀоттае хӀара билгало, хаьржинчу цӀерийн меттигийн агӀонийн хьажоргаш къайлаяха.",
        "namespace_association": "Йихкина меттиг",
        "tooltip-namespace_association": "ХӀоттае хӀара билгало, иштта дийцарийн (я кхин) цӀерийн меттиг юкъахь хилийта",
        "blanknamespace": "(Коьрта)",
index f0a86b9..aceb87e 100644 (file)
        "proxyblockreason": "Vaše IP adresa byla zablokována, protože funguje jako otevřený proxy server. Kontaktujte svého poskytovatele internetového připojení nebo technickou podporu a informujte je o tomto vážném bezpečnostním problému.",
        "sorbsreason": "Vaše IP adresa je uvedena na seznamu DNSBL jako otevřený proxy server.",
        "sorbs_create_account_reason": "Vaše IP adresa je uvedena na seznamu DNSBL jako otevřený proxy server. Z této adresy si nemůžete založit účet",
+       "softblockrangesreason": "Anonymní příspívání z vaší IP adresy ($1) není dovoleno. Prosíme přihlaste se.",
        "xffblockreason": "IP adresa uvedená v hlavičce X-Forwarded-For, ať už vaše, nebo patřící proxy serveru, který používáte, byla zablokována. Zdůvodnění tohoto zablokování: $1",
        "cant-see-hidden-user": "Uživatel, kterého se snažíte blokovat, už byl zablokován a skryt. Jelikož nemáte oprávnění hideuser, nemůžete si nastavení bloku tohoto uživatele prohlédnout ani ho změnit.",
        "ipbblocked": "Nemůžete blokovat nebo odblokovávat jiné uživatele, {{GENDER:|sám|sama|sám}} jste {{GENDER:|zablokován|zablokována|zablokován}}.",
        "api-error-unclassified": "Došlo k neznámé chybě.",
        "api-error-unknown-code": "Neznámá chyba: „$1“.",
        "api-error-unknown-error": "Vnitřní chyba: došlo k chybě při pokusu o načtení souboru.",
-       "api-error-unknown-warning": "Neznámé varování: $1",
+       "api-error-unknown-warning": "Neznámé varování: „$1“.",
        "api-error-unknownerror": "Neznámá chyba: „$1“.",
        "api-error-uploaddisabled": "Načítání souborů je na této wiki vypnuto.",
        "api-error-verification-error": "Soubor je možná poškozen nebo má špatnou příponu.",
        "pagelang-language": "Jazyk",
        "pagelang-use-default": "Použít implicitní jazyk",
        "pagelang-select-lang": "Vybrat jazyk",
+       "pagelang-reason": "Důvod",
        "pagelang-submit": "Odeslat",
+       "pagelang-nonexistent-page": "Stránka $1 neexistuje.",
+       "pagelang-unchanged-language": "Stránka $1 již má nastavený jazyk $2.",
+       "pagelang-unchanged-language-default": "Stránka $1 již má jako jazyk nastavený výchozí jazyk obsahu wiki.",
+       "pagelang-db-failed": "Databázi se nepodařilo změnit jazyk stránky.",
        "right-pagelang": "Změnit jazyk stránky",
        "action-pagelang": "měnit jazyk stránky",
        "log-name-pagelang": "Kniha změn jazyků",
index ed98ba9..abedc44 100644 (file)
        "recentchanges-legend-newpage": "{{int:recentchanges-label-newpage}} (siehe auch die [[Special:NewPages|Liste neuer Seiten]])",
        "recentchanges-legend-plusminus": "''(±123)''",
        "recentchanges-submit": "Anzeigen",
+       "rcfilters-activefilters": "Aktive Filter",
+       "rcfilters-search-placeholder": "Letzte Änderungen filtern (durchsuchen oder beginne mit der Eingabe)",
+       "rcfilters-invalid-filter": "Ungültiger Filter",
+       "rcfilters-filterlist-title": "Filter",
+       "rcfilters-filterlist-noresults": "Keine Filter gefunden",
+       "rcfilters-filtergroup-authorship": "Bearbeitungs-Autorenschaft",
+       "rcfilters-filter-editsbyself-label": "Deine eigenen Bearbeitungen",
+       "rcfilters-filter-editsbyself-description": "Bearbeitungen von dir.",
+       "rcfilters-filter-editsbyother-label": "Bearbeitungen von anderen",
+       "rcfilters-filter-editsbyother-description": "Bearbeitungen von anderen Benutzern (nicht von dir)",
+       "rcfilters-filtergroup-userExpLevel": "Niveau der Benutzererfahrung",
+       "rcfilters-filter-userExpLevel-newcomer-label": "Neulinge",
+       "rcfilters-filter-userExpLevel-newcomer-description": "Sehr neue Autoren: Weniger als 10 Bearbeitungen und eine Aktivität von weniger als 4 Tagen.",
+       "rcfilters-filter-userExpLevel-learner-label": "Anfänger",
+       "rcfilters-filter-userExpLevel-learner-description": "Eine Aktivität von mehreren Tagen und mehr Bearbeitungen als „Neulinge“, aber weniger als „Erfahrene Benutzer“.",
+       "rcfilters-filter-userExpLevel-experienced-label": "Erfahrene Benutzer",
+       "rcfilters-filter-userExpLevel-experienced-description": "Eine Aktivität von mehr als 30 Tagen und mehr als 500 Bearbeitungen.",
        "rcnotefrom": "Angezeigt {{PLURAL:$5|wird die Änderung|werden die Änderungen}} seit <strong>$3, $4</strong> (max. <strong>$1</strong> Einträge).",
        "rclistfrom": "Nur Änderungen seit $3, $2 Uhr zeigen.",
        "rcshowhideminor": "Kleine Änderungen $1",
        "proxyblockreason": "Deine IP-Adresse wurde gesperrt, da sie ein offener Proxy ist. Bitte kontaktiere deinen Internet-Provider oder deine Systemadministratoren und informiere sie über dieses mögliche Sicherheitsproblem.",
        "sorbsreason": "Die IP-Adresse ist in der DNSBL von {{SITENAME}} als offener PROXY gelistet.",
        "sorbs_create_account_reason": "Die IP-Adresse ist in der DNSBL von {{SITENAME}} als offener PROXY gelistet. Das Anlegen neuer Benutzer ist nicht möglich.",
+       "softblockrangesreason": "Anonyme Beiträge von deiner IP-Adresse ($1) sind nicht erlaubt. Bitte melde dich an.",
        "xffblockreason": "Eine IP-Adresse im X-Forwarded-For-Header wurde gesperrt, entweder deine oder die des benutzten Proxyservers. Der ursprüngliche Sperrgrund war: $1",
        "cant-see-hidden-user": "Der Benutzer, den du versuchst zu sperren, wurde bereits gesperrt und verborgen. Da du das „hideuser“-Recht nicht hast, kannst du die Benutzersperre nicht sehen und nicht bearbeiten.",
        "ipbblocked": "Du kannst keine anderen Benutzer sperren oder entsperren, da du selbst gesperrt bist",
        "movepage-page-exists": "Die Seite „$1“ ist bereits vorhanden und kann nicht automatisch überschrieben werden.",
        "movepage-page-moved": "Die Seite „$1“ wurde nach „$2“ verschoben.",
        "movepage-page-unmoved": "Die Seite „$1“ konnte nicht nach „$2“ verschoben werden.",
-       "movepage-max-pages": "Die Maximalanzahl von $1 {{PLURAL:$1|Seite|Seiten}} wurde verschoben, Alle weiteren Seiten können nicht automatisch verschoben werden.",
+       "movepage-max-pages": "Es wurde die Maximalanzahl von {{PLURAL:$1|einer Seite|$1 Seiten}} verschoben. Alle weiteren Seiten können nicht automatisch verschoben werden.",
        "movelogpage": "Verschiebungs-Logbuch",
        "movelogpagetext": "Dies ist eine Liste aller verschobenen Seiten.",
        "movesubpage": "{{PLURAL:$1|Unterseite|Unterseiten}}",
        "pagelang-language": "Sprache",
        "pagelang-use-default": "Standardsprache verwenden",
        "pagelang-select-lang": "Sprache auswählen",
+       "pagelang-reason": "Grund",
        "pagelang-submit": "Übermitteln",
+       "pagelang-nonexistent-page": "Die Seite $1 ist nicht vorhanden.",
+       "pagelang-unchanged-language": "Die Seite $1 ist bereits auf die Sprache $2 festgelegt.",
+       "pagelang-unchanged-language-default": "Die Seite $1 ist bereits auf die Standardinhaltssprache des Wikis festgelegt.",
+       "pagelang-db-failed": "Die Datenbank konnte die Seitensprache nicht ändern.",
        "right-pagelang": "Seitensprache ändern",
        "action-pagelang": "die Seitensprache zu ändern",
        "log-name-pagelang": "Sprachenänderungs-Logbuch",
index 334e655..cf7337c 100644 (file)
        "diff-multi-otherusers": "(Terefê {{PLURAL:$2|yew karberi|$2 karberan}} ra {{PLURAL:$1|yew revizyono miyanên nêmocno|$1 revizyonê miyanêni nêmocnê}})",
        "diff-multi-manyusers": "({{PLURAL:$1|jew timar kerdışo qıckeko|$1 timar kerdışo qıckeko}} timar kerdo, $2 {{PLURAL:$2|Karber|karberi}} memocne)",
        "difference-missing-revision": "Ferqê {{PLURAL:$2|Yew rewizyonê|$2 rewizyonê}} {{PLURAL:$2|dı|dı}} ($1) sero çıniyo.\n\nNo normal de werênayış dê pelanê besterneyan dı ena xırabin asena.\nDetayê besternayışi [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} tiya dı] aseno.",
-       "searchresults": "Peyniyê cıgeyrayışi",
+       "searchresults": "Peyniyê cı geyrayışi",
        "searchresults-title": "Qandê \"$1\" neticeyê geyrayışi",
        "titlematches": "Tekê (zewcê) sernameyê pele",
        "textmatches": "Tekê (zewcê) nuştey pele",
        "usermessage-editor": "Xeberdarê sistemi",
        "usermessage-template": "MediaWiki:UserMessage",
        "watchlist": "Listey pawıteyan",
-       "mywatchlist": "Seyr kerdışi",
+       "mywatchlist": "Lista seyrkerdışi",
        "watchlistfor2": "Qandê $1 ($2)",
        "nowatchlist": "listeya temaşa kerdıişê şıma de yew madde zi çina.",
        "watchlistanontext": "qey vurnayişê maddeya listeya temaşakerdiş ronıştış akerê",
index 3cfb2c2..28f3888 100644 (file)
        "accountcreated": "Ο λογαριασμός δημιουργήθηκε",
        "accountcreatedtext": "Ο λογαριασμός χρήστη για τον/την [[{{ns:User}}:$1|$1]] ([[{{ns:User talk}}:$1|συζήτηση]]) έχει δημιουργηθεί.",
        "createaccount-title": "Δημιουργία λογαριασμού για {{SITENAME}}",
-       "createaccount-text": "Î\9aάÏ\80οιοÏ\82 Î´Î·Î¼Î¹Î¿Ï\8dÏ\81γηÏ\83ε Î­Î½Î±Î½ Î»Î¿Î³Î±Ï\81ιαÏ\83μÏ\8c Î³Î¹Î± Ï\84η Î´Î¹ÎµÏ\8dθÏ\85νÏ\83η email Ï\83αÏ\82 Ï\83Ï\84ο {{SITENAME}} ($4) Î¼Îµ Ï\84ο Ï\8cνομα \"$2\", Î¼Îµ ÎºÏ\89δικÏ\8c Ï\80Ï\81Ï\8cÏ\83βαÏ\83ηÏ\82 \"$3\". Î\98α Ï\80Ï\81έÏ\80ει Î½Î± Ï\83Ï\85νδεθείÏ\84ε ÎºÎ±Î¹ Î½Î± Î±Î»Î»Î¬Î¾ÎµÏ\84ε Ï\84ον ÎºÏ\89δικÏ\8c Ï\80Ï\81Ï\8cÏ\83βαÏ\83ήÏ\82 Ï\83αÏ\82 Ï\84Ï\8eÏ\81α.\n\nÎ\9cÏ\80οÏ\81είÏ\84ε Î½Î± Î±Î³Î½Î¿Î®Ï\83εÏ\84ε Î±Ï\85Ï\84Ï\8c Ï\84ο Î¼Î®Î½Ï\85μα, Î±Î½ Î±Ï\85Ï\84Ï\8cÏ\82 Î¿ Î»Î¿Î³Î±Ï\81ιαÏ\83μÏ\8cÏ\82 Î´Î·Î¼Î¹Î¿Ï\85Ï\81γήθηκε ÎµÏ\83Ï\86αλμένα.",
+       "createaccount-text": "Î\9aάÏ\80οιοÏ\82 Î´Î·Î¼Î¹Î¿Ï\8dÏ\81γηÏ\83ε Î»Î¿Î³Î±Ï\81ιαÏ\83μÏ\8c Î³Î¹Î± Ï\84η Î´Î¹ÎµÏ\8dθÏ\85νÏ\83η Ï\83αÏ\82 Î·Î»ÎµÎºÏ\84Ï\81ονικοÏ\8d Ï\84αÏ\87Ï\85δÏ\81ομείοÏ\85 Ï\83Ï\84ο {{SITENAME}} ($4) Î¼Îµ Ï\8cνομα Â«$2» ÎºÎ±Î¹ Ï\83Ï\85νθημαÏ\84ικÏ\8c Â«$3». Î¤Ï\8eÏ\81α Î¸Î± Ï\80Ï\81έÏ\80ει Î½Î± Ï\83Ï\85νδεθείÏ\84ε ÎºÎ±Î¹ Î½Î± Î±Î»Î»Î¬Î¾ÎµÏ\84ε Ï\84ο Ï\83Ï\85νθημαÏ\84ικÏ\8c Ï\83αÏ\82.\n\nÎ\9cÏ\80οÏ\81είÏ\84ε Î½Î± Î±Î³Î½Î¿Î®Ï\83εÏ\84ε Î±Ï\85Ï\84Ï\8c Ï\84ο Î¼Î®Î½Ï\85μα, Î±Î½ Î±Ï\85Ï\84Ï\8cÏ\82 Î¿ Î»Î¿Î³Î±Ï\81ιαÏ\83μÏ\8cÏ\82 Î´Î·Î¼Î¹Î¿Ï\85Ï\81γήθηκε Î±Ï\80Ï\8c Î»Î¬Î¸Î¿Ï\82.",
        "login-throttled": "Κάνατε πάρα πολλές πρόσφατες απόπειρες σύνδεσης.\nΠαρακαλούμε περιμένετε $1 προτού ξαναδοκιμάσετε.",
        "login-abort-generic": "Η είσοδος σας απέτυχε - Ματαίωση",
        "login-migrated-generic": "Ο λογαριασμός σας έχει μεταναστεύσει, και το όνομα χρήστη σας δεν υπάρχει πλέον σε αυτό το wiki.",
index f2b27fc..a621f1c 100644 (file)
        "recentchanges-legend-unpatrolled": "{{int:recentchanges-label-unpatrolled}}",
        "recentchanges-legend-plusminus": "(<em>±123</em>)",
        "recentchanges-submit": "Show",
+       "rcfilters-activefilters": "Active filters",
+       "rcfilters-search-placeholder": "Filter recent changes (browse or start typing)",
+       "rcfilters-invalid-filter": "Invalid filter",
+       "rcfilters-filterlist-title": "Filters",
+       "rcfilters-filterlist-noresults": "No filters found",
+       "rcfilters-filtergroup-authorship": "Edit authorship",
+       "rcfilters-filter-editsbyself-label": "Your own edits",
+       "rcfilters-filter-editsbyself-description": "Edits by you.",
+       "rcfilters-filter-editsbyother-label": "Edits by others",
+       "rcfilters-filter-editsbyother-description": "Edits created by other users (not you.)",
+       "rcfilters-filtergroup-userExpLevel": "User experience level",
+       "rcfilters-filter-userExpLevel-newcomer-label": "Newcomers",
+       "rcfilters-filter-userExpLevel-newcomer-description": "Very new editors: fewer than 10 edits and 4 days of activity.",
+       "rcfilters-filter-userExpLevel-learner-label": "Learners",
+       "rcfilters-filter-userExpLevel-learner-description": "More days of activity and edits than 'Newcomers' but fewer than 'Experienced users.'",
+       "rcfilters-filter-userExpLevel-experienced-label": "Experienced users",
+       "rcfilters-filter-userExpLevel-experienced-description": "More than 30 days of activity and 500 edits.",
        "rcnotefrom": "Below {{PLURAL:$5|is the change|are the changes}} since <strong>$3, $4</strong> (up to <strong>$1</strong> shown).",
        "rclistfrom": "Show new changes starting from $2, $3",
        "rcshowhideminor": "$1 minor edits",
        "sorbs": "DNSBL",
        "sorbsreason": "Your IP address is listed as an open proxy in the DNSBL used by {{SITENAME}}.",
        "sorbs_create_account_reason": "Your IP address is listed as an open proxy in the DNSBL used by {{SITENAME}}.\nYou cannot create an account.",
+       "softblockrangesreason": "Anonymous contributions are not allowed from your IP address ($1). Please log in.",
        "xffblockreason": "An IP address present in the X-Forwarded-For header, either yours or that of a proxy server you are using, has been blocked. The original block reason was: $1",
        "cant-see-hidden-user": "The user you are trying to block has already been blocked and hidden.\nSince you do not have the hideuser right, you cannot see or edit the user's block.",
        "ipbblocked": "You cannot block or unblock other users because you are yourself blocked.",
        "pagelang-language": "Language",
        "pagelang-use-default": "Use default language",
        "pagelang-select-lang": "Select language",
+       "pagelang-reason": "Reason",
        "pagelang-submit": "Submit",
+       "pagelang-nonexistent-page": "The page $1 does not exist.",
+       "pagelang-unchanged-language": "The page $1 is already set to language $2.",
+       "pagelang-unchanged-language-default": "The page $1 is already set to the wiki's default content language.",
+       "pagelang-db-failed": "The database failed to change the page language.",
        "right-pagelang": "Change page language",
        "action-pagelang": "change the page language",
        "log-name-pagelang": "Language change log",
index 2056f6d..fc87793 100644 (file)
@@ -49,7 +49,8 @@
                        "Psychoslave",
                        "Orikrin1998",
                        "Gamliel Fishkin",
-                       "Kastanoto"
+                       "Kastanoto",
+                       "Rafaneta"
                ]
        },
        "tog-underline": "Substrekado de ligiloj:",
        "right-userrights": "Redakti ĉiujn uzanto-rajtojn",
        "right-userrights-interwiki": "Redakti la rajtojn de uzantoj en aliaj vikioj",
        "right-siteadmin": "Ŝlosi kaj malŝlosi la datumbazon",
-       "right-override-export-depth": "Eksporti paĝojn inkluzivante ligitajn paĝojn ĝis profundeco de 5",
+       "right-override-export-depth": "Elporti paĝojn inkluzivante ligitajn paĝojn ĝis profundeco de 5",
        "right-sendemail": "Sendi retpoŝton al aliaj uzantoj",
        "right-managechangetags": "Kreado kaj (mal)aktivgo de [[Special:Tags|etikedoj]]",
        "right-applychangetags": "Aldoni [[Special:Tags|etikedojn]] al propraj ŝanĝoj",
        "recentchanges-legend-heading": "<strong>Klarigo:</strong>",
        "recentchanges-legend-newpage": "{{int:recentchanges-label-newpage}} (vidu ankaŭ [[Special:NewPages|liston de novaj paĝoj]])",
        "recentchanges-submit": "Montri",
+       "rcfilters-activefilters": "Aktivaj filtriloj",
+       "rcfilters-search-placeholder": "Filtri lastajn ŝanĝojn (vi povas elekti aŭ ekskribi)",
+       "rcfilters-invalid-filter": "Nevalida filtrilo",
+       "rcfilters-filterlist-title": "Filtriloj",
+       "rcfilters-filterlist-noresults": "Neniuj filtriloj troviĝis",
+       "rcfilters-filtergroup-authorship": "Redakta aŭtoreco",
+       "rcfilters-filter-editsbyself-label": "Viaj redaktoj",
+       "rcfilters-filter-editsbyself-description": "Viaj redaktoj.",
+       "rcfilters-filter-editsbyother-label": "Redaktoj de aliuloj",
+       "rcfilters-filter-editsbyother-description": "Redaktoj de la aliaj uzantoj (krom vi)",
+       "rcfilters-filtergroup-userExpLevel": "Uzanta spertonivelo",
+       "rcfilters-filter-userExpLevel-newcomer-label": "Novuloj",
+       "rcfilters-filter-userExpLevel-newcomer-description": "Tre novaj redaktantoj: malpli ol 10 redaktoj kaj 4 tagoj da aktiveco",
+       "rcfilters-filter-userExpLevel-learner-label": "Lernantoj",
+       "rcfilters-filter-userExpLevel-learner-description": "Pliaj tagoj da aktiveco kaj redaktoj ol 'Novuloj' sed malpli ol 'Spertaj uzantoj.'",
+       "rcfilters-filter-userExpLevel-experienced-label": "Spertaj uzantoj",
+       "rcfilters-filter-userExpLevel-experienced-description": "Pli ol 30 tagoj da aktiveco kaj 500 redaktoj.",
        "rcnotefrom": "Malsupre estas la {{PLURAL:$5|ŝanĝo|ŝanĝoj}} ekde <strong>$3, $4</strong> (montrante ĝis <strong>$1</strong>).",
        "rclistfrom": "Montri novajn ŝanĝojn ekde \"$3 $2\"",
        "rcshowhideminor": "$1 etajn redaktojn",
        "apisandbox-sending-request": "Sendanta aplikprograminterfacan peton…",
        "apisandbox-loading-results": "Ricevas APIajn rezultojn…",
        "apisandbox-results-error": "Eraro okazis dum ŝutis la APIan petan respondon: $1.",
+       "apisandbox-request-params-json": "JSON-parametroj:",
        "apisandbox-request-url-label": "Mendi URL-on.",
        "apisandbox-request-time": "Tempo de peto:{{PLURAL:$1|$1 ms}}",
        "apisandbox-results-fixtoken": "Korekti ĵetonon kaj resendi",
        "changecontentmodel-emptymodels-title": "Neniu disponebla enhavomodelo",
        "changecontentmodel-emptymodels-text": "La enhavo en [[:$1]] ne transtipeblas al iu ajn tipo.",
        "log-name-contentmodel": "Ŝanĝprotokolo de enhavomodelo",
-       "log-description-contentmodel": "Eventoj rilataj kun la enhavomodeloj de paĝo",
+       "log-description-contentmodel": "Ĉi tiu paĝo montras ŝanĝojn de la enhavomodelo de paĝoj, kaj paĝojn kreitajn kun enhavomodelo aparta de la norma.",
        "logentry-contentmodel-new": "$1 {{GENDER:$2|kreis}} la paĝo $3 per uzado de ne-defaŭlta enhavomodelo \"$5\"",
        "logentry-contentmodel-change": "$1 {{GENDER:$2|ŝanĝis}} la enhavomodelon de la paĝo $3 el \"$4\" al \"$5\"",
        "logentry-contentmodel-change-revertlink": "restarigi",
        "proxyblockreason": "Via IP-adreso estis forbarita ĉar ĝi estas malferma prokurilo. Bonvolu kontakti vian provizanto de retservo aŭ komputika helpisto kaj informu ilin de ĉi serioza problemo pri sekureco.",
        "sorbsreason": "Via IP-adreso estas listigita kiel malferma prokurilo en la DNSBL uzata de {{SITENAME}}.",
        "sorbs_create_account_reason": "Via IP-adreso estas listigita kiel malferma prokurilo en la DNSBL uzata de {{SITENAME}}. Vi ne rajtas krei konton.",
+       "softblockrangesreason": "Anonimaj kontribuoj ne estas permesataj de via IP-adreso ($1). Bonvolu ensaluti.",
        "xffblockreason": "La IP-adreso en la kapo de X-Forwarded-For, ĉu via aŭ de la prokurilo kiun vi uzas, estis forbarita. La origina forbarokialo estis: $1",
        "cant-see-hidden-user": "La uzanto kiun vi provas forbari jam estis forbarita kaj kaŝita. Kiel vi ne havas la rajton kaŝi uzanton, vi ne povas vidi aŭ redakti la forbaron de la uzanto.",
        "ipbblocked": "Vi ne povas forbari aŭ malforbari aliajn uzantojn, ĉar vi mem estas forbarita",
        "cant-move-to-user-page": "Vi ne rajtas movi paĝon al uzantopaĝo (krom al uzantosubpaĝo).",
        "cant-move-category-page": "Vi ne rajtas movi kategoriajn paĝojn.",
        "cant-move-to-category-page": "Vi ne rajtas movi paĝon al kategoria paĝo.",
+       "cant-move-subpages": "Vi ne rajtas movi subpaĝojn.",
+       "namespace-nosubpages": "Nomspaco \"$1\" ne permesas subpaĝojn.",
        "newtitle": "Nova titolo:",
        "move-watch": "Atenti ĉi tiun paĝon",
        "movepagebtn": "Alinomi paĝon",
        "semiprotectedpagemovewarning": "'''Averto:''' Ĉi tiu paĝo estis ŝlosita tiel ĝi estas nur movebla de registritaj uzantoj.\nJen la lasta protokolero por via referenco:",
        "move-over-sharedrepo": "[[:$1]] ekzistas en komuna dosierujo. Movado de dosiero al ĉi tiu titolo anstataŭigos la komunan dosieron.",
        "file-exists-sharedrepo": "La elektita dosiernomo jam estas uzita en komun dosierujo.\nBonvolu elekti alian nomon.",
-       "export": "Eksporti paĝojn",
-       "exporttext": "Vi povas eksporti la tekston kaj la redaktohistorion de aparta paĝo aŭ de paĝaro kolektita en ia XML.\nĈi tio povas esti importita en alian programon funkciantan per MediaWiki-softvaro per la [[Special:Import|import-paĝo]].\n\nPor eksporti paĝojn, enigu la titolojn en la jena tekst-skatolo, po unu por linio, kaj elektu ĉu vi volas kaj la nunan version kaj ĉiujn antaŭajn versiojn, kun la paĝaj historiaj linioj, aŭ la nunan version kun la informo pri la lasta redakto.\n\nEn la lasta okazo, vi ankaŭ povas uzi ligilon, ekz-e [[{{#Special:Export}}/{{MediaWiki:Mainpage}}]] por la paĝo \"[[{{MediaWiki:Mainpage}}]]\".",
-       "exportall": "Eksporti ĉiujn paĝojn",
+       "export": "Elporti paĝojn",
+       "exporttext": "Vi povas elporti la tekston kaj la redaktohistorion de aparta paĝo aŭ de paĝaro kolektita en ia XML.\nĈi tio povas esti enportita en alian programon funkciantan per MediaWiki per la [[Special:Import|enportpaĝo]].\n\nPor elporti paĝojn, enigu la titolojn en la jena tekst-skatolo, po unu por linio, kaj elektu ĉu vi volas kaj la nunan version kaj ĉiujn antaŭajn versiojn, kun la paĝaj historiaj linioj, aŭ la nunan version kun la informo pri la lasta redakto.\n\nEn la lasta okazo, vi ankaŭ povas uzi ligilon, ekz-e [[{{#Special:Export}}/{{MediaWiki:Mainpage}}]] por la paĝo \"[[{{MediaWiki:Mainpage}}]]\".",
+       "exportall": "Elporti ĉiujn paĝojn",
        "exportcuronly": "Entenas nur la aktualan version, ne la malnovajn.",
        "exportnohistory": "----\n'''Notu:''' Eksportado de la plena historio de paĝoj per ĉi paĝo estis malebligita pro funkciigaj kialoj.",
        "exportlistauthors": "Inkluzivi plenan liston de kontribuantoj por ĉiu paĝo.",
        "thumbnail_gd-library": "Nekompleta GD-biblioteka konfiguro: mankas funkcio $1",
        "thumbnail_image-missing": "Dosiero verŝajne estas foriga: $1",
        "thumbnail_image-failure-limit": "Lastatempe estis tro multaj malsukcesaj provoj ($1 aŭ pli) por bildigi tiun ĉi miniaturon. Bonvolu reprovi poste.",
-       "import": "Importi paĝojn",
+       "import": "Enporti paĝojn",
        "importinterwiki": "Transvikia importo",
        "import-interwiki-text": "Elektu vikion kaj paĝan titolon por importi.\nDatoj de versioj kaj nomoj de redaktantoj estos konservitaj.\nĈiuj transvikaj importoj estas raportitaj ĉe la [[Special:Log/import|loglibro de importoj]].",
        "import-interwiki-sourcewiki": "Fonta vikio:",
        "import-mapping-subpage": "Importi kiel subpaĝojn de la jena paĝo:",
        "import-upload-filename": "Dosiernomo:",
        "import-comment": "Komento:",
-       "importtext": "Bonvolu eksporti la dosieron el la fonta vikio per la [[Special:Export|eksportilo]]. Konservu ĝin sur via persona komputilo kaj poste alŝutu ĝin tien ĉi.",
+       "importtext": "Bonvolu elporti la dosieron el la fonta vikio per la [[Special:Export|eksportilo]]. Konservu ĝin sur via persona komputilo kaj poste alŝutu ĝin ĉi tien.",
        "importstart": "Importante paĝojn...",
        "import-revision-count": "$1 {{PLURAL:$1|versio|versioj}}",
        "importnopages": "Neniu paĝo por importi.",
        "api-error-stashnotloggedin": "Vi devas esti ensalutinta por konservi dosieron en alŝutan rezervujon.",
        "api-error-stashwrongowner": "La rezervuja dosiero, kiun vi provis aliri, ne apartenas al vi.",
        "api-error-stashnosuchfilekey": "La dosiera ŝlosilo, kiun vi provis aliri en rezervujo, ne ekzistas.",
-       "api-error-timeout": "La servilo ne respondis ene de la antaŭvidita tempo.",
+       "api-error-timeout": "La servilo ne respondis ene de la atendita tempo.",
        "api-error-unclassified": "Okazis nekonata eraro",
        "api-error-unknown-code": "Nekonata eraro: \"$1\"",
        "api-error-unknown-error": "Interna eraro: io misokazis en la alŝuto de via dosiero.",
-       "api-error-unknown-warning": "Nekonata averto: $1",
+       "api-error-unknown-warning": "Nekonata averto: \"$1\".",
        "api-error-unknownerror": "Nekonata eraro: \"$1\"",
        "api-error-uploaddisabled": "Alŝutato estas malebligata en tiu ĉi vikio.",
        "api-error-verification-error": "Tiu ĉi dosiero eble estas difektita, aŭ havas la malĝustan dosieran finaĵon.",
        "pagelang-language": "Lingvo",
        "pagelang-use-default": "Uzi defaŭltan lingvon",
        "pagelang-select-lang": "Elekti la lingvon",
+       "pagelang-reason": "Kialo",
        "pagelang-submit": "Ek!",
+       "pagelang-nonexistent-page": "La paĝo $1 ne ekzistas.",
+       "pagelang-unchanged-language": "La paĝo $1 jam estas agordita al la lingvo $2.",
+       "pagelang-unchanged-language-default": "La paĝo $1 jam estas agordita al la norma enhav-lingvo de la vikio.",
+       "pagelang-db-failed": "La datumbazo ne povis ŝanĝi la lingvon de la paĝo.",
        "right-pagelang": "Ŝanĝi paĝan lingvon",
        "action-pagelang": "ŝanĝi la lingvon de la paĝo",
        "log-name-pagelang": "Protokolo pri lingvajn ŝanĝojn",
        "log-action-filter-block-block": "Forbari",
        "log-action-filter-block-reblock": "Forbari ŝanĝon",
        "log-action-filter-block-unblock": "Malforbari",
-       "log-action-filter-contentmodel-change": "Ŝanĝo de enhavomodelon",
+       "log-action-filter-contentmodel-change": "Ŝanĝo de enhavomodelo",
        "log-action-filter-contentmodel-new": "Kreo de paĝo kun ne-norma enhavomodelo",
        "log-action-filter-delete-delete": "Forviŝigado de paĝo",
        "log-action-filter-delete-delete_redir": "Alidirekta anstataŭigo",
index 9a37b03..192b123 100644 (file)
        "recentchanges-legend-heading": "<strong>Leyenda:</strong>",
        "recentchanges-legend-newpage": "{{int:recentchanges-label-newpage}} (véase también la [[Special:NewPages|lista de páginas nuevas]])",
        "recentchanges-submit": "Mostrar",
+       "rcfilters-activefilters": "Filtros activos",
+       "rcfilters-search-placeholder": "Filtrar cambios recientes (navega o empieza a escribir)",
+       "rcfilters-invalid-filter": "Filtro no válido",
+       "rcfilters-filterlist-title": "Filtros",
+       "rcfilters-filterlist-noresults": "No se encontraron filtros",
+       "rcfilters-filtergroup-authorship": "Editar autoría",
+       "rcfilters-filter-editsbyself-label": "Tus propias ediciones",
+       "rcfilters-filter-editsbyself-description": "Ediciones tuyas",
+       "rcfilters-filter-editsbyother-label": "Ediciones de otros",
+       "rcfilters-filter-editsbyother-description": "Ediciones creadas por otros usuarios (no por ti).",
+       "rcfilters-filtergroup-userExpLevel": "Nivel de experiencia del usuario",
+       "rcfilters-filter-userExpLevel-newcomer-label": "Recién llegados",
+       "rcfilters-filter-userExpLevel-newcomer-description": "Editores recién llegados: menos de 10 ediciones y 4 días de actividad.",
+       "rcfilters-filter-userExpLevel-learner-label": "Aprendices",
+       "rcfilters-filter-userExpLevel-learner-description": "Más días de actividad y ediciones que los «recién llegados», pero menos que los «usuarios experimentados».",
+       "rcfilters-filter-userExpLevel-experienced-label": "Usuarios experimentados",
+       "rcfilters-filter-userExpLevel-experienced-description": "Más de 30 días de actividad y 500 ediciones.",
        "rcnotefrom": "Debajo aparece{{PLURAL:$5| el cambio|n los cambios}} desde <strong>$3, $4</strong> (se muestran hasta <strong>$1</strong>).",
        "rclistfrom": "Mostrar cambios nuevos desde las $2 del $3",
        "rcshowhideminor": "$1 ediciones menores",
        "apisandbox-sending-request": "Enviando pedido a la API...",
        "apisandbox-loading-results": "Recibiendo resultados de la API...",
        "apisandbox-results-error": "Ocurrió un error durante la carga de la respuesta a la consulta API: $1",
+       "apisandbox-request-params-json": "Parámetros JSON:",
        "apisandbox-request-url-label": "URL solicitante:",
        "apisandbox-request-time": "Tiempo de solicitud: {{PLURAL:$1|$1 ms}}",
        "apisandbox-results-fixtoken": "Corrige el token y vuelve a enviar",
        "proxyblockreason": "Tu dirección IP ha sido bloqueada porque es un proxy abierto.\nContacta con tu proveedor de servicios de Internet o con tu servicio de asistencia técnica e infórmales de este grave problema de seguridad.",
        "sorbsreason": "Su dirección IP está listada como proxy abierto en DNSBL.",
        "sorbs_create_account_reason": "Su dirección IP está listada como proxy abierto en DNSBL. No puede crear una cuenta",
+       "softblockrangesreason": "Las contribuciones anónimas desde tu dirección IP ($1) no están permitidas. Por favor, inicia sesión.",
        "xffblockreason": "Una dirección IP presente en la cabecera X-Forwarded-For, tuya o del servidor proxy que estás usando, ha sido bloqueada. El motivo original del bloqueo fue: $1",
        "cant-see-hidden-user": "El usuario que estas intentando bloquear ya ha sido bloqueado y ocultado.\nDado que no tienes permisos suficientes no puedes ver ni editar el bloqueo de este usuario.",
        "ipbblocked": "No puedes bloquear o desbloquear a otros usuarios porque estás bloqueado",
        "pagelang-language": "Idioma",
        "pagelang-use-default": "Utilizar el idioma predeterminado",
        "pagelang-select-lang": "Seleccionar idioma",
+       "pagelang-reason": "Motivo",
        "pagelang-submit": "Enviar",
+       "pagelang-nonexistent-page": "La página $1 no existe.",
+       "pagelang-unchanged-language": "La página $1 ya está configurada en $2.",
+       "pagelang-unchanged-language-default": "La página $1 ya está configurada en el idioma predeterminado del wiki.",
+       "pagelang-db-failed": "La base de datos no ha podido cambiar el idioma de la página.",
        "right-pagelang": "Cambiar el idioma de la página",
        "action-pagelang": "cambiar el idioma de la página",
        "log-name-pagelang": "Registro de cambios de idiomas",
index fdd94bc..e2168bd 100644 (file)
        "pagelang-language": "Kieli",
        "pagelang-use-default": "Käytä oletuskieltä",
        "pagelang-select-lang": "Valitse kieli",
+       "pagelang-reason": "Syy",
        "pagelang-submit": "Lähetä",
        "right-pagelang": "Vaihtaa sivun kieli",
        "action-pagelang": "muuttaa sivun kieliasetuksia",
index 99f1c8f..5cf78ce 100644 (file)
        "search-relatedarticle": "Reliés",
        "searchrelated": "reliés",
        "searchall": "tout",
-       "showingresults": "Affichage de <b>$1</b> résultat{{PLURAL:$1||s}} à partir du n°<b>$2</b>.",
+       "showingresults": "Affichage de <strong>$1</strong> résultat{{PLURAL:$1||s}} à partir du n°<strong>$2</strong>.",
        "showingresultsinrange": "Afficher ci-dessous jusqu’à {{PLURAL:$1|<strong>1</strong> résultat|<strong>$1</strong> résultats}} dans la série #<strong>$2</strong> à #<strong>$3</strong>.",
        "search-showingresults": "{{PLURAL:$4|Résultat <strong>$1</strong> parmi <strong>$3</strong>|Résultats <strong>$1 à $2</strong> parmi <strong>$3</strong>}}",
        "search-nonefound": "Il n'y a aucun résultat correspondant à la requête.",
        "recentchanges-legend-newpage": "{{int:recentchanges-label-newpage}} (voir aussi la [[Special:NewPages|liste des nouvelles pages]]).",
        "recentchanges-legend-plusminus": "(''±123'')",
        "recentchanges-submit": "Lister",
+       "rcfilters-activefilters": "Filtres actifs",
+       "rcfilters-search-placeholder": "Modifications récentes de filtres (naviguer ou commencer à saisir)",
+       "rcfilters-invalid-filter": "Filtre non valide",
+       "rcfilters-filterlist-title": "Filtres",
+       "rcfilters-filterlist-noresults": "Aucun filtre trouvé",
+       "rcfilters-filtergroup-authorship": "Modifier la paternité",
+       "rcfilters-filter-editsbyself-label": "Vos propres modifications",
+       "rcfilters-filter-editsbyself-description": "Vos modifications.",
+       "rcfilters-filter-editsbyother-label": "Modifications par d’autres.",
+       "rcfilters-filter-editsbyother-description": "Modifications créées par d’autres utilisateurs (pas vous).",
+       "rcfilters-filtergroup-userExpLevel": "Niveau d’expérience utilisateur",
+       "rcfilters-filter-userExpLevel-newcomer-label": "Nouveaux arrivants",
+       "rcfilters-filter-userExpLevel-newcomer-description": "Tout nouveaux éditeurs : moins de 10 modifications et 4 jours d’activité.",
+       "rcfilters-filter-userExpLevel-learner-label": "Apprentis",
+       "rcfilters-filter-userExpLevel-learner-description": "Davantage de jours d’activité et de modifications que les 'Nouveaux arrivants' mais moins que les 'Utilisateurs expérimentés'.",
+       "rcfilters-filter-userExpLevel-experienced-label": "Utilisateurs expérimentés",
+       "rcfilters-filter-userExpLevel-experienced-description": "Plus de 30 jours d’activité et 500 modifications",
        "rcnotefrom": "Ci-dessous {{PLURAL:$5|la modification effectuée|les modifications effectuées}} depuis le <strong>$3, $4</strong> (affichées jusqu’à <strong>$1</strong>).",
        "rclistfrom": "Afficher les nouvelles modifications depuis le $3 à $2",
        "rcshowhideminor": "$1 les modifications mineures",
        "proxyblockreason": "Votre adresse IP a été bloquée car il s'agit d'un mandataire ouvert.\nVeuillez contacter votre fournisseur d'accès Internet ou votre support technique et l'informer de ce sérieux problème de sécurité.",
        "sorbsreason": "Votre adresse IP est listée comme mandataire ouvert dans le DNSBL utilisé par {{SITENAME}}.",
        "sorbs_create_account_reason": "Votre adresse IP est listée comme mandataire ouvert dans le DNSBL utilisé par {{SITENAME}}.\nVous ne pouvez pas créer un compte.",
+       "softblockrangesreason": "Les contributions anonymes ne sont pas autorisées à partir de votre adresse IP ($1). Veuillez vous connecter.",
        "xffblockreason": "Une adresse IP dans l'en-tête X-Forwarded-For, soit la vôtre ou celle d'un serveur proxy que vous utilisez, a été bloquée. La raison du blocage initial est : $1",
        "cant-see-hidden-user": "L’utilisateur que vous tentez de bloquer a déjà été bloqué et masqué. \nN’ayant pas le droit de masquer des utilisateurs, vous ne pouvez pas voir ou modifier le blocage de cet utilisateur.",
        "ipbblocked": "Vous ne pouvez pas bloquer ou débloquer d'autres utilisateurs, parce que vous êtes vous-même bloqué{{GENDER:||e}}.",
        "pagelang-language": "Langue",
        "pagelang-use-default": "Utiliser la langue par défaut",
        "pagelang-select-lang": "Sélectionner la langue",
+       "pagelang-reason": "Motif",
        "pagelang-submit": "Envoyer",
+       "pagelang-nonexistent-page": "La page $1 n’existe pas.",
+       "pagelang-unchanged-language": "La page $1 est déjà positionnée sur la langue $2.",
+       "pagelang-unchanged-language-default": "La page $1 est déjà positionnée dans la langue par défaut du contenu du wiki.",
+       "pagelang-db-failed": "La base de données n’a pas réussi à modifier la langue de la page.",
        "right-pagelang": "Changer la langue de la page",
        "action-pagelang": "changer la langue de la page",
        "log-name-pagelang": "Tracer les changements de langue",
index f5da074..b32208a 100644 (file)
        "recentchanges-legend-newpage": "{{int:recentchanges-label-newpage}} (véxase tamén a [[Special:NewPages|lista de páxinas novas]])",
        "recentchanges-legend-plusminus": "(''±123'')",
        "recentchanges-submit": "Mostrar",
+       "rcfilters-activefilters": "Filtros activos",
+       "rcfilters-invalid-filter": "Filtro no válido",
+       "rcfilters-filterlist-title": "Filtros",
+       "rcfilters-filterlist-noresults": "Non se atoparon filtros",
+       "rcfilters-filtergroup-authorship": "Editar autoría",
+       "rcfilters-filter-editsbyself-label": "As súas propias edicións",
+       "rcfilters-filter-editsbyself-description": "Edicións súas.",
+       "rcfilters-filter-editsbyother-label": "Edicións doutros.",
        "rcnotefrom": "A continuación {{PLURAL:$5|móstrase o cambio feito|móstranse os cambios feitos}} desde o <strong>$3</strong> ás <strong>$4</strong> (móstranse <strong>$1</strong> como máximo).",
        "rclistfrom": "Mostrar os cambios novos desde o $3 ás $2",
        "rcshowhideminor": "$1 as edicións pequenas",
index f60d6be..195d06f 100644 (file)
        "recentchanges-legend-newpage": "{{int:recentchanges-label-newpage}} ({{GENDER:|ראה|ראי|ראו}} גם את [[Special:NewPages|רשימת הדפים החדשים]])",
        "recentchanges-legend-plusminus": "(<em>±123</em>)",
        "recentchanges-submit": "הצגה",
+       "rcfilters-activefilters": "מסננים פעילים",
+       "rcfilters-search-placeholder": "סינון שינויים אחרונים (עיינו או התחילו להקליד)",
+       "rcfilters-invalid-filter": "מסנן בלתי־תקין",
+       "rcfilters-filterlist-title": "מסננים",
+       "rcfilters-filterlist-noresults": "לא נמצאו מסננים",
+       "rcfilters-filtergroup-authorship": "מבצעי העריכה",
+       "rcfilters-filter-editsbyself-label": "עריכות שלך",
+       "rcfilters-filter-editsbyself-description": "עריכות שביצעת בעצמך.",
+       "rcfilters-filter-editsbyother-label": "עריכות של אחרים",
+       "rcfilters-filter-editsbyother-description": "עריכות שבוצעו על־ידי משתמשים אחרים (מלבדך).",
+       "rcfilters-filtergroup-userExpLevel": "הניסיון והוותק של העורכים",
+       "rcfilters-filter-userExpLevel-newcomer-label": "חדשים",
+       "rcfilters-filter-userExpLevel-newcomer-description": "עורכים חדשים מאוד: פחות מ־10 עריכות ו־4 ימים של פעילות.",
+       "rcfilters-filter-userExpLevel-learner-label": "לומדים",
+       "rcfilters-filter-userExpLevel-learner-description": "יותר ימי פעילות ועריכות מ\"חדשים\", אבל פחות מ\"משתמשים מנוסים\".",
+       "rcfilters-filter-userExpLevel-experienced-label": "משתמשים מנוסים",
+       "rcfilters-filter-userExpLevel-experienced-description": "יותר מ־30 ימים של פעילות ו־500 עריכות.",
        "rcnotefrom": "להלן {{PLURAL:$5|השינוי שבוצע|השינויים שבוצעו}} מאז <strong>$3, $4</strong> (מוצגים עד <strong>$1</strong>).",
        "rclistfrom": "הצגת שינויים חדשים החל מ־$2, $3",
        "rcshowhideminor": "$1 עריכות משניות",
        "apisandbox-sending-request": "בקשת ה־API בשליחה...",
        "apisandbox-loading-results": "תוצאות ה־API בתהליך קבלה...",
        "apisandbox-results-error": "אירעה שגיאה בעת טעינת תשובת ה־API לבקשה: $1.",
+       "apisandbox-request-params-json": "הפרמטרים בפורמט JSON:",
        "apisandbox-request-url-label": "כתובת ה־URL של הבקשה:",
        "apisandbox-request-time": "זמן הבקשה: {{PLURAL:$1|מילישנייה אחת|$1 מילישניות}}",
        "apisandbox-results-fixtoken": "אנא תקנו את האסימון ושלחו שוב",
        "proxyblockreason": "כתובת ה־IP שלכם נחסמה משום שהיא כתובת של שרת פרוקסי פתוח.\nאנא צרו קשר עם ספק האינטרנט שלכם או עם התמיכה הטכנית של הארגון שלכם והודיעו להם על בעיית האבטחה החמורה הזאת.",
        "sorbsreason": "כתובת ה־IP שלך רשומה ככתובת פרוקסי פתוחה ב־DNSBL שאתר {{SITENAME}} משתמש בו.",
        "sorbs_create_account_reason": "כתובת ה־IP שלך רשומה ככתובת פרוקסי פתוחה ב־DNSBL שאתר {{SITENAME}} משתמש בו.\nאין באפשרותך ליצור חשבון.",
+       "softblockrangesreason": "תרומות אנונימיות אינן מותרות מכתובת ה־IP שלך ($1). נא להיכנס לחשבון.",
        "xffblockreason": "כתובת IP הנמצאת בכותרת X-Forwarded-For, בין אם שלכם או של שרת פרוקסי שאתם משתמשים בו, נחסמה. סיבת החסימה המקורית הייתה: $1",
        "cant-see-hidden-user": "המשתמש שאתם מנסים לחסום כבר נחסם והוסתר.\nכיוון שאין לכם הרשאה להסתרת משתמשים, אין באפשרותכם לצפות בחסימת המשתמש או לערוך אותה.",
        "ipbblocked": "אינכם יכולים לחסום או לשחרר את חסימתם של משתמשים אחרים, כיוון שאתם עצמכם חסומים.",
        "pagelang-language": "שפה",
        "pagelang-use-default": "להשתמש בשפה הרגילה",
        "pagelang-select-lang": "בחירת שפה",
+       "pagelang-reason": "סיבה",
        "pagelang-submit": "שליחה",
+       "pagelang-nonexistent-page": "הדף $1 אינו קיים.",
+       "pagelang-unchanged-language": "הדף $1 כבר מוגדר לשפה $2.",
+       "pagelang-unchanged-language-default": "הדף $1 כבר מוגדר לשפת התוכן ההתחלתית של אתר הוויקי.",
+       "pagelang-db-failed": "בסיס הנתונים לא הצליח לשנות את שפת הדף.",
        "right-pagelang": "שינוי שפות של דפים",
        "action-pagelang": "לשנות את שפת הדף",
        "log-name-pagelang": "יומן שינוי שפה",
index fb78acc..5f2c21b 100644 (file)
        "botpasswords-label-delete": "Mitao",
        "botpasswords-label-resetpassword": "Password ke badlo",
        "botpasswords-label-grants": "Applicable grants:",
+       "botpasswords-help-grants": "Agar aap ke lage abhi koi rights hai, tab grants aap ke iske access de hai.\nHian pe grant ke enable kare se aap ke uu right nai mile hai jon ki aap ke waise nai milat rahaa.\nAur jaaan kari ke khatir [[Special:ListGrants|table of grants]] ke dekho.",
        "botpasswords-label-grants-column": "Ijaajat hai",
        "botpasswords-bad-appid": "Bot ke naam \"$1\" valid nai hai",
        "botpasswords-insert-failed": "Bot ke naam \"$1\"nai jorre sakaa. Ka iske pahile jorraa gais rahaa?",
        "botpasswords-updated-body": "User \"$2\" ke khaatir, jiske bot naam \"$1\" hai, ke password ke badal dewa gais hai.",
        "botpasswords-deleted-title": "Bot ke password ke mitae dewa gais hai",
        "botpasswords-deleted-body": "User \"$2\" ke khaatir, bot jiske naam \"$1\" hai, ke password ke mitaae dewa gais hai.",
+       "botpasswords-newpassword": "Log in kare ke khatir nawaa password <strong>$1</strong> <strong>$2</strong> hai. <em>Iske aage kaam me laae ke khaatir likh lo.</em> <br> (For old bots which require the login name to be the same as the eventual username, you can also use <strong>$3</strong> as username and <strong>$4</strong> as password.)",
        "botpasswords-no-provider": "BotPasswordsSessionProvider abhi available nai hai.",
        "botpasswords-restriction-failed": "Bot password restrictions ii login ke roke hai.",
        "botpasswords-invalid-name": "Jon username ke dewa gais hai, me bot password separator (\"$1\") nai hai.",
        "passwordreset-emailsentusername": "Agar ii email aap ke username se associated hai tab ek password reset email ke bheja jaai.",
        "passwordreset-nocaller": "A caller must be provided",
        "passwordreset-nosuchcaller": "Caller exist nai hoe hai: $1",
+       "passwordreset-ignored": "Password reset ke hadle nai karaa gais hai. Saait koi provider ke nai configure karaa gais hoi?",
        "passwordreset-invalidemail": "Email address invalid hai",
        "passwordreset-nodata": "Na username, na email address ke dewa gais rahaa",
        "changeemail": "E-mail address ke badlo, nai to, hatao",
        "blockedtitle": "Sadasya ke rok dewa gais hai",
        "blockedtext": "'''Aapke user name nai to IP address ke rok dewa gae hai.'''\n\nRoke waala hai $1.\nIske kaaran hai ''$2''.\n\n* Roke ke suruu: $8\n* Roke kab khatam hoi: $6\n* Kiske rokaa jae hai: $7\n\nAap $1 ke mile saktaa hai nai to duusra [[{{MediaWiki:Grouppage-sysop}}|administrator]] se rukawat ke baare me baat karo.\nAap ii sadasya ke 'email this user' feature ke kaam me lae ke baat nai kare saktaa hai jab tak ki ek kanuni email address aapke [[Special:Preferences|account preferences]] me nai hai aur aap ke iske kaam me laae ke roka nai gae hai.\nAap ke abhi ke IP address $3 hai, aur roka gae ID hai #$5.\nMeharbani kar ke chahe ek nai to duno ke aapan sawaal me rakho.",
        "autoblockedtext": "Aap ke IP address ke apne se rok dewa gais hai kahe ki koi duusra sadasya iske kaam me kawat rahaa, jiske $1 rokis hai.\n\nIske khatir kaaran hai:\n:''$2''\n\n* Roke ke suruu: $8\n* Roke kab khatam hoi: $6\n*Roke waala: $7\n\nAap $1 ke mile saktaa hai nai to duusra [[{{MediaWiki:Grouppage-sysop}}|administrator]] se rukawat ke baare me baat karo.\n\nAap ii sadasya ke 'email this user' feature ke kaam me lae ke baat nai kare saktaa hai jab tak ki ek kanuni email address aapke [[Special:Preferences|account preferences]] me nai hai aur aap ke iske kaam me laae ke roka nai gae hai.\n\nAap ke abhi ke IP address $3 hai, aur roka gae ID hai #$5.\nMeharbani kar ke chahe ek nai to duno ke aapan sawaal me rakho.",
+       "systemblockedtext": "Aaap ke username nai to IP address ke Mediawiki automatically block kar diis hai.\n\nDewa gais kaaran hai :\n\n:<em>$2</em>\n\n* Start of block: $8\n* Expiration of block: $6\n* Intended blockee: $7\n\nYour current IP address is $3.\nPlease include all above details in any queries you make.",
        "blockednoreason": "koi kaaran nai dewa gais hai",
        "whitelistedittext": "Aap ke panna badle khatir $1 kare ke parri.",
        "confirmedittext": "Panna ke badle se pahile aap ke aapan e-mail ke confirm kare ke parri.\nMeharbani kar ke aap aapan e-mail ke aapan [[Special:Preferences|user preferences]] se validate karna.",
        "readonlywarning": "<strong>Chetauni: Database ke maintenance khatir band kar dewa gais hai, tab abhi aap aapan badlao ke save nai kare paega.</strong>\nAap saait aapan badlao ke ek text file me cut-n-paste kar ke baad me use kare khatir save kar le sakta hai.\nAdministrator jon ki iske lock karis hai ii kaaran diis hai: $1",
        "protectedpagewarning": "'''CHETAUNI: Ii panna ke band kar dewa gais hai jisse ke khaali uu sadasya jiske sysop adhikaar hai iske badle sake hai.'''\nNiche sab se nawaa suchi aap ke dekhe ke khatir dewa gais hae:",
        "semiprotectedpagewarning": "'''Suchna:''' Ii panna ke band kar dewa gais hai jisse ki khali registered sadasya iske badle sake hai.\nNiche sab se nawaa suchi ke aap ke dekhe ke khatir dewa gais hae:",
-       "cascadeprotectedwarning": "<strong>Chetawani:</strong> Ii panna ke band kar dewa gais jiske kaaran khali uu sadasya jiske lage sysop privileges hai iske badle sake hai, kahe ki iske niche likha gais cascade-protected {{PLURAL:$1|panna|panna}} me rakkha gais hai:",
+       "cascadeprotectedwarning": "<strong>Chetawani:</strong> Ii panna ke band kar dewa gais jiske kaaran khaali uu sadasya jiske lage sysop privileges hai iske badle sake hai, kahe ki iske niche likha gais cascade-protected {{PLURAL:$1|panna}} me rakkha gais hai:",
        "titleprotectedwarning": "'''CHETAUNI: Ii panna ke band dewa gais hai jisse ki [[Special:ListGroupRights|specific rights]] ke jarie iske badla jaae sake hai.'''\nAap ke jaankari ke khatir sab se nawaa suchi niche dewa gais hae:",
        "templatesused": "{{PLURAL:$1|Template|Templates}} ke ii panna me kaam me lawa gais hae:",
        "templatesusedpreview": "{{PLURAL:$1|Template|Templates}} ii jhalak me kaam me lawa gais hae:",
        "contentmodelediterror": "Aap iske badle nai saktaa hae kaaheki iske content model <code>$1</code> hae, aur ii  abhi ke content model <code>$2</code> ke rakam nai hae.",
        "recreate-moveddeleted-warn": "'''Chetawani: Jon panna ke pahile hatae dewa gais rahaa ke aap fir se banata hai.'''\n\nAap socho ki ii panna ke sampadan aap ke karte rahe ke chaahi ki nai.\nAap ke aaram khatir hatae waala suchi hian pe dewa jaawe hai:",
        "moveddeleted-notice": "Ii panna ke mitae dewa gais hai.\nIi panna ke mitae waala aur hatae waala log aap ke dekhe khatir niche dewa gais hai.",
+       "moveddeleted-notice-recent": "Maaf karna, ii panna ke abhi haali mitae dewa gais rahaa ( pichhle 24 ghantaa me).\nMitae aur hatae ke log panna ke niche, aap ke reference ke khaatir, dewea gais hai.",
        "log-fulllog": "Puura log dekho",
        "edit-hook-aborted": "Badalo ke hook rok diis hai.\nIi koi kaaran nai diis hai.",
        "edit-gone-missing": "Panna ke badle nai sakaa.\nJanae hai ki iske koi mitae dii hai.",
        "content-not-allowed-here": "Panna [[$2]] me \"$1\" likhe ke ijaajat nai hae",
        "editwarning-warning": "Ii panna ke chhore se jetna changes aap  karaa hae nai save hoi.\nAgar aap logged in hae, tab aap ii chetauni ke \"{{int:prefs-editing}}\"  vibhag me disable kare saktaa hae.",
        "editpage-invalidcontentmodel-title": "Content model not supported",
+       "editpage-invalidcontentmodel-text": "Content model \"$1\" ke support nai karaa jaawe hai.",
        "editpage-notsupportedcontentformat-title": "Content ke format ke support nai karaa jaawe hae.",
        "editpage-notsupportedcontentformat-text": "Content format $1 ke content model $2 nai support kare hae.",
        "content-model-wikitext": "wikitext",
        "content-model-css": "CSS",
        "content-json-empty-object": "Khaali object",
        "content-json-empty-array": "Khaali array",
+       "deprecated-self-close-category": "Panna, jon ki invalid self-closed HTML tags, ke use kare hai",
+       "deprecated-self-close-category-desc": "Panna me, invalid self-closed HTML tags hai, jaise ki <code>&lt;b/></code> nai to <code>&lt;span/></code>.  The behavior of these will change soon to be consistent with the HTML5 specification, so their use in wikitext is deprecated.",
+       "duplicate-args-warning": "<strong>Chetauni:</strong> [[:$1]] is calling [[:$2]] with more than one value for the \"$3\" parameter. Only the last value provided will be used.",
        "duplicate-args-category": "Panna jiske tamplate call me duplicate argument hae",
        "duplicate-args-category-desc": "Panna me template calls hae jisme duplicate arguments hae, jaise ki <code><nowiki>{{foo|bar=1|bar=2}}</nowiki></code> or <code><nowiki>{{foo|bar|1=baz}}</nowiki></code>.",
        "expensive-parserfunction-warning": "'''Chetauni''': Ii panna me bahut jaada expensive parser function calls hai.\n\nIske $2 {{PLURAL:$2|call|calls}} se kamti hoe ke chaahi, {{PLURAL:$1|abhi hai $1 call|abhi hai $1 calls}}.",
        "history-feed-description": "Ii panaa ke wiki me badlao ke itihaas",
        "history-feed-item-nocomment": "$1 pe $2",
        "history-feed-empty": "Aap jon panna mangta hai uu abhi tak banaa nai hai.\nSaait iske wiki me se mitae dewa gae hoi, nai to iske naam badal dewa gae hoi.\nTry karo [[Special:Search|wiki me khije ke]] aur nawaa panna ke.",
+       "history-edit-tags": "Edit tags of selected revisions",
        "rev-deleted-comment": "(badlao ke summary ke hatae dewa gais hae)",
        "rev-deleted-user": "(username ke hatae dewa gais hai)",
        "rev-deleted-event": "(log action ke hatae dewa gais hai)",
        "rev-showdeleted": "dekhao",
        "revisiondelete": "Badlao ke mitao/nai mitao",
        "revdelete-nooldid-title": "Target revision jon ki valid nai hai",
-       "revdelete-nooldid-text": "Aap chaahe target revision(s) ke specify nai karaa hai, ii function ke perform kare ke khatir, specified revision haiye nai, nai to aap abhi ke badlao ke lukae ke kosis karta hai.",
+       "revdelete-nooldid-text": "Aap chaahe target revision ke specify nai karaa hai, ii function ke perform kare ke khatir, specified revision haiye nai, nai to aap abhi ke badlao ke lukae ke kosis karta hai.",
        "revdelete-no-file": "Chuna gais file abhi nai banawa gais hai.",
        "revdelete-show-file-confirm": "Ka aap sure hai ki aap file ke mitawa gais revision ke dekhe mangtaa hai \"<nowiki>$1</nowiki>\" $2 se $3 talak?",
        "revdelete-show-file-submit": "Haan",
        "mergehistory-go": "Jorre jaae sake badlao ke dekhao",
        "mergehistory-submit": "Badlao ke jorro",
        "mergehistory-empty": "Koi badlao ke jorraa nai jaae sake hai.",
-       "mergehistory-done": "$1ke $3 {{PLURAL:$3|badlao|badlao}} ke safalta se [[:$2]] me jorr dewa gais hai.",
+       "mergehistory-done": "$1 ke $3 {{PLURAL:$3|badlao}} ke safalta se [[:$2]] me jorr dewaa gais hai.",
        "mergehistory-fail": "Itihaas ke nai jorre paaya hae, meharbaani kar ke panna aur time parameters ke check karo.",
+       "mergehistory-fail-bad-timestamp": "Timestamp valid nai hai.",
+       "mergehistory-fail-invalid-source": "Source panna valid nai hai.",
+       "mergehistory-fail-invalid-dest": "Destination panna valid nai hai.",
+       "mergehistory-fail-no-change": "Itihaas ke merge kare ke time, koi badlao waala panna ke merge nai karaa gais hai. Meharbaani kar ke recheck the page and time parameters.",
+       "mergehistory-fail-permission": "Itihaas ke merge kare ke khaatir sufficient permission nai hai.",
+       "mergehistory-fail-self-merge": "Suruu aur khatam kare waala panna ekke hai.",
+       "mergehistory-fail-timestamps-overlap": "Source revisions overlap or come after destination revisions.",
        "mergehistory-fail-toobig": "History merge nai hoe sake, kaaheki limit of $1 {{PLURAL:$1|revision|revisions}} se jaada move hoe jaai.",
        "mergehistory-no-source": "Source panna $1 nai hai.",
        "mergehistory-no-destination": "Destination panna $1 nai hai.",
        "search-external": "Bahaari khoj",
        "searchdisabled": "{{SITENAME}} me abhi khoje ke anumati nai hai.\nAap tab tak Google se khoje sakta hai.\nYaad rakhna ki uu log ke {{SITENAME}} ke index saait purana hoi.",
        "search-error": "Khoje ke tim ek error hoe gais hae:$1",
+       "search-warning": "A warning has occured while searching: $1",
        "preferences": "Pasand",
        "mypreferences": "Pasand",
        "prefs-edits": "Badlao ke number:",
        "prefs-help-recentchangescount": "Isme hai haali ke badlao, panna ke itihaas aur loga.",
        "prefs-help-watchlist-token2": "Aap ke dhyan suchi ke web feed ke ii secret key hae.\nAur koi agar iske bare me jaane hae aap ke dhyan suchi ke parrhae sake hae, tab iske aur ki ke nai dena.\n[[Special:ResetTokens|Agar aap iske reset kare mangtaa hae tab hian pe click karo]].",
        "savedprefs": "Aap ke pasand ke save kar lewa gais hai.",
-       "savedrights": "{{GENDER:$1|$1}} ke user rights ke bachae lewa gais hai.",
+       "savedrights": "{{GENDER:$1|$1}} ke user group ke bachae lewa gais hai.",
        "timezonelegend": "Time ke zone:",
        "localtime": "Sthaniye samay:",
        "timezoneuseserverdefault": "Wiki default ke kaam me laao ($1)",
        "prefswarning-warning": "Aap aapan preferences ke badla hae, jiske abhi talak save nai karaa gae hae.\nAgar aap ii panna ke bina \"$1\" me click kare chhorra, tab aap ke preferences save nai hoi.",
        "prefs-tabs-navigation-hint": "Tip: Aap left aur right arrow key use kar ke tab list me navigate kare saktaa hae.",
        "userrights": "Sadasya ke adhikaar ke chalao",
-       "userrights-lookup-user": "Sadasya ke group ke manage karo",
+       "userrights-lookup-user": "Ek sadasya ke chuno",
        "userrights-user-editname": "Ek Username ke enter karo:",
-       "editusergroup": "User groups ke badlo",
+       "editusergroup": "User groups ke load karo",
        "editinguser": "{{GENDER:$1|Sadasya}} <strong>[[User:$1|$1]]</strong>  ke adhikaar ke badlaa jaawe hae $2",
+       "viewinguserrights": "{{GENDER:$1|Sadasya}} <strong>[[User:$1|$1]]</strong>  ke adhikaar ke dekhaa jaawe hae $2",
        "userrights-editusergroup": "User groupske badlo",
-       "saveusergroups": "User groups ke save karo",
+       "userrights-viewusergroup": "User groups ke dekho",
+       "saveusergroups": "User groups, {{GENDER:$1|user}}, ke save karo",
        "userrights-groupsmember": "Iske member hai:",
        "userrights-groupsmember-auto": "Hian ke bhi member hae:",
        "userrights-groups-help": "Aap jon group me ii sadasya hai ke badle sakta hai:\n* Ek checked box ke matlab hai ki sadasya ii group me hai.\n* Ek unchecked box ke matlab hai ki sadasya ii group me nai hai.\n* Ek * ke matlab hai ki aap group ke jorre ke baad hatae nai sakta hai, nai to hatae ke baad jorre nai sakta hai.",
        "right-createpage": "Panna banao (jon ki salah kare waala panna nai hai)",
        "right-createtalk": "Salah kare waala panna banao",
        "right-createaccount": "Nawaa sadasya ke account banao",
+       "right-autocreateaccount": "Ek bahaari account se automatically login ho",
        "right-minoredit": "Badlao ke chhota mark karo",
        "right-move": "Panna ke naam badlo",
        "right-move-subpages": "Panna aur uske subpanna ke naam badlo",
        "right-siteadmin": "Database ke band karo aur kholo",
        "right-override-export-depth": "Panna aur jurra panna, 5 ke gahirrai talak, ke export karo",
        "right-sendemail": "Duusra sadasya ke lage e-mail bhejo",
-       "right-managechangetags": "Database se banao aur mitao [[Special:Tags|tags]]",
+       "right-managechangetags": "Database ke banao aur mitao [[Special:Tags|tags]]",
+       "right-applychangetags": "Aapan badlao ke saathe [[Special:Tags|tags]]  ke apply karo",
+       "right-changetags": "Individual entries aur log entries se arbitrary [[Special:Tags|tags]] ke jorro, nai to, hatao",
+       "right-deletechangetags": "Database se  [[Special:Tags|tags]] ke mitao",
+       "grant-generic": "\"$1\" rights bundle",
+       "grant-group-page-interaction": "Panna se interact karo",
+       "grant-group-file-interaction": "Media se interact karo",
+       "grant-group-watchlist-interaction": "Aapan watchlist se interact karo",
+       "grant-group-email": "Email bhejo",
+       "grant-group-high-volume": "Perform high volume activity",
+       "grant-group-customization": "Customization and preferences",
+       "grant-group-administration": "Perform administrative actions",
+       "grant-group-private-information": "Aaapan baare me private data ke access karo",
+       "grant-group-other": "Miscellaneous activity",
+       "grant-blockusers": "Sadasya ke block aur unblock karo",
+       "grant-createaccount": "Account banao",
+       "grant-createeditmovepage": "Panna ke banao, badlo aur hatao",
+       "grant-delete": "Pages, revisions, aur log entries ke mitao",
+       "grant-editinterface": "MediaWiki namespace aur user CSS/JavaScript ke badlo",
+       "grant-editmycssjs": "EAapan user CSS/JavaScript ke badlo",
+       "grant-editmyoptions": "Aapan user preferences ke badlo",
+       "grant-editmywatchlist": "Aapan dhyan suchi ke badlo",
+       "grant-editpage": "Abhi ke panna ke badlo",
+       "grant-editprotected": "Bachaawa gais panna ke badlo",
+       "grant-highvolume": "High-volume editing",
+       "grant-oversight": "Sadasya ke lukao aur revisions ke suppress karo",
+       "grant-patrol": "Panna me badlao pe pahraa do",
+       "grant-privateinfo": "Gupt jaankari ke access karo",
+       "grant-protect": "Panna ke protect aur unprotect karo",
+       "grant-rollback": "Rollback changes to pages",
+       "grant-sendemail": "Duusra sadasya ke lage e-mail bhejo",
+       "grant-uploadeditmovefile": "Upload, replace, and move files",
+       "grant-uploadfile": "Nawaa file ke upload karo",
        "newuserlogpage": "Sadasya ke banae waala log",
        "newuserlogpagetext": "Ii sadasya ke banae waala log hai.",
        "rightslog": "Sadasya adhikar suchi",
index 1e48a43..1bf31eb 100644 (file)
        "userrights-user-editname": "Unesite suradničko ime:",
        "editusergroup": "Učitaj suradničke skupine",
        "editinguser": "Promjena suradničkih prava {{GENDER:$1|suradnika|suradnice}} <strong>[[User:$1|$1]]</strong> $2",
+       "viewinguserrights": "Pregled suradničkih prava {{GENDER:$1|suradnika|suradnice}} <strong>[[User:$1|$1]]</strong> $2",
        "userrights-editusergroup": "Uredi suradničke skupine",
        "userrights-viewusergroup": "Pregled suradničkih skupina",
        "saveusergroups": "Spremi {{GENDER:$1|suradničke}} grupe",
index 30353f9..67500f2 100644 (file)
        "recentchanges-legend-heading": "<strong>Լեգենդ՝</strong>",
        "recentchanges-legend-newpage": "{{int:recentchanges-label-newpage}} (տես նաև՝  [[Special:NewPages|նոր էջերի ցանկ]])",
        "recentchanges-submit": "Ցույց տալ",
+       "rcfilters-filterlist-title": "Զտիչներ",
+       "rcfilters-filter-editsbyself-label": "Ձեր խմբագրումներ",
        "rcnotefrom": "Ստորև բերված են փոփոխությունները սկսած՝ '''$2''' (մինչև՝ '''$1''')։",
        "rclistfrom": "Ցույց տալ նոր փոփոխությունները սկսած $3 $2",
        "rcshowhideminor": "$1 չնչին խմբագրումները",
        "duration-centuries": "$1 {{PLURAL:$1|դար}}",
        "duration-millennia": "$1 {{PLURAL:$1|հազարամյակ}}",
        "expandtemplates": "Կաղապարների ընդարձակում",
+       "pagelang-nonexistent-page": "$1 էջը գոյություն չունի",
        "special-characters-group-latin": "Լատիներեն",
        "special-characters-group-latinextended": "Լատիներեն ընդլայնված",
        "special-characters-group-ipa": "IPA",
index 7430931..61b449e 100644 (file)
@@ -15,7 +15,8 @@
                        "Carlosedepaula",
                        "Macofe",
                        "Karmwiki",
-                       "Matma Rex"
+                       "Matma Rex",
+                       "Rafaneta"
                ]
        },
        "tog-underline": "Sublinear ligamines:",
        "recentchanges-legend-newpage": "{{int:recentchanges-label-newpage}} (vide etiam le [[Special:NewPages|lista de nove paginas]])",
        "recentchanges-legend-plusminus": "(''±123'')",
        "recentchanges-submit": "Monstrar",
+       "rcfilters-activefilters": "Filtros active",
+       "rcfilters-search-placeholder": "Filtrar le modificationes recente (naviga o comencia a scriber)",
+       "rcfilters-invalid-filter": "Filtro non valide",
+       "rcfilters-filterlist-title": "Filtros",
+       "rcfilters-filterlist-noresults": "Nulle filtro trovate",
+       "rcfilters-filtergroup-authorship": "Autor del modificationes",
+       "rcfilters-filter-editsbyself-label": "Tu proprie modificationes",
+       "rcfilters-filter-editsbyself-description": "Modificationes per te.",
+       "rcfilters-filter-editsbyother-label": "Modificationes per alteres",
+       "rcfilters-filter-editsbyother-description": "Modificationes create per altere usatores (non te).",
+       "rcfilters-filtergroup-userExpLevel": "Nivello de experientia del usator",
+       "rcfilters-filter-userExpLevel-newcomer-label": "Novicios",
+       "rcfilters-filter-userExpLevel-newcomer-description": "Autores multo nove: minus de 10 modificationes e 4 dies de activitate.",
+       "rcfilters-filter-userExpLevel-learner-label": "Apprentisses",
+       "rcfilters-filter-userExpLevel-learner-description": "Plus dies de activitate e modificationes que 'Novicios' ma minus que \"Usatores con experientia'.",
+       "rcfilters-filter-userExpLevel-experienced-label": "Usatores con experientia",
+       "rcfilters-filter-userExpLevel-experienced-description": "Plus de 30 dies de activitate e 500 modificationes.",
        "rcnotefrom": "Ecce le {{PLURAL:$5|modification|modificationes}} a partir del <strong>$3 a $4</strong> (usque a <strong>$1</strong> entratas monstrate).",
        "rclistfrom": "Monstrar nove modificationes a partir del $3 a $2",
        "rcshowhideminor": "$1 modificationes minor",
        "apisandbox-sending-request": "Invia requesta API...",
        "apisandbox-loading-results": "Recipe resultatos API...",
        "apisandbox-results-error": "Un error ha occurrite durante le cargamento del responsa al consulta API: $1.",
+       "apisandbox-request-params-json": "Parametros JSON:",
        "apisandbox-request-url-label": "URL de requesta:",
        "apisandbox-request-time": "Duration del requesta: {{PLURAL:$1|$1 ms}}",
        "apisandbox-results-fixtoken": "Corrige le indicio e reinvia",
        "proxyblockreason": "Tu adresse IP ha essite blocate proque illo es un proxy aperte.\nPer favor contacta tu providitor de servicio internet o supporto technic e informa les de iste problema grave de securitate.",
        "sorbsreason": "Tu adresse IP es listate como proxy aperte in le DNSBL usate per {{SITENAME}}.",
        "sorbs_create_account_reason": "Tu adresse IP es listate como proxy aperte in le DNSBL usate per {{SITENAME}}.\nTu non pote crear un conto",
+       "softblockrangesreason": "Contributiones anonime non son permittite de vostre adresse de IP ($1). Si il vos place, identifica vos.",
        "xffblockreason": "Un adresse IP presente in le capite X-Forwarded-For, o le tue o illo de un servitor proxy que tu usa, ha essite blocate. Le motivo original pro le blocada es: $1",
        "cant-see-hidden-user": "Le usator que tu tenta blocar ha ja essite blocate e celate. Post que tu non ha le derecto hideuser, tu non pote vider o modificar le blocada del usator.",
        "ipbblocked": "Tu non pote blocar o disblocar altere usatores, proque tu mesme es blocate",
        "pagelang-language": "Lingua",
        "pagelang-use-default": "Usar lingua predefinite",
        "pagelang-select-lang": "Selige lingua",
+       "pagelang-reason": "Ration",
        "pagelang-submit": "Submitter",
+       "pagelang-nonexistent-page": "Le pagina $1 non existe.",
+       "pagelang-unchanged-language": "Le pagina $1 es jam fixate sur le lingua $2.",
+       "pagelang-unchanged-language-default": "Le pagina $1 es jam fixate sur le lingua predefinite de contento del wiki.",
+       "pagelang-db-failed": "Le base de datos non ha potite cambiar le lingua del pagina.",
        "right-pagelang": "Cambiar lingua del pagina",
        "action-pagelang": "cambiar le lingua del pagina",
        "log-name-pagelang": "Registro de cambios de lingua",
index 41aa59c..8e4d1ff 100644 (file)
                        "לערי ריינהארט",
                        "아라",
                        "Macofe",
-                       "Robin van der Vliet"
+                       "Robin van der Vliet",
+                       "Algentem",
+                       "Joao Xavier"
                ]
        },
        "tog-underline": "Sub-strekizez ligili:",
        "tog-hideminor": "Celez mikra redaktaji de recenta chanji",
        "tog-hidepatrolled": "Celez patroliita redakti en recenta chanji",
        "tog-newpageshidepatrolled": "Celez patroliita pagini en la listo di nova pagino",
+       "tog-hidecategorization": "Celar kategorizeso di la pagini",
        "tog-extendwatchlist": "Expansez surveyo-listo por montrar omna chanji, vice nur la maxim recenta",
        "tog-usenewrc": "Usez augmentita Recenta chanji (JavaScript bezonesas)",
        "tog-numberheadings": "Autonumerez tituli",
        "tog-showtoolbar": "Montrez redaktilo (JavaScript bezonesas)",
        "tog-editondblclick": "Redaktez pagini kande on klikus dufoye (JavaScript bezonesas)",
        "tog-editsectiononrightclick": "Kapabligez redakto di secioni kande on dextra-klikus tituli di secioni (JavaScript bezonesas)",
-       "tog-watchcreations": "Adjuntez pagini kreota da me ad mea surveyaji",
-       "tog-watchdefault": "Adjuntez pagini redaktota da me ad mea surveyaji",
-       "tog-watchmoves": "Adjuntez pagini movota da me ad mea surveyaji",
-       "tog-watchdeletion": "Adjuntez pagini efacota da me ad mea surveyaji",
+       "tog-watchcreations": "Adjuntez la pagini qui me kreos a mea surveyaji",
+       "tog-watchdefault": "Adjuntez pagini qui me redaktos a mea surveyaji",
+       "tog-watchmoves": "Adjuntez pagini qui me movos a mea surveyaji",
+       "tog-watchdeletion": "Adjuntez pagini qui me efacos a mea surveyaji",
+       "tog-watchuploads": "Adjuntez nov arkivi qui me sendos a mea surveyaji",
+       "tog-watchrollback": "Adjuntez pagini ube me desfacos editadi a mea surveyaji",
        "tog-minordefault": "Markizez kustume omna redaktajo kom mikra",
        "tog-previewontop": "Montrez prevido avan la redakto-buxo",
        "tog-previewonfirst": "Montrez prevido pos la unesma redakto",
-       "tog-enotifwatchlistpages": "Sendez e-posto a me kande pagino quan me surveyas chanjesas",
+       "tog-enotifwatchlistpages": "Sendez e-posto a me kande pagino quan me surveyas chanjesos",
        "tog-enotifusertalkpages": "Sendez e-posto a me kande mea diskuto-pagino chanjesas",
        "tog-enotifminoredits": "Sendez e-posto a me mem por mikra chanji",
        "tog-enotifrevealaddr": "Montrez mea e-posto adreso en notifiko e-posti",
        "tog-shownumberswatching": "Montrez nombro di surveyanta uzanti",
+       "tog-oldsig": "Vua existanta signaturo:",
        "tog-fancysig": "Traktez signaturo kom wikikodo (sen automata ligilo)",
+       "tog-uselivepreview": "Uzes quika previdado",
        "tog-forceeditsummary": "Notifikez me kande skribanta vakua redakto-rezumo",
        "tog-watchlisthideown": "Celez mea redaktaji de la surveyaji",
        "tog-watchlisthidebots": "Celez redaktaji da roboti de la surveyaji",
        "tog-watchlisthideminor": "Celez mikra redaktaji de la surveyaji",
+       "tog-watchlisthideliu": "Celar l'editadi dal uzanti enrejistrita qui esas en la listo",
+       "tog-watchlistreloadautomatically": "Rimontrez automatale la listo, kande filtrilo modifikesos (bezonas JavaScript)",
+       "tog-watchlisthideanons": "Celar de la listo l'editadi facita da anonima redakteri",
        "tog-watchlisthidepatrolled": "Celez patroliita chanji en la surveyo-listo",
+       "tog-watchlisthidecategorization": "Celar la kategorizeso di pagini",
        "tog-ccmeonemails": "Sendez a me exemplero di e-posti quin me sendos ad altra uzanti",
        "tog-diffonly": "Ne montrez pagino kontenajo sub diferi",
        "tog-showhiddencats": "Montrar celita kategorii",
        "tog-norollbackdiff": "Omisar difero-komparo pos retrorulo",
+       "tog-useeditwarning": "Avertez se me probos klozar ula pagino sen sparar mea modifiki ed edituri",
+       "tog-prefershttps": "Sempre uzar sekura konekto kande facar log in",
        "underline-always": "Sempre",
        "underline-never": "Nulatempe",
+       "editfont-style": "Stilo di fonto uzata por editar la texto:",
+       "editfont-monospace": "Tipo por redaktar kun singla spaco",
+       "editfont-sansserif": "tipo Sans-serif",
+       "editfont-serif": "tipo di fonto Serif",
        "sunday": "sundio",
        "monday": "lundio",
        "tuesday": "mardio",
        "oct": "okt",
        "nov": "nov",
        "dec": "dec",
+       "january-date": "$1ma di januaro",
+       "february-date": "$1ma di februaro",
+       "march-date": "$1ma di marto",
+       "april-date": "$1ma di aprilo",
+       "may-date": "$1ma di mayo",
+       "june-date": "$1ma di junio",
+       "july-date": "$1ma di julio",
+       "august-date": "$1ma di agosto",
+       "september-date": "$1ma di septembro",
+       "october-date": "$1ma di oktobro",
+       "november-date": "$1ma di novembro",
+       "december-date": "$1ma di decembro",
+       "period-am": "matine",
+       "period-pm": "posdimezo",
        "pagecategories": "{{PLURAL:$1|Kategorio|Kategorii}}",
        "category_header": "Artikli en kategorio \"$1\"",
        "subcategories": "Subkategorii",
        "category-file-count": "{{PLURAL:$2|Ica kategorio havas nur la sequanta arkivo.|La sequanta {{PLURAL:$1|arkivo|$1 arkivi}} es en ica kategorio, ek $2.}}",
        "category-file-count-limited": "La sequanta {{PLURAL:$1|arkivo|$1 arkivi}} es en la aktuala kategorio.",
        "listingcontinuesabbrev": "seq.",
+       "index-category": "indexigata pagini",
+       "noindex-category": "pagini sen indexi",
+       "broken-file-category": "Pagini kun ligili a neexistanta pagini",
        "about": "Pri",
        "article": "artiklo",
        "newwindow": "(aparos en nova panelo)",
        "cancel": "Anular",
-       "moredotdotdot": "Plus...",
+       "moredotdotdot": "Plua...",
+       "morenotlisted": "Ca listo povas esar nekompleta",
        "mypage": "Mea pagino",
        "mytalk": "Diskuti",
        "anontalk": "Diskuto relatant ad ica IP",
        "navigation": "Navigado",
        "and": "&#32;ed",
        "qbfind": "Trovez",
+       "qbbrowse": "Montrez listo",
        "qbedit": "Redaktar",
        "qbpageoptions": "Ica pagino",
        "qbmyoptions": "Mea pagini",
+       "faq": "Maxim komuna questioni",
+       "faqpage": "Project:FAQ - maxim komuna questioni",
        "actions": "Agi",
        "namespaces": "Nomari",
        "variants": "Varianti",
+       "navigation-heading": "Selektar dum la navigado",
        "errorpagetitle": "Eroro",
        "returnto": "Retrovenar a $1.",
        "tagline": "De {{SITENAME}}",
        "help": "Helpo",
        "search": "Sercho",
+       "search-ignored-headings": " #<!-- mantenez ica lineo sen modifiki --> <pre>\n# Tituli qui ignoresos per la sistemo di serchado.\n# Modifiki en ca parto efikeskos balde pos la titulo di la pagino adicionesos a l'indexo.\n# Tu povas acelerar la riindexigo di la pagino facante nihila editado.\n# La sintaxo esas quale infre:\n#   * Omna texti qui finas kun la signo \"#\" fine de la lineo, esas komentaro.\n#   * Omna lineo ne blanka - to esas: skriptata -, esas l'exakta titulo por ignorar la diferi inter mayuskula e minuskula literi, ed altra.\nReferi\nExtera ligili\nVidez anke\n #</pre> <!-- mantenez ica lineo sen modifiki -->",
        "searchbutton": "Serchez",
        "go": "Irar",
        "searcharticle": "Irez",
        "printableversion": "Imprimebla versiono",
        "permalink": "Permananta ligilo",
        "print": "Imprimar",
+       "view": "Videz",
+       "view-foreign": "Videz en $1",
        "edit": "Redaktar",
+       "edit-local": "Facar deskriptado lokale",
        "create": "Krear",
+       "create-local": "Inkluzar lokala deskriptado",
        "editthispage": "Redaktar ca pagino",
        "create-this-page": "Kreez ca pagino",
        "delete": "Efacar",
        "deletethispage": "Efacar ica pagino",
+       "undeletethispage": "Desfacar l'efaco di ca pagino",
        "undelete_short": "Restaurar {{PLURAL:$1|1 redakto|$1 redakti}}",
+       "viewdeleted_short": "Vidar {{PLURAL:$1|1 redakto efacita|$1 redakti efacita}}",
        "protect": "Protektar",
        "protect_change": "chanjar",
        "protectthispage": "Protektar ica pagino",
        "talk": "Diskuto",
        "views": "Apari",
        "toolbox": "Utensili",
+       "tool-link-userrights": "Chanjar la grupi di {{GENDER:$1|uzanto}}",
+       "tool-link-userrights-readonly": "Vidar lua grupi",
+       "tool-link-emailuser": "Sendar e-posto a {{GENDER:$1|}}",
        "userpage": "Vidar uzanto-pagino",
        "projectpage": "Vidar projeto-pagino",
        "imagepage": "Vidar arkivo-pagino",
        "otherlanguages": "En altra lingui",
        "redirectedfrom": "(Ridirektita de $1)",
        "redirectpagesub": "Ridirektanta pagino",
+       "redirectto": "Ridirektar a:",
        "lastmodifiedat": "Ica pagino modifikesis ye $2, $1.",
        "viewcount": "Ica pagino acesesis {{PLURAL:$1|1 foyo|$1 foyi}}.",
        "protectedpage": "Protektita pagino",
        "jumpto": "Irez ad:",
        "jumptonavigation": "pilotado",
        "jumptosearch": "serchez",
+       "view-pool-error": "Pardonez, la sistemo esas okupata nun.\nMulta uzanti deziras vidar ca pagino.\nVoluntez vartar kelka instanti ante itere probar vidar ol.\n\n$1",
+       "pool-timeout": "Limito di tempo vartante la klozado",
+       "pool-queuefull": "La serio di taski esas plena",
+       "pool-errorunknown": "nekonocata eroro",
+       "pool-servererror": "La sistemo qua kontrolas l'aceso a $1 ne esas disponebla",
+       "poolcounter-usage-error": "Eroro di uzado:$1",
        "aboutsite": "Pri {{SITENAME}}",
        "aboutpage": "Project:Pri {{SITENAME}}",
-       "copyright": "La kontenajo esas disponebla sub $1.",
+       "copyright": "La kontenajo esas disponebla sub $1, ecepte kande kontree mencionata.",
        "copyrightpage": "{{ns:project}}:Autor-yuri",
        "currentevents": "Aktualaji",
        "currentevents-url": "Project:Aktualaji",
        "disclaimers": "Legala averto",
        "disclaimerpage": "Project:Generala des-agnosko",
        "edithelp": "Helpo pri redaktado",
-       "mainpage": "Frontispico",
-       "mainpage-description": "Frontispico",
+       "helppage-top-gethelp": "Helpo",
+       "mainpage": "Chefpagino",
+       "mainpage-description": "Chefpagino",
        "policy-url": "Project:Sistemo di agado",
        "portal": "Komuneso-portalo",
        "portal-url": "Project:Komuneso-portalo",
        "ok": "O.K.",
        "retrievedfrom": "Obtenita de \"$1\"",
        "youhavenewmessages": "Vu havas $1 ($2).",
+       "youhavenewmessagesfromusers": "{{PLURAL:$4|Vu havas}} $1 dal {{PLURAL:$3|altra uzanto|$3 uzanti}} ($2).",
+       "youhavenewmessagesmanyusers": "Tu havas $1 da multa uzanti ($2).",
+       "newmessageslinkplural": "{{PLURAL:$1| nova mesajo|999= nova mesaji}}",
+       "newmessagesdifflinkplural": "Lasta {{PLURAL:$1|chanjo|chanji}}",
        "youhavenewmessagesmulti": "Vu havas nova mesaji ye $1",
        "editsection": "redaktar",
        "editold": "redaktar",
        "toc": "Indexo",
        "showtoc": "montrar",
        "hidetoc": "celar",
+       "collapsible-collapse": "Celar la listo",
+       "collapsible-expand": "Montrar la listo",
+       "confirmable-confirm": "Ka vu {{GENDER:$1|vi}} fakte deziras facar to?",
+       "confirmable-yes": "Yes",
+       "confirmable-no": "No",
        "thisisdeleted": "Ka vidar o restaurar $1?",
        "viewdeleted": "Vidar $1?",
        "restorelink": "{{PLURAL:$1|1 redakto efacita|$1 redakti efacita}}",
+       "feedlinks": "Fonto RSS:",
+       "feed-invalid": "Tipo di fonto RSS nevalida",
        "site-rss-feed": "$1 RSS Provizajo",
        "site-atom-feed": "$1 Atom Provizajo",
        "page-rss-feed": "\"$1\" RSS Provizajo",
        "page-atom-feed": "\"$1\" Atom Provizajo",
        "red-link-title": "$1 (pagino ne existas)",
+       "sort-descending": "En ordino dekreskanta",
+       "sort-ascending": "En ordino kreskanta",
        "nstab-main": "Pagino",
        "nstab-user": "Uzanto-pagino",
        "nstab-special": "Specala pagino",
        "nstab-template": "Shablono",
        "nstab-help": "Helpo",
        "nstab-category": "Kategorio",
+       "mainpage-nstab": "Chefpagino",
        "nosuchaction": "Ne esas tala ago",
+       "nosuchactiontext": "L'agado determinata en la URL esas nevalida.\nPosible vu skribis la URL nekorekte, o sequis nevalida ligilo.\nTo anke povas indikar \"bug\" en la programo por *komputero uzata per {{SITENAME}}.",
        "nosuchspecialpage": "Ne existas tala specala pagino",
        "nospecialpagetext": "<strong>Vu demandis specala pagino qua ne existas.</strong>\n\nOn povas trovar listo di valida specala pagini en [[Special:SpecialPages|{{int:specialpages}}]].",
        "error": "Eroro",
        "databaseerror": "Datumarala eroro",
+       "databaseerror-error": "Eroro:$1",
+       "laggedslavemode": "<strong>Averto:</strong> La pagino povas ne kontenar la maxim recenta modifiki.",
        "readonly": "Datumaro esas blokusita",
        "enterlockreason": "Explikez la motivo por la blokuso, inkluzante\nevaluo pri kande eventos la desblokuso",
+       "readonlytext": "La datumaro nuntempe esas klozata por nova modifiki, probable pro facesar manteni rutinala. Pos la manteni, ol retrovenos a la normala stando.\n\nL'administranto di la sistemo qua klozis la datumaro explikis to: $1",
        "missingarticle-rev": "(versiono#: $1)",
        "missingarticle-diff": "(Difero: $1, $2)",
        "internalerror": "Interna eroro",
        "protectedpagetext": "Ica pagino esis protektita por preventar redaktar.",
        "viewsourcetext": "Vu povas vidar ed kopiar la fonto-kodexo di ta pagino:",
        "ns-specialprotected": "On ne povas redaktar speciala pagini.",
-       "logouttext": "'''Vu nun esas nun ek {{SITENAME}}.'''\n\nVu povas durar uzante {{SITENAME}} anonimale, o vu povas <span class='plainlinks'>[$1 enirar itere]</span> kom la sama o diferenta uzanto.\nAtencez ke kelka pagini posible duras montresar semblante ke vu ne ekirus, til vu vakuigas la tempala-magazino di vua navigilo.",
+       "virus-unknownscanner": "antiviruso nekonocata:",
+       "logouttext": "<strong>'''Vu nun esas nun ek {{SITENAME}}.'''</strong>\n\nVu povas durar uzante {{SITENAME}} anonimale, o vu povas <span class='plainlinks'>[$1 enirar itere]</span> kom la sama o diferenta uzanto.\nAtencez ke kelka pagini posible duras montresar semblante ke vu ne ekirus, til vu vakuigas la tempala-magazino di vua navigilo.",
+       "cannotlogoutnow-title": "Ne povas ekirar nun",
+       "cannotlogoutnow-text": "Ekirar ne esas posibla kande vu uzas $1.",
+       "welcomeuser": "Esez bonvenanta, $1!",
+       "welcomecreation-msg": "Vua konto kreesis.\n\nVu povas modifikar vua [[Special:Preferences|preferaji en la {{SITENAME}}]] se vu deziras.",
        "yourname": "Vua uzantonomo:",
+       "userlogin-yourname": "Uzantonomo",
+       "userlogin-yourname-ph": "Enirez vua uzantonomo",
+       "createacct-another-username-ph": "Enirez la uzantonomo",
        "yourpassword": "Pasovorto:",
+       "userlogin-yourpassword": "pasovorto",
+       "userlogin-yourpassword-ph": "Enirez vua pasovorto",
+       "createacct-yourpassword-ph": "Enirez pasovorto",
        "yourpasswordagain": "Riskribez la pasovorto:",
+       "createacct-yourpasswordagain": "Konfirmez la pasovorto",
+       "createacct-yourpasswordagain-ph": "Enirez itere la pasovorto",
+       "userlogin-remembermypassword": "Mantenez me konektata",
+       "userlogin-signwithsecure": "Usez sekura konekto",
+       "cannotlogin-title": "Ne povis enirar",
+       "cannotlogin-text": "Ne esas posibla konektar a la sistemo",
+       "cannotloginnow-title": "Ne povas enirar nun",
+       "cannotloginnow-text": "Enirar ne esas posibla kande vu usas $1",
+       "cannotcreateaccount-title": "Ne povas krear la konti",
        "yourdomainname": "Vua domano:",
        "login": "Enirar",
-       "nav-login-createaccount": "Enirar",
+       "nav-login-createaccount": "Enirar / Krear konto",
        "userlogin": "Enirar / krear konto",
        "userloginnocreate": "Enirar",
        "logout": "Ekirar",
        "userlogout": "Ekirar",
        "notloggedin": "Sesiono ne esas iniciata",
+       "userlogin-joinproject": "Enirez la {{SITENAME}}",
        "nologin": "Ka vu ne havas konto? $1.",
        "nologinlink": "Kreez konto",
        "createaccount": "Krear nova konto",
        "gotaccount": "Ka vu ja havas konto? '''$1'''.",
        "gotaccountlink": "Enirar",
-       "createaccountmail": "per e-posto",
+       "userlogin-resetlink": "Ka tu obliviis la detalii pri tua konekto?",
+       "userlogin-resetpassword-link": "Ka tu obliviis tua pasovorto?",
+       "userlogin-helplink2": "Helpo pri quale enirar",
+       "userlogin-loggedin": "Tu ja eniris, kun la nomo {{GENDER:$1|$1}}\n\nUsez la formulario infre por enirar quale altra uzanto.",
+       "createaccountmail": "Uzez provizora pasovorto, ed ad adresizez ol a la korespondanta e-posto",
+       "createacct-realname": "Vera nomo (fakultativa)",
        "createaccountreason": "Motivo:",
+       "createacct-reason": "Motivo",
+       "createacct-reason-ph": "Pro quo tu kreas nova konto",
        "badretype": "La pasovorti vu donis ne esas sama.",
        "userexists": "La uzantonomo, quan vu skribis, ja selektesis antee.\nVoluntez, elektez ula diferanta uzantonomo.",
        "loginerror": "Eroro enirante",
+       "nocookiesnew": "L'uzero-konto esis kreita, ma vu ne esas eniranta.\n{{SITENAME}} uzas ''bisquiti'' por eniras uzeri.\n''Bisquiti'' esas desacendita.\nVoluntez acendar li, lore enirez per vua nova uzero e pasovorto.",
        "nocookieslogin": "{{SITENAME}} uzas ''cookies'' por la registrago dil uzanti. Vu havas la ''cookies'' desaktivigita. Voluntez aktivigar oli e probez altrafoye.",
        "noname": "Vu ne donis valida uzantonomo.",
        "loginsuccesstitle": "Eniro sucesoza",
        "mailmypassword": "Sendez nova pasovorto per e-posto",
        "passwordremindertitle": "Nova provizora pasovorto por {{SITENAME}}",
        "noemail": "Ne esas e-adreso konservita por la uzanto \"$1\".",
+       "noemailcreate": "Tu mustas informar valida e-posto",
        "passwordsent": "Nova pasovorto sendesis a la e-adreso registragita por \"$1\".\nVoluntez enirar altrafoye pos recevar ol.",
+       "blocked-mailpassword": "Vua adreso di IP blokuzesis por redaktado. Por preventar misuzo, ne permisesas rekuperar pasovorti de ca adreso di IP.",
+       "eauthentsent": "E-posto por konfirmar l'informi sendesis a la e-posto indikita da vu.\nAnte ke altra e-posto sendesos a vua konto, vu mustos sequar l'instrukti mencionata en la e-posto, por konfirmar ke la konto fakte esas vua.",
+       "throttled-mailpassword": "A password reset email has already been sent, within the last {{PLURAL:$1|hour|$1 hours}}.\nTo prevent abuse, only one password reset email will be sent per {{PLURAL:$1|hour|$1 hours}}.",
        "mailerror": "Eroro sendante posto: $1",
        "acct_creation_throttle_hit": "Vizitanti ad ica wiki uzante vua IP adreso kreis {{PLURAL:$1|1 konto|$1 konti}} ye la antea dio (24 hori), qua esas la maximo permisata. Konseque, vizitanti uzante ca IP adreso ne pluse povas krear konti prezente.",
        "emailauthenticated": "Vua e-postala adreso autentikigesis ye $2, ye $3.",
        "permissionserrorstext-withaction": "Vu ne darfas $2, pro la {{PLURAL:$1|kauzo|kauzi}} sequanta:",
        "moveddeleted-notice": "Ca pagino efacesabas.\nLa efaco-registraro e movo-registraro dil pagino provizesar sequante por refero.",
        "edit-conflict": "Konflikto di editi.",
+       "content-model-javascript": "JavaScript",
+       "content-json-empty-object": "vakua objekto",
+       "content-json-empty-array": "vakua tabelo",
+       "deprecated-self-close-category": "Pages using invalid self-closed HTML tags",
        "viewpagelogs": "Videz registrari por ca pagino",
        "nohistory": "Ne esas redakto-historio por ica pagino.",
        "currentrev": "Aktuala versiono",
        "preferences": "Preferaji",
        "mypreferences": "Preferaji",
        "prefs-edits": "Nombro di redaktaji:",
+       "prefsnologintext2": "Voluntez enirar por chanjar vua ajusti.",
        "prefs-skin": "Pelo",
        "skin-preview": "Pre-videz",
        "datedefault": "Sen prefero",
        "recentchanges-label-minor": "Ica es mikra redaktajo",
        "recentchanges-label-bot": "Ta chanjo facita da bot",
        "recentchanges-legend-newpage": "$1 - nova pagino",
+       "rcfilters-filter-userExpLevel-experienced-description": "Plu kam 30 dii di agemeso e 500 redakti.",
        "rcnotefrom": "Infre esas la lasta chanji depos '''$2''' (montrita til '''$1''').",
        "rclistfrom": "Montrar nova chanji startante de $3 $2",
        "rcshowhideminor": "$1 mikra redakti",
        "notargettext": "Vu ne definis en qua pagino agar ica funciono.",
        "pager-newer-n": "{{PLURAL:$1|plu nova 1|plu nova $1}}",
        "pager-older-n": "{{PLURAL:$1|plu anciena 1|plu anciena $1}}",
+       "apihelp-no-such-module": "Modulo « $1 » ne esis trovita.",
+       "apisandbox-loading": "Charjas informo pri modulo « $1 » di API...",
        "booksources": "Fonti di libri",
        "booksources-search-legend": "Serchez librala fonti",
        "specialloguserlabel": "Uzanto:",
        "tooltip-search": "Serchez en {{SITENAME}}",
        "tooltip-search-go": "Irez a pagino havanta ta exakta nomo, se existus",
        "tooltip-search-fulltext": "Serchez ca texto en la pagini",
-       "tooltip-p-logo": "Frontispico",
-       "tooltip-n-mainpage": "Vizitez la Frontispico",
-       "tooltip-n-mainpage-description": "Vizitez la frontispico",
+       "tooltip-p-logo": "Chefpagino",
+       "tooltip-n-mainpage": "Vizitez la Chefpagino",
+       "tooltip-n-mainpage-description": "Vizitez la chefpagino",
        "tooltip-n-portal": "Pri la projeto, quon vu facus, ube trovus utilaji",
        "tooltip-n-currentevents": "Trovez informeco pri aktuala eventi",
        "tooltip-n-recentchanges": "Listo di recenta chanji en la wiki.",
        "tooltip-feed-atom": "Atom provizero por ica pagino",
        "tooltip-t-contributions": "Videz kontributaji di ta uzanto",
        "tooltip-t-emailuser": "Sendez mesajo al uzanto",
+       "tooltip-t-info": "Plua informo pri ca pagino",
        "tooltip-t-upload": "Adkargez arkivi",
        "tooltip-t-specialpages": "Montrez listo di omna specala pagini",
        "tooltip-t-print": "Imprimebla versiono di ca pagino",
        "tags-hitcount": "$1 {{PLURAL:$1|chanjo|chanji}}",
        "htmlform-reset": "Desfacar chanji",
        "htmlform-selectorother-other": "Altra",
+       "htmlform-cloner-create": "Adjuntar plue",
        "rightsnone": "(nula)",
        "revdelete-summary": "redakto-rezumo",
        "searchsuggest-search": "Serchez",
        "special-characters-group-greek": "Grekiana",
        "special-characters-group-cyrillic": "Kirila",
        "special-characters-group-arabic": "Arabiana",
-       "special-characters-group-persian": "Persiana"
+       "special-characters-group-persian": "Persiana",
+       "sessionprovider-nocookies": "''Bisquiti'' forsan esas desacendita. Certigez ke vu acendar ''bisquiti'' e riprobez."
 }
index e61655e..4cd0cfd 100644 (file)
        "recentchanges-legend-newpage": "{{int:recentchanges-label-newpage}} (vedi le [[Special:NewPages|nuove pagine]])",
        "recentchanges-legend-plusminus": "(''±123'')",
        "recentchanges-submit": "Mostra",
+       "rcfilters-activefilters": "Filtri attivi",
+       "rcfilters-invalid-filter": "Filtro non valido",
+       "rcfilters-filterlist-title": "Filtri",
+       "rcfilters-filterlist-noresults": "Nessun filtro trovato",
        "rcnotefrom": "Di seguito {{PLURAL:$5|è elencata la modifica apportata|sono elencate le modifiche apportate}} a partire da <strong>$3, $4</strong> (mostrate fino a <strong>$1</strong>).",
        "rclistfrom": "Mostra le modifiche apportate a partire da $3 $2",
        "rcshowhideminor": "$1 le modifiche minori",
        "apisandbox-sending-request": "Invio richiesta di API...",
        "apisandbox-loading-results": "Ricezione dei risultati di API in corso...",
        "apisandbox-results-error": "Si è verificato un errore durante il caricamento della risposta all'interrogazione API: $1",
+       "apisandbox-request-params-json": "Parametri JSON:",
        "apisandbox-request-url-label": "URL di richiesta:",
        "apisandbox-request-time": "Tempo richiesto: {{PLURAL:$1|$1 ms}}",
        "apisandbox-results-fixtoken": "Correggi token e reinvia",
        "pagelang-language": "Lingua",
        "pagelang-use-default": "Utilizza la lingua predefinita",
        "pagelang-select-lang": "Seleziona lingua",
+       "pagelang-reason": "Motivo",
        "pagelang-submit": "Invia",
+       "pagelang-nonexistent-page": "La pagina $1 non esiste.",
        "right-pagelang": "Modifica la lingua della pagina",
        "action-pagelang": "modificare la lingua della pagina",
        "log-name-pagelang": "Modifiche lingua",
index e5b0f23..146b00d 100644 (file)
        "pageinfo-length": "ページの長さ (バイト単位)",
        "pageinfo-article-id": "ページ ID",
        "pageinfo-language": "ページ本文の言語",
+       "pageinfo-language-change": "変更",
        "pageinfo-content-model": "ページのコンテンツ モデル",
        "pageinfo-content-model-change": "設定変更",
        "pageinfo-robot-policy": "ロボットによるインデックス作成",
index ed5ffde..546db7a 100644 (file)
        "eauthentsent": "입력한 이메일로 확인 이메일을 보냈습니다.\n다른 모든 형태의 이메일을 당신의 계정으로 보내기 전에, 계정이 정말 당신의 것인지 확인하기 위해 이메일 내용의 지시대로 계정 확인 절차를 실행해 주셔야 합니다.",
        "throttled-mailpassword": "비밀번호 재설정 이메일을 이미 최근 {{PLURAL:$1|$1시간}} 안에 보냈습니다.\n악용을 방지하기 위해 비밀번호 재설정 메일은 {{PLURAL:$1|$1시간}}마다 오직 하나씩만 보낼 수 있습니다.",
        "mailerror": "메일을 보내는 중 오류: $1",
-       "acct_creation_throttle_hit": "당신의 IP 주소를 이용한 방문자가 $2에 이미 {{PLURAL:$1|계정 $1개}}를 만들어, 계정 만들기 한도를 초과하였습니다.\n따라서 지금은 이 IP 주소로는 더 이상 계정을 만들 수 없습니다.",
+       "acct_creation_throttle_hit": "당신의 IP 주소를 이용한 이 위키의 방문자가 $2에 {{PLURAL:$1|계정 $1개}}를 만들었으며, 이 기간 안에 허용되는 계정 만들기 한도를 초과하였습니다.\n따라서 지금 이 IP 주소를 사용하는 방문자는 더 이상 계정을 만들 수 없습니다.",
        "emailauthenticated": "이메일 주소가 $2 $3에 인증되었습니다.",
        "emailnotauthenticated": "이메일 주소를 인증하지 않았습니다.\n이메일 확인 절차를 거치지 않으면 다음 이메일 기능을 사용할 수 없습니다.",
        "noemailprefs": "이 기능을 사용하려면 사용자 환경 설정에서 이메일 주소를 지정하세요.",
        "botpasswords-updated-body": "사용자 \"$2\"의 \"$1\"라는 이름의 봇 비밀번호가 업데이트되었습니다.",
        "botpasswords-deleted-title": "봇 비밀번호 제거",
        "botpasswords-deleted-body": "사용자 \"$2\"의 \"$1\"라는 이름의 봇 비밀번호가 삭제되었습니다.",
-       "botpasswords-newpassword": "<strong>$1</strong>님으로 로그인하기 위한 새 비밀번호가 <strong>$2</strong>입니다. <em>잊어버리지 않도록 기록해두시기 바랍니다.</em>",
+       "botpasswords-newpassword": "<strong>$1</strong>님으로 로그인하기 위한 새 비밀번호는 <strong>$2</strong>입니다. <em>추후 참조를 위해 이것을 기록해두시기 바랍니다.</em> <br> (로그인 이름이 최종 사용자 이름과 동일해야 하는 오래된 봇의 경우, 사용자 이름으로 <strong>$3</strong>을(를), 비밀번호로 <strong>$4</strong>을(를) 사용할 수도 있습니다)",
        "botpasswords-no-provider": "'BotPasswordsSessionProvider'는 이용할 수 없습니다.",
        "botpasswords-restriction-failed": "봇 비밀번호 제한으로 인해 로그인할 수 없습니다.",
        "botpasswords-invalid-name": "지정된 사용자 이름은 봇 비밀번호 구분자(\"$1\")를 포함하고 있지 않습니다.",
        "blockedtitle": "사용자가 차단됨",
        "blockedtext": "'''사용자 계정 또는 IP 주소가 차단되었습니다.'''\n\n차단한 사람은 $1입니다.\n차단한 이유는 다음과 같습니다: $2\n\n* 차단이 시작된 시간: $8\n* 차단이 끝나는 시간: $6\n* 차단된 사용자: $7\n\n$1 또는 [[{{MediaWiki:Grouppage-sysop}}|다른 관리자]]에게 차단에 대해 문의할 수 있습니다.\n[[Special:Preferences|계정 환경 설정]]에 올바른 이메일 주소가 있어야만 '이메일 보내기' 기능을 사용할 수 있습니다. 또 이메일 보내기 기능이 차단되어 있으면 이메일을 보낼 수 없습니다.\n현재 당신의 IP 주소는 $3이고, 차단 ID는 #$5입니다.\n문의할 때에 이 정보를 같이 알려주세요.",
        "autoblockedtext": "당신의 IP 주소는 $1님이 차단한 사용자가 사용했던 IP이기 때문에 자동으로 차단되었습니다.\n차단된 이유는 다음과 같습니다:\n\n:$2\n\n* 차단이 시작된 시간: $8\n* 차단이 끝나는 시간: $6\n* 차단된 사용자: $7\n\n$1 또는 [[{{MediaWiki:Grouppage-sysop}}|다른 관리자]]에게 차단에 대해 문의할 수 있습니다.\n\n[[Special:Preferences|사용자 환경 설정]]에 올바른 이메일 주소가 있어야만 \"이메일 보내기\" 기능을 사용할 수 있습니다. 또한 이메일 보내기 기능이 차단되어 있으면 이메일을 보낼 수 없습니다.\n\n현재 IP 주소는 $3이고, 차단 ID는 #$5입니다.\n문의할 때에 이 정보를 같이 알려주세요.",
+       "systemblockedtext": "당신의 사용자 이름 또는 IP 주소가 자동으로 미디어위키에 의해 차단되었습니다.\n이유는 다음과 같습니다:\n\n:<em>$2</em>\n\n* 차단 시작: $8\n* 차단 만료: $6\n* 차단 대상: $7\n\n당신의 현재 IP 주소는 $3입니다.\n문의에 대해 상기의 상세 설명을 모두 포함해 주십시오.",
        "blockednoreason": "이유를 입력하지 않음",
        "whitelistedittext": "문서를 편집하기 전에 $1해야 합니다.",
        "confirmedittext": "문서를 고치려면 이메일 인증 절차가 필요합니다.\n[[Special:Preferences|사용자 환경 설정]]에서 이메일 주소를 입력하고 이메일 주소 인증을 해주시기 바랍니다.",
        "userrights-user-editname": "사용자 이름 입력:",
        "editusergroup": "사용자 그룹 불러오기",
        "editinguser": "<strong>[[User:$1|$1]]</strong> $2 {{GENDER:$1|사용자}}의 권한 바꾸기",
+       "viewinguserrights": "<strong>[[User:$1|$1]]</strong> $2 {{GENDER:$1|사용자}}의 권한을 보는 중",
        "userrights-editusergroup": "사용자 그룹 편집",
        "userrights-viewusergroup": "사용자 그룹 보기",
        "saveusergroups": "{{GENDER:$1|사용자}} 권한 저장",
        "action-deletedtext": "삭제된 판의 문자열 보기",
        "action-browsearchive": "삭제된 문서 검색",
        "action-undelete": "문서 되살리기",
-       "action-suppressrevision": "ì\9d´ ì\88¨ê²¨ì§\84 í\8c\90ì\9d\84 ê²\80í\86 í\95\98ê³  ë³µêµ¬í\95\98기",
+       "action-suppressrevision": "숨겨진 판을 검토하고 복구하기",
        "action-suppressionlog": "비공개 기록 보기",
        "action-block": "이 사용자가 편집하지 못하도록 차단",
        "action-protect": "이 문서의 보호 설정을 바꾸기",
        "recentchanges-legend-newpage": "{{int:recentchanges-label-newpage}} ([[Special:NewPages|새 문서 목록]]도 보세요)",
        "recentchanges-legend-plusminus": "(<em>±123</em>)",
        "recentchanges-submit": "보기",
+       "rcfilters-activefilters": "사용 중인 필터",
+       "rcfilters-search-placeholder": "필터 최근 바뀜 (찾아보거나 입력을 시작하십시오)",
+       "rcfilters-invalid-filter": "유효하지 않은 필터",
+       "rcfilters-filterlist-title": "필터",
+       "rcfilters-filterlist-noresults": "필터를 찾을 수 없습니다",
+       "rcfilters-filter-editsbyself-label": "자신의 편집",
+       "rcfilters-filter-editsbyself-description": "당신의 편집.",
+       "rcfilters-filter-editsbyother-label": "다른 사용자의 편집",
+       "rcfilters-filter-editsbyother-description": "다른 사용자에 의한 편집. (당신의 편집이 아님)",
+       "rcfilters-filtergroup-userExpLevel": "사용자 경험 수준",
+       "rcfilters-filter-userExpLevel-newcomer-label": "신규 사용자",
+       "rcfilters-filter-userExpLevel-newcomer-description": "신규 편집자: 10개 미만의 편집 및 4일 미만의 활동.",
+       "rcfilters-filter-userExpLevel-learner-label": "학습자",
+       "rcfilters-filter-userExpLevel-learner-description": "'신규 사용자' 보다 활동일 및 편집 수가 더 많지만 '능숙한 사용자' 보다는 적습니다.",
+       "rcfilters-filter-userExpLevel-experienced-label": "능숙한 사용자",
+       "rcfilters-filter-userExpLevel-experienced-description": "30일 이상의 활동 및 500개 이상의 편집.",
        "rcnotefrom": "아래는 <strong>$3, $4</strong>부터 시작하는 {{PLURAL:$5|바뀜이 있습니다}}. (최대 <strong>$1</strong>개가 표시됨)",
        "rclistfrom": "$3 $2부터 시작하는 새로 바뀐 문서 보기",
        "rcshowhideminor": "사소한 편집 $1",
        "apisandbox-sending-request": "API 요청을 보내는 중...",
        "apisandbox-loading-results": "API 결과를 받는 중...",
        "apisandbox-results-error": "API 질의 응답을 불러오는 도중 오류 발생: $1.",
+       "apisandbox-request-params-json": "JSON 변수:",
        "apisandbox-request-url-label": "요청 URL:",
        "apisandbox-request-time": "요청 처리 시간: {{PLURAL:$1|$1 ms}}",
        "apisandbox-results-fixtoken": "토큰 수정 후 다시 제출",
        "proxyblockreason": "당신의 IP 주소는 공개 프록시로 밝혀져 자동으로 차단됩니다.\n만약 인터넷 사용에 문제가 있다면 인터넷 서비스 공급자나 기술 지원팀에게 문의해주세요.",
        "sorbsreason": "당신의 IP 주소는 {{SITENAME}}에서 사용하는 DNSBL 공개 프록시 목록에 들어 있습니다.",
        "sorbs_create_account_reason": "당신의 IP 주소는 {{SITENAME}}에서 사용하는 DNSBL 공개 프록시 목록에 들어 있습니다.\n계정을 만들 수 없습니다.",
+       "softblockrangesreason": "익명 기여가 당신의 IP 주소($1)에서 허용되지 않습니다. 로그인해 주십시오.",
        "xffblockreason": "X-Forwarded-For 헤더에 현재 사용하고 있는 프록시 서버 중 당신이나 해당 IP 주소가 차단되었습니다. 차단 이유는 다음과 같습니다: $1",
        "cant-see-hidden-user": "차단하려 하는 사용자는 이미 차단되었고 숨김 처리되었습니다.\n사용자 숨기기 권한을 갖고 있지 않기 때문에, 이 사용자의 차단 기록을 보거나 차단 설정을 바꿀 수 없습니다.",
        "ipbblocked": "자신이 차단되어 있기 때문에 다른 사용자를 차단하거나 차단을 해제할 수 없습니다.",
        "cant-move-to-user-page": "문서를 사용자 문서로 이동할 권한이 없습니다 (하위 문서는 예외).",
        "cant-move-category-page": "분류 문서를 이동할 권한이 없습니다.",
        "cant-move-to-category-page": "문서를 분류 문서로 이동할 권한이 없습니다.",
+       "cant-move-subpages": "하위 문서를 이동할 권한이 없습니다.",
+       "namespace-nosubpages": "\"$1\" 이름공간은 하위 문서를 허용하지 않습니다.",
        "newtitle": "새 제목:",
        "move-watch": "원래 문서와 대상 문서를 주시하기",
        "movepagebtn": "문서 이동",
        "htmlform-date-placeholder": "YYYY-MM-DD",
        "htmlform-time-placeholder": "HH:MM:SS",
        "htmlform-datetime-placeholder": "YYYY-MM-DD HH:MM:SS",
+       "htmlform-date-invalid": "지정한 값은 인식할 수 있는 날짜가 아닙니다. YYYY-MM-DD 형식을 사용하세요.",
+       "htmlform-time-invalid": "지정한 값은 인식할 수 있는 시간이 아닙니다. HH:MM:SS 형식을 사용하세요.",
+       "htmlform-datetime-invalid": "지정한 값은 인식할 수 있는 날짜 및 시간이 아닙니다. YYYY-MM-DD HH:MM:SS 형식을 사용하세요.",
        "htmlform-title-badnamespace": "[[:$1]] 문서는 \"{{ns:$2}}\" 이름공간에 없습니다.",
        "htmlform-title-not-creatable": "\"$1\"은 만들 수 없는 문서 제목입니다.",
        "htmlform-title-not-exists": "$1 문서는 존재하지 않습니다.",
        "api-error-missingresult": "내부 오류: 파일의 복제가 성공했는지 판단할 수 없습니다.",
        "api-error-mustbeloggedin": "파일을 올리려면 로그인해야 합니다.",
        "api-error-mustbeposted": "내부 오류: HTTP POST에 요청이 필요합니다.",
-       "api-error-noimageinfo": "파일 올리기는 성공했지만 서버가 파일에 대해 어떠한 정보도 주지 않았습니다.",
+       "api-error-noimageinfo": "업로드는 성공했지만 서버가 파일에 대해 어떠한 정보도 제공하지 않았습니다.",
        "api-error-nomodule": "내부 오류: 올리기 모듈이 설정되지 않았습니다.",
        "api-error-ok-but-empty": "내부 오류: 서버에서 응답이 없습니다.",
        "api-error-overwrite": "이미 있는 파일을 덮어쓸 수 없습니다.",
        "api-error-stashnotloggedin": "파일을 업로드하기 위해 로그인이 필요합니다.",
        "api-error-stashwrongowner": "저장된 임시 저장소에 존재하는 파일에 접근할 권한이 없습니다.",
        "api-error-stashnosuchfilekey": "미공개 위치에 접근을 시도한 파일 키는 존재하지 않습니다.",
-       "api-error-timeout": "ì\84\9cë²\84ê°\80 ì \9c ì\8b\9cê°\84 ë\82´ì\97\90 ì\9d\91ë\8bµí\95\98ì§\80 ì\95\8aì\95\98ì\8aµë\8b\88ë\8b¤.",
+       "api-error-timeout": "ì\84\9cë²\84ê°\80 ì\98\88측ë\90\9c ì\8b\9cê°\84 ë\82´ì\97\90 ì\9d\91ë\8bµí\95\98ì§\80 ì\95\8aì\95\98ì\8aµë\8b\88ë\8b¤.",
        "api-error-unclassified": "알 수 없는 오류가 발생했습니다.",
        "api-error-unknown-code": "알 수 없는 오류: \"$1\"",
        "api-error-unknown-error": "내부 오류: 파일을 올리려 하는 도중에 무엇인가가 잘못되었습니다.",
-       "api-error-unknown-warning": "알 수 없는 경고: \"$1\"",
+       "api-error-unknown-warning": "알 수 없는 경고: \"$1\".",
        "api-error-unknownerror": "알 수 없는 오류: \"$1\"",
        "api-error-uploaddisabled": "이 위키에서 파일 올리기가 비활성화되어 있습니다.",
        "api-error-verification-error": "파일이 손상되었거나 잘못된 확장자를 사용하고 있습니다.",
        "pagelang-language": "언어",
        "pagelang-use-default": "기본 언어 사용",
        "pagelang-select-lang": "언어 선택",
+       "pagelang-reason": "이유",
        "pagelang-submit": "제출",
+       "pagelang-nonexistent-page": "$1 문서가 존재하지 않습니다.",
+       "pagelang-unchanged-language": "$1 문서는 이미 $2 언어로 설정되어 있습니다.",
+       "pagelang-unchanged-language-default": "$1 문서는 이미 위키의 기본 콘텐츠 언어로 설정되어 있습니다.",
+       "pagelang-db-failed": "데이터베이스가 문서 언어 변경에 실패했습니다.",
        "right-pagelang": "문서 언어 바꾸기",
        "action-pagelang": "문서 언어 바꾸기",
        "log-name-pagelang": "언어 바꾸기 기록",
        "sessionprovider-nocookies": "브라우저의 쿠키 기능이 꺼져 있는지 확인하십시오. 쿠키 기능을 켠 다음 다시 시작해야 합니다.",
        "randomrootpage": "임의 루트 페이지",
        "log-action-filter-block": "차단의 유형:",
-       "log-action-filter-contentmodel": "콘텐츠 모델 수정 분류:",
+       "log-action-filter-contentmodel": "콘텐츠 모델 변경 분류:",
        "log-action-filter-delete": "삭제 종류:",
        "log-action-filter-import": "가져오기 종류:",
        "log-action-filter-managetags": "태그 관리 동작 종류:",
        "log-action-filter-block-reblock": "차단 변경",
        "log-action-filter-block-unblock": "차단 해제",
        "log-action-filter-contentmodel-change": "콘텐츠 모델 변경",
-       "log-action-filter-contentmodel-new": "비표준 콘텐츠 모델 문서 생성",
+       "log-action-filter-contentmodel-new": "기본이 아닌 콘텐츠 모델 문서 생성",
        "log-action-filter-delete-delete": "문서 삭제",
+       "log-action-filter-delete-delete_redir": "넘겨주기 덮어쓰기",
        "log-action-filter-delete-restore": "문서 복구",
        "log-action-filter-delete-event": "로그 삭제",
        "log-action-filter-delete-revision": "판 삭제",
index d4b7d83..38edc17 100644 (file)
@@ -47,7 +47,7 @@
        "tog-enotifrevealaddr": "Navnîşana enameya min di agahdariyên enameyan de nîşan bide",
        "tog-shownumberswatching": "Hejmara bikarhênerên dişopînin nîşan bide",
        "tog-oldsig": "Îmzeya heye:",
-       "tog-fancysig": "Di îmzeyê de girêdana otomatîk a bikarhêner betal bike",
+       "tog-fancysig": "Îmzeyê wek wîkîtekstê nîşan bide (bê girêdana otomatîk)",
        "tog-uselivepreview": "Pêşdîtina \"zindî\" bi kar bîne",
        "tog-forceeditsummary": "Hinga kurteyeke vala hate tomarkirin min agahdar bike",
        "tog-watchlisthideown": "Guherandinên min ji lîsteya şopandinê veşêre",
        "previewnote": "'''Ji bîr neke ku ev tenê pêşdîtinek e.'''\nGuhertinên te hê nehatine tomarkirin!",
        "continue-editing": "Here qada sazandinê",
        "editing": "$1 tê guherandin",
-       "creating": "$1 tê çêkirin",
+       "creating": "\"$1\" tê çêkirin",
        "editingsection": "Tê guherandin: $1 (beş)",
        "editingcomment": "$1 (beşek nû) tê guherandin.",
        "editconflict": "Têkçûna guherandinan: $1",
        "unwatchthispage": "Êdî neşopîne",
        "notanarticle": "Ne gotar e",
        "watchlist-details": "{{PLURAL:$1|Rûpeleka|$1 rûpel}} li ser lîsteya te ya şopandinê, rûpelên gotûbêjê nayên jimartin.",
-       "wlheader-enotif": "Agahdariya E-nameyê pêk tê.",
+       "wlheader-enotif": "Agahdariya e-nameyan hate çalakkirin",
        "wlheader-showupdated": "Ev rûpela hatî guhertin dema te lê meyzand bi '''nivîsa stûr''' tê xuyakirin.",
        "wlnote": "Niha {{PLURAL:$1|xeyrandinê|'''$1''' xeyrandinên}} dawî yê {{PLURAL:$2|seetê|'''$2''' seetên}} dawî {{PLURAL:$1|tê|tên}} dîtin.",
        "wlshowlast": "Guhertinên berî $1 saetan, $2 rojan, ya  nîşan bide",
        "feedback-subject": "Mijar:",
        "feedback-submit": "Tomar bike",
        "feedback-thanks-title": "Spas!",
-       "searchsuggest-search": "Lêgerîn",
+       "searchsuggest-search": "Li ser {{SITENAME}} bigere",
        "searchsuggest-containing": "dihundirîne...",
        "api-error-filename-tooshort": "Navê dosyeyê pir kurt e.",
        "api-error-unclassified": "Çewtiyeke nenas pêk hat.",
index 5fe5262..6d436f3 100644 (file)
        "recentchanges-legend-newpage": "{{int:recentchanges-label-newpage}} (kuckt och [[Special:NewPages|Lëscht vun den neie Säiten]])",
        "recentchanges-legend-plusminus": "''(±123)''",
        "recentchanges-submit": "Weisen",
+       "rcfilters-activefilters": "Aktiv Filteren",
+       "rcfilters-invalid-filter": "Net valabele Filter",
+       "rcfilters-filterlist-title": "Filteren",
+       "rcfilters-filterlist-noresults": "Keng Filtere fonnt",
+       "rcfilters-filter-editsbyself-label": "Är eegen Ännerungen",
+       "rcfilters-filter-editsbyself-description": "Ännerunge vun Iech.",
+       "rcfilters-filter-editsbyother-label": "Ännerunge vun Aneren",
+       "rcfilters-filter-editsbyother-description": "Ännerunge vun anere Benotzer (net vun Iech).",
+       "rcfilters-filtergroup-userExpLevel": "Niveau vun der Erfahrung vum Benotzer",
+       "rcfilters-filter-userExpLevel-newcomer-label": "Neier",
+       "rcfilters-filter-userExpLevel-newcomer-description": "Ganz nei Auteuren: manner wéi 10 Ännerungen a manner wéi 4 Deeg Aktivitéit.",
+       "rcfilters-filter-userExpLevel-learner-description": "Aktivitéit vu méi Deeg a méi Ännerunge wéi 'Nei Benotzer' awer manner wéi 'Erfuere Benotzer'.",
+       "rcfilters-filter-userExpLevel-experienced-label": "Erfuere Benotzer.",
+       "rcfilters-filter-userExpLevel-experienced-description": "Méi wéi 30 Deeg Aktivitéit a méi wéi 500 Ännerungen.",
        "rcnotefrom": "Hei drënner {{PLURAL:$5|gëtt d'Ännerung|ginn d'Ännerungen}} zanter <strong>$3, $4</strong> (maximal <strong>$1</strong> Ännerunge gi gewisen).",
        "rclistfrom": "Nei Ännerunge vum $3 $2 u weisen",
        "rcshowhideminor": "Kleng Ännerunge $1",
        "changecontentmodel-nodirectediting": "Den Inhaltsmodell $1 ënnerstëtzt keng direkt Ännerungen",
        "changecontentmodel-emptymodels-title": "Keng Modeller fir Inhalter disponibel",
        "changecontentmodel-emptymodels-text": "Den Inhalt vu(n) [[:$1]] kann net op een aneren Typ ëmgewandelt ginn.",
-       "log-description-contentmodel": "Evenementer a Relatioun mat den Inhaltsmodeller vun enger Säit",
+       "log-description-contentmodel": "OP dëser Säit stinn Ännerunge vum Inhaltsmodell vu Säiten a Säiten déi mat engem anere Säitmodell wéi dem Standard ugeluecht goufen.",
        "logentry-contentmodel-change-revertlink": "zrécksetzen",
        "logentry-contentmodel-change-revert": "zrécksetzen",
        "protectlogpage": "Protektiounslogbuch",
        "pagelang-language": "Sprooch",
        "pagelang-use-default": "Standard-Sprooch benotzen",
        "pagelang-select-lang": "Sprooch eraussichen",
+       "pagelang-reason": "Grond",
        "pagelang-submit": "Späicheren",
+       "pagelang-nonexistent-page": "D'Säit $1 gëtt et net.",
+       "pagelang-unchanged-language": "D'Säit $1 ass schonn op d'Sprooch $2 gesat.",
+       "pagelang-db-failed": "D'Datebank konnt d'Sprooch vun der Säit net änneren.",
        "right-pagelang": "Sprooch vun der Säit änneren",
        "action-pagelang": "d'Sprooch vun der Säit änneren",
        "log-name-pagelang": "Log vum Ännere vun der Sprooch",
index a6faaf2..97a2fd2 100644 (file)
        "faq": "ຄຳຖາມທີ່ພົບເລື້ອຍໆ",
        "faqpage": "Project:ຄຳຖາມທີ່ພົບເລື້ອຍໆ",
        "actions": "ການກະທຳ",
-       "namespaces": "à»\80àº\99ມສະà»\80àº\9bດ",
+       "namespaces": "àº\8aືà»\88àº\82ອàº\9aà»\80àº\82ດ",
        "variants": "ຄວາມແຕກຕ່າງ",
        "navigation-heading": "ລາຍການການນຳທາງ",
        "errorpagetitle": "ຂໍ້ຜິດພາດ",
        "nosuchspecialpage": "ບໍ່ມີໝ້າພິເສດດັ່ງກ່າວ",
        "error": "ຂໍ້ຜິດພາດ",
        "databaseerror": "ມີຂໍ້ຜິດພາດກ່ຽວກັບຖານຂໍ້ມູນ",
+       "databaseerror-error": "ຂໍ້ຜິດພາດ: $1",
        "laggedslavemode": "<strong>ຄຳເຕືອນ:</strong> ໜ້ານີ້ອາດຈະບໍ່ລວມຂໍ້ມູນລ້າສຸດ.",
        "readonly": "ຖານຂໍ້ມູນຖືກລັອກ",
        "enterlockreason": "ກະລຸນາຂຽນເຫດຜົນໃນການລັອກ, ລວມທັງປະມານເວລາທີ່ຈະປົດລັອກ",
        "directoryreadonlyerror": "ໄດເຣກທໍຣີ \"$1\" ສາມາດອ່ານໄດ້ເທົ່ານັ້ນ.",
        "directorynotreadableerror": "ໄດເຣກທໍຣີ \"$1\" ບໍ່ສາມາດອ່ານໄດ້.",
        "filenotfound": "ບໍ່ພົບໄຟລ໌ \"$1\".",
+       "formerror": "ຂໍ້ຜິດພາດ: ບໍ່ສາມາດສົ່ງແບບຟອມໄດ້.",
        "badarticleerror": "ບໍ່ສາມາດດຳເນີນການນີ້ຢູ່ເທິງໜ້ານີ້ໄດ້.",
        "cannotdelete": "ບໍ່ສາມາດລຶບໜ້າຫຼືໄຟລ໌ \"$1\" ໄດ້.\nມັນອາດຈະຖືກລຶບໂດຍໃຜຜູ້ໜຶ່ງແລ້ວ.",
        "cannotdelete-title": "ບໍ່ສາມາດລຶບໜ້າ \"$1\" ໄດ້",
        "myprivateinfoprotected": "ທ່ານບໍ່ໄດ້ຮັບອະນຸຍາດໃຫ້ແກ້ໄຂໜ້າຂໍ້ມູນສ່ວນບຸກຄົນຂອງທ່ານ.",
        "mypreferencesprotected": "ທ່ານບໍ່ໄດ້ຮັບອະນຸຍາດໃຫ້ແກ້ໄຂການຕັ້ງຄ່າຂອງທ່ານ.",
        "ns-specialprotected": "ບໍ່ສາມາດແກ້ໄຂໜ້າພິເສດໄດ້.",
+       "invalidtitle-knownnamespace": "ຊື່ເລື່ອງທີ່ມີຂອບເຂດຊື່ \"$2\" ແລະຂໍ້ຄວາມ \"$3\" ບໍ່ຖືກຕ້ອງ",
+       "invalidtitle-unknownnamespace": "ຊື່ເລື່ອງທີ່ມີຂອບເຂດຊື່ໝາຍເລກ $1 ແລະຂໍ້ຄວາມ \"$2\"",
        "exception-nologin": "ບໍ່ໄດ້ເຂົ້າສູ່ລະບົບ",
        "exception-nologin-text": "ກະລຸນາເຂົ້າສູ່ລະບົບເພື່ອໃຫ້ສາມາດເຂົ້າເບິ່ງ ຫຼື ດຳເນີນການໃດໆກັບໜ້ານີ້ໄດ້.",
        "exception-nologin-text-manual": "ກະລຸນາ $1 ເພື່ອໃຫ້ສາມາດເຂົ້າເບິ່ງ ຫຼື ດຳເນີນການໃດໆກັບໜ້ານີ້ໄດ້.",
        "lineno": "ແຖວ $1:",
        "compareselectedversions": "ສົມທຽບ ລະຫວ່າງ ສະບັບເລືອກ",
        "editundo": "ກັບຄືນ",
+       "searchresults": "ຜົນການຄົ້ນຫາ",
+       "searchresults-title": "ຜົນການຄົ້ນຫາສຳລັບ \"$1\"",
        "prevn": "{{PLURAL:$1|$1}} ກ່ອນໜ້າ",
        "nextn": "{{PLURAL:$1|$1}} ຕໍ່ໄປ",
+       "shown-title": "ສະແດງ{{PLURAL:$1|ຜົນທີ່ໄດ້ຮັບ}} $1 ລາຍການຕໍ່ໜຶ່ງໜ້າ",
        "viewprevnext": "ເບິ່ງ ($1 {{int:pipe-separator}} $2) ($3).",
        "search-result-size": "$1 ({{PLURAL:$2|1 ຄຳ|$2 ຄຳ}})",
        "search-redirect": "(ປ່ຽນເສັ້ນທາງມາຈາກ $1)",
        "filehist-dimensions": "ມິຕິ",
        "filehist-filesize": "ຂະໜາດໄຟລ໌",
        "filehist-comment": "ຄຳເຫັນ",
-       "imagelinks": "ລິà»\89àº\87àº\84໌",
-       "linkstoimage": "ລິ້ງຄ໌ຕໍ່ໄປນີ້ເຊື່ອມຕໍ່ຫາໄຟລ໌:",
+       "imagelinks": "àº\81າàº\99à»\83àº\8aà»\89à»\84àº\9fລ໌",
+       "linkstoimage": "{{PLURAL:$1|ໜ້າຕໍ່ໄປນີ້ເຊື່ອມໂຍງ|$1 ໜ້າຕໍ່ໄປນີ້ເຊື່ອມໂຍງ}}ຫາໄຟລ໌ນີ້:",
        "nolinkstoimage": "ບໍ່ມີໜ້າໃດ ລິ້ງຄ໌ ຫາ ໄຟລ໌ນີ້.",
        "sharedupload": "ໄຟລ໌ນີ້ແມ່ນການອັບໂຫຼດຣ່ວມ ແລະ ອາດຖືກໃຊ້ໂດຍໂຄງການອື່ນໆ.",
        "listredirects": "ລາຍການການໂອນໜ້າ",
        "undeletepagetext": "ໜ້າຕ່ອໄປນີ້ຖຶກລຶບໄປແຕ່ຍັງຄົງຢູ່ໃນກຸທີ່ສາມາດຮຽກຄືນໄດ້ (ກຸຂໍ້ມູນອາດຖຶກລຶບເປັນລະຍະ)",
        "cannotundelete": "ບໍ່ສາມາດ ກັບຄືນ ຫາສະບັບກ່ອນການລຶບ; ບາງຄົນອາດເຮັດກ່ອນແລ້ວ.",
        "undelete-search-submit": "ຊອກຫາ",
-       "namespace": "àº\82ອàº\9aà»\80àº\82àº\94àº\8aືà»\88:",
+       "namespace": "àº\8aືà»\88àº\82ອàº\9aà»\80àº\82àº\94:",
        "blanknamespace": "(ຫຼັກ)",
        "contributions": "ການປະກອບສ່ວນ",
        "mycontris": "ປະກອບສ່ວນ",
        "tooltip-pt-createaccount": "ນີ້ບໍ່ແມ່ນການບັງຄັບ. ແຕ່ຢ່າງໃດກໍຕາມ, ທ່ານຄວນທີ່ຈະສ້າງບັນຊີແລະເຂົ້າສູ່ລະບົບ.",
        "tooltip-ca-talk": "ສົນທະນາກ່ຽວກັບເນື້ອໃນຂອງໜ້າ",
        "tooltip-ca-edit": "ແກ້ໄຂໜ້ານີ້",
-       "tooltip-ca-addsection": "à»\80àº\9eີà»\88ມ àº\84ຳà»\80ຫັàº\99 à»\83ສà»\88 àº\81າàº\99ສົàº\99àº\97ະàº\99າàº\99ີà»\89.",
+       "tooltip-ca-addsection": "à»\80ລີà»\88ມàº\9eາàº\81à»\83à»\9dà»\88",
        "tooltip-ca-viewsource": "ໜ້ານີ້ຖືກປົກປ້ອງ. ທ່ານສາມາດເບິ່ງຊອສ.",
        "tooltip-ca-history": "ລຸ້ນແກ້ໄຂເກົ່າຂອງໜ້ານີ້",
        "tooltip-ca-protect": "ປົກປ້ອງໜ້ານີ້",
        "tooltip-search": "ຄົ້ນຫາ {{SITENAME}}",
        "tooltip-search-go": "ໄປຫາໜ້າທີ່ມີຊື່ທີ່ແນ່ນອນນີ້ຖ້າມັນມີຢູ່",
        "tooltip-search-fulltext": "ຄົ້ນຫາຂໍ້ຄວາມນີ້ໃນໜ້າ",
-       "tooltip-p-logo": "à»\80àº\82ົà»\89າສູà»\88ໜ້າຫຼັກ",
+       "tooltip-p-logo": "ຢà»\89ຽມàº\8aົມໜ້າຫຼັກ",
        "tooltip-n-mainpage": "ໄປເບິ່ງໜ້າຫຼັກ",
-       "tooltip-n-mainpage-description": "à»\80àº\82ົà»\89າສູà»\88ໜ້າຫຼັກ",
+       "tooltip-n-mainpage-description": "à»\80àº\82ົà»\89າຢà»\89ຽມàº\8aົມໜ້າຫຼັກ",
        "tooltip-n-portal": "ກ່ຽວກັບໂຄງການ, ສິ່ງທີ່ທ່ານເຮັດໄດ້, ແລະບ່ອນທີ່ສາມາດຫາສິ່ງຕ່າງໆໄດ້",
        "tooltip-n-currentevents": "ຄົ້ນຫາມູນກ່ຽວກັບກິດຈະກຳທີ່ກຳລັງດຳເນີນ",
        "tooltip-n-recentchanges": "ລາຍການການປ່ຽນແປງລ້າສຸດໃນວິກິ",
        "tooltip-t-permalink": "ລິງຄ໌ຖາວອນມາລຸ້ນແກ້ໄຂເກົ່າຂອງໜ້ານີ້",
        "tooltip-ca-nstab-main": "ເບິ່ງໜ້າເນື້ອໃນ",
        "tooltip-ca-nstab-user": "ເບິ່ງໜ້າຜູ້ໃຊ້",
+       "tooltip-ca-nstab-special": "ໜ້ານີ້ແມ່ນໜ້າພິເສດ, ແລະບໍ່ສາມາດແກ້ໄຂໄດ້",
        "tooltip-ca-nstab-project": "ເບິ່ງໜ້າໂຄງການ",
-       "tooltip-ca-nstab-image": "ເບິງໜ້າໄຟລ໌",
+       "tooltip-ca-nstab-image": "à»\80àº\9aິà»\88àº\87à»\9cà»\89າà»\84àº\9fລà»\8c",
        "tooltip-ca-nstab-template": "ເບິ່ງແມ່ແບບ",
        "tooltip-ca-nstab-category": "ເບິ່ງ ໜ້າໝວດ",
        "tooltip-minoredit": "ໝາຍວ່າແມ່ນການດັດແກ້ເລັກນ້ອຍ",
        "thumbsize": "ຂະໜາດສະແດງ:",
        "file-info-size": "$1 × $2  ປິກເຊລ, ຂະໜາດໄຟລ໌: $3, MIME type: $4",
        "file-nohires": "ບໍ່ມີຂະໜາດລະອຽດກວ່າ",
-       "show-big-image": "à»\80àº\95ັມàº\82ະà»\9cາàº\94",
+       "show-big-image": "à»\84àº\9fລà»\8càº\95ົà»\89àº\99ສະàº\9aັàº\9a",
        "show-big-image-size": "$1 × $2 ພິກເຊວ",
        "newimages": "ໄຟລ໌ຮູບໃໝ່",
        "newimages-summary": "ໜ້າພິເສດນີ້ສະແດງໄຟລ໌ທີ່ຖຶກອັປໂຫຼດຫຼ້າສຸດ",
index 53ca304..b74a4da 100644 (file)
@@ -42,6 +42,7 @@
        "tog-watchdefault": "Pievienot manis izmainītās lapas un failus uzraugāmo lapu sarakstam",
        "tog-watchmoves": "Pievienot manis pārvietotās lapas un failus uzraugāmo lapu sarakstam",
        "tog-watchdeletion": "Pievienot manis izdzēstās lapas un failus uzraugāmo lapu sarakstam",
+       "tog-watchuploads": "Pievienot manis augšuplādētos failus uzraugāmo lapu sarakstam",
        "tog-watchrollback": "Pievienot lapas, kurās es novērsu izmaiņas, manam uzraugāmo rakstu sarakstam",
        "tog-minordefault": "Atzīmēt visus labojumus jau sākotnēji par maznozīmīgiem",
        "tog-previewontop": "Parādīt priekšskatījumu virs labošanas lauka, nevis zem",
        "gender-unknown": "Es nevēlos norādīt",
        "gender-male": "Viņš labo viki lapas",
        "gender-female": "Viņa labo viki lapas",
-       "prefs-help-gender": "Dzimums nav obligāti jānorāda (šo parametru programmatūra izmanto, lai ģenerētu paziņojumus, kas atkarīgi no lietotāja dzimuma). Šī informācija būs publiski pieejama.",
+       "prefs-help-gender": "Dzimums nav obligāti jānorāda (šo parametru programmatūra izmanto, lai ģenerētu paziņojumus, kas atkarīgi no dalībnieka dzimuma). Šī informācija būs publiski pieejama.",
        "email": "E-pasts",
        "prefs-help-realname": "Īstais vārds nav obligāti jānorāda.\nJa tu izvēlies to norādīt, tas tiks izmantots, lai identificētu tavu darbu (ieguldījumu {{grammar:lokatīvs|{{SITENAME}}}}).",
        "prefs-help-email": "E-pasta adrese nav obligāta, bet ir nepieciešama nozaudētas paroles atjaunošanai.",
-       "prefs-help-email-others": "Tu arī vari izvēlēties, ka citi var sazināties ar tevi ar saites tavā lietotāja lapā vai lietotāja diskusijas lapā palīdzību. Citiem lietotājiem netiek atklāta tava e-pasta adrese, kad viņi sazinās ar tevi.",
+       "prefs-help-email-others": "Tu arī vari izvēlēties, ka citi var sazināties ar tevi ar saites tavā dalībnieka lapā vai dalībnieka diskusijas lapā palīdzību. Citiem dalībniekiem netiek atklāta tava e-pasta adrese, kad viņi sazinās ar tevi.",
        "prefs-help-email-required": "E-pasta adrese ir obligāta.",
        "prefs-info": "Pamatinformācija",
        "prefs-i18n": "Internacionalizācija",
        "wlshowlast": "Parādīt izmaiņas pēdējo $1 stundu laikā vai $2 dienu laikā, vai arī .",
        "watchlist-hide": "Slēpt",
        "watchlist-submit": "Rādīt",
+       "wlshowhideminor": "maznozīmīgos labojumus",
        "wlshowhidebots": "boti",
        "wlshowhideliu": "reģistrēti lietotāji",
        "wlshowhideanons": "anonīmi lietotāji",
index 63e207a..f982db1 100644 (file)
        "recentchanges-legend-newpage": "{{int:recentchanges-label-newpage}} (погл. и [[Special:NewPages|списокот на нови страници]])",
        "recentchanges-legend-plusminus": "(''±123'')",
        "recentchanges-submit": "Прикажи",
+       "rcfilters-activefilters": "Активни филтри",
+       "rcfilters-search-placeholder": "Филтрирај скорешни промени (прелстајте или почнете да пишувате)",
+       "rcfilters-invalid-filter": "Неважечки филтер",
+       "rcfilters-filterlist-title": "Филтри",
+       "rcfilters-filterlist-noresults": "Не пронајдов ниеден филтер",
+       "rcfilters-filtergroup-authorship": "Уреди авторство",
+       "rcfilters-filter-editsbyself-label": "Ваши сопствени уредувања",
+       "rcfilters-filter-editsbyself-description": "Ваши уредувања.",
+       "rcfilters-filter-editsbyother-label": "Туѓи уредувања",
+       "rcfilters-filter-editsbyother-description": "Уредувања направени од други корисници (не од вас).",
+       "rcfilters-filtergroup-userExpLevel": "Корисничка искусност",
+       "rcfilters-filter-userExpLevel-newcomer-label": "Новодојденци",
+       "rcfilters-filter-userExpLevel-newcomer-description": "Многу нови уредници: помалку од 10 уредувања и 4 дена активност.",
+       "rcfilters-filter-userExpLevel-learner-label": "Ученици",
+       "rcfilters-filter-userExpLevel-learner-description": "Повеќе денови активност од новодојденците, но помалку од искусните корисници.",
+       "rcfilters-filter-userExpLevel-experienced-label": "Искусни корисници",
+       "rcfilters-filter-userExpLevel-experienced-description": "Повеќе од 30 дена активност и 500 уредувања.",
        "rcnotefrom": "Подолу {{PLURAL:$5|е прикажана промената|се прикажани промените}} почнувајќи од <strong>$3, $4</strong>  (се прикажуваат до <b>$1</b>).",
        "rclistfrom": "Прикажи нови промени почнувајќи од $3 $2",
        "rcshowhideminor": "$1 ситни промени",
        "apisandbox-sending-request": "Испраќам барање до извршникот...",
        "apisandbox-loading-results": "Добивам исход од извршникот...",
        "apisandbox-results-error": "Се појави грешка при вчитувањето на одговорот од барањето до извршникот: $1.",
+       "apisandbox-request-params-json": "JSON-параметри:",
        "apisandbox-request-url-label": "URL на барањето:",
        "apisandbox-request-time": "Време за барањето: {{PLURAL:$1|$1 милисекунда|$1 милисекунди}}",
        "apisandbox-results-fixtoken": "Исправи ја шифрата и поднеси одново",
        "sorbs": "DNSBL",
        "sorbsreason": "Вашата IP-адреса е запишана како отворен застапник (proxy) во DNSBL кој го користи {{SITENAME}}..",
        "sorbs_create_account_reason": "Вашата IP-адреса е наведена како отворен застапникот (proxy) во DNSBL користена од {{SITENAME}}.\nНе можете да создадете корисничка сметка.",
+       "softblockrangesreason": "Анонимните придонеси не се дозволени од вашата IP-адреса ($1). Најавете се.",
        "xffblockreason": "Блокирана е IP-адреса присутна во заглавието X-Forwarded-For, која е ваша или на застапничкиот опслужувач што го користите. Наведеното образложение гласи: $1",
        "cant-see-hidden-user": "Корисникот кој се обидувате да го блокирате е веќе блокиран и сокриен. Бидејќи вие немате права за сокривање на корисник, не можете да ги видите или уредувате корисничките блокирања.",
        "ipbblocked": "Не можете да блокирате или одблокирате други корисници бидејќи и самите сте блокирани",
        "pagelang-language": "Јазик",
        "pagelang-use-default": "Користи стандарден јазик",
        "pagelang-select-lang": "Одберете јазик",
+       "pagelang-reason": "Причина",
        "pagelang-submit": "Поднеси",
+       "pagelang-nonexistent-page": "Страницата $1 не постои.",
+       "pagelang-unchanged-language": "Страницата $1 е веќе наместена на јазикот $2.",
+       "pagelang-unchanged-language-default": "Страницата $1 е веќе наместена на матичниот содржински јазик на викито.",
+       "pagelang-db-failed": "Базата не успеа да го смени содржинскиот јазик.",
        "right-pagelang": "Менување јазик на страница",
        "action-pagelang": "менување јазик на страница",
        "log-name-pagelang": "Дневник на менување на јазикот",
index 1596eb6..1501d02 100644 (file)
        "listgrants-grant": "अनुदान",
        "listgrants-rights": "अधिकार",
        "trackingcategories": "मागोवा घेणारे वर्ग",
-       "trackingcategories-summary": "या à¤ªà¤¾à¤¨à¤¾à¤¤ à¤¤à¥\87 à¤°à¥\87à¤\96ापथनातà¥\80ल à¤µà¤°à¥\8dà¤\97(tracking categories) आहेत, जे, मिडियाविकि संचेतनाद्वारे स्वयंचलितरित्या वसविण्यात (तयार करण्यात) आले आहेत. त्यांची नावे, {{ns:8}} नामविश्वातील संबंधित प्रणाली संदेशात फेरफार करुन, बदलविता येतात.",
+       "trackingcategories-summary": "या à¤ªà¤¾à¤¨à¤¾à¤¤ à¤¤à¥\87 à¤®à¤¾à¤\97à¥\8bवा à¤\98à¥\87णारà¥\87 à¤µà¤°à¥\8dà¤\97 (tracking categories) आहेत, जे, मिडियाविकि संचेतनाद्वारे स्वयंचलितरित्या वसविण्यात (तयार करण्यात) आले आहेत. त्यांची नावे, {{ns:8}} नामविश्वातील संबंधित प्रणाली संदेशात फेरफार करुन, बदलविता येतात.",
        "trackingcategories-msg": "मागोवा घेणारा वर्ग",
        "trackingcategories-name": "संदेश नाम",
        "trackingcategories-desc": "वर्ग अंतर्भूत करण्याचे निकष",
+       "restricted-displaytitle-ignored-desc": "या पानात दुर्लक्षित <code><nowiki>{{DISPLAYTITLE}}</nowiki></code> आहे कारण ते पानाच्या मूळ शीर्षकासम नाही.",
+       "noindex-category-desc": "हे पान सांगकाम्यांद्वारे अनुक्रमित नाही कारण त्यात <code><nowiki>__NOINDEX__</nowiki></code> हा जादुई शब्द आहे व ते त्या नामविश्वात आहे, जेथे या खूणपताकेची परवानगी आहे.",
+       "index-category-desc": "या पानात <code><nowiki>__INDEX__</nowiki></code> ही खूणपताका आहे (व ते अश्या नामविश्वात आहे जेथे या खूणपताकेची परवानगी आहे), आणि म्हणून ही सांगकाम्यांद्वारे अनुक्रमित आहे, जेथे ती सामान्यपणे असावयास नको.",
+       "post-expand-template-inclusion-category-desc": "येथील सर्व साच्यांचा विस्तार केल्यावर, या पानाचा आकार <code>$wgMaxArticleSize</code> पेक्षा जास्त मोठा झाला आहे, म्हणून काही साचे विस्तारल्या गेले नाहीत.",
+       "broken-file-category-desc": "या पानात तुटलेला संचिका-दुवा आहे (तो दुवा, जो अस्तित्वात नसलेल्या संचिकेस जोडण्याचा प्रयत्न करतो).",
+       "hidden-category-category-desc": "या वर्गाच्या आशय मजकूरात <code><nowiki>__HIDDENCAT__</nowiki></code> ही खूणपताका आहे, जी त्या पानास, पानांसाठी   असलेल्या वर्गदुवेपेटीत दिसण्यापासून अविचलरित्या रोखते.",
        "trackingcategories-nodesc": "वर्णन उपलब्ध नाही.",
        "trackingcategories-disabled": "वर्ग अक्षम केल्या गेला आहे",
        "mailnologin": "पाठविण्याचा पत्ता नाही",
        "created": "तयार केले",
        "changed": "बदलले",
        "deletepage": "पान वगळा",
-       "confirm": "निश्चीत",
+       "confirm": "निश्चीत करा",
        "excontent": "मजकूर होता: '$1'",
        "excontentauthor": "मजकूर होता: \"$1\" आणि फक्त [[Special:Contributions/$2|$2]]  ([[User talk:$2|चर्चा]])यांचेच योगदान होते.",
        "exbeforeblank": "वगळण्यापूर्वीचा मजकूर पुढीलप्रमाणे: '$1'",
index 9eb9458..1d2f69a 100644 (file)
        "wantedpages": "အလိုရှိသော စာမျက်နှာများ",
        "wantedfiles": "အလိုရှိသော ဖိုင်များ",
        "wantedtemplates": "အလိုရှိသော တမ်းပလိတ်များ",
+       "mostlinked": "အများဆုံး လာရောက်ချိတ်ဆက်ထားသည့် စာမျက်နှာများ",
+       "mostlinkedcategories": "အများဆုံး လာရောက် ချိတ်ဆက်ထားသည့် ကဏ္ဍများ",
        "mostcategories": "ကဏ္ဍအများဆုံးပါသော စာမျက်နှာများ",
+       "mostimages": "အများဆုံး လာရောက်ချိတ်ဆက်ထားသည့် ဖိုင်များ",
+       "mostrevisions": "တည်းဖြတ်မှု အများဆုံး စာမျက်နှာများ",
        "prefixindex": "ရှေ့ဆုံးမှ prefix ပါသော စာမျက်နှာ အားလုံး",
        "prefixindex-submit": "ပြသရန်",
        "shortpages": "စာမျက်နှာတို",
        "longpages": "ရှည်လျားသောစာမျက်နှာများ",
-       "deadendpages": "လမ်းပိတ်နေသော (လင့်မရှိသော) စာမျက်နှာများ",
+       "deadendpages": "လမ်းဆုံးနေသော (လင့်ခ်မချိတ်ထားသော) စာမျက်နှာများ",
+       "deadendpagestext": "အောက်ပါ စာမျက်နှာများသည် {{SITENAME}} တွင် အခြား စာမျက်နှာများသို့ လင့်ခ်ချိတ်ဆက်ထားခြင်း မရှိပါ။",
        "protectedpages": "ကာကွယ်ထားသော စာမျက်နှာများ",
        "protectedpages-noredirect": "ပြန်ညွှန်းများအား ဝှက်ရန်",
        "protectedtitles": "ကာကွယ်ထားသော ခေါင်းစဉ်များ",
        "listgrouprights-removegroup-all": "အုပ်စုအားလုံးကို ဖယ်ရှားရန်",
        "listgrouprights-addgroup-self-all": "အုပ်စုအားလုံးကို မိမိ၏အကောင့်သို့ ပေါင်းထည့်ရန်",
        "listgrouprights-removegroup-self-all": "မိမိ၏အကောင့်မှ အုပ်စုအားလုံးကို ဖယ်ရှားရန်",
+       "trackingcategories": "နောက်ယောင်ခံ ကဏ္ဍများ",
        "mailnologin": "ပို့ရန်လိပ်စာ မရှိပါ",
        "emailuser": "ဤ​အ​သုံး​ပြု​သူ​အား​ အီး​မေး​ပို့​ပါ​",
        "emailuser-title-target": "{{GENDER:$1|အသုံးပြုသူ}}ကို အီးမေးပို့ရန်",
index f7acd4f..ec04d40 100644 (file)
        "recentchanges-legend-newpage": "{{int:recentchanges-label-newpage}} (se også [[Special:NewPages|liste over nye sider]])",
        "recentchanges-legend-plusminus": "«(±123)»",
        "recentchanges-submit": "Vis",
+       "rcfilters-activefilters": "Aktive filtre",
+       "rcfilters-search-placeholder": "Filtrer siste endringer (søk eller begyn å skrive)",
+       "rcfilters-invalid-filter": "Ugyldig filter",
+       "rcfilters-filterlist-title": "Filtre",
+       "rcfilters-filterlist-noresults": "Ingen filtre funnet",
+       "rcfilters-filtergroup-authorship": "Redigeringens forfatter",
+       "rcfilters-filter-editsbyself-label": "Dine egne redigeringer",
+       "rcfilters-filter-editsbyself-description": "Redigeringer gjort av deg.",
+       "rcfilters-filter-editsbyother-label": "Redigeringer av andre",
+       "rcfilters-filter-editsbyother-description": "Redigeringer som er gjort av andre brukere enn deg.",
+       "rcfilters-filtergroup-userExpLevel": "Brukererfaringsnivå",
+       "rcfilters-filter-userExpLevel-newcomer-label": "Nykommere",
+       "rcfilters-filter-userExpLevel-newcomer-description": "Veldig nye bidragsytere: Færre enn 10 redigeringer og 4 dagers aktivitet.",
+       "rcfilters-filter-userExpLevel-learner-label": "Nybegynnere",
+       "rcfilters-filter-userExpLevel-learner-description": "Flere dagers aktivitet enn «Nykommere», men mindre enn «Erfarne brukere».",
+       "rcfilters-filter-userExpLevel-experienced-label": "Erfarne brukere",
+       "rcfilters-filter-userExpLevel-experienced-description": "Mer enn 30 dagers aktivitet og 500 redigeringer.",
        "rcnotefrom": "Nedenfor er vist {{PLURAL:$5|endringen|endringene}} som er gjort siden <strong>$3, $4</strong> (frem til <strong>$1</strong>).",
        "rclistfrom": "Vis nye endringer fra og med $3 $2",
        "rcshowhideminor": "$1 mindre endringer",
        "apisandbox-sending-request": "Sender API-forespørsel...",
        "apisandbox-loading-results": "Mottar API-resultater...",
        "apisandbox-results-error": "En feil oppsto under lasting av API-spørringssvaret: $1.",
+       "apisandbox-request-params-json": "JSON-parametre:",
        "apisandbox-request-url-label": "Forespurt URL:",
        "apisandbox-request-time": "Forespørselstid: {{PLURAL:$1|$1 ms}}",
        "apisandbox-results-fixtoken": "Fiks nøkkelen og send på nytt",
        "proxyblockreason": "IP-adressen din ble blokkert fordi den er en åpen proxy. Kontakt internettleverandøren din eller teknisk støtte og informer dem om dette alvorlige sikkerhetsproblemet.",
        "sorbsreason": "IP-adressen din er listet som en åpen proxy i DNSBL-en brukt av {{SITENAME}}.",
        "sorbs_create_account_reason": "Din IP-adresse angis som en åpen proxy i DNSBL-en brukt av {{SITENAME}}. Du kan ikke opprette en konto",
+       "softblockrangesreason": "Anonyme bidrag tillates ikke fra din IP-adresse ($1). Vennligst logg inn.",
        "xffblockreason": "En IP-adresse som er tilstede i X-Forwarded-For-headeren, enten din eller en som tilhører en proxyserver du bruker, har blitt blokkert. Den opprinnelige blokkeringsgrunnen var: $1",
        "cant-see-hidden-user": "Brukeren du prøver å blokkere har allerede blitt blokkert og skjult. Ettersom du ikke har rett til å skjule brukere (hideuser), kan du ikke se eller endre brukerens blokkering.",
        "ipbblocked": "Du kan ikke blokkere eller avblokkere andre brukere, siden du selv er blokkert",
        "pagelang-language": "Språk",
        "pagelang-use-default": "Bruk standardspråk",
        "pagelang-select-lang": "Velg språk",
+       "pagelang-reason": "Årsak",
        "pagelang-submit": "Lagre",
+       "pagelang-nonexistent-page": "Siden «$1» eksisterer ikke.",
+       "pagelang-unchanged-language": "Siden «$1» er allerede satt til språket $2.",
+       "pagelang-unchanged-language-default": "Siden $1 er allerede satt til wikiens standard innholdsspråk.",
+       "pagelang-db-failed": "Databasen kunne ikke endre sidespråket.",
        "right-pagelang": "Endre sidespråk",
        "action-pagelang": "endre sidespråket",
        "log-name-pagelang": "Logg for språkendringer",
index e85c61d..f57b140 100644 (file)
        "recentchanges-legend-newpage": "{{int:recentchanges-label-newpage}} (zie ook de [[Special:NewPages|lijst met nieuwe pagina's]])",
        "recentchanges-legend-plusminus": "(''±123'')",
        "recentchanges-submit": "Weergeven",
+       "rcfilters-activefilters": "Actieve filters",
+       "rcfilters-search-placeholder": "Filter recente wijzigingen (blader of begin met intypen)",
+       "rcfilters-invalid-filter": "Ongeldig filter",
+       "rcfilters-filterlist-title": "Filters",
+       "rcfilters-filterlist-noresults": "Geen filters gevonden",
+       "rcfilters-filter-editsbyself-label": "Uw eigen bewerkingen",
+       "rcfilters-filter-editsbyself-description": "Bewerkingen door u.",
+       "rcfilters-filter-editsbyother-label": "Bewerkingen door anderen",
+       "rcfilters-filter-editsbyother-description": "Bewerkingen die gemaakt zijn door andere gebruikers (niet door uzelf.)",
+       "rcfilters-filtergroup-userExpLevel": "Gebruikerservarings niveau",
+       "rcfilters-filter-userExpLevel-newcomer-label": "Nieuwkomers",
+       "rcfilters-filter-userExpLevel-newcomer-description": "Zeer nieuwe bewerkers: minder dan 10 bewerkingen en 4 dagen van activiteit.",
+       "rcfilters-filter-userExpLevel-learner-label": "Leerlingen",
+       "rcfilters-filter-userExpLevel-learner-description": "Meer dagen van activiteit en bewerkingen dan 'Nieuwkomers', maar minder dan 'Ervaren gebruikers.'",
+       "rcfilters-filter-userExpLevel-experienced-label": "Ervaren gebruikers",
+       "rcfilters-filter-userExpLevel-experienced-description": "Meer dan 30 dagen van activiteit en 500 bewerkingen.",
        "rcnotefrom": "Wijzigingen sinds <strong>$3 om $4</strong> (maximaal <strong>$1</strong> {{PLURAL:$1|wijziging|wijzigingen}}).",
        "rclistfrom": "Wijzigingen bekijken vanaf $3 $2",
        "rcshowhideminor": "Kleine bewerkingen $1",
        "apisandbox-sending-request": "API-verzoek verzenden...",
        "apisandbox-loading-results": "API-resultaten ontvangen...",
        "apisandbox-results-error": "Er is een fout opgetreden tijdens het laden van het antwoord op het API-verzoek: $1.",
+       "apisandbox-request-params-json": "JSON parameters:",
        "apisandbox-request-url-label": "Verzoek-URL:",
        "apisandbox-request-time": "Doorlooptijd verzoek: {{PLURAL:$1|$1 ms}}",
        "apisandbox-results-fixtoken": "Token corrigeren en opnieuw verzenden",
        "changecontentmodel-emptymodels-title": "Geen inhoudsmodellen beschikbaar",
        "changecontentmodel-emptymodels-text": "De inhoud van [[:$1]] kan niet worden omgezet in een ander type.",
        "log-name-contentmodel": "Wijzigingenlogboek van inhoudsmodel",
-       "log-description-contentmodel": "Gebeurtenissen rond het inhoudsmodel van een pagina",
+       "log-description-contentmodel": "Deze pagina bevat wijzigingen rond het inhoudsmodel van pagina's en pagina's die aangemaakt zijn met een inhoudsmodel anders dan het standaardmodel.",
        "logentry-contentmodel-new": "$1 {{GENDER:$2|maakte}} de pagina $3 aan met behulp van een niet-standaard inhoudsmodel \"$5\"",
        "logentry-contentmodel-change": "$1 {{GENDER:$2|heeft}} het inhoudsmodel gewijzigd van pagina $3 van \"$4\" in \"$5\"",
        "logentry-contentmodel-change-revertlink": "terugdraaien",
        "proxyblockreason": "Uw IP-adres is geblokkeerd, omdat u gebruik maakt van een open proxyserver.\nNeem contact op met uw internetprovider of uw helpdesk en stel die op de hoogte van dit ernstige beveiligingsprobleem.",
        "sorbsreason": "Uw IP-adres staat bekend als open proxyserver in de DNS-blacklist die {{SITENAME}} gebruikt.",
        "sorbs_create_account_reason": "Uw IP-adres staat bekend als open proxyserver in de DNS-blacklist die {{SITENAME}} gebruikt.\nU kunt geen gebruiker registreren.",
+       "softblockrangesreason": "Anonieme bijdragen zijn niet toegestaan op basis van uw IP-adres ($1). Gelieve in te loggen.",
        "xffblockreason": "Een IP-adres dat u gebruikt is geblokkeerd. Dit staat de X-Forwarded-For van de header. De oorspronkelijke blokkadereden is: $1",
        "cant-see-hidden-user": "De gebruiker die u probeert te blokken is al geblokkeerd en verborgen.\nOmdat u het recht \"hideuser\" niet hebt, kunt u de blokkade van de gebruiker niet bekijken of bewerken.",
        "ipbblocked": "U kunt geen andere gebruikers (de)blokkeren, omdat u zelf geblokkeerd bent",
        "tag-filter": "[[Special:Tags|Labelfilter]]:",
        "tag-filter-submit": "Filteren",
        "tag-list-wrapper": "([[Special:Tags|Label{{PLURAL:$1||s}}]]: $2)",
+       "tag-mw-contentmodelchange": "inhoudsmodel wijzigen",
+       "tag-mw-contentmodelchange-description": "Bewerkingen die [https://www.mediawiki.org/wiki/Special:MyLanguage/Help:ChangeContentModel het  inhoudsmodel van een pagina wijzigen]",
        "tags-title": "Labels",
        "tags-intro": "Op deze pagina staan de labels waarmee de software iedere bewerking kan markeren, en hun betekenis.",
        "tags-tag": "Labelnaam",
        "pagelang-language": "Taal",
        "pagelang-use-default": "Standaard taal gebruiken",
        "pagelang-select-lang": "Taal selecteren",
+       "pagelang-reason": "Reden",
        "pagelang-submit": "Opslaan",
+       "pagelang-nonexistent-page": "De pagina $1 bestaat niet.",
+       "pagelang-unchanged-language": "De pagina $1 is al ingesteld op de taal $2.",
+       "pagelang-unchanged-language-default": "De pagina $1 is al ingesteld op de wiki's standaard inhoudstaal.",
+       "pagelang-db-failed": "De database kon de paginataal niet wijzigen.",
        "right-pagelang": "Paginataal wijzigen",
        "action-pagelang": "paginataal te wijzigen",
        "log-name-pagelang": "Logboek taalwijzigingen",
        "sessionprovider-nocookies": "Cookies kunnen uitgeschakeld zijn. Zorg ervoor dat u cookies hebt ingeschakeld en probeer het opnieuw.",
        "randomrootpage": "Willekeurige hoofdpagina",
        "log-action-filter-block": "Soort blokkade:",
+       "log-action-filter-contentmodel": "Soort inhoudsmodel wijziging:",
        "log-action-filter-delete": "Soort verwijdering:",
        "log-action-filter-import": "Type import:",
        "log-action-filter-managetags": "Type labelbeheerhandeling:",
        "log-action-filter-block-block": "Blokkade",
        "log-action-filter-block-reblock": "Aanpassing van blokkade",
        "log-action-filter-block-unblock": "Opheffing van blokkade",
+       "log-action-filter-contentmodel-change": "Wijziging van het inhoudsmodel",
+       "log-action-filter-contentmodel-new": "Pagina creatie met een niet-standaard inhoudsmodel",
        "log-action-filter-delete-delete": "Verwijderen van pagina",
        "log-action-filter-delete-delete_redir": "Overschrijven van doorverwijzingen",
        "log-action-filter-delete-restore": "Terugplaatsen van pagina",
index d2376a5..ef834e3 100644 (file)
        "lag-warn-high": "ଅଧିକ ଡାଟାବେସ ସର୍ଭର ପଛୁଆ ଅବସ୍ଥା ହେତୁ $1 {{PLURAL:$1|ସେକେଣ୍ଡ|ସେକେଣ୍ଡ}}ରୁ ନୂଆ ବଦଳସବୁ ଏହି ତାଲିକାରେ ଦେଖାଯିବ ନାହିଁ ।",
        "watchlistedit-normal-title": "ଦେଖଣାତାଲିକା ସମ୍ପାଦନା କରିବେ",
        "watchlistedit-normal-legend": "ଦେଖିଥିବା ପୃଷ୍ଠାଗୁଡିକରୁ ଶିରୋନାମା ହଟାଇବେ ।",
-       "watchlistedit-normal-explain": "à¬\86ପଣà¬\99à­\8dà¬\95ର à¬¦à­\87à¬\96ଣା à¬¤à¬¾à¬²à¬¿à¬\95ାର à¬¶à¬¿à¬°à­\8bନାମାà¬\97à­\81ଡିà¬\95 à¬¤à¬³à­\87 à¬¦à­\87à¬\96ା à¬¯à¬¾à¬\87à¬\9bି à¥¤\nଶିରà­\8bନାମା  ହଟାଇବାକୁ ଚାହୁଁଥିଲେ, ଏହାର ପାଖରେ ଥିବା ବାକ୍ସରେ ଟିକ ମାରନ୍ତୁ ଏବଂ \"{{int:Watchlistedit-normal-submit}}\"ରେ କ୍ଲିକ କରନ୍ତୁ ।\nଆପଣ [[Special:EditWatchlist/raw|edit the raw list]] ମଧ୍ୟ କରିପାରିବେ ।",
+       "watchlistedit-normal-explain": "à¬\86ପଣà¬\99à­\8dà¬\95ର à¬¦à­\87à¬\96ଣା à¬¤à¬¾à¬²à¬¿à¬\95ାର à¬¶à¬¿à¬°à­\8bନାମà¬\97à­\81ଡ଼ିà¬\95 à¬¤à¬³à­\87 à¬¦à­\87à¬\96ା à¬¯à¬¾à¬\87à¬\9bି à¥¤\nଶିରà­\8bନାମ ହଟାଇବାକୁ ଚାହୁଁଥିଲେ, ଏହାର ପାଖରେ ଥିବା ବାକ୍ସରେ ଟିକ ମାରନ୍ତୁ ଏବଂ \"{{int:Watchlistedit-normal-submit}}\"ରେ କ୍ଲିକ କରନ୍ତୁ ।\nଆପଣ [[Special:EditWatchlist/raw|edit the raw list]] ମଧ୍ୟ କରିପାରିବେ ।",
        "watchlistedit-normal-submit": "ଶିରୋନାମାଗୁଡିକୁ ଲିଭାଇବେ",
        "watchlistedit-normal-done": "{{PLURAL:$1|ଗୋଟିଏ ନାମ|$1 ଗୋଟି ନାମ}} ଆପଣଙ୍କ ଦେଖଣାତାଲିକାରୁ କାଢ଼ିଦିଆଗଲା:",
        "watchlistedit-raw-title": "ଫାଙ୍କା ଦେଖା ତାଲିକାଟିର ସମ୍ପାଦନା କରିବେ",
index e86a079..882038b 100644 (file)
        "recentchanges-legend-newpage": "{{int:recentchanges-label-newpage}} (zobacz też [[Special:NewPages|listę nowych stron]])",
        "recentchanges-legend-plusminus": "(''±123'')",
        "recentchanges-submit": "Pokaż",
+       "rcfilters-activefilters": "Aktywne filtry",
+       "rcfilters-filterlist-title": "Filtry",
+       "rcfilters-filterlist-noresults": "Nie znaleziono filtrów",
+       "rcfilters-filtergroup-userExpLevel": "Poziomu doświadczenia użytkownika",
+       "rcfilters-filter-userExpLevel-newcomer-label": "Początkujący",
+       "rcfilters-filter-userExpLevel-experienced-label": "Doświadczeni użytkownicy",
+       "rcfilters-filter-userExpLevel-experienced-description": "Ponad 30 dni aktywności i 500 edycji.",
        "rcnotefrom": "Poniżej {{PLURAL:$5|pokazano zmianę|pokazano zmiany}} {{PLURAL:$5|wykonaną|wykonane}} po <strong>$3, $4</strong> (nie więcej niż '''$1''' pozycji).",
        "rclistfrom": "Pokaż nowe zmiany od $3 $2",
        "rcshowhideminor": "$1 drobne edycje",
        "changecontentmodel-emptymodels-title": "Nie ma dostępnych modeli treści",
        "changecontentmodel-emptymodels-text": "Zawartość [[:$1]] nie może być przekształcona do żadnego typu.",
        "log-name-contentmodel": "Rejestr zmian modelu zawartości",
-       "log-description-contentmodel": "Wydarzenia związane z modelami zawartości stron",
+       "log-description-contentmodel": "Ta strona wymienia zmiany w modelu zawartości stron oraz tworzenie nowych stron z modelem zawartości innym niż domyślnie.",
        "logentry-contentmodel-new": "$1 {{GENDER:$2|utworzył|utworzyła}} stronę $3 o niebędącym domyślnym modelu zawartości \"$5\"",
        "logentry-contentmodel-change": "$1 {{GENDER:$2|zmienił|zmieniła|zmienił(a)}} model zawartości strony $3 z „$4” na „$5”",
        "logentry-contentmodel-change-revertlink": "Przywróć",
        "pagelang-language": "Język",
        "pagelang-use-default": "Użyj domyślnego języka",
        "pagelang-select-lang": "Wybierz język",
+       "pagelang-reason": "Powód",
        "pagelang-submit": "Wyślij",
+       "pagelang-nonexistent-page": "Strona $1 nie istnieje.",
        "right-pagelang": "Zmiana języka strony",
        "action-pagelang": "zmiany języka strony",
        "log-name-pagelang": "Rejestr zmian języka",
        "sessionprovider-nocookies": "Być może cookies są wyłączone. Upewnij się, że masz włączone cookies i zacznij od nowa.",
        "randomrootpage": "Losowa strona (bez podstron)",
        "log-action-filter-block": "Rodzaj blokady:",
-       "log-action-filter-contentmodel": "Typ modyfikacji modelu zawartości:",
+       "log-action-filter-contentmodel": "Typ zmiany modelu zawartości:",
        "log-action-filter-delete": "Rodzaj usunięcia:",
        "log-action-filter-import": "Typ importu:",
        "log-action-filter-managetags": "Typ działania zarządzania znacznikami:",
        "log-action-filter-block-reblock": "Zmiana blokady",
        "log-action-filter-block-unblock": "Odblokowanie",
        "log-action-filter-contentmodel-change": "Zmiana modelu zawartości",
-       "log-action-filter-contentmodel-new": "Utworzenie strony z niestandardowym modelem zawartości",
+       "log-action-filter-contentmodel-new": "Utworzenie strony z niedomyślnym modelem zawartości",
        "log-action-filter-delete-delete": "Usunięcie strony",
        "log-action-filter-delete-delete_redir": "Nadpisanie przekierowania",
        "log-action-filter-delete-restore": "Odtworzenie strony",
index c23e1c5..c8a8f90 100644 (file)
        "passwordreset-emaildisabled": "په دې ويکي باندې د برېښليک ځانتياوې ناچارنې شوي دي.",
        "passwordreset-username": "کارن-نوم:",
        "passwordreset-domain": "شپول:",
-       "passwordreset-capture": "د پايلې برېښليک کتل غواړې؟",
        "passwordreset-email": "برېښليک پته:",
        "passwordreset-emailtitle": "د {{SITENAME}} د گڼون څرگندنې",
        "passwordreset-emailelement": "کارن-نوم: \n$1\n\nلنډمهاله پټنوم: \n$2",
        "right-userrights-interwiki": "په نورو ويکي گانو د نورو کارنانو  کارن-رښتې سمول",
        "right-siteadmin": "توکبنسټ کولپول او پرانيستل",
        "right-sendemail": "نورو کارنانو ته برېښليک لېږل",
-       "right-passwordreset": "د پټنوم بياپرځايولو برېښليکونه کتل",
        "grant-group-email": "برېښليک لېږل",
        "grant-group-other": "بېلابېل فعاليتونه",
        "grant-blockusers": "په کارنانو بنديز لگول او بنديز ليرې کول",
        "recentchanges-legend-newpage": "{{int:recentchanges-label-newpage}} ([[Special:NewPages|د نويو مخونو لړليک]] هم وگورئ)",
        "recentchanges-legend-plusminus": "(<em>±123</em>)",
        "recentchanges-submit": "ښکاره کول",
+       "rcfilters-filterlist-title": "چاڼگران",
+       "rcfilters-filter-userExpLevel-newcomer-label": "نوي راغلي",
+       "rcfilters-filter-userExpLevel-learner-label": "زده کوونکي",
        "rcnotefrom": "دلته لاندې د <strong>$2</strong> څخه راپدېخوا پېښ شوي بدلونونه راغلي (تر <strong>$1</strong> پورې ښکاري).",
        "rclistfrom": "نوي بدلونونه چې له $3، $2 څخه پيلېږي ښکاره کول",
        "rcshowhideminor": "وړې سمونې $1",
index a873752..4ae85f9 100644 (file)
                        "Tark",
                        "O Andarilho",
                        "Bruno.S.Alves 270",
-                       "!Silent"
+                       "!Silent",
+                       "Joao Xavier"
                ]
        },
        "tog-underline": "Sublinhar links:",
        "rev-deleted-comment": "(resumo da edição suprimido)",
        "rev-deleted-user": "(nome de usuário(a) removido)",
        "rev-deleted-event": "(registros de detalhes eliminados)",
-       "rev-deleted-user-contribs": "[nome de usuário(a) ou endereço de IP eliminado – edição ocultada das contribuições]",
+       "rev-deleted-user-contribs": "[nome de usuário(a) ou endereço de IP ocultado no histórico – edição invisível nas contribuições públicas]",
        "rev-deleted-text-permission": "Esta revisão desta página foi '''eliminada'''.\nPodem existir mais detalhes no [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} registro de eliminações].",
        "rev-suppressed-text-permission": "A revisão desta página foi '''eliminada'''.\nVocê pode visualizá-la; podem existir mais detalhes no [{{fullurl:{{#Special:Log}}/suppress|page={{FULLPAGENAMEE}}}} registro de eliminação].",
        "rev-deleted-text-unhide": "Esta revisão desta página foi '''removida'''.\nPoderá haver detalhes no [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} registro de eliminação].\nVocê ainda pode [$1 ver esta revisão] se deseja prosseguir.",
        "recentchanges-legend-newpage": "{{int:recentchanges-label-newpage}} (veja também a [[Special:NewPages|lista de páginas novas]])",
        "recentchanges-legend-plusminus": "(''±123'')",
        "recentchanges-submit": "Exibir",
+       "rcfilters-activefilters": "Filtros ativos",
+       "rcfilters-filterlist-title": "Filtros",
+       "rcfilters-filterlist-noresults": "Nenhum filtro encontrado",
+       "rcfilters-filtergroup-authorship": "Editar autoria",
        "rcnotefrom": "Abaixo {{PLURAL:$5|é a mudança|são as mudanças}} desde <strong>$3, $4</strong> (up to <strong>$1</strong> shown).",
        "rclistfrom": "Mostrar as novas alterações a partir das $2 de $3",
        "rcshowhideminor": "$1 edições menores",
        "notvisiblerev": "Edição eliminada",
        "watchlist-details": "{{PLURAL:$1|$1 página|$1 páginas}} na sua lista de páginas vigiadas, excluindo as páginas de discussão.",
        "wlheader-enotif": "A notificação por email encontra-se ativada.",
-       "wlheader-showupdated": "Páginas modificadas desde a sua última visita são mostradas em '''negrito'''",
+       "wlheader-showupdated": "As páginas modificadas desde a sua última visita são mostradas em <strong>negrito</strong>.",
        "wlnote": "A seguir {{PLURAL:$1|está a última alteração ocorrida|estão as últimas <strong>$1</strong> alterações ocorridas}} {{PLURAL:$2|na última hora|nas últimas <strong>$2</strong> horas}} até $3, $4.",
        "wlshowlast": "Ver últimas $1 horas $2 dias",
        "watchlist-hide": "Ocultar",
        "proxyblockreason": "O seu endereço de IP foi bloqueado por ser um proxy público. Por favor contacte o seu fornecedor do serviço de Internet ou o apoio técnico e informe-os deste problema de segurança grave.",
        "sorbsreason": "O seu endereço IP encontra-se listado como proxy aberto pela DNSBL utilizada por {{SITENAME}}.",
        "sorbs_create_account_reason": "O seu endereço de IP encontra-se listado como proxy aberto na DNSBL utilizada por {{SITENAME}}. Você não pode criar uma conta",
+       "softblockrangesreason": "Contribuições anônimas não são permitidas a partir de seu endereço IP. Por favor, faça login.",
        "xffblockreason": "Um endereço IP presente no cabeçalho X-Forwarded-For, seu ou do servidor proxy que está usando, foi bloqueado. O motivo original do bloqueio foi: $1",
        "cant-see-hidden-user": "O usuário que você está tentando bloquear já está bloqueado ou oculto. Como você não possui privilégio de ocultar usuários, você não pode ver ou editar o bloqueio desse usuário.",
        "ipbblocked": "Não é possível que você bloqueie ou desbloqueie outros usuários, já que você se encontra bloqueado",
        "logentry-import-upload": "$1 {{GENDER:$2|importado}} $3 por envio de arquivo",
        "logentry-import-interwiki": "$1 {{GENDER:$2|importado}} $3 de outra wiki",
        "logentry-merge-merge": "$1 {{GENDER:$2|fundiu}} $3 com $4 (edições até $5)",
-       "logentry-move-move": "$1 moveu a página $3 para $4",
-       "logentry-move-move-noredirect": "$1 moveu a página $3 para $4 sem deixar um redirecionamento",
-       "logentry-move-move_redir": "$1 {{GENDER:$2|moveu}} a página $3 para seu redirecionamento $4",
-       "logentry-move-move_redir-noredirect": "$1 {{GENDER:$2|moveu}} a página $3 para seu redirecionamento $4 suprimindo o primeiro",
+       "logentry-move-move": "$1 moveu $3 para $4",
+       "logentry-move-move-noredirect": "$1 moveu $3 para $4 sem deixar um redirecionamento",
+       "logentry-move-move_redir": "$1 {{GENDER:$2|moveu}} $3 para seu redirecionamento $4",
+       "logentry-move-move_redir-noredirect": "$1 {{GENDER:$2|moveu}} $3 para seu redirecionamento $4 suprimindo o primeiro",
        "logentry-patrol-patrol": "$1 {{GENDER:$2|marcou}} a revisão $4 da página $3 como patrulhada",
        "logentry-patrol-patrol-auto": "$1 {{GENDER:$2|marcou}} automaticamente a revisão $4 da página $3 como patrulhada",
        "logentry-newusers-newusers": "A conta de usuário $1 foi {{GENDER:$2|criada}}",
index ba79643..d64c8ff 100644 (file)
        "rev-deleted-comment": "(resumo da edição suprimido)",
        "rev-deleted-user": "(nome de utilizador(a) removido)",
        "rev-deleted-event": "(registos de detalhes eliminados)",
-       "rev-deleted-user-contribs": "[nome de utilizador(a) ou IP removido – edição ocultada das contribuições]",
+       "rev-deleted-user-contribs": "[nome de utilizador(a) ou IP removido do histórico – edição ocultada das contribuições públicas]",
        "rev-deleted-text-permission": "Esta revisão de página foi <strong>eliminada</strong>.\nEncontrará detalhes no [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} registo de eliminações].",
        "rev-suppressed-text-permission": "Esta revisão de página foi <strong>suprimida</strong>.\nPode consultar os detalhes no [{{fullurl:{{#Special:Log}}/suppress|page={{FULLPAGENAMEE}}}} registo de supressões].",
        "rev-deleted-text-unhide": "Esta revisão de página foi <strong>eliminada</strong>.\nEncontrará detalhes no [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} registo de eliminações].\nPode mesmo assim [$1 ver esta revisão] se deseja prosseguir.",
        "changecontentmodel-emptymodels-title": "Não há modelos de conteúdo disponíveis",
        "changecontentmodel-emptymodels-text": "O conteúdo em [[:$1]] não pode ser convertido para qualquer tipo.",
        "log-name-contentmodel": "Registo de alteração de modelo de conteúdo",
-       "log-description-contentmodel": "Eventos relacionados com os modelos de conteúdo de uma página",
+       "log-description-contentmodel": "Esta página lista alterações do modelo de conteúdo das páginas e páginas criadas com um modelo de conteúdo diferente do padrão.",
        "logentry-contentmodel-new": "$1 {{GENDER:$2|criou}} a página $3 com o modelo de conteúdo desconhecido \"$5\"",
        "logentry-contentmodel-change": "$1 {{GENDER:$2|alterou}} o modelo de conteúdo da página $3 de \"$4\" para \"$5\"",
        "logentry-contentmodel-change-revertlink": "reverter",
        "recreate": "Recriar",
        "confirm_purge_button": "OK",
        "confirm-purge-top": "Limpar a memória cache desta página?",
-       "confirm-purge-bottom": "Recarregar uma página, limpa a cache e força a sua versão mais recente a aparecer.",
+       "confirm-purge-bottom": "Recarregar uma página limpa a cache e força a sua versão mais recente a aparecer.",
        "confirm-watch-button": "OK",
        "confirm-watch-top": "Adicionar esta página à lista de páginas vigiadas?",
        "confirm-unwatch-button": "OK",
        "logentry-import-interwiki": "$1 {{GENDER:$2|importou}} $3 de outra wiki",
        "logentry-import-interwiki-details": "$1 {{GENDER:$2|importou}} $3 de $5 ($4 {{PLURAL:$4|revisão|revisões}})",
        "logentry-merge-merge": "$1 {{GENDER:$2|fundiu}} $3 com $4 (edições até $5)",
-       "logentry-move-move": "$1 moveu a página $3 para $4",
-       "logentry-move-move-noredirect": "$1 moveu a página $3 para $4 sem deixar um redirecionamento",
-       "logentry-move-move_redir": "$1 {{GENDER:$2|moveu}} a página $3 para o seu redirecionamento $4",
-       "logentry-move-move_redir-noredirect": "$1 {{GENDER:$2|moveu}} a página $3 para o seu redirecionamento $4, suprimindo o primeiro",
+       "logentry-move-move": "$1 moveu $3 para $4",
+       "logentry-move-move-noredirect": "$1 moveu $3 para $4 sem deixar um redirecionamento",
+       "logentry-move-move_redir": "$1 {{GENDER:$2|moveu}} $3 para o seu redirecionamento $4",
+       "logentry-move-move_redir-noredirect": "$1 {{GENDER:$2|moveu}} $3 para o seu redirecionamento $4, suprimindo o primeiro",
        "logentry-patrol-patrol": "$1 {{GENDER:$2|marcou}} a revisão $4 da página $3 como patrulhada",
        "logentry-patrol-patrol-auto": "$1 {{GENDER:$2|marcou}} automaticamente a revisão $4 da página $3 como patrulhada",
        "logentry-newusers-newusers": "A conta de utilizador $1 foi {{GENDER:$2|criada}}",
        "sessionprovider-nocookies": "Os cookies podem estar desativados. Certifique-se de que os cookies estão ativados e inicie novamente.",
        "randomrootpage": "Página aleatória de raiz",
        "log-action-filter-block": "Tipo de bloqueio:",
-       "log-action-filter-contentmodel": "Tipo de alteração de modelo de conteúdo:",
+       "log-action-filter-contentmodel": "Tipo de alteração do modelo de conteúdo:",
        "log-action-filter-delete": "Tipo de eliminação:",
        "log-action-filter-import": "Tipo de importação:",
        "log-action-filter-managetags": "Tipo de ação de gestão de etiqueta:",
        "log-action-filter-block-block": "Bloqueio",
        "log-action-filter-block-reblock": "Alteração de bloqueio",
        "log-action-filter-block-unblock": "Desbloqueio",
-       "log-action-filter-contentmodel-change": "Alteração de modelo de conteúdo",
+       "log-action-filter-contentmodel-change": "Alteração do modelo de conteúdo",
        "log-action-filter-contentmodel-new": "Criação de página com modelo de conteúdo não padronizado",
        "log-action-filter-delete-delete": "Eliminação de página",
        "log-action-filter-delete-delete_redir": "Sobrescrição de redirecionamento",
index 99f7679..da43aef 100644 (file)
                        "Ата",
                        "Matěj Suchánek",
                        "Chaduvari",
-                       "MarcoAurelio"
+                       "MarcoAurelio",
+                       "Joao Xavier"
                ]
        },
        "sidebar": "{{notranslate}}",
        "grant-group-private-information": "{{Related|Grant-group}}",
        "grant-group-other": "{{Related|Grant-group}}",
        "grant-blockusers": "Name for grant \"blockusers\".\n{{Related|Grant}}",
-       "grant-createaccount": "Name for grant \"createaccount\".\n{{Related|Grant}}",
+       "grant-createaccount": "Name for grant \"createaccount\".\n{{Related|Grant}}\n{{Identical|Create account}}",
        "grant-createeditmovepage": "Name for grant \"createeditmovepage\".\n{{Related|Grant}}",
        "grant-delete": "Name for grant \"delete\".\n{{Related|Grant}}",
        "grant-editinterface": "Name for grant \"editinterface\".\n\n\"JS\" stands for \"JavaScript\".\n{{Related|Grant}}",
        "recentchanges-legend-unpatrolled": "Used as legend on [[Special:RecentChanges]] and [[Special:Watchlist]].\n\nRefers to {{msg-mw|Recentchanges-label-unpatrolled}}.",
        "recentchanges-legend-plusminus": "{{optional}}\nA plus/minus sign with a number for the legend.",
        "recentchanges-submit": "Label for submit button in [[Special:RecentChanges]]\n{{Identical|Show}}",
+       "rcfilters-activefilters": "Title for the filters selection showing the active filters.",
+       "rcfilters-search-placeholder": "Placeholder for the filter search input.",
+       "rcfilters-invalid-filter": "A label for an ivalid filter.",
+       "rcfilters-filterlist-title": "Title for the filters list.\n{{Identical|Filter}}",
+       "rcfilters-filterlist-noresults": "Message showing no results found for searching a filter.",
+       "rcfilters-filtergroup-authorship": "Title for the filter group for edit authorship. This filter group allows the user to choose between \"Your own edits\" and \"Edits by others\". More info: https://phabricator.wikimedia.org/T149859\n\n{{doc-important|This is another typical example of ambiguity in the English language. Only the documentation will reveal that this message means \"(filter by) authorship of these edits\", not \"edit the authorship\". That is, \"edit\" is a modifying noun, not a verb.}}",
+       "rcfilters-filter-editsbyself-label": "Label for the filter for showing edits made by the current user.",
+       "rcfilters-filter-editsbyself-description": "Description for the filter for showing edits made by the current user.",
+       "rcfilters-filter-editsbyother-label": "Label for the filter for showing edits made by anyone other than the current user.",
+       "rcfilters-filter-editsbyother-description": "Description for the filter for showing edits made by anyone other than the current user.",
+       "rcfilters-filtergroup-userExpLevel": "Title for the filter group for user experience levels.",
+       "rcfilters-filter-userExpLevel-newcomer-label": "Label for the filter for showing edits made by new editors.",
+       "rcfilters-filter-userExpLevel-newcomer-description": "Description for the filter for showing edits made by new editors.",
+       "rcfilters-filter-userExpLevel-learner-label": "Label for the filter for showing edits made by learning editors.",
+       "rcfilters-filter-userExpLevel-learner-description": "Description for the filter for showing edits made by learning editors.",
+       "rcfilters-filter-userExpLevel-experienced-label": "Label for the filter for showing edits made by experienced editors.",
+       "rcfilters-filter-userExpLevel-experienced-description": "Description for the filter for showing edits made by experienced editors.",
        "rcnotefrom": "This message is displayed at [[Special:RecentChanges]] when viewing recentchanges from some specific time.\n\nThe corresponding message is {{msg-mw|Rclistfrom}}.\n\nParameters:\n* $1 - the maximum number of changes that are displayed\n* $2 - (Optional) a date and time\n* $3 - a date\n* $4 - a time\n* $5 - Number of changes are displayed, for use with PLURAL",
        "rclistfrom": "Used on [[Special:RecentChanges]]. Parameters:\n* $1 - (Currently not use) date and time. The date and the time adds to the rclistfrom description.\n* $2 - time. The time adds to the rclistfrom link description (with split of date and time).\n* $3 - date. The date adds to the rclistfrom link description (with split of date and time).\n\nThe corresponding message is {{msg-mw|Rcnotefrom}}.",
        "rcshowhideminor": "Option text in [[Special:RecentChanges]]. Parameters:\n* $1 - the \"show/hide\" command, with the text taken from either {{msg-mw|rcshowhideminor-show}} or {{msg-mw|rcshowhideminor-hide}}\n{{Identical|Minor edit}}",
        "sorbs": "{{optional}}",
        "sorbsreason": "See also:\n* {{msg-mw|Sorbsreason}}\n* {{msg-mw|Sorbs create account_reason}}",
        "sorbs_create_account_reason": "Used in [[Special:UserLogin]] when creating an account.\n\nSee also:\n* {{msg-mw|Sorbsreason}}\n* {{msg-mw|Sorbs create account_reason}}",
+       "softblockrangesreason": "This text is shown to the user as a block reason and describes that the user is being blocked because the user is not logged in and their IP is in [[mw:Special:MyLanguage/Manual:$wgSoftBlockRanges|$wgSoftBlockRanges]].\n\nParameters:\n* $1 - The IP address that is blocked.",
        "xffblockreason": "This text is shown to the user as a block reason and describes that the user is being blocked because an IP in the X-Forwarded-For header (which lists the user's IP as well as all IPs of the transparent proxy servers they went through) sent when they loaded the page has been blocked:\n* $1 is the original block reason for the IP address matched in the X-Forwarded-For header",
        "cant-see-hidden-user": "Used as (red) error message on [[Special:Block]] when you try to change (as sysop without the hideuser right) the block of a hidden user.",
        "ipbblocked": "Error message shown when a user tries to alter block settings when they are themselves blocked.",
        "pagelang-language": "Language selector label for Special:PageLanguage\n{{Identical|Language}}",
        "pagelang-use-default": "Radio label for selector on Special:PageLanguage for default language",
        "pagelang-select-lang": "Radio label for selector on Special:PageLanguage for language selection\n{{Identical|Select language}}",
+       "pagelang-reason": "Input label for reason on Special:PageLanguage\n\n{{Identical|Reason}}",
        "pagelang-submit": "Submit button label for Special:PageLanguage form\n{{Identical|Submit}}",
+       "pagelang-nonexistent-page": "Error message shown when the page the user is trying to change the language on does not exist.\n\nParameters:\n* $1 - the title of the nonexistent page",
+       "pagelang-unchanged-language": "Error message shown when the language the user is trying to change the page to and the current language the page is in are the same.\n\nParameters:\n* $1 - the title of the target page\n* $2 - the current language of the page",
+       "pagelang-unchanged-language-default": "Error message shown when the language the user is trying to set a page to fall back to the wiki's default content language, but the page is already set to do so.\n\nParameters:\n* $1 - the title of the target page",
+       "pagelang-db-failed": "Error message shown when the database fails to update the language of the page",
        "right-pagelang": "{{Doc-right|pagelang}}\nRight to change page language on Special:PageLanguage",
        "action-pagelang": "{{Doc-action|pagelang}}",
        "log-name-pagelang": "Display entry for log name for changes in page language in Special:Log.",
index 1f80708..9577650 100644 (file)
        "recentchanges-legend-newpage": "{{int:recentchanges-label-newpage}} (см. также [[Special:NewPages|список новых страниц]])",
        "recentchanges-legend-plusminus": "(''±123'')",
        "recentchanges-submit": "Показать",
+       "rcfilters-activefilters": "Активные фильтры",
+       "rcfilters-search-placeholder": "Последние изменения фильтров (просмотрите или начните вводить)",
+       "rcfilters-invalid-filter": "Недопустимый фильтр",
+       "rcfilters-filterlist-title": "Фильтры",
+       "rcfilters-filterlist-noresults": "Фильтры не найдены",
+       "rcfilters-filtergroup-authorship": "Редактировать авторство",
+       "rcfilters-filter-editsbyself-label": "Ваши собственные правки",
+       "rcfilters-filter-editsbyself-description": "Ваши правки.",
+       "rcfilters-filter-editsbyother-label": "Правки других участников",
+       "rcfilters-filter-editsbyother-description": "Изменения, созданные другими пользователями (а не вами.)",
+       "rcfilters-filtergroup-userExpLevel": "Уровня опыта пользователей",
+       "rcfilters-filter-userExpLevel-newcomer-label": "Новички",
+       "rcfilters-filter-userExpLevel-newcomer-description": "Совсем новые редакторы: менее 10 правок и 4 дней работы.",
+       "rcfilters-filter-userExpLevel-learner-label": "Учащиеся",
+       "rcfilters-filter-userExpLevel-learner-description": "Больше правок и дней работы, чем у 'новичков', но меньше, чем у 'опытных пользователей'.",
+       "rcfilters-filter-userExpLevel-experienced-label": "Опытные пользователи",
+       "rcfilters-filter-userExpLevel-experienced-description": "Более 30 дней активности и 500 правок.",
        "rcnotefrom": "Ниже {{PLURAL:$5|указано изменение|перечислены изменения}} с <strong>$3, $4</strong> (показано не более <strong>$1</strong>).",
        "rclistfrom": "Показать изменения с $3 $2.",
        "rcshowhideminor": "$1 малые правки",
        "apisandbox-sending-request": "Отправка API-запроса…",
        "apisandbox-loading-results": "Получение API-результатов…",
        "apisandbox-results-error": "Произошла ошибка при загрузке API-ответа на запрос: $1.",
+       "apisandbox-request-params-json": "JSON-параметры:",
        "apisandbox-request-url-label": "URL-адрес запроса:",
        "apisandbox-request-time": "Время запроса: {{PLURAL:$1|$1 мс}}",
        "apisandbox-results-fixtoken": "Исправьте токен и повторите отправку",
        "proxyblockreason": "Ваш IP-адрес заблокирован потому, что это открытый прокси-сервер. Пожалуйста, свяжитесь со своиим интернет-провайдером или службой поддержки, и сообщите им об этой серьёзной проблеме безопасности.",
        "sorbsreason": "Ваш IP-адрес числится как открытый прокси в DNSBL.",
        "sorbs_create_account_reason": "Ваш IP-адрес числится как открытый прокси в DNSBL. Вы не можете создать учётную запись.",
+       "softblockrangesreason": "Анонимные правки не разрешены с вашего IP-адреса ($1). Пожалуйста, войдите в систему.",
        "xffblockreason": "Был заблокирован IP-адрес, присутствующий в заголовке X-Forwarded-For и принадлежащий либо вам, либо используемому вами прокси-серверу. Первоначальная причина блокировки была следующей: $1",
        "cant-see-hidden-user": "Участник, которого вы пытаетесь заблокировать, уже заблокирован и скрыт. Поскольку у вас нет разрешения на работу по сокрытию участников, вы не можете просмотреть или изменить данную блокировку.",
        "ipbblocked": "Вы не можете блокировать или разблокировать других участников, так как вы сами заблокированы",
        "logentry-move-move_redir": "$1 {{GENDER:$2|переименовал|переименовала}} страницу $3 в $4 поверх перенаправления",
        "logentry-move-move_redir-noredirect": "$1 {{GENDER:$2|переименовал|переименовала}} страницу $3 в $4 поверх перенаправления и без оставления перенаправления",
        "logentry-patrol-patrol": "$1 {{GENDER:$2|отпатрулировал|отпатрулировала}} версию $4 страницы $3",
-       "logentry-patrol-patrol-auto": "$1 автоматически {{GENDER:$2|отпатрулировал|отпатрулировала}} версию $4 страницы $3",
+       "logentry-patrol-patrol-auto": "$1 автоматически {{GENDER:$2|отпатрулировал|отпатрулировала}} «старым патрулированием» версию $4 страницы $3",
        "logentry-newusers-newusers": "{{GENDER:$2|Участник создал|Участница создала}} учётную запись $1",
        "logentry-newusers-create": "{{GENDER:$2|Участник создал|Участница создала}} учётную запись $1",
        "logentry-newusers-create2": "$1 {{GENDER:$2|создал|создала}} учётную запись $3",
        "pagelang-language": "Язык",
        "pagelang-use-default": "Использовать язык по умолчанию",
        "pagelang-select-lang": "Выберите язык",
+       "pagelang-reason": "Причина",
        "pagelang-submit": "Отправить",
+       "pagelang-nonexistent-page": "Страница $1 не существует.",
+       "pagelang-unchanged-language": "Странице $1 уже установлен язык $2.",
+       "pagelang-db-failed": "Базе данных не удалось изменить язык страницы.",
        "right-pagelang": "изменение языка страницы",
        "action-pagelang": "изменять язык страницы",
        "log-name-pagelang": "Журнал изменения языка",
        "log-action-filter-block-reblock": "Изменение блокировки",
        "log-action-filter-block-unblock": "Разблокировка",
        "log-action-filter-contentmodel-change": "Изменение модели содержимого",
-       "log-action-filter-contentmodel-new": "Создание страницы с нестандартной моделью Contentmodel",
+       "log-action-filter-contentmodel-new": "Создание страницы с нестандартной моделью содержимого",
        "log-action-filter-delete-delete": "Удаления страницы",
        "log-action-filter-delete-delete_redir": "Перезапись перенаправления",
        "log-action-filter-delete-restore": "Восстановление страницы",
index 8ef53b8..b84a95b 100644 (file)
        "recentchanges-legend-heading": "<strong>Легендата:</strong>",
        "recentchanges-legend-newpage": "{{int:recentchanges-label-newpage}} (өссө көр: [[Special:NewPages|Саҥа сирэйдэр тиһиктэрэ]])",
        "recentchanges-submit": "Көрдөр",
+       "rcfilters-filterlist-title": "Сиидэ",
+       "rcfilters-filterlist-noresults": "Сиидэ көстүбэтэ",
        "rcnotefrom": "Манна {{PLURAL:$5|уларытыы көрдөрүлүннэ|уларытыылар көһүннүлэр}} баччаттан <strong>$3, $4</strong> (баччаттан элбэх көстүбэт <strong>$1</strong>).",
        "rclistfrom": "Бу кэм $3 $2 кэнниттэн оҥоһуллубуттары көрдөр",
        "rcshowhideminor": "$1 кыра уларыйыылары",
        "cant-move-to-user-page": "Эн кыттааччы аатын далыгар сирэйдэри уларытар кыаҕыҥ суох (анныкы сирэйдэриттэн ураты).",
        "cant-move-category-page": "Категория сирэйин аатын уларытар кыаҕыҥ суох эбит.",
        "cant-move-to-category-page": "Сирэй аатын уларытан категория сирэйэ гынар кыаҕыҥ суох эбит.",
+       "namespace-nosubpages": "«$1» аат далыгар сирэй оҥорор табыллыбат эбит.",
        "newtitle": "Саҥа аата:",
        "move-watch": "Кэтээн көрөргө",
        "movepagebtn": "Аатын уларыт",
        "api-error-badtoken": "Ис алҕас: Омсолоох токен.",
        "api-error-blocked": "Уларытар кыаххын быспыттар эбит.",
        "api-error-copyuploaddisabled": "URL көмөтүнэн киллэрии бу сиэрбэргэ араарыллыбыт.",
-       "api-error-duplicate": "Маннык иһинээҕилээх {{PLURAL:$1|атын билэ баар эбит}}",
+       "api-error-duplicate": "Маннык иһинээҕилээх атын {{PLURAL:$1|билэ баар|билэлэр бааллар}} эбит",
        "api-error-duplicate-archive": "Урут ситим-сиргэ маннык иһинээҕилээх {{PLURAL:$1|билэ баар|билэлэр бааллар}} этэ, ол гынан баран {{PLURAL:$1|сотуллубута|сотуллубуттара}}.",
        "api-error-empty-file": "Ыыппыт билэҥ кураанах.",
        "api-error-emptypage": "Саҥа кураанах сирэйи оҥорор табыллыбат.",
index 0da808b..dce7088 100644 (file)
@@ -49,7 +49,7 @@
        "tog-diffonly": "Neruodītė poslapė torėnė puo skėrtomās",
        "tog-showhiddencats": "Ruodītė pakavuotas kateguorėjės",
        "tog-norollbackdiff": "Nekrēptė diemesė i skėrtoma atlėkus atmetėma",
-       "tog-useeditwarning": "Monėi dout žėnuot, kāp ėšēno ėš poslapė anon naėšsauguojis",
+       "tog-useeditwarning": "Monėi doutė žėnuotė, kap ėšēno ėš poslapė anon naėšsauguojė̄s",
        "tog-prefershttps": "Vėsūmet nauduotė saugu rīši kap būno prisijongė̄s",
        "underline-always": "Vėsūmet",
        "underline-never": "Nikūmet",
index 557531f..7d4e16f 100644 (file)
        "recentchanges-legend-heading": "<strong>Legenda:</strong>",
        "recentchanges-legend-newpage": "{{int:recentchanges-label-newpage}} (glej tudi [[Special:NewPages|seznam novih strani]])",
        "recentchanges-submit": "Prikaži",
+       "rcfilters-activefilters": "Dejavni filtri",
+       "rcfilters-search-placeholder": "Zadnje spremembe filtrov (prebrskajte ali začnite vnašati)",
+       "rcfilters-invalid-filter": "Neveljaven filter",
+       "rcfilters-filterlist-title": "Filtri",
+       "rcfilters-filterlist-noresults": "Nismo našli nobenega filtra",
+       "rcfilters-filtergroup-authorship": "Uredi avtorstvo",
+       "rcfilters-filter-editsbyself-label": "Vaša lastna urejanja",
+       "rcfilters-filter-editsbyself-description": "Vaša urejanja.",
+       "rcfilters-filter-editsbyother-label": "Urejanja drugih",
+       "rcfilters-filter-editsbyother-description": "Urejanja, ki so jih naredili drugi uporabniki (ne vi).",
+       "rcfilters-filtergroup-userExpLevel": "Stopnja uporabnikove izkušenosti",
+       "rcfilters-filter-userExpLevel-newcomer-label": "Novinci",
+       "rcfilters-filter-userExpLevel-newcomer-description": "Zelo novi sodelavci: manj kot 10 urejanj in 4 dni dejavnosti.",
+       "rcfilters-filter-userExpLevel-learner-label": "Učenci",
+       "rcfilters-filter-userExpLevel-learner-description": "Več dni dejavnosti in urejanj kot »Novinci«, vendar manj kot »Izkušeni uporabniki«.",
+       "rcfilters-filter-userExpLevel-experienced-label": "Izkušeni uporabniki",
+       "rcfilters-filter-userExpLevel-experienced-description": "Več kot 30 dni dejavnosti in 500 urejanj.",
        "rcnotefrom": "{{PLURAL:$5|Navedena je sprememba|Navedeni sta spremembi|Navedene so spremembe}} od <strong>$3 $4</strong> dalje (prikazujem jih do <strong>$1</strong>).",
        "rclistfrom": "Prikaži spremembe od $3 $2 naprej",
        "rcshowhideminor": "$1 manjša urejanja",
        "proxyblockreason": "Ker uporabljate odprti posredniški strežnik, je urejanje z vašega IP-naslova preprečeno.\nGre za resno varnostno težavo, o kateri obvestite svojega internetnega ponudnika ali tehnično podporo.",
        "sorbsreason": "Vaš IP-naslov je v DNSBL uvrščen med odprte posredniške strežnike.",
        "sorbs_create_account_reason": "Vaš IP-naslov je v DNSBL, ki ga uporablja {{GRAMMAR:tožilnik|{{SITENAME}}}}, naveden kot odprti posredniški strežnik (proxy).\nRačuna žal ne morete ustvariti.",
+       "softblockrangesreason": "Brezimni prispevki z vašega IP-naslova ($1) niso dovoljeni. Prosimo, prijavite se.",
        "xffblockreason": "IP-naslov, prisoten v glavi X-Forwarded-For, ali vaš ali od strežnika proxy, ki ga uporabljate, je blokiran. Izvirni razlog za blokado: $1",
        "cant-see-hidden-user": "Uporabnik, ki ga poskušate blokirate, je že blokiran in skrit.\nKer nimate pravice hideuser, si ne morete ogledati ali urejati uporabnikove blokade.",
        "ipbblocked": "Ne morete blokirati ali deblokirati drugih uporabnikov, saj ste sami blokirani",
        "pagelang-language": "Jezik",
        "pagelang-use-default": "Uporabi privzeti jezik",
        "pagelang-select-lang": "Izberite jezik",
+       "pagelang-reason": "Razlog",
        "pagelang-submit": "Potrdi",
+       "pagelang-nonexistent-page": "Stran $1 ne obstaja.",
+       "pagelang-unchanged-language": "Stran $1 že ima nastavljen jezik $2.",
+       "pagelang-unchanged-language-default": "Stran $1 že ima nastavljen wikijev privzeti jezik vsebine.",
+       "pagelang-db-failed": "Zbirka podatkov ni uspela spremeniti jezika strani.",
        "right-pagelang": "Spreminjanje jezika strani",
        "action-pagelang": "spreminjanje jezika strani",
        "log-name-pagelang": "Dnevnik sprememb jezika",
index 1a387b2..759a9e6 100644 (file)
        "recentchanges-legend-newpage": "{{int:recentchanges-label-newpage}} (se även [[Special:NewPages|listan över nya sidor]])",
        "recentchanges-legend-plusminus": "(''±123'')",
        "recentchanges-submit": "Visa",
+       "rcfilters-activefilters": "Aktiva filter",
+       "rcfilters-search-placeholder": "Filtrera senaste ändringar (bläddra eller börja skriva)",
+       "rcfilters-invalid-filter": "Ogiltigt filter",
+       "rcfilters-filterlist-title": "Filter",
+       "rcfilters-filterlist-noresults": "Inga filter hittades",
+       "rcfilters-filtergroup-authorship": "Redigera författarskap",
+       "rcfilters-filter-editsbyself-label": "Dina egna redigeringar",
+       "rcfilters-filter-editsbyself-description": "Redigeringar av dig.",
+       "rcfilters-filter-editsbyother-label": "Redigeringar av andra",
+       "rcfilters-filter-editsbyother-description": "Redigeringar som har skapats av andra användare (inte dig.)",
+       "rcfilters-filtergroup-userExpLevel": "Erfarenhetsnivå för användare",
+       "rcfilters-filter-userExpLevel-newcomer-label": "Nykomlingar",
+       "rcfilters-filter-userExpLevel-newcomer-description": "Väldigt nya redigerare: färre än 10 redigeringar och 4 dagars aktivitet.",
+       "rcfilters-filter-userExpLevel-learner-label": "Nybörjare",
+       "rcfilters-filter-userExpLevel-learner-description": "Fler dagars aktivitet och redigeringar än \"Nybörjare\" men färre än \"Erfarna användare\".",
+       "rcfilters-filter-userExpLevel-experienced-label": "Erfarna användare",
+       "rcfilters-filter-userExpLevel-experienced-description": "Fler än 30 dagars aktivitet och 500 redigeringar.",
        "rcnotefrom": "Nedan visas {{PLURAL:$5|ändringen|ändringar}} sedan <strong>$3, $4</strong> (upp till <strong>$1</strong> ändringar visas).",
        "rclistfrom": "Visa nya ändringar från och med $2 $3",
        "rcshowhideminor": "$1 mindre ändringar",
        "apisandbox-sending-request": "Skickar API-begäran...",
        "apisandbox-loading-results": "Hämtar API-resultat...",
        "apisandbox-results-error": "Ett fel uppstod när API-förfrågans svar lästes in: $1.",
+       "apisandbox-request-params-json": "JSON-parametrar:",
        "apisandbox-request-url-label": "Begärd URL:",
        "apisandbox-request-time": "Tid för begäran: {{PLURAL:$1|$1 ms}}",
        "apisandbox-results-fixtoken": "Korrigera nyckeln och skicka igen",
        "changecontentmodel-emptymodels-title": "Inget innehållsmodeller finns tillgängliga",
        "changecontentmodel-emptymodels-text": "Innehållet på [[:$1]] kan inte konverteras till någon typ.",
        "log-name-contentmodel": "Ändringslogg för innehållsmodellen",
-       "log-description-contentmodel": "Händelser som är relaterade till en sidas innehållsmodeller",
+       "log-description-contentmodel": "Denna sida listar ändringar i innehållsmodellen för sidor och sidor som skapades med en annan innehållsmodell än den som är standard.",
        "logentry-contentmodel-new": "$1 {{GENDER:$2|skapade}} sidan $3 med den icke-standardiserade innehållsmodellen \"$5\"",
        "logentry-contentmodel-change": "$1 {{GENDER:$2|ändrade}} innehållsmodellen för sidan $3 från \"$4\" till \"$5\"",
        "logentry-contentmodel-change-revertlink": "återställ",
        "proxyblockreason": "Din IP-adress har blivit blockerad eftersom den tillhör en öppen proxy. Kontakta din internetleverantör eller din organisations eller företags tekniska support, och informera dem om denna allvarliga säkerhetsrisk.",
        "sorbsreason": "Din IP-adress är listad som öppen proxy i den DNSBL {{SITENAME}} använder.",
        "sorbs_create_account_reason": "Din IP-adress är listad som en öppen proxy i den DNSBL som används av {{SITENAME}}.\nDu får inte skapa ett användarkonto",
+       "softblockrangesreason": "Anonyma bidrag tillåts inte från din IP-adress ($1). Var god logga in.",
        "xffblockreason": "En IP-adress i sidhuvudet X-Forwarded-For, antingen din adress eller en proxyserver som du använder, har blockerats. Den ursprungliga anledningen till blockeringen var: $1",
        "cant-see-hidden-user": "Användaren du försöker blockera är redan blockerad och dold. Eftersom du inte har hideuser-rättigheter, kan du inte se eller redigera användarens blockering.",
        "ipbblocked": "Du kan inte blockera eller avblockera andra användare, eftersom du själv är blockerad",
        "pagelang-language": "Språk",
        "pagelang-use-default": "Använd standardspråk",
        "pagelang-select-lang": "Välj språk",
+       "pagelang-reason": "Orsak",
        "pagelang-submit": "Skicka",
+       "pagelang-nonexistent-page": "Sidan $1 finns inte.",
+       "pagelang-unchanged-language": "Sidan $1 har redan språket $2.",
+       "pagelang-unchanged-language-default": "Sidan $1 har redan wikins standardinnehållsspråk.",
+       "pagelang-db-failed": "Databasen misslyckades med att ändra sidans språk.",
        "right-pagelang": "Ändra sidspråk",
        "action-pagelang": "ändra sidspråket",
        "log-name-pagelang": "Språkändringslogg",
index cb87aa9..3e28160 100644 (file)
        "viewsourcetext": "Тӥ быгатӥськоды та бамлэсь кодзэ учкыны но кӧчырыны.",
        "viewyourtext": "Тӥ быгатӥськоды та бамез <strong>тӥляд тупатонъёстылэсь</strong> кодзэс учкыны но кӧчырыны.",
        "protectedinterface": "Та бам возе интерфейс текстэз та викилэн программной обеспечениезлы. Вандализмез палэнтон понна со утемын воштонъёслэсь.\nВань викиослы берыктэмъёсты ватсалляны яке вошъяны вылысь, тауна, MediaWiki локализацияя сайтэ выжелэ — [https://translatewiki.net/ translatewiki.net].",
-       "editinginterface": "<strong>Юа:</strong> Ñ\80едакÑ\82иÑ\80оваÑ\82Ñ\8c ÐºÐ°Ñ\80Ñ\8bнÑ\8b Ð±Ð°Ð¼Ð·Ñ\8d Ñ\82он, Ð¿Ñ\80огÑ\80аммное Ð¾Ð±ÐµÑ\81пеÑ\87ение Ð¿Ð¾Ð½Ð½Ð° Ñ\81о Ð¸Ð½Ñ\82еÑ\80Ñ\84ейÑ\81 Ñ\82екÑ\81Ñ\82овÑ\8bе ÐºÑ\8bлдÑ\8bÑ\82он Ð¿Ð¾Ð½Ð½Ð° ÐºÑ\83Ñ\82Ñ\8bнÑ\8b.\nТа Ð²Ð¸ÐºÐ¸Ð»Ñ\8dн Ð¼Ñ\83кеÑ\82 Ð±Ð°Ð¼Ð°Ð· Ð»Ñ\83иÑ\81Ñ\8c Ñ\82Ñ\83Ñ\81Ñ\81Ñ\8d Ð²Ð¾Ñ\88Ñ\82он Ð¿Ð¾Ð½Ð½Ð° Ñ\82а Ð¸Ð½Ñ\82еÑ\80Ñ\84ейÑ\81Ñ\8dз Ð¿Ð¾Ð»Ñ\8cзоваÑ\82елÑ\8c Ð¿Ð¾Ð»Ñ\8cзоваÑ\82елÑ\8cÑ\81кий Ð¿ÐµÐ´Ð¿Ð°Ð» Ð±Ñ\8bгаÑ\82онлÑ\8bкÑ\8aÑ\91Ñ\81Ñ\81Ñ\8dÑ\81.",
+       "editinginterface": "<strong>Сак Ð»Ñ\83Ñ\8d:</strong> Ð¢Ó¥ Ñ\82Ñ\83паÑ\82Ó¥Ñ\81Ñ\8cкодÑ\8b Ð±Ð°Ð¼ÐµÐ·, ÐºÑ\83дӥз Ð²Ð¾Ð·Ðµ Ð¿Ñ\80огÑ\80аммной Ð¾Ð±ÐµÑ\81пеÑ\87енилÑ\8dÑ\81Ñ\8c Ð¸Ð½Ñ\82еÑ\80Ñ\84ейÑ\81 Ñ\82екÑ\81Ñ\82Ñ\81Ñ\8d.\nТа Ð±Ð°Ð¼ÐµÐ· Ñ\82Ñ\83паÑ\82он Ð²Ð¾Ñ\88Ñ\82оз Ð¸Ð½Ñ\82еÑ\80Ñ\84ейÑ\81Ñ\8dз Ð²Ð¾Ð·Ñ\8cмаÑ\82онÑ\8dз Ð¼Ñ\83кеÑ\82 Ð²Ð¸ÐºÐ¸Ð°Ð²Ñ\82оÑ\80Ñ\8aÑ\91Ñ\81лÑ\8b Ñ\82а Ð²Ð¸ÐºÐ¸Ñ\8bн.",
        "namespaceprotected": "Тон дорын редактировать карыны бам ӧвӧл юаське <кужмо>$1</strong> инты нимъёс.",
        "exception-nologin": "Тон эн тусбуяськыны сӧзнэтэз",
-       "logouttext": "<strong>Тон али потэ.</strong>\n\nУчком, мар быгатозы бам куд-ог сямъёсты тӥледыз кадь возьматӥсько ке луысал, азьвыл сямен азьвыл системая пыртэмын, тон ӧд сузя, дыр кеш браузер.",
+       "logouttext": "<strong>Тӥ ужан сеансэз йылпумъяды.</strong>\n\nКуд-огез бамъёс возьматӥськыны на быгато озьы, тӥ авторизовать каремын на кадь. Талы пумит нюръяськон понна бушатэ браузерлэсь кэшсэ.",
        "welcomeuser": "Гажаса-а, $1!",
        "welcomecreation-msg": "Тӥляд гожъямъёсты учётной кылдытэмын вал.\nТӥ быгатӥськоды воштэ {{SITENAME}} [[Special:Preferences|параметръёсты]] ке потэ тӥледлы.",
        "yourname": "Пырон ним:",
index a9180ac..b021371 100644 (file)
        "newwindow": "(響新視窗度打開)",
        "cancel": "取消",
        "moredotdotdot": "更多...",
-       "morenotlisted": "爾張清單重未完成。",
+       "morenotlisted": "爾張清單可能重未完成。",
        "mypage": "版",
        "mytalk": "傾偈",
        "anontalk": "傾偈",
        "resetpass_submit": "設定密碼同登入",
        "changepassword-success": "你嘅密碼已經成功噉改咗!",
        "changepassword-throttled": "你已經試咗太多次簽到動作。\n請等$1再試過。",
+       "botpasswords-label-create": "創造",
+       "botpasswords-label-update": "上載",
+       "botpasswords-label-cancel": "取消",
        "botpasswords-label-delete": "刪除",
+       "botpasswords-label-resetpassword": "改過個個密碼",
        "resetpass_forbidden": "唔可以更改密碼",
        "resetpass-no-info": "你一定要登入咗去直接入來呢一版。",
        "resetpass-submit-loggedin": "改密碼",
index 320f902..8c60ba4 100644 (file)
        "recentchanges-legend-newpage": "{{int:recentchanges-label-newpage}}(见[[Special:NewPages|新页面列表]])",
        "recentchanges-legend-plusminus": "(<em>±123</em>)",
        "recentchanges-submit": "显示",
+       "rcfilters-activefilters": "活跃的过滤器",
+       "rcfilters-search-placeholder": "过滤器最近更改(浏览或开始输入)",
+       "rcfilters-invalid-filter": "无效过滤器",
+       "rcfilters-filterlist-title": "过滤器",
+       "rcfilters-filterlist-noresults": "找不到过滤器",
+       "rcfilters-filtergroup-authorship": "编辑的作者",
+       "rcfilters-filter-editsbyself-label": "您自己的编辑",
+       "rcfilters-filter-editsbyself-description": "由您编辑。",
+       "rcfilters-filter-editsbyother-label": "由其他人编辑",
+       "rcfilters-filter-editsbyother-description": "由其他用户(而不是您)创建的编辑。",
+       "rcfilters-filtergroup-userExpLevel": "用户体验水平",
+       "rcfilters-filter-userExpLevel-newcomer-label": "新手",
+       "rcfilters-filter-userExpLevel-newcomer-description": "非常新的编辑者:少于10次编辑和4天活跃。",
+       "rcfilters-filter-userExpLevel-learner-label": "初学者",
+       "rcfilters-filter-userExpLevel-learner-description": "比“新手”拥有更多活跃天数和编辑数,但少于“有经验的用户。”",
+       "rcfilters-filter-userExpLevel-experienced-label": "有经验的用户",
+       "rcfilters-filter-userExpLevel-experienced-description": "超过30天活跃和500次编辑。",
        "rcnotefrom": "下面{{PLURAL:$5|是}}<strong>$3 $4</strong>之后的更改(最多显示<strong>$1</strong>个)。",
        "rclistfrom": "显示$3 $2之后的新更改",
        "rcshowhideminor": "$1小编辑",
        "apisandbox-sending-request": "正在发送API请求...",
        "apisandbox-loading-results": "正在接收API请求...",
        "apisandbox-results-error": "加载API查询响应时出错:$1。",
+       "apisandbox-request-params-json": "JSON参数:",
        "apisandbox-request-url-label": "请求的URL:",
        "apisandbox-request-time": "请求时间:{{PLURAL:$1|$1毫秒}}",
        "apisandbox-results-fixtoken": "改正令牌并重新提交",
        "proxyblockreason": "您的IP地址为已被封禁的公开代理。请联系您的互联网服务提供商或技术支持者,并告知他们此严重的安全问题。",
        "sorbsreason": "在{{SITENAME}}使用的DNSBL中,您的IP地址被列为公开代理。",
        "sorbs_create_account_reason": "在{{SITENAME}}使用的DNSBL中,您的IP地址被列为公开代理,因此您不能创建新账户。",
+       "softblockrangesreason": "您的IP地址($1)不允许匿名贡献。请登录。",
        "xffblockreason": "您或您正在使用的代理服务器呈现在X-Forwarded-For数据包头的一个IP地址已被封禁。封禁原因为:$1",
        "cant-see-hidden-user": "您尝试封禁的用户已被封禁并隐藏。\n由于您尚无隐藏用户的权限,您无法查看或编辑此用户的封禁。",
        "ipbblocked": "您无法封禁或解封其他用户,因为您自己已被封禁",
        "confirm-rollback-button": "确定",
        "confirm-rollback-top": "回退此页面的编辑么?",
        "semicolon-separator": ";",
-       "comma-separator": "",
+       "comma-separator": "",
        "colon-separator": ":",
        "pipe-separator": "&#32;|&#32;",
        "word-separator": "",
        "pagelang-language": "语言",
        "pagelang-use-default": "使用默认语言",
        "pagelang-select-lang": "选择语言",
+       "pagelang-reason": "原因",
        "pagelang-submit": "提交",
+       "pagelang-nonexistent-page": "页面$1不存在。",
+       "pagelang-unchanged-language": "页面$1已设置为语言$2。",
+       "pagelang-unchanged-language-default": "页面$1已设置为wiki的默认内容语言。",
+       "pagelang-db-failed": "数据库更改页面语言失败。",
        "right-pagelang": "更改页面语言",
        "action-pagelang": "更改页面语言",
        "log-name-pagelang": "语言更改日志",
index e8806c3..e0630ee 100644 (file)
        "confirm-rollback-button": "確定",
        "confirm-rollback-top": "還原編輯到此頁面?",
        "semicolon-separator": ";",
-       "comma-separator": "",
+       "comma-separator": "",
        "colon-separator": ":",
        "word-separator": "",
        "parentheses": " ($1)",
index 67369e2..99d3f64 100644 (file)
@@ -349,6 +349,7 @@ $magicWords = [
        'directionmark'           => [ 1, 'DIRECTIONMARK', 'DIRMARK' ],
        'language'                => [ 0, '#LANGUAGE:' ],
        'contentlanguage'         => [ 1, 'CONTENTLANGUAGE', 'CONTENTLANG' ],
+       'pagelanguage'            => [ 1, 'PAGELANGUAGE' ],
        'pagesinnamespace'        => [ 1, 'PAGESINNAMESPACE:', 'PAGESINNS:' ],
        'numberofadmins'          => [ 1, 'NUMBEROFADMINS' ],
        'formatnum'               => [ 0, 'FORMATNUM' ],
diff --git a/languages/messages/MessagesRup.php b/languages/messages/MessagesRup.php
new file mode 100644 (file)
index 0000000..041dc46
--- /dev/null
@@ -0,0 +1,10 @@
+<?php
+/** Aromanian (armãneashti)
+ *
+ * To improve a translation please visit https://translatewiki.net
+ *
+ * @ingroup Language
+ * @file
+ */
+
+$fallback = 'ro';
index b705500..522871d 100644 (file)
@@ -25,6 +25,7 @@
  */
 
 use MediaWiki\Linker\LinkTarget;
+use MediaWiki\MediaWikiServices;
 
 require_once __DIR__ . '/Maintenance.php';
 
@@ -224,7 +225,7 @@ class NamespaceConflictChecker extends Maintenance {
         * @return array
         */
        private function getInterwikiList() {
-               $result = Interwiki::getAllPrefixes();
+               $result = MediaWikiServices::getInstance()->getInterwikiLookup()->getAllPrefixes();
                $prefixes = [];
                foreach ( $result as $row ) {
                        $prefixes[] = $row['iw_prefix'];
index 6c812bf..8f7a918 100644 (file)
@@ -129,7 +129,7 @@ TEXT
                                __METHOD__
                        );
 
-                       if ( ! $row ) {
+                       if ( !$row ) {
                                $dbw->insert(
                                        'interwiki',
                                        [
index 92013ec..1c16cc3 100644 (file)
@@ -1775,6 +1775,51 @@ return [
 
        /* MediaWiki Special pages */
 
+       'mediawiki.rcfilters.filters' => [
+               'scripts' => [
+                       'resources/src/mediawiki.rcfilters/mw.rcfilters.js',
+                       'resources/src/mediawiki.rcfilters/dm/mw.rcfilters.dm.FilterItem.js',
+                       'resources/src/mediawiki.rcfilters/dm/mw.rcfilters.dm.FiltersViewModel.js',
+                       'resources/src/mediawiki.rcfilters/ui/mw.rcfilters.ui.FiltersListWidget.js',
+                       'resources/src/mediawiki.rcfilters/ui/mw.rcfilters.ui.FilterGroupWidget.js',
+                       'resources/src/mediawiki.rcfilters/ui/mw.rcfilters.ui.FilterItemWidget.js',
+                       'resources/src/mediawiki.rcfilters/ui/mw.rcfilters.ui.FilterCapsuleMultiselectWidget.js',
+                       'resources/src/mediawiki.rcfilters/ui/mw.rcfilters.ui.FilterWrapperWidget.js',
+                       'resources/src/mediawiki.rcfilters/mw.rcfilters.Controller.js',
+                       'resources/src/mediawiki.rcfilters/mw.rcfilters.init.js',
+               ],
+               'styles' => [
+                       'resources/src/mediawiki.rcfilters/styles/mw.rcfilters.less',
+                       'resources/src/mediawiki.rcfilters/styles/mw.rcfilters.ui.FilterItemWidget.less',
+                       'resources/src/mediawiki.rcfilters/styles/mw.rcfilters.ui.FilterGroupWidget.less',
+                       'resources/src/mediawiki.rcfilters/styles/mw.rcfilters.ui.FiltersListWidget.less',
+                       'resources/src/mediawiki.rcfilters/styles/mw.rcfilters.ui.FilterWrapperWidget.less',
+                       'resources/src/mediawiki.rcfilters/styles/mw.rcfilters.ui.FilterCapsuleMultiselectWidget.less',
+               ],
+               'messages' => [
+                       'rcfilters-activefilters',
+                       'rcfilters-search-placeholder',
+                       'rcfilters-invalid-filter',
+                       'rcfilters-filterlist-title',
+                       'rcfilters-filterlist-noresults',
+                       'rcfilters-filtergroup-authorship',
+                       'rcfilters-filter-editsbyself-label',
+                       'rcfilters-filter-editsbyself-description',
+                       'rcfilters-filter-editsbyother-label',
+                       'rcfilters-filter-editsbyother-description',
+                       'rcfilters-filtergroup-userExpLevel',
+                       'rcfilters-filter-userExpLevel-newcomer-label',
+                       'rcfilters-filter-userExpLevel-newcomer-description',
+                       'rcfilters-filter-userExpLevel-learner-label',
+                       'rcfilters-filter-userExpLevel-learner-description',
+                       'rcfilters-filter-userExpLevel-experienced-label',
+                       'rcfilters-filter-userExpLevel-experienced-description',
+               ],
+               'dependencies' => [
+                       'oojs-ui',
+                       'mediawiki.Uri',
+               ],
+       ],
        'mediawiki.special' => [
                'styles' => 'resources/src/mediawiki.special/mediawiki.special.css',
                'targets' => [ 'desktop', 'mobile' ],
index f25944c..4f900a4 100644 (file)
@@ -24,7 +24,7 @@
         *
         * @private
         * @param {Object} [ua] An object with a 'userAgent' and 'platform' property.
-        * @return {Array} Array with 0 or more of the string values: ctrl, option, alt, shift, esc
+        * @return {Array} Array with 1 or more of the string values, in this order: ctrl, option, alt, shift, esc
         */
        function getAccessKeyModifiers( ua ) {
                var profile, accessKeyModifiers;
                }
 
                profile = $.client.profile( ua );
-               accessKeyModifiers = [ 'alt' ];
-
-               // Classic Opera on any platform
-               if ( profile.name === 'opera' && profile.versionNumber < 15 ) {
-                       accessKeyModifiers = [ 'shift', 'esc' ];
-
-               // Chrome and modern Opera on any platform
-               } else if ( profile.name === 'chrome' || profile.name === 'opera' ) {
-                       accessKeyModifiers = (
-                               profile.platform === 'mac' ?
-                                       // Chrome on Mac
-                                       [ 'ctrl', 'option' ] :
-                                       // Chrome on Windows or Linux
+
+               switch ( profile.name ) {
+                       case 'chrome':
+                       case 'opera':
+                               if ( profile.name === 'opera' && profile.versionNumber < 15 ) {
+                                       accessKeyModifiers = [ 'shift', 'esc' ];
+                               } else if ( profile.platform === 'mac' ) {
+                                       accessKeyModifiers = [ 'ctrl', 'option' ];
+                               } else {
+                                       // Chrome/Opera on Windows or Linux
                                        // (both alt- and alt-shift work, but alt with E, D, F etc does not
                                        // work since they are browser shortcuts)
-                                       [ 'alt', 'shift' ]
-                       );
-
-               // Non-Windows Safari with webkit_version > 526
-               } else if ( profile.platform !== 'win' &&
-                       profile.name === 'safari' &&
-                       profile.layoutVersion > 526
-               ) {
-                       accessKeyModifiers = [ 'ctrl', 'alt' ];
-
-               // Safari/Konqueror on any platform, or any browser on Mac
-               // (but not Safari on Windows)
-               } else if (
-                       !( profile.platform === 'win' && profile.name === 'safari' ) &&
-                       (
-                               profile.name === 'safari' ||
-                               profile.platform === 'mac' ||
-                               profile.name === 'konqueror'
-                       )
-               ) {
-                       accessKeyModifiers = [ 'ctrl' ];
-
-               // Firefox/Iceweasel 2.x and later
-               } else if (
-                       ( profile.name === 'firefox' || profile.name === 'iceweasel' ) &&
-                       profile.versionBase > '1'
-               ) {
-                       accessKeyModifiers = [ 'alt', 'shift' ];
+                                       accessKeyModifiers = [ 'alt', 'shift' ];
+                               }
+                               break;
+                       case 'firefox':
+                       case 'iceweasel':
+                               if ( profile.versionBase < 2 ) {
+                                       // Before v2, Firefox used alt, though it was rebindable in about:config
+                                       accessKeyModifiers = [ 'alt' ];
+                               } else {
+                                       if ( profile.platform === 'mac' ) {
+                                               if ( profile.versionNumber < 14 ) {
+                                                       accessKeyModifiers = [ 'ctrl' ];
+                                               } else {
+                                                       accessKeyModifiers = [ 'ctrl', 'option' ];
+                                               }
+                                       } else {
+                                               accessKeyModifiers = [ 'alt', 'shift' ];
+                                       }
+                               }
+                               break;
+                       case 'safari':
+                       case 'konqueror':
+                               if ( profile.platform === 'win' ) {
+                                       accessKeyModifiers = [ 'alt' ];
+                               } else {
+                                       if ( profile.layoutVersion > 526 ) {
+                                               // Non-Windows Safari with webkit_version > 526
+                                               accessKeyModifiers = [ 'ctrl', profile.platform === 'mac' ? 'option' : 'alt' ];
+                                       } else {
+                                               accessKeyModifiers = [ 'ctrl' ];
+                                       }
+                               }
+                               break;
+                       case 'msie':
+                       case 'edge':
+                               accessKeyModifiers = [ 'alt' ];
+                               break;
+                       default:
+                               accessKeyModifiers = profile.platform === 'mac' ? [ 'ctrl' ] : [ 'alt' ];
+                               break;
                }
 
                // cache modifiers
diff --git a/resources/src/mediawiki.rcfilters/dm/mw.rcfilters.dm.FilterItem.js b/resources/src/mediawiki.rcfilters/dm/mw.rcfilters.dm.FilterItem.js
new file mode 100644 (file)
index 0000000..63db0ea
--- /dev/null
@@ -0,0 +1,103 @@
+( function ( mw ) {
+       /**
+        * Filter item model
+        *
+        * @mixins OO.EventEmitter
+        *
+        * @constructor
+        * @param {string} name Filter name
+        * @param {Object} config Configuration object
+        * @cfg {string} [group] The group this item belongs to
+        * @cfg {string} [label] The label for the filter
+        * @cfg {string} [description] The description of the filter
+        * @cfg {boolean} [selected] Filter is selected
+        */
+       mw.rcfilters.dm.FilterItem = function MwRcfiltersDmFilterItem( name, config ) {
+               config = config || {};
+
+               // Mixin constructor
+               OO.EventEmitter.call( this );
+
+               this.name = name;
+               this.group = config.group || '';
+               this.label = config.label || this.name;
+               this.description = config.description;
+
+               this.selected = !!config.selected;
+       };
+
+       /* Initialization */
+
+       OO.initClass( mw.rcfilters.dm.FilterItem );
+       OO.mixinClass( mw.rcfilters.dm.FilterItem, OO.EventEmitter );
+
+       /* Events */
+
+       /**
+        * @event update
+        *
+        * The state of this filter has changed
+        */
+
+       /* Methods */
+
+       /**
+        * Get the name of this filter
+        *
+        * @return {string} Filter name
+        */
+       mw.rcfilters.dm.FilterItem.prototype.getName = function () {
+               return this.name;
+       };
+
+       /**
+        * Get the group name this filter belongs to
+        *
+        * @return {string} Filter group name
+        */
+       mw.rcfilters.dm.FilterItem.prototype.getGroup = function () {
+               return this.group;
+       };
+
+       /**
+        * Get the label of this filter
+        *
+        * @return {string} Filter label
+        */
+       mw.rcfilters.dm.FilterItem.prototype.getLabel = function () {
+               return this.label;
+       };
+
+       /**
+        * Get the description of this filter
+        *
+        * @return {string} Filter description
+        */
+       mw.rcfilters.dm.FilterItem.prototype.getDescription = function () {
+               return this.description;
+       };
+
+       /**
+        * Get the selected state of this filter
+        *
+        * @return {boolean} Filter is selected
+        */
+       mw.rcfilters.dm.FilterItem.prototype.isSelected = function () {
+               return this.selected;
+       };
+
+       /**
+        * Toggle the selected state of the item
+        *
+        * @param {boolean} [isSelected] Filter is selected
+        * @fires update
+        */
+       mw.rcfilters.dm.FilterItem.prototype.toggleSelected = function ( isSelected ) {
+               isSelected = isSelected === undefined ? !this.selected : isSelected;
+
+               if ( this.selected !== isSelected ) {
+                       this.selected = isSelected;
+                       this.emit( 'update' );
+               }
+       };
+}( mediaWiki ) );
diff --git a/resources/src/mediawiki.rcfilters/dm/mw.rcfilters.dm.FiltersViewModel.js b/resources/src/mediawiki.rcfilters/dm/mw.rcfilters.dm.FiltersViewModel.js
new file mode 100644 (file)
index 0000000..3217d0d
--- /dev/null
@@ -0,0 +1,342 @@
+( function ( mw, $ ) {
+       /**
+        * View model for the filters selection and display
+        *
+        * @mixins OO.EventEmitter
+        * @mixins OO.EmitterList
+        *
+        * @constructor
+        */
+       mw.rcfilters.dm.FiltersViewModel = function MwRcfiltersDmFiltersViewModel() {
+               // Mixin constructor
+               OO.EventEmitter.call( this );
+               OO.EmitterList.call( this );
+
+               this.groups = {};
+
+               // Events
+               this.aggregate( { update: 'itemUpdate' } );
+       };
+
+       /* Initialization */
+       OO.initClass( mw.rcfilters.dm.FiltersViewModel );
+       OO.mixinClass( mw.rcfilters.dm.FiltersViewModel, OO.EventEmitter );
+       OO.mixinClass( mw.rcfilters.dm.FiltersViewModel, OO.EmitterList );
+
+       /* Events */
+
+       /**
+        * @event initialize
+        *
+        * Filter list is initialized
+        */
+
+       /**
+        * @event itemUpdate
+        * @param {mw.rcfilters.dm.FilterItem} item Filter item updated
+        *
+        * Filter item has changed
+        */
+
+       /* Methods */
+
+       /**
+        * Set filters and preserve a group relationship based on
+        * the definition given by an object
+        *
+        * @param {Object} filters Filter group definition
+        */
+       mw.rcfilters.dm.FiltersViewModel.prototype.initializeFilters = function ( filters ) {
+               var i, filterItem,
+                       model = this,
+                       items = [];
+
+               // Reset
+               this.clearItems();
+               this.groups = {};
+
+               $.each( filters, function ( group, data ) {
+                       model.groups[ group ] = model.groups[ group ] || {};
+                       model.groups[ group ].filters = model.groups[ group ].filters || [];
+
+                       model.groups[ group ].title = data.title;
+                       model.groups[ group ].type = data.type;
+                       model.groups[ group ].separator = data.separator || '|';
+
+                       for ( i = 0; i < data.filters.length; i++ ) {
+                               filterItem = new mw.rcfilters.dm.FilterItem( data.filters[ i ].name, {
+                                       group: group,
+                                       label: data.filters[ i ].label,
+                                       description: data.filters[ i ].description,
+                                       selected: data.filters[ i ].selected
+                               } );
+
+                               model.groups[ group ].filters.push( filterItem );
+                               items.push( filterItem );
+                       }
+               } );
+
+               this.addItems( items );
+               this.emit( 'initialize' );
+       };
+
+       /**
+        * Get the names of all available filters
+        *
+        * @return {string[]} An array of filter names
+        */
+       mw.rcfilters.dm.FiltersViewModel.prototype.getFilterNames = function () {
+               return this.getItems().map( function ( item ) { return item.getName(); } );
+       };
+
+       /**
+        * Get the object that defines groups and their filter items.
+        * The structure of this response:
+        * {
+        *   groupName: {
+        *     title: {string} Group title
+        *     type: {string} Group type
+        *     filters: {string[]} Filters in the group
+        *   }
+        * }
+        *
+        * @return {Object} Filter groups
+        */
+       mw.rcfilters.dm.FiltersViewModel.prototype.getFilterGroups = function () {
+               return this.groups;
+       };
+
+       /**
+        * Get the current state of the filters
+        *
+        * @return {Object} Filters current state
+        */
+       mw.rcfilters.dm.FiltersViewModel.prototype.getState = function () {
+               var i,
+                       items = this.getItems(),
+                       result = {};
+
+               for ( i = 0; i < items.length; i++ ) {
+                       result[ items[ i ].getName() ] = items[ i ].isSelected();
+               }
+
+               return result;
+       };
+
+       /**
+        * Analyze the groups and their filters and output an object representing
+        * the state of the parameters they represent.
+        *
+        * @return {Object} Parameter state object
+        */
+       mw.rcfilters.dm.FiltersViewModel.prototype.getParametersFromFilters = function () {
+               var i, filterItems, anySelected, values,
+                       result = {},
+                       groupItems = this.getFilterGroups();
+
+               $.each( groupItems, function ( group, data ) {
+                       filterItems = data.filters;
+
+                       if ( data.type === 'send_unselected_if_any' ) {
+                               // First, check if any of the items are selected at all.
+                               // If none is selected, we're treating it as if they are
+                               // all false
+                               anySelected = filterItems.some( function ( filterItem ) {
+                                       return filterItem.isSelected();
+                               } );
+
+                               // Go over the items and define the correct values
+                               for ( i = 0; i < filterItems.length; i++ ) {
+                                       result[ filterItems[ i ].getName() ] = anySelected ?
+                                               Number( !filterItems[ i ].isSelected() ) : 0;
+                               }
+                       } else if ( data.type === 'string_options' ) {
+                               values = [];
+                               for ( i = 0; i < filterItems.length; i++ ) {
+                                       if ( filterItems[ i ].isSelected() ) {
+                                               values.push( filterItems[ i ].getName() );
+                                       }
+                               }
+
+                               if ( values.length === 0 || values.length === filterItems.length ) {
+                                       result[ group ] = 'all';
+                               } else {
+                                       result[ group ] = values.join( data.separator );
+                               }
+                       }
+               } );
+
+               return result;
+       };
+
+       /**
+        * Sanitize value group of a string_option groups type
+        * Remove duplicates and make sure to only use valid
+        * values.
+        *
+        * @param {string} groupName Group name
+        * @param {string[]} valueArray Array of values
+        * @return {string[]} Array of valid values
+        */
+       mw.rcfilters.dm.FiltersViewModel.prototype.sanitizeStringOptionGroup = function( groupName, valueArray ) {
+               var result = [],
+                       validNames = this.groups[ groupName ].filters.map( function ( filterItem ) {
+                               return filterItem.getName();
+                       } );
+
+               if ( valueArray.indexOf( 'all' ) > -1 ) {
+                       // If anywhere in the values there's 'all', we
+                       // treat it as if only 'all' was selected.
+                       // Example: param=valid1,valid2,all
+                       // Result: param=all
+                       return [ 'all' ];
+               }
+
+               // Get rid of any dupe and invalid parameter, only output
+               // valid ones
+               // Example: param=valid1,valid2,invalid1,valid1
+               // Result: param=valid1,valid2
+               valueArray.forEach( function ( value ) {
+                       if (
+                               validNames.indexOf( value ) > -1 &&
+                               result.indexOf( value ) === -1
+                       ) {
+                               result.push( value );
+                       }
+               } );
+
+               return result;
+       };
+
+       /**
+        * This is the opposite of the #getParametersFromFilters method; this goes over
+        * the parameters and translates into a selected/unselected value in the filters.
+        *
+        * @param {Object} params Parameters query object
+        * @return {Object} Filter state object
+        */
+       mw.rcfilters.dm.FiltersViewModel.prototype.getFiltersFromParameters = function ( params ) {
+               var i, filterItem,
+                       groupMap = {},
+                       model = this,
+                       base = this.getParametersFromFilters(),
+                       // Start with current state
+                       result = this.getState();
+
+               params = $.extend( {}, base, params );
+
+               $.each( params, function ( paramName, paramValue ) {
+                       // Find the filter item
+                       filterItem = model.getItemByName( paramName );
+                       // Ignore if no filter item exists
+                       if ( filterItem ) {
+                               groupMap[ filterItem.getGroup() ] = groupMap[ filterItem.getGroup() ] || {};
+
+                               // Mark the group if it has any items that are selected
+                               groupMap[ filterItem.getGroup() ].hasSelected = (
+                                       groupMap[ filterItem.getGroup() ].hasSelected ||
+                                       !!Number( paramValue )
+                               );
+
+                               // Add the relevant filter into the group map
+                               groupMap[ filterItem.getGroup() ].filters = groupMap[ filterItem.getGroup() ].filters || [];
+                               groupMap[ filterItem.getGroup() ].filters.push( filterItem );
+                       } else if ( model.groups.hasOwnProperty( paramName ) ) {
+                               // This parameter represents a group (values are the filters)
+                               // this is equivalent to checking if the group is 'string_options'
+                               groupMap[ paramName ] = { filters: model.groups[ paramName ].filters };
+                       }
+               } );
+
+               // Now that we know the groups' selection states, we need to go over
+               // the filters in the groups and mark their selected states appropriately
+               $.each( groupMap, function ( group, data ) {
+                       var paramValues, filterItem,
+                               allItemsInGroup = data.filters;
+
+                       if ( model.groups[ group ].type === 'send_unselected_if_any' ) {
+                               for ( i = 0; i < allItemsInGroup.length; i++ ) {
+                                       filterItem = allItemsInGroup[ i ];
+
+                                       result[ filterItem.getName() ] = data.hasSelected ?
+                                               // Flip the definition between the parameter
+                                               // state and the filter state
+                                               // This is what the 'toggleSelected' value of the filter is
+                                               !Number( params[ filterItem.getName() ] ) :
+                                               // Otherwise, there are no selected items in the
+                                               // group, which means the state is false
+                                               false;
+                               }
+                       } else if ( model.groups[ group ].type === 'string_options' ) {
+                               paramValues = model.sanitizeStringOptionGroup( group, params[ group ].split( model.groups[ group ].separator ) );
+
+                               for ( i = 0; i < allItemsInGroup.length; i++ ) {
+                                       filterItem = allItemsInGroup[ i ];
+
+                                       result[ filterItem.getName() ] = (
+                                                       // If it is the word 'all'
+                                                       paramValues.length === 1 && paramValues[ 0 ] === 'all' ||
+                                                       // All values are written
+                                                       paramValues.length === model.groups[ group ].filters.length
+                                               ) ?
+                                               // All true (either because all values are written or the term 'all' is written)
+                                               // is the same as all filters set to false
+                                               false :
+                                               // Otherwise, the filter is selected only if it appears in the parameter values
+                                               paramValues.indexOf( filterItem.getName() ) > -1;
+                               }
+                       }
+               } );
+               return result;
+       };
+
+       /**
+        * Get the item that matches the given name
+        *
+        * @param {string} name Filter name
+        * @return {mw.rcfilters.dm.FilterItem} Filter item
+        */
+       mw.rcfilters.dm.FiltersViewModel.prototype.getItemByName = function ( name ) {
+               return this.getItems().filter( function ( item ) {
+                       return name === item.getName();
+               } )[ 0 ];
+       };
+
+       /**
+        * Toggle selected state of items by their names
+        *
+        * @param {Object} filterDef Filter definitions
+        */
+       mw.rcfilters.dm.FiltersViewModel.prototype.updateFilters = function ( filterDef ) {
+               var name, filterItem;
+
+               for ( name in filterDef ) {
+                       filterItem = this.getItemByName( name );
+                       filterItem.toggleSelected( filterDef[ name ] );
+               }
+       };
+
+       /**
+        * Find items whose labels match the given string
+        *
+        * @param {string} str Search string
+        * @return {Object} An object of items to show
+        *  arranged by their group names
+        */
+       mw.rcfilters.dm.FiltersViewModel.prototype.findMatches = function ( str ) {
+               var i,
+                       result = {},
+                       items = this.getItems();
+
+               // Normalize so we can search strings regardless of case
+               str = str.toLowerCase();
+               for ( i = 0; i < items.length; i++ ) {
+                       if ( items[ i ].getLabel().toLowerCase().indexOf( str ) > -1 ) {
+                               result[ items[ i ].getGroup() ] = result[ items[ i ].getGroup() ] || [];
+                               result[ items[ i ].getGroup() ].push( items[ i ] );
+                       }
+               }
+               return result;
+       };
+
+}( mediaWiki, jQuery ) );
diff --git a/resources/src/mediawiki.rcfilters/mw.rcfilters.Controller.js b/resources/src/mediawiki.rcfilters/mw.rcfilters.Controller.js
new file mode 100644 (file)
index 0000000..ea44b8b
--- /dev/null
@@ -0,0 +1,57 @@
+( function ( mw ) {
+       /**
+        * Controller for the filters in Recent Changes
+        *
+        * @param {mw.rcfilters.dm.FiltersViewModel} model View model
+        */
+       mw.rcfilters.Controller = function MwRcfiltersController( model ) {
+               this.model = model;
+
+               // TODO: When we are ready, update the URL when a filter is updated
+               // this.model.connect( this, { itemUpdate: 'updateURL' } );
+       };
+
+       /* Initialization */
+       OO.initClass( mw.rcfilters.Controller );
+
+       /**
+        * Initialize the filter and parameter states
+        */
+       mw.rcfilters.Controller.prototype.initialize = function () {
+               var uri = new mw.Uri();
+
+               this.model.updateFilters(
+                       // Translate the url params to filter select states
+                       this.model.getFiltersFromParameters( uri.query )
+               );
+       };
+
+       /**
+        * Update the state of a filter
+        *
+        * @param {string} filterName Filter name
+        * @param {boolean} isSelected Filter selected state
+        */
+       mw.rcfilters.Controller.prototype.updateFilter = function ( filterName, isSelected ) {
+               var obj = {};
+
+               obj[ filterName ] = isSelected;
+               this.model.updateFilters( obj );
+       };
+
+       /**
+        * Update the URL of the page to reflect current filters
+        */
+       mw.rcfilters.Controller.prototype.updateURL = function () {
+               var uri = new mw.Uri();
+
+               // Add to existing queries in URL
+               // TODO: Clean up the list of filters; perhaps 'falsy' filters
+               // shouldn't appear at all? Or compare to existing query string
+               // and see if current state of a specific filter is needed?
+               uri.extend( this.model.getParametersFromFilters() );
+
+               // Update the URL itself
+               window.history.pushState( { tag: 'rcfilters' }, document.title, uri.toString() );
+       };
+}( mediaWiki ) );
diff --git a/resources/src/mediawiki.rcfilters/mw.rcfilters.init.js b/resources/src/mediawiki.rcfilters/mw.rcfilters.init.js
new file mode 100644 (file)
index 0000000..679215b
--- /dev/null
@@ -0,0 +1,108 @@
+/*!
+ * JavaScript for Special:RecentChanges
+ */
+( function ( mw, $ ) {
+       /**
+        * @class mw.rcfilters
+        * @singleton
+        */
+       var rcfilters = {
+               /** */
+               init: function () {
+                       var model = new mw.rcfilters.dm.FiltersViewModel(),
+                               controller = new mw.rcfilters.Controller( model ),
+                               widget = new mw.rcfilters.ui.FilterWrapperWidget( controller, model );
+
+                       model.initializeFilters( {
+                               authorship: {
+                                       title: mw.msg( 'rcfilters-filtergroup-authorship' ),
+                                       // Type 'send_unselected_if_any' means that the controller will go over
+                                       // all unselected filters in the group and use their parameters
+                                       // as truthy in the query string.
+                                       // This is to handle the "negative" filters. We are showing users
+                                       // a positive message ("Show xxx") but the filters themselves are
+                                       // based on "hide YYY". The purpose of this is to correctly map
+                                       // the functionality to the UI, whether we are dealing with 2
+                                       // parameters in the group or more.
+                                       type: 'send_unselected_if_any',
+                                       filters: [
+                                               {
+                                                       name: 'hidemyself',
+                                                       label: mw.msg( 'rcfilters-filter-editsbyself-label' ),
+                                                       description: mw.msg( 'rcfilters-filter-editsbyself-description' )
+                                               },
+                                               {
+                                                       name: 'hidebyothers',
+                                                       label: mw.msg( 'rcfilters-filter-editsbyother-label' ),
+                                                       description: mw.msg( 'rcfilters-filter-editsbyother-description' )
+                                               }
+                                       ]
+                               },
+                               userExpLevel: {
+                                       title: mw.msg( 'rcfilters-filtergroup-userExpLevel' ),
+                                       // Type 'string_options' means that the group is evaluated by
+                                       // string values separated by comma; for example, param=opt1,opt2
+                                       // If all options are selected they are replaced by the term "all".
+                                       // The filters are the values for the parameter defined by the group.
+                                       // ** In this case, the parameter name is the group name. **
+                                       type: 'string_options',
+                                       separator: ',',
+                                       filters: [
+                                               {
+                                                       name: 'newcomer',
+                                                       label: mw.msg( 'rcfilters-filter-userExpLevel-newcomer-label' ),
+                                                       description: mw.msg( 'rcfilters-filter-userExpLevel-newcomer-description' )
+                                               },
+                                               {
+                                                       name: 'learner',
+                                                       label: mw.msg( 'rcfilters-filter-userExpLevel-learner-label' ),
+                                                       description: mw.msg( 'rcfilters-filter-userExpLevel-learner-description' )
+                                               },
+                                               {
+                                                       name: 'experienced',
+                                                       label: mw.msg( 'rcfilters-filter-userExpLevel-experienced-label' ),
+                                                       description: mw.msg( 'rcfilters-filter-userExpLevel-experienced-description' )
+                                               }
+                                       ]
+                               }
+                       } );
+
+                       $( '.rcoptions' ).before( widget.$element );
+
+                       // Initialize values
+                       controller.initialize();
+
+                       $( '.rcoptions form' ).submit( function () {
+                               var $form = $( this );
+
+                               // Get current filter values
+                               $.each( model.getParametersFromFilters(), function ( paramName, paramValue ) {
+                                       var $existingInput = $form.find( 'input[name=' + paramName + ']' );
+                                       // Check if the hidden input already exists
+                                       // This happens if the parameter was already given
+                                       // on load
+                                       if ( $existingInput.length ) {
+                                               // Update the value
+                                               $existingInput.val( paramValue );
+                                       } else {
+                                               // Append hidden fields with filter values
+                                               $form.append(
+                                                       $( '<input>' )
+                                                               .attr( 'type', 'hidden' )
+                                                               .attr( 'name', paramName )
+                                                               .val( paramValue )
+                                               );
+                                       }
+                               } );
+
+                               // Continue the submission process
+                               return true;
+                       } );
+               }
+       };
+
+       $( rcfilters.init );
+
+       module.exports = rcfilters;
+
+}( mediaWiki, jQuery ) );
diff --git a/resources/src/mediawiki.rcfilters/mw.rcfilters.js b/resources/src/mediawiki.rcfilters/mw.rcfilters.js
new file mode 100644 (file)
index 0000000..3ddb5a0
--- /dev/null
@@ -0,0 +1,3 @@
+( function ( mw ) {
+       mw.rcfilters = { dm: {}, ui: {} };
+}( mediaWiki ) );
diff --git a/resources/src/mediawiki.rcfilters/styles/mw.rcfilters.less b/resources/src/mediawiki.rcfilters/styles/mw.rcfilters.less
new file mode 100644 (file)
index 0000000..7f71c0c
--- /dev/null
@@ -0,0 +1,5 @@
+.rcshowhidemine {
+       // HACK: Hide this filter since it already appears in
+       // the new filter drop-down.
+       display: none;
+}
diff --git a/resources/src/mediawiki.rcfilters/styles/mw.rcfilters.ui.FilterCapsuleMultiselectWidget.less b/resources/src/mediawiki.rcfilters/styles/mw.rcfilters.ui.FilterCapsuleMultiselectWidget.less
new file mode 100644 (file)
index 0000000..4e55add
--- /dev/null
@@ -0,0 +1,11 @@
+.mw-rcfilters-ui-filterCapsuleMultiselectWidget {
+       &-content-title {
+               font-weight: bold;
+               color: #54595d;
+       }
+
+       .oo-ui-capsuleItemWidget {
+               color: #222;
+               background-color: #fff;
+       }
+}
diff --git a/resources/src/mediawiki.rcfilters/styles/mw.rcfilters.ui.FilterGroupWidget.less b/resources/src/mediawiki.rcfilters/styles/mw.rcfilters.ui.FilterGroupWidget.less
new file mode 100644 (file)
index 0000000..70982d4
--- /dev/null
@@ -0,0 +1,20 @@
+.mw-rcfilters-ui-filterGroupWidget {
+       padding-bottom: 0.5em;
+
+       &-title {
+               // TODO: Unify colors with official design palette
+               background: #eaecf0;
+               padding: 0.5em 0.75em;
+               color: #555a5d;
+       }
+
+       &-invalid-notice {
+               padding: 0.5em;
+               font-style: italic;
+               display: none;
+
+               .mw-rcfilters-ui-filterGroupWidget-invalid & {
+                       display: block;
+               }
+       }
+}
diff --git a/resources/src/mediawiki.rcfilters/styles/mw.rcfilters.ui.FilterItemWidget.less b/resources/src/mediawiki.rcfilters/styles/mw.rcfilters.ui.FilterItemWidget.less
new file mode 100644 (file)
index 0000000..ad0b816
--- /dev/null
@@ -0,0 +1,18 @@
+.mw-rcfilters-ui-filterItemWidget {
+       padding-left: 0.5em;
+
+       &-label {
+               &-title {
+                       font-weight: bold;
+                       font-size: 1.2em;
+                       color: #222;
+               }
+               &-desc {
+                       color: #464a4f;
+               }
+       }
+
+       .oo-ui-fieldLayout.oo-ui-fieldLayout-align-inline {
+               margin-bottom: 0 !important;
+       }
+}
diff --git a/resources/src/mediawiki.rcfilters/styles/mw.rcfilters.ui.FilterWrapperWidget.less b/resources/src/mediawiki.rcfilters/styles/mw.rcfilters.ui.FilterWrapperWidget.less
new file mode 100644 (file)
index 0000000..a610e8f
--- /dev/null
@@ -0,0 +1,33 @@
+.mw-rcfilters-ui-filterWrapperWidget {
+       width: 100%;
+
+       .oo-ui-capsuleMultiselectWidget {
+               max-width: none;
+
+               &.oo-ui-widget-enabled .oo-ui-capsuleMultiselectWidget-handle {
+                       // TODO: Unify colors with official design palette
+                       background-color: #f8f9fa;
+                       border: 1px solid #a2a9b1;
+                       min-height: 5.5em;
+                       padding: 0.75em;
+
+               }
+       }
+
+       &-popup {
+               // We have to override OOUI's definition, which is set
+               // on the inline style of the popup
+               margin-top: 2em !important;
+               max-width: 650px;
+       }
+
+       &-search {
+               max-width: none;
+               margin-top: -0.5em;
+       }
+
+       &-capsule-invalid-filter {
+               // TODO: Unify colors with official design palette
+               background: red;
+       }
+}
diff --git a/resources/src/mediawiki.rcfilters/styles/mw.rcfilters.ui.FiltersListWidget.less b/resources/src/mediawiki.rcfilters/styles/mw.rcfilters.ui.FiltersListWidget.less
new file mode 100644 (file)
index 0000000..b874e0f
--- /dev/null
@@ -0,0 +1,16 @@
+.mw-rcfilters-ui-filtersListWidget {
+       &-title {
+               font-size: 1.2em;
+               padding: 0.75em;
+               // TODO: Unify colors with official design palette
+               color: #54595d;
+               border-bottom: 1px solid #c8ccd1;
+               background: #f8f9fa;
+       }
+
+       &-noresults {
+               padding: 0.5em;
+               // TODO: Unify colors with official design palette
+               color: #666;
+       }
+}
diff --git a/resources/src/mediawiki.rcfilters/ui/mw.rcfilters.ui.FilterCapsuleMultiselectWidget.js b/resources/src/mediawiki.rcfilters/ui/mw.rcfilters.ui.FilterCapsuleMultiselectWidget.js
new file mode 100644 (file)
index 0000000..df6cf8b
--- /dev/null
@@ -0,0 +1,91 @@
+( function ( mw, $ ) {
+       /**
+        * Filter-specific CapsuleMultiselectWidget
+        *
+        * @extends OO.ui.CapsuleMultiselectWidget
+        *
+        * @constructor
+        * @param {OO.ui.InputWidget} filterInput A filter input that focuses the capsule widget
+        * @param {Object} config Configuration object
+        */
+       mw.rcfilters.ui.FilterCapsuleMultiselectWidget = function MwRcfiltersUiFilterCapsuleMultiselectWidget( filterInput, config ) {
+               // Parent
+               mw.rcfilters.ui.FilterCapsuleMultiselectWidget.parent.call( this, $.extend( {
+                       $autoCloseIgnore: filterInput.$element
+               }, config ) );
+
+               this.filterInput = filterInput;
+
+               this.$content.prepend(
+                       $( '<div>' )
+                               .addClass( 'mw-rcfilters-ui-filterCapsuleMultiselectWidget-content-title' )
+                               .text( mw.msg( 'rcfilters-activefilters' ) )
+               );
+
+               // Events
+               // Add the filterInput as trigger
+               this.filterInput.$input
+                       .on( 'focus', this.onFocusForPopup.bind( this ) );
+
+               this.$element
+                       .addClass( 'mw-rcfilters-ui-filterCapsuleMultiselectWidget' );
+       };
+
+       /* Initialization */
+
+       OO.inheritClass( mw.rcfilters.ui.FilterCapsuleMultiselectWidget, OO.ui.CapsuleMultiselectWidget );
+
+       /* Events */
+
+       /**
+        * @event remove
+        * @param {string[]} filters Array of names of removed filters
+        *
+        * Filters were removed
+        */
+
+       /* Methods */
+
+       /**
+        * @inheritdoc
+        */
+       mw.rcfilters.ui.FilterCapsuleMultiselectWidget.prototype.onFocusForPopup = function () {
+               // Override this method; we don't want to focus on the popup, and we
+               // don't want to bind the size to the handle.
+               if ( !this.isDisabled() ) {
+                       this.popup.toggle( true );
+               }
+       };
+
+       /**
+        * @inheritdoc
+        */
+       mw.rcfilters.ui.FilterCapsuleMultiselectWidget.prototype.removeItems = function ( items ) {
+               // Parent
+               mw.rcfilters.ui.FilterCapsuleMultiselectWidget.parent.prototype.removeItems.call( this, items );
+
+               this.emit( 'remove', items.map( function ( item ) { return item.getData(); } ) );
+       };
+
+       /**
+        * @inheritdoc
+        */
+       mw.rcfilters.ui.FilterCapsuleMultiselectWidget.prototype.onKeyDown = function () {};
+
+       /**
+        * @inheritdoc
+        */
+       mw.rcfilters.ui.FilterCapsuleMultiselectWidget.prototype.onPopupFocusOut = function () {};
+
+       /**
+        * @inheritdoc
+        */
+       mw.rcfilters.ui.FilterCapsuleMultiselectWidget.prototype.clearInput = function () {
+               if ( this.filterInput ) {
+                       this.filterInput.setValue( '' );
+               }
+               this.menu.toggle( false );
+               this.menu.selectItem();
+               this.menu.highlightItem();
+       };
+}( mediaWiki, jQuery ) );
diff --git a/resources/src/mediawiki.rcfilters/ui/mw.rcfilters.ui.FilterGroupWidget.js b/resources/src/mediawiki.rcfilters/ui/mw.rcfilters.ui.FilterGroupWidget.js
new file mode 100644 (file)
index 0000000..92ae4d1
--- /dev/null
@@ -0,0 +1,51 @@
+( function ( mw, $ ) {
+       /**
+        * A group of filters
+        *
+        * @extends OO.ui.Widget
+        * @mixins OO.ui.mixin.GroupWidget
+        * @mixins OO.ui.mixin.LabelElement
+        *
+        * @constructor
+        * @param {string} name Group name
+        * @param {Object} config Configuration object
+        */
+       mw.rcfilters.ui.FilterGroupWidget = function MwRcfiltersUiFilterGroupWidget( name, config ) {
+               config = config || {};
+
+               // Parent
+               mw.rcfilters.ui.FilterGroupWidget.parent.call( this, config );
+               // Mixin constructors
+               OO.ui.mixin.GroupWidget.call( this, config );
+               OO.ui.mixin.LabelElement.call( this, $.extend( {}, config, {
+                       $label: $( '<div>' )
+                               .addClass( 'mw-rcfilters-ui-filterGroupWidget-title' )
+               } ) );
+
+               this.name = name;
+
+               this.$element
+                       .addClass( 'mw-rcfilters-ui-filterGroupWidget' )
+                       .append(
+                               this.$label,
+                               this.$group
+                                       .addClass( 'mw-rcfilters-ui-filterGroupWidget-group' )
+                       );
+       };
+
+       /* Initialization */
+
+       OO.inheritClass( mw.rcfilters.ui.FilterGroupWidget, OO.ui.Widget );
+       OO.mixinClass( mw.rcfilters.ui.FilterGroupWidget, OO.ui.mixin.GroupWidget );
+       OO.mixinClass( mw.rcfilters.ui.FilterGroupWidget, OO.ui.mixin.LabelElement );
+
+       /**
+        * Get the group name
+        *
+        * @return {string} Group name
+        */
+       mw.rcfilters.ui.FilterGroupWidget.prototype.getName = function () {
+               return this.name;
+       };
+
+}( mediaWiki, jQuery ) );
diff --git a/resources/src/mediawiki.rcfilters/ui/mw.rcfilters.ui.FilterItemWidget.js b/resources/src/mediawiki.rcfilters/ui/mw.rcfilters.ui.FilterItemWidget.js
new file mode 100644 (file)
index 0000000..b77df3b
--- /dev/null
@@ -0,0 +1,92 @@
+( function ( mw, $ ) {
+       /**
+        * A widget representing a single toggle filter
+        *
+        * @extends OO.ui.Widget
+        *
+        * @constructor
+        * @param {mw.rcfilters.Controller} controller RCFilters controller
+        * @param {mw.rcfilters.dm.FilterItem} model Filter item model
+        * @param {Object} config Configuration object
+        */
+       mw.rcfilters.ui.FilterItemWidget = function MwRcfiltersUiFilterItemWidget( controller, model, config ) {
+               var layout,
+                       $label = $( '<div>' )
+                               .addClass( 'mw-rcfilters-ui-filterItemWidget-label' );
+
+               config = config || {};
+
+               // Parent
+               mw.rcfilters.ui.FilterItemWidget.parent.call( this, config );
+
+               this.controller = controller;
+               this.model = model;
+
+               this.checkboxWidget = new OO.ui.CheckboxInputWidget( {
+                       value: this.model.getName(),
+                       selected: this.model.isSelected()
+               } );
+
+               $label.append(
+                       $( '<div>' )
+                               .addClass( 'mw-rcfilters-ui-filterItemWidget-label-title' )
+                               .text( this.model.getLabel() )
+               );
+               if ( this.model.getDescription() ) {
+                       $label.append(
+                               $( '<div>' )
+                                       .addClass( 'mw-rcfilters-ui-filterItemWidget-label-desc' )
+                                       .text( this.model.getDescription() )
+                       );
+               }
+
+               layout = new OO.ui.FieldLayout( this.checkboxWidget, {
+                       label: $label,
+                       align: 'inline'
+               } );
+
+               // Event
+               this.checkboxWidget.connect( this, { change: 'onCheckboxChange' } );
+               this.model.connect( this, { update: 'onModelUpdate' } );
+
+               this.$element
+                       .addClass( 'mw-rcfilters-ui-filterItemWidget' )
+                       .append(
+                               layout.$element
+                       );
+       };
+
+       /* Initialization */
+
+       OO.inheritClass( mw.rcfilters.ui.FilterItemWidget, OO.ui.Widget );
+
+       /* Methods */
+
+       /**
+        * Respond to checkbox change.
+        * NOTE: This event is emitted both for deliberate user action and for
+        * a change that the code requests ('setSelected')
+        *
+        * @param {boolean} isSelected The checkbox is selected
+        */
+       mw.rcfilters.ui.FilterItemWidget.prototype.onCheckboxChange = function ( isSelected ) {
+               this.controller.updateFilter( this.model.getName(), isSelected );
+       };
+
+       /**
+        * Respond to item model update event
+        */
+       mw.rcfilters.ui.FilterItemWidget.prototype.onModelUpdate = function () {
+               this.checkboxWidget.setSelected( this.model.isSelected() );
+       };
+
+       /**
+        * Get the name of this filter
+        *
+        * @return {string} Filter name
+        */
+       mw.rcfilters.ui.FilterItemWidget.prototype.getName = function () {
+               return this.model.getName();
+       };
+
+}( mediaWiki, jQuery ) );
diff --git a/resources/src/mediawiki.rcfilters/ui/mw.rcfilters.ui.FilterWrapperWidget.js b/resources/src/mediawiki.rcfilters/ui/mw.rcfilters.ui.FilterWrapperWidget.js
new file mode 100644 (file)
index 0000000..3fcfc47
--- /dev/null
@@ -0,0 +1,130 @@
+( function ( mw ) {
+       /**
+        * List displaying all filter groups
+        *
+        * @extends OO.ui.Widget
+        * @mixins OO.ui.mixin.PendingElement
+        *
+        * @constructor
+        * @param {mw.rcfilters.Controller} controller Controller
+        * @param {mw.rcfilters.dm.FiltersViewModel} model View model
+        * @param {Object} config Configuration object
+        * @cfg {Object} [filters] A definition of the filter groups in this list
+        */
+       mw.rcfilters.ui.FilterWrapperWidget = function MwRcfiltersUiFilterWrapperWidget( controller, model, config ) {
+               config = config || {};
+
+               // Parent
+               mw.rcfilters.ui.FilterWrapperWidget.parent.call( this, config );
+               // Mixin constructors
+               OO.ui.mixin.PendingElement.call( this, config );
+
+               this.controller = controller;
+               this.model = model;
+               this.filtersInCapsule = [];
+
+               this.filterPopup = new mw.rcfilters.ui.FiltersListWidget(
+                       this.controller,
+                       this.model,
+                       {
+                               label: mw.msg( 'rcfilters-filterlist-title' )
+                       }
+               );
+
+               this.textInput = new OO.ui.TextInputWidget( {
+                       classes: [ 'mw-rcfilters-ui-filterWrapperWidget-search' ],
+                       icon: 'search',
+                       placeholder: mw.msg( 'rcfilters-search-placeholder' )
+               } );
+
+               this.capsule = new mw.rcfilters.ui.FilterCapsuleMultiselectWidget( this.textInput, {
+                       popup: {
+                               $content: this.filterPopup.$element,
+                               classes: [ 'mw-rcfilters-ui-filterWrapperWidget-popup' ]
+                       }
+               } );
+
+               // Events
+               this.model.connect( this, {
+                       initialize: 'onModelInitialize',
+                       itemUpdate: 'onModelItemUpdate'
+               } );
+               this.textInput.connect( this, {
+                       change: 'onTextInputChange'
+               } );
+               this.capsule.connect( this, {
+                       remove: 'onCapsuleRemoveItem'
+               } );
+
+               this.$element
+                       .addClass( 'mw-rcfilters-ui-filterWrapperWidget' )
+                       .append( this.capsule.$element, this.textInput.$element );
+       };
+
+       /* Initialization */
+
+       OO.inheritClass( mw.rcfilters.ui.FilterWrapperWidget, OO.ui.Widget );
+       OO.mixinClass( mw.rcfilters.ui.FilterWrapperWidget, OO.ui.mixin.PendingElement );
+
+       /**
+        * Respond to text input change
+        *
+        * @param {string} newValue Current value
+        */
+       mw.rcfilters.ui.FilterWrapperWidget.prototype.onTextInputChange = function ( newValue ) {
+               // Filter the results
+               this.filterPopup.filter( this.model.findMatches( newValue ) );
+       };
+
+       /**
+        * Respond to an event where an item is removed from the capsule.
+        * This is the case where a user actively removes a filter box from the capsule widget.
+        *
+        * @param {string[]} filterNames An array of filter names that were removed
+        */
+       mw.rcfilters.ui.FilterWrapperWidget.prototype.onCapsuleRemoveItem = function ( filterNames ) {
+               var filterItem,
+                       widget = this;
+
+               filterNames.forEach( function ( filterName ) {
+                       // Go over filters
+                       filterItem = widget.model.getItemByName( filterName );
+                       filterItem.toggleSelected( false );
+               } );
+       };
+
+       /**
+        * Respond to model update event and set up the available filters to choose
+        * from.
+        */
+       mw.rcfilters.ui.FilterWrapperWidget.prototype.onModelInitialize = function () {
+               var items,
+                       filters = this.model.getItems();
+
+               // Reset
+               this.capsule.getMenu().clearItems();
+
+               // Insert hidden options for the capsule to get its item data from
+               items = filters.map( function ( filterItem ) {
+                       return new OO.ui.MenuOptionWidget( {
+                               data: filterItem.getName(),
+                               label: filterItem.getLabel()
+                       } );
+               } );
+
+               this.capsule.getMenu().addItems( items );
+       };
+
+       /**
+        * Respond to model item update
+        *
+        * @param {mw.rcfilters.dm.FilterItem} item Filter item that was updated
+        */
+       mw.rcfilters.ui.FilterWrapperWidget.prototype.onModelItemUpdate = function ( item ) {
+               if ( item.isSelected() ) {
+                       this.capsule.addItemsFromData( [ item.getName() ] );
+               } else {
+                       this.capsule.removeItemsFromData( [ item.getName() ] );
+               }
+       };
+}( mediaWiki ) );
diff --git a/resources/src/mediawiki.rcfilters/ui/mw.rcfilters.ui.FiltersListWidget.js b/resources/src/mediawiki.rcfilters/ui/mw.rcfilters.ui.FiltersListWidget.js
new file mode 100644 (file)
index 0000000..f5ec1fc
--- /dev/null
@@ -0,0 +1,154 @@
+( function ( mw, $ ) {
+       /**
+        * List displaying all filter groups
+        *
+        * @extends OO.ui.Widget
+        * @mixins OO.ui.mixin.GroupWidget
+        * @mixins OO.ui.mixin.LabelElement
+        *
+        * @constructor
+        * @param {mw.rcfilters.Controller} controller Controller
+        * @param {mw.rcfilters.dm.FiltersViewModel} model View model
+        * @param {Object} config Configuration object
+        */
+       mw.rcfilters.ui.FiltersListWidget = function MwRcfiltersUiFiltersListWidget( controller, model, config ) {
+               config = config || {};
+
+               // Parent
+               mw.rcfilters.ui.FiltersListWidget.parent.call( this, config );
+               // Mixin constructors
+               OO.ui.mixin.GroupWidget.call( this, config );
+               OO.ui.mixin.LabelElement.call( this, $.extend( {}, config, {
+                       $label: $( '<div>' )
+                               .addClass( 'mw-rcfilters-ui-filtersListWidget-title' )
+               } ) );
+
+               this.controller = controller;
+               this.model = model;
+
+               this.noResultsLabel = new OO.ui.LabelWidget( {
+                       label: mw.msg( 'rcfilters-filterlist-noresults' ),
+                       classes: [ 'mw-rcfilters-ui-filtersListWidget-noresults' ]
+               } );
+
+               // Events
+               this.model.connect( this, {
+                       initialize: 'onModelInitialize'
+               } );
+
+               // Initialize
+               this.showNoResultsMessage( false );
+               this.$element
+                       .addClass( 'mw-rcfilters-ui-filtersListWidget' )
+                       .append(
+                               this.$label,
+                               this.$group
+                                       .addClass( 'mw-rcfilters-ui-filtersListWidget-group' ),
+                               this.noResultsLabel.$element
+                       );
+       };
+
+       /* Initialization */
+
+       OO.inheritClass( mw.rcfilters.ui.FiltersListWidget, OO.ui.Widget );
+       OO.mixinClass( mw.rcfilters.ui.FiltersListWidget, OO.ui.mixin.GroupWidget );
+       OO.mixinClass( mw.rcfilters.ui.FiltersListWidget, OO.ui.mixin.LabelElement );
+
+       /* Methods */
+
+       /**
+        * Respond to initialize event from the model
+        */
+       mw.rcfilters.ui.FiltersListWidget.prototype.onModelInitialize = function () {
+               var i, group, groupWidget,
+                       itemWidgets = [],
+                       groupWidgets = [],
+                       groups = this.model.getFilterGroups();
+
+               // Reset
+               this.clearItems();
+
+               for ( group in groups ) {
+                       groupWidget = new mw.rcfilters.ui.FilterGroupWidget( group, {
+                               label: groups[ group ].title
+                       } );
+                       groupWidgets.push( groupWidget );
+
+                       itemWidgets = [];
+                       if ( groups[ group ].filters ) {
+                               for ( i = 0; i < groups[ group ].filters.length; i++ ) {
+                                       itemWidgets.push(
+                                               new mw.rcfilters.ui.FilterItemWidget(
+                                                       this.controller,
+                                                       groups[ group ].filters[ i ],
+                                                       {
+                                                               label: groups[ group ].filters[ i ].getLabel(),
+                                                               description: groups[ group ].filters[ i ].getDescription()
+                                                       }
+                                               )
+                                       );
+                               }
+
+                               groupWidget.addItems( itemWidgets );
+                       }
+               }
+
+               this.addItems( groupWidgets );
+       };
+
+       /**
+        * Switch between showing the 'no results' message for filtering results or the result list.
+        *
+        * @param {boolean} showNoResults Show no results message
+        */
+       mw.rcfilters.ui.FiltersListWidget.prototype.showNoResultsMessage = function ( showNoResults ) {
+               this.noResultsLabel.toggle( !!showNoResults );
+               this.$group.toggleClass( 'oo-ui-element-hidden', !!showNoResults );
+       };
+
+       /**
+        * Show only the items matching with the models in the given list
+        *
+        * @param {Object} groupItems An object of items to show
+        *  arranged by their group names
+        */
+       mw.rcfilters.ui.FiltersListWidget.prototype.filter = function ( groupItems ) {
+               var i, j, groupName, itemWidgets,
+                       groupWidgets = this.getItems(),
+                       hasItemWithName = function ( itemArr, name ) {
+                               return !!itemArr.filter( function ( item ) {
+                                       return item.getName() === name;
+                               } ).length;
+                       };
+
+               if ( $.isEmptyObject( groupItems ) ) {
+                       // No results. Hide everything, show only 'no results'
+                       // message
+                       this.showNoResultsMessage( true );
+                       return;
+               }
+
+               this.showNoResultsMessage( false );
+               for ( i = 0; i < groupWidgets.length; i++ ) {
+                       groupName = groupWidgets[ i ].getName();
+
+                       // If this group widget is in the filtered results,
+                       // show it - otherwise, hide it
+                       groupWidgets[ i ].toggle( !!groupItems[ groupName ] );
+
+                       if ( !groupItems[ groupName ] ) {
+                               // Continue to next group
+                               continue;
+                       }
+
+                       // We have items to show
+                       itemWidgets = groupWidgets[ i ].getItems();
+                       for ( j = 0; j < itemWidgets.length; j++ ) {
+                               // Only show items that are in the filtered list
+                               itemWidgets[ j ].toggle(
+                                       hasItemWithName( groupItems[ groupName ], itemWidgets[ j ].getName() )
+                               );
+                       }
+               }
+       };
+}( mediaWiki, jQuery ) );
index a5cf1d8..543ece8 100644 (file)
                                                                        e.stopPropagation();
                                                                } );
                                                } );
+                                       }, function ( errorMsg ) {
+                                               booklet.getPage( 'upload' ).$element.msg( errorMsg );
+                                               return $.Deferred().resolve();
                                        } )
                                );
                        }
index c7ebfd8..f736036 100644 (file)
 
                return this.upload.getApi().then(
                        function ( api ) {
-                               return $.when(
-                                       booklet.upload.loadConfig().then(
-                                               null,
-                                               function ( errorMsg ) {
-                                                       booklet.getPage( 'upload' ).$element.msg( errorMsg );
-                                                       return $.Deferred().resolve();
-                                               }
-                                       ),
-                                       // If the user can't upload anything, don't give them the option to.
-                                       api.getUserInfo().then( function ( userInfo ) {
+                               // If the user can't upload anything, don't give them the option to.
+                               return api.getUserInfo().then(
+                                       function ( userInfo ) {
                                                if ( userInfo.rights.indexOf( 'upload' ) === -1 ) {
                                                        if ( mw.user.isAnon() ) {
                                                                booklet.getPage( 'upload' ).$element.msg( 'api-error-mustbeloggedin' );
                                                        }
                                                }
                                                return $.Deferred().resolve();
-                                       } )
-                               ).then(
-                                       null,
+                                       },
                                        // Always resolve, never reject
                                        function () { return $.Deferred().resolve(); }
                                );
index f6b6bce..3853a12 100644 (file)
@@ -530,6 +530,8 @@ Extra newlines between heading and content are swallowed
 
 !! test
 Heading with line break in nowiki
+!! options
+parsoid=wt2html
 !! wikitext
 == A <nowiki>B
 C</nowiki> ==
@@ -537,6 +539,9 @@ C</nowiki> ==
 <h2><span class="mw-headline" id="A_B.0AC">A B
 C</span><span class="mw-editsection"><span class="mw-editsection-bracket">[</span><a href="/index.php?title=Parser_test&amp;action=edit&amp;section=1" title="Edit section: A B&#10;C">edit</a><span class="mw-editsection-bracket">]</span></span></h2>
 
+!! html/parsoid
+<h2 id="A_B.0AC">A <span typeof="mw:Nowiki">B
+C</span> </h2>
 !! end
 
 !! test
@@ -6476,6 +6481,14 @@ parsoid=wt2html,html2html
 <span typeof="mw:Transclusion" data-mw='{"parts":[{"template":{"target":{"wt":"echo","href":"./Template:Echo"},"params":{"1":{"wt":"ho\">ha&lt;/div>"}},"i":0}}]}'>ho">ha</span>
 !! end
 
+!! test
+Break on | in element attribute name in template
+!! wikitext
+{{echo|<div cla|ss="hiho">ha</div>}}
+!! html/parsoid
+<p about="#mwt1" typeof="mw:Transclusion" data-parsoid='{"pi":[[{"k":"1"},{"k":"ss","named":true}]]}' data-mw='{"parts":[{"template":{"target":{"wt":"echo","href":"./Template:Echo"},"params":{"1":{"wt":"&lt;div cla"},"ss":{"wt":"\"hiho\">ha&lt;/div>"}},"i":0}}]}'>&lt;div cla</p>
+!! end
+
 !! test
 Don't break on | in extension attribute in template
 !! wikitext
@@ -10276,6 +10289,26 @@ Magic Word: {{SITENAME}}
 </p>
 !! end
 
+!! test
+Magic Word: {{PAGELANGUAGE}}
+!! options
+language=fr
+!! wikitext
+{{PAGELANGUAGE}}
+!! html
+<p>fr
+</p>
+!! end
+
+!! test
+Magic Word: {{PAGELANGUAGE}} on a page with no explicitly set language
+!! wikitext
+{{PAGELANGUAGE}}
+!! html
+<p>en
+</p>
+!! end
+
 !! test
 Case-sensitive magic words, when cased differently, should just be template transclusions
 !! wikitext
@@ -10933,7 +10966,8 @@ BUG 553: link with two variables in a piped link
 
 !! html/parsoid
 <table>
-<tbody><tr><td>[[<span about="#mwt5" typeof="mw:Param" data-parsoid='{"src":"{{{1}}}"}'>{{{1}}}</span>|<span about="#mwt2" typeof="mw:Param" data-parsoid='{"src":"{{{2}}}"}'>{{{2}}}</span>]]</td></tr>
+<tbody><tr><td>[[<span about="#mwt5" typeof="mw:Param" data-mw='{"parts":[{"templatearg":{"target":{"wt":"1"},"params":{},"i":0}}]}'>{{{1}}}</span>|<span about="#mwt2" typeof="mw:Param" data-mw='{"parts":[{"templatearg":{"target":{"wt":"2"},"params":{},"i":0}}]}'>{{{2}}}</span>]]</td></tr>
+</tbody></table>
 !! end
 
 # See: T2553
@@ -11625,7 +11659,7 @@ parsoid=wt2html
 |c
 |}
 !!html/parsoid
-<meta typeof="mw:Includes/IncludeOnly" data-parsoid='{"src":"&lt;includeonly>a&lt;/includeonly>"}'/><meta typeof="mw:Includes/IncludeOnly/End" data-parsoid='{"src":""}'/><table about="#mwt2" typeof="mw:ExpandedAttrs" data-parsoid='{"a":{"{{{b}}}":null},"sa":{"{{{b}}}":""}}' data-mw='{"attribs":[[{"txt":"{{{b}}}","html":"&lt;span about=\"#mwt1\" typeof=\"mw:Param\" data-parsoid=&#39;{\"dsr\":[31,38,null,null],\"src\":\"{{{b}}}\"}&#39;>{{{b}}}&lt;/span>"},{"html":""}]]}'>
+<meta typeof="mw:Includes/IncludeOnly" data-parsoid='{"src":"&lt;includeonly>a&lt;/includeonly>"}'/><meta typeof="mw:Includes/IncludeOnly/End" data-parsoid='{"src":""}'/><table about="#mwt2" typeof="mw:ExpandedAttrs" data-parsoid='{"a":{"{{{b}}}":null},"sa":{"{{{b}}}":""}}' data-mw='{"attribs":[[{"txt":"{{{b}}}","html":"&lt;span about=\"#mwt1\" typeof=\"mw:Param\" data-parsoid=&#39;{\"pi\":[[]],\"dsr\":[31,38,null,null]}&#39; data-mw=&#39;{\"parts\":[{\"templatearg\":{\"target\":{\"wt\":\"b\"},\"params\":{},\"i\":0}}]}&#39;>{{{b}}}&lt;/span>"},{"html":""}]]}'>
 <tbody><tr><td>c</td></tr>
 </tbody></table>
 !!end
@@ -12514,11 +12548,16 @@ Templates: Ugly templates: 6. Template encapsulation test: Cyclical nesting of t
 Templates: Parameters substituted at the top-level
 !! wikitext
 {{{foo|''who'' {{echo|me}}? '''never!'''}}}
+
+{{{foo|bar|baz}}}
 !! html/php
 <p><i>who</i> me? <b>never!</b>
+</p><p>bar
 </p>
 !! html/parsoid
-<p about="#mwt2" typeof="mw:Param" data-parsoid="{&quot;src&quot;:&quot;{{{foo|''who'' {{echo|me}}? '''never!'''}}}&quot;}"><i>who</i> me? <b>never!</b></p>
+<p about="#mwt2" typeof="mw:Param" data-mw='{"parts":[{"templatearg":{"target":{"wt":"foo"},"params":{"1":{"wt":"&#39;&#39;who&#39;&#39; {{echo|me}}? &#39;&#39;&#39;never!&#39;&#39;&#39;"}},"i":0}}]}'><i>who</i> me? <b>never!</b></p>
+
+<p about="#mwt3" typeof="mw:Param" data-mw='{"parts":[{"templatearg":{"target":{"wt":"foo"},"params":{"1":{"wt":"bar"},"2":{"wt":"baz"}},"i":0}}]}'>bar</p>
 !! end
 
 !!test
@@ -17689,6 +17728,8 @@ http://===r:::https://b
 # Known to produce bad XML for now
 !! test
 Fuzz testing: Parser24
+!! options
+parsoid=wt2html
 !! wikitext
 {|
 {{{|
@@ -17698,7 +17739,7 @@ Fuzz testing: Parser24
 
 MOVE YOUR MOUSE CURSOR OVER THIS TEXT
 |
-!! html
+!! html/php
 <table>
 {{{|
 <u class="&#124;">}}}} &gt;
@@ -17711,6 +17752,14 @@ MOVE YOUR MOUSE CURSOR OVER THIS TEXT
 </tr>
 </table>
 
+!! html/parsoid
+<p data-parsoid='{"fostered":true,"autoInsertedEnd":true}'>{{{|
+<u class="|" about="#mwt2" typeof="mw:ExpandedAttrs" data-parsoid='{"stx":"html","a":{"{{{{SSSll!!!!!!!VVVV)]]][[Special:*xxxxxxx-->&lt;noinclude>}}}}":null},"sa":{"{{{{SSSll!!!!!!!VVVV)]]][[Special:*xxxxxxx-->&lt;noinclude>}}}}":""},"autoInsertedEnd":true}' data-mw='{"attribs":[[{"txt":"{{{{SSSll!!!!!!!VVVV)]]][[Special:*xxxxxxx-->}}}}","html":"{&lt;span about=\"#mwt1\" typeof=\"mw:Param\" data-parsoid=&#39;{\"pi\":[[]],\"dsr\":[21,79,null,null]}&#39; data-mw=&#39;{\"parts\":[{\"templatearg\":{\"target\":{\"wt\":\"SSSll!!!!!!!VVVV)]]][[Special:*xxxxxxx-->&amp;lt;noinclude>\"},\"params\":{},\"i\":0}}]}&#39;>{{{SSSll!!!!!!!VVVV)]]][[Special:*xxxxxxx-->}}}&lt;/span>}"},{"html":""}]]}'>
+<br style="onmouseover='alert(document.cookie);' " data-parsoid='{"stx":"html","selfClose":true}'/></u></p><p data-parsoid='{"fostered":true,"autoInsertedEnd":true}'><u class="|" about="#mwt2" typeof="mw:ExpandedAttrs" data-parsoid='{"stx":"html","a":{"{{{{SSSll!!!!!!!VVVV)]]][[Special:*xxxxxxx-->&lt;noinclude>}}}}":null},"sa":{"{{{{SSSll!!!!!!!VVVV)]]][[Special:*xxxxxxx-->&lt;noinclude>}}}}":""},"autoInsertedEnd":true,"autoInsertedStart":true}' data-mw='{"attribs":[[{"txt":"{{{{SSSll!!!!!!!VVVV)]]][[Special:*xxxxxxx-->}}}}","html":"{&lt;span about=\"#mwt1\" typeof=\"mw:Param\" data-parsoid=&#39;{\"pi\":[[]],\"dsr\":[21,79,null,null]}&#39; data-mw=&#39;{\"parts\":[{\"templatearg\":{\"target\":{\"wt\":\"SSSll!!!!!!!VVVV)]]][[Special:*xxxxxxx-->&amp;lt;noinclude>\"},\"params\":{},\"i\":0}}]}&#39;>{{{SSSll!!!!!!!VVVV)]]][[Special:*xxxxxxx-->}}}&lt;/span>}"},{"html":""}]]}'>MOVE YOUR MOUSE CURSOR OVER THIS TEXT</u></p><table data-parsoid='{"autoInsertedEnd":true}'>
+
+
+
+<tbody><tr data-parsoid='{"autoInsertedEnd":true,"autoInsertedStart":true}'><td data-parsoid='{"autoInsertedEnd":true}'></td></tr></tbody></table>
 !! end
 
 # Note: the current result listed for this is not what the original one was,
@@ -17729,9 +17778,12 @@ Fuzz testing: Parser25 (bug 6055)
 <LI CLASS=||
  >
 }}}blah" onmouseover="alert('hello world');" align="left"'''MOVE MOUSE CURSOR OVER HERE
-!! html
+!! html/php
 <p>&lt;LI CLASS=blah" onmouseover="alert('hello world');" align="left"<b>MOVE MOUSE CURSOR OVER HERE</b>
 </p>
+!! html/parsoid
+<span about="#mwt1" typeof="mw:Param" data-parsoid='{"pi":[[{"k":"1"},{"k":"2"},{"k":"3"}]]}' data-mw='{"parts":[{"templatearg":{"target":{"wt":"\n"},"params":{"1":{"wt":" \n&lt;LI CLASS="},"2":{"wt":""},"3":{"wt":"\n >\n"}},"i":0}},"blah\" onmouseover=\"alert(&#39;hello world&#39;);\" align=\"left\"&#39;&#39;&#39;MOVE MOUSE CURSOR OVER HERE"]}'> 
+</span><p about="#mwt1">&lt;LI CLASS=blah" onmouseover="alert('hello world');" align="left"<b>MOVE MOUSE CURSOR OVER HERE</b></p>
 !! end
 
 !!test
index 903d7cb..cef03ee 100644 (file)
@@ -167,7 +167,7 @@ return [
         */
        'analyze_signature_compatibility' => true,
 
-       // Emit all issues. They are then supressed via
+       // Emit all issues. They are then suppressed via
        // suppress_issue_types, rather than a minimum
        // severity.
        "minimum_severity" => 0,
index baf8687..337c65c 100644 (file)
@@ -15,7 +15,7 @@ class StoreBatchTest extends MediaWikiTestCase {
                global $wgFileBackends;
                parent::setUp();
 
-               # Forge a FSRepo object to not have to rely on local wiki settings
+               # Forge a FileRepo object to not have to rely on local wiki settings
                $tmpPrefix = $this->getNewTempDirectory();
                if ( $this->getCliArg( 'use-filebackend' ) ) {
                        $name = $this->getCliArg( 'use-filebackend' );
index 137dfb7..b1ad77a 100644 (file)
@@ -82,31 +82,32 @@ class InterwikiTest extends MediaWikiTestCase {
 
                $this->setWgInterwikiCache( false );
 
+               $interwikiLookup = MediaWikiServices::getInstance()->getInterwikiLookup();
                $this->assertEquals(
                        [ $dewiki, $zzwiki ],
-                       Interwiki::getAllPrefixes(),
+                       $interwikiLookup->getAllPrefixes(),
                        'getAllPrefixes()'
                );
                $this->assertEquals(
                        [ $dewiki ],
-                       Interwiki::getAllPrefixes( true ),
+                       $interwikiLookup->getAllPrefixes( true ),
                        'getAllPrefixes()'
                );
                $this->assertEquals(
                        [ $zzwiki ],
-                       Interwiki::getAllPrefixes( false ),
+                       $interwikiLookup->getAllPrefixes( false ),
                        'getAllPrefixes()'
                );
 
-               $this->assertTrue( Interwiki::isValidInterwiki( 'de' ), 'known prefix is valid' );
-               $this->assertFalse( Interwiki::isValidInterwiki( 'xyz' ), 'unknown prefix is valid' );
+               $this->assertTrue( $interwikiLookup->isValidInterwiki( 'de' ), 'known prefix is valid' );
+               $this->assertFalse( $interwikiLookup->isValidInterwiki( 'xyz' ), 'unknown prefix is valid' );
 
-               $this->assertNull( Interwiki::fetch( null ), 'no prefix' );
-               $this->assertFalse( Interwiki::fetch( 'xyz' ), 'unknown prefix' );
+               $this->assertNull( $interwikiLookup->fetch( null ), 'no prefix' );
+               $this->assertFalse( $interwikiLookup->fetch( 'xyz' ), 'unknown prefix' );
 
-               $interwiki = Interwiki::fetch( 'de' );
+               $interwiki = $interwikiLookup->fetch( 'de' );
                $this->assertInstanceOf( 'Interwiki', $interwiki );
-               $this->assertSame( $interwiki, Interwiki::fetch( 'de' ), 'in-process caching' );
+               $this->assertSame( $interwiki, $interwikiLookup->fetch( 'de' ), 'in-process caching' );
 
                $this->assertSame( 'http://de.wikipedia.org/wiki/', $interwiki->getURL(), 'getURL' );
                $this->assertSame( 'http://de.wikipedia.org/w/api.php', $interwiki->getAPI(), 'getAPI' );
@@ -115,7 +116,7 @@ class InterwikiTest extends MediaWikiTestCase {
                $this->assertSame( false, $interwiki->isTranscludable(), 'isTranscludable' );
 
                Interwiki::invalidateCache( 'de' );
-               $this->assertNotSame( $interwiki, Interwiki::fetch( 'de' ), 'invalidate cache' );
+               $this->assertNotSame( $interwiki, $interwikiLookup->fetch( 'de' ), 'invalidate cache' );
        }
 
        /**
@@ -190,22 +191,23 @@ class InterwikiTest extends MediaWikiTestCase {
 
                $this->setWgInterwikiCache( $cdbFile );
 
+               $interwikiLookup = MediaWikiServices::getInstance()->getInterwikiLookup();
                $this->assertEquals(
                        [ $dewiki, $zzwiki ],
-                       Interwiki::getAllPrefixes(),
+                       $interwikiLookup->getAllPrefixes(),
                        'getAllPrefixes()'
                );
 
-               $this->assertTrue( Interwiki::isValidInterwiki( 'de' ), 'known prefix is valid' );
-               $this->assertTrue( Interwiki::isValidInterwiki( 'zz' ), 'known prefix is valid' );
+               $this->assertTrue( $interwikiLookup->isValidInterwiki( 'de' ), 'known prefix is valid' );
+               $this->assertTrue( $interwikiLookup->isValidInterwiki( 'zz' ), 'known prefix is valid' );
 
-               $interwiki = Interwiki::fetch( 'de' );
+               $interwiki = $interwikiLookup->fetch( 'de' );
                $this->assertInstanceOf( 'Interwiki', $interwiki );
 
                $this->assertSame( 'http://de.wikipedia.org/wiki/', $interwiki->getURL(), 'getURL' );
                $this->assertSame( true, $interwiki->isLocal(), 'isLocal' );
 
-               $interwiki = Interwiki::fetch( 'zz' );
+               $interwiki = $interwikiLookup->fetch( 'zz' );
                $this->assertInstanceOf( 'Interwiki', $interwiki );
 
                $this->assertSame( 'http://zzwiki.org/wiki/', $interwiki->getURL(), 'getURL' );
@@ -236,22 +238,23 @@ class InterwikiTest extends MediaWikiTestCase {
 
                $this->setWgInterwikiCache( $cdbData );
 
+               $interwikiLookup = MediaWikiServices::getInstance()->getInterwikiLookup();
                $this->assertEquals(
                        [ $dewiki, $zzwiki ],
-                       Interwiki::getAllPrefixes(),
+                       $interwikiLookup->getAllPrefixes(),
                        'getAllPrefixes()'
                );
 
-               $this->assertTrue( Interwiki::isValidInterwiki( 'de' ), 'known prefix is valid' );
-               $this->assertTrue( Interwiki::isValidInterwiki( 'zz' ), 'known prefix is valid' );
+               $this->assertTrue( $interwikiLookup->isValidInterwiki( 'de' ), 'known prefix is valid' );
+               $this->assertTrue( $interwikiLookup->isValidInterwiki( 'zz' ), 'known prefix is valid' );
 
-               $interwiki = Interwiki::fetch( 'de' );
+               $interwiki = $interwikiLookup->fetch( 'de' );
                $this->assertInstanceOf( 'Interwiki', $interwiki );
 
                $this->assertSame( 'http://de.wikipedia.org/wiki/', $interwiki->getURL(), 'getURL' );
                $this->assertSame( true, $interwiki->isLocal(), 'isLocal' );
 
-               $interwiki = Interwiki::fetch( 'zz' );
+               $interwiki = $interwikiLookup->fetch( 'zz' );
                $this->assertInstanceOf( 'Interwiki', $interwiki );
 
                $this->assertSame( 'http://zzwiki.org/wiki/', $interwiki->getURL(), 'getURL' );
index 43eb299..196f688 100644 (file)
@@ -19,7 +19,7 @@ abstract class MediaWikiMediaTestCase extends MediaWikiTestCase {
                if ( $this->createsThumbnails() ) {
                        // We need a temp directory for the thumbnails
                        // the container is named 'temp-thumb' because it is the
-                       // thumb directory for a FSRepo named "temp".
+                       // thumb directory for a repo named "temp".
                        $containers['temp-thumb'] = $this->getNewTempDirectory();
                }
 
@@ -33,7 +33,7 @@ abstract class MediaWikiMediaTestCase extends MediaWikiTestCase {
        }
 
        /**
-        * @return array Argument for FSRepo constructor
+        * @return array Argument for FileRepo constructor
         */
        protected function getRepoOptions() {
                return [
index 5d9cda7..94c6b4f 100644 (file)
@@ -726,13 +726,11 @@ class UserTest extends MediaWikiTestCase {
                $this->assertArrayHasKey( 'wm_infinite_blockBlockID', $cookies );
                $expOneDay = wfTimestamp() + ( 24 * 60 * 60 );
                // Check for expiry dates in a 10-second window, to account for slow testing.
-               $this->assertGreaterThan(
-                       $expOneDay - 5,
-                       $cookies['wm_infinite_blockBlockID']['expire']
-               );
-               $this->assertLessThan(
-                       $expOneDay + 5,
-                       $cookies['wm_infinite_blockBlockID']['expire']
+               $this->assertEquals(
+                       $expOneDay,
+                       $cookies['wm_infinite_blockBlockID']['expire'],
+                       'Expiry date',
+                       5.0
                );
 
                // 3. Change the block's expiry (to 2 hours), and the cookie's should be changed also.
@@ -752,4 +750,34 @@ class UserTest extends MediaWikiTestCase {
                // Clean up.
                $block->delete();
        }
+
+       public function testSoftBlockRanges() {
+               global $wgUser;
+
+               $this->setMwGlobals( [
+                       'wgSoftBlockRanges' => [ '10.0.0.0/8' ],
+                       'wgUser' => null,
+               ] );
+
+               // IP isn't in $wgSoftBlockRanges
+               $request = new FauxRequest();
+               $request->setIP( '192.168.0.1' );
+               $wgUser = User::newFromSession( $request );
+               $this->assertNull( $wgUser->getBlock() );
+
+               // IP is in $wgSoftBlockRanges
+               $request = new FauxRequest();
+               $request->setIP( '10.20.30.40' );
+               $wgUser = User::newFromSession( $request );
+               $block = $wgUser->getBlock();
+               $this->assertInstanceOf( Block::class, $block );
+               $this->assertSame( 'wgSoftBlockRanges', $block->getSystemBlockType() );
+
+               // Make sure the block is really soft
+               $request->getSession()->setUser( $this->getTestUser()->getUser() );
+               $wgUser = User::newFromSession( $request );
+               $this->assertFalse( $wgUser->isAnon(), 'sanity check' );
+               $this->assertNull( $wgUser->getBlock() );
+       }
+
 }
index e30088d..f31a646 100644 (file)
@@ -93,6 +93,7 @@ return [
                        'tests/qunit/suites/resources/mediawiki.api/mediawiki.api.watch.test.js',
                        'tests/qunit/suites/resources/mediawiki.api/mediawiki.ForeignApi.test.js',
                        'tests/qunit/suites/resources/mediawiki.special/mediawiki.special.recentchanges.test.js',
+                       'tests/qunit/suites/resources/mediawiki.rcfilters/dm.FiltersViewModel.test.js',
                        'tests/qunit/suites/resources/mediawiki/mediawiki.language.test.js',
                        'tests/qunit/suites/resources/mediawiki/mediawiki.cldr.test.js',
                        'tests/qunit/suites/resources/mediawiki/mediawiki.cookie.test.js',
@@ -136,6 +137,7 @@ return [
                        'mediawiki.util',
                        'mediawiki.viewport',
                        'mediawiki.special.recentchanges',
+                       'mediawiki.rcfilters.filters',
                        'mediawiki.language',
                        'mediawiki.cldr',
                        'mediawiki.cookie',
index 532a6ce..0fb7d9a 100644 (file)
                        [ 'Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1)', 'Win32', 'alt-' ],
                        [ 'Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.1; Trident/6.0)', 'Win32', 'alt-' ],
                        [ 'Mozilla/5.0 (Windows NT 6.3; Win64; x64; Trident/7.0; rv:11.0) like Gecko', 'Win64', 'alt-' ],
+                       [ 'Mozilla/5.0 (Windows NT 10.0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/42.0.2311.135 Safari/537.36 Edge/12.10136', 'Win64', 'alt-' ],
                        // Firefox
                        [ 'Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.5; en-US; rv:1.9.1.19) Gecko/20110420 Firefox/3.5.19', 'MacIntel', 'ctrl-' ],
                        [ 'Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.2.17) Gecko/20110422 Ubuntu/10.10 (maverick) Firefox/3.6.17', 'Linux i686', 'alt-shift-' ],
                        [ 'Mozilla/5.0 (Windows NT 6.0; rv:2.0.1) Gecko/20100101 Firefox/4.0.1', 'Win32', 'alt-shift-' ],
+                       [ 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10.12; rv:50.0) Gecko/20100101 Firefox/50.0', 'MacIntel', 'ctrl-option-' ],
+                       [ 'Mozilla/5.0 (X11; Linux x86_64; rv:17.0) Gecko/20121202 Firefox/17.0 Iceweasel/17.0.1', 'Linux 1686', 'alt-shift-' ],
+                       [ 'Mozilla/5.0 (Windows NT 5.2; U; de; rv:1.8.0) Gecko/20060728 Firefox/1.5.0', 'Win32', 'alt-' ],
                        // Safari / Konqueror
-                       [ 'Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_6_7; nl-nl) AppleWebKit/531.22.7 (KHTML, like Gecko) Version/4.0.5 Safari/531.22.7', 'MacIntel', 'ctrl-alt-' ],
+                       [ 'Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_6_7; nl-nl) AppleWebKit/531.22.7 (KHTML, like Gecko) Version/4.0.5 Safari/531.22.7', 'MacIntel', 'ctrl-option-' ],
+                       [ 'Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_5_7; de-de) AppleWebKit/525.28.3 (KHTML, like Gecko) Version/3.2.3 Safari/525.28.3', 'MacIntel', 'ctrl-' ],
+                       [ 'Mozilla/5.0 (Windows; U; Windows NT 5.1; cs-CZ) AppleWebKit/525.28.3 (KHTML, like Gecko) Version/3.2.3 Safari/525.29', 'Win32', 'alt-' ],
                        [ 'Mozilla/5.0 (Windows; U; Windows NT 6.0; cs-CZ) AppleWebKit/533.21.1 (KHTML, like Gecko) Version/4.0.5 Safari/531.22.7', 'Win32', 'alt-' ],
                        [ 'Mozilla/5.0 (X11; Linux i686) KHTML/4.9.1 (like Gecko) Konqueror/4.9', 'Linux i686', 'ctrl-' ],
                        // Opera
                        [ 'Mozilla/5.0 (Windows NT 5.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/28.0.1500.52 Safari/537.36 OPR/15.0.1147.130', 'Win32', 'alt-shift-' ],
                        // Chrome
                        [ 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_5_8) AppleWebKit/534.30 (KHTML, like Gecko) Chrome/12.0.742.112 Safari/534.30', 'MacIntel', 'ctrl-option-' ],
-                       [ 'Mozilla/5.0 (X11; Linux i686) AppleWebKit/534.30 (KHTML, like Gecko) Chrome/12.0.742.68 Safari/534.30', 'Linux i686', 'alt-shift-' ]
+                       [ 'Mozilla/5.0 (X11; Linux i686) AppleWebKit/534.30 (KHTML, like Gecko) Chrome/12.0.742.68 Safari/534.30', 'Linux i686', 'alt-shift-' ],
+                       // Unknown! Note: These aren't necessarily *right*, this is just
+                       // testing that we're getting the expected output based on the
+                       // platform.
+                       [ 'Mozilla/5.0 (Macintosh; U; PPC Mac OS X; en-US; rv:1.0.1) Gecko/20021111 Chimera/0.6', 'MacPPC', 'ctrl-' ],
+                       [ 'Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.3a) Gecko/20021207 Phoenix/0.5', 'Linux i686', 'alt-' ]
                ],
                // strings appended to title to make sure updateTooltipAccessKeys handles them correctly
                updateTooltipAccessKeysTestData = [ '', ' [a]', ' [test-a]', ' [alt-b]' ];
diff --git a/tests/qunit/suites/resources/mediawiki.rcfilters/dm.FiltersViewModel.test.js b/tests/qunit/suites/resources/mediawiki.rcfilters/dm.FiltersViewModel.test.js
new file mode 100644 (file)
index 0000000..b2857d9
--- /dev/null
@@ -0,0 +1,779 @@
+( function ( mw, $ ) {
+       QUnit.module( 'mediawiki.rcfilters - FiltersViewModel' );
+
+       QUnit.test( 'Setting up filters', function ( assert ) {
+               var definition = {
+                               group1: {
+                                       title: 'Group 1',
+                                       type: 'send_unselected_if_any',
+                                       filters: [
+                                               {
+                                                       name: 'group1filter1',
+                                                       label: 'Group 1: Filter 1',
+                                                       description: 'Description of Filter 1 in Group 1'
+                                               },
+                                               {
+                                                       name: 'group1filter2',
+                                                       label: 'Group 1: Filter 2',
+                                                       description: 'Description of Filter 2 in Group 1'
+                                               }
+                                       ]
+                               },
+                               group2: {
+                                       title: 'Group 2',
+                                       type: 'send_unselected_if_any',
+                                       filters: [
+                                               {
+                                                       name: 'group2filter1',
+                                                       label: 'Group 2: Filter 1',
+                                                       description: 'Description of Filter 1 in Group 2'
+                                               },
+                                               {
+                                                       name: 'group2filter2',
+                                                       label: 'Group 2: Filter 2',
+                                                       description: 'Description of Filter 2 in Group 2'
+                                               }
+                                       ]
+                               },
+                               group3: {
+                                       title: 'Group 3',
+                                       type: 'string_options',
+                                       filters: [
+                                               {
+                                                       name: 'group3filter1',
+                                                       label: 'Group 3: Filter 1',
+                                                       description: 'Description of Filter 1 in Group 3'
+                                               },
+                                               {
+                                                       name: 'group3filter2',
+                                                       label: 'Group 3: Filter 2',
+                                                       description: 'Description of Filter 2 in Group 3'
+                                               }
+                                       ]
+                               }
+                       },
+                       model = new mw.rcfilters.dm.FiltersViewModel();
+
+               model.initializeFilters( definition );
+
+               assert.ok(
+                       model.getItemByName( 'group1filter1' ) instanceof mw.rcfilters.dm.FilterItem &&
+                       model.getItemByName( 'group1filter2' ) instanceof mw.rcfilters.dm.FilterItem &&
+                       model.getItemByName( 'group2filter1' ) instanceof mw.rcfilters.dm.FilterItem &&
+                       model.getItemByName( 'group2filter2' ) instanceof mw.rcfilters.dm.FilterItem &&
+                       model.getItemByName( 'group3filter1' ) instanceof mw.rcfilters.dm.FilterItem &&
+                       model.getItemByName( 'group3filter2' ) instanceof mw.rcfilters.dm.FilterItem,
+                       'Filters instantiated and stored correctly'
+               );
+
+               assert.deepEqual(
+                       model.getState(),
+                       {
+                               group1filter1: false,
+                               group1filter2: false,
+                               group2filter1: false,
+                               group2filter2: false,
+                               group3filter1: false,
+                               group3filter2: false
+                       },
+                       'Initial state of filters'
+               );
+
+               model.updateFilters( {
+                       group1filter1: true,
+                       group2filter2: true,
+                       group3filter1: true
+               } );
+               assert.deepEqual(
+                       model.getState(),
+                       {
+                               group1filter1: true,
+                               group1filter2: false,
+                               group2filter1: false,
+                               group2filter2: true,
+                               group3filter1: true,
+                               group3filter2: false
+                       },
+                       'Updating filter states correctly'
+               );
+       } );
+
+       QUnit.test( 'Finding matching filters', function ( assert ) {
+               var matches,
+                       definition = {
+                               group1: {
+                                       title: 'Group 1',
+                                       type: 'send_unselected_if_any',
+                                       filters: [
+                                               {
+                                                       name: 'group1filter1',
+                                                       label: 'Group 1: Filter 1',
+                                                       description: 'Description of Filter 1 in Group 1'
+                                               },
+                                               {
+                                                       name: 'group1filter2',
+                                                       label: 'Group 1: Filter 2',
+                                                       description: 'Description of Filter 2 in Group 1'
+                                               }
+                                       ]
+                               },
+                               group2: {
+                                       title: 'Group 2',
+                                       type: 'send_unselected_if_any',
+                                       filters: [
+                                               {
+                                                       name: 'group2filter1',
+                                                       label: 'Group 2: Filter 1',
+                                                       description: 'Description of Filter 1 in Group 2'
+                                               },
+                                               {
+                                                       name: 'group2filter2',
+                                                       label: 'Group 2: Filter 2',
+                                                       description: 'Description of Filter 2 in Group 2'
+                                               }
+                                       ]
+                               }
+                       },
+                       model = new mw.rcfilters.dm.FiltersViewModel();
+
+               model.initializeFilters( definition );
+
+               matches = model.findMatches( 'group 1' );
+               assert.equal(
+                       matches.group1.length,
+                       2,
+                       'findMatches finds correct group with correct number of results'
+               );
+
+               assert.deepEqual(
+                       matches.group1.map( function ( item ) { return item.getName(); } ),
+                       [ 'group1filter1', 'group1filter2' ],
+                       'findMatches finds the correct items within a single group'
+               );
+
+               matches = model.findMatches( 'filter 1' );
+               assert.ok(
+                       matches.group1.length === 1 && matches.group2.length === 1,
+                       'findMatches finds correct number of results in multiple groups'
+               );
+
+               assert.deepEqual(
+                       [
+                               matches.group1.map( function ( item ) { return item.getName(); } ),
+                               matches.group2.map( function ( item ) { return item.getName(); } )
+                       ],
+                       [
+                               [ 'group1filter1' ],
+                               [ 'group2filter1' ]
+                       ],
+                       'findMatches finds the correct items within multiple groups'
+               );
+
+               matches = model.findMatches( 'foo' );
+               assert.ok(
+                       $.isEmptyObject( matches ),
+                       'findMatches returns an empty object when no results found'
+               );
+       } );
+
+       QUnit.test( 'getParametersFromFilters', function ( assert ) {
+               var definition = {
+                               group1: {
+                                       title: 'Group 1',
+                                       type: 'send_unselected_if_any',
+                                       filters: [
+                                               {
+                                                       name: 'hidefilter1',
+                                                       label: 'Group 1: Filter 1',
+                                                       description: 'Description of Filter 1 in Group 1'
+                                               },
+                                               {
+                                                       name: 'hidefilter2',
+                                                       label: 'Group 1: Filter 2',
+                                                       description: 'Description of Filter 2 in Group 1'
+                                               },
+                                               {
+                                                       name: 'hidefilter3',
+                                                       label: 'Group 1: Filter 3',
+                                                       description: 'Description of Filter 3 in Group 1'
+                                               }
+                                       ]
+                               },
+                               group2: {
+                                       title: 'Group 2',
+                                       type: 'send_unselected_if_any',
+                                       filters: [
+                                               {
+                                                       name: 'hidefilter4',
+                                                       label: 'Group 2: Filter 1',
+                                                       description: 'Description of Filter 1 in Group 2'
+                                               },
+                                               {
+                                                       name: 'hidefilter5',
+                                                       label: 'Group 2: Filter 2',
+                                                       description: 'Description of Filter 2 in Group 2'
+                                               },
+                                               {
+                                                       name: 'hidefilter6',
+                                                       label: 'Group 2: Filter 3',
+                                                       description: 'Description of Filter 3 in Group 2'
+                                               }
+                                       ]
+                               },
+                               group3: {
+                                       title: 'Group 3',
+                                       type: 'string_options',
+                                       separator: ',',
+                                       filters: [
+                                               {
+                                                       name: 'filter7',
+                                                       label: 'Group 3: Filter 1',
+                                                       description: 'Description of Filter 1 in Group 3'
+                                               },
+                                               {
+                                                       name: 'filter8',
+                                                       label: 'Group 3: Filter 2',
+                                                       description: 'Description of Filter 2 in Group 3'
+                                               },
+                                               {
+                                                       name: 'filter9',
+                                                       label: 'Group 3: Filter 3',
+                                                       description: 'Description of Filter 3 in Group 3'
+                                               }
+                                       ]
+                               }
+                       },
+                       model = new mw.rcfilters.dm.FiltersViewModel();
+
+               model.initializeFilters( definition );
+
+               // Starting with all filters unselected
+               assert.deepEqual(
+                       model.getParametersFromFilters(),
+                       {
+                               hidefilter1: 0,
+                               hidefilter2: 0,
+                               hidefilter3: 0,
+                               hidefilter4: 0,
+                               hidefilter5: 0,
+                               hidefilter6: 0,
+                               group3: 'all',
+                       },
+                       'Unselected filters return all parameters falsey or \'all\'.'
+               );
+
+               // Select 1 filter
+               model.updateFilters( {
+                       hidefilter1: true,
+                       hidefilter2: false,
+                       hidefilter3: false,
+                       hidefilter4: false,
+                       hidefilter5: false,
+                       hidefilter6: false
+               } );
+               // Only one filter in one group
+               assert.deepEqual(
+                       model.getParametersFromFilters(),
+                       {
+                               // Group 1 (one selected, the others are true)
+                               hidefilter1: 0,
+                               hidefilter2: 1,
+                               hidefilter3: 1,
+                               // Group 2 (nothing is selected, all false)
+                               hidefilter4: 0,
+                               hidefilter5: 0,
+                               hidefilter6: 0,
+                               group3: 'all'
+                       },
+                       'One filters in one "send_unselected_if_any" group returns the other parameters truthy.'
+               );
+
+               // Select 2 filters
+               model.updateFilters( {
+                       hidefilter1: true,
+                       hidefilter2: true,
+                       hidefilter3: false,
+                       hidefilter4: false,
+                       hidefilter5: false,
+                       hidefilter6: false
+               } );
+               // Two selected filters in one group
+               assert.deepEqual(
+                       model.getParametersFromFilters(),
+                       {
+                               // Group 1 (two selected, the others are true)
+                               hidefilter1: 0,
+                               hidefilter2: 0,
+                               hidefilter3: 1,
+                               // Group 2 (nothing is selected, all false)
+                               hidefilter4: 0,
+                               hidefilter5: 0,
+                               hidefilter6: 0,
+                               group3: 'all'
+                       },
+                       'One filters in one "send_unselected_if_any" group returns the other parameters truthy.'
+               );
+
+               // Select 3 filters
+               model.updateFilters( {
+                       hidefilter1: true,
+                       hidefilter2: true,
+                       hidefilter3: true,
+                       hidefilter4: false,
+                       hidefilter5: false,
+                       hidefilter6: false
+               } );
+               // All filters of the group are selected == this is the same as not selecting any
+               assert.deepEqual(
+                       model.getParametersFromFilters(),
+                       {
+                               // Group 1 (all selected, all false)
+                               hidefilter1: 0,
+                               hidefilter2: 0,
+                               hidefilter3: 0,
+                               // Group 2 (nothing is selected, all false)
+                               hidefilter4: 0,
+                               hidefilter5: 0,
+                               hidefilter6: 0,
+                               group3: 'all'
+                       },
+                       'All filters selected in one "send_unselected_if_any" group returns all parameters falsy.'
+               );
+
+               // Select 1 filter from string_options
+               model.updateFilters( {
+                       filter7: true,
+                       filter8: false,
+                       filter9: false
+               } );
+               // All filters of the group are selected == this is the same as not selecting any
+               assert.deepEqual(
+                       model.getParametersFromFilters(),
+                       {
+                               // Group 1 (all selected, all)
+                               hidefilter1: 0,
+                               hidefilter2: 0,
+                               hidefilter3: 0,
+                               // Group 2 (nothing is selected, all false)
+                               hidefilter4: 0,
+                               hidefilter5: 0,
+                               hidefilter6: 0,
+                               group3: 'filter7'
+                       },
+                       'One filter selected in "string_option" group returns that filter in the value.'
+               );
+
+               // Select 2 filters from string_options
+               model.updateFilters( {
+                       filter7: true,
+                       filter8: true,
+                       filter9: false
+               } );
+               // All filters of the group are selected == this is the same as not selecting any
+               assert.deepEqual(
+                       model.getParametersFromFilters(),
+                       {
+                               // Group 1 (all selected, all)
+                               hidefilter1: 0,
+                               hidefilter2: 0,
+                               hidefilter3: 0,
+                               // Group 2 (nothing is selected, all false)
+                               hidefilter4: 0,
+                               hidefilter5: 0,
+                               hidefilter6: 0,
+                               group3: 'filter7,filter8'
+                       },
+                       'Two filters selected in "string_option" group returns those filters in the value.'
+               );
+
+               // Select 3 filters from string_options
+               model.updateFilters( {
+                       filter7: true,
+                       filter8: true,
+                       filter9: true
+               } );
+               // All filters of the group are selected == this is the same as not selecting any
+               assert.deepEqual(
+                       model.getParametersFromFilters(),
+                       {
+                               // Group 1 (all selected, all)
+                               hidefilter1: 0,
+                               hidefilter2: 0,
+                               hidefilter3: 0,
+                               // Group 2 (nothing is selected, all false)
+                               hidefilter4: 0,
+                               hidefilter5: 0,
+                               hidefilter6: 0,
+                               group3: 'all'
+                       },
+                       'All filters selected in "string_option" group returns \'all\'.'
+               );
+
+       } );
+
+       QUnit.test( 'getFiltersFromParameters', function ( assert ) {
+               var definition = {
+                               group1: {
+                                       title: 'Group 1',
+                                       type: 'send_unselected_if_any',
+                                       filters: [
+                                               {
+                                                       name: 'hidefilter1',
+                                                       label: 'Show filter 1',
+                                                       description: 'Description of Filter 1 in Group 1'
+                                               },
+                                               {
+                                                       name: 'hidefilter2',
+                                                       label: 'Show filter 2',
+                                                       description: 'Description of Filter 2 in Group 1'
+                                               },
+                                               {
+                                                       name: 'hidefilter3',
+                                                       label: 'Show filter 3',
+                                                       description: 'Description of Filter 3 in Group 1'
+                                               }
+                                       ]
+                               },
+                               group2: {
+                                       title: 'Group 2',
+                                       type: 'send_unselected_if_any',
+                                       filters: [
+                                               {
+                                                       name: 'hidefilter4',
+                                                       label: 'Show filter 4',
+                                                       description: 'Description of Filter 1 in Group 2'
+                                               },
+                                               {
+                                                       name: 'hidefilter5',
+                                                       label: 'Show filter 5',
+                                                       description: 'Description of Filter 2 in Group 2'
+                                               },
+                                               {
+                                                       name: 'hidefilter6',
+                                                       label: 'Show filter 6',
+                                                       description: 'Description of Filter 3 in Group 2'
+                                               }
+                                       ]
+                               },
+                               group3: {
+                                       title: 'Group 3',
+                                       type: 'string_options',
+                                       separator: ',',
+                                       filters: [
+                                               {
+                                                       name: 'filter7',
+                                                       label: 'Group 3: Filter 1',
+                                                       description: 'Description of Filter 1 in Group 3'
+                                               },
+                                               {
+                                                       name: 'filter8',
+                                                       label: 'Group 3: Filter 2',
+                                                       description: 'Description of Filter 2 in Group 3'
+                                               },
+                                               {
+                                                       name: 'filter9',
+                                                       label: 'Group 3: Filter 3',
+                                                       description: 'Description of Filter 3 in Group 3'
+                                               }
+                                       ]
+                               }
+                       },
+                       model = new mw.rcfilters.dm.FiltersViewModel();
+
+               model.initializeFilters( definition );
+
+               // Empty query = empty filter definition
+               assert.deepEqual(
+                       model.getFiltersFromParameters( {} ),
+                       {
+                               hidefilter1: false, // The text is "show filter 1"
+                               hidefilter2: false, // The text is "show filter 2"
+                               hidefilter3: false, // The text is "show filter 3"
+                               hidefilter4: false, // The text is "show filter 4"
+                               hidefilter5: false, // The text is "show filter 5"
+                               hidefilter6: false, // The text is "show filter 6"
+                               filter7: false,
+                               filter8: false,
+                               filter9: false
+                       },
+                       'Empty parameter query results in filters in initial state'
+               );
+
+               assert.deepEqual(
+                       model.getFiltersFromParameters( {
+                               hidefilter1: '1'
+                       } ),
+                       {
+                               hidefilter1: false, // The text is "show filter 1"
+                               hidefilter2: true, // The text is "show filter 2"
+                               hidefilter3: true, // The text is "show filter 3"
+                               hidefilter4: false, // The text is "show filter 4"
+                               hidefilter5: false, // The text is "show filter 5"
+                               hidefilter6: false, // The text is "show filter 6"
+                               filter7: false,
+                               filter8: false,
+                               filter9: false
+                       },
+                       'One falsey parameter in a group makes the rest of the filters in the group truthy (checked) in the interface'
+               );
+
+               assert.deepEqual(
+                       model.getFiltersFromParameters( {
+                               hidefilter1: '1',
+                               hidefilter2: '1'
+                       } ),
+                       {
+                               hidefilter1: false, // The text is "show filter 1"
+                               hidefilter2: false, // The text is "show filter 2"
+                               hidefilter3: true, // The text is "show filter 3"
+                               hidefilter4: false, // The text is "show filter 4"
+                               hidefilter5: false, // The text is "show filter 5"
+                               hidefilter6: false, // The text is "show filter 6"
+                               filter7: false,
+                               filter8: false,
+                               filter9: false
+                       },
+                       'Two falsey parameters in a \'send_unselected_if_any\' group makes the rest of the filters in the group truthy (checked) in the interface'
+               );
+
+               assert.deepEqual(
+                       model.getFiltersFromParameters( {
+                               hidefilter1: '1',
+                               hidefilter2: '1',
+                               hidefilter3: '1'
+                       } ),
+                       {
+                               // TODO: This will have to be represented as a different state, though.
+                               hidefilter1: false, // The text is "show filter 1"
+                               hidefilter2: false, // The text is "show filter 2"
+                               hidefilter3: false, // The text is "show filter 3"
+                               hidefilter4: false, // The text is "show filter 4"
+                               hidefilter5: false, // The text is "show filter 5"
+                               hidefilter6: false, // The text is "show filter 6"
+                               filter7: false,
+                               filter8: false,
+                               filter9: false
+                       },
+                       'All paremeters in the same \'send_unselected_if_any\' group false is equivalent to none are truthy (checked) in the interface'
+               );
+
+               // The ones above don't update the model, so we have a clean state.
+
+               model.updateFilters(
+                       model.getFiltersFromParameters( {
+                               hidefilter1: '1'
+                       } )
+               );
+
+               model.updateFilters(
+                       model.getFiltersFromParameters( {
+                               hidefilter3: '1'
+                       } )
+               );
+
+               // 1 and 3 are separately unchecked via hide parameters, 2 should still be
+               // checked.
+               // This can simulate separate filters in the same group being hidden different
+               // ways (e.g. preferences and URL).
+               assert.deepEqual(
+                       model.getState(),
+                       {
+                               hidefilter1: false, // The text is "show filter 1"
+                               hidefilter2: true, // The text is "show filter 2"
+                               hidefilter3: false, // The text is "show filter 3"
+                               hidefilter4: false, // The text is "show filter 4"
+                               hidefilter5: false, // The text is "show filter 5"
+                               hidefilter6: false, // The text is "show filter 6"
+                               filter7: false,
+                               filter8: false,
+                               filter9: false
+                       },
+                       'After unchecking 2 of 3 \'send_unselected_if_any\' filters via separate updateFilters calls, only the remaining one is still checked.'
+               );
+
+               // Reset
+               model = new mw.rcfilters.dm.FiltersViewModel();
+               model.initializeFilters( definition );
+
+               model.updateFilters(
+                       model.getFiltersFromParameters( {
+                               hidefilter1: '1'
+                       } )
+               );
+               model.updateFilters(
+                       model.getFiltersFromParameters( {
+                               hidefilter1: '0'
+                       } )
+               );
+
+               // Simulates minor edits being hidden in preferences, then unhidden via URL
+               // override.
+               assert.deepEqual(
+                       model.getState(),
+                       {
+                               hidefilter1: false, // The text is "show filter 1"
+                               hidefilter2: false, // The text is "show filter 2"
+                               hidefilter3: false, // The text is "show filter 3"
+                               hidefilter4: false, // The text is "show filter 4"
+                               hidefilter5: false, // The text is "show filter 5"
+                               hidefilter6: false, // The text is "show filter 6"
+                               filter7: false,
+                               filter8: false,
+                               filter9: false
+                       },
+                       'After unchecking then checking a \'send_unselected_if_any\' filter (without touching other filters in that group), all are checked'
+               );
+
+               model.updateFilters(
+                       model.getFiltersFromParameters( {
+                               group3: 'filter7'
+                       } )
+               );
+               assert.deepEqual(
+                       model.getState(),
+                       {
+                               hidefilter1: false, // The text is "show filter 1"
+                               hidefilter2: false, // The text is "show filter 2"
+                               hidefilter3: false, // The text is "show filter 3"
+                               hidefilter4: false, // The text is "show filter 4"
+                               hidefilter5: false, // The text is "show filter 5"
+                               hidefilter6: false, // The text is "show filter 6"
+                               filter7: true,
+                               filter8: false,
+                               filter9: false
+                       },
+                       'A \'string_options\' parameter containing 1 value, results in the corresponding filter as checked'
+               );
+
+               model.updateFilters(
+                       model.getFiltersFromParameters( {
+                               group3: 'filter7,filter8'
+                       } )
+               );
+               assert.deepEqual(
+                       model.getState(),
+                       {
+                               hidefilter1: false, // The text is "show filter 1"
+                               hidefilter2: false, // The text is "show filter 2"
+                               hidefilter3: false, // The text is "show filter 3"
+                               hidefilter4: false, // The text is "show filter 4"
+                               hidefilter5: false, // The text is "show filter 5"
+                               hidefilter6: false, // The text is "show filter 6"
+                               filter7: true,
+                               filter8: true,
+                               filter9: false
+                       },
+                       'A \'string_options\' parameter containing 2 values, results in both corresponding filters as checked'
+               );
+
+               model.updateFilters(
+                       model.getFiltersFromParameters( {
+                               group3: 'filter7,filter8,filter9'
+                       } )
+               );
+               assert.deepEqual(
+                       model.getState(),
+                       {
+                               hidefilter1: false, // The text is "show filter 1"
+                               hidefilter2: false, // The text is "show filter 2"
+                               hidefilter3: false, // The text is "show filter 3"
+                               hidefilter4: false, // The text is "show filter 4"
+                               hidefilter5: false, // The text is "show filter 5"
+                               hidefilter6: false, // The text is "show filter 6"
+                               filter7: false,
+                               filter8: false,
+                               filter9: false
+                       },
+                       'A \'string_options\' parameter containing all values, results in all filters of the group as unchecked.'
+               );
+
+               model.updateFilters(
+                       model.getFiltersFromParameters( {
+                               group3: 'filter7,filter8,filter9'
+                       } )
+               );
+               assert.deepEqual(
+                       model.getState(),
+                       {
+                               hidefilter1: false, // The text is "show filter 1"
+                               hidefilter2: false, // The text is "show filter 2"
+                               hidefilter3: false, // The text is "show filter 3"
+                               hidefilter4: false, // The text is "show filter 4"
+                               hidefilter5: false, // The text is "show filter 5"
+                               hidefilter6: false, // The text is "show filter 6"
+                               filter7: false,
+                               filter8: false,
+                               filter9: false
+                       },
+                       'A \'string_options\' parameter containing the value \'all\', results in all filters of the group as unchecked.'
+               );
+
+               model.updateFilters(
+                       model.getFiltersFromParameters( {
+                               group3: 'filter7,foo,filter9'
+                       } )
+               );
+               assert.deepEqual(
+                       model.getState(),
+                       {
+                               hidefilter1: false, // The text is "show filter 1"
+                               hidefilter2: false, // The text is "show filter 2"
+                               hidefilter3: false, // The text is "show filter 3"
+                               hidefilter4: false, // The text is "show filter 4"
+                               hidefilter5: false, // The text is "show filter 5"
+                               hidefilter6: false, // The text is "show filter 6"
+                               filter7: true,
+                               filter8: false,
+                               filter9: true
+                       },
+                       'A \'string_options\' parameter containing an invalid value, results in the invalid value ignored and the valid corresponding filters checked.'
+               );
+       } );
+
+       QUnit.test( 'sanitizeStringOptionGroup', function ( assert ) {
+               var definition = {
+                               group1: {
+                                       title: 'Group 1',
+                                       type: 'string_options',
+                                       filters: [
+                                               {
+                                                       name: 'filter1',
+                                                       label: 'Show filter 1',
+                                                       description: 'Description of Filter 1 in Group 1'
+                                               },
+                                               {
+                                                       name: 'filter2',
+                                                       label: 'Show filter 2',
+                                                       description: 'Description of Filter 2 in Group 1'
+                                               },
+                                               {
+                                                       name: 'filter3',
+                                                       label: 'Show filter 3',
+                                                       description: 'Description of Filter 3 in Group 1'
+                                               }
+                                       ]
+                               }
+                       },
+                       model = new mw.rcfilters.dm.FiltersViewModel();
+
+               model.initializeFilters( definition );
+
+               assert.deepEqual(
+                       model.sanitizeStringOptionGroup( 'group1', [ 'filter1', 'filter1', 'filter2' ] ),
+                       [ 'filter1', 'filter2' ],
+                       'Remove duplicate values'
+               );
+
+               assert.deepEqual(
+                       model.sanitizeStringOptionGroup( 'group1', [ 'filter1', 'foo', 'filter2' ] ),
+                       [ 'filter1', 'filter2' ],
+                       'Remove invalid values'
+               );
+
+               assert.deepEqual(
+                       model.sanitizeStringOptionGroup( 'group1', [ 'filter1', 'all', 'filter2' ] ),
+                       [ 'all' ],
+                       'If any value is "all", the only value is "all".'
+               );
+       } );
+}( mediaWiki, jQuery ) );