Merge "fix sidebar HTML escaping in CologneBlue"
authorOri.livneh <ori@wikimedia.org>
Fri, 26 Oct 2012 20:49:36 +0000 (20:49 +0000)
committerGerrit Code Review <gerrit@wikimedia.org>
Fri, 26 Oct 2012 20:49:36 +0000 (20:49 +0000)
191 files changed:
RELEASE-NOTES-1.21
docs/hooks.txt
includes/AutoLoader.php
includes/Block.php
includes/Cookie.php
includes/DefaultSettings.php
includes/EditPage.php
includes/HttpFunctions.php
includes/Linker.php
includes/MagicWord.php
includes/Message.php
includes/MimeMagic.php
includes/OutputPage.php
includes/RecentChange.php
includes/Sanitizer.php
includes/Skin.php
includes/SpecialPage.php
includes/Title.php
includes/User.php
includes/UserMailer.php
includes/WebRequest.php
includes/Wiki.php
includes/Xml.php
includes/api/ApiBase.php
includes/api/ApiEditPage.php
includes/api/ApiMain.php
includes/api/ApiParse.php
includes/api/ApiQuery.php
includes/api/ApiQueryBlocks.php
includes/api/ApiQueryInfo.php
includes/api/ApiQueryORM.php
includes/api/ApiQueryUsers.php
includes/cache/HTMLCacheUpdate.php
includes/cache/MessageCache.php
includes/content/ContentHandler.php
includes/content/TextContent.php
includes/db/Database.php
includes/diff/DairikiDiff.php
includes/filebackend/README [new file with mode: 0644]
includes/filerepo/file/LocalFile.php
includes/installer/DatabaseInstaller.php
includes/installer/DatabaseUpdater.php
includes/installer/Installer.i18n.php
includes/installer/PostgresUpdater.php
includes/job/DoubleRedirectJob.php [deleted file]
includes/job/EmaillingJob.php [deleted file]
includes/job/EnotifNotifyJob.php [deleted file]
includes/job/JobQueue.php
includes/job/JobQueueDB.php
includes/job/JobQueueGroup.php
includes/job/README [new file with mode: 0644]
includes/job/RefreshLinksJob.php [deleted file]
includes/job/UploadFromUrlJob.php [deleted file]
includes/job/jobs/DoubleRedirectJob.php [new file with mode: 0644]
includes/job/jobs/EmaillingJob.php [new file with mode: 0644]
includes/job/jobs/EnotifNotifyJob.php [new file with mode: 0644]
includes/job/jobs/HTMLCacheUpdateJob.php [new file with mode: 0644]
includes/job/jobs/RefreshLinksJob.php [new file with mode: 0644]
includes/job/jobs/UploadFromUrlJob.php [new file with mode: 0644]
includes/json/Services_JSON.php
includes/media/SVG.php
includes/objectcache/MemcachedClient.php
includes/parser/LinkHolderArray.php
includes/parser/Parser.php
includes/parser/Preprocessor_DOM.php
includes/resourceloader/ResourceLoader.php
includes/resourceloader/ResourceLoaderFileModule.php
includes/specials/SpecialDeletedContributions.php
includes/specials/SpecialLinkSearch.php
includes/specials/SpecialUserrights.php
languages/LanguageConverter.php
languages/classes/LanguageEo.php
languages/messages/MessagesAeb.php
languages/messages/MessagesAr.php
languages/messages/MessagesArc.php
languages/messages/MessagesAs.php
languages/messages/MessagesBa.php
languages/messages/MessagesBcl.php
languages/messages/MessagesBe_tarask.php
languages/messages/MessagesBr.php
languages/messages/MessagesCa.php
languages/messages/MessagesCkb.php
languages/messages/MessagesCs.php
languages/messages/MessagesDe.php
languages/messages/MessagesDiq.php
languages/messages/MessagesDtp.php
languages/messages/MessagesEn.php
languages/messages/MessagesEo.php
languages/messages/MessagesEs.php
languages/messages/MessagesFr.php
languages/messages/MessagesFrp.php
languages/messages/MessagesGl.php
languages/messages/MessagesGsw.php
languages/messages/MessagesGu.php
languages/messages/MessagesHe.php
languages/messages/MessagesHil.php
languages/messages/MessagesHsb.php
languages/messages/MessagesHy.php
languages/messages/MessagesIt.php
languages/messages/MessagesJa.php
languages/messages/MessagesKab.php
languages/messages/MessagesKbd_cyrl.php
languages/messages/MessagesKhw.php
languages/messages/MessagesKiu.php
languages/messages/MessagesKo.php
languages/messages/MessagesKy.php
languages/messages/MessagesLb.php
languages/messages/MessagesLez.php
languages/messages/MessagesLus.php
languages/messages/MessagesMk.php
languages/messages/MessagesMl.php
languages/messages/MessagesMs.php
languages/messages/MessagesNb.php
languages/messages/MessagesNl.php
languages/messages/MessagesNn.php
languages/messages/MessagesOr.php
languages/messages/MessagesPa.php
languages/messages/MessagesPl.php
languages/messages/MessagesPms.php
languages/messages/MessagesPt.php
languages/messages/MessagesPt_br.php
languages/messages/MessagesQqq.php
languages/messages/MessagesQu.php
languages/messages/MessagesRm.php
languages/messages/MessagesRo.php
languages/messages/MessagesRoa_tara.php
languages/messages/MessagesRu.php
languages/messages/MessagesSgs.php
languages/messages/MessagesSi.php
languages/messages/MessagesSk.php
languages/messages/MessagesSv.php
languages/messages/MessagesTa.php
languages/messages/MessagesTe.php
languages/messages/MessagesTr.php
languages/messages/MessagesUk.php
languages/messages/MessagesUz.php
languages/messages/MessagesWar.php
languages/messages/MessagesZh_hans.php
languages/messages/MessagesZh_hant.php
maintenance/archives/patch-uploadstash.sql
maintenance/importImages.php
maintenance/populateFilearchiveSha1.php
maintenance/postgres/tables.sql
maintenance/sql.php
maintenance/tables.sql
maintenance/update.php
resources/mediawiki/mediawiki.searchSuggest.js
skins/common/config.css
tests/parser/parserTests.txt
tests/phpunit/MediaWikiTestCase.php
tests/phpunit/data/db/sqlite/tables-1.18.sql
tests/phpunit/includes/ArticleTest.php
tests/phpunit/includes/CdbTest.php
tests/phpunit/includes/ContentHandlerTest.php [deleted file]
tests/phpunit/includes/CssContentTest.php [deleted file]
tests/phpunit/includes/ExtraParserTest.php
tests/phpunit/includes/FauxResponseTest.php
tests/phpunit/includes/FormOptionsInitializationTest.php
tests/phpunit/includes/FormOptionsTest.php
tests/phpunit/includes/GlobalFunctions/wfBCP47Test.php
tests/phpunit/includes/HttpTest.php
tests/phpunit/includes/JavascriptContentTest.php [deleted file]
tests/phpunit/includes/LinksUpdateTest.php
tests/phpunit/includes/MWNamespaceTest.php
tests/phpunit/includes/PathRouterTest.php
tests/phpunit/includes/RevisionStorageTest.php
tests/phpunit/includes/SiteConfigurationTest.php
tests/phpunit/includes/TextContentTest.php [deleted file]
tests/phpunit/includes/TitleMethodsTest.php
tests/phpunit/includes/UserTest.php
tests/phpunit/includes/WikiPageTest.php
tests/phpunit/includes/WikitextContentHandlerTest.php [deleted file]
tests/phpunit/includes/WikitextContentTest.php [deleted file]
tests/phpunit/includes/XmlSelectTest.php
tests/phpunit/includes/ZipDirectoryReaderTest.php
tests/phpunit/includes/content/ContentHandlerTest.php [new file with mode: 0644]
tests/phpunit/includes/content/CssContentTest.php [new file with mode: 0644]
tests/phpunit/includes/content/JavascriptContentTest.php [new file with mode: 0644]
tests/phpunit/includes/content/TextContentTest.php [new file with mode: 0644]
tests/phpunit/includes/content/WikitextContentHandlerTest.php [new file with mode: 0644]
tests/phpunit/includes/content/WikitextContentTest.php [new file with mode: 0644]
tests/phpunit/includes/db/DatabaseTest.php
tests/phpunit/includes/debug/MWDebugTest.php
tests/phpunit/includes/media/PNGMetadataExtractorTest.php
tests/phpunit/includes/media/SVGMetadataExtractorTest.php
tests/phpunit/includes/media/XMPTest.php
tests/phpunit/includes/parser/MagicVariableTest.php
tests/phpunit/includes/parser/ParserPreloadTest.php
tests/phpunit/includes/parser/PreprocessorTest.php
tests/phpunit/includes/parser/TagHooksTest.php
tests/phpunit/includes/specials/SpecialRecentchangesTest.php

index 8eb6a76..d8314a3 100644 (file)
@@ -48,6 +48,11 @@ production.
   compatibility. This also works with Squid in reverse-proxy mode. If you wish 
   to support Squid configured in forward-proxy mode, set 
   $wgSquidPurgeUseHostHeader to false.
+* (bug 37020) sql.php with readline eats semicolon
+* (bug 11748) Properly handle optionally-closed HTML tags when Tidy is
+  disabled, and don't wrap HTML-syntax definition lists in paragraphs.
+* (bug 41409) Diffs while editing an old revision should again diff against the
+  current revision.
 
 === API changes in 1.21 ===
 * prop=revisions can now report the contentmodel and contentformat, see docs/contenthandler.txt
index 46ddcfe..998523f 100644 (file)
@@ -819,7 +819,7 @@ $tooltip: The default tooltip.  Escape before using.
 $lang: The language code to use for the link in the wfMessage function
 
 'EditFilter': Perform checks on an edit
-$editor: Edit form (see includes/EditPage.php)
+$editor: EditPage instance (object). The edit form (see includes/EditPage.php)
 $text: Contents of the edit box
 $section: Section being edited
 &$error: Error message to return
index 1cf6634..c97c95a 100644 (file)
@@ -435,7 +435,6 @@ $wgAutoloadLocalClasses = array(
        'GenderCache' => 'includes/cache/GenderCache.php',
        'GlobalDependency' => 'includes/cache/CacheDependency.php',
        'HTMLCacheUpdate' => 'includes/cache/HTMLCacheUpdate.php',
-       'HTMLCacheUpdateJob' => 'includes/cache/HTMLCacheUpdate.php',
        'HTMLFileCache' => 'includes/cache/HTMLFileCache.php',
        'LinkBatch' => 'includes/cache/LinkBatch.php',
        'LinkCache' => 'includes/cache/LinkCache.php',
@@ -652,16 +651,19 @@ $wgAutoloadLocalClasses = array(
        'WebInstallerPage' => 'includes/installer/WebInstallerPage.php',
 
        # includes/job
-       'DoubleRedirectJob' => 'includes/job/DoubleRedirectJob.php',
-       'EmaillingJob' => 'includes/job/EmaillingJob.php',
-       'EnotifNotifyJob' => 'includes/job/EnotifNotifyJob.php',
        'Job' => 'includes/job/Job.php',
        'JobQueue' => 'includes/job/JobQueue.php',
        'JobQueueDB' => 'includes/job/JobQueueDB.php',
        'JobQueueGroup' => 'includes/job/JobQueueGroup.php',
-       'RefreshLinksJob' => 'includes/job/RefreshLinksJob.php',
-       'RefreshLinksJob2' => 'includes/job/RefreshLinksJob.php',
-       'UploadFromUrlJob' => 'includes/job/UploadFromUrlJob.php',
+
+       # includes/job/jobs
+       'DoubleRedirectJob' => 'includes/job/jobs/DoubleRedirectJob.php',
+       'EmaillingJob' => 'includes/job/jobs/EmaillingJob.php',
+       'EnotifNotifyJob' => 'includes/job/jobs/EnotifNotifyJob.php',
+       'HTMLCacheUpdateJob' => 'includes/job/jobs/HTMLCacheUpdateJob.php',
+       'RefreshLinksJob' => 'includes/job/jobs/RefreshLinksJob.php',
+       'RefreshLinksJob2' => 'includes/job/jobs/RefreshLinksJob.php',
+       'UploadFromUrlJob' => 'includes/job/jobs/UploadFromUrlJob.php',
 
        # includes/json
        'FormatJson' => 'includes/json/FormatJson.php',
@@ -1093,13 +1095,15 @@ $wgAutoloadLocalClasses = array(
        'TestRecorder' => 'tests/testHelpers.inc',
 
        # tests/phpunit
-       'DummyContentHandlerForTesting' => 'tests/phpunit/includes/ContentHandlerTest.php',
-       'DummyContentForTesting' => 'tests/phpunit/includes/ContentHandlerTest.php',
-       'JavascriptContentTest' => 'tests/phpunit/includes/JavascriptContentTest.php',
        'RevisionStorageTest' => 'tests/phpunit/includes/RevisionStorageTest.php',
-       'TextContentTest' => 'tests/phpunit/includes/TextContentTest.php',
        'WikiPageTest' => 'tests/phpunit/includes/WikiPageTest.php',
 
+       # tests/phpunit/content
+       'DummyContentHandlerForTesting' => 'tests/phpunit/includes/content/ContentHandlerTest.php',
+       'DummyContentForTesting' => 'tests/phpunit/includes/content/ContentHandlerTest.php',
+       'JavascriptContentTest' => 'tests/phpunit/includes/content/JavascriptContentTest.php',
+       'TextContentTest' => 'tests/phpunit/includes/content/TextContentTest.php',
+
        # tests/phpunit/includes
        'GenericArrayObjectTest' => 'tests/phpunit/includes/libs/GenericArrayObjectTest.php',
 
index 86b4d13..e05b2ac 100644 (file)
@@ -164,7 +164,7 @@ class Block {
 
        /**
         * Check if two blocks are effectively equal.  Doesn't check irrelevant things like
-        * the blocking user or the block timestamp, only things which affect the blocked user   *
+        * the blocking user or the block timestamp, only things which affect the blocked user
         *
         * @param $block Block
         *
@@ -536,10 +536,10 @@ class Block {
                        'ipb_expiry'           => $expiry,
                        'ipb_range_start'      => $this->getRangeStart(),
                        'ipb_range_end'        => $this->getRangeEnd(),
-                       'ipb_deleted'          => intval( $this->mHideName ), // typecast required for SQLite
+                       'ipb_deleted'          => intval( $this->mHideName ), // typecast required for SQLite
                        'ipb_block_email'      => $this->prevents( 'sendemail' ),
                        'ipb_allow_usertalk'   => !$this->prevents( 'editownusertalk' ),
-                       'ipb_parent_block_id'            => $this->mParentBlockId
+                       'ipb_parent_block_id'  => $this->mParentBlockId
                );
 
                return $a;
index 1b86f5d..48216f0 100644 (file)
@@ -194,7 +194,7 @@ class CookieJar {
        private $cookie = array();
 
        /**
-        * Set a cookie in the cookie jar.      Make sure only one cookie per-name exists.
+        * Set a cookie in the cookie jar. Make sure only one cookie per-name exists.
         * @see Cookie::set()
         */
        public function setCookie ( $name, $value, $attr ) {
index cea63e0..6cdacc1 100644 (file)
@@ -752,10 +752,14 @@ $wgMediaHandlers = array(
  * @since 1.21
  */
 $wgContentHandlers = array(
-       CONTENT_MODEL_WIKITEXT => 'WikitextContentHandler', // the usual case
-       CONTENT_MODEL_JAVASCRIPT => 'JavaScriptContentHandler', // dumb version, no syntax highlighting
-       CONTENT_MODEL_CSS => 'CssContentHandler', // dumb version, no syntax highlighting
-       CONTENT_MODEL_TEXT => 'TextContentHandler', // plain text, for use by extensions etc
+       // the usual case
+       CONTENT_MODEL_WIKITEXT => 'WikitextContentHandler',
+       // dumb version, no syntax highlighting
+       CONTENT_MODEL_JAVASCRIPT => 'JavaScriptContentHandler',
+       // dumb version, no syntax highlighting
+       CONTENT_MODEL_CSS => 'CssContentHandler',
+       // plain text, for use by extensions etc
+       CONTENT_MODEL_TEXT => 'TextContentHandler',
 );
 
 /**
@@ -1849,9 +1853,10 @@ $wgUseLocalMessageCache = false;
 $wgLocalMessageCacheSerialized = true;
 
 /**
- * Instead of caching everything, keep track which messages are requested and
- * load only most used messages. This only makes sense if there is lots of
- * interface messages customised in the wiki (like hundreds in many languages).
+ * Instead of caching everything, only cache those messages which have
+ * been customised in the site content language. This means that
+ * MediaWiki:Foo/ja is ignored if MediaWiki:Foo doesn't exist.
+ * This option is probably only useful for translatewiki.net.
  */
 $wgAdaptiveMessageCache = false;
 
@@ -2587,12 +2592,12 @@ $wgSiteNotice = '';
 /**
  * A subtitle to add to the tagline, for skins that have it/
  */
-$wgExtraSubtitle       = '';
+$wgExtraSubtitle = '';
 
 /**
  * If this is set, a "donate" link will appear in the sidebar. Set it to a URL.
  */
-$wgSiteSupportPage     = '';
+$wgSiteSupportPage = '';
 
 /**
  * Validate the overall output using tidy and refuse
@@ -5436,7 +5441,7 @@ $wgJobTypesExcludedFromDefaultQueue = array();
  * These settings should be global to all wikis.
  */
 $wgJobTypeConf = array(
-       'default' => array( 'class' => 'JobQueueDB' ),
+       'default' => array( 'class' => 'JobQueueDB', 'order' => 'random' ),
 );
 
 /**
index 17335e4..67f0b46 100644 (file)
@@ -409,10 +409,13 @@ class EditPage {
                                wfProfileOut( __METHOD__ );
                                return;
                        }
-                       if ( !$this->mTitle->getArticleID() )
+
+                       if ( !$this->mTitle->getArticleID() ) {
                                wfRunHooks( 'EditFormPreloadText', array( &$this->textbox1, &$this->mTitle ) );
-                       else
+                       } else {
                                wfRunHooks( 'EditFormInitialText', array( $this ) );
+                       }
+
                }
 
                $this->showEditForm();
@@ -606,8 +609,10 @@ class EditPage {
                                // modified by subclasses
                                wfProfileIn( get_class( $this ) . "::importContentFormData" );
                                $textbox1 = $this->importContentFormData( $request );
-                               if ( isset( $textbox1 ) )
+                               if ( isset( $textbox1 ) ) {
                                        $this->textbox1 = $textbox1;
+                               }
+
                                wfProfileOut( get_class( $this ) . "::importContentFormData" );
                        }
 
@@ -1057,7 +1062,7 @@ class EditPage {
 
                $title = Title::newFromText( $preload );
                # Check for existence to avoid getting MediaWiki:Noarticletext
-               if ( $title === null || !$title->exists() || !$title->userCan( 'read' ) ) {
+               if ( $title === null || !$title->exists() || !$title->userCan( 'read', $wgUser ) ) {
                        return $handler->makeEmptyContent();
                }
 
@@ -1065,7 +1070,7 @@ class EditPage {
                if ( $page->isRedirect() ) {
                        $title = $page->getRedirectTarget();
                        # Same as before
-                       if ( $title === null || !$title->exists() || !$title->userCan( 'read' ) ) {
+                       if ( $title === null || !$title->exists() || !$title->userCan( 'read', $wgUser ) ) {
                                return $handler->makeEmptyContent();
                        }
                        $page = WikiPage::factory( $title );
@@ -1347,7 +1352,7 @@ class EditPage {
 
                if ( $new ) {
                        // Late check for create permission, just in case *PARANOIA*
-                       if ( !$this->mTitle->userCan( 'create' ) ) {
+                       if ( !$this->mTitle->userCan( 'create', $wgUser ) ) {
                                $status->fatal( 'nocreatetext' );
                                $status->value = self::AS_NO_CREATE_PERMISSION;
                                wfDebug( __METHOD__ . ": no create permission\n" );
@@ -1393,8 +1398,8 @@ class EditPage {
                                        // passed.
                                        if ( $this->summary === '' ) {
                                                $cleanSectionTitle = $wgParser->stripSectionName( $this->sectiontitle );
-                                               $this->summary = wfMessage( 'newsectionsummary', $cleanSectionTitle )
-                                                       ->inContentLanguage()->text() ;
+                                               $this->summary = wfMessage( 'newsectionsummary' )
+                                                       ->rawParams( $cleanSectionTitle )->inContentLanguage()->text();
                                        }
                                } elseif ( $this->summary !== '' ) {
                                        // Insert the section title above the content.
@@ -1405,8 +1410,8 @@ class EditPage {
 
                                        // Create a link to the new section from the edit summary.
                                        $cleanSummary = $wgParser->stripSectionName( $this->summary );
-                                       $this->summary = wfMessage( 'newsectionsummary', $cleanSummary )
-                                               ->inContentLanguage()->text();
+                                       $this->summary = wfMessage( 'newsectionsummary' )
+                                               ->rawParams( $cleanSummary )->inContentLanguage()->text();
                                }
                        }
 
@@ -1468,15 +1473,16 @@ class EditPage {
                                $this->isConflict = true;
                                $content = $textbox_content; // do not try to merge here!
                        } elseif ( $this->isConflict ) {
+                               $contentObj = $content;
                                # Attempt merge
-                               if ( $this->mergeChangesIntoContent( $textbox_content ) ) {
+                               if ( $this->mergeChangesInto( $content ) ) {
                                        // Successful merge! Maybe we should tell the user the good news?
                                        $this->isConflict = false;
-                                       $content = $textbox_content;
+                                       $content = $this->toEditContent( $content );
                                        wfDebug( __METHOD__ . ": Suppressing edit conflict, successful merge.\n" );
                                } else {
                                        $this->section = '';
-                                       #$this->textbox1 = $text; #redundant, nothing to do here?
+                                       $this->textbox1 = ContentHandler::getContentText( $contentObj );
                                        wfDebug( __METHOD__ . ": Keeping edit conflict, failed merge.\n" );
                                }
                        }
@@ -1549,16 +1555,16 @@ class EditPage {
                                        // passed.
                                        if ( $this->summary === '' ) {
                                                $cleanSectionTitle = $wgParser->stripSectionName( $this->sectiontitle );
-                                               $this->summary = wfMessage( 'newsectionsummary', $cleanSectionTitle )
-                                                       ->inContentLanguage()->text();
+                                               $this->summary = wfMessage( 'newsectionsummary' )
+                                                       ->rawParams( $cleanSectionTitle )->inContentLanguage()->text();
                                        }
                                } elseif ( $this->summary !== '' ) {
                                        $sectionanchor = $wgParser->guessLegacySectionNameFromWikiText( $this->summary );
                                        # This is a new section, so create a link to the new section
                                        # in the revision summary.
                                        $cleanSummary = $wgParser->stripSectionName( $this->summary );
-                                       $this->summary = wfMessage( 'newsectionsummary', $cleanSummary )
-                                               ->inContentLanguage()->text();
+                                       $this->summary = wfMessage( 'newsectionsummary' )
+                                               ->rawParams( $cleanSummary )->inContentLanguage()->text();
                                }
                        } elseif ( $this->section != '' ) {
                                # Try to get a section anchor from the section source, redirect to edited section if header found
@@ -1603,7 +1609,7 @@ class EditPage {
 
                if ( $doEditStatus->isOK() ) {
                                $result['redirect'] = $content->isRedirect();
-                       $this->commitWatch();
+                       $this->updateWatchlist();
                        wfProfileOut( __METHOD__ );
                        return $status;
                } else {
@@ -1624,19 +1630,27 @@ class EditPage {
        }
 
        /**
-        * Commit the change of watch status
+        * Register the change of watch status
         */
-       protected function commitWatch() {
+       protected function updateWatchlist() {
                global $wgUser;
+
                if ( $wgUser->isLoggedIn() && $this->watchthis != $wgUser->isWatched( $this->mTitle ) ) {
+                       $fname = __METHOD__;
+                       $title = $this->mTitle;
+                       $watch = $this->watchthis;
+
+                       // Do this in its own transaction to reduce contention...
                        $dbw = wfGetDB( DB_MASTER );
-                       $dbw->begin( __METHOD__ );
-                       if ( $this->watchthis ) {
-                               WatchAction::doWatch( $this->mTitle, $wgUser );
-                       } else {
-                               WatchAction::doUnwatch( $this->mTitle, $wgUser );
-                       }
-                       $dbw->commit( __METHOD__ );
+                       $dbw->onTransactionIdle( function() use ( $dbw, $title, $watch, $wgUser, $fname ) {
+                               $dbw->begin( $fname );
+                               if ( $watch ) {
+                                       WatchAction::doWatch( $title, $wgUser );
+                               } else {
+                                       WatchAction::doUnwatch( $title, $wgUser );
+                               }
+                               $dbw->commit( $fname );
+                       } );
                }
        }
 
@@ -1652,15 +1666,37 @@ class EditPage {
        function mergeChangesInto( &$editText ){
                ContentHandler::deprecated( __METHOD__, "1.21" );
 
-               $editContent = $this->toEditContent( $editText );
+               wfProfileIn( __METHOD__ );
 
-               $ok = $this->mergeChangesIntoContent( $editContent );
+               $db = wfGetDB( DB_MASTER );
 
-               if ( $ok ) {
-                       $editText = $this->toEditText( $editContent );
+               // This is the revision the editor started from
+               $baseRevision = $this->getBaseRevision();
+               if ( is_null( $baseRevision ) ) {
+                       wfProfileOut( __METHOD__ );
+                       return false;
+               }
+               $baseText = $baseRevision->getText();
+
+               // The current state, we want to merge updates into it
+               $currentRevision = Revision::loadFromTitle( $db, $this->mTitle );
+               if ( is_null( $currentRevision ) ) {
+                       wfProfileOut( __METHOD__ );
+                       return false;
+               }
+               $currentText = $currentRevision->getText();
+
+               $result = '';
+               $editText = $this->toEditText( $editText );
+
+               if ( wfMerge( $baseText, $editText, $currentText, $result ) ) {
+                       $editText = $result;
+                       wfProfileOut( __METHOD__ );
                        return true;
+               } else {
+                       wfProfileOut( __METHOD__ );
+                       return false;
                }
-               return false;
        }
 
        /**
@@ -1770,7 +1806,7 @@ class EditPage {
                $wgOut->addModules( 'mediawiki.action.edit' );
 
                if ( $wgUser->getOption( 'uselivepreview', false ) ) {
-                       $wgOut->addModules( 'mediawiki.legacy.preview' );
+                       $wgOut->addModules( 'mediawiki.action.edit.preview' );
                }
                // Bug #19334: textarea jumps when editing articles in IE8
                $wgOut->addStyle( 'common/IE80Fixes.css', 'screen', 'IE 8' );
@@ -2235,7 +2271,7 @@ class EditPage {
                                if ( $revision ) {
                                        // Let sysop know that this will make private content public if saved
 
-                                       if ( !$revision->userCan( Revision::DELETED_TEXT ) ) {
+                                       if ( !$revision->userCan( Revision::DELETED_TEXT, $wgUser ) ) {
                                                $wgOut->wrapWikiMsg( "<div class='mw-warning plainlinks'>\n$1\n</div>\n", 'rev-deleted-text-permission' );
                                        } elseif ( $revision->isDeleted( Revision::DELETED_TEXT ) ) {
                                                $wgOut->wrapWikiMsg( "<div class='mw-warning plainlinks'>\n$1\n</div>\n", 'rev-deleted-text-view' );
@@ -2269,10 +2305,13 @@ class EditPage {
                                        $wgOut->wrapWikiMsg( "<div class='error' id='mw-userinvalidcssjstitle'>\n$1\n</div>", array( 'userinvalidcssjstitle', $this->mTitle->getSkinFromCssJsSubpage() ) );
                                }
                                if ( $this->formtype !== 'preview' ) {
-                                       if ( $this->isCssSubpage )
+                                       if ( $this->isCssSubpage ) {
                                                $wgOut->wrapWikiMsg( "<div id='mw-usercssyoucanpreview'>\n$1\n</div>", array( 'usercssyoucanpreview' ) );
-                                       if ( $this->isJsSubpage )
+                                       }
+
+                                       if ( $this->isJsSubpage ) {
                                                $wgOut->wrapWikiMsg( "<div id='mw-userjsyoucanpreview'>\n$1\n</div>", array( 'userjsyoucanpreview' ) );
+                                       }
                                }
                        }
                }
@@ -2403,14 +2442,16 @@ class EditPage {
         * @return String
         */
        protected function getSummaryPreview( $isSubjectPreview, $summary = "" ) {
-               if ( !$summary || ( !$this->preview && !$this->diff ) )
+               if ( !$summary || ( !$this->preview && !$this->diff ) ) {
                        return "";
+               }
 
                global $wgParser;
 
-               if ( $isSubjectPreview )
+               if ( $isSubjectPreview ) {
                        $summary = wfMessage( 'newsectionsummary', $wgParser->stripSectionName( $summary ) )
                                ->inContentLanguage()->text();
+               }
 
                $message = $isSubjectPreview ? 'subject-preview' : 'summary-preview';
 
@@ -2429,8 +2470,9 @@ class EditPage {
 
 HTML
                );
-               if ( !$this->checkUnicodeCompliantBrowser() )
+               if ( !$this->checkUnicodeCompliantBrowser() ) {
                        $wgOut->addHTML( Html::hidden( 'safemode', '1' ) );
+               }
        }
 
        protected function showFormAfterText() {
@@ -2546,8 +2588,9 @@ HTML
 
                $attribs = array( 'id' => 'wikiPreview', 'class' => implode( ' ', $classes ) );
 
-               if ( $this->formtype != 'preview' )
+               if ( $this->formtype != 'preview' ) {
                        $attribs['style'] = 'display: none;';
+               }
 
                $wgOut->addHTML( Xml::openElement( 'div', $attribs ) );
 
@@ -2608,7 +2651,7 @@ HTML
                                $oldContent = null;
                        }
                } else {
-                       $oldContent = $this->getOriginalContent();
+                       $oldContent = $this->getCurrentContent();
                }
 
                $textboxContent = $this->toEditContent( $this->textbox1 );
@@ -2852,10 +2895,13 @@ HTML
                );
                // Quick paranoid permission checks...
                if ( is_object( $data ) ) {
-                       if ( $data->log_deleted & LogPage::DELETED_USER )
+                       if ( $data->log_deleted & LogPage::DELETED_USER ) {
                                $data->user_name = wfMessage( 'rev-deleted-user' )->escaped();
-                       if ( $data->log_deleted & LogPage::DELETED_COMMENT )
+                       }
+
+                       if ( $data->log_deleted & LogPage::DELETED_COMMENT ) {
                                $data->log_comment = wfMessage( 'rev-deleted-comment' )->escaped();
+                       }
                }
                return $data;
        }
@@ -2931,11 +2977,7 @@ HTML
                                # Messages: usercsspreview, userjspreview, sitecsspreview, sitejspreview
                                if( $level && $format ) {
                                        $note = "<div id='mw-{$level}{$format}preview'>" . wfMessage( "{$level}{$format}preview" )->text()  . "</div>";
-                               } else {
-                                       $note = wfMessage( 'previewnote' )->text() ;
                                }
-                       } else {
-                               $note = wfMessage( 'previewnote' )->text() ;
                        }
 
                        $rt = $content->getRedirectChain();
index 32f77dc..e621f62 100644 (file)
@@ -581,8 +581,8 @@ class MWHttpRequest {
        }
 
        /**
-        * Sets a cookie.  Used before a request to set up any individual
-        * cookies.      Used internally after a request to parse the
+        * Sets a cookie. Used before a request to set up any individual
+        * cookies. Used internally after a request to parse the
         * Set-Cookie headers.
         * @see Cookie::set
         * @param $name
index 28c5985..e5db232 100644 (file)
@@ -1899,7 +1899,11 @@ class Linker {
                                                array( 'action' => 'edit' )
                                        );
                                }
-                               $outText .= '<li>' . self::link( $titleObj ) . ' (' . $editLink . ') ' . $protected . '</li>';
+                               $outText .= '<li>' . self::link( $titleObj )
+                                       . wfMessage( 'word-separator' )->escaped()
+                                       . wfMessage( 'parentheses' )->rawParams( $editLink )->escaped()
+                                       . wfMessage( 'word-separator' )->escaped()
+                                       . $protected . '</li>';
                        }
                        $outText .= '</ul>';
                }
@@ -2132,7 +2136,7 @@ class Linker {
        }
 
        /**
-        * @deprecated since 1.16 Use link()
+        * @deprecated since 1.16 Use link(); warnings since 1.21
         *
         * Make a link for a title which may or may not be in the database. If you need to
         * call this lots of times, pre-fill the link cache with a LinkBatch, otherwise each
@@ -2149,7 +2153,7 @@ class Linker {
         * @return string
         */
        static function makeLinkObj( $nt, $text = '', $query = '', $trail = '', $prefix = '' ) {
-               # wfDeprecated( __METHOD__, '1.16' ); // See r105985 and it's revert. Somewhere still used.
+               wfDeprecated( __METHOD__, '1.21' );
 
                wfProfileIn( __METHOD__ );
                $query = wfCgiToArray( $query );
@@ -2165,7 +2169,7 @@ class Linker {
        }
 
        /**
-        * @deprecated since 1.16 Use link()
+        * @deprecated since 1.16 Use link(); warnings since 1.21
         *
         * Make a link for a title which definitely exists. This is faster than makeLinkObj because
         * it doesn't have to do a database query. It's also valid for interwiki titles and special
@@ -2183,7 +2187,7 @@ class Linker {
        static function makeKnownLinkObj(
                $title, $text = '', $query = '', $trail = '', $prefix = '' , $aprops = '', $style = ''
        ) {
-               # wfDeprecated( __METHOD__, '1.16' ); // See r105985 and it's revert. Somewhere still used.
+               wfDeprecated( __METHOD__, '1.21' );
 
                wfProfileIn( __METHOD__ );
 
index 42791f5..6d2e1dc 100644 (file)
@@ -534,7 +534,7 @@ class MagicWord {
         *
         * @return string
         */
-       function getVariableRegex()     {
+       function getVariableRegex() {
                if ( $this->mVariableRegex == '' ) {
                        $this->initRegex();
                }
index 824f177..2feaed2 100644 (file)
@@ -618,7 +618,7 @@ class Message {
                } elseif ( !is_array( $param ) ) {
                        return array( 'before', $param );
                } else {
-                       throw new MWException( "Invalid message parameter" );
+                       throw new MWException( "Invalid message parameter: " . serialize( $param ) );
                }
        }
 
index 88383d8..65a2a6f 100644 (file)
@@ -433,7 +433,7 @@ class MimeMagic {
                $ext = explode( ' ', $ext );
 
                $extension = strtolower( $extension );
-               return  in_array( $extension, $ext );
+               return  in_array( $extension, $ext );
        }
 
        /**
index 3578568..ff83f70 100644 (file)
@@ -2982,7 +2982,7 @@ $templates
                );
                if ( $wgContLang->hasVariants() ) {
                        $vars['wgUserVariant'] = $wgContLang->getPreferredVariant();
-               }
+               }
                foreach ( $title->getRestrictionTypes() as $type ) {
                        $vars['wgRestriction' . ucfirst( $type )] = $title->getRestrictions( $type );
                }
index debec69..3cf6c72 100644 (file)
@@ -154,7 +154,7 @@ class RecentChange {
         * @return Title
         */
        public function &getTitle() {
-               if( $this->mTitle === false ) {
+               if ( $this->mTitle === false ) {
                        $this->mTitle = Title::makeTitle( $this->mAttribs['rc_namespace'], $this->mAttribs['rc_title'] );
                        # Make sure the correct page ID is process cached
                        $this->mTitle->resetArticleID( $this->mAttribs['rc_cur_id'] );
@@ -186,17 +186,17 @@ class RecentChange {
                global $wgLocalInterwiki, $wgPutIPinRC, $wgUseEnotif, $wgShowUpdatedMarker, $wgContLang;
 
                $dbw = wfGetDB( DB_MASTER );
-               if( !is_array($this->mExtra) ) {
+               if ( !is_array( $this->mExtra ) ) {
                        $this->mExtra = array();
                }
                $this->mExtra['lang'] = $wgLocalInterwiki;
 
-               if( !$wgPutIPinRC ) {
+               if ( !$wgPutIPinRC ) {
                        $this->mAttribs['rc_ip'] = '';
                }
 
                # If our database is strict about IP addresses, use NULL instead of an empty string
-               if( $dbw->strictIPs() and $this->mAttribs['rc_ip'] == '' ) {
+               if ( $dbw->strictIPs() and $this->mAttribs['rc_ip'] == '' ) {
                        unset( $this->mAttribs['rc_ip'] );
                }
 
@@ -204,12 +204,12 @@ class RecentChange {
                $this->mAttribs['rc_comment'] = $wgContLang->truncate( $this->mAttribs['rc_comment'], 255 );
 
                # Fixup database timestamps
-               $this->mAttribs['rc_timestamp'] = $dbw->timestamp($this->mAttribs['rc_timestamp']);
-               $this->mAttribs['rc_cur_time'] = $dbw->timestamp($this->mAttribs['rc_cur_time']);
+               $this->mAttribs['rc_timestamp'] = $dbw->timestamp( $this->mAttribs['rc_timestamp'] );
+               $this->mAttribs['rc_cur_time'] = $dbw->timestamp( $this->mAttribs['rc_cur_time'] );
                $this->mAttribs['rc_id'] = $dbw->nextSequenceValue( 'recentchanges_rc_id_seq' );
 
                ## If we are using foreign keys, an entry of 0 for the page_id will fail, so use NULL
-               if( $dbw->cascadingDeletes() and $this->mAttribs['rc_cur_id']==0 ) {
+               if ( $dbw->cascadingDeletes() and $this->mAttribs['rc_cur_id'] == 0 ) {
                        unset( $this->mAttribs['rc_cur_id'] );
                }
 
@@ -228,11 +228,11 @@ class RecentChange {
                }
 
                # E-mail notifications
-               if( $wgUseEnotif || $wgShowUpdatedMarker ) {
+               if ( $wgUseEnotif || $wgShowUpdatedMarker ) {
                        $editor = $this->getPerformer();
                        $title = $this->getTitle();
 
-                       if ( wfRunHooks( 'AbortEmailNotification', array($editor, $title) ) ) {
+                       if ( wfRunHooks( 'AbortEmailNotification', array( $editor, $title ) ) ) {
                                # @todo FIXME: This would be better as an extension hook
                                $enotif = new EmailNotification();
                                $enotif->notifyOnPageChange( $editor, $title,
@@ -247,7 +247,7 @@ class RecentChange {
        public function notifyRC2UDP() {
                global $wgRC2UDPAddress, $wgRC2UDPOmitBots;
                # Notify external application via UDP
-               if( $wgRC2UDPAddress && ( !$this->mAttribs['rc_bot'] || !$wgRC2UDPOmitBots ) ) {
+               if ( $wgRC2UDPAddress && ( !$this->mAttribs['rc_bot'] || !$wgRC2UDPOmitBots ) ) {
                        self::sendToUDP( $this->getIRCLine() );
                }
        }
@@ -268,12 +268,12 @@ class RecentChange {
                $prefix = $prefix ? $prefix : $wgRC2UDPPrefix;
                $port = $port ? $port : $wgRC2UDPPort;
                # Notify external application via UDP
-               if( $address ) {
+               if ( $address ) {
                        $conn = socket_create( AF_INET, SOCK_DGRAM, SOL_UDP );
-                       if( $conn ) {
+                       if ( $conn ) {
                                $line = $prefix . $line;
                                wfDebug( __METHOD__ . ": sending UDP line: $line\n" );
-                               socket_sendto( $conn, $line, strlen($line), 0, $address, $port );
+                               socket_sendto( $conn, $line, strlen( $line ), 0, $address, $port );
                                socket_close( $conn );
                                return true;
                        } else {
@@ -304,9 +304,9 @@ class RecentChange {
 
                $change = $change instanceof RecentChange
                        ? $change
-                       : RecentChange::newFromId($change);
+                       : RecentChange::newFromId( $change );
 
-               if( !$change instanceof RecentChange ) {
+               if ( !$change instanceof RecentChange ) {
                        return null;
                }
                return $change->doMarkPatrolled( $wgUser, $auto );
@@ -325,32 +325,32 @@ class RecentChange {
                $errors = array();
                // If recentchanges patrol is disabled, only new pages
                // can be patrolled
-               if( !$wgUseRCPatrol && ( !$wgUseNPPatrol || $this->getAttribute('rc_type') != RC_NEW ) ) {
-                       $errors[] = array('rcpatroldisabled');
+               if ( !$wgUseRCPatrol && ( !$wgUseNPPatrol || $this->getAttribute( 'rc_type' ) != RC_NEW ) ) {
+                       $errors[] = array( 'rcpatroldisabled' );
                }
                // Automatic patrol needs "autopatrol", ordinary patrol needs "patrol"
                $right = $auto ? 'autopatrol' : 'patrol';
                $errors = array_merge( $errors, $this->getTitle()->getUserPermissionsErrors( $right, $user ) );
-               if( !wfRunHooks('MarkPatrolled', array($this->getAttribute('rc_id'), &$user, false)) ) {
-                       $errors[] = array('hookaborted');
+               if ( !wfRunHooks( 'MarkPatrolled', array( $this->getAttribute( 'rc_id' ), &$user, false ) ) ) {
+                       $errors[] = array( 'hookaborted' );
                }
                // Users without the 'autopatrol' right can't patrol their
                // own revisions
-               if( $user->getName() == $this->getAttribute('rc_user_text') && !$user->isAllowed('autopatrol') ) {
-                       $errors[] = array('markedaspatrollederror-noautopatrol');
+               if ( $user->getName() == $this->getAttribute( 'rc_user_text' ) && !$user->isAllowed( 'autopatrol' ) ) {
+                       $errors[] = array( 'markedaspatrollederror-noautopatrol' );
                }
-               if( $errors ) {
+               if ( $errors ) {
                        return $errors;
                }
                // If the change was patrolled already, do nothing
-               if( $this->getAttribute('rc_patrolled') ) {
+               if ( $this->getAttribute( 'rc_patrolled' ) ) {
                        return array();
                }
                // Actually set the 'patrolled' flag in RC
                $this->reallyMarkPatrolled();
                // Log this patrol event
                PatrolLog::record( $this, $auto, $user );
-               wfRunHooks( 'MarkPatrolledComplete', array($this->getAttribute('rc_id'), &$user, false) );
+               wfRunHooks( 'MarkPatrolledComplete', array( $this->getAttribute( 'rc_id' ), &$user, false ) );
                return array();
        }
 
@@ -366,7 +366,7 @@ class RecentChange {
                                'rc_patrolled' => 1
                        ),
                        array(
-                               'rc_id' => $this->getAttribute('rc_id')
+                               'rc_id' => $this->getAttribute( 'rc_id' )
                        ),
                        __METHOD__
                );
@@ -392,7 +392,7 @@ class RecentChange {
         * @return RecentChange
         */
        public static function notifyEdit( $timestamp, &$title, $minor, &$user, $comment, $oldId,
-               $lastTimestamp, $bot, $ip='', $oldSize=0, $newSize=0, $newId=0, $patrol=0 ) {
+               $lastTimestamp, $bot, $ip = '', $oldSize = 0, $newSize = 0, $newId = 0, $patrol = 0 ) {
                $rc = new RecentChange;
                $rc->mTitle = $title;
                $rc->mPerformer = $user;
@@ -411,7 +411,7 @@ class RecentChange {
                        'rc_last_oldid' => $oldId,
                        'rc_bot'        => $bot ? 1 : 0,
                        'rc_ip'         => self::checkIPAddress( $ip ),
-                       'rc_patrolled'  => intval($patrol),
+                       'rc_patrolled'  => intval( $patrol ),
                        'rc_new'        => 0,  # obsolete
                        'rc_old_len'    => $oldSize,
                        'rc_new_len'    => $newSize,
@@ -450,7 +450,7 @@ class RecentChange {
         * @return RecentChange
         */
        public static function notifyNew( $timestamp, &$title, $minor, &$user, $comment, $bot,
-               $ip='', $size=0, $newId=0, $patrol=0 ) {
+               $ip = '', $size = 0, $newId = 0, $patrol = 0 ) {
                $rc = new RecentChange;
                $rc->mTitle = $title;
                $rc->mPerformer = $user;
@@ -469,7 +469,7 @@ class RecentChange {
                        'rc_last_oldid'     => 0,
                        'rc_bot'            => $bot ? 1 : 0,
                        'rc_ip'             => self::checkIPAddress( $ip ),
-                       'rc_patrolled'      => intval($patrol),
+                       'rc_patrolled'      => intval( $patrol ),
                        'rc_new'            => 1, # obsolete
                        'rc_old_len'        => 0,
                        'rc_new_len'        => $size,
@@ -506,11 +506,11 @@ class RecentChange {
         * @return bool
         */
        public static function notifyLog( $timestamp, &$title, &$user, $actionComment, $ip, $type,
-               $action, $target, $logComment, $params, $newId=0, $actionCommentIRC='' )
+               $action, $target, $logComment, $params, $newId = 0, $actionCommentIRC = '' )
        {
                global $wgLogRestrictions;
                # Don't add private logs to RC!
-               if( isset($wgLogRestrictions[$type]) && $wgLogRestrictions[$type] != '*' ) {
+               if ( isset( $wgLogRestrictions[$type] ) && $wgLogRestrictions[$type] != '*' ) {
                        return false;
                }
                $rc = self::newLogEntry( $timestamp, $title, $user, $actionComment, $ip, $type, $action,
@@ -535,7 +535,7 @@ class RecentChange {
         * @return RecentChange
         */
        public static function newLogEntry( $timestamp, &$title, &$user, $actionComment, $ip,
-               $type, $action, $target, $logComment, $params, $newId=0, $actionCommentIRC='' ) {
+               $type, $action, $target, $logComment, $params, $newId = 0, $actionCommentIRC = '' ) {
                global $wgRequest;
 
                $rc = new RecentChange;
@@ -583,7 +583,7 @@ class RecentChange {
         */
        public function loadFromRow( $row ) {
                $this->mAttribs = get_object_vars( $row );
-               $this->mAttribs['rc_timestamp'] = wfTimestamp(TS_MW, $this->mAttribs['rc_timestamp']);
+               $this->mAttribs['rc_timestamp'] = wfTimestamp( TS_MW, $this->mAttribs['rc_timestamp'] );
                $this->mAttribs['rc_deleted'] = $row->rc_deleted; // MUST be set
        }
 
@@ -594,7 +594,7 @@ class RecentChange {
         */
        public function loadFromCurRow( $row ) {
                $this->mAttribs = array(
-                       'rc_timestamp' => wfTimestamp(TS_MW, $row->rev_timestamp),
+                       'rc_timestamp' => wfTimestamp( TS_MW, $row->rev_timestamp ),
                        'rc_cur_time' => $row->rev_timestamp,
                        'rc_user' => $row->rev_user,
                        'rc_user_text' => $row->rev_user_text,
@@ -604,19 +604,19 @@ class RecentChange {
                        'rc_minor' => $row->rev_minor_edit ? 1 : 0,
                        'rc_type' => $row->page_is_new ? RC_NEW : RC_EDIT,
                        'rc_cur_id' => $row->page_id,
-                       'rc_this_oldid' => $row->rev_id,
-                       'rc_last_oldid' => isset($row->rc_last_oldid) ? $row->rc_last_oldid : 0,
-                       'rc_bot'        => 0,
+                       'rc_this_oldid' => $row->rev_id,
+                       'rc_last_oldid' => isset( $row->rc_last_oldid ) ? $row->rc_last_oldid : 0,
+                       'rc_bot' => 0,
                        'rc_ip' => '',
                        'rc_id' => $row->rc_id,
                        'rc_patrolled' => $row->rc_patrolled,
                        'rc_new' => $row->page_is_new, # obsolete
                        'rc_old_len' => $row->rc_old_len,
                        'rc_new_len' => $row->rc_new_len,
-                       'rc_params' => isset($row->rc_params) ? $row->rc_params : '',
-                       'rc_log_type' => isset($row->rc_log_type) ? $row->rc_log_type : null,
-                       'rc_log_action' => isset($row->rc_log_action) ? $row->rc_log_action : null,
-                       'rc_log_id' => isset($row->rc_log_id) ? $row->rc_log_id: 0,
+                       'rc_params' => isset( $row->rc_params ) ? $row->rc_params : '',
+                       'rc_log_type' => isset( $row->rc_log_type ) ? $row->rc_log_type : null,
+                       'rc_log_action' => isset( $row->rc_log_action ) ? $row->rc_log_action : null,
+                       'rc_logid' => isset( $row->rc_logid ) ? $row->rc_logid : 0,
                        'rc_deleted' => $row->rc_deleted // MUST be set
                );
        }
@@ -645,13 +645,13 @@ class RecentChange {
         * @return string
         */
        public function diffLinkTrail( $forceCur ) {
-               if( $this->mAttribs['rc_type'] == RC_EDIT ) {
-                       $trail = "curid=" . (int)($this->mAttribs['rc_cur_id']) .
-                               "&oldid=" . (int)($this->mAttribs['rc_last_oldid']);
-                       if( $forceCur ) {
+               if ( $this->mAttribs['rc_type'] == RC_EDIT ) {
+                       $trail = "curid=" . (int)( $this->mAttribs['rc_cur_id'] ) .
+                               "&oldid=" . (int)( $this->mAttribs['rc_last_oldid'] );
+                       if ( $forceCur ) {
                                $trail .= '&diff=0' ;
                        } else {
-                               $trail .= '&diff=' . (int)($this->mAttribs['rc_this_oldid']);
+                               $trail .= '&diff=' . (int)( $this->mAttribs['rc_this_oldid'] );
                        }
                } else {
                        $trail = '';
@@ -666,7 +666,7 @@ class RecentChange {
                global $wgUseRCPatrol, $wgUseNPPatrol, $wgRC2UDPInterwikiPrefix, $wgLocalInterwiki,
                        $wgCanonicalServer, $wgScript;
 
-               if( $this->mAttribs['rc_type'] == RC_LOG ) {
+               if ( $this->mAttribs['rc_type'] == RC_LOG ) {
                        // Don't use SpecialPage::getTitleFor, backwards compatibility with
                        // IRC API which expects "Log".
                        $titleObj = Title::newFromText( 'Log/' . $this->mAttribs['rc_log_type'], NS_SPECIAL );
@@ -676,11 +676,11 @@ class RecentChange {
                $title = $titleObj->getPrefixedText();
                $title = self::cleanupForIRC( $title );
 
-               if( $this->mAttribs['rc_type'] == RC_LOG ) {
+               if ( $this->mAttribs['rc_type'] == RC_LOG ) {
                        $url = '';
                } else {
                        $url = $wgCanonicalServer . $wgScript;
-                       if( $this->mAttribs['rc_type'] == RC_NEW ) {
+                       if ( $this->mAttribs['rc_type'] == RC_NEW ) {
                                $query = '?oldid=' . $this->mAttribs['rc_this_oldid'];
                        } else {
                                $query = '?diff=' . $this->mAttribs['rc_this_oldid'] . '&oldid=' . $this->mAttribs['rc_last_oldid'];
@@ -693,11 +693,11 @@ class RecentChange {
                        $url .= $query;
                }
 
-               if( $this->mAttribs['rc_old_len'] !== null && $this->mAttribs['rc_new_len'] !== null ) {
+               if ( $this->mAttribs['rc_old_len'] !== null && $this->mAttribs['rc_new_len'] !== null ) {
                        $szdiff = $this->mAttribs['rc_new_len'] - $this->mAttribs['rc_old_len'];
-                       if($szdiff < -500) {
+                       if ( $szdiff < -500 ) {
                                $szdiff = "\002$szdiff\002";
-                       } elseif($szdiff >= 0) {
+                       } elseif ( $szdiff >= 0 ) {
                                $szdiff = '+' . $szdiff ;
                        }
                        // @todo i18n with parentheses in content language?
@@ -750,13 +750,13 @@ class RecentChange {
         * @return string
         */
        public function getCharacterDifference( $old = 0, $new = 0 ) {
-               if( $old === 0 ) {
+               if ( $old === 0 ) {
                        $old = $this->mAttribs['rc_old_len'];
                }
-               if( $new === 0 ) {
+               if ( $new === 0 ) {
                        $new = $this->mAttribs['rc_new_len'];
                }
-               if( $old === null || $new === null ) {
+               if ( $old === null || $new === null ) {
                        return '';
                }
                return ChangesList::showCharacterDifference( $old, $new );
@@ -770,8 +770,9 @@ class RecentChange {
                        }
                } else {
                        $ip = $wgRequest->getIP();
-                       if( !$ip )
+                       if ( !$ip ) {
                                $ip = '';
+                       }
                }
                return $ip;
        }
index 8919f10..2c4ea47 100644 (file)
@@ -387,9 +387,9 @@ class Sanitizer {
                        $htmlsingleonly = array( # Elements that cannot have close tags
                                'br', 'hr'
                        );
-                       $htmlnest = array( # Tags that can be nested--??
+                       $htmlnest = array( # Tags that can be nested directly or indirectly
                                'table', 'tr', 'td', 'th', 'div', 'blockquote', 'ol', 'ul',
-                               'dl', 'font', 'big', 'small', 'sub', 'sup', 'span'
+                               'li', 'dl', 'dt', 'dd', 'font', 'big', 'small', 'sub', 'sup', 'span'
                        );
                        $tabletags = array( # Can only appear inside table, we will close them
                                'td', 'th', 'tr',
@@ -510,6 +510,10 @@ class Sanitizer {
                                                } elseif ( isset( $htmlsingle[$t] ) ) {
                                                        # Hack to not close $htmlsingle tags
                                                        $brace = null;
+                                                       # Still need to push this optionally-closed tag to
+                                                       # the tag stack so that we can match end tags
+                                                       # instead of marking them as bad.
+                                                       array_push( $tagstack, $t );
                                                } elseif ( isset( $tabletags[$t] )
                                                && in_array( $t, $tagstack ) ) {
                                                        // New table tag but forgot to close the previous one
index 24d48bc..9e5613e 100644 (file)
@@ -73,7 +73,7 @@ abstract class Skin extends ContextSource {
                return $wgValidSkinNames;
        }
 
-       /**
+       /**
         * Fetch the skinname messages for available skins.
         * @return array of strings
         */
index a72c1af..9442869 100644 (file)
@@ -522,7 +522,7 @@ class SpecialPage {
         */
        public function isRestricted() {
                // DWIM: If all anons can do something, then it is not restricted
-               return $this->mRestriction != '' && User::groupHasPermission( '*', $this->mRestriction );
+               return $this->mRestriction != '' && !User::groupHasPermission( '*', $this->mRestriction );
        }
 
        /**
index a7bea9d..00fdc3a 100644 (file)
@@ -1398,7 +1398,7 @@ class Title {
         *
 
         * @param $query string|array an optional query string,
-        *   not used for interwiki     links. Can be specified as an associative array as well,
+        *   not used for interwiki links. Can be specified as an associative array as well,
         *   e.g., array( 'action' => 'edit' ) (keys and values will be URL-escaped).
         *   Some query patterns will trigger various shorturl path replacements.
         * @param $query2 Mixed: An optional secondary query array. This one MUST
@@ -2930,6 +2930,8 @@ class Title {
                        // TODO: check the assumption that the cache actually knows about this title
                        // and handle this, such as get the title from the database.
                        // See https://bugzilla.wikimedia.org/show_bug.cgi?id=37209
+                       wfDebug( "LinkCache doesn't currently know about this title: " . $this->getPrefixedDBkey() );
+                       wfDebug( wfBacktrace() );
                }
 
                $this->mRedirect = (bool)$cached;
@@ -2957,7 +2959,8 @@ class Title {
                if ( $cached === null ) { # check the assumption that the cache actually knows about this title
                        # XXX: this does apparently happen, see https://bugzilla.wikimedia.org/show_bug.cgi?id=37209
                        #      as a stop gap, perhaps log this, but don't throw an exception?
-                       throw new MWException( "LinkCache doesn't currently know about this title: " . $this->getPrefixedDBkey() );
+                       wfDebug( "LinkCache doesn't currently know about this title: " . $this->getPrefixedDBkey() );
+                       wfDebug( wfBacktrace() );
                }
 
                $this->mLength = intval( $cached );
@@ -4471,7 +4474,7 @@ class Title {
 
        /**
         * Update page_touched timestamps and send squid purge messages for
-        * pages linking to this title. May be sent to the job queue depending
+        * pages linking to this title. May be sent to the job queue depending
         * on the number of links. Typically called on create and delete.
         */
        public function touchLinks() {
index a197077..e210eba 100644 (file)
@@ -455,11 +455,12 @@ class User {
         * will be loaded once more from the database when accessing them.
         *
         * @param $row Array A row from the user table
+        * @param $data Array Further data to load into the object (see User::loadFromRow for valid keys)
         * @return User
         */
-       public static function newFromRow( $row ) {
+       public static function newFromRow( $row, $data = null ) {
                $user = new User;
-               $user->loadFromRow( $row );
+               $user->loadFromRow( $row, $data );
                return $user;
        }
 
@@ -1036,8 +1037,12 @@ class User {
         * Initialize this object from a row from the user table.
         *
         * @param $row Array Row from the user table to load.
+        * @param $data Array Further user data to load into the object
+        *
+        *      user_groups             Array with groups out of the user_groups table
+        *      user_properties         Array with properties out of the user_properties table
         */
-       public function loadFromRow( $row ) {
+       public function loadFromRow( $row, $data = null ) {
                $all = true;
 
                $this->mGroups = null; // deferred
@@ -1095,6 +1100,15 @@ class User {
                if ( $all ) {
                        $this->mLoadedItems = true;
                }
+
+               if ( is_array( $data ) ) {
+                       if ( is_array( $data['user_groups'] ) ) {
+                               $this->mGroups = $data['user_groups'];
+                       }
+                       if ( is_array( $data['user_properties'] ) ) {
+                               $this->loadOptions( $data['user_properties'] );
+                       }
+               }
        }
 
        /**
@@ -4128,9 +4142,11 @@ class User {
        }
 
        /**
-        * @todo document
+        * Load the user options either from cache, the database or an array
+        *
+        * @param $data Rows for the current user out of the user_properties table
         */
-       protected function loadOptions() {
+       protected function loadOptions( $data = null ) {
                global $wgContLang;
 
                $this->load();
@@ -4160,21 +4176,27 @@ class User {
                                $this->mOptions[$key] = $value;
                        }
                } else {
-                       wfDebug( "User: loading options for user " . $this->getId() . " from database.\n" );
-                       // Load from database
-                       $dbr = wfGetDB( DB_SLAVE );
-
-                       $res = $dbr->select(
-                               'user_properties',
-                               array( 'up_property', 'up_value' ),
-                               array( 'up_user' => $this->getId() ),
-                               __METHOD__
-                       );
+                       if( !is_array( $data ) ) {
+                               wfDebug( "User: loading options for user " . $this->getId() . " from database.\n" );
+                               // Load from database
+                               $dbr = wfGetDB( DB_SLAVE );
 
-                       $this->mOptionOverrides = array();
-                       foreach ( $res as $row ) {
-                               $this->mOptionOverrides[$row->up_property] = $row->up_value;
-                               $this->mOptions[$row->up_property] = $row->up_value;
+                               $res = $dbr->select(
+                                       'user_properties',
+                                       array( 'up_property', 'up_value' ),
+                                       array( 'up_user' => $this->getId() ),
+                                       __METHOD__
+                               );
+
+                               $this->mOptionOverrides = array();
+                               $data = array();
+                               foreach ( $res as $row ) {
+                                       $data[$row->up_property] = $row->up_value;
+                               }
+                       }
+                       foreach ( $data as $property => $value ) {
+                               $this->mOptionOverrides[$property] = $value;
+                               $this->mOptions[$property] = $value;
                        }
                }
 
index 9830f69..b9ce9e0 100644 (file)
@@ -273,7 +273,7 @@ class UserMailer {
                        }
                        wfRestoreWarnings();
                        return Status::newGood();
-               } else  {
+               } else {
                        #
                        # PHP mail()
                        #
index 7005416..e251ac5 100644 (file)
@@ -382,7 +382,7 @@ class WebRequest {
 
        /**
         * Unset an arbitrary value from our get/post data.
-        *
+        *
         * @param $key String: key name to use
         * @return Mixed: old value if one was present, null otherwise
         */
@@ -1047,11 +1047,17 @@ HTML;
         * @return String
         */
        protected function getRawIP() {
-               if ( isset( $_SERVER['REMOTE_ADDR'] ) ) {
-                       return IP::canonicalize( $_SERVER['REMOTE_ADDR'] );
-               } else {
+               if ( !isset( $_SERVER['REMOTE_ADDR'] ) ) {
                        return null;
                }
+
+               if ( is_array( $_SERVER['REMOTE_ADDR'] ) || strpos( $_SERVER['REMOTE_ADDR'], ',' ) !== false ) {
+                       throw new MWException( __METHOD__ . " : Could not determine the remote IP address due to multiple values." );
+               } else {
+                       $ipchain = $_SERVER['REMOTE_ADDR'];
+               }
+
+               return IP::canonicalize( $ipchain );
        }
 
        /**
index 7a6b37d..d4840cc 100644 (file)
@@ -574,9 +574,6 @@ class MediaWiki {
                // Execute a job from the queue
                $this->doJobs();
 
-               // Log message usage, if $wgAdaptiveMessageCache is set to true
-               MessageCache::logMessages();
-
                // Log profiling data, e.g. in the database or UDP
                wfLogProfilingData();
 
index 2f8ba0f..67f3658 100644 (file)
@@ -576,7 +576,8 @@ class Xml {
         */
        public static function textarea( $name, $content, $cols = 40, $rows = 5, $attribs = array() ) {
                return self::element( 'textarea',
-                                       array(  'name' => $name,
+                                       array(
+                                               'name' => $name,
                                                'id' => $name,
                                                'cols' => $cols,
                                                'rows' => $rows
index 1513e7d..1b176e7 100644 (file)
@@ -775,6 +775,9 @@ abstract class ApiBase extends ContextSource {
                        if ( !$titleObj ) {
                                $this->dieUsageMsg( array( 'invalidtitle', $params['title'] ) );
                        }
+                       if ( !$titleObj->canExist() ) {
+                               $this->dieUsage( "Namespace doesn't allow actual pages", 'pagecannotexist' );
+                       }
                        $pageObj = WikiPage::factory( $titleObj );
                        if ( $load !== false ) {
                                $pageObj->loadPageData( $load );
index ca62bc6..ec1b06e 100644 (file)
@@ -568,7 +568,7 @@ class ApiEditPage extends ApiBase {
                        'watch' => 'Add the page to your watchlist',
                        'unwatch' => 'Remove the page from your watchlist',
                        'watchlist' => 'Unconditionally add or remove the page from your watchlist, use preferences or do not change watch',
-                       'md5' => array( "The MD5 hash of the {$p}text parameter, or the {$p}prependtext and {$p}appendtext parameters concatenated.",
+                       'md5' => array( "The MD5 hash of the {$p}text parameter, or the {$p}prependtext and {$p}appendtext parameters concatenated.",
                                        'If set, the edit won\'t be done unless the hash is correct' ),
                        'prependtext' => "Add this text to the beginning of the page. Overrides {$p}text",
                        'appendtext' => array( "Add this text to the end of the page. Overrides {$p}text.",
index 3aa51b7..a399c1e 100644 (file)
@@ -119,7 +119,7 @@ class ApiMain extends ApiBase {
                        'msg' => 'Use of the write API',
                        'params' => array()
                ),
-               'apihighlimits' => array(
+               'apihighlimits' => array(
                        'msg' => 'Use higher limits in API queries (Slow queries: $1 results; Fast queries: $2 results). The limits for slow queries also apply to multivalue parameters.',
                        'params' => array( ApiBase::LIMIT_SML2, ApiBase::LIMIT_BIG2 )
                )
index 1a55d5a..fae8e69 100644 (file)
@@ -165,6 +165,9 @@ class ApiParse extends ApiBase {
                        if ( !$titleObj ) {
                                $this->dieUsageMsg( array( 'invalidtitle', $title ) );
                        }
+                       if ( !$titleObj->canExist() ) {
+                               $this->dieUsage( "Namespace doesn't allow actual pages", 'pagecannotexist' );
+                       }
                        $wgTitle = $titleObj;
                        $pageObj = WikiPage::factory( $titleObj );
 
@@ -353,7 +356,7 @@ class ApiParse extends ApiBase {
        private function getParsedContent( WikiPage $page, $popts, $pageId = null, $getWikitext = false ) {
                $this->content = $page->getContent( Revision::RAW ); //XXX: really raw?
 
-               if ( $this->section !== false ) {
+               if ( $this->section !== false && $this->content !== null ) {
                        $this->content = $this->getSectionContent(
                                $this->content,
                                !is_null( $pageId ) ? 'page id ' . $pageId : $page->getTitle()->getText() );
@@ -652,6 +655,7 @@ class ApiParse extends ApiBase {
                        array( 'invalidtitle', 'title' ),
                        array( 'code' => 'parseerror', 'info' => 'Failed to parse the given text.' ),
                        array( 'code' => 'notwikitext', 'info' => 'The requested operation is only supported on wikitext content.' ),
+                       array( 'code' => 'pagecannotexist', 'info' => "Namespace doesn't allow actual pages" ),
                ) );
        }
 
index dff7524..d24745c 100644 (file)
@@ -545,7 +545,7 @@ class ApiQuery extends ApiBase {
         * @param  $pageSet ApiPageSet Pages to be exported
         * @param  $result ApiResult Result to output to
         */
-       private function doExport( $pageSet, $result )  {
+       private function doExport( $pageSet, $result ) {
                $exportTitles = array();
                $titles = $pageSet->getGoodTitles();
                if ( count( $titles ) ) {
index 96b8696..a8d4a7c 100644 (file)
@@ -301,7 +301,7 @@ class ApiQueryBlocks extends ApiQueryBase {
                        'dir' => $this->getDirectionDescription( $p ),
                        'ids' => 'List of block IDs to list (optional)',
                        'users' => 'List of users to search for (optional)',
-                       'ip' => array(  'Get all blocks applying to this IP or CIDR range, including range blocks.',
+                       'ip' => array( 'Get all blocks applying to this IP or CIDR range, including range blocks.',
                                        'Cannot be used together with bkusers. CIDR ranges broader than /16 are not accepted' ),
                        'limit' => 'The maximum amount of blocks to list',
                        'prop' => array(
index b617ed0..e5cea96 100644 (file)
@@ -394,7 +394,7 @@ class ApiQueryInfo extends ApiQueryBase {
                        }
                }
 
-               if ( $this->fld_talkid && isset( $this->talkids[$ns][$dbkey] ) )        {
+               if ( $this->fld_talkid && isset( $this->talkids[$ns][$dbkey] ) ) {
                        $pageInfo['talkid'] = $this->talkids[$ns][$dbkey];
                }
 
index ace2105..f0c2b1b 100644 (file)
@@ -94,8 +94,8 @@ abstract class ApiQueryORM extends ApiQueryBase {
        }
 
        /**
-        * Get the request parameters, handle the * value for the props param
-        * and remove all params set to null (ie those that are not actually provided).
+        * Get the request parameters and remove all params set
+        * to null (ie those that are not actually provided).
         *
         * @since 1.21
         *
index bf438d1..1cf8e31 100644 (file)
@@ -110,19 +110,39 @@ class ApiQueryUsers extends ApiQueryBase {
                        $this->addFields( User::selectFields() );
                        $this->addWhereFld( 'user_name', $goodNames );
 
-                       if ( isset( $this->prop['groups'] ) || isset( $this->prop['rights'] ) ) {
-                               $this->addTables( 'user_groups' );
-                               $this->addJoinConds( array( 'user_groups' => array( 'LEFT JOIN', 'ug_user=user_id' ) ) );
-                               $this->addFields( 'ug_group' );
-                       }
-
                        $this->showHiddenUsersAddBlockInfo( isset( $this->prop['blockinfo'] ) );
 
                        $data = array();
                        $res = $this->select( __METHOD__ );
+                       $this->resetQueryParams();
+
+                       // get user groups if needed
+                       if ( isset( $this->prop['groups'] ) || isset( $this->prop['rights'] ) ) {
+                               $userGroups = array();
+
+                               $this->addTables( 'user' );
+                               $this->addWhereFld( 'user_name', $goodNames );
+                               $this->addTables( 'user_groups' );
+                               $this->addJoinConds( array( 'user_groups' => array( 'INNER JOIN', 'ug_user=user_id' ) ) );
+                               $this->addFields( array('user_name', 'ug_group') );
+                               $userGroupsRes = $this->select( __METHOD__ );
+
+                               foreach( $userGroupsRes as $row ) {
+                                       $userGroups[$row->user_name][] = $row->ug_group;
+                               }
+                       }
 
                        foreach ( $res as $row ) {
-                               $user = User::newFromRow( $row );
+                               // create user object and pass along $userGroups if set
+                               // that reduces the number of database queries needed in User dramatically
+                               if ( !isset( $userGroups ) ) {
+                                       $user = User::newFromRow( $row );
+                               } else {
+                                       if ( !is_array( $userGroups[$row->user_name] ) ) {
+                                               $userGroups[$row->user_name] = array();
+                                       }
+                                       $user = User::newFromRow( $row, array( 'user_groups' => $userGroups[$row->user_name] ) );
+                               }
                                $name = $user->getName();
 
                                $data[$name]['userid'] = $user->getId();
@@ -137,29 +157,15 @@ class ApiQueryUsers extends ApiQueryBase {
                                }
 
                                if ( isset( $this->prop['groups'] ) ) {
-                                       if ( !isset( $data[$name]['groups'] ) ) {
-                                               $data[$name]['groups'] = $user->getAutomaticGroups();
-                                       }
-
-                                       if ( !is_null( $row->ug_group ) ) {
-                                               // This row contains only one group, others will be added from other rows
-                                               $data[$name]['groups'][] = $row->ug_group;
-                                       }
+                                       $data[$name]['groups'] = $user->getEffectiveGroups();
                                }
 
-                               if ( isset( $this->prop['implicitgroups'] ) && !isset( $data[$name]['implicitgroups'] ) ) {
+                               if ( isset( $this->prop['implicitgroups'] ) ) {
                                        $data[$name]['implicitgroups'] =  $user->getAutomaticGroups();
                                }
 
                                if ( isset( $this->prop['rights'] ) ) {
-                                       if ( !isset( $data[$name]['rights'] ) ) {
-                                               $data[$name]['rights'] = User::getGroupPermissions( $user->getAutomaticGroups() );
-                                       }
-
-                                       if ( !is_null( $row->ug_group ) ) {
-                                               $data[$name]['rights'] = array_unique( array_merge( $data[$name]['rights'],
-                                                       User::getGroupPermissions( array( $row->ug_group ) ) ) );
-                                       }
+                                       $data[$name]['rights'] = $user->getRights();
                                }
                                if ( $row->ipb_deleted ) {
                                        $data[$name]['hidden'] = '';
index 0a3c002..51a28ca 100644 (file)
@@ -228,33 +228,3 @@ class HTMLCacheUpdate implements DeferrableUpdate {
                }
        }
 }
-
-
-/**
- * Job wrapper for HTMLCacheUpdate. Gets run whenever a related
- * job gets called from the queue.
- *
- * @ingroup JobQueue
- */
-class HTMLCacheUpdateJob extends Job {
-       var $table, $start, $end;
-
-       /**
-        * Construct a job
-        * @param $title Title: the title linked to
-        * @param $params Array: job parameters (table, start and end page_ids)
-        * @param $id Integer: job id
-        */
-       function __construct( $title, $params, $id = 0 ) {
-               parent::__construct( 'htmlCacheUpdate', $title, $params, $id );
-               $this->table = $params['table'];
-               $this->start = $params['start'];
-               $this->end = $params['end'];
-       }
-
-       public function run() {
-               $update = new HTMLCacheUpdate( $this->title, $this->table, $this->start, $this->end );
-               $update->doUpdate();
-               return true;
-       }
-}
index e061101..148e26b 100644 (file)
@@ -59,26 +59,6 @@ class MessageCache {
        /// Variable for tracking which variables are already loaded
        protected $mLoadedLanguages = array();
 
-       /**
-        * Used for automatic detection of most used messages.
-        */
-       protected $mRequestedMessages = array();
-
-       /**
-        * How long the message request counts are stored. Longer period gives
-        * better sample, but also takes longer to adapt changes. The counts
-        * are aggregrated per day, regardless of the value of this variable.
-        */
-       protected static $mAdaptiveDataAge = 604800; // Is 7*24*3600
-
-       /**
-        * Filter the tail of less used messages that are requested more seldom
-        * than this factor times the number of request of most requested message.
-        * These messages are not loaded in the default set, but are still cached
-        * individually on demand with the normal cache expiry time.
-        */
-       protected static $mAdaptiveInclusionThreshold = 0.05;
-
        /**
         * Singleton instance
         *
@@ -404,19 +384,20 @@ class MessageCache {
                );
 
                $mostused = array();
-               if ( $wgAdaptiveMessageCache ) {
-                       $mostused = $this->getMostUsedMessages();
-                       if ( $code !== $wgLanguageCode ) {
-                               foreach ( $mostused as $key => $value ) {
-                                       $mostused[$key] = "$value/$code";
-                               }
+               if ( $wgAdaptiveMessageCache && $code !== $wgLanguageCode ) {
+                       if ( !isset( $this->mCache[$wgLanguageCode] ) ) {
+                               $this->load( $wgLanguageCode );
+                       }
+                       $mostused = array_keys( $this->mCache[$wgLanguageCode] );
+                       foreach ( $mostused as $key => $value ) {
+                               $mostused[$key] = "$value/$code";
                        }
                }
 
                if ( count( $mostused ) ) {
                        $conds['page_title'] = $mostused;
                } elseif ( $code !== $wgLanguageCode ) {
-                       $conds[] = 'page_title' . $dbr->buildLike( $dbr->anyString(), "/$code" );
+                       $conds[] = 'page_title' . $dbr->buildLike( $dbr->anyString(), '/', $code );
                } else {
                        # Effectively disallows use of '/' character in NS_MEDIAWIKI for uses
                        # other than language code.
@@ -459,12 +440,6 @@ class MessageCache {
                        $cache[$row->page_title] = $entry;
                }
 
-               foreach ( $mostused as $key ) {
-                       if ( !isset( $cache[$key] ) ) {
-                               $cache[$key] = '!NONEXISTENT';
-                       }
-               }
-
                $cache['VERSION'] = MSG_CACHE_VERSION;
                wfProfileOut( __METHOD__ );
                return $cache;
@@ -646,13 +621,6 @@ class MessageCache {
                        $uckey = $wgContLang->ucfirst( $lckey );
                }
 
-               /**
-                * Record each message request, but only once per request.
-                * This information is not used unless $wgAdaptiveMessageCache
-                * is enabled.
-                */
-               $this->mRequestedMessages[$uckey] = true;
-
                # Try the MediaWiki namespace
                if( !$this->mDisable && $useDB ) {
                        $title = $uckey;
@@ -719,8 +687,6 @@ class MessageCache {
         * @return string|bool False on failure
         */
        function getMsgFromNamespace( $title, $code ) {
-               global $wgAdaptiveMessageCache;
-
                $this->load( $code );
                if ( isset( $this->mCache[$code][$title] ) ) {
                        $entry = $this->mCache[$code][$title];
@@ -739,15 +705,7 @@ class MessageCache {
                                return $message;
                        }
 
-                       /**
-                        * If message cache is in normal mode, it is guaranteed
-                        * (except bugs) that there is always entry (or placeholder)
-                        * in the cache if message exists. Thus we can do minor
-                        * performance improvement and return false early.
-                        */
-                       if ( !$wgAdaptiveMessageCache ) {
-                               return false;
-                       }
+                       return false;
                }
 
                # Try the individual message cache
@@ -907,7 +865,7 @@ class MessageCache {
         */
        function clear() {
                $langs = Language::fetchLanguageNames( null, 'mw' );
-               foreach ( array_keys($langs) as $code ) {
+               foreach ( array_keys( $langs ) as $code ) {
                        # Global cache
                        $this->mMemc->delete( wfMemcKey( 'messages', $code ) );
                        # Invalidate all local caches
@@ -936,82 +894,6 @@ class MessageCache {
                return array( $message, $lang );
        }
 
-       public static function logMessages() {
-               wfProfileIn( __METHOD__ );
-               global $wgAdaptiveMessageCache;
-               if ( !$wgAdaptiveMessageCache || !self::$instance instanceof MessageCache ) {
-                       wfProfileOut( __METHOD__ );
-                       return;
-               }
-
-               $cachekey = wfMemckey( 'message-profiling' );
-               $cache = wfGetCache( CACHE_DB );
-               $data = $cache->get( $cachekey );
-
-               if ( !$data ) {
-                       $data = array();
-               }
-
-               $age = self::$mAdaptiveDataAge;
-               $filterDate = substr( wfTimestamp( TS_MW, time() - $age ), 0, 8 );
-               foreach ( array_keys( $data ) as $key ) {
-                       if ( $key < $filterDate ) {
-                               unset( $data[$key] );
-                       }
-               }
-
-               $index = substr( wfTimestampNow(), 0, 8 );
-               if ( !isset( $data[$index] ) ) {
-                       $data[$index] = array();
-               }
-
-               foreach ( self::$instance->mRequestedMessages as $message => $_ ) {
-                       if ( !isset( $data[$index][$message] ) ) {
-                               $data[$index][$message] = 0;
-                       }
-                       $data[$index][$message]++;
-               }
-
-               $cache->set( $cachekey, $data );
-               wfProfileOut( __METHOD__ );
-       }
-
-       /**
-        * @return array
-        */
-       public function getMostUsedMessages() {
-               wfProfileIn( __METHOD__ );
-               $cachekey = wfMemcKey( 'message-profiling' );
-               $cache = wfGetCache( CACHE_DB );
-               $data = $cache->get( $cachekey );
-               if ( !$data ) {
-                       wfProfileOut( __METHOD__ );
-                       return array();
-               }
-
-               $list = array();
-
-               foreach( $data as $messages ) {
-                       foreach( $messages as $message => $count ) {
-                               $key = $message;
-                               if ( !isset( $list[$key] ) ) {
-                                       $list[$key] = 0;
-                               }
-                               $list[$key] += $count;
-                       }
-               }
-
-               $max = max( $list );
-               foreach ( $list as $message => $count ) {
-                       if ( $count < intval( $max * self::$mAdaptiveInclusionThreshold ) ) {
-                               unset( $list[$message] );
-                       }
-               }
-
-               wfProfileOut( __METHOD__ );
-               return array_keys( $list );
-       }
-
        /**
         * Get all message keys stored in the message cache for a given language.
         * If $code is the content language code, this will return all message keys
index 9c4c3af..8e8de4b 100644 (file)
@@ -802,20 +802,21 @@ abstract class ContentHandler {
                $content = $rev->getContent();
                $blank = false;
 
-               $this->checkModelID( $content->getModel() );
-
                // If the page is blank, use the text from the previous revision,
                // which can only be blank if there's a move/import/protect dummy
                // revision involved
-               if ( $content->getSize() == 0 ) {
+               if ( !$content || $content->isEmpty() ) {
                        $prev = $rev->getPrevious();
 
-                       if ( $prev )    {
-                               $content = $prev->getContent();
+                       if ( $prev ) {
+                               $rev = $prev;
+                               $content = $rev->getContent();
                                $blank = true;
                        }
                }
 
+               $this->checkModelID( $rev->getContentModel() );
+
                // Find out if there was only one contributor
                // Only scan the last 20 revisions
                $res = $dbw->select( 'revision', 'rev_user_text',
@@ -871,7 +872,7 @@ abstract class ContentHandler {
                }
 
                // Max content length = max comment length - length of the comment (excl. $1)
-               $text = $content->getTextForSummary( 255 - ( strlen( $reason ) - 2 ) );
+               $text = $content ? $content->getTextForSummary( 255 - ( strlen( $reason ) - 2 ) ) : '';
 
                // Now replace the '$1' placeholder
                $reason = str_replace( '$1', $text, $reason );
index 74c5a88..048ac39 100644 (file)
@@ -32,6 +32,10 @@ class TextContent extends AbstractContent {
        public function __construct( $text, $model_id = CONTENT_MODEL_TEXT ) {
                parent::__construct( $model_id );
 
+               if ( $text === null || $text === false ) {
+                       $text = '';
+               }
+
                if ( !is_string( $text ) ) {
                        throw new MWException( "TextContent expects a string in the constructor." );
                }
index 48aac9d..db050f2 100644 (file)
@@ -290,6 +290,13 @@ abstract class DatabaseBase implements DatabaseType {
                return $this->getServerVersion();
        }
 
+       /**
+        * @return string: command delimiter used by this database engine
+        */
+       public function getDelimiter() {
+               return $this->delimiter;
+       }
+
        /**
         * Boolean, controls output of large amounts of debug information.
         * @param $debug bool|null
@@ -1800,7 +1807,7 @@ abstract class DatabaseBase implements DatabaseType {
                                $list .= "$value";
                        } elseif ( ( $mode == LIST_AND || $mode == LIST_OR ) && is_array( $value ) ) {
                                if ( count( $value ) == 0 ) {
-                                       throw new MWException( __METHOD__ . ': empty input' );
+                                       throw new MWException( __METHOD__ . ": empty input for field $field" );
                                } elseif ( count( $value ) == 1 ) {
                                        // Special-case single values, as IN isn't terribly efficient
                                        // Don't necessarily assume the single key is 0; we don't
index 72eb5d3..05e2cd2 100644 (file)
@@ -311,7 +311,7 @@ class _DiffEngine {
         * [XOFF, XLIM) and [YOFF, YLIM) into NCHUNKS approximately equally
         * sized segments.
         *
-        * Returns (LCS, PTS).  LCS is the length of the LCS. PTS is an
+        * Returns (LCS, PTS). LCS is the length of the LCS. PTS is an
         * array of NCHUNKS+1 (X, Y) indexes giving the diving points between
         * sub sequences.  The first sub-sequence is contained in [X0, X1),
         * [Y0, Y1), the second in [X1, X2), [Y1, Y2) and so on.  Note
diff --git a/includes/filebackend/README b/includes/filebackend/README
new file mode 100644 (file)
index 0000000..6ab5481
--- /dev/null
@@ -0,0 +1,208 @@
+/*!
+\ingroup FileBackend
+\page file_backend_design File backend design
+
+Some notes on the FileBackend architecture.
+
+\section intro Introduction
+
+To abstract away the differences among different types of storage media,
+MediaWiki is providing an interface known as FileBackend. Any MediaWiki
+interaction with stored files should thus use a FileBackend object.
+
+Different types of backing storage media are supported (ranging from local
+file system to distributed object stores). The types include:
+
+* FSFileBackend (used for mounted file systems)
+* SwiftFileBackend (used for Swift or Ceph Rados+RGW object stores)
+* FileBackendMultiWrite (useful for transitioning from one backend to another)
+
+Configuration documentation for each type of backend is to be found in their
+__construct() inline documentation.
+
+
+\section setup Setup
+
+File backends are registered in LocalSettings.php via the global variable
+$wgFileBackends. To access one of those defined backends, one would use
+FileBackendStore::get( <name> ) which will bring back a FileBackend object
+handle. Such handles are reused for any subsequent get() call (via singleton).
+The FileBackends objects are caching request calls such as file stats,
+SHA1 requests or TCP connection handles.
+
+\par Note:
+Some backends may require additional PHP extensions to be enabled or can rely on a
+MediaWiki extension. This is often the case when a FileBackend subclass makes use of an
+upstream client API for communicating with the backing store.
+
+
+\section fileoperations File operations
+
+The MediaWiki FileBackend API supports various operations on either files or
+directories. See FileBackend.php for full documentation for each function.
+
+
+\subsection reading Reading
+
+The following basic operations are supported for reading from a backend:
+
+On files:
+* state a file for basic information (timestamp, size)
+* read a file into a string or  several files into a map of path names to strings
+* download a file or set of files to a temporary file (on a mounted file system)
+* get the SHA1 hash of a file
+* get various properties of a file (stat information, content time, mime information, ...)
+
+On directories:
+* get a list of files directly under a directory
+* get a recursive list of files under a directory
+* get a list of directories directly under a directory
+* get a recursive list of directories under a directory
+
+\par Note:
+Backend handles should return directory listings as iterators, all though in some cases
+they may just be simple arrays (which can still be iterated over). Iterators allow for
+callers to traverse a large number of file listings without consuming excessive RAM in
+the process. Either the memory consumed is flatly bounded (if the iterator does paging)
+or it is proportional to the depth of the portion of the directory tree being traversed
+(if the iterator works via recursion).
+
+
+\subsection writing Writing
+
+The following basic operations are supported for writing or changing in the backend:
+
+On files:
+* store (copying a mounted file system file into storage)
+* create (creating a file within storage from a string)
+* copy (within storage)
+* move (within storage)
+* delete (within storage)
+* lock/unlock (lock or unlock a file in storage)
+
+The following operations are supported for writing directories in the backend:
+* prepare (create parent container and directories for a path)
+* secure (try to lock-down access to a container)
+* publish (try to reverse the effects of secure)
+* clean (remove empty containers or directories)
+
+
+\subsection invokingoperation Invoking an operation
+
+Generally, callers should use doOperations() or doQuickOperations() when doing
+batches of changes, rather than making a suite of single operation calls. This
+makes the system tolerate high latency much better by pipelining operations
+when possible.
+
+doOperations() should be used for working on important original data, i.e. when
+consistency is important. The former will only pipeline operations that do not
+depend on each other. It is best if the operations that do not depend on each
+other occur in consecutive groups. This function can also log file changes to
+a journal (see FileJournal), which can be used to sync two backend instances.
+One might use this function for user uploads of file for example.
+
+doQuickOperations() is more geared toward ephemeral items that can be easily
+regenerated from original data. It will always pipeline without checking for
+dependencies within the operation batch. One might use this function for
+creating and purging generated thumbnails of original files for example.
+
+
+\section consistency Consistency
+
+Not all backing stores are sequentially consistent by default. Various FileBackend
+functions offer a "latest" option that can be passed in to assure (or try to assure)
+that the latest version of the file is read. Some backing stores are consistent by
+default, but callers should always assume that without this option, stale data may
+be read. This is actually true for stores that have eventual consistency.
+
+Note that file listing functions have no "latest" flag, and thus some systems may
+return stale data. Thus callers should avoid assuming that listings contain changes
+made my the current client or any other client from a very short time ago. For example,
+creating a file under a directory and then immediately doing a file listing operation
+on that directory may result in a listing that does not include that file.
+
+
+\section locking Locking
+
+Locking is effective if and only if a proper lock manager is registered and is
+actually being used by the backend. Lock managers can be registered in LocalSettings.php
+using the $wgLockManagers global configuration variable.
+
+For object stores, locking is not generally useful for avoiding partially
+written or read objects, since most stores use Multi Version Concurrency
+Control (MVCC) to avoid this. However, locking can be important when:
+* One or more operations must be done without objects changing in the meantime.
+* It can also be useful when a file read is used to determine a file write or DB change.
+  For example, doOperations() first checks that there will be no "file already exists"
+  or "file does not exist" type errors before attempting an operation batch. This works
+  by stating the files first, and is only safe if the files are locked in the meantime.
+
+When locking, callers should use the latest available file data for reads.
+Also, one should always lock the file *before* reading it, not after. If stale data is
+used to determine a write, there will be some data corruption, even when reads of the
+original file finally start returning the updated data without needing the "latest"
+option (eventual consistency). The "scoped" lock functions are preferable since
+there is not the problem of forgetting to unlock due to early returns or exceptions.
+
+Since acquiring locks can fail, and lock managers can be non-blocking, callers should:
+* Acquire all required locks up font
+* Be prepared for the case where locks fail to be acquired
+* Possible retry acquiring certain locks
+
+MVCC is also a useful pattern to use on top of the backend interface, because operations
+are not atomic, even with doOperations(), so doing complex batch file changes or changing
+files and updating a database row can result in partially written "transactions". Thus one
+should avoid changing files once they have been stored, except perhaps with ephemeral data
+that are tolerant of some degree of inconsistency.
+
+Callers can use their own locking (e.g. SELECT FOR UPDATE) if it is more convenient, but
+note that all callers that change any of the files should then go through functions that
+acquire these locks. For example, if a caller just directly uses the file backend store()
+function, it will ignore any custom "FOR UPDATE" locks, which can cause problems.
+
+\section objectstore Object stores
+
+Support for object stores (like Amazon S3/Swift) drive much of the API and design
+decisions of FileBackend, but using any POSIX compliant file systems works fine.
+The system essentially stores "files" in "containers". For a mounted file system
+as a backing store, "files" will just be files under directories. For an object store
+as a backing store, the "files" will be objects stored in actual containers.
+
+
+\section file_obj_diffs File system and Object store differences
+
+An advantage of object stores is the reduced Round-Trip Times. This is
+achieved by avoiding the need to create each parent directory before placing a
+file somewhere. It gets worse the deeper the directory hierarchy is. Another
+advantage of object stores is that object listings tend to use databases, which
+scale better than the linked list directories that file sytems sometimes use.
+File systems like btrfs and xfs use tree structures, which scale better.
+For both object stores and file systems, using "/" in filenames will allow for the
+intuitive use of directory functions. For example, creating a file in Swift
+called "container/a/b/file1" will mean that:
+- a "directory listing" of "container/a" will contain "b",
+- and a "file listing" of "b" will contain "file1"
+
+This means that switching from an object store to a file system and vise versa
+using the FileBackend interface will generally be harmless. However, one must be
+aware of some important differences:
+
+* In a file system, you cannot have a file and a directory within the same path
+  whereas it is possible in an object stores. Calling code should avoid any layouts
+  which allow files and directories at the same path.
+* Some file systems have file name length restrictions or overall path length
+  restrictions that others do not. The same goes with object stores which might
+  have a maximum object length or a limitation regarding the number of files
+  under a container or volume.
+* Latency varies among systems, certain access patterns may not be tolerable for
+  certain backends but may hold up for others. Some backend subclasses use
+  MediaWiki's object caching for serving stat requests, which can greatly
+  reduce latency. Making sure that the backend has pipelining (see the
+  "parallelize" and "concurrency" settings) enabled can also mask latency in
+  batch operation scenarios.
+* File systems may implement directories as linked-lists or other structures
+  with poor scalability, so calling code should use layouts that shard the data.
+  Instead of storing files like "container/file.txt", one can store files like
+  "container/<x>/<y>/file.txt". It is best if "sharding" optional or configurable.
+
+*/
index caa93a4..f42df55 100644 (file)
@@ -1759,7 +1759,7 @@ class LocalFileDeleteBatch {
                                        'fa_deleted_user'      => $encUserId,
                                        'fa_deleted_timestamp' => $encTimestamp,
                                        'fa_deleted_reason'    => $encReason,
-                                       'fa_deleted'               => $this->suppress ? $bitfield : 0,
+                                       'fa_deleted'           => $this->suppress ? $bitfield : 0,
 
                                        'fa_name'         => 'img_name',
                                        'fa_archive_name' => 'NULL',
index de59b2d..75ede23 100644 (file)
@@ -269,14 +269,15 @@ abstract class DatabaseInstaller {
 
                $ret = true;
                ob_start( array( $this, 'outputHandler' ) );
+               $up = DatabaseUpdater::newForDB( $this->db );
                try {
-                       $up = DatabaseUpdater::newForDB( $this->db );
                        $up->doUpdates();
                } catch ( MWException $e ) {
                        echo "\nAn error occurred:\n";
                        echo $e->getText();
                        $ret = false;
                }
+               $up->purgeCache();
                ob_end_flush();
                return $ret;
        }
index 7223003..740ead5 100644 (file)
@@ -292,8 +292,8 @@ abstract class DatabaseUpdater {
         *
         * @param $what Array: what updates to perform
         */
-       public function doUpdates( $what = array( 'core', 'extensions', 'purge', 'stats' ) ) {
-               global $wgLocalisationCacheConf, $wgVersion;
+       public function doUpdates( $what = array( 'core', 'extensions', 'stats' ) ) {
+               global $wgVersion;
 
                $this->db->begin( __METHOD__ );
                $what = array_flip( $what );
@@ -310,14 +310,6 @@ abstract class DatabaseUpdater {
                if ( isset( $what['stats'] ) ) {
                        $this->checkStats();
                }
-
-               if ( isset( $what['purge'] ) ) {
-                       $this->purgeCache();
-
-                       if ( $wgLocalisationCacheConf['manualRecache'] ) {
-                               $this->rebuildLocalisationCache();
-                       }
-               }
                $this->db->commit( __METHOD__ );
        }
 
@@ -617,11 +609,15 @@ abstract class DatabaseUpdater {
        /**
         * Purge the objectcache table
         */
-       protected function purgeCache() {
+       public function purgeCache() {
+               global $wgLocalisationCacheConf;
                # We can't guarantee that the user will be able to use TRUNCATE,
                # but we know that DELETE is available to us
                $this->output( "Purging caches..." );
                $this->db->delete( 'objectcache', '*', __METHOD__ );
+               if ( $wgLocalisationCacheConf['manualRecache'] ) {
+                       $this->rebuildLocalisationCache();
+               }
                $this->output( "done.\n" );
        }
 
index c60fbb0..80ecb1f 100644 (file)
@@ -784,104 +784,6 @@ See also:
 This might be a good place to put information about <nowiki>{{GRAMMAR:}}</nowiki>. See [[{{NAMESPACE}}:{{BASEPAGENAME}}/fi]] for an example. For languages having grammatical distinctions and not having an appropriate <nowiki>{{GRAMMAR:}}</nowiki> software available, a suggestion to check and possibly amend the messages having <nowiki>{{SITENAME}}</nowiki> may be valuable. See [[{{NAMESPACE}}:{{BASEPAGENAME}}/ksh]] for an example.',
 );
 
-/** Goan Konkani (Latin script) (Konknni)
- * @author The Discoverer
- */
-$messages['gom-latn'] = array(
-       'config-page-language' => 'Bhas',
-);
-
-/** Magyar (magázó) (Magyar (magázó))
- * @author Dani
- * @author Glanthor Reviol
- */
-$messages['hu-formal'] = array(
-       'config-localsettings-upgrade' => "'''Figyelmeztetés''': már létezik a <code>LocalSettings.php</code> fájl.
-A szoftver frissíthető.
-Adja meg a <code>\$wgUpgradeKey</code>-ben található kulcsot a beviteli mezőben",
-       'config-session-expired' => 'Úgy tűnik, hogy a munkamenetadatok lejártak.
-A munkamenetek élettartama a következőre van beállítva: $1.
-Az érték növelhető a php.ini <code>session.gc_maxlifetime</code> beállításának módosításával.
-Indítsa újra a telepítési folyamatot.',
-       'config-no-session' => 'Elvesztek a munkamenetadatok!
-Ellenőrizze, hogy a php.ini-ben a <code>session.save_path</code> beállítás a megfelelő könyvtárra mutat-e.',
-       'config-your-language-help' => 'Válassza ki a telepítési folyamat során használandó nyelvet.',
-       'config-wiki-language-help' => 'Az a nyelv, amin a wiki tartalmának legnagyobb része íródik.',
-       'config-page-welcome' => 'Üdvözli a MediaWiki!',
-       'config-help-restart' => 'Szeretné törölni az eddig megadott összes adatot és újraindítani a telepítési folyamatot?',
-       'config-welcome' => '=== Környezet ellenőrzése ===
-Alapvető ellenőrzés, ami megmondja, hogy a környezet alkalmas-e a MediaWiki számára.
-Ha probléma merülne fel a telepítés során, meg kell adnia mások számára az alább megjelenő információkat.',
-       'config-unicode-pure-php-warning' => "'''Figyelmeztetés''': Az [http://pecl.php.net/intl intl PECL kiterjesztés] nem érhető el Unicode normalizáláshoz.
-Ha nagy látogatottságú oldalt üzemeltet, itt találhat információkat [//www.mediawiki.org/wiki/Unicode_normalization_considerations a témáról].",
-       'config-register-globals' => "'''Figyelmeztetés: A PHP <code>[http://php.net/register_globals register_globals]</code> beállítása engedélyezve van.'''
-'''Tiltsa le, ha van rá lehetősége.'''
-A MediaWiki működőképes a beállítás használata mellett, de a szerver biztonsági kockázatnak lesz kitéve.",
-       'config-imagemagick' => 'Az ImageMagick megtalálható a rendszeren: <code>$1</code>.
-A bélyegképek készítése engedélyezve lesz, ha engedélyezi a feltöltéseket.',
-       'config-db-name-help' => 'Válassza ki a wikije azonosítására használt nevet.
-Nem tartalmazhat szóközt vagy kötőjelet.
-
-Ha megosztott webtárhelyet használ, a szolgáltatója vagy egy konkrét adatbázisnevet ad önnek használatra, vagy létrehozhat egyet a vezérlőpulton keresztül.',
-       'config-db-install-help' => 'Adja meg a felhasználónevet és jelszót, amivel a telepítő csatlakozhat az adatbázishoz.',
-       'config-db-wiki-help' => 'Adja meg azt a felhasználónevet és jelszót, amivel a wiki fog csatlakozni az adatbázishoz működés közben.
-Ha a fiók nem létezik és a telepítést végző fiók rendelkezik megfelelő jogosultsággal, egy új fiók készül a megadott a névvel, azon minimális jogosultságkörrel, ami a wiki működéséhez szükséges.',
-       'config-charset-help' => "'''Figyelmezetés:''' Ha a '''visszafelé kompatibilis UTF-8''' beállítást használja MySQL 4.1 vagy újabb verziók esetén, és utána a <code>mysqldump</code> programmal készít róla biztonsági másolatot, az tönkreteheti az összes nem ASCII-karaktert, visszafordíthatatlanul károsítva a másolatokban tárolt adatokat!
-
-'''Bináris''' módban a MediaWiki az UTF-8-ban kódolt szöveget bináris mezőkben tárolja az adatbázisban.
-Ez sokkal hatékonyabb a MySQL UTF-8-módjától, és lehetővé teszi, hogy a teljes Unicode-karakterkészletet használja.
-'''UTF-8-módban''' MySQL tudja, hogy milyen karakterkészlettel van kódolva az adat, megfelelően van megjelenítve és konvertálva, de
-nem használhatja a [//en.wikipedia.org/wiki/Mapping_of_Unicode_character_planes Basic Multilingual Plane] feletti karaktereket.",
-       'config-db-schema-help' => 'A fenti sémák általában megfelelőek.
-Csak akkor módosítson rajta, ha szükség van rá.',
-       'config-sqlite-parent-unwritable-nogroup' => 'Nem lehet létrehozni az adatok tárolásához szükséges <code><nowiki>$1</nowiki></code> könyvtárat, mert a webszerver nem írhat a szülőkönyvtárba (<code><nowiki>$2</nowiki></code>).
-
-A telepítő nem tudta megállapíteni, hogy melyik felhasználói fiókon fut a webszerver.
-A folytatáshoz tegye írhatóvá ezen fiók (és más fiókok!) számára a következő könyvtárat: <code><nowiki>$3</nowiki></code>.
-Unix/Linux rendszereken tedd a következőt:
-
-<pre>cd $2
-mkdir $3
-chmod a+w $3</pre>',
-       'config-ns-other' => 'Más (adja meg)',
-       'config-admin-name-blank' => 'Adja meg az adminisztrátor felhasználónevét!',
-       'config-admin-name-invalid' => 'A megadott felhasználónév (<nowiki>$1</nowiki>) érvénytelen.
-Adjon meg egy másik felhasználónevet.',
-       'config-admin-password-blank' => 'Adja meg az adminisztrátori fiók jelszavát!',
-       'config-instantcommons-help' => 'Az [//www.mediawiki.org/wiki/InstantCommons Instant Commons] lehetővé teszi, hogy a wikin használhassák a [//commons.wikimedia.org/ Wikimedia Commons] oldalon található képeket, hangokat és más médiafájlokat.
-A használatához a MediaWikinek internethozzáférésre van szüksége.
-
-A funkcióról és hogy hogyan állítható be más wikik esetén [//mediawiki.org/wiki/Manual:$wgForeignFileRepos a kézikönyvben] találhat további információkat.',
-       'config-install-done' => "'''Gratulálunk!'''
-Sikeresen telepítette a MediaWikit.
-
-A telepítő készített egy <code>LocalSettings.php</code> fájlt.
-Ez tartalmazza az összes beállítást.
-
-[$1 Le kell töltenie], és el kell helyeznie a MediaWiki telepítési könyvtárába (az a könyvtár, ahol az index.php van).
-'''Megjegyzés''': Ha ezt most nem teszi meg, és kilép, a generált fájl nem lesz elérhető a későbbiekben.
-
-Ha ezzel készen van, '''[$2 beléphet a wikibe]'''.",
-       'mainpagedocfooter' => "Ha segítségre van szüksége a wikiszoftver használatához, akkor keresse fel a [//meta.wikimedia.org/wiki/Help:Contents User's Guide] oldalt.
-
-== Alapok (angol nyelven) ==
-* [//www.mediawiki.org/wiki/Manual:Configuration_settings Beállítások listája]
-* [//www.mediawiki.org/wiki/Manual:FAQ MediaWiki GyIK]
-* [https://lists.wikimedia.org/mailman/listinfo/mediawiki-announce MediaWiki-kiadások levelezőlistája]",
-);
-
-/** Español (formal) (Español (formal))
- * @author Dferg
- */
-$messages['es-formal'] = array(
-       'mainpagedocfooter' => 'Consulte usted la [//meta.wikimedia.org/wiki/Ayuda:Contenido Guía de usuario] para obtener información sobre el uso del software wiki.
-
-== Empezando ==
-* [//www.mediawiki.org/wiki/Manual:Configuration_settings Lista de ajustes de configuración]
-* [//www.mediawiki.org/wiki/Manual:FAQ/es FAQ de MediaWiki]
-* [https://lists.wikimedia.org/mailman/listinfo/mediawiki-announce Lista de correo de anuncios de distribución de MediaWiki]',
-);
-
 /** Afrikaans (Afrikaans)
  * @author Naudefj
  */
@@ -3080,17 +2982,6 @@ $messages['cps'] = array(
 * [https://lists.wikimedia.org/mailman/listinfo/mediawiki-announce Lista sang mga ginapadal-an sang sulat sang MediaWiki]',
 );
 
-/** Crimean Turkish (Latin script) (‪Qırımtatarca (Latin)‬) */
-$messages['crh-latn'] = array(
-       'mainpagetext' => "'''MediaWiki muvafaqiyetnen quruldı.'''",
-       'mainpagedocfooter' => "Bu vikiniñ yol-yoruğını [//meta.wikimedia.org/wiki/Help:Contents User's Guide qullanıcı qılavuzından] ögrenip olasıñız.
-
-== Bazı faydalı saytlar ==
-* [//www.mediawiki.org/wiki/Manual:Configuration_settings Olucı sazlamalar cedveli];
-* [//www.mediawiki.org/wiki/Manual:FAQ MediaWiki boyunca sıq berilgen suallernen cevaplar];
-* [https://lists.wikimedia.org/mailman/listinfo/mediawiki-announce MediaWiki-niñ yañı versiyalarınıñ çıquvından haber yiberüv].",
-);
-
 /** Crimean Turkish (Cyrillic script) (‪Къырымтатарджа (Кирилл)‬) */
 $messages['crh-cyrl'] = array(
        'mainpagetext' => "'''MediaWiki мувафакъиетнен къурулды.'''",
@@ -3102,6 +2993,17 @@ $messages['crh-cyrl'] = array(
 * [https://lists.wikimedia.org/mailman/listinfo/mediawiki-announce MediaWiki-нинъ янъы версияларынынъ чыкъувындан хабер йиберюв].",
 );
 
+/** Crimean Turkish (Latin script) (‪Qırımtatarca (Latin)‬) */
+$messages['crh-latn'] = array(
+       'mainpagetext' => "'''MediaWiki muvafaqiyetnen quruldı.'''",
+       'mainpagedocfooter' => "Bu vikiniñ yol-yoruğını [//meta.wikimedia.org/wiki/Help:Contents User's Guide qullanıcı qılavuzından] ögrenip olasıñız.
+
+== Bazı faydalı saytlar ==
+* [//www.mediawiki.org/wiki/Manual:Configuration_settings Olucı sazlamalar cedveli];
+* [//www.mediawiki.org/wiki/Manual:FAQ MediaWiki boyunca sıq berilgen suallernen cevaplar];
+* [https://lists.wikimedia.org/mailman/listinfo/mediawiki-announce MediaWiki-niñ yañı versiyalarınıñ çıquvından haber yiberüv].",
+);
+
 /** Czech (česky)
  * @author Danny B.
  * @author Mormegil
@@ -4919,6 +4821,18 @@ Cuando lo haya hecho, usted puede '''[$2  entrar en su wiki]'''.",
 * [https://lists.wikimedia.org/mailman/listinfo/mediawiki-announce Lista de correo de anuncios de distribución de MediaWiki]',
 );
 
+/** Español (formal) (Español (formal))
+ * @author Dferg
+ */
+$messages['es-formal'] = array(
+       'mainpagedocfooter' => 'Consulte usted la [//meta.wikimedia.org/wiki/Ayuda:Contenido Guía de usuario] para obtener información sobre el uso del software wiki.
+
+== Empezando ==
+* [//www.mediawiki.org/wiki/Manual:Configuration_settings Lista de ajustes de configuración]
+* [//www.mediawiki.org/wiki/Manual:FAQ/es FAQ de MediaWiki]
+* [https://lists.wikimedia.org/mailman/listinfo/mediawiki-announce Lista de correo de anuncios de distribución de MediaWiki]',
+);
+
 /** Estonian (eesti)
  * @author Avjoska
  */
@@ -6648,6 +6562,13 @@ Cando faga todo isto, xa poderá '''[$2 entrar no seu wiki]'''.",
 * [https://lists.wikimedia.org/mailman/listinfo/mediawiki-announce Lista de correo dos lanzamentos de MediaWiki]',
 );
 
+/** Goan Konkani (Latin script) (Konknni)
+ * @author The Discoverer
+ */
+$messages['gom-latn'] = array(
+       'config-page-language' => 'Bhas',
+);
+
 /** Ancient Greek (Ἀρχαία ἑλληνικὴ)
  * @author Crazymadlover
  * @author Omnipaedista
@@ -6929,7 +6850,7 @@ $1
 אם מערכת ההפעלה שלהם היא Mandrake, התקינו את החבילה php-xml.',
        'config-pcre' => 'נראה שחסרה תמיכה במודול PCRE.
 כדי שמדיה־ויקי תעבוד, נדרשת תמיכה בביטויים רגולריים תואמי Perl.',
-       'config-pcre-no-utf8' => "'''שגיאה סופנית:''': נראה שמודול PCRE של PHP מקומפל ללא תמיכה ב־PCRE_UTF8.
+       'config-pcre-no-utf8' => "'''שגיאה סופנית''': נראה שמודול PCRE של PHP מקומפל ללא תמיכה ב־PCRE_UTF8.
 מדיה־ויקי דורשת תמיכה ב־UTF-8 לפעילות נכונה.",
        'config-memory-raised' => 'ערך האפשרות <code>memory_limit</code> של PHP הוא $1, הועלה ל־$2.',
        'config-memory-bad' => "'''אזהרה:''' ערך האפשרות <code>memory_limit</code> של PHP הוא $1.
@@ -7150,7 +7071,7 @@ chmod a+w $3</pre></div>',
        'config-ns-generic' => 'מיזם',
        'config-ns-site-name' => 'זהה לשם הוויקי: $1',
        'config-ns-other' => 'אחר (לציין)',
-       'config-ns-other-default' => 'הוויקי־שלי',
+       'config-ns-other-default' => 'הוויקי שלי',
        'config-project-namespace-help' => "בהתאם לדוגמה של ויקיפדיה, אתרי ויקי רבים שומרים על דפי המדיניות שלהם בנפרד מדפי התוכן שלהם ב\"'''מרחב השמות של המיזם'''\" (\"'''project namespace'''\").
 כל שמות הדפים במרחב השמות הזה מתחילים בתחילית מסוימת שאתם יכולים להגדיר כאן.
 באופן מסורתי התחילית הזאת מבוססת על שם הוויקי, והיא אינה יכולה להכיל תווי פיסוק כגון \"#\" או \":\".",
@@ -7223,9 +7144,9 @@ chmod a+w $3</pre></div>',
        'config-enable-email' => 'להפעיל דוא״ל יוצא',
        'config-enable-email-help' => 'אם אתם רוצים שדוא״ל יעבוד, [http://www.php.net/manual/en/mail.configuration.php אפשרויות הדוא״ל של PHP] צריכות להיות מוגדרות נכון.
 אם אינכם רוצים להפעיל שום אפשרויות דוא״ל, כבו אותן כאן ועכשיו.',
-       'config-email-user' => '×\9c×\90פשר שליחת דוא״ל ממשתמש למשתמש',
+       'config-email-user' => '×\9c×\94פע×\99×\9c שליחת דוא״ל ממשתמש למשתמש',
        'config-email-user-help' => 'לאפשר לכל המשתמשים לשלוח אחד לשני דוא״ל אם הם הפעילו את זה בהעדפות שלהם.',
-       'config-email-usertalk' => '×\9c×\90פשר הודעות על דף שיחת משתמש',
+       'config-email-usertalk' => '×\9c×\94פע×\99×\9c הודעות על דף שיחת משתמש',
        'config-email-usertalk-help' => 'לאפשר למשתמשים לקבל הודעות על שינויים בדפי המשתמש שלהם, אם הם הפעילו את זה בהעדפות שלהם.',
        'config-email-watchlist' => 'הפעלת התרעה על רשימת המעקב',
        'config-email-watchlist-help' => 'לאפשר למשתמשים לקבל הודעות על הדפים ברשימת המעקב שלהם אם הם הפעילו את זה בהעדפות שלהם.',
@@ -7238,7 +7159,7 @@ chmod a+w $3</pre></div>',
 לשם יישלחו תגובות שגיאה (bounce).
 שרתי דוא״ל רבים דורשים שלפחות החלק של המתחם יהיה תקין.',
        'config-upload-settings' => 'העלאת קבצים ותמונות',
-       'config-upload-enable' => '×\9c×\90פשר העלאת קבצים',
+       'config-upload-enable' => '×\9c×\94פע×\99×\9c העלאת קבצים',
        'config-upload-help' => 'העלאות קבצים חושפות את השרת שלכם לסיכוני אבטחה.
 למידע נוסף, קִראו את [//www.mediawiki.org/wiki/Manual:Security חלק האבטחה] בספר ההדרכה.
 
@@ -8275,6 +8196,85 @@ Ha végeztél a fájl elhelyezésével, '''[$2 beléphetsz a wikibe]'''.",
 * [https://lists.wikimedia.org/mailman/listinfo/mediawiki-announce MediaWiki-kiadások levelezőlistája]",
 );
 
+/** Magyar (magázó) (Magyar (magázó))
+ * @author Dani
+ * @author Glanthor Reviol
+ */
+$messages['hu-formal'] = array(
+       'config-localsettings-upgrade' => "'''Figyelmeztetés''': már létezik a <code>LocalSettings.php</code> fájl.
+A szoftver frissíthető.
+Adja meg a <code>\$wgUpgradeKey</code>-ben található kulcsot a beviteli mezőben",
+       'config-session-expired' => 'Úgy tűnik, hogy a munkamenetadatok lejártak.
+A munkamenetek élettartama a következőre van beállítva: $1.
+Az érték növelhető a php.ini <code>session.gc_maxlifetime</code> beállításának módosításával.
+Indítsa újra a telepítési folyamatot.',
+       'config-no-session' => 'Elvesztek a munkamenetadatok!
+Ellenőrizze, hogy a php.ini-ben a <code>session.save_path</code> beállítás a megfelelő könyvtárra mutat-e.',
+       'config-your-language-help' => 'Válassza ki a telepítési folyamat során használandó nyelvet.',
+       'config-wiki-language-help' => 'Az a nyelv, amin a wiki tartalmának legnagyobb része íródik.',
+       'config-page-welcome' => 'Üdvözli a MediaWiki!',
+       'config-help-restart' => 'Szeretné törölni az eddig megadott összes adatot és újraindítani a telepítési folyamatot?',
+       'config-welcome' => '=== Környezet ellenőrzése ===
+Alapvető ellenőrzés, ami megmondja, hogy a környezet alkalmas-e a MediaWiki számára.
+Ha probléma merülne fel a telepítés során, meg kell adnia mások számára az alább megjelenő információkat.',
+       'config-unicode-pure-php-warning' => "'''Figyelmeztetés''': Az [http://pecl.php.net/intl intl PECL kiterjesztés] nem érhető el Unicode normalizáláshoz.
+Ha nagy látogatottságú oldalt üzemeltet, itt találhat információkat [//www.mediawiki.org/wiki/Unicode_normalization_considerations a témáról].",
+       'config-register-globals' => "'''Figyelmeztetés: A PHP <code>[http://php.net/register_globals register_globals]</code> beállítása engedélyezve van.'''
+'''Tiltsa le, ha van rá lehetősége.'''
+A MediaWiki működőképes a beállítás használata mellett, de a szerver biztonsági kockázatnak lesz kitéve.",
+       'config-imagemagick' => 'Az ImageMagick megtalálható a rendszeren: <code>$1</code>.
+A bélyegképek készítése engedélyezve lesz, ha engedélyezi a feltöltéseket.',
+       'config-db-name-help' => 'Válassza ki a wikije azonosítására használt nevet.
+Nem tartalmazhat szóközt vagy kötőjelet.
+
+Ha megosztott webtárhelyet használ, a szolgáltatója vagy egy konkrét adatbázisnevet ad önnek használatra, vagy létrehozhat egyet a vezérlőpulton keresztül.',
+       'config-db-install-help' => 'Adja meg a felhasználónevet és jelszót, amivel a telepítő csatlakozhat az adatbázishoz.',
+       'config-db-wiki-help' => 'Adja meg azt a felhasználónevet és jelszót, amivel a wiki fog csatlakozni az adatbázishoz működés közben.
+Ha a fiók nem létezik és a telepítést végző fiók rendelkezik megfelelő jogosultsággal, egy új fiók készül a megadott a névvel, azon minimális jogosultságkörrel, ami a wiki működéséhez szükséges.',
+       'config-charset-help' => "'''Figyelmezetés:''' Ha a '''visszafelé kompatibilis UTF-8''' beállítást használja MySQL 4.1 vagy újabb verziók esetén, és utána a <code>mysqldump</code> programmal készít róla biztonsági másolatot, az tönkreteheti az összes nem ASCII-karaktert, visszafordíthatatlanul károsítva a másolatokban tárolt adatokat!
+
+'''Bináris''' módban a MediaWiki az UTF-8-ban kódolt szöveget bináris mezőkben tárolja az adatbázisban.
+Ez sokkal hatékonyabb a MySQL UTF-8-módjától, és lehetővé teszi, hogy a teljes Unicode-karakterkészletet használja.
+'''UTF-8-módban''' MySQL tudja, hogy milyen karakterkészlettel van kódolva az adat, megfelelően van megjelenítve és konvertálva, de
+nem használhatja a [//en.wikipedia.org/wiki/Mapping_of_Unicode_character_planes Basic Multilingual Plane] feletti karaktereket.",
+       'config-db-schema-help' => 'A fenti sémák általában megfelelőek.
+Csak akkor módosítson rajta, ha szükség van rá.',
+       'config-sqlite-parent-unwritable-nogroup' => 'Nem lehet létrehozni az adatok tárolásához szükséges <code><nowiki>$1</nowiki></code> könyvtárat, mert a webszerver nem írhat a szülőkönyvtárba (<code><nowiki>$2</nowiki></code>).
+
+A telepítő nem tudta megállapíteni, hogy melyik felhasználói fiókon fut a webszerver.
+A folytatáshoz tegye írhatóvá ezen fiók (és más fiókok!) számára a következő könyvtárat: <code><nowiki>$3</nowiki></code>.
+Unix/Linux rendszereken tedd a következőt:
+
+<pre>cd $2
+mkdir $3
+chmod a+w $3</pre>',
+       'config-ns-other' => 'Más (adja meg)',
+       'config-admin-name-blank' => 'Adja meg az adminisztrátor felhasználónevét!',
+       'config-admin-name-invalid' => 'A megadott felhasználónév (<nowiki>$1</nowiki>) érvénytelen.
+Adjon meg egy másik felhasználónevet.',
+       'config-admin-password-blank' => 'Adja meg az adminisztrátori fiók jelszavát!',
+       'config-instantcommons-help' => 'Az [//www.mediawiki.org/wiki/InstantCommons Instant Commons] lehetővé teszi, hogy a wikin használhassák a [//commons.wikimedia.org/ Wikimedia Commons] oldalon található képeket, hangokat és más médiafájlokat.
+A használatához a MediaWikinek internethozzáférésre van szüksége.
+
+A funkcióról és hogy hogyan állítható be más wikik esetén [//mediawiki.org/wiki/Manual:$wgForeignFileRepos a kézikönyvben] találhat további információkat.',
+       'config-install-done' => "'''Gratulálunk!'''
+Sikeresen telepítette a MediaWikit.
+
+A telepítő készített egy <code>LocalSettings.php</code> fájlt.
+Ez tartalmazza az összes beállítást.
+
+[$1 Le kell töltenie], és el kell helyeznie a MediaWiki telepítési könyvtárába (az a könyvtár, ahol az index.php van).
+'''Megjegyzés''': Ha ezt most nem teszi meg, és kilép, a generált fájl nem lesz elérhető a későbbiekben.
+
+Ha ezzel készen van, '''[$2 beléphet a wikibe]'''.",
+       'mainpagedocfooter' => "Ha segítségre van szüksége a wikiszoftver használatához, akkor keresse fel a [//meta.wikimedia.org/wiki/Help:Contents User's Guide] oldalt.
+
+== Alapok (angol nyelven) ==
+* [//www.mediawiki.org/wiki/Manual:Configuration_settings Beállítások listája]
+* [//www.mediawiki.org/wiki/Manual:FAQ MediaWiki GyIK]
+* [https://lists.wikimedia.org/mailman/listinfo/mediawiki-announce MediaWiki-kiadások levelezőlistája]",
+);
+
 /** Armenian (Հայերեն) */
 $messages['hy'] = array(
        'mainpagetext' => "'''«MediaWiki» ծրագիրը հաջողությամբ տեղադրվեց։'''",
@@ -9616,8 +9616,8 @@ $messages['ja'] = array(
 インストールされているものをアップグレードするには、update.php を実行してください',
        'config-localsettings-key' => 'アップグレード キー:',
        'config-localsettings-badkey' => '与えられたキーが間違っています',
-       'config-upgrade-key-missing' => 'MediaWikiの既存インストールを検出しました。
\82¤ã\83³ã\82¹ã\83\88ã\83¼ã\83«ã\82\92ã\82¢ã\83\83ã\83\97ã\82°ã\83¬ã\83¼ã\83\89ã\81\99ã\82\8bã\81\9fã\82\81ã\81«ã\80\81次ã\81®è¡\8cã\82\92LocalSettings.phpの末尾に挿入してください:
+       'config-upgrade-key-missing' => 'MediaWiki が既にインストールされていることを検出しました。
\82¤ã\83³ã\82¹ã\83\88ã\83¼ã\83«ã\81\95ã\82\8cã\81¦ã\81\84ã\82\8bã\82\82ã\81®ã\82\92ã\82¢ã\83\83ã\83\97ã\82°ã\83¬ã\83¼ã\83\89ã\81\99ã\82\8bã\81\9fã\82\81ã\81«ã\80\81以ä¸\8bã\81®è¡\8cã\82\92 LocalSettings.php の末尾に挿入してください:
 
 $1',
        'config-localsettings-incomplete' => '既存の LocalSettings.php の内容は不完全のようです。
@@ -18681,4 +18681,3 @@ $messages['zh-tw'] = array(
 * [//www.mediawiki.org/wiki/Manual:FAQ MediaWiki 常見問題解答]
 * [https://lists.wikimedia.org/mailman/listinfo/mediawiki-announce MediaWiki 發佈郵件清單]',
 );
-
index 2942c0b..457268c 100644 (file)
@@ -155,6 +155,10 @@ class PostgresUpdater extends DatabaseUpdater {
                        array( 'addPgField', 'archive',       'ar_sha1',              "TEXT NOT NULL DEFAULT ''" ),
                        array( 'addPgField', 'uploadstash',   'us_chunk_inx',         "INTEGER NULL" ),
                        array( 'addPgField', 'job',           'job_timestamp',        "TIMESTAMPTZ" ),
+                       array( 'addPgField', 'job',           'job_random',           "INTEGER NOT NULL DEFAULT 0" ),
+                       array( 'addPgField', 'job',           'job_token',            "TEXT NOT NULL DEFAULT ''" ),
+                       array( 'addPgField', 'job',           'job_token_timestamp',  "TIMESTAMPTZ" ),
+                       array( 'addPgField', 'job',           'job_sha1',             "TEXT NOT NULL DEFAULT ''" ),
 
                        # type changes
                        array( 'changeField', 'archive',       'ar_deleted',      'smallint', '' ),
@@ -228,6 +232,8 @@ class PostgresUpdater extends DatabaseUpdater {
                        array( 'addPgIndex', 'logging',       'logging_page_id_time',   '(log_page,log_timestamp)' ),
                        array( 'addPgIndex', 'iwlinks',       'iwl_prefix_title_from',  '(iwl_prefix, iwl_title, iwl_from)' ),
                        array( 'addPgIndex', 'job',           'job_timestamp_idx',      '(job_timestamp)' ),
+                       array( 'addPgIndex', 'job',           'job_sha1',               '(job_sha1)' ),
+                       array( 'addPgIndex', 'job',           'job_cmd_token',          '(job_cmd, job_token, job_random)' ),
                        array( 'addPgIndex', 'filearchive',   'fa_sha1',                '(fa_sha1)' ),
 
                        array( 'checkIndex', 'pagelink_unique', array(
diff --git a/includes/job/DoubleRedirectJob.php b/includes/job/DoubleRedirectJob.php
deleted file mode 100644 (file)
index b1b96b6..0000000
+++ /dev/null
@@ -1,210 +0,0 @@
-<?php
-/**
- * Job to fix double redirects after moving a page.
- *
- * 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 JobQueue
- */
-
-/**
- * Job to fix double redirects after moving a page
- *
- * @ingroup JobQueue
- */
-class DoubleRedirectJob extends Job {
-       var $reason, $redirTitle;
-
-       /**
-        * @var User
-        */
-       static $user;
-
-       /**
-        * Insert jobs into the job queue to fix redirects to the given title
-        * @param $reason String: the reason for the fix, see message "double-redirect-fixed-<reason>"
-        * @param $redirTitle Title: the title which has changed, redirects pointing to this title are fixed
-        * @param $destTitle bool Not used
-        */
-       public static function fixRedirects( $reason, $redirTitle, $destTitle = false ) {
-               # Need to use the master to get the redirect table updated in the same transaction
-               $dbw = wfGetDB( DB_MASTER );
-               $res = $dbw->select(
-                       array( 'redirect', 'page' ),
-                       array( 'page_namespace', 'page_title' ),
-                       array(
-                               'page_id = rd_from',
-                               'rd_namespace' => $redirTitle->getNamespace(),
-                               'rd_title' => $redirTitle->getDBkey()
-                       ), __METHOD__ );
-               if ( !$res->numRows() ) {
-                       return;
-               }
-               $jobs = array();
-               foreach ( $res as $row ) {
-                       $title = Title::makeTitle( $row->page_namespace, $row->page_title );
-                       if ( !$title ) {
-                               continue;
-                       }
-
-                       $jobs[] = new self( $title, array(
-                               'reason' => $reason,
-                               'redirTitle' => $redirTitle->getPrefixedDBkey() ) );
-                       # Avoid excessive memory usage
-                       if ( count( $jobs ) > 10000 ) {
-                               Job::batchInsert( $jobs );
-                               $jobs = array();
-                       }
-               }
-               Job::batchInsert( $jobs );
-       }
-
-       function __construct( $title, $params = false, $id = 0 ) {
-               parent::__construct( 'fixDoubleRedirect', $title, $params, $id );
-               $this->reason = $params['reason'];
-               $this->redirTitle = Title::newFromText( $params['redirTitle'] );
-       }
-
-       /**
-        * @return bool
-        */
-       function run() {
-               if ( !$this->redirTitle ) {
-                       $this->setLastError( 'Invalid title' );
-                       return false;
-               }
-
-               $targetRev = Revision::newFromTitle( $this->title, false, Revision::READ_LATEST );
-               if ( !$targetRev ) {
-                       wfDebug( __METHOD__.": target redirect already deleted, ignoring\n" );
-                       return true;
-               }
-               $content = $targetRev->getContent();
-               $currentDest = $content->getRedirectTarget();
-               if ( !$currentDest || !$currentDest->equals( $this->redirTitle ) ) {
-                       wfDebug( __METHOD__.": Redirect has changed since the job was queued\n" );
-                       return true;
-               }
-
-               # Check for a suppression tag (used e.g. in periodically archived discussions)
-               $mw = MagicWord::get( 'staticredirect' );
-               if ( $content->matchMagicWord( $mw ) ) {
-                       wfDebug( __METHOD__.": skipping: suppressed with __STATICREDIRECT__\n" );
-                       return true;
-               }
-
-               # Find the current final destination
-               $newTitle = self::getFinalDestination( $this->redirTitle );
-               if ( !$newTitle ) {
-                       wfDebug( __METHOD__.": skipping: single redirect, circular redirect or invalid redirect destination\n" );
-                       return true;
-               }
-               if ( $newTitle->equals( $this->redirTitle ) ) {
-                       # The redirect is already right, no need to change it
-                       # This can happen if the page was moved back (say after vandalism)
-                       wfDebug( __METHOD__.": skipping, already good\n" );
-               }
-
-               # Preserve fragment (bug 14904)
-               $newTitle = Title::makeTitle( $newTitle->getNamespace(), $newTitle->getDBkey(),
-                       $currentDest->getFragment(), $newTitle->getInterwiki() );
-
-               # Fix the text
-               $newContent = $content->updateRedirect( $newTitle );
-
-               if ( $newContent->equals( $content ) ) {
-                       $this->setLastError( 'Content unchanged???' );
-                       return false;
-               }
-
-               # Save it
-               global $wgUser;
-               $oldUser = $wgUser;
-               $wgUser = $this->getUser();
-               $article = WikiPage::factory( $this->title );
-               $reason = wfMessage( 'double-redirect-fixed-' . $this->reason,
-                       $this->redirTitle->getPrefixedText(), $newTitle->getPrefixedText()
-               )->inContentLanguage()->text();
-               $article->doEditContent( $newContent, $reason, EDIT_UPDATE | EDIT_SUPPRESS_RC, false, $this->getUser() );
-               $wgUser = $oldUser;
-
-               return true;
-       }
-
-       /**
-        * Get the final destination of a redirect
-        *
-        * @param $title Title
-        *
-        * @return bool if the specified title is not a redirect, or if it is a circular redirect
-        */
-       public static function getFinalDestination( $title ) {
-               $dbw = wfGetDB( DB_MASTER );
-
-               $seenTitles = array(); # Circular redirect check
-               $dest = false;
-
-               while ( true ) {
-                       $titleText = $title->getPrefixedDBkey();
-                       if ( isset( $seenTitles[$titleText] ) ) {
-                               wfDebug( __METHOD__, "Circular redirect detected, aborting\n" );
-                               return false;
-                       }
-                       $seenTitles[$titleText] = true;
-
-                       if ( $title->getInterwiki() ) {
-                               // 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
-                               // unexpected results (e.g. X -> foo:Bar -> Bar -> .. )
-                               break;
-                       }
-
-                       $row = $dbw->selectRow(
-                               array( 'redirect', 'page' ),
-                               array( 'rd_namespace', 'rd_title', 'rd_interwiki' ),
-                               array(
-                                       'rd_from=page_id',
-                                       'page_namespace' => $title->getNamespace(),
-                                       'page_title' => $title->getDBkey()
-                               ), __METHOD__ );
-                       if ( !$row ) {
-                               # No redirect from here, chain terminates
-                               break;
-                       } else {
-                               $dest = $title = Title::makeTitle( $row->rd_namespace, $row->rd_title, '', $row->rd_interwiki );
-                       }
-               }
-               return $dest;
-       }
-
-       /**
-        * Get a user object for doing edits, from a request-lifetime cache
-        * @return User
-        */
-       function getUser() {
-               if ( !self::$user ) {
-                       self::$user = User::newFromName( wfMessage( 'double-redirect-fixer' )->inContentLanguage()->text(), false );
-                       # FIXME: newFromName could return false on a badly configured wiki.
-                       if ( !self::$user->isLoggedIn() ) {
-                               self::$user->addToDatabase();
-                       }
-               }
-               return self::$user;
-       }
-}
-
diff --git a/includes/job/EmaillingJob.php b/includes/job/EmaillingJob.php
deleted file mode 100644 (file)
index d359988..0000000
+++ /dev/null
@@ -1,46 +0,0 @@
-<?php
-/**
- * Old job for notification emails.
- *
- * 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 JobQueue
- */
-
-/**
- * Old job used for sending single notification emails;
- * kept for backwards-compatibility
- *
- * @ingroup JobQueue
- */
-class EmaillingJob extends Job {
-       function __construct( $title, $params, $id = 0 ) {
-               parent::__construct( 'sendMail', Title::newMainPage(), $params, $id );
-       }
-
-       function run() {
-               UserMailer::send(
-                       $this->params['to'],
-                       $this->params['from'],
-                       $this->params['subj'],
-                       $this->params['body'],
-                       $this->params['replyto']
-               );
-               return true;
-       }
-
-}
diff --git a/includes/job/EnotifNotifyJob.php b/includes/job/EnotifNotifyJob.php
deleted file mode 100644 (file)
index b4c925e..0000000
+++ /dev/null
@@ -1,57 +0,0 @@
-<?php
-/**
- * Job for notification emails.
- *
- * 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 JobQueue
- */
-
-/**
- * Job for email notification mails
- *
- * @ingroup JobQueue
- */
-class EnotifNotifyJob extends Job {
-
-       function __construct( $title, $params, $id = 0 ) {
-               parent::__construct( 'enotifNotify', $title, $params, $id );
-       }
-
-       function run() {
-               $enotif = new EmailNotification();
-               // Get the user from ID (rename safe). Anons are 0, so defer to name.
-               if( isset( $this->params['editorID'] ) && $this->params['editorID'] ) {
-                       $editor = User::newFromId( $this->params['editorID'] );
-               // B/C, only the name might be given.
-               } else {
-                       # FIXME: newFromName could return false on a badly configured wiki.
-                       $editor = User::newFromName( $this->params['editor'], false );
-               }
-               $enotif->actuallyNotifyOnPageChange(
-                       $editor,
-                       $this->title,
-                       $this->params['timestamp'],
-                       $this->params['summary'],
-                       $this->params['minorEdit'],
-                       $this->params['oldid'],
-                       $this->params['watchers']
-               );
-               return true;
-       }
-
-}
index 6409cff..4637bd2 100644 (file)
@@ -31,6 +31,7 @@
 abstract class JobQueue {
        protected $wiki; // string; wiki ID
        protected $type; // string; job type
+       protected $order; // string; job priority for pop()
 
        const QoS_Atomic = 1; // integer; "all-or-nothing" job insertions
 
@@ -38,8 +39,9 @@ abstract class JobQueue {
         * @param $params array
         */
        protected function __construct( array $params ) {
-               $this->wiki = $params['wiki'];
-               $this->type = $params['type'];
+               $this->wiki  = $params['wiki'];
+               $this->type  = $params['type'];
+               $this->order = isset( $params['order'] ) ? $params['order'] : 'random';
        }
 
        /**
@@ -48,6 +50,12 @@ abstract class JobQueue {
         *     class : what job class to use (determines job type)
         *     wiki  : wiki ID of the wiki the jobs are for (defaults to current wiki)
         *     type  : The name of the job types this queue handles
+        *     order : Order that pop() selects jobs, either "timestamp" or "random".
+        *             If "timestamp" is used, the queue will effectively be FIFO. Note that
+        *             pop() will not be exactly FIFO, and even if it was, job completion would
+        *             not appear to be exactly FIFO since jobs can take different times to finish.
+        *             If "random" is used, pop() will pick jobs in random order. This might be
+        *             useful for improving concurrency depending on the queue storage medium.
         *
         * @param $params array
         * @return JobQueue
index bea4a6f..f6003b2 100644 (file)
@@ -121,38 +121,44 @@ class JobQueueDB extends JobQueue {
                $dbw->clearFlag( DBO_TRX ); // make each query its own transaction
                try {
                        do { // retry when our row is invalid or deleted as a duplicate
-                               $row = false; // row claimed
-                               $rand = mt_rand( 0, self::MAX_JOB_RANDOM ); // encourage concurrent UPDATEs
-                               $gte  = (bool)mt_rand( 0, 1 ); // find rows with rand before/after $rand
-                               // Try to reserve a DB row...
-                               if ( $this->claim( $uuid, $rand, $gte ) || $this->claim( $uuid, $rand, !$gte ) ) {
-                                       // Fetch any row that we just reserved...
-                                       $row = $dbw->selectRow( 'job', '*',
-                                               array( 'job_cmd' => $this->type, 'job_token' => $uuid ), __METHOD__ );
-                                       // Check if another process deleted it as a duplicate
-                                       if ( !$row ) {
-                                               wfDebugLog( 'JobQueueDB', "Row deleted as duplicate by another process." );
-                                               continue; // try again
-                                       }
-                                       // Get the job object from the row...
-                                       $title = Title::makeTitleSafe( $row->job_namespace, $row->job_title );
-                                       if ( !$title ) {
-                                               $dbw->delete( 'job', array( 'job_id' => $row->job_id ), __METHOD__ );
-                                               wfDebugLog( 'JobQueueDB', "Row has invalid title '{$row->job_title}'." );
-                                               continue; // try again
-                                       }
-                                       $job = Job::factory( $row->job_cmd, $title,
-                                               self::extractBlob( $row->job_params ), $row->job_id );
-                                       // Delete any *other* duplicate jobs in the queue...
-                                       if ( $job->ignoreDuplicates() && strlen( $row->job_sha1 ) ) {
-                                               $dbw->delete( 'job',
-                                                       array( 'job_sha1' => $row->job_sha1,
-                                                               "job_id != {$dbw->addQuotes( $row->job_id )}" ),
-                                                       __METHOD__
-                                               );
-                                       }
-                               } else {
+                               // Try to reserve a row in the DB...
+                               if ( $this->order === 'timestamp' ) { // oldest first
+                                       $found = $this->claim( $uuid, 0, true );
+                               } else { // random first
+                                       $rand  = mt_rand( 0, self::MAX_JOB_RANDOM ); // encourage concurrent UPDATEs
+                                       $gte   = (bool)mt_rand( 0, 1 ); // find rows with rand before/after $rand
+                                       $found = $this->claim( $uuid, $rand, $gte )
+                                               || $this->claim( $uuid, $rand, !$gte ); // try both directions
+                               }
+                               // Check if we found a row to reserve...
+                               if ( !$found ) {
                                        $wgMemc->set( $this->getEmptinessCacheKey(), 'true', self::CACHE_TTL );
+                                       break; // nothing to do
+                               }
+                               // Fetch any row that we just reserved...
+                               $row = $dbw->selectRow( 'job', '*',
+                                       array( 'job_cmd' => $this->type, 'job_token' => $uuid ), __METHOD__ );
+                               // Check if another process deleted it as a duplicate
+                               if ( !$row ) {
+                                       wfDebugLog( 'JobQueueDB', "Row deleted as duplicate by another process." );
+                                       continue; // try again
+                               }
+                               // Get the job object from the row...
+                               $title = Title::makeTitleSafe( $row->job_namespace, $row->job_title );
+                               if ( !$title ) {
+                                       $dbw->delete( 'job', array( 'job_id' => $row->job_id ), __METHOD__ );
+                                       wfDebugLog( 'JobQueueDB', "Row has invalid title '{$row->job_title}'." );
+                                       continue; // try again
+                               }
+                               $job = Job::factory( $row->job_cmd, $title,
+                                       self::extractBlob( $row->job_params ), $row->job_id );
+                               // Delete any *other* duplicate jobs in the queue...
+                               if ( $job->ignoreDuplicates() && strlen( $row->job_sha1 ) ) {
+                                       $dbw->delete( 'job',
+                                               array( 'job_sha1' => $row->job_sha1,
+                                                       "job_id != {$dbw->addQuotes( $row->job_id )}" ),
+                                               __METHOD__
+                                       );
                                }
                                break; // done
                        } while( true );
@@ -274,6 +280,11 @@ class JobQueueDB extends JobQueue {
                        'job_params'    => self::makeBlob( $job->getParams() ),
                );
                // Additional job metadata
+               if ( $this->order === 'timestamp' ) { // oldest first
+                       $random = time() - 1325376000; // seconds since "January 1, 2012"
+               } else { // random first
+                       $random = mt_rand( 0, self::MAX_JOB_RANDOM );
+               }
                $dbw = $this->getMasterDB();
                $metaFields = array(
                        'job_id'        => $dbw->nextSequenceValue( 'job_job_id_seq' ),
index 69bcf01..4ebd531 100644 (file)
@@ -62,18 +62,14 @@ class JobQueueGroup {
        public function get( $type ) {
                global $wgJobTypeConf;
 
-               $conf = false;
+               $conf = array( 'wiki' => $this->wiki, 'type' => $type );
                if ( isset( $wgJobTypeConf[$type] ) ) {
-                       $conf = $wgJobTypeConf[$type];
+                       $conf = $conf + $wgJobTypeConf[$type];
                } else {
-                       $conf = $wgJobTypeConf['default'];
+                       $conf = $conf + $wgJobTypeConf['default'];
                }
 
-               return JobQueue::factory( array(
-                       'class' => $conf['class'],
-                       'wiki'  => $this->wiki,
-                       'type'  => $type,
-               ) );
+               return JobQueue::factory( $conf );
        }
 
        /**
diff --git a/includes/job/README b/includes/job/README
new file mode 100644 (file)
index 0000000..57c92e9
--- /dev/null
@@ -0,0 +1,58 @@
+/*!
+\ingroup JobQueue
+\page jobqueue_design Job queue design
+
+Notes on the Job queuing system architecture.
+
+\section intro Introduction
+
+The data model consist of the following main components:
+
+* The Job object represents a particular deferred task that happens in the
+  background. All jobs subclass the Job object and put the main logic in the
+  function called run().
+* The JobQueue object represents a particular queue of jobs of a certain type.
+  For example there may be a queue for email jobs and a queue for squid purge
+  jobs.
+
+Each job type has its own queue and is associated to a storage medium. One
+queue might save its jobs in redis while another one uses would use a database.
+
+Storage medium are defined in a queue class. Before using it, you must
+define in $wgJobTypeConf a mapping of the job type to a queue class.
+
+The factory class JobQueueGroup provides helper functions:
+- getting the queue for a given job
+- route new job insertions to the proper queue
+
+The following queue classes are available:
+* JobQueueDB (stores jobs in the `job` table in a database)
+
+All queue classes support some basic operations (though some may be no-ops):
+* enqueueing a batch of jobs
+* dequeueing a single job
+* acknowledging a job is completed
+* checking if the queue is empty
+
+Some queue classes (like JobQueueDB) may dequeue jobs in random order while other
+queues might dequeue jobs in exact FIFO order. Callers should thus not assume jobs
+are executed in FIFO order.
+
+Also note that not all queue classes will have the same reliability guarantees.
+In-memory queues may lose data when restarted depending on snapshot and journal
+settings (including journal fsync() frequency).  Some queue types may totally remove
+jobs when dequeued while leaving the ack() function as a no-op; if a job is
+dequeued by a job runner, which crashes before completion, the job will be
+lost. Some jobs, like purging squid caches after a template change, may not
+require durable queues, whereas other jobs might be more important.
+
+Callers should also try to make jobs maintain correctness when executed twice.
+This is useful for queues that actually implement ack(), since they may recycle
+dequeued but un-acknowledged jobs back into the queue to be attempted again. If
+a runner dequeues a job, runs it, but then crashes before calling ack(), the
+job may be returned to the queue and run a second time. Jobs like cache purging can
+happen several times without any correctness problems. However, a pathological case
+would be if a bug causes the problem to systematically keep repeating. For example,
+a job may always throw a DB error at the end of run(). This problem is trickier to
+solve and more obnoxious for things like email jobs, for example. For such jobs,
+it might be useful to use a queue that does not retry jobs.
diff --git a/includes/job/RefreshLinksJob.php b/includes/job/RefreshLinksJob.php
deleted file mode 100644 (file)
index a29f29f..0000000
+++ /dev/null
@@ -1,202 +0,0 @@
-<?php
-/**
- * Job to update links for a given title.
- *
- * 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 JobQueue
- */
-
-/**
- * Background job to update links for a given title.
- *
- * @ingroup JobQueue
- */
-class RefreshLinksJob extends Job {
-       function __construct( $title, $params = '', $id = 0 ) {
-               parent::__construct( 'refreshLinks', $title, $params, $id );
-               $this->removeDuplicates = true; // job is expensive
-       }
-
-       /**
-        * Run a refreshLinks job
-        * @return boolean success
-        */
-       function run() {
-               wfProfileIn( __METHOD__ );
-
-               $linkCache = LinkCache::singleton();
-               $linkCache->clear();
-
-               if ( is_null( $this->title ) ) {
-                       $this->error = "refreshLinks: Invalid title";
-                       wfProfileOut( __METHOD__ );
-                       return false;
-               }
-
-               # Wait for the DB of the current/next slave DB handle to catch up to the master.
-               # This way, we get the correct page_latest for templates or files that just changed
-               # milliseconds ago, having triggered this job to begin with.
-               if ( isset( $this->params['masterPos'] ) ) {
-                       wfGetLB()->waitFor( $this->params['masterPos'] );
-               }
-
-               $revision = Revision::newFromTitle( $this->title, false, Revision::READ_NORMAL );
-               if ( !$revision ) {
-                       $this->error = 'refreshLinks: Article not found "' .
-                               $this->title->getPrefixedDBkey() . '"';
-                       wfProfileOut( __METHOD__ );
-                       return false; // XXX: what if it was just deleted?
-               }
-
-               self::runForTitleInternal( $this->title, $revision, __METHOD__ );
-
-               wfProfileOut( __METHOD__ );
-               return true;
-       }
-
-       public static function runForTitleInternal( Title $title, Revision $revision, $fname ) {
-               global $wgContLang;
-
-               wfProfileIn( $fname . '-parse' );
-               $options = ParserOptions::newFromUserAndLang( new User, $wgContLang );
-               $content = $revision->getContent();
-               $parserOutput = $content->getParserOutput( $title, $revision->getId(), $options, false );
-               wfProfileOut( $fname . '-parse' );
-
-               wfProfileIn( $fname . '-update' );
-               $updates = $content->getSecondaryDataUpdates( $title, null, false, $parserOutput  );
-               DataUpdate::runUpdates( $updates );
-               wfProfileOut( $fname . '-update' );
-       }
-}
-
-/**
- * Background job to update links for a given title.
- * Newer version for high use templates.
- *
- * @ingroup JobQueue
- */
-class RefreshLinksJob2 extends Job {
-       const MAX_TITLES_RUN = 10;
-
-       function __construct( $title, $params, $id = 0 ) {
-               parent::__construct( 'refreshLinks2', $title, $params, $id );
-       }
-
-       /**
-        * Run a refreshLinks2 job
-        * @return boolean success
-        */
-       function run() {
-               wfProfileIn( __METHOD__ );
-
-               $linkCache = LinkCache::singleton();
-               $linkCache->clear();
-
-               if ( is_null( $this->title ) ) {
-                       $this->error = "refreshLinks2: Invalid title";
-                       wfProfileOut( __METHOD__ );
-                       return false;
-               } elseif ( !isset( $this->params['start'] ) || !isset( $this->params['end'] ) ) {
-                       $this->error = "refreshLinks2: Invalid params";
-                       wfProfileOut( __METHOD__ );
-                       return false;
-               }
-
-               // Back compat for pre-r94435 jobs
-               $table = isset( $this->params['table'] ) ? $this->params['table'] : 'templatelinks';
-
-               // Avoid slave lag when fetching templates
-               if ( isset( $this->params['masterPos'] ) ) {
-                       $masterPos = $this->params['masterPos'];
-               } elseif ( wfGetLB()->getServerCount() > 1  ) {
-                       $masterPos = wfGetLB()->getMasterPos();
-               } else {
-                       $masterPos = false;
-               }
-
-               $titles = $this->title->getBacklinkCache()->getLinks(
-                       $table, $this->params['start'], $this->params['end'] );
-
-               if ( $titles->count() > self::MAX_TITLES_RUN ) {
-                       # We don't want to parse too many pages per job as it can starve other jobs.
-                       # If there are too many pages to parse, break this up into smaller jobs. By passing
-                       # in the master position here we can cut down on the time spent waiting for slaves to
-                       # catch up by the runners handling these jobs since time will have passed between now
-                       # and when they pop these jobs off the queue.
-                       $start = 0; // batch start
-                       $end   = 0; // batch end
-                       $bsize = 0; // batch size
-                       $first = true; // first of batch
-                       $jobs  = array();
-                       foreach ( $titles as $title ) {
-                               $start = $first ? $title->getArticleId() : $start;
-                               $end   = $title->getArticleId();
-                               $first = false;
-                               if ( ++$bsize >= self::MAX_TITLES_RUN ) {
-                                       $jobs[] = new RefreshLinksJob2( $this->title, array(
-                                               'table'     => $table,
-                                               'start'     => $start,
-                                               'end'       => $end,
-                                               'masterPos' => $masterPos
-                                       ) );
-                                       $first = true;
-                                       $start = $end = $bsize = 0;
-                               }
-                       }
-                       if ( $bsize > 0 ) { // group remaining pages into a job
-                               $jobs[] = new RefreshLinksJob2( $this->title, array(
-                                       'table'     => $table,
-                                       'start'     => $start,
-                                       'end'       => $end,
-                                       'masterPos' => $masterPos
-                               ) );
-                       }
-                       Job::batchInsert( $jobs );
-               } elseif ( php_sapi_name() != 'cli' ) {
-                       # Not suitable for page load triggered job running!
-                       # Gracefully switch to refreshLinks jobs if this happens.
-                       $jobs = array();
-                       foreach ( $titles as $title ) {
-                               $jobs[] = new RefreshLinksJob( $title, array( 'masterPos' => $masterPos ) );
-                       }
-                       Job::batchInsert( $jobs );
-               } else {
-                       # Wait for the DB of the current/next slave DB handle to catch up to the master.
-                       # This way, we get the correct page_latest for templates or files that just changed
-                       # milliseconds ago, having triggered this job to begin with.
-                       if ( $masterPos ) {
-                               wfGetLB()->waitFor( $masterPos );
-                       }
-                       # Re-parse each page that transcludes this page and update their tracking links...
-                       foreach ( $titles as $title ) {
-                               $revision = Revision::newFromTitle( $title, false, Revision::READ_NORMAL );
-                               if ( !$revision ) {
-                                       $this->error = 'refreshLinks: Article not found "' .
-                                               $title->getPrefixedDBkey() . '"';
-                                       continue; // skip this page
-                               }
-                               RefreshLinksJob::runForTitleInternal( $title, $revision, __METHOD__ );
-                               wfWaitForSlaves();
-                       }
-               }
-
-               wfProfileOut( __METHOD__ );
-               return true;
-       }
-}
diff --git a/includes/job/UploadFromUrlJob.php b/includes/job/UploadFromUrlJob.php
deleted file mode 100644 (file)
index e06f68e..0000000
+++ /dev/null
@@ -1,179 +0,0 @@
-<?php
-/**
- * Job for asynchronous upload-by-url.
- *
- * 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 JobQueue
- */
-
-/**
- * Job for asynchronous upload-by-url.
- *
- * This job is in fact an interface to UploadFromUrl, which is designed such
- * that it does not require any globals. If it does, fix it elsewhere, do not
- * add globals in here.
- *
- * @ingroup JobQueue
- */
-class UploadFromUrlJob extends Job {
-       const SESSION_KEYNAME = 'wsUploadFromUrlJobData';
-
-       /**
-        * @var UploadFromUrl
-        */
-       public $upload;
-
-       /**
-        * @var User
-        */
-       protected $user;
-
-       public function __construct( $title, $params, $id = 0 ) {
-               parent::__construct( 'uploadFromUrl', $title, $params, $id );
-       }
-
-       public function run() {
-               # Initialize this object and the upload object
-               $this->upload = new UploadFromUrl();
-               $this->upload->initialize(
-                       $this->title->getText(),
-                       $this->params['url'],
-                       false
-               );
-               $this->user = User::newFromName( $this->params['userName'] );
-
-               # Fetch the file
-               $status = $this->upload->fetchFile();
-               if ( !$status->isOk() ) {
-                       $this->leaveMessage( $status );
-                       return true;
-               }
-
-               # Verify upload
-               $result = $this->upload->verifyUpload();
-               if ( $result['status'] != UploadBase::OK ) {
-                       $status = $this->upload->convertVerifyErrorToStatus( $result );
-                       $this->leaveMessage( $status );
-                       return true;
-               }
-
-               # Check warnings
-               if ( !$this->params['ignoreWarnings'] ) {
-                       $warnings = $this->upload->checkWarnings();
-                       if ( $warnings ) {
-
-                               # Stash the upload
-                               $key = $this->upload->stashFile();
-
-                               if ( $this->params['leaveMessage'] ) {
-                                       $this->user->leaveUserMessage(
-                                               wfMessage( 'upload-warning-subj' )->text(),
-                                               wfMessage( 'upload-warning-msg',
-                                                       $key,
-                                                       $this->params['url'] )->text()
-                                       );
-                               } else {
-                                       wfSetupSession( $this->params['sessionId'] );
-                                       $this->storeResultInSession( 'Warning',
-                                               'warnings', $warnings );
-                                       session_write_close();
-                               }
-
-                               return true;
-                       }
-               }
-
-               # Perform the upload
-               $status = $this->upload->performUpload(
-                       $this->params['comment'],
-                       $this->params['pageText'],
-                       $this->params['watch'],
-                       $this->user
-               );
-               $this->leaveMessage( $status );
-               return true;
-
-       }
-
-       /**
-        * Leave a message on the user talk page or in the session according to
-        * $params['leaveMessage'].
-        *
-        * @param $status Status
-        */
-       protected function leaveMessage( $status ) {
-               if ( $this->params['leaveMessage'] ) {
-                       if ( $status->isGood() ) {
-                               $this->user->leaveUserMessage( wfMessage( 'upload-success-subj' )->text(),
-                                       wfMessage( 'upload-success-msg',
-                                               $this->upload->getTitle()->getText(),
-                                               $this->params['url']
-                                       )->text() );
-                       } else {
-                               $this->user->leaveUserMessage( wfMessage( 'upload-failure-subj' )->text(),
-                                       wfMessage( 'upload-failure-msg',
-                                               $status->getWikiText(),
-                                               $this->params['url']
-                                       )->text() );
-                       }
-               } else {
-                       wfSetupSession( $this->params['sessionId'] );
-                       if ( $status->isOk() ) {
-                               $this->storeResultInSession( 'Success',
-                                       'filename', $this->upload->getLocalFile()->getName() );
-                       } else {
-                               $this->storeResultInSession( 'Failure',
-                                       'errors', $status->getErrorsArray() );
-                       }
-                       session_write_close();
-               }
-       }
-
-       /**
-        * Store a result in the session data. Note that the caller is responsible
-        * for appropriate session_start and session_write_close calls.
-        *
-        * @param $result String: the result (Success|Warning|Failure)
-        * @param $dataKey String: the key of the extra data
-        * @param $dataValue Mixed: the extra data itself
-        */
-       protected function storeResultInSession( $result, $dataKey, $dataValue ) {
-               $session =& self::getSessionData( $this->params['sessionKey'] );
-               $session['result'] = $result;
-               $session[$dataKey] = $dataValue;
-       }
-
-       /**
-        * Initialize the session data. Sets the intial result to queued.
-        */
-       public function initializeSessionData() {
-               $session =& self::getSessionData( $this->params['sessionKey'] );
-               $$session['result'] = 'Queued';
-       }
-
-       /**
-        * @param $key
-        * @return mixed
-        */
-       public static function &getSessionData( $key ) {
-               if ( !isset( $_SESSION[self::SESSION_KEYNAME][$key] ) ) {
-                       $_SESSION[self::SESSION_KEYNAME][$key] = array();
-               }
-               return $_SESSION[self::SESSION_KEYNAME][$key];
-       }
-}
diff --git a/includes/job/jobs/DoubleRedirectJob.php b/includes/job/jobs/DoubleRedirectJob.php
new file mode 100644 (file)
index 0000000..b1b96b6
--- /dev/null
@@ -0,0 +1,210 @@
+<?php
+/**
+ * Job to fix double redirects after moving a page.
+ *
+ * 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 JobQueue
+ */
+
+/**
+ * Job to fix double redirects after moving a page
+ *
+ * @ingroup JobQueue
+ */
+class DoubleRedirectJob extends Job {
+       var $reason, $redirTitle;
+
+       /**
+        * @var User
+        */
+       static $user;
+
+       /**
+        * Insert jobs into the job queue to fix redirects to the given title
+        * @param $reason String: the reason for the fix, see message "double-redirect-fixed-<reason>"
+        * @param $redirTitle Title: the title which has changed, redirects pointing to this title are fixed
+        * @param $destTitle bool Not used
+        */
+       public static function fixRedirects( $reason, $redirTitle, $destTitle = false ) {
+               # Need to use the master to get the redirect table updated in the same transaction
+               $dbw = wfGetDB( DB_MASTER );
+               $res = $dbw->select(
+                       array( 'redirect', 'page' ),
+                       array( 'page_namespace', 'page_title' ),
+                       array(
+                               'page_id = rd_from',
+                               'rd_namespace' => $redirTitle->getNamespace(),
+                               'rd_title' => $redirTitle->getDBkey()
+                       ), __METHOD__ );
+               if ( !$res->numRows() ) {
+                       return;
+               }
+               $jobs = array();
+               foreach ( $res as $row ) {
+                       $title = Title::makeTitle( $row->page_namespace, $row->page_title );
+                       if ( !$title ) {
+                               continue;
+                       }
+
+                       $jobs[] = new self( $title, array(
+                               'reason' => $reason,
+                               'redirTitle' => $redirTitle->getPrefixedDBkey() ) );
+                       # Avoid excessive memory usage
+                       if ( count( $jobs ) > 10000 ) {
+                               Job::batchInsert( $jobs );
+                               $jobs = array();
+                       }
+               }
+               Job::batchInsert( $jobs );
+       }
+
+       function __construct( $title, $params = false, $id = 0 ) {
+               parent::__construct( 'fixDoubleRedirect', $title, $params, $id );
+               $this->reason = $params['reason'];
+               $this->redirTitle = Title::newFromText( $params['redirTitle'] );
+       }
+
+       /**
+        * @return bool
+        */
+       function run() {
+               if ( !$this->redirTitle ) {
+                       $this->setLastError( 'Invalid title' );
+                       return false;
+               }
+
+               $targetRev = Revision::newFromTitle( $this->title, false, Revision::READ_LATEST );
+               if ( !$targetRev ) {
+                       wfDebug( __METHOD__.": target redirect already deleted, ignoring\n" );
+                       return true;
+               }
+               $content = $targetRev->getContent();
+               $currentDest = $content->getRedirectTarget();
+               if ( !$currentDest || !$currentDest->equals( $this->redirTitle ) ) {
+                       wfDebug( __METHOD__.": Redirect has changed since the job was queued\n" );
+                       return true;
+               }
+
+               # Check for a suppression tag (used e.g. in periodically archived discussions)
+               $mw = MagicWord::get( 'staticredirect' );
+               if ( $content->matchMagicWord( $mw ) ) {
+                       wfDebug( __METHOD__.": skipping: suppressed with __STATICREDIRECT__\n" );
+                       return true;
+               }
+
+               # Find the current final destination
+               $newTitle = self::getFinalDestination( $this->redirTitle );
+               if ( !$newTitle ) {
+                       wfDebug( __METHOD__.": skipping: single redirect, circular redirect or invalid redirect destination\n" );
+                       return true;
+               }
+               if ( $newTitle->equals( $this->redirTitle ) ) {
+                       # The redirect is already right, no need to change it
+                       # This can happen if the page was moved back (say after vandalism)
+                       wfDebug( __METHOD__.": skipping, already good\n" );
+               }
+
+               # Preserve fragment (bug 14904)
+               $newTitle = Title::makeTitle( $newTitle->getNamespace(), $newTitle->getDBkey(),
+                       $currentDest->getFragment(), $newTitle->getInterwiki() );
+
+               # Fix the text
+               $newContent = $content->updateRedirect( $newTitle );
+
+               if ( $newContent->equals( $content ) ) {
+                       $this->setLastError( 'Content unchanged???' );
+                       return false;
+               }
+
+               # Save it
+               global $wgUser;
+               $oldUser = $wgUser;
+               $wgUser = $this->getUser();
+               $article = WikiPage::factory( $this->title );
+               $reason = wfMessage( 'double-redirect-fixed-' . $this->reason,
+                       $this->redirTitle->getPrefixedText(), $newTitle->getPrefixedText()
+               )->inContentLanguage()->text();
+               $article->doEditContent( $newContent, $reason, EDIT_UPDATE | EDIT_SUPPRESS_RC, false, $this->getUser() );
+               $wgUser = $oldUser;
+
+               return true;
+       }
+
+       /**
+        * Get the final destination of a redirect
+        *
+        * @param $title Title
+        *
+        * @return bool if the specified title is not a redirect, or if it is a circular redirect
+        */
+       public static function getFinalDestination( $title ) {
+               $dbw = wfGetDB( DB_MASTER );
+
+               $seenTitles = array(); # Circular redirect check
+               $dest = false;
+
+               while ( true ) {
+                       $titleText = $title->getPrefixedDBkey();
+                       if ( isset( $seenTitles[$titleText] ) ) {
+                               wfDebug( __METHOD__, "Circular redirect detected, aborting\n" );
+                               return false;
+                       }
+                       $seenTitles[$titleText] = true;
+
+                       if ( $title->getInterwiki() ) {
+                               // 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
+                               // unexpected results (e.g. X -> foo:Bar -> Bar -> .. )
+                               break;
+                       }
+
+                       $row = $dbw->selectRow(
+                               array( 'redirect', 'page' ),
+                               array( 'rd_namespace', 'rd_title', 'rd_interwiki' ),
+                               array(
+                                       'rd_from=page_id',
+                                       'page_namespace' => $title->getNamespace(),
+                                       'page_title' => $title->getDBkey()
+                               ), __METHOD__ );
+                       if ( !$row ) {
+                               # No redirect from here, chain terminates
+                               break;
+                       } else {
+                               $dest = $title = Title::makeTitle( $row->rd_namespace, $row->rd_title, '', $row->rd_interwiki );
+                       }
+               }
+               return $dest;
+       }
+
+       /**
+        * Get a user object for doing edits, from a request-lifetime cache
+        * @return User
+        */
+       function getUser() {
+               if ( !self::$user ) {
+                       self::$user = User::newFromName( wfMessage( 'double-redirect-fixer' )->inContentLanguage()->text(), false );
+                       # FIXME: newFromName could return false on a badly configured wiki.
+                       if ( !self::$user->isLoggedIn() ) {
+                               self::$user->addToDatabase();
+                       }
+               }
+               return self::$user;
+       }
+}
+
diff --git a/includes/job/jobs/EmaillingJob.php b/includes/job/jobs/EmaillingJob.php
new file mode 100644 (file)
index 0000000..d359988
--- /dev/null
@@ -0,0 +1,46 @@
+<?php
+/**
+ * Old job for notification emails.
+ *
+ * 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 JobQueue
+ */
+
+/**
+ * Old job used for sending single notification emails;
+ * kept for backwards-compatibility
+ *
+ * @ingroup JobQueue
+ */
+class EmaillingJob extends Job {
+       function __construct( $title, $params, $id = 0 ) {
+               parent::__construct( 'sendMail', Title::newMainPage(), $params, $id );
+       }
+
+       function run() {
+               UserMailer::send(
+                       $this->params['to'],
+                       $this->params['from'],
+                       $this->params['subj'],
+                       $this->params['body'],
+                       $this->params['replyto']
+               );
+               return true;
+       }
+
+}
diff --git a/includes/job/jobs/EnotifNotifyJob.php b/includes/job/jobs/EnotifNotifyJob.php
new file mode 100644 (file)
index 0000000..b4c925e
--- /dev/null
@@ -0,0 +1,57 @@
+<?php
+/**
+ * Job for notification emails.
+ *
+ * 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 JobQueue
+ */
+
+/**
+ * Job for email notification mails
+ *
+ * @ingroup JobQueue
+ */
+class EnotifNotifyJob extends Job {
+
+       function __construct( $title, $params, $id = 0 ) {
+               parent::__construct( 'enotifNotify', $title, $params, $id );
+       }
+
+       function run() {
+               $enotif = new EmailNotification();
+               // Get the user from ID (rename safe). Anons are 0, so defer to name.
+               if( isset( $this->params['editorID'] ) && $this->params['editorID'] ) {
+                       $editor = User::newFromId( $this->params['editorID'] );
+               // B/C, only the name might be given.
+               } else {
+                       # FIXME: newFromName could return false on a badly configured wiki.
+                       $editor = User::newFromName( $this->params['editor'], false );
+               }
+               $enotif->actuallyNotifyOnPageChange(
+                       $editor,
+                       $this->title,
+                       $this->params['timestamp'],
+                       $this->params['summary'],
+                       $this->params['minorEdit'],
+                       $this->params['oldid'],
+                       $this->params['watchers']
+               );
+               return true;
+       }
+
+}
diff --git a/includes/job/jobs/HTMLCacheUpdateJob.php b/includes/job/jobs/HTMLCacheUpdateJob.php
new file mode 100644 (file)
index 0000000..4e6fd6c
--- /dev/null
@@ -0,0 +1,51 @@
+<?php
+/**
+ * HTML cache invalidation of all pages linking to a given title.
+ *
+ * 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 Cache
+ */
+
+/**
+ * Job wrapper for HTMLCacheUpdate. Gets run whenever a related
+ * job gets called from the queue.
+ *
+ * @ingroup JobQueue
+ */
+class HTMLCacheUpdateJob extends Job {
+       var $table, $start, $end;
+
+       /**
+        * Construct a job
+        * @param $title Title: the title linked to
+        * @param $params Array: job parameters (table, start and end page_ids)
+        * @param $id Integer: job id
+        */
+       function __construct( $title, $params, $id = 0 ) {
+               parent::__construct( 'htmlCacheUpdate', $title, $params, $id );
+               $this->table = $params['table'];
+               $this->start = $params['start'];
+               $this->end = $params['end'];
+       }
+
+       public function run() {
+               $update = new HTMLCacheUpdate( $this->title, $this->table, $this->start, $this->end );
+               $update->doUpdate();
+               return true;
+       }
+}
diff --git a/includes/job/jobs/RefreshLinksJob.php b/includes/job/jobs/RefreshLinksJob.php
new file mode 100644 (file)
index 0000000..a29f29f
--- /dev/null
@@ -0,0 +1,202 @@
+<?php
+/**
+ * Job to update links for a given title.
+ *
+ * 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 JobQueue
+ */
+
+/**
+ * Background job to update links for a given title.
+ *
+ * @ingroup JobQueue
+ */
+class RefreshLinksJob extends Job {
+       function __construct( $title, $params = '', $id = 0 ) {
+               parent::__construct( 'refreshLinks', $title, $params, $id );
+               $this->removeDuplicates = true; // job is expensive
+       }
+
+       /**
+        * Run a refreshLinks job
+        * @return boolean success
+        */
+       function run() {
+               wfProfileIn( __METHOD__ );
+
+               $linkCache = LinkCache::singleton();
+               $linkCache->clear();
+
+               if ( is_null( $this->title ) ) {
+                       $this->error = "refreshLinks: Invalid title";
+                       wfProfileOut( __METHOD__ );
+                       return false;
+               }
+
+               # Wait for the DB of the current/next slave DB handle to catch up to the master.
+               # This way, we get the correct page_latest for templates or files that just changed
+               # milliseconds ago, having triggered this job to begin with.
+               if ( isset( $this->params['masterPos'] ) ) {
+                       wfGetLB()->waitFor( $this->params['masterPos'] );
+               }
+
+               $revision = Revision::newFromTitle( $this->title, false, Revision::READ_NORMAL );
+               if ( !$revision ) {
+                       $this->error = 'refreshLinks: Article not found "' .
+                               $this->title->getPrefixedDBkey() . '"';
+                       wfProfileOut( __METHOD__ );
+                       return false; // XXX: what if it was just deleted?
+               }
+
+               self::runForTitleInternal( $this->title, $revision, __METHOD__ );
+
+               wfProfileOut( __METHOD__ );
+               return true;
+       }
+
+       public static function runForTitleInternal( Title $title, Revision $revision, $fname ) {
+               global $wgContLang;
+
+               wfProfileIn( $fname . '-parse' );
+               $options = ParserOptions::newFromUserAndLang( new User, $wgContLang );
+               $content = $revision->getContent();
+               $parserOutput = $content->getParserOutput( $title, $revision->getId(), $options, false );
+               wfProfileOut( $fname . '-parse' );
+
+               wfProfileIn( $fname . '-update' );
+               $updates = $content->getSecondaryDataUpdates( $title, null, false, $parserOutput  );
+               DataUpdate::runUpdates( $updates );
+               wfProfileOut( $fname . '-update' );
+       }
+}
+
+/**
+ * Background job to update links for a given title.
+ * Newer version for high use templates.
+ *
+ * @ingroup JobQueue
+ */
+class RefreshLinksJob2 extends Job {
+       const MAX_TITLES_RUN = 10;
+
+       function __construct( $title, $params, $id = 0 ) {
+               parent::__construct( 'refreshLinks2', $title, $params, $id );
+       }
+
+       /**
+        * Run a refreshLinks2 job
+        * @return boolean success
+        */
+       function run() {
+               wfProfileIn( __METHOD__ );
+
+               $linkCache = LinkCache::singleton();
+               $linkCache->clear();
+
+               if ( is_null( $this->title ) ) {
+                       $this->error = "refreshLinks2: Invalid title";
+                       wfProfileOut( __METHOD__ );
+                       return false;
+               } elseif ( !isset( $this->params['start'] ) || !isset( $this->params['end'] ) ) {
+                       $this->error = "refreshLinks2: Invalid params";
+                       wfProfileOut( __METHOD__ );
+                       return false;
+               }
+
+               // Back compat for pre-r94435 jobs
+               $table = isset( $this->params['table'] ) ? $this->params['table'] : 'templatelinks';
+
+               // Avoid slave lag when fetching templates
+               if ( isset( $this->params['masterPos'] ) ) {
+                       $masterPos = $this->params['masterPos'];
+               } elseif ( wfGetLB()->getServerCount() > 1  ) {
+                       $masterPos = wfGetLB()->getMasterPos();
+               } else {
+                       $masterPos = false;
+               }
+
+               $titles = $this->title->getBacklinkCache()->getLinks(
+                       $table, $this->params['start'], $this->params['end'] );
+
+               if ( $titles->count() > self::MAX_TITLES_RUN ) {
+                       # We don't want to parse too many pages per job as it can starve other jobs.
+                       # If there are too many pages to parse, break this up into smaller jobs. By passing
+                       # in the master position here we can cut down on the time spent waiting for slaves to
+                       # catch up by the runners handling these jobs since time will have passed between now
+                       # and when they pop these jobs off the queue.
+                       $start = 0; // batch start
+                       $end   = 0; // batch end
+                       $bsize = 0; // batch size
+                       $first = true; // first of batch
+                       $jobs  = array();
+                       foreach ( $titles as $title ) {
+                               $start = $first ? $title->getArticleId() : $start;
+                               $end   = $title->getArticleId();
+                               $first = false;
+                               if ( ++$bsize >= self::MAX_TITLES_RUN ) {
+                                       $jobs[] = new RefreshLinksJob2( $this->title, array(
+                                               'table'     => $table,
+                                               'start'     => $start,
+                                               'end'       => $end,
+                                               'masterPos' => $masterPos
+                                       ) );
+                                       $first = true;
+                                       $start = $end = $bsize = 0;
+                               }
+                       }
+                       if ( $bsize > 0 ) { // group remaining pages into a job
+                               $jobs[] = new RefreshLinksJob2( $this->title, array(
+                                       'table'     => $table,
+                                       'start'     => $start,
+                                       'end'       => $end,
+                                       'masterPos' => $masterPos
+                               ) );
+                       }
+                       Job::batchInsert( $jobs );
+               } elseif ( php_sapi_name() != 'cli' ) {
+                       # Not suitable for page load triggered job running!
+                       # Gracefully switch to refreshLinks jobs if this happens.
+                       $jobs = array();
+                       foreach ( $titles as $title ) {
+                               $jobs[] = new RefreshLinksJob( $title, array( 'masterPos' => $masterPos ) );
+                       }
+                       Job::batchInsert( $jobs );
+               } else {
+                       # Wait for the DB of the current/next slave DB handle to catch up to the master.
+                       # This way, we get the correct page_latest for templates or files that just changed
+                       # milliseconds ago, having triggered this job to begin with.
+                       if ( $masterPos ) {
+                               wfGetLB()->waitFor( $masterPos );
+                       }
+                       # Re-parse each page that transcludes this page and update their tracking links...
+                       foreach ( $titles as $title ) {
+                               $revision = Revision::newFromTitle( $title, false, Revision::READ_NORMAL );
+                               if ( !$revision ) {
+                                       $this->error = 'refreshLinks: Article not found "' .
+                                               $title->getPrefixedDBkey() . '"';
+                                       continue; // skip this page
+                               }
+                               RefreshLinksJob::runForTitleInternal( $title, $revision, __METHOD__ );
+                               wfWaitForSlaves();
+                       }
+               }
+
+               wfProfileOut( __METHOD__ );
+               return true;
+       }
+}
diff --git a/includes/job/jobs/UploadFromUrlJob.php b/includes/job/jobs/UploadFromUrlJob.php
new file mode 100644 (file)
index 0000000..e06f68e
--- /dev/null
@@ -0,0 +1,179 @@
+<?php
+/**
+ * Job for asynchronous upload-by-url.
+ *
+ * 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 JobQueue
+ */
+
+/**
+ * Job for asynchronous upload-by-url.
+ *
+ * This job is in fact an interface to UploadFromUrl, which is designed such
+ * that it does not require any globals. If it does, fix it elsewhere, do not
+ * add globals in here.
+ *
+ * @ingroup JobQueue
+ */
+class UploadFromUrlJob extends Job {
+       const SESSION_KEYNAME = 'wsUploadFromUrlJobData';
+
+       /**
+        * @var UploadFromUrl
+        */
+       public $upload;
+
+       /**
+        * @var User
+        */
+       protected $user;
+
+       public function __construct( $title, $params, $id = 0 ) {
+               parent::__construct( 'uploadFromUrl', $title, $params, $id );
+       }
+
+       public function run() {
+               # Initialize this object and the upload object
+               $this->upload = new UploadFromUrl();
+               $this->upload->initialize(
+                       $this->title->getText(),
+                       $this->params['url'],
+                       false
+               );
+               $this->user = User::newFromName( $this->params['userName'] );
+
+               # Fetch the file
+               $status = $this->upload->fetchFile();
+               if ( !$status->isOk() ) {
+                       $this->leaveMessage( $status );
+                       return true;
+               }
+
+               # Verify upload
+               $result = $this->upload->verifyUpload();
+               if ( $result['status'] != UploadBase::OK ) {
+                       $status = $this->upload->convertVerifyErrorToStatus( $result );
+                       $this->leaveMessage( $status );
+                       return true;
+               }
+
+               # Check warnings
+               if ( !$this->params['ignoreWarnings'] ) {
+                       $warnings = $this->upload->checkWarnings();
+                       if ( $warnings ) {
+
+                               # Stash the upload
+                               $key = $this->upload->stashFile();
+
+                               if ( $this->params['leaveMessage'] ) {
+                                       $this->user->leaveUserMessage(
+                                               wfMessage( 'upload-warning-subj' )->text(),
+                                               wfMessage( 'upload-warning-msg',
+                                                       $key,
+                                                       $this->params['url'] )->text()
+                                       );
+                               } else {
+                                       wfSetupSession( $this->params['sessionId'] );
+                                       $this->storeResultInSession( 'Warning',
+                                               'warnings', $warnings );
+                                       session_write_close();
+                               }
+
+                               return true;
+                       }
+               }
+
+               # Perform the upload
+               $status = $this->upload->performUpload(
+                       $this->params['comment'],
+                       $this->params['pageText'],
+                       $this->params['watch'],
+                       $this->user
+               );
+               $this->leaveMessage( $status );
+               return true;
+
+       }
+
+       /**
+        * Leave a message on the user talk page or in the session according to
+        * $params['leaveMessage'].
+        *
+        * @param $status Status
+        */
+       protected function leaveMessage( $status ) {
+               if ( $this->params['leaveMessage'] ) {
+                       if ( $status->isGood() ) {
+                               $this->user->leaveUserMessage( wfMessage( 'upload-success-subj' )->text(),
+                                       wfMessage( 'upload-success-msg',
+                                               $this->upload->getTitle()->getText(),
+                                               $this->params['url']
+                                       )->text() );
+                       } else {
+                               $this->user->leaveUserMessage( wfMessage( 'upload-failure-subj' )->text(),
+                                       wfMessage( 'upload-failure-msg',
+                                               $status->getWikiText(),
+                                               $this->params['url']
+                                       )->text() );
+                       }
+               } else {
+                       wfSetupSession( $this->params['sessionId'] );
+                       if ( $status->isOk() ) {
+                               $this->storeResultInSession( 'Success',
+                                       'filename', $this->upload->getLocalFile()->getName() );
+                       } else {
+                               $this->storeResultInSession( 'Failure',
+                                       'errors', $status->getErrorsArray() );
+                       }
+                       session_write_close();
+               }
+       }
+
+       /**
+        * Store a result in the session data. Note that the caller is responsible
+        * for appropriate session_start and session_write_close calls.
+        *
+        * @param $result String: the result (Success|Warning|Failure)
+        * @param $dataKey String: the key of the extra data
+        * @param $dataValue Mixed: the extra data itself
+        */
+       protected function storeResultInSession( $result, $dataKey, $dataValue ) {
+               $session =& self::getSessionData( $this->params['sessionKey'] );
+               $session['result'] = $result;
+               $session[$dataKey] = $dataValue;
+       }
+
+       /**
+        * Initialize the session data. Sets the intial result to queued.
+        */
+       public function initializeSessionData() {
+               $session =& self::getSessionData( $this->params['sessionKey'] );
+               $$session['result'] = 'Queued';
+       }
+
+       /**
+        * @param $key
+        * @return mixed
+        */
+       public static function &getSessionData( $key ) {
+               if ( !isset( $_SESSION[self::SESSION_KEYNAME][$key] ) ) {
+                       $_SESSION[self::SESSION_KEYNAME][$key] = array();
+               }
+               return $_SESSION[self::SESSION_KEYNAME][$key];
+       }
+}
index 398ed6a..2566072 100644 (file)
@@ -283,7 +283,7 @@ class Services_JSON
                return $this->encode2($var);
        }
 
-       /**
+       /**
         * encodes an arbitrary variable into JSON format
         *
         * @param $var Mixed: any number, boolean, string, array, or object to be encoded.
index 75d474c..53716df 100644 (file)
@@ -252,7 +252,7 @@ class SvgHandler extends ImageHandler {
                try {
                        $metadata = SVGMetadataExtractor::getMetadata( $filename );
                } catch( Exception $e ) {
-                       // Broken file?
+                       // Broken file?
                        wfDebug( __METHOD__ . ': ' . $e->getMessage() . "\n" );
                        return '0';
                }
index 9ac8ad8..72f6a9f 100644 (file)
@@ -1167,10 +1167,16 @@ class MWMemcached {
                if ( !is_resource( $f ) ) {
                        return;
                }
-               $n = stream_select( $r = array( $f ), $w = null, $e = null, 0, 0 );
+               $r = array( $f );
+               $w = null;
+               $e = null;
+               $n = stream_select( $r, $w, $e, 0, 0 );
                while ( $n == 1 && !feof( $f ) ) {
                        fread( $f, 1024 );
-                       $n = stream_select( $r = array( $f ), $w = null, $e = null, 0, 0 );
+                       $r = array( $f );
+                       $w = null;
+                       $e = null;
+                       $n = stream_select( $r, $w, $e, 0, 0 );
                }
        }
 
index 49160e8..9f1fff2 100644 (file)
@@ -43,7 +43,7 @@ class LinkHolderArray {
                }
        }
 
-       /**
+       /**
         * Don't serialize the parent object, it is big, and not needed when it is
         * a parameter to mergeForeign(), which is the only application of
         * serializing at present.
index 8671665..b31288f 100644 (file)
@@ -2377,10 +2377,10 @@ class Parser {
                                wfProfileIn( __METHOD__."-paragraph" );
                                # No prefix (not in list)--go to paragraph mode
                                # XXX: use a stack for nestable elements like span, table and div
-                               $openmatch = preg_match('/(?:<table|<blockquote|<h1|<h2|<h3|<h4|<h5|<h6|<pre|<tr|<p|<ul|<ol|<li|<\\/tr|<\\/td|<\\/th)/iS', $t );
+                               $openmatch = preg_match('/(?:<table|<blockquote|<h1|<h2|<h3|<h4|<h5|<h6|<pre|<tr|<p|<ul|<ol|<dl|<li|<\\/tr|<\\/td|<\\/th)/iS', $t );
                                $closematch = preg_match(
                                        '/(?:<\\/table|<\\/blockquote|<\\/h1|<\\/h2|<\\/h3|<\\/h4|<\\/h5|<\\/h6|'.
-                                       '<td|<th|<\\/?div|<hr|<\\/pre|<\\/p|'.$this->mUniqPrefix.'-pre|<\\/li|<\\/ul|<\\/ol|<\\/?center)/iS', $t );
+                                       '<td|<th|<\\/?div|<hr|<\\/pre|<\\/p|'.$this->mUniqPrefix.'-pre|<\\/li|<\\/ul|<\\/ol|<\\/dl|<\\/?center)/iS', $t );
                                if ( $openmatch or $closematch ) {
                                        $paragraphStack = false;
                                        # TODO bug 5718: paragraph closed
index b2dd7db..53f3feb 100644 (file)
@@ -797,8 +797,8 @@ class PPDStack {
  * @ingroup Parser
  */
 class PPDStackElement {
-       var $open,                      // Opening character (\n for heading)
-               $close,             // Matching closing character
+       var     $open,              // Opening character (\n for heading)
+               $close,             // Matching closing character
                $count,             // Number of opening characters found (number of "=" for heading)
                $parts,             // Array of PPDPart objects describing pipe-separated parts.
                $lineStart;         // True if the open char appeared at the start of the input line. Not set for headings.
index 6705863..b4bd98c 100644 (file)
@@ -347,7 +347,7 @@ class ResourceLoader {
                return array_keys( $this->moduleInfos );
        }
 
-       /**
+       /**
         * Get a list of test module names for one (or all) frameworks.
         * If the given framework id is unknkown, or if the in-object variable is not an array,
         * then it will return an empty array.
index db4c758..ffa3046 100644 (file)
@@ -532,7 +532,8 @@ class ResourceLoaderFileModule extends ResourceLoaderModule {
                if ( $context->getDebug() ) {
                        $files = array_merge( $files, $this->debugScripts );
                }
-               return $files;
+
+               return array_unique( $files );
        }
 
        /**
index c880b61..3d39e37 100644 (file)
@@ -260,7 +260,7 @@ class DeletedContributionsPage extends SpecialPage {
         * Special page "deleted user contributions".
         * Shows a list of the deleted contributions of a user.
         *
-        * @param       $par    String: (optional) user name of the user for which to show the contributions
+        * @param $par String: (optional) user name of the user for which to show the contributions
         */
        function execute( $par ) {
                global $wgQueryPageDefaultLimit;
index 0810ee7..5de6076 100644 (file)
@@ -103,7 +103,7 @@ class LinkSearchPage extends QueryPage {
                                )
                        );
                }
-               $s .=   Xml::submitButton( $this->msg( 'linksearch-ok' )->text() ) .
+               $s .= Xml::submitButton( $this->msg( 'linksearch-ok' )->text() ) .
                        '</fieldset>' .
                        Xml::closeElement( 'form' );
                $out->addHTML( $s );
index 56ae302..0616d56 100644 (file)
@@ -535,7 +535,7 @@ class UserrightsPage extends SpecialPage {
                }
 
                # Build the HTML table
-               $ret .= Xml::openElement( 'table', array( 'class' => 'mw-userrights-groups' ) ) .
+               $ret .= Xml::openElement( 'table', array( 'class' => 'mw-userrights-groups' ) ) .
                        "<tr>\n";
                foreach( $columns as $name => $column ) {
                        if( $column === array() )
index 6016605..79783cc 100644 (file)
@@ -824,9 +824,9 @@ class LanguageConverter {
        /**
         * Guess if a text is written in a variant. This should be implemented in subclasses.
         *
-        * @param string        $text the text to be checked
-        * @param string        $variant language code of the variant to be checked for
-        * @return bool true if $text appears to be written in $variant, false if not
+        * @param string $text the text to be checked
+        * @param string $variant language code of the variant to be checked for
+        * @return bool true if $text appears to be written in $variant, false if not
         *
         * @author Nikola Smolenski <smolensk@eunet.rs>
         * @since 1.19
@@ -1270,7 +1270,7 @@ class ConverterRule {
                                $bidtable[$v] = $to;
                        } elseif ( count( $u ) == 2 ) {
                                $from = trim( $u[0] );
-                               $v      = trim( $u[1] );
+                               $v = trim( $u[1] );
                                if ( array_key_exists( $v, $unidtable )
                                         && !is_array( $unidtable[$v] )
                                         && $to
index 3c16248..8f84322 100644 (file)
@@ -63,7 +63,7 @@ class LanguageEo extends Language {
                if ( strcasecmp( $in, 'x' ) == 0 && strcasecmp( $out, 'utf-8' ) == 0 ) {
                        return preg_replace_callback (
                                '/([cghjsu]x?)((?:xx)*)(?!x)/i',
-                               array( $this, 'strrtxuCallback' ), $string      );
+                               array( $this, 'strrtxuCallback' ), $string );
                } elseif ( strcasecmp( $in, 'UTF-8' ) == 0 && strcasecmp( $out, 'x' ) == 0 ) {
                        # Double Xs only if they follow cxapelutaj literoj.
                        return preg_replace_callback(
index 3aa6b1f..f98b4bd 100644 (file)
@@ -156,7 +156,6 @@ $messages = array(
 'qbbrowse' => 'ara',
 'qbedit' => 'modifi el page (baddelha)',
 'qbpageoptions' => 'هذه الصفحة',
-'qbpageinfo' => 'سياق النص',
 'qbmyoptions' => 'صفحاتي',
 'qbspecialpages' => 'الصفحات الخاصة',
 'faq' => 'الأسئلة الأكثر تكرارا',
index 0baa8ed..a14fb0e 100644 (file)
@@ -732,7 +732,7 @@ $1',
 'youhavenewmessages' => 'توجد لديك $1 ($2).',
 'newmessageslink' => 'رسائل جديدة',
 'newmessagesdifflink' => 'آخر تغيير',
-'youhavenewmessagesfromusers' => 'لديك $1 من {{PLURAL:$3|مستخدم آخر|$3 مستخدمين}} ($2).',
+'youhavenewmessagesfromusers' => 'لديك $1 من {{PLURAL:$3||مستخدم واحد|مستخدمين اثنين|$3 مستخدمين|$3 مستخدماً|$3 مستخدم}} ($2).',
 'youhavenewmessagesmanyusers' => 'لديك $1 من مستخدمين كثر ($2).',
 'newmessageslinkplural' => '{{PLURAL:$1|رسالة جديدة|رسائل جديدة}}',
 'newmessagesdifflinkplural' => 'آخر {{PLURAL:$1|تغيير|تغييرات}}',
@@ -964,7 +964,7 @@ $2',
 'emailauthenticated' => 'تم تأكيد بريدك الإلكتروني في $2 الساعة $3.',
 'emailnotauthenticated' => 'لم يتم التحقق من بريدك الإلكتروني.
 لن يتم إرسال رسائل لأي من الميزات التالية.',
-'noemailprefs' => 'حدد عنوان بريد إلكتروني في تفضيلاتك لهذه الخصائص لتعمل.',
+'noemailprefs' => 'حدد عنوان بريد إلكتروني في تفضيلاتك لتفعيل هذه الخصائص.',
 'emailconfirmlink' => 'أكد عنوان بريدك الإلكتروني',
 'invalidemailaddress' => 'لا يمكن قبول عنوان البريد الإلكتروني حيث تبدو صيغته خاطئة.
 ضع عنوانا مضبوطا أو أفرغ هذا الحقل.',
@@ -1265,6 +1265,9 @@ $2
 'invalid-content-data' => 'بيانات المحتوى غير صالحة',
 'content-not-allowed-here' => '"$1" المحتوى غير مسموح على صفحة [[$2]]',
 
+# Content models
+'content-model-javascript' => 'جافاسكربت',
+
 # Parser/template warnings
 'expensive-parserfunction-warning' => "'''تحذير:''' هذه الصفحة تحتوي على استدعاءات دالة محلل كثيرة مكلفة.
 
@@ -1655,8 +1658,8 @@ $1",
 'email' => 'البريد الإلكتروني',
 'prefs-help-realname' => 'الاسم الحقيقي اختياري.
 لو اخترت أن توفره، فسيستخدم في الإشارة إلى عملك.',
-'prefs-help-email' => 'عÙ\86Ù\88اÙ\86 Ø§Ù\84برÙ\8aد Ø§Ù\84Ø¥Ù\84Ù\83ترÙ\88Ù\86Ù\8a Ù\87Ù\88 Ø£Ù\85ر Ø§Ø®ØªÙ\8aارÙ\8aØ\8c Ù\88Ù\84Ù\83Ù\86 Ø³ØªØ­ØªØ§Ø¬ Ù\84إعادة ØªØ¹Ù\8aÙ\8aÙ\86 Ù\83Ù\84Ù\85Ø© Ø§Ù\84Ù\85رÙ\88رØ\8c Ø¥Ù\86 نسيت كلمة المرور الخاصة بك.',
-'prefs-help-email-others' => 'Ù\8aÙ\85Ù\83Ù\86Ù\83 Ø£Ù\8aضا Ø§Ø®ØªÙ\8aار Ù\84Ù\84سÙ\85اح Ù\84Ù\84آخرÙ\8aÙ\86 Ø§Ù\84اتصاÙ\84 Ø¨Ù\83 Ø¹Ù\86 Ø·Ø±Ù\8aÙ\82 ØµÙ\81حة Ø§Ù\84Ù\85ستخدÙ\85 Ø£Ù\88 Ù\86Ù\82اش Ø§Ù\84Ù\85ستخدÙ\85 Ø§Ù\84خاص Ø¨Ù\83 Ø¯Ù\88Ù\86 Ø§Ù\84حاجة Ø¥Ù\84Ù\89 Ø§Ù\84Ù\83Ø´Ù\81 Ø¹Ù\86 Ø§Ù\84Ù\87Ù\88Ù\8aØ© Ø§Ù\84خاصة Ø¨Ù\83.',
+'prefs-help-email' => 'تحدÙ\8aد Ø¹Ù\86Ù\88اÙ\86 Ø§Ù\84برÙ\8aد Ø§Ù\84Ø¥Ù\84Ù\83ترÙ\88Ù\86Ù\8a Ø§Ø®ØªÙ\8aارÙ\8aØ\8c Ù\88Ù\84Ù\83Ù\86Ù\87 Ù\8aÙ\84زÙ\85 Ù\84إعادة ØªØ¹Ù\8aÙ\8aÙ\86 Ù\83Ù\84Ù\85Ø© Ø§Ù\84Ù\85رÙ\88ر Ù\81Ù\8a Ø­Ø§Ù\84 نسيت كلمة المرور الخاصة بك.',
+'prefs-help-email-others' => 'Ù\8aÙ\85Ù\83Ù\86Ù\83 Ø£Ù\8aضا Ø£Ù\86 {{GENDER:$1|تسÙ\85Ø­|تسÙ\85Ø­Ù\8a}} Ù\84Ù\84آخرÙ\8aÙ\86 Ø§Ù\84اتصاÙ\84 Ø¨Ù\83 Ø¹Ù\86 Ø·Ø±Ù\8aÙ\82 Ù\88صÙ\84Ø© Ù\81Ù\8a ØµÙ\81حة Ø§Ù\84Ù\85ستخدÙ\85 Ø£Ù\88 Ù\86Ù\82اش Ø§Ù\84Ù\85ستخدÙ\85 Ø§Ù\84خاصة Ø¨Ù\83. Ù\84ا Ù\8aÙ\83Ø´Ù\81 Ø¨Ø±Ù\8aدÙ\83 Ø§Ù\84Ø¥Ù\84Ù\83ترÙ\88Ù\86Ù\8a Ø¹Ù\86دÙ\85ا Ù\8aراسÙ\84Ù\83 Ø£Ø­Ø¯ Ø¨Ù\87Ø°Ù\87 Ø§Ù\84طرÙ\8aÙ\82Ø©Ø\8c Ù\88Ù\84Ù\83Ù\86 Ø¥Ø°Ø§ Ø±Ø§Ø³Ù\84ت Ø£Ø­Ø¯Ø§Ù\8b Ø³Ù\8aرÙ\89 Ø¨Ø±Ù\8aدÙ\83 Ø§Ù\84Ø¥Ù\84Ù\83ترÙ\88Ù\86Ù\8a.',
 'prefs-help-email-required' => 'عنوان البريد الإلكتروني مطلوب.',
 'prefs-info' => 'المعلومات الأساسية',
 'prefs-i18n' => 'الترجمة',
@@ -2740,7 +2743,7 @@ $UNWATCHURL
 'undeletedrevisions-files' => 'أسترجعت {{PLURAL:$1||مراجعة واحدة|مراجعتان|$1 مراجعات|$1 مراجعة}}  و{{PLURAL:$2||ملف واحد|ملفان|$2 ملفات|$2 ملفًا|$2 ملف}}',
 'undeletedfiles' => 'أسترجع {{PLURAL:$1||ملف واحد|ملفان|$1 ملفات|$1 ملفًا|$1 ملف}}',
 'cannotundelete' => 'فشل الاسترجاع؛
-ربما قام شخص آخر باسترجاع الصفحة بالفعل.',
+$1',
 'undeletedpage' => "'''تم استرجاع $1'''
 
 راجع [[Special:Log/delete|سجل الحدف]] لمعاينة عمليات الحذف والاسترجاعات الحديثة.",
@@ -4388,7 +4391,7 @@ $5
 # Durations
 'duration-seconds' => '{{PLURAL:$1|أقل من ثانية|ثانية واحدة|ثانيتان|$1 ثوانٍ|$1 ثانية}}',
 'duration-minutes' => '{{PLURAL:$1|أقل من دقيقة|دقيقة واحدة|دقيقتان|$1 دقائق|$1 دقيقة}}',
-'duration-hours' => '({{PLURAL:$1||ساعة واحد|ساعتان|$1 ساعات|$1 ساعة}})',
+'duration-hours' => '({{PLURAL:$1||ساعة واحدة|ساعتان|$1 ساعات|$1 ساعة}})',
 'duration-days' => '{{PLURAL:$1||يوم واحد|يومان|$1 أيام|$1 يومًا|$1 يوم}}',
 'duration-weeks' => '{{PLURAL:$1||أسبوع واحد|أسبوعان|$1 أسابيع|$1 أسبوعًا|$1 أسبوع}}',
 'duration-years' => '{{PLURAL: $1||سنة واحدة|سنتان|$1 سنين|$1 سنة}}',
index cc9242c..786c965 100644 (file)
@@ -185,7 +185,7 @@ $messages = array(
 'category_header' => 'ܦܐܬܬ̈ܐ ܒܣܕܪܐ ܕ "$1"',
 'subcategories' => 'ܣܕܪ̈ܐ ܦܪ̈ܥܝܐ',
 'category-media-header' => 'ܡܝܕܝܐ ܒܣܕܪܐ ܕ "$1"',
-'category-empty' => "''ܗܢܐ ܣܕܪܐ ܗܫܐ ܠܝܬ ܒܗ ܦܐܬܬ̈ܐ ܐܘ ܡܝܕܝܐ.''",
+'category-empty' => "''ܗܢܐ ܣܕܪܐ ܗܫܐܝܬ ܠܝܬ ܒܗ ܦܐܬܬ̈ܐ ܐܘ ܡܝܕܝܐ.''",
 'hidden-categories' => '{{PLURAL:$1|ܣܕܪܐ ܛܘܫܝܐ|ܣܕܪ̈ܐ ܛܘܫܝܐ}}',
 'hidden-category-category' => 'ܣܕܪ̈ܐ ܛܘܫܝ̈ܐ',
 'category-subcat-count' => '{{PLURAL:$2|ܣܕܪܐ ܗܢܐ ܐܝܬ ܒܗ ܗܢܐ ܣܕܪܐ ܦܪܥܝܐ ܕܐܬܐ ܒܠܚܘܕ.|ܣܕܪܐ ܗܢܐ ܐܝܬ ܒܗ {{PLURAL:$1|ܣܕܪܐ ܦܪܥܝܐ ܕܐܬܐ|$1 ܣܕܪ̈ܐ ܦܪ̈ܥܝܐ ܕܐܬܝܢ}}، ܡܢ ܣܘܝܟܐ ܕ $2.}}',
@@ -423,6 +423,10 @@ $1',
 'loginsuccesstitle' => 'ܥܠܠܐ ܓܡܪ',
 'loginsuccess' => "'''ܗܫܐ ܥܠܝܠܐ ܐܢܬ ܒ{{SITENAME}} ܒܫܡ \"\$1\".'''",
 'nouserspecified' => 'ܘܠܐ ܠܟ ܕܬܚܡ ܫܡܐ ܕܡܦܠܚܢܐ',
+'wrongpassword' => 'ܡܠܬܐ ܕܥܠܠܐ ܠܐ ܬܪܝܨܬܐ ܐܥܠܬ.
+ܒܒܥܘ ܡܢܟ ܕܬܢܣܐ ܙܒܢ ܐܚܪܝܢ.',
+'wrongpasswordempty' => 'ܡܠܬܐ ܕܥܠܠܐ ܕܐܥܠܬ ܣܦܝܩܬܐ ܐܝܬܝܗ.
+ܒܒܥܘ ܡܢܟ ܕܬܢܣܐ ܙܒܢ ܐܚܪܝܢ.',
 'mailmypassword' => 'ܫܕܪ ܠܝ ܡܠܬܐ ܚܕܬܐ ܕܥܠܠܐ',
 'passwordremindertitle' => 'ܡܠܬܐ ܕܥܠܠܐ ܙܒܢܢܝܬܐ ܚܕܬܐ ܠ{{SITENAME}}',
 'noemail' => 'ܠܝܬ ܒܝܠܕܪܐ ܐܠܩܛܪܘܢܝܐ ܠܡܦܠܚܢܐ "$1".',
@@ -493,7 +497,7 @@ $1',
 'note' => "'''ܡܥܝܪܢܘܬܐ:'''",
 'previewnote' => "'''ܕܟܪ ܕܗܢܘ ܚܝܪܐ ܩܕܡܝܐ ܒܠܚܘܕ'''.
 ܫܘܚܠܦ̈ܐ ܕܝܠܟ ܠܐ ܐܬܠܒܟܘ ܥܕܡܐ ܠܗܫܐ!",
-'continue-editing' => 'Ü\90Ü\93ܡܪ Ü ܫܘܚܠܦܐ',
+'continue-editing' => 'Ü\99Ü  Ü Ü\9dܬÜ\92Ü\90 Ü\95ܫܘܚܠܦܐ',
 'editing' => 'ܫܚܠܦܬܐ ܕ $1',
 'creating' => 'ܣܘܝܡܐ ܕ $1',
 'editingsection' => 'ܫܚܠܦܬܐ ܕ $1 (ܡܢܬܐ)',
@@ -1468,6 +1472,32 @@ Do you want to change the settings?',
 'anonusers' => '{{SITENAME}} {{PLURAL:$2|ܡܦܠܚܢܐ ܠܐ ܝܕܝܥܐ|ܡܦܠܚܢ̈ܐ ܠܐ ܝܕ̈ܝܥܐ}} $1',
 'creditspage' => 'ܙܕ̈ܩܐ ܕܦܐܬܐ',
 
+# Info page
+'pageinfo-title' => 'ܝܕ̈ܥܬܐ ܥܠ "$1"',
+'pageinfo-header-basic' => 'ܝܕ̈ܥܬܐ ܪ̈ܫܝܬܐ',
+'pageinfo-header-edits' => 'ܬܫܥܝܬܐ ܕܫܘܚܠܦ̈ܐ',
+'pageinfo-header-restrictions' => 'ܢܘܛܪܐ ܕܦܐܬܐ',
+'pageinfo-display-title' => 'ܚܘܘܝܐ ܕܟܘܢܝܐ',
+'pageinfo-default-sort' => 'ܩܠܝܕܐ ܕܛܘܟܣܐ ܡܬܚܫܒܢܝܐ',
+'pageinfo-length' => 'ܥܓܪܐ ܕܦܐܬܐ (ܒܒܐܝܛ)',
+'pageinfo-article-id' => 'ܗܝܝܘܬܐ ܕܦܐܬܐ',
+'pageinfo-robot-policy' => 'ܐܝܟܢܝܘܬܐ ܕܡܙܝܥܢܐ ܕܒܨܝܐ',
+'pageinfo-robot-index' => 'ܡܬܚܘܝܢܐ',
+'pageinfo-robot-noindex' => 'ܠܐ ܡܬܚܘܝܢܐ',
+'pageinfo-views' => 'ܡܢܝܢܐ ܕܚܙܝܬ̈ܐ',
+'pageinfo-watchers' => 'ܡܢܝܢܐ ܕܪ̈ܗܝܐ',
+'pageinfo-redirects-name' => 'ܨܘܝܒ̈ܐ ܠܦܐܬܐ ܗܕܐ',
+'pageinfo-subpages-name' => 'ܦܐܬܬ̈ܐ ܦܪ̈ܥܝܐ ܕܦܐܬܐ ܗܕܐ',
+'pageinfo-firstuser' => 'ܒܪܝܢܐ ܕܦܐܬܐ',
+'pageinfo-firsttime' => 'ܣܝܩܘܡܐ ܕܒܪܝܬܐ ܕܦܐܬܐ',
+'pageinfo-lastuser' => 'ܫܚܠܦܢܐ ܐܚܪܝܐ',
+'pageinfo-lasttime' => 'ܣܝܩܘܡܐ ܕܫܘܚܠܦܐ ܐܚܪܝܐ',
+'pageinfo-edits' => 'ܡܢܝܢܐ ܕܫܘܚܠܦ̈ܐ',
+'pageinfo-authors' => 'ܡܢܝܢܐ ܕܡܫܚܠܦܢ̈ܐ ܡܫܚܠܦ̈ܐ',
+'pageinfo-recent-edits' => 'ܡܢܝܢܐ ܕܫܘܚܠܦ̈ܐ ܐܚܪ̈ܝܐ (ܒ {{PLURAL:$1||ܚܕ ܝܘܡܐ|$1 ܝܘܡܬ̈ܐ}})',
+'pageinfo-recent-authors' => 'ܡܢܝܢܐ ܕܡܫܚܠܦܢ̈ܐ ܡܫܚܠܦ̈ܐ ܐܚܪ̈ܝܐ',
+'pageinfo-toolboxlink' => 'ܝܕ̈ܥܬܐ ܥܠ ܦܐܬܐ',
+
 # Image deletion
 'filedeleteerror-short' => 'ܦܘܕܐ ܒܫܝܦܐ ܕܠܦܦܐ: $1',
 'filedeleteerror-long' => 'ܦܘܕ̈ܐ ܐܫܟܚܬ ܟܕ ܫܝܦܐ ܠܦܦܐ:
index 0d00d74..7c2b31d 100644 (file)
@@ -339,7 +339,7 @@ $messages = array(
 'vector-action-protect' => 'সুৰক্ষিত কৰক',
 'vector-action-undelete' => 'পুনৰুদ্ধাৰ কৰক',
 'vector-action-unprotect' => 'সুৰক্ষা সলনি কৰক',
-'vector-simplesearch-preference' => 'à¦\89à§\8eà¦\95à§\83ষà§\8dà¦\9f à¦¸à¦¨à§\8dধানৰ à¦ªà§°à¦¾à¦®à§°à§\8dশ সক্ৰিয় কৰক (ভেক্টৰ স্কিনৰ বাবেহে)',
+'vector-simplesearch-preference' => 'সৰল à¦¸à¦¨à§\8dধান à¦¦à¦£à§\8dডিà¦\95া সক্ৰিয় কৰক (ভেক্টৰ স্কিনৰ বাবেহে)',
 'vector-view-create' => 'সৃষ্টি কৰক',
 'vector-view-edit' => 'সম্পাদনা',
 'vector-view-history' => 'ইতিহাস চাওক',
@@ -445,6 +445,8 @@ $1',
 'youhavenewmessages' => 'আপোনাৰ কাৰণে $1 আছে। ($2)',
 'newmessageslink' => 'নতুন সংবাদ',
 'newmessagesdifflink' => 'শেহতীয়া সাল-সলনি',
+'youhavenewmessagesfromusers' => '{{PLURAL:$3|আন এজন সদস্য|$3 জন সদস্য}}ৰ পৰা আপোনালৈ $1 আহিছে ($2)।',
+'youhavenewmessagesmanyusers' => 'কেইবাজনো সদস্যৰ পৰা আপোনালৈ $1 আহিছে ($2)।',
 'newmessageslinkplural' => '{{PLURAL:$1|এটা নতুন বাৰ্তা|নতুন বাৰ্তা}}',
 'newmessagesdifflinkplural' => 'অন্তিম {{PLURAL:$1|সংশোধন}}',
 'youhavenewmessagesmulti' => '$1ত আপোনাৰ কাৰণে নতুন সংবাদ আছে',
@@ -498,12 +500,12 @@ $1',
 # General errors
 'error' => 'ভুল',
 'databaseerror' => 'তথ্যকোষৰ ভুল',
-'dberrortext' => 'Database query’ত ত্ৰুটি আছে।
+'dberrortext' => 'Database query syntaxত ত্ৰুটি হৈছে।
 ছফ্টৱেৰত থকা কোনো বাগৰ বাবে এনে হব পাৰে।
 অন্তিমবাৰ চেষ্টা কৰা ডাটাবেচ কুৱেৰীটো আছিল এনেধৰণৰ:
-<blockquote><tt>$1</tt></blockquote>
-"<tt>$2</tt>" ফাংচনৰ পৰা
-ডাটাবেচে প্ৰেৰণ কৰা ত্ৰুটি: "<tt>$3: $4</tt>".',
+<blockquote><code>$1</code></blockquote>
+"<code>$2</code>" ফাংচনৰ পৰা।
+ডাটাবেচে প্ৰেৰণ কৰা ত্ৰুটি: "<samp>$3: $4</samp>"।',
 'dberrortextcl' => 'এক ডাটাবেচ চিণ্টেক্স ত্ৰুটি ঘটিছে।
 অন্তিমবাৰ চেষ্টা কৰা ডাটাবেচ কুৱেৰীটো আছিল এনেধৰণৰ:
 "$1"
@@ -557,8 +559,11 @@ $1',
 'protectedpagetext' => 'এই পৃষ্ঠাটোৰ সম্পাদনা ৰোধ কৰিবলৈ সুৰক্ষিত কৰা হৈছে।',
 'viewsourcetext' => 'আপুনি এই পৃষ্ঠাটোৰ উৎস চাব আৰু নকল কৰিব পাৰে',
 'viewyourtext' => "আপুনি '''আপোনাৰ সম্পাদনাসমূহ'''ৰ উৎস চাব আৰু এই পৃষ্ঠালৈ নকল কৰিব পাৰে:",
-'protectedinterface' => 'এই পৃষ্ঠাই ৱিকি ছফ্টৱেৰৰ ইণ্টাৰফে’চ বাৰ্তা প্ৰদান কৰে, আৰু ইয়াক সুৰক্ষিত কৰি ৰখা হৈছে ।',
-'editinginterface' => "'''সাৱধানবাণী:''' আপুনি যিখন পৃষ্ঠা সম্পাদনা কৰিছে সেইখন ৱিকি ছফ্টৱেৰৰ ইণ্টাৰফে’চ বাৰ্তা দিবলৈ ব্যৱহাৰ হয় । এই পৃষ্ঠাৰ সাল-সলনিয়ে আন ব্যৱহাৰকাৰীৰ বাবে ইণ্টাৰফে’চত প্ৰভাৱ পেলাব । অনুবাদৰ বাবে অনুগ্ৰহ কৰি মিডিয়াৱিকি স্থানীয়কৰণ প্ৰকল্প [//translatewiki.net/wiki/Main_Page?setlang=bn translatewiki.net] ব্যৱহাৰ কৰক ।",
+'protectedinterface' => 'এই পৃষ্ঠাই ৱিকি ছফ্টৱেৰৰ ইণ্টাৰফে’চ বাৰ্তা প্ৰদান কৰে আৰু ইয়াক সুৰক্ষিত কৰি ৰখা হৈছে।
+সকলো ৱিকিৰ বাবে অনুবাদ যোগ কৰিবলৈ বা সলাবলৈ অনুগ্ৰহ কৰি মিডিয়াৱিকি স্থানীয়কৰণ প্ৰকল্প [//translatewiki.net/ translatewiki.net] ব্যৱহাৰ কৰক।',
+'editinginterface' => "'''সাৱধানবাণী:''' আপুনি যিখন পৃষ্ঠা সম্পাদনা কৰিছে সেইখন এই ছফ্টৱেৰৰ ইণ্টাৰফে’চ বাৰ্তা দিবলৈ ব্যৱহাৰ হয়।
+এই পৃষ্ঠাৰ সাল-সলনিয়ে আন ব্যৱহাৰকাৰীৰ বাবে ইণ্টাৰফে’চত প্ৰভাৱ পেলাব।
+সকলো ৱিকিৰ বাবে অনুবাদৰ বাবে অনুগ্ৰহ কৰি মিডিয়াৱিকি স্থানীয়কৰণ প্ৰকল্প [//translatewiki.net/ translatewiki.net] ব্যৱহাৰ কৰক ।",
 'sqlhidden' => '(নিহিত SQL query)',
 'cascadeprotected' => 'এই পৃষ্ঠাখন সম্পাদনাৰ পৰা সুৰক্ষিত কাৰণ এই {{PLURAL:$1|পৃষ্ঠা, যিখন|পৃষ্ঠা, যিবোৰ}} "প্ৰপাতাকাৰ" (cascading) বিকল্পৰ সহযোগত সুৰক্ষিত কৰা হৈছে: 
 $2',
@@ -594,6 +599,7 @@ $2',
 'remembermypassword' => 'মোৰ প্ৰৱেশ এই কম্পিউটাৰত মনত ৰাখিব (সৰ্বাধিক $1 {{PLURAL:$1|দিনলৈ|দিনলৈ}})',
 'securelogin-stick-https' => 'প্ৰৱেশ কৰা পাছত HTTPS-ৰ দ্বাৰা সংযোগ ৰাখক',
 'yourdomainname' => 'আপোনাৰ ডমেইন:',
+'password-change-forbidden' => 'আপুনি এই ৱিকিত গুপ্তশব্দ সলাব নোৱাৰে।',
 'externaldberror' => 'কোনো প্ৰামাণ্যকৰণ তথ্যকোষৰ ত্ৰুটি ঘটিছে নতুবা আপোনাৰ বৰ্হি-একাউণ্ট নৱীকৰণ কৰাৰ অনুমতি নাই ।',
 'login' => 'প্ৰৱেশ',
 'nav-login-createaccount' => 'প্ৰৱেশ/সদস্যভুক্তি',
@@ -836,9 +842,13 @@ $1ৰ দ্বাৰা এই অৱৰোধ কৰা হৈছে ।
 আপুনি আন পৃষ্ঠাত [[Special:Search/{{PAGENAME}}| এই শিৰোনামা অনুসন্ধান কৰিব পাৰে]],
 <span class="plainlinks">[{{fullurl:{{#Special:Log}}|page={{FULLPAGENAMEE}}}} সম্পৰ্কীয় অভিলেখ অনুসন্ধান কৰিব পাৰে],
 বা [{{fullurl:{{FULLPAGENAME}}|action=edit}} এই পৃষ্ঠা সম্পাদনা কৰিব পাৰে]</span>',
-'noarticletext-nopermission' => 'এই পৃষ্ঠাত বৰ্তমান কোনো পাঠ্য নাই ।
-আপুনি আন পৃষ্ঠাত [[Special:Search/{{PAGENAME}}| এই শিৰোনামা অনুসন্ধান কৰিব পাৰে]],
-বা <span class="plainlinks">[{{fullurl:{{#Special:Log}}|page={{FULLPAGENAMEE}}}} সম্পৰ্কীয় অভিলেখ অনুসন্ধান কৰিব পাৰে ।]</span>',
+'noarticletext-nopermission' => 'এই পৃষ্ঠাত বৰ্তমান কোনো পাঠ্য নাই।
+আপুনি আন পৃষ্ঠাত [[Special:Search/{{PAGENAME}}|এই শিৰোনামা অনুসন্ধান কৰিব পাৰে]],
+বা <span class="plainlinks">[{{fullurl:{{#Special:Log}}|page={{FULLPAGENAMEE}}}} সম্পৰ্কীয় অভিলেখ অনুসন্ধান কৰিব পাৰে]</span>, কিন্তু এই পৃষ্ঠা সৃষ্টি কৰিবলৈ আপোনাৰ অনুমতি নাই।',
+'missing-revision' => '"{{PAGENAME}}" নামৰ পৃষ্ঠাৰ #$1 সংশোধনৰ অস্তিত্ব নাই।
+
+সাধাৰণতে বিলোপ কৰা এখন পৃষ্ঠাৰ পুৰণা ইতিহাস লিংক অনুসৰণ কৰিলে এনে হয়।
+[{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} বিলোপন ল\'গ]ত অধিক তথ্য পাব।',
 'userpage-userdoesnotexist' => '"<nowiki>$1</nowiki>" নামৰ সদস্য একাউন্ট নিবন্ধিত নহয় ।
 অনুগ্ৰহ কৰি চাওক আপুনি এই পৃষ্ঠা সৃষ্টি/সম্পাদনা কৰিব বিচাৰিছে নেকি ।',
 'userpage-userdoesnotexist-view' => "সদস্য একাউন্ট ''$1'' পঞ্জীভূত নহয়",
@@ -848,7 +858,6 @@ $1ৰ দ্বাৰা এই অৱৰোধ কৰা হৈছে ।
 * '''Firefox / Safari: ''' ''Shift'' ধৰি ৰাখি ''Reload'' ক্লিক কৰক, নাইবা ''Ctrl-F5'' বা ''Ctrl-R'' টিপক (এপল মেকৰ বাবে ''⌘-R'')
 * '''Google Chrome:''' ''Ctrl-Shift-R'' টিপক (এপল মেকৰ বাবে ''⌘-Shift-R'' )
 * '''Internet Explorer:''' ''Ctrl'' ধৰি ৰাখি ''Refresh'' ক্লিক কৰক, অথবা ''Ctrl-F5'' টিপক
-* '''Konqueror: ''' ''Reload'' ক্লিক কৰক বা ''F5'' টিপক
 * '''Opera:''' ''Tools→Preferences'' ত গৈ কেচ্‌ মচি পেলাওক",
 'usercssyoucanpreview' => "'''পৰামৰ্শ:''' \"{{int:showpreview}}\" বুটাম ব্যৱহাৰ কৰি সাঁচি ৰখাৰ আগতে আপোনাৰ নতুন CSS পৰীক্ষা কৰক ।",
 'userjsyoucanpreview' => "'''পৰামৰ্শ:''' \"{{int:showpreview}}\" বুটাম ব্যৱহাৰ কৰি সাঁচি ৰখাৰ আগতে আপোনাৰ নতুন জাভালিপি পৰীক্ষা কৰক ।",
@@ -865,7 +874,7 @@ $1ৰ দ্বাৰা এই অৱৰোধ কৰা হৈছে ।
 'note' => "'''টোকা:'''",
 'previewnote' => "'''মনত ৰাখিব এয়া মাথোন প্ৰাক্‌দৰ্শনহে।'''
 আপোনাৰ সালসলনিসমূহ এতিয়াও সংৰক্ষণ কৰা হোৱা নাই!",
-'continue-editing' => 'সমà§\8dপাদনা à¦\9cাৰà§\80 à§°à¦¾à¦\96ক',
+'continue-editing' => 'সমà§\8dপাদনা à¦\95à§\8dষà§\87তà§\8dৰলà§\88 à¦¯à¦¾à¦\93ক',
 'previewconflict' => 'এই প্ৰাকদৰ্শনে ওপৰৰ সম্পাদনা ক্ষেত্ৰৰ লেখা সাঁচি ৰাখিলে যেনেকুৱা দেখা যাব তেনেকুৱা দেখাইছে ।',
 'session_fail_preview' => "'''দুঃখিত! চেচন ডাটা হেৰাই যোৱাৰ কাৰণে আপোনাৰ সম্পাদনা কৃতকাৰ্য্য নহ'ল ।'''
 অনুগ্ৰহ কৰি পুনৰ চেষ্টা কৰক ।
@@ -951,6 +960,14 @@ $1ৰ দ্বাৰা এই অৱৰোধ কৰা হৈছে ।
 'edit-already-exists' => "নতুন পৃষ্ঠা সৃষ্টি কৰা নহ'ল ।
 পৃষ্ঠাখন ইতিমধ্যে আছেই ।",
 'defaultmessagetext' => 'সাধাৰণ বাৰ্তা পাঠ্য',
+'invalid-content-data' => 'অবৈধ সমল তথ্য',
+'content-not-allowed-here' => '[[$2]] পৃষ্ঠাত "$1" সমল অনুমোদিত নহয়',
+
+# Content models
+'content-model-wikitext' => 'ৱিকিপাঠ্য',
+'content-model-text' => 'সাধাৰণ পাঠ্য',
+'content-model-javascript' => 'জাভাস্ক্ৰীপ্ট',
+'content-model-css' => 'চি.এচ.এচ.',
 
 # Parser/template warnings
 'expensive-parserfunction-warning' => "'''সতৰ্কবাণী:''' এই পৃষ্ঠাখনত অধিক এক্সপেনচিভ পাৰ্চাৰ ফাংচন কল আছে ।
@@ -972,6 +989,7 @@ $1ৰ দ্বাৰা এই অৱৰোধ কৰা হৈছে ।
 'expansion-depth-exceeded-warning' => 'পৃষ্ঠাখনৰ বিস্তৃতি গভীৰতা বেছি হৈছে',
 'parser-unstrip-loop-warning' => 'আন্‌ষ্ট্ৰীপ লুপ চিনাক্ত কৰা হৈছে',
 'parser-unstrip-recursion-limit' => 'আন্‌ষ্ট্ৰিপ ৰিকাৰ্ছন সীমা অতিক্ৰম হৈছে ($1)',
+'converter-manual-rule-error' => 'মেনুৱেল ভাষা পৰিৱৰ্তন নিয়মত ত্ৰুটি পোৱা গৈছে',
 
 # "Undo" feature
 'undo-success' => 'এই সম্পাদনা পূৰ্ববৎ কৰিব পাৰি ।
@@ -1093,7 +1111,7 @@ $1",
 'revdel-restore' => 'দৃষ্টিপাত সালসলনি কৰক',
 'revdel-restore-deleted' => 'বাতিল কৰা সংশোধনসমূহ',
 'revdel-restore-visible' => 'দৃশ্যমান সংশোধনসমূহ',
-'pagehist' => 'পৃষ্ঠা ইতিহাস',
+'pagehist' => 'পৃষ্ঠা ইতিহাস',
 'deletedhist' => 'বিলোপ কৰাৰ ইতিহাস',
 'revdelete-hide-current' => ' $2, $1 তাৰিখৰ এই আইটেমটো গোপন কৰাত সমস্যা হৈছে: এইটো বৰ্তমানৰ সংশোধনী ।
 এইটোক গোপন কৰিব পৰা নাযাব ।',
@@ -1107,8 +1125,9 @@ $1",
 অনুগ্ৰহ কৰি ল’গ পৰীক্ষা কৰক ।',
 'revdelete-only-restricted' => '$2, $1 তৰিখৰ আইটেমটো গোপন কৰাত সমস্যা হৈছে: আন প্ৰত্যক্ষতা বিকল্প বাছনি নকৰাকৈ আপুনি প্ৰশাসকৰ দৃষ্টিৰ পৰা আইটেমসমূহ নিবাৰণ কৰিব নোৱাৰে ।',
 'revdelete-reason-dropdown' => '*বিলোপৰ সাধাৰণ কাৰণসমূহ 
-** স্বত্বাধিকাৰ উলংঘন 
-** অনুপযুক্ত ব্যক্তিগত তথ্য 
+** কপিৰাইট উলংঘন 
+** অনুপযুক্ত মন্তব্য বা ব্যক্তিগত তথ্য 
+** অনুপযুক্ত সদস্যনাম
 ** সম্ভাব্য ক্ষতিকাৰক তথ্য',
 'revdelete-otherreason' => 'অন্য/অতিৰিক্ত কাৰণ:',
 'revdelete-reasonotherlist' => 'অন্য কাৰণ',
@@ -1198,7 +1217,7 @@ $1",
 'search-result-size' => '$1 ({{PLURAL:$2|1 শব্দ|$2 শব্দসমূহ}})',
 'search-result-category-size' => '{{PLURAL:$1|১ জন সদস্য|$1 জন সদস্য}} ({{PLURAL:$2|এটা উপশ্ৰেণী|$2 টা উপশ্ৰেণী}}, {{PLURAL:$3|এটা ফাইল|$3 টা ফাইল}})',
 'search-result-score' => 'যথাৰ্থতা: $1%',
-'search-redirect' => '(পুনৰ্নিদেশনা $1)',
+'search-redirect' => '(পà§\81নৰà§\8dনিৰà§\8dদà§\87শনা $1)',
 'search-section' => '(অনুচ্ছেদ $1)',
 'search-suggest' => 'আপুনি $1 বুজাব খুজিছে নেকি?',
 'search-interwiki-caption' => 'সহপ্ৰকল্পসমূহ',
@@ -1215,10 +1234,10 @@ $1",
 'nonefound' => "'''টোকা:''' ডিফ’ল্ট অনুযায়ী মাথোঁ কেইটামানহে নামস্থান অনুসন্ধান কৰা হয় ।
 আপোনাৰ অনুসন্ধানত ''all:'' ব্যবহাৰ কৰি সকলো সমল (কথা-বতৰা, শ্ৰেনী ইত্যদি) অনুসন্ধান কৰিব পাৰে, নতুবা আকাংক্ষিত নামস্থান প্ৰিফিক্স হিছাপে ব্যবহাৰ কৰিব পাৰে ।",
 'search-nonefound' => 'এই অনুসন্ধানৰ কোনো ফলাফল নাই ।',
-'powersearch' => 'à¦\85তিসন্ধান',
+'powersearch' => 'শà¦\95à§\8dতিশালà§\80 সন্ধান',
 'powersearch-legend' => 'শক্তিশালী সন্ধান',
 'powersearch-ns' => 'নামস্থানবোৰত সন্ধান:',
-'powersearch-redir' => 'পà§\81ননিৰà§\8dদà§\87শà¦\95ৰ তালিকা',
+'powersearch-redir' => 'পà§\81নৰà§\8dনিৰà§\8dদà§\87শনাৰ তালিকা',
 'powersearch-field' => 'ৰ কাৰণে সন্ধান কৰক',
 'powersearch-togglelabel' => 'পৰীক্ষা কৰক:',
 'powersearch-toggleall' => 'সকলো',
@@ -1301,7 +1320,7 @@ $1",
 'timezoneregion-indian' => 'ভাৰত মহাসাগৰ',
 'timezoneregion-pacific' => 'প্ৰশান্ত মহাসাগৰ',
 'allowemail' => 'অন্য সদস্যৰ পৰা ই-মেইল সমৰ্থ কৰক',
-'prefs-searchoptions' => 'সনà§\8dধান à¦¬à¦¿à¦\95লà§\8dপসমà§\82হ',
+'prefs-searchoptions' => 'সনà§\8dধান à¦\95ৰà¦\95',
 'prefs-namespaces' => 'নামস্থান',
 'defaultns' => 'অন্যথা এই নামস্থান সমূহত অনুসন্ধান কৰিব:',
 'default' => 'অবিচল',
@@ -1724,7 +1743,7 @@ URL টোৰ বৈধতা বিচাৰ কৰি পুনৰ চেষ
 'backend-fail-internal' => 'ষ্ট\'ৰেজ বেক্‌এণ্ড "$1"ত এক অজ্ঞাত ত্ৰুটী ঘটিছে।',
 'backend-fail-contenttype' => '"$1"ত সাঁচি থ\'বলৈ ফাইলটোৰ সমল প্ৰকাৰ স্থিৰ কৰিব পৰা নগ\'ল।',
 'backend-fail-batchsize' => "$1টা ফাইল {{PLURAL:$1|কাৰ্যৰ|কাৰ্যৰ}} ষ্ট'ৰেজ বেকএ'ণ্ড দিয়া হৈছে; সীমা হৈছে $2টা {{PLURAL:$2|কাৰ্য|কাৰ্য}}।",
-'backend-fail-usable' => "অপৰ্যাপ্ত অনুমতি বা হেৰোৱা নিৰ্দেশিকা/সমলৰ বাবে $1 ফাইলটো লিখিব পৰা নগ'ল।",
+'backend-fail-usable' => 'অপৰ্যাপ্ত অনুমতি বা হেৰোৱা নিৰ্দেশিকা/সমলৰ বাবে "$1" ফাইলটো পঢ়িব বা লিখিব পৰা নগ\'ল।',
 
 # File journal errors
 'filejournal-fail-dbconnect' => 'ষ্ট\'ৰেজ বেকএ\'ণ্ড "$1"ৰ বাবে জাৰ্ণাল তথ্যকোষৰ লগত সংযোগ স্থাপন নহ\'ল।',
@@ -1860,6 +1879,7 @@ https://www.mediawiki.org/wiki/Manual:Image_Authorization চাওক।",
 'uploadnewversion-linktext' => "এই ফাইলতোৰ নতুন সংশোধন এটা আপল'ড কৰক",
 'shared-repo-from' => '$1 পৰা',
 'shared-repo' => 'এটা উমৈহতীয়া ভঁৰাল',
+'upload-disallowed-here' => 'আপুনি এই ফাইলটো  প্ৰতিস্থাপন কৰিব নোৱাৰে।',
 
 # File reversion
 'filerevert' => '$1 ক আগৰ অৱস্থালৈ ঘূৰাই আনক',
@@ -1941,9 +1961,9 @@ https://www.mediawiki.org/wiki/Manual:Image_Authorization চাওক।",
 
 'disambiguations' => 'দ্ব্যৰ্থতা-দূৰীকৰণ পৃষ্ঠাসমূহলৈ সংযোগ থকা পৃষ্ঠাসমূহ',
 'disambiguationspage' => 'সাঁচ:দ্ব্যৰ্থতা-দূৰীকৰণ',
-'disambiguations-text' => "তলৰ পৃষ্ঠাখনসমূহত '''দ্ব্যৰ্থতা দূৰীকৰণ পৃষ্ঠা'''ৰ লগত সংযোগ আছে 
-à¦\87য়à§\87 à¦\89পযà§\81à¦\95à§\8dত à¦ªà§\83ষà§\8dঠাৰ à¦²à¦\97ত à¦¸à¦\82যà§\8bà¦\97 à¦\95ৰিব à¦ªà¦¾à§°à§\87 
-[[MediaWiki:Disambiguationspage]]ৰ পৰা সংযোগ থকা কোনো সাঁচ ব্যৱহাৰ কৰিলে এখন পৃষ্ঠাক দ্ব্যৰ্থতা দূৰীকৰণ পৃষ্ঠা হিছাপে গণ্য কৰা হ’ব ।",
+'disambiguations-text' => "তলৰ পৃষ্ঠাখনসমূহত অন্ততঃ এটা হ'লেই '''দ্ব্যৰ্থতা দূৰীকৰণ পৃষ্ঠা'''ৰ সংযোগ আছে
+তাৰ à¦¸à¦²à¦¨à¦¿ à¦¸à§\87à¦\87বà§\8bৰত à¦\89পযà§\81à¦\95à§\8dত à¦ªà§\83ষà§\8dঠাৰ à¦²à¦\97ত à¦¸à¦\82যà§\8bà¦\97 à¦¥à¦¾à¦\95িব à¦ªà¦¾à§°à§\87
+[[MediaWiki:Disambiguationspage]]ৰ পৰা সংযোগ থকা কোনো সাঁচ ব্যৱহাৰ কৰিলে এখন পৃষ্ঠাক দ্ব্যৰ্থতা দূৰীকৰণ পৃষ্ঠা হিছাপে গণ্য কৰা হয়।",
 
 'doubleredirects' => 'দ্বি-পুনঃনিৰ্দেশিত',
 'doubleredirectstext' => 'আন পুনৰ্নিদেশনা পৃষ্ঠালৈ পুনৰ্নিৰ্দেশিত পৃষ্ঠাসমূহ এই তালিকাত দিয়া হৈছে ।
@@ -1969,6 +1989,7 @@ https://www.mediawiki.org/wiki/Manual:Image_Authorization চাওক।",
 # Miscellaneous special pages
 'nbytes' => '$1 {{PLURAL:$1|বাইট|বাইট}}',
 'ncategories' => '$1টা {{PLURAL:$1|শ্ৰেণী|শ্ৰেণী}}',
+'ninterwikis' => '$1 {{PLURAL:$1|ইণ্টাৰৱিকি|ইণ্টাৰৱিকিসমূহ}}',
 'nlinks' => '$1 {{PLURAL:$1|সংযোগ|সংযোগ}}',
 'nmembers' => '{{PLURAL:$1|সদস্য|$1 সদস্যবৃন্দ}}',
 'nrevisions' => '$1টা {{PLURAL:$1|সংশোধন|সংশোধন}}',
@@ -2292,6 +2313,7 @@ $UNWATCHURL
 'rollback_short' => 'পূৰ্ববৎ কৰক',
 'rollbacklink' => 'পূৰ্ববৎ কৰক',
 'rollbacklinkcount' => '$1 {{PLURAL:$1|সম্পাদনা|সম্পাদনাসমূহ}} পূৰ্বৱত কৰক',
+'rollbacklinkcount-morethan' => '$1 {{PLURAL:$1|সম্পাদনা|সম্পাদনাসমূহ}} পূৰ্বৱত কৰক',
 'rollbackfailed' => 'পূৰ্ববৎ ব্যৰ্থ',
 'cantrollback' => 'পূৰ্বৰ অৱস্থালৈ ঘূৰাই নিব নোৱাৰি;
 শেষৰ সম্পাদকজন এই পৃষ্ঠাৰ একমাত্ৰ লেখক ।',
@@ -2338,9 +2360,9 @@ $UNWATCHURL
 '''$1''' পৃষ্ঠাখনৰ সুৰক্ষা-স্তৰৰ গাঁথনি ইয়াত আছে:",
 'protect-cascadeon' => 'এই পৃষ্ঠাখন বৰ্তমান সুৰক্ষিত কাৰণ ই {{PLURAL:$1|খন পৃষ্ঠাৰ|খন পৃষ্ঠাৰ}} অন্তৰ্গত য’ত প্ৰপাতাকাৰ সুৰক্ষা সক্ৰিয় ।
 আপুনি এই পৃষ্ঠাৰ সুৰক্ষা স্তৰ সলাব পাৰে কিন্তু সি প্ৰপাতাকাৰ সুৰক্ষাত কোনো প্ৰভাৱ নেপেলায ।',
-'protect-default' => 'সà¦\95লà§\8b à¦¬à§\8dযবহাৰà¦\95াৰà§\80à¦\95 à¦\85নà§\81মতি à¦¦à¦¿à¦¯à¦¼à¦\95',
+'protect-default' => 'সà¦\95লà§\8b à¦¬à§\8dযৱহাৰà¦\95াৰà§\80ৰ à¦¬à¦¾à¦¬à§\87',
 'protect-fallback' => '"$1" অনুমতি লাগিব',
-'protect-level-autoconfirmed' => 'নতà§\81ন à¦¬à¦¾ à¦¨à¦¥à¦¿à¦­à§\81à¦\95à§\8dত à¦¨à§\8bহà§\8bৱা à¦¸à¦¦à¦¸à§\8dযà¦\95 à¦¬à¦¾à§°à¦£ à¦\95ৰà¦\95',
+'protect-level-autoconfirmed' => 'নতà§\81ন à¦¬à¦¾ à¦\85পà¦\9eà§\8dà¦\9cà§\80ভà§\81à¦\95à§\8dত à¦¸à¦¦à¦¸à§\8dযà¦\95 à¦\85ৱৰà§\8bধ',
 'protect-level-sysop' => 'কেৱল প্ৰশাসকবৃন্দৰ বাবে',
 'protect-summary-cascade' => 'প্ৰপাতাকাৰ/কেচ্‌কেডিং',
 'protect-expiring' => ' $1 (UTC) ত সময় শেষ হব',
@@ -2408,8 +2430,8 @@ $UNWATCHURL
 'undeletedrevisions' => '{{PLURAL:$1|১টা সংশোধন|$1টা সংশোধন}} পুনৰুদ্ধাৰ কৰা হৈছে',
 'undeletedrevisions-files' => '{{PLURAL:$1|১টা সংশোধন|$1 টা সংশোধন}} আৰু {{PLURAL:$2|১ খন নথি|$2 খন নথি}} পুনৰুদ্ধাৰ কৰা হ’ল',
 'undeletedfiles' => '{{PLURAL:$1|১খন নথি|$1 খন নথি}} পুনৰুদ্ধাৰ কৰা হ’ল',
-'cannotundelete' => 'à¦\85ৱলà§\81পà§\8dতি বিফল হৈছে;
-আন কোনোবাই আগতেই ইয়াক বিলোপ কৰিছে ।',
+'cannotundelete' => 'বিলà§\8bপ à¦¬à¦¾à¦¤à¦¿à¦²à¦\95ৰণ বিফল হৈছে;
+$1',
 'undeletedpage' => "'''$1ক পুনৰুদ্ধাৰ কৰা হৈছে'''
 অনুগ্ৰহ কৰি শেহতীয়া অৱলুপ্তি আৰু পুনৰুদ্ধাৰৰ বাবে [[Special:Log/delete|অৱলুপ্তি অভিলেখ]] চাওক ।",
 'undelete-header' => 'শেহতীয়াকৈ বিলোপ কৰা পৃষ্ঠাসমূহৰ বাবে [[Special:Log/delete|অৱলুপ্তি ল’গ]] চাওক ।',
@@ -2798,6 +2820,7 @@ $1ৰ অৱৰোধৰ কাৰণ: "$2"',
 'import-interwiki-templates' => 'সকলো সাঁচ অন্তৰ্ভুক্ত কৰক',
 'import-interwiki-submit' => 'আমদানি',
 'import-interwiki-namespace' => 'গন্তব্য নামস্থান:',
+'import-interwiki-rootpage' => 'গন্তব্য মূল পৃষ্ঠা (বৈকল্পিক):',
 'import-upload-filename' => 'নথিৰ নাম:',
 'import-comment' => 'মন্তব্য:',
 'importtext' => "অনুগ্ৰহ কৰি [[Special:Export|ৰপ্তানি সুবিধা]] ব্যৱহাৰ কৰি উৎস ৱিকিৰ পৰা ফাইলটো ৰপ্তানি কৰক।
@@ -2834,6 +2857,9 @@ $1ৰ অৱৰোধৰ কাৰণ: "$2"',
 'import-error-interwiki' => '"$1" পৃষ্ঠাখন আমদানি কৰা নহ\'ল কাৰণ ইয়াৰ নামটো বাহিৰা সংযোগৰ (আন্তঃৱিকি) বাবে সংৰক্ষিত।',
 'import-error-special' => '"$1" পৃষ্ঠাখন আমদানি কৰা নহ\'ল কাৰণ ই পৃষ্ঠা অনুমোদন নকৰা এটা বিশেষ নামস্থানৰ অন্তৰ্গত।',
 'import-error-invalid' => '"$1" পৃষ্ঠাখন আমদানি কৰা নহ\'ল কাৰণ ইয়াৰ নামটো অবৈধ।',
+'import-options-wrong' => 'ভুল {{PLURAL:$2|বিকল্প|বিকল্পসমূহ}}: <nowiki>$1</nowiki>',
+'import-rootpage-invalid' => 'মূল পৃষ্ঠাৰ শিৰোনামা অবৈধ।',
+'import-rootpage-nosubpage' => 'মূল পৃষ্ঠাৰ "$1" নামস্থানে উপপৃষ্ঠা অনুমোদন নকৰে।',
 
 # Import log
 'importlogpage' => 'আমদানিৰ অভিলেখ',
@@ -2949,11 +2975,42 @@ $1ৰ অৱৰোধৰ কাৰণ: "$2"',
 
 # Info page
 'pageinfo-title' => '"$1" ৰ তথ্য',
-'pageinfo-header-edits' => 'সম্পাদনাসমূহ',
+'pageinfo-not-current' => "কেৱল সাম্প্ৰতিক সংশোধনৰ বাবে তথ্য দৃশ্যমান হ'ব পাৰে।",
+'pageinfo-header-basic' => 'প্ৰাথমিক তথ্য',
+'pageinfo-header-edits' => 'ইতিহাস সম্পাদনা কৰক',
+'pageinfo-header-restrictions' => 'পৃষ্ঠা সুৰক্ষা',
+'pageinfo-header-properties' => 'পৃষ্ঠাৰ  বৈশিষ্টসমূহ',
+'pageinfo-display-title' => 'শিৰোনাম প্ৰদৰ্শন কৰক',
+'pageinfo-default-sort' => 'ডিফল্ট চৰ্ট কী',
+'pageinfo-length' => 'পৃষ্ঠাৰ দৈৰ্ঘ্য (বাইটত)',
+'pageinfo-article-id' => 'পৃষ্ঠা ID',
+'pageinfo-robot-policy' => 'সন্ধান ইঞ্জিনৰ স্থিতি',
+'pageinfo-robot-index' => 'ইনডেক্স উপযোগী',
+'pageinfo-robot-noindex' => 'ইনডেক্সৰ অনুপযোগী',
 'pageinfo-views' => 'দৰ্শনৰ সংখ্যা',
-'pageinfo-watchers' => 'নিৰীক্ষকৰ সংখ্যা',
-'pageinfo-edits' => 'সম্পাদনাৰ সংখ্যা',
-'pageinfo-authors' => 'মুখ্য লেখকৰ সংখ্যা',
+'pageinfo-watchers' => 'পৃষ্ঠা নিৰীক্ষকৰ সংখ্যা',
+'pageinfo-redirects-name' => 'পৃষ্ঠালৈ থকা পুনৰ্নিৰ্দেশ',
+'pageinfo-subpages-name' => 'এই পৃষ্ঠাৰ উপপৃষ্ঠাসমূহ',
+'pageinfo-subpages-value' => '$1 ($2 {{PLURAL:$2|পুনৰ্নিৰ্দেশ|পুনৰ্নিৰ্দেশসমূহ}}; $3 {{PLURAL:$3|অপুনৰ্নিৰ্দেশ নাই|অপুনৰ্নিৰ্দেশসমূহ}})',
+'pageinfo-firstuser' => 'পৃষ্ঠাখনৰ সৃষ্টিকৰ্তা',
+'pageinfo-firsttime' => 'পৃষ্ঠা সৃষ্টিৰ তাৰিখ',
+'pageinfo-lastuser' => 'অন্তিম সম্পাদক',
+'pageinfo-lasttime' => 'অন্তিম সম্পাদনাৰ তাৰিখ',
+'pageinfo-edits' => 'মুঠ সম্পাদনাৰ সংখ্যা',
+'pageinfo-authors' => 'মুঠ স্বতন্ত্ৰ লেখকৰ সংখ্যা',
+'pageinfo-recent-edits' => 'শেহতীয়া সম্পাদনাসমূহৰ সংখ্যা (যোৱা $1 দিনত)',
+'pageinfo-recent-authors' => 'স্বতন্ত্ৰ সম্পাদকৰ শেহতীয়া সংখ্যা',
+'pageinfo-magic-words' => 'যাদুকৰী {{PLURAL:$1|শব্দ|শব্দবোৰ}} ($1)',
+'pageinfo-hidden-categories' => 'অদৃশ্য {{PLURAL:$1|শ্ৰেণী|শ্ৰেণীসমূহ}} ($1)',
+'pageinfo-templates' => 'সংযুক্ত {{PLURAL:$1|সাঁচ|সাঁচসমূহ}} ($1)',
+'pageinfo-toolboxlink' => 'পৃষ্ঠাৰ বিষয়ে তথ্য',
+'pageinfo-redirectsto' => 'পুনৰ্নিৰ্দেশ কৰা হৈছে',
+'pageinfo-redirectsto-info' => 'তথ্য',
+'pageinfo-contentpage' => 'সমল পৃষ্ঠাৰূপে গণনা কৰা হৈছে',
+'pageinfo-contentpage-yes' => 'হয়',
+'pageinfo-protect-cascading' => 'সুৰক্ষাসমূহ ইয়াৰ পৰা প্ৰপাতাকাৰ হৈছে',
+'pageinfo-protect-cascading-yes' => 'হয়',
+'pageinfo-protect-cascading-from' => 'সুৰক্ষাসমূহ প্ৰপাতাকাৰ হৈছে',
 
 # Patrolling
 'markaspatrolleddiff' => 'নিৰীক্ষিত বুলি চিহ্নিত কৰক',
@@ -2997,6 +3054,7 @@ $1',
 'file-info-size-pages' => '$1 × $2 পিক্সেলসমূহ, নথিপত্ৰৰ আকাৰ: $3, MIME ধৰণ: $4, $5 {{PLURAL:$5|page|pages}}',
 'file-nohires' => 'ইয়াতকৈ ডাঙৰকৈ দেখুৱাব নোৱাৰি ।',
 'svg-long-desc' => 'SVG ফাইল, সাধাৰণতঃ $1 × $2 পিক্সেল, ফাইল মাত্ৰা: $3',
+'svg-long-desc-animated' => 'এনিমেটেড SVG ফাইল, সাধাৰণতে $1 × $2 পিক্সেল, ফাইলৰ আকাৰ: $3',
 'show-big-image' => "সম্পূৰ্ণ ৰিজ'লিউশ্যন",
 'show-big-image-preview' => 'এই খচৰাৰ আকাৰ: $1.',
 'show-big-image-other' => "আন {{PLURAL:$2|ৰিজ'লিউশ্যন|ৰিজ'লিউশ্যনসমূহ}}: $1।",
@@ -3006,6 +3064,8 @@ $1',
 'file-info-png-looped' => 'লুপকৃত',
 'file-info-png-repeat' => "$1 {{PLURAL:$1|বাৰ|বাৰ}} চলোৱা হ'ল",
 'file-info-png-frames' => '$1 {{PLURAL:$1|ফ্ৰেম|ফ্ৰেম}}',
+'file-no-thumb-animation' => "'''টোকা: কাৰিকৰী অসুবিধাবশতঃ এই ফাইলৰ থাম্বনেইল এনিমেটেড নহ'ব।'''",
+'file-no-thumb-animation-gif' => "'''টোকা: কাৰিকৰী অসুবিধাবশতঃ উচ্চ ৰিজ'লিউচনৰ GIF চিত্ৰ যেনে এইখন এনিমেটেড নহ'ব।'''",
 
 # Special:NewFiles
 'newimages' => 'নতুন ফাইলৰ বিথীকা',
@@ -3526,6 +3586,7 @@ $5
 # Scary transclusion
 'scarytranscludedisabled' => '[আন্তঃৱিকি আন্তঃভুক্তি নিষ্ক্ৰিয় কৰা আছে]',
 'scarytranscludefailed' => '[$1ৰ বাবে সাঁচ অনা অসফল হৈছে]',
+'scarytranscludefailed-httpstatus' => '[$1ৰ বাবে সাঁচ অনা অসফল হৈছে: HTTP $2]',
 'scarytranscludetoolong' => '[URL অত্যাধিক দীঘল]',
 
 # Delete conflict
@@ -3677,7 +3738,7 @@ $5
 * <span class="mw-specialpagecached">কেশ্ব কৰা বিশেষ পৃষ্ঠাসমূহ (অপ্ৰচলিতও হ\'ব পাৰে)।</span>',
 'specialpages-group-maintenance' => 'তত্বাৱধানৰ কাৰ্যবিৱৰণীসমূহ',
 'specialpages-group-other' => 'অন্যান্য বিশেষ পৃষ্ঠাসমূহ',
-'specialpages-group-login' => 'পà§\8dৰৱà§\87শ/সদসà§\8dযভà§\81à¦\95à§\8dতি',
+'specialpages-group-login' => 'পà§\8dৰৱà§\87শ/à¦\8fà¦\95াà¦\89ণà§\8dà¦\9f à¦¸à§\83ষà§\8dà¦\9fি à¦\95ৰà¦\95',
 'specialpages-group-changes' => 'সাম্প্ৰতিক সালসলনি আৰু অভিলেখসমূহ',
 'specialpages-group-media' => "মিডিয়া বিৱৰণী আৰু আপল'ডসমূহ",
 'specialpages-group-users' => 'সদস্যবৃন্দ আৰু অধিকাৰসমূহ',
@@ -3821,7 +3882,7 @@ $5
 'api-error-file-too-large' => 'আপুনি দাখিল কৰা ফাইলখন বৰ ডাঙৰ ।',
 'api-error-filename-tooshort' => 'ফাইলৰ নামটো অতি চুটি।',
 'api-error-filetype-banned' => 'এই ধৰণৰ ফাইল নিষিদ্ধ।',
-'api-error-filetype-banned-type' => '$1 {{PLURAL:$4|অনুমোদিত ফাইল প্ৰকাৰ নহয়|সমূহ অনুমোদিত ফাইল প্ৰকাৰ নহয়}} । {{PLURAL:$3|অনুমোদিত ফাইল প্ৰকাৰ হ’ল|অনুমোদিত ফাইল প্ৰকাৰসমূহ হ’ল}} $2 ।',
+'api-error-filetype-banned-type' => '$1 {{PLURAL:$4|অনুমোদিত ফাইল প্ৰকাৰ নহয়|সমূহ অনুমোদিত ফাইল প্ৰকাৰ নহয়}}। অনুমোদিত {{PLURAL:$3|ফাইল প্ৰকাৰ হ’ল|ফাইল প্ৰকাৰসমূহ হ’ল}} $2।',
 'api-error-filetype-missing' => 'ফাইল নামটোত এক্সটেন্‌ছন নাই।',
 'api-error-hookaborted' => 'আপুনি কৰিব বিচৰা সালসলনি এটা এক্সটেনচনৰ দ্বাৰা বাতিল কৰা হৈছে।',
 'api-error-http' => "আভ্যন্তৰীণ ত্ৰুটি: চাৰ্ভাৰৰ লগত সংযোগ স্থাপন নহ'ল।",
index 80c8530..687d5cc 100644 (file)
@@ -136,20 +136,20 @@ $messages = array(
 'thu' => 'Кс',
 'fri' => 'Йм',
 'sat' => 'Шб',
-'january' => 'ғинуар (һыуығай)',
-'february' => 'февраль (шаҡай)',
-'march' => 'март (буранай)',
-'april' => 'апрель (алағарай)',
+'january' => 'ғинуар',
+'february' => 'февраль',
+'march' => 'март',
+'april' => 'апрель',
 'may_long' => 'май (һабанай)',
-'june' => 'июнь (һөтай)',
-'july' => 'июль (майай)',
-'august' => 'август (урағай)',
-'september' => 'сентябрь (һарысай)',
-'october' => 'октябрь (ҡарасай)',
-'november' => 'ноябрь (ҡырпағай)',
-'december' => 'декабрь (аҡъюлай)',
-'january-gen' => 'ғинуар (һыуығай)',
-'february-gen' => 'февраль (шаҡай)',
+'june' => 'июнь',
+'july' => 'июль',
+'august' => 'август',
+'september' => 'сентябрь',
+'october' => 'октябрь',
+'november' => 'ноябрь',
+'december' => 'декабрь',
+'january-gen' => 'ғинуар',
+'february-gen' => 'февраль',
 'march-gen' => 'март',
 'april-gen' => 'апрель',
 'may-gen' => 'май',
@@ -158,8 +158,8 @@ $messages = array(
 'august-gen' => 'август',
 'september-gen' => 'сентябрь',
 'october-gen' => 'октябрь',
-'november-gen' => 'ноябрь (ҡырпағай)',
-'december-gen' => 'декабрь (аҡъюлай)',
+'november-gen' => 'ноябрь',
+'december-gen' => 'декабрь',
 'jan' => 'ғин',
 'feb' => 'фев',
 'mar' => 'мар',
index 04f2ba6..a924935 100644 (file)
@@ -254,7 +254,7 @@ $messages = array(
 'vector-action-protect' => 'Protektaran',
 'vector-action-undelete' => 'Bawion sa pagkapara',
 'vector-action-unprotect' => 'Ribayan an proteksyon',
-'vector-simplesearch-preference' => 'Paganahon an pinapusog na suhestiyon sa paghahanap (Yanong panhanap sana)',
+'vector-simplesearch-preference' => 'Paganahon an pinagyanong panukod sa paghahanap (Pansolong kublit sana)',
 'vector-view-create' => 'Magmukna',
 'vector-view-edit' => 'Liwatón',
 'vector-view-history' => 'Tanawon sa historiya',
@@ -476,8 +476,9 @@ Paki-otroha giraray sa nagkapirang minuto sana.',
 'protectedpagetext' => 'An pahinang ini pigsará tangarig pogolon an paghirá.',
 'viewsourcetext' => 'Pwede mong hilingón asin arógon an ginikanan kan pahinang ini:',
 'viewyourtext' => "Saimong mahihiling asin makokopya an gikanan kan '''saimong mga pinagriliwat''' sa pahinang ini:",
-'protectedinterface' => 'An pahinang ini nagtatao nin interface para sa software, asin sarado tangarig mapondo an pag-abuso.',
-'editinginterface' => "'''Warning:''' Ika nagliliwat kan pahina na ginagamit sa pagtao nin pantahaw-olay na teksto para sa software.
+'protectedinterface' => 'An pahinang ini nagtatao nin panlaog-olay para sa software, asin protektado tangaring malikayan an abuso.
+Sa pagdagdag or pagliwat nin mga dakit-taramon para sa bilog na wiki, gamita tabi an [//translatewiki.net/translatewiki.net], an MediaWiki sa proyektong lokalisasyon.',
+'editinginterface' => "'''Patanid:''' Ika nagliliwat kan pahina na ginagamit sa pagtao nin pantahaw-olay na teksto para sa software.
 An mga pagbabago kaining pahina makaka-apekto sa hitsura kan pantahaw-olay nin paragamit para sa iba man na paragamit.
 Para sa mga pagdadakit-taramon, pakikonsidera man tabi an paggagamit kan [//translatewiki.net/wiki/Main_Page?setlang=en translatewiki.net], an MediaWiking lokalisasyon kan proyekto.",
 'sqlhidden' => '(nakatagô an hapót nin SQL)',
@@ -761,7 +762,7 @@ Kun ika sarong dae pa bistadong paragamit asin mati mo na igwang irelebanteng sa
 Ika mapuwedeng [[Special:Search/{{PAGENAME}}|maghanap para sa titulo kan pahinang ini]] sa iba pang mga pahina,
 <span class="plainlinks">[{{fullurl:{{#Special:Log}}|page={{FULLPAGENAMEE}}}} maghanap sa magkasurundong mga talaan],
 o [{{fullurl:{{FULLPAGENAME}}|action=edit}} liwaton ining pahina]</span>.',
-'noarticletext-nopermission' => 'Mayo tabing teksto sa presente an pahinang ini.
+'noarticletext-nopermission' => 'Mayong sa presente nin teksto an pahinang ini.
 Ika mapuwedeng [[Special:Search/{{PAGENAME}}|hanapa para kaining titulo kan pahina]] sa iba pang mga pahina,
 o <span class="plainlinks">[{{fullurl:{{#Special:Log}}|page={{FULLPAGENAMEE}}}} maghanap sa magkasurundong mga talaan]</span>.',
 'missing-revision' => 'An rebisyon #$1 kan pahina pinagngaranan na "{{PAGENAME}}" bakong eksistido.
@@ -872,6 +873,15 @@ Ini minapahiwatig tabi na pinagpura na.',
 'edit-already-exists' => 'Dai maggibo an bàgong pahina.
 Igwa na kaini.',
 'defaultmessagetext' => 'Tugmadong mensahe sa teksto',
+'content-failed-to-parse' => 'Nagpalya sa paglunhay an $2 na laman para sa $1 na modelo: $3',
+'invalid-content-data' => 'Imbalidong datos nin laman',
+'content-not-allowed-here' => '"$1" na laman dae pinagtutugutan sa pahina [[$2]]',
+
+# Content models
+'content-model-wikitext' => 'wiki-teksto',
+'content-model-text' => 'yanong-teksto',
+'content-model-javascript' => 'Java-Kurit',
+'content-model-css' => 'CSS',
 
 # Parser/template warnings
 'expensive-parserfunction-warning' => "'''Patanid tabi:''' Ining pahina naglalaman nin grabe kadakulon na ekspensibong programang pambaranga sa punksyon nin mga pag-aapod.
@@ -1027,9 +1037,10 @@ Ika mayo tabing pangaputan kaini.',
 'revdelete-concurrent-change' => 'Napasalang pagsasangli kan item petsado $2, $1: An status nagpapahiling na pinagribayan kan ibang tawo habang ikan nagprubar na sanglian ini.
 Paki-tsek tabi sa mga talaan.',
 'revdelete-only-restricted' => 'Napasalang pagtatago kan item petsado $2, $1: Ika dae tabi makakapaglubog kan mga item na mahiling kan mga administrador na mayo kang piniling saro sa iba pang bisibilidad na mga pagpipilian.',
-'revdelete-reason-dropdown' => '*Pirmihang mga rason sa pagpura
+'revdelete-reason-dropdown' => '*Komon na mga rason sa pagpura
 **Paglapas kan Copyright
 **Bakong angay na personal na impormasyon
+**Bakong angay na pangaran nin paragamit
 **Potensiyal na libelosong impormasyon',
 'revdelete-otherreason' => 'Iba pa/kadagdagang rason:',
 'revdelete-reasonotherlist' => 'Ibang rason',
@@ -1225,7 +1236,7 @@ Uya an halaga sa random na pagbuswang na puwede mong magamit: $1',
 'timezoneregion-indian' => 'Indiyang Kadagatan',
 'timezoneregion-pacific' => 'Pasipikong Kadagatan',
 'allowemail' => "Togotan an mga ''e''-surat halî sa ibang mga parágamit",
-'prefs-searchoptions' => 'Pagpipilian sa Paghahanap',
+'prefs-searchoptions' => 'Hanapa',
 'prefs-namespaces' => 'Pangarang mga espasyo',
 'defaultns' => 'Kun laen maghanap sa laog kaining pangarang mga espasyo:',
 'default' => 'pwestong normal',
@@ -1268,6 +1279,7 @@ An saimong e-surat na adres dae ipagbuyagyag kunsoarin na an ibang paragamit mak
 'prefs-signature' => 'Pirma',
 'prefs-dateformat' => 'Pampetsang pormat',
 'prefs-timeoffset' => 'Pan-oras na tapal',
+'prefs-advancedediting' => 'Pinag-abanteng mga Pagpipilian',
 'prefs-advancedrc' => 'Pangenot na mga pagpipilian',
 'prefs-advancedrendering' => 'Abantidong mga pagpipilian',
 'prefs-advancedsearchoptions' => 'Abantidong mga pagpipilian',
@@ -1640,7 +1652,7 @@ Kun an problema yaon pa, pakikontak tabi nin sarong [[Special:ListUsers/sysop|ad
 'backend-fail-internal' => 'Sarong bakong bistadong kasalaan an nangyari sa panampad na sarayan "$1".',
 'backend-fail-contenttype' => 'Dae makapagdeterminar sa tipo kan laog kan sagunson na magsaray sa "$1".',
 'backend-fail-batchsize' => 'An panampad na sarayan pinagtao nin sarong batch kan sagunson sa $1 {{PLURAL:$1|operasyon|mga operasyon}}; an limit $2 {{PLURAL:$2|operasyon|mga operasyon}}.',
-'backend-fail-usable' => 'Dae makakapagsurat nin sagunson $1 sa dahilan na kulang an permiso o nawawara an mga direktoryo/kaaganan.',
+'backend-fail-usable' => 'Dae makakapagbasa o makakapagsurat nin sagunson sa "$1" nin hulita ta kulang an mga permiso o nawawara an mga direktoryo/kaaganan.',
 
 # File journal errors
 'filejournal-fail-dbconnect' => 'Dae makakasugpon sa datos-sarayan kan dyornal para sa panampad na sarayan "$1".',
@@ -1772,6 +1784,7 @@ Mapuwede gayod na ika magustong liwatong an deskripsyon na yaon sa [$2 sagunsong
 'uploadnewversion-linktext' => 'Magkarga nin bàgong bersyon kaining file',
 'shared-repo-from' => 'gikan sa $1',
 'shared-repo' => 'sarong pinagheras na repositoryo',
+'upload-disallowed-here' => 'Ika dae makakapagpatong sa pagsurat kaining sagunson.',
 
 # File reversion
 'filerevert' => 'Ibalik an $1',
@@ -1880,6 +1893,7 @@ Ini ngunyan minatukdo-liwat pasiring sa [[$2]].',
 # Miscellaneous special pages
 'nbytes' => '$1 {{PLURAL:$1|byte|mga byte}}',
 'ncategories' => '$1 {{PLURAL:$1|kategorya|mga kategorya}}',
+'ninterwikis' => '$1 {{PLURAL:$1|an interwiki|mga interwiki}}',
 'nlinks' => '$1 {{PLURAL:$1|takod|mga takod}}',
 'nmembers' => '$1 {{PLURAL:$1|myembro|mga myembro}}',
 'nrevisions' => '$1 {{PLURAL:$1|pagpakarhay|mga pagpakarhay}}',
@@ -1908,6 +1922,7 @@ Ini ngunyan minatukdo-liwat pasiring sa [[$2]].',
 'mostlinkedtemplates' => 'An mga pinakanatakodan na templato',
 'mostcategories' => 'Mga artikulong may pinaka dakol na kategorya',
 'mostimages' => 'An pinakapakisugpunan na mga sagunson',
+'mostinterwikis' => 'Mga pahina na igwang mas kadakol na interwiki',
 'mostrevisions' => 'Mga artikulong may pinakadakol na pagpakarháy',
 'prefixindex' => 'Gabos na mga pahina na igwa nin enotang panigmit',
 'prefixindex-namespace' => 'Gabos na mga pahina na igwa nin enotang panigmit ($1 espasyong ngaran)',
@@ -2055,6 +2070,8 @@ Puwedeng magkakaigwa nin [[{{MediaWiki:Listgrouprights-helppage}}|kadagdagang im
 asin may marhay na ''e''-surat sa saimong [[Special:Preferences|Mga kabôtan]]
 para makapadara nin ''e''-surat sa ibang parágamit.",
 'emailuser' => 'E-koreohan ining paragamit',
+'emailuser-title-target' => 'E-surat kaining {{GENDER:$1|paragamit}}',
+'emailuser-title-notarget' => 'E-surat na paragamit',
 'emailpage' => 'E-suratan an parágamit',
 'emailpagetext' => 'Ika makakagamit kan porma na yaon sa ibaba tanganing magpadara nin e-surat na mensahe sa paragamit na ini.
 An e-surat na adres na saimong ilalaog sa [[Special:Preferences|saimong paragamit kagustuhan]] magluluwas bilang iyo an "Gikan ki" adres kan e-surat, kaya an sinuratan makakapagsimbag direkta mismo saimo.',
@@ -2316,7 +2333,8 @@ binalik an na pagribay o hinalî sa archibo.',
 'undeletedrevisions' => '{{PLURAL:$1|1 rebisyon|$1 mga rebisyon}} ipinagbalik',
 'undeletedrevisions-files' => '{{PLURAL:$1|1 rebisyon|$1 mga rebisyon}} asin {{PLURAL:$2|1 sagunson|$2 mga sagunson}} ipinagbalik',
 'undeletedfiles' => '{{PLURAL:$1|1 sagunson|$1 mga sagunson}} ipinagbalik',
-'cannotundelete' => 'Naprakaso an pagbalik kan pigparâ; pwede ser an binawi an pagparâ kan páhina kan ibang parágamit.',
+'cannotundelete' => 'An dae pagpura nagpalya:
+$1',
 'undeletedpage' => "'''binalik na an $1 '''
 
 Ikonsultar an [[Special:Log/delete|historial nin pagparâ]] para mahiling an lista nin mga kaaaging pagparâ asin pagbalik.",
@@ -2480,17 +2498,28 @@ Hilngon an [[Special:BlockList|listahan kan binarahan]] tanganing repasohon an m
 'blocklogpage' => 'Usip nin pagbagat',
 'blocklog-showlog' => 'Ining paragamit dati nang pinagbarahan.
 An talaan nin pagbara nakahaya sa ibaba bilang reperensiya:',
+'blocklog-showsuppresslog' => 'Ining paragamit pinagkubkob asin dati nang ipinagtago.
+An talaan nin pagpaunlok ipinagtao sa ibaba para hilingan.',
 'blocklogentry' => 'binagat na [[$1]] na may oras nin pagpaso na $2 $3',
-'blocklogtext' => 'Ini an historial kan pagbagat asin pagbawi sa pagbagat nin mga paragamit. An mga enseguidang binagat na direccion nin
-IP dai nakalista digdi. Hilingon an [[Special:BlockList|IP lista nin mga binagat]] para sa lista nin mga nakaandar na mga pagpangalad buda mga pagbagat.',
+'reblock-logentry' => 'pinagliwat an mga panuytoy nin pagkubkob para sa [[$1]] na igwang oras nin pagpaso kan $2 $3',
+'blocklogtext' => 'Ini sarong talaan kan mga aksyon nin paragamit sa pagkukubkob asin dae pagkukubkob.
+Awtomatikong pagkubkob kan IP address dae pinaglilista.
+Hilngon an [[Special:Blocklist|block list]] para sa listahan kan presenteng operasyonal na pagpangalad asin pagkukubkob.',
 'unblocklogentry' => 'binawi an pagbagat $1',
 'block-log-flags-anononly' => 'Mga paragamit na anónimo sana',
 'block-log-flags-nocreate' => "pigpopondohán an paggibo nin ''account'",
 'block-log-flags-noautoblock' => 'pigpopondo an enseguidang pagbagat',
 'block-log-flags-noemail' => 'binagát an e-surat',
+'block-log-flags-angry-autoblock' => 'pinakusog na awto-kubkob pinaandar',
+'block-log-flags-hiddenname' => 'pangaran nin paragamit itinago',
 'range_block_disabled' => 'Pigpopondo an abilidad kan sysop na maggibo nin bagat na hilera.',
 'ipb_expiry_invalid' => 'Dai pwede ini bilang oras kan pagpasó.',
-'ipb_already_blocked' => 'Dating binagat na si "$1"',
+'ipb_expiry_temp' => 'Itinagong pangaran nin paragamit na nagkukubkob dapat na magin permanente.',
+'ipb_hide_invalid' => 'Dae nakayanan na untukon ining panindog; ini gayod nagkaigwa nin kadakulon na mga pagliliwat.',
+'ipb_already_blocked' => 'An "$1" pinagkubkob na',
+'ipb-needreblock' => 'An $1 pinagkubkob na. Gusto mong liwaton an mga panuytoy?',
+'ipb-otherblocks-header' => 'Ibang {{PLURAL:$1|kubkob|mga kubkob',
+'unblock-hideuser' => 'Ika dae makakakubkog kaining paragamit, siring na an saindang paragamit na ngaran itinatago.',
 'ipb_cant_unblock' => 'Error: Dai nahanap an ID nin binagat na $1. Puede ser na dati nang binawi an pagbagat kaini.',
 'ip_range_invalid' => 'Dai pwede ining serye nin IP.',
 'proxyblocker' => 'Parabagát na karibay',
index 75f0e68..0aab6e4 100644 (file)
@@ -941,7 +941,7 @@ $2
 'note' => "'''Заўвага: '''",
 'previewnote' => "'''Гэта толькі папярэдні прагляд.'''
 Вашыя зьмены яшчэ не былі захаваныя!",
-'continue-editing' => 'Працягнуць рэдагаваньне',
+'continue-editing' => 'Перайсьці да рэдагаваньня',
 'previewconflict' => 'Гэта папярэдні прагляд тэксту зь верхняга вакна рэдагаваньня, так ён будзе выглядаць, калі Вы вырашыце яго захаваць.',
 'session_fail_preview' => "'''Не атрымалася захаваць Вашую праўку праз тое, што былі страчаныя зьвесткі пра сэсію.
 Калі ласка, паспрабуйце яшчэ раз. Калі памылка ня зьнікне, паспрабуйце [[Special:UserLogout|выйсьці з сыстэмы]] і ўвайсьці ізноў.'''",
index 390c926..d0dfafc 100644 (file)
@@ -1844,7 +1844,7 @@ Marteze a-walc'h e fell deoc'h kemmañ an deskrivadur anezhi war ar [$2 bajenn d
 'uploadnewversion-linktext' => 'Kargañ ur stumm nevez eus ar restr-mañ',
 'shared-repo-from' => 'eus $1',
 'shared-repo' => 'ur sanailh rannet',
-'upload-disallowed-here' => "Siwazh, ne c'hallit ket erlec'hiañ ar skeudenn-mañ",
+'upload-disallowed-here' => "Ne c'hallit ket erlec'hiañ ar restr-mañ",
 
 # File reversion
 'filerevert' => 'Disteuler $1',
@@ -2944,6 +2944,7 @@ Sur a-walc'h abalamour d'ul liamm enni a gas d'ul lec'hienn ziavaez berzet.",
 
 # Info page
 'pageinfo-title' => 'Titouroù evit "$1"',
+'pageinfo-not-current' => "Evit an adwel bremañ e c'hall bezañ diskwelet an titouroù hepken.",
 'pageinfo-header-basic' => 'Titouroù diazez',
 'pageinfo-header-edits' => 'Kemmoù',
 'pageinfo-header-restrictions' => 'Gwarez ar bajenn',
index 967cf66..98010ff 100644 (file)
@@ -853,11 +853,11 @@ Detalls es poden trobar en el [{{fullurl: {{# especial: registre}} / delete|page
 'userpage-userdoesnotexist-view' => 'El compte d\'usuari "$1" no està registrat.',
 'blocked-notice-logextract' => "En aquests moments aquest compte d'usuari es troba blocat.
 Per més detalls, la darrera entrada del registre es mostra a continuació:",
-'clearyourcache' => "'''Nota:''' després de guardar possiblement necessites refrescar el teu cache per poder veure els canvis.
-* '''Firefox / Safari:''' pressiona ''Shift'' mentre cliques el botó ''Actualitzar'', o pressiona ''Ctrl+F5'' o ''Ctrl+R'' (''⌘+R'' a Mac)
-* '''Google Chrome:''' pressiona ''Ctrl+Shift+R'' (''⌘+Shift+R'' a Mac)
-* '''Internet Explorer:''' pressiona la tecla ''Ctrl'' mentre cliques a ''Actualitzar'' o pressiona ''Ctrl+F5''
-* '''Opera:''' buida la memòria cau (cache) ''Eines → Preferències''",
+'clearyourcache' => "'''Nota:''' Després de desar, possiblement necessiteu refrescar la memòria cau del vostre navegador per a veure'n els canvis.
+* '''Firefox / Safari:''' Premeu ''Shift'' mentre cliqueu el botó ''Actualitzar'', o pressioneu ''Ctrl+F5'' o ''Ctrl+R'' (''⌘+R'' a Mac)
+* '''Google Chrome:''' Premeu ''Ctrl+Shift+R'' (''⌘+Shift+R'' a Mac)
+* '''Internet Explorer:''' Premeu la tecla ''Ctrl'' mentre cliqueu a ''Actualitzar'' o pressioneu ''Ctrl+F5''
+* '''Opera:''' Netegeu la memòria cau ''Eines → Preferències''",
 'usercssyoucanpreview' => "'''Consell:''' Utilitzeu el botó \"{{int:showpreview}}\" per provar el vostre nou CSS abans de desar-lo.",
 'userjsyoucanpreview' => "'''Consell:''' Utilitzeu el botó \"{{int:showpreview}}\" per provar el vostre nou JavaScript abans de desar-lo.",
 'usercsspreview' => "'''Recordeu que esteu previsualitzant el vostre CSS d'usuari.'''
index eebf07c..3f9ba0a 100644 (file)
@@ -412,7 +412,7 @@ $1',
 'youhavenewmessages' => '$1ت ھەیە ($2).',
 'newmessageslink' => 'پەیامی نوێ',
 'newmessagesdifflink' => 'دوایین گۆڕانکاری',
-'youhavenewmessagesfromusers' => '$1ت لە {{PLURAL:$3|بەکارھێنەرێکی تر| $3 بەکارھێنەر}} ھەیە ( $2 ).',
+'youhavenewmessagesfromusers' => '$1ت لە {{PLURAL:$3|بەکارھێنەرێکی تر| $3 بەکارھێنەر}} ھەیە ($2).',
 'youhavenewmessagesmanyusers' => '$1ت  لە ژمارەیەک بەکارھێنەر ھەیە ( $2 ).',
 'newmessageslinkplural' => '{{PLURAL:$1|پەیامێکی نوێ|پەیامی نوێ}}',
 'newmessagesdifflinkplural' => 'دوایین {{PLURAL:$1|گۆڕانکاری|گۆڕانکارییەکان}}',
@@ -789,7 +789,7 @@ $2
 'noarticletext' => 'ھەنووکە ھیچ دەقێک لەم پەڕەدا نییە.
 دەتوانی بۆ ئەم ناوە لە [[Special:Search/{{PAGENAME}}|پەڕەکانی تردا بگەڕێی]]، <span class="plainlinks">[{{fullurl:{{#Special:Log}}|page={{FULLPAGENAMEE}}}} لە لۆگەکاندا بگەڕێی]، یان [{{fullurl:{{FULLPAGENAME}}|action=edit}} ئەم پەڕە دەستکاری بکەیت]</span>.',
 'noarticletext-nopermission' => 'ھەنووکە ھیچ دەقێک لەم پەڕەیەدا نییە.
-دەتوانی بۆ ئەم ناوە لە [[Special:Search/{{PAGENAME}}|پەڕەکانی تردا بگەڕێی]] یان <span class="plainlinks">[{{fullurl:{{#Special:Log}}|page={{FULLPAGENAMEE}}}} لە لۆگە پەیوەندیدارەکاندا بگەڕێی]</span>.',
+دەتوانی لە پەڕەکانی تردا [[Special:Search/{{PAGENAME}}|بۆ ئەم ناوە بگەڕێی]]، یان <span class="plainlinks">[{{fullurl:{{#Special:Log}}|page={{FULLPAGENAMEE}}}} لە لۆگە پەیوەندیدارەکاندا بگەڕێی]</span>، بەڵام ناتوانی ئەم پەڕەیە دروست بکەی.',
 'userpage-userdoesnotexist' => 'هەژماری بەکارهێنەری "<nowiki>$1</nowiki>" تۆمار نەکراوە.<br />
 گەر دەتەوێ ئەم لاپەڕە درووست‌کەی یان دەستکاری بکەی تکایە تاقی‌بکەوە .',
 'userpage-userdoesnotexist-view' => 'ھەژماری بەکارھێنەریی «$1» تۆمار نەکراوە.',
@@ -1228,7 +1228,7 @@ $1",
 'timezoneregion-indian' => 'ئوقیانووسی ھیند',
 'timezoneregion-pacific' => 'ئوقیانووسی پاسیفیک',
 'allowemail' => 'ڕێگە بدە بە بەکارھێنەرانی تر کە ئیمەیلم بۆ بنێرن',
-'prefs-searchoptions' => 'Ú¾Û\95ڵبÚ\98اردÛ\95کاÙ\86Û\8c Ú¯Û\95Ú\95اÙ\86',
+'prefs-searchoptions' => 'گەڕان',
 'prefs-namespaces' => 'بۆشایی‌ناوەکان',
 'defaultns' => 'ئەگەرنا لەم بۆشایی‌ناوانەدا بگەڕێ:',
 'default' => 'بنچینەیی',
@@ -2090,7 +2090,7 @@ $UNWATCHURL
 'rollback' => 'گەڕاندنەوەی دەستکارییەکان',
 'rollback_short' => 'گەڕاندنەوە',
 'rollbacklink' => 'گەڕاندنەوە',
-'rollbacklinkcount' => 'گەڕاندنەوەی $1 دەستکاری',
+'rollbacklinkcount' => 'گەڕاندنەوەی $1 {{PLURAL:$1|دەستکاری}}',
 'rollbackfailed' => 'گەڕاندنەوە سەرکەوتوو نەبوو',
 'cantrollback' => 'دەستکاریەکان ناگەڕێندرێتەوە؛
 دوایین هاوبەش تەنها ڕێکخەری ئەم لاپەڕەیە.',
@@ -2682,16 +2682,27 @@ $1',
 'pageinfo-header-restrictions' => 'پاراستنی پەڕە',
 'pageinfo-header-properties' => 'تایبەتمەندییەکانی پەڕە',
 'pageinfo-display-title' => 'ناونیشان نیشانبدە',
+'pageinfo-default-sort' => 'کلیلی ڕیزکردنی بەرگریمانە',
+'pageinfo-length' => 'قەبارەی پەڕە (بایت)',
 'pageinfo-article-id' => 'زنجیرەی پەڕە',
+'pageinfo-robot-policy' => 'چۆنێتیی مۆتۆڕی گەڕان',
+'pageinfo-robot-index' => 'شیاو بۆ پێرستکردن',
+'pageinfo-robot-noindex' => 'نەشیاو بۆ پێرستکردن',
 'pageinfo-views' => 'ژمارەی بینینەکان',
 'pageinfo-watchers' => 'ژمارەی چاودێرانی پەڕە',
 'pageinfo-redirects-name' => 'ڕەوانەکردنەکان بۆ ئەم پەڕەیە',
 'pageinfo-subpages-name' => 'ژێرپەڕەکانی ئەم پەڕەیە',
+'pageinfo-subpages-value' => '$1 ($2 {{PLURAL:$2|ڕەوانەکەر}}; $3 {{PLURAL:$3|ڕەوانەنەکەر}})',
 'pageinfo-firstuser' => 'دروستکەری پەڕە',
 'pageinfo-firsttime' => 'ڕێکەوتی دروستکردنی پەڕە',
 'pageinfo-lastuser' => 'دوایین دەستکاریکەر',
 'pageinfo-lasttime' => 'ڕێکەوتی دوایین دەستکاری',
 'pageinfo-edits' => 'ژمارەی سەرجەمی دەستکارییەکان',
+'pageinfo-authors' => 'ژمارەی نووسەرە جیاوازەکان',
+'pageinfo-recent-edits' => 'ژمارەی دوایین دەستکارییەکان (لە $1ی ڕابردوودا)',
+'pageinfo-recent-authors' => 'ژمارەی دوایین نووسەرە جیاوازەکان',
+'pageinfo-templates' => 'داڕێژە{{PLURAL:$1|ی بەکارگیراو| بەکارگیراوەکان}} ($1)',
+'pageinfo-toolboxlink' => 'زانیاریی پەڕە',
 
 # Skin names
 'skinname-standard' => 'کلاسیک',
index 8ed6e83..5c9e666 100644 (file)
@@ -1041,7 +1041,7 @@ Zde je pro přehled zobrazen nejnovější záznam z knihy zablokování:',
 'note' => "'''Poznámka:'''&nbsp;",
 'previewnote' => "'''Pamatujte, že toto je pouze náhled.'''
 Změny zatím nebyly uloženy!",
-'continue-editing' => 'Pokračovat v editaci',
+'continue-editing' => 'Přejít k editačnímu poli',
 'previewconflict' => 'Tento náhled ukazuje text tak, jak bude vypadat po uložení stránky.',
 'session_fail_preview' => "'''Váš požadavek se nepodařilo zpracovat kvůli ztrátě dat z relace.
 Zkuste to prosím znovu.
@@ -3915,6 +3915,8 @@ MediaWiki je distribuována v naději, že bude užitečná, avšak BEZ JAKÉKOL
 'version-entrypoints' => 'URL vstupních bodů',
 'version-entrypoints-header-entrypoint' => 'Vstupní bod',
 'version-entrypoints-header-url' => 'URL',
+'version-entrypoints-articlepath' => '[https://www.mediawiki.org/wiki/Manual:$wgArticlePath Cesta k článkům]',
+'version-entrypoints-scriptpath' => '[https://www.mediawiki.org/wiki/Manual:$wgScriptPath Cesta ke skriptům]',
 
 # Special:FilePath
 'filepath' => 'Cesta k souboru',
index c2782be..62de136 100644 (file)
@@ -1086,7 +1086,7 @@ Zur Information folgt ein aktueller Auszug aus dem Benutzersperr-Logbuch:',
 'note' => "'''Hinweis:'''",
 'previewnote' => "'''Dies ist nur eine Vorschau.'''
 Die Seite wurde noch nicht gespeichert!",
-'continue-editing' => 'Weiter bearbeiten',
+'continue-editing' => 'Zum Bearbeitungsfeld gehen',
 'previewconflict' => 'Diese Vorschau gibt den Inhalt des oberen Textfeldes wieder. So wird die Seite aussehen, wenn du jetzt speicherst.',
 'session_fail_preview' => "'''Deine Bearbeitung konnte nicht gespeichert werden, da Sitzungsdaten verloren gegangen sind.
 Bitte versuche es erneut, indem du unter der folgenden Textvorschau nochmals auf „Seite speichern“ klickst.
@@ -3118,7 +3118,7 @@ Diese auf dem lokalen Rechner speichern und danach hier hochladen.',
 'standard.css' => '/* Das folgende CSS wird für Benutzer der Klassik-Benutzeroberfläche geladen. Für allgemeingültige Benutzeroberflächen-Anpassungen bitte [[MediaWiki:Common.css]] bearbeiten. */',
 'nostalgia.css' => '/* Das folgende CSS wird für Benutzer der Nostalgie-Benutzeroberfläche geladen. Für allgemeingültige Benutzeroberflächen-Anpassungen bitte [[MediaWiki:Common.css]] bearbeiten. */',
 'cologneblue.css' => '/* Das folgende CSS wird für Benutzer der Kölnisch-Blau-Benutzeroberfläche geladen. Für allgemeingültige Benutzeroberflächen-Anpassungen bitte [[MediaWiki:Common.css]] bearbeiten. */',
-'monobook.css' => '/* Das folgende CSS wird für Benutzer der Monobook-Benutzeroberfläche geladen. Für allgemeingültige Benutzeroberflächen-Anpassungen bitte [[MediaWiki:Common.css]] bearbeiten. */',
+'monobook.css' => '/* Das folgende CSS wird für Benutzer der MonoBook-Benutzeroberfläche geladen */',
 'myskin.css' => '/* Das folgende CSS wird für Benutzer der MySkin-Benutzeroberfläche geladen. Für allgemeingültige Benutzeroberflächen-Anpassungen bitte [[MediaWiki:Common.css]] bearbeiten. */',
 'chick.css' => '/* Das folgende CSS wird für Benutzer der Küken-Benutzeroberfläche geladen. Für allgemeingültige Benutzeroberflächen-Anpassungen bitte [[MediaWiki:Common.css]] bearbeiten. */',
 'simple.css' => '/* Das folgende CSS wird für Benutzer der Einfach-Benutzeroberfläche geladen. Für allgemeingültige Benutzeroberflächen-Anpassungen bitte [[MediaWiki:Common.css]] bearbeiten. */',
@@ -3137,7 +3137,7 @@ Diese auf dem lokalen Rechner speichern und danach hier hochladen.',
 'standard.js' => '/* Das folgende JavaScript wird für Benutzer der Klassik-Benutzeroberfläche geladen. Allgemeingültiges JavaScript bitte in [[MediaWiki:Common.js]] eintragen. */',
 'nostalgia.js' => '/* Das folgende JavaScript wird für Benutzer der Nostalgie-Benutzeroberfläche geladen. Allgemeingültiges JavaScript bitte in [[MediaWiki:Common.js]] eintragen. */',
 'cologneblue.js' => '/* Das folgende JavaScript wird für Benutzer der Kölnisch-Blau-Benutzeroberfläche geladen. Allgemeingültiges JavaScript bitte in [[MediaWiki:Common.js]] eintragen. */',
-'monobook.js' => '/* Das folgende JavaScript wird für Benutzer der Monobook-Benutzeroberfläche geladen. Allgemeingültiges JavaScript bitte in [[MediaWiki:Common.js]] eintragen. */',
+'monobook.js' => '/* Das folgende JavaScript wird für Benutzer der MonoBook-Benutzeroberfläche geladen */',
 'myskin.js' => '/* Das folgende JavaScript wird für Benutzer der MySkin-Benutzeroberfläche geladen. Allgemeingültiges JavaScript bitte in [[MediaWiki:Common.js]] eintragen. */',
 'chick.js' => '/* Das folgende JavaScript wird für Benutzer der Küken-Benutzeroberfläche geladen. Allgemeingültiges JavaScript bitte in [[MediaWiki:Common.js]] eintragen. */',
 'simple.js' => '/* Das folgende JavaScript wird für Benutzer der Einfach-Benutzeroberfläche geladen. Allgemeingültiges JavaScript bitte in [[MediaWiki:Common.js]] eintragen. */',
@@ -3204,7 +3204,7 @@ Das liegt wahrscheinlich an einem Link auf eine externe Seite.',
 'pageinfo-magic-words' => '{{PLURAL:$1|Magisches Wort|Magische Wörter}} ($1)',
 'pageinfo-hidden-categories' => 'Versteckte {{PLURAL:$1|Kategorie|Kategorien}} ($1)',
 'pageinfo-templates' => 'Eingebundene {{PLURAL:$1|Vorlage|Vorlagen}} ($1)',
-'pageinfo-toolboxlink' => 'Informationen zur Seite',
+'pageinfo-toolboxlink' => 'Seiteninformationen',
 'pageinfo-redirectsto' => 'Weiterleitungen nach',
 'pageinfo-redirectsto-info' => 'Information',
 'pageinfo-contentpage' => 'Gezählt als eine Inhaltsseite',
index 90b40ea..3e93338 100644 (file)
@@ -342,7 +342,7 @@ $messages = array(
 'tog-uselivepreview' => 'Verqayto cınde bıxebetne (JavaScript lazımo) (hewna cerrebnayış dero)',
 'tog-forceeditsummary' => 'Mı ke xulasa kerde cı vira, hay be mı ser de',
 'tog-watchlisthideown' => 'Vurnayışanê mı lista mına seyrkerdışi de bınımne',
-'tog-watchlisthidebots' => 'Vurnayışanê bota liste da seyrkerdışi de bınımne',
+'tog-watchlisthidebots' => 'Lista mına seyrkerdışi ra vurnayışanê botan bınımne',
 'tog-watchlisthideminor' => 'Vurnayışanê qıckekan lista mına seyrkerdışi de bınımne',
 'tog-watchlisthideliu' => 'Lista seyrkerdışi ra vurnayışanê karberanê cıkewteyan bınımne',
 'tog-watchlisthideanons' => 'Lista seyrkerdışi ra vurnayışanê karberanê anoniman bınımne',
@@ -445,7 +445,7 @@ $messages = array(
 'cancel' => 'Bıtexelne',
 'moredotdotdot' => 'Vêşi...',
 'mypage' => 'Pela mı',
-'mytalk' => 'Werênayışê mı',
+'mytalk' => '[Werênayışê mı]',
 'anontalk' => 'Pela werênayışê nê IPy',
 'navigation' => 'Geyrayış',
 'and' => '&#32;u',
@@ -473,7 +473,7 @@ $messages = array(
 'vector-view-history' => 'Vurnayışê verêni',
 'vector-view-view' => 'Bıwanê',
 'vector-view-viewsource' => 'Çımey bıvêne',
-'actions' => 'Kerdeni',
+'actions' => 'Kerdışi',
 'namespaces' => 'Cayê namey',
 'variants' => 'Varyanti',
 
@@ -611,7 +611,7 @@ $1',
 'sort-ascending' => 'Ratnayışê Zeydnayışi',
 
 # Short words for each namespace, by default used in the namespace tab in monobook
-'nstab-main' => 'Per',
+'nstab-main' => 'Pele',
 'nstab-user' => 'Pera Karberi',
 'nstab-media' => 'Pela Medya',
 'nstab-special' => 'Pela xısusiye',
@@ -999,7 +999,7 @@ Dosyanê be namey .css u .js'i de herfa werdiye bıgurêne, mesela herında {{ns
 'note' => "'''Not:'''",
 'previewnote' => "'''Xo vira mekerê ke ena yew verqayta.'''
 Vurnayışê şıma hona qeyd nêbiyo!",
-'continue-editing' => 'Vurnayışi rê dewam ke',
+'continue-editing' => 'Şo herunda vurnayışi',
 'previewconflict' => 'No seyrkerdışê verqaydi serê qutiyê nuşte tezim kerdış de yo, eke şıma qayile vurnayişê maddeyi seyino bıvini, no mocneno şıma.',
 'session_fail_preview' => 'Ma ef kere. Vindibiyayişê tayê datay ra a kerdışê hesabê şıma de ma vurnayişê şıma qayd nêkerd. Newe ra tesel (cereb) bıkere. Eke no qayde zi nêbo, [[Special:UserLogout|hesabê xo bıqefelne]] u newera a kere.',
 'session_fail_preview_html' => "'''Ma meluli! Sebayê vindbiyayişê datasistemi ma vurnayişê şıma nêeşkeni qaydker.'''
@@ -1320,9 +1320,9 @@ Detayê besternayışi [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}
 'searchhelp-url' => 'Help:Tedeestey',
 'searchmenu-prefix' => '[[Special:PrefixIndex/$1|pê eno prefix ser pelan de bigêre]]',
 'searchprofile-articles' => 'Pelê tedeestey',
-'searchprofile-project' => 'Pelê yardım u projey',
+'searchprofile-project' => 'Pelê yardım u procey',
 'searchprofile-images' => 'Multimedya',
-'searchprofile-everything' => 'Hemnan',
+'searchprofile-everything' => 'Her çi',
 'searchprofile-advanced' => 'Raverşiyaye',
 'searchprofile-articles-tooltip' => '$1 de bigêre',
 'searchprofile-project-tooltip' => '$1 de bigêre',
@@ -1348,7 +1348,7 @@ Detayê besternayışi [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}
 'showingresultsheader' => "{{PLURAL:$5|Neticeyê '''$1''' of '''$3'''|Neticeyanê '''$1 - $2''' hetê '''$3'''}} qe '''$4'''",
 'nonefound' => "'''Teme''': Teyna tay namecayan cıgeyro beno.
 Pe verbendi ''all:'', vaceyê xo bıvurni ki contenti hemi cıgeyro (pelanê mınaqeşe, templatenan, ucb.) ya zi cıgeyro ser namecay ki tı wazeni.",
-'search-nonefound' => 'Zey cıgeyrayış de şıma netice nêvineya',
+'search-nonefound' => 'Zey perskerden da şıma netice nêvineya.',
 'powersearch' => 'Cıgeyrayışo hera',
 'powersearch-legend' => 'Cıgeyrayışo hera',
 'powersearch-ns' => 'Cayanê nameyan de cıgeyrayış:',
@@ -1397,7 +1397,7 @@ Pe verbendi ''all:'', vaceyê xo bıvurni ki contenti hemi cıgeyro (pelanê mı
 'prefs-setemail' => 'E-posta adresiyê xo saz kerê',
 'prefs-email' => 'Tercihê e-maili',
 'prefs-rendering' => 'Asayış',
-'saveprefs' => 'Star ke',
+'saveprefs' => 'Qeyd ke',
 'resetprefs' => 'Vurnayışê ke qeyd nêbiy, pak ke',
 'restoreprefs' => 'Sazanê hesıbyaya pêron newe dere barke',
 'prefs-editing' => 'Cay pela nustısi',
@@ -1423,13 +1423,13 @@ Etıya şıma rê yew kılito raştameo ke şıma şenê bıgurenê/bıxebetnê:
 'timezoneoffset' => 'Offset¹:',
 'servertime' => 'Wextê serveri:',
 'guesstimezone' => 'Browser ra pırr ke',
-'timezoneregion-africa' => 'Afriqa',
+'timezoneregion-africa' => 'Afrika',
 'timezoneregion-america' => 'Amerika',
 'timezoneregion-antarctica' => 'Antarktika',
 'timezoneregion-arctic' => 'Arktik',
 'timezoneregion-asia' => 'Asya',
 'timezoneregion-atlantic' => 'Okyanuso Atlantik',
-'timezoneregion-australia' => 'Evistiralya',
+'timezoneregion-australia' => 'Awıstralya',
 'timezoneregion-europe' => 'Ewropa',
 'timezoneregion-indian' => 'Okyanuso Hind',
 'timezoneregion-pacific' => 'Okyanuso Pasifik',
@@ -1437,7 +1437,7 @@ Etıya şıma rê yew kılito raştameo ke şıma şenê bıgurenê/bıxebetnê:
 'prefs-searchoptions' => 'Cı geyre',
 'prefs-namespaces' => 'Caê namey',
 'defaultns' => 'Eke heni, enê cayanê namey de cı geyre (sae ke):',
-'default' => 'hesıbyaye',
+'default' => 'qısur',
 'prefs-files' => 'Dosyey',
 'prefs-custom-css' => 'CSSê xasi',
 'prefs-custom-js' => 'JSê xasi',
@@ -1463,7 +1463,7 @@ Na game tepeya nêerziyena.',
 Etiketê HTMLî kontrol bike.',
 'badsiglength' => 'İmzayê şıma zaf dergo.
 $1 gani bınê no {{PLURAL:$1|karakter|karakter}} de bıbo.',
-'yourgender' => 'Neri makey:',
+'yourgender' => 'Cınsiyet:',
 'gender-unknown' => 'Cınsiyet nêvato',
 'gender-male' => 'cıwamêrd',
 'gender-female' => 'Cenıke',
@@ -1475,8 +1475,8 @@ Eka tu wazene ke nameyo raşt xo bide, ma nameyo raşt ti iştirakanê ti de moc
 'prefs-help-email-others' => 'Şıma şenê weçinê ke ê bini be yew gırey pela şımaya karberi ya zi pela werênayışi sera şıma de ebe e-poste irtıbat kewê.
 Kaberê bini ke şıma de kewti irtıbat, adresa e-postey şıma eşkera nêbena.',
 'prefs-help-email-required' => 'E-mail adrese mecburiya.',
-'prefs-info' => 'Seron zanayış',
-'prefs-i18n' => 'Şaryayış kerdış',
+'prefs-info' => 'Melumato bıngeh',
+'prefs-i18n' => 'Beynelmılelkerdış',
 'prefs-signature' => 'İmza',
 'prefs-dateformat' => 'Formatê tarixi',
 'prefs-timeoffset' => 'Wext offset',
@@ -1488,7 +1488,7 @@ Kaberê bini ke şıma de kewti irtıbat, adresa e-postey şıma eşkera nêbena
 'prefs-displayrc' => 'Tercihan bımocne',
 'prefs-displaysearchoptions' => 'Weçinayışê mocnayışi',
 'prefs-displaywatchlist' => 'Weçinayışê mocnayışi',
-'prefs-diffs' => 'Diffs',
+'prefs-diffs' => 'Ferqi',
 
 # User preference: e-mail validation using jQuery
 'email-address-validity-valid' => 'e-posta adresi raştayo',
@@ -1497,12 +1497,12 @@ Kaberê bini ke şıma de kewti irtıbat, adresa e-postey şıma eşkera nêbena
 # User rights
 'userrights' => 'İdarey heqanê karberan',
 'userrights-lookup-user' => 'Grubanê karberi/karbere idare bıke',
-'userrights-user-editname' => 'Yew namey karberi bınusne',
+'userrights-user-editname' => 'Yew nameyê karberi cı kewe:',
 'editusergroup' => 'Grupanê karberi/karbere bıvurne (bıbedelne)',
 'editinguser' => "'''[[User:$1|$1]]''' keno weziyetê $2'i bıvurno",
 'userrights-editusergroup' => 'Grubanê karberi/karbere sero bıgureye (bıxebetiye)',
 'saveusergroups' => 'Grubanê karberi qeyd bıke',
-'userrights-groupsmember' => 'Ezaê / Ezaya:',
+'userrights-groupsmember' => 'Eza:',
 'userrights-groupsmember-auto' => 'Ezao daxıl/ezaa daxıle ê:',
 'userrights-groups-help' => 'şıma şenê grubanê nê karberi/na karbere, oyo/aya ke tede, bıvurnê:
 * qutiya ke nışankerdiya, mocnena ke karber/e na grube dero/dera.
@@ -1518,7 +1518,7 @@ Kaberê bini ke şıma de kewti irtıbat, adresa e-postey şıma eşkera nêbena
 'userrights-irreversible-marker' => '$1*',
 
 # Groups
-'group' => 'Grup:',
+'group' => 'Grube:',
 'group-user' => 'Karberi',
 'group-autoconfirmed' => 'Karberê ke xob xo biyê araşt',
 'group-bot' => 'Boti',
@@ -1539,7 +1539,7 @@ Kaberê bini ke şıma de kewti irtıbat, adresa e-postey şıma eşkera nêbena
 'grouppage-bot' => '{{ns:project}}:Boti',
 'grouppage-sysop' => '{{ns:project}}:İdarekeri',
 'grouppage-bureaucrat' => '{{ns:project}}:Burokrati',
-'grouppage-suppress' => '{{ns:project}}:Kontrol',
+'grouppage-suppress' => '{{ns:project}}:Qontrol',
 
 # Rights
 'right-read' => 'Pelan bıwanê',
@@ -1570,7 +1570,7 @@ Kaberê bini ke şıma de kewti irtıbat, adresa e-postey şıma eşkera nêbena
 'right-deleterevision' => 'Vurnayışê xısusiyê ke ê pelanê, inan bestere ya zi peyser bia',
 'right-deletedhistory' => 'Qeydanê tarixanê esterıteyan de qayt ke, bê nuştey inan',
 'right-deletedtext' => 'Mabênê newede vurnayışanê esterıtiyan de qaytê nuştey esterıtey u vurnayışan ke',
-'right-browsearchive' => 'Bıgeyre pelanê eserıtiyan',
+'right-browsearchive' => 'Pelanê esterıteyan bıgeyre',
 'right-undelete' => 'Jû pela esterıtiye peyser bia',
 'right-suppressrevision' => 'İdarekeran ra dızdeni/miyanki, newede vurnayışan de qayt ke u newede vıraze',
 'right-suppressionlog' => 'Rocekanê xasan bıvêne',
@@ -1579,7 +1579,7 @@ Kaberê bini ke şıma de kewti irtıbat, adresa e-postey şıma eşkera nêbena
 'right-hideuser' => 'Yew namey karberi  şari ra dızdeni/miyanki bloke bıke',
 'right-ipblock-exempt' => 'Blokanê IPi, oto-blokan u blokanê menzıli ra ravêre',
 'right-proxyunbannable' => 'Blokanê otomatikiê proksiyan ra ravêre',
-'right-unblockself' => 'Inan a bike',
+'right-unblockself' => 'İnan ake',
 'right-protect' => 'Sewiyanê pawıtışi (mıhafezey) bıvurne u pelanê kılitbiyaiyan sero bıgureye.',
 'right-editprotected' => 'Pelanê pawıtiyan sero bıgureye (bê pawıtena kaskadi (game be game))',
 'right-editinterface' => 'Interfaceê karberi sero bıgureye',
@@ -1595,7 +1595,7 @@ Kaberê bini ke şıma de kewti irtıbat, adresa e-postey şıma eşkera nêbena
 'right-autopatrol' => 'Vurnayîşanê xo otomatik nîşan bike ke patrol biyê',
 'right-patrolmarks' => 'Vurnayîşanê peniyî nîşan patrol biyê bivîne',
 'right-unwatchedpages' => 'Yew listeyê pelanê seyrnibiye bivîne',
-'right-mergehistory' => 'Tarixê pelanê yew bike',
+'right-mergehistory' => 'Tarixê pelan yew ke',
 'right-userrights' => 'Heqanê karberi pêro bıvurne',
 'right-userrights-interwiki' => 'Heqqa karberanê ke ho wîkîyo binî de ey bivurne',
 'right-siteadmin' => 'Database kilit bike u a bike',
@@ -1621,7 +1621,7 @@ Kaberê bini ke şıma de kewti irtıbat, adresa e-postey şıma eşkera nêbena
 'action-move-subpages' => 'ena pele, u pelanê daê bınênan bere',
 'action-move-rootuserpages' => 'pelanê karberiyê bıngeyan bere',
 'action-movefile' => 'ena dosya bere',
-'action-upload' => 'ena dosya bar bike',
+'action-upload' => 'ena dosya bar ke',
 'action-reupload' => 'dosyayê ke database de esto ser ey binuse',
 'action-reupload-shared' => 'dosyayê ki ho embarê medyayî de esto ser ay binusne',
 'action-upload_by_url' => 'Ena dosya yew URL ra bar bike',
@@ -1641,7 +1641,7 @@ Kaberê bini ke şıma de kewti irtıbat, adresa e-postey şıma eşkera nêbena
 'action-patrol' => 'vurnayîşê karberanê binî nişan bike patrol biye',
 'action-autopatrol' => 'vurnayîşê xoye nişan bike ke belli biyo patrol biye',
 'action-unwatchedpages' => 'listeyê pelanê seyirnibiya bivîne',
-'action-mergehistory' => 'tarixê ena pele yew bike',
+'action-mergehistory' => 'tarixê ena pele yew ke',
 'action-userrights' => 'heqqa karberanê hemî bivurne',
 'action-userrights-interwiki' => 'heqqa karberanê ke wikiyê binî de hemî bivurne',
 'action-siteadmin' => 'database kilit bike ya zi a bike',
@@ -1650,23 +1650,23 @@ Kaberê bini ke şıma de kewti irtıbat, adresa e-postey şıma eşkera nêbena
 # Recent changes
 'nchanges' => '$1 {{PLURAL:$1|fın vurna|fıni vurna}}',
 'recentchanges' => 'Vurnayışê peyêni',
-'recentchanges-legend' => 'Tercihê vurnayışanê peniyan',
-'recentchanges-summary' => 'Ena pele de wiki sero vurnayışê peyêni teqib ke',
+'recentchanges-legend' => 'Tercihê vurnayışanê peyênan',
+'recentchanges-summary' => 'Ena pela sera vurnayışanê peyênan de wiki teqib ke.',
 'recentchanges-feed-description' => 'Ena feed dı vurnayişanê tewr peniyan teqip bık.',
 'recentchanges-label-newpage' => 'Enê vurnayışi pelaya newi vıraşt',
-'recentchanges-label-minor' => 'Eno vurnayışo do qickek o',
+'recentchanges-label-minor' => 'Eno yew vurnayışo qıckeko',
 'recentchanges-label-bot' => 'Yew boti xo het ra no vurnayış vıraşto',
-'recentchanges-label-unpatrolled' => 'Eno edît patrol nibiyo',
+'recentchanges-label-unpatrolled' => 'Eno vurnayış hewna dewriya nêbiyo',
 'rcnote' => "Bıni dı {{PLURAL:$1|'''1''' vurnayış|peyni de '''$1''' vurnayışi estê}} {{PLURAL:$2|roc|'''$2''' roci}}, hetana $5, $4.",
 'rcnotefrom' => "Cêr de '''$2''' ra nata vurnayışiyê asenê (tewr vêşi <b> '''$1'''</b> asenê).",
 'rclistfrom' => '$1 ra vurnayışanê neweyan bımocne',
-'rcshowhideminor' => 'Vurnayışanê werdiya $1',
-'rcshowhidebots' => 'Bota $1',
-'rcshowhideliu' => 'Karberanê qeydına $1',
+'rcshowhideminor' => 'Vurnayışanê werdiyan $1',
+'rcshowhidebots' => 'Botan $1',
+'rcshowhideliu' => 'Karberanê qeydınan $1',
 'rcshowhideanons' => 'Karberanê anoniman $1',
 'rcshowhidepatr' => '$1 vurnayışê ke dewriya geyrayê',
-'rcshowhidemine' => 'nuştışanê mı $1',
-'rclinks' => 'Peyni $2 rocan de vurnayışa $1  bımocne <br />$3',
+'rcshowhidemine' => 'Vurnayışanê mı $1',
+'rclinks' => 'Peyniya $2 rocan de $1 vurnayışan bımocne <br />$3',
 'diff' => 'ferq',
 'hist' => 'verên',
 'hide' => 'Bınımne',
@@ -1726,7 +1726,7 @@ wexta şima qayîl e yew peli re dosya bierzî, formanê cêrinan ra yewi bişux
 'filedesc' => 'Xulasa',
 'fileuploadsummary' => 'Xulasa:',
 'filereuploadsummary' => 'Vurnayîşê dosyayî:',
-'filestatus' => 'Weziyetê heqê telifiye:',
+'filestatus' => 'Weziyetê heqa telifi:',
 'filesource' => 'Çıme:',
 'uploadedfiles' => 'Dosyayê ke bar biye',
 'ignorewarning' => 'Îkazi kebul meke u dosya reyna bar bike',
@@ -1826,7 +1826,7 @@ PICT # misc.
 
 'upload-proto-error' => 'Porotokol raşt ni yo.',
 'upload-proto-error-text' => 'Bar kerdişê durî gani  URLî estbiye ke pe <code>http://</code> ya zi <code>ftp://</code> başli beno.',
-'upload-file-error' => 'Ğeletê dahilî',
+'upload-file-error' => 'Xeta daxılkiye',
 'upload-file-error-text' => 'Peşkeşwan de wexta yew dosya vıraziyayene xeta bı.
 kerem kerê [[Special:ListUsers/sysop|serkari]]de irtibat kewe.',
 'upload-misc-error' => 'Ğeletê bar kerdişî nizanyeno',
@@ -2060,7 +2060,7 @@ listeya ke ha ver a têna na {{PLURAL:$1|dosyaya ewwili|dosyaya $1 ewwili}} mocn
 'statistics-header-users' => 'Îstatistiksê karberî',
 'statistics-header-hooks' => 'Îstatistiksê binî',
 'statistics-articles' => 'Pelanê tedesteyî',
-'statistics-pages' => 'Peri',
+'statistics-pages' => 'Peli',
 'statistics-pages-desc' => 'Pelanê hemî ke wîkî de estê, pelanê mineqeşeyî, redireksiyon ucb... dehil o.',
 'statistics-files' => 'Dosyayê bar biye',
 'statistics-edits' => 'Amarê vurnayîşî ke wextê {{SITENAME}} ronayîşî ra',
@@ -2268,8 +2268,8 @@ qey heqê şexsi de [[{{MediaWiki:Listgrouprights-helppage}}|hema malumato ziyed
 'listgrouprights-removegroup' => '{{PLURAL:$2|Grube|Gruban}} bıvecê: $1',
 'listgrouprights-addgroup-all' => 'şıma hesabê xo re heme gruban eşkeni têare bıkeri',
 'listgrouprights-removegroup-all' => 'şıma hesabê xo ra heme gruban eşkeni veci',
-'listgrouprights-addgroup-self' => 'şıma hesabê xo re eşkeni {{PLURAL:$2|grub|gruban}} têare bıkerî: $1',
-'listgrouprights-removegroup-self' => 'şıma hesabê xo ra eşkeni {{PLURAL:$2|grub|gruban}} bıveci: $1',
+'listgrouprights-addgroup-self' => 'Hesabê xo rê {{PLURAL:$2|grube|gruban}} cı kerê: $1',
+'listgrouprights-removegroup-self' => 'Hesabê xo ra {{PLURAL:$2|grube|gruban}} bıvecê: $1',
 'listgrouprights-addgroup-self-all' => 'şıma eşkeni hesabê xo re heme gruban têare bıkerî',
 'listgrouprights-removegroup-self-all' => 'şıma hesabê xo ra eşkeni heme gruban bıveci',
 
@@ -2562,16 +2562,16 @@ $1',
 
 # Namespace form on various pages
 'namespace' => 'Cayê namey:',
-'invert' => 'Bê weçineni ê bina peyser biya',
+'invert' => 'Weçinıtışo peyserki',
 'tooltip-invert' => 'nameyo ke nışan biyo (u nameyo elekeyın zi nışanyyayo se) vurnayışan  zerrekan nımtışi re ena dore tesdiqi nışan kerê',
-'namespace_association' => 'Cayê nameyanê elaqadaran',
+'namespace_association' => 'Cayê nameyanê eleqedaran',
 'tooltip-namespace_association' => 'Herunda canemiya elekeyın nışan kerdışi sero qıse kerdışi yana zerre dekerdışi rê ena dora tesdiqi nışan kerê',
 'blanknamespace' => '(Ser)',
 
 # Contributions
 'contributions' => 'İştiraqê karberi',
 'contributions-title' => 'Dekerdenê karber de $1',
-'mycontris' => 'İştıraqê mı',
+'mycontris' => '[Dekerdenê mı]',
 'contribsub2' => 'Qandê $1 ($2)',
 'nocontribs' => 'Ena kriteriya de vurnayîş çini yo.',
 'uctop' => '(top)',
@@ -2599,7 +2599,7 @@ Cıkewtışo tewr peyêno ke bloke biyo, cêr seba referansi belikerdeyo:',
 # What links here
 'whatlinkshere' => 'Gıreyê pele',
 'whatlinkshere-title' => 'Per da "$1" rê perê ke gre danê',
-'whatlinkshere-page' => 'Per:',
+'whatlinkshere-page' => 'Pele:',
 'linkshere' => "Ena peleyan grey biya '''[[:$1]]''':",
 'nolinkshere' => "Per da '''[[:$1]]''' rê pera ke gıre dana çıniya.",
 'nolinkshere-ns' => "Ena cayê nameyî de yew pel zi '''[[:$1]]''' rê link nibeno.",
@@ -2694,7 +2694,7 @@ Cıkewtışo tewr peyêno ke bloke biyo, cêr seba referansi belikerdeyo:',
 'blocklink' => 'kılit ke',
 'unblocklink' => 'bloqi hewad',
 'change-blocklink' => 'kılit-kerdışi bıvurne',
-'contribslink' => 'dekerdeni',
+'contribslink' => 'iştıraqi',
 'emaillink' => 'e-poste bırışe',
 'autoblocker' => 'Şıma otomatikmen kılit biy, çıke adresa şımawa \'\'IP\'\'y terefê "[[User:$1|$1]]" gureniyena.
 Sebebê kılit-biyayışê $1\'i: "$2"o',
@@ -3045,7 +3045,7 @@ Kerem ke, qeydkerdış ra ver gocega verqayti bıxebetne.',
 'tooltip-watchlistedit-raw-submit' => 'Listeyê seyri newen ke',
 'tooltip-recreate' => 'pel hewn a bışiyo zi tepiya biya',
 'tooltip-upload' => 'Bar bike',
-'tooltip-rollback' => '"Peyser biya" be yew tik pela îştirak(an)ê peyên|i(an) peyser ano.',
+'tooltip-rollback' => '"Peyser bia" be yew tık pela iştıraq(an)ê peyên|i(an) peyser ano.',
 'tooltip-undo' => '"Undo" ena vurnayışê newi iptal kena u vurnayışê verni a kena.
 Tı eşkeno yew sebeb bınus.',
 'tooltip-preferences-save' => 'Terciha qeyd ke',
@@ -4197,7 +4197,7 @@ $8',
 'exif-ycbcrpositioning-1' => 'Wertekerdış',
 'exif-ycbcrpositioning-2' => 'Wayırê-site',
 
-'exif-dc-contributor' => 'Dekerdeni',
+'exif-dc-contributor' => 'İştıraqkeri',
 'exif-dc-coverage' => 'Heruna yana wextin grotışa medya',
 'exif-dc-date' => 'Tarix(i)',
 'exif-dc-publisher' => 'Hesrekar',
@@ -4357,7 +4357,7 @@ Ma rica keno tesdiq bike ke ti raştî wazeno eno pel bivirazo.",
 # Table pager
 'ascending_abbrev' => 'berz',
 'descending_abbrev' => 'nızm',
-'table_pager_next' => 'Pela peyên',
+'table_pager_next' => 'Pela peyêne',
 'table_pager_prev' => 'Pela verêne',
 'table_pager_first' => 'Pela jûyıne',
 'table_pager_last' => 'Pela peyêne',
@@ -4600,8 +4600,8 @@ satır ê ke pê ney # # destpêkenê zey mışore/mıjore muamele vineno.
 # Special:ComparePages
 'comparepages' => 'Pela miqeyese ke',
 'compare-selector' => 'Revizyonê pele miqayese bike',
-'compare-page1' => 'Pela 1',
-'compare-page2' => 'Pel 2',
+'compare-page1' => 'Pele 1',
+'compare-page2' => 'Pele 2',
 'compare-rev1' => 'Revizyonê 1i',
 'compare-rev2' => 'Revizyonê 2i',
 'compare-submit' => 'Miqayese',
index c184f3d..9508efc 100644 (file)
@@ -158,7 +158,6 @@ $messages = array(
 'qbbrowse' => 'Pogihum',
 'qbedit' => 'Idito',
 'qbpageoptions' => 'Bolikon diti',
-'qbpageinfo' => 'Pogiromutan',
 'qbmyoptions' => 'Bobolikonku ngawi',
 'qbspecialpages' => 'Bobolikon suaikowokon',
 'faq' => 'Ponguhatan Koinsoruan om Poninimbar',
index dc5fb52..a61ab82 100644 (file)
@@ -1392,7 +1392,7 @@ Custom .css and .js pages use a lowercase title, e.g. {{ns:user}}:Foo/vector.css
 'note'                             => "'''Note:'''",
 'previewnote'                      => "'''Remember that this is only a preview.'''
 Your changes have not yet been saved!",
-'continue-editing'                 => 'Continue editing',
+'continue-editing'                 => 'Go to editing area',
 'previewconflict'                  => 'This preview reflects the text in the upper text editing area as it will appear if you choose to save.',
 'session_fail_preview'             => "'''Sorry! We could not process your edit due to a loss of session data.'''
 Please try again.
@@ -3684,7 +3684,7 @@ You can view its source',
 'standard.css'            => '/* CSS placed here will affect users of the Standard skin */', # only translate this message to other languages if you have to change it
 'nostalgia.css'           => '/* CSS placed here will affect users of the Nostalgia skin */', # only translate this message to other languages if you have to change it
 'cologneblue.css'         => '/* CSS placed here will affect users of the Cologne Blue skin */', # only translate this message to other languages if you have to change it
-'monobook.css'            => '/* CSS placed here will affect users of the Monobook skin */', # only translate this message to other languages if you have to change it
+'monobook.css'            => '/* CSS placed here will affect users of the MonoBook skin */', # only translate this message to other languages if you have to change it
 'myskin.css'              => '/* CSS placed here will affect users of the MySkin skin */', # only translate this message to other languages if you have to change it
 'chick.css'               => '/* CSS placed here will affect users of the Chick skin */', # only translate this message to other languages if you have to change it
 'simple.css'              => '/* CSS placed here will affect users of the Simple skin */', # only translate this message to other languages if you have to change it
index ed973de..cc28a22 100644 (file)
@@ -1245,8 +1245,9 @@ Bonvolu kontroli la protokolojn.',
 'revdelete-only-restricted' => 'Eraro kaŝante la aĵon de $2, $1: Vi ne povas subpremi aĵojn de vido de administrantoj sen ankaŭ selektante unu el la aliaj subpremo-opcioj.',
 'revdelete-reason-dropdown' => '*Oftaj kialoj por forigado
 ** Aŭtorrajta neglekto
-** Maltaŭga persona informo
-** Eventualaj malhonorigaj informoj',
+** Maltaŭga komento aŭ persona informo
+** Nekonvena uzantnomo
+** Eventuale kalumnaj informoj',
 'revdelete-otherreason' => 'Alia/aldona kialo:',
 'revdelete-reasonotherlist' => 'Alia kialo',
 'revdelete-edit-reasonlist' => 'Redakti kialojn por forigo',
index a586007..0ebce80 100644 (file)
@@ -1057,7 +1057,7 @@ La última entrada del registro de bloqueos se proporciona debajo para mayor ref
 'note' => "'''Nota:'''",
 'previewnote' => "'''¡Recuerda que esto es solo una previsualización.'''
 ¡Tus cambios aún no se ha guardado!",
-'continue-editing' => 'Continuar editando',
+'continue-editing' => 'Ir al área de edición',
 'previewconflict' => 'Esta previsualización refleja el texto en el área de edición superior como aparecerá una vez guardados los cambios.',
 'session_fail_preview' => "'''Lo sentimos, no pudimos procesar la edición debido a una pérdida de los datos de sesión.'''
 Por favor, inténtalo de nuevo.
@@ -3105,7 +3105,7 @@ Permite añadir una razón al resumen de edición.',
 'standard.css' => '/* Los estilos CSS colocados aquí se aplicarán para todos los usuarios que usen la piel Standard */',
 'nostalgia.css' => '/* Los estilos CSS colocados aquí se aplicarán para todos los usuarios que usen la piel Nostalgia */',
 'cologneblue.css' => '/* Los estilos CSS colocados aquí se aplicarán para todos los usuarios que usen la piel Cologne Blue */',
-'monobook.css' => '/* Los estilos CSS colocados aquí se aplicarán para todos los usuarios que usen la piel Monobook */',
+'monobook.css' => '/* Los estilos CSS colocados aquí se aplicarán para todos los usuarios que usen la piel MonoBook */',
 'myskin.css' => '/* Los estilos CSS colocados aquí se aplicarán para todos los usuarios que usen la piel MySkin */',
 'chick.css' => '/* Los estilos CSS colocados aquí se aplicarán para todos los usuarios que usen la piel Chick */',
 'simple.css' => '/* Los estilos CSS colocados aquí se aplicarán para todos los usuarios que usen la piel Simple */',
index 29b6604..e281f90 100644 (file)
@@ -378,7 +378,7 @@ $messages = array(
 'tog-hideminor' => 'Masquer les modifications mineures dans les modifications récentes',
 'tog-hidepatrolled' => 'Masquer les modifications surveillées dans les modifications récentes',
 'tog-newpageshidepatrolled' => 'Masquer les pages surveillées parmi les nouvelles pages',
-'tog-extendwatchlist' => 'Étendre la liste de suivi pour afficher toutes les modifications et non seulement les plus récentes',
+'tog-extendwatchlist' => 'Étendre la liste de suivi pour afficher toutes les modifications et pas uniquement les plus récentes',
 'tog-usenewrc' => 'Grouper les changements dans les modifications récentes et la liste de suivi (nécessite JavaScript)',
 'tog-numberheadings' => 'Numéroter automatiquement les titres de section',
 'tog-showtoolbar' => "Montrer la barre d'outils de modification (nécessite JavaScript)",
@@ -635,7 +635,7 @@ $1',
 'youhavenewmessages' => 'Vous avez $1 ($2).',
 'newmessageslink' => 'de nouveaux messages',
 'newmessagesdifflink' => 'dernière modification',
-'youhavenewmessagesfromusers' => "Vous avez  $1  d'{{PLURAL:$3| un autre utilisateur|$3 autres utilisateurs}} ( $2 ).",
+'youhavenewmessagesfromusers' => "Vous avez $1 {{PLURAL:$3|d'un autre utilisateur|de $3 autres utilisateurs}} ($2).",
 'youhavenewmessagesmanyusers' => 'Vous avez $1 de nombreux utilisateurs ($2).',
 'newmessageslinkplural' => '{{PLURAL:$1|un message|nouveaux messages}}',
 'newmessagesdifflinkplural' => 'dernières modification{{PLURAL:$1||s}}',
@@ -785,7 +785,7 @@ Notez que certaines pages peuvent être encore affichées comme si vous étiez t
 
 Votre compte a été créé.
 N’oubliez pas de personnaliser vos [[Special:Preferences|préférences sur {{SITENAME}}]].',
-'yourname' => 'Nom d’utilisateur :',
+'yourname' => 'Nom d’utilisateur :',
 'yourpassword' => 'Mot de passe&nbsp;:',
 'yourpasswordagain' => 'Confirmez le mot de passe :',
 'remembermypassword' => 'Me reconnecter automatiquement aux prochaines visites avec ce navigateur (au maximum $1&nbsp;{{PLURAL:$1|jour|jours}})',
@@ -1056,7 +1056,7 @@ La dernière entrée du registre des blocages est indiquée ci-dessous à titre
 'note' => "'''Note :'''",
 'previewnote' => "'''Rappelez-vous que ce n’est qu’une prévisualisation.'''
 Vos modifications n’ont pas encore été enregistrées !",
-'continue-editing' => 'Continuer la modification',
+'continue-editing' => 'Aller à modification de la zone',
 'previewconflict' => 'Cette prévisualisation montre le texte de la boîte supérieure de modification tel qu’il apparaîtra si vous choisissez de le publier.',
 'session_fail_preview' => "'''Nous ne pouvons enregistrer votre modification à cause d’une perte d’informations concernant votre session.'''
 Veuillez réessayer.
@@ -3195,6 +3195,13 @@ Permet de rétablir la version précédente et d’ajouter un motif dans la boî
 'pageinfo-hidden-categories' => '{{PLURAL:$1|Catégorie cachée|Catégories cachées}} ($1)',
 'pageinfo-templates' => '{{PLURAL:$1|Modèle inclu|Modèles inclus}} ($1)',
 'pageinfo-toolboxlink' => 'Information sur la page',
+'pageinfo-redirectsto' => 'Rediriger vers',
+'pageinfo-redirectsto-info' => 'info',
+'pageinfo-contentpage' => 'Compté comme page de contenu',
+'pageinfo-contentpage-yes' => 'Oui',
+'pageinfo-protect-cascading' => "Les protections sont déduites d'ici",
+'pageinfo-protect-cascading-yes' => 'Oui',
+'pageinfo-protect-cascading-from' => 'Les protections sont déduites depuis',
 
 # Skin names
 'skinname-standard' => 'Standard',
index 3826bbd..e58b27a 100644 (file)
@@ -939,7 +939,7 @@ La rêson balyêye est ''$2''.
 * Èxpiracion du blocâjo : $6
 * Compto blocâ : $7
 
-Vos vos pouede veriér vers $1 ou ben yon des ôtros [[{{MediaWiki:Grouppage-sysop}}|administrators]] por nen discutar.
+Vos vos pouede veriér vers $1 ou ben un ôtr’[[{{MediaWiki:Grouppage-sysop}}|administrator]] por nen discutar.
 Vos pouede pas empleyér la fonccionalitât « Lui mandar un mèssâjo » a muens qu’un’adrèce èlèctronica valida est spècifiâye dens voutres [[Special:Preferences|prèferences]] et que vos éte pas étâ blocâ de l’empleyér.
 Voutron adrèce IP d’ora est $3, et lo numerô de blocâjo est $5.
 Volyéd encllure tôs los dètalys ce-dessus dedens quinta que seye demanda que vos faréd.",
index 7552e54..094f048 100644 (file)
@@ -930,7 +930,7 @@ Lembre que as páxinas .css e .js personalizadas utilizan un título en minúscu
 'updated' => '(Actualizado)',
 'note' => "'''Nota:'''",
 'previewnote' => "'''Lembre que esta é só unha vista previa e que aínda non gardou os seus cambios!'''",
-'continue-editing' => 'Continuar editando',
+'continue-editing' => 'Ir ata a caixa de edición',
 'previewconflict' => 'Esta vista previa mostra o texto na área superior tal e como aparecerá se escolle gardar.',
 'session_fail_preview' => "'''O sistema non pode procesar a súa edición porque se perderon os datos de inicio da sesión.
 Por favor, inténteo de novo.
@@ -2378,7 +2378,7 @@ proceda con coidado.',
 'rollbacklink' => 'reverter',
 'rollbacklinkcount' => 'reverter $1 {{PLURAL:$1|edición|edicións}}',
 'rollbacklinkcount-morethan' => 'reverter máis de $1 {{PLURAL:$1|edición|edicións}}',
-'rollbackfailed' => 'Houbo un fallo ao reverter as edicións',
+'rollbackfailed' => 'Houbo un erro ao reverter as edicións',
 'cantrollback' => 'Non se pode desfacer a edición; o último colaborador é o único autor desta páxina.',
 'alreadyrolled' => 'Non se pode desfacer a edición en "[[:$1]]" feita por [[User:$2|$2]] ([[User talk:$2|conversa]]{{int:pipe-separator}}[[Special:Contributions/$2|{{int:contribslink}}]]); alguén máis editou ou desfixo os cambios desta páxina.
 
index 7048d38..4dd850e 100644 (file)
@@ -1788,7 +1788,7 @@ Villicht witt d Bschryybig uf dr dertige [$2 Dateibschryybigssyte] bearbeite.',
 'uploadnewversion-linktext' => 'E nöui Version vo dere Datei ufelade',
 'shared-repo-from' => 'vu $1',
 'shared-repo' => 'eme gmeinsame Repositorium',
-'upload-disallowed-here' => 'Leider chasch des Bild nit iberschryybe.',
+'upload-disallowed-here' => 'Du chasch die Datei nit iberschryybe.',
 
 # File reversion
 'filerevert' => 'Zrucksetze vu „$1“',
@@ -2833,6 +2833,7 @@ Die uf em lokale Rächner spychere un derno do uffelade.',
 
 # Info page
 'pageinfo-title' => 'Informatione zue „$1“',
+'pageinfo-not-current' => 'Die Informatione chenne nume fir di nejscht Versions aazeigt wäre.',
 'pageinfo-header-basic' => 'Basisinformatione',
 'pageinfo-header-edits' => 'Bearbeitige',
 'pageinfo-header-restrictions' => 'Syteschutz',
index 5ee71b8..baff36b 100644 (file)
@@ -173,7 +173,7 @@ $messages = array(
 'tog-nocache' => 'બ્રાઉઝરનું પેજ કેશિંગ અક્રિય કરો',
 'tog-enotifwatchlistpages' => 'મારી ધ્યાનસૂચિમાંનું પાનુ અને ફાઇલમાં ફેરફાર થાય ત્યારે મને ઇ-મેલ મોકલો',
 'tog-enotifusertalkpages' => 'મારી ચર્ચાનાં પાનામાં ફેરફાર થાય ત્યારે મને ઇ-મેલ મોકલો',
-'tog-enotifminoredits' => 'પાનાં અનેફાઇલ્સમાં નાનાં ફેરફાર થાય તો પણ મને ઇ-મેલ મોકલો',
+'tog-enotifminoredits' => 'પાનાં અને ફાઇલ્સમાં નાનાં ફેરફાર થાય તો પણ મને ઇ-મેલ મોકલો',
 'tog-enotifrevealaddr' => 'નોટીફીકેશનના ઇમેલમાં મારૂ ઇમેલ એડ્રેસ બતાવો',
 'tog-shownumberswatching' => 'ધ્યાનમાં રાખતા સભ્યોની સંખ્યા બતાવો',
 'tog-oldsig' => 'હાલના હસ્તાક્ષર',
index faa2d37..5ef71ca 100644 (file)
@@ -1057,7 +1057,7 @@ $2
 'note' => "'''הערה:'''",
 'previewnote' => "'''זכרו שזו רק תצוגה מקדימה.'''
 השינויים שלכם טרם נשמרו!",
-'continue-editing' => '×\9c×\94×\9eש×\9a העריכה',
+'continue-editing' => '×\9e×¢×\91ר ×\9c×\90×\96×\95ר העריכה',
 'previewconflict' => 'תצוגה מקדימה זו מציגה כיצד ייראה הטקסט בחלון העריכה העליון, אם תבחרו לשמור אותו.',
 'session_fail_preview' => "'''לא ניתן לבצע את עריכתכם עקב אובדן מידע הכניסה.'''
 אנא נסו שוב.
@@ -1562,8 +1562,8 @@ $1",
 'editinguser' => "שינוי הרשאות המשתמש של '''[[User:$1|$1]]''' $2",
 'userrights-editusergroup' => 'עריכת קבוצות משתמש',
 'saveusergroups' => 'שמירת קבוצות משתמש',
-'userrights-groupsmember' => '{{GENDER:$2|חבר|חברה}} {{PLURAL:$1|בקבוצה|בקבוצות}}:',
-'userrights-groupsmember-auto' => '{{GENDER:$2|חבר|חברה}} אוטומטית {{PLURAL:$1|בקבוצה|בקבוצות}}:',
+'userrights-groupsmember' => '{{GENDER:$2|חבר|חברה}} ב{{PLURAL:$1|קבוצה|קבוצות}}:',
+'userrights-groupsmember-auto' => '{{GENDER:$2|חבר|חברה}} אוטומטית ב{{PLURAL:$1|קבוצה|קבוצות}}:',
 'userrights-groups-help' => 'באפשרותכם לשנות את הקבוצות שמשתמש זה חבר בהן:
 * תיבה מסומנת פירושה שהמשתמש חבר בקבוצה.
 * תיבה בלתי מסומנת פירושה שהמשתמש אינו חבר בקבוצה.
@@ -3119,7 +3119,7 @@ $1',
 'standard.css' => '/* הסגנונות הנכתבים כאן ישפיעו על העיצוב Standard בלבד */',
 'nostalgia.css' => '/* הסגנונות הנכתבים כאן ישפיעו על העיצוב Nostalgia בלבד */',
 'cologneblue.css' => '/* הסגנונות הנכתבים כאן ישפיעו על העיצוב CologneBlue בלבד */',
-'monobook.css' => '/* הסגנונות הנכתבים כאן ישפיעו על העיצוב Monobook בלבד */',
+'monobook.css' => '/* הסגנונות הנכתבים כאן ישפיעו על העיצוב MonoBook בלבד */',
 'myskin.css' => '/* הסגנונות הנכתבים כאן ישפיעו על העיצוב MySkin בלבד */',
 'chick.css' => '/* הסגנונות הנכתבים כאן ישפיעו על העיצוב Chick בלבד */',
 'simple.css' => '/* הסגנונות הנכתבים כאן ישפיעו על העיצוב Simple בלבד */',
index 983d30b..7c57a24 100644 (file)
@@ -161,7 +161,6 @@ $messages = array(
 'qbbrowse' => 'Magbasa-basa',
 'qbedit' => 'Ilisan',
 'qbpageoptions' => 'Ining panid',
-'qbpageinfo' => 'Kahulugan/Konteksto',
 'qbmyoptions' => 'Akon mga panid',
 'qbspecialpages' => 'Pinasahi nga mga panid',
 'faq' => 'Mga masami pamangkoton',
index a4a648e..91ae583 100644 (file)
@@ -817,7 +817,7 @@ Podrobnosće móžeš w  [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE
 'note' => "'''Kedźbu:'''",
 'previewnote' => "'''Wobmysl, zo to je jenož přehlad.'''
 Twoje změny hišće njejsu składowane!",
-'continue-editing' => 'Dale wobdźěłać',
+'continue-editing' => 'K wobdźěłowanskemu polu',
 'previewconflict' => 'Tutón přehlad zwobraznja tekst w hornim tekstowym polu,  kaž so zjewi, jeli jón składuješ.',
 'session_fail_preview' => "'''Njemóžachmy twoju změnu předźěłać, dokelž su so posedźenske daty zhubili.'''
 Spytaj prošu hišće raz.
index fdda6be..ef7ca14 100644 (file)
@@ -2274,6 +2274,7 @@ Please visit [//www.mediawiki.org/wiki/Localisation MediaWiki Localisation] and
 'pageinfo-watchers' => 'Դիտողների քանակ',
 'pageinfo-edits' => 'Խմբագրումների քանակ',
 'pageinfo-authors' => 'Տարբեր հեղինակների քանակ',
+'pageinfo-toolboxlink' => 'Էջի մասին տեղեկություն',
 
 # Skin names
 'skinname-standard' => 'Դասական',
index 5eaedf2..6f2e046 100644 (file)
@@ -941,7 +941,7 @@ L'ultimo elemento del registro dei blocchi è riportato di seguito per informazi
 'note' => "'''Nota:'''",
 'previewnote' => "'''Ricorda che questa è solo un'anteprima.'''
 Le tue modifiche NON sono ancora state salvate!",
-'continue-editing' => 'Continua a modificare',
+'continue-editing' => "Vai all'area di modifica",
 'previewconflict' => 'L\'anteprima corrisponde al testo presente nella casella di modifica superiore e rappresenta la pagina come apparirà se si sceglie di premere "Salva la pagina" in questo momento.',
 'session_fail_preview' => "'''Non è stato possibile elaborare la modifica perché sono andati persi i dati relativi alla sessione.
 Riprovare.
index fb473e3..555ba01 100644 (file)
@@ -377,7 +377,7 @@ $messages = array(
 'tog-editsection' => '[編集]リンクから節を編集できるようにする',
 'tog-editsectiononrightclick' => '節見出しの右クリックで節を編集できるようにする(JavaScriptが必要)',
 'tog-showtoc' => '目次を表示(ページに見出しが4つ以上ある場合)',
-'tog-rememberpassword' => 'このブラウザーにログイン情報を記憶(最大 $1 {{PLURAL:$1|日間}})',
+'tog-rememberpassword' => 'このブラウザーにログイン情報を保存 (最長 $1 {{PLURAL:$1|日|日間}})',
 'tog-watchcreations' => '自分が作成したページやアップロードしたファイルをウォッチリストに追加',
 'tog-watchdefault' => '自分が編集したページやファイルをウォッチリストに追加',
 'tog-watchmoves' => '自分が移動したページやファイルをウォッチリストに追加',
@@ -393,10 +393,10 @@ $messages = array(
 'tog-shownumberswatching' => 'ページをウォッチしている利用者数を表示',
 'tog-oldsig' => '既存の署名:',
 'tog-fancysig' => '署名をウィキ文として扱う (自動リンクなし)',
-'tog-externaleditor' => '既定で編集に外部アプリケーションを使用(上級者向け、コンピューターに特殊な設定が必要。[//www.mediawiki.org/wiki/Manual:External_editors 詳細])',
-'tog-externaldiff' => '差分表示に外部アプリケーションを使用(上級者向け、コンピューターに特殊な設定が必要。[//www.mediawiki.org/wiki/Manual:External_editors 詳細])',
+'tog-externaleditor' => '既定で編集に外部アプリケーションを使用 (上級者向け、コンピューターに特殊な設定が必要。[//www.mediawiki.org/wiki/Manual:External_editors 詳細])',
+'tog-externaldiff' => '差分表示に外部アプリケーションを使用 (上級者向け、コンピューターに特殊な設定が必要。[//www.mediawiki.org/wiki/Manual:External_editors 詳細])',
 'tog-showjumplinks' => '利用しやすさ向上のための「{{int:jumpto}}」リンクを有効にする',
-'tog-uselivepreview' => 'ライブプレビューを使用(JavaScriptが必要)(開発中)',
+'tog-uselivepreview' => 'ライブプレビューを使用 (JavaScriptが必要) (開発中)',
 'tog-forceeditsummary' => '要約欄が空欄の場合に確認を促す',
 'tog-watchlisthideown' => 'ウォッチリストに自分の編集を表示しない',
 'tog-watchlisthidebots' => 'ウォッチリストにボットによる編集を表示しない',
@@ -1083,8 +1083,8 @@ IP アドレスは複数の利用者で共有されている場合がありま
 'updated' => '(更新)',
 'note' => "'''お知らせ:'''",
 'previewnote' => "'''これはプレビューです。'''
-変更箇所はまだ保存されていません!",
-'continue-editing' => 'ç·¨é\9b\86ã\82\92ç¶\9aè¡\8c',
+変更内容はまだ保存されていません!",
+'continue-editing' => 'ç·¨é\9b\86ã\82¨ã\83ªã\82¢ã\81«ç§»å\8b\95',
 'previewconflict' => 'これは、上の編集エリアの文章を保存した場合にどう表示されるかを示すプレビューです。',
 'session_fail_preview' => "'''申し訳ありません!セッションデータが消失したため編集を処理できませんでした。'''
 もう一度やり直してください。
@@ -1946,7 +1946,7 @@ $1',
 'upload-file-error' => '内部エラー',
 'upload-file-error-text' => '内部エラーのため、サーバー上の一時ファイル作成に失敗しました。
 [[Special:ListUsers/sysop|管理者]]に連絡してください。',
-'upload-misc-error' => 'ä¸\8dæ\98\8eã\81ªã\82¢ã\83\83ã\83\97ã\83­ã\83¼ã\83\89ã\81®ã\82¨ã\83©ã\83¼',
+'upload-misc-error' => '不明なアップロードエラー',
 'upload-misc-error-text' => 'アップロード中に不明なエラーが発生しました。
 指定した URL が正しいこととアクセスできることを確認して、もう一度試してください。
 それでもこのエラーが発生する場合は、[[Special:ListUsers/sysop|管理者]]に連絡してください。',
@@ -2116,7 +2116,7 @@ $1での[$2 ファイル解説ページ]にある説明を編集したほうが
 'shared-repo' => '共有リポジトリ',
 'shared-repo-name-wikimediacommons' => 'ウィキメディア・コモンズ',
 'filepage.css' => '/* ここに記述したCSSはファイル解説ページにて読み込まれます。また外部のクライアントウィキにも影響します */',
-'upload-disallowed-here' => 'ã\81\93ã\81®ã\83\95ã\82¡ã\82¤ã\83«ã\81«ã\81¯上書きできません。',
+'upload-disallowed-here' => 'ã\81\82ã\81ªã\81\9fã\81¯ã\81\93ã\81®ã\83\95ã\82¡ã\82¤ã\83«ã\82\92上書きできません。',
 
 # File reversion
 'filerevert' => '$1を差し戻す',
@@ -4033,8 +4033,8 @@ $5
 'watchlistedit-raw-titles' => 'ページ名:',
 'watchlistedit-raw-submit' => 'ウォッチリストを更新',
 'watchlistedit-raw-done' => 'ウォッチリストを更新しました。',
-'watchlistedit-raw-added' => '{{PLURAL:$1|$1 件のページ}}を追加しました:',
-'watchlistedit-raw-removed' => '{{PLURAL:$1|$1 件のページ}}を除去しました:',
+'watchlistedit-raw-added' => '{{PLURAL:$1|$1 ページ}}を追加しました:',
+'watchlistedit-raw-removed' => '{{PLURAL:$1|$1 ページ}}を除去しました:',
 
 # Watchlist editing tools
 'watchlisttools-view' => '関連する変更を閲覧',
index a73802f..f5531d0 100644 (file)
@@ -1943,6 +1943,8 @@ Ineggafen imazdayen : <code>$1</code> (ur d-renu acemma deg unadi inek/inem)',
 'listgrouprights' => 'Izerfan n igrawen n iseqdacen',
 'listgrouprights-summary' => 'Asebter agi yesɛa yiwen umuɣ n igrawen i sengelen deg wiki agi dɣa izerfan n wadduf i qqenen.
 Zemrent ad ilint [[{{MediaWiki:Listgrouprights-helppage}}|tilɣa nniḍen]] ɣef izerfan n yiwen.',
+'listgrouprights-key' => '*<span class="listgrouprights-granted">Izerfan sefkan</span>
+*<span class="listgrouprights-revoked">Izerfan ekkesen</span>',
 'listgrouprights-group' => 'Agraw',
 'listgrouprights-rights' => 'Izerfan',
 'listgrouprights-helppage' => 'Help:Izerfan n igrawen',
@@ -2083,6 +2085,7 @@ Tuɣalin d tadhelt :
 'delete-confirm' => 'Kkes "$1"',
 'delete-legend' => 'Ekkes',
 'historywarning' => 'Ɣur-wet : Asebter i ara temḥuḍ yesɛa amezruy s azal alemmas n $1 {{PLURAL:$1|lqem|ileqman}} :',
+'confirmdeletetext' => 'Aqlak ad mḥuḍ asebter naɣ afaylu, dɣa akkw ileqman-is iqdimen. Ilaq ad segegeḍ tigawt agi dɣa tfehemeḍ [[{{MediaWiki:Policy-url}}|ilugan n wiki]].',
 'actioncomplete' => 'Axdam yekfa',
 'actionfailed' => 'Tigawt agi texser',
 'deletedtext' => '"$1" yettumḥa.
@@ -2094,7 +2097,13 @@ Tuɣalin d tadhelt :
 'deletecomment' => 'Ayɣer',
 'deleteotherreason' => 'Taɣẓint nniḍen / taɣzint tamarnant :',
 'deletereasonotherlist' => 'Taɣẓint nniḍen',
+'deletereason-dropdown' => '* Tiɣẓinin n umḥu id t-uɣalen aṭas tikkwal
+** Asuter n useqdac
+** Akukel n izerfan umeskar
+** Asfata',
 'delete-edit-reasonlist' => 'Beddel tiɣẓinin n umḥu n usebter',
+'delete-toobig' => 'Asebter agi yesɛa amezruy ameqqṛan aṭas n ibeddilen, yugar $1 {{PLURAL:$1|lqem|ileqman}}.
+Amḥu n isebtar am wagi yesɛa akref iwakken {{SITENAME}} ur yesɛu ara arway.',
 
 # Rollback
 'rollback' => 'Semmet ibeddilen',
@@ -2488,6 +2497,8 @@ Anda tebɣiḍ tesmimeḍ "[[:$1]]" yella yagi. tebɣiḍ ad temḥuḍ iwakken
 'pageinfo-views' => 'Amḍan n timuɣliwin',
 'pageinfo-watchers' => 'Amḍan n imttekkiyen yesɛan asebter agi deg umuɣ nsen n uɛassi',
 'pageinfo-subpages-name' => 'Adu-isebtar n usebter agi',
+'pageinfo-contentpage-yes' => 'Ih',
+'pageinfo-protect-cascading-yes' => 'Ih',
 
 # Patrolling
 'markaspatrolleddiff' => 'Rcem "yettwassenqden"',
@@ -2973,6 +2984,17 @@ G leɛnaya-k sentem belli ṣaḥḥ tebɣiḍ ad tɛiwedeḍ axlaq n usebter-ag
 # Special:Version
 'version' => 'Lqem',
 'version-specialpages' => 'isebtar usligen',
+'version-software' => 'Iseɣẓanen i serkeben',
+'version-software-product' => 'Afaris',
+'version-software-version' => 'Lqem',
+'version-entrypoints' => 'Tansa URL n irden n wekcam',
+'version-entrypoints-header-entrypoint' => 'Ired n wekcam',
+'version-entrypoints-header-url' => 'Tansa URL',
+
+# Special:FilePath
+'filepath' => 'Abrid n wadduf ufaylu',
+'filepath-page' => 'Afaylu :',
+'filepath-submit' => 'Ruḥ',
 
 # Special:SpecialPages
 'specialpages' => 'isebtar usligen',
index 6aeebf5..4d79af7 100644 (file)
@@ -161,7 +161,6 @@ $messages = array(
 'qbbrowse' => 'Хэплъэн',
 'qbedit' => 'Гъэтэрэзын',
 'qbpageoptions' => 'НапэкӀуэцӀым и зэгъэзэхуэгъуэр',
-'qbpageinfo' => 'НапэкIуэцIым теухуауэ',
 'qbmyoptions' => 'Уи зэгъэзэхуэгъуэхэр',
 'qbspecialpages' => 'Специал напэкӀуэцӀхэр',
 'faq' => 'FAQ',
index 04088c4..ff6fdad 100644 (file)
@@ -158,7 +158,6 @@ $messages = array(
 'qbbrowse' => 'Browse/تصفّح',
 'qbedit' => 'ترمیم',
 'qbpageoptions' => 'ھیہ صفحہ',
-'qbpageinfo' => 'مفہوم',
 'qbmyoptions' => 'مہ صفحات',
 'qbspecialpages' => 'خاص صفحات',
 'faq' => 'عام معلومات',
index 08bf1de..0159e7e 100644 (file)
@@ -198,7 +198,6 @@ $messages = array(
 'qbbrowse' => 'Çım ra viarne',
 'qbedit' => 'Bıvurne',
 'qbpageoptions' => 'Na pele',
-'qbpageinfo' => 'Gire',
 'qbmyoptions' => 'Pelê mı',
 'qbspecialpages' => 'Pelê xısusiy',
 'faq' => 'PZP (Persê ke zaf perşinê)',
@@ -941,12 +940,12 @@ Kaberê bini ke şıma de kewti irtıbat, adresa e-postey şıma eşkera nêbena
 'rcnotefrom' => "Cêr de vurnayîşê esto ke '''$2''' ra raver  (heta '''$1''' mucnayiyo).",
 'rclistfrom' => '$1 ra hata nıka vurnaisunê newu bıasne',
 'rcshowhideminor' => '$1 vurnaisê qızkeki',
-'rcshowhidebots' => 'botê $1i',
-'rcshowhideliu' => '$1 karberê qeydbiyaey',
+'rcshowhidebots' => 'Botu $1',
+'rcshowhideliu' => 'Karberunê qeydbiyayu $1',
 'rcshowhideanons' => '$1 karberê anonimi',
 'rcshowhidepatr' => 'Vurnayışê cıyê vênıtey $1',
-'rcshowhidemine' => '$1 vurnaisê mı',
-'rclinks' => '$1 vurnaisunê peyênunê $2 rozunê<br />$3 peyênun bıasne',
+'rcshowhidemine' => 'Vurnayisanê mı $1',
+'rclinks' => 'Peyniya $2 rozu de $1 vurnayisu bıasne <br />$3',
 'diff' => 'ferq',
 'hist' => 'ver',
 'hide' => 'Bınımne',
@@ -1254,7 +1253,7 @@ Tı şikina sewiya sevekiyaena na pele bıvurnê, hema yê nae sevekiyaena qedem
 
 # Namespace form on various pages
 'namespace' => 'Caê namey:',
-'invert' => 'Weçinıtu ra qêri bıasne',
+'invert' => 'Weçinıtiso peyserki',
 'blanknamespace' => '(Ser)',
 
 # Contributions
@@ -1316,7 +1315,7 @@ Tı şikina sewiya sevekiyaena na pele bıvurnê, hema yê nae sevekiyaena qedem
 'blocklink' => 'kilıt ke',
 'unblocklink' => 'ra ke',
 'change-blocklink' => 'mani bıvurne',
-'contribslink' => 'iştıraki',
+'contribslink' => 'iştıraqi',
 'emaillink' => 'e-poste bırusne',
 'autoblocker' => 'Sıma otomatikmen kılit biy, çıke adresa sımawa \'\'IP\'\'y terefê "[[User:$1|$1]]" gurenina.
 Sebebê kılit-biyaena $1\'i: "$2"o',
index 8bd46c0..6f5d739 100644 (file)
@@ -1052,7 +1052,7 @@ IP 주소는 여러 사용자가 공유할 수 있습니다.
 'note' => "'''참고:'''",
 'previewnote' => "'''이 화면은 미리 보기입니다.'''
 편집한 내용은 아직 저장되지 않았습니다!",
-'continue-editing' => '계속 편집하기',
+'continue-editing' => '편집 영역으로 가기',
 'previewconflict' => '이 미리 보기는 저장할 때의 모습으로 위쪽 편집창의 문서를 반영합니다.',
 'session_fail_preview' => "'''세션 데이터가 없어져 편집을 저장하지 못했습니다.'''
 다시 시도하세요.
@@ -2255,6 +2255,7 @@ URL이 맞고 해당 웹사이트가 작동하는지 확인해주세요.',
 # Book sources
 'booksources' => '책 찾기',
 'booksources-search-legend' => '책 찾기',
+'booksources-isbn' => 'ISBN:',
 'booksources-go' => '찾기',
 'booksources-text' => '아래의 목록은 새 책이나 중고 책을 판매하는 바깥 사이트로, 원하는 책의 정보를 얻을 수 있습니다:',
 'booksources-invalid-isbn' => '입력한 ISBN이 잘못된 것으로 보입니다. 원본과 대조해 보세요.',
index ec9c19b..b2ea2a7 100644 (file)
@@ -135,7 +135,6 @@ $messages = array(
 'qbbrowse' => 'Сереп сал',
 'qbedit' => 'Оңдоо',
 'qbpageoptions' => 'Бул барак',
-'qbpageinfo' => 'Контекст',
 'qbmyoptions' => 'Барактарым',
 'qbspecialpages' => 'Атайын барактар',
 'faq' => 'КБС',
index 3cc772c..8ee93d7 100644 (file)
@@ -864,7 +864,7 @@ Denkt drun datt eegen .css an .js Säiten e kleng geschriwwenen Titel benotzen,
 'note' => "'''Notiz:'''",
 'previewnote' => "'''Denkt drun datt dëst nëmmen eng net gespäichert Versioun ass.'''
 Är Ännerunge sinn nach net gespäichert!",
-'continue-editing' => 'Weider änneren',
+'continue-editing' => "Gitt weider an de Beräich fir z'änneren",
 'previewconflict' => 'Dir gesitt an dem ieweschten Textfeld wéi den Text ausgesi wäert, wann Dir späichert.',
 'session_fail_preview' => "'''Är Ännerung konnt net gespäichert gi well d'Date vun Ärer Sessioun verluergaange sinn.
 Versicht et w.e.g. nach eng Kéier.
index d6e15d9..c5cb833 100644 (file)
@@ -148,7 +148,6 @@ $messages = array(
 'qbbrowse' => 'Килигун',
 'qbedit' => 'Дегишарун',
 'qbpageoptions' => 'Ччинин низамарунар',
-'qbpageinfo' => 'Ччиникай малумат',
 'qbmyoptions' => 'Зи ччинар',
 'qbspecialpages' => 'Кьетlен хъувун',
 'faq' => 'Фад-фад гузвай жузунар (ФГЖ)',
@@ -523,7 +522,7 @@ $messages = array(
 'revertmerge' => 'Ччара авун',
 
 # Diffs
-'history-title' => '$1  -  масакIавилерин тарих',
+'history-title' => 'Masak\'avilerin q\'isa "$1"',
 'lineno' => 'ЦIар $1:',
 'compareselectedversions' => 'Хкягъай жуьреяр гекъигун',
 'editundo' => 'гьич авун',
index c431b99..0638a5d 100644 (file)
@@ -1,5 +1,5 @@
 <?php
-/** Lushai (Mizo ţawng)
+/** Mizo (Mizo ţawng)
  *
  * See MessagesQqq.php for message documentation incl. usage of parameters
  * To improve a translation please visit http://translatewiki.net
index 163bc26..9f89e5c 100644 (file)
@@ -385,7 +385,7 @@ $messages = array(
 'tog-watchlisthideliu' => 'Скриј ги уредувањата на најавените корисници во списокот на набљудувања',
 'tog-watchlisthideanons' => 'Скриј ги уредувањата од анонимни корисници во списокот на набљудувања',
 'tog-watchlisthidepatrolled' => 'Скриј испатролирани уредувања од мојот список на набљудувања',
-'tog-ccmeonemails' => 'Ð\98Ñ\81пÑ\80аÑ\9cаÑ\98 Ð¼Ð¸ ÐºÐ¾Ð¿Ð¸Ð¸ Ð¾Ð´ Ðµ-поÑ\80акиÑ\82е Ñ\88Ñ\82о Ð³Ð¸ Ð¿Ñ\80аÑ\9cам Ð´Ð¾ Ð´Ñ\80Ñ\83ги корисници',
+'tog-ccmeonemails' => 'Ð\98Ñ\81пÑ\80аÑ\9cаÑ\98 Ð¼Ð¸ Ð¼Ð¾Ð¸ Ð¿Ñ\80имеÑ\80оÑ\86и Ð¾Ð´ Ð¿Ð¸Ñ\81маÑ\82а Ñ\88Ñ\82о Ð³Ð¸ Ð¿Ñ\80аÑ\9cам Ð½Ð° Ð´Ñ\80Ñ\83гиÑ\82е корисници',
 'tog-diffonly' => 'Не ја покажувај содржината на страницата под разликите',
 'tog-showhiddencats' => 'Прикажи скриени категории',
 'tog-noconvertlink' => 'Оневозможи претворање на наслов на врска',
@@ -1057,7 +1057,7 @@ $2
 'note' => "'''Напомена:'''",
 'previewnote' => "'''Имајте предвид дека ова е само преглед.'''
 Промените сè уште не се зачувани!",
-'continue-editing' => 'Ð\9fÑ\80одолжеÑ\82е Ñ\81о уредување',
+'continue-editing' => 'Ð\9eди Ð½Ð° Ð¿Ð¾Ð»ÐµÑ\82о Ð·Ð° уредување',
 'previewconflict' => 'Овој преглед прикажува како ќе изгледа текстот внесен во горниот дел откако ќе се зачува страницата.',
 'session_fail_preview' => "'''Жалиме! Не можевме да го обработиме вашето уредување поради загуба на сесиски податоци.'''
 Обидете се повторно.
index fc159a1..cf4693c 100644 (file)
@@ -1001,7 +1001,7 @@ $1 ആണ് ഈ തടയൽ നടത്തിയത്. ''$2'' എന്ന
 'note' => "'''പ്രത്യേക ശ്രദ്ധയ്ക്ക്:'''",
 'previewnote' => "'''ഇതൊരു പ്രിവ്യൂ മാത്രമാണെന്ന് ഓർക്കുക.'''
 താങ്കൾ വരുത്തിയ മാറ്റങ്ങൾ ഇതുവരെ സേവ് ചെയ്തിട്ടില്ല!",
-'continue-editing' => 'തിരàµ\81à´¤àµ\8dതൽ à´¤àµ\81à´\9fà´°ുക',
+'continue-editing' => 'തിരàµ\81à´¤àµ\8dതൽ à´®àµ\87à´\96ലയിലàµ\87à´¯àµ\8dà´\95àµ\8dà´\95àµ\8d à´ªàµ\8bà´µുക',
 'previewconflict' => 'ഈ പ്രിവ്യൂവിൽ മുകളിലെ ടെക്സ്റ്റ് ഏരിയയിലുള്ള എഴുത്ത് മാത്രമാണ് കാട്ടുന്നത്, സേവ്‌ ചെയ്യാൻ താങ്കൾ തീരുമാനിച്ചാൽ അത് സേവ് ആകുന്നതാണ്.',
 'session_fail_preview' => "'''ക്ഷമിക്കണം! സെഷൻ ഡാറ്റ നഷ്ടപ്പെട്ടതിനാൽ താങ്കളുടെ തിരുത്തലിന്റെ തുടർപ്രക്രിയ നടത്തുവാൻ സാധിച്ചില്ല.''' 
 ദയവായി വീണ്ടും ശ്രമിക്കൂ.
@@ -3120,6 +3120,9 @@ $1',
 'pageinfo-redirectsto-info' => 'വിവരം',
 'pageinfo-contentpage' => 'ഉള്ളടക്ക താളായി എണ്ണുന്നവ',
 'pageinfo-contentpage-yes' => 'അതെ',
+'pageinfo-protect-cascading' => 'സംരക്ഷണങ്ങൾ ഇവിടെ നിന്ന് നിർഝരിതപ്പെടുത്തുന്നു',
+'pageinfo-protect-cascading-yes' => 'അതെ',
+'pageinfo-protect-cascading-from' => 'സംരക്ഷണങ്ങൾ നിർഝരിതപ്പെടുത്തുന്നത്',
 
 # Skin names
 'skinname-standard' => 'സാർവത്രികം',
index 1e04a18..394b3b8 100644 (file)
@@ -873,7 +873,7 @@ Masukan log sekatan terakhir disediakan di bawah sebagai rujukan:',
 'note' => "'''Catatan:'''",
 'previewnote' => "'''Ingatlah bahawa ini hanya pralihat.'''
 Perubahan anda belum disimpan!",
-'continue-editing' => 'Teruskan menyunting',
+'continue-editing' => 'Pergi ke tempat menyunting',
 'previewconflict' => 'Paparan ini merupakan teks di bahagian atas dalam kotak sunting teks. Teks ini akan disimpan sekiranya anda memilih berbuat demikian.',
 'session_fail_preview' => "'''Kami tidak dapat memproses suntingan anda kerana kehilangan data sesi. Sila cuba lagi. Jika masalah ini berlanjutan, [[Special:UserLogout|log keluar]] dahulu, kemudian log masuk sekali lagi.'''",
 'session_fail_preview_html' => "'''Kami tidak dapat memproses suntingan anda kerana kehilangan data sesi.'''
index 26d0596..b213ccf 100644 (file)
@@ -1901,7 +1901,7 @@ Den kan ikke sikkerhetskontrolleres.',
 'uploadstash-summary' => 'Denne siden gir tilgang til filer som har blitt lastet opp (eller er i ferd med å bli lastet opp) men som ennå ikke er publisert til wikien. Disse filene er ikke synlige for andre enn brukeren som lastet dem opp.',
 'uploadstash-clear' => 'Fjern stashede filer',
 'uploadstash-nofiles' => 'Du har ingen stashede filer.',
-'uploadstash-badtoken' => 'Utføringen av den handlingen var mislykket, kanskje fordi dine redigeringsrettigheter har utløpt. Prøv igjen.',
+'uploadstash-badtoken' => 'Utføringen av den handlingen var mislykket, kanskje fordi redigeringsrettighetene dine har utløpt. Prøv igjen.',
 'uploadstash-errclear' => 'Fjerning av filene var mislykket.',
 'uploadstash-refresh' => 'Oppdater listen over filer',
 'invalid-chunk-offset' => 'Ugyldig delforskyvning',
index 51f7ad9..af105d5 100644 (file)
@@ -1068,7 +1068,7 @@ Uw eigen .css- en .js-pagina's beginnen met een kleine letter, bijvoorbeeld {{ns
 'note' => "'''Opmerking:'''",
 'previewnote' => "'''Let op: dit is een controlepagina.'''
 Uw tekst is niet opgeslagen!",
-'continue-editing' => 'Doorgaan met bewerken',
+'continue-editing' => 'Naar het bewerkingsvenster gaan',
 'previewconflict' => 'Deze voorvertoning geeft aan hoe de tekst in het bovenste veld eruit ziet als u deze opslaat.',
 'session_fail_preview' => "'''Uw bewerking is niet verwerkt, omdat de sessiegegevens verloren zijn gegaan.
 Probeer het opnieuw.
index 110cc1f..e5f674e 100644 (file)
@@ -578,7 +578,7 @@ $1',
 'youhavenewmessages' => 'Du har $1 ($2).',
 'newmessageslink' => 'nye meldingar',
 'newmessagesdifflink' => 'sjå skilnad',
-'youhavenewmessagesfromusers' => 'Du har $1 frå {{PLURAL:$3|ein annan bruker| $3 brukarar}} ($2).',
+'youhavenewmessagesfromusers' => 'Du har $1 frå {{PLURAL:$3|ein annan brukar| $3 brukarar}} ($2).',
 'youhavenewmessagesmanyusers' => 'Du har $1 frå mange brukarar ($2).',
 'newmessageslinkplural' => '{{PLURAL:$1|ei ny melding|nye meldingar}}',
 'newmessagesdifflinkplural' => 'siste {{PLURAL:$1|endringa|endringane}}',
@@ -1212,9 +1212,10 @@ Du har ikkje tilgang til henne.',
 Sjekk gjerne loggføringa.',
 'revdelete-only-restricted' => 'Feil under gøyming av objektet datert $2 $1: du kan ikkje gøyma objekt for administratorar utan å i tillegg velja eit av dei andre visingsvala.',
 'revdelete-reason-dropdown' => '*Vanlege grunnar til sletting
-** Brot på opphavsrettar
-** Ikkje høveleg personleg informasjon
-** Mogleg falskt sladder',
+** Brot på opphavsrett
+** Kommentar eller personleg informasjon som ikkje høver seg
+** Brukarnamn som ikkje høver seg
+** Mogeleg falskt sladder',
 'revdelete-otherreason' => 'Anna årsak, eller tilleggsårsak:',
 'revdelete-reasonotherlist' => 'Annan grunn',
 'revdelete-edit-reasonlist' => 'Endre grunnar til sletting',
@@ -1256,7 +1257,7 @@ Pass på at den nye sida også har innhald frå den innfletta sida.',
 
 # Diffs
 'history-title' => '$1: Versjonshistorikk',
-'difference-title' => '$1: Skilnad mellom versjonar',
+'difference-title' => 'Skilnad mellom versjonar av «$1»',
 'difference-title-multipage' => '$1 og $2: Skilnad mellom sidene',
 'difference-multipage' => '(Skilnad mellom sider)',
 'lineno' => 'Line $1:',
@@ -1265,6 +1266,10 @@ Pass på at den nye sida også har innhald frå den innfletta sida.',
 'editundo' => 'angre',
 'diff-multi' => '({{PLURAL:$1|Éin mellomversjon|$1 mellomversjonar}} frå {{PLURAL:$2|éin brukar|$2 brukarar}} er ikkje {{PLURAL:$1|vist|viste}})',
 'diff-multi-manyusers' => '({{PLURAL:$1|Ein mellomversjon|$1 mellomversjonar}} av meir enn $2 {{PLURAL:$2|brukar|brukarar}}  er ikkje {{PLURAL:$1|vist|viste}})',
+'difference-missing-revision' => '{{PLURAL:$2|Éin versjon|$2 versjonar}} av skilnaden ($1) vart ikkje funne.
+
+Dette skriv seg som oftast frå at ein har fylgd ei forelda versjonslenkje til ei side som er sletta.
+Detaljar kan ein finna i [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} sletteloggen].',
 
 # Search results
 'searchresults' => 'Søkjeresultat',
@@ -1425,6 +1430,7 @@ Dette kan ikkje tilbakestillast.',
 'yourrealname' => 'Verkeleg namn:',
 'yourlanguage' => 'Språk:',
 'yourvariant' => 'Språkvariant for innhald:',
+'prefs-help-variant' => 'Varianten eller ortografien som du føretrekkjer at innhaldet i wikien vert vist på.',
 'yournick' => 'Signatur:',
 'prefs-help-signature' => 'Kommentarar på diskusjonssider bør alltid signerast med «<nowiki>~~~~</nowiki>», som vil konverterast til signaturen din med tidspunkt.',
 'badsig' => 'Ugyldig råsignatur, sjekk HTML-kodinga.',
@@ -1816,6 +1822,7 @@ $1',
 'backend-fail-synced' => 'Fila «$1» er i ei inkonsistent stode i dei interne lagringsbaksystema',
 'backend-fail-connect' => 'Kunne ikkje kopla til filbaksystemet «$1».',
 'backend-fail-internal' => 'Ein ukjend feil oppstod i lagringsbaksystemet «$1».',
+'backend-fail-batchsize' => 'Baksystemet vart gjeve ei gruppe med $1 {{PLURAL:$1|filoperasjon|filoperasjonar}}; grensa er $2 {{PLURAL:$2|operasjon|operasjonar}}.',
 
 # File journal errors
 'filejournal-fail-dbconnect' => 'Kunne ikkje kopla til journaldatabasen for lagringsbaksystemet «$1».',
@@ -1839,6 +1846,11 @@ $1',
 Ho kan ikkje tryggingskontrollerast.',
 
 # Special:UploadStash
+'uploadstash' => 'Lasta opp løynd samling',
+'uploadstash-summary' => 'Denne sida gjev tilgang til filer som er opplasta (eller i ferd med å verta det), men som ikkje er publiserte til wikien. Desse filene er ikkje synlege for andre enn opplastaren.',
+'uploadstash-clear' => 'Fjerna filer i den løynde samlinga',
+'uploadstash-nofiles' => 'Du har ingen filer i den løynde samlinga.',
+'uploadstash-badtoken' => 'Utføringa av handlinga lukkast ikkje; kan henda av di endringsrettane dine har gått ut. Freista om att.',
 'uploadstash-errclear' => 'Fjerning av filene var mislykka.',
 'uploadstash-refresh' => 'Oppdater fillista',
 
@@ -1859,6 +1871,7 @@ Berre tilgjenge til filer er tillete.',
 Denne wikien er sett opp som ein ålmennt tilgjengeleg wiki.
 For best tryggleik, er img_auth.php sett ut av funksjon.',
 'img-auth-noread' => 'Brukaren har ikkje rettar til å lesa «$1».',
+'img-auth-bad-query-string' => 'URL-en har ein ugild spørjestreng.',
 
 # HTTP errors
 'http-invalid-url' => 'Ugyldig URL: $1',
@@ -1928,6 +1941,10 @@ Ei [[Special:WhatLinksHere/$2|fullstendig liste]] er tilgjengeleg.',
 Sjå [$2 filskildringssida] for meir informasjon.',
 'sharedupload-desc-here' => 'Denne fila er frå $1 og kan verta nytta av andre prosjekt.
 Skildringa frå [$2 filskildringssida] der er vist nedanfor.',
+'sharedupload-desc-edit' => 'Fila er frå $1 og kan vera nytta på andre prosjekt.
+Du vil kan henda endra skildringa på [$2 filskildringssida] hennar der.',
+'sharedupload-desc-create' => 'Fila er frå $1 og kan vera nytta på andre prosjekt.
+Du vil kan henda endra skildringa på [$2 filskildringssida] hennar der.',
 'filepage-nofile' => 'Det finst ikkje noka fil med dette namnet.',
 'filepage-nofile-link' => 'Inga fil med dette namnet finst, men du kan [$1 lasta ho opp].',
 'uploadnewversion-linktext' => 'Last opp ny versjon av denne fila',
@@ -2004,6 +2021,7 @@ Skildringa frå [$2 filskildringssida] der er vist nedanfor.',
 'statistics-edits' => 'Endringar sidan {{SITENAME}} vart oppretta',
 'statistics-edits-average' => 'Gjennomsnittleg tal på endringar per side',
 'statistics-views-total' => 'Totalt visningstal',
+'statistics-views-total-desc' => 'Visingar av sider som ikkje finst og spesialsider er ikkje tekne med',
 'statistics-views-peredit' => 'Visingar per endring',
 'statistics-users' => 'Registrerte [[Special:ListUsers|brukarar]]',
 'statistics-users-active' => 'Aktive brukarar',
@@ -2058,6 +2076,8 @@ Ei side vert handsama som ei fleirtydingsside om ho nyttar ein mal som er lenkja
 'wantedpages' => 'Etterspurde sider',
 'wantedpages-badtitle' => 'Ugyldig tittel mellom resultata: $1',
 'wantedfiles' => 'Etterspurde filer',
+'wantedfiletext-cat' => 'Desse filene er nytta men finst ikkje. Filer frå utannettstadlege samlingar kan vera lista opp sjølv om dei finst. Slike falske positivar vert <del>strokne ut</del>. Sider som nyttar filer som ikkje finst vert lista opp i [[:$1]].',
+'wantedfiletext-nocat' => 'Desse filene er nytta men finst ikkje. Filer frå utannettstadlege samlingar kan vera lista opp sjølv om dei finst. Slike falske positivar vert <del>strokne ut</del>.',
 'wantedtemplates' => 'Etterspurde malar',
 'mostlinked' => 'Sidene med flest lenkjer til seg',
 'mostlinkedcategories' => 'Mest brukte kategoriar',
@@ -2988,6 +3008,7 @@ Vitja [//www.mediawiki.org/wiki/Localisation MediaWiki Localisation] og [//trans
 
 # Info page
 'pageinfo-title' => 'Informasjon om «$1»',
+'pageinfo-not-current' => 'Informasjon vert berre vist for den gjeldande versjonen.',
 'pageinfo-header-basic' => 'Grunnleggjande informasjon',
 'pageinfo-header-edits' => 'Endringshistorikk',
 'pageinfo-header-restrictions' => 'Sidevern',
@@ -3015,6 +3036,9 @@ Vitja [//www.mediawiki.org/wiki/Localisation MediaWiki Localisation] og [//trans
 'pageinfo-magic-words' => '{{PLURAL:$1|Trylleord}} ($1)',
 'pageinfo-hidden-categories' => '{{PLURAL:$1|Løynd kategori|Løynde kategoriar}} ($1)',
 'pageinfo-templates' => '{{PLURAL:$1|Inkludert mal|Inkluderte malar}} ($1)',
+'pageinfo-toolboxlink' => 'Sideinformasjon',
+'pageinfo-redirectsto' => 'Omdirigerer til',
+'pageinfo-redirectsto-info' => 'info',
 'pageinfo-contentpage' => 'Tald som ei innhaldsside',
 'pageinfo-contentpage-yes' => 'Ja',
 'pageinfo-protect-cascading' => 'Djupvern byrjar her',
index 89c91c4..3b88424 100644 (file)
@@ -3016,6 +3016,8 @@ MediaWiki ବ୍ୟବହାର କରି [[Special:Import|ପୃଷ୍ଠା 
 'pageinfo-watchers' => 'ଦେଖଣାହାରି ସଂଖ୍ୟା',
 'pageinfo-edits' => 'ସମ୍ପାଦନା ସଂଖ୍ୟା',
 'pageinfo-authors' => 'ନିଆରା ଲେଖକଙ୍କ ସଂଖ୍ୟା',
+'pageinfo-contentpage-yes' => 'ହଁ',
+'pageinfo-protect-cascading-yes' => 'ହଁ',
 
 # Patrolling
 'markaspatrolleddiff' => 'ଜଗାଯାଇଅଛି ବୋଲି ଚିହ୍ନିତ କରାଗଲା',
index c5bd9e6..9060ccf 100644 (file)
@@ -231,7 +231,6 @@ Manual:External_editors ਹੋਰ ਜਾਣਕਾਰੀ।])',
 'qbbrowse' => 'ਬਰਾਊਜ਼',
 'qbedit' => 'ਸੋਧ',
 'qbpageoptions' => 'ਇਹ ਸਫ਼ਾ',
-'qbpageinfo' => 'ਭਾਗ',
 'qbmyoptions' => 'ਮੇਰੇ ਸਫ਼ੇ',
 'qbspecialpages' => 'ਖ਼ਾਸ ਸਫ਼ਾ',
 'faq' => 'ਅਕਸਰ ਪੁੱਛੇ ਜਾਣ ਵਾਲ਼ੇ ਸਵਾਲ',
index 31ea8bf..add4524 100644 (file)
@@ -990,7 +990,7 @@ Strony użytkownika zawierające CSS i JavaScript powinny zaczynać się małą
 'note' => "'''Uwaga:'''",
 'previewnote' => "'''To jest tylko podgląd'''
 Zmiany nie zostały jeszcze zapisane!",
-'continue-editing' => 'Kontynuuj edycję',
+'continue-editing' => 'Przejdź do pola edycji',
 'previewconflict' => 'Podgląd odnosi się do tekstu z górnego pola edycji. Tak będzie wyglądać strona, jeśli zdecydujesz się ją zapisać.',
 'session_fail_preview' => "'''Uwaga! Serwer nie może przetworzyć tej edycji z powodu utraty danych sesji.
 Spróbuj jeszcze raz.
@@ -1072,6 +1072,15 @@ Zdaje się, że została skasowana.',
 'edit-already-exists' => 'Nie udało się stworzyć nowej strony.
 Strona już istnieje.',
 'defaultmessagetext' => 'Domyślny tekst komunikatu',
+'content-failed-to-parse' => 'Format zawartości typu $2 (dla modelu: $1) nieprawidłowy: $3',
+'invalid-content-data' => 'Zawartość strony zawiera nieprawidłowe dane',
+'content-not-allowed-here' => 'Zawartość tego typu ($1) nie jest dozwolona na stronie [[$2]]',
+
+# Content models
+'content-model-wikitext' => 'wikitekst',
+'content-model-text' => 'zwykły tekst',
+'content-model-javascript' => 'JavaScript',
+'content-model-css' => 'CSS',
 
 # Parser/template warnings
 'expensive-parserfunction-warning' => 'Uwaga! Ta strona zawiera zbyt wiele wywołań złożonych obliczeniowo funkcji parsera.
@@ -1987,7 +1996,7 @@ Być może zechcesz zmienić opis na tej [$2 stronie opisu pliku].',
 'uploadnewversion-linktext' => 'Załaduj nowszą wersję tego pliku',
 'shared-repo-from' => 'z $1',
 'shared-repo' => 'współdzielone zasoby',
-'upload-disallowed-here' => 'Niestety, nie możesz nadpisać tego pliku.',
+'upload-disallowed-here' => 'Nie możesz nadpisać tego pliku.',
 
 # File reversion
 'filerevert' => 'Przywracanie $1',
@@ -2529,8 +2538,8 @@ Możesz mieć zły link lub wersja mogła zostać odtworzona lub usunięta z arc
 'undeletedrevisions' => 'odtworzono {{PLURAL:$1|1 wersję|$1 wersje|$1 wersji}}',
 'undeletedrevisions-files' => 'odtworzono $1 {{PLURAL:$1|wersję|wersje|wersji}} i $2 {{PLURAL:$2|plik|pliki|plików}}',
 'undeletedfiles' => 'odtworzył $1 {{PLURAL:$1|plik|pliki|plików}}',
-'cannotundelete' => 'Odtworzenie nie powiodło się.
-Ktoś inny prawdopodobnie odtworzył już tę stronę.',
+'cannotundelete' => 'Odtworzenie nie powiodło się:
+$1',
 'undeletedpage' => "'''Odtworzono stronę $1.'''
 
 Zobacz [[Special:Log/delete|rejestr usunięć]], jeśli chcesz przejrzeć ostatnie operacje usuwania i odtwarzania stron.",
@@ -2836,6 +2845,7 @@ Strony nie można przenieść na nią samą.',
 'immobile-target-namespace-iw' => 'Link interwiki jest nieprawidłowym tytułem, pod który miałaby być przeniesiona strona.',
 'immobile-source-page' => 'Tej strony nie można przenieść.',
 'immobile-target-page' => 'Nie można przenieść pod wskazany tytuł.',
+'bad-target-model' => 'Strona docelowa używa innego modelu zawartości. Konwersja $1 → $2 nie jest możliwa.',
 'imagenocrossnamespace' => 'Nie można przenieść grafiki do przestrzeni nazw nie przeznaczonej dla grafik',
 'nonfile-cannot-move-to-file' => 'Nie można przenieść obiektu nie będącego plikiem do przestrzeni nazw „{{ns:file}}“',
 'imagetypemismatch' => 'Nowe rozszerzenie nazwy pliku jest innego typu niż zawartość',
@@ -3095,6 +3105,7 @@ Najprawdopodobniej zostało to spowodowane przez link do zewnętrznej strony int
 
 # Info page
 'pageinfo-title' => 'Informacje o „$1“',
+'pageinfo-not-current' => 'Informacje mogą być wyświetlane tylko dla najnowszej wersji strony.',
 'pageinfo-header-basic' => 'Podstawowe informacje',
 'pageinfo-header-edits' => 'Historia edycji',
 'pageinfo-header-restrictions' => 'Zmień zabezpieczenie',
@@ -3122,6 +3133,14 @@ Najprawdopodobniej zostało to spowodowane przez link do zewnętrznej strony int
 'pageinfo-magic-words' => 'Magiczne {{PLURAL:$1|słowo|słowa|słowa}} ($1)',
 'pageinfo-hidden-categories' => '{{PLURAL:$1|Ukryta kategoria|Ukryte kategorie|Ukryte kategorie}} ($1)',
 'pageinfo-templates' => 'Wykorzystywan{{PLURAL:$1|y szablon|e szablony}} ($1)',
+'pageinfo-toolboxlink' => 'Informacje o tej stronie',
+'pageinfo-redirectsto' => 'Przekierowuje na',
+'pageinfo-redirectsto-info' => 'informacje',
+'pageinfo-contentpage' => 'Liczona jako artykuł',
+'pageinfo-contentpage-yes' => 'Tak',
+'pageinfo-protect-cascading' => 'Zabezpieczona z włączoną opcją dziedziczenia',
+'pageinfo-protect-cascading-yes' => 'Tak',
+'pageinfo-protect-cascading-from' => 'Zabezpieczenie dziedziczone z',
 
 # Skin names
 'skinname-standard' => 'Standardowa',
@@ -3717,6 +3736,7 @@ Kod zawarty w linku straci ważność $4.',
 # Scary transclusion
 'scarytranscludedisabled' => '[Transkluzja przez interwiki jest wyłączona]',
 'scarytranscludefailed' => '[Pobranie szablonu dla $1 nie powiodło się]',
+'scarytranscludefailed-httpstatus' => '[Pobranie szablonu dla $1 nie powiodło się: HTTP $2]',
 'scarytranscludetoolong' => '[zbyt długi adres URL]',
 
 # Delete conflict
index 32a1c50..288767e 100644 (file)
@@ -3197,7 +3197,7 @@ J'àutri a saran stërmà coma stàndard.
 'exif-lightsource-3' => 'Lus al tungsten (a incandessensa)',
 'exif-lightsource-4' => 'Lòsna',
 'exif-lightsource-9' => 'Temp bel',
-'exif-lightsource-10' => 'Temp an-nivolà',
+'exif-lightsource-10' => 'Temp nìvol',
 'exif-lightsource-11' => 'Ombra',
 'exif-lightsource-12' => 'Fluoressensa tipo lus dël dì (D 5700 – 7100K)',
 'exif-lightsource-13' => 'Fluoressensa bianca për ël dì (N 4600 – 5400K)',
@@ -3210,15 +3210,15 @@ J'àutri a saran stërmà coma stàndard.
 'exif-lightsource-21' => 'Anluminant D65',
 'exif-lightsource-22' => 'Anluminant D75',
 'exif-lightsource-23' => 'Anluminant D50',
-'exif-lightsource-24' => 'Làmpada da studio ISO al tungsten',
-'exif-lightsource-255' => "tra sorgiss d'anluminassion",
+'exif-lightsource-24' => 'Làmpada da studi ISO al tungsten',
+'exif-lightsource-255' => "Àutra sorgiss d'anluminassion",
 
 # Flash modes
-'exif-flash-fired-0' => "Ël flash a l'é pa scatà",
-'exif-flash-fired-1' => 'Flash scatà',
-'exif-flash-return-0' => "Gnun-e fonsion ëd rilevassion dl'artorn ëd lë stroboscòpi",
-'exif-flash-return-2' => "lus stoboscòpica d'artorn pa arlevà",
-'exif-flash-return-3' => "lus stroboscòpica d'artorn arlevà",
+'exif-flash-fired-0' => "La lòsna a l'é nen ëscatà",
+'exif-flash-fired-1' => "La lòsna a l'ha scatà",
+'exif-flash-return-0' => "gnun ëstroboscòpi a dà andaré na fonsion d'artrovament",
+'exif-flash-return-2' => "lë stoboscòpi a arleva gnun-a lus d'artorn",
+'exif-flash-return-3' => "lë stroboscòpi a l'ha arlevà n'artorn ëd lus",
 'exif-flash-mode-1' => 'scat dël flash sforsà',
 'exif-flash-mode-2' => 'eliminassion dël flash sforsà',
 'exif-flash-mode-3' => 'manera automàtica',
index aaee1a5..bde138f 100644 (file)
@@ -3147,6 +3147,7 @@ Este bloqueio foi provavelmente causado por um link para um site externo que con
 'pageinfo-recent-authors' => 'Número recente de autores distintos',
 'pageinfo-magic-words' => '{{PLURAL:$1|Palavra mágica|Palavras mágicas}} ($1)',
 'pageinfo-hidden-categories' => '{{PLURAL:$1|Categoria oculta|Categorias ocultas}} ($1)',
+'pageinfo-toolboxlink' => 'Informações da página',
 
 # Skin names
 'skinname-standard' => 'Clássico',
index 649fa98..3610f91 100644 (file)
@@ -3111,6 +3111,16 @@ Tal bloqueio foi provavelmente causado por uma ligação para um ''website'' ext
 'pageinfo-authors' => 'Número total de autores distintos',
 'pageinfo-recent-edits' => 'Número de edições recentes (nos últimos $1)',
 'pageinfo-recent-authors' => 'Número recente de autores distintos',
+'pageinfo-magic-words' => '{{PLURAL:$1|Palavra mágica|Palavras mágicas}} ($1)',
+'pageinfo-hidden-categories' => '{{PLURAL:$1|Categoria oculta|Categorias ocultas}} ($1)',
+'pageinfo-templates' => '{{PLURAL:$1|predefinição transcluída|predefinições transcluídas}}',
+'pageinfo-toolboxlink' => 'Informações da página',
+'pageinfo-redirectsto' => 'Redirecionar para',
+'pageinfo-redirectsto-info' => 'informações',
+'pageinfo-contentpage' => 'Contado como uma página de conteúdo',
+'pageinfo-contentpage-yes' => 'Sim',
+'pageinfo-protect-cascading' => 'Proteção em cascata ativada',
+'pageinfo-protect-cascading-yes' => 'Sim',
 
 # Skin names
 'skinname-standard' => 'Clássico',
@@ -3124,7 +3134,7 @@ Tal bloqueio foi provavelmente causado por uma ligação para um ''website'' ext
 
 # Patrolling
 'markaspatrolleddiff' => 'Marcar como patrulhada',
-'markaspatrolledtext' => 'Marcar esta página como verificada',
+'markaspatrolledtext' => 'Marcar esta página como patrulhada',
 'markedaspatrolled' => 'Marcado como verificado',
 'markedaspatrolledtext' => 'A revisão selecionada de [[:$1]] foi marcada como patrulhada.',
 'rcpatroldisabled' => 'Edições verificadas nas Mudanças Recentes desativadas',
index 76b726f..82cf299 100644 (file)
@@ -3641,6 +3641,7 @@ Start with a lowercase letter, unless the first word is “SVG”.',
 
 Start with a lowercase letter, unless the first word is “SVG”.',
 'show-big-image' => 'Displayed under an image at the image description page, when it is displayed smaller there than it was uploaded.',
+'show-big-image-other' => 'Message shown under the image description page thumbnail, next to {{msg-mw|show-big-image-preview}}, if the image is in high resolution.',
 'show-big-image-size' => '
 Parameters:
 * $1 is the width of the image(s) in pixels.
index afb3cc7..844b84a 100644 (file)
@@ -273,7 +273,7 @@ $messages = array(
 'tog-hidepatrolled' => "Patrullasqa llamk'apusqakunata ñaqha hukchasqapi pakay",
 'tog-newpageshidepatrolled' => "Patrullasqa llamk'apusqakunata musuq p'anqakunapi pakay",
 'tog-extendwatchlist' => "Watiqana sutisuyuta tukuy rurachinalla hukchaykunaman mast'ay, ama lliwmanta aswan ñaqhallachu",
-'tog-usenewrc' => "Sananchasqa ñaqha hukchasqakuna (JavaScript nisqallawanmi llamk'an)",
+'tog-usenewrc' => "Huñu hukchasqakuna p'anqallakama ñaqha hukchasqakunapi watiqasqakunapipas (JavaScript nisqallawanmi llamk'an)",
 'tog-numberheadings' => "Uma siq'ikunata kikinmanta yupay",
 'tog-showtoolbar' => "Llamk'apuna sillwita rikuchiy",
 'tog-editondblclick' => "P'anqakunata llamk'apuy iskaylla ñit'iywan (JavaScript)",
@@ -281,17 +281,17 @@ $messages = array(
 'tog-editsectiononrightclick' => "Rakirilla llamk'apuyta saqillay paña butunta rakirip sutinpi ñit'ispa (JavaScript)",
 'tog-showtoc' => "Yuyarina wachuchasqata rikuchiy (kimsamanta aswan uma siq'iyuq p'anqakunapaq)",
 'tog-rememberpassword' => "Ruraqpa sutiyta yaykuna rimaytapas yuyaykuy kay llika wamp'unapi ({{PLURAL:$1|huk p'unchawkama|$1 p'unchawkama}})",
-'tog-watchcreations' => "Qallarisqay p'anqakunata watiqay.",
-'tog-watchdefault' => "Hukchasqay p'anqakunata watiqay",
-'tog-watchmoves' => "Astasqay p'anqakunata watiqay",
-'tog-watchdeletion' => "Qullusqay p'anqakunata watiqay",
+'tog-watchcreations' => "Qallarisqay p'anqakunata churkusqay willañiqikunatapas watiqay",
+'tog-watchdefault' => "Hukchasqay p'anqakunata willañiqikunatapas watiqay",
+'tog-watchmoves' => "Astasqay p'anqakunata willañiqikunatapas watiqay",
+'tog-watchdeletion' => "Qullusqay p'anqakunata willañiqikunatapas watiqay",
 'tog-minordefault' => 'Tukuy hukchasqakunata kikinmanta aslla nispa sananchay',
 'tog-previewontop' => "Rikch'ay qhawana ñawpaqman, ama qhipanpi kachunchu",
 'tog-previewonfirst' => "Manaraq llamk'apuspa rikch'ayta qhaway",
 'tog-nocache' => "Llika wamp'unap ''cache'' nisqa paki hallch'anman ama niy",
-'tog-enotifwatchlistpages' => "Watiqasqay p'anqa hukchasqa kaptinqa, e-chaskita kachamuway",
+'tog-enotifwatchlistpages' => "Watiqasqay p'anqa icha willañiqi hukchasqa kaptinqa, e-chaskita kachamuway",
 'tog-enotifusertalkpages' => "Rimachinay p'anqa hukchasqa kaptinqa, e-chaskita kachamuway",
-'tog-enotifminoredits' => "P'anqapi uchuy hukchasqamantapas willawaspa e-chaskita kachamuway",
+'tog-enotifminoredits' => "P'anqapi icha willañiqipi uchuy hukchasqamantapas willawaspa e-chaskita kachamuway",
 'tog-enotifrevealaddr' => 'E-chaski imamaytayta rikuchiy willamuwanayki e-chaskikunapi',
 'tog-shownumberswatching' => "Rikuchiy hayk'a watiqaq ruraqkuna",
 'tog-oldsig' => "Kachkaqña silq'uy:",
@@ -423,7 +423,7 @@ $messages = array(
 'vector-action-protect' => 'Amachay',
 'vector-action-undelete' => 'Qullusqata paqarichiy',
 'vector-action-unprotect' => 'Amachayta wakinchay',
-'vector-simplesearch-preference' => 'Maskanapaq kallpachasqa sakumanakunata atichiy (Vector qarallapi)',
+'vector-simplesearch-preference' => 'Maskanapaq sikllallachasqa sinruta atichiy (Vector qarallapi)',
 'vector-view-create' => 'Kamariy',
 'vector-view-edit' => "Llamk'apuy",
 'vector-view-history' => 'Wiñay kawsayta qhaway',
@@ -529,6 +529,10 @@ $1",
 'youhavenewmessages' => '$1 qhawanayki kachkan ($2).',
 'newmessageslink' => 'Musuq willaymi',
 'newmessagesdifflink' => 'qayna hukchasqapi wakin kaynin',
+'youhavenewmessagesfromusers' => '$1 {{PLURAL:$3|huk ruraqmanta|$3 ruraqkunamanta}} qhawanayki kachkan ($2).',
+'youhavenewmessagesmanyusers' => '$1 achka ruraqkunamanta qhawanayki kachkan ($2).',
+'newmessageslinkplural' => '{{PLURAL:$1|Musuq willaymi|Musuq willaykunam}}',
+'newmessagesdifflinkplural' => 'qayna {{PLURAL:$1|hukchasqapi|hukchasqakunapi}} wakin kaynin',
 'youhavenewmessagesmulti' => 'Musuq willaykunam qhawanayki kachkan $1-pi',
 'editsection' => 'allichay',
 'editold' => "llamk'apuy",
@@ -582,7 +586,10 @@ Allin sapaq p'anqakunataqa tarinki [[Special:SpecialPages|Sapaq p'anqakuna]] nis
 'databaseerror' => 'Willañiqintin pantasqa',
 'dberrortext' => 'Willañiqimanta mañakuptiyki sintaksis pantasqam tukurqan.
 Llamp\'u kaq wakichipi pantasqachá.
-Qayna willañiqimanta mañakusqaqa karqan kaypacham: <blockquote><tt>$1</tt></blockquote> kay ruraypim: "<tt>$2</tt>". MySQL-pa kutichisqan pantasqaqa karqan "<tt>$3: $4</tt>".',
+Qayna willañiqimanta mañakusqaqa karqan kaypacham:
+<blockquote><code>$1</code></blockquote>
+kay ruraypim: "<code>$2</code>".
+Willañiqintinpa kutichisqan pantasqaqa karqan "<samp>$3: $4</samp>".',
 'dberrortextcl' => 'Willañiqimanta mañakuptiyki sintaksis pantasqam tukurqan.
 Qayna willañiqimanta mañakusqaqa karqan kaymi:
 "$1"
@@ -634,9 +641,11 @@ Tapuna: $2',
 'protectedpagetext' => "Kay p'anqaqa llamk'apuymanta amachasqam.",
 'viewsourcetext' => "Kay p'anqap pukyu qillqantam qhawayta iskaychaytapas atinki:",
 'viewyourtext' => "'''Qampa llamk'apusqayki'''p pukyu qillqantam qhawayta iskaychaytapas atinki:",
-'protectedinterface' => "Kay p'anqapiqa wakichintinpa uyapuranpaq qillqam.
-Wandalismu nisqamanta amachasqam kachkan.",
-'editinginterface' => "'''Paqtataq:''' Uyapura p'anqatam llamk'apuchkanki. Hukchaptiykiqa, chay uyapurap rikch'ayninqa hukyanqa huk ruraqkunapaqpas. Uyapurata t'ikrayta munaspaykiqa, [//translatewiki.net/wiki/Main_Page?setlang=qu translatewiki.net] nisqa MediaWiki t'ikrana ruraykamay llika tiyaypi ruranaykimanta hamut'ariy.",
+'protectedinterface' => "Kay p'anqapiqa wakichintinpa uyapuranpaq qillqam. Wandalismu nisqamanta amachasqam kachkan.
+Tukuy wikikunapi uyapuraman t'ikrasqakunata yapayta icha hukchayta munaspaykiqa, [//translatewiki.net/wiki/Main_Page?setlang=qu translatewiki.net] nisqa MediaWiki t'ikrana ruraykamay llika tiyaypi ruray.",
+'editinginterface' => "'''Paqtataq:''' Llamp'u kaqpaq uyapura qillqakuna runanapaq p'anqatam llamk'apuchkanki.
+Hukchaptiykiqa, chay uyapurap rikch'ayninqa hukyanqa kay wikipi huk ruraqkunapaqpas.
+Uyapuraman t'ikrasqakunata yapayta icha hukchayta munaspaykiqa, [//translatewiki.net/wiki/Main_Page?setlang=qu translatewiki.net] nisqa MediaWiki t'ikrana ruraykamay llika tiyaypi ruranaykimanta hamut'ariy.",
 'sqlhidden' => '(SQL tapunaqa pakasqam)',
 'cascadeprotected' => "Kay p'anqaqa amachasqam kachkan, ''phaqcha'' nisqa kamachiwan amachasqa kay {{PLURAL:$1|p'anqapi|p'anqakunapi}} ch'aqtasqa kaspanmi:
 $2",
@@ -650,6 +659,7 @@ $2",
 Amachaq kamachiqqa kayrayku amachani nispa nirqanmi: "$3".',
 'invalidtitle-knownnamespace' => '"$2" sutisuyu, "$3" qillqasqayuq mana allin kaq qillqa suti',
 'invalidtitle-unknownnamespace' => 'Mana riqsisqa $1 kaq sutisuyu yupay, "$2" qillqasqayuq mana allin kaq qillqa suti',
+'exception-nologin' => 'Manam yaykurqankichu',
 
 # Virus scanner
 'virus-badscanner' => "Manam allintachu churapusqa: mana riqsisqa añaw maskaq: ''$1''",
@@ -892,10 +902,14 @@ Yaykurqaspaqa ''[[Special:ChangePassword|yaykuna rima hukchana]]'' p'anqapi kay
 'newarticle' => '(Musuq)',
 'newarticletext' => "Manaraq kachkaq p'anqatam llamk'apuchkanki. Musuq p'anqata kamariyta munaspaykiqa, qillqarillay. Astawan ñawiriyta munaspaykiqa, [[{{MediaWiki:Helppage}}|yanapana p'anqata]] qhaway. Mana munaspaykitaq, ñawpaq p'anqaman ripuy.",
 'anontalkpagetext' => "---- ''Kayqa huk sutinnaq icha mana sutinta llamk'achiq ruraqpa rimanakuyninmi. IP huchhantam hallch'asunchik payta sutinchanapaq. Achka ruraqkunam huklla IP huchhanta llamk'achiyta atin. Sutinnaq ruraq kaspaykiqa, mana qampa rurasqaykimanta willamusqakunata rikuspaykiqa, ama hina kaspa [[Special:UserLogin/signup|rakiqunaykita kamariy]] icha [[Special:UserLogin|yaykuy]] huk sutinnaq ruraqkunawan ama pantasqa kanaykipaq.''",
-'noarticletext' => "Kunanqa kay p'anqa ch'usaqmi. Kaytam rurayta atinkiman: kay p'anqap sutinta [[Special:Search/{{PAGENAME}}|huk p'anqakunapi maskay]], <span class=\"plainlinks\">[{{fullurl:{{#Special:Log}}|page={{FULLPAGENAMEE}}}} hallch'ankunapi maskay] icha [{{fullurl:{{FULLPAGENAME}}|action=edit}} kay p'anqata llamk'apuy]</span>.",
-'noarticletext-nopermission' => "Kay p'anqaqa ch'usaqmi.
-Kay p'anqap sutintaqa [[Special:Search/{{PAGENAME}}|huk p'anqakunapi maskaytam atinki]],
-icha payman kapuq <span class=\"plainlinks\">[{{fullurl:{{#Special:Log}}|page={{FULLPAGENAMEE}}}} hallch'akunapi maskaykiman]</span>.",
+'noarticletext' => "Kunanqa kay p'anqa ch'usaqmi kachkan.
+Kaytam rurayta atinkiman: kay p'anqap sutinta [[Special:Search/{{PAGENAME}}|huk p'anqakunapi maskay]],
+<span class=\"plainlinks\">[{{fullurl:{{#Special:Log}}|page={{FULLPAGENAMEE}}}} hallch'ankunapi maskay]
+icha [{{fullurl:{{FULLPAGENAME}}|action=edit}} kay p'anqata llamk'apuy]</span>.",
+'noarticletext-nopermission' => "Kunanqa kay p'anqa ch'usaqmi kachkan.
+Kaytam rurayta atinkiman: kay p'anqap sutinta [[Special:Search/{{PAGENAME}}|huk p'anqakunapi maskay]]
+icha payman kapuq <span class=\"plainlinks\">[{{fullurl:{{#Special:Log}}|page={{FULLPAGENAMEE}}}} hallch'akunapi maskay]</span>,
+ichataq kay p'anqata kamariyta manam saqillasunkichu.",
 'userpage-userdoesnotexist' => '"<nowiki>$1</nowiki>" sutiyuq ruraqpa rakiqunanqa manam kanchu. Ama hina kaspa, llanchikuy kay p\'anqata kamarinaykimanta.',
 'userpage-userdoesnotexist-view' => '"$1" sutiyuq rakiqunaqa manam hallch\'asqachu.',
 'blocked-notice-logextract' => "Kay ruraqqa hark'asqam kachkan.
@@ -904,7 +918,6 @@ Hark'ay hallch'api qhipaq hark'asqataqa kaypim rikunki willasunaykipaq:",
 * '''Firefox / Safari:''' ''Shift'' yatachkaspa ''Reload'' ñit'iy, ichataq ''Ctrl-F5'' icha ''Ctrl-R'' yatay (''⌘-R'' Mac nisqapi)
 * '''Google Chrome:''' ''Ctrl-Shift-R'' yatay (''⌘-Shift-R'' Mac nisqapi)
 * '''Internet Explorer:''' ''Ctrl'' yatachkaspa ''Refresh'' ñit'iy, icha ''Ctrl-F5'' yatay
-* '''Konqueror: '''''Reload'' ñit'iy icha ''F5'' yatay
 * '''Opera:''' ''cache'' nisqata ch'usaqchay kaypi: ''Tools → Preferences''",
 'usercssyoucanpreview' => "'''Kunay:''' \"{{int:showpreview}}\" nisqa ñit'inata llamk'achiy musuq css nisqata qhawanaykipaq, manaraq waqaychaspa.",
 'userjsyoucanpreview' => "'''Kunay:''' \"{{int:showpreview}}\" nisqa ñit'inata llamk'achiy musuq JavaScript nisqata qhawanaykipaq, manaraq waqaychaspa.",
@@ -919,7 +932,7 @@ Hark'ay hallch'api qhipaq hark'asqataqa kaypim rikunki willasunaykipaq:",
 'note' => "'''Musyay:'''",
 'previewnote' => "'''Yuyaykuy: Kayqa qhawariyllam.'''
 Llamk'apusqaykiqa manaraqmi waqaychasqachu!",
-'continue-editing' => "Llamk'apuyta qatiykuy",
+'continue-editing' => "Llamk'apuy millkaman riy",
 'previewconflict' => "Rikuchkanki kay p'anqataqa, ima hinachus waqaychasqa kanqa.",
 'session_fail_preview' => "'''Achachaw! Llamk'apusqaykiqa manam waqaychasqachu, llamk'ana tiyaypa willankuna chinkaptinmi. Ama hina kaspa, musuqmanta ruraykachay. Mana atispaykiqa, [[Special:UserLogout|lluqsispa]] musuqmanta yaykuy.'''",
 'session_fail_preview_html' => "'''Achachaw! Llamk'apusqaykiqa manam waqaychasqachu, llamk'ana tiyaypa willankuna chinkaptinmi.'''
@@ -994,6 +1007,12 @@ Qullusqachá.",
 Kachkañam.",
 'defaultmessagetext' => 'Ñawpaq qillqa',
 
+# Content models
+'content-model-wikitext' => 'wiki qillqa',
+'content-model-text' => 'qillqalla',
+'content-model-javascript' => 'JavaScript',
+'content-model-css' => 'CSS',
+
 # Parser/template warnings
 'expensive-parserfunction-warning' => "Paqtataq: Kay p'anqaqa nisyu achka qullqipaq t'ikrana rurana qayayniyuqmi.
 
@@ -1148,6 +1167,7 @@ Ama hina kaspa, hallch'akunapi qhaway.",
 'revdelete-reason-dropdown' => "*Qulluypaq sapsi raykukuna
 ** Ruraqpa hayñinta k'irisqa
 ** Runamanta mana allin willaykuna
+** Ruraqpa mana allin sutin
 ** Runata k'amiqchá willaykuna",
 'revdelete-otherreason' => 'Huk/aswan rayku:',
 'revdelete-reasonotherlist' => 'Huk rayku',
@@ -1334,7 +1354,7 @@ Pi kay k'itichapi llawiykita riqsiqpas watiqasqaykikunata ñawiriytam atinqa. Ch
 'timezoneregion-indian' => 'Indiku mama qucha',
 'timezoneregion-pacific' => 'Pasiphiku mama qucha',
 'allowemail' => 'Huk ruraqkunamanta e-chaskita saqillay',
-'prefs-searchoptions' => 'Akllanakunata maskay',
+'prefs-searchoptions' => 'Maskay',
 'prefs-namespaces' => "Suti k'itikuna",
 'defaultns' => "Mana hinaptintaq kay suti k'itikunapi maskay:",
 'default' => 'kikinmanta',
@@ -1732,7 +1752,7 @@ $1',
 'backend-fail-internal' => '"$1" sutiyuq willañiqi hallch\'ana sirwiqpi mana riqsisqa pantasqam tukurqan.',
 'backend-fail-contenttype' => 'Manam atinichu "$1" nisqapi hallch\'ana willañiqip samiqninpa layanta yuqanchayta.',
 'backend-fail-batchsize' => "Willañiqi hallch'ana sirwiqmanqa $1 willañiqi {{PLURAL:$1|ruranayuq|ruranayuq}} tawqam qusqa; saywataq $2 {{PLURAL:$1|ruranam|ruranam}}.",
-'backend-fail-usable' => 'Manam atinichu $1 sutiyuq willañiqita qillqayta, mana aypalla saqillaykuna icha mana churanakuna/qullqakuna kaptinmi.',
+'backend-fail-usable' => 'Manam atinichu "$1" sutiyuq willañiqita ñawiriyta icha qillqayta, mana aypalla saqillaykuna icha mana churanakuna/qullqakuna kaptinmi.',
 
 # File journal errors
 'filejournal-fail-dbconnect' => "Manam atinichu \"\$1\" sutiyuq willañiqi hallch'ana sirwiqpaq p'unchawnintin hallch'awan t'inkiyta.",
@@ -1942,7 +1962,9 @@ Ama hina kaspa, [$2 willañiqi ch'uyanchana p'anqata] qhaway astawan willachikun
 
 'disambiguations' => "Sut'ichana qillqakunaman t'inkimuq p'anqakuna",
 'disambiguationspage' => "Template:Sut'ichana qillqa",
-'disambiguations-text' => "Kay qatiq p'anqakunam t'inkimun '''sut'ichana qillqaman'''. Chiqap, hukchanasqa p'anqaman t'inkichun.<br />Tukuy [[MediaWiki:Disambiguationspage]] plantillayuq p'anqakunaqa sut'ichana qillqam.",
+'disambiguations-text' => "Kay qatiq p'anqakunam t'inkimun '''sut'ichana qillqa''' nisqaman.
+Chay rantiqa chiqap, hukchanasqa p'anqamanmi t'inkichun.<br />
+P'anqa [[MediaWiki:Disambiguationspage]] plantillayuq kaspaqa sut'ichana qillqam kanqa.",
 
 'doubleredirects' => 'Iskaylla pusapunakuna',
 'doubleredirectstext' => "Kay p'anqapiqa huk pusapuna p'anqaman pusapuq p'anqakunap sutinkunatam rikunki. Sapa sinrupiqa ñawpaq ñiqin, iskay ñiqinpas pusapunaman t'inkikunam, iskay ñiqin pusapunap taripananpa qallariyninpas, sapsilla \"chiqap\" allin taripana qillqam, maymanchus ñawpaq ñiqin pusapuna p'anqa pusachun.
@@ -2383,7 +2405,7 @@ Huklla llamk'apusqakunata paqarichinaykipaqqa, munasqayki llamk'apusqakunata akl
 'undeletedrevisions' => "{{PLURAL:$1|Huk paqarichisqa llamk'apusqa|$1 paqarichisqa llamk'apusqakuna}}",
 'undeletedrevisions-files' => "{{PLURAL:$1|1 llamk'apusqaqa|$1 llamk'apusqakunaqa}} {{PLURAL:$2|1 willañiqipas|$2 willañiqikunapas}} paqarichisqam",
 'undeletedfiles' => '{{PLURAL:$1|1 willañiqiqa|$1 willañiqikunaqa}} paqarichisqam',
-'cannotundelete' => 'Manam atinichu qullusqata paqarichiyta; huk runachá ñawpaqtaña qullusqata paqarichirqan.',
+'cannotundelete' => 'Manam atinichu qullusqata paqarichiyta: $1',
 'undeletedpage' => "'''$1 nisqaqa paqarichisqañam'''
 
 [[Special:Log/delete|Qulluy hallch'api]] qhaway ñaqha qullusqakunata paqarichisqakunatapas rikunaykipaq.",
@@ -2920,11 +2942,21 @@ Tukuy hawa wikimanta chaskisqakunaqa [[Special:Log/import|hawamanta chaskiy hall
 
 # Info page
 'pageinfo-title' => '"$1" sutiyuq p\'anqamanta willay',
-'pageinfo-header-edits' => "Llamk'apusqakuna",
+'pageinfo-header-edits' => "Llamk'apusqakunap wiñay kawsaynin",
 'pageinfo-views' => "Hayk'a qhawaykuna",
-'pageinfo-watchers' => "Hayk'a watiqaqkuna",
-'pageinfo-edits' => "Hayk'a hukchasqakuna",
-'pageinfo-authors' => "Hayk'a sapaq kaq ruraqkuna",
+'pageinfo-watchers' => "P'anqata hayk'a watiqaqkuna",
+'pageinfo-firstuser' => "P'anqap kamariqnin",
+'pageinfo-firsttime' => "P'anqa kamariypa p'unchawnin",
+'pageinfo-lastuser' => "Ñaqha llamk'apuqnin",
+'pageinfo-lasttime' => "Ñaqha llamk'apuypa p'unchawnin",
+'pageinfo-edits' => "Tukuymanta hayk'a hukchasqakuna",
+'pageinfo-authors' => "Tukuymanta hayk'a sapaq kaq ruraqkuna",
+'pageinfo-toolboxlink' => "P'anqamanta willakuna",
+'pageinfo-redirectsto' => 'Kayman pusampun:',
+'pageinfo-redirectsto-info' => 'willachikuy',
+'pageinfo-contentpage' => "Samiqniyuq p'anqa hinam chaninchasqa",
+'pageinfo-contentpage-yes' => 'Arí',
+'pageinfo-protect-cascading-yes' => 'Arí',
 
 # Patrolling
 'markaspatrolleddiff' => 'Qhawakipasqaman sananchay',
@@ -3624,7 +3656,7 @@ Rikchakunatataq hunt'a ch'irkukupim rikunki. Huk willañiqi llayakunaqa tantapus
 * <span class="mw-specialpagerestricted">Sapaqkunallapaq sapaq p\'anqakuna.</span>',
 'specialpages-group-maintenance' => 'Hatalliy willaykuna',
 'specialpages-group-other' => "Huk sapaq p'anqakuna",
-'specialpages-group-login' => 'Yaykuy / rakiqunata kichariy',
+'specialpages-group-login' => 'Yaykuy / rakiqunata kamariy',
 'specialpages-group-changes' => "Ñaqha hukchasqa hallch'asqapas",
 'specialpages-group-media' => 'Midya willaykuna churkuykunapas',
 'specialpages-group-users' => 'Ruraqkuna hayñinkunapas',
index e295cd6..4c23deb 100644 (file)
@@ -49,7 +49,7 @@ $messages = array(
 'tog-hidepatrolled' => 'Zuppentar midadas controlladas en las «ultimas midadas»',
 'tog-newpageshidepatrolled' => 'Zuppentar paginas controlladas en las «paginas novas»',
 'tog-extendwatchlist' => "Extender la glista d'observaziun per mussar tut las midadas e betg be las ultimas",
-'tog-usenewrc' => "Duvrar la versiun extendida da las ''Ultimas midadas'' (basegna JavaScript)",
+'tog-usenewrc' => "Gruppar las midadas tenor pagina en las ''ultimas midadas'' ed la ''glista d'observaziun'' (basegna JavaScript)",
 'tog-numberheadings' => 'Numerar automaticamain ils titels',
 'tog-showtoolbar' => "Mussa la trav d'utensils (basegna JavaScript)",
 'tog-editondblclick' => 'Modifitgar paginas cun in clic dubel (basegna JavaScript)',
@@ -57,17 +57,17 @@ $messages = array(
 'tog-editsectiononrightclick' => 'Activar la pussaivladad da modifitgar secziuns cun in clic dretg (basegna JavaScript)',
 'tog-showtoc' => 'Mussar ina tabla da cuntegn sin paginas cun dapli che trais tetels',
 'tog-rememberpassword' => "S'annunziar permanantamain cun quest navigatur (per maximalmain $1 {{PLURAL:$1|di|dis}})",
-'tog-watchcreations' => "Observar paginas ch'jau hai creà",
-'tog-watchdefault' => "Observar paginas ch'jau hai edità",
-'tog-watchmoves' => "Observar paginas ch'jau hai spustà",
-'tog-watchdeletion' => "Observar paginas ch'jau hai stizzà",
+'tog-watchcreations' => "Agiuntar paginas ch'jeu creesch e datotecas ch'jau transferesch a la glista d'observaziun",
+'tog-watchdefault' => "Agiuntar paginas e datotecas ch'jau modifitgesch a la glista d'observaziun",
+'tog-watchmoves' => "Agiuntar paginas e datotecas ch'jau hai spustà a la glista d'observaziun",
+'tog-watchdeletion' => "Agiuntar paginas e datotecas ch'jau hai stizzà a la glista d'observaziun",
 'tog-minordefault' => 'Marcar tut las modificaziuns per ordinari sco pitschnas',
 'tog-previewontop' => "Mussar la prevista sur il champ d'endatziun",
 'tog-previewonfirst' => "Adina mussar la prevista suenter l'emprima modificaziun",
 'tog-nocache' => 'Impedir che tes navigatur memorisescha las paginas en il cache',
-'tog-enotifwatchlistpages' => "Trametta in e-mail sch'ina pagina sin mia glista d'observaziun vegn midada",
+'tog-enotifwatchlistpages' => "Ma trametter in e-mail sch'ina pagina u ina datoteca sin mia glista d'observaziun vegn midada",
 'tog-enotifusertalkpages' => "Trametta in e-mail sch'i ha dà midadas sin mia pagina da discussiun.",
-'tog-enotifminoredits' => 'Trametta era in e-mail tar pitschnas midadas da las paginas',
+'tog-enotifminoredits' => 'Era ma trametter in e-mail en cas da midadas pitschnas vid paginas u datotecas',
 'tog-enotifrevealaddr' => "Mussar mia adressa dad e-mail en e-mails d'avis",
 'tog-shownumberswatching' => "Mussar il dumber d'utilisaders che obervan questa pagina",
 'tog-oldsig' => 'Signatura actuala:',
@@ -186,7 +186,6 @@ $messages = array(
 'qbbrowse' => 'Sfegliar',
 'qbedit' => 'Modifitgar',
 'qbpageoptions' => 'Questa pagina',
-'qbpageinfo' => 'Context',
 'qbmyoptions' => 'Mia pagina',
 'qbspecialpages' => 'paginas spezialas',
 'faq' => 'FAQ',
@@ -199,7 +198,7 @@ $messages = array(
 'vector-action-protect' => 'Bloccar',
 'vector-action-undelete' => 'Restituir',
 'vector-action-unprotect' => 'Midar la protecziun',
-'vector-simplesearch-preference' => 'Activar las propostas per tschertgar extendidas (be per il skin Vector)',
+'vector-simplesearch-preference' => 'Activar la trav da tschertgar simplifitgada (be per il skin Vector)',
 'vector-view-create' => 'Crear',
 'vector-view-edit' => 'Modifitgar',
 'vector-view-history' => 'Cronologia',
@@ -305,6 +304,10 @@ $1',
 'youhavenewmessages' => 'Ti has $1 ($2).',
 'newmessageslink' => 'novs messadis',
 'newmessagesdifflink' => "l'ultima midada",
+'youhavenewmessagesfromusers' => 'Ti has $1 da{{PLURAL:$3|d in utilisader| $3 utilisaders}} ($2).',
+'youhavenewmessagesmanyusers' => 'Ti has $1 da divers utilisaders ($2).',
+'newmessageslinkplural' => '{{PLURAL:$1|in nov messadi|novs messadis}}',
+'newmessagesdifflinkplural' => 'ultima{{PLURAL:$1| midada|s midadas}}',
 'youhavenewmessagesmulti' => 'Ti as novs messadis en $1',
 'editsection' => 'modifitgar',
 'editold' => 'modifitgar',
@@ -361,9 +364,9 @@ Ina glista da las paginas spezialas existentas chattais vus sut [[Special:Specia
 'dberrortext' => 'In sbagl da la sintaxa da la dumonda a la banca da datas è capità.
 Quai po esser in sbagl en la software.
 L\'ultima dumonda per la banca da datas era:
-<blockquote><tt>$1</tt></blockquote>
-ord la funcziun "<tt>$2</tt>".
-La banca da datas ha rapportà l\'errur "<tt>$3: $4</tt>".',
+<blockquote><code>$1</code></blockquote>
+ord la funcziun "<code>$2</code>".
+La banca da datas ha rapportà l\'errur "<samp>$3: $4</samp>".',
 'dberrortextcl' => 'In sbagl da la sintaxa da la dumonda a la banca da datas è capità.
 L\'ultima dumonda per la banca da datas era:
 "$1"
@@ -400,6 +403,8 @@ Annunzia per plaschair la URL ad in [[Special:ListUsers/sysop|administratur]].',
 'cannotdelete' => 'Betg pussaivel da stizzar la pagina u datoteca "$1".
 Eventualmain ha gia insatgi auter stizza quest element.',
 'cannotdelete-title' => 'Impussibel da stizzar la pagina "$1"',
+'delete-hook-aborted' => 'Il prozess da stizzar è vegnì interrut dal hook. 
+El ha dà nagina explicaziun.',
 'badtitle' => "Il num da titel endatà n'è betg valid",
 'badtitletext' => 'Il titel da pagina era betg valid, vids u in titel inter-lingua u inter-wiki betg correct.
 El po cuntegnair in u plirs segns che na pon betg vegnir utilisads en titels.',
@@ -417,8 +422,11 @@ Query: $2',
 Emprova danovamain en in per minutas.',
 'protectedpagetext' => "Questa pagina è vegnida bloccada per evitar ch'ella vegn modifitgada.",
 'viewsourcetext' => 'Ti pos guardar e copiar il code-fundamental da questa pagina:',
-'protectedinterface' => "Questa pagina cuntegna text per l'interfatscha da la software ed è protegida per evitar abus.",
-'editinginterface' => "'''Attenziun:''' Questa pagina cuntegna text che vegn duvra da la software MediaWiki. Midadas influenzeschan directamain l'interfatscha da l'utilisader. Sche ti vuls far translaziuns u correcturas: Studegia da far quai sin [//translatewiki.net/wiki/Main_Page?setlang=rm translatewiki.net], per che las midadas pon vegnidas surprendidas da tut ils projects.",
+'viewyourtext' => "Ti pos giardar e copiar la il code da funatuna da '''tias midadas''' vid questa pagina:",
+'protectedinterface' => "Questa pagina cuntegna ils texts per l'interfatscha da la software ed è protegida per evitar abus.",
+'editinginterface' => "'''Attenziun:''' Questa pagina cuntegna text che vegn duvra en la interfatscha da questa software. 
+Midadas influenzeschan directamain l'interfatscha per tut ils utilisaders sin questa vichi. 
+Sche ti vuls far translaziuns u correcturas per tut las vichis, lura utilisescha [//translatewiki.net/ translatewiki.net], il project per translatar MediaWiki.",
 'sqlhidden' => '(Zuppentà la dumonda da SQL)',
 'cascadeprotected' => "Questa pagina è protegida da modificaziuns perquai ch'ella è integrada en suandanta{{PLURAL:$1| pagina, ch'è protegida|s paginas, ch'èn protegidas}} entras l'opziun «protecziun ertada»: 
 $2",
@@ -428,6 +436,13 @@ $2",
 'ns-specialprotected' => 'Paginas spezialas no pon betg vegnir modifitgadas.',
 'titleprotected' => 'Quest titel è vegnì protegì da la creaziun da [[User:$1|$1]].
 Il motiv inditgà è "\'\'$2\'\'".',
+'filereadonlyerror' => 'Impussibel da modifitgar la datoteca "$1" perquai ch\'il repository da datotecas "$2" è en il modus \'be leger\'.
+
+L\'administratur che ha bloccà l\'access da scriva ha dà suandanta explicaziun: "$3".',
+'invalidtitle-knownnamespace' => 'Titel nunvalid cun tip da pagina "$2" e text "$3"',
+'invalidtitle-unknownnamespace' => 'Titel nunvalid cun numer da tip da pagina nunenconuschent $1 e text "$2"',
+'exception-nologin' => "Betg s'annunzià",
+'exception-nologin-text' => "Questa pagina u acziun pretenda che ti es s'annunzià en quest vichi.",
 
 # Virus scanner
 'virus-badscanner' => "Configuraziun fauss: antivirus nunenconuschent: ''$1''",
@@ -447,6 +462,7 @@ Betg emblida da midar tias [[Special:Preferences|preferenzas da {{SITENAME}}]].'
 'remembermypassword' => "S'annunziar permanantamain sin quest computer (per maximalmain $1 {{PLURAL:$1|di|dis}})",
 'securelogin-stick-https' => "Restar collià entras HTTPS suenter l'annunzia",
 'yourdomainname' => 'Vossa domain',
+'password-change-forbidden' => 'Ti na pos betg midar pleds-clav sin quest vichi.',
 'externaldberror' => "U ch'i è capità ina errur cun l'autentificaziun externa u che ti na dastgas betg actualisar tes conto extern.",
 'login' => "T'annunziar",
 'nav-login-createaccount' => "T'annunziar / registrar",
@@ -517,6 +533,8 @@ Perquei è anc nagin retschaiver e trametter dad e-mails per las suandantas func
 'emailconfirmlink' => "Confermar l'adressa dad e-mail",
 'invalidemailaddress' => "L'adressa dad e-mail na po betg vegnir acceptada perquai ch'ella para dad avair in format nunvalid. 
 Endatescha per plaschair ina adressa formatada correctamain u svida cumplettamain il champ.",
+'cannotchangeemail' => "L'adressa dad e-mail dal conto na po betg vegnir midada sin questa vichi.",
+'emaildisabled' => 'Questa pagina na sa betg trametter e-mails.',
 'accountcreated' => "Creà il conto d'utilisader",
 'accountcreatedtext' => "Il conto d'utilisader per $1 è vegnì creà.",
 'createaccount-title' => 'Crear in conto per {{SITENAME}}',
@@ -532,6 +550,7 @@ Spetga per plaschair avant ch'empruvar anc ina giada.",
 
 # E-mail sending
 'php-mail-error-unknown' => 'Errur nunenconuschenta en la funcziun mail() da PHP',
+'user-mail-no-addy' => 'Empruvà da trametter in e-mail senza ina adressa dad e-mail.',
 
 # Change password dialog
 'resetpass' => 'Midar il pled-clav',
@@ -560,6 +579,8 @@ Eventualmain has ti gia midà cun success tes pled-clav u dumandà per in nov pl
 'passwordreset-pretext' => '{{PLURAL:$1||Endatescha in dals tocs da data sutvart}}',
 'passwordreset-username' => "Num d'utilisader:",
 'passwordreset-domain' => 'Domain:',
+'passwordreset-capture' => "Mussar l'e-mail che resultescha?",
+'passwordreset-capture-help' => "Sche ti activeschas quest champ vegn l'e-mail (cun il pled-clav temporar) mussà a ti sco era tramess a l'utilisader.",
 'passwordreset-email' => 'Adressa dad e-mail:',
 'passwordreset-emailtitle' => 'Detagls davart il conto sn {{SITENAME}}',
 'passwordreset-emailtext-ip' => "Insatgi (probablamain ti da l'adressa dad IP $1) ha dumandà in nov pled-clav per la pagina {{SITENAME}} ($4). 
@@ -579,12 +600,18 @@ Ti duessas t'annunziar e tscherner ussa in nov pled-clav. Sche ti na levas betg
 'passwordreset-emailelement' => "Num d'utilisader: $1
 Pled-clav temporar: $2",
 'passwordreset-emailsent' => 'In e-mail cun in nov pled-clav è vegnì tramess.',
+'passwordreset-emailsent-capture' => "L'e-mail per far endament, che vegn mussà sutvart, è vegnì tramess.",
+'passwordreset-emailerror-capture' => "L'e-mail per far endament, che vegn mussà sutvart, è vegnì generà, ma ha dentant betg pudì vegnir spedì a l'utilisader: $1",
 
 # Special:ChangeEmail
 'changeemail' => "Midar l'adressa dad e-mail",
+'changeemail-header' => "Midar l'adressa dad e-mail dal conto",
+'changeemail-text' => 'Cumpletescha quest formular per midar tia adressa dad e-mail. Ti stos endatar tes pled-clav per confermar questa midada.',
 'changeemail-no-info' => "Ti stos t'annunziar per acceder directamain questa pagina.",
+'changeemail-oldemail' => 'Adressa dad e-mail actuala:',
 'changeemail-newemail' => ' Nova adressa dad e-mail',
 'changeemail-none' => '(nagina)',
+'changeemail-submit' => "Midar l'adressa dad e-mail",
 'changeemail-cancel' => 'Interrumper',
 
 # Edit page toolbar
@@ -678,8 +705,11 @@ Ti pos [[Special:Search/{{PAGENAME}}|tschertgar il term]] sin in\'autra pagina,
 <span class="plainlinks">[{{fullurl:{{#Special:Log}}|page={{FULLPAGENAMEE}}}} tschertgar en ils logs],
 u [{{fullurl:{{FULLPAGENAME}}|action=edit}} crear questa pagina]</span>.',
 'noarticletext-nopermission' => 'Questa pagina cuntegna actualmain nagin text.
-Ti pos [[Special:Search/{{PAGENAME}}|tschertgar il term]] sin in\'autra pagina,
-<span class="plainlinks">[{{fullurl:{{#Special:Log}}|page={{FULLPAGENAMEE}}}} tschertgar en ils logs]</span>.',
+Ti pos [[Special:Search/{{PAGENAME}}|tschertgar quest titel]] en autras paginas u <span class="plainlinks">[{{fullurl:{{#Special:Log}}|page={{FULLPAGENAMEE}}}} tschertgar en ils protocols correspundents]</span>, ma ti n\'has betg ils dretgs da crear questa pagina.',
+'missing-revision' => 'La versiun #$1 da la pagina cun il num "{{PAGENAME}}" n\'exista betg.
+
+Quai capita savnes sche ti cliccas sin ina colliaziun antiquada en la cronologia per ina pagina ch\'è vegnida stizzada.
+Detagls pon vegnri chattads en il [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} protocol da stizzar].',
 'userpage-userdoesnotexist' => 'Il conto d\'utilisader "<nowiki>$1</nowiki>" n\'èxista betg.
 Controllescha sch ti vuls propi crear/modiftgar questa pagina.',
 'userpage-userdoesnotexist-view' => 'Il conto d\'utilisader "$1" n\'exista betg.',
@@ -689,7 +719,6 @@ L'ultima endataziun dal log da bloccar vegn mussà sutvart sco referenza:",
 * '''Firefox / Safari:''' Tegnair ''Shift'' durant cliccar ''chargiar danovamain'', u smatgar ''Ctrl-F5'' u ''Ctrl-R'' (''⌘-R'' sin in Mac)
 * '''Google Chrome:''' Smatgar ''Ctrl-Shift-R'' (''⌘-Shift-R'' sin in Mac)
 * '''Internet Explorer:''' Tegnair ''Ctrl'' durant cliccar ''Rechargiar,'' u smatgar ''Ctrl-F5''
-* '''Konqueror:''' Cliccar ''Rechargiar'' ni smatgar ''F5''
 * '''Opera:''' Stizzar il cache sut ''Tools → Preferences''",
 'usercssyoucanpreview' => "'''Tip:''' Utilisescha il buttun \"{{int:showpreview}}\" per testar tes nov CSS avant che memorisar.",
 'userjsyoucanpreview' => "'''Tip:''' Utilisescha il buttun \"{{int:showpreview}}\" per testar tes nov JavaScript avant che memorisar.",
@@ -707,6 +736,7 @@ Fa stim che titels da paginas persunalisadas .css u .js vegnan scrits pitschen,
 'note' => "'''Remartga:'''",
 'previewnote' => "'''Fa stim che quai è be ina prevista.'''
 Tias midadas n'èn anc betg vegnidas memorisadas!",
+'continue-editing' => 'Cuntinuar da modifitgar',
 'previewconflict' => "Questa prevista visualisescha il text en il champ d'endataziun sura. Uschia vegn la pagina vesair ora, sche ti la memoriseschas ussa.",
 'session_fail_preview' => "'''Stgisa! Tia modificaziun na pudeva betg vegnir memorisada perquei che las datas da la sesida èn idas a perder.'''
 Emprova per plaschair danovamain.
@@ -722,6 +752,7 @@ La modificaziun è vegnida refusada per evitar ch'il cuntegn da la pagina vegnia
 Quai po capitar sche ti utiliseschas in survetsch da proxy anonim che na funcziuna betg correctamain.",
 'edit_form_incomplete' => "'''Entginas parts dal formular da modifitgar n'èn betg arrivadas cumplattamain al server; controllescha p.pl. che tias midadas èn intactas ed emprova danovamain.'''",
 'editing' => 'Modifitgar $1',
+'creating' => 'Crear $1',
 'editingsection' => 'Modifitgar $1 (secziun)',
 'editingcomment' => 'Modifitgar $1 (nova secziun)',
 'editconflict' => 'Conflict da modifitgar: $1',
@@ -787,6 +818,7 @@ I para sco sch'ella fiss vegnida stizzada.",
 'edit-conflict' => 'Conflict da modifitgar.',
 'edit-no-change' => 'Tia modificaziun è vegnida ignorada perquai che naginas midadas èn vegnidas fatgas en il text.',
 'edit-already-exists' => "Betg pussaivel da crear ina nova pagina perquai ch'ella exista gia.",
+'defaultmessagetext' => 'Text da standard',
 
 # Parser/template warnings
 'expensive-parserfunction-warning' => "'''Attenziun:''' Questa pagina cuntegna memia bleras funcziuns dal parser cumplitgadas. 
@@ -802,6 +834,10 @@ Quests arguments vegnan ignorads.",
 'parser-template-loop-warning' => 'Chattà cirquit da models: [[$1]]',
 'parser-template-recursion-depth-warning' => 'Surpassa la limita da recursiun da models ($1)',
 'language-converter-depth-warning' => 'Surpassà la limita ($1) dal convertader da linguas',
+'node-count-exceeded-category' => "Paginas, nua ch'il dumber da nufs è surpassà",
+'node-count-exceeded-warning' => 'Questa pagina ha surpassà il dumber da nufs',
+'expansion-depth-exceeded-category' => "Paginas, nua che la porfunditad d'extensiun è surpassada",
+'expansion-depth-exceeded-warning' => "Questa pagina ha surpassà la profunditad d'expansiun",
 
 # "Undo" feature
 'undo-success' => 'Questa modificaziun na po betg vegnir revocada.
@@ -866,20 +902,20 @@ Ti pos anc adina [$1 contemplar questa versiun].",
 'rev-deleted-text-view' => "Questa versiun da la pagina è vegnida '''stizzada'''.
 Ti pos la vesair; detagls pon vegnir chattads en il [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} log da stizzar].",
 'rev-suppressed-text-view' => "Questa versiun da la pagina è vegnida '''supprimida'''.
-Sco administratur pos ti la vesair; detagls pon vegnir chattads en il [{{fullurl:{{#Special:Log}}/suppress|page={{FULLPAGENAMEE}}}}  log da supprimer].",
+Ti pos la vesair; detagls pon vegnir chattads en il [{{fullurl:{{#Special:Log}}/suppress|page={{FULLPAGENAMEE}}}}  log da supprimer].",
 'rev-deleted-no-diff' => "Ti na pos betg guardar quest diff perquai ch'ina da las versiuns è vegnida '''stizzada'''.
 Detagls pos ti chattar en [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} log da stizzar].",
 'rev-suppressed-no-diff' => "Ti na pos betg guardar quest diff perquai ch'ina da las versiuns è vegnida '''stizzada'''.",
 'rev-deleted-unhide-diff' => "Ina da las versiuns da quest diff è vegnida '''stizzada'''.
 Detagls pon vegnir chattads en il [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} log da stizzar].
-Sco administratur pos ti anc adina [$1 contemplar quest diff].",
+Ti pos anc adina [$1 contemplar quest diff] sche ti vuls cuntinuar.",
 'rev-suppressed-unhide-diff' => "Ina da las versiuns da quest diff è vegnida '''supprimida'''.
 Detagls pon vegnir chattads en il [{{fullurl:{{#Special:Log}}/suppress|page={{FULLPAGENAMEE}}}} log da supprimer].
-Sco administratur pos ti anc adina [$1 contemplar quest diff] sche ti vuls cuntinuar.",
+Ti pos anc adina [$1 contemplar quest diff] sche ti vuls cuntinuar.",
 'rev-deleted-diff-view' => "Ina da las versiuns da quest diff è vegnida '''stizzada'''.
-Sco administratur pos ti vesair quest diff; detagls pon vegnir chattads en il [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} log da stizzar].",
+Ti pos vesair quest diff; detagls pon vegnir chattads en il [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} log da stizzar].",
 'rev-suppressed-diff-view' => "Ina da las versiuns da quest diff è vegnida '''supprimida'''.
-Sco administratur pos ti vesair quest diff; detagls pon vegnir chattads en il [{{fullurl:{{#Special:Log}}/suppress|page={{FULLPAGENAMEE}}}}  log da supprimer].",
+Ti pos vesair quest diff; detagls pon vegnir chattads en il [{{fullurl:{{#Special:Log}}/suppress|page={{FULLPAGENAMEE}}}}  log da supprimer].",
 'rev-delundel' => 'mussar/zuppentar',
 'rev-showdeleted' => 'mussar',
 'revisiondelete' => 'Stizzar/restituir versiuns',
@@ -1074,7 +1110,7 @@ Considerescha che lur index da {{SITENAME}} po cuntegnair datas ch'èn betg pli
 'timezoneregion-indian' => 'Ocean Indic',
 'timezoneregion-pacific' => 'Ocean pacific',
 'allowemail' => 'Retschaiver e-mails dad auters utilisaders',
-'prefs-searchoptions' => 'Opziuns da tschertgar',
+'prefs-searchoptions' => 'Tschertgar',
 'prefs-namespaces' => 'Tips da pagina',
 'defaultns' => 'Uschiglio tschertgar en quests tips da pagina:',
 'default' => 'Standard',
@@ -2510,8 +2546,12 @@ Probablamien è quai capità pervia dad in link ad ina pagina externa ch'è sin
 'pageinfo-header-edits' => 'Midadas',
 'pageinfo-views' => 'Dumber da visitas',
 'pageinfo-watchers' => 'Dumber dad observaturs',
-'pageinfo-edits' => 'Dumber da midadas',
-'pageinfo-authors' => 'Dumber dad auturs differents',
+'pageinfo-firstuser' => 'Creatur da la pagina',
+'pageinfo-firsttime' => 'Data da la creaziun da la pagina',
+'pageinfo-lastuser' => 'Ultima midada da',
+'pageinfo-lasttime' => "Data da l'ultima midada",
+'pageinfo-edits' => 'Dumber total da midadas',
+'pageinfo-authors' => 'Dumber total dad auturs differents',
 
 # Patrolling
 'markaspatrolleddiff' => 'Marcar sco controllà',
@@ -3132,6 +3172,9 @@ Ti pos era utilisar [[Special:EditWatchlist|la pagina da standard]].',
 'watchlisttools-edit' => "Mussar e modifitgar la glista d'observaziun",
 'watchlisttools-raw' => 'Modifitgar il format da la glista (import/export)',
 
+# Signatures
+'signature' => '[[{{ns:user}}:$1|$2]] ([[{{ns:user_talk}}:$1|talk]])',
+
 # Core parser functions
 'unknown_extension_tag' => 'Tag d\'extensiun nunenconuschent "$1"',
 'duplicate-defaultsort' => '\'\'\'Attenziun:\'\'\' La clav da zavrar da standard "$2" remplazza la clav da zavrar da standard veglia "$1".',
@@ -3164,6 +3207,9 @@ Ti duessas avair retschavì [{{SERVER}}{{SCRIPTPATH}}/COPYING ina copia da la GN
 'version-software' => 'Software installada',
 'version-software-product' => 'Product',
 'version-software-version' => 'Versiun',
+'version-entrypoints' => "URLs dals puncts d'entrada",
+'version-entrypoints-header-entrypoint' => "Punct d'entrada",
+'version-entrypoints-header-url' => 'URL',
 
 # Special:FilePath
 'filepath' => 'Percurs da la datoteca',
@@ -3193,7 +3239,7 @@ Endatescha il num da datoteca senza il prefix "{{ns:file}}:".',
 * <span class="mw-specialpagecached">Paginas spezialas en il cache (pon esser antiquadas).</span>',
 'specialpages-group-maintenance' => 'Rapports da mantegnamant',
 'specialpages-group-other' => 'Autras paginas spezialas',
-'specialpages-group-login' => "T'annunziar / registrar",
+'specialpages-group-login' => "S'annunziar / crear in conto",
 'specialpages-group-changes' => 'Ultimas midadas e logs',
 'specialpages-group-media' => 'Rapports ed elements multimedials',
 'specialpages-group-users' => 'Utilisaders e dretgs',
@@ -3327,4 +3373,15 @@ Questa pagina ha actualmain difficultads tecnicas.',
 'api-error-uploaddisabled' => 'La funcziun da chargiar datotecas sin quest vichi è deactivada.',
 'api-error-verification-error' => 'Questa datoteca pudess esser corrupta ni avair ina extensiun faussa.',
 
+# Durations
+'duration-seconds' => '$1 {{PLURAL:$1|secunda|secundas}}',
+'duration-minutes' => '$1 {{PLURAL:$1|minuta|minutas}}',
+'duration-hours' => '$1 {{PLURAL:$1|ura|uras}}',
+'duration-days' => '$1 {{PLURAL:$1|di|dis}}',
+'duration-weeks' => '$1 {{PLURAL:$1|emna|emnas}}',
+'duration-years' => '$1 {{PLURAL:$1|onn|onns}}',
+'duration-decades' => '$1 {{PLURAL:$1|decada|decadas}}',
+'duration-centuries' => '$1 {{PLURAL:$1|tschientaner|tschientaners}}',
+'duration-millennia' => '$1 {{PLURAL:$1|millenni|millennis}}',
+
 );
index ec3693a..fbb8908 100644 (file)
@@ -992,7 +992,7 @@ Paginile .css și .js specifice utilizatorilor au titluri care încep cu literă
 'note' => "'''Notă:'''",
 'previewnote' => "'''Țineți cont că aceasta este doar o previzualizare.'''
 Modificările dumneavoastră nu au fost încă salvate!",
-'continue-editing' => 'Continuare editare',
+'continue-editing' => 'Mergi la zona de editare',
 'previewconflict' => 'Această pre-vizualizare reflectă textul din caseta de sus, respectiv felul în care va arăta articolul dacă alegeți să-l salvați acum.',
 'session_fail_preview' => "'''Ne pare rău! Nu am putut procesa modificarea dumneavoastră din cauza pierderii datelor sesiunii.
 Vă rugăm să încercați din nou.
index d9ed9c9..c0628ab 100644 (file)
@@ -711,8 +711,8 @@ Ce tu non ge si 'n'utende anonime e pinze ca le commende ca so revolte a te sond
 'noarticletext' => 'Non ge stè scritte ninde jndr\'à sta pàgene.
 Tu puè [[Special:Search/{{PAGENAME}}|cercà pe quiste titele]] jndr\'à otre pàggene, <span class="plainlinks">[{{fullurl:{{#Special:Log}}|page={{FULLPAGENAMEE}}}}] oppure [{{fullurl:{{FULLPAGENAME}}|action=edit}} cange sta pàgene]</span>.',
 'noarticletext-nopermission' => "Pe mò non ge stè teste jndr'à sta pàgene.
-Tu puè [[Special:Search/{{PAGENAME}}|cercà pe stu titele]]  jndr'à otre pàggene,
-o <span class=\"plainlinks\">[{{fullurl:{{#Special:Log}}|page={{FULLPAGENAMEE}}}} cirche jndr'à l'archivije cullegate]</span>.",
+Tu puè [[Special:Search/{{PAGENAME}}|cercà pe stu titole]] jndr'à otre pàggene,
+o <span class=\"plainlinks\">[{{fullurl:{{#Special:Log}}|page={{FULLPAGENAMEE}}}} cirche jndr'à l'archivije cullegate]</span>, ma non ge tìne le permesse pe ccrejà sta pàgene.",
 'missing-revision' => "'A revisione #\$1 d'a pàgene chiamate \"{{PAGENAME}}\" non g'esiste.
 
 Quiste succede normalmende purcé 'u cunde jè collegate a 'na pàgene ca ha state scangellate.
@@ -829,6 +829,11 @@ Pare proprie ca l'onne scangellete.",
 'edit-already-exists' => "Non ge puè ccrejà 'na pàgene nove purcè esiste già!",
 'defaultmessagetext' => 'Messàgge de teste de base',
 
+# Content models
+'content-model-text' => 'teste semblice',
+'content-model-javascript' => 'JavaScript',
+'content-model-css' => 'CSS',
+
 # Parser/template warnings
 'expensive-parserfunction-warning' => "Fà attenziò: Sta vosce tène 'nu sbuenne de funziune de chiamate a l'analizzatore.
 
@@ -1762,7 +1767,7 @@ Pò essere ca tu vuè cangià 'a descrizione de jidde [$2 pàgene de descrizione
 'shared-repo' => "'nu condenitore de cose condivise",
 'shared-repo-name-wikimediacommons' => 'Wikimedia Commons',
 'filepage.css' => "/* 'U CSS ca se iacchie aqquà jè ingluse sus 'a pàgene de descrizione d'u file, pure ingluse pe le client de le Uicchi furastire */",
-'upload-disallowed-here' => "Sfortunatamende non ge puè sovrascrivere st'immaggine.",
+'upload-disallowed-here' => 'Non ge puè sovrascrivere stu file.',
 
 # File reversion
 'filerevert' => "'Nvirte $1",
@@ -2319,8 +2324,8 @@ Tu puè avè 'nu collegamende sbagliate o 'a revisione pò essere ca ha state re
 'undeletedrevisions' => '{{PLURAL:$1|1 revisione|$1 revisiune}} ripristinete',
 'undeletedrevisions-files' => '{{PLURAL:$1|1 revisione|$1 revisiune}} e {{PLURAL:$2|1 file|$2 file}} ripristinete',
 'undeletedfiles' => '{{PLURAL:$1|1 file|$1 file}} ripristinete',
-'cannotundelete' => "Repristine fallite;
-quaccheotre pò essere ca ha repristinate 'a pàgene apprime.",
+'cannotundelete' => 'Repristine fallite:
+$1',
 'undeletedpage' => "'''$1 ha state repristinate'''
 
 Ligge l'[[Special:Log/delete|archivije de le scangellaminde]] pe 'nu report de le urteme scangellaminde e repristinaminde.",
@@ -2931,6 +2936,8 @@ Stu fatte ha state causate da 'nu collegamende a 'nu site esterne ca appartene a
 'pageinfo-magic-words' => '{{PLURAL:$1|Parole|Parole}} maggiche ($1)',
 'pageinfo-hidden-categories' => '{{PLURAL:$1|Categorije|Categorije}} scunnute ($1)',
 'pageinfo-templates' => 'Esclude {{PLURAL:$1|template|template}} ($1)',
+'pageinfo-contentpage-yes' => 'Sine',
+'pageinfo-protect-cascading-yes' => 'Sine',
 
 # Skin names
 'skinname-standard' => 'Classeche',
index af21544..923e2b3 100644 (file)
@@ -55,6 +55,7 @@
  * @author Lockal
  * @author MaxBioHazard
  * @author MaxSem
+ * @author NBS
  * @author Ola
  * @author Ole Yves
  * @author Putnik
@@ -3010,7 +3011,7 @@ $1',
 'djvu_no_xml' => 'Невозможно получить XML для DjVu',
 'thumbnail-temp-create' => 'Не удаётся создать временный файл эскиза',
 'thumbnail-dest-create' => 'Не удаётся сохранить эскиз по месту назначения',
-'thumbnail_invalid_params' => 'Ошибочный параметр миниатюры или файл содержит более 12,5 млн. пикселей',
+'thumbnail_invalid_params' => 'Ошибочный параметр миниатюры',
 'thumbnail_dest_directory' => 'Невозможно создать целевую директорию',
 'thumbnail_image-type' => 'Данный тип изображения не поддерживается',
 'thumbnail_gd-library' => 'Неполная конфигурация библиотеки GD, отсутствует функция $1',
index 7982896..a91db8d 100644 (file)
@@ -198,7 +198,6 @@ $messages = array(
 'qbbrowse' => 'Naršītė',
 'qbedit' => 'Taisītė',
 'qbpageoptions' => 'Tas poslapis',
-'qbpageinfo' => 'Konteksts',
 'qbmyoptions' => 'Mona poslapē',
 'qbspecialpages' => 'Specēlė̅jė poslapē',
 'faq' => 'DOK',
index 936f8db..8a97d5c 100644 (file)
@@ -2954,11 +2954,29 @@ $1 ගේ වාරණයට හේතුව මෙය වේ: "$2"',
 
 # Info page
 'pageinfo-title' => '"$1" සඳහා තොරතුරු',
+'pageinfo-header-basic' => 'මූලික තොරතුරු',
 'pageinfo-header-edits' => 'සංස්කරණ',
+'pageinfo-header-restrictions' => 'පිටු ආරක්ෂණය',
+'pageinfo-display-title' => 'මාතෘකාව පෙන්වන්න',
+'pageinfo-default-sort' => 'පෙරනිමි තේරීම් යතුර',
+'pageinfo-length' => 'පිටු දිග (බයිට් වලින්)',
+'pageinfo-article-id' => 'පිටු අනන්‍යනාංකය',
+'pageinfo-robot-policy' => 'සෙවුම් එන්ජිම් තත්ත්වය',
 'pageinfo-views' => 'නැරඹුම් සංඛ්‍යාව',
-'pageinfo-watchers' => 'මුරකරන්නන් සංඛ්‍යාව',
-'pageinfo-edits' => 'සංස්කරණයන් සංඛ්‍යාව',
-'pageinfo-authors' => 'ප්‍රභින්න කර්තෘවරුන් සංඛ්‍යාව',
+'pageinfo-watchers' => 'පිටු මුරකරන්නන් සංඛ්‍යාව',
+'pageinfo-redirects-name' => 'මෙම පිටුවට යළියොමු ගණන',
+'pageinfo-subpages-name' => 'මෙම පිටුවෙහි උපපිටු',
+'pageinfo-subpages-value' => '$1 ($2 {{PLURAL:$2|යළියොමු වෙයි|යළියොමු වෙති}}; $3 {{PLURAL:$3|යළියොමු-නොවෙයි|යළියොමු-නොවෙති}})',
+'pageinfo-firstuser' => 'පිටු තැනූ තැනැත්තේ',
+'pageinfo-firsttime' => 'පිටු තැනූ දිනය',
+'pageinfo-lastuser' => 'අවසන් සංස්කාරක',
+'pageinfo-lasttime' => 'අවසන් සංස්කරණය වූ දිනය',
+'pageinfo-edits' => 'මුළු සංස්කරණ සංඛ්‍යාව',
+'pageinfo-authors' => 'ප්‍රභින්න කර්තෘවරුන් මුළු  සංඛ්‍යාව',
+'pageinfo-recent-edits' => 'මෑත සංස්කරණ සංඛ්‍යාව (අවසන් $1 තුලදී)',
+'pageinfo-recent-authors' => 'මෑත ප්‍රභින්න කර්තෘවරුන් සංඛ්‍යාව',
+'pageinfo-magic-words' => 'මැජික් {{PLURAL:$1|වචනය|වචන}} ($1)',
+'pageinfo-toolboxlink' => 'පිටු තොරතුරු',
 
 # Patrolling
 'markaspatrolleddiff' => 'පරික්ෂාකර බැලූ ලෙස සලකුණු කරන්න',
index d4b6883..4a26e3a 100644 (file)
@@ -1971,7 +1971,7 @@ Možno chcete upraviť popis na jeho [$2 popisnej stránke súboru] tam.',
 'uploadnewversion-linktext' => 'Nahrať novú verziu tohto súboru',
 'shared-repo-from' => 'z $1',
 'shared-repo' => 'zdieľané úložisko',
-'upload-disallowed-here' => 'Ľutujeme, tento súbor nie je možné prepísať.',
+'upload-disallowed-here' => 'Tento súbor nie je možné prepísať.',
 
 # File reversion
 'filerevert' => 'Obnoviť $1',
index 7a310a7..3bebf45 100644 (file)
@@ -2007,7 +2007,7 @@ Kanske vill du redigera beskrivningen på dess [$2 filbeskrivningssida] där.',
 'shared-repo-from' => 'från $1',
 'shared-repo' => 'en gemensam filförvaring',
 'filepage.css' => '/* CSS som skrivs här inkluderas på filbeskrivningssidan, även på utländska klientwikis */',
-'upload-disallowed-here' => 'Du kan inte skriva över denna bild.',
+'upload-disallowed-here' => 'Du kan inte skriva över denna fil.',
 
 # File reversion
 'filerevert' => 'Återställ $1',
@@ -3117,6 +3117,7 @@ Detta orsakades troligen av en länk till en svartlistad webbplats.',
 
 # Info page
 'pageinfo-title' => 'Information om "$1"',
+'pageinfo-not-current' => 'Information kan endast visas för den aktuella versionen.',
 'pageinfo-header-basic' => 'Grundläggande information',
 'pageinfo-header-edits' => 'Redigeringshistorik',
 'pageinfo-header-restrictions' => 'Sidskydd',
@@ -3145,6 +3146,11 @@ Detta orsakades troligen av en länk till en svartlistad webbplats.',
 'pageinfo-hidden-categories' => '{{PLURAL:$1|Dold kategori|Dolda kategorier}} ($1)',
 'pageinfo-templates' => '{{PLURAL:$1|Inkluderad mall|Inkluderade mallar}} ($1)',
 'pageinfo-toolboxlink' => 'Sidinformation',
+'pageinfo-redirectsto' => 'Omdirigerar till',
+'pageinfo-redirectsto-info' => 'info',
+'pageinfo-contentpage' => 'Räknas som en innehållssida',
+'pageinfo-contentpage-yes' => 'Ja',
+'pageinfo-protect-cascading-yes' => 'Ja',
 
 # Skin names
 'skinname-standard' => 'Standard',
index daf40e2..f8fca7a 100644 (file)
@@ -740,7 +740,7 @@ or <span class="plainlinks">[{{fullurl:{{#Special:Log}}|page={{FULLPAGENAMEE}}}}
 'updated' => '(இற்றைப்படுத்தப்பட்டது)',
 'note' => "'''குறிப்பு:'''",
 'previewnote' => "'''இது ஒரு முன்தோற்றம் மட்டுமே''', உங்கள் மாற்றங்கள் இன்னும் சேமிக்கப்படவில்லை!",
-'continue-editing' => 'தà¯\8aà®\95à¯\81தà¯\8dதலà¯\88தà¯\8d à®¤à¯\8aà®\9fà®°வும்',
+'continue-editing' => 'தà¯\8aà®\95à¯\81à®\95à¯\8dà®\95à¯\81à®®à¯\8d à®ªà®\95à¯\81திà®\95à¯\8dà®\95à¯\81 à®\9aà¯\86லà¯\8dலவும்',
 'previewconflict' => 'இந்த முன்தோற்றம் உரை தொகுப்புப் பகுதியின் மேற்பகுதியிலுள்ள உரையைப் பிரதிபலிக்கின்றது. நீங்கள் இப்பொழுது சேமித்தால் மேற்படி தோற்றமே கிடைக்கும்.',
 'session_fail_preview' => "'''உங்கள் அமர்வுத் தரவுகள் அழிந்துப்போனமையால் உங்கள் தொகுப்பை செயற்படுத்த முடியவில்லை. அருள் கூர்ந்து மீண்டும் முயலவும். அதுவும் பலனளிக்காவிட்டால் விடுபதிகைச் செய்து மீண்டும் புகுபதிகைச் செய்யவும்'''",
 'session_fail_preview_html' => "'''மன்னிக்கவும்! தங்கள் அமர்வுத் தரவுகள் அழிந்துப்போனமையால் தொகுப்பைச் செயற்படுத்த முடியவில்லை.'''
@@ -1687,6 +1687,7 @@ $1',
 'uploadnewversion-linktext' => 'இப்படிமத்தின் புதிய பதிப்பை பதிவேற்று',
 'shared-repo-from' => '$1-ல் இருந்து',
 'shared-repo' => 'பகிர்ந்து பயன்கொள் வைப்பகம்',
+'upload-disallowed-here' => 'நீங்கள் இந்தக் கோப்பை மேலெழுத முடியாது.',
 
 # File reversion
 'filerevert' => '$1 ஐ முன்நிலையாக்கு',
@@ -1771,6 +1772,7 @@ $1',
 'doubleredirects' => 'இரட்டை வழிமாற்றுகள்',
 'doubleredirectstext' => 'இந்தப் பட்டியல் போலியான நேர்மதிப்புக்களைக் கொண்டிருக்கக்கூடும். இது வழக்கமாக, இணைப்புடன் கூடிய மேலதிக உரை முதலாவது #வழிமாற்றுக்குக் கீழ் இருப்பதைக் குறிக்கும்.ஒவ்வொரு வரியும், முதலாம் இரண்டாம் வழிமாற்றுகளுக்கு இணைப்புகளைக் கொண்டிருப்பதுடன், இரண்டாவது வழிமாற்று உரையின் முதல் வரிக்கும் இணைப்பைக் கொண்டிருக்கும், இது வழக்கமாக முதலாவது வழிமாற்று குறித்துக் காட்ட வேண்டிய "உண்மையான" இலக்குக் கட்டுரையைக் கொடுக்கும்.',
 'double-redirect-fixed-move' => '[[$1]] நகர்த்தப்பட்டுவிட்டது. இப்பொழுது [[$2]] உக்கு வழிமாற்று தருகின்றது.',
+'double-redirect-fixed-maintenance' => '[[$1]] என்பதிலிருந்து [[$2]] என்பதற்கு இரட்டை வழிமாற்றைச் சரிசெய்கிறது',
 'double-redirect-fixer' => '(இரட்டை) வழிமாற்றைத் திருத்தியபயனர்',
 
 'brokenredirects' => 'முறிந்த வழிமாற்றுகள்',
@@ -1952,6 +1954,7 @@ $1',
 'mailnologintext' => 'நீங்கள்[[Special:UserLogin|புகுபதிகை செய்திருப்பதுடன்]]
 ஏனைய பயனர்களுக்கு மின்னஞ்சல் அனுப்பக்கூடியத்தாக செல்லுபடியாகக்கூடிய மின்னஞ்சல் முகவரியொன்றும் உங்களுடைய  [[Special:Preferences|விருப்பத் தெரிவுகளில்]] கொடுபட்டிருக்கவேண்டும்.',
 'emailuser' => 'இப் பயனருக்கு மின்னஞ்சல் செய்',
+'emailuser-title-notarget' => 'பயனருக்கு மின்னஞ்சல் செய்',
 'emailpage' => 'மின்னஞ்சல் பயனர்',
 'emailpagetext' => 'நீங்கள் கீழ்வரும் படிவத்தை உபயோகித்து இந்த பயனருக்கு மின்னஞ்சல் செய்யலாம்.
 
@@ -2707,9 +2710,19 @@ $1',
 
 # Info page
 'pageinfo-title' => '"$1" பக்கத்துக்கான தகவல்',
-'pageinfo-header-edits' => 'தொகுப்புகள்',
+'pageinfo-header-basic' => 'அடிப்படைத் தகவல்',
+'pageinfo-header-edits' => 'தொகுப்பு வரலாறு',
+'pageinfo-header-restrictions' => 'பக்கக் காப்பு',
+'pageinfo-header-properties' => 'பக்க இயல்புகள்',
+'pageinfo-display-title' => 'காட்சித் தலைப்பு',
+'pageinfo-length' => 'பக்க நீளம் (எண்ணுண்மிகளில்)',
+'pageinfo-article-id' => 'பக்க அடையாள இலக்கம்',
+'pageinfo-robot-policy' => 'தேடற்பொறி நிலைமை',
 'pageinfo-views' => 'காட்சிகள் எண்ணிக்கை',
 'pageinfo-watchers' => 'பார்வையாளர்கள் எண்ணிக்கை',
+'pageinfo-firstuser' => 'பக்க உருவாக்குநர்',
+'pageinfo-firsttime' => 'பக்கம் உருவாக்கப்பட்ட காலம்',
+'pageinfo-lastuser' => 'பிந்திய தொகுப்பாளர்',
 'pageinfo-edits' => 'தொகுப்புகளின் எண்ணிக்கை:',
 'pageinfo-authors' => 'சாதகமான அம்சங்களை பெற்றிருக்கும் எழுத்தாளர்கள் எண்ணிக்கை',
 
index 5bbccf2..4c08f5c 100644 (file)
@@ -809,7 +809,7 @@ $2
 'note' => "'''గమనిక:'''",
 'previewnote' => "'''ఇది మునుజూపు మాత్రమేనని గుర్తుంచుకోండి.'''
 మీ మార్పులు ఇంకా భద్రమవ్వలేదు!",
-'continue-editing' => 'దిదà±\8dà°¦à±\81బాà°\9fà±\81ని à°\95à±\8aనసాà°\97à°¿à°\82à°\9aండి',
+'continue-editing' => 'సరిదిదà±\8dà°¦à±\87 à°\9aà±\8bà°\9fà±\81à°\95à°¿ à°µà±\86à°³à±\8dà°³ండి',
 'previewconflict' => 'భద్రపరచిన తరువాత పై టెక్స్ట్‌ ఏరియాలోని టెక్స్టు ఇలాగ కనిపిస్తుంది.',
 'session_fail_preview' => "'''క్షమించండి! సెషను డేటా పోవడం వలన మీ మార్పులను స్వీకరించలేకపోతున్నాం.'''
 దయచేసి మళ్ళీ ప్రయత్నించండి.
index 8aac893..f585128 100644 (file)
@@ -21,6 +21,7 @@
  * @author Goktr001
  * @author Hanberke
  * @author Hcagri
+ * @author Hedda Gabler
  * @author Ijon
  * @author Incelemeelemani
  * @author Joseph
@@ -480,7 +481,7 @@ $messages = array(
 'vector-action-protect' => 'Koru',
 'vector-action-undelete' => 'Silinmeyi geri al',
 'vector-action-unprotect' => 'Korumayı değiştir',
-'vector-simplesearch-preference' => 'Gelişmiş arama önerilerini getir (Sadece Vector görünümü için)',
+'vector-simplesearch-preference' => 'Gelişmiş arama önerilerini etkinleştir (Sadece Vector görünümü için)',
 'vector-view-create' => 'Oluştur',
 'vector-view-edit' => 'Düzenle',
 'vector-view-history' => 'Geçmişi gör',
@@ -503,7 +504,7 @@ $messages = array(
 'updatedmarker' => 'son ziyaretimden sonra güncellenmiş',
 'printableversion' => 'Yazdırılabilir sürüm',
 'permalink' => 'Kalıcı bağlantı',
-'print' => 'Bastır',
+'print' => 'Yazdır',
 'view' => 'Görüntüle',
 'edit' => 'Düzenle',
 'create' => 'Oluştur',
@@ -587,7 +588,9 @@ $1',
 'youhavenewmessages' => 'Yeni $1 var ($2).',
 'newmessageslink' => 'mesajınız',
 'newmessagesdifflink' => 'son değişiklik',
-'newmessageslinkplural' => 'mesajınız',
+'youhavenewmessagesfromusers' => '{{PLURAL:$3|Başka bir kullanıcıdan|$3 kullanıcıdan}} yeni $1 var. ($2)',
+'youhavenewmessagesmanyusers' => 'Birçok kullanıcıdan $1 var. ($2)',
+'newmessageslinkplural' => '{{PLURAL:$1|yeni mesaj|yeni mesaj}}',
 'newmessagesdifflinkplural' => 'son {{PLURAL:$1|değişiklik|değişiklikler}}',
 'youhavenewmessagesmulti' => "$1'de yeni mesajınız var.",
 'editsection' => 'düzenle',
@@ -640,7 +643,7 @@ Bu, {{SITENAME}} sitesindeki bir hatayı da belirtebilir.",
 # General errors
 'error' => 'Hata',
 'databaseerror' => 'Veritabanı hatası',
-'dberrortext' => 'Veritabanı sorgu sözdizimi hatası oluştu.
+'dberrortext' => 'Bir veritabanı sorgusu sözdizimi hatası oluştu.
 Bu yazılımdaki bir hatadan kaynaklanabilir.
 "<tt>$2</tt>" işlevinden denenen son sorgulama:
 <blockquote><tt>$1</tt></blockquote>.
@@ -700,7 +703,7 @@ Lütfen birkaç dakika sonra yeniden deneyin.',
 'viewsourcetext' => 'Bu sayfanın kaynağını görebilir ve kopyalayabilirsiniz:',
 'viewyourtext' => "Bu sayfaya '''yaptığınız değişikliklerin''' kaynağını görünteleyip kopyalayabilirsiniz:",
 'protectedinterface' => "Bu sayfa yazılım için arayüz metni sağlamaktadır ve kötüye kullanımı önlemek için korumaya alınmıştır. Eklemek ya da bütün vikilerdeki çevirileri değiştirmek için lütfen MediaWiki yerelleştirme projesi [//translatewiki.net/ translatewiki.net]'i kullanın.",
-'editinginterface' => "'''UYARI:''' Yazılım için arayüz sağlamakta kullanılan bir sayfayı değiştirmektesiniz. Bu sayfadaki değişiklikler kullanıcı arayüzünü diğer kullanıcılar için de değiştirecektir. Çeviriler için, lütfen [//translatewiki.net/wiki/Main_Page?setlang=tr translatewiki.net]'yi kullanarak MediaWiki yerelleştirme projesini dikkate alınız.",
+'editinginterface' => "'''UYARI:''' Wiki yazılımı için arayüz sağlamakta kullanılan bir sayfayı değiştirmektesiniz. Bu sayfadaki değişiklikler kullanıcı arayüzünü diğer kullanıcılar için de değiştirecektir. Çeviriler için, lütfen [//translatewiki.net/wiki/Main_Page?setlang=tr translatewiki.net]'yi kullanarak MediaWiki yerelleştirme projesini dikkate alınız.",
 'sqlhidden' => '(SQL gizli sorgu)',
 'cascadeprotected' => 'Bu sayfa değişiklik yapılması engellenmiştir, çünkü  "kademeli" seçeneği aktif hale getirilerek koruma altına alınan {{PLURAL:$1|sayfada|sayfada}} kullanılmaktadır:
 $2',
@@ -1076,9 +1079,14 @@ Silinmiş görünüyor.',
 'edit-already-exists' => 'Yeni sayfa oluşturulamıyor.
 Sayfa zaten mevcut.',
 'defaultmessagetext' => 'Varsayılan mesaj metni',
+'invalid-content-data' => 'Geçersiz içerik verisi',
+'content-not-allowed-here' => '"$1" içeriğine, [[$2]] sayfasında izin verilmemekte.',
 
 # Content models
+'content-model-wikitext' => 'vikimetin',
+'content-model-text' => 'düz metin',
 'content-model-javascript' => 'JavaScript',
+'content-model-css' => 'CSS',
 
 # Parser/template warnings
 'expensive-parserfunction-warning' => 'Uyarı: Bu sayfa çok fazla zengin derleyici fonksiyonu çağrısı içeriyor.
@@ -1094,6 +1102,11 @@ Bu değişkenler atlandı.",
 'parser-template-loop-warning' => 'Şablon düğümü tespit edildi: [[$1]]',
 'parser-template-recursion-depth-warning' => 'Şablon özyineleme yoğunluğu sınırı aşıldı ($1)',
 'language-converter-depth-warning' => 'Dil çevirici derinlik sınırı aşıldı ($1)',
+'node-count-exceeded-category' => 'Düğüm sayısı aşılan sayfalar',
+'node-count-exceeded-warning' => 'Sayfa düğüm sayımı aşıldı',
+'expansion-depth-exceeded-category' => 'Genişleme derinliği aşılan sayfalar',
+'expansion-depth-exceeded-warning' => 'Sayfa genişletme derinliği aşıldı',
+'parser-unstrip-loop-warning' => 'Yineleme döngüsü algılandı',
 
 # "Undo" feature
 'undo-success' => 'Bu değişiklik geri alınabilir. Lütfen aşağıdaki karşılaştırmayı kontrol edin, gerçekten bu değişikliği yapmak istediğinizden emin olun ve sayfayı kaydederek bir önceki değişikliği geriye alın.',
@@ -1225,9 +1238,11 @@ Erişiminiz yok.',
 'revdelete-concurrent-change' => '$2 $1 tarihli öğe değiştirilirken hata: öğenin durumu siz değiştirmeye çalışırken bir başkası tarafından değiştirilmiş görünüyor.
 Lütfen günlükleri kontrol edin.',
 'revdelete-only-restricted' => '$2 $1 tarihli öğe gizlenirken hata: Öğeleri, diğer gizleme seçeneklerinden birini seçmeden, hizmetli görünümden bastıramazsınız.',
-'revdelete-reason-dropdown' => '*Genel silme sebepleri
-** Telif ihlali
-** Uygunsuz kişisel bilgi',
+'revdelete-reason-dropdown' => '*Genel silme nedenleri
+** Telif hakkı ihlali
+** Sakıncalı yorum veya kişisel bilgi 
+** Sakıncalı kullanıcı adı
+** Muhtemel iftira niteliğinde bilgiler',
 'revdelete-otherreason' => 'Diğer/ek sebep:',
 'revdelete-reasonotherlist' => 'Diğer sebep',
 'revdelete-edit-reasonlist' => 'Silme nedenlerini değiştir',
@@ -1272,6 +1287,7 @@ Gezinti bağlantılarının bu sütunu sıfırlayacağını unutmayın.',
 # Diffs
 'history-title' => '"$1" sayfasının geçmişi',
 'difference-title' => '"$1" sayfasının sürümleri arasındaki fark',
+'difference-title-multipage' => '"$1" ile "$2" sayfaları arasındaki fark',
 'difference-multipage' => '(Sayfalar arasındaki fark)',
 'lineno' => '$1. satır:',
 'compareselectedversions' => 'Seçilen sürümleri karşılaştır',
@@ -1417,7 +1433,7 @@ Kullanabileceğiniz rastgele-üretilmiş bir değer: $1',
 'timezoneregion-indian' => 'Hint Okyanusu',
 'timezoneregion-pacific' => 'Pasifik Okyanusu',
 'allowemail' => 'Diğer kullanıcılar bana e-posta atabilsin',
-'prefs-searchoptions' => 'Arama seçenekleri',
+'prefs-searchoptions' => 'Arama',
 'prefs-namespaces' => 'İsim alanları',
 'defaultns' => 'Aksi halde bu ad alanlarında ara:',
 'default' => 'varsayılan',
@@ -1816,8 +1832,11 @@ Eğer sorun tekrarlanırsa, bir [[Special:ListUsers/sysop|hizmetli]] ile temasa
 'upload-http-error' => 'Bir HTTP hatası oluştu: $1',
 
 # File backend
+'backend-fail-stream' => '$1 dosyası okunamadı.',
 'backend-fail-notexists' => '$1 dosyası mevcut değil.',
+'backend-fail-invalidpath' => '"$1" geçerli bir depolama yolu değil.',
 'backend-fail-delete' => '"$1" dosyası silinemedi.',
+'backend-fail-alreadyexists' => '"$1" dosyası zaten mevcut.',
 'backend-fail-opentemp' => 'Geçici dosya açılamadı.',
 'backend-fail-closetemp' => 'Geçici dosya kapanamadı.',
 'backend-fail-read' => '$1 dosyası okunamadı.',
@@ -2065,6 +2084,7 @@ Her satırın içerdiği bağlantılar; birinci ve ikinci yönlendirme, ayrıca
 'mostlinkedtemplates' => 'En çok kullanılan şablonlar',
 'mostcategories' => 'En fazla kategoriye bağlanmış sayfalar',
 'mostimages' => 'En çok bağlantı verilmiş dosyalar',
+'mostinterwikis' => "En çok interwiki'ye sahip sayfalar",
 'mostrevisions' => 'En çok değişikliğe uğramış sayfalar',
 'prefixindex' => 'Önek ile tüm sayfalar',
 'shortpages' => 'Kısa sayfalar',
@@ -2136,6 +2156,9 @@ Günlük tipini, kullanıcı adını (büyük-küçük harf duyarlı), ya da etk
 'allpages-bad-ns' => '{{SITENAME}} sitesinde "$1" ad alanı yok.',
 'allpages-hide-redirects' => 'Yönlendirmeleri gizle',
 
+# SpecialCachedPage
+'cachedspecial-refresh-now' => 'En son görünüm.',
+
 # Special:Categories
 'categories' => 'Kategoriler',
 'categoriespagetext' => "Aşağıdaki {{PLURAL:$1|kategori|kategoriler}} sayfa veya ortam içerir.
@@ -2203,6 +2226,8 @@ Bireysel haklarla ilgili [[{{MediaWiki:Listgrouprights-helppage}}|daha fazla bil
 'mailnologin' => 'Gönderi adresi yok.',
 'mailnologintext' => 'Diğer kullanıcılara e-posta gönderebilmeniz için [[Special:UserLogin|oturum aç]]malısınız ve [[Special:Preferences|tercihler]] sayfasında geçerli bir e-posta adresiniz olmalı.',
 'emailuser' => 'Bu kullanıcıya e-posta gönder',
+'emailuser-title-target' => 'Bu {{GENDER:$1|kullanıcıya}} e-posta gönder',
+'emailuser-title-notarget' => 'Kullanıcı e-posta',
 'emailpage' => 'Kullanıcıya e-posta gönder',
 'emailpagetext' => 'Bu kullanıcıya e-posta mesajı göndermek için aşağıdaki formu kullanabilirsiniz.
 [[Special:Preferences|Kullanıcı tercihlerinizde]] girdiğiniz e-posta adresiniz, e-postanın "From (Kimden)" adresinde görünecektir, bu yüzden alıcı size direk cevap verebilecektir.',
@@ -2476,6 +2501,7 @@ Revizyon onarılmış veya arşivden silinmiş olabilir ya da sahip olduğunuz b
 'undelete-cleanup-error' => 'Kullanılmayan "$1" arşiv dosyasını silerken hata.',
 'undelete-missing-filearchive' => 'Dosya arşiv IDsi $1 geri getirilemiyor çünkü veritabanında değil.
 Daha önceden silinmesi geri alınmış olabilir.',
+'undelete-error' => 'Sayfa silinemiyor hatası',
 'undelete-error-short' => 'Bu dosyanın silinmesini geri alırken hata çıktı: $1',
 'undelete-error-long' => 'Bu dosyanın silinmesini geri alırken hatalar çıktı:
 
@@ -2831,6 +2857,7 @@ Bütün vikilerarası içe aktarım eylemleri [[Special:Log/import|içe aktarım
 'import-interwiki-templates' => 'Tüm şablonları içer',
 'import-interwiki-submit' => 'Import',
 'import-interwiki-namespace' => 'Hedef ad alanı:',
+'import-interwiki-rootpage' => 'Hedeflenen kaynak sayfası (isteğe bağlı):',
 'import-upload-filename' => 'Dosya adı:',
 'import-comment' => 'Yorum:',
 'importtext' => 'Lütfen dosyayı [[Special:Export|dışa aktarım yardımcı yazılımıyla]] kaynak vikiden dışa aktarın.
@@ -2974,11 +3001,36 @@ Geçici dosya kayıp.',
 
 # Info page
 'pageinfo-title' => 'Bilgi için "$1"',
-'pageinfo-header-edits' => 'Değişiklikler',
+'pageinfo-header-basic' => 'Temel bilgiler',
+'pageinfo-header-edits' => 'Düzenleme geçmişi',
+'pageinfo-header-restrictions' => 'Sayfa koruması',
+'pageinfo-header-properties' => 'Sayfa özellikleri',
+'pageinfo-display-title' => 'Görüntülenen başlık',
+'pageinfo-default-sort' => 'Varsayılan sıralama anahtarı',
+'pageinfo-length' => 'Sayfa uzunluğu (bayt cinsinden)',
+'pageinfo-article-id' => 'Sayfa ID',
+'pageinfo-robot-policy' => 'Arama motoru durumu',
+'pageinfo-robot-index' => 'İndekslenebilir',
+'pageinfo-robot-noindex' => 'İndekslenemez',
 'pageinfo-views' => 'Görüntülenme sayısı',
-'pageinfo-watchers' => 'İzleyen sayısı',
+'pageinfo-watchers' => 'Sayfanın izleyici sayısı',
+'pageinfo-redirects-name' => 'Bu sayfaya yönlendirmeler',
 'pageinfo-redirects-value' => '$1',
+'pageinfo-subpages-name' => 'Bu sayfanın alt sayfaları',
+'pageinfo-firstuser' => 'Sayfa oluşturucu',
+'pageinfo-firsttime' => 'Sayfa oluşturulma tarihi',
+'pageinfo-lastuser' => 'En son düzenleyici',
+'pageinfo-lasttime' => 'Son düzenleme tarihi',
 'pageinfo-edits' => 'Değişiklik sayısı',
+'pageinfo-authors' => 'Farklı yazar sayısı',
+'pageinfo-recent-authors' => 'Farklı yazarların son sayısı',
+'pageinfo-magic-words' => 'Sihirli {{PLURAL:$1|kelimeler|kelimeler}} ($1)',
+'pageinfo-toolboxlink' => 'Sayfa bilgisi',
+'pageinfo-redirectsto' => 'Yönlendirilen',
+'pageinfo-redirectsto-info' => 'bilgi',
+'pageinfo-contentpage' => 'Bir içerik sayfası sayılır',
+'pageinfo-contentpage-yes' => 'Evet',
+'pageinfo-protect-cascading-yes' => 'Evet',
 
 # Skin names
 'skinname-standard' => 'Klasik',
@@ -3233,6 +3285,7 @@ Diğerleri varsayılan olarak gizlenecektir.
 'exif-serialnumber' => 'Kameranın seri numarası',
 'exif-cameraownername' => 'Kameranın sahibi',
 'exif-label' => 'Etiket',
+'exif-nickname' => 'Görüntünün resmî olmayan adı',
 'exif-rating' => 'Oylama (5 üzerinden)',
 'exif-copyrighted' => 'Telif hakkı durumu',
 'exif-copyrightowner' => 'Telif hakkı sahibi',
@@ -3240,12 +3293,15 @@ Diğerleri varsayılan olarak gizlenecektir.
 'exif-webstatement' => 'Çevrimiçi telif hakkı bildirimi',
 'exif-licenseurl' => 'Telif hakkı lisansı için URL',
 'exif-morepermissionsurl' => 'Alternatif lisans bilgileri',
+'exif-attributionurl' => 'Bu çalışmayı yeniden kullanırken lütfen bağlantı verin',
 'exif-pngfilecomment' => 'PNG dosyası yorumu',
 'exif-disclaimer' => 'Sorumluluk reddi',
 'exif-contentwarning' => 'İçerik uyarısı',
 'exif-giffilecomment' => 'GIF dosyası yorumu',
+'exif-intellectualgenre' => 'Öğe türü',
 'exif-subjectnewscode' => 'Konu kodu',
 'exif-event' => 'Adı geçen olay',
+'exif-organisationinimage' => 'Organizasyon gösterilmiştir',
 'exif-personinimage' => 'Adı geçen kişi',
 'exif-originalimageheight' => 'Resmin kırpılmadan önceki yükseliği',
 'exif-originalimagewidth' => 'Resmin kırpılmadan önceki genişliği',
@@ -3680,6 +3736,9 @@ Bu programla birlikte [{{SERVER}}{{SCRIPTPATH}}/COPYING GNU Genel Kamu Lisansın
 'version-software' => 'Yüklü yazılım',
 'version-software-product' => 'Ürün',
 'version-software-version' => 'Versiyon',
+'version-entrypoints' => "Giriş noktası URL'leri",
+'version-entrypoints-header-entrypoint' => 'Giriş noktası',
+'version-entrypoints-header-url' => 'URL',
 
 # Special:FilePath
 'filepath' => 'Dosyanın konumu',
@@ -3813,6 +3872,7 @@ Resimler tam çözünürlükte görüntülenir, diğer dosya tipleri ilgili prog
 'feedback-cancel' => 'İptal',
 'feedback-submit' => 'Geribildirimi Gönder',
 'feedback-adding' => 'Sayfaya geribildirim ekleniyor...',
+'feedback-error1' => 'Hata: Bilinmeyen API sonucu',
 'feedback-error2' => 'Hata: Düzenleme başarısız oldu',
 'feedback-error3' => "Hata: API'den yanıt yok",
 'feedback-thanks' => 'Teşekkürler! Görüşleriniz "[$2 $1]" sayfasında paylaşılmıştır.',
@@ -3830,20 +3890,28 @@ Resimler tam çözünürlükte görüntülenir, diğer dosya tipleri ilgili prog
 'api-error-duplicate-popup-title' => 'Çift {{PLURAL:$1|dosya|dosya}}',
 'api-error-empty-file' => 'Gönderdiğiniz dosya boş.',
 'api-error-emptypage' => 'Yeni, boş bir sayfa oluşturmaya izin verilmez.',
+'api-error-fetchfileerror' => 'İç hata: Dosya alınırken bir hata oluştu.',
+'api-error-fileexists-forbidden' => '"$1" adıyla bir dosya zaten mevcut dolayısıyla üzerine yazamazsınız.',
 'api-error-file-too-large' => 'Gönderdiğiniz dosya çok büyük.',
 'api-error-filename-tooshort' => 'Dosya adı çok kısa.',
 'api-error-filetype-banned' => 'Bu dosya biçimi yasaklanmıştır.',
 'api-error-filetype-banned-type' => '$1 {{PLURAL:$4|izin verilen bir dosya türü değil|izin verilen bir dosya türü değil}}. İzin verilen {{PLURAL:$3|dosya türü|dosya türleri}} $2.',
 'api-error-filetype-missing' => 'Dosya uzantısı eksik.',
+'api-error-hookaborted' => 'Yapmaya çalıştığınız değişiklik bir eklenti tarafından iptal edildi.',
 'api-error-http' => 'İç hata: sunucu ile bağlantı kurulamıyor.',
 'api-error-illegal-filename' => 'Bu dosya adına izin verilmiyor.',
+'api-error-internal-error' => "İç hata: Wiki'ye yükleme yapma işleminizde bir şeyler ters gitti.",
 'api-error-invalid-file-key' => 'İç hata: geçici depolama dosyası bulunamadı.',
+'api-error-missingparam' => 'İç hata: İstenilen parametreler eksik.',
+'api-error-missingresult' => 'İç hata: Kopyalamanın başarılı olup olmadığı belirlenemedi.',
 'api-error-mustbeloggedin' => 'Dosya yükleyebilmek için oturum açmanız gereklidir.',
 'api-error-mustbeposted' => 'İç hata: İstek HTTP POST gerektiriyor.',
+'api-error-noimageinfo' => 'Yükleme başarılı oldu, ancak sunucu, bize dosya hakkında herhangi bir bilgi vermedi.',
 'api-error-nomodule' => 'İç hata: Yükleme modülü ayarı yapılmadı.',
 'api-error-ok-but-empty' => 'İç hata: Sunucu yanıt vermiyor.',
 'api-error-overwrite' => 'Varolan dosyanın üzerine yazmaya izin verilmiyor.',
 'api-error-stashfailed' => 'İç hata: Sunucu, geçici dosyaları kaybetti.',
+'api-error-timeout' => 'Sunucu beklenen süre içinde yanıt vermedi.',
 'api-error-unclassified' => 'Bilinmeyen bir hata oluştu.',
 'api-error-unknown-code' => 'Bilinmeyen hata: "$1"',
 'api-error-unknown-error' => 'İç hata: Dosya yüklemeye çalışırken bir şeyler ters gitti.',
@@ -3852,4 +3920,15 @@ Resimler tam çözünürlükte görüntülenir, diğer dosya tipleri ilgili prog
 'api-error-uploaddisabled' => 'Yükleme bu vikide devre dışı bırakılmıştır.',
 'api-error-verification-error' => 'Dosya bozuk veya yanlış uzantıya sahip olabilir.',
 
+# Durations
+'duration-seconds' => '$1 {{PLURAL:$1|saniye|saniye}}',
+'duration-minutes' => '$1 {{PLURAL:$1|dakika|dakika}}',
+'duration-hours' => '$1 {{PLURAL:$1|saat|saat}}',
+'duration-days' => '$1 {{PLURAL:$1|gün|gün}}',
+'duration-weeks' => '$1 {{PLURAL:$1|hafta|hafta}}',
+'duration-years' => '$1 {{PLURAL:$1|yıl|yıl}}',
+'duration-decades' => '$1 {{PLURAL:$1|on yıl|on yıl}}',
+'duration-centuries' => '$1 {{PLURAL:$1|yüzyıl|yüzyıl}}',
+'duration-millennia' => '$1 {{PLURAL:$1|bin yıl|bin yıl}}',
+
 );
index 0315ba6..06531ed 100644 (file)
@@ -725,7 +725,7 @@ $1',
 'badtitletext' => 'Запитана назва сторінки неправильна, порожня, або неправильно зазначена міжмовна чи міжвікі назва.
 Можливо, в назві використовуються недопустимі символи.',
 'perfcached' => 'Наступні дані взяті з кешу і можуть бути застарілими. В кеші зберігається не більше  {{PLURAL:$1| запису| записів}}.',
-'perfcachedts' => 'Ð\9dаÑ\81Ñ\82Ñ\83пнÑ\96 Ð´Ð°Ð½Ñ\96 Ð²Ð·Ñ\8fÑ\82Ñ\96 Ð· ÐºÐµÑ\88Ñ\83, Ð²Ð¾Ñ\81Ñ\82аннÑ\94 Ð²Ñ\96н Ð¾Ð½Ð¾Ð²Ð»Ñ\8eвавÑ\81Ñ\8f Ð¾ $1. Ð\92 ÐºÐµÑ\88Ñ\96 Ð·Ð±ÐµÑ\80Ñ\96гаÑ\94Ñ\82Ñ\8cÑ\81Ñ\8f Ð½Ðµ Ð±Ñ\96лÑ\8cÑ\88е {{PLURAL:$4|запису|записів}}.',
+'perfcachedts' => 'Ð\9dаÑ\81Ñ\82Ñ\83пнÑ\96 Ð´Ð°Ð½Ñ\96 Ð²Ð·Ñ\8fÑ\82Ñ\96 Ð· ÐºÐµÑ\88Ñ\83, Ð²Ð¾Ñ\81Ñ\82аннÑ\94 Ð²Ñ\96н Ð¾Ð½Ð¾Ð²Ð»Ñ\8eвавÑ\81Ñ\8f Ð¾ $1. Ð£ ÐºÐµÑ\88Ñ\96 Ð·Ð±ÐµÑ\80Ñ\96гаÑ\94Ñ\82Ñ\8cÑ\81Ñ\8f Ð½Ðµ Ð±Ñ\96лÑ\8cÑ\88е $4 {{PLURAL:$4|запису|записів}}.',
 'querypage-no-updates' => 'Зміни цієї сторінки зараз заборонені. Дані тут не можуть бути оновлені зараз.',
 'wrong_wfQuery_params' => 'Неприпустима параметри функцій wfQuery()<br />
 Функція: $1<br />
@@ -1024,6 +1024,10 @@ $2
 'noarticletext-nopermission' => 'Зараз на цій сторінці немає тексту.
 Ви можете [[Special:Search/{{PAGENAME}}|пошукати цю назву]] на інших сторінках,
 або <span class="plainlinks">[{{fullurl:{{#Special:Log}}|page={{FULLPAGENAMEE}}}} пошукати пов\'язані записи в журналах]</span>, але ви не маєте дозволу на створення такої сторінки.',
+'missing-revision' => 'Версія #$1 сторінки «{{PAGENAME}}» не існує.
+
+Імовірно, Ви перейшли за застарілим посиланням на вилучену сторінку.
+Подробиці можна дізнатися з [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} журналу вилучень].',
 'userpage-userdoesnotexist' => 'Користувач під назвою "<nowiki>$1</nowiki>" не зареєстрований. Переконайтеся, що ви хочете створити/редагувати цю сторінку.',
 'userpage-userdoesnotexist-view' => 'Обліковий запис користувача „$1“ не зареєстровано.',
 'blocked-notice-logextract' => 'Цей користувач наразі заблокований.
@@ -1340,6 +1344,10 @@ $1",
 'editundo' => 'скасувати',
 'diff-multi' => '({{PLURAL:$1|Одна проміжна версія одного користувача не показана|$1 проміжні версії {{PLURAL:$2|одного користувача|$2 користувачів}} не показані|$1 проміжних версій {{PLURAL:$2|одного користувача|$2 користувачів}} не показані}})',
 'diff-multi-manyusers' => '({{PLURAL:$1|не показана $1 проміжна я версія|не показані $1 проміжні версії|не показано $1 проміжних версій}}, зроблених більш, ніж {{PLURAL:$2|$1 користувачем|$2 користувачами}})',
+'difference-missing-revision' => '{{PLURAL:$2|$2 версія|$2 версії|$2 версій}} для цього порівняння ($1) не {{PLURAL:$2|знайдене|знайдені}}.
+
+Імовірно, ви перейшли за застарілим посиланням на порівняння версій вилученої сторінки.
+Подробиці можна дізнатися з [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} журналу вилучень].',
 
 # Search results
 'searchresults' => 'Результати пошуку',
@@ -1477,7 +1485,7 @@ $1",
 'timezoneregion-indian' => 'Індійський океан',
 'timezoneregion-pacific' => 'Тихий океан',
 'allowemail' => 'Дозволити електронну пошту від інших користувачів',
-'prefs-searchoptions' => 'Ð\9fаÑ\80амеÑ\82Ñ\80и Ð¿Ð¾Ñ\88Ñ\83кÑ\83',
+'prefs-searchoptions' => 'Ð\9fоÑ\88Ñ\83к',
 'prefs-namespaces' => 'Простори назв',
 'defaultns' => 'Інакше шукати в таких просторах назв:',
 'default' => 'за умовчанням',
@@ -2157,6 +2165,7 @@ $1',
 # Miscellaneous special pages
 'nbytes' => '$1 {{PLURAL:$1|байт|байти|байтів}}',
 'ncategories' => '$1 {{PLURAL:$1|категорія|категорії|категорій}}',
+'ninterwikis' => '$1 {{PLURAL:$1|інтервікі-посилання|інтервікі-посилання|інтервікі-посилань}}',
 'nlinks' => '$1 {{PLURAL:$1|посилання|посилання|посилань}}',
 'nmembers' => "$1 {{PLURAL:$1|об'єкт|об'єкти|об'єктів}}",
 'nrevisions' => '$1 {{PLURAL:$1|версія|версії|версій}}',
@@ -3165,14 +3174,28 @@ The wiki server can't provide data in a format your client can read.",
 
 # Info page
 'pageinfo-title' => 'Інформація про " $1 "',
+'pageinfo-header-basic' => 'Основна інформація',
 'pageinfo-header-edits' => 'Історія редагувань',
+'pageinfo-header-restrictions' => 'Захист сторінки',
+'pageinfo-header-properties' => 'Властивості сторінки',
+'pageinfo-display-title' => 'Заголовок для відображення',
+'pageinfo-default-sort' => 'Ключ сортування за замовчуванням',
+'pageinfo-length' => 'Довжина сторінки (в байтах)',
+'pageinfo-article-id' => 'ID сторінки',
 'pageinfo-views' => 'Кількість переглядів',
 'pageinfo-watchers' => 'Кількість спостерігачів',
+'pageinfo-redirects-name' => 'Перенаправлення на цю сторінку',
+'pageinfo-subpages-name' => 'Підсторінки цієї сторінки',
+'pageinfo-subpages-value' => '$1($2 {{PLURAL:$2|перенаправлення|перенаправлення|перенаправлень}}; $3 {{PLURAL:$3|не-перенаправлення|не-перенаправлення|не-перенаправлень}})',
+'pageinfo-firstuser' => 'Створив сторінку',
 'pageinfo-firsttime' => 'Дата створення сторінки',
 'pageinfo-lastuser' => 'Останній редактор',
 'pageinfo-lasttime' => 'Дата останньої правки',
 'pageinfo-edits' => 'Загальна кількість редагувань',
 'pageinfo-authors' => 'Загальна кількість унікальних авторів',
+'pageinfo-recent-edits' => 'Кількість поточних редагувань в історії (протягом $1)',
+'pageinfo-recent-authors' => 'Кількість авторів за останній час',
+'pageinfo-templates' => 'Включено {{PLURAL:$1|шаблон|шаблонів}} ($1)',
 
 # Skin names
 'skinname-standard' => 'Стандартне',
index e1f0178..282f1b6 100644 (file)
@@ -510,6 +510,7 @@ Agar bu sahifaga xatolik sabab kelgan bo'lsangiz brauzeringizning '''orqaga''' t
 'note' => "'''Izoh:'''",
 'previewnote' => "'''Bu shunchaki ko‘rib chiqish. O‘zgartirishlar hali saqlangani yo‘q!'''",
 'editing' => '$1 tahrirlanmoqda',
+'creating' => '«$1» sahifasini yaratish',
 'editingsection' => '$1 (boʻlim) tahrirlanmoqda',
 'copyrightwarning' => "Iltimos, {{SITENAME}}ga yuklangan har qanday axborot $2 ostida tarqatilishiga diqqat qiling (batafsil ma'lumot uchun $1ni ko'ring).
 Agar yozganlaringiz keyinchalik tahrir qilinishi va qayta tarqatilishiga rozi bo'lmasangiz, u holda bu yerga yozmang.<br />
index 6861d0d..3100c9b 100644 (file)
@@ -457,7 +457,7 @@ An magdudurmara nga nagtrangka hini in naghatag hini nga eksplenasyon: "$3".',
 'exception-nologin-text' => 'Ini nga pakli o pagbuhat in nagkikinahanglan nga ikaw in mag-log-in ha dinhi nga wiki.',
 
 # Virus scanner
-'virus-scanfailed' => 'Nagpalya an pag-scan (kodigo $1)',
+'virus-scanfailed' => 'Pakyas an pag-scan (kodigo $1)',
 'virus-unknownscanner' => 'diri-nasasabtan nga antivirus:',
 
 # Login and logout pages
@@ -555,7 +555,7 @@ Ikaw in naglalog-in yana...',
 Temporaryo nga tigaman han pagsakob: $2',
 'passwordreset-emailsent' => 'Ginpadara hin usa ka pahinumdom nga e-mail.',
 'passwordreset-emailsent-capture' => 'Mayda pahinumdom nga ginpadangat ha im e-mail, kun diin ini in ginpapakita ha ubos.',
-'passwordreset-emailerror-capture' => 'Mayda pahinumdom nga e-mail han nahimo, kun diin ini in ginpapakita ha ubos, pero an pagpadangat ngada ha gumaramit in nagpalya: $1',
+'passwordreset-emailerror-capture' => 'Mayda pahinumdom nga e-mail han nahimo, kun diin ini in ginpapakita ha ubos, pero pakyas an pagpadangat ngada ha gumaramit: $1',
 
 # Special:ChangeEmail
 'changeemail' => 'Igliwan an e-mail address',
@@ -1469,7 +1469,7 @@ Kitaa an $2 para hin talaan han mga gibag-ohi nga mga ginpamara.',
 'undeletelink' => 'igpakita/igbalik',
 'undeleteviewlink' => 'kitaa',
 'undeletecomment' => 'Katadungan:',
-'cannotundelete' => 'Nagpalya an pabalik han pinara:
+'cannotundelete' => 'Pakyas an pagpabalik han pinara:
 $1',
 'undelete-search-title' => 'Pamiling hin mga ginpara nga mga pakli',
 'undelete-search-box' => 'Pamiling hin mga ginpara nga mga pakli',
@@ -1525,6 +1525,8 @@ $1',
 'blockip' => 'Pugngi an gumaramit',
 'blockip-title' => 'Pugngi an gumaramit',
 'blockip-legend' => 'Pugngi an gumaramit',
+'ipadressorusername' => 'IP address o agnay-hit-gumaramit:',
+'ipbexpiry' => 'Matitima an dulot:',
 'ipbreason' => 'Katadungan:',
 'ipbreasonotherlist' => 'Lain nga katadungan',
 'ipbreason-dropdown' => '*Agsob nga mga rason hit pagpugong
@@ -1535,14 +1537,30 @@ $1',
 ** Panhahadlok nga pamatasan/makakalilisang nga pansamok
 ** Pan-abusar hin dirudilain nga mga akawnt
 ** Diri makakarawat nga agnay-hit-gumaramit',
+'ipb-hardblock' => 'Pugnga an mga nakalog-in nga mga gumaramit tikang ha pagliwat ha dinhi nga IP address',
+'ipbcreateaccount' => 'Pugnga paghimo hin akawnt',
+'ipbemailban' => 'Pugnga an uska gumaramit tikang ha pagpadangat hin e-mail',
 'ipbsubmit' => 'Pugngi ini nga gumaramit',
 'ipbother' => 'Iba nga oras:',
 'ipboptions' => '2 ka oras:2 hours,1 ka adlaw:1 day,3 ka adlaw:3 days,1 ka semana:1 week,2 ka semana:2 weeks,1 ka bulan:1 month,3 ka bulan:3 months,6 ka bulan:6 months,1 ka tuig:1 year,waray katapusan:infinite',
 'ipbotheroption' => 'iba',
 'ipbotherreason' => 'Lain/dugang nga katadungan:',
+'ipbhidename' => 'Tagoa an agnay-han-gumaramit tikang ha mga pagliwat ngan mga talaan',
+'ipb-disableusertalk' => 'Ayaw tugota ini nga gumaramit ha pagliwat han iya kalugaringon nga hiruhimangraw nga pakli samtang nakapugong hiya',
+'ipb-change-block' => 'Ig-utro pagpugong an gumaramit upod ini nga mga kahimtang',
+'ipb-confirm' => 'Igkompirma an pagpugong',
+'badipaddress' => 'Diri balido nga IP addres',
 'blockipsuccesssub' => 'Malinamposon an pagpugong',
+'ipb-blockingself' => 'Imo pala pupugngan it imo kalugaringong!  Sigurado ka ba hit imo bubuhaton?',
 'ipb-edit-dropdown' => 'Igliwat an mga rason han pagpugong',
+'ipb-unblock-addr' => '
+Tanggala an pagpugong $1',
+'ipb-unblock' => 'Tanggala an pagpugong ha uska aganay-hit-gumaramit o IP address',
+'ipusubmit' => 'Tanggala ini nga pagpugong',
+'blocklist' => 'Mga gumaramit nga nakapugong',
 'ipblocklist' => 'Mga ginpugngan nga gumaramit',
+'ipblocklist-legend' => 'Pamiling hin uska napugngan nga gumaramit',
+'blocklist-timestamp' => 'Marka-oras',
 'blocklist-target' => 'Gin-iigo',
 'blocklist-expiry' => 'Napan-os',
 'blocklist-by' => 'Ginpupugngan an admin',
@@ -1550,6 +1568,12 @@ $1',
 'ipblocklist-submit' => 'Bilnga',
 'ipblocklist-localblock' => 'Lokal nga pagpugong',
 'ipblocklist-otherblocks' => 'Iba {{PLURAL:$1|ka pagpugong|ka mga pagpugong}}',
+'expiringblock' => 'diri madulot pag $1 han $2',
+'anononlyblock' => 'Waray nagpakilala la',
+'createaccountblock' => 'Diri ginpapagana an paghimo hin akawnt',
+'emailblock' => 'Diri ginpapagana an e-mail',
+'blocklist-nousertalk' => 'diri nakakaliwat hin kalugaringong nga hiruhimangraw nga pakli',
+'ipblocklist-empty' => 'An talaan han pagpugong in waray sulod.',
 'blocklink' => 'igpugong',
 'unblocklink' => 'igtanggal an pagpugong',
 'change-blocklink' => 'igliwan an papugong',
@@ -1557,12 +1581,27 @@ $1',
 'emaillink' => 'Padara hin e-mail',
 'blocklogpage' => 'Talaan han pagpugong',
 'blocklogentry' => 'ginpugngan hi [[$1]] nga natatapos ha takna hin $2 $3',
+'unblocklogentry' => 'gintanggal an pagpugong $1',
 'block-log-flags-nocreate' => 'diri gintutugutan an paghimo hin akawnt',
+'block-log-flags-noemail' => 'Diri ginpapagana an e-mail',
 'block-log-flags-nousertalk' => 'diri makakaliwat hit kalugaringon nga hiruhimangraw nga pakli',
+'block-log-flags-hiddenname' => 'nakatago an agnay-hit-gumaramit',
+'ipb_already_blocked' => '"$1" in ginpugngan na',
 'blockme' => 'Pugngi ako',
 'proxyblocksuccess' => 'Human na.',
+'ipbnounblockself' => 'Diri ka gintutugotan hin pagtanggal hit pagpugong ha kalugaringon',
 
 # Developer tools
+'lockdb' => 'Trangkaha an database',
+'unlockdb' => 'Abreha an database',
+'lockbtn' => 'Trangkaha an database',
+'unlockbtn' => 'Abreha an database',
+'lockdbsuccesssub' => 'Malinamposon an pagtrangka han database',
+'unlockdbsuccesssub' => '
+Gintanggal an pagtrangka han databae',
+'unlockdbsuccesstext' => 'Natanggal an trangka han database',
+'lockfilenotwritable' => 'An database paypay han trangka in diri mahisusurat.
+Para pagtrangka o pagtanggal han trangka han database, ini in kinahanglanon magin masusuratan han serbidor han web.',
 'databasenotlocked' => 'An database in diri nakatrangka.',
 
 # Move page
@@ -1571,10 +1610,22 @@ $1',
 'movearticle' => 'Balhina an pakli:',
 'moveuserpage-warning' => "'''Pahimatngon:''' Tibalhin ka hin pakli hin gumaramit. Alayon pagtigaman nga an pakli là an mababalhin ngan an gumaramit in ''diri'' mababalyoan hin ngaran.",
 'movenologin' => 'Diri nakalog-in',
+'movenotallowed' => 'Waray ka pagtugot para makabalhin hin mga pakli.',
+'movenotallowedfile' => 'Waray ka pagtugot para makabalhin hin mga paypay.',
+'cant-move-user-page' => 'Diri ka gintutugotan pagbalhin hin mga pakli nga gumaramit (labot la tikang ha mga bahin-pakli).',
+'cant-move-to-user-page' => 'Diri ka gintutugotan pagbalhin hin uska pakli pakada ha uska pakli hin gumaramit (labot la pakadto ha usa nga bahin-pakli han gumaramit).',
 'newtitle' => 'Para ha bag-o nga titulo:',
+'move-watch' => 'Kitaa an tinikangan nga pakli ngan kakadtoan nga pakli',
 'movepagebtn' => 'Igbalhin an pakli',
 'pagemovedsub' => 'Malinamposon an pagbalhin',
+'movepage-moved' => '\'\'\'"$1" in ginbalhin ngadto ha "$2"\'\'\'',
+'movepage-moved-redirect' => 'Nahimo an uska redirect.',
 'movedto' => 'ginbalhin ngadto',
+'move-subpages' => 'Balhina an mga bahin-pakli (tubtob ngadto ha $1)',
+'move-talk-subpages' => 'Balhina an mga bahin-pakli han pakli han hiruhimangraw (tubtob ngadto ha $1)',
+'movepage-page-exists' => 'An pakli nga $1 in aada na ngan diri ini lugaring nga masasapawan pagsurat.',
+'movepage-page-moved' => 'An pakli nga $1 in nabalhin ngadto ha $2.',
+'movepage-page-unmoved' => 'An pakli nga $1 in diri mababalhin ngadto ha $2.',
 'movelogpage' => 'Talaan han pagbalhin',
 'movelogpagetext' => 'Ubos hini in uska talaan han ngatanan nga nabalhin nga pakli',
 'movenosubpage' => 'Ini nga pakli in waray mga bahin-pakli.',
@@ -1582,6 +1633,16 @@ $1',
 'revertmove' => 'igbalik',
 'delete_and_move' => 'Igapara ngan igbalhin',
 'delete_and_move_confirm' => 'Oo, paraa an pakli',
+'delete_and_move_reason' => 'Ginpara para makahatag hin aragian para makabalhin tikan "[[$1]]"',
+'selfmove' => 'An tinikangan ngan kakadtoan nga mga titulo in parehas;
+diri makakabalhin ha iya kalugaringon ngahaw.',
+'immobile-source-namespace' => 'Diri nababalhin an mga pakli ha ngaran-lat\'ang nga "$1"',
+'immobile-target-namespace' => 'Diri makakabalhin hin mga pakli ngada ha ngaran-lat\'ang nga "$1"',
+'immobile-target-namespace-iw' => 'An sumpay interwiki in diri balido nga irig-on para han pagbalhin hin pakli.',
+'immobile-source-page' => 'Diri mababalhin ini nga pakli.',
+'immobile-target-page' => 'Diri makakabalhin ha ngada nga kakadtoon nga titulo.',
+'imageinvalidfilename' => 'An kakadtoon nga ngaran-han-paypay in diri balido',
+'move-leave-redirect' => 'Pagbilin hin redirect',
 
 # Export
 'export' => 'Mga pakli hit pagexport',
@@ -1593,6 +1654,7 @@ $1',
 'export-addnstext' => "Igdugang an mga pakli tikang ha ngaran-lat'ang:",
 'export-addns' => 'Dugngi',
 'export-download' => 'Igtipig komo paypay',
+'export-templates' => 'Iglakip an mga batakan',
 
 # Namespace 8 related
 'allmessages' => 'Mga mensahe han sistema',
@@ -1624,11 +1686,25 @@ $1',
 'importnotext' => 'Waray sulod o waray teksto',
 'importsuccess' => 'Natapos an pag-aangbit!',
 'import-noarticle' => 'Waray pakli nga maaangbit!',
+'import-token-mismatch' => 'Nawara an datos sesyon.
+Alayon utroha.',
+'import-error-edit' => 'An pakli nga "$1" in waray naangbit tungod nga diri ka gintutugotan pagliwat hini.',
+'import-error-create' => 'An pakli nga "$1" in waray naangbit tungod nga diri ka gintutugotan paghimo hini.',
+'import-error-interwiki' => 'An pakli nga "$1" in waray naangbit tungod nga an ngaran in nakareserba para han pagsusumpay ha gawas (interwiki).',
+'import-error-special' => 'An pakli nga "$1" in waray naangbit tungod nga nahihilakip ini ha uska pinaurog nga ngaran-lat\'ang nga diri natugot hin mga pakli.',
+'import-error-invalid' => 'An pakli nga "$1" in waray naangbit tungod nga it iya ngaran in diri balido.',
+'import-options-wrong' => 'Sayop {{PLURAL:$2|nga pirilion|nga mga pirilion}}: <nowiki>$1</nowiki>',
+'import-rootpage-invalid' => 'An ginhatag nga gamot-pakli in uska diri balido nga titulo.',
+'import-rootpage-nosubpage' => 'Ngaran-lat\'ang nga "$1" han gamot-pakli in diri natugot hin mga bahin-pakli.',
 
 # Import log
 'importlogpage' => 'Talaan hin pan-aangbit',
+'import-logentry-upload' => 'ginangbit [[$1]] pinaagi hin pagkarga-pasaka han paypay',
 'import-logentry-interwiki' => 'natranswiki $1',
 
+# JavaScriptTest
+'javascripttest-pagetext-skins' => 'Pagpili hin panit para ha pag-paandar han:',
+
 # Tooltip help for the actions
 'tooltip-pt-userpage' => 'An imo pakli hin gumaramit',
 'tooltip-pt-mytalk' => 'An imo pakli hin hiruhimangraw',
@@ -1686,19 +1762,26 @@ Makikit-an nimo an ginkuhaaan',
 'tooltip-compareselectedversions' => 'Kitaa an mga kaibhan ha butnga han duha nga pinili nga mga pagliwat hini nga pakli',
 'tooltip-watch' => 'Dugnga ini nga pakli ngadto han imo talaan hin ginbibinantayan',
 'tooltip-watchlistedit-normal-submit' => 'Igtanggal an mga titulo',
+'tooltip-recreate' => 'Utroha paghimo an pakli bisan ini in ginpara na',
+'tooltip-upload' => 'Tikanga an pagkarga-pasaka',
 'tooltip-rollback' => 'An "libot-pabalik" in nabalik han (mga) pagliwat hini nga pakli ngadto han kataposan nga nag-amot hin usa ka pidlit',
 'tooltip-undo' => '"Igpawara an ginbuhat (undo)" in nagbabalik hinin nga pagliwat ngan nabuklad hin pagliwat nga porma ha pahiuna-nga-paggawas nga kahimtang.  Natugot liwat pagdugang hin katadungan ha dinalikyat nga sumat.',
+'tooltip-preferences-save' => 'Tipiga an mga karuyag',
 'tooltip-summary' => 'Pagbutang hin dalikyat nga sumat',
 
 # Attribution
+'siteuser' => '{{SITENAME}} gumaramit $1',
+'anonuser' => '{{SITENAME}} waray nagpakilala nga gumaramit $1',
 'othercontribs' => 'Ginbasihan ha binuhat ni $1.',
 'others' => 'mga iba',
 'siteusers' => '{{SITENAME}} {{PLURAL:$2|gumaramit|mga gumaramit}} $1',
 
 # Info page
+'pageinfo-title' => 'Impormasyon para "$1"',
 'pageinfo-header-basic' => 'Panguna nga pananabotan',
 'pageinfo-header-edits' => 'Kaagi han pagliwat',
 'pageinfo-header-restrictions' => 'Panalipod han pakli',
+'pageinfo-display-title' => 'Iglatag an titulo',
 'pageinfo-length' => 'Kahilaba han pakli (ha mga byte)',
 'pageinfo-article-id' => 'ID han pakli',
 'pageinfo-robot-policy' => 'Pamilnga an kahimtang han makina',
@@ -1714,26 +1797,54 @@ Makikit-an nimo an ginkuhaaan',
 'pageinfo-lastuser' => 'Giurhii nga nagliwat',
 'pageinfo-lasttime' => 'Petsa han kataposan nga pagliwat',
 'pageinfo-edits' => 'Ngatanan nga ihap han mga pakli',
+'pageinfo-toolboxlink' => 'Impormasyon han pakli',
+'pageinfo-redirectsto' => 'Igredirect ngadto ha',
+'pageinfo-contentpage' => 'Ginlakip komo uska unod nga pakli',
 'pageinfo-contentpage-yes' => 'Oo',
 'pageinfo-protect-cascading-yes' => 'Oo',
 
+# Patrolling
+'markaspatrolleddiff' => 'Igmarka komo ginpatrolya na',
+'markaspatrolledtext' => 'Markaha ini nga pakli komo ginpatrolya na',
+'markedaspatrolled' => 'Igmarka komo ginpatrolya na',
+'markedaspatrollederror' => 'Diri nakakamarka komo ginpatrolya na',
+
+# Patrol log
+'patrol-log-page' => 'Talaan han pagpatrolya',
+'patrol-log-header' => 'Ini in uska talaan hin mga ginpatrolya nga mga rebisyon.',
+'log-show-hide-patrol' => '$1 talaan hin pagpatrolya',
+
+# Image deletion
+'deletedrevision' => 'Ginpara an daan nga rebisyon $1',
+'filedeleteerror-short' => 'Nagsayop ha pagpara han paypay: $1',
+'filedeleteerror-long' => 'Mga sayop nga ginengkwentro samtang nagpapara hin paypay:
+
+$1',
+'filedelete-missing' => 'An paypay nga "$1" in diri mapapara, tunogd nga waray ini dida.',
+
 # Browsing diffs
 'previousdiff' => '← Durudaan nga pagliwat',
 'nextdiff' => 'Burubag-o nga pagliwat',
 
 # Media information
 'widthheightpage' => '$1 × $2, $3 {{PLURAL:$3|pakli|mga pakli}}',
+'file-info' => 'Kadako han paypay: $1, klase han MIME: $2',
 'file-info-size' => '$1 × $2 nga pixel, kadako han fayl: $3, MIME nga tipo: $4',
 'file-nohires' => 'Waray mas hiruhitaas nga resolusyon.',
 'svg-long-desc' => 'SVG nga fayl, ginbabanabanahan nga $1 × $2 nga mga pixel, kadako han fayl: $3',
 'show-big-image' => 'Bug-os nga resolusyon',
+'show-big-image-preview' => 'Kadako hin nga pahiuna nga pagawas: $1.',
+'show-big-image-other' => 'Iba {{PLURAL:$2|nga resolusyon|nga mga resolusyon}}: $1.',
 'show-big-image-size' => '$1 × $2 nga mga pixel',
 
 # Special:NewFiles
 'newimages' => 'Galeryia hin mga paypay nga bag-o',
 'newimages-legend' => 'Panara',
+'newimages-label' => 'Ngaran han paypay (o uska bahin hini):',
+'showhidebots' => '($1 ka mga bot)',
 'noimages' => 'Waray makikit-an.',
 'ilsubmit' => 'Bilnga',
+'bydate' => 'pinaagi han petsa',
 
 # Video information, used by Language::formatTimePeriod() to format lengths in the above messages
 'ago' => '$1 an nakalabay',
@@ -1769,18 +1880,46 @@ An iba in daan nakatago.
 'exif-imagewidth' => 'Kahaluag',
 'exif-imagelength' => 'Kahitaas',
 'exif-ycbcrpositioning' => 'Pagpoposisyon han Y ngan C',
+'exif-referenceblackwhite' => 'Padis han itom nga busag nga reperensya hin mga balor',
+'exif-datetime' => 'Pagliwat han petsa ngan oras han paypay',
 'exif-imagedescription' => 'Titulo han hulagway',
+'exif-make' => 'Naghimo han kamera',
+'exif-model' => 'Modelo han kamera',
+'exif-software' => 'Software nga gingamit',
 'exif-artist' => 'Tag-iya',
+'exif-colorspace' => 'Kolor lat-ang',
+'exif-subsectime' => 'Mga bahin-segundo han PetsaOras',
 'exif-exposuretime-format' => '$1 seg ($2)',
 'exif-fnumber' => 'F Numero',
+'exif-lightsource' => 'Ginkuhaan han suga',
+'exif-filesource' => 'Ginkuhaan han paypay',
+'exif-saturation' => 'saturasyon',
 'exif-sharpness' => 'Pagkatarom',
+'exif-gpslatituderef' => 'Amihanan o salatan nga latitud',
 'exif-gpslatitude' => 'Latitud',
+'exif-gpslongituderef' => 'Sinirangan o katundan nga longitud',
 'exif-gpslongitude' => 'Longitud',
 'exif-gpsaltitude' => 'Altitud',
 'exif-gpstimestamp' => 'GPS nga oras (atomiko nga relo)',
+'exif-gpssatellites' => 'Mga satelayt nga gingamit ha pagsukol',
+'exif-gpsstatus' => 'Kahimtang han nagkakarawat',
+'exif-gpsdop' => 'kauntop han pagsukol',
 'exif-gpsspeedref' => 'Sukol han kalaksi',
+'exif-gpstrack' => 'Direksyon han kiwa',
+'exif-gpsimgdirection' => 'Direksyon han imahe',
+'exif-gpsdestlatitude' => 'kakadtoan latitud',
+'exif-gpsdestlongitude' => 'kakadtoan longitud',
 'exif-gpsdestdistance' => 'Distansya ha destinasyon',
+'exif-gpsareainformation' => 'Ngaran han lugar an GPS',
 'exif-gpsdatestamp' => 'petsa han GPS',
+'exif-jpegfilecomment' => 'Komento han JPEG nga paypay',
+'exif-worldregioncreated' => 'Rehiyon han kalibutan kun diin an ritrato ginkuha',
+'exif-countrycreated' => 'Nasod kun diin an ritrato ginkuha',
+'exif-countrycodecreated' => 'Kodigo han nasod kun diin an ritrato ginkuha',
+'exif-provinceorstatecreated' => 'Lalawigan o estado kun diin an ritrato ginkuha',
+'exif-citycreated' => 'An syudad kun diin an ritrato ginkuha',
+'exif-sublocationcreated' => 'Bahin-lokasyon han syudad kun diin an ritrato ginkuha',
+'exif-worldregiondest' => 'Ginpakita an rehiyon han kalibutan',
 'exif-countrydest' => 'Ginpapakita an nasod',
 'exif-countrycodedest' => 'Ginpapakita an kodigo han nasod',
 'exif-provinceorstatedest' => 'Ginpapakita an lalawigan o estado',
@@ -1798,6 +1937,10 @@ An iba in daan nakatago.
 'exif-cameraownername' => 'Tag-iya han kamera',
 'exif-usageterms' => 'Mga termino hit paggamit',
 
+'exif-copyrighted-false' => 'Dominyo panpubliko',
+
+'exif-unknowndate' => 'Waray kasabti an petsa',
+
 'exif-orientation-1' => 'Normal',
 
 'exif-exposureprogram-1' => 'Mano-mano',
@@ -1827,6 +1970,8 @@ An iba in daan nakatago.
 
 'exif-subjectdistancerange-0' => 'Waray kasabti',
 'exif-subjectdistancerange-1' => 'Macro',
+'exif-subjectdistancerange-2' => 'Harani nga pagkita',
+'exif-subjectdistancerange-3' => 'Harayo nga pagkita',
 
 # Pseudotags used for GPSAltitudeRef
 'exif-gpsaltitude-above-sealevel' => '$1 {{PLURAL:$1|metro|mga metro}} bawbaw han katupngan ha dagat',
@@ -1842,15 +1987,24 @@ An iba in daan nakatago.
 
 'exif-objectcycle-a' => 'Aga la',
 'exif-objectcycle-p' => 'Gab-i la',
+'exif-objectcycle-b' => 'Pareho pan-aga ngan pan-gab-i',
 
 # Pseudotags used for GPSTrackRef, GPSImgDirectionRef and GPSDestBearingRef
 'exif-gpsdirection-t' => 'Tinood nga direksyon',
 
+'exif-ycbcrpositioning-1' => 'Nakabutnga',
+
+'exif-dc-contributor' => 'Mga nag-ámot',
 'exif-dc-date' => '(Mga) petsa',
+'exif-dc-relation' => 'Nahisumpay nga medya',
 'exif-dc-rights' => 'Mga katungod',
+'exif-dc-source' => 'Tinikangan nga medya',
+'exif-dc-type' => 'Klase nga medya',
 
 'exif-rating-rejected' => 'Waray karawta',
 
+'exif-isospeedratings-overflow' => 'Lapos han 65535',
+
 'exif-iimcategory-ace' => 'mga arte, kultura ngan panlibang',
 'exif-iimcategory-clj' => 'Krimen ngan balaod',
 'exif-iimcategory-fin' => 'Ekonomiya ngan negosyo',
@@ -1868,6 +2022,8 @@ An iba in daan nakatago.
 'exif-iimcategory-wea' => 'panahon',
 
 'exif-urgency-normal' => 'Normal ($1)',
+'exif-urgency-low' => 'Hamubo ($1)',
+'exif-urgency-high' => 'Hataas ($1)',
 
 # External editor support
 'edit-externally' => 'Igliwat ini nga fayl gamit han gawas nga aplikasyon',
@@ -1879,7 +2035,19 @@ An iba in daan nakatago.
 'monthsall' => 'ngatanan',
 'limitall' => 'ngatanan',
 
+# E-mail address confirmation
+'confirmemail' => 'Igkompirma an e-mail address',
+'confirmemail_sent' => 'Ginpadara an kompirmasyon han e-mail.',
+'confirmemail_needlogin' => 'Kinahanglanon mo hin $1 para makakompirma han imo e-mail address.',
+'confirmemail_loggedin' => 'Ginkompirma na yana an imo e-mail address',
+'confirmemail_error' => 'Mayda diri asya nga nahitabo ha pagtipig ha imo kompirmasyon.',
+'confirmemail_subject' => '{{SITENAME}} kompirmasyon han e-mail address',
+
+# Scary transclusion
+'scarytranscludetoolong' => '[Hala hin duro an URL]',
+
 # Delete conflict
+'deletedwhileediting' => "'''Pahimatngon''': Ini nga pakli in ginpara kahuman nim magtikang pagliwat!",
 'recreate' => 'Himo-a utro',
 
 # action=purge
@@ -1887,7 +2055,9 @@ An iba in daan nakatago.
 
 # action=watch/unwatch
 'confirm-watch-button' => 'OK',
+'confirm-watch-top' => 'Dudugngon ini nga pakli ngadto han imo talaan hin ginbibinantayan?',
 'confirm-unwatch-button' => 'OK',
+'confirm-unwatch-top' => 'Tatanggalon ini nga pakli tikang han imo tala hin binabantayan?',
 
 # Multipage image navigation
 'imgmultipageprev' => '← naha-una nga pakli',
@@ -1896,6 +2066,8 @@ An iba in daan nakatago.
 'imgmultigoto' => 'Pakadto ha pakli $1',
 
 # Table pager
+'ascending_abbrev' => 'pasaka',
+'descending_abbrev' => 'paubos',
 'table_pager_next' => 'Sunod nga pakli',
 'table_pager_prev' => 'Naha-una nga pakli',
 'table_pager_first' => 'Una nga pakli',
@@ -1905,6 +2077,12 @@ An iba in daan nakatago.
 'table_pager_limit_submit' => 'Kadto-a',
 'table_pager_empty' => 'Waray mga resulta',
 
+# Auto-summaries
+'autosumm-blank' => 'Blankoha an pakli',
+'autosumm-replace' => 'Ginsaliwanan an sulod hin "$1"',
+'autoredircomment' => 'Ginredirecta an pakli ngada ha [[$1]]',
+'autosumm-new' => 'Nahimo an pakli nga may "$1"',
+
 # Size units
 'size-bytes' => '$1 nga B',
 'size-kilobytes' => '$1 nga KB',
@@ -1916,8 +2094,18 @@ An iba in daan nakatago.
 'livepreview-ready' => 'Ginkakarga. . . Pag-andam!',
 
 # Watchlist editor
+'watchlistedit-numitems' => 'An imo talaan hin binabantayan hin may sulod nga {{PLURAL:$1|1 ka titulo|$1 ka mga titulo}}, diri lakip an mga pakli nga hiruhimangraw.',
+'watchlistedit-noitems' => 'An imo talaan han binabantayan in waray sulod nga mga titulo.',
+'watchlistedit-normal-title' => 'Igliwat an talaan han binabantayan',
+'watchlistedit-normal-legend' => 'Igtanggal an mga titulo tikang ha talaan hit binabantayan',
 'watchlistedit-normal-submit' => 'Igtanggal an mga titulo',
+'watchlistedit-raw-title' => 'Igliwat an hilaw nga talaan han binabantayan',
+'watchlistedit-raw-legend' => 'Igliwat an hilaw nga talaan han binabantayan',
 'watchlistedit-raw-titles' => 'Mga titulo:',
+'watchlistedit-raw-submit' => 'Igpayana an talaan han binabantayan',
+'watchlistedit-raw-done' => 'Ginpayana an imo talaan han barantayon.',
+'watchlistedit-raw-added' => '{{PLURAL:$1|1 nga titulo|$1 nga mga titulo}} in gindugang:',
+'watchlistedit-raw-removed' => '{{PLURAL:$1|1 nga titulo|$1 nga mga titulo}} in gintanggal:',
 
 # Watchlist editing tools
 'watchlisttools-view' => 'Kitaa an mga nanginginlabot nga mga pagbabag-o',
@@ -1929,11 +2117,24 @@ An iba in daan nakatago.
 
 # Special:Version
 'version' => 'Bersyon',
+'version-specialpages' => 'Mga pinaurog nga pakli',
+'version-parserhooks' => 'Mga kawil parser',
+'version-variables' => 'Mga variable',
+'version-antispam' => 'Pamugong hin spam',
 'version-skins' => 'Mga panit',
+'version-other' => 'iba',
+'version-mediahandlers' => 'Mga nakapot han medya',
+'version-hooks' => 'Mga kawil',
+'version-hook-name' => 'Ngaran han kawil',
 'version-version' => '(Bersion $1)',
 'version-license' => 'Lisensya',
+'version-poweredby-credits' => "Ini nga wiki in pinapaandar han '''[//www.mediawiki.org/ MediaWiki]''', copyright © 2001-$1 $2.",
+'version-poweredby-others' => 'mga iba',
 'version-software-product' => 'Produkto',
 'version-software-version' => 'Bersyon',
+'version-entrypoints' => 'Surudlan nga mga URL',
+'version-entrypoints-header-entrypoint' => 'Surudlan',
+'version-entrypoints-header-url' => 'URL',
 
 # Special:FilePath
 'filepath' => 'Aragian han paypay',
@@ -1941,11 +2142,16 @@ An iba in daan nakatago.
 'filepath-submit' => 'Kadto-a',
 
 # Special:FileDuplicateSearch
+'fileduplicatesearch' => 'Pamiling hin nadoble nga mga paypay',
+'fileduplicatesearch-legend' => 'Pamiling hin nadoble',
+'fileduplicatesearch-filename' => 'Ngaran han paypay:',
 'fileduplicatesearch-submit' => 'Pamilnga',
 'fileduplicatesearch-noresults' => 'Waray nabilngan nga paypay nga an ngaran in "$1".',
 
 # Special:SpecialPages
 'specialpages' => 'Mga pinaurog nga pakli',
+'specialpages-group-maintenance' => 'Mga sumat han pagmintinar',
+'specialpages-group-other' => 'Mga iba nga pinaurog nga pakli',
 'specialpages-group-login' => 'Magpalista nga masakob / paghimo hin bag-o nga akawnt',
 'specialpages-group-users' => 'Mga gumaramit ngan mga katungod',
 'specialpages-group-highuse' => 'Mga pakli nga damo nagamit',
@@ -1988,10 +2194,14 @@ An iba in daan nakatago.
 'dberr-header' => 'Ini nga wiki mayda problema',
 
 # HTML forms
+'htmlform-submit' => 'Isumite',
 'htmlform-reset' => 'Igbalik an mga pinamalyuan',
 'htmlform-selectorother-other' => 'iba',
 
 # New logging system
+'revdelete-content-hid' => 'sulod nakatago',
+'revdelete-summary-hid' => 'nakatago an dalikyat nga sumat han pagliwat',
+'revdelete-uname-hid' => 'nakatago an agnay-hit-gumaramit',
 'logentry-newusers-newusers' => '$1 in naghimo hin gumaramit nga akawnt',
 'logentry-newusers-create' => '$1 in naghimo hin gumaramit nga akawnt',
 'logentry-newusers-create2' => '$1 in naghimo hin gumaramit nga akawnt $3',
@@ -2002,6 +2212,7 @@ An iba in daan nakatago.
 'feedback-subject' => 'Himangrawon:',
 'feedback-message' => 'Mensahe:',
 'feedback-cancel' => 'Pasagdi',
+'feedback-error2' => 'Sayop: Pakyas an pagliwat',
 'feedback-close' => 'Human na.',
 
 # Search suggestions
@@ -2012,11 +2223,17 @@ An iba in daan nakatago.
 'api-error-badaccess-groups' => 'Diri ka gintutugotan pagkarga paigbaw ha dinhi nga wiki.',
 'api-error-badtoken' => 'Sayop ha sulod: Maraot nga token.',
 'api-error-copyuploaddisabled' => 'Pagkarga paigbaw pinaagi han URL in diri mahihimo ha dinhi nga serbidor.',
+'api-error-duplicate-archive-popup-title' => 'An nagdodoble {{PLURAL:$1|nga paypay|nga mga paypay}} in napara na.',
+'api-error-duplicate-popup-title' => 'Nadoble {{PLURAL:$1|nga paypay|nga mga paypay}}.',
+'api-error-empty-file' => 'An paypay nga isinumite nimo in waray sulod.',
+'api-error-emptypage' => 'Naghihimo hin bag-o, diri gintutugotan an waray sulod nga mga pakli.',
 'api-error-filename-tooshort' => 'An ngaran han paypay in halipot hin duro.',
 'api-error-filetype-banned' => 'Diri gintutugotan ini nga klase nga paypay.',
 'api-error-filetype-missing' => 'Ini nga ngaran han paypay in nawawad-an hin ekstensyon.',
 'api-error-http' => 'Sayop ha sulod: Diri nakakasumpay ha serbidor.',
 'api-error-illegal-filename' => 'Diri gintutugotan an ngaran-han-paypay.',
+'api-error-mustbeloggedin' => 'Diri ka nakalog-in para makapagkarga-pasaka hin mga paypay.',
+'api-error-mustbeposted' => 'Sayop ha sulod: Iton paalayon in nagkikinahanglan hin HTTP POST.',
 'api-error-overwrite' => 'Pagsasapaw in aada nga paypay in diri gintutugotan.',
 'api-error-stashfailed' => 'Sayop ha sulod:  An serbidor in waray makatipig han temporaryo nga paypay.',
 'api-error-timeout' => 'An serbidor in diri nabaton ha sulod han ginaasahan nga oras.',
index 024a446..558778d 100644 (file)
@@ -927,7 +927,7 @@ $2
 'updated' => '(已更新)',
 'note' => "'''注意:'''",
 'previewnote' => "'''请记住这仅为预览。'''您的更改还未保存!",
-'continue-editing' => '继续编辑',
+'continue-editing' => '往编辑框',
 'previewconflict' => '这个预览显示了上面文字编辑区中的内容。它将在你选择保存后出现。',
 'session_fail_preview' => "'''抱歉!由于会话数据丢失,我们不能处理你的编辑。'''请重试。如果再次失败,请尝试[[Special:UserLogout|退出]]后重新登录。",
 'session_fail_preview_html' => "'''抱歉!我们不能处理你在进程数据丢失时的编辑。'''
@@ -2962,9 +2962,10 @@ $1被封禁的理由是:“$2”',
 'pageinfo-authors' => '不同编者总计',
 'pageinfo-recent-edits' => '最近的编辑数($1内)',
 'pageinfo-recent-authors' => '最近的不同编者数',
-'pageinfo-magic-words' => '魔术字 ($1)',
-'pageinfo-hidden-categories' => '隐藏分类 ($1)',
-'pageinfo-templates' => '使用的模板 ($1)',
+'pageinfo-magic-words' => '魔术字($1)',
+'pageinfo-hidden-categories' => '隐藏分类($1)',
+'pageinfo-templates' => '使用的模板($1)',
+'pageinfo-toolboxlink' => '页面信息',
 
 # Skin names
 'skinname-standard' => '标准',
index 72c1825..244798e 100644 (file)
@@ -883,7 +883,7 @@ $2
 'updated' => '(已更新)',
 'note' => "'''注意:'''",
 'previewnote' => "'''請記住這只是預覽,內容尚未儲存!'''",
-'continue-editing' => '繼續編輯',
+'continue-editing' => '往編輯框',
 'previewconflict' => '這個預覽顯示了上面文字編輯區中的內容。它將在{{GENDER:|你|妳|你}}選擇保存後出現。',
 'session_fail_preview' => "'''很抱歉!由於部份資料遺失,我們無法處理您的編輯。'''
 請再試一次。
@@ -2974,11 +2974,11 @@ $1被封禁的理由是“$2”',
 'pageinfo-lasttime' => '最新編輯日期',
 'pageinfo-edits' => '編輯總次數',
 'pageinfo-authors' => '作者總數',
-'pageinfo-recent-edits' => '最近編輯次數 (過去 $1 內)',
+'pageinfo-recent-edits' => '最近編輯次數 (過去$1內)',
 'pageinfo-recent-authors' => '最近作者數目',
-'pageinfo-magic-words' => '魔術{{PLURAL:$1|字|字}} ( $1 )',
-'pageinfo-hidden-categories' => '隱藏{{PLURAL:$1|分類|分類}} ( $1 )',
-'pageinfo-templates' => '被引用的{{PLURAL:$1|模版|模版}} ( $1 )',
+'pageinfo-magic-words' => '魔術{{PLURAL:$1|字|字}}($1)',
+'pageinfo-hidden-categories' => '隱藏{{PLURAL:$1|分類|分類}}($1)',
+'pageinfo-templates' => '被引用的{{PLURAL:$1|模版|模版}}($1)',
 'pageinfo-toolboxlink' => '頁面資訊',
 'pageinfo-redirectsto' => '重定向到',
 'pageinfo-redirectsto-info' => '資訊',
index 556d6b2..14eaeab 100644 (file)
@@ -33,7 +33,7 @@ CREATE TABLE /*_*/uploadstash (
        us_sha1 varchar(31) NOT NULL,
        us_mime varchar(255),
        -- Media type as defined by the MEDIATYPE_xxx constants, should duplicate definition in the image table
-       us_media_type ENUM("UNKNOWN", "BITMAP", "DRAWING", "AUDIO", "VIDEO", "MULTIMEDIA", "OFFICE", "TEXT", "EXECUTABLE", "ARCHIVE") default NULL,
+       us_media_type ENUM("UNKNOWN", "BITMAP", "DRAWING", "AUDIO", "VIDEO", "MULTIMEDIA", "OFFICE", "TEXT", "EXECUTABLE", "ARCHIVE") default NULL,
        -- image-specific properties
        us_image_width int unsigned,
        us_image_height int unsigned,
index a8cd2ff..d94b948 100644 (file)
@@ -326,7 +326,7 @@ USAGE: php importImages.php [options] <dir>
 <dir> : Path to the directory containing images to be imported
 
 Options:
---extensions=<exts>    Comma-separated list of allowable extensions, defaults to \$wgFileExtensions
+--extensions=<exts>     Comma-separated list of allowable extensions, defaults to \$wgFileExtensions
 --overwrite             Overwrite existing images with the same name (default is to skip them)
 --limit=<num>           Limit the number of images to process. Ignored or skipped images are not counted.
 --from=<name>           Ignore all files until the one with the given name. Useful for resuming
index e9baef9..6c57fde 100644 (file)
@@ -49,7 +49,7 @@ class PopulateFilearchiveSha1 extends LoggedUpdateMaintenance {
                $table = 'filearchive';
                $conds = array( 'fa_sha1' => '', 'fa_storage_key IS NOT NULL' );
                $this->output( "Populating fa_sha1 field from fa_storage_key\n" );
-               $endId = $dbw->selectField( $table, 'MAX(fa_id)', false, __METHOD__ );\r
+               $endId = $dbw->selectField( $table, 'MAX(fa_id)', false, __METHOD__ );
 
                $batchSize = $this->mBatchSize;
                $done = 0;
@@ -65,6 +65,10 @@ class PopulateFilearchiveSha1 extends LoggedUpdateMaintenance {
 
                        $i = 0;
                        foreach ( $res as $row ) {
+                               if ( $row->fa_storage_key == '' ) {
+                                       // Revision was missing pre-deletion
+                                       continue;
+                               }
                                $sha1 = LocalRepo::getHashFromKey( $row->fa_storage_key );
                                $dbw->update( $table,
                                        array( 'fa_sha1' => $sha1 ),
index ec28716..27759d5 100644 (file)
@@ -523,13 +523,19 @@ CREATE INDEX ls_log_id ON log_search (ls_log_id);
 
 CREATE SEQUENCE job_job_id_seq;
 CREATE TABLE job (
-  job_id         INTEGER   NOT NULL  PRIMARY KEY DEFAULT nextval('job_job_id_seq'),
-  job_cmd        TEXT      NOT NULL,
-  job_namespace  SMALLINT  NOT NULL,
-  job_title      TEXT      NOT NULL,
-  job_timestamp  TIMESTAMPTZ,
-  job_params     TEXT      NOT NULL
-);
+  job_id              INTEGER   NOT NULL  PRIMARY KEY DEFAULT nextval('job_job_id_seq'),
+  job_cmd             TEXT      NOT NULL,
+  job_namespace       SMALLINT  NOT NULL,
+  job_title           TEXT      NOT NULL,
+  job_timestamp       TIMESTAMPTZ,
+  job_params          TEXT      NOT NULL,
+  job_random          INTEGER   NOT NULL DEFAULT 0,
+  job_token           TEXT      NOT NULL DEFAULT '',
+  job_token_timestamp TIMESTAMPTZ,
+  job_sha1            TEXT NOT NULL DEFAULT ''
+);
+CREATE INDEX job_sha1 ON job (job_sha1);
+CREATE INDEX job_cmd_token ON job (job_cmd, job_token, job_random);
 CREATE INDEX job_cmd_namespace_title ON job (job_cmd, job_namespace, job_title);
 CREATE INDEX job_timestamp_idx ON job (job_timestamp);
 
index 04e98d9..72e6775 100644 (file)
@@ -63,24 +63,36 @@ class MwSql extends Maintenance {
                }
 
                $wholeLine = '';
-               while ( ( $line = Maintenance::readconsole() ) !== false ) {
+               $newPrompt = '> ';
+               $prompt    = $newPrompt;
+               while ( ( $line = Maintenance::readconsole( $prompt ) ) !== false ) {
+                       if( !$line ) {
+                               # User simply pressed return key
+                               continue;
+                       }
                        $done = $dbw->streamStatementEnd( $wholeLine, $line );
 
                        $wholeLine .= $line;
 
                        if ( !$done ) {
+                               $wholeLine .= ' ';
+                               $prompt = '    -> ';
                                continue;
                        }
                        if ( $useReadline ) {
-                               readline_add_history( $wholeLine );
+                               # Delimiter is eated by streamStatementEnd, we add it
+                               # up in the history (bug 37020)
+                               readline_add_history( $wholeLine . $dbw->getDelimiter() );
                                readline_write_history( $historyFile );
                        }
                        try{
                                $res = $dbw->query( $wholeLine );
                                $this->sqlPrintResult( $res, $dbw );
+                               $prompt    = $newPrompt;
                                $wholeLine = '';
                        } catch (DBQueryError $e) {
-                               $this->error( $e, true );
+                               $doDie = ! Maintenance::posix_isatty( 0 );
+                               $this->error( $e, $doDie );
                        }
                }
        }
index 197151b..a4cdefd 100644 (file)
@@ -1291,7 +1291,8 @@ CREATE TABLE /*_*/job (
   -- Stored as a PHP serialized array, or an empty string if there are no parameters
   job_params blob NOT NULL,
 
-  -- Random, non-unique, number used for concurrent job acquisition
+  -- Random, non-unique, number used for job acquisition
+  -- Either a simple timestamp or a totally random number (for lock concurrency)
   job_random integer unsigned NOT NULL default 0,
 
   -- Field that conveys process locks on rows via process UUIDs
index e3c993b..cb6f06b 100644 (file)
@@ -118,9 +118,6 @@ class UpdateMediaWiki extends Maintenance {
                $shared = $this->hasOption( 'doshared' );
 
                $updates = array( 'core', 'extensions', 'stats' );
-               if( !$this->hasOption('nopurge') ) {
-                       $updates[] = 'purge';
-               }
 
                $updater = DatabaseUpdater::newForDb( $db, $shared, $this );
                $updater->doUpdates( $updates );
@@ -140,6 +137,10 @@ class UpdateMediaWiki extends Maintenance {
                        }
                }
 
+               if( !$this->hasOption('nopurge') ) {
+                       $updater->purgeCache();
+               }
+
                $this->output( "\nDone.\n" );
        }
 
index ca719ab..99a5557 100644 (file)
@@ -3,7 +3,7 @@
  */
 ( function ( mw, $ ) {
        $( document ).ready( function ( $ ) {
-               var map,
+               var map, searchboxesSelectors,
                        // Region where the suggestions box will appear directly below
                        // (using the same width). Can be a container element or the input
                        // itself, depending on what suits best in the environment.
                        $searchRegion = $( '#simpleSearch, #searchInput' ).first(),
                        $searchInput = $( '#searchInput' );
 
-               // Ensure that the thing is actually present!
-               if ( $searchRegion.length === 0 ) {
-                       // Don't try to set anything up if simpleSearch is disabled sitewide.
-                       // The loader code loads us if the option is present, even if we're
-                       // not actually enabled (anymore).
-                       return;
-               }
-
                // Compatibility map
                map = {
                        browsers: {
                        return;
                }
 
-               // Placeholder text for search box
-               $searchInput
-                       .attr( 'placeholder', mw.msg( 'searchsuggest-search' ) )
-                       .placeholder();
-
                // General suggestions functionality for all search boxes
-               $( '#searchInput, #searchInput2, #powerSearchText, #searchText' )
+               searchboxesSelectors = [
+                       // Primary searchbox on every page in standard skins
+                       '#searchInput',
+                       // Secondary searchbox in legacy skins (LegacyTemplate::searchForm uses id "searchInput + unique id")
+                       '#searchInput2',
+                       // Special:Search
+                       '#powerSearchText',
+                       '#searchText',
+                       // Generic selector for skins with multiple searchboxes (used by CologneBlue)
+                       '.mw-searchInput'
+               ];
+               $( searchboxesSelectors.join(', ') )
                        .suggestions( {
                                fetch: function ( query ) {
                                        var $el, jqXhr;
                                $( this ).trigger( 'keypress' );
                        } );
 
+               // Ensure that the thing is actually present!
+               if ( $searchRegion.length === 0 ) {
+                       // Don't try to set anything up if simpleSearch is disabled sitewide.
+                       // The loader code loads us if the option is present, even if we're
+                       // not actually enabled (anymore).
+                       return;
+               }
+
+               // Placeholder text for search box
+               $searchInput
+                       .attr( 'placeholder', mw.msg( 'searchsuggest-search' ) )
+                       .placeholder();
+
                // Special suggestions functionality for skin-provided search box
                $searchInput.suggestions( {
                        result: {
                                },
                                select: function ( $input ) {
                                        $input.closest( 'form' ).append(
-                                               $( '<input type="hidden"/>', {
-                                                       name: 'fulltext',
-                                                       val: '1'
-                                               })
+                                               $( '<input type="hidden" name="fulltext" value="1"/>' )
                                        );
                                        $input.closest( 'form' ).submit();
                                }
 
        } );
 
-}( mediaWiki, jQuery ) );
\ No newline at end of file
+}( mediaWiki, jQuery ) );
index aa982d3..39206c3 100644 (file)
 .config-settings-block {
        list-style-type: none;
        list-style-image: none;
-       float: left;
        margin: 0;
        padding: 0;
 }
index fa60b42..27843a3 100644 (file)
@@ -987,8 +987,7 @@ bar
 !!end
 
 ###
-### Parsoid-centric tests for testing RT edge cases
-### around comments and white-space inside pre blocks
+### Parsoid-centric tests for testing RT edge cases for pre
 ###
 
 !!test
@@ -1030,6 +1029,75 @@ c
 </pre>
 !!end
 
+!!test
+2a. Pre and tables
+!!input
+ {|
+ |-
+ !h1!!h2
+ |foo||bar
+ |}
+!!result
+<table>
+
+<tr>
+<th>h1</th>
+<th>h2
+</th>
+<td>foo</td>
+<td>bar
+</td></tr></table>
+
+!!end
+
+!!test
+2b. Pre and tables
+!!input
+  {|
+ |-
+|foo
+|}
+!!result
+<table>
+
+<tr>
+<td>foo
+</td></tr></table>
+
+!!end
+
+!!test
+3. Pre and block tags
+!!input
+ <p> foo </p>
+ <div> foo </div>
+ <span> foo </span>
+!!result
+ <p> foo </p>
+ <div> foo </div>
+<pre><span> foo </span>
+</pre>
+!!end
+
+!!test
+4. Multiple spaces at start-of-line
+!!input
+    <p> foo </p>
+    foo
+       {|
+|foo
+|}
+!!result
+    <p> foo </p>
+<pre>   foo
+</pre>
+<table>
+<tr>
+<td>foo
+</td></tr></table>
+
+!!end
+
 ###
 ### Definition lists
 ###
@@ -1134,7 +1202,6 @@ Definition lists: colon in HTML attribute
 
 !! end
 
-
 !! test
 Definition lists: self-closed tag
 !! input
@@ -1147,8 +1214,6 @@ Definition lists: self-closed tag
 
 !! test
 Bug 11748: Literal closing tags
-!! options
-disabled
 !! input
 <dl>
 <dt>test 1</dt>
@@ -1163,6 +1228,7 @@ disabled
 <dt>test 2</dt>
 <dd>test test test test test</dd>
 </dl>
+
 !! end
 
 !! test
@@ -1185,6 +1251,7 @@ Definition and unordered list using wiki syntax nested in unordered list using h
 !! end
 
 !! test
+
 Definition list with empty definition and following paragraph
 !! input
 ; term:
@@ -1196,6 +1263,23 @@ Paragraph text
 </p>
 !! end
 
+!! test
+Nested definition lists using html syntax
+!! input
+<dl><dd>
+<dl>
+<dd>Foo</dd>
+</dl>
+</dd></dl>
+!! result
+<dl><dd>
+<dl>
+<dd>Foo</dd>
+</dl>
+</dd></dl>
+
+!! end
+
 !! test
 Definition Lists: No nesting: Multiple dd's
 !! input
@@ -1252,6 +1336,26 @@ Definition Lists: Indentation: Multi-level indent
 
 !! end
 
+!! test
+Definition Lists: Hacky use to indent tables
+!! input
+::{|
+|foo
+|bar
+|}
+this text
+should be left alone
+!! result
+<dl><dd><dl><dd><table>
+<tr>
+<td>foo
+</td>
+<td>bar
+</td></tr></table></dd></dl></dd></dl>
+<p>this text
+should be left alone
+</p>
+!! end
 ## The PHP parser treats : items (dd) without a corresponding ; item (dt)
 ## as an empty dt item.  It also ignores all but the last ";" when followed
 ## by ":" later on.  So, ";" are not ignored in ";;;t3" but are ignored  in
@@ -2278,6 +2382,24 @@ Simple table
 
 !! end
 
+!! test
+Simple table but with multiple dashes for row wikitext
+!! input
+{| 
+| foo
+|-----
+| bar
+|}
+!! result
+<table>
+<tr>
+<td> foo
+</td></tr>
+<tr>
+<td> bar
+</td></tr></table>
+
+!! end
 !! test
 Multiplication table
 !! input
@@ -2349,6 +2471,29 @@ Multiplication table
 
 !! end
 
+!!test
+Allow +/- in 2nd and later cells in a row
+!!input
+{|
+| 1 || 2 || 3
+|-
+| 1 || +2 || -3
+|}
+!!result
+<table>
+<tr>
+<td> 1 </td>
+<td> 2 </td>
+<td> 3
+</td></tr>
+<tr>
+<td> 1 </td>
+<td> +2 </td>
+<td> -3
+</td></tr></table>
+
+!!end
+
 !! test
 Table rowspan
 !! input
@@ -3315,6 +3460,31 @@ Nested lists 8 (multiple nesting transitions)
 
 !! end
 
+!! test
+1. Lists with start-of-line-transparent tokens before bullets: Comments
+!! input
+*foo
+*<!--cmt-->bar
+<!--cmt-->*baz
+!! result
+<ul><li>foo
+</li><li>bar
+</li><li>baz
+</li></ul>
+
+!! end
+
+!! test
+2. Lists with start-of-line-transparent tokens before bullets: Template close
+!! input
+*foo {{echo|bar
+}}*baz
+!! result
+<ul><li>foo bar
+</li><li>baz
+</li></ul>
+
+!! end
 
 !! test
 List items are not parsed correctly following a <pre> block (bug 785)
@@ -4762,6 +4932,70 @@ a<div>bc</div>de
 
 !!end
 
+!!test
+Templates: Ugly templates: 1. Navbox template parses badly leading to table misnesting
+(Parsoid-centric)
+!! options
+disabled
+!!input
+{|
+|{{echo|foo</table>}}
+|bar
+|}
+!!result
+<table data-parsoid="{&quot;src&quot;:&quot;{|\n|{{echo|foo&lt;/table&gt;}}\n|bar\n|}&quot;}" about="#mwt1" typeof="mw:Object/Template ">
+<tbody><tr><td>foo</td></tr></tbody></table><span about="#mwt1">
+bar</span><span about="#mwt1">
+</span>
+!!end
+
+!!test
+Templates: Ugly templates: 2. Navbox template parses badly leading to table misnesting
+(Parsoid-centric)
+!! options
+disabled
+!!input
+<table>
+  <tr>
+    <td>
+    <table>
+      <tr>
+        <td>1. {{echo|foo </table>}}</td>
+        <td> bar </td>
+        <td>2. {{echo|baz </table>}}</td>
+      </tr>
+      <tr>
+        <td>abc</td>
+      </tr>
+    </table>
+    </td>
+  </tr>
+  <tr>
+    <td>xyz</td>
+  </tr>
+</table>
+!!result
+<table data-parsoid="{&quot;src&quot;:&quot;&lt;table&gt;\n  &lt;tr&gt;\n    &lt;td&gt;\n    &lt;table&gt;\n      &lt;tr&gt;\n        &lt;td&gt;1. {{echo|foo &lt;/table&gt;}}&lt;/td&gt;\n        &lt;td&gt; bar &lt;/td&gt;\n        &lt;td&gt;2. {{echo|baz &lt;/table&gt;}}&lt;/td&gt;\n      &lt;/tr&gt;\n      &lt;tr&gt;\n        &lt;td&gt;abc&lt;/td&gt;\n      &lt;/tr&gt;\n    &lt;/table&gt;\n    &lt;/td&gt;\n  &lt;/tr&gt;\n  &lt;tr&gt;\n    &lt;td&gt;xyz&lt;/td&gt;\n  &lt;/tr&gt;\n&lt;/table&gt;&quot;}" about="#mwt1" typeof="mw:Object/Template">
+  <tbody><tr data-parsoid="{&quot;stx&quot;:&quot;html&quot;}">
+    <td data-parsoid="{&quot;stx&quot;:&quot;html&quot;}">
+    <table data-parsoid="{&quot;stx&quot;:&quot;html&quot;}">
+      <tbody><tr data-parsoid="{&quot;stx&quot;:&quot;html&quot;}">
+        <td data-parsoid="{&quot;stx&quot;:&quot;html&quot;}">1. foo </td></tr></tbody></table></td>
+        <td data-parsoid="{&quot;stx&quot;:&quot;html&quot;}"> bar </td>
+        <td data-parsoid="{&quot;stx&quot;:&quot;html&quot;}">2. baz </td></tr></tbody></table><span about="#mwt1">
+      </span><span about="#mwt1">
+      
+        abc</span><span about="#mwt1">
+      </span><span about="#mwt1">
+    </span><span about="#mwt1">
+    </span><span about="#mwt1">
+  </span><span about="#mwt1">
+  
+    xyz</span><span about="#mwt1">
+  </span><span about="#mwt1">
+</span>
+!!end
+
 !!test
 Parser Functions: 1. Simple example
 !!input
@@ -5449,6 +5683,29 @@ Image with empty attribute
 
 !! end
 
+!! test
+Image with link tails
+!! input
+123[[Image:foobar.jpg]]456
+123[[Image:foobar.jpg|right]]456
+123[[Image:foobar.jpg|thumb]]456
+!! result
+<p>123<a href="/wiki/File:Foobar.jpg" class="image"><img alt="Foobar.jpg" src="http://example.com/images/3/3a/Foobar.jpg" width="1941" height="220" /></a>456
+</p>
+123<div class="floatright"><a href="/wiki/File:Foobar.jpg" class="image"><img alt="Foobar.jpg" src="http://example.com/images/3/3a/Foobar.jpg" width="1941" height="220" /></a></div>456
+123<div class="thumb tright"><div class="thumbinner" style="width:182px;"><a href="/wiki/File:Foobar.jpg" class="image"><img alt="Foobar.jpg" src="http://example.com/images/thumb/3/3a/Foobar.jpg/180px-Foobar.jpg" width="180" height="20" class="thumbimage" srcset="http://example.com/images/thumb/3/3a/Foobar.jpg/270px-Foobar.jpg 1.5x, http://example.com/images/thumb/3/3a/Foobar.jpg/360px-Foobar.jpg 2x" /></a>  <div class="thumbcaption"><div class="magnify"><a href="/wiki/File:Foobar.jpg" class="internal" title="Enlarge"><img src="/skins/common/images/magnify-clip.png" width="15" height="11" alt="" /></a></div></div></div></div>456
+
+!! end
+
+!! test
+Image with multiple captions -- only last one is accepted
+!! input
+[[Image:foobar.jpg|right|Caption1 - ignored|[[Caption2]] - ignored|Caption3 - accepted]]
+!! result
+<div class="floatright"><a href="/wiki/File:Foobar.jpg" class="image" title="Caption3 - accepted"><img alt="Caption3 - accepted" src="http://example.com/images/3/3a/Foobar.jpg" width="1941" height="220" /></a></div>
+
+!! end
+
 !! test
 Image with link parameter, wiki target
 !! input
@@ -5916,6 +6173,17 @@ pst
 [[Category:Foo (bar)|Foo]]
 !! end
 
+!! test
+Category with link tail
+!! options
+cat
+pst
+!! input
+123[[Category:Foo]]456
+!! result
+123[[Category:Foo]]456
+!! end
+
 !! test
 Category with template
 !! options
index 5bc36ed..258dfec 100644 (file)
@@ -250,7 +250,7 @@ abstract class MediaWikiTestCase extends PHPUnit_Framework_TestCase {
                                throw new MWException( "MW global $name is not an array." );
                        }
 
-                       //NOTE: do not use array_merge, it screws up for numeric keys.
+                       // NOTE: do not use array_merge, it screws up for numeric keys.
                        $merged = $GLOBALS[$name];
                        foreach ( $values as $k => $v ) {
                                $merged[$k] = $v;
index bedf6c3..b106d2b 100644 (file)
@@ -296,7 +296,7 @@ CREATE TABLE /*_*/uploadstash (
        us_size int unsigned NOT NULL,
        us_sha1 varchar(31) NOT NULL,
        us_mime varchar(255),
-       us_media_type ENUM("UNKNOWN", "BITMAP", "DRAWING", "AUDIO", "VIDEO", "MULTIMEDIA", "OFFICE", "TEXT", "EXECUTABLE", "ARCHIVE") default NULL,
+       us_media_type ENUM("UNKNOWN", "BITMAP", "DRAWING", "AUDIO", "VIDEO", "MULTIMEDIA", "OFFICE", "TEXT", "EXECUTABLE", "ARCHIVE") default NULL,
        us_image_width int unsigned,
        us_image_height int unsigned,
        us_image_bits smallint unsigned
index 46aaa4b..20952b1 100644 (file)
@@ -13,16 +13,16 @@ class ArticleTest extends MediaWikiTestCase {
 
        /** creates a title object and its article object */
        protected function setUp() {
+               parent::setUp();
                $this->title = Title::makeTitle( NS_MAIN, 'SomePage' );
                $this->article = new Article( $this->title );
-
        }
 
        /** cleanup title object and its article object */
        protected function tearDown() {
+               parent::tearDown();
                $this->title = null;
                $this->article = null;
-
        }
 
        function testImplementsGetMagic() {
index 97fffda..7db8c8c 100644 (file)
@@ -7,6 +7,7 @@
 class CdbTest extends MediaWikiTestCase {
 
        protected function setUp() {
+               parent::setUp();
                if ( !CdbReader::haveExtension() ) {
                        $this->markTestSkipped( 'Native CDB support is not available' );
                }
diff --git a/tests/phpunit/includes/ContentHandlerTest.php b/tests/phpunit/includes/ContentHandlerTest.php
deleted file mode 100644 (file)
index 797a3ee..0000000
+++ /dev/null
@@ -1,410 +0,0 @@
-<?php
-
-/**
- * @group ContentHandler
- *
- * @note: Declare that we are using the database, because otherwise we'll fail in the "databaseless" test run.
- * This is because the LinkHolderArray used by the parser needs database access.
- *
- * @group Database
- */
-class ContentHandlerTest extends MediaWikiTestCase {
-
-       public function setup() {
-               parent::setup();
-
-               global $wgExtraNamespaces, $wgNamespaceContentModels, $wgContentHandlers, $wgContLang;
-
-               $wgExtraNamespaces[ 12312 ] = 'Dummy';
-               $wgExtraNamespaces[ 12313 ] = 'Dummy_talk';
-
-               $wgNamespaceContentModels[ 12312 ] = "testing";
-               $wgContentHandlers[ "testing" ] = 'DummyContentHandlerForTesting';
-
-               MWNamespace::getCanonicalNamespaces( true ); # reset namespace cache
-               $wgContLang->resetNamespaces(); # reset namespace cache
-       }
-
-       public function teardown() {
-               global $wgExtraNamespaces, $wgNamespaceContentModels, $wgContentHandlers, $wgContLang;
-
-               unset( $wgExtraNamespaces[ 12312 ] );
-               unset( $wgExtraNamespaces[ 12313 ] );
-
-               unset( $wgNamespaceContentModels[ 12312 ] );
-               unset( $wgContentHandlers[ "testing" ] );
-
-               MWNamespace::getCanonicalNamespaces( true ); # reset namespace cache
-               $wgContLang->resetNamespaces(); # reset namespace cache
-
-               parent::teardown();
-       }
-
-       public function dataGetDefaultModelFor() {
-               //NOTE: assume that the Help namespace default to wikitext content
-               return array(
-                       array( 'Help:Foo', CONTENT_MODEL_WIKITEXT ),
-                       array( 'Help:Foo.js', CONTENT_MODEL_WIKITEXT ),
-                       array( 'Help:Foo/bar.js', CONTENT_MODEL_WIKITEXT ),
-                       array( 'User:Foo', CONTENT_MODEL_WIKITEXT ),
-                       array( 'User:Foo.js', CONTENT_MODEL_WIKITEXT ),
-                       array( 'User:Foo/bar.js', CONTENT_MODEL_JAVASCRIPT ),
-                       array( 'User:Foo/bar.css', CONTENT_MODEL_CSS ),
-                       array( 'User talk:Foo/bar.css', CONTENT_MODEL_WIKITEXT ),
-                       array( 'User:Foo/bar.js.xxx', CONTENT_MODEL_WIKITEXT ),
-                       array( 'User:Foo/bar.xxx', CONTENT_MODEL_WIKITEXT ),
-                       array( 'MediaWiki:Foo.js', CONTENT_MODEL_JAVASCRIPT ),
-                       array( 'MediaWiki:Foo.css', CONTENT_MODEL_CSS ),
-                       array( 'MediaWiki:Foo.JS', CONTENT_MODEL_WIKITEXT ),
-                       array( 'MediaWiki:Foo.CSS', CONTENT_MODEL_WIKITEXT ),
-                       array( 'MediaWiki:Foo.css.xxx', CONTENT_MODEL_WIKITEXT ),
-               );
-       }
-
-       /**
-        * @dataProvider dataGetDefaultModelFor
-        */
-       public function testGetDefaultModelFor( $title, $expectedModelId ) {
-               $title = Title::newFromText( $title );
-               $this->assertEquals( $expectedModelId, ContentHandler::getDefaultModelFor( $title ) );
-       }
-       /**
-        * @dataProvider dataGetDefaultModelFor
-        */
-       public function testGetForTitle( $title, $expectedContentModel ) {
-               $title = Title::newFromText( $title );
-               $handler = ContentHandler::getForTitle( $title );
-               $this->assertEquals( $expectedContentModel, $handler->getModelID() );
-       }
-
-       public function dataGetLocalizedName() {
-               return array(
-                       array( null, null ),
-                       array( "xyzzy", null ),
-
-                       array( CONTENT_MODEL_JAVASCRIPT, '/javascript/i' ), //XXX: depends on content language
-               );
-       }
-
-       /**
-        * @dataProvider dataGetLocalizedName
-        */
-       public function testGetLocalizedName( $id, $expected ) {
-               $name = ContentHandler::getLocalizedName( $id );
-
-               if ( $expected ) {
-                       $this->assertNotNull( $name, "no name found for content model $id" );
-                       $this->assertTrue( preg_match( $expected, $name ) > 0 ,
-                                                               "content model name for #$id did not match pattern $expected" );
-               } else {
-                       $this->assertEquals( $id, $name, "localization of unknown model $id should have "
-                                                                                       . "fallen back to use the model id directly." );
-               }
-       }
-
-       public function dataGetPageLanguage() {
-               global $wgLanguageCode;
-
-               return array(
-                       array( "Main", $wgLanguageCode ),
-                       array( "Dummy:Foo", $wgLanguageCode ),
-                       array( "MediaWiki:common.js", 'en' ),
-                       array( "User:Foo/common.js", 'en' ),
-                       array( "MediaWiki:common.css", 'en' ),
-                       array( "User:Foo/common.css", 'en' ),
-                       array( "User:Foo", $wgLanguageCode ),
-
-                       array( CONTENT_MODEL_JAVASCRIPT, 'javascript' ),
-               );
-       }
-
-       /**
-        * @dataProvider dataGetPageLanguage
-        */
-       public function testGetPageLanguage( $title, $expected ) {
-               if ( is_string( $title ) ) {
-                       $title = Title::newFromText( $title );
-               }
-
-               $expected = wfGetLangObj( $expected );
-
-               $handler = ContentHandler::getForTitle( $title );
-               $lang = $handler->getPageLanguage( $title );
-
-               $this->assertEquals( $expected->getCode(), $lang->getCode() );
-       }
-
-       public function testGetContentText_Null( ) {
-               global $wgContentHandlerTextFallback;
-
-               $content = null;
-
-               $wgContentHandlerTextFallback = 'fail';
-               $text = ContentHandler::getContentText( $content );
-               $this->assertEquals( '', $text );
-
-               $wgContentHandlerTextFallback = 'serialize';
-               $text = ContentHandler::getContentText( $content );
-               $this->assertEquals( '', $text );
-
-               $wgContentHandlerTextFallback = 'ignore';
-               $text = ContentHandler::getContentText( $content );
-               $this->assertEquals( '', $text );
-       }
-
-       public function testGetContentText_TextContent( ) {
-               global $wgContentHandlerTextFallback;
-
-               $content = new WikitextContent( "hello world" );
-
-               $wgContentHandlerTextFallback = 'fail';
-               $text = ContentHandler::getContentText( $content );
-               $this->assertEquals( $content->getNativeData(), $text );
-
-               $wgContentHandlerTextFallback = 'serialize';
-               $text = ContentHandler::getContentText( $content );
-               $this->assertEquals( $content->serialize(), $text );
-
-               $wgContentHandlerTextFallback = 'ignore';
-               $text = ContentHandler::getContentText( $content );
-               $this->assertEquals( $content->getNativeData(), $text );
-       }
-
-       public function testGetContentText_NonTextContent( ) {
-               global $wgContentHandlerTextFallback;
-
-               $content = new DummyContentForTesting( "hello world" );
-
-               $wgContentHandlerTextFallback = 'fail';
-
-               try {
-                       $text = ContentHandler::getContentText( $content );
-
-                       $this->fail( "ContentHandler::getContentText should have thrown an exception for non-text Content object" );
-               } catch (MWException $ex) {
-                       // as expected
-               }
-
-               $wgContentHandlerTextFallback = 'serialize';
-               $text = ContentHandler::getContentText( $content );
-               $this->assertEquals( $content->serialize(), $text );
-
-               $wgContentHandlerTextFallback = 'ignore';
-               $text = ContentHandler::getContentText( $content );
-               $this->assertNull( $text );
-       }
-
-       #public static function makeContent( $text, Title $title, $modelId = null, $format = null )
-
-       public function dataMakeContent() {
-               //NOTE: assume the Help namespace defaults to wikitext content
-               return array(
-                       array( 'hallo', 'Help:Test', null, null, CONTENT_MODEL_WIKITEXT, 'hallo', false ),
-                       array( 'hallo', 'MediaWiki:Test.js', null, null, CONTENT_MODEL_JAVASCRIPT, 'hallo', false ),
-                       array( serialize('hallo'), 'Dummy:Test', null, null, "testing", 'hallo', false ),
-
-                       array( 'hallo', 'Help:Test', null, CONTENT_FORMAT_WIKITEXT, CONTENT_MODEL_WIKITEXT, 'hallo', false ),
-                       array( 'hallo', 'MediaWiki:Test.js', null, CONTENT_FORMAT_JAVASCRIPT, CONTENT_MODEL_JAVASCRIPT, 'hallo', false ),
-                       array( serialize('hallo'), 'Dummy:Test', null, "testing", "testing", 'hallo', false ),
-
-                       array( 'hallo', 'Help:Test', CONTENT_MODEL_CSS, null, CONTENT_MODEL_CSS, 'hallo', false ),
-                       array( 'hallo', 'MediaWiki:Test.js', CONTENT_MODEL_CSS, null, CONTENT_MODEL_CSS, 'hallo', false ),
-                       array( serialize('hallo'), 'Dummy:Test', CONTENT_MODEL_CSS, null, CONTENT_MODEL_CSS, serialize('hallo'), false ),
-
-                       array( 'hallo', 'Help:Test', CONTENT_MODEL_WIKITEXT, "testing", null, null, true ),
-                       array( 'hallo', 'MediaWiki:Test.js', CONTENT_MODEL_CSS, "testing", null, null, true ),
-                       array( 'hallo', 'Dummy:Test', CONTENT_MODEL_JAVASCRIPT, "testing", null, null, true ),
-               );
-       }
-
-       /**
-        * @dataProvider dataMakeContent
-        */
-       public function testMakeContent( $data, $title, $modelId, $format, $expectedModelId, $expectedNativeData, $shouldFail ) {
-               global $wgExtraNamespaces, $wgNamespaceContentModels, $wgContentHandlers;
-
-               $title = Title::newFromText( $title );
-
-               try {
-                       $content = ContentHandler::makeContent( $data, $title, $modelId, $format );
-
-                       if ( $shouldFail ) $this->fail( "ContentHandler::makeContent should have failed!" );
-
-                       $this->assertEquals( $expectedModelId, $content->getModel(), 'bad model id' );
-                       $this->assertEquals( $expectedNativeData, $content->getNativeData(), 'bads native data' );
-               } catch ( MWException $ex ) {
-                       if ( !$shouldFail ) $this->fail( "ContentHandler::makeContent failed unexpectedly: " . $ex->getMessage() );
-                       else $this->assertTrue( true ); // dummy, so we don't get the "test did not perform any assertions" message.
-               }
-
-       }
-
-       public function testSupportsSections() {
-               $this->markTestIncomplete( "not yet implemented" );
-       }
-
-       public function testRunLegacyHooks() {
-               Hooks::register( 'testRunLegacyHooks', __CLASS__ . '::dummyHookHandler' );
-
-               $content = new WikitextContent( 'test text' );
-               $ok = ContentHandler::runLegacyHooks( 'testRunLegacyHooks', array( 'foo', &$content, 'bar' ), false );
-
-               $this->assertTrue( $ok, "runLegacyHooks should have returned true" );
-               $this->assertEquals( "TEST TEXT", $content->getNativeData() );
-       }
-
-       public static function dummyHookHandler( $foo, &$text, $bar ) {
-               if ( $text === null || $text === false ) {
-                       return false;
-               }
-
-               $text = strtoupper( $text );
-
-               return true;
-       }
-}
-
-class DummyContentHandlerForTesting extends ContentHandler {
-
-       public function __construct( $dataModel ) {
-               parent::__construct( $dataModel, array( "testing" ) );
-       }
-
-       /**
-        * Serializes Content object of the type supported by this ContentHandler.
-        *
-        * @param Content $content the Content object to serialize
-        * @param null $format the desired serialization format
-        * @return String serialized form of the content
-        */
-       public function serializeContent( Content $content, $format = null )
-       {
-          return $content->serialize();
-       }
-
-       /**
-        * Unserializes a Content object of the type supported by this ContentHandler.
-        *
-        * @param $blob String serialized form of the content
-        * @param null $format the format used for serialization
-        * @return Content the Content object created by deserializing $blob
-        */
-       public function unserializeContent( $blob, $format = null )
-       {
-               $d = unserialize( $blob );
-               return new DummyContentForTesting( $d );
-       }
-
-       /**
-        * Creates an empty Content object of the type supported by this ContentHandler.
-        *
-        */
-       public function makeEmptyContent()
-       {
-               return new DummyContentForTesting( '' );
-       }
-}
-
-class DummyContentForTesting extends AbstractContent {
-
-       public function __construct( $data ) {
-               parent::__construct( "testing" );
-
-               $this->data = $data;
-       }
-
-       public function serialize( $format = null ) {
-               return serialize( $this->data );
-       }
-
-       /**
-        * @return String a string representing the content in a way useful for building a full text search index.
-        *         If no useful representation exists, this method returns an empty string.
-        */
-       public function getTextForSearchIndex() {
-               return '';
-       }
-
-       /**
-        * @return String the wikitext to include when another page includes this  content, or false if the content is not
-        *         includable in a wikitext page.
-        */
-       public function getWikitextForTransclusion() {
-               return false;
-       }
-
-       /**
-        * Returns a textual representation of the content suitable for use in edit summaries and log messages.
-        *
-        * @param int $maxlength maximum length of the summary text
-        * @return String the summary text
-        */
-       public function getTextForSummary( $maxlength = 250 ) {
-               return '';
-       }
-
-       /**
-        * Returns native represenation of the data. Interpretation depends on the data model used,
-        * as given by getDataModel().
-        *
-        * @return mixed the native representation of the content. Could be a string, a nested array
-        *         structure, an object, a binary blob... anything, really.
-        */
-       public function getNativeData()
-       {
-               return $this->data;
-       }
-
-       /**
-        * returns the content's nominal size in bogo-bytes.
-        *
-        * @return int
-        */
-       public function getSize() {
-               return strlen( $this->data );
-       }
-
-       /**
-        * Return a copy of this Content object. The following must be true for the object returned
-        * if $copy = $original->copy()
-        *
-        * * get_class($original) === get_class($copy)
-        * * $original->getModel() === $copy->getModel()
-        * * $original->equals( $copy )
-        *
-        * If and only if the Content object is imutable, the copy() method can and should
-        * return $this. That is,  $copy === $original may be true, but only for imutable content
-        * objects.
-        *
-        * @return Content. A copy of this object
-        */
-       public function copy() {
-               return $this;
-       }
-
-       /**
-        * Returns true if this content is countable as a "real" wiki page, provided
-        * that it's also in a countable location (e.g. a current revision in the main namespace).
-        *
-        * @param $hasLinks Bool: if it is known whether this content contains links, provide this information here,
-        *                        to avoid redundant parsing to find out.
-        * @return boolean
-        */
-       public function isCountable( $hasLinks = null ) {
-               return false;
-       }
-
-       /**
-        * @param Title $title
-        * @param null $revId
-        * @param null|ParserOptions $options
-        * @param Boolean $generateHtml whether to generate Html (default: true). If false,
-        *        the result of calling getText() on the ParserOutput object returned by
-        *        this method is undefined.
-        *
-        * @return ParserOutput
-        */
-       public function getParserOutput( Title $title, $revId = null, ParserOptions $options = NULL, $generateHtml = true ) {
-               return new ParserOutput( $this->getNativeData() );
-       }
-}
diff --git a/tests/phpunit/includes/CssContentTest.php b/tests/phpunit/includes/CssContentTest.php
deleted file mode 100644 (file)
index b6e8d29..0000000
+++ /dev/null
@@ -1,60 +0,0 @@
-<?php
-
-/**
- * @group ContentHandler
- *
- * @group Database
- *        ^--- needed, because we do need the database to test link updates
- */
-class CssContentTest extends JavascriptContentTest {
-
-       public function newContent( $text ) {
-               return new CssContent( $text );
-       }
-
-
-       public function dataGetParserOutput() {
-               return array(
-                       array(
-                               "MediaWiki:Test.css",
-                               null,
-                               "hello <world>\n",
-                               "<pre class=\"mw-code mw-css\" dir=\"ltr\">\nhello &lt;world&gt;\n\n</pre>" ),
-
-                       array(
-                               "MediaWiki:Test.css",
-                               null,
-                               "/* hello [[world]] */\n",
-                               "<pre class=\"mw-code mw-css\" dir=\"ltr\">\n/* hello [[world]] */\n\n</pre>",
-                               array( 'Links' => array( // NOTE: assumes default settings for $wgTextModelsToParse
-                                       array( 'World' => 0 ) ) ) ),
-
-                       // @todo: more...?
-               );
-       }
-
-
-       # =================================================================================================================
-
-       public function testGetModel() {
-               $content = $this->newContent( "hello world." );
-
-               $this->assertEquals( CONTENT_MODEL_CSS, $content->getModel() );
-       }
-
-       public function testGetContentHandler() {
-               $content = $this->newContent( "hello world." );
-
-               $this->assertEquals( CONTENT_MODEL_CSS, $content->getContentHandler()->getModelID() );
-       }
-
-       public function dataEquals( ) {
-               return array(
-                       array( new CssContent( "hallo" ), null, false ),
-                       array( new CssContent( "hallo" ), new CssContent( "hallo" ), true ),
-                       array( new CssContent( "hallo" ), new WikitextContent( "hallo" ), false ),
-                       array( new CssContent( "hallo" ), new CssContent( "HALLO" ), false ),
-               );
-       }
-
-}
index 14bc0bb..ca1615e 100644 (file)
@@ -8,17 +8,18 @@ class ExtraParserTest extends MediaWikiTestCase {
        protected function setUp() {
                parent::setUp();
 
+               $contLang = Language::factory( 'en' );
                $this->setMwGlobals( array(
                        'wgShowDBErrorBacktrace' => true,
                        'wgLanguageCode' => 'en',
-                       'wgContLang' => Language::factory( 'en' ),
+                       'wgContLang' => $contLang,
                        'wgLang' => Language::factory( 'en' ),
                        'wgMemc' => new EmptyBagOStuff,
                        'wgAlwaysUseTidy' => false,
                        'wgCleanSignatures' => true,
                ) );
                
-               $this->options = new ParserOptions;
+               $this->options = ParserOptions::newFromUserAndLang( new User, $contLang );
                $this->options->setTemplateCallback( array( __CLASS__, 'statelessFetchTemplate' ) );
                $this->parser = new Parser;
 
index 35c7f8f..56691c9 100644 (file)
@@ -26,6 +26,7 @@ class FauxResponseTest extends MediaWikiTestCase {
        var $response;
 
        protected function setUp() {
+               parent::setUp();
                $this->response = new FauxResponse;
        }
 
index d86c95d..af28f79 100644 (file)
@@ -41,8 +41,8 @@ class FormOptionsInitializationTest extends MediaWikiTestCase {
         * with.
         */
        protected function setUp() {
+               parent::setUp();
                $this->object = new FormOptionsExposed();
-               
        }
 
        public function testAddStringOption() {
index 749343e..d4e3c5e 100644 (file)
@@ -23,12 +23,13 @@ class FormOptionsTest extends MediaWikiTestCase {
        protected $object;
 
        /**
-        * Instanciates a FormOptions object to play with.       
+        * Instanciates a FormOptions object to play with.
         * FormOptions::add() is tested by the class FormOptionsInitializationTest
         * so we assume the function is well tested already an use it to create
         * the fixture.
         */
        protected function setUp() {
+               parent::setUp();
                $this->object = new FormOptions;
                $this->object->add( 'string1', 'string one' );
                $this->object->add( 'string2', 'string two' );
index f4ec7a5..4a0f406 100644 (file)
@@ -7,7 +7,7 @@ class wfBCP47 extends MediaWikiTestCase {
         * test @see wfBCP47().
         * Please note the BCP explicitly state that language codes are case
         * insensitive, there are some exceptions to the rule :)
-        * This test is used to verify our formatting against all lower and
+        * This test is used to verify our formatting against all lower and
         * all upper cases language code.
         *
         * @see http://tools.ietf.org/html/bcp47
index 155bd31..b49de65 100644 (file)
@@ -131,13 +131,10 @@ class HttpTest extends MediaWikiTestCase {
         * handles header reporting on redirect pages, and will need to be
         * rewritten when bug 29232 is taken care of (high-level handling of
         * HTTP redirects).
-        * @group Broken
-        *  MWHttpRequestTester's constructor is private, needs to use
-        *  MWHttpRequestTester::factory instead. However the objects coming
-        *  from that won't have MWHttpRequestTester::setRespHeaders...
         */
        function testRelativeRedirections() {
-               $h = new MWHttpRequestTester( 'http://oldsite/file.ext' );
+               $h = MWHttpRequestTester::factory( 'http://oldsite/file.ext' );
+
                # Forge a Location header
                $h->setRespHeaders( 'location', array(
                        'http://newsite/file.ext',
@@ -175,10 +172,42 @@ class HttpTest extends MediaWikiTestCase {
 }
 
 /**
- * Class to let us overwrite MWHttpREquest respHeaders variable
+ * Class to let us overwrite MWHttpRequest respHeaders variable
  */
 class MWHttpRequestTester extends MWHttpRequest {
+
+       // function derived from the MWHttpRequest factory function but 
+       // returns appropriate tester class here
+       public static function factory( $url, $options = null ) {
+               if ( !Http::$httpEngine ) {
+                       Http::$httpEngine = function_exists( 'curl_init' ) ? 'curl' : 'php';
+               } elseif ( Http::$httpEngine == 'curl' && !function_exists( 'curl_init' ) ) {
+                       throw new MWException( __METHOD__ . ': curl (http://php.net/curl) is not installed, but' .
+                                       'Http::$httpEngine is set to "curl"' );
+               }
+
+               switch( Http::$httpEngine ) {
+                       case 'curl':
+                               return new CurlHttpRequestTester( $url, $options );
+                       case 'php':
+                               if ( !wfIniGetBool( 'allow_url_fopen' ) ) {
+                                       throw new MWException( __METHOD__ . ': allow_url_fopen needs to be enabled for pure PHP' .
+                                               ' http requests to work. If possible, curl should be used instead. See http://php.net/curl.' );
+                               }
+                               return new PhpHttpRequestTester( $url, $options );
+                       default:
+               }
+       }
+}
+
+class CurlHttpRequestTester extends CurlHttpRequest {
+       function setRespHeaders( $name, $value ) {
+               $this->respHeaders[$name] = $value;
+       }
+}
+
+class PhpHttpRequestTester extends PhpHttpRequest {
        function setRespHeaders( $name, $value ) {
-               $this->respHeaders[$name] = $value ;
+               $this->respHeaders[$name] = $value;
        }
 }
diff --git a/tests/phpunit/includes/JavascriptContentTest.php b/tests/phpunit/includes/JavascriptContentTest.php
deleted file mode 100644 (file)
index d3810af..0000000
+++ /dev/null
@@ -1,272 +0,0 @@
-<?php
-
-/**
- * @group ContentHandler
- *
- * @group Database
- *        ^--- needed, because we do need the database to test link updates
- */
-class JavascriptContentTest extends TextContentTest {
-
-       public function newContent( $text ) {
-               return new JavascriptContent( $text );
-       }
-
-
-       public function dataGetParserOutput() {
-               return array(
-                       array(
-                               "MediaWiki:Test.js",
-                               null,
-                               "hello <world>\n",
-                               "<pre class=\"mw-code mw-js\" dir=\"ltr\">\nhello &lt;world&gt;\n\n</pre>" ),
-
-                       array(
-                               "MediaWiki:Test.js",
-                               null,
-                               "hello(); // [[world]]\n",
-                               "<pre class=\"mw-code mw-js\" dir=\"ltr\">\nhello(); // [[world]]\n\n</pre>",
-                               array( 'Links' => array( // NOTE: assumes default settings for $wgTextModelsToParse
-                                                       array( 'World' => 0 ) ) ) ),
-
-                       // @todo: more...?
-               );
-       }
-
-       public function dataGetSection() {
-               return array(
-                       array( WikitextContentTest::$sections,
-                              "0",
-                              null
-                       ),
-                       array( WikitextContentTest::$sections,
-                              "2",
-                              null
-                       ),
-                       array( WikitextContentTest::$sections,
-                              "8",
-                              null
-                       ),
-               );
-       }
-
-       public function dataReplaceSection() {
-               return array(
-                       array( WikitextContentTest::$sections,
-                              "0",
-                              "No more",
-                              null,
-                              null
-                       ),
-                       array( WikitextContentTest::$sections,
-                              "",
-                              "No more",
-                              null,
-                              null
-                       ),
-                       array( WikitextContentTest::$sections,
-                              "2",
-                              "== TEST ==\nmore fun",
-                              null,
-                              null
-                       ),
-                       array( WikitextContentTest::$sections,
-                              "8",
-                              "No more",
-                              null,
-                              null
-                       ),
-                       array( WikitextContentTest::$sections,
-                              "new",
-                              "No more",
-                              "New",
-                              null
-                       ),
-               );
-       }
-
-       public function testAddSectionHeader( ) {
-               $content = $this->newContent( 'hello world' );
-               $c = $content->addSectionHeader( 'test' );
-
-               $this->assertTrue( $content->equals( $c ) );
-       }
-
-       // XXX: currently, preSaveTransform is applied to scripts. this may change or become optional.
-       public function dataPreSaveTransform() {
-               return array(
-                       array( 'hello this is ~~~',
-                               "hello this is [[Special:Contributions/127.0.0.1|127.0.0.1]]",
-                       ),
-                       array( 'hello \'\'this\'\' is <nowiki>~~~</nowiki>',
-                               'hello \'\'this\'\' is <nowiki>~~~</nowiki>',
-                       ),
-                       array( " Foo \n ",
-                               " Foo",
-                       ),
-               );
-       }
-
-       public function dataPreloadTransform() {
-               return array(
-                       array( 'hello this is ~~~',
-                              "hello this is ~~~",
-                       ),
-                       array( 'hello \'\'this\'\' is <noinclude>foo</noinclude><includeonly>bar</includeonly>',
-                              'hello \'\'this\'\' is <noinclude>foo</noinclude><includeonly>bar</includeonly>',
-                       ),
-               );
-       }
-
-       public function dataGetRedirectTarget() {
-               return array(
-                       array( '#REDIRECT [[Test]]',
-                              null,
-                       ),
-                       array( '#REDIRECT Test',
-                              null,
-                       ),
-                       array( '* #REDIRECT [[Test]]',
-                              null,
-                       ),
-               );
-       }
-
-       /**
-        * @todo: test needs database!
-        */
-       /*
-       public function getRedirectChain() {
-               $text = $this->getNativeData();
-               return Title::newFromRedirectArray( $text );
-       }
-       */
-
-       /**
-        * @todo: test needs database!
-        */
-       /*
-       public function getUltimateRedirectTarget() {
-               $text = $this->getNativeData();
-               return Title::newFromRedirectRecurse( $text );
-       }
-       */
-
-
-       public function dataIsCountable() {
-               return array(
-                       array( '',
-                              null,
-                              'any',
-                              true
-                       ),
-                       array( 'Foo',
-                              null,
-                              'any',
-                              true
-                       ),
-                       array( 'Foo',
-                              null,
-                              'comma',
-                              false
-                       ),
-                       array( 'Foo, bar',
-                              null,
-                              'comma',
-                              false
-                       ),
-                       array( 'Foo',
-                              null,
-                              'link',
-                              false
-                       ),
-                       array( 'Foo [[bar]]',
-                              null,
-                              'link',
-                              false
-                       ),
-                       array( 'Foo',
-                              true,
-                              'link',
-                              false
-                       ),
-                       array( 'Foo [[bar]]',
-                              false,
-                              'link',
-                              false
-                       ),
-                       array( '#REDIRECT [[bar]]',
-                              true,
-                              'any',
-                              true
-                       ),
-                       array( '#REDIRECT [[bar]]',
-                              true,
-                              'comma',
-                              false
-                       ),
-                       array( '#REDIRECT [[bar]]',
-                              true,
-                              'link',
-                              false
-                       ),
-               );
-       }
-
-       public function dataGetTextForSummary() {
-               return array(
-                       array( "hello\nworld.",
-                              16,
-                              'hello world.',
-                       ),
-                       array( 'hello world.',
-                              8,
-                              'hello...',
-                       ),
-                       array( '[[hello world]].',
-                              8,
-                              '[[hel...',
-                       ),
-               );
-       }
-
-       public function testMatchMagicWord( ) {
-               $mw = MagicWord::get( "staticredirect" );
-
-               $content = $this->newContent( "#REDIRECT [[FOO]]\n__STATICREDIRECT__" );
-               $this->assertFalse( $content->matchMagicWord( $mw ), "should not have matched magic word, since it's not wikitext" );
-       }
-
-       public function testUpdateRedirect( ) {
-               $target = Title::newFromText( "testUpdateRedirect_target" );
-
-               $content = $this->newContent( "#REDIRECT [[Someplace]]" );
-               $newContent = $content->updateRedirect( $target );
-
-               $this->assertTrue( $content->equals( $newContent ), "content should be unchanged since it's not wikitext" );
-       }
-
-       # =================================================================================================================
-
-       public function testGetModel() {
-               $content = $this->newContent( "hello world." );
-
-               $this->assertEquals( CONTENT_MODEL_JAVASCRIPT, $content->getModel() );
-       }
-
-       public function testGetContentHandler() {
-               $content = $this->newContent( "hello world." );
-
-               $this->assertEquals( CONTENT_MODEL_JAVASCRIPT, $content->getContentHandler()->getModelID() );
-       }
-
-       public function dataEquals( ) {
-               return array(
-                       array( new JavascriptContent( "hallo" ), null, false ),
-                       array( new JavascriptContent( "hallo" ), new JavascriptContent( "hallo" ), true ),
-                       array( new JavascriptContent( "hallo" ), new CssContent( "hallo" ), false ),
-                       array( new JavascriptContent( "hallo" ), new JavascriptContent( "HALLO" ), false ),
-               );
-       }
-
-}
index bc71ab7..7499272 100644 (file)
@@ -26,6 +26,7 @@ class LinksUpdateTest extends MediaWikiTestCase {
        }
 
        protected function setUp() {
+               parent::setUp();
                $dbw = wfGetDB( DB_MASTER );
                $dbw->replace(
                        'interwiki',
index 5de5cc9..01d406a 100644 (file)
@@ -449,7 +449,7 @@ class MWNamespaceTest extends MediaWikiTestCase {
         *   $wgCapitalLinkOverrides = array(); by default
         *   $wgCapitalLinks = true; by default
         * This function test $wgCapitalLinks
-        *
+        *
         * Global setting correctness is tested against the NS_PROJECT and
         * NS_PROJECT_TALK namespaces since they are not hardcoded nor specials
         */
index 4487210..910743e 100644 (file)
@@ -6,6 +6,7 @@
 class PathRouterTest extends MediaWikiTestCase {
 
        protected function setUp() {
+               parent::setUp();
                $router = new PathRouter;
                $router->add("/wiki/$1");
                $this->basicRouter = $router;
index 8d2a7bd..fbaa34c 100644 (file)
@@ -41,6 +41,8 @@ class RevisionStorageTest extends MediaWikiTestCase {
        public function setUp() {
                global $wgExtraNamespaces, $wgNamespaceContentModels, $wgContentHandlers, $wgContLang;
 
+               parent::setUp();
+
                $wgExtraNamespaces[ 12312 ] = 'Dummy';
                $wgExtraNamespaces[ 12313 ] = 'Dummy_talk';
 
@@ -57,6 +59,8 @@ class RevisionStorageTest extends MediaWikiTestCase {
        public function tearDown() {
                global $wgExtraNamespaces, $wgNamespaceContentModels, $wgContentHandlers, $wgContLang;
 
+               parent::tearDown();
+
                unset( $wgExtraNamespaces[ 12312 ] );
                unset( $wgExtraNamespaces[ 12313 ] );
 
index 4e0d2f4..27c0bb5 100644 (file)
@@ -26,6 +26,8 @@ class SiteConfigurationTest extends MediaWikiTestCase {
        var $mConf;
 
        protected function setUp() {
+               parent::setUp();
+
                $this->mConf = new SiteConfiguration;
 
                $this->mConf->suffixes = array( 'wiki' );
@@ -92,7 +94,6 @@ class SiteConfigurationTest extends MediaWikiTestCase {
                $GLOBALS['global'] = array( 'global' => 'global' );
        }
 
-
        function testSiteFromDb() {
                $this->assertEquals(
                        array( 'wikipedia', 'en' ),
diff --git a/tests/phpunit/includes/TextContentTest.php b/tests/phpunit/includes/TextContentTest.php
deleted file mode 100644 (file)
index 10934b4..0000000
+++ /dev/null
@@ -1,371 +0,0 @@
-<?php
-
-/**
- * @group ContentHandler
- *
- * @group Database
- *        ^--- needed, because we do need the database to test link updates
- */
-class TextContentTest extends MediaWikiTestCase {
-
-       public function setup() {
-               global $wgUser;
-
-               // anon user
-               $wgUser = new User();
-               $wgUser->setName( '127.0.0.1' );
-
-               $this->context = new RequestContext( new FauxRequest() );
-               $this->context->setTitle( Title::newFromText( "Test" ) );
-               $this->context->setUser( $wgUser );
-       }
-
-       public function newContent( $text ) {
-               return new TextContent( $text );
-       }
-
-
-       public function dataGetParserOutput() {
-               return array(
-                       array(
-                               "TextContentTest_testGetParserOutput",
-                               CONTENT_MODEL_TEXT,
-                               "hello ''world'' & [[stuff]]\n", "hello ''world'' &amp; [[stuff]]",
-                               array( 'Links' => array() ) ),
-                       // @todo: more...?
-               );
-       }
-
-       /**
-        * @dataProvider dataGetParserOutput
-        */
-       public function testGetParserOutput( $title, $model, $text, $expectedHtml, $expectedFields = null ) {
-               $title = Title::newFromText( $title );
-               $content = ContentHandler::makeContent( $text, $title, $model );
-
-               $po = $content->getParserOutput( $title );
-
-               $html = $po->getText();
-               $html = preg_replace( '#<!--.*?-->#sm', '', $html ); // strip comments
-
-               $this->assertEquals( $expectedHtml, trim( $html ) );
-
-               if ( $expectedFields ) {
-                       foreach ( $expectedFields as $field => $exp ) {
-                               $f = 'get' . ucfirst( $field );
-                               $v = call_user_func( array( $po, $f ) );
-
-                               if ( is_array( $exp ) ) {
-                                       $this->assertArrayEquals( $exp, $v );
-                               } else {
-                                       $this->assertEquals( $exp, $v );
-                               }
-                       }
-               }
-
-               // @todo: assert more properties
-       }
-
-       public function dataPreSaveTransform() {
-               return array(
-                       array( #0: no signature resolution
-                               "hello this is ~~~",
-                               "hello this is ~~~",
-                       ),
-                       array( #1: rtrim
-                               " Foo \n ",
-                               " Foo",
-                       ),
-               );
-       }
-
-       /**
-        * @dataProvider dataPreSaveTransform
-        */
-       public function testPreSaveTransform( $text, $expected ) {
-               global $wgContLang;
-
-               $options = ParserOptions::newFromUserAndLang( $this->context->getUser(), $wgContLang );
-
-               $content = $this->newContent( $text );
-               $content = $content->preSaveTransform( $this->context->getTitle(), $this->context->getUser(), $options );
-
-               $this->assertEquals( $expected, $content->getNativeData() );
-       }
-
-       public function dataPreloadTransform() {
-               return array(
-                       array( 'hello this is ~~~',
-                              "hello this is ~~~",
-                       ),
-               );
-       }
-
-       /**
-        * @dataProvider dataPreloadTransform
-        */
-       public function testPreloadTransform( $text, $expected ) {
-               global $wgContLang;
-               $options = ParserOptions::newFromUserAndLang( $this->context->getUser(), $wgContLang );
-
-               $content = $this->newContent( $text );
-               $content = $content->preloadTransform( $this->context->getTitle(), $options );
-
-               $this->assertEquals( $expected, $content->getNativeData() );
-       }
-
-       public function dataGetRedirectTarget() {
-               return array(
-                       array( '#REDIRECT [[Test]]',
-                               null,
-                       ),
-               );
-       }
-
-       /**
-        * @dataProvider dataGetRedirectTarget
-        */
-       public function testGetRedirectTarget( $text, $expected ) {
-               $content = $this->newContent( $text );
-               $t = $content->getRedirectTarget( );
-
-               if ( is_null( $expected ) ) {
-                       $this->assertNull( $t, "text should not have generated a redirect target: $text" );
-               } else {
-                       $this->assertEquals( $expected, $t->getPrefixedText() );
-               }
-       }
-
-       /**
-        * @dataProvider dataGetRedirectTarget
-        */
-       public function isRedirect( $text, $expected ) {
-               $content = $this->newContent( $text );
-
-               $this->assertEquals( !is_null($expected), $content->isRedirect() );
-       }
-
-
-       /**
-        * @todo: test needs database! Should be done by a test class in the Database group.
-        */
-       /*
-       public function getRedirectChain() {
-               $text = $this->getNativeData();
-               return Title::newFromRedirectArray( $text );
-       }
-       */
-
-       /**
-        * @todo: test needs database! Should be done by a test class in the Database group.
-        */
-       /*
-       public function getUltimateRedirectTarget() {
-               $text = $this->getNativeData();
-               return Title::newFromRedirectRecurse( $text );
-       }
-       */
-
-
-       public function dataIsCountable() {
-               return array(
-                       array( '',
-                              null,
-                              'any',
-                              true
-                       ),
-                       array( 'Foo',
-                              null,
-                              'any',
-                              true
-                       ),
-                       array( 'Foo',
-                              null,
-                              'comma',
-                              false
-                       ),
-                       array( 'Foo, bar',
-                              null,
-                              'comma',
-                              false
-                       ),
-               );
-       }
-
-
-       /**
-        * @dataProvider dataIsCountable
-        * @group Database
-        */
-       public function testIsCountable( $text, $hasLinks, $mode, $expected ) {
-               global $wgArticleCountMethod;
-
-               $old = $wgArticleCountMethod;
-               $wgArticleCountMethod = $mode;
-
-               $content = $this->newContent( $text );
-
-               $v = $content->isCountable( $hasLinks, $this->context->getTitle() );
-               $wgArticleCountMethod = $old;
-
-               $this->assertEquals( $expected, $v, "isCountable() returned unexpected value " . var_export( $v, true )
-                                                   . " instead of " . var_export( $expected, true ) . " in mode `$mode` for text \"$text\"" );
-       }
-
-       public function dataGetTextForSummary() {
-               return array(
-                       array( "hello\nworld.",
-                              16,
-                              'hello world.',
-                       ),
-                       array( 'hello world.',
-                              8,
-                              'hello...',
-                       ),
-                       array( '[[hello world]].',
-                              8,
-                              '[[hel...',
-                       ),
-               );
-       }
-
-       /**
-        * @dataProvider dataGetTextForSummary
-        */
-       public function testGetTextForSummary( $text, $maxlength, $expected ) {
-               $content = $this->newContent( $text );
-
-               $this->assertEquals( $expected, $content->getTextForSummary( $maxlength ) );
-       }
-
-
-       public function testGetTextForSearchIndex( ) {
-               $content = $this->newContent( "hello world." );
-
-               $this->assertEquals( "hello world.", $content->getTextForSearchIndex() );
-       }
-
-       public function testCopy() {
-               $content = $this->newContent( "hello world." );
-               $copy = $content->copy();
-
-               $this->assertTrue( $content->equals( $copy ), "copy must be equal to original" );
-               $this->assertEquals( "hello world.", $copy->getNativeData() );
-       }
-
-       public function testGetSize( ) {
-               $content = $this->newContent( "hello world." );
-
-               $this->assertEquals( 12, $content->getSize() );
-       }
-
-       public function testGetNativeData( ) {
-               $content = $this->newContent( "hello world." );
-
-               $this->assertEquals( "hello world.", $content->getNativeData() );
-       }
-
-       public function testGetWikitextForTransclusion( ) {
-               $content = $this->newContent( "hello world." );
-
-               $this->assertEquals( "hello world.", $content->getWikitextForTransclusion() );
-       }
-
-       # =================================================================================================================
-
-       public function testGetModel() {
-               $content = $this->newContent( "hello world." );
-
-               $this->assertEquals( CONTENT_MODEL_TEXT, $content->getModel() );
-       }
-
-       public function testGetContentHandler() {
-               $content = $this->newContent( "hello world." );
-
-               $this->assertEquals( CONTENT_MODEL_TEXT, $content->getContentHandler()->getModelID() );
-       }
-
-       public function dataIsEmpty( ) {
-               return array(
-                       array( '', true ),
-                       array( '  ', false ),
-                       array( '0', false ),
-                       array( 'hallo welt.', false ),
-               );
-       }
-
-       /**
-        * @dataProvider dataIsEmpty
-        */
-       public function testIsEmpty( $text, $empty ) {
-               $content = $this->newContent( $text );
-
-               $this->assertEquals( $empty, $content->isEmpty() );
-       }
-
-       public function dataEquals( ) {
-               return array(
-                       array( new TextContent( "hallo" ), null, false ),
-                       array( new TextContent( "hallo" ), new TextContent( "hallo" ), true ),
-                       array( new TextContent( "hallo" ), new JavascriptContent( "hallo" ), false ),
-                       array( new TextContent( "hallo" ), new WikitextContent( "hallo" ), false ),
-                       array( new TextContent( "hallo" ), new TextContent( "HALLO" ), false ),
-               );
-       }
-
-       /**
-        * @dataProvider dataEquals
-        */
-       public function testEquals( Content $a, Content $b = null, $equal = false ) {
-               $this->assertEquals( $equal, $a->equals( $b ) );
-       }
-
-       public function dataGetDeletionUpdates() {
-               return array(
-                       array("TextContentTest_testGetSecondaryDataUpdates_1",
-                               CONTENT_MODEL_TEXT, "hello ''world''\n",
-                               array( )
-                       ),
-                       array("TextContentTest_testGetSecondaryDataUpdates_2",
-                               CONTENT_MODEL_TEXT, "hello [[world test 21344]]\n",
-                               array( )
-                       ),
-                       // @todo: more...?
-               );
-       }
-
-       /**
-        * @dataProvider dataGetDeletionUpdates
-        */
-       public function testDeletionUpdates( $title, $model, $text, $expectedStuff ) {
-               $title = Title::newFromText( $title );
-               $title->resetArticleID( 2342 ); //dummy id. fine as long as we don't try to execute the updates!
-
-               $content = ContentHandler::makeContent( $text, $title, $model );
-
-               $updates = $content->getDeletionUpdates( WikiPage::factory( $title ) );
-
-               // make updates accessible by class name
-               foreach ( $updates as $update ) {
-                       $class = get_class( $update );
-                       $updates[ $class ] = $update;
-               }
-
-               if ( !$expectedStuff ) {
-                       $this->assertTrue( true ); // make phpunit happy
-                       return;
-               }
-
-               foreach ( $expectedStuff as $class => $fieldValues ) {
-                       $this->assertArrayHasKey( $class, $updates, "missing an update of type $class" );
-
-                       $update = $updates[ $class ];
-
-                       foreach ( $fieldValues as $field => $value ) {
-                               $v = $update->$field; #if the field doesn't exist, just crash and burn
-                               $this->assertEquals( $value, $v, "unexpected value for field $field in instance of $class" );
-                       }
-               }
-       }
-
-}
index 44fd690..c12fb22 100644 (file)
@@ -12,6 +12,8 @@ class TitleMethodsTest extends MediaWikiTestCase {
        public function setup() {
                global $wgExtraNamespaces, $wgNamespaceContentModels, $wgContLang;
 
+               parent::setUp();
+
                $this->mergeMwGlobalArrayValue(
                        'wgExtraNamespaces',
                        array(
@@ -34,6 +36,8 @@ class TitleMethodsTest extends MediaWikiTestCase {
        public function teardown() {
                global $wgContLang;
 
+               parent::tearDown();
+
                MWNamespace::getCanonicalNamespaces( true ); # reset namespace cache
                $wgContLang->resetNamespaces(); # reset namespace cache
        }
index a788253..8c92f36 100644 (file)
@@ -165,25 +165,26 @@ class UserTest extends MediaWikiTestCase {
 
        /**
         * Test User::editCount
+        * @group medium
         */
        public function testEditCount() {
                $user = User::newFromName( 'UnitTestUser' );
                $user->loadDefaults();
                $user->addToDatabase();
 
-               // let the user have a few (10) edits
+               // let the user have a few (3) edits
                $page = WikiPage::factory( Title::newFromText( 'UserTest_EditCount' ) );
-               for( $i = 0; $i < 10; $i++ ) {
+               for( $i = 0; $i < 3; $i++ ) {
                        $page->doEdit( (string) $i, 'test', 0, false, $user );
                }
 
                $user->clearInstanceCache();
-               $this->assertEquals( 10, $user->getEditCount(), 'After ten edits, the user edit count should be 10' );
+               $this->assertEquals( 3, $user->getEditCount(), 'After three edits, the user edit count should be 3' );
 
                // increase the edit count and clear the cache
                $user->incEditCount();
 
                $user->clearInstanceCache();
-               $this->assertEquals( 11, $user->getEditCount(), 'After increasing the edit count manually, the user edit count should be 11' );
+               $this->assertEquals( 4, $user->getEditCount(), 'After increasing the edit count manually, the user edit count should be 4' );
        }
 }
index e98f5a7..6dc1568 100644 (file)
@@ -579,7 +579,7 @@ class WikiPageTest extends MediaWikiLangTestCase {
        public function testGetParserOutput( $model, $text, $expectedHtml ) {
                $page = $this->createPage( 'WikiPageTest_testGetParserOutput', $text, $model );
 
-               $opt = new ParserOptions();
+               $opt = $page->makeParserOptions( 'canonical' );
                $po = $page->getParserOutput( $opt );
                $text = $po->getText();
 
diff --git a/tests/phpunit/includes/WikitextContentHandlerTest.php b/tests/phpunit/includes/WikitextContentHandlerTest.php
deleted file mode 100644 (file)
index 8aeb529..0000000
+++ /dev/null
@@ -1,199 +0,0 @@
-<?php
-
-/**
- * @group ContentHandler
- */
-class WikitextContentHandlerTest extends MediaWikiTestCase {
-
-       /**
-        * @var ContentHandler
-        */
-       var $handler;
-
-       public function setup() {
-               $this->handler = ContentHandler::getForModelID( CONTENT_MODEL_WIKITEXT );
-       }
-
-       public function teardown() {
-       }
-
-       public function testSerializeContent( ) {
-               $content = new WikitextContent( 'hello world' );
-
-               $this->assertEquals( 'hello world', $this->handler->serializeContent( $content ) );
-               $this->assertEquals( 'hello world', $this->handler->serializeContent( $content, CONTENT_FORMAT_WIKITEXT ) );
-
-               try {
-                       $this->handler->serializeContent( $content, 'dummy/foo' );
-                       $this->fail( "serializeContent() should have failed on unknown format" );
-               } catch ( MWException $e ) {
-                       // ok, as expected
-               }
-       }
-
-       public function testUnserializeContent( ) {
-               $content = $this->handler->unserializeContent( 'hello world' );
-               $this->assertEquals( 'hello world', $content->getNativeData() );
-
-               $content = $this->handler->unserializeContent( 'hello world', CONTENT_FORMAT_WIKITEXT );
-               $this->assertEquals( 'hello world', $content->getNativeData() );
-
-               try {
-                       $this->handler->unserializeContent( 'hello world', 'dummy/foo' );
-                       $this->fail( "unserializeContent() should have failed on unknown format" );
-               } catch ( MWException $e ) {
-                       // ok, as expected
-               }
-       }
-
-       public function testMakeEmptyContent() {
-               $content = $this->handler->makeEmptyContent();
-
-               $this->assertTrue( $content->isEmpty() );
-               $this->assertEquals( '', $content->getNativeData() );
-       }
-
-       public function dataIsSupportedFormat( ) {
-               return array(
-                       array( null, true ),
-                       array( CONTENT_FORMAT_WIKITEXT, true ),
-                       array( 99887766, false ),
-               );
-       }
-
-       /**
-        * @dataProvider dataIsSupportedFormat
-        */
-       public function testIsSupportedFormat( $format, $supported ) {
-               $this->assertEquals( $supported, $this->handler->isSupportedFormat( $format ) );
-       }
-
-       public function dataMerge3( ) {
-               return array(
-                       array( "first paragraph
-
-                                       second paragraph\n",
-
-                                       "FIRST paragraph
-
-                                       second paragraph\n",
-
-                                       "first paragraph
-
-                                       SECOND paragraph\n",
-
-                                       "FIRST paragraph
-
-                                       SECOND paragraph\n",
-                       ),
-
-                       array( "first paragraph
-                                       second paragraph\n",
-
-                                  "Bla bla\n",
-
-                                  "Blubberdibla\n",
-
-                                  false,
-                       ),
-
-               );
-       }
-
-       /**
-        * @dataProvider dataMerge3
-        */
-       public function testMerge3( $old, $mine, $yours, $expected ) {
-               global $wgDiff3;
-
-               if ( !$wgDiff3 ) {
-                       $this->markTestSkipped( "Can't test merge3(), since \$wgDiff3 is not configured" );
-               }
-
-               if ( !file_exists( $wgDiff3 ) ) {
-                       #XXX: this sucks, since it uses arcane internal knowledge about TextContentHandler::merge3 and wfMerge.
-                       $this->markTestSkipped( "Can't test merge3(), since \$wgDiff3 is misconfigured: can't find $wgDiff3" );
-               }
-
-               // test merge
-               $oldContent = new WikitextContent( $old );
-               $myContent = new WikitextContent( $mine );
-               $yourContent = new WikitextContent( $yours );
-
-               $merged = $this->handler->merge3( $oldContent, $myContent, $yourContent );
-
-               $this->assertEquals( $expected, $merged ? $merged->getNativeData() : $merged );
-       }
-
-       public function dataGetAutosummary( ) {
-               return array(
-                       array(
-                               'Hello there, world!',
-                               '#REDIRECT [[Foo]]',
-                               0,
-                               '/^Redirected page .*Foo/'
-                       ),
-
-                       array(
-                               null,
-                               'Hello world!',
-                               EDIT_NEW,
-                               '/^Created page .*Hello/'
-                       ),
-
-                       array(
-                               'Hello there, world!',
-                               '',
-                               0,
-                               '/^Blanked/'
-                       ),
-
-                       array(
-                               'Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut
-                               labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et
-                               ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.',
-                               'Hello world!',
-                               0,
-                               '/^Replaced .*Hello/'
-                       ),
-
-                       array(
-                               'foo',
-                               'bar',
-                               0,
-                               '/^$/'
-                       ),
-               );
-       }
-
-       /**
-        * @dataProvider dataGetAutoSummary
-        */
-       public function testGetAutosummary( $old, $new, $flags, $expected ) {
-               global $wgLanguageCode, $wgContLang;
-
-               $oldContent = is_null( $old ) ? null : new WikitextContent( $old );
-               $newContent = is_null( $new ) ? null : new WikitextContent( $new );
-
-               $summary = $this->handler->getAutosummary( $oldContent, $newContent, $flags );
-
-               $this->assertTrue( (bool)preg_match( $expected, $summary ), "Autosummary didn't match expected pattern $expected: $summary" );
-       }
-
-       /**
-        * @todo Text case requires database, should be done by a test class in the Database group
-        */
-       /*
-       public function testGetAutoDeleteReason( Title $title, &$hasHistory ) {
-       }
-       */
-
-       /**
-        * @todo Text case requires database, should be done by a test class in the Database group
-        */
-       /*
-       public function testGetUndoContent( Revision $current, Revision $undo, Revision $undoafter = null ) {
-       }
-       */
-
-}
diff --git a/tests/phpunit/includes/WikitextContentTest.php b/tests/phpunit/includes/WikitextContentTest.php
deleted file mode 100644 (file)
index c1332a6..0000000
+++ /dev/null
@@ -1,374 +0,0 @@
-<?php
-
-/**
- * @group ContentHandler
- *
- * @group Database
- *        ^--- needed, because we do need the database to test link updates
- */
-class WikitextContentTest extends TextContentTest {
-
-       public function newContent( $text ) {
-               return new WikitextContent( $text );
-       }
-
-       public function dataGetParserOutput() {
-               return array(
-                       array("WikitextContentTest_testGetParserOutput", CONTENT_MODEL_WIKITEXT, "hello ''world''\n", "<p>hello <i>world</i>\n</p>"),
-                       // @todo: more...?
-               );
-       }
-
-       public function dataGetSecondaryDataUpdates() {
-               return array(
-                       array( "WikitextContentTest_testGetSecondaryDataUpdates_1",
-                               CONTENT_MODEL_WIKITEXT, "hello ''world''\n",
-                               array( 'LinksUpdate' => array(  'mRecursive' => true,
-                                                               'mLinks' => array() ) )
-                       ),
-                       array( "WikitextContentTest_testGetSecondaryDataUpdates_2",
-                               CONTENT_MODEL_WIKITEXT, "hello [[world test 21344]]\n",
-                               array( 'LinksUpdate' => array(  'mRecursive' => true,
-                                                               'mLinks' => array( array( 'World_test_21344' => 0 ) ) ) )
-                       ),
-                       // @todo: more...?
-               );
-       }
-
-       /**
-        * @dataProvider dataGetSecondaryDataUpdates
-        * @group Database
-        */
-       public function testGetSecondaryDataUpdates( $title, $model, $text, $expectedStuff ) {
-               $title = Title::newFromText( $title );
-               $title->resetArticleID( 2342 ); //dummy id. fine as long as we don't try to execute the updates!
-
-               $content = ContentHandler::makeContent( $text, $title, $model );
-
-               $updates = $content->getSecondaryDataUpdates( $title );
-
-               // make updates accessible by class name
-               foreach ( $updates as $update ) {
-                       $class = get_class( $update );
-                       $updates[$class] = $update;
-               }
-
-               foreach ( $expectedStuff as $class => $fieldValues ) {
-                       $this->assertArrayHasKey( $class, $updates, "missing an update of type $class" );
-
-                       $update = $updates[$class];
-
-                       foreach ( $fieldValues as $field => $value ) {
-                               $v = $update->$field; #if the field doesn't exist, just crash and burn
-                               $this->assertEquals( $value, $v, "unexpected value for field $field in instance of $class" );
-                       }
-               }
-       }
-
-
-       static $sections =
-
-"Intro
-
-== stuff ==
-hello world
-
-== test ==
-just a test
-
-== foo ==
-more stuff
-";
-
-       public function dataGetSection() {
-               return array(
-                       array( WikitextContentTest::$sections,
-                                       "0",
-                                       "Intro"
-                       ),
-                       array( WikitextContentTest::$sections,
-                                       "2",
-"== test ==
-just a test"
-                       ),
-                       array( WikitextContentTest::$sections,
-                                       "8",
-                                       false
-                       ),
-               );
-       }
-
-       /**
-        * @dataProvider dataGetSection
-        */
-       public function testGetSection( $text, $sectionId, $expectedText ) {
-               $content = $this->newContent( $text );
-
-               $sectionContent = $content->getSection( $sectionId );
-               if ( is_object( $sectionContent ) ) {
-                       $sectionText = $sectionContent->getNativeData();
-               } else {
-                       $sectionText = $sectionContent;
-               }
-
-               $this->assertEquals( $expectedText, $sectionText );
-       }
-
-       public function dataReplaceSection() {
-               return array(
-                       array( WikitextContentTest::$sections,
-                              "0",
-                              "No more",
-                              null,
-                              trim( preg_replace( '/^Intro/sm', 'No more', WikitextContentTest::$sections ) )
-                       ),
-                       array( WikitextContentTest::$sections,
-                              "",
-                              "No more",
-                              null,
-                              "No more"
-                       ),
-                       array( WikitextContentTest::$sections,
-                              "2",
-                              "== TEST ==\nmore fun",
-                              null,
-                              trim( preg_replace( '/^== test ==.*== foo ==/sm', "== TEST ==\nmore fun\n\n== foo ==", WikitextContentTest::$sections ) )
-                       ),
-                       array( WikitextContentTest::$sections,
-                              "8",
-                              "No more",
-                              null,
-                              WikitextContentTest::$sections
-                       ),
-                       array( WikitextContentTest::$sections,
-                              "new",
-                              "No more",
-                              "New",
-                              trim( WikitextContentTest::$sections ) . "\n\n\n== New ==\n\nNo more"
-                       ),
-               );
-       }
-
-       /**
-        * @dataProvider dataReplaceSection
-        */
-       public function testReplaceSection( $text, $section, $with, $sectionTitle, $expected ) {
-               $content = $this->newContent( $text );
-               $c = $content->replaceSection( $section, $this->newContent( $with ), $sectionTitle );
-
-               $this->assertEquals( $expected, is_null( $c ) ? null : $c->getNativeData() );
-       }
-
-       public function testAddSectionHeader( ) {
-               $content = $this->newContent( 'hello world' );
-               $content = $content->addSectionHeader( 'test' );
-
-               $this->assertEquals( "== test ==\n\nhello world", $content->getNativeData() );
-       }
-
-       public function dataPreSaveTransform() {
-               return array(
-                       array( 'hello this is ~~~',
-                              "hello this is [[Special:Contributions/127.0.0.1|127.0.0.1]]",
-                       ),
-                       array( 'hello \'\'this\'\' is <nowiki>~~~</nowiki>',
-                              'hello \'\'this\'\' is <nowiki>~~~</nowiki>',
-                       ),
-                       array( // rtrim
-                               " Foo \n ",
-                               " Foo",
-                       ),
-               );
-       }
-
-       public function dataPreloadTransform() {
-               return array(
-                       array( 'hello this is ~~~',
-                              "hello this is ~~~",
-                       ),
-                       array( 'hello \'\'this\'\' is <noinclude>foo</noinclude><includeonly>bar</includeonly>',
-                              'hello \'\'this\'\' is bar',
-                       ),
-               );
-       }
-
-       public function dataGetRedirectTarget() {
-               return array(
-                       array( '#REDIRECT [[Test]]',
-                              'Test',
-                       ),
-                       array( '#REDIRECT Test',
-                              null,
-                       ),
-                       array( '* #REDIRECT [[Test]]',
-                              null,
-                       ),
-               );
-       }
-
-       public function dataGetTextForSummary() {
-               return array(
-                       array( "hello\nworld.",
-                               16,
-                               'hello world.',
-                       ),
-                       array( 'hello world.',
-                               8,
-                               'hello...',
-                       ),
-                       array( '[[hello world]].',
-                               8,
-                               'hel...',
-                       ),
-               );
-       }
-
-       /**
-        * @todo: test needs database! Should be done by a test class in the Database group.
-        */
-       /*
-       public function getRedirectChain() {
-               $text = $this->getNativeData();
-               return Title::newFromRedirectArray( $text );
-       }
-       */
-
-       /**
-        * @todo: test needs database! Should be done by a test class in the Database group.
-        */
-       /*
-       public function getUltimateRedirectTarget() {
-               $text = $this->getNativeData();
-               return Title::newFromRedirectRecurse( $text );
-       }
-       */
-
-
-       public function dataIsCountable() {
-               return array(
-                       array( '',
-                              null,
-                              'any',
-                              true
-                       ),
-                       array( 'Foo',
-                              null,
-                              'any',
-                              true
-                       ),
-                       array( 'Foo',
-                              null,
-                              'comma',
-                              false
-                       ),
-                       array( 'Foo, bar',
-                              null,
-                              'comma',
-                              true
-                       ),
-                       array( 'Foo',
-                              null,
-                              'link',
-                              false
-                       ),
-                       array( 'Foo [[bar]]',
-                              null,
-                              'link',
-                              true
-                       ),
-                       array( 'Foo',
-                              true,
-                              'link',
-                              true
-                       ),
-                       array( 'Foo [[bar]]',
-                              false,
-                              'link',
-                              false
-                       ),
-                       array( '#REDIRECT [[bar]]',
-                              true,
-                              'any',
-                              false
-                       ),
-                       array( '#REDIRECT [[bar]]',
-                              true,
-                              'comma',
-                              false
-                       ),
-                       array( '#REDIRECT [[bar]]',
-                              true,
-                              'link',
-                              false
-                       ),
-               );
-       }
-
-       public function testMatchMagicWord( ) {
-               $mw = MagicWord::get( "staticredirect" );
-
-               $content = $this->newContent( "#REDIRECT [[FOO]]\n__STATICREDIRECT__" );
-               $this->assertTrue( $content->matchMagicWord( $mw ), "should have matched magic word" );
-
-               $content = $this->newContent( "#REDIRECT [[FOO]]" );
-               $this->assertFalse( $content->matchMagicWord( $mw ), "should not have matched magic word" );
-       }
-
-       public function testUpdateRedirect( ) {
-               $target = Title::newFromText( "testUpdateRedirect_target" );
-
-               // test with non-redirect page
-               $content = $this->newContent( "hello world." );
-               $newContent = $content->updateRedirect( $target );
-
-               $this->assertTrue( $content->equals( $newContent ), "content should be unchanged" );
-
-               // test with actual redirect
-               $content = $this->newContent( "#REDIRECT [[Someplace]]" );
-               $newContent = $content->updateRedirect( $target );
-
-               $this->assertFalse( $content->equals( $newContent ), "content should have changed" );
-               $this->assertTrue( $newContent->isRedirect(), "new content should be a redirect" );
-
-               $this->assertEquals( $target->getFullText(), $newContent->getRedirectTarget()->getFullText() );
-       }
-
-       # =================================================================================================================
-
-       public function testGetModel() {
-               $content = $this->newContent( "hello world." );
-
-               $this->assertEquals( CONTENT_MODEL_WIKITEXT, $content->getModel() );
-       }
-
-       public function testGetContentHandler() {
-               $content = $this->newContent( "hello world." );
-
-               $this->assertEquals( CONTENT_MODEL_WIKITEXT, $content->getContentHandler()->getModelID() );
-       }
-
-       public function dataEquals( ) {
-               return array(
-                       array( new WikitextContent( "hallo" ), null, false ),
-                       array( new WikitextContent( "hallo" ), new WikitextContent( "hallo" ), true ),
-                       array( new WikitextContent( "hallo" ), new JavascriptContent( "hallo" ), false ),
-                       array( new WikitextContent( "hallo" ), new TextContent( "hallo" ), false ),
-                       array( new WikitextContent( "hallo" ), new WikitextContent( "HALLO" ), false ),
-               );
-       }
-
-       public function dataGetDeletionUpdates() {
-               return array(
-                       array("WikitextContentTest_testGetSecondaryDataUpdates_1",
-                               CONTENT_MODEL_WIKITEXT, "hello ''world''\n",
-                               array( 'LinksDeletionUpdate' => array( ) )
-                       ),
-                       array("WikitextContentTest_testGetSecondaryDataUpdates_2",
-                               CONTENT_MODEL_WIKITEXT, "hello [[world test 21344]]\n",
-                               array( 'LinksDeletionUpdate' => array( ) )
-                       ),
-                       // @todo: more...?
-               );
-       }
-
-}
index 75bd922..1b48ad2 100644 (file)
@@ -5,9 +5,11 @@ class XmlSelectTest extends MediaWikiTestCase {
        protected $select;
 
        protected function setUp() {
+               parent::setUp();
                $this->select = new XmlSelect();
        }
        protected function tearDown() {
+               parent::tearDown();
                $this->select = null;
        }
 
index 81b32c2..9a03d5c 100644 (file)
@@ -4,6 +4,7 @@ class ZipDirectoryReaderTest extends MediaWikiTestCase {
        var $zipDir, $entries;
 
        protected function setUp() {
+               parent::setUp();
                $this->zipDir = __DIR__ . '/../data/zip';
        }
 
diff --git a/tests/phpunit/includes/content/ContentHandlerTest.php b/tests/phpunit/includes/content/ContentHandlerTest.php
new file mode 100644 (file)
index 0000000..60baedc
--- /dev/null
@@ -0,0 +1,423 @@
+<?php
+
+/**
+ * @group ContentHandler
+ * @group Database
+ *
+ * @note Declare that we are using the database, because otherwise we'll fail in the "databaseless" test run.
+ * This is because the LinkHolderArray used by the parser needs database access.
+ *
+ */
+class ContentHandlerTest extends MediaWikiTestCase {
+
+       public function setup() {
+               global $wgContLang;
+               parent::setup();
+
+               $this->setMwGlobals( array(
+                       'wgExtraNamespaces' => array(
+                               12312 => 'Dummy',
+                               12313 => 'Dummy_talk',
+                       ),
+                       // The below tests assume that namespaces not mentioned here (Help, User, MediaWiki, ..)
+                       // default to CONTENT_MODEL_WIKITEXT.
+                       'wgNamespaceContentModels' => array(
+                               12312 => 'testing',
+                       ),
+                       'wgContentHandlers' => array(
+                               CONTENT_MODEL_WIKITEXT => 'WikitextContentHandler',
+                               CONTENT_MODEL_JAVASCRIPT => 'JavaScriptContentHandler',
+                               CONTENT_MODEL_CSS => 'CssContentHandler',
+                               CONTENT_MODEL_TEXT => 'TextContentHandler',
+                               'testing' => 'DummyContentHandlerForTesting',
+                       ),
+               ) );
+
+               // Reset namespace cache
+               MWNamespace::getCanonicalNamespaces( true );
+               $wgContLang->resetNamespaces();
+       }
+
+       public function tearDown() {
+               global $wgContLang;
+
+               // Reset namespace cache
+               MWNamespace::getCanonicalNamespaces( true );
+               $wgContLang->resetNamespaces();
+
+               parent::tearDown();
+       }
+
+       public static function dataGetDefaultModelFor() {
+               return array(
+                       array( 'Help:Foo', CONTENT_MODEL_WIKITEXT ),
+                       array( 'Help:Foo.js', CONTENT_MODEL_WIKITEXT ),
+                       array( 'Help:Foo/bar.js', CONTENT_MODEL_WIKITEXT ),
+                       array( 'User:Foo', CONTENT_MODEL_WIKITEXT ),
+                       array( 'User:Foo.js', CONTENT_MODEL_WIKITEXT ),
+                       array( 'User:Foo/bar.js', CONTENT_MODEL_JAVASCRIPT ),
+                       array( 'User:Foo/bar.css', CONTENT_MODEL_CSS ),
+                       array( 'User talk:Foo/bar.css', CONTENT_MODEL_WIKITEXT ),
+                       array( 'User:Foo/bar.js.xxx', CONTENT_MODEL_WIKITEXT ),
+                       array( 'User:Foo/bar.xxx', CONTENT_MODEL_WIKITEXT ),
+                       array( 'MediaWiki:Foo.js', CONTENT_MODEL_JAVASCRIPT ),
+                       array( 'MediaWiki:Foo.css', CONTENT_MODEL_CSS ),
+                       array( 'MediaWiki:Foo.JS', CONTENT_MODEL_WIKITEXT ),
+                       array( 'MediaWiki:Foo.CSS', CONTENT_MODEL_WIKITEXT ),
+                       array( 'MediaWiki:Foo.css.xxx', CONTENT_MODEL_WIKITEXT ),
+               );
+       }
+
+       /**
+        * @dataProvider dataGetDefaultModelFor
+        */
+       public function testGetDefaultModelFor( $title, $expectedModelId ) {
+               $title = Title::newFromText( $title );
+               $this->assertEquals( $expectedModelId, ContentHandler::getDefaultModelFor( $title ) );
+       }
+
+       /**
+        * @dataProvider dataGetDefaultModelFor
+        */
+       public function testGetForTitle( $title, $expectedContentModel ) {
+               $title = Title::newFromText( $title );
+               $handler = ContentHandler::getForTitle( $title );
+               $this->assertEquals( $expectedContentModel, $handler->getModelID() );
+       }
+
+       public static function dataGetLocalizedName() {
+               return array(
+                       array( null, null ),
+                       array( "xyzzy", null ),
+
+                       // XXX: depends on content language
+                       array( CONTENT_MODEL_JAVASCRIPT, '/javascript/i' ),
+               );
+       }
+
+       /**
+        * @dataProvider dataGetLocalizedName
+        */
+       public function testGetLocalizedName( $id, $expected ) {
+               $name = ContentHandler::getLocalizedName( $id );
+
+               if ( $expected ) {
+                       $this->assertNotNull( $name, "no name found for content model $id" );
+                       $this->assertTrue( preg_match( $expected, $name ) > 0 ,
+                               "content model name for #$id did not match pattern $expected"
+                       );
+               } else {
+                       $this->assertEquals( $id, $name, "localization of unknown model $id should have "
+                               . "fallen back to use the model id directly."
+                       );
+               }
+       }
+
+       public static function dataGetPageLanguage() {
+               global $wgLanguageCode;
+
+               return array(
+                       array( "Main", $wgLanguageCode ),
+                       array( "Dummy:Foo", $wgLanguageCode ),
+                       array( "MediaWiki:common.js", 'en' ),
+                       array( "User:Foo/common.js", 'en' ),
+                       array( "MediaWiki:common.css", 'en' ),
+                       array( "User:Foo/common.css", 'en' ),
+                       array( "User:Foo", $wgLanguageCode ),
+
+                       array( CONTENT_MODEL_JAVASCRIPT, 'javascript' ),
+               );
+       }
+
+       /**
+        * @dataProvider dataGetPageLanguage
+        */
+       public function testGetPageLanguage( $title, $expected ) {
+               if ( is_string( $title ) ) {
+                       $title = Title::newFromText( $title );
+               }
+
+               $expected = wfGetLangObj( $expected );
+
+               $handler = ContentHandler::getForTitle( $title );
+               $lang = $handler->getPageLanguage( $title );
+
+               $this->assertEquals( $expected->getCode(), $lang->getCode() );
+       }
+
+       public function testGetContentText_Null( ) {
+               global $wgContentHandlerTextFallback;
+
+               $content = null;
+
+               $wgContentHandlerTextFallback = 'fail';
+               $text = ContentHandler::getContentText( $content );
+               $this->assertEquals( '', $text );
+
+               $wgContentHandlerTextFallback = 'serialize';
+               $text = ContentHandler::getContentText( $content );
+               $this->assertEquals( '', $text );
+
+               $wgContentHandlerTextFallback = 'ignore';
+               $text = ContentHandler::getContentText( $content );
+               $this->assertEquals( '', $text );
+       }
+
+       public function testGetContentText_TextContent( ) {
+               global $wgContentHandlerTextFallback;
+
+               $content = new WikitextContent( "hello world" );
+
+               $wgContentHandlerTextFallback = 'fail';
+               $text = ContentHandler::getContentText( $content );
+               $this->assertEquals( $content->getNativeData(), $text );
+
+               $wgContentHandlerTextFallback = 'serialize';
+               $text = ContentHandler::getContentText( $content );
+               $this->assertEquals( $content->serialize(), $text );
+
+               $wgContentHandlerTextFallback = 'ignore';
+               $text = ContentHandler::getContentText( $content );
+               $this->assertEquals( $content->getNativeData(), $text );
+       }
+
+       public function testGetContentText_NonTextContent( ) {
+               global $wgContentHandlerTextFallback;
+
+               $content = new DummyContentForTesting( "hello world" );
+
+               $wgContentHandlerTextFallback = 'fail';
+
+               try {
+                       $text = ContentHandler::getContentText( $content );
+
+                       $this->fail( "ContentHandler::getContentText should have thrown an exception for non-text Content object" );
+               } catch ( MWException $ex ) {
+                       // as expected
+               }
+
+               $wgContentHandlerTextFallback = 'serialize';
+               $text = ContentHandler::getContentText( $content );
+               $this->assertEquals( $content->serialize(), $text );
+
+               $wgContentHandlerTextFallback = 'ignore';
+               $text = ContentHandler::getContentText( $content );
+               $this->assertNull( $text );
+       }
+
+       /*
+       public static function makeContent( $text, Title $title, $modelId = null, $format = null ) {}
+       */
+
+       public static function dataMakeContent() {
+               return array(
+                       array( 'hallo', 'Help:Test', null, null, CONTENT_MODEL_WIKITEXT, 'hallo', false ),
+                       array( 'hallo', 'MediaWiki:Test.js', null, null, CONTENT_MODEL_JAVASCRIPT, 'hallo', false ),
+                       array( serialize('hallo'), 'Dummy:Test', null, null, "testing", 'hallo', false ),
+
+                       array( 'hallo', 'Help:Test', null, CONTENT_FORMAT_WIKITEXT, CONTENT_MODEL_WIKITEXT, 'hallo', false ),
+                       array( 'hallo', 'MediaWiki:Test.js', null, CONTENT_FORMAT_JAVASCRIPT, CONTENT_MODEL_JAVASCRIPT, 'hallo', false ),
+                       array( serialize('hallo'), 'Dummy:Test', null, "testing", "testing", 'hallo', false ),
+
+                       array( 'hallo', 'Help:Test', CONTENT_MODEL_CSS, null, CONTENT_MODEL_CSS, 'hallo', false ),
+                       array( 'hallo', 'MediaWiki:Test.js', CONTENT_MODEL_CSS, null, CONTENT_MODEL_CSS, 'hallo', false ),
+                       array( serialize('hallo'), 'Dummy:Test', CONTENT_MODEL_CSS, null, CONTENT_MODEL_CSS, serialize('hallo'), false ),
+
+                       array( 'hallo', 'Help:Test', CONTENT_MODEL_WIKITEXT, "testing", null, null, true ),
+                       array( 'hallo', 'MediaWiki:Test.js', CONTENT_MODEL_CSS, "testing", null, null, true ),
+                       array( 'hallo', 'Dummy:Test', CONTENT_MODEL_JAVASCRIPT, "testing", null, null, true ),
+               );
+       }
+
+       /**
+        * @dataProvider dataMakeContent
+        */
+       public function testMakeContent( $data, $title, $modelId, $format, $expectedModelId, $expectedNativeData, $shouldFail ) {
+               global $wgExtraNamespaces, $wgNamespaceContentModels, $wgContentHandlers;
+
+               $title = Title::newFromText( $title );
+
+               try {
+                       $content = ContentHandler::makeContent( $data, $title, $modelId, $format );
+
+                       if ( $shouldFail ) {
+                               $this->fail( "ContentHandler::makeContent should have failed!" );
+                       }
+
+                       $this->assertEquals( $expectedModelId, $content->getModel(), 'bad model id' );
+                       $this->assertEquals( $expectedNativeData, $content->getNativeData(), 'bads native data' );
+               } catch ( MWException $ex ) {
+                       if ( !$shouldFail ) $this->fail( "ContentHandler::makeContent failed unexpectedly: " . $ex->getMessage() );
+                       else $this->assertTrue( true ); // dummy, so we don't get the "test did not perform any assertions" message.
+               }
+
+       }
+
+       /*
+       public function testSupportsSections() {
+               $this->markTestIncomplete( "not yet implemented" );
+       }
+       */
+
+       public function testRunLegacyHooks() {
+               Hooks::register( 'testRunLegacyHooks', __CLASS__ . '::dummyHookHandler' );
+
+               $content = new WikitextContent( 'test text' );
+               $ok = ContentHandler::runLegacyHooks( 'testRunLegacyHooks', array( 'foo', &$content, 'bar' ), false );
+
+               $this->assertTrue( $ok, "runLegacyHooks should have returned true" );
+               $this->assertEquals( "TEST TEXT", $content->getNativeData() );
+       }
+
+       public static function dummyHookHandler( $foo, &$text, $bar ) {
+               if ( $text === null || $text === false ) {
+                       return false;
+               }
+
+               $text = strtoupper( $text );
+
+               return true;
+       }
+}
+
+class DummyContentHandlerForTesting extends ContentHandler {
+
+       public function __construct( $dataModel ) {
+               parent::__construct( $dataModel, array( "testing" ) );
+       }
+
+       /**
+        * Serializes Content object of the type supported by this ContentHandler.
+        *
+        * @param Content $content the Content object to serialize
+        * @param null $format the desired serialization format
+        * @return String serialized form of the content
+        */
+       public function serializeContent( Content $content, $format = null ) {
+          return $content->serialize();
+       }
+
+       /**
+        * Unserializes a Content object of the type supported by this ContentHandler.
+        *
+        * @param $blob String serialized form of the content
+        * @param null $format the format used for serialization
+        * @return Content the Content object created by deserializing $blob
+        */
+       public function unserializeContent( $blob, $format = null ) {
+               $d = unserialize( $blob );
+               return new DummyContentForTesting( $d );
+       }
+
+       /**
+        * Creates an empty Content object of the type supported by this ContentHandler.
+        *
+        */
+       public function makeEmptyContent() {
+               return new DummyContentForTesting( '' );
+       }
+}
+
+class DummyContentForTesting extends AbstractContent {
+
+       public function __construct( $data ) {
+               parent::__construct( "testing" );
+
+               $this->data = $data;
+       }
+
+       public function serialize( $format = null ) {
+               return serialize( $this->data );
+       }
+
+       /**
+        * @return String a string representing the content in a way useful for building a full text search index.
+        *         If no useful representation exists, this method returns an empty string.
+        */
+       public function getTextForSearchIndex() {
+               return '';
+       }
+
+       /**
+        * @return String the wikitext to include when another page includes this  content, or false if the content is not
+        *  includable in a wikitext page.
+        */
+       public function getWikitextForTransclusion() {
+               return false;
+       }
+
+       /**
+        * Returns a textual representation of the content suitable for use in edit summaries and log messages.
+        *
+        * @param int $maxlength Maximum length of the summary text.
+        * @return string The summary text.
+        */
+       public function getTextForSummary( $maxlength = 250 ) {
+               return '';
+       }
+
+       /**
+        * Returns native represenation of the data. Interpretation depends on the data model used,
+        * as given by getDataModel().
+        *
+        * @return mixed the native representation of the content. Could be a string, a nested array
+        *  structure, an object, a binary blob... anything, really.
+        */
+       public function getNativeData()
+       {
+               return $this->data;
+       }
+
+       /**
+        * returns the content's nominal size in bogo-bytes.
+        *
+        * @return int
+        */
+       public function getSize() {
+               return strlen( $this->data );
+       }
+
+       /**
+        * Return a copy of this Content object. The following must be true for the object returned
+        * if $copy = $original->copy()
+        *
+        * * get_class($original) === get_class($copy)
+        * * $original->getModel() === $copy->getModel()
+        * * $original->equals( $copy )
+        *
+        * If and only if the Content object is imutable, the copy() method can and should
+        * return $this. That is,  $copy === $original may be true, but only for imutable content
+        * objects.
+        *
+        * @return Content. A copy of this object.
+        */
+       public function copy() {
+               return $this;
+       }
+
+       /**
+        * Returns true if this content is countable as a "real" wiki page, provided
+        * that it's also in a countable location (e.g. a current revision in the main namespace).
+        *
+        * @param boolean $hasLinks if it is known whether this content contains links, provide this information here,
+        *  to avoid redundant parsing to find out.
+        * @return boolean
+        */
+       public function isCountable( $hasLinks = null ) {
+               return false;
+       }
+
+       /**
+        * @param Title $title
+        * @param null $revId
+        * @param null|ParserOptions $options
+        * @param boolean $generateHtml whether to generate Html (default: true). If false,
+        *  the result of calling getText() on the ParserOutput object returned by
+        *   this method is undefined.
+        *
+        * @return ParserOutput
+        */
+       public function getParserOutput( Title $title, $revId = null, ParserOptions $options = NULL, $generateHtml = true ) {
+               return new ParserOutput( $this->getNativeData() );
+       }
+}
diff --git a/tests/phpunit/includes/content/CssContentTest.php b/tests/phpunit/includes/content/CssContentTest.php
new file mode 100644 (file)
index 0000000..b08a468
--- /dev/null
@@ -0,0 +1,81 @@
+<?php
+
+/**
+ * @group ContentHandler
+ * @group Database
+ *        ^--- needed, because we do need the database to test link updates
+ */
+class CssContentTest extends MediaWikiTestCase {
+
+       protected function setUp() {
+               parent::setUp();
+
+               // Anon user
+               $user = new User();
+               $user->setName( '127.0.0.1' );
+
+               $this->setMwGlobals( array(
+                       'wgUser' => $user,
+                       'wgTextModelsToParse' => array(
+                               CONTENT_MODEL_CSS,
+                       )
+               ) );
+       }
+
+       public function newContent( $text ) {
+               return new CssContent( $text );
+       }
+
+       public static function dataGetParserOutput() {
+               return array(
+                       array(
+                               'MediaWiki:Test.css',
+                               null,
+                               "hello <world>\n",
+                               "<pre class=\"mw-code mw-css\" dir=\"ltr\">\nhello &lt;world&gt;\n\n</pre>"
+                       ),
+                       array(
+                               'MediaWiki:Test.css',
+                               null,
+                               "/* hello [[world]] */\n",
+                               "<pre class=\"mw-code mw-css\" dir=\"ltr\">\n/* hello [[world]] */\n\n</pre>",
+                               array(
+                                       'Links' => array(
+                                               array( 'World' => 0 )
+                                       )
+                               )
+                       ),
+
+                       // TODO: more...?
+               );
+       }
+
+       public function testGetModel() {
+               $content = $this->newContent( 'hello world.' );
+
+               $this->assertEquals( CONTENT_MODEL_CSS, $content->getModel() );
+       }
+
+       public function testGetContentHandler() {
+               $content = $this->newContent( 'hello world.' );
+
+               $this->assertEquals( CONTENT_MODEL_CSS, $content->getContentHandler()->getModelID() );
+       }
+
+       public static function dataEquals( ) {
+               return array(
+                       array( new CssContent( 'hallo' ), null, false ),
+                       array( new CssContent( 'hallo' ), new CssContent( 'hallo' ), true ),
+                       array( new CssContent( 'hallo' ), new WikitextContent( 'hallo' ), false ),
+                       array( new CssContent( 'hallo' ), new CssContent( 'HALLO' ), false ),
+               );
+       }
+
+       /**
+        * @dataProvider dataEquals
+        */
+       public function testEquals( Content $a, Content $b = null, $equal = false ) {
+               $this->assertEquals( $equal, $a->equals( $b ) );
+       }
+
+}
diff --git a/tests/phpunit/includes/content/JavascriptContentTest.php b/tests/phpunit/includes/content/JavascriptContentTest.php
new file mode 100644 (file)
index 0000000..e08252c
--- /dev/null
@@ -0,0 +1,273 @@
+<?php
+
+/**
+ * @group ContentHandler
+ * @group Database
+ *        ^--- needed, because we do need the database to test link updates
+ */
+class JavascriptContentTest extends TextContentTest {
+
+       public function newContent( $text ) {
+               return new JavascriptContent( $text );
+       }
+
+       public static function dataGetParserOutput() {
+               return array(
+                       array(
+                               'MediaWiki:Test.js',
+                               null,
+                               "hello <world>\n",
+                               "<pre class=\"mw-code mw-js\" dir=\"ltr\">\nhello &lt;world&gt;\n\n</pre>"
+                       ),
+                       array(
+                               'MediaWiki:Test.js',
+                               null,
+                               "hello(); // [[world]]\n",
+                               "<pre class=\"mw-code mw-js\" dir=\"ltr\">\nhello(); // [[world]]\n\n</pre>",
+                               array(
+                                       'Links' => array(
+                                               array( 'World' => 0 )
+                                       )
+                               )
+                       ),
+
+                       // TODO: more...?
+               );
+       }
+
+       // XXX: Unused function
+       public static function dataGetSection() {
+               return array(
+                       array( WikitextContentTest::$sections,
+                              '0',
+                              null
+                       ),
+                       array( WikitextContentTest::$sections,
+                              '2',
+                              null
+                       ),
+                       array( WikitextContentTest::$sections,
+                              '8',
+                              null
+                       ),
+               );
+       }
+
+       // XXX: Unused function
+       public static function dataReplaceSection() {
+               return array(
+                       array( WikitextContentTest::$sections,
+                              '0',
+                              'No more',
+                              null,
+                              null
+                       ),
+                       array( WikitextContentTest::$sections,
+                              '',
+                              'No more',
+                              null,
+                              null
+                       ),
+                       array( WikitextContentTest::$sections,
+                              '2',
+                              "== TEST ==\nmore fun",
+                              null,
+                              null
+                       ),
+                       array( WikitextContentTest::$sections,
+                              '8',
+                              'No more',
+                              null,
+                              null
+                       ),
+                       array( WikitextContentTest::$sections,
+                              'new',
+                              'No more',
+                              'New',
+                              null
+                       ),
+               );
+       }
+
+       public function testAddSectionHeader( ) {
+               $content = $this->newContent( 'hello world' );
+               $c = $content->addSectionHeader( 'test' );
+
+               $this->assertTrue( $content->equals( $c ) );
+       }
+
+       // XXX: currently, preSaveTransform is applied to scripts. this may change or become optional.
+       public static function dataPreSaveTransform() {
+               return array(
+                       array( 'hello this is ~~~',
+                               "hello this is [[Special:Contributions/127.0.0.1|127.0.0.1]]",
+                       ),
+                       array( 'hello \'\'this\'\' is <nowiki>~~~</nowiki>',
+                               'hello \'\'this\'\' is <nowiki>~~~</nowiki>',
+                       ),
+                       array( " Foo \n ",
+                               " Foo",
+                       ),
+               );
+       }
+
+       public static function dataPreloadTransform() {
+               return array(
+                       array( 'hello this is ~~~',
+                              'hello this is ~~~',
+                       ),
+                       array( 'hello \'\'this\'\' is <noinclude>foo</noinclude><includeonly>bar</includeonly>',
+                              'hello \'\'this\'\' is <noinclude>foo</noinclude><includeonly>bar</includeonly>',
+                       ),
+               );
+       }
+
+       public static function dataGetRedirectTarget() {
+               return array(
+                       array( '#REDIRECT [[Test]]',
+                              null,
+                       ),
+                       array( '#REDIRECT Test',
+                              null,
+                       ),
+                       array( '* #REDIRECT [[Test]]',
+                              null,
+                       ),
+               );
+       }
+
+       /**
+        * @todo: test needs database!
+        */
+       /*
+       public function getRedirectChain() {
+               $text = $this->getNativeData();
+               return Title::newFromRedirectArray( $text );
+       }
+       */
+
+       /**
+        * @todo: test needs database!
+        */
+       /*
+       public function getUltimateRedirectTarget() {
+               $text = $this->getNativeData();
+               return Title::newFromRedirectRecurse( $text );
+       }
+       */
+
+       public static function dataIsCountable() {
+               return array(
+                       array( '',
+                              null,
+                              'any',
+                              true
+                       ),
+                       array( 'Foo',
+                              null,
+                              'any',
+                              true
+                       ),
+                       array( 'Foo',
+                              null,
+                              'comma',
+                              false
+                       ),
+                       array( 'Foo, bar',
+                              null,
+                              'comma',
+                              false
+                       ),
+                       array( 'Foo',
+                              null,
+                              'link',
+                              false
+                       ),
+                       array( 'Foo [[bar]]',
+                              null,
+                              'link',
+                              false
+                       ),
+                       array( 'Foo',
+                              true,
+                              'link',
+                              false
+                       ),
+                       array( 'Foo [[bar]]',
+                              false,
+                              'link',
+                              false
+                       ),
+                       array( '#REDIRECT [[bar]]',
+                              true,
+                              'any',
+                              true
+                       ),
+                       array( '#REDIRECT [[bar]]',
+                              true,
+                              'comma',
+                              false
+                       ),
+                       array( '#REDIRECT [[bar]]',
+                              true,
+                              'link',
+                              false
+                       ),
+               );
+       }
+
+       public static function dataGetTextForSummary() {
+               return array(
+                       array( "hello\nworld.",
+                              16,
+                              'hello world.',
+                       ),
+                       array( 'hello world.',
+                              8,
+                              'hello...',
+                       ),
+                       array( '[[hello world]].',
+                              8,
+                              '[[hel...',
+                       ),
+               );
+       }
+
+       public function testMatchMagicWord( ) {
+               $mw = MagicWord::get( "staticredirect" );
+
+               $content = $this->newContent( "#REDIRECT [[FOO]]\n__STATICREDIRECT__" );
+               $this->assertFalse( $content->matchMagicWord( $mw ), "should not have matched magic word, since it's not wikitext" );
+       }
+
+       public function testUpdateRedirect( ) {
+               $target = Title::newFromText( "testUpdateRedirect_target" );
+
+               $content = $this->newContent( "#REDIRECT [[Someplace]]" );
+               $newContent = $content->updateRedirect( $target );
+
+               $this->assertTrue( $content->equals( $newContent ), "content should be unchanged since it's not wikitext" );
+       }
+
+       public function testGetModel() {
+               $content = $this->newContent( "hello world." );
+
+               $this->assertEquals( CONTENT_MODEL_JAVASCRIPT, $content->getModel() );
+       }
+
+       public function testGetContentHandler() {
+               $content = $this->newContent( "hello world." );
+
+               $this->assertEquals( CONTENT_MODEL_JAVASCRIPT, $content->getContentHandler()->getModelID() );
+       }
+
+       public static function dataEquals( ) {
+               return array(
+                       array( new JavascriptContent( "hallo" ), null, false ),
+                       array( new JavascriptContent( "hallo" ), new JavascriptContent( "hallo" ), true ),
+                       array( new JavascriptContent( "hallo" ), new CssContent( "hallo" ), false ),
+                       array( new JavascriptContent( "hallo" ), new JavascriptContent( "HALLO" ), false ),
+               );
+       }
+
+}
diff --git a/tests/phpunit/includes/content/TextContentTest.php b/tests/phpunit/includes/content/TextContentTest.php
new file mode 100644 (file)
index 0000000..c867a83
--- /dev/null
@@ -0,0 +1,381 @@
+<?php
+
+/**
+ * @group ContentHandler
+ * @group Database
+ *        ^--- needed, because we do need the database to test link updates
+ */
+class TextContentTest extends MediaWikiTestCase {
+       protected $context;
+
+       protected function setUp() {
+               parent::setUp();
+
+               // Anon user
+               $user = new User();
+               $user->setName( '127.0.0.1' );
+
+               $this->setMwGlobals( array(
+                       'wgUser' => $user,
+                       'wgTextModelsToParse' => array(
+                               CONTENT_MODEL_WIKITEXT,
+                               CONTENT_MODEL_CSS,
+                               CONTENT_MODEL_JAVASCRIPT,
+                       )
+               ) );
+
+               $this->context = new RequestContext( new FauxRequest() );
+               $this->context->setTitle( Title::newFromText( 'Test' ) );
+               $this->context->setUser( $user );
+       }
+
+       public function newContent( $text ) {
+               return new TextContent( $text );
+       }
+
+       public static function dataGetParserOutput() {
+               return array(
+                       array(
+                               'TextContentTest_testGetParserOutput',
+                               CONTENT_MODEL_TEXT,
+                               "hello ''world'' & [[stuff]]\n", "hello ''world'' &amp; [[stuff]]",
+                               array(
+                                       'Links' => array()
+                               )
+                       ),
+                       // TODO: more...?
+               );
+       }
+
+       /**
+        * @dataProvider dataGetParserOutput
+        */
+       public function testGetParserOutput( $title, $model, $text, $expectedHtml, $expectedFields = null ) {
+               $title = Title::newFromText( $title );
+               $content = ContentHandler::makeContent( $text, $title, $model );
+
+               $po = $content->getParserOutput( $title );
+
+               $html = $po->getText();
+               $html = preg_replace( '#<!--.*?-->#sm', '', $html ); // strip comments
+
+               $this->assertEquals( $expectedHtml, trim( $html ) );
+
+               if ( $expectedFields ) {
+                       foreach ( $expectedFields as $field => $exp ) {
+                               $f = 'get' . ucfirst( $field );
+                               $v = call_user_func( array( $po, $f ) );
+
+                               if ( is_array( $exp ) ) {
+                                       $this->assertArrayEquals( $exp, $v );
+                               } else {
+                                       $this->assertEquals( $exp, $v );
+                               }
+                       }
+               }
+
+               // TODO: assert more properties
+       }
+
+       public static function dataPreSaveTransform() {
+               return array(
+                       array(
+                               #0: no signature resolution
+                               'hello this is ~~~',
+                               'hello this is ~~~',
+                       ),
+                       array(
+                               #1: rtrim
+                               " Foo \n ",
+                               ' Foo',
+                       ),
+               );
+       }
+
+       /**
+        * @dataProvider dataPreSaveTransform
+        */
+       public function testPreSaveTransform( $text, $expected ) {
+               global $wgContLang;
+
+               $options = ParserOptions::newFromUserAndLang( $this->context->getUser(), $wgContLang );
+
+               $content = $this->newContent( $text );
+               $content = $content->preSaveTransform( $this->context->getTitle(), $this->context->getUser(), $options );
+
+               $this->assertEquals( $expected, $content->getNativeData() );
+       }
+
+       public static function dataPreloadTransform() {
+               return array(
+                       array(
+                               'hello this is ~~~',
+                               'hello this is ~~~',
+                       ),
+               );
+       }
+
+       /**
+        * @dataProvider dataPreloadTransform
+        */
+       public function testPreloadTransform( $text, $expected ) {
+               global $wgContLang;
+               $options = ParserOptions::newFromUserAndLang( $this->context->getUser(), $wgContLang );
+
+               $content = $this->newContent( $text );
+               $content = $content->preloadTransform( $this->context->getTitle(), $options );
+
+               $this->assertEquals( $expected, $content->getNativeData() );
+       }
+
+       public static function dataGetRedirectTarget() {
+               return array(
+                       array( '#REDIRECT [[Test]]',
+                               null,
+                       ),
+               );
+       }
+
+       /**
+        * @dataProvider dataGetRedirectTarget
+        */
+       public function testGetRedirectTarget( $text, $expected ) {
+               $content = $this->newContent( $text );
+               $t = $content->getRedirectTarget( );
+
+               if ( is_null( $expected ) ) {
+                       $this->assertNull( $t, "text should not have generated a redirect target: $text" );
+               } else {
+                       $this->assertEquals( $expected, $t->getPrefixedText() );
+               }
+       }
+
+       /**
+        * @dataProvider dataGetRedirectTarget
+        */
+       public function testIsRedirect( $text, $expected ) {
+               $content = $this->newContent( $text );
+
+               $this->assertEquals( !is_null($expected), $content->isRedirect() );
+       }
+
+       /**
+        * @todo: test needs database! Should be done by a test class in the Database group.
+        */
+       /*
+       public function getRedirectChain() {
+               $text = $this->getNativeData();
+               return Title::newFromRedirectArray( $text );
+       }
+       */
+
+       /**
+        * @todo: test needs database! Should be done by a test class in the Database group.
+        */
+       /*
+       public function getUltimateRedirectTarget() {
+               $text = $this->getNativeData();
+               return Title::newFromRedirectRecurse( $text );
+       }
+       */
+
+       public static function dataIsCountable() {
+               return array(
+                       array( '',
+                              null,
+                              'any',
+                              true
+                       ),
+                       array( 'Foo',
+                              null,
+                              'any',
+                              true
+                       ),
+                       array( 'Foo',
+                              null,
+                              'comma',
+                              false
+                       ),
+                       array( 'Foo, bar',
+                              null,
+                              'comma',
+                              false
+                       ),
+               );
+       }
+
+
+       /**
+        * @dataProvider dataIsCountable
+        * @group Database
+        */
+       public function testIsCountable( $text, $hasLinks, $mode, $expected ) {
+               global $wgArticleCountMethod;
+
+               $old = $wgArticleCountMethod;
+               $wgArticleCountMethod = $mode;
+
+               $content = $this->newContent( $text );
+
+               $v = $content->isCountable( $hasLinks, $this->context->getTitle() );
+               $wgArticleCountMethod = $old;
+
+               $this->assertEquals( $expected, $v, 'isCountable() returned unexpected value ' . var_export( $v, true )
+                                                   . ' instead of ' . var_export( $expected, true ) . " in mode `$mode` for text \"$text\"" );
+       }
+
+       public static function dataGetTextForSummary() {
+               return array(
+                       array( "hello\nworld.",
+                              16,
+                              'hello world.',
+                       ),
+                       array( 'hello world.',
+                              8,
+                              'hello...',
+                       ),
+                       array( '[[hello world]].',
+                              8,
+                              '[[hel...',
+                       ),
+               );
+       }
+
+       /**
+        * @dataProvider dataGetTextForSummary
+        */
+       public function testGetTextForSummary( $text, $maxlength, $expected ) {
+               $content = $this->newContent( $text );
+
+               $this->assertEquals( $expected, $content->getTextForSummary( $maxlength ) );
+       }
+
+
+       public function testGetTextForSearchIndex( ) {
+               $content = $this->newContent( 'hello world.' );
+
+               $this->assertEquals( 'hello world.', $content->getTextForSearchIndex() );
+       }
+
+       public function testCopy() {
+               $content = $this->newContent( 'hello world.' );
+               $copy = $content->copy();
+
+               $this->assertTrue( $content->equals( $copy ), 'copy must be equal to original' );
+               $this->assertEquals( 'hello world.', $copy->getNativeData() );
+       }
+
+       public function testGetSize( ) {
+               $content = $this->newContent( 'hello world.' );
+
+               $this->assertEquals( 12, $content->getSize() );
+       }
+
+       public function testGetNativeData( ) {
+               $content = $this->newContent( 'hello world.' );
+
+               $this->assertEquals( 'hello world.', $content->getNativeData() );
+       }
+
+       public function testGetWikitextForTransclusion( ) {
+               $content = $this->newContent( 'hello world.' );
+
+               $this->assertEquals( 'hello world.', $content->getWikitextForTransclusion() );
+       }
+
+       public function testGetModel() {
+               $content = $this->newContent( "hello world." );
+
+               $this->assertEquals( CONTENT_MODEL_TEXT, $content->getModel() );
+       }
+
+       public function testGetContentHandler() {
+               $content = $this->newContent( "hello world." );
+
+               $this->assertEquals( CONTENT_MODEL_TEXT, $content->getContentHandler()->getModelID() );
+       }
+
+       public static function dataIsEmpty( ) {
+               return array(
+                       array( '', true ),
+                       array( '  ', false ),
+                       array( '0', false ),
+                       array( 'hallo welt.', false ),
+               );
+       }
+
+       /**
+        * @dataProvider dataIsEmpty
+        */
+       public function testIsEmpty( $text, $empty ) {
+               $content = $this->newContent( $text );
+
+               $this->assertEquals( $empty, $content->isEmpty() );
+       }
+
+       public static function dataEquals( ) {
+               return array(
+                       array( new TextContent( "hallo" ), null, false ),
+                       array( new TextContent( "hallo" ), new TextContent( "hallo" ), true ),
+                       array( new TextContent( "hallo" ), new JavascriptContent( "hallo" ), false ),
+                       array( new TextContent( "hallo" ), new WikitextContent( "hallo" ), false ),
+                       array( new TextContent( "hallo" ), new TextContent( "HALLO" ), false ),
+               );
+       }
+
+       /**
+        * @dataProvider dataEquals
+        */
+       public function testEquals( Content $a, Content $b = null, $equal = false ) {
+               $this->assertEquals( $equal, $a->equals( $b ) );
+       }
+
+       public static function dataGetDeletionUpdates() {
+               return array(
+                       array("TextContentTest_testGetSecondaryDataUpdates_1",
+                               CONTENT_MODEL_TEXT, "hello ''world''\n",
+                               array( )
+                       ),
+                       array("TextContentTest_testGetSecondaryDataUpdates_2",
+                               CONTENT_MODEL_TEXT, "hello [[world test 21344]]\n",
+                               array( )
+                       ),
+                       // TODO: more...?
+               );
+       }
+
+       /**
+        * @dataProvider dataGetDeletionUpdates
+        */
+       public function testDeletionUpdates( $title, $model, $text, $expectedStuff ) {
+               $title = Title::newFromText( $title );
+               $title->resetArticleID( 2342 ); //dummy id. fine as long as we don't try to execute the updates!
+
+               $content = ContentHandler::makeContent( $text, $title, $model );
+
+               $updates = $content->getDeletionUpdates( WikiPage::factory( $title ) );
+
+               // make updates accessible by class name
+               foreach ( $updates as $update ) {
+                       $class = get_class( $update );
+                       $updates[ $class ] = $update;
+               }
+
+               if ( !$expectedStuff ) {
+                       $this->assertTrue( true ); // make phpunit happy
+                       return;
+               }
+
+               foreach ( $expectedStuff as $class => $fieldValues ) {
+                       $this->assertArrayHasKey( $class, $updates, "missing an update of type $class" );
+
+                       $update = $updates[ $class ];
+
+                       foreach ( $fieldValues as $field => $value ) {
+                               $v = $update->$field; #if the field doesn't exist, just crash and burn
+                               $this->assertEquals( $value, $v, "unexpected value for field $field in instance of $class" );
+                       }
+               }
+       }
+
+}
diff --git a/tests/phpunit/includes/content/WikitextContentHandlerTest.php b/tests/phpunit/includes/content/WikitextContentHandlerTest.php
new file mode 100644 (file)
index 0000000..1ba85a9
--- /dev/null
@@ -0,0 +1,196 @@
+<?php
+
+/**
+ * @group ContentHandler
+ */
+class WikitextContentHandlerTest extends MediaWikiTestCase {
+
+       /**
+        * @var ContentHandler
+        */
+       var $handler;
+
+       public function setUp() {
+               parent::setUp();
+
+               $this->handler = ContentHandler::getForModelID( CONTENT_MODEL_WIKITEXT );
+       }
+
+       public function testSerializeContent( ) {
+               $content = new WikitextContent( 'hello world' );
+
+               $this->assertEquals( 'hello world', $this->handler->serializeContent( $content ) );
+               $this->assertEquals( 'hello world', $this->handler->serializeContent( $content, CONTENT_FORMAT_WIKITEXT ) );
+
+               try {
+                       $this->handler->serializeContent( $content, 'dummy/foo' );
+                       $this->fail( "serializeContent() should have failed on unknown format" );
+               } catch ( MWException $e ) {
+                       // ok, as expected
+               }
+       }
+
+       public function testUnserializeContent( ) {
+               $content = $this->handler->unserializeContent( 'hello world' );
+               $this->assertEquals( 'hello world', $content->getNativeData() );
+
+               $content = $this->handler->unserializeContent( 'hello world', CONTENT_FORMAT_WIKITEXT );
+               $this->assertEquals( 'hello world', $content->getNativeData() );
+
+               try {
+                       $this->handler->unserializeContent( 'hello world', 'dummy/foo' );
+                       $this->fail( "unserializeContent() should have failed on unknown format" );
+               } catch ( MWException $e ) {
+                       // ok, as expected
+               }
+       }
+
+       public function testMakeEmptyContent() {
+               $content = $this->handler->makeEmptyContent();
+
+               $this->assertTrue( $content->isEmpty() );
+               $this->assertEquals( '', $content->getNativeData() );
+       }
+
+       public static function dataIsSupportedFormat( ) {
+               return array(
+                       array( null, true ),
+                       array( CONTENT_FORMAT_WIKITEXT, true ),
+                       array( 99887766, false ),
+               );
+       }
+
+       /**
+        * @dataProvider dataIsSupportedFormat
+        */
+       public function testIsSupportedFormat( $format, $supported ) {
+               $this->assertEquals( $supported, $this->handler->isSupportedFormat( $format ) );
+       }
+
+       public static function dataMerge3( ) {
+               return array(
+                       array( "first paragraph
+
+                                       second paragraph\n",
+
+                                       "FIRST paragraph
+
+                                       second paragraph\n",
+
+                                       "first paragraph
+
+                                       SECOND paragraph\n",
+
+                                       "FIRST paragraph
+
+                                       SECOND paragraph\n",
+                       ),
+
+                       array( "first paragraph
+                                       second paragraph\n",
+
+                                  "Bla bla\n",
+
+                                  "Blubberdibla\n",
+
+                                  false,
+                       ),
+
+               );
+       }
+
+       /**
+        * @dataProvider dataMerge3
+        */
+       public function testMerge3( $old, $mine, $yours, $expected ) {
+               global $wgDiff3;
+
+               if ( !$wgDiff3 ) {
+                       $this->markTestSkipped( "Can't test merge3(), since \$wgDiff3 is not configured" );
+               }
+
+               if ( !file_exists( $wgDiff3 ) ) {
+                       #XXX: this sucks, since it uses arcane internal knowledge about TextContentHandler::merge3 and wfMerge.
+                       $this->markTestSkipped( "Can't test merge3(), since \$wgDiff3 is misconfigured: can't find $wgDiff3" );
+               }
+
+               // test merge
+               $oldContent = new WikitextContent( $old );
+               $myContent = new WikitextContent( $mine );
+               $yourContent = new WikitextContent( $yours );
+
+               $merged = $this->handler->merge3( $oldContent, $myContent, $yourContent );
+
+               $this->assertEquals( $expected, $merged ? $merged->getNativeData() : $merged );
+       }
+
+       public static function dataGetAutosummary( ) {
+               return array(
+                       array(
+                               'Hello there, world!',
+                               '#REDIRECT [[Foo]]',
+                               0,
+                               '/^Redirected page .*Foo/'
+                       ),
+
+                       array(
+                               null,
+                               'Hello world!',
+                               EDIT_NEW,
+                               '/^Created page .*Hello/'
+                       ),
+
+                       array(
+                               'Hello there, world!',
+                               '',
+                               0,
+                               '/^Blanked/'
+                       ),
+
+                       array(
+                               'Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut
+                               labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et
+                               ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.',
+                               'Hello world!',
+                               0,
+                               '/^Replaced .*Hello/'
+                       ),
+
+                       array(
+                               'foo',
+                               'bar',
+                               0,
+                               '/^$/'
+                       ),
+               );
+       }
+
+       /**
+        * @dataProvider dataGetAutosummary
+        */
+       public function testGetAutosummary( $old, $new, $flags, $expected ) {
+               global $wgLanguageCode, $wgContLang;
+
+               $oldContent = is_null( $old ) ? null : new WikitextContent( $old );
+               $newContent = is_null( $new ) ? null : new WikitextContent( $new );
+
+               $summary = $this->handler->getAutosummary( $oldContent, $newContent, $flags );
+
+               $this->assertTrue( (bool)preg_match( $expected, $summary ), "Autosummary didn't match expected pattern $expected: $summary" );
+       }
+
+       /**
+        * @todo Text case requires database, should be done by a test class in the Database group
+        */
+       /*
+       public function testGetAutoDeleteReason( Title $title, &$hasHistory ) {}
+       */
+
+       /**
+        * @todo Text case requires database, should be done by a test class in the Database group
+        */
+       /*
+       public function testGetUndoContent( Revision $current, Revision $undo, Revision $undoafter = null ) {}
+       */
+
+}
diff --git a/tests/phpunit/includes/content/WikitextContentTest.php b/tests/phpunit/includes/content/WikitextContentTest.php
new file mode 100644 (file)
index 0000000..ceb6d48
--- /dev/null
@@ -0,0 +1,385 @@
+<?php
+
+/**
+ * @group ContentHandler
+ *
+ * @group Database
+ *        ^--- needed, because we do need the database to test link updates
+ */
+class WikitextContentTest extends TextContentTest {
+
+       static $sections =
+
+"Intro
+
+== stuff ==
+hello world
+
+== test ==
+just a test
+
+== foo ==
+more stuff
+";
+
+       public function newContent( $text ) {
+               return new WikitextContent( $text );
+       }
+
+       public static function dataGetParserOutput() {
+               return array(
+                       array(
+                               "WikitextContentTest_testGetParserOutput",
+                               CONTENT_MODEL_WIKITEXT,
+                               "hello ''world''\n",
+                               "<p>hello <i>world</i>\n</p>"
+                       ),
+                       // TODO: more...?
+               );
+       }
+
+       public static function dataGetSecondaryDataUpdates() {
+               return array(
+                       array( "WikitextContentTest_testGetSecondaryDataUpdates_1",
+                               CONTENT_MODEL_WIKITEXT, "hello ''world''\n",
+                               array(
+                                       'LinksUpdate' => array(
+                                               'mRecursive' => true,
+                                               'mLinks' => array()
+                                       )
+                               )
+                       ),
+                       array( "WikitextContentTest_testGetSecondaryDataUpdates_2",
+                               CONTENT_MODEL_WIKITEXT, "hello [[world test 21344]]\n",
+                               array(
+                                       'LinksUpdate' => array(
+                                               'mRecursive' => true,
+                                               'mLinks' => array(
+                                                       array( 'World_test_21344' => 0 )
+                                               )
+                                       )
+                               )
+                       ),
+                       // TODO: more...?
+               );
+       }
+
+       /**
+        * @dataProvider dataGetSecondaryDataUpdates
+        * @group Database
+        */
+       public function testGetSecondaryDataUpdates( $title, $model, $text, $expectedStuff ) {
+               $title = Title::newFromText( $title );
+               $title->resetArticleID( 2342 ); //dummy id. fine as long as we don't try to execute the updates!
+
+               $content = ContentHandler::makeContent( $text, $title, $model );
+
+               $updates = $content->getSecondaryDataUpdates( $title );
+
+               // make updates accessible by class name
+               foreach ( $updates as $update ) {
+                       $class = get_class( $update );
+                       $updates[$class] = $update;
+               }
+
+               foreach ( $expectedStuff as $class => $fieldValues ) {
+                       $this->assertArrayHasKey( $class, $updates, "missing an update of type $class" );
+
+                       $update = $updates[$class];
+
+                       foreach ( $fieldValues as $field => $value ) {
+                               $v = $update->$field; #if the field doesn't exist, just crash and burn
+                               $this->assertEquals( $value, $v, "unexpected value for field $field in instance of $class" );
+                       }
+               }
+       }
+
+       public static function dataGetSection() {
+               return array(
+                       array( WikitextContentTest::$sections,
+                                       "0",
+                                       "Intro"
+                       ),
+                       array( WikitextContentTest::$sections,
+                                       "2",
+"== test ==
+just a test"
+                       ),
+                       array( WikitextContentTest::$sections,
+                                       "8",
+                                       false
+                       ),
+               );
+       }
+
+       /**
+        * @dataProvider dataGetSection
+        */
+       public function testGetSection( $text, $sectionId, $expectedText ) {
+               $content = $this->newContent( $text );
+
+               $sectionContent = $content->getSection( $sectionId );
+               if ( is_object( $sectionContent ) ) {
+                       $sectionText = $sectionContent->getNativeData();
+               } else {
+                       $sectionText = $sectionContent;
+               }
+
+               $this->assertEquals( $expectedText, $sectionText );
+       }
+
+       public static function dataReplaceSection() {
+               return array(
+                       array( WikitextContentTest::$sections,
+                              "0",
+                              "No more",
+                              null,
+                              trim( preg_replace( '/^Intro/sm', 'No more', WikitextContentTest::$sections ) )
+                       ),
+                       array( WikitextContentTest::$sections,
+                              "",
+                              "No more",
+                              null,
+                              "No more"
+                       ),
+                       array( WikitextContentTest::$sections,
+                              "2",
+                              "== TEST ==\nmore fun",
+                              null,
+                              trim( preg_replace( '/^== test ==.*== foo ==/sm', "== TEST ==\nmore fun\n\n== foo ==", WikitextContentTest::$sections ) )
+                       ),
+                       array( WikitextContentTest::$sections,
+                              "8",
+                              "No more",
+                              null,
+                              WikitextContentTest::$sections
+                       ),
+                       array( WikitextContentTest::$sections,
+                              "new",
+                              "No more",
+                              "New",
+                              trim( WikitextContentTest::$sections ) . "\n\n\n== New ==\n\nNo more"
+                       ),
+               );
+       }
+
+       /**
+        * @dataProvider dataReplaceSection
+        */
+       public function testReplaceSection( $text, $section, $with, $sectionTitle, $expected ) {
+               $content = $this->newContent( $text );
+               $c = $content->replaceSection( $section, $this->newContent( $with ), $sectionTitle );
+
+               $this->assertEquals( $expected, is_null( $c ) ? null : $c->getNativeData() );
+       }
+
+       public function testAddSectionHeader( ) {
+               $content = $this->newContent( 'hello world' );
+               $content = $content->addSectionHeader( 'test' );
+
+               $this->assertEquals( "== test ==\n\nhello world", $content->getNativeData() );
+       }
+
+       public static function dataPreSaveTransform() {
+               return array(
+                       array( 'hello this is ~~~',
+                              "hello this is [[Special:Contributions/127.0.0.1|127.0.0.1]]",
+                       ),
+                       array( 'hello \'\'this\'\' is <nowiki>~~~</nowiki>',
+                              'hello \'\'this\'\' is <nowiki>~~~</nowiki>',
+                       ),
+                       array( // rtrim
+                               " Foo \n ",
+                               " Foo",
+                       ),
+               );
+       }
+
+       public static function dataPreloadTransform() {
+               return array(
+                       array( 'hello this is ~~~',
+                              "hello this is ~~~",
+                       ),
+                       array( 'hello \'\'this\'\' is <noinclude>foo</noinclude><includeonly>bar</includeonly>',
+                              'hello \'\'this\'\' is bar',
+                       ),
+               );
+       }
+
+       public static function dataGetRedirectTarget() {
+               return array(
+                       array( '#REDIRECT [[Test]]',
+                              'Test',
+                       ),
+                       array( '#REDIRECT Test',
+                              null,
+                       ),
+                       array( '* #REDIRECT [[Test]]',
+                              null,
+                       ),
+               );
+       }
+
+       public static function dataGetTextForSummary() {
+               return array(
+                       array( "hello\nworld.",
+                               16,
+                               'hello world.',
+                       ),
+                       array( 'hello world.',
+                               8,
+                               'hello...',
+                       ),
+                       array( '[[hello world]].',
+                               8,
+                               'hel...',
+                       ),
+               );
+       }
+
+       /**
+        * @todo: test needs database! Should be done by a test class in the Database group.
+        */
+       /*
+       public function getRedirectChain() {
+               $text = $this->getNativeData();
+               return Title::newFromRedirectArray( $text );
+       }
+       */
+
+       /**
+        * @todo: test needs database! Should be done by a test class in the Database group.
+        */
+       /*
+       public function getUltimateRedirectTarget() {
+               $text = $this->getNativeData();
+               return Title::newFromRedirectRecurse( $text );
+       }
+       */
+
+       public static function dataIsCountable() {
+               return array(
+                       array( '',
+                              null,
+                              'any',
+                              true
+                       ),
+                       array( 'Foo',
+                              null,
+                              'any',
+                              true
+                       ),
+                       array( 'Foo',
+                              null,
+                              'comma',
+                              false
+                       ),
+                       array( 'Foo, bar',
+                              null,
+                              'comma',
+                              true
+                       ),
+                       array( 'Foo',
+                              null,
+                              'link',
+                              false
+                       ),
+                       array( 'Foo [[bar]]',
+                              null,
+                              'link',
+                              true
+                       ),
+                       array( 'Foo',
+                              true,
+                              'link',
+                              true
+                       ),
+                       array( 'Foo [[bar]]',
+                              false,
+                              'link',
+                              false
+                       ),
+                       array( '#REDIRECT [[bar]]',
+                              true,
+                              'any',
+                              false
+                       ),
+                       array( '#REDIRECT [[bar]]',
+                              true,
+                              'comma',
+                              false
+                       ),
+                       array( '#REDIRECT [[bar]]',
+                              true,
+                              'link',
+                              false
+                       ),
+               );
+       }
+
+       public function testMatchMagicWord( ) {
+               $mw = MagicWord::get( "staticredirect" );
+
+               $content = $this->newContent( "#REDIRECT [[FOO]]\n__STATICREDIRECT__" );
+               $this->assertTrue( $content->matchMagicWord( $mw ), "should have matched magic word" );
+
+               $content = $this->newContent( "#REDIRECT [[FOO]]" );
+               $this->assertFalse( $content->matchMagicWord( $mw ), "should not have matched magic word" );
+       }
+
+       public function testUpdateRedirect( ) {
+               $target = Title::newFromText( "testUpdateRedirect_target" );
+
+               // test with non-redirect page
+               $content = $this->newContent( "hello world." );
+               $newContent = $content->updateRedirect( $target );
+
+               $this->assertTrue( $content->equals( $newContent ), "content should be unchanged" );
+
+               // test with actual redirect
+               $content = $this->newContent( "#REDIRECT [[Someplace]]" );
+               $newContent = $content->updateRedirect( $target );
+
+               $this->assertFalse( $content->equals( $newContent ), "content should have changed" );
+               $this->assertTrue( $newContent->isRedirect(), "new content should be a redirect" );
+
+               $this->assertEquals( $target->getFullText(), $newContent->getRedirectTarget()->getFullText() );
+       }
+
+       public function testGetModel() {
+               $content = $this->newContent( "hello world." );
+
+               $this->assertEquals( CONTENT_MODEL_WIKITEXT, $content->getModel() );
+       }
+
+       public function testGetContentHandler() {
+               $content = $this->newContent( "hello world." );
+
+               $this->assertEquals( CONTENT_MODEL_WIKITEXT, $content->getContentHandler()->getModelID() );
+       }
+
+       public static function dataEquals( ) {
+               return array(
+                       array( new WikitextContent( "hallo" ), null, false ),
+                       array( new WikitextContent( "hallo" ), new WikitextContent( "hallo" ), true ),
+                       array( new WikitextContent( "hallo" ), new JavascriptContent( "hallo" ), false ),
+                       array( new WikitextContent( "hallo" ), new TextContent( "hallo" ), false ),
+                       array( new WikitextContent( "hallo" ), new WikitextContent( "HALLO" ), false ),
+               );
+       }
+
+       public static function dataGetDeletionUpdates() {
+               return array(
+                       array("WikitextContentTest_testGetSecondaryDataUpdates_1",
+                               CONTENT_MODEL_WIKITEXT, "hello ''world''\n",
+                               array( 'LinksDeletionUpdate' => array( ) )
+                       ),
+                       array("WikitextContentTest_testGetSecondaryDataUpdates_2",
+                               CONTENT_MODEL_WIKITEXT, "hello [[world test 21344]]\n",
+                               array( 'LinksDeletionUpdate' => array( ) )
+                       ),
+                       // @todo: more...?
+               );
+       }
+
+}
index a8a6b48..cbbdc1f 100644 (file)
@@ -8,10 +8,12 @@ class DatabaseTest extends MediaWikiTestCase {
        var $db, $functionTest = false;
 
        protected function setUp() {
+               parent::setUp();
                $this->db = wfGetDB( DB_MASTER );
        }
 
        protected function tearDown() {
+               parent::tearDown();
                if ( $this->functionTest ) {
                        $this->dropFunctions();
                        $this->functionTest = false;
index 4f338d3..bd2c388 100644 (file)
@@ -4,6 +4,7 @@ class MWDebugTest extends MediaWikiTestCase {
 
 
        protected function setUp() {
+               parent::setUp();
                // Make sure MWDebug class is enabled
                static $MWDebugEnabled = false;
                if( !$MWDebugEnabled ) {
@@ -17,6 +18,7 @@ class MWDebugTest extends MediaWikiTestCase {
 
        protected function tearDown() {
                wfRestoreWarnings();
+               parent::tearDown();
        }
 
        function testAddLog() {
index ee1c6f8..e027668 100644 (file)
@@ -2,6 +2,7 @@
 class PNGMetadataExtractorTest extends MediaWikiTestCase {
 
        protected function setUp() {
+               parent::setUp();
                $this->filePath = __DIR__ . '/../../data/media/';
        }
        /**
index 007ce46..d9a59ca 100644 (file)
@@ -3,6 +3,7 @@
 class SVGMetadataExtractorTest extends MediaWikiTestCase {
 
        protected function setUp() {
+               parent::setUp();
                AutoLoader::loadClass( 'SVGMetadataExtractorTest' );
        }
 
index be02dd7..452016f 100644 (file)
@@ -2,6 +2,7 @@
 class XMPTest extends MediaWikiTestCase {
 
        protected function setUp() {
+               parent::setUp();
                if ( !wfDl( 'xml' ) ) {
                        $this->markTestSkipped( 'Requires libxml to do XMP parsing' );
                }
index 46ef5da..611a45a 100644 (file)
@@ -32,10 +32,11 @@ class MagicVariableTest extends MediaWikiTestCase {
        protected function setUp() {
                parent::setUp();
 
-               $this->setMwGlobals( 'wgContLang', Language::factory( 'en' ) );
+               $contLang = Language::factory( 'en' );
+               $this->setMwGlobals( 'wgContLang', $contLang );
 
                $this->testParser = new Parser();
-               $this->testParser->Options( new ParserOptions() );
+               $this->testParser->Options( ParserOptions::newFromUserAndLang( new User, $contLang ) );
 
                # initialize parser output
                $this->testParser->clearState();
index d537b6e..8c22c59 100644 (file)
@@ -9,7 +9,10 @@ class ParserPreloadTest extends MediaWikiTestCase {
        private $title;
 
        protected function setUp() {
-               $this->testParserOptions = new ParserOptions();
+               global $wgContLang;
+
+               parent::setUp();
+               $this->testParserOptions = ParserOptions::newFromUserAndLang( new User, $wgContLang );
 
                $this->testParser = new Parser();
                $this->testParser->Options( $this->testParserOptions );
@@ -19,6 +22,8 @@ class ParserPreloadTest extends MediaWikiTestCase {
        }
 
        protected function tearDown() {
+               parent::tearDown();
+
                unset( $this->testParser );
                unset( $this->title );
        }
index d82fc6c..362d9f7 100644 (file)
@@ -6,8 +6,9 @@ class PreprocessorTest extends MediaWikiTestCase {
        var $mOptions;
 
        protected function setUp() {
-               global $wgParserConf;
-               $this->mOptions = new ParserOptions();
+               global $wgParserConf, $wgContLang;
+               parent::setUp();
+               $this->mOptions = ParserOptions::newFromUserAndLang( new User, $wgContLang );
                $name = isset( $wgParserConf['preprocessorClass'] ) ? $wgParserConf['preprocessorClass'] : 'Preprocessor_DOM';
 
                $this->mPreprocessor = new $name( $this );
index 713ce84..d089aff 100644 (file)
@@ -17,11 +17,11 @@ class TagHookTest extends MediaWikiTestCase {
         * @dataProvider provideValidNames
         */
        function testTagHooks( $tag ) {
-               global $wgParserConf;
+               global $wgParserConf, $wgContLang;
                $parser = new Parser( $wgParserConf );
                
                $parser->setHook( $tag, array( $this, 'tagCallback' ) );
-               $parserOutput = $parser->parse( "Foo<$tag>Bar</$tag>Baz", Title::newFromText( 'Test' ), new ParserOptions );
+               $parserOutput = $parser->parse( "Foo<$tag>Bar</$tag>Baz", Title::newFromText( 'Test' ), ParserOptions::newFromUserAndLang( new User, $wgContLang ) );
                $this->assertEquals( "<p>FooOneBaz\n</p>", $parserOutput->getText() );
                
                $parser->mPreprocessor = null; # Break the Parser <-> Preprocessor cycle
@@ -32,11 +32,11 @@ class TagHookTest extends MediaWikiTestCase {
         * @expectedException MWException
         */
        function testBadTagHooks( $tag ) {
-               global $wgParserConf;
+               global $wgParserConf, $wgContLang;
                $parser = new Parser( $wgParserConf );
                
                $parser->setHook( $tag, array( $this, 'tagCallback' ) );
-               $parser->parse( "Foo<$tag>Bar</$tag>Baz", Title::newFromText( 'Test' ), new ParserOptions );
+               $parser->parse( "Foo<$tag>Bar</$tag>Baz", Title::newFromText( 'Test' ), ParserOptions::newFromUserAndLang( new User, $wgContLang ) );
                $this->fail('Exception not thrown.');
        }
        
@@ -44,11 +44,11 @@ class TagHookTest extends MediaWikiTestCase {
         * @dataProvider provideValidNames
         */
        function testFunctionTagHooks( $tag ) {
-               global $wgParserConf;
+               global $wgParserConf, $wgContLang;
                $parser = new Parser( $wgParserConf );
                
                $parser->setFunctionTagHook( $tag, array( $this, 'functionTagCallback' ), 0 );
-               $parserOutput = $parser->parse( "Foo<$tag>Bar</$tag>Baz", Title::newFromText( 'Test' ), new ParserOptions );
+               $parserOutput = $parser->parse( "Foo<$tag>Bar</$tag>Baz", Title::newFromText( 'Test' ), ParserOptions::newFromUserAndLang( new User, $wgContLang ) );
                $this->assertEquals( "<p>FooOneBaz\n</p>", $parserOutput->getText() );
                
                $parser->mPreprocessor = null; # Break the Parser <-> Preprocessor cycle
@@ -59,11 +59,11 @@ class TagHookTest extends MediaWikiTestCase {
         * @expectedException MWException
         */
        function testBadFunctionTagHooks( $tag ) {
-               global $wgParserConf;
+               global $wgParserConf, $wgContLang;
                $parser = new Parser( $wgParserConf );
                
                $parser->setFunctionTagHook( $tag, array( $this, 'functionTagCallback' ), SFH_OBJECT_ARGS );
-               $parser->parse( "Foo<$tag>Bar</$tag>Baz", Title::newFromText( 'Test' ), new ParserOptions );
+               $parser->parse( "Foo<$tag>Bar</$tag>Baz", Title::newFromText( 'Test' ), ParserOptions::newFromUserAndLang( new User, $wgContLang ) );
                $this->fail('Exception not thrown.');
        }
        
index f102309..82426bd 100644 (file)
@@ -14,9 +14,6 @@ class SpecialRecentchangesTest extends MediaWikiTestCase {
         */
        protected $rc;
 
-       protected function setUp() {
-       }
-
        /** helper to test SpecialRecentchanges::buildMainQueryConds() */
        private function assertConditions( $expected, $requestOptions = null, $message = '' ) {
                $context = new RequestContext;