From: jenkins-bot Date: Tue, 31 Oct 2017 09:22:39 +0000 (+0000) Subject: Merge "Prefer using plaintextParams instead of rawParams where possible" X-Git-Tag: 1.31.0-rc.0~1643 X-Git-Url: https://git.cyclocoop.org/%28%28?a=commitdiff_plain;h=28cb34cfae46c29033f10a3b192ec3e5bde3f6b7;hp=fc6d8a9cdb90e753ea05f2da9b32148456ecccc1;p=lhc%2Fweb%2Fwiklou.git Merge "Prefer using plaintextParams instead of rawParams where possible" --- diff --git a/.stylelintrc.json b/.stylelintrc.json index 27e289d430..60c8f36d48 100644 --- a/.stylelintrc.json +++ b/.stylelintrc.json @@ -3,6 +3,6 @@ "rules": { "no-descending-specificity": null, - "selector-no-id": null + "selector-max-id": null } } diff --git a/Gruntfile.js b/Gruntfile.js index dbbfcb814e..d1ef72f270 100644 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -62,9 +62,6 @@ module.exports = function ( grunt ) { installer: 'includes/installer/i18n/' }, stylelint: { - options: { - syntax: 'less' - }, src: '{resources/src,mw-config}/**/*.{css,less}' }, watch: { diff --git a/RELEASE-NOTES-1.31 b/RELEASE-NOTES-1.31 index a4ce4810ac..a7edba436e 100644 --- a/RELEASE-NOTES-1.31 +++ b/RELEASE-NOTES-1.31 @@ -13,6 +13,8 @@ production. temporary variable during the migration period, deprecated since 1.29. * $wgLogoHD has been updated to support svg images and uses $wgLogo where possible for fallback images such as png. +* (T44246) $wgFilterLogTypes will no longer ignore 'patrol' when user does + not have the right to mark things patrolled. * … === New features in 1.31 === @@ -62,6 +64,28 @@ changes to languages because of Phabricator reports. in 1.24, were removed. * Installer::locateExecutable() and Installer::locateExecutableInDefaultPaths() were removed, use ExecutableFinder::findInDefaultPaths() instead. +* Several methods for returning lists of fields to select from the database + have been deprecated in favor of similar methods that also return the tables + to select from and the join conditions for those tables. + * Block::selectFields() → Block::getQueryInfo() + * RecentChange::selectFields() → RecentChange::getQueryInfo() + * ArchivedFile::selectFields() → ArchivedFile::getQueryInfo() + * LocalFile::selectFields() → LocalFile::getQueryInfo() + * LocalFile::getCacheFields() with a prefix no longer works + * LocalFile::getLazyCacheFields() with a prefix no longer works + * OldLocalFile::selectFields() → OldLocalFile::getQueryInfo() + * RecentChange::selectFields() → RecentChange::getQueryInfo() + * Revision::userJoinCond() → Revision::getQueryInfo( [ 'user' ] ) + * Revision::selectUserFields() → Revision::getQueryInfo( [ 'user' ] ) + * Revision::pageJoinCond() → Revision::getQueryInfo( [ 'page' ] ) + * Revision::selectPageFields() → Revision::getQueryInfo( [ 'page' ] ) + * Revision::selectTextFields() → Revision::getQueryInfo( [ 'text' ] ) + * Revision::selectFields() → Revision::getQueryInfo() + * Revision::selectArchiveFields() → Revision::getArchiveQueryInfo() + * User::selectFields() → User::getQueryInfo() + * WikiPage::selectFields() → WikiPage::getQueryInfo() +* Due to significant refactoring, method ContribsPager::getUserCond() that had + no access restriction has been removed. == Compatibility == MediaWiki 1.31 requires PHP 5.5.9 or later. There is experimental support for diff --git a/docs/hooks.txt b/docs/hooks.txt index a19e9fc0e2..effc6d9ee2 100644 --- a/docs/hooks.txt +++ b/docs/hooks.txt @@ -689,6 +689,8 @@ $destTitle: destination title (object) 'ArticlePageDataBefore': Before loading data of an article from the database. &$wikiPage: WikiPage (object) that data will be loaded &$fields: fields (array) to load from the database +&$tables: tables (array) to load from the database +&$joinConds: join conditions (array) to load from the database 'ArticlePrepareTextForEdit': Called when preparing text to be saved. $wikiPage: the WikiPage being saved diff --git a/includes/Block.php b/includes/Block.php index 8d69d9a914..d1e78bb6cf 100644 --- a/includes/Block.php +++ b/includes/Block.php @@ -183,11 +183,14 @@ class Block { */ public static function newFromID( $id ) { $dbr = wfGetDB( DB_REPLICA ); + $blockQuery = self::getQueryInfo(); $res = $dbr->selectRow( - 'ipblocks', - self::selectFields(), + $blockQuery['tables'], + $blockQuery['fields'], [ 'ipb_id' => $id ], - __METHOD__ + __METHOD__, + [], + $blockQuery['joins'] ); if ( $res ) { return self::newFromRow( $res ); @@ -199,11 +202,11 @@ class Block { /** * Return the list of ipblocks fields that should be selected to create * a new block. - * @todo Deprecate this in favor of a method that returns tables and joins - * as well, and use CommentStore::getJoin(). + * @deprecated since 1.31, use self::getQueryInfo() instead. * @return array */ public static function selectFields() { + wfDeprecated( __METHOD__, '1.31' ); return [ 'ipb_id', 'ipb_address', @@ -222,6 +225,39 @@ class Block { ] + CommentStore::newKey( 'ipb_reason' )->getFields(); } + /** + * Return the tables, fields, and join conditions to be selected to create + * a new block object. + * @since 1.31 + * @return array With three keys: + * - tables: (string[]) to include in the `$table` to `IDatabase->select()` + * - fields: (string[]) to include in the `$vars` to `IDatabase->select()` + * - joins: (array) to include in the `$join_conds` to `IDatabase->select()` + */ + public static function getQueryInfo() { + $commentQuery = CommentStore::newKey( 'ipb_reason' )->getJoin(); + return [ + 'tables' => [ 'ipblocks' ] + $commentQuery['tables'], + 'fields' => [ + 'ipb_id', + 'ipb_address', + 'ipb_by', + 'ipb_by_text', + 'ipb_timestamp', + 'ipb_auto', + 'ipb_anon_only', + 'ipb_create_account', + 'ipb_enable_autoblock', + 'ipb_expiry', + 'ipb_deleted', + 'ipb_block_email', + 'ipb_allow_usertalk', + 'ipb_parent_block_id', + ] + $commentQuery['fields'], + 'joins' => $commentQuery['joins'], + ]; + } + /** * 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 @@ -295,7 +331,10 @@ class Block { } } - $res = $db->select( 'ipblocks', self::selectFields(), $conds, __METHOD__ ); + $blockQuery = self::getQueryInfo(); + $res = $db->select( + $blockQuery['tables'], $blockQuery['fields'], $conds, __METHOD__, [], $blockQuery['joins'] + ); # This result could contain a block on the user, a block on the IP, and a russian-doll # set of rangeblocks. We want to choose the most specific one, so keep a leader board. @@ -422,7 +461,7 @@ class Block { $db = wfGetDB( DB_REPLICA ); $this->mExpiry = $db->decodeExpiry( $row->ipb_expiry ); $this->mReason = CommentStore::newKey( 'ipb_reason' ) - // Legacy because $row probably came from self::selectFields() + // Legacy because $row may have come from self::selectFields() ->getCommentLegacy( $db, $row )->text; $this->isHardblock( !$row->ipb_anon_only ); @@ -1187,14 +1226,14 @@ class Block { if ( !$isAnon ) { $conds = [ $conds, 'ipb_anon_only' => 0 ]; } - $selectFields = array_merge( - [ 'ipb_range_start', 'ipb_range_end' ], - self::selectFields() - ); - $rows = $db->select( 'ipblocks', - $selectFields, + $blockQuery = self::getQueryInfo(); + $rows = $db->select( + $blockQuery['tables'], + array_merge( [ 'ipb_range_start', 'ipb_range_end' ], $blockQuery['fields'] ), $conds, - __METHOD__ + __METHOD__, + [], + $blockQuery['joins'] ); $blocks = []; diff --git a/includes/DefaultSettings.php b/includes/DefaultSettings.php index 040f1ce7bf..497b86d074 100644 --- a/includes/DefaultSettings.php +++ b/includes/DefaultSettings.php @@ -6804,6 +6804,10 @@ $wgRCWatchCategoryMembership = false; /** * Use RC Patrolling to check for vandalism (from recent changes and watchlists) * New pages and new files are included. + * + * @note If you disable all patrolling features, you probably also want to + * remove 'patrol' from $wgFilterLogTypes so a show/hide link isn't shown on + * Special:Log. */ $wgUseRCPatrol = true; @@ -6835,12 +6839,20 @@ $wgStructuredChangeFiltersLiveUpdatePollingRate = 3; /** * Use new page patrolling to check new pages on Special:Newpages + * + * @note If you disable all patrolling features, you probably also want to + * remove 'patrol' from $wgFilterLogTypes so a show/hide link isn't shown on + * Special:Log. */ $wgUseNPPatrol = true; /** * Use file patrolling to check new files on Special:Newfiles * + * @note If you disable all patrolling features, you probably also want to + * remove 'patrol' from $wgFilterLogTypes so a show/hide link isn't shown on + * Special:Log. + * * @since 1.27 */ $wgUseFilePatrol = true; diff --git a/includes/FeedUtils.php b/includes/FeedUtils.php index b1c3ce615a..6c343ab39f 100644 --- a/includes/FeedUtils.php +++ b/includes/FeedUtils.php @@ -89,9 +89,7 @@ class FeedUtils { $timestamp, $row->rc_deleted & Revision::DELETED_COMMENT ? wfMessage( 'rev-deleted-comment' )->escaped() - : CommentStore::newKey( 'rc_comment' ) - // Legacy from RecentChange::selectFields() via ChangesListSpecialPage::doMainQuery() - ->getCommentLegacy( wfGetDB( DB_REPLICA ), $row )->text, + : CommentStore::newKey( 'rc_comment' )->getComment( $row )->text, $actiontext ); } diff --git a/includes/Revision.php b/includes/Revision.php index dd3ee782fd..f9810a0354 100644 --- a/includes/Revision.php +++ b/includes/Revision.php @@ -193,7 +193,7 @@ class Revision implements IDBAccessObject { 'page' => isset( $row->ar_page_id ) ? $row->ar_page_id : null, 'id' => isset( $row->ar_rev_id ) ? $row->ar_rev_id : null, 'comment' => CommentStore::newKey( 'ar_comment' ) - // Legacy because $row probably came from self::selectArchiveFields() + // Legacy because $row may have come from self::selectArchiveFields() ->getCommentLegacy( wfGetDB( DB_REPLICA ), $row, true )->text, 'user' => $row->ar_user, 'user_text' => $row->ar_user_text, @@ -403,22 +403,18 @@ class Revision implements IDBAccessObject { * @return stdClass */ private static function fetchFromConds( $db, $conditions, $flags = 0 ) { - $fields = array_merge( - self::selectFields(), - self::selectPageFields(), - self::selectUserFields() - ); + $revQuery = self::getQueryInfo( [ 'page', 'user' ] ); $options = []; if ( ( $flags & self::READ_LOCKING ) == self::READ_LOCKING ) { $options[] = 'FOR UPDATE'; } return $db->selectRow( - [ 'revision', 'page', 'user' ], - $fields, + $revQuery['tables'], + $revQuery['fields'], $conditions, __METHOD__, $options, - [ 'page' => self::pageJoinCond(), 'user' => self::userJoinCond() ] + $revQuery['joins'] ); } @@ -426,6 +422,7 @@ class Revision implements IDBAccessObject { * Return the value of a select() JOIN conds array for the user table. * This will get user table rows for logged-in users. * @since 1.19 + * @deprecated since 1.31, use self::getQueryInfo( [ 'user' ] ) instead. * @return array */ public static function userJoinCond() { @@ -436,6 +433,7 @@ class Revision implements IDBAccessObject { * Return the value of a select() page conds array for the page table. * This will assure that the revision(s) are not orphaned from live pages. * @since 1.19 + * @deprecated since 1.31, use self::getQueryInfo( [ 'page' ] ) instead. * @return array */ public static function pageJoinCond() { @@ -445,8 +443,7 @@ class Revision implements IDBAccessObject { /** * Return the list of revision fields that should be selected to create * a new revision. - * @todo Deprecate this in favor of a method that returns tables and joins - * as well, and use CommentStore::getJoin(). + * @deprecated since 1.31, use self::getQueryInfo() instead. * @return array */ public static function selectFields() { @@ -479,8 +476,7 @@ class Revision implements IDBAccessObject { /** * Return the list of revision fields that should be selected to create * a new revision from an archive row. - * @todo Deprecate this in favor of a method that returns tables and joins - * as well, and use CommentStore::getJoin(). + * @deprecated since 1.31, use self::getArchiveQueryInfo() instead. * @return array */ public static function selectArchiveFields() { @@ -513,6 +509,7 @@ class Revision implements IDBAccessObject { /** * Return the list of text fields that should be selected to read the * revision text + * @deprecated since 1.31, use self::getQueryInfo( [ 'text' ] ) instead. * @return array */ public static function selectTextFields() { @@ -524,6 +521,7 @@ class Revision implements IDBAccessObject { /** * Return the list of page fields that should be selected from page table + * @deprecated since 1.31, use self::getQueryInfo( [ 'page' ] ) instead. * @return array */ public static function selectPageFields() { @@ -539,12 +537,127 @@ class Revision implements IDBAccessObject { /** * Return the list of user fields that should be selected from user table + * @deprecated since 1.31, use self::getQueryInfo( [ 'user' ] ) instead. * @return array */ public static function selectUserFields() { return [ 'user_name' ]; } + /** + * Return the tables, fields, and join conditions to be selected to create + * a new revision object. + * @since 1.31 + * @param array $options Any combination of the following strings + * - 'page': Join with the page table, and select fields to identify the page + * - 'user': Join with the user table, and select the user name + * - 'text': Join with the text table, and select fields to load page text + * @return array With three keys: + * - tables: (string[]) to include in the `$table` to `IDatabase->select()` + * - fields: (string[]) to include in the `$vars` to `IDatabase->select()` + * - joins: (array) to include in the `$join_conds` to `IDatabase->select()` + */ + public static function getQueryInfo( $options = [] ) { + global $wgContentHandlerUseDB; + + $commentQuery = CommentStore::newKey( 'rev_comment' )->getJoin(); + $ret = [ + 'tables' => [ 'revision' ] + $commentQuery['tables'], + 'fields' => [ + 'rev_id', + 'rev_page', + 'rev_text_id', + 'rev_timestamp', + 'rev_user_text', + 'rev_user', + 'rev_minor_edit', + 'rev_deleted', + 'rev_len', + 'rev_parent_id', + 'rev_sha1', + ] + $commentQuery['fields'], + 'joins' => $commentQuery['joins'], + ]; + + if ( $wgContentHandlerUseDB ) { + $ret['fields'][] = 'rev_content_format'; + $ret['fields'][] = 'rev_content_model'; + } + + if ( in_array( 'page', $options, true ) ) { + $ret['tables'][] = 'page'; + $ret['fields'] = array_merge( $ret['fields'], [ + 'page_namespace', + 'page_title', + 'page_id', + 'page_latest', + 'page_is_redirect', + 'page_len', + ] ); + $ret['joins']['page'] = [ 'INNER JOIN', [ 'page_id = rev_page' ] ]; + } + + if ( in_array( 'user', $options, true ) ) { + $ret['tables'][] = 'user'; + $ret['fields'] = array_merge( $ret['fields'], [ + 'user_name', + ] ); + $ret['joins']['user'] = [ 'LEFT JOIN', [ 'rev_user != 0', 'user_id = rev_user' ] ]; + } + + if ( in_array( 'text', $options, true ) ) { + $ret['tables'][] = 'text'; + $ret['fields'] = array_merge( $ret['fields'], [ + 'old_text', + 'old_flags' + ] ); + $ret['joins']['text'] = [ 'INNER JOIN', [ 'rev_text_id=old_id' ] ]; + } + + return $ret; + } + + /** + * Return the tables, fields, and join conditions to be selected to create + * a new archived revision object. + * @since 1.31 + * @return array With three keys: + * - tables: (string[]) to include in the `$table` to `IDatabase->select()` + * - fields: (string[]) to include in the `$vars` to `IDatabase->select()` + * - joins: (array) to include in the `$join_conds` to `IDatabase->select()` + */ + public static function getArchiveQueryInfo() { + global $wgContentHandlerUseDB; + + $commentQuery = CommentStore::newKey( 'ar_comment' )->getJoin(); + $ret = [ + 'tables' => [ 'archive' ] + $commentQuery['tables'], + 'fields' => [ + 'ar_id', + 'ar_page_id', + 'ar_rev_id', + 'ar_text', + 'ar_text_id', + 'ar_timestamp', + 'ar_user_text', + 'ar_user', + 'ar_minor_edit', + 'ar_deleted', + 'ar_len', + 'ar_parent_id', + 'ar_sha1', + ] + $commentQuery['fields'], + 'joins' => $commentQuery['joins'], + ]; + + if ( $wgContentHandlerUseDB ) { + $ret['fields'][] = 'ar_content_format'; + $ret['fields'][] = 'ar_content_model'; + } + + return $ret; + } + /** * Do a batched query to get the parent revision lengths * @param IDatabase $db @@ -590,7 +703,7 @@ class Revision implements IDBAccessObject { $this->mPage = intval( $row->rev_page ); $this->mTextId = intval( $row->rev_text_id ); $this->mComment = CommentStore::newKey( 'rev_comment' ) - // Legacy because $row probably came from self::selectFields() + // Legacy because $row may have come from self::selectFields() ->getCommentLegacy( wfGetDB( DB_REPLICA ), $row, true )->text; $this->mUser = intval( $row->rev_user ); $this->mMinorEdit = intval( $row->rev_minor_edit ); @@ -837,11 +950,21 @@ class Revision implements IDBAccessObject { // rev_id is defined as NOT NULL, but this revision may not yet have been inserted. if ( $this->mId !== null ) { $dbr = wfGetLB( $this->mWiki )->getConnectionRef( DB_REPLICA, [], $this->mWiki ); + // @todo: Title::getSelectFields(), or Title::getQueryInfo(), or something like that $row = $dbr->selectRow( - [ 'page', 'revision' ], - self::selectPageFields(), - [ 'page_id=rev_page', 'rev_id' => $this->mId ], - __METHOD__ + [ 'revision', 'page' ], + [ + 'page_namespace', + 'page_title', + 'page_id', + 'page_latest', + 'page_is_redirect', + 'page_len', + ], + [ 'rev_id' => $this->mId ], + __METHOD__, + [], + [ 'page' => [ 'JOIN', 'page_id=rev_page' ] ] ); if ( $row ) { // @TODO: better foreign title handling diff --git a/includes/RevisionList.php b/includes/RevisionList.php index b0bc60a188..fa454e07e3 100644 --- a/includes/RevisionList.php +++ b/includes/RevisionList.php @@ -296,15 +296,14 @@ class RevisionList extends RevisionListBase { if ( $this->ids !== null ) { $conds['rev_id'] = array_map( 'intval', $this->ids ); } + $revQuery = Revision::getQueryInfo( [ 'page', 'user' ] ); return $db->select( - [ 'revision', 'page', 'user' ], - array_merge( Revision::selectFields(), Revision::selectUserFields() ), + $revQuery['tables'], + $revQuery['fields'], $conds, __METHOD__, [ 'ORDER BY' => 'rev_id DESC' ], - [ - 'page' => Revision::pageJoinCond(), - 'user' => Revision::userJoinCond() ] + $revQuery['joins'] ); } diff --git a/includes/ServiceWiring.php b/includes/ServiceWiring.php index 75ce8eca94..0496b67fc7 100644 --- a/includes/ServiceWiring.php +++ b/includes/ServiceWiring.php @@ -442,6 +442,7 @@ return [ $factory = new CommandFactory( $limits, $cgroup ); $factory->setLogger( LoggerFactory::getInstance( 'exec' ) ); + $factory->logStderr(); return $factory; }, diff --git a/includes/Title.php b/includes/Title.php index 718239dbeb..d043b442ac 100644 --- a/includes/Title.php +++ b/includes/Title.php @@ -3628,19 +3628,20 @@ class Title implements LinkTarget { $blNamespace = "{$prefix}_namespace"; $blTitle = "{$prefix}_title"; + $pageQuery = WikiPage::getQueryInfo(); $res = $db->select( - [ $table, 'page' ], + [ $table, 'nestpage' => $pageQuery['tables'] ], array_merge( [ $blNamespace, $blTitle ], - WikiPage::selectFields() + $pageQuery['fields'] ), [ "{$prefix}_from" => $id ], __METHOD__, $options, - [ 'page' => [ + [ 'nestpage' => [ 'LEFT JOIN', [ "page_namespace=$blNamespace", "page_title=$blTitle" ] - ] ] + ] ] + $pageQuery['joins'] ); $retVal = []; @@ -4193,13 +4194,15 @@ class Title implements LinkTarget { $pageId = $this->getArticleID( $flags ); if ( $pageId ) { $db = ( $flags & self::GAID_FOR_UPDATE ) ? wfGetDB( DB_MASTER ) : wfGetDB( DB_REPLICA ); - $row = $db->selectRow( 'revision', Revision::selectFields(), + $revQuery = Revision::getQueryInfo(); + $row = $db->selectRow( $revQuery['tables'], $revQuery['fields'], [ 'rev_page' => $pageId ], __METHOD__, [ 'ORDER BY' => 'rev_timestamp ASC, rev_id ASC', - 'IGNORE INDEX' => 'rev_timestamp', // See T159319 - ] + 'IGNORE INDEX' => [ 'revision' => 'rev_timestamp' ], // See T159319 + ], + $revQuery['joins'] ); if ( $row ) { return new Revision( $row ); diff --git a/includes/actions/HistoryAction.php b/includes/actions/HistoryAction.php index a9a504d13a..a9e3d6accd 100644 --- a/includes/actions/HistoryAction.php +++ b/includes/actions/HistoryAction.php @@ -258,12 +258,18 @@ class HistoryAction extends FormlessAction { $page_id = $this->page->getId(); - return $dbr->select( 'revision', - Revision::selectFields(), + $revQuery = Revision::getQueryInfo(); + return $dbr->select( + $revQuery['tables'], + $revQuery['fields'], array_merge( [ 'rev_page' => $page_id ], $offsets ), __METHOD__, - [ 'ORDER BY' => "rev_timestamp $dirs", - 'USE INDEX' => 'page_timestamp', 'LIMIT' => $limit ] + [ + 'ORDER BY' => "rev_timestamp $dirs", + 'USE INDEX' => [ 'revision' => 'page_timestamp' ], + 'LIMIT' => $limit + ], + $revQuery['joins'] ); } @@ -418,14 +424,15 @@ class HistoryPager extends ReverseChronologicalPager { } function getQueryInfo() { + $revQuery = Revision::getQueryInfo( [ 'user' ] ); $queryInfo = [ - 'tables' => [ 'revision', 'user' ], - 'fields' => array_merge( Revision::selectFields(), Revision::selectUserFields() ), + 'tables' => $revQuery['tables'], + 'fields' => $revQuery['fields'], 'conds' => array_merge( [ 'rev_page' => $this->getWikiPage()->getId() ], $this->conds ), 'options' => [ 'USE INDEX' => [ 'revision' => 'page_timestamp' ] ], - 'join_conds' => [ 'user' => Revision::userJoinCond() ], + 'join_conds' => $revQuery['joins'], ]; ChangeTags::modifyDisplayQuery( $queryInfo['tables'], diff --git a/includes/api/ApiComparePages.php b/includes/api/ApiComparePages.php index 953bc10cc3..eb67babf2a 100644 --- a/includes/api/ApiComparePages.php +++ b/includes/api/ApiComparePages.php @@ -175,14 +175,17 @@ class ApiComparePages extends ApiBase { $rev = Revision::newFromId( $revId ); if ( !$rev ) { // Titles of deleted revisions aren't secret, per T51088 + $arQuery = Revision::getArchiveQueryInfo(); $row = $this->getDB()->selectRow( - 'archive', + $arQuery['tables'], array_merge( - Revision::selectArchiveFields(), + $arQuery['fields'], [ 'ar_namespace', 'ar_title' ] ), [ 'ar_rev_id' => $revId ], - __METHOD__ + __METHOD__, + [], + $arQuery['joins'] ); if ( $row ) { $rev = Revision::newFromArchiveRow( $row ); @@ -285,14 +288,17 @@ class ApiComparePages extends ApiBase { $rev = Revision::newFromId( $revId ); if ( !$rev && $this->getUser()->isAllowedAny( 'deletedtext', 'undelete' ) ) { // Try the 'archive' table + $arQuery = Revision::getArchiveQueryInfo(); $row = $this->getDB()->selectRow( - 'archive', + $arQuery['tables'], array_merge( - Revision::selectArchiveFields(), + $arQuery['fields'], [ 'ar_namespace', 'ar_title' ] ), [ 'ar_rev_id' => $revId ], - __METHOD__ + __METHOD__, + [], + $arQuery['joins'] ); if ( $row ) { $rev = Revision::newFromArchiveRow( $row ); diff --git a/includes/api/ApiQueryAllDeletedRevisions.php b/includes/api/ApiQueryAllDeletedRevisions.php index b22bb1ff15..765b5c7f1d 100644 --- a/includes/api/ApiQueryAllDeletedRevisions.php +++ b/includes/api/ApiQueryAllDeletedRevisions.php @@ -103,13 +103,16 @@ class ApiQueryAllDeletedRevisions extends ApiQueryRevisionsBase { } } - $this->addTables( 'archive' ); if ( $resultPageSet === null ) { $this->parseParameters( $params ); - $this->addFields( Revision::selectArchiveFields() ); + $arQuery = Revision::getArchiveQueryInfo(); + $this->addTables( $arQuery['tables'] ); + $this->addJoinConds( $arQuery['joins'] ); + $this->addFields( $arQuery['fields'] ); $this->addFields( [ 'ar_title', 'ar_namespace' ] ); } else { $this->limit = $this->getParameter( 'limit' ) ?: 10; + $this->addTables( 'archive' ); $this->addFields( [ 'ar_title', 'ar_namespace' ] ); if ( $optimizeGenerateTitles ) { $this->addOption( 'DISTINCT' ); diff --git a/includes/api/ApiQueryAllImages.php b/includes/api/ApiQueryAllImages.php index 250bee667f..6f497b1996 100644 --- a/includes/api/ApiQueryAllImages.php +++ b/includes/api/ApiQueryAllImages.php @@ -90,10 +90,12 @@ class ApiQueryAllImages extends ApiQueryGeneratorBase { $userId = !is_null( $params['user'] ) ? User::idFromName( $params['user'] ) : null; // Table and return fields - $this->addTables( 'image' ); - $prop = array_flip( $params['prop'] ); - $this->addFields( LocalFile::selectFields() ); + + $fileQuery = LocalFile::getQueryInfo(); + $this->addTables( $fileQuery['tables'] ); + $this->addFields( $fileQuery['fields'] ); + $this->addJoinConds( $fileQuery['joins'] ); $ascendingOrder = true; if ( $params['dir'] == 'descending' || $params['dir'] == 'older' ) { diff --git a/includes/api/ApiQueryAllRevisions.php b/includes/api/ApiQueryAllRevisions.php index 8f7d6eb28f..c8db6a1189 100644 --- a/includes/api/ApiQueryAllRevisions.php +++ b/includes/api/ApiQueryAllRevisions.php @@ -63,20 +63,20 @@ class ApiQueryAllRevisions extends ApiQueryRevisionsBase { } } - $this->addTables( 'revision' ); if ( $resultPageSet === null ) { $this->parseParameters( $params ); - $this->addTables( 'page' ); - $this->addJoinConds( - [ 'page' => [ 'INNER JOIN', [ 'rev_page = page_id' ] ] ] + $revQuery = Revision::getQueryInfo( + $this->fetchContent ? [ 'page', 'text' ] : [ 'page' ] ); - $this->addFields( Revision::selectFields() ); - $this->addFields( Revision::selectPageFields() ); + $this->addTables( $revQuery['tables'] ); + $this->addFields( $revQuery['fields'] ); + $this->addJoinConds( $revQuery['joins'] ); // Review this depeneding on the outcome of T113901 $this->addOption( 'STRAIGHT_JOIN' ); } else { $this->limit = $this->getParameter( 'limit' ) ?: 10; + $this->addTables( 'revision' ); $this->addFields( [ 'rev_timestamp', 'rev_id' ] ); if ( $params['generatetitles'] ) { $this->addFields( [ 'rev_page' ] ); @@ -105,15 +105,6 @@ class ApiQueryAllRevisions extends ApiQueryRevisionsBase { $this->addFields( 'ts_tags' ); } - if ( $this->fetchContent ) { - $this->addTables( 'text' ); - $this->addJoinConds( - [ 'text' => [ 'INNER JOIN', [ 'rev_text_id=old_id' ] ] ] - ); - $this->addFields( 'old_id' ); - $this->addFields( Revision::selectTextFields() ); - } - if ( $params['user'] !== null ) { $id = User::idFromName( $params['user'] ); if ( $id ) { diff --git a/includes/api/ApiQueryDeletedRevisions.php b/includes/api/ApiQueryDeletedRevisions.php index 8e4752e8cf..3339fec5e5 100644 --- a/includes/api/ApiQueryDeletedRevisions.php +++ b/includes/api/ApiQueryDeletedRevisions.php @@ -60,13 +60,16 @@ class ApiQueryDeletedRevisions extends ApiQueryRevisionsBase { $this->requireMaxOneParameter( $params, 'user', 'excludeuser' ); - $this->addTables( 'archive' ); if ( $resultPageSet === null ) { $this->parseParameters( $params ); - $this->addFields( Revision::selectArchiveFields() ); + $arQuery = Revision::getArchiveQueryInfo(); + $this->addTables( $arQuery['tables'] ); + $this->addFields( $arQuery['fields'] ); + $this->addJoinConds( $arQuery['joins'] ); $this->addFields( [ 'ar_title', 'ar_namespace' ] ); } else { $this->limit = $this->getParameter( 'limit' ) ?: 10; + $this->addTables( 'archive' ); $this->addFields( [ 'ar_title', 'ar_namespace', 'ar_timestamp', 'ar_rev_id', 'ar_id' ] ); } diff --git a/includes/api/ApiQueryFilearchive.php b/includes/api/ApiQueryFilearchive.php index 212b61340a..838fc2bda4 100644 --- a/includes/api/ApiQueryFilearchive.php +++ b/includes/api/ApiQueryFilearchive.php @@ -60,25 +60,10 @@ class ApiQueryFilearchive extends ApiQueryBase { $fld_bitdepth = isset( $prop['bitdepth'] ); $fld_archivename = isset( $prop['archivename'] ); - $this->addTables( 'filearchive' ); - - $this->addFields( ArchivedFile::selectFields() ); - $this->addFields( [ 'fa_id', 'fa_name', 'fa_timestamp', 'fa_deleted' ] ); - $this->addFieldsIf( 'fa_sha1', $fld_sha1 ); - $this->addFieldsIf( [ 'fa_user', 'fa_user_text' ], $fld_user ); - $this->addFieldsIf( [ 'fa_height', 'fa_width', 'fa_size' ], $fld_dimensions || $fld_size ); - $this->addFieldsIf( [ 'fa_major_mime', 'fa_minor_mime' ], $fld_mime ); - $this->addFieldsIf( 'fa_media_type', $fld_mediatype ); - $this->addFieldsIf( 'fa_metadata', $fld_metadata ); - $this->addFieldsIf( 'fa_bits', $fld_bitdepth ); - $this->addFieldsIf( 'fa_archive_name', $fld_archivename ); - - if ( $fld_description ) { - $commentQuery = $commentStore->getJoin(); - $this->addTables( $commentQuery['tables'] ); - $this->addFields( $commentQuery['fields'] ); - $this->addJoinConds( $commentQuery['joins'] ); - } + $fileQuery = ArchivedFile::getQueryInfo(); + $this->addTables( $fileQuery['tables'] ); + $this->addFields( $fileQuery['fields'] ); + $this->addJoinConds( $fileQuery['joins'] ); if ( !is_null( $params['continue'] ) ) { $cont = explode( '|', $params['continue'] ); diff --git a/includes/api/ApiQueryRevisions.php b/includes/api/ApiQueryRevisions.php index 2dfa42a3a4..a04b7c545c 100644 --- a/includes/api/ApiQueryRevisions.php +++ b/includes/api/ApiQueryRevisions.php @@ -129,20 +129,31 @@ class ApiQueryRevisions extends ApiQueryRevisionsBase { } $db = $this->getDB(); - $this->addTables( [ 'revision', 'page' ] ); - $this->addJoinConds( - [ 'page' => [ 'INNER JOIN', [ 'page_id = rev_page' ] ] ] - ); if ( $resultPageSet === null ) { $this->parseParameters( $params ); $this->token = $params['token']; - $this->addFields( Revision::selectFields() ); + $opts = []; if ( $this->token !== null || $pageCount > 0 ) { - $this->addFields( Revision::selectPageFields() ); + $opts[] = 'page'; } + if ( $this->fetchContent ) { + $opts[] = 'text'; + } + if ( $this->fld_user ) { + $opts[] = 'user'; + } + $revQuery = Revision::getQueryInfo( $opts ); + $this->addTables( $revQuery['tables'] ); + $this->addFields( $revQuery['fields'] ); + $this->addJoinConds( $revQuery['joins'] ); } else { $this->limit = $this->getParameter( 'limit' ) ?: 10; + // Always join 'page' so orphaned revisions are filtered out + $this->addTables( [ 'revision', 'page' ] ); + $this->addJoinConds( + [ 'page' => [ 'INNER JOIN', [ 'page_id = rev_page' ] ] ] + ); $this->addFields( [ 'rev_id', 'rev_timestamp', 'rev_page' ] ); } @@ -162,7 +173,7 @@ class ApiQueryRevisions extends ApiQueryRevisionsBase { $this->addWhereFld( 'ct_tag', $params['tag'] ); } - if ( $this->fetchContent ) { + if ( $resultPageSet === null && $this->fetchContent ) { // For each page we will request, the user must have read rights for that page $user = $this->getUser(); $status = Status::newGood(); @@ -178,20 +189,6 @@ class ApiQueryRevisions extends ApiQueryRevisionsBase { if ( !$status->isGood() ) { $this->dieStatus( $status ); } - - $this->addTables( 'text' ); - $this->addJoinConds( - [ 'text' => [ 'INNER JOIN', [ 'rev_text_id=old_id' ] ] ] - ); - $this->addFields( 'old_id' ); - $this->addFields( Revision::selectTextFields() ); - } - - // add user name, if needed - if ( $this->fld_user ) { - $this->addTables( 'user' ); - $this->addJoinConds( [ 'user' => Revision::userJoinCond() ] ); - $this->addFields( Revision::selectUserFields() ); } if ( $enumRevMode ) { diff --git a/includes/api/ApiQueryUsers.php b/includes/api/ApiQueryUsers.php index fbf1f9ebfb..8fc99bbcf9 100644 --- a/includes/api/ApiQueryUsers.php +++ b/includes/api/ApiQueryUsers.php @@ -144,8 +144,10 @@ class ApiQueryUsers extends ApiQueryBase { $result = $this->getResult(); if ( count( $parameters ) ) { - $this->addTables( 'user' ); - $this->addFields( User::selectFields() ); + $userQuery = User::getQueryInfo(); + $this->addTables( $userQuery['tables'] ); + $this->addFields( $userQuery['fields'] ); + $this->addJoinConds( $userQuery['joins'] ); if ( $useNames ) { $this->addWhereFld( 'user_name', $goodNames ); } else { diff --git a/includes/api/i18n/ru.json b/includes/api/i18n/ru.json index 1bb70959d4..e60ce87d9a 100644 --- a/includes/api/i18n/ru.json +++ b/includes/api/i18n/ru.json @@ -26,7 +26,8 @@ "Ivan-r", "Redredsonia", "Alexey zakharenkov", - "Facenapalm" + "Facenapalm", + "Jack who built the house" ] }, "apihelp-main-extended-description": "
\n* [[mw:Special:MyLanguage/API:Main_page|Документация]]\n* [[mw:Special:MyLanguage/API:FAQ|ЧаВО]]\n* [https://lists.wikimedia.org/mailman/listinfo/mediawiki-api Почтовая рассылка]\n* [https://lists.wikimedia.org/mailman/listinfo/mediawiki-api-announce Новости API]\n* [https://phabricator.wikimedia.org/maniphest/query/GebfyV4uCaLd/#R Ошибки и запросы]\n
\nСтатус: Все отображаемые на этой странице функции должны работать, однако API находится в статусе активной разработки и может измениться в любой момент. Подпишитесь на [https://lists.wikimedia.org/pipermail/mediawiki-api-announce/ почтовую рассылку mediawiki-api-announce], чтобы быть в курсе обновлений.\n\nОшибочные запросы: Если API получает запрос с ошибкой, вернётся заголовок HTTP с ключом «MediaWiki-API-Error», после чего значение заголовка и код ошибки будут отправлены обратно и установлены в то же значение. Более подробную информацию см. [[mw:Special:MyLanguage/API:Errors_and_warnings|API: Ошибки и предупреждения]].\n\nТестирование: для удобства тестирования API-запросов, см. [[Special:ApiSandbox]].", @@ -42,9 +43,9 @@ "apihelp-main-param-curtimestamp": "Включить в результат временную метку.", "apihelp-main-param-responselanginfo": "Включить языки, использованные для uselang и errorlang, в результат.", "apihelp-main-param-origin": "При обращении к API с использованием кросс-доменного AJAX-запроса (CORS), задайте параметру значение исходного домена. Он должен быть включён в любой предварительный запрос и таким образом должен быть частью URI-запроса (не тела POST).\n\nДля аутентифицированных запросов он должен точно соответствовать одному из источников в заголовке Origin, так что он должен быть задан наподобие https://ru.wikipedia.org или https://meta.wikimedia.org. Если параметр не соответствует заголовку Origin, будет возвращён ответ с кодом ошибки 403. Если параметр соответствует заголовку Origin, и источник находится в белом списке, будут установлены заголовки Access-Control-Allow-Origin и Access-Control-Allow-Credentials.\n\nДля неаутентифицированных запросов укажите значение *. В результате заголовок Access-Control-Allow-Origin будет установлен, но Access-Control-Allow-Credentials примет значение false и все пользовательские данные будут ограничены.", - "apihelp-main-param-uselang": "Язык, используемый для перевода сообщений. Запрос «[[Special:ApiHelp/query+siteinfo|action=query&meta=siteinfo]]» с «siprop=languages» возвращает список кодов языков; укажите «user», чтобы использовать текущие языковые настройки участника, или «content» для использования основного языка этой вики.", + "apihelp-main-param-uselang": "Язык, используемый для перевода сообщений. Запрос [[Special:ApiHelp/query+siteinfo|action=query&meta=siteinfo]] с siprop=languages возвращает список кодов языков; укажите user, чтобы использовать текущие языковые настройки участника, или content для использования основного языка этой вики.", "apihelp-main-param-errorformat": "Формат, используемый для вывода текста предупреждений и ошибок.\n; plaintext: Вики-текст с удалёнными HTML-тегами и замещёнными мнемониками.\n; wikitext: Нераспарсенный вики-текст.\n; html: HTML.\n; raw: Ключ сообщения и параметры.\n; none: Без текстового вывода, только коды ошибок.\n; bc: Формат, используемый до MediaWiki 1.29. errorlang и errorsuselocal игнорируются.", - "apihelp-main-param-errorlang": "Язык, используемый для вывода предупреждений и сообщений об ошибках. Запрос «[[Special:ApiHelp/query+siteinfo|action=query&meta=siteinfo]]» с «siprop=languages» возвращает список кодов языков; укажите «content» для использования основного языка этой вики, или «uselang» для использования того же значения, что и в параметре «uselang».", + "apihelp-main-param-errorlang": "Язык, используемый для вывода предупреждений и сообщений об ошибках. Запрос [[Special:ApiHelp/query+siteinfo|action=query&meta=siteinfo]] с siprop=languages возвращает список кодов языков; укажите content для использования основного языка этой вики, или uselang для использования того же значения, что и в параметре uselang.", "apihelp-main-param-errorsuselocal": "Если задан, тексты ошибок будут использовать локально модифицированные сообщения из пространства имён {{ns:MediaWiki}}.", "apihelp-block-summary": "Блокировка участника.", "apihelp-block-param-user": "Имя участника, IP-адрес или диапазон IP-адресов, которые вы хотите заблокировать. Нельзя использовать вместе с $1userid", diff --git a/includes/api/i18n/zh-hans.json b/includes/api/i18n/zh-hans.json index 0084717132..d09c65110d 100644 --- a/includes/api/i18n/zh-hans.json +++ b/includes/api/i18n/zh-hans.json @@ -303,7 +303,7 @@ "apihelp-move-param-ignorewarnings": "忽略任何警告。", "apihelp-move-param-tags": "要在移动日志,以及在目标页面的空修订版本中应用到实体的更改标签。", "apihelp-move-example-move": "移动Badtitle到Goodtitle,不保留重定向。", - "apihelp-opensearch-summary": "使用OpenSearch协议搜索wiki。", + "apihelp-opensearch-summary": "使用开放搜索协议搜索wiki。", "apihelp-opensearch-param-search": "搜索字符串。", "apihelp-opensearch-param-limit": "要返回的结果最大数。", "apihelp-opensearch-param-namespace": "搜索的名字空间。", diff --git a/includes/changes/RecentChange.php b/includes/changes/RecentChange.php index fd789a6421..bb2412074c 100644 --- a/includes/changes/RecentChange.php +++ b/includes/changes/RecentChange.php @@ -192,7 +192,10 @@ class RecentChange { $dbType = DB_REPLICA ) { $db = wfGetDB( $dbType ); - $row = $db->selectRow( 'recentchanges', self::selectFields(), $conds, $fname ); + $rcQuery = self::getQueryInfo(); + $row = $db->selectRow( + $rcQuery['tables'], $rcQuery['fields'], $conds, $fname, [], $rcQuery['joins'] + ); if ( $row !== false ) { return self::newFromRow( $row ); } else { @@ -203,8 +206,7 @@ class RecentChange { /** * Return the list of recentchanges fields that should be selected to create * a new recentchanges object. - * @todo Deprecate this in favor of a method that returns tables and joins - * as well, and use CommentStore::getJoin(). + * @deprecated since 1.31, use self::getQueryInfo() instead. * @return array */ public static function selectFields() { @@ -235,6 +237,48 @@ class RecentChange { ] + CommentStore::newKey( 'rc_comment' )->getFields(); } + /** + * Return the tables, fields, and join conditions to be selected to create + * a new recentchanges object. + * @since 1.31 + * @return array With three keys: + * - tables: (string[]) to include in the `$table` to `IDatabase->select()` + * - fields: (string[]) to include in the `$vars` to `IDatabase->select()` + * - joins: (array) to include in the `$join_conds` to `IDatabase->select()` + */ + public static function getQueryInfo() { + $commentQuery = CommentStore::newKey( 'rc_comment' )->getJoin(); + return [ + 'tables' => [ 'recentchanges' ] + $commentQuery['tables'], + 'fields' => [ + 'rc_id', + 'rc_timestamp', + 'rc_user', + 'rc_user_text', + 'rc_namespace', + 'rc_title', + 'rc_minor', + 'rc_bot', + 'rc_new', + 'rc_cur_id', + 'rc_this_oldid', + 'rc_last_oldid', + 'rc_type', + 'rc_source', + 'rc_patrolled', + 'rc_ip', + 'rc_old_len', + 'rc_new_len', + 'rc_deleted', + 'rc_logid', + 'rc_log_type', + 'rc_log_action', + 'rc_params', + ] + $commentQuery['fields'], + 'joins' => $commentQuery['joins'], + ]; + } + # Accessors /** @@ -951,7 +995,7 @@ class RecentChange { } $comment = CommentStore::newKey( 'rc_comment' ) - // Legacy because $row probably came from self::selectFields() + // Legacy because $row may have come from self::selectFields() ->getCommentLegacy( wfGetDB( DB_REPLICA ), $row, true )->text; $this->mAttribs['rc_comment'] = &$comment; $this->mAttribs['rc_comment_text'] = &$comment; diff --git a/includes/changetags/ChangeTagsRevisionList.php b/includes/changetags/ChangeTagsRevisionList.php index 91193b0ecd..61259b4192 100644 --- a/includes/changetags/ChangeTagsRevisionList.php +++ b/includes/changetags/ChangeTagsRevisionList.php @@ -36,18 +36,16 @@ class ChangeTagsRevisionList extends ChangeTagsList { */ public function doQuery( $db ) { $ids = array_map( 'intval', $this->ids ); + $revQuery = Revision::getQueryInfo( [ 'user' ] ); $queryInfo = [ - 'tables' => [ 'revision', 'user' ], - 'fields' => array_merge( Revision::selectFields(), Revision::selectUserFields() ), + 'tables' => $revQuery['tables'], + 'fields' => $revQuery['fields'], 'conds' => [ 'rev_page' => $this->title->getArticleID(), 'rev_id' => $ids, ], 'options' => [ 'ORDER BY' => 'rev_id DESC' ], - 'join_conds' => [ - 'page' => Revision::pageJoinCond(), - 'user' => Revision::userJoinCond(), - ], + 'join_conds' => $revQuery['joins'], ]; ChangeTags::modifyDisplayQuery( $queryInfo['tables'], diff --git a/includes/diff/DifferenceEngine.php b/includes/diff/DifferenceEngine.php index ef67477c66..6a2837b43a 100644 --- a/includes/diff/DifferenceEngine.php +++ b/includes/diff/DifferenceEngine.php @@ -182,13 +182,15 @@ class DifferenceEngine extends ContextSource { public function deletedLink( $id ) { if ( $this->getUser()->isAllowed( 'deletedhistory' ) ) { $dbr = wfGetDB( DB_REPLICA ); - $row = $dbr->selectRow( 'archive', - array_merge( - Revision::selectArchiveFields(), - [ 'ar_namespace', 'ar_title' ] - ), + $arQuery = Revision::getArchiveQueryInfo(); + $row = $dbr->selectRow( + $arQuery['tables'], + array_merge( $arQuery['fields'], [ 'ar_namespace', 'ar_title' ] ), [ 'ar_rev_id' => $id ], - __METHOD__ ); + __METHOD__, + [], + $arQuery['joins'] + ); if ( $row ) { $rev = Revision::newFromArchiveRow( $row ); $title = Title::makeTitleSafe( $row->ar_namespace, $row->ar_title ); diff --git a/includes/filerepo/LocalRepo.php b/includes/filerepo/LocalRepo.php index ed00793508..f5b83ae5cc 100644 --- a/includes/filerepo/LocalRepo.php +++ b/includes/filerepo/LocalRepo.php @@ -310,8 +310,9 @@ class LocalRepo extends FileRepo { } if ( count( $imgNames ) ) { - $res = $dbr->select( 'image', - LocalFile::selectFields(), [ 'img_name' => $imgNames ], __METHOD__ ); + $fileQuery = LocalFile::getQueryInfo(); + $res = $dbr->select( $fileQuery['tables'], $fileQuery['fields'], [ 'img_name' => $imgNames ], + __METHOD__, [], $fileQuery['joins'] ); $applyMatchingFiles( $res, $searchSet, $finalFiles ); } @@ -330,8 +331,10 @@ class LocalRepo extends FileRepo { } if ( count( $oiConds ) ) { - $res = $dbr->select( 'oldimage', - OldLocalFile::selectFields(), $dbr->makeList( $oiConds, LIST_OR ), __METHOD__ ); + $fileQuery = OldLocalFile::getQueryInfo(); + $res = $dbr->select( $fileQuery['tables'], $fileQuery['fields'], + $dbr->makeList( $oiConds, LIST_OR ), + __METHOD__, [], $fileQuery['joins'] ); $applyMatchingFiles( $res, $searchSet, $finalFiles ); } @@ -372,12 +375,14 @@ class LocalRepo extends FileRepo { */ function findBySha1( $hash ) { $dbr = $this->getReplicaDB(); + $fileQuery = LocalFile::getQueryInfo(); $res = $dbr->select( - 'image', - LocalFile::selectFields(), + $fileQuery['tables'], + $fileQuery['fields'], [ 'img_sha1' => $hash ], __METHOD__, - [ 'ORDER BY' => 'img_name' ] + [ 'ORDER BY' => 'img_name' ], + $fileQuery['joins'] ); $result = []; @@ -404,12 +409,14 @@ class LocalRepo extends FileRepo { } $dbr = $this->getReplicaDB(); + $fileQuery = LocalFile::getQueryInfo(); $res = $dbr->select( - 'image', - LocalFile::selectFields(), + $fileQuery['tables'], + $fileQuery['fields'], [ 'img_sha1' => $hashes ], __METHOD__, - [ 'ORDER BY' => 'img_name' ] + [ 'ORDER BY' => 'img_name' ], + $fileQuery['joins'] ); $result = []; @@ -434,12 +441,14 @@ class LocalRepo extends FileRepo { // Query database $dbr = $this->getReplicaDB(); + $fileQuery = LocalFile::getQueryInfo(); $res = $dbr->select( - 'image', - LocalFile::selectFields(), + $fileQuery['tables'], + $fileQuery['fields'], 'img_name ' . $dbr->buildLike( $prefix, $dbr->anyString() ), __METHOD__, - $selectOptions + $selectOptions, + $fileQuery['joins'] ); // Build file objects diff --git a/includes/filerepo/file/ArchivedFile.php b/includes/filerepo/file/ArchivedFile.php index 758fb4b5a1..7f48659ba3 100644 --- a/includes/filerepo/file/ArchivedFile.php +++ b/includes/filerepo/file/ArchivedFile.php @@ -178,12 +178,14 @@ 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_REPLICA ); + $fileQuery = self::getQueryInfo(); $row = $dbr->selectRow( - 'filearchive', - self::selectFields(), + $fileQuery['tables'], + $fileQuery['fields'], $conds, __METHOD__, - [ 'ORDER BY' => 'fa_timestamp DESC' ] + [ 'ORDER BY' => 'fa_timestamp DESC' ], + $fileQuery['joins'] ); if ( !$row ) { // this revision does not exist? @@ -215,11 +217,11 @@ class ArchivedFile { /** * Fields in the filearchive table - * @todo Deprecate this in favor of a method that returns tables and joins - * as well, and use CommentStore::getJoin(). + * @deprecated since 1.31, use self::getQueryInfo() instead. * @return array */ static function selectFields() { + wfDeprecated( __METHOD__, '1.31' ); return [ 'fa_id', 'fa_name', @@ -243,6 +245,44 @@ class ArchivedFile { ] + CommentStore::newKey( 'fa_description' )->getFields(); } + /** + * Return the tables, fields, and join conditions to be selected to create + * a new archivedfile object. + * @since 1.31 + * @return array With three keys: + * - tables: (string[]) to include in the `$table` to `IDatabase->select()` + * - fields: (string[]) to include in the `$vars` to `IDatabase->select()` + * - joins: (array) to include in the `$join_conds` to `IDatabase->select()` + */ + public static function getQueryInfo() { + $commentQuery = CommentStore::newKey( 'fa_description' )->getJoin(); + return [ + 'tables' => [ 'filearchive' ] + $commentQuery['tables'], + 'fields' => [ + 'fa_id', + 'fa_name', + 'fa_archive_name', + 'fa_storage_key', + 'fa_storage_group', + 'fa_size', + 'fa_bits', + 'fa_width', + 'fa_height', + 'fa_metadata', + 'fa_media_type', + 'fa_major_mime', + 'fa_minor_mime', + 'fa_user', + 'fa_user_text', + 'fa_timestamp', + 'fa_deleted', + 'fa_deleted_timestamp', /* Used by LocalFileRestoreBatch */ + 'fa_sha1', + ] + $commentQuery['fields'], + 'joins' => $commentQuery['joins'], + ]; + } + /** * Load ArchivedFile object fields from a DB row. * @@ -263,7 +303,7 @@ class ArchivedFile { $this->mime = "$row->fa_major_mime/$row->fa_minor_mime"; $this->media_type = $row->fa_media_type; $this->description = CommentStore::newKey( 'fa_description' ) - // Legacy because $row probably came from self::selectFields() + // Legacy because $row may have come from self::selectFields() ->getCommentLegacy( wfGetDB( DB_REPLICA ), $row )->text; $this->user = $row->fa_user; $this->user_text = $row->fa_user_text; diff --git a/includes/filerepo/file/LocalFile.php b/includes/filerepo/file/LocalFile.php index 3271c966b8..0b730f60af 100644 --- a/includes/filerepo/file/LocalFile.php +++ b/includes/filerepo/file/LocalFile.php @@ -183,7 +183,10 @@ class LocalFile extends File { $conds['img_timestamp'] = $dbr->timestamp( $timestamp ); } - $row = $dbr->selectRow( 'image', self::selectFields(), $conds, __METHOD__ ); + $fileQuery = self::getQueryInfo(); + $row = $dbr->selectRow( + $fileQuery['tables'], $fileQuery['fields'], $conds, __METHOD__, [], $fileQuery['joins'] + ); if ( $row ) { return self::newFromRow( $row, $repo ); } else { @@ -193,8 +196,7 @@ class LocalFile extends File { /** * Fields in the image table - * @todo Deprecate this in favor of a method that returns tables and joins - * as well, and use CommentStore::getJoin(). + * @deprecated since 1.31, use self::getQueryInfo() instead. * @return array */ static function selectFields() { @@ -215,6 +217,51 @@ class LocalFile extends File { ] + CommentStore::newKey( 'img_description' )->getFields(); } + /** + * Return the tables, fields, and join conditions to be selected to create + * a new localfile object. + * @since 1.31 + * @param string[] $options + * - omit-lazy: Omit fields that are lazily cached. + * @return array With three keys: + * - tables: (string[]) to include in the `$table` to `IDatabase->select()` + * - fields: (string[]) to include in the `$vars` to `IDatabase->select()` + * - joins: (array) to include in the `$join_conds` to `IDatabase->select()` + */ + public static function getQueryInfo( array $options = [] ) { + $commentQuery = CommentStore::newKey( 'img_description' )->getJoin(); + $ret = [ + 'tables' => [ 'image' ] + $commentQuery['tables'], + 'fields' => [ + 'img_name', + 'img_size', + 'img_width', + 'img_height', + 'img_metadata', + 'img_bits', + 'img_media_type', + 'img_major_mime', + 'img_minor_mime', + 'img_user', + 'img_user_text', + 'img_timestamp', + 'img_sha1', + ] + $commentQuery['fields'], + 'joins' => $commentQuery['joins'], + ]; + + if ( in_array( 'omit-nonlazy', $options, true ) ) { + // Internal use only for getting only the lazy fields + $ret['fields'] = []; + } + if ( !in_array( 'omit-lazy', $options, true ) ) { + // Note: Keep this in sync with self::getLazyCacheFields() + $ret['fields'][] = 'img_metadata'; + } + + return $ret; + } + /** * Do not call this except from inside a repo class. * @param Title $title @@ -341,51 +388,43 @@ class LocalFile extends File { } /** - * @param string $prefix + * Returns the list of object properties that are included as-is in the cache. + * @param string $prefix Must be the empty string * @return array + * @since 1.31 No longer accepts a non-empty $prefix */ - function getCacheFields( $prefix = 'img_' ) { - static $fields = [ 'size', 'width', 'height', 'bits', 'media_type', - 'major_mime', 'minor_mime', 'metadata', 'timestamp', 'sha1', 'user', - 'user_text' ]; - static $results = []; - - if ( $prefix == '' ) { - return array_merge( $fields, [ 'description' ] ); - } - if ( !isset( $results[$prefix] ) ) { - $prefixedFields = []; - foreach ( $fields as $field ) { - $prefixedFields[] = $prefix . $field; - } - $prefixedFields += CommentStore::newKey( "{$prefix}description" )->getFields(); - $results[$prefix] = $prefixedFields; + protected function getCacheFields( $prefix = 'img_' ) { + if ( $prefix !== '' ) { + throw new InvalidArgumentException( + __METHOD__ . ' with a non-empty prefix is no longer supported.' + ); } - return $results[$prefix]; + // See self::getQueryInfo() for the fetching of the data from the DB, + // self::loadFromRow() for the loading of the object from the DB row, + // and self::loadFromCache() for the caching, and self::setProps() for + // populating the object from an array of data. + return [ 'size', 'width', 'height', 'bits', 'media_type', + 'major_mime', 'minor_mime', 'metadata', 'timestamp', 'sha1', 'user', + 'user_text', 'description' ]; } /** - * @param string $prefix + * Returns the list of object properties that are included as-is in the + * cache, only when they're not too big, and are lazily loaded by self::loadExtraFromDB(). + * @param string $prefix Must be the empty string * @return array + * @since 1.31 No longer accepts a non-empty $prefix */ - function getLazyCacheFields( $prefix = 'img_' ) { - static $fields = [ 'metadata' ]; - static $results = []; - - if ( $prefix == '' ) { - return $fields; - } - - if ( !isset( $results[$prefix] ) ) { - $prefixedFields = []; - foreach ( $fields as $field ) { - $prefixedFields[] = $prefix . $field; - } - $results[$prefix] = $prefixedFields; + protected function getLazyCacheFields( $prefix = 'img_' ) { + if ( $prefix !== '' ) { + throw new InvalidArgumentException( + __METHOD__ . ' with a non-empty prefix is no longer supported.' + ); } - return $results[$prefix]; + // Keep this in sync with the omit-lazy option in self::getQueryInfo(). + return [ 'metadata' ]; } /** @@ -403,8 +442,15 @@ class LocalFile extends File { ? $this->repo->getMasterDB() : $this->repo->getReplicaDB(); - $row = $dbr->selectRow( 'image', $this->getCacheFields( 'img_' ), - [ 'img_name' => $this->getName() ], $fname ); + $fileQuery = static::getQueryInfo(); + $row = $dbr->selectRow( + $fileQuery['tables'], + $fileQuery['fields'], + [ 'img_name' => $this->getName() ], + $fname, + [], + $fileQuery['joins'] + ); if ( $row ) { $this->loadFromRow( $row ); @@ -423,9 +469,9 @@ class LocalFile extends File { # Unconditionally set loaded=true, we don't want the accessors constantly rechecking $this->extraDataLoaded = true; - $fieldMap = $this->loadFieldsWithTimestamp( $this->repo->getReplicaDB(), $fname ); + $fieldMap = $this->loadExtraFieldsWithTimestamp( $this->repo->getReplicaDB(), $fname ); if ( !$fieldMap ) { - $fieldMap = $this->loadFieldsWithTimestamp( $this->repo->getMasterDB(), $fname ); + $fieldMap = $this->loadExtraFieldsWithTimestamp( $this->repo->getMasterDB(), $fname ); } if ( $fieldMap ) { @@ -442,26 +488,46 @@ class LocalFile extends File { * @param string $fname * @return array|bool */ - private function loadFieldsWithTimestamp( $dbr, $fname ) { + private function loadExtraFieldsWithTimestamp( $dbr, $fname ) { $fieldMap = false; - $row = $dbr->selectRow( 'image', $this->getLazyCacheFields( 'img_' ), [ + $fileQuery = self::getQueryInfo( [ 'omit-nonlazy' ] ); + $row = $dbr->selectRow( + $fileQuery['tables'], + $fileQuery['fields'], + [ 'img_name' => $this->getName(), - 'img_timestamp' => $dbr->timestamp( $this->getTimestamp() ) - ], $fname ); + 'img_timestamp' => $dbr->timestamp( $this->getTimestamp() ), + ], + $fname, + [], + $fileQuery['joins'] + ); if ( $row ) { $fieldMap = $this->unprefixRow( $row, 'img_' ); } else { # File may have been uploaded over in the meantime; check the old versions - $row = $dbr->selectRow( 'oldimage', $this->getLazyCacheFields( 'oi_' ), [ + $fileQuery = OldLocalFile::getQueryInfo( [ 'omit-nonlazy' ] ); + $row = $dbr->selectRow( + $fileQuery['tables'], + $fileQuery['fields'], + [ 'oi_name' => $this->getName(), - 'oi_timestamp' => $dbr->timestamp( $this->getTimestamp() ) - ], $fname ); + 'oi_timestamp' => $dbr->timestamp( $this->getTimestamp() ), + ], + $fname, + [], + $fileQuery['joins'] + ); if ( $row ) { $fieldMap = $this->unprefixRow( $row, 'oi_' ); } } + if ( isset( $fieldMap['metadata'] ) ) { + $fieldMap['metadata'] = $this->repo->getReplicaDB()->decodeBlob( $fieldMap['metadata'] ); + } + return $fieldMap; } @@ -499,6 +565,9 @@ class LocalFile extends File { function decodeRow( $row, $prefix = 'img_' ) { $decoded = $this->unprefixRow( $row, $prefix ); + $decoded['description'] = CommentStore::newKey( 'description' ) + ->getComment( (object)$decoded )->text; + $decoded['timestamp'] = wfTimestamp( TS_MW, $decoded['timestamp'] ); $decoded['metadata'] = $this->repo->getReplicaDB()->decodeBlob( $decoded['metadata'] ); @@ -536,10 +605,6 @@ class LocalFile extends File { $this->dataLoaded = true; $this->extraDataLoaded = true; - $this->description = CommentStore::newKey( "{$prefix}description" ) - // $row is probably using getFields() from self::getCacheFields() - ->getCommentLegacy( wfGetDB( DB_REPLICA ), $row )->text; - $array = $this->decodeRow( $row, $prefix ); foreach ( $array as $name => $value ) { @@ -1069,9 +1134,12 @@ class LocalFile extends File { */ function getHistory( $limit = null, $start = null, $end = null, $inc = true ) { $dbr = $this->repo->getReplicaDB(); - $tables = [ 'oldimage' ]; - $fields = OldLocalFile::selectFields(); - $conds = $opts = $join_conds = []; + $oldFileQuery = OldLocalFile::getQueryInfo(); + + $tables = $oldFileQuery['tables']; + $fields = $oldFileQuery['fields']; + $join_conds = $oldFileQuery['joins']; + $conds = $opts = []; $eq = $inc ? '=' : ''; $conds[] = "oi_name = " . $dbr->addQuotes( $this->title->getDBkey() ); @@ -1127,13 +1195,16 @@ class LocalFile extends File { $dbr = $this->repo->getReplicaDB(); if ( $this->historyLine == 0 ) { // called for the first time, return line from cur - $this->historyRes = $dbr->select( 'image', - self::selectFields() + [ + $fileQuery = self::getQueryInfo(); + $this->historyRes = $dbr->select( $fileQuery['tables'], + $fileQuery['fields'] + [ 'oi_archive_name' => $dbr->addQuotes( '' ), 'oi_deleted' => 0, ], [ 'img_name' => $this->title->getDBkey() ], - $fname + $fname, + [], + $fileQuery['joins'] ); if ( 0 == $dbr->numRows( $this->historyRes ) ) { @@ -1142,12 +1213,14 @@ class LocalFile extends File { return false; } } elseif ( $this->historyLine == 1 ) { + $fileQuery = OldLocalFile::getQueryInfo(); $this->historyRes = $dbr->select( - 'oldimage', - OldLocalFile::selectFields(), + $fileQuery['tables'], + $fileQuery['fields'], [ 'oi_name' => $this->title->getDBkey() ], $fname, - [ 'ORDER BY' => 'oi_timestamp DESC' ] + [ 'ORDER BY' => 'oi_timestamp DESC' ], + $fileQuery['joins'] ); } $this->historyLine++; @@ -2418,22 +2491,23 @@ class LocalFileDeleteBatch { } if ( count( $oldRels ) ) { + $fileQuery = OldLocalFile::getQueryInfo(); $res = $dbw->select( - 'oldimage', - OldLocalFile::selectFields(), + $fileQuery['tables'], + $fileQuery['fields'], [ 'oi_name' => $this->file->getName(), 'oi_archive_name' => array_keys( $oldRels ) ], __METHOD__, - [ 'FOR UPDATE' ] + [ 'FOR UPDATE' ], + $fileQuery['joins'] ); $rowsInsert = []; if ( $res->numRows() ) { $reason = $commentStoreFaReason->createComment( $dbw, $this->reason ); foreach ( $res as $row ) { - // Legacy from OldLocalFile::selectFields() just above - $comment = $commentStoreOiDesc->getCommentLegacy( $dbw, $row ); + $comment = $commentStoreOiDesc->getComment( $row ); $rowsInsert[] = [ // Deletion-specific fields 'fa_storage_group' => 'deleted', @@ -2680,12 +2754,14 @@ class LocalFileRestoreBatch { $conditions['fa_id'] = $this->ids; } + $arFileQuery = ArchivedFile::getQueryInfo(); $result = $dbw->select( - 'filearchive', - ArchivedFile::selectFields(), + $arFileQuery['tables'], + $arFileQuery['fields'], $conditions, __METHOD__, - [ 'ORDER BY' => 'fa_timestamp DESC' ] + [ 'ORDER BY' => 'fa_timestamp DESC' ], + $arFileQuery['joins'] ); $idsPresent = []; @@ -2745,8 +2821,7 @@ class LocalFileRestoreBatch { ]; } - // Legacy from ArchivedFile::selectFields() just above - $comment = $commentStoreFaDesc->getCommentLegacy( $dbw, $row ); + $comment = $commentStoreFaDesc->getComment( $row ); if ( $first && !$exists ) { // This revision will be published as the new current version $destRel = $this->file->getRel(); diff --git a/includes/filerepo/file/OldLocalFile.php b/includes/filerepo/file/OldLocalFile.php index ee172e1143..6833a3880e 100644 --- a/includes/filerepo/file/OldLocalFile.php +++ b/includes/filerepo/file/OldLocalFile.php @@ -93,7 +93,10 @@ class OldLocalFile extends LocalFile { $conds['oi_timestamp'] = $dbr->timestamp( $timestamp ); } - $row = $dbr->selectRow( 'oldimage', self::selectFields(), $conds, __METHOD__ ); + $fileQuery = self::getQueryInfo(); + $row = $dbr->selectRow( + $fileQuery['tables'], $fileQuery['fields'], $conds, __METHOD__, [], $fileQuery['joins'] + ); if ( $row ) { return self::newFromRow( $row, $repo ); } else { @@ -103,8 +106,7 @@ class OldLocalFile extends LocalFile { /** * Fields in the oldimage table - * @todo Deprecate this in favor of a method that returns tables and joins - * as well, and use CommentStore::getJoin(). + * @deprecated since 1.31, use self::getQueryInfo() instead. * @return array */ static function selectFields() { @@ -127,6 +129,52 @@ class OldLocalFile extends LocalFile { ] + CommentStore::newKey( 'oi_description' )->getFields(); } + /** + * Return the tables, fields, and join conditions to be selected to create + * a new oldlocalfile object. + * @since 1.31 + * @param string[] $options + * - omit-lazy: Omit fields that are lazily cached. + * @return array With three keys: + * - tables: (string[]) to include in the `$table` to `IDatabase->select()` + * - fields: (string[]) to include in the `$vars` to `IDatabase->select()` + * - joins: (array) to include in the `$join_conds` to `IDatabase->select()` + */ + public static function getQueryInfo( array $options = [] ) { + $commentQuery = CommentStore::newKey( 'oi_description' )->getJoin(); + $ret = [ + 'tables' => [ 'oldimage' ] + $commentQuery['tables'], + 'fields' => [ + 'oi_name', + 'oi_archive_name', + 'oi_size', + 'oi_width', + 'oi_height', + 'oi_bits', + 'oi_media_type', + 'oi_major_mime', + 'oi_minor_mime', + 'oi_user', + 'oi_user_text', + 'oi_timestamp', + 'oi_deleted', + 'oi_sha1', + ] + $commentQuery['fields'], + 'joins' => $commentQuery['joins'], + ]; + + if ( in_array( 'omit-nonlazy', $options, true ) ) { + // Internal use only for getting only the lazy fields + $ret['fields'] = []; + } + if ( !in_array( 'omit-lazy', $options, true ) ) { + // Note: Keep this in sync with self::getLazyCacheFields() + $ret['fields'][] = 'oi_metadata'; + } + + return $ret; + } + /** * @param Title $title * @param FileRepo $repo @@ -188,8 +236,15 @@ class OldLocalFile extends LocalFile { } else { $conds['oi_timestamp'] = $dbr->timestamp( $this->requestedTime ); } - $row = $dbr->selectRow( 'oldimage', $this->getCacheFields( 'oi_' ), - $conds, __METHOD__, [ 'ORDER BY' => 'oi_timestamp DESC' ] ); + $fileQuery = static::getQueryInfo(); + $row = $dbr->selectRow( + $fileQuery['tables'], + $fileQuery['fields'], + $conds, + __METHOD__, + [ 'ORDER BY' => 'oi_timestamp DESC' ], + $fileQuery['joins'] + ); if ( $row ) { $this->loadFromRow( $row, 'oi_' ); } else { @@ -209,14 +264,27 @@ class OldLocalFile extends LocalFile { } else { $conds['oi_timestamp'] = $dbr->timestamp( $this->requestedTime ); } + $fileQuery = static::getQueryInfo( [ 'omit-nonlazy' ] ); // In theory the file could have just been renamed/deleted...oh well - $row = $dbr->selectRow( 'oldimage', $this->getLazyCacheFields( 'oi_' ), - $conds, __METHOD__, [ 'ORDER BY' => 'oi_timestamp DESC' ] ); + $row = $dbr->selectRow( + $fileQuery['tables'], + $fileQuery['fields'], + $conds, + __METHOD__, + [ 'ORDER BY' => 'oi_timestamp DESC' ], + $fileQuery['joins'] + ); if ( !$row ) { // fallback to master $dbr = $this->repo->getMasterDB(); - $row = $dbr->selectRow( 'oldimage', $this->getLazyCacheFields( 'oi_' ), - $conds, __METHOD__, [ 'ORDER BY' => 'oi_timestamp DESC' ] ); + $row = $dbr->selectRow( + $fileQuery['tables'], + $fileQuery['fields'], + $conds, + __METHOD__, + [ 'ORDER BY' => 'oi_timestamp DESC' ], + $fileQuery['joins'] + ); } if ( $row ) { @@ -228,11 +296,8 @@ class OldLocalFile extends LocalFile { } } - /** - * @param string $prefix - * @return array - */ - function getCacheFields( $prefix = 'img_' ) { + /** @inheritDoc */ + protected function getCacheFields( $prefix = 'img_' ) { $fields = parent::getCacheFields( $prefix ); $fields[] = $prefix . 'archive_name'; $fields[] = $prefix . 'deleted'; diff --git a/includes/installer/i18n/es.json b/includes/installer/i18n/es.json index 1db63a2ccf..7d7e47b6fd 100644 --- a/includes/installer/i18n/es.json +++ b/includes/installer/i18n/es.json @@ -81,7 +81,7 @@ "config-env-hhvm": "HHVM $1 está instalado.", "config-unicode-using-intl": "Usando la [http://pecl.php.net/intl extensión intl PECL] para la normalización Unicode.", "config-unicode-pure-php-warning": "Advertencia: la [http://pecl.php.net/intl extensión intl] no está disponible para efectuar la normalización Unicode. Se utilizará la implementación más lenta en PHP puro.\nSi tu web tiene mucho tráfico, te recomendamos leer acerca de la [https://www.mediawiki.org/wiki/Special:MyLanguage/Unicode_normalization_considerations normalización Unicode].", - "config-unicode-update-warning": "Warning: la versión instalada del contenedor de normalización Unicode usa una versión antigua de la biblioteca del [http://site.icu-project.org/ proyecto ICU].\nDeberás [https://www.mediawiki.org/wiki/Special:MyLanguage/Unicode_normalization_considerations actualizar] si realmente deseas usar Unicode.", + "config-unicode-update-warning": "Atención: la versión instalada del contenedor de normalización de Unicode utiliza una versión anticuada de la biblioteca del [http://site.icu-project.org/ proyecto ICU].\nDeberías [https://www.mediawiki.org/wiki/Special:MyLanguage/Unicode_normalization_considerations modernizarla] si te interesa utilizar Unicode.", "config-no-db": "No se encontró un controlador adecuado para la base de datos. Necesitas instalar un controlador de base de datos para PHP.\n{{PLURAL:$2|Se admite el siguiente gestor de bases de datos|Se admiten los siguientes gestores de bases de datos}}: $1.\n\nSi compilaste PHP por tu cuenta, debes reconfigurarlo activando un cliente de base de datos, por ejemplo, mediante ./configure --with-mysqli.\nSi instalaste PHP desde un paquete de Debian o Ubuntu, también debes instalar, por ejemplo, el paquete php5-mysql.", "config-outdated-sqlite": "Advertencia: tienes SQLite $1, que es inferior a la mínima versión requerida: $2. SQLite no estará disponible.", "config-no-fts3": "Advertencia: SQLite está compilado sin el [//sqlite.org/fts3.html módulo FTS3]. Las funcionalidades de búsqueda no estarán disponibles en esta instalación.", @@ -107,7 +107,7 @@ "config-using-uri": "Utilizando la URL del servidor \"$1$2\".", "config-uploads-not-safe": "Advertencia: tu directorio predeterminado para las cargas, $1, es vulnerable a la ejecución de scripts arbitrarios.\nAunque MediaWiki comprueba todos los archivos cargados por si hubiese amenazas de seguridad, es altamente recomendable [https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:Security#Upload_security cerrar esta vulnerabilidad de seguridad] antes de activar las cargas.", "config-no-cli-uploads-check": "Advertencia: tu directorio predeterminado para cargas ($1) no está comprobado contra la vulnerabilidad\n de ejecución arbitraria de \"scripts\" durante la instalación por línea de comandos.", - "config-brokenlibxml": "El sistema tiene una combinación de versiones de PHP y de libxml2 que es poco confiable y puede provocar corrupción oculta en los datos de MediaWiki y otras aplicaciones web.\nActualiza a libxml2 2.7.3 o posterior ([https://bugs.php.net/bug.php?id=45996 bug reportado con PHP]).\nInstalación abortada.", + "config-brokenlibxml": "El sistema utiliza una combinación de versiones de PHP y de libxml2 que es poco fiable y puede provocar daños ocultos en los datos de MediaWiki y otras aplicaciones web.\nActualiza a libxml2 2.7.3 o posterior ([https://bugs.php.net/bug.php?id=45996 defecto informado a PHP]).\nSe interrumpió la instalación.", "config-suhosin-max-value-length": "Suhosin está instalado y limita el parámetro length GET a $1 bytes.\nEl componente ResourceLoader (gestor de recursos) de MediaWiki trabajará en este límite, pero eso perjudicará el rendimiento.\nSi es posible, deberías establecer suhosin.get.max_value_length en el valor 1024 o superior en php.ini y establecer $wgResourceLoaderMaxQueryLength en el mismo valor en php.ini.", "config-using-32bit": "Atención: parece que el sistema funciona con enteros de 32 bits. Esto está [https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:32-bit desaconsejado].", "config-db-type": "Tipo de base de datos:", @@ -192,7 +192,7 @@ "config-mysql-engine": "Motor de almacenamiento:", "config-mysql-innodb": "InnoDB", "config-mysql-myisam": "MyISAM", - "config-mysql-myisam-dep": "Advertencia: has seleccionado MyISAM como motor de almacenamiento de MySQL, el cual no está recomendado para usarse con MediaWiki, porque:\n* apenas soporta concurrencia debido al bloqueo de tablas\n* es más propenso a la corrupción que otros motores\n* el código MediaWiki no siempre controla MyISAM como debiera\n\nSi tu instalación de MySQL soporta InnoDB, es muy recomendable que lo elijas en su lugar.\nSi tu instalación de MySQL no soporta InnoDB, quizás es el momento de una actualización.", + "config-mysql-myisam-dep": "Atención: has seleccionado MyISAM como motor de almacenamiento de MySQL, el cual no está recomendado para usarse con MediaWiki, porque:\n* apenas admite la concurrencia debido al bloqueo de tablas\n* es más propenso a daños que otros motores\n* el código MediaWiki no siempre controla MyISAM como debería\n\nSi tu instalación de MySQL admite InnoDB, es muy recomendable que lo elijas en su lugar.\nSi tu instalación de MySQL no admite InnoDB, quizás es el momento de una modernización.", "config-mysql-only-myisam-dep": "Advertencia: solo se ha encontrado el motor de almacenamiento MyISAM para MySQL en esta máquina, y no se recomienda su uso con MediaWiki, porque:\n* apenas admite la concurrencia debido al bloqueo de tablas\n* es más propenso a daños que otros motores\n* el código de MediaWiki no siempre controla MyISAM como debería\n\nTu instalación de MySQL no admite InnoDB; quizás es el momento de una actualización.", "config-mysql-engine-help": "InnoDB es casi siempre la mejor opción, dado que soporta bien los accesos simultáneos.\n\nMyISAM puede ser más rápido en instalaciones con usuario único o de sólo lectura.\nLas bases de datos MyISAM tienden a corromperse más a menudo que las bases de datos InnoDB.", "config-mysql-charset": "Conjunto de caracteres de la base de datos:", @@ -221,7 +221,7 @@ "config-admin-password-confirm": "Repite la contraseña:", "config-admin-help": "Escribe aquí el nombre de usuario que desees, como por ejemplo \"Pedro Bloggs\".\nEste es el nombre que usarás para entrar al wiki.", "config-admin-name-blank": "Escribe un nombre de usuario de administrador.", - "config-admin-name-invalid": "El nombre de usuario especificado \"$1\" no es válido.\nEspecifica un nombre de usuario diferente.", + "config-admin-name-invalid": "El nombre de usuario especificado, «$1», no es válido.\nEspecifica un nombre de usuario diferente.", "config-admin-password-blank": "Escribe una contraseña para la cuenta de administrador.", "config-admin-password-mismatch": "Las dos contraseñas que ingresaste no coinciden.", "config-admin-email": "Dirección de correo electrónico:", @@ -271,9 +271,9 @@ "config-upload-help": "La subida de archivos potencialmente expone tu servidor a riesgos de seguridad.\nPara obtener más información, consulta la [https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:Security sección de seguridad] en el manual.\n\nPara activar la subida de archivos, cambia el modo en el subdirectorio images bajo el directorio raíz de MediaWiki para que el servidor web pueda escribir en él.\nLuego, activa esta opción.", "config-upload-deleted": "Directorio para los archivos eliminados:", "config-upload-deleted-help": "Elige un directorio en el que guardar los archivos eliminados.\nLo ideal es una carpeta no accesible desde la red.", - "config-logo": "URL del logo :", + "config-logo": "URL del logotipo:", "config-logo-help": "La apariencia predeterminada de MediaWiki incluye espacio para un logotipo de 135x160 píxeles encima del menú de la barra lateral.\nCarga una imagen de tamaño adecuado y escribe la dirección URL aquí.\n\nPuedes usar $wgStylePath o $wgScriptPath si tu logotipo es relativo a esas rutas.\n\nSi no deseas un logotipo, deja esta casilla en blanco.", - "config-instantcommons": "Habilitar Instant Commons", + "config-instantcommons": "Activar Instant Commons", "config-instantcommons-help": "[https://www.mediawiki.org/wiki/InstantCommons Instant Commons] es una característica que permite que los wikis puedan utilizar imágenes, sonidos y otros archivos multimedia que se encuentran en el sitio [https://commons.wikimedia.org/ Wikimedia Commons].\nPara ello, MediaWiki requiere acceso a Internet.\n\nPara obtener más información sobre esta función, incluidas las instrucciones sobre cómo configurarlo para otras wikis distintas de Wikimedia Commons, consulta [https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:$wgForeignFileRepos el manual].", "config-cc-error": "El selector de licencia de Creative Commons no dio resultado.\nEscribe el nombre de la licencia manualmente.", "config-cc-again": "Elegir otra vez...", @@ -313,9 +313,9 @@ "config-pg-no-create-privs": "La cuenta especificada para la instalación no tiene suficientes privilegios para crear una cuenta.", "config-pg-not-in-role": "La cuenta especificada para el usuario web ya existe.\nLa cuenta especificada para la instalación no es de un superusuario y no es miembro del grupo de usuarios con acceso a la web, por lo que es incapaz de crear objetos pertenecientes al usuario web.\n\nMediaWiki requiere actualmente que las tablas sean propiedad del usuario web. Especifica otro nombre de cuenta web, o haz clic en \"atrás\" y especifica un usuario de instalación con los privilegios convenientes.", "config-install-user": "Creando el usuario de la base de datos", - "config-install-user-alreadyexists": "El usuario \"$1\" ya existe", - "config-install-user-create-failed": "La creación del usuario \"$1\" falló: $2", - "config-install-user-grant-failed": "La concesión de permisos al usuario \"$1\" falló: $2", + "config-install-user-alreadyexists": "La cuenta de usuario «$1» ya existe", + "config-install-user-create-failed": "Falló la creación de la cuenta de usuario «$1»: $2", + "config-install-user-grant-failed": "Falló la concesión de permisos a la cuenta de usuario «$1»: $2", "config-install-user-missing": "El usuario especificado \"$1\" no existe.", "config-install-user-missing-create": "El usuario especificado \"$1\" no existe.\nHaz clic en la casilla \"Crear cuenta\" debajo si quieres crearlo.", "config-install-tables": "Creando tablas", @@ -341,9 +341,10 @@ "config-download-localsettings": "Descargar LocalSettings.php", "config-help": "ayuda", "config-help-tooltip": "haz clic para ampliar", - "config-nofile": "El archivo \"$1\" no se pudo encontrar. ¿Se ha eliminado?", + "config-nofile": "No se pudo encontrar el archivo «$1». Quizá se eliminó.", "config-extension-link": "¿Sabías que tu wiki admite [https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:Extensions extensiones]?\n\nPuedes navegar por las [https://www.mediawiki.org/wiki/Special:MyLanguage/Category:Extensions_by_category categorías] o visitar el [https://www.mediawiki.org/wiki/Extension_Matrix centro de extensiones] para ver una lista completa.", "config-skins-screenshots": "$1 (capturas de pantalla: $2)", + "config-skins-screenshot": "$1 ($2)", "config-screenshot": "captura de pantalla", "mainpagetext": "MediaWiki se ha instalado.", "mainpagedocfooter": "Consulta la [https://www.mediawiki.org/wiki/Special:MyLanguage/Help:Contents guía] para obtener información sobre el uso del software wiki.\n\n== Primeros pasos ==\n* [https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:Configuration_settings Lista de ajustes de configuración]\n* [https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:FAQ Preguntas frecuentes sobre MediaWiki]\n* [https://lists.wikimedia.org/mailman/listinfo/mediawiki-announce Lista de correo de anuncios de publicación de MediaWiki]\n* [https://www.mediawiki.org/wiki/Special:MyLanguage/Localisation#Translation_resources Traducir MediaWiki a tu idioma]\n* [https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:Combating_spam Aprende a combatir el spam en tu wiki]" diff --git a/includes/installer/i18n/ja.json b/includes/installer/i18n/ja.json index f0c121ca2b..3f226624cc 100644 --- a/includes/installer/i18n/ja.json +++ b/includes/installer/i18n/ja.json @@ -193,23 +193,23 @@ "config-mssql-sqlauth": "SQL Server 認証", "config-mssql-windowsauth": "Windows 認証", "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": "ウィキペディアの例に従い、多くのウィキは、コンテンツのページとは分離したポリシーページを'''プロジェクトの名前空間'''に持っています。\nこの名前空間内のページのページ名はすべて特定の接頭辞で始まります。それをここで指定できます。\n通常、この接頭辞はウィキ名に基づきますが、「#」や「:」のような区切り文字を含めることはできません。", + "config-project-namespace-help": "ウィキペディアの例に従い、多くのウィキではコンテンツのページとは分離したポリシーページを'''プロジェクト名前空間'''に持っています。\nこの名前空間内のページ名はすべて特定の接頭辞で始まり、この欄ではその指定ができます。\n通常、この接頭辞はウィキ名に基づきますが、「#」や「:」のような区切り文字を含めることはできません。", "config-ns-invalid": "指定した名前空間「$1」は無効です。\n別のプロジェクト名前空間を指定してください。", "config-ns-conflict": "指定された名前空間「\"$1\" 」は、MediaWikiのデフォルト名前空間と衝突しています。\n他のプロジェクト名前空間を指定してください。", "config-admin-box": "管理アカウント", "config-admin-name": "利用者名:", "config-admin-password": "パスワード:", "config-admin-password-confirm": "パスワードの再入力:", - "config-admin-help": "希望するユーザー名をここに入力してください (例:「Joe Bloggs」)。\nこの名前でこのウィキにログインすることになります。", - "config-admin-name-blank": "管理者のユーザー名を入力してください。", - "config-admin-name-invalid": "指定したユーザー名「$1」は無効です。\n別のユーザー名を指定してください。", + "config-admin-help": "希望する利用者名をここに入力してください (例:「Joe Bloggs」)。\nこの名前でこのウィキにログインすることになります。", + "config-admin-name-blank": "管理者の利用者名を入力してください。", + "config-admin-name-invalid": "指定した利用者名「$1」は無効です。\n別の利用者名を指定してください。", "config-admin-password-blank": "管理者アカウントのパスワードを入力してください。", "config-admin-password-mismatch": "入力された2つのパスワードが一致しません。", "config-admin-email": "メールアドレス:", @@ -221,7 +221,7 @@ "config-subscribe-help": "これは、リリースの告知 (重要なセキュリティに関する案内を含む) に使用される、流量が少ないメーリングリストです。\nこのメーリングリストを購読して、新しいバージョンが出た場合にMediaWikiを更新してください。", "config-subscribe-noemail": "メールアドレスなしでリリースアナウンスのメーリングリストを購読しようとしています。\nメーリングリストを購読する場合にはメールアドレスを入力してください。", "config-pingback": "このインストールに関するデータをMediaWikiの開発者と共有する。", - "config-pingback-help": "もしこのオプションを選択すると、メディアウィキは定期的にhttps://www.mediawiki.orgとメディアウィキのインスタンスに関する基本データを呼び出します。このデータは例えばシステムのタイプ、PHPのバージョンと選択したデータベースのバックエンドなどを含んでいます。メディアウィキ財団はメディアウィキ開発者とこの情報を共有し、将来の開発の方向付けに役立たせます。ご使用のシステムに送るデータは次のとおりです。\n
$1
", + "config-pingback-help": "もし下記のオプションを有効にした場合、MediaWiki は定期的にこの MediaWiki インスタンスに関する基本データとともに https://www.mediawiki.org を呼び出します。このデータは例えばシステムのタイプ、PHPのバージョンと選択したデータベースのバックエンドなどを含んでいます。ウィキメディア財団は MediaWiki 開発者とこの情報を共有し、将来の開発に役立たせます。ご使用のシステムに送るデータは次のとおりです。\n
$1
", "config-almost-done": "これでほぼ終わりました!\n残りの設定を飛ばして、ウィキを今すぐインストールできます。", "config-optional-continue": "私にもっと質問してください。", "config-optional-skip": "もう飽きてしまったので、とにかくウィキをインストールしてください。", @@ -317,7 +317,7 @@ "config-insecure-keys": "警告: インストール中に生成されたセキュアキー ($1) は完璧に安全ではありません。手動で変更することを検討してください。", "config-install-updates": "不要な更新を実行するのを防ぐ", "config-install-updates-failed": "エラー: 更新キーをテーブルに挿入する際に失敗しました。以下のエラーが起こっています: $1", - "config-install-sysop": "管理者のアカウントの作成", + "config-install-sysop": "管理者アカウントの作成", "config-install-subscribe-fail": "mediawiki-announce を購読できませんでした: $1", "config-install-subscribe-notpossible": "cURL がインストールされていないため、allow_url_fopen を利用できません。", "config-install-mainpage": "メインページを既定の内容で作成", diff --git a/includes/jobqueue/jobs/CategoryMembershipChangeJob.php b/includes/jobqueue/jobs/CategoryMembershipChangeJob.php index 3907fc65ec..55c1367c23 100644 --- a/includes/jobqueue/jobs/CategoryMembershipChangeJob.php +++ b/includes/jobqueue/jobs/CategoryMembershipChangeJob.php @@ -115,16 +115,18 @@ class CategoryMembershipChangeJob extends Job { // Find revisions to this page made around and after this revision which lack category // notifications in recent changes. This lets jobs pick up were the last one left off. $encCutoff = $dbr->addQuotes( $dbr->timestamp( $cutoffUnix ) ); + $revQuery = Revision::getQueryInfo(); $res = $dbr->select( - 'revision', - Revision::selectFields(), + $revQuery['tables'], + $revQuery['fields'], [ 'rev_page' => $page->getId(), "rev_timestamp > $encCutoff" . " OR (rev_timestamp = $encCutoff AND rev_id > $lastRevId)" ], __METHOD__, - [ 'ORDER BY' => 'rev_timestamp ASC, rev_id ASC' ] + [ 'ORDER BY' => 'rev_timestamp ASC, rev_id ASC' ], + $revQuery['joins'] ); // Apply all category updates in revision timestamp order diff --git a/includes/jobqueue/jobs/RecentChangesUpdateJob.php b/includes/jobqueue/jobs/RecentChangesUpdateJob.php index 6f349d4447..a92ae96074 100644 --- a/includes/jobqueue/jobs/RecentChangesUpdateJob.php +++ b/includes/jobqueue/jobs/RecentChangesUpdateJob.php @@ -85,14 +85,17 @@ class RecentChangesUpdateJob extends Job { $factory = MediaWikiServices::getInstance()->getDBLoadBalancerFactory(); $ticket = $factory->getEmptyTransactionTicket( __METHOD__ ); $cutoff = $dbw->timestamp( time() - $wgRCMaxAge ); + $rcQuery = RecentChange::getQueryInfo(); do { $rcIds = []; $rows = []; - $res = $dbw->select( 'recentchanges', - RecentChange::selectFields(), + $res = $dbw->select( + $rcQuery['tables'], + $rcQuery['fields'], [ 'rc_timestamp < ' . $dbw->addQuotes( $cutoff ) ], __METHOD__, - [ 'LIMIT' => $wgUpdateRowsPerQuery ] + [ 'LIMIT' => $wgUpdateRowsPerQuery ], + $rcQuery['joins'] ); foreach ( $res as $row ) { $rcIds[] = $row->rc_id; diff --git a/includes/libs/objectcache/WANObjectCache.php b/includes/libs/objectcache/WANObjectCache.php index 0531d7f709..c6aac9a0ed 100644 --- a/includes/libs/objectcache/WANObjectCache.php +++ b/includes/libs/objectcache/WANObjectCache.php @@ -1119,7 +1119,15 @@ class WANObjectCache implements IExpiringStore, LoggerAwareInterface { * $setOpts += Database::getCacheSetOptions( $dbr ); * * // Load the row for this file - * $row = $dbr->selectRow( 'file', File::selectFields(), [ 'id' => $id ], __METHOD__ ); + * $queryInfo = File::getQueryInfo(); + * $row = $dbr->selectRow( + * $queryInfo['tables'], + * $queryInfo['fields'], + * [ 'id' => $id ], + * __METHOD__, + * [], + * $queryInfo['joins'] + * ); * * return $row ? (array)$row : false; * }, @@ -1205,7 +1213,15 @@ class WANObjectCache implements IExpiringStore, LoggerAwareInterface { * * // Load the rows for these files * $rows = []; - * $res = $dbr->select( 'file', File::selectFields(), [ 'id' => $ids ], __METHOD__ ); + * $queryInfo = File::getQueryInfo(); + * $res = $dbr->select( + * $queryInfo['tables'], + * $queryInfo['fields'], + * [ 'id' => $ids ], + * __METHOD__, + * [], + * $queryInfo['joins'] + * ); * foreach ( $res as $row ) { * $rows[$row->id] = $row; * $mtime = wfTimestamp( TS_UNIX, $row->timestamp ); diff --git a/includes/libs/rdbms/database/Database.php b/includes/libs/rdbms/database/Database.php index c04e167738..a9dd07483f 100644 --- a/includes/libs/rdbms/database/Database.php +++ b/includes/libs/rdbms/database/Database.php @@ -945,10 +945,12 @@ abstract class Database implements IDatabase, IMaintainableDatabase, LoggerAware # Update state tracking to reflect transaction loss due to disconnection $this->handleSessionLoss(); if ( $this->reconnect() ) { - $msg = __METHOD__ . ": lost connection to {$this->getServer()}; reconnected"; - $this->connLogger->warning( $msg ); + $msg = __METHOD__ . ': lost connection to {dbserver}; reconnected'; + $params = [ 'dbserver' => $this->getServer() ]; + $this->connLogger->warning( $msg, $params ); $this->queryLogger->warning( - "$msg:\n" . ( new RuntimeException() )->getTraceAsString() ); + "$msg:\n" . ( new RuntimeException() )->getTraceAsString(), + $params ); if ( !$recoverable ) { # Callers may catch the exception and continue to use the DB @@ -958,8 +960,8 @@ abstract class Database implements IDatabase, IMaintainableDatabase, LoggerAware $ret = $this->doProfiledQuery( $sql, $commentedSql, $isNonTempWrite, $fname ); } } else { - $msg = __METHOD__ . ": lost connection to {$this->getServer()} permanently"; - $this->connLogger->error( $msg ); + $msg = __METHOD__ . ': lost connection to {dbserver} permanently'; + $this->connLogger->error( $msg, [ 'dbserver' => $this->getServer() ] ); } } diff --git a/includes/libs/rdbms/loadbalancer/LoadBalancer.php b/includes/libs/rdbms/loadbalancer/LoadBalancer.php index 8393e2bcfe..1be8926bfa 100644 --- a/includes/libs/rdbms/loadbalancer/LoadBalancer.php +++ b/includes/libs/rdbms/loadbalancer/LoadBalancer.php @@ -568,7 +568,8 @@ class LoadBalancer implements ILoadBalancer { $knownReachedPos->hasReached( $this->mWaitForPos ) ) { $this->replLogger->debug( __METHOD__ . - ": replica DB $server known to be caught up (pos >= $knownReachedPos)." ); + ': replica DB {dbserver} known to be caught up (pos >= $knownReachedPos).', + [ 'dbserver' => $server ] ); return true; } @@ -576,13 +577,15 @@ class LoadBalancer implements ILoadBalancer { $conn = $this->getAnyOpenConnection( $index ); if ( !$conn ) { if ( !$open ) { - $this->replLogger->debug( __METHOD__ . ": no connection open for $server" ); + $this->replLogger->debug( __METHOD__ . ': no connection open for {dbserver}', + [ 'dbserver' => $server ] ); return false; } else { $conn = $this->openConnection( $index, self::DOMAIN_ANY ); if ( !$conn ) { - $this->replLogger->warning( __METHOD__ . ": failed to connect to $server" ); + $this->replLogger->warning( __METHOD__ . ': failed to connect to {dbserver}', + [ 'dbserver' => $server ] ); return false; } @@ -592,7 +595,8 @@ class LoadBalancer implements ILoadBalancer { } } - $this->replLogger->info( __METHOD__ . ": Waiting for replica DB $server to catch up..." ); + $this->replLogger->info( __METHOD__ . ': Waiting for replica DB {dbserver} to catch up...', + [ 'dbserver' => $server ] ); $timeout = $timeout ?: $this->mWaitTimeout; $result = $conn->masterPosWait( $this->mWaitForPos, $timeout ); diff --git a/includes/libs/xmp/XMP.php b/includes/libs/xmp/XMP.php index c46acc691c..0cc14669a7 100644 --- a/includes/libs/xmp/XMP.php +++ b/includes/libs/xmp/XMP.php @@ -388,7 +388,7 @@ class XMPReader implements LoggerAwareInterface { } } catch ( Exception $e ) { $this->logger->warning( - '{method} Exception caught while parsing: ' . $e->getMessage(), + '{method} {exception}', [ 'method' => __METHOD__, 'exception' => $e, @@ -420,7 +420,8 @@ class XMPReader implements LoggerAwareInterface { || $this->results['xmp-special']['HasExtendedXMP'] !== $guid ) { $this->logger->info( __METHOD__ . - " Ignoring XMPExtended block due to wrong guid (guid= '$guid')" ); + " Ignoring XMPExtended block due to wrong guid (guid= '{guid}')", + [ 'guid' => 'guid' ] ); return false; } @@ -954,8 +955,8 @@ class XMPReader implements LoggerAwareInterface { } else { // something else we don't recognize, like a qualifier maybe. $this->logger->info( __METHOD__ . - " Encountered element <$elm> where only expecting character data as value of " . - $this->curItem[0] ); + " Encountered element <{element}> where only expecting character data as value of {curitem}", + [ 'element' => $elm, 'curitem' => $this->curItem[0] ] ); array_unshift( $this->mode, self::MODE_IGNORE ); array_unshift( $this->curItem, $elm ); } @@ -1005,8 +1006,10 @@ class XMPReader implements LoggerAwareInterface { // a child of a struct), then something weird is // happening, so ignore this element and its children. - $this->logger->warning( "Encountered <$ns:$tag> outside" - . " of its expected parent. Ignoring." ); + $this->logger->warning( + 'Encountered <{element}> outside of its expected parent. Ignoring.', + [ 'element' => "$ns:$tag" ] + ); array_unshift( $this->mode, self::MODE_IGNORE ); array_unshift( $this->curItem, $ns . ' ' . $tag ); @@ -1027,7 +1030,8 @@ class XMPReader implements LoggerAwareInterface { } } else { // This element is not on our list of allowed elements so ignore. - $this->logger->debug( __METHOD__ . " Ignoring unrecognized element <$ns:$tag>." ); + $this->logger->debug( __METHOD__ . ' Ignoring unrecognized element <{element}>.', + [ 'element' => "$ns:$tag" ] ); array_unshift( $this->mode, self::MODE_IGNORE ); array_unshift( $this->curItem, $ns . ' ' . $tag ); diff --git a/includes/logging/LogEntry.php b/includes/logging/LogEntry.php index 8b51932be7..bf35d78d25 100644 --- a/includes/logging/LogEntry.php +++ b/includes/logging/LogEntry.php @@ -383,7 +383,7 @@ class RCDatabaseLogEntry extends DatabaseLogEntry { public function getComment() { return CommentStore::newKey( 'rc_comment' ) - // Legacy because the row probably used RecentChange::selectFields() + // Legacy because the row may have used RecentChange::selectFields() ->getCommentLegacy( wfGetDB( DB_REPLICA ), $this->row )->text; } diff --git a/includes/logging/LogPager.php b/includes/logging/LogPager.php index f79fcfa61c..df432e1517 100644 --- a/includes/logging/LogPager.php +++ b/includes/logging/LogPager.php @@ -97,13 +97,11 @@ class LogPager extends ReverseChronologicalPager { return $filters; } foreach ( $wgFilterLogTypes as $type => $default ) { - // Avoid silly filtering - if ( $type !== 'patrol' || $this->getUser()->useNPPatrol() ) { - $hide = $this->getRequest()->getInt( "hide_{$type}_log", $default ); - $filters[$type] = $hide; - if ( $hide ) { - $this->mConds[] = 'log_type != ' . $this->mDb->addQuotes( $type ); - } + $hide = $this->getRequest()->getInt( "hide_{$type}_log", $default ); + + $filters[$type] = $hide; + if ( $hide ) { + $this->mConds[] = 'log_type != ' . $this->mDb->addQuotes( $type ); } } diff --git a/includes/page/Article.php b/includes/page/Article.php index 3767ecc141..df189af341 100644 --- a/includes/page/Article.php +++ b/includes/page/Article.php @@ -1179,7 +1179,8 @@ class Article implements Page { $cache = MediaWikiServices::getInstance()->getMainObjectStash(); $key = $cache->makeKey( 'page-recent-delete', md5( $title->getPrefixedText() ) ); $loggedIn = $this->getContext()->getUser()->isLoggedIn(); - if ( $loggedIn || $cache->get( $key ) ) { + $sessionExists = $this->getContext()->getRequest()->getSession()->isPersistent(); + if ( $loggedIn || $cache->get( $key ) || $sessionExists ) { $logTypes = [ 'delete', 'move', 'protect' ]; $dbr = wfGetDB( DB_REPLICA ); @@ -1196,7 +1197,7 @@ class Article implements Page { 'lim' => 10, 'conds' => $conds, 'showIfEmpty' => false, - 'msgKey' => [ $loggedIn + 'msgKey' => [ $loggedIn || $sessionExists ? 'moveddeleted-notice' : 'moveddeleted-notice-recent' ] diff --git a/includes/page/PageArchive.php b/includes/page/PageArchive.php index af936cc730..209551b296 100644 --- a/includes/page/PageArchive.php +++ b/includes/page/PageArchive.php @@ -231,12 +231,14 @@ class PageArchive { } $dbr = wfGetDB( DB_REPLICA ); + $fileQuery = ArchivedFile::getQueryInfo(); return $dbr->select( - 'filearchive', - ArchivedFile::selectFields(), + $fileQuery['tables'], + $fileQuery['fields'], [ 'fa_name' => $this->title->getDBkey() ], __METHOD__, - [ 'ORDER BY' => 'fa_timestamp DESC' ] + [ 'ORDER BY' => 'fa_timestamp DESC' ], + $fileQuery['joins'] ); } @@ -249,34 +251,11 @@ class PageArchive { */ public function getRevision( $timestamp ) { $dbr = wfGetDB( DB_REPLICA ); - $commentQuery = CommentStore::newKey( 'ar_comment' )->getJoin(); - - $tables = [ 'archive' ] + $commentQuery['tables']; - - $fields = [ - 'ar_rev_id', - 'ar_text', - 'ar_user', - 'ar_user_text', - 'ar_timestamp', - 'ar_minor_edit', - 'ar_flags', - 'ar_text_id', - 'ar_deleted', - 'ar_len', - 'ar_sha1', - ] + $commentQuery['fields']; - - if ( $this->config->get( 'ContentHandlerUseDB' ) ) { - $fields[] = 'ar_content_format'; - $fields[] = 'ar_content_model'; - } - - $join_conds = [] + $commentQuery['joins']; + $arQuery = Revision::getArchiveQueryInfo(); $row = $dbr->selectRow( - $tables, - $fields, + $arQuery['tables'], + $arQuery['fields'], [ 'ar_namespace' => $this->title->getNamespace(), 'ar_title' => $this->title->getDBkey(), @@ -284,7 +263,7 @@ class PageArchive { ], __METHOD__, [], - $join_conds + $arQuery['joins'] ); if ( $row ) { diff --git a/includes/page/WikiPage.php b/includes/page/WikiPage.php index 146c054cd3..946c7f062b 100644 --- a/includes/page/WikiPage.php +++ b/includes/page/WikiPage.php @@ -158,8 +158,11 @@ class WikiPage implements Page, IDBAccessObject { $from = self::convertSelectType( $from ); $db = wfGetDB( $from === self::READ_LATEST ? DB_MASTER : DB_REPLICA ); + $pageQuery = self::getQueryInfo(); $row = $db->selectRow( - 'page', self::selectFields(), [ 'page_id' => $id ], __METHOD__ ); + $pageQuery['tables'], $pageQuery['fields'], [ 'page_id' => $id ], __METHOD__, + [], $pageQuery['joins'] + ); if ( !$row ) { return null; } @@ -277,6 +280,7 @@ class WikiPage implements Page, IDBAccessObject { * Return the list of revision fields that should be selected to create * a new page. * + * @deprecated since 1.31, use self::getQueryInfo() instead. * @return array */ public static function selectFields() { @@ -307,6 +311,47 @@ class WikiPage implements Page, IDBAccessObject { return $fields; } + /** + * Return the tables, fields, and join conditions to be selected to create + * a new page object. + * @since 1.31 + * @return array With three keys: + * - tables: (string[]) to include in the `$table` to `IDatabase->select()` + * - fields: (string[]) to include in the `$vars` to `IDatabase->select()` + * - joins: (array) to include in the `$join_conds` to `IDatabase->select()` + */ + public static function getQueryInfo() { + global $wgContentHandlerUseDB, $wgPageLanguageUseDB; + + $ret = [ + 'tables' => [ 'page' ], + 'fields' => [ + 'page_id', + 'page_namespace', + 'page_title', + 'page_restrictions', + 'page_is_redirect', + 'page_is_new', + 'page_random', + 'page_touched', + 'page_links_updated', + 'page_latest', + 'page_len', + ], + 'joins' => [], + ]; + + if ( $wgContentHandlerUseDB ) { + $ret['fields'][] = 'page_content_model'; + } + + if ( $wgPageLanguageUseDB ) { + $ret['fields'][] = 'page_lang'; + } + + return $ret; + } + /** * Fetch a page record with the given conditions * @param IDatabase $dbr @@ -315,14 +360,23 @@ class WikiPage implements Page, IDBAccessObject { * @return object|bool Database result resource, or false on failure */ protected function pageData( $dbr, $conditions, $options = [] ) { - $fields = self::selectFields(); + $pageQuery = self::getQueryInfo(); // Avoid PHP 7.1 warning of passing $this by reference $wikiPage = $this; - Hooks::run( 'ArticlePageDataBefore', [ &$wikiPage, &$fields ] ); + Hooks::run( 'ArticlePageDataBefore', [ + &$wikiPage, &$pageQuery['fields'], &$pageQuery['tables'], &$pageQuery['joins'] + ] ); - $row = $dbr->selectRow( 'page', $fields, $conditions, __METHOD__, $options ); + $row = $dbr->selectRow( + $pageQuery['tables'], + $pageQuery['fields'], + $conditions, + __METHOD__, + $options, + $pageQuery['joins'] + ); Hooks::run( 'ArticlePageDataAfter', [ &$wikiPage, &$row ] ); @@ -2788,13 +2842,13 @@ class WikiPage implements Page, IDBAccessObject { $revCommentStore = new CommentStore( 'rev_comment' ); $arCommentStore = new CommentStore( 'ar_comment' ); - $fields = Revision::selectFields(); + $revQuery = Revision::getQueryInfo(); $bitfield = false; // Bitfields to further suppress the content if ( $suppress ) { $bitfield = Revision::SUPPRESSED_ALL; - $fields = array_diff( $fields, [ 'rev_deleted' ] ); + $revQuery['fields'] = array_diff( $revQuery['fields'], [ 'rev_deleted' ] ); } // For now, shunt the revision data into the archive table. @@ -2805,14 +2859,13 @@ class WikiPage implements Page, IDBAccessObject { // the rev_deleted field, which is reserved for this purpose. // Get all of the page revisions - $commentQuery = $revCommentStore->getJoin(); $res = $dbw->select( - [ 'revision' ] + $commentQuery['tables'], - $fields + $commentQuery['fields'], + $revQuery['tables'], + $revQuery['fields'], [ 'rev_page' => $id ], __METHOD__, 'FOR UPDATE', - $commentQuery['joins'] + $revQuery['joins'] ); // Build their equivalent archive rows diff --git a/includes/revisiondelete/RevDelArchiveList.php b/includes/revisiondelete/RevDelArchiveList.php index 9afaf404c8..4f66cdae55 100644 --- a/includes/revisiondelete/RevDelArchiveList.php +++ b/includes/revisiondelete/RevDelArchiveList.php @@ -43,14 +43,15 @@ class RevDelArchiveList extends RevDelRevisionList { $timestamps[] = $db->timestamp( $id ); } - $tables = [ 'archive' ]; - $fields = Revision::selectArchiveFields(); + $arQuery = Revision::getArchiveQueryInfo(); + $tables = $arQuery['tables']; + $fields = $arQuery['fields']; $conds = [ 'ar_namespace' => $this->title->getNamespace(), 'ar_title' => $this->title->getDBkey(), 'ar_timestamp' => $timestamps, ]; - $join_conds = []; + $join_conds = $arQuery['joins']; $options = [ 'ORDER BY' => 'ar_timestamp DESC' ]; ChangeTags::modifyDisplayQuery( diff --git a/includes/revisiondelete/RevDelArchivedFileList.php b/includes/revisiondelete/RevDelArchivedFileList.php index 1d80d8696c..1ed87263f1 100644 --- a/includes/revisiondelete/RevDelArchivedFileList.php +++ b/includes/revisiondelete/RevDelArchivedFileList.php @@ -40,15 +40,17 @@ class RevDelArchivedFileList extends RevDelFileList { public function doQuery( $db ) { $ids = array_map( 'intval', $this->ids ); + $fileQuery = ArchivedFile::getQueryInfo(); return $db->select( - 'filearchive', - ArchivedFile::selectFields(), + $fileQuery['tables'], + $fileQuery['fields'], [ 'fa_name' => $this->title->getDBkey(), 'fa_id' => $ids ], __METHOD__, - [ 'ORDER BY' => 'fa_id DESC' ] + [ 'ORDER BY' => 'fa_id DESC' ], + $fileQuery['joins'] ); } diff --git a/includes/revisiondelete/RevDelFileList.php b/includes/revisiondelete/RevDelFileList.php index 77cf976762..6a6b86c099 100644 --- a/includes/revisiondelete/RevDelFileList.php +++ b/includes/revisiondelete/RevDelFileList.php @@ -60,15 +60,17 @@ class RevDelFileList extends RevDelList { $archiveNames[] = $timestamp . '!' . $this->title->getDBkey(); } + $oiQuery = OldLocalFile::getQueryInfo(); return $db->select( - 'oldimage', - OldLocalFile::selectFields(), + $oiQuery['tables'], + $oiQuery['fields'], [ 'oi_name' => $this->title->getDBkey(), 'oi_archive_name' => $archiveNames ], __METHOD__, - [ 'ORDER BY' => 'oi_timestamp DESC' ] + [ 'ORDER BY' => 'oi_timestamp DESC' ], + $oiQuery['joins'] ); } diff --git a/includes/revisiondelete/RevDelRevisionList.php b/includes/revisiondelete/RevDelRevisionList.php index 1ea6a381b5..07362c422f 100644 --- a/includes/revisiondelete/RevDelRevisionList.php +++ b/includes/revisiondelete/RevDelRevisionList.php @@ -62,9 +62,10 @@ class RevDelRevisionList extends RevDelList { */ public function doQuery( $db ) { $ids = array_map( 'intval', $this->ids ); + $revQuery = Revision::getQueryInfo( [ 'page', 'user' ] ); $queryInfo = [ - 'tables' => [ 'revision', 'page', 'user' ], - 'fields' => array_merge( Revision::selectFields(), Revision::selectUserFields() ), + 'tables' => $revQuery['tables'], + 'fields' => $revQuery['fields'], 'conds' => [ 'rev_page' => $this->title->getArticleID(), 'rev_id' => $ids, @@ -73,10 +74,7 @@ class RevDelRevisionList extends RevDelList { 'ORDER BY' => 'rev_id DESC', 'USE INDEX' => [ 'revision' => 'PRIMARY' ] // workaround for MySQL bug (T104313) ], - 'join_conds' => [ - 'page' => Revision::pageJoinCond(), - 'user' => Revision::userJoinCond(), - ], + 'join_conds' => $revQuery['joins'], ]; ChangeTags::modifyDisplayQuery( $queryInfo['tables'], @@ -100,14 +98,15 @@ class RevDelRevisionList extends RevDelList { return $live; } + $arQuery = Revision::getArchiveQueryInfo(); $archiveQueryInfo = [ - 'tables' => [ 'archive' ], - 'fields' => Revision::selectArchiveFields(), + 'tables' => $arQuery['tables'], + 'fields' => $arQuery['fields'], 'conds' => [ 'ar_rev_id' => $ids, ], 'options' => [ 'ORDER BY' => 'ar_rev_id DESC' ], - 'join_conds' => [], + 'join_conds' => $arQuery['joins'], ]; ChangeTags::modifyDisplayQuery( diff --git a/includes/shell/Command.php b/includes/shell/Command.php index 1816c5aed1..9f080d5141 100644 --- a/includes/shell/Command.php +++ b/includes/shell/Command.php @@ -57,7 +57,10 @@ class Command { private $method; /** @var bool */ - private $useStderr = false; + private $doIncludeStderr = false; + + /** @var bool */ + private $doLogStderr = false; /** @var bool */ private $everExecuted = false; @@ -180,7 +183,19 @@ class Command { * @return $this */ public function includeStderr( $yesno = true ) { - $this->useStderr = $yesno; + $this->doIncludeStderr = $yesno; + + return $this; + } + + /** + * When enabled, text sent to stderr will be logged with a level of 'error'. + * + * @param bool $yesno + * @return $this + */ + public function logStderr( $yesno = true ) { + $this->doLogStderr = $yesno; return $this; } @@ -235,7 +250,7 @@ class Command { $cmd = '/bin/bash ' . escapeshellarg( __DIR__ . '/limit.sh' ) . ' ' . escapeshellarg( $cmd ) . ' ' . escapeshellarg( - "MW_INCLUDE_STDERR=" . ( $this->useStderr ? '1' : '' ) . ';' . + "MW_INCLUDE_STDERR=" . ( $this->doIncludeStderr ? '1' : '' ) . ';' . "MW_CPU_LIMIT=$time; " . 'MW_CGROUP=' . escapeshellarg( $this->cgroup ) . '; ' . "MW_MEM_LIMIT=$mem; " . @@ -246,7 +261,7 @@ class Command { $useLogPipe = true; } } - if ( !$useLogPipe && $this->useStderr ) { + if ( !$useLogPipe && $this->doIncludeStderr ) { $cmd .= ' 2>&1'; } @@ -424,6 +439,15 @@ class Command { $this->logger->warning( "$logMsg: {command}", [ 'command' => $cmd ] ); } + if ( $errBuffer && $this->doLogStderr ) { + $this->logger->error( "Error running {command}: {error}", [ + 'command' => $cmd, + 'error' => $errBuffer, + 'exitcode' => $retval, + 'exception' => new Exception( 'Shell error' ), + ] ); + } + return new Result( $retval, $outBuffer, $errBuffer ); } } diff --git a/includes/shell/CommandFactory.php b/includes/shell/CommandFactory.php index c0b8f899ed..84dd50f71f 100644 --- a/includes/shell/CommandFactory.php +++ b/includes/shell/CommandFactory.php @@ -37,6 +37,9 @@ class CommandFactory { /** @var string|bool */ private $cgroup; + /** @var bool */ + private $doLogStderr = false; + /** * Constructor * @@ -49,6 +52,16 @@ class CommandFactory { $this->setLogger( new NullLogger() ); } + /** + * When enabled, text sent to stderr will be logged with a level of 'error'. + * + * @param bool $yesno + * @see Command::logStderr + */ + public function logStderr( $yesno = true ) { + $this->doLogStderr = $yesno; + } + /** * Instantiates a new Command * @@ -60,6 +73,7 @@ class CommandFactory { return $command ->limits( $this->limits ) - ->cgroup( $this->cgroup ); + ->cgroup( $this->cgroup ) + ->logStderr( $this->doLogStderr ); } } diff --git a/includes/specialpage/ChangesListSpecialPage.php b/includes/specialpage/ChangesListSpecialPage.php index eab31bcdbc..5194983964 100644 --- a/includes/specialpage/ChangesListSpecialPage.php +++ b/includes/specialpage/ChangesListSpecialPage.php @@ -1412,8 +1412,10 @@ abstract class ChangesListSpecialPage extends SpecialPage { protected function doMainQuery( $tables, $fields, $conds, $query_options, $join_conds, FormOptions $opts ) { - $tables[] = 'recentchanges'; - $fields = array_merge( RecentChange::selectFields(), $fields ); + $rcQuery = RecentChange::getQueryInfo(); + $tables = array_merge( $tables, $rcQuery['tables'] ); + $fields = array_merge( $rcQuery['fields'], $fields ); + $join_conds = array_merge( $join_conds, $rcQuery['joins'] ); ChangeTags::modifyDisplayQuery( $tables, diff --git a/includes/specials/SpecialMyLanguage.php b/includes/specials/SpecialMyLanguage.php index 9cb6d4b529..37d96f47cc 100644 --- a/includes/specials/SpecialMyLanguage.php +++ b/includes/specials/SpecialMyLanguage.php @@ -81,6 +81,7 @@ class SpecialMyLanguage extends RedirectSpecialArticle { } if ( !$base ) { + // No subpage provided or base page does not exist return null; } @@ -90,14 +91,38 @@ class SpecialMyLanguage extends RedirectSpecialArticle { } $uiCode = $this->getLanguage()->getCode(); + $wikiLangCode = $this->getConfig()->get( 'LanguageCode' ); + + if ( $uiCode === $wikiLangCode ) { + // Short circuit when the current UI language is the + // wiki's default language to avoid unnecessary page lookups. + return $base; + } + + // Check for a subpage in current UI language $proposed = $base->getSubpage( $uiCode ); - if ( $proposed && $proposed->exists() && $uiCode !== $base->getPageLanguage()->getCode() ) { + if ( $proposed && $proposed->exists() ) { return $proposed; - } elseif ( $provided && $provided->exists() ) { + } + + if ( $provided !== $base && $provided->exists() ) { + // Explicit language code given and the page exists return $provided; - } else { - return $base; } + + // Check for fallback languages specified by the UI language + $possibilities = Language::getFallbacksFor( $uiCode ); + foreach ( $possibilities as $lang ) { + if ( $lang !== $wikiLangCode ) { + $proposed = $base->getSubpage( $lang ); + if ( $proposed && $proposed->exists() ) { + return $proposed; + } + } + } + + // When all else has failed, return the base page + return $base; } /** diff --git a/includes/specials/SpecialRecentchanges.php b/includes/specials/SpecialRecentchanges.php index c3ce78e301..dfa13b6cd7 100644 --- a/includes/specials/SpecialRecentchanges.php +++ b/includes/specials/SpecialRecentchanges.php @@ -288,8 +288,10 @@ class SpecialRecentChanges extends ChangesListSpecialPage { $dbr = $this->getDB(); $user = $this->getUser(); - $tables[] = 'recentchanges'; - $fields = array_merge( RecentChange::selectFields(), $fields ); + $rcQuery = RecentChange::getQueryInfo(); + $tables = array_merge( $tables, $rcQuery['tables'] ); + $fields = array_merge( $rcQuery['fields'], $fields ); + $join_conds = array_merge( $join_conds, $rcQuery['joins'] ); // JOIN on watchlist for users if ( $user->isLoggedIn() && $user->isAllowed( 'viewmywatchlist' ) ) { diff --git a/includes/specials/SpecialRecentchangeslinked.php b/includes/specials/SpecialRecentchangeslinked.php index a13af55de5..99880de786 100644 --- a/includes/specials/SpecialRecentchangeslinked.php +++ b/includes/specials/SpecialRecentchangeslinked.php @@ -84,8 +84,10 @@ class SpecialRecentChangesLinked extends SpecialRecentChanges { $ns = $title->getNamespace(); $dbkey = $title->getDBkey(); - $tables[] = 'recentchanges'; - $select = array_merge( RecentChange::selectFields(), $select ); + $rcQuery = RecentChange::getQueryInfo(); + $tables = array_merge( $tables, $rcQuery['tables'] ); + $select = array_merge( $rcQuery['fields'], $select ); + $join_conds = array_merge( $join_conds, $rcQuery['joins'] ); // left join with watchlist table to highlight watched rows $uid = $this->getUser()->getId(); diff --git a/includes/specials/SpecialUndelete.php b/includes/specials/SpecialUndelete.php index 9cb34073a2..71dee3d832 100644 --- a/includes/specials/SpecialUndelete.php +++ b/includes/specials/SpecialUndelete.php @@ -969,7 +969,7 @@ class SpecialUndelete extends SpecialPage { $key = urlencode( $row->fa_storage_key ); $pageLink = $this->getFileLink( $file, $this->getPageTitle(), $ts, $key ); } else { - $pageLink = $this->getLanguage()->userTimeAndDate( $ts, $user ); + $pageLink = htmlspecialchars( $this->getLanguage()->userTimeAndDate( $ts, $user ) ); } $userLink = $this->getFileUser( $file ); $data = $this->msg( 'widthheight' )->numParams( $row->fa_width, $row->fa_height )->text(); @@ -1049,7 +1049,7 @@ class SpecialUndelete extends SpecialPage { $time = $this->getLanguage()->userTimeAndDate( $ts, $user ); if ( !$file->userCan( File::DELETED_FILE, $user ) ) { - return '' . $time . ''; + return '' . htmlspecialchars( $time ) . ''; } $link = $this->getLinkRenderer()->makeKnownLink( diff --git a/includes/specials/SpecialWatchlist.php b/includes/specials/SpecialWatchlist.php index 921a6dd465..ff62e9e603 100644 --- a/includes/specials/SpecialWatchlist.php +++ b/includes/specials/SpecialWatchlist.php @@ -357,8 +357,9 @@ class SpecialWatchlist extends ChangesListSpecialPage { $dbr = $this->getDB(); $user = $this->getUser(); - $tables = array_merge( [ 'recentchanges', 'watchlist' ], $tables ); - $fields = array_merge( RecentChange::selectFields(), $fields ); + $rcQuery = RecentChange::getQueryInfo(); + $tables = array_merge( $tables, $rcQuery['tables'], [ 'watchlist' ] ); + $fields = array_merge( $rcQuery['fields'], $fields ); $join_conds = array_merge( [ @@ -371,6 +372,7 @@ class SpecialWatchlist extends ChangesListSpecialPage { ], ], ], + $rcQuery['joins'], $join_conds ); diff --git a/includes/specials/pagers/ContribsPager.php b/includes/specials/pagers/ContribsPager.php index 979460cf8a..5936423128 100644 --- a/includes/specials/pagers/ContribsPager.php +++ b/includes/specials/pagers/ContribsPager.php @@ -175,79 +175,25 @@ class ContribsPager extends RangeChronologicalPager { } function getQueryInfo() { - list( $tables, $index, $userCond, $join_cond ) = $this->getUserCond(); - - $user = $this->getUser(); - $conds = array_merge( $userCond, $this->getNamespaceCond() ); - - // Paranoia: avoid brute force searches (T19342) - if ( !$user->isAllowed( 'deletedhistory' ) ) { - $conds[] = $this->mDb->bitAnd( 'rev_deleted', Revision::DELETED_USER ) . ' = 0'; - } elseif ( !$user->isAllowedAny( 'suppressrevision', 'viewsuppressed' ) ) { - $conds[] = $this->mDb->bitAnd( 'rev_deleted', Revision::SUPPRESSED_USER ) . - ' != ' . Revision::SUPPRESSED_USER; - } - - # Don't include orphaned revisions - $join_cond['page'] = Revision::pageJoinCond(); - # Get the current user name for accounts - $join_cond['user'] = Revision::userJoinCond(); - - $options = []; - if ( $index ) { - $options['USE INDEX'] = [ 'revision' => $index ]; - } - + $revQuery = Revision::getQueryInfo( [ 'page', 'user' ] ); $queryInfo = [ - 'tables' => $tables, - 'fields' => array_merge( - Revision::selectFields(), - Revision::selectUserFields(), - [ 'page_namespace', 'page_title', 'page_is_new', - 'page_latest', 'page_is_redirect', 'page_len' ] - ), - 'conds' => $conds, - 'options' => $options, - 'join_conds' => $join_cond + 'tables' => $revQuery['tables'], + 'fields' => $revQuery['fields'], + 'conds' => [], + 'options' => [], + 'join_conds' => $revQuery['joins'], ]; - // For IPv6, we use ipc_rev_timestamp on ip_changes as the index field, - // which will be referenced when parsing the results of a query. - if ( self::isQueryableRange( $this->target ) ) { - $queryInfo['fields'][] = 'ipc_rev_timestamp'; - } - - ChangeTags::modifyDisplayQuery( - $queryInfo['tables'], - $queryInfo['fields'], - $queryInfo['conds'], - $queryInfo['join_conds'], - $queryInfo['options'], - $this->tagFilter - ); - - // Avoid PHP 7.1 warning from passing $this by reference - $pager = $this; - Hooks::run( 'ContribsPager::getQueryInfo', [ &$pager, &$queryInfo ] ); - - return $queryInfo; - } - - function getUserCond() { - $condition = []; - $join_conds = []; - $tables = [ 'revision', 'page', 'user' ]; - $index = false; if ( $this->contribs == 'newbie' ) { $max = $this->mDb->selectField( 'user', 'max(user_id)', false, __METHOD__ ); - $condition[] = 'rev_user >' . (int)( $max - $max / 100 ); + $queryInfo['conds'][] = 'rev_user >' . (int)( $max - $max / 100 ); # ignore local groups with the bot right # @todo FIXME: Global groups may have 'bot' rights $groupsWithBotPermission = User::getGroupsWithPermission( 'bot' ); if ( count( $groupsWithBotPermission ) ) { - $tables[] = 'user_groups'; - $condition[] = 'ug_group IS NULL'; - $join_conds['user_groups'] = [ + $queryInfo['tables'][] = 'user_groups'; + $queryInfo['conds'][] = 'ug_group IS NULL'; + $queryInfo['join_conds']['user_groups'] = [ 'LEFT JOIN', [ 'ug_user = rev_user', 'ug_group' => $groupsWithBotPermission, @@ -259,46 +205,76 @@ class ContribsPager extends RangeChronologicalPager { // (T140537) Disallow looking too far in the past for 'newbies' queries. If the user requested // a timestamp offset far in the past such that there are no edits by users with user_ids in // the range, we would end up scanning all revisions from that offset until start of time. - $condition[] = 'rev_timestamp > ' . + $queryInfo['conds'][] = 'rev_timestamp > ' . $this->mDb->addQuotes( $this->mDb->timestamp( wfTimestamp() - 30 * 24 * 60 * 60 ) ); } else { $uid = User::idFromName( $this->target ); if ( $uid ) { - $condition['rev_user'] = $uid; - $index = 'user_timestamp'; + $queryInfo['conds']['rev_user'] = $uid; + $queryInfo['options']['USE INDEX']['revision'] = 'user_timestamp'; } else { $ipRangeConds = $this->getIpRangeConds( $this->mDb, $this->target ); if ( $ipRangeConds ) { - $tables[] = 'ip_changes'; - $join_conds['ip_changes'] = [ + $queryInfo['tables'][] = 'ip_changes'; + $queryInfo['join_conds']['ip_changes'] = [ 'LEFT JOIN', [ 'ipc_rev_id = rev_id' ] ]; - $condition[] = $ipRangeConds; + $queryInfo['conds'][] = $ipRangeConds; } else { - $condition['rev_user_text'] = $this->target; - $index = 'usertext_timestamp'; + $queryInfo['conds']['rev_user_text'] = $this->target; + $queryInfo['options']['USE INDEX']['revision'] = 'usertext_timestamp'; } } } if ( $this->deletedOnly ) { - $condition[] = 'rev_deleted != 0'; + $queryInfo['conds'][] = 'rev_deleted != 0'; } if ( $this->topOnly ) { - $condition[] = 'rev_id = page_latest'; + $queryInfo['conds'][] = 'rev_id = page_latest'; } if ( $this->newOnly ) { - $condition[] = 'rev_parent_id = 0'; + $queryInfo['conds'][] = 'rev_parent_id = 0'; } if ( $this->hideMinor ) { - $condition[] = 'rev_minor_edit = 0'; + $queryInfo['conds'][] = 'rev_minor_edit = 0'; + } + + $user = $this->getUser(); + $queryInfo['conds'] = array_merge( $queryInfo['conds'], $this->getNamespaceCond() ); + + // Paranoia: avoid brute force searches (T19342) + if ( !$user->isAllowed( 'deletedhistory' ) ) { + $queryInfo['conds'][] = $this->mDb->bitAnd( 'rev_deleted', Revision::DELETED_USER ) . ' = 0'; + } elseif ( !$user->isAllowedAny( 'suppressrevision', 'viewsuppressed' ) ) { + $queryInfo['conds'][] = $this->mDb->bitAnd( 'rev_deleted', Revision::SUPPRESSED_USER ) . + ' != ' . Revision::SUPPRESSED_USER; } - return [ $tables, $index, $condition, $join_conds ]; + // For IPv6, we use ipc_rev_timestamp on ip_changes as the index field, + // which will be referenced when parsing the results of a query. + if ( self::isQueryableRange( $this->target ) ) { + $queryInfo['fields'][] = 'ipc_rev_timestamp'; + } + + ChangeTags::modifyDisplayQuery( + $queryInfo['tables'], + $queryInfo['fields'], + $queryInfo['conds'], + $queryInfo['join_conds'], + $queryInfo['options'], + $this->tagFilter + ); + + // Avoid PHP 7.1 warning from passing $this by reference + $pager = $this; + Hooks::run( 'ContribsPager::getQueryInfo', [ &$pager, &$queryInfo ] ); + + return $queryInfo; } function getNamespaceCond() { diff --git a/includes/specials/pagers/MergeHistoryPager.php b/includes/specials/pagers/MergeHistoryPager.php index bbf97e13cb..6a8f7da74e 100644 --- a/includes/specials/pagers/MergeHistoryPager.php +++ b/includes/specials/pagers/MergeHistoryPager.php @@ -85,13 +85,12 @@ class MergeHistoryPager extends ReverseChronologicalPager { $conds['rev_page'] = $this->articleID; $conds[] = "rev_timestamp < " . $this->mDb->addQuotes( $this->maxTimestamp ); + $revQuery = Revision::getQueryInfo( [ 'page', 'user' ] ); return [ - 'tables' => [ 'revision', 'page', 'user' ], - 'fields' => array_merge( Revision::selectFields(), Revision::selectUserFields() ), + 'tables' => $revQuery['tables'], + 'fields' => $revQuery['fields'], 'conds' => $conds, - 'join_conds' => [ - 'page' => Revision::pageJoinCond(), - 'user' => Revision::userJoinCond() ] + 'join_conds' => $revQuery['joins'] ]; } diff --git a/includes/user/PasswordReset.php b/includes/user/PasswordReset.php index dd16fb78ba..faf09eefef 100644 --- a/includes/user/PasswordReset.php +++ b/includes/user/PasswordReset.php @@ -288,11 +288,14 @@ class PasswordReset implements LoggerAwareInterface { * @throws MWException On unexpected database errors */ protected function getUsersByEmail( $email ) { + $userQuery = User::getQueryInfo(); $res = wfGetDB( DB_REPLICA )->select( - 'user', - User::selectFields(), + $userQuery['tables'], + $userQuery['fields'], [ 'user_email' => $email ], - __METHOD__ + __METHOD__, + [], + $userQuery['joins'] ); if ( !$res ) { diff --git a/includes/user/User.php b/includes/user/User.php index 1c894a0f34..d397962ded 100644 --- a/includes/user/User.php +++ b/includes/user/User.php @@ -688,20 +688,25 @@ class User implements IDBAccessObject { } $dbr = wfGetDB( DB_REPLICA ); + $userQuery = self::getQueryInfo(); $row = $dbr->selectRow( - 'user', - self::selectFields(), + $userQuery['tables'], + $userQuery['fields'], [ 'user_name' => $name ], - __METHOD__ + __METHOD__, + [], + $userQuery['joins'] ); if ( !$row ) { // Try the master database... $dbw = wfGetDB( DB_MASTER ); $row = $dbw->selectRow( - 'user', - self::selectFields(), + $userQuery['tables'], + $userQuery['fields'], [ 'user_name' => $name ], - __METHOD__ + __METHOD__, + [], + $userQuery['joins'] ); } @@ -1278,12 +1283,14 @@ class User implements IDBAccessObject { list( $index, $options ) = DBAccessObjectUtils::getDBOptions( $flags ); $db = wfGetDB( $index ); + $userQuery = self::getQueryInfo(); $s = $db->selectRow( - 'user', - self::selectFields(), + $userQuery['tables'], + $userQuery['fields'], [ 'user_id' => $this->mId ], __METHOD__, - $options + $options, + $userQuery['joins'] ); $this->queryFlagsUsed = $flags; @@ -5497,6 +5504,7 @@ class User implements IDBAccessObject { /** * Return the list of user fields that should be selected to create * a new user object. + * @deprecated since 1.31, use self::getQueryInfo() instead. * @return array */ public static function selectFields() { @@ -5515,6 +5523,35 @@ class User implements IDBAccessObject { ]; } + /** + * Return the tables, fields, and join conditions to be selected to create + * a new user object. + * @since 1.31 + * @return array With three keys: + * - tables: (string[]) to include in the `$table` to `IDatabase->select()` + * - fields: (string[]) to include in the `$vars` to `IDatabase->select()` + * - joins: (array) to include in the `$join_conds` to `IDatabase->select()` + */ + public static function getQueryInfo() { + return [ + 'tables' => [ 'user' ], + 'fields' => [ + 'user_id', + 'user_name', + 'user_real_name', + 'user_email', + 'user_touched', + 'user_token', + 'user_email_authenticated', + 'user_email_token', + 'user_email_token_expires', + 'user_registration', + 'user_editcount', + ], + 'joins' => [], + ]; + } + /** * Factory function for fatal permission-denied errors * diff --git a/includes/user/UserArray.php b/includes/user/UserArray.php index ab6683b297..f3a7f9f236 100644 --- a/includes/user/UserArray.php +++ b/includes/user/UserArray.php @@ -49,11 +49,14 @@ abstract class UserArray implements Iterator { return new ArrayIterator( [] ); } $dbr = wfGetDB( DB_REPLICA ); + $userQuery = User::getQueryInfo(); $res = $dbr->select( - 'user', - User::selectFields(), + $userQuery['tables'], + $userQuery['fields'], [ 'user_id' => array_unique( $ids ) ], - __METHOD__ + __METHOD__, + [], + $userQuery['joins'] ); return self::newFromResult( $res ); } @@ -70,11 +73,14 @@ abstract class UserArray implements Iterator { return new ArrayIterator( [] ); } $dbr = wfGetDB( DB_REPLICA ); + $userQuery = User::getQueryInfo(); $res = $dbr->select( - 'user', - User::selectFields(), + $userQuery['tables'], + $userQuery['fields'], [ 'user_name' => array_unique( $names ) ], - __METHOD__ + __METHOD__, + [], + $userQuery['joins'] ); return self::newFromResult( $res ); } diff --git a/languages/i18n/ais.json b/languages/i18n/ais.json index 5359320ca8..d31807c9af 100644 --- a/languages/i18n/ais.json +++ b/languages/i18n/ais.json @@ -225,9 +225,11 @@ "badaccess": "mungangaw ku tungus", "badaccess-group0": "sisetyimo caay mahasa kisu mikawaw tina saungay.", "versionrequired": "maydih $1 baziyong a MediaWiki", + "versionrequiredtext": "maydih pisaungay $1 baziyong a MediaWiki dada’ kapah pisaungay tina kasabelih.\npiazih tu tatenga’ay [[Special:Version|baziyong]].", "ok": "malucekay", "retrievedfrom": "miala i \"$1\"", "youhavenewmessages": "{{PLURAL:$3|izaw kisu}} $1 ($2).", + "youhavenewmessagesfromusers": "{{PLURAL:$4|kisu}}izaw namakay {{PLURAL:$3|zumaay a misaungayay|$3 misaungayay}} a $1 ($2).", "youhavenewmessagesmanyusers": "izaw kisu namakay katuud misaungayay a $1 ($2).", "newmessageslinkplural": "{{PLURAL:$1|cacay baluhay palatuh|999=baluhay palatuh}}", "youhavenewmessagesmulti": "izaw $1 baluhay palatuh kisu", @@ -301,7 +303,9 @@ "title-invalid-interwiki": "milungucay a kasabelih satangahan yamalyilu la’cus pisaungay i satangahan a milakuid Wiki masasiket.", "title-invalid-talk-namespace": "milungucay a kasabelih satangahan nimicaliw hakay inayi’ay a sasukamu belih", "title-invalid-characters": "milungucay a kasabelih satangahan yamalyilu la’cusay a tatebanan-nisulitan: \"$1\".", + "title-invalid-too-long": "namilungucay a kasabelih satangahan mangasiw, satangahan pisaungay UTF-8 sakababalic a bang gu amana mangasiw $1 {{PLURAL:$1|wyiyincu}}.", "title-invalid-leading-colon": "milungucay a kasabelih satangahan yamalyilu la’cusay a mahaw-bacu i lalingatuan.", + "perfcachedts": "isasa’ay u saduba’ kalunasulitan, sazikuz misabaluh tuki sa u $1. saduba’ kalunasulitan sayadah sa kapah misuped {{PLURAL:$4|1 ku heci|$4 ku heci}}.", "viewsource": "ciwsace yuensma-kodo", "viewsource-title": "ciwsace $1 a sakatizeng banggu", "actionthrottled": "makelec saungay tuway", @@ -320,6 +324,7 @@ "virus-badscanner": "mungangaw setin: caay kapulitaimelang-walak sekyin cengse: $1", "virus-scanfailed": "sekyin mungangaw (kodo $1)", "virus-unknownscanner": "caay kapulita tena’ tu milepi’ay:", + "logouttext": "matahkal tu kisu ayza. \n\npiazihen, izaw ku kasabelih matuling paazih patalabu a setyitase, katukuh kisu palawpes saazihay-sakaluk kabilil-miala.", "cannotlogoutnow-text": "anu pisaungay $1 la’cus katahkal.", "welcomeuser": "manamuh tu tayniay, $1!", "yourname": "misaungayay a kalungangan:", @@ -437,8 +442,11 @@ "botpasswords-insert-failed": "micunusen kikay-tademaw kalungangan \"$1\" mungnhaw, pacunusen tu haw?", "botpasswords-update-failed": "misabaluh kikay-tademaw kalungangan \"$1\" mungnhaw, masipu tu haw?", "botpasswords-created-title": "patizeng tu ku kikay-tademaw mima", + "botpasswords-created-body": "pabeli misaungayay \"$2\" a kikay-tademaw \"$1\" a kikay-tademaw mima mapatizeng tuway.", "botpasswords-updated-title": "masabaluh kikay-tademaw mima", + "botpasswords-updated-body": "pabeli misaungayay \"$2\" a kikay-tademaw \"$1\" a kikay-tademaw mima masabaluh tuway.", "botpasswords-deleted-title": "masipu tu kikay-tademaw mima", + "botpasswords-deleted-body": "pabeli misaungayay \"$2\" a kikay-tademaw \"$1\" a kikay-tademaw mima masipu tuway.", "botpasswords-restriction-failed": "kikay-tademaw a mima kelec makai tu ayzaay a patalabu.", "botpasswords-invalid-name": "matuzu’ay a misaungayay a kalungangan caay yamalyilu kikay-tademaw mima maliyasay a tatebanan nu nisulitan (\"$1\")", "botpasswords-not-exist": "misaungayay \"$1\" zumasatu inayi’ kalungangan ku \"$2\" a kikay-tademaw mima.", @@ -466,6 +474,7 @@ "passwordreset-invalidemail": "la’cusay a imyiyo(email) puenengan", "passwordreset-nodata": "caay nipabeli misaungayay a kalungangan saca ku imyiyo(email) puenengan", "changeemail": "misumad saca misipu imyiyo(email) puenengan", + "changeemail-header": "pisuliten tina aazihan cudad amisumad imyiyo(email) puenengan nu misu, amahica misipu kisu mumisuay a canghaw sa masasiketay a sacahamin imyiyo(email) puenengan, akapisulit i imyiyo(email) puenengan langat-pisinga’an.", "changeemail-no-info": "kanca kisu patalabu kyu taneng kakelulan kisu misuped-miala tina kasabelih.", "changeemail-oldemail": "ayzaay a imyiyo(email) puengengan:", "changeemail-newemail": "baluhay imyiyo(email) puenengan:", @@ -506,7 +515,9 @@ "preview": "pataayaway miazih", "showpreview": "paazih pataayaway miazih", "showdiff": "paazih ku masumaday", + "blankarticle": " patalaw: imahini kisu patizengay a kasabelih ku nayi’ ku cacanay.\namahica kisu mipecec \"$1\", apatizeng inayi’ amahicahica lacul a kasabelih.", "anoneditwarning": "patalaw:caay henay kisu patalabu. anu miteka mikawaway tu kalumyiti, IP adolyise nu misu ama mitilak. anu kisu [$1 patalabu ] acasa [$2 panganganen ku canghaw ], misuay mikawaway tu kalumyiti payni tu nu misuay misaungayay kalungangan sacuzu’ ,izaway zuma kapahayay.", + "missingsummary": " pacekil:caay henay kisu suliten mikawaway-kalumyiti pecu’ nu lacul.\namahica kisu amisapecec aca \"$1\" kinacacay, atakud han pecu’ nu lacul kakelul misuped mikawaway-kalumyiti nu misu.", "missingcommenttext": "pisuliten buhci tu kamu isasa’.", "summary-preview": "mikawaway-kalumyiti pecu’ nu lacul pataayaway miazih:", "subject-preview": "pataayaway miazih taazihan tu kawaw:", @@ -525,6 +536,8 @@ "noarticletext-nopermission": "tina kasabelih ayza inayi’ lacul,\nkapah tu kisu i zuma kasabelih [[Special:Search/{{PAGENAME}}| kilim kina kasabelih pyawti ]],acasa [{{fullurl:{{#Special:Log}}|page={{FULLPAGENAMEE}}}} kilim sasuala nasulitan nakawawan ],uyzasa inayi’ ku tungus patizeng tina kasabelih.", "userpage-userdoesnotexist-view": "misaungayay canghaw \"$1\" caay henay mapangangan.", "blocked-notice-logextract": "tina misaungayay malangat tu ayza.\nisasa’ay ku capi demiad malangatay a nasulitan apabeli miazih tu tatenga’ay:", + "userjspreview": "strong>imhini pataayaway miazih kisu numisuay misaungayay a JavaScript.\nJavaScript caay henay misuped!", + "sitejspreview": " mipataayaway miazih tina JavaScript kisu ayza, JavaScript caay henay misuped!", "updated": "(misabaluh tuway)", "note": "azihen:", "continue-editing": "taayaw mikawaway-kalumyiti nikatatapal", @@ -535,8 +548,10 @@ "editconflict": "mikawaway-kalumyiti sasula’cus: $1", "yourtext": "numisuay a sulit", "storedversion": "misupedtu tu sumad", + "editingold": "patalaw: imahini kisu mikawaway-kalumyiti kasabelih maluman a sumad baziyong.\namahica kisu suped, itini masumad tu haw masumaday a amahicahica a lacul amahedaw.", "yourdiff": "sasizuma", "editpage-cannot-use-custom-model": "tina kasabelih a lacul tatudungen-misanga’ amana pasumad.", + "semiprotectedpagewarning": " azihen:tina kasabelih madiput tuway, mapanganganay a misaungayay dada’ kapah mikawaway-kalumyiti.\nisasa’ sa, pabeli capi demiad a nasulitan nazipa’an kya kapah miazih tu tatenga’ay", "templatesused": "uyni kasabelih pisaungay tu isasaay {{PLURAL:$1|taazihan mitudung}}:", "templatesusedpreview": "tina pataayaway miazih pisaungay kya isasa’ay a {{PLURAL:$1|taazihan mitudung}}", "templatesusedsection": "tina belih pisaungay tu isasa’ay a {{PLURAL:$1|taazihan mitudung}}:", @@ -649,6 +664,7 @@ "deletedhist": "masiputu tu nazipa’an", "revdelete-hide-current": "midimut i $1 $2 a kasacacay mungangaw: tina ku sumad nuayzaay, amana midimut.", "revdelete-modify-missing": "misumad kasacacay ID $1 mungangaw: kalunasulitan-sulu inayi’ kya kalunasulitan", + "revdelete-reason-dropdown": "* lalid maazihay a misipuay a mahicaay \n** midebung nisanga’an niza tu tungus a kawaw \n** caay matatungusay a buhci tu kamu saca tekeday a cesyun\n** caay matatungusay a misaungayay a kalungangan \n** midimut yamalyilu palawacu’ay a cesyun", "revdelete-otherreason": "zumaay/nicunusay a mahicaay:", "revdelete-reasonotherlist": "zuma a mahicaay", "revdelete-edit-reasonlist": "masipu a mahicaay nu mikawaway-kalumyiti", @@ -806,11 +822,13 @@ "yourvariant": "lacul kamu masazumaay:", "prefs-help-variant": "maydih kisu sapaazih tina kakacawan a lacul kalukamu saca sasuala tu sulit nu kamu.", "yournick": "baluhay sulitan a ngangan:", + "prefs-help-signature": "i sasukamu kasabelih buhci tu kamu kanca pisaungay \"~~~~\" pangangan, bkya tatebanan nu nisulitan amaliyaw tu sulitan nu ngangan atu tuki.", "badsig": "mungangaw a saayaway sulitan a ngangan.\npikinsa HTML aazihen-paya.", "yourgender": "milunguc kisu pisaungay canan a etul muawaw tisuwanan?", "gender-unknown": "anu miawaw tisuwan sa, tina zwanti hakay amana misaungay tu etul-sulit.", "gender-male": "mikawaway-kalumyiti Wiki kasabelih ciniza", "gender-female": "mikawaway-kalumyiti Wiki kasabelih ciniza", + "prefs-help-gender": "tina kanamuhan a setin ku mapili’ay langat-pisinga’an.\nsisetyimo apisaungay namapili’ay nu misu a sasakawawen mitakus tisuwan, anu sasukamu tu tawan mapatahkal tisuwan sa apisaungay tu matatungus a ngangan.\ntina cesyun apabinawlan.", "email": "imyiyo(email)", "prefs-help-email-required": "imyiyo(email) puenengan manakanca suliten naca kasacacay.", "prefs-info": "anganganay a cesyun", @@ -1168,6 +1186,7 @@ "filename-toolong": "tangan kalungangan amana mangsiw 240 wyiyincu.", "badfilename": "masumad tuway tangan kalungangan ku \"$1\"", "filetype-badmime": "amana mahasa patapabaw MIME nikalahizaan ku \"$1\" a tangan.", + "filetype-bad-ie-mime": "Internet Explorer amitangan itini nikalahizaan mungangaw piazih ku \"$1\", hakay malecay midimutay a mundayk, caay mahasa patapabaw tina nikalahizaan tangan.", "filetype-missing": "kya tangan inayi’ mikilulay ngangan nu tangan (tinaku \".jpg\")", "empty-file": "patayzaan nu misu a tangan u inayi’ay.", "file-too-large": "patayzaan tangan nu misu micalapay.", @@ -1190,8 +1209,10 @@ "uploaddisabled": "mapasatezep tu ku patapabaw", "copyuploaddisabled": "mapasatezep pisaungay URL patudud.", "uploaddisabledtext": "patapabaw tangan mapasatezep tuway.", + "upload-scripted-pi-callback": "la’cus patapabaw yamalyilu XML-stylesheet sapisadimel mituzu’ a tangan.", "uploaded-script-svg": "i mapatapabaway a SVG tangan matepa kapah micengseay a kuku’-ulic aazihen-paya \"$1\".", "uploaded-hostile-svg": "i mapatapabaway a SVG tangan yangse aazihen-paya matepa caay kaenapay a CSS.", + "uploaded-image-filter-svg": "ilabu’ mapatapabaway a SVG tangan matepa zunga sebseb-sakaluk pisaungay URL:<$1 $2=\"$3\">.", "uploadinvalidxml": "la’cus mitingalaw matapabaway tangan a XML.", "upload-source": "saangangan a tangan", "sourcefilename": "saangangan tangan kalungangan:", @@ -1203,6 +1224,7 @@ "watchthisupload": "miazih tina tangan", "upload-proto-error": "padinwaay a ketun caay katatenga’", "upload-file-error": "ilabuay a mungangaw", + "upload-file-error-text": "mitanam i sefu-kikay patizeng singa’an tu sulit sa tahkal labuay mungangaw.\npimasukazih [[Special:ListUsers/sysop|mikuwanay]].", "upload-misc-error": "caay kapulita patudud mungangaw", "upload-too-many-redirects": "kya URL miliyaw patatuzu’ tayza sayadah zuma a puenengan", "upload-http-error": "HTTP mungangaw: $1", @@ -1242,6 +1264,7 @@ "backend-fail-connect": "la’cus misasiket tayza suped-sulu zikuzan malutapiingan \"$1\"", "backend-fail-internal": "suped-sulu zikuzan \"$1\" izaw caay kapulitaay a mungangaw.", "backend-fail-contenttype": "la’cus taazihan misuped i \"$1\" a tangan lacul nikalahizaan", + "backend-fail-usable": "u nanu tungus caay kataneng saca dilyikotoling/sapilacul mahedaw, la’cus miasip saca misuliten tangan \"$1\" .", "filejournal-fail-dbconnect": "la’cus papatun tu zikuzan nu suped-sulu \"$1\" a nasulitan-nazipa’an kalunasulitan-sulu.", "filejournal-fail-dbquery": "la’cus misabaluh suped-sulu zikuzan \"$1\" a nasulitan-nazipa’an kalunasulitan-sulu", "lockmanager-notlocked": "la’cus mihulak pamutek \"$1\"; kya tangan caay pamutek.", @@ -1283,6 +1306,7 @@ "http-bad-status": "miteka HTTP milunguc izaw tu ku munday: $1 $2", "upload-curl-error6": "la’cus misiket tu calay-zazan(wanglu) ta URL", "upload-curl-error28": "patapabaw mautang", + "upload-curl-error28-text": "calay-kakacawan(wangcan) mangasiw patukil a tukiay kelec. \npikinsa kya calay-kakacawan(wangcan) malecek saungay haw? pihanhan henay pitaneng aca.\npatahkal nizateng tisuwan kapah kisu i caay makalahay a tuki mitanam misiket tu calay-zazan(wanglu).", "license": "sapabeli tu kinli a cedang", "license-header": "sapabeli tu kinli a cedang", "nolicense": "caay henay mipili’", @@ -1336,10 +1360,12 @@ "filerevert-legend": "patiku tu tangan", "filerevert-comment": "mahicaay:", "filerevert-defaultcomment": "patiku tuway tayza i $1 $2 ($3) a baziyong", + "filerevert-success": "[[Media:$1|$1]] mapatiku ta [$4 i $2 $3 a baziyong ].", "filerevert-badversion": "caay katepa tangan nu nasawniay matuzu’ tu demiad a itiniay baziyong.", "filerevert-identical": "ayzaay baziyong a tangan atu mipili’ay baziyong malecalecad.", "filedelete": "misipu \"$1\"", "filedelete-legend": "misipu tu tangan", + "filedelete-intro-old": "imahini amisipu kisu [[Media:$1|$1]] i [$4 $2 $3] a baziyong.", "filedelete-comment": "mahicaay:", "filedelete-submit": "masipu", "filedelete-success": "masipu tu $1.", @@ -1375,6 +1401,7 @@ "statistics-files": "mapatapabaw tu a tangan", "statistics-edits": "nay {{SITENAME}} napatizeng katukuh ayza sa kasabelih mikawaway-kalumyiti sulyang", "statistics-edits-average": "paybelih malecalecad mikawaway-kalumyiti sulyang", + "statistics-users": "mapanganganay tu [[Special:ListUsers|misaungayay]]", "statistics-users-active": "saungay nu binawlan a misaungayay", "pageswithprop": "izaw susin a kasabelih", "pageswithprop-text": "tina kasabelih sapalalitemuh tu kawaw pisaungay matuzu’ay susin a kasabelih", @@ -1428,6 +1455,7 @@ "shortpages": "ma’ngadisay a kasabelih", "longpages": "mangasiway a kasabelih", "deadendpages": "inayi’ masasiket kasabelih", + "deadendpagestext": "isasa’ay i {{SITENAME}} a kasabelih caay masasiket katukuh zuma kasabelih.", "protectedpages": "madiputay a kasabelih", "protectedpages-indef": "paazih a cacay inayi’-kakatekuhan midiputay kasabelih", "protectedpages-cascade": "paazih a cacay patatusulay a midiput kasabelih", @@ -1455,6 +1483,7 @@ "newpages-username": "misaungayay a kalungangan:", "ancientpages": "samalumanay a kasabelih", "move": "milimad", + "unusedimagestext": "isasa’ay ku caay pisaungay a tangan nu mahicahica a kasabelih.\npiazihen, zuma calay-kakacawan(wangcan) hakay kakelul micaliw URL masasiket tu tangan, sisa pasilsilay a tangan itini hakay izaw henay pisaungay.", "unusedcategoriestext": "isasa’ kakuniza inayi’ caay henay masaungay nu kasabelih saca kakuniza", "notargettitle": "inayi’ ku pabalucu’an", "notargettext": "caay henay kisu matuzu’ papatuzu'an kasabelih saca misaungayay amiteka tina saungay.", @@ -1472,6 +1501,7 @@ "apisandbox-fullscreen": "micuwat tu sapat", "apisandbox-fullscreen-tooltip": "micuwat sandobokese banyilo amipatumes saazihay-sakaluk azih-sasingalan.", "apisandbox-unfullscreen": "paazih kasabelih", + "apisandbox-unfullscreen-tooltip": "wada’en sandobokese banyilo a tabaki, ngay MediaWiki pasubana’ tu miidangay masasiket kapah misaungay.", "apisandbox-submit": "miawaw tu milunguc", "apisandbox-reset": "palawpis", "apisandbox-retry": "miliyaw mitaneng", @@ -1577,6 +1607,7 @@ "trackingcategories": "mikilul nazikuzan kakuniza", "trackingcategories-desc": "kakuniza milisimet a tatungus", "restricted-displaytitle-ignored": "sekipo paazih satangah a kasabelih", + "post-expand-template-inclusion-category-desc": "namicuwat taazihan mitudung tuway kya tabaki’ mangawi $wgMaxArticleSize hamaw layad taazihan mitudung caay malecek micuwat kasabelih.", "broken-file-category-desc": "yamalyilu malepi’ a tangan masasiket a kasabelih (sipakabit ilabu tangan masasiket a tangan inayi’).", "trackingcategories-nodesc": "inayi’ ku silaheciay a sapuelac", "trackingcategories-disabled": "mapasatezep kakuniza tuway", @@ -1650,6 +1681,7 @@ "excontent": "lacul nu: \"$1\"", "exbeforeblank": "caay henay palawpes hamin a lacul ku: \"$1\"", "delete-confirm": "misipu \"$1\"", + "historywarning": " patalaw: imahini amisipuay a kasabelih nu misu yamalyilu $1 {{PLURAL:$1|sumad}} nazipa’an", "historyaction-submit": "paazih", "actioncomplete": "pahezek tu ku saungay", "actionfailed": "saungay mungangaw", @@ -1672,6 +1704,7 @@ "cantrollback": "la’cus patiku mikawaway-kalumyiti;\ntina kasabelih a sazikuz paaninay u kinacacay a masacudaday.", "editcomment": "mikawaway-kalumyiti pecu’ nu lacul ku: $1.", "sessionfailure-title": "kasasiket mungangaw", + "sessionfailure": "kisu patalabu kasasiketan mahiza simunday,\nsaka pataayaw-milangat kasasiketan maalaw atu madebung, tina saungay mapalawpes tuway.\npitatiku ayaway a kasabelih, miliyaw maasip kya kasabelih pitaneng aca.", "changecontentmodel": "misumad lacul tatudungen misanga’", "changecontentmodel-title-label": "kasabelih satangahan", "changecontentmodel-model-label": "tatudungen misanga’ nu baluhay a lacul", @@ -1735,6 +1768,7 @@ "viewdeletedpage": "ciwsace masipuay tu kasabelih", "undelete-fieldset-title": "patiku misumad nu ayaway", "undeleterevisions": "$1{{PLURAL:$1|baziyong}}misipu", + "undeleterevdel": "amahica sabaluhayay a kasabelih saca tangan masumad nu ayaway masipu tu liyad, a la’cus mileku palawpes misipuay a saungay.\nanumahiza sa kanca mipili’ hatizaay saca palawpes midimut masipuay tu sabaluhay a sumad nu ayaway.", "undelete-revision": "masipu nu $3 a $1 (i $4 $5) masumad nu ayaway", "undelete-nodiff": "inayi’ nasawniay a sumad.", "undeletebtn": "patiku", @@ -1823,6 +1857,7 @@ "badipaddress": "la’cusay a IP puenengan", "blockipsuccesssub": "milangat malahci", "ipb-blockingself": "amilangat tu kisu haw! malucek kisu amahiza haw?", + "ipb-confirmhideuser": "amilangat kisu cacay a misaungayay zumasatu \"midimut\" kya misaungayay, apasatezep paazih sacahamin patahkal i piazihan-tu-sulit atu ibalu nu nasulitan a misaungayay a kalungangan.\ntatenga’ kisu ahatizaan haw?", "ipb-edit-dropdown": "malangat a mahicaay nu mikawaway-kalumyiti", "ipb-unblock-addr": "mihulak tu langat $1", "ipb-unblock": "mihulak malangat misaungayay a kalungangan saca IP puenengan", @@ -1865,6 +1900,7 @@ "change-blocklink": "misumad tu langat", "contribslink": "paanin", "emaillink": "pabahel imyiyo(email)", + "autoblocker": "IP nu misu puenengan izay capi demiad pasaungay ni [[User:$1|$1]] sisa lunuk malangat.\nmilangat $1 a mahicaay ku \"$2\"", "blocklogpage": "milangat tu nasulitan nakawawan", "blocklog-showlog": "tina misaungayay nasawniay malangat tuway.\nisasa’ay ku malangatay a kiluk sapaazih tu tatenga’ay:", "blocklogentry": "malangat [[$1]] a kakatukuhan i $2 $3", @@ -1890,6 +1926,7 @@ "ip_range_toolarge": "caay mahasa milangat kya taliyuk mangasiw /$1.", "proxyblocker": "kutay sefu-kikay milangat-kikay", "softblockrangesreason": "IP puenengan nu misu ($1) inayi’ mahasa paceba pangangan paanin, pipatalabu.", + "xffblockreason": "IP puenengan nu misu pisaungay X-Forwarded-For satangahan, kisu saca pisaungay nu misu a kutay sefu-kikay malangat tuway.\nmalangatay a mahicaay ku:$1", "ipbblocked": "izay kisu malangat, sisa la’cus milangat saca mihulak malangatay a zuma misaungayay", "ipbnounblockself": "caay mahasa mihulak malangat tu kisu.", "lockdb": "pamutek tu sulu nu kalunasulitan", @@ -1901,6 +1938,7 @@ "locknoconfirm": "caay henay kisu hatizaay malucekay tu mapili’ay atilad", "lockdbsuccesssub": "malahci pamutek sulu nu nasulitan tuway", "unlockdbsuccesssub": "misipu pamutek tu sulu nu kalunasulitan tuway", + "lockdbsuccesstext": "mamutek tu ku nasulitan-sulu.
\namana kapawan anu mahemin midiput pahezek [[Special:UnlockDB| mihulak pamutek ]] nasulitan-sulu.", "databaselocked": "pamutek tuway ku kalunasulitan-sulu", "databasenotlocked": "caay pamutek henay ku kalunasulitan-sulu", "lockedbyandtime": "(nay {{GENDER:$1|$1}} i $2 a $3)", @@ -1948,6 +1986,7 @@ "imageinvalidfilename": "papatuzu’an a tangan kalungangan la’cus.", "fix-double-redirects": "misabaluh sacahamin patatuzu’ nuayaway a satangahan miliyaw patatuzu’ kasabelih", "move-leave-redirect": "miliwan miliyaw patatuzu’ kasabelih", + "semiprotectedpagemovewarning": " azihen: tina kasabelih madiput tuway, u mapanganganay a misaungayay dada’ kapah milimad. \nisasa’ sa, pabeli capi demiad a nasulitan nazipa’an kya kapah miazih tu tatenga’ay:", "export": "patahkal ku kasabelih", "exportall": "patahkal sacahamin kasabelih", "exportcuronly": "yamalyilu dada’ ayzaay a sumad nu ayaway, caay yamalyilu lekuay a sumad nu nazipa’an", @@ -1998,6 +2037,7 @@ "import-mapping-subpage": "pacumud sapa isasa’ay kasabelih a sailuc-kasabelih:", "import-upload-filename": "kalungangan nu tangan:", "import-comment": "pacunus sakacaay kapawan:", + "importtext": "pisaungay [[Special:Export|patahkal sakaluk]] nay Wiki patahkal ku tangan.\nmisuped i tinnaw nu misu zumasatu patapabaw itini.", "importstart": "pacumud tayza pataayaw tu kawaw kakitizaan", "import-revision-count": "$1 {{PLURAL:$1|masumad nu ayaway}}", "importnopages": "inayi’ mapacumuday a kasabelih.", @@ -2633,6 +2673,7 @@ "watchlisttools-raw": "mikawaway-kalumyiti saayaway misisip a piazihan-tu-sulit", "signature": "[[{{ns:user}}:$1|$2]] ([[{{ns:user_talk}}:$1| sasukamu ]])", "timezone-local": "itizaay", + "invalid-indicator-name": " mungangaw: kasabelih setyitase micuzu’ay tu kawaw a name susin amana inayi’", "version": "baziyong", "version-extensions": "malacul tu sacunusan a sakaluk", "version-skins": "malacul tu nuhekalan", @@ -2737,6 +2778,7 @@ "tags-create-warnings-below": "apalalid patizeng aazihen a paya kisu haw?", "tags-delete-title": "misipu tu aazihen a paya", "tags-delete-explanation-initial": "imahini amisipu kisu tu aazihen-paya \"$1\" nay kalunasulitan-sulu.", + "tags-delete-explanation-in-use": "aazihen-paya amakay ayzaay imahini pisaungay a {{PLURAL:$2|$2 masumad nu ayaway saca nazipa’annasulitan nazipa’an kasacacay|$2 sumad nu ayaway saca nazipa’an kasacacay}} misipu.", "tags-delete-reason": "mahicaay:", "tags-delete-submit": "la’cus palawpes misipu tina aazihen a paya", "tags-delete-not-allowed": "la’cus misipu nay sacunus misaheciay a aazihen-paya, anu... kya sacunus mahasa tuway", @@ -2825,6 +2867,7 @@ "logentry-delete-delete": "$1 {{GENDER:$2|masiputu}} kasabelih $3", "logentry-delete-restore": "$1{{GENDER:$2|patiku}} kasabelih $3($4)", "restore-count-files": "{{PLURAL:$1|1 tangan}}", + "logentry-delete-event": "ilabu nu $1 {{GENDER:$2|masumad tuway}} $3 {{PLURAL:$5|1 nazipa’an|$5 nasulitan nazipa’an}} a maazihay:$4", "logentry-suppress-delete": "$1 {{GENDER:$2|misatezep paazih tuway}} kasabelih $3", "revdelete-content-hid": "madimut tu ku lacul", "revdelete-summary-hid": "madimut mikawaway-kalumyiti pecu’ nu lacul", @@ -2835,6 +2878,7 @@ "revdelete-restricted": "caedung mikuwanay a kelec tuway", "revdelete-unrestricted": "masipu tu ku mikuwanay a kelec", "logentry-import-upload": "$1 nay tangan patapabaw {{GENDER:$2|pacumud}} $3", + "logentry-import-upload-details": "$1 pisaungay tangan patapabaw tuway {{GENDER:$2|pacumud}} $3 ($4 {{PLURAL:$4| misumad nu ayaway}})", "logentry-move-move": "$1 {{GENDER:$2|milimad tuway}} kasabelih $3 katukuh $4", "logentry-move-move_redir": "$1 malimad kasabelih $3 tu $4 zumasatu mitahpu nuayaway miliyaw patatuzau’", "logentry-newusers-newusers": "{{GENDER:$2|patizeng}} misaungayay canghaw tuway $1", @@ -2843,12 +2887,15 @@ "logentry-newusers-autocreate": "lunuk {{GENDER:$2|patizeng}} misaungayay a canghaw $1", "logentry-protect-unprotect": "$1 {{GENDER:$2|masipu tuway}} $3 a midiput", "logentry-protect-protect": "$1 {{GENDER:$2|madiput tuway}} $3 $4", + "logentry-rights-rights": "$1 {{GENDER:$2|masumad tuway}} {{GENDER:$6|$3}} a luyaluy tatungus sakawaway nay $4 mala $5", "logentry-upload-upload": "$1 {{GENDER:$2|masayacay tuway}} $3", "logentry-upload-overwrite": "$1 {{GENDER:$2|patapabaw tuway}} baluhay baziyong a $3", "logentry-upload-revert": "$1 {{GENDER:$2|masayacay tuway}} $3", "log-name-managetags": "tazihan-paya kuwan tu nasulitan", "logentry-managetags-create": "$1 {{GENDER:$2|mapatizeng yuway}} aazihen-paya \"$4\"", "log-name-tag": "aazihen a paya nasulitan nazipa’an", + "logentry-tag-update-remove-revision": "$1 {{GENDER:$2|masipu tuway}} {{PLURAL:$9|aazihen-paya}} $8 nay kasabelih $3 sumad $4.", + "logentry-tag-update-remove-logentry": "$1 {{GENDER:$2|masipu tuway}} {{PLURAL:$9|aazihen-paya}} $8 nay nasulitan nazipa’an kasacacay $3 a sumad $5.", "rightsnone": "(nayi’)", "rightslogentry-temporary-group": "$1 (nanunuz, katukuh $2)", "feedback-adding": "imahini micunus nabalucu’ hwidubaku tayza kasabelih...", @@ -3101,6 +3148,7 @@ "authenticationdatachange-ignored": "zencen kalunasulitan a sumad caay henay milisimet, hakay inayi’ misetin nipabeliay?", "restrictionsfield-badip": "la’cusay a IP puenengan saca subal: $1", "restrictionsfield-label": "mahasaay a subal nu IP:", + "restrictionsfield-help": "cacay IP puenengan saca CIDR tatungus cacay a silsil, amiwawah sacahamin tatungus kapah pisaungay:
0.0.0.0/0\n::/0
", "revid": "masumad nu ayaway $1", "pageid": "kasabelih ID $1", "rawhtml-notallowed": "<html> aazihen-paya la’cus pisaungay i hekal nu habutud kasabelih." diff --git a/languages/i18n/azb.json b/languages/i18n/azb.json index e43fb4325c..246b59351f 100644 --- a/languages/i18n/azb.json +++ b/languages/i18n/azb.json @@ -1786,7 +1786,7 @@ "deleting-backlinks-warning": "'''اخطار:''' بو سیلمگه قصدینیز اولان صفحه‌یه، [[Special:WhatLinksHere/{{FULLPAGENAME}}|باشقا صفحه‌لر]] باغلانتی وئریب یا اونو اؤزلرین‌ده ایشلدیب‌لر.", "rollback": "اوولکی نوسخه لر", "rollbacklink": "قایتار", - "rollbacklinkcount": "{{PLURAL:$1|دییشدیرمه}}نی قایتار", + "rollbacklinkcount": "{{PLURAL:$1|دییشدیرمه}}‌نی قایتار", "rollbacklinkcount-morethan": "$1-دن چوْخ دییشدیرمه‌نی قایتار", "rollbackfailed": "گئری قایتارما اوغورسوزدور", "cantrollback": "دییشدیر گئری قایتاریلا بیلمز؛ آخیرینجی دییشدیر صحیفه‌ده اولان یئگانه فالیت‌دیر.", diff --git a/languages/i18n/be-tarask.json b/languages/i18n/be-tarask.json index 2e85dc4ec5..939080c35f 100644 --- a/languages/i18n/be-tarask.json +++ b/languages/i18n/be-tarask.json @@ -986,7 +986,7 @@ "searchresultshead": "Пошук", "stub-threshold": "Максымальны памер старонкі для паказу спасылак як на накід ($1):", "stub-threshold-sample-link": "прыклад", - "stub-threshold-disabled": "Выключаны", + "stub-threshold-disabled": "Адключаны", "recentchangesdays": "Колькасьць дзён для паказу ў апошніх зьменах:", "recentchangesdays-max": "(максымальна $1 {{PLURAL:$1|дзень|дні|дзён}})", "recentchangescount": "Колькасьць рэдагаваньняў для паказу па змоўчваньні:", diff --git a/languages/i18n/bg.json b/languages/i18n/bg.json index 352aaec619..7c5cfbeefa 100644 --- a/languages/i18n/bg.json +++ b/languages/i18n/bg.json @@ -1551,7 +1551,7 @@ "backend-fail-opentemp": "Временният файл не може да бъде отворен.", "backend-fail-writetemp": "Грешка при записването във временния файл.", "backend-fail-closetemp": "Не може да бъде затворен временният файл.", - "backend-fail-read": "Файлът $1 не може да бъде прочетен.", + "backend-fail-read": "Файлът „$1“ не може да бъде прочетен.", "backend-fail-create": "Файлът „$1“ не може да бъде съхранен.", "backend-fail-maxsize": "Файлът „$1“ не може да бъде съхранен, тъй като размерът му надвишава {{PLURAL:$2|един байт|$2 байт}}.", "backend-fail-connect": "Не е възможно свързването към бекенда за съхранение „1“.", @@ -2071,7 +2071,7 @@ "changecontentmodel-cannot-convert": "Съдържанието на [[:$1]] не може да преобразувано в тип $2.", "changecontentmodel-nodirectediting": "Моделът на съдържание $1 не поддържа пряко редактиране", "changecontentmodel-emptymodels-title": "Не са налични модели на съдържание", - "changecontentmodel-emptymodels-text": "Съдържанието в [[:$1]] не може да бъде превърнато в никакъв тип.", + "changecontentmodel-emptymodels-text": "Съдържанието в [[:$1]] не може да бъде преобразувано в никакъв тип.", "log-name-contentmodel": "Дневник на промените на модела на съдържанието", "log-description-contentmodel": "Страницата показва промените в модела на съдържанието на страниците и страниците, създадени с модел на съдържанието различен от този по подразбиране.", "logentry-contentmodel-new": "$1 {{GENDER:$2|създаде}} страницата $3, използвайки модел на съдържанието „$5“, който не е по подразбиране", @@ -2211,7 +2211,7 @@ "whatlinkshere-page": "Страница:", "linkshere": "Следните страници сочат към '''[[:$1]]''':", "nolinkshere": "Няма страници, сочещи към '''[[:$1]]'''.", - "nolinkshere-ns": "Няма страници, сочещи към '''[[:$1]]''' в избраното именно пространство.", + "nolinkshere-ns": "Няма страници, сочещи към [[:$1]] в избраното именно пространство.", "isredirect": "пренасочваща страница", "istemplate": "включване", "isimage": "препратка към файла", @@ -2346,7 +2346,7 @@ "locknoconfirm": "Не сте отметнали кутийката за потвърждение.", "lockdbsuccesssub": "Заключването на базата от данни беше успешно", "unlockdbsuccesssub": "Отключването на базата от данни беше успешно", - "lockdbsuccesstext": "Базата данни на {{SITENAME}} беше заключена.\n
Не забравяйте да я [[Special:UnlockDB|отключите]] когато привършите с работата по поддръжката.", + "lockdbsuccesstext": "Базата данни на {{SITENAME}} беше заключена.\n
Не забравяйте да я [[Special:UnlockDB|отключите]] когато завършите с работата по поддръжката.", "unlockdbsuccesstext": "Базата от данни на {{SITENAME}} беше отключена.", "lockfilenotwritable": "Няма права за писане върху файла за заключване на базата данни. За да заключи или отключи базата данни, уеб-сървърът трябва да има тези права.", "databaselocked": "Базата от данни е вече заключена.", @@ -3081,7 +3081,7 @@ "confirm-watch-button": "Потвърждаване", "confirm-watch-top": "Добавяне на страницата в списъка ви за наблюдение?", "confirm-unwatch-button": "Потвърждаване", - "confirm-unwatch-top": "Премахване на страницата от списъка ви за наблюдение?", + "confirm-unwatch-top": "Премахване на страницата от списъка Ви за наблюдение?", "confirm-rollback-button": "OK", "confirm-rollback-top": "Отменяне на редакции по тази страница?", "quotation-marks": "„$1“", @@ -3342,11 +3342,11 @@ "htmlform-date-invalid": "Избраната от вас стойност за дата не е разпозната. Опитайте да използвате формат ГГГГ-ММ-ДД.", "htmlform-time-invalid": "Стойността, която сте уточнили, не е разпозната. Опитайте да използвате формат ЧЧ:ММ:СС.", "htmlform-datetime-invalid": "Избраната от вас стойност за дата не е разпозната. Опитайте да използвате формат ГГГГ-ММ-ДД ЧЧ:ММ:СС.", - "htmlform-date-toolow": "Стойността, която сте уточнили, е по-рано от най-ранната позволена дата $1.", - "htmlform-date-toohigh": "Стойността, която сте уточнили, е след най-късната позволена дата $1.", - "htmlform-time-toolow": "Стойността, която сте уточнили, е преди най-ранното позволено време $1.", - "htmlform-time-toohigh": "Стойността, която сте уточнили, е след най-късното позволено време $1.", - "htmlform-datetime-toolow": "Стойността, която сте уточнили, е преди най-ранните позволени дата и час $1.", + "htmlform-date-toolow": "Стойността, която сте указали, е по-рано от най-ранната позволена дата $1.", + "htmlform-date-toohigh": "Стойността, която сте указали, е след най-късната позволена дата $1.", + "htmlform-time-toolow": "Стойността, която сте указали, е преди най-ранното позволено време $1.", + "htmlform-time-toohigh": "Стойността, която сте указали, е след най-късното позволено време $1.", + "htmlform-datetime-toolow": "Стойността, която сте указали, е преди най-ранните позволени дата и час $1.", "htmlform-title-badnamespace": "[[:$1]] не е в именното пространство „{{ns:$2}}“.", "htmlform-title-not-creatable": "Заглавието „$1“ не може да бъде създадено", "htmlform-title-not-exists": "$1 не съществува.", diff --git a/languages/i18n/bn.json b/languages/i18n/bn.json index f225e7dc35..fb59209291 100644 --- a/languages/i18n/bn.json +++ b/languages/i18n/bn.json @@ -640,7 +640,7 @@ "anonpreviewwarning": "আপনি অ্যাকাউন্টে প্রবেশ করেননি। সম্পাদনা সংরক্ষণ করলে এই পাতার সম্পাদনার ইতিহাসে আপনার আইপি ঠিকানা সংরক্ষিত হবে।", "missingsummary": "'''খেয়াল করুন''': আপনি আপনার সম্পাদনার কোনও সারাংশ দেননি। আবার যদি \"$1\" বোতামে ক্লিক করেন, তাহলে ঐ সারাংশ বাক্যটি ছাড়াই আপনার সম্পাদনা সংরক্ষিত হবে।", "selfredirect": "সতর্কতা: আপনি এই পাতাকে এর নিজের দিকে পুনঃনির্দেশিত করছেন।\nআপনাকে পুনঃনির্দেশিত করার জন্য হয় ভুল লক্ষ্য নির্দিষ্ট করেছেন, অথবা আপনি ভুল পাতা সম্পাদনা করছেন।\nআপনি যদি আবার \"$1\" ক্লিক করেন, পুনর্নির্দেশ যেকোনোভাবেই হোক তৈরি করা হবে।", - "missingcommenttext": "দয়া করে নিচে মন্তব্য যোগ করুন।", + "missingcommenttext": "দয়া করে একটি মন্তব্য যোগ করুন।", "missingcommentheader": "খেয়াল করুন: আপনি এই মন্তব্যের জন্য কোনও বিষয় প্রদান করেননি। আপনি যদি আবার \"$1\" বোতামে ক্লিক করেন, আপনার এই সম্পাদনা কোন বিষয় ছাড়াই সংরক্ষিত হবে।", "summary-preview": "সম্পাদনা সারাংশের প্রাকদর্শন:", "subject-preview": "বিষয়ের প্রাকদর্শন:", @@ -1300,6 +1300,7 @@ "recentchanges-legend": "সাম্প্রতিক পরিবর্তনের পছন্দগুলি", "recentchanges-summary": "এই পাতায় উইকিটির সবচেয়ে সাম্প্রতিক পরিবর্তনগুলি অনুসরণ করুন।", "recentchanges-noresult": "নির্ধারিত সময়ের মধ্যে কোনো পরিবর্তন পাওয়া যায়নি।", + "recentchanges-timeout": "এই অনুসন্ধানের সময় শেষ হয়েছে। আপনি ভিন্ন অনুসন্ধানের পরামিতি দিয়ে চেষ্টা করতে পারেন।", "recentchanges-feed-description": "এই ফিডে উইকিটির সবচেয়ে সাম্প্রতিক পরিবর্তনগুলি অনুসরণ করুন।", "recentchanges-label-newpage": "এই সম্পাদনায় একটি নতুন পাতা তৈরি হয়েছে", "recentchanges-label-minor": "এটি একটি অনুল্লেখিত সম্পাদনা", @@ -1365,7 +1366,7 @@ "rcfilters-filter-user-experience-level-unregistered-label": "অনিবন্ধিত", "rcfilters-filter-user-experience-level-unregistered-description": "যেসব সম্পাদক অ্যাকাউন্টে প্রবেশ করেননি।", "rcfilters-filter-user-experience-level-newcomer-label": "নতুন আগত", - "rcfilters-filter-user-experience-level-newcomer-description": "১০টির কম সম্পাদনা ও ৪ দিনের কম সময় ধরে সক্রিয় থাকা নিবন্ধিত সম্পাদক।", + "rcfilters-filter-user-experience-level-newcomer-description": "১০টির কম সম্পাদনা বা ৪ দিনের কম সময় ধরে সক্রিয় থাকা নিবন্ধিত সম্পাদক।", "rcfilters-filter-user-experience-level-learner-label": "শিক্ষার্থী", "rcfilters-filter-user-experience-level-learner-description": "নিবন্ধিত সম্পাদক যাদের অভিজ্ঞতা \"নতুন আগত\" ও \"অভিজ্ঞ ব্যবহারকারীদের\" মধ্যে পড়ে।", "rcfilters-filter-user-experience-level-experienced-label": "অভিজ্ঞ ব্যবহারকারী", @@ -1426,6 +1427,7 @@ "rcfilters-liveupdates-button-title-on": "সরাসরি হালনাগাদ বন্ধ করুন", "rcfilters-liveupdates-button-title-off": "নতুন পরিবর্তন ঘটামাত্র তাঁদের দেখান", "rcfilters-watchlist-markseen-button": "দেখা হিসাবে সব পরিবর্তন চিহ্নিত করুন", + "rcfilters-watchlist-edit-watchlist-button": "আপনার নজরে রাখা পাতার তালিকা সম্পাদনা করুন", "rcfilters-watchlist-showupdated": "পরিবর্তন যখন ঘটেছে তখন থেকে যে পাতাগুলি আপনি এখনো দেখেননি তা মোটা চিহ্নসহ গাঢ় করে দেখানো হয়েছে।", "rcfilters-preference-label": "সাম্প্রতিক পরিবর্তনের উন্নত সংস্করণটি লুকান", "rcfilters-preference-help": "২০১৭-এর পুনঃনকশাকৃত ইন্টারফেস এবং তখন পর্যন্ত ও তখন থেকে যোগ করা সকল সরঞ্জামে ফেরত নিবে।", diff --git a/languages/i18n/ca.json b/languages/i18n/ca.json index 8e5f5ecd2f..70200bb9d5 100644 --- a/languages/i18n/ca.json +++ b/languages/i18n/ca.json @@ -670,7 +670,7 @@ "anonpreviewwarning": "''No us heu identificat amb un compte d'usuari. La vostra adreça IP quedarà registrada a l'historial d'aquesta pàgina.''", "missingsummary": "'''Recordatori''': Heu deixat en blanc el resum de l'edició. Si torneu a clicar al botó de desar, l'edició es guardarà sense resum.", "selfredirect": "Avís: Esteu redirigint la pàgina a si mateixa.\nPodeu haver especificat un objectiu erroni per a la redirecció, o potser esteu modificant una pàgina incorrecta.\nSi feu clic a «$1» una vegada més, la redirecció es crearà de totes maneres.", - "missingcommenttext": "Introduïu un comentari a continuació.", + "missingcommenttext": "Introduïu un comentari.", "missingcommentheader": "Recordatori: no heu proporcionat un assumpte/encapçalament per al comentari.\nSi feu clic de nou al botó «$1», la vostra contribució es desarà sense cap.", "summary-preview": "Previsualització del resum de modificació:", "subject-preview": "Previsualització de l’assumpte:", @@ -1351,7 +1351,7 @@ "rcfilters-days-show-hours": "$1 {{PLURAL:$1|hora|hores}}", "rcfilters-highlighted-filters-list": "Destacat: $1", "rcfilters-quickfilters": "Filtres desats", - "rcfilters-quickfilters-placeholder-title": "Encara no s’ha desat cap enllaç", + "rcfilters-quickfilters-placeholder-title": "Encara no s’ha desat cap filtre", "rcfilters-quickfilters-placeholder-description": "Per desar els teus filtres i usar-los després, premeu l'icona de marcador de pàgina a l'àrea de Filtres Actius, més avall.", "rcfilters-savedqueries-defaultlabel": "Filtres desats", "rcfilters-savedqueries-rename": "Reanomena", diff --git a/languages/i18n/ce.json b/languages/i18n/ce.json index 8d836c2c30..6fb2267a3e 100644 --- a/languages/i18n/ce.json +++ b/languages/i18n/ce.json @@ -411,6 +411,8 @@ "createacct-reason-ph": "Стен кхуллуш ду ахьа керла декъашхочун дӀаяздар", "createacct-submit": "Кхолла декъашхочун дӀаяздар", "createacct-another-submit": "Кхолла декъашхочун кхин дӀаяздар", + "createacct-continue-submit": "Декъашхочун дӀаяздар кхоллар чекхдаккха", + "createacct-another-continue-submit": "Декъашхочун дӀаяздар кхоллар чекхдаккха", "createacct-benefit-heading": "{{SITENAME}} кхолийна хьо санначу наха.", "createacct-benefit-body1": "{{PLURAL:$1|нисдар|нисдарш}}", "createacct-benefit-body2": "{{PLURAL:$1|яззам|яззамаш}}", @@ -482,15 +484,24 @@ "changepassword-success": "Хьан пароль хийцина!", "changepassword-throttled": "Хьо дукха гӀиртира.\nДехар до, собар де $1 юха гӀортале.", "botpasswords": "Ботийн парольш", + "botpasswords-existing": "Ботан йолуш йолу паролаш", + "botpasswords-createnew": "Ботан керла пароль кхолла", "botpasswords-editexisting": "Тае ботан йолуш йолу пароль", "botpasswords-label-appid": "Ботан цӀе:", "botpasswords-label-create": "Кхолла", "botpasswords-label-update": "Карлаяккха", "botpasswords-label-cancel": "Юхаяккха", "botpasswords-label-delete": "ДӀаяккхар", + "botpasswords-label-resetpassword": "Пароль кхоссар", + "botpasswords-label-grants": "Лелош йолу шоралаш:", "botpasswords-label-grants-column": "Магийна", "botpasswords-bad-appid": "«$1» ботан цӀе магийна яц.", + "botpasswords-created-title": "Ботан пароль кхоьллина", "botpasswords-created-body": "Ботан «$1» пароль кхиамца кхоьллина.", + "botpasswords-updated-title": "Ботан пароль карлаяьккхина", + "botpasswords-updated-body": "«$2» декъашхочун «$1» ботан пароль карлаяьккхина.", + "botpasswords-deleted-title": "Ботан пароль дӀаяьккхина", + "botpasswords-deleted-body": "«$2» декъашхочун «$1» ботан пароль дӀаяьккхина.", "resetpass_forbidden": "Пароль хийца йиш яц", "resetpass-no-info": "ХӀара агӀо лело системин чугӀо.", "resetpass-submit-loggedin": "Хийца пароль", diff --git a/languages/i18n/de-ch.json b/languages/i18n/de-ch.json index d37dc57b22..8a26c7d36f 100644 --- a/languages/i18n/de-ch.json +++ b/languages/i18n/de-ch.json @@ -263,7 +263,7 @@ "undeletedpage": "'''«$1»''' wurde wiederhergestellt.\n\nIm [[Special:Log/delete|Lösch-Logbuch]] findest du eine Übersicht der gelöschten und wiederhergestellten Seiten.", "undelete-cleanup-error": "Fehler beim Löschen der unbenutzten Archiv-Version «$1».", "undelete-show-file-confirm": "Bist du sicher, dass du eine gelöschte Version der Datei «$1» vom $2, $3 Uhr sehen willst?", - "blanknamespace": "(Hauptseite)", + "blanknamespace": "(Seiten)", "contributions-title": "Benutzerbeiträge von «$1»", "whatlinkshere-title": "Seiten, die auf «$1» verlinken", "linkshere": "Die folgenden Seiten verlinken auf '''«[[:$1]]»''':", diff --git a/languages/i18n/de.json b/languages/i18n/de.json index 48024fe805..2407157a66 100644 --- a/languages/i18n/de.json +++ b/languages/i18n/de.json @@ -2379,7 +2379,7 @@ "tooltip-whatlinkshere-invert": "Markiere dieses Kontrollkästchen, um Links von Seiten innerhalb des ausgewählten Namensraums auszublenden.", "namespace_association": "Zugehöriger Namensraum", "tooltip-namespace_association": "Dieses Auswahlfeld anklicken, um den deiner Auswahl zugehörigen Diskussionsnamensraum, oder im umgekehrten Fall, den zugehörigen Namensraum, mit einzubeziehen", - "blanknamespace": "(Artikel)", + "blanknamespace": "(Seiten)", "contributions": "{{GENDER:$1|Benutzerbeiträge}}", "contributions-title": "Benutzerbeiträge von „$1“", "mycontris": "Beiträge", diff --git a/languages/i18n/es.json b/languages/i18n/es.json index 5d3e0bcfa1..491b8047c3 100644 --- a/languages/i18n/es.json +++ b/languages/i18n/es.json @@ -812,7 +812,7 @@ "previewconflict": "Esta previsualización muestra cómo aparecerá el texto en el área de edición superior una vez guardados los cambios.", "session_fail_preview": "Lo sentimos, no hemos podido procesar tu edición debido a una pérdida de los datos de sesión.\n\nPuede que se haya cerrado tu sesión. Verifica que hayas accedido e inténtalo de nuevo.\nSi el problema persiste, prueba a [[Special:UserLogout|cerrar sesión]] y volver a acceder. Y verifica que tu navegador permita las cookies de este sitio.", "session_fail_preview_html": "Lo sentimos, no hemos podido procesar tu edición debido a una pérdida de datos de sesión.\n\nLa previsualización está oculta como prevención frente a ataques JavaScript, puesto que este wiki tiene habilitado el HTML en bruto.\n\nSi se trata de un intento legítimo de modificación, inténtalo de nuevo.\nSi aún así no funcionase, prueba a [[Special:UserLogout|cerrar sesión]] y volver a acceder, y verifica que tu navegador acepte cookies de este sitio.", - "token_suffix_mismatch": "Tu edición ha sido rechazada porque tu cliente ha mezclado los signos de puntuación en la clave de edición.\nSe rechazó la edición para evitar la corrupción del texto de la página.\nEsto sucede en ocasiones si se usa un servicio de proxy anónimo defectuoso.", + "token_suffix_mismatch": "Se rechazó tu edición porque el cliente utilizado estropeó los caracteres de puntuación de la ficha de edición.\nEl rechazo se realizó para evitar daños en el texto de la página.\nEsto sucede a veces cuando se utiliza un servicio web de proxy anónimo defectuoso.", "edit_form_incomplete": "Una parte del formulario de edición no ha llegado al servidor. Comprueba que tus cambios están intactos e inténtalo de nuevo.", "editing": "Edición de «$1»", "creating": "Creación de «$1»", @@ -2289,7 +2289,7 @@ "delete-legend": "Borrar", "historywarning": "Atención: la página que estás a punto de borrar tiene un historial con $1 {{PLURAL:$1|revisión|revisiones}}:", "historyaction-submit": "Mostrar", - "confirmdeletetext": "Estás a punto de borrar una página, así como todo su historial.\nConfirma que realmente quieres hacer esto, que entiendes las consecuencias y que lo estás haciendo de acuerdo con [[{{MediaWiki:Policy-url}}|las políticas]].", + "confirmdeletetext": "Estás a punto de borrar una página, así como todo su historial.\nConfirma que realmente quieres hacer esto, que entiendes las consecuencias y que lo estás haciendo de acuerdo con [[{{MediaWiki:Policy-url}}|las normativas]].", "actioncomplete": "Se ha realizado la acción", "actionfailed": "Ha fallado la acción", "deletedtext": "«$1» ha sido borrado.\nVéase $2 para un registro de los borrados recientes.", diff --git a/languages/i18n/fr.json b/languages/i18n/fr.json index 202f247323..3739450831 100644 --- a/languages/i18n/fr.json +++ b/languages/i18n/fr.json @@ -158,7 +158,8 @@ "Jona", "Epok", "DePlusJean", - "Pierpao" + "Pierpao", + "Vexthedorito" ] }, "tog-underline": "Soulignement des liens :", diff --git a/languages/i18n/hi.json b/languages/i18n/hi.json index b2bd8fb35b..c74ede4e5d 100644 --- a/languages/i18n/hi.json +++ b/languages/i18n/hi.json @@ -1354,6 +1354,7 @@ "recentchanges-legend": "हाल के परिवर्तन संबंधी विकल्प", "recentchanges-summary": "इस विकि पर हाल में हुए बदलाव इस पन्ने पर देखे जा सकते हैं।", "recentchanges-noresult": "इस अवधि के दौरान इन मापदंडों को पूर्ण करते कोई परिवर्तन नहीं किए गए हैं।", + "recentchanges-timeout": "इस खोज का समय समाप्त हो गया है आप विभिन्न खोज मापदंडों की कोशिश करना चाहेंगे।", "recentchanges-feed-description": "इस विकि पर हाल में हुए बदलाव इस फ़ीड में देखे जा सकते हैं।", "recentchanges-label-newpage": "इस संपादन से नया पृष्ठ बना", "recentchanges-label-minor": "यह एक छोटा सम्पादन है", @@ -1378,7 +1379,7 @@ "rcfilters-days-show-hours": "$1 {{PLURAL:$1|घंटा|घंटे}}", "rcfilters-highlighted-filters-list": "पर प्रकाश डाला:$1", "rcfilters-quickfilters": "सुरक्षित फ़िल्टर", - "rcfilters-quickfilters-placeholder-title": "कोई कड़ी अभी तक सहेजा नहीं गया", + "rcfilters-quickfilters-placeholder-title": "कोई फ़िल्टर अभी तक सहेजे नहीं गए", "rcfilters-quickfilters-placeholder-description": "अपने फ़िल्टर सेटिंग को सहेजने और बाद में उपयोग करने के लिए नीचे दिये बूकमार्क छवि पर क्लिक करें।", "rcfilters-savedqueries-defaultlabel": "सहेजे फ़िल्टर", "rcfilters-savedqueries-rename": "नाम बदलें", @@ -1418,7 +1419,7 @@ "rcfilters-filter-user-experience-level-unregistered-label": "अपंजीकृत", "rcfilters-filter-user-experience-level-unregistered-description": "संपादक जो लॉग-इन नहीं हैं।", "rcfilters-filter-user-experience-level-newcomer-label": "अपरिचित", - "rcfilters-filter-user-experience-level-newcomer-description": "4 दिनों की गतिविधि और 10 सम्पादन से कम वाले पंजीकृत संपादक।", + "rcfilters-filter-user-experience-level-newcomer-description": "पंजीकृत संपादकों, जिनके कम से कम 10 संपादन या 4 दिन की गतिविधि हो।", "rcfilters-filter-user-experience-level-learner-label": "शिक्षार्थियों", "rcfilters-filter-user-experience-level-learner-description": "पंजीकृत संपादक जिनका अनुभव \"नये संपादक\" और \"अनुभवी संपादक\" के बीच का है।", "rcfilters-filter-user-experience-level-experienced-label": "अनुभवी सदस्य", @@ -1476,6 +1477,7 @@ "rcfilters-view-namespaces-tooltip": "नाम स्थान द्वारा फिल्टर परिणाम", "rcfilters-view-tags-tooltip": "संपादन टैग का उपयोग करके फ़िल्टर परिणाम", "rcfilters-view-return-to-default-tooltip": "मुख्य फ़िल्टर मेनू पर लौटें", + "rcfilters-view-tags-help-icon-tooltip": "टैग किए गए संपादन के बारे में और जानें", "rcfilters-liveupdates-button": "जीवंत अद्यतन", "rcfilters-liveupdates-button-title-on": "जीवंत अद्यतन बंद करें", "rcfilters-liveupdates-button-title-off": "नये परिवर्तन प्रदर्शित करें जैसे ही वे घटित होते हैं", @@ -2524,6 +2526,8 @@ "ipb_blocked_as_range": "गलती: $1 यह आइपी सीधे बाधित नहीं है और अबाध्य नहीं किया जा सकता।\nफिर भी, $2 प्रकार को बाध्य किया जा सकता है, जिनको अबाध्य किया जा सकता है।", "ip_range_invalid": "गलत आईपी रेंज", "ip_range_toolarge": "/$1 से अधिक बड़े रेञ्ज ब्लॉकों की अनुमति नहीं है।", + "ip_range_exceeded": "आईपी श्रेणी इसकी अधिकतम सीमा से अधिक है अनुमत रेंज: / $1", + "ip_range_toolow": "आईपी रेंज प्रभावी रूप से अनुमति नहीं है", "proxyblocker": "प्रॉक्सी ब्लॉकर", "proxyblockreason": "आपका IP पता बाधित किया जा चुका है क्योंकि यह एक मुक्त प्रतिनिधि है।\nकृपया आप अपने इंटरनेट सेवा प्रदान करने वाले से या तकनीकी सहायक से सम्पर्क करें अथवा उन्हें इस भयावह सुरक्षा समस्या के बारे में सूचित करें।", "sorbsreason": "{{SITENAME}} द्वारा इस्तेमालमें लाये जाने वाले DNSBL में आपके आईपी एड्रेसको ओपन प्रॉक्सीमें दर्शाया गया हैं।", diff --git a/languages/i18n/hr.json b/languages/i18n/hr.json index 547a2fd390..ab35c93eff 100644 --- a/languages/i18n/hr.json +++ b/languages/i18n/hr.json @@ -1689,7 +1689,7 @@ "statistics-files": "Postavljene datoteke", "statistics-edits": "Broj uređivanja od nastanka projekta {{SITENAME}}", "statistics-edits-average": "Prosječan broj uređivanja po stranici", - "statistics-users": "Prijavljeni [[Special:ListUsers|suradnici]]", + "statistics-users": "Registrirani [[Special:ListUsers|suradnici]]", "statistics-users-active": "Aktivni suradnici", "statistics-users-active-desc": "Suradnici koji su napravili neku od radnji u posljednjih {{PLURAL:$1|dan|$1 dana}}", "pageswithprop": "Stranice s određenim osobinama", @@ -2053,7 +2053,7 @@ "unprotectedarticle": "uklonjena zaštita članka \"[[$1]]\"", "movedarticleprotection": "premještene postavke zaštite s \"[[$2]]\" na \"[[$1]]\"", "protectedarticle-comment": "{{GENDER:$2|$2 je zaštitio|$2 je zaštitila}} \"[[$1]]\"", - "modifiedarticleprotection-comment": "{{GENDER:$2|$2 je promijenio nivo zaštite|$2 je promijenila nivo zaštite}} za \"[[$1]]\"", + "modifiedarticleprotection-comment": "{{GENDER:$2|$2 je promijenio razinu zaštite|$2 je promijenila razinu zaštite}} za »[[$1]]«", "unprotectedarticle-comment": "{{GENDER:$2|$2 je uklonio zaštitu|$2 je uklonila zaštitu}} za \"[[$1]]\"", "protect-title": "Zaštićujem \"$1\"", "protect-title-notallowed": "Vidi stupanj zaštite stranice \"$1\"", diff --git a/languages/i18n/hu.json b/languages/i18n/hu.json index f9ce3c5737..c30a33167a 100644 --- a/languages/i18n/hu.json +++ b/languages/i18n/hu.json @@ -86,6 +86,7 @@ "tog-watchlisthideminor": "Apró változtatások elrejtése", "tog-watchlisthideliu": "Bejelentkezett szerkesztők módosításainak elrejtése a figyelőlistáról", "tog-watchlistreloadautomatically": "A figyelőlista automatikus újratöltése bármelyik szűrő megváltoztatása esetén (JavaScript szükséges)", + "tog-watchlistunwatchlinks": "Közvetlen olvasottnak/olvasatlannak jelölő link hozzáadása a figyelőlista elemeihez (JavaScript szükséges)", "tog-watchlisthideanons": "Névtelen szerkesztések elrejtése", "tog-watchlisthidepatrolled": "Az ellenőrzött szerkesztések elrejtése", "tog-watchlisthidecategorization": "Lapok kategorizálásának elrejtése", @@ -341,6 +342,7 @@ "databaseerror-query": "Lekérdezés: $1", "databaseerror-function": "Függvény: $1", "databaseerror-error": "Hiba: $1", + "transaction-duration-limit-exceeded": "A nagy késleltetési idő elkerülése érdekében ez a művelet megszakadt, mert az írási idő ($1) meghaladta a $2 másodperces korlátot.\nAmennyiben sok elemet szeretnél egyszerre megváltoztatni, próbálkozz inkább többször kisebb műveletekkel.", "laggedslavemode": "'''Figyelem:''' Ez a lap nem feltétlenül tartalmazza a legfrissebb változtatásokat!", "readonly": "Az adatbázis le van zárva", "enterlockreason": "Add meg a lezárás okát, valamint egy becslést, hogy mikor lesz a lezárásnak vége", @@ -1312,6 +1314,7 @@ "recentchanges-legend": "A friss változtatások beállításai", "recentchanges-summary": "Ezen a lapon a wikiben történt legutóbbi fejleményeket lehet nyomon követni.", "recentchanges-noresult": "A megadott időszakban nincs a feltételeknek megfelelő szerkesztés.", + "recentchanges-timeout": "A keresés időtúllépés miatt leállt. Próbálkozz más keresési paraméterekkel.", "recentchanges-feed-description": "Kövesd a wiki friss változtatásait ezzel a hírcsatornával.", "recentchanges-label-newpage": "Ezzel a szerkesztéssel egy új lap jött létre", "recentchanges-label-minor": "Ez egy apró szerkesztés", @@ -1407,6 +1410,7 @@ "rcfilters-filter-watchlistactivity-unseen-label": "Még nem látott változtatások", "rcfilters-filter-watchlistactivity-unseen-description": "A figyelőlistádon szereplő lapokon az utolsó látogatásod után történt változtatások.", "rcfilters-filter-watchlistactivity-seen-label": "Változtatások megtekintése", + "rcfilters-filter-watchlistactivity-seen-description": "A lapokon az utolsó látogatásod után történt változtatások.", "rcfilters-filtergroup-changetype": "Változtatás típusa", "rcfilters-filter-pageedits-label": "Lapszerkesztések", "rcfilters-filter-pageedits-description": "A wiki tartalom szerkesztése, beszélgetések, kategória leírások...", diff --git a/languages/i18n/hy.json b/languages/i18n/hy.json index 69a2c139bb..dc53038d79 100644 --- a/languages/i18n/hy.json +++ b/languages/i18n/hy.json @@ -977,6 +977,7 @@ "rcfilters-filterlist-whatsthis": "Ինչպե՞ս է սա աշխատում:", "rcfilters-highlightmenu-title": "Ընտրեք գույնը", "rcfilters-filter-editsbyself-label": "Ձեր խմբագրումներ", + "rcfilters-filter-user-experience-level-newcomer-label": "Նորեկներ", "rcfilters-filter-user-experience-level-newcomer-description": "Գրանցված խմբագիրներ՝ ոչ պակաս քան 10 խմբագրումով և 4 օր ակտիվությամբ:", "rcfilters-filtergroup-lastRevision": "Ընթացիկ տարբերակ", "rcnotefrom": "Ստորև բերված են փոփոխությունները սկսած՝ '''$2''' (մինչև՝ '''$1''')։", diff --git a/languages/i18n/id.json b/languages/i18n/id.json index 1971cb112a..ae54a18cd4 100644 --- a/languages/i18n/id.json +++ b/languages/i18n/id.json @@ -1105,6 +1105,7 @@ "prefs-editor": "Penyunting", "prefs-preview": "Pratayang", "prefs-advancedrc": "Opsi lanjutan", + "prefs-opt-out": "Memilih keluar dari perbaikan", "prefs-advancedrendering": "Opsi lanjutan", "prefs-advancedsearchoptions": "Opsi lanjutan", "prefs-advancedwatchlist": "Opsi lanjutan", @@ -1332,6 +1333,7 @@ "recentchanges-legend": "Opsi perubahan terbaru", "recentchanges-summary": "Temukan perubahan terbaru dalam wiki di halaman ini.
\n;Keterangan:(beda) perubahan, (versi) sejarah revisi, '''B''' halaman baru, '''b''' suntingan bot, '''k''' suntingan kecil, ! perubahan belum dipatroli,
'''(+ ''bita'')''' isi konten bertambah, (- ''bita'') isi konten berkurang, (← Ringkasan otomatis), (→ Suntingan bagian)", "recentchanges-noresult": "Tidak ada perubahan dalam rentang waktu ini yang cocok dengan kriteria.", + "recentchanges-timeout": "Waktu pencarian ini telah habis. Anda mungkin ingin mencoba parameter pencarian lain.", "recentchanges-feed-description": "Temukan perubahan terbaru dalam wiki di umpan ini.", "recentchanges-label-newpage": "Suntingan ini membuat halaman baru", "recentchanges-label-minor": "Ini adalah suntingan kecil", @@ -1437,6 +1439,9 @@ "rcfilters-filter-categorization-description": "Rekam jejak halaman yang telah ditambahkan atau dihapus dari kategori.", "rcfilters-filter-logactions-label": "Tindakan tercatat", "rcfilters-filter-logactions-description": "Tindakan administratif, pembuatan akun, penghapusan halaman, pengunggahan...", + "rcfilters-hideminor-conflicts-typeofchange-global": "Tapis \"Suntingan kecil\" konflik dengan satu atau lebih jenis tapis perubahan lain, karena jenis perubahan tertentu tidak dapat ditandai sebagai \"kecil\".Tapis yang berkonflik ditandai di area Tapis aktif, di atas.", + "rcfilters-hideminor-conflicts-typeofchange": "Jenis perubahan tertentu tidak dapat ditandai sebagai \"kecil\", jadi tapis ini berkonflik dengan tapis Jenis Perubahan ini: $1", + "rcfilters-typeofchange-conflicts-hideminor": "Tapis Jenis perubahan ini berkonflik dengan tapis \"Suntingan kecil\". Jenis perubahan tertentu tidak dapat ditandai sebagai \"kecil\".", "rcfilters-filtergroup-lastRevision": "Revisi terbaru", "rcfilters-filter-lastrevision-label": "Revisi terbaru", "rcfilters-filter-lastrevision-description": "Hanya perubahan terbaru pada halaman ini.", @@ -1451,7 +1456,7 @@ "rcfilters-view-namespaces-tooltip": "Saring hasil menurut ruangnama", "rcfilters-view-tags-tooltip": "Saring hasil menggunakan tag penyuntingan", "rcfilters-view-return-to-default-tooltip": "Kembali ke menu penyaringan utama", - "rcfilters-view-tags-help-icon-tooltip": "Pelajari lebih lanjut tentang suntinggan dengan TAG", + "rcfilters-view-tags-help-icon-tooltip": "Pelajari lebih lanjut tentang suntingan dengan TAG", "rcfilters-liveupdates-button": "Perubahan langsung", "rcfilters-liveupdates-button-title-on": "Matikan perubahan langsung", "rcfilters-liveupdates-button-title-off": "Tampilkan perubahan baru ketika perubahan tersebut terjadi", @@ -2139,7 +2144,7 @@ "unwatchthispage": "Batal pantau halaman ini", "notanarticle": "Bukan sebuah halaman isi", "notvisiblerev": "Revisi telah dihapus", - "watchlist-details": "Terdapat {{PLURAL:$1|$1 halaman|$1 halaman}} di daftar pantauan Anda, tidak termasuk halaman pembicaraan.", + "watchlist-details": "Terdapat {{PLURAL:$1|$1 halaman|$1 halaman}} di daftar pantauan Anda, (termasuk halaman pembicaraan).", "wlheader-enotif": "Notifikasi surel diaktifkan.", "wlheader-showupdated": "Halaman-halaman yang telah berubah sejak kunjungan terakhir Anda ditampilkan dengan '''huruf tebal'''.", "wlnote": "Di bawah ini adalah {{PLURAL:$1|perubahan|$1 perubahan}} terakhir dalam {{PLURAL:$2|jam|$2 jam}}, per $3, $4.", diff --git a/languages/i18n/kab.json b/languages/i18n/kab.json index e93cf04716..089896b17e 100644 --- a/languages/i18n/kab.json +++ b/languages/i18n/kab.json @@ -702,8 +702,9 @@ "parser-template-recursion-depth-warning": "Talast n lqay n tiɣriwin n tilɣatin tefel ($1)", "language-converter-depth-warning": "Talast n lqay n uselkat n tutlayt tefel ($1)", "node-count-exceeded-category": "Isebtar anda amḍa n tikerwas yefel", - "node-count-exceeded-warning": "Asebter yefelen amḍan n tikerwas", + "node-count-exceeded-warning": "Asebter iɛedda amḍan afellay n tkerras", "expansion-depth-exceeded-category": "Isebtar anda lqay n uderrec yefel", + "expansion-depth-exceeded-category-desc": "Asebter iɛedda talqayt n temɣer tafellayt.", "expansion-depth-exceeded-warning": "Isebtar yefelen lqay n uderrec", "parser-unstrip-loop-warning": "Tifin n tineddict ur nezmer ara an sentuter", "parser-unstrip-recursion-limit": "Talast n usniles ur nezmer ara an sentuter tefel ($1)", @@ -711,6 +712,7 @@ "undo-success": "Tzemreḍ ad tessefsuḍ abeddil. Ssenqed asidmer akken ad tessneḍ ayen tebɣiḍ ad txdmeḍ d ṣṣeḥ, umbeɛd smekti ibeddlen u tkemmleḍ ad tessefsuḍ abeddil.", "undo-failure": "Ur yezmir ara ad issefu abeddel axaṭer yella amennuɣ abusari deg ubeddel.", "undo-norev": "Abeddel ur yezmer ara ad yetwekkes acku ulac-itt naɣ tetwekkes yakan", + "undo-nochange": "Ad yettban d akken abeddel yettwasefsex yakan.", "undo-summary": "Ssefsu tasiwelt $1 sɣur [[Special:Contributions/$2|$2]] ([[User talk:$2|Meslay]])", "undo-summary-username-hidden": "Semmewet tacaggart $1 sɣur amseqdac yeffren", "cantcreateaccount-text": "Asnulfu n umiḍan seg tansa IP ($1) tekyef sɣur [[User:$3|$3]].\n\nTaɣẓint n $3 : ''$2''", @@ -731,7 +733,7 @@ "page_last": "aneggaru", "histlegend": "Axtiri n umgerrad: rcem tankulin akken ad teẓreḍ imgerraden ger tisiwal u wekki ɣef enter/entrée neɣ ɣef taqeffalt deg ukessar.
\nTabadut: (tura) = amgirred akk d tasiwelt n tura,\n(amgirred) = amgirred akk d tasiwelt ssabeq, M = abeddel afessas.", "history-fieldset-title": "Nadi iceggiren", - "history-show-deleted": "Ekkes kan", + "history-show-deleted": "Aceggir yettwakksen kan", "histfirst": "tiqdimin", "histlast": "timaynutin", "historysize": "({{PLURAL:$1|1 atamḍan|$1 itamḍanen}})", @@ -740,9 +742,10 @@ "history-feed-description": "Amezruy n tsiwelt n usebter-agi deg wiki", "history-feed-item-nocomment": "$1 deg $2", "history-feed-empty": "Asebter i tebɣiḍ ulac-it.\nAhat yettumḥa neɣ yettbeddel isem-is.\nƐreḍ [[Special:Search|ad tnadiḍ deg wiki]] ɣef isebtar imaynuten.", + "history-edit-tags": "Ẓreg tirekkizin n ileqman yettwafernen", "rev-deleted-comment": "(agzul n taẓrigt yettwakes)", "rev-deleted-user": "(isem n wemseqdac yettwakes)", - "rev-deleted-event": "(asekcem yettwakkes)", + "rev-deleted-event": "(talqayt n umazray tettwakkes)", "rev-deleted-user-contribs": "[isem n useqdac naɣ tansa IP yetwemḥa - abeddel yeffer deg tiwsitin]", "rev-deleted-text-permission": "Lqem n usebter agi '''tetwesfeḍ'''.\nTilɣa llant deg [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} uɣmis n usfeḍ].", "rev-deleted-text-unhide": "Lqem n usebter agi '''tetwesfeḍ'''.\nTilɣa llant deg [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} uɣmis n usfeḍ].\nTzemreḍ meqqar [$1 ad ẓṛeḍ lqem agi] ma tebɣiḍ", diff --git a/languages/i18n/ko.json b/languages/i18n/ko.json index 3ba1eafe79..77221be8ac 100644 --- a/languages/i18n/ko.json +++ b/languages/i18n/ko.json @@ -698,7 +698,7 @@ "missing-revision": "\"{{FULLPAGENAME}}\"이라는 문서의 #$1판이 존재하지 않습니다.\n\n이 문제는 주로 삭제된 문서를 가리키는 오래된 문서 역사 링크로 인해 발생합니다.\n자세한 내용은 [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} 삭제 기록]에서 확인할 수 있습니다.", "userpage-userdoesnotexist": "\"$1\" 사용자 계정은 등록되어 있지 않습니다.\n이 문서를 만들거나 편집하기 전에 계정이 존재하는지 확인해주세요.", "userpage-userdoesnotexist-view": "\"$1\" 사용자 계정은 등록되어 있지 않습니다.", - "blocked-notice-logextract": "이 사용자는 현재 차단되어 있습니다.\n해당 사용자의 최근 차단 기록을 참조하십시오:", + "blocked-notice-logextract": "이 사용자는 현재 차단되어 있습니다.\n해당 사용자의 최신 차단 기록을 참조하십시오:", "clearyourcache": "참고: 설정을 저장한 후에 바뀐 점을 확인하기 위해서는 브라우저의 캐시를 새로 고쳐야 합니다.\n* 파이어폭스 / 사파리: Shift 키를 누르면서 새로 고침을 클릭하거나, Ctrl-F5 또는 Ctrl-R을 입력 (Mac에서는 ⌘-R)\n* 구글 크롬: Ctrl-Shift-R키를 입력 (Mac에서는 ⌘-Shift-R)\n* 인터넷 익스플로러: Ctrl 키를 누르면서 새로 고침을 클릭하거나, Ctrl-F5를 입력.\n* 오페라: 메뉴 → 설정(맥의 경우 오페라 → 환경 설정)으로 이동한 다음 개인 정보 보호 및 보안 → 검색 데이터 지우기 → 캐시한 이미지 및 파일을 누름.", "usercssyoucanpreview": "'''안내''': CSS 문서를 저장하기 전에 \"{{int:showpreview}}\" 기능을 통해 작동을 확인해주세요.", "userjsyoucanpreview": "'''안내''': 자바스크립트 문서를 저장하기 전에 \"{{int:showpreview}}\" 기능을 통해 작동을 확인해주세요.", @@ -732,10 +732,10 @@ "editpage-cannot-use-custom-model": "이 문서의 콘텐츠 모델은 변경될 수 없습니다.", "longpageerror": "'''오류: 문서의 크기가 {{PLURAL:$1|$1킬로바이트}}로 최대 크기인 {{PLURAL:$2|$2킬로바이트}}보다 큽니다.'''\n저장할 수 없습니다.", "readonlywarning": "경고: 데이터베이스가 관리를 위해 잠겨 있습니다. 따라서 문서를 편집한 내용을 지금 저장할 수 없습니다.\n편집 내용을 복사하여 붙여넣기 등을 사용하여 일단 다른 곳에 저장한 후, 나중에 다시 시도해 주세요.\n\n데이터베이스를 잠근 시스템 관리자가 남긴 설명은 다음과 같습니다: $1", - "protectedpagewarning": "경고: 이 문서는 관리자 권한이 있는 사용자만 편집할 수 있도록 보호되어 있습니다.\n이 문서의 최근 기록을 참조하십시오:", - "semiprotectedpagewarning": "참고: 이 문서는 계정을 등록한 사용자만이 편집할 수 있도록 보호되어 있습니다.\n이 문서의 최근 기록을 참조하십시오:", + "protectedpagewarning": "경고: 이 문서는 관리자 권한이 있는 사용자만 편집할 수 있도록 보호되어 있습니다.\n최신 기록은 참조를 위해 아래에 제공됩니다:", + "semiprotectedpagewarning": "참고: 이 문서는 계정을 등록한 사용자만이 편집할 수 있도록 보호되어 있습니다.\n최신 기록은 참조를 위해 아래에 제공됩니다:", "cascadeprotectedwarning": "경고: 이 문서는 보호되어 있어 [[Special:ListGroupRights|특정 권한]]이 있는 사용자만 편집할 수 있습니다. 연쇄적 보호가 걸린 다음 {{PLURAL:$1|문서}}에서 이 문서를 사용하고 있습니다:", - "titleprotectedwarning": "경고: 이 문서는 보호되어 있어, 문서를 만드려면 [[Special:ListGroupRights|특정한 권한]]이 필요합니다.\n아래 문서의 최근 기록을 참조하십시오:", + "titleprotectedwarning": "경고: 이 문서는 보호되어 있어, 문서를 만드려면 [[Special:ListGroupRights|특정한 권한]]이 필요합니다.\n최신 기록은 참조를 위해 아래에 제공됩니다:", "templatesused": "이 문서에서 사용한 {{PLURAL:$1|틀}}:", "templatesusedpreview": "이 미리 보기에서 사용하고 있는 {{PLURAL:$1|틀}}:", "templatesusedsection": "이 문단에서 사용하고 있는 {{PLURAL:$1|틀}}:", @@ -1591,7 +1591,7 @@ "uploaded-script-svg": "업로드된 SVG 파일에서 스크립트로 만들 수 있는 \"$1\" 요소를 발견했습니다.", "uploaded-hostile-svg": "업로드된 SVG 파일의 스타일 요소에 안전하지 않은 CSS가 있습니다.", "uploaded-event-handler-on-svg": "이벤트 핸들러 속성 $1=\"$2\" 설정은 SVG 파일에서 사용할 수 없습니다.", - "uploaded-href-attribute-svg": "SVG 파일의 href 속성은 http:// 또는 https:// 대상의 링크만 허용되지만 <$1 $2=\"$3\">를 발견했습니다.", + "uploaded-href-attribute-svg": " 요소는 data: (내장 파일), http://, https://, 문서의 부분 (#, 동일 문서) 타겟만을 링크(href)할 수 있습니다. 와 같은 그 외 요소는 data:와 부분 타겟만 허용됩니다. SVG 파일을 내보낼 때 사진을 포함해 보세요. <$1 $2=\"$3\">를 발견했습니다.", "uploaded-href-unsafe-target-svg": "안전하지 않은 데이터를 가리키는 href를 발견했습니다: 업로드된 SVG 파일의 URI 대상 <$1 $2=\"$3\">", "uploaded-animate-svg": "업로드된 SVG 파일에서 \"from\" 특성 <$1 $2=\"$3\">을 이용 중 \"animate\" 태그가 href를 변경할 수 있음을 발견했습니다.", "uploaded-setting-event-handler-svg": "이벤트 핸들러 속성을 차단으로 설정한 상태에서 <$1 $2=\"$3\">가 업로드된 SVG 파일에서 발견되었습니다.", @@ -2036,7 +2036,7 @@ "allpages-hide-redirects": "넘겨주기 숨기기", "cachedspecial-viewing-cached-ttl": "이 문서의 캐시된 판을 보고 있으며, 최대 $1만큼 지난 판일 수 일 수 있습니다.", "cachedspecial-viewing-cached-ts": "현재 이 문서는 캐시 처리된 버전으로 현재 문서 상태를 반영하지 않을 수도 있습니다.", - "cachedspecial-refresh-now": "최신 버전 보기.", + "cachedspecial-refresh-now": "최신판을 봅니다.", "categories": "분류 목록", "categories-submit": "보이기", "categoriespagetext": "문서나 자료를 {{PLURAL:$1|포함하고 있는 분류}} 목록입니다.\n[[Special:UnusedCategories|사용되지 않는 분류]]는 여기에 보이지 않습니다.\n[[Special:WantedCategories|필요한 분류]]도 참조하세요.", @@ -2590,8 +2590,8 @@ "imageinvalidfilename": "대상 파일 이름이 잘못되었습니다.", "fix-double-redirects": "원래 제목을 가리키는 넘겨주기를 새로 고침", "move-leave-redirect": "이동한 뒤 넘겨주기를 남기기", - "protectedpagemovewarning": "경고: 이 문서는 관리자만 이동할 수 있도록 보호되어 있습니다.\n최근 기록을 참조를 위해 아래에 제공합니다:", - "semiprotectedpagemovewarning": "참고: 이 문서는 등록된 사용자만이 이동할 수 있도록 보호되어 있습니다.\n최근 기록 내용이 참조를 위해 아래에 제공됩니다:", + "protectedpagemovewarning": "경고: 이 문서는 관리자 권한이 있는 사용자만 이동할 수 있도록 보호되어 있습니다.\n최신 기록은 참조를 위해 아래에 제공됩니다:", + "semiprotectedpagemovewarning": "참고: 이 문서는 등록된 사용자만이 이동할 수 있도록 보호되어 있습니다.\n최신 기록은 참조를 위해 아래에 제공됩니다:", "move-over-sharedrepo": "== 파일이 존재함 ==\n[[:$1]] 파일이 공용 저장소에 있습니다. 이 이름으로 파일을 이동하면 공용의 파일을 덮어쓰게 될 것입니다.", "file-exists-sharedrepo": "선택한 파일 이름은 공용 저장소에서 사용 중입니다.\n다른 이름을 선택하세요.", "export": "문서 내보내기", @@ -2823,7 +2823,7 @@ "pageinfo-firstuser": "문서 작성자", "pageinfo-firsttime": "문서 작성 날짜", "pageinfo-lastuser": "마지막 편집자", - "pageinfo-lasttime": "최근 편집 날짜", + "pageinfo-lasttime": "마지막으로 편집한 날짜", "pageinfo-edits": "총 편집 수", "pageinfo-authors": "총 서로 다른 편집자 수", "pageinfo-recent-edits": "최근 편집 수 (지난 $1 이내)", diff --git a/languages/i18n/lb.json b/languages/i18n/lb.json index 41f4d4c34a..2dabb8f5f0 100644 --- a/languages/i18n/lb.json +++ b/languages/i18n/lb.json @@ -730,6 +730,7 @@ "parser-template-loop-warning": "Endlos Schleef an der Schabloun: [[$1]] entdeckt", "template-loop-category": "Säite mat Endlos-Schleefe vu Schablounen", "template-loop-category-desc": "An der Säit ass eng Endlos-Schabloun, z. Bsp. eng Schabloun déi sech selwer rekursiv oprifft.", + "template-loop-warning": "Opgepasst: Dës Säit benotzt [[:$1]] déi eng Endlooschleef vu Schabloune generéiert (deng onendlech Zuel vum selwechten Opruff)", "parser-template-recursion-depth-warning": "D'Limit vun der Zuel vun de Verschachtelunge vu Schabloune gouf iwwerschratt ($1)", "language-converter-depth-warning": "D'Limite vun der déift vun der Sproochëmwandlung gouf iwwerschratt ($1)", "node-count-exceeded-category-desc": "D'Säit huet méi wéi déi maximal Zuel vu Kniet (Node-count).", @@ -1277,6 +1278,7 @@ "rcfilters-savedqueries-new-name-label": "Numm", "rcfilters-savedqueries-new-name-placeholder": "Den Zweck vum Filter beschreiwen", "rcfilters-savedqueries-apply-label": "Filter uleeën", + "rcfilters-savedqueries-apply-and-setdefault-label": "Standardfilter uleeën", "rcfilters-savedqueries-cancel-label": "Ofbriechen", "rcfilters-savedqueries-add-new-title": "Aktuell Filter-Astellunge späicheren", "rcfilters-restore-default-filters": "Standardfiltere restauréieren", @@ -3345,7 +3347,10 @@ "compare-title-not-exists": "Den Titel deen Dir uginn hutt gëtt et net.", "compare-revision-not-exists": "D'Versioun déi Dir uginn hutt gëtt et net.", "diff-form": "Ënnerscheeder", + "diff-form-oldid": "Al Versiounsnummer (fakultativ)", + "diff-form-revid": "Versiounsnummer vum Ënnerscheed", "diff-form-submit": "Ënnerscheeder weisen.", + "permanentlink": "Permanente Link", "permanentlink-revid": "Nummer (ID) vun der Versioun", "permanentlink-submit": "Op d'Versioun goen", "dberr-problems": "Pardon! Dëse Site huet technesch Schwieregkeeten.", diff --git a/languages/i18n/lfn.json b/languages/i18n/lfn.json index 8a730c912d..c416fd30ee 100644 --- a/languages/i18n/lfn.json +++ b/languages/i18n/lfn.json @@ -611,7 +611,7 @@ "anonpreviewwarning": "Tu no es autenticida. Si tu fisa cambias, tua adirije IP va es rejistrada en la istoria de esta paje.", "missingsummary": "Avisa: Tu no ia furni un resoma de la edita.\nSi tu clica \"$1\" denova, tua edita va es fisada sin resoma.", "selfredirect": "Avisa: Tu redirije esta paje a se.\nCisa tu no ia spesifa coreta la gol de la redirije, o cisa tu no edita la paje intendeda.\nSi tu clica \"$1\" denova, la redirije va es creada an tal.", - "missingcommenttext": "Tape un comenta a su, per favore.", + "missingcommenttext": "Presenta un comenta, per favore.", "missingcommentheader": "Avisa: Tu no ia furni un tema per esta comenta.\nSi tu clica \"$1\" denova, tua edita va es fisada sin tema.", "summary-preview": "Previde de resoma:", "subject-preview": "Previde de tema:", @@ -665,6 +665,7 @@ "yourtext": "Tua testo", "storedversion": "Testo esistente", "editingold": "Avisa: Tu edita un revisa nonfresca de esta paje.\nSi tu fisa lo, cualce cambias fada pos esta revisa va es perdeda.", + "unicode-support-fail": "Lo pare ce tua surfador no suporta Unicode. Lo es nesesada per edita pajes, donce tua edita no ia es fisada.", "yourdiff": "Diferes", "copyrightwarning": "Per favore, nota ce tota contribuis a {{SITENAME}} es regardada como relasada su la $2 (vide $1 per detalias). Si tu no desira ce on edita tua scrives sin compatia e redistribui libre los, alora no ajunta los asi.
\nTu promete ance a nos ce tu mesma ia scrive esta, o ia copia lo de un recurso de domina publica o simil libre.\nNo ajunta testo restrinjeda par direto de autor sin permete!", "copyrightwarning2": "Per favore, nota ce tota contribuis a {{SITENAME}} pote es editada, alterada o sutraeda par otra contribuores.\nSi tu no desira ce on edita tua scrives sin compatia, alora no ajunta los asi.
\nTu promete ance a nos ce tu mesma ia scrive esta, o ia copia lo de un recurso de domina publica o simil libre (vide $1 per detalias).\nNo ajunta testo restrinjeda par direto de autor sin permete!", @@ -998,8 +999,8 @@ "timezoneregion-europe": "Europa", "timezoneregion-indian": "Mar Indian", "timezoneregion-pacific": "Mar Pasifica", - "allowemail": "Permete epostas de otra usores", - "email-blacklist-label": "Proibi esta usores de envia epostas a me:", + "allowemail": "Permete ce otra usores pote eposta me", + "email-blacklist-label": "Proibi esta usores de eposta a me:", "prefs-searchoptions": "Xerca", "prefs-namespaces": "Spasios de nom", "default": "inisial", @@ -1267,6 +1268,7 @@ "recentchanges-legend": "Elejes per cambias resente", "recentchanges-summary": "Segue asi la cambias la plu resente a la vici.", "recentchanges-noresult": "No cambias en la periodo spesifada coresponde a esta criterios.", + "recentchanges-timeout": "Esta xerca ia es abandonada. Posible, tu desira atenta otra parametres de xerca.", "recentchanges-feed-description": "Segue la cambias la plu resente a la vici en esta flue.", "recentchanges-label-newpage": "Esta edita ia crea un paje nova", "recentchanges-label-minor": "Esta es un edita minor", @@ -1291,7 +1293,7 @@ "rcfilters-days-show-hours": "$1 {{PLURAL:$1|ora|oras}}", "rcfilters-highlighted-filters-list": "Marcada: $1", "rcfilters-quickfilters": "Filtros fisada", - "rcfilters-quickfilters-placeholder-title": "No lias es fisada", + "rcfilters-quickfilters-placeholder-title": "No filtreos es fisada ancora", "rcfilters-quickfilters-placeholder-description": "Per fisa tua ajustas de filtro e reusa los en la futur, clica la icon de sinta de libro en la area \"Filtros ativa\", a su.", "rcfilters-savedqueries-defaultlabel": "Filtros fisada", "rcfilters-savedqueries-rename": "Renomi", @@ -1331,7 +1333,7 @@ "rcfilters-filter-user-experience-level-unregistered-label": "Anonim", "rcfilters-filter-user-experience-level-unregistered-description": "Editores ci no ia autentici", "rcfilters-filter-user-experience-level-newcomer-label": "Comensores", - "rcfilters-filter-user-experience-level-newcomer-description": "Editores autenticida con min ca 10 editas e 4 dias de ativia.", + "rcfilters-filter-user-experience-level-newcomer-description": "Editores autenticida ci ave min ca 10 editas o 4 dias de ativia.", "rcfilters-filter-user-experience-level-learner-label": "Aprendores", "rcfilters-filter-user-experience-level-learner-description": "Editores autenticida de ci sua esperia es entre \"Comensores\" e \"Usores esperiosa\".", "rcfilters-filter-user-experience-level-experienced-label": "Usores esperiosa", @@ -1389,6 +1391,7 @@ "rcfilters-view-namespaces-tooltip": "Filtri resultas par spasio de nom", "rcfilters-view-tags-tooltip": "Filtri resultas par eticetas de edita", "rcfilters-view-return-to-default-tooltip": "Revade a menu xef de filtros", + "rcfilters-view-tags-help-icon-tooltip": "Aprende plu sur editas edicetida", "rcfilters-liveupdates-button": "Refrescis automata", "rcfilters-liveupdates-button-title-on": "Descomuta refrescis automata", "rcfilters-liveupdates-button-title-off": "Mostra cambias nova, direta cuando los aveni", @@ -1525,7 +1528,7 @@ "uploaded-script-svg": "Elemento automatable \"$1\" ia es trovada en la fix SVG cargada.", "uploaded-hostile-svg": "CSS nonsecur ia es trovada en la stilo de la fix SVG cargada.", "uploaded-event-handler-on-svg": "On no permete defini atribuidas per trata avenis $1=\"$2\" en fixes de SVG.", - "uploaded-href-attribute-svg": "Atribuidas href en fixes SVG es sola permeteda a lia a adirijes http:// o https://, ma <$1 $2=\"$3\"> ia es trovada.", + "uploaded-href-attribute-svg": "elementos de
pote lia (href) sola a datos: (arcivo caxida), http:// o https://, o ojetos fratal (#, mesma-testo). Per otra elementos, com , sola datos e fratas es permeteda. Atenta caxi imajes cuando on esporta sua SVG. <$1 $2=\"$3\"> ia es trovada.", "uploaded-href-unsafe-target-svg": "Un href a datos nonsecur ia es trovada en la fix SVG cargada: adirije destinal <$1 $2=\"$3\">.", "uploaded-animate-svg": "Un eticeta \"animate\" cual ta pote cambia href, usante la atribuida \"from\" <$1 $2=\"$3\">, ia es trovada en la fix SVG cargada.", "uploaded-setting-event-handler-svg": "On proibi la defini de atribuidas per trata avenis, ma <$1 $2=\"$3\"> ia es trovada en la fix SVG cargada.", @@ -2435,6 +2438,8 @@ "ipb_blocked_as_range": "Era: La adirije IP $1 no es direta impedida e no pote es desimpedida.\nMa lo es impedida como parte de la estende $2, cual pote es desimpedida.", "ip_range_invalid": "Estende nonvalida de adirijes IP.", "ip_range_toolarge": "Impedis de estendes IP plu grande ca /$1 no es permeteda.", + "ip_range_exceeded": "La estende de IP surpasa sua estenda masima. Estenda permeteda: /$1.", + "ip_range_toolow": "estendes de IP no es valida permeteda.", "proxyblocker": "Impedador de proxis", "proxyblockreason": "Tua adirije IP es impedida car lo es un proxi abrida.\nPer favore, contata tua furnor de servi de interede o la suporta tecnical de tua organiza e informa los de esta problem major de securia.", "sorbsreason": "Tua adirije IP es listada como un proxi abrida en la DNSBL usada par {{SITENAME}}.", @@ -2504,7 +2509,7 @@ "delete_and_move_text": "La paje destinal \"[[:$1]]\" esiste ja.\nEsce tu vole sutrae lo per crea un spasio per la move?", "delete_and_move_confirm": "Si, sutrae la paje", "delete_and_move_reason": "Sutraeda per crea un spasio per move de \"[[$1]]\"", - "selfmove": "Titulos fontal e destinal es la mesma;\nun paje no pote moveda a la mesma paje.", + "selfmove": "La titulo es la mesma; on no pote move un paje sur sua mesma.", "immobile-source-namespace": "Pajes en spasio de nom \"$1\" no pote es moveda.", "immobile-target-namespace": "Pajes no pote es moveda a en spasio de nom \"$1\".", "immobile-target-namespace-iw": "Lia intervical no es un destina valida per move de paje.", diff --git a/languages/i18n/lv.json b/languages/i18n/lv.json index dee5cf197c..1caea8d606 100644 --- a/languages/i18n/lv.json +++ b/languages/i18n/lv.json @@ -626,7 +626,7 @@ "permissionserrorstext": "Tev nav atļauts veikt šo darbību {{PLURAL:$1|šādu iemeslu|šāda iemesla|šādu iemeslu}} dēļ:", "permissionserrorstext-withaction": "Tev nav atļauts $2 {{PLURAL:$1|šādu iemeslu|šāda iemesla|šādu iemeslu}} dēļ:", "recreate-moveddeleted-warn": "'''Brīdinājums: Tu atjauno lapu, kas ir tikusi izdzēsta'''\n\nTev vajadzētu pārliecināties, vai ir lietderīgi turpināt izmainīt šo lapu.\nTe var apskatīt dzēšanas un pārvietošanas reģistrus, kuros jābūt datiem par to kas, kad un kāpēc šo lapu izdzēsa.", - "moveddeleted-notice": "Šī lapa ir tikusi izdzēsta.\nTe var apskatīt dzēšanas un pārvietošanas reģistru fragmentus, lai noskaidrotu kurš, kāpēc un kad to izdzēsa.", + "moveddeleted-notice": "Šī lapa ir tikusi izdzēsta.\nDzēšanas, aizsargāšanas un pārvietošanas reģistru ieraksti ir pieejami zemāk.", "log-fulllog": "Paskatīties pilnu reģistru", "edit-hook-aborted": "Aizķere pārtrauca labojumu.\nNetika sniegts paskaidrojums.", "edit-gone-missing": "Nevar atjaunināt lapu.\nIzskatās, ka lapa ir dzēsta.", @@ -676,7 +676,7 @@ "page_first": "pirmā", "page_last": "pēdējā", "histlegend": "Atšķirību izvēle: atzīmē vajadzīgo versiju apaļās pogas un spied \"Salīdzināt izvēlētās versijas\".
\nApzīmējumi:\n\"ar pašreizējo\" = salīdzināt ar pašreizējo versiju,\n\"ar iepriekšējo\" = salīdzināt ar iepriekšējo versiju,\nm = maznozīmīgs labojums.", - "history-fieldset-title": "Meklēt hronoloģijā", + "history-fieldset-title": "Versiju meklēšana", "history-show-deleted": "Tikai dzēstās", "histfirst": "Senākās", "histlast": "Jaunākās", @@ -2192,6 +2192,7 @@ "pageinfo-header-edits": "Labojumu vēsture", "pageinfo-header-restrictions": "Lapas aizsardzība", "pageinfo-header-properties": "Lapas parametri", + "pageinfo-display-title": "Attēlojamais nosaukums", "pageinfo-length": "Lapas garums (baitos)", "pageinfo-article-id": "Lapas ID", "pageinfo-language": "Lappuses satura valoda", @@ -2210,6 +2211,7 @@ "pageinfo-authors": "Kopējais atsevišķu autoru skaits", "pageinfo-magic-words": "{{PLURAL:$1|Maģiskie vārdi|Maģiskais vārds|Maģiskie vārdi}} ($1)", "pageinfo-hidden-categories": "{{PLURAL:$1|Slēptas kategorijas|Slēpta kategorija|Slēptas kategorijas}} ($1)", + "pageinfo-templates": "{{PLURAL:$1|Iekļautās veidnes|Iekļautā veidne|Iekļautās veidnes}} ($1)", "pageinfo-toolboxlink": "Lapas informācija", "pageinfo-redirectsto": "Pāradresē uz", "pageinfo-redirectsto-info": "info", @@ -2784,6 +2786,7 @@ "logentry-move-move-noredirect": "$1 {{GENDER:$2|pārvietoja}} lapu $3 uz $4, neatstājot pāradresāciju", "logentry-move-move_redir": "$1 {{GENDER:$2|pārvietoja}} lapu $3 uz $4, atstājot pāradresāciju", "logentry-move-move_redir-noredirect": "$1 {{GENDER:$2|pārvietoja}} lapu $3 uz $4 ar pāradresāciju, neatstājot pāradresāciju", + "logentry-patrol-patrol-auto": "$1 automātiski {{GENDER:$2|atzīmēja}} lapas $3 versiju $4 kā pārbaudītu", "logentry-newusers-newusers": "Lietotāja konts $1 tika {{GENDER:$2|izveidots}}", "logentry-newusers-create": "Lietotāja konts $1 tika {{GENDER:$2|izveidots}}", "logentry-newusers-create2": "$1 {{GENDER:$2|izveidoja}} lietotāja kontu $3", diff --git a/languages/i18n/ml.json b/languages/i18n/ml.json index 5c35bf02b6..b02efb8708 100644 --- a/languages/i18n/ml.json +++ b/languages/i18n/ml.json @@ -2157,6 +2157,7 @@ "sp-contributions-username": "ഐ.പി. വിലാസം അഥവാ ഉപയോക്തൃനാമം:", "sp-contributions-toponly": "ഒടുവിലത്തെ നാൾപ്പതിപ്പുകൾ മാത്രം പ്രദർശിപ്പിക്കുക", "sp-contributions-newonly": "താളുകൾ സൃഷ്ടിച്ച തിരുത്തുകൾ മാത്രം പ്രദർശിപ്പിക്കുക", + "sp-contributions-hideminor": "ചെറുതിരുത്തുകൾ മറയ്ക്കുക", "sp-contributions-submit": "തിരയൂ", "whatlinkshere": "ഈ താളിലേക്കുള്ള കണ്ണികൾ", "whatlinkshere-title": "\"$1\" എന്ന താളിലേക്കുള്ള കണ്ണികൾ", @@ -3530,6 +3531,8 @@ "mw-widgets-dateinput-no-date": "തീയതി ഒന്നും തിരഞ്ഞെടുത്തിട്ടില്ല", "mw-widgets-titleinput-description-new-page": "താൾ ഇപ്പോൾ നിലവിലില്ല", "mw-widgets-titleinput-description-redirect": "$1 എന്ന താളിലേക്കുള്ള തിരിച്ചുവിടൽ", + "date-range-from": "ഈ തീയതി മുതൽ:", + "date-range-to": "ഈ തീയതി വരെ:", "sessionmanager-tie": "വ്യത്യസ്ത തരത്തിലുള്ള അനുമതി നൽകൽ തരങ്ങൾ സംയോജിപ്പിക്കാനാവില്ല: $1.", "sessionprovider-generic": "$1 സെഷനുകൾ", "sessionprovider-mediawiki-session-cookiesessionprovider": "കൂക്കി-അധിഷ്ഠിത സെഷനുകൾ", diff --git a/languages/i18n/mr.json b/languages/i18n/mr.json index b38e64151c..fab2cbb341 100644 --- a/languages/i18n/mr.json +++ b/languages/i18n/mr.json @@ -260,7 +260,7 @@ "pool-errorunknown": "अपरिचित त्रुटी", "pool-servererror": "पूल काउंटर सेवा उपलब्ध नाही($1).", "poolcounter-usage-error": "वापर त्रुटी:$1", - "aboutsite": "{{SITENAME}} बद्दल", + "aboutsite": "{{SITENAME}}बद्दल", "aboutpage": "Project:माहितीपृष्ठ", "copyright": "येथील मजकूर $1च्या अंतर्गत उपलब्ध आहे जोपर्यंत इतर नोंदी केलेल्या नाहीत.", "copyrightpage": "{{ns:project}}:प्रताधिकार", diff --git a/languages/i18n/nl.json b/languages/i18n/nl.json index 6fc29108e0..aa73bbea47 100644 --- a/languages/i18n/nl.json +++ b/languages/i18n/nl.json @@ -88,7 +88,8 @@ "Jos1950", "Ooswesthoesbes", "MarcoSwart", - "Pahles" + "Pahles", + "Optilete" ] }, "tog-underline": "Verwijzingen onderstrepen:", @@ -1352,6 +1353,7 @@ "recentchanges-legend": "Opties voor recente wijzigingen", "recentchanges-summary": "Op deze pagina kunt u de recentste wijzigingen in deze wiki bekijken.", "recentchanges-noresult": "Er zijn in deze periode geen wijzigingen gemaakt die aan de criteria voldoen.", + "recentchanges-timeout": "Deze zoekopdracht kost te veel tijd. U kunt het opnieuw proberen met andere zoekparameters.", "recentchanges-feed-description": "Met deze feed kunt u de recentste wijzigingen in deze wiki bekijken.", "recentchanges-label-newpage": "Met deze bewerking is een nieuwe pagina aangemaakt", "recentchanges-label-minor": "Dit is een kleine bewerking", diff --git a/languages/i18n/pcd.json b/languages/i18n/pcd.json index 5398d0f20d..3db9ccbdf6 100644 --- a/languages/i18n/pcd.json +++ b/languages/i18n/pcd.json @@ -130,13 +130,7 @@ "anontalk": "Bavouér", "navigation": "Navigachon", "and": " pi", - "qbfind": "Trouvoèr", - "qbbrowse": "Trifouille", - "qbedit": "Editer", - "qbpageoptions": "Chol pache-lo", - "qbmyoptions": "Mes paches", "faq": "FAQ", - "faqpage": "Project:FAQ", "actions": "Acchons", "namespaces": "Éspaces d'chés noms", "variants": "Ércanjantes", @@ -162,32 +156,22 @@ "edit-local": "Modifier el déscripcion locale", "create": "Créer", "create-local": "Ajouter ène déscripcion locale", - "editthispage": "Éditer chl'pache-lo", - "create-this-page": "Créer chl'pache lo", "delete": "Défacer", - "deletethispage": "Défacer chl'pache lo", - "undeletethispage": "n'poin défacer chol pache", "undelete_short": "Déface poin {{PLURAL:$1|un édite|$1 édites}}", "viewdeleted_short": "{{PLURAL:$1|eune édition défacée|$1 éditions défacées}}", "protect": "Garantir", "protect_change": "canger", - "protectthispage": "Défènner l'pache", "unprotect": "Canger l'garantie", - "unprotectthispage": "Canger la garantie ed chol pache", "newpage": "Nouvèle pache", - "talkpage": "Alédjer l'pache-lo", "talkpagelinktext": "Dviser", "specialpage": "Pache éspéchiale", "personaltools": "Otis dech uzeu", - "articlepage": "Vir el pache ed ches étnus", "talk": "distchuter", "views": "Vues", "toolbox": "Boéte à otis", "tool-link-userrights": "Modifier chés groupes éd {{GENDER:$1|l’uzeu|l’uzeuse}}", "tool-link-userrights-readonly": "Vir chés {{GENDER:$1|groupes d'uzeu}}", "tool-link-emailuser": "Invouéyer un courriel à {{GENDER:$1|l’uzeu|l’uzeuse}}", - "userpage": "Vir el pache dech uzeu", - "projectpage": "Vir l'pache dech prodjé", "imagepage": "Vir el pache dech fichié", "mediawikipage": "Vir messache pache", "templatepage": "Vir el pache dech modéle", @@ -514,6 +498,8 @@ "recentchanges-label-minor": "C'est un tiot canjemint", "recentchanges-label-bot": "Chol modificacion ale o té foaite pèr un robot.", "recentchanges-label-unpatrolled": "Chol modificacion ale n’o poin coèr té controlée.", + "recentchanges-label-plusminus": "Él taille deul pache al o cangé éd chol nombe d’octets.", + "rcfilters-legend-heading": "Lisse des abréviacions :", "rcnotefrom": "Vlo chés modificacions foaites édpuis l' '''$2''' (dousqu'à '''$1''' au plus).", "rclistfrom": "Montrer chés nouvieus cangemints d'puis $3 $2", "rcshowhideminor": "$1 tiotes éditions", @@ -711,7 +697,6 @@ "whatlinkshere-filters": "Filtes", "block": "Blotcher l'uzeu", "blockip": "Blotcher l'uzeu", - "blockip-legend": "Blotcher l'uzeu", "blockiptext": "Uzer dech teske-lo pour blotcher l’ahérse aux canjemints foaits dpui eune adrèche IP éspéchifique o bin d’un nom d’uzeu.\nI feut l'foaire seleumint pour inréyer ech vindalime et pi i feut ète acordant aveuc chés [[{{MediaWiki:Policy-url}}|usages intérnes]].\nDonner apré ch'motif (pèr egzimpe chiter chés paches qu'ont té vindalisées).", "ipboptions": "2 heures:2 hours,1 jour:1 day,3 jours:3 days,1 ésminne:1 week,2 ésminnes:2 weeks,1 moés:1 month,3 moés:3 months,6 moés:6 months,1 an:1 year,infini:infinite", "blocklist": "Uzeus blotchés", @@ -823,7 +808,6 @@ "version-specialpages": "Paches éspéchiales", "fileduplicatesearch": "Dénicher chés doublons", "specialpages": "Paches éspéchiales", - "specialpages-note": "* Paches éspéchiales conformes.\n* Paches éspéchiales réstrintes.\n* Paches éspéchiales seulemint in muche (pétète des viuseries).", "specialpages-group-maintenance": "Rapports d'maintenanche", "specialpages-group-other": "Eutes paches éspéchiales", "specialpages-group-changes": "Darins canjemints pi gazètes", diff --git a/languages/i18n/qqq.json b/languages/i18n/qqq.json index d731322dda..5f72b75635 100644 --- a/languages/i18n/qqq.json +++ b/languages/i18n/qqq.json @@ -192,7 +192,8 @@ "Mazab IZW", "Mainframe98", "Pginer", - "Wladek92" + "Wladek92", + "Gombang" ] }, "sidebar": "{{notranslate}}", diff --git a/languages/i18n/ru.json b/languages/i18n/ru.json index 2de638c357..9a8f38214e 100644 --- a/languages/i18n/ru.json +++ b/languages/i18n/ru.json @@ -1139,11 +1139,11 @@ "yourvariant": "Вариант языка содержания:", "prefs-help-variant": "Предпочитаемый для отображения содержимого страниц вики вариант языка или орфография.", "yournick": "Новая подпись:", - "prefs-help-signature": "Комментарии на страницах обсуждений должны быть подписаны посредством добавления символов «~~~~», которые будут преобразованы в вашу подпись и время.", + "prefs-help-signature": "Комментарии на страницах обсуждений должны быть подписаны с помощью «~~~~», что будет преобразовано в вашу подпись и время.", "badsig": "Неверная подпись. Проверьте корректность HTML-тегов.", "badsiglength": "Слишком длинная подпись.\nПодпись не должна превышать $1 {{PLURAL:$1|символа|символа|символов}}.", "yourgender": "Какое описание подходит для вас больше всего?", - "gender-unknown": "При упоминании вас, программное обеспечение будет по возможности использовать гендерно-нейтральные слова", + "gender-unknown": "При упоминании вас программное обеспечение будет по возможности использовать гендерно-нейтральные слова", "gender-male": "Он редактирует страницы вики", "gender-female": "Онa редактирует страницы вики", "prefs-help-gender": "Этот параметр задавать необязательно.\nЗначение будет использовано для того, чтобы обращаться к вам и упоминать вас в правильном грамматическом роде.\nЭта информация будет общедоступной.", diff --git a/languages/i18n/sr-ec.json b/languages/i18n/sr-ec.json index 7b99cf1b57..522b76a6d0 100644 --- a/languages/i18n/sr-ec.json +++ b/languages/i18n/sr-ec.json @@ -64,7 +64,7 @@ "tog-shownumberswatching": "Прикажи број корисника који надгледају", "tog-oldsig": "Текући потпис:", "tog-fancysig": "Сматрај потпис као викитекст (без самоповезивања)", - "tog-uselivepreview": "Користи тренутни преглед", + "tog-uselivepreview": "Прикажи преглед без освежавања стране", "tog-forceeditsummary": "Упозори ме када не унесем опис измене", "tog-watchlisthideown": "Сакриј моје измене са списка надгледања", "tog-watchlisthidebots": "Сакриј измене ботова са списка надгледања", diff --git a/languages/i18n/sv.json b/languages/i18n/sv.json index 300a037cca..a1460eeee1 100644 --- a/languages/i18n/sv.json +++ b/languages/i18n/sv.json @@ -683,7 +683,7 @@ "anonpreviewwarning": "''Du är inte inloggad. Om du sparar kommer din IP-adress registreras på denna sidas redigeringshistorik.''", "missingsummary": "Påminnelse: Du har inte skrivit någon redigeringskommentar.\nOm du klickar på \"$1\" igen kommer din redigering att sparas utan en sådan.", "selfredirect": "Varning: Du omdirigerar denna sida till sig själv.\nDu kanske angav fel mål för din omdirigering, eller redigerar fel sida.\nOm du klickar på \"$1\" igen kommer omdirigeringen att skapas trots detta.", - "missingcommenttext": "Var god och skriv in en kommentar nedan.", + "missingcommenttext": "Var god och skriv en kommentar.", "missingcommentheader": "Påminnelse: Du har inte skrivit något ämne för den här kommentaren.\nOm du trycker på \"$1\" igen kommer din redigering sparas utan rubrik.", "summary-preview": "Förhandsgranskning av redigeringssammanfattning:", "subject-preview": "Förhandsgranskning av ämne:", @@ -1343,6 +1343,7 @@ "recentchanges-legend": "Alternativ för senaste ändringarna", "recentchanges-summary": "Följ de senaste ändringarna i wikin på denna sida.", "recentchanges-noresult": "Inga ändringar under den angivna perioden matchar dessa kriterier.", + "recentchanges-timeout": "Tidsgränsen för denna sökning har gått ut. Du kan prova andra sökparametrar.", "recentchanges-feed-description": "Följ de senaste ändringarna i wikin genom detta flöde", "recentchanges-label-newpage": "Denna redigering skapade en ny sida", "recentchanges-label-minor": "Detta är en mindre ändring", diff --git a/languages/i18n/tl.json b/languages/i18n/tl.json index cb2d2a788d..07c79e66f4 100644 --- a/languages/i18n/tl.json +++ b/languages/i18n/tl.json @@ -25,13 +25,13 @@ "LR Guanzon" ] }, - "tog-underline": "Pagsasalungguhit ng link:", - "tog-hideminor": "Itago ang mga maliliit na pagbabago mula sa mga huling binago", - "tog-hidepatrolled": "Ikubli ang napatrolyang mga pagbabagong nasa kamakailang mga pagbabago", - "tog-newpageshidepatrolled": "Itago ang napatrolyang mga pahina mula talaan ng bagong pahina", + "tog-underline": "Pagsasalungguhit ng kawing:", + "tog-hideminor": "Itago ang mga maliliit na pagbabago mula sa mga huling pagbabago", + "tog-hidepatrolled": "Itago ang mga napatrolyang pagbabago mula sa mga huling pagbabago", + "tog-newpageshidepatrolled": "Itago ang mga napatrolyang pahina mula talaan ng bagong pahina", "tog-hidecategorization": "Itago ang kategorisasyon ng mga pahina", - "tog-extendwatchlist": "Palawigin ang talaan ng mga binabantayan upang maipakita ang lahat ng mga pagbabago, hindi lamang ang pinakakamakailan lamang", - "tog-usenewrc": "Mga pagbabago ng pangkat ayon sa pahina sa kamakailang mga pagbabago at bantayan", + "tog-extendwatchlist": "Palawigin ang tala ng binabantayan upang maipakita ang lahat ng mga pagbabago, hindi lamang ang pinakahuling pagbabago", + "tog-usenewrc": "Ipangkat ang mga pagbabago ayon sa pahina sa mga huling pagbabago at tala ng binabantayan", "tog-numberheadings": "Automatikong bilangin ang mga pamagat", "tog-showtoolbar": "Ipakita ang ''toolbar'' ng pagbabago", "tog-editondblclick": "Magbago ng mga pahina sa dalawahang pagpindot", @@ -40,8 +40,8 @@ "tog-watchdefault": "Idagdag sa aking tala ng mga binabantayan ang mga pahina at mga talaksang binago ko", "tog-watchmoves": "Idagdag sa aking tala ng mga binabantayan ang mga pahina at mga talaksang inilipat ko", "tog-watchdeletion": "Idagdag sa aking tala ng mga binabantayan ang mga pahina at mga talaksang binura ko", - "tog-watchuploads": "Magdagdag ng mga bagong file sa aking mga sinusubaybayang listahan.", - "tog-watchrollback": "Magdagdag ng mga pahina kung saan ako nag-rollback sa aking bantayan", + "tog-watchuploads": "Idagdag sa aking tala ng mga binabantayan ang mga talaksang ikinarga kong pataas", + "tog-watchrollback": "Idagdag sa aking tala ng mga binabantayan ang mga pahinang aking iginulong pabalik", "tog-minordefault": "Markahan ang lahat ng pagbabago bilang maliit nang nakatakda", "tog-previewontop": "Ipakita ang paunang tingin bago ang kahon ng pagbabago", "tog-previewonfirst": "Ipakita ang paunang tingin sa unang pagbabago", @@ -53,12 +53,12 @@ "tog-oldsig": "Ang iyong umiiral na lagda:", "tog-fancysig": "Ituring ang lagda bilang teksto ng wiki (walang automatikong pagkawing)", "tog-uselivepreview": "Ipakita ang mga paunang tingin nang hindi kinakargang muli ang pahina", - "tog-forceeditsummary": "Pagsabihan ako kapag nagpapasok ng walang-lamang buod ng pagbabago", + "tog-forceeditsummary": "Sabihan ako kapag nagpapasok ng walang-lamang buod ng pagbabago", "tog-watchlisthideown": "Itago ang aking mga pagbabago mula sa tala ng mga binabantayan", "tog-watchlisthidebots": "Itago ang mga pagbabago ng mga bot mula sa tala ng mga binabantayan", "tog-watchlisthideminor": "Itago ang mga maliliit na pagbabago mula sa tala ng mga binabantayan", "tog-watchlisthideliu": "Itago ang mga pagbabago ng mga nakalagdang tagagamit mula sa tala ng mga binabantayan", - "tog-watchlistreloadautomatically": "I-karga muli ang bantayan ng awtomatiko kung kailan man nabago ang isang filter (kinakailangan ang JavaScript)", + "tog-watchlistreloadautomatically": "Ikarga muli ang bantayan ng awtomatiko kung kailan man nabago ang isang filter (kinakailangan ang JavaScript)", "tog-watchlistunwatchlinks": "Magdagdag ng direktang huwag panoorin/panoorin na kawing sa talaan ng mga pinapanood (Kailangan ang JavaScript para gumana)", "tog-watchlisthideanons": "Itago ang mga pagbabago ng hindi nakikilalang mga tagagamit mula sa tala ng mga binabantayan", "tog-watchlisthidepatrolled": "Itago ang napatrolyang mga pagbabago mula sa tala ng mga binabantayan", @@ -66,16 +66,16 @@ "tog-ccmeonemails": "Padalahan ako ng mga kopya ng mga ipinadala kong e-liham sa ibang mga tagagamit", "tog-diffonly": "Huwag ipakita ang nilalaman ng pahinang nasa ilalim ng mga pagkakaiba", "tog-showhiddencats": "Ipakita ang mga nakatagong kategorya", - "tog-norollbackdiff": "Alisin ang mga pagkakaiba pagkatapos isagawa ang pagpapagulong na pabalik sa dati", - "tog-useeditwarning": "Magbabala sa akin kapag umalis ako sa isang pahina ng pampatnugot na hindi pa nasasagip ang mga pagbabago", - "tog-prefershttps": "Laging gamitin ang isang walang panganib na koneksiyon kapag naka-login", + "tog-norollbackdiff": "Huwag ipakita ang pagkakaiba pagkatapos isagawa ang pagpapagulong pabalik", + "tog-useeditwarning": "Balaan ako kapag umalis ako sa isang pagbabagong pahinang mayroong hindi pa nasasagip na pagbabago", + "tog-prefershttps": "Palaging gumamit ng ligtas na koneksyon habang nakalagda", "underline-always": "Palagi", - "underline-never": "Hindi magpakailanman", - "underline-default": "Tinakda ng pambasa-basa o balat", - "editfont-style": "Baguhin ang estilong pantitik ng lugar:", - "editfont-monospace": "Estilo ng titik na isahan ang puwang", - "editfont-sansserif": "Estilo ng titik na walang gutli sa dulo", - "editfont-serif": "Estilo ng titik na may gutli sa dulo", + "underline-never": "Hindi kailanman", + "underline-default": "Balat o tinakda ng pambasa-basa", + "editfont-style": "Estilo ng titik ng lugar ng pagbabago:", + "editfont-monospace": "Isahang puwang", + "editfont-sansserif": "Walang gutli", + "editfont-serif": "May gutli", "sunday": "Linggo", "monday": "Lunes", "tuesday": "Martes", @@ -144,7 +144,7 @@ "category_header": "Mga pahina sa kategoryang \"$1\"", "subcategories": "Mga subkategorya", "category-media-header": "Mga midya sa kategoryang \"$1\"", - "category-empty": "''Kasalukuyang walang artikulo o midya ang kategoryang ito.''", + "category-empty": "Kasalukuyang walang artikulo o midya ang kategoryang ito.", "hidden-categories": "{{PLURAL:$1|Nakatagong kategorya|Mga nakatagong kategorya}}", "hidden-category-category": "Mga nakatagong kategorya", "category-subcat-count": "{{PLURAL:$2|Ang kategoryang ito ay mayroong sumusunod na subkategorya lamang.|Ang kategoryang ito ay mayroong sumusunod na {{PLURAL:$1|subkategorya|$1 subkategorya}}, mula sa kabuuan na $2.}}", @@ -160,16 +160,16 @@ "categoryviewer-pagedlinks": "($1) ($2)", "about": "Patungkol", "article": "Pahina ng nilalaman", - "newwindow": "(magbubukas sa bagong window)", + "newwindow": "(magbubukas sa bagong bintana)", "cancel": "Kanselahin", - "moredotdotdot": "Damihan pa...", + "moredotdotdot": "Marami pa...", "morenotlisted": "Maaring hindi kumpleto ang talang ito.", - "mypage": "Pahina ko", + "mypage": "Pahina", "mytalk": "Usapan", "anontalk": "Usapan", - "navigation": "Paglilibot (nabigasyon)", + "navigation": "Paglilibot", "and": ", at", - "faq": "Mga karaniwang itinatanong (''FAQ'')", + "faq": "Mga malilimit itanong", "actions": "Mga kilos", "namespaces": "Mga ngalan-espasyo", "variants": "Naiiba pa", @@ -188,7 +188,7 @@ "history_small": "kasaysayan", "updatedmarker": "isinapanahon mula noong huli kong pagdalaw", "printableversion": "Bersiyong maililimbag", - "permalink": "Palagiang link", + "permalink": "Permanenteng kawing", "print": "Ilimbag", "view": "Tingnan", "view-foreign": "Tingnan sa $1", @@ -199,11 +199,11 @@ "delete": "Burahin", "undelete_short": "Baligtarin ang pagbura ng {{PLURAL:$1|isang pagbabago|$1 pagbabago}}", "viewdeleted_short": "Tingnan ang {{PLURAL:$1|isang binurang pagbabago|$1 binurang pagbabago}}", - "protect": "Ipagsanggalang", + "protect": "Isanggalang", "protect_change": "baguhin", "unprotect": "Baguhin ang pagsasanggalang", "newpage": "Bagong pahina", - "talkpagelinktext": "Usapan", + "talkpagelinktext": "usapan", "specialpage": "Natatanging pahina", "personaltools": "Mga kagamitang pansarili", "talk": "Usapan", @@ -220,9 +220,9 @@ "viewtalkpage": "Tingnan ang usapan", "otherlanguages": "Sa ibang wika", "redirectedfrom": "(Nakaturo mula sa $1)", - "redirectpagesub": "Pahina ng pagkarga", + "redirectpagesub": "Pahinang panuro", "redirectto": "Papuntahin sa:", - "lastmodifiedat": "Huling binago ang pahinang ito noong $1, noong $2.", + "lastmodifiedat": "Huling binago ang pahinang ito noong $1 ng $2.", "viewcount": "Namataan ang pahinang ito nang {{PLURAL:$1|isang|$1}} beses.", "protectedpage": "Pahinang nakasanggalang", "jumpto": "Tumalon sa:", @@ -233,7 +233,7 @@ "pool-timeout": "Ang pagpapahinga ay naghihintay ng kandado", "pool-queuefull": "Puno na ang pisan ng mga pila", "pool-errorunknown": "Hindi nalalamang kamalian", - "pool-servererror": "Hindi magagamit ang serbisyo ng pool counter ($1).", + "pool-servererror": "Hindi magagamit ang serbisyo ng pambilang ng pisan ($1).", "poolcounter-usage-error": "Pagkakamali sa paggamit: $1", "aboutsite": "Tungkol sa {{SITENAME}}", "aboutpage": "Project:Patungkol", @@ -439,13 +439,17 @@ "createacct-realname": "Tunay na pangalan (maaaring wala)", "createacct-reason": "Dahilan", "createacct-reason-ph": "Bakit ka gagawa ng isa pang account?", + "createacct-reason-help": "Mensaheng ipinapakita sa listahan ng paggawa ng account", "createacct-submit": "Likhain ang iyong account", "createacct-another-submit": "Lumikha ng account", + "createacct-continue-submit": "Ituloy ang paggawa ng account", + "createacct-another-continue-submit": "Ituloy ang paggawa ng account", "createacct-benefit-heading": "{{SITENAME}} ay nilikha ng mga taong iyong katulad.", "createacct-benefit-body1": "{{PLURAL:$1|pagbabago|mga pagbabago}}", "createacct-benefit-body2": "{{PLURAL:$1|pahina|mga pahina}}", "createacct-benefit-body3": "{{PLURAL:$1|kamakailang taga-ambag|mga kamakailang taga-ambag}}", "badretype": "Hindi magkatugma ang ipinasok mong mga password.", + "usernameinprogress": "Ang paggawa ng account para sa pangalan ng tagagamit na ito ay nasa progreso na. Mangyaring maghintay.", "userexists": "May gumagamit na ng ipinasok na bansag.\nPumili po ng ibang pangalan.", "loginerror": "Kamalian sa paglagda", "createacct-error": "May pagkakamali sa paglikha ng account", @@ -454,6 +458,7 @@ "nocookieslogin": "Gumagamit ang {{SITENAME}} ng mga kuki (''cookies'') para mailagda ang mga tagagamit.\nHindi mo pinagagana ang mga kuki.\nPaki-andar mo ang mga ito at sumubok uli.", "nocookiesfornew": "Hindi nalikha ang account ng tagagamit, dahil hindi namin matiyak ang pinagmulan nito. \nTiyaking mayroon kang pinagaganang cookies, ikarga muli ang pahinang ito at subukan muli.", "nocookiesforlogin": "{{int:nocookieslogin}}", + "createacct-loginerror": "Matagumpay na nagawa ang account ngunit hindi ka mailagda ng awtomatiko. Mangyaring pumunta sa [[Special:UserLogin|manu-manong paglagda]].", "noname": "Hindi mo tinukoy ang isang tanggap na pangalan ng tagagamit.", "loginsuccesstitle": "Nailagda", "loginsuccess": "'''Nakalagda ka na sa {{SITENAME}} bilang si \"$1\".'''", @@ -464,6 +469,7 @@ "wrongpassword": "Mali ang ipinasok na password.\nPakisubok muli.", "wrongpasswordempty": "Walang laman ang ipinasok na password.\nPakisubok muli.", "passwordtooshort": "Ang mga password ay dapat mayroong {{PLURAL:$1|1 panitik|$1 panitik}} (karakter).", + "passwordtoolong": "Ang mga password ay hindi maaaring mas mahaba sa {{PLURAL:$1|1 panitik|$1 panitik}}.", "passwordtoopopular": "Hindi maaaring gamitin ang mga hudyat (''password'') na pangkaraniwang pinipili. Mangyaring pumili ng higit na natatanging hudyat.", "password-name-match": "Dapat magkaiba ang password mo sa bansag o username mo.", "password-login-forbidden": "Ipinagbabawal ang paggamit ng ganitong pangalan ng tagagamit at password.", @@ -491,11 +497,13 @@ "createaccount-text": "May lumikha ng account para sa iyong email address sa {{SITENAME}} ($4) na pinangalanang \"$2\", na may password na \"$3\".\nDapat kang mag-login at baguhin ang password mo ngayon.\n\nMaaari mong huwag pansinin ang mensaheng ito, kung mali ang paglikha ng account na ito.", "login-throttled": "Masyadong madami ang kamakailan lamang mong pagsubok sa pag-login.\nMaghintay po muna ng $1 bago subukan uli.", "login-abort-generic": "Nabigo ang iyong paglagda - Pinigil", + "login-migrated-generic": "Ang iyong account ay inilipat, at ang iyong pangalan ay hindi na umiiral sa wiking ito.", "loginlanguagelabel": "Wika: $1", "suspicious-userlogout": "Tinanggihan ang inyong kahilingang umalis sa pagkalagda dahil tila ito ay ipinadala ng sirang pambasa-basa o apoderadong pambaon (''caching proxy'')", "createacct-another-realname-tip": "Hindi kinakailangan ang tunay na pangalan.\nKung nais mo na ibigay ito, gagamitin ito para sa pagbibigay ng atribusyon para sa kanilang gawa.", "pt-login": "Mag-login", "pt-login-button": "Mag-login", + "pt-login-continue-button": "Magpatuloy sa paglagda", "pt-createaccount": "Lumikha ng account", "pt-userlogout": "Umalis sa pagkakatala", "php-mail-error-unknown": "Hindi malamang kamalian sa tungkulin ng liham ng PHP ()", @@ -511,6 +519,7 @@ "resetpass_submit": "Itakda ang password at mag-login", "changepassword-success": "Nabago ang iyong password!", "changepassword-throttled": "Masyadong madami ang kamakailan lamang mong pagsubok sa pag-login.\nMaghintay po muna ng $1 bago subukan uli.", + "botpasswords": "Mga password ng bot", "botpasswords-label-delete": "Burahin", "botpasswords-label-resetpassword": "Itakdang-muli/baguhin ang hudyat (password)", "botpasswords-label-grants-column": "Ipinagkaloob na", diff --git a/languages/i18n/tr.json b/languages/i18n/tr.json index 8564c553b9..9c737b5cff 100644 --- a/languages/i18n/tr.json +++ b/languages/i18n/tr.json @@ -2513,7 +2513,7 @@ "tooltip-pt-login": "Oturum açmanız tavsiye edilmektedir; ancak bu zorunlu değildir", "tooltip-pt-logout": "Sistemden çık", "tooltip-pt-createaccount": "Bir hesap oluşturup oturum açmanız tavsiye edilmektedir ancak bu zorunlu değildir", - "tooltip-ca-talk": "Kullanıcı mesaj sayfası", + "tooltip-ca-talk": "İçerik ile ilgili tartışma", "tooltip-ca-edit": "Bu sayfayı düzenleyin", "tooltip-ca-addsection": "Yeni bir altbaşlık aç", "tooltip-ca-viewsource": "Bu sayfa koruma altında. Sadece kaynağını görebilirsiniz.", diff --git a/languages/i18n/yo.json b/languages/i18n/yo.json index ebd66e02b1..e600939cf9 100644 --- a/languages/i18n/yo.json +++ b/languages/i18n/yo.json @@ -27,6 +27,7 @@ "tog-watchmoves": "Ṣ'àfikún àwọn ojúewé ati fáìlì tí mo yípò mọ́ ìmójútó mi", "tog-watchdeletion": "Ṣ'àfikún àwọn ojúewé àti fáìlì tí mo parẹ́ mọ́ ìmójútó mi", "tog-watchuploads": "Ìdàpọ̀ àwọn fáìlì tuntun sí ìmójútó mi", + "tog-watchrollback": "Ṣe àròpọ̀ àwọn ojúewé níbi tí mo ti ṣe ìdápadà pọ̀ mọ́ ìtòjọ àmójútó mi", "tog-minordefault": "Se àmì sí gbogbo àtúnse gẹ́gẹ́ bi kékeré lát'ìbẹ̀rẹ̀.", "tog-previewontop": "Se àyẹ̀wò kí ẹ tó s'àtúnṣe", "tog-previewonfirst": "S'àfihàn àgbéwò fún àtúnse àkọ́kọ́", @@ -37,20 +38,22 @@ "tog-shownumberswatching": "S'àfihàn iye àwọn oníṣe tí wọn tẹjú mọ́ọ", "tog-oldsig": "Ìtọwọ́bọ̀wé yín tówà lọ́wọ́:", "tog-fancysig": "Ṣe ìtọwọ́bọ̀wé bíi ìkọ wiki (láìní ìjápọ̀ fúnrararẹ̀)", - "tog-uselivepreview": "Ìlo àkọ́kọ́yẹ̀wò lẹ́ṣẹ̀kẹṣẹ̀ (àdánwò)", + "tog-uselivepreview": "Ìfihàn àwọn àkọ̀yẹ̀wò lái ṣe ìtúngbéjáde ojúewé náà", "tog-forceeditsummary": "Kìlọ̀ fún mi tí àkótán àtúnṣe bá jẹ́ òfo", "tog-watchlisthideown": "Ìbòmọ́lẹ̀ àwọn àtúnṣe mi nínú ìmójútó", "tog-watchlisthidebots": "Ìbòmọ́lẹ̀ àwọn àtúnṣe bot nínú ìmójútó", "tog-watchlisthideminor": "Ìbòmọ́lẹ̀ àwọn àtúnṣe kéékèké nínú ìmójútó", "tog-watchlisthideliu": "Ìbòmọ́lẹ̀ àwọn àtúnṣe àwọn oníṣe tó ti wọlé nínú ìmójútó", + "tog-watchlistreloadautomatically": "Ìtúngbéjáde ìtọ̀jọ àmójútó fúnrararẹ̀ nígbogbo tí ajọ̀ bá ti yípadà (JavaScript pọndandan)", "tog-watchlisthideanons": "Ìbòmọ́lẹ̀ àwọn àtúnṣe àwọn oníṣe aláìlórúkọ nínú ìmójútó", "tog-watchlisthidepatrolled": "Ìbòmọ́lẹ̀ àwọn àtúnṣe olùṣọ́ lọ́wọ́ ìmójútó", + "tog-watchlisthidecategorization": "Ìbòmọ́lẹ̀ ìṣeẹ̀ka àwọn ojúewé", "tog-ccmeonemails": "Ìfiránṣẹ́ sími àwọn àwòkọ àwọn e-mail tí mo firánṣẹ́ sí àwọn oníṣe míràn", "tog-diffonly": "Kò gbọdọ̀ ṣàfihàn àkóónú ojúewé lábẹ́ àwọn ìyàtọ̀", "tog-showhiddencats": "Ṣ'àfihàn àwọn ẹ̀ka pípamọ́", - "tog-norollbackdiff": "Fo ìyàtọ̀ lẹ́yín síṣe ìyísẹ́yìn", + "tog-norollbackdiff": "Mọ fi ìyàtọ̀ hàn lẹ́yín tí ìyísẹ́yìn bá parí", "tog-useeditwarning": "Kìlọ̀ fún mi tí mo bá únkúrò ní ojúewé àtúnṣe láì tíì mupamọ́", - "tog-prefershttps": "Lo ìjáwọlé oníàbò ní gbogbo ìgbà", + "tog-prefershttps": "Lo ìsomọ́ra tó ní àbò ní gbogbo ìgbà tí a bá forúkọ wọlé", "underline-always": "Nígbà gbogbo", "underline-never": "Rárá", "underline-default": "Ti àwọ tàbí ẹrọ́ ìtọ́kùn", @@ -142,7 +145,7 @@ "newwindow": "(yíò sí nínú fèrèsè tuntun)", "cancel": "Fagilé", "moredotdotdot": "Ẹ̀kúnrẹ́rẹ́...", - "morenotlisted": "Àtòjọ yìí kò kúnrẹ́rẹ́.", + "morenotlisted": "Ìtòjọ yìí le jẹ́pé kò kúnrẹ́rẹ́.", "mypage": "Ojúewé", "mytalk": "Ọ̀rọ̀", "anontalk": "Ọ̀rọ̀", @@ -211,6 +214,7 @@ "pool-timeout": "Ìsinmi ìgbàdíẹ̀ láti dúro de ìtìpadé", "pool-queuefull": "Oríìlà dátà ti kún", "pool-errorunknown": "Àsìṣe àwámárìdí", + "poolcounter-usage-error": "Àṣìṣe ìlò: $1", "aboutsite": "Nípa {{SITENAME}}", "aboutpage": "Project:Nípa", "copyright": "Gbogbo ohun inú ibí yìí wà lábẹ́ $1 àyàfi tí a bá sọ pé kò rí bẹ̀ẹ̀.", @@ -300,10 +304,13 @@ "readonly_lag": "Ibùdó dátà ti jẹ́ títìpa fúnrararẹ̀ kí àwọn ẹ̀rọ awọ̀fà ẹrú ibùdó dátà le baà yára bíi ti àwọn ẹ̀rọ awọ̀fà ọ̀gà.", "internalerror": "Àsìṣe inú", "internalerror_info": "Àsìṣe inú: $1", + "internalerror-fatal-exception": "Ìṣàtì tí kò ṣe é túnṣe irú \"$1\"", "filecopyerror": "Àwòkọ faili \"$1\" sí \"$2\" kò ṣe é ṣe.", "filerenameerror": "Àtúnsọlórúkọ fáìlì \"$1\" sí \"$2\" kò ṣe é ṣe.", "filedeleteerror": "Ìparẹ́ fáìlì \"$1\" kò ṣe é ṣe.", "directorycreateerror": "Kò le dá àpò \"$1\".", + "directoryreadonlyerror": "Àpò fáìlì \"$1\" jẹ́ àwòkà nìkan.", + "directorynotreadableerror": "Àpò fáìlì \"$1\" kò ṣe é wòkà.", "filenotfound": "Kò sí fáìlì \"$1\".", "unexpected": "Iye àìretí: \"$1\"=\"$2\".", "formerror": "Àsìṣe: fọ́ọ̀mù kò ṣe fi ránṣẹ́", @@ -861,6 +868,7 @@ "youremail": "E-mail:", "username": "{{GENDER:$1|Orúkọ oníṣe}}:", "prefs-memberingroups": "{{GENDER:$2|Ọ̀kan}} nínú {{PLURAL:$1|ẹgbẹ́|àwọn ẹgbẹ́}}:", + "group-membership-link-with-expiry": "$1 (títí di $2)", "prefs-registration": "Àsìkò ìforúkọsílẹ́:", "yourrealname": "Orúkọ ganangan:", "yourlanguage": "Èdè:", @@ -895,21 +903,26 @@ "prefs-displayrc": "Ìfihàn àwọn àṣàyàn", "prefs-displaywatchlist": "Ìfihàn àwọn àṣàyàn", "prefs-diffs": "Àwọn ìyàtọ̀", - "userrights": "Ìmójútó àwọn ẹ̀tọ́ oníṣe", - "userrights-lookup-user": "Àkóso àwọn àdìpò oníṣe", + "userrights": "Àwọn ẹ̀tọ́ oníṣe", + "userrights-lookup-user": "Mú oníṣe kan", "userrights-user-editname": "Ẹ tẹ orúkọ oníṣe kan:", - "editusergroup": "Àtúnṣe àwọn ẹgbẹ́ oníṣe", - "editinguser": "Ṣíṣàyípadà àwọn ẹ̀tọ́ oníṣe fún oníṣe '''[[User:$1|$1]]''' $2", - "userrights-editusergroup": "Àtúnṣe àwọn ẹgbẹ́ oníṣe", - "saveusergroups": "Ìmúpamọ́ àwọn ẹgbẹ́ oníṣe", + "editusergroup": "Ìgbéjáde àwọn ẹgbẹ́ oníṣe", + "editinguser": "Àyípadà àwọn ẹ̀tọ́ oníṣe fún {{GENDER:$1|oníṣe}} [[User:$1|$1]] $2", + "viewinguserrights": "Àgbéwò àwọn ẹ̀tọ́ oníṣe fún {{GENDER:$1|oníṣe}} [[User:$1|$1]] $2", + "userrights-editusergroup": "Àtúnṣe àwọn ẹgbẹ́ {{GENDER:$1|oníṣe}}", + "userrights-viewusergroup": "Àgbéwò àwọn ẹgbẹ́ {{GENDER:$1|oníṣe}}", + "saveusergroups": "Ìmúpamọ́ àwọn ẹgbẹ́ {{GENDER:$1|oníṣe}}", "userrights-groupsmember": "Ọ̀kan nínú:", "userrights-groupsmember-auto": "Ẹlẹgbẹ́ tódájú:", - "userrights-groups-help": "Ẹ le ṣàyípadà àwọn ẹgbẹ́ tí oníṣe wà nínú wọn:\n* Àpótí aṣàmìsí túmọ̀sí pé oníṣe náà wà nínú ẹgbẹ́ náà.\n* Àpótí aláìsàmìsí túmọ̀sí pé oníṣe náà kò sí nínú ẹgbẹ́ náà\n* Àmì * kan fihàn pé ẹ kò le yọ ẹgbẹ́ náà kúrò mọ́ tí ẹ bá ti ṣàfikún rẹ̀, tàbí lódì kejì.", + "userrights-groups-help": "Ẹ le ṣàyípadà àwọn ẹgbẹ́ tí oníṣe yìí wà nínú:\n* Àpótí aṣàmìsí túmọ̀sí pé oníṣe náà wà nínú ẹgbẹ́ náà.\n* Àpótí aláìsàmìsí túmọ̀sí pé oníṣe náà kò sí nínú ẹgbẹ́ náà\n* Àmì * kan fihàn pé ẹ kò le yọ ẹgbẹ́ náà kúrò mọ́ tí ẹ bá ti ṣàfikún rẹ̀, tàbí lódì kejì.\n* Àmí # kan fihàn pé ẹ kàn lè fa àsìkò ìparí ọmọẹgbẹ́ ẹgbẹ́ yìí sẹ́yin nìkan; ẹ kò le fàá síwájú.", "userrights-reason": "Ìdíẹ̀:", "userrights-no-interwiki": "Ẹ kò ní ìyọ̀nda láti ṣàtúnṣe àwọn ẹ̀tọ́ oníṣe lórí àwọn wiki míràn.", "userrights-nodatabase": "Ibùdó dátà $1 kò sí tàbí kò sí lábẹ́lé.", "userrights-changeable-col": "Àwọn ẹgbẹ́ tí ẹ le túnṣe", "userrights-unchangeable-col": "Àwọn ẹgbẹ́ tí ẹ kò le túnṣe", + "userrights-expiry-current": "Yíòparí $1", + "userrights-expiry-none": "Kò ní parí", + "userrights-expiry": "Ìparí:", "group": "Ìdìpọ̀:", "group-user": "Àwọn oníṣe", "group-autoconfirmed": "Àwọn oníṣe aláàmúdájúarawọn", @@ -1039,6 +1052,34 @@ "recentchanges-label-plusminus": "Iye bytes àtúnṣe sí ìtóbi ojúewé", "recentchanges-legend-heading": "Ìtumọ̀:", "recentchanges-legend-newpage": "{{int:recentchanges-label-newpage}} (ẹ tún wo [[Special:NewPages|àtòjọ àwọn ojúewé tuntun]])", + "recentchanges-submit": "Ìfihàn", + "rcfilters-tag-remove": "Ìyọkúrò $1", + "rcfilters-legend-heading": "Ìtòjọ àwọn ìkékúrú:", + "rcfilters-other-review-tools": "Àwọn irinṣẹ́ àtúnyẹ̀wò míràn", + "rcfilters-group-results-by-page": "Ìdìpọ̀ àwọn èsì gẹ́gẹ́bí ojúewé", + "rcfilters-grouping-title": "Àdìpọ̀", + "rcfilters-activefilters": "Àwọn ajọ̀ àsiṣẹ́", + "rcfilters-advancedfilters": "Àwọn ajọ̀ onígíga", + "rcfilters-limit-title": "Àwọn àtúnṣe tí yíò hàn", + "rcfilters-limit-shownum": "Ìfihàn {{PLURAL:$1|àtúnṣe|àtúnṣe $1}} sẹ́yìn", + "rcfilters-days-title": "Àwọn ọjọ́ ṣẹ̀ṣẹ̀", + "rcfilters-hours-title": "Àwọn wákàtí ṣẹ̀ṣẹ̀", + "rcfilters-days-show-days": "{{PLURAL:$1|ọjọ́|ọjọ́}} $1", + "rcfilters-days-show-hours": "{{PLURAL:$1|wákàtí|wákàtí}} $1", + "rcfilters-highlighted-filters-list": "Aláfíṣeàkíyèsí: $1", + "rcfilters-quickfilters": "Àwọn ajọ̀ ìpamọ́", + "rcfilters-quickfilters-placeholder-title": "Kò tí ì sí ajọ ní ìpamọ́", + "rcfilters-quickfilters-placeholder-description": "Láti fi àwọn ìtò ajọ̀ yín pamọ́ láti le lò wọ́n nígbà míràn, ẹ tẹ klik sí àwòrán àmì-ìkàwé nínú àyè Ajọ̀ Àsiṣẹ́, nísàlẹ̀.", + "rcfilters-savedqueries-defaultlabel": "Àwọn ajọ̀ ìpamọ́", + "rcfilters-savedqueries-rename": "Ìtúnsọlórúkọ", + "rcfilters-savedqueries-setdefault": "Ìtò bí i ìbẹ̀rẹ̀", + "rcfilters-savedqueries-unsetdefault": "Ìyọkúrò bí i ìbẹ̀rẹ̀", + "rcfilters-savedqueries-remove": "Ìyọkúrò", + "rcfilters-savedqueries-new-name-label": "Orúkọ", + "rcfilters-savedqueries-new-name-placeholder": "Àlàyé iṣẹ́ ajọ̀ náà", + "rcfilters-savedqueries-apply-label": "Ìdáálẹ̀ ajọ̀", + "rcfilters-savedqueries-apply-and-setdefault-label": "Ìdáálẹ̀ ajọ̀ ìbẹ̀rẹ̀", + "rcfilters-savedqueries-cancel-label": "Fagilé", "rcnotefrom": "Àwọn àtúnṣe láti ''''$2''' (títí dé '''$1''' hàn) lábẹ́.", "rclistfrom": "Àfihàn àwọn àtúnṣe tuntun nípa bíbẹ̀rẹ̀ láti $3 $2", "rcshowhideminor": "$1 àwọn àtúnṣe kékéèké", diff --git a/languages/i18n/zh-hant.json b/languages/i18n/zh-hant.json index 564c932798..58b388c2ce 100644 --- a/languages/i18n/zh-hant.json +++ b/languages/i18n/zh-hant.json @@ -1921,7 +1921,7 @@ "prefixindex": "按詞頭查詢頁面", "prefixindex-namespace": "按詞頭查詢頁面 ($1 命名空間)", "prefixindex-submit": "顯示", - "prefixindex-strip": "於清單中省略詞首", + "prefixindex-strip": "於清單中省略詞頭", "shortpages": "過短的頁面", "longpages": "過長的頁面", "deadendpages": "無連結頁面", @@ -2044,9 +2044,9 @@ "allpagesfrom": "顯示頁面開始於:", "allpagesto": "顯示頁面結束於:", "allarticles": "所有頁面", - "allinnamespace": "所有頁面 ($1 命名空間)", + "allinnamespace": "所有頁面($1 命名空間)", "allpagessubmit": "執行", - "allpagesprefix": "根據詞首查詢頁面", + "allpagesprefix": "根據詞頭查詢頁面", "allpagesbadtitle": "指定的頁面標題無效、包含內部語言或內部 Wiki 的字首。\n它可能包含一個或多個的不能用於標題的字元。", "allpages-bad-ns": "{{SITENAME}} 沒有 \"$1\" 命名空間。", "allpages-hide-redirects": "隱藏重新導向頁面", diff --git a/maintenance/checkImages.php b/maintenance/checkImages.php index 2df0a0954c..c2f0b2713b 100644 --- a/maintenance/checkImages.php +++ b/maintenance/checkImages.php @@ -43,10 +43,11 @@ class CheckImages extends Maintenance { $numGood = 0; $repo = RepoGroup::singleton()->getLocalRepo(); + $fileQuery = LocalFile::getQueryInfo(); do { - $res = $dbr->select( 'image', LocalFile::selectFields(), + $res = $dbr->select( $fileQuery['tables'], $fileQuery['fields'], [ 'img_name > ' . $dbr->addQuotes( $start ) ], - __METHOD__, [ 'LIMIT' => $this->mBatchSize ] ); + __METHOD__, [ 'LIMIT' => $this->mBatchSize ], $fileQuery['joins'] ); foreach ( $res as $row ) { $numImages++; $start = $row->img_name; diff --git a/maintenance/cleanupBlocks.php b/maintenance/cleanupBlocks.php index f489333f8f..37417c73d1 100644 --- a/maintenance/cleanupBlocks.php +++ b/maintenance/cleanupBlocks.php @@ -39,6 +39,7 @@ class CleanupBlocks extends Maintenance { public function execute() { $db = $this->getDB( DB_MASTER ); + $blockQuery = Block::getQueryInfo(); $max = $db->selectField( 'ipblocks', 'MAX(ipb_user)' ); @@ -65,11 +66,14 @@ class CleanupBlocks extends Maintenance { foreach ( $res as $row ) { $bestBlock = null; $res2 = $db->select( - 'ipblocks', - Block::selectFields(), + $blockQuery['tables'], + $blockQuery['fields'], [ 'ipb_user' => $row->ipb_user, - ] + ], + __METHOD__, + [], + $blockQuery['joins'] ); foreach ( $res2 as $row2 ) { $block = Block::newFromRow( $row2 ); diff --git a/maintenance/eraseArchivedFile.php b/maintenance/eraseArchivedFile.php index 05fbbbcb49..d94d49b72b 100644 --- a/maintenance/eraseArchivedFile.php +++ b/maintenance/eraseArchivedFile.php @@ -55,9 +55,10 @@ class EraseArchivedFile extends Maintenance { $afile = false; } else { // specified version $dbw = $this->getDB( DB_MASTER ); - $row = $dbw->selectRow( 'filearchive', ArchivedFile::selectFields(), + $fileQuery = ArchivedFile::getQueryInfo(); + $row = $dbw->selectRow( $fileQuery['tables'], $fileQuery['fields'], [ 'fa_storage_group' => 'deleted', 'fa_storage_key' => $filekey ], - __METHOD__ ); + __METHOD__, [], $fileQuery['joins'] ); if ( !$row ) { $this->error( "No deleted file exists with key '$filekey'.", 1 ); } @@ -85,9 +86,10 @@ class EraseArchivedFile extends Maintenance { protected function scrubAllVersions( $name ) { $dbw = $this->getDB( DB_MASTER ); - $res = $dbw->select( 'filearchive', ArchivedFile::selectFields(), + $fileQuery = ArchivedFile::getQueryInfo(); + $res = $dbw->select( $fileQuery['tables'], $fileQuery['fields'], [ 'fa_name' => $name, 'fa_storage_group' => 'deleted' ], - __METHOD__ ); + __METHOD__, [], $fileQuery['joins'] ); foreach ( $res as $row ) { $this->scrubVersion( ArchivedFile::newFromRow( $row ) ); } diff --git a/maintenance/populateRevisionLength.php b/maintenance/populateRevisionLength.php index a9457c2a1c..0cb14c42c8 100644 --- a/maintenance/populateRevisionLength.php +++ b/maintenance/populateRevisionLength.php @@ -54,10 +54,10 @@ class PopulateRevisionLength extends LoggedUpdateMaintenance { } $this->output( "Populating rev_len column\n" ); - $rev = $this->doLenUpdates( 'revision', 'rev_id', 'rev', Revision::selectFields() ); + $rev = $this->doLenUpdates( 'revision', 'rev_id', 'rev', Revision::getQueryInfo() ); $this->output( "Populating ar_len column\n" ); - $ar = $this->doLenUpdates( 'archive', 'ar_id', 'ar', Revision::selectArchiveFields() ); + $ar = $this->doLenUpdates( 'archive', 'ar_id', 'ar', Revision::getArchiveQueryInfo() ); $this->output( "rev_len and ar_len population complete " . "[$rev revision rows, $ar archive rows].\n" ); @@ -69,10 +69,10 @@ class PopulateRevisionLength extends LoggedUpdateMaintenance { * @param string $table * @param string $idCol * @param string $prefix - * @param array $fields + * @param array $queryInfo * @return int */ - protected function doLenUpdates( $table, $idCol, $prefix, $fields ) { + protected function doLenUpdates( $table, $idCol, $prefix, $queryInfo ) { $dbr = $this->getDB( DB_REPLICA ); $dbw = $this->getDB( DB_MASTER ); $start = $dbw->selectField( $table, "MIN($idCol)", false, __METHOD__ ); @@ -91,14 +91,16 @@ class PopulateRevisionLength extends LoggedUpdateMaintenance { while ( $blockStart <= $end ) { $this->output( "...doing $idCol from $blockStart to $blockEnd\n" ); $res = $dbr->select( - $table, - $fields, + $queryInfo['tables'], + $queryInfo['fields'], [ "$idCol >= $blockStart", "$idCol <= $blockEnd", "{$prefix}_len IS NULL" ], - __METHOD__ + __METHOD__, + [], + $queryInfo['joins'] ); if ( $res->numRows() > 0 ) { diff --git a/maintenance/populateRevisionSha1.php b/maintenance/populateRevisionSha1.php index c06f1e85df..f96c2eca36 100644 --- a/maintenance/populateRevisionSha1.php +++ b/maintenance/populateRevisionSha1.php @@ -55,10 +55,10 @@ class PopulateRevisionSha1 extends LoggedUpdateMaintenance { } $this->output( "Populating rev_sha1 column\n" ); - $rc = $this->doSha1Updates( 'revision', 'rev_id', Revision::selectFields(), 'rev' ); + $rc = $this->doSha1Updates( 'revision', 'rev_id', Revision::getQueryInfo(), 'rev' ); $this->output( "Populating ar_sha1 column\n" ); - $ac = $this->doSha1Updates( 'archive', 'ar_rev_id', Revision::selectArchiveFields(), 'ar' ); + $ac = $this->doSha1Updates( 'archive', 'ar_rev_id', Revision::getArchiveQueryInfo(), 'ar' ); $this->output( "Populating ar_sha1 column legacy rows\n" ); $ac += $this->doSha1LegacyUpdates(); @@ -71,10 +71,11 @@ class PopulateRevisionSha1 extends LoggedUpdateMaintenance { /** * @param string $table * @param string $idCol + * @param array $queryInfo * @param string $prefix * @return int Rows changed */ - protected function doSha1Updates( $table, $idCol, $fields, $prefix ) { + protected function doSha1Updates( $table, $idCol, $queryInfo, $prefix ) { $db = $this->getDB( DB_MASTER ); $start = $db->selectField( $table, "MIN($idCol)", false, __METHOD__ ); $end = $db->selectField( $table, "MAX($idCol)", false, __METHOD__ ); @@ -93,7 +94,9 @@ class PopulateRevisionSha1 extends LoggedUpdateMaintenance { $this->output( "...doing $idCol from $blockStart to $blockEnd\n" ); $cond = "$idCol BETWEEN $blockStart AND $blockEnd AND $idCol IS NOT NULL AND {$prefix}_sha1 = ''"; - $res = $db->select( $table, $fields, $cond, __METHOD__ ); + $res = $db->select( + $queryInfo['tables'], $queryInfo['fields'], $cond, __METHOD__, [], $queryInfo['joins'] + ); $this->beginTransaction( $db, __METHOD__ ); foreach ( $res as $row ) { @@ -117,8 +120,9 @@ class PopulateRevisionSha1 extends LoggedUpdateMaintenance { protected function doSha1LegacyUpdates() { $count = 0; $db = $this->getDB( DB_MASTER ); - $res = $db->select( 'archive', Revision::selectArchiveFields(), - [ 'ar_rev_id IS NULL', 'ar_sha1' => '' ], __METHOD__ ); + $arQuery = Revision::getArchiveQueryInfo(); + $res = $db->select( $arQuery['tables'], $arQuery['fields'], + [ 'ar_rev_id IS NULL', 'ar_sha1' => '' ], __METHOD__, [], $arQuery['joins'] ); $updateSize = 0; $this->beginTransaction( $db, __METHOD__ ); diff --git a/maintenance/rebuildImages.php b/maintenance/rebuildImages.php index a8fb9a3bd0..8fceedb28c 100644 --- a/maintenance/rebuildImages.php +++ b/maintenance/rebuildImages.php @@ -125,12 +125,14 @@ class ImageBuilder extends Maintenance { flush(); } - function buildTable( $table, $key, $fields, $callback ) { + function buildTable( $table, $key, $queryInfo, $callback ) { $count = $this->dbw->selectField( $table, 'count(*)', '', __METHOD__ ); $this->init( $count, $table ); $this->output( "Processing $table...\n" ); - $result = $this->getDB( DB_REPLICA )->select( $table, $fields, [], __METHOD__ ); + $result = $this->getDB( DB_REPLICA )->select( + $queryInfo['tables'], $queryInfo['fields'], [], __METHOD__, [], $queryInfo['joins'] + ); foreach ( $result as $row ) { $update = call_user_func( $callback, $row, null ); @@ -145,7 +147,7 @@ class ImageBuilder extends Maintenance { function buildImage() { $callback = [ $this, 'imageCallback' ]; - $this->buildTable( 'image', 'img_name', LocalFile::selectFields(), $callback ); + $this->buildTable( 'image', 'img_name', LocalFile::getQueryInfo(), $callback ); } function imageCallback( $row, $copy ) { @@ -157,7 +159,7 @@ class ImageBuilder extends Maintenance { } function buildOldImage() { - $this->buildTable( 'oldimage', 'oi_archive_name', OldLocalFile::selectFields(), + $this->buildTable( 'oldimage', 'oi_archive_name', OldLocalFile::getQueryInfo(), [ $this, 'oldimageCallback' ] ); } diff --git a/maintenance/rebuildtextindex.php b/maintenance/rebuildtextindex.php index c786925440..5971d5e9f7 100644 --- a/maintenance/rebuildtextindex.php +++ b/maintenance/rebuildtextindex.php @@ -93,11 +93,7 @@ class RebuildTextIndex extends Maintenance { $this->output( "Rebuilding index fields for {$count} pages...\n" ); $n = 0; - $fields = array_merge( - Revision::selectPageFields(), - Revision::selectFields(), - Revision::selectTextFields() - ); + $revQuery = Revision::getQueryInfo( [ 'page', 'text' ] ); while ( $n < $count ) { if ( $n ) { @@ -105,7 +101,7 @@ class RebuildTextIndex extends Maintenance { } $end = $n + self::RTI_CHUNK_SIZE - 1; - $res = $this->db->select( [ 'page', 'revision', 'text' ], $fields, + $res = $this->db->select( $revQuery['tables'], $revQuery['fields'], [ "page_id BETWEEN $n AND $end", 'page_latest = rev_id', 'rev_text_id = old_id' ], __METHOD__ ); diff --git a/maintenance/refreshFileHeaders.php b/maintenance/refreshFileHeaders.php index 16702350f6..e123de7fdb 100644 --- a/maintenance/refreshFileHeaders.php +++ b/maintenance/refreshFileHeaders.php @@ -57,6 +57,8 @@ class RefreshFileHeaders extends Maintenance { $count = 0; $dbr = $this->getDB( DB_REPLICA ); + $fileQuery = LocalFile::getQueryInfo(); + do { $conds = [ "img_name > {$dbr->addQuotes( $start )}" ]; @@ -76,8 +78,9 @@ class RefreshFileHeaders extends Maintenance { $conds[] = "img_minor_mime = {$dbr->addQuotes( $minor_mime )}"; } - $res = $dbr->select( 'image', LocalFile::selectFields(), $conds, - __METHOD__, [ 'LIMIT' => $this->mBatchSize, 'ORDER BY' => 'img_name ASC' ] ); + $res = $dbr->select( $fileQuery['tables'], $fileQuery['fields'], $conds, + __METHOD__, [ 'LIMIT' => $this->mBatchSize, 'ORDER BY' => 'img_name ASC' ], $fileQuery['joins'] + ); if ( $res->numRows() > 0 ) { $row1 = $res->current(); diff --git a/maintenance/refreshImageMetadata.php b/maintenance/refreshImageMetadata.php index 41da6b46e4..b7f03d9bb6 100644 --- a/maintenance/refreshImageMetadata.php +++ b/maintenance/refreshImageMetadata.php @@ -124,13 +124,16 @@ class RefreshImageMetadata extends Maintenance { 'ORDER BY' => 'img_name ASC', ]; + $fileQuery = LocalFile::getQueryInfo(); + do { $res = $dbw->select( - 'image', - LocalFile::selectFields(), + $fileQuery['tables'], + $fileQuery['fields'], array_merge( $conds, $conds2 ), __METHOD__, - $options + $options, + $fileQuery['joins'] ); if ( $res->numRows() > 0 ) { diff --git a/maintenance/storage/testCompression.php b/maintenance/storage/testCompression.php index deb2ca60d5..028f11cc6d 100644 --- a/maintenance/storage/testCompression.php +++ b/maintenance/storage/testCompression.php @@ -48,20 +48,18 @@ if ( isset( $options['limit'] ) ) { $type = isset( $options['type'] ) ? $options['type'] : 'ConcatenatedGzipHistoryBlob'; $dbr = $this->getDB( DB_REPLICA ); +$revQuery = Revision::getQueryInfo( [ 'page', 'text' ] ); $res = $dbr->select( - [ 'page', 'revision', 'text' ], - array_merge( - Revision::selectFields(), - Revision::selectPageFields(), - Revision::selectTextFields() - ), + $revQuery['tables'], + $revQuery['fields'], [ 'page_namespace' => $title->getNamespace(), 'page_title' => $title->getDBkey(), - 'page_id=rev_page', 'rev_timestamp > ' . $dbr->addQuotes( $dbr->timestamp( $start ) ), - 'rev_text_id=old_id' - ], __FILE__, [ 'LIMIT' => $limit ] + ], + __FILE__, + [ 'LIMIT' => $limit ], + $revQuery['joins'] ); $blob = new $type; diff --git a/package.json b/package.json index c30e150257..faca87da19 100644 --- a/package.json +++ b/package.json @@ -8,26 +8,26 @@ }, "devDependencies": { "deepmerge": "1.3.2", - "eslint": "3.12.2", + "eslint": "4.9.0", "eslint-config-wikimedia": "0.5.0", "grunt": "1.0.1", "grunt-banana-checker": "0.6.0", "grunt-contrib-copy": "1.0.0", "grunt-contrib-watch": "1.0.0", - "grunt-eslint": "20.0.0", + "grunt-eslint": "20.1.0", "grunt-jsonlint": "1.1.0", "grunt-karma": "2.0.0", - "grunt-stylelint": "0.8.0", + "grunt-stylelint": "0.9.0", "grunt-webdriver": "2.0.3", - "karma": "1.5.0", - "karma-chrome-launcher": "2.0.0", + "karma": "1.7.1", + "karma-chrome-launcher": "2.2.0", "karma-firefox-launcher": "1.0.1", - "karma-mocha-reporter": "2.2.3", + "karma-mocha-reporter": "2.2.5", "karma-qunit": "1.2.1", - "nodemw": "0.10.1", - "qunitjs": "2.4.0", - "stylelint": "7.8.0", - "stylelint-config-wikimedia": "0.4.1", + "nodemw": "0.11.0", + "qunitjs": "2.4.1", + "stylelint": "8.2.0", + "stylelint-config-wikimedia": "0.4.2", "wdio-junit-reporter": "0.2.0", "wdio-mocha-framework": "0.5.8", "wdio-sauce-service": "^0.3.1", diff --git a/resources/Resources.php b/resources/Resources.php index b9986fec57..1a2d707f22 100644 --- a/resources/Resources.php +++ b/resources/Resources.php @@ -360,7 +360,7 @@ return [ /* jQuery UI */ 'jquery.ui.core' => [ - 'deprecated' => 'Please use "mediawiki.ui.button" or "oojs-ui" instead.', + 'deprecated' => 'Please use OOUI instead.', 'scripts' => 'resources/lib/jquery.ui/jquery.ui.core.js', 'dependencies' => [ 'jquery.ui.core.styles', @@ -2311,6 +2311,7 @@ return [ /* MediaWiki UI */ 'mediawiki.ui' => [ + 'deprecated' => 'Please use OOUI instead.', 'skinStyles' => [ 'default' => [ 'resources/src/mediawiki.ui/default.less', diff --git a/resources/src/mediawiki.action/mediawiki.action.history.css b/resources/src/mediawiki.action/mediawiki.action.history.css index f3ea1639eb..520917a40c 100644 --- a/resources/src/mediawiki.action/mediawiki.action.history.css +++ b/resources/src/mediawiki.action/mediawiki.action.history.css @@ -1,6 +1,6 @@ /* Styles for the JavaScript enhancements of the history page */ -#pagehistory li.before input[name='oldid'], -#pagehistory li.after input[name='diff'] { +#pagehistory li.before input[ name='oldid' ], +#pagehistory li.after input[ name='diff' ] { visibility: hidden; } diff --git a/resources/src/mediawiki.legacy/commonPrint.css b/resources/src/mediawiki.legacy/commonPrint.css index 8ff0634207..6931c7d724 100644 --- a/resources/src/mediawiki.legacy/commonPrint.css +++ b/resources/src/mediawiki.legacy/commonPrint.css @@ -77,8 +77,8 @@ a.stub { } /* Expand protocol-relative URLs for printing */ -.mw-body-content a.external.text[href^='//']:after, -.mw-body-content a.external.autonumber[href^='//']:after { +.mw-body-content a.external.text[ href^='//' ]:after, +.mw-body-content a.external.autonumber[ href^='//' ]:after { content: ' (https:' attr( href ) ')'; } diff --git a/resources/src/mediawiki.legacy/shared.css b/resources/src/mediawiki.legacy/shared.css index 74233d6375..ecdfb6161d 100644 --- a/resources/src/mediawiki.legacy/shared.css +++ b/resources/src/mediawiki.legacy/shared.css @@ -56,36 +56,36 @@ wbr { /* Input types that should follow user direction, like buttons */ /* TODO: What about buttons in wikipage content ? */ -input[type='submit'], -input[type='button'], -input[type='reset'], -input[type='file'] { +input[ type='submit' ], +input[ type='button' ], +input[ type='reset' ], +input[ type='file' ] { direction: ltr; } /* Override default values */ -textarea[dir='ltr'], -input[dir='ltr'] { +textarea[ dir='ltr' ], +input[ dir='ltr' ] { /* @noflip */ direction: ltr; } -textarea[dir='rtl'], -input[dir='rtl'] { +textarea[ dir='rtl' ], +input[ dir='rtl' ] { /* @noflip */ direction: rtl; } /* Default style for semantic tags */ -abbr[title], -.explain[title] { +abbr[ title ], +.explain[ title ] { border-bottom: 1px dotted; cursor: help; } @supports ( text-decoration: underline dotted ) { - abbr[title], - .explain[title] { + abbr[ title ], + .explain[ title ] { border-bottom: 0; text-decoration: underline dotted; } diff --git a/resources/src/mediawiki.less/mediawiki.ui/mixins.less b/resources/src/mediawiki.less/mediawiki.ui/mixins.less index 505aa61012..1e078bd6f2 100644 --- a/resources/src/mediawiki.less/mediawiki.ui/mixins.less +++ b/resources/src/mediawiki.less/mediawiki.ui/mixins.less @@ -17,8 +17,8 @@ line-height: normal; font-weight: normal; - & > input[type='checkbox'], - & > input[type='radio'] { + & > input[ type='checkbox' ], + & > input[ type='radio' ] { width: auto; height: auto; margin: 0 0.1em 0 0; diff --git a/resources/src/mediawiki.rcfilters/styles/mw.rcfilters.mixins.less b/resources/src/mediawiki.rcfilters/styles/mw.rcfilters.mixins.less index f3d81b7638..790e01584e 100644 --- a/resources/src/mediawiki.rcfilters/styles/mw.rcfilters.mixins.less +++ b/resources/src/mediawiki.rcfilters/styles/mw.rcfilters.mixins.less @@ -55,9 +55,9 @@ // work if the rules are inside the above widget LESS scope .highlight-changesListWrapperWidget( @bgcolor ) { .mw-rcfilters-ui-changesListWrapperWidget li&, - .mw-rcfilters-ui-changesListWrapperWidget & tr:first-child, - .mw-rcfilters-ui-changesListWrapperWidget tr&.mw-rcfilters-ui-changesListWrapperWidget-enhanced-toplevel:not(.mw-rcfilters-ui-changesListWrapperWidget-enhanced-grey) td:not( :nth-child( -n+2 ) ), - .mw-rcfilters-ui-changesListWrapperWidget tr&.mw-rcfilters-ui-changesListWrapperWidget-enhanced-nested:not(.mw-rcfilters-ui-changesListWrapperWidget-enhanced-grey) td:not( :nth-child( -n+4 ) ) { + .mw-rcfilters-ui-changesListWrapperWidget & tr:first-child, + .mw-rcfilters-ui-changesListWrapperWidget tr&.mw-rcfilters-ui-changesListWrapperWidget-enhanced-toplevel:not( .mw-rcfilters-ui-changesListWrapperWidget-enhanced-grey ) td:not( :nth-child( -n+2 ) ), + .mw-rcfilters-ui-changesListWrapperWidget tr&.mw-rcfilters-ui-changesListWrapperWidget-enhanced-nested:not( .mw-rcfilters-ui-changesListWrapperWidget-enhanced-grey ) td:not( :nth-child( -n+4 ) ) { background-color: @bgcolor; } } diff --git a/resources/src/mediawiki.rcfilters/styles/mw.rcfilters.ui.ChangesListWrapperWidget.highlightCircles.seenunseen.less b/resources/src/mediawiki.rcfilters/styles/mw.rcfilters.ui.ChangesListWrapperWidget.highlightCircles.seenunseen.less index deaee284aa..5f6fbea2fb 100644 --- a/resources/src/mediawiki.rcfilters/styles/mw.rcfilters.ui.ChangesListWrapperWidget.highlightCircles.seenunseen.less +++ b/resources/src/mediawiki.rcfilters/styles/mw.rcfilters.ui.ChangesListWrapperWidget.highlightCircles.seenunseen.less @@ -21,7 +21,7 @@ .mw-rcfilters-mixin-circle( @highlight-none, @result-circle-diameter, 0, true, @highlight-grey, true ); } - .mw-rcfilters-ui-changesListWrapperWidget:not(.mw-rcfilters-ui-changesListWrapperWidget-highlighted) & { + .mw-rcfilters-ui-changesListWrapperWidget:not( .mw-rcfilters-ui-changesListWrapperWidget-highlighted ) & { .mw-rcfilters-mixin-circle( @highlight-none, @result-circle-diameter, 0, true, @highlight-bluedot, true ); } } @@ -31,7 +31,7 @@ .mw-rcfilters-mixin-circle( @highlight-grey, @result-circle-diameter, 0, true, @highlight-grey ); } - .mw-rcfilters-ui-changesListWrapperWidget:not(.mw-rcfilters-ui-changesListWrapperWidget-highlighted) & { + .mw-rcfilters-ui-changesListWrapperWidget:not( .mw-rcfilters-ui-changesListWrapperWidget-highlighted ) & { .mw-rcfilters-mixin-circle( @highlight-bluedot, @result-circle-diameter, 0, true, @highlight-bluedot ); } } diff --git a/resources/src/mediawiki.rcfilters/styles/mw.rcfilters.ui.TagItemWidget.less b/resources/src/mediawiki.rcfilters/styles/mw.rcfilters.ui.TagItemWidget.less index 0e7a635db6..e9c982a86c 100644 --- a/resources/src/mediawiki.rcfilters/styles/mw.rcfilters.ui.TagItemWidget.less +++ b/resources/src/mediawiki.rcfilters/styles/mw.rcfilters.ui.TagItemWidget.less @@ -58,23 +58,23 @@ top: 50%; } - &[data-color='c1']:before { + &[ data-color='c1' ]:before { .mw-rcfilters-mixin-circle( @highlight-c1, 10px, ~'-5px 0.5em 0 0' ); } - &[data-color='c2']:before { + &[ data-color='c2' ]:before { .mw-rcfilters-mixin-circle( @highlight-c2, 10px, ~'-5px 0.5em 0 0' ); } - &[data-color='c3']:before { + &[ data-color='c3' ]:before { .mw-rcfilters-mixin-circle( @highlight-c3, 10px, ~'-5px 0.5em 0 0' ); } - &[data-color='c4']:before { + &[ data-color='c4' ]:before { .mw-rcfilters-mixin-circle( @highlight-c4, 10px, ~'-5px 0.5em 0 0' ); } - &[data-color='c5']:before { + &[ data-color='c5' ]:before { .mw-rcfilters-mixin-circle( @highlight-c5, 10px, ~'-5px 0.5em 0 0' ); } } diff --git a/resources/src/mediawiki.skinning/content.externallinks.css b/resources/src/mediawiki.skinning/content.externallinks.css index cd674ef92e..2a64aa3075 100644 --- a/resources/src/mediawiki.skinning/content.externallinks.css +++ b/resources/src/mediawiki.skinning/content.externallinks.css @@ -19,7 +19,7 @@ padding-right: 15px; } -.mw-body-content a.external[href^='mailto:'], +.mw-body-content a.external[ href^='mailto:' ], .link-mailto { background: url( images/mail.png ) center right no-repeat; /* @embed */ @@ -27,7 +27,7 @@ padding-right: 15px; } -.mw-body-content a.external[href^='ftp://'], +.mw-body-content a.external[ href^='ftp://' ], .link-ftp { background: url( images/ftp-ltr.png ) center right no-repeat; /* @embed */ @@ -35,8 +35,8 @@ padding-right: 15px; } -.mw-body-content a.external[href^='irc://'], -.mw-body-content a.external[href^='ircs://'], +.mw-body-content a.external[ href^='irc://' ], +.mw-body-content a.external[ href^='ircs://' ], .link-irc { background: url( images/chat-ltr.png ) center right no-repeat; /* @embed */ @@ -44,18 +44,18 @@ padding-right: 15px; } -.mw-body-content a.external[href$='.ogg'], -.mw-body-content a.external[href$='.OGG'], -.mw-body-content a.external[href$='.mid'], -.mw-body-content a.external[href$='.MID'], -.mw-body-content a.external[href$='.midi'], -.mw-body-content a.external[href$='.MIDI'], -.mw-body-content a.external[href$='.mp3'], -.mw-body-content a.external[href$='.MP3'], -.mw-body-content a.external[href$='.wav'], -.mw-body-content a.external[href$='.WAV'], -.mw-body-content a.external[href$='.wma'], -.mw-body-content a.external[href$='.WMA'], +.mw-body-content a.external[ href$='.ogg' ], +.mw-body-content a.external[ href$='.OGG' ], +.mw-body-content a.external[ href$='.mid' ], +.mw-body-content a.external[ href$='.MID' ], +.mw-body-content a.external[ href$='.midi' ], +.mw-body-content a.external[ href$='.MIDI' ], +.mw-body-content a.external[ href$='.mp3' ], +.mw-body-content a.external[ href$='.MP3' ], +.mw-body-content a.external[ href$='.wav' ], +.mw-body-content a.external[ href$='.WAV' ], +.mw-body-content a.external[ href$='.wma' ], +.mw-body-content a.external[ href$='.WMA' ], .link-audio { background: url( images/audio-ltr.png ) center right no-repeat; /* @embed */ @@ -63,14 +63,14 @@ padding-right: 15px; } -.mw-body-content a.external[href$='.ogm'], -.mw-body-content a.external[href$='.OGM'], -.mw-body-content a.external[href$='.avi'], -.mw-body-content a.external[href$='.AVI'], -.mw-body-content a.external[href$='.mpeg'], -.mw-body-content a.external[href$='.MPEG'], -.mw-body-content a.external[href$='.mpg'], -.mw-body-content a.external[href$='.MPG'], +.mw-body-content a.external[ href$='.ogm' ], +.mw-body-content a.external[ href$='.OGM' ], +.mw-body-content a.external[ href$='.avi' ], +.mw-body-content a.external[ href$='.AVI' ], +.mw-body-content a.external[ href$='.mpeg' ], +.mw-body-content a.external[ href$='.MPEG' ], +.mw-body-content a.external[ href$='.mpg' ], +.mw-body-content a.external[ href$='.MPG' ], .link-video { background: url( images/video.png ) center right no-repeat; /* @embed */ @@ -78,12 +78,12 @@ padding-right: 15px; } -.mw-body-content a.external[href$='.pdf'], -.mw-body-content a.external[href$='.PDF'], -.mw-body-content a.external[href*='.pdf#'], -.mw-body-content a.external[href*='.PDF#'], -.mw-body-content a.external[href*='.pdf?'], -.mw-body-content a.external[href*='.PDF?'], +.mw-body-content a.external[ href$='.pdf' ], +.mw-body-content a.external[ href$='.PDF' ], +.mw-body-content a.external[ href*='.pdf#' ], +.mw-body-content a.external[ href*='.PDF#' ], +.mw-body-content a.external[ href*='.pdf?' ], +.mw-body-content a.external[ href*='.PDF?' ], .link-document { background: url( images/document-ltr.png ) center right no-repeat; /* @embed */ diff --git a/resources/src/mediawiki.skinning/content.parsoid.less b/resources/src/mediawiki.skinning/content.parsoid.less index 654b65550c..a36ba6ce6d 100644 --- a/resources/src/mediawiki.skinning/content.parsoid.less +++ b/resources/src/mediawiki.skinning/content.parsoid.less @@ -44,9 +44,9 @@ sub { /** * Block media items */ -figure[typeof*='mw:Image'], -figure[typeof*='mw:Video'], -figure[typeof*='mw:Audio'] { +figure[ typeof*='mw:Image' ], +figure[ typeof*='mw:Video' ], +figure[ typeof*='mw:Audio' ] { margin: 0; a { @@ -91,12 +91,12 @@ figure[typeof*='mw:Audio'] { } } -figure[typeof~='mw:Image/Thumb'], -figure[typeof~='mw:Video/Thumb'], -figure[typeof~='mw:Audio/Thumb'], -figure[typeof~='mw:Image/Frame'], -figure[typeof~='mw:Video/Frame'], -figure[typeof~='mw:Audio/Frame'] { +figure[ typeof~='mw:Image/Thumb' ], +figure[ typeof~='mw:Video/Thumb' ], +figure[ typeof~='mw:Audio/Thumb' ], +figure[ typeof~='mw:Image/Frame' ], +figure[ typeof~='mw:Video/Frame' ], +figure[ typeof~='mw:Audio/Frame' ] { display: table; text-align: center; border: 1px solid #c8ccd1; @@ -139,9 +139,9 @@ figure[typeof~='mw:Audio/Frame'] { } } -figure[typeof*='mw:Image/Thumb'], -figure[typeof*='mw:Video/Thumb'], -figure[typeof*='mw:Audio/Thumb'] { +figure[ typeof*='mw:Image/Thumb' ], +figure[ typeof*='mw:Video/Thumb' ], +figure[ typeof*='mw:Audio/Thumb' ] { > a:after { content: ''; width: 15px; diff --git a/resources/src/mediawiki.skinning/elements.css b/resources/src/mediawiki.skinning/elements.css index 245fb53f38..366c5a940b 100644 --- a/resources/src/mediawiki.skinning/elements.css +++ b/resources/src/mediawiki.skinning/elements.css @@ -13,7 +13,7 @@ a { background: none; } -a:not( [href] ) { +a:not( [ href ] ) { cursor: pointer; /* Always cursor:pointer even without href */ } diff --git a/resources/src/mediawiki.special/mediawiki.special.comparepages.styles.less b/resources/src/mediawiki.special/mediawiki.special.comparepages.styles.less index c951169d31..87b7a8b7cb 100644 --- a/resources/src/mediawiki.special/mediawiki.special.comparepages.styles.less +++ b/resources/src/mediawiki.special/mediawiki.special.comparepages.styles.less @@ -10,7 +10,7 @@ .box-sizing( border-box ); } -.mw-special-ComparePages .oo-ui-layout.oo-ui-panelLayout.oo-ui-panelLayout-padded.oo-ui-panelLayout-framed:nth-of-type(2) { +.mw-special-ComparePages .oo-ui-layout.oo-ui-panelLayout.oo-ui-panelLayout-padded.oo-ui-panelLayout-framed:nth-of-type( 2 ) { margin-left: 2%; } diff --git a/resources/src/mediawiki.ui/components/checkbox.less b/resources/src/mediawiki.ui/components/checkbox.less index c1626db610..0c13daf8b1 100644 --- a/resources/src/mediawiki.ui/components/checkbox.less +++ b/resources/src/mediawiki.ui/components/checkbox.less @@ -49,7 +49,7 @@ vertical-align: middle; } - [type='checkbox'] { + [ type='checkbox' ] { display: table-cell; position: relative; // Ensure the invisible input takes up the required `width` & `height` diff --git a/resources/src/mediawiki.ui/components/forms.less b/resources/src/mediawiki.ui/components/forms.less index d3c76d09d0..0a9023e923 100644 --- a/resources/src/mediawiki.ui/components/forms.less +++ b/resources/src/mediawiki.ui/components/forms.less @@ -66,7 +66,7 @@ } // Override input styling just for checkboxes and radio inputs. - input[type='radio'] { + input[ type='radio' ] { display: inline; .box-sizing( content-box ); width: auto; diff --git a/resources/src/mediawiki.ui/components/inputs.less b/resources/src/mediawiki.ui/components/inputs.less index 74dc0b756a..1c79d52ad1 100644 --- a/resources/src/mediawiki.ui/components/inputs.less +++ b/resources/src/mediawiki.ui/components/inputs.less @@ -73,7 +73,7 @@ } // Normalize styling for `` - &[type='search'] { + &[ type='search' ] { // Correct the odd appearance in Chrome and Safari 5 -webkit-appearance: textfield; @@ -103,7 +103,7 @@ textarea.mw-ui-input { // // // Styleguide 1.2. -input[type='number'], +input[ type='number' ], .mw-ui-input-inline { display: inline-block; width: auto; diff --git a/resources/src/mediawiki.ui/components/radio.less b/resources/src/mediawiki.ui/components/radio.less index 3d82e8eda2..d9b7c6d301 100644 --- a/resources/src/mediawiki.ui/components/radio.less +++ b/resources/src/mediawiki.ui/components/radio.less @@ -48,14 +48,14 @@ vertical-align: middle; } - [type='radio'] { + [ type='radio' ] { // ensure the invisible radio takes up the required width width: @sizeInputBinary; height: @sizeInputBinary; // This is needed for Firefox mobile (See T73750 to workaround default Firefox stylesheet) max-width: none; margin: 0; - // Hide `input[type=radio]` and instead style the label that follows + // Hide `input[ type=radio ]` and instead style the label that follows // Support: VoiceOver. Use `opacity` so that VoiceOver can still identify the radio opacity: 0; diff --git a/tests/phpunit/includes/RevisionIntegrationTest.php b/tests/phpunit/includes/RevisionIntegrationTest.php index 10186edf28..96ce7660c4 100644 --- a/tests/phpunit/includes/RevisionIntegrationTest.php +++ b/tests/phpunit/includes/RevisionIntegrationTest.php @@ -265,7 +265,9 @@ class RevisionIntegrationTest extends MediaWikiTestCase { $orig = $this->makeRevisionWithProps(); $dbr = wfGetDB( DB_REPLICA ); - $res = $dbr->select( 'revision', Revision::selectFields(), [ 'rev_id' => $orig->getId() ] ); + $revQuery = Revision::getQueryInfo(); + $res = $dbr->select( $revQuery['tables'], $revQuery['fields'], [ 'rev_id' => $orig->getId() ], + __METHOD__, [], $revQuery['joins'] ); $this->assertTrue( is_object( $res ), 'query failed' ); $row = $res->fetchObject(); @@ -333,9 +335,11 @@ class RevisionIntegrationTest extends MediaWikiTestCase { $page->doDeleteArticle( 'test Revision::newFromArchiveRow' ); $dbr = wfGetDB( DB_REPLICA ); - $selectFields = $selectModifier( Revision::selectArchiveFields() ); + $arQuery = Revision::getArchiveQueryInfo(); + $arQuery['fields'] = $selectModifier( $arQuery['fields'] ); $res = $dbr->select( - 'archive', $selectFields, [ 'ar_rev_id' => $orig->getId() ] + $arQuery['tables'], $arQuery['fields'], [ 'ar_rev_id' => $orig->getId() ], + __METHOD__, [], $arQuery['joins'] ); $this->assertTrue( is_object( $res ), 'query failed' ); @@ -360,8 +364,10 @@ class RevisionIntegrationTest extends MediaWikiTestCase { $page->doDeleteArticle( 'test Revision::newFromArchiveRow' ); $dbr = wfGetDB( DB_REPLICA ); + $arQuery = Revision::getArchiveQueryInfo(); $res = $dbr->select( - 'archive', Revision::selectArchiveFields(), [ 'ar_rev_id' => $orig->getId() ] + $arQuery['tables'], $arQuery['fields'], [ 'ar_rev_id' => $orig->getId() ], + __METHOD__, [], $arQuery['joins'] ); $this->assertTrue( is_object( $res ), 'query failed' ); diff --git a/tests/phpunit/includes/RevisionUnitTest.php b/tests/phpunit/includes/RevisionUnitTest.php index 53725bd173..7b8d316f47 100644 --- a/tests/phpunit/includes/RevisionUnitTest.php +++ b/tests/phpunit/includes/RevisionUnitTest.php @@ -361,178 +361,6 @@ class RevisionUnitTest extends MediaWikiTestCase { Revision::getRevisionText( $row ), "getRevisionText" ); } - /** - * @covers Revision::userJoinCond - */ - public function testUserJoinCond() { - $this->assertEquals( - [ 'LEFT JOIN', [ 'rev_user != 0', 'user_id = rev_user' ] ], - Revision::userJoinCond() - ); - } - - /** - * @covers Revision::pageJoinCond - */ - public function testPageJoinCond() { - $this->assertEquals( - [ 'INNER JOIN', [ 'page_id = rev_page' ] ], - Revision::pageJoinCond() - ); - } - - public function provideSelectFields() { - yield [ - true, - [ - 'rev_id', - 'rev_page', - 'rev_text_id', - 'rev_timestamp', - 'rev_user_text', - 'rev_user', - 'rev_minor_edit', - 'rev_deleted', - 'rev_len', - 'rev_parent_id', - 'rev_sha1', - 'rev_comment_text' => 'rev_comment', - 'rev_comment_data' => 'NULL', - 'rev_comment_cid' => 'NULL', - 'rev_content_format', - 'rev_content_model', - ] - ]; - yield [ - false, - [ - 'rev_id', - 'rev_page', - 'rev_text_id', - 'rev_timestamp', - 'rev_user_text', - 'rev_user', - 'rev_minor_edit', - 'rev_deleted', - 'rev_len', - 'rev_parent_id', - 'rev_sha1', - 'rev_comment_text' => 'rev_comment', - 'rev_comment_data' => 'NULL', - 'rev_comment_cid' => 'NULL', - ] - ]; - } - - /** - * @dataProvider provideSelectFields - * @covers Revision::selectFields - * @todo a true unit test would mock CommentStore - */ - public function testSelectFields( $contentHandlerUseDB, $expected ) { - $this->setMwGlobals( 'wgContentHandlerUseDB', $contentHandlerUseDB ); - $this->assertEquals( $expected, Revision::selectFields() ); - } - - public function provideSelectArchiveFields() { - yield [ - true, - [ - 'ar_id', - 'ar_page_id', - 'ar_rev_id', - 'ar_text', - 'ar_text_id', - 'ar_timestamp', - 'ar_user_text', - 'ar_user', - 'ar_minor_edit', - 'ar_deleted', - 'ar_len', - 'ar_parent_id', - 'ar_sha1', - 'ar_comment_text' => 'ar_comment', - 'ar_comment_data' => 'NULL', - 'ar_comment_cid' => 'NULL', - 'ar_content_format', - 'ar_content_model', - ] - ]; - yield [ - false, - [ - 'ar_id', - 'ar_page_id', - 'ar_rev_id', - 'ar_text', - 'ar_text_id', - 'ar_timestamp', - 'ar_user_text', - 'ar_user', - 'ar_minor_edit', - 'ar_deleted', - 'ar_len', - 'ar_parent_id', - 'ar_sha1', - 'ar_comment_text' => 'ar_comment', - 'ar_comment_data' => 'NULL', - 'ar_comment_cid' => 'NULL', - ] - ]; - } - - /** - * @dataProvider provideSelectArchiveFields - * @covers Revision::selectArchiveFields - * @todo a true unit test would mock CommentStore - */ - public function testSelectArchiveFields( $contentHandlerUseDB, $expected ) { - $this->setMwGlobals( 'wgContentHandlerUseDB', $contentHandlerUseDB ); - $this->assertEquals( $expected, Revision::selectArchiveFields() ); - } - - /** - * @covers Revision::selectTextFields - */ - public function testSelectTextFields() { - $this->assertEquals( - [ - 'old_text', - 'old_flags', - ], - Revision::selectTextFields() - ); - } - - /** - * @covers Revision::selectPageFields - */ - public function testSelectPageFields() { - $this->assertEquals( - [ - 'page_namespace', - 'page_title', - 'page_id', - 'page_latest', - 'page_is_redirect', - 'page_len', - ], - Revision::selectPageFields() - ); - } - - /** - * @covers Revision::selectUserFields - */ - public function testSelectUserFields() { - $this->assertEquals( - [ - 'user_name', - ], - Revision::selectUserFields() - ); - } - public function provideFetchFromConds() { yield [ 0, [] ]; yield [ Revision::READ_LOCKING, [ 'FOR UPDATE' ] ]; diff --git a/tests/phpunit/includes/shell/CommandFactoryTest.php b/tests/phpunit/includes/shell/CommandFactoryTest.php index aacfd43c16..f90e8377ca 100644 --- a/tests/phpunit/includes/shell/CommandFactoryTest.php +++ b/tests/phpunit/includes/shell/CommandFactoryTest.php @@ -23,11 +23,13 @@ class CommandFactoryTest extends PHPUnit_Framework_TestCase { $factory = new CommandFactory( $limits, $cgroup ); $factory->setLogger( $logger ); + $factory->logStderr(); $command = $factory->create(); $wrapper = TestingAccessWrapper::newFromObject( $command ); $this->assertSame( $logger, $wrapper->logger ); $this->assertSame( $cgroup, $wrapper->cgroup ); $this->assertSame( $limits, $wrapper->limits ); + $this->assertTrue( $wrapper->doLogStderr ); } } diff --git a/tests/phpunit/includes/shell/CommandTest.php b/tests/phpunit/includes/shell/CommandTest.php index 32d855ea39..81fae33c84 100644 --- a/tests/phpunit/includes/shell/CommandTest.php +++ b/tests/phpunit/includes/shell/CommandTest.php @@ -118,4 +118,25 @@ class CommandTest extends PHPUnit_Framework_TestCase { $this->assertEquals( 333333, strlen( $output ) ); } } + + public function testLogStderr() { + $this->requirePosix(); + + $logger = new TestLogger( true, function ( $message, $level, $context ) { + return $level === Psr\Log\LogLevel::ERROR ? '1' : null; + }, true ); + $command = new Command(); + $command->setLogger( $logger ); + $command->params( 'bash', '-c', 'echo ThisIsStderr 1>&2' ); + $command->execute(); + $this->assertEmpty( $logger->getBuffer() ); + + $command = new Command(); + $command->setLogger( $logger ); + $command->logStderr(); + $command->params( 'bash', '-c', 'echo ThisIsStderr 1>&2' ); + $command->execute(); + $this->assertSame( 1, count( $logger->getBuffer() ) ); + $this->assertSame( trim( $logger->getBuffer()[0][2]['error'] ), 'ThisIsStderr' ); + } } diff --git a/tests/phpunit/includes/specials/SpecialMyLanguageTest.php b/tests/phpunit/includes/specials/SpecialMyLanguageTest.php index 89fd1b0696..84fa71a2c6 100644 --- a/tests/phpunit/includes/specials/SpecialMyLanguageTest.php +++ b/tests/phpunit/includes/specials/SpecialMyLanguageTest.php @@ -8,7 +8,10 @@ class SpecialMyLanguageTest extends MediaWikiTestCase { public function addDBDataOnce() { $titles = [ 'Page/Another', + 'Page/Another/ar', + 'Page/Another/en', 'Page/Another/ru', + 'Page/Another/zh-hans', ]; foreach ( $titles as $title ) { $page = WikiPage::factory( Title::newFromText( $title ) ); @@ -54,12 +57,22 @@ class SpecialMyLanguageTest extends MediaWikiTestCase { } public static function provideFindTitle() { + // See addDBDataOnce() for page declarations return [ + // [ $expected, $subpage, $langCode, $userLang ] [ null, '::Fail', 'en', 'en' ], [ 'Page/Another', 'Page/Another/en', 'en', 'en' ], [ 'Page/Another', 'Page/Another', 'en', 'en' ], [ 'Page/Another/ru', 'Page/Another', 'en', 'ru' ], [ 'Page/Another', 'Page/Another', 'en', 'es' ], + [ 'Page/Another/zh-hans', 'Page/Another', 'en', 'zh-hans' ], + [ 'Page/Another/zh-hans', 'Page/Another', 'en', 'zh-mo' ], + [ 'Page/Another/en', 'Page/Another', 'de', 'es' ], + [ 'Page/Another/ar', 'Page/Another', 'en', 'ar' ], + [ 'Page/Another/ar', 'Page/Another', 'en', 'arz' ], + [ 'Page/Another/ar', 'Page/Another/de', 'en', 'arz' ], + [ 'Page/Another/ru', 'Page/Another/ru', 'en', 'arz' ], + [ 'Page/Another/ar', 'Page/Another/ru', 'en', 'ar' ], ]; } }