Merge "jquery.textSelection: Remove code supporting IE 6 selection APIs"
authorjenkins-bot <jenkins-bot@gerrit.wikimedia.org>
Wed, 31 Jan 2018 15:53:51 +0000 (15:53 +0000)
committerGerrit Code Review <gerrit@wikimedia.org>
Wed, 31 Jan 2018 15:53:51 +0000 (15:53 +0000)
57 files changed:
includes/EditPage.php
includes/Storage/RevisionStore.php
includes/api/i18n/de.json
includes/api/i18n/fr.json
includes/api/i18n/it.json
includes/api/i18n/pt.json
includes/changetags/ChangeTags.php
includes/db/DatabaseOracle.php
includes/installer/i18n/pt.json
includes/libs/objectcache/WANObjectCache.php
includes/libs/rdbms/database/Database.php
includes/libs/rdbms/database/DatabaseMssql.php
includes/libs/rdbms/database/DatabaseMysqlBase.php
includes/libs/rdbms/database/DatabaseMysqli.php
includes/libs/rdbms/database/DatabasePostgres.php
includes/libs/rdbms/database/DatabaseSqlite.php
includes/parser/Sanitizer.php
includes/resourceloader/ResourceLoader.php
includes/resourceloader/ResourceLoaderUserOptionsModule.php
includes/resourceloader/ResourceLoaderUserTokensModule.php
includes/specials/SpecialExpandTemplates.php
includes/specials/SpecialUserrights.php
languages/i18n/ast.json
languages/i18n/be-tarask.json
languages/i18n/bg.json
languages/i18n/de.json
languages/i18n/diq.json
languages/i18n/en.json
languages/i18n/es.json
languages/i18n/eu.json
languages/i18n/he.json
languages/i18n/hu.json
languages/i18n/ja.json
languages/i18n/jv.json
languages/i18n/pt.json
languages/i18n/qqq.json
languages/i18n/sd.json
languages/i18n/sl.json
resources/Resources.php
resources/src/jquery/jquery.textSelection.js
resources/src/mediawiki.action/mediawiki.action.view.postEdit.js
resources/src/mediawiki/mediawiki.feedback.js
tests/phpunit/includes/LinkerTest.php
tests/phpunit/includes/Storage/RevisionStoreDbTest.php
tests/phpunit/includes/WikiReferenceTest.php
tests/phpunit/includes/db/DatabaseTestHelper.php
tests/phpunit/includes/installer/OracleInstallerTest.php
tests/phpunit/includes/libs/ArrayUtilsTest.php
tests/phpunit/includes/libs/IPTest.php
tests/phpunit/includes/libs/rdbms/database/DatabaseMysqlBaseTest.php
tests/phpunit/includes/libs/rdbms/database/DatabaseSQLTest.php
tests/phpunit/includes/libs/rdbms/database/DatabaseTest.php
tests/phpunit/includes/session/SessionBackendTest.php
tests/phpunit/includes/session/SessionManagerTest.php
tests/phpunit/includes/session/TestBagOStuff.php
tests/phpunit/includes/skins/SkinTemplateTest.php
tests/phpunit/includes/specials/ImageListPagerTest.php

index d49f205..6bf3c89 100644 (file)
@@ -2472,12 +2472,22 @@ ERROR;
                        $displayTitle = $contextTitle->getPrefixedText();
                }
                $out->setPageTitle( $this->context->msg( $msg, $displayTitle ) );
+
+               $config = $this->context->getConfig();
+
                # Transmit the name of the message to JavaScript for live preview
                # Keep Resources.php/mediawiki.action.edit.preview in sync with the possible keys
                $out->addJsConfigVars( [
                        'wgEditMessage' => $msg,
-                       'wgAjaxEditStash' => $this->context->getConfig()->get( 'AjaxEditStash' ),
+                       'wgAjaxEditStash' => $config->get( 'AjaxEditStash' ),
                ] );
+
+               // Add whether to use 'save' or 'publish' messages to JavaScript for post-edit, other
+               // editors, etc.
+               $out->addJsConfigVars(
+                       'wgEditSubmitButtonLabelPublish',
+                       $config->get( 'EditSubmitButtonLabelPublish' )
+               );
        }
 
        /**
index b6a751b..79ecec6 100644 (file)
@@ -1484,13 +1484,29 @@ class RevisionStore implements IDBAccessObject, RevisionFactory, RevisionLookup
         * @throws MWException
         */
        private function checkDatabaseWikiId( IDatabase $db ) {
-               $storeWiki = $this->loadBalancer->getLocalDomainID();
+               $storeWiki = $this->wikiId;
                $dbWiki = $db->getDomainID();
 
                if ( $dbWiki === $storeWiki ) {
                        return;
                }
 
+               // XXX: we really want the default database ID...
+               $storeWiki = $storeWiki ?: wfWikiID();
+               $dbWiki = $dbWiki ?: wfWikiID();
+
+               if ( $dbWiki === $storeWiki ) {
+                       return;
+               }
+
+               // HACK: counteract encoding imposed by DatabaseDomain
+               $storeWiki = str_replace( '?h', '-', $storeWiki );
+               $dbWiki = str_replace( '?h', '-', $dbWiki );
+
+               if ( $dbWiki === $storeWiki ) {
+                       return;
+               }
+
                throw new MWException( "RevisionStore for $storeWiki "
                        . "cannot be used with a DB connection for $dbWiki" );
        }
index 218454d..4da9509 100644 (file)
@@ -22,7 +22,7 @@
                        "Tacsipacsi"
                ]
        },
-       "apihelp-main-extended-description": "<div class=\"hlist plainlinks api-main-links\">\n* [[mw:Special:MyLanguage/API:Main_page|Dokumentation]]\n* [[mw:Special:MyLanguage/API:FAQ|Häufig gestellte Fragen]]\n* [https://lists.wikimedia.org/mailman/listinfo/mediawiki-api Mailingliste]\n* [https://lists.wikimedia.org/mailman/listinfo/mediawiki-api-announce API-Ankündigungen]\n* [https://phabricator.wikimedia.org/maniphest/query/GebfyV4uCaLd/#R Fehlerberichte und Anfragen]\n</div>\n<strong>Status:</strong> Alle auf dieser Seite gezeigten Funktionen sollten funktionieren, allerdings ist die API in aktiver Entwicklung und kann sich zu jeder Zeit ändern. Abonniere die [https://lists.wikimedia.org/pipermail/mediawiki-api-announce/ MediaWiki-API-Ankündigungs-Mailingliste], um über Aktualisierungen informiert zu werden.\n\n<strong>Fehlerhafte Anfragen:</strong> Wenn fehlerhafte Anfragen an die API gesendet werden, wird ein HTTP-Header mit dem Schlüssel „MediaWiki-API-Error“ gesendet. Der Wert des Headers und der Fehlercode werden auf den gleichen Wert gesetzt. Für weitere Informationen siehe [[mw:Special:MyLanguage/API:Errors_and_warnings|API: Fehler und Warnungen]].\n\n<strong>Testen:</strong> Zum einfachen Testen von API-Anfragen, siehe [[Special:ApiSandbox]].",
+       "apihelp-main-extended-description": "<div class=\"hlist plainlinks api-main-links\">\n* [[mw:Special:MyLanguage/API:Main_page|Dokumentation]]\n* [[mw:Special:MyLanguage/API:FAQ|Häufig gestellte Fragen]]\n* [https://lists.wikimedia.org/mailman/listinfo/mediawiki-api Mailingliste]\n* [https://lists.wikimedia.org/mailman/listinfo/mediawiki-api-announce API-Ankündigungen]\n* [https://phabricator.wikimedia.org/maniphest/query/GebfyV4uCaLd/#R Fehlerberichte und Anfragen]\n</div>\n<strong>Status:</strong> Alle auf dieser Seite gezeigten Funktionen sollten funktionieren, allerdings ist die API in aktiver Entwicklung und kann sich zu jeder Zeit ändern. Abonniere die [https://lists.wikimedia.org/pipermail/mediawiki-api-announce/ MediaWiki-API-Ankündigungs-Mailingliste], um über Aktualisierungen informiert zu werden.\n\n<strong>Fehlerhafte Anfragen:</strong> Wenn fehlerhafte Anfragen an die API gesendet werden, wird ein HTTP-Header mit dem Schlüssel „MediaWiki-API-Error“ gesendet. Der Wert des Headers und der Fehlercode werden auf den gleichen Wert gesetzt. Für weitere Informationen siehe [[mw:Special:MyLanguage/API:Errors_and_warnings|API: Fehler und Warnungen]].\n\n<p class=\"mw-apisandbox-link\"><strong>Testen:</strong> Zum einfachen Testen von API-Anfragen, siehe [[Special:ApiSandbox]].</p>",
        "apihelp-main-param-action": "Auszuführende Aktion.",
        "apihelp-main-param-format": "Format der Ausgabe.",
        "apihelp-main-param-maxlag": "maxlag kann verwendet werden, wenn MediaWiki auf einem datenbankreplizierten Cluster installiert ist. Um weitere Replikationsrückstände zu verhindern, lässt dieser Parameter den Client warten, bis der Replikationsrückstand kleiner als der angegebene Wert (in Sekunden) ist. Bei einem größerem Rückstand wird der Fehlercode <samp>maxlag</samp> zurückgegeben mit einer Nachricht wie <samp>Waiting for $host: $lag seconds lagged</samp>.<br />Siehe [[mw:Special:MyLanguage/Manual:Maxlag_parameter|Handbuch: Maxlag parameter]] für weitere Informationen.",
index 2f27b58..d72b218 100644 (file)
@@ -33,7 +33,7 @@
                        "Kenjiraw"
                ]
        },
-       "apihelp-main-extended-description": "<div class=\"hlist plainlinks api-main-links\">\n* [[mw:Special:MyLanguage/API:Main_page|Documentation]]\n* [[mw:Special:MyLanguage/API:FAQ|FAQ]]\n* [https://lists.wikimedia.org/mailman/listinfo/mediawiki-api Liste de diffusion]\n* [https://lists.wikimedia.org/mailman/listinfo/mediawiki-api-announce Annonces de l’API]\n* [https://phabricator.wikimedia.org/maniphest/query/GebfyV4uCaLd/#R Bogues et demandes]\n</div>\n<strong>État :</strong> Toutes les fonctionnalités affichées sur cette page devraient fonctionner, mais l’API est encore en cours de développement et peut changer à tout moment. Inscrivez-vous à [https://lists.wikimedia.org/pipermail/mediawiki-api-announce/ la liste de diffusion mediawiki-api-announce] pour être informé des mises à jour.\n\n<strong>Requêtes erronées :</strong> Si des requêtes erronées sont envoyées à l’API, un entête HTTP sera renvoyé avec la clé « MediaWiki-API-Error ». La valeur de cet entête et le code d’erreur renvoyé prendront la même valeur. Pour plus d’information, voyez [[mw:Special:MyLanguage/API:Errors_and_warnings|API: Errors and warnings]].\n\n<strong>Test :</strong> Pour faciliter le test des requêtes de l’API, voyez [[Special:ApiSandbox]].",
+       "apihelp-main-extended-description": "<div class=\"hlist plainlinks api-main-links\">\n* [[mw:Special:MyLanguage/API:Main_page|Documentation]]\n* [[mw:Special:MyLanguage/API:FAQ|FAQ]]\n* [https://lists.wikimedia.org/mailman/listinfo/mediawiki-api Liste de diffusion]\n* [https://lists.wikimedia.org/mailman/listinfo/mediawiki-api-announce Annonces de l’API]\n* [https://phabricator.wikimedia.org/maniphest/query/GebfyV4uCaLd/#R Bogues et demandes]\n</div>\n<strong>État :</strong> Toutes les fonctionnalités affichées sur cette page devraient fonctionner, mais l’API est encore en cours de développement et peut changer à tout moment. Inscrivez-vous à [https://lists.wikimedia.org/pipermail/mediawiki-api-announce/ la liste de diffusion mediawiki-api-announce] pour être informé des mises à jour.\n\n<strong>Requêtes erronées :</strong> Si des requêtes erronées sont envoyées à l’API, un entête HTTP sera renvoyé avec la clé « MediaWiki-API-Error ». La valeur de cet entête et le code d’erreur renvoyé prendront la même valeur. Pour plus d’information, voyez [[mw:Special:MyLanguage/API:Errors_and_warnings|API: Errors and warnings]].\n\n<p class=\"mw-apisandbox-link\"><strong>Test :</strong> Pour faciliter le test des requêtes de l’API, voyez [[Special:ApiSandbox]].</p>",
        "apihelp-main-param-action": "Quelle action effectuer.",
        "apihelp-main-param-format": "Le format de sortie.",
        "apihelp-main-param-maxlag": "La latence maximale peut être utilisée quand MédiaWiki est installé sur un cluster de base de données répliqué. Pour éviter des actions provoquant un supplément de latence de réplication de site, ce paramètre peut faire attendre le client jusqu’à ce que la latence de réplication soit inférieure à une valeur spécifiée. En cas de latence excessive, le code d’erreur <samp>maxlag</samp> est renvoyé avec un message tel que <samp>Attente de $host : $lag secondes de délai</samp>.<br />Voyez [[mw:Special:MyLanguage/Manual:Maxlag_parameter|Manuel: Maxlag parameter]] pour plus d’information.",
index 5682036..25da0e6 100644 (file)
@@ -19,7 +19,7 @@
                        "Margherita.mignanelli"
                ]
        },
-       "apihelp-main-extended-description": "<div class=\"hlist plainlinks api-main-links\">\n* [[mw:Special:MyLanguage/API:Main_page|Documentazione]] (in inglese)\n* [[mw:Special:MyLanguage/API:FAQ|FAQ]] (in inglese)\n* [https://lists.wikimedia.org/mailman/listinfo/mediawiki-api Mailing list]\n* [https://lists.wikimedia.org/mailman/listinfo/mediawiki-api-announce Annunci sull'API]\n* [https://phabricator.wikimedia.org/maniphest/query/GebfyV4uCaLd/#R Bug & richieste]\n</div>\n<strong>Stato:</strong> tutte le funzioni e caratteristiche mostrate su questa pagina dovrebbero funzionare, ma le API sono ancora in fase attiva di sviluppo, e potrebbero cambiare in qualsiasi momento. Iscriviti alla [https://lists.wikimedia.org/pipermail/mediawiki-api-announce/ la mailing list sugli annunci delle API MediaWiki] per essere informato sugli aggiornamenti.\n\n<strong>Istruzioni sbagliate:</strong> quando vengono impartite alle API delle istruzioni sbagliate, un'intestazione HTTP verrà inviata col messaggio \"MediaWiki-API-Error\" e, sia il valore dell'intestazione, sia il codice d'errore, verranno impostati con lo stesso valore. Per maggiori informazioni leggi [[mw:Special:MyLanguage/API:Errors_and_warnings|API:Errori ed avvertimenti]] (in inglese).\n\n<strong>Test:</strong> per testare facilmente le richieste API, vedi [[Special:ApiSandbox]].",
+       "apihelp-main-extended-description": "<div class=\"hlist plainlinks api-main-links\">\n* [[mw:Special:MyLanguage/API:Main_page|Documentazione]] (in inglese)\n* [[mw:Special:MyLanguage/API:FAQ|FAQ]] (in inglese)\n* [https://lists.wikimedia.org/mailman/listinfo/mediawiki-api Mailing list]\n* [https://lists.wikimedia.org/mailman/listinfo/mediawiki-api-announce Annunci sull'API]\n* [https://phabricator.wikimedia.org/maniphest/query/GebfyV4uCaLd/#R Bug & richieste]\n</div>\n<strong>Stato:</strong> tutte le funzioni e caratteristiche mostrate su questa pagina dovrebbero funzionare, ma le API sono ancora in fase attiva di sviluppo, e potrebbero cambiare in qualsiasi momento. Iscriviti alla [https://lists.wikimedia.org/pipermail/mediawiki-api-announce/ la mailing list sugli annunci delle API MediaWiki] per essere informato sugli aggiornamenti.\n\n<strong>Istruzioni sbagliate:</strong> quando vengono impartite alle API delle istruzioni sbagliate, un'intestazione HTTP verrà inviata col messaggio \"MediaWiki-API-Error\" e, sia il valore dell'intestazione, sia il codice d'errore, verranno impostati con lo stesso valore. Per maggiori informazioni leggi [[mw:Special:MyLanguage/API:Errors_and_warnings|API:Errori ed avvertimenti]] (in inglese).\n\n<p class=\"mw-apisandbox-link\"><strong>Test:</strong> per testare facilmente le richieste API, vedi [[Special:ApiSandbox]].</p>",
        "apihelp-main-param-action": "Azione da compiere.",
        "apihelp-main-param-format": "Formato dell'output.",
        "apihelp-main-param-assert": "Verifica che l'utente abbia effettuato l'accesso se si è impostato <kbd>user</kbd>, o che abbia i permessi di bot se si è impostato <kbd>bot</kbd>.",
index f4a4662..aa697fb 100644 (file)
@@ -8,13 +8,14 @@
                        "Hamilton Abreu",
                        "Mansil",
                        "Felipe L. Ewald",
-                       "Athena in Wonderland"
+                       "Athena in Wonderland",
+                       "Waldir"
                ]
        },
-       "apihelp-main-extended-description": "<div class=\"hlist plainlinks api-main-links\">\n* [[mw:Special:MyLanguage/API:Main_page|Documentação]]\n* [[mw:Special:MyLanguage/API:FAQ|FAQ]]\n* [https://lists.wikimedia.org/mailman/listinfo/mediawiki-api Lista de discussão]\n* [https://lists.wikimedia.org/mailman/listinfo/mediawiki-api-announce Anúncios da API]\n* [https://phabricator.wikimedia.org/maniphest/query/GebfyV4uCaLd/#R Erros e pedidos]\n</div>\n<strong>Estado:</strong> Todas as funcionalidades mostradas nesta página devem ter o comportamento documentado, mas a API ainda está em desenvolvimento ativo e pode ser alterada a qualquer momento. Inscreva-se na [https://lists.wikimedia.org/pipermail/mediawiki-api-announce/ lista de discussão mediawiki-api-announce] para ser informado acerca das atualizações.\n\n<strong>Pedidos incorretos:</strong> Quando são enviados pedidos incorretos à API, será devolvido um cabeçalho HTTP com a chave \"MediaWiki-API-Error\" e depois tanto o valor desse cabeçalho como o código de erro devolvido serão definidos com o mesmo valor. Para mais informação, consulte [[mw:Special:MyLanguage/API:Errors_and_warnings|API:Erros e avisos]].\n\n<strong>Testes:</strong> Para testar facilmente pedidos à API, visite [[Special:ApiSandbox|Testes da API]].",
+       "apihelp-main-extended-description": "<div class=\"hlist plainlinks api-main-links\">\n* [[mw:Special:MyLanguage/API:Main_page|Documentação]]\n* [[mw:Special:MyLanguage/API:FAQ|FAQ]]\n* [https://lists.wikimedia.org/mailman/listinfo/mediawiki-api Lista de discussão]\n* [https://lists.wikimedia.org/mailman/listinfo/mediawiki-api-announce Anúncios da API]\n* [https://phabricator.wikimedia.org/maniphest/query/GebfyV4uCaLd/#R Erros e pedidos]\n</div>\n<strong>Estado:</strong> Todas as funcionalidades mostradas nesta página devem ter o comportamento documentado, mas a API ainda está em desenvolvimento ativo e pode ser alterada a qualquer momento. Inscreva-se na [https://lists.wikimedia.org/pipermail/mediawiki-api-announce/ lista de discussão mediawiki-api-announce] para ser informado acerca das atualizações.\n\n<strong>Pedidos incorretos:</strong> Quando são enviados pedidos incorretos à API, será devolvido um cabeçalho HTTP com a chave \"MediaWiki-API-Error\" e depois tanto o valor desse cabeçalho como o código de erro devolvido serão definidos com o mesmo valor. Para mais informação, consulte [[mw:Special:MyLanguage/API:Errors_and_warnings|API:Erros e avisos]].\n\n<p class=\"mw-apisandbox-link\">\n<strong>Testes:</strong> Para testar facilmente pedidos à API, visite [[Special:ApiSandbox|Testes da API]].\n</p>",
        "apihelp-main-param-action": "A operação a ser realizada.",
        "apihelp-main-param-format": "O formato do resultado.",
-       "apihelp-main-param-maxlag": "O atraso máximo pode ser usado quando o MediaWiki é instalado num ''cluster'' de bases de dados replicadas. Para impedir que as operações causem ainda mais atrasos de replicação do ''site'', este parâmetro pode fazer o cliente aguardar até que o atraso de replicação seja inferior ao valor especificado. Caso o atraso atual exceda esse valor, o código de erro <samp>maxlag</samp> é devolvido com uma mensagem como <samp>À espera do servidor $host: $lag segundos de atraso</samp>.<br />Consulte [[mw:Special:MyLanguage/Manual:Maxlag_parameter|Manual: Parâmetro maxlag]] para mais informações.",
+       "apihelp-main-param-maxlag": "O atraso máximo pode ser usado quando o MediaWiki é instalado num ''cluster'' de bases de dados replicadas. Para impedir que as operações causem ainda mais atrasos de replicação do sítio, este parâmetro pode fazer o cliente aguardar até que o atraso de replicação seja inferior ao valor especificado. Caso o atraso atual exceda esse valor, o código de erro <samp>maxlag</samp> é devolvido com uma mensagem como <samp>À espera do servidor $host: $lag segundos de atraso</samp>.<br />Consulte [[mw:Special:MyLanguage/Manual:Maxlag_parameter|Manual: Parâmetro maxlag]] para mais informações.",
        "apihelp-main-param-smaxage": "Definir no cabeçalho HTTP <code>s-maxage</code> de controlo da cache este número de segundos. Os erros nunca são armazenados na cache.",
        "apihelp-main-param-maxage": "Definir no cabeçalho HTTP <code>max-age</code> de controlo da cache este número de segundos. Os erros nunca são armazenados na cache.",
        "apihelp-main-param-assert": "Se definido com o valor <kbd>user</kbd>, verificar que o utilizador está autenticado. Se definido com o valor <kbd>bot</kbd>, verificar que o utilizador tem o privilégio de conta robô.",
        "apihelp-opensearch-example-te": "Encontrar as páginas que começam por <kbd>Te</kbd>.",
        "apihelp-options-summary": "Alterar as preferências do utilizador atual.",
        "apihelp-options-extended-description": "Só podem ser definidas as opções que estão registadas no núcleo do MediaWiki ou numa das extensões instaladas, ou opções cuja chave tem o prefixo <code>userjs-</code> (que são supostas ser usadas por ''scripts'' de utilizador).",
-       "apihelp-options-param-reset": "Reiniciar preferências para os valores por omissão do ''site''.",
+       "apihelp-options-param-reset": "Reiniciar preferências para os valores por omissão do sítio.",
        "apihelp-options-param-resetkinds": "Lista dos tipos de opções a reiniciar quando a opção <var>$1reset</var> está definida.",
        "apihelp-options-param-change": "Listas das alterações, na forma nome=valor (isto é, skin=vector). Se não for fornecido nenhum valor (nem sequer um sinal de igualdade), por exemplo, nomedaopção|outraopção|..., a opção será reiniciada para o seu valor por omissão. Se qualquer dos valores passados contém uma barra vertical (<kbd>|</kbd>), use um [[Special:ApiHelp/main#main/datatypes|separador alternativo para valores múltiplos]] de forma a obter o comportamento correto.",
        "apihelp-options-param-optionname": "O nome da opção que deve ser configurada com o valor dado por <var>$1optionvalue</var>.",
        "apihelp-purge-example-simple": "Purgar as páginas <kbd>Main Page</kbd> e <kbd>API</kbd>.",
        "apihelp-purge-example-generator": "Purgar as primeiras 10 páginas no espaço nominal principal.",
        "apihelp-query-summary": "Obter dados de, e sobre, o MediaWiki.",
-       "apihelp-query-extended-description": "Todas as modificações de dados terão primeiro que usar uma consulta para adquirir uma chave, o que visa impedir abusos de sites maliciosos.",
+       "apihelp-query-extended-description": "Todas as modificações de dados terão primeiro que usar uma consulta para adquirir uma chave, o que visa impedir abusos de sítios maliciosos.",
        "apihelp-query-param-prop": "As propriedades a serem obtidas para as páginas consultadas.",
        "apihelp-query-param-list": "As listas a serem obtidas.",
        "apihelp-query-param-meta": "Os metadados a serem obtidos.",
        "apihelp-query-param-exportnowrap": "Devolver o XML de exportação sem envolvê-lo num resultado XML (o mesmo formato que [[Special:Export]]). Só pode ser usado com $1export.",
        "apihelp-query-param-iwurl": "Indica se deve ser obtido o URL completo quando o título é uma hiperligação interwikis.",
        "apihelp-query-param-rawcontinue": "Devolver os dados em bruto de <samp>query-continue</samp> para continuar.",
-       "apihelp-query-example-revisions": "Obter [[Special:ApiHelp/query+siteinfo|informação do ''site'']] e as [[Special:ApiHelp/query+revisions|revisões]] da página <kbd>Main Page</kbd>.",
+       "apihelp-query-example-revisions": "Obter [[Special:ApiHelp/query+siteinfo|informação do sítio]] e as [[Special:ApiHelp/query+revisions|revisões]] da página <kbd>Main Page</kbd>.",
        "apihelp-query-example-allpages": "Obter as revisões das páginas que começam por <kbd>API/</kbd>.",
        "apihelp-query+allcategories-summary": "Enumerar todas as categorias.",
        "apihelp-query+allcategories-param-from": "A categoria a partir da qual será começada a enumeração.",
        "apihelp-query+alllinks-example-unique": "Listar os títulos únicos para os quais existem hiperligações.",
        "apihelp-query+alllinks-example-unique-generator": "Obtém todos os títulos para os quais existem hiperligações, marcando aqueles em falta.",
        "apihelp-query+alllinks-example-generator": "Obtém as páginas que contêm as ligações.",
-       "apihelp-query+allmessages-summary": "Devolver as mensagens deste ''site''.",
+       "apihelp-query+allmessages-summary": "Devolver as mensagens deste sítio.",
        "apihelp-query+allmessages-param-messages": "Mensagens a serem produzidas no resultado. <kbd>*</kbd> (o valor por omissão) significa todas as mensagens.",
        "apihelp-query+allmessages-param-prop": "As propriedades a serem obtidas:",
        "apihelp-query+allmessages-param-enableparser": "Definir para ativar o analisador sintático; irá pré-processar o texto wiki da mensagem (substituir palavras mágicas, processar predefinições, etc.).",
        "apihelp-query+embeddedin-example-simple": "Mostrar as páginas que transcluem <kbd>Template:Stub</kbd>.",
        "apihelp-query+embeddedin-example-generator": "Obter informação sobre as páginas que transcluem <kbd>Template:Stub</kbd>.",
        "apihelp-query+extlinks-summary": "Devolve todos os URL externos (que não sejam interwikis) das páginas especificadas.",
-       "apihelp-query+extlinks-param-limit": "O número de ''links'' a serem devolvidos.",
+       "apihelp-query+extlinks-param-limit": "O número de hiperligações a serem devolvidas.",
        "apihelp-query+extlinks-param-protocol": "Protocolo do URL. Se vazio e <var>$1query</var> está definido, o protocolo é <kbd>http</kbd>. Deixe este parâmetro e <var>$1query</var> vazios para listar todas as hiperligações externas.",
        "apihelp-query+extlinks-param-query": "Texto de pesquisa sem protocolo. Útil para verificar se uma determinada página contém um determinado URL externo.",
        "apihelp-query+extlinks-param-expandurl": "Expandir os URL relativos a protocolo com o protocolo canónico.",
        "apihelp-query+info-param-token": "Em substituição, usar [[Special:ApiHelp/query+tokens|action=query&meta=tokens]].",
        "apihelp-query+info-example-simple": "Obter informações sobre a página <kbd>Main Page</kbd>.",
        "apihelp-query+info-example-protection": "Obter informação geral e de proteção sobre a página <kbd>Main Page</kbd>.",
-       "apihelp-query+iwbacklinks-summary": "Encontrar todas as páginas que contêm ''links'' para as páginas indicadas.",
+       "apihelp-query+iwbacklinks-summary": "Encontrar todas as páginas que contêm hiperligações para as páginas indicadas.",
        "apihelp-query+iwbacklinks-extended-description": "Pode ser usado para encontrar todas as hiperligações com um prefixo, ou todas as hiperligações para um título (com um prefixo especificado). Se nenhum dos parâmetros for usado, isso efetivamente significa \"todas as hiperligações interwikis\".",
        "apihelp-query+iwbacklinks-param-prefix": "O prefixo interwikis.",
        "apihelp-query+iwbacklinks-param-title": "A hiperligação interwikis a ser procurada. Tem de ser usado em conjunto com <var>$1blprefix</var>.",
        "apihelp-query+langlinks-example-simple": "Obter as hiperligações interlínguas da página <kbd>Main Page</kbd>.",
        "apihelp-query+links-summary": "Devolve todas as hiperligações das páginas indicadas.",
        "apihelp-query+links-param-namespace": "Mostrar apenas as hiperligações destes espaços nominais.",
-       "apihelp-query+links-param-limit": "O número de ''links'' a serem devolvidos.",
+       "apihelp-query+links-param-limit": "O número de hiperligações a serem devolvidas.",
        "apihelp-query+links-param-titles": "Listar só as hiperligações para estes títulos. Útil para verificar se uma determinada página contém hiperligações para um determinado título.",
        "apihelp-query+links-param-dir": "A direção de listagem.",
-       "apihelp-query+links-example-simple": "Obter os ''links'' da página <kbd>Main Page</kbd>.",
+       "apihelp-query+links-example-simple": "Obter as hiperligações da página <kbd>Main Page</kbd>.",
        "apihelp-query+links-example-generator": "Obter informação sobre as páginas ligadas na página <kbd>Main Page</kbd>.",
        "apihelp-query+links-example-namespaces": "Obter as hiperligações da página <kbd>Main Page</kbd> nos espaços nominais {{ns:user}} e {{ns:template}}.",
        "apihelp-query+linkshere-summary": "Encontrar todas as páginas que contêm hiperligações para as páginas indicadas.",
        "apihelp-query+search-example-simple": "Pesquisar <kbd>meaning</kbd>.",
        "apihelp-query+search-example-text": "Pesquisar <kbd>meaning</kbd> nos textos.",
        "apihelp-query+search-example-generator": "Obter informação sobre as páginas devolvidas por uma pesquisa do termo <kbd>meaning</kbd>.",
-       "apihelp-query+siteinfo-summary": "Devolver informação geral sobre o ''site''.",
+       "apihelp-query+siteinfo-summary": "Devolver informação geral sobre o sítio.",
        "apihelp-query+siteinfo-param-prop": "A informação a ser obtida:",
        "apihelp-query+siteinfo-paramvalue-prop-general": "Informação global do sistema.",
        "apihelp-query+siteinfo-paramvalue-prop-namespaces": "Uma lista dos espaços nominais registados e dos seus nomes canónicos.",
        "apihelp-query+siteinfo-paramvalue-prop-namespacealiases": "Uma lista dos nomes alternativos dos espaços nominais registados.",
        "apihelp-query+siteinfo-paramvalue-prop-specialpagealiases": "Uma lista dos nomes alternativos das páginas especiais.",
        "apihelp-query+siteinfo-paramvalue-prop-magicwords": "Uma lista das palavras mágicas e dos seus nomes alternativos.",
-       "apihelp-query+siteinfo-paramvalue-prop-statistics": "Devolve as estatísticas do ''site''.",
+       "apihelp-query+siteinfo-paramvalue-prop-statistics": "Devolve as estatísticas do sítio.",
        "apihelp-query+siteinfo-paramvalue-prop-interwikimap": "Devolve o mapa de interwikis (opcionalmente filtrado, opcionalmente localizado usando <var>$1inlanguagecode</var>).",
        "apihelp-query+siteinfo-paramvalue-prop-dbrepllag": "Devolve o servidor da base de dados com o maior atraso de replicação.",
        "apihelp-query+siteinfo-paramvalue-prop-usergroups": "Devolve os grupos de utilizadores e as permissões associadas.",
        "apihelp-query+siteinfo-paramvalue-prop-functionhooks": "Devolve uma lista dos ''hooks'' de funções do analisador sintático.",
        "apihelp-query+siteinfo-paramvalue-prop-showhooks": "Devolve uma lista de todos os ''hooks'' subscritos (conteúdo de <var>[[mw:Special:MyLanguage/Manual:$wgHooks|$wgHooks]]</var>).",
        "apihelp-query+siteinfo-paramvalue-prop-variables": "Devolve uma lista de identificadores de variáveis.",
-       "apihelp-query+siteinfo-paramvalue-prop-protocols": "Devolve uma lista dos protocolos permitidos nos ''links'' externos.",
+       "apihelp-query+siteinfo-paramvalue-prop-protocols": "Devolve uma lista dos protocolos permitidos nas hiperligações externas.",
        "apihelp-query+siteinfo-paramvalue-prop-defaultoptions": "Devolve os valores padrão para as preferências dos utilizadores.",
        "apihelp-query+siteinfo-paramvalue-prop-uploaddialog": "Devolve a configuração do diálogo de carregamento.",
        "apihelp-query+siteinfo-param-filteriw": "Devolver só as entradas locais, ou só as não locais, do mapa de interwikis.",
        "apihelp-query+siteinfo-param-showalldb": "Listar todos os servidores da base de dados, não só aquele que tem maior atraso.",
        "apihelp-query+siteinfo-param-numberingroup": "Lista o número de utilizadores nos grupos de utilizadores.",
        "apihelp-query+siteinfo-param-inlanguagecode": "O código de língua dos nomes localizados (o melhor possível) das línguas e dos temas.",
-       "apihelp-query+siteinfo-example-simple": "Obter as informações do ''site''.",
+       "apihelp-query+siteinfo-example-simple": "Obter as informações do sítio.",
        "apihelp-query+siteinfo-example-interwiki": "Obter uma lista dos prefixos interwikis locais.",
        "apihelp-query+siteinfo-example-replag": "Verificar o atraso de replicação atual.",
        "apihelp-query+stashimageinfo-summary": "Devolve informações dos ficheiros escondidos.",
index 95848ea..7e4dd00 100644 (file)
@@ -408,19 +408,24 @@ class ChangeTags {
                sort( $prevTags );
                sort( $newTags );
                if ( $prevTags == $newTags ) {
-                       // No change.
                        return false;
                }
 
                if ( !$newTags ) {
-                       // no tags left, so delete the row altogether
+                       // No tags left, so delete the row altogether
                        $dbw->delete( 'tag_summary', $tsConds, __METHOD__ );
                } else {
-                       $dbw->replace( 'tag_summary',
-                               [ 'ts_rev_id', 'ts_rc_id', 'ts_log_id' ],
-                               array_filter( array_merge( $tsConds, [ 'ts_tags' => implode( ',', $newTags ) ] ) ),
-                               __METHOD__
-                       );
+                       // Specify the non-DEFAULT value columns in the INSERT/REPLACE clause
+                       $row = array_filter( [ 'ts_tags' => implode( ',', $newTags ) ] + $tsConds );
+                       // Check the unique keys for conflicts, ignoring any NULL *_id values
+                       $uniqueKeys = [];
+                       foreach ( [ 'ts_rev_id', 'ts_rc_id', 'ts_log_id' ] as $uniqueColumn ) {
+                               if ( isset( $row[$uniqueColumn] ) ) {
+                                       $uniqueKeys[] = [ $uniqueColumn ];
+                               }
+                       }
+
+                       $dbw->replace( 'tag_summary', $uniqueKeys, $row, __METHOD__ );
                }
 
                return true;
index e2feb1f..90fabaf 100644 (file)
@@ -354,7 +354,7 @@ class DatabaseOracle extends Database {
                return $e['code'];
        }
 
-       function affectedRows() {
+       protected function fetchAffectedRowCount() {
                return $this->mAffectedRows;
        }
 
index 760986d..2280644 100644 (file)
@@ -67,7 +67,7 @@
        "config-env-php": "O PHP $1 está instalado.",
        "config-env-hhvm": "HHVM $1 está instalado.",
        "config-unicode-using-intl": "A usar a [http://pecl.php.net/intl extensão intl PECL] para a normalização Unicode.",
-       "config-unicode-pure-php-warning": "<strong>Aviso:</strong> A [http://pecl.php.net/intl extensão intl PECL] não está disponível para efetuar a normalização Unicode. Irá recorrer-se à implementação em PHP puro, que é mais lenta.\nSe o seu site tem alto volume de tráfego, devia informar-se um pouco sobre a [https://www.mediawiki.org/wiki/Special:MyLanguage/Unicode_normalization_considerations/pt normalização Unicode].",
+       "config-unicode-pure-php-warning": "<strong>Aviso:</strong> A [http://pecl.php.net/intl extensão intl PECL] não está disponível para efetuar a normalização Unicode. Irá recorrer-se à implementação em PHP puro, que é mais lenta.\nSe o seu sítio tem alto volume de tráfego, devia informar-se um pouco sobre a [https://www.mediawiki.org/wiki/Special:MyLanguage/Unicode_normalization_considerations/pt normalização Unicode].",
        "config-unicode-update-warning": "<strong>Aviso:</strong> A versão instalada do wrapper de normalização Unicode usa uma versão mais antiga da biblioteca do [http://site.icu-project.org/ projeto ICU].\nDevia [https://www.mediawiki.org/wiki/Special:MyLanguage/Unicode_normalization_considerations atualizá-la] se tem quaisquer preocupações sobre o uso do Unicode.",
        "config-no-db": "Não foi possível encontrar um controlador apropriado da base de dados! Precisa de instalar um controlador da base de dados para o PHP. {{PLURAL:$2|É aceite o seguinte tipo|São aceites os seguintes tipos}} de base de dados: $1.\n\nSe fez a compilação do PHP, reconfigure-o com um cliente de base de dados ativado; por exemplo, usando <code>./configure --with-mysqli</code>.\nSe instalou o PHP a partir de um pacote Debian ou Ubuntu, então precisa de instalar também, por exemplo, o pacote <code>php5-mysql</code>.",
        "config-outdated-sqlite": "<strong>Aviso:</strong> Tem a versão $1 do SQLite, que é anterior à versão mínima necessária, a $2. O SQLite não estará disponível.",
        "config-mssql-windowsauth": "Autenticação do Windows",
        "config-site-name": "Nome da wiki:",
        "config-site-name-help": "Este nome aparecerá no título da janela do seu navegador e em vários outros sítios.",
-       "config-site-name-blank": "Introduza o nome do site.",
+       "config-site-name-blank": "Introduza o nome do sítio.",
        "config-project-namespace": "Espaço nominal do projeto:",
        "config-ns-generic": "Projeto",
        "config-ns-site-name": "O mesmo que o nome da wiki: $1",
        "config-logo": "URL do logótipo:",
        "config-logo-help": "O tema padrão do MediaWiki inclui espaço para um logótipo de 135x160 píxeis acima do menu da barra lateral.\nColoque na wiki uma imagem com estas dimensões e introduza aqui o URL dessa imagem.\n\nSe não pretende usar um logótipo, deixe este campo em branco.",
        "config-instantcommons": "Ativar Instant Commons",
-       "config-instantcommons-help": "O [https://www.mediawiki.org/wiki/InstantCommons Instant Commons] é uma funcionalidade que permite que as wikis usem imagens, áudio e outros ficheiros multimédia disponíveis no site [https://commons.wikimedia.org/ Wikimedia Commons].\nPara poder usá-los, o MediaWiki necessita de acesso à Internet.\n\nPara mais informações sobre esta funcionalidade, incluindo instruções sobre como configurá-la para usar outras wikis em vez da Wikimedia Commons, consulte o [https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:$wgForeignFileRepos Manual Técnico].",
+       "config-instantcommons-help": "O [https://www.mediawiki.org/wiki/InstantCommons Instant Commons] é uma funcionalidade que permite que as wikis usem imagens, áudio e outros ficheiros multimédia disponíveis no sítio [https://commons.wikimedia.org/ Wikimedia Commons].\nPara poder usá-los, o MediaWiki necessita de acesso à Internet.\n\nPara mais informações sobre esta funcionalidade, incluindo instruções sobre como configurá-la para usar outras wikis em vez da Wikimedia Commons, consulte o [https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:$wgForeignFileRepos Manual Técnico].",
        "config-cc-error": "O auxiliar de escolha de licenças da Creative Commons não produziu resultados.\nIntroduza o nome da licença manualmente.",
        "config-cc-again": "Escolha outra vez...",
        "config-cc-not-chosen": "Escolha a licença da Creative Commons que pretende e clique \"proceed\".",
        "config-advanced-settings": "Configuração avançada",
        "config-cache-options": "Configuração da cache de objetos:",
-       "config-cache-help": "A cache de objetos é usada para melhorar o desempenho do MediaWiki. Armazena dados usados com frequência.\nSites de tamanho médio ou grande são altamente encorajados a ativar esta funcionalidade e os sites pequenos também terão alguns benefícios em fazê-lo.",
+       "config-cache-help": "A cache de objetos é usada para melhorar o desempenho do MediaWiki. Armazena dados usados com frequência.\nSítios de tamanho médio ou grande são altamente encorajados a ativar esta funcionalidade e os sítios pequenos também terão alguns benefícios em fazê-lo.",
        "config-cache-none": "Sem cache (não é removida nenhuma funcionalidade, mas a velocidade de operação pode ser afectada nas wikis grandes)",
        "config-cache-accel": "Cache de objetos do PHP (APC, APCu, XCache ou WinCache)",
        "config-cache-memcached": "Usar Memcached (requer instalação e configurações adicionais)",
index 409f507..08424c9 100644 (file)
@@ -419,6 +419,12 @@ class WANObjectCache implements IExpiringStore, LoggerAwareInterface {
         *
         * Setting 'lag' and 'since' help avoids keys getting stuck in stale states.
         *
+        * Be aware that this does not update the process cache for getWithSetCallback()
+        * callers. Keys accessed via that method are not generally meant to also be set
+        * using this primitive method.
+        *
+        * Do not use this method on versioned keys accessed via getWithSetCallback().
+        *
         * Example usage:
         * @code
         *     $dbr = wfGetDB( DB_REPLICA );
@@ -535,6 +541,10 @@ class WANObjectCache implements IExpiringStore, LoggerAwareInterface {
         *
         * Note that set() can also be lag-aware and lower the TTL if it's high.
         *
+        * Be aware that this does not clear the process cache. Even if it did, callbacks
+        * used by getWithSetCallback() might still return stale data in the case of either
+        * uncommitted or not-yet-replicated changes (callback generally use replica DBs).
+        *
         * When using potentially long-running ACID transactions, a good pattern is
         * to use a pre-commit hook to issue the delete. This means that immediately
         * after commit, callers will see the tombstone in cache upon purge relay.
index 1efa9a1..f3877fb 100644 (file)
@@ -126,6 +126,8 @@ abstract class Database implements IDatabase, IMaintainableDatabase, LoggerAware
        protected $delimiter = ';';
        /** @var DatabaseDomain */
        protected $currentDomain;
+       /** @var integer|null Rows affected by the last query to query() or its CRUD wrappers */
+       protected $affectedRowCount;
 
        /**
         * Either 1 if a transaction is active or 0 otherwise.
@@ -1002,8 +1004,7 @@ abstract class Database implements IDatabase, IMaintainableDatabase, LoggerAware
        }
 
        /**
-        * Helper method for query() that handles profiling and logging and sends
-        * the query to doQuery()
+        * Wrapper for query() that also handles profiling, logging, and affected row count updates
         *
         * @param string $sql Original SQL query
         * @param string $commentedSql SQL query with debugging/trace comment
@@ -1029,7 +1030,9 @@ abstract class Database implements IDatabase, IMaintainableDatabase, LoggerAware
                if ( $this->profiler ) {
                        call_user_func( [ $this->profiler, 'profileIn' ], $queryProf );
                }
+               $this->affectedRowCount = null;
                $ret = $this->doQuery( $commentedSql );
+               $this->affectedRowCount = $this->affectedRows();
                if ( $this->profiler ) {
                        call_user_func( [ $this->profiler, 'profileOut' ], $queryProf );
                }
@@ -2238,51 +2241,49 @@ abstract class Database implements IDatabase, IMaintainableDatabase, LoggerAware
        }
 
        public function replace( $table, $uniqueIndexes, $rows, $fname = __METHOD__ ) {
-               $quotedTable = $this->tableName( $table );
-
                if ( count( $rows ) == 0 ) {
                        return;
                }
 
-               # Single row case
+               // Single row case
                if ( !is_array( reset( $rows ) ) ) {
                        $rows = [ $rows ];
                }
 
-               // @FXIME: this is not atomic, but a trx would break affectedRows()
+               $affectedRowCount = 0;
                foreach ( $rows as $row ) {
-                       # Delete rows which collide
-                       if ( $uniqueIndexes ) {
-                               $sql = "DELETE FROM $quotedTable WHERE ";
-                               $first = true;
-                               foreach ( $uniqueIndexes as $index ) {
-                                       if ( $first ) {
-                                               $first = false;
-                                               $sql .= '( ';
-                                       } else {
-                                               $sql .= ' ) OR ( ';
-                                       }
-                                       if ( is_array( $index ) ) {
-                                               $first2 = true;
-                                               foreach ( $index as $col ) {
-                                                       if ( $first2 ) {
-                                                               $first2 = false;
-                                                       } else {
-                                                               $sql .= ' AND ';
-                                                       }
-                                                       $sql .= $col . '=' . $this->addQuotes( $row[$col] );
-                                               }
-                                       } else {
-                                               $sql .= $index . '=' . $this->addQuotes( $row[$index] );
-                                       }
+                       // Delete rows which collide with this one
+                       $indexWhereClauses = [];
+                       foreach ( $uniqueIndexes as $index ) {
+                               $indexColumns = (array)$index;
+                               $indexRowValues = array_intersect_key( $row, array_flip( $indexColumns ) );
+                               if ( count( $indexRowValues ) != count( $indexColumns ) ) {
+                                       throw new DBUnexpectedError(
+                                               $this,
+                                               'New record does not provide all values for unique key (' .
+                                                       implode( ', ', $indexColumns ) . ')'
+                                       );
+                               } elseif ( in_array( null, $indexRowValues, true ) ) {
+                                       throw new DBUnexpectedError(
+                                               $this,
+                                               'New record has a null value for unique key (' .
+                                                       implode( ', ', $indexColumns ) . ')'
+                                       );
                                }
-                               $sql .= ' )';
-                               $this->query( $sql, $fname );
+                               $indexWhereClauses[] = $this->makeList( $indexRowValues, LIST_AND );
+                       }
+
+                       if ( $indexWhereClauses ) {
+                               $this->delete( $table, $this->makeList( $indexWhereClauses, LIST_OR ), $fname );
+                               $affectedRowCount += $this->affectedRows();
                        }
 
-                       # Now insert the row
+                       // Now insert the row
                        $this->insert( $table, $row, $fname );
+                       $affectedRowCount += $this->affectedRows();
                }
+
+               $this->affectedRowCount = $affectedRowCount;
        }
 
        /**
@@ -2347,6 +2348,7 @@ abstract class Database implements IDatabase, IMaintainableDatabase, LoggerAware
                        $where = false;
                }
 
+               $affectedRowCount = 0;
                $useTrx = !$this->mTrxLevel;
                if ( $useTrx ) {
                        $this->begin( $fname, self::TRANSACTION_INTERNAL );
@@ -2355,11 +2357,13 @@ abstract class Database implements IDatabase, IMaintainableDatabase, LoggerAware
                        # Update any existing conflicting row(s)
                        if ( $where !== false ) {
                                $ok = $this->update( $table, $set, $where, $fname );
+                               $affectedRowCount += $this->affectedRows();
                        } else {
                                $ok = true;
                        }
                        # Now insert any non-conflicting row(s)
                        $ok = $this->insert( $table, $rows, $fname, [ 'IGNORE' ] ) && $ok;
+                       $affectedRowCount += $this->affectedRows();
                } catch ( Exception $e ) {
                        if ( $useTrx ) {
                                $this->rollback( $fname, self::FLUSHING_INTERNAL );
@@ -2369,6 +2373,7 @@ abstract class Database implements IDatabase, IMaintainableDatabase, LoggerAware
                if ( $useTrx ) {
                        $this->commit( $fname, self::FLUSHING_INTERNAL );
                }
+               $this->affectedRowCount = $affectedRowCount;
 
                return $ok;
        }
@@ -3187,6 +3192,17 @@ abstract class Database implements IDatabase, IMaintainableDatabase, LoggerAware
                }
        }
 
+       public function affectedRows() {
+               return ( $this->affectedRowCount === null )
+                       ? $this->fetchAffectedRowCount() // default to driver value
+                       : $this->affectedRowCount;
+       }
+
+       /**
+        * @return int Number of retrieved rows according to the driver
+        */
+       abstract protected function fetchAffectedRowCount();
+
        /**
         * Take the result from a query, and wrap it in a ResultWrapper if
         * necessary. Boolean values are passed through as is, to indicate success
index 53beb65..832ed9e 100644 (file)
@@ -353,7 +353,7 @@ class DatabaseMssql extends Database {
        /**
         * @return int
         */
-       public function affectedRows() {
+       protected function fetchAffectedRowCount() {
                return $this->mAffectedRows;
        }
 
index 82a78ca..6a545ce 100644 (file)
@@ -889,8 +889,10 @@ abstract class DatabaseMysqlBase extends Database {
                        return 0; // already reached this point for sure
                }
 
+               $useGTID = ( $this->useGTIDs && $pos->gtids );
+
                // Call doQuery() directly, to avoid opening a transaction if DBO_TRX is set
-               if ( $this->useGTIDs && $pos->gtids ) {
+               if ( $useGTID ) {
                        // Wait on the GTID set (MariaDB only)
                        $gtidArg = $this->addQuotes( implode( ',', $pos->gtids ) );
                        $res = $this->doQuery( "SELECT MASTER_GTID_WAIT($gtidArg, $timeout)" );
@@ -910,14 +912,17 @@ abstract class DatabaseMysqlBase extends Database {
                // Result can be NULL (error), -1 (timeout), or 0+ per the MySQL manual
                $status = ( $row[0] !== null ) ? intval( $row[0] ) : null;
                if ( $status === null ) {
-                       // T126436: jobs programmed to wait on master positions might be referencing binlogs
-                       // with an old master hostname. Such calls make MASTER_POS_WAIT() return null. Try
-                       // to detect this and treat the replica DB as having reached the position; a proper master
-                       // switchover already requires that the new master be caught up before the switch.
-                       $replicationPos = $this->getReplicaPos();
-                       if ( $replicationPos && !$replicationPos->channelsMatch( $pos ) ) {
-                               $this->lastKnownReplicaPos = $replicationPos;
-                               $status = 0;
+                       if ( !$useGTID ) {
+                               // T126436: jobs programmed to wait on master positions might be referencing
+                               // binlogs with an old master hostname; this makes MASTER_POS_WAIT() return null.
+                               // Try to detect this case and treat the replica DB as having reached the given
+                               // position (any master switchover already requires that the new master be caught
+                               // up before the switch).
+                               $replicationPos = $this->getReplicaPos();
+                               if ( $replicationPos && !$replicationPos->channelsMatch( $pos ) ) {
+                                       $this->lastKnownReplicaPos = $replicationPos;
+                                       $status = 0;
+                               }
                        }
                } elseif ( $status >= 0 ) {
                        // Remember that this position was reached to save queries next time
index c1a5698..09ea66c 100644 (file)
@@ -172,7 +172,7 @@ class DatabaseMysqli extends DatabaseMysqlBase {
        /**
         * @return int
         */
-       function affectedRows() {
+       protected function fetchAffectedRowCount() {
                $conn = $this->getBindingHandle();
 
                return $conn->affected_rows;
index 8c21d72..5bf845b 100644 (file)
@@ -384,7 +384,7 @@ class DatabasePostgres extends Database {
                }
        }
 
-       public function affectedRows() {
+       protected function fetchAffectedRowCount() {
                if ( !is_null( $this->mAffectedRows ) ) {
                        // Forced result for simulated queries
                        return $this->mAffectedRows;
index 2b06607..01772cf 100644 (file)
@@ -56,6 +56,9 @@ class DatabaseSqlite extends Database {
        /** @var FSLockManager (hopefully on the same server as the DB) */
        protected $lockMgr;
 
+       /** @var array List of shared database already attached to this connection */
+       private $alreadyAttached = [];
+
        /**
         * Additional params include:
         *   - dbDirectory : directory containing the DB and the lock file directory
@@ -82,16 +85,7 @@ class DatabaseSqlite extends Database {
                        parent::__construct( $p );
                        // Super doesn't open when $user is false, but we can work with $dbName
                        if ( $p['dbname'] && !$this->isOpen() ) {
-                               if ( $this->open( $p['host'], $p['user'], $p['password'], $p['dbname'] ) ) {
-                                       $done = [];
-                                       foreach ( $this->tableAliases as $params ) {
-                                               if ( isset( $done[$params['dbname']] ) ) {
-                                                       continue;
-                                               }
-                                               $this->attachDatabase( $params['dbname'] );
-                                               $done[$params['dbname']] = 1;
-                                       }
-                               }
+                               $this->open( $p['host'], $p['user'], $p['password'], $p['dbname'] );
                        }
                }
 
@@ -302,6 +296,14 @@ class DatabaseSqlite extends Database {
                return parent::isWriteQuery( $sql ) && !preg_match( '/^(ATTACH|PRAGMA)\b/i', $sql );
        }
 
+       protected function isTransactableQuery( $sql ) {
+               return parent::isTransactableQuery( $sql ) && !in_array(
+                       $this->getQueryVerb( $sql ),
+                       [ 'ATTACH', 'PRAGMA' ],
+                       true
+               );
+       }
+
        /**
         * SQLite doesn't allow buffered results or data seeking etc, so we'll use fetchAll as the result
         *
@@ -494,7 +496,7 @@ class DatabaseSqlite extends Database {
        /**
         * @return int
         */
-       function affectedRows() {
+       protected function fetchAffectedRowCount() {
                return $this->mAffectedRows;
        }
 
@@ -1033,6 +1035,17 @@ class DatabaseSqlite extends Database {
                return $this->query( $sql, $fName );
        }
 
+       public function setTableAliases( array $aliases ) {
+               parent::setTableAliases( $aliases );
+               foreach ( $this->tableAliases as $params ) {
+                       if ( isset( $this->alreadyAttached[$params['dbname']] ) ) {
+                               continue;
+                       }
+                       $this->attachDatabase( $params['dbname'] );
+                       $this->alreadyAttached[$params['dbname']] = true;
+               }
+       }
+
        protected function requiresDatabaseUser() {
                return false; // just a file
        }
index 8fee2c7..de7a6fa 100644 (file)
@@ -1171,7 +1171,9 @@ class Sanitizer {
                # Stupid hack
                $encValue = preg_replace_callback(
                        '/((?i)' . wfUrlProtocols() . ')/',
-                       [ self::class, 'armorLinksCallback' ],
+                       function ( $matches ) {
+                               return str_replace( ':', '&#58;', $matches[1] );
+                       },
                        $encValue );
                return $encValue;
        }
@@ -1416,15 +1418,6 @@ class Sanitizer {
                return $html;
        }
 
-       /**
-        * Regex replace callback for armoring links against further processing.
-        * @param array $matches
-        * @return string
-        */
-       private static function armorLinksCallback( $matches ) {
-               return str_replace( ':', '&#58;', $matches[1] );
-       }
-
        /**
         * Return an associative array of attribute names and values from
         * a partial tag string. Attribute names are forced to lowercase,
index 4a3e8af..830dbb4 100644 (file)
@@ -1227,7 +1227,11 @@ MESSAGE;
                $name, $scripts, $styles, $messages, $templates
        ) {
                if ( $scripts instanceof XmlJsCode ) {
-                       $scripts = new XmlJsCode( "function ( $, jQuery, require, module ) {\n{$scripts->value}\n}" );
+                       if ( self::inDebugMode() ) {
+                               $scripts = new XmlJsCode( "function ( $, jQuery, require, module ) {\n{$scripts->value}\n}" );
+                       } else {
+                               $scripts = new XmlJsCode( 'function($,jQuery,require,module){'. $scripts->value . '}' );
+                       }
                } elseif ( !is_string( $scripts ) && !is_array( $scripts ) ) {
                        throw new MWException( 'Invalid scripts error. Array of URLs or string of code expected.' );
                }
index 458c44d..ffa55c0 100644 (file)
@@ -51,10 +51,12 @@ class ResourceLoaderUserOptionsModule extends ResourceLoaderModule {
         * @return string JavaScript code
         */
        public function getScript( ResourceLoaderContext $context ) {
-               return Xml::encodeJsCall( 'mw.user.options.set',
+               // Use FILTER_NOMIN annotation to prevent needless minification and caching (T84960).
+               return ResourceLoader::FILTER_NOMIN . Xml::encodeJsCall(
+                       'mw.user.options.set',
                        [ $context->getUserObj()->getOptions( User::GETOPTIONS_EXCLUDE_DEFAULTS ) ],
                        ResourceLoader::inDebugMode()
-               ) . ResourceLoader::FILTER_NOMIN;
+               );
        }
 
        /**
index e933f1f..ae4fb67 100644 (file)
@@ -48,19 +48,16 @@ class ResourceLoaderUserTokensModule extends ResourceLoaderModule {
        }
 
        /**
-        * Generate the JavaScript content of this module.
-        *
-        * Add FILTER_NOMIN annotation to prevent needless minification and caching (T84960).
-        *
         * @param ResourceLoaderContext $context
         * @return string JavaScript code
         */
        public function getScript( ResourceLoaderContext $context ) {
-               return Xml::encodeJsCall(
+               // Use FILTER_NOMIN annotation to prevent needless minification and caching (T84960).
+               return ResourceLoader::FILTER_NOMIN . Xml::encodeJsCall(
                        'mw.user.tokens.set',
                        [ $this->contextUserTokens( $context ) ],
                        ResourceLoader::inDebugMode()
-               ) . ResourceLoader::FILTER_NOMIN;
+               );
        }
 
        /**
index 0c18a48..73ca76b 100644 (file)
@@ -164,7 +164,6 @@ class SpecialExpandTemplates extends SpecialPage {
                                'size' => 60,
                                'default' => $title,
                                'autofocus' => true,
-                               'cssclass' => 'mw-ui-input-inline',
                        ],
                        'input' => [
                                'type' => 'textarea',
index fd066ac..e62731f 100644 (file)
@@ -873,6 +873,10 @@ class UserrightsPage extends SpecialPage {
                                                } else {
                                                        $expiryHtml = $this->msg( 'userrights-expiry-none' )->text();
                                                }
+                                               // T171345: Add a hidden form element so that other groups can still be manipulated,
+                                               // otherwise saving errors out with an invalid expiry time for this group.
+                                               $expiryHtml .= Html::Hidden( "wpExpiry-$group",
+                                                       $currentExpiry ? 'existing' : 'infinite' );
                                                $expiryHtml .= "<br />\n";
                                        } else {
                                                $expiryHtml = Xml::element( 'span', null,
index de3b6af..e96d46a 100644 (file)
        "rcfilters-activefilters": "Filtros activos",
        "rcfilters-advancedfilters": "Filtros avanzaos",
        "rcfilters-limit-title": "Resultancies qu'amosar",
-       "rcfilters-limit-and-date-label": "{{PLURAL:$1|cambiu|$1 cambios}}, $2",
+       "rcfilters-limit-and-date-label": "$1 {{PLURAL:$1|cambiu|$1 cambios}}, $2",
        "rcfilters-date-popup-title": "Periodu de tiempu a buscar",
        "rcfilters-days-title": "Últimos díes",
        "rcfilters-hours-title": "Últimes hores",
        "lockmanager-fail-closelock": "Nun se pudo zarrar el ficheru de bloquéu pa \"$1\".",
        "lockmanager-fail-deletelock": "Non se pudo desaniciar el ficheru de bloquéu pa \"$1\".",
        "lockmanager-fail-acquirelock": "Nun se pudo adquirir el bloquéu pa \"$1\".",
-       "lockmanager-fail-openlock": "Nun se pudo abrir el ficheru de bloquéu pa \"$1\".",
+       "lockmanager-fail-openlock": "Nun se pudo abrir el ficheru de bloquéu pa \"$1\". Por favor comprueba que'l direutoriu de xubíes ta configuráu correutamente y que'l to sirvidor web tien permisos d'escritura nesi direutoriu. Ver https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:$wgUploadDirectory pa más información.",
        "lockmanager-fail-releaselock": "Nun se pudo lliberar el bloquéu pa \"$1\".",
        "lockmanager-fail-db-bucket": "Nun se pudo contautar con bloqueos de bases de datos bastantes nel conxuntu $1.",
        "lockmanager-fail-db-release": "Nun se pudieron lliberar los bloqueos na base de datos $1.",
        "doubleredirects": "Redireiciones dobles",
        "doubleredirectstext": "Esta páxina llista páxines que redireicionen a otres páxines de redireición.\nCada filera contien enllaces a la primera y segunda redireición, asina como al oxetivu de la segunda redireición, que de vezu ye la páxina oxetivu \"real\", onde tendría d'empobinar la primera redireición.\nLes entraes <del>tachaes</del> tan resueltes.",
        "double-redirect-fixed-move": "[[$1]] treslladóse.\nAnovóse automáticamente y agora redirixe haza [[$2]].",
-       "double-redirect-fixed-maintenance": "Iguando automáticamente la doble redireición de [[$1]] a [[$2]] nuna xera de mantenimientu.",
+       "double-redirect-fixed-maintenance": "Iguando automáticamente la doble redireición de [[$1]] a [[$2]] nuna xera de mantenimientu",
        "double-redirect-fixer": "Iguador de redireiciones",
        "brokenredirects": "Redireiciones frañaes",
        "brokenredirectstext": "Les redireiciones siguientes enllacien a páxines que nun esisten:",
index a03318a..607d11b 100644 (file)
        "right-createtalk": "Стварэньне старонак абмеркаваньня",
        "right-createaccount": "Стварэньне новых рахункаў удзельнікаў",
        "right-autocreateaccount": "Аўтаматычны ўваход з вонкавага рахунку ўдзельніка",
-       "right-minoredit": "пазнаÑ\87Ñ\8dнÑ\8cне Ñ\80Ñ\8dдагаванÑ\8cнÑ\8fÑ\9e Ñ\8fк Ð´Ñ\80обнÑ\8bÑ\8f",
+       "right-minoredit": "Ð\9fазнаÑ\87Ñ\8dнÑ\8cне Ñ\80Ñ\8dдагаванÑ\8cнÑ\8fÑ\9e Ñ\8fк Ð´Ñ\80обнÑ\8bÑ\85",
        "right-move": "перанос старонак",
        "right-move-subpages": "перанос старонак разам зь іх падстаронкамі",
        "right-move-rootuserpages": "перанос карэнных старонак удзельнікаў",
index a569fc9..3f3f3e9 100644 (file)
        "zip-file-open-error": "Възникна грешка при отваряне на файла за проверка на ZIP.",
        "zip-wrong-format": "Указаният файл не е ZIP файл.",
        "zip-bad": "Файлът е повреден или е нечетим ZIP файл.\nСигурността му не може да бъде проверена.",
-       "zip-unsupported": "Файлът е ZIP файл, който използва ZIP компоненти, които не се поддържат от МедияУики.\nСигурността му не може да бъде коректно проверена.",
+       "zip-unsupported": "Файлът е ZIP файл, който използва функционалност, която не се поддържа от МедияУики.\nСигурността му не може да бъде коректно проверена.",
        "uploadstash": "Скрити качвания",
        "uploadstash-summary": "Тази страница предоставя достъп до файловете, които са качени (или са в процес на качване), но все още не са публикувани в уикито. Тези файлове не са достъпни само за потребителя, който ги е качил.",
        "uploadstash-clear": "Изчистване на скритите качвания",
index 828804d..3a018c8 100644 (file)
        "postedit-confirmation-created": "Die Seite wurde erstellt.",
        "postedit-confirmation-restored": "Die Seite wurde wiederhergestellt.",
        "postedit-confirmation-saved": "Deine Bearbeitung wurde gespeichert.",
+       "postedit-confirmation-published": "Deine Bearbeitung wurde veröffentlicht.",
        "edit-already-exists": "Die neue Seite konnte nicht erstellt werden, da sie bereits vorhanden ist.",
        "defaultmessagetext": "Standardtext",
        "content-failed-to-parse": "Parsen des Inhalts $2 für Modell $1 fehlgeschlagen: $3",
index 745a432..ca5672d 100644 (file)
        "seconds-ago": "Verê $1 {{PLURAL:$1|saniya|saniyeyan}}",
        "monday-at": "Dışeme $1 de",
        "tuesday-at": "Sêşeme $1 de",
-       "wednesday-at": "Çarşeme $1 de",
+       "wednesday-at": "Çeharşeme $1 de",
        "thursday-at": "Pancşeme $1 de",
        "friday-at": "Êne $1 de",
        "saturday-at": "Şeme $1 de",
index 3726ae9..a638833 100644 (file)
        "postedit-confirmation-created": "The page has been created.",
        "postedit-confirmation-restored": "The page has been restored.",
        "postedit-confirmation-saved": "Your edit was saved.",
+       "postedit-confirmation-published": "Your edit was published.",
        "edit-already-exists": "Could not create a new page.\nIt already exists.",
        "addsection-preload": "",
        "addsection-editintro": "",
index 3bf879f..e112dce 100644 (file)
        "lockmanager-fail-closelock": "No se pudo cerrar la referencia para el archivo de bloqueo de \"$1\".",
        "lockmanager-fail-deletelock": "No se pudo eliminar el archivo de bloqueo para \"$1\".",
        "lockmanager-fail-acquirelock": "No pudo adquirir el bloqueo para \"$1\".",
-       "lockmanager-fail-openlock": "No se pudo abrir el archivo de bloqueo para \"$1\". Por favor verifica que el directorio de subidas está configurado correctamente y que tu servidor web tiene permisos de escritura en ese directorio. Ver https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:$wgUploadDirectory para más información.",
+       "lockmanager-fail-openlock": "No se pudo abrir el archivo de bloqueo de «$1». Revisa que el directorio de cargas esté configurado correctamente y que tu servidor web tenga permisos de escritura en ese directorio. Consulta https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:$wgUploadDirectory para obtener más información.",
        "lockmanager-fail-releaselock": "No se pudo liberar el bloqueo de \"$1\".",
        "lockmanager-fail-db-bucket": "No se pudo contactar con las suficientes bases de datos del conjunto $1.",
        "lockmanager-fail-db-release": "No se pudieron liberar los bloqueos registrados en la base de datos $1.",
        "protect-otherreason": "Otra razón:",
        "protect-otherreason-op": "Otro motivo",
        "protect-dropdown": "*Razones de protección habituales\n**Vandalismo excesivo\n**Spam excesivo\n**Guerra de ediciones\n**Página muy visitada",
-       "protect-edit-reasonlist": "Editar las razones de protección",
+       "protect-edit-reasonlist": "Editar motivos de protección",
        "protect-expiry-options": "1 hora:1 hour,1 día:1 day,1 semana:1 week,2 semanas:2 weeks,1 mes:1 month,3 meses:3 months,6 meses:6 months,1 año:1 year,para siempre:infinite",
        "restriction-type": "Permiso:",
        "restriction-level": "Nivel de restricción:",
index a92336b..de21953 100644 (file)
        "lockmanager-fail-closelock": "Ezin izan da \"$1\" fitxategiaren giltza itxi.",
        "lockmanager-fail-deletelock": "Ezin izan da \"$1\" fitxategia desblokeatu.",
        "lockmanager-fail-acquirelock": "Ezin izan da \"$1\" blokeoa eskuratu.",
-       "lockmanager-fail-openlock": "Ezin izan da \"$1\" blokeo fitxategia ireki.",
+       "lockmanager-fail-openlock": "Ezin izan da \"$1\"-rentzako blokeo fitxategia ireki. Ziurtatu igoera direktorioa behar bezala konfiguratuta dagoela eta zure web zerbitzariak baimena duela idazteko. Ikusi informazio gehiagorako https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:$wgUploadDirectory.",
        "lockmanager-fail-releaselock": "Ezin izan da \"$1\" blokeoa askatu.",
        "lockmanager-fail-db-bucket": "Ezin izan dut $1 buketean datubase nahikoa ziurtatu.",
        "lockmanager-fail-db-release": "Ezin izan da $1 datubasean giltzaraporik askatu.",
        "restrictionsfield-badip": "Baliogabeko IP helbide edo eremua: $1",
        "restrictionsfield-label": "Onartutako IP eremuak:",
        "restrictionsfield-help": "Linea bakoitzeko IP helbide edo CIDR eremu bakarra. Guztia gaitzeko, erabili: \n<pre>0.0.0.0/0\n::/0</pre>",
+       "edit-error-short": "Akatsa: $1",
+       "edit-error-long": "Akatsak:\n\n$1",
        "revid": "$1 berrikusi",
        "pageid": "$1 orri IDa",
        "rawhtml-notallowed": "&lt;html&gt; etiketak ezin dira orri arruntetatik kanpo erabili.",
index e79ee5f..7bbbed5 100644 (file)
        "lockmanager-fail-closelock": "לא הייתה אפשרות לסגור את קובץ הנעילה עבור \"$1\".",
        "lockmanager-fail-deletelock": "לא הייתה אפשרות למחוק את קובץ הנעילה עבור \"$1\".",
        "lockmanager-fail-acquirelock": "לא הייתה אפשרות לקבל נעילה עבור \"$1\".",
-       "lockmanager-fail-openlock": "לא הייתה אפשרות לפתוח את קובץ הנעילה עבור \"$1\".",
+       "lockmanager-fail-openlock": "לא הייתה אפשרות לפתוח את קובץ הנעילה עבור \"$1\". יש לוודא שתיקיית ההעלאות מוגדרת בצורה תקינה ושלשרת האינטרנט יש הרשאות לכתוב לתיקייה זו. [https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:$wgUploadDirectory למידע נוסף].",
        "lockmanager-fail-releaselock": "לא הייתה אפשרות לשחרר את הנעילה עבור \"$1\".",
        "lockmanager-fail-db-bucket": "לא הייתה אפשרות לקבל מספיק מסדי נתונים של נעילות בדלי $1.",
        "lockmanager-fail-db-release": "לא הייתה אפשרות לשחרר נעילות על מסד הנתונים $1.",
index 1a1353d..58d3d17 100644 (file)
        "search-external": "Külső kereső",
        "searchdisabled": "Elnézésed kérjük, de a teljes szöveges keresés terhelési okok miatt átmenetileg nem használható. Ezidő alatt használhatod a lenti Google keresést, mely viszont lehetséges, hogy nem teljesen friss adatokkal dolgozik.",
        "search-error": "A keresés közben hiba történt: $1",
-       "search-warning": "$1 keresése közben hiba történt",
+       "search-warning": "Hiba történt a keresés közben: $1",
        "preferences": "Beállítások",
        "mypreferences": "Beállítások",
        "prefs-edits": "Szerkesztéseid száma:",
index a50f7bc..367115c 100644 (file)
        "recentchangeslinked-feed": "関連ページの更新状況",
        "recentchangeslinked-toolbox": "関連ページの更新状況",
        "recentchangeslinked-title": "「$1」と関連する変更",
-       "recentchangeslinked-summary": "ã\81\93ã\82\8cã\81¯æ\8c\87å®\9aã\81\97ã\81\9fã\83\9aã\83¼ã\82¸ã\81\8bã\82\89ã\83ªã\83³ã\82¯ã\81\95ã\82\8cã\81¦ã\81\84ã\82\8b (ã\81¾ã\81\9fã\81¯æ\8c\87å®\9aã\81\97ã\81\9fã\82«ã\83\86ã\82´ã\83ªã\81«å\90«ã\81¾ã\82\8cã\81¦ã\81\84ã\82\8b) ã\83\9aã\83¼ã\82¸ã\81®æ\9c\80è¿\91ã\81®å¤\89æ\9b´ã\81®ä¸\80覧ã\81§ã\81\99ã\80\82\n[[Special:Watchlist|è\87ªå\88\86ã\81®ã\82¦ã\82©ã\83\83ã\83\81ã\83ªã\82¹ã\83\88]]ã\81«ã\81\82ã\82\8bã\83\9aã\83¼ã\82¸は<strong>太字</strong>で表示されます。",
+       "recentchangeslinked-summary": "ã\83\9aã\83¼ã\82¸å\90\8dã\82\92å\85¥å\8a\9bã\81\99ã\82\8bã\81¨ã\80\81ã\83ªã\83³ã\82¯é\96¢ä¿\82 (ã\81\9dã\81®ã\83\9aã\83¼ã\82¸ã\81®ã\83ªã\83³ã\82¯å\85\88ã\82\82ã\81\97ã\81\8fã\81¯ä»\96ã\81®ã\83\9aã\83¼ã\82¸ã\81\8bã\82\89ã\81®ã\83ªã\83³ã\82¯) ã\81®æ\9c\80è¿\91ã\81®å¤\89æ\9b´ã\82\92調ã\81¹ã\82\8bã\81\93ã\81¨ã\81\8cã\81§ã\81\8dã\81¾ã\81\99ã\80\82 (ä¸\8bä½\8dã\82«ã\83\86ã\82´ã\83ªã\82\92å\8f\82ç\85§ã\81\99ã\82\8bã\81«ã\81¯ã\80\81ã\82«ã\83\86ã\82´ã\83ª:ã\82«ã\83\86ã\82´ã\83ªå\90\8d (Category:Name of category) ã\82\92å\85¥å\8a\9b\80\82[[Special:Watchlist|è\87ªå\88\86ã\81®ã\82¦ã\82©ã\83\83ã\83\81ã\83ªã\82¹ã\83\88]]ã\81«ã\81\82ã\82\8bã\83\9aã\83¼ã\82¸ã\81®å¤\89æ\9b´は<strong>太字</strong>で表示されます。",
        "recentchangeslinked-page": "ページ名:",
        "recentchangeslinked-to": "このページへのリンク元での変更の表示に切り替え",
        "recentchanges-page-added-to-category": "[[:$1]]をカテゴリに追加",
index 500e25e..9bb875a 100644 (file)
        "site-rss-feed": "$1 ''RSS Feed''",
        "site-atom-feed": "Lebon atom $1",
        "page-rss-feed": "\"$1\" ''RSS Feed''",
-       "page-atom-feed": "\"$1\" ''Atom Feed''",
+       "page-atom-feed": "Pakan atom \"$1\"",
        "red-link-title": "$1 (kaca ora ana)",
        "sort-descending": "Urutaké medhun",
        "sort-ascending": "Urutaké munggah",
        "nosuchaction": "Ora ana tumindak mangkono",
        "nosuchactiontext": "Tumindak sing dikarepaké déning URL ora trep.\nPanjenengan bokmanawa salah ngetik URL-é, utawa salah nurut pranala.\nIki bokmanawa uga nuduhaké yèn ana ama ing piranti alus sing dianggo déning {{SITENAME}}.",
        "nosuchspecialpage": "Ora ana kaca mirunggan mangkono",
-       "nospecialpagetext": "Panjenengan nyuwun kaca astaméwa sing ora sah. Daftar kaca astaméwa sing sah bisa dipirsani ing [[Special:SpecialPages|daftar kaca astaméwa]].",
+       "nospecialpagetext": "<strong>Panjenengan nyuwun kaca mirunggan sing ora sah.</strong>\n\nPratélan kaca mirunggan sing sah bisa tinemu ing [[Special:SpecialPages|{{int:specialpages}}]].",
        "error": "Masalah",
        "databaseerror": "Masalah sasana dhata",
        "databaseerror-text": "Ana kerusakan ing basis data (query error).\n\nMungkin ana masalah ing software-e.",
        "showingresults": "Ing ngisor iki dituduhaké {{PLURAL:$1|'''1''' kasil|'''$1''' kasil}}, wiwitané saking #<strong>$2</strong>.",
        "showingresultsinrange": "Nuduhaké nganti {{PLURAL:$1|<strong>1</strong> kasil|<strong>$1</strong> kasil}} sajeroning penthangan #<strong>$2</strong> tekan #<strong>$3</strong>.",
        "search-showingresults": "{{PLURAL:$4|Asil <strong>$1</strong> saka <strong>$3</strong>|Asil <strong>$1 – $2</strong> saka <strong>$3</strong>}}",
-       "search-nonefound": "Ora ana kasil sing cocog karo pitakonan (''query'').",
+       "search-nonefound": "Ora ana kasil sing mathuk karo pitakoné.",
        "search-nonefound-thiswiki": "Ora ana kasil sing jumbuh karo panjalukan ing situs iki.",
        "powersearch-legend": "Panggolèkan sabanjuré (''advance search'')",
        "powersearch-ns": "Golèk ing mandala aran:",
        "recentchanges": "Owahan-owahan anyar",
        "recentchanges-legend": "Opsi owah-owahan anyar",
        "recentchanges-summary": "Lacak owah-owahan anyar wiki iki ing kaca iki.",
-       "recentchanges-noresult": "Ora ana pangowahan ing periode sing diwiwiti kriteria iki.",
+       "recentchanges-noresult": "Ora ana owahan ing kalamangsa sing mathuk karo pranatan iki.",
        "recentchanges-feed-description": "Urutna owah-owahan anyar ing wiki ing ''feed'' iki.",
        "recentchanges-label-newpage": "Besutan iki nggawé kaca anyar",
        "recentchanges-label-minor": "Iki besutan cilik",
        "recentchangeslinked-title": "Owah-owahan sing magepokan \"$1\"",
        "recentchangeslinked-summary": "Iki pratélaning owah-owahan sing mentas digawé tumrap ing kaca-kaca sing nggayut sawijining kaca (utawa kaca-kaca anggotaning sawijining kategori).\nKaca ing [[Special:Watchlist|pawawangané panjenegan]] <strong>dikandeli</strong>.",
        "recentchangeslinked-page": "Jeneng kaca:",
-       "recentchangeslinked-to": "Nuduhaké owah-owahan menyang kaca sing disambung menyang kaca-kaca iki",
+       "recentchangeslinked-to": "Nuduhaké owah-owahan kaca-kaca sing nggayut kaca iki",
        "recentchanges-page-added-to-category": "[[:$1]] ditambahaké ing kategori",
        "recentchanges-page-added-to-category-bundled": "[[:$1]] ditambahaké ing kategori, [[Special:WhatLinksHere/$1|kaca iki kalebu ing njeroné kaca liyané]]",
        "recentchanges-page-removed-from-category": "[[:$1]] dibusak saka kategori",
        "mywatchlist": "Pawawangan",
        "watchlistfor2": "Kanggo $1 $2",
        "nowatchlist": "Ora ana apa-apa ing pawawanganing sampéyan.",
-       "watchlistanontext": "Mangga $1 kanggo mirsani utawa nyunting daftar pangawasan panjenengan.",
+       "watchlistanontext": "Sumangga mlebu log saperlu ndeleng utawa mbesut barang ing pawawangané panjenengan.",
        "watchnologin": "Durung mlebu log",
        "addwatch": "Tambah nèng daptar pangawasan",
        "addedwatchtext": "Kaca \"[[:$1]]\" wis ditambahaké menyang [[Special:Watchlist|daftar pangawasan]].\nOwah-owahan sing dumadi ing tembé ing kaca iku lan kaca dhiskusi sing kagandhèng, bakal dipacak ing kéné.",
        "import-upload": "Ngunggahaké data XML",
        "import-token-mismatch": "Kélangan data sèsi. Mangga dijajal manèh.",
        "import-invalid-interwiki": "Ora bisa ngimport saka wiki sing kapilih.",
-       "import-error-edit": "Kaca \"$1\" ora diimpor amarga Sampéyan ora dililakaké nyunting kuwi.",
+       "import-error-edit": "Kaca \"$1\" ora kaimpor amarga panjenengan ora kawogan mbesut iku.",
        "import-error-create": "Kaca \"$1\" ora diimpor amarga Sampéyan ora dililakaké nggawé kuwi.",
        "import-error-interwiki": "Kaca \"$1\" ora diimpor amarga jenengé dicadhangaké kango pranala njaba (interwiki).",
        "import-error-special": "Kaca \"$1\" ora diimpor amarga darbèké mandala aran mirunggan sing ora nglilakaké anané kaca.",
        "tooltip-t-whatlinkshere": "Pratélané kabèh kaca wiki sing nggayut mréné",
        "tooltip-t-recentchangeslinked": "Owah-owahan anyar saka kaca-kaca sing nggayut kaca iki",
        "tooltip-feed-rss": "''RSS feed'' kanggo kaca iki",
-       "tooltip-feed-atom": "''Atom feed'' kanggo kaca iki",
+       "tooltip-feed-atom": "Pakan atom tumrap kaca iki",
        "tooltip-t-contributions": "Pratélaning pisumbanging {{GENDER:$1|panganggo iki}}",
        "tooltip-t-emailuser": "Kirimi layang-èl nyang {{GENDER:$1|panganggo iki}}",
        "tooltip-t-info": "Katerangan liyané ngenani kaca iki",
        "exif-referenceblackwhite": "Wiji réferènsi pasangan ireng putih",
        "exif-datetime": "Tanggal lan wektu owahé barkas",
        "exif-imagedescription": "Sesirah gambar",
-       "exif-make": "Produsèn kamera",
+       "exif-make": "Prodhusèn kodhak",
        "exif-model": "Modhèl kaméra",
        "exif-software": "Piranti alus sing dianggo",
        "exif-artist": "Prodhusèn",
        "scarytranscludetoolong": "[URL-é kedawan]",
        "deletedwhileediting": "<strong>Pélik:</strong> Kaca iki wis dibusak kawit pisanan panjenengan mbesut!",
        "confirmrecreate": "Panganggo [[User:$1|$1]] ([[User talk:$1|Wicara]]) wis mbusak kaca iki nalika panjenengan miwiti panyuntingan mawa alesan:\n: ''$2''\nMangga didhedhes (dikonfirmasi) menawa panjenengan kersa nggawé ulang kaca iki.",
-       "confirmrecreate-noreason": "Panganggo [[User:$1|$1]] ([[User talk:$1|wicara]]) mbusak kaca iki sakbaré Sampéyan lekas nyunting. Mangga pesthèkaké yèn Sampéyan pancen pingin tenan nggawé manèh kaca iki.",
+       "confirmrecreate-noreason": "Panganggo [[User:$1|$1]] ([[User talk:$1|rembug]]) {{GENDER:$1|mbusak}} kaca iki sawisé panjenengan wiwit mbesut. Sumangga konfirmasi yèn panjenengan temen arep nggawé manèh kaca iki.",
        "recreate": "Gawé ulang",
        "confirm-purge-title": "Buwang kaca iki",
        "confirm_purge_button": "OK",
        "redirect": "Lih-lihan miturut barkas, panganggo, kaca, owahan, utawa cathetan",
        "redirect-summary": "Kaca mirunggan iki ngener ing sawijining barkas (jeneng gambar diwenehi), kaca (ID revisi utama ID kaca diwenehi), utawa kaca panganggo (ID panganggo diwenehi). Cara nganggo: [[{{#Special:Redirect}}/file/Example.jpg]], [[{{#Special:Redirect}}/page/64308]], [[{{#Special:Redirect}}/revision/328429]], or [[{{#Special:Redirect}}/user/101]].",
        "redirect-submit": "Menyang",
-       "redirect-lookup": "Golek:",
+       "redirect-lookup": "Luru:",
        "redirect-value": "Aji:",
        "redirect-user": "ID panganggo",
        "redirect-page": "ID kaca",
        "logentry-patrol-patrol": "$1 {{GENDER:$2|nengeri}} révisi $4 saka kaca $3 sing diawasi",
        "logentry-patrol-patrol-auto": "$1 otomatis {{GENDER:$2|nandhani}} benahan $4 saka kaca $3 kaawasake",
        "logentry-newusers-newusers": "Akun panganggo $1 {{GENDER:$2|digawé}}",
-       "logentry-newusers-create": "Akun panganggo $1 {{GENDER:$2|digawé}}",
+       "logentry-newusers-create": "Akun panganggo $1 wis {{GENDER:$2|kagawé}}",
        "logentry-newusers-create2": "Akun panganggo $3 {{GENDER:$2|digawé}} déning $1",
        "logentry-newusers-byemail": "Akun panganggo $3 {{GENDER:$2|digawé}} déning $1 lan tembung wadi dikirim lumantar layang-èl",
        "logentry-newusers-autocreate": "Akun panganggo $1 otomatis {{GENDER:$2|digawé}}",
index a4e13c6..c6021f0 100644 (file)
        "emailconfirmlink": "Confirme o seu endereço de correio eletrónico",
        "invalidemailaddress": "O endereço de correio eletrónico não pode ser aceite porque parece ter um formato inválido.\nIntroduza um endereço formatado corretamente ou deixe o campo vazio.",
        "cannotchangeemail": "Os endereços de correio eletrónico das contas não podem ser alterados nesta wiki.",
-       "emaildisabled": "Este site não consegue enviar mensagens de correio eletrónico.",
+       "emaildisabled": "Este sítio não consegue enviar mensagens de correio eletrónico.",
        "accountcreated": "Conta criada",
        "accountcreatedtext": "A conta de utilizador para [[{{ns:User}}:$1|$1]] ([[{{ns:User talk}}:$1|talk]]) foi criada.",
        "createaccount-title": "Criação de conta na wiki {{SITENAME}}",
        "previewnote": "<strong>Lembre-se de que esta é apenas uma antevisão do resultado.</strong>\nAs modificações ainda não foram gravadas!",
        "continue-editing": "Ir para a área de edição",
        "previewconflict": "Esta antevisão do resultado apresenta o texto da caixa de edição acima tal como este aparecerá se escolher gravá-lo.",
-       "session_fail_preview": "Desculpe! Não foi possível processar a edição devido à perda dos dados da sua sessão.\n\nA sua sessão poderá ter sido encerrada. <strong>Verifique se ainda está autenticado e tente novamente, por favor</strong>. \nCaso continue a não funcionar, tente [[Special:UserLogout|sair]] e voltar a entrar na sua conta, e verifique se o seu navegador permite cookies deste site.",
-       "session_fail_preview_html": "Desculpe! Não foi possível processar a edição devido à perda de dados da sua sessão.\n\n<em>Como a wiki {{SITENAME}} possibilita o uso de HTML puro, a antevisão está oculta por precaução contra ataques com JavaScript.</em>\n\n<strong>Se esta é uma tentativa legítima de edição tente novamente, por favor</strong>. \nCaso continue a não funcionar, tente [[Special:UserLogout|sair]] e voltar a entrar na sua conta, e verifique se o seu navegador permite <em>cookies</em> deste <em>site</em>.",
+       "session_fail_preview": "Desculpe! Não foi possível processar a edição devido à perda dos dados da sua sessão.\n\nA sua sessão poderá ter sido encerrada. <strong>Verifique se ainda está autenticado e tente novamente, por favor</strong>. \nCaso continue a não funcionar, tente [[Special:UserLogout|sair]] e voltar a entrar na sua conta, e verifique se o seu navegador permite cookies deste sítio.",
+       "session_fail_preview_html": "Desculpe! Não foi possível processar a edição devido à perda de dados da sua sessão.\n\n<em>Como a wiki {{SITENAME}} possibilita o uso de HTML puro, a antevisão está oculta por precaução contra ataques com JavaScript.</em>\n\n<strong>Se esta é uma tentativa legítima de edição tente novamente, por favor</strong>. \nCaso continue a não funcionar, tente [[Special:UserLogout|sair]] e voltar a entrar na sua conta, e verifique se o seu navegador permite <em>cookies</em> deste sítio.",
        "token_suffix_mismatch": "<strong>A edição foi rejeitada porque o seu navegador alterou os sinais de pontuação no editor.</strong>\nA edição foi rejeitada para evitar perdas no texto da página.\nIsto acontece ocasionalmente quando se usa um serviço de proxy anonimizador mal configurado.",
        "edit_form_incomplete": "<strong>Algumas partes do formulário de edição não chegaram ao servidor; verifique que a sua edição continua intacta e tente novamente, por favor.</strong>",
        "editing": "A editar $1",
        "showingresultsinrange": "Apresenta-se abaixo {{PLURAL:$1|<strong>1</strong> resultado|até <strong>$1</strong> resultados}} no intervalo #<strong>$2</strong> a #<strong>$3</strong>.",
        "search-showingresults": "{{PLURAL:$4|Resultado <strong>$1</strong> de <strong>$3</strong>|Resultados <strong>$1 - $2</strong> de <strong>$3</strong>}}",
        "search-nonefound": "A pesquisa não produziu resultados.",
-       "search-nonefound-thiswiki": "Não existem resultados que correspondam à consulta neste site.",
+       "search-nonefound-thiswiki": "Não existem resultados que correspondam à consulta neste sítio.",
        "powersearch-legend": "Pesquisa avançada",
        "powersearch-ns": "Pesquisar nos domínios:",
        "powersearch-togglelabel": "Marcar:",
        "prefs-custom-css": "CSS personalizado",
        "prefs-custom-js": "JS personalizado",
        "prefs-common-css-js": "CSS/JS partilhado por todos os temas:",
-       "prefs-reset-intro": "Pode usar esta página para repor as configurações padrão das preferências.\nAs suas preferências serão modificadas para os valores predefinidos do site.\nEsta operação não pode ser desfeita.",
+       "prefs-reset-intro": "Pode usar esta página para repor as configurações padrão das preferências.\nAs suas preferências serão modificadas para os valores predefinidos do sítio.\nEsta operação não pode ser desfeita.",
        "prefs-emailconfirm-label": "Confirmação do correio eletrónico:",
        "youremail": "Correio eletrónico:",
        "username": "Nome de {{GENDER:$1|utilizador|utilizadora|utilizador(a)}}:",
        "http-curl-error": "Ocorreu um erro ao aceder ao URL: $1",
        "http-bad-status": "Ocorreu um problema durante o pedido HTTP: $1 $2",
        "upload-curl-error6": "Não foi possível aceder ao URL",
-       "upload-curl-error6-text": "Não foi possível aceder ao URL.\nVerifique se o endereço está correto e o site disponível, por favor.",
+       "upload-curl-error6-text": "Não foi possível aceder ao URL.\nVerifique se o endereço está correto e o sítio disponível, por favor.",
        "upload-curl-error28": "Tempo limite para o envio do ficheiro excedido",
-       "upload-curl-error28-text": "O site demorou demasiado tempo a responder. Verifique que o site está disponível, aguarde alguns momentos e tente novamente, por favor. Talvez queira voltar a tentar numa altura menos congestionada.",
+       "upload-curl-error28-text": "O sítio demorou demasiado tempo a responder. Verifique que o sítio está disponível, aguarde alguns momentos e tente novamente, por favor. Talvez queira voltar a tentar numa altura menos congestionada.",
        "license": "Licença:",
        "license-header": "Licenciamento",
        "nolicense": "Nenhuma selecionada",
        "apihelp-no-such-module": "Módulo \"$1\" não encontrado.",
        "apisandbox": "Testes da API",
        "apisandbox-jsonly": "Para usar a área de testes da API é necessário o JavaScript.",
-       "apisandbox-api-disabled": "A API está desativada neste site.",
+       "apisandbox-api-disabled": "A API está desativada neste sítio.",
        "apisandbox-intro": "Use esta página para fazer experiências com a <strong>API operacional do MediaWiki</strong>.\nConsulte a [[mw:API:Main page|documentação da API]] para informações sobre o seu uso. Exemplo: [https://www.mediawiki.org/wiki/API#A_simple_example obter o conteúdo da Página Principal]. Selecione uma operação para ver mais exemplos.\n\nNote que, embora esta seja uma área de testes, as operações que executar nesta página podem modificar a wiki.",
        "apisandbox-fullscreen": "Expandir painel",
        "apisandbox-fullscreen-tooltip": "Expandir o painel da página de testes para preencher a janela do navegador.",
        "booksources-invalid-isbn": "O número ISBN fornecido não parece ser válido; verifique a existência de erros ao copiar da fonte original.",
        "magiclink-tracking-rfc": "Páginas que usam hiperligações mágicas RFC",
        "magiclink-tracking-rfc-desc": "Esta página usa hiperligações mágicas RFC. Consulte a [https://www.mediawiki.org/wiki/Special:MyLanguage/Help:Magic_links mediawiki.org] para saber como migrar.",
-       "magiclink-tracking-pmid": "Páginas que usam links mágicos PMID",
+       "magiclink-tracking-pmid": "Páginas que usam hiperligações mágicas PMID",
        "magiclink-tracking-pmid-desc": "Esta página usa hiperligações mágicas PMID. Consulte a [https://www.mediawiki.org/wiki/Special:MyLanguage/Help:Magic_links mediawiki.org] para saber como migrar.",
-       "magiclink-tracking-isbn": "Páginas que usam links mágicos ISBN",
+       "magiclink-tracking-isbn": "Páginas que usam hiperligações mágicas ISBN",
        "magiclink-tracking-isbn-desc": "Esta página usa hiperligações mágicas ISBN. Consulte a [https://www.mediawiki.org/wiki/Special:MyLanguage/Help:Magic_links mediawiki.org] para saber como migrar.",
        "specialloguserlabel": "Executante:",
        "speciallogtitlelabel": "Alvo (título ou página ou {{ns:user}}:nome de utilizador):",
        "import-nonewrevisions": "Não foi importada nenhuma revisão (já estavam todas presentes ou foram ignoradas devido a erros).",
        "xml-error-string": "$1 na linha $2, coluna $3 (byte $4): $5",
        "import-upload": "Enviar dados em XML",
-       "import-token-mismatch": "Perda de dados da sessão.\n\nA sua sessão pode ter sido encerrada. '''Verifique se ainda está autenticado e tente novamente, por favor'''. \nCaso continue a não funcionar, tente [[Special:UserLogout|sair]] e voltar a entrar na sua conta, e verifique se o seu navegador permite cookies deste site.",
+       "import-token-mismatch": "Perda de dados da sessão.\n\nA sua sessão pode ter sido encerrada. '''Verifique se ainda está autenticado e tente novamente, por favor'''. \nCaso continue a não funcionar, tente [[Special:UserLogout|sair]] e voltar a entrar na sua conta, e verifique se o seu navegador permite cookies deste sítio.",
        "import-invalid-interwiki": "Não é possível importar da wiki especificada.",
        "import-error-edit": "A página \"$1\" não foi importada porque não tem permissão para editá-la.",
        "import-error-create": "A página \"$1\" não foi importada porque não tem permissão para criá-la.",
        "creditspage": "Créditos da página",
        "nocredits": "Não há informação disponível sobre os créditos desta página.",
        "spamprotectiontitle": "Filtro de proteção contra spam",
-       "spamprotectiontext": "O texto que pretendia gravar foi bloqueado pelo filtro de spam.\nEste bloqueio foi provavelmente causado por uma hiperligação para um ''site'' externo que está na lista negra.",
+       "spamprotectiontext": "O texto que pretendia gravar foi bloqueado pelo filtro de spam.\nEste bloqueio foi provavelmente causado por uma hiperligação para um sítio externo que está na lista negra.",
        "spamprotectionmatch": "O seguinte texto ativou o filtro de <i>spam</i>: $1",
        "spambot_username": "MediaWiki limpeza de spam",
        "spam_reverting": "A reverter para a última revisão que não contém ligação para $1",
        "invalidateemail": "Cancelar confirmação do correio eletrónico",
        "notificationemail_subject_changed": "O endereço de correio eletrónico registado na wiki {{SITENAME}} foi alterado",
        "notificationemail_subject_removed": "O endereço de correio eletrónico registado na wiki {{SITENAME}} foi removido",
-       "notificationemail_body_changed": "Alguém, provavelmente você, a partir do endereço IP $1, alterou o endereço de correio eletrónico da conta \"$2\" para \"$3\" na wiki {{SITENAME}}.\n\nCaso não o tenha alterado, contacte imediatamente um administrador do site.",
-       "notificationemail_body_removed": "Alguém, provavelmente você, a partir do endereço IP $1, eliminou o endereço de correio eletrónico da conta \"$2\" na wiki {{SITENAME}}.\n\nCaso não o tenha eliminado, contacte imediatamente um administrador do site.",
+       "notificationemail_body_changed": "Alguém, provavelmente você, a partir do endereço IP $1, alterou o endereço de correio eletrónico da conta \"$2\" para \"$3\" na wiki {{SITENAME}}.\n\nCaso não o tenha alterado, contacte imediatamente um administrador do sítio.",
+       "notificationemail_body_removed": "Alguém, provavelmente você, a partir do endereço IP $1, eliminou o endereço de correio eletrónico da conta \"$2\" na wiki {{SITENAME}}.\n\nCaso não o tenha eliminado, contacte imediatamente um administrador do sítio.",
        "scarytranscludedisabled": "[Transclusão interwikis foi impossibilitada]",
        "scarytranscludefailed": "[Não foi possível obter a predefinição a partir de $1]",
        "scarytranscludefailed-httpstatus": "[Não foi possível obter a predefinição a partir de $1: HTTP $2]",
        "permanentlink": "Hiperligação permanente",
        "permanentlink-revid": "Identificador de revisão",
        "permanentlink-submit": "Ir para a revisão",
-       "dberr-problems": "Desculpe! Este site está com dificuldades técnicas.",
+       "dberr-problems": "Desculpe! Este sítio está com dificuldades técnicas.",
        "dberr-again": "Experimente esperar alguns minutos e atualizar.",
        "dberr-info": "(Não foi possível aceder ao servidor da base de dados: $1)",
        "dberr-info-hidden": "(Não foi possível aceder ao servidor da base de dados)",
        "expand_templates_generate_xml": "Mostrar a árvore de análise sintáctica do XML",
        "expand_templates_generate_rawhtml": "Mostrar o HTML puro",
        "expand_templates_preview": "Antevisão do resultado",
-       "expand_templates_preview_fail_html": "<em>Porque a wiki {{SITENAME}} permite código HTML puro e ocorreu uma perda de dados da sessão, a antevisão ficará ocultada como precaução contra ataques por JavaScript.</em>\n\n<strong>Se esta é uma tentativa legítima de visionamento, por favor tente novamente.</strong>\nCaso continue a não funcionar, tente [[Special:UserLogout|sair]] e voltar a entrar na sua conta, e verifique se o seu navegador permite que este site crie ''cookies''.",
+       "expand_templates_preview_fail_html": "<em>Porque a wiki {{SITENAME}} permite código HTML puro e ocorreu uma perda de dados da sessão, a antevisão ficará ocultada como precaução contra ataques por JavaScript.</em>\n\n<strong>Se esta é uma tentativa legítima de visionamento, por favor tente novamente.</strong>\nCaso continue a não funcionar, tente [[Special:UserLogout|sair]] e voltar a entrar na sua conta, e verifique se o seu navegador permite que este sítio crie ''cookies''.",
        "expand_templates_preview_fail_html_anon": "<em>Porque a wiki {{SITENAME}} permite código HTML puro e não iniciou uma sessão, a antevisão ficará ocultada como precaução contra ataques por JavaScript.</em>\n\n<strong>Se esta é uma tentativa legítima de visionamento, por favor [[Special:UserLogin|inicie uma sessão]] e tente novamente.</strong>",
        "expand_templates_input_missing": "Necessita de fornecer pelo menos algum texto wiki de entrada.",
        "pagelanguage": "Alterar a língua da página",
        "rawhtml-notallowed": "As etiquetas &lt;html&gt; não podem ser utilizadas fora de páginas normais.",
        "gotointerwiki": "A sair da wiki {{SITENAME}}",
        "gotointerwiki-invalid": "O título especificado é inválido.",
-       "gotointerwiki-external": "Está prestes a sair da wiki {{SITENAME}} para visitar [[$2]], que é um site externo.\n\n'''[$1 Continuar para $1]'''",
+       "gotointerwiki-external": "Está prestes a sair da wiki {{SITENAME}} para visitar [[$2]], que é um sítio externo.\n\n'''[$1 Continuar para $1]'''",
        "undelete-cantedit": "Não pode restaurar esta página porque não tem privilégios para a editar.",
        "undelete-cantcreate": "Não pode restaurar esta página porque não existe nenhuma página com este nome e não tem privilégios para criar esta página.",
        "pagedata-title": "Dados de página",
index e29bcad..a4f1d64 100644 (file)
        "postedit-confirmation-created": "{{gender}}\nShown after a user creates a new page. Parameters:\n* $1 - the current user, for GENDER support",
        "postedit-confirmation-restored": "{{gender}}\nShown after a user restores a page to a previous revision. Parameters:\n* $1 - the current user, for GENDER support",
        "postedit-confirmation-saved": "{{gender}}\nShown after a user saves a page. Parameters:\n* $1 - the current user, for GENDER support",
+       "postedit-confirmation-published": "{{gender}}\nShown after a user publishes a page. Parameters:\n* $1 - the current user, for GENDER support",
        "edit-already-exists": "Used as error message.\n\nSee also:\n* {{msg-mw|edit-hook-aborted}}\n* {{msg-mw|edit-gone-missing}}\n* {{msg-mw|edit-conflict}}\n* {{msg-mw|edit-no-change}}",
        "addsection-preload": "{{notranslate}}",
        "addsection-editintro": "{{notranslate}}",
index 31abcc0..7bd0919 100644 (file)
        "search-showingresults": "{{PLURAL:$4|نتيجو <strong>$1</strong> of <strong>$3</strong>|نتيجا <strong>$1 - $2</strong> of <strong>$3</strong>}}",
        "search-nonefound": "توھان جي ڳولا جي نتيجي ۾ ڪجھہ بہ نہ لڌو.",
        "powersearch-legend": "اعليٰ ڳولا",
+       "powersearch-ns": "نالن لاءِ ڇڏين وڇوٽين ۾ ڳولھيو (سرچ اِن نيم اسپيسز)",
        "powersearch-togglelabel": "چڪاسيو:",
        "powersearch-toggleall": "سڀ",
        "powersearch-togglenone": "ڪو بہ نہ",
        "nrevisions": "$1 {{PLURAL:$1|مسودو|مسودا}}",
        "nimagelinks": "$1 {{PLURAL:$1|صفحي|صفحن}} ۾ استعمال ٿيل",
        "ntransclusions": "$1 {{PLURAL:$1|صفحي|صفحن}} ۾ استعمال ٿيل",
-       "specialpage-empty": "ھن رپورٽ لاءِ ڪي-بہ نتيجا ناھن.",
+       "specialpage-empty": "ھن رپورٽ لاءِ ڪي بہ نتيجا ناھن.",
        "lonelypages": "يتيم صفحا",
        "uncategorizedpages": "اڻ زمريل صفحا",
        "uncategorizedcategories": "اڻزمرايل زمرا",
        "restriction-level-sysop": "مڪمل طور تحفظيل",
        "restriction-level-autoconfirmed": "نيم تحفظيل",
        "viewdeletedpage": "ڊاٺل صفحا ڏسو",
-       "undelete-nodiff": "ڪوبہ پويون مسودو نہ لڌو",
+       "undelete-nodiff": "ڪوبہ اڳيون مسودو نہ لڌو",
        "undeletebtn": "بحاليو",
        "undeleteviewlink": "ڏسو",
        "undeletecomment": "سبب:",
        "version-libraries-description": "تشريح",
        "version-libraries-authors": "ليکڪ",
        "redirect-submit": "ھلو",
+       "redirect-lookup": "ڏسو:",
        "redirect-value": "قدر:",
        "redirect-user": "واپرائيندڙ آءِڊي",
        "redirect-page": "صفحي جي آءِڊي",
index 05a1229..6d07338 100644 (file)
        "lockmanager-fail-closelock": "Ne morem zapreti zaklenitvene datoteke »$1«.",
        "lockmanager-fail-deletelock": "Ne morem izbrisati zaklenitvene datoteke »$1«.",
        "lockmanager-fail-acquirelock": "Ne morem pridobiti zaklenitvene datoteke »$1«.",
-       "lockmanager-fail-openlock": "Ne morem odpreti zaklenitvene datoteke »$1«.",
+       "lockmanager-fail-openlock": "Ne morem odpreti zaklenitvene datoteke »$1«. Prepričajte se, da je mapa za nalaganje nastavljena pravilno in da ima vaš spletni strežnik pravice za pisanje v tej mapi. Oglejte si https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:$wgUploadDirectory za več informacij.",
        "lockmanager-fail-releaselock": "Ne morem sprostiti zaklepa »$1«.",
        "lockmanager-fail-db-bucket": "Ne morem kontaktirati zadostnega števila zaklenitvenih zbirk podatkov v vedru $1.",
        "lockmanager-fail-db-release": "Ne morem sprostiti zaklepov zbirke podatkov $1.",
index 5a16641..2142f1f 100644 (file)
@@ -1508,6 +1508,7 @@ return [
                        'postedit-confirmation-created',
                        'postedit-confirmation-restored',
                        'postedit-confirmation-saved',
+                       'postedit-confirmation-published',
                ],
        ],
        'mediawiki.action.view.redirect' => [
index 3774cd2..394b42f 100644 (file)
                                        // Return [start, end] instead of just start
                                        startAndEnd: false
                                }, options );
-                               // FIXME: We may not need character position-based functions if we insert markers in the right places
                                break;
                        case 'setSelection':
                                options = $.extend( {
                                if ( options.end === undefined ) {
                                        options.end = options.start;
                                }
-                               // FIXME: We may not need character position-based functions if we insert markers in the right places
                                break;
                        case 'scrollToCaretPosition':
                                options = $.extend( {
index e0ab45a..5e859ac 100644 (file)
                data = data || {};
 
                if ( data.message === undefined ) {
-                       data.message = $.parseHTML( mw.message( 'postedit-confirmation-saved', data.user || mw.user ).escaped() );
+                       data.message = $.parseHTML( mw.message(
+                               mw.config.get( 'wgEditSubmitButtonLabelPublish' ) ?
+                                       'postedit-confirmation-published' :
+                                       'postedit-confirmation-saved',
+                               data.user || mw.user
+                       ).escaped() );
                }
 
                $content = $( '<div>' ).addClass( 'postedit-icon postedit-icon-checkmark postedit-content' );
index bfd5c06..ca4d239 100644 (file)
@@ -57,6 +57,7 @@
                this.feedbackPageTitle = config.title || new mw.Title( 'Feedback' );
 
                this.messagePosterPromise = mw.messagePoster.factory.create( this.feedbackPageTitle, config.apiUrl );
+               this.foreignApi = config.apiUrl ? new mw.ForeignApi( config.apiUrl ) : null;
 
                // Links
                this.bugsTaskSubmissionLink = config.bugsLink || '//phabricator.wikimedia.org/maniphest/task/edit/form/1/';
         * Respond to dialog submit event. If the information was
         * submitted successfully, open a MessageDialog to thank the user.
         *
-        * @param {string} [status] A status of the end of operation
+        * @param {string} status A status of the end of operation
         *  of the main feedback dialog. Empty if the dialog was
         *  dismissed with no action or the user followed the button
         *  to the external task reporting site.
+        * @param {string} feedbackPageName
+        * @param {string} feedbackPageUrl
         */
-       mw.Feedback.prototype.onDialogSubmit = function ( status ) {
+       mw.Feedback.prototype.onDialogSubmit = function ( status, feedbackPageName, feedbackPageUrl ) {
                var dialogConfig;
 
                if ( status !== 'submitted' ) {
                        title: mw.msg( 'feedback-thanks-title' ),
                        message: $( '<span>' ).msg(
                                'feedback-thanks',
-                               this.feedbackPageTitle.getNameText(),
+                               feedbackPageName,
                                $( '<a>' ).attr( {
                                        target: '_blank',
-                                       href: this.feedbackPageTitle.getUrl()
+                                       href: feedbackPageUrl
                                } )
                        ),
                        actions: [
                        this.constructor.static.dialog,
                        {
                                title: mw.msg( this.dialogTitleMessageKey ),
+                               foreignApi: this.foreignApi,
                                settings: {
                                        messagePosterPromise: this.messagePosterPromise,
                                        title: this.feedbackPageTitle,
         */
        mw.Feedback.Dialog.prototype.getSetupProcess = function ( data ) {
                return mw.Feedback.Dialog.parent.prototype.getSetupProcess.call( this, data )
+                       .next( function () {
+                               // Get the URL of the target page, we want to use that in links in the intro
+                               // and in the success dialog
+                               var dialog = this;
+                               if ( data.foreignApi ) {
+                                       return data.foreignApi.get( {
+                                               action: 'query',
+                                               prop: 'info',
+                                               inprop: 'url',
+                                               formatversion: 2,
+                                               titles: data.settings.title.getPrefixedText()
+                                       } ).then( function ( data ) {
+                                               dialog.feedbackPageUrl = OO.getProp( data, 'query', 'pages', 0, 'canonicalurl' );
+                                       } );
+                               } else {
+                                       this.feedbackPageUrl = data.settings.title.getUrl();
+                               }
+                       }, this )
                        .next( function () {
                                var plainMsg, parsedMsg,
                                        settings = data.settings;
                                this.setBugReportLink( settings.bugsTaskSubmissionLink );
                                this.feedbackPageTitle = settings.title;
                                this.feedbackPageName = settings.title.getNameText();
-                               this.feedbackPageUrl = settings.title.getUrl();
 
                                // Useragent checkbox
                                if ( settings.useragentCheckbox.show ) {
index 7f42254..f9e2cc1 100644 (file)
@@ -5,7 +5,6 @@ use MediaWiki\MediaWikiServices;
 /**
  * @group Database
  */
-
 class LinkerTest extends MediaWikiLangTestCase {
 
        /**
index d1b9157..8185670 100644 (file)
@@ -22,7 +22,6 @@ use TestUserRegistry;
 use Title;
 use WANObjectCache;
 use Wikimedia\Rdbms\Database;
-use Wikimedia\Rdbms\DatabaseDomain;
 use Wikimedia\Rdbms\DatabaseSqlite;
 use Wikimedia\Rdbms\FakeResultWrapper;
 use Wikimedia\Rdbms\LoadBalancer;
@@ -41,12 +40,7 @@ class RevisionStoreDbTest extends MediaWikiTestCase {
        private function getLoadBalancerMock( array $server ) {
                $lb = $this->getMockBuilder( LoadBalancer::class )
                        ->setMethods( [ 'reallyOpenConnection' ] )
-                       ->setConstructorArgs( [ [
-                               'servers' => [ $server ],
-                               'localDomain' => new DatabaseDomain(
-                                       $server['dbname'], null, $server['tablePrefix']
-                               ),
-                       ] ] )
+                       ->setConstructorArgs( [ [ 'servers' => [ $server ] ] ] )
                        ->getMock();
 
                $lb->method( 'reallyOpenConnection' )->willReturnCallback(
index 227dd87..dc2e9ae 100644 (file)
@@ -3,7 +3,6 @@
 /**
  * @covers WikiReference
  */
-
 class WikiReferenceTest extends PHPUnit_Framework_TestCase {
 
        use MediaWikiCoversValidator;
index d19d998..fa9898d 100644 (file)
@@ -174,7 +174,7 @@ class DatabaseTestHelper extends Database {
                return false;
        }
 
-       function affectedRows() {
+       function fetchAffectedRowCount() {
                return -1;
        }
 
index bd1412e..2811a9c 100644 (file)
@@ -6,7 +6,6 @@
  * @group Database
  * @group Installer
  */
-
 class OracleInstallerTest extends MediaWikiTestCase {
 
        /**
index 76b4ee1..8831265 100644 (file)
@@ -4,7 +4,6 @@
  *
  * @group Database
  */
-
 class ArrayUtilsTest extends PHPUnit_Framework_TestCase {
 
        use MediaWikiCoversValidator;
index 8a120ea..a36b259 100644 (file)
@@ -8,7 +8,6 @@
  * @todo Test methods in this call should be split into a method and a
  * dataprovider.
  */
-
 class IPTest extends PHPUnit_Framework_TestCase {
 
        use MediaWikiCoversValidator;
index a23a2a0..caf1281 100644 (file)
@@ -53,6 +53,9 @@ class FakeDatabaseMysqlBase extends DatabaseMysqlBase {
        protected function doQuery( $sql ) {
        }
 
+       protected function fetchAffectedRowCount() {
+       }
+
        // From DatabaseMysqli
        protected function mysqlConnect( $realServer ) {
        }
index 23f7865..d8ebeff 100644 (file)
@@ -560,7 +560,7 @@ class DatabaseSQLTest extends PHPUnit_Framework_TestCase {
                                        'rows' => [ 'field' => 'text', 'field2' => 'text2' ],
                                ],
                                "DELETE FROM replace_table " .
-                                       "WHERE ( field='text' ); " .
+                                       "WHERE (field = 'text'); " .
                                        "INSERT INTO replace_table " .
                                        "(field,field2) " .
                                        "VALUES ('text','text2')"
@@ -576,7 +576,7 @@ class DatabaseSQLTest extends PHPUnit_Framework_TestCase {
                                        ],
                                ],
                                "DELETE FROM module_deps " .
-                                       "WHERE ( md_module='module' AND md_skin='skin' ); " .
+                                       "WHERE (md_module = 'module' AND md_skin = 'skin'); " .
                                        "INSERT INTO module_deps " .
                                        "(md_module,md_skin,md_deps) " .
                                        "VALUES ('module','skin','deps')"
@@ -598,12 +598,12 @@ class DatabaseSQLTest extends PHPUnit_Framework_TestCase {
                                        ],
                                ],
                                "DELETE FROM module_deps " .
-                                       "WHERE ( md_module='module' AND md_skin='skin' ); " .
+                                       "WHERE (md_module = 'module' AND md_skin = 'skin'); " .
                                        "INSERT INTO module_deps " .
                                        "(md_module,md_skin,md_deps) " .
                                        "VALUES ('module','skin','deps'); " .
                                        "DELETE FROM module_deps " .
-                                       "WHERE ( md_module='module2' AND md_skin='skin2' ); " .
+                                       "WHERE (md_module = 'module2' AND md_skin = 'skin2'); " .
                                        "INSERT INTO module_deps " .
                                        "(md_module,md_skin,md_deps) " .
                                        "VALUES ('module2','skin2','deps2')"
@@ -625,12 +625,12 @@ class DatabaseSQLTest extends PHPUnit_Framework_TestCase {
                                        ],
                                ],
                                "DELETE FROM module_deps " .
-                                       "WHERE ( md_module='module' ) OR ( md_skin='skin' ); " .
+                                       "WHERE (md_module = 'module') OR (md_skin = 'skin'); " .
                                        "INSERT INTO module_deps " .
                                        "(md_module,md_skin,md_deps) " .
                                        "VALUES ('module','skin','deps'); " .
                                        "DELETE FROM module_deps " .
-                                       "WHERE ( md_module='module2' ) OR ( md_skin='skin2' ); " .
+                                       "WHERE (md_module = 'module2') OR (md_skin = 'skin2'); " .
                                        "INSERT INTO module_deps " .
                                        "(md_module,md_skin,md_deps) " .
                                        "VALUES ('module2','skin2','deps2')"
index 4a0a7e7..e131506 100644 (file)
@@ -322,7 +322,7 @@ class DatabaseTest extends PHPUnit_Framework_TestCase {
         */
        private function getMockDB( $methods = [] ) {
                static $abstractMethods = [
-                       'affectedRows',
+                       'fetchAffectedRowCount',
                        'closeConnection',
                        'dataSeek',
                        'doQuery',
index 88f58cf..e460960 100644 (file)
@@ -2,6 +2,7 @@
 
 namespace MediaWiki\Session;
 
+use Config;
 use MediaWikiTestCase;
 use User;
 use Wikimedia\TestingAccessWrapper;
@@ -14,9 +15,16 @@ use Wikimedia\TestingAccessWrapper;
 class SessionBackendTest extends MediaWikiTestCase {
        const SESSIONID = 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa';
 
+       /** @var SessionManager */
        protected $manager;
+
+       /** @var Config */
        protected $config;
+
+       /** @var SessionProvider */
        protected $provider;
+
+       /** @var TestBagOStuff */
        protected $store;
 
        protected $onSessionMetadataCalled = false;
@@ -25,6 +33,7 @@ class SessionBackendTest extends MediaWikiTestCase {
         * Returns a non-persistent backend that thinks it has at least one session active
         * @param User|null $user
         * @param string $id
+        * @return SessionBackend
         */
        protected function getBackend( User $user = null, $id = null ) {
                if ( !$this->config ) {
@@ -149,7 +158,7 @@ class SessionBackendTest extends MediaWikiTestCase {
                $this->assertSame( $info->forceHTTPS(), $backend->shouldForceHTTPS() );
 
                $expire = time() + 100;
-               $this->store->setSessionMeta( self::SESSIONID, [ 'expires' => $expire ], 2 );
+               $this->store->setSessionMeta( self::SESSIONID, [ 'expires' => $expire ] );
 
                $info = new SessionInfo( SessionInfo::MIN_PRIORITY, [
                        'provider' => $this->provider,
index 6c989f3..e042f76 100644 (file)
@@ -14,7 +14,14 @@ use Wikimedia\TestingAccessWrapper;
  */
 class SessionManagerTest extends MediaWikiTestCase {
 
-       protected $config, $logger, $store;
+       /** @var \HashConfig */
+       private $config;
+
+       /** @var \TestLogger */
+       private $logger;
+
+       /** @var TestBagOStuff */
+       private $store;
 
        protected function getManager() {
                \ObjectCache::$instances['testSessionStore'] = new TestBagOStuff();
index bac2088..f9e30f0 100644 (file)
@@ -14,53 +14,44 @@ class TestBagOStuff extends \CachedBagOStuff {
        /**
         * @param string $id Session ID
         * @param array $data Session data
-        * @param int $expiry
-        * @param User $user User for metadata
         */
-       public function setSessionData( $id, array $data, $expiry = 0, User $user = null ) {
-               $this->setSession( $id, [ 'data' => $data ], $expiry, $user );
+       public function setSessionData( $id, array $data ) {
+               $this->setSession( $id, [ 'data' => $data ] );
        }
 
        /**
         * @param string $id Session ID
         * @param array $metadata Session metadata
-        * @param int $expiry
         */
-       public function setSessionMeta( $id, array $metadata, $expiry = 0 ) {
-               $this->setSession( $id, [ 'metadata' => $metadata ], $expiry );
+       public function setSessionMeta( $id, array $metadata ) {
+               $this->setSession( $id, [ 'metadata' => $metadata ] );
        }
 
        /**
         * @param string $id Session ID
         * @param array $blob Session metadata and data
-        * @param int $expiry
-        * @param User $user User for metadata
         */
-       public function setSession( $id, array $blob, $expiry = 0, User $user = null ) {
+       public function setSession( $id, array $blob ) {
                $blob += [
                        'data' => [],
                        'metadata' => [],
                ];
                $blob['metadata'] += [
-                       'userId' => $user ? $user->getId() : 0,
-                       'userName' => $user ? $user->getName() : null,
-                       'userToken' => $user ? $user->getToken( true ) : null,
+                       'userId' => 0,
+                       'userName' => null,
+                       'userToken' => null,
                        'provider' => 'DummySessionProvider',
                ];
 
-               $this->setRawSession( $id, $blob, $expiry, $user );
+               $this->setRawSession( $id, $blob );
        }
 
        /**
         * @param string $id Session ID
         * @param array|mixed $blob Session metadata and data
-        * @param int $expiry
         */
-       public function setRawSession( $id, $blob, $expiry = 0 ) {
-               if ( $expiry <= 0 ) {
-                       $expiry = \RequestContext::getMain()->getConfig()->get( 'ObjectCacheSessionExpiry' );
-               }
-
+       public function setRawSession( $id, $blob ) {
+               $expiry = \RequestContext::getMain()->getConfig()->get( 'ObjectCacheSessionExpiry' );
                $this->set( $this->makeKey( 'MWSession', $id ), $blob, $expiry );
        }
 
index 5b3fbfa..06b0667 100644 (file)
@@ -7,7 +7,6 @@
  *
  * @author Bene* < benestar.wikimedia@gmail.com >
  */
-
 class SkinTemplateTest extends MediaWikiTestCase {
        /**
         * @dataProvider makeListItemProvider
index 22bdefd..10c6d04 100644 (file)
@@ -8,7 +8,6 @@
  *
  * @group Database
  */
-
 class ImageListPagerTest extends MediaWikiTestCase {
        /**
         * @expectedException MWException