From: Hashar Date: Sat, 10 Nov 2012 16:44:44 +0000 (+0000) Subject: Merge "(Bug 41352) Provide tests for edit conflicts." X-Git-Tag: 1.31.0-rc.0~21672 X-Git-Url: https://git.cyclocoop.org/%7B%24admin_url%7Dcompta/operations/modifier.php?a=commitdiff_plain;h=6670bf66dfa0a0ae6025c63e16094bb65a9ada38;hp=3dcf8c5284ba8012f75ac44e54d8647e47a24e35;p=lhc%2Fweb%2Fwiklou.git Merge "(Bug 41352) Provide tests for edit conflicts." --- diff --git a/.gitignore b/.gitignore index 319f19640e..a47a454f77 100644 --- a/.gitignore +++ b/.gitignore @@ -11,6 +11,7 @@ cscope.out ## NetBeans nbproject* project.index +sublime-* # MediaWiki install & usage cache @@ -30,6 +31,9 @@ AdminSettings.php LocalSettings.php StartProfiler.php +# Building & testing +node_modules/ + # Operating systems ## Mac OS X .DS_Store diff --git a/.jshintignore b/.jshintignore index 026eaaaf85..3869deb913 100644 --- a/.jshintignore +++ b/.jshintignore @@ -1,4 +1,6 @@ -# upstream libs +# third-party libs +extensions/ +node_modules/ resources/jquery/jquery.appear.js resources/jquery/jquery.async.js resources/jquery/jquery.cycle.all.js @@ -13,9 +15,13 @@ resources/jquery/jquery.mockjax.js resources/jquery/jquery.qunit.js resources/jquery/jquery.validate.js resources/jquery/jquery.xmldom.js -resources/jquery.effects -resources/jquery.tipsy -resources/jquery.ui -resources/mediawiki.libs -tests/jasmine/lib/jasmine-1.0.1/jasmine-html.js -tests/jasmine/lib/jasmine-1.0.1/jasmine.js +resources/jquery.effects/ +resources/jquery.tipsy/ +resources/jquery.ui/ +resources/mediawiki.libs/ + +# legacy scripts +skins/common/ + +# github.com/jshint/jshint/issues/729 +tests/qunit/suites/resources/mediawiki/mediawiki.jscompat.test.js diff --git a/.jshintrc b/.jshintrc index b86ceb5f0c..7fa138d44f 100644 --- a/.jshintrc +++ b/.jshintrc @@ -1,20 +1,25 @@ { "predef": [ "mediaWiki", + "jQuery", "QUnit" ], "bitwise": true, + "camelcase": true, "curly": true, "eqeqeq": true, + "forin": false, "immed": true, "latedef": true, "newcap": true, "noarg": true, "noempty": true, "nonew": true, + "quotmark": "single", "regexp": false, "undef": true, + "unused": true, "strict": false, "trailing": true, @@ -23,7 +28,6 @@ "multistr": true, "browser": true, - "jquery": true, "nomen": true, "onevar": true diff --git a/CREDITS b/CREDITS index 68c945c96f..6555b07ccb 100644 --- a/CREDITS +++ b/CREDITS @@ -2,6 +2,7 @@ MediaWiki 1.21 is a collaborative project released under the GNU General Public License v2. We would like to recognize the following names for their contribution to the product. + == Developers == * Aaron Schulz * Alex Z. @@ -44,6 +45,7 @@ following names for their contribution to the product. * Leon Weber * Leslie Hoare * Marco Schuster +* Marius Hoch * Matěj Grabovský * Matt Johnston * Max Semenik @@ -206,4 +208,4 @@ following names for their contribution to the product. * Meno25 * Rotem Liss * Shinjiman -* Translatewiki.net Translators https://translatewiki.net/wiki/Special:ListUsers/translator +* [https://translatewiki.net/wiki/Special:ListUsers/translator Translatewiki.net Translators] diff --git a/README.mediawiki b/README.mediawiki new file mode 120000 index 0000000000..100b93820a --- /dev/null +++ b/README.mediawiki @@ -0,0 +1 @@ +README \ No newline at end of file diff --git a/RELEASE-NOTES-1.20 b/RELEASE-NOTES-1.20 index 52c4e8685c..1a9296842a 100644 --- a/RELEASE-NOTES-1.20 +++ b/RELEASE-NOTES-1.20 @@ -5,10 +5,7 @@ setting since version 1.2.0. If you have it on, turn it '''off''' if you can. == MediaWiki 1.20 == -THIS IS NOT A RELEASE YET - -MediaWiki 1.20 is an alpha-quality branch and is not recommended for use in -production. +MediaWiki 1.20 is a stable release. === PHP 5.3 now required === Since 1.20, the lowest supported version of PHP is now 5.3.2. Please @@ -152,7 +149,32 @@ upgrade PHP if you have not done so prior to upgrading MediaWiki. * (bug 40448) mediawiki.legacy.mwsuggest has been replaced with a new module, mediawiki.searchSuggest, based on SimpleSeach from Extension:Vector. +=== Known issues in 1.20.0 === +These are issues that we're targeting to be fixed in a later release +in the 1.20 series. Issues may be added or removed from this list as +we see fit. For now, it is comprised of those bugs on the 1.20.0 +milestone in Bugzilla. + +* (bug 35894): Reports of secret key generation "hanging" on windows + This is probably a bug that has been fixed in PHP. If you run + into this, try upgrading your PHP. +* (bug 38334): PHP Notice: Undefined index: href in /www/w/skins/Vector.php on line 416 + We think this is a problem in some extension. If you see this, + try disabling your extensions and check out the logging patch on + this bug. Or try this patch: + +* (bug 39268): [Regression] Toolbar inserts in main textarea only (instead of the focussed textarea) + This should only be an issue if you are using the ProofreadPage + extension. +* (bug 40641): Clicking "others" in Special:Version asks to download a file + If you encounter this, you can tell your webserver to serve the + CREDITS file with text/plain MIME type to fix it. + === Bug fixes in 1.20 === +* (bug 40939): [Regression] InfoAction: Call to a member function getUserText() on a non-object +* (bug 40780): searchsuggest-containing line ("containing...") doesn't include the entered text +* (bug 37714): [Regression] Incomplete log entries +* (bug 27202): API: Add timestamp sort to list=allimages * (bug 30245) Use the correct way to construct a log page title. * (bug 34237) Regenerate an empty user_token and save to the database when we try to set the user's cookies for login. diff --git a/RELEASE-NOTES-1.21 b/RELEASE-NOTES-1.21 index 8eb6a7612f..b9b026cb37 100644 --- a/RELEASE-NOTES-1.21 +++ b/RELEASE-NOTES-1.21 @@ -34,6 +34,7 @@ production. * Added ApiQueryORM class to facilitate creation of query API modules based on tables that have a corresponding ORMTable class. * (bug 40876) Icon for PSD (Adobe Photoshop) file types. +* (bug 40641) Implemented Special:Version/Credits with a list of contributors. === Bug fixes in 1.21 === * (bug 40353) SpecialDoubleRedirect should support interwiki redirects. @@ -48,6 +49,18 @@ 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. +* (bug 41494) Honor $wgLogExceptionBacktrace when logging non-API exceptions + caught during API execution. +* (bug 37963) Fixed loading process for user options +* (bug 26995) Update filename field on Upload page after having sanitized it. +* (bug 41793) Contribution links to users with 0 edits on Special:ListUsers didn't + show up red. +* (bug 41899) A PHP notice no longer occurs when using the "rvcontinue" API parameter. === API changes in 1.21 === * prop=revisions can now report the contentmodel and contentformat, see docs/contenthandler.txt @@ -55,6 +68,7 @@ production. page content; See docs/contenthandler.txt for details. * (bug 35693) ApiQueryImageInfo now suppresses errors when unserializing metadata. * (bug 40111) Disable minor edit for page/section creation by API +* (bug 41042) Revert change to action=parse&page=... behavior when the page does not exist. === Languages updated in 1.21 === diff --git a/docs/export-0.8.xsd b/docs/export-0.8.xsd index a18c608e58..07b432a197 100644 --- a/docs/export-0.8.xsd +++ b/docs/export-0.8.xsd @@ -134,13 +134,13 @@ - + - + diff --git a/docs/export-demo.xml b/docs/export-demo.xml index d198b93c8a..591f675c58 100644 --- a/docs/export-demo.xml +++ b/docs/export-demo.xml @@ -1,4 +1,4 @@ - + @@ -79,8 +79,10 @@ I have just one thing to say! - 5x0ux8iwjrbmfzgv6pkketxgkcnpr7h A bunch of [[text]] here. + 5x0ux8iwjrbmfzgv6pkketxgkcnpr7h + wikitext + text/x-wiki @@ -90,8 +92,10 @@ 10.0.0.2 new! - etaxt3shcge6igz1biwy3d4um2pnle4 An earlier [[revision]]. + etaxt3shcge6igz1biwy3d4um2pnle4 + wikitext + text/x-wiki @@ -104,8 +108,10 @@ 2001-01-15T14:03:00Z 10.0.0.2 hey - ml80vmyjlixdstnywwihx003exfzq9j WHYD YOU LOCK PAGE??!!! i was editing that jerk + ml80vmyjlixdstnywwihx003exfzq9j + wikitext + text/x-wiki @@ -118,8 +124,10 @@ 2001-01-15T20:34:12Z Foobar42 My awesomeest image! - mehom37npwkpzhaiwu3wyr0egalumki This is an awesome little imgae. I lurves it. {{PD}} + mehom37npwkpzhaiwu3wyr0egalumki + wikitext + text/x-wiki 2001-01-15T20:34:12Z diff --git a/docs/hooks.txt b/docs/hooks.txt index 998523f334..67b4580b75 100644 --- a/docs/hooks.txt +++ b/docs/hooks.txt @@ -752,6 +752,16 @@ cointent model name, but no entry for that model exists in $wgContentHandlers. $modeName: the requested content model name &$handler: set this to a ContentHandler object, if desired. +'ConvertContent': Called by AbstractContent::convert when a conversion to another +content model is requested. +$content: The Content object to be converted. +$toModel: The ID of the content model to convert to. +$lossy: boolean indicating whether lossy conversion is allowed. +&$result: Output parameter, in case the handler function wants to provide a +converted Content object. Note that $result->getContentModel() must return $toModel. +Handler functions that modify $result should generally return false to further +attempts at conversion. + 'ContribsPager::getQueryInfo': Before the contributions query is about to run &$pager: Pager object for contributions &$queryInfo: The query for the contribs Pager @@ -1831,6 +1841,21 @@ $result: The search result $terms: The search terms entered $page: The SpecialSearch object. +'ShowSearchHit': Customize display of search hit. +$searchPage: The SpecialSearch instance. +$result: The SearchResult to show +$terms: Search terms, for highlighting +&$link: HTML of link to the matching page. May be modified. +&$redirect: HTML of redirect info. May be modified. +&$section: HTML of matching section. May be modified. +&$extract: HTML of content extract. May be modified. +&$score: HTML of score. May be modified. +&$size: HTML of page size. May be modified. +&$date: HTML of of page modification date. May be modified. +&$related: HTML of additional info for the matching page. May be modified. +&$html: May be set to the full HTML that should be used to represent the search hit. Must include +the
  • ...
  • tags. Will only be used if the hook function returned false. + 'SiteNoticeBefore': Before the sitenotice/anonnotice is composed &$siteNotice: HTML returned as the sitenotice $skin: Skin object @@ -2110,7 +2135,7 @@ $result: Boolean; whether MediaWiki currently thinks this is a CSS/JS page. Hook Allows overriding default behaviour for determining if a page exists. If $isKnown is kept as null, regular checks happen. If it's a boolean, this value is returned by the isKnown method. $title: Title object that is being checked -$result: Boolean|null; whether MediaWiki currently thinks this page is known +&$isKnown: Boolean|null; whether MediaWiki currently thinks this page is known 'TitleIsMovable': Called when determining if it is possible to move a page. Note that this hook is not called for interwiki pages or pages in immovable namespaces: for these, isMovable() always returns false. diff --git a/img_auth.php b/img_auth.php index b3a34955de..b04974bf82 100644 --- a/img_auth.php +++ b/img_auth.php @@ -48,7 +48,7 @@ if ( isset( $_SERVER['MW_COMPILED'] ) ) { wfProfileIn( 'img_auth.php' ); # Set action base paths so that WebRequest::getPathInfo() -# recognizes the "X" as the 'title' in ../image_auth/X urls. +# recognizes the "X" as the 'title' in ../img_auth.php/X urls. $wgArticlePath = false; # Don't let a "/*" article path clober our action path $wgActionPaths = array( "$wgUploadPath/" ); diff --git a/includes/Article.php b/includes/Article.php index 0eb0c68b08..169dd03af3 100644 --- a/includes/Article.php +++ b/includes/Article.php @@ -688,7 +688,7 @@ class Article extends Page { $outputDone = true; } else { $content = $this->getContentObject(); - $rt = $content->getRedirectChain(); + $rt = $content ? $content->getRedirectChain() : null; if ( $rt ) { wfDebug( __METHOD__ . ": showing redirect=no page\n" ); # Viewing a redirect page (e.g. with parameter redirect=no) @@ -704,9 +704,8 @@ class Article extends Page { # Run the parse, protected by a pool counter wfDebug( __METHOD__ . ": doing uncached parse\n" ); - // @todo: shouldn't we be passing $this->getPage() to PoolWorkArticleView instead of plain $this? - $poolArticleView = new PoolWorkArticleView( $this, $parserOptions, - $this->getRevIdFetched(), $useParserCache, $this->getContentObject(), $this->getContext() ); + $poolArticleView = new PoolWorkArticleView( $this->getPage(), $parserOptions, + $this->getRevIdFetched(), $useParserCache, $this->getContentObject() ); if ( !$poolArticleView->execute() ) { $error = $poolArticleView->getError(); @@ -842,10 +841,14 @@ class Article extends Page { 'clearyourcache' ); } - // Give hooks a chance to customise the output - if ( ContentHandler::runLegacyHooks( 'ShowRawCssJs', array( $this->fetchContentObject(), $this->getTitle(), $outputPage ) ) ) { - $po = $this->mContentObject->getParserOutput( $this->getTitle() ); - $outputPage->addHTML( $po->getText() ); + $this->fetchContentObject(); + + if ( $this->mContentObject ) { + // Give hooks a chance to customise the output + if ( ContentHandler::runLegacyHooks( 'ShowRawCssJs', array( $this->mContentObject, $this->getTitle(), $outputPage ) ) ) { + $po = $this->mContentObject->getParserOutput( $this->getTitle() ); + $outputPage->addHTML( $po->getText() ); + } } } diff --git a/includes/AutoLoader.php b/includes/AutoLoader.php index d98556ee34..dcaaf5a8d4 100644 --- a/includes/AutoLoader.php +++ b/includes/AutoLoader.php @@ -254,7 +254,6 @@ $wgAutoloadLocalClasses = array( 'UnlistedSpecialPage' => 'includes/SpecialPage.php', 'UploadSourceAdapter' => 'includes/Import.php', 'UppercaseCollation' => 'includes/Collation.php', - 'Uri' => 'includes/Uri.php', 'User' => 'includes/User.php', 'UserArray' => 'includes/UserArray.php', 'UserArrayFromResult' => 'includes/UserArray.php', @@ -299,6 +298,7 @@ $wgAutoloadLocalClasses = array( 'JavaScriptContentHandler' => 'includes/content/JavaScriptContentHandler.php', 'JavaScriptContent' => 'includes/content/JavaScriptContent.php', 'MessageContent' => 'includes/content/MessageContent.php', + 'MWContentSerializationException' => 'includes/content/ContentHandler.php', 'TextContentHandler' => 'includes/content/TextContentHandler.php', 'TextContent' => 'includes/content/TextContent.php', 'WikitextContentHandler' => 'includes/content/WikitextContentHandler.php', @@ -446,11 +446,6 @@ $wgAutoloadLocalClasses = array( 'TitleDependency' => 'includes/cache/CacheDependency.php', 'TitleListDependency' => 'includes/cache/CacheDependency.php', - # includes/conf - 'Conf' => 'includes/conf/Conf.php', - 'DatabaseConf' => 'includes/conf/DatabaseConf.php', - 'DefaultSettings' => 'includes/conf/DefaultSettings.php', - # includes/context 'ContextSource' => 'includes/context/ContextSource.php', 'DerivativeContext' => 'includes/context/DerivativeContext.php', @@ -661,6 +656,7 @@ $wgAutoloadLocalClasses = array( 'EmaillingJob' => 'includes/job/jobs/EmaillingJob.php', 'EnotifNotifyJob' => 'includes/job/jobs/EnotifNotifyJob.php', 'HTMLCacheUpdateJob' => 'includes/job/jobs/HTMLCacheUpdateJob.php', + 'NullJob' => 'includes/job/jobs/NullJob.php', 'RefreshLinksJob' => 'includes/job/jobs/RefreshLinksJob.php', 'RefreshLinksJob2' => 'includes/job/jobs/RefreshLinksJob.php', 'UploadFromUrlJob' => 'includes/job/jobs/UploadFromUrlJob.php', @@ -702,6 +698,7 @@ $wgAutoloadLocalClasses = array( 'PatrolLog' => 'includes/logging/PatrolLog.php', 'PatrolLogFormatter' => 'includes/logging/LogFormatter.php', 'RCDatabaseLogEntry' => 'includes/logging/LogEntry.php', + 'RightsLogFormatter' => 'includes/logging/LogFormatter.php', # includes/media 'BitmapHandler' => 'includes/media/Bitmap.php', @@ -1095,13 +1092,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', diff --git a/includes/Block.php b/includes/Block.php index 86b4d13d36..e05b2acfa4 100644 --- a/includes/Block.php +++ b/includes/Block.php @@ -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; diff --git a/includes/Category.php b/includes/Category.php index ffd7bb8bda..6a5eac7b89 100644 --- a/includes/Category.php +++ b/includes/Category.php @@ -58,6 +58,9 @@ class Category { # Already initialized return true; } + + wfProfileIn( __METHOD__ ); + $dbr = wfGetDB( DB_SLAVE ); $row = $dbr->selectRow( 'category', @@ -66,6 +69,8 @@ class Category { __METHOD__ ); + wfProfileOut( __METHOD__ ); + if ( !$row ) { # Okay, there were no contents. Nothing to initialize. if ( $this->mTitle ) { @@ -190,25 +195,37 @@ class Category { } /** @return mixed DB key name, or false on failure */ - public function getName() { return $this->getX( 'mName' ); } + public function getName() { + return $this->getX( 'mName' ); + } /** @return mixed Category ID, or false on failure */ - public function getID() { return $this->getX( 'mID' ); } + public function getID() { + return $this->getX( 'mID' ); + } /** @return mixed Total number of member pages, or false on failure */ - public function getPageCount() { return $this->getX( 'mPages' ); } + public function getPageCount() { + return $this->getX( 'mPages' ); + } /** @return mixed Number of subcategories, or false on failure */ - public function getSubcatCount() { return $this->getX( 'mSubcats' ); } + public function getSubcatCount() { + return $this->getX( 'mSubcats' ); + } /** @return mixed Number of member files, or false on failure */ - public function getFileCount() { return $this->getX( 'mFiles' ); } + public function getFileCount() { + return $this->getX( 'mFiles' ); + } /** * @return Title|bool Title for this category, or false on failure. */ public function getTitle() { - if ( $this->mTitle ) return $this->mTitle; + if ( $this->mTitle ) { + return $this->mTitle; + } if ( !$this->initialize() ) { return false; @@ -226,20 +243,22 @@ class Category { * @return TitleArray object for category members. */ public function getMembers( $limit = false, $offset = '' ) { + wfProfileIn( __METHOD__ ); + $dbr = wfGetDB( DB_SLAVE ); $conds = array( 'cl_to' => $this->getName(), 'cl_from = page_id' ); $options = array( 'ORDER BY' => 'cl_sortkey' ); if ( $limit ) { - $options[ 'LIMIT' ] = $limit; + $options['LIMIT'] = $limit; } if ( $offset !== '' ) { $conds[] = 'cl_sortkey > ' . $dbr->addQuotes( $offset ); } - return TitleArray::newFromResult( + $result = TitleArray::newFromResult( $dbr->select( array( 'page', 'categorylinks' ), array( 'page_id', 'page_namespace', 'page_title', 'page_len', @@ -249,6 +268,10 @@ class Category { $options ) ); + + wfProfileOut( __METHOD__ ); + + return $result; } /** @@ -259,7 +282,7 @@ class Category { if ( !$this->initialize() ) { return false; } - return $this-> { $key } ; + return $this->{$key}; } /** @@ -279,8 +302,10 @@ class Category { } } + wfProfileIn( __METHOD__ ); + $dbw = wfGetDB( DB_MASTER ); - $dbw->begin( __METHOD__ ); + $dbw->begin( __METHOD__ ); # Insert the row if it doesn't exist yet (e.g., this is being run via # update.php from a pre-1.16 schema). TODO: This will cause lots and @@ -303,8 +328,8 @@ class Category { $result = $dbw->selectRow( array( 'categorylinks', 'page' ), array( 'pages' => 'COUNT(*)', - 'subcats' => "COUNT($cond1)", - 'files' => "COUNT($cond2)" + 'subcats' => "COUNT($cond1)", + 'files' => "COUNT($cond2)" ), array( 'cl_to' => $this->mName, 'page_id = cl_from' ), __METHOD__, @@ -322,6 +347,8 @@ class Category { ); $dbw->commit( __METHOD__ ); + wfProfileOut( __METHOD__ ); + # Now we should update our local counts. $this->mPages = $result->pages; $this->mSubcats = $result->subcats; diff --git a/includes/CategoryViewer.php b/includes/CategoryViewer.php index 3d66b74a26..b59b4e1afe 100644 --- a/includes/CategoryViewer.php +++ b/includes/CategoryViewer.php @@ -173,7 +173,7 @@ class CategoryViewer extends ContextSource { /** * Add a subcategory to the internal lists, using a title object - * @deprecated since 1.17 kept for compatibility, please use addSubcategoryObject instead + * @deprecated since 1.17 kept for compatibility, use addSubcategoryObject instead */ function addSubcategory( Title $title, $sortkey, $pageLength ) { wfDeprecated( __METHOD__, '1.17' ); @@ -181,14 +181,14 @@ class CategoryViewer extends ContextSource { } /** - * Get the character to be used for sorting subcategories. - * If there's a link from Category:A to Category:B, the sortkey of the resulting - * entry in the categorylinks table is Category:A, not A, which it SHOULD be. - * Workaround: If sortkey == "Category:".$title, than use $title for sorting, - * else use sortkey... - * - * @param Title $title - * @param string $sortkey The human-readable sortkey (before transforming to icu or whatever). + * Get the character to be used for sorting subcategories. + * If there's a link from Category:A to Category:B, the sortkey of the resulting + * entry in the categorylinks table is Category:A, not A, which it SHOULD be. + * Workaround: If sortkey == "Category:".$title, than use $title for sorting, + * else use sortkey... + * + * @param Title $title + * @param string $sortkey The human-readable sortkey (before transforming to icu or whatever). * @return string */ function getSubcategorySortChar( $title, $sortkey ) { @@ -259,15 +259,15 @@ class CategoryViewer extends ContextSource { function finaliseCategoryState() { if ( $this->flip['subcat'] ) { - $this->children = array_reverse( $this->children ); + $this->children = array_reverse( $this->children ); $this->children_start_char = array_reverse( $this->children_start_char ); } if ( $this->flip['page'] ) { - $this->articles = array_reverse( $this->articles ); + $this->articles = array_reverse( $this->articles ); $this->articles_start_char = array_reverse( $this->articles_start_char ); } if ( !$this->showGallery && $this->flip['file'] ) { - $this->imgsNoGallery = array_reverse( $this->imgsNoGallery ); + $this->imgsNoGallery = array_reverse( $this->imgsNoGallery ); $this->imgsNoGallery_start_char = array_reverse( $this->imgsNoGallery_start_char ); } } @@ -302,7 +302,7 @@ class CategoryViewer extends ContextSource { 'page_is_redirect', 'cl_sortkey', 'cat_id', 'cat_title', 'cat_subcats', 'cat_pages', 'cat_files', 'cl_sortkey_prefix', 'cl_collation' ), - array_merge( array( 'cl_to' => $this->title->getDBkey() ), $extraConds ), + array_merge( array( 'cl_to' => $this->title->getDBkey() ), $extraConds ), __METHOD__, array( 'USE INDEX' => array( 'categorylinks' => 'cl_sortkey' ), @@ -310,7 +310,7 @@ class CategoryViewer extends ContextSource { 'ORDER BY' => $this->flip[$type] ? 'cl_sortkey DESC' : 'cl_sortkey', ), array( - 'categorylinks' => array( 'INNER JOIN', 'cl_from = page_id' ), + 'categorylinks' => array( 'INNER JOIN', 'cl_from = page_id' ), 'category' => array( 'LEFT JOIN', 'cat_title = page_title AND page_namespace = ' . NS_CATEGORY ) ) ); @@ -469,7 +469,7 @@ class CategoryViewer extends ContextSource { */ function formatList( $articles, $articles_start_char, $cutoff = 6 ) { $list = ''; - if ( count ( $articles ) > $cutoff ) { + if ( count( $articles ) > $cutoff ) { $list = self::columnList( $articles, $articles_start_char ); } elseif ( count( $articles ) > 0 ) { // for short lists of articles in categories. @@ -478,7 +478,7 @@ class CategoryViewer extends ContextSource { $pageLang = $this->title->getPageLanguage(); $attribs = array( 'lang' => $pageLang->getCode(), 'dir' => $pageLang->getDir(), - 'class' => 'mw-content-'.$pageLang->getDir() ); + 'class' => 'mw-content-' . $pageLang->getDir() ); $list = Html::rawElement( 'div', $attribs, $list ); return $list; @@ -604,7 +604,7 @@ class CategoryViewer extends ContextSource { ); } - return $this->msg('categoryviewer-pagedlinks')->rawParams($prevLink, $nextLink)->escaped(); + return $this->msg( 'categoryviewer-pagedlinks' )->rawParams( $prevLink, $nextLink )->escaped(); } /** @@ -635,6 +635,7 @@ class CategoryViewer extends ContextSource { return Title::makeTitle( $title->getNamespace(), $title->getDBkey(), $fragment ); } + /** * What to do if the category table conflicts with the number of results * returned? This function says what. Each type is considered independently @@ -676,8 +677,9 @@ class CategoryViewer extends ContextSource { $fromOrUntil = true; } - if ( $dbcnt == $rescnt || ( ( $rescnt == $this->limit || $fromOrUntil ) - && $dbcnt > $rescnt ) ) { + if ( $dbcnt == $rescnt || + ( ( $rescnt == $this->limit || $fromOrUntil ) && $dbcnt > $rescnt ) + ) { # Case 1: seems sane. $totalcnt = $dbcnt; } elseif ( $rescnt < $this->limit && !$fromOrUntil ) { diff --git a/includes/Categoryfinder.php b/includes/Categoryfinder.php index e2b6a0caa6..589950ff28 100644 --- a/includes/Categoryfinder.php +++ b/includes/Categoryfinder.php @@ -28,17 +28,17 @@ * * Example use : * - * # Determines whether the article with the page_id 12345 is in both - * # "Category 1" and "Category 2" or their subcategories, respectively + * # Determines whether the article with the page_id 12345 is in both + * # "Category 1" and "Category 2" or their subcategories, respectively * - * $cf = new Categoryfinder; - * $cf->seed( - * array( 12345 ), - * array( 'Category 1', 'Category 2' ), - * 'AND' - * ); - * $a = $cf->run(); - * print implode( ',' , $a ); + * $cf = new Categoryfinder; + * $cf->seed( + * array( 12345 ), + * array( 'Category 1', 'Category 2' ), + * 'AND' + * ); + * $a = $cf->run(); + * print implode( ',' , $a ); * * */ @@ -135,7 +135,7 @@ class Categoryfinder { # iterate through the parents foreach ( $this->parents[$id] as $p ) { - $pname = $p->cl_to ; + $pname = $p->cl_to; # Is this a condition? if ( isset( $conds[$pname] ) ) { @@ -172,6 +172,8 @@ class Categoryfinder { * Scans a "parent layer" of the articles/categories in $this->next */ function scan_next_layer() { + wfProfileIn( __METHOD__ ); + # Find all parents of the article currently in $this->next $layer = array(); $res = $this->dbr->select( @@ -225,6 +227,7 @@ class Categoryfinder { foreach ( $layer as $v ) { $this->deadend[$v] = $v; } - } + wfProfileOut( __METHOD__ ); + } } diff --git a/includes/ChangesList.php b/includes/ChangesList.php index e7395c0261..6b7e99c4d4 100644 --- a/includes/ChangesList.php +++ b/includes/ChangesList.php @@ -514,12 +514,12 @@ class ChangesList extends ContextSource { if ( $this->getUser()->isAllowed('rollback') && $rc->mAttribs['page_latest'] == $rc->mAttribs['rc_this_oldid'] ) { $rev = new Revision( array( + 'title' => $page, 'id' => $rc->mAttribs['rc_this_oldid'], 'user' => $rc->mAttribs['rc_user'], 'user_text' => $rc->mAttribs['rc_user_text'], 'deleted' => $rc->mAttribs['rc_deleted'] ) ); - $rev->setTitle( $page ); $s .= ' '.Linker::generateRollback( $rev, $this->getContext() ); } } diff --git a/includes/Cookie.php b/includes/Cookie.php index 1b86f5da83..48216f0d87 100644 --- a/includes/Cookie.php +++ b/includes/Cookie.php @@ -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 ) { diff --git a/includes/DefaultSettings.php b/includes/DefaultSettings.php index cea63e07a3..494b2a378b 100644 --- a/includes/DefaultSettings.php +++ b/includes/DefaultSettings.php @@ -361,7 +361,9 @@ $wgImgAuthPublicTest = true; * container : backend container name the zone is in * directory : root path within container for the zone * url : base URL to the root of the zone - * handlerUrl : base script handled URL to the root of the zone + * urlsByExt : map of file extension types to base URLs + * (useful for using a different cache for videos) + * handlerUrl : base script-handled URL to the root of the zone * (see FileRepo::getZoneHandlerUrl() function) * Zones default to using "-" as the container name * and default to using the container root as the zone's root directory. @@ -752,10 +754,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 +1855,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 +2594,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 @@ -2774,6 +2781,13 @@ $wgFooterIcons = array( */ $wgUseCombinedLoginLink = false; +/** + * Appearance of user page and talk page labels in personal tools. + * - true = combine links into a single label + * - false = keep links in separate labels + */ +$wgVectorCombineUserTalk = false; + /** * Search form look for Vector skin only. * - true = use an icon search button @@ -3730,7 +3744,7 @@ $wgAllowPrefChange = array(); /** * This is to let user authenticate using https when they come from http. * Based on an idea by George Herbert on wikitech-l: - * http://lists.wikimedia.org/pipermail/wikitech-l/2010-October/050065.html + * http://lists.wikimedia.org/pipermail/wikitech-l/2010-October/050039.html * @since 1.17 */ $wgSecureLogin = false; @@ -5409,14 +5423,15 @@ $wgHooks = array(); * can add to this to provide custom jobs */ $wgJobClasses = array( - 'refreshLinks' => 'RefreshLinksJob', - 'refreshLinks2' => 'RefreshLinksJob2', - 'htmlCacheUpdate' => 'HTMLCacheUpdateJob', + 'refreshLinks' => 'RefreshLinksJob', + 'refreshLinks2' => 'RefreshLinksJob2', + 'htmlCacheUpdate' => 'HTMLCacheUpdateJob', 'html_cache_update' => 'HTMLCacheUpdateJob', // backwards-compatible - 'sendMail' => 'EmaillingJob', - 'enotifNotify' => 'EnotifNotifyJob', + 'sendMail' => 'EmaillingJob', + 'enotifNotify' => 'EnotifNotifyJob', 'fixDoubleRedirect' => 'DoubleRedirectJob', - 'uploadFromUrl' => 'UploadFromUrlJob', + 'uploadFromUrl' => 'UploadFromUrlJob', + 'null' => 'NullJob' ); /** @@ -5436,7 +5451,7 @@ $wgJobTypesExcludedFromDefaultQueue = array(); * These settings should be global to all wikis. */ $wgJobTypeConf = array( - 'default' => array( 'class' => 'JobQueueDB' ), + 'default' => array( 'class' => 'JobQueueDB', 'order' => 'random' ), ); /** @@ -5641,8 +5656,6 @@ $wgLogActions = array( 'protect/modify' => 'modifiedarticleprotection', 'protect/unprotect' => 'unprotectedarticle', 'protect/move_prot' => 'movedarticleprotection', - 'rights/rights' => 'rightslogentry', - 'rights/autopromote' => 'rightslogentry-autopromote', 'upload/upload' => 'uploadedimage', 'upload/overwrite' => 'overwroteimage', 'upload/revert' => 'uploadedimage', @@ -5660,16 +5673,18 @@ $wgLogActions = array( * @see LogFormatter */ $wgLogActionsHandlers = array( - 'move/move' => 'MoveLogFormatter', - 'move/move_redir' => 'MoveLogFormatter', - 'delete/delete' => 'DeleteLogFormatter', - 'delete/restore' => 'DeleteLogFormatter', - 'delete/revision' => 'DeleteLogFormatter', - 'delete/event' => 'DeleteLogFormatter', - 'suppress/revision' => 'DeleteLogFormatter', - 'suppress/event' => 'DeleteLogFormatter', - 'suppress/delete' => 'DeleteLogFormatter', - 'patrol/patrol' => 'PatrolLogFormatter', + 'move/move' => 'MoveLogFormatter', + 'move/move_redir' => 'MoveLogFormatter', + 'delete/delete' => 'DeleteLogFormatter', + 'delete/restore' => 'DeleteLogFormatter', + 'delete/revision' => 'DeleteLogFormatter', + 'delete/event' => 'DeleteLogFormatter', + 'suppress/revision' => 'DeleteLogFormatter', + 'suppress/event' => 'DeleteLogFormatter', + 'suppress/delete' => 'DeleteLogFormatter', + 'patrol/patrol' => 'PatrolLogFormatter', + 'rights/rights' => 'RightsLogFormatter', + 'rights/autopromote' => 'RightsLogFormatter', ); /** diff --git a/includes/EditPage.php b/includes/EditPage.php index 88afb66fe3..21a100f0aa 100644 --- a/includes/EditPage.php +++ b/includes/EditPage.php @@ -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,16 +1473,14 @@ class EditPage { $this->isConflict = true; $content = $textbox_content; // do not try to merge here! } elseif ( $this->isConflict ) { - $contentObj = $content; # Attempt merge - if ( $this->mergeChangesInto( $content ) ) { + if ( $this->mergeChangesIntoContent( $content ) ) { // Successful merge! Maybe we should tell the user the good news? $this->isConflict = false; - $content = $this->toEditContent( $content ); wfDebug( __METHOD__ . ": Suppressing edit conflict, successful merge.\n" ); } else { $this->section = ''; - $this->textbox1 = ContentHandler::getContentText( $contentObj ); + $this->textbox1 = ContentHandler::getContentText( $content ); wfDebug( __METHOD__ . ": Keeping edit conflict, failed merge.\n" ); } } @@ -1550,16 +1553,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 @@ -1661,37 +1664,15 @@ class EditPage { function mergeChangesInto( &$editText ){ ContentHandler::deprecated( __METHOD__, "1.21" ); - wfProfileIn( __METHOD__ ); + $editContent = $this->toEditContent( $editText ); - $db = wfGetDB( DB_MASTER ); + $ok = $this->mergeChangesIntoContent( $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__ ); + if ( $ok ) { + $editText = $this->toEditText( $editContent ); return true; - } else { - wfProfileOut( __METHOD__ ); - return false; } + return false; } /** @@ -1940,7 +1921,7 @@ class EditPage { * an exception will be raised. Set $this->allowNonTextContent to true to allow editing of non-textual * content. * - * @param Content|null|false|string $content + * @param Content|null|bool|string $content * @return String the editable text form of the content. * * @throws MWException if $content is not an instance of TextContent and $this->allowNonTextContent is not true. @@ -2266,7 +2247,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( "\n", 'rev-deleted-text-permission' ); } elseif ( $revision->isDeleted( Revision::DELETED_TEXT ) ) { $wgOut->wrapWikiMsg( "\n", 'rev-deleted-text-view' ); @@ -2300,10 +2281,13 @@ class EditPage { $wgOut->wrapWikiMsg( "
    \n$1\n
    ", array( 'userinvalidcssjstitle', $this->mTitle->getSkinFromCssJsSubpage() ) ); } if ( $this->formtype !== 'preview' ) { - if ( $this->isCssSubpage ) + if ( $this->isCssSubpage ) { $wgOut->wrapWikiMsg( "
    \n$1\n
    ", array( 'usercssyoucanpreview' ) ); - if ( $this->isJsSubpage ) + } + + if ( $this->isJsSubpage ) { $wgOut->wrapWikiMsg( "
    \n$1\n
    ", array( 'userjsyoucanpreview' ) ); + } } } } @@ -2434,14 +2418,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'; @@ -2460,8 +2446,9 @@ class EditPage { HTML ); - if ( !$this->checkUnicodeCompliantBrowser() ) + if ( !$this->checkUnicodeCompliantBrowser() ) { $wgOut->addHTML( Html::hidden( 'safemode', '1' ) ); + } } protected function showFormAfterText() { @@ -2577,8 +2564,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 ) ); @@ -2639,7 +2627,7 @@ HTML $oldContent = null; } } else { - $oldContent = $this->getOriginalContent(); + $oldContent = $this->getCurrentContent(); } $textboxContent = $this->toEditContent( $this->textbox1 ); @@ -2883,10 +2871,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; } diff --git a/includes/Export.php b/includes/Export.php index e2b01b5397..45a5366e1a 100644 --- a/includes/Export.php +++ b/includes/Export.php @@ -636,29 +636,29 @@ class XmlDumpWriter { $out = " \n"; $out .= " " . Xml::element( 'id', null, strval( $row->rev_id ) ) . "\n"; - if( $row->rev_parent_id ) { + if( isset( $row->rev_parent_id ) && $row->rev_parent_id ) { $out .= " " . Xml::element( 'parentid', null, strval( $row->rev_parent_id ) ) . "\n"; } $out .= $this->writeTimestamp( $row->rev_timestamp ); - if ( $row->rev_deleted & Revision::DELETED_USER ) { + if ( isset( $row->rev_deleted ) && ( $row->rev_deleted & Revision::DELETED_USER ) ) { $out .= " " . Xml::element( 'contributor', array( 'deleted' => 'deleted' ) ) . "\n"; } else { $out .= $this->writeContributor( $row->rev_user, $row->rev_user_text ); } - if ( $row->rev_minor_edit ) { + if ( isset( $row->rev_minor_edit ) && $row->rev_minor_edit ) { $out .= " \n"; } - if ( $row->rev_deleted & Revision::DELETED_COMMENT ) { + if ( isset( $row->rev_deleted ) && ( $row->rev_deleted & Revision::DELETED_COMMENT ) ) { $out .= " " . Xml::element( 'comment', array( 'deleted' => 'deleted' ) ) . "\n"; } elseif ( $row->rev_comment != '' ) { $out .= " " . Xml::elementClean( 'comment', array(), strval( $row->rev_comment ) ) . "\n"; } $text = ''; - if ( $row->rev_deleted & Revision::DELETED_TEXT ) { + if ( isset( $row->rev_deleted ) && ( $row->rev_deleted & Revision::DELETED_TEXT ) ) { $out .= " " . Xml::element( 'text', array( 'deleted' => 'deleted' ) ) . "\n"; } elseif ( isset( $row->old_text ) ) { // Raw text from the database may have invalid chars @@ -673,7 +673,7 @@ class XmlDumpWriter { "" ) . "\n"; } - if ( $row->rev_sha1 && !( $row->rev_deleted & Revision::DELETED_TEXT ) ) { + if ( isset( $row->rev_sha1 ) && $row->rev_sha1 && !( $row->rev_deleted & Revision::DELETED_TEXT ) ) { $out .= " " . Xml::element('sha1', null, strval( $row->rev_sha1 ) ) . "\n"; } else { $out .= " \n"; diff --git a/includes/Html.php b/includes/Html.php index 5be67ab6d9..01dca6f92c 100644 --- a/includes/Html.php +++ b/includes/Html.php @@ -48,7 +48,7 @@ * @since 1.16 */ class Html { - # List of void elements from HTML5, section 8.1.2 as of 2011-08-12 + // List of void elements from HTML5, section 8.1.2 as of 2011-08-12 private static $voidElements = array( 'area', 'base', @@ -68,8 +68,8 @@ class Html { 'wbr', ); - # Boolean attributes, which may have the value omitted entirely. Manually - # collected from the HTML5 spec as of 2011-08-12. + // Boolean attributes, which may have the value omitted entirely. Manually + // collected from the HTML5 spec as of 2011-08-12. private static $boolAttribs = array( 'async', 'autofocus', @@ -97,7 +97,7 @@ class Html { 'selected', 'truespeed', 'typemustmatch', - # HTML5 Microdata + // HTML5 Microdata 'itemscope', ); @@ -139,7 +139,7 @@ class Html { $start = self::openElement( $element, $attribs ); if ( in_array( $element, self::$voidElements ) ) { if ( $wgWellFormedXml ) { - # Silly XML. + // Silly XML. return substr( $start, 0, -1 ) . ' />'; } return $start; @@ -160,8 +160,8 @@ class Html { */ public static function element( $element, $attribs = array(), $contents = '' ) { return self::rawElement( $element, $attribs, strtr( $contents, array( - # There's no point in escaping quotes, >, etc. in the contents of - # elements. + // There's no point in escaping quotes, >, etc. in the contents of + // elements. '&' => '&', '<' => '<' ) ) ); @@ -179,19 +179,19 @@ class Html { public static function openElement( $element, $attribs = array() ) { global $wgHtml5, $wgWellFormedXml; $attribs = (array)$attribs; - # This is not required in HTML5, but let's do it anyway, for - # consistency and better compression. + // This is not required in HTML5, but let's do it anyway, for + // consistency and better compression. $element = strtolower( $element ); - # In text/html, initial and tags can be omitted under - # pretty much any sane circumstances, if they have no attributes. See: - # + // In text/html, initial and tags can be omitted under + // pretty much any sane circumstances, if they have no attributes. See: + // if ( !$wgWellFormedXml && !$attribs && in_array( $element, array( 'html', 'head' ) ) ) { return ''; } - # Remove invalid input types + // Remove invalid input types if ( $element == 'input' ) { $validTypes = array( 'hidden', @@ -206,7 +206,7 @@ class Html { 'button', ); - # Allow more input types in HTML5 mode + // Allow more input types in HTML5 mode if( $wgHtml5 ) { $validTypes = array_merge( $validTypes, array( 'datetime', @@ -251,8 +251,8 @@ class Html { $element = strtolower( $element ); - # Reference: - # http://www.whatwg.org/specs/web-apps/current-work/multipage/syntax.html#optional-tags + // Reference: + // http://www.whatwg.org/specs/web-apps/current-work/multipage/syntax.html#optional-tags if ( !$wgWellFormedXml && in_array( $element, array( 'html', 'head', @@ -287,15 +287,15 @@ class Html { * @return array An array of attributes functionally identical to $attribs */ private static function dropDefaults( $element, $attribs ) { - # Don't bother doing anything if we aren't outputting HTML5; it's too - # much of a pain to maintain two sets of defaults. + // Don't bother doing anything if we aren't outputting HTML5; it's too + // much of a pain to maintain two sets of defaults. global $wgHtml5; if ( !$wgHtml5 ) { return $attribs; } - # Whenever altering this array, please provide a covering test case - # in HtmlTest::provideElementsWithAttributesHavingDefaultValues + // Whenever altering this array, please provide a covering test case + // in HtmlTest::provideElementsWithAttributesHavingDefaultValues static $attribDefaults = array( 'area' => array( 'shape' => 'rect' ), 'button' => array( @@ -320,8 +320,8 @@ class Html { 'keygen' => array( 'keytype' => 'rsa' ), 'link' => array( 'media' => 'all' ), 'menu' => array( 'type' => 'list' ), - # Note: the use of text/javascript here instead of other JavaScript - # MIME types follows the HTML5 spec. + // Note: the use of text/javascript here instead of other JavaScript + // MIME types follows the HTML5 spec. 'script' => array( 'type' => 'text/javascript' ), 'style' => array( 'media' => 'all', @@ -340,7 +340,7 @@ class Html { $value = strval( $value ); } - # Simple checks using $attribDefaults + // Simple checks using $attribDefaults if ( isset( $attribDefaults[$element][$lcattrib] ) && $attribDefaults[$element][$lcattrib] == $value ) { unset( $attribs[$attrib] ); @@ -351,7 +351,7 @@ class Html { } } - # More subtle checks + // More subtle checks if ( $element === 'link' && isset( $attribs['type'] ) && strval( $attribs['type'] ) == 'text/css' ) { unset( $attribs['type'] ); @@ -383,12 +383,12 @@ class Html { if ( in_array( 'multiple', $attribs ) || ( isset( $attribs['multiple'] ) && $attribs['multiple'] !== false ) ) { - # A multi-select + // A multi-select if ( strval( $attribs['size'] ) == '4' ) { unset( $attribs['size'] ); } } else { - # Single select + // Single select if ( strval( $attribs['size'] ) == '1' ) { unset( $attribs['size'] ); } @@ -447,29 +447,29 @@ class Html { continue; } - # For boolean attributes, support array( 'foo' ) instead of - # requiring array( 'foo' => 'meaningless' ). + // For boolean attributes, support array( 'foo' ) instead of + // requiring array( 'foo' => 'meaningless' ). if ( is_int( $key ) && in_array( strtolower( $value ), self::$boolAttribs ) ) { $key = $value; } - # Not technically required in HTML5, but required in XHTML 1.0, - # and we'd like consistency and better compression anyway. + // Not technically required in HTML5, but required in XHTML 1.0, + // and we'd like consistency and better compression anyway. $key = strtolower( $key ); - # Here we're blacklisting some HTML5-only attributes... + // Here we're blacklisting some HTML5-only attributes... if ( !$wgHtml5 && in_array( $key, self::$HTMLFiveOnlyAttribs ) ) { continue; } - # Bug 23769: Blacklist all form validation attributes for now. Current - # (June 2010) WebKit has no UI, so the form just refuses to submit - # without telling the user why, which is much worse than failing - # server-side validation. Opera is the only other implementation at - # this time, and has ugly UI, so just kill the feature entirely until - # we have at least one good implementation. + // Bug 23769: Blacklist all form validation attributes for now. Current + // (June 2010) WebKit has no UI, so the form just refuses to submit + // without telling the user why, which is much worse than failing + // server-side validation. Opera is the only other implementation at + // this time, and has ugly UI, so just kill the feature entirely until + // we have at least one good implementation. if ( in_array( $key, array( 'max', 'min', 'pattern', 'required', 'step' ) ) ) { continue; } @@ -485,7 +485,7 @@ class Html { 'rel', ); - # Specific features for attributes that allow a list of space-separated values + // Specific features for attributes that allow a list of space-separated values if ( in_array( $key, $spaceSeparatedListAttributes ) ) { // Apply some normalization and remove duplicates @@ -522,14 +522,14 @@ class Html { $value = implode( ' ', array_unique( $value ) ); } - # See the "Attributes" section in the HTML syntax part of HTML5, - # 9.1.2.3 as of 2009-08-10. Most attributes can have quotation - # marks omitted, but not all. (Although a literal " is not - # permitted, we don't check for that, since it will be escaped - # anyway.) + // See the "Attributes" section in the HTML syntax part of HTML5, + // 9.1.2.3 as of 2009-08-10. Most attributes can have quotation + // marks omitted, but not all. (Although a literal " is not + // permitted, we don't check for that, since it will be escaped + // anyway.) # - # See also research done on further characters that need to be - # escaped: http://code.google.com/p/html5lib/issues/detail?id=93 + // See also research done on further characters that need to be + // escaped: http://code.google.com/p/html5lib/issues/detail?id=93 $badChars = "\\x00- '=<>`/\x{00a0}\x{1680}\x{180e}\x{180F}\x{2000}\x{2001}" . "\x{2002}\x{2003}\x{2004}\x{2005}\x{2006}\x{2007}\x{2008}\x{2009}" . "\x{200A}\x{2028}\x{2029}\x{202F}\x{205F}\x{3000}"; @@ -541,9 +541,9 @@ class Html { } if ( in_array( $key, self::$boolAttribs ) ) { - # In XHTML 1.0 Transitional, the value needs to be equal to the - # key. In HTML5, we can leave the value empty instead. If we - # don't need well-formed XML, we can omit the = entirely. + // In XHTML 1.0 Transitional, the value needs to be equal to the + // key. In HTML5, we can leave the value empty instead. If we + // don't need well-formed XML, we can omit the = entirely. if ( !$wgWellFormedXml ) { $ret .= " $key"; } elseif ( $wgHtml5 ) { @@ -552,16 +552,16 @@ class Html { $ret .= " $key=\"$key\""; } } else { - # Apparently we need to entity-encode \n, \r, \t, although the - # spec doesn't mention that. Since we're doing strtr() anyway, - # and we don't need <> escaped here, we may as well not call - # htmlspecialchars(). - # @todo FIXME: Verify that we actually need to - # escape \n\r\t here, and explain why, exactly. + // Apparently we need to entity-encode \n, \r, \t, although the + // spec doesn't mention that. Since we're doing strtr() anyway, + // and we don't need <> escaped here, we may as well not call + // htmlspecialchars(). + // @todo FIXME: Verify that we actually need to + // escape \n\r\t here, and explain why, exactly. # - # We could call Sanitizer::encodeAttribute() for this, but we - # don't because we're stubborn and like our marginal savings on - # byte size from not having to encode unnecessary quotes. + // We could call Sanitizer::encodeAttribute() for this, but we + // don't because we're stubborn and like our marginal savings on + // byte size from not having to encode unnecessary quotes. $map = array( '&' => '&', '"' => '"', @@ -570,9 +570,9 @@ class Html { "\t" => ' ' ); if ( $wgWellFormedXml ) { - # This is allowed per spec: - # But reportedly it breaks some XML tools? - # @todo FIXME: Is this really true? + // This is allowed per spec: + // But reportedly it breaks some XML tools? + // @todo FIXME: Is this really true? $map['<'] = '<'; } $ret .= " $key=$quote" . strtr( $value, $map ) . $quote; diff --git a/includes/HttpFunctions.php b/includes/HttpFunctions.php index 32f77dcfab..e621f625ac 100644 --- a/includes/HttpFunctions.php +++ b/includes/HttpFunctions.php @@ -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 diff --git a/includes/Import.php b/includes/Import.php index 71498ac72e..201746661b 100644 --- a/includes/Import.php +++ b/includes/Import.php @@ -1397,6 +1397,7 @@ class WikiRevision { # @todo FIXME: Use original rev_id optionally (better for backups) # Insert the row $revision = new Revision( array( + 'title' => $this->title, 'page' => $pageId, 'content_model' => $this->getModel(), 'content_format' => $this->getFormat(), diff --git a/includes/Linker.php b/includes/Linker.php index b947f8f4e7..e5db232a51 100644 --- a/includes/Linker.php +++ b/includes/Linker.php @@ -2136,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 @@ -2153,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 ); @@ -2169,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 @@ -2187,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__ ); diff --git a/includes/MagicWord.php b/includes/MagicWord.php index 42791f57a5..6d2e1dca94 100644 --- a/includes/MagicWord.php +++ b/includes/MagicWord.php @@ -534,7 +534,7 @@ class MagicWord { * * @return string */ - function getVariableRegex() { + function getVariableRegex() { if ( $this->mVariableRegex == '' ) { $this->initRegex(); } diff --git a/includes/Message.php b/includes/Message.php index 2feaed2b71..5a4b810d1e 100644 --- a/includes/Message.php +++ b/includes/Message.php @@ -629,7 +629,8 @@ class Message { * @return string Wikitext parsed into HTML */ protected function parseText( $string ) { - return MessageCache::singleton()->parse( $string, $this->title, /*linestart*/true, $this->interface, $this->language )->getText(); + $out = MessageCache::singleton()->parse( $string, $this->title, /*linestart*/true, $this->interface, $this->language ); + return is_object( $out ) ? $out->getText() : $out; } /** diff --git a/includes/MimeMagic.php b/includes/MimeMagic.php index 88383d8f38..65a2a6fa79 100644 --- a/includes/MimeMagic.php +++ b/includes/MimeMagic.php @@ -433,7 +433,7 @@ class MimeMagic { $ext = explode( ' ', $ext ); $extension = strtolower( $extension ); - return in_array( $extension, $ext ); + return in_array( $extension, $ext ); } /** diff --git a/includes/OutputPage.php b/includes/OutputPage.php index 3578568651..ff83f700ad 100644 --- a/includes/OutputPage.php +++ b/includes/OutputPage.php @@ -2982,7 +2982,7 @@ $templates ); if ( $wgContLang->hasVariants() ) { $vars['wgUserVariant'] = $wgContLang->getPreferredVariant(); - } + } foreach ( $title->getRestrictionTypes() as $type ) { $vars['wgRestriction' . ucfirst( $type )] = $title->getRestrictions( $type ); } diff --git a/includes/RecentChange.php b/includes/RecentChange.php index debec69faf..2bdcab4031 100644 --- a/includes/RecentChange.php +++ b/includes/RecentChange.php @@ -125,7 +125,7 @@ class RecentChange { */ public static function newFromConds( $conds, $fname = __METHOD__ ) { $dbr = wfGetDB( DB_SLAVE ); - $row = $dbr->selectRow( 'recentchanges', '*', $conds, $fname ); + $row = $dbr->selectRow( 'recentchanges', self::selectFields(), $conds, $fname ); if ( $row !== false ) { return self::newFromRow( $row ); } else { @@ -133,6 +133,40 @@ class RecentChange { } } + /** + * Return the list of recentchanges fields that should be selected to create + * a new recentchanges object. + * @return array + */ + public static function selectFields() { + return array( + 'rc_id', + 'rc_timestamp', + 'rc_cur_time', + 'rc_user', + 'rc_user_text', + 'rc_namespace', + 'rc_title', + 'rc_comment', + 'rc_minor', + 'rc_bot', + 'rc_new', + 'rc_cur_id', + 'rc_this_oldid', + 'rc_last_oldid', + 'rc_type', + 'rc_patrolled', + 'rc_ip', + 'rc_old_len', + 'rc_new_len', + 'rc_deleted', + 'rc_logid', + 'rc_log_type', + 'rc_log_action', + 'rc_params', + ); + } + # Accessors /** @@ -154,7 +188,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 +220,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 +238,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 +262,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 +281,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 +302,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 +338,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 +359,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 +400,7 @@ class RecentChange { 'rc_patrolled' => 1 ), array( - 'rc_id' => $this->getAttribute('rc_id') + 'rc_id' => $this->getAttribute( 'rc_id' ) ), __METHOD__ ); @@ -392,7 +426,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 +445,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 +484,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 +503,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 +540,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 +569,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 +617,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 +628,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 +638,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 +679,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 +700,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 +710,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 +727,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 +784,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 +804,9 @@ class RecentChange { } } else { $ip = $wgRequest->getIP(); - if( !$ip ) + if ( !$ip ) { $ip = ''; + } } return $ip; } diff --git a/includes/Revision.php b/includes/Revision.php index 984da69206..fd356e12c8 100644 --- a/includes/Revision.php +++ b/includes/Revision.php @@ -52,7 +52,7 @@ class Revision implements IDBAccessObject { protected $mContentFormat; /** - * @var Content + * @var Content|null|bool */ protected $mContent; @@ -124,7 +124,7 @@ class Revision implements IDBAccessObject { * Returns null if no such revision can be found. * * $flags include: - * Revision::READ_LATEST : Select the data from the master + * Revision::READ_LATEST : Select the data from the master (since 1.20) * Revision::READ_LOCKING : Select & lock the data from the master * * @param $revId Integer @@ -178,6 +178,13 @@ class Revision implements IDBAccessObject { unset( $attribs['content_format'] ); } + if ( !isset( $attribs['title'] ) + && isset( $row->ar_namespace ) + && isset( $row->ar_title ) ) { + + $attribs['title'] = Title::makeTitle( $row->ar_namespace, $row->ar_title ); + } + if ( isset( $row->ar_text ) && !$row->ar_text_id ) { // Pre-1.5 ar_text row $attribs['text'] = self::getRevisionText( $row, 'ar_' ); @@ -600,15 +607,19 @@ class Revision implements IDBAccessObject { $this->mContent = $handler->unserializeContent( $this->mText ); } - // if we have a Title object, override mPage. Useful for testing and convenience. - if ( isset( $row['title'] ) ) { - $this->mTitle = $row['title']; - $this->mPage = $this->mTitle->getArticleID(); - } else { - $this->mTitle = null; // Load on demand if needed + // If we have a Title object, make sure it is consistent with mPage. + if ( $this->mTitle && $this->mTitle->exists() ) { + if ( $this->mPage === null ) { + // if the page ID wasn't known, set it now + $this->mPage = $this->mTitle->getArticleID(); + } elseif ( $this->mTitle->getArticleID() !== $this->mPage ) { + // Got different page IDs. This may be legit (e.g. during undeletion), + // but it seems worth mentioning it in the log. + wfDebug( "Page ID " . $this->mPage . " mismatches the ID " + . $this->mTitle->getArticleID() . " provided by the Title object." ); + } } - // @todo: XXX: really? we are about to create a revision. it will usually then be the current one. $this->mCurrent = false; // If we still have no length, see it we have the text to figure it out @@ -971,27 +982,34 @@ class Revision implements IDBAccessObject { } /** - * Gets the content object for the revision + * Gets the content object for the revision (or null on failure). + * + * Note that for mutable Content objects, each call to this method will return a + * fresh clone. * * @since 1.21 - * @return Content + * @return Content|null the Revision's content, or null on failure. */ protected function getContentInternal() { if( is_null( $this->mContent ) ) { // Revision is immutable. Load on demand: - - $handler = $this->getContentHandler(); - $format = $this->getContentFormat(); - if( is_null( $this->mText ) ) { - // Load text on demand: $this->mText = $this->loadText(); } - $this->mContent = is_null( $this->mText ) ? null : $handler->unserializeContent( $this->mText, $format ); + if ( $this->mText !== null && $this->mText !== false ) { + // Unserialize content + $handler = $this->getContentHandler(); + $format = $this->getContentFormat(); + + $this->mContent = $handler->unserializeContent( $this->mText, $format ); + } else { + $this->mContent = false; // negative caching! + } } - return $this->mContent->copy(); // NOTE: copy() will return $this for immutable content objects + // NOTE: copy() will return $this for immutable content objects + return $this->mContent ? $this->mContent->copy() : null; } /** @@ -1366,7 +1384,7 @@ class Revision implements IDBAccessObject { $content = $this->getContent( Revision::RAW ); - if ( !$content->isValid() ) { + if ( !$content || !$content->isValid() ) { $t = $title->getPrefixedDBkey(); throw new MWException( "Content of $t is not valid! Content model is $model" ); @@ -1386,7 +1404,11 @@ class Revision implements IDBAccessObject { * Lazy-load the revision's text. * Currently hardcoded to the 'text' table storage engine. * - * @return String +<<<<<<< HEAD + * @return String|boolean the revision text, or false on failure +======= + * @return String|bool the revision's text, or false on failure +>>>>>>> (Bug 41244) Gracefully handle failure to load text blob. */ protected function loadText() { wfProfileIn( __METHOD__ ); diff --git a/includes/Sanitizer.php b/includes/Sanitizer.php index 8919f10ad6..5aa0545ba0 100644 --- a/includes/Sanitizer.php +++ b/includes/Sanitizer.php @@ -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 @@ -912,7 +916,7 @@ class Sanitizer { // Reject problematic keywords and control characters if ( preg_match( '/[\000-\010\016-\037\177]/', $value ) ) { return '/* invalid control char */'; - } elseif ( preg_match( '! expression | filter\s*: | accelerator\s*: | url\s*\( | image\s*\( !ix', $value ) ) { + } elseif ( preg_match( '! expression | filter\s*: | accelerator\s*: | url\s*\( | image\s*\( | image-set\s*\( !ix', $value ) ) { return '/* insecure input */'; } return $value; diff --git a/includes/Skin.php b/includes/Skin.php index 24d48bc44c..4889863710 100644 --- a/includes/Skin.php +++ b/includes/Skin.php @@ -73,7 +73,7 @@ abstract class Skin extends ContextSource { return $wgValidSkinNames; } - /** + /** * Fetch the skinname messages for available skins. * @return array of strings */ @@ -1132,7 +1132,23 @@ abstract class Skin extends ContextSource { } /** - * Build an array that represents the sidebar(s), the navigation bar among them + * Build an array that represents the sidebar(s), the navigation bar among them. + * + * BaseTemplate::getSidebar can be used to simplify the format and id generation in new skins. + * + * The format of the returned array is array( heading => content, ... ), where: + * - heading is the heading of a navigation portlet. It is either: + * - magic string to be handled by the skins ('SEARCH' / 'LANGUAGES' / 'TOOLBOX' / ...) + * - a message name (e.g. 'navigation'), the message should be HTML-escaped by the skin + * - plain text, which should be HTML-escaped by the skin + * - content is the contents of the portlet. It is either: + * - HTML text (
    • ...
    • ...
    ) + * - array of link data in a format accepted by BaseTemplate::makeListItem() + * - (for a magic string as a key, any value) + * + * Note that extensions can control the sidebar contents using the SkinBuildSidebar hook + * and can technically insert anything in here; skin creators are expected to handle + * values described above. * * @return array */ diff --git a/includes/SkinTemplate.php b/includes/SkinTemplate.php index 5a32d47138..dcc37d75bc 100644 --- a/includes/SkinTemplate.php +++ b/includes/SkinTemplate.php @@ -1177,11 +1177,6 @@ class SkinTemplate extends Skin { ); } - $nav_urls['info'] = array( - 'text' => $this->msg( 'pageinfo-toolboxlink' )->text(), - 'href' => $out->getTitle()->getLocalURL( "action=info" ) - ); - // Use the copy of revision ID in case this undocumented, shady hook tries to mess with internals wfRunHooks( 'SkinTemplateBuildNavUrlsNav_urlsAfterPermalink', array( &$this, &$nav_urls, &$revid, &$revid ) ); @@ -1191,6 +1186,12 @@ class SkinTemplate extends Skin { $nav_urls['whatlinkshere'] = array( 'href' => SpecialPage::getTitleFor( 'Whatlinkshere', $this->thispage )->getLocalUrl() ); + + $nav_urls['info'] = array( + 'text' => $this->msg( 'pageinfo-toolboxlink' )->text(), + 'href' => $this->getTitle()->getLocalURL( "action=info" ) + ); + if ( $this->getTitle()->getArticleID() ) { $nav_urls['recentchangeslinked'] = array( 'href' => SpecialPage::getTitleFor( 'Recentchangeslinked', $this->thispage )->getLocalUrl() diff --git a/includes/SpecialPage.php b/includes/SpecialPage.php index 9442869774..67aa2b33f4 100644 --- a/includes/SpecialPage.php +++ b/includes/SpecialPage.php @@ -513,6 +513,19 @@ class SpecialPage { return false; } + /** + * Is this page cached? + * Expensive pages are cached or disabled in miser mode. + * Used by QueryPage and subclasses, moved here so that + * Special:SpecialPages can safely call it for all special pages. + * + * @return Boolean + * @since 1.21 + */ + public function isCached() { + return false; + } + /** * Can be overridden by subclasses with more complicated permissions * schemes. @@ -1017,14 +1030,12 @@ abstract class RedirectSpecialPage extends UnlistedSpecialPage { if ( $redirect instanceof Title ) { $url = $redirect->getFullUrl( $query ); $this->getOutput()->redirect( $url ); - wfProfileOut( __METHOD__ ); return $redirect; // Redirect to index.php with query parameters } elseif ( $redirect === true ) { global $wgScript; $url = $wgScript . '?' . wfArrayToCGI( $query ); $this->getOutput()->redirect( $url ); - wfProfileOut( __METHOD__ ); return $redirect; } else { $class = __CLASS__; @@ -1209,7 +1220,7 @@ abstract class RedirectSpecialArticle extends RedirectSpecialPage { 'ctype', 'maxage', 'smaxage', ); - wfRunHooks( "RedirectSpecialArticleRedirectParams", array(&$redirectParams) ); + wfRunHooks( "RedirectSpecialArticleRedirectParams", array( &$redirectParams ) ); $this->mAllowedRedirectParams = $redirectParams; } } diff --git a/includes/Title.php b/includes/Title.php index b1569e2837..0f02dc7939 100644 --- a/includes/Title.php +++ b/includes/Title.php @@ -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 @@ -3816,6 +3816,7 @@ class Title { $newid = $redirectArticle->insertOn( $dbw ); if ( $newid ) { // sanity $redirectRevision = new Revision( array( + 'title' => $this, // for determining the default content model 'page' => $newid, 'comment' => $comment, 'content' => $redirectContent ) ); @@ -3980,7 +3981,7 @@ class Title { $content = $rev->getContent(); # Does the redirect point to the source? # Or is it a broken self-redirect, usually caused by namespace collisions? - $redirTitle = $content->getRedirectTarget(); + $redirTitle = $content ? $content->getRedirectTarget() : null; if ( $redirTitle ) { if ( $redirTitle->getPrefixedDBkey() != $this->getPrefixedDBkey() && @@ -4474,7 +4475,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() { @@ -4701,8 +4702,6 @@ class Title { $contentHandler = ContentHandler::getForTitle( $this ); $pageLang = $contentHandler->getPageLanguage( $this ); - // Hook at the end because we don't want to override the above stuff - wfRunHooks( 'PageContentLanguage', array( $this, &$pageLang, $wgLang ) ); return wfGetLangObj( $pageLang ); } diff --git a/includes/User.php b/includes/User.php index e210eba6cf..0aa613afca 100644 --- a/includes/User.php +++ b/includes/User.php @@ -1102,10 +1102,10 @@ class User { } if ( is_array( $data ) ) { - if ( is_array( $data['user_groups'] ) ) { + if ( isset( $data['user_groups'] ) && is_array( $data['user_groups'] ) ) { $this->mGroups = $data['user_groups']; } - if ( is_array( $data['user_properties'] ) ) { + if ( isset( $data['user_properties'] ) && is_array( $data['user_properties'] ) ) { $this->loadOptions( $data['user_properties'] ); } } @@ -1169,13 +1169,17 @@ class User { } $newGroups = array_merge( $oldGroups, $toPromote ); // all groups - $log = new LogPage( 'rights', $wgAutopromoteOnceLogInRC /* in RC? */ ); - $log->addEntry( 'autopromote', - $this->getUserPage(), - '', // no comment - // These group names are "list to texted"-ed in class LogPage. - array( implode( ', ', $oldGroups ), implode( ', ', $newGroups ) ) - ); + $logEntry = new ManualLogEntry( 'rights', 'autopromote' ); + $logEntry->setPerformer( $this ); + $logEntry->setTarget( $this->getUserPage() ); + $logEntry->setParameters( array( + '4::oldgroups' => $oldGroups, + '5::newgroups' => $newGroups, + ) ); + $logid = $logEntry->insert(); + if ( $wgAutopromoteOnceLogInRC ) { + $logEntry->publish( $logid ); + } } } return $toPromote; @@ -1216,6 +1220,14 @@ class User { public static function getDefaultOptions() { global $wgNamespacesToBeSearchedDefault, $wgDefaultUserOptions, $wgContLang, $wgDefaultSkin; + static $defOpt = null; + if ( !defined( 'MW_PHPUNIT_TEST' ) && $defOpt !== null ) { + // Disabling this for the unit tests, as they rely on being able to change $wgContLang + // mid-request and see that change reflected in the return value of this function. + // Which is insane and would never happen during normal MW operation + return $defOpt; + } + $defOpt = $wgDefaultUserOptions; # default language setting $defOpt['variant'] = $wgContLang->getCode(); @@ -1225,12 +1237,6 @@ class User { } $defOpt['skin'] = $wgDefaultSkin; - // FIXME: Ideally we'd cache the results of this function so the hook is only run once, - // but that breaks the parser tests because they rely on being able to change $wgContLang - // mid-request and see that change reflected in the return value of this function. - // Which is insane and would never happen during normal MW operation, but is also not - // likely to get fixed unless and until we context-ify everything. - // See also https://www.mediawiki.org/wiki/Special:Code/MediaWiki/101488#c25275 wfRunHooks( 'UserGetDefaultOptions', array( &$defOpt ) ); return $defOpt; @@ -2213,13 +2219,6 @@ class User { global $wgHiddenPrefs; $this->loadOptions(); - if ( is_null( $this->mOptions ) ) { - if($defaultOverride != '') { - return $defaultOverride; - } - $this->mOptions = User::getDefaultOptions(); - } - # We want 'disabled' preferences to always behave as the default value for # users, even if they have set the option explicitly in their settings (ie they # set it, and then it was disabled removing their ability to change it). But @@ -2295,15 +2294,11 @@ class User { * @param $val mixed New value to set */ public function setOption( $oname, $val ) { - $this->load(); $this->loadOptions(); // Explicitly NULL values should refer to defaults if( is_null( $val ) ) { - $defaultOption = self::getDefaultOption( $oname ); - if( !is_null( $defaultOption ) ) { - $val = $defaultOption; - } + $val = self::getDefaultOption( $oname ); } $this->mOptions[$oname] = $val; @@ -2362,7 +2357,7 @@ class User { $this->mRights = self::getGroupPermissions( $this->getEffectiveGroups() ); wfRunHooks( 'UserGetRights', array( $this, &$this->mRights ) ); // Force reindexation of rights when a hook has unset one of them - $this->mRights = array_values( $this->mRights ); + $this->mRights = array_values( array_unique( $this->mRights ) ); } return $this->mRights; } @@ -2394,6 +2389,8 @@ class User { ) ); # Hook for additional groups wfRunHooks( 'UserEffectiveGroups', array( &$this, &$this->mEffectiveGroups ) ); + // Force reindexation of groups when a hook has unset one of them + $this->mEffectiveGroups = array_values( array_unique( $this->mEffectiveGroups ) ); wfProfileOut( __METHOD__ ); } return $this->mEffectiveGroups; @@ -2474,7 +2471,7 @@ class User { $count = $this->initEditCount(); } wfProfileOut( __METHOD__ ); - $this->mEditCount = $count; + $this->mEditCount = intval( $count ); } return $this->mEditCount; } else { @@ -3984,7 +3981,7 @@ class User { // Pull from a slave to be less cruel to servers // Accuracy isn't the point anyway here $dbr = wfGetDB( DB_SLAVE ); - $count = $dbr->selectField( + $count = (int) $dbr->selectField( 'revision', 'COUNT(rev_user)', array( 'rev_user' => $this->getId() ), diff --git a/includes/UserMailer.php b/includes/UserMailer.php index 9830f69578..b9ce9e0574 100644 --- a/includes/UserMailer.php +++ b/includes/UserMailer.php @@ -273,7 +273,7 @@ class UserMailer { } wfRestoreWarnings(); return Status::newGood(); - } else { + } else { # # PHP mail() # diff --git a/includes/WebRequest.php b/includes/WebRequest.php index aeac69420a..e251ac5bb5 100644 --- a/includes/WebRequest.php +++ b/includes/WebRequest.php @@ -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 */ diff --git a/includes/Wiki.php b/includes/Wiki.php index 7a6b37d9fd..d4840cc22e 100644 --- a/includes/Wiki.php +++ b/includes/Wiki.php @@ -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(); diff --git a/includes/WikiPage.php b/includes/WikiPage.php index c148a5f14d..a4bc6ee824 100644 --- a/includes/WikiPage.php +++ b/includes/WikiPage.php @@ -1237,8 +1237,8 @@ class WikiPage extends Page implements IDBAccessObject { wfProfileIn( __METHOD__ ); $content = $revision->getContent(); - $len = $content->getSize(); - $rt = $content->getUltimateRedirectTarget(); + $len = $content ? $content->getSize() : 0; + $rt = $content ? $content->getUltimateRedirectTarget() : null; $conditions = array( 'page_id' => $this->getId() ); @@ -1469,11 +1469,6 @@ class WikiPage extends Page implements IDBAccessObject { // Bug 30711: always use current version when adding a new section if ( is_null( $edittime ) || $section == 'new' ) { $oldContent = $this->getContent(); - if ( ! $oldContent ) { - wfDebug( __METHOD__ . ": no page text\n" ); - wfProfileOut( __METHOD__ ); - return null; - } } else { $dbw = wfGetDB( DB_MASTER ); $rev = Revision::loadFromTimestamp( $dbw, $this->mTitle, $edittime ); @@ -1488,6 +1483,13 @@ class WikiPage extends Page implements IDBAccessObject { $oldContent = $rev->getContent(); } + if ( ! $oldContent ) { + wfDebug( __METHOD__ . ": no page text\n" ); + wfProfileOut( __METHOD__ ); + return null; + } + + //FIXME: $oldContent might be null? $newContent = $oldContent->replaceSection( $section, $sectionContent, $sectionTitle ); } @@ -1708,6 +1710,7 @@ class WikiPage extends Page implements IDBAccessObject { $revision = new Revision( array( 'page' => $this->getId(), + 'title' => $this->getTitle(), // for determining the default content model 'comment' => $summary, 'minor_edit' => $isminor, 'text' => $serialized, @@ -1835,6 +1838,7 @@ class WikiPage extends Page implements IDBAccessObject { # Save the revision text... $revision = new Revision( array( 'page' => $newid, + 'title' => $this->getTitle(), // for determining the default content model 'comment' => $summary, 'minor_edit' => $isminor, 'text' => $serialized, @@ -1850,6 +1854,10 @@ class WikiPage extends Page implements IDBAccessObject { # Bug 37225: use accessor to get the text as Revision may trim it $content = $revision->getContent(); // sanity; get normalized version + if ( $content ) { + $newsize = $content->getSize(); + } + # Update the page record with revision data $this->updateRevisionOn( $dbw, $revision, 0 ); @@ -1862,7 +1870,7 @@ class WikiPage extends Page implements IDBAccessObject { $this->mTitle->getUserPermissionsErrors( 'autopatrol', $user ) ); # Add RC row to the DB $rc = RecentChange::notifyNew( $now, $this->mTitle, $isminor, $user, $summary, $bot, - '', $content->getSize(), $revisionId, $patrolled ); + '', $newsize, $revisionId, $patrolled ); # Log auto-patrolled edits if ( $patrolled ) { @@ -1954,7 +1962,7 @@ class WikiPage extends Page implements IDBAccessObject { * @since 1.21 */ public function prepareContentForEdit( Content $content, $revid = null, User $user = null, $serialization_format = null ) { - global $wgParser, $wgContLang, $wgUser; + global $wgContLang, $wgUser; $user = is_null( $user ) ? $wgUser : $user; //XXX: check $user->getId() here??? @@ -1975,23 +1983,21 @@ class WikiPage extends Page implements IDBAccessObject { $edit = (object)array(); $edit->revid = $revid; - $edit->pstContent = $content->preSaveTransform( $this->mTitle, $user, $popts ); - $edit->pst = $edit->pstContent->serialize( $serialization_format ); #XXX: do we need this?? - $edit->format = $serialization_format; + $edit->pstContent = $content ? $content->preSaveTransform( $this->mTitle, $user, $popts ) : null; + $edit->format = $serialization_format; $edit->popts = $this->makeParserOptions( 'canonical' ); - - $edit->output = $edit->pstContent->getParserOutput( $this->mTitle, $revid, $edit->popts ); + $edit->output = $edit->pstContent ? $edit->pstContent->getParserOutput( $this->mTitle, $revid, $edit->popts ) : null; $edit->newContent = $content; $edit->oldContent = $this->getContent( Revision::RAW ); #NOTE: B/C for hooks! don't use these fields! - $edit->newText = ContentHandler::getContentText( $edit->newContent ); + $edit->newText = $edit->newContent ? ContentHandler::getContentText( $edit->newContent ) : ''; $edit->oldText = $edit->oldContent ? ContentHandler::getContentText( $edit->oldContent ) : ''; + $edit->pst = $edit->pstContent ? $edit->pstContent->serialize( $serialization_format ) : ''; $this->mPreparedEdit = $edit; - return $edit; } @@ -2036,8 +2042,10 @@ class WikiPage extends Page implements IDBAccessObject { } # Update the links tables and other secondary data - $updates = $content->getSecondaryDataUpdates( $this->getTitle(), null, true, $editInfo->output ); - DataUpdate::runUpdates( $updates ); + if ( $content ) { + $updates = $content->getSecondaryDataUpdates( $this->getTitle(), null, true, $editInfo->output ); + DataUpdate::runUpdates( $updates ); + } wfRunHooks( 'ArticleEditUpdates', array( &$this, &$editInfo, $options['changed'] ) ); @@ -2109,7 +2117,7 @@ class WikiPage extends Page implements IDBAccessObject { if ( $this->mTitle->getNamespace() == NS_MEDIAWIKI ) { #XXX: could skip pseudo-messages like js/css here, based on content model. - $msgtext = $content->getWikitextForTransclusion(); + $msgtext = $content ? $content->getWikitextForTransclusion() : null; if ( $msgtext === false || $msgtext === null ) $msgtext = ''; MessageCache::singleton()->replace( $shortTitle, $msgtext ); @@ -2161,6 +2169,7 @@ class WikiPage extends Page implements IDBAccessObject { $dbw = wfGetDB( DB_MASTER ); $revision = new Revision( array( + 'title' => $this->getTitle(), // for determining the default content model 'page' => $this->getId(), 'text' => $serialized, 'length' => $content->getSize(), diff --git a/includes/Xml.php b/includes/Xml.php index 2f8ba0fe39..67f365848d 100644 --- a/includes/Xml.php +++ b/includes/Xml.php @@ -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 diff --git a/includes/ZhConversion.php b/includes/ZhConversion.php index 0cbbad93e7..b1ccbe6315 100644 --- a/includes/ZhConversion.php +++ b/includes/ZhConversion.php @@ -9,36 +9,66 @@ */ $zh2Hant = array( +'㐽' => '偑', +'㑇' => '㑳', +'㑈' => '倲', +'㑔' => '㑯', '㑩' => '儸', '㓥' => '劏', '㔉' => '劚', '㖊' => '噚', '㖞' => '喎', +'㘎' => '㘚', +'㚯' => '㜄', +'㛀' => '媰', '㛟' => '𡞵', '㛠' => '𡢃', +'㛣' => '㜏', +'㛤' => '孋', '㛿' => '𡠹', '㟆' => '㠏', +'㟜' => '𡾱', +'㤘' => '㥮', +'㧏' => '掆', +'㧐' => '㩳', '㧑' => '撝', '㧟' => '擓', +'㧰' => '擽', '㨫' => '㩜', +'㭎' => '棡', +'㭏' => '椲', +'㭣' => '𣙎', +'㭤' => '樢', +'㭴' => '樫', '㱩' => '殰', '㱮' => '殨', '㲿' => '瀇', +'㳔' => '濧', +'㳕' => '灡', '㳠' => '澾', +'㳡' => '濄', +'㳢' => '𣾷', +'㳽' => '瀰', '㶉' => '鸂', '㶶' => '燶', '㶽' => '煱', '㺍' => '獱', +'㻅' => '璯', '㻏' => '𤫩', '㻘' => '𤪺', +'䀥' => '䁻', '䁖' => '瞜', +'䂵' => '碽', '䅉' => '稏', +'䅪' => '𥢢', '䇲' => '筴', +'䉤' => '籔', '䌶' => '䊷', '䌷' => '紬', '䌸' => '縳', '䌹' => '絅', '䌺' => '䋙', +'䌻' => '䋚', '䌼' => '綐', '䌽' => '綵', '䌾' => '䋻', @@ -48,24 +78,34 @@ $zh2Hant = array( '䓕' => '薳', '䗖' => '螮', '䘛' => '𧝞', +'䘞' => '𧜗', '䙊' => '𧜵', +'䙌' => '䙡', '䙓' => '襬', '䜣' => '訢', '䜥' => '𧩙', -'䜧' => '譅', +'䜧' => '䜀', +'䜩' => '讌', '䝙' => '貙', '䞌' => '𧵳', '䞍' => '䝼', +'䞎' => '𧶧', '䞐' => '賰', +'䟢' => '躎', +'䢀' => '𨊰', +'䢁' => '𨊸', '䢂' => '𨋢', '䥺' => '釾', '䥽' => '鏺', +'䥾' => '䥱', '䥿' => '𨯅', '䦀' => '𨦫', '䦁' => '𨧜', +'䦂' => '䥇', '䦃' => '鐯', '䦅' => '鐥', -'䩄' => '靦', +'䦶' => '䦛', +'䦷' => '䦟', '䭪' => '𩞯', '䯃' => '𩣑', '䯄' => '騧', @@ -136,6 +176,7 @@ $zh2Hant = array( '伞' => '傘', '伟' => '偉', '传' => '傳', +'伡' => '俥', '伣' => '俔', '伤' => '傷', '伥' => '倀', @@ -217,6 +258,7 @@ $zh2Hant = array( '刭' => '剄', '刹' => '剎', '刽' => '劊', +'刾' => '㓨', '刿' => '劌', '剀' => '剴', '剂' => '劑', @@ -321,6 +363,8 @@ $zh2Hant = array( '啬' => '嗇', '啭' => '囀', '啮' => '嚙', +'啯' => '嘓', +'啰' => '囉', '啴' => '嘽', '啸' => '嘯', '喷' => '噴', @@ -410,6 +454,7 @@ $zh2Hant = array( '婵' => '嬋', '婶' => '嬸', '媪' => '媼', +'媭' => '嬃', '嫒' => '嬡', '嫔' => '嬪', '嫱' => '嬙', @@ -513,7 +558,9 @@ $zh2Hant = array( '归' => '歸', '当' => '當', '录' => '錄', +'彟' => '彠', '彦' => '彥', +'彨' => '彲', '彻' => '徹', '径' => '徑', '徕' => '徠', @@ -648,6 +695,7 @@ $zh2Hant = array( '攒' => '攢', '敌' => '敵', '敛' => '斂', +'敩' => '斆', '数' => '數', '斋' => '齋', '斓' => '斕', @@ -719,6 +767,7 @@ $zh2Hant = array( '桧' => '檜', '桨' => '槳', '桩' => '樁', +'桪' => '樳', '梦' => '夢', '梼' => '檮', '梾' => '棶', @@ -727,9 +776,12 @@ $zh2Hant = array( '棁' => '梲', '棂' => '欞', '椁' => '槨', +'椝' => '槼', '椟' => '櫝', '椠' => '槧', +'椢' => '槶', '椤' => '欏', +'椫' => '樿', '椭' => '橢', '楼' => '樓', '榄' => '欖', @@ -783,6 +835,7 @@ $zh2Hant = array( '沥' => '瀝', '沦' => '淪', '沧' => '滄', +'沨' => '渢', '沩' => '溈', '沪' => '滬', '泞' => '濘', @@ -813,6 +866,7 @@ $zh2Hant = array( '浒' => '滸', '浓' => '濃', '浔' => '潯', +'浕' => '濜', '涂' => '塗', '涛' => '濤', '涝' => '澇', @@ -820,6 +874,7 @@ $zh2Hant = array( '涟' => '漣', '涠' => '潿', '涡' => '渦', +'涢' => '溳', '涣' => '渙', '涤' => '滌', '润' => '潤', @@ -833,7 +888,6 @@ $zh2Hant = array( '渐' => '漸', '渑' => '澠', '渔' => '漁', -'渖' => '瀋', '渗' => '滲', '温' => '溫', '湾' => '灣', @@ -841,6 +895,7 @@ $zh2Hant = array( '溃' => '潰', '溅' => '濺', '溆' => '漵', +'溇' => '漊', '滗' => '潷', '滚' => '滾', '滞' => '滯', @@ -861,6 +916,7 @@ $zh2Hant = array( '潍' => '濰', '潜' => '潛', '潴' => '瀦', +'澛' => '瀂', '澜' => '瀾', '濑' => '瀨', '濒' => '瀕', @@ -872,7 +928,6 @@ $zh2Hant = array( '灿' => '燦', '炀' => '煬', '炉' => '爐', -'炖' => '燉', '炜' => '煒', '炝' => '熗', '点' => '點', @@ -1014,12 +1069,13 @@ $zh2Hant = array( '硖' => '硤', '硗' => '磽', '硙' => '磑', +'硚' => '礄', '确' => '確', +'硵' => '磠', '硷' => '礆', '碍' => '礙', '碛' => '磧', '碜' => '磣', -'碱' => '鹼', '礼' => '禮', '祃' => '禡', '祎' => '禕', @@ -1081,6 +1137,7 @@ $zh2Hant = array( '篑' => '簣', '篓' => '簍', '篮' => '籃', +'篯' => '籛', '篱' => '籬', '簖' => '籪', '籁' => '籟', @@ -1256,6 +1313,8 @@ $zh2Hant = array( '羟' => '羥', '羡' => '羨', '翘' => '翹', +'翙' => '翽', +'翚' => '翬', '耢' => '耮', '耧' => '耬', '耸' => '聳', @@ -1295,6 +1354,7 @@ $zh2Hant = array( '脶' => '腡', '脸' => '臉', '腊' => '臘', +'腘' => '膕', '腭' => '齶', '腻' => '膩', '腼' => '靦', @@ -1337,6 +1397,7 @@ $zh2Hant = array( '荚' => '莢', '荛' => '蕘', '荜' => '蓽', +'荝' => '萴', '荞' => '蕎', '荟' => '薈', '荠' => '薺', @@ -1405,6 +1466,7 @@ $zh2Hant = array( '蚀' => '蝕', '蚁' => '蟻', '蚂' => '螞', +'蚃' => '蠁', '蚕' => '蠶', '蚬' => '蜆', '蛊' => '蠱', @@ -1445,9 +1507,10 @@ $zh2Hant = array( '裢' => '褳', '裣' => '襝', '裤' => '褲', -'裥' => '襇', +'裥' => '襉', '褛' => '褸', '褴' => '襤', +'襕' => '襴', '见' => '見', '观' => '觀', '觃' => '覎', @@ -1469,6 +1532,7 @@ $zh2Hant = array( '触' => '觸', '觯' => '觶', '訚' => '誾', +'詟' => '讋', '誉' => '譽', '誊' => '謄', '讠' => '訁', @@ -2209,6 +2273,7 @@ $zh2Hant = array( '颠' => '顛', '颡' => '顙', '颢' => '顥', +'颣' => '纇', '颤' => '顫', '颥' => '顬', '颦' => '顰', @@ -2344,6 +2409,7 @@ $zh2Hant = array( '髋' => '髖', '髌' => '髕', '鬓' => '鬢', +'鬶' => '鬹', '魇' => '魘', '魉' => '魎', '鱼' => '魚', @@ -2404,7 +2470,6 @@ $zh2Hant = array( '鲳' => '鯧', '鲴' => '鯝', '鲵' => '鯢', -'鲶' => '鯰', '鲷' => '鯛', '鲸' => '鯨', '鲹' => '鰺', @@ -2570,9 +2635,144 @@ $zh2Hant = array( '龚' => '龔', '龛' => '龕', '龟' => '龜', +'𠆲' => '儣', +'𠆿' => '𠌥', +'𠉂' => '㒓', +'𠉗' => '𠏢', +'𠚳' => '𠠎', +'𠛅' => '剾', +'𠛆' => '𠞆', '𠮶' => '嗰', +'𠯟' => '哯', +'𠯠' => '噅', +'𠲥' => '𡅏', +'𠴢' => '𡄔', +'𠵸' => '𡄣', +'𠵾' => '㗲', +'𡋀' => '𡓾', +'𡋗' => '𡑭', '𡒄' => '壈', +'𡝠' => '㜷', +'𡞱' => '㜢', +'𡭜' => '𡮉', +'𡭬' => '𡮣', +'𡶴' => '嵼', +'𢋈' => '㢝', +'𢘝' => '𢣚', +'𢘞' => '𢣭', +'𢙓' => '懀', +'𢛯' => '㦎', +'𢫊' => '𢷮', +'𢫞' => '𢶫', +'𢫬' => '摋', +'𢬦' => '𢹿', +'𢭏' => '擣', +'𢽾' => '斅', +'𣆐' => '曥', +'𣍨' => '𦢈', +'𣍯' => '腪', +'𣍰' => '脥', +'𣎑' => '臗', +'𣐤' => '欍', +'𣑶' => '𣠲', +'𣗋' => '欓', +'𣘓' => '𣞻', +'𣘴' => '檭', +'𣘷' => '𣝕', +'𣭤' => '𣯴', +'𣶩' => '澅', +'𣶫' => '𣿉', +'𣸣' => '濆', +'𣺼' => '灙', +'𣺽' => '𤁣', +'𣽷' => '瀃', +'𤆡' => '熓', +'𤇃' => '爄', +'𤇄' => '熌', +'𤈶' => '熉', +'𤈷' => '㷿', +'𤊀' => '𤒎', +'𤋏' => '熡', +'𤞤' => '玁', +'𤠋' => '㺏', +'𤦀' => '瓕', +'𤳄' => '𤳸', +'𤶧' => '𤸫', +'𤽯' => '㿧', +'𤾀' => '皟', +'𥅘' => '𥌃', +'𥅴' => '䀹', +'𥆧' => '瞤', +'𥇢' => '䁪', +'𥐟' => '礒', +'𥐯' => '𥖅', +'𥐰' => '𥕥', +'𥐻' => '碙', +'𥧂' => '𥨐', +'𥬀' => '䉙', +'𥬞' => '籋', +'𥬠' => '篘', +'𥭉' => '𥵊', +'𥮋' => '𥸠', +'𥮜' => '䉲', +'𥱔' => '𥵃', +'𥹥' => '𥼽', +'𥺅' => '䊭', +'𥺇' => '𥽖', +'𦈈' => '𥿊', +'𦈉' => '緷', +'𦈋' => '綇', +'𦈌' => '綀', +'𦈎' => '繟', +'𦈏' => '緍', +'𦈐' => '縺', +'𦈑' => '緸', +'𦈒' => '𦂅', +'𦈓' => '䋿', +'𦈔' => '縎', +'𦈕' => '緰', '𦈖' => '䌈', +'𦈗' => '𦃄', +'𦈘' => '䌋', +'𦈙' => '䌰', +'𦈚' => '縬', +'𦈛' => '繓', +'𦈜' => '䌖', +'𦈝' => '繏', +'𦈞' => '䌟', +'𦈟' => '䌝', +'𦈠' => '䌥', +'𦈡' => '繻', +'𦛨' => '朥', +'𦝼' => '膢', +'𦟗' => '𦣎', +'𦨩' => '𦪽', +'𦰴' => '䕳', +'𧉞' => '䗿', +'𧒭' => '𧔥', +'𧮪' => '詀', +'𧳕' => '𧳟', +'𧹑' => '䞈', +'𧹓' => '𧶔', +'𧹕' => '䝻', +'𧹖' => '賟', +'𧹗' => '贃', +'𧿈' => '𨇁', +'𨀱' => '𨄣', +'𨁴' => '𨅍', +'𨂺' => '𨈊', +'𨄄' => '𨈌', +'𨅫' => '𨇞', +'𨅬' => '躝', +'𨉗' => '軉', +'𨐅' => '軗', +'𨐆' => '𨊻', +'𨐇' => '𨏠', +'𨐈' => '輄', +'𨐉' => '𨎮', +'𨐊' => '𨏥', +'𨑹' => '䢨', +'𨤰' => '𨤻', '𨰾' => '鎷', '𨰿' => '釳', '𨱀' => '𨥛', @@ -2581,6 +2781,7 @@ $zh2Hant = array( '𨱃' => '鈲', '𨱄' => '鈯', '𨱅' => '鉁', +'𨱆' => '龯', '𨱇' => '銶', '𨱈' => '鋉', '𨱉' => '鍄', @@ -2591,12 +2792,28 @@ $zh2Hant = array( '𨱎' => '鍮', '𨱏' => '鎝', '𨱐' => '𨫒', +'𨱑' => '鐄', '𨱒' => '鏉', '𨱓' => '鐎', '𨱔' => '鐏', '𨱕' => '𨮂', +'𨱖' => '䥩', +'𨷿' => '䦳', +'𨸀' => '𨳕', +'𨸁' => '𨳑', '𨸂' => '閍', '𨸃' => '閐', +'𨸄' => '䦘', +'𨸅' => '𨴗', +'𨸆' => '𨵩', +'𨸇' => '𨵸', +'𨸉' => '𨶀', +'𨸊' => '𨶏', +'𨸋' => '𨶲', +'𨸌' => '𨶮', +'𨸎' => '𨷲', +'𨸘' => '𨽏', +'𨸟' => '䧢', '𩏼' => '䪏', '𩏽' => '𩏪', '𩏾' => '𩎢', @@ -2617,12 +2834,22 @@ $zh2Hant = array( '𩙮' => '䬘', '𩙯' => '䬝', '𩙰' => '𩙈', +'𩟿' => '𩚛', +'𩠀' => '𩚥', +'𩠁' => '𩚵', +'𩠂' => '𩛆', +'𩠃' => '𩛩', '𩠅' => '𩟐', '𩠆' => '𩜦', '𩠇' => '䭀', '𩠈' => '䭃', +'𩠉' => '𩜇', +'𩠊' => '𩜵', '𩠋' => '𩝔', '𩠌' => '餸', +'𩠎' => '𩞄', +'𩠏' => '𩞦', +'𩠠' => '𩠴', '𩧦' => '𩡺', '𩧨' => '駎', '𩧩' => '𩤊', @@ -2649,14 +2876,20 @@ $zh2Hant = array( '𩨄' => '騪', '𩨅' => '𩤸', '𩨆' => '𩤙', +'𩨇' => '䮫', '𩨈' => '騟', '𩨉' => '𩤲', '𩨊' => '騚', '𩨋' => '𩥄', '𩨌' => '𩥑', '𩨍' => '𩥇', +'𩨎' => '龭', '𩨏' => '䮳', '𩨐' => '𩧆', +'𩬣' => '𩭙', +'𩬤' => '𩰀', +'𩯒' => '𩯳', +'𩲒' => '𩳤', '𩽹' => '魥', '𩽺' => '𩵩', '𩽻' => '𩵹', @@ -2666,6 +2899,7 @@ $zh2Hant = array( '𩽿' => '𩶰', '𩾀' => '鮕', '𩾁' => '鯄', +'𩾂' => '䲖', '𩾃' => '鮸', '𩾄' => '𩷰', '𩾅' => '𩸃', @@ -2699,6 +2933,8 @@ $zh2Hant = array( '𪎊' => '麨', '𪎋' => '䴴', '𪎌' => '麳', +'𪎍' => '𪋿', +'𪔭' => '𪔵', '𪚏' => '𪘀', '𪚐' => '𪘯', '𪞝' => '凙', @@ -2715,7 +2951,7 @@ $zh2Hant = array( '𫌀' => '襀', '𫌨' => '覼', '𫍙' => '訑', -'𫍟' => '𧦧', +'𫍟' => '詑', '𫍢' => '譊', '𫍰' => '諰', '𫍲' => '謏', @@ -2728,6 +2964,7 @@ $zh2Hant = array( '𫓧' => '鈇', '𫓩' => '鏦', '𫔎' => '鐍', +'𫖸' => '願', '𫗠' => '餦', '𫗦' => '餔', '𫗧' => '餗', @@ -3993,7 +4230,6 @@ $zh2Hant = array( '优游' => '優遊', '兀术' => '兀朮', '元凶' => '元兇', -'充饥' => '充饑', '兆个' => '兆個', '兆余' => '兆餘', '凶刀' => '兇刀', @@ -4144,7 +4380,6 @@ $zh2Hant = array( '出于' => '出於', '出游' => '出遊', '出丑' => '出醜', -'出锤' => '出鎚', '分占' => '分佔', '分别致' => '分别致', '分半钟' => '分半鐘', @@ -4393,6 +4628,7 @@ $zh2Hant = array( '古书云' => '古書云', '古書云' => '古書云', '古柯咸' => '古柯鹹', +'古柯碱' => '古柯鹼', '古朴' => '古樸', '古语云' => '古語云', '古語云' => '古語云', @@ -4534,7 +4770,7 @@ $zh2Hant = array( '吹干' => '吹乾', '吹发' => '吹髮', '吹胡' => '吹鬍', -'吾为之范我驰驱' => '吾爲之範我馳驅', +'吾爲之范我驰驱' => '吾爲之範我馳驅', '吕后' => '呂后', '呂后' => '呂后', '呆呆傻傻' => '呆呆傻傻', @@ -4617,8 +4853,8 @@ $zh2Hant = array( '严于' => '嚴於', '严丝合缝' => '嚴絲合縫', '嚼谷' => '嚼穀', -'囉囉苏苏' => '囉囉囌囌', -'囉苏' => '囉囌', +'啰啰苏苏' => '囉囉囌囌', +'啰苏' => '囉囌', '嘱托' => '囑託', '四个' => '四個', '四出刊' => '四出刊', @@ -4711,7 +4947,7 @@ $zh2Hant = array( '城里' => '城裡', '埔裡社撫墾局' => '埔裏社撫墾局', '埔裏社撫墾局' => '埔裏社撫墾局', -'埔里社抚垦局' => '埔裏社撫墾局', +'埔裏社抚垦局' => '埔裏社撫墾局', '基干' => '基幹', '基于' => '基於', '基准' => '基準', @@ -4815,7 +5051,6 @@ $zh2Hant = array( '大赞' => '大讚', '大周折' => '大週摺', '大金发苔' => '大金髮苔', -'大锤' => '大鎚', '大钟' => '大鐘', '大只' => '大隻', '大风后' => '大風後', @@ -4836,6 +5071,7 @@ $zh2Hant = array( '天文钟' => '天文鐘', '天历' => '天曆', '天历史' => '天歷史', +'天然碱' => '天然鹼', '天翻地覆' => '天翻地覆', '天覆地载' => '天覆地載', '太仆' => '太僕', @@ -4885,7 +5121,6 @@ $zh2Hant = array( '好丑' => '好醜', '好斗' => '好鬥', '如果干' => '如果幹', -'如饥似渴' => '如饑似渴', '妖后' => '妖后', '妙药' => '妙藥', '始于' => '始於', @@ -5279,6 +5514,7 @@ $zh2Hant = array( '弘历史' => '弘歷史', '弱于' => '弱於', '弱水三千只取一瓢' => '弱水三千只取一瓢', +'弱碱' => '弱鹼', '张三丰' => '張三丰', '張三丰' => '張三丰', '张勋' => '張勳', @@ -5288,6 +5524,7 @@ $zh2Hant = array( '强奸' => '強姦', '强干' => '強幹', '强于' => '強於', +'强碱' => '強鹼', '别口气' => '彆口氣', '别强' => '彆強', '别扭' => '彆扭', @@ -5503,7 +5740,6 @@ $zh2Hant = array( '心脏' => '心臟', '心荡' => '心蕩', '心药' => '心藥', -'心里面' => '心裏面', '心里' => '心裡', '心长发短' => '心長髮短', '心余' => '心餘', @@ -5635,7 +5871,7 @@ $zh2Hant = array( '手表达' => '手表達', '手表露' => '手表露', '手表面' => '手表面', -'手里剑' => '手裏劍', +'手裏剑' => '手裏劍', '手里' => '手裡', '手表' => '手錶', '手松' => '手鬆', @@ -5686,6 +5922,7 @@ $zh2Hant = array( '抗癌药' => '抗癌藥', '抗御' => '抗禦', '抗药' => '抗藥', +'抗碱' => '抗鹼', '折向往' => '折向往', '折子戏' => '折子戲', '折戟沈河' => '折戟沈河', @@ -5824,7 +6061,7 @@ $zh2Hant = array( '挂名' => '掛名', '挂帘' => '掛帘', '挂历' => '掛曆', -'挂钩' => '掛鈎', +'挂鈎' => '掛鈎', '挂钟' => '掛鐘', '采下' => '採下', '采伐' => '採伐', @@ -6528,12 +6765,14 @@ $zh2Hant = array( '水里浊水溪' => '水里濁水溪', '水里鄉' => '水里鄉', '水里乡' => '水里鄉', +'水碱' => '水鹼', '永历' => '永曆', '永历史' => '永歷史', '永志不忘' => '永誌不忘', '求知欲' => '求知慾', '求签' => '求籤', '求道于盲' => '求道於盲', +'汗碱' => '汗鹼', '池里' => '池裡', '污蔑' => '污衊', '汲于' => '汲於', @@ -6726,16 +6965,8 @@ $zh2Hant = array( '滃郁' => '滃鬱', '滑借' => '滑藉', '汇丰' => '滙豐', -'卤味' => '滷味', -'卤水' => '滷水', -'卤汁' => '滷汁', -'卤湖' => '滷湖', -'卤肉' => '滷肉', -'卤菜' => '滷菜', -'卤蛋' => '滷蛋', -'卤制' => '滷製', -'卤鸡' => '滷雞', -'卤面' => '滷麵', +'滷制' => '滷製', +'滷面' => '滷麵', '满拼自尽' => '滿拚自盡', '满满当当' => '滿滿當當', '满头洋发' => '滿頭洋髮', @@ -6831,6 +7062,7 @@ $zh2Hant = array( '煎面' => '煎麵', '烟卷' => '煙捲', '烟斗丝' => '煙斗絲', +'烟碱' => '煙鹼', '照占' => '照佔', '照入签' => '照入籤', '照准' => '照準', @@ -6840,9 +7072,10 @@ $zh2Hant = array( '熊杰' => '熊杰', '荧郁' => '熒鬱', '熬药' => '熬藥', -'炖药' => '燉藥', +'燉药' => '燉藥', '燎发' => '燎髮', '烧干' => '燒乾', +'烧碱' => '燒鹼', '燕几' => '燕几', '燕巢于幕' => '燕巢於幕', '燕燕于飞' => '燕燕于飛', @@ -7015,7 +7248,7 @@ $zh2Hant = array( '发松' => '發鬆', '发面' => '發麵', '白干' => '白乾', -'白兔擣药' => '白兔擣藥', +'白兔𢭏药' => '白兔擣藥', '白干儿' => '白干兒', '白术' => '白朮', '白朴' => '白樸', @@ -7149,6 +7382,7 @@ $zh2Hant = array( '石英钟表' => '石英鐘錶', '石莼' => '石蓴', '石钟乳' => '石鐘乳', +'石碱' => '石鹼', '矽谷' => '矽谷', '研制' => '研製', '砰当' => '砰噹', @@ -7159,6 +7393,7 @@ $zh2Hant = array( '朱红色' => '硃紅色', '朱色' => '硃色', '朱谕' => '硃諭', +'硫化碱' => '硫化鹼', '硬干' => '硬幹', '确瘠' => '确瘠', '碑志' => '碑誌', @@ -7267,7 +7502,6 @@ $zh2Hant = array( '积极参加' => '積极參加', '积淀' => '積澱', '积谷' => '積穀', -'积谷防饥' => '積穀防饑', '积郁' => '積鬱', '稳占' => '穩佔', '稳扎' => '穩紮', @@ -7404,6 +7638,7 @@ $zh2Hant = array( '纡郁' => '紆鬱', '纳征' => '納徵', '纯朴' => '純樸', +'纯碱' => '純鹼', '纸扎' => '紙紮', '素朴' => '素樸', '素发' => '素髮', @@ -7599,6 +7834,7 @@ $zh2Hant = array( '考试' => '考試', '而克制' => '而剋制', '耍斗' => '耍鬥', +'耐碱' => '耐鹼', '耕佣' => '耕傭', '耕获' => '耕穫', '耳余' => '耳餘', @@ -7732,6 +7968,7 @@ $zh2Hant = array( '花马吊嘴' => '花馬弔嘴', '花哄' => '花鬨', '苑里' => '苑裡', +'苛性碱' => '苛性鹼', '若干' => '若干', '苦干' => '苦幹', '苦药' => '苦藥', @@ -7762,7 +7999,7 @@ $zh2Hant = array( '草药' => '草藥', '荐居' => '荐居', '荐臻' => '荐臻', -'荐饥' => '荐饑', +'荐饑' => '荐饑', '荷花淀' => '荷花澱', '庄上' => '莊上', '庄主' => '莊主', @@ -7796,6 +8033,7 @@ $zh2Hant = array( '菠萝干' => '菠蘿乾', '华严钟' => '華嚴鐘', '华发' => '華髮', +'菸碱' => '菸鹼', '萬一只' => '萬一只', '万一只' => '萬一只', '万个' => '萬個', @@ -7875,7 +8113,7 @@ $zh2Hant = array( '姜饼' => '薑餅', '姜黄' => '薑黃', '薙发' => '薙髮', -'薝卜' => '薝蔔', +'薝蔔' => '薝蔔', '苧悴' => '薴悴', '薴烯' => '薴烯', '苧烯' => '薴烯', @@ -7962,8 +8200,7 @@ $zh2Hant = array( '蕴含着' => '蘊含著', '蕴涵着' => '蘊涵著', '苹果干' => '蘋果乾', -'萝卜' => '蘿蔔', -'萝卜干' => '蘿蔔乾', +'萝蔔干' => '蘿蔔乾', '虎须' => '虎鬚', '虎斗' => '虎鬥', '号志' => '號誌', @@ -7983,7 +8220,7 @@ $zh2Hant = array( '蛏干' => '蟶乾', '蚁后' => '蟻后', '蟻后' => '蟻后', -'蠁干' => '蠁幹', +'蚃干' => '蠁幹', '蛮干' => '蠻幹', '血拼' => '血拚', '血余' => '血餘', @@ -8061,8 +8298,9 @@ $zh2Hant = array( '被发阳狂' => '被髮陽狂', '裁并' => '裁併', '裁制' => '裁製', -'里手' => '裏手', -'里海' => '裏海', +'裏勾外连' => '裏勾外連', +'裏手' => '裏手', +'裏海' => '裏海', '补于' => '補於', '补药' => '補藥', '补血药' => '補血藥', @@ -8379,7 +8617,6 @@ $zh2Hant = array( '资金占用' => '資金占用', '贾后' => '賈后', '賈后' => '賈后', -'赈饥' => '賑饑', '赏赞' => '賞讚', '贤后' => '賢后', '賢后' => '賢后', @@ -8655,6 +8892,7 @@ $zh2Hant = array( '酒醴曲蘖' => '酒醴麴櫱', '酒曲' => '酒麴', '酥松' => '酥鬆', +'酸碱' => '酸鹼', '醇朴' => '醇樸', '醉于' => '醉於', '醋坛' => '醋罈', @@ -8729,7 +8967,6 @@ $zh2Hant = array( '重复' => '重複', '重托' => '重託', '重游' => '重遊', -'重锤' => '重鎚', '野姜' => '野薑', '野游' => '野遊', '厘出' => '釐出', @@ -8756,10 +8993,10 @@ $zh2Hant = array( '金装玉里' => '金裝玉裡', '金表' => '金錶', '金钟' => '金鐘', +'金鸡纳碱' => '金雞納鹼', '金马仑道' => '金馬崙道', '金发' => '金髮', -'钉锤' => '釘鎚', -'钩心斗角' => '鈎心鬥角', +'鈎心斗角' => '鈎心鬥角', '银朱' => '銀硃', '银发' => '銀髮', '铜范' => '銅範', @@ -8777,7 +9014,7 @@ $zh2Hant = array( '钱谷' => '錢穀', '钱范' => '錢範', '钱庄' => '錢莊', -'锦绣花园' => '錦綉花園', +'锦綉花园' => '錦綉花園', '锦绣' => '錦繡', '表停' => '錶停', '表冠' => '錶冠', @@ -8814,9 +9051,6 @@ $zh2Hant = array( '锻炼出' => '鍛鍊出', '锲而不舍' => '鍥而不捨', '镰仓' => '鎌倉', -'锤儿' => '鎚兒', -'锤子' => '鎚子', -'锤头' => '鎚頭', '锈病' => '鏽病', '锈菌' => '鏽菌', '锈蚀' => '鏽蝕', @@ -8896,7 +9130,6 @@ $zh2Hant = array( '钟鼓' => '鐘鼓', '铁杆' => '鐵杆', '铁栏杆' => '鐵欄杆', -'铁锤' => '鐵鎚', '铁锈' => '鐵鏽', '铁钟' => '鐵鐘', '铸钟' => '鑄鐘', @@ -9298,13 +9531,8 @@ $zh2Hant = array( '喂鱼' => '餵魚', '喂鸭' => '餵鴨', '喂鹅' => '餵鵝', -'饥寒' => '饑寒', -'饥民' => '饑民', -'饥渴' => '饑渴', -'饥溺' => '饑溺', -'饥荒' => '饑荒', -'饥饱' => '饑飽', -'饥馑' => '饑饉', +'饑荒' => '饑荒', +'饑馑' => '饑饉', '首当其冲' => '首當其衝', '首发' => '首發', '首只' => '首隻', @@ -9581,7 +9809,7 @@ $zh2Hant = array( '鱼干' => '魚乾', '鱼松' => '魚鬆', '鲸须' => '鯨鬚', -'鲇鱼' => '鯰魚', +'鯰鱼' => '鯰魚', '鸠占鹊巢' => '鳩佔鵲巢', '凤凰于飞' => '鳳凰于飛', '凤梨干' => '鳳梨乾', @@ -9624,9 +9852,22 @@ $zh2Hant = array( '咸鸭蛋' => '鹹鴨蛋', '咸卤' => '鹹鹵', '咸咸' => '鹹鹹', +'碱化' => '鹼化', +'碱土金属' => '鹼土金屬', +'碱地' => '鹼地', +'碱度' => '鹼度', +'碱性' => '鹼性', +'碱水' => '鹼水', +'碱液' => '鹼液', +'碱熔' => '鹼熔', +'碱石灰' => '鹼石灰', +'碱纤维素' => '鹼纖維素', +'碱金属' => '鹼金屬', +'碱类' => '鹼類', '盐打怎么咸' => '鹽打怎麼鹹', -'盐卤' => '鹽滷', '盐余' => '鹽餘', +'盐碱土' => '鹽鹼土', +'盐碱滩' => '鹽鹼灘', '丽于' => '麗於', '曲尘' => '麴塵', '曲蘖' => '麴櫱', @@ -9779,18 +10020,90 @@ $zh2Hant = array( ); $zh2Hans = array( +'㑯' => '㑔', +'㑳' => '㑇', +'㒓' => '𠉂', +'㓨' => '刾', +'㗲' => '𠵾', +'㘚' => '㘎', +'㜄' => '㚯', +'㜏' => '㛣', +'㜢' => '𡞱', +'㜷' => '𡝠', '㞞' => '𪨊', '㠏' => '㟆', +'㢝' => '𢋈', +'㥮' => '㤘', +'㦎' => '𢛯', '㩜' => '㨫', +'㩳' => '㧐', +'㷿' => '𤈷', +'㺏' => '𤠋', +'㿧' => '𤽯', +'䀹' => '𥅴', +'䁪' => '𥇢', +'䁻' => '䀥', +'䉙' => '𥬀', '䉬' => '𫂈', +'䉲' => '𥮜', +'䊭' => '𥺅', '䊷' => '䌶', '䋙' => '䌺', +'䋚' => '䌻', '䋻' => '䌾', +'䋿' => '𦈓', +'䌈' => '𦈖', +'䌋' => '𦈘', +'䌖' => '𦈜', +'䌝' => '𦈟', +'䌟' => '𦈞', +'䌥' => '𦈠', +'䌰' => '𦈙', +'䕳' => '𦰴', +'䗿' => '𧉞', +'䙡' => '䙌', +'䜀' => '䜧', +'䝻' => '𧹕', '䝼' => '䞍', +'䞈' => '𧹑', +'䢨' => '𨑹', +'䥇' => '䦂', +'䥩' => '𨱖', +'䥱' => '䥾', +'䦘' => '𨸄', +'䦛' => '䦶', +'䦟' => '䦷', +'䦳' => '𨷿', +'䧢' => '𨸟', +'䪏' => '𩏼', +'䪗' => '𩐀', +'䪘' => '𩏿', +'䫴' => '𩖗', +'䬘' => '𩙮', +'䬝' => '𩙯', +'䬞' => '𩙧', +'䭀' => '𩠇', +'䭃' => '𩠈', +'䭿' => '𩧭', +'䮝' => '𩧰', +'䮞' => '𩨁', +'䮠' => '𩧿', +'䮫' => '𩨇', +'䮳' => '𩨏', +'䮾' => '𩧪', '䯀' => '䯅', '䰾' => '鲃', +'䱙' => '𩾈', +'䱬' => '𩾊', +'䱰' => '𩾋', +'䱷' => '䲣', '䱽' => '䲝', '䲁' => '鳚', +'䲖' => '𩾂', +'䲰' => '𪉂', +'䴉' => '鹮', +'䴬' => '𪎈', +'䴴' => '𪎋', '丟' => '丢', '並' => '并', '乾' => '干', @@ -9808,6 +10121,7 @@ $zh2Hans = array( '係' => '系', '俔' => '伣', '俠' => '侠', +'俥' => '伡', '倀' => '伥', '倆' => '俩', '倈' => '俫', @@ -9816,7 +10130,9 @@ $zh2Hans = array( '們' => '们', '倖' => '幸', '倫' => '伦', +'倲' => '㑈', '偉' => '伟', +'偑' => '㐽', '側' => '侧', '偵' => '侦', '偽' => '伪', @@ -9852,6 +10168,7 @@ $zh2Hans = array( '儕' => '侪', '儘' => '尽', '償' => '偿', +'儣' => '𠆲', '優' => '优', '儲' => '储', '儷' => '俪', @@ -9885,6 +10202,7 @@ $zh2Hans = array( '剴' => '剀', '創' => '创', '剷' => '铲', +'剾' => '𠛅', '劃' => '划', '劇' => '剧', '劉' => '刘', @@ -9915,7 +10233,6 @@ $zh2Hans = array( '卻' => '却', '卽' => '即', '厙' => '厍', -'厠' => '厕', '厤' => '历', '厭' => '厌', '厲' => '厉', @@ -9929,10 +10246,10 @@ $zh2Hans = array( '呂' => '吕', '咼' => '呙', '員' => '员', +'哯' => '𠯟', '唄' => '呗', '唚' => '吣', '問' => '问', -'啓' => '启', '啞' => '哑', '啟' => '启', '啢' => '唡', @@ -9953,6 +10270,7 @@ $zh2Hans = array( '嗹' => '𪡏', '嘆' => '叹', '嘍' => '喽', +'嘓' => '啯', '嘔' => '呕', '嘖' => '啧', '嘗' => '尝', @@ -9965,6 +10283,7 @@ $zh2Hans = array( '嘸' => '呒', '嘽' => '啴', '噁' => '恶', +'噅' => '𠯠', '噓' => '嘘', '噚' => '㖊', '噝' => '咝', @@ -9995,6 +10314,7 @@ $zh2Hans = array( '囂' => '嚣', '囅' => '冁', '囈' => '呓', +'囉' => '啰', '囌' => '苏', '囑' => '嘱', '囪' => '囱', @@ -10032,7 +10352,6 @@ $zh2Hans = array( '墮' => '堕', '墰' => '坛', '墳' => '坟', -'墻' => '墙', '墾' => '垦', '壇' => '坛', '壈' => '𡒄', @@ -10059,7 +10378,6 @@ $zh2Hans = array( '奧' => '奥', '奩' => '奁', '奪' => '夺', -'奬' => '奖', '奮' => '奋', '奼' => '姹', '妝' => '妆', @@ -10071,13 +10389,14 @@ $zh2Hans = array( '婭' => '娅', '媧' => '娲', '媯' => '妫', +'媰' => '㛀', '媼' => '媪', '媽' => '妈', '嫗' => '妪', '嫵' => '妩', '嫻' => '娴', '嫿' => '婳', -'嬀' => '妫', +'嬃' => '媭', '嬈' => '娆', '嬋' => '婵', '嬌' => '娇', @@ -10087,6 +10406,7 @@ $zh2Hans = array( '嬪' => '嫔', '嬰' => '婴', '嬸' => '婶', +'孋' => '㛤', '孌' => '娈', '孫' => '孙', '學' => '学', @@ -10128,6 +10448,7 @@ $zh2Hans = array( '崬' => '岽', '嵐' => '岚', '嵗' => '岁', +'嵼' => '𡶴', '嶁' => '嵝', '嶄' => '崭', '嶇' => '岖', @@ -10189,7 +10510,9 @@ $zh2Hans = array( '彎' => '弯', '彙' => '汇', '彞' => '彝', +'彠' => '彟', '彥' => '彦', +'彲' => '彨', '後' => '后', '徑' => '径', '從' => '从', @@ -10220,7 +10543,6 @@ $zh2Hans = array( '慚' => '惭', '慟' => '恸', '慣' => '惯', -'慤' => '悫', '慪' => '怄', '慫' => '怂', '慮' => '虑', @@ -10239,6 +10561,7 @@ $zh2Hans = array( '憮' => '怃', '憲' => '宪', '憶' => '忆', +'懀' => '𢙓', '懇' => '恳', '應' => '应', '懌' => '怿', @@ -10274,6 +10597,7 @@ $zh2Hans = array( '捲' => '卷', '掃' => '扫', '掄' => '抡', +'掆' => '㧏', '掗' => '挜', '掙' => '挣', '掛' => '挂', @@ -10287,6 +10611,7 @@ $zh2Hans = array( '搗' => '捣', '搵' => '揾', '搶' => '抢', +'摋' => '𢫬', '摑' => '掴', '摜' => '掼', '摟' => '搂', @@ -10318,6 +10643,7 @@ $zh2Hans = array( '擔' => '担', '據' => '据', '擠' => '挤', +'擣' => '𢭏', '擬' => '拟', '擯' => '摈', '擰' => '拧', @@ -10328,6 +10654,7 @@ $zh2Hans = array( '擺' => '摆', '擻' => '擞', '擼' => '撸', +'擽' => '㧰', '擾' => '扰', '攄' => '摅', '攆' => '撵', @@ -10349,6 +10676,8 @@ $zh2Hans = array( '數' => '数', '斂' => '敛', '斃' => '毙', +'斅' => '𢽾', +'斆' => '敩', '斕' => '斓', '斬' => '斩', '斷' => '断', @@ -10371,10 +10700,12 @@ $zh2Hans = array( '曏' => '向', '曖' => '暧', '曠' => '旷', +'曥' => '𣆐', '曨' => '昽', '曬' => '晒', '書' => '书', '會' => '会', +'朥' => '𦛨', '朧' => '胧', '朮' => '术', '東' => '东', @@ -10391,10 +10722,12 @@ $zh2Hans = array( '棖' => '枨', '棗' => '枣', '棟' => '栋', +'棡' => '㭎', '棧' => '栈', '棲' => '栖', '棶' => '梾', '椏' => '桠', +'椲' => '㭏', '楊' => '杨', '楓' => '枫', '楨' => '桢', @@ -10412,6 +10745,8 @@ $zh2Hans = array( '槧' => '椠', '槨' => '椁', '槳' => '桨', +'槶' => '椢', +'槼' => '椝', '樁' => '桩', '樂' => '乐', '樅' => '枞', @@ -10419,10 +10754,14 @@ $zh2Hans = array( '樓' => '楼', '標' => '标', '樞' => '枢', +'樢' => '㭤', '樣' => '样', +'樫' => '㭴', +'樳' => '桪', '樸' => '朴', '樹' => '树', '樺' => '桦', +'樿' => '椫', '橈' => '桡', '橋' => '桥', '機' => '机', @@ -10435,6 +10774,7 @@ $zh2Hans = array( '檟' => '槚', '檢' => '检', '檣' => '樯', +'檭' => '𣘴', '檮' => '梼', '檯' => '台', '檳' => '槟', @@ -10460,8 +10800,10 @@ $zh2Hans = array( '欄' => '栏', '欅' => '榉', '權' => '权', +'欍' => '𣐤', '欏' => '椤', '欒' => '栾', +'欓' => '𣗋', '欖' => '榄', '欞' => '棂', '欽' => '钦', @@ -10484,7 +10826,6 @@ $zh2Hans = array( '殰' => '㱩', '殲' => '歼', '殺' => '杀', -'殻' => '壳', '殼' => '壳', '毀' => '毁', '毆' => '殴', @@ -10518,6 +10859,7 @@ $zh2Hans = array( '淺' => '浅', '渙' => '涣', '減' => '减', +'渢' => '沨', '渦' => '涡', '測' => '测', '渾' => '浑', @@ -10529,6 +10871,7 @@ $zh2Hans = array( '準' => '准', '溝' => '沟', '溫' => '温', +'溳' => '涢', '滄' => '沧', '滅' => '灭', '滌' => '涤', @@ -10537,12 +10880,12 @@ $zh2Hans = array( '滬' => '沪', '滯' => '滞', '滲' => '渗', -'滷' => '卤', '滸' => '浒', '滻' => '浐', '滾' => '滚', '滿' => '满', '漁' => '渔', +'漊' => '溇', '漚' => '沤', '漢' => '汉', '漣' => '涟', @@ -10554,7 +10897,6 @@ $zh2Hans = array( '潁' => '颍', '潑' => '泼', '潔' => '洁', -'潙' => '沩', '潛' => '潜', '潤' => '润', '潯' => '浔', @@ -10562,6 +10904,7 @@ $zh2Hans = array( '潷' => '滗', '潿' => '涠', '澀' => '涩', +'澅' => '𣶩', '澆' => '浇', '澇' => '涝', '澐' => '沄', @@ -10575,16 +10918,22 @@ $zh2Hans = array( '澾' => '㳠', '濁' => '浊', '濃' => '浓', +'濄' => '㳡', +'濆' => '𣸣', '濕' => '湿', '濘' => '泞', +'濜' => '浕', '濟' => '济', '濤' => '涛', +'濧' => '㳔', '濫' => '滥', '濰' => '潍', '濱' => '滨', '濺' => '溅', '濼' => '泺', '濾' => '滤', +'瀂' => '澛', +'瀃' => '𣽷', '瀅' => '滢', '瀆' => '渎', '瀇' => '㲿', @@ -10607,8 +10956,10 @@ $zh2Hans = array( '灑' => '洒', '灕' => '漓', '灘' => '滩', +'灙' => '𣺼', '灝' => '灏', '灠' => '漤', +'灡' => '㳕', '灣' => '湾', '灤' => '滦', '灧' => '滟', @@ -10626,14 +10977,17 @@ $zh2Hans = array( '煬' => '炀', '煱' => '㶽', '熅' => '煴', +'熉' => '𤈶', +'熌' => '𤇄', '熒' => '荧', +'熓' => '𤆡', '熗' => '炝', +'熡' => '𤋏', '熱' => '热', '熲' => '颎', '熾' => '炽', '燁' => '烨', '燈' => '灯', -'燉' => '炖', '燒' => '烧', '燙' => '烫', '燜' => '焖', @@ -10645,11 +10999,11 @@ $zh2Hans = array( '燶' => '㶶', '燼' => '烬', '燾' => '焘', +'爄' => '𤇃', '爍' => '烁', '爐' => '炉', '爛' => '烂', '爭' => '争', -'爲' => '为', '爺' => '爷', '爾' => '尔', '牆' => '墙', @@ -10683,6 +11037,7 @@ $zh2Hans = array( '獻' => '献', '獼' => '猕', '玀' => '猡', +'玁' => '𤞤', '現' => '现', '琺' => '珐', '琿' => '珲', @@ -10698,16 +11053,17 @@ $zh2Hans = array( '璣' => '玑', '璦' => '瑷', '璫' => '珰', +'璯' => '㻅', '環' => '环', '璽' => '玺', '瓊' => '琼', '瓏' => '珑', '瓔' => '璎', +'瓕' => '𤦀', '瓚' => '瓒', '甌' => '瓯', '甕' => '瓮', '產' => '产', -'産' => '产', '甦' => '苏', '甯' => '宁', '畝' => '亩', @@ -10731,7 +11087,6 @@ $zh2Hans = array( '瘮' => '瘆', '瘲' => '疭', '瘺' => '瘘', -'瘻' => '瘘', '療' => '疗', '癆' => '痨', '癇' => '痫', @@ -10753,6 +11108,7 @@ $zh2Hans = array( '癲' => '癫', '發' => '发', '皚' => '皑', +'皟' => '𤾀', '皰' => '疱', '皸' => '皲', '皺' => '皱', @@ -10774,6 +11130,7 @@ $zh2Hans = array( '瞘' => '眍', '瞜' => '䁖', '瞞' => '瞒', +'瞤' => '𥆧', '瞭' => '了', '瞶' => '瞆', '瞼' => '睑', @@ -10787,19 +11144,24 @@ $zh2Hans = array( '硨' => '砗', '硯' => '砚', '碕' => '埼', +'碙' => '𥐻', '碩' => '硕', '碭' => '砀', '碸' => '砜', '確' => '确', '碼' => '码', +'碽' => '䂵', '磑' => '硙', '磚' => '砖', +'磠' => '硵', '磣' => '碜', '磧' => '碛', '磯' => '矶', '磽' => '硗', +'礄' => '硚', '礆' => '硷', '礎' => '础', +'礒' => '𥐟', '礙' => '碍', '礦' => '矿', '礪' => '砺', @@ -10846,9 +11208,7 @@ $zh2Hans = array( '竄' => '窜', '竅' => '窍', '竇' => '窦', -'竈' => '灶', '竊' => '窃', -'竪' => '竖', '競' => '竞', '筆' => '笔', '筍' => '笋', @@ -10862,6 +11222,7 @@ $zh2Hans = array( '築' => '筑', '篋' => '箧', '篔' => '筼', +'篘' => '𥬠', '篤' => '笃', '篩' => '筛', '篳' => '筚', @@ -10876,8 +11237,11 @@ $zh2Hans = array( '簽' => '签', '簾' => '帘', '籃' => '篮', +'籋' => '𥬞', '籌' => '筹', +'籔' => '䉤', '籙' => '箓', +'籛' => '篯', '籜' => '箨', '籟' => '籁', '籠' => '笼', @@ -10950,14 +11314,14 @@ $zh2Hans = array( '統' => '统', '絲' => '丝', '絳' => '绛', -'絶' => '绝', '絹' => '绢', '絺' => '𫄨', +'綀' => '𦈌', '綁' => '绑', '綃' => '绡', '綆' => '绠', +'綇' => '𦈋', '綈' => '绨', -'綉' => '绣', '綌' => '绤', '綏' => '绥', '綐' => '䌼', @@ -10967,14 +11331,12 @@ $zh2Hans = array( '綠' => '绿', '綢' => '绸', '綣' => '绻', -'綫' => '线', '綬' => '绶', '維' => '维', '綯' => '绹', '綰' => '绾', '綱' => '纲', '網' => '网', -'綳' => '绷', '綴' => '缀', '綵' => '彩', '綸' => '纶', @@ -10988,10 +11350,9 @@ $zh2Hans = array( '緇' => '缁', '緊' => '紧', '緋' => '绯', -'緑' => '绿', +'緍' => '𦈏', '緒' => '绪', '緓' => '绬', -'緔' => '绱', '緗' => '缃', '緘' => '缄', '緙' => '缂', @@ -11006,16 +11367,20 @@ $zh2Hans = array( '緩' => '缓', '緬' => '缅', '緯' => '纬', +'緰' => '𦈕', '緱' => '缑', '緲' => '缈', '練' => '练', '緶' => '缏', +'緷' => '𦈉', +'緸' => '𦈑', '緹' => '缇', '緻' => '致', '縈' => '萦', '縉' => '缙', '縊' => '缢', '縋' => '缒', +'縎' => '𦈔', '縐' => '绉', '縑' => '缣', '縕' => '缊', @@ -11025,8 +11390,8 @@ $zh2Hans = array( '縞' => '缟', '縟' => '缛', '縣' => '县', -'縧' => '绦', '縫' => '缝', +'縬' => '𦈚', '縭' => '缡', '縮' => '缩', '縱' => '纵', @@ -11037,34 +11402,39 @@ $zh2Hans = array( '縶' => '絷', '縷' => '缕', '縹' => '缥', +'縺' => '𦈐', '總' => '总', '績' => '绩', '繃' => '绷', '繅' => '缫', '繆' => '缪', +'繏' => '𦈝', '繐' => '穗', '繒' => '缯', +'繓' => '𦈛', '織' => '织', '繕' => '缮', '繚' => '缭', '繞' => '绕', +'繟' => '𦈎', '繡' => '绣', '繢' => '缋', '繩' => '绳', '繪' => '绘', '繫' => '系', '繭' => '茧', -'繮' => '缰', '繯' => '缳', '繰' => '缲', '繳' => '缴', '繸' => '䍁', '繹' => '绎', +'繻' => '𦈡', '繼' => '继', '繽' => '缤', '繾' => '缱', '繿' => '䍀', '纁' => '𫄸', +'纇' => '颣', '纈' => '缬', '纊' => '纩', '續' => '续', @@ -11090,7 +11460,9 @@ $zh2Hans = array( '羨' => '羡', '義' => '义', '習' => '习', +'翬' => '翚', '翹' => '翘', +'翽' => '翙', '耬' => '耧', '耮' => '耢', '聖' => '圣', @@ -11110,18 +11482,22 @@ $zh2Hans = array( '脈' => '脉', '脛' => '胫', '脣' => '唇', +'脥' => '𣍰', '脫' => '脱', '脹' => '胀', '腎' => '肾', '腖' => '胨', '腡' => '脶', '腦' => '脑', +'腪' => '𣍯', '腫' => '肿', '腳' => '脚', '腸' => '肠', '膃' => '腽', +'膕' => '腘', '膚' => '肤', '膠' => '胶', +'膢' => '𦝼', '膩' => '腻', '膽' => '胆', '膾' => '脍', @@ -11129,6 +11505,7 @@ $zh2Hans = array( '臉' => '脸', '臍' => '脐', '臏' => '膑', +'臗' => '𣎑', '臘' => '腊', '臚' => '胪', '臟' => '脏', @@ -11161,14 +11538,13 @@ $zh2Hans = array( '萇' => '苌', '萊' => '莱', '萬' => '万', +'萴' => '荝', '萵' => '莴', '葉' => '叶', '葒' => '荭', '葤' => '荮', '葦' => '苇', -'葯' => '药', '葷' => '荤', -'蒓' => '莼', '蒔' => '莳', '蒞' => '莅', '蒼' => '苍', @@ -11178,7 +11554,6 @@ $zh2Hans = array( '蓯' => '苁', '蓴' => '莼', '蓽' => '荜', -'蔔' => '卜', '蔘' => '参', '蔞' => '蒌', '蔣' => '蒋', @@ -11215,7 +11590,6 @@ $zh2Hans = array( '藝' => '艺', '藥' => '药', '藪' => '薮', -'藴' => '蕴', '藶' => '苈', '藹' => '蔼', '藺' => '蔺', @@ -11259,6 +11633,7 @@ $zh2Hans = array( '蟲' => '虫', '蟶' => '蛏', '蟻' => '蚁', +'蠁' => '蚃', '蠅' => '蝇', '蠆' => '虿', '蠍' => '蝎', @@ -11270,17 +11645,14 @@ $zh2Hans = array( '蠱' => '蛊', '蠶' => '蚕', '蠻' => '蛮', -'衆' => '众', '衊' => '蔑', '術' => '术', '衕' => '同', '衚' => '胡', '衛' => '卫', '衝' => '冲', -'衹' => '只', '袞' => '衮', '裊' => '袅', -'裏' => '里', '補' => '补', '裝' => '装', '裡' => '里', @@ -11294,7 +11666,7 @@ $zh2Hans = array( '褻' => '亵', '襀' => '𫌀', '襆' => '幞', -'襇' => '裥', +'襉' => '裥', '襏' => '袯', '襖' => '袄', '襝' => '裣', @@ -11304,6 +11676,7 @@ $zh2Hans = array( '襬' => '䙓', '襯' => '衬', '襲' => '袭', +'襴' => '襕', '見' => '见', '覎' => '觃', '規' => '规', @@ -11355,10 +11728,12 @@ $zh2Hans = array( '訶' => '诃', '診' => '诊', '註' => '注', +'詀' => '𧮪', '詁' => '诂', '詆' => '诋', '詎' => '讵', '詐' => '诈', +'詑' => '𫍟', '詒' => '诒', '詔' => '诏', '評' => '评', @@ -11404,7 +11779,6 @@ $zh2Hans = array( '誦' => '诵', '誨' => '诲', '說' => '说', -'説' => '说', '誰' => '谁', '課' => '课', '誶' => '谇', @@ -11460,15 +11834,12 @@ $zh2Hans = array( '講' => '讲', '謝' => '谢', '謠' => '谣', -'謡' => '谣', '謨' => '谟', '謫' => '谪', '謬' => '谬', -'謭' => '谫', '謳' => '讴', '謹' => '谨', '謾' => '谩', -'譅' => '䜧', '證' => '证', '譊' => '𫍢', '譎' => '谲', @@ -11489,6 +11860,8 @@ $zh2Hans = array( '譾' => '谫', '讀' => '读', '變' => '变', +'讋' => '詟', +'讌' => '䜩', '讎' => '仇', '讒' => '谗', '讓' => '让', @@ -11547,6 +11920,7 @@ $zh2Hans = array( '賚' => '赉', '賜' => '赐', '賞' => '赏', +'賟' => '𧹖', '賠' => '赔', '賡' => '赓', '賢' => '贤', @@ -11555,7 +11929,6 @@ $zh2Hans = array( '賦' => '赋', '賧' => '赕', '質' => '质', -'賫' => '赍', '賬' => '账', '賭' => '赌', '賰' => '䞐', @@ -11566,12 +11939,12 @@ $zh2Hans = array( '購' => '购', '賽' => '赛', '賾' => '赜', +'贃' => '𧹗', '贄' => '贽', '贅' => '赘', '贇' => '赟', '贈' => '赠', '贊' => '赞', -'贋' => '赝', '贍' => '赡', '贏' => '赢', '贐' => '赆', @@ -11580,7 +11953,6 @@ $zh2Hans = array( '贖' => '赎', '贗' => '赝', '贛' => '赣', -'贜' => '赃', '赬' => '赪', '趕' => '赶', '趙' => '赵', @@ -11600,16 +11972,19 @@ $zh2Hans = array( '躊' => '踌', '躋' => '跻', '躍' => '跃', +'躎' => '䟢', '躑' => '踯', '躒' => '跞', '躓' => '踬', '躕' => '蹰', '躚' => '跹', +'躝' => '𨅬', '躡' => '蹑', '躥' => '蹿', '躦' => '躜', '躪' => '躏', '軀' => '躯', +'軉' => '𨉗', '車' => '车', '軋' => '轧', '軌' => '轨', @@ -11618,6 +11993,7 @@ $zh2Hans = array( '軑' => '轪', '軒' => '轩', '軔' => '轫', +'軗' => '𨐅', '軛' => '轭', '軟' => '软', '軤' => '轷', @@ -11631,6 +12007,7 @@ $zh2Hans = array( '軼' => '轶', '軾' => '轼', '較' => '较', +'輄' => '𨐈', '輅' => '辂', '輇' => '辁', '輈' => '辀', @@ -11721,7 +12098,6 @@ $zh2Hans = array( '鄺' => '邝', '酇' => '酂', '酈' => '郦', -'醖' => '酝', '醜' => '丑', '醞' => '酝', '醣' => '糖', @@ -11747,10 +12123,12 @@ $zh2Hans = array( '釤' => '钐', '釧' => '钏', '釩' => '钒', +'釳' => '𨰿', '釵' => '钗', '釷' => '钍', '釹' => '钕', '釺' => '钎', +'釾' => '䥺', '鈀' => '钯', '鈁' => '钫', '鈃' => '钘', @@ -11758,20 +12136,23 @@ $zh2Hans = array( '鈇' => '𫓧', '鈈' => '钚', '鈉' => '钠', +'鈋' => '𨱂', '鈍' => '钝', -'鈎' => '钩', '鈐' => '钤', '鈑' => '钣', '鈒' => '钑', '鈔' => '钞', '鈕' => '钮', '鈞' => '钧', +'鈠' => '𨱁', '鈣' => '钙', '鈥' => '钬', '鈦' => '钛', '鈧' => '钪', '鈮' => '铌', +'鈯' => '𨱄', '鈰' => '铈', +'鈲' => '𨱃', '鈳' => '钶', '鈴' => '铃', '鈷' => '钴', @@ -11782,6 +12163,7 @@ $zh2Hans = array( '鈾' => '铀', '鈿' => '钿', '鉀' => '钾', +'鉁' => '𨱅', '鉅' => '钜', '鉈' => '铊', '鉉' => '铉', @@ -11793,7 +12175,6 @@ $zh2Hans = array( '鉚' => '铆', '鉛' => '铅', '鉞' => '钺', -'鉢' => '钵', '鉤' => '钩', '鉦' => '钲', '鉬' => '钼', @@ -11825,14 +12206,15 @@ $zh2Hans = array( '銬' => '铐', '銱' => '铞', '銳' => '锐', +'銶' => '𨱇', '銷' => '销', -'銹' => '锈', '銻' => '锑', '銼' => '锉', '鋁' => '铝', '鋃' => '锒', '鋅' => '锌', '鋇' => '钡', +'鋉' => '𨱈', '鋌' => '铤', '鋏' => '铗', '鋒' => '锋', @@ -11846,7 +12228,6 @@ $zh2Hans = array( '鋨' => '锇', '鋩' => '铓', '鋪' => '铺', -'鋭' => '锐', '鋮' => '铖', '鋯' => '锆', '鋰' => '锂', @@ -11855,6 +12236,7 @@ $zh2Hans = array( '鋸' => '锯', '鋼' => '钢', '錁' => '锞', +'錂' => '𨱋', '錄' => '录', '錆' => '锖', '錇' => '锫', @@ -11877,13 +12259,12 @@ $zh2Hans = array( '錫' => '锡', '錮' => '锢', '錯' => '错', -'録' => '录', '錳' => '锰', '錶' => '表', '錸' => '铼', '鍀' => '锝', -'鍁' => '锨', '鍃' => '锪', +'鍄' => '𨱉', '鍆' => '钔', '鍇' => '锴', '鍈' => '锳', @@ -11899,6 +12280,7 @@ $zh2Hans = array( '鍥' => '锲', '鍩' => '锘', '鍬' => '锹', +'鍮' => '𨱎', '鍰' => '锾', '鍵' => '键', '鍶' => '锶', @@ -11912,7 +12294,6 @@ $zh2Hans = array( '鎔' => '镕', '鎖' => '锁', '鎘' => '镉', -'鎚' => '锤', '鎛' => '镈', '鎝' => '𨱏', '鎡' => '镃', @@ -11925,15 +12306,18 @@ $zh2Hans = array( '鎬' => '镐', '鎭' => '鎮', '鎮' => '镇', +'鎯' => '𨱍', '鎰' => '镒', '鎲' => '镋', '鎳' => '镍', '鎵' => '镓', -'鎸' => '镌', +'鎷' => '𨰾', '鎿' => '镎', '鏃' => '镞', +'鏆' => '𨱌', '鏇' => '镟', '鏈' => '链', +'鏉' => '𨱒', '鏌' => '镆', '鏍' => '镙', '鏐' => '镠', @@ -11954,23 +12338,28 @@ $zh2Hans = array( '鏵' => '铧', '鏷' => '镤', '鏹' => '镪', +'鏺' => '䥽', '鏽' => '锈', '鐃' => '铙', +'鐄' => '𨱑', '鐋' => '铴', '鐍' => '𫔎', +'鐎' => '𨱓', +'鐏' => '𨱔', '鐐' => '镣', '鐒' => '铹', '鐓' => '镦', '鐔' => '镡', '鐘' => '钟', '鐙' => '镫', -'鐝' => '镢', '鐠' => '镨', +'鐥' => '䦅', '鐦' => '锎', '鐧' => '锏', '鐨' => '镄', '鐫' => '镌', '鐮' => '镰', +'鐯' => '䦃', '鐲' => '镯', '鐳' => '镭', '鐵' => '铁', @@ -12010,8 +12399,10 @@ $zh2Hans = array( '閉' => '闭', '開' => '开', '閌' => '闶', +'閍' => '𨸂', '閎' => '闳', '閏' => '闰', +'閐' => '𨸃', '閑' => '闲', '閒' => '闲', '間' => '间', @@ -12027,7 +12418,6 @@ $zh2Hans = array( '閬' => '阆', '閭' => '闾', '閱' => '阅', -'閲' => '阅', '閶' => '阊', '閹' => '阉', '閻' => '阎', @@ -12143,7 +12533,7 @@ $zh2Hans = array( '頸' => '颈', '頹' => '颓', '頻' => '频', -'頽' => '颓', +'顃' => '𩖖', '顆' => '颗', '題' => '题', '額' => '额', @@ -12151,7 +12541,6 @@ $zh2Hans = array( '顏' => '颜', '顒' => '颙', '顓' => '颛', -'顔' => '颜', '願' => '愿', '顙' => '颡', '顛' => '颠', @@ -12170,13 +12559,16 @@ $zh2Hans = array( '颭' => '飐', '颮' => '飑', '颯' => '飒', +'颰' => '𩙥', '颱' => '台', '颳' => '刮', '颶' => '飓', +'颷' => '𩙪', '颸' => '飔', '颺' => '飏', '颻' => '飖', '颼' => '飕', +'颾' => '𩙫', '飀' => '飗', '飄' => '飘', '飆' => '飙', @@ -12227,6 +12619,7 @@ $zh2Hans = array( '餵' => '喂', '餶' => '馉', '餷' => '馇', +'餸' => '𩠌', '餺' => '馎', '餼' => '饩', '餾' => '馏', @@ -12239,7 +12632,6 @@ $zh2Hans = array( '饊' => '馓', '饋' => '馈', '饌' => '馔', -'饑' => '饥', '饒' => '饶', '饗' => '飨', '饘' => '𫗴', @@ -12255,6 +12647,7 @@ $zh2Hans = array( '馹' => '驲', '駁' => '驳', '駃' => '𫘝', +'駎' => '𩧨', '駐' => '驻', '駑' => '驽', '駒' => '驹', @@ -12262,14 +12655,17 @@ $zh2Hans = array( '駕' => '驾', '駘' => '骀', '駙' => '驸', +'駚' => '𩧫', '駛' => '驶', '駝' => '驼', '駟' => '驷', -'駡' => '骂', '駢' => '骈', +'駧' => '𩧲', +'駩' => '𩧴', '駭' => '骇', '駰' => '骃', '駱' => '骆', +'駶' => '𩧺', '駸' => '骎', '駻' => '𫘣', '駿' => '骏', @@ -12281,11 +12677,16 @@ $zh2Hans = array( '騍' => '骒', '騎' => '骑', '騏' => '骐', +'騔' => '𩨀', '騖' => '骛', '騙' => '骗', +'騚' => '𩨊', +'騝' => '𩨃', +'騟' => '𩨈', '騠' => '𫘨', '騤' => '骙', '騧' => '䯄', +'騪' => '𩨄', '騫' => '骞', '騭' => '骘', '騮' => '骝', @@ -12301,6 +12702,7 @@ $zh2Hans = array( '驄' => '骢', '驅' => '驱', '驊' => '骅', +'驋' => '𩧯', '驌' => '骕', '驍' => '骁', '驏' => '骣', @@ -12332,12 +12734,14 @@ $zh2Hans = array( '鬩' => '阋', '鬮' => '阄', '鬱' => '郁', +'鬹' => '鬶', '魎' => '魉', '魘' => '魇', '魚' => '鱼', '魛' => '鱽', '魟' => '𫚉', '魢' => '鱾', +'魥' => '𩽹', '魨' => '鲀', '魯' => '鲁', '魴' => '鲂', @@ -12349,15 +12753,15 @@ $zh2Hans = array( '鮊' => '鲌', '鮋' => '鲉', '鮍' => '鲏', -'鮎' => '鲇', '鮐' => '鲐', '鮑' => '鲍', '鮒' => '鲋', '鮓' => '鲊', '鮚' => '鲒', '鮜' => '鲘', -'鮝' => '鲞', '鮞' => '鲕', +'鮟' => '𩽾', +'鮣' => '䲟', '鮦' => '鲖', '鮪' => '鲔', '鮫' => '鲛', @@ -12366,9 +12770,11 @@ $zh2Hans = array( '鮰' => '𫚔', '鮳' => '鲓', '鮶' => '鲪', +'鮸' => '𩾃', '鮺' => '鲝', '鯀' => '鲧', '鯁' => '鲠', +'鯄' => '𩾁', '鯆' => '𫚙', '鯇' => '鲩', '鯉' => '鲤', @@ -12387,19 +12793,21 @@ $zh2Hans = array( '鯨' => '鲸', '鯪' => '鲮', '鯫' => '鲰', -'鯰' => '鲇', +'鯱' => '𩾇', '鯴' => '鲺', +'鯶' => '𩽼', '鯷' => '鳀', '鯽' => '鲫', '鯿' => '鳊', '鰁' => '鳈', '鰂' => '鲗', '鰃' => '鳂', +'鰆' => '䲠', '鰈' => '鲽', '鰉' => '鳇', +'鰌' => '䲡', '鰍' => '鳅', '鰏' => '鲾', -'鰐' => '鳄', '鰒' => '鳆', '鰓' => '鳃', '鰜' => '鳒', @@ -12408,6 +12816,7 @@ $zh2Hans = array( '鰣' => '鲥', '鰤' => '𫚕', '鰥' => '鳏', +'鰧' => '䲢', '鰨' => '鳎', '鰩' => '鳐', '鰭' => '鳍', @@ -12424,6 +12833,7 @@ $zh2Hans = array( '鰾' => '鳔', '鱂' => '鳉', '鱅' => '鳙', +'鱇' => '𩾌', '鱈' => '鳕', '鱉' => '鳖', '鱒' => '鳟', @@ -12447,12 +12857,12 @@ $zh2Hans = array( '鳥' => '鸟', '鳧' => '凫', '鳩' => '鸠', -'鳬' => '凫', '鳲' => '鸤', '鳳' => '凤', '鳴' => '鸣', '鳶' => '鸢', '鳷' => '𫛛', +'鳼' => '𪉃', '鳾' => '䴓', '鴃' => '𫛞', '鴆' => '鸩', @@ -12462,6 +12872,7 @@ $zh2Hans = array( '鴕' => '鸵', '鴗' => '𫁡', '鴛' => '鸳', +'鴜' => '𪉈', '鴝' => '鸲', '鴞' => '鸮', '鴟' => '鸱', @@ -12470,6 +12881,7 @@ $zh2Hans = array( '鴨' => '鸭', '鴯' => '鸸', '鴰' => '鸹', +'鴲' => '𪉆', '鴴' => '鸻', '鴷' => '䴕', '鴻' => '鸿', @@ -12481,6 +12893,7 @@ $zh2Hans = array( '鵑' => '鹃', '鵒' => '鹆', '鵓' => '鹁', +'鵚' => '𪉍', '鵜' => '鹈', '鵝' => '鹅', '鵠' => '鹄', @@ -12516,19 +12929,19 @@ $zh2Hans = array( '鶻' => '鹘', '鶼' => '鹣', '鶿' => '鹚', -'鷀' => '鹚', '鷁' => '鹢', '鷂' => '鹞', -'鷄' => '鸡', '鷈' => '䴘', '鷊' => '鹝', '鷓' => '鹧', +'鷔' => '𪉑', '鷖' => '鹥', '鷗' => '鸥', '鷙' => '鸷', '鷚' => '鹨', '鷥' => '鸶', '鷦' => '鹪', +'鷨' => '𪉊', '鷫' => '鹔', '鷯' => '鹩', '鷲' => '鹫', @@ -12556,10 +12969,12 @@ $zh2Hans = array( '鹽' => '盐', '麗' => '丽', '麥' => '麦', +'麨' => '𪎊', '麩' => '麸', '麪' => '面', '麫' => '面', '麯' => '曲', +'麲' => '𪎉', '麴' => '曲', '麵' => '面', '麼' => '么', @@ -12605,25 +13020,167 @@ $zh2Hans = array( '龔' => '龚', '龕' => '龛', '龜' => '龟', +'龭' => '𩨎', +'龯' => '𨱆', +'𠌥' => '𠆿', +'𠏢' => '𠉗', +'𠞆' => '𠛆', +'𠠎' => '𠚳', +'𡄔' => '𠴢', +'𡄣' => '𠵸', +'𡅏' => '𠲥', +'𡑭' => '𡋗', +'𡓾' => '𡋀', '𡞵' => '㛟', '𡠹' => '㛿', '𡢃' => '㛠', +'𡮉' => '𡭜', +'𡮣' => '𡭬', '𡻕' => '岁', +'𡾱' => '㟜', +'𢣚' => '𢘝', +'𢣭' => '𢘞', +'𢶫' => '𢫞', +'𢷮' => '𢫊', +'𢹿' => '𢬦', +'𣙎' => '㭣', +'𣝕' => '𣘷', +'𣞻' => '𣘓', +'𣠲' => '𣑶', +'𣯴' => '𣭤', +'𣾷' => '㳢', +'𣿉' => '𣶫', +'𤁣' => '𣺽', +'𤒎' => '𤊀', '𤪺' => '㻘', '𤫩' => '㻏', +'𤳸' => '𤳄', +'𤸫' => '𤶧', +'𥌃' => '𥅘', +'𥕥' => '𥐰', +'𥖅' => '𥐯', +'𥢢' => '䅪', +'𥨐' => '𥧂', +'𥵃' => '𥱔', +'𥵊' => '𥭉', +'𥸠' => '𥮋', +'𥼽' => '𥹥', +'𥽖' => '𥺇', +'𥿊' => '𦈈', +'𦂅' => '𦈒', +'𦃄' => '𦈗', +'𦢈' => '𣍨', +'𦣎' => '𦟗', +'𦪽' => '𦨩', +'𧔥' => '𧒭', +'𧜗' => '䘞', '𧜵' => '䙊', '𧝞' => '䘛', -'𧦧' => '𫍟', '𧩙' => '䜥', +'𧳟' => '𧳕', '𧵳' => '䞌', +'𧶔' => '𧹓', +'𧶧' => '䞎', +'𨄣' => '𨀱', +'𨅍' => '𨁴', +'𨇁' => '𧿈', +'𨇞' => '𨅫', +'𨈊' => '𨂺', +'𨈌' => '𨄄', +'𨊰' => '䢀', +'𨊸' => '䢁', +'𨊻' => '𨐆', '𨋢' => '䢂', +'𨎮' => '𨐉', +'𨏠' => '𨐇', +'𨏥' => '𨐊', +'𨤻' => '𨤰', +'𨥛' => '𨱀', '𨦫' => '䦀', '𨧜' => '䦁', +'𨧱' => '𨱊', +'𨫒' => '𨱐', +'𨮂' => '𨱕', '𨯅' => '䥿', +'𨳑' => '𨸁', +'𨳕' => '𨸀', +'𨴗' => '𨸅', +'𨵩' => '𨸆', +'𨵸' => '𨸇', +'𨶀' => '𨸉', +'𨶏' => '𨸊', +'𨶮' => '𨸌', +'𨶲' => '𨸋', +'𨷲' => '𨸎', +'𨽏' => '𨸘', +'𩎢' => '𩏾', +'𩏪' => '𩏽', +'𩓣' => '𩖕', +'𩗀' => '𩙦', +'𩘀' => '𩙩', +'𩘝' => '𩙭', +'𩘹' => '𩙨', +'𩘺' => '𩙬', +'𩙈' => '𩙰', +'𩚛' => '𩟿', +'𩚥' => '𩠀', +'𩚵' => '𩠁', +'𩛆' => '𩠂', +'𩛩' => '𩠃', +'𩜇' => '𩠉', +'𩜦' => '𩠆', +'𩜵' => '𩠊', +'𩝔' => '𩠋', +'𩞄' => '𩠎', +'𩞦' => '𩠏', +'𩞯' => '䭪', +'𩟐' => '𩠅', +'𩠴' => '𩠠', +'𩡺' => '𩧦', +'𩢡' => '𩧬', +'𩢴' => '𩧵', +'𩢸' => '𩧳', +'𩢾' => '𩧮', +'𩣏' => '𩧶', '𩣑' => '䯃', '𩣵' => '𩧻', +'𩣺' => '𩧼', +'𩤊' => '𩧩', +'𩤙' => '𩨆', +'𩤲' => '𩨉', +'𩤸' => '𩨅', +'𩥄' => '𩨋', +'𩥇' => '𩨍', +'𩥉' => '𩧱', +'𩥑' => '𩨌', +'𩧆' => '𩨐', +'𩭙' => '𩬣', +'𩯳' => '𩯒', +'𩰀' => '𩬤', +'𩳤' => '𩲒', +'𩵩' => '𩽺', +'𩵹' => '𩽻', '𩶘' => '䲞', -'𫚒' => '軿', +'𩶰' => '𩽿', +'𩶱' => '𩽽', +'𩷰' => '𩾄', +'𩸃' => '𩾅', +'𩸦' => '𩾆', +'𩿪' => '𪉄', +'𪀦' => '𪉅', +'𪀾' => '𪉋', +'𪁈' => '𪉉', +'𪁖' => '𪉌', +'𪂆' => '𪉎', +'𪃍' => '𪉐', +'𪃏' => '𪉏', +'𪄆' => '𪉔', +'𪄕' => '𪉒', +'𪇳' => '𪉕', +'𪋿' => '𪎍', +'𪔵' => '𪔭', +'𪘀' => '𪚏', +'𪘯' => '𪚐', '《易乾' => '《易乾', '不著痕跡' => '不着痕迹', '不著邊際' => '不着边际', @@ -12762,8 +13319,8 @@ $zh2Hans = array( '乾曜' => '乾曜', '乾构' => '乾构', '乾構' => '乾构', -'乾枢' => '乾枢', '乾樞' => '乾枢', +'乾枢' => '乾枢', '乾栋' => '乾栋', '乾棟' => '乾栋', '乾步' => '乾步', @@ -13473,6 +14030,7 @@ $zh2Hans = array( '尋著稱' => '寻著称', '尋著者' => '寻著者', '尋著述' => '寻著述', +'將軍抽俥' => '将军抽俥', '將軍抽車' => '将军抽車', '尼乾陀' => '尼乾陀', '展著' => '展着', @@ -14790,6 +15348,8 @@ $zh2Hans = array( '繞著稱' => '绕著称', '繞著者' => '绕著者', '繞著述' => '绕著述', +'綳著勁' => '绷着劲', +'綳著臉' => '绷着脸', '編著' => '编著', '纏著' => '缠着', '纏著書' => '缠著书', @@ -14918,7 +15478,9 @@ $zh2Hans = array( '著者' => '著者', '著身' => '著身', '著述' => '著述', +'蒙汗葯' => '蒙汗药', '蒙著' => '蒙着', +'蒙葯' => '蒙药', '蒙著書' => '蒙著书', '蒙著书' => '蒙著书', '蒙著作' => '蒙著作', @@ -15512,7 +16074,6 @@ $zh2Hans = array( '鬱氏' => '鬱氏', '魏徵' => '魏徵', '魚乾乾' => '鱼干干', -'鯰魚' => '鲶鱼', '麯崇裕' => '麯崇裕', '麴義' => '麴义', '麴义' => '麴义', diff --git a/includes/actions/InfoAction.php b/includes/actions/InfoAction.php index e986323bac..29c3d7e35a 100644 --- a/includes/actions/InfoAction.php +++ b/includes/actions/InfoAction.php @@ -234,6 +234,12 @@ class InfoAction extends FormlessAction { // Page ID (number not localised, as it's a database ID) $pageInfo['header-basic'][] = array( $this->msg( 'pageinfo-article-id' ), $id ); + // Language in which the page content is (supposed to be) written + $pageLang = $title->getPageLanguage()->getCode(); + $pageInfo['header-basic'][] = array( $this->msg( 'pageinfo-language' ), + Language::fetchLanguageName( $pageLang, $lang->getCode() ) + . ' ' . $this->msg( 'parentheses', $pageLang ) ); + // Search engine status $pOutput = new ParserOutput(); if ( isset( $pageProperties['noindex'] ) ) { diff --git a/includes/api/ApiEditPage.php b/includes/api/ApiEditPage.php index ca62bc6930..4cb91bc9e8 100644 --- a/includes/api/ApiEditPage.php +++ b/includes/api/ApiEditPage.php @@ -246,6 +246,11 @@ class ApiEditPage extends ApiBase { $requestArray['wpSectionTitle'] = $params['sectiontitle']; } + // TODO: Pass along information from 'undoafter' as well + if ( $params['undo'] > 0 ) { + $requestArray['wpUndidRevision'] = $params['undo']; + } + // Watch out for basetimestamp == '' // wfTimestamp() treats it as NOW, almost certainly causing an edit conflict if ( !is_null( $params['basetimestamp'] ) && $params['basetimestamp'] != '' ) { @@ -568,7 +573,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.", diff --git a/includes/api/ApiMain.php b/includes/api/ApiMain.php index 3aa51b7967..91b8cc834b 100644 --- a/includes/api/ApiMain.php +++ b/includes/api/ApiMain.php @@ -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 ) ) @@ -376,7 +376,12 @@ class ApiMain extends ApiBase { // Log it if ( !( $e instanceof UsageException ) ) { - wfDebugLog( 'exception', $e->getLogMessage() ); + global $wgLogExceptionBacktrace; + if ( $wgLogExceptionBacktrace ) { + wfDebugLog( 'exception', $e->getLogMessage() . "\n" . $e->getTraceAsString() . "\n" ); + } else { + wfDebugLog( 'exception', $e->getLogMessage() ); + } } // Handle any kind of exception by outputing properly formatted error message. diff --git a/includes/api/ApiParse.php b/includes/api/ApiParse.php index fae8e690b0..12c20fb596 100644 --- a/includes/api/ApiParse.php +++ b/includes/api/ApiParse.php @@ -147,6 +147,9 @@ class ApiParse extends ApiBase { $pageObj = $this->getTitleOrPageId( $pageParams, 'fromdb' ); $titleObj = $pageObj->getTitle(); + if ( !$titleObj || !$titleObj->exists() ) { + $this->dieUsage( "The page you specified doesn't exist", 'missingtitle' ); + } $wgTitle = $titleObj; if ( isset( $prop['revid'] ) ) { @@ -630,7 +633,7 @@ class ApiParse extends ApiBase { 'uselang' => 'Which language to parse the request in', 'section' => 'Only retrieve the content of this section number', 'disablepp' => 'Disable the PP Report from the parser output', - 'generatexml' => 'Generate XML parse tree', + 'generatexml' => 'Generate XML parse tree (requires prop=wikitext)', 'contentformat' => 'Content serialization format used for the input text', 'contentmodel' => 'Content model of the new content', ); diff --git a/includes/api/ApiQuery.php b/includes/api/ApiQuery.php index dff7524d88..d24745cebb 100644 --- a/includes/api/ApiQuery.php +++ b/includes/api/ApiQuery.php @@ -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 ) ) { diff --git a/includes/api/ApiQueryAllUsers.php b/includes/api/ApiQueryAllUsers.php index 7f50cbad2e..79f6469442 100644 --- a/includes/api/ApiQueryAllUsers.php +++ b/includes/api/ApiQueryAllUsers.php @@ -81,12 +81,18 @@ class ApiQueryAllUsers extends ApiQueryBase { $db->buildLike( $this->getCanonicalUserName( $params['prefix'] ), $db->anyString() ) ); } - if ( !is_null( $params['rights'] ) ) { + if ( !is_null( $params['rights'] ) && count( $params['rights'] ) ) { $groups = array(); foreach( $params['rights'] as $r ) { $groups = array_merge( $groups, User::getGroupsWithPermission( $r ) ); } + // no group with the given right(s) exists, no need for a query + if( !count( $groups ) ) { + $this->getResult()->setIndexedTagName_internal( array( 'query', $this->getModuleName() ), '' ); + return; + } + $groups = array_unique( $groups ); if ( is_null( $params['group'] ) ) { diff --git a/includes/api/ApiQueryBlocks.php b/includes/api/ApiQueryBlocks.php index 96b8696240..a8d4a7c327 100644 --- a/includes/api/ApiQueryBlocks.php +++ b/includes/api/ApiQueryBlocks.php @@ -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( diff --git a/includes/api/ApiQueryInfo.php b/includes/api/ApiQueryInfo.php index b617ed05d5..e5cea96421 100644 --- a/includes/api/ApiQueryInfo.php +++ b/includes/api/ApiQueryInfo.php @@ -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]; } diff --git a/includes/api/ApiQueryRevisions.php b/includes/api/ApiQueryRevisions.php index 881b79721b..ad40a6486a 100644 --- a/includes/api/ApiQueryRevisions.php +++ b/includes/api/ApiQueryRevisions.php @@ -261,7 +261,7 @@ class ApiQueryRevisions extends ApiQueryBase { // rvstart and rvstartid when that is supplied. if ( !is_null( $params['continue'] ) ) { $params['startid'] = $params['continue']; - unset( $params['start'] ); + $params['start'] = null; } // This code makes an assumption that sorting by rev_id and rev_timestamp produces @@ -715,9 +715,10 @@ class ApiQueryRevisions extends ApiQueryBase { 'dir' => $this->getDirectionDescription( $p, ' (enum)' ), 'user' => 'Only include revisions made by user (enum)', 'excludeuser' => 'Exclude revisions made by user (enum)', - 'expandtemplates' => 'Expand templates in revision content', - 'generatexml' => 'Generate XML parse tree for revision content', - 'parse' => 'Parse revision content. For performance reasons if this option is used, rvlimit is enforced to 1.', + 'expandtemplates' => "Expand templates in revision content (requires {$p}prop=content)", + 'generatexml' => "Generate XML parse tree for revision content (requires {$p}prop=content)", + 'parse' => array( "Parse revision content (requires {$p}prop=content).", + 'For performance reasons if this option is used, rvlimit is enforced to 1.' ), 'section' => 'Only retrieve the content of this section number', 'token' => 'Which tokens to obtain for each revision', 'continue' => 'When more results are available, use this to continue', diff --git a/includes/api/ApiQueryUsers.php b/includes/api/ApiQueryUsers.php index 1cf8e31cfa..591ace93e1 100644 --- a/includes/api/ApiQueryUsers.php +++ b/includes/api/ApiQueryUsers.php @@ -138,7 +138,7 @@ class ApiQueryUsers extends ApiQueryBase { if ( !isset( $userGroups ) ) { $user = User::newFromRow( $row ); } else { - if ( !is_array( $userGroups[$row->user_name] ) ) { + if ( !isset( $userGroups[$row->user_name] ) || !is_array( $userGroups[$row->user_name] ) ) { $userGroups[$row->user_name] = array(); } $user = User::newFromRow( $row, array( 'user_groups' => $userGroups[$row->user_name] ) ); diff --git a/includes/cache/MessageCache.php b/includes/cache/MessageCache.php index e061101bc6..9bf743667d 100644 --- a/includes/cache/MessageCache.php +++ b/includes/cache/MessageCache.php @@ -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 @@ -862,7 +820,7 @@ class MessageCache { * @param $linestart bool * @param $interface bool * @param $language - * @return ParserOutput + * @return ParserOutput|string */ public function parse( $text, $title = null, $linestart = true, $interface = false, $language = null ) { if ( $this->mInParser ) { @@ -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 diff --git a/includes/conf/Conf.php b/includes/conf/Conf.php deleted file mode 100644 index 22c621fe5a..0000000000 --- a/includes/conf/Conf.php +++ /dev/null @@ -1,202 +0,0 @@ - - * http://www.mediawiki.org/ - * - * 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 - * @defgroup Config Config - */ -abstract class Conf { - /** - * A special value to return when default config items do not exist. Use - * this to differentiate from 'null' which may be a valid config value. - * - * Please don't ever make this a default (or accepted) value for your - * configuration. It's liable to Break Something. - */ - const NO_SUCH_DEFAULT_CONFIG = 'mw-no-such-default-config'; - - /** - * The Wiki ID (usually $wgDBname) - * @var String - */ - private $wikiId; - - /** - * Singleton - * @var Conf - */ - private static $__instance; - - /** - * Stores of the core defaults, extension defaults and wiki overrides - * - * @var array - */ - protected $defaults, $extensionDefaults, $values = array(); - - /** - * Constructor. Children should call this if implementing. - * @param $confConfig Array of config vars - */ - protected function __construct( $confConfig ) { - $this->wikiId = $confConfig['wikiId']; - $this->defaults = (array)(new DefaultSettings); - // @todo implement this: - // $this->initExtensionDefaults(); - $this->initChangedSettings(); - if( isset( $confConfig['exposeGlobals'] ) ) { - $this->exposeGlobals(); - } - } - - /** - * Expose all config variables as globals for back-compat. Ewwww. - */ - private function exposeGlobals() { - $allVars = $this->defaults + $this->extensionDefaults + $this->values; - foreach( $allVars as $name => $value ) { - $var = 'wg' . ucfirst( $name ); - $GLOBALS[$var] = $value; - } - } - - /** - * Load customized settings from whatever the data store is - */ - abstract protected function initChangedSettings(); - - /** - * Apply a setting to the backend store - * @param $name String Name of the setting - * @param $value mixed Value to store - */ - abstract protected function writeSetting( $name, $value ); - - /** - * Initialize a new child class based on a configuration array - * @param $conf Array of configuration settings, see $wgConfiguration - * for details - * @throws MWException - * @return Conf - */ - private static function newFromSettings( $conf ) { - $class = ucfirst( $conf['type'] ) . 'Conf'; - if( !class_exists( $class ) ) { - throw new MWException( '$wgConfiguration misconfigured with invalid "type"' ); - } - return new $class( $conf ); - } - - /** - * Get the singleton if we don't want a specific wiki - * @param bool|string $wiki An id for a remote wiki - * @throws MWException - * @return Conf child - */ - public static function load( $wiki = false ) { - throw new MWException( "Not working yet, don't attempt to use this" ); - if( !self::$__instance ) { - /**global $wgConfiguration; - self::$__instance = self::newFromSettings( $wgConfiguration );*/ - } - if( $wiki && $wiki != self::$__instance->getWikiId() ) { - // Load configuration for a different wiki, not sure how - // we're gonna do this yet - return null; - } - return self::$__instance; - } - - /** - * Get a property from the configuration database, falling back - * to DefaultSettings if undefined - * @param $name String Name of setting to retrieve. - * @param $wiki String An id for a remote wiki - * @return mixed - */ - public static function get( $name, $wiki = false ) { - return self::load( $wiki )->retrieveSetting( $name ); - } - - /** - * Actually get the setting, checking overrides, extensions, then core. - * - * @param $name String Name of setting to get - * @return mixed - */ - public function retrieveSetting( $name ) { - // isset() is ok here, because the default is to return null anyway. - if( isset( $this->values[$name] ) ) { - return $this->values[$name]; - } elseif( isset( $this->extensionDefaults[$name] ) ) { - return $this->extensionDefaults[$name]; - } elseif( isset( $this->defaults[$name] ) ) { - return $this->defaults[$name]; - } else { - wfDebug( __METHOD__ . " called for unknown configuration item '$name'\n" ); - return null; - } - } - - /** - * Apply a setting to the configuration object. - * @param $name String Name of the config item - * @param $value mixed Any value to use for the key - * @param $write bool Whether to write to the static copy (db, file, etc) - */ - public function applySetting( $name, $value, $write = false ) { - $this->values[$name] = $value; - if( $write && ( $value !== $this->getDefaultSetting( $name ) ) ) { - $this->writeSetting( $name, $value ); - } - } - - /** - * Get the default for a given setting name. Check core and then extensions. - * Will return NO_SUCH_DEFAULT_CONFIG if the config item does not exist. - * - * @param $name String Name of setting - * @return mixed - */ - public function getDefaultSetting( $name ) { - // Use array_key_exists() here, to make sure we return a default - // that's really set to null. - if( array_key_exists( $name, $this->defaults ) ) { - return $this->defaults[$name]; - } elseif( array_key_exists( $name, $this->extensionDefaults ) ) { - return $this->extensionDefaults[$name]; - } else { - wfDebug( __METHOD__ . " called for unknown configuration item '$name'\n" ); - return self::NO_SUCH_DEFAULT_CONFIG; - } - } - - /** - * What is the wiki ID for this site? - * @return String - */ - public function getWikiId() { - return $this->wikiId; - } -} diff --git a/includes/conf/DatabaseConf.php b/includes/conf/DatabaseConf.php deleted file mode 100644 index d8f644deec..0000000000 --- a/includes/conf/DatabaseConf.php +++ /dev/null @@ -1,57 +0,0 @@ - - * http://www.mediawiki.org/ - * - * 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 Config - */ -class DatabaseConf extends Conf { - /** - * @see Conf::initChangedSettings() - */ - protected function initChangedSettings() { - $res = wfGetDB( DB_MASTER )->select( 'config', '*', array(), __METHOD__ ); - foreach( $res as $row ) { - $this->values[$row->cf_name] = unserialize( $row->cf_value ); - } - } - - /** - * @see Conf::writeSetting() - * - * @param $name - * @param $value - * - * @return bool - */ - protected function writeSetting( $name, $value ) { - $dbw = wfGetDB( DB_MASTER ); - $value = serialize( $value ); - if( $dbw->selectRow( 'config', 'cf_name', array( 'cf_name' => $name ), __METHOD__ ) ) { - $dbw->update( 'config', array( 'cf_value' => $value ), - array( 'cf_name' => $name ), __METHOD__ ); - } else { - $dbw->insert( 'config', - array( 'cf_name' => $name, 'cf_value' => $value ), __METHOD__ ); - } - return (bool)$dbw->affectedRows(); - } -} diff --git a/includes/conf/DefaultSettings.php b/includes/conf/DefaultSettings.php deleted file mode 100644 index 4601f048a4..0000000000 --- a/includes/conf/DefaultSettings.php +++ /dev/null @@ -1,28 +0,0 @@ - - * http://www.mediawiki.org/ - * - * 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 Config - */ -final class DefaultSettings { - public $mySetting = 'defaultValue'; -} diff --git a/includes/content/AbstractContent.php b/includes/content/AbstractContent.php index 0a8bb9e997..386f55aee5 100644 --- a/includes/content/AbstractContent.php +++ b/includes/content/AbstractContent.php @@ -411,4 +411,30 @@ abstract class AbstractContent implements Content { public function matchMagicWord( MagicWord $word ) { return false; } + + /** + * @see Content::convert() + * + * This base implementation calls the hook ConvertContent to enable custom conversions. + * Subclasses may override this to implement conversion for "their" content model. + * + * @param String $toModel the desired content model, use the CONTENT_MODEL_XXX flags. + * @param String $lossy flag, set to "lossy" to allow lossy conversion. If lossy conversion is + * not allowed, full round-trip conversion is expected to work without losing information. + * + * @return Content|bool A content object with the content model $toModel, or false if + * that conversion is not supported. + */ + public function convert( $toModel, $lossy = '' ) { + if ( $this->getModel() === $toModel ) { + //nothing to do, shorten out. + return $this; + } + + $lossy = ( $lossy === 'lossy' ); // string flag, convert to boolean for convenience + $result = false; + + wfRunHooks( 'ConvertContent', array( $this, $toModel, $lossy, &$result ) ); + return $result; + } } diff --git a/includes/content/Content.php b/includes/content/Content.php index 66d720955d..35b51c346f 100644 --- a/includes/content/Content.php +++ b/includes/content/Content.php @@ -42,7 +42,7 @@ interface Content { /** * @since 1.21 * - * @return string The wikitext to include when another page includes this + * @return string|false The wikitext to include when another page includes this * content, or false if the content is not includable in a wikitext page. * * @todo allow native handling, bypassing wikitext representation, like @@ -241,7 +241,6 @@ interface Content { */ public function isCountable( $hasLinks = null ); - /** * Parse the Content object and generate a ParserOutput from the result. * $result->getText() can be used to obtain the generated HTML. If no HTML @@ -262,7 +261,7 @@ interface Content { public function getParserOutput( Title $title, $revId = null, ParserOptions $options = null, $generateHtml = true ); - # TODO: make RenderOutput and RenderOptions base classes + // TODO: make RenderOutput and RenderOptions base classes /** * Returns a list of DataUpdate objects for recording information about this @@ -381,7 +380,7 @@ interface Content { * * @since 1.21 * - * @param $section Empty/null/false or a section number (0, 1, 2, T1, T2...), or "new" + * @param $section null/false or a section number (0, 1, 2, T1, T2...), or "new" * @param $with Content: new content of the section * @param $sectionTitle String: new section's subject, only if $section is 'new' * @return string Complete article text, or null if error @@ -396,10 +395,10 @@ interface Content { * * @param $title Title * @param $user User - * @param $popts null|ParserOptions + * @param $parserOptions null|ParserOptions * @return Content */ - public function preSaveTransform( Title $title, User $user, ParserOptions $popts ); + public function preSaveTransform( Title $title, User $user, ParserOptions $parserOptions ); /** * Returns a new WikitextContent object with the given section heading @@ -420,10 +419,10 @@ interface Content { * @since 1.21 * * @param $title Title - * @param $popts null|ParserOptions + * @param $parserOptions null|ParserOptions * @return Content */ - public function preloadTransform( Title $title, ParserOptions $popts ); + public function preloadTransform( Title $title, ParserOptions $parserOptions ); /** * Prepare Content for saving. Called before Content is saved by WikiPage::doEditContent() and in @@ -482,9 +481,22 @@ interface Content { */ public function matchMagicWord( MagicWord $word ); - # TODO: ImagePage and CategoryPage interfere with per-content action handlers - # TODO: nice&sane integration of GeSHi syntax highlighting - # [11:59] Hooks are ugly; make CodeHighlighter interface and a - # config to set the class which handles syntax highlighting - # [12:00] And default it to a DummyHighlighter + /** + * Converts this content object into another content object with the given content model, + * if that is possible. + * + * @param String $toModel the desired content model, use the CONTENT_MODEL_XXX flags. + * @param String $lossy flag, set to "lossy" to allow lossy conversion. If lossy conversion is + * not allowed, full round-trip conversion is expected to work without losing information. + * + * @return Content|bool A content object with the content model $toModel, or false if + * that conversion is not supported. + */ + public function convert( $toModel, $lossy = '' ); + + // TODO: ImagePage and CategoryPage interfere with per-content action handlers + // TODO: nice&sane integration of GeSHi syntax highlighting + // [11:59] Hooks are ugly; make CodeHighlighter interface and a + // config to set the class which handles syntax highlighting + // [12:00] And default it to a DummyHighlighter } diff --git a/includes/content/ContentHandler.php b/includes/content/ContentHandler.php index 9c4c3afc94..b61dc34e4b 100644 --- a/includes/content/ContentHandler.php +++ b/includes/content/ContentHandler.php @@ -582,8 +582,6 @@ abstract class ContentHandler { $rcid = 0, # FIXME: use everywhere! $refreshCache = false, $unhide = false ) { - $this->checkModelID( $context->getTitle()->getContentModel() ); - $diffEngineClass = $this->getDiffEngineClass(); return new $diffEngineClass( $context, $old, $new, $rcid, $refreshCache, $unhide ); @@ -607,15 +605,17 @@ abstract class ContentHandler { * @return Language the page's language */ public function getPageLanguage( Title $title, Content $content = null ) { - global $wgContLang; + global $wgContLang, $wgLang; + $pageLang = $wgContLang; if ( $title->getNamespace() == NS_MEDIAWIKI ) { // Parse mediawiki messages with correct target language list( /* $unused */, $lang ) = MessageCache::singleton()->figureMessage( $title->getText() ); - return wfGetLangObj( $lang ); + $pageLang = wfGetLangObj( $lang ); } - return $wgContLang; + wfRunHooks( 'PageContentLanguage', array( $title, &$pageLang, $wgLang ) ); + return wfGetLangObj( $pageLang ); } /** @@ -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 ); diff --git a/includes/content/TextContent.php b/includes/content/TextContent.php index 048ac396d3..872738b4fe 100644 --- a/includes/content/TextContent.php +++ b/includes/content/TextContent.php @@ -33,6 +33,9 @@ class TextContent extends AbstractContent { parent::__construct( $model_id ); if ( $text === null || $text === false ) { + wfWarn( "TextContent constructed with \$text = " . var_export( $text, true ) . "! " + . "This may indicate an error in the caller's scope." ); + $text = ''; } @@ -112,12 +115,21 @@ class TextContent extends AbstractContent { } /** - * Returns the text represented by this Content object, as a string. + * Returns attempts to convert this content object to wikitext, + * and then returns the text string. The conversion may be lossy. * - * @return string: the raw text + * @note: this allows any text-based content to be transcluded as if it was wikitext. + * + * @return string|false: the raw text, or null if the conversion failed */ public function getWikitextForTransclusion( ) { - return $this->getNativeData(); + $wikitext = $this->convert( CONTENT_MODEL_WIKITEXT, 'lossy' ); + + if ( $wikitext ) { + return $wikitext->getNativeData(); + } else { + return false; + } } /** @@ -234,4 +246,35 @@ class TextContent extends AbstractContent { # TODO: make Highlighter interface, use highlighter here, if available return htmlspecialchars( $this->getNativeData() ); } + + /** + * @see Content::convert() + * + * This implementation provides lossless conversion between content models based + * on TextContent. + * + * @param String $toModel the desired content model, use the CONTENT_MODEL_XXX flags. + * @param String $lossy flag, set to "lossy" to allow lossy conversion. If lossy conversion is + * not allowed, full round-trip conversion is expected to work without losing information. + * + * @return Content|bool A content object with the content model $toModel, or false if + * that conversion is not supported. + */ + public function convert( $toModel, $lossy = '' ) { + $converted = parent::convert( $toModel, $lossy ); + + if ( $converted !== false ) { + return $converted; + } + + $toHandler = ContentHandler::getForModelID( $toModel ); + + if ( $toHandler instanceof TextContentHandler ) { + //NOTE: ignore content serialization format - it's just text anyway. + $text = $this->getNativeData(); + $converted = $toHandler->unserializeContent( $text ); + } + + return $converted; + } } diff --git a/includes/context/RequestContext.php b/includes/context/RequestContext.php index cd2bf556f8..e4de030c74 100644 --- a/includes/context/RequestContext.php +++ b/includes/context/RequestContext.php @@ -93,6 +93,8 @@ class RequestContext implements IContextSource { */ public function setTitle( Title $t ) { $this->title = $t; + // Erase the WikiPage so a new one with the new title gets created. + $this->wikipage = null; } /** @@ -138,6 +140,12 @@ class RequestContext implements IContextSource { * @param $p WikiPage object */ public function setWikiPage( WikiPage $p ) { + $contextTitle = $this->getTitle(); + $pageTitle = $p->getTitle(); + if ( !$contextTitle || !$pageTitle->equals( $contextTitle ) ) { + $this->setTitle( $pageTitle ); + } + // Defer this to the end since setTitle sets it to null. $this->wikipage = $p; } diff --git a/includes/db/Database.php b/includes/db/Database.php index c9d2fda111..db050f2df5 100644 --- a/includes/db/Database.php +++ b/includes/db/Database.php @@ -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 diff --git a/includes/db/DatabaseSqlite.php b/includes/db/DatabaseSqlite.php index 1125d4f37a..d30d984fcc 100644 --- a/includes/db/DatabaseSqlite.php +++ b/includes/db/DatabaseSqlite.php @@ -705,6 +705,14 @@ class DatabaseSqlite extends DatabaseBase { function addQuotes( $s ) { if ( $s instanceof Blob ) { return "x'" . bin2hex( $s->fetch() ) . "'"; + } else if ( strpos( $s, "\0" ) !== false ) { + // SQLite doesn't support \0 in strings, so use the hex representation as a workaround. + // This is a known limitation of SQLite's mprintf function which PDO should work around, + // but doesn't. I have reported this to php.net as bug #63419: + // https://bugs.php.net/bug.php?id=63419 + // There was already a similar report for SQLite3::escapeString, bug #62361: + // https://bugs.php.net/bug.php?id=62361 + return "x'" . bin2hex( $s ) . "'"; } else { return $this->mConn->quote( $s ); } diff --git a/includes/db/ORMRow.php b/includes/db/ORMRow.php index fa25868d7a..affd65f99a 100644 --- a/includes/db/ORMRow.php +++ b/includes/db/ORMRow.php @@ -263,8 +263,10 @@ abstract class ORMRow implements IORMRow { switch ( $type ) { case 'array': $value = (array)$value; + // fall-through! case 'blob': $value = serialize( $value ); + // fall-through! } $values[$this->table->getPrefixedField( $name )] = $value; @@ -347,7 +349,7 @@ abstract class ORMRow implements IORMRow { * @return boolean Success indicator */ protected function saveExisting( $functionName = null ) { - $dbw = wfGetDB( DB_MASTER ); + $dbw = $this->table->getWriteDbConnection(); $success = $dbw->update( $this->table->getName(), @@ -356,6 +358,8 @@ abstract class ORMRow implements IORMRow { is_null( $functionName ) ? __METHOD__ : $functionName ); + $this->table->releaseConnection( $dbw ); + // DatabaseBase::update does not always return true for success as documented... return $success !== false; } @@ -383,13 +387,13 @@ abstract class ORMRow implements IORMRow { * @return boolean Success indicator */ protected function insert( $functionName = null, array $options = null ) { - $dbw = wfGetDB( DB_MASTER ); + $dbw = $this->table->getWriteDbConnection(); $success = $dbw->insert( $this->table->getName(), $this->getWriteValues(), is_null( $functionName ) ? __METHOD__ : $functionName, - is_null( $options ) ? array( 'IGNORE' ) : $options + $options ); // DatabaseBase::insert does not always return true for success as documented... @@ -399,6 +403,8 @@ abstract class ORMRow implements IORMRow { $this->setField( 'id', $dbw->insertId() ); } + $this->table->releaseConnection( $dbw ); + return $success; } @@ -558,7 +564,7 @@ abstract class ORMRow implements IORMRow { $absoluteAmount = abs( $amount ); $isNegative = $amount < 0; - $dbw = wfGetDB( DB_MASTER ); + $dbw = $this->table->getWriteDbConnection(); $fullField = $this->table->getPrefixedField( $field ); @@ -573,6 +579,8 @@ abstract class ORMRow implements IORMRow { $this->setField( $field, $this->getField( $field ) + $amount ); } + $this->table->releaseConnection( $dbw ); + return $success; } diff --git a/includes/diff/DairikiDiff.php b/includes/diff/DairikiDiff.php index 72eb5d3c2c..05e2cd2925 100644 --- a/includes/diff/DairikiDiff.php +++ b/includes/diff/DairikiDiff.php @@ -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/diff/DifferenceEngine.php b/includes/diff/DifferenceEngine.php index f3dc5a3a00..0295f776d1 100644 --- a/includes/diff/DifferenceEngine.php +++ b/includes/diff/DifferenceEngine.php @@ -522,8 +522,10 @@ class DifferenceEngine extends ContextSource { if ( ContentHandler::runLegacyHooks( 'ShowRawCssJs', array( $this->mNewContent, $this->mNewPage, $out ) ) ) { // NOTE: deprecated hook, B/C only // use the content object's own rendering - $po = $this->mNewRev->getContent()->getParserOutput( $this->mNewRev->getTitle(), $this->mNewRev->getId() ); - $out->addHTML( $po->getText() ); + $cnt = $this->mNewRev->getContent(); + $po = $cnt ? $cnt->getParserOutput( $this->mNewRev->getTitle(), $this->mNewRev->getId() ) : null; + $txt = $po ? $po->getText() : ''; + $out->addHTML( $txt ); } } elseif( !wfRunHooks( 'ArticleContentViewCustom', array( $this->mNewContent, $this->mNewPage, $out ) ) ) { // Handled by extension @@ -545,7 +547,7 @@ class DifferenceEngine extends ContextSource { $parserOutput = $this->getParserOutput( $wikiPage, $this->mNewRev ); # Also try to load it as a redirect - $rt = $this->mNewContent->getRedirectTarget(); + $rt = $this->mNewContent ? $this->mNewContent->getRedirectTarget() : null; if ( $rt ) { $article = Article::newFromTitle( $this->mNewPage, $this->getContext() ); @@ -1169,13 +1171,13 @@ class DifferenceEngine extends ContextSource { } if ( $this->mOldRev ) { $this->mOldContent = $this->mOldRev->getContent( Revision::FOR_THIS_USER, $this->getUser() ); - if ( $this->mOldContent === false ) { + if ( $this->mOldContent === null ) { return false; } } if ( $this->mNewRev ) { $this->mNewContent = $this->mNewRev->getContent( Revision::FOR_THIS_USER, $this->getUser() ); - if ( $this->mNewContent === false ) { + if ( $this->mNewContent === null ) { return false; } } diff --git a/includes/filebackend/FSFileBackend.php b/includes/filebackend/FSFileBackend.php index dd43f82921..3a03d4d12b 100644 --- a/includes/filebackend/FSFileBackend.php +++ b/includes/filebackend/FSFileBackend.php @@ -190,21 +190,9 @@ class FSFileBackend extends FileBackendStore { return $status; } - if ( file_exists( $dest ) ) { - if ( !empty( $params['overwrite'] ) ) { - $ok = unlink( $dest ); - if ( !$ok ) { - $status->fatal( 'backend-fail-delete', $params['dst'] ); - return $status; - } - } else { - $status->fatal( 'backend-fail-alreadyexists', $params['dst'] ); - return $status; - } - } - if ( !empty( $params['async'] ) ) { // deferred - $cmd = implode( ' ', array( wfIsWindows() ? 'COPY' : 'cp', + $cmd = implode( ' ', array( + wfIsWindows() ? 'COPY /B /Y' : 'cp', // (binary, overwrite) wfEscapeShellArg( $this->cleanPathSlashes( $params['src'] ) ), wfEscapeShellArg( $this->cleanPathSlashes( $dest ) ) ) ); @@ -255,21 +243,16 @@ class FSFileBackend extends FileBackendStore { return $status; } - if ( file_exists( $dest ) ) { - if ( !empty( $params['overwrite'] ) ) { - $ok = unlink( $dest ); - if ( !$ok ) { - $status->fatal( 'backend-fail-delete', $params['dst'] ); - return $status; - } - } else { - $status->fatal( 'backend-fail-alreadyexists', $params['dst'] ); - return $status; + if ( !is_file( $source ) ) { + if ( empty( $params['ignoreMissingSource'] ) ) { + $status->fatal( 'backend-fail-copy', $params['src'] ); } + return $status; // do nothing; either OK or bad status } if ( !empty( $params['async'] ) ) { // deferred - $cmd = implode( ' ', array( wfIsWindows() ? 'COPY' : 'cp', + $cmd = implode( ' ', array( + wfIsWindows() ? 'COPY /B /Y' : 'cp', // (binary, overwrite) wfEscapeShellArg( $this->cleanPathSlashes( $source ) ), wfEscapeShellArg( $this->cleanPathSlashes( $dest ) ) ) ); @@ -320,24 +303,16 @@ class FSFileBackend extends FileBackendStore { return $status; } - if ( file_exists( $dest ) ) { - if ( !empty( $params['overwrite'] ) ) { - // Windows does not support moving over existing files - if ( wfIsWindows() ) { - $ok = unlink( $dest ); - if ( !$ok ) { - $status->fatal( 'backend-fail-delete', $params['dst'] ); - return $status; - } - } - } else { - $status->fatal( 'backend-fail-alreadyexists', $params['dst'] ); - return $status; + if ( !is_file( $source ) ) { + if ( empty( $params['ignoreMissingSource'] ) ) { + $status->fatal( 'backend-fail-move', $params['src'] ); } + return $status; // do nothing; either OK or bad status } if ( !empty( $params['async'] ) ) { // deferred - $cmd = implode( ' ', array( wfIsWindows() ? 'MOVE' : 'mv', + $cmd = implode( ' ', array( + wfIsWindows() ? 'MOVE /Y' : 'mv', // (overwrite) wfEscapeShellArg( $this->cleanPathSlashes( $source ) ), wfEscapeShellArg( $this->cleanPathSlashes( $dest ) ) ) ); @@ -385,7 +360,8 @@ class FSFileBackend extends FileBackendStore { } if ( !empty( $params['async'] ) ) { // deferred - $cmd = implode( ' ', array( wfIsWindows() ? 'DEL' : 'unlink', + $cmd = implode( ' ', array( + wfIsWindows() ? 'DEL' : 'unlink', wfEscapeShellArg( $this->cleanPathSlashes( $source ) ) ) ); $status->value = new FSFileOpHandle( $this, $params, 'Copy', $cmd ); @@ -423,19 +399,6 @@ class FSFileBackend extends FileBackendStore { return $status; } - if ( file_exists( $dest ) ) { - if ( !empty( $params['overwrite'] ) ) { - $ok = unlink( $dest ); - if ( !$ok ) { - $status->fatal( 'backend-fail-delete', $params['dst'] ); - return $status; - } - } else { - $status->fatal( 'backend-fail-alreadyexists', $params['dst'] ); - return $status; - } - } - if ( !empty( $params['async'] ) ) { // deferred $tempFile = TempFSFile::factory( 'create_', 'tmp' ); if ( !$tempFile ) { @@ -447,7 +410,8 @@ class FSFileBackend extends FileBackendStore { $status->fatal( 'backend-fail-create', $params['dst'] ); return $status; } - $cmd = implode( ' ', array( wfIsWindows() ? 'COPY' : 'cp', + $cmd = implode( ' ', array( + wfIsWindows() ? 'COPY /B /Y' : 'cp', // (binary, overwrite) wfEscapeShellArg( $this->cleanPathSlashes( $tempFile->getPath() ) ), wfEscapeShellArg( $this->cleanPathSlashes( $dest ) ) ) ); diff --git a/includes/filebackend/FileBackend.php b/includes/filebackend/FileBackend.php index 0ef4cd0131..b5e231540b 100644 --- a/includes/filebackend/FileBackend.php +++ b/includes/filebackend/FileBackend.php @@ -206,6 +206,7 @@ abstract class FileBackend { * 'dst' => , * 'overwrite' => , * 'overwriteSame' => , + * 'ignoreMissingSource' => , # since 1.21 * 'disposition' => * ) * @endcode @@ -218,6 +219,7 @@ abstract class FileBackend { * 'dst' => , * 'overwrite' => , * 'overwriteSame' => , + * 'ignoreMissingSource' => , # since 1.21 * 'disposition' => * ) * @endcode @@ -427,6 +429,7 @@ abstract class FileBackend { * 'op' => 'copy', * 'src' => , * 'dst' => , + * 'ignoreMissingSource' => , # since 1.21 * 'disposition' => * ) * @endcode @@ -436,6 +439,7 @@ abstract class FileBackend { * 'op' => 'move', * 'src' => , * 'dst' => , + * 'ignoreMissingSource' => , # since 1.21 * 'disposition' => * ) * @endcode @@ -900,6 +904,24 @@ abstract class FileBackend { */ abstract public function getLocalCopyMulti( array $params ); + /** + * Return an HTTP URL to a given file that requires no authentication to use. + * The URL may be pre-authenticated (via some token in the URL) and temporary. + * This will return null if the backend cannot make an HTTP URL for the file. + * + * This is useful for key/value stores when using scripts that seek around + * large files and those scripts (and the backend) support HTTP Range headers. + * Otherwise, one would need to use getLocalReference(), which involves loading + * the entire file on to local disk. + * + * @param $params Array + * $params include: + * - src : source storage path + * @return string|null + * @since 1.21 + */ + abstract public function getFileHttpUrl( array $params ); + /** * Check if a directory exists at a given storage path. * Backends using key/value stores will check if the path is a diff --git a/includes/filebackend/FileBackendMultiWrite.php b/includes/filebackend/FileBackendMultiWrite.php index 90292ee027..a443a3aadd 100644 --- a/includes/filebackend/FileBackendMultiWrite.php +++ b/includes/filebackend/FileBackendMultiWrite.php @@ -651,6 +651,15 @@ class FileBackendMultiWrite extends FileBackend { return $tempFiles; } + /** + * @see FileBackend::getFileHttpUrl() + * @return string|null + */ + public function getFileHttpUrl( array $params ) { + $realParams = $this->substOpPaths( $params, $this->backends[$this->masterIndex] ); + return $this->backends[$this->masterIndex]->getFileHttpUrl( $realParams ); + } + /** * @see FileBackend::directoryExists() * @param $params array diff --git a/includes/filebackend/FileBackendStore.php b/includes/filebackend/FileBackendStore.php index 5f562d2d8c..97e49a5a09 100644 --- a/includes/filebackend/FileBackendStore.php +++ b/includes/filebackend/FileBackendStore.php @@ -72,8 +72,9 @@ abstract class FileBackendStore extends FileBackend { } /** - * Check if a file can be created at a given storage path. - * FS backends should check if the parent directory exists and the file is writable. + * Check if a file can be created or changed at a given storage path. + * FS backends should check if the parent directory exists, files can be + * written under it, and that any file already there is writable. * Backends using key/value stores should check if the container exists. * * @param $storagePath string @@ -83,12 +84,12 @@ abstract class FileBackendStore extends FileBackend { /** * Create a file in the backend with the given contents. + * This will overwrite any file that exists at the destination. * Do not call this function from places outside FileBackend and FileOp. * * $params include: * - content : the raw file contents * - dst : destination storage path - * - overwrite : overwrite any file that exists at the destination * - disposition : Content-Disposition header value for the destination * - async : Status will be returned immediately if supported. * If the status is OK, then its value field will be @@ -106,9 +107,7 @@ abstract class FileBackendStore extends FileBackend { } else { $status = $this->doCreateInternal( $params ); $this->clearCache( array( $params['dst'] ) ); - if ( !empty( $params['overwrite'] ) ) { // file possibly mutated - $this->deleteFileCache( $params['dst'] ); // persistent cache - } + $this->deleteFileCache( $params['dst'] ); // persistent cache } wfProfileOut( __METHOD__ . '-' . $this->name ); wfProfileOut( __METHOD__ ); @@ -122,12 +121,12 @@ abstract class FileBackendStore extends FileBackend { /** * Store a file into the backend from a file on disk. + * This will overwrite any file that exists at the destination. * Do not call this function from places outside FileBackend and FileOp. * * $params include: * - src : source path on disk * - dst : destination storage path - * - overwrite : overwrite any file that exists at the destination * - disposition : Content-Disposition header value for the destination * - async : Status will be returned immediately if supported. * If the status is OK, then its value field will be @@ -145,9 +144,7 @@ abstract class FileBackendStore extends FileBackend { } else { $status = $this->doStoreInternal( $params ); $this->clearCache( array( $params['dst'] ) ); - if ( !empty( $params['overwrite'] ) ) { // file possibly mutated - $this->deleteFileCache( $params['dst'] ); // persistent cache - } + $this->deleteFileCache( $params['dst'] ); // persistent cache } wfProfileOut( __METHOD__ . '-' . $this->name ); wfProfileOut( __METHOD__ ); @@ -161,16 +158,17 @@ abstract class FileBackendStore extends FileBackend { /** * Copy a file from one storage path to another in the backend. + * This will overwrite any file that exists at the destination. * Do not call this function from places outside FileBackend and FileOp. * * $params include: - * - src : source storage path - * - dst : destination storage path - * - overwrite : overwrite any file that exists at the destination - * - disposition : Content-Disposition header value for the destination - * - async : Status will be returned immediately if supported. - * If the status is OK, then its value field will be - * set to a FileBackendStoreOpHandle object. + * - src : source storage path + * - dst : destination storage path + * - ignoreMissingSource : do nothing if the source file does not exist + * - disposition : Content-Disposition header value for the destination + * - async : Status will be returned immediately if supported. + * If the status is OK, then its value field will be + * set to a FileBackendStoreOpHandle object. * * @param $params Array * @return Status @@ -180,9 +178,7 @@ abstract class FileBackendStore extends FileBackend { wfProfileIn( __METHOD__ . '-' . $this->name ); $status = $this->doCopyInternal( $params ); $this->clearCache( array( $params['dst'] ) ); - if ( !empty( $params['overwrite'] ) ) { // file possibly mutated - $this->deleteFileCache( $params['dst'] ); // persistent cache - } + $this->deleteFileCache( $params['dst'] ); // persistent cache wfProfileOut( __METHOD__ . '-' . $this->name ); wfProfileOut( __METHOD__ ); return $status; @@ -225,16 +221,17 @@ abstract class FileBackendStore extends FileBackend { /** * Move a file from one storage path to another in the backend. + * This will overwrite any file that exists at the destination. * Do not call this function from places outside FileBackend and FileOp. * * $params include: - * - src : source storage path - * - dst : destination storage path - * - overwrite : overwrite any file that exists at the destination - * - disposition : Content-Disposition header value for the destination - * - async : Status will be returned immediately if supported. - * If the status is OK, then its value field will be - * set to a FileBackendStoreOpHandle object. + * - src : source storage path + * - dst : destination storage path + * - ignoreMissingSource : do nothing if the source file does not exist + * - disposition : Content-Disposition header value for the destination + * - async : Status will be returned immediately if supported. + * If the status is OK, then its value field will be + * set to a FileBackendStoreOpHandle object. * * @param $params Array * @return Status @@ -245,9 +242,7 @@ abstract class FileBackendStore extends FileBackend { $status = $this->doMoveInternal( $params ); $this->clearCache( array( $params['src'], $params['dst'] ) ); $this->deleteFileCache( $params['src'] ); // persistent cache - if ( !empty( $params['overwrite'] ) ) { // file possibly mutated - $this->deleteFileCache( $params['dst'] ); // persistent cache - } + $this->deleteFileCache( $params['dst'] ); // persistent cache wfProfileOut( __METHOD__ . '-' . $this->name ); wfProfileOut( __METHOD__ ); return $status; @@ -809,6 +804,14 @@ abstract class FileBackendStore extends FileBackend { */ abstract protected function doGetLocalCopyMulti( array $params ); + /** + * @see FileBackend::getFileHttpUrl() + * @return string|null + */ + public function getFileHttpUrl( array $params ) { + return null; // not supported + } + /** * @see FileBackend::streamFile() * @return Status diff --git a/includes/filebackend/FileOp.php b/includes/filebackend/FileOp.php index 7c43c48908..ff1b604337 100644 --- a/includes/filebackend/FileOp.php +++ b/includes/filebackend/FileOp.php @@ -45,6 +45,7 @@ abstract class FileOp { protected $useLatest = true; // boolean protected $batchId; // string + protected $doOperation = true; // boolean; operation is not a no-op protected $sourceSha1; // string protected $destSameAsSource; // boolean @@ -65,19 +66,53 @@ abstract class FileOp { list( $required, $optional ) = $this->allowedParams(); foreach ( $required as $name ) { if ( isset( $params[$name] ) ) { - $this->params[$name] = $params[$name]; + $this->params[$name] = self::normalizeAnyStoragePaths( $params[$name] ); } else { throw new MWException( "File operation missing parameter '$name'." ); } } foreach ( $optional as $name ) { if ( isset( $params[$name] ) ) { - $this->params[$name] = $params[$name]; + $this->params[$name] = self::normalizeAnyStoragePaths( $params[$name] ); } } $this->params = $params; } + /** + * Normalize $item or anything in $item that is a valid storage path + * + * @param $item string|array + * @return string|Array + */ + protected function normalizeAnyStoragePaths( $item ) { + if ( is_array( $item ) ) { + $res = array(); + foreach ( $item as $k => $v ) { + $k = self::normalizeIfValidStoragePath( $k ); + $v = self::normalizeIfValidStoragePath( $v ); + $res[$k] = $v; + } + return $res; + } else { + return self::normalizeIfValidStoragePath( $item ); + } + } + + /** + * Normalize a string if it is a valid storage path + * + * @param $path string + * @return string + */ + protected static function normalizeIfValidStoragePath( $path ) { + if ( FileBackend::isStoragePath( $path ) ) { + $res = FileBackend::normalizeStoragePath( $path ); + return ( $res !== null ) ? $res : $path; + } + return $path; + } + /** * Set the batch UUID this operation belongs to * @@ -175,11 +210,14 @@ abstract class FileOp { * @return Array */ final public function getJournalEntries( array $oPredicates, array $nPredicates ) { + if ( !$this->doOperation ) { + return array(); // this is a no-op + } $nullEntries = array(); $updateEntries = array(); $deleteEntries = array(); $pathsUsed = array_merge( $this->storagePathsRead(), $this->storagePathsChanged() ); - foreach ( $pathsUsed as $path ) { + foreach ( array_unique( $pathsUsed ) as $path ) { $nullEntries[] = array( // assertion for recovery 'op' => 'null', 'path' => $path, @@ -205,7 +243,9 @@ abstract class FileOp { } /** - * Check preconditions of the operation without writing anything + * Check preconditions of the operation without writing anything. + * This must update $predicates for each path that the op can change + * except when a failing status object is returned. * * @param $predicates Array * @return Status @@ -241,10 +281,14 @@ abstract class FileOp { return Status::newFatal( 'fileop-fail-attempt-precheck' ); } $this->state = self::STATE_ATTEMPTED; - $status = $this->doAttempt(); - if ( !$status->isOK() ) { - $this->failed = true; - $this->logFailure( 'attempt' ); + if ( $this->doOperation ) { + $status = $this->doAttempt(); + if ( !$status->isOK() ) { + $this->failed = true; + $this->logFailure( 'attempt' ); + } + } else { // no-op + $status = Status::newGood(); } return $status; } @@ -292,15 +336,7 @@ abstract class FileOp { * * @return Array */ - final public function storagePathsRead() { - return array_map( 'FileBackend::normalizeStoragePath', $this->doStoragePathsRead() ); - } - - /** - * @see FileOp::storagePathsRead() - * @return Array - */ - protected function doStoragePathsRead() { + public function storagePathsRead() { return array(); } @@ -309,15 +345,7 @@ abstract class FileOp { * * @return Array */ - final public function storagePathsChanged() { - return array_map( 'FileBackend::normalizeStoragePath', $this->doStoragePathsChanged() ); - } - - /** - * @see FileOp::storagePathsChanged() - * @return Array - */ - protected function doStoragePathsChanged() { + public function storagePathsChanged() { return array(); } @@ -396,6 +424,8 @@ abstract class FileOp { final protected function fileSha1( $source, array $predicates ) { if ( isset( $predicates['sha1'][$source] ) ) { return $predicates['sha1'][$source]; // previous op assures this + } elseif ( isset( $predicates['exists'][$source] ) && !$predicates['exists'][$source] ) { + return false; // previous op assures this } else { $params = array( 'src' => $source, 'latest' => $this->useLatest ); return $this->backend->getFileSha1Base36( $params ); @@ -458,7 +488,7 @@ class StoreFileOp extends FileOp { $this->params['dst'], $this->backend->maxFileSizeInternal() ); $status->fatal( 'backend-fail-store', $this->params['src'], $this->params['dst'] ); return $status; - // Check if a file can be placed at the destination + // Check if a file can be placed/changed at the destination } elseif ( !$this->backend->isPathUsableInternal( $this->params['dst'] ) ) { $status->fatal( 'backend-fail-usable', $this->params['dst'] ); $status->fatal( 'backend-fail-store', $this->params['src'], $this->params['dst'] ); @@ -498,7 +528,7 @@ class StoreFileOp extends FileOp { return $hash; } - protected function doStoragePathsChanged() { + public function storagePathsChanged() { return array( $this->params['dst'] ); } } @@ -521,7 +551,7 @@ class CreateFileOp extends FileOp { $this->params['dst'], $this->backend->maxFileSizeInternal() ); $status->fatal( 'backend-fail-create', $this->params['dst'] ); return $status; - // Check if a file can be placed at the destination + // Check if a file can be placed/changed at the destination } elseif ( !$this->backend->isPathUsableInternal( $this->params['dst'] ) ) { $status->fatal( 'backend-fail-usable', $this->params['dst'] ); $status->fatal( 'backend-fail-create', $this->params['dst'] ); @@ -558,7 +588,7 @@ class CreateFileOp extends FileOp { /** * @return array */ - protected function doStoragePathsChanged() { + public function storagePathsChanged() { return array( $this->params['dst'] ); } } @@ -573,7 +603,7 @@ class CopyFileOp extends FileOp { */ protected function allowedParams() { return array( array( 'src', 'dst' ), - array( 'overwrite', 'overwriteSame', 'disposition' ) ); + array( 'overwrite', 'overwriteSame', 'ignoreMissingSource', 'disposition' ) ); } /** @@ -584,9 +614,17 @@ class CopyFileOp extends FileOp { $status = Status::newGood(); // Check if the source file exists if ( !$this->fileExists( $this->params['src'], $predicates ) ) { - $status->fatal( 'backend-fail-notexists', $this->params['src'] ); - return $status; - // Check if a file can be placed at the destination + if ( $this->getParam( 'ignoreMissingSource' ) ) { + $this->doOperation = false; // no-op + // Update file existence predicates (cache 404s) + $predicates['exists'][$this->params['src']] = false; + $predicates['sha1'][$this->params['src']] = false; + return $status; // nothing to do + } else { + $status->fatal( 'backend-fail-notexists', $this->params['src'] ); + return $status; + } + // Check if a file can be placed/changed at the destination } elseif ( !$this->backend->isPathUsableInternal( $this->params['dst'] ) ) { $status->fatal( 'backend-fail-usable', $this->params['dst'] ); $status->fatal( 'backend-fail-copy', $this->params['src'], $this->params['dst'] ); @@ -619,14 +657,14 @@ class CopyFileOp extends FileOp { /** * @return array */ - protected function doStoragePathsRead() { + public function storagePathsRead() { return array( $this->params['src'] ); } /** * @return array */ - protected function doStoragePathsChanged() { + public function storagePathsChanged() { return array( $this->params['dst'] ); } } @@ -641,7 +679,7 @@ class MoveFileOp extends FileOp { */ protected function allowedParams() { return array( array( 'src', 'dst' ), - array( 'overwrite', 'overwriteSame', 'disposition' ) ); + array( 'overwrite', 'overwriteSame', 'ignoreMissingSource', 'disposition' ) ); } /** @@ -652,9 +690,17 @@ class MoveFileOp extends FileOp { $status = Status::newGood(); // Check if the source file exists if ( !$this->fileExists( $this->params['src'], $predicates ) ) { - $status->fatal( 'backend-fail-notexists', $this->params['src'] ); - return $status; - // Check if a file can be placed at the destination + if ( $this->getParam( 'ignoreMissingSource' ) ) { + $this->doOperation = false; // no-op + // Update file existence predicates (cache 404s) + $predicates['exists'][$this->params['src']] = false; + $predicates['sha1'][$this->params['src']] = false; + return $status; // nothing to do + } else { + $status->fatal( 'backend-fail-notexists', $this->params['src'] ); + return $status; + } + // Check if a file can be placed/changed at the destination } elseif ( !$this->backend->isPathUsableInternal( $this->params['dst'] ) ) { $status->fatal( 'backend-fail-usable', $this->params['dst'] ); $status->fatal( 'backend-fail-move', $this->params['src'], $this->params['dst'] ); @@ -693,14 +739,14 @@ class MoveFileOp extends FileOp { /** * @return array */ - protected function doStoragePathsRead() { + public function storagePathsRead() { return array( $this->params['src'] ); } /** * @return array */ - protected function doStoragePathsChanged() { + public function storagePathsChanged() { return array( $this->params['src'], $this->params['dst'] ); } } @@ -717,21 +763,29 @@ class DeleteFileOp extends FileOp { return array( array( 'src' ), array( 'ignoreMissingSource' ) ); } - protected $needsDelete = true; - /** - * @param array $predicates + * @param $predicates array * @return Status */ protected function doPrecheck( array &$predicates ) { $status = Status::newGood(); // Check if the source file exists if ( !$this->fileExists( $this->params['src'], $predicates ) ) { - if ( !$this->getParam( 'ignoreMissingSource' ) ) { + if ( $this->getParam( 'ignoreMissingSource' ) ) { + $this->doOperation = false; // no-op + // Update file existence predicates (cache 404s) + $predicates['exists'][$this->params['src']] = false; + $predicates['sha1'][$this->params['src']] = false; + return $status; // nothing to do + } else { $status->fatal( 'backend-fail-notexists', $this->params['src'] ); return $status; } - $this->needsDelete = false; + // Check if a file can be placed/changed at the source + } elseif ( !$this->backend->isPathUsableInternal( $this->params['src'] ) ) { + $status->fatal( 'backend-fail-usable', $this->params['src'] ); + $status->fatal( 'backend-fail-delete', $this->params['src'] ); + return $status; } // Update file existence predicates $predicates['exists'][$this->params['src']] = false; @@ -743,17 +797,14 @@ class DeleteFileOp extends FileOp { * @return Status */ protected function doAttempt() { - if ( $this->needsDelete ) { - // Delete the source file - return $this->backend->deleteInternal( $this->setFlags( $this->params ) ); - } - return Status::newGood(); + // Delete the source file + return $this->backend->deleteInternal( $this->setFlags( $this->params ) ); } /** * @return array */ - protected function doStoragePathsChanged() { + public function storagePathsChanged() { return array( $this->params['src'] ); } } diff --git a/includes/filebackend/FileOpBatch.php b/includes/filebackend/FileOpBatch.php index 335587255b..736393af86 100644 --- a/includes/filebackend/FileOpBatch.php +++ b/includes/filebackend/FileOpBatch.php @@ -136,48 +136,12 @@ class FileOpBatch { } // Attempt each operation (in parallel if allowed and possible)... - if ( count( $pPerformOps ) < count( $performOps ) ) { - self::runBatchParallel( $pPerformOps, $status ); - } else { - self::runBatchSeries( $performOps, $status ); - } + self::runParallelBatches( $pPerformOps, $status ); wfProfileOut( __METHOD__ ); return $status; } - /** - * Attempt a list of file operations in series. - * This will abort remaining ops on failure. - * - * @param $performOps Array - * @param $status Status - * @return bool Success - */ - protected static function runBatchSeries( array $performOps, Status $status ) { - foreach ( $performOps as $index => $fileOp ) { - if ( $fileOp->failed() ) { - continue; // nothing to do - } - $subStatus = $fileOp->attempt(); - $status->merge( $subStatus ); - if ( $subStatus->isOK() ) { - $status->success[$index] = true; - ++$status->successCount; - } else { - $status->success[$index] = false; - ++$status->failCount; - // We can't continue (even with $ignoreErrors) as $predicates is wrong. - // Log the remaining ops as failed for recovery... - for ( $i = ($index + 1); $i < count( $performOps ); $i++ ) { - $performOps[$i]->logFailure( 'attempt_aborted' ); - } - return false; // bail out - } - } - return true; - } - /** * Attempt a list of file operations sub-batches in series. * @@ -190,8 +154,8 @@ class FileOpBatch { * @param $status Status * @return bool Success */ - protected static function runBatchParallel( array $pPerformOps, Status $status ) { - $aborted = false; + protected static function runParallelBatches( array $pPerformOps, Status $status ) { + $aborted = false; // set to true on unexpected errors foreach ( $pPerformOps as $performOpsBatch ) { if ( $aborted ) { // check batch op abort flag... // We can't continue (even with $ignoreErrors) as $predicates is wrong. @@ -205,11 +169,16 @@ class FileOpBatch { $opHandles = array(); // Get the backend; all sub-batch ops belong to a single backend $backend = reset( $performOpsBatch )->getBackend(); - // If attemptAsync() returns synchronously, it was either an - // error Status or the backend just doesn't support async ops. + // Get the operation handles or actually do it if there is just one. + // If attemptAsync() returns a Status, it was either due to an error + // or the backend does not support async ops and did it synchronously. foreach ( $performOpsBatch as $i => $fileOp ) { if ( !$fileOp->failed() ) { // failed => already has Status - $subStatus = $fileOp->attemptAsync(); + // If the batch is just one operation, it's faster to avoid + // pipelining as that can involve creating new TCP connections. + $subStatus = ( count( $performOpsBatch ) > 1 ) + ? $fileOp->attemptAsync() + : $fileOp->attempt(); if ( $subStatus->value instanceof FileBackendStoreOpHandle ) { $opHandles[$i] = $subStatus->value; // deferred } else { diff --git a/includes/filebackend/README b/includes/filebackend/README index d42c6a3195..6ab5481048 100644 --- a/includes/filebackend/README +++ b/includes/filebackend/README @@ -11,9 +11,9 @@ 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 -filesystem to distributed object stores). The types include: +file system to distributed object stores). The types include: -* FSFileBackend (used for mounted filesystems) +* 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) @@ -24,10 +24,10 @@ __construct() inline documentation. \section setup Setup File backends are registered in LocalSettings.php via the global variable -$wgFileBackends. To access one of those defined backend, one would use +$wgFileBackends. To access one of those defined backends, one would use FileBackendStore::get( ) which will bring back a FileBackend object -handle. Such handles are reused for any subsequent get() call (singleton -paradigm). The FileBackends objects are caching request calls such as file stats, +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: @@ -44,7 +44,7 @@ directories. See FileBackend.php for full documentation for each function. \subsection reading Reading -The following operations are supported for reading from a backend: +The following basic operations are supported for reading from a backend: On files: * state a file for basic information (timestamp, size) @@ -61,18 +61,19 @@ On directories: \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). +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 operations are supported for writing or changing in the backend: +The following basic operations are supported for writing or changing in the backend: On files: -* store (copying a mounted filesystem file into storage) +* store (copying a mounted file system file into storage) * create (creating a file within storage from a string) * copy (within storage) * move (within storage) @@ -108,17 +109,17 @@ 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. +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. +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 @@ -133,13 +134,15 @@ 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 attempted a given operation batch. This works + 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 also 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 using the "latest" option (eventual consistency). +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 @@ -147,32 +150,34 @@ Since acquiring locks can fail, and lock managers can be non-blocking, callers s * 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". One should avoid -changing files once they have been stored, except perhaps with ephemeral data that are tolerant -of some inconsistency. +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. +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, these will just be "files" under "directories". For -an object store as a backing store, the "files" will be "objects" stored in -"containers". +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 and Object store differences +\section file_obj_diffs File system and Object store differences -An advantage of objects stores is the reduced Round-Trip Times. This is +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. For both -object stores and file systems, using "/" in filenames will allow for the +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", @@ -182,7 +187,7 @@ 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 filesystem, you cannot have a file and a directory within the same path +* 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 @@ -195,5 +200,9 @@ aware of some important differences: 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///file.txt". It is best if "sharding" optional or configurable. */ diff --git a/includes/filebackend/SwiftFileBackend.php b/includes/filebackend/SwiftFileBackend.php index fed496afcf..48db9d3c3f 100644 --- a/includes/filebackend/SwiftFileBackend.php +++ b/includes/filebackend/SwiftFileBackend.php @@ -40,6 +40,7 @@ class SwiftFileBackend extends FileBackendStore { /** @var CF_Authentication */ protected $auth; // Swift authentication handler protected $authTTL; // integer seconds + protected $swiftTempUrlKey; // string; shared secret value for making temp urls protected $swiftAnonUser; // string; username to handle unauthenticated requests protected $swiftUseCDN; // boolean; whether CloudFiles CDN is enabled protected $swiftCDNExpiry; // integer; how long to cache things in the CDN @@ -66,6 +67,8 @@ class SwiftFileBackend extends FileBackendStore { * - swiftUser : Swift user used by MediaWiki (account:username) * - swiftKey : Swift authentication key for the above user * - swiftAuthTTL : Swift authentication TTL (seconds) + * - swiftTempUrlKey : Swift "X-Account-Meta-Temp-URL-Key" value on the account. + * Do not set this until it has been set in the backend. * - swiftAnonUser : Swift user used for end-user requests (account:username). * If set, then views of public containers are assumed to go * through this user. If not set, then public containers are @@ -104,6 +107,9 @@ class SwiftFileBackend extends FileBackendStore { $this->swiftAnonUser = isset( $config['swiftAnonUser'] ) ? $config['swiftAnonUser'] : ''; + $this->swiftTempUrlKey = isset( $config['swiftTempUrlKey'] ) + ? $config['swiftTempUrlKey'] + : ''; $this->shardViaHashLevels = isset( $config['shardViaHashLevels'] ) ? $config['shardViaHashLevels'] : ''; @@ -201,12 +207,6 @@ class SwiftFileBackend extends FileBackendStore { // (a) Check the destination container and object try { $dContObj = $this->getContainer( $dstCont ); - if ( empty( $params['overwrite'] ) && - $this->fileExists( array( 'src' => $params['dst'], 'latest' => 1 ) ) ) - { - $status->fatal( 'backend-fail-alreadyexists', $params['dst'] ); - return $status; - } } catch ( NoSuchContainerException $e ) { $status->fatal( 'backend-fail-create', $params['dst'] ); return $status; @@ -223,8 +223,7 @@ class SwiftFileBackend extends FileBackendStore { // Create a fresh CF_Object with no fields preloaded. // We don't want to preserve headers, metadata, and such. $obj = new CF_Object( $dContObj, $dstRel, false, false ); // skip HEAD - // Note: metadata keys stored as [Upper case char][[Lower case char]...] - $obj->metadata = array( 'Sha1base36' => $sha1Hash ); + $obj->setMetadataValues( array( 'Sha1base36' => $sha1Hash ) ); // Manually set the ETag (https://github.com/rackspace/php-cloudfiles/issues/59). // The MD5 here will be checked within Swift against its own MD5. $obj->set_etag( md5( $params['content'] ) ); @@ -240,14 +239,10 @@ class SwiftFileBackend extends FileBackendStore { if ( !empty( $params['async'] ) ) { // deferred $op = $obj->write_async( $params['content'] ); $status->value = new SwiftFileOpHandle( $this, $params, 'Create', $op ); - if ( !empty( $params['overwrite'] ) ) { // file possibly mutated - $status->value->affectedObjects[] = $obj; - } + $status->value->affectedObjects[] = $obj; } else { // actually write the object in Swift $obj->write( $params['content'] ); - if ( !empty( $params['overwrite'] ) ) { // file possibly mutated - $this->purgeCDNCache( array( $obj ) ); - } + $this->purgeCDNCache( array( $obj ) ); } } catch ( CDNNotEnabledException $e ) { // CDN not enabled; nothing to see here @@ -287,12 +282,6 @@ class SwiftFileBackend extends FileBackendStore { // (a) Check the destination container and object try { $dContObj = $this->getContainer( $dstCont ); - if ( empty( $params['overwrite'] ) && - $this->fileExists( array( 'src' => $params['dst'], 'latest' => 1 ) ) ) - { - $status->fatal( 'backend-fail-alreadyexists', $params['dst'] ); - return $status; - } } catch ( NoSuchContainerException $e ) { $status->fatal( 'backend-fail-copy', $params['src'], $params['dst'] ); return $status; @@ -314,8 +303,7 @@ class SwiftFileBackend extends FileBackendStore { // Create a fresh CF_Object with no fields preloaded. // We don't want to preserve headers, metadata, and such. $obj = new CF_Object( $dContObj, $dstRel, false, false ); // skip HEAD - // Note: metadata keys stored as [Upper case char][[Lower case char]...] - $obj->metadata = array( 'Sha1base36' => $sha1Hash ); + $obj->setMetadataValues( array( 'Sha1base36' => $sha1Hash ) ); // The MD5 here will be checked within Swift against its own MD5. $obj->set_etag( md5_file( $params['src'] ) ); // Use the same content type as StreamFile for security @@ -337,15 +325,11 @@ class SwiftFileBackend extends FileBackendStore { $op = $obj->write_async( $fp, filesize( $params['src'] ), true ); $status->value = new SwiftFileOpHandle( $this, $params, 'Store', $op ); $status->value->resourcesToClose[] = $fp; - if ( !empty( $params['overwrite'] ) ) { // file possibly mutated - $status->value->affectedObjects[] = $obj; - } + $status->value->affectedObjects[] = $obj; } } else { // actually write the object in Swift $obj->load_from_filename( $params['src'], true ); // calls $obj->write() - if ( !empty( $params['overwrite'] ) ) { // file possibly mutated - $this->purgeCDNCache( array( $obj ) ); - } + $this->purgeCDNCache( array( $obj ) ); } } catch ( CDNNotEnabledException $e ) { // CDN not enabled; nothing to see here @@ -396,12 +380,6 @@ class SwiftFileBackend extends FileBackendStore { try { $sContObj = $this->getContainer( $srcCont ); $dContObj = $this->getContainer( $dstCont ); - if ( empty( $params['overwrite'] ) && - $this->fileExists( array( 'src' => $params['dst'], 'latest' => 1 ) ) ) - { - $status->fatal( 'backend-fail-alreadyexists', $params['dst'] ); - return $status; - } } catch ( NoSuchContainerException $e ) { $status->fatal( 'backend-fail-copy', $params['src'], $params['dst'] ); return $status; @@ -420,19 +398,17 @@ class SwiftFileBackend extends FileBackendStore { if ( !empty( $params['async'] ) ) { // deferred $op = $sContObj->copy_object_to_async( $srcRel, $dContObj, $dstRel, null, $hdrs ); $status->value = new SwiftFileOpHandle( $this, $params, 'Copy', $op ); - if ( !empty( $params['overwrite'] ) ) { // file possibly mutated - $status->value->affectedObjects[] = $dstObj; - } + $status->value->affectedObjects[] = $dstObj; } else { // actually write the object in Swift $sContObj->copy_object_to( $srcRel, $dContObj, $dstRel, null, $hdrs ); - if ( !empty( $params['overwrite'] ) ) { // file possibly mutated - $this->purgeCDNCache( array( $dstObj ) ); - } + $this->purgeCDNCache( array( $dstObj ) ); } } catch ( CDNNotEnabledException $e ) { // CDN not enabled; nothing to see here } catch ( NoSuchObjectException $e ) { // source object does not exist - $status->fatal( 'backend-fail-copy', $params['src'], $params['dst'] ); + if ( empty( $params['ignoreMissingSource'] ) ) { + $status->fatal( 'backend-fail-copy', $params['src'], $params['dst'] ); + } } catch ( CloudFilesException $e ) { // some other exception? $this->handleException( $e, $status, __METHOD__, $params ); } @@ -474,12 +450,6 @@ class SwiftFileBackend extends FileBackendStore { try { $sContObj = $this->getContainer( $srcCont ); $dContObj = $this->getContainer( $dstCont ); - if ( empty( $params['overwrite'] ) && - $this->fileExists( array( 'src' => $params['dst'], 'latest' => 1 ) ) ) - { - $status->fatal( 'backend-fail-alreadyexists', $params['dst'] ); - return $status; - } } catch ( NoSuchContainerException $e ) { $status->fatal( 'backend-fail-move', $params['src'], $params['dst'] ); return $status; @@ -500,20 +470,18 @@ class SwiftFileBackend extends FileBackendStore { $op = $sContObj->move_object_to_async( $srcRel, $dContObj, $dstRel, null, $hdrs ); $status->value = new SwiftFileOpHandle( $this, $params, 'Move', $op ); $status->value->affectedObjects[] = $srcObj; - if ( !empty( $params['overwrite'] ) ) { // file possibly mutated - $status->value->affectedObjects[] = $dstObj; - } + $status->value->affectedObjects[] = $dstObj; } else { // actually write the object in Swift $sContObj->move_object_to( $srcRel, $dContObj, $dstRel, null, $hdrs ); $this->purgeCDNCache( array( $srcObj ) ); - if ( !empty( $params['overwrite'] ) ) { // file possibly mutated - $this->purgeCDNCache( array( $dstObj ) ); - } + $this->purgeCDNCache( array( $dstObj ) ); } } catch ( CDNNotEnabledException $e ) { // CDN not enabled; nothing to see here } catch ( NoSuchObjectException $e ) { // source object does not exist - $status->fatal( 'backend-fail-move', $params['src'], $params['dst'] ); + if ( empty( $params['ignoreMissingSource'] ) ) { + $status->fatal( 'backend-fail-move', $params['src'], $params['dst'] ); + } } catch ( CloudFilesException $e ) { // some other exception? $this->handleException( $e, $status, __METHOD__, $params ); } @@ -761,7 +729,7 @@ class SwiftFileBackend extends FileBackendStore { // Convert dates like "Tue, 03 Jan 2012 22:01:04 GMT" to TS_MW 'mtime' => wfTimestamp( TS_MW, $srcObj->last_modified ), 'size' => (int)$srcObj->content_length, - 'sha1' => $srcObj->metadata['Sha1base36'] + 'sha1' => $srcObj->getMetadataValue( 'Sha1base36' ) ); } catch ( NoSuchContainerException $e ) { } catch ( NoSuchObjectException $e ) { @@ -782,7 +750,7 @@ class SwiftFileBackend extends FileBackendStore { * @throws Exception cloudfiles exceptions */ protected function addMissingMetadata( CF_Object $obj, $path ) { - if ( isset( $obj->metadata['Sha1base36'] ) ) { + if ( $obj->getMetadataValue( 'Sha1base36' ) !== null ) { return true; // nothing to do } wfProfileIn( __METHOD__ ); @@ -794,14 +762,14 @@ class SwiftFileBackend extends FileBackendStore { if ( $tmpFile ) { $hash = $tmpFile->getSha1Base36(); if ( $hash !== false ) { - $obj->metadata['Sha1base36'] = $hash; + $obj->setMetadataValues( array( 'Sha1base36' => $hash ) ); $obj->sync_metadata(); // save to Swift wfProfileOut( __METHOD__ ); return true; // success } } } - $obj->metadata['Sha1base36'] = false; + $obj->setMetadataValues( array( 'Sha1base36' => false ) ); wfProfileOut( __METHOD__ ); return false; // failed } @@ -1157,6 +1125,28 @@ class SwiftFileBackend extends FileBackendStore { return $tmpFiles; } + /** + * @see FileBackendStore::getFileHttpUrl() + * @return string|null + */ + public function getFileHttpUrl( array $params ) { + if ( $this->swiftTempUrlKey != '' ) { // temp urls enabled + list( $srcCont, $srcRel ) = $this->resolveStoragePathReal( $params['src'] ); + if ( $srcRel === null ) { + return null; // invalid path + } + try { + $sContObj = $this->getContainer( $srcCont ); + $obj = new CF_Object( $sContObj, $srcRel, false, false ); // skip HEAD + return $obj->get_temp_url( $this->swiftTempUrlKey, 86400, "GET" ); + } catch ( NoSuchContainerException $e ) { + } catch ( CloudFilesException $e ) { // some other exception? + $this->handleException( $e, null, __METHOD__, $params ); + } + } + return null; + } + /** * @see FileBackendStore::directoriesAreVirtual() * @return bool diff --git a/includes/filebackend/filejournal/DBFileJournal.php b/includes/filebackend/filejournal/DBFileJournal.php index 34f3e53d50..44c6567b6a 100644 --- a/includes/filebackend/filejournal/DBFileJournal.php +++ b/includes/filebackend/filejournal/DBFileJournal.php @@ -75,6 +75,9 @@ class DBFileJournal extends FileJournal { try { $dbw->insert( 'filejournal', $data, __METHOD__ ); + if ( mt_rand( 0, 99 ) == 0 ) { + $this->purgeOldLogs(); // occasionally delete old logs + } } catch ( DBError $e ) { $status->fatal( 'filejournal-fail-dbquery', $this->backend ); return $status; diff --git a/includes/filebackend/filejournal/FileJournal.php b/includes/filebackend/filejournal/FileJournal.php index 3bc0df74f5..d99384db1b 100644 --- a/includes/filebackend/filejournal/FileJournal.php +++ b/includes/filebackend/filejournal/FileJournal.php @@ -85,7 +85,7 @@ abstract class FileJournal { /** * Log changes made by a batch file operation. * $entries is an array of log entries, each of which contains: - * op : Basic operation name (create, store, copy, delete) + * op : Basic operation name (create, update, delete) * path : The storage path of the file * newSha1 : The final base 36 SHA-1 of the file * Note that 'false' should be used as the SHA-1 for non-existing files. diff --git a/includes/filerepo/FileRepo.php b/includes/filerepo/FileRepo.php index e8aa5a6335..651ee27127 100644 --- a/includes/filerepo/FileRepo.php +++ b/includes/filerepo/FileRepo.php @@ -127,6 +127,9 @@ class FileRepo { if ( !isset( $this->zones[$zone]['directory'] ) ) { $this->zones[$zone]['directory'] = ''; } + if ( !isset( $this->zones[$zone]['urlsByExt'] ) ) { + $this->zones[$zone]['urlsByExt'] = array(); + } } } @@ -196,14 +199,17 @@ class FileRepo { /** * Get the URL corresponding to one of the four basic zones * - * @param $zone String: one of: public, deleted, temp, thumb + * @param $zone String One of: public, deleted, temp, thumb + * @param $ext String|null Optional file extension * @return String or false */ - public function getZoneUrl( $zone ) { - if ( isset( $this->zones[$zone]['url'] ) - && in_array( $zone, array( 'public', 'temp', 'thumb' ) ) ) - { - return $this->zones[$zone]['url']; // custom URL + public function getZoneUrl( $zone, $ext = null ) { + if ( in_array( $zone, array( 'public', 'temp', 'thumb' ) ) ) { // standard public zones + if ( $ext !== null && isset( $this->zones[$zone]['urlsByExt'][$ext] ) ) { + return $this->zones[$zone]['urlsByExt'][$ext]; // custom URL for extension/zone + } elseif ( isset( $this->zones[$zone]['url'] ) ) { + return $this->zones[$zone]['url']; // custom URL for zone + } } switch ( $zone ) { case 'public': @@ -1094,47 +1100,42 @@ class FileRepo { return $this->newFatal( 'directorycreateerror', $archiveDir ); } - // Archive destination file if it exists - if ( $backend->fileExists( array( 'src' => $dstPath ) ) ) { - // Check if the archive file exists - // This is a sanity check to avoid data loss. In UNIX, the rename primitive - // unlinks the destination file if it exists. DB-based synchronisation in - // publishBatch's caller should prevent races. In Windows there's no - // problem because the rename primitive fails if the destination exists. - if ( $backend->fileExists( array( 'src' => $archivePath ) ) ) { - $operations[] = array( 'op' => 'null' ); - continue; - } else { - $operations[] = array( - 'op' => 'move', - 'src' => $dstPath, - 'dst' => $archivePath - ); - } - $status->value[$i] = 'archived'; - } else { - $status->value[$i] = 'new'; - } + // Archive destination file if it exists. + // This will check if the archive file also exists and fail if does. + // This is a sanity check to avoid data loss. On Windows and Linux, + // copy() will overwrite, so the existence check is vulnerable to + // race conditions unless an functioning LockManager is used. + // LocalFile also uses SELECT FOR UPDATE for synchronization. + $operations[] = array( + 'op' => 'copy', + 'src' => $dstPath, + 'dst' => $archivePath, + 'ignoreMissingSource' => true + ); + // Copy (or move) the source file to the destination if ( FileBackend::isStoragePath( $srcPath ) ) { if ( $flags & self::DELETE_SOURCE ) { $operations[] = array( 'op' => 'move', 'src' => $srcPath, - 'dst' => $dstPath + 'dst' => $dstPath, + 'overwrite' => true // replace current ); } else { $operations[] = array( 'op' => 'copy', 'src' => $srcPath, - 'dst' => $dstPath + 'dst' => $dstPath, + 'overwrite' => true // replace current ); } } else { // FS source path $operations[] = array( 'op' => 'store', 'src' => $srcPath, - 'dst' => $dstPath + 'dst' => $dstPath, + 'overwrite' => true // replace current ); if ( $flags & self::DELETE_SOURCE ) { $sourceFSFilesToDelete[] = $srcPath; @@ -1143,8 +1144,17 @@ class FileRepo { } // Execute the operations for each triplet - $opts = array( 'force' => true ); - $status->merge( $backend->doOperations( $operations, $opts ) ); + $status->merge( $backend->doOperations( $operations ) ); + // Find out which files were archived... + foreach ( $triplets as $i => $triplet ) { + list( $srcPath, $dstRel, $archiveRel ) = $triplet; + $archivePath = $this->getZonePath( 'public' ) . "/$archiveRel"; + if ( $this->fileExists( $archivePath ) ) { + $status->value[$i] = 'archived'; + } else { + $status->value[$i] = 'new'; + } + } // Cleanup for disk source files... foreach ( $sourceFSFilesToDelete as $file ) { wfSuppressWarnings(); diff --git a/includes/filerepo/file/ArchivedFile.php b/includes/filerepo/file/ArchivedFile.php index 694623b627..e1a8547895 100644 --- a/includes/filerepo/file/ArchivedFile.php +++ b/includes/filerepo/file/ArchivedFile.php @@ -135,8 +135,9 @@ class ArchivedFile { } if( !$this->title || $this->title->getNamespace() == NS_FILE ) { + $this->dataLoaded = true; // set it here, to have also true on miss $dbr = wfGetDB( DB_SLAVE ); - $res = $dbr->select( 'filearchive', + $row = $dbr->selectRow( 'filearchive', array( 'fa_id', 'fa_name', @@ -159,20 +160,18 @@ class ArchivedFile { 'fa_sha1' ), $conds, __METHOD__, - array( 'ORDER BY' => 'fa_timestamp DESC' ) ); - if ( $res == false || $dbr->numRows( $res ) == 0 ) { - // this revision does not exist? + array( 'ORDER BY' => 'fa_timestamp DESC') + ); + if ( !$row ) { + // this revision does not exist? return null; } - $ret = $dbr->resultObject( $res ); - $row = $ret->fetchObject(); // initialize fields for filestore image object $this->loadFromRow( $row ); } else { throw new MWException( 'This title does not correspond to an image page.' ); } - $this->dataLoaded = true; $this->exists = true; return true; diff --git a/includes/filerepo/file/File.php b/includes/filerepo/file/File.php index 557609d4b0..9a080ae04b 100644 --- a/includes/filerepo/file/File.php +++ b/includes/filerepo/file/File.php @@ -316,7 +316,8 @@ abstract class File { public function getUrl() { if ( !isset( $this->url ) ) { $this->assertRepoDefined(); - $this->url = $this->repo->getZoneUrl( 'public' ) . '/' . $this->getUrlRel(); + $ext = $this->getExtension(); + $this->url = $this->repo->getZoneUrl( 'public', $ext ) . '/' . $this->getUrlRel(); } return $this->url; } @@ -1253,7 +1254,8 @@ abstract class File { */ function getArchiveUrl( $suffix = false ) { $this->assertRepoDefined(); - $path = $this->repo->getZoneUrl( 'public' ) . '/archive/' . $this->getHashPath(); + $ext = $this->getExtension(); + $path = $this->repo->getZoneUrl( 'public', $ext ) . '/archive/' . $this->getHashPath(); if ( $suffix === false ) { $path = substr( $path, 0, -1 ); } else { @@ -1272,7 +1274,8 @@ abstract class File { */ function getArchiveThumbUrl( $archiveName, $suffix = false ) { $this->assertRepoDefined(); - $path = $this->repo->getZoneUrl( 'thumb' ) . '/archive/' . + $ext = $this->getExtension(); + $path = $this->repo->getZoneUrl( 'thumb', $ext ) . '/archive/' . $this->getHashPath() . rawurlencode( $archiveName ) . "/"; if ( $suffix === false ) { $path = substr( $path, 0, -1 ); @@ -1291,7 +1294,8 @@ abstract class File { */ function getThumbUrl( $suffix = false ) { $this->assertRepoDefined(); - $path = $this->repo->getZoneUrl( 'thumb' ) . '/' . $this->getUrlRel(); + $ext = $this->getExtension(); + $path = $this->repo->getZoneUrl( 'thumb', $ext ) . '/' . $this->getUrlRel(); if ( $suffix !== false ) { $path .= '/' . rawurlencode( $suffix ); } diff --git a/includes/filerepo/file/LocalFile.php b/includes/filerepo/file/LocalFile.php index caa93a42c6..f0a3c15e35 100644 --- a/includes/filerepo/file/LocalFile.php +++ b/includes/filerepo/file/LocalFile.php @@ -814,7 +814,9 @@ class LocalFile extends File { foreach ( $files as $file ) { # Check that the base file name is part of the thumb name # This is a basic sanity check to avoid erasing unrelated directories - if ( strpos( $file, $this->getName() ) !== false ) { + if ( strpos( $file, $this->getName() ) !== false + || strpos( $file, "-thumbnail" ) !== false // "short" thumb name + ) { $purgeList[] = "{$dir}/{$file}"; } } @@ -1759,7 +1761,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', diff --git a/includes/installer/DatabaseInstaller.php b/includes/installer/DatabaseInstaller.php index de59b2d65f..75ede239b3 100644 --- a/includes/installer/DatabaseInstaller.php +++ b/includes/installer/DatabaseInstaller.php @@ -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; } diff --git a/includes/installer/DatabaseUpdater.php b/includes/installer/DatabaseUpdater.php index 7223003180..740ead528d 100644 --- a/includes/installer/DatabaseUpdater.php +++ b/includes/installer/DatabaseUpdater.php @@ -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" ); } diff --git a/includes/installer/Ibm_db2Updater.php b/includes/installer/Ibm_db2Updater.php index 805ff0ff66..33bf69c69e 100644 --- a/includes/installer/Ibm_db2Updater.php +++ b/includes/installer/Ibm_db2Updater.php @@ -85,9 +85,6 @@ class Ibm_db2Updater extends DatabaseUpdater { array( 'addField', 'revision', 'rev_sha1', 'patch-rev_sha1.sql' ), array( 'addField', 'archive', 'ar_sha1', 'patch-ar_sha1.sql' ), - // 1.20 - array( 'addTable', 'config', 'patch-config.sql' ), - // 1.21 array( 'addField', 'revision', 'rev_content_format', 'patch-revision-rev_content_format.sql' ), array( 'addField', 'revision', 'rev_content_model', 'patch-revision-rev_content_model.sql' ), diff --git a/includes/installer/Installer.i18n.php b/includes/installer/Installer.i18n.php index 80ecb1f690..32056e3055 100644 --- a/includes/installer/Installer.i18n.php +++ b/includes/installer/Installer.i18n.php @@ -832,7 +832,7 @@ U kan MediaWiki installeer.', 'config-env-bad' => 'Die omgewing is gekontroleer. U kan nie MediaWiki installeer nie.', 'config-env-php' => 'PHP $1 is tans geïnstalleer.', - 'config-no-db' => "Kon nie 'n geskikte databasisdrywer vind nie!", + 'config-no-db' => "Kon nie 'n geskikte databasisdrywer vind nie!", # Fuzzy 'config-memory-raised' => 'PHP se memory_limit is $1, en is verhoog tot $2.', 'config-memory-bad' => "'''Waarskuwing:''' PHP se memory_limit is $1. Dit is waarskynlik te laag. @@ -941,7 +941,7 @@ Die skep van tabelle word oorgeslaan.", 'config-install-interwiki-exists' => "'''Waarskuwing''': Die interwiki-tabel bevat reeds inskrywings. Die standaardlys word oorgeslaan.", 'config-install-stats' => 'Inisialiseer statistieke', - 'config-install-keys' => 'Genereer geheime sleutel', + 'config-install-keys' => 'Genereer geheime sleutel', # Fuzzy 'config-install-sysop' => "Skep 'n gebruiker vir die administrateur", 'config-install-subscribe-fail' => 'Kon nie vir MediaWiki-announce inskryf nie: $1', 'config-install-mainpage' => 'Skep die hoofblad met standaard inhoud', @@ -956,7 +956,7 @@ Dit bevat al u instellings. U sal dit moet [$1 aflaai] en dit in die hoofgids van u wiki-installasie plaas; in dieselfde gids as index.php. '''Let wel''': As u dit nie nou doen nie, sal die gegenereerde konfigurasielêer nie later meer beskikbaar wees nadat u die installasie afgesluit het nie. -As dit gedoen is, kan u '''[u $2 wiki besoek]'''.", +As dit gedoen is, kan u '''[u $2 wiki besoek]'''.", # Fuzzy 'config-download-localsettings' => 'Laai LocalSettings.php af', 'config-help' => 'hulp', 'mainpagetext' => "'''MediaWiki is suksesvol geïnstalleer.'''", @@ -983,7 +983,8 @@ $messages['aln'] = array( * [https://lists.wikimedia.org/mailman/listinfo/mediawiki-announce Njoftime rreth MediaWikit]', ); -/** Amharic (አማርኛ) */ +/** Amharic (አማርኛ) + */ $messages['am'] = array( 'mainpagetext' => "'''MediaWiki በትክክል ማስገባቱ ተከናወነ።'''", 'mainpagedocfooter' => "ስለ ዊኪ ሶፍትዌር ጥቅም ለመረዳት፣ [//meta.wikimedia.org/wiki/Help:Contents User's Guide] ያንብቡ። @@ -1029,7 +1030,7 @@ $messages['ang'] = array( */ $messages['ar'] = array( 'config-desc' => 'مثبت لميدياويكي', - 'config-title' => 'ميدياويكي 1$ التثبيت', + 'config-title' => 'ميدياويكي 1$ التثبيت', # Fuzzy 'config-information' => 'معلومات', 'config-back' => '→ ارجع', 'config-continue' => 'استمر ←', @@ -1087,7 +1088,8 @@ $messages['ary'] = array( * [https://lists.wikimedia.org/mailman/listinfo/mediawiki-announce Lista dyal l-modakaraṫ ĝla versyonaṫ jdad dyal MediaWiki]', ); -/** Egyptian Spoken Arabic (مصرى) */ +/** Egyptian Spoken Arabic (مصرى) + */ $messages['arz'] = array( 'mainpagetext' => "''' ميدياويكى اتنزلت بنجاح.'''", 'mainpagedocfooter' => 'اسال [//meta.wikimedia.org/wiki/Help:Contents دليل اليوزر] للمعلومات حوالين استخدام برنامج الويكى. @@ -1113,7 +1115,8 @@ $messages['as'] = array( * [https://lists.wikimedia.org/mailman/listinfo/mediawiki-announce MediaWiki release mailing list]", ); -/** Asturian (asturianu) */ +/** Asturian (asturianu) + */ $messages['ast'] = array( 'mainpagetext' => "'''MediaWiki instalóse correchamente.'''", 'mainpagedocfooter' => "Visita la [//meta.wikimedia.org/wiki/Help:Contents Guía d'usuariu] pa saber cómo usar esti software wiki. @@ -1125,7 +1128,8 @@ $messages['ast'] = array( * [https://lists.wikimedia.org/mailman/listinfo/mediawiki-announce Llista de corréu de les ediciones de MediaWiki]", ); -/** Kotava (Kotava) */ +/** Kotava (Kotava) + */ $messages['avk'] = array( 'mainpagetext' => "'''MediaWiki inkeyen talpeyot.'''", ); @@ -1164,7 +1168,7 @@ $messages['az'] = array( * [https://lists.wikimedia.org/mailman/listinfo/mediawiki-announce MediaWiki e-poçt siyahısı]', ); -/** Bashkir (Башҡортса) +/** Bashkir (башҡортса) * @author Haqmar */ $messages['ba'] = array( @@ -1191,7 +1195,8 @@ $messages['bar'] = array( * [https://lists.wikimedia.org/mailman/listinfo/mediawiki-announce Mailinglisten voh de neichen MediaWiki-Versionen]', ); -/** Southern Balochi (بلوچی مکرانی) */ +/** Southern Balochi (بلوچی مکرانی) + */ $messages['bcc'] = array( 'mainpagetext' => "'''مدیا وی کی گون موفقیت نصب بوت.'''", 'mainpagedocfooter' => "مشورت کنیت گون [//meta.wikimedia.org/wiki/Help:Contents User's Guide] په گشیترین اطلاعات په استفاده چه برنامه ویکی. @@ -1202,7 +1207,8 @@ $messages['bcc'] = array( * [https://lists.wikimedia.org/mailman/listinfo/mediawiki-announce MediaWiki release mailing list]", ); -/** Bikol Central (Bikol Central) */ +/** Bikol Central (Bikol Central) + */ $messages['bcl'] = array( 'mainpagetext' => "'''Instalado na an MediaWiki.'''", 'mainpagedocfooter' => "Konsultarón tabì an [//meta.wikimedia.org/wiki/Help:Contents User's Guide] para sa impormasyon sa paggamit nin progama kaining wiki. @@ -1214,7 +1220,8 @@ $messages['bcl'] = array( * [https://lists.wikimedia.org/mailman/listinfo/mediawiki-announce MediaWiki release mailing list]", ); -/** Belarusian (беларуская) */ +/** Belarusian (беларуская) + */ $messages['be'] = array( 'mainpagetext' => "'''MediaWiki паспяхова ўсталяваная.'''", 'mainpagedocfooter' => 'Гл. [//meta.wikimedia.org/wiki/Help:Contents Дапаможнік карыстальніка (англ.)] па далейшыя звесткі аб карыстанні вікі-праграмамі. @@ -1226,7 +1233,7 @@ $messages['be'] = array( * [https://lists.wikimedia.org/mailman/listinfo/mediawiki-announce Ліставанне аб выпусках MediaWiki (англ.)]', ); -/** Belarusian (Taraškievica orthography) (‪беларуская (тарашкевіца)‬) +/** Belarusian (Taraškievica orthography) (беларуская (тарашкевіца)‎) * @author EugeneZelenko * @author Jim-by * @author Wizardist @@ -2398,7 +2405,7 @@ $messages['bn'] = array( 'config-license-none' => 'কোনো লাইসেন্স ফুটার নেই', 'config-license-cc-by-sa' => 'ক্রিয়েটিভ কমন্স অ্যাট্রিবিউশন শেয়ার অ্যালাইক', 'config-license-cc-by-nc-sa' => 'ক্রিয়েটিভ কমন্স অ্যাট্রিবিউশন নন-কমার্শিয়াল শেয়ার অ্যালাইক', - 'config-license-cc-0' => 'ক্রিয়েটিভ কমন্স জিরো', + 'config-license-cc-0' => 'ক্রিয়েটিভ কমন্স জিরো', # Fuzzy 'config-license-pd' => 'পাবলিক ডোমেইন', 'config-license-cc-choose' => 'একটি স্বনির্ধারিত ক্রিয়েটিভ কমন্স লাইসেন্ট নির্বাচন করুন', 'config-email-settings' => 'ই-মেইল সেটিংস', @@ -2427,7 +2434,8 @@ $messages['bn'] = array( * [https://lists.wikimedia.org/mailman/listinfo/mediawiki-announce মিডিয়াউইকি রিলিজের মেইলিং লিস্ট]', ); -/** Bishnupria Manipuri (বিষ্ণুপ্রিয়া মণিপুরী) */ +/** Bishnupria Manipuri (বিষ্ণুপ্রিয়া মণিপুরী) + */ $messages['bpy'] = array( 'mainpagetext' => "'''মিডিয়াউইকি হবাবালা ইয়া ইন্সটল ইল.'''", 'mainpagedocfooter' => 'উইকি সফটৱ্যার এহান আতানির বারে দরকার ইলে [//meta.wikimedia.org/wiki/Help:Contents আতাকুরার গাইড]হানর পাঙলাক নেগা। @@ -2593,7 +2601,7 @@ Staliadur paouezet.", Ma rit gant un herberc'hiañ kenrannet, e tlefe ho herberc'hier bezañ pourchaset deoc'h un anv ostiz reizh en teulioù titouriñ. -M'emaoc'h o staliañ ur servijer Windows ha ma rit gant MySQL, marteze ne'z aio ket en-dro \"localhost\" evel anv servijer. Ma ne dro ket, klaskit ober gant \"127.0.0.1\" da chomlec'h IP lechel.", +M'emaoc'h o staliañ ur servijer Windows ha ma rit gant MySQL, marteze ne'z aio ket en-dro \"localhost\" evel anv servijer. Ma ne dro ket, klaskit ober gant \"127.0.0.1\" da chomlec'h IP lechel.", # Fuzzy 'config-db-host-oracle' => 'TNS an diaz roadennoù :', 'config-db-wiki-settings' => 'Anavezout ar wiki-mañ', 'config-db-name' => 'Anv an diaz roadennoù :', @@ -2930,7 +2938,7 @@ $messages['ca'] = array( * [https://lists.wikimedia.org/mailman/listinfo/mediawiki-announce Llista de correu (''listserv'') per a anuncis del MediaWiki]", ); -/** Chechen (Нохчийн) +/** Chechen (нохчийн) * @author Sasan700 */ $messages['ce'] = array( @@ -2944,7 +2952,8 @@ $messages['ce'] = array( * [https://lists.wikimedia.org/mailman/listinfo/mediawiki-announce Хаам бохьуьйту араяларца башхонца керла MediaWiki].', ); -/** Cebuano (Cebuano) */ +/** Cebuano (Cebuano) + */ $messages['ceb'] = array( 'mainpagetext' => "'''Malamposon ang pag-instalar sa MediaWiki.'''", 'mainpagedocfooter' => 'Konsultaha ang [//meta.wikimedia.org/wiki/Help:Contents Giya sa mga gumagamit] alang sa impormasyon unsaon paggamit niining wiki nga software. @@ -2982,7 +2991,8 @@ $messages['cps'] = array( * [https://lists.wikimedia.org/mailman/listinfo/mediawiki-announce Lista sang mga ginapadal-an sang sulat sang MediaWiki]', ); -/** Crimean Turkish (Cyrillic script) (‪Къырымтатарджа (Кирилл)‬) */ +/** Crimean Turkish (Cyrillic script) (къырымтатарджа (Кирилл)‎) + */ $messages['crh-cyrl'] = array( 'mainpagetext' => "'''MediaWiki мувафакъиетнен къурулды.'''", 'mainpagedocfooter' => "Бу викининъ ёл-ёругъыны [//meta.wikimedia.org/wiki/Help:Contents User's Guide къулланыджы къылавузындан] огренип оласынъыз. @@ -2993,7 +3003,8 @@ $messages['crh-cyrl'] = array( * [https://lists.wikimedia.org/mailman/listinfo/mediawiki-announce MediaWiki-нинъ янъы версияларынынъ чыкъувындан хабер йиберюв].", ); -/** Crimean Turkish (Latin script) (‪Qırımtatarca (Latin)‬) */ +/** 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. @@ -3542,6 +3553,7 @@ $3 Až to dokončíte, můžete '''[$2 vstoupit do své wiki]'''.", 'config-download-localsettings' => 'Stáhnout LocalSettings.php', 'config-help' => 'nápověda', + 'config-nofile' => 'Soubor „$1“ nelze nalézt. Byl smazán?', 'mainpagetext' => "'''MediaWiki byla úspěšně nainstalována.'''", 'mainpagedocfooter' => '[//meta.wikimedia.org/wiki/Help:Contents Uživatelská příručka] vám napoví, jak MediaWiki používat. @@ -3552,12 +3564,14 @@ Až to dokončíte, můžete '''[$2 vstoupit do své wiki]'''.", * [https://lists.wikimedia.org/mailman/listinfo/mediawiki-announce E-mailová konference oznámení MediaWiki]', ); -/** Kashubian (kaszëbsczi) */ +/** Kashubian (kaszëbsczi) + */ $messages['csb'] = array( 'mainpagetext' => "'''MediaWiki òsta zainstalowónô.'''", ); -/** Chuvash (Чӑвашла) */ +/** Chuvash (Чӑвашла) + */ $messages['cv'] = array( 'mainpagetext' => "'''«MediaWiki» вики-движока лартасси ăнăçлă вĕçленчĕ.'''", 'mainpagedocfooter' => 'Ку википе ĕçлеме пулăшакан информацине [//meta.wikimedia.org/wiki/%D0%9F%D0%BE%D0%BC%D0%BE%D1%89%D1%8C:%D0%A1%D0%BE%D0%B4%D0%B5%D1%80%D0%B6%D0%B0%D0%BD%D0%B8%D0%B5 усăç руководствинче] тупма пултаратăр. @@ -4078,7 +4092,7 @@ Es muss daher mit den nächsten Seite weitergemacht werden.", Sofern Änderungen vorgenommen werden sollen, kann man auf „← Zurück“ klicken.', 'config-install-step-done' => 'erledigt', 'config-install-step-failed' => 'gescheitert', - 'config-install-extensions' => 'Softwareerweiterungen', + 'config-install-extensions' => 'Programmerweiterungen', 'config-install-database' => 'Datenbank wird eingerichtet', 'config-install-schema' => 'Datenschema wird erstellt', 'config-install-pg-schema-not-exist' => 'Das PostgesSQL-Datenschema ist nicht vorhanden', @@ -4144,7 +4158,7 @@ Sobald alles erledigt wurde, kann auf das '''[$2 Wiki zugegriffen werden]'''. Wi * [https://lists.wikimedia.org/mailman/listinfo/mediawiki-announce Mailingliste neuer MediaWiki-Versionen]', ); -/** German (formal address) (‪Deutsch (Sie-Form)‬) +/** German (formal address) (Deutsch (Sie-Form)‎) * @author MichaelFrey */ $messages['de-formal'] = array( @@ -4163,7 +4177,7 @@ $messages['de-formal'] = array( $messages['diq'] = array( 'config-your-language' => 'Zıwanê şıma:', 'config-wiki-language' => 'Wiki zıwan:', - 'config-back' => '← Peyd', + 'config-back' => '← Peyser', 'config-continue' => 'Dewam ke', 'config-page-language' => 'Zıwan', 'config-page-welcome' => 'Şıma xeyr ameyê MediaWiki!', @@ -4204,6 +4218,7 @@ $messages['diq'] = array( 'config-license-cc-by' => 'Creative Commons Attribution', 'config-license-cc-by-nc-sa' => 'Creative Commons Attribution Non-Commercial Share Alike', 'config-license-pd' => 'Malê Şari', + 'config-extensions' => 'Olekeni', 'mainpagetext' => "'''MediaWiki vıst ra ser, vıraziya.'''", 'mainpagedocfooter' => 'Seba gurenayış u eyarkerdışê Wiki-Softwarey [//meta.wikimedia.org/wiki/Help:Contents İdarê karberi] de mıracaet ke. @@ -4214,7 +4229,8 @@ $messages['diq'] = array( * [https://lists.wikimedia.org/mailman/listinfo/mediawiki-announce MediaWiki ra lista serbest-dayışê postey]', ); -/** Lower Sorbian (dolnoserbski) */ +/** Lower Sorbian (dolnoserbski) + */ $messages['dsb'] = array( 'mainpagetext' => "'''MediaWiki jo se wuspěšnje instalěrowało.'''", 'mainpagedocfooter' => "Pomoc pśi wužywanju softwary wiki namakajoš pód [//meta.wikimedia.org/wiki/Help:Contents User's Guide]. @@ -4239,7 +4255,8 @@ $messages['dtp'] = array( * [https://lists.wikimedia.org/mailman/listinfo/mediawiki-announce Lis pininsuratan pinolabus do ModiaWiki]', ); -/** Greek (Ελληνικά) */ +/** Greek (Ελληνικά) + */ $messages['el'] = array( 'mainpagetext' => "'''To λογισμικό MediaWiki εγκαταστάθηκε με επιτυχία.'''", 'mainpagedocfooter' => 'Περισσότερες πληροφορίες σχετικά με τη χρήση και με τη ρύθμιση παραμέτρων θα βρείτε στους συνδέσμους: [//meta.wikimedia.org/wiki/MediaWiki_localisation Οδηγίες για τροποποίηση του περιβάλλοντος εργασίας] και [//meta.wikimedia.org/wiki/MediaWiki_User%27s_Guide Εγχειρίδιο χρήστη].', @@ -4821,7 +4838,7 @@ 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)) +/** español (formal) (español (formal)) * @author Dferg */ $messages['es-formal'] = array( @@ -4946,7 +4963,8 @@ $messages['eu'] = array( * [https://lists.wikimedia.org/mailman/listinfo/mediawiki-announce MediaWikiren argitalpenen posta zerrenda]', ); -/** Extremaduran (estremeñu) */ +/** Extremaduran (estremeñu) + */ $messages['ext'] = array( 'mainpagetext' => "'''MeyaGüiqui s'á istalau satihatoriamenti.'''", 'mainpagedocfooter' => "Consurta la [//meta.wikimedia.org/wiki/Help:Contents User's Guide] pa sabel mas al tentu el huncionamientu el software güiqui. @@ -4978,10 +4996,27 @@ $messages['fa'] = array( 'config-page-readme' => 'مرا بخوان', 'config-page-releasenotes' => 'یادداشت‌های انتشار', 'config-page-existingwiki' => 'ویکی موجود', + 'config-restart' => 'بله ، آن دوباره راه اندازی کن', + 'config-sidebar' => '* [//www.mediawiki.org صفحهٔ اصلی مدیاویکی] +* [//www.mediawiki.org/wiki/Help:Contents راهنمای کاربر] +* [//www.mediawiki.org/wiki/Manual:Contents راهنمای مدیر] +* [//www.mediawiki.org/wiki/Manual:FAQ پرسش‌های رایج] +---- +* مرا بخوان +* یادداشت‌های انتشار +* نسخه برداری +* ارتقا', + 'config-env-php' => 'پی‌اچ‌پی $1 نصب شده است.', + 'config-env-php-toolow' => 'پی‌اچ‌پی $1 نصب شده است. +در هر صورت، مدیاویکی نیاز به پی‌اچ‌پی نسخهٔ $2 یا بالاتر دارد.', 'config-db-type' => 'نوع پایگاه اطلاعات:', 'config-db-host' => 'میزبان پایگاه اطلاعات:', 'config-db-username' => 'نام کاربری پایگاه اطلاعات:', 'config-db-password' => 'کلمه عبور پایگاه اطلاعات:', + 'config-header-mysql' => 'تنظیمات مای‌اس‌کیو‌ال', + 'config-connection-error' => '$1. + +میزبان، نام کاربری و گذرواژه را بررسی کنید و دوباره امتحان کنید.', 'config-site-name' => 'نام ویکی:', 'config-site-name-blank' => 'نام تارنما را وارد کنید.', 'config-project-namespace' => 'فضای نام پروژه:', @@ -4991,9 +5026,12 @@ $messages['fa'] = array( 'config-admin-email' => 'پست الکترونیکی شما:', 'config-profile-private' => 'ویکی خصوصی', 'config-license' => 'حق تکثیر و مجوز:', + 'config-license-none' => 'بدون پاورقی مجوز', + 'config-license-pd' => 'دامنه عمومی', 'config-license-cc-choose' => 'انتخاب یک مجوز سفارشی عوام خلاق', 'config-email-settings' => 'تنظیمات پست الکترونیکی', 'config-upload-enable' => 'فعال سازی بارگذاری پرونده', + 'config-logo' => 'نشانی نامواره:', 'config-install-step-done' => 'انجام شد', 'config-install-step-failed' => 'ناموفق بود', 'config-help' => 'راهنما', @@ -5078,7 +5116,7 @@ Et voi asentaa MediaWikiä.', 'config-env-php-toolow' => 'PHP $1 on asennettu. MediaWiki vaatii PHP:n version $2 tai uudemman.', 'config-no-db' => 'Sopivaa tietokanta-ajuria ei löytynyt! Sinun täytyy asentaa tietokanta-ajurit PHP:lle. -Seuraavat tietokantatyypit ovat tuettuja: $1.', +Seuraavat tietokantatyypit ovat tuettuja: $1.', # Fuzzy 'config-safe-mode' => "'''Varoitus:''' PHP:n [http://www.php.net/features.safe-mode safe mode] -tila on aktiivinen. Se voi aiheuttaa ongelmia erityisesti tiedostojen tallentamisen ja matemaattisten kaavojen kanssa.", 'config-pcre' => 'PCRE-tukimoduuli puuttuu. @@ -5192,7 +5230,8 @@ Tarkista, että alla olevat taivutusmuodot ovat oikein. Jos eivät, tee tarvitta Taivutusmuodot: {{GRAMMAR:genitive|{{SITENAME}}}} (yön) – {{GRAMMAR:partitive|{{SITENAME}}}} (yötä) – {{GRAMMAR:elative|{{SITENAME}}}} (yöstä) – {{GRAMMAR:inessive|{{SITENAME}}}} (yössä) – {{GRAMMAR:illative|{{SITENAME}}}} (yöhön).", ); -/** Faroese (føroyskt) */ +/** Faroese (føroyskt) + */ $messages['fo'] = array( 'mainpagetext' => "'''Innlegging av Wiki-ritbúnaði væleydnað.'''", ); @@ -5202,6 +5241,7 @@ $messages['fo'] = array( * @author Crochet.david * @author Gomoko * @author Grondin + * @author Guillom * @author Hashar * @author IAlex * @author Jean-Frédéric @@ -5446,7 +5486,7 @@ Si vous ne voyez pas le système de base de données que vous essayez d'utiliser 'config-support-mysql' => '* $1 est le premier choix pour MediaWiki et est mieux pris en charge ([http://www.php.net/manual/en/mysql.installation.php how to compile PHP with MySQL support])', 'config-support-postgres' => "* $1 est un système de base de données populaire et ''open source'' qui peut être une alternative à MySQL ([http://www.php.net/manual/en/pgsql.installation.php how to compile PHP with PostgreSQL support]). Il peut contenir quelques bogues mineurs et n'est pas recommandé dans un environnement de production.", 'config-support-sqlite' => '* $1 est un système de base de données léger qui est bien supporté. ([http://www.php.net/manual/en/pdo.installation.php How to compile PHP with SQLite support], utilise PDO)', - 'config-support-oracle' => '* $1 est un système commercial de gestion de base de données d’entreprise. ([Http://www.php.net/manual/en/oci8.installation.php Comment compiler PHP avec le support OCI8])', + 'config-support-oracle' => '* $1 est un système commercial de gestion de base de données d’entreprise. ([http://www.php.net/manual/en/oci8.installation.php Comment compiler PHP avec le support OCI8])', 'config-support-ibm_db2' => "* $1 est une base de données d'entreprise commerciale.", 'config-header-mysql' => 'Paramètres de MySQL', 'config-header-postgres' => 'Paramètres de PostgreSQL', @@ -5748,7 +5788,8 @@ Lorsque c'est fait, vous pouvez '''[$2 accéder à votre wiki]'''.", * [https://lists.wikimedia.org/mailman/listinfo/mediawiki-announce Liste de discussion sur les distributions de MediaWiki]', ); -/** Cajun French (français cadien) */ +/** Cajun French (français cadien) + */ $messages['frc'] = array( 'mainpagetext' => "'''Vous avez bien installé MediaWiki.'''", 'mainpagedocfooter' => 'Lisez la [//meta.wikimedia.org/wiki/Help:Contents Guide des Useurs] pour apprendre à user le wiki software. @@ -5935,12 +5976,14 @@ $messages['frr'] = array( * [https://lists.wikimedia.org/mailman/listinfo/mediawiki-announce Mailingliste neuer MediaWiki-Versionen]', ); -/** Friulian (furlan) */ +/** Friulian (furlan) + */ $messages['fur'] = array( 'mainpagetext' => "'''MediaWiki e je stade instalade cun sucès.'''", ); -/** Western Frisian (Frysk) */ +/** Western Frisian (Frysk) + */ $messages['fy'] = array( 'mainpagetext' => "'''MediaWiki-program goed ynstallearre.'''", 'mainpagedocfooter' => "Rieplachtsje de [//meta.wikimedia.org/wiki/Help:Ynhâldsopjefte hantlieding] foar ynformaasje oer it gebrûk fan 'e wikisoftware. @@ -5965,7 +6008,8 @@ $messages['ga'] = array( agus an [//meta.wikimedia.org/wiki/MediaWiki_User%27s_Guide Lámhleabhar úsáideora] chun cabhair úsáide agus fíoraíochta a fháil.', ); -/** Gagauz (Gagauz) */ +/** Gagauz (Gagauz) + */ $messages['gag'] = array( 'mainpagetext' => "'''MediaWiki başarılan kuruldu.'''", 'mainpagedocfooter' => "Vikilän iş uurunda bilgi almaa için [//meta.wikimedia.org/wiki/Help:Contents User's Guide] sayfasına bakınız @@ -5977,7 +6021,8 @@ $messages['gag'] = array( * [https://lists.wikimedia.org/mailman/listinfo/mediawiki-announce MediaWiki release mailing list]", ); -/** Simplified Gan script (‪赣语(简体)‬) */ +/** Simplified Gan script (赣语(简体)‎) + */ $messages['gan-hans'] = array( 'mainpagetext' => "'''安装正MediaWiki喽。'''", 'mainpagedocfooter' => '参看[//meta.wikimedia.org/wiki/Help:Contents 用户指南]里头会话到啷用wiki软件 @@ -5989,7 +6034,8 @@ $messages['gan-hans'] = array( * [https://lists.wikimedia.org/mailman/listinfo/mediawiki-announce MediaWiki 发布email清单]', ); -/** Traditional Gan script (‪贛語(繁體)‬) */ +/** Traditional Gan script (贛語(繁體)‎) + */ $messages['gan-hant'] = array( 'mainpagetext' => "'''安裝正MediaWiki嘍。'''", 'mainpagedocfooter' => '參看[//meta.wikimedia.org/wiki/Help:Contents 用戶指南]裡頭會話到啷用wiki軟件 @@ -6640,7 +6686,7 @@ E Kopi vu dr GNU General Public-Lizänz sott zä 'config-sidebar' => '* [//www.mediawiki.org MediaWiki Websyte vu MediaWiki] * [//www.mediawiki.org/wiki/Help:Contents Nutzeraaleitig zue MediaWiki] * [//www.mediawiki.org/wiki/Manual:Contents Adminischtratoreaaleitig zue MediaWiki] -* [//www.mediawiki.org/wiki/Manual:FAQ Vilmol gstellti Froge zue MediaWiki]', +* [//www.mediawiki.org/wiki/Manual:FAQ Vilmol gstellti Froge zue MediaWiki]', # Fuzzy 'config-env-good' => 'D Inschtallationsumgäbig isch prieft wore. Du chasch MediaWiki inschtalliere.', 'config-env-bad' => 'D Inschtallationsumgäbigisch prieft wore. @@ -6652,7 +6698,7 @@ Du chasch MediaWiki nit inschtalliere.', Wänn Du ne Websyte mit ere große Bsuechrzahl bedrybsch, sottsch e weng ebis läse iber [//www.mediawiki.org/wiki/Unicode_normalization_considerations Unicode-Normalisierig (en)].", 'config-unicode-update-warning' => "'''Warnig:''' Di inschtalliert Version vum Unicode-Normalisierigswrapper verwändet e elteri Version vu dr Bibliothek vum [http://site.icu-project.org/ ICU-Projäkt]. Du sottsch si [//www.mediawiki.org/wiki/Unicode_normalization_considerations aktualisiere], wänn Dor d Verwändig vu Unicode wichtig isch.", - 'config-no-db' => 'S isch kei adäquate Datebanktryyber gfunde wore!', + 'config-no-db' => 'S isch kei adäquate Datebanktryyber gfunde wore!', # Fuzzy 'config-no-fts3' => "'''Warnig:''' SQLite isch ohni s [//sqlite.org/fts3.html FTS3-Modul] kumpiliert wore, s stehn kei Suechfunktione z Verfiegig.", 'config-register-globals' => "'''Warnig: Dr Parameter [http://php.net/register_globals register_globals] vu PHP isch aktiviert.''' '''Är sott deaktiviert wäre, wänn des megli isch.''' @@ -6708,12 +6754,14 @@ $messages['gu'] = array( * [https://lists.wikimedia.org/mailman/listinfo/mediawiki-announce મિડીયાવિકિ રીલીઝ મેઇલીંગ લીસ્ટ]', ); -/** Manx (Gaelg) */ +/** Manx (Gaelg) + */ $messages['gv'] = array( 'mainpagetext' => "'''Ta MediaWiki currit stiagh nish.'''", ); -/** Hakka (Hak-kâ-fa) */ +/** Hakka (Hak-kâ-fa) + */ $messages['hak'] = array( 'mainpagetext' => "'''Yí-kîn sṳ̀n-kûng ôn-chông MediaWiki.'''", 'mainpagedocfooter' => 'chhiáng fóng-mun [//meta.wikimedia.org/wiki/Help:Contents Yung-fu sú-chhak] yî-khi̍p sṳ́-yung chhṳ́ wiki ngiôn-khien ke sin-sit! @@ -6725,7 +6773,8 @@ $messages['hak'] = array( * [https://lists.wikimedia.org/mailman/listinfo/mediawiki-announce MediaWiki fat-phu email chhîn-tân]', ); -/** Hawaiian (Hawai`i) */ +/** Hawaiian (Hawai`i) + */ $messages['haw'] = array( 'mainpagetext' => "'''Ua pono ka ho‘ouka ‘ana o MediaWiki.'''", ); @@ -7274,7 +7323,8 @@ $3 * [https://lists.wikimedia.org/mailman/listinfo/mediawiki-announce רשימת התפוצה על השקת גרסאות]', ); -/** Hindi (हिन्दी) */ +/** Hindi (हिन्दी) + */ $messages['hi'] = array( 'mainpagetext' => "'''मीडियाविकिका इन्स्टॉलेशन पूरा हो गया हैं ।'''", 'mainpagedocfooter' => 'विकि सॉफ्टवेयरके इस्तेमाल के लिये [//meta.wikimedia.org/wiki/Help:Contents उपयोगकर्ता गाईड] देखें । @@ -7311,7 +7361,8 @@ $messages['hil'] = array( * [https://lists.wikimedia.org/mailman/listinfo/mediawiki-announce Lista sang mga ginapadal-an sang sulat kon may paguha-on nga MediaWiki]", ); -/** Croatian (hrvatski) */ +/** Croatian (hrvatski) + */ $messages['hr'] = array( 'mainpagetext' => "'''Softver MediaWiki je uspješno instaliran.'''", 'mainpagedocfooter' => 'Pogledajte [//meta.wikimedia.org/wiki/MediaWiki_localisation dokumentaciju o prilagodbi sučelja] @@ -7396,6 +7447,7 @@ Slědowace typy datoweje banki so podpěruja: $1. Jeli wužiwaš zhromadnje wužiwany serwer, proš swojeho poskićowarja, zo by přihódny ćěrjak datoweje banki instalował. Jeli sy PHP sam kompilował, konfiguruj jón znowa z aktiwizowanym programom datoweje banki, na přikład z pomocu ./configure --with-mysql. Jeli sy PHP z Debianoweho abo Ubuntuoweho paketa instalował, dyrbiš tež modul php5-mysql instalować.', + 'config-outdated-sqlite' => "'''Warnowanje''': maš SQLite $1, kotryž je starši hač minimalna trěbna wersija $2. SQLite njebudźe k dispoziciji stać.", 'config-no-fts3' => "'''Warnowanje''': SQLite je so bjez [//sqlite.org/fts3.html FTS3-modula] kompilował, pytanske funkcije njebudu k dispoziciji stać.", 'config-register-globals' => "'''Warnowanje: Funkcija [http://php.net/register_globals register_globals] PHP je zmóžnjena.''' '''Znjemóžń ju, jeli móžeš.''' @@ -7408,10 +7460,15 @@ To móže problemy zawinować, předewšěm, jeli so datajowe nahraća a podpěr 'config-xml-bad' => 'XML-modul za PHP faluje. MediaWiki trjeba funkcije w tutym modulu a njebudźe w tutej konfiguraciji fungować. Jeli wužiwaš Mandrake, instaluj paket php-xml.', + 'config-pcre' => 'Zda so, zo modul za PCRE-podpěru faluje. +MediaWiki trjeba z Perl kompatibelne funkcije za regularne wurazy, zo by fungował.', + 'config-pcre-no-utf8' => "'''Ćežki zmylk''': Zda so, zo PCRE-modul za PHP ma so bjez PCRE_UTF8-podpěry kompilować. +MediaWiki trjeba UTF-8-podpěru, zo by korektnje fungował.", 'config-memory-raised' => 'PHP-parameter memory_limit je $1, je so na hódnotu $2 zwyšił.', 'config-memory-bad' => "'''Warnowanje:''' PHP-parameter memory_limit ma hódnotu $1, To je najskerje přeniske. Instalacija móhła so njeporadźić!", + 'config-ctype' => "'''Ćežki zmylk''': PHP dyrbi so z podpěru za [http://www.php.net/manual/en/ctype.installation.php rozšěrjenje Ctype] kompilować.", 'config-xcache' => '[http://xcache.lighttpd.net/ XCache] je instalowany', 'config-apc' => '[http://www.php.net/apc APC] je instalowany', 'config-wincache' => '[http://www.iis.net/download/WinCacheForPhp WinCache] je instalowany', @@ -7460,6 +7517,7 @@ Změń ju jenož, jeli su přeswědčiwe přičiny za to.', 'config-type-ibm_db2' => 'IBM DB2', 'config-support-mysql' => '* $1 je primarny cil za MediaWiki a podpěruje so najlěpje ([http://www.php.net/manual/en/mysql.installation.php Nawod ke kompilowanju PHP z MySQL-podpěru])', 'config-support-postgres' => '* $1 je popularny system datoweje banki zjawneho žórła jako alternatiwa k MySQL ([http://www.php.net/manual/en/pgsql.installation.php nawod za kompilowanje PHP z podpěru PostgreSQL]). Móhło hišće někotre zmylki eksistować, a njeporuča so jón w produktiwnej wokolinje wužiwać.', + 'config-support-oracle' => '* $1 je komercielna předewzaćelska datowa banka. ([http://www.php.net/manual/en/oci8.installation.php Nawod za kompilowanje PHP z OCI8-podpěru])', 'config-support-ibm_db2' => '* $1 je komercielna předewzaćelska datowa banka.', 'config-header-mysql' => 'Nastajenja MySQL', 'config-header-postgres' => 'Nastajenja PostgreSQL', @@ -7826,7 +7884,7 @@ Telepítés megszakítva.', Ha megosztott webtárhelyet használsz, a szolgáltató dokumentációjában megtalálható a helyes hosztnév. -Ha Windows-alapú szerverre telepítesz, és MySQL-t használsz, a „localhost” nem biztos, hogy működni fog. Ha így van, próbáld meg a „127.0.0.1” helyi IP-cím használatát.', +Ha Windows-alapú szerverre telepítesz, és MySQL-t használsz, a „localhost” nem biztos, hogy működni fog. Ha így van, próbáld meg a „127.0.0.1” helyi IP-cím használatát.', # Fuzzy 'config-db-host-oracle' => 'Adatbázis TNS:', 'config-db-wiki-settings' => 'A wiki azonosítása', 'config-db-name' => 'Adatbázisnév:', @@ -8203,7 +8261,7 @@ Ha végeztél a fájl elhelyezésével, '''[$2 beléphetsz a wikibe]'''.", $messages['hu-formal'] = array( 'config-localsettings-upgrade' => "'''Figyelmeztetés''': már létezik a LocalSettings.php fájl. A szoftver frissíthető. -Adja meg a \$wgUpgradeKey-ben található kulcsot a beviteli mezőben", +Adja meg a \$wgUpgradeKey-ben található kulcsot a beviteli mezőben", # Fuzzy '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 session.gc_maxlifetime beállításának módosításával. @@ -8218,7 +8276,7 @@ Ellenőrizze, hogy a php.ini-ben a session.save_path beállítás a 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].", +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].", # Fuzzy 'config-register-globals' => "'''Figyelmeztetés: A PHP [http://php.net/register_globals register_globals] 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.", @@ -8227,7 +8285,7 @@ A bélyegképek készítése engedélyezve lesz, ha engedélyezi a feltöltések '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.', +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.', # Fuzzy '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.', @@ -8238,7 +8296,7 @@ Ez sokkal hatékonyabb a MySQL UTF-8-módjától, és lehetővé teszi, hogy a t '''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á.', +Csak akkor módosítson rajta, ha szükség van rá.', # Fuzzy 'config-sqlite-parent-unwritable-nogroup' => 'Nem lehet létrehozni az adatok tárolásához szükséges $1 könyvtárat, mert a webszerver nem írhat a szülőkönyvtárba ($2). A telepítő nem tudta megállapíteni, hogy melyik felhasználói fiókon fut a webszerver. @@ -8266,7 +8324,7 @@ 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]'''.", +Ha ezzel készen van, '''[$2 beléphet a wikibe]'''.", # Fuzzy '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) == @@ -8275,7 +8333,8 @@ Ha ezzel készen van, '''[$2 beléphet a wikibe]'''.", * [https://lists.wikimedia.org/mailman/listinfo/mediawiki-announce MediaWiki-kiadások levelezőlistája]", ); -/** Armenian (Հայերեն) */ +/** Armenian (Հայերեն) + */ $messages['hy'] = array( 'mainpagetext' => "'''«MediaWiki» ծրագիրը հաջողությամբ տեղադրվեց։'''", 'mainpagedocfooter' => "Այցելեք [//meta.wikimedia.org/wiki/Help:Contents User's Guide]՝ վիքի ծրագրային ապահովման օգտագործման մասին տեղեկությունների համար։ @@ -8991,7 +9050,7 @@ Instalasi dibatalkan.', Jika Anda menggunakan inang web bersama, penyedia inang Anda harus memberikan nama inang yang benar di dokumentasi mereka. -Jika Anda menginstal pada server Windows dan menggunakan MySQL, "localhost" mungkin tidak dapat digunakan sebagai nama server. Jika demikian, coba "127.0.0.1" untuk alamat IP lokal.', +Jika Anda menginstal pada server Windows dan menggunakan MySQL, "localhost" mungkin tidak dapat digunakan sebagai nama server. Jika demikian, coba "127.0.0.1" untuk alamat IP lokal.', # Fuzzy 'config-db-host-oracle' => 'TNS basis data:', 'config-db-host-oracle-help' => 'Masukkan [http://download.oracle.com/docs/cd/B28359_01/network.111/b28317/tnsnames.htm Local Connect Name] yang sah; berkas tnsnames.ora harus dapat diakses oleh instalasi ini.
    Jika Anda menggunakan pustaka klien 10g atau lebih baru, Anda juga dapat menggunakan metode penamaan [http://download.oracle.com/docs/cd/E11882_01/network.112/e10836/naming.htm Easy Connect].', 'config-db-wiki-settings' => 'Identifikasi wiki ini', @@ -9324,7 +9383,7 @@ Mengabaikan daftar bawaan.", 'config-install-keys' => 'Membuat kunci rahasia', 'config-insecure-keys' => "'''Peringatan:''' {{PLURAL:$2|Suatu|Beberapa}} kunci aman ($1) yang dibuat selama instalasi {{PLURAL:$2|tidak|tidak}} benar-benar aman. Pertimbangkan untuk mengubah {{PLURAL:$2|kunci|kunci-kunci}} tersebut secara manual.", 'config-install-sysop' => 'Membuat akun pengguna pengurus', - 'config-install-subscribe-fail' => 'Tidak dapat berlangganan mediawiki-announce', + 'config-install-subscribe-fail' => 'Tidak dapat berlangganan mediawiki-announce', # Fuzzy 'config-install-mainpage' => 'Membuat halaman utama dengan konten bawaan', 'config-install-extension-tables' => 'Pembuatan tabel untuk ekstensi yang diaktifkan', 'config-install-mainpage-failed' => 'Tidak dapat membuat halaman utama: $1', @@ -9355,7 +9414,8 @@ Setelah melakukannya, Anda dapat '''[$2 memasuki wiki Anda]'''.", * [https://lists.wikimedia.org/mailman/listinfo/mediawiki-announce Milis rilis MediaWiki]', ); -/** Interlingue (Interlingue) */ +/** Interlingue (Interlingue) + */ $messages['ie'] = array( 'mainpagetext' => "'''Software del wiki installat con successe.'''", ); @@ -9375,7 +9435,8 @@ $messages['ig'] = array( * [https://lists.wikimedia.org/mailman/listinfo/mediawiki-announce wéfù ndétu nke ozi MediaWiki]", ); -/** Iloko (Ilokano) */ +/** Iloko (Ilokano) + */ $messages['ilo'] = array( 'mainpagetext' => "'''Sibaballigi a nainstolar ti MediaWiki.'''", ); @@ -9393,7 +9454,8 @@ $messages['io'] = array( * [https://lists.wikimedia.org/mailman/listinfo/mediawiki-announce MediaWiki nova versioni posto-listo]", ); -/** Icelandic (íslenska) */ +/** Icelandic (íslenska) + */ $messages['is'] = array( 'mainpagetext' => "'''Uppsetning á MediaWiki heppnaðist.'''", 'mainpagedocfooter' => 'Ráðfærðu þig við [//meta.wikimedia.org/wiki/Help:Contents Notandahandbókina] fyrir frekari upplýsingar um notkun wiki-hugbúnaðarins. @@ -9409,6 +9471,7 @@ $messages['is'] = array( * @author Beta16 * @author Darth Kule * @author F. Cosoleto + * @author Gianfranco * @author Karika */ $messages['it'] = array( @@ -9483,7 +9546,7 @@ MediaWiki necessita di questo modulo per funzinare, che fornisce funzioni per le 'config-memory-bad' => "''Attenzione:''' Il valore di memory_limit di PHP è $1. Probabilmente è troppo basso. L'installazione potrebbe non riuscire!", - 'config-ctype' => "'''Errore''': PHP deve essere compilato con il supporto per la [http://www.php.net/manual/en/ctype.installation.php estensione Ctype].", + 'config-ctype' => "'''Errore''': PHP deve essere compilato con il supporto per l'[http://www.php.net/manual/it/ctype.installation.php estensione Ctype].", 'config-xcache' => '[http://xcache.lighttpd.net/ XCache] è installato', 'config-apc' => '[http://www.php.net/apc APC] è installato', 'config-wincache' => '[http://www.iis.net/download/WinCacheForPhp WinCache] è installato', @@ -9494,7 +9557,7 @@ La caching degli oggetti non è attivata.", Le miniature delle immagini saranno presenti se gli upload vengono abilitati.', 'config-gd' => 'Trovata la GD Graphics Library built-in. Le miniature delle immagini saranno presenti se gli upload vengono abilitati.', - 'config-no-scaling' => 'La GD library o ImageMagick non sono state trovate. + 'config-no-scaling' => 'Impossibile trovare GD library o ImageMagick. Le miniature delle immagini saranno disabilitate.', 'config-no-uri' => "'''Errore:''' Impossibile determinare l'URI attuale. Installazione interrotta.", @@ -9502,10 +9565,14 @@ Installazione interrotta.", 'config-using-server' => 'Nome server in uso "$1".', 'config-using-uri' => 'URL del server in uso "$1$2".', 'config-db-type' => 'Tipo di database:', + 'config-db-wiki-settings' => 'Identifica questo wiki', 'config-db-name' => 'Nome del database:', + 'config-db-name-oracle' => 'Schema del database:', + 'config-db-username' => 'Nome utente del database:', 'config-db-password-empty' => 'Inserire una password per il nuovo utente del database: $1. Anche se può essere possibile creare utenti senza password, questo non è sicuro.', 'config-db-install-help' => "Inserire il nome utente e la password che verranno usate per la connessione al database durante il processo d'installazione.", + 'config-db-prefix' => 'Prefisso tabella del database:', 'config-db-charset' => 'Set di caratteri del database', 'config-charset-mysql5' => 'MySQL 4.1/5.0 UTF-8', 'config-charset-mysql4' => 'MySQL 4.0 con compatibilità UTF-8', @@ -9523,15 +9590,18 @@ Da cambiare solamente se si è sicuri di averne bisogno.', 'config-header-oracle' => 'Impostazioni Oracle', 'config-header-ibm_db2' => 'Impostazioni IBM DB2', 'config-invalid-db-type' => 'Tipo di database non valido', + 'config-db-web-account' => "Account del database per l'accesso web", 'config-db-web-create' => "Crea l'account se non esiste già", 'config-mysql-engine' => 'Storage engine:', 'config-mysql-innodb' => 'InnoDB', 'config-mysql-myisam' => 'MyISAM', 'config-mysql-charset' => 'Set di caratteri del database:', + 'config-mysql-binary' => 'Binario', 'config-mysql-utf8' => 'UTF-8', 'config-ibm_db2-low-db-pagesize' => "Il database DB2 in uso ha una tablespace predefinita con un insufficiente pagesize, che dovrebbe essere '''32K''' o maggiore.", 'config-ns-generic' => 'Progetto', 'config-ns-site-name' => 'Stesso nome wiki: $1', + 'config-ns-other-default' => 'MyWiki', 'config-admin-box' => 'Account amministratore', 'config-admin-name' => 'Tuo nome:', 'config-admin-password' => 'Password:', @@ -9552,26 +9622,47 @@ Specificare un nome utente diverso.', Inserire un indirizzo email se si desidera effettuare l'iscrizione alla mailing list.", 'config-almost-done' => 'Hai quasi finito! Adesso puoi saltare la rimanente parte della configurazione e semplicemente installare la wiki.', + 'config-optional-continue' => 'Fammi altre domande.', + 'config-profile-wiki' => 'Wiki tradizionale', + 'config-profile-no-anon' => 'Creazione utenza obbligatoria', + 'config-profile-fishbowl' => 'Solo editori autorizzati', + 'config-profile-private' => 'Wiki privata', 'config-license' => 'Copyright e licenza:', + 'config-license-none' => 'Nessun piè di pagina per la licenza', 'config-license-cc-by-sa' => 'Creative Commons Attribuzione-Condividi allo stesso modo', 'config-license-cc-by' => 'Creative Commons Attribuzione', 'config-license-cc-by-nc-sa' => 'Creative Commons Attribuzione-Non commerciale-Condividi allo stesso modo', 'config-license-cc-0' => 'Creative Commons Zero (pubblico dominio)', 'config-license-gfdl' => 'GNU Free Documentation License 1.3 o versioni successive', 'config-license-pd' => 'Pubblico dominio', + 'config-license-cc-choose' => 'Seleziona una delle licenze Creative Commons', + 'config-license-help' => "Molti wiki pubblici rilasciano i loro contributi con una [http://freedomdefined.org/Definition licenza libera]. Questo aiuta a creare un senso di proprietà condivisa nella comunità e incoraggia a contribuire a lungo termine. Non è generalmente necessario per un wiki privato o aziendale. + +Se vuoi usare testi da Wikipedia, o desideri che Wikipedia possa essere in grado di accettare testi copiati dal tuo wiki, dovresti scegliere '''Creative Commons Attribution Share Alike'''. + +In precedenza Wikipedia ha utilizzato la GNU Free Documentation License. La GFDL è una licenza valida, ma è di difficile comprensione e complica il riutilizzo dei contenuti.", 'config-email-settings' => 'Impostazioni email', + 'config-email-user' => 'Abilita invio email fra utenti', 'config-email-auth' => 'Abilita autenticazione via email', + 'config-upload-enable' => 'Consentire il caricamento di file', 'config-upload-deleted' => 'Directory per i file cancellati:', 'config-logo' => 'URL del logo:', + 'config-instantcommons' => 'Abilita Instant Commons', 'config-cc-again' => 'Seleziona di nuovo...', 'config-cc-not-chosen' => 'Scegliere quale licenza Creative Commons si desidera e cliccare su "procedi".', 'config-advanced-settings' => 'Configurazione avanzata', + 'config-memcache-needservers' => 'È stato selezionato il tipo di caching Memcached, ma non è stato impostato alcun server.', 'config-memcache-badip' => 'È stato inserito un indirizzo IP non valido per Memcached: $1.', 'config-extensions' => 'Estensioni', + 'config-install-step-done' => 'fatto', + 'config-install-step-failed' => 'non riuscito', + 'config-install-schema' => 'Creazione dello schema', + 'config-install-user' => 'Creazione di utente del database', 'config-install-user-alreadyexists' => 'L\'utente "$1" è già presente', 'config-install-user-create-failed' => 'Creazione dell\'utente "$1" non riuscita: $2', 'config-install-user-missing' => 'L\'utente indicato "$1" non esiste.', 'config-install-tables-failed' => "'''Errore''': La creazione della tabella non è riuscita: $1", + 'config-install-interwiki' => 'Riempimento della tabella interwiki predefinita', 'config-install-interwiki-list' => 'Impossibile leggere il file interwiki.list.', 'config-install-stats' => 'Inizializzazione delle statistiche', 'config-install-keys' => 'Generazione delle chiavi segrete', @@ -10122,7 +10213,8 @@ $messages['jut'] = array( 'mainpagedocfooter' => "Se vores engelskspråĝede [//meta.wikimedia.org/wiki/MediaWiki_localisation dokumentåsje tilpasnenge'm åf æ brugergrænseflade] og [//meta.wikimedia.org/wiki/MediaWiki_User%27s_Guide æ brugervejlednenge] før åplysnenger åpsætnenge'm og anvendelse.", ); -/** Javanese (Basa Jawa) */ +/** Javanese (Basa Jawa) + */ $messages['jv'] = array( 'mainpagetext' => "'''Prangkat empuk wiki wis suksès dipasang.'''", 'mainpagedocfooter' => "Mangga maca [//meta.wikimedia.org/wiki/Help:Contents User's Guide] kanggo katrangan luwih langkung prakara panggunan prangkat empuk wiki @@ -10132,8 +10224,90 @@ $messages['jv'] = array( * [https://lists.wikimedia.org/mailman/listinfo/mediawiki-announce Milis rilis MediaWiki]", ); -/** Georgian (ქართული) */ +/** Georgian (ქართული) + * @author David1010 + */ $messages['ka'] = array( + 'config-information' => 'ინფორმაცია', + 'config-your-language' => 'თქვენი ენა:', + 'config-wiki-language' => 'ვიკის ენა:', + 'config-back' => '← უკან', + 'config-continue' => 'გაგრძელება →', + 'config-page-language' => 'ენა', + 'config-page-welcome' => 'კეთილი იყოს თქვენი მობრძანება მედიავიკიში!', + 'config-page-dbconnect' => 'მონაცემთა ბაზასთან დაკავშირება', + 'config-page-dbsettings' => 'მონაცემთა ბაზის კონფიგურაცია', + 'config-page-name' => 'სახელი', + 'config-page-options' => 'პარამეტრები', + 'config-page-install' => 'ინსტალაცია', + 'config-page-complete' => 'დასრულებულია!', + 'config-page-restart' => 'ინსტალაციის თავიდან დაწყება', + 'config-page-readme' => 'წამიკითხე', + 'config-page-copying' => 'ლიცენზია', + 'config-page-upgradedoc' => 'განახლება', + 'config-restart' => 'დიახ, თავიდან დაიწყეთ', + 'config-sidebar' => '* [//www.mediawiki.org მედიავიკის ვებ-გვერდი] +* [//www.mediawiki.org/wiki/Help:Contents/ka მომხმარებლების დახმარება] +* [//www.mediawiki.org/wiki/Manual:Contents/ka ადმინისტრატორების დახმარება] +* [//www.mediawiki.org/wiki/Manual:FAQ/ka FAQ] +---- +* წამიკითხე +* ინფორმაცია გამოშვებაზე +* ლიცენზია +* განახლება', + 'config-db-type' => 'მონაცემთა ბაზის ტიპი:', + 'config-db-host-oracle' => 'მონაცემთა ბაზის TNS:', + 'config-db-name' => 'მონაცემთა ბაზის სახელი:', + 'config-db-name-oracle' => 'მონაცემთა ბაზის სქემა:', + 'config-db-username' => 'მონაცემთა ბაზის მომხმარებლის სახელი:', + 'config-db-password' => 'მონაცემთა ბაზის პაროლი:', + 'config-charset-mysql5-binary' => 'MySQL 4.1/5.0 ორობითი', + 'config-charset-mysql5' => 'MySQL 4.1/5.0 UTF-8', + 'config-db-port' => 'მონაცემთა ბაზის პორტი:', + 'config-db-schema' => 'მედიავიკის სქემა:', + 'config-header-mysql' => 'MySQL-ის პარამეტრები', + 'config-header-postgres' => 'PostgreSQL-ის პარამეტრები', + 'config-header-sqlite' => 'SQLite-ის პარამეტრები', + 'config-header-oracle' => 'Oracle-ის პარამეტრები', + 'config-header-ibm_db2' => 'IBM DB2-ის პარამეტრები', + 'config-invalid-db-type' => 'არასწორი მონაცემთა ბაზის ტიპი', + 'config-mysql-innodb' => 'InnoDB', + 'config-mysql-myisam' => 'MyISAM', + 'config-mysql-binary' => 'ორობითი', + 'config-mysql-utf8' => 'UTF-8', + 'config-site-name' => 'ვიკის სახელი:', + 'config-site-name-blank' => 'შეიყვანეთ ვებ-გვერდის სახელი.', + 'config-project-namespace' => 'პროექტის სახელთა სივრცე:', + 'config-ns-generic' => 'პროექტი', + 'config-ns-other' => 'სხვა (მიუთითეთ)', + 'config-ns-other-default' => 'ჩემი ვიკი', + 'config-admin-box' => 'ადმინისტრატორის ანგარიში', + 'config-admin-name' => 'თქვენი სახელი:', + 'config-admin-password' => 'პაროლი:', + 'config-admin-password-confirm' => 'პაროლი ხელმეორედ:', + 'config-admin-name-blank' => 'შეიყვანეთ ადმინისტრატორის მომხმარებლის სახელი.', + 'config-admin-email' => 'ელ. ფოსტის მისამართი:', + 'config-profile-wiki' => 'ტრადიციული ვიკი', + 'config-profile-private' => 'დახურული ვიკი', + 'config-license' => 'საავტორო უფლები და ლიცენზია:', + 'config-license-cc-by-sa' => 'Creative Commons Attribution Share Alike', + 'config-license-cc-by' => 'Creative Commons Attribution', + 'config-license-cc-by-nc-sa' => 'Creative Commons Attribution Non-Commercial Share Alike', + 'config-license-cc-0' => 'Creative Commons Zero (საზოგადოებრივი საკუთრება)', + 'config-license-gfdl' => 'GNU Free Documentation License 1.3 ან უფრო გვიანი', + 'config-license-pd' => 'საზოგადოებრივი საკუთრება', + 'config-license-cc-choose' => 'აირჩიეთ Creative Commons-ის ლიცენზიიდან ერთ-ერთი', + 'config-email-settings' => 'ელ. ფოსტის პარამეტრები', + 'config-upload-settings' => 'სურათებისა და ფაილების ატვირთვა', + 'config-upload-enable' => 'ფაილების ატვირთვის ჩართვა', + 'config-logo' => 'ლოგოს URL:', + 'config-cc-again' => 'აირჩიეთ კიდევ ერთხელ...', + 'config-extensions' => 'გაფართოებები', + 'config-install-step-done' => 'შესრულდა', + 'config-install-step-failed' => 'ვერ მოხერხდა', + 'config-install-tables' => 'ცხრილების შექმნა', + 'config-download-localsettings' => 'LocalSettings.php-ის გადმოწერა', + 'config-help' => 'დახმარება', 'mainpagetext' => "'''მედიავიკი წარმატებით ჩაიტვირთა.'''", 'mainpagedocfooter' => 'ვიკი პროგრამის გამოყენების ინფორმაციისთვის იხილეთ [//meta.wikimedia.org/wiki/Help:Contents მომხმარებლის მეგზური]. @@ -10144,7 +10318,8 @@ $messages['ka'] = array( * [https://lists.wikimedia.org/mailman/listinfo/mediawiki-announce მედიავიკის გამოცემის დაგზავნის სია]', ); -/** Kara-Kalpak (Qaraqalpaqsha) */ +/** Kara-Kalpak (Qaraqalpaqsha) + */ $messages['kaa'] = array( 'mainpagetext' => "'''MediaWiki tabıslı ornatıldı.'''", 'mainpagedocfooter' => "Wiki bag'darlamasın qollanıw haqqındag'i mag'lıwmat usın [//meta.wikimedia.org/wiki/Help:Contents Paydalanıwshılar qollanbasınan] ken'es alın'. @@ -10189,7 +10364,8 @@ $messages['kiu'] = array( * [https://lists.wikimedia.org/mailman/listinfo/mediawiki-announce MediaWiki ra lista serbest-daena postey]", ); -/** Kazakh (Arabic script) (‫قازاقشا (تٴوتە)‬) */ +/** Kazakh (Arabic script) (قازاقشا (تٴوتە)‏) + */ $messages['kk-arab'] = array( 'mainpagetext' => "'''مەدىياۋىيكىي بۋماسى ٴساتتى ورناتىلدى.'''", 'mainpagedocfooter' => 'ۋىيكىي باعدارلامالىق جاساقتاماسىن قالاي قولداناتىن اقپاراتى ٴۇشىن [//meta.wikimedia.org/wiki/Help:Contents پايدالانۋشىلىق نۇسقاۋلارىنان] كەڭەس الىڭىز. @@ -10200,7 +10376,8 @@ $messages['kk-arab'] = array( * [https://lists.wikimedia.org/mailman/listinfo/mediawiki-announce مەدىياۋىيكىي شىعۋ تۋرالى حات تاراتۋ ٴتىزىمى]', ); -/** Kazakh (Cyrillic script) (‪Қазақша (кирил)‬) */ +/** Kazakh (Cyrillic script) (қазақша (кирил)‎) + */ $messages['kk-cyrl'] = array( 'mainpagetext' => "'''МедиаУики бумасы сәтті орнатылды.'''", 'mainpagedocfooter' => 'Уики бағдарламалық жасақтамасын қалай қолданатын ақпараты үшін [//meta.wikimedia.org/wiki/Help:Contents Пайдаланушылық нұсқауларынан] кеңес алыңыз. @@ -10211,7 +10388,8 @@ $messages['kk-cyrl'] = array( * [https://lists.wikimedia.org/mailman/listinfo/mediawiki-announce МедиаУики шығу туралы хат тарату тізімі]', ); -/** Kazakh (Latin script) (‪Qazaqşa (latın)‬) */ +/** Kazakh (Latin script) (qazaqşa (latın)‎) + */ $messages['kk-latn'] = array( 'mainpagetext' => "'''MedïaWïkï bwması sätti ornatıldı.'''", 'mainpagedocfooter' => 'Wïkï bağdarlamalıq jasaqtamasın qalaý qoldanatın aqparatı üşin [//meta.wikimedia.org/wiki/Help:Contents Paýdalanwşılıq nusqawlarınan] keñes alıñız. @@ -10252,7 +10430,8 @@ $messages['km'] = array( * [https://lists.wikimedia.org/mailman/listinfo/mediawiki-announce បញ្ជី​ពិភាក្សា​ការផ្សព្វផ្សាយ​របស់​មេឌាវិគី]', ); -/** Kannada (ಕನ್ನಡ) */ +/** Kannada (ಕನ್ನಡ) + */ $messages['kn'] = array( 'mainpagetext' => "'''ವಿಕಿ ತಂತ್ರಾಂಶವನ್ನು ಯಶಸ್ವಿಯಾಗಿ ಅನುಸ್ಥಾಪಿಸಲಾಯಿತು.'''", 'mainpagedocfooter' => 'ವಿಕಿ ತಂತ್ರಾಂಶವನ್ನು ಬಳಸುವ ಬಗ್ಗೆ ಮಾಹಿತಿಗೆ [//meta.wikimedia.org/wiki/Help:Contents ಬಳಕೆದಾರರಿಗೆ ನಿರ್ದೇಶನ ಪುಟ] ನೋಡಿ. @@ -10273,7 +10452,7 @@ $messages['ko'] = array( 'config-title' => 'MediaWiki $1 설치', 'config-information' => '정보', 'config-localsettings-upgrade' => 'LocalSettings.php 파일이 감지되었습니다. -이 설치를 업그레이드하려면 아래 상자에 $wgUpgradeKey의 값을 입력해주세요. +이 설치를 업그레이드하려면 아래 상자에 $wgUpgradeKey의 값을 입력하세요. LocalSettings.php에 찾으세요.', 'config-localsettings-cli-upgrade' => 'LocalSettings.php 파일이 감지되었습니다. 이 설치를 업그레이드하려면 update.php를 대신 실행하세요', @@ -10285,7 +10464,7 @@ LocalSettings.php에 찾으세요.', $1', 'config-localsettings-incomplete' => '기존 LocalSettings.php가 완전하지 않은 것 같습니다. $1 변수가 설정되어 있지 않습니다. -이 변수가 설정되도록 LocalSettings.php를 변경하고 "계속"을 클릭하세요.', +이 변수가 설정되도록 LocalSettings.php를 바꾸고 "계속"을 클릭하세요.', 'config-localsettings-connection-error' => 'LocalSettings.php 또는 AdminSettings.php에 지정한 설정을 사용하여 데이터베이스에 연결할 때 오류가 발생했습니다. 이러한 설정을 수정하고 다시 시도하세요. $1', @@ -10303,12 +10482,12 @@ php.ini를 확인하고 session.save_path가 적절한 디렉토리 'config-back' => '← 뒤로', 'config-continue' => '계속 →', 'config-page-language' => '언어', - 'config-page-welcome' => '미디어위키에 온 것을 환영합니다!', + 'config-page-welcome' => '미디어위키에 오신 것을 환영합니다!', 'config-page-dbconnect' => '데이터베이스에 연결', 'config-page-upgrade' => '기존 설치 업그레이드', 'config-page-dbsettings' => '데이터베이스 설정', 'config-page-name' => '이름', - 'config-page-options' => '옵션', + 'config-page-options' => '설정', 'config-page-install' => '설치', 'config-page-complete' => '완료!', 'config-page-restart' => '설치 다시 시작', @@ -10317,10 +10496,10 @@ php.ini를 확인하고 session.save_path가 적절한 디렉토리 'config-page-copying' => '전문', 'config-page-upgradedoc' => '업그레이드하기', 'config-page-existingwiki' => '기존 위키', - 'config-help-restart' => '당신이 입력한 모든 저장된 데이터를 지우고 설치 과정을 다시 시작하겠습니까?', - 'config-restart' => '예, 다시 시작합니다.', + 'config-help-restart' => '입력한 모든 저장된 데이터를 지우고 설치 과정을 다시 시작하겠습니까?', + 'config-restart' => '예, 다시 시작합니다', 'config-welcome' => '=== 사용 환경 검사 === -이 환경이 미디어위키 설치에 적합할 지 기본 검사를 실행합니다. +이 환경이 미디어위키 설치에 적합한지 기본 검사를 실행합니다. 설치 중 도움이 필요하다면 이 검사 결과를 함께 제공해주어야 합니다.', 'config-copyright' => "=== 저작권 및 이용 약관 === @@ -10358,7 +10537,7 @@ $1 다음 데이터베이스 유형을 지원합니다 : $1. 호스팅을 공유하고 있다면 적절한 데이터베이스 드라이버를 설치하도록 호스팅 제공 업체에 문의하세요. -PHP를 직접 컴파일할 경우 데이터베이스 클라이언트를 사용하여 활성화하도록 다시 설정하세요. 예들 들어 ./configure --with-mysql을 사용합니다. +PHP를 직접 컴파일할 경우 데이터베이스 클라이언트를 사용하여 활성화하도록 다시 설정하세요. 예들 들어 ./configure --with-mysql을 사용하세요. 데비안이나 우분트 패키지에서 PHP를 설치했다면 php-mysql 모듈도 설치해야 합니다.', 'config-outdated-sqlite' => "'''경고''': SQLite 필요한 최소 $2 버전보다 낮은 $1(이)가 있습니다. SQLite는 사용할 수 없습니다.", 'config-no-fts3' => "'''경고''': SQLite는 [//sqlite.org/fts3.html FTS3 모듈] 없이 컴파일되어, 검색 기능은 백엔드에 사용할 수 없습니다.", @@ -10378,7 +10557,7 @@ PHP를 직접 컴파일할 경우 데이터베이스 클라이언트를 사용 이 옵션은 미디어위키에 끔찍한 버그를 일으킵니다. 설치할 수 없습니다. 또는 미디어위키가 사용하지 않는 이 옵션을 비활성화하십시오.", 'config-safe-mode' => "'''경고:''' [http://www.php.net/features.safe-mode 안전 모드]이 활성합니다! -이는 특히 파일을 올리거나 math를 지원하는 데 문제가 발생할 수 있습니다.", +특히 파일을 올리거나 math를 지원하는 데 문제가 발생할 수 있습니다.", 'config-xml-bad' => 'PHP의 XML 모듈이 없습니다. 미디어위키는 이 모듈의 기능이 필요하며 이 설정에서는 작동하지 않습니다. Mandrake를 실행하고 있다면 php-xml 패키지를 설치하세요.', @@ -10388,7 +10567,7 @@ Mandrake를 실행하고 있다면 php-xml 패키지를 설치하세요.', 미디어위키가 제대로 작동하려면 UTF-8 지원이 필요합니다.", 'config-memory-raised' => 'PHP의 memory_limit는 $1이며 $2(으)로 늘리세요.', 'config-memory-bad' => "'''경고:''' PHP의 memory_limit는 $1입니다. -이는 아마도 너무 낮은 것 같습니다. +아마도 너무 낮은 것 같습니다. 설치가 실패할 수 있습니다!", 'config-ctype' => "'''치명''': PHP는 [http://www.php.net/manual/en/ctype.installation.php Ctype 확장 기능]에 대해 지원하여 컴파일해야 합니다.", 'config-xcache' => '[http://xcache.lighttpd.net/ XCache]가 설치되었습니다', @@ -10411,7 +10590,7 @@ Mandrake를 실행하고 있다면 php-xml 패키지를 설치하세요.', 'config-using-server' => '"$1"(을)를 서버 이름으로 사용합니다.', 'config-using-uri' => '"$1$2"(을)를 서버 URL로 사용합니다.', 'config-uploads-not-safe' => "'''경고:''' 올리기에 대한 기본 디렉토리($1)는 임의의 스크립트 실행에 취약합니다. -미디어위키는 보안 위협에 대한 모든 올린 파일을 검사하지만, 이는 올리기를 활성화하기 전에 [//www.mediawiki.org/wiki/Manual:Security#Upload_security 이 보안 취약점을 해결할 것]을 매우 권장합니다.", +미디어위키는 보안 위협에 대한 모든 올린 파일을 검사하지만, 올리기를 활성화하기 전에 [//www.mediawiki.org/wiki/Manual:Security#Upload_security 이 보안 취약점을 해결할 것]을 매우 권장합니다.", 'config-no-cli-uploads-check' => "'''경고:''' 올리기에 대한 기본 디렉토리($1)는 CLI를 설치하는 동안 임의의 스크립트 실행에 대한 취약점에 대해 검사되지 않습니다.", 'config-brokenlibxml' => '시스템에 버그가 있는 PHP와 libxml2의 조합이 있으며 미디어위키나 다른 웹 어플리케이션에 숨겨진 데이터 손상을 일으킬 수 있습니다. PHP 5.2.9 이후와 libxml2 2.7.3 이후로 업그레이드하세요 ([//bugs.php.net/bug.php?id=45996 PHP에 제기한 버그]). @@ -10424,7 +10603,7 @@ PHP 5.2.9 이후와 libxml2 2.7.3 이후로 업그레이드하세요 ([//bugs.ph 'config-db-host' => '데이터베이스 호스트:', 'config-db-host-help' => '데이터베이스 서버가 다른 서버에 있을 경우 여기에 호스트 이름이나 IP 주소를 입력하세요. -웹 호스팅을 공유하여 사용하는 경우 호스팅 공급자는 당신에게 이들 설명서의 올바른 호스트 이름을 표기해야 합니다. +공유된 웹 호스팅을 사용하는 경우 호스팅 공급자는 올바른 호스트 이름을 설명해야 합니다. 윈도 서버에 설치하고 MySQL을 사용할 경우 "localhost"는 서버 이름으로 작동하지 않을 수 있습니다. 그렇지 않으면 로컬 IP 주소로 "127.0.0.1"를 시도하세요. @@ -10434,9 +10613,9 @@ PostgreSQL을 사용할 경우 유닉스 소켓을 통해 연결되도록 입력 'config-db-wiki-settings' => '이 위키 식별', 'config-db-name' => '데이터베이스 이름:', 'config-db-name-help' => '위키를 식별하기 위한 이름을 선택하세요. -이는 공백이 없어야 합니다. +공백이 없어야 합니다. -웹 호스팅을 공유해 사용하는 경우 호스팅 제공 업체도 당신에게 제어판을 통해 데이터베이스를 사용하거나 만들 수 있도록 특정 데이터베이스 이름을 제공합니다.', +공유된 웹 호스팅 사용하는 경우 호스팅 제공 업체가 특정 데이터베이스 이름을 제공하거나 제어판에서 데이터베이스를 만들 수 있도록 합니다.', 'config-db-name-oracle' => '데이터베이스 스키마:', 'config-db-account-oracle-warn' => '데이터베이스 백엔드로 오라클을 설치하기 위해 지원하는 세 가지 시나리오가 있습니다: @@ -10447,10 +10626,11 @@ PostgreSQL을 사용할 경우 유닉스 소켓을 통해 연결되도록 입력 'config-db-username' => '데이터베이스 사용자 이름:', 'config-db-password' => '데이터베이스 비밀번호:', 'config-db-password-empty' => '새 데이터베이스 사용자의 비밀번호를 입력하세요: $1. -비밀번호 없이 사용자를 만들 수도 있지만 이는 안전하지 않습니다.', +비밀번호 없이 사용자를 만들 수도 있지만 안전하지 않습니다.', 'config-db-install-username' => '설치 과정 중에 데이터베이스에 연결할 때 사용할 사용자 이름을 입력하세요. -이는 미디어위키 계정의 사용자 이름이 아닌 데이터베이스에 대한 사용자 이름입니다.', - 'config-db-install-password' => '설치 과정 중에 데이터베이스에 연결할 때 사용할 비밀번호을 입력하세요. 이는 미디어위키 계정의 비밀번호가 아닌 데이터베이스에 대한 비밀번호입니다.', +미디어위키 계정의 사용자 이름이 아닌 데이터베이스에 대한 사용자 이름입니다.', + 'config-db-install-password' => '설치 과정 중에 데이터베이스에 연결할 때 사용할 비밀번호을 입력하세요. +미디어위키 계정의 비밀번호가 아닌 데이터베이스에 대한 비밀번호입니다.', 'config-db-install-help' => '설치 과정 중에 데이터베이스에 연결할 때 사용할 사용자 이름과 비밀번호를 입력하세요.', 'config-db-account-lock' => '정상적으로 작동하는 동안 같은 사용자 이름과 비밀번호를 사용함', 'config-db-wiki-account' => '정상적인 작동을 위한 사용자 계정', @@ -10465,10 +10645,10 @@ PostgreSQL을 사용할 경우 유닉스 소켓을 통해 연결되도록 입력 'config-charset-mysql5-binary' => 'MySQL 4.1/5.0 바이너리', 'config-charset-mysql5' => 'MySQL 4.1/5.0 UTF-8', 'config-charset-mysql4' => 'MySQL 4.0 UTF-8 하위 호환성', - 'config-charset-help' => "'''경고:''' MySQL 4.1에서 '''UTF-8 하위 호환성'''을 사용하고 나서 mysqldump로 데이터베이스에 백업한다면 이는 모든 ASCII가 아닌 문자를 파괴하고 손상한 백업을 되돌릴 수 없습니다! + 'config-charset-help' => "'''경고:''' MySQL 4.1에서 '''UTF-8 하위 호환성'''을 사용하고 나서 mysqldump로 데이터베이스에 백업한다면 모든 ASCII가 아닌 문자를 파괴하고 손상한 백업을 되돌릴 수 없습니다! '''바이너리 모드'''에서는 미디어위키는 바이너리 필드의 데이터베이스에 UTF-8 텍스트를 저장합니다. -이는 MySQL의 UTF-8 모드를 보다 더 효율적이고 유니코드 문자의 전체 범위를 사용할 수 있습니다. +MySQL의 UTF-8 모드를 보다 더 효율적이고 유니코드 문자의 전체 범위를 사용할 수 있습니다. '''UTF-8 모드'''에서는 MySQL은 데이터를 설정하는 어떤 문자열인지를 알 것이며, 표현하고 적절하게 그것을 변환할 수 있지만 [//en.wikipedia.org/wiki/Mapping_of_Unicode_character_planes 기본 다국어 범위] 상의 문자를 저장하지 못하게 될 수 있습니다.", 'config-mysql-old' => 'MySQL $1 이상이 필요하나 $2(이)가 있습니다.', @@ -10484,8 +10664,8 @@ PostgreSQL을 사용할 경우 유닉스 소켓을 통해 연결되도록 입력 PHP 파일이 있는 곳을 우리가 이를 맡길 수 없는 이유는 웹을 통해 접근할 수 없다는 것입니다. -설치 마법사가 이과 함께 .htaccess 파일을 만들지만 거기서 실패하면 누군가는 원시 데이터베이스에 접근하는 데 실패합니다. -이는 원시 사용자 데이터(이메일 주소, 암호 해시) 뿐만 아니라 삭제된 개정판과 위키의 다른 제한된 데이터를 포함합니다. +설치 마법사가 이과 함께 .htaccess 파일을 만들지만 거기서 실패하면 누군가는 원본 데이터베이스에 접근하는 데 실패합니다. +원시 사용자 데이터(이메일 주소, 암호 해시) 뿐만 아니라 삭제된 개정판과 위키의 다른 제한된 데이터를 포함합니다. /var/lib/mediawiki/yourwiki와 같이 모두 다른 곳에서 데이터베이스를 넣어보도록 하세요.', 'config-oracle-def-ts' => '기본 테이블공간:', @@ -10496,7 +10676,7 @@ PHP 파일이 있는 곳을 우리가 이를 맡길 수 없는 이유는 웹을 $1 -데이터베이스 시스템이 표시되지 않을 때 아래에 나열된 다음 지원을 활성화하려면 당신은 위의 링크된 지시에 따라 사용해볼 수도 있습니다.', +데이터베이스 시스템이 표시되지 않을 때 아래에 나열된 다음 지원을 활성화하려면 위의 링크된 지시에 따라 설치해볼 수 있습니다.', 'config-support-mysql' => '* $1은 미디어위키의 기본 대상으로 가장 잘 지원합니다. ([http://www.php.net/manual/en/mysql.installation.php MySQL을 지원하여 PHP를 컴파일하는 방법])', 'config-support-postgres' => '* $1은 MySQL의 대안으로 인기있는 오픈 소스 데이터베이스 시스템입니다. ([http://www.php.net/manual/en/pgsql.installation.php PostgreSQL을 지원하여 PHP를 컴파일하는 방법]) 몇가지 사소한 해결하지 못한 버그가 있을 수 있으며, 이를 제작 환경에서 사용하지 않는 것이 좋습니다.', 'config-support-sqlite' => '* $1는 매우 잘 지원하는 가벼운 데이터베이스 시스템입니다. ([http://www.php.net/manual/en/pdo.installation.php SQLite를 지원하여 PHP를 컴파일하는 방법], PDO 사용)', @@ -10527,7 +10707,7 @@ ASCII 글자 (a-z, A-Z), 숫자 (0-9), 밑줄 (_)과 하이픈 (-)만 사용하 'config-postgres-old' => 'PostgreSQL $1 이상이 필요하나 $2(이)가 있습니다.', 'config-sqlite-name-help' => '위키를 식별하기 위한 이름을 선택하세요. 공백이나 하이픈을 사용하지 마십시오. -이는 SQLite 데이터 파일 이름에 사용됩니다.', +SQLite 데이터 파일 이름에 사용됩니다.', 'config-sqlite-parent-unwritable-group' => '$1 데이터 디렉토리를 만들 수 없으며 $2 상위 디렉토리에 웹 서버에 의해 쓸 수 없기 때문입니다. 설치 마법사는 웹 서버로 실행중인 사용자를 결정할 수 없습니다. @@ -10554,7 +10734,7 @@ chmod a+w $3', 'config-sqlite-connection-error' => '$1. 호스트, 계정 이름과 비밀번호를 확인하고 다시 시도하세요.', - 'config-sqlite-readonly' => '파일 $1은 쓰기가 불가능합니다.', + 'config-sqlite-readonly' => '$1 파일은 쓰기가 불가능합니다.', 'config-sqlite-cant-create-db' => '$1 데이터베이스 파일을 만들 수 없습니다.', 'config-sqlite-fts3-downgrade' => 'PHP가 FTS3 지원이 없어졌습니다. 테이블을 다운그레이드하세요.', 'config-can-upgrade' => "이 데이터베이스에 미디어위키 테이블이 있습니다. @@ -10581,9 +10761,9 @@ chmod a+w $3', 'config-mysql-innodb' => 'InnoDB', 'config-mysql-myisam' => 'MyISAM', 'config-mysql-myisam-dep' => "'''경고''': 미디어위키와 함께 사용하도록 권장하지 않는 MySQL에 대한 스토리지 엔진으로 MyISAM을 선택하였습니다. 이유는: -* 이는 테이블이 잠겨있어 동시성을 거의 지원하지 않습니다 -* 이는 다른 엔진보다 손상이 더 자주 발생합니다. -* 미디어위키 바탕 코드가 항상 정상적으로 MyISAM을 처리하지 않습니다. +* 테이블이 잠겨있어 동시성을 거의 지원하지 않습니다 +* 다른 엔진보다 손상이 더 자주 발생합니다 +* 미디어위키 바탕 코드가 항상 정상적으로 MyISAM을 처리하지 않습니다 MySQL 설치가 InnoDB를 지원한다면 그 선택 대신에 InnoDB를 선택할 것을 매우 권장합니다. MySQL 설치가 InnoDB를 지원하지 않는다면 아마도 업그레이드를 해야 할 수도 있습니다.", @@ -10595,21 +10775,21 @@ MyISAM 데이터베이스는 InnoDB 데이터베이스보다 더 자주 손실 'config-mysql-binary' => '바이너리', 'config-mysql-utf8' => 'UTF-8', 'config-mysql-charset-help' => "'''바이너리 모드'''에서는 미디어위키는 바이너리 필드의 데이터베이스에 UTF-8 텍스트를 저장합니다. -이는 MySQL의 UTF-8 모드를 보다 더 효율적이고 유니코드 문자의 전체 범위를 사용할 수 있습니다. +MySQL의 UTF-8 모드를 보다 더 효율적이고 유니코드 문자의 전체 범위를 사용할 수 있습니다. '''UTF-8 모드'''에서는 MySQL은 데이터를 설정하는 어떤 문자열인지를 알 것이며, 표현하고 적절하게 그것을 변환할 수 있지만 [//en.wikipedia.org/wiki/Mapping_of_Unicode_character_planes 기본 다국어 범위] 상의 문자를 저장하지 못하게 될 수 있습니다.", - 'config-ibm_db2-low-db-pagesize' => "당신의 DB2 데이터베이스에 부족한 페이지 크기가 기본 테이블 공간에 있습니다. 페이지 크기는 '''32K''' 이상이어야 합니다.", + 'config-ibm_db2-low-db-pagesize' => "DB2 데이터베이스에 부족한 페이지 크기가 기본 테이블 공간에 있습니다. 페이지 크기는 '''32K''' 이상이어야 합니다.", 'config-site-name' => '위키 이름:', - 'config-site-name-help' => '이는 브라우저 제목 표시줄과 다른 여러 곳에 나타날 것입니다.', + 'config-site-name-help' => '브라우저 제목 표시줄과 다른 여러 곳에 나타납니다.', 'config-site-name-blank' => '사이트 이름을 입력하세요.', 'config-project-namespace' => '프로젝트 이름공간:', 'config-ns-generic' => '프로젝트', 'config-ns-site-name' => '위키 이름과 같은 이름: $1', 'config-ns-other' => '기타 (지정)', 'config-ns-other-default' => '내위키', - 'config-project-namespace-help' => '위키백과의 예를 따라서, 많은 위키는 "프로젝트 이름공간"에 그들의 콘텐츠 페이지에서 그들의 정책 페이지는 별도로 보관합니다. + 'config-project-namespace-help' => '위키백과의 예를 따라서, 많은 위키는 "\'\'\'프로젝트 이름공간\'\'\'"에 그들의 콘텐츠 페이지에서 그들의 정책 페이지는 별도로 보관합니다. 이 이름공간에 있는 모든 페이지의 제목은 여기서 지정할 수 있는 특정 접두어로 시작합니다. -보통 이 접두어는 위키의 이름에서 파생되지만, 이는 "#" 또는 ":"와 같은 특수 문자를 포함할 수 없습니다.', +보통 이 접두어는 위키의 이름에서 파생되지만, "#" 또는 ":"와 같은 특수 문자를 포함할 수 없습니다.', 'config-ns-invalid' => '특정 "$1" 이름공간이 잘못되었습니다. 다른 프로젝트 이름공간을 지정하세요.', 'config-ns-conflict' => '특정 "$1" 이름공간이 기본 미디어위키 이름공간과 충돌합니다. @@ -10619,7 +10799,7 @@ MyISAM 데이터베이스는 InnoDB 데이터베이스보다 더 자주 손실 'config-admin-password' => '비밀번호:', 'config-admin-password-confirm' => '비밀번호 확인:', 'config-admin-help' => '"홍길동"과 같이 여기에 원하는 사용자 이름을 입력하세요. -이는 위키에 로그인하는 데 사용되는 이름입니다.', +위키에 로그인하는 데 사용되는 이름입니다.', 'config-admin-name-blank' => '관리자의 사용자 이름을 입력하세요.', 'config-admin-name-invalid' => '특정 "$1" 사용자 이름이 잘못되었습니다. 다른 사용자 이름을 지정하세요.', @@ -10627,33 +10807,35 @@ MyISAM 데이터베이스는 InnoDB 데이터베이스보다 더 자주 손실 'config-admin-password-same' => '비밀번호는 사용자 이름과 같아서는 안 됩니다.', 'config-admin-password-mismatch' => '입력한 비밀번호 두 개가 일치하지 않습니다.', 'config-admin-email' => '이메일 주소:', - 'config-admin-email-help' => '위키의 다른 사용자로부터 이메일을 전달받거나 비밀번호를 재설정하고 주시문서 목록에 대한 변경 알림을 받기 위해 여기에 이메일 주소를 입력하세요. 이 필드를 비워 둘 수 있습니다.', + 'config-admin-email-help' => '위키의 다른 사용자로부터 이메일을 전달받거나 비밀번호를 재설정하고 주시문서 목록에 대한 바뀜 알림을 받기 위해 여기에 이메일 주소를 입력하세요. 이 필드를 비워 둘 수 있습니다.', 'config-admin-error-user' => '"$1" 이름의 관리자를 만드는 중 내부 오류가 발생했습니다.', 'config-admin-error-password' => '"$1" 관리자의 비밀번호를 설정하는 중 내부 오류가 발생했습니다:
    $2
    ', 'config-admin-error-bademail' => '이메일 주소를 잘못 입력하였습니다.', 'config-subscribe' => '[https://lists.wikimedia.org/mailman/listinfo/mediawiki-announce 배포 발표 메일링 리스트]에 가입합니다.', - 'config-subscribe-help' => '이는 중요한 보안 알림을 포함한 배포 알림에 대해 사용되는 로우 볼륨 메일링 리스트입니다. -당신이 이를 구독하고 나서 새 버전이 나올 때 미디어위키 설치를 업데이트해야합니다.', + 'config-subscribe-help' => '중요한 보안 알림을 포함한 배포 알림에 대해 사용되는 로우 볼륨 메일링 리스트입니다. +이 리스트를 구독하고 나서 새 버전이 나올 때 미디어위키 설치를 업데이트하십시오.', 'config-subscribe-noemail' => '이메일 주소를 제공하지 않고 배포 발표 메일링 리스트에 가입하려 합니다. 메일링 리스트에 가입하고자 할 경우 이메일 주소를 제공하세요.', - 'config-almost-done' => '거의 다 완료했습니다! 이제 남은 설정을 생략하고 지금 바로 위키를 설치할 수 있습니다.', + 'config-almost-done' => '거의 다 완료했습니다! +이제 남은 설정을 생략하고 지금 바로 위키를 설치할 수 있습니다.', 'config-optional-continue' => '더 많은 질문을 물어보세요.', 'config-optional-skip' => '지겨워요, 그냥 위키를 설치할래요.', 'config-profile' => '사용자 권한 프로필:', 'config-profile-wiki' => '평범한 위키', - 'config-profile-no-anon' => '계정 생성 필요', + 'config-profile-no-anon' => '계정 만들기 필요', 'config-profile-fishbowl' => '승인된 편집자만 이용 가능', 'config-profile-private' => '비공개 위키', - 'config-profile-help' => "위키는 당신이 가능한 한 많은 사람들이 편집하도록 할 때 최고로 적합합니다. -미디어위키에서는 최근 바뀜을 검토하고, 선하거나 악의적인 사용자에 의해 수행되는 모든 손실을 되돌리는 것이 쉽습니다. + 'config-profile-help' => "위키는 많은 사람들이 가능한 한 해당 위키를 편집할 때 가장 뛰어난 역할을 합니다. +미디어위키에서는 최근 바뀜을 검토하고, 선하거나 악의적인 사용자의 모든 손실을 되돌리는 것이 쉽습니다. -그러나 많은 사람들이 미디어위키가 다양한 역할의 유용하지만, 때로는 그것이 위키 방식의 장점을 모두 설득하기 쉽지 않음을 발견했습니다. +그러나 많은 사람들이 미디어위키가 다양한 역할로 유용하지만, 때로는 모든 사람에게 위키 방식의 장점을 모두 설득하기 쉽지 않을 지도 모릅니다. 그래서 선택할 수 있습니다. '''{{int:config-profile-wiki}}'''는 로그인하지 않고도 누구나 편집할 수 있습니다. -'''{{int:config-profile-no-anon}}'''는 추가적으로 필요한 책임을 제공하지만, 기존의 기여자를 망칠 수도 있습니다. +'''{{int:config-profile-no-anon}}'''는 각 편집에 추가적으로 강한 책임성을 제공하지만, 부담 없는 기여를 저해할 수도 있습니다. -'''{{int:config-profile-fishbowl}}''' 같은 경우는 승인된 사용자만 편집할 수 있지만, 대중은 역사를 포함하여 페이지를 볼 수 있습니다. '''{{int:config-profile-private}}'''는 승인된 사용자만 같은 그룹에서 편집할 수 있고 볼 수 있습니다. +'''{{int:config-profile-fishbowl}}''' 같은 경우는 승인된 사용자만 편집할 수 있지만, 대중은 역사를 포함하여 페이지를 볼 수 있습니다. +'''{{int:config-profile-private}}'''는 승인된 사용자만 같은 그룹에서 편집할 수 있고 볼 수 있습니다. 더 복잡한 사용자 권한을 설정하여 설치한 후 사용할 수 있도록 하려면 [//www.mediawiki.org/wiki/Manual:User_rights 관련 매뉴얼 항목]을 참고하세요.", 'config-license' => '저작권 및 라이선스:', @@ -10667,13 +10849,13 @@ MyISAM 데이터베이스는 InnoDB 데이터베이스보다 더 자주 손실 'config-license-cc-choose' => '다른 크리에이티브 커먼즈 라이선스 선택', 'config-license-help' => '많은 공개 위키는 모든 기여를 [http://freedomdefined.org/Definition 자유 라이선스] 하에 넣습니다. 이럴 경우 커뮤니티 소유권의 이해를 할 수 있도록 하고 장기적인 기여를 장려합니다. -이는 일반적으로 개인 또는 회사 위키에 대해서는 필요하지 않습니다. +일반적으로 개인 또는 회사 위키에 대해서는 필요하지 않습니다. 위키백과의 텍스트를 사용할 수 있도록 하고 위키백과가 위키에서 복사한 텍스트를 사용할 수 있도록 원한다면 크리에이티브 커먼즈 저작자표시-동일조건변경허락으로 선택해야 합니다. 위키백과는 이전에 GNU 자유 문서 사용 허가서를 사용했습니다. -GFDL은 유효한 라이선스이지만 이는 이해하기 어렵습니다. -이는 GFDL 하에 라이선스 내용을 재사용하는 것도 어렵습니다.', +GFDL은 유효한 라이선스이지만 이해하기 어렵습니다. +GFDL 하에 라이선스 내용을 재사용하는 것도 어렵습니다.', 'config-email-settings' => '이메일 설정', 'config-enable-email' => '발신 이메일 활성화', 'config-enable-email-help' => '이메일을 작동하려면 [http://www.php.net/manual/en/mail.configuration.php PHP의 메일 설정]을 올바르게 설정해야 합니다. @@ -10681,23 +10863,23 @@ GFDL은 유효한 라이선스이지만 이는 이해하기 어렵습니다. 'config-email-user' => '사용자와 사용자 간 이메일 활성화', 'config-email-user-help' => '환경 설정에서 활성화한 경우 모든 사용자가 이메일을 서로 보내도록 활성화합니다.', 'config-email-usertalk' => '사용자 토론 문서 알림 활성화', - 'config-email-usertalk-help' => '환경 설정에서 활성화한 경우 사용자는 사용자 토론 문서의 변경 알림을 받도록 활성화합니다.', + 'config-email-usertalk-help' => '환경 설정에서 활성화한 경우 사용자는 사용자 토론 문서의 바뀜 알림을 받도록 활성화합니다.', 'config-email-watchlist' => '주시문서 목록 알림 활성화', 'config-email-watchlist-help' => '환경 설정에서 활성화한 경우 사용자가 주시한 문서에 대한 알림을 받도록 활성화합니다.', 'config-email-auth' => '이메일 인증 활성화', - 'config-email-auth-help' => "이 설정이 활성화되어 있으면 사용자는 이메일 주소를 설정하거나 변경할 때마다 그들에게 보낸 링크를 사용하여 이메일 주소를 확인해야 합니다. -인증된 이메일 주소만 다른 사용자로부터의 이메일이나 변경 알림 이메일을 받을 수 있습니다. + 'config-email-auth-help' => "이 설정이 활성화되어 있으면 사용자는 이메일 주소를 설정하거나 바꿀 때마다 그들에게 보낸 링크를 사용하여 이메일 주소를 확인해야 합니다. +인증된 이메일 주소만 다른 사용자로부터의 이메일이나 바뀜 알림 이메일을 받을 수 있습니다. 이메일 기능의 남용 가능성이 있기 때문에 이 옵션을 설정하는 것은 공개 위키에서 '''권장'''합니다.", 'config-email-sender' => '반송 이메일 주소', 'config-email-sender-help' => '발신한 이메일에 대한 반송 주소로 사용할 이메일 주소를 입력하세요. -이는 반송할 때 보내는 주소입니다. +반송할 때 보내는 주소입니다. 대부분의 메일 서버는 적어도 도메인 이름 부분은 유효합니다.', 'config-upload-settings' => '그림과 파일 올리기', 'config-upload-enable' => '파일 올리기 활성화', 'config-upload-help' => '파일 올리기는 서버에 잠재적인 보안 위험에 쉽게 노출될 수 있습니다. 자세한 내용은 매뉴얼의 [//www.mediawiki.org/wiki/Manual:Security 보안 문단]을 읽어보세요. -파일 올리기를 활성화하려면 미디어위키의 루트 디렉토리에 있는 images 하위 디렉토리에서 웹 서버가 기록할 수 있도록 모드를 변경합니다. +파일 올리기를 활성화하려면 미디어위키의 루트 디렉토리에 있는 images 하위 디렉토리에서 웹 서버가 기록할 수 있도록 모드를 바꿉니다. 그 다음 이 옵션을 활성화합니다.', 'config-upload-deleted' => '삭제된 파일에 대한 디렉토리:', 'config-upload-deleted-help' => '삭제된 파일을 보관할 디렉토리를 선택하세요. @@ -10736,11 +10918,11 @@ GFDL은 유효한 라이선스이지만 이는 이해하기 어렵습니다. 'config-extensions' => '확장 기능', 'config-extensions-help' => '위에 나열된 확장 기능이 ./extensions에서 발견되었습니다. -이들은 추가적인 설정이 필요할 수 있습니다만 지금 활성화시킬 수 있습니다.', - 'config-install-alreadydone' => "'''경고:''' 당신은 이미 미디어위키를 설치하였고 다시 설치하려고 합니다. +추가적인 설정이 필요할 수 있습니다만 지금 활성화시킬 수 있습니다.', + 'config-install-alreadydone' => "'''경고:''' 이미 미디어위키를 설치했고 다시 설치하려고 합니다. 다음 페이지에서 진행하세요.", 'config-install-begin' => '"{{int:config-continue}}"을 누르면 미디어위키의 설치를 시작합니다. -그래도 변경하는 것을 원한다면 뒤로를 누릅니다.', +그래도 바꾸는 것을 원한다면 뒤로를 누릅니다.', 'config-install-step-done' => '완료', 'config-install-step-failed' => '실패', 'config-install-extensions' => '확장 기능을 포함하는 중', @@ -10766,15 +10948,15 @@ GFDL은 유효한 라이선스이지만 이는 이해하기 어렵습니다. 이를 만드는 것을 원하면 아래의 "계정 만들기" 확인 상자를 클릭하세요.', 'config-install-tables' => '테이블을 만드는 중', 'config-install-tables-exist' => "'''경고''': 미디어위키 테이블이 이미 있는 것 같습니다. -테이블 생성을 생략합니다.", - 'config-install-tables-failed' => "'''오류''': 다음 오류와 함께 테이블 생성에 실패했습니다: $1", +테이블 만들기를 생략합니다.", + 'config-install-tables-failed' => "'''오류''': 다음 오류와 함께 테이블 만들기에 실패했습니다: $1", 'config-install-interwiki' => '기본 인터위키 테이블을 채우는 중', 'config-install-interwiki-list' => 'interwiki.list 파일을 불러올 수 없습니다.', 'config-install-interwiki-exists' => "'''경고''': 인터위키 테이블이 이미 항목을 갖고 있는 것 같습니다. 기본 목록으로 넘어갑니다.", 'config-install-stats' => '통계를 초기화하는 중', 'config-install-keys' => '보안 키를 만드는 중', - 'config-insecure-keys' => "'''경고:''' 설치 중에 생성한 {{PLURAL:$2|보안 키}} ($1)를 설치하는 동안 완전히 안전하지 {{PLURAL:$2|않습니다}}. 직접 변경을 고려하세요.", + 'config-insecure-keys' => "'''경고:''' 설치 중에 생성한 {{PLURAL:$2|보안 키}} ($1)를 설치하는 동안 완전히 안전하지 {{PLURAL:$2|않습니다}}. 직접 바꾸기를 고려하세요.", 'config-install-sysop' => '관리자 사용자 계정을 만드는 중', 'config-install-subscribe-fail' => '미디어위키 발표를 구독할 수 없습니다: $1', 'config-install-subscribe-notpossible' => 'cURL이 설치되지 않았고 allow_url_fopen를 사용할 수 없습니다.', @@ -10785,9 +10967,9 @@ GFDL은 유효한 라이선스이지만 이는 이해하기 어렵습니다. 미디어위키가 성공적으로 설치되었습니다. 설치 마법사가 LocalSettings.php 파일을 만들었습니다. -이는 모든 설정이 포함되어 있습니다. +모든 설정이 포함되어 있습니다. -이를 다운로드하여 위키 설치의 거점에 넣어야 합니다 (index.php와 같은 디렉토리). 다운로드가 자동으로 시작됩니다. +파일을 다운로드하여 위키 설치의 거점에 넣어야 합니다. (index.php와 같은 디렉토리) 다운로드가 자동으로 시작됩니다. 다운로드가 제공되지 않을 경우나 그것을 취소한 경우에는 아래의 링크를 클릭하여 다운로드를 다시 시작할 수 있습니다: @@ -10798,7 +10980,7 @@ $3 완료되었으면 '''[$2 위키에 들어갈 수 있습니다]'''.", 'config-download-localsettings' => 'LocalSettings.php 다운로드', 'config-help' => '도움말', - 'config-nofile' => '파일 "$1"(을)를 찾을 수 없습니다. 이미 삭제되었나요?', + 'config-nofile' => '"$1" 파일을 찾을 수 없습니다. 이미 삭제되었나요?', 'mainpagetext' => "'''미디어위키가 성공적으로 설치되었습니다.'''", 'mainpagedocfooter' => '[//meta.wikimedia.org/wiki/Help:Contents 이곳]에서 위키 프로그램에 대한 정보를 얻을 수 있습니다. @@ -10809,7 +10991,7 @@ $3 * [https://lists.wikimedia.org/mailman/listinfo/mediawiki-announce 미디어위키 발표 메일링 리스트]', ); -/** Karachay-Balkar (Къарачай-Малкъар) +/** Karachay-Balkar (къарачай-малкъар) * @author Iltever */ $messages['krc'] = array( @@ -10858,13 +11040,13 @@ Dat kanns De verlängere, endämm dat De de session.gc_maxlifeti Don dat Projramm för et Opsäze norr_ens aanschmiiße.', 'config-no-session' => 'De Daate för Ding Setzung sinn verschött jejange. Donn en dä Dattei php.ini nohloore, ov dä session.save_path op e zopaß Verzeijschneß zeisch.', - 'config-your-language' => 'Ding Shprooch:', + 'config-your-language' => 'Ding Schprooch:', 'config-your-language-help' => 'Donn heh di Shprooch ußsöhke, di dat Enshtallzjuhnsprojramm kalle sull.', 'config-wiki-language' => 'Dem Wiki sing Shprooch:', 'config-wiki-language-help' => 'Donn heh di Shprooch ußsöhke, di et Wiki shtandattmääßesch kalle sull.', 'config-back' => '← Retuur', 'config-continue' => 'Wigger →', - 'config-page-language' => 'Shprooch', + 'config-page-language' => 'Schprooch', 'config-page-welcome' => 'Wellkumme beim MediaWiki!', 'config-page-dbconnect' => 'Met dä Daatebangk Verbenge', 'config-page-upgrade' => 'En Inshtallzjuhn op der neuste Shtand bränge', @@ -11383,7 +11565,7 @@ Dat es och all op Änglesch: * [https://lists.wikimedia.org/mailman/listinfo/mediawiki-announce MediaWiki release mailing list]', ); -/** Kurdish (Latin script) (‪Kurdî (latînî)‬) +/** Kurdish (Latin script) (Kurdî (latînî)‎) * @author George Animal */ $messages['ku-latn'] = array( @@ -11394,6 +11576,7 @@ $messages['ku-latn'] = array( 'config-page-options' => 'Vebijêrk', 'config-ns-generic' => 'Proje', 'config-install-step-done' => 'çêbû', + 'config-help' => 'alîkarî', 'mainpagetext' => "'''MediaWiki serketî hate çêkirin.'''", 'mainpagedocfooter' => 'Alîkarî ji bo bikaranîn û guherandin yê datayê Wîkî tu di bin [//meta.wikimedia.org/wiki/Help:Contents pirtûka alîkarîyê ji bikarhêneran] da dikarê bibînê. @@ -11429,6 +11612,9 @@ $messages['lb'] = array( Dir fannt en am LocalSettings.php.", 'config-localsettings-key' => 'Aktualisatiounsschlëssel:', 'config-localsettings-badkey' => 'De Schlëssel deen Dir aginn hutt ass net korrekt', + 'config-localsettings-incomplete' => 'De Fichier LocalSettings.php schéngt net komplett ze sinn. +D\'Variabel $1 ass net definéiert. +Ännert w.e.g. de Fichier LocalSettings.php esou datt déi Variabel definéiert ass a klickt op "Virufueren".', 'config-session-error' => 'Feeler beim Starte vun der Sessioun: $1', 'config-no-session' => "D'Donnéeë vun ärer Sessioun si verluergaangen! Kuckt Är php.ini no a vergewëssert Iech datt session.save_path op adequate REpertoire agestallt ass.", @@ -11529,6 +11715,7 @@ Wann et de Kont net gëtt, a wann den Installatiouns-Kont genuch Rechter huet, g 'config-header-ibm_db2' => 'IBM DB2-Astellungen', 'config-invalid-db-type' => 'Net valabelen Datebank-Typ', 'config-missing-db-name' => 'Dir musst en Numm fir de Wäert "Numm vun der Datebank" uginn', + 'config-missing-db-host' => 'Dir musst e Wäert fir "Database host" uginn', 'config-missing-db-server-oracle' => 'Dir musst e Wäert fir "Datebank-TNS" uginn', 'config-db-sys-user-exists-oracle' => 'De Benotzerkont "$1" gëtt et schonn. SYSDBA kann nëmme benotzt gi fir en neie Benotzerkont opzemaachen.', 'config-postgres-old' => 'PostgreSQL $1 oder eng méi nei Versioun gëtt gebraucht, Dir hutt $2.', @@ -11615,6 +11802,7 @@ Dir kënnt elo déi Astellungen déi nach iwwreg sinn iwwersprangen an d'Wiki el 'config-install-stats' => 'Initialisatioun vun de Statistiken', 'config-install-keys' => 'Generéiere vum Geheimschlëssel', 'config-install-sysop' => 'Administrateur Benotzerkont gëtt ugeluecht', + 'config-install-extension-tables' => "D'Tabelle fir déi aktivéiert Erweiderunge ginn ugeluecht", 'config-install-mainpage-failed' => "D'Haaptsäit konnt net dragesat ginn: $1", 'config-download-localsettings' => 'LocalSettings.php eroflueden', 'config-help' => 'Hëllef', @@ -11628,7 +11816,8 @@ Dir kënnt elo déi Astellungen déi nach iwwreg sinn iwwersprangen an d'Wiki el * [https://lists.wikimedia.org/mailman/listinfo/mediawiki-announce Mailinglëscht vun neie MediaWiki-Versiounen]", ); -/** Lingua Franca Nova (Lingua Franca Nova) */ +/** Lingua Franca Nova (Lingua Franca Nova) + */ $messages['lfn'] = array( 'mainpagetext' => "'''MediaWiki es aora instalada.'''", 'mainpagedocfooter' => 'Atenda la [//meta.wikimedia.org/wiki/Help:Contents Gida per Usores] per informa supra la usa de la programa de vici. @@ -11653,7 +11842,8 @@ $messages['lg'] = array( * [https://lists.wikimedia.org/mailman/listinfo/mediawiki-announce Wewandise ofunenga amawulire aga email ag'ebifa ku MediaWiki]", ); -/** Limburgish (Limburgs) */ +/** Limburgish (Limburgs) + */ $messages['li'] = array( 'mainpagetext' => "'''MediaWiki software succesvol geïnsjtalleerd.'''", 'mainpagedocfooter' => "Raodpleeg de [//meta.wikimedia.org/wiki/NL_Help:Inhoudsopgave handjleiding] veur informatie euver 't gebroek van de wikisoftware. @@ -11665,12 +11855,14 @@ $messages['li'] = array( * [https://lists.wikimedia.org/mailman/listinfo/mediawiki-announce MediaWiki mailinglies veur nuuj versies]", ); -/** Lao (ລາວ) */ +/** Lao (ລາວ) + */ $messages['lo'] = array( 'mainpagetext' => "'''ຕິດຕັ້ງມີເດຍວິກິນີ້ສຳເລັດແລ້ວ.'''", ); -/** Lithuanian (lietuvių) */ +/** Lithuanian (lietuvių) + */ $messages['lt'] = array( 'mainpagetext' => "'''MediaWiki sėkmingai įdiegta.'''", 'mainpagedocfooter' => 'Informacijos apie wiki programinės įrangos naudojimą, ieškokite [//meta.wikimedia.org/wiki/Help:Contents žinyne]. @@ -11709,7 +11901,8 @@ $messages['lv'] = array( * [https://lists.wikimedia.org/mailman/listinfo/mediawiki-announce Parakstīties uz paziņojumiem par jaunām MediaWiki versijām]', ); -/** Literary Chinese (文言) */ +/** Literary Chinese (文言) + */ $messages['lzh'] = array( 'mainpagetext' => "'''共筆臺已立'''", 'mainpagedocfooter' => "欲識維基,見[//meta.wikimedia.org/wiki/Help:Contents User's Guide] @@ -11747,7 +11940,8 @@ $messages['mai'] = array( * [https://lists.wikimedia.org/mailman/listinfo/mediawiki-announce MediaWiki release mailing list]", ); -/** Moksha (Мокшень) */ +/** Moksha (мокшень) + */ $messages['mdf'] = array( 'mainpagetext' => "'''МедиаВикить арафтозь лац.'''", 'mainpagedocfooter' => 'Ванк [//meta.wikimedia.org/wiki/Help:Contents Ветямовал Тиинди] тяса ули кода содамс Вики програпнень эрявикснень колга. @@ -11817,7 +12011,8 @@ $messages['mg'] = array( * [https://lists.wikimedia.org/mailman/listinfo/mediawiki-announce Resaka momba ny fizaràn'ny MediaWiki]", ); -/** Eastern Mari (Олык Марий) */ +/** Eastern Mari (олык марий) + */ $messages['mhr'] = array( 'mainpagetext' => "'''MediaWiki сай шындыме.'''", ); @@ -12393,7 +12588,7 @@ $messages['ml'] = array( 'config-information' => 'വിവരങ്ങൾ', 'config-localsettings-upgrade' => "'''അറിയിപ്പ്''': ഒരു LocalSettings.php ഫയൽ കാണുന്നു. സോഫ്റ്റ്‌വേർ അപ്‌ഗ്രേഡ് ചെയ്യുക സാദ്ധ്യമാണ്. -ദയവായി പെട്ടിയിൽ \$wgUpgradeKey എന്നതിന്റെ വില നൽകുക.", +ദയവായി പെട്ടിയിൽ \$wgUpgradeKey എന്നതിന്റെ വില നൽകുക.", # Fuzzy 'config-localsettings-key' => 'അപ്‌ഗ്രേഡ് ചാവി:', 'config-localsettings-badkey' => 'താങ്കൾ നൽകിയ ചാവി തെറ്റാണ്', 'config-session-error' => 'സെഷൻ തുടങ്ങുന്നതിൽ പിഴവ്: $1', @@ -12422,9 +12617,9 @@ $messages['ml'] = array( 'config-sidebar' => '* [//www.mediawiki.org മീഡിയവിക്കി പ്രധാനതാൾ] * [//www.mediawiki.org/wiki/Help:Contents ഉപയോക്തൃസഹായി] * [//www.mediawiki.org/wiki/Manual:Contents കാര്യനിർവഹണസഹായി] -* [//www.mediawiki.org/wiki/Manual:FAQ പതിവുചോദ്യങ്ങൾ]', +* [//www.mediawiki.org/wiki/Manual:FAQ പതിവുചോദ്യങ്ങൾ]', # Fuzzy 'config-env-php' => 'പി.എച്ച്.പി. $1 ഇൻസ്റ്റോൾ ചെയ്തിട്ടുണ്ട്.', - 'config-no-db' => 'അനുയോജ്യമായ ഡേറ്റാബേസ് ഡ്രൈവർ കണ്ടെത്താനായില്ല!', + 'config-no-db' => 'അനുയോജ്യമായ ഡേറ്റാബേസ് ഡ്രൈവർ കണ്ടെത്താനായില്ല!', # Fuzzy 'config-memory-raised' => 'പി.എച്ച്.പി.യുടെ memory_limit $1 ആണ്, $2 ആയി ഉയർത്തിയിരിക്കുന്നു.', 'config-memory-bad' => "'''മുന്നറിയിപ്പ്:''' പി.എച്ച്.പി.യുടെ memory_limit $1 ആണ്. ഇത് മിക്കവാറും വളരെ കുറവാണ്. @@ -12506,7 +12701,7 @@ $1 'config-logo-help' => 'മീഡിയവിക്കിയിൽ സ്വതേയുള്ള ദൃശ്യരൂപത്തിൽ 135x160 പിക്സലുള്ള ലോഗോ മുകളിൽ ഇടത് മൂലയിൽ കാണാം. അനുയോജ്യമായ വലിപ്പമുള്ള ഒരു ചിത്രം അപ്‌ലോഡ് ചെയ്തിട്ട്, അതിന്റെ യൂ.ആർ.എൽ. ഇവിടെ നൽകുക. -താങ്കൾക്ക് ലോഗോ ആവശ്യമില്ലെങ്കിൽ, ഈ പെട്ടി ശൂന്യമായിടുക.', +താങ്കൾക്ക് ലോഗോ ആവശ്യമില്ലെങ്കിൽ, ഈ പെട്ടി ശൂന്യമായിടുക.', # Fuzzy 'config-cc-again' => 'ഒന്നുകൂടി എടുക്കൂ...', 'config-advanced-settings' => 'വിപുലീകൃത ക്രമീകരണങ്ങൾ', 'config-extensions' => 'അനുബന്ധങ്ങൾ', @@ -12553,7 +12748,8 @@ $messages['mn'] = array( * [https://lists.wikimedia.org/mailman/listinfo/mediawiki-announce МедиаВикигийн мэдээний мэйл явуулах жагсаалт]', ); -/** Marathi (मराठी) */ +/** Marathi (मराठी) + */ $messages['mr'] = array( 'mainpagetext' => "'''मीडियाविकीचे इन्स्टॉलेशन पूर्ण.'''", 'mainpagedocfooter' => 'विकी सॉफ्टवेअर वापरण्याकरिता [//meta.wikimedia.org/wiki/Help:Contents यूजर गाईड] पहा. @@ -12656,7 +12852,7 @@ $messages['my'] = array( 'mainpagetext' => "'''မီဒီယာဝီကီကို အောင်မြင်စွာ သွင်းပြီးပါပြီ။'''", ); -/** Erzya (Эрзянь) +/** Erzya (эрзянь) * @author Botuzhaleny-sodamo */ $messages['myv'] = array( @@ -12678,7 +12874,8 @@ $messages['mzn'] = array( 'config-help' => 'راهنما', ); -/** Nahuatl (Nāhuatl) */ +/** Nahuatl (Nāhuatl) + */ $messages['nah'] = array( 'mainpagetext' => "'''MediaHuiqui cualli ōmotlahtlāli.'''", ); @@ -12696,7 +12893,7 @@ $messages['nan'] = array( * [https://lists.wikimedia.org/mailman/listinfo/mediawiki-announce MediaWiki的公布列單]', ); -/** Norwegian Bokmål (‪norsk (bokmål)‬) +/** Norwegian Bokmål (norsk (bokmål)‎) * @author Event * @author Nghtwlkr */ @@ -12741,7 +12938,7 @@ Sjekk din php.ini og sørg for at session.save_path er satt til en 'config-page-dbsettings' => 'Databaseinnstillinger', 'config-page-name' => 'Navn', 'config-page-options' => 'Valg', - 'config-page-install' => 'Innstaller', + 'config-page-install' => 'Installer', 'config-page-complete' => 'Ferdig!', 'config-page-restart' => 'Start installasjonen på nytt', 'config-page-readme' => 'Les meg', @@ -13090,7 +13287,7 @@ Mer komplekse konfigurasjoner av brukerrettigheter er tilgjengelig etter install 'config-license-cc-by-sa' => 'Creative Commons Navngivelse Del på samme vilkår', 'config-license-cc-by' => 'Creative Commons Attribution', 'config-license-cc-by-nc-sa' => 'Creative Commons Navngivelse Ikke-kommersiell Del på samme vilkår', - 'config-license-cc-0' => 'Creative Commons Zero', + 'config-license-cc-0' => 'Creative Commons Zero', # Fuzzy 'config-license-pd' => 'Offentlig rom', 'config-license-cc-choose' => 'Velg en egendefinert Creative Commons-lisens', 'config-email-settings' => 'E-postinnstillinger', @@ -13125,7 +13322,7 @@ Ideelt burde ikke denne være tilgjengelig for nettet.', 'config-logo-help' => 'MediaWikis standarddrakt inkluderer plass til en 135x160 pikslers logo i øvre venstre hjørne. Last opp et bilde i passende størrelse og skriv inn nettadressen her. -Hvis du ikke ønsker en logo, la denne boksen være tom.', +Hvis du ikke ønsker en logo, la denne boksen være tom.', # Fuzzy 'config-instantcommons' => 'Aktiver Instant Commons', 'config-instantcommons-help' => '[//www.mediawiki.org/wiki/InstantCommons Instant Commons] er en funksjon som gjør det mulig for wikier å bruke bilder, lyder og andre media funnet på nettstedet [//commons.wikimedia.org/ Wikimedia Commons]. For å gjøre dette krever MediaWiki tilgang til internett. @@ -13157,7 +13354,8 @@ For mer informasjon om denne funksjonen, inklusive instruksjoner om hvordan man *[https://lists.wikimedia.org/mailman/listinfo/mediawiki-announce MediaWiki e-postliste]', ); -/** Low German (Plattdüütsch) */ +/** Low German (Plattdüütsch) + */ $messages['nds'] = array( 'mainpagetext' => "'''De MediaWiki-Software is mit Spood installeert worrn.'''", 'mainpagedocfooter' => 'Kiek de [//meta.wikimedia.org/wiki/MediaWiki_localisation Dokumentatschoon för dat Anpassen vun de Brukerböversiet] @@ -13752,7 +13950,7 @@ Na het plaatsen van het bestand met instellingen kunt u '''[$2 uw wiki betreden] * [https://lists.wikimedia.org/mailman/listinfo/mediawiki-announce Mailinglijst voor aankondigingen van nieuwe versies]', ); -/** Norwegian Nynorsk (‪norsk (nynorsk)‬) +/** Norwegian Nynorsk (norsk (nynorsk)‎) * @author Harald Khan * @author Nghtwlkr */ @@ -13785,9 +13983,9 @@ Installasjonen kan mislukkast!", 'config-header-oracle' => 'Oracle-innstillingar', 'config-invalid-db-type' => 'Ugyldig databasetype', 'config-invalid-db-name' => 'Ugyldig databasenamn «$1». -Berre bruk ASCII-bokstavar (a-z, A-Z), tal (0-9) og undestrekar (_).', +Berre bruk ASCII-bokstavar (a-z, A-Z), tal (0-9) og undestrekar (_).', # Fuzzy 'config-invalid-db-prefix' => 'Ugyldig databaseprefiks «$1». -Berre bruk ASCII-bokstavar (a-z, A-Z), tal (0-9) og undestrekar (_).', +Berre bruk ASCII-bokstavar (a-z, A-Z), tal (0-9) og undestrekar (_).', # Fuzzy 'config-invalid-schema' => 'Ugyldig skjema for MediaWiki «$1». Berre bruk ASCII-bokstavar (a-z, A-Z), tal (0-9) og undestrekar (_).', 'config-postgres-old' => 'PostgreSQL $1 eller seinare krevst, du har $2.', @@ -13807,7 +14005,8 @@ $messages['no'] = array( 'mainpagetext' => "'''MediaWiki-programvaren er nå installert.'''", ); -/** Occitan (occitan) */ +/** Occitan (occitan) + */ $messages['oc'] = array( 'mainpagetext' => "'''MediaWiki es estat installat amb succès.'''", 'mainpagedocfooter' => "Consultatz lo [//meta.wikimedia.org/wiki/Ajuda:Contengut Guida de l'utilizaire] per mai d'entresenhas sus l'utilizacion d'aqueste logicial. @@ -13839,12 +14038,14 @@ $messages['os'] = array( 'mainpagetext' => "'''Вики-скрипт «MediaWiki» æнтыстджынæй æвæрд æрцыд.'''", ); -/** Punjabi (ਪੰਜਾਬੀ) */ +/** Punjabi (ਪੰਜਾਬੀ) + */ $messages['pa'] = array( 'mainpagetext' => "'''ਮੀਡਿਆਵਿਕਿ ਠੀਕ ਤਰ੍ਹਾਂ ਇੰਸਟਾਲ ਹੋ ਗਿਆ ਹੈ।'''", ); -/** Pampanga (Kapampangan) */ +/** Pampanga (Kapampangan) + */ $messages['pam'] = array( 'mainpagetext' => "'''Melaus ing pamipalyari ning MediaWiki.'''", 'mainpagedocfooter' => "Basan me ing [//meta.wikimedia.org/wiki/Help:Contents User's Guide] para king impormasiun keng pamangamit ning wiki software. @@ -13855,7 +14056,8 @@ $messages['pam'] = array( * [https://lists.wikimedia.org/mailman/listinfo/mediawiki-announce MediaWiki release mailing list]", ); -/** Picard (Picard) */ +/** Picard (Picard) + */ $messages['pcd'] = array( 'mainpagetext' => "'''MediaWiki o té instalé aveuc victoère.'''", ); @@ -14501,7 +14703,7 @@ It peule pa instalé MediaWiki.", S'a gestiss un sit a àut tràfich, a dovrìa lese cheicòs an sla [//www.mediawiki.org/wiki/Unicode_normalization_considerations normalisassion Unicode].", 'config-unicode-update-warning' => "'''Avis:''' La version instalà dlë spassiador ëd normalisassion Unicode a deuvra na version veja ëd la librarìa dël [http://site.icu-project.org/ proget ICU]. A dovrìa fé n'[//www.mediawiki.org/wiki/Unicode_normalization_considerations agiornament] s'a l'é anteressà a dovré Unicode.", - 'config-no-db' => 'Impossìbil tové un pilòta ëd base ëd dàit bon!', + 'config-no-db' => 'Impossìbil tové un pilòta ëd base ëd dàit bon!', # Fuzzy 'config-no-fts3' => "'''Avis''': SQLite a l'é compilà sensa ël mòdul [//sqlite.org/fts3.html FTS3], le funsion d'arserca a saran pa disponìbij su cost motor.", 'config-register-globals' => "'''Avis: L'opsion [http://php.net/register_globals register_globals] ëd PHP a l'é abilità.''' '''Ch'a la disabìlita s'a peul.''' @@ -14550,7 +14752,7 @@ Bele che MediaWiki a contròla j'aspet ëd sicurëssa ëd tùit j'archivi carià S'a deuvra n'ospitalità partagià, sò fornidor d'ospitalità a dovrìa deje ël nòm dl'ospitant giust ant soa documentassion. -Se a anstala su un servent Windows e a deuvra MySQL, dovré \"localhost\" a podrìa funsioné nen com nòm dël servent. S'a marcia nen, ch'a preuva \"127.0.0.1\" com adrëssa IP local.", +Se a anstala su un servent Windows e a deuvra MySQL, dovré \"localhost\" a podrìa funsioné nen com nòm dël servent. S'a marcia nen, ch'a preuva \"127.0.0.1\" com adrëssa IP local.", # Fuzzy 'config-db-host-oracle' => 'TNS dla base ëd dàit:', 'config-db-host-oracle-help' => "Anserì un [http://download.oracle.com/docs/cd/B28359_01/network.111/b28317/tnsnames.htm nòm ëd conession local] bon; n'archivi tnsnames.ora a dev esse visìbil da costa anstalassion..
    S'a deuvra le librarìe cliente 10g o pi neuve a peul ëdcò dovré ël métod ëd nominassion [http://download.oracle.com/docs/cd/E11882_01/network.112/e10836/naming.htm Easy Connect].", 'config-db-wiki-settings' => 'Identìfica sta wiki', @@ -14558,7 +14760,7 @@ Se a anstala su un servent Windows e a deuvra MySQL, dovré \"localhost\" a podr 'config-db-name-help' => "Ch'a serna un nòm ch'a identìfica soa wiki. A dovrìa conten-e gnun ëspassi o tratin. -S'a deuvra n'ospitalità partagià, sò fornidor ëd l'ospitalità a-j darà un nòm ëd base ëd dàit specìfich da dovré, o a lassrà ch'a lo crea via un panel ëd contròl.", +S'a deuvra n'ospitalità partagià, sò fornidor ëd l'ospitalità a-j darà un nòm ëd base ëd dàit specìfich da dovré, o a lassrà ch'a lo crea via un panel ëd contròl.", # Fuzzy 'config-db-name-oracle' => 'Schema dla base ëd dàit:', 'config-db-install-account' => "Cont d'utent për l'instalassion.", 'config-db-username' => "Nòm d'utent dla base ëd dàit:", @@ -14572,7 +14774,7 @@ S'ël cont a esist pa, e ël cont d'instalassion a l'ha ij privilegi ch'a-i van, 'config-db-prefix-help' => "S'a l'ha dabzògn ëd partagé na base ëd dàit an tra vàire wiki, o tra MediaWiki e n'àutra aplicassion dl'aragnà, a peul serne ëd gionté un prefiss a tùit ij nòm ëd le tàule për evité ëd conflit. Ch'a deuvra ni dë spassi ni ëd tratin. -Cost camp a l'é lassà normalment veuid.", +Cost camp a l'é lassà normalment veuid.", # Fuzzy 'config-db-charset' => 'Ansema dij caràter dla base ëd dàit', 'config-charset-mysql5-binary' => 'MySQL 4.1/5.0 binari', 'config-charset-mysql5' => 'MySQL 4.1/5.0 UTF-8', @@ -14586,7 +14788,7 @@ An '''manera UTF-8''', MySQL a arconòss an che ansema ëd caràter a son ij sò 'config-db-port' => 'Porta dla base ëd dàit:', 'config-db-schema' => 'Schema për MediaWiki', 'config-db-schema-help' => "Jë schema sì-dzora a son normalment giust. -Ch'a-j cangia mach s'a sa ch'a n'ha da manca.", +Ch'a-j cangia mach s'a sa ch'a n'ha da manca.", # Fuzzy 'config-sqlite-dir' => 'Dossié dij dat SQLite:', 'config-sqlite-dir-help' => "SQLite a memorisa tùit ij dat ant n'archivi ùnich. @@ -14606,7 +14808,7 @@ $1 S'a vëd pa listà sì-sota ël sistema ëd base ëd dàit ch'a preuva a dovré, antlora va andaré a j'istrussion dl'anliura sì-dzora për abilité ël manteniment.", 'config-support-mysql' => "* $1 e l'é l'obietiv primari për MediaWiki e a l'é mej mantnù ([http://www.php.net/manual/en/mysql.installation.php com compilé PHP con ël manteniment MySQL])", - 'config-support-postgres' => "* $1 e l'é un sistema ëd base ëd dàit popolar a sorgiss duverta com alternativa a MySQL ([http://www.php.net/manual/en/pgsql.installation.php com compilé PHP con ël manteniment ëd PostgreSQL])", + 'config-support-postgres' => "* $1 e l'é un sistema ëd base ëd dàit popolar a sorgiss duverta com alternativa a MySQL ([http://www.php.net/manual/en/pgsql.installation.php com compilé PHP con ël manteniment ëd PostgreSQL])", # Fuzzy 'config-support-sqlite' => "* $1 e l'é un sistema ëd base ëd dàit leger che a l'é motobin bin mantnù ([http://www.php.net/manual/en/pdo.installation.php com compilé PHP con ël manteniment ëd SQLite], a deuvra PDO)", 'config-support-oracle' => "* $1 a l'é na base ëd dàit comersial për j'amprèise. ([http://www.php.net/manual/en/oci8.installation.php Com compilé PHP con ël manteniment OCI8])", 'config-header-mysql' => 'Ampostassion MySQL', @@ -14619,9 +14821,9 @@ S'a vëd pa listà sì-sota ël sistema ëd base ëd dàit ch'a preuva a dovré, 'config-invalid-db-server-oracle' => 'TNS ëd la base ëd dat pa bon "$1". Dovré mach dle litre ASCII (a-z, A-Z), nùmer (0-9), sotlignadure (_) e pontin (.).', 'config-invalid-db-name' => 'Nòm ëd la base ëd dàit pa bon "$1". -Dovré mach litre ASCII (a-z, A-Z), nùmer (0-9) e sotlignadure (_).', +Dovré mach litre ASCII (a-z, A-Z), nùmer (0-9) e sotlignadure (_).', # Fuzzy 'config-invalid-db-prefix' => 'Prefiss dla base ëd dàit pa bon "$1". -Dovré mach litre ASCII (a-z, A-Z), nùmer (0-9) e sotlignadure (_).', +Dovré mach litre ASCII (a-z, A-Z), nùmer (0-9) e sotlignadure (_).', # Fuzzy 'config-connection-error' => "$1. Controla l'ospitant, lë stranòm d'utent e la ciav sì-sota e prové torna.", @@ -14715,7 +14917,7 @@ Specìfica un nòm utent diferent.', 'config-admin-password-same' => "La ciav a dev nen esse l'istessa ëd lë stranòm d'utent.", 'config-admin-password-mismatch' => "Le doe ciav che a l'ha scrivù a son diferente antra 'd lor.", 'config-admin-email' => 'Adrëssa ëd pòsta eletrònica:', - 'config-admin-email-help' => "Ch'a anserissa ambelessì n'adrëssa ëd pòsta eletrònica për përmëtt-je d'arsèive ëd mëssagi da d'àutri utent an sla wiki, riamposté soa ciav, e esse anformà ëd camgiament a le pàgine ch'a ten sot-euj.", + 'config-admin-email-help' => "Ch'a anserissa ambelessì n'adrëssa ëd pòsta eletrònica për përmëtt-je d'arsèive ëd mëssagi da d'àutri utent an sla wiki, riamposté soa ciav, e esse anformà ëd camgiament a le pàgine ch'a ten sot-euj.", # Fuzzy 'config-admin-error-user' => 'Eror antern an creand n\'aministrator con lë stranòm "$1".', 'config-admin-error-password' => 'Eror antern an ampostand na ciav për l\'admin "$1":
    $2
    ', 'config-subscribe' => "Ch'a sot-scriva la [https://lists.wikimedia.org/mailman/listinfo/mediawiki-announce lista ëd discussion ëd j'anonsi ëd publicassion].", @@ -14755,7 +14957,7 @@ A l'é generalment nen necessari për na wiki privà o d'asienda. S'a veul podèj dovré dij test da Wikipedia, e a veul che Wikipedia a aceta dij test copià da soa wiki, a dovrìa serne '''Creative Commons Attribution Share Alike'''. La GNU Free Documentation License a l'era la veja licensa dont sota a-i era Wikipedia. -A l'é anco' na licensa bon-a, an tùit ij cas, sta licensa a l'ha chèich funsion ch'a rendo difìcij l'utilisassion e l'antërpretassion.", +A l'é anco' na licensa bon-a, an tùit ij cas, sta licensa a l'ha chèich funsion ch'a rendo difìcij l'utilisassion e l'antërpretassion.", # Fuzzy 'config-email-settings' => 'Ampostassion ëd pòsta eletrònica', 'config-enable-email' => 'Abilité ij mëssagi ëd pòsta eletrònica an surtìa', 'config-enable-email-help' => "S'a veul che la pòsta eletrònica a marcia, j'[http://www.php.net/manual/en/mail.configuration.php ampostassion ëd pòsta eletrònica PHP] a devo esse configurà për da bin. @@ -14788,7 +14990,7 @@ Idealment, sòn a dovrìa pa esse acessìbil an sl'aragnà.", 'config-logo-help' => "La pel dë stàndard ëd MediaWiki a comprend lë spassi për na marca ëd 135x160 pontin ant ël canton an àut a snista. Ch'a dëscaria na figura ëd la dimension aproprià, e ch'a anserissa l'anliura ambelessì. -S'a veul gnun-e marche, ch'a lassa ës camp bianch.", +S'a veul gnun-e marche, ch'a lassa ës camp bianch.", # Fuzzy 'config-instantcommons' => 'Abìlita Instant Commons', 'config-instantcommons-help' => "[//www.mediawiki.org/wiki/InstantCommons Instant Commons] a l'é na funsion ch'a përmët a le wiki ëd dovré dle figure, dij son e d'àutri mojen trovà an sël sit [//commons.wikimedia.org/ Wikimedia Commons]. Për dovré sossì, MediaWiki a l'ha da manca dl'acess a la ragnà. @@ -14807,7 +15009,7 @@ Ij sit da mesan a gròss a son motobin ancoragià a abilité sòn, e ij sit cit 'config-cache-memcached' => "Dovré Memcached (a ciama n'ampostassion e na configurassion adissionaj)", 'config-memcached-servers' => 'Servent Memcached:', 'config-memcached-help' => "Lista d'adrësse IP da dovré për Memcached. -A dovrìa esse separà con dle vìrgole e specifiché la pòrta da dovré (për esempi: 127.0.0.1:11211, 192.168.1.25:11211).", +A dovrìa esse separà con dle vìrgole e specifiché la pòrta da dovré (për esempi: 127.0.0.1:11211, 192.168.1.25:11211).", # Fuzzy 'config-extensions' => 'Estension', 'config-extensions-help' => "J'estension listà dì-sota a son ëstàite trovà ant sò dossié ./extensions. @@ -14830,7 +15032,7 @@ Sauté la creassion.", 'config-install-interwiki-list' => "As peul pa trovesse l'archivi interwiki.list.", 'config-install-interwiki-exists' => "'''Avis''': La tàula interwiki a smija ch'a l'abia già dj'element. Për stàndard, la lista a sarà sautà.", - 'config-install-keys' => 'Generassion ëd la ciav segreta', + 'config-install-keys' => 'Generassion ëd la ciav segreta', # Fuzzy 'config-install-sysop' => "Creassion dël cont ëd l'utent aministrator", 'config-install-done' => "'''Congratulassion!''' A l'ha instalà për da bin mediaWiki. @@ -14841,7 +15043,7 @@ A conten tuta soa configurassion. A dovrà [$1 dëscarielo] e butelo ant la bas ëd l'instalassion ëd soa wiki (ël midem dossié d'index.php). '''Nòta''': S'a lo fa nen adess, cost archivi ëd configurassion generà a sarà pa disponìbil për chiel pi tard s'a chita l'instalassion sensa dëscarielo. -Quand che a l'é stàit fàit, a peul '''[$2 intré an soa wiki]'''.", +Quand che a l'é stàit fàit, a peul '''[$2 intré an soa wiki]'''.", # Fuzzy 'config-help' => 'agiut', 'mainpagetext' => "'''MediaWiki a l'é staita anstalà a la përfession.'''", 'mainpagedocfooter' => "Che a varda la [//meta.wikimedia.org/wiki/Help:Contents User's Guide] për avèj dj'anformassion ant sël coma dovré ël programa dla wiki. @@ -14909,8 +15111,11 @@ $messages['ps'] = array( 'config-admin-password-confirm' => 'پټنوم يو ځل بيا:', 'config-admin-email' => 'برېښليک پته:', 'config-profile-wiki' => 'دوديزه ويکي', + 'config-license-pd' => 'ټولګړی شپول', 'config-email-settings' => 'د برېښليک امستنې', 'config-install-step-done' => 'ترسره شو', + 'config-install-tables' => 'لښتيالونه جوړول', + 'config-help' => 'لارښود', 'mainpagetext' => "'''MediaWiki په برياليتوب سره نصب شو.'''", 'mainpagedocfooter' => 'د ويکي ساوترې د کارولو د مالوماتو په اړه [//meta.wikimedia.org/wiki/Help:Contents د کارن لارښود] سره سلا وکړۍ. @@ -15019,6 +15224,7 @@ Devia [//www.mediawiki.org/wiki/Unicode_normalization_considerations actualizá- Se usa alojamento partilhado, peça ao fornecedor do alojamento para instalar um controlador apropriado. Se foi você quem compilou o PHP, reconfigure-o com um cliente de base de dados activado; por exemplo, usando ./configure --with-mysql. Se instalou o PHP a partir de um pacote Debian ou Ubuntu, então precisa de instalar também o módulo php5-mysql.", + 'config-outdated-sqlite' => "'''Aviso''': Tem a versão $1 do SQLite, que é anterior à versão mínima necessária, a $2. O SQLite não estará disponível.", 'config-no-fts3' => "'''Aviso''': O SQLite foi compilado sem o módulo [//sqlite.org/fts3.html FTS3]; as funcionalidades de pesquisa não estarão disponíveis nesta instalação.", 'config-register-globals' => "'''Aviso: A opção [http://php.net/register_globals register_globals] do PHP está activada.''' '''Desactive-a, se puder.''' @@ -15048,11 +15254,14 @@ O MediaWiki necessita do suporte UTF-8 para funcionar correctamente.", 'config-memory-bad' => "'''Aviso:''' A configuração memory_limit do PHP é $1. Isto é provavelmente demasiado baixo. A instalação poderá falhar!", + 'config-ctype' => "'''Fatal''': O PHP tem de ser compilado com suporte para a [http://www.php.net/manual/en/ctype.installation.php extensão Ctype].", 'config-xcache' => '[http://xcache.lighttpd.net/ XCache] instalada', 'config-apc' => '[http://www.php.net/apc APC] instalada', 'config-wincache' => '[http://www.iis.net/download/WinCacheForPhp WinCache] instalada', - 'config-no-cache' => "'''Aviso:''' Não foram encontrados [http://www.php.net/apc APC], [http://xcache.lighttpd.net/ XCache] nem [http://www.iis.net/download/WinCacheForPhp WinCache]. + 'config-no-cache' => "'''Aviso:''' Não foi possível encontrar: [http://www.php.net/apc APC], [http://xcache.lighttpd.net/ XCache], nem [http://www.iis.net/download/WinCacheForPhp WinCache]. A cache de objectos não será activada.", + 'config-mod-security' => "'''Aviso''': O seu servidor de internet tem o [http://modsecurity.org/ mod_security] ativado. Se este estiver mal configurado, pode causar problemas ao MediaWiki ou a outros programas, permitindo que os utilizadores publiquem conteúdos arbitrários. +Consulte a [http://modsecurity.org/documentation/ mod_security documentação] ou peça apoio ao fornecedor do alojamento do seu servidor se encontrar erros aleatórios.", 'config-diff3-bad' => 'O GNU diff3 não foi encontrado.', 'config-imagemagick' => 'Foi encontrado o ImageMagick: $1. Se possibilitar uploads, a miniaturização de imagens será activada.', @@ -15067,7 +15276,7 @@ A instalação foi abortada.", 'config-using-uri' => 'Será usada a URL do servidor "$1$2".', 'config-uploads-not-safe' => "'''Aviso:''' O directório por omissão para uploads $1, está vulnerável à execução arbitrária de scripts. Embora o MediaWiki verifique a existência de ameaças de segurança em todos os ficheiros enviados, é altamente recomendado que [//www.mediawiki.org/wiki/Manual:Security#Upload_security vede esta vulnerabilidade de segurança] antes de possibilitar uploads.", - 'config-no-cli-uploads-check' => "'''Aviso:''' Durante a instalação da CLI (\"Call Level Interface\", a Interface ao Nível da Chamada de Execução), o directório por omissão para uploads, \$1, não é verificado para determinar se é vulnerável à execução de código arbitrário.", + 'config-no-cli-uploads-check' => "'''Aviso:''' O directório por omissão para uploads, \$1, não é verificado para determinar se é vulnerável à execução de código arbitrário durante a instalação por CLI (\"Command-line Interface\").", 'config-brokenlibxml' => 'O seu sistema tem uma combinação de versões de PHP e libxml2 conhecida por ser problemática, podendo causar corrupção de dados no MediaWiki e outras aplicações da internet. Actualize para o PHP versão 5.2.9 ou posterior e libxml2 versão 2.7.3 ou posterior ([//bugs.php.net/bug.php?id=45996 incidência reportada no PHP]). Instalação interrompida.', @@ -15079,9 +15288,11 @@ Instalação interrompida.', 'config-db-host' => 'Servidor da base de dados:', 'config-db-host-help' => 'Se a base de dados estiver num servidor separado, introduza aqui o nome ou o endereço IP desse servidor. -Se estiver a usar um servidor partilhado, o fornecedor do alojamento deve ter-lhe fornecido o nome do servidor na documentação. +Se estiver a usar um servidor partilhado, o fornecedor do alojamento deve fornecer o nome do servidor na documentação. -Se está a fazer a instalação num servidor Windows com MySQL, usar como nome do servidor "localhost" poderá não funcionar. Se não funcionar, tente usar "127.0.0.1" como endereço IP local.', +Se está a fazer a instalação num servidor Windows com MySQL, usar como nome do servidor "localhost" poderá não funcionar. Se não funcionar, tente usar "127.0.0.1" como endereço IP local. + +Se estiver a usar PostgreSQL, deixe este campo em branco para fazer a ligação através de um socket Unix.', 'config-db-host-oracle' => 'TNS (Transparent Network Substrate) da base de dados:', 'config-db-host-oracle-help' => 'Introduza um [http://download.oracle.com/docs/cd/B28359_01/network.111/b28317/tnsnames.htm Nome Local de Ligação] válido; tem de estar visível para esta instalação um ficheiro tnsnames.ora.
    Se está a usar bibliotecas cliente versão 10g ou posterior, também pode usar o método [http://download.oracle.com/docs/cd/E11882_01/network.112/e10836/naming.htm Ligação Fácil] de atribuição do nome.', 'config-db-wiki-settings' => 'Identifique esta wiki', @@ -15456,6 +15667,7 @@ $3 Depois de terminar o passo anterior, pode '''[$2 entrar na wiki]'''.", 'config-download-localsettings' => 'Download do LocalSettings.php', 'config-help' => 'ajuda', + 'config-nofile' => 'Não foi possível encontrar o ficheiro "$1". Terá sido apagado?', 'mainpagetext' => "'''MediaWiki instalado com sucesso.'''", 'mainpagedocfooter' => 'Consulte o [//meta.wikimedia.org/wiki/Help:Contents Guia de Utilizadores] para informações sobre o uso do software wiki. @@ -15486,7 +15698,7 @@ Esta instalação deverá ser atualizada através do update.php', 'config-upgrade-key-missing' => 'Foi detectada uma instalação existente do MediaWiki. Para atualizar esta instalação, por favor, coloque a seguinte linha na parte inferior do seu LocalSettings.php: -$ 1', +$ 1', # Fuzzy 'config-session-error' => 'Erro ao iniciar a sessão: $1', 'config-session-expired' => 'Os seus dados de sessão parecem ter expirado. As sessões estão configuradas para uma duração de $1. @@ -15532,7 +15744,7 @@ Em conjunto com este programa você deve ter recebido uma 'config-sidebar' => '* [//www.mediawiki.org/wiki/MediaWiki/pt Página principal do MediaWiki] * [//www.mediawiki.org/wiki/Help:Contents/pt Ajuda] * [//www.mediawiki.org/wiki/Manual:Contents/pt Manual técnico] -* [//www.mediawiki.org/wiki/Manual:FAQ FAQ]', +* [//www.mediawiki.org/wiki/Manual:FAQ FAQ]', # Fuzzy 'config-env-good' => 'O ambiente foi verificado. Você pode instalar o MediaWiki.', 'config-env-bad' => 'O ambiente foi verificado. @@ -15541,8 +15753,8 @@ Você não pode instalar o MediaWiki.', 'config-unicode-using-utf8' => 'A usar o utf8_normalize.so, de Brian Viper, para a normalização Unicode.', 'config-unicode-using-intl' => 'Usando a [http://pecl.php.net/intl extensão intl PECL] para a normalização Unicode.', 'config-unicode-pure-php-warning' => "'''Aviso''': A [http://pecl.php.net/intl extensão intl PECL] não está disponível para efetuar a normalização Unicode. -Se o seu site tem um alto volume de tráfego, devia informar-se um pouco sobre a [//www.mediawiki.org/wiki/Unicode_normalization_considerations normalização Unicode].", - 'config-no-db' => 'Não foi possível encontrar um driver de banco de dados adequado!', +Se o seu site tem um alto volume de tráfego, devia informar-se um pouco sobre a [//www.mediawiki.org/wiki/Unicode_normalization_considerations normalização Unicode].", # Fuzzy + 'config-no-db' => 'Não foi possível encontrar um driver de banco de dados adequado!', # Fuzzy 'config-no-fts3' => "' ' 'Aviso' ' ': O SQLite foi compilado sem o módulo [//sqlite.org/fts3.html FTS3]; as funcionalidades de pesquisa não estarão disponíveis nesta instalação.", 'config-register-globals' => "' ' 'Aviso: A opção [http://php.net/register_globals register_globals] do PHP está ativada.''' ' ' 'Desative-a, se puder.''' @@ -15550,7 +15762,7 @@ O MediaWiki funcionará mesmo assim, mas o seu servidor ficará exposto a potenc 'config-logo-help' => 'O tema padrão do MediaWiki inclui espaço para um logotipo de 135x160 pixels no canto superior esquerdo. Faça o upload de uma imagem com estas dimensões e introduza aqui a URL dessa imagem. -Se você não pretende usar um logotipo, deixe este campo em branco.', +Se você não pretende usar um logotipo, deixe este campo em branco.', # Fuzzy 'mainpagetext' => "'''MediaWiki instalado com sucesso.'''", 'mainpagedocfooter' => 'Consulte o [//meta.wikimedia.org/wiki/Help:Contents Manual de Usuário] para informações de como usar o software wiki. @@ -15561,7 +15773,8 @@ Se você não pretende usar um logotipo, deixe este campo em branco.', * [https://lists.wikimedia.org/mailman/listinfo/mediawiki-announce Lista de discussão com avisos de novas versões do MediaWiki]', ); -/** Quechua (Runa Simi) */ +/** Quechua (Runa Simi) + */ $messages['qu'] = array( 'mainpagetext' => "'''MediaWiki nisqa llamp'u kaqqa aypaylla takyachisqañam.'''", 'mainpagedocfooter' => "Wiki llamp'u kaqmanta willasunaykipaqqa [//meta.wikimedia.org/wiki/Help:Contents Ruraqpaq yanapana] ''(User's Guide)'' sutiyuq p'anqata qhaway. @@ -15573,7 +15786,8 @@ $messages['qu'] = array( * [https://lists.wikimedia.org/mailman/listinfo/mediawiki-announce MediaWiki release mailing list]", ); -/** Romagnol (Rumagnôl) */ +/** Romagnol (Rumagnôl) + */ $messages['rgn'] = array( 'mainpagetext' => "'''L'instalaziòn d'MediaWiki l'è andêda ben'''", ); @@ -15620,8 +15834,18 @@ $messages['ro'] = array( 'config-header-sqlite' => 'Setări SQLite', 'config-header-oracle' => 'Setări Oracle', 'config-missing-db-name' => 'Trebuie să introduci o valoare pentru „Numele bazei de date”', + 'config-mysql-engine' => 'Motor de stocare:', + 'config-mysql-innodb' => 'InnoDB', + 'config-mysql-myisam' => 'MyISAM', + 'config-site-name-blank' => 'Introduceți un nume pentru sit.', 'config-ns-generic' => 'Proiect', 'config-admin-password' => 'Parolă:', + 'config-optional-continue' => 'Adresează-mi mai multe întrebări.', + 'config-optional-skip' => 'Sunt deja plictisit, doar instalează wikiul.', + 'config-profile-wiki' => 'Wiki tradițional', + 'config-profile-private' => 'Wiki privat', + 'config-email-settings' => 'Setări pentru e-mail', + 'config-install-step-done' => 'realizat', 'mainpagetext' => "'''Programul Wiki a fost instalat cu succes.'''", 'mainpagedocfooter' => 'Consultați [//meta.wikimedia.org/wiki/Help:Contents Ghidul utilizatorului (en)] pentru informații despre utilizarea software-ului wiki. @@ -16225,7 +16449,8 @@ $messages['sa'] = array( 'mainpagetext' => 'मीडियाविकि तु सफलतया अन्तःस्थापितमस्ति', ); -/** Sakha (саха тыла) */ +/** Sakha (саха тыла) + */ $messages['sah'] = array( 'mainpagetext' => "'''«MediaWiki» сөпкө туруорулунна.'''", 'mainpagedocfooter' => 'Биики программатын туһунан [//meta.wikimedia.org/wiki/Help:Contents справочникка] көрүөххүн сөп. @@ -16244,7 +16469,8 @@ $messages['sc'] = array( 'mainpagetext' => "'''MediaWiki est stadu installadu in modu currègidu.'''", ); -/** Sicilian (sicilianu) */ +/** Sicilian (sicilianu) + */ $messages['scn'] = array( 'mainpagetext' => "'''Nstallazzioni di MediaWiki cumplitata currettamenti.'''", 'mainpagedocfooter' => "Pi favuri taliari [//meta.wikimedia.org/wiki/Help:Contents Guida utenti] pi aiutu supra l'usu e la cunfigurazzioni di stu software wiki. @@ -16255,7 +16481,8 @@ $messages['scn'] = array( * [https://lists.wikimedia.org/mailman/listinfo/mediawiki-announce Mailing list dî rilassi di MediaWiki]", ); -/** Scots (Scots) */ +/** Scots (Scots) + */ $messages['sco'] = array( 'mainpagetext' => "'''MediaWiki haes been installit wi speed.'''", 'mainpagedocfooter' => "Aks the [//meta.wikimedia.org/wiki/Help:Contents Uiser's Manual] for speirins aboot using the wiki saftware. @@ -16267,7 +16494,8 @@ $messages['sco'] = array( * [https://lists.wikimedia.org/mailman/listinfo/mediawiki-announce MediaWiki releese mailin leet]", ); -/** Sassaresu (Sassaresu) */ +/** Sassaresu (Sassaresu) + */ $messages['sdc'] = array( 'mainpagetext' => "'''Isthallazioni di MediaWiki accabadda currentementi.'''", 'mainpagedocfooter' => "Cunsultha la [//meta.wikimedia.org/wiki/Aggiuddu:Summàriu Ghia utenti] pa maggiori infuimmazioni i l'usu di chisthu software wiki. @@ -16280,7 +16508,8 @@ Li sighenti cullegamenti so in linga ingrese: * [https://lists.wikimedia.org/mailman/listinfo/mediawiki-announce Mailing list annùnzii MediaWiki]", ); -/** Cmique Itom (Cmique Itom) */ +/** Cmique Itom (Cmique Itom) + */ $messages['sei'] = array( 'mainpagetext' => "'''MediaWiki coccebj installöx successua zo mii.'''", ); @@ -16374,8 +16603,17 @@ $messages['si'] = array( * [https://lists.wikimedia.org/mailman/listinfo/mediawiki-announce මීඩියාවිකි නිකුතුව තැපැල් ලැයිස්තුව]', ); -/** Slovak (slovenčina) */ +/** Slovak (slovenčina) + * @author Kusavica + */ $messages['sk'] = array( + 'config-your-language' => 'Váš jazyk:', + 'config-wiki-language' => 'Wiki jazyk:', + 'config-back' => '← Späť', + 'config-continue' => 'Pokračovať →', + 'config-page-language' => 'Jazyk', + 'config-download-localsettings' => 'Stiahnuť LocalSettings.php', + 'config-nofile' => 'Súbor "$1" sa nenašiel. Bol zmazaný?', 'mainpagetext' => "'''Softvér MediaWiki bol úspešne nainštalovaný.'''", 'mainpagedocfooter' => 'Informácie ako používať wiki softvér nájdete v [//meta.wikimedia.org/wiki/Help:Contents Používateľskej príručke]. @@ -16628,7 +16866,8 @@ $messages['so'] = array( * [https://lists.wikimedia.org/mailman/listinfo/mediawiki-announce MediaWiki release mailing list]", ); -/** Albanian (shqip) */ +/** Albanian (shqip) + */ $messages['sq'] = array( 'mainpagetext' => "'''MediaWiki software u instalua me sukses.'''", 'mainpagedocfooter' => 'Për më shumë informata rreth përdorimit të softwerit wiki , ju lutem shikoni [//meta.wikimedia.org/wiki/Help:Contents dokumentacionin përkatës]. @@ -16639,12 +16878,39 @@ $messages['sq'] = array( * [https://lists.wikimedia.org/mailman/listinfo/mediawiki-announce Njoftime rreth MediaWiki-t]', ); -/** Serbian (Cyrillic script) (‪српски (ћирилица)‬) +/** Serbian (Cyrillic script) (српски (ћирилица)‎) * @author Rancher + * @author Михајло Анђелковић */ $messages['sr-ec'] = array( + 'config-session-error' => 'Грешка при започињању сесије: $1', + 'config-session-expired' => 'Ваши подаци о сесији су истекли. +Сесије су подешене да трају $1. +Њихов рок можете повећати постављањем session.gc_maxlifetime у php.ini. +Поново покрените инсталацију.', + 'config-no-session' => 'Ваши подаци о сесији су изгубљени! +Проверите Ваш php.ini и обезбедите да је session.save_path постављен на одговарајући директоријум.', + 'config-your-language' => 'Ваш језик:', + 'config-your-language-help' => 'Изаберите језик који желите да користите током инсталације.', + 'config-wiki-language' => 'Језик викија:', + 'config-wiki-language-help' => 'Изаберите језик на ком ће бити садржај викија.', + 'config-back' => '← Назад', 'config-continue' => 'Настави →', 'config-page-language' => 'Језик', + 'config-page-welcome' => 'Добро дошли на МедијаВики!', + 'config-page-dbconnect' => 'Повезивање са базом података', + 'config-page-upgrade' => 'Надоградња постојеће инсталације', + 'config-page-dbsettings' => 'Подешавања базе података', + 'config-page-name' => 'Назив', + 'config-page-options' => 'Поставке', + 'config-page-install' => 'Инсталирај', + 'config-page-complete' => 'Завршено!', + 'config-page-restart' => 'Поновно покретање инсталације', + 'config-page-copying' => 'Умножавање', + 'config-page-upgradedoc' => 'Надоградња', + 'config-page-existingwiki' => 'Постојећи вики', + 'config-help-restart' => 'Желите ли да обришете све сачуване податке које сте унели и поново покренете инсталацију?', + 'config-restart' => 'Да, покрени поново', 'config-type-mysql' => 'MySQL', 'config-type-postgres' => 'PostgreSQL', 'config-type-sqlite' => 'SQLite', @@ -16658,10 +16924,37 @@ $messages['sr-ec'] = array( * [https://lists.wikimedia.org/mailman/listinfo/mediawiki-announce Дописна листа о издањима Медијавикија]', ); -/** Serbian (Latin script) (‪srpski (latinica)‬) */ +/** Serbian (Latin script) (srpski (latinica)‎) + */ $messages['sr-el'] = array( + 'config-session-error' => 'Greška pri započinjanju sesije: $1', + 'config-session-expired' => 'Vaši podaci o sesiji su istekli. +Sesije su podešene da traju $1. +Njihov rok možete povećati postavljanjem session.gc_maxlifetime u php.ini. +Ponovo pokrenite instalaciju.', + 'config-no-session' => 'Vaši podaci o sesiji su izgubljeni! +Proverite Vaš php.ini i obezbedite da je session.save_path postavljen na odgovarajući direktorijum.', + 'config-your-language' => 'Vaš jezik:', + 'config-your-language-help' => 'Izaberite jezik koji želite da koristite tokom instalacije.', + 'config-wiki-language' => 'Jezik vikija:', + 'config-wiki-language-help' => 'Izaberite jezik na kom će biti sadržaj vikija.', + 'config-back' => '← Nazad', 'config-continue' => 'Nastavi →', 'config-page-language' => 'Jezik', + 'config-page-welcome' => 'Dobro došli na MedijaViki!', + 'config-page-dbconnect' => 'Povezivanje sa bazom podataka', + 'config-page-upgrade' => 'Nadogradnja postojeće instalacije', + 'config-page-dbsettings' => 'Podešavanja baze podataka', + 'config-page-name' => 'Naziv', + 'config-page-options' => 'Postavke', + 'config-page-install' => 'Instaliraj', + 'config-page-complete' => 'Završeno!', + 'config-page-restart' => 'Ponovno pokretanje instalacije', + 'config-page-copying' => 'Umnožavanje', + 'config-page-upgradedoc' => 'Nadogradnja', + 'config-page-existingwiki' => 'Postojeći viki', + 'config-help-restart' => 'Želite li da obrišete sve sačuvane podatke koje ste uneli i ponovo pokrenete instalaciju?', + 'config-restart' => 'Da, pokreni ponovo', 'config-type-mysql' => 'MySQL', 'config-type-postgres' => 'PostgreSQL', 'config-type-sqlite' => 'SQLite', @@ -16675,7 +16968,8 @@ $messages['sr-el'] = array( * [https://lists.wikimedia.org/mailman/listinfo/mediawiki-announce Mejling lista o izdanjima MedijaVikija]', ); -/** Sranan Tongo (Sranantongo) */ +/** Sranan Tongo (Sranantongo) + */ $messages['srn'] = array( 'mainpagetext' => "'''MediaWiki seti kon bun.'''", 'mainpagedocfooter' => 'Luku na ini a [//meta.wikimedia.org/wiki/Help:Yepi yepibuku] fu si fa fu kebrouki a wikisoftware. @@ -16687,7 +16981,8 @@ $messages['srn'] = array( * [https://lists.wikimedia.org/mailman/listinfo/mediawiki-announce Boskopu grupu gi nyun meki]', ); -/** Swati (SiSwati) */ +/** Swati (SiSwati) + */ $messages['ss'] = array( 'mainpagetext' => "'''i-MediaWiki seyifakeke ngalokuphelele.'''", ); @@ -16700,7 +16995,8 @@ $messages['stq'] = array( 'mainpagedocfooter' => 'Sjuch ju [//meta.wikimedia.org/wiki/MediaWiki_localization Dokumentation tou de Anpaasenge fon dän Benutseruurfläche] un dät [//meta.wikimedia.org/wiki/Help:Contents Benutserhondbouk] foar Hälpe tou ju Benutsenge un Konfiguration.', ); -/** Sundanese (Basa Sunda) */ +/** Sundanese (Basa Sunda) + */ $messages['su'] = array( 'mainpagetext' => "'''''Software'' MediaWiki geus diinstal.'''", 'mainpagedocfooter' => "Mangga tingal ''[//meta.wikimedia.org/wiki/MediaWiki_localisation documentation on customizing the interface]'' jeung [//meta.wikimedia.org/wiki/MediaWiki_User%27s_Guide Tungtunan Pamaké] pikeun pitulung maké jeung konfigurasi.", @@ -16961,7 +17257,8 @@ $messages['ta'] = array( * [https://lists.wikimedia.org/mailman/listinfo/mediawiki-announce மீடியாவிக்கி வெளியீடு மின்னஞ்சல் பட்டியல்]', ); -/** Tulu (ತುಳು) */ +/** Tulu (ತುಳು) + */ $messages['tcy'] = array( 'mainpagetext' => "'''ಮೀಡಿಯವಿಕಿ ಯಶಸ್ವಿಯಾದ್ ಇನ್’ಸ್ಟಾಲ್ ಆಂಡ್.'''", 'mainpagedocfooter' => 'ವಿಕಿ ತಂತ್ರಾಂಶನ್ ಉಪಗೋಗ ಮನ್ಪುನ ಬಗ್ಗೆ ಮಾಹಿತಿಗ್ [//meta.wikimedia.org/wiki/Help:Contents ಸದಸ್ಯೆರ್ನ ನಿರ್ದೇಶನ ಪುಟ] ತೂಲೆ. @@ -17010,6 +17307,7 @@ $messages['te'] = array( 'config-mysql-utf8' => 'UTF-8', 'config-site-name' => 'వికీ యొక్క పేరు:', 'config-ns-other' => 'ఇతర (ఇవ్వండి)', + 'config-ns-other-default' => 'నావికీ', 'config-admin-name' => 'మీ పేరు:', 'config-admin-password' => 'సంకేతపదం:', 'config-admin-password-confirm' => 'సంకేతపదం మళ్ళీ:', @@ -17022,6 +17320,7 @@ $messages['te'] = array( 'config-license-pd' => 'సార్వజనీనం', 'config-email-settings' => 'ఈ-మెయిల్ అమరికలు', 'config-upload-deleted' => 'తొలగించిన దస్త్రాల కొరకు సంచయం:', + 'config-advanced-settings' => 'ఉన్నత స్వరూపణం', 'config-install-step-done' => 'పూర్తయింది', 'config-install-step-failed' => 'విఫలమైంది', 'config-help' => 'సహాయం', @@ -17043,7 +17342,8 @@ $messages['tet'] = array( 'config-page-name' => 'Naran', ); -/** Tajik (Cyrillic script) (тоҷикӣ) */ +/** Tajik (Cyrillic script) (тоҷикӣ) + */ $messages['tg-cyrl'] = array( 'mainpagetext' => "'''Нармафзори МедиаВики бо муваффақият насб шуд.'''", 'mainpagedocfooter' => 'Аз [//meta.wikimedia.org/wiki/Help:Contents Роҳнамои Корбарон] барои истифодаи нармафзори вики кӯмак бигиред. @@ -17101,9 +17401,12 @@ $messages['tk'] = array( * @author Sky Harbor */ $messages['tl'] = array( - 'config-desc' => 'Ang instalador para sa MediaWiki', + 'config-desc' => 'Ang tagapagluklok para sa MediaWiki', 'config-title' => 'Instalasyong $1 ng MediaWiki', 'config-information' => 'Kabatiran', + 'config-localsettings-upgrade' => 'Napansin ang isang talaksang LocalSettings.php. +Upang maitaas ang uri ng pagluluklok na ito, paki ipasok ang halaga ng $wgUpgradeKey sa loob ng kahong nasa ibaba. +Matatagpuan mo ito sa loob ng LocalSettings.php.', 'config-localsettings-cli-upgrade' => 'Napansin ang isang talaksan ng LocalSettings.php. Upang isapanahon ang pagtatalagang ito, mangyaring patakbuhin sa halip ang update.php', 'config-localsettings-key' => 'Susi ng pagsasapanahon:', @@ -17115,7 +17418,15 @@ $1', 'config-localsettings-incomplete' => 'Lumilitaw na hindi pa buo ang umiiral na LocalSettings.php. Ang pabagu-bagong $1 ay hindi nakatakda. Mangyaring baguhin ang LocalSettings.php upang ang maitakda ang pagpapabagu-bagong ito, at pindutin ang "Magpatuloy".', + 'config-localsettings-connection-error' => 'Isang kamalian ang nakatagpo noong kumakabit sa kalipunan ng dato na ginagamit ang tinukoy na mga katakdaan sa loob ng LocalSettings.php o +AdminSettings.php. Paki kumpunihin ang mga katakdaang ito at subukang muli. + +$1', 'config-session-error' => 'Kamalian sa pagsisimula ng sesyon: $1', + 'config-session-expired' => 'Tila nagwakas na ang inilaan sa iyong panahon ng dato. +Ang inilaang mga panahon ay iniayos para sa isang panahon ng buhay na $1. +Mapapataas mo ito sa pamamagitan ng pagtatakda ng session.gc_maxlifetime sa loob ng php.ini. +Muling simulan ang proseso ng pagluluklok.', 'config-no-session' => 'Nawala ang iyong datos ng sesyon! Suriin ang iyong php.ini at tiyakin na ang session.save_path ay nakatakda sa angkop na direktoryo.', 'config-your-language' => 'Ang wika mo:', @@ -17172,54 +17483,157 @@ Hindi mo mailuklok ang MediaWiki.', Subalit, nangangailangan ang MediaWiki ng PHP $2 o mas mataas pa.', 'config-unicode-using-utf8' => 'Ginagamit ang utf8_normalize.so ni Brion Vibber para sa pagpapanormal ng Unikodigo.', 'config-unicode-using-intl' => 'Ginagamit ang [http://pecl.php.net/intl intl dugtong na PECL] para sa pagsasanormal ng Unikodigo.', + 'config-unicode-pure-php-warning' => "'''Babala''': Ang [http://pecl.php.net/intl dugtong ng internasyunal na PECL] ay hindi makukuha upang makapanghawak ng pagpapanormal ng Unikodigo, na babagsak na pabalik sa mabagal na pagsasakatuparan ng dalisay na PHP. +Kapag nagpapatakbo ka ng isang pook na mataas ang trapiko, dapat kang bumasa ng kaunti hinggil sa [//www.mediawiki.org/wiki/Unicode_normalization_considerations pagpapanormal ng Unikodigo].", + 'config-unicode-update-warning' => "'''Babala''': Ang nakaluklok na bersiyon ng pambalot ng pagpapanormal ng Unikodigo ay gumagamit ng isang mas matandang bersiyon ng aklatan ng [http://site.icu-project.org/ proyekto ng ICU]. +Dapat kang [//www.mediawiki.org/wiki/Unicode_normalization_considerations magtaas ng uri] kung may pag-aalala ka hinggil sa paggamit ng Unikodigo.", 'config-no-db' => 'Hindi matagpuan ang isang angkop na tagapagmaneho ng kalipunan ng datos! Kailangan mong magluklok ng isang tagapagmaneho ng kalipunan ng dato para sa PHP. Tinatangkilik ang sumusunod na mga uri ng kalipunan ng dato: $1. Kung ikaw ay nasa isang pinagsasaluhang pagpapasinaya, hilingin sa iyong tagapagbigay ng pagpapasinaya na iluklok ang isang angkop na tagapagmaneho ng kalipunan ng dato. Kung ikaw mismo ang nangalap ng PHP, muling isaayos ito na pinagagana ang isang kliyente ng kalipunan ng dato, halimbawa na ang paggamit ng ./configure --with-mysql. Kung iniluklok mo ang PHP mula sa isang pakete ng Debian o Ubuntu, kung gayon kailangan mo ring magluklok ng modyul na php5-mysql.', + 'config-outdated-sqlite' => "'''Babala''': mayroong kang $1 ng SQLite, na mas mababa kaysa sa pinaka mababang kailangang bersiyon na $2. Magiging hindi makukuha ang SQLite.", + 'config-no-fts3' => "'''Warning''': Ang SQLite ay hindi itinala at tinipon na wala ang [//sqlite.org/fts3.html modulong FTS3], ang mga tampok na panghanap ay magiging hindi makukuha sa ibabaw ng panlikod na dulong ito.", + 'config-register-globals' => "'''Babala: Ang mapipili na [http://php.net/register_globals register_globals] ng PHP ay pinagagana.''' +'''Huwag paganahin kung kaya mo.''' +Aandar ang MediaWiki, subalit ang tagapaghain mo ay nakalantad sa maaaring maganap na mga kahinaang pangkatiwasayan.", + 'config-magic-quotes-runtime' => "'''Malubha: Masigla ang [http://www.php.net/manual/en/ref.info.php#ini.magic-quotes-runtime magic_quotes_runtime]!''' +Ang piniling ito ay hindi mahuhulaan na pipinsala sa lahok na dato. +Hindi mo maaaring iluklok o gamitin ang MediaWiki maliban na lamang kung hindi na gumagana ang pinili na ito.", + 'config-magic-quotes-sybase' => "'''Malubha: Masigla ang [http://www.php.net/manual/en/ref.info.php#ini.magic-quotes-sybase magic_quotes_sybase]!''' +Hindi mahuhulaan na sinisira ng napiling ito ang lahok na dato. +Hindi mo maaaring iluklok o gamitin ang MediaWiki maliban na lamang kung hindi na pinagagana ang napiling ito.", + 'config-mbstring' => "'''Malubha: Masigla ang [http://www.php.net/manual/en/ref.mbstring.php#mbstring.overload mbstring.func_overload]!''' +Ang napiling ito ay nagdurulot ng mga kamalian at maaaring sumira nang hindi nahuhulaan ang dato. +Hindi mo maaaring iluklok o gamitin ang MediaWiki maliban na lamang kung hindi na pinagagana ang napiling ito.", + 'config-ze1' => "'''Malubha: Masigla ang [http://www.php.net/manual/en/ini.core.php zend.ze1_compatibility_mode]!''' +Ang napiling ito ay nagsasanhi ng karima-rimarim na mga sira sa MediaWiki. +Hindi mo maaaring iluklok o gamitin ang MediaWiki maliban na lamang kung hindi na pinagagana ang napiling ito.", + 'config-safe-mode' => "'''Babala:''' Masigla ang [http://www.php.net/features.safe-mode safe mode] ng PHP. +Maaari itong magdulot ng mga suliranin, partikular na kung gumagamit ng mga ikinargang paitaas na talaksan at ng suporta sa math.", + 'config-xml-bad' => 'Nawawala ang modulong XML ng PHP. +Nangangailangan ang MediaWiki ng mga tungkulin sa loob ng modulong ito at hindi aandar sa loob ng ganitong pagkakaayos. +Kung pinapatakbo mo ang Mandrake, iluklok ang pakete ng php-xml.', + 'config-pcre' => 'Tila nawawala ang modyul na pangsuporta ng PCRE. +Nangangailangan ang MediaWiki ng nakaukol sa Perl na mga tungkulin ng karaniwang pagsasaad upang gumana.', + 'config-pcre-no-utf8' => "'''Malubha''': Tila tinipon ang modyul na PCRE ng PHP na wala ang suporta ng PCRE_UTF8. +Nangangailangan ang MediaWiki ng suporta ng UTF-8 upang maging tama ang pag-andar.", 'config-memory-raised' => 'Ang hangganan_ng_alaala ng PHP ay $1, itinaas sa $2.', 'config-memory-bad' => "'''Babala:''' Ang hangganan_ng_alaala ng PHP ay $1. Ito ay maaaring napakababa. Maaaring mabigo ang pagluluklok!", + 'config-ctype' => "'''Maluba''': Dapat na tipunin ang PHP na mayroong suporta para sa [http://www.php.net/manual/en/ctype.installation.php dugtong Ctype].", 'config-xcache' => 'Ininstala na ang [http://xcache.lighttpd.net/ XCache]', 'config-apc' => 'Ininstala na ang [http://www.php.net/apc APC]', 'config-wincache' => 'Ininstala na ang [http://www.iis.net/download/WinCacheForPhp WinCache]', 'config-no-cache' => "'''Babala:''' Hindi mahanap ang [http://www.php.net/apc APC], [http://xcache.lighttpd.net/ XCache] o [http://www.iis.net/download/WinCacheForPhp WinCache]. Hindi pinapagana ang pagbabaon ng mga bagay.", + 'config-mod-security' => "'''Babala''': Ang tagapaghain mo ng sangkasaputan ay pinagana na mayroong [http://modsecurity.org/ mod_security]. Kung mali ang kaayusan, makapagdurulot ito ng mga suliranin para sa MediaWiki o ibang mga sopwer na nagpapahintulot sa mga tagagamit na magpaskil ng hindi makatwirang nilalaman. +Sumangguni sa [http://modsecurity.org/documentation/ mod_security kasulatan] o makipag-ugnayan sa suporta ng iyong tagapagpasinaya kapag nakatagpo ng alin mang mga kamalian.", 'config-diff3-bad' => 'Hindi natagpuan ang GNU diff3.', 'config-imagemagick' => 'Natagpuan ang ImageMagick: $1. +Papaganahin ang pagkakagyat ng larawan kapag pinagana mo ang mga pagkakargang paitaas.', + 'config-gd' => 'Natagpuan ang pinasadyang nakapaloob na grapiks ng GD. Papaganahin ang pagkakagyat ng larawan kapag pinagana mo ang mga pagkakargang paitaas.', 'config-no-scaling' => 'Hindi matagpuan ang aklatang GD o ImageMagick. Hindi papaganahin ang pagkakagyat ng larawan.', 'config-no-uri' => "'''Kamalian:''' Hindi matukoy ang kasalukuyang URI. Pinigilan ang pag-iinstala.", + 'config-no-cli-uri' => "'''Babala''': Walang tinukoy na --landas ng panitik, ginagamit ang likas na katakdaan: $1.", + 'config-using-server' => 'Ginagamit ang pangalan ng tagapaghain na "$1".', + 'config-using-uri' => 'Ginagamit ang URL ng tagapaghain na "$1$2".', + 'config-uploads-not-safe' => "'''Babala:''' Ang iyong likas na nakatakdang direktoryo para sa paitaas na mga pagkakarga na $1 ay may kahinaan laban sa pagsasagawa ng mga panitiki na hindi makatwiran. Bagaman sinisiyasat ng MediaWiki ang lahat ng paitaas na naikargang mga talaksan para sa mga panganib na pangkatiwasayan, mataas na iminumungkahi na [//www.mediawiki.org/wiki/Manual:Security#Upload_security isara ang kahinaang ito na pangkatiwasayan] bago paganahin ang paitaas na mga pagkakarga.", + 'config-no-cli-uploads-check' => "'''Babala:''' Ang iyong likas na nakatakdang direktoryo para sa paitaas na mga pagkakarga ($1) ay hindi nasuri para sa kahinaan laban sa pagsasagawa ng panitik na hindi makatwiran habang iniluluklok ang Ugnayang Mukha ng Guhit ng Kaataasan o Command-Line Interface (CLI).", + 'config-brokenlibxml' => "Ang sistema mo ay mayroong isang pagsasama ng mga bersiyon ng PHP at libxml2 na maaaring masurot at maaaring makapagsanhi ng pagkasira ng datong nakakubli sa loob ng MediaWiki at iba pang mga aplikasyon ng sangkasaputan. +Magtaas ng uri upang maging PHP 5.2.9 o mas lalong huli at libxml2 2.7.3 o mas lalong huli ([//bugs.php.net/bug.php?id=45996 isinalansan ang surot o ''bug'' na mayroong PHP]). Binigo ang pagluluklok.", + 'config-using531' => 'Hindi maaaring gamitin ang MediaWiki na kapiling ang PHP na $1 dahil sa isang surot na kinasasangkutan ng mga parametrong pangsangguni sa __call(). Magtaas ng uri upang maging PHP 5.3.2 o mas mataas, o magbaba ng uri upang maging PHP 5.3.0 upang malutas ito. Binigo ang pagluluklok.', + 'config-suhosin-max-value-length' => 'Nakaluklok ang Suhosin at hinahanggahan ang haba ng parametro ng GET sa $1 mga byte. Ang sangkap na ResourceLoader ng MediaWiki ay gagana sa paligid ng hangganang ito, subalit pasasamain nito ang pagganap. Kung talagang maaari, dapat mong itakda ang suhosin.get.max_value_length upang maging 1024 o mas mataas sa loob ng php.ini, at itakda ang $wgResourceLoaderMaxQueryLength sa katulad na halaga sa loob ng LocalSettings.php.', 'config-db-type' => 'Uri ng kalipunan ng datos:', 'config-db-host' => 'Tagapagpasinaya ng kalipunan ng datos:', + 'config-db-host-help' => 'Kung ang iyong tagapaghain ng kalipunan ng dato ay nasa ibabaw ng isang ibang tagapaghain, ipasok ang pangalan ng tagapagpasinaya o tirahan ng IP dito. + +Kung gumagamit ka ng pinagsasaluhang pagpapasinaya ng sangkasaputan, dapat ibigay sa iyo ng iyong tagapagbigay ng pagpapasinaya ang tamang pangalan ng tagapagpasinaya sa loob ng kanilang kasulatan. + +Kapag nagluluklok ka sa ibabaw ng isang tagapaghain ng Windows at gumagamit ng MySQL, maaaring hindi gumana ang paggamit ng "localhost" para sa pangalan ng tagapaghain. Kung hindi, subukan ang "127.0.0.1" para sa katutubong tirahan ng IP. + +Kapag gumagamit ka ng PostgreSQL, iwanang walang laman ang hanay na ito upang kumabit sa pamamagitan ng bokilya ng Unix.', 'config-db-host-oracle' => 'TNS ng kalipunan ng dato:', + 'config-db-host-oracle-help' => 'Magpasok ng isang katanggap-tanggap na [http://download.oracle.com/docs/cd/B28359_01/network.111/b28317/tnsnames.htm Katutubong Pangalan ng Pagkabit]; dapat na nakikita ang isang talaksan ng tnsnames.ora sa pagluluklok na ito.
    Kung gumagamit ka ng mga aklatan ng kliyente na 10g o mas bago, maaari mo ring gamitin ang pamamaraan ng pagpapangalan ng [http://download.oracle.com/docs/cd/E11882_01/network.112/e10836/naming.htm Maginhawang Pagkabit].', 'config-db-wiki-settings' => 'Kilalanin ang wiking ito', 'config-db-name' => 'Pangalan ng kalipunan ng dato:', + 'config-db-name-help' => 'Pumili ng isang pangalan na pangkilala sa wiki mo. +Hindi ito dapat maglaman ng mga patlang. + +Kung gumagamit ka ng pinagsasaluhang pagpapasinaya ng sangkasaputan, ang iyong tagapagbigay ng pagpapasinaya ay maaaring bigyan ka ng isang tiyak na pangalan ng kalipunan ng datong gagamitin o papayagan kang lumikha ng mga kalipunan ng dato sa pamamagitan ng isang entrepanyong pantaban.', 'config-db-name-oracle' => 'Balangkas ng kalipunan ng dato:', + 'config-db-account-oracle-warn' => 'Mayroong tatlong tinatangkilik na tagpo para sa pagluluklok ng Oracle bilang panlikurang hulihan ng kalipunan ng dato: + +Kung nais mong lumikha ng akawnt ng kalipunan ng dato bilang bahagi ng proseso ng pagluluklok, paki magbigay ng isang akawnt na mayroong gampanin ng SYSDBA bilang akawnt ng kalipunan ng dato para sa pagluluklok at tukuyin ang ninanais na mga kredensiyal para sa akawnt ng pagpunta sa sangkasaputan, o di kaya ay maaaring kinakamay na lumikha ng akawnt ng pagpunta sa sangkasaputan at ibigay lamang ang akawnt na iyan (kung mayroong ito ng kinakailangang mga pahintulot upang malikha ang mga bagay na pampagpapanukala) o magbigay ng dalawang magkaibang mga akawnt, isang mayroong pribilehiyo ng paglikha at isang may pagbabawal para sa pagpunta sa sangkasaputan. + +Ang panitik sa paglikha ng isang akawnt na mayroon ng kinakailangang mga pribilehiyo ay matatagpuan sa loob ng direktoryong "maintenance/oracle/" ng pagluluklok na ito. Pakatandaan na ang paggamit ng isang akawnt na may pagbabawal ay hindi magpapagana isa lahat ng mga kakayahang pampananatili sa piling ng likas na nakatakdang akawnt.', 'config-db-install-account' => 'Akawnt ng tagagamit para sa pagluluklok', 'config-db-username' => 'Pangalang pangtagagamit ng kalipunan ng dato:', 'config-db-password' => 'Hudyat sa kalipunan ng dato:', + 'config-db-password-empty' => 'Paki magpasok ng isang hudyat para sa bagong tagagamit ng kalipunan ng dato: $1. +Habang maging maaari na makalikha ng mga tagagamit na walang mga hudyat, hindi ito ligtas.', + 'config-db-install-username' => 'Ipasok ang pangalan ng tagagamit na gagamitin upang kumabit sa kalipunan ng dato habang isinasagawa ang pagluluklok. +Hindi ito ang pangalan ng tagagamit ng akawnt ng MediaWiki; ito ang pangalan ng tagagamit para sa iyong kalipunan ng dato.', + 'config-db-install-password' => 'Ipasok ang hudyat na gagamitin upang kumabit sa kalipunan ng dato habang isinasagawa ang pagluluklok. +Hindi ito ang hudyat para sa akawnt ng MediaWiki; ito ang hudyat para sa iyong kalipunan ng dato.', 'config-db-install-help' => 'Ipasok ang pangalan ng tagagamit at hudyat na gagamitin upang umugnay sa kalipunan ng dato habang isinasagawa ang pagluluklok.', 'config-db-account-lock' => 'Gamitin ang gayun ding pangalan ng tagagamit at hudyat habang nasa normal na operasyon', 'config-db-wiki-account' => 'Akawnt ng tagagamit para sa pangkaraniwang pagpapaandar', + 'config-db-wiki-help' => 'Ipasok ang pangalan ng tagagamit at hudyat na gagamitin upang kumabit sa kalipunan ng dato habang nasa karaniwang pagtakbo ng wiki. +Kung hindi umiiral ang akawnt, at ang akawnt ng pagluluklok ay mayroong sapat na mga pribilehiyo, ang akawnt na ito ng tagagamit ay lilikhain na mayroong pinaka mababang mga pribilehiyo na kailangan upang mapatakbo ang wiki.', 'config-db-prefix' => 'Unlapi ng talahanayan ng kalipunan ng dato:', + 'config-db-prefix-help' => 'Kung kailangan mong ibahagi ang isang kalipunan ng dato sa pagitan ng maramihang mga wiki, o sa pagitan ng MediaWiki at ibang aplikasyon ng kasaputan, maaaring piliin mo na magdagdag ng isang unlapi sa lahat ng mga pangalan ng talahanayan upang maiwasan ang mga salungatan. +Huwag gumamit ng mga patlang. + +Ang hanay na ito ay karaniwang iniiwanang walang laman.', 'config-db-charset' => 'Pangkat ng panitik ng kalipunan ng dato', 'config-charset-mysql5-binary' => 'MySQL 4.1/5.0 binaryo', 'config-charset-mysql5' => 'MySQL 4.1/5.0 UTF-8', 'config-charset-mysql4' => 'MySQL 4.0 paurong-kabagay UTF-8', + 'config-charset-help' => "'''Babala:''' Kapag ginamit mo ang '''backwards-compatible UTF-8''' o \"nauukol na pabalik na UTF-8\" sa MySQL 4.1+, at may kasunod na pagtatabi ng pansalong kopya ng kalipunan ng dato na mayroong mysqldump, maaaring wasakin nito ang lahat ng mga panitik na hindi ASCII, na hindi na mababawi pa ang mga pansalong kopya. + +Sa '''gawi na nakahalo sa dalawa (binaryo)''', itinatabi ng MediaWiki ang tekstong UTF-8 sa kalipunan ng dato sa loob ng mga kahanayang binaryo. +Mas kapaki-pakinabang ito kaysa sa gawi na UTF-8 ng MySQL, at nagpapahintulot sa iyo na gamitin ang buong kasaklawan ng mga panitik na Unikodigo. +Sa '''gawi ng UTF-8''', malalaman ng MySQL kung anong pangkat ng panitik ang kinapapalooban ng iyong dato, at may kaangkupang maihaharap at mapapalitan ito, ngunit hindi ka nito papayagan na mag-imbak ng mga panitik sa ibabaw ng [//en.wikipedia.org/wiki/Mapping_of_Unicode_character_planes Basic Multilingual Plane] o Saligang Patag na Kayas na Pangmaramihang Wika.", 'config-mysql-old' => 'Hindi kailangan ang MySQL na $1 o mas bago, mayroon kang $2.', 'config-db-port' => 'Daungan ng kalipunan ng dato:', 'config-db-schema' => 'Panukala para sa MediaWiki', 'config-db-schema-help' => 'Ang nasa itaas na panukala ay pangkaraniwang magiging maayos. Baguhin lamang ito kung alam mong kinakailangan.', + 'config-pg-test-error' => "Hindi makakabit sa kalipunan ng dato na '''$1''': $2", 'config-sqlite-dir' => 'Direktoryo ng dato ng SQLite:', + 'config-sqlite-dir-help' => "Iniimbak ng SQLite ang lahat ng dato sa loob ng isang nag-iisang talaksan. + +Ang ibibigay mong direktoryo ay dapat na maging masusulatan ng tagapaghain ng kasaputan habang nagluluklok. + +'''Hindi''' ito dapat na mapuntahan sa pamamagitan ng kasaputan, ito ang dahilan kung bakit hindi namin ito inilalagay sa kung nasaan ang iyong mga talaksan ng PHP. + +Ang tagapagluklok ay magsusulat ng isang talaksang .htaccess na kasama ito, subalit kapag nabigo iyon mayroong isang tao na maaaring makakuha ng pagka nakakapunta sa iyong hilaw na kalipunan ng dato. +Kasama riyan ang hilaw na dato ng tagagamit (mga tirahan ng e-liham, pinaghalong mga hudyat) pati na ang nabura nang mga pagbabago at iba pang may pagbabawal na dato sa ibabaw ng wiki. + +Isaalang-alang ang paglalagay na magkakasama ang kalipunan ng dato sa ibang lugar, halimbawa na ang sa loob ng /var/lib/mediawiki/yourwiki.", 'config-oracle-def-ts' => 'Likas na nakatakdang puwang ng talahanayan:', 'config-oracle-temp-ts' => 'Pansamantalang puwang ng talahanayan:', + 'config-type-mysql' => 'MySQL', + 'config-type-postgres' => 'PostgreSQL', + 'config-type-sqlite' => 'SQLite', + 'config-type-oracle' => 'Oracle', 'config-type-ibm_db2' => 'DB2 ng IBM', + 'config-support-info' => 'Sinusuportahan ng MediaWiki ang sumusunod na mga sistema ng kalipunan ng dato: + +$1 + +Kung hindi mo makita ang sistema ng kalipunan ng dato na sinusubukan mong gamitin na nakatala sa ibaba, kung gayon ay sundi ang mga tagubilin na nakakawing sa itaas upang mapagana ang suporta,', + 'config-support-mysql' => '* Ang $1 ay ang pangunahing puntirya para sa MediaWiki at ang pinaka sinusuportahan ([http://www.php.net/manual/en/mysql.installation.php paano magtipon ng PHP na mayroong suporta ng MySQL])', + 'config-support-postgres' => '* Ang $1 ay isang bantog na sistema ng kalipunan ng dato na bukas ang pinagmulan na panghalili sa MySQL ([http://www.php.net/manual/en/pgsql.installation.php paano magtipon ng PHP na mayroong suporta ng PostgreSQL]). Maaaring mayroong ilang hindi pangunahing mga surot na natitira pa, at hindi iminumungkahi para gamitin sa loob ng isang kapaligiran ng produksiyon.', + 'config-support-sqlite' => 'Ang $1 ay isang magaan ang timbang na sistema ng kalipunan ng dato na sinusuportahan nang napaka mainam. ([http://www.php.net/manual/en/pdo.installation.php Paano magtipon ng PHP na mayroong suporta ng SQLite], gumagamit ng PDO)', + 'config-support-oracle' => '* Ang $1 ay isang kalipunan ng dato ng kasigasigang pangkalakal. ([http://www.php.net/manual/en/oci8.installation.php Paano magtipunan ng PHP na mayroong suporta ng OCI8])', + 'config-support-ibm_db2' => '* Ang $1 ay isang kalipunan ng dato ng kasigasigang pangkalakal.', 'config-header-mysql' => 'Mga katakdaan ng MySQL', 'config-header-postgres' => 'Mga katakdaan ng PostgreSQL', 'config-header-sqlite' => 'Mga katakdaan ng SQLite', @@ -17229,14 +17643,42 @@ Baguhin lamang ito kung alam mong kinakailangan.', 'config-missing-db-name' => 'Dapat kang magpasok ng isang halaga para sa "Pangalan ng kalipunan ng dato"', 'config-missing-db-host' => 'Dapat kang magpasok ng isang halaga para sa "Tagapagpasinaya ng kalipunan ng dato"', 'config-missing-db-server-oracle' => 'Dapat kang magpasok ng isang halaga para sa "TNS ng kalipunan ng dato"', + 'config-invalid-db-server-oracle' => 'Hindi katanggap-tanggap na pangalan ng TNSng kalipunan ng dato na "$1". +Gumamit lamang ng mga titik ng ASCII (a-z, A-Z), mga bilang (0-9), mga salungguhit (_) at mga tuldok (.).', 'config-invalid-db-name' => 'Hindi tanggap na pangalan ng kalipunan ng dato na "$1". -Gumamit lamang ng mga titik ng ASCII (a-z, A-Z), mga bilang (0-9), mga salangguhit (_) at mga gitling (-).', +Gumamit lamang ng mga titik ng ASCII (a-z, A-Z), mga bilang (0-9), mga salungguhit (_) at mga gitling (-).', 'config-invalid-db-prefix' => 'Hindi tanggap na unlapi ng kalipunan ng dato na "$1". -Gamitin lamang ang mga titik na ASCII (a-z, A-Z), mga bilang (0-9), mga salangguhit (_) at mga gitling (-).', +Gamitin lamang ang mga titik na ASCII (a-z, A-Z), mga bilang (0-9), mga salungguhit (_) at mga gitling (-).', 'config-connection-error' => '$1. Suriin ang punong-abala, pangalan ng tagagamit at hudyat na nasa ibaba at subukan ulit.', + 'config-invalid-schema' => 'Hindi katanggap-tanggap na panukala para sa "$1" ng MediaWiki. +Gumamit lamang ng mga titik ng ASCII (a-z, A-Z), mga bilang (0-9), at mga salungguhit (_).', + 'config-db-sys-create-oracle' => 'Ang panluklok ay tumatangkilik lamang sa paggamit ng isang akawnt ng SYSDBA para sa paglikha ng isang bagong akawnt.', + 'config-db-sys-user-exists-oracle' => 'Umiiral na ang akawnt ng tagagamit na "$1". Magagamit lamang ang SYSDBA para sa paglikha ng isang bagong akawnt!', 'config-postgres-old' => 'Kailangan ang PostgreSQL $1 o mas bago, mayroon kang $2.', + 'config-sqlite-name-help' => 'Pumili ng isang pangalan na pangkilala na wiki mo. +Huwag gumamit ng mga puwang o mga gitling. +Gagamitin ito para sa pangalan ng talaksan ng dato ng SQLite.', + 'config-sqlite-parent-unwritable-group' => 'Hindi malikha ang direktoryo ng dato na $1, sapagkat ang magulang na direktoryong $2 ay hindi masulatan ng tagapaghain ng kasaputan. + +Napag-alaman ng tagapagluklok kung sinong tagagamit ang kinatatakbuhan ng iyong tagapaghain ng kasaputan. +Gawing nasusulatan nito ang $3 ng direktoryo upang makapagpatuloy. +Ito ang gawin sa ibabaw ng isang sistema ng Unix/Linux: + +
    cd $2
    +mkdir $3
    +chgrp $4 $3
    +chmod g+w $3
    ', + 'config-sqlite-parent-unwritable-nogroup' => 'Hindi malikha ang direktoryo ng dato na $1, sapagkat ang magulang na direktoryong $2 ay hindi masulatan ng tagapaghain ng kasaputan. + +Hindi malaman ng tagapagluklok kung sinong tagagamit ang kinatatakbuhan ng iyong tagapaghain ng kasaputan. +Gawing nasusulatan nito (at ng mga iba pa) ang $3 ng direktoryo upang makapagpatuloy. +Ito ang gawin sa ibabaw ng isang sistema ng Unix/Linux: + +
    cd $2
    +mkdir $3
    +chmod a+w $3
    ', 'config-sqlite-mkdir-error' => 'Kamalian sa paglikha ng direktoryo ng datong "$1". Suriin ang kinalalagyan at subukang muli.', 'config-sqlite-dir-unwritable' => 'Hindi nagawang magsulat sa direktoryong "$1". @@ -17247,6 +17689,14 @@ Surrin ang direktoryo ng dato at pangalan ng kalipunan ng datong nasa ibaba at s 'config-sqlite-readonly' => 'Ang talaksang $1 ay hindi maisusulat.', 'config-sqlite-cant-create-db' => 'Hindi malikha ang talaksang $1 ng kalipunan ng dato.', 'config-sqlite-fts3-downgrade' => 'Nawawala ang suportang FTS3 ng PHP, ibinababa ang uri ng mga talahanayan', + 'config-can-upgrade' => "Mayroong mga talahanayan ng MediaWiki sa loob ng kalipunan ng datong ito. +Upang maitaas ang uri ng mga ito upang maging MediaWiki na $1, pindutin ang '''Magpatuloy'''.", + 'config-upgrade-done' => "Buo na ang pagtataas ng uri. + +Maaari mo na ngayong [$1 gamitin ang iyong wiki]. + +Kung nais mong muling likhain ang iyong talaksang LocalSettings.php, lagitikin ang pindutang nasa ibaba. +'''Hindi minumungkahi''' ito maliban na lamang kung nagkakaroon ka ng mga suliranin sa piling ng wiki mo.", 'config-upgrade-done-no-regenerate' => 'Buo na ang pagsasapanahon. Maaari ka na ngayong [$1 magsimula sa paggamit ng wiki mo].', @@ -17257,12 +17707,30 @@ Maaari ka na ngayong [$1 magsimula sa paggamit ng wiki mo].', 'config-db-web-help' => 'Piliin ang pangalan ng tagagamit at hudyat na gagamitin ng tagapaghain ng web upang umugnay sa tagapaghain ng kalipunan ng dato, habang nasa pangkaraniwang pagtakbo ng wiki.', 'config-db-web-account-same' => 'Gamitin ang gayun din akawnt katulad ng sa pagluluklok', 'config-db-web-create' => 'Likhain ang akawnt kung hindi pa ito umiiral', + 'config-db-web-no-create-privs' => 'Ang tinukoy mong akawnt na iluluklok ay walang sapat na mga pribilehiyo upang makalikha ng isang akawnt. +Ang akawnt na tutukuyin mo rito ay umiiral na dapat.', 'config-mysql-engine' => 'Makinang imbakan:', 'config-mysql-innodb' => 'InnoDB', 'config-mysql-myisam' => 'MyISAM', + 'config-mysql-myisam-dep' => "'''Babala''': Pinili mo ang MyISAM bilang makinang imbakan para sa MySQL, na hindi iminumungkahi para gamitin sa MediaWiki, sapagkat: +* bahagya lamang itong sumusuporta ng pagkakasundu-sundo dahil sa pagkakandado ng talahanayan +* mas malaki ang pagkakataon na kapitan ng sira kaysa sa ibang mga makina +* ang himpilang kodigo ng MediaWiki ay hindi palaging humahawak ng MyISAM ayon sa nararapat + +Kung ang iyong nakaluklok na MySQL ay sumusuporta ng InnoDB, higit na iminumungkahi na piliin mo iyon sa halip. +Kung ang iyong nakaluklok na MySQL ay hindi sumusuporta ng InnoDB, marahil ay panahon na para sa isang pagtataas ng uri.", + 'config-mysql-engine-help' => "Ang '''InnoDB''' ay ang halos palaging pinaka mainam na mapipili, dahil mayroon itong mabuting suporta ng pagkakasundu-sundo. + +Maaaring mas mabilis ang '''MyISAM''' sa mga pagluluklok na pang-isahang tagagamit o mababasa lamang. +May gawi ang mga kalipunan ng dato ng MyISAM na masira nang mas madalas kaysa sa mga kalipunan ng dato ng InnoDB.", 'config-mysql-charset' => 'Pangkat ng panitik ng kalipunan ng dato:', 'config-mysql-binary' => 'Binaryo', 'config-mysql-utf8' => 'UTF-8', + 'config-mysql-charset-help' => "Sa '''gawi na binaryo''', iniimbak ng MediaWiki ang tekstong UTF-8 sa kalipunan ng dato sa loob ng mga hanay na binaryo. +Mas kapaki-pakinabang ito kaysa sa gawi na UTF-8 ng MySQL, at nagpapahintulot sa iyo upang magamit ang buong kasaklawan ng mga panitik ng Unikodigo. + +Sa ''gawi na UTF-8''', malalaman ng MySQL kung sa anong pangkat ng panitik nakapaloob ang iyong dato, at angkop na makakapagharap at makapapagpalit nito, subalit hindi ka nito papayagan na mag-imbak ng mga panitik na nasa itaas ng [//en.wikipedia.org/wiki/Mapping_of_Unicode_character_planes Basic Multilingual Plane] o Saligang Tapyas na Pangmaramihang Wika.", + 'config-ibm_db2-low-db-pagesize' => "Ang kalipunan mo ng dato na DB2 ay mayroong isang likas na nakatakdang puwang ng talahanayan na mayroong hindi sapat na sukat ng pahina. Ang sukat ng pahina ay dapat na maging '''32K''' o mas mataas.", 'config-site-name' => 'Pangalan ng wiki:', 'config-site-name-help' => "Lilitaw ito sa bareta ng pamagat ng pantingin-tingin at sa samu't saring ibang mga lugar.", 'config-site-name-blank' => 'Magpasok ng isang pangalan ng sityo.', @@ -17271,10 +17739,19 @@ Maaari ka na ngayong [$1 magsimula sa paggamit ng wiki mo].', 'config-ns-site-name' => 'Katulad ng sa pangalan ng wiki: $1', 'config-ns-other' => 'Iba pa (tukuyin)', 'config-ns-other-default' => 'Wiki Ko', + 'config-project-namespace-help' => 'Bilang pagsunod sa halimbawa ng Wikipedia, maraming mga wiki ang nagpapanatili ng kanilang mga pahina ng patakaran na nakahiwalay magmula sa kanilang mga pahina ng nilalaman, na nasa loob ng isang "\'\'\'puwang na pampangalan ng proyekto\'\'\'". +Ang lahat ng mga pamagat ng pahina na nasa loob ng puwang ng pangalang ito ay nagsisimula na mayroong isang partikular na unlapi, na maaari mong tukuyin dito. +Sa nakaugalian, ang unlaping ito ay hinango mula sa pangalan ng wiki, subalit hindi ito maaaring maglaman ng mga panitik ng palabantasan na katulad ng "#" o ":".', + 'config-ns-invalid' => 'Ang tinukoy na puwang ng pangalan na "$1" ay hindi katanggap-tanggap. +Tumukoy ng isang ibang puwang ng pangalan ng proyekto.', + 'config-ns-conflict' => 'Ang tinukoy na puwang ng pangalan na "$1" ay sumasalungat sa isang likas na nakatakdang puwang ng pangalan ng MediaWiki. +Tumukoy ng isang ibang puwang ng pangalan ng proyekto.', 'config-admin-box' => 'Akawnt ng tagapangasiwa', 'config-admin-name' => 'Pangalan mo:', 'config-admin-password' => 'Hudyat:', 'config-admin-password-confirm' => 'Hudyat uli:', + 'config-admin-help' => 'Ipasok dito ang mas ninanais mong pangalan ng tagagamit, bilang halimbawa na ang "Joe Bloggs". +Ito ang pangalang gagamitin mo upang lumagdang papasok sa wiki.', 'config-admin-name-blank' => 'Magpasok ng isang pangalan ng tagagamit na tagapangasiwa.', 'config-admin-name-invalid' => 'Ang tinukoy na pangalan ng tagagamit na "$1" ay hindi tanggap. Tumukoy ng ibang pangalan ng tagagamit.', @@ -17282,10 +17759,13 @@ Tumukoy ng ibang pangalan ng tagagamit.', 'config-admin-password-same' => 'Ang hudyat ay hindi dapat na katulad ng pangalan ng tagagamit.', 'config-admin-password-mismatch' => 'Hindi magkatugma ang ipinasok mong dalawang mga hudyat.', 'config-admin-email' => 'Tirahan ng e-liham:', + 'config-admin-email-help' => 'Magpasok dito ng isang tirahan ng e-liham upang mapahintulutan kang makatanggap ng e-liham mula sa iba pang mga tagagamit sa ibabaw ng wiki, itakdang muli ang hudyat mo, at mapabatiran ng mga pagbabago sa mga pahinang nasa ibabaw ng iyong tala ng mga binabantayan. Maiiwanan mo na walang laman ang hanay na ito.', 'config-admin-error-user' => 'Panloob na kamalian kapag nililikha ang isang tagapangasiwa na may pangalang "$1".', 'config-admin-error-password' => 'Panloob na kamalian kapag nagtatakda ng isang hudyat na para sa tagapangasiwang "$1":
    $2
    ', 'config-admin-error-bademail' => 'Nagpasok ka ng isang hindi katanggap-tanggap na tirahan ng e-liham.', 'config-subscribe' => 'Tumanggap mula sa [https://lists.wikimedia.org/mailman/listinfo/mediawiki-announce talaan ng mga pinadadalhan ng mga nilalabas na mga pabatid].', + 'config-subscribe-help' => 'Isang itong tala ng pagliliham na mababa ang dami na ginagamit para sa pagpapakawala ng mga pahayag, kabilang na ang mahahalagang mga pahayag na pangkatiwasayan. Dapat kang magpasipi nito at isapanahon ang iyong nakaluklok na MediaWiki kapag lumalabas ang bagong mga bersiyon.', + 'config-subscribe-noemail' => 'Sinubukan mong magpasipi sa tala ng nililihaman ng pagpapakawala ng mga pahayag na hindi nagbibigay ng isang tirahan ng -eliham. Paki magbigay ng isang tirahan ng e-liham kung nais mong magpasipi sa listahan ng pagliliham.', 'config-almost-done' => 'Halos tapos ka na! Maaari mo ngayong laktawan ang natitira pang pag-aayos at iluklok na ang wiki ngayon.', 'config-optional-continue' => 'Magtanong sa akin ng marami pang mga tanong.', @@ -17295,14 +17775,41 @@ Maaari mo ngayong laktawan ang natitira pang pag-aayos at iluklok na ang wiki ng 'config-profile-no-anon' => 'Kailangan ang paglikha ng akawnt', 'config-profile-fishbowl' => 'Pinahintulutang mga patnugot lamang', 'config-profile-private' => 'Pribadong wiki', + 'config-profile-help' => "Pinaka mahusay ang pagtakbo ng mga Wiki kapag pinapahintulutan mo ang pinaka maraming mga tao na makapamatnugot ng mga ito hanggang sa maaari. +Sa loob ng MediaWiki, maginhawang masusuring muli ang kamakailang mga pagbabago, at mapanauli sa dati ang anumang nasira na nagawa ng isang walang muwang o may masamang hangarin na mga tagagamit. + +Subalit, marami ang nakatagpo na nagagamit ang MediaWiki sa loob ng malawak na sari-saring mga gampanin, at kung minsan ay hindi madaling makumbinsi ang lahat ng mga tao hinggil sa kapakinabangan ng kaparaanan ng wiki. +Kung kaya't nasa iyo ang pagpili. + +Ang isang '''{{int:config-profile-wiki}}''' ay nagpapahintulot sa sinuman upang makapagbago, na hindi kailangan ang paglagdang papasok. +Ang isang wiki na mayroong '''{{int:config-profile-no-anon}}''' ay nagbibigay ng karagdagang pananagutan, subalit maaaring pumigil sa nagkataon lamang na mga tagapag-ambag. + +Ang tagpo na '''{{int:config-profile-fishbowl}}''' ay nagpapahintulot lamang sa pinayagang mga tagagamit na makatingin ng mga pahina, na kapiling ang pangkat na pinayagang makapamatnugot. +Ang isang '''{{int:config-profile-private}}''' ay nagpapahintulot lamang sa pinayagang mga tagagamit na makatingin ng mga pahina, na kapiling ang pangkat na pinayagang makapamatnugot. + +Ang mas masasalimuot na mga kaayusan ng mga karapatan ng tagagamit ay makukuha pagkaraan ng pagluluklok, tingnan ang [//www.mediawiki.org/wiki/Manual:User_rights may kaugnayang kinamay na lahok].", 'config-license' => 'Karapatang-ari at lisensiya:', 'config-license-none' => 'Walang talababa ng lisensiya', 'config-license-cc-by-sa' => 'Malikhaing Pangkaraniwang Pagtukoy Pamamahaging Magkatulad', + 'config-license-cc-by' => 'Atribusyon ng Creative Commons', 'config-license-cc-by-nc-sa' => 'Malikhaing Pangkaraniwang Pagtukoy Hindi-Pangkalakal Pamamahaging Magkatulad', + 'config-license-cc-0' => 'Sero na Creative Commons (Nasasakop ng Madla)', + 'config-license-gfdl' => 'Lisensiyang 1.3 ng Malayang Dokumentasyon ng GNU o mas lalong huli', 'config-license-pd' => 'Nasasakupan ng Madla', 'config-license-cc-choose' => 'Pumili ng isang pasadyang Lisensiya ng Malikhaing mga Pangkaraniwan', + 'config-license-help' => "Maraming mga pangmadlang wiki ang naglalagay ng lahat ng mga ambag sa ilalim ng [http://freedomdefined.org/Definition lisensiyang malaya]. +Nakakatulong ito sa paglikha ng isang diwa ng pagmamay-ari ng pamayanan at nakapanghihikayat ng ambag na pangmahabang panahon. +Sa pangkalahatan, hindi kailangan ang isang wiking pribado o pangsamahan. + +Kung nais mong magamit ang teksto magmula sa Wikipedia, at nais mong makatanggap ang Wikipedia ng tekstong kinopya magmula sa wiki mo, dapat mong piliin ang '''Creative Commons Attribution Share Alike''' (Pagbanggit na Pinagsasaluhang Magkatulad ng Malikhaing Pangkaraniwan). + +Dating ginamit ng Wikipedia ang Lisensiya ng Kasulatang Malaya ng GNU (GNU Free Documentation License o GFDL). +Isang katanggap-tanggap na lisensiya ang GFDL, subalit mahirap itong maunawaan. +Mahirap din ang paggamit na muli ng nilalaman na nasa ilalim ng GFDL.", 'config-email-settings' => 'Mga katakdaan ng e-liham', 'config-enable-email' => 'Paganahin ang palabas na e-liham', + 'config-enable-email-help' => 'Kung nais mong gumana ang e-liham, ang mga katakdaan ng liham ng [http://www.php.net/manual/en/mail.configuration.php PHP] ay kailangang maging wasto ang pagkakaayos. +Kung ayaw mo nang anumang mga katampukan ng e-liham, maaari mong huwag paganahin ang mga ito rito.', 'config-email-user' => 'Paganahin ang tagagamit-sa-tagagamit na e-liham', 'config-email-user-help' => 'Payagan ang lahat ng mga tagagamit na magpadala ng e-liham sa bawat isa kapag pinagana nila ito sa kanilang mga nais.', 'config-email-usertalk' => 'Paganahin ang pabatid na pampahina ng usapan ng tagagamit', @@ -17310,31 +17817,67 @@ Maaari mo ngayong laktawan ang natitira pang pag-aayos at iluklok na ang wiki ng 'config-email-watchlist' => 'Paganahin ang pabatid ng talaan ng bantayan', 'config-email-watchlist-help' => 'Payagan ang mga tagagamit na tumanggap ng mga pabatid tungkol sa kanilang binabantayang mga pahina kapag pinagana nila ito sa kanilang mga nais.', 'config-email-auth' => 'Paganahin ang pagpapatunay ng e-liham', + 'config-email-auth-help' => "Kapag pinagagana ang mapipiling ito, dapat tiyakin ng mga tagagamit ang kanilang tirahan ng e-liham na ginagamit ang isang kawing na ipinadala sa kanila tuwing itinatakda o binabago nila ito. +Tanging napatunayang mga tirahan ng e-liham lamang ang makakatanggap ng mga e-liham magmula sa ibang mga tagagamit o makakapagbago ng mga e-liham ng pagpapabatid. +'''Iminumungkahi''' ang mapipiling katakdaan na ito para sa mga wiking pangmadla dahil sa maaaring mangyaring pagmamalabis ng mga katampukan ng e-liham.", 'config-email-sender' => 'Pabalik na tirahan ng e-liham:', + 'config-email-sender-help' => 'Ipasok ang tirahan ng e-liham na gagamitin bilang tirahang pagsasaulian ng e-liham na papalabas. +Dito ang kung saan ipapadala ang mga pagtalbog. +Maraming mga tagapaghain ng liham ang nangangailangan ng kahit na bahagi lamang ng pangalan ng nasasakupan upang maging katanggap-tanggap.', 'config-upload-settings' => 'Mga pagkakarga ng mga larawan at talaksan', 'config-upload-enable' => 'Paganahin ang pagkakarga ng talaksan', + 'config-upload-help' => 'Ang paitaas na mga pagkakarga ng mga talaksan ay maaaring makapaglantad ng iyong tagapaghain sa mga panganib na pangkatiwasayan. +Para sa mas marami pang kabatiran, basahin ang [//www.mediawiki.org/wiki/Manual:Security seksiyon ng katiwasayan] sa loob ng gabay. + +Upang mapagana ang paitaas na mga pagkakarga ng talaksan, baguhin ang gawi roon sa subdirektoryo ng mga imahe sa ilalim ng ugat na direktoryo ng MediaWiki upang ang tagapaghain ng kasaputan ay makapagsulat dito. +Pagkaraan ay paganahin ang pipiliing ito.', 'config-upload-deleted' => 'Direktoryo para sa binurang mga talaksan:', 'config-upload-deleted-help' => 'Pumili ng isang direktoryong pagsusupnayan ng naburang mga talaksan. Ideyal na dapat itong hindi mapupuntahan mula sa web.', 'config-logo' => 'URL ng logo:', + 'config-logo-help' => 'Ang likas na nakatakdang pabalat ng MediaWiki ay nagsasama ng puwang para sa isang logong 135x160 ang piksel na nasa itaas ng menu ng panggilid na bareta. +Magkargang papaitaas ng isang imahe na mayroong naaangkop na sukat, at ipasok dito ang URL. + +Kung ayaw mo ng isang logo, iwanang walang laman ang kahong ito.', 'config-instantcommons' => 'Paganahin ang Mga Pangkaraniwang Biglaan', + 'config-instantcommons-help' => 'Ang [//www.mediawiki.org/wiki/InstantCommons Instant Commons] ay isang tampok na nagpapahintulot sa mga wiki upang gumamit ng mga imahe, mga tunog at iba pang mga midyang matatagpuan sa pook ng [//commons.wikimedia.org/ Wikimedia Commons]. +Upang magawa ito, nangangailangan ang MediaWiki ng pagka nakakapunta sa Internet. + +Para sa mas marami pang kabatiran hinggil sa tampok na ito, kabilang na ang mga tagubilin sa kung paano ito itakda para sa mga wiki na bukod pa kaysa sa Wikimedia Commons, sumangguni sa [//mediawiki.org/wiki/Manual:$wgForeignFileRepos gabay].', 'config-cc-error' => 'Hindi nagbigay ng resulta ang pampili ng lisensiya ng Malikhaing Pangkaraniwan. Ipasok na kinakamay ang pangalan ng lisensiya.', 'config-cc-again' => 'Pumili uli...', 'config-cc-not-chosen' => 'Piliin kung anong lisensiya ng Malikhaing mga Pangkaraniwan ang nais mo at pindutin ang "magpatuloy".', 'config-advanced-settings' => 'Mas masulong na pagkakaayos', 'config-cache-options' => 'Mga katakdaan para sa pagtatago ng bagay:', + 'config-cache-help' => 'Ang pagtatago ng bagay ay ginagamit upang mapainam ang tulin ng MediaWiki sa pamamagitan ng pagtatago ng madalas gamiting dato. +Ang mga pook na bahagya hanggang malalaki ang sukat ay labis na hinihikayat na paganahin ito, at ang mga pook na maliliit ay makakakita rin ng mga kapakinabangan.', + 'config-cache-none' => 'Walang pagtatago (tinanggal ang katungkulan, subalit maaaring maapektuhan ang tulin sa mas malalaking mga pook ng wiki)', + 'config-cache-accel' => 'Pagtatago ng bagay ng PHP (APC, XCache o WinCache)', + 'config-cache-memcached' => 'Gamitin ang Pagtatago sa Alaala (Memcached) (nangangailangan ng karagdagang kaayusan ng pagkakahanda at pagsasaayos)', 'config-memcached-servers' => 'Mga tagapaghaing itinago sa alaala:', + 'config-memcached-help' => 'Listahan ng mga tirahan ng IP na gagamitin para sa Memcached o Itinagong Alaala. +Dapat na tukuyin na isa sa bawat guhit at tukuyin ang daungang gagamitin. Bilang halimbawa: + 127.0.0.1:11211 + 192.168.1.25:1234', 'config-memcache-needservers' => 'Pinili mo ang Memcached bilang uri mo ng taguan ngunit hindi tumukoy ng anumang mga tagapaghain.', 'config-memcache-badip' => 'Nagpasok ka ng isang hindi tanggap na tirahan ng IP para sa Memcached: $1.', 'config-memcache-noport' => 'Hindi ka tumukoy ng isang daungan na gagamitin para sa tagapaghain ng Memcached: $1. Kung hindi mo alam ang daungan, ang likas na nakatakda ay 11211.', 'config-memcache-badport' => 'Ang bilang ng daungan ng Memcached ay dapat na nasa pagitan ng $1 at $2.', 'config-extensions' => 'Mga dugtong', + 'config-extensions-help' => 'Ang mga dugtong na nakalista sa ibabaw ay napansin sa loob ng iyong direktoryo ng ./extensions. + +Maaaring mangailangan ang mga ito ng karagdagang kaayusan, subalit mapapagana mo ngayon ang mga ito', + 'config-install-alreadydone' => "'''Babala:''' Tila nailuklok mo na ang MediaWiki at tinatangka mong iluklok ito ulit. +Paki magpatuloy sa susunod na pahina.", + 'config-install-begin' => 'Sa pamamagitan ng pagpindot sa "{{int:config-continue}}", sisimulan mo ang pagluluklok ng MediaWiki. +Kung nais mo paring gumawa ng mga pagbabago, paki pindutin ang bumalik.', 'config-install-step-done' => 'nagawa na', 'config-install-step-failed' => 'nabigo', 'config-install-extensions' => 'Isinasama ang mga karugtong', 'config-install-database' => 'Inihahanda ang kalipunan ng dato', + 'config-install-schema' => 'Nililikha ang panukala', 'config-install-pg-schema-not-exist' => 'Hindi umiiral ang panukala ng PostgreSQL.', 'config-install-pg-schema-failed' => 'Nabigo ang paglikha ng mga talahanayan. Tiyakin na ang tagagamit na "$1" ay maaaring makasulat sa balangkas na "$2".', @@ -17342,11 +17885,17 @@ Tiyakin na ang tagagamit na "$1" ay maaaring makasulat sa balangkas na "$2".', 'config-install-pg-plpgsql' => 'Sumusuri ng wikang PL/pgSQL', 'config-pg-no-plpgsql' => 'Kailangan mong magtalaga ng wikang PL/pgSQL sa loob ng kalipunan ng datong $1', 'config-pg-no-create-privs' => 'Ang tinukoy mong akawnt para sa pagtatalaga ay walang sapat na mga pribilehiyo upang makalikha ng isang akawnt.', + 'config-pg-not-in-role' => 'Umiiral na ang akawnt na tinukoy mo para sa tagagamit ng sangkasaputan. +Ang tinukoy mong akawnt para sa pagluluklok ay hindi isang tagagamit na super at hindi isang kasapi sa gampanin ng tagagamit ng sangkasaputan, kung kaya\'t hindi nito nagawang makalikha ng mga bagay na pag-aari ng tagagamit ng sangkasaputan. + +Sa kasalukuyan, nangangailangan ang MediaWiki na ang mga talahanayan ay maging pag-aari ng tagagamit ng sangkasaputan. Paki tumukoy ng isa pang pangalan ng akawnt na pangsangkasaputan, o pindutin ang "bumalik" at tumukoy ng isang tagagamit na may kaangkupang pribilehiyo ng pagluluklok.', 'config-install-user' => 'Nililikha ang tagagamit ng kalipunan ng dato', 'config-install-user-alreadyexists' => 'Umiiral na ang tagagamit na "$1"', 'config-install-user-create-failed' => 'Nabigo ang paglikha ng tagagamit na "$1": $2', 'config-install-user-grant-failed' => 'Nabigo ang pagbibigay ng pahintulot sa tagagamit na "$1": $2', 'config-install-user-missing' => 'Hindi umiiral ang tinukoy na tagagamit na si "$1".', + 'config-install-user-missing-create' => 'Hindi umiiral ang tinukoy na tagagamit na si "$1". +Paki lagitikin ang nasa ibabang kahong natsetsekan na "likhain ang akawnt" kung nais mong likhain ito.', 'config-install-tables' => 'Nililikha ang mga talahanayan', 'config-install-tables-exist' => "'''Babala''': Tila umiiral na ang mga talahanayan ng MediaWiki. Nilalaktawan ang paglikha.", @@ -17357,6 +17906,7 @@ Nilalaktawan ang paglikha.", Nilalaktawan ang likas na nakatakdang talaan.", 'config-install-stats' => 'Sinisimulan ang estadistika', 'config-install-keys' => 'Ginagawa ang lihim na mga susi', + 'config-insecure-keys' => "'''Babala:''' Nalikha ang {{PLURAL:$2|A secure key|ligtas na mga susi}} ($1) habang ang pagluluklok {{PLURAL:$2|ay|ay}} hindi pa lubos na ligtas. Isaalang-alang ang kinakamay na pagbago {{PLURAL:$2|nito|ng mga ito}}.", 'config-install-sysop' => 'Nililikha ang akawnt ng tagagamit na tagapangasiwa', 'config-install-subscribe-fail' => 'Hindi nagawang magpasipi mula sa mediawiki-announce: $1', 'config-install-subscribe-notpossible' => 'Hindi nakalagak ang cURL at hindi makukuha ang allow_url_fopen', @@ -17380,6 +17930,7 @@ $3 Kapag nagawa na iyan, maaari ka nang '''[$2 pumasok sa wiki mo]'''.", 'config-download-localsettings' => 'Ikargang paibaba ang LocalSettings.php', 'config-help' => 'saklolo', + 'config-nofile' => 'Hindi matagpuan ang talaksang "$1". Binura na ba ito?', 'mainpagetext' => "'''Matagumpay na ininstala ang MediaWiki.'''", 'mainpagedocfooter' => "Silipin ang [//meta.wikimedia.org/wiki/Help:Contents Patnubay sa Tagagamit] (''\"User's Guide\"'') para sa kaalaman sa paggamit ng wiking ''software''. @@ -17390,7 +17941,15 @@ Kapag nagawa na iyan, maaari ka nang '''[$2 pumasok sa wiki mo]'''.", * [https://lists.wikimedia.org/mailman/listinfo/mediawiki-announce Tala ng mga pinadadalhan ng liham ng MediaWiki]", ); -/** Turkish (Türkçe) */ +/** толышә зывон (толышә зывон) + * @author Erdemaslancan + */ +$messages['tly'] = array( + 'config-page-options' => 'Кукон', +); + +/** Turkish (Türkçe) + */ $messages['tr'] = array( 'mainpagetext' => "'''MediaWiki başarı ile kuruldu.'''", 'mainpagedocfooter' => 'Viki yazılımının kullanımı hakkında bilgi almak için [//meta.wikimedia.org/wiki/Help:Contents kullanıcı rehberine] bakınız. @@ -17427,7 +17986,7 @@ $messages['tt-latn'] = array( * [https://lists.wikimedia.org/mailman/listinfo/mediawiki-announce MediaWiki'nıñ yaña versiäläre turında xäbärlär yazdırıp alu].", ); -/** Udmurt (Удмурт) +/** Udmurt (удмурт) * @author Andrewboltachev */ $messages['udm'] = array( @@ -17497,7 +18056,7 @@ $1', 'config-sidebar' => '* [//www.mediawiki.org Сайт MediaWiki] * [//www.mediawiki.org/wiki/Help:Contents/uk Керівництво користувача] * [//www.mediawiki.org/wiki/Manual:Contents/uk Керівництво адміністратора] -* [//www.mediawiki.org/wiki/Manual:FAQ/uk FAQ]', +* [//www.mediawiki.org/wiki/Manual:FAQ/uk FAQ]', # Fuzzy 'config-env-good' => 'Перевірку середовища успішно завершено. Ви можете встановити MediaWiki.', 'config-env-bad' => 'Було проведено перевірку середовища. Ви не можете встановити MediaWiki.', @@ -17587,7 +18146,8 @@ $messages['ur'] = array( 'mainpagetext' => "'''میڈیاوکی کو کامیابی سے چالو کردیا گیا ہے۔.'''", ); -/** Uzbek (Oʻzbekcha) */ +/** Uzbek (oʻzbekcha) + */ $messages['uz'] = array( 'mainpagetext' => "'''MediaWiki muvaffaqiyatli o'rnatildi.'''", 'mainpagedocfooter' => "Wiki dasturini ishlatish haqida ma'lumot olish uchun [//meta.wikimedia.org/wiki/Help:Contents Foydalanuvchi qo'llanmasi] sahifasiga murojaat qiling. @@ -17615,7 +18175,7 @@ I seguenti cołegamenti i xé en łengua inglese: * [https://lists.wikimedia.org/mailman/listinfo/mediawiki-announce Mailing list anunsi MediaWiki]", ); -/** Veps (Vepsän kel’) +/** Veps (vepsän kel’) * @author Игорь Бродский */ $messages['vep'] = array( @@ -17650,7 +18210,8 @@ $messages['vi'] = array( * [https://lists.wikimedia.org/mailman/listinfo/mediawiki-announce Danh sách gửi thư về việc phát hành MediaWiki]', ); -/** Volapük (Volapük) */ +/** Volapük (Volapük) + */ $messages['vo'] = array( 'mainpagetext' => "'''El MediaWiki pestiton benosekiko.'''", 'mainpagedocfooter' => 'Konsultolös [//meta.wikimedia.org/wiki/Help:Contents Gebanageidian] ad tuvön nünis dö geb programema vükik. @@ -17662,7 +18223,8 @@ $messages['vo'] = array( * [https://lists.wikimedia.org/mailman/listinfo/mediawiki-announce Potalised tefü fomams nulik ela MediaWiki]', ); -/** Võro (Võro) */ +/** Võro (Võro) + */ $messages['vro'] = array( 'mainpagetext' => "'''MediaWiki tarkvara paika säet.'''", 'mainpagedocfooter' => 'Vikitarkvara pruukmisõ kotsilõ loeq mano: @@ -17692,7 +18254,8 @@ $messages['war'] = array( * [https://lists.wikimedia.org/mailman/listinfo/mediawiki-announce MediaWiki release mailing list]", ); -/** Wolof (Wolof) */ +/** Wolof (Wolof) + */ $messages['wo'] = array( 'mainpagetext' => "'''Campug MediaWiki gi sotti na . '''", 'mainpagedocfooter' => 'Saytul [//meta.wikimedia.org/wiki/Ndimbal:Ndefu Gindikaayu jëfandikukat bi] ngir yeneeni xibaar ci jëfandiku gu tëriin gi. @@ -17717,7 +18280,7 @@ $messages['wuu'] = array( * [https://lists.wikimedia.org/mailman/listinfo/mediawiki-announce MediaWiki 发布邮件列表]', ); -/** Kalmyk (Хальмг) +/** Kalmyk (хальмг) * @author Huuchin */ $messages['xal'] = array( @@ -17765,7 +18328,8 @@ $messages['yo'] = array( * [https://lists.wikimedia.org/mailman/listinfo/mediawiki-announce MediaWiki release mailing list]", ); -/** Cantonese (粵語) */ +/** Cantonese (粵語) + */ $messages['yue'] = array( 'mainpagetext' => "'''MediaWiki已經裝好。'''", 'mainpagedocfooter' => '參閱[//meta.wikimedia.org/wiki/Help:Contents 用戶指引](英),裏面有資料講點用wiki軟件。 @@ -17776,7 +18340,8 @@ $messages['yue'] = array( * [https://lists.wikimedia.org/mailman/listinfo/mediawiki-announce MediaWiki 發佈郵件名單](英)', ); -/** Zeeuws (Zeêuws) */ +/** Zeeuws (Zeêuws) + */ $messages['zea'] = array( 'mainpagetext' => "'''De installaotie van MediaWiki is geslaegd.'''", 'mainpagedocfooter' => "Raedpleeg de [//meta.wikimedia.org/wiki/ZEA_Ulpe:Inhoudsopgaeve andleidieng] voe informatie over 't gebruuk van de wikisoftware. @@ -17788,12 +18353,13 @@ $messages['zea'] = array( * [https://lists.wikimedia.org/mailman/listinfo/mediawiki-announce Mailienglieste voe ankondigiengen van nieuwe versies]", ); -/** Simplified Chinese (‪中文(简体)‬) +/** Simplified Chinese (中文(简体)‎) * @author Hydra * @author Hzy980512 * @author Liangent * @author PhiLiP * @author Xiaomingyan + * @author Yfdyh000 * @author 阿pp */ $messages['zh-hans'] = array( @@ -18221,6 +18787,7 @@ $3 当本步骤完成后,您可以 '''[$2 进入您的wiki]'''。", 'config-download-localsettings' => '下载LocalSettings.php', 'config-help' => '帮助', + 'config-nofile' => '找不到文件“$1”。它是否已被删除?', 'mainpagetext' => "'''已成功安装MediaWiki。'''", 'mainpagedocfooter' => '请查阅[//meta.wikimedia.org/wiki/Help:Contents 用户指南]以获取使用本wiki软件的信息! @@ -18230,7 +18797,7 @@ $3 * [https://lists.wikimedia.org/mailman/listinfo/mediawiki-announce MediaWiki发布邮件列表]', ); -/** Traditional Chinese (‪中文(繁體)‬) +/** Traditional Chinese (中文(繁體)‎) * @author Hzy980512 * @author Liangent * @author Mark85296341 @@ -18307,6 +18874,7 @@ $1', 'config-no-db' => '找不到合適的數據庫驅動!您需要為PHP安裝數據庫驅動。目前支持以下數據庫:$1。 如果您正在使用共享主機,請向您的主機提供商申請安裝合適的數據庫驅動。如果您通過自行編譯安裝的PHP,請對其進行重新配置以啟用數據庫客戶端,例如使用./configure --with-mysql。如果您通過Debian或Ubuntu包安裝的PHP,您還需要安裝php5-mysql模塊。', + 'config-outdated-sqlite' => "'''警告''':您已安裝SQLite $1,但是它的版本低於最低要求版本$2。因此您無法選擇SQLite。", 'config-no-fts3' => "'''警告''':已編譯的SQLite不包含[//sqlite.org/fts3.html FTS3模塊],後台搜索功能將不可用。", 'config-register-globals' => "'''警告:PHP的[http://php.net/register_globals register_globals]選項被啟用。請盡量禁用該功能,'''雖然不會影響MediaWiki的運行,但您的服務器會被暴露給潛在的安全漏洞。", 'config-magic-quotes-runtime' => "'''致命錯誤:[http://www.php.net/manual/en/ref.info.php#ini.magic-quotes-runtime magic_quotes_runtime]被啟用!''' @@ -18323,11 +18891,13 @@ $1', 'config-pcre-no-utf8' => "'''致命錯誤''':PHP的PCRE模塊在編譯時可能沒有包含PCRE_UTF8支持。MediaWiki需要UTF-8支持才能正常工作。", 'config-memory-raised' => 'PHP的內存使用上限memory_limit為$1,自動提升到$2。', 'config-memory-bad' => "'''警告:'''PHP的內存使用上限memory_limit為$1。該設定可能過低,並導致安裝失敗!", + 'config-ctype' => "'''毀滅性錯誤''':PHP必須有[http://www.php.net/manual/en/ctype.installation.php Ctype 擴展]來支持編譯。", 'config-xcache' => '[http://xcache.lighttpd.net/ XCache]已安裝', 'config-apc' => '[http://www.php.net/apc APC]已安裝', 'config-wincache' => '[http://www.iis.net/download/WinCacheForPhp WinCache]已安裝', 'config-no-cache' => "'''警告:'''找不到[http://www.php.net/apc APC]、[http://xcache.lighttpd.net/ XCache]或[http://www.iis.net/download/WinCacheForPhp WinCache],無法啟用對象緩存。 Object caching is not enabled.", + 'config-mod-security' => "'''警告''':您的服務器已啟動[http://modsecurity.org/ mod_security]。若其配置錯誤, 會導致MediaWiki和其他軟件的錯誤並允許用戶任意發布內容。如果您遇到任何錯誤,請查閱[http://modsecurity.org/documentation/ mod_security文檔]或聯繫您的客服。", 'config-diff3-bad' => '找不到GNU diff3。', 'config-imagemagick' => '已找到ImageMagick:$1。如果你啟用了上傳功能,縮略圖功能也將被啟用。', 'config-gd' => '已找到內建的GD圖形庫。如果你啟用了上傳功能,縮略圖功能也將被啟用。', @@ -18343,6 +18913,13 @@ Object caching is not enabled.", 'config-suhosin-max-value-length' => 'Suhosin已經安裝並將GET請求的參數長度限制在$1字節。MediaWiki的ResourceLoader部件可以在此限制下正常工作,但其性能會被降低。如果可能,請在php.ini中將suhosin.get.max_value_length設為1024或更高值,並在LocalSettings.php中將$wgResourceLoaderMaxQueryLength設為同一值。', 'config-db-type' => '資料庫類型:', 'config-db-host' => '資料庫主機:', + 'config-db-host-help' => '如果您的數據庫在別的服務器上,請在這裡輸入它的域名或IP地址。 + +如果您在使用共享網站套餐,您的網站商應該已在他們的控制面板中給您數據庫信息了。 + +如果您在Windows中安裝並且使用MySQL,“localhost”可能無效。如果確實無效,請輸入“127.0.0.1”作為IP地址。 + +如果您在使用PostgreSQL,並且要用Unix socket來連接,請留空。', 'config-db-host-oracle' => '資料庫的 TNS:', 'config-db-host-oracle-help' => '請輸入合法的[http://download.oracle.com/docs/cd/B28359_01/network.111/b28317/tnsnames.htm 本地連接名],並確保tnsnames.ora文件對本安裝程序可見。
    如果您使用的客戶端庫為10g或更新的版本,您還可以使用[http://download.oracle.com/docs/cd/E11882_01/network.112/e10836/naming.htm 簡單連接名方法](easy connect naming method)。', 'config-db-wiki-settings' => '識別這個 Wiki', diff --git a/includes/installer/MysqlUpdater.php b/includes/installer/MysqlUpdater.php index 82de913618..3f1dad9f2e 100644 --- a/includes/installer/MysqlUpdater.php +++ b/includes/installer/MysqlUpdater.php @@ -209,7 +209,6 @@ class MysqlUpdater extends DatabaseUpdater { array( 'modifyField', 'user_former_groups', 'ufg_group', 'patch-ufg_group-length-increase.sql' ), // 1.20 - array( 'addTable', 'config', 'patch-config.sql' ), array( 'addIndex', 'revision', 'page_user_timestamp', 'patch-revision-user-page-index.sql' ), array( 'addField', 'ipblocks', 'ipb_parent_block_id', 'patch-ipb-parent-block-id.sql' ), array( 'addIndex', 'ipblocks', 'ipb_parent_block_id', 'patch-ipb-parent-block-id-index.sql' ), diff --git a/includes/installer/OracleUpdater.php b/includes/installer/OracleUpdater.php index f946d59a96..5523470e1f 100644 --- a/includes/installer/OracleUpdater.php +++ b/includes/installer/OracleUpdater.php @@ -67,7 +67,6 @@ class OracleUpdater extends DatabaseUpdater { array( 'modifyField', 'user_former_groups', 'ufg_group', 'patch-ufg_group-length-increase.sql' ), //1.20 - array( 'addTable', 'config', 'patch-config.sql' ), array( 'addIndex', 'ipblocks', 'i05', 'patch-ipblocks_i05_index.sql' ), array( 'addIndex', 'revision', 'i05', 'patch-revision_i05_index.sql' ), array( 'dropField', 'category', 'cat_hidden', 'patch-cat_hidden.sql' ), diff --git a/includes/installer/PostgresUpdater.php b/includes/installer/PostgresUpdater.php index 2942c0b7f7..5a13d4211d 100644 --- a/includes/installer/PostgresUpdater.php +++ b/includes/installer/PostgresUpdater.php @@ -89,7 +89,6 @@ class PostgresUpdater extends DatabaseUpdater { array( 'addTable', 'module_deps', 'patch-module_deps.sql' ), array( 'addTable', 'uploadstash', 'patch-uploadstash.sql' ), array( 'addTable', 'user_former_groups','patch-user_former_groups.sql' ), - array( 'addTable', 'config', 'patch-config.sql' ), array( 'addTable', 'external_user', 'patch-external_user.sql' ), # Needed before new field @@ -155,6 +154,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 +231,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/installer/SqliteUpdater.php b/includes/installer/SqliteUpdater.php index c3f7a81674..2fa3f31c76 100644 --- a/includes/installer/SqliteUpdater.php +++ b/includes/installer/SqliteUpdater.php @@ -88,7 +88,6 @@ class SqliteUpdater extends DatabaseUpdater { array( 'modifyField', 'user_former_groups', 'ufg_group', 'patch-ug_group-length-increase.sql' ), // 1.20 - array( 'addTable', 'config', 'patch-config.sql' ), array( 'addIndex', 'revision', 'page_user_timestamp', 'patch-revision-user-page-index.sql' ), array( 'addField', 'ipblocks', 'ipb_parent_block_id', 'patch-ipb-parent-block-id.sql' ), array( 'addIndex', 'ipblocks', 'ipb_parent_block_id', 'patch-ipb-parent-block-id-index.sql' ), diff --git a/includes/job/JobQueue.php b/includes/job/JobQueue.php index 6409cffc41..21ef6d34e1 100644 --- a/includes/job/JobQueue.php +++ b/includes/job/JobQueue.php @@ -26,11 +26,12 @@ * Class to handle enqueueing and running of background jobs * * @ingroup JobQueue - * @since 1.20 + * @since 1.21 */ 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,16 +39,23 @@ 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'; } /** * Get a job queue object of the specified type. * $params includes: - * class : what job class to use (determines job type) + * 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 @@ -80,7 +88,10 @@ abstract class JobQueue { } /** - * @return bool Quickly check if the queue is empty + * Quickly check if the queue is empty. + * Queue classes should use caching if they are any slower without memcached. + * + * @return bool */ final public function isEmpty() { wfProfileIn( __METHOD__ ); diff --git a/includes/job/JobQueueDB.php b/includes/job/JobQueueDB.php index bea4a6f69a..223ef41fe8 100644 --- a/includes/job/JobQueueDB.php +++ b/includes/job/JobQueueDB.php @@ -25,10 +25,10 @@ * Class to handle job queues stored in the DB * * @ingroup JobQueue - * @since 1.20 + * @since 1.21 */ class JobQueueDB extends JobQueue { - const CACHE_TTL = 30; // integer; seconds + const CACHE_TTL = 300; // integer; seconds const MAX_JOB_RANDOM = 2147483647; // 2^31 - 1; used for job_random /** @@ -97,7 +97,7 @@ class JobQueueDB extends JobQueue { $dbw->setFlag( $autoTrx ? DBO_TRX : 0 ); // restore automatic begin() } - $wgMemc->set( $key, 'false', $ttl ); + $wgMemc->set( $key, 'false', $ttl ); // queue is not empty } ); } @@ -111,48 +111,53 @@ class JobQueueDB extends JobQueue { protected function doPop() { global $wgMemc; - $uuid = wfRandomString( 32 ); // pop attempt + if ( $wgMemc->get( $this->getEmptinessCacheKey() ) === 'true' ) { + return false; // queue is empty + } $dbw = $this->getMasterDB(); $dbw->commit( __METHOD__, 'flush' ); // flush existing transaction + $uuid = wfRandomString( 32 ); // pop attempt $job = false; // job popped off $autoTrx = $dbw->getFlag( DBO_TRX ); // automatic begin() enabled? $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 + // Try to reserve a row in the DB... + if ( $this->order === 'timestamp' ) { // oldest first + $row = $this->claimOldest( $uuid ); + } 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 + $row = $this->claimRandom( $uuid, $rand, $gte ); + if ( !$row ) { // need to try the other direction + $row = $this->claimRandom( $uuid, $rand, !$gte ); } - $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 { + } + // Check if we found a row to reserve... + if ( !$row ) { $wgMemc->set( $this->getEmptinessCacheKey(), 'true', self::CACHE_TTL ); + break; // nothing to do + } + // 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__ ); + wfIncrStats( 'job-pop' ); + 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__ + ); + wfIncrStats( 'job-pop', $dbw->affectedRows() ); } break; // done } while( true ); @@ -167,51 +172,105 @@ class JobQueueDB extends JobQueue { /** * Reserve a row with a single UPDATE without holding row locks over RTTs... + * * @param $uuid string 32 char hex string * @param $rand integer Random unsigned integer (31 bits) * @param $gte bool Search for job_random >= $random (otherwise job_random <= $random) - * @return integer Number of affected rows + * @return Row|false */ - protected function claim( $uuid, $rand, $gte ) { + protected function claimRandom( $uuid, $rand, $gte ) { $dbw = $this->getMasterDB(); $dir = $gte ? 'ASC' : 'DESC'; $ineq = $gte ? '>=' : '<='; - if ( $dbw->getType() === 'mysql' ) { - // Per http://bugs.mysql.com/bug.php?id=6980, we can't use subqueries on the - // same table being changed in an UPDATE query in MySQL (gives Error: 1093). - // Oracle and Postgre have no such limitation. However, MySQL offers an - // alternative here by supporting ORDER BY + LIMIT for UPDATE queries. - // The DB wrapper functions do not support this, so it's done manually. - $dbw->query( "UPDATE {$dbw->tableName( 'job' )} - SET - job_token = {$dbw->addQuotes( $uuid ) }, - job_token_timestamp = {$dbw->addQuotes( $dbw->timestamp() )} - WHERE ( - job_cmd = {$dbw->addQuotes( $this->type )} - AND job_token = {$dbw->addQuotes( '' )} - AND job_random {$ineq} {$dbw->addQuotes( $rand )} - ) ORDER BY job_random {$dir} LIMIT 1", - __METHOD__ - ); - } else { - // Use a subquery to find the job, within an UPDATE to claim it. - // This uses as much of the DB wrapper functions as possible. - $dbw->update( 'job', - array( 'job_token' => $uuid, 'job_token_timestamp' => $dbw->timestamp() ), - array( 'job_id = (' . - $dbw->selectSQLText( 'job', 'job_id', - array( - 'job_cmd' => $this->type, - 'job_token' => '', - "job_random {$ineq} {$dbw->addQuotes( $rand )}" ), - __METHOD__, - array( 'ORDER BY' => "job_random {$dir}", 'LIMIT' => 1 ) ) . - ')' - ), - __METHOD__ + + $row = false; // the row acquired + // This uses a replication safe method for acquiring jobs. One could use UPDATE+LIMIT + // instead, but that either uses ORDER BY (in which case it deadlocks in MySQL) or is + // not replication safe. Due to http://bugs.mysql.com/bug.php?id=6980, subqueries cannot + // be used here with MySQL. + do { + $row = $dbw->selectRow( 'job', '*', // find a random job + array( + 'job_cmd' => $this->type, + 'job_token' => '', + "job_random {$ineq} {$dbw->addQuotes( $rand )}" ), + __METHOD__, + array( 'ORDER BY' => "job_random {$dir}" ) ); - } - return $dbw->affectedRows(); + if ( $row ) { // claim the job + $dbw->update( 'job', // update by PK + array( 'job_token' => $uuid, 'job_token_timestamp' => $dbw->timestamp() ), + array( 'job_cmd' => $this->type, 'job_id' => $row->job_id, 'job_token' => '' ), + __METHOD__ + ); + // This might get raced out by another runner when claiming the previously + // selected row. The use of job_random should minimize this problem, however. + if ( !$dbw->affectedRows() ) { + $row = false; // raced out + } + } else { + break; // nothing to do + } + } while ( !$row ); + + return $row; + } + + /** + * Reserve a row with a single UPDATE without holding row locks over RTTs... + * + * @param $uuid string 32 char hex string + * @return Row|false + */ + protected function claimOldest( $uuid ) { + $dbw = $this->getMasterDB(); + + $row = false; // the row acquired + do { + if ( $dbw->getType() === 'mysql' ) { + // Per http://bugs.mysql.com/bug.php?id=6980, we can't use subqueries on the + // same table being changed in an UPDATE query in MySQL (gives Error: 1093). + // Oracle and Postgre have no such limitation. However, MySQL offers an + // alternative here by supporting ORDER BY + LIMIT for UPDATE queries. + $dbw->query( "UPDATE {$dbw->tableName( 'job' )} + SET + job_token = {$dbw->addQuotes( $uuid ) }, + job_token_timestamp = {$dbw->addQuotes( $dbw->timestamp() )} + WHERE ( + job_cmd = {$dbw->addQuotes( $this->type )} + AND job_token = {$dbw->addQuotes( '' )} + ) ORDER BY job_random ASC LIMIT 1", + __METHOD__ + ); + } else { + // Use a subquery to find the job, within an UPDATE to claim it. + // This uses as much of the DB wrapper functions as possible. + $dbw->update( 'job', + array( 'job_token' => $uuid, 'job_token_timestamp' => $dbw->timestamp() ), + array( 'job_id = (' . + $dbw->selectSQLText( 'job', 'job_id', + array( 'job_cmd' => $this->type, 'job_token' => '' ), + __METHOD__, + array( 'ORDER BY' => 'job_random ASC', 'LIMIT' => 1 ) ) . + ')' + ), + __METHOD__ + ); + } + // Fetch any row that we just reserved... + if ( $dbw->affectedRows() ) { + $row = $dbw->selectRow( 'job', '*', + array( 'job_cmd' => $this->type, 'job_token' => $uuid ), __METHOD__ + ); + if ( !$row ) { // raced out by duplicate job removal + wfDebugLog( 'JobQueueDB', "Row deleted as duplicate by another process." ); + } + } else { + break; // nothing to do + } + } while ( !$row ); + + return $row; } /** @@ -220,10 +279,7 @@ class JobQueueDB extends JobQueue { */ protected function doAck( Job $job ) { $dbw = $this->getMasterDB(); - if ( $dbw->trxLevel() ) { - wfWarn( "Attempted to ack a job in a transaction; committing first." ); - $dbw->commit(); // push existing transaction - } + $dbw->commit( __METHOD__, 'flush' ); // flush existing transaction $autoTrx = $dbw->getFlag( DBO_TRX ); // automatic begin() enabled? $dbw->clearFlag( DBO_TRX ); // make each query its own transaction @@ -274,12 +330,17 @@ 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' ), 'job_timestamp' => $dbw->timestamp(), 'job_sha1' => wfBaseConvert( sha1( serialize( $descFields ) ), 16, 36, 32 ), - 'job_random' => mt_rand( 0, self::MAX_JOB_RANDOM ) + 'job_random' => $random ); return ( $descFields + $metaFields ); } diff --git a/includes/job/JobQueueGroup.php b/includes/job/JobQueueGroup.php index 69bcf011be..48f27469e5 100644 --- a/includes/job/JobQueueGroup.php +++ b/includes/job/JobQueueGroup.php @@ -25,7 +25,7 @@ * Class to handle enqueueing of background jobs * * @ingroup JobQueue - * @since 1.20 + * @since 1.21 */ class JobQueueGroup { /** @var Array */ @@ -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 ); } /** @@ -157,4 +153,17 @@ class JobQueueGroup { return array_diff( $this->getQueueTypes(), $wgJobTypesExcludedFromDefaultQueue ); } + + /** + * @return Array List of job types that have non-empty queues + */ + public function getQueuesWithJobs() { + $types = array(); + foreach ( $this->getQueueTypes() as $type ) { + if ( !$this->get( $type )->isEmpty() ) { + $types[] = $type; + } + } + return $types; + } } diff --git a/includes/job/jobs/DoubleRedirectJob.php b/includes/job/jobs/DoubleRedirectJob.php index b1b96b62ab..ddd4fcca15 100644 --- a/includes/job/jobs/DoubleRedirectJob.php +++ b/includes/job/jobs/DoubleRedirectJob.php @@ -94,7 +94,7 @@ class DoubleRedirectJob extends Job { return true; } $content = $targetRev->getContent(); - $currentDest = $content->getRedirectTarget(); + $currentDest = $content ? $content->getRedirectTarget() : null; if ( !$currentDest || !$currentDest->equals( $this->redirTitle ) ) { wfDebug( __METHOD__.": Redirect has changed since the job was queued\n" ); return true; diff --git a/includes/job/jobs/NullJob.php b/includes/job/jobs/NullJob.php new file mode 100644 index 0000000000..eef3bf7888 --- /dev/null +++ b/includes/job/jobs/NullJob.php @@ -0,0 +1,58 @@ +params['lives'] ) ) { + $this->params['lives'] = 1; + } + if ( !isset( $this->params['usleep'] ) ) { + $this->params['usleep'] = 0; + } + } + + public function run() { + if ( $this->params['usleep'] > 0 ) { + usleep( $this->params['usleep'] ); + } + if ( $this->params['lives'] > 1 ) { + $params = $this->params; + $params['lives']--; + $job = new self( $this->title, $params ); + $job->insert(); + } + return true; + } +} diff --git a/includes/job/jobs/RefreshLinksJob.php b/includes/job/jobs/RefreshLinksJob.php index a29f29fe64..384244fbad 100644 --- a/includes/job/jobs/RefreshLinksJob.php +++ b/includes/job/jobs/RefreshLinksJob.php @@ -70,18 +70,17 @@ class RefreshLinksJob extends Job { } public static function runForTitleInternal( Title $title, Revision $revision, $fname ) { - global $wgContLang; + wfProfileIn( $fname ); + $content = $revision->getContent( Revision::RAW ); - wfProfileIn( $fname . '-parse' ); - $options = ParserOptions::newFromUserAndLang( new User, $wgContLang ); - $content = $revision->getContent(); - $parserOutput = $content->getParserOutput( $title, $revision->getId(), $options, false ); - wfProfileOut( $fname . '-parse' ); + if ( !$content ) { + // if there is no content, pretend the content is empty + $content = $revision->getContentHandler()->makeEmptyContent(); + } - wfProfileIn( $fname . '-update' ); - $updates = $content->getSecondaryDataUpdates( $title, null, false, $parserOutput ); + $updates = $content->getSecondaryDataUpdates( $title, null, false ); DataUpdate::runUpdates( $updates ); - wfProfileOut( $fname . '-update' ); + wfProfileOut( $fname ); } } diff --git a/includes/json/Services_JSON.php b/includes/json/Services_JSON.php index 398ed6a28f..2566072dba 100644 --- a/includes/json/Services_JSON.php +++ b/includes/json/Services_JSON.php @@ -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. diff --git a/includes/logging/LogFormatter.php b/includes/logging/LogFormatter.php index 7d94a30bd4..8c1e294b3e 100644 --- a/includes/logging/LogFormatter.php +++ b/includes/logging/LogFormatter.php @@ -293,6 +293,28 @@ class LogFormatter { } break; + case 'rights': + if ( count( $parameters['4::oldgroups'] ) ) { + $oldgroups = implode( ', ', $parameters['4::oldgroups'] ); + } else { + $oldgroups = wfMessage( 'rightsnone' )->inContentLanguage()->escaped(); + } + if ( count( $parameters['5::newgroups'] ) ) { + $newgroups = implode( ', ', $parameters['5::newgroups'] ); + } else { + $newgroups = wfMessage( 'rightsnone' )->inContentLanguage()->escaped(); + } + switch( $entry->getSubtype() ) { + case 'rights': + $text = wfMessage( 'rightslogentry' ) + ->rawParams( $target, $oldgroups, $newgroups )->inContentLanguage()->escaped(); + break; + case 'autopromote': + $text = wfMessage( 'rightslogentry-autopromote' ) + ->rawParams( $target, $oldgroups, $newgroups )->inContentLanguage()->escaped(); + break; + } + break; // case 'suppress' --private log -- aaron (sign your messages so we know who to blame in a few years :-D) // default: @@ -1009,3 +1031,88 @@ class NewUsersLogFormatter extends LogFormatter { return array(); } } + +/** + * This class formats rights log entries. + * @since 1.21 + */ +class RightsLogFormatter extends LogFormatter { + protected function makePageLink( Title $title = null, $parameters = array() ) { + global $wgContLang, $wgUserrightsInterwikiDelimiter; + + if ( !$this->plaintext ) { + $text = $wgContLang->ucfirst( $title->getText() ); + $parts = explode( $wgUserrightsInterwikiDelimiter, $text, 2 ); + + if ( count( $parts ) === 2 ) { + $titleLink = WikiMap::foreignUserLink( $parts[1], $parts[0], + htmlspecialchars( $title->getPrefixedText() ) ); + + if ( $titleLink !== false ) { + return $titleLink; + } + } + } + + return parent::makePageLink( $title, $parameters ); + } + + protected function getMessageKey() { + $key = parent::getMessageKey(); + $params = $this->getMessageParameters(); + if ( !isset( $params[3] ) && !isset( $params[4] ) ) { + $key .= '-legacy'; + } + return $key; + } + + protected function getMessageParameters() { + $params = parent::getMessageParameters(); + + // Really old entries + if ( !isset( $params[3] ) && !isset( $params[4] ) ) { + return $params; + } + + $oldGroups = $params[3]; + $newGroups = $params[4]; + + // Less old entries + if ( $oldGroups === '' ) { + $oldGroups = array(); + } elseif ( is_string( $oldGroups ) ) { + $oldGroups = array_map( 'trim', explode( ',', $oldGroups ) ); + } + if ( $newGroups === '' ) { + $newGroups = array(); + } elseif ( is_string( $newGroups ) ) { + $newGroups = array_map( 'trim', explode( ',', $newGroups ) ); + } + + $userName = $this->entry->getTarget()->getText(); + if ( !$this->plaintext && count( $oldGroups ) ) { + foreach ( $oldGroups as &$group ) { + $group = User::getGroupMember( $group, $userName ); + } + } + if ( !$this->plaintext && count( $newGroups ) ) { + foreach ( $newGroups as &$group ) { + $group = User::getGroupMember( $group, $userName ); + } + } + + $lang = $this->context->getLanguage(); + if ( count( $oldGroups ) ) { + $params[3] = $lang->listToText( $oldGroups ); + } else { + $params[3] = $this->msg( 'rightsnone' )->text(); + } + if ( count( $newGroups ) ) { + $params[4] = $lang->listToText( $newGroups ); + } else { + $params[4] = $this->msg( 'rightsnone' )->text(); + } + + return $params; + } +} diff --git a/includes/logging/LogPage.php b/includes/logging/LogPage.php index 90393ea8d6..07238a053a 100644 --- a/includes/logging/LogPage.php +++ b/includes/logging/LogPage.php @@ -253,29 +253,6 @@ class LogPage { } else { $titleLink = self::getTitleLink( $type, $langObjOrNull, $title, $params ); - if( preg_match( '/^rights\/(rights|autopromote)/', $key ) ) { - $rightsnone = wfMessage( 'rightsnone' )->inLanguage( $langObj )->text(); - - if( $skin ) { - $username = $title->getText(); - foreach ( $params as &$param ) { - $groupArray = array_map( 'trim', explode( ',', $param ) ); - foreach( $groupArray as &$group ) { - $group = User::getGroupMember( $group, $username ); - } - $param = $wgLang->listToText( $groupArray ); - } - } - - if( !isset( $params[0] ) || trim( $params[0] ) == '' ) { - $params[0] = $rightsnone; - } - - if( !isset( $params[1] ) || trim( $params[1] ) == '' ) { - $params[1] = $rightsnone; - } - } - if( count( $params ) == 0 ) { $rv = wfMessage( $wgLogActions[$key] )->rawParams( $titleLink )->inLanguage( $langObj )->escaped(); } else { @@ -350,8 +327,6 @@ class LogPage { * @return String */ protected static function getTitleLink( $type, $lang, $title, &$params ) { - global $wgContLang, $wgUserrightsInterwikiDelimiter; - if( !$lang ) { return $title->getPrefixedText(); } @@ -388,20 +363,6 @@ class LogPage { . Linker::userToolLinks( $id, $title->getText(), false, Linker::TOOL_LINKS_NOBLOCK ); } break; - case 'rights': - $text = $wgContLang->ucfirst( $title->getText() ); - $parts = explode( $wgUserrightsInterwikiDelimiter, $text, 2 ); - - if ( count( $parts ) == 2 ) { - $titleLink = WikiMap::foreignUserLink( $parts[1], $parts[0], - htmlspecialchars( $title->getPrefixedText() ) ); - - if ( $titleLink !== false ) { - break; - } - } - $titleLink = Linker::link( Title::makeTitle( NS_USER, $text ) ); - break; case 'merge': $titleLink = Linker::link( $title, diff --git a/includes/media/SVG.php b/includes/media/SVG.php index 75d474c0ab..53716df6b9 100644 --- a/includes/media/SVG.php +++ b/includes/media/SVG.php @@ -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'; } diff --git a/includes/objectcache/MemcachedPeclBagOStuff.php b/includes/objectcache/MemcachedPeclBagOStuff.php index 76886ebb18..7793710ede 100644 --- a/includes/objectcache/MemcachedPeclBagOStuff.php +++ b/includes/objectcache/MemcachedPeclBagOStuff.php @@ -107,8 +107,11 @@ class MemcachedPeclBagOStuff extends MemcachedBagOStuff { * @return Mixed */ public function get( $key ) { + wfProfileIn( __METHOD__ ); $this->debugLog( "get($key)" ); - return $this->checkResult( $key, parent::get( $key ) ); + $value = $this->checkResult( $key, parent::get( $key ) ); + wfProfileOut( __METHOD__ ); + return $value; } /** @@ -224,9 +227,11 @@ class MemcachedPeclBagOStuff extends MemcachedBagOStuff { * @return Array */ public function getMulti( array $keys ) { + wfProfileIn( __METHOD__ ); $this->debugLog( 'getMulti(' . implode( ', ', $keys ) . ')' ); $callback = array( $this, 'encodeKey' ); $result = $this->client->getMulti( array_map( $callback, $keys ) ); + wfProfileOut( __METHOD__ ); return $this->checkResult( false, $result ); } diff --git a/includes/parser/LinkHolderArray.php b/includes/parser/LinkHolderArray.php index 49160e8a71..9f1fff22de 100644 --- a/includes/parser/LinkHolderArray.php +++ b/includes/parser/LinkHolderArray.php @@ -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. diff --git a/includes/parser/Parser.php b/includes/parser/Parser.php index 8671665ffc..9dad1e5be9 100644 --- a/includes/parser/Parser.php +++ b/includes/parser/Parser.php @@ -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('/(?:mUniqPrefix.'-pre|<\\/li|<\\/ul|<\\/ol|<\\/?center)/iS', $t ); + 'mUniqPrefix.'-pre|<\\/li|<\\/ul|<\\/ol|<\\/dl|<\\/?center)/iS', $t ); if ( $openmatch or $closematch ) { $paragraphStack = false; # TODO bug 5718: paragraph closed @@ -3617,7 +3617,7 @@ class Parser { if ( $rev ) { $content = $rev->getContent(); - $text = $content->getWikitextForTransclusion(); + $text = $content ? $content->getWikitextForTransclusion() : null; if ( $text === false || $text === null ) { $text = false; diff --git a/includes/parser/ParserOutput.php b/includes/parser/ParserOutput.php index b6bcf63264..28d07f1479 100644 --- a/includes/parser/ParserOutput.php +++ b/includes/parser/ParserOutput.php @@ -346,7 +346,45 @@ class ParserOutput extends CacheTime { } /** - * Set a property to be cached in the DB + * Set a property to be stored in the page_props database table. + * + * page_props is a key value store indexed by the page ID. This allows + * the parser to set a property on a page which can then be quickly + * retrieved given the page ID or via a DB join when given the page + * title. + * + * setProperty() is thus used to propagate properties from the parsed + * page to request contexts other than a page view of the currently parsed + * article. + * + * Some applications examples: + * + * * To implement hidden categories, hiding pages from category listings + * by storing a property. + * + * * Overriding the displayed article title. + * @see ParserOutput::setDisplayTitle() + * + * * To implement image tagging, for example displaying an icon on an + * image thumbnail to indicate that it is listed for deletion on + * Wikimedia Commons. + * This is not actually implemented, yet but would be pretty cool. + * + * Do not use setProperty() to set a property which is only used in a + * context where the ParserOutput object itself is already available, for + * example a normal page view. There is no need to save such a property + * in the database since it the text is already parsed. You can just hook + * OutputPageParserOutput and get your data out of the ParserOutput object. + * + * If you are writing an extension where you want to set + * a property in the parser which is used by an OutputPageParserOutput hook, + * just use a custom variable within the ParserOutput object: + * + * @par Example: + * @code + * $parser->getOutput()->my_ext_foo = '...'; + * @endcode + * */ public function setProperty( $name, $value ) { $this->mProperties[$name] = $value; diff --git a/includes/parser/Preprocessor_DOM.php b/includes/parser/Preprocessor_DOM.php index b2dd7db1a1..53f3febc27 100644 --- a/includes/parser/Preprocessor_DOM.php +++ b/includes/parser/Preprocessor_DOM.php @@ -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. diff --git a/includes/resourceloader/ResourceLoader.php b/includes/resourceloader/ResourceLoader.php index 670586383d..b4bd98cd8e 100644 --- a/includes/resourceloader/ResourceLoader.php +++ b/includes/resourceloader/ResourceLoader.php @@ -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. diff --git a/includes/resourceloader/ResourceLoaderWikiModule.php b/includes/resourceloader/ResourceLoaderWikiModule.php index 28c3426c33..1e61a3e846 100644 --- a/includes/resourceloader/ResourceLoaderWikiModule.php +++ b/includes/resourceloader/ResourceLoaderWikiModule.php @@ -77,10 +77,16 @@ abstract class ResourceLoaderWikiModule extends ResourceLoaderModule { } $content = $revision->getContent( Revision::RAW ); + + if ( !$content ) { + wfDebug( __METHOD__ . "failed to load content of JS/CSS page!\n" ); + return null; + } + $model = $content->getModel(); if ( $model !== CONTENT_MODEL_CSS && $model !== CONTENT_MODEL_JAVASCRIPT ) { - wfDebug( __METHOD__ . "bad content model #$model for JS/CSS page!\n" ); + wfDebug( __METHOD__ . "bad content model $model for JS/CSS page!\n" ); return null; } diff --git a/includes/search/SearchEngine.php b/includes/search/SearchEngine.php index f8f5fa59f6..ec542a612d 100644 --- a/includes/search/SearchEngine.php +++ b/includes/search/SearchEngine.php @@ -795,7 +795,7 @@ class SearchResult { //TODO: if we could plug in some code that knows about special content models *and* about // special features of the search engine, the search could benefit. $content = $this->mRevision->getContent(); - $this->mText = $content->getTextForSearchIndex(); + $this->mText = $content ? $content->getTextForSearchIndex() : ''; } else { // TODO: can we fetch raw wikitext for commons images? $this->mText = ''; } diff --git a/includes/site/MediaWikiSite.php b/includes/site/MediaWikiSite.php index 716f14494a..0d5db11dc0 100644 --- a/includes/site/MediaWikiSite.php +++ b/includes/site/MediaWikiSite.php @@ -52,9 +52,8 @@ class MediaWikiSite extends SiteObject { * @note : This actually makes an API request to the remote site, so beware that this function is slow and depends * on an external service. * - * @note : If MW_PHPUNIT_TEST is defined or $egWBRemoteTitleNormalization is set to false, the call to the - * external site is skipped, and the title is normalized using the local normalization rules as - * implemented by the Title class. + * @note : If MW_PHPUNIT_TEST is defined, the call to the external site is skipped, and the title + * is normalized using the local normalization rules as implemented by the Title class. * * @see Site::normalizePageName * @@ -66,7 +65,6 @@ class MediaWikiSite extends SiteObject { * @throws MWException */ public function normalizePageName( $pageName ) { - global $egWBRemoteTitleNormalization; // Check if we have strings as arguments. if ( !is_string( $pageName ) ) { diff --git a/includes/site/SiteObject.php b/includes/site/SiteObject.php index 6470c86e0d..0c6aeb39b8 100644 --- a/includes/site/SiteObject.php +++ b/includes/site/SiteObject.php @@ -157,10 +157,23 @@ class SiteObject extends ORMRow implements Site { $path = $this->getLinkPath(); if ( $path === false ) { - return false; + return ''; + } + + $protocol = parse_url( $path, PHP_URL_SCHEME ); + + // Malformed URL + if ( $protocol === false ) { + throw new MWException( "failed to parse URL $path" ); + } + + // No schema + if ( $protocol === null ) { + // Used for protocol relative URLs + $protocol = ''; } - return parse_url( $path, PHP_URL_SCHEME ); + return $protocol; } /** diff --git a/includes/site/SitesTable.php b/includes/site/SitesTable.php index a03c5989fe..bb12740d77 100644 --- a/includes/site/SitesTable.php +++ b/includes/site/SitesTable.php @@ -95,6 +95,7 @@ class SitesTable extends ORMTable { 'forward' => false, 'config' => array(), + 'language' => 'en', // XXX: can we default to '' instead? ); } diff --git a/includes/specials/SpecialCachedPage.php b/includes/specials/SpecialCachedPage.php index 949ac35145..ddd11ad03d 100644 --- a/includes/specials/SpecialCachedPage.php +++ b/includes/specials/SpecialCachedPage.php @@ -119,7 +119,7 @@ abstract class SpecialCachedPage extends SpecialPage implements ICacheHelper { * * @since 1.20 * - * @param function $computeFunction + * @param callable $computeFunction * @param array|mixed $args * @param string|null $key * @@ -137,7 +137,7 @@ abstract class SpecialCachedPage extends SpecialPage implements ICacheHelper { * * @since 1.20 * - * @param function $computeFunction + * @param callable $computeFunction * @param array $args * @param string|null $key */ diff --git a/includes/specials/SpecialChangePassword.php b/includes/specials/SpecialChangePassword.php index 41b3b2558f..54a277183b 100644 --- a/includes/specials/SpecialChangePassword.php +++ b/includes/specials/SpecialChangePassword.php @@ -27,6 +27,9 @@ * @ingroup SpecialPage */ class SpecialChangePassword extends UnlistedSpecialPage { + + protected $mUserName, $mOldpass, $mNewpass, $mRetype, $mDomain; + public function __construct() { parent::__construct( 'ChangePassword' ); } @@ -105,6 +108,9 @@ class SpecialChangePassword extends UnlistedSpecialPage { $this->getOutput()->redirect( $titleObj->getFullURL() ); } + /** + * @param $msg string + */ function error( $msg ) { $this->getOutput()->addHTML( Xml::element('p', array( 'class' => 'error' ), $msg ) ); } @@ -170,6 +176,10 @@ class SpecialChangePassword extends UnlistedSpecialPage { ); } + /** + * @param $fields array + * @return string + */ function pretty( $fields ) { $out = ''; foreach ( $fields as $list ) { @@ -234,7 +244,7 @@ class SpecialChangePassword extends UnlistedSpecialPage { try { $user->setPassword( $this->mNewpass ); wfRunHooks( 'PrefsPasswordAudit', array( $user, $newpass, 'success' ) ); - $this->mNewpass = $this->mOldpass = $this->mRetypePass = ''; + $this->mNewpass = $this->mOldpass = $this->mRetype = ''; } catch( PasswordError $e ) { wfRunHooks( 'PrefsPasswordAudit', array( $user, $newpass, 'error' ) ); throw new PasswordError( $e->getMessage() ); diff --git a/includes/specials/SpecialDeletedContributions.php b/includes/specials/SpecialDeletedContributions.php index c880b61759..bdeb7fef95 100644 --- a/includes/specials/SpecialDeletedContributions.php +++ b/includes/specials/SpecialDeletedContributions.php @@ -135,7 +135,10 @@ class DeletedContribsPager extends IndexPager { function formatRow( $row ) { wfProfileIn( __METHOD__ ); + $page = Title::makeTitle( $row->ar_namespace, $row->ar_title ); + $rev = new Revision( array( + 'title' => $page, 'id' => $row->ar_rev_id, 'comment' => $row->ar_comment, 'user' => $row->ar_user, @@ -145,8 +148,6 @@ class DeletedContribsPager extends IndexPager { 'deleted' => $row->ar_deleted, ) ); - $page = Title::makeTitle( $row->ar_namespace, $row->ar_title ); - $undelete = SpecialPage::getTitleFor( 'Undelete' ); $logs = SpecialPage::getTitleFor( 'Log' ); @@ -260,7 +261,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; diff --git a/includes/specials/SpecialEmailuser.php b/includes/specials/SpecialEmailuser.php index 4d875e6ef9..9a42c0959e 100644 --- a/includes/specials/SpecialEmailuser.php +++ b/includes/specials/SpecialEmailuser.php @@ -139,7 +139,8 @@ class SpecialEmailUser extends UnlistedSpecialPage { $this->mTargetObj = $ret; $form = new HTMLForm( $this->getFormFields(), $this->getContext() ); - $form->addPreText( $this->msg( 'emailpagetext' )->parse() ); + // By now we are supposed to be sure that $this->mTarget is a user name + $form->addPreText( $this->msg( 'emailpagetext', $this->mTarget )->parse() ); $form->setSubmitTextMsg( 'emailsend' ); $form->setTitle( $this->getTitle() ); $form->setSubmitCallback( array( __CLASS__, 'uiSubmit' ) ); diff --git a/includes/specials/SpecialLinkSearch.php b/includes/specials/SpecialLinkSearch.php index 0810ee777a..5de60769bd 100644 --- a/includes/specials/SpecialLinkSearch.php +++ b/includes/specials/SpecialLinkSearch.php @@ -103,7 +103,7 @@ class LinkSearchPage extends QueryPage { ) ); } - $s .= Xml::submitButton( $this->msg( 'linksearch-ok' )->text() ) . + $s .= Xml::submitButton( $this->msg( 'linksearch-ok' )->text() ) . '' . Xml::closeElement( 'form' ); $out->addHTML( $s ); diff --git a/includes/specials/SpecialListusers.php b/includes/specials/SpecialListusers.php index 8b448281c5..ea598c3687 100644 --- a/includes/specials/SpecialListusers.php +++ b/includes/specials/SpecialListusers.php @@ -153,7 +153,7 @@ class UsersPager extends AlphabeticPager { $userName = $row->user_name; $ulinks = Linker::userLink( $row->user_id, $userName ); - $ulinks .= Linker::userToolLinks( $row->user_id, $userName ); + $ulinks .= Linker::userToolLinksRedContribs( $row->user_id, $userName, intval( $row->edits ) ); $lang = $this->getLanguage(); diff --git a/includes/specials/SpecialMergeHistory.php b/includes/specials/SpecialMergeHistory.php index bc9a3d90f8..85e1d656cb 100644 --- a/includes/specials/SpecialMergeHistory.php +++ b/includes/specials/SpecialMergeHistory.php @@ -380,6 +380,7 @@ class SpecialMergeHistory extends SpecialPage { if ( $redirectContent ) { $redirectPage = WikiPage::factory( $targetTitle ); $redirectRevision = new Revision( array( + 'title' => $targetTitle, 'page' => $this->mTargetID, 'comment' => $comment, 'content' => $redirectContent ) ); diff --git a/includes/specials/SpecialMovepage.php b/includes/specials/SpecialMovepage.php index af3dbf3e44..ce2633fd19 100644 --- a/includes/specials/SpecialMovepage.php +++ b/includes/specials/SpecialMovepage.php @@ -464,8 +464,6 @@ class MovePageForm extends UnlistedSpecialPage { DoubleRedirectJob::fixRedirects( 'move', $ot, $nt ); } - wfRunHooks( 'SpecialMovepageAfterMove', array( &$this, &$ot, &$nt ) ); - $out = $this->getOutput(); $out->setPageTitle( $this->msg( 'pagemovedsub' ) ); @@ -484,6 +482,8 @@ class MovePageForm extends UnlistedSpecialPage { $newLink )->params( $oldText, $newText )->parseAsBlock() ); $out->addWikiMsg( $msgName ); + wfRunHooks( 'SpecialMovepageAfterMove', array( &$this, &$ot, &$nt ) ); + # Now we move extra pages we've been asked to move: subpages and talk # pages. First, if the old page or the new page is a talk page, we # can't move any talk pages: cancel that. diff --git a/includes/specials/SpecialPasswordReset.php b/includes/specials/SpecialPasswordReset.php index 97f0037eaf..d7cf693c25 100644 --- a/includes/specials/SpecialPasswordReset.php +++ b/includes/specials/SpecialPasswordReset.php @@ -255,7 +255,7 @@ class SpecialPasswordReset extends FormSpecialPage { $title = $this->msg( 'passwordreset-emailtitle' ); - $this->result = $firstUser->sendMail( $title->escaped(), $this->email->escaped() ); + $this->result = $firstUser->sendMail( $title->escaped(), $this->email->text() ); // Blank the email if the user is not supposed to see it if( !isset( $data['Capture'] ) || !$data['Capture'] ) { diff --git a/includes/specials/SpecialRecentchanges.php b/includes/specials/SpecialRecentchanges.php index 2bd8b0a96d..f542640252 100644 --- a/includes/specials/SpecialRecentchanges.php +++ b/includes/specials/SpecialRecentchanges.php @@ -382,7 +382,7 @@ class SpecialRecentChanges extends IncludableSpecialPage { $invert = $opts['invert']; $associated = $opts['associated']; - $fields = array( $dbr->tableName( 'recentchanges' ) . '.*' ); // all rc columns + $fields = RecentChange::selectFields(); // JOIN on watchlist for users if ( $uid ) { $tables[] = 'watchlist'; diff --git a/includes/specials/SpecialRecentchangeslinked.php b/includes/specials/SpecialRecentchangeslinked.php index 40ebc2fe4f..4db89586f8 100644 --- a/includes/specials/SpecialRecentchangeslinked.php +++ b/includes/specials/SpecialRecentchangeslinked.php @@ -93,7 +93,7 @@ class SpecialRecentchangeslinked extends SpecialRecentChanges { $dbkey = $title->getDBkey(); $tables = array( 'recentchanges' ); - $select = array( $dbr->tableName( 'recentchanges' ) . '.*' ); + $select = RecentChange::selectFields(); $join_conds = array(); $query_options = array(); diff --git a/includes/specials/SpecialSearch.php b/includes/specials/SpecialSearch.php index 6c33bb8040..7c8ff84c4e 100644 --- a/includes/specials/SpecialSearch.php +++ b/includes/specials/SpecialSearch.php @@ -684,11 +684,21 @@ class SpecialSearch extends SpecialPage { } } - wfProfileOut( __METHOD__ ); - return "
  • {$link} {$redirect} {$section}
    {$extract}\n" . - "
    {$score}{$size} - {$date}{$related}
    " . - "
  • \n"; + $html = null; + + if ( wfRunHooks( 'ShowSearchHit', array ( + $this, $result, $terms, + &$link, &$redirect, &$section, &$extract, + &$score, &$size, &$date, &$related, + &$html + ) ) ) { + $html = "
  • {$link} {$redirect} {$section}
    {$extract}\n" . + "
    {$score}{$size} - {$date}{$related}
    " . + "
  • \n"; + } + wfProfileOut( __METHOD__ ); + return $html; } /** diff --git a/includes/specials/SpecialSpecialpages.php b/includes/specials/SpecialSpecialpages.php index e973ddc89d..1e7c8bb565 100644 --- a/includes/specials/SpecialSpecialpages.php +++ b/includes/specials/SpecialSpecialpages.php @@ -66,7 +66,11 @@ class SpecialSpecialpages extends UnlistedSpecialPage { if( !isset( $groups[$group] ) ) { $groups[$group] = array(); } - $groups[$group][$page->getDescription()] = array( $page->getTitle(), $page->isRestricted(), $page->isExpensive() ); + $groups[$group][$page->getDescription()] = array( + $page->getTitle(), + $page->isRestricted(), + $page->isCached() + ); } } @@ -88,15 +92,14 @@ class SpecialSpecialpages extends UnlistedSpecialPage { } private function outputPageList( $groups ) { - global $wgMiserMode; $out = $this->getOutput(); $includesRestrictedPages = false; $includesCachedPages = false; foreach ( $groups as $group => $sortedPages ) { - $middle = ceil( count( $sortedPages )/2 ); $total = count( $sortedPages ); + $middle = ceil( $total / 2 ); $count = 0; $out->wrapWikiMsg( "

    $1

    \n", "specialpages-group-$group" ); @@ -107,10 +110,10 @@ class SpecialSpecialpages extends UnlistedSpecialPage { Html::openElement( 'ul' ) . "\n" ); foreach( $sortedPages as $desc => $specialpage ) { - list( $title, $restricted, $expensive) = $specialpage; + list( $title, $restricted, $cached ) = $specialpage; $pageClasses = array(); - if ( $expensive && $wgMiserMode ){ + if ( $cached ) { $includesCachedPages = true; $pageClasses[] = 'mw-specialpagecached'; } diff --git a/includes/specials/SpecialUndelete.php b/includes/specials/SpecialUndelete.php index 4c38a781ba..c0420e56c2 100644 --- a/includes/specials/SpecialUndelete.php +++ b/includes/specials/SpecialUndelete.php @@ -575,6 +575,9 @@ class PageArchive { return Status::newFatal( "undeleterevdel" ); } } + + $newid = false; + $pageId = $article->getId(); } $revision = null; @@ -593,6 +596,7 @@ class PageArchive { // unless we are specifically removing all restrictions... $revision = Revision::newFromArchiveRow( $row, array( + 'page' => $pageId, 'title' => $this->title, 'deleted' => $unsuppress ? 0 : $row->ar_deleted ) ); diff --git a/includes/specials/SpecialUpload.php b/includes/specials/SpecialUpload.php index fd24af1a4e..73c7e2aefd 100644 --- a/includes/specials/SpecialUpload.php +++ b/includes/specials/SpecialUpload.php @@ -312,12 +312,12 @@ class SpecialUpload extends SpecialPage { $this->showUploadForm( $form ); } /** - * Stashes the upload, shows the main form, but adds an "continue anyway button". + * Stashes the upload, shows the main form, but adds a "continue anyway button". * Also checks whether there are actually warnings to display. * * @param $warnings Array * @return boolean true if warnings were displayed, false if there are no - * warnings and the should continue processing like there was no warning + * warnings and it should continue processing */ protected function showUploadWarning( $warnings ) { # If there are no warnings, or warnings we can ignore, return early. @@ -336,6 +336,9 @@ class SpecialUpload extends SpecialPage { $warningHtml = '

    ' . $this->msg( 'uploadwarning' )->escaped() . "

    \n" . '