Merge "Leading semicolon line-bolding made visible in printable version"
authorjenkins-bot <jenkins-bot@gerrit.wikimedia.org>
Fri, 3 Jan 2014 17:32:10 +0000 (17:32 +0000)
committerGerrit Code Review <gerrit@wikimedia.org>
Fri, 3 Jan 2014 17:32:10 +0000 (17:32 +0000)
113 files changed:
RELEASE-NOTES-1.23
api.php
includes/AutoLoader.php
includes/DefaultSettings.php
includes/EditPage.php
includes/Export.php
includes/Import.php
includes/Linker.php
includes/PrefixSearch.php
includes/SpecialPageFactory.php
includes/Title.php
includes/User.php
includes/UserMailer.php
includes/Wiki.php
includes/WikiFilePage.php
includes/WikiPage.php
includes/actions/HistoryAction.php
includes/actions/RollbackAction.php
includes/api/ApiFileRevert.php
includes/api/ApiPageSet.php
includes/api/ApiQueryBase.php
includes/api/ApiUpload.php
includes/cache/CacheDependency.php
includes/cache/LocalisationCache.php
includes/cache/MessageCache.php
includes/db/DatabaseError.php
includes/db/DatabaseMysqlBase.php
includes/db/DatabasePostgres.php
includes/db/LBFactory.php
includes/db/LBFactoryMulti.php
includes/deferred/SquidUpdate.php
includes/job/JobQueueDB.php
includes/job/jobs/DoubleRedirectJob.php
includes/libs/MWMessagePack.php [new file with mode: 0644]
includes/libs/RunningStat.php [new file with mode: 0644]
includes/logging/DeleteLogFormatter.php
includes/logging/LogFormatter.php
includes/logging/LogPager.php
includes/parser/Parser.php
includes/parser/ParserCache.php
includes/parser/ParserOutput.php
includes/profiler/RunningStat.php [deleted file]
includes/resourceloader/ResourceLoader.php
includes/resourceloader/ResourceLoaderFileModule.php
includes/resourceloader/ResourceLoaderStartUpModule.php
includes/resourceloader/ResourceLoaderUserCSSPrefsModule.php
includes/resourceloader/ResourceLoaderUserOptionsModule.php
includes/search/SearchEngine.php
includes/specialpage/SpecialPage.php
includes/specials/SpecialEmailuser.php
includes/specials/SpecialExport.php
includes/specials/SpecialListfiles.php
includes/specials/SpecialProtectedpages.php
includes/specials/SpecialRecentchangeslinked.php
includes/upload/UploadBase.php
includes/utils/UIDGenerator.php
languages/Language.php
languages/LanguageConverter.php
languages/classes/LanguageBe_tarask.php
languages/classes/LanguageHr.php [deleted file]
languages/classes/LanguageRu.php
languages/classes/LanguageSr.php
languages/classes/LanguageSr_ec.php [deleted file]
languages/classes/LanguageSr_el.php [deleted file]
languages/classes/LanguageUk.php
languages/data/plurals-mediawiki.xml
languages/data/plurals.xml [changed mode: 0644->0755]
languages/messages/MessagesBr.php
languages/messages/MessagesBs.php
languages/messages/MessagesCa.php
languages/messages/MessagesCe.php
languages/messages/MessagesCy.php
languages/messages/MessagesDa.php
languages/messages/MessagesDe.php
languages/messages/MessagesDiq.php
languages/messages/MessagesEgl.php
languages/messages/MessagesEn.php
languages/messages/MessagesFr.php
languages/messages/MessagesHe.php
languages/messages/MessagesIt.php
languages/messages/MessagesKo.php
languages/messages/MessagesLrc.php
languages/messages/MessagesNap.php
languages/messages/MessagesOc.php
languages/messages/MessagesQqq.php
languages/messages/MessagesSv.php
languages/messages/MessagesTr.php
languages/messages/MessagesVro.php
languages/messages/MessagesZh_hans.php
maintenance/language/messageTypes.inc
maintenance/language/messages.inc
resources/jquery/jquery.client.js
resources/mediawiki.libs/CLDRPluralRuleParser.js
skins/common/shared.css
tests/phpunit/includes/RunningStatTest.php [deleted file]
tests/phpunit/includes/db/LBFactoryTest.php
tests/phpunit/includes/libs/MWMessagePackTest.php [new file with mode: 0644]
tests/phpunit/includes/libs/RunningStatTest.php [new file with mode: 0644]
tests/phpunit/includes/search/SearchEngineTest.php
tests/phpunit/includes/specials/SpecialListFilesTest.php [new file with mode: 0644]
tests/phpunit/includes/utils/UIDGeneratorTest.php
tests/phpunit/languages/LanguageBe_taraskTest.php
tests/phpunit/languages/LanguageBsTest.php
tests/phpunit/languages/LanguageHrTest.php
tests/phpunit/languages/LanguageHyTest.php
tests/phpunit/languages/LanguageLvTest.php
tests/phpunit/languages/LanguageMkTest.php
tests/phpunit/languages/LanguageRuTest.php
tests/phpunit/languages/LanguageSgsTest.php
tests/phpunit/languages/LanguageShTest.php
tests/phpunit/languages/LanguageSrTest.php
tests/phpunit/languages/LanguageUkTest.php
tests/qunit/suites/resources/jquery/jquery.client.test.js

index d13f9cd..d682206 100644 (file)
@@ -26,6 +26,8 @@ production.
   now enabled by default.
 * $wgLBFactoryConf: Class names have had underscores removed. The configuration
   should be updated if LBFactory_Simple or LBFactory_Multi is configured.
+* $wgPasswordSenderName has been deprecated. To set a custom mailer name,
+  the system message 'emailsender' should be modified (default: "{{SITENAME}}").
 
 === New features in 1.23 ===
 * ResourceLoader can utilize the Web Storage API to cache modules client-side.
@@ -59,6 +61,10 @@ production.
 * Added ApiBeforeMain hook, roughly equivalent to the BeforeInitialize hook:
   it's called after everything is set up but before any major processing
   happens.
+* The jquery.client module now performs a component-wise version comparison in
+  its #test method when strings are used in the browser map: version '1.10' is
+  now correctly considered larger than '1.2'. Using numbers in the version map
+  is not affected.
 
 === Bug fixes in 1.23 ===
 * (bug 41759) The "updated since last visit" markers (on history pages, recent
@@ -78,8 +84,13 @@ production.
 * (bug 57201) SpecialRecentChangesFilters hook is now executed for feeds.
 * (bug 58640) Fixed a compatibility issue with PCRE 8.34 that caused pages
   to appear blank or with missing text.
+* (bug 56931) Updated the plural rules to CLDR 24. They are in new format
+  which is detailed in UTS 35 Rev 33. The PHP parser and evaluator as well as
+  the JavaScript evaluator were updated to support the new format. Plural rules
+  for some languages have changed, most notably Russian. Affected software
+  messages have been updated and marked for review at translatewiki.net.
 
-=== API changes in 1.23 ===
+=== Web API changes in 1.23 ===
 * (bug 54884) action=parse&prop=categories now indicates hidden and missing
   categories.
 * action=query&meta=filerepoinfo now returns additional information for each
@@ -100,7 +111,7 @@ MediaWiki supports over 350 languages. Many localisations are updated
 regularly. Below only new and removed languages are listed, as well as
 changes to languages because of Bugzilla reports.
 
-* Support was added for Northern Luri (lrc)
+* Support was added for Northern Luri (lrc).
 
 === Other changes in 1.23 ===
 * The rc_type field in the recentchanges table has been superseded by a new
@@ -115,7 +126,6 @@ changes to languages because of Bugzilla reports.
 * The global variable $wgArticle has been removed after a lengthy deprecation.
 * The global functions addButton and insertTags (for mw.toolbar.addButton and
   mw.toolbar.insertTags) now emits mw.log.warn when accessed.
-* User::getPageRenderingHash() was deprecated since 1.17 and has been removed.
 * The ExpandTemplates extension has been moved into MediaWiki core.
 * (bug 52812) Removed "Disable search suggestions" from Preference.
 * (bug 52809) Removed "Disable browser page caching" from Preference.
@@ -131,53 +141,59 @@ changes to languages because of Bugzilla reports.
 * A page_links_updated field has been added to the page table.
 * SpecialPage::getTitle has been deprecated in favor of
   SpecialPage::getPageTitle.
-* EditPage::spamPage() was deprecated since 1.17 and has been removed.
-* SpecialRecentChanges::feedSetup() was removed.
-* Removed classes:
-  - TitleDependency
-  - TitleListDependency
-* Renamed classes:
-  - CdbReader_DBA to CdbReaderDBA
-  - CdbReader_PHP to CdbReaderPHP
-  - CdbWriter_DBA to CdbWriterDBA
-  - CdbWriter_PHP to CdbWriterPHP
-  - DiffOp_Add to DiffOpAdd
-  - DiffOp_Change to DiffOpChange
-  - DiffOp_Copy to DiffOpCopy
-  - DiffOp_Delete to DiffOpDelete
-  - HWLDF_WordAccumulator to HWLDFWordAccumulator
-  - LBFactory_Fake to LBFactoryFake
-  - LBFactory_Multi to LBFactoryMulti
-  - LBFactory_Simple to LBFactorySimple
-  - LBFactory_Single to LBFactorySingle
-  - LCStore_Accel to LCStoreAccel
-  - LCStore_CDB to LCStoreCDB
-  - LCStore_DB to LCStoreDB
-  - LCStore_Null to LCStoreNull
-  - LoadBalancer_Single to LoadBalancerSingle
-  - LoadMonitor_MySQL to LoadMonitorMySQL
-  - LoadMonitor_Null to LoadMonitorNull
-  - LocalisationCache_BulkLoad to LocalisationCacheBulkLoad
-  - csvStatsOutput to CsvStatsOutput
-  - extensionLanguages to ExtensionLanguages
-  - languages to Languages
-  - statsOutput to StatsOutput
-  - textStatsOutput to TextStatsOutput
-  - wikiStatsOutput to WikiStatsOutput
-* Removed methods:
-  - Exif::getFormattedData() (deprecated in 1.18)
-  - Exif::makeFormattedData() (deprecated in 1.18)
-  - Linker::makeBrokenLink() (deprecated in 1.16)
-  - Linker::makeBrokenLinkObj() (deprecated in 1.16)
-  - Linker::makeColouredLinkObj() (deprecated in 1.16)
-  - Linker::makeSizeLinkObj() (deprecated in 1.17)
-  - ProfilerSimple::getCpuTime (deprecated in 1.20)
-  - Revision::revText() (deprecated in 1.17)
-  - SkinTemplate::jstext() (deprecated in 1.21)
-  - SpecialRevisionDelete::extractBitField() (deprecated in 1.22)
-  - WikiPage::quickEdit() (deprecated in 1.18)
-  - WikiPage::useParserCache() (deprecated in 1.18)
-  - WikiPage::viewUpdates() (deprecated in 1.18)
+
+==== Removed classes ====
+* TitleDependency
+* TitleListDependency
+
+==== Renamed classes ====
+* CdbReader_DBA to CdbReaderDBA
+* CdbReader_PHP to CdbReaderPHP
+* CdbWriter_DBA to CdbWriterDBA
+* CdbWriter_PHP to CdbWriterPHP
+* DiffOp_Add to DiffOpAdd
+* DiffOp_Change to DiffOpChange
+* DiffOp_Copy to DiffOpCopy
+* DiffOp_Delete to DiffOpDelete
+* HWLDF_WordAccumulator to HWLDFWordAccumulator
+* LBFactory_Fake to LBFactoryFake
+* LBFactory_Multi to LBFactoryMulti
+* LBFactory_Simple to LBFactorySimple
+* LBFactory_Single to LBFactorySingle
+* LCStore_Accel to LCStoreAccel
+* LCStore_CDB to LCStoreCDB
+* LCStore_DB to LCStoreDB
+* LCStore_Null to LCStoreNull
+* LoadBalancer_Single to LoadBalancerSingle
+* LoadMonitor_MySQL to LoadMonitorMySQL
+* LoadMonitor_Null to LoadMonitorNull
+* LocalisationCache_BulkLoad to LocalisationCacheBulkLoad
+* csvStatsOutput to CsvStatsOutput
+* extensionLanguages to ExtensionLanguages
+* languages to Languages
+* statsOutput to StatsOutput
+* textStatsOutput to TextStatsOutput
+* wikiStatsOutput to WikiStatsOutput
+
+==== Removed methods ====
+* EditPage::spamPage() (deprecated since 1.17)
+* Exif::getFormattedData() (deprecated in 1.18)
+* Exif::makeFormattedData() (deprecated in 1.18)
+* Language::convertLinkToAllVariants() (deprecated in 1.17)
+* LanguageConverter::convertLinkToAllVariants() (deprecated in 1.17)
+* Linker::makeBrokenLink() (deprecated in 1.16)
+* Linker::makeBrokenLinkObj() (deprecated in 1.16)
+* Linker::makeColouredLinkObj() (deprecated in 1.16)
+* Linker::makeSizeLinkObj() (deprecated in 1.17)
+* ProfilerSimple::getCpuTime (deprecated in 1.20)
+* Revision::revText() (deprecated in 1.17)
+* SkinTemplate::jstext() (deprecated in 1.21)
+* SpecialRecentChanges::feedSetup()
+* SpecialRevisionDelete::extractBitField() (deprecated in 1.22)
+* User::getPageRenderingHash() (deprecated in 1.17)
+* WikiPage::quickEdit() (deprecated in 1.18)
+* WikiPage::useParserCache() (deprecated in 1.18)
+* WikiPage::viewUpdates() (deprecated in 1.18)
 
 == Compatibility ==
 
diff --git a/api.php b/api.php
index 51bb2ad..0d2312a 100644 (file)
--- a/api.php
+++ b/api.php
@@ -75,12 +75,17 @@ wfRunHooks( 'ApiBeforeMain', array( &$processor ) );
 // Process data & print results
 $processor->execute();
 
+if ( function_exists( 'fastcgi_finish_request' ) ) {
+       fastcgi_finish_request();
+}
+
 // Execute any deferred updates
 DeferredUpdates::doUpdates();
 
 // Log what the user did, for book-keeping purposes.
 $endtime = microtime( true );
 wfProfileOut( 'api.php' );
+
 wfLogProfilingData();
 
 // Log the request
index 1f81249..a9b0376 100644 (file)
@@ -185,7 +185,6 @@ $wgAutoloadLocalClasses = array(
        'Revision' => 'includes/Revision.php',
        'RevisionList' => 'includes/RevisionList.php',
        'RSSFeed' => 'includes/Feed.php',
-       'RunningStat' => 'includes/profiler/RunningStat.php',
        'Sanitizer' => 'includes/Sanitizer.php',
        'SiteConfiguration' => 'includes/SiteConfiguration.php',
        'SiteStats' => 'includes/SiteStats.php',
@@ -688,6 +687,8 @@ $wgAutoloadLocalClasses = array(
        'JSParser' => 'includes/libs/jsminplus.php',
        'JSToken' => 'includes/libs/jsminplus.php',
        'JSTokenizer' => 'includes/libs/jsminplus.php',
+       'MWMessagePack' => 'includes/libs/MWMessagePack.php',
+       'RunningStat' => 'includes/libs/RunningStat.php',
        'ScopedCallback' => 'includes/libs/ScopedCallback.php',
        'ScopedPHPTimeout' => 'includes/libs/ScopedPHPTimeout.php',
        'XmlTypeCheck' => 'includes/libs/XmlTypeCheck.php',
index f799452..9b2b676 100644 (file)
@@ -1319,6 +1319,8 @@ unset( $serverName ); # Don't leak local variables to global scope
 
 /**
  * Password reminder name
+ *
+ * @deprecated since 1.23; use the system message 'emailsender' instead.
  */
 $wgPasswordSenderName = 'MediaWiki Mail';
 
index f86cae4..ba49378 100644 (file)
@@ -1913,12 +1913,10 @@ class EditPage {
        function getBaseRevision() {
                if ( !$this->mBaseRevision ) {
                        $db = wfGetDB( DB_MASTER );
-                       $baseRevision = Revision::loadFromTimestamp(
+                       $this->mBaseRevision = Revision::loadFromTimestamp(
                                $db, $this->mTitle, $this->edittime );
-                       return $this->mBaseRevision = $baseRevision;
-               } else {
-                       return $this->mBaseRevision;
                }
+               return $this->mBaseRevision;
        }
 
        /**
index b4a507d..639ba28 100644 (file)
@@ -866,7 +866,7 @@ class XmlDumpWriter {
         * @since 1.18
         */
        public static function canonicalTitle( Title $title ) {
-               if ( $title->getInterwiki() ) {
+               if ( $title->isExternal() ) {
                        return $title->getPrefixedText();
                }
 
index 8b7af02..721b94b 100644 (file)
@@ -1717,7 +1717,7 @@ class ImportStreamSource {
                        return Status::newFatal( 'import-noarticle' );
                }
                $link = Title::newFromText( "$interwiki:Special:Export/$page" );
-               if ( is_null( $link ) || $link->getInterwiki() == '' ) {
+               if ( is_null( $link ) || !$link->isExternal() ) {
                        return Status::newFatal( 'importbadinterwiki' );
                } else {
                        $params = array();
index 27f8ab4..867b88b 100644 (file)
@@ -1446,7 +1446,7 @@ class Linker {
 
                        $target = Title::newFromText( $linkTarget );
                        if ( $target ) {
-                               if ( $target->getText() == '' && $target->getInterwiki() === ''
+                               if ( $target->getText() == '' && !$target->isExternal()
                                        && !self::$commentLocal && self::$commentContextTitle
                                ) {
                                        $newTarget = clone ( self::$commentContextTitle );
@@ -2137,7 +2137,8 @@ class Linker {
                }
 
                wfProfileOut( __METHOD__ );
-               return self::$accesskeycache[$name] = $accesskey;
+               self::$accesskeycache[$name] = $accesskey;
+               return self::$accesskeycache[$name];
        }
 
        /**
index 3c464c5..780cae5 100644 (file)
@@ -44,7 +44,7 @@ class PrefixSearch {
 
                // Find a Title which is not an interwiki and is in NS_MAIN
                $title = Title::newFromText( $search );
-               if ( $title && $title->getInterwiki() == '' ) {
+               if ( $title && !$title->isExternal() ) {
                        $ns = array( $title->getNamespace() );
                        if ( $ns[0] == NS_MAIN ) {
                                $ns = $namespaces; // no explicit prefix, use default namespaces
@@ -57,7 +57,7 @@ class PrefixSearch {
                $title = Title::newFromText( $search . 'Dummy' );
                if ( $title && $title->getText() == 'Dummy'
                        && $title->getNamespace() != NS_MAIN
-                       && $title->getInterwiki() == '' ) {
+                       && !$title->isExternal() ) {
                        return self::searchBackend(
                                array( $title->getNamespace() ), '', $limit );
                }
index 2cd9a3a..18b8f0b 100644 (file)
@@ -44,7 +44,6 @@
  * @since 1.17
  */
 class SpecialPageFactory {
-
        /**
         * List of special page names to the subclass of SpecialPage which handles them.
         */
@@ -259,8 +258,8 @@ class SpecialPageFactory {
         * where the first element is the special page name and the second is the
         * subpage.
         *
-        * @param $alias String
-        * @return Array( String, String|null ), or array( null, null ) if the page is invalid
+        * @param string $alias
+        * @return array Array( String, String|null ), or array( null, null ) if the page is invalid
         */
        public static function resolveAlias( $alias ) {
                global $wgContLang;
@@ -286,8 +285,8 @@ class SpecialPageFactory {
        /**
         * Add a page to a certain display group for Special:SpecialPages
         *
-        * @param $page Mixed: SpecialPage or string
-        * @param $group String
+        * @param SpecialPage|string $page
+        * @param string $group
         * @deprecated since 1.21 Override SpecialPage::getGroupName
         */
        public static function setGroup( $page, $group ) {
@@ -301,8 +300,8 @@ class SpecialPageFactory {
        /**
         * Get the group that the special page belongs in on Special:SpecialPage
         *
-        * @param $page SpecialPage
-        * @return String
+        * @param SpecialPage $page
+        * @return string
         * @deprecated since 1.21 Use SpecialPage::getFinalGroupName
         */
        public static function getGroup( &$page ) {
@@ -314,8 +313,8 @@ class SpecialPageFactory {
        /**
         * Check if a given name exist as a special page or as a special page alias
         *
-        * @param string $name name of a special page
-        * @return Boolean: true if a special page exists with this name
+        * @param string $name Name of a special page
+        * @return bool True if a special page exists with this name
         */
        public static function exists( $name ) {
                list( $title, /*...*/ ) = self::resolveAlias( $name );
@@ -351,9 +350,9 @@ class SpecialPageFactory {
         * Return categorised listable special pages which are available
         * for the current user, and everyone.
         *
-        * @param $user User object to check permissions, $wgUser will be used
-        *              if not provided
-        * @return Array( String => Specialpage )
+        * @param $user User object to check permissions, $wgUser will be used if
+        *   if not provided
+        * @return array ( string => Specialpage )
         */
        public static function getUsablePages( User $user = null ) {
                $pages = array();
@@ -378,7 +377,7 @@ class SpecialPageFactory {
        /**
         * Return categorised listable special pages for all users
         *
-        * @return Array( String => Specialpage )
+        * @return array ( string => Specialpage )
         */
        public static function getRegularPages() {
                $pages = array();
@@ -395,7 +394,7 @@ class SpecialPageFactory {
         * Return categorised listable special pages which are available
         * for the current user, but not for everyone
         *
-        * @return Array( String => Specialpage )
+        * @return array ( string => Specialpage )
         */
        public static function getRestrictedPages() {
                global $wgUser;
@@ -421,9 +420,9 @@ class SpecialPageFactory {
         * Returns a title object if the page is redirected, false if there was no such special
         * page, and true if it was successful.
         *
-        * @param $title          Title object
-        * @param $context        IContextSource
-        * @param $including      Bool output is being captured for use in {{special:whatever}}
+        * @param Title $title
+        * @param IContextSource $context
+        * @param bool $including Bool output is being captured for use in {{special:whatever}}
         *
         * @return bool
         */
@@ -501,10 +500,9 @@ class SpecialPageFactory {
         * variables so that the special page will get the context it'd expect on a
         * normal request, and then restores them to their previous values after.
         *
-        * @param $title Title
-        * @param $context IContextSource
-        *
-        * @return String: HTML fragment
+        * @param Title $title
+        * @param IContextSource $context
+        * @return string HTML fragment
         */
        static function capturePath( Title $title, IContextSource $context ) {
                global $wgOut, $wgTitle, $wgRequest, $wgUser, $wgLang;
@@ -539,10 +537,9 @@ class SpecialPageFactory {
        /**
         * Get the local name for a specified canonical name
         *
-        * @param $name String
-        * @param $subpage String|Bool
-        *
-        * @return String
+        * @param string $name
+        * @param string|bool $subpage
+        * @return string
         */
        static function getLocalNameFor( $name, $subpage = false ) {
                global $wgContLang;
@@ -576,9 +573,8 @@ class SpecialPageFactory {
        /**
         * Get a title for a given alias
         *
-        * @param $alias String
-        *
-        * @return Title or null if there is no such alias
+        * @param string $alias
+        * @return Title|null Title or null if there is no such alias
         */
        static function getTitleForAlias( $alias ) {
                $name = self::resolveAlias( $alias );
index 5ab9e94..88268bb 100644 (file)
@@ -59,7 +59,7 @@ class Title {
        var $mDbkeyform = '';             // /< Main part with underscores
        var $mUserCaseDBKey;              // /< DB key with the initial letter in the case specified by the user
        var $mNamespace = NS_MAIN;        // /< Namespace index, i.e. one of the NS_xxxx constants
-       var $mInterwiki = '';             // /< Interwiki prefix (or null string)
+       var $mInterwiki = '';             // /< Interwiki prefix
        var $mFragment;                   // /< Title fragment (i.e. the bit after the #)
        var $mArticleID = -1;             // /< Article ID, fetched from the link cache on demand
        var $mLatestID = false;           // /< ID of most recent revision
@@ -73,7 +73,7 @@ class Title {
        var $mHasCascadingRestrictions;   ///< Are cascading restrictions in effect on this page?
        var $mCascadeSources;             ///< Where are the cascading restrictions coming from on this page?
        var $mRestrictionsLoaded = false; ///< Boolean for initialisation on demand
-       var $mPrefixedText;               ///< Text form including namespace/interwiki, initialised on demand
+       var $mPrefixedText = null;        ///< Text form including namespace/interwiki, initialised on demand
        var $mTitleProtection;            ///< Cached value for getTitleProtection (create protection)
        # Don't change the following default, NS_MAIN is hardcoded in several
        # places.  See bug 696.
@@ -685,7 +685,7 @@ class Title {
         * @return Bool TRUE if this is an in-project interwiki link or a wikilink, FALSE otherwise
         */
        public function isLocal() {
-               if ( $this->mInterwiki != '' ) {
+               if ( $this->isExternal() ) {
                        $iw = Interwiki::fetch( $this->mInterwiki );
                        if ( $iw ) {
                                return $iw->isLocal();
@@ -700,11 +700,11 @@ class Title {
         * @return Bool
         */
        public function isExternal() {
-               return ( $this->mInterwiki != '' );
+               return $this->mInterwiki !== '';
        }
 
        /**
-        * Get the interwiki prefix (or null string)
+        * Get the interwiki prefix
         *
         * @return String Interwiki prefix
         */
@@ -719,7 +719,7 @@ class Title {
         * @return Bool TRUE if this is transcludable
         */
        public function isTrans() {
-               if ( $this->mInterwiki == '' ) {
+               if ( !$this->isExternal() ) {
                        return false;
                }
 
@@ -732,7 +732,7 @@ class Title {
         * @return String the DB name
         */
        public function getTransWikiID() {
-               if ( $this->mInterwiki == '' ) {
+               if ( !$this->isExternal() ) {
                        return false;
                }
 
@@ -830,7 +830,7 @@ class Title {
        public function getNsText() {
                global $wgContLang;
 
-               if ( $this->mInterwiki != '' ) {
+               if ( $this->isExternal() ) {
                        // This probably shouldn't even happen. ohh man, oh yuck.
                        // But for interwiki transclusion it sometimes does.
                        // Shit. Shit shit shit.
@@ -1014,7 +1014,7 @@ class Title {
         * @return Bool TRUE or FALSE
         */
        public function isMovable() {
-               if ( !MWNamespace::isMovable( $this->getNamespace() ) || $this->getInterwiki() != '' ) {
+               if ( !MWNamespace::isMovable( $this->getNamespace() ) || $this->isExternal() ) {
                        // Interwiki title or immovable namespace. Hooks don't get to override here
                        return false;
                }
@@ -1236,7 +1236,7 @@ class Title {
         */
        private function prefix( $name ) {
                $p = '';
-               if ( $this->mInterwiki != '' ) {
+               if ( $this->isExternal() ) {
                        $p = $this->mInterwiki . ':';
                }
 
@@ -1265,8 +1265,7 @@ class Title {
         * @return String the prefixed title, with spaces
         */
        public function getPrefixedText() {
-               // @todo FIXME: Bad usage of empty() ?
-               if ( empty( $this->mPrefixedText ) ) {
+               if ( $this->mPrefixedText === null ) {
                        $s = $this->prefix( $this->mTextform );
                        $s = str_replace( '_', ' ', $s );
                        $this->mPrefixedText = $s;
@@ -1735,7 +1734,7 @@ class Title {
         *  interwiki link
         */
        public function getEditURL() {
-               if ( $this->mInterwiki != '' ) {
+               if ( $this->isExternal() ) {
                        return '';
                }
                $s = $this->getLocalURL( 'action=edit' );
@@ -2892,15 +2891,15 @@ class Title {
                # alone to cache the result.  There's no point in having it hanging
                # around uninitialized in every Title object; therefore we only add it
                # if needed and don't declare it statically.
-               if ( isset( $this->mHasSubpages ) ) {
-                       return $this->mHasSubpages;
+               if ( !isset( $this->mHasSubpages ) ) {
+                       $this->mHasSubpages = false;
+                       $subpages = $this->getSubpages( 1 );
+                       if ( $subpages instanceof TitleArray ) {
+                               $this->mHasSubpages = (bool)$subpages->count();
+                       }
                }
 
-               $subpages = $this->getSubpages( 1 );
-               if ( $subpages instanceof TitleArray ) {
-                       return $this->mHasSubpages = (bool)$subpages->count();
-               }
-               return $this->mHasSubpages = false;
+               return $this->mHasSubpages;
        }
 
        /**
@@ -2922,7 +2921,7 @@ class Title {
                if ( $limit > -1 ) {
                        $options['LIMIT'] = $limit;
                }
-               return $this->mSubpages = TitleArray::newFromResult(
+               $this->mSubpages = TitleArray::newFromResult(
                        $dbr->select( 'page',
                                array( 'page_id', 'page_namespace', 'page_title', 'page_is_redirect' ),
                                $conds,
@@ -2930,6 +2929,7 @@ class Title {
                                $options
                        )
                );
+               return $this->mSubpages;
        }
 
        /**
@@ -2990,7 +2990,8 @@ class Title {
         */
        public function getArticleID( $flags = 0 ) {
                if ( $this->getNamespace() < 0 ) {
-                       return $this->mArticleID = 0;
+                       $this->mArticleID = 0;
+                       return $this->mArticleID;
                }
                $linkCache = LinkCache::singleton();
                if ( $flags & self::GAID_FOR_UPDATE ) {
@@ -3019,7 +3020,8 @@ class Title {
                }
                # Calling getArticleID() loads the field from cache as needed
                if ( !$this->getArticleID( $flags ) ) {
-                       return $this->mRedirect = false;
+                       $this->mRedirect = false;
+                       return $this->mRedirect;
                }
 
                $linkCache = LinkCache::singleton();
@@ -3031,7 +3033,8 @@ class Title {
                        # LinkCache as appropriate, or use $flags = Title::GAID_FOR_UPDATE. If that flag is
                        # set, then LinkCache will definitely be up to date here, since getArticleID() forces
                        # LinkCache to refresh its data from the master.
-                       return $this->mRedirect = false;
+                       $this->mRedirect = false;
+                       return $this->mRedirect;
                }
 
                $this->mRedirect = (bool)$cached;
@@ -3052,13 +3055,15 @@ class Title {
                }
                # Calling getArticleID() loads the field from cache as needed
                if ( !$this->getArticleID( $flags ) ) {
-                       return $this->mLength = 0;
+                       $this->mLength = 0;
+                       return $this->mLength;
                }
                $linkCache = LinkCache::singleton();
                $cached = $linkCache->getGoodLinkFieldObj( $this, 'length' );
                if ( $cached === null ) {
                        # Trust LinkCache's state over our own, as for isRedirect()
-                       return $this->mLength = 0;
+                       $this->mLength = 0;
+                       return $this->mLength;
                }
 
                $this->mLength = intval( $cached );
@@ -3078,14 +3083,16 @@ class Title {
                }
                # Calling getArticleID() loads the field from cache as needed
                if ( !$this->getArticleID( $flags ) ) {
-                       return $this->mLatestID = 0;
+                       $this->mLatestID = 0;
+                       return $this->mLatestID;
                }
                $linkCache = LinkCache::singleton();
                $linkCache->addLinkObj( $this );
                $cached = $linkCache->getGoodLinkFieldObj( $this, 'revision' );
                if ( $cached === null ) {
                        # Trust LinkCache's state over our own, as for isRedirect()
-                       return $this->mLatestID = 0;
+                       $this->mLatestID = 0;
+                       return $this->mLatestID;
                }
 
                $this->mLatestID = intval( $cached );
@@ -3250,7 +3257,7 @@ class Title {
                } while ( true );
 
                # We already know that some pages won't be in the database!
-               if ( $this->mInterwiki != '' || NS_SPECIAL == $this->mNamespace ) {
+               if ( $this->isExternal() || NS_SPECIAL == $this->mNamespace ) {
                        $this->mArticleID = 0;
                }
                $fragment = strstr( $dbkey, '#' );
@@ -3306,13 +3313,13 @@ class Title {
                # and [[Foo]] point to the same place.  Don't force it for interwikis, since the
                # other site might be case-sensitive.
                $this->mUserCaseDBKey = $dbkey;
-               if ( $this->mInterwiki == '' ) {
+               if ( !$this->isExternal() ) {
                        $dbkey = self::capitalize( $dbkey, $this->mNamespace );
                }
 
                # Can't make a link to a namespace alone... "empty" local links can only be
                # self-links with a fragment identifier.
-               if ( $dbkey == '' && $this->mInterwiki == '' && $this->mNamespace != NS_MAIN ) {
+               if ( $dbkey == '' && !$this->isExternal() && $this->mNamespace != NS_MAIN ) {
                        return false;
                }
 
@@ -3582,7 +3589,7 @@ class Title {
                if ( !$this->isMovable() ) {
                        $errors[] = array( 'immobile-source-namespace', $this->getNsText() );
                }
-               if ( $nt->getInterwiki() != '' ) {
+               if ( $nt->isExternal() ) {
                        $errors[] = array( 'immobile-target-namespace-iw' );
                }
                if ( !$nt->isMovable() ) {
@@ -4494,7 +4501,7 @@ class Title {
                        return $isKnown;
                }
 
-               if ( $this->mInterwiki != '' ) {
+               if ( $this->isExternal() ) {
                        return true;  // any interwiki link might be viewable, for all we know
                }
 
@@ -4649,7 +4656,8 @@ class Title {
                        return $this->mNotificationTimestamp[$uid];
                }
                if ( !$uid || !$wgShowUpdatedMarker || !$user->isAllowed( 'viewmywatchlist' ) ) {
-                       return $this->mNotificationTimestamp[$uid] = false;
+                       $this->mNotificationTimestamp[$uid] = false;
+                       return $this->mNotificationTimestamp[$uid];
                }
                // Don't cache too much!
                if ( count( $this->mNotificationTimestamp ) >= self::CACHE_MAX ) {
index 43128fa..ca3f79b 100644 (file)
@@ -3777,8 +3777,9 @@ class User {
         */
        public function sendMail( $subject, $body, $from = null, $replyto = null ) {
                if ( is_null( $from ) ) {
-                       global $wgPasswordSender, $wgPasswordSenderName;
-                       $sender = new MailAddress( $wgPasswordSender, $wgPasswordSenderName );
+                       global $wgPasswordSender;
+                       $sender = new MailAddress( $wgPasswordSender,
+                               wfMessage( 'emailsender' )->inContentLanguage()->text() );
                } else {
                        $sender = new MailAddress( $from );
                }
index 39c3e18..e1d00d3 100644 (file)
@@ -120,6 +120,8 @@ class UserMailer {
        static function arrayToHeaderString( $headers, $endl = "\n" ) {
                $strings = array();
                foreach ( $headers as $name => $value ) {
+                       // Prevent header injection by stripping newlines from value
+                       $value = self::sanitizeHeaderValue( $value );
                        $strings[] = "$name: $value";
                }
                return implode( $endl, $strings );
@@ -393,13 +395,25 @@ class UserMailer {
                self::$mErrorString = preg_replace( '/^mail\(\)(\s*\[.*?\])?: /', '', $string );
        }
 
+       /**
+        * Strips bad characters from a header value to prevent PHP mail header injection attacks
+        * @param string $val String to be santizied
+        * @return string
+        */
+       public static function sanitizeHeaderValue( $val ) {
+               return strtr( $val, array( "\r" => '', "\n" => '' ) );
+       }
+
        /**
         * Converts a string into a valid RFC 822 "phrase", such as is used for the sender name
         * @param $phrase string
         * @return string
         */
        public static function rfc822Phrase( $phrase ) {
-               $phrase = strtr( $phrase, array( "\r" => '', "\n" => '', '"' => '' ) );
+               // Remove line breaks
+               $phrase = self::sanitizeHeaderValue( $phrase );
+               // Remove quotes
+               $phrase = str_replace( '"', '', $phrase );
                return '"' . $phrase . '"';
        }
 
@@ -694,7 +708,7 @@ class EmailNotification {
         * Generate the generic "this page has been changed" e-mail text.
         */
        private function composeCommonMailtext() {
-               global $wgPasswordSender, $wgPasswordSenderName, $wgNoReplyAddress;
+               global $wgPasswordSender, $wgNoReplyAddress;
                global $wgEnotifFromEditor, $wgEnotifRevealEditorAddress;
                global $wgEnotifImpersonal, $wgEnotifUseRealName;
 
@@ -779,7 +793,8 @@ class EmailNotification {
                # Reveal the page editor's address as REPLY-TO address only if
                # the user has not opted-out and the option is enabled at the
                # global configuration level.
-               $adminAddress = new MailAddress( $wgPasswordSender, $wgPasswordSenderName );
+               $adminAddress = new MailAddress( $wgPasswordSender,
+                       wfMessage( 'emailsender' )->inContentLanguage()->text() );
                if ( $wgEnotifRevealEditorAddress
                        && ( $this->editor->getEmail() != '' )
                        && $this->editor->getOption( 'enotifrevealaddr' )
index 5ebf5a0..fd7898f 100644 (file)
@@ -121,7 +121,7 @@ class MediaWiki {
                        $ret = Title::newMainPage();
                }
 
-               if ( $ret === null || ( $ret->getDBkey() == '' && $ret->getInterwiki() == '' ) ) {
+               if ( $ret === null || ( $ret->getDBkey() == '' && !$ret->isExternal() ) ) {
                        $ret = SpecialPage::getTitleFor( 'Badtitle' );
                }
 
@@ -197,7 +197,7 @@ class MediaWiki {
                wfRunHooks( 'BeforeInitialize', array( &$title, &$unused, &$output, &$user, $request, $this ) );
 
                // Invalid titles. Bug 21776: The interwikis must redirect even if the page name is empty.
-               if ( is_null( $title ) || ( $title->getDBkey() == '' && $title->getInterwiki() == '' )
+               if ( is_null( $title ) || ( $title->getDBkey() == '' && !$title->isExternal() )
                        || $title->isSpecial( 'Badtitle' )
                ) {
                        $this->context->setTitle( SpecialPage::getTitleFor( 'Badtitle' ) );
@@ -231,7 +231,7 @@ class MediaWiki {
                $pageView = false; // was an article or special page viewed?
 
                // Interwiki redirects
-               if ( $title->getInterwiki() != '' ) {
+               if ( $title->isExternal() ) {
                        $rdfrom = $request->getVal( 'rdfrom' );
                        if ( $rdfrom ) {
                                $url = $title->getFullURL( array( 'rdfrom' => $rdfrom ) );
@@ -458,6 +458,9 @@ class MediaWiki {
                try {
                        $this->checkMaxLag();
                        $this->main();
+                       if ( function_exists( 'fastcgi_finish_request' ) ) {
+                               fastcgi_finish_request();
+                       }
                        $this->restInPeace();
                } catch ( Exception $e ) {
                        MWExceptionHandler::handle( $e );
index 2b192b0..817f0fa 100644 (file)
@@ -85,7 +85,8 @@ class WikiFilePage extends WikiPage {
                if ( $from == $to ) {
                        return null;
                }
-               return $this->mRedirectTarget = Title::makeTitle( NS_FILE, $to );
+               $this->mRedirectTarget = Title::makeTitle( NS_FILE, $to );
+               return $this->mRedirectTarget;
        }
 
        /**
@@ -142,7 +143,8 @@ class WikiFilePage extends WikiPage {
                }
                $hash = $this->mFile->getSha1();
                if ( !( $hash ) ) {
-                       return $this->mDupes = array();
+                       $this->mDupes = array();
+                       return $this->mDupes;
                }
                $dupes = RepoGroup::singleton()->findBySha1( $hash );
                // Remove duplicates with self and non matching file sizes
index d4acb6f..f0a58d3 100644 (file)
@@ -908,13 +908,15 @@ class WikiPage implements Page, IDBAccessObject {
 
                // rd_fragment and rd_interwiki were added later, populate them if empty
                if ( $row && !is_null( $row->rd_fragment ) && !is_null( $row->rd_interwiki ) ) {
-                       return $this->mRedirectTarget = Title::makeTitle(
+                       $this->mRedirectTarget = Title::makeTitle(
                                $row->rd_namespace, $row->rd_title,
                                $row->rd_fragment, $row->rd_interwiki );
+                       return $this->mRedirectTarget;
                }
 
                // This page doesn't have an entry in the redirect table
-               return $this->mRedirectTarget = $this->insertRedirect();
+               $this->mRedirectTarget = $this->insertRedirect();
+               return $this->mRedirectTarget;
        }
 
        /**
index 34db1d2..8e800f9 100644 (file)
@@ -260,6 +260,7 @@ class HistoryAction extends FormlessAction {
                }
                $request = $this->getRequest();
 
+               /** @var RSSFeed|AtomFeed $feed */
                $feed = new $wgFeedClasses[$type](
                        $this->getTitle()->getPrefixedText() . ' - ' .
                        $this->msg( 'history-feed-title' )->inContentLanguage()->text(),
index d48a0ea..617f1c9 100644 (file)
@@ -62,6 +62,7 @@ class RollbackAction extends FormlessAction {
                        $this->getOutput()->addWikiMsgArray( $errMsg, $errArray );
 
                        if ( isset( $details['current'] ) ) {
+                               /** @var Revision $current */
                                $current = $details['current'];
 
                                if ( $current->getComment() != '' ) {
@@ -85,6 +86,7 @@ class RollbackAction extends FormlessAction {
                        throw new ErrorPageError( 'rollbackfailed', $error[0], array_slice( $error, 1 ) );
                }
 
+               /** @var Revision $current */
                $current = $details['current'];
                $target = $details['target'];
                $newId = $details['newid'];
index dc5e24e..a3fa5f9 100644 (file)
  * @ingroup API
  */
 class ApiFileRevert extends ApiBase {
-
-       /**
-        * @var File
-        */
+       /** @var LocalFile */
        protected $file;
+
+       /** @var string */
        protected $archiveName;
 
+       /** @var array */
        protected $params;
 
        public function execute() {
index e95e680..0d733a2 100644 (file)
@@ -308,7 +308,7 @@ class ApiPageSet extends ApiBase {
 
        /**
         * All Title objects provided.
-        * @return array of Title objects
+        * @return Title[]
         */
        public function getTitles() {
                return $this->mTitles;
@@ -324,7 +324,7 @@ class ApiPageSet extends ApiBase {
 
        /**
         * Title objects that were found in the database.
-        * @return array page_id (int) => Title (obj)
+        * @return Title[] Array page_id (int) => Title (obj)
         */
        public function getGoodTitles() {
                return $this->mGoodTitles;
@@ -341,7 +341,7 @@ class ApiPageSet extends ApiBase {
        /**
         * Title objects that were NOT found in the database.
         * The array's index will be negative for each item
-        * @return array of Title objects
+        * @return Title[]
         */
        public function getMissingTitles() {
                return $this->mMissingTitles;
@@ -350,7 +350,7 @@ class ApiPageSet extends ApiBase {
        /**
         * Titles that were deemed invalid by Title::newFromText()
         * The array's index will be unique and negative for each item
-        * @return array of strings (not Title objects)
+        * @return string[] Array of strings (not Title objects)
         */
        public function getInvalidTitles() {
                return $this->mInvalidTitles;
index d9aacaa..32a03f1 100644 (file)
@@ -493,7 +493,7 @@ abstract class ApiQueryBase extends ApiBase {
                if ( !$t ) {
                        $this->dieUsageMsg( array( 'invalidtitle', $titlePart ) );
                }
-               if ( $defaultNamespace != $t->getNamespace() || $t->getInterwiki() !== '' ) {
+               if ( $defaultNamespace != $t->getNamespace() || $t->isExternal() ) {
                        // This can happen in two cases. First, if you call titlePartToKey with a title part
                        // that looks like a namespace, but with $defaultNamespace = NS_MAIN. It would be very
                        // difficult to handle such a case. Such cases cannot exist and are therefore treated
index 1a642b9..7d0d78e 100644 (file)
  * @ingroup API
  */
 class ApiUpload extends ApiBase {
-
-       /**
-        * @var UploadBase
-        */
+       /** @var UploadBase */
        protected $mUpload = null;
 
        protected $mParams;
index b7d0a7c..28889b5 100644 (file)
  */
 class DependencyWrapper {
        private $value;
+       /** @var CacheDependency[] */
        private $deps;
 
        /**
         * Create an instance.
         * @param $value Mixed: the user-supplied value
-        * @param $deps Mixed: a dependency or dependency array. All dependencies
-        *        must be objects implementing CacheDependency.
+        * @param CacheDependency|CacheDependency[] $deps A dependency or dependency
+        *   array. All dependencies must be objects implementing CacheDependency.
         */
        function __construct( $value = false, $deps = array() ) {
                $this->value = $value;
index 47a5904..cba2ba7 100644 (file)
@@ -1232,9 +1232,16 @@ class LCStoreDB implements LCStore {
  * See Cdb.php and http://cr.yp.to/cdb.html
  */
 class LCStoreCDB implements LCStore {
+       /** @var CdbReader[] */
        private $readers;
+
+       /** @var CdbWriter */
        private $writer;
+
+       /** @var string Current language code */
        private $currentLang;
+
+       /** @var bool|string Cache directory. False if not set */
        private $directory;
 
        function __construct( $conf = array() ) {
index 8b52728..3dee806 100644 (file)
@@ -124,7 +124,7 @@ class MessageCache {
        }
 
        /**
-        * @param ObjectCache $memCached A cache instance. If none, fall back to CACHE_NONE.
+        * @param BagOStuff $memCached A cache instance. If none, fall back to CACHE_NONE.
         * @param bool $useDB
         * @param int $expiry Lifetime for cache. @see $mExpiry.
         */
index 8be8530..a314605 100644 (file)
@@ -270,21 +270,21 @@ EOT;
         * @return string
         */
        private function fileCachedPage() {
-               global $wgTitle, $wgOut, $wgRequest;
+               $context = RequestContext::getMain();
 
-               if ( $wgOut->isDisabled() ) {
+               if ( $context->getOutput()->isDisabled() ) {
                        // Done already?
                        return '';
                }
 
-               if ( $wgTitle ) {
-                       // use $wgTitle if we managed to set it
-                       $t = $wgTitle->getPrefixedDBkey();
+               if ( $context->getTitle() ) {
+                       // Use the main context's title if we managed to set it
+                       $t = $context->getTitle()->getPrefixedDBkey();
                } else {
                        // Fallback to the raw title URL param. We can't use the Title
                        // class is it may hit the interwiki table and give a DB error.
                        // We may get a cache miss due to not sanitizing the title though.
-                       $t = str_replace( ' ', '_', $wgRequest->getVal( 'title' ) );
+                       $t = str_replace( ' ', '_', $context->getRequest()->getVal( 'title' ) );
                        if ( $t == '' ) { // fallback to main page
                                $t = Title::newFromText(
                                        $this->msg( 'mainpage', 'Main Page' ) )->getPrefixedDBkey();
index 08fb2c9..1e0bbc0 100644 (file)
@@ -95,7 +95,7 @@ abstract class DatabaseMysqlBase extends DatabaseBase {
 
                        wfProfileOut( __METHOD__ );
 
-                       return $this->reportConnectionError( $error );
+                       $this->reportConnectionError( $error );
                }
 
                if ( $dbName != '' ) {
@@ -109,13 +109,13 @@ abstract class DatabaseMysqlBase extends DatabaseBase {
 
                                wfProfileOut( __METHOD__ );
 
-                               return $this->reportConnectionError( "Error selecting database $dbName" );
+                               $this->reportConnectionError( "Error selecting database $dbName" );
                        }
                }
 
                // Tell the server what we're communicating with
                if ( !$this->connectInitCharset() ) {
-                       return $this->reportConnectionError( "Error setting character set" );
+                       $this->reportConnectionError( "Error setting character set" );
                }
 
                // Set SQL mode, default is turning them all off, can be overridden or skipped with null
@@ -126,7 +126,7 @@ abstract class DatabaseMysqlBase extends DatabaseBase {
                        if ( !$success ) {
                                wfLogDBError( "Error setting sql_mode to $mode on server {$this->mServer}" );
                                wfProfileOut( __METHOD__ );
-                               return $this->reportConnectionError( "Error setting sql_mode to $mode" );
+                               $this->reportConnectionError( "Error setting sql_mode to $mode" );
                        }
                }
 
@@ -1217,7 +1217,11 @@ class MySQLField implements Field {
 }
 
 class MySQLMasterPos implements DBMasterPos {
-       var $file, $pos;
+       /** @var string */
+       private $file;
+
+       /** @var int */
+       private $pos;
 
        function __construct( $file, $pos ) {
                $this->file = $file;
index 7410e49..21a7bcf 100644 (file)
@@ -135,8 +135,7 @@ SQL;
  * @ingroup Database
  */
 class PostgresTransactionState {
-
-       static $WATCHED = array(
+       private static $WATCHED = array(
                array(
                        "desc" => "%s: Connection state changed from %s -> %s\n",
                        "states" => array(
@@ -156,6 +155,12 @@ class PostgresTransactionState {
                )
        );
 
+       /** @var array */
+       private $mNewState;
+
+       /** @var array */
+       private $mCurrentState;
+
        public function __construct( $conn ) {
                $this->mConn = $conn;
                $this->update();
@@ -284,10 +289,26 @@ class SavepointPostgres {
  * @ingroup Database
  */
 class DatabasePostgres extends DatabaseBase {
-       var $mInsertId = null;
-       var $mLastResult = null;
-       var $numeric_version = null;
-       var $mAffectedRows = null;
+       /** @var resource */
+       protected $mLastResult = null;
+
+       /** @var int The number of rows affected as an integer */
+       protected $mAffectedRows = null;
+
+       /** @var int */
+       private $mInsertId = null;
+
+       /** @var float|string */
+       private $numericVersion = null;
+
+       /** @var string Connect string to open a PostgreSQL connection */
+       private $connectString;
+
+       /** @var PostgresTransactionState */
+       private $mTransactionState;
+
+       /** @var string */
+       private $mCoreSchema;
 
        function getType() {
                return 'postgres';
@@ -602,7 +623,7 @@ class DatabasePostgres extends DatabaseBase {
         * Return the result of the last call to nextSequenceValue();
         * This must be called after nextSequenceValue().
         *
-        * @return integer|null
+        * @return int|null
         */
        function insertId() {
                return $this->mInsertId;
@@ -788,7 +809,7 @@ __INDEXATTR__;
                }
 
                $table = $this->tableName( $table );
-               if ( !isset( $this->numeric_version ) ) {
+               if ( !isset( $this->numericVersion ) ) {
                        $this->getServerVersion();
                }
 
@@ -817,7 +838,7 @@ __INDEXATTR__;
                $sql = "INSERT INTO $table (" . implode( ',', $keys ) . ') VALUES ';
 
                if ( $multi ) {
-                       if ( $this->numeric_version >= 8.2 && !$savepoint ) {
+                       if ( $this->numericVersion >= 8.2 && !$savepoint ) {
                                $first = true;
                                foreach ( $args as $row ) {
                                        if ( $first ) {
@@ -981,7 +1002,9 @@ __INDEXATTR__;
 
        /**
         * Return the next in a sequence, save the value for retrieval via insertId()
-        * @return null
+        * 
+        * @param string $seqName
+        * @return int|null
         */
        function nextSequenceValue( $seqName ) {
                $safeseq = str_replace( "'", "''", $seqName );
@@ -994,6 +1017,8 @@ __INDEXATTR__;
 
        /**
         * Return the current value of a sequence. Assumes it has been nextval'ed in this session.
+        *
+        * @param string $seqName
         * @return
         */
        function currentSequenceValue( $seqName ) {
@@ -1123,7 +1148,7 @@ __INDEXATTR__;
         * Needs transaction
         *
         * @since 1.19
-        * @return string return default schema for the current session
+        * @return string Default schema for the current session
         */
        function getCurrentSchema() {
                $res = $this->query( "SELECT current_schema()", __METHOD__ );
@@ -1236,21 +1261,21 @@ __INDEXATTR__;
         * @return string Version information from the database
         */
        function getServerVersion() {
-               if ( !isset( $this->numeric_version ) ) {
+               if ( !isset( $this->numericVersion ) ) {
                        $versionInfo = pg_version( $this->mConn );
                        if ( version_compare( $versionInfo['client'], '7.4.0', 'lt' ) ) {
                                // Old client, abort install
-                               $this->numeric_version = '7.3 or earlier';
+                               $this->numericVersion = '7.3 or earlier';
                        } elseif ( isset( $versionInfo['server'] ) ) {
                                // Normal client
-                               $this->numeric_version = $versionInfo['server'];
+                               $this->numericVersion = $versionInfo['server'];
                        } else {
                                // Bug 16937: broken pgsql extension from PHP<5.3
-                               $this->numeric_version = pg_parameter_status( $this->mConn, 'server_version' );
+                               $this->numericVersion = pg_parameter_status( $this->mConn, 'server_version' );
                        }
                }
 
-               return $this->numeric_version;
+               return $this->numericVersion;
        }
 
        /**
@@ -1428,12 +1453,12 @@ SQL;
        protected function replaceVars( $ins ) {
                $ins = parent::replaceVars( $ins );
 
-               if ( $this->numeric_version >= 8.3 ) {
+               if ( $this->numericVersion >= 8.3 ) {
                        // Thanks for not providing backwards-compatibility, 8.3
                        $ins = preg_replace( "/to_tsvector\s*\(\s*'default'\s*,/", 'to_tsvector(', $ins );
                }
 
-               if ( $this->numeric_version <= 8.1 ) { // Our minimum version
+               if ( $this->numericVersion <= 8.1 ) { // Our minimum version
                        $ins = str_replace( 'USING gin', 'USING gist', $ins );
                }
 
index c4e7976..847e173 100644 (file)
  * @ingroup Database
  */
 abstract class LBFactory {
-       /**
-        * @var LBFactory
-        */
-       static $instance;
+       /** @var LBFactory */
+       protected static $instance;
 
        /**
         * Disables all access to the load balancer, will cause all database access
@@ -46,10 +44,12 @@ abstract class LBFactory {
         * @return LBFactory
         */
        static function &singleton() {
+               global $wgLBFactoryConf;
+
                if ( is_null( self::$instance ) ) {
-                       $LBFactoryConf = self::getLBFactoryClass();
+                       $class = self::getLBFactoryClass( $wgLBFactoryConf );
 
-                       self::$instance = new $LBFactoryConf[0]( $LBFactoryConf[1] );
+                       self::$instance = new $class( $wgLBFactoryConf );
                }
 
                return self::$instance;
@@ -58,11 +58,11 @@ abstract class LBFactory {
        /**
         * Returns the LBFactory class to use and the load balancer configuration.
         *
-        * @return array ( factory class, $wgLBFactoryConf )
+        * @param array $config (e.g. $wgLBFactoryConf)
+        *
+        * @return string class name
         */
-       static function getLBFactoryClass() {
-               global $wgLBFactoryConf;
-
+       public static function getLBFactoryClass( array $config ) {
                // For configuration backward compatibility after removing
                // underscores from class names in MediaWiki 1.23.
                $bcClasses = array(
@@ -72,9 +72,9 @@ abstract class LBFactory {
                        'LBFactory_Fake' => 'LBFactoryFake',
                );
 
-               $class = $wgLBFactoryConf['class'];
+               $class = $config['class'];
 
-               if ( in_array( $class, array_keys( $bcClasses ) ) ) {
+               if ( isset( $bcClasses[$class] ) ) {
                        $class = $bcClasses[$class];
                        wfDeprecated(
                                '$wgLBFactoryConf must be updated. See RELEASE-NOTES for details',
@@ -82,7 +82,7 @@ abstract class LBFactory {
                        );
                }
 
-               return array( $class, $wgLBFactoryConf );
+               return $class;
        }
 
        /**
@@ -198,15 +198,14 @@ abstract class LBFactory {
  * A simple single-master LBFactory that gets its configuration from the b/c globals
  */
 class LBFactorySimple extends LBFactory {
+       /** @var LoadBalancer */
+       protected $mainLB;
 
-       /**
-        * @var LoadBalancer
-        */
-       var $mainLB;
-       var $extLBs = array();
+       /** @var LoadBalancer[] */
+       protected $extLBs = array();
 
-       # Chronology protector
-       var $chronProt;
+       /** @var ChronologyProtector */
+       protected $chronProt;
 
        function __construct( $conf ) {
                $this->chronProt = new ChronologyProtector;
index 2f4cb57..2ab0554 100644 (file)
@@ -26,7 +26,7 @@
  * Ignores the old configuration globals
  *
  * Configuration:
- *     sectionsByDB                A map of database names to section names
+ *     sectionsByDB                A map of database names to section names.
  *
  *     sectionLoads                A 2-d map. For each section, gives a map of server names to
  *                                 load ratios. For example:
  *
  *     hostsByName                 A map of hostname to IP address.
  *
- *     externalLoads               A map of external storage cluster name to server load map
+ *     externalLoads               A map of external storage cluster name to server load map.
  *
  *     externalTemplateOverrides   A set of server info keys overriding serverTemplate for external
- *                                 storage
+ *                                 storage.
  *
  *     templateOverridesByServer   A 2-d map overriding serverTemplate and
  *                                 externalTemplateOverrides on a server-by-server basis. Applies
  *                                 to both core and external storage.
  *
- *     templateOverridesByCluster  A 2-d map overriding the server info by external storage cluster
+ *     templateOverridesByCluster  A 2-d map overriding the server info by external storage cluster.
  *
  *     masterTemplateOverrides     An override array for all master servers.
  *
  */
 class LBFactoryMulti extends LBFactory {
        // Required settings
-       var $sectionsByDB, $sectionLoads, $serverTemplate;
+
+       /** @var array A map of database names to section names */
+       protected $sectionsByDB;
+
+       /**
+        * @var array A 2-d map. For each section, gives a map of server names to
+        * load ratios
+        */
+       protected $sectionLoads;
+
+       /**
+        * @var array A server info associative array as documented for
+        * $wgDBservers. The host, hostName and load entries will be
+        * overridden
+        */
+       protected $serverTemplate;
+
        // Optional settings
-       var $groupLoadsBySection = array(), $groupLoadsByDB = array(), $hostsByName = array();
-       var $externalLoads = array(), $externalTemplateOverrides, $templateOverridesByServer;
-       var $templateOverridesByCluster, $masterTemplateOverrides, $readOnlyBySection = array();
+
+       /** @var array A 3-d map giving server load ratios for each section and group */
+       protected $groupLoadsBySection = array();
+
+       /** @var array A 3-d map giving server load ratios by DB name */
+       protected $groupLoadsByDB = array();
+
+       /** @var array A map of hostname to IP address */
+       protected $hostsByName = array();
+
+       /** @var array A map of external storage cluster name to server load map */
+       protected $externalLoads = array();
+
+       /**
+        * @var array A set of server info keys overriding serverTemplate for
+        * external storage
+        */
+       protected $externalTemplateOverrides;
+
+       /**
+        * @var array A 2-d map overriding serverTemplate and
+        * externalTemplateOverrides on a server-by-server basis. Applies to both
+        * core and external storage
+        */
+       protected $templateOverridesByServer;
+
+       /** @var array A 2-d map overriding the server info by external storage cluster */
+       protected $templateOverridesByCluster;
+
+       /** @var array An override array for all master servers */
+       protected $masterTemplateOverrides;
+
+       /**
+        * @var array|bool A map of section name to read-only message. Missing or
+        * false for read/write
+        */
+       protected $readOnlyBySection = array();
+
        // Other stuff
-       var $conf, $mainLBs = array(), $extLBs = array();
-       var $lastWiki, $lastSection;
+
+       /** @var array Load balancer factory configuration */
+       protected $conf;
+
+       /** @var LoadBalancer[] */
+       protected $mainLBs = array();
+
+       /** @var LoadBalancer[] */
+       protected $extLBs = array();
+
+       /** @var string */
+       protected $lastWiki;
+
+       /** @var string */
+       protected $lastSection;
 
        /**
         * @param $conf array
index bac9f10..85592e8 100644 (file)
@@ -216,6 +216,11 @@ class SquidUpdate {
 
                // Remove duplicate URLs from collection
                $urlArr = array_unique( $urlArr );
+               // Get sequential trx IDs for packet loss counting
+               $ids = UIDGenerator::newSequentialPerNodeIDs(
+                       'squidhtcppurge', 32, count( $urlArr ), UIDGenerator::QUICK_VOLATILE
+               );
+
                foreach ( $urlArr as $url ) {
                        if ( !is_string( $url ) ) {
                                wfProfileOut( __METHOD__ );
@@ -243,7 +248,8 @@ class SquidUpdate {
                        // Construct a minimal HTCP request diagram
                        // as per RFC 2756
                        // Opcode 'CLR', no response desired, no auth
-                       $htcpTransID = rand();
+                       $htcpTransID = current( $ids );
+                       next( $ids );
 
                        $htcpSpecifier = pack( 'na4na*na8n',
                                4, 'HEAD', strlen( $url ), $url,
index 79ff4e8..e7a269a 100644 (file)
@@ -358,7 +358,7 @@ class JobQueueDB extends JobQueue {
                                // Instead, this uses job_random to pick a row (possibly checking both directions).
                                $ineq = $gte ? '>=' : '<=';
                                $dir = $gte ? 'ASC' : 'DESC';
-                               $row = $dbw->selectRow( 'job', '*', // find a random job
+                               $row = $dbw->selectRow( 'job', self::selectFields(), // find a random job
                                        array(
                                                'job_cmd' => $this->type,
                                                'job_token' => '', // unclaimed
@@ -375,7 +375,7 @@ class JobQueueDB extends JobQueue {
                                // Bug 42614: "ORDER BY job_random" with a job_random inequality causes high CPU
                                // in MySQL if there are many rows for some reason. This uses a small OFFSET
                                // instead of job_random for reducing excess claim retries.
-                               $row = $dbw->selectRow( 'job', '*', // find a random job
+                               $row = $dbw->selectRow( 'job', self::selectFields(), // find a random job
                                        array(
                                                'job_cmd' => $this->type,
                                                'job_token' => '', // unclaimed
@@ -459,7 +459,7 @@ class JobQueueDB extends JobQueue {
                        }
                        // Fetch any row that we just reserved...
                        if ( $dbw->affectedRows() ) {
-                               $row = $dbw->selectRow( 'job', '*',
+                               $row = $dbw->selectRow( 'job', self::selectFields(),
                                        array( 'job_cmd' => $this->type, 'job_token' => $uuid ), __METHOD__
                                );
                                if ( !$row ) { // raced out by duplicate job removal
@@ -589,7 +589,7 @@ class JobQueueDB extends JobQueue {
                $dbr = $this->getSlaveDB();
                try {
                        return new MappedIterator(
-                               $dbr->select( 'job', '*',
+                               $dbr->select( 'job', self::selectFields(),
                                        array( 'job_cmd' => $this->getType(), 'job_token' => '' ) ),
                                function ( $row ) use ( $dbr ) {
                                        $job = Job::factory(
@@ -824,4 +824,25 @@ class JobQueueDB extends JobQueue {
        protected function throwDBException( DBError $e ) {
                throw new JobQueueError( get_class( $e ) . ": " . $e->getMessage() );
        }
+
+       /**
+        * Return the list of job fields that should be selected.
+        * @since 1.23
+        * @return array
+        */
+       public static function selectFields() {
+               return array(
+                       'job_id',
+                       'job_cmd',
+                       'job_namespace',
+                       'job_title',
+                       'job_timestamp',
+                       'job_params',
+                       'job_random',
+                       'job_attempts',
+                       'job_token',
+                       'job_token_timestamp',
+                       'job_sha1',
+               );
+       }
 }
index 99d7527..94b56ef 100644 (file)
@@ -197,7 +197,7 @@ class DoubleRedirectJob extends Job {
                        }
                        $seenTitles[$titleText] = true;
 
-                       if ( $title->getInterwiki() ) {
+                       if ( $title->isExternal() ) {
                                // If the target is interwiki, we have to break early (bug 40352).
                                // Otherwise it will look up a row in the local page table
                                // with the namespace/page of the interwiki target which can cause
diff --git a/includes/libs/MWMessagePack.php b/includes/libs/MWMessagePack.php
new file mode 100644 (file)
index 0000000..c61e8f8
--- /dev/null
@@ -0,0 +1,188 @@
+<?php
+/**
+ * MessagePack serializer
+ *
+ * MessagePack is a space-efficient binary data interchange format. This
+ * class provides a pack() method that encodes native PHP values as MessagePack
+ * binary strings. The implementation is derived from msgpack-php.
+ *
+ * Copyright (c) 2013 Ori Livneh <ori@wikimedia.org>
+ * Copyright (c) 2011 OnlineCity <https://github.com/onlinecity/msgpack-php>.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ *
+ * @see <http://msgpack.org/>
+ * @see <http://wiki.msgpack.org/display/MSGPACK/Format+specification>
+ *
+ * @since 1.23
+ * @file
+ */
+class MWMessagePack {
+
+       /** @var boolean|null Whether current system is bigendian. **/
+       public static $bigendian = null;
+
+       /**
+        * Encode a value using MessagePack
+        *
+        * This method supports null, boolean, integer, float, string and array
+        * (both indexed and associative) types. Object serialization is not
+        * supported.
+        *
+        * @param mixed $value
+        * @return string
+        * @throws InvalidArgumentException if $value is an unsupported type or too long a string
+        */
+       public static function pack( $value ) {
+               if ( self::$bigendian === null ) {
+                       self::$bigendian = pack( 'S', 1 ) === pack( 'n', 1 );
+               }
+
+               switch ( gettype( $value ) ) {
+               case 'NULL':
+                       return "\xC0";
+
+               case 'boolean':
+                       return $value ? "\xC3" : "\xC2";
+
+               case 'double':
+               case 'float':
+                       return self::$bigendian
+                               ? "\xCB" . pack( 'd', $value )
+                               : "\xCB" . strrev( pack( 'd', $value ) );
+
+               case 'string':
+                       $length = strlen( $value );
+                       if ( $length < 32 ) {
+                               return pack( 'Ca*', 0xA0 | $length, $value );
+                       } elseif ( $length <= 0xFFFF ) {
+                               return pack( 'Cna*', 0xDA, $length, $value );
+                       } elseif ( $length <= 0xFFFFFFFF ) {
+                               return pack( 'CNa*', 0xDB, $length, $value );
+                       }
+                       throw new InvalidArgumentException( __METHOD__ . ": string too long (length: $length; max: 4294967295)" );
+
+               case 'integer':
+                       if ( $value >= 0 ) {
+                               if ( $value <= 0x7F ) {
+                                       // positive fixnum
+                                       return chr( $value );
+                               }
+                               if ( $value <= 0xFF ) {
+                                       // uint8
+                                       return pack( 'CC', 0xCC, $value );
+                               }
+                               if ( $value <= 0xFFFF ) {
+                                       // uint16
+                                       return pack( 'Cn', 0xCD, $value );
+                               }
+                               if ( $value <= 0xFFFFFFFF ) {
+                                       // uint32
+                                       return pack( 'CN', 0xCE, $value );
+                               }
+                               if ( $value <= 0xFFFFFFFFFFFFFFFF ) {
+                                       // uint64
+                                       $hi = ( $value & 0xFFFFFFFF00000000 ) >> 32;
+                                       $lo = $value & 0xFFFFFFFF;
+                                       return self::$bigendian
+                                               ? pack( 'CNN', 0xCF, $lo, $hi )
+                                               : pack( 'CNN', 0xCF, $hi, $lo );
+                               }
+                       } else {
+                               if ( $value >= -32 ) {
+                                       // negative fixnum
+                                       return pack( 'c', $value );
+                               }
+                               if ( $value >= -0x80 ) {
+                                       // int8
+                                       return pack( 'Cc', 0xD0, $value );
+                               }
+                               if ( $value >= -0x8000 ) {
+                                       // int16
+                                       $p = pack( 's', $value );
+                                       return self::$bigendian
+                                               ? pack( 'Ca2', 0xD1, $p )
+                                               : pack( 'Ca2', 0xD1, strrev( $p ) );
+                               }
+                               if ( $value >= -0x80000000 ) {
+                                       // int32
+                                       $p = pack( 'l', $value );
+                                       return self::$bigendian
+                                               ? pack( 'Ca4', 0xD2, $p )
+                                               : pack( 'Ca4', 0xD2, strrev( $p ) );
+                               }
+                               if ( $value >= -0x8000000000000000 ) {
+                                       // int64
+                                       // pack() does not support 64-bit ints either so pack into two 32-bits
+                                       $p1 = pack( 'l', $value & 0xFFFFFFFF );
+                                       $p2 = pack( 'l', ( $value >> 32 ) & 0xFFFFFFFF );
+                                       return self::$bigendian
+                                               ? pack( 'Ca4a4', 0xD3, $p1, $p2 )
+                                               : pack( 'Ca4a4', 0xD3, strrev( $p2 ), strrev( $p1 ) );
+                               }
+                       }
+                       throw new InvalidArgumentException( __METHOD__ . ": invalid integer '$value'" );
+
+               case 'array':
+                       $buffer = '';
+                       $length = count( $value );
+                       if ( $length > 0xFFFFFFFF ) {
+                               throw new InvalidArgumentException( __METHOD__ . ": array too long (length: $length, max: 4294967295)" );
+                       }
+
+                       $index = 0;
+                       foreach ( $value as $k => $v ) {
+                               if ( $index !== $k || $index === $length ) {
+                                       break;
+                               } else {
+                                       $index++;
+                               }
+                       }
+                       $associative = $index !== $length;
+
+                       if ( $associative ) {
+                               if ( $length < 16 ) {
+                                       $buffer .= pack( 'C', 0x80 | $length );
+                               } elseif ( $length <= 0xFFFF ) {
+                                       $buffer .= pack( 'Cn', 0xDE, $length );
+                               } else {
+                                       $buffer .= pack( 'CN', 0xDF, $length );
+                               }
+                               foreach ( $value as $k => $v ) {
+                                       $buffer .= self::pack( $k );
+                                       $buffer .= self::pack( $v );
+                               }
+                       } else {
+                               if ( $length < 16 ) {
+                                       $buffer .= pack( 'C', 0x90 | $length );
+                               } elseif ( $length <= 0xFFFF ) {
+                                       $buffer .= pack( 'Cn', 0xDC, $length );
+                               } else {
+                                       $buffer .= pack( 'CN', 0xDD, $length );
+                               }
+                               foreach ( $value as $v ) {
+                                       $buffer .= self::pack( $v );
+                               }
+                       }
+                       return $buffer;
+
+               default:
+                       throw new InvalidArgumentException( __METHOD__ . ': unsupported type ' . gettype( $value ) );
+               }
+       }
+}
diff --git a/includes/libs/RunningStat.php b/includes/libs/RunningStat.php
new file mode 100644 (file)
index 0000000..dda5254
--- /dev/null
@@ -0,0 +1,176 @@
+<?php
+/**
+ * Compute running mean, variance, and extrema of a stream of numbers.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ *
+ * @file
+ * @ingroup Profiler
+ */
+
+// Needed due to PHP non-bug <https://bugs.php.net/bug.php?id=49828>.
+define( 'NEGATIVE_INF', -INF );
+
+/**
+ * Represents a running summary of a stream of numbers.
+ *
+ * RunningStat instances are accumulator-like objects that provide a set of
+ * continuously-updated summary statistics for a stream of numbers, without
+ * requiring that each value be stored. The measures it provides are the
+ * arithmetic mean, variance, standard deviation, and extrema (min and max);
+ * together they describe the central tendency and statistical dispersion of a
+ * set of values.
+ *
+ * One RunningStat instance can be merged into another; the resultant
+ * RunningStat has the state it would have had if it had accumulated each
+ * individual point. This allows data to be summarized in parallel and in
+ * stages without loss of fidelity.
+ *
+ * Based on a C++ implementation by John D. Cook:
+ *  <http://www.johndcook.com/standard_deviation.html>
+ *  <http://www.johndcook.com/skewness_kurtosis.html>
+ *
+ * The in-line documentation for this class incorporates content from the
+ * English Wikipedia articles "Variance", "Algorithms for calculating
+ * variance", and "Standard deviation".
+ *
+ * @since 1.23
+ */
+class RunningStat implements Countable {
+
+       /** @var int Number of samples. **/
+       public $n = 0;
+
+       /** @var float The first moment (or mean, or expected value). **/
+       public $m1 = 0.0;
+
+       /** @var float The second central moment (or variance). **/
+       public $m2 = 0.0;
+
+       /** @var float The least value in the the set. **/
+       public $min = INF;
+
+       /** @var float The most value in the set. **/
+       public $max = NEGATIVE_INF;
+
+       /**
+        * Count the number of accumulated values.
+        * @return int Number of values
+        */
+       public function count() {
+               return $this->n;
+       }
+
+       /**
+        * Add a number to the data set.
+        * @param int|float $x Value to add
+        */
+       public function push( $x ) {
+               $x = (float) $x;
+
+               $this->min = min( $this->min, $x );
+               $this->max = max( $this->max, $x );
+
+               $n1 = $this->n;
+               $this->n += 1;
+               $delta = $x - $this->m1;
+               $delta_n = $delta / $this->n;
+               $this->m1 += $delta_n;
+               $this->m2 += $delta * $delta_n * $n1;
+       }
+
+       /**
+        * Get the mean, or expected value.
+        *
+        * The arithmetic mean is the sum of all measurements divided by the number
+        * of observations in the data set.
+        *
+        * @return float Mean
+        */
+       public function getMean() {
+               return $this->m1;
+       }
+
+       /**
+        * Get the estimated variance.
+        *
+        * Variance measures how far a set of numbers is spread out. A small
+        * variance indicates that the data points tend to be very close to the
+        * mean (and hence to each other), while a high variance indicates that the
+        * data points are very spread out from the mean and from each other.
+        *
+        * @return float Estimated variance
+        */
+       public function getVariance() {
+               if ( $this->n === 0 ) {
+                       // The variance of the empty set is undefined.
+                       return NAN;
+               } elseif ( $this->n === 1 ) {
+                       return 0.0;
+               } else {
+                       return $this->m2 / ( $this->n - 1.0 );
+               }
+       }
+
+       /**
+        * Get the estimated stanard deviation.
+        *
+        * The standard deviation of a statistical population is the square root of
+        * its variance. It shows shows how much variation from the mean exists. In
+        * addition to expressing the variability of a population, the standard
+        * deviation is commonly used to measure confidence in statistical conclusions.
+        *
+        * @return float Estimated standard deviation
+        */
+       public function getStdDev() {
+               return sqrt( $this->getVariance() );
+       }
+
+       /**
+        * Merge another RunningStat instance into this instance.
+        *
+        * This instance then has the state it would have had if all the data had
+        * been accumulated by it alone.
+        *
+        * @param RunningStat RunningStat instance to merge into this one
+        */
+       public function merge( RunningStat $other ) {
+               // If the other RunningStat is empty, there's nothing to do.
+               if ( $other->n === 0 ) {
+                       return;
+               }
+
+               // If this RunningStat is empty, copy values from other RunningStat.
+               if ( $this->n === 0 ) {
+                       $this->n = $other->n;
+                       $this->m1 = $other->m1;
+                       $this->m2 = $other->m2;
+                       $this->min = $other->min;
+                       $this->max = $other->max;
+                       return;
+               }
+
+               $n = $this->n + $other->n;
+               $delta = $other->m1 - $this->m1;
+               $delta2 = $delta * $delta;
+
+               $this->m1 = ( ( $this->n * $this->m1 ) + ( $other->n * $other->m1 ) ) / $n;
+               $this->m2 = $this->m2 + $other->m2 + ( $delta2 * $this->n * $other->n / $n );
+               $this->min = min( $this->min, $other->min );
+               $this->max = max( $this->max, $other->max );
+               $this->n = $n;
+       }
+}
index d761a87..b658ac1 100644 (file)
@@ -79,13 +79,16 @@ class DeleteLogFormatter extends LogFormatter {
                                $count = count( explode( ',', $params[$paramStart] ) );
                                $newParams[4] = $this->context->getLanguage()->formatNum( $count );
 
-                               return $this->parsedParametersDeleteLog = $newParams;
+                               $this->parsedParametersDeleteLog = $newParams;
+                               return $this->parsedParametersDeleteLog;
                        } else {
-                               return $this->parsedParametersDeleteLog = array_slice( $params, 0, 3 );
+                               $this->parsedParametersDeleteLog = array_slice( $params, 0, 3 );
+                               return $this->parsedParametersDeleteLog;
                        }
                }
 
-               return $this->parsedParametersDeleteLog = $params;
+               $this->parsedParametersDeleteLog = $params;
+               return $this->parsedParametersDeleteLog;
        }
 
        protected function parseBitField( $string ) {
index 084a4b2..9e7f056 100644 (file)
@@ -455,7 +455,8 @@ class LogFormatter {
                // Bad things happens if the numbers are not in correct order
                ksort( $params );
 
-               return $this->parsedParameters = $params;
+               $this->parsedParameters = $params;
+               return $this->parsedParameters;
        }
 
        /**
@@ -737,7 +738,8 @@ class LegacyLogFormatter extends LogFormatter {
                }
 
                if ( $this->entry->isDeleted( LogPage::DELETED_ACTION ) ) {
-                       return $this->revert = '';
+                       $this->revert = '';
+                       return $this->revert;
                }
 
                $title = $this->entry->getTarget();
index 7efb23d..900ece9 100644 (file)
@@ -154,15 +154,15 @@ class LogPager extends ReverseChronologicalPager {
         * Set the log reader to return only entries by the given user.
         *
         * @param string $name (In)valid user name
-        * @return bool
+        * @return void
         */
        private function limitPerformer( $name ) {
                if ( $name == '' ) {
-                       return false;
+                       return;
                }
                $usertitle = Title::makeTitleSafe( NS_USER, $name );
                if ( is_null( $usertitle ) ) {
-                       return false;
+                       return;
                }
                /* Fetch userid at first, if known, provides awesome query plan afterwards */
                $userid = User::idFromName( $name );
@@ -179,6 +179,7 @@ class LogPager extends ReverseChronologicalPager {
                        $this->mConds[] = $this->mDb->bitAnd( 'log_deleted', LogPage::SUPPRESSED_USER ) .
                                ' != ' . LogPage::SUPPRESSED_USER;
                }
+
                $this->performer = $usertitle->getText();
        }
 
@@ -188,7 +189,7 @@ class LogPager extends ReverseChronologicalPager {
         *
         * @param string|Title $page Title name
         * @param string $pattern
-        * @return bool
+        * @return void
         */
        private function limitTitle( $page, $pattern ) {
                global $wgMiserMode;
@@ -198,7 +199,7 @@ class LogPager extends ReverseChronologicalPager {
                } else {
                        $title = Title::newFromText( $page );
                        if ( strlen( $page ) == 0 || !$title instanceof Title ) {
-                               return false;
+                               return;
                        }
                }
 
index 27065e5..d81ad98 100644 (file)
@@ -3079,8 +3079,6 @@ class Parser {
         * cache may be implemented at a later date which takes further advantage of these strict
         * dependency requirements.
         *
-        * @private
-        *
         * @return PPNode
         */
        function preprocessToDom( $text, $flags = 0 ) {
index dae0c68..9eaa3e2 100644 (file)
@@ -213,11 +213,11 @@ class ParserCache {
 
        /**
         * @param ParserOutput $parserOutput
-        * @param Article $article
+        * @param WikiPage $page
         * @param ParserOptions $popts
         * @param string $cacheTime Time when the cache was generated
         */
-       public function save( $parserOutput, $article, $popts, $cacheTime = null ) {
+       public function save( $parserOutput, $page, $popts, $cacheTime = null ) {
                $expire = $parserOutput->getCacheExpiry();
                if ( $expire > 0 ) {
                        $cacheTime = $cacheTime ?: wfTimestampNow();
@@ -231,11 +231,11 @@ class ParserCache {
 
                        $optionsKey->setContainsOldMagic( $parserOutput->containsOldMagic() );
 
-                       $parserOutputKey = $this->getParserOutputKey( $article,
-                               $popts->optionsHash( $optionsKey->mUsedOptions, $article->getTitle() ) );
+                       $parserOutputKey = $this->getParserOutputKey( $page,
+                               $popts->optionsHash( $optionsKey->mUsedOptions, $page->getTitle() ) );
 
                        // Save the timestamp so that we don't have to load the revision row on view
-                       $parserOutput->setTimestamp( $article->getTimestamp() );
+                       $parserOutput->setTimestamp( $page->getTimestamp() );
 
                        $parserOutput->mText .= "\n<!-- Saved in parser cache with key $parserOutputKey and timestamp $cacheTime\n -->\n";
                        wfDebug( "Saved in parser cache with key $parserOutputKey and timestamp $cacheTime\n" );
@@ -244,7 +244,7 @@ class ParserCache {
                        $this->mMemc->set( $parserOutputKey, $parserOutput, $expire );
 
                        // ...and its pointer
-                       $this->mMemc->set( $this->getOptionsKey( $article ), $optionsKey, $expire );
+                       $this->mMemc->set( $this->getOptionsKey( $page ), $optionsKey, $expire );
                } else {
                        wfDebug( "Parser output was marked as uncacheable and has not been saved.\n" );
                }
index 76d14cf..8cd978b 100644 (file)
@@ -279,10 +279,10 @@ class ParserOutput extends CacheTime {
         * @throws MWException if given invalid input
         */
        function addInterwikiLink( $title ) {
-               $prefix = $title->getInterwiki();
-               if ( $prefix == '' ) {
+               if ( !$title->isExternal() ) {
                        throw new MWException( 'Non-interwiki link passed, internal parser error.' );
                }
+               $prefix = $title->getInterwiki();
                if ( !isset( $this->mInterwikiLinks[$prefix] ) ) {
                        $this->mInterwikiLinks[$prefix] = array();
                }
diff --git a/includes/profiler/RunningStat.php b/includes/profiler/RunningStat.php
deleted file mode 100644 (file)
index dda5254..0000000
+++ /dev/null
@@ -1,176 +0,0 @@
-<?php
-/**
- * Compute running mean, variance, and extrema of a stream of numbers.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- * http://www.gnu.org/copyleft/gpl.html
- *
- * @file
- * @ingroup Profiler
- */
-
-// Needed due to PHP non-bug <https://bugs.php.net/bug.php?id=49828>.
-define( 'NEGATIVE_INF', -INF );
-
-/**
- * Represents a running summary of a stream of numbers.
- *
- * RunningStat instances are accumulator-like objects that provide a set of
- * continuously-updated summary statistics for a stream of numbers, without
- * requiring that each value be stored. The measures it provides are the
- * arithmetic mean, variance, standard deviation, and extrema (min and max);
- * together they describe the central tendency and statistical dispersion of a
- * set of values.
- *
- * One RunningStat instance can be merged into another; the resultant
- * RunningStat has the state it would have had if it had accumulated each
- * individual point. This allows data to be summarized in parallel and in
- * stages without loss of fidelity.
- *
- * Based on a C++ implementation by John D. Cook:
- *  <http://www.johndcook.com/standard_deviation.html>
- *  <http://www.johndcook.com/skewness_kurtosis.html>
- *
- * The in-line documentation for this class incorporates content from the
- * English Wikipedia articles "Variance", "Algorithms for calculating
- * variance", and "Standard deviation".
- *
- * @since 1.23
- */
-class RunningStat implements Countable {
-
-       /** @var int Number of samples. **/
-       public $n = 0;
-
-       /** @var float The first moment (or mean, or expected value). **/
-       public $m1 = 0.0;
-
-       /** @var float The second central moment (or variance). **/
-       public $m2 = 0.0;
-
-       /** @var float The least value in the the set. **/
-       public $min = INF;
-
-       /** @var float The most value in the set. **/
-       public $max = NEGATIVE_INF;
-
-       /**
-        * Count the number of accumulated values.
-        * @return int Number of values
-        */
-       public function count() {
-               return $this->n;
-       }
-
-       /**
-        * Add a number to the data set.
-        * @param int|float $x Value to add
-        */
-       public function push( $x ) {
-               $x = (float) $x;
-
-               $this->min = min( $this->min, $x );
-               $this->max = max( $this->max, $x );
-
-               $n1 = $this->n;
-               $this->n += 1;
-               $delta = $x - $this->m1;
-               $delta_n = $delta / $this->n;
-               $this->m1 += $delta_n;
-               $this->m2 += $delta * $delta_n * $n1;
-       }
-
-       /**
-        * Get the mean, or expected value.
-        *
-        * The arithmetic mean is the sum of all measurements divided by the number
-        * of observations in the data set.
-        *
-        * @return float Mean
-        */
-       public function getMean() {
-               return $this->m1;
-       }
-
-       /**
-        * Get the estimated variance.
-        *
-        * Variance measures how far a set of numbers is spread out. A small
-        * variance indicates that the data points tend to be very close to the
-        * mean (and hence to each other), while a high variance indicates that the
-        * data points are very spread out from the mean and from each other.
-        *
-        * @return float Estimated variance
-        */
-       public function getVariance() {
-               if ( $this->n === 0 ) {
-                       // The variance of the empty set is undefined.
-                       return NAN;
-               } elseif ( $this->n === 1 ) {
-                       return 0.0;
-               } else {
-                       return $this->m2 / ( $this->n - 1.0 );
-               }
-       }
-
-       /**
-        * Get the estimated stanard deviation.
-        *
-        * The standard deviation of a statistical population is the square root of
-        * its variance. It shows shows how much variation from the mean exists. In
-        * addition to expressing the variability of a population, the standard
-        * deviation is commonly used to measure confidence in statistical conclusions.
-        *
-        * @return float Estimated standard deviation
-        */
-       public function getStdDev() {
-               return sqrt( $this->getVariance() );
-       }
-
-       /**
-        * Merge another RunningStat instance into this instance.
-        *
-        * This instance then has the state it would have had if all the data had
-        * been accumulated by it alone.
-        *
-        * @param RunningStat RunningStat instance to merge into this one
-        */
-       public function merge( RunningStat $other ) {
-               // If the other RunningStat is empty, there's nothing to do.
-               if ( $other->n === 0 ) {
-                       return;
-               }
-
-               // If this RunningStat is empty, copy values from other RunningStat.
-               if ( $this->n === 0 ) {
-                       $this->n = $other->n;
-                       $this->m1 = $other->m1;
-                       $this->m2 = $other->m2;
-                       $this->min = $other->min;
-                       $this->max = $other->max;
-                       return;
-               }
-
-               $n = $this->n + $other->n;
-               $delta = $other->m1 - $this->m1;
-               $delta2 = $delta * $delta;
-
-               $this->m1 = ( ( $this->n * $this->m1 ) + ( $other->n * $other->m1 ) ) / $n;
-               $this->m2 = $this->m2 + $other->m2 + ( $delta2 * $this->n * $other->n / $n );
-               $this->min = min( $this->min, $other->min );
-               $this->max = max( $this->max, $other->max );
-               $this->n = $n;
-       }
-}
index 3b072f9..08b1ac1 100644 (file)
@@ -1130,11 +1130,11 @@ class ResourceLoader {
        public static function inDebugMode() {
                global $wgRequest, $wgResourceLoaderDebug;
                static $retval = null;
-               if ( !is_null( $retval ) ) {
-                       return $retval;
+               if ( is_null( $retval ) ) {
+                       $retval = $wgRequest->getFuzzyBool( 'debug',
+                               $wgRequest->getCookie( 'resourceLoaderDebug', '', $wgResourceLoaderDebug ) );
                }
-               return $retval = $wgRequest->getFuzzyBool( 'debug',
-                       $wgRequest->getCookie( 'resourceLoaderDebug', '', $wgResourceLoaderDebug ) );
+               return $retval;
        }
 
        /**
index 43330da..eaff86f 100644 (file)
@@ -454,8 +454,9 @@ class ResourceLoaderFileModule extends ResourceLoaderModule {
                // If a module is nothing but a list of dependencies, we need to avoid
                // giving max() an empty array
                if ( count( $files ) === 0 ) {
+                       $this->modifiedTime[$context->getHash()] = 1;
                        wfProfileOut( __METHOD__ );
-                       return $this->modifiedTime[$context->getHash()] = 1;
+                       return $this->modifiedTime[$context->getHash()];
                }
 
                wfProfileIn( __METHOD__ . '-filemtime' );
index 93c5d1b..d0c3068 100644 (file)
@@ -273,7 +273,8 @@ class ResourceLoaderStartUpModule extends ResourceLoaderModule {
                        $module = $loader->getModule( $name );
                        $time = max( $time, $module->getModifiedTime( $context ) );
                }
-               return $this->modifiedTime[$hash] = $time;
+               $this->modifiedTime[$hash] = $time;
+               return $this->modifiedTime[$hash];
        }
 
        /* Methods */
index aafe432..a9d1076 100644 (file)
@@ -41,12 +41,12 @@ class ResourceLoaderUserCSSPrefsModule extends ResourceLoaderModule {
         */
        public function getModifiedTime( ResourceLoaderContext $context ) {
                $hash = $context->getHash();
-               if ( isset( $this->modifiedTime[$hash] ) ) {
-                       return $this->modifiedTime[$hash];
+               if ( !isset( $this->modifiedTime[$hash] ) ) {
+                       global $wgUser;
+                       $this->modifiedTime[$hash] = wfTimestamp( TS_UNIX, $wgUser->getTouched() );
                }
 
-               global $wgUser;
-               return $this->modifiedTime[$hash] = wfTimestamp( TS_UNIX, $wgUser->getTouched() );
+               return $this->modifiedTime[$hash];
        }
 
        /**
index 1df8c56..3686bea 100644 (file)
@@ -43,12 +43,12 @@ class ResourceLoaderUserOptionsModule extends ResourceLoaderModule {
         */
        public function getModifiedTime( ResourceLoaderContext $context ) {
                $hash = $context->getHash();
-               if ( isset( $this->modifiedTime[$hash] ) ) {
-                       return $this->modifiedTime[$hash];
+               if ( !isset( $this->modifiedTime[$hash] ) ) {
+                       global $wgUser;
+                       $this->modifiedTime[$hash] = wfTimestamp( TS_UNIX, $wgUser->getTouched() );
                }
 
-               global $wgUser;
-               return $this->modifiedTime[$hash] = wfTimestamp( TS_UNIX, $wgUser->getTouched() );
+               return $this->modifiedTime[$hash];
        }
 
        /**
index 71c05d8..1556961 100644 (file)
@@ -485,11 +485,10 @@ class SearchEngine {
         */
        public static function getSearchTypes() {
                global $wgSearchType, $wgSearchTypeAlternatives;
-               static $alternatives = null;
-               if ( $alternatives === null ) {
-                       $alternatives = $wgSearchTypeAlternatives ?: array();
-                       array_unshift( $alternatives, $wgSearchType );
-               }
+
+               $alternatives = $wgSearchTypeAlternatives ?: array();
+               array_unshift( $alternatives, $wgSearchType );
+
                return $alternatives;
        }
 
index f50542d..1df52f2 100644 (file)
@@ -255,11 +255,11 @@ class SpecialPage {
        /**
         * Get a localised Title object for a specified special page name
         *
-        * @param $name String
-        * @param string|Bool $subpage subpage string, or false to not use a subpage
-        * @param string $fragment the link fragment (after the "#")
+        * @param string $name
+        * @param string|bool $subpage Subpage string, or false to not use a subpage
+        * @param string $fragment The link fragment (after the "#")
+        * @return Title
         * @throws MWException
-        * @return Title object
         */
        public static function getTitleFor( $name, $subpage = false, $fragment = '' ) {
                $name = SpecialPageFactory::getLocalNameFor( $name, $subpage );
@@ -269,9 +269,9 @@ class SpecialPage {
        /**
         * Get a localised Title object for a page name with a possibly unvalidated subpage
         *
-        * @param $name String
-        * @param string|Bool $subpage subpage string, or false to not use a subpage
-        * @return Title object or null if the page doesn't exist
+        * @param string $name
+        * @param string|bool $subpage Subpage string, or false to not use a subpage
+        * @return Title|null Title object or null if the page doesn't exist
         */
        public static function getSafeTitleFor( $name, $subpage = false ) {
                $name = SpecialPageFactory::getLocalNameFor( $name, $subpage );
@@ -307,10 +307,10 @@ class SpecialPage {
         * @param string $name Name of the special page, as seen in links and URLs
         * @param string $restriction User right required, e.g. "block" or "delete"
         * @param bool $listed Whether the page is listed in Special:Specialpages
-        * @param Callback|Bool $function Function called by execute(). By default
-        * it is constructed from $name
+        * @param callable|bool $function Function called by execute(). By default
+        *   it is constructed from $name
         * @param string $file File which is included by execute(). It is also
-        * constructed from $name by default
+        *   constructed from $name by default
         * @param bool $includable Whether the page can be included in normal pages
         */
        public function __construct(
@@ -326,10 +326,10 @@ class SpecialPage {
         * @param string $name Name of the special page, as seen in links and URLs
         * @param string $restriction User right required, e.g. "block" or "delete"
         * @param bool $listed Whether the page is listed in Special:Specialpages
-        * @param Callback|Bool $function Function called by execute(). By default
-        * it is constructed from $name
+        * @param callable|bool $function Function called by execute(). By default
+        *   it is constructed from $name
         * @param string $file File which is included by execute(). It is also
-        * constructed from $name by default
+        *   constructed from $name by default
         * @param bool $includable Whether the page can be included in normal pages
         */
        private function init( $name, $restriction, $listed, $function, $file, $includable ) {
@@ -379,7 +379,7 @@ class SpecialPage {
 
        /**
         * Get the name of this Special Page.
-        * @return String
+        * @return string
         */
        function getName() {
                return $this->mName;
@@ -387,7 +387,7 @@ class SpecialPage {
 
        /**
         * Get the permission that a user must have to execute this page
-        * @return String
+        * @return string
         */
        function getRestriction() {
                return $this->mRestriction;
@@ -397,7 +397,7 @@ class SpecialPage {
         * Get the file which will be included by SpecialPage::execute() if your extension is
         * still stuck in the past and hasn't overridden the execute() method.  No modern code
         * should want or need to know this.
-        * @return String
+        * @return string
         * @deprecated since 1.18
         */
        function getFile() {
@@ -409,25 +409,25 @@ class SpecialPage {
        /**
         * Whether this special page is listed in Special:SpecialPages
         * @since r3583 (v1.3)
-        * @return Bool
+        * @return bool
         */
        function isListed() {
                return $this->mListed;
        }
        /**
         * Set whether this page is listed in Special:Specialpages, at run-time
-        * @since r3583 (v1.3)
-        * @param $listed Bool
-        * @return Bool
+        * @since 1.3
+        * @param bool $listed
+        * @return bool
         */
        function setListed( $listed ) {
                return wfSetVar( $this->mListed, $listed );
        }
        /**
         * Get or set whether this special page is listed in Special:SpecialPages
-        * @since r11308 (v1.6)
-        * @param $x Bool
-        * @return Bool
+        * @since 1.6
+        * @param bool $x
+        * @return bool
         */
        function listed( $x = null ) {
                return wfSetVar( $this->mListed, $x );
@@ -435,7 +435,7 @@ class SpecialPage {
 
        /**
         * Whether it's allowed to transclude the special page via {{Special:Foo/params}}
-        * @return Bool
+        * @return bool
         */
        public function isIncludable() {
                return $this->mIncludable;
@@ -503,8 +503,8 @@ class SpecialPage {
 
        /**
         * Whether the special page is being evaluated via transclusion
-        * @param $x Bool
-        * @return Bool
+        * @param bool $x
+        * @return bool
         */
        function including( $x = null ) {
                return wfSetVar( $this->mIncluding, $x );
@@ -512,6 +512,7 @@ class SpecialPage {
 
        /**
         * Get the localised name of the special page
+        * @return string
         */
        function getLocalName() {
                if ( !isset( $this->mLocalName ) ) {
@@ -526,7 +527,7 @@ class SpecialPage {
         * (and still overridden) by QueryPage and subclasses, moved here so that
         * Special:SpecialPages can safely call it for all special pages.
         *
-        * @return Boolean
+        * @return bool
         */
        public function isExpensive() {
                return false;
@@ -538,7 +539,7 @@ class SpecialPage {
         * Used by QueryPage and subclasses, moved here so that
         * Special:SpecialPages can safely call it for all special pages.
         *
-        * @return Boolean
+        * @return bool
         * @since 1.21
         */
        public function isCached() {
@@ -549,7 +550,7 @@ class SpecialPage {
         * Can be overridden by subclasses with more complicated permissions
         * schemes.
         *
-        * @return Boolean: should the page be displayed with the restricted-access
+        * @return bool Should the page be displayed with the restricted-access
         *   pages?
         */
        public function isRestricted() {
@@ -562,8 +563,8 @@ class SpecialPage {
         * special page (as defined by $mRestriction).  Can be overridden by sub-
         * classes with more complicated permissions schemes.
         *
-        * @param $user User: the user to check
-        * @return Boolean: does the user have permission to view the page?
+        * @param User $user The user to check
+        * @return bool Does the user have permission to view the page?
         */
        public function userCanExecute( User $user ) {
                return $user->isAllowed( $this->mRestriction );
@@ -571,6 +572,7 @@ class SpecialPage {
 
        /**
         * Output an error message telling the user what access level they have to have
+        * @throws PermissionsError
         */
        function displayRestrictionError() {
                throw new PermissionsError( $this->mRestriction );
@@ -580,6 +582,8 @@ class SpecialPage {
         * Checks if userCanExecute, and if not throws a PermissionsError
         *
         * @since 1.19
+        * @return void
+        * @throws PermissionsError
         */
        public function checkPermissions() {
                if ( !$this->userCanExecute( $this->getUser() ) ) {
@@ -591,6 +595,7 @@ class SpecialPage {
         * If the wiki is currently in readonly mode, throws a ReadOnlyError
         *
         * @since 1.19
+        * @return void
         * @throws ReadOnlyError
         */
        public function checkReadOnly() {
@@ -657,7 +662,7 @@ class SpecialPage {
         *
         * @since 1.20
         *
-        * @param $subPage string|null
+        * @param string|null $subPage
         */
        final public function run( $subPage ) {
                /**
@@ -665,8 +670,8 @@ class SpecialPage {
                 *
                 * @since 1.20
                 *
-                * @param $special SpecialPage
-                * @param $subPage string|null
+                * @param SpecialPage $this
+                * @param string|null $subPage
                 */
                wfRunHooks( 'SpecialPageBeforeExecute', array( $this, $subPage ) );
 
@@ -679,8 +684,8 @@ class SpecialPage {
                 *
                 * @since 1.20
                 *
-                * @param $special SpecialPage
-                * @param $subPage string|null
+                * @param SpecialPage $this
+                * @param string|null $subPage
                 */
                wfRunHooks( 'SpecialPageAfterExecute', array( $this, $subPage ) );
        }
@@ -690,7 +695,7 @@ class SpecialPage {
         *
         * @since 1.20
         *
-        * @param $subPage string|null
+        * @param string|null $subPage
         */
        protected function beforeExecute( $subPage ) {
                // No-op
@@ -701,7 +706,7 @@ class SpecialPage {
         *
         * @since 1.20
         *
-        * @param $subPage string|null
+        * @param string|null $subPage
         */
        protected function afterExecute( $subPage ) {
                // No-op
@@ -713,7 +718,7 @@ class SpecialPage {
         *
         * This must be overridden by subclasses; it will be made abstract in a future version
         *
-        * @param $subPage string|null
+        * @param string|null $subPage
         */
        public function execute( $subPage ) {
                $this->setHeaders();
@@ -734,7 +739,7 @@ class SpecialPage {
         * May be overridden, i.e. by extensions to stick with the naming conventions
         * for message keys: 'extensionname-xxx'
         *
-        * @param string $summaryMessageKey message key of the summary
+        * @param string $summaryMessageKey Message key of the summary
         */
        function outputHeader( $summaryMessageKey = '' ) {
                global $wgContLang;
@@ -767,8 +772,8 @@ class SpecialPage {
        /**
         * Get a self-referential title object
         *
-        * @param $subpage String|Bool
-        * @return Title object
+        * @param string|bool $subpage
+        * @return Title
         * @deprecated in 1.23, use SpecialPage::getPageTitle
         */
        function getTitle( $subpage = false ) {
@@ -779,8 +784,8 @@ class SpecialPage {
        /**
         * Get a self-referential title object
         *
-        * @param $subpage String|Bool
-        * @return Title object
+        * @param string|bool $subpage
+        * @return Title
         * @since 1.23
         */
        function getPageTitle( $subpage = false ) {
@@ -790,7 +795,7 @@ class SpecialPage {
        /**
         * Sets the context this SpecialPage is executed in
         *
-        * @param $context IContextSource
+        * @param IContextSource $context
         * @since 1.18
         */
        public function setContext( $context ) {
@@ -909,7 +914,7 @@ class SpecialPage {
        /**
         * Adds RSS/atom links
         *
-        * @param $params array
+        * @param array $params
         */
        protected function addFeedLinks( $params ) {
                global $wgFeedClasses;
index 908e59c..6695c82 100644 (file)
@@ -330,9 +330,10 @@ class SpecialEmailUser extends UnlistedSpecialPage {
                        // This is a bit ugly, but will serve to differentiate
                        // wiki-borne mails from direct mails and protects against
                        // SPF and bounce problems with some mailers (see below).
-                       global $wgPasswordSender, $wgPasswordSenderName;
+                       global $wgPasswordSender;
 
-                       $mailFrom = new MailAddress( $wgPasswordSender, $wgPasswordSenderName );
+                       $mailFrom = new MailAddress( $wgPasswordSender,
+                               wfMessage( 'emailsender' )->inContentLanguage()->text() );
                        $replyTo = $from;
                } else {
                        // Put the sending user's e-mail address in the From: header.
index bbed9e6..6fb5e8c 100644 (file)
@@ -315,7 +315,7 @@ class SpecialExport extends SpecialPage {
                        foreach ( explode( "\n", $page ) as $pageName ) {
                                $pageName = trim( $pageName );
                                $title = Title::newFromText( $pageName );
-                               if ( $title && $title->getInterwiki() == '' && $title->getText() !== '' ) {
+                               if ( $title && !$title->isExternal() && $title->getText() !== '' ) {
                                        // Only record each page once!
                                        $pageSet[$title->getPrefixedText()] = true;
                                }
index b518140..ba3e73f 100644 (file)
@@ -387,6 +387,20 @@ class ImageListPager extends TablePager {
                UserCache::singleton()->doQuery( $userIds, array( 'userpage' ), __METHOD__ );
        }
 
+       /**
+        * @param string $field
+        * @param string $value
+        * @return Message|string|int The return type depends on the value of $field:
+        *   - thumb: string
+        *   - img_timestamp: string
+        *   - img_name: string
+        *   - img_user_text: string
+        *   - img_size: string
+        *   - img_description: string
+        *   - count: int
+        *   - top: Message
+        * @throws MWException
+        */
        function formatValue( $field, $value ) {
                switch ( $field ) {
                        case 'thumb':
@@ -446,6 +460,8 @@ class ImageListPager extends TablePager {
                        case 'top':
                                // Messages: listfiles-latestversion-yes, listfiles-latestversion-no
                                return $this->msg( 'listfiles-latestversion-' . $value );
+                       default:
+                               throw new MWException( "Unknown field '$field'" );
                }
        }
 
index db3be12..214fbd9 100644 (file)
@@ -52,6 +52,7 @@ class SpecialProtectedpages extends SpecialPage {
                $ns = $request->getIntOrNull( 'namespace' );
                $indefOnly = $request->getBool( 'indefonly' ) ? 1 : 0;
                $cascadeOnly = $request->getBool( 'cascadeonly' ) ? 1 : 0;
+               $noRedirect = $request->getBool( 'noredirect' ) ? 1 : 0;
 
                $pager = new ProtectedPagesPager(
                        $this,
@@ -62,7 +63,8 @@ class SpecialProtectedpages extends SpecialPage {
                        $sizetype,
                        $size,
                        $indefOnly,
-                       $cascadeOnly
+                       $cascadeOnly,
+                       $noRedirect
                );
 
                $this->getOutput()->addHTML( $this->showOptions(
@@ -72,7 +74,8 @@ class SpecialProtectedpages extends SpecialPage {
                        $sizetype,
                        $size,
                        $indefOnly,
-                       $cascadeOnly
+                       $cascadeOnly,
+                       $noRedirect
                ) );
 
                if ( $pager->getNumRows() ) {
@@ -186,17 +189,18 @@ class SpecialProtectedpages extends SpecialPage {
        }
 
        /**
-        * @param $namespace Integer
-        * @param string $type restriction type
-        * @param string $level restriction level
+        * @param int $namespace
+        * @param string $type Restriction type
+        * @param string $level Restriction level
         * @param string $sizetype "min" or "max"
-        * @param $size Integer
-        * @param $indefOnly Boolean: only indefinie protection
-        * @param $cascadeOnly Boolean: only cascading protection
+        * @param int $size
+        * @param bool $indefOnly Only indefinite protection
+        * @param bool $cascadeOnly Only cascading protection
+        * @param bool $noRedirect Don't show redirects
         * @return String: input form
         */
        protected function showOptions( $namespace, $type = 'edit', $level, $sizetype,
-               $size, $indefOnly, $cascadeOnly
+               $size, $indefOnly, $cascadeOnly, $noRedirect
        ) {
                global $wgScript;
 
@@ -212,6 +216,7 @@ class SpecialProtectedpages extends SpecialPage {
                        "<br /><span style='white-space: nowrap'>" .
                        $this->getExpiryCheck( $indefOnly ) . "&#160;\n" .
                        $this->getCascadeCheck( $cascadeOnly ) . "&#160;\n" .
+                       $this->getRedirectCheck( $noRedirect ) . "&#160;\n" .
                        "</span><br /><span style='white-space: nowrap'>" .
                        $this->getSizeLimit( $sizetype, $size ) . "&#160;\n" .
                        "</span>" .
@@ -269,6 +274,19 @@ class SpecialProtectedpages extends SpecialPage {
                ) . "\n";
        }
 
+       /**
+        * @param bool $noRedirect
+        * @return string Formatted HTML
+        */
+       protected function getRedirectCheck( $noRedirect ) {
+               return Xml::checkLabel(
+                       $this->msg( 'protectedpages-noredirect' )->text(),
+                       'noredirect',
+                       'noredirect',
+                       $noRedirect
+               ) . "\n";
+       }
+
        /**
         * @param string $sizetype "min" or "max"
         * @param mixed $size
@@ -372,10 +390,10 @@ class SpecialProtectedpages extends SpecialPage {
  */
 class ProtectedPagesPager extends AlphabeticPager {
        public $mForm, $mConds;
-       private $type, $level, $namespace, $sizetype, $size, $indefonly;
+       private $type, $level, $namespace, $sizetype, $size, $indefonly, $cascadeonly, $noredirect;
 
        function __construct( $form, $conds = array(), $type, $level, $namespace,
-               $sizetype = '', $size = 0, $indefonly = false, $cascadeonly = false
+               $sizetype = '', $size = 0, $indefonly = false, $cascadeonly = false, $noredirect = false
        ) {
                $this->mForm = $form;
                $this->mConds = $conds;
@@ -386,6 +404,7 @@ class ProtectedPagesPager extends AlphabeticPager {
                $this->size = intval( $size );
                $this->indefonly = (bool)$indefonly;
                $this->cascadeonly = (bool)$cascadeonly;
+               $this->noredirect = (bool)$noredirect;
                parent::__construct( $form->getContext() );
        }
 
@@ -424,6 +443,9 @@ class ProtectedPagesPager extends AlphabeticPager {
                if ( $this->cascadeonly ) {
                        $conds[] = 'pr_cascade = 1';
                }
+               if ( $this->noredirect ) {
+                       $conds[] = 'page_is_redirect = 0';
+               }
 
                if ( $this->level ) {
                        $conds[] = 'pr_level=' . $this->mDb->addQuotes( $this->level );
index 5dee226..9a9cd13 100644 (file)
@@ -65,7 +65,7 @@ class SpecialRecentChangesLinked extends SpecialRecentChanges {
                }
                $outputPage = $this->getOutput();
                $title = Title::newFromURL( $target );
-               if ( !$title || $title->getInterwiki() != '' ) {
+               if ( !$title || $title->isExternal() ) {
                        $outputPage->addHtml( '<div class="errorbox">' . $this->msg( 'allpagesbadtitle' )->parse() . '</div>' );
                        return false;
                }
index a6c3421..9f34f9c 100644 (file)
@@ -31,8 +31,6 @@
  * UploadBase and subclasses are the backend of MediaWiki's file uploads.
  * The frontends are formed by ApiUpload and SpecialUpload.
  *
- * See also includes/docs/upload.txt
- *
  * @author Brion Vibber
  * @author Bryan Tong Minh
  * @author Michael Dale
@@ -723,7 +721,8 @@ abstract class UploadBase {
                # exclamation mark, so restrict file name to 240 bytes.
                if ( strlen( $this->mFilteredName ) > 240 ) {
                        $this->mTitleError = self::FILENAME_TOO_LONG;
-                       return $this->mTitle = null;
+                       $this->mTitle = null;
+                       return $this->mTitle;
                }
 
                /**
@@ -736,7 +735,8 @@ abstract class UploadBase {
                $nt = Title::makeTitleSafe( NS_FILE, $this->mFilteredName );
                if ( is_null( $nt ) ) {
                        $this->mTitleError = self::ILLEGAL_FILENAME;
-                       return $this->mTitle = null;
+                       $this->mTitle = null;
+                       return $this->mTitle;
                }
                $this->mFilteredName = $nt->getDBkey();
 
@@ -777,19 +777,22 @@ abstract class UploadBase {
 
                if ( $this->mFinalExtension == '' ) {
                        $this->mTitleError = self::FILETYPE_MISSING;
-                       return $this->mTitle = null;
+                       $this->mTitle = null;
+                       return $this->mTitle;
                } elseif ( $blackListedExtensions ||
                                ( $wgCheckFileExtensions && $wgStrictFileExtensions &&
                                        !$this->checkFileExtensionList( $ext, $wgFileExtensions ) ) ) {
                        $this->mBlackListedExtensions = $blackListedExtensions;
                        $this->mTitleError = self::FILETYPE_BADTYPE;
-                       return $this->mTitle = null;
+                       $this->mTitle = null;
+                       return $this->mTitle;
                }
 
                // Windows may be broken with special characters, see bug XXX
                if ( wfIsWindows() && !preg_match( '/^[\x0-\x7f]*$/', $nt->getText() ) ) {
                        $this->mTitleError = self::WINDOWS_NONASCII_FILENAME;
-                       return $this->mTitle = null;
+                       $this->mTitle = null;
+                       return $this->mTitle;
                }
 
                # If there was more than one "extension", reassemble the base
@@ -802,10 +805,12 @@ abstract class UploadBase {
 
                if ( strlen( $partname ) < 1 ) {
                        $this->mTitleError = self::MIN_LENGTH_PARTNAME;
-                       return $this->mTitle = null;
+                       $this->mTitle = null;
+                       return $this->mTitle;
                }
 
-               return $this->mTitle = $nt;
+               $this->mTitle = $nt;
+               return $this->mTitle;
        }
 
        /**
index 10ff957..47cef8b 100644 (file)
@@ -40,6 +40,7 @@ class UIDGenerator {
        protected $fileHandles = array(); // cache file handles
 
        const QUICK_RAND = 1; // get randomness from fast and insecure sources
+       const QUICK_VOLATILE = 2; // use an APC like in-memory counter if available
 
        protected function __construct() {
                $idFile = wfTempDir() . '/mw-' . __CLASS__ . '-UID-nodeid';
@@ -214,6 +215,95 @@ class UIDGenerator {
                return str_replace( '-', '', self::newUUIDv4( $flags ) );
        }
 
+       /**
+        * Return an ID that is sequential *only* for this node and bucket
+        *
+        * These IDs are suitable for per-host sequence numbers, e.g. for some packet protocols.
+        * If UIDGenerator::QUICK_VOLATILE is used the counter might reset on server restart.
+        *
+        * @param string $bucket Arbitrary bucket name (should be ASCII)
+        * @param integer $bits Bit size (<=48) of resulting numbers before wrap-around
+        * @param integer $flags (supports UIDGenerator::QUICK_VOLATILE)
+        * @return float Integer value as float
+        * @since 1.23
+        */
+       public static function newSequentialPerNodeID( $bucket, $bits = 48, $flags = 0 ) {
+               return current( self::newSequentialPerNodeIDs( $bucket, $bits, 1, $flags ) );
+       }
+
+       /**
+        * Return IDs that are sequential *only* for this node and bucket
+        *
+        * @see UIDGenerator::newSequentialPerNodeID()
+        * @param string $bucket Arbitrary bucket name (should be ASCII)
+        * @param integer $bits Bit size (16 to 48) of resulting numbers before wrap-around
+        * @param integer $count Number of IDs to return (1 to 10000)
+        * @param integer $flags (supports UIDGenerator::QUICK_VOLATILE)
+        * @return array Ordered list of float integer values
+        * @since 1.23
+        */
+       public static function newSequentialPerNodeIDs( $bucket, $bits, $count, $flags = 0 ) {
+               if ( $count <= 0 ) {
+                       return array(); // nothing to do
+               } elseif ( $count > 10000 ) {
+                       throw new MWException( "Number of requested IDs ($count) is too high." );
+               } elseif ( $bits < 16 || $bits > 48 ) {
+                       throw new MWException( "Requested bit size ($bits) is out of range." );
+               }
+
+               $counter = null; // post-increment persistent counter value
+
+               // Use APC/eAccelerator/xcache if requested, available, and not in CLI mode;
+               // Counter values would not survive accross script instances in CLI mode.
+               $cache = null;
+               if ( ( $flags & self::QUICK_VOLATILE ) && PHP_SAPI !== 'cli' ) {
+                       try {
+                               $cache = ObjectCache::newAccelerator( array() );
+                       } catch ( MWException $e ) {} // not supported
+               }
+               if ( $cache ) {
+                       $counter = $cache->incr( $bucket, $count );
+                       if ( $counter === false ) {
+                               if ( !$cache->add( $bucket, $count ) ) {
+                                       throw new MWException( 'Unable to set value to ' . get_class( $cache ) );
+                               }
+                               $counter = $count;
+                       }
+               }
+
+               // Note: use of fmod() avoids "division by zero" on 32 bit machines
+               if ( $counter === null ) {
+                       $path = wfTempDir() . '/mw-' . __CLASS__ . '-' . rawurlencode( $bucket ) . '-48';
+                       $handle = fopen( $path, 'cb+' );
+                       // Acquire the UID lock file
+                       if ( $handle === false ) {
+                               throw new MWException( "Could not open '{$path}'." );
+                       } elseif ( !flock( $handle, LOCK_EX ) ) {
+                               fclose( $handle );
+                               throw new MWException( "Could not acquire '{$path}'." );
+                       }
+                       // Fetch the counter value and increment it...
+                       rewind( $handle );
+                       $counter = floor( trim( fgets( $handle ) ) ) + $count; // fetch as float
+                       // Write back the new counter value
+                       ftruncate( $handle, 0 );
+                       rewind( $handle );
+                       fwrite( $handle, fmod( $counter, pow( 2, 48 ) ) ); // warp-around as needed
+                       fflush( $handle );
+                       // Release the UID lock file
+                       flock( $handle, LOCK_UN );
+                       fclose( $handle );
+               }
+               $ids = array();
+               $divisor = pow( 2, $bits );
+               $currentId = floor( $counter - $count ); // pre-increment counter value
+               for ( $i = 0; $i < $count; ++$i ) {
+                       $ids[] = fmod( ++$currentId, $divisor );
+               }
+
+               return $ids;
+       }
+
        /**
         * Get a (time,counter,clock sequence) where (time,counter) is higher
         * than any previous (time,counter) value for the given clock sequence.
@@ -237,6 +327,7 @@ class UIDGenerator {
                if ( $handle === false ) {
                        throw new MWException( "Could not open '{$this->$lockFile}'." );
                } elseif ( !flock( $handle, LOCK_EX ) ) {
+                       fclose( $handle );
                        throw new MWException( "Could not acquire '{$this->$lockFile}'." );
                }
                // Get the current timestamp, clock sequence number, last time, and counter
index 23506e9..320688a 100644 (file)
@@ -62,7 +62,6 @@ class FakeConverter {
        function getParsedTitle() { return ''; }
        function markNoConversion( $text, $noParse = false ) { return $text; }
        function convertCategoryKey( $key ) { return $key; }
-       function convertLinkToAllVariants( $text ) { return $this->autoConvertToAllVariants( $text ); }
        /** @deprecated since 1.22 is no longer used */
        function armourMath( $text ) { return $text; }
        function validateVariant( $variant = null ) { return $variant === $this->mLang->getCode() ? $variant : null; }
@@ -3905,21 +3904,6 @@ class Language {
                $this->mConverter->findVariantLink( $link, $nt, $ignoreOtherCond );
        }
 
-       /**
-        * If a language supports multiple variants, converts text
-        * into an array of all possible variants of the text:
-        *  'variant' => text in that variant
-        *
-        * @deprecated since 1.17 Use autoConvertToAllVariants()
-        *
-        * @param $text string
-        *
-        * @return string
-        */
-       public function convertLinkToAllVariants( $text ) {
-               return $this->mConverter->convertLinkToAllVariants( $text );
-       }
-
        /**
         * returns language specific options used by User::getPageRenderHash()
         * for example, the preferred language variant
index cdaab2c..bb5b49f 100644 (file)
@@ -236,7 +236,8 @@ class LanguageConverter {
                        $ret = $wgRequest->getVal( 'uselang' );
                }
 
-               return $this->mURLVariant = $this->validateVariant( $ret );
+               $this->mURLVariant = $this->validateVariant( $ret );
+               return $this->mURLVariant;
        }
 
        /**
@@ -269,7 +270,8 @@ class LanguageConverter {
                        $ret = $wgUser->getOption( 'language' );
                }
 
-               return $this->mUserVariant = $this->validateVariant( $ret );
+               $this->mUserVariant = $this->validateVariant( $ret );
+               return $this->mUserVariant;
        }
 
        /**
@@ -489,21 +491,6 @@ class LanguageConverter {
                return $ret;
        }
 
-       /**
-        * Convert link text to all valid variants.
-        * In the first, this function only convert text outside the
-        * "-{" "}-" markups. Since the "{" and "}" are not allowed in
-        * titles, the text will get all converted always.
-        * So I removed this feature and deprecated the function.
-        *
-        * @param $text String: the text to be converted
-        * @return Array: variant => converted text
-        * @deprecated since 1.17 Use autoConvertToAllVariants() instead
-        */
-       public function convertLinkToAllVariants( $text ) {
-               return $this->autoConvertToAllVariants( $text );
-       }
-
        /**
         * Apply manual conversion rules.
         *
index d3e78fe..05b9550 100644 (file)
  * @see http://be-x-old.wikipedia.org/wiki/Project_talk:LanguageBe_tarask.php
  */
 class LanguageBe_tarask extends Language {
-       /**
-        * Plural form transformations
-        *
-        * $wordform1 - singular form (for 1, 21, 31, 41...)
-        * $wordform2 - plural form (for 2, 3, 4, 22, 23, 24, 32, 33, 34...)
-        * $wordform3 - plural form (for 0, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 25, 26...)
-        */
-
-       /**
-        * @param $count int
-        * @param $forms array
-        *
-        * @return string
-        */
-       function convertPlural( $count, $forms ) {
-               $forms = $this->handleExplicitPluralForms( $count, $forms );
-               if ( is_string( $forms ) ) {
-                       return $forms;
-               }
-               if ( !count( $forms ) ) {
-                       return '';
-               }
-
-               // If the actual number is not mentioned in the expression, then just two forms are enough:
-               // singular for $count == 1
-               // plural   for $count != 1
-               // For example, "This user belongs to {{PLURAL:$1|one group|several groups}}."
-               if ( count( $forms ) === 2 ) {
-                       return $count == 1 ? $forms[0] : $forms[1];
-               }
-
-               // @todo FIXME: CLDR defines 4 plural forms instead of 3
-               //        http://unicode.org/repos/cldr-tmp/trunk/diff/supplemental/language_plural_rules.html
-               $forms = $this->preConvertPlural( $forms, 3 );
-
-               if ( $count > 10 && floor( ( $count % 100 ) / 10 ) == 1 ) {
-                       return $forms[2];
-               } else {
-                       switch ( $count % 10 ) {
-                               case 1: return $forms[0];
-                               case 2:
-                               case 3:
-                               case 4: return $forms[1];
-                               default: return $forms[2];
-                       }
-               }
-       }
-
        /**
         * The Belarusian language uses apostrophe sign,
         * but the characters used for this could be both U+0027 and U+2019.
diff --git a/languages/classes/LanguageHr.php b/languages/classes/LanguageHr.php
deleted file mode 100644 (file)
index 0c65ec7..0000000
+++ /dev/null
@@ -1,60 +0,0 @@
-<?php
-/**
- * Croatian (hrvatski) specific code.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- * http://www.gnu.org/copyleft/gpl.html
- *
- * @file
- * @ingroup Language
- */
-
-/**
- * Croatian (hrvatski)
- *
- * @ingroup Language
- */
-class LanguageHr extends Language {
-
-       /**
-        * @param $count int
-        * @param $forms array
-        * @return string
-        */
-       function convertPlural( $count, $forms ) {
-               $forms = $this->handleExplicitPluralForms( $count, $forms );
-               if ( is_string( $forms ) ) {
-                       return $forms;
-               }
-               if ( !count( $forms ) ) {
-                       return '';
-               }
-               // @todo FIXME: CLDR defines 4 plural forms instead of 3. Plural for for decimals is missing.
-               //        http://unicode.org/repos/cldr-tmp/trunk/diff/supplemental/language_plural_rules.html
-               $forms = $this->preConvertPlural( $forms, 3 );
-
-               if ( $count > 10 && floor( ( $count % 100 ) / 10 ) == 1 ) {
-                       return $forms[2];
-               } else {
-                       switch ( $count % 10 ) {
-                               case 1: return $forms[0];
-                               case 2:
-                               case 3:
-                               case 4: return $forms[1];
-                               default: return $forms[2];
-                       }
-               }
-       }
-}
index 243a876..d3ac1d2 100644 (file)
@@ -44,8 +44,9 @@ class LanguageRu extends Language {
                        return $wgGrammarForms['ru'][$case][$word];
                }
 
-               # These rules are not perfect, but they are currently only used for Wikimedia site names so it doesn't
-               # matter if they are wrong sometimes. Just add a special case for your site name if necessary.
+               # These rules are not perfect, but they are currently only used for Wikimedia
+               # site names so it doesn't matter if they are wrong sometimes.
+               # Just add a special case for your site name if necessary.
 
                # substr doesn't support Unicode and mb_substr has issues,
                # so break it to characters using preg_match_all and then use array_slice and join
@@ -102,62 +103,6 @@ class LanguageRu extends Language {
                return $word;
        }
 
-       /**
-        * Plural form transformations
-        *
-        * $forms[0] - singular form (for 1, 21, 31, 41...)
-        * $forms[1] - paucal form (for 2, 3, 4, 22, 23, 24, 32, 33, 34...)
-        * $forms[2] - plural form (for 0, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 25, 26...)
-        *
-        * Examples:
-        *   message with number
-        *     "Сделано $1 {{PLURAL:$1|изменение|изменения|изменений}}"
-        *     ("$1 change[s] were made)
-        *   message without number
-        *     "Действие не может быть выполнено по {{PLURAL:$1|следующей причине|следующим причинам}}:"
-        *     ("The action cannot be performed for the following reason[s]")
-        * @param $count int
-        * @param $forms array
-        *
-        * @return string
-        */
-       function convertPlural( $count, $forms ) {
-               $forms = $this->handleExplicitPluralForms( $count, $forms );
-               if ( is_string( $forms ) ) {
-                       return $forms;
-               }
-               if ( !count( $forms ) ) {
-                       return '';
-               }
-
-               // If the actual number is not mentioned in the expression, then just two forms are enough:
-               // singular for $count === 1
-               // plural   for $count !== 1
-               // For example, "This user belongs to {{PLURAL:$1|one group|several groups}}."
-               if ( count( $forms ) === 2 ) {
-                       return $count === 1 ? $forms[0] : $forms[1];
-               }
-
-               // @todo FIXME: CLDR defines 4 plural forms. Form with decimals missing.
-               // See http://unicode.org/repos/cldr-tmp/trunk/diff/supplemental/language_plural_rules.html#ru
-               $forms = $this->preConvertPlural( $forms, 3 );
-
-               if ( $count > 10 && (int)floor( ( $count % 100 ) / 10 ) === 1 ) {
-                       return $forms[2];
-               }
-
-               switch ( $count % 10 ) {
-                       case 1:
-                               return $forms[0];
-                       case 2:
-                       case 3:
-                       case 4:
-                               return $forms[1];
-                       default:
-                               return $forms[2];
-               }
-       }
-
        /**
         * Four-digit number should be without group commas (spaces)
         * See manual of style at http://ru.wikipedia.org/wiki/Википедия:Оформление_статей
index 283ef22..a728c9d 100644 (file)
@@ -22,8 +22,6 @@
  */
 
 require_once __DIR__ . '/../LanguageConverter.php';
-require_once __DIR__ . '/LanguageSr_ec.php';
-require_once __DIR__ . '/LanguageSr_el.php';
 
 /**
  * There are two levels of conversion for Serbian: the script level
@@ -166,14 +164,16 @@ class SrConverter extends LanguageConverter {
                // regexp for roman numbers
                $roman = 'M{0,4}(CM|CD|D?C{0,3})(XC|XL|L?X{0,3})(IX|IV|V?I{0,3})';
 
-               $reg = '/^' . $roman . '$|^' . $roman . $breaks . '|' . $breaks . $roman . '$|' . $breaks . $roman . $breaks . '/';
+               $reg = '/^' . $roman . '$|^' . $roman . $breaks . '|' . $breaks
+                       . $roman . '$|' . $breaks . $roman . $breaks . '/';
 
                $matches = preg_split( $reg, $text, -1, PREG_SPLIT_OFFSET_CAPTURE );
 
                $m = array_shift( $matches );
                $this->loadTables();
                if ( !isset( $this->mTables[$toVariant] ) ) {
-                       throw new MWException( "Broken variant table: " . implode( ',', array_keys( $this->mTables ) ) );
+                       throw new MWException( "Broken variant table: "
+                               . implode( ',', array_keys( $this->mTables ) ) );
                }
                $ret = $this->mTables[$toVariant]->replace( $m[0] );
                $mstart = $m[1] + strlen( $m[0] );
@@ -218,7 +218,7 @@ class SrConverter extends LanguageConverter {
  *
  * @ingroup Language
  */
-class LanguageSr extends LanguageSr_ec {
+class LanguageSr extends Language {
        function __construct() {
                global $wgHooks;
 
@@ -238,44 +238,4 @@ class LanguageSr extends LanguageSr_ec {
                $this->mConverter = new SrConverter( $this, 'sr', $variants, $variantfallbacks, $flags );
                $wgHooks['PageContentSaveComplete'][] = $this->mConverter;
        }
-
-       /**
-        * @param $count int
-        * @param $forms array
-        *
-        * @return string
-        */
-       function convertPlural( $count, $forms ) {
-               $forms = $this->handleExplicitPluralForms( $count, $forms );
-               if ( is_string( $forms ) ) {
-                       return $forms;
-               }
-               if ( !count( $forms ) ) {
-                       return '';
-               }
-
-               // If the actual number is not mentioned in the expression, then just two forms are enough:
-               // singular for $count == 1
-               // plural   for $count != 1
-               // For example, "This user belongs to {{PLURAL:$1|one group|several groups}}."
-               if ( count( $forms ) === 2 ) {
-                       return $count == 1 ? $forms[0] : $forms[1];
-               }
-
-               // @todo FIXME: CLDR defines 4 plural forms. Form with decimals missing.
-               // See http://unicode.org/repos/cldr-tmp/trunk/diff/supplemental/language_plural_rules.html#ru
-               $forms = $this->preConvertPlural( $forms, 3 );
-
-               if ( $count > 10 && floor( ( $count % 100 ) / 10 ) == 1 ) {
-                       return $forms[2];
-               } else {
-                       switch ( $count % 10 ) {
-                               case 1: return $forms[0];
-                               case 2:
-                               case 3:
-                               case 4: return $forms[1];
-                               default: return $forms[2];
-                       }
-               }
-       }
 }
diff --git a/languages/classes/LanguageSr_ec.php b/languages/classes/LanguageSr_ec.php
deleted file mode 100644 (file)
index 4787856..0000000
+++ /dev/null
@@ -1,58 +0,0 @@
-<?php
-/**
- * Serbian (cyrillic script) specific code.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- * http://www.gnu.org/copyleft/gpl.html
- *
- * @file
- * @ingroup Language
- */
-
-/**
- * Serbian (cyrillic script)
- *
- * @ingroup Language
- */
-class LanguageSr_ec extends Language {
-
-       /**
-        * @param $count int
-        * @param $forms array
-        * @return string
-        */
-       function convertPlural( $count, $forms ) {
-               $forms = $this->handleExplicitPluralForms( $count, $forms );
-               if ( is_string( $forms ) ) {
-                       return $forms;
-               }
-               if ( !count( $forms ) ) {
-                       return '';
-               }
-               $forms = $this->preConvertPlural( $forms, 3 );
-
-               if ( $count > 10 && floor( ( $count % 100 ) / 10 ) == 1 ) {
-                       return $forms[2];
-               } else {
-                       switch ( $count % 10 ) {
-                               case 1: return $forms[0];
-                               case 2:
-                               case 3:
-                               case 4: return $forms[1];
-                               default: return $forms[2];
-                       }
-               }
-       }
-}
diff --git a/languages/classes/LanguageSr_el.php b/languages/classes/LanguageSr_el.php
deleted file mode 100644 (file)
index 3f086df..0000000
+++ /dev/null
@@ -1,58 +0,0 @@
-<?php
-/**
- * Serbian (latin script) specific code.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- * http://www.gnu.org/copyleft/gpl.html
- *
- * @file
- * @ingroup Language
- */
-
-/**
- * Serbian (latin script)
- *
- * @ingroup Language
- */
-class LanguageSr_el extends Language {
-
-       /**
-        * @param $count int
-        * @param $forms array
-        * @return string
-        */
-       function convertPlural( $count, $forms ) {
-               $forms = $this->handleExplicitPluralForms( $count, $forms );
-               if ( is_string( $forms ) ) {
-                       return $forms;
-               }
-               if ( !count( $forms ) ) {
-                       return '';
-               }
-               $forms = $this->preConvertPlural( $forms, 3 );
-
-               if ( $count > 10 && floor( ( $count % 100 ) / 10 ) == 1 ) {
-                       return $forms[2];
-               } else {
-                       switch ( $count % 10 ) {
-                               case 1: return $forms[0];
-                               case 2:
-                               case 3:
-                               case 4: return $forms[1];
-                               default: return $forms[2];
-                       }
-               }
-       }
-}
index aabe390..08041a9 100644 (file)
@@ -86,45 +86,6 @@ class LanguageUk extends Language {
                return $word;
        }
 
-       /**
-        * @param $count int
-        * @param $forms array
-        * @return string
-        */
-       function convertPlural( $count, $forms ) {
-               $forms = $this->handleExplicitPluralForms( $count, $forms );
-               if ( is_string( $forms ) ) {
-                       return $forms;
-               }
-               if ( !count( $forms ) ) {
-                       return '';
-               }
-
-               // If the actual number is not mentioned in the expression, then just two forms are enough:
-               // singular for $count == 1
-               // plural   for $count != 1
-               // For example, "This user belongs to {{PLURAL:$1|one group|several groups}}."
-               if ( count( $forms ) === 2 ) {
-                       return $count == 1 ? $forms[0] : $forms[1];
-               }
-
-               // @todo FIXME: CLDR defines 4 plural forms. Form for decimals is missing/
-               // See http://unicode.org/repos/cldr-tmp/trunk/diff/supplemental/language_plural_rules.html#uk
-               $forms = $this->preConvertPlural( $forms, 3 );
-
-               if ( $count > 10 && floor( ( $count % 100 ) / 10 ) == 1 ) {
-                       return $forms[2];
-               } else {
-                       switch ( $count % 10 ) {
-                               case 1: return $forms[0];
-                               case 2:
-                               case 3:
-                               case 4: return $forms[1];
-                               default: return $forms[2];
-                       }
-               }
-       }
-
        /**
         * Ukrainian numeric format is "12 345,67" but "1234,56"
         *
index 3314793..aafc393 100644 (file)
@@ -2,48 +2,44 @@
 <!DOCTYPE supplementalData SYSTEM "../../common/dtd/ldmlSupplemental.dtd">
 <supplementalData>
        <plurals>
-               <!--
-               The "one" and "two" rules are copied directly from CLDR.
-               The "many" rule overrides CLDR, because CLDR seems to have a mistake:
-               it's sometimes needed for multiples of 10, but not for 10 itself.
-               When the CLDR is fixed, this should be removed.
-               -->
-               <pluralRules locales="he">
-                       <pluralRule count="one">n is 1</pluralRule>
-                       <pluralRule count="two">n is 2</pluralRule>
-                       <pluralRule count="many">n is not 0 AND n is not 10 AND n mod 10 is 0</pluralRule>
-               </pluralRules>
+               <!-- Lower Sorbian (Dolnoserbski) and  Upper Sorbian (Hornjoserbsce). Not present in CLDR -->
                <pluralRules locales="dsb hsb">
-                       <pluralRule count="one">n mod 100 is 1</pluralRule>
-                       <pluralRule count="two">n mod 100 is 2</pluralRule>
-                       <pluralRule count="few">n mod 100 in 3..4</pluralRule>
+                       <pluralRule count="one">n % 100 = 1 @integer 1, 101, 201, 301, …</pluralRule>
+                       <pluralRule count="two">n % 100 = 2 @integer 2, 102, 202, 302, …</pluralRule>
+                       <pluralRule count="few">n % 100 = 3..4 @integer 3~4, 103~104, …</pluralRule>
+                       <pluralRule count="other"> @integer 5, 6, 7, 8, 9, 10, 105, 206, 307, …</pluralRule>
                </pluralRules>
-               <!-- Copied from "be" -->
+
+               <!-- Belarusian in Taraškievica orthography (Беларуская тарашкевіца). Copied from "be" -->
                <pluralRules locales="be-tarask">
-                       <pluralRule count="one">n mod 10 is 1 and n mod 100 is not 11</pluralRule>
-                       <pluralRule count="few">n mod 10 in 2..4 and n mod 100 not in 12..14</pluralRule>
-                       <pluralRule count="many">n mod 10 is 0 or n mod 10 in 5..9 or n mod 100 in 11..14</pluralRule>
-                       <!-- others are fractions -->
+                       <pluralRule count="one">n % 10 = 1 and n % 100 != 11 @integer 1, 21, 31, 41, 51, 61, 71, 81, 101, 1001, … @decimal 1.0, 21.0, 31.0, 41.0, 51.0, 61.0, 71.0, 81.0, 101.0, 1001.0, …</pluralRule>
+                       <pluralRule count="few">n % 10 = 2..4 and n % 100 != 12..14 @integer 2~4, 22~24, 32~34, 42~44, 52~54, 62, 102, 1002, … @decimal 2.0, 3.0, 4.0, 22.0, 23.0, 24.0, 32.0, 33.0, 102.0, 1002.0, …</pluralRule>
+                       <pluralRule count="many">n % 10 = 0 or n % 10 = 5..9 or n % 100 = 11..14 @integer 0, 5~19, 100, 1000, 10000, 100000, 1000000, … @decimal 0.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 11.0, 100.0, 1000.0, 10000.0, 100000.0, 1000000.0, …</pluralRule>
+                       <pluralRule count="other">   @decimal 0.1~0.9, 1.1~1.7, 10.1, 100.1, 1000.1, …</pluralRule>
                </pluralRules>
+               <!--  Old Church Slavonic (Ѩзыкъ словѣньскъ). Not present in CLDR -->
                <pluralRules locales="cu">
-                       <pluralRule count="one">n mod 10 is 1</pluralRule>
-                       <pluralRule count="two">n mod 10 is 2</pluralRule>
-                       <pluralRule count="few">n mod 10 in 3..4</pluralRule>
+                       <pluralRule count="one">n % 10 = 1 @integer 1, 11, 21, 31, …</pluralRule>
+                       <pluralRule count="two">n % 10 = 2 @integer 2, 12, 22, 32, …</pluralRule>
+                       <pluralRule count="few">n % 10 = 3..4 @integer 3~4, 13~14, 23~24, …</pluralRule>
+                       <pluralRule count="other"> @integer 5, 6, 7, 8, 9, 10, 15, 105, 206, 307, …</pluralRule>
                </pluralRules>
                <!-- Copied from "bh" -->
                <pluralRules locales="bho">
-                       <pluralRule count="one">n in 0..1</pluralRule>
+                       <pluralRule count="one">n = 0..1 @integer 0, 1 @decimal 0.0, 1.0, 0.00, 1.00, 0.000, 1.000, 0.0000, 1.0000</pluralRule>
+                       <pluralRule count="other"> @integer 2~17, 100, 1000, 10000, 100000, 1000000, … @decimal 0.1~0.9, 1.1~1.7, 10.0, 100.0, 1000.0, 10000.0, 100000.0, 1000000.0, …</pluralRule>
                </pluralRules>
+               <!-- Samogitian. Not present in CLDR -->
                <pluralRules locales="sgs">
-                       <pluralRule count="one">n mod 10 is 1 and n mod 100 is not 11</pluralRule>
-                       <pluralRule count="two">n mod 10 is 2 and n mod 100 is not 12</pluralRule>
-                       <pluralRule count="few">n is 0 or n mod 100 is 0 or n mod 100 in 10..19</pluralRule>
+                       <pluralRule count="one">n % 10 = 1 and n % 100 != 11 @integer 1, 21, 31, 41, 51, 61, 71, 81, 91, 101, 121, …</pluralRule>
+                       <pluralRule count="two">n % 10 = 2 and n % 100 != 12 @integer 2, 22, 32, 42, 52, 62, 72, 82, 92, 102, 122, …</pluralRule>
+                       <pluralRule count="few">n = 0 or n % 100 = 0 or n % 100 = 10..19 @integer 0, 11, 12, 13, 14, 15, 16, 17, 18, 19, 100, 111,112, …</pluralRule>
+                       <pluralRule count="other"> @integer 3, 4, 5, 6, 7, 8, 9, 20, 103, 104, …</pluralRule>
                </pluralRules>
-               <!-- Override as per https://bugzilla.wikimedia.org/show_bug.cgi?id=47099, porting from CLDR 24 -->
-               <pluralRules locales="gv">
-                       <pluralRule count="one">n mod 10 is 1</pluralRule>
-                       <pluralRule count="two">n mod 10 is 2</pluralRule>
-                       <pluralRule count="few">n mod 100 in 0,20,40,60</pluralRule>
+               <pluralRules locales="sr-el sr-ec">
+                       <pluralRule count="one">v = 0 and i % 10 = 1 and i % 100 != 11 or f % 10 = 1 and f % 100 != 11 @integer 1, 21, 31, 41, 51, 61, 71, 81, 101, 1001, … @decimal 0.1, 1.1, 2.1, 3.1, 4.1, 5.1, 6.1, 7.1, 10.1, 100.1, 1000.1, …</pluralRule>
+                       <pluralRule count="few">v = 0 and i % 10 = 2..4 and i % 100 != 12..14 or f % 10 = 2..4 and f % 100 != 12..14 @integer 2~4, 22~24, 32~34, 42~44, 52~54, 62, 102, 1002, … @decimal 0.2~0.4, 1.2~1.4, 2.2~2.4, 3.2~3.4, 4.2~4.4, 5.2, 10.2, 100.2, 1000.2, …</pluralRule>
+                       <pluralRule count="other"> @integer 0, 5~19, 100, 1000, 10000, 100000, 1000000, … @decimal 0.0, 0.5~1.0, 1.5~2.0, 2.5~2.7, 10.0, 100.0, 1000.0, 10000.0, 100000.0, 1000000.0, …</pluralRule>
                </pluralRules>
        </plurals>
 </supplementalData>
old mode 100644 (file)
new mode 100755 (executable)
index d5a1cfe..fd4eaf6
 <?xml version="1.0" encoding="UTF-8" ?>
 <!DOCTYPE supplementalData SYSTEM "../../common/dtd/ldmlSupplemental.dtd">
+<!--
+Copyright © 1991-2013 Unicode, Inc.
+CLDR data files are interpreted according to the LDML specification (http://unicode.org/reports/tr35/)
+For terms of use, see http://www.unicode.org/copyright.html
+-->
 <supplementalData>
-    <version number="$Revision: 8007 $"/>
-    <generation date="$Date: 2013-01-03 07:17:41 +0530 (Thu, 03 Jan 2013) $"/>
-    <plurals>
+    <version number="$Revision: 9369 $"/>
+    <generation date="$Date: 2013-09-14 01:26:08 +0530 (ശ, 14 സെപ് 2013) $"/>
+    <plurals type="cardinal">
+        <!-- For a canonicalized list, use GeneratedPluralSamples -->
         <!-- if locale is known to have no plurals, there are no rules -->
-        <pluralRules locales="az bm bo dz fa id ig ii hu ja jv ka kde kea km kn ko lo ms my sah ses sg th to tr vi wo yo zh"/>
         <pluralRules locales="ar">
-            <pluralRule count="zero">n is 0</pluralRule>
-            <pluralRule count="one">n is 1</pluralRule>
-            <pluralRule count="two">n is 2</pluralRule>
-            <pluralRule count="few">n mod 100 in 3..10</pluralRule>
-            <pluralRule count="many">n mod 100 in 11..99</pluralRule>
-        </pluralRules>
-        <pluralRules locales="he">
-            <pluralRule count="one">n is 1</pluralRule>
-            <pluralRule count="two">n is 2</pluralRule>
-            <pluralRule count="many">n is not 0 AND n mod 10 is 0</pluralRule>
-        </pluralRules>
-        <pluralRules locales="asa ast af bem bez bg bn brx ca cgg chr ckb da de dv ee el en eo es et eu fi fo fur fy gl gsw gu ha haw hy is it jgo jmc kaj kcg kk kkj kl ks ksb ku ky lb lg mas mgo ml mn mr nah nb nd ne nl nn nnh no nr ny nyn om or os pa pap ps pt rof rm rwk saq seh sn so sq ss ssy st sv sw syr ta te teo tig tk tn ts ur vo wae ve vun xh xog zu">
-            <pluralRule count="one">n is 1</pluralRule>
-        </pluralRules>
-        <pluralRules locales="ak am bh fil tl guw hi ln mg nso ti wa">
-            <pluralRule count="one">n in 0..1</pluralRule>
-        </pluralRules>
-        <pluralRules locales="ff fr kab">
-            <pluralRule count="one">n within 0..2 and n is not 2</pluralRule>
+            <pluralRule count="zero">n = 0 @integer 0 @decimal 0.0, 0.00, 0.000, 0.0000</pluralRule>
+            <pluralRule count="one">n = 1 @integer 1 @decimal 1.0, 1.00, 1.000, 1.0000</pluralRule>
+            <pluralRule count="two">n = 2 @integer 2 @decimal 2.0, 2.00, 2.000, 2.0000</pluralRule>
+            <pluralRule count="few">n % 100 = 3..10 @integer 3~10, 103~110, 1003, … @decimal 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 103.0, 1003.0, …</pluralRule>
+            <pluralRule count="many">n % 100 = 11..99 @integer 11~26, 111, 1011, … @decimal 11.0, 12.0, 13.0, 14.0, 15.0, 16.0, 17.0, 18.0, 111.0, 1011.0, …</pluralRule>
+            <pluralRule count="other"> @integer 100~102, 200~202, 300~302, 400~402, 500~502, 600, 1000, 10000, 100000, 1000000, … @decimal 0.1~0.9, 1.1~1.7, 10.1, 100.0, 1000.0, 10000.0, 100000.0, 1000000.0, …</pluralRule>
+        </pluralRules>
+        <pluralRules locales="he iw">
+            <pluralRule count="one">i = 1 and v = 0 @integer 1</pluralRule>
+            <pluralRule count="two">i = 2 and v = 0 @integer 2</pluralRule>
+            <pluralRule count="many">v = 0 and n != 0..10 and n % 10 = 0 @integer 20, 30, 40, 50, 60, 70, 80, 90, 100, 1000, 10000, 100000, 1000000, …</pluralRule>
+            <pluralRule count="other"> @integer 0, 3~17, 101, 1001, … @decimal 0.0~1.5, 10.0, 100.0, 1000.0, 10000.0, 100000.0, 1000000.0, …</pluralRule>
+        </pluralRules>
+        <pluralRules locales="af asa ast az bem bez bg brx cgg chr ckb dv ee el eo es eu fo fur fy gsw ha haw hu jgo jmc ka kaj kcg kk kkj kl ks ksb ku ky lb lg mas mgo ml mn nah nb nd ne nn nnh no nr ny nyn om or os pap ps rm rof rwk saq seh sn so sq ss ssy st syr ta te teo tig tk tn tr ts uz ve vo vun wae xh xog">
+            <pluralRule count="one">n = 1 @integer 1 @decimal 1.0, 1.00, 1.000, 1.0000</pluralRule>
+            <pluralRule count="other"> @integer 0, 2~16, 100, 1000, 10000, 100000, 1000000, … @decimal 0.0~0.9, 1.1~1.6, 10.0, 100.0, 1000.0, 10000.0, 100000.0, 1000000.0, …</pluralRule>
+        </pluralRules>
+        <pluralRules locales="ak bh guw ln mg nso pa ti wa">
+            <pluralRule count="one">n = 0..1 @integer 0, 1 @decimal 0.0, 1.0, 0.00, 1.00, 0.000, 1.000, 0.0000, 1.0000</pluralRule>
+            <pluralRule count="other"> @integer 2~17, 100, 1000, 10000, 100000, 1000000, … @decimal 0.1~0.9, 1.1~1.7, 10.0, 100.0, 1000.0, 10000.0, 100000.0, 1000000.0, …</pluralRule>
+        </pluralRules>
+        <pluralRules locales="ff fr hy kab">
+            <pluralRule count="one">i = 0,1 @integer 0, 1 @decimal 0.0~1.5</pluralRule>
+            <pluralRule count="other"> @integer 2~17, 100, 1000, 10000, 100000, 1000000, … @decimal 2.0~3.5, 10.0, 100.0, 1000.0, 10000.0, 100000.0, 1000000.0, …</pluralRule>
         </pluralRules>
         <pluralRules locales="lv">
-            <pluralRule count="zero">n is 0</pluralRule>
-            <pluralRule count="one">n mod 10 is 1 and n mod 100 is not 11</pluralRule>
+            <pluralRule count="zero">n % 10 = 0 or n % 100 = 11..19 or v = 2 and f % 100 = 11..19 @integer 0, 10~20, 30, 40, 50, 60, 100, 1000, 10000, 100000, 1000000, … @decimal 0.0, 10.0, 11.0, 12.0, 13.0, 14.0, 15.0, 16.0, 100.0, 1000.0, 10000.0, 100000.0, 1000000.0, …</pluralRule>
+            <pluralRule count="one">n % 10 = 1 and n % 100 != 11 or v = 2 and f % 10 = 1 and f % 100 != 11 or v != 2 and f % 10 = 1 @integer 1, 21, 31, 41, 51, 61, 71, 81, 101, 1001, … @decimal 0.1, 1.0, 1.1, 2.1, 3.1, 4.1, 5.1, 6.1, 7.1, 10.1, 100.1, 1000.1, …</pluralRule>
+            <pluralRule count="other"> @integer 2~9, 22~29, 102, 1002, … @decimal 0.2~0.9, 1.2~1.9, 10.2, 100.2, 1000.2, …</pluralRule>
         </pluralRules>
         <pluralRules locales="iu kw naq se sma smi smj smn sms">
-            <pluralRule count="one">n is 1</pluralRule>
-            <pluralRule count="two">n is 2</pluralRule>
-        </pluralRules>
-        <pluralRules locales="ga"> <!-- http://unicode.org/cldr/trac/ticket/3915 -->
-            <pluralRule count="one">n is 1</pluralRule>
-            <pluralRule count="two">n is 2</pluralRule>
-            <pluralRule count="few">n in 3..6</pluralRule>
-            <pluralRule count="many">n in 7..10</pluralRule>
-        </pluralRules>
-        <pluralRules locales="ro mo">
-            <pluralRule count="one">n is 1</pluralRule>
-            <pluralRule count="few">n is 0 OR n is not 1 AND n mod 100 in 1..19</pluralRule>
+            <pluralRule count="one">n = 1 @integer 1 @decimal 1.0, 1.00, 1.000, 1.0000</pluralRule>
+            <pluralRule count="two">n = 2 @integer 2 @decimal 2.0, 2.00, 2.000, 2.0000</pluralRule>
+            <pluralRule count="other"> @integer 0, 3~17, 100, 1000, 10000, 100000, 1000000, … @decimal 0.0~0.9, 1.1~1.6, 10.0, 100.0, 1000.0, 10000.0, 100000.0, 1000000.0, …</pluralRule>
+        </pluralRules>
+        <pluralRules locales="ga">
+            <pluralRule count="one">n = 1 @integer 1 @decimal 1.0, 1.00, 1.000, 1.0000</pluralRule>
+            <pluralRule count="two">n = 2 @integer 2 @decimal 2.0, 2.00, 2.000, 2.0000</pluralRule>
+            <pluralRule count="few">n = 3..6 @integer 3~6 @decimal 3.0, 4.0, 5.0, 6.0, 3.00, 4.00, 5.00, 6.00, 3.000, 4.000, 5.000, 6.000, 3.0000, 4.0000, 5.0000, 6.0000</pluralRule>
+            <pluralRule count="many">n = 7..10 @integer 7~10 @decimal 7.0, 8.0, 9.0, 10.0, 7.00, 8.00, 9.00, 10.00, 7.000, 8.000, 9.000, 10.000, 7.0000, 8.0000, 9.0000, 10.0000</pluralRule>
+            <pluralRule count="other"> @integer 0, 11~25, 100, 1000, 10000, 100000, 1000000, … @decimal 0.0~0.9, 1.1~1.6, 10.1, 100.0, 1000.0, 10000.0, 100000.0, 1000000.0, …</pluralRule>
+        </pluralRules>
+        <pluralRules locales="mo ro">
+            <pluralRule count="one">i = 1 and v = 0 @integer 1</pluralRule>
+            <pluralRule count="few">v != 0 or n = 0 or n != 1 and n % 100 = 1..19 @integer 0, 2~16, 101, 1001, … @decimal 0.0~1.5, 10.0, 100.0, 1000.0, 10000.0, 100000.0, 1000000.0, …</pluralRule>
+            <pluralRule count="other"> @integer 20~35, 100, 1000, 10000, 100000, 1000000, …</pluralRule>
         </pluralRules>
         <pluralRules locales="lt">
-            <pluralRule count="one">n mod 10 is 1 and n mod 100 not in 11..19</pluralRule>
-            <pluralRule count="few">n mod 10 in 2..9 and n mod 100 not in 11..19</pluralRule>
+            <pluralRule count="one">n % 10 = 1 and n % 100 != 11..19 @integer 1, 21, 31, 41, 51, 61, 71, 81, 101, 1001, … @decimal 1.0, 21.0, 31.0, 41.0, 51.0, 61.0, 71.0, 81.0, 101.0, 1001.0, …</pluralRule>
+            <pluralRule count="few">n % 10 = 2..9 and n % 100 != 11..19 @integer 2~9, 22~29, 102, 1002, … @decimal 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 22.0, 102.0, 1002.0, …</pluralRule>
+            <pluralRule count="many">f != 0   @decimal 0.1~0.9, 1.1~1.7, 10.1, 100.1, 1000.1, …</pluralRule>
+            <pluralRule count="other"> @integer 0, 10~20, 30, 40, 50, 60, 100, 1000, 10000, 100000, 1000000, … @decimal 0.0, 10.0, 11.0, 12.0, 13.0, 14.0, 15.0, 16.0, 100.0, 1000.0, 10000.0, 100000.0, 1000000.0, …</pluralRule>
         </pluralRules>
-        <pluralRules locales="be bs hr ru sh sr uk">
-            <pluralRule count="one">n mod 10 is 1 and n mod 100 is not 11</pluralRule>
-            <pluralRule count="few">n mod 10 in 2..4 and n mod 100 not in 12..14</pluralRule>
-            <pluralRule count="many">n mod 10 is 0 or n mod 10 in 5..9 or n mod 100 in 11..14</pluralRule>
-            <!-- others are fractions -->
+        <pluralRules locales="be">
+            <pluralRule count="one">n % 10 = 1 and n % 100 != 11 @integer 1, 21, 31, 41, 51, 61, 71, 81, 101, 1001, … @decimal 1.0, 21.0, 31.0, 41.0, 51.0, 61.0, 71.0, 81.0, 101.0, 1001.0, …</pluralRule>
+            <pluralRule count="few">n % 10 = 2..4 and n % 100 != 12..14 @integer 2~4, 22~24, 32~34, 42~44, 52~54, 62, 102, 1002, … @decimal 2.0, 3.0, 4.0, 22.0, 23.0, 24.0, 32.0, 33.0, 102.0, 1002.0, …</pluralRule>
+            <pluralRule count="many">n % 10 = 0 or n % 10 = 5..9 or n % 100 = 11..14 @integer 0, 5~19, 100, 1000, 10000, 100000, 1000000, … @decimal 0.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 11.0, 100.0, 1000.0, 10000.0, 100000.0, 1000000.0, …</pluralRule>
+            <pluralRule count="other">   @decimal 0.1~0.9, 1.1~1.7, 10.1, 100.1, 1000.1, …</pluralRule>
         </pluralRules>
         <pluralRules locales="cs sk">
-            <pluralRule count="one">n is 1</pluralRule>
-            <pluralRule count="few">n in 2..4</pluralRule>
+            <pluralRule count="one">i = 1 and v = 0 @integer 1</pluralRule>
+            <pluralRule count="few">i = 2..4 and v = 0 @integer 2~4</pluralRule>
+            <pluralRule count="many">v != 0   @decimal 0.0~1.5, 10.0, 100.0, 1000.0, 10000.0, 100000.0, 1000000.0, …</pluralRule>
+            <pluralRule count="other"> @integer 0, 5~19, 100, 1000, 10000, 100000, 1000000, …</pluralRule>
         </pluralRules>
         <pluralRules locales="pl">
-            <pluralRule count="one">n is 1</pluralRule>
-            <pluralRule count="few">n mod 10 in 2..4 and n mod 100 not in 12..14</pluralRule>
-            <pluralRule count="many">n is not 1 and n mod 10 in 0..1 or n mod 10 in 5..9 or n mod 100 in 12..14</pluralRule>
-            <!-- others are fractions -->
-            <!-- and n mod 100 not in 22..24 from Tamplin -->
+            <pluralRule count="one">i = 1 and v = 0 @integer 1</pluralRule>
+            <pluralRule count="few">v = 0 and i % 10 = 2..4 and i % 100 != 12..14 @integer 2~4, 22~24, 32~34, 42~44, 52~54, 62, 102, 1002, …</pluralRule>
+            <pluralRule count="many">v = 0 and i != 1 and i % 10 = 0..1 or v = 0 and i % 10 = 5..9 or v = 0 and i % 100 = 12..14 @integer 0, 5~19, 100, 1000, 10000, 100000, 1000000, …</pluralRule>
+            <pluralRule count="other">   @decimal 0.0~1.5, 10.0, 100.0, 1000.0, 10000.0, 100000.0, 1000000.0, …</pluralRule>
         </pluralRules>
         <pluralRules locales="sl">
-            <pluralRule count="one">n mod 100 is 1</pluralRule>
-            <pluralRule count="two">n mod 100 is 2</pluralRule>
-            <pluralRule count="few">n mod 100 in 3..4</pluralRule>
-        </pluralRules>
-        <pluralRules locales="mt"> <!-- from Tamplin's data -->
-            <pluralRule count="one">n is 1</pluralRule>
-            <pluralRule count="few">n is 0 or n mod 100 in 2..10</pluralRule>
-            <pluralRule count="many">n mod 100 in 11..19</pluralRule>
-        </pluralRules>
-        <pluralRules locales="mk"> <!-- from Tamplin's data -->
-            <pluralRule count="one">n mod 10 is 1 and n is not 11</pluralRule>
-        </pluralRules>
-        <pluralRules locales="cy"> <!-- from http://www.saltcymru.org/wordpress/?p=99&lang=en -->
-            <pluralRule count="zero">n is 0</pluralRule>
-            <pluralRule count="one">n is 1</pluralRule>
-            <pluralRule count="two">n is 2</pluralRule>
-            <pluralRule count="few">n is 3</pluralRule>
-            <pluralRule count="many">n is 6</pluralRule>
+            <pluralRule count="one">v = 0 and i % 100 = 1 @integer 1, 101, 201, 301, 401, 501, 601, 701, 1001, …</pluralRule>
+            <pluralRule count="two">v = 0 and i % 100 = 2 @integer 2, 102, 202, 302, 402, 502, 602, 702, 1002, …</pluralRule>
+            <pluralRule count="few">v = 0 and i % 100 = 3..4 or v != 0 @integer 3, 4, 103, 104, 203, 204, 303, 304, 403, 404, 503, 504, 603, 604, 703, 704, 1003, … @decimal 0.0~1.5, 10.0, 100.0, 1000.0, 10000.0, 100000.0, 1000000.0, …</pluralRule>
+            <pluralRule count="other"> @integer 0, 5~19, 100, 1000, 10000, 100000, 1000000, …</pluralRule>
+        </pluralRules>
+        <pluralRules locales="mt">
+            <pluralRule count="one">n = 1 @integer 1 @decimal 1.0, 1.00, 1.000, 1.0000</pluralRule>
+            <pluralRule count="few">n = 0 or n % 100 = 2..10 @integer 0, 2~10, 102~107, 1002, … @decimal 0.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 10.0, 102.0, 1002.0, …</pluralRule>
+            <pluralRule count="many">n % 100 = 11..19 @integer 11~19, 111~117, 1011, … @decimal 11.0, 12.0, 13.0, 14.0, 15.0, 16.0, 17.0, 18.0, 111.0, 1011.0, …</pluralRule>
+            <pluralRule count="other"> @integer 20~35, 100, 1000, 10000, 100000, 1000000, … @decimal 0.1~0.9, 1.1~1.7, 10.1, 100.0, 1000.0, 10000.0, 100000.0, 1000000.0, …</pluralRule>
+        </pluralRules>
+        <pluralRules locales="mk">
+            <pluralRule count="one">v = 0 and i % 10 = 1 or f % 10 = 1 @integer 1, 11, 21, 31, 41, 51, 61, 71, 101, 1001, … @decimal 0.1, 1.1, 2.1, 3.1, 4.1, 5.1, 6.1, 7.1, 10.1, 100.1, 1000.1, …</pluralRule>
+            <pluralRule count="other"> @integer 0, 2~10, 12~17, 100, 1000, 10000, 100000, 1000000, … @decimal 0.0, 0.2~1.0, 1.2~1.7, 10.0, 100.0, 1000.0, 10000.0, 100000.0, 1000000.0, …</pluralRule>
+        </pluralRules>
+        <pluralRules locales="cy">
+            <pluralRule count="zero">n = 0 @integer 0 @decimal 0.0, 0.00, 0.000, 0.0000</pluralRule>
+            <pluralRule count="one">n = 1 @integer 1 @decimal 1.0, 1.00, 1.000, 1.0000</pluralRule>
+            <pluralRule count="two">n = 2 @integer 2 @decimal 2.0, 2.00, 2.000, 2.0000</pluralRule>
+            <pluralRule count="few">n = 3 @integer 3 @decimal 3.0, 3.00, 3.000, 3.0000</pluralRule>
+            <pluralRule count="many">n = 6 @integer 6 @decimal 6.0, 6.00, 6.000, 6.0000</pluralRule>
+            <pluralRule count="other"> @integer 4, 5, 7~20, 100, 1000, 10000, 100000, 1000000, … @decimal 0.1~0.9, 1.1~1.7, 10.0, 100.0, 1000.0, 10000.0, 100000.0, 1000000.0, …</pluralRule>
         </pluralRules>
         <pluralRules locales="lag">
-            <pluralRule count="zero">n is 0</pluralRule>
-            <pluralRule count="one">n within 0..2 and n is not 0 and n is not 2</pluralRule>
+            <pluralRule count="zero">n = 0 @integer 0 @decimal 0.0, 0.00, 0.000, 0.0000</pluralRule>
+            <pluralRule count="one">i = 0,1 and n != 0 @integer 1 @decimal 0.1~1.6</pluralRule>
+            <pluralRule count="other"> @integer 2~17, 100, 1000, 10000, 100000, 1000000, … @decimal 2.0~3.5, 10.0, 100.0, 1000.0, 10000.0, 100000.0, 1000000.0, …</pluralRule>
         </pluralRules>
         <pluralRules locales="shi">
-            <pluralRule count="one">n within 0..1</pluralRule>
-            <pluralRule count="few">n in 2..10</pluralRule>
+            <pluralRule count="one">i = 0 or n = 1 @integer 0, 1 @decimal 0.0~1.0, 0.00~0.04</pluralRule>
+            <pluralRule count="few">n = 2..10 @integer 2~10 @decimal 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 2.00, 3.00, 4.00, 5.00, 6.00, 7.00, 8.00</pluralRule>
+            <pluralRule count="other"> @integer 11~26, 100, 1000, 10000, 100000, 1000000, … @decimal 1.1~1.9, 2.1~2.7, 10.1, 100.0, 1000.0, 10000.0, 100000.0, 1000000.0, …</pluralRule>
         </pluralRules>
-        <pluralRules locales="br"> <!-- from http://unicode.org/cldr/trac/ticket/2886 -->
-            <pluralRule count="one">n mod 10 is 1 and n mod 100 not in 11,71,91</pluralRule>
-            <pluralRule count="two">n mod 10 is 2 and n mod 100 not in 12,72,92</pluralRule>
-            <pluralRule count="few">n mod 10 in 3..4,9 and n mod 100 not in 10..19,70..79,90..99</pluralRule>
-            <pluralRule count="many">n is not 0 and n mod 1000000 is 0</pluralRule>
+        <pluralRules locales="br">
+            <pluralRule count="one">n % 10 = 1 and n % 100 != 11,71,91 @integer 1, 21, 31, 41, 51, 61, 81, 101, 1001, … @decimal 1.0, 21.0, 31.0, 41.0, 51.0, 61.0, 81.0, 101.0, 1001.0, …</pluralRule>
+            <pluralRule count="two">n % 10 = 2 and n % 100 != 12,72,92 @integer 2, 22, 32, 42, 52, 62, 82, 102, 1002, … @decimal 2.0, 22.0, 32.0, 42.0, 52.0, 62.0, 82.0, 102.0, 1002.0, …</pluralRule>
+            <pluralRule count="few">n % 10 = 3..4,9 and n % 100 != 10..19,70..79,90..99 @integer 3, 4, 9, 23, 24, 29, 33, 34, 39, 43, 44, 49, 103, 1003, … @decimal 3.0, 4.0, 9.0, 23.0, 24.0, 29.0, 33.0, 34.0, 103.0, 1003.0, …</pluralRule>
+            <pluralRule count="many">n != 0 and n % 1000000 = 0 @integer 1000000, … @decimal 1000000.0, 1000000.00, 1000000.000, …</pluralRule>
+            <pluralRule count="other"> @integer 0, 5~8, 10~20, 100, 1000, 10000, 100000, … @decimal 0.0~0.9, 1.1~1.6, 10.0, 100.0, 1000.0, 10000.0, 100000.0, …</pluralRule>
         </pluralRules>
         <pluralRules locales="ksh">
-            <pluralRule count="zero">n is 0</pluralRule>
-            <pluralRule count="one">n is 1</pluralRule>
+            <pluralRule count="zero">n = 0 @integer 0 @decimal 0.0, 0.00, 0.000, 0.0000</pluralRule>
+            <pluralRule count="one">n = 1 @integer 1 @decimal 1.0, 1.00, 1.000, 1.0000</pluralRule>
+            <pluralRule count="other"> @integer 2~17, 100, 1000, 10000, 100000, 1000000, … @decimal 0.1~0.9, 1.1~1.7, 10.0, 100.0, 1000.0, 10000.0, 100000.0, 1000000.0, …</pluralRule>
         </pluralRules>
         <pluralRules locales="tzm">
-            <pluralRule count="one">n in 0..1 or n in 11..99</pluralRule>
+            <pluralRule count="one">n = 0..1 or n = 11..99 @integer 0, 1, 11~24 @decimal 0.0, 1.0, 11.0, 12.0, 13.0, 14.0, 15.0, 16.0, 17.0, 18.0, 19.0, 20.0, 21.0, 22.0, 23.0, 24.0</pluralRule>
+            <pluralRule count="other"> @integer 2~10, 100~106, 1000, 10000, 100000, 1000000, … @decimal 0.1~0.9, 1.1~1.7, 10.0, 100.0, 1000.0, 10000.0, 100000.0, 1000000.0, …</pluralRule>
         </pluralRules>
         <pluralRules locales="gv">
-            <pluralRule count="one">n mod 10 in 1..2 or n mod 20 is 0</pluralRule>
+            <pluralRule count="one">n % 10 = 1 @integer 1, 11, 21, 31, 41, 51, 61, 71, 101, 1001, … @decimal 1.0, 11.0, 21.0, 31.0, 41.0, 51.0, 61.0, 71.0, 101.0, 1001.0, …</pluralRule>
+            <pluralRule count="two">n % 10 = 2 @integer 2, 12, 22, 32, 42, 52, 62, 72, 102, 1002, … @decimal 2.0, 12.0, 22.0, 32.0, 42.0, 52.0, 62.0, 72.0, 102.0, 1002.0, …</pluralRule>
+            <pluralRule count="few">n % 100 = 0,20,40,60 @integer 0, 20, 40, 60, 100, 120, 140, 160, 1000, 10000, 100000, 1000000, … @decimal 0.0, 20.0, 40.0, 60.0, 100.0, 120.0, 140.0, 160.0, 1000.0, 10000.0, 100000.0, 1000000.0, …</pluralRule>
+            <pluralRule count="other"> @integer 3~10, 13~19, 23, 103, 1003, … @decimal 0.1~0.9, 1.1~1.7, 10.0, 100.1, 1000.1, …</pluralRule>
         </pluralRules>
         <pluralRules locales="gd">
-            <pluralRule count="one">n in 1,11</pluralRule>
-            <pluralRule count="two">n in 2,12</pluralRule>
-            <pluralRule count="few">n in 3..10,13..19</pluralRule>
+            <pluralRule count="one">n = 1,11 @integer 1, 11 @decimal 1.0, 11.0, 1.00, 11.00, 1.000, 11.000, 1.0000</pluralRule>
+            <pluralRule count="two">n = 2,12 @integer 2, 12 @decimal 2.0, 12.0, 2.00, 12.00, 2.000, 12.000, 2.0000</pluralRule>
+            <pluralRule count="few">n = 3..10,13..19 @integer 3~10, 13~19 @decimal 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 13.0, 14.0, 15.0, 16.0, 17.0, 18.0, 19.0, 3.00</pluralRule>
+            <pluralRule count="other"> @integer 0, 20~34, 100, 1000, 10000, 100000, 1000000, … @decimal 0.0~0.9, 1.1~1.6, 10.1, 100.0, 1000.0, 10000.0, 100000.0, 1000000.0, …</pluralRule>
+        </pluralRules>
+        <pluralRules locales="bm bo dz id ig ii in ja jbo jv jw kde kea km ko lkt lo ms my nqo sah ses sg th to vi wo yo zh">
+            <pluralRule count="other"> @integer 0~15, 100, 1000, 10000, 100000, 1000000, … @decimal 0.0~1.5, 10.0, 100.0, 1000.0, 10000.0, 100000.0, 1000000.0, …</pluralRule>
+        </pluralRules>
+        <pluralRules locales="fil tl">
+            <pluralRule count="one">i = 0..1 and v = 0 @integer 0, 1</pluralRule>
+            <pluralRule count="other"> @integer 2~17, 100, 1000, 10000, 100000, 1000000, … @decimal 0.0~1.5, 10.0, 100.0, 1000.0, 10000.0, 100000.0, 1000000.0, …</pluralRule>
+        </pluralRules>
+        <pluralRules locales="ca de en et fi gl it ji nl sv sw ur yi">
+            <pluralRule count="one">i = 1 and v = 0 @integer 1</pluralRule>
+            <pluralRule count="other"> @integer 0, 2~16, 100, 1000, 10000, 100000, 1000000, … @decimal 0.0~1.5, 10.0, 100.0, 1000.0, 10000.0, 100000.0, 1000000.0, …</pluralRule>
+        </pluralRules>
+        <pluralRules locales="pt">
+            <pluralRule count="one">i = 1 and v = 0 or i = 0 and t = 1 @integer 1 @decimal 0.1, 0.01, 0.10, 0.001, 0.010, 0.100, 0.0001, 0.0010, 0.0100, 0.1000</pluralRule>
+            <pluralRule count="other"> @integer 0, 2~16, 100, 1000, 10000, 100000, 1000000, … @decimal 0.0, 0.2~1.6, 10.0, 100.0, 1000.0, 10000.0, 100000.0, 1000000.0, …</pluralRule>
+        </pluralRules>
+        <pluralRules locales="da">
+            <pluralRule count="one">n = 1 or t != 0 and i = 0,1 @integer 1 @decimal 0.1~1.6</pluralRule>
+            <pluralRule count="other"> @integer 0, 2~16, 100, 1000, 10000, 100000, 1000000, … @decimal 0.0, 2.0~3.4, 10.0, 100.0, 1000.0, 10000.0, 100000.0, 1000000.0, …</pluralRule>
+        </pluralRules>
+        <pluralRules locales="pt_PT">
+            <pluralRule count="one">n = 1 and v = 0 @integer 1</pluralRule>
+            <pluralRule count="other"> @integer 0, 2~16, 100, 1000, 10000, 100000, 1000000, … @decimal 0.0~1.5, 10.0, 100.0, 1000.0, 10000.0, 100000.0, 1000000.0, …</pluralRule>
+        </pluralRules>
+        <pluralRules locales="am bn fa gu hi kn mr zu">
+            <pluralRule count="one">i = 0 or n = 1 @integer 0, 1 @decimal 0.0~1.0, 0.00~0.04</pluralRule>
+            <pluralRule count="other"> @integer 2~17, 100, 1000, 10000, 100000, 1000000, … @decimal 1.1~2.6, 10.0, 100.0, 1000.0, 10000.0, 100000.0, 1000000.0, …</pluralRule>
+        </pluralRules>
+        <pluralRules locales="is">
+            <pluralRule count="one">t = 0 and i % 10 = 1 and i % 100 != 11 or t != 0 @integer 1, 21, 31, 41, 51, 61, 71, 81, 101, 1001, … @decimal 0.1~1.6, 10.1, 100.1, 1000.1, …</pluralRule>
+            <pluralRule count="other"> @integer 0, 2~16, 100, 1000, 10000, 100000, 1000000, … @decimal 0.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 10.0, 100.0, 1000.0, 10000.0, 100000.0, 1000000.0, …</pluralRule>
+        </pluralRules>
+        <pluralRules locales="si">
+            <pluralRule count="one">n = 0,1 or i = 0 and f = 1 @integer 0, 1 @decimal 0.0, 0.1, 1.0, 0.00, 0.01, 1.00, 0.000, 0.001, 1.000, 0.0000, 0.0001, 1.0000</pluralRule>
+            <pluralRule count="other"> @integer 2~17, 100, 1000, 10000, 100000, 1000000, … @decimal 0.2~0.9, 1.1~1.8, 10.0, 100.0, 1000.0, 10000.0, 100000.0, 1000000.0, …</pluralRule>
+        </pluralRules>
+        <pluralRules locales="bs hr sh sr">
+            <pluralRule count="one">v = 0 and i % 10 = 1 and i % 100 != 11 or f % 10 = 1 and f % 100 != 11 @integer 1, 21, 31, 41, 51, 61, 71, 81, 101, 1001, … @decimal 0.1, 1.1, 2.1, 3.1, 4.1, 5.1, 6.1, 7.1, 10.1, 100.1, 1000.1, …</pluralRule>
+            <pluralRule count="few">v = 0 and i % 10 = 2..4 and i % 100 != 12..14 or f % 10 = 2..4 and f % 100 != 12..14 @integer 2~4, 22~24, 32~34, 42~44, 52~54, 62, 102, 1002, … @decimal 0.2~0.4, 1.2~1.4, 2.2~2.4, 3.2~3.4, 4.2~4.4, 5.2, 10.2, 100.2, 1000.2, …</pluralRule>
+            <pluralRule count="other"> @integer 0, 5~19, 100, 1000, 10000, 100000, 1000000, … @decimal 0.0, 0.5~1.0, 1.5~2.0, 2.5~2.7, 10.0, 100.0, 1000.0, 10000.0, 100000.0, 1000000.0, …</pluralRule>
+        </pluralRules>
+        <pluralRules locales="ru">
+            <pluralRule count="one">v = 0 and i % 10 = 1 and i % 100 != 11 @integer 1, 21, 31, 41, 51, 61, 71, 81, 101, 1001, …</pluralRule>
+            <pluralRule count="many">v = 0 and i % 10 = 0 or v = 0 and i % 10 = 5..9 or v = 0 and i % 100 = 11..14 @integer 0, 5~19, 100, 1000, 10000, 100000, 1000000, …</pluralRule>
+            <pluralRule count="other"> @integer 2~4, 22~24, 32~34, 42~44, 52~54, 62, 102, 1002, … @decimal 0.0~1.5, 10.0, 100.0, 1000.0, 10000.0, 100000.0, 1000000.0, …</pluralRule>
+        </pluralRules>
+        <pluralRules locales="uk">
+            <pluralRule count="one">v = 0 and i % 10 = 1 and i % 100 != 11 @integer 1, 21, 31, 41, 51, 61, 71, 81, 101, 1001, …</pluralRule>
+            <pluralRule count="few">v = 0 and i % 10 = 2..4 and i % 100 != 12..14 @integer 2~4, 22~24, 32~34, 42~44, 52~54, 62, 102, 1002, …</pluralRule>
+            <pluralRule count="many">v = 0 and i % 10 = 0 or v = 0 and i % 10 = 5..9 or v = 0 and i % 100 = 11..14 @integer 0, 5~19, 100, 1000, 10000, 100000, 1000000, …</pluralRule>
+            <pluralRule count="other">   @decimal 0.0~1.5, 10.0, 100.0, 1000.0, 10000.0, 100000.0, 1000000.0, …</pluralRule>
         </pluralRules>
     </plurals>
 </supplementalData>
index eedee7a..b29e16e 100644 (file)
@@ -1554,7 +1554,7 @@ Ma skrivit anezhañ e vo implijet evit lakaat war wel ar pezh a vo bet degaset g
 'recentchanges-label-minor' => "Ur c'hemm dister eo hemañ",
 'recentchanges-label-bot' => "Gant ur bot eo bet degaset ar c'hemm-mañ.",
 'recentchanges-label-unpatrolled' => "N'eo ket bet gwiriet ar c'hemm-mañ evit c'hoazh.",
-'recentchanges-label-plusminus' => 'Kemmet he deus ment ar bajenn eus an niver-se a bitoù',
+'recentchanges-label-plusminus' => 'Kemmet eo ment ar bajenn eus an niver-mañ a oktedoù',
 'recentchanges-legend-newpage' => '(gwelet ivez [[Dibar:PajennoùNevez|roll ar pajennoù nevez krouet]])',
 'rcnotefrom' => "Setu aze roll ar c'hemmoù c'hoarvezet abaoe an '''$2''' ('''$1''' d'ar muiañ).",
 'rclistfrom' => "Diskouez ar c'hemmoù diwezhañ abaoe an $1.",
index 2fc5d64..f68c3e3 100644 (file)
@@ -423,7 +423,7 @@ $messages = array(
 'article' => 'Članak',
 'newwindow' => '(otvara se u novom prozoru)',
 'cancel' => 'Poništite',
-'moredotdotdot' => 'Još...',
+'moredotdotdot' => 'Više...',
 'morenotlisted' => 'Ovaj spisak nije kompletan.',
 'mypage' => 'Korisnička stranica',
 'mytalk' => 'Razgovor',
index 8202ea1..35b7eb4 100644 (file)
@@ -1065,6 +1065,9 @@ Se n'han omès els arguments.",
 'cantcreateaccounttitle' => 'No es pot crear el compte',
 'cantcreateaccount-text' => "[[User:$3|$3]] ha bloquejat la creació de comptes des d'aquesta adreça IP ('''$1''').
 
+El motiu donat per $3 és ''$2''",
+'cantcreateaccount-range-text' => "La creació de comptes des de les adreces IP en el rang '''$1''', que inclou la vostra adreça IP ('''$4'''), ha esta blocada per [[User:$3|$3]].
+
 El motiu donat per $3 és ''$2''",
 
 # History pages
@@ -2350,6 +2353,7 @@ Vegeu $2 per a un registre dels esborrats més recents.",
 'delete-edit-reasonlist' => "Edita els motius d'eliminació",
 'delete-toobig' => "Aquesta pàgina té un historial d'edicions molt gran, amb més de $1 {{PLURAL:$1|canvi|canvis}}. L'eliminació d'aquestes pàgines està restringida per a prevenir que hi pugui haver un desajustament seriós de la base de dades de tot el projecte {{SITENAME}} per accident.",
 'delete-warning-toobig' => "Aquesta pàgina té un historial d'edicions molt gran, amb més de $1 {{PLURAL:$1|canvi|canvis}}. Eliminar-la podria suposar un seriós desajustament de la base de dades de tot el projecte {{SITENAME}}; aneu en compte abans dur a terme l'acció.",
+'deleting-backlinks-warning' => "'''Avís:''' Altres pàgines enllacen a la pàgina que esteu a punt de suprimir.",
 
 # Rollback
 'rollback' => 'Reverteix edicions',
index 6aea594..9b75b1f 100644 (file)
@@ -698,8 +698,10 @@ URL язъеш гӀалат даьлла хила мега.
 'viewsource' => 'Хьажар',
 'viewsource-title' => 'Агӏона $1 дуьххьарлера йозане хьажар',
 'actionthrottled' => 'Сиххалин доза тохар',
+'actionthrottledtext' => 'Спам цахилийта хӀара дешдерг кӀезиг хенахь дукху ца дайта дихкина ду. Дехар до массийта минот яьлча гӀорта.',
 'protectedpagetext' => 'ХӀара агӀо дӀакъойлина йу рé цадаккхийта.',
 'viewsourcetext' => 'Хьоьга далундерг хьажар а дезахь хlокху агlон чура йоза хьаэцар:',
+'viewyourtext' => "Хьан йиш ю '''хьой нисдинчу''' дӀадолалун йозе хьажа а цуна копи ян а:",
 'protectedinterface' => 'ХӀара схьгайтарна гӀирса хаамаш латтош йолу агӀо ю. Куьйгалхошна бен иза хийца цало.',
 'editinginterface' => "'''Тергам бе:''' Ахьа таеш ю интерфейсан йоза долу агӀо програмин латторан.
 Цуна бина хийцам хьокху википедин кхечу декъашхошна гур бу.
@@ -711,6 +713,7 @@ URL язъеш гӀалат даьлла хила мега.
 'mycustomjsprotected' => 'Хьан бакъо яц JavaScript агӀо тая.',
 'myprivateinfoprotected' => 'Хьайн долара хаамна хийцам ба хьа йиш яц',
 'mypreferencesprotected' => 'Хьай гӀирс нисбан хьа бакъо яц.',
+'ns-specialprotected' => 'ХӀокху «{{ns:special}}» цӀерийн меттигашан агӀонаш таян йиш яц.',
 'exception-nologin' => 'ХӀинца а ахьа системин чохь болх беш бац',
 
 # Virus scanner
@@ -824,6 +827,7 @@ URL язъеш гӀалат даьлла хила мега.
 'usernamehasherror' => 'Декъашхочун цӀеран юкъахь хийла ца еза «цаца»',
 'login-throttled' => 'Хьо дукха гӀиртира.
 Дехар до, собар де $1 юха гӀортале.',
+'login-abort-generic' => 'Сестемин довзийта тарцаделира',
 'loginlanguagelabel' => 'Мотт: $1',
 
 # Change password dialog
@@ -833,11 +837,14 @@ URL язъеш гӀалат даьлла хила мега.
 'oldpassword' => 'Шираелла пароль:',
 'newpassword' => 'Керла пароль:',
 'retypenew' => 'Юха язъйе керла пароль:',
+'resetpass_submit' => 'Пароль дӀахӀоттийна системин чугӀо',
+'changepassword-success' => 'Хьан пароль кхиамца хийцина!',
 'resetpass_forbidden' => 'Пароль хийца йиш яц',
 'resetpass-no-info' => 'ХӀара агӀо лело системин чугӀо.',
 'resetpass-submit-loggedin' => 'Хийца пароль',
 'resetpass-submit-cancel' => 'Цаоьшу',
 'resetpass-temp-password' => 'Цхьан хана пароль:',
+'resetpass-abort-generic' => 'Пароль хийцар дӀахедар',
 
 # Special:PasswordReset
 'passwordreset' => 'Пароль кхоссар',
@@ -845,7 +852,14 @@ URL язъеш гӀалат даьлла хила мега.
 'passwordreset-legend' => 'Пароль кхоссар',
 'passwordreset-username' => 'Декъашхочун цӀе:',
 'passwordreset-domain' => 'Домен:',
+'passwordreset-capture' => 'Хьажа беанчу хааме?',
 'passwordreset-email' => 'Электронни почтан адрес:',
+'passwordreset-emailtitle' => '{{SITENAME}}: декъашхочун дӀаяздарх лаьцна хаам',
+'passwordreset-emailelement' => 'Декъашхочун цӀе: $1
+Ханна йолу пароль: $2',
+'passwordreset-emailsent' => 'Электронан хаам баийтина кхоьссинчу паролах лаьцна хаам чохь болуш.',
+'passwordreset-emailsent-capture' => 'Электронан хаам баийтина кхоьссинчу паролах лаьцна хаам чохь болуш. 
+цуна йозане хьажа йиш ю лахахь.',
 
 # Special:ChangeEmail
 'changeemail' => 'Хийца электрони почт',
@@ -864,6 +878,7 @@ URL язъеш гӀалат даьлла хила мега.
 'resettokens-text' => 'Хьан йиш ю токенаш кхосса, цара йиш хуьлуьйту цхьаболу долара хаамашна тӀекхача, уьш ю хьан дӀаяздар ца вовшахтесна. 
 
 Хьона иза оьшу, ахьа хьай токенаш цхьам гучу яьхна елахь я хьан аккаунт йохийна елахь.',
+'resettokens-no-tokens' => 'Кхосса токенаш яц.',
 'resettokens-legend' => 'Токенаш кхоссар',
 'resettokens-tokens' => 'Токенаш:',
 'resettokens-token-label' => '$1 (карара маьӀна: $2)',
@@ -903,13 +918,18 @@ URL язъеш гӀалат даьлла хила мега.
 'showdiff' => 'Хlоттина болу хийцам',
 'anoneditwarning' => "'''Тергам бе''': Ахьа хьай цӀарца тадарш деш дац. Хьан IP-адрес дӀаяздина хира ду хӀокху агӀон истори чу.",
 'anonpreviewwarning' => "''Системин чу цагӀахь хьан IP-адрес агӀона истори чу дӀаяз лур ду.''",
+'missingcommenttext' => 'Дехар до дӀаязбе хайн хаам лахахь.',
 'summary-preview' => 'Цуьнах лаьцна хирду:',
+'subject-preview' => 'Коьрта могӀа хира бу:',
 'blockedtitle' => 'Декъашхочун блоктоьхана',
+'blockednoreason' => 'бахьана билгалдина дац',
+'whitelistedittext' => 'Ахьа да деза $1 агӀона хийцамаш бан.',
 'nosuchsectiontitle' => 'Дакъа каро йиш яц.',
 'nosuchsectiontext' => 'Хьо гӀерта доцу дакъа тадан.
 Хьо хӀокху агӀоне хьоьжучу хенахь иза кхечухьа деккхина я дӀадаьккхина хела тарло.',
 'loginreqtitle' => 'Хьай цӀарца чугӀо',
 'loginreqlink' => 'Логин',
+'loginreqpagetext' => 'Ахьа да деза $1, кхин агӀонаш хьажа.',
 'accmailtitle' => 'Пароль дlаяхьийтина.',
 'accmailtext' => "Пароль декъашхочуьна [[User talk:$1|$1]], йина ша шех хитта делла чу элпашах, дlаяхийтина хьокху $2 адрес тӀе.
 
@@ -987,6 +1007,7 @@ URL язъеш гӀалат даьлла хила мега.
 'template-semiprotected' => '(дуьззина доцуш гlаролла)',
 'hiddencategories' => 'ХӀара агӀо чуйогӀуш ю оцу $1 {{PLURAL:$1|къайлаха категори чу|къайлаха категореш чу}}:',
 'edittools' => '<!-- Кхузе буха диллина йоза гуш хир ду редоккхуче бухахь а хlума чуйоккхуче бухахь. -->',
+'nocreate-loggedin' => 'Хьан бакъо яц керла агӀонаш кхолла.',
 'sectioneditnotsupported-title' => 'Дакъош тадар ловш дац',
 'sectioneditnotsupported-text' => 'ХӀокху агӀорахь дакъош тадар ловш дац',
 'permissionserrors' => 'ТӀекхачаре бакъона гӀалат',
@@ -1014,6 +1035,8 @@ URL язъеш гӀалат даьлла хила мега.
 'content-not-allowed-here' => 'Чулацам "$1" [[$2]] агӀонгахь хилийта йиш яц',
 
 # Content models
+'content-model-wikitext' => 'вики-йоза',
+'content-model-text' => 'цхьалхе йоза',
 'content-model-javascript' => 'JavaScript',
 'content-model-css' => 'CSS',
 
@@ -1085,14 +1108,18 @@ URL язъеш гӀалат даьлла хила мега.
 'revdelete-hide-comment' => 'Хийцамах лаьцнарг',
 'revdelete-hide-user' => 'Къайлаяккха авторан цӀе',
 'revdelete-radio-same' => '(ма хийца)',
-'revdelete-radio-set' => 'Хlаъ',
-'revdelete-radio-unset' => 'Хlахlа',
+'revdelete-radio-set' => 'Къайлаяьккхина',
+'revdelete-radio-unset' => 'Гуш ерг',
+'revdelete-suppress' => 'Къайлабаха хаамаш куьйгалхойх а',
+'revdelete-unsuppress' => 'МеттахӀоьттина версешан дихкар къайладаккха',
 'revdelete-log' => 'Бахьан:',
 'revdelete-submit' => 'Кхочушде {{PLURAL:$1|къастина версин|къастина версешан}}',
 'revdelete-success' => "'''Версеш гуш хилар кхиамца хийцина.'''",
 'revdelete-failure' => "'''Версеш гуш хилар хийца йиш яц:'''
 $1",
 'logdelete-success' => 'Хиларг гуш хилар хийцина.',
+'logdelete-failure' => "'''Тептаран гуш хилар хӀоттина дац:'''
+$1",
 'revdel-restore' => 'Хийцам бе схьагарехь',
 'pagehist' => 'АгӀона истори',
 'deletedhist' => 'ДӀаяккхаран истори',
@@ -1105,9 +1132,20 @@ $1",
 'revdelete-otherreason' => 'Кхин бахьна/тӀетохар:',
 'revdelete-reasonotherlist' => 'Кхин бахьан',
 'revdelete-edit-reasonlist' => 'Бахьанин список нисяр',
+'revdelete-offender' => 'АгӀона версен автор:',
+
+# Suppression log
+'suppressionlog' => 'Хьулдаран тептар',
 
 # History merging
+'mergehistory' => 'Нисдарин истори цхьаьнатохар',
+'mergehistory-box' => 'Шин агӀона нисдарин истори цхьаьнатохар:',
 'mergehistory-from' => 'Дуьххьарлера агӀоно',
+'mergehistory-into' => 'Ӏалашонан агӀо:',
+'mergehistory-list' => 'Цхьаьнатухуш долу нисдарин истори',
+'mergehistory-go' => 'Гайта цхьаьнатухуш долу нисдарш',
+'mergehistory-submit' => 'Цхьаьнатоха нисдарш',
+'mergehistory-empty' => 'Цхьаьнатоха нисдарш цакарий.',
 'mergehistory-fail' => 'АгӀонийн истореш вовшахтоха цаделира, дехар до агӀона параметаршка а хене а хьажа.',
 'mergehistory-invalid-source' => 'Хьостан нийса корта хила еза.',
 'mergehistory-invalid-destination' => 'Юзийна агӀона нийса корта хила еза.',
@@ -1251,7 +1289,7 @@ $1",
 И хаам массарна гуш хир бу.',
 'email' => 'Email',
 'prefs-help-email' => 'Электрони почтан адрес цахlоттийча аъ хlумма дац, амма иза оьшар ю, нагахь хьуна хьай пароль йицлахь.',
-'prefs-help-email-others' => 'Ð\9aÑ\85ин Ð´Ó\80а Ñ\86о ÐºÑ\85еÑ\87Ñ\83 Ð´ÐµÐºÑ\8aаÑ\88Ñ\85оÑ\88на Ð¹Ð¸Ñ\88 Ñ\85Ñ\83Ñ\8cлÑ\83Ñ\8cйÑ\82Ñ\83 Ñ\85Ñ\8cога Ñ\8dлекÑ\82Ñ\80онни ÐºÐµÑ\85аÑ\82 Ð´Ð°Ð¸Ð¹Ñ\82а Ñ\85Ñ\8cан Ð°Ð³Ó\80она Ñ\87оÑ\85Ñ\8c Ð¹Ð¾Ð»Ñ\83 Ñ\85Ñ\8cажоÑ\80иган Ð³Ó\80онца.',
+'prefs-help-email-others' => 'Ð\9aÑ\85ин Ð´Ó\80а Ñ\86о ÐºÑ\85еÑ\87Ñ\83 Ð´ÐµÐºÑ\8aаÑ\88Ñ\85оÑ\88на Ð¹Ð¸Ñ\88 Ñ\85Ñ\83Ñ\8cлÑ\83Ñ\8cйÑ\82Ñ\83 Ñ\85Ñ\8cога Ñ\8dлекÑ\82Ñ\80онан ÐºÐµÑ\85аÑ\82 Ð´Ð°Ð¸Ð¹Ñ\82а Ñ\85Ñ\8cан Ð°Ð³Ó\80она Ñ\87оÑ\85Ñ\8c Ð¹Ð¾Ð»Ñ\83 Ñ\85Ñ\8cажоÑ\80иган Ð³Ó\80оÑ\8cнца.',
 'prefs-info' => 'Коьрта хаам',
 'prefs-i18n' => 'Юкъардекъа мотт',
 'prefs-signature' => 'КуьгтаӀор',
@@ -2624,7 +2662,7 @@ MediaWiki яржош ю и шуна пайдане хир яц те аьлла,
 'dberr-problems' => 'Бехк ма бил! Хlинц машан меттиган хилла гlирсаца халонаш.',
 'dberr-again' => 'Хьажа карла йаккха агlо массех минот йаьлча.',
 'dberr-info' => '(аьтто ца хили зlе хlотта гlулкхдечуьнца бухара хаамашца: $1)',
-'dberr-usegoogle' => 'ЦӀачун хьо хьажа лаха гӀонца Google.',
+'dberr-usegoogle' => 'ЦӀачун хьо хьажа лаха гӀоьнца Google.',
 'dberr-outofdate' => 'Хьуна хаалахь, цуьна йолу меттиг хила мега тишйелла черахь.',
 
 # HTML forms
index bfac832..96bb2fa 100644 (file)
@@ -972,7 +972,9 @@ Cafodd yr argiau hyn eu hepgor.",
 'cantcreateaccount-text' => "Rhwystrwyd y gallu i greu cyfrif ar gyfer y cyfeiriad IP hwn, ('''$1'''), gan [[User:$3|$3]].
 
 Y rheswm a roddwyd dros y bloc gan $3 yw ''$2''.",
-'cantcreateaccount-range-text' => "Gosododd [[User:$3|$3]] floc ar agor cyfrifon o gyfeiriadau IP yn yr ystod '''$1''', sy'n cynnwys eich cyfeiriad IP chi ('''$4''').",
+'cantcreateaccount-range-text' => "Gosododd [[User:\$3|\$3]] floc ar agor cyfrifon o gyfeiriadau IP yn yr ystod '''\$1''', sy'n cynnwys eich cyfeiriad IP chi ('''\$4''').
+
+Y rheswm a roddwyd gan \$3 yw \"\$2\"",
 
 # History pages
 'viewpagelogs' => "Dangos logiau'r dudalen hon",
@@ -2275,6 +2277,7 @@ Gwelwch y $2 am gofnod o\'r dileuon diweddar.',
 Cyfyngwyd ar y gallu i ddileu tudalennau sydd wedi eu golygu cymaint â hyn, er mwyn osgoi amharu ar weithrediad databas {{SITENAME}} yn ddamweiniol.",
 'delete-warning-toobig' => "Cafwyd dros $1 {{PLURAL:$1|o olygiadau}} i'r dudalen hon.
 Gallai dileu tudalen, gyda hanes golygu cymaint â hyn iddi, beri dryswch i weithrediadau'r databas ar {{SITENAME}}; ewch ati'n ofalus.",
+'deleting-backlinks-warning' => "'''Rhybudd:''' Mae tudalennau eraill yn cysylltu i'r dudalen yr ydych ar fin ei dileu.",
 
 # Rollback
 'rollback' => 'Gwrthdroi golygiadau',
index 8ac8ff4..b8b8202 100644 (file)
@@ -559,9 +559,9 @@ Den kan være blevet slettet af en anden.',
 'delete-hook-aborted' => 'Sletningen blev afbrudt af en programfunktion.
 Der var ikke nogen forklaring.',
 'no-null-revision' => 'Kunne ikke oprette nye tom revision for side "$1"',
-'badtitle' => 'Forkert titel',
-'badtitletext' => 'Den ønskede sides titel var ikke tilladt, tom eller siden er forkert henvist fra en {{SITENAME}} på et andet sprog.
-Den kan indeholde et eller flere tegn, som ikke kan anvendes i titler.',
+'badtitle' => 'Ugyldig titel',
+'badtitletext' => 'Den ønskede sides titel var ikke tilladt, tom eller siden er forkert henvist fra {{SITENAME}} på et andet sprog.
+Den kan indeholde et eller flere tegn, som ikke  anvendes i titler.',
 'perfcached' => 'Følgende data er gemt i cachen, der muligvis ikke er helt opdateret. Der gemmes højst {{PLURAL:$1|ét resultat|$1 resultater}} i cachen.',
 'perfcachedts' => 'Disse data stammer fra cachen, som senest blev opdateret $1. Der gemmes højst {{PLURAL:$4|ét resultat|$4 resultater}} i cachen.',
 'querypage-no-updates' => "'''Opdateringer til denne side er deaktiveret for øjeblikket. Dataene bliver indtil videre ikke fornyet.'''",
@@ -853,7 +853,7 @@ Du bør gøre det, hvis du ved et uheld deler dem med nogen, eller hvis din kont
 'missingcommentheader' => "'''Bemærk:''' Du har ikke angivet en overskrift/emne for denne kommentar. Hvis du trykker \"{{int:savearticle}}\" én gang til, gemmes dine ændringer uden overskrift/emne.",
 'summary-preview' => 'Forhåndsvisning af beskrivelsen:',
 'subject-preview' => 'Forhåndsvisning af emnet:',
-'blockedtitle' => 'Brugeren er blokeret',
+'blockedtitle' => 'Du eller din IP-adresse er blokeret',
 'blockedtext' => "'''Dit brugernavn eller din IP-adresse er blevet blokeret.'''
 
 Blokeringen er foretaget af $1.
@@ -1347,7 +1347,7 @@ Hvis andre kender den, man vil være i stand til at læse din overvågningsliste
 'timezoneregion-europe' => 'Europa',
 'timezoneregion-indian' => 'Indiske Ocean',
 'timezoneregion-pacific' => 'Stillehavet',
-'allowemail' => 'Tillad e-mails fra andre brugere',
+'allowemail' => 'Tillad e-mail fra andre brugere',
 'prefs-searchoptions' => 'Søg',
 'prefs-namespaces' => 'Navnerum',
 'defaultns' => 'Ellers søg i disse navnerum:',
@@ -2036,7 +2036,7 @@ Hver linje indeholder henvisninger til den første og den anden omdirigering, s
 
 'brokenredirects' => 'Defekte omdirigeringer',
 'brokenredirectstext' => 'Følgende omdirigeringer peger på en side der ikke eksisterer:',
-'brokenredirects-edit' => 'rediger',
+'brokenredirects-edit' => 'redigér',
 'brokenredirects-delete' => 'slet',
 
 'withoutinterwiki' => 'Sider uden henvisninger til andre sprog',
@@ -2619,7 +2619,7 @@ Se [[Special:BlockList|blokeringslisten]] for alle blokeringer.',
 'blocklist-target' => 'Mål',
 'blocklist-expiry' => 'Udløber',
 'blocklist-by' => 'Blokerende administrator',
-'blocklist-params' => 'Block parametre',
+'blocklist-params' => 'Parametre for blokeringen',
 'blocklist-reason' => 'Årsag',
 'ipblocklist-submit' => 'Søg',
 'ipblocklist-localblock' => 'Lokal blokering',
@@ -2627,7 +2627,7 @@ Se [[Special:BlockList|blokeringslisten]] for alle blokeringer.',
 'infiniteblock' => 'udløber ikke',
 'expiringblock' => 'udløber $1 $2',
 'anononlyblock' => 'kun anonyme',
-'noautoblockblock' => 'Autoblok deaktiveret',
+'noautoblockblock' => 'automatisk blokering slået fra',
 'createaccountblock' => 'Oprettelse af brugerkonti spærret',
 'emailblock' => 'e-mail blokeret',
 'blocklist-nousertalk' => 'kan ikke redigere egen diskussionsside',
@@ -2653,10 +2653,10 @@ Se [[Special:BlockList|blokeringslisten]] for den nuværende liste med aktuelle
 'unblocklogentry' => 'ophævede blokering af "$1"',
 'block-log-flags-anononly' => 'kun anonyme',
 'block-log-flags-nocreate' => 'Oprettelse af brugerkonti blokeret',
-'block-log-flags-noautoblock' => 'Autoblok deaktiveret',
+'block-log-flags-noautoblock' => 'automatisk blokering slået fra',
 'block-log-flags-noemail' => 'e-mail blokeret',
 'block-log-flags-nousertalk' => 'kan ikke redigere egen diskussionsside',
-'block-log-flags-angry-autoblock' => 'udvidet automatisk blokering slået tilenhanced autoblock enabled',
+'block-log-flags-angry-autoblock' => 'udvidet automatisk blokering slået til',
 'block-log-flags-hiddenname' => 'brugernavnet er skjult',
 'range_block_disabled' => 'Sysop-muligheden for at oprette blokeringsklasser er slået fra.',
 'ipb_expiry_invalid' => 'Udløbstiden er ugyldig.',
@@ -2741,7 +2741,7 @@ I disse tilfælde er du nødt til at flytte eller sammenflette siden manuelt.",
 'movepage-moved' => 'Siden \'\'\'"$1" er flyttet til "$2"\'\'\'',
 'movepage-moved-redirect' => 'En omdirigering er oprettet.',
 'movepage-moved-noredirect' => 'Der oprettedes ikke en omdirigering.',
-'articleexists' => 'En side med det navn eksisterer allerede, eller det
+'articleexists' => 'En side med dette navn eksisterer allerede, eller det
 navn du har valgt er ikke gyldigt. Vælg et andet navn.',
 'cantmove-titleprotected' => 'Du kan ikke omdøbe en side til dette navn. Det nye navn er beskyttet mod oprettelse.',
 'movetalk' => 'Flyt også "diskussionssiden", hvis den eksisterer.',
@@ -2834,7 +2834,7 @@ $2',
 'djvu_no_xml' => 'XML-data kan ikke hentes til DjVu-filen',
 'thumbnail-temp-create' => 'Kunne ikke oprette midlertidig miniaturefil',
 'thumbnail-dest-create' => 'Kunne ikke gemme miniaturebillede til destinationen',
-'thumbnail_invalid_params' => 'Ugyldige thumbnail-parametre',
+'thumbnail_invalid_params' => 'Ugyldige parametre for miniaturebillede',
 'thumbnail_dest_directory' => 'Kataloget kan ikke oprettes.',
 'thumbnail_image-type' => 'Billedtypen understøttes ikke',
 'thumbnail_gd-library' => 'Ufuldstændig konfiguration af GD-biblioteket: funktionen $1 mangler',
index 312d7d4..7e98132 100644 (file)
@@ -2328,6 +2328,7 @@ Jede Zeile enthält Links zur ersten und zweiten Weiterleitung sowie dem Ziel de
 'protectedpages' => 'Geschützte Seiten',
 'protectedpages-indef' => 'Nur unbeschränkt geschützte Seiten zeigen',
 'protectedpages-cascade' => 'Nur Seiten mit Kaskadenschutz',
+'protectedpages-noredirect' => 'Weiterleitungen ausblenden',
 'protectedpagesempty' => 'Aktuell sind keine Seiten mit diesen Parametern geschützt.',
 'protectedtitles' => 'Geschützte Seitennamen',
 'protectedtitlesempty' => 'Zurzeit sind mit den angegebenen Parametern keine Seiten zur Neuerstellung gesperrt.',
index 9039dc3..7eba4b8 100644 (file)
@@ -786,9 +786,9 @@ Wexta ke verhafızayê cıgerayoxê şıma pak beno no benate de taye peli de he
 'gotaccount' => "Hesabê şıma esto? '''$1'''.",
 'gotaccountlink' => 'Dekewtış',
 'userlogin-resetlink' => 'Melumatê cıkewtışi xo vira kerdê?',
-'userlogin-resetpassword-link' => 'Şıma parola ke ğo vira?',
+'userlogin-resetpassword-link' => 'Parola xo kerda xo vira?',
 'helplogin-url' => 'Help:Qeydbiyayış',
-'userlogin-helplink' => '[[{{MediaWiki:helplogin-url}}|Desteg be qeydbiyayış ra]]',
+'userlogin-helplink' => '[[{{MediaWiki:helplogin-url}}|Peşti be qeydbiyayış ra]]',
 'userlogin-loggedin' => 'Tı xora namey {{GENDER:$1|$1}} ra kewtê/kewtay cı.
 Formê cêrêni bıgureyne ke namey karberio bin ra cı kewê.',
 'userlogin-createanother' => 'Zewbi hesab vıraz',
index dabb137..e895fa2 100644 (file)
@@ -224,7 +224,7 @@ $messages = array(
 'nstab-image' => "'File'",
 'nstab-mediawiki' => 'Mesâg',
 'nstab-template' => 'Mudèl',
-'nstab-help' => 'Ajót',
+'nstab-help' => 'Per quî rivê da pôch',
 'nstab-category' => 'Categoréia',
 
 # General errors
@@ -302,6 +302,7 @@ $messages = array(
 'anoneditwarning' => "'''Atensiòun:''' Ingrès mìa fât. Al tó indirés IP al srà sgnê int la stòria ed cla pàgina chè.",
 'blockedtitle' => 'Utèint bluchê',
 'newarticle' => '(Nōv)',
+'newarticletext' => "Al colegamèint apèina fât al cumbîna cun 'na pàgina ch' an n'é mìa incòra stêda fâta. S'ét vō fêr la pàgina adès, l'é asê cumincêr a scréver al tèst int la caşèla ché sòt (per vedèr infurmasiòun pió precîşi guêrda la [[{{MediaWiki:Helppage}}|pàgina 'd ajót]]). Se al colegamèint  l'é stê avêrt per erōr, l'é asê clichêr al pulsânt \"Indrē\" dal tó navigadōr.",
 'noarticletext' => 'In cól mumèint ché la pàgina serchêda l\'é vōda. L\'é pusébil [[Special:Search/{{PAGENAME}}|serchêr sté tétol]] int al j êtri pàgini dal sît, <span class="plainlinks">[{{fullurl:{{#Special:Log}}|page={{FULLPAGENAMEE}}}} serchêr int i regéster coleghê] opór  [{{fullurl:{{FULLPAGENAME}}|action=edit}} mudifichêr la pàgina adèsa]</span>.',
 'noarticletext-nopermission' => "In cól mumèint ché la pàgina serchêda l'é vōda. L'é pusébil [[Special:Search/{{PAGENAME}}|serchêr sté tétol]] int al j êtri pàgini dal sît o<span class=\"plainlinks\">[{{fullurl:{{#Special:Log}}|page={{FULLPAGENAMEE}}}} serchêr int i regéster coleghê] <span>, mó an 't gh'ê mìa al permès ed fêr cla pàgina ché.",
 'note' => "'''Nôta:'''",
@@ -605,6 +606,7 @@ $messages = array(
 'whatlinkshere-page' => 'Pàgina:',
 'isimage' => "Colegamèint vêrs al 'file'",
 'whatlinkshere-links' => '← colegamèint',
+'whatlinkshere-hideredirs' => '$1redirect',
 'whatlinkshere-hidetrans' => '$1 uniòun',
 'whatlinkshere-hidelinks' => '$1 colegamèint',
 'whatlinkshere-filters' => 'Fîlter',
@@ -686,7 +688,7 @@ $messages = array(
 'tooltip-t-upload' => "Cârga un 'file'",
 'tooltip-t-specialpages' => 'Elèinch ed tót al pàgini specêli',
 'tooltip-t-print' => 'Per stampêr cla pàgina ché.',
-'tooltip-t-permalink' => "Colegamèint fés a cla rervişiòun ché 'd  la pàgina.",
+'tooltip-t-permalink' => "Colegamèint fés a cla revişiòun ché 'd  la pàgina.",
 'tooltip-ca-nstab-main' => 'Guêrda la pàgina',
 'tooltip-ca-nstab-user' => 'Guêrda la pàgina utèint',
 'tooltip-ca-nstab-project' => 'Guêrda la pàgina dal prugèt',
@@ -718,6 +720,7 @@ $messages = array(
 
 # Media information
 'file-info-size' => '$1 × $2 pixel, amzûra dal file:$3, gèner MIME: $4',
+'file-nohires' => "An gh'é mìa la manēra ed vèder pió cêr de csé.",
 'show-big-image' => 'File uriginêl',
 'file-info-gif-looped' => 'A ripetisiòun',
 'file-info-png-looped' => 'A ripetisiòun',
@@ -739,6 +742,20 @@ a vînen cunsidrê sōl j elèinch puntê (ríghi che cumîncen cun al carâter
 # Metadata
 'metadata' => 'Metadati',
 'metadata-help' => "In cól file ché agh'é dal j infurmasiòun zuntêdi, prubabilmèint zuntêdi da la mâchina fotogrâfica o dal scàner druvê per fotografêrel o per fêrel dvintêr digitêl. Se al file l'é stê mudfifichê, soquânt particulêr a prén cumbinêr mìa cun la realtê.",
+'metadata-fields' => "I câmp relatîv a i metadati ed la figûra, in lésta in cól mesâg ché, a gnirân més int la pàgina ed la figûra quând la tabèla di metadati l'é mustrêda int la fōrma cûrta. Per impustasiòun pre-stabilîda, chiêter câmp a gnirân lughê. 
+* make 
+* model 
+* datetimeoriginal 
+* exposuretime 
+* fnumber 
+* isospeedratings 
+* focallength 
+* artist 
+* copyright 
+* imagedescription 
+* gpslatitude 
+* gpslongitude 
+* gpsaltitude",
 
 # Exif tags
 'exif-exposuretime-format' => '$1 s ($2)',
index 344e234..30c41e5 100644 (file)
@@ -1233,6 +1233,7 @@ No email will be sent for any of the following features.',
 Please enter a well-formatted address or empty that field.',
 'cannotchangeemail'               => 'Account email addresses cannot be changed on this wiki.',
 'emaildisabled'                   => 'This site cannot send emails.',
+'emailsender'                     => '{{SITENAME}}', # do not translate or duplicate this message to other languages
 'accountcreated'                  => 'Account created',
 'accountcreatedtext'              => 'The user account for [[{{ns:User}}:$1|$1]] ([[{{ns:User talk}}:$1|talk]]) has been created.',
 'createaccount-title'             => 'Account creation for {{SITENAME}}',
@@ -2752,6 +2753,7 @@ It now redirects to [[$2]].',
 'protectedpages-indef'            => 'Indefinite protections only',
 'protectedpages-summary'          => '', # do not translate or duplicate this message to other languages
 'protectedpages-cascade'          => 'Cascading protections only',
+'protectedpages-noredirect'       => 'Hide redirects',
 'protectedpagesempty'             => 'No pages are currently protected with these parameters.',
 'protectedtitles'                 => 'Protected titles',
 'protectedtitles-summary'         => '', # do not translate or duplicate this message to other languages
@@ -5081,6 +5083,7 @@ Otherwise, you can use the easy form below. Your comment will be added to the pa
 'api-error-unknownerror'                  => 'Unknown error: "$1".',
 'api-error-uploaddisabled'                => 'Uploading is disabled on this wiki.',
 'api-error-verification-error'            => 'This file might be corrupt, or have the wrong extension.',
+'api-error-stasherror'                    => 'There was an error while uploading the file to stash.',
 
 # Durations
 'duration-seconds'   => '$1 {{PLURAL:$1|second|seconds}}',
index 2001a39..2ea4b66 100644 (file)
@@ -1399,8 +1399,8 @@ Vérifiez les journaux.",
 'revdelete-offender' => 'Auteur de la révision :',
 
 # Suppression log
-'suppressionlog' => 'Journal des suppressions',
-'suppressionlogtext' => 'Voici la liste des suppressions et des blocages qui portent sur du contenu caché aux administrateurs.
+'suppressionlog' => 'Journal des masquages',
+'suppressionlogtext' => 'Voici la liste des masquages et des blocages qui portent sur du contenu caché aux administrateurs.
 Voir la [[Special:BlockList|liste des blocages]] pour la liste des bannissements et des blocages actuellement opérationnels.',
 
 # History merging
index 1d35baa..7d87020 100644 (file)
@@ -376,7 +376,7 @@ $messages = array(
 'tog-showtoolbar' => 'הצגת סרגל העריכה',
 'tog-editondblclick' => 'עריכת דפים בלחיצה כפולה',
 'tog-editsection' => 'עריכת פסקאות באמצעות קישורי [עריכה]',
-'tog-editsectiononrightclick' => 'ער×\99×\9bת ×¤×¡×§×\90×\95ת ×¢×\9c ×\99×\93×\99 לחיצה ימנית על כותרות הפסקאות',
+'tog-editsectiononrightclick' => 'ער×\99×\9bת ×¤×¡×§×\90×\95ת ×\91×\90×\9eצע×\95ת לחיצה ימנית על כותרות הפסקאות',
 'tog-showtoc' => 'הצגת תוכן עניינים (עבור דפים עם יותר מ־3 כותרות)',
 'tog-rememberpassword' => 'שמירת הכניסה שלי בדפדפן זה ({{PLURAL:$1|ליום אחד|ליומיים|ל־$1 ימים}} לכל היותר)',
 'tog-watchcreations' => 'מעקב אחרי דפים שיצרתי וקבצים שהעליתי',
@@ -1532,7 +1532,7 @@ $1",
 'timezonelegend' => 'אזור זמן:',
 'localtime' => 'זמן מקומי:',
 'timezoneuseserverdefault' => 'ברירת המחדל של האתר ($1)',
-'timezoneuseoffset' => '×\90×\97ר (× ×\90 ×¦×\99×\99× ×\95 את ההפרש)',
+'timezoneuseoffset' => '×\90×\97ר (×\99ש ×\9cצ×\99×\99×\9f את ההפרש)',
 'servertime' => 'השעה הנוכחית בשרת:',
 'guesstimezone' => 'קבלה מהדפדפן',
 'timezoneregion-africa' => 'אפריקה',
@@ -2856,8 +2856,10 @@ $1',
 'autoblocker' => 'נחסמתם באופן אוטומטי משום שאתם חולקים את כתובת ה־IP שלכם עם [[User:$1|$1]].
 הסיבה שניתנה לחסימת $1 היא "\'\'\'$2\'\'\'"',
 'blocklogpage' => 'יומן חסימות',
-'blocklog-showlog' => 'משתמש זה נחסם בעבר. יומן החסימות מוצג למטה:',
-'blocklog-showsuppresslog' => 'משתמש זה נחסם והוסתר בעבר. יומן ההסתרות מוצג למטה:',
+'blocklog-showlog' => 'משתמש זה נחסם בעבר.
+יומן החסימות מוצג להלן:',
+'blocklog-showsuppresslog' => 'משתמש זה נחסם והוסתר בעבר.
+יומן ההסתרות מוצג להלן:',
 'blocklogentry' => 'חסם את [[$1]] למשך $2 $3',
 'reblock-logentry' => 'שינה את הגדרות החסימה של [[$1]] עם זמן פקיעה של $2 $3',
 'blocklogtext' => 'זהו יומן פעולות החסימה והשחרור של משתמשים.
index 9c26841..e168fcf 100644 (file)
@@ -944,7 +944,7 @@ Dovresti farlo se le hai accidentalmente condivise con qualcuno o se la tua uten
 'preview' => 'Anteprima',
 'showpreview' => 'Visualizza anteprima',
 'showlivepreview' => "Funzione ''Live preview''",
-'showdiff' => 'Mostra cambiamenti',
+'showdiff' => 'Mostra modifiche',
 'anoneditwarning' => "'''Attenzione:''' Accesso non effettuato. Nella cronologia della pagina verrà registrato il tuo indirizzo IP.",
 'anonpreviewwarning' => "''Non è stato eseguito il login. Salvando la pagina, il proprio indirizzo IP sarà registrato nella cronologia.''",
 'missingsummary' => "'''Attenzione:''' non è stato specificato l'oggetto di questa modifica. Premendo di nuovo \"{{int:savearticle}}\" la modifica verrà salvata con l'oggetto vuoto.",
@@ -2440,6 +2440,7 @@ Consultare il log delle $2 per un elenco delle pagine cancellate di recente.',
 'delete-edit-reasonlist' => 'Modifica i motivi di cancellazione',
 'delete-toobig' => 'La cronologia di questa pagina è molto lunga (oltre $1 {{PLURAL:$1|revisione|revisioni}}). La sua cancellazione è stata limitata per evitare di creare accidentalmente dei problemi di funzionamento al database di {{SITENAME}}.',
 'delete-warning-toobig' => 'La cronologia di questa pagina è molto lunga (oltre $1 {{PLURAL:$1|revisione|revisioni}}). La sua cancellazione può creare dei problemi di funzionamento al database di {{SITENAME}}; procedere con cautela.',
+'deleting-backlinks-warning' => "'''Attenzione:''' altre pagine contengono collegamenti alla pagina che stai per cancellare.",
 
 # Rollback
 'rollback' => 'Annulla le modifiche',
index 3ebb231..2e6a7c2 100644 (file)
@@ -1798,7 +1798,7 @@ HTML 태그를 확인하세요.',
 'recentchanges-label-unpatrolled' => '아직 검토하지 않은 편집',
 'recentchanges-label-plusminus' => '바이트로 표기된 바뀐 문서 크기',
 'recentchanges-legend-heading' => "'''범례:'''",
-'recentchanges-legend-newpage' => '([[Special:NewPages|새 문서 목록]]도 참고하세요)',
+'recentchanges-legend-newpage' => '([[Special:NewPages|새 문서 목록]]도 세요)',
 'recentchanges-legend-plusminus' => "(''±123'')",
 'rcnotefrom' => "다음은 '''$2'''에서부터 바뀐 문서 '''$1'''개입니다.",
 'rclistfrom' => '$1 이래로 새로 바뀐 문서 보기',
index 2ff6b71..17f006f 100644 (file)
@@ -7,6 +7,7 @@
  * @ingroup Language
  * @file
  *
+ * @author Bonevarluri
  * @author Mogoeilor
  */
 
@@ -35,14 +36,26 @@ $messages = array(
 'tog-minordefault' => 'همه ویرایشتیا کؤچک نه وا پیش فرض بیئن نشو دار کو.',
 'tog-previewontop' => 'پیش سیل نه دما جعوه ویرایشت نشو بیئه',
 'tog-previewonfirst' => 'پیش سیل نه د اولین ویرایشت نشو بیئه',
+'tog-enotifwatchlistpages' => 'اوسه که یه گل بلگه یا فایلی د سیل برگ مه آلشت بوئه منه وا ایمیل خور کو',
 'tog-enotifusertalkpages' => 'وختی که بلگه گپسن کارور آلشت پیدا کرد منه وا ایمیل خور کو',
+'tog-enotifminoredits' => 'همچنو اوسه که ویرایشتیا کؤچکی د بلگیا یا فایلیا انجوم بوئه منه خور کو',
+'tog-enotifrevealaddr' => 'نشونی ایمیل منه د ایمیل اشگار نشو بیه',
 'tog-shownumberswatching' => 'انازه کاروریایی که د حالت دیئنن نشو بیه',
 'tog-oldsig' => 'امضايی هيئش:',
+'tog-fancysig' => 'وا امضا چی ویکی متن برخورد کو',
 'tog-uselivepreview' => 'د پیش سیل زنه استفاده کو',
+'tog-forceeditsummary' => 'منه وختی که یه گل چکسه ویرایشت حالی وارد بوئه سریع خور کو',
 'tog-watchlisthideown' => 'قام كو ويرايشت منه د',
+'tog-watchlisthidebots' => 'ویرایشت یا بوت نه د سیل برگ قام کو',
 'tog-watchlisthideminor' => 'قام كو ويرايشت کؤچک منه د',
+'tog-watchlisthideliu' => 'ویرایشت یا کاروریا وامئن سیستم نه د سیل برگ قام کو',
+'tog-watchlisthideanons' => 'ویرایشت یا کاروریا ناشناس نه د سیل برگ قام کو',
+'tog-watchlisthidepatrolled' => 'ویرایش تیا د تی رس نه د سیل برگ قام کو',
+'tog-ccmeonemails' => 'کپی ایمیل یا منه که سی کسونا تر می فرسنم سیم کل کو',
 'tog-diffonly' => 'بلگیایی که شومل فرخیا هارن نشون نیه',
 'tog-showhiddencats' => 'دسه يا قام بيئنه نشون بيه',
+'tog-useeditwarning' => 'وختی که آلشتیا ذخیره نبیه د بلگه ویرایشت وه جا می نم خورم کو',
+'tog-prefershttps' => 'همیشه وختی که مه وامئن هئم د ارتواط امن استفاده کو',
 
 'underline-always' => 'هميشه',
 'underline-never' => 'هيژوخت',
@@ -127,7 +140,8 @@ $messages = array(
 'category-empty' => 'ای دسه واقعن شومل هیژ بلگه ای یا رسانه ای نی',
 'hidden-categories' => '{{PLURAL:$1|دسته قام بيه|دسته يا قام بيه}}',
 'hidden-category-category' => 'دسه یا قام بیه',
-'category-subcat-count' => '{{جمی:$2|ای دسه شومل بلگه نهاییه .| {{جمی:$1| بلگه هئ|$1 بلگیا هئن}} د ای زیردسه, خارج د $2 کل.}}',
+'category-subcat-count' => '{{جمی:$2|ای دسه فقط زیر دسه دینداگر هان دش .|ای دسه {{جمی:$1| زیردسه|$1 زیردسه یا}}هئ , خارج د $2 کل.}}',
+'category-subcat-count-limited' => 'ای دسه وا دمال {{جمی:$1|زیردسه|$1زیردسه یا}} بوئه',
 'category-article-count' => '{{جمی:$2|ای دسه شومل بلگه نهاییه .| {{جمی:$1| بلگه هئ|$1 بلگیا هئن}} د ای دسه, خارج د $2 کل.}}',
 'listingcontinuesabbrev' => 'دماله',
 'index-category' => 'بلگيا سيائه دار',
@@ -227,6 +241,8 @@ $messages = array(
 'jumpto' => 'پئرستن د',
 'jumptonavigation' => 'ناوگشتن',
 'jumptosearch' => 'پی جوری',
+'pool-timeout' => 'وخت سی تیه وه ره منن سی قلف بیئن تموم بی',
+'pool-queuefull' => 'ذخیره گی گرتن پر بیه',
 'pool-errorunknown' => 'خطا ناشناس',
 
 # All link text and link target definitions of links into project namespace that get used by other message strings, with the exception of user group pages (see grouppage).
@@ -249,15 +265,20 @@ $messages = array(
 
 'badaccess' => 'خطا :اجازه بئیر',
 'badaccess-group0' => 'شما اجازه انجوم کاری که حاستیت نارین',
+'badaccess-groups' => 'ای کاری که شما هاستیته سی کاروریا د  {{جمی:$2|گرو|یکی د گرویا}}: $1 مئدود بیه',
 
 'versionrequired' => 'یه نسقه د نیازمنیا ویکی رسانه
 $1',
+'versionrequiredtext' => 'نسقه $1 ویکی مدیا سی استفاده د ای بلگه لازم هئی .
+وه نه بوینیت [[ویجه:نسقه|نسقه بلگه]].',
 
 'ok' => 'خوئه',
 'retrievedfrom' => 'بازيافته د"$1"',
 'youhavenewmessages' => 'شما داريت $1($2)',
+'youhavenewmessagesfromusers' => '{{جمی:$4|شما }} $1 د {{جمی:$3|کارور هنی|$3 کاروریا}}داریتو($2).',
 'youhavenewmessagesmanyusers' => 'شما $1 د خيلی كاروريا داريت ($2).',
-'newmessagesdifflinkplural' => 'آخر {{PLURAL:$1|change|changes}}',
+'newmessageslinkplural' => '{{جمی:$1|یه گل پیغوم تازه|999=پیغوم ئل تازه}}',
+'newmessagesdifflinkplural' => 'آخر {{جمی:$1|آلشت|آلشتیا}}',
 'youhavenewmessagesmulti' => 'شما یه گل پیغوم تازه د $1 داریتو',
 'editsection' => 'ويرايشت',
 'editold' => 'ويرايشت',
@@ -272,6 +293,7 @@ $1',
 'collapsible-expand' => 'وا كردن',
 'thisisdeleted' => 'دیئن یا ورگنين $1?',
 'viewdeleted' => 'دیئن$1?',
+'restorelink' => '{{جمی:$1|یه گل ویرایشت پاک بیه|$1 ویرایشتیا پاک بیه}}',
 'feedlinks' => 'غذا دهنه:',
 'feed-invalid' => 'نوع مشترک بین خورحو نامعتور',
 'site-rss-feed' => 'خورخو RSS سی $1',
@@ -308,32 +330,41 @@ $1',
 'databaseerror-error' => 'خطا: $1',
 'laggedslavemode' => 'زنهار:بلگه شايت شومل روزامديا تازه باو نبوئه',
 'readonly' => 'جاگه دونسمنيا بسه بيه',
+'enterlockreason' => 'دلیل قلف کردن نه بنیست،یه وختی سی وا کردن قلف د ویر داشتویت.',
 'missing-article' => 'پاگا داده نتونه بلگه ای با پیدا بکه بجوره.که نومش $1 و $2 هئ.
 معمولند یه سی یه که فرخ ویرگار رئته دش بیه پاک بیه.',
 'missingarticle-rev' => '(دوواره ديئن#: $1)',
 'missingarticle-diff' => '(فرخ: $1، $2)',
 'internalerror' => 'خطا داخلی',
 'internalerror_info' => 'خطا داخلی:$1',
+'fileappenderrorread' => 'نبوئه $1 نه اوسه که پیوست بوئه بحونیت.',
+'fileappenderror' => 'نبوئه فایل $1 د $2 پیوست بوئه',
 'filecopyerror' => 'نبوئه فایل $1 د $2 کپی بوئه',
 'filerenameerror' => 'نبوئه فایل $1 د $2 نوم آلشت بوئه',
 'filedeleteerror' => 'نبوئه فایل $1 پاک بوئه',
+'directorycreateerror' => 'نبوئه سردسه $1 راس بوئه.',
 'filenotfound' => 'نتونیت فایل $1 پیدا بکید',
+'fileexistserror' => 'نبوئه د فایل "$1" بنیسید:فایل هئیش',
+'unexpected' => 'ارزایشت ناحاسته: "$1"="$2".',
 'formerror' => 'خطا:نبوئه فرم وه مو بئيت',
+'badarticleerror' => 'ای انجوم دئنی د ای بلگه انجوم نگره.',
 'cannotdelete-title' => 'نبوئه بلگه $1 حذف بو',
 'badtitle' => 'موضو گن',
 'badtitletext' => 'عنوان بلگه حاسته بیه معتور نی،یا  یه گل مئن زونی یا مئن ویکی عنوان غلطه.
 یه شایت شومل یکی با یا بیشتر کاراکتریا نبوئه سی ای موضوعیا استفاده بوئن',
 'viewsource' => 'سرچشمه نه بوينيت',
 'viewsource-title' => 'سرچشمه $1 بوينيت',
+'actionthrottled' => 'عمل جلوگئری بیه',
 'mycustomcssprotected' => 'شما حق ناریت ای بلگه سی اس اس نه ویرایشت بکید',
 'mycustomjsprotected' => 'شما حق ناریت ای بلگه جاوا اسکریپت نه ویرایشت بکید',
 'myprivateinfoprotected' => 'شما حق ناریت دونسمنیا خصوصی نه ویرایشت بکید',
 'mypreferencesprotected' => 'شما حق ناریت ویجگی یا هنی تونه ویرایشت بکید',
 'ns-specialprotected' => 'بلگیا ویجه نتونن ویرایشت بوئن',
 'exception-nologin' => 'نبوئه وارد بوئيد',
+'exception-nologin-text-manual' => 'خواهشمنیدم که $1 تونسه بوئه د ای بلگه دسرسی داشتوه یا کاری انجوم بیئه.',
 
 # Virus scanner
-'virus-scanfailed' => 'زل گشتن شکست حرد',
+'virus-scanfailed' => 'زل بیئن شکست حرد($1)',
 'virus-unknownscanner' => 'ويروس كش ناآشگار',
 
 # Login and logout pages
@@ -370,8 +401,9 @@ $1',
 'gotaccount' => 'ایسنی حساو کاروری داریتو؟$1',
 'gotaccountlink' => 'اومائن',
 'userlogin-resetlink' => 'جزییات وامین اومائن تونه د ویر بردیته',
-'userlogin-resetpassword-link' => 'Ù\87Ù\86Û\8c Ø±Ù\85ز Ù\88ارد Ø¨Ù\83Ù\8aد',
+'userlogin-resetpassword-link' => 'پاسÙ\88رد Ø¯ Ù\88Û\8cرتÙ\88 Ø±Ø¦ØªÙ\87Ø\9f',
 'helplogin-url' => 'هومياری:د حالت اومائن د سيستم',
+'userlogin-helplink' => '[[{{مدیاویکی:هومیاری وامئن اومائن-یو آر ال}}|هومیاری وا مئن اومائن]]',
 'userlogin-createanother' => 'يه گل حساوهنی راست بكيد',
 'createacct-join' => 'دونسمنيا دباره خوتونه د هار وارد بكيد',
 'createacct-another-join' => 'دونسمنیا یه گل حساو د هار وارد بکید',
@@ -388,14 +420,18 @@ $1',
 'createacct-submit' => 'حساو خوتونه راس بكيد',
 'createacct-another-submit' => 'يه گل حساوهنی راست بكيد',
 'createacct-benefit-heading' => '{{نوم مالگه}} وه دس خلکی چی شما راس بیه.',
-'createacct-benefit-body1' => '{{جمی:$1|ویرایشت|ویرایشتا}}',
-'createacct-benefit-body2' => '{{جمی:$1|بلگه|بلگیا}}',
+'createacct-benefit-body1' => '{{جمی:$1|ویرایشت|ویرایشتیا}}',
+'createacct-benefit-body2' => '{{جمی:$1|بلگه|بلگه یا}}',
+'createacct-benefit-body3' => 'تازه{{جمی:$1|هومیار|هومیارا}}',
 'badretype' => 'پاسوردی که شما دئیته مطاوقت ناره',
 'userexists' => 'کارور نوم که وارد بیه د ایسه استفاده بوئه.
 لطف بکید یه گل نوم هنی انتخاو بکید',
 'loginerror' => 'خطا اومائن د سيستم',
 'createacct-error' => 'خطا راس كردن حساو',
 'createaccounterror' => 'نبوئه حساو راس بكيد:$1',
+'nocookiesnew' => 'حساو کاروری راس بی،اما شما وامئن نیامایئته.{{نوم مالگه}} د کوکیا سی اومائن د سیستم کاروریا استفاده می که.کوکیا شما د کار افتائه.لطفن وا کارشو بونیت، اوسه وا نوم کاروری تازه و پسورد هنی بیایت وا مئن.',
+'nocookieslogin' => '{{نوم مالگه}} د کوکیا سی وامئن اومائن کاروریا استفاده می که. کوکیا شما د کار افتائه.
+لطف بکید د کارشو بونیت و دوواره تلاش بکید.',
 'noname' => 'شما یه گل نوم کاروری خو ناریت',
 'loginsuccesstitle' => 'اومائن د سيستم موفق بی',
 'loginsuccess' => 'شما ایسه وارد بیته {{SITENAME}} د دعنوان "$1".\'',
@@ -409,12 +445,13 @@ $1',
 'passwordtooshort' => 'پاسورد با حداقل  {{PLURAL:$1|1 character|$1 characters}}          با',
 'password-name-match' => 'پاسوردتو با د نوم کاروریتو فرخ داشتوه',
 'password-login-forbidden' => 'وه کار گرتن ای پاسوردو نوم کاروری ممنو بیه.',
-'mailmypassword' => 'رÙ\85ز Ù\87Ù\86Û\8c Ù\86Ù\87 Ø§Ù\8aÙ\85Ù\8aÙ\84 Ø¨Ù\83Ù\8aد',
+'mailmypassword' => 'د Ù\86Û\88 Ù\88ارد Ù\83ردÙ\86 Ø±Ù\85ز',
 'passwordremindertitle' => 'پاسورد موقت تازه سی {{SITENAME}}',
 'noemail' => 'هیچ نشونی ایمیلی سی کارور $1 ضفط نبیه.',
 'noemailcreate' => 'شما باید یه نشونی نومه معتور فراهم بکید',
 'mailerror' => 'خطا داره کل موئه:$1',
 'emailconfirmlink' => 'نشونی ايملتو نه محكم بكيد',
+'cannotchangeemail' => 'نشونی ایمیل حساو نتونه د ای ویکی آلشت بوئه.',
 'emaildisabled' => 'ای مالگه نتونه ایمیل بفرسنه',
 'accountcreated' => 'حساو راس بی',
 'createaccount-title' => 'حساو راس کرده سی  {{SITENAME}}',
@@ -451,6 +488,7 @@ $1',
 # Special:ChangeEmail
 'changeemail' => 'ایمیل تو نه آلشت بکید',
 'changeemail-header' => 'ایمیل حساوتونه آلشت بکید',
+'changeemail-no-info' => 'شما با بیایت د سیستم تا د ای بلگه دسرسی داشتویت',
 'changeemail-oldemail' => 'نشونی ایمیل تازه باو:',
 'changeemail-newemail' => 'نشونی ایمیل تازه',
 'changeemail-none' => '(هيش كوم)',
@@ -458,6 +496,15 @@ $1',
 'changeemail-submit' => 'آلشت کردن ایمیل',
 'changeemail-cancel' => 'رد كردن',
 
+# Special:ResetTokens
+'resettokens' => 'تازه کردن نشونه یا',
+'resettokens-no-tokens' => 'هیژ نشونه ای سی تازه کردن نئ.',
+'resettokens-legend' => 'تازه کردن نشونه یا',
+'resettokens-tokens' => 'نشونه یا:',
+'resettokens-token-label' => '$1 (ارزشت تازه: $2)',
+'resettokens-done' => 'نشونه یا تازه بیه.',
+'resettokens-resetbutton' => 'نشونه یا انتخاو بیه تازه بوئن',
+
 # Edit page toolbar
 'bold_sample' => 'متن توپر بيه',
 'bold_tip' => 'متن توپر بيه',
@@ -495,6 +542,7 @@ $1',
 'nosuchsectiontitle' => 'نبوئه بشخ پیدا بوئه',
 'loginreqtitle' => 'وامین اومائن لازمه',
 'loginreqlink' => 'اومائن',
+'loginreqpagetext' => '$1 لطف بکید بلگه یا هنی نه بوینیت',
 'accmailtitle' => 'پاسورد کل بی',
 'newarticle' => 'تازه',
 'newarticletext' => 'شما وادما هوم پیوندی هئیت که وجود ناره.
@@ -559,6 +607,8 @@ $1',
 'last' => 'دمايی',
 'page_first' => 'اولی',
 'page_last' => 'آخر',
+'histlegend' => "انتخاو فرخدار:جعویا رادیو نه سی دوواره دیئن و وارسی نشو دار بکید و یا ری رئتن کلیک بکید .<br />
+شرح نوشته: '''({{int:cur}})''' = وا آخری دوواره دیئن فرخ داره '''({{ int:last}})'''= وا دواره دیئن انجوم دئنی فرخ داره  '''{{int:minoreditletter}}''' =ویرایشت کؤچک.",
 'history-fieldset-title' => 'ویرگار مرور ون',
 'history-show-deleted' => 'فقط پاك بيه',
 'histfirst' => 'قديمي تري',
@@ -571,6 +621,7 @@ $1',
 $2',
 
 # Revision deletion
+'rev-deleted-user' => '(نوم کاروری جا وه جا بیه)',
 'rev-delundel' => 'آلشت وضئيت ديئن',
 'rev-showdeleted' => 'نشو دائن',
 'revdelete-show-file-submit' => 'هری',
@@ -610,7 +661,7 @@ $2',
 'nextn' => 'نيايی {{PLURAL:$1|$1}}',
 'prevn-title' => 'پيشتر $1 {{PLURAL:$1|نتيجه|نتيجيا}}',
 'nextn-title' => 'نيايی $1 {{PLURAL:$1|نتيجه|نتيجيا}}',
-'shown-title' => 'Ù\86Ø´Ù\88Ù\86 Ø¯Ø§Ø¦Ù\86 $1 {{PLURAL:$1|Ù\86تÙ\8aجÙ\87\86تÙ\8aجÙ\87}} Ø³Û\8c Ù\87Ù\85Ù\87 بلگه',
+'shown-title' => 'Ù\86Ø´Ù\88Ù\86 Ø¯Ø¦Ù\86 $1 {{PLURAL:$1|Ù\86تÙ\8aجÙ\87\86تÙ\8aجÙ\87}} Ø³Û\8c Ù\87ر بلگه',
 'viewprevnext' => 'ديئن ($1 {{int:pipe-separator}} $2) ($3)',
 'searchmenu-exists' => "'''ایچه بلگه ای هئ وه نوم\"[[:\$1]]\" که ها د ای ویکی'''",
 'searchmenu-new' => "'''ای بلگه نه راس كو \"[[:\$1]]\" د ای  ويكي!'''",
@@ -683,10 +734,17 @@ $2',
 'yourrealname' => 'نوم راستكی:',
 'yourlanguage' => 'زون:',
 'yournick' => 'امضا تازه:',
+'gender-unknown' => 'مه میهام چی یی نموئم',
+'gender-male' => 'وه(پیا) بلگه یا ویکی نه ویرایشت می که',
+'gender-female' => 'وه(زئنه)بلگه یا ویکی نه ویرایشت می که',
 'email' => 'پیومک برقی',
 'prefs-help-email' => 'نشونی ایمیل اختیاری هئ.اما سی بازجست پاسورد دش نیاز بوئه.شما باید پاسوردتونه د ویر بوریت',
 'prefs-help-email-others' => 'شما می تونید سی پیوند گرتن تو وا نهایین ایمیل مئن یه هوم پیوند د بلگه کاروری یا بلگه چک چنه تو انتخاو بکید.
 نشونی ایمیلتو وختی که کاروریا هنی وا تو پیوند می گرن دیار نی.',
+'prefs-help-email-required' => 'نشونی ایمیل لازم هئ.',
+'prefs-info' => 'دونسمنیا اولیه',
+'prefs-i18n' => 'جهون ولاتمنی',
+'prefs-signature' => 'امضا',
 'prefs-editor' => 'ويرايشتگر',
 'prefs-preview' => 'پیش سیل',
 'prefs-diffs' => 'فرخیا',
@@ -698,6 +756,8 @@ $2',
 'saveusergroups' => 'ذخیره کرد گرویا کاروری',
 'userrights-groupsmember' => 'اندوم:',
 'userrights-reason' => 'دليل:',
+'userrights-changeable-col' => 'گرویایی که شما تونیت ویرایشت بکید',
+'userrights-unchangeable-col' => 'گرویایی که شما نتونیت ویرایشت بکید',
 
 # Groups
 'group' => 'گرو',
@@ -708,9 +768,15 @@ $2',
 'group-bureaucrat' => 'بروکراتیا',
 'group-all' => '(همه)',
 
+'group-user-member' => '{{جنس:$1|کارور}}',
+'group-bot-member' => '{{حنس:$1|بوت}}',
+'group-sysop-member' => '{{جنس:$1|مدیر}}',
+'group-bureaucrat-member' => '{{جنس:$1|بروکرات}}',
+
 # Rights
 'right-read' => 'حنن بلگیا',
 'right-edit' => 'ویرایشت بلگیا',
+'right-delete' => 'بلگیا نه پاک کو',
 
 # Special:Log/newusers
 'newuserlogpage' => 'راس بیه وا کارور',
@@ -739,7 +805,7 @@ $2',
 'rclistfrom' => 'آلشتیا تازه ایی که وا $1 شرو بیه نشونش بئه',
 'rcshowhideminor' => 'ويرايشتيا کؤچک $1',
 'rcshowhidebots' => '$1 رواتيا یا بوتيا',
-'rcshowhideliu' => '$1 کارورياداخل بيه',
+'rcshowhideliu' => '$1 کاروريا ثوت نام کرده',
 'rcshowhideanons' => '$1 کاروريا ناشناس',
 'rcshowhidepatr' => '$1 ویرایشتیا تیه پرس بیه',
 'rcshowhidemine' => 'ويرايشتيا مه$1',
@@ -766,6 +832,9 @@ $2',
 
 # Upload
 'upload' => 'بلم گير كردن فايلا',
+'uploadbtn' => 'سوار کردن فایل',
+'uploadnologin' => 'وارد نبیه',
+'uploaderror' => 'خطا د سوار کردن',
 'uploadlogpage' => 'سوارکرد',
 'filename' => 'نوم فایل',
 'filedesc' => 'چكسته',
@@ -857,6 +926,9 @@ $2',
 'booksources-search-legend' => 'پی جوری سی سرچشمه یا کتاو',
 'booksources-go' => 'رو',
 
+# Special:Log
+'log' => 'نیسنن رخ ونیا',
+
 # Special:AllPages
 'allpages' => 'همه بلگيا',
 'alphaindexline' => '$1 د
@@ -919,6 +991,7 @@ $2',
 'sp-contributions-newbies' => 'فقط هومیاری یایی که د حساو تازه بیه نشون بئه',
 'sp-contributions-blocklog' => 'قلف',
 'sp-contributions-uploads' => 'سواركرديا',
+'sp-contributions-logs' => 'نیسنن رخ ونیا',
 'sp-contributions-talk' => 'چك چنه',
 'sp-contributions-search' => 'سی هومیاریا پی جور با',
 'sp-contributions-username' => 'نوم نشون آی پی يا نوم كاروری:',
@@ -1034,7 +1107,7 @@ $2',
 'file-info-size' => '$1 × $2 پیکسل, انازه فایل: $3, MIME نوع: $4',
 'file-nohires' => 'عسك ون بالاتري دش ني',
 'svg-long-desc' => 'اس وی جی فايل.نومنا $1 $2 پيكسل',
-'show-big-image' => 'تموم رخ ون',
+'show-big-image' => 'فایل اصلی',
 
 # Bad image list
 'bad_image_list' => 'دونسمنديانه وه ای شلگ وارد بكيت:
index ea3a794..1c80f65 100644 (file)
@@ -430,8 +430,8 @@ Putite cuntinuà a ausà {{SITENAME}} comme n'utente senza nomme, o si nò putit
 'rev-delundel' => 'faje vedé/annascunne',
 'rev-showdeleted' => 'faje vedé',
 'revdelete-show-file-submit' => 'Sì',
-'revdelete-radio-set' => '',
-'revdelete-radio-unset' => 'No',
+'revdelete-radio-set' => 'Nasconde',
+'revdelete-radio-unset' => 'Faje vedé',
 'revdel-restore' => 'càgna visiblità',
 
 # Diffs
index e9db6b7..67556e4 100644 (file)
@@ -397,18 +397,18 @@ $messages = array(
 'oct' => "d'oct",
 'nov' => 'de nov',
 'dec' => 'de dec',
-'january-date' => '$1 genièr',
-'february-date' => '$1 febrièr',
-'march-date' => '$1 març',
-'april-date' => '$1 abril',
-'may-date' => '$1 mai',
-'june-date' => '$1 junh',
-'july-date' => '$1 julhet',
-'august-date' => '$1 agost',
-'september-date' => '$1 setembre',
-'october-date' => '$1 octobre',
-'november-date' => '$1 novembre',
-'december-date' => '$1 decembre',
+'january-date' => '$1 de genièr',
+'february-date' => '$1 de febrièr',
+'march-date' => '$1 de març',
+'april-date' => '$1 de abril',
+'may-date' => '$1 de mai',
+'june-date' => '$1 de junh',
+'july-date' => '$1 de julhet',
+'august-date' => "$1 d'agost",
+'september-date' => '$1 de setembre',
+'october-date' => "$1 d'octobre",
+'november-date' => '$1 de novembre',
+'december-date' => '$1 de decembre',
 
 # Categories related messages
 'pagecategories' => '{{PLURAL:$1|Categoria|Categorias}}',
@@ -1143,6 +1143,7 @@ D'unas inclusions seràn pas efectuadas.",
 'cantcreateaccount-text' => "La creacion de compte dempuèi aquesta adreça IP ('''$1''') es estada blocada per [[User:$3|$3]].
 
 La rason balhada per $3 èra ''$2''.",
+'cantcreateaccount-range-text' => "La creacion de compte dempuèi las adressas IP  '''$1''', que la vòstra n'es ('''$4''') es estada blocada per [[User:$3|$3]].",
 
 # History pages
 'viewpagelogs' => 'Vejatz las operacions per aquesta pagina',
@@ -1671,6 +1672,7 @@ Tanben podètz causir de permetre a d’autres de vos contactar per vòstra pagi
 'recentchanges-label-minor' => 'Aqueste cambiament es menor',
 'recentchanges-label-bot' => 'Aqueste cambiament es estat efectuat per un bòt.',
 'recentchanges-label-unpatrolled' => 'Aqueste cambiament es pas estat verificat encara.',
+'recentchanges-legend-heading' => "'''Legenda:'''",
 'recentchanges-legend-newpage' => '$1 - pagina novèla',
 'rcnotefrom' => "Vaquí los cambiaments efectuats dempuèi lo '''$2''' ('''$1''' al maximum).",
 'rclistfrom' => 'Afichar las modificacions novèlas dempuèi lo $1.',
index 8c56454..295fb33 100644 (file)
@@ -4942,6 +4942,7 @@ See the following search results:
 'protectedpages' => '{{doc-special|ProtectedPages}}',
 'protectedpages-indef' => 'Option in [[Special:ProtectedPages]]',
 'protectedpages-cascade' => 'Option in [[Special:ProtectedPages]]',
+'protectedpages-noredirect' => 'Option in [[Special:ProtectedPages]]',
 'protectedpagesempty' => 'Used in [[Special:ProtectedPages]], when there are no protected pages with the specified parameters.',
 'protectedtitles' => '{{doc-special|ProtectedTitles}}',
 'protectedtitlesempty' => 'Used on [[Special:ProtectedTitles]]. This text appears if the list of protected titles is empty. See the [[mw:Project:Protected_titles|help page on MediaWiki]] for more information.',
@@ -10387,6 +10388,7 @@ Parameters:
 'api-error-duplicate-archive' => 'API error message that can be used for client side localisation of API errors. Parameters:
 * $1 - a number of files
 * $2 - a link to a list of duplicate files',
+'api-error-stasherror' => 'API error message that can be used for client side localisation of API errors.',
 'api-error-duplicate-archive-popup-title' => 'API error message that can be used for client side localisation of API errors. Parameters:
 * $1 is a number of files.',
 'api-error-duplicate-popup-title' => 'This message is a pop-up title shown in case one or more files exactly equal to the one just uploaded are already present.
index 969503e..6c97952 100644 (file)
@@ -1468,7 +1468,7 @@ Notera dock att deras indexering av {{SITENAME}} kan vara något föråldrad.',
 'stub-threshold' => 'Gräns för <a href="#" class="stub">stubblänk</a>-formatering (byte):',
 'stub-threshold-disabled' => 'Avaktiverat',
 'recentchangesdays' => 'Antal dygn som skall visas i "senaste ändringarna":',
-'recentchangesdays-max' => 'Maximalt $1 {{PLURAL:$1|dygn|dygn}}',
+'recentchangesdays-max' => 'Maximalt $1 {{PLURAL:$1|dygn}}',
 'recentchangescount' => 'Antal redigeringar som visas som standard:',
 'prefs-help-recentchangescount' => 'Detta inkluderar senaste ändringarna, sidhistorik och loggar.',
 'prefs-help-watchlist-token2' => 'Detta är den hemliga nyckeln till webbflödet i din bevakningslista.
index 9de93d8..c8ce60f 100644 (file)
@@ -512,7 +512,7 @@ $messages = array(
 'qbpageoptions' => 'Bu sayfa',
 'qbmyoptions' => 'Sayfalarım',
 'faq' => 'SSS',
-'faqpage' => 'Proje:SSS',
+'faqpage' => 'Project:SSS',
 
 # Vector skin
 'vector-action-addsection' => 'Konu ekle',
@@ -603,16 +603,16 @@ $1',
 'copyright' => 'Aksi belirtilmedikçe içerik $1 altındadır.',
 'copyrightpage' => '{{ns:project}}:Telif hakları',
 'currentevents' => 'Güncel olaylar',
-'currentevents-url' => 'Proje: güncel olaylar',
+'currentevents-url' => 'Project:Güncel olaylar',
 'disclaimers' => 'Sorumluluk reddi',
-'disclaimerpage' => 'Proje: genel sorumluluk reddi',
+'disclaimerpage' => 'Project:Genel sorumluluk reddi',
 'edithelp' => 'Nasıl değiştirilir?',
 'helppage' => 'Help:İçindekiler',
 'mainpage' => 'Ana Sayfa',
 'mainpage-description' => 'Ana sayfa',
-'policy-url' => 'Proje: politika',
+'policy-url' => 'Project:İlkeler',
 'portal' => 'Topluluk portalı',
-'portal-url' => 'Proje: Topluluk portalı',
+'portal-url' => 'Project:Topluluk portali',
 'privacy' => 'Gizlilik ilkesi',
 'privacypage' => 'Project:Gizlilik ilkesi',
 
@@ -626,7 +626,7 @@ $1',
 'ok' => 'Tamam',
 'pagetitle-view-mainpage' => '{{SITENAME}}',
 'retrievedfrom' => '"$1" adresinden alındı.',
-'youhavenewmessages' => 'Yeni $1 var olan($2).',
+'youhavenewmessages' => '$1 {{PLURAL:$3|var}} ($2).',
 'youhavenewmessagesfromusers' => '{{PLURAL:$3|Başka bir kullanıcıdan|$3 kullanıcıdan}} $1 var ($2).',
 'youhavenewmessagesmanyusers' => 'Birçok kullanıcıdan $1 var ($2).',
 'newmessageslinkplural' => '{{PLURAL:$1|yeni mesajınız|yeni mesajlarınız}}',
@@ -2531,6 +2531,7 @@ Böyle sayfaların silinmesi, {{SITENAME}} sitesini bozmamak için sınırlanmak
 'delete-warning-toobig' => 'Bu sayfanın büyük bir değişiklik geçmişi var, $1 {{PLURAL:$1|revizyonun|revizyonun}} üzerinde.
 Bunu silmek {{SITENAME}} işlemlerini aksatabilir;
 dikkatle devam edin.',
+'deleting-backlinks-warning' => "'''Uyarı:''' Silmek üzere olduğunuz sayfaya başka sayfalardan bağlantılar var.",
 
 # Rollback
 'rollback' => 'değişiklikleri geri al',
index f7ee5cf..00b610d 100644 (file)
@@ -49,17 +49,17 @@ $messages = array(
 'tog-hidepatrolled' => 'Käkiq perämäidsi muutmiisi nimekirän ärq muutmisõq, miä ommaq perräkaemisnimekirän',
 'tog-newpageshidepatrolled' => 'Käkiq vahtsidõ lehti nimekirän ärq ülekaeduq leheq',
 'tog-extendwatchlist' => 'Laendaq perräkaemisnimekirjä, et nätäq kõiki muutmiisi, mitte õnnõ kõgõ perämäidsi',
-'tog-usenewrc' => 'Laendõduq perämädseq muutmisõq (vaia JavaScripti)',
+'tog-usenewrc' => 'Sordiq viimädseq muutmisõq ja muutmisnimekirän leheküle perrä',
 'tog-numberheadings' => 'Päälkirjo automaatnummõrdus',
-'tog-showtoolbar' => 'Näütäq toimõndusõ riistakasti',
-'tog-editondblclick' => 'Artiklidõ toimõndaminõ topõltklõpsu pääle (JavaScript)',
+'tog-showtoolbar' => 'Näütäq toimõndusõ tüüriistaripa',
+'tog-editondblclick' => 'Toimõndaq artikliid topõltklõpsu pääle',
 'tog-editsection' => 'Lupaq lõikõ toimõndaq [toimõndaq]-linkõga',
-'tog-editsectiononrightclick' => 'Lupaq lõikõ toimõndaq hüäpoolidsõ klõpsutusõga <br /> lõigu päälkirä pääl (JavaScript)',
+'tog-editsectiononrightclick' => 'Lupaq lõikõ toimõndaq hüäpoolidsõ klõpsutusõga lõigu päälkirä pääl',
 'tog-showtoc' => 'Näütäq sisukõrda (rohkõmb ku kolmõ vaihõpäälkiräga lehile)',
 'tog-rememberpassword' => 'Salasõna miildejätmine tulõvaidsis kõrros (kõgõ inämb $1 {{PLURAL:$1|pääväs|pääväs}})',
-'tog-watchcreations' => 'Panõq mu luuduq leheq mu perräkaemisnimekirjä',
-'tog-watchdefault' => 'Kaeq vahtsidõ ja muudõtuidõ artiklidõ perrä',
-'tog-watchmoves' => 'Panõq mu ümbrenõstõduq leheküleq mu perräkaemisnimekirjä',
+'tog-watchcreations' => 'Panõq muq luuduq leheq ja üleslaadiduq teedüstüq muq perräkaemisnimekirjä',
+'tog-watchdefault' => 'Panõq perräkaemisnimekirjä muq muudõduq leheq ja teedüstüq',
+'tog-watchmoves' => 'Panõq muq ümbrenõstõduq leheq ja teedüstüq muq perräkaemisnimekirjä',
 'tog-watchdeletion' => 'Panõq mu kistutõduq leheküleq mu perräkaemisnimekirjä',
 'tog-minordefault' => 'Märgiq kõik parandusõq vaikimiisi väikeisis paranduisis',
 'tog-previewontop' => 'Näütäq proovikaehust inne, mitte perän toimõnduskasti',
@@ -71,7 +71,7 @@ $messages = array(
 'tog-shownumberswatching' => "Näütäq, ku pall'o pruukjit taa lehe perrä kaes",
 'tog-oldsig' => 'Parhillanõ alakirotus:',
 'tog-fancysig' => 'Pruugiq vikiteksti moodulist alakirotust (ilma automaatsõ lingildä)',
-'tog-uselivepreview' => 'Pruugiq kipõkaehust (JavaScript) (proomi)',
+'tog-uselivepreview' => 'Pruugiq õkvakipõkaehust (proomivõimalus)',
 'tog-forceeditsummary' => 'Annaq teedäq, ku olõ-i kirotõt kokkovõtõt',
 'tog-watchlisthideown' => 'Näüdäku-i perräkaemisnimekirän mu hindä toimõnduisi',
 'tog-watchlisthidebots' => 'Näüdäku-i perräkaemisnimekirän robotidõ toimõnduisi',
@@ -83,6 +83,8 @@ $messages = array(
 'tog-diffonly' => 'Näüdäku-i lahkominekide lehe all lehe täüt sissu',
 'tog-showhiddencats' => 'Näütäq käkitüid katõgoorijit',
 'tog-norollbackdiff' => 'Päält tagasivõtmist näüdäku-i lahkominekiid',
+'tog-useeditwarning' => 'Hoiadaq minno, ku ma lääq lehe päält ärq ilma ummi muutmiisi ärq pästmäldä',
+'tog-prefershttps' => 'Pruugiq nimega sisseminemises kõgõ kaidsõtut ütistüst',
 
 'underline-always' => 'Kõgõ',
 'underline-never' => 'Ei kunagi',
@@ -146,6 +148,18 @@ $messages = array(
 'oct' => 'rehek',
 'nov' => 'märtek',
 'dec' => 'jouluk',
+'january-date' => '$1. vahtsõaastakuu päiv',
+'february-date' => '$1. radokuu päiv',
+'march-date' => '$1. urbõkuu päiv',
+'april-date' => '$1. mahlakuu päiv',
+'may-date' => '$1. lehekuu päiv',
+'june-date' => '$1. piimäkuu päiv',
+'july-date' => '$1. hainakuu päiv',
+'august-date' => '$1. põimukuu päiv',
+'september-date' => '$1. süküskuu päiv',
+'october-date' => '$1. rehekuu päiv',
+'november-date' => '$1. märtekuu päiv',
+'december-date' => '$1. joulukuu päiv',
 
 # Categories related messages
 'pagecategories' => '{{PLURAL:$1|Katõgooria|Katõgooriaq}}',
@@ -171,6 +185,7 @@ $messages = array(
 'newwindow' => '(tulõ vallalõ vahtsõn aknõn)',
 'cancel' => 'Jätäq katski',
 'moredotdotdot' => 'Viil...',
+'morenotlisted' => 'Seo nimekiri olõ-õi tävveline.',
 'mypage' => 'Muq lehekülg',
 'mytalk' => 'Arotus',
 'anontalk' => 'Seo puutri võrgoaadrõsi arotus',
@@ -193,7 +208,7 @@ $messages = array(
 'vector-action-protect' => 'Kaidsaq',
 'vector-action-undelete' => 'Tiiq tagasi',
 'vector-action-unprotect' => 'Muudaq kaidsõt',
-'vector-simplesearch-preference' => 'Lupaq tävvendedüid otsmispakmiisi (õnnõ Vektori-kujundusõn)',
+'vector-simplesearch-preference' => 'Lupaq lihtsüstedüt otsmisripa (õnnõ Vektor-kujondusõn)',
 'vector-view-create' => 'Luuq',
 'vector-view-edit' => 'Toimõndaq',
 'vector-view-history' => 'Näütäq aoluku',
@@ -203,6 +218,7 @@ $messages = array(
 'namespaces' => 'Nimeruumiq',
 'variants' => 'Tõõsõndiq',
 
+'navigation-heading' => 'Juhtmisvaliguq',
 'errorpagetitle' => 'Viga',
 'returnto' => 'Tagasi lehe manoq $1.',
 'tagline' => 'Läteq: {{SITENAME}}',
@@ -224,6 +240,7 @@ $messages = array(
 'create-this-page' => 'Luuq seo leht',
 'delete' => 'Kistudaq ärq',
 'deletethispage' => 'Kistudaq seo artikli ärq',
+'undeletethispage' => 'Tiiq seo leht tagasi',
 'undelete_short' => 'Võtaq tagasi {{PLURAL:$1|üts muutminõ|$1 muutmist}}',
 'viewdeleted_short' => 'Kaeq {{PLURAL:$1|ütte|$1}} kistutõdut redaktsiooni',
 'protect' => 'Kaidsaq',
@@ -270,14 +287,14 @@ $1",
 # All link text and link target definitions of links into project namespace that get used by other message strings, with the exception of user group pages (see grouppage).
 'aboutsite' => '{{SITENAME}} tutvustus',
 'aboutpage' => 'Project:Pääteedüs',
-'copyright' => 'Teksti või vabalt pruukiq litsendsi $1 perrä.',
+'copyright' => 'Teksti või vabalt pruukiq litsendsi $1 perrä, ku olõ-õi tõisildõ üteld.',
 'copyrightpage' => '{{ns:project}}:Tegijäõigusõq',
 'currentevents' => 'Miä sünnüs',
 'currentevents-url' => 'Project:Miä sünnüs',
 'disclaimers' => 'Hoiatuisi',
 'disclaimerpage' => 'Project:Üledseq hoiatusõq',
 'edithelp' => 'Toimõndamisoppus',
-'helppage' => 'Help:Oppus',
+'helppage' => 'Help:Sisukõrd',
 'mainpage' => 'Pääleht',
 'mainpage-description' => 'Pääleht',
 'policy-url' => 'Project:Säädüseq',
@@ -296,6 +313,10 @@ $1",
 'ok' => 'Hää külh',
 'retrievedfrom' => 'Vällä otsit teedüskogost "$1"',
 'youhavenewmessages' => 'Sul om $1 ($2).',
+'youhavenewmessagesfromusers' => 'Sullõ om $1 {{PLURAL:$3|ütelt|$3}} pruukjalt ($2).',
+'youhavenewmessagesmanyusers' => "Sullõ om $1 pall'odõlt pruukjilt ($2).",
+'newmessageslinkplural' => '{{PLURAL:$1|vahtsõnõ sõnnom|999=vahtsit sõnomit}}',
+'newmessagesdifflinkplural' => '{{PLURAL:$1|viimäne muutminõ|999=viimädseq muutmisõq}}',
 'youhavenewmessagesmulti' => 'Sullõ om vahtsit sõnomit lehe pääl $1',
 'editsection' => 'toimõndaq',
 'editold' => 'toimõndaq',
@@ -319,6 +340,8 @@ $1",
 'page-rss-feed' => '$1 (RSS-söödüs)',
 'page-atom-feed' => '$1 (Atom-söödüs)',
 'red-link-title' => '$1 (säänest lehte olõ-i)',
+'sort-descending' => 'Panõq alanõvahe järekõrda',
+'sort-ascending' => 'Panõq nõsõvahe järekõrda',
 
 # Short words for each namespace, by default used in the namespace tab in monobook
 'nstab-main' => 'Artikli',
@@ -345,6 +368,11 @@ Olõmanolõvaq tallitusleheküleq ommaq löüdäq leheküle päält [[Special:Sp
 # General errors
 'error' => 'Viga',
 'databaseerror' => 'Teedüskogo viga',
+'databaseerror-text' => "Teedüskogost perräküsümise man oll' viga.
+Viga või ollaq tarkvaran.",
+'databaseerror-textcl' => "Teedüskogost perräküsümise man oll' viga.",
+'databaseerror-query' => 'Perräküsümine: $1',
+'databaseerror-function' => 'Ülesannõq: $1',
 'databaseerror-error' => 'Viga: $1',
 'laggedslavemode' => 'Hoiatus: Taa lehe pääl pruugi-i ollaq perämäidsi muutmiisi.',
 'readonly' => 'Teedüskogo kirotuskaitsõ all',
@@ -363,6 +391,8 @@ Annaq taa lehe aadrõs viki [[Special:ListUsers/sysop|ülevänpidäjäle]].',
 'readonly_lag' => 'Teedüskogo panti automaatsõhe kinniq, et kõik teedüskogoserveriq saasiq kätte kõik värskiq muutmisõq',
 'internalerror' => 'Sisemäne viga',
 'internalerror_info' => 'Viga: $1',
+'fileappenderrorread' => 'Teedüstüt "$1" saa-as manopandmisõ aol lukõq.',
+'fileappenderror' => 'Teedüstüt "$1" saa-as manoq pandaq teedüstüle "$2".',
 'filecopyerror' => 'Es saaq teedüstüt "$1" teedüstüs "$2" kopidaq.',
 'filerenameerror' => 'Es saaq teedüstüt "$1" teedüstüs "$2" ümbre nimetäq.',
 'filedeleteerror' => 'Teedüstüt nimega "$1" saa-i ärq kistutaq.',
@@ -374,19 +404,24 @@ Annaq taa lehe aadrõs viki [[Special:ListUsers/sysop|ülevänpidäjäle]].',
 'badarticleerror' => 'Taad tallitust saa ei seo leheküle pääl tetäq.',
 'cannotdelete' => 'Lehekülge vai pilti "$1" saa ei ärq kistutaq. 
 Või-ollaq kiäki tõõnõ jo kistut\' taa ärq.',
+'cannotdelete-title' => 'Lehekülge "$1" saa-ai ärq kistutaq',
 'badtitle' => 'Viganõ päälkiri',
 'badtitletext' => "Küsüt artiklipäälkiri oll' kas viganõ, tühi vai sis
 võlssi näüdät kiili- vai wikidevaihõlinõ päälkiri.",
-'perfcached' => 'Järgmäne teedüs om puhvõrdõt ja pruugi ei ollaq kõgõ värskimb. A maximum of {{PLURAL:$1|one result is|$1 results are}} available in the cache.',
-'perfcachedts' => 'Järgmäne teedüs om puhvõrdõt ja om viimäte muudõt $1. A maximum of {{PLURAL:$4|one result is|$4 results are}} available in the cache.',
+'perfcached' => 'Järgmäne teedüs om puhvõrdõt ja pruugi ei ollaq kõgõ värskimb. 
+Puhvrin om {{PLURAL:$1|üts tullõm|$1 tulõmit}}.',
+'perfcachedts' => 'Järgmõne teedüs om vaihõmälon. Viimäne vahtsõndamisaig: $2, kell $3. Puhvrin om kooniq {{PLURAL:$4|üts tullõm|$4 tulõmit}}.',
 'querypage-no-updates' => 'Taad lehe teedüst parhilla värskis ei tetäq.',
 'viewsource' => 'Kaeq lätteteksti',
+'viewsource-title' => 'Lehe $1 lätteteksti kaeminõ',
 'actionthrottled' => 'Tallitusõ kibõhus piirõt',
 'actionthrottledtext' => "Taa tallitusõ mitmit kõrdo tegemine om prahipandjidõ peräst ärq keelet. Olõt taad lühkü ao seen pall'o hulga tennüq. Prooviq veidükese ao peräst vahtsõst.",
-'protectedpagetext' => 'Taa lehekülg om kirotuskaidsõt.',
+'protectedpagetext' => 'Taa lehekülg om kirotuskaidsõt, taad saa-ai muutaq.',
 'viewsourcetext' => 'Võit kaiaq ja kopidaq taa lehe lättekoodi:',
-'protectedinterface' => "Taa lehe pääl om tarkvara pruukjapalgõ tekst. Leht om lukku pant, et taad saasi-i ärq ts'urkiq.",
-'editinginterface' => "'''Hoiatus:''' Sa toimõndat tarkvara pruukjapalgõ tekstiga lehte. Ku siin midä muudat, mõotas tuu pruukjapalõt. Ümbrepandmisõs tasos pruukiq MediaWiki ümbrepandmisõ tüüriista [//translatewiki.net/wiki/Main_Page?setlang=fiu-vro translatewiki.net].",
+'viewyourtext' => "Saat kaiaq ja kopidaq noidõ muutmiisi lätteteksti, miä sa seo lehe pääle '''esiq''' tennüq olõt:",
+'protectedinterface' => "Taa lehe pääl om tarkvara pruukjapalgõ tekst. Leht om lukku pant, et taad saasi-i ärq ts'urkiq. 
+Ku tahat tetäq ümbrepandmiisi (midä pruukvaq kõik vikiq) pruugiq tuus MediaWiki ümbrepandmisõ tüükeskkunda [//translatewiki.net/ translatewiki.net].",
+'editinginterface' => "'''Hoiatus:''' Sa toimõndat tarkvara pruukjapalgõ tekstiga lehte. Ku siin midä muudat, mõotas tuu pruukjapalõt. Ümbrepandmisõs tasos pruukiq MediaWiki ümbrepandmisõ tüükeskkunda [//translatewiki.net/ translatewiki.net].",
 'cascadeprotected' => 'Taa leht om kirotuskaidsõt, selle et taa {{PLURAL:$1|kuulus alanolõvidõ kaidsõtuidõ lehti hulka|kuulus alanolõvidõ kaidsõtuidõ lehti hulka}}:
 $2',
 'namespaceprotected' => "Sul olõ-i lubat toimõndaq nimeruumi '''$1''' lehti.",
@@ -422,6 +457,7 @@ Tähelepandmisõs: niikavva, ku sa olõ-i tühäs tennüq uma võrgokaeja vaihõ
 'createaccount' => 'Tiiq pruukjanimi ärq',
 'gotaccount' => "Ku sul jo om uma pruukjanimi, sis '''$1'''.",
 'gotaccountlink' => 'võit nimega sisse minnäq',
+'userlogin-resetlink' => 'Kas olõt uma salasõna ärq unõhtanuq?',
 'createaccountmail' => 'e-postiga',
 'createaccountreason' => 'Põhjus:',
 'badretype' => 'Kirotõduq salasõnaq ei klapiq kokko.',
@@ -441,7 +477,7 @@ Kaeq kiräpilt üle vai [[Special:UserLogin/signup|luuq vahtsõnõ pruukjanimi]]
 'wrongpassword' => 'Kirotõt võlss salasõna. Prooviq vahtsõst.',
 'wrongpasswordempty' => 'Salasõna tohe-i tühi ollaq.',
 'passwordtooshort' => "Salasõna om viganõ vai pall'o lühkü. Taan piät olõma vähämbält {{PLURAL:$1|1 märk|$1 märki}} ja taa tohe-i ollaq sama, miä su pruukjanimi.",
-'mailmypassword' => 'Saadaq mullõ e-postiga vahtsõnõ salasõna',
+'mailmypassword' => 'Vahtsõndaq umma salasõnna',
 'passwordremindertitle' => '{{SITENAME}} salasõna miildetulõtus',
 'passwordremindertext' => 'Kiäki (arvadaq saq esiq, puutri võrgonummõr $1),
 pallõl\' vahtsõt sisseminegi salasõnna {{SITENAME}} ($4) jaos.
@@ -498,7 +534,7 @@ Või-ollaq olõt jo uma salasõna ärq muutnuq vai küsünüq vahtsõ aotlidsõ
 'bold_tip' => 'Paks kiri',
 'italic_sample' => 'Liuhkakiri',
 'italic_tip' => 'Liuhkakiri',
-'link_sample' => 'Lingitäv päälkiri',
+'link_sample' => 'Lingi päälkiri',
 'link_tip' => 'Siselink',
 'extlink_sample' => 'http://www.example.com Lingi nimi',
 'extlink_tip' => 'Välislink (unõhtagu-i ette pandaq http://)',
@@ -579,6 +615,9 @@ Ku sa johtuq siiäq kogõmaldaq, sis klõpsaq võrgokaeja '''Tagasi'''-nuppi.",
 'noarticletext' => 'Seo leht om parlaq tühi.
 Võit [[Special:Search/{{PAGENAME}}|otsiq soe lehe nimme]]  tõisi lehti päält vai
 <span class="plainlinks">[{{fullurl:{{#Special:Log}}|page={{FULLPAGENAMEE}}}} uuriq muutmisnimekirjo] vai [{{fullurl:{{FULLPAGENAME}}|action=edit}} puuduolõva leheküle esiq luvvaq]</span>.',
+'noarticletext-nopermission' => 'Seo lehe pääl olõ-õi parlaq teksti.
+Võit [[Special:Search/{{PAGENAME}}|otsiq soe lehe nimme]] tõisi lehti päält vai
+<span class="plainlinks">[{{fullurl:{{#Special:Log}}|page={{FULLPAGENAMEE}}}} uuriq muutmisnimekirjo]</span>, a sul olõ-õi õigust seod lehte alostaq.',
 'userpage-userdoesnotexist' => 'Pruukjanimme "<nowiki>$1</nowiki>" olõ-i kirjä pant. Kaeq perrä, kas olõt iks kimmäs, et tahat taad lehte toimõndaq.',
 'userpage-userdoesnotexist-view' => 'Pruukjanimme "$1" olõ-õi kirjä pant.',
 'clearyourcache' => "'''Panõq tähele:''' perän pästmist piät muutmiisi nägemises uma võrgokaeja vaihõmälo tühäs tegemä. '''Mozillal / Firofoxil / Safaril''' hoiaq all nõstmisnuppi ''Shift'' ja vaodaq ''Reload'' vai ''Ctrl-R'' (Macil ''Command-R''); Konqueroril vaodaq ''Reload'' vai ''F5''. Operal puhastaq vaihõmälo ja võtaq valikust ''Tools → Preferences''. Internet Exploreril hoiaq ''Ctrl'' ja vaodaq ''Refresh'' vai vaodaq  ''ctrl-f5''.",
@@ -589,7 +628,8 @@ Võit [[Special:Search/{{PAGENAME}}|otsiq soe lehe nimme]]  tõisi lehti päält
 'userinvalidcssjstitle' => "'''Miildetulõtus:''' Olõ-i stiili nimega \"\$1\". Piäq meelen, et pruukja säedüq .css- and .js-leheq piät nakkama väiku algustähega.",
 'updated' => '(Värskis tett)',
 'note' => "'''Miildetulõtus:'''",
-'previewnote' => "'''Taa om õnnõ proovikaehus; muutmisõq olõ-i pästedüq!'''",
+'previewnote' => "'''Seo om õnnõ proovikaehus!''' 
+Suq tettüq muutmisõq olõ-õi viil pästedüq!",
 'previewconflict' => "Taa proovikaehus näütäs, kuis ülembädsen toimõtuskastin ollõv tekst' päält pästmist vällä nägemä nakkas.",
 'session_fail_preview' => "'''Annaq andis! Su toimõndust saa-s pästäq, selle et su tüükõrra teedüs om kaoma lännüq. Olõq hää, proomiq viilkõrd. Ku tuust olõ-i kassu, proomiq nii, et läät nime alt vällä ja sis jälq tagasi sisse.'''",
 'session_fail_preview_html' => "'''Annaq andis, mi saa-i tallitaq su toimõndust, selle et toimõnduskõrra teedüs om kaoma lännüq.'''
@@ -633,13 +673,19 @@ Võit toimõndaq olõmanolõvit lehti vai [[Special:UserLogin|minnäq nimega sis
 'permissionserrorstext-withaction' => 'Sul olõ-õi lubat {{lcfirst:$2}} {{PLURAL:$1|järgmädsel põhjusõl|järgmäidsil põhjuisil}}:',
 'recreate-moveddeleted-warn' => "'''Hoiatus: Sa proovit vahtsõst luvvaq lehte, miä om ärq kistutõt.'''
 
-Kas tahat taad lehte tõtõstõ toimõndaq? Kaeq ka sissekirotust seo lehe ärqkistutamisõ kotsilõ:",
+Märgiq perrä, kas tahat taad lehte tõtõstõ luvvaq. 
+Tan ommaq nätäq seo lehe innembädseq ärqkistutamisõq ja tõistõ paika pandmisõq:",
+'moveddeleted-notice' => 'Seo leht om ärq kistutõt.
+Tan om lehe kistutamiisi ja tõistõ paika pandmiisi nimekiri.',
 'edit-conflict' => 'Samaaignõ toimõndus.',
 
 # Parser/template warnings
 'post-expand-template-inclusion-warning' => "'''Hoiatus:''' Pruugitavidõ näüdüsside maht om pall'o suur.
 Tuuperäst ossa näüdüssit näüdädä-äi.",
 'post-expand-template-inclusion-category' => 'Leheküleq, mil om näüdüsside mahupiir ületet',
+'post-expand-template-argument-warning' => "'''Hoiatus:''' Seo lehe pääl om näüdüs, mil vähämbält üts muutuja om määrät pall'o suurõs.
+Sääntseq muutujaq ommaq vaihõlõ jätedüq.",
+'post-expand-template-argument-category' => 'Leheq, kon om näüdüsside seen vaihõlõjätetüisi muutujit',
 
 # "Undo" feature
 'undo-success' => "Tagasivõtminõ läts' kõrda. Kaeq üle, kas taa om tuu, midä sa tetäq tahtsõt ja pästäq muutusõq.",
@@ -672,8 +718,8 @@ Seletüs: (viim) = lahkominegiq viimätsest kujost,
 (minev) = lahkominegiq minevädsest kujost, ts = väiku (tsill'okõnõ) muutminõ",
 'history-fieldset-title' => 'Kaeq muutmiisi aoluku',
 'history-show-deleted' => 'Õnnõ kistutõduq',
-'histfirst' => 'Edimädseq',
-'histlast' => 'Viimädseq',
+'histfirst' => 'Kõgõ vanõmbaq',
+'histlast' => 'Kõgõ vahtsõmbaq',
 'historysize' => '({{PLURAL:$1|1 bait|$1 baiti}})',
 'historyempty' => '(tühi)',
 
@@ -730,14 +776,14 @@ Lisateedüst või ollaq [{{fullurl:{{#Special:Log}}/suppress|page={{FULLPAGENAME
 'revertmerge' => 'Lüüq jälki lahko',
 
 # Diffs
-'history-title' => '"$1" muutmiisi nimekiri',
+'history-title' => 'Lehekülje "$1" muutmiisi aolugu',
 'lineno' => 'Rida $1:',
 'compareselectedversions' => 'Võrdõlõq valituid kujjõ',
 'editundo' => 'võtaq tagasi',
-'diff-multi' => '(Kujjõ vaihõl {{PLURAL:$1|üts näütämäldä muutminõ|$1 näütämäldä muutmist}}.)',
+'diff-multi' => '(Naidõ kujjõ vaihõl om {{PLURAL:$1|üts toimõndus|$1 kujjo, miä ommaq {{PLURAL:$2|üte pruukja tettüq|$2 esiq pruukja tettüq}}}}.)',
 
 # Search results
-'searchresults' => 'Otsmisõ tulõmusõq',
+'searchresults' => 'Otsmisõ tulõmiq',
 'searchresults-title' => 'Otsmisõ "$1" tulõmiq',
 'titlematches' => "Artiklipäälkir'ost löüt",
 'textmatches' => 'Artiklitekstest löüt',
@@ -748,6 +794,7 @@ Lisateedüst või ollaq [{{fullurl:{{#Special:Log}}/suppress|page={{FULLPAGENAME
 'nextn-title' => '{{PLURAL:$1|Järgmäne tulõmus|Järgmädseq $1 tulõmust}}',
 'shown-title' => 'Näütäq lehe kotsilõ $1 {{PLURAL:$1|tulõmus|tulõmust}}',
 'viewprevnext' => 'Näütäq ($1 {{int:pipe-separator}} $2) ($3).',
+'searchmenu-exists' => "'''Lehekülg päälkiräga \"[[:\$1]]\" om olõman.''' {{PLURAL:\$2|0=|Kaeq ka tõisi otsmistulõmit.}}",
 'searchmenu-new' => "'''Luuq leht päälkiräga \"[[:\$1]]\".'''",
 'searchprofile-articles' => 'Sisuleheq',
 'searchprofile-project' => 'Abi- ja projektileheq',
@@ -825,7 +872,9 @@ Lisateedüst või ollaq [{{fullurl:{{#Special:Log}}/suppress|page={{FULLPAGENAME
 Taa tohe-i ollaq rohkõmb ku $1 {{PLURAL:$1|märk|märki}}.",
 'email' => 'e-posti aadrõs',
 'prefs-help-realname' => "* <strong>Peris nimi</strong> (piä-i kirotama): ku taa teedäq annat, sis pruugitas taad pruukjanime asõmõl lehekülgi tegijide nimekir'on.",
-'prefs-help-email' => 'E-postiaadrõssit piä-i kirotama, a taa lupa tõisil pruukjil sullõ kirotaq ilma su aadrõssit nägemäldäq. Taast om sis kah kassu, ku uma salasõna ärq johtut unõhtama.',
+'prefs-help-email' => 'E-postiaadrõssit piä-i kirotama, a taa lupa sul telliq vahtsõ salasõna, ku uma salasõna ärq johtut unõhtama.',
+'prefs-help-email-others' => 'Nii saavaq ka tõõsõq pruukjaq sullõ kirotaq lingi kaudu su arotuslehe pääl
+ilma, et nä näesiq suq e-posti-aadrõssit.',
 'prefs-help-email-required' => 'E-postiaadrõs piät olõma.',
 
 # User rights
@@ -925,7 +974,7 @@ Taa tohe-i ollaq rohkõmb ku $1 {{PLURAL:$1|märk|märki}}.",
 'rclistfrom' => 'Näütäq muutmiisi kuupääväst $1 pääle',
 'rcshowhideminor' => '$1 väikuq parandusõq',
 'rcshowhidebots' => '$1 robodiq',
-'rcshowhideliu' => '$1 nimega pruukjaq',
+'rcshowhideliu' => '$1 nimega pruukjat',
 'rcshowhideanons' => '$1 nimeldä pruukjaq',
 'rcshowhidepatr' => '$1 kontrolliduq muutmisõq',
 'rcshowhidemine' => '$1 mu toimõndusõq.',
@@ -940,7 +989,7 @@ Taa tohe-i ollaq rohkõmb ku $1 {{PLURAL:$1|märk|märki}}.",
 'number_of_watching_users_pageview' => '[{{PLURAL:$1|$1 perräkaejat|üts perräkaeja}}]',
 'rc_categories' => 'Õnnõ katõgoorijist (eräldedäs märgiga "|")',
 'rc_categories_any' => 'Miä taht',
-'rc-enhanced-expand' => 'Näütäq ütsikasjo (nõud JavaScripti)',
+'rc-enhanced-expand' => 'Näütäq ütsikasjo',
 'rc-enhanced-hide' => "Käkiq ütsikas'aq ärq",
 
 # Recent changes linked
@@ -1047,7 +1096,7 @@ Ku ülekaet teedüstü om sama pilt alguperälidsen suurusõn, sis olõ-i vaia e
 'listfiles_description' => 'Seletüs',
 
 # File description page
-'file-anchor-link' => 'Pilt',
+'file-anchor-link' => 'Teedüstü',
 'filehist' => 'Teedüstü aolugu',
 'filehist-help' => "Klõpsaq kuupäävä/kelläao pääl, et nätäq määne taa teedüstü sis oll'.",
 'filehist-deleteall' => 'kistudaq kõik ärq',
@@ -1172,6 +1221,7 @@ Ku ülekaet teedüstü om sama pilt alguperälidsen suurusõn, sis olõ-i vaia e
 'protectedpages' => 'Kaidsõduq leheq',
 'protectedpagesempty' => 'Olõ-i kaidsõtuid lehti.',
 'listusers' => 'Pruukjaq',
+'usercreated' => '{{GENDER:$3|Luud}} $1 kell $2',
 'newpages' => 'Vahtsõq leheküleq',
 'newpages-username' => 'Pruukjanimi:',
 'ancientpages' => 'Kõgõ vanõmbaq leheküleq',
@@ -1223,6 +1273,7 @@ Also see [[Special:WantedCategories|wanted categories]].',
 # Special:LinkSearch
 'linksearch' => 'Välislingiq',
 'linksearch-ok' => 'Otsminõ',
+'linksearch-line' => '$1 on lingit lehekülelt $2',
 
 # Special:ListUsers
 'listusersfrom' => 'Näütäq pruukjit alostõn:',
@@ -1323,6 +1374,7 @@ As\'a kotsilõ mano kaiaq ja küssü saat lehe päält: {{canonicalurl:{{MediaWi
 'confirmdeletetext' => 'Sa kistutat teedüskogost periselt ärq lehe vai pildi üten kõgõ timä aoluuga.
 Kinnüdäq, et sa tahat tuud tõtõstõ tetäq, et sa saat arvo, miä tuust tullaq või ja et tuu, miä sa tiit, klapis [[{{MediaWiki:Policy-url}}|sisekõrraga]].',
 'actioncomplete' => 'Tallitus valmis',
+'actionfailed' => 'Tallitus lää-äs kõrda',
 'deletedtext' => '"$1" om ärq kistutõt.
 Perämäidsi kistutuisi nimekirjä näet siist: $2.',
 'dellogpage' => 'Kistutõduq leheküleq',
@@ -1426,25 +1478,28 @@ Perämäidsi kistutuisi ja tagasitegemiisi saat kaiaq [[Special:Log/delete|kistu
 # Namespace form on various pages
 'namespace' => 'Nimeruum:',
 'invert' => 'Näütäq kõiki päält validu nimeruumi',
-'blanknamespace' => '(Artikliq)',
+'blanknamespace' => '(artikliq)',
 
 # Contributions
-'contributions' => 'Pruukja kirotusõq',
+'contributions' => '{{GENDER:$1|Pruukja}} toimõndusõq',
 'contributions-title' => 'Pruukja $1 toimõndusõq',
 'mycontris' => 'Hindä kirotusõq',
-'contribsub2' => 'Pruukja "$1 ($2)" kirotusõq',
+'contribsub2' => 'Pruukja {{GENDER:$3|$1}} ($2) toimõndusõq',
 'nocontribs' => 'Sääntsit muutmiisi es lövväq.',
-'uctop' => '(kõgõ vahtsõmb)',
+'uctop' => '(parhillanõ)',
 'month' => 'Alostõn kuust (ja varrampa):',
 'year' => 'Alostõn aastagast (ja varrampa):',
 
 'sp-contributions-newbies' => 'Näütäq õnnõ vahtsidõ pruukjidõ toimõnduisi',
 'sp-contributions-newbies-sub' => 'Vahtsidõ pruukjidõ toimõndusõq',
 'sp-contributions-blocklog' => 'Kinniqpidämisnimekiri',
+'sp-contributions-uploads' => 'üleslaatmisõq',
+'sp-contributions-logs' => 'muutmisnimekiräq',
 'sp-contributions-talk' => 'arotus',
 'sp-contributions-userrights' => 'Pruukja õiguisi muutminõ',
 'sp-contributions-search' => 'Otsiq muutmiisi',
 'sp-contributions-username' => 'Puutri võrgoaadrõs vai pruukjanimi:',
+'sp-contributions-toponly' => 'Näütäq õnnõ kõgõ vahtsõmbit toimõnduisi',
 'sp-contributions-submit' => 'Otsiq',
 
 # What links here
@@ -1456,13 +1511,14 @@ Perämäidsi kistutuisi ja tagasitegemiisi saat kaiaq [[Special:Log/delete|kistu
 'nolinkshere-ns' => "Valitun nimeruumin näütä-i ütegi lehe päält linke lehe '''[[:$1]]''' pääle.",
 'isredirect' => 'ümbresaatmislehekülg',
 'istemplate' => 'pruugit näüdüssen',
-'isimage' => 'pildilink',
+'isimage' => 'teedüstülink',
 'whatlinkshere-prev' => '← {{PLURAL:$1|mineväne leht|$1 mineväst lehte}}',
 'whatlinkshere-next' => '{{PLURAL:$1|mineväne leht|$1 mineväst lehte}} →',
 'whatlinkshere-links' => '← lingiq',
 'whatlinkshere-hideredirs' => '$1 ümbresaatmisõq',
 'whatlinkshere-hidetrans' => '$1 näüdüsses pruukmisõq',
 'whatlinkshere-hidelinks' => '$1 lingiq',
+'whatlinkshere-hideimages' => 'Teedüstülingiq ($1)',
 'whatlinkshere-filters' => 'Sõglaq',
 
 # Block/unblock
@@ -1513,7 +1569,7 @@ Perämäidsi kistutuisi ja tagasitegemiisi saat kaiaq [[Special:Log/delete|kistu
 'blocklink' => 'piäq kinniq',
 'unblocklink' => 'võtaq kinniqpidämine maaha',
 'change-blocklink' => 'muudaq kinniqpidämist',
-'contribslink' => 'kirotusõq',
+'contribslink' => 'toimõndusõq',
 'autoblocker' => 'Olõt automaatsõhe kinniq peet, selle et jaat puutri võrgoaadrõssit pruukjaga $1. Kinniqpidämise põhjus: $2.',
 'blocklogpage' => 'Kinniqpidämiisi nimekiri',
 'blocklogentry' => 'pidi kinniq pruukja vai puutri võrgoaadrõsi "[[$1]]". Kinniqpidämise tähtaig $2 $3',
@@ -1787,7 +1843,7 @@ Kokkovõttõria pääle või kirotaq tagasivõtmisõ põhjusõ.',
 'file-info-size' => '$1 × $2 pikslit, $3, MIME-tüüp: $4',
 'file-nohires' => 'Taast terävämpä pilti olõ-i saiaq.',
 'svg-long-desc' => 'SVG-teedüstü, põhisuurus $1 × $2 pikslit, teedüstü suurus $3',
-'show-big-image' => 'Täüsterräv kujo',
+'show-big-image' => 'Algteedüstü',
 
 # Special:NewFiles
 'newimages' => 'Vahtsõq pildiq',
@@ -1808,7 +1864,7 @@ Kokkovõttõria pääle või kirotaq tagasivõtmisõ põhjusõ.',
 'metadata-help' => 'Seon teedüstün om lisateedüst, miä om arvadaq peri pildinudsijast, digikaamõrast vai pilditoimõndusprogrammist. Ku teedüstüt om peräst timä tegemist muudõt, sis pruugi-i taa teedüs inämb õigõ ollaq.',
 'metadata-expand' => 'Näütäq kõiki sisuseletüisi',
 'metadata-collapse' => 'Näütäq õnnõ tähtsämbit sisuseletüisi',
-'metadata-fields' => 'Naaq riaq ommaq nätäq pildilehe pääl, ku sisuseletüse tapõl om tühi.
+'metadata-fields' => 'Naid pildi metateedüse väljo näüdätäs pildi seletüslehe vähändedün kahusõn. Ülejäänüq teedüs om vaikimiisi käkit.
 * make
 * model
 * datetimeoriginal
@@ -1821,6 +1877,12 @@ Kokkovõttõria pääle või kirotaq tagasivõtmisõ põhjusõ.',
 * imagedescription
 * gpslatitude
 * gpslongitude
+* gpsaltitude
+* artist
+* copyright
+* imagedescription
+* gpslatitude
+* gpslongitude
 * gpsaltitude',
 
 # Exif tags
@@ -2156,6 +2218,9 @@ Prooviq harilikku kaehust.',
 'watchlisttools-edit' => 'Kaeq ja toimõndaq perräkaemisnimekirjä',
 'watchlisttools-raw' => 'Toimõndaq lätteteedüstüt',
 
+# Core parser functions
+'duplicate-defaultsort' => '\'\'\'Hoiatus:\'\'\' Sortmisvõti "$2" tühistäs ärq innembädse sortmisvõtmõ "$1".',
+
 # Special:Version
 'version' => 'Kujo',
 'version-version' => '(Kujo $1)',
@@ -2181,6 +2246,19 @@ Prooviq harilikku kaehust.',
 'specialpages-group-wiki' => 'Vikiteedüseq ja tüüriistaq',
 'specialpages-group-redirects' => 'Ümbrenäütämistallitusleheq',
 
+# External image whitelist
+'external_image_whitelist' => '  #Jätäq seo rida muutmalda kujo pääle<pre>
+#Panõq regulaaravaldusõ osaq (õnnõ //-märke vaihõl ollõv jago) allapoolõ
+#Naaq pandasõq vastama vikivälitside pilte internetiaadrõssidõga
+#Nuuq, miä vastasõq, näüdätäseq ku pildiq, muido näüdätäs õnnõ pildi link
+#Märgiga # päälenakkajaq riaq ommaq kommõntaariq
+#Seo tii-i vaiht suuril ja väikeisil tähil
+
+#Panõq kõik regulaaravaldusq osaq seo joonõ kotsilõ. Jätäq seo rida muutmalda</pre>',
+
+# Special:Tags
+'tag-filter' => '[[Special:Tags|Märkmisfiltri]]:',
+
 # New logging system
 'rightsnone' => '(olõ-i õiguisi)',
 
index 76becba..9f6032c 100644 (file)
@@ -2139,7 +2139,7 @@ $1',
 'nviews' => '$1次浏览',
 'nimagelinks' => '用于$1个页面中',
 'ntransclusions' => '用于$1个页面中',
-'specialpage-empty' => 'æ\97 è¯¥æ\8a¥å\91\8aç\9a\84结果。',
+'specialpage-empty' => 'æ­¤æ\8a¥å\91\8aæ\97 结果。',
 'lonelypages' => '孤立页面',
 'lonelypagestext' => '以下页面没有被{{SITENAME}}的其它页面链接或包含。',
 'uncategorizedpages' => '未归类页面',
index 80a31bc..2e6b110 100644 (file)
@@ -131,6 +131,7 @@ $wgIgnoredMessages = array(
        'signupstart',
        'signupend',
        'signupend-https',
+       'emailsender',
        'sitenotice',
        'sitesubtitle',
        'sitetitle',
index 2af682e..b6af033 100644 (file)
@@ -550,6 +550,7 @@ $wgMessageStructure = array(
                'invalidemailaddress',
                'cannotchangeemail',
                'emaildisabled',
+               'emailsender',
                'accountcreated',
                'accountcreatedtext',
                'createaccount-title',
@@ -1808,6 +1809,7 @@ $wgMessageStructure = array(
                'protectedpages-indef',
                'protectedpages-summary',
                'protectedpages-cascade',
+               'protectedpages-noredirect',
                'protectedpagesempty',
                'protectedtitles',
                'protectedtitles-summary',
@@ -3903,6 +3905,7 @@ $wgMessageStructure = array(
                'api-error-overwrite',
                'api-error-stashfailed',
                'api-error-publishfailed',
+               'api-error-stasherror',
                'api-error-timeout',
                'api-error-unclassified',
                'api-error-unknown-code',
index 5a95dc5..f35782b 100644 (file)
                /**
                 * Checks the current browser against a support map object.
                 *
+                * Version numbers passed as numeric values will be compared like numbers (1.2 > 1.11).
+                * Version numbers passed as string values will be compared using a simple component-wise
+                * algorithm, similar to PHP's version_compare ('1.2' < '1.11').
+                *
                 * A browser map is in the following format:
                 * {
                 *   // Multiple rules with configurable operators
                test: function ( map, profile, exactMatchOnly ) {
                        /*jshint evil: true */
 
-                       var conditions, dir, i, op, val;
+                       var conditions, dir, i, op, val, j, pieceVersion, pieceVal, compare;
                        profile = $.isPlainObject( profile ) ? profile : $.client.profile();
                        if ( map.ltr && map.rtl ) {
                                dir = $( 'body' ).is( '.rtl' ) ? 'rtl' : 'ltr';
                                op = conditions[i][0];
                                val = conditions[i][1];
                                if ( typeof val === 'string' ) {
-                                       if ( !( eval( 'profile.version' + op + '"' + val + '"' ) ) ) {
+                                       // Perform a component-wise comparison of versions, similar to PHP's version_compare
+                                       // but simpler. '1.11' is larger than '1.2'.
+                                       pieceVersion = profile.version.toString().split( '.' );
+                                       pieceVal = val.split( '.' );
+                                       // Extend with zeroes to equal length
+                                       while ( pieceVersion.length < pieceVal.length ) {
+                                               pieceVersion.push( '0' );
+                                       }
+                                       while ( pieceVal.length < pieceVersion.length ) {
+                                               pieceVal.push( '0' );
+                                       }
+                                       // Compare components
+                                       compare = 0;
+                                       for ( j = 0; j < pieceVersion.length; j++ ) {
+                                               if ( Number( pieceVersion[j] ) < Number( pieceVal[j] ) ) {
+                                                       compare = -1;
+                                                       break;
+                                               } else if ( Number( pieceVersion[j] ) > Number( pieceVal[j] ) ) {
+                                                       compare = 1;
+                                                       break;
+                                               }
+                                       }
+                                       // compare will be -1, 0 or 1, depending on comparison result
+                                       if ( !( eval( '' + compare + op + '0' ) ) ) {
                                                return false;
                                        }
                                } else if ( typeof val === 'number' ) {
index 441bc91..3def37c 100644 (file)
@@ -1,7 +1,7 @@
-/* This is cldrpluralparser 1.0, ported to MediaWiki ResourceLoader */
+/* This is CLDRPluralRuleParser v1.1, ported to MediaWiki ResourceLoader */
 
 /**
-* cldrpluralparser.js
+* CLDRPluralRuleParser.js
 * A parser engine for CLDR plural rules.
 *
 * Copyright 2012 GPLV3+, Santhosh Thottingal
 * @author Amir Aharoni
 */
 
+( function ( mw ) {
 /**
  * Evaluates a plural rule in CLDR syntax for a number
- * @param rule
- * @param number
- * @return true|false|null
+ * @param {string} rule
+ * @param {integer} number
+ * @return {boolean} true if evaluation passed, false if evaluation failed.
  */
-( function( mw ) {
 
 function pluralRuleParser(rule, number) {
        /*
        Syntax: see http://unicode.org/reports/tr35/#Language_Plural_Rules
        -----------------------------------------------------------------
-
        condition     = and_condition ('or' and_condition)*
+               ('@integer' samples)?
+               ('@decimal' samples)?
        and_condition = relation ('and' relation)*
-       relation      = is_relation | in_relation | within_relation | 'n' <EOL>
+       relation      = is_relation | in_relation | within_relation
        is_relation   = expr 'is' ('not')? value
-       in_relation   = expr ('not')? 'in' range_list
+       in_relation   = expr (('not')? 'in' | '=' | '!=') range_list
        within_relation = expr ('not')? 'within' range_list
-       expr          = 'n' ('mod' value)?
+       expr          = operand (('mod' | '%') value)?
+       operand       = 'n' | 'i' | 'f' | 't' | 'v' | 'w'
        range_list    = (range | value) (',' range_list)*
        value         = digit+
        digit         = 0|1|2|3|4|5|6|7|8|9
        range         = value'..'value
-
+       samples       = sampleRange (',' sampleRange)* (',' ('…'|'...'))?
+       sampleRange   = decimalValue '~' decimalValue
+       decimalValue  = value ('.' value)?
        */
+
+       // we don't evaluate the samples section of the rule. Ignore it.
+       rule = rule.split('@')[0].trim();
+
+       if (!rule.length) {
+               // empty rule or 'other' rule.
+               return true;
+       }
        // Indicates current position in the rule as we parse through it.
        // Shared among all parsing functions below.
-       var pos = 0;
-
-       var whitespace = makeRegexParser(/^\s+/);
-       var digits = makeRegexParser(/^\d+/);
-
-       var _n_ = makeStringParser('n');
-       var _is_ = makeStringParser('is');
-       var _mod_ = makeStringParser('mod');
-       var _not_ = makeStringParser('not');
-       var _in_ = makeStringParser('in');
-       var _within_ = makeStringParser('within');
-       var _range_ = makeStringParser('..');
-       var _comma_ = makeStringParser(',');
-       var _or_ = makeStringParser('or');
-       var _and_ = makeStringParser('and');
+       var pos = 0,
+               operand,
+               expression,
+               relation,
+               result,
+               whitespace = makeRegexParser(/^\s+/),
+               value = makeRegexParser(/^\d+/),
+               _n_ = makeStringParser('n'),
+               _i_ = makeStringParser('i'),
+               _f_ = makeStringParser('f'),
+               _t_ = makeStringParser('t'),
+               _v_ = makeStringParser('v'),
+               _w_ = makeStringParser('w'),
+               _is_ = makeStringParser('is'),
+               _isnot_ = makeStringParser('is not'),
+               _isnot_sign_ = makeStringParser('!='),
+               _equal_ = makeStringParser('='),
+               _mod_ = makeStringParser('mod'),
+               _percent_ = makeStringParser('%'),
+               _not_ = makeStringParser('not'),
+               _in_ = makeStringParser('in'),
+               _within_ = makeStringParser('within'),
+               _range_ = makeStringParser('..'),
+               _comma_ = makeStringParser(','),
+               _or_ = makeStringParser('or'),
+               _and_ = makeStringParser('and');
 
        function debug() {
-               /* console.log.apply(console, arguments);*/
+               // console.log.apply(console, arguments);
        }
 
        debug('pluralRuleParser', rule, number);
 
        // Try parsers until one works, if none work return null
+
        function choice(parserSyntax) {
-               return function () {
+               return function() {
                        for (var i = 0; i < parserSyntax.length; i++) {
                                var result = parserSyntax[i]();
                                if (result !== null) {
@@ -79,6 +103,7 @@ function pluralRuleParser(rule, number) {
        // Try several parserSyntax-es in a row.
        // All must succeed; otherwise, return null.
        // This is the only eager one.
+
        function sequence(parserSyntax) {
                var originalPos = pos;
                var result = [];
@@ -95,8 +120,9 @@ function pluralRuleParser(rule, number) {
 
        // Run the same parser over and over until it fails.
        // Must succeed a minimum of n times; otherwise, return null.
+
        function nOrMore(n, p) {
-               return function () {
+               return function() {
                        var originalPos = pos;
                        var result = [];
                        var parsed = p();
@@ -113,21 +139,21 @@ function pluralRuleParser(rule, number) {
        }
 
        // Helpers -- just make parserSyntax out of simpler JS builtin types
-
        function makeStringParser(s) {
                var len = s.length;
-               return function () {
+               return function() {
                        var result = null;
                        if (rule.substr(pos, len) === s) {
                                result = s;
                                pos += len;
                        }
+
                        return result;
                };
        }
 
        function makeRegexParser(regex) {
-               return function () {
+               return function() {
                        var matches = rule.substr(pos).match(regex);
                        if (matches === null) {
                                return null;
@@ -137,62 +163,166 @@ function pluralRuleParser(rule, number) {
                };
        }
 
+       /*
+        * integer digits of n.
+        */
+       function i() {
+               var result = _i_();
+               if (result === null) {
+                       debug(' -- failed i', parseInt(number, 10));
+                       return result;
+               }
+               result = parseInt(number, 10);
+               debug(' -- passed i ', result);
+               return result;
+       }
+
+       /*
+        * absolute value of the source number (integer and decimals).
+        */
        function n() {
                var result = _n_();
                if (result === null) {
-                       debug(" -- failed n");
+                       debug(' -- failed n ', number);
                        return result;
                }
-               result = parseInt(number, 10);
-               debug(" -- passed n ", result);
+               result = parseFloat(number, 10);
+               debug(' -- passed n ', result);
+               return result;
+       }
+
+       /*
+        * visible fractional digits in n, with trailing zeros.
+        */
+       function f() {
+               var result = _f_();
+               if (result === null) {
+                       debug(' -- failed f ', number);
+                       return result;
+               }
+               result = (number + '.').split('.')[1] || 0;
+               debug(' -- passed f ', result);
+               return result;
+       }
+
+       /*
+        * visible fractional digits in n, without trailing zeros.
+        */
+       function t() {
+               var result = _t_();
+               if (result === null) {
+                       debug(' -- failed t ', number);
+                       return result;
+               }
+               result = (number + '.').split('.')[1].replace(/0$/, '') || 0;
+               debug(' -- passed t ', result);
+               return result;
+       }
+
+       /*
+        * number of visible fraction digits in n, with trailing zeros.
+        */
+       function v() {
+               var result = _v_();
+               if (result === null) {
+                       debug(' -- failed v ', number);
+                       return result;
+               }
+               result = (number + '.').split('.')[1].length || 0;
+               debug(' -- passed v ', result);
+               return result;
+       }
+
+       /*
+        * number of visible fraction digits in n, without trailing zeros.
+        */
+       function w() {
+               var result = _w_();
+               if (result === null) {
+                       debug(' -- failed w ', number);
+                       return result;
+               }
+               result = (number + '.').split('.')[1].replace(/0$/, '').length || 0;
+               debug(' -- passed w ', result);
                return result;
        }
 
-       var expression = choice([mod, n]);
+       // operand       = 'n' | 'i' | 'f' | 't' | 'v' | 'w'
+       operand = choice([n, i, f, t, v, w]);
+
+       // expr          = operand (('mod' | '%') value)?
+       expression = choice([mod, operand]);
 
        function mod() {
-               var result = sequence([n, whitespace, _mod_, whitespace, digits]);
+               var result = sequence([operand, whitespace, choice([_mod_, _percent_]), whitespace, value]);
                if (result === null) {
-                       debug(" -- failed mod");
+                       debug(' -- failed mod');
                        return null;
                }
-               debug(" -- passed mod");
+               debug(' -- passed ' + parseInt(result[0], 10) + ' ' + result[2] + ' ' + parseInt(result[4], 10));
                return parseInt(result[0], 10) % parseInt(result[4], 10);
        }
 
        function not() {
                var result = sequence([whitespace, _not_]);
                if (result === null) {
-                       debug(" -- failed not");
+                       debug(' -- failed not');
                        return null;
-               } else {
-                       return result[1];
                }
+
+               return result[1];
        }
 
+       // is_relation   = expr 'is' ('not')? value
        function is() {
-               var result = sequence([expression, whitespace, _is_, nOrMore(0, not), whitespace, digits]);
+               var result = sequence([expression, whitespace, choice([_is_]), whitespace, value]);
                if (result !== null) {
-                       debug(" -- passed is");
-                       if (result[3][0] === 'not') {
-                               return result[0] !== parseInt(result[5], 10);
-                       } else {
-                               return result[0] === parseInt(result[5], 10);
+                       debug(' -- passed is : ' + result[0] + ' == ' + parseInt(result[4], 10));
+                       return result[0] === parseInt(result[4], 10);
+               }
+               debug(' -- failed is');
+               return null;
+       }
+
+       // is_relation   = expr 'is' ('not')? value
+       function isnot() {
+               var result = sequence([expression, whitespace, choice([_isnot_, _isnot_sign_]), whitespace, value]);
+               if (result !== null) {
+                       debug(' -- passed isnot: ' + result[0] + ' != ' + parseInt(result[4], 10));
+                       return result[0] !== parseInt(result[4], 10);
+               }
+               debug(' -- failed isnot');
+               return null;
+       }
+
+       function not_in() {
+               var result = sequence([expression, whitespace, _isnot_sign_, whitespace, rangeList]);
+               if (result !== null) {
+                       debug(' -- passed not_in: ' + result[0] + ' != ' + result[4]);
+                       var range_list = result[4];
+                       for (var i = 0; i < range_list.length; i++) {
+                               if (parseInt(range_list[i], 10) === parseInt(result[0], 10)) {
+                                       return false;
+                               }
                        }
+                       return true;
                }
-               debug(" -- failed is");
+               debug(' -- failed not_in');
                return null;
        }
 
+       // range_list    = (range | value) (',' range_list)*
        function rangeList() {
-               // range_list    = (range | value) (',' range_list)*
-               var result = sequence([choice([range, digits]), nOrMore(0, rangeTail)]);
+               var result = sequence([choice([range, value]), nOrMore(0, rangeTail)]);
                var resultList = [];
                if (result !== null) {
-                       resultList = resultList.concat(result[0], result[1][0]);
+                       resultList = resultList.concat(result[0]);
+                       if (result[1][0]) {
+                               resultList = resultList.concat(result[1][0]);
+                       }
                        return resultList;
                }
-               debug(" -- failed rangeList");
+               debug(' -- failed rangeList');
                return null;
        }
 
@@ -202,111 +332,141 @@ function pluralRuleParser(rule, number) {
                if (result !== null) {
                        return result[1];
                }
-               debug(" -- failed rangeTail");
+               debug(' -- failed rangeTail');
                return null;
        }
 
+       // range         = value'..'value
+
        function range() {
                var i;
-               var result = sequence([digits, _range_, digits]);
+               var result = sequence([value, _range_, value]);
                if (result !== null) {
-                       debug(" -- passed range");
+                       debug(' -- passed range');
                        var array = [];
                        var left = parseInt(result[0], 10);
                        var right = parseInt(result[2], 10);
-                       for ( i = left; i <= right; i++) {
+                       for (i = left; i <= right; i++) {
                                array.push(i);
                        }
                        return array;
                }
-               debug(" -- failed range");
+               debug(' -- failed range');
                return null;
        }
 
        function _in() {
                // in_relation   = expr ('not')? 'in' range_list
-               var result = sequence([expression, nOrMore(0, not), whitespace, _in_, whitespace, rangeList]);
+               var result = sequence([expression, nOrMore(0, not), whitespace, choice([_in_, _equal_]), whitespace, rangeList]);
                if (result !== null) {
-                       debug(" -- passed _in");
+                       debug(' -- passed _in:' + result);
                        var range_list = result[5];
                        for (var i = 0; i < range_list.length; i++) {
-                               if (parseInt(range_list[i], 10) === result[0]) {
+                               if (parseInt(range_list[i], 10) === parseInt(result[0], 10)) {
                                        return (result[1][0] !== 'not');
                                }
                        }
                        return (result[1][0] === 'not');
                }
-               debug(" -- failed _in ");
+               debug(' -- failed _in ');
                return null;
        }
 
+       /*
+        * The difference between in and within is that in only includes integers in the specified range,
+        * while within includes all values.
+        */
+
        function within() {
-               var result = sequence([expression, whitespace, _within_, whitespace, rangeList]);
+               // within_relation = expr ('not')? 'within' range_list
+               var result = sequence([expression, nOrMore(0, not), whitespace, _within_, whitespace, rangeList]);
                if (result !== null) {
-                       debug(" -- passed within ");
-                       var range_list = result[4];
-                       return (parseInt( range_list[0],10 )<= result[0] && result[0] <= parseInt( range_list[1], 10));
+                       debug(' -- passed within');
+                       var range_list = result[5];
+                       if ((result[0] >= parseInt(range_list[0], 10)) &&
+                               (result[0] < parseInt(range_list[range_list.length - 1], 10))) {
+                               return (result[1][0] !== 'not');
+                       }
+                       return (result[1][0] === 'not');
                }
-               debug(" -- failed within ");
+               debug(' -- failed within ');
                return null;
        }
 
+       // relation      = is_relation | in_relation | within_relation
+       relation = choice([is, not_in, isnot, _in, within]);
 
-       var relation = choice([is, _in, within]);
-
+       // and_condition = relation ('and' relation)*
        function and() {
-               var result = sequence([relation, whitespace, _and_, whitespace, condition]);
+               var result = sequence([relation, nOrMore(0, andTail)]);
                if (result) {
-                       debug(" -- passed and");
-                       return result[0] && result[4];
+                       if (!result[0]) {
+                               return false;
+                       }
+                       for (var i = 0; i < result[1].length; i++) {
+                               if (!result[1][i]) {
+                                       return false;
+                               }
+                       }
+                       return true;
                }
-               debug(" -- failed and");
+               debug(' -- failed and');
                return null;
        }
 
-       function or() {
-               var result = sequence([relation, whitespace, _or_, whitespace, condition]);
-               if (result) {
-                       debug(" -- passed or");
-                       return result[0] || result[4];
+       // ('and' relation)*
+       function andTail() {
+               var result = sequence([whitespace, _and_, whitespace, relation]);
+               if (result !== null) {
+                       debug(' -- passed andTail' + result);
+                       return result[3];
                }
-               debug(" -- failed or");
+               debug(' -- failed andTail');
                return null;
-       }
 
-       var condition = choice([and, or, relation]);
+       }
+       //  ('or' and_condition)*
+       function orTail() {
+               var result = sequence([whitespace, _or_, whitespace, and]);
+               if (result !== null) {
+                       debug(' -- passed orTail: ' + result[3]);
+                       return result[3];
+               }
+               debug(' -- failed orTail');
+               return null;
 
-       function isInt(n) {
-               return parseFloat(n) % 1 === 0;
        }
 
+       // condition     = and_condition ('or' and_condition)*
+       function condition() {
+               var result = sequence([and, nOrMore(0, orTail)]);
+               if (result) {
+                       for (var i = 0; i < result[1].length; i++) {
+                               if (result[1][i]) {
+                                       return true;
+                               }
+                       }
+                       return result[0];
 
-       function start() {
-               if (!isInt(number)) {
-                       return false;
                }
-               var result = condition();
-               return result;
+               return false;
        }
 
-
-       var result = start();
-
+       result = condition();
        /*
         * For success, the pos must have gotten to the end of the rule
         * and returned a non-null.
         * n.b. This is part of language infrastructure, so we do not throw an internationalizable message.
         */
-       if (result === null || pos !== rule.length) {
-               // throw new Error("Parse error at position " + pos.toString() + " in input: " + rule + " result is " + result);
+       if (result === null) {
+               throw new Error('Parse error at position ' + pos.toString() + ' for rule: ' + rule);
        }
 
-       return result;
-}
+       if (pos !== rule.length) {
+               debug('Warning: Rule not parsed completely. Parser stopped at ' + rule.substr(0, pos) + ' for rule: ' + rule);
+       }
 
-/* For module loaders, e.g. NodeJS, NPM */
-if (typeof module !== 'undefined' && module.exports) {
-       module.exports = pluralRuleParser;
+       return result;
 }
 
 /* pluralRuleParser ends here */
index 310294a..b068915 100644 (file)
@@ -1176,14 +1176,15 @@ table.floatleft {
        display: none;
 }
 
-/* For developpers */
+/* For developers */
 .xdebug-error {
        position: absolute;
        z-index: 99;
 }
 
 .mw-editsection,
-.toctoggle {
+.toctoggle,
+#jump-to-nav {
        -moz-user-select: none;
        -webkit-user-select: none;
        -ms-user-select: none;
diff --git a/tests/phpunit/includes/RunningStatTest.php b/tests/phpunit/includes/RunningStatTest.php
deleted file mode 100644 (file)
index e24c088..0000000
+++ /dev/null
@@ -1,81 +0,0 @@
-<?php
-/**
- * PHP Unit tests for RunningStat class.
- * @covers RunningStat
- */
-class RunningStatTest extends MediaWikiTestCase {
-
-       public $points = array(
-               49.7168, 74.3804,  7.0115, 96.5769, 34.9458,
-               36.9947, 33.8926, 89.0774, 23.7745, 73.5154,
-               86.1322, 53.2124, 16.2046, 73.5130, 10.4209,
-               42.7299, 49.3330, 47.0215, 34.9950, 18.2914,
-       );
-
-       /**
-        * Verify that the statistical moments and extrema computed by RunningStat
-        * match expected values.
-        * @covers RunningStat::push
-        * @covers RunningStat::count
-        * @covers RunningStat::getMean
-        * @covers RunningStat::getVariance
-        * @covers RunningStat::getStdDev
-        */
-       public function testRunningStatAccuracy() {
-               $rstat = new RunningStat();
-               foreach( $this->points as $point ) {
-                       $rstat->push( $point );
-               }
-
-               $mean = array_sum( $this->points ) / count( $this->points );
-               $variance = array_sum( array_map( function ( $x ) use ( $mean ) {
-                       return pow( $mean - $x, 2 );
-               }, $this->points ) ) / ( count( $rstat ) - 1 );
-               $stddev = sqrt( $variance );
-               $min = min( $this->points );
-               $max = max( $this->points );
-
-               $this->assertEquals( count( $rstat ), count( $this->points ) );
-               $this->assertEquals( $rstat->min, min( $this->points ) );
-               $this->assertEquals( $rstat->max, max( $this->points ) );
-               $this->assertEquals( $rstat->getMean(), $mean );
-               $this->assertEquals( $rstat->getVariance(), $variance );
-               $this->assertEquals( $rstat->getStdDev(), $stddev );
-       }
-
-       /**
-        * When one RunningStat instance is merged into another, the state of the
-        * target RunningInstance should have the state that it would have had if
-        * all the data had been accumulated by it alone.
-        * @covers RunningStat::merge
-        * @covers RunningStat::count
-        */
-       public function testRunningStatMerge() {
-               $expected = new RunningStat();
-
-               foreach( $this->points as $point ) {
-                       $expected->push( $point );
-               }
-
-               // Split the data into two sets
-               $sets = array_chunk( $this->points, floor( count( $this->points ) / 2 ) );
-
-               // Accumulate the first half into one RunningStat object
-               $first = new RunningStat();
-               foreach( $sets[0] as $point ) {
-                       $first->push( $point );
-               }
-
-               // Accumulate the second half into another RunningStat object
-               $second = new RunningStat();
-               foreach( $sets[1] as $point ) {
-                       $second->push( $point );
-               }
-
-               // Merge the second RunningStat object into the first
-               $first->merge( $second );
-
-               $this->assertEquals( count( $first ), count( $this->points ) );
-               $this->assertEquals( $first, $expected );
-       }
-}
index f64a784..4c59f47 100644 (file)
  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
  * http://www.gnu.org/copyleft/gpl.html
  *
+ * @group Database
  * @file
  * @author Antoine Musso
  * @copyright © 2013 Antoine Musso
  * @copyright © 2013 Wikimedia Foundation Inc.
  */
-
-class FakeLBFactory extends LBFactory {
-       function __construct( $conf ) {}
-       function newMainLB( $wiki = false ) {}
-       function getMainLB( $wiki = false ) {}
-       function newExternalLB( $cluster, $wiki = false ) {}
-       function &getExternalLB( $cluster, $wiki = false ) {}
-       function forEachLB( $callback, $params = array() ) {}
-}
-
 class LBFactoryTest extends MediaWikiTestCase {
 
-       function setup() {
-               parent::setup();
-               FakeLBFactory::destroyInstance();
-       }
-
        /**
-        * @dataProvider provideDeprecatedLbfactoryClasses
+        * @dataProvider getLBFactoryClassProvider
         */
-       function testLbfactoryClassBackcompatibility( $expected, $deprecated ) {
+       public function testGetLBFactoryClass( $expected, $deprecated ) {
                $mockDB = $this->getMockBuilder( 'DatabaseMysql' )
-                       -> disableOriginalConstructor()
+                       ->disableOriginalConstructor()
                        ->getMock();
-               $this->setMwGlobals( 'wgLBFactoryConf',
-                       array(
-                               'class'          => $deprecated,
-                               'connection'     => $mockDB,
-                               # Various other parameters required:
-                               'sectionsByDB'   => array(),
-                               'sectionLoads'   => array(),
-                               'serverTemplate' => array(),
-                       )
-               );
 
-               global $wgLBFactoryConf;
-               $this->assertArrayHasKey( 'class', $wgLBFactoryConf );
-               $this->assertEquals( $wgLBFactoryConf['class'], $deprecated );
+               $config = array(
+                       'class'          => $deprecated,
+                       'connection'     => $mockDB,
+                       # Various other parameters required:
+                       'sectionsByDB'   => array(),
+                       'sectionLoads'   => array(),
+                       'serverTemplate' => array(),
+               );
 
-               # The point of this test is to call a deprecated interface and make
-               # sure it keeps back compatibility, so skip the deprecation warning.
                $this->hideDeprecated( '$wgLBFactoryConf must be updated. See RELEASE-NOTES for details' );
-               $lbfactory = FakeLBFactory::singleton();
-               $this->assertInstanceOf( $expected, $lbfactory,
-                       "LBFactory passed $deprecated should yield the new class $expected" );
+               $result = LBFactory::getLBFactoryClass( $config );
+
+               $this->assertEquals( $expected, $result );
        }
 
-       function provideDeprecatedLbfactoryClasses() {
+       public function getLBFactoryClassProvider() {
                return array(
                        # Format: new class, old class
                        array( 'LBFactorySimple', 'LBFactory_Simple' ),
diff --git a/tests/phpunit/includes/libs/MWMessagePackTest.php b/tests/phpunit/includes/libs/MWMessagePackTest.php
new file mode 100644 (file)
index 0000000..b99ef86
--- /dev/null
@@ -0,0 +1,70 @@
+<?php
+/**
+ * PHP Unit tests for MWMessagePack
+ * @covers MWMessagePack
+ */
+class MWMessagePackTest extends MediaWikiTestCase {
+
+       /**
+        * Provides test cases for MWMessagePackTest::testMessagePack
+        *
+        * Returns an array of test cases. Each case is an array of (type, value,
+        * expected encoding as hex string). The expected values were generated
+        * using <https://github.com/msgpack/msgpack-php>, which includes a
+        * serialization function.
+        */
+       public function provider() {
+               return array(
+                       array( 'nil', null, 'c0' ),
+                       array( 'bool', true, 'c3' ),
+                       array( 'bool', false, 'c2' ),
+                       array( 'positive fixnum', 0, '00' ),
+                       array( 'positive fixnum', 1, '01' ),
+                       array( 'positive fixnum', 5, '05' ),
+                       array( 'positive fixnum', 35, '23' ),
+                       array( 'uint 8', 128, 'cc80' ),
+                       array( 'uint 16', 1000, 'cd03e8' ),
+                       array( 'uint 32', 100000, 'ce000186a0' ),
+                       array( 'uint 64', 10000000000, 'cf00000002540be400' ),
+                       array( 'negative fixnum', -1, 'ff' ),
+                       array( 'negative fixnum', -2, 'fe' ),
+                       array( 'int 8', -128, 'd080' ),
+                       array( 'int 8', -35, 'd0dd' ),
+                       array( 'int 16', -1000, 'd1fc18' ),
+                       array( 'int 32', -100000, 'd2fffe7960' ),
+                       array( 'int 64', -10000000000, 'd3fffffffdabf41c00' ),
+                       array( 'int 64', -223372036854775807, 'd3fce66c50e2840001' ),
+                       array( 'int 64', -9223372036854775807, 'd38000000000000001' ),
+                       array( 'double', 0.1, 'cb3fb999999999999a' ),
+                       array( 'double', 1.1, 'cb3ff199999999999a' ),
+                       array( 'double', 123.456, 'cb405edd2f1a9fbe77' ),
+                       array( 'fix raw', '', 'a0' ),
+                       array( 'fix raw', 'foobar', 'a6666f6f626172' ),
+                       array(
+                               'raw 16',
+                               'Lorem ipsum dolor sit amet amet.',
+                               'da00204c6f72656d20697073756d20646f6c6f722073697420616d657420616d65742e'
+                       ),
+                       array(
+                               'fix array',
+                               array( 'abc', 'def', 'ghi' ),
+                               '93a3616263a3646566a3676869'
+                       ),
+                       array(
+                               'fix map',
+                               array( 'one' => 1, 'two' => 2 ),
+                               '82a36f6e6501a374776f02'
+                       ),
+               );
+       }
+
+       /**
+        * Verify that values are serialized correctly.
+        * @covers MWMessagePack::pack
+        * @dataProvider provider
+        */
+       public function testPack( $type, $value, $expected ) {
+               $actual = bin2hex( MWMessagePack::pack( $value ) );
+               $this->assertEquals( $actual, $expected, $type );
+       }
+}
diff --git a/tests/phpunit/includes/libs/RunningStatTest.php b/tests/phpunit/includes/libs/RunningStatTest.php
new file mode 100644 (file)
index 0000000..e24c088
--- /dev/null
@@ -0,0 +1,81 @@
+<?php
+/**
+ * PHP Unit tests for RunningStat class.
+ * @covers RunningStat
+ */
+class RunningStatTest extends MediaWikiTestCase {
+
+       public $points = array(
+               49.7168, 74.3804,  7.0115, 96.5769, 34.9458,
+               36.9947, 33.8926, 89.0774, 23.7745, 73.5154,
+               86.1322, 53.2124, 16.2046, 73.5130, 10.4209,
+               42.7299, 49.3330, 47.0215, 34.9950, 18.2914,
+       );
+
+       /**
+        * Verify that the statistical moments and extrema computed by RunningStat
+        * match expected values.
+        * @covers RunningStat::push
+        * @covers RunningStat::count
+        * @covers RunningStat::getMean
+        * @covers RunningStat::getVariance
+        * @covers RunningStat::getStdDev
+        */
+       public function testRunningStatAccuracy() {
+               $rstat = new RunningStat();
+               foreach( $this->points as $point ) {
+                       $rstat->push( $point );
+               }
+
+               $mean = array_sum( $this->points ) / count( $this->points );
+               $variance = array_sum( array_map( function ( $x ) use ( $mean ) {
+                       return pow( $mean - $x, 2 );
+               }, $this->points ) ) / ( count( $rstat ) - 1 );
+               $stddev = sqrt( $variance );
+               $min = min( $this->points );
+               $max = max( $this->points );
+
+               $this->assertEquals( count( $rstat ), count( $this->points ) );
+               $this->assertEquals( $rstat->min, min( $this->points ) );
+               $this->assertEquals( $rstat->max, max( $this->points ) );
+               $this->assertEquals( $rstat->getMean(), $mean );
+               $this->assertEquals( $rstat->getVariance(), $variance );
+               $this->assertEquals( $rstat->getStdDev(), $stddev );
+       }
+
+       /**
+        * When one RunningStat instance is merged into another, the state of the
+        * target RunningInstance should have the state that it would have had if
+        * all the data had been accumulated by it alone.
+        * @covers RunningStat::merge
+        * @covers RunningStat::count
+        */
+       public function testRunningStatMerge() {
+               $expected = new RunningStat();
+
+               foreach( $this->points as $point ) {
+                       $expected->push( $point );
+               }
+
+               // Split the data into two sets
+               $sets = array_chunk( $this->points, floor( count( $this->points ) / 2 ) );
+
+               // Accumulate the first half into one RunningStat object
+               $first = new RunningStat();
+               foreach( $sets[0] as $point ) {
+                       $first->push( $point );
+               }
+
+               // Accumulate the second half into another RunningStat object
+               $second = new RunningStat();
+               foreach( $sets[1] as $point ) {
+                       $second->push( $point );
+               }
+
+               // Merge the second RunningStat object into the first
+               $first->merge( $second );
+
+               $this->assertEquals( count( $first ), count( $this->points ) );
+               $this->assertEquals( $first, $expected );
+       }
+}
index e460591..ff360e9 100644 (file)
@@ -8,10 +8,12 @@
  * @note Coverage will only ever show one of on of the Search* classes
  */
 class SearchEngineTest extends MediaWikiLangTestCase {
+
        /**
         * @var SearchEngine
         */
        protected $search;
+
        protected $pageList;
 
        /**
@@ -22,17 +24,23 @@ class SearchEngineTest extends MediaWikiLangTestCase {
                parent::setUp();
 
                // Search tests require MySQL or SQLite with FTS
-               # Get database type and version
                $dbType = $this->db->getType();
-               $dbSupported =
-                       ( $dbType === 'mysql' )
-                               || ( $dbType === 'sqlite' && $this->db->getFulltextSearchModule() == 'FTS3' );
+               $dbSupported = ( $dbType === 'mysql' )
+                       || ( $dbType === 'sqlite' && $this->db->getFulltextSearchModule() == 'FTS3' );
 
                if ( !$dbSupported ) {
                        $this->markTestSkipped( "MySQL or SQLite with FTS3 only" );
                }
 
                $searchType = $this->db->getSearchEngine();
+               $this->setMwGlobals( array(
+                       'wgSearchType' => $searchType
+               ) );
+
+               if ( !isset( self::$pageList ) ) {
+                       $this->addPages();
+               }
+
                $this->search = new $searchType( $this->db );
        }
 
@@ -42,15 +50,7 @@ class SearchEngineTest extends MediaWikiLangTestCase {
                parent::tearDown();
        }
 
-       function pageExists( $title ) {
-               return false;
-       }
-
-       function addDBData() {
-               if ( $this->pageExists( 'Not_Main_Page' ) ) {
-                       return;
-               }
-
+       protected function addPages() {
                if ( !$this->isWikitextNS( NS_MAIN ) ) {
                        // @todo cover the case of non-wikitext content in the main namespace
                        return;
@@ -75,12 +75,11 @@ class SearchEngineTest extends MediaWikiLangTestCase {
                $this->insertPage( 'DomainName', 'example.com', 0 );
        }
 
-       function fetchIds( $results ) {
+       protected function fetchIds( $results ) {
                if ( !$this->isWikitextNS( NS_MAIN ) ) {
                        $this->markTestIncomplete( __CLASS__ . " does no yet support non-wikitext content "
                                . "in the main namespace" );
                }
-
                $this->assertTrue( is_object( $results ) );
 
                $matches = array();
@@ -105,7 +104,7 @@ class SearchEngineTest extends MediaWikiLangTestCase {
         * @param $text String: page's content
         * @param $n Integer: unused
         */
-       function insertPage( $pageName, $text, $ns ) {
+       protected function insertPage( $pageName, $text, $ns ) {
                $title = Title::newFromText( $pageName, $ns );
 
                $user = User::newFromName( 'WikiSysop' );
@@ -180,4 +179,5 @@ class SearchEngineTest extends MediaWikiLangTestCase {
                        $this->fetchIds( $this->search->searchTitle( 'smithee' ) ),
                        "Title power search failed" );
        }
+
 }
diff --git a/tests/phpunit/includes/specials/SpecialListFilesTest.php b/tests/phpunit/includes/specials/SpecialListFilesTest.php
new file mode 100644 (file)
index 0000000..2689236
--- /dev/null
@@ -0,0 +1,21 @@
+<?php
+/**
+ * Test class for SpecialListFiles class.
+ *
+ * Copyright © 2013, Antoine Musso
+ * Copyright © 2013, Siebrand Mazeland
+ * Copyright © 2013, Wikimedia Foundation Inc.
+ *
+ */
+
+class SpecialListFilesTest extends MediaWikiTestCase {
+       /**
+        * @expectedException MWException
+        * @expectedExceptionMesage invalid_field
+        * @covers ImageListPager::formatValue
+        */
+       public function testFormatValuesThrowException() {
+               $page = new ImageListPager( RequestContext::getMain() );
+               $page->formatValue( 'invalid_field', 'invalid_value' );
+       }
+}
index 8f78ae5..1a1bbaf 100644 (file)
@@ -95,4 +95,32 @@ class UIDGeneratorTest extends MediaWikiTestCase {
                }
        }
 
+       /**
+        * @covers UIDGenerator::newSequentialPerNodeID
+        */
+       public function testNewSequentialID() {
+               $id1 = UIDGenerator::newSequentialPerNodeID( 'test', 32 );
+               $id2 = UIDGenerator::newSequentialPerNodeID( 'test', 32 );
+
+               $this->assertType( 'float', $id1, "ID returned as float" );
+               $this->assertType( 'float', $id2, "ID returned as float" );
+               $this->assertGreaterThan( 0, $id1, "ID greater than 1" );
+               $this->assertGreaterThan( $id1, $id2, "IDs increasing in value" );
+       }
+
+       /**
+        * @covers UIDGenerator::newSequentialPerNodeIDs
+        */
+       public function testNewSequentialIDs() {
+               $ids = UIDGenerator::newSequentialPerNodeIDs( 'test', 32, 5 );
+               $lastId = null;
+               foreach ( $ids as $id ) {
+                       $this->assertType( 'float', $id, "ID returned as float" );
+                       $this->assertGreaterThan( 0, $id, "ID greater than 1" );
+                       if ( $lastId ) {
+                               $this->assertGreaterThan( $lastId, $id, "IDs increasing in value" );
+                       }
+                       $lastId = $id;
+               }
+       }
 }
index 97a17ec..dbdb588 100644 (file)
@@ -79,13 +79,13 @@ class LanguageBe_taraskTest extends LanguageClassesTestCase {
         * @covers Language::convertPlural
         */
        public function testPluralTwoForms( $result, $value ) {
-               $forms = array( 'one', 'other', '0=one' );
+               $forms = array( '1=one', 'other' );
                $this->assertEquals( $result, $this->getLang()->convertPlural( $value, $forms ) );
        }
 
        public static function providePluralTwoForms() {
                return array(
-                       array( 'one', 0 ),
+                       array( 'other', 0 ),
                        array( 'one', 1 ),
                        array( 'other', 11 ),
                        array( 'other', 91 ),
index fb965b8..7aca2ab 100644 (file)
@@ -5,14 +5,14 @@
  * @file
  */
 
-/** Tests for MediaWiki languages/LanguageBs.php */
+/** Tests for Croatian (hrvatski) */
 class LanguageBsTest extends LanguageClassesTestCase {
        /**
         * @dataProvider providePlural
         * @covers Language::convertPlural
         */
        public function testPlural( $result, $value ) {
-               $forms = array( 'one', 'few', 'many', 'other' );
+               $forms = array( 'one', 'few', 'other' );
                $this->assertEquals( $result, $this->getLang()->convertPlural( $value, $forms ) );
        }
 
@@ -26,17 +26,17 @@ class LanguageBsTest extends LanguageClassesTestCase {
 
        public static function providePlural() {
                return array(
-                       array( 'many', 0 ),
+                       array( 'other', 0 ),
                        array( 'one', 1 ),
                        array( 'few', 2 ),
                        array( 'few', 4 ),
-                       array( 'many', 5 ),
-                       array( 'many', 11 ),
-                       array( 'many', 20 ),
+                       array( 'other', 5 ),
+                       array( 'other', 11 ),
+                       array( 'other', 20 ),
                        array( 'one', 21 ),
                        array( 'few', 24 ),
-                       array( 'many', 25 ),
-                       array( 'many', 200 ),
+                       array( 'other', 25 ),
+                       array( 'other', 200 ),
                );
        }
 }
index 6ce4aff..644c525 100644 (file)
@@ -12,7 +12,7 @@ class LanguageHrTest extends LanguageClassesTestCase {
         * @covers Language::convertPlural
         */
        public function testPlural( $result, $value ) {
-               $forms = array( 'one', 'few', 'many', 'other' );
+               $forms = array( 'one', 'few', 'other' );
                $this->assertEquals( $result, $this->getLang()->convertPlural( $value, $forms ) );
        }
 
@@ -26,17 +26,17 @@ class LanguageHrTest extends LanguageClassesTestCase {
 
        public static function providePlural() {
                return array(
-                       array( 'many', 0 ),
+                       array( 'other', 0 ),
                        array( 'one', 1 ),
                        array( 'few', 2 ),
                        array( 'few', 4 ),
-                       array( 'many', 5 ),
-                       array( 'many', 11 ),
-                       array( 'many', 20 ),
+                       array( 'other', 5 ),
+                       array( 'other', 11 ),
+                       array( 'other', 20 ),
                        array( 'one', 21 ),
                        array( 'few', 24 ),
-                       array( 'many', 25 ),
-                       array( 'many', 200 ),
+                       array( 'other', 25 ),
+                       array( 'other', 200 ),
                );
        }
 }
index 896522b..92e0ef9 100644 (file)
@@ -5,7 +5,7 @@
  * @file
  */
 
-/** Tests for MediaWiki languages/LanguageHy.php */
+/** Tests for Armenian (Հայերեն) */
 class LanguageHyTest extends LanguageClassesTestCase {
        /**
         * @dataProvider providePlural
@@ -21,13 +21,12 @@ class LanguageHyTest extends LanguageClassesTestCase {
         * @covers Language::getPluralRuleType
         */
        public function testGetPluralRuleType( $result, $value ) {
-               // This fails for 0, but I'm not sure why. Some voodoo going on here.
                $this->assertEquals( $result, $this->getLang()->getPluralRuleType( $value ) );
        }
 
        public static function providePlural() {
                return array(
-                       array( 'other', 0 ),
+                       array( 'one', 0 ),
                        array( 'one', 1 ),
                        array( 'other', 2 ),
                        array( 'other', 200 ),
index c4d8a6f..7120cfe 100644 (file)
@@ -5,7 +5,7 @@
  * @file
  */
 
-/** Tests for MediaWiki languages/classes/LanguageLv.php */
+/** Tests for Latvian */
 class LanguageLvTest extends LanguageClassesTestCase {
        /**
         * @dataProvider providePlural
@@ -28,13 +28,17 @@ class LanguageLvTest extends LanguageClassesTestCase {
                return array(
                        array( 'zero', 0 ),
                        array( 'one', 1 ),
-                       array( 'other', 11 ),
+                       array( 'zero', 11 ),
                        array( 'one', 21 ),
-                       array( 'other', 411 ),
+                       array( 'zero', 411 ),
+                       array( 'other', 2 ),
+                       array( 'other', 9 ),
+                       array( 'zero', 12 ),
                        array( 'other', 12.345 ),
-                       array( 'other', 20 ),
+                       array( 'zero', 20 ),
+                       array( 'other', 22 ),
                        array( 'one', 31 ),
-                       array( 'other', 200 ),
+                       array( 'zero', 200 ),
                );
        }
 }
index 7d47b37..ed15526 100644 (file)
@@ -5,7 +5,7 @@
  * @file
  */
 
-/** Tests for MediaWiki languages/classes/LanguageMk.php */
+/** Tests for македонски/Macedonian */
 class LanguageMkTest extends LanguageClassesTestCase {
        /**
         * @dataProvider providePlural
@@ -28,7 +28,7 @@ class LanguageMkTest extends LanguageClassesTestCase {
                return array(
                        array( 'other', 0 ),
                        array( 'one', 1 ),
-                       array( 'other', 11 ),
+                       array( 'one', 11 ),
                        array( 'one', 21 ),
                        array( 'one', 411 ),
                        array( 'other', 12.345 ),
index 56f8490..e17c708 100644 (file)
@@ -13,7 +13,7 @@ class LanguageRuTest extends LanguageClassesTestCase {
         * @covers Language::convertPlural
         */
        public function testPlural( $result, $value ) {
-               $forms = array( 'one', 'few', 'many', 'other' );
+               $forms = array( 'one', 'many', 'other' );
                $this->assertEquals( $result, $this->getLang()->convertPlural( $value, $forms ) );
        }
 
@@ -22,9 +22,9 @@ class LanguageRuTest extends LanguageClassesTestCase {
         * @covers Language::convertPlural
         */
        public function testExplicitPlural() {
-               $forms = array( 'one', 'few', 'many', 'other', '12=dozen' );
+               $forms = array( 'one','many', 'other', '12=dozen' );
                $this->assertEquals( 'dozen', $this->getLang()->convertPlural( 12, $forms ) );
-               $forms = array( 'one', 'few', 'many', '100=hundred', 'other', '12=dozen' );
+               $forms = array( 'one', 'many', '100=hundred', 'other', '12=dozen' );
                $this->assertEquals( 'hundred', $this->getLang()->convertPlural( 100, $forms ) );
        }
 
@@ -42,10 +42,10 @@ class LanguageRuTest extends LanguageClassesTestCase {
                        array( 'many', 11 ),
                        array( 'one', 91 ),
                        array( 'one', 121 ),
-                       array( 'few', 2 ),
-                       array( 'few', 3 ),
-                       array( 'few', 4 ),
-                       array( 'few', 334 ),
+                       array( 'other', 2 ),
+                       array( 'other', 3 ),
+                       array( 'other', 4 ),
+                       array( 'other', 334 ),
                        array( 'many', 5 ),
                        array( 'many', 15 ),
                        array( 'many', 120 ),
@@ -57,7 +57,7 @@ class LanguageRuTest extends LanguageClassesTestCase {
         * @covers Language::convertPlural
         */
        public function testPluralTwoForms( $result, $value ) {
-               $forms = array( 'one', 'other' );
+               $forms = array( '1=one', 'other' );
                $this->assertEquals( $result, $this->getLang()->convertPlural( $value, $forms ) );
        }
 
index bf6a14b..fa49a4d 100644 (file)
@@ -5,7 +5,7 @@
  * @file
  */
 
-/** Tests for MediaWiki languages/classes/LanguageSgs.php */
+/** Tests for Samogitian */
 class LanguageSgsTest extends LanguageClassesTestCase {
        /**
         * @dataProvider providePluralAllForms
index 6d2e25a..1b39087 100644 (file)
@@ -5,14 +5,14 @@
  * @file
  */
 
-/** Tests for MediaWiki languages/classes/LanguageSh.php */
+/** Tests for  srpskohrvatski / српскохрватски / Serbocroatian */
 class LanguageShTest extends LanguageClassesTestCase {
        /**
         * @dataProvider providePlural
         * @covers Language::convertPlural
         */
        public function testPlural( $result, $value ) {
-               $forms = array( 'one', 'few', 'many', 'other' );
+               $forms = array( 'one', 'few', 'other' );
                $this->assertEquals( $result, $this->getLang()->convertPlural( $value, $forms ) );
        }
 
@@ -26,17 +26,17 @@ class LanguageShTest extends LanguageClassesTestCase {
 
        public static function providePlural() {
                return array(
-                       array( 'many', 0 ),
+                       array( 'other', 0 ),
                        array( 'one', 1 ),
                        array( 'few', 2 ),
                        array( 'few', 4 ),
-                       array( 'many', 5 ),
-                       array( 'many', 10 ),
-                       array( 'many', 11 ),
-                       array( 'many', 12 ),
+                       array( 'other', 5 ),
+                       array( 'other', 10 ),
+                       array( 'other', 11 ),
+                       array( 'other', 12 ),
                        array( 'one', 101 ),
                        array( 'few', 102 ),
-                       array( 'many', 111 ),
+                       array( 'other', 111 ),
                );
        }
 }
index f551248..8d35f36 100644 (file)
@@ -130,7 +130,7 @@ class LanguageSrTest extends LanguageClassesTestCase {
         * @covers Language::convertPlural
         */
        public function testPlural( $result, $value ) {
-               $forms = array( 'one', 'few', 'many', 'other' );
+               $forms = array( 'one', 'few', 'other' );
                $this->assertEquals( $result, $this->getLang()->convertPlural( $value, $forms ) );
        }
 
@@ -145,16 +145,16 @@ class LanguageSrTest extends LanguageClassesTestCase {
        public static function providePlural() {
                return array(
                        array( 'one', 1 ),
-                       array( 'many', 11 ),
+                       array( 'other', 11 ),
                        array( 'one', 91 ),
                        array( 'one', 121 ),
                        array( 'few', 2 ),
                        array( 'few', 3 ),
                        array( 'few', 4 ),
                        array( 'few', 334 ),
-                       array( 'many', 5 ),
-                       array( 'many', 15 ),
-                       array( 'many', 120 ),
+                       array( 'other', 5 ),
+                       array( 'other', 15 ),
+                       array( 'other', 120 ),
                );
        }
 
@@ -171,8 +171,9 @@ class LanguageSrTest extends LanguageClassesTestCase {
                return array(
                        array( 'one', 1 ),
                        array( 'other', 11 ),
-                       array( 'other', 91 ),
-                       array( 'other', 121 ),
+                       array( 'other', 4 ),
+                       array( 'one', 91 ),
+                       array( 'one', 121 ),
                );
        }
 
index 1d81bc5..9051bcf 100644 (file)
@@ -6,7 +6,7 @@
  * @file
  */
 
-/** Tests for MediaWiki languages/classes/LanguageUk.php */
+/** Tests for Ukrainian */
 class LanguageUkTest extends LanguageClassesTestCase {
        /**
         * @dataProvider providePlural
@@ -57,7 +57,7 @@ class LanguageUkTest extends LanguageClassesTestCase {
         * @covers Language::convertPlural
         */
        public function testPluralTwoForms( $result, $value ) {
-               $forms = array( 'one', 'other' );
+               $forms = array( '1=one', 'other' );
                $this->assertEquals( $result, $this->getLang()->convertPlural( $value, $forms ) );
        }
 
index 4c7c302..6030206 100644 (file)
                                        rtl: true
                                }
                        },
-                       // Bug #34924
+                       // Rekonq (bug 34924)
                        'Mozilla/5.0 (X11; Linux i686) AppleWebKit/534.34 (KHTML, like Gecko) rekonq Safari/534.34': {
                                title: 'Rekonq',
                                platform: 'Linux i686',
                                        ltr: true,
                                        rtl: true
                                }
+                       },
+                       // Konqueror
+                       'Mozilla/5.0 (X11; Linux i686) KHTML/4.9.1 (like Gecko) Konqueror/4.9': {
+                               title: 'Konqueror',
+                               platform: 'Linux i686',
+                               profile: {
+                                       name: 'konqueror',
+                                       layout: 'khtml',
+                                       layoutVersion: 'unknown',
+                                       platform: 'linux',
+                                       version: '4.9.1',
+                                       versionBase: '4',
+                                       versionNumber: 4.9
+                               },
+                               wikiEditor: {
+                                       // '4.9' is less than '4.11'.
+                                       ltr: false,
+                                       rtl: false
+                               },
+                               wikiEditorLegacy: {
+                                       // The check is missing in legacyTestMap
+                                       ltr: true,
+                                       rtl: true
+                               }
                        }
                },
                testMap = {
-                       // Example from WikiEditor
-                       // Make sure to use raw numbers, a string like "7.0" would fail on a
-                       // version 10 browser since in string comparaison "10" is before "7.0" :)
+                       // Example from WikiEditor, modified to provide version identifiers as strings and with
+                       // Konqueror 4.11 check added.
+                       'ltr': {
+                               'msie': [['>=', '7.0']],
+                               'firefox': [['>=', '2']],
+                               'opera': [['>=', '9.6']],
+                               'safari': [['>=', '3']],
+                               'chrome': [['>=', '3']],
+                               'netscape': [['>=', '9']],
+                               'konqueror': [['>=', '4.11']],
+                               'blackberry': false,
+                               'ipod': false,
+                               'iphone': false
+                       },
+                       'rtl': {
+                               'msie': [['>=', '8']],
+                               'firefox': [['>=', '2']],
+                               'opera': [['>=', '9.6']],
+                               'safari': [['>=', '3']],
+                               'chrome': [['>=', '3']],
+                               'netscape': [['>=', '9']],
+                               'konqueror': [['>=', '4.11']],
+                               'blackberry': false,
+                               'ipod': false,
+                               'iphone': false
+                       }
+               },
+               legacyTestMap = {
+                       // Original example from WikiEditor.
+                       // This is using the old, but still supported way of providing version identifiers as numbers
+                       // instead of strings; with this method, 4.9 would be considered larger than 4.11.
                        'ltr': {
                                'msie': [['>=', 7.0]],
                                'firefox': [['>=', 2]],
                }, ie7Profile, true ), false, 'returns false if browser not found and exactMatchOnly is set' );
        } );
 
-       QUnit.test( 'test( testMap) - WikiEditor sample', uacount * 2, function ( assert ) {
+       QUnit.test( 'test( testMap ), test( legacyTestMap ) - WikiEditor sample', uacount * 2 * 2, function ( assert ) {
                var $body = $( 'body' ),
                        bodyClasses = $body.attr( 'class' );
 
                // Loop through and run tests
                $.each( uas, function ( agent, data ) {
                        $.each( ['ltr', 'rtl'], function ( i, dir ) {
-                               var profile, testMatch;
+                               var profile, testMatch, legacyTestMatch;
                                $body.removeClass( 'ltr rtl' ).addClass( dir );
                                profile = $.client.profile( {
                                        userAgent: agent,
                                        platform: data.platform
                                } );
                                testMatch = $.client.test( testMap, profile );
+                               legacyTestMatch = $.client.test( legacyTestMap, profile );
                                $body.removeClass( dir );
 
-                               assert.equal( testMatch, data.wikiEditor[dir], 'testing comparison based on ' + dir + ', ' + agent );
+                               assert.equal(
+                                       testMatch,
+                                       data.wikiEditor[dir],
+                                       'testing comparison based on ' + dir + ', ' + agent
+                               );
+                               assert.equal(
+                                       legacyTestMatch,
+                                       data.wikiEditorLegacy ? data.wikiEditorLegacy[dir] : data.wikiEditor[dir],
+                                       'testing comparison based on ' + dir + ', ' + agent + ' (legacyTestMap)'
+                               );
                        } );
                } );