summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'MLEB/UniversalLanguageSelector/includes/UniversalLanguageSelectorHooks.php')
-rw-r--r--MLEB/UniversalLanguageSelector/includes/UniversalLanguageSelectorHooks.php576
1 files changed, 576 insertions, 0 deletions
diff --git a/MLEB/UniversalLanguageSelector/includes/UniversalLanguageSelectorHooks.php b/MLEB/UniversalLanguageSelector/includes/UniversalLanguageSelectorHooks.php
new file mode 100644
index 00000000..647a401d
--- /dev/null
+++ b/MLEB/UniversalLanguageSelector/includes/UniversalLanguageSelectorHooks.php
@@ -0,0 +1,576 @@
+<?php
+/**
+ * Hooks for UniversalLanguageSelector extension.
+ *
+ * Copyright (C) 2012-2018 Alolita Sharma, Amir Aharoni, Arun Ganesh, Brandon
+ * Harris, Niklas Laxström, Pau Giner, Santhosh Thottingal, Siebrand Mazeland
+ * and other contributors. See CREDITS for a list.
+ *
+ * UniversalLanguageSelector is dual licensed GPLv2 or later and MIT. You don't
+ * have to do anything special to choose one license or the other and you don't
+ * have to notify anyone which license you are using. You are free to use
+ * UniversalLanguageSelector in commercial projects as long as the copyright
+ * header is left intact. See files GPL-LICENSE and MIT-LICENSE for details.
+ *
+ * @file
+ * @ingroup Extensions
+ * @license GPL-2.0-or-later
+ * @license MIT
+ */
+
+use MediaWiki\MediaWikiServices;
+
+class UniversalLanguageSelectorHooks {
+
+ /**
+ * Used when extension registration in use which skips the main php file
+ */
+ public static function setVersionConstant() {
+ global $wgHooks;
+ define( 'ULS_VERSION', '2020-07-20' );
+ // The SkinAfterPortlet hook was introduced in version >= 1.35.
+ // It is the same as BaseTemplateAfterPortlet with the exception of its parameters.
+ if ( interface_exists( MediaWiki\Skins\Hook\SkinAfterPortletHook::class ) ) {
+ $wgHooks['SkinAfterPortlet'][] = "UniversalLanguageSelectorHooks::onSkinAfterPortlet";
+ } else {
+ $wgHooks['BaseTemplateAfterPortlet'][] = "UniversalLanguageSelectorHooks::onBaseTemplateAfterPortlet";
+ }
+ }
+
+ /**
+ * Whether ULS user toolbar (language selection and settings) is enabled.
+ *
+ * @param User $user
+ * @return bool
+ */
+ private static function isToolbarEnabled( User $user ) {
+ global $wgULSEnable, $wgULSEnableAnon;
+
+ if ( !$wgULSEnable ) {
+ return false;
+ }
+ if ( !$wgULSEnableAnon && $user->isAnon() ) {
+ return false;
+ }
+
+ return true;
+ }
+
+ /**
+ * Whether ULS Compact interlanguage links enabled
+ *
+ * @param User $user
+ * @return bool
+ */
+ private static function isCompactLinksEnabled( User $user ) {
+ global $wgULSEnable, $wgInterwikiMagic,
+ $wgULSCompactLinksEnableAnon,
+ $wgHideInterlanguageLinks, $wgULSCompactLanguageLinksBetaFeature;
+
+ // Whether any user visible features are enabled
+ if ( !$wgULSEnable ) {
+ return false;
+ }
+
+ if ( $user->isAnon() && $wgULSCompactLinksEnableAnon ) {
+ return true;
+ }
+
+ if ( $wgULSCompactLanguageLinksBetaFeature === true &&
+ $wgInterwikiMagic === true &&
+ $wgHideInterlanguageLinks === false &&
+ ExtensionRegistry::getInstance()->isLoaded( 'BetaFeatures' ) &&
+ BetaFeatures::isFeatureEnabled( $user, 'uls-compact-links' )
+ ) {
+ // Compact language links is a beta feature in this wiki. Check the user's
+ // preference.
+ return true;
+ }
+
+ if ( $wgULSCompactLanguageLinksBetaFeature === false ) {
+ // Compact language links is a default feature in this wiki.
+ // Check user preference
+ return $user->getBoolOption( 'compact-language-links' );
+ }
+
+ return false;
+ }
+
+ /**
+ * Sets user preference to enable the Compact language links if the
+ * user account is new.
+ *
+ * To be removed once no longer needed.
+ * @param User $user
+ * @param bool $autoCreate
+ */
+ public static function onLocalUserCreated( User $user, $autoCreate ) {
+ if ( RequestContext::getMain()->getConfig()->get( 'ULSCompactLinksForNewAccounts' ) ) {
+ $user->setOption( 'compact-language-links', 1 );
+ $user->saveSettings();
+ }
+ }
+
+ /**
+ * @param OutputPage $out
+ * @param Skin $skin
+ * Hook: BeforePageDisplay
+ */
+ public static function addModules( OutputPage $out, $skin ) {
+ global $wgULSPosition, $wgULSGeoService;
+
+ // Soft dependency to Wikibase client. Don't enable CLL if links are managed manually.
+ $excludedLinks = $out->getProperty( 'noexternallanglinks' );
+ $override = is_array( $excludedLinks ) && in_array( '*', $excludedLinks );
+ if ( !$override && self::isCompactLinksEnabled( $out->getUser() ) ) {
+ $out->addModules( 'ext.uls.compactlinks' );
+ }
+
+ if ( is_string( $wgULSGeoService ) ) {
+ $out->addModules( 'ext.uls.geoclient' );
+ }
+
+ if ( self::isToolbarEnabled( $out->getUser() ) ) {
+ // Enable UI language selection for the user.
+ $out->addModules( 'ext.uls.interface' );
+ }
+
+ // This is added here, and not in addConfig to allow skins and extensions to vary it
+ // For example, ContentTranslation special pages depend on being able to change it.
+ $out->addJsConfigVars( 'wgULSPosition', $wgULSPosition );
+ if ( $wgULSPosition === 'personal' ) {
+ $out->addModuleStyles( 'ext.uls.pt' );
+ } else {
+ $out->addModuleStyles( 'ext.uls.interlanguage' );
+ }
+
+ if ( $out->getTitle()->isSpecial( 'Preferences' ) ) {
+ $out->addModuleStyles( 'ext.uls.preferencespage' );
+ }
+
+ self::handleSetLang( $out );
+ }
+
+ /**
+ * Handle setlang query parameter; and decide if the setlang related scripts
+ * have to be loaded.
+ * @param OutputPage $out
+ * @return void
+ */
+ protected static function handleSetLang( OutputPage $out ): void {
+ $languageToSet = self::getSetLang( $out );
+
+ if ( !$languageToSet ) {
+ return;
+ }
+
+ MediaWikiServices::getInstance()->getStatsdDataFactory()
+ ->increment( 'uls.setlang_used' );
+
+ $user = $out->getUser();
+ if ( $user->isAnon() && !$out->getConfig()->get( 'ULSAnonCanChangeLanguage' ) ) {
+ // User is anon, and cannot change language, return.
+ return;
+ }
+
+ $out->addModules( 'ext.uls.setlang' );
+ }
+
+ /**
+ * @param ResourceLoader $resourceLoader
+ */
+ public static function onResourceLoaderRegisterModules( ResourceLoader $resourceLoader ) {
+ global $wgVersion;
+
+ // Support: MediaWiki 1.34
+ $hasOldNotify = version_compare( $wgVersion, '1.35', '<' );
+
+ $tpl = [
+ 'localBasePath' => dirname( __DIR__ ) . '/resources',
+ 'remoteExtPath' => 'UniversalLanguageSelector/resources',
+ ];
+
+ $modules = [
+ "ext.uls.ime" => $tpl + [
+ "scripts" => "js/ext.uls.ime.js",
+ "dependencies" => array_merge( [
+ "ext.uls.common",
+ "ext.uls.preferences",
+ "ext.uls.mediawiki",
+ "ext.uls.messages",
+ "jquery.ime",
+ ], $hasOldNotify ? [ 'mediawiki.notify' ] : [] ),
+ "messages" => [
+ "uls-ime-helppage"
+ ],
+ ],
+ "ext.uls.setlang" => $tpl + [
+ "styles" => [
+ "css/ext.uls.dialog.less",
+ "css/ext.uls.setlang.less"
+ ],
+ "scripts" => [
+ "js/ext.uls.dialog.js",
+ "js/ext.uls.setlang.js"
+ ],
+ "dependencies" => array_merge( [
+ "mediawiki.api",
+ "mediawiki.ui.button",
+ "mediawiki.Uri"
+ ], $hasOldNotify ? [ 'mediawiki.notify' ] : [] ),
+ "messages" => [
+ "ext-uls-setlang-error",
+ "ext-uls-setlang-unknown-error",
+ "ext-uls-setlang-heading",
+ "ext-uls-setlang-message",
+ "ext-uls-setlang-accept",
+ "ext-uls-setlang-cancel",
+ "ext-uls-setlang-loading"
+ ],
+ ],
+ ];
+
+ $resourceLoader->register( $modules );
+ }
+
+ /**
+ * Add some tabs for navigation for users who do not use Ajax interface.
+ * Hook: PersonalUrls
+ * @param array &$personal_urls
+ * @param Title &$title
+ * @param SkinTemplate $context SkinTemplate object providing context
+ */
+ public static function addPersonalBarTrigger(
+ array &$personal_urls,
+ &$title,
+ SkinTemplate $context
+ ) {
+ global $wgULSPosition;
+
+ if ( $wgULSPosition !== 'personal' ) {
+ return;
+ }
+
+ if ( !self::isToolbarEnabled( $context->getUser() ) ) {
+ return;
+ }
+
+ // The element id will be 'pt-uls'
+ $langCode = $context->getLanguage()->getCode();
+ $personal_urls = [
+ 'uls' => [
+ 'text' => Language::fetchLanguageName( $langCode ),
+ 'href' => '#',
+ 'class' => 'uls-trigger',
+ 'active' => true
+ ]
+ ] + $personal_urls;
+ }
+
+ /**
+ * @param array $preferred
+ * @return string
+ */
+ protected static function getDefaultLanguage( array $preferred ) {
+ $supported = Language::fetchLanguageNames( null, 'mwfile' );
+
+ // look for a language that is acceptable to the client
+ // and known to the wiki.
+ foreach ( $preferred as $code => $weight ) {
+ if ( isset( $supported[$code] ) ) {
+ return $code;
+ }
+ }
+
+ // Some browsers might only send codes like de-de.
+ // Try with bare code.
+ foreach ( $preferred as $code => $weight ) {
+ $parts = explode( '-', $code, 2 );
+ $code = $parts[0];
+ if ( isset( $supported[$code] ) ) {
+ return $code;
+ }
+ }
+
+ return '';
+ }
+
+ /**
+ * Hook to UserGetLanguageObject
+ * @param User $user
+ * @param string &$code
+ * @param IContextSource $context
+ */
+ public static function getLanguage( User $user, &$code, IContextSource $context ) {
+ global $wgULSAnonCanChangeLanguage, $wgULSLanguageDetection;
+
+ if ( $wgULSLanguageDetection ) {
+ // Vary any caching based on the header value. Note that
+ // we need to vary regardless of whether we end up using
+ // the header or not, so that requests without the header
+ // don't show up for people with it.
+ $context->getOutput()->addVaryHeader( 'Accept-Language' );
+ }
+
+ if ( !self::isToolbarEnabled( $user ) ) {
+ return;
+ }
+
+ $request = $context->getRequest();
+
+ if (
+ // uselang can be used for temporary override of language preference
+ $request->getText( 'uselang' ) ||
+ // Registered user: use preferences
+ !$user->isAnon()
+ ) {
+ return;
+ }
+
+ // If using cookie storage for anons is OK, read from that
+ if ( $wgULSAnonCanChangeLanguage ) {
+ // Try to set the language based on the cookie
+ $languageToUse = $request->getCookie( 'language', null, '' );
+ if ( Language::isSupportedLanguage( $languageToUse ) ) {
+ $code = $languageToUse;
+
+ return;
+ }
+ }
+
+ // As last resort, try Accept-Language headers if allowed
+ if ( $wgULSLanguageDetection ) {
+ // We added a Vary header at the top of this function,
+ // since we're depending upon the Accept-Language header
+ $preferred = $request->getAcceptLang();
+ $default = self::getDefaultLanguage( $preferred );
+ if ( $default !== '' ) {
+ $code = $default;
+ }
+ }
+ }
+
+ /**
+ * Hook: ResourceLoaderGetConfigVars
+ * @param array &$vars
+ */
+ public static function addConfig( array &$vars ) {
+ global $wgULSGeoService,
+ $wgULSIMEEnabled, $wgULSWebfontsEnabled,
+ $wgULSNoWebfontsSelectors,
+ $wgULSAnonCanChangeLanguage,
+ $wgULSEventLogging,
+ $wgULSImeSelectors, $wgULSNoImeSelectors,
+ $wgULSFontRepositoryBasePath,
+ $wgExtensionAssetsPath,
+ $wgInterwikiSortingSortPrepend;
+
+ // Place constant stuff here (not depending on request context)
+
+ if ( is_string( $wgULSGeoService ) ) {
+ $vars['wgULSGeoService'] = $wgULSGeoService;
+ }
+
+ $vars['wgULSIMEEnabled'] = $wgULSIMEEnabled;
+ $vars['wgULSWebfontsEnabled'] = $wgULSWebfontsEnabled;
+ $vars['wgULSAnonCanChangeLanguage'] = $wgULSAnonCanChangeLanguage;
+ $vars['wgULSEventLogging'] = $wgULSEventLogging
+ && ExtensionRegistry::getInstance()->isLoaded( 'EventLogging' );
+ $vars['wgULSImeSelectors'] = $wgULSImeSelectors;
+ $vars['wgULSNoImeSelectors'] = $wgULSNoImeSelectors;
+ $vars['wgULSNoWebfontsSelectors'] = $wgULSNoWebfontsSelectors;
+
+ if ( is_string( $wgULSFontRepositoryBasePath ) ) {
+ $vars['wgULSFontRepositoryBasePath'] = $wgULSFontRepositoryBasePath;
+ } else {
+ $vars['wgULSFontRepositoryBasePath'] = $wgExtensionAssetsPath .
+ '/UniversalLanguageSelector/data/fontrepo/fonts/';
+ }
+
+ if ( isset( $wgInterwikiSortingSortPrepend ) && $wgInterwikiSortingSortPrepend !== [] ) {
+ $vars['wgULSCompactLinksPrepend'] = $wgInterwikiSortingSortPrepend;
+ }
+ }
+
+ /**
+ * Hook: MakeGlobalVariablesScript
+ * @param array &$vars
+ * @param OutputPage $out
+ */
+ public static function addVariables( array &$vars, OutputPage $out ) {
+ // Place request context dependent stuff here
+ $user = $out->getUser();
+ $loggedIn = $user->isLoggedIn();
+
+ // Do not output accept languages if there is risk it will get cached across requests
+ if ( $out->getConfig()->get( 'ULSAnonCanChangeLanguage' ) || $loggedIn ) {
+ $vars['wgULSAcceptLanguageList'] = array_keys( $out->getRequest()->getAcceptLang() );
+ }
+
+ if ( $loggedIn && class_exists( Babel::class ) ) {
+ $userLanguageInfo = Babel::getCachedUserLanguageInfo( $user );
+
+ // This relies on the fact that Babel levels are 'N' and
+ // the digits 0 to 5 as strings, and that in reverse
+ // ASCII order they will be 'N', '5', '4', '3', '2', '1', '0'.
+ arsort( $userLanguageInfo );
+
+ $vars['wgULSBabelLanguages'] = array_keys( $userLanguageInfo );
+ }
+
+ // An optimization to avoid loading all of uls.data just to get the autonym
+ $langCode = $out->getLanguage()->getCode();
+ $vars['wgULSCurrentAutonym'] = Language::fetchLanguageName( $langCode );
+
+ $setLangCode = self::getSetLang( $out );
+ if ( $setLangCode ) {
+ $vars['wgULSCurrentLangCode'] = $langCode;
+ $vars['wgULSSetLangCode'] = $setLangCode;
+ $vars['wgULSSetLangName'] = Language::fetchLanguageName( $setLangCode );
+ }
+ }
+
+ public static function onGetPreferences( $user, array &$preferences ) {
+ global $wgULSCompactLanguageLinksBetaFeature;
+
+ $preferences['uls-preferences'] = [
+ 'type' => 'api',
+ ];
+
+ // A link shown for accessing ULS language settings from preferences screen
+ $preferences['languagesettings'] = [
+ 'type' => 'info',
+ 'raw' => true,
+ 'section' => 'personal/i18n',
+ // We use this class to hide this from no-JS users
+ 'cssclass' => 'uls-preferences-link-wrapper',
+ 'default' => "<a id='uls-preferences-link' role='button' tabindex='0'>" .
+ wfMessage( 'ext-uls-language-settings-preferences-link' )->escaped() . "</a>",
+ ];
+
+ if ( $wgULSCompactLanguageLinksBetaFeature === false ) {
+ $preferences['compact-language-links'] = [
+ 'type' => 'check',
+ 'section' => 'rendering/languages',
+ 'label-message' => [
+ 'ext-uls-compact-language-links-preference',
+ 'mediawikiwiki:Special:MyLanguage/Universal_Language_Selector/Compact_Language_Links'
+ ]
+ ];
+ }
+ }
+
+ public static function onGetBetaFeaturePreferences( $user, array &$prefs ) {
+ global $wgExtensionAssetsPath, $wgULSCompactLanguageLinksBetaFeature,
+ $wgHideInterlanguageLinks, $wgInterwikiMagic;
+
+ if ( $wgULSCompactLanguageLinksBetaFeature === true &&
+ $wgInterwikiMagic === true &&
+ $wgHideInterlanguageLinks === false
+ ) {
+ $imagesDir = "$wgExtensionAssetsPath/UniversalLanguageSelector/resources/images";
+ $prefs['uls-compact-links'] = [
+ 'label-message' => 'uls-betafeature-label',
+ 'desc-message' => 'uls-betafeature-desc',
+ 'screenshot' => [
+ 'ltr' => "$imagesDir/compact-links-ltr.svg",
+ 'rtl' => "$imagesDir/compact-links-rtl.svg",
+ ],
+ 'info-link' =>
+ 'https://www.mediawiki.org/wiki/Special:MyLanguage/' .
+ 'Universal_Language_Selector/Compact_Language_Links',
+ 'discussion-link' =>
+ 'https://www.mediawiki.org/wiki/Talk:Universal_Language_Selector/Compact_Language_Links',
+ ];
+ }
+ }
+
+ /**
+ * Kept for backward compatability with MW < 1.35, and older versions of skins
+ * such as Vector and Timeless
+ * @param QuickTemplate $template
+ * @param string $name
+ * @param string &$content
+ */
+ public static function onBaseTemplateAfterPortlet(
+ QuickTemplate $template,
+ string $name,
+ string &$content
+ ) {
+ global $wgULSPosition;
+
+ if ( $wgULSPosition !== 'interlanguage' ) {
+ return;
+ }
+
+ if ( !self::isToolbarEnabled( $template->getSkin()->getUser() ) ) {
+ return;
+ }
+
+ // Set to an empty array, just to make sure that the section appears
+ if ( $template->get( 'language_urls' ) === false ) {
+ $template->set( 'language_urls', [] );
+ }
+ }
+
+ /**
+ * @param Skin $skin
+ * @param string $name
+ * @param string &$content
+ */
+ public static function onSkinAfterPortlet(
+ Skin $skin,
+ string $name,
+ string &$content
+ ) {
+ global $wgULSPosition;
+
+ if ( $name !== 'lang' ) {
+ return;
+ }
+
+ if ( $wgULSPosition !== 'interlanguage' ) {
+ return;
+ }
+
+ if ( !self::isToolbarEnabled( $skin->getUser() ) ) {
+ return;
+ }
+
+ // An empty span will force the language portal to always display in
+ // the skins that support it! e.g. Vector.
+ if ( count( $skin->getLanguages() ) === 0 ) {
+ // If no languages force it on.
+ $content .= Html::element(
+ 'span',
+ [
+ 'class' => 'uls-after-portlet-link',
+ ],
+ ''
+ );
+ }
+ }
+
+ /**
+ * Add basic webfonts support to the mobile interface (via MobileFrontend extension)
+ * Hook: EnterMobileMode
+ * @param MobileContext $context
+ */
+ public static function onEnterMobileMode( MobileContext $context ) {
+ global $wgULSEnable, $wgULSMobileWebfontsEnabled;
+
+ // Currently only supported in mobile Beta mode
+ if ( $wgULSEnable && $wgULSMobileWebfontsEnabled && $context->isBetaGroupMember() ) {
+ $context->getOutput()->addModules( 'ext.uls.webfonts.mobile' );
+ }
+ }
+
+ private static function getSetLang( OutputPage $out ): ?string {
+ $setLangCode = $out->getRequest()->getText( 'setlang' );
+ if ( $setLangCode && Language::isSupportedLanguage( $setLangCode ) ) {
+ return $setLangCode;
+ }
+
+ return null;
+ }
+}