Allow change tags to have help links in separate messages
Many changes tags added by extensions include links in the 'tag-<tag>' label messages, which point to help pages for the tags and the software features that add them. This makes translating the labels unpleasant. Introduce localisation messages like 'tag-<tag>-helppage' (following the pattern of 'tag-<tag>-description'), which should contain a URL or a page title of a help page for the given tag. When such link message is defined, the tag description in changes lists, history pages etc. is wrapped in a link that points to the given URL or page. Unlike the label messages, the link messages are always used in wiki content language, for easy on-wiki customization. For compatibility with old translations and existing on-wiki overrides, if 'tag-<tag>' already contains any links, 'tag-<tag>-helppage' is ignored. Add buttons that allow editing the new links on Special:Tags. Correct existing buttons that allow editing the labels to use user language. Add help links using the new messages to the changes list filtering interface (which can't display links in tag descriptions themselves). Introduce a link message for 'mw-contentmodelchange' tag as an example. Bug: T372175 Change-Id: I1e2242a8591597a110a5a430f4c251f0f601cfbe
This commit is contained in:
parent
aa7a7bf3e8
commit
7bab3cd60e
9 changed files with 91 additions and 13 deletions
|
|
@ -225,13 +225,34 @@ class ChangeTags {
|
|||
return $msg;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the tag's help link.
|
||||
*
|
||||
* Checks if message key "mediawiki:tag-$tag-helppage" exists in content language. If it does,
|
||||
* and contains a URL or a page title, return a (possibly relative) link URL that points there.
|
||||
* Otherwise return null.
|
||||
*
|
||||
* @since 1.43
|
||||
* @param string $tag
|
||||
* @param MessageLocalizer $context
|
||||
* @return string|null Tag link, or null if not provided or invalid
|
||||
*/
|
||||
public static function tagHelpLink( $tag, MessageLocalizer $context ) {
|
||||
$msg = $context->msg( "tag-$tag-helppage" )->inContentLanguage();
|
||||
if ( $msg->exists() && !$msg->isDisabled() ) {
|
||||
$url = Skin::makeInternalOrExternalUrl( $msg->plain() );
|
||||
if ( $url ) {
|
||||
return $url;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a short description for a tag.
|
||||
*
|
||||
* Checks if message key "mediawiki:tag-$tag" exists. If it does not,
|
||||
* returns the HTML-escaped tag name. Uses the message if the message
|
||||
* exists, provided it is not disabled. If the message is disabled,
|
||||
* we consider the tag hidden, and return false.
|
||||
* The description combines the label from tagShortDescriptionMessage() with the link from
|
||||
* tagHelpLink() (unless the label already contains some links).
|
||||
*
|
||||
* @param string $tag
|
||||
* @param MessageLocalizer $context
|
||||
|
|
@ -240,6 +261,14 @@ class ChangeTags {
|
|||
*/
|
||||
public static function tagDescription( $tag, MessageLocalizer $context ) {
|
||||
$msg = self::tagShortDescriptionMessage( $tag, $context );
|
||||
$link = self::tagHelpLink( $tag, $context );
|
||||
if ( $msg && $link ) {
|
||||
$label = $msg->parse();
|
||||
// Avoid invalid HTML caused by link wrapping if the label already contains a link
|
||||
if ( !str_contains( $label, '<a ' ) ) {
|
||||
return Html::rawElement( 'a', [ 'href' => $link ], $label );
|
||||
}
|
||||
}
|
||||
return $msg ? $msg->parse() : false;
|
||||
}
|
||||
|
||||
|
|
@ -1227,6 +1256,7 @@ class ChangeTags {
|
|||
* - descriptionMsg: Long description message (Message object)
|
||||
* - description: Long description message (raw message contents)
|
||||
* - cssClass: CSS class to use for RC entries with this tag
|
||||
* - helpLink: Link to a help page describing this tag (string or null)
|
||||
* - hits: Number of RC entries that have this tag
|
||||
*
|
||||
* This data is consumed by the `mediawiki.rcfilters.filters.ui` module,
|
||||
|
|
@ -1255,6 +1285,7 @@ class ChangeTags {
|
|||
}
|
||||
|
||||
$labelMsg = self::tagShortDescriptionMessage( $tagName, $localizer );
|
||||
$helpLink = self::tagHelpLink( $tagName, $localizer );
|
||||
$descriptionMsg = self::tagLongDescriptionMessage( $tagName, $localizer );
|
||||
// Don't cache the message object, use the correct MessageLocalizer to parse later.
|
||||
$result[] = [
|
||||
|
|
@ -1263,6 +1294,7 @@ class ChangeTags {
|
|||
'label' => $labelMsg ? $labelMsg->plain() : $tagName,
|
||||
'descriptionMsg' => (bool)$descriptionMsg,
|
||||
'description' => $descriptionMsg ? $descriptionMsg->plain() : '',
|
||||
'helpLink' => $helpLink,
|
||||
'cssClass' => Sanitizer::escapeClass( 'mw-tag-' . $tagName ),
|
||||
];
|
||||
}
|
||||
|
|
|
|||
|
|
@ -204,12 +204,20 @@ class SpecialTags extends SpecialPage {
|
|||
if ( $showEditLinks ) {
|
||||
$disp .= ' ';
|
||||
$editLink = $linkRenderer->makeLink(
|
||||
$this->msg( "tag-$tag" )->inContentLanguage()->getTitle(),
|
||||
$this->msg( "tag-$tag" )->getTitle(),
|
||||
$this->msg( 'tags-edit' )->text(),
|
||||
[],
|
||||
[ 'action' => 'edit' ]
|
||||
);
|
||||
$disp .= $this->msg( 'parentheses' )->rawParams( $editLink )->escaped();
|
||||
$helpEditLink = $linkRenderer->makeLink(
|
||||
$this->msg( "tag-$tag-helppage" )->inContentLanguage()->getTitle(),
|
||||
$this->msg( 'tags-helppage-edit' )->text(),
|
||||
[],
|
||||
[ 'action' => 'edit' ]
|
||||
);
|
||||
$disp .= $this->msg( 'parentheses' )->rawParams(
|
||||
$this->getLanguage()->pipeList( [ $editLink, $helpEditLink ] )
|
||||
)->escaped();
|
||||
}
|
||||
$newRow .= Xml::tags( 'td', null, $disp );
|
||||
|
||||
|
|
|
|||
|
|
@ -1505,6 +1505,7 @@
|
|||
"rcfilters-filter-previousrevision-label": "Not the latest revision",
|
||||
"rcfilters-filter-previousrevision-description": "All changes that are not the \"latest revision\".",
|
||||
"rcfilters-filter-excluded": "Excluded",
|
||||
"rcfilters-tag-help": "More information about the \"$1\" tag",
|
||||
"rcfilters-tag-prefix-namespace": ":$1",
|
||||
"rcfilters-tag-prefix-namespace-inverted": "<strong>not</strong> :$1",
|
||||
"rcfilters-tag-prefix-tags": "#$1",
|
||||
|
|
@ -3734,7 +3735,8 @@
|
|||
"tag-hidden": "$1 (hidden tag)",
|
||||
"tag-list-wrapper": "[[Special:Tags|{{PLURAL:$1|Tag|Tags}}]]: $2",
|
||||
"tag-mw-contentmodelchange": "content model change",
|
||||
"tag-mw-contentmodelchange-description": "Edits that [https://www.mediawiki.org/wiki/Special:MyLanguage/Help:ChangeContentModel change the content model] of a page",
|
||||
"tag-mw-contentmodelchange-description": "Edits that change the content model of a page",
|
||||
"tag-mw-contentmodelchange-helppage": "https://www.mediawiki.org/wiki/Special:MyLanguage/Help:ChangeContentModel",
|
||||
"tag-mw-new-redirect": "New redirect",
|
||||
"tag-mw-new-redirect-description": "Edits that create a new redirect or change a page to a redirect",
|
||||
"tag-mw-removed-redirect": "Removed redirect",
|
||||
|
|
@ -3772,6 +3774,7 @@
|
|||
"tags-source-none": "No longer in use",
|
||||
"tags-hidden": "(hidden)",
|
||||
"tags-edit": "edit",
|
||||
"tags-helppage-edit": "edit link",
|
||||
"tags-delete": "delete",
|
||||
"tags-activate": "activate",
|
||||
"tags-deactivate": "deactivate",
|
||||
|
|
|
|||
|
|
@ -1768,6 +1768,7 @@
|
|||
"rcfilters-filter-previousrevision-label": "Title for the filter for showing changes on previous revisions of a page.",
|
||||
"rcfilters-filter-previousrevision-description": "Description for the filter for showing changes on previous revisions of a page.",
|
||||
"rcfilters-filter-excluded": "Label for a menu item in [[Special:RecentChanges]] noting that the item is being excluded from the results.",
|
||||
"rcfilters-tag-help": "Tooltip for the help button that leads user to a help page for a given tag.\n\nParameters: $1 - tag label, e.g. {{msg-mw|tag-mw-contentmodelchange}}",
|
||||
"rcfilters-tag-prefix-namespace": "Prefix for the namespace tags in [[Special:RecentChanges]]. Namespace tags use a colon (:) as prefix. Please keep this format.\n\nParameters:\n* $1 - Filter name.",
|
||||
"rcfilters-tag-prefix-namespace-inverted": "Prefix for inverted namespace tags in [[Special:RecentChanges]]. Namespace tags use a colon (:) as prefix. Please keep this format.\n\nParameters:\n* $1 - Filter name.\n{{Identical|Not}}",
|
||||
"rcfilters-tag-prefix-tags": "Prefix for the edit tags in [[Special:RecentChanges]]. Edit tags use a hash (#) as prefix. Please keep this format.\n\nParameters:\n* $1 - Tag display name.",
|
||||
|
|
@ -3998,6 +3999,7 @@
|
|||
"tag-list-wrapper": "Wrapper for the list of tags shown on recent changes, watchlists, history pages and diffs. The message will be wrapped in {{msg-mw|parentheses-start}} and {{msg-mw|parentheses-end}} if set. \n\nParameters:\n* $1 - number of distinct tags for given edit\n* $2 - comma-separated list of tags for given edit",
|
||||
"tag-mw-contentmodelchange": "Change tag for edits that change the content model of a page",
|
||||
"tag-mw-contentmodelchange-description": "Description for \"content model change\" change tag",
|
||||
"tag-mw-contentmodelchange-helppage": "{{optional}}\nHelp link for \"content model change\" change tag",
|
||||
"tag-mw-new-redirect": "Change tag for edits that make the page a redirect (either redirect creation or editing an existing page)",
|
||||
"tag-mw-new-redirect-description": "Description for \"New redirect\" change tag",
|
||||
"tag-mw-removed-redirect": "Change tag for edits that change an existing redirect into a non-redirect",
|
||||
|
|
@ -4035,6 +4037,7 @@
|
|||
"tags-source-none": "Table cell contents if given tag is no longer in use. (It was applied in the past, but it is currently not applied.)\n\nSee also:\n* {{msg-mw|Tags-source-extension}}\n* {{msg-mw|Tags-source-manual}}",
|
||||
"tags-hidden": "Table cell contents if given tag is hidden (not shown on histories, recent changes, diffs, etc.)",
|
||||
"tags-edit": "Used on [[Special:Tags]]. Verb. Used as display text on a link to create/edit a description.\n{{Identical|Edit}}",
|
||||
"tags-helppage-edit": "Used on [[Special:Tags]]. Verb. Used as display text on a link to create/edit a link to a help page.\n{{Identical|Edit}}",
|
||||
"tags-delete": "Used on [[Special:Tags]]. Verb. Used as display text on a link to delete a tag.\n{{Identical|Delete}}",
|
||||
"tags-activate": "Used on [[Special:Tags]]. Verb. Used as display text on a link to activate a tag.\n{{Identical|Activate}}",
|
||||
"tags-deactivate": "Used on [[Special:Tags]]. Verb. Used as display text on a link to deactivate a tag.\n{{Identical|Delete}}",
|
||||
|
|
|
|||
|
|
@ -1942,6 +1942,7 @@ return [
|
|||
'rcfilters-state-message-subset',
|
||||
'rcfilters-state-message-fullcoverage',
|
||||
'rcfilters-filter-excluded',
|
||||
'rcfilters-tag-help',
|
||||
'rcfilters-tag-prefix-namespace',
|
||||
'rcfilters-tag-prefix-namespace-inverted',
|
||||
'rcfilters-tag-prefix-tags',
|
||||
|
|
|
|||
|
|
@ -113,6 +113,7 @@ FilterGroup.prototype.initializeFilters = function ( filterDefinition, groupDefa
|
|||
description: filter.description || '',
|
||||
labelPrefixKey: model.labelPrefixKey,
|
||||
cssClass: filter.cssClass,
|
||||
helpLink: filter.helpLink,
|
||||
identifiers: filter.identifiers,
|
||||
defaultHighlightColor: filter.defaultHighlightColor
|
||||
} );
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@
|
|||
* @param {string} [config.namePrefix='item_'] A prefix to add to the param name to act as a unique
|
||||
* identifier
|
||||
* @param {string} [config.cssClass] The class identifying the results that match this filter
|
||||
* @param {string|null} [config.helpLink] Link to a help page for this filter
|
||||
* @param {string[]} [config.identifiers] An array of identifiers for this item. They will be
|
||||
* added and considered in the view.
|
||||
* @param {string} [config.defaultHighlightColor=null] If set, highlight this filter by default with this color
|
||||
|
|
@ -41,6 +42,7 @@ var ItemModel = function MwRcfiltersDmItemModel( param, config ) {
|
|||
|
||||
// Highlight
|
||||
this.cssClass = config.cssClass;
|
||||
this.helpLink = config.helpLink;
|
||||
this.highlightColor = config.defaultHighlightColor || null;
|
||||
};
|
||||
|
||||
|
|
@ -245,6 +247,16 @@ ItemModel.prototype.getCssClass = function () {
|
|||
return this.cssClass;
|
||||
};
|
||||
|
||||
/**
|
||||
* Get a link to a help page for this filter
|
||||
* or null if none is configured
|
||||
*
|
||||
* @return {string|null}
|
||||
*/
|
||||
ItemModel.prototype.getHelpLink = function () {
|
||||
return this.helpLink;
|
||||
};
|
||||
|
||||
/**
|
||||
* Get the item's identifiers
|
||||
*
|
||||
|
|
|
|||
|
|
@ -71,15 +71,13 @@
|
|||
|
||||
.mw-rcfilters-ui-cell {
|
||||
align-self: center;
|
||||
|
||||
> * {
|
||||
margin-left: 1em;
|
||||
}
|
||||
}
|
||||
|
||||
&-excludeLabel {
|
||||
width: 5em;
|
||||
padding-left: 1em;
|
||||
color: @color-subtle;
|
||||
}
|
||||
|
||||
&-highlightButton {
|
||||
padding-left: 1em;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -58,6 +58,19 @@ ItemMenuOptionWidget = function MwRcfiltersUiItemMenuOptionWidget(
|
|||
);
|
||||
}
|
||||
|
||||
this.helpLink = null;
|
||||
if ( this.itemModel.getHelpLink() ) {
|
||||
this.helpLink = new OO.ui.ButtonWidget( {
|
||||
icon: 'helpNotice',
|
||||
framed: false,
|
||||
title: mw.msg( 'rcfilters-tag-help', this.itemModel.getLabel() ),
|
||||
href: this.itemModel.getHelpLink(),
|
||||
target: '_blank'
|
||||
} );
|
||||
// Prevent clicks on the help link from toggling the option
|
||||
this.helpLink.$button.on( 'mousedown', ( e ) => e.stopPropagation() );
|
||||
}
|
||||
|
||||
this.highlightButton = new FilterItemHighlightButton(
|
||||
this.controller,
|
||||
this.itemModel,
|
||||
|
|
@ -108,6 +121,13 @@ ItemMenuOptionWidget = function MwRcfiltersUiItemMenuOptionWidget(
|
|||
)
|
||||
);
|
||||
|
||||
if ( this.helpLink ) {
|
||||
$widgetRow.find( '.mw-rcfilters-ui-row' ).append(
|
||||
$( '<div>' )
|
||||
.addClass( 'mw-rcfilters-ui-cell mw-rcfilters-ui-itemMenuOptionWidget-helpLink' )
|
||||
.append( this.helpLink.$element )
|
||||
);
|
||||
}
|
||||
if ( !OO.ui.isMobile() ) {
|
||||
$widgetRow.find( '.mw-rcfilters-ui-row' ).append(
|
||||
$( '<div>' )
|
||||
|
|
|
|||
Loading…
Reference in a new issue