Page MenuHomePhabricator

Allow to hide translations on special page "WhatLinksHere"
Closed, ResolvedPublic4 Estimated Story PointsFeature

Assigned To
Authored By
Kghbln
Feb 17 2019, 5:57 PM
Referenced Files
F57639884: 2024-10-24_09-15-19.png
Thu, Oct 24, 4:21 PM
F57639881: 2024-10-24_09-15-00.png
Thu, Oct 24, 4:21 PM
F57639874: 2024-10-24_09-14-26.mp4.gif
Thu, Oct 24, 4:21 PM
F57531832: image.png
Sep 23 2024, 12:33 PM
F57531815: image.png
Sep 23 2024, 12:26 PM
F57531805: image.png
Sep 23 2024, 12:26 PM
Tokens
"Love" token, awarded by Michael."Love" token, awarded by Kghbln."Love" token, awarded by Aklapper.

Description

Setup

  • MediaWiki 1.33.0-wmf.17 (rMW484a1d08a285) 21:23, 14 February 2019
  • Translate 2018-11-05 (9484763) 23:28, 11 February 2019

Issue
The number of links to translated pages may get overwhelming when using special page "WhatLinksHere". See this example. Thus it will be nice to have a filter "Show/Hide translations" with hide translations enabled be default.

Derived Requirement

Add a filter option "Show/Hide translations" to the special page "WhatLinksHere" that allows users to hide links to translated pages by default, reducing the overwhelming number of translated links displayed.

BDD

gherkin
Feature: Hide Translations Filter on Special:WhatLinksHere

Scenario: Filter to hide translated pages on Special:WhatLinksHere
  Given the user is on the Special:WhatLinksHere page
  And there are links to translated pages
  When the user applies the "Hide translations" filter
  Then the translated pages should be hidden from the list by default
  And the user should be able to toggle the filter to show translations again if needed

Test Result - Translatewiki

Status: ✅ PASS / ❓Need More Info / ❌ FAIL
Environment: Translatewiki
OS: macOS Sonoma 15.0
Browser: Chrome 130
Device: MBA
Emulated Device: NA

Test Artifact(s):

Test Steps

Test Case 1: Ensure Translations Can Be Hidden on Special:WhatLinksHere

  1. Navigate to the Special:WhatLinksHere page on any wiki with multiple translations.
  2. Observe that the filter option "Show/Hide translations" is available, with "Hide translations" enabled by default.
  3. ✅❓❌⬜ AC1: Confirm that the translated pages are hidden by default when the filter is applied.
  4. Toggle the filter to "Show translations."
  5. ✅❓❌⬜ AC2: Confirm that the translated pages are visible when the filter is toggled to show translations.

QA Results - Translatewiki

ACStatusDetails
1T216368#10259628
2T216368#10259628

Event Timeline

Nikerabbit subscribed.

There is one hook in Special:WhatLinksHere and that cannot be used to implement this feature in the Translate extension. Moving to "cross projects" column because I cannot set the priority.

There is one hook in Special:WhatLinksHere and that cannot be used to implement this feature in the Translate extension. Moving to "cross projects" column because I cannot set the priority.

Thanks for the note. Ultimately it will be good to be able to even select a specific language to be shown but I guess on step at a time is the best approach.

Okay, so, assuming hooks can be used to allow this, there needs to be a way to detect page translations via sql.
Currently, the logic for detecting them to prevent direct editing is:

PageTranslationHooks::preventDirectEditing
[...]
$page = TranslatablePage::isTranslationPage( $title );
if ( $page !== false && $page->getMarkedTag() ) {
	[...]
	return false;
}
return true;
TranslatablePage::isTranslationPage
public static function isTranslationPage( Title $title ) {
	$handle = new MessageHandle( $title );
	$key = $handle->getKey();
	$code = $handle->getCode();
	if ( $key === '' || $code === '' ) {
		return false;
	}
	$codes = Language::fetchLanguageNames();
	global $wgTranslateDocumentationLanguageCode;
	unset( $codes[$wgTranslateDocumentationLanguageCode] );
	if ( !isset( $codes[$code] ) ) {
		return false;
	}
	$newtitle = self::changeTitleText( $title, $key );
	if ( !$newtitle ) {
		return false;
	}
	$page = self::newFromTitle( $newtitle );
	if ( $page->getMarkedTag() === false ) {
		return false;
	}
	return $page;
}
MessageHandle::__construct
public function __construct( Title $title ) {
	$this->title = $title;
}

A bad way to try and add sql filtering would be to ensure that the page title doesn't end with a language code, but that would also exclude translations that are not a part of the translate system.

If it need to be done with SQL, perhaps setting a prop in page_props (or revtag) could make it fast and accurate enough?

Nikerabbit changed the subtype of this task from "Task" to "Feature Request".Nov 23 2020, 3:14 PM

Implementing this (to reduce that long output list) would help a lot with updating now defunct anchor links pointing to restructured documentation pages (random example), and finding links on mediawiki.org pointing to removed function doc pages in MW Core (random example).

Change #1071145 had a related patch set uploaded (by Huei Tan; author: Huei Tan):

[mediawiki/extensions/Translate@master] WhatLinksHere: Add hide translations checkbox

https://gerrit.wikimedia.org/r/1071145

abi_ triaged this task as Medium priority.Sep 10 2024, 11:57 AM
abi_ set the point value for this task to 4.

Change #1073191 had a related patch set uploaded (by Huei Tan; author: Huei Tan):

[mediawiki/core@master] WhatLinksHere: Add hook runner to filter some rows

https://gerrit.wikimedia.org/r/1073191

The request is to hide the translation page. Should we also hide the translation units on this page?

There is namespace and an "invert selection" checkbox available, so I would suggest that the "hide translation" checkbox should not filter them to avoid confusion.

Translation units availableInvert the translation units namespace
image.png (1×1 px, 334 KB)
image.png (724×1 px, 87 KB)

hide translations enabled be default.

Due to the way the form and URL parameters are implemented, it appears unchecked by default, meaning "show translation" is actually active by default. We could change the label to "show translation" (so the default behavior is to hide translations), but since all the other checkboxes default to "hide", I propose we keep "hide translation" as the checkbox for consistency. Users can easily check the "hide translation" box if they wish to hide them.

We can either

  1. "show translation" unchecked by default to have translation page hidden; or
  2. "hide translation" unchecked by default for consistency;

image.png (594×1 px, 54 KB)

Change #1078638 had a related patch set uploaded (by Abijeet Patro; author: Abijeet Patro):

[mediawiki/core@master] SpecialWhatLinksHere: Replace FormOptions with request data in an array

https://gerrit.wikimedia.org/r/1078638

Normal query

SELECT
	page_id,
	page_namespace,
	page_title,
	rd_from,
	rd_fragment,
	page_is_redirect
FROM
	(
	SELECT
		pl_from,
		rd_from,
		rd_fragment
	FROM
		`pagelinks`
	LEFT JOIN `redirect` ON
		((rd_from = pl_from)
			AND rd_title = 'Main_Page'
			AND rd_namespace = 0
			AND rd_interwiki = '')
	WHERE
		pl_target_id = 12
		AND pl_from_namespace IN (0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 470, 471, 828, 829, 1100, 1101, 1198, 1199)
	ORDER BY
		pl_from_namespace ASC,
		pl_from ASC
	LIMIT 102 ) `temp_backlink_range`
JOIN `page` ON
	((pl_from = page_id))
ORDER BY
	page_namespace ASC,
	page_id ASC
LIMIT 51

Query plan on Meta-Wiki, retrieved using EXPLAIN:

+------+-------------+------------+--------+-----------------------------------------------+----------------------------------+---------+-----------------------------+------+---------------------------------+
| id   | select_type | table      | type   | possible_keys                                 | key                              | key_len | ref                         | rows | Extra                           |
+------+-------------+------------+--------+-----------------------------------------------+----------------------------------+---------+-----------------------------+------+---------------------------------+
|    1 | PRIMARY     | <derived2> | ALL    | NULL                                          | NULL                             | NULL    | NULL                        | 2    | Using temporary; Using filesort |
|    1 | PRIMARY     | page       | eq_ref | PRIMARY                                       | PRIMARY                          | 4       | temp_backlink_range.pl_from | 1    |                                 |
|    2 | DERIVED     | pagelinks  | range  | pl_target_id,pl_backlinks_namespace_target_id | pl_backlinks_namespace_target_id | 12      | NULL                        | 39   | Using where; Using index        |
|    2 | DERIVED     | redirect   | eq_ref | PRIMARY,rd_ns_title                           | PRIMARY                          | 4       | metawiki.pagelinks.pl_from  | 1    | Using where                     |
+------+-------------+------------+--------+-----------------------------------------------+----------------------------------+---------+-----------------------------+------+---------------------------------+

Query with the "Hide translation" filter selected

SELECT
	page_id,
	page_namespace,
	page_title,
	rd_from,
	rd_fragment,
	page_is_redirect
FROM
	(
	SELECT
		pl_from,
		rd_from,
		rd_fragment
	FROM
		`pagelinks`
	LEFT JOIN `redirect` ON
		((rd_from = pl_from)
			AND rd_title = 'Main_Page'
			AND rd_namespace = 0
			AND rd_interwiki = '')
	WHERE
		pl_target_id = 12
		AND pl_from_namespace IN (0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 470, 471, 828, 829, 1100, 1101, 1198, 1199)
	ORDER BY
		pl_from_namespace ASC,
		pl_from ASC
	LIMIT 102 ) `temp_backlink_range`
JOIN `page` ON
	((pl_from = page_id))
LEFT JOIN `page_props` `translate_pp` ON
	((translate_pp.pp_page = page_id)
		AND translate_pp.pp_propname = 'translate-is-translation')
WHERE
	translate_pp.pp_value IS NULL
ORDER BY
	page_namespace ASC,
	page_id ASC
LIMIT 51

The query returned 21 rows and took 0.018 seconds to run with a stale buffer pool cache.

Query plan on Meta-Wiki:

+------+-------------+--------------+--------+---------------------------------------------------+----------------------------------+---------+-----------------------------------+------+---------------------------------+
| id   | select_type | table        | type   | possible_keys                                     | key                              | key_len | ref                               | rows | Extra                           |
+------+-------------+--------------+--------+---------------------------------------------------+----------------------------------+---------+-----------------------------------+------+---------------------------------+
|    1 | PRIMARY     | <derived2>   | ALL    | NULL                                              | NULL                             | NULL    | NULL                              | 2    | Using temporary; Using filesort |
|    1 | PRIMARY     | page         | eq_ref | PRIMARY                                           | PRIMARY                          | 4       | temp_backlink_range.pl_from       | 1    |                                 |
|    1 | PRIMARY     | translate_pp | eq_ref | PRIMARY,pp_propname_page,pp_propname_sortkey_page | PRIMARY                          | 66      | temp_backlink_range.pl_from,const | 1    | Using where; Not exists         |
|    2 | DERIVED     | pagelinks    | range  | pl_target_id,pl_backlinks_namespace_target_id     | pl_backlinks_namespace_target_id | 12      | NULL                              | 39   | Using where; Using index        |
|    2 | DERIVED     | redirect     | eq_ref | PRIMARY,rd_ns_title                               | PRIMARY                          | 4       | metawiki.pagelinks.pl_from        | 1    | Using where                     |
+------+-------------+--------------+--------+---------------------------------------------------+----------------------------------+---------+-----------------------------------+------+---------------------------------+

Ran this query on Meta-Wiki to see the impact.

Performance looks OK.

The risk scenarios here are:

  • You would have a lot of pages, like in order of millions, and only a handful of non-translation pages, this could become slow but the chance of it happening is really low.
  • Adding more joins, after five or six starts to become hard for mariadb to find the correct join order and that's why we have a lot of "straight join" hints all over the code. It's not that adding one more join here is bad, it's that if it reaches joining of a lot of tables, then mariadb starts to act stupid.

Both are quite minor so it looks good to me! If you want to make sure everything is alright, get the change deployed and then check slow queries dashboard after a week.

Change #1078638 merged by jenkins-bot:

[mediawiki/core@master] SpecialWhatLinksHere: Replace FormOptions with request data in an array

https://gerrit.wikimedia.org/r/1078638

Change #1073191 merged by jenkins-bot:

[mediawiki/core@master] WhatLinksHere: Allow extensible filters

https://gerrit.wikimedia.org/r/1073191

Change #1071145 merged by jenkins-bot:

[mediawiki/extensions/Translate@master] WhatLinksHere: Add translation page filter

https://gerrit.wikimedia.org/r/1071145

@hueitan Can you please review AC1 gif since hide translations is not enabled be default, thanks!

Test Result - Translatewiki

Status: ❌ AC1
Environment: Translatewiki
OS: macOS Sonoma 15.0
Browser: Chrome 130
Device: MBA
Emulated Device: NA

Test Artifact(s):

https://translatewiki.net/wiki/Special:WhatLinksHere?target=FAQ&namespace=&translate-hidetranslations=1&limit=50
https://translatewiki.net/wiki/Special:WhatLinksHere?target=FAQ&namespace=&limit=50

Test Steps

Test Case 1: Ensure Translations Can Be Hidden on Special:WhatLinksHere

  1. Navigate to the Special:WhatLinksHere page on any wiki with multiple translations.
  2. Observe that the filter option "Show/Hide translations" is available, with "Hide translations" enabled by default.
  3. AC1: Confirm that the translated pages are hidden by default when the filter is applied.

Hide translation is NOT enabled by default as seen in the gif below

2024-10-24_09-14-26.mp4.gif (910×1 px, 722 KB)

  1. Toggle the filter to "Show translations."
  2. AC2: Confirm that the translated pages are visible when the filter is toggled to show translations.
Disable Hide Translation pagesEnable Hide Translation pages
2024-10-24_09-15-00.png (876×1 px, 188 KB)
2024-10-24_09-15-19.png (834×1 px, 172 KB)
GMikesell-WMF changed the task status from Open to In Progress.Thu, Oct 24, 4:22 PM
GMikesell-WMF updated the task description. (Show Details)
abi_ moved this task from In Progress to Done on the LPL Essential (LPL Essential 2024 Jul-Oct) board.

@GMikesell-WMF Thanks for the QA on this.

While the original task description says: hide translations should be enabled be default, with the current hooks that we use in the code this would be difficult to implement cleanly. The easiest way would be to rename "hide translations" option to "show translations" and load the translations when "show translations" option is selected.

Considering that we've already had quite a bit of technical scope creep in the task, I will mark this task as done. If users want translations to be hidden by default, please create a separate task.