Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
0.83% covered (danger)
0.83%
11 / 1325
11.76% covered (danger)
11.76%
2 / 17
CRAP
0.00% covered (danger)
0.00%
0 / 1
Hooks
0.83% covered (danger)
0.83%
11 / 1325
11.76% covered (danger)
11.76%
2 / 17
7299.32
0.00% covered (danger)
0.00%
0 / 1
 __construct
100.00% covered (success)
100.00%
6 / 6
100.00% covered (success)
100.00%
1 / 1
1
 factory
0.00% covered (danger)
0.00%
0 / 7
0.00% covered (danger)
0.00%
0 / 1
2
 onMessageCacheFetchOverrides
0.00% covered (danger)
0.00%
0 / 103
0.00% covered (danger)
0.00%
0 / 1
272
 shortenLicenseLink
0.00% covered (danger)
0.00%
0 / 18
0.00% covered (danger)
0.00%
0 / 1
20
 onSkinCopyrightFooter
6.67% covered (danger)
6.67%
2 / 30
0.00% covered (danger)
0.00%
0 / 1
109.38
 onEditPageCopyrightWarning
0.00% covered (danger)
0.00%
0 / 15
0.00% covered (danger)
0.00%
0 / 1
72
 skinCopyrightFooterMobile
0.00% covered (danger)
0.00%
0 / 17
0.00% covered (danger)
0.00%
0 / 1
72
 onDiscussionToolsTermsOfUseMessages
0.00% covered (danger)
0.00%
0 / 22
0.00% covered (danger)
0.00%
0 / 1
72
 onFlowTermsOfUseMessages
0.00% covered (danger)
0.00%
0 / 24
0.00% covered (danger)
0.00%
0 / 1
72
 onSkinAddFooterLinks
0.00% covered (danger)
0.00%
0 / 28
0.00% covered (danger)
0.00%
0 / 1
6
 onTorBlockBlockedMsg
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 onUploadForm_initial
0.00% covered (danger)
0.00%
0 / 4
0.00% covered (danger)
0.00%
0 / 1
12
 onRegistration
0.00% covered (danger)
0.00%
0 / 1018
0.00% covered (danger)
0.00%
0 / 1
6
 onBeforePageDisplay
100.00% covered (success)
100.00%
3 / 3
100.00% covered (success)
100.00%
1 / 1
2
 onResourceLoaderRegisterModules
0.00% covered (danger)
0.00%
0 / 16
0.00% covered (danger)
0.00%
0 / 1
6
 onSpecialPageBeforeExecute
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 addIPInfoLinks
0.00% covered (danger)
0.00%
0 / 12
0.00% covered (danger)
0.00%
0 / 1
72
1<?php
2
3// phpcs:disable MediaWiki.NamingConventions.LowerCamelFunctionsName.FunctionName
4// Need to be able to define ::onUploadForm_initial
5
6namespace MediaWiki\Extension\WikimediaMessages;
7
8use ErrorPageError;
9use ExtensionRegistry;
10use HtmlArmor;
11use MediaWiki\Cache\Hook\MessageCacheFetchOverridesHook;
12use MediaWiki\Config\Config;
13use MediaWiki\Config\ConfigException;
14use MediaWiki\Config\ServiceOptions;
15use MediaWiki\Extension\WikimediaMessages\LogFormatter\WMUserMergeLogFormatter;
16use MediaWiki\Hook\BeforePageDisplayHook;
17use MediaWiki\Hook\EditPageCopyrightWarningHook;
18use MediaWiki\Hook\SkinAddFooterLinksHook;
19use MediaWiki\Hook\SkinCopyrightFooterHook;
20use MediaWiki\Hook\UploadForm_initialHook;
21use MediaWiki\Html\Html;
22use MediaWiki\Linker\Linker;
23use MediaWiki\Linker\LinkRenderer;
24use MediaWiki\MainConfigNames;
25use MediaWiki\MediaWikiServices;
26use MediaWiki\Output\OutputPage;
27use MediaWiki\Permissions\PermissionManager;
28use MediaWiki\ResourceLoader\Hook\ResourceLoaderRegisterModulesHook;
29use MediaWiki\ResourceLoader\ResourceLoader;
30use MediaWiki\SpecialPage\Hook\SpecialPageBeforeExecuteHook;
31use MediaWiki\SpecialPage\SpecialPage;
32use MediaWiki\Specials\SpecialUpload;
33use MediaWiki\Title\Title;
34use MediaWiki\User\Options\UserOptionsLookup;
35use MessageCache;
36use MessageLocalizer;
37use Skin;
38use Wikimedia\IPUtils;
39
40/**
41 * Hooks for WikimediaMessages extension
42 *
43 * @file
44 * @ingroup Extensions
45 */
46class Hooks implements
47    BeforePageDisplayHook,
48    EditPageCopyrightWarningHook,
49    MessageCacheFetchOverridesHook,
50    ResourceLoaderRegisterModulesHook,
51    SkinAddFooterLinksHook,
52    SkinCopyrightFooterHook,
53    SpecialPageBeforeExecuteHook,
54    UploadForm_initialHook
55{
56
57    public const CONSTRUCTOR_OPTIONS = [
58        MainConfigNames::DBname,
59        MainConfigNames::ForceUIMsgAsContentMsg,
60        'WikimediaMessagesLicensing',
61        MainConfigNames::LanguageCode,
62        MainConfigNames::RightsText,
63    ];
64
65    private ExtensionRegistry $extensionRegistry;
66    private LinkRenderer $linkRenderer;
67    private PermissionManager $permissionManager;
68    private ServiceOptions $options;
69    private UserOptionsLookup $userOptionsLookup;
70
71    /**
72     * @param ExtensionRegistry $extensionRegistry
73     * @param LinkRenderer $linkRenderer
74     * @param PermissionManager $permissionManager
75     * @param ServiceOptions $options
76     * @param UserOptionsLookup $userOptionsLookup
77     */
78    public function __construct(
79        ExtensionRegistry $extensionRegistry,
80        LinkRenderer $linkRenderer,
81        PermissionManager $permissionManager,
82        ServiceOptions $options,
83        UserOptionsLookup $userOptionsLookup
84    ) {
85        $options->assertRequiredOptions( self::CONSTRUCTOR_OPTIONS );
86        $this->extensionRegistry = $extensionRegistry;
87        $this->linkRenderer = $linkRenderer;
88        $this->permissionManager = $permissionManager;
89        $this->options = $options;
90        $this->userOptionsLookup = $userOptionsLookup;
91    }
92
93    /**
94     * @param LinkRenderer $linkRenderer
95     * @param Config $mainConfig
96     * @param PermissionManager $permissionManager
97     * @param UserOptionsLookup $userOptionsLookup
98     *
99     * @return Hooks
100     */
101    public static function factory(
102        LinkRenderer $linkRenderer,
103        Config $mainConfig,
104        PermissionManager $permissionManager,
105        UserOptionsLookup $userOptionsLookup
106    ): self {
107        return new self(
108            ExtensionRegistry::getInstance(),
109            $linkRenderer,
110            $permissionManager,
111            new ServiceOptions( self::CONSTRUCTOR_OPTIONS, $mainConfig ),
112            $userOptionsLookup
113        );
114    }
115
116    /**
117     * When core requests certain messages, change the key to a Wikimedia version.
118     *
119     * @see https://www.mediawiki.org/wiki/Manual:Hooks/MessageCacheFetchOverrides
120     * @param string[] &$keys
121     */
122    public function onMessageCacheFetchOverrides( array &$keys ): void {
123        global $wmgRealm;
124
125        static $keysToOverride = [
126            'acct_creation_throttle_hit',
127            'centralauth-contribs-locked',
128            // T216347
129            'centralauth-login-error-locked',
130            // T86741
131            'centralauth-groupname',
132            // T345549
133            'checkuser-api-useragent-clienthints-explanation',
134            'checkuser-toollinks',
135            // T327281
136            'checkuser-tempaccount-enable-preference-description',
137            // T362548
138            'checkuser-investigateblock-warning-ips-and-users-in-targets',
139            'createacct-helpusername',
140            'createacct-imgcaptcha-help',
141            // T139797
142            'delete-toobig',
143            'feedback-termsofuse',
144            'globalblocking-blockedtext-ip',
145            'globalblocking-blockedtext-range',
146            'globalblocking-blockedtext-xff',
147            'globalblocking-ipblocked',
148            'globalblocking-ipblocked-range',
149            'globalblocking-ipblocked-xff',
150            'globalrenamequeue-email-body-approved',
151            'globalrenamequeue-email-body-rejected',
152            'interfaceadmin-info',
153            // T121639
154            'ipb-confirmhideuser',
155            'mwoauth-form-privacypolicy-link',
156            // T252375
157            'mobile-frontend-terms-url',
158            'mwoauthserver-invalid-user',
159            // T226059
160            'oathauth-step1-test',
161            // T189924
162            'oathauth-hint',
163            // T272412
164            'prefs-user-downloaddata-help-message',
165            'privacypage',
166            'sidebar',
167            // T140941
168            'sitematrix',
169            'sitematrix-others',
170            'sitematrix-summary',
171            'sulrenamewarning-usenew',
172            // T248367
173            'webauthn-module-description',
174            // T248367
175            'webauthn-ui-login-prompt',
176            // T218160
177            'log-action-filter-usermerge',
178            'log-action-filter-usermerge-mergeuser',
179            'log-action-filter-usermerge-deleteuser',
180            'notification-body-oathauth-disable-other',
181            'oathauth-notifications-disable-helplink',
182            // T307493
183            'ipinfo-source-geoip2',
184            'ipinfo-infobox-use-terms',
185            'ipinfo-preference-use-agreement',
186            'similareditors-error-default',
187            // T348926
188            'jsonconfig-license-copyrightwarning',
189            'jsonconfig-license-copyrightwarning-license-unset',
190            'jsonconfig-license-notice',
191            'jsonconfig-license-notice-license-unset',
192            // T340115
193            'campaignevents-edit-field-clickwrap-checkbox-label',
194            // T322209
195            'campaignevents-edit-form-questions-pii-notice',
196            // T357869
197            'pt-movepage-page-count-limit',
198        ];
199
200        static $allbutmetawikikeys = [
201            // T221526
202            'apierror-urlshortener-disabled',
203            // T230253
204            'apierror-urlshortener-permissiondenied',
205            // T331743
206            'centralauth-admin-log-otherwiki',
207            // T230253
208            'urlshortener-badaccessgroups',
209            // T221526
210            'urlshortener-disabled',
211        ];
212
213        // Temporarily override grouppage-suppress to grouppage-oversight,
214        // to avoid breaking links. See T112147.
215        $keys['grouppage-suppress'] = 'grouppage-oversight';
216
217        if ( $wmgRealm === 'labs' ) {
218            $keys['privacypage'] = 'wikimedia-privacypage-labs';
219        }
220
221        $languageCode = $this->options->get( MainConfigNames::LanguageCode );
222
223        $transformationCallback = static function ( string $key, MessageCache $cache ) use ( $languageCode ): string {
224            $transformedKey = "wikimedia-$key";
225
226            // MessageCache uses ucfirst if ord( key ) is < 128, which is true of all
227            // of the above.  Revisit if non-ASCII keys are used.
228            $ucKey = ucfirst( $key );
229
230            if (
231                /*
232                 * Override order:
233                 * 1. If the MediaWiki:$ucKey page exists, use the key unprefixed
234                 * (in all languages) with normal fallback order.  Specific
235                 * language pages (MediaWiki:$ucKey/xy) are not checked when
236                 * deciding which key to use, but are still used if applicable
237                 * after the key is decided.
238                 *
239                 * 2. Otherwise, use the prefixed key with normal fallback order
240                 * (including MediaWiki pages if they exist).
241                 */
242                $cache->getMsgFromNamespace( $ucKey, $languageCode ) === false
243            ) {
244                return $transformedKey;
245            }
246
247            return $key;
248        };
249
250        foreach ( $keysToOverride as $key ) {
251            $keys[$key] = $transformationCallback;
252        }
253
254        if ( $this->options->get( MainConfigNames::DBname ) !== 'metawiki' ) {
255            foreach ( $allbutmetawikikeys as $key ) {
256                $keys[$key] = $transformationCallback;
257            }
258        }
259
260        $licensing = $this->options->get( 'WikimediaMessagesLicensing' );
261        $rightsText = $this->options->get( MainConfigNames::RightsText );
262
263        switch ( $licensing ) {
264            case 'mediawiki':
265                $keys['mobile-frontend-license-links'] = 'mediawiki.org-mobile-license-links';
266                break;
267            case 'wikidata':
268                $keys['mobile-frontend-license-links'] = 'wikidata-mobile-license-links';
269                break;
270            case 'wikifunctions':
271                $keys['mobile-frontend-license-links'] = 'wikifunctions-mobile-license-links';
272                break;
273            case 'commons':
274            case 'standard':
275                $keys['mobile-frontend-license-links'] = 'wikimedia-mobile-license-links';
276                break;
277            case 'wikinews':
278                // This is necessary because MobileFrontend doesn't always display the license based on
279                // config settings (T296791)
280                if ( $rightsText === 'Creative Commons Attribution 3.0' ) {
281                    $keys['mobile-frontend-license-links'] = 'wikinews-mobile-license-links-ccby30';
282                } else {
283                    $keys['mobile-frontend-license-links'] = 'wikinews-mobile-license-links';
284                }
285                break;
286            default:
287                throw new ConfigException( "Unknown value for WikimediaMessagesLicensing: '$licensing'" );
288        }
289
290        if ( $this->extensionRegistry->isLoaded( 'MobileFrontend' ) ) {
291            $keys['mainpage-title-loggedin'] = static function ( string $key ): string {
292                $context = MediaWikiServices::getInstance()->getService( 'MobileFrontend.Context' );
293
294                return $context->shouldDisplayMobileView() ? 'wikimedia-mobile-mainpage-title-loggedin' : $key;
295            };
296        }
297    }
298
299    /**
300     * @param Config $config
301     * @return string
302     */
303    private function shortenLicenseLink( Config $config ): string {
304        $rightsText = $config->get( 'RightsText' );
305        $rightsPage = $config->get( 'RightsPage' );
306        $rightsUrl = $config->get( 'RightsUrl' );
307        $commonLicenses = [
308            'Creative Commons Attribution-Share Alike 4.0' => 'CC BY-SA 4.0',
309            'Creative Commons Attribution-Share Alike 3.0' => 'CC BY-SA 3.0',
310            'Creative Commons Attribution 3.0' => 'CC BY 3.0',
311            'Creative Commons Attribution 2.5' => 'CC BY 2.5',
312        ];
313        if ( isset( $commonLicenses[$rightsText] ) ) {
314            $rightsText = $commonLicenses[$rightsText];
315        }
316        if ( $rightsPage ) {
317            $title = Title::newFromText( $rightsPage );
318            $link = $this->linkRenderer->makeKnownLink( $title, new HtmlArmor( $rightsText ), [] );
319        } elseif ( $rightsUrl ) {
320            $link = Linker::makeExternalLink( $rightsUrl, $rightsText, true, '', [] );
321        } else {
322            $link = $rightsText;
323        }
324        return $link;
325    }
326
327    /**
328     * Override for copyright message in skin footer.
329     *
330     * @see https://www.mediawiki.org/wiki/Manual:Hooks/SkinCopyrightFooter
331     *
332     * @param Title $title
333     * @param string $type
334     * @param string &$msg
335     * @param string &$link
336     */
337    public function onSkinCopyrightFooter( $title, $type, &$msg, &$link ) {
338        if ( $type === 'history' ) {
339            return;
340        }
341
342        $licensing = $this->options->get( 'WikimediaMessagesLicensing' );
343
344        if ( $this->extensionRegistry->isLoaded( 'MobileFrontend' ) ) {
345            $services = MediaWikiServices::getInstance();
346            $config = $services->getConfigFactory()->makeConfig( 'wikimedia-messages' );
347            $context = $services->getService( 'MobileFrontend.Context' );
348            if ( $context->shouldDisplayMobileView() ) {
349                $msg = 'mobile-frontend-copyright';
350                $link = $this->shortenLicenseLink( $config );
351                self::skinCopyrightFooterMobile( $msg );
352                return;
353            }
354        }
355
356        switch ( $licensing ) {
357            case 'wikidata':
358                // Wikidata is licensed under CC-BY-SA 4.0 only, no GFDL. (Also, the data is under CC0.)
359                $msg = 'wikidata-copyright';
360                break;
361            case 'mediawiki':
362                // MediaWiki.org has a special licence for the Help: namespace.
363                $msg = 'mediawiki.org-copyright';
364                break;
365            case 'commons':
366                // Commons has a special licence for the structured data.
367                // TODO: Should we also mention the special Data: namespace?
368                $msg = 'wikimedia-commons-copyright';
369                break;
370            case 'standard':
371                // Almost all Wikimedia wikis using CC-BY-SA 4.0 are also dual-licensed under GFDL.
372                $msg = 'wikimedia-copyright';
373                break;
374            case 'wikinews':
375                // Use the default MediaWiki message. (It's overridden locally on most Wikinewses.)
376                break;
377            case 'wikifunctions':
378                // Wikifunctions like Wikidata is licensed under CC-BY-SA 4.0 only, no GFDL. The data is
379                // under CC0. The code is under Apache 2.0.
380                $msg = 'wikifunctions-site-footer-copyright';
381                break;
382            default:
383                throw new ConfigException( "Unknown value for WikimediaMessagesLicensing: '$licensing'" );
384        }
385    }
386
387    /**
388     * Override for copyright message on edit page.
389     *
390     * @see https://www.mediawiki.org/wiki/Manual:Hooks/EditPageCopyrightWarning
391     *
392     * @param Title $title
393     * @param array &$msg
394     */
395    public function onEditPageCopyrightWarning( $title, &$msg ) {
396        $licensing = $this->options->get( 'WikimediaMessagesLicensing' );
397
398        switch ( $licensing ) {
399            case 'wikidata':
400            case 'wikifunctions':
401                // Wikidata and Wikifunctions are licensed under CC-BY-SA 4.0 only, no GFDL.
402                $msg = [ 'wikimedia-copyrightwarning-ccbysa40only' ];
403                break;
404            case 'mediawiki':
405                // MediaWiki.org pages are dual-licensed under CC-BY-SA 4.0 and GFDL, except for the Help: namespace.
406                $msg = [ 'mediawiki.org-copyrightwarning' ];
407                break;
408            case 'commons':
409            case 'standard':
410                // Almost all Wikimedia wikis using CC-BY-SA 4.0 are also dual-licensed under GFDL.
411                $msg = [ 'wikimedia-copyrightwarning' ];
412                break;
413            case 'wikinews':
414                // Use the default MediaWiki message. (It's overridden locally on most Wikinewses.)
415                break;
416            default:
417                throw new ConfigException( "Unknown value for WikimediaMessagesLicensing: '$licensing'" );
418        }
419    }
420
421    /**
422     * Override for copyright message (MobileFrontend extension).
423     *
424     * @param string &$msg
425     */
426    private static function skinCopyrightFooterMobile( &$msg ) {
427        global $wgWikimediaMessagesLicensing;
428        $licensing = $wgWikimediaMessagesLicensing;
429
430        switch ( $licensing ) {
431            case 'wikidata':
432                // Wikidata needs its own special message. See T112088
433                $msg = 'wikidata-copyright';
434                break;
435            case 'mediawiki':
436                // MediaWiki.org also needs its own special message, to mention the Help: namespace.
437                $msg = 'mediawiki.org-copyright';
438                break;
439            case 'commons':
440                // Commons also needs its own special message, to mention the structured data.
441                $msg = 'wikimedia-commons-copyright';
442                break;
443            case 'standard':
444            case 'wikinews':
445                // Use the default MobileFrontend message.
446                break;
447            case 'wikifunctions':
448                // Wikifunctions is licensed under CC-BY-SA 4.0 only, no GFDL. The data is under CC0.
449                // The code is under Apache 2.0.
450                $msg = 'wikifunctions-site-footer-copyright';
451                break;
452            default:
453                throw new ConfigException( "Unknown value for WikimediaMessagesLicensing: '$licensing'" );
454        }
455    }
456
457    /**
458     * Override for copyright messages (DiscussionTools extension).
459     *
460     * @param array &$messages
461     * @param MessageLocalizer $context
462     * @param Config $config
463     */
464    public static function onDiscussionToolsTermsOfUseMessages(
465        array &$messages, MessageLocalizer $context, Config $config
466    ) {
467        $licensing = $config->get( 'WikimediaMessagesLicensing' );
468
469        switch ( $licensing ) {
470            case 'wikidata':
471            case 'wikifunctions':
472                // Do not use $wgRightsText or $wgRightsPage, as they are customized for the API (T112606).
473                $rightsUrl = $config->get( 'RightsUrl' );
474                $rightsText = 'Creative Commons Attribution-Share Alike 4.0';
475                $links = [ "[$rightsUrl $rightsText]", 1 ];
476                break;
477            case 'wikinews':
478                // Add the license name to the terms-of-use message
479                $rightsUrl = $config->get( 'RightsUrl' );
480                $rightsText = $config->get( 'RightsText' );
481                $links = [ "[$rightsUrl $rightsText]", 1 ];
482                break;
483            case 'commons':
484            case 'mediawiki':
485            case 'standard':
486                // Add the license names to the terms-of-use message - dual-licensed wikis
487                $links = [ $context->msg( 'wikimedia-license-links' )->plain(), 2 ];
488                break;
489            default:
490                throw new ConfigException( "Unknown value for WikimediaMessagesLicensing: '$licensing'" );
491        }
492
493        $messages['reply'] = array_merge( [ 'wikimedia-discussiontools-replywidget-terms-click',
494            $context->msg( 'discussiontools-replywidget-reply' )->text() ], $links );
495        $messages['newtopic'] = array_merge( [ 'wikimedia-discussiontools-replywidget-terms-click',
496            $context->msg( 'discussiontools-replywidget-newtopic' )->text() ], $links );
497    }
498
499    /**
500     * Override for copyright messages (Flow extension).
501     *
502     * @param array &$messages
503     * @param MessageLocalizer $context
504     * @param Config $config
505     */
506    public static function onFlowTermsOfUseMessages(
507        array &$messages, MessageLocalizer $context, Config $config
508    ) {
509        $licensing = $config->get( 'WikimediaMessagesLicensing' );
510
511        switch ( $licensing ) {
512            case 'wikidata':
513            case 'wikifunctions':
514                // Do not use $wgRightsText or $wgRightsPage, as they are customized for the API (T112606).
515                $rightsUrl = $config->get( 'RightsUrl' );
516                $rightsText = 'Creative Commons Attribution-Share Alike 4.0';
517                $links = [ "[$rightsUrl $rightsText]", 1 ];
518                break;
519            case 'wikinews':
520                // Add the license name to the terms-of-use message
521                $rightsUrl = $config->get( 'RightsUrl' );
522                $rightsText = $config->get( 'RightsText' );
523                $links = [ "[$rightsUrl $rightsText]", 1 ];
524                break;
525            case 'commons':
526            case 'mediawiki':
527            case 'standard':
528                // Add the license names to the terms-of-use message - dual-licensed wikis
529                $links = [ $context->msg( 'wikimedia-license-links' )->plain(), 2 ];
530                break;
531            default:
532                throw new ConfigException( "Unknown value for WikimediaMessagesLicensing: '$licensing'" );
533        }
534
535        $messages['edit'] = array_merge( [ 'wikimedia-flow-terms-of-use-edit' ], $links );
536        $messages['lock-topic'] = array_merge( [ 'wikimedia-flow-terms-of-use-lock-topic' ], $links );
537        $messages['new-topic'] = array_merge( [ 'wikimedia-flow-terms-of-use-new-topic' ], $links );
538        $messages['reply'] = array_merge( [ 'wikimedia-flow-terms-of-use-reply' ], $links );
539        $messages['summarize'] = array_merge( [ 'wikimedia-flow-terms-of-use-summarize' ], $links );
540        $messages['unlock-topic'] = array_merge( [ 'wikimedia-flow-terms-of-use-unlock-topic' ], $links );
541    }
542
543    /**
544     * Add links to the footer of every page:
545     *   - "Developers" (T35464),
546     *   - "Statistics" (T235803), and
547     *   - "Cookie statement" (T124366)
548     *
549     * @see https://www.mediawiki.org/wiki/Manual:Hooks/SkinAddFooterLinks
550     *
551     * @param Skin $skin
552     * @param string $key
553     * @param array &$footerLinks
554     */
555    public function onSkinAddFooterLinks( Skin $skin, string $key, array &$footerLinks ) {
556        if ( $key !== 'places' ) {
557            return;
558        }
559        $devDestination = Skin::makeInternalOrExternalUrl(
560            $skin->msg( 'wikimedia-developers-url' )->inContentLanguage()->text()
561        );
562        $footerLinks['developers'] = Html::element(
563            'a',
564            [ 'href' => $devDestination ],
565            $skin->msg( 'wikimedia-developers' )->text()
566        );
567
568        $statsDestination = Skin::makeInternalOrExternalUrl(
569            $skin->msg(
570                'wikimedia-statslink-url', $skin->getConfig()->get( 'ServerName' )
571            )->inContentLanguage()->text()
572        );
573        $footerLinks['statslink'] = Html::element(
574            'a',
575            [ 'href' => $statsDestination ],
576            $skin->msg( 'wikimedia-statslink' )->text()
577        );
578
579        $cookieDestination = Skin::makeInternalOrExternalUrl(
580            $skin->msg( 'wikimedia-cookiestatement-page' )->inContentLanguage()->text()
581        );
582        $footerLinks['cookiestatement'] = Html::element(
583            'a',
584            [ 'href' => $cookieDestination ],
585            $skin->msg( 'wikimedia-cookiestatement' )->text()
586        );
587    }
588
589    /**
590     * Change which message is shown when TorBlock triggers (TorBlock extension)
591     *
592     * @todo FIXME: Should have a specific message for WMF projects (T44231)
593     *
594     * @todo once TorBlock updates to use hook interfaces that can be implemented,
595     * convert to using this class as a hook handler and make non-static with DI
596     *
597     * @param string &$msg The message key
598     */
599    public static function onTorBlockBlockedMsg( &$msg ) {
600        $msg = 'wikimedia-torblock-blocked';
601    }
602
603    /**
604     * Require the creation of MediaWiki:Licenses to enable uploading.
605     * This should prevent a lot of uploading without licenses on small wikis;
606     * some or many of the small WMF wikis do not have any license options,
607     * which is really needed for our copyright policy.
608     *
609     * Do not require it when licenses is in $wgForceUIMsgAsContentMsg,
610     * to prevent checking each subpage of MediaWiki:Licenses.
611     *
612     * @param SpecialUpload $upload
613     * @throws ErrorPageError
614     */
615    public function onUploadForm_initial( $upload ) {
616        $forceUIMsgAsContentMsg = $this->options->get( MainConfigNames::ForceUIMsgAsContentMsg );
617
618        // TODO inject something to replace use of wfMessage
619        if ( !in_array( 'licenses', $forceUIMsgAsContentMsg )
620            && wfMessage( 'licenses' )->inContentLanguage()->isDisabled()
621        ) {
622            throw new ErrorPageError( 'uploaddisabled', 'wikimedia-upload-nolicenses' );
623        }
624    }
625
626    /**
627     * Override `$wgGrammarForms` for Wikimedia sites as a more convenient form
628     * than setting in InitialiseSettings.php. Initial version was compiled from
629     * then-current Wikimedia configuration and contents of LanguageXx.php.
630     */
631    public static function onRegistration() {
632        global $wgGrammarForms;
633
634        $wgGrammarForms['ang'] = [
635            // accusative
636            'wrēgendlīc' => [
637                'Wikipǣdia' => 'Wikipǣdie',
638                'Wikiwordbōc' => 'Wikiwordbōc',
639            ],
640            // genitive
641            'geāgniendlīc' => [
642                'Wikipǣdia' => 'Wikipǣdie',
643                'Wikiwordbōc' => 'Wikiwordbēc',
644            ],
645            // dative
646            'forgifendlīc' => [
647                'Wikipǣdia' => 'Wikipǣdie',
648                'Wikiwordbōc' => 'Wikiwordbēc',
649            ],
650            // instrumental
651            'tōllīc' => [
652                'Wikipǣdia' => 'Wikipǣdie',
653                'Wikiwordbōc' => 'Wikiwordbēc',
654            ],
655        ];
656
657        $wgGrammarForms['be'] = [
658            // genitive
659            'родны' => [
660                'Віківіды'    => 'Віківідаў',
661                'Вікіданыя'   => 'Вікіданых',
662                'Вікікнігі'   => 'Вікікніг',
663                'Вікікрыніцы' => 'Вікікрыніц',
664                'Вікінавіны'  => 'Вікінавін',
665                'Вікіслоўнік' => 'Вікіслоўніка',
666                'Вікіпедыя'   => 'Вікіпедыі',
667            ],
668            // accusative
669            'вінавальны' => [
670                'Вікіпедыя'   => 'Вікіпедыю',
671            ],
672            // prepositional
673            'месны' => [
674                'Віківіды'    => 'Віківідах',
675                'Вікіданыя'   => 'Вікіданых',
676                'Вікікнігі'   => 'Вікікнігах',
677                'Вікікрыніцы' => 'Вікікрыніцах',
678                'Вікінавіны'  => 'Вікінавінах',
679                'Вікіслоўнік' => 'Вікіслоўніку',
680                'Вікіпедыя'   => 'Вікіпедыі',
681            ],
682        ];
683
684        $wgGrammarForms['be-tarask'] = [
685            // genitive
686            'родны' => [
687                'Віківіды'    => 'Віківідаў',
688                'Вікізьвесткі' => 'Вікізьвестак',
689                'Вікікнігі'   => 'Вікікніг',
690                'Вікікрыніцы' => 'Вікікрыніц',
691                'Вікімэдыя'   => 'Вікімэдыі',
692                'Вікінавіны'  => 'Вікінавін',
693                'Вікіпэдыя'   => 'Вікіпэдыі',
694                'Вікіслоўнік' => 'Вікіслоўніка',
695                'Вікісховішча' => 'Вікісховішча',
696                'Фундацыя «Вікімэдыя»' => 'Фундацыі «Вікімэдыя»',
697            ],
698            // dative
699            'давальны' => [
700                'Віківіды'    => 'Віківідам',
701                'Вікізьвесткі' => 'Вікізьвесткам',
702                'Вікікнігі'   => 'Вікікнігам',
703                'Вікікрыніцы' => 'Вікікрыніцам',
704                'Вікімэдыя'   => 'Вікімэдыі',
705                'Вікінавіны'  => 'Вікінавінам',
706                'Вікіпэдыя'   => 'Вікіпэдыі',
707                'Вікіслоўнік' => 'Вікіслоўніку',
708                'Вікісховішча' => 'Вікісховішчу',
709                'Фундацыя «Вікімэдыя»' => 'Фундацыі «Вікімэдыя»',
710            ],
711            // accusative
712            'вінавальны' => [
713                'Віківіды'    => 'Віківіды',
714                'Вікізьвесткі' => 'Вікізьвесті',
715                'Вікікнігі'   => 'Вікікнігі',
716                'Вікікрыніцы' => 'Вікікрыніцы',
717                'Вікімэдыя'   => 'Вікімэдыю',
718                'Вікінавіны'  => 'Вікінавіны',
719                'Вікіпэдыя'   => 'Вікіпэдыю',
720                'Вікіслоўнік' => 'Вікіслоўнік',
721                'Вікісховішча' => 'Вікісховішча',
722                'Фундацыя «Вікімэдыя»' => 'Фундацыю «Вікімэдыя»',
723            ],
724            // instrumental
725            'творны' => [
726                'Віківіды'    => 'Віківідамі',
727                'Вікізьвесткі' => 'Вікізьвесткамі',
728                'Вікікнігі'   => 'Вікікнігамі',
729                'Вікікрыніцы' => 'Вікікрыніцамі',
730                'Вікімэдыя'   => 'Вікімэдыяй',
731                'Вікінавіны'  => 'Вікінавінамі',
732                'Вікіпэдыя'   => 'Вікіпэдыяй',
733                'Вікіслоўнік' => 'Вікіслоўнікам',
734                'Вікісховішча' => 'Вікісховішчам',
735                'Фундацыя «Вікімэдыя»' => 'Фундацыяй «Вікімэдыя»',
736            ],
737            // prepositional
738            'месны' => [
739                'Віківіды'    => 'Віківідах',
740                'Вікізьвесткі' => 'Вікізьвестках',
741                'Вікікнігі'   => 'Вікікнігах',
742                'Вікікрыніцы' => 'Вікікрыніцах',
743                'Вікімэдыя'   => 'Вікімэдыі',
744                'Вікінавіны'  => 'Вікінавінах',
745                'Вікіпэдыя'   => 'Вікіпэдыі',
746                'Вікіслоўнік' => 'Вікіслоўніку',
747                'Вікісховішча' => 'Вікісховішчы',
748                'Фундацыя «Вікімэдыя»' => 'Фундацыі «Вікімэдыя»',
749            ],
750        ];
751
752        $wgGrammarForms['bs'] = [
753            // genitive
754            'genitiv' => [
755                'Vikirječnik' => 'Wikirječnika',
756                'Wikicitati'  => 'Wikicitata',
757                'Wikiizvor'   => 'Wikiizvora',
758                'Wikiknjige'  => 'Wikiknjiga',
759                'Wikipedia'   => 'Wikipedije',
760                'Wikipodaci'  => 'Wikipodataka',
761                'Wikimedia Commons' => 'Wikimedia Commonsa',
762            ],
763            // dative
764            'dativ' => [
765                'Vikirječnik' => 'Wikirječniku',
766                'Wikicitati'  => 'Wikicitatima',
767                'Wikiizvor'   => 'Wikiizvoru',
768                'Wikiknjige'  => 'Wikiknjigama',
769                'Wikipedia'   => 'Wikipediji',
770                'Wikipodaci'  => 'Wikipodacima',
771                'Wikivijesti' => 'Wikivijestima',
772                'Wikimedia Commons' => 'Wikimedia Commonsu',
773            ],
774            // accusative
775            'akuzativ' => [
776                'Vikirječnik' => 'Wikirječnik',
777                'Wikicitati'  => 'Wikicitate',
778                'Wikiizvor'   => 'Wikiizvora',
779                'Wikipedia'   => 'Wikipediju',
780                'Wikipodaci'  => 'Wikipodatke',
781            ],
782            // vocative
783            'vokativ' => [
784                'Vikirječnik' => 'Wikirječniče',
785                'Wikiizvor'   => 'Wikizivoru',
786                'Wikipedia'   => 'Wikipedijo',
787                'Wikimedia Commons' => 'Wikimedia Commonse',
788            ],
789            // instrumental
790            'instrumental' => [
791                'Vikirječnik' => 'Wikirječnikom',
792                'Wikicitati'  => 'Wikicitatima',
793                'Wikiizvor'   => 'Wikiizvorom',
794                'Wikiknjige'  => 'Wikiknjigama',
795                // T130141
796                'Wikipedia'   => 'Wikipedijom',
797                'Wikipodaci'  => 'Wikipodacima',
798                'Wikivijesti' => 'Wikivijestima',
799                'Wikimedia Commons' => 'Wikimedia Commonsom',
800            ],
801            // locative
802            'lokativ' => [
803                'Vikirječnik' => 'Wikirječniku',
804                'Wikicitati'  => 'Wikicitatima',
805                'Wikiizvor'   => 'Wikiizvoru',
806                'Wikiknjige'  => 'Wikiknjigama',
807                'Wikipedia'   => 'Wikipediji',
808                'Wikipodaci'  => 'Wikipodacima',
809                'Wikivijesti' => 'Wikivijestima',
810                'Wikimedia Commons' => 'Wikimedia Commonsu',
811            ],
812        ];
813
814        $wgGrammarForms['cs'] = [
815            // only forms different than default/given
816            '1sg' => [
817                'Wikibooks'   => 'Wikiknihy',
818                'Wikifunctions' => 'Wikifunkce',
819                'Wikinews'    => 'Wikizprávy',
820                'Wikipedia'   => 'Wikipedie',
821                'Wikiquote'   => 'Wikicitáty',
822                'Wikisource'  => 'Wikizdroje',
823                'Wikispecies' => 'Wikidruhy',
824                'Wikiversity' => 'Wikiverzita',
825                'Wikivoyage'  => 'Wikicesty',
826                'Wiktionary'  => 'Wikislovník',
827            ],
828            '2sg' => [
829                'uživatel'    => 'uživatele',
830                'Wikibooks'   => 'Wikiknih',
831                'Wikidata'    => 'Wikidat',
832                'Wikifunctions' => 'Wikifunkcí',
833                'Wikinews'    => 'Wikizpráv',
834                'Wikipedia'   => 'Wikipedie',
835                'Wikiquote'   => 'Wikicitátů',
836                'Wikisource'  => 'Wikizdrojů',
837                'Wikispecies' => 'Wikidruhů',
838                'Wikiversity' => 'Wikiverzity',
839                'Wikivoyage'  => 'Wikicest',
840                'Wiktionary'  => 'Wikislovníku',
841                'Wikicesty'   => 'Wikicest',
842                'Wikicitáty'  => 'Wikicitátů',
843                'Wikidruhy'   => 'Wikidruhů',
844                'Wikifunkce'  => 'Wikifunkcí',
845                'Wikiknihy'   => 'Wikiknih',
846                'Wikislovník' => 'Wikislovníku',
847                'Wikiverzita' => 'Wikiverzity',
848                'Wikizdroje'  => 'Wikizdrojů',
849                'Wikizprávy'  => 'Wikizpráv',
850            ],
851            '3sg' => [
852                'uživatel'    => 'uživateli',
853                'Wikibooks'   => 'Wikiknihám',
854                'Wikidata'    => 'Wikidatům',
855                'Wikifunctions' => 'Wikifunkcím',
856                'Wikinews'    => 'Wikizprávám',
857                'Wikipedia'   => 'Wikipedii',
858                'Wikiquote'   => 'Wikicitátům',
859                'Wikisource'  => 'Wikizdrojům',
860                'Wikispecies' => 'Wikidruhům',
861                'Wikiversity' => 'Wikiverzitě',
862                'Wikivoyage'  => 'Wikicestám',
863                'Wiktionary'  => 'Wikislovníku',
864                'Wikicesty'   => 'Wikicestám',
865                'Wikicitáty'  => 'Wikicitátům',
866                'Wikidruhy'   => 'Wikidruhům',
867                'Wikifunkce'  => 'Wikifunkcím',
868                'Wikiknihy'   => 'Wikiknihám',
869                'Wikipedie'   => 'Wikipedii',
870                'Wikislovník' => 'Wikislovníku',
871                'Wikiverzita' => 'Wikiverzitě',
872                'Wikizdroje'  => 'Wikizdrojům',
873                'Wikizprávy'  => 'Wikizprávám',
874            ],
875            '4sg' => [
876                'uživatel'    => 'uživatele',
877                'Wikibooks'   => 'Wikiknihy',
878                'Wikifunctions' => 'Wikifunkce',
879                'Wikinews'    => 'Wikizprávy',
880                'Wikipedia'   => 'Wikipedii',
881                'Wikiquote'   => 'Wikicitáty',
882                'Wikisource'  => 'Wikizdroje',
883                'Wikispecies' => 'Wikidruhy',
884                'Wikiversity' => 'Wikiverzitu',
885                'Wikivoyage'  => 'Wikicesty',
886                'Wiktionary'  => 'Wikislovník',
887                'Wikipedie'   => 'Wikipedii',
888                'Wikiverzita' => 'Wikiverzitu',
889            ],
890            '5sg' => [
891                'uživatel'    => 'uživateli',
892                'Wikibooks'   => 'Wikiknihy',
893                'Wikifunctions' => 'Wikifunkce',
894                'Wikinews'    => 'Wikizprávy',
895                'Wikipedia'   => 'Wikipedie',
896                'Wikiquote'   => 'Wikicitáty',
897                'Wikisource'  => 'Wikizdroje',
898                'Wikispecies' => 'Wikidruhy',
899                'Wikiversity' => 'Wikiverzito',
900                'Wikivoyage'  => 'Wikicesty',
901                'Wiktionary'  => 'Wikislovníku',
902                'Wikislovník' => 'Wikislovníku',
903                'Wikiverzita' => 'Wikiverzito',
904            ],
905            '6sg' => [
906                'uživatel'    => 'uživateli',
907                'Wikibooks'   => 'Wikiknihách',
908                'Wikidata'    => 'Wikidatech',
909                'Wikifunctions' => 'Wikifunkcích',
910                'Wikinews'    => 'Wikizprávách',
911                'Wikipedia'   => 'Wikipedii',
912                'Wikiquote'   => 'Wikicitátech',
913                'Wikisource'  => 'Wikizdrojích',
914                'Wikispecies' => 'Wikidruzích',
915                'Wikiversity' => 'Wikiverzitě',
916                'Wikivoyage'  => 'Wikicestách',
917                'Wiktionary'  => 'Wikislovníku',
918                'Wikicesty'   => 'Wikicestách',
919                'Wikicitáty'  => 'Wikicitátech',
920                'Wikidruhy'   => 'Wikidruzích',
921                'Wikifunkce'  => 'Wikifunkcích',
922                'Wikiknihy'   => 'Wikiknihách',
923                'Wikipedie'   => 'Wikipedii',
924                'Wikislovník' => 'Wikislovníku',
925                'Wikiverzita' => 'Wikiverzitě',
926                'Wikizdroje'  => 'Wikizdrojích',
927                'Wikizprávy'  => 'Wikizprávách',
928            ],
929            '7sg' => [
930                'uživatel'    => 'uživatelem',
931                'Wikibooks'   => 'Wikiknihami',
932                'Wikidata'    => 'Wikidaty',
933                'Wikifunctions' => 'Wikifunkcemi',
934                'Wikinews'    => 'Wikizprávami',
935                'Wikipedia'   => 'Wikipedií',
936                'Wikiquote'   => 'Wikicitáty',
937                'Wikisource'  => 'Wikizdroji',
938                'Wikispecies' => 'Wikidruhy',
939                'Wikiversity' => 'Wikiverzitou',
940                'Wikivoyage'  => 'Wikicestami',
941                'Wiktionary'  => 'Wikislovníkem',
942                'Wikicesty'   => 'Wikicestami',
943                'Wikifunkce'  => 'Wikifunkcemi',
944                'Wikiknihy'   => 'Wikiknihami',
945                'Wikipedie'   => 'Wikipedií',
946                'Wikislovník' => 'Wikislovníkem',
947                'Wikiverzita' => 'Wikiverzitou',
948                'Wikizdroje'  => 'Wikizdroji',
949                'Wikizprávy'  => 'Wikizprávami',
950            ],
951            '1pl' => [
952                'uživatel'    => 'uživatelé',
953                'Wikibooks'   => 'Wikiknihy',
954                'Wikifunctions' => 'Wikifunkce',
955                'Wikinews'    => 'Wikizprávy',
956                'Wikipedia'   => 'Wikipedie',
957                'Wikiquote'   => 'Wikicitáty',
958                'Wikisource'  => 'Wikizdroje',
959                'Wikispecies' => 'Wikidruhy',
960                'Wikiversity' => 'Wikiverzity',
961                'Wikivoyage'  => 'Wikicesty',
962                'Wiktionary'  => 'Wikislovníky',
963                'Wikislovník' => 'Wikislovníky',
964                'Wikiverzita' => 'Wikiverzity',
965            ],
966            '2pl' => [
967                'uživatel'    => 'uživatelů',
968                'Wikibooks'   => 'Wikiknih',
969                'Wikidata'    => 'Wikidat',
970                'Wikifunctions' => 'Wikifunkcí',
971                'Wikinews'    => 'Wikizpráv',
972                'Wikipedia'   => 'Wikipedií',
973                'Wikiquote'   => 'Wikicitátů',
974                'Wikisource'  => 'Wikizdrojů',
975                'Wikispecies' => 'Wikidruhů',
976                'Wikiversity' => 'Wikiverzit',
977                'Wikivoyage'  => 'Wikicest',
978                'Wiktionary'  => 'Wikislovníků',
979                'Wikicesty'   => 'Wikicest',
980                'Wikicitáty'  => 'Wikicitátů',
981                'Wikidruhy'   => 'Wikidruhů',
982                'Wikifunkce'  => 'Wikifunkcí',
983                'Wikiknihy'   => 'Wikiknih',
984                'Wikipedie'   => 'Wikipedií',
985                'Wikislovník' => 'Wikislovníků',
986                'Wikiverzita' => 'Wikiverzit',
987                'Wikizdroje'  => 'Wikizdrojů',
988                'Wikizprávy'  => 'Wikizpráv',
989            ],
990            '3pl' => [
991                'uživatel'    => 'uživatelům',
992                'Wikibooks'   => 'Wikiknihám',
993                'Wikidata'    => 'Wikidatům',
994                'Wikifunctions' => 'Wikifunkcím',
995                'Wikinews'    => 'Wikizprávám',
996                'Wikipedia'   => 'Wikipediím',
997                'Wikiquote'   => 'Wikicitátům',
998                'Wikisource'  => 'Wikizdrojům',
999                'Wikispecies' => 'Wikidruhům',
1000                'Wikiversity' => 'Wikiverzitám',
1001                'Wikivoyage'  => 'Wikicestám',
1002                'Wiktionary'  => 'Wikislovníkům',
1003                'Wikicesty'   => 'Wikicestám',
1004                'Wikicitáty'  => 'Wikicitátům',
1005                'Wikidruhy'   => 'Wikidruhům',
1006                'Wikifunkce'  => 'Wikifunkcím',
1007                'Wikiknihy'   => 'Wikiknihám',
1008                'Wikipedie'   => 'Wikipediím',
1009                'Wikislovník' => 'Wikislovníkům',
1010                'Wikiverzita' => 'Wikiverzitám',
1011                'Wikizdroje'  => 'Wikizdrojům',
1012                'Wikizprávy'  => 'Wikizprávám',
1013            ],
1014            '4pl' => [
1015                'uživatel'    => 'uživatele',
1016                'Wikibooks'   => 'Wikiknihy',
1017                'Wikifunctions' => 'Wikifunkce',
1018                'Wikinews'    => 'Wikizprávy',
1019                'Wikipedia'   => 'Wikipedie',
1020                'Wikiquote'   => 'Wikicitáty',
1021                'Wikisource'  => 'Wikizdroje',
1022                'Wikispecies' => 'Wikidruhy',
1023                'Wikiversity' => 'Wikiverzity',
1024                'Wikivoyage'  => 'Wikicesty',
1025                'Wiktionary'  => 'Wikislovníky',
1026                'Wikislovník' => 'Wikislovníky',
1027                'Wikiverzita' => 'Wikiverzity',
1028            ],
1029            '5pl' => [
1030                'uživatel'    => 'uživatelé',
1031                'Wikibooks'   => 'Wikiknihy',
1032                'Wikifunctions' => 'Wikifunkce',
1033                'Wikinews'    => 'Wikizprávy',
1034                'Wikipedia'   => 'Wikipedie',
1035                'Wikiquote'   => 'Wikicitáty',
1036                'Wikisource'  => 'Wikizdroje',
1037                'Wikispecies' => 'Wikidruhy',
1038                'Wikiversity' => 'Wikiverzity',
1039                'Wikivoyage'  => 'Wikicesty',
1040                'Wiktionary'  => 'Wikislovníky',
1041                'Wikislovník' => 'Wikislovníky',
1042                'Wikiverzita' => 'Wikiverzity',
1043            ],
1044            '6pl' => [
1045                'uživatel'    => 'uživatelích',
1046                'Wikibooks'   => 'Wikiknihách',
1047                'Wikidata'    => 'Wikidatech',
1048                'Wikifunctions' => 'Wikifunkcích',
1049                'Wikinews'    => 'Wikizprávách',
1050                'Wikipedia'   => 'Wikipediích',
1051                'Wikiquote'   => 'Wikicitátech',
1052                'Wikisource'  => 'Wikizdrojích',
1053                'Wikispecies' => 'Wikidruzích',
1054                'Wikiversity' => 'Wikiverzitách',
1055                'Wikivoyage'  => 'Wikicestách',
1056                'Wiktionary'  => 'Wikislovnících',
1057                'Wikicesty'   => 'Wikicestách',
1058                'Wikicitáty'  => 'Wikicitátech',
1059                'Wikidruhy'   => 'Wikidruzích',
1060                'Wikifunkce'  => 'Wikifunkcích',
1061                'Wikiknihy'   => 'Wikiknihách',
1062                'Wikipedie'   => 'Wikipediích',
1063                'Wikislovník' => 'Wikislovnících',
1064                'Wikiverzita' => 'Wikiverzitách',
1065                'Wikizdroje'  => 'Wikizdrojích',
1066                'Wikizprávy'  => 'Wikizprávách',
1067            ],
1068            '7pl' => [
1069                'uživatel'    => 'uživateli',
1070                'Wikibooks'   => 'Wikiknihami',
1071                'Wikidata'    => 'Wikidaty',
1072                'Wikifunctions' => 'Wikifunkcemi',
1073                'Wikinews'    => 'Wikizprávami',
1074                'Wikipedia'   => 'Wikipediemi',
1075                'Wikiquote'   => 'Wikicitáty',
1076                'Wikisource'  => 'Wikizdroji',
1077                'Wikispecies' => 'Wikidruhy',
1078                'Wikiversity' => 'Wikiverzitami',
1079                'Wikivoyage'  => 'Wikicestami',
1080                'Wiktionary'  => 'Wikislovníky',
1081                'Wikicesty'   => 'Wikicestami',
1082                'Wikifunkce'  => 'Wikifunkcemi',
1083                'Wikiknihy'   => 'Wikiknihami',
1084                'Wikipedie'   => 'Wikipediemi',
1085                'Wikislovník' => 'Wikislovníky',
1086                'Wikiverzita' => 'Wikiverzitami',
1087                'Wikizdroje'  => 'Wikizdroji',
1088                'Wikizprávy'  => 'Wikizprávami',
1089            ],
1090        ];
1091
1092        $wgGrammarForms['dsb'] = [
1093            // genitive
1094            'genitiw' => [
1095                'Wikipedija'  => 'Wikipedije',
1096                'Wikiknihi'   => 'Wikiknih',
1097                'Wikinowiny'  => 'Wikinowin',
1098                'Wikižórło'   => 'Wikižórła',
1099                'Wikicitaty'  => 'Wikicitatow',
1100                'Wikisłownik' => 'Wikisłownika',
1101            ],
1102            // dative
1103            'datiw' => [
1104                'Wikipedija'  => 'Wikipediji',
1105                'Wikiknihi'   => 'Wikikniham',
1106                'Wikinowiny'  => 'Wikinowinam',
1107                'Wikižórło'   => 'Wikižórłu',
1108                'Wikicitaty'  => 'Wikicitatam',
1109                'Wikisłownik' => 'Wikisłownikej',
1110            ],
1111            // accusative
1112            'akuzativ' => [
1113                'Wikipedija'  => 'Wikipediju',
1114                'Wikiknihi'   => 'Wikiknknihi',
1115            ],
1116            // instrumental
1117            'instrumental' => [
1118                'Wikipedija'  => 'Wikipediju',
1119                'Wikiknihi'   => 'Wikiknihami',
1120                'Wikinowiny'  => 'Wikinowinami',
1121                'Wikižórło'   => 'Wikižórłom',
1122                'Wikicitaty'  => 'Wikicitatami',
1123                'Wikisłownik' => 'Wikisłownikom',
1124            ],
1125            // locative
1126            'lokatiw' => [
1127                'Wikipedija'  => 'Wikipediji',
1128                'Wikiknihi'   => 'Wikiknihach',
1129                'Wikinowiny'  => 'Wikinowinach',
1130                'Wikižórło'   => 'Wikižórłu',
1131                'Wikicitaty'  => 'Wikicitatach',
1132                'Wikisłownik' => 'Wikisłowniku',
1133            ],
1134        ];
1135
1136        $wgGrammarForms['et'] = [
1137            'genitive' => [
1138                'Vikisõnastik'  => 'Vikisõnastiku',
1139                'Vikitekstid'   => 'Vikitekstide',
1140                'Vikitsitaadid' => 'Vikitsitaatide',
1141                'Vikiõpikud'    => 'Vikiõpikute',
1142            ],
1143            'partitive' => [
1144                'Vikipeedia'    => 'Vikipeediat',
1145                'Vikisõnastik'  => 'Vikisõnastikku',
1146                'Vikitekstid'   => 'Vikitekste',
1147                'Vikitsitaadid' => 'Vikitsitaate',
1148                'Vikiõpikud'    => 'Vikiõpikuid',
1149            ],
1150            'illative' => [
1151                'Vikipeedia'    => 'Vikipeediasse',
1152                'Vikisõnastik'  => 'Vikisõnastikku',
1153                'Vikitekstid'   => 'Vikitekstidesse',
1154                'Vikitsitaadid' => 'Vikitsitaatidesse',
1155                'Vikiõpikud'    => 'Vikiõpikutesse',
1156            ],
1157            'inessive' => [
1158                'Vikipeedia'    => 'Vikipeedias',
1159                'Vikisõnastik'  => 'Vikisõnastikus',
1160                'Vikitekstid'   => 'Vikitekstides',
1161                'Vikitsitaadid' => 'Vikitsitaatides',
1162                'Vikiõpikud'    => 'Vikiõpikutes',
1163            ],
1164            'elative' => [
1165                'Vikipeedia'    => 'Vikipeediast',
1166                'Vikisõnastik'  => 'Vikisõnastikust',
1167                'Vikitekstid'   => 'Vikitekstidest',
1168                'Vikitsitaadid' => 'Vikitsitaatidest',
1169                'Vikiõpikud'    => 'Vikiõpikutest',
1170            ],
1171        ];
1172
1173        $wgGrammarForms['fi'] = [
1174            'genitive' => [
1175                'Wikiuutiset' => 'Wikiuutisten',
1176                'Wikisitaatit' => 'Wikisitaattien',
1177                'Wikimedia Suomi' => 'Wikimedia Suomen',
1178                'Wikimatkat' => 'Wikimatkojen',
1179            ],
1180            'partitive' => [
1181                'Wikiuutiset' => 'Wikiuutisia',
1182                'Wikisitaatit' => 'Wikisitaatteja',
1183                'Wikimedia Suomi' => 'Wikimedia Suomea',
1184                'Wikimatkat' => 'Wikimatkoja',
1185            ],
1186            'elative' => [
1187                'Wikiuutiset' => 'Wikiuutisista',
1188                'Wikisitaatit' => 'Wikisitaateista',
1189                'Wikimedia Suomi' => 'Wikimedia Suomesta',
1190                'Wikimatkat' => 'Wikimatkoista',
1191            ],
1192            'inessive' => [
1193                'Wikiuutiset' => 'Wikiuutisissa',
1194                'Wikisitaatit' => 'Wikisitaateissa',
1195                'Wikimedia Suomi' => 'Wikimedia Suomessa',
1196                'Wikimatkat' => 'Wikimatkoissa',
1197            ],
1198            'illative' => [
1199                'Wikiuutiset' => 'Wikiuutisiin',
1200                'Wikisitaatit' => 'Wikisitaatteihin',
1201                'Wikimedia Suomi' => 'Wikimedia Suomeen',
1202                'Wikimatkat' => 'Wikimatkoihin',
1203            ],
1204        ];
1205
1206        $wgGrammarForms['ga'] = [
1207            'genitive' => [
1208                'Vicipéid'     => 'Vicipéide',
1209                'Vicífhoclóir' => 'Vicífhoclóra',
1210                'Vicíleabhair' => 'Vicíleabhar',
1211                'Vicíshliocht' => 'Vicíshleachta',
1212                'Vicífhoinse'  => 'Vicífhoinse',
1213                'Vicíghnéithe' => 'Vicíghnéithe',
1214                'Vicínuacht'   => 'Vicínuachta',
1215            ],
1216        ];
1217
1218        $wgGrammarForms['gsw'] = [
1219            // dative
1220            'dativ' => [
1221                'Wikipedia'       => 'vo de Wikipedia',
1222                'Wikinorchrichte' => 'vo de Wikinochrichte',
1223                'Wiktionaire'     => 'vom Wiktionaire',
1224                'Wikibuecher'     => 'vo de Wikibuecher',
1225                'Wikisprüch'      => 'vo de Wikisprüch',
1226                'Wikiquälle'      => 'vo de Wikiquälle',
1227            ],
1228            // accusative
1229            'akkusativ' => [
1230                'Wikipedia'       => 'd Wikipedia',
1231                'Wikinorchrichte' => 'd Wikinorchrichte',
1232                'Wiktionaire'     => 's Wiktionaire',
1233                'Wikibuecher'     => 'd Wikibuecher',
1234                'Wikisprüch'      => 'd Wikisprüch',
1235                'Wikiquälle'      => 'd Wikiquälle',
1236            ],
1237            // nominative
1238            'nominativ' => [
1239                'Wikipedia'       => 'd Wikipedia',
1240                'Wikinorchrichte' => 'd Wikinorchrichte',
1241                'Wiktionaire'     => 's Wiktionaire',
1242                'Wikibuecher'     => 'd Wikibuecher',
1243                'Wikisprüch'      => 'd Wikisprüch',
1244                'Wikiquälle'      => 'd Wikiquälle',
1245            ],
1246        ];
1247
1248        $wgGrammarForms['hsb'] = [
1249            // genitive
1250            'genitiw' => [
1251                'Wikipedija'  => 'Wikipedije',
1252                'Wikiknihi'   => 'Wikiknih',
1253                'Wikinowiny'  => 'Wikinowin',
1254                'Wikižórło'   => 'Wikižórła',
1255                'Wikicitaty'  => 'Wikicitatow',
1256                'Wikisłownik' => 'Wikisłownika',
1257            ],
1258            // dative
1259            'datiw' => [
1260                'Wikipedija'  => 'Wikipediji',
1261                'Wikiknihi'   => 'Wikikniham',
1262                'Wikinowiny'  => 'Wikinowinam',
1263                'Wikižórło'   => 'Wikižórłu',
1264                'Wikicitaty'  => 'Wikicitatam',
1265                'Wikisłownik' => 'Wikisłownikej',
1266            ],
1267            // accusative
1268            'akuzativ' => [
1269                'Wikipedija'  => 'Wikipediju',
1270                'Wikiknihi'   => 'Wikiknknihi',
1271            ],
1272            // instrumental
1273            'instrumental' => [
1274                'Wikipedija'  => 'Wikipediju',
1275                'Wikiknihi'   => 'Wikiknihami',
1276                'Wikinowiny'  => 'Wikinowinami',
1277                'Wikižórło'   => 'Wikižórłom',
1278                'Wikicitaty'  => 'Wikicitatami',
1279                'Wikisłownik' => 'Wikisłownikom',
1280            ],
1281            // locative
1282            'lokatiw' => [
1283                'Wikipedija'  => 'Wikipediji',
1284                'Wikiknihi'   => 'Wikiknihach',
1285                'Wikinowiny'  => 'Wikinowinach',
1286                'Wikižórło'   => 'Wikižórłu',
1287                'Wikicitaty'  => 'Wikicitatach',
1288                'Wikisłownik' => 'Wikisłowniku',
1289            ],
1290        ];
1291
1292        $wgGrammarForms['hu'] = [
1293            'rol' => [
1294                'Wikipédia'   => 'Wikipédiáról',
1295                'Wikidézet'   => 'Wikidézetről',
1296                'Wikiszótár'  => 'Wikiszótárról',
1297                'Wikikönyvek' => 'Wikikönyvekről',
1298            ],
1299            'ba' => [
1300                'Wikipédia'   => 'Wikipédiába',
1301                'Wikidézet'   => 'Wikidézetbe',
1302                'Wikiszótár'  => 'Wikiszótárba',
1303                'Wikikönyvek' => 'Wikikönyvekbe',
1304            ],
1305            'k' => [
1306                'Wikipédia'   => 'Wikipédiák',
1307                'Wikidézet'   => 'Wikidézetek',
1308                'Wikiszótár'  => 'Wikiszótárak',
1309            ],
1310        ];
1311        // T289767
1312        $wgGrammarForms['ks'] = [
1313            // ergative
1314            'کرٛاوَل' => [
1315                'وِکیٖلۄغَتھ' => 'وِکیٖلۄغتَن',
1316            ],
1317            // dative
1318            'دُکرٛٲوؠ' => [
1319                'وِکیٖلۄغَتھ' => 'وِکیٖلۄغتَس',
1320            ],
1321            // ablative
1322            'آیِتؠ' => [
1323                'وِکیٖلۄغَتھ' => 'وِکیٖلۄغتہٕ',
1324            ],
1325        ];
1326        $wgGrammarForms['la'] = [
1327            'genitive' => [
1328                'Vicimedia Communia' => 'Vicimediorum Communium',
1329            ],
1330            'ablative' => [
1331                'Vicimedia Communia' => 'Vicimediis Communibus',
1332            ],
1333        ];
1334
1335        $wgGrammarForms['lv'] = [
1336            'ģenitīvs' => [
1337                'Vikipēdija'   => 'Vikipēdijas',
1338                'Vikivārdnīca' => 'Vikivārdnīcas',
1339            ],
1340            'datīvs' => [
1341                'Vikipēdija'   => 'Vikipēdijai',
1342                'Vikivārdnīca' => 'Vikivārdnīcai',
1343            ],
1344            'akuzatīvs' => [
1345                'Vikipēdija'   => 'Vikipēdiju',
1346                'Vikivārdnīca' => 'Vikivārdnīcu',
1347            ],
1348            'lokatīvs' => [
1349                'Vikipēdija'   => 'Vikipēdijā',
1350                'Vikivārdnīca' => 'Vikivārdnīcā',
1351            ],
1352        ];
1353
1354        $wgGrammarForms['pl'] = [
1355            'D.lp' => [
1356                'Wikicytaty'   => 'Wikicytatów',
1357                'Wikipedia'    => 'Wikipedii',
1358                'Wikipodróże'  => 'Wikipodróży',
1359                'Wikisłownik'  => 'Wikisłownika',
1360                'Wikiźródła'   => 'Wikiźródeł',
1361                'Wikidane'     => 'Wikidanych',
1362                'Wikimania'    => 'Wikimanii',
1363                'Wikifunkcje'  => 'Wikifunkcji',
1364            ],
1365            'C.lp' => [
1366                'Wikicytaty'   => 'Wikicytatom',
1367                'Wikipedia'    => 'Wikipedii',
1368                'Wikipodróże'  => 'Wikipodróżom',
1369                'Wikisłownik'  => 'Wikisłownikowi',
1370                'Wikiźródła'   => 'Wikiźródłom',
1371                'Wikidane'     => 'Wikidanym',
1372                'Wikimania'    => 'Wikimanii',
1373                'Wikifunkcje'  => 'Wikifunkcjom',
1374            ],
1375            'B.lp' => [
1376                'Wikipedia'    => 'Wikipedię',
1377                'Wikimania'    => 'Wikimanię',
1378            ],
1379            'N.lp' => [
1380                'Wikicytaty'   => 'Wikicytatami',
1381                'Wikipedia'    => 'Wikipedią',
1382                'Wikipodróże'  => 'Wikipodróżami',
1383                'Wikisłownik'  => 'Wikisłownikiem',
1384                'Wikiźródła'   => 'Wikiźródłami',
1385                'Wikidane'     => 'Wikidanymi',
1386                'Wikimania'    => 'Wikimanią',
1387                'Wikifunkcje'  => 'Wikifunkcjami',
1388            ],
1389            'MS.lp' => [
1390                'Wikicytaty'   => 'Wikicytatach',
1391                'Wikipedia'    => 'Wikipedii',
1392                'Wikipodróże'  => 'Wikipodróżach',
1393                'Wikisłownik'  => 'Wikisłowniku',
1394                'Wikiźródła'   => 'Wikiźródłach',
1395                'Wikidane'     => 'Wikidanych',
1396                'Wikimania'    => 'Wikimanii',
1397                'Wikifunkcje'  => 'Wikifunkcjach',
1398            ],
1399            'W.lp' => [
1400                'Wikipedia'    => 'Wikipedio',
1401                'Wikisłownik'  => 'Wikisłowniku',
1402                'Wikimania'    => 'Wikimanio',
1403            ],
1404        ];
1405
1406        $wgGrammarForms['rmy'] = [
1407            // genitive (m.sg.)
1408            'genitive-m-sg' => [
1409                'Vikipidiya' => 'Vikipidiyako',
1410                'Vikcyonaro' => 'Vikcyonaresko',
1411            ],
1412            // genitive (f.sg.)
1413            'genitive-f-sg' => [
1414                'Vikipidiya' => 'Vikipidiyaki',
1415                'Vikcyonaro' => 'Vikcyonareski',
1416            ],
1417            // genitive (pl.)
1418            'genitive-pl' => [
1419                'Vikipidiya' => 'Vikipidiyake',
1420                'Vikcyonaro' => 'Vikcyonareske',
1421            ],
1422            // dative
1423            'dativ' => [
1424                'Vikipidiya' => 'Wikipediji',
1425                'Vikcyonaro' => 'Vikcyonareske',
1426            ],
1427            // locative
1428            'locative' => [
1429                'Vikipidiya' => 'Wikipedijo',
1430                'Vikcyonaro' => 'Vikcyonareste',
1431            ],
1432            // ablative
1433            'ablative' => [
1434                'Vikipidiya' => 'o Wikipediji',
1435                'Vikcyonaro' => 'Vikcyonarestar',
1436            ],
1437            // instrumental
1438            'instrumental' => [
1439                'Vikipidiya' => 'z Wikipedijo',
1440                'Vikcyonaro' => 'Vikcyonaresa',
1441            ],
1442        ];
1443
1444        $wgGrammarForms['sk'] = [
1445            'genitív' => [
1446                'Wikipédia'   => 'Wikipédie',
1447                'Wikislovník' => 'Wikislovníku',
1448                'Wikicitáty'  => 'Wikicitátov',
1449                'Wikiknihy'   => 'Wikikníh',
1450            ],
1451            'datív' => [
1452                'Wikipédia'   => 'Wikipédii',
1453                'Wikislovník' => 'Wikislovníku',
1454                'Wikicitáty'  => 'Wikicitátom',
1455                'Wikiknihy'   => 'Wikiknihám',
1456            ],
1457            'akuzatív' => [
1458                'Wikipédia'   => 'Wikipédiu',
1459                'Wikislovník' => 'Wikislovník',
1460                'Wikicitáty'  => 'Wikicitáty',
1461                'Wikiknihy'   => 'Wikiknihy',
1462            ],
1463            'lokál' => [
1464                'Wikipédia'   => 'Wikipédii',
1465                'Wikislovník' => 'Wikislovníku',
1466                'Wikicitáty'  => 'Wikicitátoch',
1467                'Wikiknihy'   => 'Wikiknihách',
1468            ],
1469            'inštrumentál' => [
1470                'Wikipédia'   => 'Wikipédiou',
1471                'Wikislovník' => 'Wikislovníkom',
1472                'Wikicitáty'  => 'Wikicitátmi',
1473                'Wikiknihy'   => 'Wikiknihami',
1474            ],
1475        ];
1476
1477        $wgGrammarForms['sl'] = [
1478            // genitive
1479            'rodilnik' => [
1480                'Wikipedija'  => 'Wikipedije',
1481                'Wikiknjige'  => 'Wikiknjig',
1482                'Wikinovice'  => 'Wikinovic',
1483                'Wikinavedek' => 'Wikinavedka',
1484                'Wikivir'     => 'Wikivira',
1485                'Wikislovar'  => 'Wikislovarja',
1486            ],
1487            // dative
1488            'dajalnik' => [
1489                'Wikipedija'  => 'Wikipediji',
1490                'Wikiknjige'  => 'Wikiknjigam',
1491                'Wikinovice'  => 'Wikinovicam',
1492                'Wikinavedek' => 'Wikinavedku',
1493                'Wikivir'     => 'Wikiviru',
1494                'Wikislovar'  => 'Wikislovarju',
1495            ],
1496            // accusative
1497            'tožilnik' => [
1498                'Wikipedija'  => 'Wikipedijo',
1499                // no need to transform the others
1500            ],
1501            // locative
1502            'mestnik' => [
1503                'Wikipedija'  => 'o Wikipediji',
1504                'Wikiknjige'  => 'o Wikiknjigah',
1505                'Wikinovice'  => 'o Wikinovicah',
1506                'Wikinavedek' => 'o Wikinavedku',
1507                'Wikivir'     => 'o Wikiviru',
1508                'Wikislovar'  => 'o Wikislovarju',
1509            ],
1510            // instrumental
1511            'orodnik' => [
1512                'Wikipedija'  => 'z Wikipedijo',
1513                'Wikiknjige'  => 'z Wikiknjigami',
1514                'Wikinovice'  => 'z Wikinovicami',
1515                'Wikinavedek' => 'z Wikinavedkom',
1516                'Wikivir'     => 'z Wikivirom',
1517                'Wikislovar'  => 'z Wikislovarjem',
1518            ],
1519        ];
1520
1521        $wgGrammarForms['sr-ec'] =
1522        $wgGrammarForms['sr-cyrl'] = [
1523            // genitive
1524            'генитив' => [
1525                'Викиречник'  => 'Викиречника',
1526                'Викицитат'   => 'Викицитата',
1527                'Викизворник' => 'Викизворника',
1528                'Викикњиге'   => 'Викикњига',
1529                'Википедија'  => 'Википедије',
1530                'Википодаци'  => 'Википодатака',
1531                'Викимедијина остава' => 'Викимедијине оставе',
1532                'Викиверзитет' => 'Викиверзитета',
1533            ],
1534            // dative
1535            'датив' => [
1536                'Викиречник'  => 'Викиречнику',
1537                'Викицитат'   => 'Викицитату',
1538                'Викизворник' => 'Викизворнику',
1539                'Викикњиге'   => 'Викикњигама',
1540                'Википедија'  => 'Википедији',
1541                'Википодаци'  => 'Википодацима',
1542                'Викиновости'   => 'Викиновистима',
1543                'Викимедијина остава' => 'Викимедијиној остави',
1544                'Викиверзитет' => 'Викиверзитету',
1545            ],
1546            // accusative
1547            'акузатив' => [
1548                'Викиречник'  => 'Викиречник',
1549                'Викицитат'   => 'Викицитат',
1550                'Викизворник' => 'Викизворник',
1551                'Википедија'  => 'Википедију',
1552                'Википодаци'  => 'Википодатке',
1553            ],
1554            // vocative
1555            'вокатив' => [
1556                'Викиречник'  => 'Викиречниче',
1557                'Викизворник' => 'Викизворниче',
1558                'Википедија'  => 'Википедијо',
1559                'Викимедијина остава' => 'Викимедијина оставо',
1560                'Викиверзитет' => 'Викиверзитету',
1561            ],
1562            // instrumental
1563            'инструментал' => [
1564                'Викиречник'  => 'Викиречником',
1565                'Викицитат'   => 'Викицитатом',
1566                'Викизворник' => 'Викизворником',
1567                'Викикњиге'   => 'Викикњигама',
1568                'Википедија'  => 'Википедијом',
1569                'Википодаци'  => 'Википодацима',
1570                'Викиновости'   => 'Викиновостима',
1571                'Викимедијина остава' => 'Викимедијином оставом',
1572                'Викиверзитет' => 'Викиверзитетом',
1573            ],
1574            // locative
1575            'локатив' => [
1576                'Викиречник'  => 'Викиречнику',
1577                'Викицитат'   => 'Викицитату',
1578                'Викизворник' => 'Викизворнику',
1579                'Викикњиге'   => 'Викикњигама',
1580                'Википедија'  => 'Википедији',
1581                'Википодаци'  => 'Википодацима',
1582                'Викиновости'   => 'Викиновостима',
1583                'Викимедијина остава' => 'Викимедијиној остави',
1584                'Викиверзитет' => 'Викиверзитету',
1585            ],
1586        ];
1587
1588        $wgGrammarForms['sr-el'] =
1589        $wgGrammarForms['sr-latn'] = [
1590            // genitive
1591            'genitiv' => [
1592                'Vikirečnik'  => 'Vikirečnika',
1593                'Vikicitat'   => 'Vikicitata',
1594                'Vikizvornik' => 'Vikizvornika',
1595                'Vikiknjige'  => 'Vikiknjiga',
1596                'Vikipedija'  => 'Vikipedije',
1597                'Vikipodaci'  => 'Vikipodataka',
1598                'Vikimedijina ostava' => 'Vikimedijine ostave',
1599                'Vikiverzitet' => 'Vikiverziteta',
1600            ],
1601            // dative
1602            'dativ' => [
1603                'Vikirečnik'  => 'Vikirečniku',
1604                'Vikicitat'   => 'Vikicitatu',
1605                'Vikizvornik' => 'Vikizvorniku',
1606                'Vikiknjige'  => 'Vikiknjigama',
1607                'Vikipedija'  => 'Vikipediji',
1608                'Vikipodaci'  => 'Vikipodacima',
1609                'Vikinovosti'   => 'Vikinovostima',
1610                'Vikimedijina ostava' => 'Vikimedijinoj ostavi',
1611                'Vikiverzitet' => 'Vikiverzitetu',
1612            ],
1613            // accusative
1614            'akuzativ' => [
1615                'Vikirečnik'  => 'Vikirečnik',
1616                'Vikicitat'   => 'Vikicitat',
1617                'Vikizvornik' => 'Vikizvornik',
1618                'Vikipedija'  => 'Vikipediju',
1619                'Vikipodaci'  => 'Vikipodatke',
1620            ],
1621            // vocative
1622            'vokativ' => [
1623                'Vikirečnik'  => 'Vikirečniče',
1624                'Vikizvornik' => 'Vikizvorniče',
1625                'Vikipedija'  => 'Vikipedijo',
1626                'Vikimedijina ostava' => 'Vikimedijina ostavo',
1627                'Vikiverzitet' => 'Vikiverzitetu',
1628            ],
1629            // instrumental
1630            'instrumental' => [
1631                'Vikirečnik'  => 'Vikirečnikom',
1632                'Vikicitat'   => 'Vikicitatom',
1633                'Vikizvornik' => 'Vikizvornikom',
1634                'Vikiknjige'  => 'Vikiknjigama',
1635                'Vikipedija'  => 'Vikipedijom',
1636                'Vikipodaci'  => 'Vikipodacima',
1637                'Vikinovosti'   => 'Vikinovostima',
1638                'Vikimedijina ostava' => 'Vikimedijinom ostavom',
1639                'Vikiverzitet' => 'Vikiverzitetom',
1640            ],
1641            // locative
1642            'lokativ' => [
1643                'Vikirečnik'  => 'Vikirečniku',
1644                'Vikicitat'   => 'Vikicitatu',
1645                'Vikizvornik' => 'Vikizvorniku',
1646                'Vikiknjige'  => 'Vikiknjigama',
1647                'Vikipedija'  => 'Vikipediji',
1648                'Vikipodaci'  => 'Vikipodacima',
1649                'Vikinovosti'   => 'Vikinovostima',
1650                'Vikimedijina ostava' => 'Vikimedijinoj ostavi',
1651                'Vikiverzitet' => 'Vikiverzitetu',
1652            ],
1653        ];
1654
1655        $wgGrammarForms['uk'] = [
1656            // genitive
1657            'genitive' => [
1658                'Вікіпедія' => 'Вікіпедії',
1659                'Вікісловник' => 'Вікісловника',
1660                'Вікісховище' => 'Вікісховища',
1661                'Вікіпідручник' => 'Вікіпідручника',
1662                'Вікіцитати' => 'Вікіцитат',
1663                'Вікіджерела' => 'Вікіджерел',
1664                'Вікіновини' => 'Вікіновин',
1665                'Вікідані' => 'Вікіданих',
1666                'Вікімандри' => 'Вікімандрів',
1667            ],
1668            // dative
1669            'dative' => [
1670                'Вікіпедія' => 'Вікіпедії',
1671                'Вікісловник' => 'Вікісловнику',
1672                'Вікісховище' => 'Вікісховищу',
1673                'Вікіпідручник' => 'Вікіпідручнику',
1674                'Вікіцитати' => 'Вікіцитатам',
1675                'Вікіджерела' => 'Вікіджерелам',
1676                'Вікіновини' => 'Вікіновинам',
1677                'Вікідані' => 'Вікіданим',
1678                'Вікімандри' => 'Вікімандрам',
1679            ],
1680            // accusative
1681            'accusative' => [
1682                'Вікіпедія' => 'Вікіпедію',
1683                'Вікісловник' => 'Вікісловник',
1684                'Вікісховище' => 'Вікісховище',
1685                'Вікіпідручник' => 'Вікіпідручник',
1686                'Вікіцитати' => 'Вікіцитати',
1687                'Вікіджерела' => 'Вікіджерела',
1688                'Вікіновини' => 'Вікіновини',
1689                'Вікідані' => 'Вікідані',
1690                'Вікімандри' => 'Вікімандри',
1691            ],
1692            // instrumental
1693            'instrumental' => [
1694                'Вікіпедія' => 'Вікіпедією',
1695                'Вікісловник' => 'Вікісловником',
1696                'Вікісховище' => 'Вікісховищем',
1697                'Вікіпідручник' => 'Вікіпідручником',
1698                'Вікіцитати' => 'Вікіцитатами',
1699                'Вікіджерела' => 'Вікіджерелами',
1700                'Вікіновини' => 'Вікіновинами',
1701                'Вікідані' => 'Вікіданими',
1702                'Вікімандри' => 'Вікімандрами',
1703            ],
1704            // locative
1705            'locative' => [
1706                'Вікіпедія' => 'у Вікіпедії',
1707                'Вікісловник' => 'у Вікісловнику',
1708                'Вікісховище' => 'у Вікісховищі',
1709                'Вікіпідручник' => 'у Вікіпідручнику',
1710                'Вікіцитати' => 'у Вікіцитатах',
1711                'Вікіджерела' => 'у Вікіджерелах',
1712                'Вікіновини' => 'у Вікіновинах',
1713                'Вікідані' => 'у Вікіданих',
1714                'Вікімандри' => 'у Вікімандрах',
1715            ],
1716            // vocative
1717            'vocative' => [
1718                'Вікіпедія' => 'Вікіпедіє',
1719                'Вікісловник' => 'Вікісловнику',
1720                'Вікісховище' => 'Вікісховище',
1721                'Вікіпідручник' => 'Вікіпідручнику',
1722                'Вікіцитати' => 'Вікіцитати',
1723                'Вікіджерела' => 'Вікіджерела',
1724                'Вікіновини' => 'Вікіновини',
1725                'Вікідані' => 'Вікідані',
1726                'Вікімандри' => 'Вікімандри',
1727            ],
1728        ];
1729
1730        // Avoid weirdness if both extensions are loaded at the same time.
1731        if ( !ExtensionRegistry::getInstance()->isLoaded( 'UserMerge' ) ) {
1732            global $wgLogTypes, $wgLogNames, $wgLogHeaders, $wgLogActionsHandlers, $wgActionFilteredLogs;
1733
1734            $wgLogTypes[] = 'usermerge';
1735            $wgLogNames['usermerge'] = 'wikimedia-usermerge-logpage';
1736            $wgLogHeaders['usermerge'] = 'wikimedia-usermerge-logpagetext';
1737
1738            $wgLogActionsHandlers['usermerge/*'] = WMUserMergeLogFormatter::class;
1739            $wgActionFilteredLogs['usermerge'] = [
1740                'mergeuser'  => [ 'mergeuser' ],
1741                'deleteuser' => [ 'deleteuser' ],
1742            ];
1743        }
1744    }
1745
1746    /**
1747     * Allows last minute changes to the output page, e.g. adding of CSS or JavaScript by extensions.
1748     *
1749     * @param OutputPage $out The Output page object
1750     * @param Skin $skin Skin object that will be used to generate the page
1751     */
1752    public function onBeforePageDisplay( $out, $skin ): void {
1753        $skins = $out->getConfig()->get( 'WikimediaStylesSkins' );
1754
1755        if ( in_array( $skin->getSkinName(), $skins ) ) {
1756            $out->addModuleStyles( [ 'ext.wikimediamessages.styles' ] );
1757        }
1758    }
1759
1760    /**
1761     * @see https://www.mediawiki.org/wiki/Manual:Hooks/ResourceLoaderRegisterModules
1762     *
1763     * @param ResourceLoader $resourceLoader
1764     */
1765    public function onResourceLoaderRegisterModules( ResourceLoader $resourceLoader ): void {
1766        if ( $this->extensionRegistry->isLoaded( 'IPInfo' ) ) {
1767            $resourceLoader->register( 'ext.wikimediaMessages.ipInfo.hooks', [
1768                'localBasePath' => dirname( __DIR__ ) . '/modules/ext.wikimediaMessages.ipInfo.hooks',
1769                'remoteExtPath' => 'WikimediaMessages/modules/ext.wikimediaMessages.ipInfo.hooks',
1770                'scripts' => 'infobox.js',
1771                'styles' => 'infobox.less',
1772                'messages' => [
1773                    'ipinfo-global-contributions-url-label',
1774                    'ipinfo-global-contributions-url',
1775                    'ipinfo-xtools-url-label',
1776                    'ipinfo-xtools-url',
1777                ],
1778                'dependencies' => [
1779                    'ext.ipInfo',
1780                ],
1781            ] );
1782        }
1783    }
1784
1785    /**
1786     * Handle SpecialPageBeforeExecute hook
1787     *
1788     * @param SpecialPage $special
1789     * @param string|null $subPage
1790     */
1791    public function onSpecialPageBeforeExecute( $special, $subPage ) {
1792        $this->addIPInfoLinks( $special, $subPage );
1793    }
1794
1795    /**
1796     * @param SpecialPage $special
1797     * @param string|null $subPage
1798     */
1799    private function addIPInfoLinks( $special, $subPage ): void {
1800        if (
1801            $special->getName() !== 'Contributions' &&
1802            $special->getName() !== 'DeletedContributions'
1803        ) {
1804            return;
1805        }
1806
1807        // Return if target is not an IP address
1808        if ( $subPage === null || !IPUtils::isValid( $subPage ) ) {
1809            return;
1810        }
1811
1812        $accessingUser = $special->getUser();
1813        $isBetaFeaturesLoaded = $this->extensionRegistry->isLoaded( 'BetaFeatures' );
1814
1815        // Check the same permissions and preferences as
1816        // MediaWiki\IPInfo\HookHandler\InfoboxHandler
1817        if (
1818            !$this->permissionManager->userHasRight( $accessingUser, 'ipinfo' ) ||
1819            ( $isBetaFeaturesLoaded &&
1820                !$this->userOptionsLookup->getOption( $accessingUser, 'ipinfo-beta-feature-enable' ) )
1821        ) {
1822            return;
1823        }
1824
1825        $special->getOutput()->addModules( 'ext.wikimediaMessages.ipInfo.hooks' );
1826    }
1827}