Merge "objectcache: Forward MultiWriteBagOStuff::makeKey to primary backend"
authorjenkins-bot <jenkins-bot@gerrit.wikimedia.org>
Thu, 15 Jun 2017 02:45:08 +0000 (02:45 +0000)
committerGerrit Code Review <gerrit@wikimedia.org>
Thu, 15 Jun 2017 02:45:08 +0000 (02:45 +0000)
65 files changed:
RELEASE-NOTES-1.30
autoload.php
includes/DefaultSettings.php
includes/Sanitizer.php
includes/actions/Action.php
includes/api/i18n/qqq.json
includes/changes/ChangesList.php
includes/context/ContextSource.php
includes/context/DerivativeContext.php
includes/context/IContextSource.php
includes/context/RequestContext.php
includes/installer/WebInstallerLanguage.php
includes/installer/i18n/lij.json
includes/resourceloader/ResourceLoaderContext.php
includes/specialpage/ChangesListSpecialPage.php
includes/specialpage/SpecialPage.php
includes/specials/SpecialRecentchanges.php
languages/Language.php
languages/LanguageConverter.php
languages/MessageLocalizer.php [new file with mode: 0644]
languages/classes/LanguageEn.php [new file with mode: 0644]
languages/data/Names.php
languages/i18n/atj.json
languages/i18n/be-tarask.json
languages/i18n/be.json
languages/i18n/bg.json
languages/i18n/bn.json
languages/i18n/br.json
languages/i18n/bs.json
languages/i18n/en.json
languages/i18n/glk.json
languages/i18n/id.json
languages/i18n/ja.json
languages/i18n/jv.json
languages/i18n/mr.json
languages/i18n/my.json
languages/i18n/nn.json
languages/i18n/pt.json
languages/i18n/qqq.json
languages/i18n/sv.json
languages/i18n/tcy.json
languages/i18n/uk.json
languages/i18n/yi.json
resources/Resources.php
resources/src/mediawiki.rcfilters/dm/mw.rcfilters.dm.FilterGroup.js
resources/src/mediawiki.rcfilters/dm/mw.rcfilters.dm.FiltersViewModel.js
resources/src/mediawiki.rcfilters/dm/mw.rcfilters.dm.ItemModel.js
resources/src/mediawiki.rcfilters/mw.rcfilters.Controller.js
resources/src/mediawiki.rcfilters/mw.rcfilters.UriProcessor.js [new file with mode: 0644]
resources/src/mediawiki.rcfilters/mw.rcfilters.init.js
resources/src/mediawiki.rcfilters/styles/mw.rcfilters.ui.FilterMenuHeaderWidget.less
resources/src/mediawiki.rcfilters/styles/mw.rcfilters.ui.FilterWrapperWidget.less
resources/src/mediawiki.rcfilters/styles/mw.rcfilters.ui.ItemMenuOptionWidget.less
resources/src/mediawiki.rcfilters/ui/mw.rcfilters.ui.FilterMenuHeaderWidget.js
resources/src/mediawiki.rcfilters/ui/mw.rcfilters.ui.FilterTagMultiselectWidget.js
resources/src/mediawiki.rcfilters/ui/mw.rcfilters.ui.FilterWrapperWidget.js
resources/src/mediawiki.rcfilters/ui/mw.rcfilters.ui.FormWrapperWidget.js
resources/src/mediawiki.rcfilters/ui/mw.rcfilters.ui.ItemMenuOptionWidget.js
resources/src/mediawiki.rcfilters/ui/mw.rcfilters.ui.MenuSelectWidget.js
resources/src/mediawiki.rcfilters/ui/mw.rcfilters.ui.TagItemWidget.js
tests/phpunit/includes/auth/AuthManagerTest.php
tests/phpunit/languages/LanguageTest.php
tests/qunit/QUnitTestResources.php
tests/qunit/suites/resources/mediawiki.rcfilters/UriProcessor.test.js [new file with mode: 0644]
tests/qunit/suites/resources/mediawiki.rcfilters/dm.FiltersViewModel.test.js

index f2cb871..0f5cb47 100644 (file)
@@ -27,6 +27,7 @@ production.
   ParserOptions would pollute the parser cache. Callers should use
   WikiPage::makeParserOptions() to create the ParserOptions object and only
   change options that affect the parser cache key.
+* (T45547) $wgUsePigLatinVariant added (off by default).
 
 === New features in 1.30 ===
 * (T37247) Output from Parser::parse() will now be wrapped in a div with
@@ -36,6 +37,10 @@ production.
   specific tags to be added by users.
 * Added a 'ParserOptionsRegister' hook to allow extensions to register
   additional parser options.
+* (T45547) Included Pig Latin, a language game in English, as a
+  LanguageConverter variant.  This allows English-speaking developers
+  to develop and test LanguageConverter more easily.  Pig Latin can be
+  enabled by setting $wgUsePigLatinVariant to true.
 
 === Languages updated in 1.30 ===
 
@@ -76,6 +81,11 @@ changes to languages because of Phabricator reports.
 
 * …
 
+==== Pig Latin added ====
+* (T45547) Added Pig Latin, a made-up English variant (en-x-piglatin),
+  for easier variant development and testing. Disabled by default. It can be
+  enabled by setting $wgUsePigLatinVariant to true.
+
 === Other changes in 1.30 ===
 * The use of an associative array for $wgProxyList, where the IP address is in
   the key instead of the value, is deprecated (e.g. [ '127.0.0.1' => 'value' ]).
index 6c5aff5..293bf6a 100644 (file)
@@ -426,6 +426,7 @@ $wgAutoloadLocalClasses = [
        'EmailNotification' => __DIR__ . '/includes/mail/EmailNotification.php',
        'EmaillingJob' => __DIR__ . '/includes/jobqueue/jobs/EmaillingJob.php',
        'EmptyBagOStuff' => __DIR__ . '/includes/libs/objectcache/EmptyBagOStuff.php',
+       'EnConverter' => __DIR__ . '/languages/classes/LanguageEn.php',
        'EncryptedPassword' => __DIR__ . '/includes/password/EncryptedPassword.php',
        'EnhancedChangesList' => __DIR__ . '/includes/changes/EnhancedChangesList.php',
        'EnotifNotifyJob' => __DIR__ . '/includes/jobqueue/jobs/EnotifNotifyJob.php',
@@ -701,6 +702,7 @@ $wgAutoloadLocalClasses = [
        'LanguageConverter' => __DIR__ . '/languages/LanguageConverter.php',
        'LanguageCu' => __DIR__ . '/languages/classes/LanguageCu.php',
        'LanguageDsb' => __DIR__ . '/languages/classes/LanguageDsb.php',
+       'LanguageEn' => __DIR__ . '/languages/classes/LanguageEn.php',
        'LanguageEs' => __DIR__ . '/languages/classes/LanguageEs.php',
        'LanguageEt' => __DIR__ . '/languages/classes/LanguageEt.php',
        'LanguageFi' => __DIR__ . '/languages/classes/LanguageFi.php',
@@ -979,6 +981,7 @@ $wgAutoloadLocalClasses = [
        'MessageBlobStore' => __DIR__ . '/includes/cache/MessageBlobStore.php',
        'MessageCache' => __DIR__ . '/includes/cache/MessageCache.php',
        'MessageContent' => __DIR__ . '/includes/content/MessageContent.php',
+       'MessageLocalizer' => __DIR__ . '/languages/MessageLocalizer.php',
        'MessageSpecifier' => __DIR__ . '/includes/libs/MessageSpecifier.php',
        'MigrateFileRepoLayout' => __DIR__ . '/maintenance/migrateFileRepoLayout.php',
        'MigrateUserGroup' => __DIR__ . '/maintenance/migrateUserGroup.php',
index 9436aa6..48414b7 100644 (file)
@@ -3056,6 +3056,12 @@ $wgDisableTitleConversion = false;
  */
 $wgDefaultLanguageVariant = false;
 
+/**
+ * Whether to enable the pig latin variant of English (en-x-piglatin),
+ * used to ease variant development work.
+ */
+$wgUsePigLatinVariant = false;
+
 /**
  * Disabled variants array of language variant conversion.
  *
@@ -6767,6 +6773,12 @@ $wgUseRCPatrol = true;
  */
 $wgStructuredChangeFiltersEnableSaving = true;
 
+/**
+ * Whether to show the new experimental views (like namespaces, tags, and users) in
+ * RecentChanges filters
+ */
+$wgStructuredChangeFiltersEnableExperimentalViews = false;
+
 /**
  * Use new page patrolling to check new pages on Special:Newpages
  */
index 5aaa3ed..8920e92 100644 (file)
@@ -1207,7 +1207,7 @@ class Sanitizer {
                ];
 
                $id = urlencode( strtr( $id, ' ', '_' ) );
-               $id = str_replace( array_keys( $replace ), array_values( $replace ), $id );
+               $id = strtr( $id, $replace );
 
                if ( !preg_match( '/^[a-zA-Z]/', $id ) && !in_array( 'noninitial', $options ) ) {
                        // Initial character must be a letter!
index f06f828..844a0d6 100644 (file)
@@ -34,7 +34,7 @@
  * format (protect, delete, move, etc), and the just-do-something format (watch, rollback,
  * patrol, etc). The FormAction and FormlessAction classes represent these two groups.
  */
-abstract class Action {
+abstract class Action implements MessageLocalizer {
 
        /**
         * Page on which we're performing the action
@@ -253,7 +253,7 @@ abstract class Action {
         *
         * @return Message
         */
-       final public function msg() {
+       final public function msg( $key ) {
                $params = func_get_args();
                return call_user_func_array( [ $this->getContext(), 'msg' ], $params );
        }
index c5fb799..2f6041c 100644 (file)
        "apihelp-xmlfm-description": "{{doc-apihelp-description|xmlfm|seealso=* {{msg-mw|apihelp-xml-description}}}}",
        "api-format-title": "{{technical}}\nPage title when API output is pretty-printed in HTML.",
        "api-format-prettyprint-header": "{{technical}} Displayed as a header when API output is pretty-printed in HTML, but a post request is received.\n\nParameters:\n* $1 - Format name\n* $2 - Non-pretty-printing module name",
-       "api-format-prettyprint-header-hyperlinked": "{{technical}} Displayed as a header when API output is pretty-printed in HTML.\n\nParameters:\n* $1 - Format name\n* $2 - Non-pretty-printing module name\n* $3 - URL to Non-pretty-printing module",
        "api-format-prettyprint-header-only-html": "{{technical}} Displayed as a header when API output is pretty-printed in HTML, but there is no non-html module.\n\nParameters:\n* $1 - Format name",
+       "api-format-prettyprint-header-hyperlinked": "{{technical}} Displayed as a header when API output is pretty-printed in HTML.\n\nParameters:\n* $1 - Format name\n* $2 - Non-pretty-printing module name\n* $3 - URL to Non-pretty-printing module",
        "api-format-prettyprint-status": "{{technical}} Displayed as a header when API pretty-printed output is used for a response that uses an unusual HTTP status code.\n\nParameters:\n* $1 - HTTP status code (integer)\n* $2 - Standard English text for the status code.",
        "api-login-fail-aborted": "{{technical}} Displayed as an error when API login fails due to AuthManager requiring user interaction.\n\nSee also:\n* {{msg-mw|api-login-fail-aborted-nobotpw}}",
        "api-login-fail-aborted-nobotpw": "{{technical}} Displayed as an error when API login fails due to AuthManager requiring user interaction. Used when BotPasswords is disabled.\n\nSee also:\n* {{msg-mw|api-login-fail-aborted}}",
index 00d842f..5aa693d 100644 (file)
@@ -177,6 +177,8 @@ class ChangesList extends ContextSource {
                } else {
                        $classes[] = Sanitizer::escapeClass( self::CSS_CLASS_PREFIX . 'ns' .
                                $rc->mAttribs['rc_namespace'] . '-' . $rc->mAttribs['rc_title'] );
+                       $classes[] = Sanitizer::escapeClass( self::CSS_CLASS_PREFIX . 'ns-' .
+                               $rc->mAttribs['rc_namespace'] );
                }
 
                // Indicate watched status on the line to allow for more
index 2264670..36d6df2 100644 (file)
@@ -181,10 +181,12 @@ abstract class ContextSource implements IContextSource {
         * Parameters are the same as wfMessage()
         *
         * @since 1.18
+        * @param string|string[]|MessageSpecifier $key Message key, or array of keys,
+        *   or a MessageSpecifier.
         * @param mixed ...
         * @return Message
         */
-       public function msg( /* $args */ ) {
+       public function msg( $key /* $args */ ) {
                $args = func_get_args();
 
                return call_user_func_array( [ $this->getContext(), 'msg' ], $args );
index 2939510..9c3c42a 100644 (file)
@@ -324,10 +324,12 @@ class DerivativeContext extends ContextSource implements MutableContext {
         * it would set only the original context, and not take
         * into account any changes.
         *
+        * @param string|string[]|MessageSpecifier $key Message key, or array of keys,
+        *   or a MessageSpecifier.
         * @param mixed $args,... Arguments to wfMessage
         * @return Message
         */
-       public function msg() {
+       public function msg( $key ) {
                $args = func_get_args();
 
                return call_user_func_array( 'wfMessage', $args )->setContext( $this );
index 8e9fc6f..d13e1a5 100644 (file)
@@ -52,7 +52,7 @@ use Liuggio\StatsdClient\Factory\StatsdDataFactory;
  * belong here either. Session state changes should only be propagated on
  * shutdown by separate persistence handler objects, for example.
  */
-interface IContextSource {
+interface IContextSource extends MessageLocalizer {
        /**
         * Get the WebRequest object
         *
@@ -143,14 +143,6 @@ interface IContextSource {
         */
        public function getTiming();
 
-       /**
-        * Get a Message object with context set.  See wfMessage for parameters.
-        *
-        * @param mixed ...
-        * @return Message
-        */
-       public function msg();
-
        /**
         * Export the resolved user IP, HTTP headers, user ID, and session ID.
         * The result will be reasonably sized to allow for serialization.
index 0e1de50..2cabfe1 100644 (file)
@@ -449,10 +449,12 @@ class RequestContext implements IContextSource, MutableContext {
         * Get a Message object with context set
         * Parameters are the same as wfMessage()
         *
+        * @param string|string[]|MessageSpecifier $key Message key, or array of keys,
+        *   or a MessageSpecifier.
         * @param mixed ...
         * @return Message
         */
-       public function msg() {
+       public function msg( $key ) {
                $args = func_get_args();
 
                return call_user_func_array( 'wfMessage', $args )->setContext( $this );
index cfd4a86..bce07d3 100644 (file)
@@ -98,17 +98,19 @@ class WebInstallerLanguage extends WebInstallerPage {
         * @return string
         */
        public function getLanguageSelector( $name, $label, $selectedCode, $helpHtml = '' ) {
-               global $wgDummyLanguageCodes;
+               global $wgExtraLanguageCodes;
 
                $output = $helpHtml;
 
                $select = new XmlSelect( $name, $name, $selectedCode );
                $select->setAttribute( 'tabindex', $this->parent->nextTabIndex() );
 
+               $unwantedLanguageCodes = $wgExtraLanguageCodes +
+                       LanguageCode::getDeprecatedCodeMapping();
                $languages = Language::fetchLanguageNames();
                ksort( $languages );
                foreach ( $languages as $code => $lang ) {
-                       if ( isset( $wgDummyLanguageCodes[$code] ) ) {
+                       if ( isset( $unwantedLanguageCodes[$code] ) ) {
                                continue;
                        }
                        $select->addOption( "$code - $lang", $code );
index ba39bc7..b9ccdd3 100644 (file)
        "config-mysql-charset": "Set di caratteri do database:",
        "config-mysql-binary": "Binaio",
        "config-mysql-utf8": "UTF-8",
+       "config-mysql-charset-help": "In <strong>modalitæ binaia</strong>, MediaWiki a l'archivvia o testo UTF-8 into database in campi binai.\nQuest'o l'è ciu efficaçe che a modalitæ UTF-8 do MySQL, e o consente de doeuviâ a gamma completa de caratteri Unicode.\n\nIn <strong>modalitæ UTF-8</strong>, MySQL o saviâ inte quæ set de caratteri l'è che son i to dæti, e o poriâ presentâli e convertîli in moddo apropiou, ma o no te permetiâ de memorizâ i caratteri de d'ato a-o [https://en.wikipedia.org/wiki/Mapping_of_Unicode_character_planes Cian de base murtilenguistego].",
        "config-mssql-auth": "Tipo d'aotenticaçion:",
        "config-mssql-install-auth": "Seleçion-a o tipo d'aotenticaçion ch'o saiâ doeuviou pe conettise a-o database durante o processo de instalaçion.\nSe ti seleçion-i \"{{int:config-mssql-windowsauth}}\", saiâ doeuviou e credençiæ de quæ se segge utente segge aproeuv'a fâ giâ o serviou web.",
        "config-mssql-web-auth": "Seleçion-a o tipo d'aotenticaçion che o serviou web o doeuviâ pe conettise a-o database. \nSe ti seleçion-i \"{{int:config-mssql-windowsauth}}\", saiâ doeuviou e credençiæ de quæ se segge utente segge aproeuv'a fâ giâ o serviou web.",
        "config-admin-error-password": "Erô interno durante l'impostaçion de 'na password pe aministratô \"<nowiki>$1</nowiki>\": <pre>$2</pre>",
        "config-admin-error-bademail": "T'hæ inseio un adresso e-mail non vallido.",
        "config-subscribe": "Sottoscrivi a [https://lists.wikimedia.org/mailman/listinfo/mediawiki-announce mailing list di anonçi de release].",
-       "config-subscribe-help": "Se tratta de 'na mailing list a basso traffego dedicâ a-i anonçi de sciortie de noeuve verscioin, compreize de importante segnalaçioin pe-a segueçça.\nSe conseggia de inscrivise e agiornâ a proppia instalaçion de MediaWiki quande sciorte 'na noeuva verscion."
+       "config-subscribe-help": "Se tratta de 'na mailing list a basso traffego dedicâ a-i anonçi de sciortie de noeuve verscioin, compreize de importante segnalaçioin pe-a segueçça.\nSe conseggia de inscrivise e agiornâ a proppia instalaçion de MediaWiki quande sciorte 'na noeuva verscion.",
+       "config-subscribe-noemail": "T'hæ provou a inscrivite a-a mailing list dedicâ a-i anonçi de noeuve verscioin sença fornî un adresso e-mail.\nInseisci un adresso e-mail se ti dexidei efetoâ l'inscriçion a-a mailing list.",
+       "config-pingback": "Condividdi i dæti insce questa installaçion co-i svilupatoî da MediaWiki.",
+       "config-pingback-help": "Se ti seleçion-i questa opçion, MediaWiki a contattiâ periodicamente https://www.mediawiki.org co-i dæti base insce questa instançia MediaWiki. Queta categoria de dæti a l'includde, prexempio, o tipo de scistema, a verscion de PHP e o database de backend çernuo. A Wikimedia Foundation a condividde questi dæti co-i sviluppatoî Mediawiki pe agiutâla a guidâ i futuri sforsci de sviluppo. Pe-o to scistema saiâ inviou i seguenti dæti:\n<pre>$1</pre>",
+       "config-almost-done": "T'hæ quæxi a tio!\nAoa ti poeu sâtâ a restante parte da configuaçion e instalâ a wiki subbito.",
+       "config-optional-continue": "Famme di atre domande.",
+       "config-optional-skip": "Son za stuffo, installa a wiki e basta.",
+       "config-profile": "Profî di driti utente:",
+       "config-profile-wiki": "Wiki averta",
+       "config-profile-no-anon": "Creaçion utença obrigatoia",
+       "config-profile-fishbowl": "Solo utenti aotorizæ",
+       "config-profile-private": "Wiki privâ",
+       "config-profile-help": "E wiki fonçion-an megio se ti permetti a tante person-e de poeili modificâ.\nIn MediaWiki, l'è sempliçe controlâ i urtime modiffiche, e ripristinâ i danni caosæ da di utenti inesperti ò malintençionæ.\n\nTuttavia, tanti han trovou a MediaWiki uttile inte 'n'ampia varietæ de rolli, e de volte no l'è faççile convinçe tutti di vantaggi da modalitæ wiki.\nPerciò, fanni a to scelta.\n\nO modello <strong>{{int:config-profile-wiki}}</strong> o consente a chi se segge de modificâ, anche sença efetoâ l'acesso.\nUna wiki con <strong>{{int:config-profile-no-anon}}</strong> a l'ofre 'na magiô responsabilitæ, ma a poriæ scoragî i contributoî ocaxonæ.\n\nO scenario <strong>{{int:config-profile-fishbowl}}</strong> o consente a-i utenti aotorizæ de modificâ, ma o pubbrico o poeu vixualizâ e paggine, compreiso a cronologia.\nUn <strong>{{int:config-profile-private}}</strong> o consente solo ch'a-i utenti aotorizæ de vixualizâ e paggine, o mæximo groppo o poeu modificâle.\n\nDe configuaçioin di driti utente ciu complesse son disponibbile doppo l'instalaçion, amia a  [https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:User_rights parte relativa do manoâ].",
+       "config-license": "Driti d'aotô e liçençia:",
+       "config-license-none": "Nisciun pê de paggina pe-a liçençia",
+       "config-license-cc-by-sa": "Creative Commons Attribuçion-Condividdi pægio",
+       "config-license-cc-by": "Creative Commons Attribuçion",
+       "config-license-cc-by-nc-sa": "Creative Commons Attribuçion-Non comerciale-Condividdi Pægio",
+       "config-license-cc-0": "Creative Commons Zero (pubbrico dominnio)",
+       "config-license-gfdl": "GNU Free Documentation License 1.3 o verscioin sucescive",
+       "config-license-pd": "Pubbrico dominnio",
+       "config-license-cc-choose": "Seleçion-a un-a de liçençie Creative Commons",
+       "config-license-help": "Tante wiki pubbriche rilascian i so contributi co-ina [http://freedomdefined.org/Definition liçençia libbera]. Sto fæto o l'agiutta a creâ un senso de propietæ condivisa inta comunitæ e o l'incoragisce a contriboî a longo termine. O no l'è generalmente necessaio pe 'na wiki privâ ò aziendale.\n\nSe ti voeu doeuviâ di scriti da Wikipedia, ò ti dexiddei che a Wikipedia a posse vese in graddo de acetâ di scriti copiæ da-a to wiki, ti doviesci scellie <strong>{{int:config-license-cc-by-sa}}</strong>.\n\nIn precedença a Wikipedia a l'ha doeuviou a GNU Free Documentation License. A GFDL a l'è 'na liçençia vallida, ma a l'è difiççile da capî e a complica o riutilizzo di contegnui.",
+       "config-email-settings": "Impostaçioin e-mail",
+       "config-enable-email": "Abillita a sciortia da posta elettronica",
+       "config-enable-email-help": "Se ti voeu che fonçion-e l'e-mail, e [http://www.php.net/manual/en/mail.configuration.php PHP's impostaçioin della posta] dev'esan configuæ corettamente.\nSe non ti dexiddei arcun-a fonçionalitæ de posta eletronnica, ti a poeu disabilitâ chie.",
+       "config-email-user": "Abillita e-mail fra utenti",
+       "config-email-user-help": "Consente a tutti i utenti de inviâse l'un l'atro l'e-mail, se l'han abilitou inte so preferençe.",
+       "config-email-usertalk": "Abillita e notiffiche pe-e paggine de discuscion utente",
+       "config-email-usertalk-help": "Consente a-i utenti de riçeive de notiffiche pe-e modiffiche de so paggine de discuscion, se l'han abilitou inte so preferençe.",
+       "config-email-watchlist": "Abillita e notiffiche pe-a lista sott'oservaçion",
+       "config-email-watchlist-help": "Consente a-i utenti de riçeive de notiffiche pe-e pagine da lista sott'oservaçion, se l'han abilitou inte so preferençe.",
+       "config-email-auth": "Abillita aotenticaçion via e-mail",
+       "config-email-auth-help": "Se questa opçion a l'è attivâ, i utenti dovian confermâ o so adresso e-mail doeouviando un ingancio ch'o ven inviou ogni votta che l'impostan ò o cangian.\nSolo i adressi de posta elettronica aotenticæ poeuan riçeive de e-mail da di atri utenti ò cangiâ e e-mail de notiffica.\nImpostâ st'opçion l'è <strong>raccomandou</strong> pe-e wiki pubbriche pe via do potençiale abuso dee fonçioin de posta elettronica.",
+       "config-email-sender": "Adresso e-mail de ritorno:",
+       "config-email-sender-help": "Inseisci l'adresso e-mail da doeuviâ comme adresso de ritorno pe-a posta ch'a sciorte.\nChì l'è donde ghe saiâ inviou i eventoali eroî.\nMolti server de posta richiedan che armeno a parte do nomme de dominnio a segge vallida.",
+       "config-upload-settings": "Caregamenti de inmaggine e file",
+       "config-upload-enable": "Consentî o caregamento di file",
+       "config-upload-help": "O caregamento di file o poriæ espon-e o to serviou a di reizeghi de segueçça.\nPe magioî informaçioin, lezi a  [https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:Security seçion in sciâ segueçça] into manoâ.\n\nPe consentî o caregamento di file, modiffica a modalitæ inta sottodirectory <code>images</code> da directory prinçipâ da MediaWiki coscì che o serviou web o posse scrive lì.\nPoi attiva questa opçion.",
+       "config-upload-deleted": "Directory pe-i file scassæ:",
+       "config-upload-deleted-help": "Çerni 'na directory onde archiviâ i file scassæ.\nIdealmente, questa a no doviæ ese accescibbile da-o web.",
+       "config-logo": "URL do logo:",
+       "config-logo-help": "O tema predefinio da MediaWiki o l'includde o spaççio pe 'n logo de 135 x 160 pixel sorve o menù laterâ.\nCarrega 'n'inmaggine de dimenscioin apropiæ e inseisci l'URL chie.\n\nL'è poscibbile doeuviâ <code>$wgStylePath</code> o <code>$wgScriptPath</code> se o logo o l'è relativo a sti percorsci.\n\nSe un logo no ti o voeu, lascia sta casella voeua.",
+       "config-instantcommons": "Abillita Instant Commons"
 }
index 8955b8c..f99114e 100644 (file)
@@ -29,7 +29,7 @@ use MediaWiki\MediaWikiServices;
  * Object passed around to modules which contains information about the state
  * of a specific loader request.
  */
-class ResourceLoaderContext {
+class ResourceLoaderContext implements MessageLocalizer {
        protected $resourceLoader;
        protected $request;
        protected $logger;
@@ -222,10 +222,12 @@ class ResourceLoaderContext {
         * Get a Message object with context set.  See wfMessage for parameters.
         *
         * @since 1.27
+        * @param string|string[]|MessageSpecifier $key Message key, or array of keys,
+        *   or a MessageSpecifier.
         * @param mixed ...
         * @return Message
         */
-       public function msg() {
+       public function msg( $key ) {
                return call_user_func_array( 'wfMessage', func_get_args() )
                        ->inLanguage( $this->getLanguage() )
                        // Use a dummy title because there is no real title
index 09ed3c4..1b561ef 100644 (file)
@@ -791,16 +791,18 @@ abstract class ChangesListSpecialPage extends SpecialPage {
                $config = $this->getConfig();
                $opts = new FormOptions();
                $structuredUI = $this->getUser()->getOption( 'rcenhancedfilters' );
+               // If urlversion=2 is set, ignore the filter defaults and set them all to false/empty
+               $useDefaults = $this->getRequest()->getInt( 'urlversion' ) !== 2;
 
                // Add all filters
                foreach ( $this->filterGroups as $filterGroup ) {
                        // URL parameters can be per-group, like 'userExpLevel',
                        // or per-filter, like 'hideminor'.
                        if ( $filterGroup->isPerGroupRequestParameter() ) {
-                               $opts->add( $filterGroup->getName(), $filterGroup->getDefault() );
+                               $opts->add( $filterGroup->getName(), $useDefaults ? $filterGroup->getDefault() : '' );
                        } else {
                                foreach ( $filterGroup->getFilters() as $filter ) {
-                                       $opts->add( $filter->getName(), $filter->getDefault( $structuredUI ) );
+                                       $opts->add( $filter->getName(), $useDefaults ? $filter->getDefault( $structuredUI ) : false );
                                }
                        }
                }
@@ -808,6 +810,7 @@ abstract class ChangesListSpecialPage extends SpecialPage {
                $opts->add( 'namespace', '', FormOptions::STRING );
                $opts->add( 'invert', false );
                $opts->add( 'associated', false );
+               $opts->add( 'urlversion', 1 );
 
                return $opts;
        }
index e861afe..9594952 100644 (file)
@@ -33,7 +33,7 @@ use MediaWiki\MediaWikiServices;
  *
  * @ingroup SpecialPage
  */
-class SpecialPage {
+class SpecialPage implements MessageLocalizer {
        // The canonical name of this special page
        // Also used for the default <h1> heading, @see getDescription()
        protected $mName;
@@ -743,7 +743,7 @@ class SpecialPage {
         * @return Message
         * @see wfMessage
         */
-       public function msg( /* $args */ ) {
+       public function msg( $key /* $args */ ) {
                $message = call_user_func_array(
                        [ $this->getContext(), 'msg' ],
                        func_get_args()
index acfc1c0..cbf2e37 100644 (file)
@@ -138,7 +138,8 @@ class SpecialRecentChanges extends ChangesListSpecialPage {
         * @param string $subpage
         */
        public function execute( $subpage ) {
-               global $wgStructuredChangeFiltersEnableSaving;
+               global $wgStructuredChangeFiltersEnableSaving,
+                       $wgStructuredChangeFiltersEnableExperimentalViews;
 
                // Backwards-compatibility: redirect to new feed URLs
                $feedFormat = $this->getRequest()->getVal( 'feed' );
@@ -184,6 +185,10 @@ class SpecialRecentChanges extends ChangesListSpecialPage {
                                'wgStructuredChangeFiltersEnableSaving',
                                $wgStructuredChangeFiltersEnableSaving
                        );
+                       $out->addJsConfigVars(
+                               'wgStructuredChangeFiltersEnableExperimentalViews',
+                               $wgStructuredChangeFiltersEnableExperimentalViews
+                       );
                }
        }
 
index fb45cf7..f84e21e 100644 (file)
@@ -203,10 +203,11 @@ class Language {
        /**
         * Create a language object for a given language code
         * @param string $code
+        * @param $fallback boolean Whether we're going through language fallback chain
         * @throws MWException
         * @return Language
         */
-       protected static function newFromCode( $code ) {
+       protected static function newFromCode( $code, $fallback = false ) {
                if ( !Language::isValidCode( $code ) ) {
                        throw new MWException( "Invalid language code \"$code\"" );
                }
@@ -220,7 +221,7 @@ class Language {
                }
 
                // Check if there is a language class for the code
-               $class = self::classFromCode( $code );
+               $class = self::classFromCode( $code, $fallback );
                if ( class_exists( $class ) ) {
                        $lang = new $class;
                        return $lang;
@@ -4338,10 +4339,11 @@ class Language {
 
        /**
         * @param string $code
+        * @param boolean $fallback Whether we're going through language fallback chain
         * @return string Name of the language class
         */
-       public static function classFromCode( $code ) {
-               if ( $code == 'en' ) {
+       public static function classFromCode( $code, $fallback = true ) {
+               if ( $fallback && $code == 'en' ) {
                        return 'Language';
                } else {
                        return 'Language' . str_replace( '-', '_', ucfirst( $code ) );
index 5382df4..19d644c 100644 (file)
@@ -36,6 +36,7 @@ class LanguageConverter {
         * @var array
         */
        static public $languagesWithVariants = [
+               'en',
                'gan',
                'iu',
                'kk',
diff --git a/languages/MessageLocalizer.php b/languages/MessageLocalizer.php
new file mode 100644 (file)
index 0000000..9a1796b
--- /dev/null
@@ -0,0 +1,43 @@
+<?php
+/**
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ *
+ * @file
+ * @ingroup Language
+ */
+
+/**
+ * Interface for localizing messages in MediaWiki
+ *
+ * @since 1.30
+ * @ingroup Language
+ */
+interface MessageLocalizer {
+
+       /**
+        * This is the method for getting translated interface messages.
+        *
+        * @see https://www.mediawiki.org/wiki/Manual:Messages_API
+        * @see Message::__construct
+        *
+        * @param string|string[]|MessageSpecifier $key Message key, or array of keys,
+        *   or a MessageSpecifier.
+        * @param mixed $params,... Normal message parameters
+        * @return Message
+        */
+       public function msg( $key /*...*/ );
+
+}
diff --git a/languages/classes/LanguageEn.php b/languages/classes/LanguageEn.php
new file mode 100644 (file)
index 0000000..dcb7a91
--- /dev/null
@@ -0,0 +1,85 @@
+<?php
+/**
+ * English specific code.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ *
+ * @file
+ * @ingroup Language
+ */
+
+class EnConverter extends LanguageConverter {
+       /**
+        * Dummy methods required by base class.
+        */
+       function loadDefaultTables() {
+               $this->mTables = [
+                       'en' => new ReplacementArray(),
+                       'en-x-piglatin' => new ReplacementArray(),
+               ];
+       }
+
+       /**
+        * Translates text into Pig Latin. This allows developers to test the language variants
+        * functionality and user interface without having to switch wiki language away from default.
+        *
+        * @param $text string
+        * @param $toVariant string
+        * @return string
+        */
+       function translate( $text, $toVariant ) {
+               if ( $toVariant === 'en-x-piglatin' ) {
+                       // Only process words composed of standard English alphabet, leave the rest unchanged.
+                       // This skips some English words like 'naïve' or 'résumé', but we can live with that.
+                       // Ignore single letters and words which aren't lowercase or uppercase-first.
+                       return preg_replace_callback( '/[A-Za-z][a-z]+/', function ( $matches ) {
+                               $word = $matches[0];
+                               if ( preg_match( '/^[aeiou]/i', $word ) ) {
+                                       return $word . 'way';
+                               } else {
+                                       return preg_replace_callback( '/^(qu|[^aeiou][^aeiouy]*)(.*)$/i', function ( $m ) {
+                                               $ucfirst = strtoupper( $m[1][0] ) === $m[1][0];
+                                               if ( $ucfirst ) {
+                                                       return ucfirst( $m[2] ) . lcfirst( $m[1] ) . 'ay';
+                                               } else {
+                                                       return $m[2] . $m[1] . 'ay';
+                                               }
+                                       }, $word );
+                               }
+                       }, $text );
+               } else {
+                       return $text;
+               }
+       }
+}
+
+/**
+ * English
+ *
+ * @ingroup Language
+ */
+class LanguageEn extends Language {
+       function __construct() {
+               global $wgUsePigLatinVariant, $wgHooks;
+
+               parent::__construct();
+
+               if ( $wgUsePigLatinVariant ) {
+                       $this->mConverter = new EnConverter( $this, 'en', [ 'en', 'en-x-piglatin' ] );
+                       $wgHooks['PageContentSaveComplete'][] = $this->mConverter;
+               }
+       }
+}
index 76ced3e..21479f1 100644 (file)
@@ -146,6 +146,7 @@ class Names {
                'en' => 'English', # English
                'en-ca' => 'Canadian English', # Canadian English
                'en-gb' => 'British English', # British English
+               'en-x-piglatin' => 'Igpay Atinlay', # Pig Latin (for variant development)
                'eo' => 'Esperanto', # Esperanto
                'es' => 'español', # Spanish
                'et' => 'eesti', # Estonian
index f104ab7..b915faf 100644 (file)
@@ -21,6 +21,9 @@
        "tog-numberheadings": " Nicike kata masinihikepirik akitasowina  e icinikateki tipanisinihikanica",
        "tog-showtoolbar": "Motena ka maskotikw kata nokoki irapitcitcikana masinihikakan e nisawitakaniwok",
        "tog-editondblclick": "Nicowaw mamakona kata kweskisinahaman paskickwemakana",
+       "tog-watchcreations": "Ita acotcita nosinesinihikanik paskickwemikana ocki ka ocitaian acit nohwe ka natcipitaman natisinihikaniwoca.",
+       "tog-watchdefault": "Acotcicta paskickemikana nosinesinihikanik acit natisinihikaniwoca ka ki kweskisinahaman",
+       "tog-watchuploads": "Ka natcipitaman ocki natisinihikaniwoca nta ici acotcita nosinesinihikanik",
        "underline-always": "Mocak",
        "underline-never": "Nama wiskat",
        "sunday": "Manactakaniwon",
index 9a3ebe9..4101509 100644 (file)
        "authform-nosession-login": "Аўтэнтыфікацыя была пасьпяховай, але ваш браўзэр ня змог «запомніць» уваход у сыстэму.\n\n$1",
        "authform-nosession-signup": "Рахунак быў створаны, але ваш браўзэр ня змог «запомніць» уваход у сыстэму.\n\n$1",
        "authform-newtoken": "Адсутнічае токен. $1",
+       "authform-notoken": "Адсутнічае токен",
        "changecredentials": "Зьмена ўліковых зьвестак",
        "removecredentials": "Выдаленьне ўліковых зьвестак",
        "removecredentials-submit": "Выдаліць уліковыя зьвесткі",
index 49fd7e9..9cd29ac 100644 (file)
        "anontalk": "Размовы",
        "navigation": "Навігацыя",
        "and": "&#32;і",
-       "qbfind": "Знайсці",
-       "qbbrowse": "Выбраць",
-       "qbedit": "Правіць",
-       "qbpageoptions": "Гэтая старонка",
-       "qbmyoptions": "Свае старонкі",
        "faq": "ЧАПЫ",
-       "faqpage": "Project:ЧАПЫ",
        "actions": "Дзеянні",
        "namespaces": "Прасторы імёнаў",
        "variants": "Варыянты",
        "edit-local": "Правіць тутэйшае апісанне",
        "create": "Стварыць",
        "create-local": "Дадаць тутэйшае апісанне",
-       "editthispage": "Правіць гэту старонку",
-       "create-this-page": "Стварыць старонку",
        "delete": "Сцерці",
-       "deletethispage": "Сцерці гэту старонку",
-       "undeletethispage": "Аднавіць гэту старонку",
        "undelete_short": "Аднавіць {{PLURAL:$1|адну праўку|$1 правак}}",
        "viewdeleted_short": "Паказаць {{PLURAL:$1|адну сцёртую праўку|$1 сцёртыя праўкі}}",
        "protect": "Ахова",
        "protect_change": "змяніць",
-       "protectthispage": "Пачаць ахоўваць гэтую старонку",
        "unprotect": "Змяніць ахову",
-       "unprotectthispage": "Змяніць ахову гэтай старонкі",
        "newpage": "Новая старонка",
-       "talkpage": "Размовы пра гэтую старонку",
        "talkpagelinktext": "Размовы",
        "specialpage": "Адмысловая старонка",
        "personaltools": "Асабістыя прылады",
-       "articlepage": "Паказаць старонку змесціва",
        "talk": "Размовы",
        "views": "Віды",
        "toolbox": "Прылады",
        "tool-link-userrights": "Змяніць групы {{GENDER:$1|ўдзельніка|ўдзельніцы}}",
        "tool-link-userrights-readonly": "Паказаць групы {{GENDER:$1|ўдзельніка|ўдзельніцы}}",
        "tool-link-emailuser": "Напісаць ліст {{GENDER:$1|удзельніку|удзельніцы}}",
-       "userpage": "Паказаць старонку ўдзельніка",
-       "projectpage": "Паказаць старонку праекта",
        "imagepage": "Гл. старонку файла",
        "mediawikipage": "Паказаць старонку паведамлення",
        "templatepage": "Паказаць старонку шаблона",
        "recentchanges-legend-newpage": "{{int:recentchanges-label-newpage}} (гл. асобна [[Special:NewPages|новыя старонкі]])",
        "recentchanges-submit": "Паказаць",
        "rcfilters-activefilters": "Актыўныя фільтры",
+       "rcfilters-savedqueries-rename": "Перайменаваць",
+       "rcfilters-savedqueries-setdefault": "Устанавіць прадвызначаным",
+       "rcfilters-savedqueries-unsetdefault": "Зняць прадвызначэнне",
+       "rcfilters-savedqueries-remove": "Сцерці",
+       "rcfilters-savedqueries-new-name-label": "Назва",
+       "rcfilters-savedqueries-apply-label": "Запісаць настройкі",
+       "rcfilters-savedqueries-cancel-label": "Скасаваць",
+       "rcfilters-savedqueries-add-new-title": "Запісаць цяперашнія настройкі фільтра",
        "rcfilters-restore-default-filters": "Аднавіць фільтры па змоўчанні",
        "rcfilters-clear-all-filters": "Ачысціць усе фільтры",
+       "rcfilters-invalid-filter": "Недапушчальны фільтр",
+       "rcfilters-filterlist-title": "Фільтры",
+       "rcfilters-filterlist-whatsthis": "Што гэта?",
        "rcfilters-highlightmenu-title": "Выбраць колер",
        "rcfilters-highlightmenu-help": "Выбраць колер для падсвечвання уласцівасці",
        "rcfilters-filtergroup-registration": "Рэгістрацыя ўдзельніка",
        "rcfilters-filter-humans-description": "Праўкі, зробленыя людзьмі",
        "rcfilters-filter-patrolled-label": "Дагледжаны",
        "rcfilters-filter-unpatrolled-label": "Недагледжаны",
+       "rcfilters-filtergroup-lastRevision": "Цяперашняя версія",
+       "rcfilters-filter-lastrevision-label": "Актуальная версія",
        "rcnotefrom": "Ніжэй {{PLURAL:$5|паказана змяненне|паказаны змены}} з <strong>$3, $4</strong> (не больш за <strong>$1</strong>).",
        "rclistfrom": "Паказаць змены з $3 $2",
        "rcshowhideminor": "$1 дробныя праўкі",
        "editcomment": "Тлумачэнне праўкі было: <em>$1</em>.",
        "revertpage": "Праўкі аўтарства [[Special:Contributions/$2|$2]] ([[User talk:$2|размова]]) адкочаныя; вернута апошняя версія аўтарства [[User:$1|$1]]",
        "revertpage-nouser": "Праўкі (імя ўдзельніка схавана) адкочаны да версіі {{GENDER:$1|[[User:$1|$1]]}}",
-       "rollback-success": "Адкочаны праўкі $1; вернута апошняя версія $2.",
+       "rollback-success": "Адкочаны праўкі {{GENDER:$3|$1}}; вернута апошняя версія {{GENDER:$4|$2}}.",
        "rollback-success-notify": "Адкочаны праўкі $1;\nвернута апошняя версія $2. [$3 Паказаць змены]",
        "sessionfailure-title": "Памылка сеансу",
        "sessionfailure": "Магчыма, ёсць праблемы з вашым сеансам працы ў сістэме. Таму вам было адмоўлена ў выкананні дзеяння, каб засцерагчыся ад захопу сеанса.\n\nВярніцеся на папярэднюю старонку, перазагрузіце яе і тады паспрабуйце зноў.",
        "changecontentmodel-emptymodels-text": "Змесціва [[:$1]] не можа быць ператворана ні ў які тып.",
        "log-name-contentmodel": "Журнал змен мадэляў змесціва",
        "log-description-contentmodel": "Падзеі, звязаныя з мадэлямі змесціва старонак",
+       "logentry-contentmodel-new": "$1 {{GENDER:$2|стварыў|стварыла}} старонку $3, выкарыстаўшы нетыповую мадэль змесціва \"$5\"",
        "logentry-contentmodel-change-revertlink": "адкаціць",
        "logentry-contentmodel-change-revert": "адкат",
        "protectlogpage": "Журнал аховы",
        "sp-contributions-uploads": "укладанні",
        "sp-contributions-logs": "журналы",
        "sp-contributions-talk": "размовы",
-       "sp-contributions-userrights": "распараджэнне правамі ўдзельніка",
+       "sp-contributions-userrights": "распараджэнне правамі {{GENDER:$1|ўдзельніка|ўдзельніцы}}",
        "sp-contributions-blocked-notice": "Гэты ўдзельнік у дадзены момант заблакаваны. Ніжэй прыведзены апошні запіс з журнала блакаванняў:",
        "sp-contributions-blocked-notice-anon": "Гэты IP-адрас у дадзены момант заблакаваны.\nНіжэй прыведзены апошні запіс з журнала блакаванняў:",
        "sp-contributions-search": "Знайсці ўклад",
        "unblocked-id": "Блок $1 быў зняты",
        "unblocked-ip": "[[Special:Contributions/$1|$1]] быў разблакіраваны.",
        "blocklist": "Заблакаваныя ўдзельнікі",
+       "autoblocklist-submit": "Шукаць",
        "ipblocklist": "Заблакаваныя ўдзельнікі",
        "ipblocklist-legend": "Знайсці заблакаванага ўдзельніка",
        "blocklist-userblocks": "Схаваць блакіроўкі ўліковых запісаў",
        "version-libraries-description": "Апісанне",
        "version-libraries-authors": "Аўтары",
        "redirect": "Перасылка да файла, ID удзельніка, старонкі, версіі ці журнала",
-       "redirect-summary": "Гэта адмысловая старонка перасылае да файла (з назвы файла), на старонку (з ідэнтыфікатара версіі ці старонкі), ці на старонку ўдзельніка (калі дадзены лічбавы ID удзельніка). Ужыванне: [[{{#Special:Redirect}}/file/Example.jpg]], [[{{#Special:Redirect}}/page/64308]], [[{{#Special:Redirect}}/revision/328429]], ці [[{{#Special:Redirect}}/user/101]].",
+       "redirect-summary": "Гэта адмысловая старонка перасылае да файла (з назвы файла), на старонку (з ідэнтыфікатара версіі ці старонкі), на старонку ўдзельніка (калі дадзены лічбавы ID удзельніка), ці на запіс журнала (калі дадзены лічбавы ID запісу). Ужыванне: [[{{#Special:Redirect}}/file/Example.jpg]], [[{{#Special:Redirect}}/page/64308]], [[{{#Special:Redirect}}/revision/328429]],[[{{#Special:Redirect}}/user/101]], ці [[{{#Special:Redirect}}/logid/186]].",
        "redirect-submit": "Перайсці",
        "redirect-lookup": "Шукаць:",
        "redirect-value": "Значэнне:",
        "htmlform-user-not-valid": "<strong>$1</strong> - недапушчальная назва уліковага запісу.",
        "logentry-delete-delete": "$1 {{GENDER:$2|сцёр|сцёрла}} старонку $3",
        "logentry-delete-delete_redir": "$1 {{GENDER:$2|выдаліў|выдаліла}} перанакіраванне $3 шляхам перазапісу",
-       "logentry-delete-restore": "$1 {{GENDER:$2|аднавіў|аднавіла}} старонку $3",
+       "logentry-delete-restore": "$1 {{GENDER:$2|аднавіў|аднавіла}} старонку $3 ($4)",
        "logentry-delete-event": "$1 {{GENDER:$2|змяніў|змяніла}} бачнасць {{PLURAL:$5|запісу журнала|$5 запісаў журнала}} $3: $4",
        "logentry-delete-revision": "$1 {{GENDER:$2|змяніў|змяніла}} бачнасць {{PLURAL:$5|версіі|$5 версій|$5 версій}} старонкі $3: $4",
        "logentry-delete-event-legacy": "$1 {{GENDER:$2|змяніў|змяніла}} бачнасць запісаў журнала $3",
        "mw-widgets-mediasearch-input-placeholder": "Пошук мультымедыя",
        "mw-widgets-titleinput-description-new-page": "старонка яшчэ не існуе",
        "mw-widgets-titleinput-description-redirect": "перанакіраванне на $1",
+       "randomrootpage": "Выпадковая карэнная старонка",
        "log-action-filter-all": "Усе",
        "log-action-filter-block-block": "заблакаваць",
        "log-action-filter-block-reblock": "Змена блакіроўкі",
index 006c69e..ef52a9b 100644 (file)
        "subject-preview": "Предварителен преглед на заглавието:",
        "previewerrortext": "Възникна грешка при опита за преглед на промените.",
        "blockedtitle": "Потребителят е блокиран",
-       "blockedtext": "'''Вашето потребителско име (или IP-адрес) беше блокирано.'''\n\nБлокирането е извършено от $1. Посочената причина е: ''$2''\n\n*Начало на блокирането: $8\n*Край на блокирането: $6\n*Блокирането се отнася за: $7\n\nМожете да се свържете с $1 или с някой от останалите [[{{MediaWiki:Grouppage-sysop}}|администратори]], за да обсъдите блокирането.\n\nМожете да използвате услугата „Пращане писмо на потребител“ само ако не ви е забранена употребата й и ако сте посочили валидна електронна поща в [[Special:Preferences|настройките]] си.\n\nВашият IP адрес е $3, а номерът на блокирането е $5. Включвайте едно от двете или и двете във всяко запитване, което правите.",
-       "autoblockedtext": "IP-адресът ви беше блокиран автоматично, защото е бил използван от друг потребител, който е бил блокиран от $1.\nПосочената причина е:\n\n:''$2''\n\n* Начало на блокирането: $8\n* Край на блокирането: $6\n* Блокирането се отнася за: $7\n\nМожете да се свържете с $1 или с някой от останалите [[{{MediaWiki:Grouppage-sysop}}|администратори]], за да обсъдите блокирането.\n\nМожете да използвате услугата „Пращане писмо на потребител“ само ако не ви е забранена употребата й и ако сте посочили валидна електронна поща в [[Special:Preferences|настройките]] си.\n\nТекущият ви IP-адрес е $3, а номерът на блокирането ви е $5. Включвайте ги във всяко питане, което правите.",
+       "blockedtext": "'''Вашето потребителско име (или IP-адрес) беше блокирано.'''\n\nБлокирането е извършено от $1. Посочената причина е: ''$2''\n\n*Начало на блокирането: $8\n*Край на блокирането: $6\n*Блокирането се отнася за: $7\n\nМожете да се свържете с $1 или с някой от останалите [[{{MediaWiki:Grouppage-sysop}}|администратори]], за да обсъдите блокирането.\n\nМожете да използвате услугата „Пращане писмо на потребител“ само ако не ви е забранена употребата ѝ и ако сте посочили валидна електронна поща в [[Special:Preferences|настройките]] си.\n\nВашият IP адрес е $3, а номерът на блокирането е $5. Включвайте едно от двете или и двете във всяко запитване, което правите.",
+       "autoblockedtext": "IP-адресът ви беше блокиран автоматично, защото е бил използван от друг потребител, който е бил блокиран от $1.\nПосочената причина е:\n\n:''$2''\n\n* Начало на блокирането: $8\n* Край на блокирането: $6\n* Блокирането се отнася за: $7\n\nМожете да се свържете с $1 или с някой от останалите [[{{MediaWiki:Grouppage-sysop}}|администратори]], за да обсъдите блокирането.\n\nМожете да използвате услугата „Пращане писмо на потребител“ само ако не ви е забранена употребата ѝ и ако сте посочили валидна електронна поща в [[Special:Preferences|настройките]] си.\n\nТекущият ви IP-адрес е $3, а номерът на блокирането ви е $5. Включвайте ги във всяко питане, което правите.",
        "blockednoreason": "не е указана причина",
        "whitelistedittext": "Редактирането на страници изисква $1 в системата.",
        "confirmedittext": "Необходимо е да потвърдите електронната си поща, преди да редактирате страници.\nВъведете и потвърдете адреса си на [[Special:Preferences|страницата с настройките]].",
        "img-auth-public": "Функцията img_auth.php е да извлича файлове от частни уикита.\nТова уики е конфигурирано като публично.\nС цел оптимална сигурност, функцията img_auth.php е деактивирана.",
        "img-auth-noread": "Потребителят няма достъп за четене на „$1“.",
        "http-invalid-url": "Невалиден адрес: $1",
-       "http-invalid-scheme": "Не се поддържат URL адреси с префикс „$1“.",
+       "http-invalid-scheme": "Не се поддържат URL адреси с представка „$1“.",
        "http-request-error": "HTTP заявката пропадна поради неизвестна грешка.",
        "http-read-error": "HTTP грешка при четене.",
        "http-timed-out": "Пресрочено време за HTTP заявка.",
        "undeleteextrahelp": "За възстановяване на пълната история на страницата не се слагат отметки и се натиска '''''{{int:undeletebtn}}'''''.\nЗа частично възстановяване се поставят отметки на тези версии на страницата, които трябва да бъдат възстановени, след което се натиска '''''{{int:undeletebtn}}'''''.",
        "undeleterevisions": "$1 {{PLURAL:$1|версия беше изтрита|версии бяха изтрити}}",
        "undeletehistory": "Ако възстановите страницата, всички версии ще бъдат върнати в историята.\nАко след изтриването е създадена страница със същото име, възстановените версии ще се появят като по-ранна история, а текущата версия на страницата няма да бъде заменена автоматично. Също така обърнете внимание, че ограниченията, приложени върху версиите, ще се загубят след възстановяването.",
-       "undeleterevdel": "Възстановяването няма да бъде изпълнено, ако би довело до частично изтриване на актуалната версия. В такъв случай актуалната версия не трябва да бъде избирана или пък състоянието й трябва да бъде променено на нормална (нескрита) версия. Версиите на файлове, които нямате право да преглеждате, няма да бъдат възстановени.",
-       "undeletehistorynoadmin": "Тази страница е била изтрита. В резюмето отдолу е посочена причината за това, заедно с информация за потребителите, редактирали страницата преди изтриването й. Конкретното съдържание на изтритите версии е достъпно само за администратори.",
+       "undeleterevdel": "Възстановяването няма да бъде изпълнено, ако би довело до частично изтриване на актуалната версия. В такъв случай актуалната версия не трябва да бъде избирана или пък състоянието ѝ трябва да бъде променено на нормална (нескрита) версия. Версиите на файлове, които нямате право да преглеждате, няма да бъдат възстановени.",
+       "undeletehistorynoadmin": "Тази страница е била изтрита. В резюмето отдолу е посочена причината за това, заедно с информация за потребителите, редактирали страницата преди изтриването ѝ. Конкретното съдържание на изтритите версии е достъпно само за администратори.",
        "undelete-revision": "Изтрита версия на $1 (към $4, в $5) от $3:",
        "undeleterevision-missing": "Неправилна или липсваща версия. Може да сте последвали грешна препратка или указаната версия да е била възстановена или премахната от архива",
        "undelete-nodiff": "Не е открита предишна редакция.",
        "delete_and_move_reason": "Изтрита, за да се освободи място за преместване от „[[$1]]“",
        "selfmove": "Страницата не може да бъде преместена, тъй като целевото име съвпада с първоначалното ѝ заглавие.",
        "immobile-source-namespace": "Не могат да се местят страници в именно пространство „$1“",
-       "immobile-target-namespace": "Ð\9dе Ðµ Ð²Ñ\8aзможно Ð¿Ñ\80емеÑ\81Ñ\82ванеÑ\82о Ð½Ð° Ñ\81Ñ\82Ñ\80аниÑ\86и Ð² Ð¸Ð¼ÐµÐ½Ð½Ð¾Ñ\82о Ð¿Ñ\80оÑ\81Ñ\82Ñ\80анÑ\81Ñ\82во â\80\9e$1â\80\9c",
+       "immobile-target-namespace": "Ð\9dе Ð¼Ð¾Ð³Ð°Ñ\82 Ð´Ð° Ñ\81е Ð¼ÐµÑ\81Ñ\82Ñ\8fÑ\82 Ñ\81Ñ\82Ñ\80аниÑ\86и Ð² Ð¸Ð¼ÐµÐ½Ð½Ð¾ Ð¿Ñ\80оÑ\81Ñ\82Ñ\80анÑ\81Ñ\82во â\80\9e$1â\80\9c.",
        "immobile-target-namespace-iw": "Страницата не може да бъде преместена под заглавие, оформено като междууики препратка.",
        "immobile-source-page": "Тази страница не може да бъде премествана.",
        "immobile-target-page": "Не може да се извърши преместване върху това целево заглавие.",
-       "imagenocrossnamespace": "Невъзможно е да се преместват картинки извън това именно пространство",
+       "imagenocrossnamespace": "Не може да се преместват картинки извън това именно пространство",
        "nonfile-cannot-move-to-file": "Не може да се премести във файл нещо, което не е файл.",
-       "imagetypemismatch": "Новото разширение на файла не съвпада с типа му",
-       "imageinvalidfilename": "Целевото име на файл е невалидно",
+       "imagetypemismatch": "Новото разширение на файла не съвпада с типа му.",
+       "imageinvalidfilename": "Целевото име на файл е невалидно.",
        "fix-double-redirects": "Обновяване на всички двойни пренасочвания, които сочат към оригиналното заглавие",
        "move-leave-redirect": "Оставяне на пренасочваща страница от старото към новото заглавие",
        "protectedpagemovewarning": "<strong>Внимание:</strong> Тази страница е защитена и само потребители със статут на администратори могат да я преместят.\nЗа справка по-долу е показан последният запис от дневниците.",
-       "semiprotectedpagemovewarning": "'''Внимание:''' Тази страница е защитена и само регистрирани потребители могат да я преместят.\nЗа справка по-долу е показан последният запис от дневниците.",
+       "semiprotectedpagemovewarning": "<strong>Забележка:</strong> Тази страница е защитена и само регистрирани потребители могат да я преместят.\nЗа справка по-долу е показан последният запис от дневниците.",
        "move-over-sharedrepo": "[[:$1]] вече съществува в споделеното хранилище. Преместване на файл с това заглавие ще замени споделения файл.",
-       "file-exists-sharedrepo": "Ð\98збÑ\80аноÑ\82о Ð¸Ð¼Ðµ Ð½Ð° Ñ\84айл Ð²ÐµÑ\87е Ñ\81е Ð¸Ð·Ð¿Ð¾Ð»Ð·Ð²Ð° Ð¾Ñ\82 Ñ\84айл Ð² Ñ\81опделеното хранилище.\nНеобходимо е да изберете друго име.",
+       "file-exists-sharedrepo": "Ð\98збÑ\80аноÑ\82о Ð¸Ð¼Ðµ Ð½Ð° Ñ\84айл Ð²ÐµÑ\87е Ñ\81е Ð¸Ð·Ð¿Ð¾Ð»Ð·Ð²Ð° Ð¾Ñ\82 Ñ\84айл Ð² Ñ\81поделеното хранилище.\nНеобходимо е да изберете друго име.",
        "export": "Изнасяне на страници",
        "exporttext": "Тук можете да изнесете като XML текста и историята на една или повече страници. Получените данни можете да вмъкнете в друг сайт, използващ софтуера МедияУики, чрез [[Special:Import|неговата страница за внaсяне]].\n\nЗа да изнесете няколко страници, въвеждайте всяко ново заглавие на '''нов ред'''. След това изберете дали искате само текущата версия (заедно с информация за последната редакция) или всички версии (заедно с текущата) на страницата.\n\nАко желаете само текущата версия, бихте могли да използвате препратка от вида [[{{#Special:Export}}/{{MediaWiki:Mainpage}}]] за страницата [[{{MediaWiki:Mainpage}}]].",
        "exportall": "Изнасяне на всички страници",
        "exportcuronly": "Включване само на текущата версия, а не на цялата история",
-       "exportnohistory": "----\n'''Важно:''' Изнасянето на пълната история на страниците е забранено, защото много забавя уикито.",
+       "exportnohistory": "----\n<strong>Забележка:</strong>' Изнасянето на пълната история на страниците е забранено, защото много забавя уикито.",
        "exportlistauthors": "Добавяне на пълен списък на редакторите за всяка страница",
        "export-submit": "Изнасяне",
        "export-addcattext": "Добавяне на страници от категория:",
        "export-download": "Съхраняване като файл",
        "export-templates": "Включване на шаблоните",
        "export-pagelinks": "Включване на свързаните страници с дълбочина до:",
-       "export-manual": "Добавяне на страниците ръчно:",
+       "export-manual": "Добавете страници ръчно:",
        "allmessages": "Системни съобщения",
        "allmessagesname": "Име",
        "allmessagesdefault": "Текст по подразбиране",
        "allmessagescurrent": "Текущ текст",
        "allmessagestext": "Тази страница съдържа списък на системните съобщения от именното пространство „МедияУики“.\nПосетете [https://www.mediawiki.org/wiki/Special:MyLanguage/Localisation MediaWiki Localisation] и [https://translatewiki.net translatewiki.net], ако желаете да допринесете за общата локализация на софтуера МедияУики.",
-       "allmessagesnotsupportedDB": "Тази страница не може да бъде използвана, тъй като е изключена възможността '''$wgUseDatabaseMessages'''.",
+       "allmessagesnotsupportedDB": "Тази страница не може да бъде използвана, тъй като е изключена възможността <strong>$wgUseDatabaseMessages</strong>",
        "allmessages-filter-legend": "Филтър",
        "allmessages-filter": "Филтриране по ниво на персонализация:",
        "allmessages-filter-unmodified": "Непроменени",
        "allmessages-prefix": "Филтриране по представка:",
        "allmessages-language": "Език:",
        "allmessages-filter-submit": "Отваряне",
-       "allmessages-filter-translate": "Ð\9fÑ\80евеждане",
+       "allmessages-filter-translate": "Ð\9fÑ\80евод",
        "thumbnail-more": "Увеличаване",
        "filemissing": "Липсващ файл",
        "thumbnail_error": "Грешка при създаване на миникартинка: $1",
        "import-revision-count": "$1 {{PLURAL:$1|версия|версии}}",
        "importnopages": "Няма страници за внасяне.",
        "imported-log-entries": "{{PLURAL:$1|Внесен е $1 запис|Внесени са $1 записа}} в дневника.",
-       "importfailed": "Внасянето беше неуспешно: $1",
+       "importfailed": "Внасянето беше неуспешно: nowiki>$1</nowiki>",
        "importunknownsource": "Непознат тип файл",
        "importcantopen": "Не е възможно да се отвори файла за внасяне",
        "importbadinterwiki": "Невалидна уики препратка",
        "import-upload": "Качване на XML данни",
        "import-token-mismatch": "Загуба на данните за текущата сесия.\n\nМоже би сте излезли от системата. <strong>Моля, уверете се, че сте влезли в профила си и опитайте отново</strong>.\nАко все още не работи, опитайте да [[Special:UserLogout|излезете]] и да влезете отново, също така проверете дали браузърът ви позволява бисквитки от този сайт.",
        "import-invalid-interwiki": "Не може да бъде извършено внасяне от посоченото уики.",
-       "import-error-edit": "СÑ\82Ñ\80аниÑ\86аÑ\82а â\80\9e$1â\80\9c Ð½Ðµ Ð±ÐµÑ\88е Ð¸Ð¼Ð¿Ð¾Ñ\80Ñ\82иÑ\80ана, тъй като нямате права да я редактирате.",
-       "import-error-create": "СÑ\82Ñ\80аниÑ\86аÑ\82а â\80\9e$1â\80\9c Ð½Ðµ Ð±ÐµÑ\88е Ð¸Ð¼Ð¿Ð¾Ñ\80Ñ\82иÑ\80ана, тъй като нямате права да я създадете.",
-       "import-error-interwiki": "СÑ\82Ñ\80аниÑ\86аÑ\82а â\80\9e$1â\80\9c Ð½Ðµ Ð±ÐµÑ\88е Ð¸Ð¼Ð¿Ð¾Ñ\80Ñ\82иÑ\80ана, тъй като името ѝ е запазено за външно свързване (междууики).",
+       "import-error-edit": "СÑ\82Ñ\80аниÑ\86аÑ\82а â\80\9e$1â\80\9c Ð½Ðµ Ð±ÐµÑ\88е Ð²Ð½ÐµÑ\81ена, тъй като нямате права да я редактирате.",
+       "import-error-create": "СÑ\82Ñ\80аниÑ\86аÑ\82а â\80\9e$1â\80\9c Ð½Ðµ Ð±ÐµÑ\88е Ð²Ð½ÐµÑ\81ена, тъй като нямате права да я създадете.",
+       "import-error-interwiki": "СÑ\82Ñ\80аниÑ\86аÑ\82а â\80\9e$1â\80\9c Ð½Ðµ Ð±ÐµÑ\88е Ð²Ð½ÐµÑ\81ена, тъй като името ѝ е запазено за външно свързване (междууики).",
        "import-error-special": "Страницата „$1“ не беше внесена, тъй като принадлежи към специално именно пространство, което не позволява страници.",
        "import-error-invalid": "Страницата „$1“ не беше внесена, тъй като името към което трябваше да бъде внесена е невалидно на това уики.",
        "import-rootpage-invalid": "Посочената основна страница е с невалидно заглавие.",
        "import-logentry-upload-detail": "$1 {{PLURAL:$1|версия беше внесена|версии бяха внесени}}",
        "import-logentry-interwiki-detail": "{{PLURAL:$1|една версия беше внесена|$1 версии бяха внесени}} от $2",
        "javascripttest": "Тестване на JavaScript",
-       "javascripttest-pagetext-unknownaction": "Неизвестно действие \"$1\".",
+       "javascripttest-pagetext-unknownaction": "Неизвестно действие „$1“.",
        "javascripttest-qunit-intro": "Вижте [$1 тестовата документация] на mediawiki.org.",
        "tooltip-pt-userpage": "Вашата потребителска страница",
        "tooltip-pt-anonuserpage": "Потребителската страница за адреса, от който редактирате",
        "tooltip-pt-watchlist": "Списък на страници, чиито промени сте избрали да наблюдавате",
        "tooltip-pt-mycontris": "Списък на {{GENDER:|вашите}} приноси",
        "tooltip-pt-anoncontribs": "Списък на промените, направени от този IP адрес",
-       "tooltip-pt-login": "Ð\9dаÑ\81Ñ\8aÑ\80Ñ\87аваме Ð\92и Ð´Ð° Ð²Ð»ÐµÐ·ÐµÑ\82е, Ð²Ñ\8aпÑ\80еки че не е задължително.",
-       "tooltip-pt-logout": "Излизане от {{SITENAME}}",
+       "tooltip-pt-login": "Ð\9fÑ\80епоÑ\80Ñ\8aÑ\87ваме Ð\92и Ð´Ð° Ð²Ð»ÐµÐ·ÐµÑ\82е, Ð²Ñ\8aпÑ\80еки, че не е задължително.",
+       "tooltip-pt-logout": "Излизане",
        "tooltip-pt-createaccount": "Насърчаваме Ви да си създадете сметка и да влезете, въпреки че не е задължително.",
-       "tooltip-ca-talk": "Ð\91еÑ\81еда Ð¾Ñ\82ноÑ\81но страницата",
+       "tooltip-ca-talk": "Ð\91еÑ\81еда Ð·Ð° страницата",
        "tooltip-ca-edit": "Редактиране на страницата",
        "tooltip-ca-addsection": "Започване на нов раздел",
-       "tooltip-ca-viewsource": "Страницата е защитена. Можете да разгледате изходния й код.",
+       "tooltip-ca-viewsource": "Страницата е защитена. Можете да разгледате изходният ѝ код.",
        "tooltip-ca-history": "Предишни версии на страницата",
        "tooltip-ca-protect": "Защитаване на страницата",
        "tooltip-ca-unprotect": "Промяна на защитата за тази страница",
        "tooltip-minoredit": "Отбелязване на промяната като малка",
        "tooltip-save": "Съхраняване на промените",
        "tooltip-publish": "Публикуване на промените",
-       "tooltip-preview": "Предварителен преглед, използвайте го преди да съхраните!",
+       "tooltip-preview": "Предварителен преглед. Използвайте го преди да съхраните.",
        "tooltip-diff": "Показване на направените от вас промени по текста",
        "tooltip-compareselectedversions": "Показване на разликите между двете избрани версии на страницата",
        "tooltip-watch": "Добавяне на страницата към списъка ви за наблюдение",
        "creditspage": "Библиография и източници",
        "nocredits": "Няма въведени източници или библиография.",
        "spamprotectiontitle": "Филтър за защита от спам",
-       "spamprotectiontext": "СÑ\82Ñ\80аниÑ\86аÑ\82а, ÐºÐ¾Ñ\8fÑ\82о Ð¸Ñ\81каÑ\85Ñ\82е Ð´Ð° Ñ\81Ñ\8aÑ\85Ñ\80аниÑ\82е, Ð±ÐµÑ\88е Ð±Ð»Ð¾ÐºÐ¸Ñ\80ана Ð¾Ñ\82 Ñ\84илÑ\82Ñ\8aÑ\80а Ð¿Ñ\80оÑ\82ив Ñ\81пам. Ð¢Ð¾Ð²Ð° Ð¾Ð±Ð¸ÐºÐ½Ð¾Ð²ÐµÐ½Ð¾ Ðµ Ð¿Ñ\80иÑ\87инено от препратка към външен сайт.",
+       "spamprotectiontext": "СÑ\82Ñ\80аниÑ\86аÑ\82а, ÐºÐ¾Ñ\8fÑ\82о Ð¸Ñ\81каÑ\85Ñ\82е Ð´Ð° Ñ\81Ñ\8aÑ\85Ñ\80аниÑ\82е, Ð±ÐµÑ\88е Ð±Ð»Ð¾ÐºÐ¸Ñ\80ана Ð¾Ñ\82 Ñ\84илÑ\82Ñ\8aÑ\80а Ð·Ð° Ñ\81пам. Ð¢Ð¾Ð²Ð° Ð¾Ð±Ð¸ÐºÐ½Ð¾Ð²ÐµÐ½Ð¾ Ðµ Ð¿Ñ\80едизвикано от препратка към външен сайт.",
        "spamprotectionmatch": "Следният текст предизвика включването на филтъра: $1",
        "spambot_username": "Спамочистач",
        "spam_reverting": "Връщане на последната версия, несъдържаща препратки към $1",
        "spam_blanking": "Всички версии, съдържащи препратки към $1, изчистване",
        "spam_deleting": "Всички версии съдържат препратки към $1, изтриване",
-       "simpleantispam-label": "Ð\9fÑ\80овеÑ\80ка Ð·Ð° Ñ\81пам.\n<strong>Ð\9dÐ\95</strong> попълвайте това поле!",
+       "simpleantispam-label": "Ð\9fÑ\80овеÑ\80ка Ð·Ð° Ñ\81пам.\n<strong>не</strong> попълвайте това поле!",
        "pageinfo-title": "Информация за \"$1\"",
        "pageinfo-not-current": "За съжаление тази информация не може да бъде предоставена за стари версии.",
        "pageinfo-header-basic": "Основна информация",
        "exif-artist": "Автор",
        "exif-copyright": "Притежател на авторското право",
        "exif-exifversion": "Exif версия",
-       "exif-flashpixversion": "Поддържана версия Flashpix",
+       "exif-flashpixversion": "Поддържана версия на Flashpix",
        "exif-colorspace": "Цветово пространство",
        "exif-componentsconfiguration": "Значение на всеки компонент",
-       "exif-compressedbitsperpixel": "Режим Ð½Ð° ÐºÐ¾Ð¼Ð¿Ñ\80еÑ\81иÑ\8f Ð½Ð° Ð¾Ð±Ñ\80аза",
+       "exif-compressedbitsperpixel": "Режим Ð½Ð° ÐºÐ¾Ð¼Ð¿Ñ\80еÑ\81иÑ\8f Ð½Ð° Ð¸Ð·Ð¾Ð±Ñ\80ажениеÑ\82о",
        "exif-pixelxdimension": "Ширина на изображението",
        "exif-pixelydimension": "Височина на изображението",
-       "exif-usercomment": "Ð\94опÑ\8aлниÑ\82елни коментари",
+       "exif-usercomment": "Ð\9fоÑ\82Ñ\80ебиÑ\82елÑ\81ки коментари",
        "exif-relatedsoundfile": "Свързан звуков файл",
        "exif-datetimeoriginal": "Дата и час на създаване",
-       "exif-datetimedigitized": "Ð\94аÑ\82а Ð¸ Ñ\87аÑ\81 Ð½Ð° Ð·Ð°Ð¿Ð¸Ñ\81а",
+       "exif-datetimedigitized": "Ð\94аÑ\82а Ð¸ Ñ\87аÑ\81 Ð½Ð° Ð´Ð¸Ð³Ð¸Ñ\82ализаÑ\86иÑ\8f",
        "exif-subsectime": "DateTime части от секундата",
        "exif-subsectimeoriginal": "DateTimeOriginal части от секундата",
        "exif-subsectimedigitized": "DateTimeDigitized части от секундата",
        "exif-keywords": "Ключови думи",
        "exif-worldregioncreated": "Регион на света, където е направена снимката",
        "exif-countrycreated": "Държава, в която е направена снимката",
-       "exif-countrycodecreated": "Ð\9aод Ð½Ð° Ð´Ñ\8aÑ\80жаваÑ\82а, ÐºÑ\8aдето е направена снимката",
-       "exif-provinceorstatecreated": "Ð\9eблаÑ\81Ñ\82 Ð¸Ð»Ð¸ Ñ\89аÑ\82, ÐºÑ\8aдето е направена снимката",
+       "exif-countrycodecreated": "Ð\9aод Ð½Ð° Ð´Ñ\8aÑ\80жаваÑ\82а, Ð² ÐºÐ¾Ñ\8fто е направена снимката",
+       "exif-provinceorstatecreated": "Ð\9eблаÑ\81Ñ\82 Ð¸Ð»Ð¸ Ñ\89аÑ\82, Ð² ÐºÐ¾Ð¹то е направена снимката",
        "exif-citycreated": "Град, в който е направена снимката",
        "exif-worldregiondest": "Показан регион на света",
        "exif-countrydest": "Показана държава",
        "exif-urgency-low": "Ниска ($1)",
        "exif-urgency-high": "Висока ($1)",
        "exif-urgency-other": "Зададен от потребителя приоритет ($1)",
-       "namespacesall": "Ð\92сички",
+       "namespacesall": "всички",
        "monthsall": "всички",
        "confirmemail": "Потвърждаване на адрес за електронна поща",
        "confirmemail_noemail": "Не сте посочили валиден адрес за електронна поща в [[Special:Preferences|настройки си]].",
        "confirmrecreate": "Потребител [[User:$1|$1]] ([[User talk:$1|беседа]]) е {{GENDER:$1|изтрил}} страницата, след като сте започнали да я редактирате, като е посочил следното обяснение:\n: <em>$2</em>\nПотвърдете, че наистина желаете да създадете страницата отново.",
        "confirmrecreate-noreason": "Потребител [[User:$1|$1]] ([[User talk:$1|беседа]]) {{GENDER:$1|изтри}} тази страница след като сте започнали да я редактирате. Необходимо е потвърждение, че наистина желаете да създадете страницата отново.",
        "recreate": "Ново създаване",
+       "confirm-purge-title": "Изчистване на страницата",
        "confirm_purge_button": "Добре",
        "confirm-purge-top": "Изчистване на складираното копие на страницата?",
-       "confirm-purge-bottom": "Изчистването на страница опреснява кеша и показва последната й версия.",
+       "confirm-purge-bottom": "Изчистването на страница опреснява кеша и показва последната ѝ версия.",
        "confirm-watch-button": "Потвърждаване",
        "confirm-watch-top": "Добавяне на страницата в списъка ви за наблюдение?",
        "confirm-unwatch-button": "Потвърждаване",
index 3c3f6ed..aa9df08 100644 (file)
        "tagline": "{{SITENAME}} থেকে",
        "help": "সাহায্য",
        "search": "অনুসন্ধান",
-       "search-ignored-headings": " #<!-- এই লাইনটিকে ঠিক যেমন আছে তেমনটি রেখে দিন --> <pre>\n# যেসব শিরোনাম অনুসন্ধানে অগ্রাহ্য করা হবে।\n# যখনই শিরোনামযুক্ত পাতাটি সূচীভুক্ত হবে, তখনই এখানকার কোন পরিবর্তন বাস্তবায়িত হবে।\n# আপনি একটি নাল/শূন্য সম্পাদনা করে পাতাটিকে বলপূর্বক পুনঃসূচীভুক্ত করতে পারেন।\n# সিনট্যাক্স বা পদক্রম/পদবিন্যাসের নিয়মগুলি নিম্নরূপ:\n#   * অক্ষর থেকে শুরু করে লাইনের শেষ পর্যন্ত সবকিছু হচ্ছে একটি মন্তব্য বা কমেন্ট।\n#   * প্রতিটি অশূন্য লাইন হচ্ছে যে শিরোনামটি অগ্রাহ্য করা হবে, বড় হাতের লেখা এবং অন্যান্য সবকিছু গণনায় ধরে।\nতথ্যসূত্র\nবহিঃসংযোগ\nআরও দেখুন\n#</pre> <!-- এই লাইনটিকে ঠিক যেমন আছে তেমনটি রেখে দিন -->",
+       "search-ignored-headings": " #<!-- এই লাইনটিকে ঠিক যেমন আছে তেমনটি রেখে দিন --> <pre>\n# যেসব শিরোনাম অনুসন্ধানে অগ্রাহ্য করা হবে।\n# যখনই শিরোনামযুক্ত পাতাটি সূচীভুক্ত হবে, তখনই এখানকার কোন পরিবর্তন বাস্তবায়িত হবে।\n# আপনি একটি নাল/শূন্য সম্পাদনা করে পাতাটিকে বলপূর্বক পুনঃসূচীভুক্ত করতে পারেন।\n# সিনট্যাক্স বা পদক্রম/পদবিন্যাসের নিয়মগুলি নিম্নরূপ:\n#   * অক্ষর থেকে শুরু করে লাইনের শেষ পর্যন্ত সবকিছু হচ্ছে একটি মন্তব্য।\n#   * প্রতিটি অশূন্য লাইন হচ্ছে যে শিরোনামটি অগ্রাহ্য করা হবে, বড় হাতের লেখা এবং অন্যান্য সবকিছু গণনায় ধরে।\nতথ্যসূত্র\nবহিঃসংযোগ\nআরও দেখুন\n#</pre> <!-- এই লাইনটিকে ঠিক যেমন আছে তেমনটি রেখে দিন -->",
        "searchbutton": "অনুসন্ধান",
        "go": "চলো",
        "searcharticle": "চলো",
index 1808595..d58caf3 100644 (file)
        "anontalk": "Kaozeal",
        "navigation": "Merdeiñ",
        "and": "&#32;ha(g)",
-       "qbfind": "Klask",
-       "qbbrowse": "Furchal",
-       "qbedit": "Kemmañ",
-       "qbpageoptions": "Pajenn an dibaboù",
-       "qbmyoptions": "Ma dibaboù",
        "faq": "FAG",
-       "faqpage": "Project:FAG",
        "actions": "Oberoù",
        "namespaces": "Esaouennoù anv",
        "variants": "Adstummoù",
        "edit-local": "Kemmañ an deskrivadur lec'hel",
        "create": "Krouiñ",
        "create-local": "Ouzhpennañ un deskrivadur lec'hel",
-       "editthispage": "Kemmañ ar bajenn-mañ",
-       "create-this-page": "Krouiñ ar bajenn-mañ",
        "delete": "Diverkañ",
-       "deletethispage": "Diverkañ ar bajenn-mañ",
-       "undeletethispage": "Diziverkañ ar bajenn-mañ",
        "undelete_short": "Diziverkañ {{PLURAL:$1|ur c'hemm|$1 kemm}}",
        "viewdeleted_short": "Gwelet {{PLURAL:$1|ur c'hemm diverket|$1 kemm diverket}}",
        "protect": "Gwareziñ",
        "protect_change": "kemmañ",
-       "protectthispage": "Gwareziñ ar bajenn-mañ",
        "unprotect": "Cheñch gwarez",
-       "unprotectthispage": "Cheñch live gwareziñ ar bajenn-mañ",
        "newpage": "Pajenn nevez",
-       "talkpage": "Pajenn gaozeal",
        "talkpagelinktext": "kaozeal",
        "specialpage": "Pajenn dibar",
        "personaltools": "Ostilhoù personel",
-       "articlepage": "Sellet ouzh ar pennad",
        "talk": "Kaozeadenn",
        "views": "Gweladennoù",
        "toolbox": "Ostilhoù",
        "tool-link-userrights": "Kemmañ strolladoù an {{GENDER:$1|implijer|implijerez}}",
        "tool-link-userrights-readonly": "Gwelet strolladoù an {{GENDER:$1|implijer|implijerez}}",
        "tool-link-emailuser": "Kas ur postel d'an {{PLURAL:$1|an implijer-mañ|an implijerez-mañ}}",
-       "userpage": "Pajenn implijer",
-       "projectpage": "Pajenn meta",
        "imagepage": "Gwelet pajenn ar restr",
        "mediawikipage": "Sellet ouzh pajenn ar c'hemennadennoù",
        "templatepage": "Gwelet patrom ar bajenn",
        "rcfilters-savedqueries-unsetdefault": "Diweredekaat dre ziouer",
        "rcfilters-savedqueries-remove": "Dilemel",
        "rcfilters-savedqueries-new-name-label": "Anv",
-       "rcfilters-savedqueries-apply-label": "Krouiñ ul liamm prim",
+       "rcfilters-savedqueries-apply-label": "Enrollañ an arventennoù",
        "rcfilters-savedqueries-cancel-label": "Nullañ",
-       "rcfilters-savedqueries-add-new-title": "Enrollañ ar siloù evel liammoù prim",
+       "rcfilters-savedqueries-add-new-title": "Enrollañ arventennoù ar sil en implij",
        "rcfilters-restore-default-filters": "Assevel ar siloù dre ziouer",
        "rcfilters-clear-all-filters": "Riñsañ an holl siloù",
        "rcfilters-search-placeholder": "Silañ ar c'hemmoù diwezhañ (merdeiñ pe kregiñ da skrivañ)",
index 67075fd..0a3d591 100644 (file)
        "activeusers-intro": "Ovo je spisak korisnika koji su imali neku aktivnost u {{PLURAL:$1|posljednji $1 dan|posljednja $1 dana|posljednjih $1 dana}}.",
        "activeusers-count": "$1 {{PLURAL:$1|izmjena|izmjene|izmjena}} u {{PLURAL:$3|posljednji $3 dan|posljednja $3 dana|posljednjih $3 dana}}",
        "activeusers-from": "Prikaži korisnike koji počinju sa:",
+       "activeusers-groups": "Prikaži korisnike koji su članovi grupa:",
+       "activeusers-excludegroups": "Izuzmi korisnike koji su članovi grupa:",
        "activeusers-noresult": "Nije pronađen korisnik.",
        "activeusers-submit": "Prikaži aktivne korisnike",
        "listgrouprights": "Prava korisničkih grupa",
index 9f34b7b..bcb9f2d 100644 (file)
        "rcfilters-filter-lastrevision-description": "The most recent change to a page.",
        "rcfilters-filter-previousrevision-label": "Earlier revisions",
        "rcfilters-filter-previousrevision-description": "All changes that are not the most recent change to a page.",
+       "rcfilters-filter-excluded": "Excluded",
+       "rcfilters-tag-prefix-namespace": ":$1",
+       "rcfilters-tag-prefix-namespace-inverted": "<strong>:not</strong> $1",
        "rcnotefrom": "Below {{PLURAL:$5|is the change|are the changes}} since <strong>$3, $4</strong> (up to <strong>$1</strong> shown).",
        "rclistfromreset": "Reset date selection",
        "rclistfrom": "Show new changes starting from $2, $3",
index e42ae97..d521606 100644 (file)
        "anontalk": "گب",
        "navigation": "گرأخؤردن",
        "and": "&#32;ؤ",
-       "qbfind": "ىاتن",
-       "qbedit": "دچینواچین",
-       "qbpageoptions": "اي ولگ",
        "faq": "رايج سۊالؤن",
-       "faqpage": "Project:رايج سۊالؤن",
        "actions": "کۊنۊشؤن",
        "namespaces": "نؤمفضاؤن",
        "variants": "گۊىشؤن",
        "view-foreign": "دئن $1ˇ ميئن",
        "edit": "دچينواچين",
        "create": "چاگۊدن",
-       "editthispage": "اي ولگه دچينواچين بکۊن",
-       "create-this-page": "اي ولگه چاکۊن",
        "delete": "حذف",
-       "deletethispage": "اي ولگه پاکأ کۊن.",
-       "undeletethispage": "اي ولگه احيا بکۊن.",
        "protect": "پأسن",
        "protect_change": "تغيير",
-       "protectthispage": "اي ولگه بپا",
        "unprotect": "پأسنه عوضأؤدن",
-       "unprotectthispage": "اي ولگˇ پأسنه عوضأکۊن",
        "newpage": "تازه ولگ",
        "talkpagelinktext": "گب",
        "specialpage": "خاصˇ ولگ",
        "talk": "گب",
        "views": "بدئرؤن",
        "toolbox": "أبزارؤن",
-       "userpage": "کارگيرˇ ولگه دئن",
        "imagepage": "فايلˇ ولگه دئن",
        "categorypage": "جرگه ولگه دئن",
        "otherlanguages": "باخي زوانؤنˇ جي",
        "redirectedfrom": "(مسير عوضاؤدن $1 أجي)",
+       "redirectpagesub": "تغييرمسيرˇ ولگ",
        "redirectto": "تغييرمسير به:",
        "lastmodifiedat": "اي ولگ آخري گرش $1ˇ ميئن ساعت $2 دچينواچين بۊبؤ.",
        "protectedpage": "بپأسه ولگ",
        "right-sendemail": "باخي کارگيرؤنه ايمىل بخسأن",
        "newuserlogpage": "کارگير چاگۊدنˇ سياهه",
        "newuserlogpagetext": "اي ىکته سياهه' کارگير چاگۊدنؤنˇ جي",
+       "action-edit": "اي ولگه دچينواچين بکۊن",
        "action-createaccount": "اي کارگيري حيسابه چاکۊن",
        "action-move-categorypages": "جرگه ولگؤنه جابجا گۊدن",
        "action-block": "اي کارگيرˇ دچينواچينˇ دسفأرسه دبۊد",
        "rcshowhidebots-show": "نۊشؤن دأن",
        "rcshowhidebots-hide": "دۊخۊسان",
        "rcshowhideliu": "$1 ثبتˇ نام بؤده کارگيرؤن",
+       "rcshowhideliu-show": "نۊشؤن دأن",
        "rcshowhideliu-hide": "دۊخۊسان",
        "rcshowhideanons": "$1 ناشناس کارگيرؤن",
        "rcshowhideanons-show": "نۊشؤن دأن",
        "file-anchor-link": "فاىل",
        "filehist": "فاىلˇ تاريخ",
        "filehist-help": "تاريخ/زمتؤنˇ سر کيليک بکۊنين تا اۊ تاريخ/زمتˇ نۊسخه' بىنين.",
+       "filehist-revert": "واگرداني",
        "filehist-current": "ألؤنˇ نۊسخه",
        "filehist-datetime": "تاريخ/زمت",
        "filehist-thumb": "کلˇ أنگۊشتي",
        "listusers": "کارگيرؤنˇ ليست",
        "newpages": "تازه ولگؤن",
        "newpages-username": "کارگيري نؤم:",
+       "move": "جابجا گۊدن",
        "unusedcategoriestext": "اي جرگهٰ‌ن درن ولي هيته وانيويسؤن ىا باخيˇ جرگهٰ‌ن اۊشؤنه کارأنگينن.",
        "suppress": "دۊخۊسانگري",
        "booksources": "کيتابˇ سربسؤن",
        "trackingcategories-desc": "جرگه گۊنجاىشˇ ملاک",
        "hidden-category-category-desc": "جرگه خؤ ولگˇ مئن <code><nowiki>__HIDDENCAT__</nowiki></code> شامل بنه، کي نۊگذارنه کي جرگه خالؤنˇ جعبه پيشفرض ولگؤنˇ مئن نۊشؤن بدأببۊن.",
        "trackingcategories-disabled": "جرگه دئه کار نۊکؤنه",
+       "emailuser": "اي کارگيره ايميل گۊدن",
        "emailuser-title-target": "اي {{GENDER:$1|کارگيره}} ايمىل بخسأن.",
        "usermaildisabled": "نشأنه کارگير ئبه ايمىل خسأنئن.",
        "usermaildisabledtext": "شمه اي ويکي مئن مننين باخي کارگيرؤنه ايمىل بخسأنين",
        "anoncontribs": "مۊشارکتؤن",
        "month": "اي ماه مئن (ؤ دأميشک):",
        "year": "اي سالˇ مئن (ؤ دأميشک):",
+       "sp-contributions-uploads": "جؤرأکشئنؤن",
        "sp-contributions-talk": "گب",
+       "sp-contributions-submit": "وامج",
        "whatlinkshere": "هرچي خال ببؤ ائره",
        "whatlinkshere-title": "ولگؤني گه «$1»ˇ أمرأ خال دأنن",
        "whatlinkshere-page": "ولگ:",
        "tooltip-ca-viewsource": "اي ولگ بپاسأکه.\nتؤنين اينˇ سربسه بينين",
        "tooltip-ca-history": "اي ولگˇ قديمي نۊسخه'ن",
        "tooltip-ca-protect": "أ ولگه بپا",
+       "tooltip-ca-delete": "اي ولگه پاکأ کۊن",
        "tooltip-ca-move": "اي ولگه جابجا گۊدن",
        "tooltip-ca-watch": "اي ولگه علاوه بکۊن تي پىگيري ليسته",
        "tooltip-search": "{{SITENAME}} مئن وامج",
        "tooltip-diff": "تغييرؤني گه شۊمۊ وؤتˇ ميئن بدأينˇ نۊشؤن دأن",
        "tooltip-rollback": "\"پساوگردان\" اي ولگˇ آخري دچينواچينگرˇ دچينواچينؤنه ىکته تنگۊلى أجي خؤنثا کؤنه.",
        "tooltip-summary": "فيچالسه وارد بکۊنين",
+       "pageinfo-header-edits": "تاريخچهٰ دچينواچين گۊدن",
        "pageinfo-header-restrictions": "ولگه پأسن",
+       "pageinfo-robot-index": "مؤجاز",
+       "pageinfo-firstuser": "ولگˇ چاکۊنکس",
        "pageinfo-hidden-categories": "جخۊته {{PLURAL:$1| جرگه|جرگه}} ( $1 )",
        "pageinfo-toolboxlink": "ولگˇ اطلاعات",
        "pageinfo-category-info": "جرگه اطلاعات",
        "namespacesall": "همه",
        "monthsall": "همه",
        "signature": "[[{{ns:user}}:$1|$2]] ([[{{ns:user_talk}}:$1|گب]])",
+       "redirect-submit": "بۊشۊ",
+       "redirect-file": "فايلˇ نؤم",
        "specialpages": "خاصˇ ولگؤن",
        "specialpages-group-login": "ديرين/ثبتˇ نؤم",
        "tag-list-wrapper": "([[Special:Tags|{{PLURAL:$1|تگ|تگؤن}}]]: $2)",
index 7f39185..8cd844c 100644 (file)
        "rcfilters-highlightmenu-help": "Pilihlah warna untuk menyorot atribut ini",
        "rcfilters-filterlist-noresults": "Tidak ada penyaring ditemukan",
        "rcfilters-noresults-conflict": "Hasil tidak ditemukan karena kriteria pencariannya bertentangan",
+       "rcfilters-state-message-subset": "Filter ini tidak akan berpengaruh karena hasilnya disertakan oleh {{PLURAL:$2|filter}} berikut yang lebih luas (coba soroti untuk membedakannya): $1",
        "rcfilters-filtergroup-registration": "Pendaftaran pengguna",
        "rcfilters-filter-registered-label": "Terdaftar",
        "rcfilters-filter-registered-description": "Penyunting masuk log",
        "rcfilters-filter-user-experience-level-newcomer-label": "Pendatang baru",
        "rcfilters-filter-user-experience-level-newcomer-description": "Kurang dari 10 suntingan dan aktivitas selama 4 hari.",
        "rcfilters-filter-user-experience-level-learner-label": "Pelajar",
+       "rcfilters-filter-user-experience-level-learner-description": "Lebih berpengalaman daripada \"Pendatang baru\" namun belum menjadi \"Pengguna berpengalaman\"",
        "rcfilters-filter-user-experience-level-experienced-label": "Pengguna berpengalaman",
+       "rcfilters-filter-user-experience-level-experienced-description": "Lebih dari 30 hari dan 500 suntingan.",
        "rcfilters-filtergroup-automated": "Kontribusi otomatis",
        "rcfilters-filter-bots-label": "Bot",
        "rcfilters-filter-bots-description": "Suntingan yang dibuat dengan perkakas terotomatisasi.",
        "uploadstash-errclear": "Penghapusan berkas gagal.",
        "uploadstash-refresh": "Segarkan daftar berkas.",
        "uploadstash-thumbnail": "lihat miniatur",
+       "uploadstash-exception": "Tidak dapat menyimpan unggahan dalam simpanan ($1): \"$2\".",
        "invalid-chunk-offset": "Ofset potongan tidak valid",
        "img-auth-accessdenied": "Akses ditolak",
        "img-auth-nopathinfo": "PATH_INFO hilang.\nServer Anda tidak diatur untuk melewatkan informasi ini.\nServer tersebut mungkin berbasis CGI dan tidak dapat mendukung img_auth.\nLihat https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:Image_Authorization.",
        "filerevert-submit": "Batalkan",
        "filerevert-success": "'''[[Media:$1|$1]]''' telah dibatalkan ke versi [$4 pada $3, $2]",
        "filerevert-badversion": "Tidak ada versi lokal terdahulu dari berkas ini dengan stempel waktu yang dimaksud.",
+       "filerevert-identical": "Versi berkas sekarang telah identik dengan berkas yang terpilih.",
        "filedelete": "Menghapus $1",
        "filedelete-legend": "Menghapus berkas",
        "filedelete-intro": "Anda akan menghapus berkas '''[[Media:$1|$1]]''' berikut semua riwayatnya.",
        "emailccsubject": "Salinan pesan Anda untuk $1: $2",
        "emailsent": "Surel terkirim",
        "emailsenttext": "Surel Anda telah dikirimkan.",
-       "emailuserfooter": "Surel ini telah {{GENDER:$1|dikirim}} oleh $1 kepada {{GENDER:$2|$2}} dengan fungsi \"{{int:emailuser}}\" pada {{SITENAME}}. Surel {{GENDER:$2|Anda}} akan dikirim langsung kepada {{GENDER:$1|pengirim asal}}, dengan menampilkan alamat surel {{GENDER:$2|Anda}} kepada {{GENDER:$1|mereka}}.",
+       "emailuserfooter": "Surel ini telah {{GENDER:$1|dikirim}} oleh $1 kepada {{GENDER:$2|$2}} dengan fungsi \"{{int:emailuser}}\" pada {{SITENAME}}. Jika {{GENDER:$2|Anda}} membalas surel ini, surel {{GENDER:$2|Anda}} akan dikirim langsung kepada {{GENDER:$1|pengirim asal}}, dengan menampilkan alamat surel {{GENDER:$2|Anda}} kepada {{GENDER:$1|mereka}}.",
        "usermessage-summary": "Tinggalkan pesan sistem.",
        "usermessage-editor": "Penyampai pesan sistem",
        "usermessage-template": "MediaWiki:UserMessage",
        "watchnologin": "Belum masuk log",
        "addwatch": "Tambahkan ke daftar pantauan",
        "addedwatchtext": "\"[[:$1]]\" dan diskusinya telah ditambahkan ke [[Special:Watchlist|watchlist]] Anda.\nPerubahan-perubahan berikutnya pada halaman tersebut dan halaman pembicaraan terkaitnya akan tercantum di sini.",
+       "addedwatchtext-talk": "\"[[:$1]]\" dan halaman terkaitnya telah ditambahkan ke [[Special:Watchlist|daftar pantauan Anda]].",
        "addedwatchtext-short": "Halaman \"$1\" telah ditambahkan ke daftar pantauan Anda.",
        "removewatch": "Hapus dari daftar pantauan",
        "removedwatchtext": "\"[[:$1]]\" dan diskusinya telah dihapus dari [[Special:Watchlist|watchlist]] Anda.",
+       "removedwatchtext-talk": "\"[[:$1]]\" dan halaman terkaitnya telah dihapus dari [[Special:Watchlist|daftar pantauan Anda]].",
        "removedwatchtext-short": "Halaman \"$1\" telah dihapus dari daftar pantauan Anda.",
        "watch": "Pantau",
        "watchthispage": "Pantau halaman ini",
        "special-characters-group-thai": "Thai",
        "special-characters-group-lao": "Lao",
        "special-characters-group-khmer": "Khmer",
+       "special-characters-group-canadianaboriginal": "Aborigin Kanada",
        "special-characters-title-endash": "en dash",
        "special-characters-title-emdash": "em dash",
        "special-characters-title-minus": "tanda kurang",
        "revid": "revisi $1",
        "pageid": "ID halaman $1",
        "rawhtml-notallowed": "Tag &lt;html&gt; tidak dapat digunakan di luar halaman normal.",
+       "gotointerwiki": "Meninggalkan {{SITENAME}}",
        "gotointerwiki-invalid": "Judul yang ditentukan tidak sah",
+       "gotointerwiki-external": "Anda akan meninggalkan {{SITENAME}} untuk mengunjungi [[$2]], yang merupakan situs lain.\n\n'''[$1 Lanjut ke $1]'''",
+       "undelete-cantedit": "Anda tidak dapat membatalkan penghapusan halaman ini karena Anda tidak dapat menyunting halaman ini.",
+       "undelete-cantcreate": "Anda tidak dapat membatalkan penghapusan halaman ini karena tidak ada halaman yang memiliki judul ini dan Anda tidak diizinkan membuat halaman ini.",
        "pagedata-title": "Data halaman",
+       "pagedata-text": "Halaman ini memberikan antarmuka data ke halaman. Silakan masukkan judul halaman di URL, menggunakan sintaks subhalaman.\n* Negosiasi konten diatur berdasarkan header \"Accept\" klien Anda. Ini berarti halaman data akan diformat berdasarkan format yang dimintai klien Anda.",
+       "pagedata-not-acceptable": "Tidak ditemukan format yang sesuai. Jenis MIME yang didukung: $1",
        "pagedata-bad-title": "Judul tidak sah: $1"
 }
index 5657f4e..21ea0bc 100644 (file)
        "rcfilters-filter-user-experience-level-newcomer-label": "新規利用者",
        "rcfilters-filter-user-experience-level-newcomer-description": "登録から4日以内、かつ10編集以下の利用者",
        "rcfilters-filter-user-experience-level-learner-label": "初学者",
-       "rcfilters-filter-user-experience-level-learner-description": "ã\80\8cæ\96°è¦\8få\8f\82å\8a 者」よりも編集経験があり、「経験者」より編集経験が少ない利用者",
+       "rcfilters-filter-user-experience-level-learner-description": "ã\80\8cæ\96°è¦\8få\88©ç\94¨者」よりも編集経験があり、「経験者」より編集経験が少ない利用者",
        "rcfilters-filter-user-experience-level-experienced-label": "経験者",
        "rcfilters-filter-user-experience-level-experienced-description": "30日以上、かつ500編集以上の活動履歴がある利用者",
        "rcfilters-filtergroup-automated": "自動編集",
        "rcfilters-filter-minor-description": "編集者が細部の編集とマークしたもの。",
        "rcfilters-filter-major-label": "細部でない編集",
        "rcfilters-filter-major-description": "細部とマークされていない編集。",
-       "rcfilters-filtergroup-watchlist": "ウォッチリストに追加されているページ",
-       "rcfilters-filter-watchlist-watched-label": "ウォッチリストに登録されたページ",
+       "rcfilters-filtergroup-watchlist": "ウォッチリストに登録されているページ",
+       "rcfilters-filter-watchlist-watched-label": "ウォッチリスト登録済",
        "rcfilters-filter-watchlist-watched-description": "ウォッチリストに登録されているページの変更",
-       "rcfilters-filter-watchlist-watchednew-label": "ウォッチリストのページの新しい変更",
-       "rcfilters-filter-watchlist-watchednew-description": "Changes to Watchlisted pages you haven't visited since the changes occurred.",
-       "rcfilters-filter-watchlist-notwatched-label": "ウォッチリストに登録されていないページ",
+       "rcfilters-filter-watchlist-watchednew-label": "ウォッチリスト登録済(新しい変更)",
+       "rcfilters-filter-watchlist-watchednew-description": "ウォッチリストに登録されていて、前回訪れた後に更新があったページ。",
+       "rcfilters-filter-watchlist-notwatched-label": "ウォッチリスト登録外",
        "rcfilters-filter-watchlist-notwatched-description": "ウォッチリストに登録されているページ以外の全ての変更。",
        "rcfilters-filtergroup-changetype": "変更の種類",
        "rcfilters-filter-pageedits-label": "ページの編集",
index 3a43d1d..875a0db 100644 (file)
        "mergehistory-invalid-destination": "Kaca tujuan kudu asesirah sing sah.",
        "mergehistory-autocomment": "Nggabung [[:$1]] menyang [[:$2]]",
        "mergehistory-comment": "Nggabung [[:$1]] menyang [[:$2]]: $3",
-       "mergehistory-same-destination": "Jeneng kaca sumber lan tujuan ora kena padha",
+       "mergehistory-same-destination": "Kaca sumber lan tujuan ora kena padha",
        "mergehistory-reason": "Alesan:",
        "mergelog": "Gabung log",
        "revertmerge": "Wurung gabung",
        "timezoneregion-pacific": "Samodra Pasifik",
        "allowemail": "Idinaké panganggo liyané ngirimi layang-èl",
        "prefs-searchoptions": "Golèk",
-       "prefs-namespaces": "Ruang jeneng / Bilik jeneng",
+       "prefs-namespaces": "Mandala aran",
        "default": "baku",
        "prefs-files": "Barkas",
        "prefs-custom-css": "CSS priangga",
        "right-move-subpages": "Pindhahaké kaca lan kabèh anak-kacané",
        "right-move-rootuserpages": "Ngalih kaca panganggo oyod",
        "right-move-categorypages": "Lih kaca kategori",
-       "right-movefile": "Mindhah berkas",
+       "right-movefile": "Lih barkas",
        "right-suppressredirect": "Aja nggawé pangalihan saka kaca sing lawas yèn mindhah sawijining kaca",
        "right-upload": "Unggah barkas",
        "right-reupload": "Tindhihana sawijining berkas sing wis ana",
        "action-block": "malang panganggo iki mbesut",
        "action-protect": "owahi tataran rereksané kaca iki",
        "action-rollback": "gelis mbalèkaké suntingané panganggo pungkasan nèng sawijining saca",
-       "action-import": "impor kaca iki saka wiki liya",
+       "action-import": "impor kaca saka wiki liyané",
        "action-importupload": "impor kaca iki saka pamunggahan berkas",
        "action-patrol": "nandhani besutan wong liya yèn wis kapriksa",
        "action-autopatrol": "nandhani besutané panjenengan dhéwé yèn wis kapriksa",
        "action-unwatchedpages": "deleng pratélan kaca sing ingawasan",
        "action-mergehistory": "nggabungaké sajarah kaca iki",
        "action-userrights": "besut kabèh hak panganggo",
-       "action-userrights-interwiki": "ngowahi hak aksès saka panganggo ing wiki liya",
+       "action-userrights-interwiki": "besut hak aksès panganggo ing wiki liyané",
        "action-siteadmin": "ngunci utawa mbukak kunci basis data",
        "action-sendemail": "kirim layang-èl",
        "action-editmyoptions": "besut pilalané panjenengan",
        "recentchanges-page-removed-from-category-bundled": "[[:$1]] dibusak saka kategori, [[Special:WhatLinksHere/$1|kaca iki kalebu ing njeroné kaca liyané]]",
        "autochange-username": "Salin otomatis MediaWiki",
        "upload": "Unggah barkas",
-       "uploadbtn": "Unggahna berkas",
-       "reuploaddesc": "Bali ing formulir pamotan",
+       "uploadbtn": "Unggah barkas",
+       "reuploaddesc": "Wurung ngunggah lan bali nyang formulir unggahan",
        "upload-tryagain": "Kirim déskripsi berkas sing wis diowah",
        "uploadnologin": "Durung mlebu log",
        "uploadnologintext": "Mangga $1 saperlu ngunggah barkas.",
        "upload_directory_read_only": "Dhirèktori pangunggahan ($1) ora bisa ditulis déning paladèn jaringan.",
        "uploaderror": "Kaluputan pangunggahan berkas",
        "upload-recreate-warning": "'''Pèngetan: Berkas mawa jeneng kuwi wis dibusak utawa disingkiraké.'''\n\nLog pambusakan lan panyingkiran saka kaca iki sumadhiya nèng kéné:",
-       "uploadtext": "Anggé formulir ing ngandhap punika kanggé nginggahaké gambar.\nKanggé mirsani utawi madosi gambar ingkang sampun dipununggah sakdèrèngipun pigunakaken [[Special:FileList|dhaftar berkas sing wis diunggah]], gambar ingkang dipununggah ulang ugi kadhaftar ing [[Special:Log/upload|log pangunggahan]], pambusakan ing [[Special:Log/delete|Log pambusakan]].\n\nKanggé nyertakaken gambar ing satunggiling kaca, pigunakaken pranala salah setunggal saking format ing ngandhap punika:\n* '''<code><nowiki>[[</nowiki>{{ns:file}}<nowiki>:Berkas.jpg]]</nowiki></code>''' kanggé migunakaken versi pepak gambar\n* '''<code><nowiki>[[</nowiki>{{ns:file}}<nowiki>:Berkas.png|200px|thumb|left|tèks alt]]</nowiki></code>''' kanggé migunakaken gambar wiyaripun 200 piksel ing kothak ing sisih kiwa kanthi 'tèks alt' minangka panjelasan\n* '''<code><nowiki>[[</nowiki>{{ns:media}}<nowiki>:Berkas.ogg]]</nowiki></code>''' kanggé nggandhèng langsung dhumateng gambar tanpi nampilaké gambar",
+       "uploadtext": "Anggonen formulir ngisor iki saperlu ngunggah barkas.\nKanggo ndeleng utawa nggolèki barkas sing wis diunggah sadurungé, panjenengan menyanga [[Special:FileList|pratélan barkas unggahan]]. Barkas unggahan ulang uga kacathet ing [[Special:Log/upload|log unggah]], déné barkas busakan ing [[Special:Log/delete|log busak]].\n\nKanggo muwuhi barkas ing kaca, anggonen pranala kanthi formulir ing ngisor iki, pilih salah siji:\n* <strong><code><nowiki>[[</nowiki>{{ns:file}}<nowiki>:File.jpg]]</nowiki></code></strong> saperlu nganggo barkasé kanthi vèrsi sing wutuh\n* <strong><code><nowiki>[[</nowiki>{{ns:file}}<nowiki>:File.png|200px|thumb|left|alt text]]</nowiki></code></strong> saperlu nganggo barkasé kanthi amba 200 piksel déné ana ing njeron kothak lan kapacak ing sisih kiwané kaca mawa \"alt text\" minangka katerangané\n* <strong><code><nowiki>[[</nowiki>{{ns:media}}<nowiki>:File.ogg]]</nowiki></code></strong> saperlu nggayutaké langsung barkasé tanpa mitontonaké barkasé dhéwé",
        "upload-permitted": "{{PLURAL:$2|Jinis}} barkas sing diidinaké: $1.",
        "upload-preferred": "{{PLURAL:$2|Jinis}} barkas sing diprayogakaké: $1.",
        "upload-prohibited": "{{PLURAL:$2|Jinis}} barkas sing dilarang: $1.",
        "filetype-badmime": "Berkas mawa tipe MIME \"$1\" ora pareng diunggahaké.",
        "filetype-bad-ie-mime": "Ora bisa ngunggahaké berkas iki amarga Internet Explorer ndhétèksi minangka \"$1\", sing ora diidinaké lan minangka tipe berkas sing nduwèni potènsi mbebayani.",
        "filetype-unwanted-type": "'''\".$1\"''' klebu jenis berkas sing ora diidinaké.\nLuwih becik {{PLURAL:$3|jinis berkas|Jinis-jinis berkas}} $2.",
-       "filetype-banned-type": "'''\".$1\"''' {{PLURAL:$4|dudu jinis berkas sing dililakaké|dudu jinis berkas sing dililakaké}}.\n{{PLURAL:$3|Berkas|Berkas}} sing dililakaké $2.",
+       "filetype-banned-type": "<strong>\".$1\"</strong> {{PLURAL:$4|dudu jinis barkas sing diidinaké}}.\n{{PLURAL:$3|Jinis barkas}} sing diidinaké $2.",
        "filetype-missing": "Berkas ini ora duwé ekstènsi (contoné \".jpg\").",
        "empty-file": "Barkas sing panjenengan kirim kosong.",
        "file-too-large": "Barkas sing panjenengan kirim kagedhèn.",
-       "filename-tooshort": "Jeneng berkas kacendhèken.",
+       "filename-tooshort": "Jeneng barkas kecendhèken.",
        "filetype-banned": "Jinis berkas iki dilarang.",
        "verification-error": "Berkas iki ora lulus pangesahan.",
        "hookaborted": "Owahan sing panjenengan ayahi diwurungaké déning èkstènsi.",
-       "illegal-filename": "Jeneng berkas ora dililakaké.",
+       "illegal-filename": "Jeneng barkas ora diidinaké.",
        "overwrite": "Nibani berkas sing wis ana ora dililakaké.",
        "unknown-error": "Ana masalah sing ora dingertèni.",
        "tmp-create-error": "Ora bisa nggawé berkas sawetara.",
        "file-thumbnail-no": "Jeneng berkas diwiwiti kanthi <strong>$1</strong>. Katoné berkas iki sawijining gambar mawa ukuran sing dicilikaké <em>(thumbnail)</em>.\nYèn panjenengan kagungan vèrsi mawa résolusi kebak saka gambar iki, mangga diunggahaké. Yèn ora, tulung jeneng berkas diganti.",
        "fileexists-forbidden": "Sawijining berkas mawa jeneng iki wis ana, lan ora bisa ditindhes.\nYèn panjenengan isih arep ngunggahaké berkas panjenengan, supaya\nmbalik lan gunakna jeneng liya.\n[[File:$1|thumb|center|$1]]",
        "fileexists-shared-forbidden": "Wis ana berkas liyané mawa jeneng sing padha ing gudhang berkas sing dianggo bebarengan.\nYèn isih ngersakaké ngunggahaké, mangga berkas diunggahaké manèh mawa jeneng liya. [[File:$1|thumb|center|$1]]",
-       "file-exists-duplicate": "Berkas iki duplikat utawa padha karo {{PLURAL:$1|berkas|berkas-berkas}} ing ngisor:",
+       "file-exists-duplicate": "Barkas iki dhuplikaté {{PLURAL:$1|barkas}} iki:",
        "file-deleted-duplicate": "Sawijining berkas persis berkas iki ([[:$1]]) wis tau dibusak. Mangga panjenengan priksani sajarah pambusakan berkas kasebut sadurungé nerusaké ngunggahaké berkas kuwi manèh.",
        "uploadwarning": "Pèngetan pangunggahan berkas",
        "uploadwarning-text": "Mangga owah katrangan berkas nèng ngisor lan coba manèh.",
        "php-uploaddisabledtext": "Pangunggahan berkas dipatèni ing PHP.\nMangga priksa panyetèlan pangunggahan berkas.",
        "uploadscripted": "Berkas iki ngandhut HTML utawa kode sing bisa diinterpretasi salah déning panjlajah wèb.",
        "uploadvirus": "Berkas iki ngamot virus! Détil: $1",
-       "uploadjava": "Berkas kuwi berkas ZIP sing kaisi berkas .class Java.\nNgungga berkas Java ora dililakaké amarga bisa nyebabaké ngluwèhaké wates kamanan.",
+       "uploadjava": "Barkasé barkas ZIP sing ngemu barkas .class Java.\nNgunggah barkas Java ora diidinaké amarga bisa njalari dilanggaré watesan kaamanan.",
        "upload-source": "Barkas sumber",
-       "sourcefilename": "Jeneng berkas sumber:",
+       "sourcefilename": "Jeneng barkas sumber:",
        "sourceurl": "URL sumber:",
-       "destfilename": "Jeneng berkas sing dituju",
+       "destfilename": "Jeneng barkas tujuan:",
        "upload-maxfilesize": "Ukuran maksimal berkas: $1",
-       "upload-description": "Katrangan berkas",
+       "upload-description": "Katerangan barkas",
        "upload-options": "Opsi pangundhuhan",
        "watchthisupload": "Awasana berkas iki",
        "filewasdeleted": "Sawijining berkas mawa jeneng iki wis tau diunggahaké lan sawisé dibusak.\nMangga priksanen $1 sadurungé ngunggahaké berkas iku manèh.",
        "upload-form-label-infoform-date": "Tanggal",
        "backend-fail-stream": "Ora bisa milikaké berkas \"$1\".",
        "backend-fail-backup": "Ora bisa nyadangaké berkas \"$1\".",
-       "backend-fail-notexists": "Berkas $1 ora ana.",
+       "backend-fail-notexists": "Barkas $1 ora ana.",
        "backend-fail-hashes": "Ora bisa ngéntukaké has berkas kanggo mbandingaké.",
        "backend-fail-notsame": "Berkas nonidèntik wis ana nèng \"$1\".",
        "backend-fail-invalidpath": "\"$1\" dudu jurusan nyimpen sing sah.",
        "lockmanager-fail-svr-acquire": "Ora bisa ngentokaké gembok nèng sasana $1.",
        "lockmanager-fail-svr-release": "Ora bisa nguculaké gembok neng sasana $1.",
        "zip-file-open-error": "Ana masalah nalika mbukak barkas kanggo pamriksan ZIP.",
-       "zip-wrong-format": "Berkas sing diawèhaké dudu berkas ZIP.",
+       "zip-wrong-format": "Barkas sing diisèkaké dudu barkas ZIP.",
        "zip-bad": "Berkas rusak utawa berkas ZIP sing ora bisa diwaca.\nKuwi ora bisa kapriksa kanthi patut kanggo kamanan.",
        "zip-unsupported": "Berkasé kuwi berkas ZIP sing nganggo piranti ZIP sing ora kasengkuyung déning MediaWiki.\nKuwi ora bisa kapriksa kanthi patut kanggo kamanan.",
        "uploadstash": "Unggah pandhelikan",
        "filehist-nothumb": "Ora ana miniatur",
        "filehist-user": "Panganggo",
        "filehist-dimensions": "Alang ujur",
-       "filehist-filesize": "Gedhené berkas",
+       "filehist-filesize": "Gedhené barkas",
        "filehist-comment": "Tanggapan",
        "imagelinks": "Panggunané barkas",
        "linkstoimage": "{{PLURAL:$1|Kaca|$1 kaca}} ngisor iki nggayut barkas iki:",
        "linkstoimage-more": "Luwih saka $1 {{PLURAL:$1|kaca|kaca-kaca}} nduwèni pranala menyang berkas iki.\nDhaftar ing ngisor nuduhaké {{PLURAL:$1|kaca pisanan kanthi pranala langsung|$1 kaca kanthi pranala langsung}} menyang berkas iki.\n[[Special:WhatLinksHere/$2|dhaftar pepak]] uga ana.",
        "nolinkstoimage": "Ora ana kaca sing nggayut menyang barkas iki.",
        "morelinkstoimage": "Ndeleng [[Special:WhatLinksHere/$1|luwih akèh pranala]] menyang berkas iki.",
-       "linkstoimage-redirect": "$1 (alihan berkas) $2",
+       "linkstoimage-redirect": "$1 (alihan barkas) $2",
        "duplicatesoffile": "{{PLURAL:$1|berkas ing ngisor arupa duplikat|$1 berkas ing ngisor arupa duplikat}} saka berkas iki ([[Special:FileDuplicateSearch/$2|luwih rinci]]):",
        "sharedupload": "Barkas iki saka $1 lan bisa kanggo proyèk-proyèk liyané.",
        "sharedupload-desc-there": "Berkas iki asal saka $1 lan bisa dipigunakaké déning proyèk liya.\nMangga pirsani [$2 kaca dhèskripsi berkas] kanggo informasi sabanjuré.",
        "sharedupload-desc-here": "Barkas iki saka $1 lan kena kanggo proyèk liya.\nPanyandraning [$2 kaca panyandra barkas]é kapacak ing ngisor.",
        "sharedupload-desc-edit": "Berkas iki saka $1 lan mungkin dianggo nèng proyèk liya.\nMungkin Sampéyan pingin nyunting katrangan nèng [$2 kaca katrangan berkasé] nèng kono.",
        "sharedupload-desc-create": "Berkas iki saka $1 lan mungkin dianggo nèng proyèk liya.\nMungkin Sampéyan pingin nyunting katrangan nèng [$2 kaca katrangan berkasé] nèng kono.",
-       "filepage-nofile": "Ora ana berkas nganggo jeneng iki.",
+       "filepage-nofile": "Ora ana barkas kanthi jeneng kaya mangkéné.",
        "filepage-nofile-link": "Ora ana berkas nganggo jeneng iki, nanging panjenengan bisa [$1 ngunggahaké].",
        "uploadnewversion-linktext": "Unggahna vèrsi sing luwih anyar tinimbang gambar iki",
        "shared-repo-from": "saka $1",
        "shared-repo": "sawijining panyimpenan kanggo bebarengan",
        "upload-disallowed-here": "Sampéyan ora kena ngeblegi barkas iki.",
        "filerevert": "Balèkna $1",
-       "filerevert-legend": "Balèkna berkas",
+       "filerevert-legend": "Pulihaké barkas",
        "filerevert-intro": "Panjenengan mbalèkaké '''[[Media:$1|$1]]''' menyang [vèrsi $4 ing $3, $2].",
        "filerevert-comment": "Alesan:",
        "filerevert-defaultcomment": "Dibalèkaké menyang vèrsi ing $2, $1 ($3)",
        "filerevert-badversion": "Ora ana vèrsi lokal sadurungé saka berkas iki mawa stèmpel wektu sing dikarepaké.",
        "filerevert-identical": "Vèrsi barkasé sing saiki padha plek karo sing dipilih.",
        "filedelete": "Mbusak $1",
-       "filedelete-legend": "Mbusak berkas",
+       "filedelete-legend": "Busak barkas",
        "filedelete-intro": "Panjenengan bakal mbusak berkas '''[[Media:$1|$1]]''' sekaliyan kabèh riwayaté.",
        "filedelete-intro-old": "Panjenengan mbusak vèrsi '''[[Media:$1|$1]]''' per [$4 $3, $2].",
        "filedelete-comment": "Alesan:",
        "filedelete-reason-dropdown": "*Alesan pambusakan\n** Nglanggar hak cipta\n** Berkas duplikat",
        "filedelete-edit-reasonlist": "Besut alesané mbusak",
        "filedelete-maintenance": "Pambusakan lan pambalikan berkas kanggo sawetara dipatèni salawas ana pangruwatan.",
-       "filedelete-maintenance-title": "Ora bisa mbusak berkas",
+       "filedelete-maintenance-title": "Ora bisa mbusak barkas",
        "mimesearch": "Panggolèkan MIME",
        "mimesearch-summary": "Kaca iki nyedyaké fasilitas nyaring berkas miturut tipe MIME-né. Lebokna: contenttype/subtype, contoné <code>image/jpeg</code>.",
        "mimetype": "Tipe MIME:",
        "protect-expiry-indefinite": "salawasé",
        "protect-cascade": "Reksa kaca sing kalebu ing kaca iki (rereksan runtun).",
        "protect-cantedit": "Panjenengan ora bisa ngowahi tataran rereksan kaca iki amarga panjenengan ora kawogan mbesut.",
-       "protect-othertime": "Wektu liya:",
-       "protect-othertime-op": "wektu liya",
+       "protect-othertime": "Wektu liya:",
+       "protect-othertime-op": "wektu liya",
        "protect-existing-expiry": "Wektu kadaluwarsa saiki: $3, $2",
-       "protect-otherreason": "Alesan liya/tambahan:",
-       "protect-otherreason-op": "Alesan liya",
+       "protect-otherreason": "Alesan tambahan/liyané:",
+       "protect-otherreason-op": "Alesan liya",
        "protect-dropdown": "*Alesan umum pangreksa\n** Vandalisme makaping-kaping\n** Spam makaping-kaping\n** Perang besutan ora prodhuktif\n** Kaca sing dhuwur trafiké",
        "protect-edit-reasonlist": "Besut alesané ngreksa",
        "protect-expiry-options": "1 jam:1 hour,1 dina:1 day,1 minggu:1 week,2 minggu:2 weeks,1 wulan:1 month,3 wulan:3 months,6 wulan:6 months,1 taun:1 year,tanpa wates:infinite",
        "immobile-target-page": "Ora bisa mindhahaké menyang irah-irahan tujuan kasebut.",
        "bad-target-model": "Tujuan sing diarepaké nganggo gagrag isi sing béda. Ora bisa ngganti $1 dadi $2.",
        "imagenocrossnamespace": "Ora bisa mindhahaké gambar menyang bilik nama non-gambar",
-       "nonfile-cannot-move-to-file": "Ora bisa mindhahaké non-berkas nèng bilik jeneng berkas",
+       "nonfile-cannot-move-to-file": "Ora bisa ngalih non-barkas nyang mandala aran barkas.",
        "imagetypemismatch": "Èkstènsi anyar berkas ora cocog karo jenisé",
-       "imageinvalidfilename": "Jeneng berkas tujuan ora sah",
+       "imageinvalidfilename": "Jeneng barkas tujuan ora trep.",
        "fix-double-redirects": "Dandani kabèh pangalihan gandha sing tumuju marang irah-irahan asli",
        "move-leave-redirect": "Ungkur kaca alihan",
        "protectedpagemovewarning": "'''Pènget:''' Kaca iki wis dikunci dadi mung panganggo sing nduwé hak aksès pangurus baé sing bisa mindhahaké.\nCathetan entri pungkasan disadiakaké ing ngisor kanggo referensi:",
        "imagelisttext": "Ing ngisor iki kapacak daftar '''$1''' {{PLURAL:$1|berkas|berkas}} sing diurutaké $2.",
        "newimages-summary": "Kaca astaméwa utawa kusus iki nuduhaké daftar berkas anyar dhéwé sing diunggahaké.",
        "newimages-legend": "Filter",
-       "newimages-label": "Jeneng berkas (utawa sapérangan seka jeneng berkas):",
+       "newimages-label": "Jeneng barkas (utawa pérangané):",
        "noimages": "Ora ana sing dideleng.",
        "ilsubmit": "Golek",
        "bydate": "miturut tanggal",
        "exif-gpsdifferential": "Korèksi diférènsial GPS",
        "exif-jpegfilecomment": "Tanggepan berkas JPEG",
        "exif-keywords": "Tembung kunci",
-       "exif-worldregioncreated": "Dhaèrahing donya ing endi gambar dijupuk",
-       "exif-countrycreated": "Nagara ing endi gambar dijupuk",
-       "exif-countrycodecreated": "Kodhe kanggo nagara ing endi gambar dijupuk",
+       "exif-worldregioncreated": "Tlatah ing donya anggoné gambaré dijupuk",
+       "exif-countrycreated": "Nagara anggoné gambaré dijupuk",
+       "exif-countrycodecreated": "Kodhe nagara anggoné gambaré dijupuk",
        "exif-provinceorstatecreated": "Propinsi utawa nagara bagéyan ing endi gambar dujupuk",
-       "exif-citycreated": "Kutha ing endi gambar dijupuk",
-       "exif-sublocationcreated": "Dhaérahing kutha ing endi gambar dijupuk",
+       "exif-citycreated": "Kutha anggoné gambaré dijupuk",
+       "exif-sublocationcreated": "Laladan ing kutha anggoné gambaré dijupuk",
        "exif-worldregiondest": "Wewengkon dunya katampilaké",
        "exif-countrydest": "Nagara katampilaké",
        "exif-countrycodedest": "Kodhe nagara katampilaké",
        "imgmultigo": "Golèk!",
        "imgmultigoto": "Lungaa menyang kaca $1",
        "img-lang-default": "(basa gawan)",
-       "img-lang-info": "Dadekna gambar iki ing $1, $2",
-       "img-lang-go": "Nuju",
+       "img-lang-info": "Olah gambar iki ing $1. $2",
+       "img-lang-go": "Mangkat",
        "ascending_abbrev": "unggah",
        "descending_abbrev": "mudhun",
        "table_pager_next": "Kaca sabanjuré",
        "redirect-not-exists": "Nilai ora ditemokaké",
        "fileduplicatesearch": "Golèk berkas duplikat",
        "fileduplicatesearch-summary": "Golèk duplikat berkas adhedhasar biji hash-é.",
-       "fileduplicatesearch-filename": "Jeneng berkas:",
+       "fileduplicatesearch-filename": "Jeneng barkas:",
        "fileduplicatesearch-submit": "Golèk",
        "fileduplicatesearch-info": "$1 × $2 piksel<br />Ukuran berkas: $3<br />Tipe MIME: $4",
        "fileduplicatesearch-result-1": "Berkas \"$1\" ora duwé duplikat idèntik.",
        "fileduplicatesearch-result-n": "Berkas \"$1\" ora ndarbèni {{PLURAL:$2|1 duplikat idèntik|$2 duplikat idèntik}}.",
-       "fileduplicatesearch-noresults": "Ora ana berkas mawa jeneng \"$1\" ditemokaké.",
+       "fileduplicatesearch-noresults": "Ora tinemu barkas kanthi jeneng \"$1\".",
        "specialpages": "Kaca mirunggan",
        "specialpages-note-top": "Katrangan",
        "specialpages-note": "* Kaca mirunggan sedhengan.\n* <span class=\"mw-specialpagerestricted\">Kaca mirunggan winatesan.</span>",
index 79281bf..07bf86a 100644 (file)
        "anontalk": "चर्चा पान",
        "navigation": "सुचालन",
        "and": "&#32;आणि",
-       "qbfind": "शोधा",
-       "qbbrowse": "न्याहाळा",
-       "qbedit": "संपादन",
-       "qbpageoptions": "हे पान",
-       "qbmyoptions": "माझी पाने",
        "faq": "नेहमी विचारण्यात येणारे प्रश्न",
-       "faqpage": "Project:प्रश्नावली",
        "actions": "क्रिया",
        "namespaces": "नामविश्वे",
        "variants": "चले(व्हेरियंट्स)",
        "edit-local": "स्थानिक वर्णन संपादा",
        "create": "तयार करा",
        "create-local": "स्थानिक वर्णन जोडा",
-       "editthispage": "हे पृष्ठ संपादित करा",
-       "create-this-page": "हे पान तयार करा",
        "delete": "वगळा",
-       "deletethispage": "हे पान काढून टाका",
-       "undeletethispage": "गाळलेला लेख पुर्ववत् करा",
        "undelete_short": "पुनर्स्थापन {{PLURAL:$1|एक संपादन|$1 संपादने}}",
        "viewdeleted_short": "{{PLURAL:$1|एक वगळलेले संपादन|$1 वगळलेली संपादने}}  पहा.",
        "protect": "सुरक्षित करा",
        "protect_change": "बदला",
-       "protectthispage": "हे पान सुरक्षित करा",
        "unprotect": "सुरक्षितता बदला",
-       "unprotectthispage": "या पानाची सुरक्षितता बदला",
        "newpage": "नवीन पृष्ठ",
-       "talkpage": "या पानाबद्दल चर्चा करा",
        "talkpagelinktext": "चर्चा",
        "specialpage": "विशेष पृष्ठ",
        "personaltools": "वैयक्तिक साधने",
-       "articlepage": "लेख पृष्ठ",
        "talk": "चर्चा",
        "views": "दृष्ये",
        "toolbox": "साधने",
        "tool-link-userrights": "{{GENDER:$1|वापरकर्ता}} गट बदला",
        "tool-link-emailuser": "{{GENDER:$1|सदस्याला}} विपत्र पाठवा",
-       "userpage": "सदस्य पृष्ठ",
-       "projectpage": "प्रकल्प पान पहा",
        "imagepage": "संचिका पृष्ठ पहा",
        "mediawikipage": "संदेश पान पहा",
        "templatepage": "साच्याचे पृष्ठ पहा.",
        "post-expand-template-argument-warning": "<strong>ईशारा:</strong> या पानावर असा एकतरी साचा आहे जो वाढविल्यास खूप मोठा होईल.\nअसे साचे वगळण्यात आलेले आहेत.",
        "post-expand-template-argument-category": "अशी पाने ज्यांच्यामध्ये साचे वगळलेले आहेत",
        "parser-template-loop-warning": "साचा चक्र मिळाले: [[$1]]",
+       "template-loop-category-desc": "या पानात एक साचा वलय आहे, म्हणजे, तो साचा जो स्वतःसच वारंवार हाक देतो.",
        "parser-template-recursion-depth-warning": "साचा पुनरावर्तन खोली मर्यादा ओलांडली ($1)",
        "language-converter-depth-warning": "भाषा रुपांतरण खोली मर्यादा ओलांडली ($1)",
        "node-count-exceeded-category": "लेख जेथे निस्पंद-गणना(नोड-काऊंट) पार केल्या गेला",
index f10cdb6..fb9de03 100644 (file)
        "anontalk": "ဆွေးနွေးရန်",
        "navigation": "အ​ညွှန်း​",
        "and": "&#32;နှင့်",
-       "qbfind": "ရှာပါ",
-       "qbbrowse": "ရှာဖွေလှန်လှောရန်",
-       "qbedit": "ပြင်ဆင်ရန်",
-       "qbpageoptions": "ဤစာမျက်နှာ",
-       "qbmyoptions": "ကျွန်ုပ် စာမျက်နှာများ",
        "faq": "မေးလေ့ရှိကြသည်များ",
-       "faqpage": "Project:မေးလေ့ရှိကြသည်များ",
        "actions": "ဆောင်ရွက်ချက်များ",
        "namespaces": "အမည်ညွှန်းများ",
        "variants": "အမျိုးမျိုးအပြားပြား",
        "edit-local": "ဒေသတွင်း ဖော်ပြချက် ပြင်ဆင်ရန်",
        "create": "စတင်ရေးသားရန်",
        "create-local": "ဒေသတွင်း ဖော်ပြချက် ထည့်ရန်",
-       "editthispage": "ဤစာမျက်နှာကို ပြင်ရန်",
-       "create-this-page": "ဤစာမျက်နှာကို စတင်ရေးသားရန်",
        "delete": "ဖျက်​ပါ​",
-       "deletethispage": "ဤစာမျက်နှာဖျက်ပါ",
-       "undeletethispage": "ဤစာမျက်နှာကို မဖျက်တော့ရန်",
        "undelete_short": "{{PLURAL:$1|တည်းဖြတ်မှုတစ်ခု|တည်းဖြတ်မှု $1 ခုတို့}}ကို မဖျက်တော့ရန်",
        "viewdeleted_short": "{{PLURAL:$1|ဖျက်လိုက်သည့်တည်းဖြတ်မှုတစ်ခု|ဖျက်လိုက်သည့် တည်းဖြတ်မှု $1 ခု}}ကို ကြည့်ရန်",
        "protect": "ကာကွယ်ပါ",
        "protect_change": "ပြောင်းလဲရန်",
-       "protectthispage": "ဤစာမျက်နှာကို ကာကွယ်ရန်",
        "unprotect": "ကာကွယ်ခြင်းကို ပြောင်းလဲရန်",
-       "unprotectthispage": "စာမျက်နှာ ကာကွယ်ခြင်းကို ပြောင်းလဲရန်",
        "newpage": "စာမျက်နှာအသစ်",
-       "talkpage": "ဆွေးနွေးရန်",
        "talkpagelinktext": "ဆွေးနွေး",
        "specialpage": "အထူး စာမျက်နှာ",
        "personaltools": "ကိုယ်ပိုင် ကိရိယာများ",
-       "articlepage": "မာတိကာ ကြည့်ရန်",
        "talk": "ဆွေးနွေးချက်",
        "views": "အမြင်ပုံစံများ",
        "toolbox": "ကိရိယာများ",
        "tool-link-userrights": "{{GENDER:$1|အသုံးပြုသူ}}အုပ်စုများကို ပြောင်းလဲရန်",
        "tool-link-userrights-readonly": "{{GENDER:$1|အသုံးပြုသူ}}အုပ်စုများကို ကြည့်ရန်",
        "tool-link-emailuser": "ဤ{{GENDER:$1|အသုံးပြုသူ}}ကို အီးမေးပို့ရန်",
-       "userpage": "အသုံးပြုသူ၏ စာမျက်နှာကို ကြည့်ရန်",
-       "projectpage": "ပရောဂျက်စာမျက်နှာကို ကြည့်ရန်",
        "imagepage": "ဖိုင်စာမျက်နှာကိုကြည့်ရန်",
        "mediawikipage": "စာတိုစာမျက်နှာ ကြည့်ရန်",
        "templatepage": "တမ်းပလိတ်စာမျက်နှာကို ကြည့်ရန်",
        "pageinfo-toolboxlink": "စာမျက်နှာ အချက်အလက်များ",
        "markaspatrolleddiff": "စောင့်ကြပ်စစ်ဆေးပြီးကြောင်း မှတ်သားရန်",
        "markaspatrolledtext": "ဤစာမျက်နှာအား စောင့်ကြပ်စစ်ဆေးပြီးကြောင်း မှတ်သားရန်",
+       "markedaspatrolled": "စောင့်ကြပ်စစ်ဆေးပြီးကြောင်း မှတ်သားပြီး",
+       "markedaspatrolledtext": "[[:$1]] ၏ ရွေးချယ်ထားသော တည်းဖြတ်မူကို စောင့်ကြပ်စစ်ဆေးပြီးကြောင်း မှတ်သားပြီးပါပြီ။",
+       "markedaspatrollednotify": "$1 သို့ ဤပြောင်းလဲမှုအား စောင့်ကြပ်စစ်ဆေးပြီးကြောင်း မှတ်သားပြီးပါပြီ။",
        "filedeleteerror-short": "ဖိုင်ဖျက်ရာတွင် အမှားအယွင်း - $1",
        "previousdiff": "← တည်းဖြတ်မူ အဟောင်း",
        "nextdiff": "ပိုသစ်သော တည်းဖြတ်မှု",
index f2e8b92..eac0e4b 100644 (file)
        "confirmrecreate": "Brukaren «[[User:$1|$1]]» ([[User talk:$1|brukardiskusjon]]) sletta denne sida medan du endra henne, og gav denne grunnen: ''$2''\n\nDu må stadfeste at du verkeleg vil nyopprette denne sida.",
        "confirmrecreate-noreason": "Brukaren [[User:$1|$1]] ([[User talk:$1|diskusjon]]) sletta sida etter at du byrja å endra henne. Stadfest at du verkeleg ynskjer å oppretta sida på nytt.",
        "recreate": "Attopprett",
+       "confirm-purge-title": "Slett mellomlagring av sida",
        "confirm_purge_button": "OK",
        "confirm-purge-top": "Vil du slette tenarane sin mellomlagra versjon av denne sida?",
        "confirm-purge-bottom": "Reinsing av ei side slettar mellomlageret og tvingar fram den nyaste versjonen.",
index 8fc3da1..5b51197 100644 (file)
        "jumptonavigation": "navegação",
        "jumptosearch": "pesquisa",
        "view-pool-error": "Desculpe, mas de momento os servidores estão sobrecarregados.\nHá demasiados utilizadores a tentar visualizar esta página.\nEspere um pouco antes de tentar aceder à página novamente, por favor.\n\n$1",
-       "generic-pool-error": "Desculpe, os servidores estão sobrecarregados nesse momento.\nDemasiados utilizadores estão tentando visualizar este recurso.\nPor favor, espere um pouco antes de tentar aceder a este recurso novamente.",
+       "generic-pool-error": "Desculpe, neste momento os servidores estão sobrecarregados.\nHá demasiados utilizadores a tentar ver este recurso.\nEspere um pouco antes de tentar aceder a este recurso novamente, por favor.",
        "pool-timeout": "Tempo limite de espera para o bloqueio excedido",
        "pool-queuefull": "A fila de processos está cheia",
        "pool-errorunknown": "Erro desconhecido",
index d96657f..0569267 100644 (file)
        "rcfilters-filter-lastrevision-description": "Description for the filter for showing changes on last revision of a page.",
        "rcfilters-filter-previousrevision-label": "Title for the filter for showing changes on previous revisions of a page.",
        "rcfilters-filter-previousrevision-description": "Description for the filter for showing changes on previous revisions of a page.",
+       "rcfilters-filter-excluded": "Label for a menu item in [[Special:RecentChanges]] noting that the item is being excluded from the results.",
+       "rcfilters-tag-prefix-namespace": "Prefix for the namespace tags in [[Special:RecentChanges]]. Namespace tags use a colon (:) as prefix. Please keep this format.\n\nParameters:\n* $1 - Filter name.",
+       "rcfilters-tag-prefix-namespace-inverted": "Prefix for the namespace inverted tags in [[Special:RecentChanges]]. Namespace tags use a colon (:) as prefix. Please keep this format.\n\nParameters:\n* $1 - Filter name.",
        "rcnotefrom": "This message is displayed at [[Special:RecentChanges]] when viewing recentchanges from some specific time.\n\nThe corresponding message is {{msg-mw|Rclistfrom}}.\n\nParameters:\n* $1 - the maximum number of changes that are displayed\n* $2 - (Optional) a date and time\n* $3 - a date\n* $4 - a time\n* $5 - Number of changes are displayed, for use with PLURAL",
        "rclistfromreset": "Used on [[Special:RecentChanges]] to reset a selection of a certain date range.",
        "rclistfrom": "Used on [[Special:RecentChanges]]. Parameters:\n* $1 - (Currently not use) date and time. The date and the time adds to the rclistfrom description.\n* $2 - time. The time adds to the rclistfrom link description (with split of date and time).\n* $3 - date. The date adds to the rclistfrom link description (with split of date and time).\n\nThe corresponding message is {{msg-mw|Rcnotefrom}}.",
index e9d45b7..e0e62fc 100644 (file)
        "gotointerwiki-invalid": "Den angivna titeln är ogiltig.",
        "gotointerwiki-external": "Du håller på att lämna {{SITENAME}} för att besöka [[$2]] som är en separat webbplats.\n\n'''[$1 Fortsätt till $1]'''",
        "undelete-cantedit": "Du kan inte återställa denna sida eftersom du är inte tillåten att redigera denna sida.",
-       "undelete-cantcreate": "Du kan inte återställa denna sida eftersom det inte finns någon befintlig sida med detta namn och du tillåts inte att skapa denna sida."
+       "undelete-cantcreate": "Du kan inte återställa denna sida eftersom det inte finns någon befintlig sida med detta namn och du tillåts inte att skapa denna sida.",
+       "pagedata-title": "Siddata",
+       "pagedata-text": "Denna sida tillhandahåller ett datagränssnitt till sidor. Ange sidans titel i webbadressen med hjälp av undersidesyntax.\n* Innehållsförhandling gäller baserat på att din klients Accept-header. Detta innebär att siddatan kommer att tillhandahållas i det format som din klient föredrar.",
+       "pagedata-not-acceptable": "Inga matchande format finns. MIME-typer som stöds:$1",
+       "pagedata-bad-title": "Ogiltig titel: $1."
 }
index 196c581..6983c01 100644 (file)
@@ -10,7 +10,8 @@
                        "Soundarya shetty s",
                        "రహ్మానుద్దీన్",
                        "BHARATHESHA ALASANDEMAJALU",
-                       "Lokesha kunchadka"
+                       "Lokesha kunchadka",
+                       "Kiranpoojary"
                ]
        },
        "tog-underline": "ಲಿಂಕ್‍ಲೆದ ತಿರ್ತ್ ಗೆರೆ(ಅಂಡರ್ ಲೈನ್) ಪಾಡ್‍ಲೆ",
@@ -53,7 +54,7 @@
        "tog-diffonly": "ವ್ಯತ್ಯಾಸದ ತಿರ್ತುಪ್ಪುನಂಚಿನ ಪುಟೊತ ವಿವರೊಲೆನ್ ತೊಜ್’ಪಾವೊಚಿ",
        "tog-showhiddencats": "ದೆಂಗಾದಿನ ವರ್ಗೊಲೆನ್ ತೊಜ್ಪಾಲೆ",
        "tog-norollbackdiff": "ದೆತ್ತ್‌ ಪಾಡ್‍ನೆಡ್‍ದ್ ಬುಕ್ಕೊ ವ್ಯತ್ಯಾಸೊನು ಬುಡ್‍ಲೆ",
-       "tog-useeditwarning": "ಸà²\82ಪà³\8aಲಿತà³\8dâ\80\8dನà³\86ನà³\8d à²\92ರಿಪಾವà²\82ದà³\86 à²ªà²¿à²¦à²¡à³\8dà²\82ಡ à²\8eನನà³\8d à²\8eà²\9aà³\8dà²\9aರಿಸಲೆ",
+       "tog-useeditwarning": "ಸà²\82ಪà³\8aಲಿತà³\8dâ\80\8dನà³\86ನà³\8d à²\92ರಿಪಾವà²\82ದà³\86 à²ªà²¿à²¦à²¡à³\8dà²\82ಡ à²\8eನನà³\8d à²\8eà²\9aà³\8dà²\9aರಿಪà³\81ಲೆ",
        "tog-prefershttps": "ಏಪೊಗುಲ ಲಾಗಿನ್ ಆಯಿನ ಬುಕ್ಕೊ ಜಾಗ್ರತೆದ ಸಂಪರ್ಕೊನು  ಬಳಕೆ ಮಲ್ಪುಲೆ",
        "underline-always": "ಯಾಪಲ",
        "underline-never": "ಯಾಪಗ್ಲಾ ಇಜ್ಜಿ",
        "june": "ಜೂನ್",
        "july": "ಜುಲಾಯಿ",
        "august": "ಆಗೋಸ್ಟು",
-       "september": "ಸಪ್ಟಂಬರ",
-       "october": "ಅಕ್ಟೋಬರ",
-       "november": "ನವà²\82ಬರà³\8a",
-       "december": "ದಸà²\82ಬರà³\8a",
+       "september": "ಸಪ್ಟಂಬರ",
+       "october": "ಅಕ್ಟೋಬರ",
+       "november": "ನವà²\82ಬರà³\8d",
+       "december": "ದಸà²\82ಬರà³\8d",
        "january-gen": "ಜನವರಿ",
        "february-gen": "ಪೆಬ್ರವರಿ",
        "march-gen": "ಮಾರ್ಚಿ",
        "jun": "ಜೂನ್",
        "jul": "ಜುಲಾಯಿ",
        "aug": "ಅಗೋಸ್ಟು",
-       "sep": "ಸಪ್ಟಂಬರ",
-       "oct": "ಅಕ್ಟೋಬರ",
-       "nov": "ನವà²\82ಬರà³\8a",
-       "dec": "ದಸà²\82ಬರà³\8a",
+       "sep": "ಸಪ್ಟಂಬರ",
+       "oct": "ಅಕ್ಟೋಬರ",
+       "nov": "ನವà²\82ಬರà³\8d",
+       "dec": "ದಸà²\82ಬರà³\8d",
        "january-date": "ಜನವರಿ $1",
        "february-date": "ಪೆಬ್ರುವರಿ $1",
        "march-date": "ಮಾರ್ಚಿ $1",
        "subcategories": "ಉಪ ವರ್ಗೊಲು",
        "category-media-header": "\"$1\" ವರ್ಗಡುಪ್ಪುನಂಚಿನ ಚಿತ್ರೊ/ಶಬ್ಧೊ ಫೈಲ್‍ಲು",
        "category-empty": "''ಈ ವರ್ಗೊಡು ಸದ್ಯಗ್ ಓವುಲ ಪುಟೊಲಾವಡ್ ಅತ್ತ್’ನ್ಡ ಚಿತ್ರೊಲಾವಡ್ ಇಜ್ಜಿ.''",
-       "hidden-categories": "{{PLURAL:$1|Hidden category|ದà³\86à²\82à²\97ಾದà³\8d à²¦à³\80ಡà³\8dâ\80\8dನ ವರ್ಗೊಲು}}",
+       "hidden-categories": "{{PLURAL:$1|Hidden category|ದà³\86à²\82à²\97ಾದà³\8d à²¦à³\80ತಿನ ವರ್ಗೊಲು}}",
        "hidden-category-category": "ದೆಂಗಾದ್ ದೀತಿನ ವರ್ಗೊಲು",
        "category-subcat-count": "{{PLURAL:$2|This category has only the following subcategory.|ಈ ವರ್ಗೊಡು ಈ ತಿರ್ತ್‍ದ {{PLURAL:$1|subcategory|$1 ಉಪವರ್ಗೊಲೆನ್}} ಸೇರಾದ್, ಒಟ್ಟಿಗೆ $2 ಉಂಡು.}}",
        "category-subcat-count-limited": "ಈ ವರ್ಗೊಡು ತಿರ್ತ್ ತೊಜ್ಪಾದಿನ {{PLURAL:$1|ಉಪವರ್ಗ|$1 ಉಪವರ್ಗೊಲು}} ಉಂಡು.",
        "anontalk": "ಪಾತೆರ್ಲೆ",
        "navigation": "ಸಂಚಾರೊ",
        "and": "&#32;ಬೊಕ್ಕ",
-       "qbfind": "ನಾಡ್’ಲೆ",
-       "qbbrowse": "ಬ್ರೌಸ್",
-       "qbedit": "ಸಂಪಾದನೆ ಮಲ್ಪುಲೆ",
-       "qbpageoptions": "ಈ ಪುಟ",
-       "qbmyoptions": "ಎನ್ನ ಪುಟೊಲು",
        "faq": "ಸಾಮಾನ್ಯವಾದ್ ಕೇನುನ ಪ್ರಶ್ನೆಲು",
-       "faqpage": "Project:ಸಾಮಾನ್ಯವಾದ್ ಕೇನುನ ಪ್ರಶ್ನೆಲು",
        "actions": "ಕ್ರಿಯೆಕ್ಕುಲು",
        "namespaces": "ಪುದರ್‍ದ ವರ್ಗೊಲು",
        "variants": "ದಿಂಜ",
        "edit-local": "ಸ್ಥಳೀಯ ವಿವರಣೆನ್ ಸೇರಾಲೆ",
        "create": "ಸೃಷ್ಟಿಸಾಲೆ",
        "create-local": "ಸ್ಥಳೀಯ ವಿವರಣೆನ್ ಸೇರಾಲೆ",
-       "editthispage": "ಈ ಪುಟೊನು ಬದಲಾಯಿಸಾಲೆ",
-       "create-this-page": "ಈ ಪುಟೊನು ಸೃಷ್ಟಿಸಾಲೆ",
        "delete": "ದೆತ್ತ್ ಪಾಡ್ಲೆ",
-       "deletethispage": "ಈ ಪುಟೊನು ದೆತ್ತ್ ಪಾಡ್ಲೆ",
-       "undeletethispage": "ಈ ಪುಟೊ ದೆತ್ತ್‌ ಪಾಡುನವು ರದ್ದಾತ್ಂಡ್",
        "undelete_short": "ಪಿರ ಪಾಡ್ಲೆ {{PLURAL:$1|ಒ೦ಜಿ ಬದಲಾವಣೆ|$1 ಬದಲಾವಣೆಲು}}",
        "viewdeleted_short": "ನೋಟ{{PLURAL:$1|1 ಡಿಲೀಟ್ ಆತಿನ ಸಂಪಾದನೆ|$1 ಡಿಲೀಟ್ ಆತಿನ ಸಂಪಾದನೆಲು}}",
        "protect": "ಸ೦ರಕ್ಷಿಸಾಲೆ",
        "protect_change": "ಬದಲಾಲೆ",
-       "protectthispage": "ಈ ಪುಟೊನು ಸ೦ರಕ್ಷಿಸಾಲೆ",
        "unprotect": "ರಕ್ಷಣೆನ್ ಬದಲ್‍ಪುಲೆ",
-       "unprotectthispage": "ಈ ಪುಟೊತ ರಕ್ಷಣೆನ್ ಬದಲ್‍ಪುಲೆ",
        "newpage": "ಪೊಸ ಪುಟೊ",
-       "talkpage": "ಪುಟದ ಬಗ್ಗೆ ಚರ್ಚೆ ಮನ್ಪುಲೆ",
        "talkpagelinktext": "ಪಾತೆರ",
        "specialpage": "ವಿಶೇಷ ಪುಟ",
        "personaltools": "ಸ್ವಂತೊ ಉಪಕರಣೊಲು",
-       "articlepage": "ಲೇಖನ ಪುಟೊನು ತೂಲೆ",
        "talk": "ಚರ್ಚೆ",
        "views": "ಅಬಿಪ್ರಾಯೊಲು",
        "toolbox": "ಉಪಕರಣೊಲು",
-       "userpage": "ಸದಸ್ಯೆರ್ನ ಪುಟೊನು ತೂಲೆ",
-       "projectpage": "ಪ್ರೊಜೆಕ್ಟ್ ಪುಟೊನು ತೂಲೆ",
        "imagepage": "ಫೈಲ್‍ದ ಪುಟೊನು ತೂಲೆ",
        "mediawikipage": "ಸಂದೇಶ ಪುಟೊನು ತೂಲೆ",
        "templatepage": "ಟೆಂಪ್ಲೇಟ್ ಪುಟೊನು ತೂಲೆ",
        "yourpasswordagain": "ಪಾಸ್ವರ್ಡ್ ಪಿರ ಟೈಪ್ ಮಲ್ಪುಲೆ",
        "createacct-yourpasswordagain": "ಪ್ರವೇಸೊ ಪದೊನು ದೃಡೊ ಮಲ್ಪುಲೆ",
        "createacct-yourpasswordagain-ph": "ಪ್ರವೇಸೊ ಪದೊನು ನನ ಒರ ನಮೂದಿಸಲೆ",
-       "userlogin-remembermypassword": "à²\8eನನà³\8d à²²à²¾à²\97ಿನà³\8d à²\86ತà³\87 à²¦à³\80ಡà³\8dಲà³\86",
+       "userlogin-remembermypassword": "ಎನನ್ ಲಾಗಿನ್ ಆತೇ ದೀಲೆ",
        "userlogin-signwithsecure": "ರಕ್ಷಣೆದ ಕನೆಕ್ಷನ್ ಉಪಯೋಗಿಸಲೆ.",
        "cannotlogin-title": "ಇತ್ತೆ ಉಲಾಯಿ ಪೋಯರ್ ಸಾದ್ಯೊ ಅವೊಂತಿಜ್ಜಿ",
        "cannotloginnow-title": "ಇತ್ತೆ ಉಲಾಯಿ ಪೋಯರ್ ಸಾದ್ಯೊ ಇದ್ದಿ",
        "accmailtitle": "ಪ್ರವೇಶಪದ ಕಡಪುಡ್‘ದುಂಡು",
        "newarticle": "(ಪೊಸತ್)",
        "newarticletext": "ನನಲ ಅಸ್ಥಿತ್ವಡ್ ಉಪ್ಪಂದಿನ ಪುಟೊಗು ಈರ್ ಬೈದರ್.\nಈ ಪುಟೊನು ಸ್ರಿಸ್ಟಿ ಮಲ್ಪೆರೆ ತಿರ್ತ್‍ದ ಚೌಕೊಡು ಬರೆಯೆರೆ ಸುರು ಮಲ್ಪುಲೆ.\n(ಜಾಸ್ತಿ ಮಾಹಿತಿಗ್ [$1 ಸಹಾಯ ಪುಟೊನು] ತೂಲೆ).\nಈ ಪುಟೊಕು ಈರ್ ತಪ್ಪಾದ್ ಬತ್ತಿತ್ತ್ಂಡ ಇರೆನ ಬ್ರೌಸರ್‍ದ '''back''' ಬಟನ್’ನ್ ಒತ್ತ್’ಲೆ.",
-       "noarticletext": "à²\88 à²ªà³\81à²\9fà³\8aಡà³\8d à²¸à²¦à³\8dಯà²\97à³\8d à²\92ವà³\8dವà³\87 à²¬à²°à²µà³\81ಲಾ à²\87à²\9cà³\8dà²\9cಿ, à²\88ರà³\8d à²¬à³\87ತà³\86 à²ªà³\81à²\9fà³\8aಡà³\8d [[Special:Search/{{PAGENAME}}|ಈ ಲೇಕನೊನು ನಾಡೊಲಿ]] <span class=\"plainlinks\">[{{fullurl:{{#Special:Log}}|page={{FULLPAGENAMEE}}}} ಸಂಬಂದೊ ಇತ್ತಿನ ದಾಕಲೆನ್ ನಾಡ್‍ಲೆ], ಅತ್ತಾಂಡ  [{{fullurl:{{FULLPAGENAME}}|action=edit}} ಈ ಪುಟೊನು ಸಂಪೊಲಿಪೊಲಿ]</span>.",
+       "noarticletext": "à²\88 à²ªà³\81à²\9fà³\8aà²\9fà³\81 à²¸à²¦à³\8dಯà²\97à³\8d à²\92ವà³\8dವà³\87 à²¬à²°à²µà³\81ಲಾ à²\87à²\9cà³\8dà²\9cಿ, à²\88ರà³\8d à²¬à³\87ತà³\86 à²ªà³\81à²\9fà³\8aà²\9fà³\81 [[Special:Search/{{PAGENAME}}|ಈ ಲೇಕನೊನು ನಾಡೊಲಿ]] <span class=\"plainlinks\">[{{fullurl:{{#Special:Log}}|page={{FULLPAGENAMEE}}}} ಸಂಬಂದೊ ಇತ್ತಿನ ದಾಕಲೆನ್ ನಾಡ್‍ಲೆ], ಅತ್ತಾಂಡ  [{{fullurl:{{FULLPAGENAME}}|action=edit}} ಈ ಪುಟೊನು ಸಂಪೊಲಿಪೊಲಿ]</span>.",
        "noarticletext-nopermission": "ಈ ಪುಟೊಡ್ ಸದ್ಯಗ್ ಒವ್ವೇ ಬರವುಲಾ ಇಜ್ಜಿ, ಈರ್ ಬೇತೆ ಪುಟೊಡ್ [[Special:Search/{{PAGENAME}}|ಈ ಲೇಕನೊನು ನಾಡೊಲಿ]] <span class=\"plainlinks\">[{{fullurl:{{#Special:Log}}|page={{FULLPAGENAMEE}}}} ಸಂಬಂದೊ ಇತ್ತ್‌ನ ಲಾಗ್‌ನ್ ನಾಡ್‍ಲೆ],[{{fullurl:{{FULLPAGENAME}}|action=edit}} ಅಂಡ ಇರೆಗ್ ಈ ಪುಟೊನು ಸಂಪೊಲಿಪೊಲಿಪುನೆಗ್ ಒಪ್ಪಿಗೆ ಇಜ್ಜಿ]</span>.",
        "userpage-userdoesnotexist": "ಬಳಕೆದಾರ ಖಾತೆ \"<nowiki>$1</nowiki>\" ದಾಖಲಾತ್‘ಜ್ಜಿ. ಈರ್ ಉಂದುವೇ ಪುಟನ್ ಸಂಪಾದನೆ ಮಲ್ಪರ ಉಂಡಾಂದ್ ಖಾತ್ರಿ ಮಲ್ತೊನಿ.",
        "previewnote": "'''ಉಂದು ಕೇವಲ ಮುನ್ನೋಟ; ಪುಟೊನು ನನಲ ಒರಿಪಾದಿಜಿ ಪನ್ಪುನೇನ್ ಮರಪೊರ್ಚಿ!'''",
        "currentrevisionlink": "ಇತ್ತೆದ ತಿದ್ದುಪಡಿ",
        "cur": "ಸದ್ಯೊ",
        "next": "ಬೊಕ್ಕದ",
-       "last": "ಪಿರವà³\81",
+       "last": "ದà³\81à²\82ಬà³\81ದ",
        "page_first": "ಸುರುತ",
        "page_last": "ಕಡೆತ",
        "history-fieldset-title": "ಇತಿಹಾಸಡ್ ನಾಡ್ಲೆ",
        "compareselectedversions": "ಆಯ್ಕೆ ಮಲ್ತಿನ ಆವೃತ್ತಿಲೆನ್ ಹೊಂದಾಣಿಕೆ ಮಲ್ತ್ ತೂಲೆ",
        "editundo": "ದುಂಬುದಲೆಕೊ",
        "diff-multi-sameuser": "({{PLURAL:$1|One intermediate revision|$1 ಮದ್ಯಂತರೊ ಪರಿಸ್ಕರಣೆ}} ಅವ್ವೇ ಬಳಕೆದಾರೆರೆನ್ ತೋಜಾದ್‍ಜಿ)",
-       "searchresults": "ನಾಡà³\8dâ\80\8dಪತà³\8dತà³\8dâ\80\8cನà³\86ದ ಪಲಿತಾಂಸೊಲು",
-       "searchresults-title": "\"$1\"à²\95à³\8d à²¨à²¾à²¡à³\8dâ\80\8dಪತà³\8dತà³\8dâ\80\8cನà³\86ದ ಪಲಿತಾಂಸೊಲು",
+       "searchresults": "ನಾಡà³\8dâ\80\8dಪತà³\8dತà³\8dâ\80\8cನà³\86ತ ಪಲಿತಾಂಸೊಲು",
+       "searchresults-title": "\"$1\"à²\95à³\8d à²¨à²¾à²¡à³\8dâ\80\8dಪತà³\8dತà³\8dâ\80\8cನà³\86ತ ಪಲಿತಾಂಸೊಲು",
        "notextmatches": "ವಾ ಪುಟೊತ ಪಠ್ಯೊಡುಲಾ ಹೋಲಿಕೆ ಇಜ್ಜಿ",
        "prevn": "ದುಂಬುತ್ತ {{PLURAL:$1|$1}}",
-       "nextn": "ಬà³\8aà²\95à³\8dà²\95à³\8a {{PLURAL:$1|$1}}",
+       "nextn": "ಬà³\8aà²\95à³\8dà²\95ದ {{PLURAL:$1|$1}}",
        "prev-page": "ದುಂಬುತ ಪುಟೊ",
        "next-page": "ನನತಾ ಪುಟ",
        "nextn-title": "ದುಂಬುದ $1 {{PLURAL:$1|result|ಪಲಿತಾಂಸೊಲು}}",
-       "shown-title": "ಪà³\8dರತಿ à²ªà³\81à²\9fà³\8aಡà³\81ಲಾ $1 {{PLURAL:$1|result|ಪಲಿತಾà²\82ಸà³\8a}} à²¤à³\8bà²\9cಿಪಾವà³\81",
+       "shown-title": "ಪ್ರತಿ ಪುಟೊಡುಲಾ $1 {{PLURAL:$1|result|ಪಲಿತಾಂಸೊ}} ತೋಜಪಾವು",
        "viewprevnext": "ತೂಲೆ ($1 {{int:pipe-separator}} $2) ($3)",
        "searchmenu-new": "<strong>ಈ ಪುಟೊನು ರಚಿಸಲೆ \"[[:$1]]\" ಈ ವಿಕಿಡ್!</strong> {{PLURAL:$2|0=|See also the page found with your search.|ನಾಡ್‍ನಗ ತೋಜಿದ್ ಬರ್ಪುನ ಪಲಿತಾಂಸೊನು ತೂಲೆ.}}",
        "searchprofile-articles": "ಲೇಕನೊ ಪುಟೊ",
        "recentchanges-submit": "ತೋಜಾಲೆ",
        "rcfilters-filterlist-whatsthis": "ಉಂದು ದಾದಾ?",
        "rcfilters-filter-user-experience-level-learner-label": "ಕಲ್ಪುನರ್",
-       "rclistfrom": "$3 $2 ರ್ದ್ ಸುರುವಾತಿನ ಪೊಸ ಬದಲಾವಣೆಲೆನ್ ತೊಜ್ಪಾವು",
+       "rclistfrom": "$2, $3 ಡ್ದ್ ಸುರುವಾತಿನ ಪೊಸ ಬದಲಾವಣೆಲೆನ್ ತೊಜ್ಪಾವು",
        "rcshowhideminor": "$1 ಎಲ್ಯೆಲ್ಯ ಬದಲಾವಣೆಲು",
        "rcshowhideminor-show": "ತೋಜಾಲೆ",
        "rcshowhideminor-hide": "ಅಡೆಂಗಾವು",
        "rcshowhideliu": "ನೋಂದವಣೆ ಆತಿನಂಚಿನ ಸದಸ್ಯೆರ್ $1",
        "rcshowhideliu-show": "ತೋಜಾಲೆ",
        "rcshowhideliu-hide": "ಅಡೆಂಗಾವು",
-       "rcshowhideanons": "ಪà³\81ದರà³\8d à²\87ದà³\8dಯಾà²\82ದಿನ ಸದಸ್ಯೆರ್ $1",
+       "rcshowhideanons": "ಪà³\81ದರà³\8d à²¦à²¾à²\82ತಿ ಸದಸ್ಯೆರ್ $1",
        "rcshowhideanons-show": "ತೋಜಾಲೆ",
        "rcshowhideanons-hide": "ಅಡೆಂಗಾವು",
        "rcshowhidepatr": "$1 ಪರೀಕ್ಷಿಸಾದಿನ ಸಂಪಾದನೆಲು",
        "rcshowhidemine-hide": "ಅಡೆಂಗಾವು",
        "rcshowhidecategorization-show": "ತೋಜಾಲೆ",
        "rcshowhidecategorization-hide": "ಅಡೆಂಗಾವು",
-       "rclinks": "ದà³\81à²\82ಬà³\81ದ $2 à²¦à²¿à²¨à³\8aಲà³\86ಡà³\8d à²®à²²à³\8dತಿನ $1 à²ªà²¿à²°à²µà³\81ದ ಬದಲಾವಣೆಲೆನ್ ತೂಲೆ",
+       "rclinks": "à²\95ರಿನ $2 à²¦à²¿à²¨à³\8aಲà³\86ಡà³\8d à²®à²²à³\8dತಿನ à²\95ಡà³\86ತà³\8dತ $1 ಬದಲಾವಣೆಲೆನ್ ತೂಲೆ",
        "diff": "ವ್ಯತ್ಯಾಸೊ",
        "hist": "ಇತಿಹಾಸೊ",
        "hide": "ಅಡೆಂಗಾವು",
        "filehist-dimensions": "ಆಯಾಮೊಲು",
        "filehist-filesize": "ಫೈಲ್’ದ ಗಾತ್ರ",
        "filehist-comment": "ಅಬಿಪ್ರಾಯೊ",
-       "imagelinks": "ಫà³\88ಲà³\8dâ\80\8dದ à²¬à²³à²\95à³\86",
+       "imagelinks": "ಫà³\88ಲà³\8dâ\80\8dದ à²\89ಪಯà³\8bà²\97",
        "linkstoimage": "ಈ ತಿರ್ತ್‍ದ {{PLURAL:$1|page links|$1 ಪುಟೊಲೆ ಕೊಂಡಿ}}ಈ ಫೈಲ್‍ಗ್ ಕೊನಪೋಪುಂಡು.",
        "nolinkstoimage": "ಈ ಫೈಲ್‍ಗ್ ಸಂಪರ್ಕೊ ಉಪ್ಪುನ ವಾ ಪುಟೊಲಾ ಇದ್ದಿ.",
        "sharedupload": "ಈ ಫೈಲ್’ನ್ ಮಸ್ತ್ ಜನ ಪಟ್ಟ್’ದುಲ್ಲೆರ್ ಅಂಚೆನೆ ಉಂದು ಮಸ್ತ್ ಪ್ರೊಜೆಕ್ಟ್’ಲೆಡ್ ಉಪಯೋಗಿಸೊಲಿ",
-       "sharedupload-desc-here": "à²\88 à²ªà³\81à²\9fà³\8a $1ಡà³\8dದà³\8d à²¬à³\8aà²\95à³\8dà²\95 à²¬à³\87ತà³\86 à²¯à³\8bà²\9cನà³\86ಡà³\8dದà³\8d à²\97ಳಸೊಲಿ.\nಈ ಪುಟೊತ ವಿವರೊ [$2 ಪುಟೊತ ವಿವರೊ] ತಿರ್ತ ಸಾಲ್‍ಡ್ ತೋಜಾದ್ಂಡ್",
+       "sharedupload-desc-here": "à²\88 à²ªà³\81à²\9fà³\8a $1ಡà³\8dದà³\8d à²¬à³\8aà²\95à³\8dà²\95 à²¬à³\87ತà³\86 à²¯à³\8bà²\9cನà³\86ಡà³\8dದà³\8d à²\97ಲಸೊಲಿ.\nಈ ಪುಟೊತ ವಿವರೊ [$2 ಪುಟೊತ ವಿವರೊ] ತಿರ್ತ ಸಾಲ್‍ಡ್ ತೋಜಾದ್ಂಡ್",
        "upload-disallowed-here": "ಈರ್ ಈ ಫೈಲ್‍ನ್ ಕುಡೊರೊ ಬರೆವರೆ ಸಾದ್ಯೊ ಇದ್ದಿ.",
        "filerevert-comment": "ಕಾರಣ:",
        "filerevert-submit": "ದುಂಬುದ ಲೆಕ ಮಲ್ಪುಲೆ",
        "protectedpages-unknown-performer": "ಅಜ್ಞಾತ ಬಳಕೆದಾರೆ",
        "protectedtitles": "ಸಂರಕ್ಷಿತ ಶೀರ್ಷಿಕೆಲು",
        "listusers": "ಬಳಕೆದಾರರೆನ ತಖ್ತೆ",
-       "newpages": "ಪೊಸ ಪುಟೊಲು",
+       "newpages": "ಪà³\8aಸ à²ªà³\81à²\9fà³\8aà²\95à³\81ಲà³\81",
        "newpages-submit": "ತೋಜಾಲೆ",
        "newpages-username": "ಸದಸ್ಯೆರ್ನ ಪುದರ್:",
        "move": "ಮೂವ್(ಸ್ಥಳಾಂತರ) ಮಲ್ಪುಲೆ",
        "undelete-show-file-submit": "ಅಂದ್",
        "namespace": "ಪುದರ್‍ದ ಬಗೆ:",
        "invert": "ಆಯ್ಕೆನ್ ತಿರ್ಗಾಲೆ",
-       "tooltip-invert": "à²\88 à²\9aà³\8cà²\95à³\8aದà³\81ಲಯಿಡà³\8d à²\85ಡà³\86à²\82à²\97ಿನ à²ªà³\81ದರà³\8dâ\80\8dನà³\8d à²\88 à²\9aà³\8cà²\95à³\8aಡà³\86 à²ªà²°à³\80à²\95à³\8dಷಿಸಲà³\86ಲà³\86(ಬà³\8aà²\95à³\8dà²\95à³\8a à²\92à²\9fà³\8dà²\9fà³\81à²\97ಿತà³\8dತಿನ à²ªà³\81ದರà³\8dâ\80\8dನà³\8dಲಾ à²ªà²°à³\80à²\95à³\8dಷಿಸವà³\8aಲಿ)",
-       "namespace_association": "à²\9cತà³\86à²\9fಿತà³\8dತಿನ à²ªà³\81ದರà³\8d",
-       "tooltip-namespace_association": "à²\88 à²\9aà³\8cà²\95à³\8aನà³\81 à²\9aರà³\8dà²\9aà³\86ನà³\8d à²¸à³\87ರಾದà³\8d à²ªà²°à³\80à²\95à³\8dಷಿಸಲà³\86 à²\85ತà³\8dತà³\8dà²\82ಡ à²µà²¿à²¸à²¯à³\8aà²\97à³\81 à²¸à²°à²¿à²¯à²¾à²¯à²¿à²¨ à²ªà³\81ದರà³\8dದ à²\9cತà³\86à²\9fà³\8d à²¸à³\87ರಾಲೆ",
+       "tooltip-invert": "à²\86ಯà³\8dತಿ à²ªà³\81ದರà³\8d-à²\9cಾà²\97à³\86ದà³\81ಲಯಿದ (ಬà³\8aà²\95à³\8dà²\95 à²\86ಯà³\8dತಿತà³\8dತà³\8dà²\82ಡ, à²¸à²\82ಬà²\82ಧ à²ªà²\9fà³\8dà²\9fಿನ à²ªà³\81ದರà³\8d-à²\9cಾà²\97à³\86ದಲಾ) à²ªà³\81à²\9fà³\8aà²\95à³\81ಲà³\86ನ à²¬à²¦à²²à²¾à²µà²£à³\86ನà³\8d à²¦à³\86à²\82à²\97ಾಯà³\86ರà³\86 à²\88 à²ªà³\86à²\9fà³\8dà²\9fಿà²\97à³\86ನà³\8d à²\86ಯà³\8dಪà³\81ಲà³\86",
+       "namespace_association": "ಸà²\82ಬà²\82ಧ à²ªà²\9fà³\8dà²\9fಿನ à²ªà³\81ದರà³\8d-à²\9cಾà²\97à³\86",
+       "tooltip-namespace_association": "à²\86ಯà³\8dತಿ à²ªà³\81ದರà³\8d-à²\9cಾà²\97à³\86à²\97à³\8d à²¸à²\82ಬà²\82ಧ à²ªà²\9fà³\8dà²\9fಿನ à²ªà²¾à²¤à³\86ರ à²\85ತà³\8dತಾà²\82ಡ à²µà²¿à²¸à²¯à²¦ à²ªà³\81ದರà³\8d-à²\9cಾà²\97à³\86ನà³\8dಲಾ à²\92à²\9fà³\8dà²\9fà³\81à²\97à³\81 à²¸à³\87ರಾಯà³\86ರà³\86 à²\88 à²ªà³\86à²\9fà³\8dà²\9fಿà²\97à³\86ನà³\8d à²\86ಯà³\8dಪà³\81ಲೆ",
        "blanknamespace": "(ಮುಖ್ಯ)",
        "contributions": "{{GENDER:$1|ಸದಸ್ಯೆರ್ನ}} ಕಾಣಿಕೆಲು",
        "contributions-title": "$1 ಗ್ ಸದಸ್ಯೆರ್ನ ಕಾಣಿಕೆ",
        "allmessages-language": "ಬಾಸೆ:",
        "allmessages-filter-submit": "ಪೋ",
        "allmessages-filter-translate": "ಭಾಷಾಂತರ ಮಲ್ಪುಲೆ",
-       "thumbnail-more": "ಮಲ್ಲ ಮಲ್ಪುಲೆ",
+       "thumbnail-more": "ಮಲ್ಲ ಮಲ್ಪುಲೆ",
        "thumbnail_error": "ಮುನ್ನೋಟ ಚಿತ್ರೊನು ಸೃಷ್ಟಿ ಮನ್ಪುನಗ ದೋಷ: $1",
        "import": "ಪುಟೊಲೆನ್ ಕಡಪುಡ್ಲೆ",
        "import-interwiki-sourcepage": "ಮೂಲ ಪುಟ",
        "tooltip-pt-mycontris": "{{GENDER:|ಎನ್ನ}} ಕಾನಿಕೆಲೆನ ಪಟ್ಟಿ",
        "tooltip-pt-login": "ಈರ್ ಲಾಗಿನ್ ಆವೊಡುಂದು ಕೇನೊಂದುಲ್ಲೊ, ಆಂಡ ಉಂದು ದಾಲ ಕಡ್ಡಾಯ ಅತ್ತ್.",
        "tooltip-pt-logout": "ಲಾಗ್ ಔಟ್",
-       "tooltip-pt-createaccount": "à²\87ರà³\8d  à²ªà³\8bಸ à²\96ಾತà³\86 à²¸à³\81ರà³\81ಮಾà²\82ತà³\8dâ\80\8dದà³\8d, ಲಾಗಿನ್ ಆಪುನೈನ್ ಬೆರಿ ಬೊಟ್ಟುಪೋ, ಆಂಡ ಉಂದು ಕಡ್ಡಾಯ ಅತ್ತ್.",
+       "tooltip-pt-createaccount": "à²\88ರà³\8d à²ªà³\8aಸ à²\96ಾತà³\86 à²¸à³\81ರà³\81ಮಲà³\8dತà³\8d ಲಾಗಿನ್ ಆಪುನೈನ್ ಬೆರಿ ಬೊಟ್ಟುಪೋ, ಆಂಡ ಉಂದು ಕಡ್ಡಾಯ ಅತ್ತ್.",
        "tooltip-ca-talk": "ಮಾಹಿತಿ ಪುಟೊತ ಬಗೆಟ್ ಚರ್ಚೆ",
        "tooltip-ca-edit": "ಈ ಪುಟೊನ್ ಸಂಪೊಲಿಪುಲೆ",
        "tooltip-ca-addsection": "ಪೊಸ ವಿಬಾಗೊನು ಸುರು ಮಲ್ಪುಲೆ",
        "tooltip-ca-watch": "ಈ ಪುಟೊನು ಈರೆನ ವೀಕ್ಷಣಾಪಟ್ಟಿಗ್ ಸೆರ್ಪಾಲೆ",
        "tooltip-ca-unwatch": "ಈ ಪುಟೊನು ಇರೆನ ವೀಕ್ಷಣಾ ಪಟ್ಟಿರ್ದ್ ದೆಪ್ಪುಲೆ",
        "tooltip-search": "{{SITENAME}}ನ್ ನಾಡ್‍ಲೆ",
-       "tooltip-search-go": "à²\89à²\82ದà³\81ವà³\87 à²ªà³\81ದರà³\8dದ à²ªà³\81à²\9fà³\8a à²\87ತà³\8dತà³\8dâ\80\8cà²\82ಡ à²\86ಡೆ ಪೋಲೆ",
+       "tooltip-search-go": "à²\89à²\82ದà³\81ವà³\87 à²ªà³\81ದರà³\8dದ à²ªà³\81à²\9fà³\8a à²\87ತà³\8dತà³\8dâ\80\8cà²\82ಡ à²\85ಡೆ ಪೋಲೆ",
        "tooltip-search-fulltext": "ಈ ಪಟ್ಯೊಡ್ ಉಪ್ಪುನಂಚಿನ ಪುಟೊಲೆನ್ ನಾಡ್‌ಲೆ",
-       "tooltip-p-logo": "ಮà³\81à²\96à³\8dಯ à²ªà³\81à²\9fà²\97್ ಪೋಲೆ",
+       "tooltip-p-logo": "ಮà³\81à²\96à³\8dಯ à²ªà³\81à²\9fà²\95್ ಪೋಲೆ",
        "tooltip-n-mainpage": "ಮುಖ್ಯಪುಟನ್ ತೂಲೆ",
        "tooltip-n-mainpage-description": "ಮುಕ್ಯೊ ಪುಟೊನ್ ತೂಲೆ",
        "tooltip-n-portal": "ಯೋಜನೆದ ಬಗೆಟ್, ಈರ್ ದಾದ ಮಲ್ಪೊಲಿ, ಓಲು ಇಂದೆತ ಬಗೆಟ್ ತೆರಿಯೊನೊಲಿ",
        "tooltip-n-randompage": "ಇಚ್ಚೆದ ಪುಟೊ ಒಂಜೆನ್ ತೋಜಾವು",
        "tooltip-n-help": "ಇಂದೆತ ಬಗೆಟ್ ತೆರೆಯೊನುನ ಜಾಗೆ",
        "tooltip-t-whatlinkshere": "ಇಡೆಗ್ ಕೊಂಡಿ ಕೊರ್ಪುನಂಚಿನ ಪೂರ ವಿಕಿ ಪುಟೊಲೆನ ಪಟ್ಟಿ",
-       "tooltip-t-recentchangeslinked": "à²\88 à²ªà³\81à²\9fà³\8aಡà³\8dದà³\8d à²¸à²\82ಪರà³\8dà²\95à³\8a à²\89ಪà³\8dಪà³\81ನà²\82à²\9aಿನ à²ªà³\81à²\9fà³\8aಡà³\8d ಇಂಚಿಪೊದ ಬದಲಾವಣೆಲು",
+       "tooltip-t-recentchangeslinked": "à²\88 à²ªà³\81à²\9fà³\8aಡà³\8dದà³\8d à²¸à²\82ಪರà³\8dà²\95à³\8a à²\89ಪà³\8dಪà³\81ನà²\82à²\9aಿನ à²ªà³\81à²\9fà³\8aà²\9fà³\81 ಇಂಚಿಪೊದ ಬದಲಾವಣೆಲು",
        "tooltip-feed-rss": "ಈ ಪುಟೊಗು ಆರ್.ಎಸ್.ಎಸ್ ಫೀಡ್",
-       "tooltip-feed-atom": "à²\88 à²ªà³\81à²\9fà³\8aà²\97ು ಆಟಮ್ ಫೀಡ್ ಮಲ್ಪುಲೆ",
+       "tooltip-feed-atom": "à²\88 à²ªà³\81à²\9fà³\8aà²\95ು ಆಟಮ್ ಫೀಡ್ ಮಲ್ಪುಲೆ",
        "tooltip-t-contributions": "{{GENDER:$1|ಈ ಸದಸ್ಯೆರ್ನ}} ಕಾಣಿಕೆದ ಪಟ್ಟಿನ್ ತೋಜಾವು",
        "tooltip-t-emailuser": "ಈ ಸದಸ್ಯೆರೆಗ್ ಇ-ಮೇಲ್ ಕಡಪುಡ್ಲೆ",
-       "tooltip-t-upload": "ಫೈಲನ್ ಅಪ್ಲೋಡ್ ಮಲ್ಪುಲೆ",
+       "tooltip-t-upload": "ಫà³\88ಲà³\8dâ\80\99ನà³\8d à²\85ಪà³\8dಲà³\8bಡà³\8d à²®à²²à³\8dಪà³\81ಲà³\86",
        "tooltip-t-specialpages": "ಪೂರ  ವಿಸೇಸೊ ಪುಟೊಲೆನ ಪಟ್ಟಿ",
-       "tooltip-t-print": "à²\88 à²ªà³\81à²\9fà³\8aದ ಮುದ್ರಣೊ ಮಲ್ಪುನ ಆವೃತ್ತಿ",
-       "tooltip-t-permalink": "ಪà³\81à²\9fà³\8aದ ಈ ಆವೃತ್ತಿಗ್ ಸಾಸಿತೊ ಕೊಂಡಿ",
+       "tooltip-t-print": "à²\88 à²ªà³\81à²\9fà³\8aತ ಮುದ್ರಣೊ ಮಲ್ಪುನ ಆವೃತ್ತಿ",
+       "tooltip-t-permalink": "ಪà³\81à²\9fà³\8aತ ಈ ಆವೃತ್ತಿಗ್ ಸಾಸಿತೊ ಕೊಂಡಿ",
        "tooltip-ca-nstab-main": "ಮಾಹಿತಿ ಪುಟೊನ್ ತೂಲೆ",
        "tooltip-ca-nstab-user": "ಸದಸ್ಯೆರ್ನ ಪುಟೊನು ತೂಲೆ",
        "tooltip-ca-nstab-special": "ಉಂದೊಂಜಿ ವಿಸೇಸ ಪುಟೊ, ಇಂದೆನ್ ಈರ್ ಸಂಪೊಲಿಪೆರೆ ಆಪುಜಿ",
        "file-nohires": "ಇಂದೆರ್ದ್ ಜಾಸ್ತಿ ರೆಸಲ್ಯೂಶನ್ ಇದ್ದಿ,",
        "svg-long-desc": "ಎಸ್.ವಿ.ಜಿ ಫೈಲ್, ಸುಮಾರಾದ್ $1 × $2 ಚಿತ್ರೊಬಿಂದು, ಫೈಲ್‍ದ ಗಾತ್ರ: $3",
        "show-big-image": "ಮೂಲೊ ಫೈಲ್",
-       "show-big-image-preview": "ಪಿರವà³\81ದ à²ªà³\81à²\9fà³\8aದ ಗಾತ್ರೊ: $1.",
+       "show-big-image-preview": "ಪಿರವà³\81ದ à²ªà³\81à²\9fà³\8aತ ಗಾತ್ರೊ: $1.",
        "show-big-image-other": "ಬೇತೆ{{PLURAL:$2|resolution|ಪಟೊತ್ತ ಗಾತ್ರೊ }}: $1.",
        "show-big-image-size": "$1 × $2 ಚಿತ್ರೊ ಬಿಂದುಲು",
        "newimages-legend": "ಅರಿಪೆ",
        "ilsubmit": "ನಾಡ್‍ಲೆ",
        "bad_image_list": "ವ್ಯವಸ್ಥೆದ ಆಕಾರ ಈ ರೀತಿ ಉಂಡು:\n\nಪಟ್ಟಿಡುಪ್ಪುನಂಚಿನ ದಾಖಲೆಲೆನ್ (* ರ್ದ್ ಶುರು ಆಪುನ ಸಾಲ್’ಲು) ಮಾತ್ರ ಪರಿಗಣನೆಗ್ ದೆತೊನೆರಾಪುಂಡು.\nಪ್ರತಿ ಸಾಲ್’ದ ಶುರುತ ಲಿಂಕ್ ಒಂಜಿ ದೋಷ ಉಪ್ಪುನಂಚಿನ ಫೈಲ್’ಗ್ ಲಿಂಕಾದುಪ್ಪೊಡು.\nಅವ್ವೇ ಸಾಲ್’ದ ಶುರುತ ಪೂರಾ ಲಿಂಕ್’ಲೆನ್ ಪರಿಗನೆರ್ದ್ ದೆಪ್ಪೆರಾಪುಂಡು, ಪಂಡ ಓವು ಪುಟೊಲೆಡ್ ಫೈಲ್’ದ ಬಗ್ಗೆ ಬರ್ಪುಂಡೋ ಔಲು.",
        "metadata": "ಮೆಟಾಡೇಟಾ",
-       "metadata-help": "à²\88 à²ªà³\88ಲà³\8dâ\80\8dಡà³\8d à²\9cಾಸà³\8dತಿ à²®à²¾à²¹à²¿à²¤à²¿ à²\89à²\82ಡà³\81. à²¹à³\86à²\9aà³\8dà²\9aಿನà²\82ಸà³\8a à²ªà³\88ಲà³\8dâ\80\8dನà³\8d à²\89à²\82ಡà³\81 à²®à²²à³\8dಪà³\86ರà³\86 à²\89ಪಯà³\8bà²\97 à²®à²²à³\8dತಿನ à²¡à²¿à²\9cಿà²\9fಲà³\8d à²\95à³\8dಯಾಮà³\86ರರà³\8dದà³\8d à²\85ತà³\8dತà³\8dà²\82ಡ à²¸à³\8dà²\95à³\8dಯಾನರà³\8dâ\80\8cರà³\8dದà³\8d à²\88 à²®à²¾à²¹à²¿à²¤à²¿ à²¬à²¤à³\8dತà³\8dà²\82ಡà³\8d.\nಮà³\82ಲಪà³\8dರತಿರà³\8dದà³\8d à²\88 à²ªà³\88ಲà³\8d à²¬à²¦à²²à²¾à²¦à²¿à²¤à³\8dತà³\8dà²\82ಡà³\8d, à²\88 ಮಾಹಿತಿ ಬದಲಾತಿನ ಪೈಲ್‍ದ ವಿವರೊಲೆಗ್ ಸರಿಯಾದ್ ಹೊಂದಂದೆ ಉಪ್ಪು.",
+       "metadata-help": "à²\88 à²ªà³\88ಲà³\8dâ\80\8dಡà³\8d à²\9cಾಸà³\8dತಿ à²®à²¾à²¹à²¿à²¤à²¿ à²\89à²\82ಡà³\81. à²¹à³\86à²\9aà³\8dà²\9aಿನà²\82ಸà³\8a à²ªà³\88ಲà³\8dâ\80\8dನà³\8d à²\89à²\82ಡà³\81 à²®à²²à³\8dಪà³\86ರà³\86 à²\89ಪಯà³\8bà²\97 à²®à²²à³\8dತಿನ à²¡à²¿à²\9cಿà²\9fಲà³\8d à²\95à³\8dಯಾಮà³\86ರರà³\8dದà³\8d à²\85ತà³\8dತà³\8dà²\82ಡ à²¸à³\8dà²\95à³\8dಯಾನರà³\8dâ\80\8cರà³\8dದà³\8d à²\88 à²®à²¾à²¹à²¿à²¤à²¿ à²¬à³\88ದà³\8dà²\82ಡà³\8d.\nಮà³\82ಲಪà³\8dರತಿರà³\8dದà³\8d à²\88 à²ªà³\88ಲà³\8d à²¬à²¦à²²à²¾à²¦à²¿à²¤à³\8dತà³\8dà²\82ಡ, à²\95à³\86ಲವà³\81 ಮಾಹಿತಿ ಬದಲಾತಿನ ಪೈಲ್‍ದ ವಿವರೊಲೆಗ್ ಸರಿಯಾದ್ ಹೊಂದಂದೆ ಉಪ್ಪು.",
        "metadata-expand": "ವಿಸ್ತಾರವಾಯಿನ ವಿವರೊಲೆನ್ ತೊಜ್ಪಾವು",
        "metadata-collapse": "ವಿಸ್ತಾರವಾಯಿನ ವಿವರೊಲೆನ್ ದೆಂಗಾವು",
        "metadata-fields": "ಈ ಸಂದೇಸೊಡು ಪಟ್ಟಿ ಮಲ್ತಿನಂಚಿನ EXIF ಮಿತ್ತ ದರ್ಜೆದ ಮಾಹಿತಿನ್ ಚಿತ್ರೊ ಪುಟೊಕು ಸೇರ್ಪಾಯೆರೆ ಆವೊಂದುಂಡು. ಪುಟೊಟು ಮಿತ್ತ ದರ್ಜೆ ಮಾಹಿತಿದ ಪಟ್ಟಿನ್ ದೆಪ್ಪುನಗ ಉಂದು ತೋಜುಂಡು.\nಒರಿದನವು ಮೂಲೊ ಸ್ಥಿತಿಟ್ ಅಡೆಂಗ್‍ದುಂಡು.\n*ಮಲ್ಪುಲೆ\n*ಮಾದರಿ\n*ದಿನೊ ಪೊರ್ತು ಮೂಲೊ\n*ಮಾನಾದಿಗೆದ ಸಮಯೊ\n*ಫ್‍ಸಂಖ್ಯೆ\n*ಐಎಸ್ಒ ವೇಗೊದ ರೇಟಿಂಗ್\n*ತೂಪಿನ ಜಾಗೆದ ದೂರ\n*ಕಲಾವಿದೆ\n*ಕೃತಿಸ್ವಾಮ್ಯೊ\n*ಚಿತ್ರೊ ವಿವರಣೆ\n*ಜಿಪಿಎಸ್ ಅಕ್ಷಾಂಸೊ\n*ಜಿಪಿಎಸ್ ರೇಖಾಂಸೊ\n*ಜಿಪಿಎಸ್ ಎತ್ತರೊ",
index 077becc..48c45f9 100644 (file)
        "anontalk": "Обговорення",
        "navigation": "Навігація",
        "and": "&#32;і",
-       "qbfind": "Знайти",
-       "qbbrowse": "Переглянути",
-       "qbedit": "Редагувати",
-       "qbpageoptions": "Налаштування сторінки",
-       "qbmyoptions": "Мої налаштування",
        "faq": "Часті питання",
-       "faqpage": "Project:Часті питання",
        "actions": "Дії",
        "namespaces": "Простори назв",
        "variants": "Варіанти",
        "edit-local": "Редагувати локальний опис",
        "create": "Створити",
        "create-local": "Додати локальний опис",
-       "editthispage": "Редагувати цю сторінку",
-       "create-this-page": "Створити цю сторінку",
        "delete": "Вилучити",
-       "deletethispage": "Вилучити цю сторінку",
-       "undeletethispage": "Відновити цю сторінку",
        "undelete_short": "Відновити $1 {{PLURAL:$1|редагування|редагування|редагувань}}",
        "viewdeleted_short": "Переглянути {{PLURAL:$1|одне вилучене редагування|$1 вилучені редагування|$1 вилучених редагувань}}",
        "protect": "Захистити",
        "protect_change": "змінити",
-       "protectthispage": "Захистити цю сторінку",
        "unprotect": "Змінити захист",
-       "unprotectthispage": "Змінити захист цієї сторінки",
        "newpage": "Нова сторінка",
-       "talkpage": "Обговорити цю сторінку",
        "talkpagelinktext": "обговорення",
        "specialpage": "Спеціальна сторінка",
        "personaltools": "Особисті інструменти",
-       "articlepage": "Переглянути статтю",
        "talk": "Обговорення",
        "views": "Перегляди",
        "toolbox": "Інструменти",
        "tool-link-userrights": "Змінити групи {{GENDER:$1|користувача|користувачки}}",
        "tool-link-userrights-readonly": "Перегляд груп {{GENDER:$1|користувача|користувачки}}",
        "tool-link-emailuser": "Лист {{GENDER:$1|користувачеві|користувачці}}",
-       "userpage": "Переглянути сторінку користувача",
-       "projectpage": "Переглянути сторінку проекту",
        "imagepage": "Переглянути сторінку файлу",
        "mediawikipage": "Переглянути сторінку повідомлення",
        "templatepage": "Переглянути сторінку шаблону",
        "recentchanges-legend-plusminus": "(''±123'')",
        "recentchanges-submit": "Показати",
        "rcfilters-activefilters": "Активні фільтри",
-       "rcfilters-quickfilters": "Швидкі посилання",
+       "rcfilters-quickfilters": "Збережені налаштування фільтрів",
+       "rcfilters-quickfilters-placeholder-title": "Ще немає збережених посилань",
+       "rcfilters-quickfilters-placeholder-description": "Щоб зберегти Ваші налаштування фільтрів та використати їх пізніше, клацніть на іконку закладки в ділянці активних фільтрів нижче.",
        "rcfilters-savedqueries-defaultlabel": "Збережені фільтри",
        "rcfilters-savedqueries-rename": "Перейменувати",
        "rcfilters-savedqueries-setdefault": "Зробити стандартним",
        "rcfilters-savedqueries-unsetdefault": "Прибрати зі стандартних",
        "rcfilters-savedqueries-remove": "Вилучити",
        "rcfilters-savedqueries-new-name-label": "Назва",
-       "rcfilters-savedqueries-apply-label": "СÑ\82воÑ\80иÑ\82и Ñ\88видке Ð¿Ð¾Ñ\81илання",
+       "rcfilters-savedqueries-apply-label": "Ð\97беÑ\80егÑ\82и Ð½Ð°Ð»Ð°Ñ\88Ñ\82Ñ\83вання",
        "rcfilters-savedqueries-cancel-label": "Скасувати",
-       "rcfilters-savedqueries-add-new-title": "Зберегти фільтри як швидке посилання",
+       "rcfilters-savedqueries-add-new-title": "Зберегти поточні налаштування фільтрів",
        "rcfilters-restore-default-filters": "Відновити стандартні фільтри",
        "rcfilters-clear-all-filters": "Очистити фільтри",
        "rcfilters-search-placeholder": "Фільтруйте нові редагування (переглядайте або почніть вводити)",
        "autoblocklist-submit": "Пошук",
        "autoblocklist-legend": "Вивести список автоблокувань",
        "autoblocklist-localblocks": "{{PLURAL:$1|Локальне|Локальні}} автоблокування",
+       "autoblocklist-total-autoblocks": "Загальна кількість автоблокувань: $1",
        "autoblocklist-empty": "Список автоблокувань порожній.",
        "autoblocklist-otherblocks": "{{PLURAL:$1|Інше|Інші}} автоблокування",
        "ipblocklist": "Список заблокованих адрес та користувачів",
        "rawhtml-notallowed": "Теги &lt;html&gt; не можна використовувати за межами звичайних сторінок.",
        "gotointerwiki": "Ви покидаєте сайт {{SITENAME}}",
        "gotointerwiki-invalid": "Вказана назва неприпустима.",
-       "gotointerwiki-external": "Ви збираєтесь покинути сайт {{SITENAME}}, щоб відвідати проект [[$2]], який є окремим веб-сайтом.\n\n[$1 Клацніть тут, щоб продовжити, перейшовши до $1].",
+       "gotointerwiki-external": "Ви збираєтесь покинути сайт {{SITENAME}}, щоб відвідати проект [[$2]], який є окремим веб-сайтом.\n\n'''[$1 Продовжити, перейшовши до $1]'''",
        "undelete-cantedit": "Ви не можете відновити цю сторінку, оскільки Ви не маєте прав на редагування цієї сторінки.",
-       "undelete-cantcreate": "Ви не можете відновити цю сторінку, оскільки сторінка з такою назвою не існує, і Ви не маєте прав на створення цієї сторінки."
+       "undelete-cantcreate": "Ви не можете відновити цю сторінку, оскільки сторінка з такою назвою не існує, і Ви не маєте прав на створення цієї сторінки.",
+       "pagedata-title": "Дані сторінки",
+       "pagedata-text": "Ця сторінка надає сторінкам інтерфейс даних. Будь ласка, вкажіть назву сторінки в URL-адресі, скориставшись синтаксисом підсторінок.\n* Переговори щодо контенту застосовуються на основі прийнятних форматів Вашого клієнта. Це означає, що дані сторінки будуть надані в тому форматі, якому віддає перевагу Ваш клієнт.",
+       "pagedata-not-acceptable": "Не знайдено підхожого формату. Підтримувані MIME-типи: $1",
+       "pagedata-bad-title": "Недійсна назва: $1."
 }
index e0eb586..afa9d5c 100644 (file)
        "page-atom-feed": "Atom פֿון $1",
        "feed-atom": "אטאם",
        "feed-rss": "אר.עס.עס.",
-       "red-link-title": "$1 (בלאט טוט נאָך נישט עקזיסטירן)",
+       "red-link-title": "$1 (בלאַט עקזיסטירט נאָך נישט)",
        "sort-descending": "סארטירן אַראָפ",
        "sort-ascending": "סארטירן אַרויף",
        "nstab-main": "בלאַט",
        "rcfilters-filterlist-whatsthis": "וואס איז דאס?",
        "rcfilters-filterlist-noresults": "קיין פֿילטערס נישט געטראפֿן",
        "rcfilters-filter-registered-label": "אײַנגעשריבן",
+       "rcfilters-filter-editsbyself-label": "ענדערונגען פון אייך",
+       "rcfilters-filter-editsbyself-description": "אייערע אייגענע בײשטײערונגען.",
+       "rcfilters-filter-editsbyother-label": "ענדערונגען פֿון אנדערע",
+       "rcfilters-filter-editsbyother-description": "אלע ענדערונגען אחוץ אייערע אייגענע.",
+       "rcfilters-filter-user-experience-level-learner-label": "לערנער",
        "rcfilters-filter-bots-label": "באט",
+       "rcfilters-filter-humans-label": "מענטש (נישט קיין באט)",
+       "rcfilters-filter-humans-description": "רעדאקטירונגען געמאכט פון מענטשן רעדאקטארן.",
+       "rcfilters-filtergroup-reviewstatus": "רעצענזירונג־סטאטוס",
+       "rcfilters-filter-patrolled-label": "פאטראלירט",
        "rcfilters-filter-newpages-label": "בלאַט־שאַפֿונגען",
+       "rcfilters-filtergroup-lastRevision": "לעצטע ווערסיע",
+       "rcfilters-filter-lastrevision-label": "לעצטע ווערסיע",
        "rcnotefrom": "פֿאלגנד {{PLURAL:$5|איז די ענדערונג| זענען די ענדערונגען}} זײַט <strong>$3, $4</strong> (ביז <strong>$1</strong>).",
        "rclistfrom": "װײַזן נײַע ענדערונגען פֿון $3 $2",
        "rcshowhideminor": "$1 מינערדיגע ענדערונגען",
        "uploadstash-nofiles": "איר האט נישט קיין טעקעס אין זאפאס.",
        "uploadstash-errclear": "אוועקנעמען די טעקעס דורכגעפאלן.",
        "uploadstash-refresh": "דערפֿרישן די רשימה פון טעקעס",
+       "uploadstash-thumbnail": "באקוקן קליינבילד",
        "invalid-chunk-offset": "אומגילטיקער סטארטפונקט",
        "img-auth-accessdenied": "צוטריט אָפגעזאָגט",
        "img-auth-notindir": "געשיכטעס שטעג איז נישט אין דער קאנפיגורטער ארויפלאד־דירעקטאריע.",
        "tooltip-pt-mytalk": "{{GENDER:|אייער}} שמועס בלאט",
        "tooltip-pt-anontalk": "שמועס איבער באטייליגען פון די איי.פי.",
        "tooltip-pt-preferences": "{{GENDER:|אייערע}} פרעפערענצן",
-       "tooltip-pt-watchlist": "ליסטע פון בלעטער וואס איר טוט אויפפאסן נאך ענדערונגן",
+       "tooltip-pt-watchlist": "ליסטע פון בלעטער וואס איר טוט אויפפאסן נאָך ענדערונגען",
        "tooltip-pt-mycontris": "ליסטע פון {{GENDER:|אייערע}} ביישטייערונגען",
        "tooltip-pt-login": "עס איז רעקאָמענדירט זיך אײַנשרײַבן; ס'איז אבער נישט קיין פֿליכט",
        "tooltip-pt-logout": "ארויסלאגירן",
        "logentry-rights-rights-legacy": "$1 {{GENDER:$2|האט געביטן}} גרופע מיטגלידערשאפט פאר $3",
        "logentry-rights-autopromote": "$1 אויטאמאטיש  {{GENDER:$2|פראמאווירט}} פון $4 צו $5",
        "logentry-upload-upload": "$1 {{GENDER:$2|האט ארויפגעלאדן}} $3",
+       "logentry-upload-overwrite": "$1 {{GENDER:$2|האט ארויפֿגעלאדן}} א נייע ווערסיע פֿון $3",
        "rightsnone": "(גארנישט)",
        "feedback-adding": "צולייגן פֿידבעק צו בלאַט...",
        "feedback-bugcheck": "געוואלדיק! אבער זייט בודק אז עס איז נישט איינער פון די [$1 באוואוסטע באגן].",
        "special-characters-title-endash": "ען טירע",
        "special-characters-title-emdash": "עם טירע",
        "special-characters-title-minus": "מינוס",
-       "mw-widgets-titleinput-description-new-page": "דער בלאט עקזיסטירט נאך נישט",
+       "mw-widgets-titleinput-description-new-page": "דער בלאַט עקזיסטירט נאך נישט",
        "date-range-from": "פֿון דאטע",
        "date-range-to": "ביז דאטע:",
+       "randomrootpage": "צופֿעליגער שטאם־בלאט",
        "log-action-filter-upload": "טיפ ארויפֿלאד:",
        "log-action-filter-all": "אַלע",
        "log-action-filter-delete-delete": "אויסמעקן בלאט",
index 77c8af8..87a62cd 100644 (file)
@@ -1751,6 +1751,7 @@ return [
                        'resources/src/mediawiki.rcfilters/dm/mw.rcfilters.dm.SavedQueriesModel.js',
                        'resources/src/mediawiki.rcfilters/dm/mw.rcfilters.dm.ChangesListViewModel.js',
                        'resources/src/mediawiki.rcfilters/mw.rcfilters.Controller.js',
+                       'resources/src/mediawiki.rcfilters/mw.rcfilters.UriProcessor.js',
                ],
                'dependencies' => [
                        'oojs',
@@ -1836,6 +1837,12 @@ return [
                        'rcfilters-noresults-conflict',
                        'rcfilters-state-message-subset',
                        'rcfilters-state-message-fullcoverage',
+                       'rcfilters-filter-excluded',
+                       'rcfilters-tag-prefix-namespace',
+                       'rcfilters-tag-prefix-namespace-inverted',
+                       'blanknamespace',
+                       'namespaces',
+                       'invert',
                        'recentchanges-noresult',
                        'quotation-marks',
                ],
@@ -1849,6 +1856,7 @@ return [
                        'oojs-ui.styles.icons-editing-core',
                        'oojs-ui.styles.icons-editing-styling',
                        'oojs-ui.styles.icons-interactions',
+                       'oojs-ui.styles.icons-content',
                ],
        ],
        'mediawiki.special' => [
index 59c0a19..bec40b4 100644 (file)
@@ -9,11 +9,16 @@
         * @param {string} name Group name
         * @param {Object} [config] Configuration options
         * @cfg {string} [type='send_unselected_if_any'] Group type
+        * @cfg {string} [view='default'] Name of the display group this group
+        *  is a part of.
         * @cfg {string} [title] Group title
         * @cfg {string} [separator='|'] Value separator for 'string_options' groups
         * @cfg {boolean} [active] Group is active
         * @cfg {boolean} [fullCoverage] This filters in this group collectively cover all results
         * @cfg {Object} [conflicts] Defines the conflicts for this filter group
+        * @cfg {string|Object} [labelPrefixKey] An i18n key defining the prefix label for this
+        *  group. If the prefix has 'invert' state, the parameter is expected to be an object
+        *  with 'default' and 'inverted' as keys.
         * @cfg {Object} [whatsThis] Defines the messages that should appear for the 'what's this' popup
         * @cfg {string} [whatsThis.header] The header of the whatsThis popup message
         * @cfg {string} [whatsThis.body] The body of the whatsThis popup message
 
                this.name = name;
                this.type = config.type || 'send_unselected_if_any';
+               this.view = config.view || 'default';
                this.title = config.title;
                this.separator = config.separator || '|';
+               this.labelPrefixKey = config.labelPrefixKey;
 
                this.active = !!config.active;
                this.fullCoverage = !!config.fullCoverage;
                        var subsetNames = [],
                                filterItem = new mw.rcfilters.dm.FilterItem( filter.name, model, {
                                        group: model.getName(),
-                                       label: mw.msg( filter.label ),
-                                       description: mw.msg( filter.description ),
-                                       cssClass: filter.cssClass
+                                       label: filter.label || filter.name,
+                                       description: filter.description || '',
+                                       labelPrefixKey: model.labelPrefixKey,
+                                       cssClass: filter.cssClass,
+                                       identifiers: filter.identifiers
                                } );
 
                        filter.subset = filter.subset || [];
                return this.type;
        };
 
+       /**
+        * Get display group
+        *
+        * @return {string} Display group
+        */
+       mw.rcfilters.dm.FilterGroup.prototype.getView = function () {
+               return this.view;
+       };
+
        /**
         * Get the prefix used for the filter names inside this group.
         *
index 3c2f8d7..53a1170 100644 (file)
                this.defaultParams = {};
                this.defaultFiltersEmpty = null;
                this.highlightEnabled = false;
+               this.invertedNamespaces = false;
                this.parameterMap = {};
 
+               this.views = {};
+               this.currentView = null;
+
                // Events
                this.aggregate( { update: 'filterItemUpdate' } );
                this.connect( this, { filterItemUpdate: [ 'emit', 'itemUpdate' ] } );
         * Filter list is initialized
         */
 
+       /**
+        * @event update
+        *
+        * Model has been updated
+        */
+
        /**
         * @event itemUpdate
         * @param {mw.rcfilters.dm.FilterItem} item Filter item updated
         * Highlight feature has been toggled enabled or disabled
         */
 
+       /**
+        * @event invertChange
+        * @param {boolean} isInverted Namespace selected is inverted
+        *
+        * Namespace selection is inverted or straight forward
+        */
+
        /* Methods */
 
        /**
         * the definition given by an object
         *
         * @param {Array} filters Filter group definition
+        * @param {Object} [namespaces] Namespace definition
         */
-       mw.rcfilters.dm.FiltersViewModel.prototype.initializeFilters = function ( filters ) {
+       mw.rcfilters.dm.FiltersViewModel.prototype.initializeFilters = function ( filters, namespaces ) {
                var filterItem, filterConflictResult, groupConflictResult,
                        model = this,
                        items = [],
+                       namespaceDefinition = [],
                        groupConflictMap = {},
                        filterConflictMap = {},
                        /*!
                // Reset
                this.clearItems();
                this.groups = {};
+               this.views = {};
 
+               // Filters
+               this.views.default = { name: 'default', label: mw.msg( 'rcfilters-filterlist-title' ) };
                filters.forEach( function ( data ) {
                        var i,
                                group = data.name;
                        if ( !model.groups[ group ] ) {
                                model.groups[ group ] = new mw.rcfilters.dm.FilterGroup( group, {
                                        type: data.type,
-                                       title: mw.msg( data.title ),
+                                       title: data.title ? mw.msg( data.title ) : group,
                                        separator: data.separator,
                                        fullCoverage: !!data.fullCoverage,
                                        whatsThis: {
                                        }
                                } );
                        }
+
+                       // Filters are given to us with msg-keys, we need
+                       // to translate those before we hand them off
+                       for ( i = 0; i < data.filters.length; i++ ) {
+                               data.filters[ i ].label = data.filters[ i ].label ? mw.msg( data.filters[ i ].label ) : data.filters[ i ].name;
+                               data.filters[ i ].description = data.filters[ i ].description ? mw.msg( data.filters[ i ].description ) : '';
+                       }
+
                        model.groups[ group ].initializeFilters( data.filters, data.default );
                        items = items.concat( model.groups[ group ].getItems() );
 
                        }
                } );
 
+               namespaces = namespaces || {};
+               if (
+                       mw.config.get( 'wgStructuredChangeFiltersEnableExperimentalViews' ) &&
+                       !$.isEmptyObject( namespaces )
+               ) {
+                       // Namespaces group
+                       this.views.namespaces = { name: 'namespaces', label: mw.msg( 'namespaces' ), trigger: ':' };
+                       $.each( namespaces, function ( namespaceID, label ) {
+                               // Build and clean up the definition
+                               namespaceDefinition.push( {
+                                       name: namespaceID,
+                                       label: label || mw.msg( 'blanknamespace' ),
+                                       description: '',
+                                       identifiers: [
+                                               ( namespaceID < 0 || namespaceID % 2 === 0 ) ?
+                                                       'subject' : 'talk'
+                                       ],
+                                       cssClass: 'mw-changeslist-ns-' + namespaceID
+                               } );
+                       } );
+
+                       // Add the group
+                       model.groups.namespace = new mw.rcfilters.dm.FilterGroup(
+                               'namespace', // Parameter name is singular
+                               {
+                                       type: 'string_options',
+                                       view: 'namespaces',
+                                       title: 'namespaces', // Message key
+                                       separator: ';',
+                                       labelPrefixKey: { 'default': 'rcfilters-tag-prefix-namespace', inverted: 'rcfilters-tag-prefix-namespace-inverted' },
+                                       fullCoverage: true
+                               }
+                       );
+                       // Add namespace items to group
+                       model.groups.namespace.initializeFilters( namespaceDefinition );
+                       items = items.concat( model.groups.namespace.getItems() );
+               }
+
                // Add item references to the model, for lookup
                this.addItems( items );
-
                // Expand conflicts
                groupConflictResult = expandConflictDefinitions( groupConflictMap );
                filterConflictResult = expandConflictDefinitions( filterConflictMap );
                        }
                } );
 
+               this.currentView = 'default';
+
                // Finish initialization
                this.emit( 'initialize' );
        };
                return this.groups;
        };
 
+       /**
+        * Get the object that defines groups that match a certain view by their name.
+        *
+        * @param {string} [view] Requested view. If not given, uses current view
+        * @return {Object} Filter groups matching a display group
+        */
+       mw.rcfilters.dm.FiltersViewModel.prototype.getFilterGroupsByView = function ( view ) {
+               var result = {};
+
+               view = view || this.getCurrentView();
+
+               $.each( this.groups, function ( groupName, groupModel ) {
+                       if ( groupModel.getView() === view ) {
+                               result[ groupName ] = groupModel;
+                       }
+               } );
+
+               return result;
+       };
+
+       /**
+        * Get an array of filters matching the given display group.
+        *
+        * @param {string} [view] Requested view. If not given, uses current view
+        * @return {mw.rcfilters.dm.FilterItem} Filter items matching the group
+        */
+       mw.rcfilters.dm.FiltersViewModel.prototype.getFiltersByView = function ( view ) {
+               var groups,
+                       result = [];
+
+               view = view || this.getCurrentView();
+
+               groups = this.getFilterGroupsByView( view );
+
+               $.each( groups, function ( groupName, groupModel ) {
+                       result = result.concat( groupModel.getItems() );
+               } );
+
+               return result;
+       };
+
+       /**
+        * Get the trigger for the requested view.
+        *
+        * @param {string} view View name
+        * @return {string} View trigger, if exists
+        */
+       mw.rcfilters.dm.FiltersViewModel.prototype.getViewTrigger = function ( view ) {
+               return this.views[ view ] && this.views[ view ].trigger;
+       };
        /**
         * Get the value of a specific parameter
         *
 
                // Get default filter state
                $.each( this.groups, function ( name, model ) {
-                       result = $.extend( true, {}, result, model.getDefaultParams() );
+                       $.extend( true, result, model.getDefaultParams() );
                } );
 
-               // Get default highlight state
-               result = $.extend( true, {}, result, this.getHighlightParameters() );
-
                return result;
        };
 
         *  arranged by their group names
         */
        mw.rcfilters.dm.FiltersViewModel.prototype.findMatches = function ( query, returnFlat ) {
-               var i,
+               var i, searchIsEmpty,
                        groupTitle,
                        result = {},
                        flatResult = [],
-                       items = this.getItems();
+                       view = query.indexOf( this.getViewTrigger( 'namespaces' ) ) === 0 ? 'namespaces' : 'default',
+                       items = this.getFiltersByView( view );
 
-               // Normalize so we can search strings regardless of case
+               // Normalize so we can search strings regardless of case and view
                query = query.toLowerCase();
+               if ( view === 'namespaces' ) {
+                       query = query.substr( 1 );
+               }
+
+               // Check if the search if actually empty; this can be a problem when
+               // we use prefixes to denote different views
+               searchIsEmpty = query.length === 0;
 
                // item label starting with the query string
                for ( i = 0; i < items.length; i++ ) {
-                       if ( items[ i ].getLabel().toLowerCase().indexOf( query ) === 0 ) {
+                       if (
+                               searchIsEmpty ||
+                               items[ i ].getLabel().toLowerCase().indexOf( query ) === 0
+                       ) {
                                result[ items[ i ].getGroupName() ] = result[ items[ i ].getGroupName() ] || [];
                                result[ items[ i ].getGroupName() ].push( items[ i ] );
                                flatResult.push( items[ i ] );
                        for ( i = 0; i < items.length; i++ ) {
                                groupTitle = items[ i ].getGroupModel().getTitle();
                                if (
+                                       searchIsEmpty ||
                                        items[ i ].getLabel().toLowerCase().indexOf( query ) > -1 ||
                                        items[ i ].getDescription().toLowerCase().indexOf( query ) > -1 ||
                                        groupTitle.toLowerCase().indexOf( query ) > -1
                } );
        };
 
+       /**
+        * Switch the current view
+        *
+        * @param {string} view View name
+        * @fires update
+        */
+       mw.rcfilters.dm.FiltersViewModel.prototype.switchView = function ( view ) {
+               if ( this.views[ view ] && this.currentView !== view ) {
+                       this.currentView = view;
+                       this.emit( 'update' );
+               }
+       };
+
+       /**
+        * Get the current view
+        *
+        * @return {string} Current view
+        */
+       mw.rcfilters.dm.FiltersViewModel.prototype.getCurrentView = function () {
+               return this.currentView;
+       };
+
+       /**
+        * Get the label for the current view
+        *
+        * @return {string} Label for the current view
+        */
+       mw.rcfilters.dm.FiltersViewModel.prototype.getCurrentViewLabel = function () {
+               return this.views[ this.getCurrentView() ].label;
+       };
+
        /**
         * Toggle the highlight feature on and off.
         * Propagate the change to filter items.
                return !!this.highlightEnabled;
        };
 
+       /**
+        * Toggle the inverted namespaces property on and off.
+        * Propagate the change to namespace filter items.
+        *
+        * @param {boolean} enable Inverted property is enabled
+        * @fires invertChange
+        */
+       mw.rcfilters.dm.FiltersViewModel.prototype.toggleInvertedNamespaces = function ( enable ) {
+               enable = enable === undefined ? !this.invertedNamespaces : enable;
+
+               if ( this.invertedNamespaces !== enable ) {
+                       this.invertedNamespaces = enable;
+
+                       this.getFiltersByView( 'namespaces' ).forEach( function ( filterItem ) {
+                               filterItem.toggleInverted( this.invertedNamespaces );
+                       }.bind( this ) );
+
+                       this.emit( 'invertChange', this.invertedNamespaces );
+               }
+       };
+
+       /**
+        * Check if the namespaces selection is set to be inverted
+        * @return {boolean}
+        */
+       mw.rcfilters.dm.FiltersViewModel.prototype.areNamespacesInverted = function () {
+               return !!this.invertedNamespaces;
+       };
+
        /**
         * Set highlight color for a specific filter item
         *
index 675fcc7..aa82e21 100644 (file)
@@ -9,6 +9,9 @@
         * @param {Object} config Configuration object
         * @cfg {string} [label] The label for the filter
         * @cfg {string} [description] The description of the filter
+        * @cfg {string|Object} [labelPrefixKey] An i18n key defining the prefix label for this
+        *  group. If the prefix has 'invert' state, the parameter is expected to be an object
+        *  with 'default' and 'inverted' as keys.
         * @cfg {boolean} [active=true] The filter is active and affecting the result
         * @cfg {boolean} [selected] The item is selected
         * @cfg {boolean} [inverted] The item is inverted, meaning the search is excluding
@@ -16,6 +19,8 @@
         * @cfg {string} [namePrefix='item_'] A prefix to add to the param name to act as a unique
         *  identifier
         * @cfg {string} [cssClass] The class identifying the results that match this filter
+        * @cfg {string[]} [identifiers] An array of identifiers for this item. They will be
+        *  added and considered in the view.
         */
        mw.rcfilters.dm.ItemModel = function MwRcfiltersDmItemModel( param, config ) {
                config = config || {};
                this.name = this.namePrefix + param;
 
                this.label = config.label || this.name;
-               this.description = config.description;
+               this.labelPrefixKey = config.labelPrefixKey;
+               this.description = config.description || '';
                this.selected = !!config.selected;
 
                this.inverted = !!config.inverted;
+               this.identifiers = config.identifiers || [];
 
                // Highlight
                this.cssClass = config.cssClass;
                return this.name;
        };
 
+       /**
+        * Get a prefixed label
+        *
+        * @return {string} Prefixed label
+        */
+       mw.rcfilters.dm.ItemModel.prototype.getPrefixedLabel = function () {
+               if ( this.labelPrefixKey ) {
+                       if ( typeof this.labelPrefixKey === 'string' ) {
+                               return mw.message( this.labelPrefixKey, this.getLabel() ).parse();
+                       } else {
+                               return mw.message(
+                                       this.labelPrefixKey[
+                                               // Only use inverted-prefix if the item is selected
+                                               // Highlight-only an inverted item makes no sense
+                                               this.isInverted() && this.isSelected() ?
+                                                       'inverted' : 'default'
+                                       ],
+                                       this.getLabel()
+                               ).parse();
+                       }
+               } else {
+                       return this.getLabel();
+               }
+       };
+
        /**
         * Get the param name or value of this filter
         *
                return this.cssClass;
        };
 
+       /**
+        * Get the item's identifiers
+        *
+        * @return {string[]}
+        */
+       mw.rcfilters.dm.ItemModel.prototype.getIdentifiers = function () {
+               return this.identifiers;
+       };
+
        /**
         * Toggle the highlight feature on and off for this filter.
         * It only works if highlight is supported for this filter.
index 375b68b..5e430c3 100644 (file)
@@ -13,7 +13,7 @@
                this.savedQueriesModel = savedQueriesModel;
                this.requestCounter = 0;
                this.baseFilterState = {};
-               this.emptyParameterState = {};
+               this.uriProcessor = null;
                this.initializing = false;
        };
 
         * Initialize the filter and parameter states
         *
         * @param {Array} filterStructure Filter definition and structure for the model
+        * @param {Object} [namespaceStructure] Namespace definition
         */
-       mw.rcfilters.Controller.prototype.initialize = function ( filterStructure ) {
-               var parsedSavedQueries, validParameterNames,
+       mw.rcfilters.Controller.prototype.initialize = function ( filterStructure, namespaceStructure ) {
+               var parsedSavedQueries,
                        uri = new mw.Uri(),
                        $changesList = $( '.mw-changeslist' ).first().contents();
 
                // Initialize the model
-               this.filtersModel.initializeFilters( filterStructure );
-
+               this.filtersModel.initializeFilters( filterStructure, namespaceStructure );
                this._buildBaseFilterState();
-               this._buildEmptyParameterState();
-               validParameterNames = Object.keys( this._getEmptyParameterState() )
-                       .filter( function ( param ) {
-                               // Remove 'highlight' parameter from this check;
-                               // if it's the only parameter in the URL we still
-                               // want to consider the URL 'empty' for defaults to load
-                               return param !== 'highlight';
-                       } );
+
+               this.uriProcessor = new mw.rcfilters.UriProcessor(
+                       this.filtersModel
+               );
 
                try {
                        parsedSavedQueries = JSON.parse( mw.user.options.get( 'rcfilters-saved-queries' ) || '{}' );
                // the user loads the base-page and we load defaults.
                // Defaults should only be applied on load (if necessary)
                // or on request
+               this.initializing = true;
                if (
-                       Object.keys( uri.query ).some( function ( parameter ) {
-                               return validParameterNames.indexOf( parameter ) > -1;
-                       } )
+                       this.savedQueriesModel.getDefault() &&
+                       !this.uriProcessor.doesQueryContainRecognizedParams( uri.query )
                ) {
-                       // There are parameters in the url, update model state
-                       this.updateStateBasedOnUrl();
+                       // We have defaults from a saved query.
+                       // We will load them straight-forward (as if
+                       // they were clicked in the menu) so we trigger
+                       // a full ajax request and change of URL
+                       this.applySavedQuery( this.savedQueriesModel.getDefault() );
                } else {
-                       this.initializing = true;
-                       // No valid parameters are given, load defaults
-                       this._updateModelState(
-                               $.extend(
-                                       true,
-                                       // We've ignored the highlight parameter for the sake
-                                       // of seeing whether we need to apply defaults - but
-                                       // while we do load the defaults, we still want to retain
-                                       // the actual value given in the URL for it on top of the
-                                       // defaults
-                                       { highlight: String( Number( uri.query.highlight ) ) },
-                                       this._getDefaultParams()
-                               )
+                       // There are either recognized parameters in the URL
+                       // or there are none, but there is also no default
+                       // saved query (so defaults are from the backend)
+                       // We want to update the state but not fetch results
+                       // again
+                       this.updateStateFromUrl( false );
+
+                       // Update the changes list with the existing data
+                       // so it gets processed
+                       this.changesListModel.update(
+                               $changesList.length ? $changesList : 'NO_RESULTS',
+                               $( 'fieldset.rcoptions' ).first()
                        );
-                       this.updateChangesList();
-                       this.initializing = false;
                }
 
-               // Update the changes list with the existing data
-               // so it gets processed
-               this.changesListModel.update(
-                       $changesList.length ? $changesList : 'NO_RESULTS',
-                       $( 'fieldset.rcoptions' ).first()
-               );
+               this.initializing = false;
+               this.switchView( 'default' );
+       };
+
+       /**
+        * Switch the view of the filters model
+        *
+        * @param {string} view Requested view
+        */
+       mw.rcfilters.Controller.prototype.switchView = function ( view ) {
+               this.filtersModel.switchView( view );
        };
 
        /**
         * Reset to default filters
         */
        mw.rcfilters.Controller.prototype.resetToDefaults = function () {
-               this._updateModelState( $.extend( true, { highlight: '0' }, this._getDefaultParams() ) );
+               this.uriProcessor.updateModelBasedOnQuery( this._getDefaultParams() );
                this.updateChangesList();
        };
 
                }
        };
 
+       /**
+        * Toggle the namespaces inverted feature on and off
+        */
+       mw.rcfilters.Controller.prototype.toggleInvertedNamespaces = function () {
+               this.filtersModel.toggleInvertedNamespaces();
+               this.updateChangesList();
+       };
+
        /**
         * Set the highlight color for a filter item
         *
                        label || mw.msg( 'rcfilters-savedqueries-defaultlabel' ),
                        {
                                filters: this.filtersModel.getSelectedState(),
-                               highlights: highlightedItems
+                               highlights: highlightedItems,
+                               invert: this.filtersModel.areNamespacesInverted()
                        }
                );
 
                        // Update model state from filters
                        this.filtersModel.toggleFiltersSelected( data.filters );
 
+                       // Update namespace inverted property
+                       this.filtersModel.toggleInvertedNamespaces( !!Number( data.invert ) );
+
                        // Update highlight state
                        this.filtersModel.toggleHighlight( !!Number( highlights.highlight ) );
                        this.filtersModel.getItems().forEach( function ( filterItem ) {
                return this.savedQueriesModel.findMatchingQuery(
                        {
                                filters: this.filtersModel.getSelectedState(),
-                               highlights: highlightedItems
+                               highlights: highlightedItems,
+                               invert: this.filtersModel.areNamespacesInverted()
                        }
                );
        };
 
                this.baseFilterState = {
                        filters: this.filtersModel.getFiltersFromParameters( defaultParams ),
-                       highlights: highlightedItems
+                       highlights: highlightedItems,
+                       invert: false
                };
        };
 
-       /**
-        * Build an empty representation of the parameters, where all parameters
-        * are either set to '0' or '' depending on their type.
-        * This must run during initialization, before highlights are set.
-        */
-       mw.rcfilters.Controller.prototype._buildEmptyParameterState = function () {
-               var emptyParams = this.filtersModel.getParametersFromFilters( {} ),
-                       emptyHighlights = this.filtersModel.getHighlightParameters();
-
-               this.emptyParameterState = $.extend(
-                       true,
-                       {},
-                       emptyParams,
-                       emptyHighlights,
-                       { highlight: '0' }
-               );
-       };
-
        /**
         * Get an object representing the base filter state of both
         * filters and highlights. The structure is similar to what we use
                return this.baseFilterState;
        };
 
-       /**
-        * Get an object representing the base state of parameters
-        * and highlights. The structure is similar to what we use
-        * to store each query in the saved queries object:
-        * {
-        *    param1: "value",
-        *    param2: "value1|value2"
-        * }
-        *
-        * @return {Object} Object representing the base state of
-        *  parameters and highlights
-        */
-       mw.rcfilters.Controller.prototype._getEmptyParameterState = function () {
-               return this.emptyParameterState;
-       };
-
        /**
         * Get an object that holds only the parameters and highlights that have
         * values different than the base default value.
         * without adding an history entry.
         */
        mw.rcfilters.Controller.prototype.replaceUrl = function () {
-               window.history.replaceState(
-                       { tag: 'rcfilters' },
-                       document.title,
-                       this._getUpdatedUri().toString()
-               );
+               mw.rcfilters.UriProcessor.static.replaceState( this._getUpdatedUri() );
        };
 
        /**
         * Update filter state (selection and highlighting) based
         * on current URL values.
+        *
+        * @param {boolean} [fetchChangesList=true] Fetch new results into the changes
+        *  list based on the updated model.
         */
-       mw.rcfilters.Controller.prototype.updateStateBasedOnUrl = function () {
-               var uri = new mw.Uri();
+       mw.rcfilters.Controller.prototype.updateStateFromUrl = function ( fetchChangesList ) {
+               fetchChangesList = fetchChangesList === undefined ? true : !!fetchChangesList;
 
-               this._updateModelState( uri.query );
-               this.updateChangesList();
+               this.uriProcessor.updateModelBasedOnQuery( new mw.Uri().query );
+
+               // Only update and fetch new results if it is requested
+               if ( fetchChangesList ) {
+                       this.updateChangesList();
+               }
        };
 
        /**
        };
 
        /**
-        * Update the model state from given the given parameters.
-        *
-        * This is an internal method, and should only be used from inside
-        * the controller.
+        * Get an object representing the default parameter state, whether
+        * it is from the model defaults or from the saved queries.
         *
-        * @param {Object} parameters Object representing the parameters for
-        *  filters and highlights
+        * @return {Object} Default parameters
         */
-       mw.rcfilters.Controller.prototype._updateModelState = function ( parameters ) {
-               // Update filter states
-               this.filtersModel.toggleFiltersSelected(
-                       this.filtersModel.getFiltersFromParameters(
-                               parameters
-                       )
-               );
+       mw.rcfilters.Controller.prototype._getDefaultParams = function () {
+               var data, queryHighlights,
+                       savedParams = {},
+                       savedHighlights = {},
+                       defaultSavedQueryItem = this.savedQueriesModel.getItemByID( this.savedQueriesModel.getDefault() );
 
-               // Update highlight state
-               this.filtersModel.toggleHighlight( !!Number( parameters.highlight ) );
-               this.filtersModel.getItems().forEach( function ( filterItem ) {
-                       var color = parameters[ filterItem.getName() + '_color' ];
-                       if ( color ) {
-                               filterItem.setHighlightColor( color );
-                       } else {
-                               filterItem.clearHighlightColor();
-                       }
-               } );
+               if ( mw.config.get( 'wgStructuredChangeFiltersEnableSaving' ) &&
+                       defaultSavedQueryItem ) {
 
-               // Check all filter interactions
-               this.filtersModel.reassessFilterInteractions();
+                       data = defaultSavedQueryItem.getData();
+
+                       queryHighlights = data.highlights || {};
+                       savedParams = this.filtersModel.getParametersFromFilters( data.filters || {} );
+
+                       // Translate highlights to parameters
+                       savedHighlights.highlight = String( Number( queryHighlights.highlight ) );
+                       $.each( queryHighlights, function ( filterName, color ) {
+                               if ( filterName !== 'highlights' ) {
+                                       savedHighlights[ filterName + '_color' ] = color;
+                               }
+                       } );
+
+                       return $.extend( true, {}, savedParams, savedHighlights, { invert: data.invert } );
+               }
+
+               return $.extend(
+                       { highlight: '0' },
+                       this.filtersModel.getDefaultParams()
+               );
        };
 
        /**
         * @param {Object} [params] Extra parameters to add to the API call
         */
        mw.rcfilters.Controller.prototype._updateURL = function ( params ) {
-               var currentFilterState, updatedFilterState, updatedUri,
-                       uri = new mw.Uri(),
-                       notEquivalent = function ( obj1, obj2 ) {
-                               var keys = Object.keys( obj1 ).concat( Object.keys( obj2 ) );
-                               return keys.some( function ( key ) {
-                                       return obj1[ key ] != obj2[ key ]; // eslint-disable-line eqeqeq
-                               } );
-                       };
-
-               params = params || {};
-
-               updatedUri = this._getUpdatedUri();
-               updatedUri.extend( params );
-
-               // Compare states instead of parameters
-               // This will allow us to always have a proper check of whether
-               // the requested new url is one to change or not, regardless of
-               // actual parameter visibility/representation in the URL
-               currentFilterState = this.filtersModel.getFiltersFromParameters( uri.query );
-               updatedFilterState = this.filtersModel.getFiltersFromParameters( updatedUri.query );
-               // HACK: Re-merge extra parameters in
-               // This is a hack and a quickfix; a better, more sustainable
-               // fix is being worked on with a UriProcessor, but for now
-               // we need to make sure the **comparison** of whether currentFilterState
-               // and updatedFilterState differ **includes** the extra parameters in the URL
-               currentFilterState = $.extend( true, {}, uri.query, currentFilterState );
-               updatedFilterState = $.extend( true, {}, updatedUri.query, updatedFilterState );
-
-               // Include highlight states
-               $.extend( true,
-                       currentFilterState,
-                       this.filtersModel.extractHighlightValues( uri.query ),
-                       { highlight: !!Number( uri.query.highlight ) }
-               );
-               $.extend( true,
-                       updatedFilterState,
-                       this.filtersModel.extractHighlightValues( updatedUri.query ),
-                       { highlight: !!Number( updatedUri.query.highlight ) }
-               );
+               var currentUri = new mw.Uri(),
+                       updatedUri = this._getUpdatedUri();
+
+               updatedUri.extend( params || {} );
 
-               if ( notEquivalent( currentFilterState, updatedFilterState ) ) {
+               if (
+                       this.uriProcessor.getVersion( currentUri.query ) !== 2 ||
+                       this.uriProcessor.isNewState( currentUri.query, updatedUri.query )
+               ) {
                        if ( this.initializing ) {
                                // Initially, when we just build the first page load
                                // out of defaults, we want to replace the history
-                               window.history.replaceState( { tag: 'rcfilters' }, document.title, updatedUri.toString() );
+                               mw.rcfilters.UriProcessor.static.replaceState( updatedUri );
                        } else {
-                               window.history.pushState( { tag: 'rcfilters' }, document.title, updatedUri.toString() );
+                               mw.rcfilters.UriProcessor.static.pushState( updatedUri );
                        }
                }
        };
         * @return {mw.Uri} Updated Uri
         */
        mw.rcfilters.Controller.prototype._getUpdatedUri = function () {
-               var uri = new mw.Uri(),
-                       highlightParams = this.filtersModel.getHighlightParameters(),
-                       modelParameters = this.filtersModel.getParametersFromFilters(),
-                       baseParams = this._getEmptyParameterState();
-
-               // Minimize values of the model parameters; show only the values that
-               // are non-zero. We assume that all parameters that are not literally
-               // showing in the URL are set to zero or empty
-               $.each( modelParameters, function ( paramName, value ) {
-                       if ( baseParams[ paramName ] !== value ) {
-                               uri.query[ paramName ] = value;
-                       } else {
-                               // We need to remove this value from the url
-                               delete uri.query[ paramName ];
-                       }
-               } );
+               var uri = new mw.Uri();
 
-               // highlight params
-               if ( this.filtersModel.isHighlightEnabled() ) {
-                       uri.query.highlight = Number( this.filtersModel.isHighlightEnabled() );
-               } else {
-                       delete uri.query.highlight;
-               }
-               $.each( highlightParams, function ( paramName, value ) {
-                       // Only output if it is different than the base parameters
-                       if ( baseParams[ paramName ] !== value ) {
-                               uri.query[ paramName ] = value;
-                       } else {
-                               delete uri.query[ paramName ];
-                       }
-               } );
+               // Minimize url
+               uri.query = this.uriProcessor.minimizeQuery(
+                       $.extend(
+                               true,
+                               {},
+                               // We want to retain unrecognized params
+                               // The uri params from model will override
+                               // any recognized value in the current uri
+                               // query, retain unrecognized params, and
+                               // the result will then be minimized
+                               uri.query,
+                               this.uriProcessor.getUriParametersFromModel(),
+                               { urlversion: '2' }
+                       )
+               );
 
                return uri;
        };
diff --git a/resources/src/mediawiki.rcfilters/mw.rcfilters.UriProcessor.js b/resources/src/mediawiki.rcfilters/mw.rcfilters.UriProcessor.js
new file mode 100644 (file)
index 0000000..b7852d0
--- /dev/null
@@ -0,0 +1,275 @@
+( function ( mw, $ ) {
+       /* eslint no-underscore-dangle: "off" */
+       /**
+        * URI Processor for RCFilters
+        *
+        * @param {mw.rcfilters.dm.FiltersViewModel} filtersModel Filters view model
+        */
+       mw.rcfilters.UriProcessor = function MwRcfiltersController( filtersModel ) {
+               this.emptyParameterState = {};
+               this.filtersModel = filtersModel;
+
+               // Initialize
+               this._buildEmptyParameterState();
+       };
+
+       /* Initialization */
+       OO.initClass( mw.rcfilters.UriProcessor );
+
+       /* Static methods */
+
+       /**
+        * Replace the url history through replaceState
+        *
+        * @param {mw.Uri} newUri New URI to replace
+        */
+       mw.rcfilters.UriProcessor.static.replaceState = function ( newUri ) {
+               window.history.replaceState(
+                       { tag: 'rcfilters' },
+                       document.title,
+                       newUri.toString()
+               );
+       };
+
+       /**
+        * Push the url to history through pushState
+        *
+        * @param {mw.Uri} newUri New URI to push
+        */
+       mw.rcfilters.UriProcessor.static.pushState = function ( newUri ) {
+               window.history.pushState(
+                       { tag: 'rcfilters' },
+                       document.title,
+                       newUri.toString()
+               );
+       };
+
+       /* Methods */
+
+       /**
+        * Get the version that this URL query is tagged with.
+        *
+        * @param {Object} [uriQuery] URI query
+        * @return {number} URL version
+        */
+       mw.rcfilters.UriProcessor.prototype.getVersion = function ( uriQuery ) {
+               uriQuery = uriQuery || new mw.Uri().query;
+
+               return Number( uriQuery.urlversion || 1 );
+       };
+
+       /**
+        * Update the filters model based on the URI query
+        * This happens on initialization, and from this moment on,
+        * we consider the system synchronized, and the model serves
+        * as the source of truth for the URL.
+        *
+        * This methods should only be called once on initialiation.
+        * After initialization, the model updates the URL, not the
+        * other way around.
+        *
+        * @param {Object} [uriQuery] URI query
+        */
+       mw.rcfilters.UriProcessor.prototype.updateModelBasedOnQuery = function ( uriQuery ) {
+               var parameters = this._getNormalizedQueryParams( uriQuery || new mw.Uri().query );
+
+               // Update filter states
+               this.filtersModel.toggleFiltersSelected(
+                       this.filtersModel.getFiltersFromParameters(
+                               parameters
+                       )
+               );
+
+               this.filtersModel.toggleInvertedNamespaces( !!Number( parameters.invert ) );
+
+               // Update highlight state
+               this.filtersModel.toggleHighlight( !!Number( parameters.highlight ) );
+               this.filtersModel.getItems().forEach( function ( filterItem ) {
+                       var color = parameters[ filterItem.getName() + '_color' ];
+                       if ( color ) {
+                               filterItem.setHighlightColor( color );
+                       } else {
+                               filterItem.clearHighlightColor();
+                       }
+               } );
+
+               // Check all filter interactions
+               this.filtersModel.reassessFilterInteractions();
+       };
+
+       /**
+        * Get parameters representing the current state of the model
+        *
+        * @return {Object} Uri query parameters
+        */
+       mw.rcfilters.UriProcessor.prototype.getUriParametersFromModel = function () {
+               return $.extend(
+                       true,
+                       {},
+                       this.filtersModel.getParametersFromFilters(),
+                       this.filtersModel.getHighlightParameters(),
+                       {
+                               highlight: String( Number( this.filtersModel.isHighlightEnabled() ) ),
+                               invert: String( Number( this.filtersModel.areNamespacesInverted() ) )
+                       }
+               );
+       };
+
+       /**
+        * Build the full parameter representation based on given query parameters
+        *
+        * @private
+        * @param {Object} uriQuery Given URI query
+        * @return {Object} Full parameter state representing the URI query
+        */
+       mw.rcfilters.UriProcessor.prototype._expandModelParameters = function ( uriQuery ) {
+               var filterRepresentation = this.filtersModel.getFiltersFromParameters( uriQuery );
+
+               return $.extend( true,
+                       {},
+                       uriQuery,
+                       this.filtersModel.getParametersFromFilters( filterRepresentation ),
+                       this.filtersModel.extractHighlightValues( uriQuery ),
+                       {
+                               highlight: String( Number( uriQuery.highlight ) ),
+                               invert: String( Number( uriQuery.invert ) )
+                       }
+               );
+       };
+
+       /**
+        * Compare two URI queries to decide whether they are different
+        * enough to represent a new state.
+        *
+        * @param {Object} currentUriQuery Current Uri query
+        * @param {Object} updatedUriQuery Updated Uri query
+        * @return {boolean} This is a new state
+        */
+       mw.rcfilters.UriProcessor.prototype.isNewState = function ( currentUriQuery, updatedUriQuery ) {
+               var currentParamState, updatedParamState,
+                       notEquivalent = function ( obj1, obj2 ) {
+                               var keys = Object.keys( obj1 ).concat( Object.keys( obj2 ) );
+                               return keys.some( function ( key ) {
+                                       return obj1[ key ] != obj2[ key ]; // eslint-disable-line eqeqeq
+                               } );
+                       };
+
+               // Compare states instead of parameters
+               // This will allow us to always have a proper check of whether
+               // the requested new url is one to change or not, regardless of
+               // actual parameter visibility/representation in the URL
+               currentParamState = this._expandModelParameters( currentUriQuery );
+               updatedParamState = this._expandModelParameters( updatedUriQuery );
+
+               return notEquivalent( currentParamState, updatedParamState );
+       };
+
+       /**
+        * Check whether the given query has parameters that are
+        * recognized as parameters we should load the system with
+        *
+        * @param {mw.Uri} [uriQuery] Given URI query
+        * @return {boolean} Query contains valid recognized parameters
+        */
+       mw.rcfilters.UriProcessor.prototype.doesQueryContainRecognizedParams = function ( uriQuery ) {
+               var anyValidInUrl,
+                       validParameterNames = Object.keys( this._getEmptyParameterState() )
+                               .filter( function ( param ) {
+                                       // Remove 'highlight' parameter from this check;
+                                       // if it's the only parameter in the URL we still
+                                       // want to consider the URL 'empty' for defaults to load
+                                       return param !== 'highlight';
+                               } );
+
+               uriQuery = uriQuery || new mw.Uri().query;
+
+               anyValidInUrl = Object.keys( uriQuery ).some( function ( parameter ) {
+                       return validParameterNames.indexOf( parameter ) > -1;
+               } );
+
+               // URL version 2 is allowed to be empty or within nonrecognized params
+               return anyValidInUrl || this.getVersion( uriQuery ) === 2;
+       };
+
+       /**
+        * Remove all parameters that have the same value as the base state
+        * This method expects uri queries of the urlversion=2 format
+        *
+        * @private
+        * @param {Object} uriQuery Current uri query
+        * @return {Object} Minimized query
+        */
+       mw.rcfilters.UriProcessor.prototype.minimizeQuery = function ( uriQuery ) {
+               var baseParams = this._getEmptyParameterState(),
+                       uriResult = $.extend( true, {}, uriQuery );
+
+               $.each( uriResult, function ( paramName, paramValue ) {
+                       if (
+                               baseParams[ paramName ] !== undefined &&
+                               baseParams[ paramName ] === paramValue
+                       ) {
+                               // Remove parameter from query
+                               delete uriResult[ paramName ];
+                       }
+               } );
+
+               return uriResult;
+       };
+
+       /**
+        * Get the adjusted URI params based on the url version
+        * If the urlversion is not 2, the parameters are merged with
+        * the model's defaults.
+        *
+        * @private
+        * @param {Object} uriQuery Current URI query
+        * @return {Object} Normalized parameters
+        */
+       mw.rcfilters.UriProcessor.prototype._getNormalizedQueryParams = function ( uriQuery ) {
+               // Check whether we are dealing with urlversion=2
+               // If we are, we do not merge the initial request with
+               // defaults. Not having urlversion=2 means we need to
+               // reproduce the server-side request and merge the
+               // requested parameters (or starting state) with the
+               // wiki default.
+               // Any subsequent change of the URL through the RCFilters
+               // system will receive 'urlversion=2'
+               var base = this.getVersion( uriQuery ) === 2 ?
+                       {} :
+                       this.filtersModel.getDefaultParams();
+
+               return this.minimizeQuery(
+                       $.extend( true, {}, base, uriQuery, { urlversion: '2' } )
+               );
+       };
+
+       /**
+        * Get the representation of an empty parameter state
+        *
+        * @private
+        * @return {Object} Empty parameter state
+        */
+       mw.rcfilters.UriProcessor.prototype._getEmptyParameterState = function () {
+               return this.emptyParameterState;
+       };
+
+       /**
+        * Build an empty representation of the parameters, where all parameters
+        * are either set to '0' or '' depending on their type.
+        * This must run during initialization, before highlights are set.
+        *
+        * @private
+        */
+       mw.rcfilters.UriProcessor.prototype._buildEmptyParameterState = function () {
+               var emptyParams = this.filtersModel.getParametersFromFilters( {} ),
+                       emptyHighlights = this.filtersModel.getHighlightParameters();
+
+               this.emptyParameterState = $.extend(
+                       true,
+                       {},
+                       emptyParams,
+                       emptyHighlights,
+                       { highlight: '0', invert: '0' }
+               );
+       };
+}( mediaWiki, jQuery ) );
index dd8fae0..03edca3 100644 (file)
@@ -24,7 +24,7 @@
                        new mw.rcfilters.ui.ChangesListWrapperWidget(
                                filtersModel, changesListModel, $( '.mw-changeslist, .mw-changeslist-empty' ) );
 
-                       controller.initialize( mw.config.get( 'wgStructuredChangeFilters' ) );
+                       controller.initialize( mw.config.get( 'wgStructuredChangeFilters' ), mw.config.get( 'wgFormattedNamespaces' ) );
 
                        // eslint-disable-next-line no-new
                        new mw.rcfilters.ui.FormWrapperWidget(
@@ -37,8 +37,9 @@
                        $( '.rcfilters-head' ).addClass( 'mw-rcfilters-ui-ready' );
 
                        window.addEventListener( 'popstate', function () {
-                               controller.updateStateBasedOnUrl();
-                               controller.updateChangesList();
+                               // Update the state of the model from the URL
+                               // and re-fetch results into the changes list
+                               controller.updateStateFromUrl();
                        } );
 
                        $( 'a.mw-helplink' ).attr(
index 4914dd9..24907b9 100644 (file)
@@ -12,6 +12,7 @@
                border-bottom: 1px solid #c8ccd1;
                background: #f8f9fa;
 
+               &-invert,
                &-highlight {
                        width: 1em;
                        vertical-align: middle;
index 1029d54..00ec87c 100644 (file)
@@ -3,4 +3,8 @@
        width: 100%;
        // Make sure this uses the interface direction, not the content direction
        direction: ltr;
+
+       &-namespaceToggle {
+               margin-top: 1em;
+       }
 }
index 44c5529..86bfafb 100644 (file)
@@ -1,6 +1,7 @@
 @import 'mediawiki.mixins';
 
 .mw-rcfilters-ui-itemMenuOptionWidget {
+       min-height: 3.5em;
        padding: 0 0.5em;
        .box-sizing( border-box );
 
@@ -8,6 +9,15 @@
                border-bottom: solid 1px #eaecf0; // Base 80 AAA
        }
 
+       &-view-namespaces {
+               border-top: 5px solid #ccc;
+
+               &:first-child,
+               &.mw-rcfilters-ui-itemMenuOptionWidget-identifier-subject + &.mw-rcfilters-ui-itemMenuOptionWidget-identifier-talk {
+                       border-top: 0;
+               }
+       }
+
        &:hover {
                background-color: #fbfbfb;
        }
                }
        }
 
+       .mw-rcfilters-ui-cell {
+               vertical-align: middle;
+       }
+
+       &-excludeLabel {
+               width: 5em;
+               padding-left: 1em;
+               color: #54595d; // Base20 AAA
+       }
+
        &-highlightButton {
                width: 4em;
                padding-left: 1em;
index 15e7eee..b8b68a7 100644 (file)
                        classes: [ 'mw-rcfilters-ui-filterMenuHeaderWidget-hightlightButton' ]
                } );
 
+               // Invert namespaces button
+               this.invertNamespacesButton = new OO.ui.ToggleButtonWidget( {
+                       icon: '',
+                       label: mw.msg( 'invert' ),
+                       classes: [ 'mw-rcfilters-ui-filterMenuHeaderWidget-invertNamespacesButton' ]
+               } );
+               this.invertNamespacesButton.toggle( this.model.getCurrentView() === 'namespaces' );
+
                // Events
                this.highlightButton
                        .connect( this, { click: 'onHighlightButtonClick' } );
-               this.model.connect( this, { highlightChange: 'onModelHighlightChange' } );
+               this.invertNamespacesButton
+                       .connect( this, { click: 'onInvertNamespacesButtonClick' } );
+               this.model.connect( this, {
+                       highlightChange: 'onModelHighlightChange',
+                       invertChange: 'onModelInvertChange',
+                       update: 'onModelUpdate'
+               } );
 
                // Initialize
                this.$element
                                                                        .addClass( 'mw-rcfilters-ui-cell' )
                                                                        .addClass( 'mw-rcfilters-ui-filterMenuHeaderWidget-header-title' )
                                                                        .append( this.$label ),
+                                                               $( '<div>' )
+                                                                       .addClass( 'mw-rcfilters-ui-cell' )
+                                                                       .addClass( 'mw-rcfilters-ui-filterMenuHeaderWidget-header-invert' )
+                                                                       .append( this.invertNamespacesButton.$element ),
                                                                $( '<div>' )
                                                                        .addClass( 'mw-rcfilters-ui-cell' )
                                                                        .addClass( 'mw-rcfilters-ui-filterMenuHeaderWidget-header-highlight' )
 
        /* Methods */
 
+       /**
+        * Respond to model update event
+        */
+       mw.rcfilters.ui.FilterMenuHeaderWidget.prototype.onModelUpdate = function () {
+               this.setLabel( this.model.getCurrentViewLabel() );
+
+               this.invertNamespacesButton.toggle( this.model.getCurrentView() === 'namespaces' );
+       };
+
        /**
         * Respond to model highlight change event
         *
                this.highlightButton.setActive( highlightEnabled );
        };
 
+       /**
+        * Respond to model invert change event
+        *
+        * @param {boolean} isInverted Namespaces selection is inverted
+        */
+       mw.rcfilters.ui.FilterMenuHeaderWidget.prototype.onModelInvertChange = function ( isInverted ) {
+               this.invertNamespacesButton.setActive( isInverted );
+       };
+
        /**
         * Respond to highlight button click
         */
        mw.rcfilters.ui.FilterMenuHeaderWidget.prototype.onHighlightButtonClick = function () {
                this.controller.toggleHighlight();
        };
+
+       /**
+        * Respond to highlight button click
+        */
+       mw.rcfilters.ui.FilterMenuHeaderWidget.prototype.onInvertNamespacesButtonClick = function () {
+               this.controller.toggleInvertedNamespaces();
+       };
 }( mediaWiki, jQuery ) );
index e14c1fa..b1927c6 100644 (file)
                this.resetButton.$element.on( 'mousedown', function ( e ) { e.stopPropagation(); } );
                this.model.connect( this, {
                        initialize: 'onModelInitialize',
+                       update: 'onModelUpdate',
                        itemUpdate: 'onModelItemUpdate',
                        highlightChange: 'onModelHighlightChange'
                } );
+               this.input.connect( this, { change: 'onInputChange' } );
                this.queriesModel.connect( this, { itemUpdate: 'onSavedQueriesItemUpdate' } );
 
                // The filter list and button should appear side by side regardless of how
                this.$element
                        .addClass( 'mw-rcfilters-ui-filterTagMultiselectWidget' );
 
-               this.populateFromModel();
                this.reevaluateResetRestoreState();
        };
 
 
        /* Methods */
 
+       /**
+        * Respond to input change event
+        *
+        * @param {string} value Value of the input
+        */
+       mw.rcfilters.ui.FilterTagMultiselectWidget.prototype.onInputChange = function ( value ) {
+               var view = 'default';
+
+               if ( value.indexOf( this.model.getViewTrigger( 'namespaces' ) ) === 0 ) {
+                       view = 'namespaces';
+               }
+
+               this.controller.switchView( view );
+       };
        /**
         * Respond to query button click
         */
                } else {
                        // Clear selection
                        this.selectTag( null );
+
+                       // Clear input if the only thing in the input is the prefix
+                       if (
+                               this.input.getValue() === this.model.getViewTrigger( this.model.getCurrentView() )
+                       ) {
+                               // Clear the input
+                               this.input.setValue( '' );
+                       }
                }
        };
 
         * Respond to model initialize event
         */
        mw.rcfilters.ui.FilterTagMultiselectWidget.prototype.onModelInitialize = function () {
-               this.populateFromModel();
-
                this.setSavedQueryVisibility();
        };
 
+       /**
+        * Respond to model update event
+        */
+       mw.rcfilters.ui.FilterTagMultiselectWidget.prototype.onModelUpdate = function () {
+               this.updateElementsForView();
+       };
+
+       /**
+        * Update the elements in the widget to the current view
+        */
+       mw.rcfilters.ui.FilterTagMultiselectWidget.prototype.updateElementsForView = function () {
+               var view = this.model.getCurrentView(),
+                       inputValue = this.input.getValue(),
+                       newInputValue = inputValue;
+
+               switch ( view ) {
+                       case 'namespaces':
+                               if ( inputValue.indexOf( this.model.getViewTrigger( 'namespaces' ) ) !== 0 ) {
+                                       // Add the prefix to the input
+                                       newInputValue = this.model.getViewTrigger( 'namespaces' ) + inputValue;
+                               }
+                               break;
+                       default:
+                       case 'default':
+                               if ( inputValue.indexOf( this.model.getViewTrigger( 'namespaces' ) ) === 0 ) {
+                                       // Remove the prefix
+                                       newInputValue = inputValue.substr( 1 );
+                               }
+                               break;
+               }
+
+               // Update input
+               this.input.setValue( newInputValue );
+       };
+
        /**
         * Set the visibility of the saved query button
         */
                        );
                }
        };
+
        /**
         * Respond to model itemUpdate event
         *
         */
        mw.rcfilters.ui.FilterTagMultiselectWidget.prototype.isAllowedData = function ( data ) {
                return (
-                       this.menu.getItemFromData( data ) &&
+                       this.model.getItemByName( data ) &&
                        !this.isDuplicateData( data )
                );
        };
         */
        mw.rcfilters.ui.FilterTagMultiselectWidget.prototype.onTagSelect = function ( tagItem ) {
                var widget = this,
-                       menuOption = this.menu.getItemFromData( tagItem.getData() ),
+                       menuOption = this.menu.getItemFromModel( tagItem.getModel() ),
                        oldInputValue = this.input.getValue();
 
                // Reset input
                this.input.setValue( '' );
 
+               // Switch view
+               this.controller.switchView( tagItem.getView() );
+
                // Parent method
                mw.rcfilters.ui.FilterTagMultiselectWidget.parent.prototype.onTagSelect.call( this, tagItem );
 
                );
        };
 
-       /**
-        * Populate the menu from the model
-        */
-       mw.rcfilters.ui.FilterTagMultiselectWidget.prototype.populateFromModel = function () {
-               var widget = this,
-                       items = [];
-
-               // Reset
-               this.getMenu().clearItems();
-
-               $.each( this.model.getFilterGroups(), function ( groupName, groupModel ) {
-                       items.push(
-                               // Group section
-                               new mw.rcfilters.ui.FilterMenuSectionOptionWidget(
-                                       widget.controller,
-                                       groupModel,
-                                       {
-                                               $overlay: widget.$overlay
-                                       }
-                               )
-                       );
-
-                       // Add items
-                       widget.model.getGroupFilters( groupName ).forEach( function ( filterItem ) {
-                               items.push(
-                                       new mw.rcfilters.ui.FilterMenuOptionWidget(
-                                               widget.controller,
-                                               filterItem,
-                                               {
-                                                       $overlay: widget.$overlay
-                                               }
-                                       )
-                               );
-                       } );
-               } );
-
-               // Add all items to the menu
-               this.getMenu().addItems( items );
-       };
-
        /**
         * @inheritdoc
         */
index ebef62f..e007621 100644 (file)
                        { $overlay: this.$overlay }
                );
 
+               this.namespaceButton = new OO.ui.ButtonWidget( {
+                       label: mw.msg( 'namespaces' ),
+                       icon: 'article',
+                       classes: [ 'mw-rcfilters-ui-filterWrapperWidget-namespaceToggle' ]
+               } );
+               this.namespaceButton.setActive( this.model.getCurrentView() === 'namespaces' );
+
+               // Events
+               this.model.connect( this, { update: 'onModelUpdate' } );
+               this.namespaceButton.connect( this, { click: 'onNamespaceToggleClick' } );
+
                // Initialize
                this.$element
                        .addClass( 'mw-rcfilters-ui-filterWrapperWidget' );
                }
 
                this.$element.append(
-                       this.filterTagWidget.$element
+                       this.filterTagWidget.$element,
+                       this.namespaceButton.$element
                );
+               this.namespaceButton.toggle( !!mw.config.get( 'wgStructuredChangeFiltersEnableExperimentalViews' ) );
        };
 
        /* Initialization */
 
        OO.inheritClass( mw.rcfilters.ui.FilterWrapperWidget, OO.ui.Widget );
        OO.mixinClass( mw.rcfilters.ui.FilterWrapperWidget, OO.ui.mixin.PendingElement );
+
+       /* Methods */
+
+       /**
+        * Respond to model update event
+        */
+       mw.rcfilters.ui.FilterWrapperWidget.prototype.onModelUpdate = function () {
+               // Synchronize the state of the toggle button with the current view
+               this.namespaceButton.setActive( this.model.getCurrentView() === 'namespaces' );
+       };
+
+       /**
+        * Respond to namespace toggle button click
+        */
+       mw.rcfilters.ui.FilterWrapperWidget.prototype.onNamespaceToggleClick = function () {
+               this.controller.switchView( 'namespaces' );
+               this.filterTagWidget.focus();
+       };
 }( mediaWiki ) );
index 7605fae..721d4ab 100644 (file)
         */
        mw.rcfilters.ui.FormWrapperWidget.prototype.cleanUpFieldset = function () {
                var $namespaceSelect = this.$element.find( '#namespace' ),
-                       $namespaceCheckboxes = this.$element.find( '#nsassociated, #nsinvert' ),
                        collapseCookieName = 'changeslist-state';
 
                this.$element.find( '.rcshowhideoption[data-feature-in-structured-ui=1]' ).each( function () {
                        this.parentNode.removeChild( this );
                } );
 
-               // Bind namespace select to change event
-               // see resources/src/mediawiki.special/mediawiki.special.recentchanges.js
-               $namespaceCheckboxes.prop( 'disabled', $namespaceSelect.val() === '' );
-               $namespaceSelect.on( 'change', function () {
-                       $namespaceCheckboxes.prop( 'disabled', $( this ).val() === '' );
-               } );
+               // Hide namespaces
+               if ( mw.config.get( 'wgStructuredChangeFiltersEnableExperimentalViews' ) ) {
+                       $namespaceSelect.closest( 'tr' ).detach();
+               }
 
                // Collapse legend
                // see resources/src/mediawiki.special/mediawiki.special.changelist.legend.js
index a88d119..f2e9b1d 100644 (file)
@@ -11,6 +11,7 @@
         */
        mw.rcfilters.ui.ItemMenuOptionWidget = function MwRcfiltersUiItemMenuOptionWidget( controller, model, config ) {
                var layout,
+                       classes = [],
                        $label = $( '<div>' )
                                .addClass( 'mw-rcfilters-ui-itemMenuOptionWidget-label' );
 
                );
                this.highlightButton.toggle( this.model.isHighlightEnabled() );
 
+               this.excludeLabel = new OO.ui.LabelWidget( {
+                       label: mw.msg( 'rcfilters-filter-excluded' )
+               } );
+               this.excludeLabel.toggle( this.model.isSelected() && this.model.isInverted() );
+
                layout = new OO.ui.FieldLayout( this.checkboxWidget, {
                        label: $label,
                        align: 'inline'
@@ -71,6 +77,7 @@
 
                this.$element
                        .addClass( 'mw-rcfilters-ui-itemMenuOptionWidget' )
+                       .addClass( 'mw-rcfilters-ui-itemMenuOptionWidget-view-' + this.model.getGroupModel().getView() )
                        .append(
                                $( '<div>' )
                                        .addClass( 'mw-rcfilters-ui-table' )
                                                                $( '<div>' )
                                                                        .addClass( 'mw-rcfilters-ui-cell mw-rcfilters-ui-itemMenuOptionWidget-itemCheckbox' )
                                                                        .append( layout.$element ),
+                                                               $( '<div>' )
+                                                                       .addClass( 'mw-rcfilters-ui-cell mw-rcfilters-ui-itemMenuOptionWidget-excludeLabel' )
+                                                                       .append( this.excludeLabel.$element ),
                                                                $( '<div>' )
                                                                        .addClass( 'mw-rcfilters-ui-cell mw-rcfilters-ui-itemMenuOptionWidget-highlightButton' )
                                                                        .append( this.highlightButton.$element )
                                                        )
                                        )
                        );
+
+               if ( this.model.getIdentifiers() ) {
+                       this.model.getIdentifiers().forEach( function ( ident ) {
+                               classes.push( 'mw-rcfilters-ui-itemMenuOptionWidget-identifier-' + ident );
+                       } );
+
+                       this.$element.addClass( classes.join( ' ' ) );
+               }
        };
 
        /* Initialization */
                this.checkboxWidget.setSelected( this.model.isSelected() );
 
                this.highlightButton.toggle( this.model.isHighlightEnabled() );
+               this.excludeLabel.toggle( this.model.isSelected() && this.model.isInverted() );
        };
 
        /**
index 91de969..d971faf 100644 (file)
@@ -18,6 +18,8 @@
 
                this.controller = controller;
                this.model = model;
+               this.currentView = '';
+               this.views = {};
 
                this.inputValue = '';
                this.$overlay = config.$overlay || this.$element;
                        classes: [ 'mw-rcfilters-ui-menuSelectWidget-noresults' ]
                } );
 
+               // Events
+               this.model.connect( this, {
+                       update: 'onModelUpdate',
+                       initialize: 'onModelInitialize'
+               } );
+
+               // Initialization
                this.$element
                        .addClass( 'mw-rcfilters-ui-menuSelectWidget' )
                        .append( header.$element )
@@ -64,6 +73,7 @@
                                        .addClass( 'mw-rcfilters-ui-menuSelectWidget-footer' )
                        );
                }
+               this.switchView( this.model.getCurrentView() );
        };
 
        /* Initialize */
 
        /* Methods */
 
+       /**
+        * Respond to model update event
+        */
+       mw.rcfilters.ui.MenuSelectWidget.prototype.onModelUpdate = function () {
+               // Change view
+               this.switchView( this.model.getCurrentView() );
+       };
+
+       /**
+        * Respond to model initialize event. Populate the menu from the model
+        */
+       mw.rcfilters.ui.MenuSelectWidget.prototype.onModelInitialize = function () {
+               var widget = this,
+                       viewGroupCount = {},
+                       groups = this.model.getFilterGroups();
+
+               // Reset
+               this.clearItems();
+
+               // Count groups per view
+               $.each( groups, function ( groupName, groupModel ) {
+                       viewGroupCount[ groupModel.getView() ] = viewGroupCount[ groupModel.getView() ] || 0;
+                       viewGroupCount[ groupModel.getView() ]++;
+               } );
+
+               $.each( groups, function ( groupName, groupModel ) {
+                       var currentItems = [],
+                               view = groupModel.getView();
+
+                       if ( viewGroupCount[ view ] > 1 ) {
+                               // Only add a section header if there is more than
+                               // one group
+                               currentItems.push(
+                                       // Group section
+                                       new mw.rcfilters.ui.FilterMenuSectionOptionWidget(
+                                               widget.controller,
+                                               groupModel,
+                                               {
+                                                       $overlay: widget.$overlay
+                                               }
+                                       )
+                               );
+                       }
+
+                       // Add items
+                       widget.model.getGroupFilters( groupName ).forEach( function ( filterItem ) {
+                               currentItems.push(
+                                       new mw.rcfilters.ui.FilterMenuOptionWidget(
+                                               widget.controller,
+                                               filterItem,
+                                               {
+                                                       $overlay: widget.$overlay
+                                               }
+                                       )
+                               );
+                       } );
+
+                       // Cache the items per view, so we can switch between them
+                       // without rebuilding the widgets each time
+                       widget.views[ view ] = widget.views[ view ] || [];
+                       widget.views[ view ] = widget.views[ view ].concat( currentItems );
+               } );
+
+               this.switchView( this.model.getCurrentView() );
+       };
+
+       /**
+        * Switch view
+        *
+        * @param {string} [viewName] View name. If not given, default is used.
+        */
+       mw.rcfilters.ui.MenuSelectWidget.prototype.switchView = function ( viewName ) {
+               viewName = viewName || 'default';
+
+               if ( this.views[ viewName ] && this.currentView !== viewName ) {
+                       this.clearItems();
+                       this.addItems( this.views[ viewName ] );
+
+                       this.$element
+                               .data( 'view', viewName )
+                               .removeClass( 'mw-rcfilters-ui-menuSelectWidget-view-' + this.currentView )
+                               .addClass( 'mw-rcfilters-ui-menuSelectWidget-view-' + viewName );
+
+                       this.currentView = viewName;
+               }
+       };
+
        /**
         * @fires itemVisibilityChange
         * @inheritdoc
                }
        };
 
+       /**
+        * Get the option widget that matches the model given
+        *
+        * @param {mw.rcfilters.dm.ItemModel} model Item model
+        * @return {mw.rcfilters.ui.ItemMenuOptionWidget} Option widget
+        */
+       mw.rcfilters.ui.MenuSelectWidget.prototype.getItemFromModel = function ( model ) {
+               return this.views[ model.getGroupModel().getView() ].filter( function ( item ) {
+                       return item.getName() === model.getName();
+               } )[ 0 ];
+       };
+
        /**
         * Override the item matcher to use the model's match process
         *
index 637dbdc..886f6d4 100644 (file)
@@ -22,7 +22,7 @@
 
                mw.rcfilters.ui.TagItemWidget.parent.call( this, $.extend( {
                        data: this.model.getName(),
-                       label: this.model.getLabel()
+                       label: $( '<div>' ).html( this.model.getPrefixedLabel() ).contents()
                }, config ) );
 
                this.$overlay = config.$overlay || this.$element;
@@ -78,6 +78,9 @@
        mw.rcfilters.ui.TagItemWidget.prototype.onModelUpdate = function () {
                this.setCurrentMuteState();
 
+               // Update label if needed
+               this.setLabel( $( '<div>' ).html( this.model.getPrefixedLabel() ).contents() );
+
                this.setHighlightColor();
        };
 
                return this.model.getName();
        };
 
+       /**
+        * Get item model
+        *
+        * @return {string} Filter model
+        */
+       mw.rcfilters.ui.TagItemWidget.prototype.getModel = function () {
+               return this.model;
+       };
+
+       /**
+        * Get item view
+        *
+        * @return {string} Filter view
+        */
+       mw.rcfilters.ui.TagItemWidget.prototype.getView = function () {
+               return this.model.getGroupModel().getView();
+       };
+
        /**
         * Remove and destroy external elements of this widget
         */
index 015fb3e..a840599 100644 (file)
@@ -611,7 +611,7 @@ class AuthManagerTest extends \MediaWikiTestCase {
                $this->assertSame( 'de', $user->getOption( 'language' ) );
                $this->assertSame( 'zh', $user->getOption( 'variant' ) );
 
-               $this->setMwGlobals( 'wgContLang', \Language::factory( 'en' ) );
+               $this->setMwGlobals( 'wgContLang', \Language::factory( 'fr' ) );
 
                $user = \User::newFromName( self::usernameForCreation() );
                $user->addToDatabase();
index 22fd7b8..a474f20 100644 (file)
@@ -1739,9 +1739,8 @@ class LanguageTest extends LanguageClassesTestCase {
                        [ 'zh', 'zh', 'zh is defined as the parent language of zh, '
                                . 'because zh converter can convert zh-cn to zh' ],
                        [ 'zh-invalid', null, 'do not be fooled by arbitrarily composed language codes' ],
-                       [ 'en-gb', null, 'en does not have converter' ],
-                       [ 'en', null, 'en does not have converter. Although FakeConverter '
-                                       . 'handles en -> en conversion but it is useless' ],
+                       [ 'de-formal', null, 'de does not have converter' ],
+                       [ 'de', null, 'de does not have converter' ],
                ];
        }
 
index 53362c4..ee3cd5b 100644 (file)
@@ -94,6 +94,7 @@ return [
                        'tests/qunit/suites/resources/mediawiki.special/mediawiki.special.recentchanges.test.js',
                        'tests/qunit/suites/resources/mediawiki.rcfilters/dm.FiltersViewModel.test.js',
                        'tests/qunit/suites/resources/mediawiki.rcfilters/dm.FilterItem.test.js',
+                       'tests/qunit/suites/resources/mediawiki.rcfilters/UriProcessor.test.js',
                        'tests/qunit/suites/resources/mediawiki/mediawiki.language.test.js',
                        'tests/qunit/suites/resources/mediawiki/mediawiki.cldr.test.js',
                        'tests/qunit/suites/resources/mediawiki/mediawiki.cookie.test.js',
diff --git a/tests/qunit/suites/resources/mediawiki.rcfilters/UriProcessor.test.js b/tests/qunit/suites/resources/mediawiki.rcfilters/UriProcessor.test.js
new file mode 100644 (file)
index 0000000..edaaa39
--- /dev/null
@@ -0,0 +1,262 @@
+/* eslint-disable camelcase */
+/* eslint no-underscore-dangle: "off" */
+( function ( mw, $ ) {
+       var mockFilterStructure = [ {
+                       name: 'group1',
+                       title: 'Group 1',
+                       type: 'send_unselected_if_any',
+                       filters: [
+                               { name: 'filter1', default: true },
+                               { name: 'filter2' }
+                       ]
+               }, {
+                       name: 'group2',
+                       title: 'Group 2',
+                       type: 'send_unselected_if_any',
+                       filters: [
+                               { name: 'filter3' },
+                               { name: 'filter4', default: true }
+                       ]
+               }, {
+                       name: 'group3',
+                       title: 'Group 3',
+                       type: 'string_options',
+                       filters: [
+                               { name: 'filter5' },
+                               { name: 'filter6' }
+                       ]
+               } ],
+               minimalDefaultParams = {
+                       filter1: '1',
+                       filter4: '1'
+               };
+
+       QUnit.module( 'mediawiki.rcfilters - UriProcessor' );
+
+       QUnit.test( 'getVersion', function ( assert ) {
+               var uriProcessor = new mw.rcfilters.UriProcessor( new mw.rcfilters.dm.FiltersViewModel() );
+
+               assert.ok(
+                       uriProcessor.getVersion( { param1: 'foo', urlversion: '2' } ),
+                       2,
+                       'Retrieving the version from the URI query'
+               );
+
+               assert.ok(
+                       uriProcessor.getVersion( { param1: 'foo' } ),
+                       1,
+                       'Getting version 1 if no version is specified'
+               );
+       } );
+
+       QUnit.test( 'updateModelBasedOnQuery & getUriParametersFromModel', function ( assert ) {
+               var uriProcessor,
+                       filtersModel = new mw.rcfilters.dm.FiltersViewModel(),
+                       baseParams = {
+                               filter1: '0',
+                               filter2: '0',
+                               filter3: '0',
+                               filter4: '0',
+                               group3: '',
+                               highlight: '0',
+                               invert: '0',
+                               group1__filter1_color: null,
+                               group1__filter2_color: null,
+                               group2__filter3_color: null,
+                               group2__filter4_color: null,
+                               group3__filter5_color: null,
+                               group3__filter6_color: null
+                       };
+
+               filtersModel.initializeFilters( mockFilterStructure );
+               uriProcessor = new mw.rcfilters.UriProcessor( filtersModel );
+
+               uriProcessor.updateModelBasedOnQuery( {} );
+               assert.deepEqual(
+                       uriProcessor.getUriParametersFromModel(),
+                       $.extend( true, {}, baseParams, minimalDefaultParams ),
+                       'Version 1: Empty url query sets model to defaults'
+               );
+
+               uriProcessor.updateModelBasedOnQuery( { urlversion: '2' } );
+               assert.deepEqual(
+                       uriProcessor.getUriParametersFromModel(),
+                       baseParams,
+                       'Version 2: Empty url query sets model to all-false'
+               );
+
+               uriProcessor.updateModelBasedOnQuery( { filter1: '1', urlversion: '2' } );
+               assert.deepEqual(
+                       uriProcessor.getUriParametersFromModel(),
+                       $.extend( true, {}, baseParams, { filter1: '1' } ),
+                       'Parameters in Uri query set parameter value in the model'
+               );
+
+               uriProcessor.updateModelBasedOnQuery( { highlight: '1', group1__filter1_color: 'c1', urlversion: '2' } );
+               assert.deepEqual(
+                       uriProcessor.getUriParametersFromModel(),
+                       $.extend( true, {}, baseParams, {
+                               highlight: '1',
+                               group1__filter1_color: 'c1'
+                       } ),
+                       'Highlight parameters in Uri query set highlight state in the model'
+               );
+
+               uriProcessor.updateModelBasedOnQuery( { invert: '1', urlversion: '2' } );
+               assert.deepEqual(
+                       uriProcessor.getUriParametersFromModel(),
+                       $.extend( true, {}, baseParams, {
+                               invert: '1'
+                       } ),
+                       'Invert parameter in Uri query set invert state in the model'
+               );
+       } );
+
+       QUnit.test( 'isNewState', function ( assert ) {
+               var uriProcessor,
+                       filtersModel = new mw.rcfilters.dm.FiltersViewModel(),
+                       cases = [
+                               {
+                                       states: {
+                                               curr: {},
+                                               new: {}
+                                       },
+                                       result: false,
+                                       message: 'Empty objects are not new state.'
+                               },
+                               {
+                                       states: {
+                                               curr: { filter1: '1' },
+                                               new: { filter1: '0' }
+                                       },
+                                       result: true,
+                                       message: 'Nulified parameter is a new state'
+                               },
+                               {
+                                       states: {
+                                               curr: { filter1: '1' },
+                                               new: { filter1: '1', filter2: '1' }
+                                       },
+                                       result: true,
+                                       message: 'Added parameters are a new state'
+                               },
+                               {
+                                       states: {
+                                               curr: { filter1: '1' },
+                                               new: { filter1: '1', filter2: '0' }
+                                       },
+                                       result: false,
+                                       message: 'Added null parameters are not a new state (normalizing equals old state)'
+                               },
+                               {
+                                       states: {
+                                               curr: { filter1: '1' },
+                                               new: { filter1: '1', foo: 'bar' }
+                                       },
+                                       result: true,
+                                       message: 'Added unrecognized parameters are a new state'
+                               },
+                               {
+                                       states: {
+                                               curr: { filter1: '1', foo: 'bar' },
+                                               new: { filter1: '1', foo: 'baz' }
+                                       },
+                                       result: true,
+                                       message: 'Changed unrecognized parameters are a new state'
+                               }
+                       ];
+
+               filtersModel.initializeFilters( mockFilterStructure );
+               uriProcessor = new mw.rcfilters.UriProcessor( filtersModel );
+
+               cases.forEach( function ( testCase ) {
+                       assert.equal(
+                               uriProcessor.isNewState( testCase.states.curr, testCase.states.new ),
+                               testCase.result,
+                               testCase.message
+                       );
+               } );
+       } );
+
+       QUnit.test( 'doesQueryContainRecognizedParams', function ( assert ) {
+               var uriProcessor,
+                       filtersModel = new mw.rcfilters.dm.FiltersViewModel(),
+                       cases = [
+                               {
+                                       query: {},
+                                       result: false,
+                                       message: 'Empty query is not valid for load.'
+                               },
+                               {
+                                       query: { highlight: '1' },
+                                       result: false,
+                                       message: 'Highlight state alone is not valid for load'
+                               },
+                               {
+                                       query: { urlversion: '2' },
+                                       result: true,
+                                       message: 'urlversion=2 state alone is valid for load as an empty state'
+                               },
+                               {
+                                       query: { filter1: '1', foo: 'bar' },
+                                       result: true,
+                                       message: 'Existence of recognized parameters makes the query valid for load'
+                               },
+                               {
+                                       query: { foo: 'bar', debug: true },
+                                       result: false,
+                                       message: 'Only unrecognized parameters makes the query invalid for load'
+                               }
+                       ];
+
+               filtersModel.initializeFilters( mockFilterStructure );
+               uriProcessor = new mw.rcfilters.UriProcessor( filtersModel );
+
+               cases.forEach( function ( testCase ) {
+                       assert.equal(
+                               uriProcessor.doesQueryContainRecognizedParams( testCase.query ),
+                               testCase.result,
+                               testCase.message
+                       );
+               } );
+       } );
+
+       QUnit.test( '_getNormalizedQueryParams', function ( assert ) {
+               var uriProcessor,
+                       filtersModel = new mw.rcfilters.dm.FiltersViewModel(),
+                       cases = [
+                               {
+                                       query: {},
+                                       result: $.extend( true, { urlversion: '2' }, minimalDefaultParams ),
+                                       message: 'Empty query returns defaults (urlversion 1).'
+                               },
+                               {
+                                       query: { urlversion: '2' },
+                                       result: { urlversion: '2' },
+                                       message: 'Empty query returns empty (urlversion 2)'
+                               },
+                               {
+                                       query: { filter1: '0' },
+                                       result: { urlversion: '2', filter4: '1' },
+                                       message: 'urlversion 1 returns query that overrides defaults'
+                               },
+                               {
+                                       query: { filter3: '1' },
+                                       result: { urlversion: '2', filter1: '1', filter4: '1', filter3: '1' },
+                                       message: 'urlversion 1 with an extra param value returns query that is joined with defaults'
+                               }
+                       ];
+
+               filtersModel.initializeFilters( mockFilterStructure );
+               uriProcessor = new mw.rcfilters.UriProcessor( filtersModel );
+
+               cases.forEach( function ( testCase ) {
+                       assert.deepEqual(
+                               uriProcessor._getNormalizedQueryParams( testCase.query ),
+                               testCase.result,
+                               testCase.message
+                       );
+               } );
+       } );
+
+}( mediaWiki, jQuery ) );
index 714739b..233ec76 100644 (file)
@@ -10,6 +10,9 @@
                        'group2filter1-desc': 'Description of Filter 1 in Group 2',
                        'group2filter2-label': 'xGroup 2: Filter 2',
                        'group2filter2-desc': 'Description of Filter 2 in Group 2'
+               },
+               config: {
+                       wgStructuredChangeFiltersEnableExperimentalViews: true
                }
        } ) );
 
                                        }
                                ]
                        } ],
+                       namespaces = {
+                               0: 'Main',
+                               1: 'Talk',
+                               2: 'User',
+                               3: 'User talk'
+                       },
                        model = new mw.rcfilters.dm.FiltersViewModel();
 
-               model.initializeFilters( definition );
+               model.initializeFilters( definition, namespaces );
 
                assert.ok(
                        model.getItemByName( 'group1__filter1' ) instanceof mw.rcfilters.dm.FilterItem &&
                        model.getItemByName( 'group2__filter2' ) instanceof mw.rcfilters.dm.FilterItem &&
                        model.getItemByName( 'group3__filter1' ) instanceof mw.rcfilters.dm.FilterItem &&
                        model.getItemByName( 'group3__filter2' ) instanceof mw.rcfilters.dm.FilterItem,
+                       model.getItemByName( 'namespace__0' ) instanceof mw.rcfilters.dm.FilterItem,
+                       model.getItemByName( 'namespace__1' ) instanceof mw.rcfilters.dm.FilterItem,
+                       model.getItemByName( 'namespace__2' ) instanceof mw.rcfilters.dm.FilterItem,
+                       model.getItemByName( 'namespace__3' ) instanceof mw.rcfilters.dm.FilterItem,
                        'Filters instantiated and stored correctly'
                );
 
                                group2__filter1: false,
                                group2__filter2: false,
                                group3__filter1: false,
-                               group3__filter2: false
+                               group3__filter2: false,
+                               namespace__0: false,
+                               namespace__1: false,
+                               namespace__2: false,
+                               namespace__3: false
                        },
                        'Initial state of filters'
                );
                                group2__filter1: false,
                                group2__filter2: true,
                                group3__filter1: true,
-                               group3__filter2: false
+                               group3__filter2: false,
+                               namespace__0: false,
+                               namespace__1: false,
+                               namespace__2: false,
+                               namespace__3: false
                        },
                        'Updating filter states correctly'
                );
                assert.deepEqual(
                        model.getDefaultParams(),
                        {
-                               group1__hidefilter1_color: null,
-                               group1__hidefilter2_color: null,
-                               group1__hidefilter3_color: null,
-                               group2__hidefilter4_color: null,
-                               group2__hidefilter5_color: null,
-                               group2__hidefilter6_color: null,
-                               group3__filter7_color: null,
-                               group3__filter8_color: null,
-                               group3__filter9_color: null,
-                               highlight: '0',
                                hidefilter1: '1',
                                hidefilter2: '0',
                                hidefilter3: '1',
                                        }
                                ]
                        } ],
+                       namespaces = {
+                               0: 'Main',
+                               1: 'Talk',
+                               2: 'User',
+                               3: 'User talk'
+                       },
                        testCases = [
                                {
                                        query: 'group',
                                                group2: [ 'group2__filter1', 'group2__filter2' ]
                                        },
                                        reason: 'Finds filters containing the query string in their group title'
+                               },
+                               {
+                                       query: ':Main',
+                                       expectedMatches: {
+                                               namespace: [ 'namespace__0' ]
+                                       },
+                                       reason: 'Finds namespaces when using : prefix'
+                               },
+                               {
+                                       query: ':group',
+                                       expectedMatches: {},
+                                       reason: 'Finds no results if using namespaces prefix (:) to search for filter title'
                                }
                        ],
                        model = new mw.rcfilters.dm.FiltersViewModel(),
                                return result;
                        };
 
-               model.initializeFilters( definition );
+               model.initializeFilters( definition, namespaces );
 
                testCases.forEach( function ( testCase ) {
                        matches = model.findMatches( testCase.query );