Merge "objectcache: fix WRITE_ALLOW_SEGMENTS in BagOStuff cas() and add() methods"
authorjenkins-bot <jenkins-bot@gerrit.wikimedia.org>
Tue, 20 Aug 2019 15:50:58 +0000 (15:50 +0000)
committerGerrit Code Review <gerrit@wikimedia.org>
Tue, 20 Aug 2019 15:50:58 +0000 (15:50 +0000)
43 files changed:
docs/hooks.txt
docs/pageupdater.txt
includes/ServiceWiring.php
includes/changes/ChangesList.php
includes/jobqueue/jobs/ActivityUpdateJob.php
includes/logging/LogEntry.php
includes/objectcache/ObjectCache.php
includes/registration/ExtensionRegistry.php
includes/resourceloader/ResourceLoaderFileModule.php
includes/specialpage/ChangesListSpecialPage.php
includes/specials/SpecialJavaScriptTest.php
languages/i18n/ar.json
languages/i18n/da.json
languages/i18n/en.json
languages/i18n/fr.json
languages/i18n/ja.json
languages/i18n/jv.json
languages/i18n/lv.json
languages/i18n/min.json
languages/i18n/nap.json
languages/i18n/nds.json
languages/i18n/nqo.json
languages/i18n/pt-br.json
languages/i18n/qqq.json
languages/i18n/ro.json
languages/i18n/roa-tara.json
languages/i18n/sd.json
languages/i18n/sh.json
languages/i18n/sl.json
languages/i18n/sv.json
languages/i18n/th.json
languages/i18n/vec.json
languages/i18n/zh-hant.json
maintenance/createAndPromote.php
maintenance/mctest.php
resources/Resources.php
resources/src/mediawiki.rcfilters/Controller.js
resources/src/mediawiki.widgets/mw.widgets.TitleOptionWidget.js
tests/common/TestsAutoLoader.php
tests/phpunit/includes/libs/filebackend/fsfile/TempFSFileIntegrationTest.php [new file with mode: 0644]
tests/phpunit/includes/libs/objectcache/BagOStuffTest.php
tests/phpunit/includes/specialpage/ChangesListSpecialPageTest.php
tests/phpunit/unit/includes/libs/filebackend/fsfile/TempFSFileTestTrait.php [new file with mode: 0644]

index d832012..6207b12 100644 (file)
@@ -91,23 +91,29 @@ title-reversing if-blocks spread all over the codebase in showAnArticle,
 deleteAnArticle, exportArticle, etc., we can concentrate it all in an extension
 file:
 
-       function reverseArticleTitle( $article ) {
+       function onArticleShow( &$article ) {
                # ...
        }
 
-       function reverseForExport( $article ) {
+       function onArticleDelete( &$article ) {
                # ...
        }
 
-The setup function for the extension just has to add its hook functions to the
-appropriate events:
-
-       setupTitleReversingExtension() {
-               global $wgHooks;
+       function onArticleExport( &$article ) {
+               # ...
+       }
 
-               $wgHooks['ArticleShow'][] = 'reverseArticleTitle';
-               $wgHooks['ArticleDelete'][] = 'reverseArticleTitle';
-               $wgHooks['ArticleExport'][] = 'reverseForExport';
+General practice is to have a dedicated file for functions activated by hooks,
+which functions named 'onHookName'. In the example above, the file
+'ReverseHooks.php' includes the functions that should be activated by the
+'ArticleShow', 'ArticleDelete', and 'ArticleExport' hooks. The 'extension.json'
+file with the extension's registration just has to add its hook functions
+to the appropriate events:
+
+       "Hooks": {
+               "ArticleShow": "ReverseHooks:onArticleShow",
+               "ArticleDelete": "ReverseHooks::onArticleDelete",
+               "ArticleExport": "ReverseHooks::onArticleExport"
        }
 
 Having all this code related to the title-reversion option in one place means
index fd084c0..3d113f6 100644 (file)
@@ -148,7 +148,7 @@ parent of $revision parameter passed to prepareUpdate().
 transformation (PST) and allow subsequent access to the canonical ParserOutput of the
 revision. getSlots() and getCanonicalParserOutput() as well as getSecondaryDataUpdates()
 may be used after prepareContent() was called. Calling prepareContent() with the same
-parameters again has no effect. Calling it again with mismatching paramters, or calling
+parameters again has no effect. Calling it again with mismatching parameters, or calling
 it after prepareUpdate() was called, triggers a LogicException.
 
 - prepareUpdate() is called after the new revision has been created. This may happen
index bb6c2c2..0b4ce4a 100644 (file)
@@ -268,9 +268,10 @@ return [
        },
 
        'LocalServerObjectCache' => function ( MediaWikiServices $services ) : BagOStuff {
+               $config = $services->getMainConfig();
                $cacheId = \ObjectCache::detectLocalServerCache();
 
-               return \ObjectCache::newFromId( $cacheId );
+               return \ObjectCache::newFromParams( $config->get( 'ObjectCaches' )[$cacheId] );
        },
 
        'MagicWordFactory' => function ( MediaWikiServices $services ) : MagicWordFactory {
index e2b35a8..7807877 100644 (file)
@@ -232,6 +232,13 @@ class ChangesList extends ContextSource {
                $classes[] = Sanitizer::escapeClass( self::CSS_CLASS_PREFIX . 'ns-' .
                        $rc->mAttribs['rc_namespace'] );
 
+               $nsInfo = MediaWikiServices::getInstance()->getNamespaceInfo();
+               $classes[] = Sanitizer::escapeClass(
+                       self::CSS_CLASS_PREFIX .
+                       'ns-' .
+                       ( $nsInfo->isTalk( $rc->mAttribs['rc_namespace'] ) ? 'talk' : 'subject' )
+               );
+
                if ( $this->filterGroups !== null ) {
                        foreach ( $this->filterGroups as $filterGroup ) {
                                foreach ( $filterGroup->getFilters() as $filter ) {
index 4de72a9..d27056d 100644 (file)
@@ -42,7 +42,7 @@ class ActivityUpdateJob extends Job {
                static $required = [ 'type', 'userid', 'notifTime', 'curTime' ];
                $missing = implode( ', ', array_diff( $required, array_keys( $this->params ) ) );
                if ( $missing != '' ) {
-                       throw new InvalidArgumentException( "Missing paramter(s) $missing" );
+                       throw new InvalidArgumentException( "Missing parameter(s) $missing" );
                }
 
                $this->removeDuplicates = true;
index 17f72bd..ce68a91 100644 (file)
@@ -59,7 +59,7 @@ interface LogEntry {
        public function getParameters();
 
        /**
-        * Get the user for performed this action.
+        * Get the user who performed this action.
         *
         * @return User
         */
index 3bb0771..ad0f67e 100644 (file)
@@ -119,7 +119,7 @@ class ObjectCache {
         * @return BagOStuff
         * @throws InvalidArgumentException
         */
-       public static function newFromId( $id ) {
+       private static function newFromId( $id ) {
                global $wgObjectCaches;
 
                if ( !isset( $wgObjectCaches[$id] ) ) {
@@ -146,7 +146,7 @@ class ObjectCache {
         *
         * @return string
         */
-       public static function getDefaultKeyspace() {
+       private static function getDefaultKeyspace() {
                global $wgCachePrefix;
 
                $keyspace = $wgCachePrefix;
@@ -297,7 +297,7 @@ class ObjectCache {
         * @return WANObjectCache
         * @throws UnexpectedValueException
         */
-       public static function newWANCacheFromId( $id ) {
+       private static function newWANCacheFromId( $id ) {
                global $wgWANObjectCaches, $wgObjectCaches;
 
                if ( !isset( $wgWANObjectCaches[$id] ) ) {
index 9cae73c..3e65f6c 100644 (file)
@@ -146,7 +146,7 @@ class ExtensionRegistry {
         *  be loaded then).
         */
        public function loadFromQueue() {
-               global $wgVersion, $wgDevelopmentWarnings;
+               global $wgVersion, $wgDevelopmentWarnings, $wgObjectCaches;
                if ( !$this->queued ) {
                        return;
                }
@@ -169,10 +169,9 @@ class ExtensionRegistry {
                // We use a try/catch because we don't want to fail here
                // if $wgObjectCaches is not configured properly for APC setup
                try {
-                       // Don't use MediaWikiServices here to prevent instantiating it before extensions have
-                       // been loaded
+                       // Avoid MediaWikiServices to prevent instantiating it before extensions have loaded
                        $cacheId = ObjectCache::detectLocalServerCache();
-                       $cache = ObjectCache::newFromId( $cacheId );
+                       $cache = ObjectCache::newFromParams( $wgObjectCaches[$cacheId] );
                } catch ( InvalidArgumentException $e ) {
                        $cache = new EmptyBagOStuff();
                }
index eed2aed..d308d50 100644 (file)
@@ -1015,7 +1015,7 @@ class ResourceLoaderFileModule extends ResourceLoaderModule {
         * Keeps track of all used files and adds them to localFileRefs.
         *
         * @since 1.22
-        * @since 1.27 Added $context paramter.
+        * @since 1.27 Added $context parameter.
         * @throws Exception If less.php encounters a parse error
         * @param string $fileName File path of LESS source
         * @param ResourceLoaderContext $context Context in which to generate script
index bbbd6a8..2fa8fab 100644 (file)
@@ -1503,6 +1503,8 @@ abstract class ChangesListSpecialPage extends SpecialPage {
                if ( $opts[ 'namespace' ] !== '' ) {
                        $namespaces = explode( ';', $opts[ 'namespace' ] );
 
+                       $namespaces = $this->expandSymbolicNamespaceFilters( $namespaces );
+
                        if ( $opts[ 'associated' ] ) {
                                $namespaceInfo = MediaWikiServices::getInstance()->getNamespaceInfo();
                                $associatedNamespaces = array_map(
@@ -1948,4 +1950,21 @@ abstract class ChangesListSpecialPage extends SpecialPage {
        public function getDefaultDays() {
                return floatval( $this->getUser()->getOption( static::$daysPreferenceName ) );
        }
+
+       private function expandSymbolicNamespaceFilters( array $namespaces ) {
+               $nsInfo = MediaWikiServices::getInstance()->getNamespaceInfo();
+               $symbolicFilters = [
+                       'all-contents' => $nsInfo->getSubjectNamespaces(),
+                       'all-discussions' => $nsInfo->getTalkNamespaces(),
+               ];
+               $additionalNamespaces = [];
+               foreach ( $symbolicFilters as $name => $values ) {
+                       if ( in_array( $name, $namespaces ) ) {
+                               $additionalNamespaces = array_merge( $additionalNamespaces, $values );
+                       }
+               }
+               $namespaces = array_diff( $namespaces, array_keys( $symbolicFilters ) );
+               $namespaces = array_merge( $namespaces, $additionalNamespaces );
+               return array_unique( $namespaces );
+       }
 }
index 8c137aa..50a909f 100644 (file)
@@ -111,7 +111,7 @@ class SpecialJavaScriptTest extends SpecialPage {
                $qunitConfig = 'QUnit.config.autostart = false;'
                        . 'if (window.__karma__) {'
                        // karma-qunit's use of autostart=false and QUnit.start conflicts with ours.
-                       // Hack around this by replacing 'karma.loaded' with a no-op and perfom its duty of calling
+                       // Hack around this by replacing 'karma.loaded' with a no-op and perform its duty of calling
                        // `__karma__.start()` ourselves. See <https://github.com/karma-runner/karma-qunit/issues/27>.
                        . 'window.__karma__.loaded = function () {};'
                        . '}';
index 8e3fd79..60f54e2 100644 (file)
        "move-subpages": "انقل الصفحات الفرعية (حتى $1)",
        "move-talk-subpages": "انقل الصفحات الفرعية لصفحة النقاش (حتى $1)",
        "movepage-page-exists": "الصفحة $1 موجودة بالفعل ولا يمكن الكتابة عليها تلقائياً.",
+       "movepage-source-doesnt-exist": "الصفحة $1 غير موجودة ولا يمكن نقلها.",
        "movepage-page-moved": "نقلت صفحة $1 إلى $2 بنجاح.",
        "movepage-page-unmoved": "لم يمكن نقل صفحة $1 إلى $2.",
        "movepage-max-pages": "تم نقل الحد الأقصى وهو {{PLURAL:$1|صفحة واحدة|صفحتان|$1 صفحات|$1 صفحة}} ولن يتم نقل المزيد تلقائيا.",
        "delete_and_move_reason": "حُذِفت لإفساح مجال لنقل \"[[$1]]\"",
        "selfmove": "العنوان هو نفسه؛\nلا يمكن نقل صفحة على نفسها.",
        "immobile-source-namespace": "غير قادر على نقل الصفحات في النطاق \"$1\"",
+       "immobile-source-namespace-iw": "لا يمكن نقل الصفحات على الويكيات الأخرى من هذه الويكي.",
        "immobile-target-namespace": "غير قادر على نقل الصفحات إلى النطاق \"$1\"",
        "immobile-target-namespace-iw": "وصلة الإنترويكي ليست هدفاً صالحاً لنقل صفحة.",
        "immobile-source-page": "هذه الصفحة غير قابلة للنقل.",
        "immobile-target-page": "غير قادر على النقل إلى العنوان الوجهة هذا.",
+       "movepage-invalid-target-title": "الاسم المطلوب غير صحيح.",
        "bad-target-model": "الوجهة المطلوبة تستخدم نموذج محتوى مختلف. لا يمكن تحويل من $1 إلى $2.",
        "imagenocrossnamespace": "لا يمكن نقل الملف إلى نطاق غير نطاق الملفات",
        "nonfile-cannot-move-to-file": "لا يمكن نقل غير الملفات إلى نطاق الملفات",
index 0d88510..10d1709 100644 (file)
        "autoblockedtext": "Din IP-adresse er blevet blokeret automatisk fordi den blev brugt af en anden bruger som er blevet blokeret af $1.\nDen givne begrundelse er:\n\n:<em>$2</em>\n\n* Blokeringen starter: $8\n* Blokeringen udløber: $6\n* Blokeringen er rettet mod: $7\n\nDu kan kontakte $1 eller en af de andre [[{{MediaWiki:Grouppage-sysop}}|administratorer]] for at diskutere blokeringen.\n\nBemærk at du ikke kan bruge funktionen \"{{int:emailuser}}\" medmindre du har en gyldig e-mailadresse registreret i dine [[Special:Preferences|brugerindstillinger]] og du ikke er blevet blokeret fra at bruge den.\n\nDin nuværende IP-adresse er $3, og blokerings-id'et er #$5.\nAngiv venligst alle de ovenstående detaljer ved eventuelle henvendelser.",
        "systemblockedtext": "Dit brugernavn eller din IP-adresse er automatisk blokeret af MediaWiki.\nBegrundelsen for det er:\n\n:<em>$2</em>\n\n* Blokeringsperiodens start: $8\n* Blokeringen udløber: $6\n* Blokeringen er ment for: $7\n\nDin nuværende IP-adresse er $3.\nAngiv venligst alle de ovenstående detaljer ved eventuelle henvendelser.",
        "blockednoreason": "ingen begrundelse givet",
+       "blockedtext-composite-no-ids": "Din IP-adresse findes i flere sortlister",
        "whitelistedittext": "Du skal $1 for at kunne redigere sider.",
        "confirmedittext": "Du skal bekræfte din e-mailadresse, før du kan redigere sider. Udfyld og bekræft din e-mailadresse i dine [[Special:Preferences|bruger indstillinger]].",
        "nosuchsectiontitle": "Kan ikke finde afsnittet",
        "blocklink": "blokér",
        "unblocklink": "ophæv blokering",
        "change-blocklink": "ændring af blokering",
+       "empty-username": "(intet tilgængeligt brugernavn)",
        "contribslink": "bidrag",
        "emaillink": "send e-mail",
        "autoblocker": "Du er automatisk blokeret, fordi din IP-adresse for nylig er blevet brugt af \"[[User:$1|$1]]\".\nBegrundelsen for blokeringen af $1 er \"$2\".",
        "immobile-target-namespace-iw": "En side kan ikke flyttes til en interwiki-henvisning.",
        "immobile-source-page": "Denne side kan ikke flyttes.",
        "immobile-target-page": "Kan ikke flytte til det navn.",
+       "movepage-invalid-target-title": "Det ønskede navn er ugyldigt.",
        "bad-target-model": "Den ønskede destination bruger en anden indholdsmodel. Kan ikke konvertere fra $1 til $2.",
        "imagenocrossnamespace": "Filer kan ikke flyttes til et navnerum der ikke indeholder filer",
        "nonfile-cannot-move-to-file": "Kan ikke flytte ikke-filer til fil-navnerummet",
        "permanentlink": "Permanent link",
        "permanentlink-revid": "Versions-ID",
        "permanentlink-submit": "Gå til version",
+       "newsection": "Nyt afsnit",
+       "newsection-submit": "Gå til side",
        "dberr-problems": "Undskyld! Siden har tekniske problemer.",
        "dberr-again": "Prøv at vente et par minutter og opdater så siden igen.",
        "dberr-info": "(Kan ikke tilgå databasen: $1)",
        "mw-widgets-abandonedit-discard": "Kasser redigeringer",
        "mw-widgets-abandonedit-keep": "Fortsæt med at redigere",
        "mw-widgets-abandonedit-title": "Er du sikker?",
+       "mw-widgets-copytextlayout-copy": "Kopiér",
        "mw-widgets-dateinput-no-date": "Ingen dato valgt",
        "mw-widgets-dateinput-placeholder-day": "ÅÅÅÅ-MM-DD",
        "mw-widgets-dateinput-placeholder-month": "ÅÅÅÅ-MM",
index 56d0842..8988419 100644 (file)
        "rcfilters-filter-showlinkedto-label": "Show changes on pages linking to",
        "rcfilters-filter-showlinkedto-option-label": "<strong>Pages linking to</strong> the selected page",
        "rcfilters-target-page-placeholder": "Enter a page name (or category)",
+       "rcfilters-allcontents-label": "All contents",
+       "rcfilters-alldiscussions-label": "All discussions",
        "rcnotefrom": "Below {{PLURAL:$5|is the change|are the changes}} since <strong>$3, $4</strong> (up to <strong>$1</strong> shown).",
        "rclistfromreset": "Reset date selection",
        "rclistfrom": "Show new changes starting from $2, $3",
index 52ed8af..27ac340 100644 (file)
        "move-subpages": "Renommer les sous-pages (maximum $1)",
        "move-talk-subpages": "Renommer les sous-pages de la page de discussion (maximum $1)",
        "movepage-page-exists": "La page $1 existe déjà et ne peut pas être écrasée automatiquement.",
+       "movepage-source-doesnt-exist": "La page $1 n’existe pas et n’a pas pu être supprimée.",
        "movepage-page-moved": "La page $1 a été renommée en $2.",
        "movepage-page-unmoved": "La page $1 n'a pas pu être renommée en $2.",
        "movepage-max-pages": "Le maximum de $1 {{PLURAL:$1|page renommée|pages renommées}} a été atteint et aucune autre page ne sera renommée automatiquement.",
        "delete_and_move_reason": "Page supprimée pour permettre le renommage depuis « [[$1]] »",
        "selfmove": "Le titre est le même ;\nimpossible de renommer une page sur elle-même.",
        "immobile-source-namespace": "Vous ne pouvez pas renommer les pages dans l'espace de noms « $1 »",
+       "immobile-source-namespace-iw": "Les pages sur d’autres wikis ne peuvent être déplacées depuis ce wiki.",
        "immobile-target-namespace": "Vous ne pouvez pas renommer des pages vers l’espace de noms « $1 ».",
        "immobile-target-namespace-iw": "Un lien interwiki n’est pas une cible valide pour un renommage de page.",
        "immobile-source-page": "Cette page n'est pas renommable.",
        "immobile-target-page": "Il n'est pas possible de renommer la page vers ce titre.",
+       "movepage-invalid-target-title": "Le nom demandé n’est pas valide.",
        "bad-target-model": "La destination souhaitée utilise un autre modèle de contenu. Impossible de convertir de $1 vers $2.",
        "imagenocrossnamespace": "Impossible de renommer un fichier vers un espace de noms autre que fichier.",
        "nonfile-cannot-move-to-file": "Impossible de renommer quelque chose d'autre qu’un fichier vers l’espace de noms fichier.",
index c2e544f..65f2f8e 100644 (file)
        "specialmute-label-mute-email": "この利用者からのウィキメールをミュートする",
        "specialmute-header": "<b>{{BIDI:[[User:$1|$1]]}}</b>さんに対するミュートを個人設定で選択してください。",
        "specialmute-error-invalid-user": "あなたが要求した利用者名は見つかりませんでした。",
+       "specialmute-error-no-options": "ミュート機能はご使用になれません。いくつかの理由が考えられます: メールアドレスをまだ確認されていないか、このウィキの管理者がメールの機能および/もしくはこのウィキのメールのブラックリストを無効にしているか、です。",
        "specialmute-email-footer": "{{BIDI:$2}}のメール発信者の個人設定を変更するには<$1>を開いてください。",
        "specialmute-login-required": "ミュートの個人設定を変更するにはログインしてください。",
+       "mute-preferences": "ミュート設定",
        "revid": "版 $1",
        "pageid": "ページID $1",
        "interfaceadmin-info": "$1\n\nサイト全体のCSS/JavaScriptの編集権限は、最近<code>editinterface</code> 権限から分離されました。なぜこのエラーが表示されたのかわからない場合は、[[mw:MediaWiki_1.32/interface-admin]]をご覧ください。",
index 8bf1a30..4b23cf2 100644 (file)
        "rcfilters-savedqueries-already-saved": "Saringan iki wis kasimpen. Ganti setèlané panjenengan saperlu nggawé Saringan Kasimpen kang anyar.",
        "rcfilters-restore-default-filters": "Pulihaké saringan gawan",
        "rcfilters-clear-all-filters": "Resiki kabèh saringan",
-       "rcfilters-show-new-changes": "Deleng owah-owahan anyar dhéwé",
+       "rcfilters-show-new-changes": "Deleng owah-owahan anyar kawit $1",
        "rcfilters-search-placeholder": "Owah-owahan saringan (anggo menu utawa golèk jeneng saringan)",
        "rcfilters-invalid-filter": "Saringan ora sah",
        "rcfilters-empty-filter": "Ora ana saringan kang aktif. Kabèh sumbangan katuduhaké.",
index db50961..a427820 100644 (file)
@@ -35,7 +35,7 @@
        "tog-hideminor": "Paslēpt maznozīmīgus labojumus pēdējo izmaiņu lapā",
        "tog-hidepatrolled": "Slēpt apstiprinātās izmaņas pēdējo izmaiņu sarakstā",
        "tog-newpageshidepatrolled": "Paslēpt pārbaudītās lapas jauno lapu sarakstā",
-       "tog-hidecategorization": "Paslēpt lapu kategorizēšanu",
+       "tog-hidecategorization": "Slēpt lapu kategorizēšanu",
        "tog-extendwatchlist": "Izvērst uzraugāmo lapu sarakstu, lai parādītu visas veiktās izmaiņas (ne tikai pašas svaigākās)",
        "tog-usenewrc": "Grupēt izmaiņas pēc lapas pēdējās izmaiņās un uzraugāmo lapu sarakstā",
        "tog-numberheadings": "Automātiski numurēt virsrakstus",
        "uploadinvalidxml": "Nevarēja apstrādāt augšupielādētā faila XML saturu.",
        "uploadvirus": "Šis fails satur vīrusu! Sīkāk: $1",
        "uploadjava": "Fails ir ZIP fails, kas satur Java .class failu.\nJava failu augšupielāde nav atļauta, jo tas var radīt iespējas apiet drošības ierobežojumus.",
-       "upload-source": "Augšuplādējamais fails",
+       "upload-source": "Augšupielādējamais fails",
        "sourcefilename": "Faila adrese:",
        "sourceurl": "Avota URL:",
        "destfilename": "Mērķa faila nosaukums:",
        "export-download": "Saglabāt kā failu",
        "export-templates": "Iekļaut veidnes",
        "export-manual": "Pievienot lapas manuāli:",
-       "allmessages": "Visi sistēmas paziņojumi",
+       "allmessages": "Sistēmas ziņojumi",
        "allmessagesname": "Nosaukums",
        "allmessagesdefault": "Noklusētais ziņojuma teksts",
        "allmessagescurrent": "Pašreizējais teksts",
index 1272347..110841f 100644 (file)
        "virus-badscanner": "Kasalahan konfigurasi: pamindai virus indak dikenal: ''$1''",
        "virus-scanfailed": "Pamindaian gagal (kode $1)",
        "virus-unknownscanner": "Antivirus indak dikenal:",
-       "logouttext": "<strong>Sanak alah kalua log</strong\n\nMohon diingek kalau babarapo laman mungkin masih tampil cando Sanak alun kalua log. Silakan untuak mambarasiahan singgahan panjalajah web Sanak.",
+       "logouttext": "<strong>Sanak alah kalua log</strong>\n\nMohon diingek kalau babarapo laman mungkin masih tampil cando Sanak alun kalua log. Silakan untuak mambarasiahan singgahan panjalajah web Sanak.",
        "cannotlogoutnow-title": "Indak bisa kalua kini",
        "cannotlogoutnow-text": "Indak bisa kalua katiko manggunoan $1.",
        "welcomeuser": "Salamaik datang, $1!",
index 96e06fa..c75710f 100644 (file)
        "importuploaderrortemp": "'A carreca d' 'o file mpurtato nun se facette.\nNa cartella temporanea nun se truova.",
        "import-parse-failure": "mpurtaziune XML scassata pe' n'errore d'analiso",
        "import-noarticle": "Nisciuna paggena 'a mpurtà!",
-       "import-nonewrevisions": "Nisciuna verziona mpurtata (Tutt' 'e verziune so' state già mpurtate o pure zumpajeno pe' bbia 'e cocch'errore).",
+       "import-nonewrevisions": "Nisciuna verziona mpurtata (Tutt' 'e verziune so' state mpurtate già o zumpajeno pe bbia 'e cocch'errore).",
        "xml-error-string": "$1 a 'a linea $2, culonne $3 (byte $4): $5",
        "import-upload": "Carreca 'e date 'e XML",
        "import-token-mismatch": "Se so' perdut' 'e date d' 'a sessione.\n\nPuò darse ca site asciuto/a. <strong>Pe' piacere cuntrullate si site ancora dinto e tentate n'ata vota</strong>.\n\nSi chesto nun funziunasse ancora, tentate 'e ve n'[[Special:UserLogout|ascì]] e trasì n'ata vota dinto, cuntrullate si 'o navigatore vuosto premmettesse 'e cookies 'e stu sito.",
        "tooltip-ca-move": "Mòve sta paggena",
        "tooltip-ca-watch": "Azzecca sta paggena int' 'a lista 'e paggene cuntrullate vuosta",
        "tooltip-ca-unwatch": "Lèva sta paggena d' 'a lista 'e paggene cuntrullate vuosta",
-       "tooltip-search": "Truova dint'ô {{SITENAME}}",
+       "tooltip-search": "Truova dint'a {{SITENAME}}",
        "tooltip-search-go": "Vaje â paggena cu stu nomme si esiste",
        "tooltip-search-fulltext": "Ascià 'o testo indicato dint'e paggene",
        "tooltip-p-logo": "Visita a paggena prencepale",
        "feedback-thanks": "Grazie! 'O feedback vuosto s'è mpizzato dint' 'a paggena \"[$2 $1]\".",
        "feedback-thanks-title": "Ve ringraziammo!",
        "feedback-useragent": "Aggente utente:",
-       "searchsuggest-search": "Truova dint'ô {{SITENAME}}",
+       "searchsuggest-search": "Truova dint'a {{SITENAME}}",
        "searchsuggest-containing": "tène...",
        "api-error-badtoken": "Errore interno: 'O token nun è buono.",
        "api-error-emptypage": "'A criazione 'e paggene nuove abbacante nun è permessa.",
index 192a852..d3983c8 100644 (file)
        "recentchanges-label-unpatrolled": "Düsse Ännern is noch nich kontrolleert worrn",
        "recentchanges-label-plusminus": "Disse Siedengrött is mit dit Antall Bytes ännert",
        "recentchanges-legend-newpage": "{{int:recentchanges-label-newpage}}<br />(süh ok de [[Special:NewPages|List mit ne'e Sieden]])",
+       "rcfilters-search-placeholder-mobile": "Filters",
        "rcnotefrom": "Dit sünd de Ännern siet <b>$2</b> (bet to <b>$1</b> wiest).",
        "rclistfrom": "Wies ne’e Ännern siet $3 $2",
        "rcshowhideminor": "lütte Ännern $1",
index 6904c4c..92fb9bb 100644 (file)
        "metadata-fields": "ߟߐ߲ߕߊߞߐ߫ ߖߌ߬ߦߊ߬ߓߍ ߞߣߍ ߡߍ߲ ߦߋ߫ ߗߋߛߓߍ ߣߌ߲߬ ߘߐ߫߸ ߏ߬ ߘߌ߫ ߣߊ߬ ߥߟߏ߫ ߖߌ߬ߦߊ߬ߓߍ ߞߐߜߍ ߘߐ߫ ߣߌ߫ ߟߐ߲ߕߊߞߐ߫ ߥߟߊ߬ߟߋ߲ ߠߊߘߐ߯ߦߊ߫ ߘߊ߫. ߊ߬ ߕߐ߭ ߟߎ߬ ߢߡߊߘߏ߲߰ߣߍ߲ ߘߌ߫ ߕߏ߫ ߝߍ߭ ߞߏߛߐ߲߬.\n•ߊ߬ ߞߍ߫ \n•ߛߎ߯ߦߊ \n•ߕߎ߬ߡߊ߬ߘߊ ߣߌ߫ ߕߎ߬ߡߊ߬ߙߋ߲߫ ߓߐߛߎ߲ߡߊ \n•ߟߊ߬ߝߏߦߌ ߕߎ߬ߡߊ߬ߘߊ߬ ߖߐ߲ߖߐ߲ \n•ߞ ߝߙߍߕߍ \n•ߡ.ߛ.ߛ ߞߊߟߌߦߊ ߡߐ߬ߟߐ߲߬ߦߊ߬ߟߌ \n•ߕߊߞߎ߲ߡߊ ߥߊ߲߬ߥߊ߲ \n•ߞߎ߬ߛߊ߲ \n•ߓߊߦߟߍߡߊ߲ ߤߊߞߍ  ߘߞߖ \n•ߖߌ߬ߦߊ߬ߓߍ ߞߊ߲߬ߛߓߍ\n•ߘߟߊߕߍ߮ ߘߞߖ (ߘߊ߲߬ߠߊ߬ߕߍ߰ ߞߊ߲ߞߋ߫ ߖߊ߯ߓߡߊ)\n•ߘߎ߰ߕߍߟߍ߲ ߘߞߖ (ߘߊ߲߬ߠߊ߬ߕߍ߰ ߞߊ߲ߞߋ߫ ߖߊ߯ߓߡߊ)\n•ߞߐߓߋ ߘߞߖ (ߘߊ߲߬ߠߊ߬ߕߍ߰ ߞߊ߲ߞߋ߫ ߖߊ߯ߓߡߊ)",
        "namespacesall": "ߊ߬ ߓߍ߯",
        "monthsall": "ߡߎ߰ߡߍ",
+       "scarytranscludetoolong": "[URL ߖߊ߰ߡߊ߲߬ ߞߏߖߎ߰]",
+       "deletedwhileediting": "<strong>ߖߊ߲߬ߓߌ߬ߟߊ߬ߟߌ</strong> ߞߐߜߍ ߣߌ߲߬ ߕߎ߲߬ ߓߘߊ߫ ߖߏ߰ߛߌ߫ ߊ߬ ߡߊߦߟߍ߬ߡߊ߲ ߘߊߡߌ߬ߣߊ ߞߐ߫ ߌ ߓߟߏ߫.",
+       "recreate": "ߊ߬ ߟߊߘߊ߲߫ ߕߎ߲߯",
+       "confirm_purge_button": "ߏ߬ߞߍ߫",
        "parentheses-start": "⸜",
        "parentheses-end": "⸝",
        "imgmultipagenext": "ߞߐߜߍ ߣߊ߬ߕߐ ←",
index d7167ba..f6491eb 100644 (file)
        "move-subpages": "Mover subpáginas (até $1)",
        "move-talk-subpages": "Mover subpáginas da página de discussão (até $1)",
        "movepage-page-exists": "A página $1 já existe e não pode ser substituída.",
+       "movepage-source-doesnt-exist": "A página $1 não existe e não pode ser movida.",
        "movepage-page-moved": "A página $1 foi movida para $2",
        "movepage-page-unmoved": "A página $1 não pôde ser movida para $2.",
        "movepage-max-pages": "O limite de $1 {{PLURAL:$1|página movida|páginas movidas}} foi atingido; não será possível mover mais páginas de forma automática.",
        "delete_and_move_reason": "Eliminada para mover \"[[$1]]\"",
        "selfmove": "O título fonte e o título destinatário são os mesmos; não é possível mover uma página para ela mesma.",
        "immobile-source-namespace": "Não é possível mover páginas no espaço nominal \"$1\"",
+       "immobile-source-namespace-iw": "Páginas em outras wikis não podem ser movidas dessa wiki.",
        "immobile-target-namespace": "Não é possível mover páginas para o espaço nominal \"$1\"",
        "immobile-target-namespace-iw": "Um link interwiki não é um destino válido para movimentação de página.",
        "immobile-source-page": "Esta página não pode ser movida.",
        "immobile-target-page": "Não é possível mover para esse título de destino.",
+       "movepage-invalid-target-title": "O nome solicitado é inválido.",
        "bad-target-model": "O destino especificado usa um modelo de conteúdo diferente. Não é possível converter $1 para $2.",
        "imagenocrossnamespace": "Não é possível mover imagem para espaço nominal que não de imagens",
        "nonfile-cannot-move-to-file": "Não é possível mover não arquivos para espaço nominal de arquivos",
index ae6379b..86933e3 100644 (file)
        "rcfilters-filter-showlinkedto-label": "Label that indicates that the page is showing changes that link TO the target page. Used on [[Special:Recentchangeslinked]] when structured filters are enabled.",
        "rcfilters-filter-showlinkedto-option-label": "Menu option to show changes TO the target page. Used on [[Special:Recentchangeslinked]] when structured filters are enabled.",
        "rcfilters-target-page-placeholder": "Placeholder text for the title lookup [[Special:Recentchangeslinked]] when structured filters are enabled.",
+       "rcfilters-allcontents-label": "Label of the filter for all content namespaces on [[Special:Recentchanges]] or [[Special:Watchlist]] when structured filters are enabled.",
+       "rcfilters-alldiscussions-label": "Label of the filter for all discussion namespaces on [[Special:Recentchanges]] or [[Special:Watchlist]] when structured filters are enabled.",
        "rcnotefrom": "This message is displayed at [[Special:RecentChanges]] when viewing recentchanges from some specific time.\n\nThe corresponding message is {{msg-mw|Rclistfrom}}.\n\nParameters:\n* $1 - the maximum number of changes that are displayed\n* $2 - (Optional) a date and time\n* $3 - a date\n* $4 - a time\n* $5 - Number of changes are displayed, for use with PLURAL",
        "rclistfromreset": "Used on [[Special:RecentChanges]] to reset a selection of a certain date range.",
        "rclistfrom": "Used on [[Special:RecentChanges]]. Parameters:\n* $1 - (Currently not use) date and time. The date and the time adds to the rclistfrom description.\n* $2 - time. The time adds to the rclistfrom link description (with split of date and time).\n* $3 - date. The date adds to the rclistfrom link description (with split of date and time).\n\nThe corresponding message is {{msg-mw|Rcnotefrom}}.",
index edb642a..add3803 100644 (file)
        "history": "Istoricul paginii",
        "history_short": "Istoric",
        "history_small": "istoric",
-       "updatedmarker": "actualizat de la ultima mea vizită",
+       "updatedmarker": "actualizat de la ultima dumneavoastră vizită",
        "printableversion": "Versiune de tipărit",
        "permalink": "Legătură permanentă",
        "print": "Tipărire",
        "autoblockedtext": "Această adresă IP a fost blocată automat deoarece a fost folosită de către un alt utilizator, care a fost blocat de $1.\nMotivul blocării este:\n\n:<em>$2</em>\n\n* Începutul blocării: $8\n* Sfârșitul blocării: $6\n* Intervalul blocării: $7\n\nPuteți contacta pe $1 sau pe unul dintre ceilalți [[{{MediaWiki:Grouppage-sysop}}|administratori]] pentru a discuta blocarea.\n\nNu veți putea folosi opțiunea de \"{{int:emailuser}}\" decât dacă aveți înregistrată o adresă de e-mail validă la [[Special:Preferences|preferințe]] și nu sunteți blocat la folosirea ei.\n\nAveți adresa IP $3, iar identificatorul dumneavoastră de blocare este #$5.\nVă rugăm să includeți detaliile de mai sus în orice mesaje pe care le trimiteți.",
        "systemblockedtext": "Numele de utilizator sau adresa IP a fost blocat automat de MediaWiki.\nMotivul indicat este:\n\n:<em>$2</em>\n\n\n* Începutul blocării: $8\n* Expirarea blocării: $6\n* Utilizatorul vizat: $7\n\nAdresa IP curentă a dumneavoastră este $3.\nVă rugăm să includeți toate detaliile de mai sus în orice interogare pe care o veți faceți.",
        "blockednoreason": "nici un motiv oferit",
+       "blockedtext-composite": "<strong>Numele dumneavoastră de utilizator sau adresa IP au fost blocate.</strong>\nMotivul indicat este:\n\n:<em>$2</em>\n\n\n* Începutul blocării: $8\n* Expirarea celei mai lungi blocări: $6\n\n* $5\n\nAdresa dumneavoastră IP este $3.\nVă rugăm să includeți toate detaliile de mai sus în orice demers pe care îl veți face.",
+       "blockedtext-composite-no-ids": "Adresa dumneavoastră ip apare în mai multe liste negre",
+       "blockedtext-composite-reason": "Există mai multe blocări asupra contului sau adresei dumneavoastră IP",
        "whitelistedittext": "Trebuie să vă $1 pentru a putea modifica pagini.",
        "confirmedittext": "Trebuie să vă confirmați adresa de e-mail înainte de a edita pagini. Vă rugăm să vă setați și să vă validați adresa de e-mail cu ajutorul [[Special:Preferences|preferințelor utilizatorului]].",
        "nosuchsectiontitle": "Secțiunea nu poate fi găsită",
        "group-bureaucrat-member": "{{GENDER:$1|birocrat}}",
        "group-suppress-member": "{{GENDER:$1|suprimător|suprimătoare}}",
        "grouppage-user": "{{ns:project}}:Utilizatori",
-       "grouppage-autoconfirmed": "{{ns:project}}:Utilizator autoconfirmați",
+       "grouppage-autoconfirmed": "{{ns:project}}:Utilizatori confirmați automat",
        "grouppage-bot": "{{ns:project}}:Boți",
        "grouppage-sysop": "{{ns:project}}:Administratori",
        "grouppage-interface-admin": "{{ns:project}}:Administratori de interfață",
        "rcfilters-clear-all-filters": "Ștergeți toate filtrele",
        "rcfilters-show-new-changes": "Arată schimbările mai noi de la $1",
        "rcfilters-search-placeholder": "Filtrați modificările recente (folosiți meniul sau căutați numele filtrului)",
+       "rcfilters-search-placeholder-mobile": "Filtre",
        "rcfilters-invalid-filter": "Filtru invalid",
        "rcfilters-empty-filter": "Nu există filtre active. Toate contribuțiile sunt afișate.",
        "rcfilters-filterlist-title": "Filtre",
        "changecontentmodel": "Modificare model de conținut al unei pagini",
        "changecontentmodel-legend": "Modifică modelul de conținut",
        "changecontentmodel-title-label": "Titlul paginii",
+       "changecontentmodel-current-label": "Modelul de conținut curent:",
        "changecontentmodel-model-label": "Model de conținut nou",
        "changecontentmodel-reason-label": "Motiv:",
        "changecontentmodel-submit": "Schimbă",
        "contribsub2": "Pentru {{GENDER:$3|$1}} ($2)",
        "contributions-subtitle": "Pentru {{GENDER:$3|$1}}",
        "contributions-userdoesnotexist": "Contul de utilizator „$1” nu este înregistrat.",
+       "negative-namespace-not-supported": "Spațiile de nume cu valori negative nu sunt permise.",
        "nocontribs": "Nu a fost găsită nici o modificare care să satisfacă acest criteriu.",
        "uctop": "actuală",
        "month": "Din luna (și dinainte):",
        "interlanguage-link-title-nonlang": "$1 – $2",
        "common.css": "/** CSS plasate aici vor fi aplicate tuturor aparițiilor */",
        "print.css": "/* CSS plasate aici vor afecta modul în care paginile vor fi imprimate */",
+       "group-autoconfirmed.css": "/* Orice stil CSS din această pagină va afecta doar utilizatorii autoconfirmați */",
        "common.json": "/* Orice JSON din această pagină va fi încărcat pentru toți utilizatorii la fiecare pagină încărcată. */",
+       "group-autoconfirmed.js": "/* Orice cod JavaScript din această pagină va fi încărcat doar pentru utilizatorii autoconfirmați */",
        "anonymous": "{{PLURAL:$1|Utilizator anonim|Utilizatori anonimi}} ai {{SITENAME}}",
        "siteuser": "Utilizator {{SITENAME}} $1",
        "anonuser": "utlizator anonim $1 al {{SITENAME}}",
        "permanentlink": "Legătură permanentă",
        "permanentlink-revid": "ID versiune",
        "permanentlink-submit": "Mergi la versiunea",
+       "newsection": "Secțiune nouă",
+       "newsection-page": "Pagină țintă",
+       "newsection-submit": "Mergi la pagină",
        "dberr-problems": "Ne cerem scuze! Acest site întâmpină dificultăți tehnice.",
        "dberr-again": "Așteptați câteva minute și încercați din nou.",
        "dberr-info": "(Nu se poate accesa baza de date: $1)",
        "mw-widgets-abandonedit-discard": "Renunță la modificări",
        "mw-widgets-abandonedit-keep": "Continuă editarea",
        "mw-widgets-abandonedit-title": "Sunteți sigur(ă)?",
+       "mw-widgets-copytextlayout-copy": "Copiază",
+       "mw-widgets-copytextlayout-copy-fail": "Nu am putut copia în clipboard.",
+       "mw-widgets-copytextlayout-copy-success": "Copiat în clipboard.",
        "mw-widgets-dateinput-no-date": "Nicio dată selectată",
        "mw-widgets-dateinput-placeholder-day": "AAAA-LL-ZZ",
        "mw-widgets-dateinput-placeholder-month": "AAAA-LL",
        "changecredentials": "Schimbă credențialele",
        "changecredentials-submit": "Schimbă credențialele",
        "changecredentials-invalidsubpage": "„$1” nu este un tip de credențiale valid.",
+       "removecredentials-invalidsubpage": "$1 nu este un tip de credențiale valid.",
+       "removecredentials-success": "Credențialele dumneavoastră au fost șterse.",
+       "credentialsform-provider": "Tipuri de credențiale:",
        "credentialsform-account": "Numele contului:",
        "cannotlink-no-provider-title": "Nu există conturi conectate",
        "cannotlink-no-provider": "Nu există conturi conectate.",
        "linkaccounts": "Conectează conturile",
        "linkaccounts-success-text": "Contul a fost conectat.",
        "linkaccounts-submit": "Leagă conturile",
+       "cannotunlink-no-provider-title": "Nu există conturi ce pot fi deconectate",
+       "cannotunlink-no-provider": "Nu există conturi ce pot fi deconectate",
        "unlinkaccounts": "Dezleagă conturile",
        "unlinkaccounts-success": "Contul a fost dezlegat",
        "userjsispublic": "Atenție: subpaginile JavaScript nu trebuie să conțină date confidențiale, întrucât ele sunt vizibile altor utilizatori.",
        "restrictionsfield-help": "O adresă IP sau gamă CIDR pe linie. Pentru a activa tot, folosiți:<pre>0.0.0.0/0\n::/0</pre>",
        "edit-error-short": "Eroare: $1",
        "edit-error-long": "Erori:\n\n$1",
+       "specialmute-submit": "Confirmare",
+       "specialmute-label-mute-email": "Ascunde e-mailuri de la acest utilizator",
+       "specialmute-error-invalid-user": "Numele de utilizator solicitat nu a putut fi găsit.",
        "revid": "versiunea $1",
        "pageid": "ID pagină $1",
        "interfaceadmin-info": "$1\n\nPermisiunile pentru editarea de CSS/JS/JSON global au fost recent separate de dreptul <code>editinterface</code>. Dacă nu înțelegeți de ce primiți această eroare, vedeți [[mw:MediaWiki_1.32/interface-admin]].",
        "passwordpolicies-policy-passwordcannotmatchblacklist": "Parolele nu pot fi cele de pe lista neagră",
        "passwordpolicies-policy-maximalpasswordlength": "Parola trebuie să aibă cel puțin $1 {{PLURAL:$1|caracter|caractere|de caractere}}.",
        "passwordpolicies-policy-passwordcannotbepopular": "Parola nu poate fi {{PLURAL:$1|o parolă populară|în lista celor $1 parole populare|în lista celor $1 de parole populare}}.",
-       "easydeflate-invaliddeflate": "Conținutul oferit nu este comprimat corect"
+       "passwordpolicies-policy-passwordnotinlargeblacklist": "Parola nu poate fi în lista celor mai comune 100.000 de parole.",
+       "passwordpolicies-policyflag-forcechange": "trebuie schimbată la conectare",
+       "passwordpolicies-policyflag-suggestchangeonlogin": "sugerează schimbarea la conectare",
+       "easydeflate-invaliddeflate": "Conținutul oferit nu este comprimat corect",
+       "userlogout-continue": "Doriți să vă deconectați?"
 }
index 585a532..c4fa153 100644 (file)
        "blockedtext": "<strong>'U nome de l'utende o l'indirizze IP ha state bloccate.</strong>\n\n'U blocche ha state fatte da $1.\n'U mutive date jè <em>$2</em>.\n\n* 'U Blocche accumenze: $8\n* 'U Blocche spicce: $6\n* Tipe de blocche: $7\n\nTu puè condatta $1 o n'otre [[{{MediaWiki:Grouppage-sysop}}|amministratore]] pe 'ngazzarte sus a 'u blocche.\nTu non ge puè ausà 'u strumende \"{{int:emailuser}}\" senza ca mitte n'indirizze email valide jndr'à le\n[[Special:Preferences|preferenze tune]] e ce è state bloccate sus a l'use sue.\nL'IP ca tine mò jè $3 e 'u codece d'u blocche jè #$5.\nPe piacere mitte ste doje 'mbormaziune ce manne 'na richieste de sblocche.",
        "autoblockedtext": "L'indirizze IP tue ha state automaticamende blocchete purcè ha state ausete da n'otre utende, ca avère state blocchete da $1.\n'U mutive date jè 'u seguende:\n\n:''$2''\n\n* Inizie d'u blocche: $8\n* Scadenze d'u blocche: $6\n* Blocche 'ndise: $7\n\nTu puè cundattà $1 o une de l'otre [[{{MediaWiki:Grouppage-sysop}}|amministrature]] pe parà de stu probbleme.\n\nVide Bbuene ca tu non ge puè ausà 'a funziona \"manne n'e-mail a stu utende\" senze ca tu tìne 'n'indirizze e-mail valide e reggistrete jndr'à seziona [[Special:Preferences|me piace accussì]] e tu non ge sinde blocchete da ausarle.\n\nL'indirizze IP corrende jè $3, e 'u codece d'u blocche jè #$5.\nPe piacere mitte tutte le dettaglie ca ponne essere utile pe le richieste tune.",
        "blockednoreason": "nisciune mutive",
+       "blockedtext-composite-ids": "ID d'u blocche relevande: $1 ('u 'ndirizze IP tune pò sta pure jndr'à lista gnore)",
        "blockedtext-composite-no-ids": "'U 'ndirizze IP tune jesse jndr'à 'nu sacche de liste gnore",
        "blockedtext-composite-reason": "Stonne attive cchiù blocche sus a 'u cunde tune e/o indirizze IP",
        "whitelistedittext": "Tu ha $1 pàggene da cangià.",
        "yourtext": "'U teste tue",
        "storedversion": "Versione archivijete",
        "editingold": "'''FA ATTENZIO': Tu ste cange 'na revisione de sta pàgena scadute.'''\nCe tu a reggistre, ogne cangiamende fatte apprisse a sta revisione avène perdute.",
+       "unicode-support-fail": "Pare ca 'u browser tune non ge supporte l'Unicode. Essenne richieste pe cangià le pàggene, 'u cangiamende tune non g'avène reggistrate.",
        "yourdiff": "Differenze",
        "copyrightwarning": "Pe piacere vide ca tutte le condrebbute de {{SITENAME}} sonde considerete de essere rilasciete sotte 'a $2 (vide $1 pe le dettaglie).\nCe tu non ge vuè ca le condrebbute tue avènene ausete da otre o avènene cangete, non le scè mettènne proprie.<br />\nTu na promettere pure ca le cose ca scrive tu, sonde 'mbormaziune libbere o copiete da 'nu pubbleche dominie.<br />\n'''NON METTE' NISCIUNA FATJE CA JE' PROTETTE DA DERITTE SENZA PERMESSE!'''",
        "copyrightwarning2": "Pe piacere vide ca tutte le condrebbute de {{SITENAME}} ponne essere cangete, alterate o luvete da otre condrebbutore.\nCe tu non ge vuè ca quidde ca scrive avène cangete da tre, allore non scè scrivenne proprie aqquà.<br />\nTu ne stè promitte ca quidde ca scrive tu, o lè scritte cu 'u penziere tue o lè cupiate da risorse de pubbliche dominie o sembre robba libbere (vide $1 pe cchiù dettaglie).\n'''NO REGGISTRA' FATIJE CUPERTE DA 'U COPYRIGHT SENZA PERMESSE! NO FA STUDECARIE!'''",
index 4d575f4..0719083 100644 (file)
        "rcfilters-filter-watchlistactivity-seen-label": "ڏٺل سنوارون",
        "rcfilters-filtergroup-changetype": "تبديليءَ جو قِسم",
        "rcfilters-filter-pageedits-label": "صفحي سنوارون",
-       "rcfilters-filter-newpages-label": "صÙ\81Ø­Ù\8a ØªØ®Ù\84Ù\8aÙ\82ون",
+       "rcfilters-filter-newpages-label": "صÙ\81Ø­Ù\8a Ø³Ø±Ø¬Ø§Ù\8aون",
        "rcfilters-filter-newpages-description": "نوان صفحا ٺاھيندڙ سنوارون.",
        "rcfilters-filter-categorization-label": "زمري ۾ تبديليون",
        "rcfilters-filter-logactions-label": "لاگڊ عمل",
        "sp-contributions-search": "ڀاڱيدارين لاءِ ڳولا ڪريو",
        "sp-contributions-username": "آءِپي پتو يا واپرائيندڙ-نانءُ:",
        "sp-contributions-toponly": "صرف اھي سنوارون ڏيکاريو جيڪي تازا ترين مسودا آھن",
-       "sp-contributions-newonly": "صرف اھي سنوارون ڏيکاريو جيڪي صرف صفحي تخليقون آھن",
+       "sp-contributions-newonly": "صرف اھي سنوارون ڏيکاريو جيڪي صفحي سرجايون آھن",
        "sp-contributions-hideminor": "معمولي سنوارون لڪايو",
        "sp-contributions-submit": "ڳوليو",
        "whatlinkshere": "هتان ڇا ڳنڍيل آهي",
index b231f89..e0f4f5c 100644 (file)
        "mycustomjsredirectprotected": "Nemate dopuštenje za uređivanje ove JavaScript stranice jer predstavlja preusmjeravanje i ne vodi do vašeg imenskog prostora.",
        "easydeflate-invaliddeflate": "Sadržaj nije ispravno pročišćen",
        "unprotected-js": "JavaScript ne može da se učita sa nezaštićenih stranica iz bezbednosnih razloga. Samo napravite JavaScript u imenskom prostoru MediaWiki: ili kao korisničku podstranicu",
-       "userlogout-continue": "Ako se želite odjaviti, [$1 nastavite na odjavnoj strnaici]."
+       "userlogout-continue": "Želite se odjaviti?"
 }
index 7cfbd84..a65feb1 100644 (file)
        "move-subpages": "Premakni podstrani (do $1)",
        "move-talk-subpages": "Premakni podstrani pogovorne strani (do $1)",
        "movepage-page-exists": "Stran $1 že obstaja in je ni mogoče samodejno prepisati.",
+       "movepage-source-doesnt-exist": "Stran $1 ne obstaja in je ni mogoče premakniti.",
        "movepage-page-moved": "Stran $1 je bila prestavljena na $2.",
        "movepage-page-unmoved": "Strani $1 ni bilo mogoče prestaviti na $2.",
        "movepage-max-pages": "{{PLURAL:$1|Premaknjena je bila največ $1 stran|Premaknjeni sta bili največ $1 strani|Premaknjene so bile največ $1 strani|Premaknjenih je bilo največ $1 strani}} in nobena več ne bo samodejno premaknjena.",
        "delete_and_move_reason": "Izbrisano z namenom pripraviti prostor za »[[$1]]«",
        "selfmove": "Naslov je enak;\nstrani ni mogoče prestaviti čez njo.",
        "immobile-source-namespace": "Ne morem premikati strani v imenskem prostoru »$1«",
+       "immobile-source-namespace-iw": "Strani na drugih wikijih ne morete premikati s tega wikija.",
        "immobile-target-namespace": "Ne morem premakniti strani v imenski prostor »$1«",
        "immobile-target-namespace-iw": "Povezava interwiki ni veljaven cilj za premik strani.",
        "immobile-source-page": "Te strani ni mogoče prestaviti.",
        "immobile-target-page": "Ne morem premakniti na ta ciljni naslov.",
+       "movepage-invalid-target-title": "Zahtevano ime ni veljavno.",
        "bad-target-model": "Želen cilj uporablja drugačno obliko vsebine. Ne morem pretvoriti iz $1 v $2.",
        "imagenocrossnamespace": "Ne morem premakniti datoteke izven imenskega prostora datotek",
        "nonfile-cannot-move-to-file": "Ne morem premakniti nedatoteko v imenski prostor datotek",
index 2f330b3..5129716 100644 (file)
        "grant-group-customization": "Anpassning och inställningar",
        "grant-group-administration": "Utför administrativa åtgärder",
        "grant-group-private-information": "Få tillgång till privat data om dig",
-       "grant-group-other": "Diverse aktivitet",
+       "grant-group-other": "Övrig aktivitet",
        "grant-blockusers": "Blockera och avblockera användare",
        "grant-createaccount": "Skapa konton",
        "grant-createeditmovepage": "Skapa, redigera och flytta sidor",
index 560eeb6..873fae3 100644 (file)
        "title-invalid-talk-namespace": "ชื่อเรื่องหน้าที่ขออ้างถึงหน้าพูดคุยซึ่งมีไม่ได้",
        "title-invalid-characters": "ชื่อเรื่องหน้าที่ขอมีอักขระไม่สมเหตุสมผล: \"$1\"",
        "title-invalid-relative": "ชื่อเรื่องมีเส้นทางสัมพัทธ์ ชื่อเรื่องหน้าสัมพัทธ์ (./, ../) ไม่สมเหตุสมผล เพราะมักจะเข้าถึงไม่ได้เมื่อจัดการด้วยเบราว์เซอร์ของผู้ใช้",
-       "title-invalid-magic-tilde": "à¸\8aืà¹\88อà¹\80รืà¹\88อà¸\87หà¸\99à¹\89าà¸\97ีà¹\88à¸\82อมีลำà¸\94ัà¸\9aà¸\97ิลà¸\94าà¹\80มà¸\88ิà¸\81à¹\84มà¹\88สมà¹\80หà¸\95ุสมà¸\9cล (<nowiki>~~~</nowiki>)",
+       "title-invalid-magic-tilde": "à¸\8aืà¹\88อหà¸\99à¹\89าà¸\97ีà¹\88รà¹\89อà¸\87à¸\82อมีลำà¸\94ัà¸\9aà¸\97ิลà¹\80à¸\94อà¸\9eิà¹\80ศษà¸\97ีà¹\88à¹\83à¸\8aà¹\89à¹\84มà¹\88à¹\84à¸\94à¹\89 (<nowiki>~~~</nowiki>)",
        "title-invalid-too-long": "ชื่อเรื่องหน้าที่ขอยาวเกินไป ไม่สามารถยาวกว่า $1 ไบต์ในการเข้ารหัส UTF-8",
        "title-invalid-leading-colon": "ชื่อเรื่องหน้าที่ขอขึ้นต้นด้วยโคลอนไม่สมเหตุสมผล",
        "perfcached": "ข้อมูลต่อไปนี้ถูกเก็บในแคชและอาจล้าสมัย มีผลการค้นหาสูงสุด $1 รายการในแคช",
        "booksources-search": "ค้นหา",
        "booksources-text": "ด้านล่างเป็นรายการการเชื่อมโยงไปยังเว็บไซต์อื่นที่ขายหนังสือใหม่และหนังสือใช้แล้ว และอาจมีข้อมูลเพิ่มเติมเกี่ยวกับหนังสือที่คุณกำลังมองหา:",
        "booksources-invalid-isbn": "รหัส ISBN ที่ให้ไว้ไม่ถูกต้อง กรุณาตรวจสอบจากต้นฉบับอีกครั้ง",
+       "magiclink-tracking-rfc": "หน้าที่ใช้ลิงก์พิเศษ RFC",
+       "magiclink-tracking-rfc-desc": "หน้านี้ใช้ลิงก์พิเศษ RFC วิธีโยกย้ายให้ดูที่ [https://www.mediawiki.org/wiki/Special:MyLanguage/Help:Magic_links mediawiki.org]",
+       "magiclink-tracking-pmid": "หน้าที่ใช้ลิงก์พิเศษ PMID",
+       "magiclink-tracking-pmid-desc": "หน้านี้ใช้ลิงก์พิเศษ PMID วิธีโยกย้ายให้ดูที่ [https://www.mediawiki.org/wiki/Special:MyLanguage/Help:Magic_links mediawiki.org]",
+       "magiclink-tracking-isbn": "หน้าที่ใช้ลิงก์พิเศษ ISBN",
+       "magiclink-tracking-isbn-desc": "หน้านี้ใช้ลิงก์พิเศษ ISBN วิธีโยกย้ายให้ดูที่ [https://www.mediawiki.org/wiki/Special:MyLanguage/Help:Magic_links mediawiki.org]",
        "specialloguserlabel": "ผู้ดำเนินการ:",
        "speciallogtitlelabel": "เป้าหมาย (ชื่อเรื่องหรือ {{ns:user}}:ชื่อผู้ใช้ สำหรับผู้ใช้):",
        "log": "ปูม",
        "trackingcategories-desc": "เกณฑ์การรวมหมวดหมู่",
        "restricted-displaytitle-ignored": "หน้าที่มีชื่อเรื่องแสดงที่ถูกละเลย",
        "restricted-displaytitle-ignored-desc": "หน้ามี <code><nowiki>{{DISPLAYTITLE}}</nowiki></code> ที่ถูกละเลย เพราะไม่สมนัยกับชื่อเรื่องแท้จริงของหน้า",
-       "noindex-category-desc": "à¹\82รà¸\9aอà¸\95à¹\84มà¹\88สามารà¸\96à¸\97ำà¸\94ัà¸\8aà¸\99ีหà¸\99à¹\89าà¸\99ีà¹\89à¹\80à¸\9eราะมีà¹\80มà¸\88ิà¸\81à¹\80วิรà¹\8cà¸\94 <code><nowiki>__NOINDEX__</nowiki></code> อยู่และอยู่ในเนมสเปซซึ่งอนุญาตตัวบ่งชี้นี้",
+       "noindex-category-desc": "à¸\9aอà¸\95à¹\84มà¹\88สามารà¸\96à¸\97ำà¸\94ัà¸\8aà¸\99ีหà¸\99à¹\89าà¸\99ีà¹\89à¹\80à¸\9eราะมีà¸\84ำสัà¹\88à¸\87à¸\9eิà¹\80ศษ <code><nowiki>__NOINDEX__</nowiki></code> อยู่และอยู่ในเนมสเปซซึ่งอนุญาตตัวบ่งชี้นี้",
        "index-category-desc": "หน้านี้มี <code><nowiki>__INDEX__</nowiki></code> อยู่ (และอยู่ในเนมสเปซซึ่งอนุญาตตัวบ่งชี้นี้) ฉะนั้น โรบอตจึงทำดัชนี้ได้ ซึ่งปกติไม่สามารถทำได้",
        "post-expand-template-inclusion-category-desc": "การแทนที่แม่แบบทั้งหมดทำให้ขนาดของหน้าใหญ่กว่า <code>$wgMaxArticleSize</code> จึงไม่มีการแทนที่แม่แบบบางตัว",
        "post-expand-template-argument-category-desc": "หน้านี้มีขนาดใหญ่กว่า <code>$wgMaxArticleSize</code> หลังจากขยายอาร์กิวเมนต์ของแม่แบบ (สิ่งที่อยู่ภายในวงเล็บปีกกาสามวง เช่น <code>{{{Foo}}}</code>)",
index ff50d0b..49b249b 100644 (file)
        "nstab-template": "Modèl",
        "nstab-help": "Ajuto",
        "nstab-category": "Categoria",
-       "mainpage-nstab": "Pàgina prinsipale",
+       "mainpage-nstab": "Pajina prinsipałe",
        "nosuchaction": "Operasion no riconossua",
        "nosuchactiontext": "L'asion spesifegà ne l'URL no a xè vałida.\nXè posibiłe che l'URL sia sta dizità en modo erato o che sia sta seguio on cołegamento no vałido.\nCiò podaria anca indicare on bug en {{SITENAME}}.",
        "nosuchspecialpage": "Pajina prinsipałe no disponibiłe",
index 1645687..c5641c9 100644 (file)
        "userlogin-resetpassword-link": "忘記密碼?",
        "userlogin-helplink2": "登入說明",
        "userlogin-loggedin": "您目前已登入 {{GENDER:$1|$1}} 使用者,\n請使用下列表單改登入另一位使用者。",
-       "userlogin-reauth": "æ\82¨å¿\85é \88å\86\8dç\99»å\85¥ä¸\80次ä¾\86é©\97証æ\82¨ç\82º {{GENDER:$1|$1}}。",
+       "userlogin-reauth": "æ\82¨å¿\85é \88å\86\8dç\99»å\85¥ä¸\80次ä¾\86é©\97è­\89æ\82¨ç\82º{{GENDER:$1|$1}}。",
        "userlogin-createanother": "建立另一個帳號",
        "createacct-emailrequired": "電子郵件地址",
        "createacct-emailoptional": "電子郵件地址(選填)",
        "move-subpages": "移動子頁面(至多 $1 頁)",
        "move-talk-subpages": "移動討論頁面的子頁面 (共 $1 頁)",
        "movepage-page-exists": "頁面 $1 已存在,無法自動覆蓋。",
+       "movepage-source-doesnt-exist": "頁面$1不存在因此無法移動。",
        "movepage-page-moved": "已移動頁面 $1 到 $2。",
        "movepage-page-unmoved": "無法移動頁面 $1 到 $2。",
        "movepage-max-pages": "移動頁面的上限為 $1 頁,超出限制的頁面將不會自動移動。",
        "delete_and_move_reason": "已刪除讓來自 [[$1]] 頁面可移動",
        "selfmove": "標題相同;無法移動頁面到自己本身。",
        "immobile-source-namespace": "無法移動在命名空間 \"$1\" 中的頁面",
+       "immobile-source-namespace-iw": "在其它 wiki 的頁面無法從此 wiki 移動。",
        "immobile-target-namespace": "無法移動頁面至命名空間 \"$1\"",
        "immobile-target-namespace-iw": "移動頁面不可使用 Interwiki 連結做為目標。",
        "immobile-source-page": "此頁面無法移動。",
        "immobile-target-page": "無法移動至目標標題。",
+       "movepage-invalid-target-title": "請求的名稱無效。",
        "bad-target-model": "指定的目標地使用不同的內容模型。無法轉換 $1 為 $2。",
        "imagenocrossnamespace": "不可以移動檔案到非檔案命名空間",
        "nonfile-cannot-move-to-file": "不可以移動非檔案到檔案命名空間",
index da9b4d6..505168e 100644 (file)
@@ -114,7 +114,7 @@ class CreateAndPromote extends Maintenance {
 
                if ( !$exists ) {
                        // Create the user via AuthManager as there may be various side
-                       // effects that are perfomed by the configured AuthManager chain.
+                       // effects that are performed by the configured AuthManager chain.
                        $status = MediaWiki\Auth\AuthManager::singleton()->autoCreateUser(
                                $user,
                                MediaWiki\Auth\AuthManager::AUTOCREATE_SOURCE_MAINT,
index 9548d6b..6b1cdc3 100644 (file)
@@ -33,8 +33,11 @@ require_once __DIR__ . '/Maintenance.php';
 class McTest extends Maintenance {
        public function __construct() {
                parent::__construct();
-               $this->addDescription( "Makes several 'set', 'incr' and 'get' requests on every"
-                       . " memcached server and shows a report" );
+               $this->addDescription(
+                       "Makes several operation requests on every cache server and shows a report.\n" .
+                       "This tests both per-key and batched *Multi() methods as well as WRITE_BACKGROUND.\n" .
+                       "\"IB\" means \"immediate blocking\" and \"DB\" means \"deferred blocking.\""
+               );
                $this->addOption( 'i', 'Number of iterations', false, true );
                $this->addOption( 'cache', 'Use servers from this $wgObjectCaches store', false, true );
                $this->addOption( 'driver', 'Either "php" or "pecl"', false, true );
@@ -76,37 +79,47 @@ class McTest extends Maintenance {
                        $this->fatalError( "Invalid driver type '$type'" );
                }
 
+               $this->output( "Warming up connections to cache servers..." );
+               $mccByServer = [];
                foreach ( $servers as $server ) {
-                       $this->output( str_pad( $server, $maxSrvLen ) . "\n" );
-
                        /** @var BagOStuff $mcc */
-                       $mcc = new $class( [
+                       $mccByServer[$server] = new $class( [
                                'servers' => [ $server ],
                                'persistent' => true,
+                               'allow_tcp_nagle_delay' => false,
                                'timeout' => $wgMemCachedTimeout
                        ] );
+                       $mccByServer[$server]->get( 'key' );
+               }
+               $this->output( "done\n" );
+               $this->output( "Single and batched operation profiling/test results:\n" );
+
+               $valueByKey = [];
+               for ( $i = 1; $i <= $iterations; $i++ ) {
+                       $valueByKey["test$i"] = 'S' . str_pad( $i, 2048 );
+               }
 
-                       $this->benchmarkSingleKeyOps( $mcc, $iterations );
-                       $this->benchmarkMultiKeyOpsImmediateBlocking( $mcc, $iterations );
-                       $this->benchmarkMultiKeyOpsDeferredBlocking( $mcc, $iterations );
+               foreach ( $mccByServer as $server => $mcc ) {
+                       $this->output( str_pad( $server, $maxSrvLen ) . "\n" );
+                       $this->benchmarkSingleKeyOps( $mcc, $valueByKey );
+                       $this->benchmarkMultiKeyOpsImmediateBlocking( $mcc, $valueByKey );
+                       $this->benchmarkMultiKeyOpsDeferredBlocking( $mcc, $valueByKey );
                }
        }
 
        /**
         * @param BagOStuff $mcc
-        * @param int $iterations
+        * @param array $valueByKey
         */
-       private function benchmarkSingleKeyOps( $mcc, $iterations ) {
+       private function benchmarkSingleKeyOps( BagOStuff $mcc, array $valueByKey ) {
                $add = 0;
                $set = 0;
                $incr = 0;
                $get = 0;
                $delete = 0;
 
-               $keys = [];
-               for ( $i = 1; $i <= $iterations; $i++ ) {
-                       $keys[] = "test$i";
-               }
+               $i = count( $valueByKey );
+               $keys = array_keys( $valueByKey );
 
                // Clear out any old values
                $mcc->deleteMulti( $keys );
@@ -153,43 +166,40 @@ class McTest extends Maintenance {
                $delMs = intval( 1e3 * ( microtime( true ) - $time_start ) );
 
                $this->output(
-                       " add: $add/$iterations {$addMs}ms   " .
-                       "set: $set/$iterations {$setMs}ms   " .
-                       "incr: $incr/$iterations {$incrMs}ms   " .
-                       "get: $get/$iterations ({$getMs}ms)   " .
-                       "delete: $delete/$iterations ({$delMs}ms)\n"
+                       " add: $add/$i {$addMs}ms   " .
+                       "set: $set/$i {$setMs}ms   " .
+                       "incr: $incr/$i {$incrMs}ms   " .
+                       "get: $get/$i ({$getMs}ms)   " .
+                       "delete: $delete/$i ({$delMs}ms)\n"
                );
        }
 
        /**
         * @param BagOStuff $mcc
-        * @param int $iterations
+        * @param array $valueByKey
         */
-       private function benchmarkMultiKeyOpsImmediateBlocking( $mcc, $iterations ) {
-               $keysByValue = [];
-               for ( $i = 1; $i <= $iterations; $i++ ) {
-                       $keysByValue["test$i"] = 'S' . str_pad( $i, 2048 );
-               }
-               $keyList = array_keys( $keysByValue );
+       private function benchmarkMultiKeyOpsImmediateBlocking( BagOStuff $mcc, array $valueByKey ) {
+               $keys = array_keys( $valueByKey );
+               $iterations = count( $valueByKey );
 
                $time_start = microtime( true );
-               $mSetOk = $mcc->setMulti( $keysByValue ) ? 'S' : 'F';
+               $mSetOk = $mcc->setMulti( $valueByKey ) ? '✓' : '✗';
                $mSetMs = intval( 1e3 * ( microtime( true ) - $time_start ) );
 
                $time_start = microtime( true );
-               $found = $mcc->getMulti( $keyList );
+               $found = $mcc->getMulti( $keys );
                $mGetMs = intval( 1e3 * ( microtime( true ) - $time_start ) );
                $mGetOk = 0;
                foreach ( $found as $key => $value ) {
-                       $mGetOk += ( $value === $keysByValue[$key] );
+                       $mGetOk += ( $value === $valueByKey[$key] );
                }
 
                $time_start = microtime( true );
-               $mChangeTTLOk = $mcc->changeTTLMulti( $keyList, 3600 ) ? 'S' : 'F';
+               $mChangeTTLOk = $mcc->changeTTLMulti( $keys, 3600 ) ? '✓' : '✗';
                $mChangeTTTMs = intval( 1e3 * ( microtime( true ) - $time_start ) );
 
                $time_start = microtime( true );
-               $mDelOk = $mcc->deleteMulti( $keyList ) ? 'S' : 'F';
+               $mDelOk = $mcc->deleteMulti( $keys ) ? '✓' : '✗';
                $mDelMs = intval( 1e3 * ( microtime( true ) - $time_start ) );
 
                $this->output(
@@ -202,34 +212,31 @@ class McTest extends Maintenance {
 
        /**
         * @param BagOStuff $mcc
-        * @param int $iterations
+        * @param array $valueByKey
         */
-       private function benchmarkMultiKeyOpsDeferredBlocking( $mcc, $iterations ) {
+       private function benchmarkMultiKeyOpsDeferredBlocking( BagOStuff $mcc, array $valueByKey ) {
+               $keys = array_keys( $valueByKey );
+               $iterations = count( $valueByKey );
                $flags = $mcc::WRITE_BACKGROUND;
-               $keysByValue = [];
-               for ( $i = 1; $i <= $iterations; $i++ ) {
-                       $keysByValue["test$i"] = 'A' . str_pad( $i, 2048 );
-               }
-               $keyList = array_keys( $keysByValue );
 
                $time_start = microtime( true );
-               $mSetOk = $mcc->setMulti( $keysByValue, 0, $flags ) ? 'S' : 'F';
+               $mSetOk = $mcc->setMulti( $valueByKey, 0, $flags ) ? '✓' : '✗';
                $mSetMs = intval( 1e3 * ( microtime( true ) - $time_start ) );
 
                $time_start = microtime( true );
-               $found = $mcc->getMulti( $keyList );
+               $found = $mcc->getMulti( $keys );
                $mGetMs = intval( 1e3 * ( microtime( true ) - $time_start ) );
                $mGetOk = 0;
                foreach ( $found as $key => $value ) {
-                       $mGetOk += ( $value === $keysByValue[$key] );
+                       $mGetOk += ( $value === $valueByKey[$key] );
                }
 
                $time_start = microtime( true );
-               $mChangeTTLOk = $mcc->changeTTLMulti( $keyList, 3600, $flags ) ? 'S' : 'F';
+               $mChangeTTLOk = $mcc->changeTTLMulti( $keys, 3600, $flags ) ? '✓' : '✗';
                $mChangeTTTMs = intval( 1e3 * ( microtime( true ) - $time_start ) );
 
                $time_start = microtime( true );
-               $mDelOk = $mcc->deleteMulti( $keyList, $flags ) ? 'S' : 'F';
+               $mDelOk = $mcc->deleteMulti( $keys, $flags ) ? '✓' : '✗';
                $mDelMs = intval( 1e3 * ( microtime( true ) - $time_start ) );
 
                $this->output(
index eaf720c..d33e3de 100644 (file)
@@ -1934,6 +1934,8 @@ return [
                        'rcfilters-filter-showlinkedto-label',
                        'rcfilters-filter-showlinkedto-option-label',
                        'rcfilters-target-page-placeholder',
+                       'rcfilters-allcontents-label',
+                       'rcfilters-alldiscussions-label',
                        'blanknamespace',
                        'namespaces',
                        'tags-title',
index 97b73ae..85a4efe 100644 (file)
@@ -58,6 +58,7 @@ OO.initClass( Controller );
  */
 Controller.prototype.initialize = function ( filterStructure, namespaceStructure, tagList, conditionalViews ) {
        var parsedSavedQueries, pieces,
+               nsAllContents, nsAllDiscussions,
                displayConfig = mw.config.get( 'StructuredChangeFiltersDisplayConfig' ),
                defaultSavedQueryExists = mw.config.get( 'wgStructuredChangeFiltersDefaultSavedQueryExists' ),
                controller = this,
@@ -67,20 +68,38 @@ Controller.prototype.initialize = function ( filterStructure, namespaceStructure
 
        // Prepare views
        if ( namespaceStructure ) {
-               items = [];
+               nsAllContents = {
+                       name: 'all-contents',
+                       label: mw.msg( 'rcfilters-allcontents-label' ),
+                       description: '',
+                       identifiers: [ 'subject' ],
+                       cssClass: 'mw-changeslist-ns-subject',
+                       subset: []
+               };
+               nsAllDiscussions = {
+                       name: 'all-discussions',
+                       label: mw.msg( 'rcfilters-alldiscussions-label' ),
+                       description: '',
+                       identifiers: [ 'talk' ],
+                       cssClass: 'mw-changeslist-ns-talk',
+                       subset: []
+               };
+               items = [ nsAllContents, nsAllDiscussions ];
                // eslint-disable-next-line no-jquery/no-each-util
                $.each( namespaceStructure, function ( namespaceID, label ) {
                        // Build and clean up the individual namespace items definition
-                       items.push( {
-                               name: namespaceID,
-                               label: label || mw.msg( 'blanknamespace' ),
-                               description: '',
-                               identifiers: [
-                                       mw.Title.isTalkNamespace( namespaceID ) ?
-                                               'talk' : 'subject'
-                               ],
-                               cssClass: 'mw-changeslist-ns-' + namespaceID
-                       } );
+                       var isTalk = mw.Title.isTalkNamespace( namespaceID ),
+                               nsFilter = {
+                                       name: namespaceID,
+                                       label: label || mw.msg( 'blanknamespace' ),
+                                       description: '',
+                                       identifiers: [
+                                               isTalk ? 'talk' : 'subject'
+                                       ],
+                                       cssClass: 'mw-changeslist-ns-' + namespaceID
+                               };
+                       items.push( nsFilter );
+                       ( isTalk ? nsAllDiscussions : nsAllContents ).subset.push( { filter: namespaceID } );
                } );
 
                views.namespaces = {
index a5b71b9..0eb1134 100644 (file)
@@ -23,7 +23,7 @@
         * @cfg {boolean} [redirect] Page is a redirect
         * @cfg {boolean} [disambiguation] Page is a disambiguation page
         * @cfg {string} [query] Matching query string to highlight
-        * @cfg {string} [compare] String comparison function for query highlighting
+        * @cfg {Function} [compare] String comparison function for query highlighting
         */
        mw.widgets.TitleOptionWidget = function MwWidgetsTitleOptionWidget( config ) {
                var icon;
index fd418f7..e71cc88 100644 (file)
@@ -217,6 +217,9 @@ $wgAutoloadClasses += [
        'MockSearchResultSet' => "$testDir/phpunit/mocks/search/MockSearchResultSet.php",
        'MockSearchResult' => "$testDir/phpunit/mocks/search/MockSearchResult.php",
 
+       # tests/phpunit/unit/includes/libs/filebackend/fsfile
+       'TempFSFileTestTrait' => "$testDir/phpunit/unit/includes/libs/filebackend/fsfile/TempFSFileTestTrait.php",
+
        # tests/suites
        'ParserTestFileSuite' => "$testDir/phpunit/suites/ParserTestFileSuite.php",
        'ParserTestTopLevelSuite' => "$testDir/phpunit/suites/ParserTestTopLevelSuite.php",
diff --git a/tests/phpunit/includes/libs/filebackend/fsfile/TempFSFileIntegrationTest.php b/tests/phpunit/includes/libs/filebackend/fsfile/TempFSFileIntegrationTest.php
new file mode 100644 (file)
index 0000000..42805b2
--- /dev/null
@@ -0,0 +1,9 @@
+<?php
+
+class TempFSFileIntegrationTest extends MediaWikiIntegrationTestCase {
+       use TempFSFileTestTrait;
+
+       private function newFile() {
+               return TempFSFile::factory( 'tmp' );
+       }
+}
index 7d3e82c..f496fa3 100644 (file)
@@ -19,9 +19,10 @@ class BagOStuffTest extends MediaWikiTestCase {
 
                // type defined through parameter
                if ( $this->getCliArg( 'use-bagostuff' ) !== null ) {
-                       $name = $this->getCliArg( 'use-bagostuff' );
+                       global $wgObjectCaches;
 
-                       $this->cache = ObjectCache::newFromId( $name );
+                       $id = $this->getCliArg( 'use-bagostuff' );
+                       $this->cache = ObjectCache::newFromParams( $wgObjectCaches[$id] );
                } else {
                        // no type defined - use simple hash
                        $this->cache = new HashBagOStuff;
@@ -36,7 +37,7 @@ class BagOStuffTest extends MediaWikiTestCase {
         * @covers MediumSpecificBagOStuff::makeKeyInternal
         */
        public function testMakeKey() {
-               $cache = ObjectCache::newFromId( 'hash' );
+               $cache = new HashBagOStuff();
 
                $localKey = $cache->makeKey( 'first', 'second', 'third' );
                $globalKey = $cache->makeGlobalKey( 'first', 'second', 'third' );
index dff18ca..9d58cef 100644 (file)
@@ -1,5 +1,6 @@
 <?php
 
+use MediaWiki\MediaWikiServices;
 use Wikimedia\TestingAccessWrapper;
 
 /**
@@ -209,6 +210,19 @@ class ChangesListSpecialPageTest extends AbstractChangesListSpecialPageTestCase
                );
        }
 
+       public function testRcNsFilterAllContents() {
+               $namespaces = MediaWikiServices::getInstance()->getNamespaceInfo()->getSubjectNamespaces();
+               $this->assertConditions(
+                       [ # expected
+                               'rc_namespace IN (' . $this->db->makeList( $namespaces ) . ')',
+                       ],
+                       [
+                               'namespace' => 'all-contents',
+                       ],
+                       "rc conditions with all-contents"
+               );
+       }
+
        public function testRcHidemyselfFilter() {
                $this->setMwGlobals( 'wgActorTableSchemaMigrationStage', SCHEMA_COMPAT_NEW );
                $this->overrideMwServices();
diff --git a/tests/phpunit/unit/includes/libs/filebackend/fsfile/TempFSFileTestTrait.php b/tests/phpunit/unit/includes/libs/filebackend/fsfile/TempFSFileTestTrait.php
new file mode 100644 (file)
index 0000000..d32e01e
--- /dev/null
@@ -0,0 +1,54 @@
+<?php
+
+/**
+ * Code shared between the unit and integration tests
+ */
+trait TempFSFileTestTrait {
+       abstract protected function newFile();
+
+       /**
+        * @covers TempFSFile::__construct
+        * @covers TempFSFile::purge
+        */
+       public function testPurge() {
+               $file = $this->newFile();
+               $this->assertTrue( file_exists( $file->getPath() ) );
+               $file->purge();
+               $this->assertFalse( file_exists( $file->getPath() ) );
+       }
+
+       /**
+        * @covers TempFSFile::__construct
+        * @covers TempFSFile::bind
+        * @covers TempFSFile::autocollect
+        * @covers TempFSFile::__destruct
+        */
+       public function testBind() {
+               $file = $this->newFile();
+               $path = $file->getPath();
+               $this->assertTrue( file_exists( $path ) );
+               $obj = new stdclass;
+               $file->bind( $obj );
+               unset( $file );
+               $this->assertTrue( file_exists( $path ) );
+               unset( $obj );
+               $this->assertFalse( file_exists( $path ) );
+       }
+
+       /**
+        * @covers TempFSFile::__construct
+        * @covers TempFSFile::preserve
+        * @covers TempFSFile::__destruct
+        */
+       public function testPreserve() {
+               $file = $this->newFile();
+               $path = $file->getPath();
+               $this->assertTrue( file_exists( $path ) );
+               $file->preserve();
+               unset( $file );
+               $this->assertTrue( file_exists( $path ) );
+               Wikimedia\suppressWarnings();
+               unlink( $path );
+               Wikimedia\restoreWarnings();
+       }
+}