jenkins-bot has submitted this change and it was merged.
Change subject: Split language details to subpage on Special:SupportedLanguages
......................................................................
Split language details to subpage on Special:SupportedLanguages
This is the only way I was able to make this page fast enough:
* We scan almost all of the page table
* We only pick up titles in translation namespaces
* We only pick up titles having subpage of requested language code
* We check all revisions of those pages and give one score for each
rev_user_text for those
We could further limit the scans by only checking latest version of
each page.
However, given that editcount is a better measure of translation
activity than "edits on the tip of history", and that translation unit
pages usually do not have that long a history, I did not think that
necessary.
The language cloud is still output at the top of each page for easy
navigation.
$wgTranslateAuthorBlacklist is now applied to the list of translators.
Removed the html-output caching as the generation of the pages is now
fast enough: it is not generating tens of thousands of links, which
alone used to take multiple seconds.
The NS_PORTAL way of fetching translators is removed. Even though it was
faster on translatewiki.net, now the general method is fast enough and
gives good data.
Portal pages are not regularly updated anymore and gave stale data.
Issues were caused on wikis where NS_PORTAL namespace is defined
but is not used as in translatewiki.net.
Bug: T54728
Change-Id: I071b806a08d78e01bfe05bccfcbdb5e5d73220f4
---
M specials/SpecialSupportedLanguages.php
1 file changed, 89 insertions(+), 148 deletions(-)
Approvals:
Amire80: Looks good to me, approved
jenkins-bot: Verified
diff --git a/specials/SpecialSupportedLanguages.php
b/specials/SpecialSupportedLanguages.php
index d70f7d2..030ad18 100644
--- a/specials/SpecialSupportedLanguages.php
+++ b/specials/SpecialSupportedLanguages.php
@@ -39,24 +39,6 @@
$this->setHeaders();
$out->addModules( 'ext.translate.special.supportedlanguages' );
- // Do not add html content to OutputPage before this block of
code!
- $cache = wfGetCache( CACHE_ANYTHING );
- $cachekey = wfMemcKey( 'translate-supportedlanguages',
$lang->getCode() );
- if ( $this->purge ) {
- $cache->delete( $cachekey );
- } else {
- $data = $cache->get( $cachekey );
- if ( is_string( $data ) ) {
- TranslateUtils::addSpecialHelpLink(
- $out,
-
'Help:Extension:Translate/Statistics_and_reporting#List_of_languages_and_translators'
- );
- $out->addHtml( $data );
-
- return;
- }
- }
-
TranslateUtils::addSpecialHelpLink(
$out,
'Help:Extension:Translate/Statistics_and_reporting#List_of_languages_and_translators'
@@ -70,29 +52,35 @@
return;
}
- $out->addWikiMsg( 'supportedlanguages-colorlegend',
$this->getColorLegend() );
$out->addWikiMsg( 'supportedlanguages-localsummary' );
- // Check if CLDR extension has been installed.
- $cldrInstalled = class_exists( 'LanguageNames' );
- $locals = Language::fetchLanguageNames( $lang->getCode(), 'all'
);
- $natives = Language::fetchLanguageNames( null, 'all' );
+ $names = Language::fetchLanguageNames( null, 'all' );
+ $languages = $this->languageCloud();
+ // There might be all sorts of subpages which are not languages
+ $languages = array_intersect_key( $languages, $names );
- $this->outputLanguageCloud( $natives );
+ $this->outputLanguageCloud( $languages, $names );
+ $out->addWikiMsg( 'supportedlanguages-count', $lang->formatNum(
count( $languages ) ) );
- if ( !defined( 'NS_PORTAL' ) ) {
- $users = $this->fetchTranslatorsAuto();
- } else {
- $users = $this->fetchTranslatorsPortal( $natives );
+ if ( $par && Language::isKnownLanguageTag( $par ) ) {
+ $code = $par;
+
+ $out->addWikiMsg( 'supportedlanguages-colorlegend',
$this->getColorLegend() );
+
+ $users = $this->fetchTranslators( $code );
+
+ global $wgTranslateAuthorBlacklist;
+ $users = $this->filterUsers( $users, $code,
$wgTranslateAuthorBlacklist );
+ $this->preQueryUsers( $users );
+ $this->showLanguage( $code, $users );
}
+ }
- if ( $users === array() ) {
- return;
- }
+ protected function showLanguage( $code, $users ) {
+ $out = $this->getOutput();
+ $lang = $this->getLanguage();
- $this->preQueryUsers( $users );
-
- $usernames = array_keys( call_user_func_array( 'array_merge',
array_values( $users ) ) );
+ $usernames = array_keys( $users );
$userStats = $this->getUserStats( $usernames );
// Information to be used inside the foreach loop.
@@ -101,65 +89,46 @@
$linkInfo['stats']['title'] = SpecialPage::getTitleFor(
'LanguageStats' );
$linkInfo['stats']['msg'] = $this->msg( 'languagestats'
)->escaped();
- foreach ( array_keys( $natives ) as $code ) {
- if ( !isset( $users[$code] ) ) {
- continue;
- }
+ $local = Language::fetchLanguageName( $code, $lang->getCode(),
'all' );
+ $native = Language::fetchLanguageName( $code, null, 'all' );
- // If CLDR is installed, add localised header and link
title.
- if ( $cldrInstalled ) {
- $headerText = $this->msg(
'supportedlanguages-portallink' )
- ->params( $code, $locals[$code],
$natives[$code] )->escaped();
- } else {
- // No CLDR, so a less localised header and link
title.
- $headerText = $this->msg(
'supportedlanguages-portallink-nocldr' )
- ->params( $code, $natives[$code]
)->escaped();
- }
-
- $headerText = htmlspecialchars( $headerText );
-
- $out->addHtml( Html::openElement( 'h2', array( 'id' =>
$code ) ) );
- if ( defined( 'NS_PORTAL' ) ) {
- $portalTitle = Title::makeTitleSafe( NS_PORTAL,
$code );
- $out->addHtml( Linker::linkKnown( $portalTitle,
$headerText ) );
- } else {
- $out->addHtml( $headerText );
- }
-
- $out->addHTML( "</h2>" );
-
- // Add useful links for language stats and recent
changes for the language.
- $links = array();
- $links[] = Linker::link(
- $linkInfo['stats']['title'],
- $linkInfo['stats']['msg'],
- array(),
- array(
- 'code' => $code,
- 'suppresscomplete' => '1'
- ),
- array( 'known', 'noclasses' )
- );
- $links[] = Linker::link(
- $linkInfo['rc']['title'],
- $linkInfo['rc']['msg'],
- array(),
- array(
- 'translations' => 'only',
- 'trailer' => "/" . $code
- ),
- array( 'known', 'noclasses' )
- );
- $linkList = $lang->listToText( $links );
-
- $out->addHTML( "<p>" . $linkList . "</p>\n" );
- $this->makeUserList( $users[$code], $userStats );
+ if ( $local !== $native ) {
+ $headerText = $this->msg(
'supportedlanguages-portallink' )
+ ->params( $code, $local, $native )->escaped();
+ } else {
+ // No CLDR, so a less localised header and link title.
+ $headerText = $this->msg(
'supportedlanguages-portallink-nocldr' )
+ ->params( $code, $native )->escaped();
}
- $out->addHtml( Html::element( 'hr' ) );
- $out->addWikiMsg( 'supportedlanguages-count', $lang->formatNum(
count( $users ) ) );
+ $out->addHtml( Html::rawElement( 'h2', array( 'id' => $code ),
$headerText ) );
- $cache->set( $cachekey, $out->getHTML(), 3600 );
+ // Add useful links for language stats and recent changes for
the language.
+ $links = array();
+ $links[] = Linker::link(
+ $linkInfo['stats']['title'],
+ $linkInfo['stats']['msg'],
+ array(),
+ array(
+ 'code' => $code,
+ 'suppresscomplete' => '1'
+ ),
+ array( 'known', 'noclasses' )
+ );
+ $links[] = Linker::link(
+ $linkInfo['rc']['title'],
+ $linkInfo['rc']['msg'],
+ array(),
+ array(
+ 'translations' => 'only',
+ 'trailer' => "/" . $code
+ ),
+ array( 'known', 'noclasses' )
+ );
+ $linkList = $lang->listToText( $links );
+
+ $out->addHTML( "<p>" . $linkList . "</p>\n" );
+ $this->makeUserList( $users, $userStats );
}
protected function languageCloud() {
@@ -200,11 +169,11 @@
return $data;
}
- protected function fetchTranslatorsAuto() {
+ protected function fetchTranslators( $code ) {
global $wgTranslateMessageNamespaces;
$cache = wfGetCache( CACHE_ANYTHING );
- $cachekey = wfMemcKey(
'translate-supportedlanguages-translator-list' );
+ $cachekey = wfMemcKey(
'translate-supportedlanguages-translator-list', $code );
if ( $this->purge ) {
$cache->delete( $cachekey );
} else {
@@ -218,21 +187,20 @@
$tables = array( 'page', 'revision' );
$fields = array(
'rev_user_text',
- 'substring_index(page_title, \'/\', -1) as lang',
'count(page_id) as count'
);
$conds = array(
- 'page_title' . $dbr->buildLike( $dbr->anyString(), '/',
$dbr->anyString() ),
+ 'page_title' . $dbr->buildLike( $dbr->anyString(), '/',
$code ),
'page_namespace' => $wgTranslateMessageNamespaces,
'page_id=rev_page',
);
- $options = array( 'GROUP BY' => 'rev_user_text, lang' );
+ $options = array( 'GROUP BY' => 'rev_user_text' );
$res = $dbr->select( $tables, $fields, $conds, __METHOD__,
$options );
$data = array();
foreach ( $res as $row ) {
- $data[$row->lang][$row->rev_user_text] = $row->count;
+ $data[$row->rev_user_text] = $row->count;
}
$cache->set( $cachekey, $data, 3600 );
@@ -240,69 +208,44 @@
return $data;
}
- public function fetchTranslatorsPortal( $natives ) {
- $titles = array();
- foreach ( $natives as $code => $_ ) {
- $titles[] = Title::capitalize( $code, NS_PORTAL ) .
'/translators';
- }
+ protected function filterUsers( array $users, $code, $blacklist ) {
+ foreach ( array_keys( $users ) as $username ) {
+ # We do not know the group
+ $hash = "#;$code;$username";
- $dbr = wfGetDB( DB_SLAVE );
- $tables = array( 'page', 'revision', 'text' );
- $vars = array_merge(
- Revision::selectTextFields(),
- Revision::selectPageFields(),
- Revision::selectFields()
- );
- $conds = array(
- 'page_latest = rev_id',
- 'rev_text_id = old_id',
- 'page_namespace' => NS_PORTAL,
- 'page_title' => $titles,
- );
+ $blacklisted = false;
+ foreach ( $blacklist as $rule ) {
+ list( $type, $regex ) = $rule;
- $res = $dbr->select( $tables, $vars, $conds, __METHOD__ );
-
- $users = array();
- $lc = LinkCache::singleton();
-
- foreach ( $res as $row ) {
- $title = Title::newFromRow( $row );
- // Does not contain page_content_model, but should not
matter
- $lc->addGoodLinkObjFromRow( $title, $row );
-
- $rev = Revision::newFromRow( $row );
- $text = ContentHandler::getContentText(
$rev->getContent() );
- $code = strtolower( preg_replace( '!/translators$!',
'', $row->page_title ) );
-
- preg_match_all( '!{{[Uu]ser\|([^}|]+)!', $text,
$matches, PREG_SET_ORDER );
- foreach ( $matches as $match ) {
- $user = Title::capitalize( $match[1], NS_USER );
- if ( !isset( $users[$code] ) ) {
- $users[$code] = array();
+ if ( preg_match( $regex, $hash ) ) {
+ if ( $type === 'white' ) {
+ $blacklisted = false;
+ break;
+ } else {
+ $blacklisted = true;
+ }
}
- $users[$code][strtr( $user, '_', ' ' )] = -1;
+ }
+
+ if ( $blacklisted ) {
+ unset( $users[$username] );
}
}
return $users;
}
- protected function outputLanguageCloud( $names ) {
+ protected function outputLanguageCloud( array $languages, array $names
) {
$out = $this->getOutput();
- $langs = $this->languageCloud();
$out->addHtml( '<div class="tagcloud autonym">' );
- $langs = $this->shuffle_assoc( $langs );
- foreach ( $langs as $k => $v ) {
- if ( !isset( $names[$k] ) ) {
- // All sorts of incorrect languages may turn up
- continue;
- }
+ $langs = $this->shuffle_assoc( $languages );
+ foreach ( $languages as $k => $v ) {
$name = $names[$k];
$size = round( log( $v ) * 20 ) + 10;
$params = array(
- 'href' => "#$k",
+ 'href' => $this->getPageTitle( $k
)->getLocalUrl(),
'class' => 'tag',
'style' => "font-size:$size%",
'lang' => $k,
@@ -435,12 +378,10 @@
protected function preQueryUsers( $users ) {
$lb = new LinkBatch;
- foreach ( $users as $translators ) {
- foreach ( $translators as $user => $count ) {
- $user = Title::capitalize( $user, NS_USER );
- $lb->add( NS_USER, $user );
- $lb->add( NS_USER_TALK, $user );
- }
+ foreach ( $users as $user => $count ) {
+ $user = Title::capitalize( $user, NS_USER );
+ $lb->add( NS_USER, $user );
+ $lb->add( NS_USER_TALK, $user );
}
$lb->execute();
}
--
To view, visit https://gerrit.wikimedia.org/r/189228
To unsubscribe, visit https://gerrit.wikimedia.org/r/settings
Gerrit-MessageType: merged
Gerrit-Change-Id: I071b806a08d78e01bfe05bccfcbdb5e5d73220f4
Gerrit-PatchSet: 5
Gerrit-Project: mediawiki/extensions/Translate
Gerrit-Branch: master
Gerrit-Owner: Nikerabbit <[email protected]>
Gerrit-Reviewer: Amire80 <[email protected]>
Gerrit-Reviewer: Nikerabbit <[email protected]>
Gerrit-Reviewer: jenkins-bot <>
_______________________________________________
MediaWiki-commits mailing list
[email protected]
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits