From a4536a5a72b21aafdd8bc756810012e051ac4b76 Mon Sep 17 00:00:00 2001 From: Rob Church Date: Wed, 4 Jul 2007 01:52:16 +0000 Subject: [PATCH] Move all watchlist editing into WatchlistEditor class, integrating "raw editing" from ExportWatchlist extension, per Brion. Spiffed up the existing editor and "clear" interface; all three editors better integrated from a UI perspective. --- RELEASE-NOTES | 8 +- includes/AutoLoader.php | 1 + includes/SpecialWatchlist.php | 167 +------------ includes/WatchlistEditor.php | 393 ++++++++++++++++++++++++++++++ languages/messages/MessagesEn.php | 38 ++- maintenance/language/messages.inc | 30 ++- 6 files changed, 455 insertions(+), 182 deletions(-) create mode 100644 includes/WatchlistEditor.php diff --git a/RELEASE-NOTES b/RELEASE-NOTES index b5343a2ae5..e193f9bd94 100644 --- a/RELEASE-NOTES +++ b/RELEASE-NOTES @@ -117,9 +117,11 @@ it from source control: http://www.mediawiki.org/wiki/Download_from_SVN * New javascript for upload page that will show a warning if a file with the "destination filename" already exists. * Add 'editsection-brackets' message to allow localization (or removal) of the - brackets in the "[edit]" link for sections. -* (bug 10437) Move texvc styling to shared.css. -* (bug 10438) HTML TeX formulas should not wrap. + brackets in the "[edit]" link for sections +* (bug 10437) Move texvc styling to shared.css +* (bug 10438) HTML TeX formulas should not wrap +* Introduce "raw editing" mode for the watchlist, to allow bulk additions, + removals, and convenient exporting of watchlist contents == Bugfixes since 1.10 == diff --git a/includes/AutoLoader.php b/includes/AutoLoader.php index fbd01a127b..745c378d2b 100644 --- a/includes/AutoLoader.php +++ b/includes/AutoLoader.php @@ -252,6 +252,7 @@ function __autoload($className) { 'ZhClient' => 'includes/ZhClient.php', 'memcached' => 'includes/memcached-client.php', 'EmaillingJob' => 'includes/JobQueue.php', + 'WatchlistEditor' => 'includes/WatchlistEditor.php', # filerepo 'ArchivedFile' => 'includes/filerepo/ArchivedFile.php', diff --git a/includes/SpecialWatchlist.php b/includes/SpecialWatchlist.php index 07fc6b06f6..a921e982a3 100644 --- a/includes/SpecialWatchlist.php +++ b/includes/SpecialWatchlist.php @@ -35,10 +35,17 @@ function wfSpecialWatchlist( $par ) { $wgOut->setSubtitle( wfMsgWikiHtml( 'watchlistfor', htmlspecialchars( $wgUser->getName() ) ) ); } - if( wlHandleClear( $wgOut, $wgRequest, $par ) ) { + if( ( $mode = WatchlistEditor::getMode( $wgRequest, $par ) ) !== false ) { + $editor = new WatchlistEditor(); + $editor->execute( $wgUser, $wgOut, $wgRequest, $mode ); return; } + $uid = $wgUser->getId(); + if( $wgEnotifWatchlist && $wgRequest->getVal( 'reset' ) && $wgRequest->wasPosted() ) { + $wgUser->clearAllNotifications( $uid ); + } + $defaults = array( /* float */ 'days' => floatval( $wgUser->getOption( 'watchlistdays' ) ), /* 3.0 or 0.5, watch further below */ /* bool */ 'hideOwn' => (int)$wgUser->getBoolOption( 'watchlisthideown' ), @@ -72,37 +79,6 @@ function wfSpecialWatchlist( $par ) { $nameSpaceClause = ''; } - # Watchlist editing - $action = $wgRequest->getVal( 'action' ); - $remove = $wgRequest->getVal( 'remove' ); - $id = $wgRequest->getArray( 'id' ); - - $uid = $wgUser->getID(); - if( $wgEnotifWatchlist && $wgRequest->getVal( 'reset' ) && $wgRequest->wasPosted() ) { - $wgUser->clearAllNotifications( $uid ); - } - - # Deleting items from watchlist - if(($action == 'submit') && isset($remove) && is_array($id)) { - $wgOut->addWikiText( wfMsg( 'removingchecked' ) ); - $wgOut->addHTML( "\n

" . wfMsg( 'wldone' ) . "

\n" ); - } - $dbr = wfGetDB( DB_SLAVE, 'watchlist' ); list( $page, $watchlist, $recentchanges ) = $dbr->tableNamesN( 'page', 'watchlist', 'recentchanges' ); @@ -155,81 +131,6 @@ function wfSpecialWatchlist( $par ) { $npages = 40000 * $days; } - /* Edit watchlist form */ - if($wgRequest->getBool('edit') || $par == 'edit' ) { - $wgOut->addWikiText( wfMsgExt( 'watchlistcontains', array( 'parseinline' ), $wgLang->formatNum( $nitems ) ) . - "\n\n" . wfMsg( 'watcheditlist' ) ); - - $wgOut->addHTML( '
escapeLocalUrl( 'action=submit' ) . - "' method='post'>\n" ); - -# Patch A2 -# The following was proposed by KTurner 07.11.2004 to T.Gries -# $sql = "SELECT distinct (wl_namespace & ~1),wl_title FROM $watchlist WHERE wl_user=$uid"; - $sql = "SELECT wl_namespace, wl_title, page_is_redirect FROM $watchlist LEFT JOIN $page ON wl_namespace = page_namespace AND wl_title = page_title WHERE wl_user=$uid"; - - $res = $dbr->query( $sql, $fname ); - - # Batch existence check - $linkBatch = new LinkBatch(); - while( $row = $dbr->fetchObject( $res ) ) - $linkBatch->addObj( Title::makeTitleSafe( $row->wl_namespace, $row->wl_title ) ); - $linkBatch->execute(); - - if( $dbr->numRows( $res ) > 0 ) - $dbr->dataSeek( $res, 0 ); # Let's do the time warp again! - - $sk = $wgUser->getSkin(); - - $list = array(); - while( $s = $dbr->fetchObject( $res ) ) { - $list[$s->wl_namespace][$s->wl_title] = $s->page_is_redirect; - } - - // TODO: Display a TOC - foreach($list as $ns => $titles) { - if (Namespace::isTalk($ns)) - continue; - if ($ns != NS_MAIN) - $wgOut->addHTML( '

' . $wgContLang->getFormattedNsText( $ns ) . '

' ); - $wgOut->addHTML( '' ); - } - $wgOut->addHTML( - wfSubmitButton( wfMsg('removechecked'), array('name' => 'remove') ) . - "\n
\n" - ); - - return; - } - # If the watchlist is relatively short, it's simplest to zip # down its entirety and then sort the results. @@ -463,54 +364,4 @@ function wlCountItems( &$user, $talk = true ) { $count = floor( $count / 2 ); return( $count ); -} - -/** - * Allow the user to clear their watchlist - * - * @param $out Output object - * @param $request Request object - * @param $par Parameters passed to the watchlist page - * @return bool True if it's been taken care of; false indicates the watchlist - * code needs to do something further - */ -function wlHandleClear( &$out, &$request, $par ) { - global $wgLang; - - # Check this function has something to do - if( $request->getText( 'action' ) == 'clear' || $par == 'clear' ) { - global $wgUser; - $out->setPageTitle( wfMsgHtml( 'clearwatchlist' ) ); - $count = wlCountItems( $wgUser ); - if( $count > 0 ) { - # See if we're clearing or confirming - if( $request->wasPosted() && $wgUser->matchEditToken( $request->getText( 'token' ), 'clearwatchlist' ) ) { - # Clearing, so do it and report the result - $dbw = wfGetDB( DB_MASTER ); - $dbw->delete( 'watchlist', array( 'wl_user' => $wgUser->mId ), 'wlHandleClear' ); - $out->addWikiText( wfMsgExt( 'watchlistcleardone', array( 'parsemag', 'escape'), $wgLang->formatNum( $count ) ) ); - $out->returnToMain(); - } else { - # Confirming, so show a form - $wlTitle = SpecialPage::getTitleFor( 'Watchlist' ); - $out->addHTML( wfElement( 'form', array( 'method' => 'post', 'action' => $wlTitle->getLocalUrl( 'action=clear' ) ), NULL ) ); - $out->addWikiText( wfMsgExt( 'watchlistcount', array( 'parsemag', 'escape'), $wgLang->formatNum( $count ) ) ); - $out->addWikiText( wfMsg( 'watchlistcleartext' ) ); - $out->addHTML( - wfHidden( 'token', $wgUser->editToken( 'clearwatchlist' ) ) . - wfElement( 'input', array( 'type' => 'submit', 'name' => 'submit', 'value' => wfMsgHtml( 'watchlistclearbutton' ) ), '' ) . - wfCloseElement( 'form' ) - ); - } - return( true ); - } else { - # Nothing on the watchlist; nothing to do here - $out->addWikiText( wfMsg( 'nowatchlist' ) ); - $out->returnToMain(); - return( true ); - } - } else { - return( false ); - } -} - +} \ No newline at end of file diff --git a/includes/WatchlistEditor.php b/includes/WatchlistEditor.php new file mode 100644 index 0000000000..aec6f4d08f --- /dev/null +++ b/includes/WatchlistEditor.php @@ -0,0 +1,393 @@ + + */ +class WatchlistEditor { + + /** + * Editing modes + */ + const EDIT_CLEAR = 1; + const EDIT_RAW = 2; + const EDIT_NORMAL = 3; + + /** + * Main execution point + * + * @param User $user + * @param OutputPage $output + * @param WebRequest $request + * @param int $mode + */ + public function execute( $user, $output, $request, $mode ) { + if( wfReadOnly() ) { + $output->readOnlyPage(); + return; + } + switch( $mode ) { + case self::EDIT_CLEAR: + $output->setPageTitle( wfMsg( 'watchlistedit-clear-title' ) ); + if( $request->wasPosted() && $this->checkToken( $request, $user ) ) { + $this->clearWatchlist( $user ); + $user->invalidateCache(); + $output->addHtml( wfMsgExt( 'watchlistedit-clear-done', 'parse' ) ); + } else { + $this->showClearForm( $output, $user ); + } + break; + case self::EDIT_RAW: + $output->setPageTitle( wfMsg( 'watchlistedit-raw-title' ) ); + if( $request->wasPosted() && $this->checkToken( $request, $user ) ) { + $titles = $this->extractTitles( $request->getText( 'titles' ) ); + $this->clearWatchlist( $user ); + $this->watchTitles( $titles, $user ); + $user->invalidateCache(); + $output->addHtml( wfMsgExt( 'watchlistedit-raw-done', 'parse' ) ); + } + $this->showRawForm( $output, $user ); + break; + case self::EDIT_NORMAL: + $output->setPageTitle( wfMsg( 'watchlistedit-normal-title' ) ); + if( $request->wasPosted() && $this->checkToken( $request, $user ) ) { + $titles = $this->extractTitles( $request->getArray( 'titles' ) ); + $this->unwatchTitles( $titles, $user ); + $user->invalidateCache(); + $output->addHtml( wfMsgExt( 'watchlistedit-normal-done', 'parse', + $GLOBALS['wgLang']->formatNum( count( $titles ) ) ) ); + $this->showTitles( $titles, $output, $user->getSkin() ); + } + $this->showNormalForm( $output, $user ); + } + } + + /** + * Check the edit token from a form submission + * + * @param WebRequest $request + * @param User $user + * @return bool + */ + private function checkToken( $request, $user ) { + return $user->matchEditToken( $request->getVal( 'token' ), 'watchlistedit' ); + } + + /** + * Extract a list of titles from a text list; if we're given + * an array, convert each item into a Title + * + * @param mixed $list + * @return array + */ + private function extractTitles( $list ) { + if( !is_array( $list ) ) { + $list = explode( "\n", $list ); + if( !is_array( $list ) ) + return array(); + } + for( $i = 0; $i < count( $list ); $i++ ) { + $list[$i] = Title::newFromText( $list[$i] ); + if( !$list[$i] instanceof Title ) + unset( $list[$i] ); + } + return $list; + } + + /** + * Print out a list of linked titles + * + * @param array $titles + * @param OutputPage $output + * @param Skin $skin + */ + private function showTitles( $titles, $output, $skin ) { + $talk = htmlspecialchars( $GLOBALS['wgContLang']->getFormattedNsText( NS_TALK ) ); + // Do a batch existence check + $batch = new LinkBatch(); + foreach( $titles as $title ) { + $batch->addObj( $title ); + $batch->addObj( $title->getTalkPage() ); + } + $batch->execute(); + // Print out the list + $output->addHtml( "\n" ); + } + + /** + * Count the number of titles on a user's watchlist, excluding talk pages + * + * @param User $user + * @return int + */ + private function countWatchlist( $user ) { + $dbr = wfGetDB( DB_SLAVE ); + $res = $dbr->select( 'watchlist', 'COUNT(*) AS count', array( 'wl_user' => $user->getId() ), __METHOD__ ); + $row = $dbr->fetchObject( $res ); + return ceil( $row->count / 2 ); // Paranoia + } + + /** + * Get a list of titles on a user's watchlist, excluding talk pages, + * and return as a two-dimensional array with namespace, title and + * redirect status + * + * @param User $user + * @return array + */ + private function getWatchlist( $user ) { + $titles = array(); + $dbr = wfGetDB( DB_SLAVE ); + $uid = intval( $user->getId() ); + list( $watchlist, $page ) = $dbr->tableNamesN( 'watchlist', 'page' ); + $sql = "SELECT wl_namespace, wl_title, page_id, page_is_redirect + FROM {$watchlist} LEFT JOIN {$page} ON ( wl_namespace = page_namespace + AND wl_title = page_title ) WHERE wl_user = {$uid}"; + $res = $dbr->query( $sql, __METHOD__ ); + if( $res && $dbr->numRows( $res ) > 0 ) { + $cache = LinkCache::singleton(); + while( $row = $dbr->fetchObject( $res ) ) { + $title = Title::makeTitleSafe( $row->wl_namespace, $row->wl_title ); + if( $title instanceof Title ) { + // Update the link cache while we're at it + if( $row->page_id ) { + $cache->addGoodLinkObj( $row->page_id, $title ); + } else { + $cache->addBadLinkObj( $title ); + } + // Ignore non-talk + if( !$title->isTalkPage() ) + $titles[$row->wl_namespace][$row->wl_title] = $row->page_is_redirect; + } + } + } + return $titles; + } + + /** + * Show a message indicating the number of items on the user's watchlist, + * and return this count for additional checking + * + * @param OutputPage $output + * @param User $user + * @return int + */ + private function showItemCount( $output, $user ) { + if( ( $count = $this->countWatchlist( $user ) ) > 0 ) { + $output->addHtml( wfMsgExt( 'watchlistedit-numitems', 'parse', + $GLOBALS['wgLang']->formatNum( $count ) ) ); + } else { + $output->addHtml( wfMsgExt( 'watchlistedit-noitems', 'parse' ) ); + } + return $count; + } + + /** + * Remove all titles from a user's watchlist + * + * @param User $user + */ + private function clearWatchlist( $user ) { + $dbw = wfGetDB( DB_MASTER ); + $dbw->delete( 'watchlist', array( 'wl_user' => $user->getId() ), __METHOD__ ); + } + + /** + * Add a list of titles to a user's watchlist + * + * @param array $titles + * @param User $user + */ + private function watchTitles( $titles, $user ) { + $dbw = wfGetDB( DB_MASTER ); + $rows = array(); + foreach( $titles as $title ) { + $rows[] = array( + 'wl_user' => $user->getId(), + 'wl_namespace' => ( $title->getNamespace() & ~1 ), + 'wl_title' => $title->getDBkey(), + 'wl_notificationtimestamp' => null, + ); + $rows[] = array( + 'wl_user' => $user->getId(), + 'wl_namespace' => ( $title->getNamespace() | 1 ), + 'wl_title' => $title->getDBkey(), + 'wl_notificationtimestamp' => null, + ); + } + $dbw->insert( 'watchlist', $rows, __METHOD__, 'IGNORE' ); + } + + /** + * Remove a list of titles from a user's watchlist + * + * @param array $titles + * @param User $user + */ + private function unwatchTitles( $titles, $user ) { + $dbw = wfGetDB( DB_MASTER ); + foreach( $titles as $title ) { + $dbw->delete( + 'watchlist', + array( + 'wl_user' => $user->getId(), + 'wl_namespace' => ( $title->getNamespace() & ~1 ), + 'wl_title' => $title->getDBkey(), + ), + __METHOD__ + ); + $dbw->delete( + 'watchlist', + array( + 'wl_user' => $user->getId(), + 'wl_namespace' => ( $title->getNamespace() | 1 ), + 'wl_title' => $title->getDBkey(), + ), + __METHOD__ + ); + } + } + + /** + * Show a confirmation form for users wishing to clear their watchlist + * + * @param OutputPage $output + * @param User $user + */ + private function showClearForm( $output, $user ) { + if( ( $count = $this->showItemCount( $output, $user ) ) > 0 ) { + $self = SpecialPage::getTitleFor( 'Watchlist' ); + $form = Xml::openElement( 'form', array( 'method' => 'post', + 'action' => $self->getLocalUrl( 'action=clear' ) ) ); + $form .= Xml::hidden( 'token', $user->editToken( 'watchlistedit' ) ); + $form .= '
' . wfMsgHtml( 'watchlistedit-clear-legend' ) . ''; + $form .= wfMsgExt( 'watchlistedit-clear-confirm', 'parse' ); + $form .= '

' . Xml::submitButton( wfMsg( 'watchlistedit-clear-submit' ) ) . '

'; + $form .= '
'; + $output->addHtml( $form ); + } + } + + /** + * Show the standard watchlist editing form + * + * @param OutputPage $output + * @param User $user + */ + private function showNormalForm( $output, $user ) { + if( ( $count = $this->showItemCount( $output, $user ) ) > 0 ) { + $self = SpecialPage::getTitleFor( 'Watchlist' ); + $form = Xml::openElement( 'form', array( 'method' => 'post', + 'action' => $self->getLocalUrl( 'action=edit' ) ) ); + $form .= Xml::hidden( 'token', $user->editToken( 'watchlistedit' ) ); + $form .= '
' . wfMsgHtml( 'watchlistedit-normal-legend' ) . ''; + $form .= wfMsgExt( 'watchlistedit-normal-explain', 'parse' ); + foreach( $this->getWatchlist( $user ) as $namespace => $pages ) { + $form .= '

' . $this->getNamespaceHeading( $namespace ) . '

'; + $form .= ''; + } + $form .= '

' . Xml::submitButton( wfMsg( 'watchlistedit-normal-submit' ) ) . '

'; + $form .= '
'; + $output->addHtml( $form ); + } + } + + /** + * Get the correct "heading" for a namespace + * + * @param int $namespace + * @return string + */ + private function getNamespaceHeading( $namespace ) { + return $namespace == NS_MAIN + ? wfMsgHtml( 'blanknamespace' ) + : htmlspecialchars( $GLOBALS['wgContLang']->getFormattedNsText( $namespace ) ); + } + + /** + * Build a single list item containing a check box selecting a title + * and a link to that title, with various additional bits + * + * @param Title $title + * @param bool $redirect + * @param Skin $skin + * @return string + */ + private function buildRemoveLine( $title, $redirect, $skin ) { + $link = $skin->makeLinkObj( $title ); + if( $redirect ) + $link = '' . $link . ''; + $tools[] = $skin->makeLinkObj( $title->getTalkPage(), + htmlspecialchars( $GLOBALS['wgContLang']->getFormattedNsText( NS_TALK ) ) ); + if( $title->exists() ) + $tools[] = $skin->makeKnownLinkObj( $title, wfMsgHtml( 'history_short' ), 'action=history' ); + return '
  • ' + . Xml::check( 'titles[]', false, array( 'value' => $title->getPrefixedText() ) ) + . $link . ' (' . implode( ' | ', $tools ) . ')' . '
  • '; + } + + /** + * Show a form for editing the watchlist in "raw" mode + * + * @param OutputPage $output + * @param User $user + */ + public function showRawForm( $output, $user ) { + $this->showItemCount( $output, $user ); + $self = SpecialPage::getTitleFor( 'Watchlist' ); + $form = Xml::openElement( 'form', array( 'method' => 'post', + 'action' => $self->getLocalUrl( 'action=raw' ) ) ); + $form .= Xml::hidden( 'token', $user->editToken( 'watchlistedit' ) ); + $form .= '
    ' . wfMsgHtml( 'watchlistedit-raw-legend' ) . ''; + $form .= wfMsgExt( 'watchlistedit-raw-explain', 'parse' ); + $form .= Xml::label( wfMsg( 'watchlistedit-raw-titles' ), 'titles' ); + $form .= Xml::openElement( 'textarea', array( 'id' => 'titles', 'name' => 'titles', + 'rows' => 6, 'cols' => 80 ) ); + foreach( $this->getWatchlist( $user ) as $namespace => $pages ) { + foreach( $pages as $dbkey => $redirect ) { + $title = Title::makeTitleSafe( $namespace, $dbkey ); + if( $title instanceof Title ) + $form .= htmlspecialchars( $title->getPrefixedText() ) . "\n"; + } + } + $form .= ''; + $form .= '

    ' . Xml::submitButton( wfMsg( 'watchlistedit-raw-submit' ) ) . '

    '; + $form .= '
    '; + $output->addHtml( $form ); + } + + /** + * Determine whether we are editing the watchlist, and if so, what + * kind of editing operation + * + * @param WebRequest $request + * @param mixed $par + * @return int + */ + public static function getMode( $request, $par ) { + $mode = strtolower( $request->getVal( 'action', $par ) ); + switch( $mode ) { + case 'clear': + return self::EDIT_CLEAR; + case 'raw': + return self::EDIT_RAW; + case 'edit': + return self::EDIT_NORMAL; + default: + return false; + } + } + +} \ No newline at end of file diff --git a/languages/messages/MessagesEn.php b/languages/messages/MessagesEn.php index d4065af35d..8d402eb95e 100644 --- a/languages/messages/MessagesEn.php +++ b/languages/messages/MessagesEn.php @@ -1692,10 +1692,6 @@ or has chosen not to receive e-mail from other users.', 'nowatchlist' => 'You have no items on your watchlist.', 'watchlistanontext' => 'Please $1 to view or edit items on your watchlist.', 'watchlistcount' => "'''You have {{PLURAL:$1|$1 item|$1 items}} on your watchlist, including talk pages.'''", -'clearwatchlist' => 'Clear watchlist', -'watchlistcleartext' => 'Are you sure you wish to remove them?', -'watchlistclearbutton' => 'Clear watchlist', -'watchlistcleardone' => 'Your watchlist has been cleared. {{PLURAL:$1|$1 item was|$1 items were}} removed.', 'watchnologin' => 'Not logged in', 'watchnologintext' => 'You must be [[Special:Userlogin|logged in]] to modify your watchlist.', 'addedwatch' => 'Added to watchlist', @@ -1720,13 +1716,7 @@ If you want to remove the page from your watchlist later, click \"Unwatch\" in t 'wlheader-showupdated' => "* Pages which have been changed since you last visited them are shown in '''bold'''", 'watchmethod-recent' => 'checking recent edits for watched pages', 'watchmethod-list' => 'checking watched pages for recent edits', -'removechecked' => 'Remove checked items from watchlist', 'watchlistcontains' => 'Your watchlist contains $1 {{PLURAL:$1|page|pages}}.', -'watcheditlist' => "Here's an alphabetical list of your -watched content pages. Check the boxes of pages you want to remove from your watchlist and click the 'remove checked' button -at the bottom of the screen (deleting a content page also deletes the accompanying talk page and vice versa).", -'removingchecked' => 'Removing requested items from watchlist...', -'couldntremove' => "Couldn't remove item '$1'...", 'iteminvalidname' => "Problem with item '$1', invalid name...", 'wlnote' => "Below {{PLURAL:$1|is the last change|are the last '''$1''' changes}} in the last {{PLURAL:$2|hour|'''$2''' hours}}.", 'wlshowlast' => 'Show last $1 hours $2 days $3', @@ -1737,7 +1727,6 @@ at the bottom of the screen (deleting a content page also deletes the accompanyi 'watchlist-hide-own' => 'Hide my edits', 'watchlist-show-minor' => 'Show minor edits', 'watchlist-hide-minor' => 'Hide minor edits', -'wldone' => 'Done.', # Displayed when you click the "watch" button and it's in the process of watching 'watching' => 'Watching...', @@ -2896,4 +2885,29 @@ $1', 'lag-warn-normal' => 'Changes newer than $1 seconds may not be shown in this list.', 'lag-warn-high' => 'Due to high database server lag, changes newer than $1 seconds may not be shown in this list.', -); +# Watchlist editor +'watchlistedit-numitems' => 'Your watchlist contains $1 title(s), excluding talk pages.', +'watchlistedit-noitems' => 'Your watchlist contains no titles.', +'watchlistedit-clear-title' => 'Clear watchlist', +'watchlistedit-clear-legend' => 'Clear watchlist', +'watchlistedit-clear-confirm' => 'This will remove all titles from your watchlist. Are you sure you + want to do this? You can also [[Special:Watchlist/edit|remove individual titles]].', +'watchlistedit-clear-submit' => 'Clear', +'watchlistedit-clear-done' => 'Your watchlist has been cleared. All titles were removed.', +'watchlistedit-normal-title' => 'Edit watchlist', +'watchlistedit-normal-legend' => 'Remove titles from watchlist', +'watchlistedit-normal-explain' => 'Titles on your watchlist are shown below. To remove a title, check + the box next to it, and click Remove Titles. You can also [[Special:Watchlist/raw|edit the raw list]], + or [[Special:Watchlist/clear|remove all titles]].', +'watchlistedit-normal-submit' => 'Remove Titles', +'watchlistedit-normal-done' => '$1 title(s) were removed from your watchlist:', +'watchlistedit-raw-title' => 'Edit raw watchlist', +'watchlistedit-raw-legend' => 'Edit raw watchlist', +'watchlistedit-raw-explain' => 'Titles on your watchlist are shown below, and can be edited by + adding to and removing from the list; one title per line. When finished, click Update Watchlist. + You can also [[Special:Watchlist/edit|use the standard editor]].', +'watchlistedit-raw-titles' => 'Titles:', +'watchlistedit-raw-submit' => 'Update Watchlist', +'watchlistedit-raw-done' => 'Your watchlist has been updated.', + +); \ No newline at end of file diff --git a/maintenance/language/messages.inc b/maintenance/language/messages.inc index c252b92133..fa0ede304f 100644 --- a/maintenance/language/messages.inc +++ b/maintenance/language/messages.inc @@ -1080,10 +1080,6 @@ $wgMessageStructure = array( 'nowatchlist', 'watchlistanontext', 'watchlistcount', - 'clearwatchlist', - 'watchlistcleartext', - 'watchlistclearbutton', - 'watchlistcleardone', 'watchnologin', 'watchnologintext', 'addedwatch', @@ -1101,11 +1097,7 @@ $wgMessageStructure = array( 'wlheader-showupdated', 'watchmethod-recent', 'watchmethod-list', - 'removechecked', 'watchlistcontains', - 'watcheditlist', - 'removingchecked', - 'couldntremove', 'iteminvalidname', 'wlnote', 'wlshowlast', @@ -1116,7 +1108,6 @@ $wgMessageStructure = array( 'watchlist-hide-own', 'watchlist-show-minor', 'watchlist-hide-minor', - 'wldone', ), 'watching' => array( 'watching', @@ -2131,6 +2122,26 @@ $wgMessageStructure = array( 'lag-warn-normal', 'lag-warn-high', ), + 'watchlisteditor' => array( + 'watchlistedit-numitems', + 'watchlistedit-noitems', + 'watchlistedit-clear-title', + 'watchlistedit-clear-legend', + 'watchlistedit-clear-confirm', + 'watchlistedit-clear-submit', + 'watchlistedit-clear-done', + 'watchlistedit-normal-title', + 'watchlistedit-normal-legend', + 'watchlistedit-normal-explain', + 'watchlistedit-normal-submit', + 'watchlistedit-normal-done', + 'watchlistedit-raw-title', + 'watchlistedit-raw-legend', + 'watchlistedit-raw-explain', + 'watchlistedit-raw-titles', + 'watchlistedit-raw-submit', + 'watchlistedit-raw-done', + ), ); /** Comments for each block */ $wgBlockComments = array( @@ -2297,6 +2308,7 @@ Variants for Chinese language", 'sizeunits' => 'Size units', 'livepreview' => 'Live preview', 'lagwarning' => 'Friendlier slave lag warnings', + 'watchlisteditor' => 'Watchlist editor', ); /** Short comments for standalone messages */ -- 2.20.1