Merge "Give links to a user's suppressed edits on Special:Contribs"
authorjenkins-bot <jenkins-bot@gerrit.wikimedia.org>
Thu, 6 Mar 2014 17:18:02 +0000 (17:18 +0000)
committerGerrit Code Review <gerrit@wikimedia.org>
Thu, 6 Mar 2014 17:18:02 +0000 (17:18 +0000)
239 files changed:
.jshintignore
.travis.yml
RELEASE-NOTES-1.23
composer-example.json
includes/Action.php [deleted file]
includes/AutoLoader.php
includes/DefaultSettings.php
includes/GlobalFunctions.php
includes/MediaWikiVersionFetcher.php [new file with mode: 0644]
includes/Message.php
includes/PoolCounter.php
includes/Setup.php
includes/SkinTemplate.php
includes/User.php
includes/Wiki.php
includes/actions/Action.php [new file with mode: 0644]
includes/actions/FormAction.php [new file with mode: 0644]
includes/actions/FormlessAction.php [new file with mode: 0644]
includes/api/ApiFeedContributions.php
includes/api/ApiFormatBase.php
includes/api/ApiMain.php
includes/api/ApiQueryRecentChanges.php
includes/api/ApiQueryUserContributions.php
includes/api/ApiRunJobs.php [new file with mode: 0644]
includes/changes/OldChangesList.php
includes/composer/ComposerHookHandler.php [new file with mode: 0644]
includes/composer/ComposerPackageModifier.php [new file with mode: 0644]
includes/composer/ComposerVersionNormalizer.php [new file with mode: 0644]
includes/content/AbstractContent.php
includes/content/Content.php
includes/content/ContentHandler.php
includes/content/CssContent.php
includes/content/CssContentHandler.php
includes/content/JavaScriptContent.php
includes/content/JavaScriptContentHandler.php
includes/content/MessageContent.php
includes/content/TextContent.php
includes/content/TextContentHandler.php
includes/content/WikitextContent.php
includes/content/WikitextContentHandler.php
includes/db/DatabaseError.php
includes/db/DatabaseMysqli.php
includes/diff/ArrayDiffFormatter.php
includes/diff/DairikiDiff.php
includes/diff/DiffFormatter.php
includes/diff/DifferenceEngine.php
includes/diff/TableDiffFormatter.php
includes/diff/UnifiedDiffFormatter.php
includes/diff/WikiDiff3.php
includes/filebackend/SwiftFileBackend.php
includes/htmlform/HTMLFormField.php
includes/htmlform/HTMLMultiSelectField.php
includes/htmlform/HTMLRadioField.php
includes/htmlform/HTMLSelectAndOtherField.php
includes/htmlform/HTMLSelectField.php
includes/htmlform/HTMLSelectOrOtherField.php
includes/installer/Installer.i18n.php
includes/installer/OracleUpdater.php
includes/job/JobQueue.php
includes/job/JobQueueRedis.php
includes/media/Jpeg.php
includes/resourceloader/ResourceLoaderFileModule.php
includes/resourceloader/ResourceLoaderStartUpModule.php
includes/search/SearchEngine.php
includes/site/SiteList.php
includes/specials/SpecialContributions.php
includes/specials/SpecialPrefixindex.php
includes/specials/SpecialRecentchanges.php
includes/specials/SpecialUserlogin.php
includes/specials/SpecialVersion.php
includes/templates/Usercreate.php
includes/upload/UploadBase.php
languages/messages/MessagesAr.php
languages/messages/MessagesAst.php
languages/messages/MessagesBe.php
languages/messages/MessagesBe_tarask.php
languages/messages/MessagesBg.php
languages/messages/MessagesBo.php
languages/messages/MessagesCa.php
languages/messages/MessagesCe.php
languages/messages/MessagesCo.php
languages/messages/MessagesCs.php
languages/messages/MessagesCy.php
languages/messages/MessagesDa.php
languages/messages/MessagesDe.php
languages/messages/MessagesDiq.php
languages/messages/MessagesDsb.php
languages/messages/MessagesEgl.php
languages/messages/MessagesEl.php
languages/messages/MessagesEn.php
languages/messages/MessagesEo.php
languages/messages/MessagesEs.php
languages/messages/MessagesEt.php
languages/messages/MessagesEu.php
languages/messages/MessagesFa.php
languages/messages/MessagesFi.php
languages/messages/MessagesFr.php
languages/messages/MessagesFrr.php
languages/messages/MessagesGl.php
languages/messages/MessagesGsw.php
languages/messages/MessagesHaw.php
languages/messages/MessagesHe.php
languages/messages/MessagesHi.php
languages/messages/MessagesHr.php
languages/messages/MessagesHsb.php
languages/messages/MessagesHu.php
languages/messages/MessagesIa.php
languages/messages/MessagesId.php
languages/messages/MessagesIlo.php
languages/messages/MessagesIs.php
languages/messages/MessagesIt.php
languages/messages/MessagesJa.php
languages/messages/MessagesKa.php
languages/messages/MessagesKab.php
languages/messages/MessagesKm.php
languages/messages/MessagesKo.php
languages/messages/MessagesKsh.php
languages/messages/MessagesLad.php
languages/messages/MessagesLb.php
languages/messages/MessagesLez.php
languages/messages/MessagesLrc.php
languages/messages/MessagesLt.php
languages/messages/MessagesMg.php
languages/messages/MessagesMk.php
languages/messages/MessagesMl.php
languages/messages/MessagesMn.php
languages/messages/MessagesMr.php
languages/messages/MessagesMs.php
languages/messages/MessagesNb.php
languages/messages/MessagesNe.php
languages/messages/MessagesNl.php
languages/messages/MessagesNn.php
languages/messages/MessagesOc.php
languages/messages/MessagesPl.php
languages/messages/MessagesPms.php
languages/messages/MessagesPt.php
languages/messages/MessagesPt_br.php
languages/messages/MessagesQqq.php
languages/messages/MessagesQu.php
languages/messages/MessagesRo.php
languages/messages/MessagesRoa_tara.php
languages/messages/MessagesRu.php
languages/messages/MessagesSc.php
languages/messages/MessagesSco.php
languages/messages/MessagesSi.php
languages/messages/MessagesSl.php
languages/messages/MessagesSq.php
languages/messages/MessagesSr_ec.php
languages/messages/MessagesSr_el.php
languages/messages/MessagesSv.php
languages/messages/MessagesTe.php
languages/messages/MessagesTl.php
languages/messages/MessagesTr.php
languages/messages/MessagesUk.php
languages/messages/MessagesUz.php
languages/messages/MessagesVi.php
languages/messages/MessagesYi.php
languages/messages/MessagesZh_hans.php
languages/messages/MessagesZh_hant.php
maintenance/language/messageTypes.inc
maintenance/language/messages.inc
maintenance/oracle/archives/patch-user_password_expire.sql [new file with mode: 0644]
resources/Resources.php
resources/jquery/jquery.color.js
resources/jquery/jquery.tablesorter.js
resources/mediawiki.api/mediawiki.api.category.js
resources/mediawiki.api/mediawiki.api.edit.js
resources/mediawiki.api/mediawiki.api.js
resources/mediawiki.api/mediawiki.api.parse.js
resources/mediawiki.api/mediawiki.api.watch.js
resources/mediawiki.less/mediawiki.mixins.animation.less [new file with mode: 0644]
resources/mediawiki.less/mediawiki.mixins.rotation.less
resources/mediawiki.libs/CLDRPluralRuleParser.js
resources/mediawiki.page/mediawiki.page.watch.ajax.js
resources/mediawiki.special/mediawiki.special.css
resources/mediawiki.special/mediawiki.special.userlogin.signup.js
resources/mediawiki.ui/components/default/forms.less
resources/mediawiki.ui/mixins/forms.less
resources/mediawiki/mediawiki.debug.css [deleted file]
resources/mediawiki/mediawiki.debug.less [new file with mode: 0644]
resources/mediawiki/mediawiki.js
resources/mediawiki/mediawiki.user.js
resources/oojs-ui/i18n/ast.json
resources/oojs-ui/i18n/bg.json
resources/oojs-ui/i18n/de.json
resources/oojs-ui/i18n/en.json
resources/oojs-ui/i18n/fr.json
resources/oojs-ui/i18n/hsb.json
resources/oojs-ui/i18n/hy.json
resources/oojs-ui/i18n/is.json
resources/oojs-ui/i18n/it.json
resources/oojs-ui/i18n/ja.json
resources/oojs-ui/i18n/ko.json
resources/oojs-ui/i18n/lb.json
resources/oojs-ui/i18n/lt.json
resources/oojs-ui/i18n/mk.json
resources/oojs-ui/i18n/nl.json
resources/oojs-ui/i18n/om.json
resources/oojs-ui/i18n/pl.json
resources/oojs-ui/i18n/qqq.json
resources/oojs-ui/i18n/ro.json
resources/oojs-ui/i18n/ru.json
resources/oojs-ui/i18n/sl.json
resources/oojs-ui/i18n/sq.json
resources/oojs-ui/i18n/sr-ec.json
resources/oojs-ui/i18n/sv.json
resources/oojs-ui/i18n/uk.json
resources/oojs-ui/i18n/zh-hans.json
resources/oojs-ui/i18n/zh-hant.json
resources/oojs-ui/oojs-ui-apex.css [new file with mode: 0644]
resources/oojs-ui/oojs-ui.js
resources/oojs-ui/oojs-ui.svg.css
resources/oojs-ui/update-oojs-ui.sh
resources/oojs/update-oojs.sh
resources/sinonjs/sinon-1.8.1.js [deleted file]
resources/sinonjs/sinon-1.9.0.js [new file with mode: 0644]
resources/sinonjs/sinon-ie-1.8.1.js [deleted file]
resources/sinonjs/sinon-ie-1.9.0.js [new file with mode: 0644]
skins/vector/components/search.less
tests/parser/parserTests.txt
tests/phpunit/MediaWikiTestCase.php
tests/phpunit/includes/LinksUpdateTest.php
tests/phpunit/includes/MediaWikiVersionFetcherTest.php [new file with mode: 0644]
tests/phpunit/includes/SkinTemplateTest.php [new file with mode: 0644]
tests/phpunit/includes/StatusTest.php
tests/phpunit/includes/composer/ComposerVersionNormalizerTest.php [new file with mode: 0644]
tests/phpunit/includes/exception/ErrorPageErrorTest.php [new file with mode: 0644]
tests/phpunit/includes/exception/MWExceptionTest.php
tests/phpunit/includes/exception/ReadOnlyErrorTest.php [new file with mode: 0644]
tests/phpunit/includes/exception/UserNotLoggedInTest.php [new file with mode: 0644]
tests/phpunit/includes/site/SiteListTest.php
tests/phpunit/languages/SpecialPageAliasTest.php [new file with mode: 0644]
tests/qunit/QUnitTestResources.php
tests/qunit/suites/resources/jquery/jquery.color.test.js [new file with mode: 0644]
tests/qunit/suites/resources/jquery/jquery.delayedBind.test.js [deleted file]
tests/qunit/suites/resources/jquery/jquery.makeCollapsible.test.js
tests/qunit/suites/resources/jquery/jquery.tablesorter.test.js
tests/qunit/suites/resources/mediawiki.api/mediawiki.api.parse.test.js
tests/qunit/suites/resources/mediawiki.api/mediawiki.api.test.js

index 0e3c679..a44a4d4 100644 (file)
@@ -16,6 +16,7 @@ resources/jquery/jquery.cookie.js
 resources/jquery/jquery.cycle.all.js
 resources/jquery/jquery.farbtastic.js
 resources/jquery/jquery.form.js
+resources/jquery/jquery.fullscreen.js
 resources/jquery/jquery.hoverIntent.js
 resources/jquery/jquery.js
 resources/jquery/jquery.json.js
index 84fa456..eb05fe2 100644 (file)
@@ -4,12 +4,21 @@
 # The Wikimedia Foundation uses a self-hosted Jenkins instance to run unit
 # tests, but it tests code against the version of PHP that is deployed on
 # Wikimedia's production cluster. This Travis CI configuration is designed to
-# complement that setup by testing MediaWiki against HHVM.
+# complement that setup by testing MediaWiki on travis
 #
 language: php
 
 php:
   - hhvm
+  - 5.3
+  - 5.4
+  - 5.5
+
+matrix:
+  allow_failures:
+    - php: 5.3
+    - php: 5.4
+    - php: 5.5
 
 services:
   - mysql
@@ -29,7 +38,7 @@ before_script:
   # Travis CI's HHVM environment provides PHPUnit as a phar file, but
   # MediaWiki's test suite only works if individual PHPUnit files are
   # actual files on disk (bug 58881).
-  - composer require 'phpunit/phpunit=3.7.*'
+  - composer require 'phpunit/phpunit=3.7.*' --prefer-source
   - >
       php maintenance/install.php testwiki admin
       --pass travis
@@ -40,7 +49,13 @@ before_script:
 
 script:
   - >
-      hhvm --php
-      -d include_path=".$(printf ':%s' vendor/phpunit/*)"
-      -d date.timezone="Etc/UTC"
-      tests/phpunit/phpunit.php
+      if [ "$TRAVIS_PHP_VERSION" = "hhvm" ];
+      then
+        hhvm --php \
+        -d include_path=".$(printf ':%s' vendor/phpunit/*)" \
+        -d date.timezone="Etc/UTC" \
+        tests/phpunit/phpunit.php
+      else
+        php tests/phpunit/phpunit.php \
+        --with-phpunitdir ./vendor/phpunit/phpunit
+      fi
index 4f29097..798d59c 100644 (file)
@@ -9,6 +9,9 @@ MediaWiki 1.23 is an alpha-quality branch and is not recommended for use in
 production.
 
 === Configuration changes in 1.23 ===
+* When $wgJobRunRate is higher that zero, jobs are now executed via an
+  asynchronous HTTP request to a MediaWiki entry point. This may require
+  increasing the number of server worker threads.
 * $wgDebugLogGroups values may be set to an associative array with a
   'destination' key specifying the log destination. The array may also contain
   a 'sample' key with a positive integer value N indicating that the log group
@@ -109,6 +112,14 @@ production.
   $wgPasswordExpirationDays configuration setting.
 * Add new hook SendWatchlistEmailNotification, this will be used to determine
   whether to send a watchlist email notification.
+* (bug 42026) Special:Contributions now includes an option to filter page
+  creations, similar to the topOnly option.
+* Add mediawiki.ui.button styling to all pages so wiki content can use styled
+  buttons.
+* Special:UserLogin/signup now does AJAX checks for invalid and taken usernames,
+  displaying the error live.
+* Special:UserLogin/signup now warns the user if their chosen username has to be
+  normalized.
 
 === Bug fixes in 1.23 ===
 * (bug 41759) The "updated since last visit" markers (on history pages, recent
@@ -146,6 +157,9 @@ production.
   message instead of leading the user to make a null edit.
 * (bug 52659) mediawiki.notification: Notification area remained visible when
   empty and thus was stealing pointer events from links on the page.
+* (bug 26811) When a DBUnexpectedError occurs, DB server hostnames are now
+  hidden unless $wgShowExceptionDetails is true, and $wgShowDBErrorBacktrace
+  no longer applies in such cases.
 
 === Web API changes in 1.23 ===
 * (bug 54884) action=parse&prop=categories now indicates hidden and missing
@@ -193,6 +207,9 @@ production.
 * Added llprop=langname and llprop=autonym for action=query&prop=langlinks.
 * prop=redirects is added, to return redirects to the pages in the query.
 * list=allredirects is added, to list all redirects pointing to a namespace.
+* (bug 42026) Added ucshow={new,!new,top,!top} to list=usercontribs.
+  Also added newonly to action=feedcontributions.
+* (bug 42026) Deprecated uctoponly in favor of ucshow=top.
 
 === Languages updated in 1.23 ===
 
@@ -256,6 +273,11 @@ changes to languages because of Bugzilla reports.
   object expects this column to exist. Use update.php to create this new field.
 * The jquery.delayedBind ResourceLoader module was deprecated in favor of the
   jquery.throttle-debounce module. It will be removed in MediaWiki 1.24.
+* mw.user.bucket has been deprecated.
+* On Special:PrefixIndex, a table#mw-prefixindex-list-table was changed to
+  table.mw-prefixindex-list-table to avoid duplicate ids when the special page
+  is transcluded.
+* (bug 62198) window.$j has been deprecated.
 
 ==== Removed classes ====
 * FakeMemCachedClient (deprecated in 1.18)
index cf63678..85304c1 100644 (file)
@@ -7,5 +7,14 @@
                "ext-mbstring": "Faster unicode handling",
                "ext-wikidiff2": "Faster diff generation",
                "ext-apc": "Speed up MediaWiki with opcode caching (before PHP 5.5)"
+       },
+       "autoload": {
+               "psr-0": {
+                       "ComposerHookHandler": "includes/composer"
+               }
+       },
+       "scripts": {
+               "pre-update-cmd": "ComposerHookHandler::onPreUpdate",
+               "pre-install-cmd": "ComposerHookHandler::onPreInstall"
        }
 }
diff --git a/includes/Action.php b/includes/Action.php
deleted file mode 100644 (file)
index 72be46f..0000000
+++ /dev/null
@@ -1,600 +0,0 @@
-<?php
-/**
- * Base classes for actions done on pages.
- *
- * 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
- *
- * @file
- */
-
-/**
- * @defgroup Actions Action done on pages
- */
-
-/**
- * Actions are things which can be done to pages (edit, delete, rollback, etc).  They
- * are distinct from Special Pages because an action must apply to exactly one page.
- *
- * To add an action in an extension, create a subclass of Action, and add the key to
- * $wgActions.  There is also the deprecated UnknownAction hook
- *
- * Actions generally fall into two groups: the show-a-form-then-do-something-with-the-input
- * 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 {
-
-       /**
-        * Page on which we're performing the action
-        * @var WikiPage|Article|ImagePage|CategoryPage|Page $page
-        */
-       protected $page;
-
-       /**
-        * IContextSource if specified; otherwise we'll use the Context from the Page
-        * @var IContextSource $context
-        */
-       protected $context;
-
-       /**
-        * The fields used to create the HTMLForm
-        * @var Array $fields
-        */
-       protected $fields;
-
-       /**
-        * Get the Action subclass which should be used to handle this action, false if
-        * the action is disabled, or null if it's not recognised
-        * @param $action String
-        * @param $overrides Array
-        * @return bool|null|string|callable
-        */
-       final private static function getClass( $action, array $overrides ) {
-               global $wgActions;
-               $action = strtolower( $action );
-
-               if ( !isset( $wgActions[$action] ) ) {
-                       return null;
-               }
-
-               if ( $wgActions[$action] === false ) {
-                       return false;
-               } elseif ( $wgActions[$action] === true && isset( $overrides[$action] ) ) {
-                       return $overrides[$action];
-               } elseif ( $wgActions[$action] === true ) {
-                       return ucfirst( $action ) . 'Action';
-               } else {
-                       return $wgActions[$action];
-               }
-       }
-
-       /**
-        * Get an appropriate Action subclass for the given action
-        * @param $action String
-        * @param $page Page
-        * @param $context IContextSource
-        * @return Action|bool|null false if the action is disabled, null
-        *     if it is not recognised
-        */
-       final public static function factory( $action, Page $page, IContextSource $context = null ) {
-               $classOrCallable = self::getClass( $action, $page->getActionOverrides() );
-
-               if ( is_string( $classOrCallable ) ) {
-                       $obj = new $classOrCallable( $page, $context );
-                       return $obj;
-               }
-
-               if ( is_callable( $classOrCallable ) ) {
-                       return call_user_func_array( $classOrCallable, array( $page, $context ) );
-               }
-
-               return $classOrCallable;
-       }
-
-       /**
-        * Get the action that will be executed, not necessarily the one passed
-        * passed through the "action" request parameter. Actions disabled in
-        * $wgActions will be replaced by "nosuchaction".
-        *
-        * @since 1.19
-        * @param $context IContextSource
-        * @return string: action name
-        */
-       final public static function getActionName( IContextSource $context ) {
-               global $wgActions;
-
-               $request = $context->getRequest();
-               $actionName = $request->getVal( 'action', 'view' );
-
-               // Check for disabled actions
-               if ( isset( $wgActions[$actionName] ) && $wgActions[$actionName] === false ) {
-                       $actionName = 'nosuchaction';
-               }
-
-               // Workaround for bug #20966: inability of IE to provide an action dependent
-               // on which submit button is clicked.
-               if ( $actionName === 'historysubmit' ) {
-                       if ( $request->getBool( 'revisiondelete' ) ) {
-                               $actionName = 'revisiondelete';
-                       } else {
-                               $actionName = 'view';
-                       }
-               } elseif ( $actionName == 'editredlink' ) {
-                       $actionName = 'edit';
-               }
-
-               // Trying to get a WikiPage for NS_SPECIAL etc. will result
-               // in WikiPage::factory throwing "Invalid or virtual namespace -1 given."
-               // For SpecialPages et al, default to action=view.
-               if ( !$context->canUseWikiPage() ) {
-                       return 'view';
-               }
-
-               $action = Action::factory( $actionName, $context->getWikiPage(), $context );
-               if ( $action instanceof Action ) {
-                       return $action->getName();
-               }
-
-               return 'nosuchaction';
-       }
-
-       /**
-        * Check if a given action is recognised, even if it's disabled
-        *
-        * @param string $name name of an action
-        * @return Bool
-        */
-       final public static function exists( $name ) {
-               return self::getClass( $name, array() ) !== null;
-       }
-
-       /**
-        * Get the IContextSource in use here
-        * @return IContextSource
-        */
-       final public function getContext() {
-               if ( $this->context instanceof IContextSource ) {
-                       return $this->context;
-               } elseif ( $this->page instanceof Article ) {
-                       // NOTE: $this->page can be a WikiPage, which does not have a context.
-                       wfDebug( __METHOD__ . ': no context known, falling back to Article\'s context.' );
-                       return $this->page->getContext();
-               }
-
-               wfWarn( __METHOD__ . ': no context known, falling back to RequestContext::getMain().' );
-               return RequestContext::getMain();
-       }
-
-       /**
-        * Get the WebRequest being used for this instance
-        *
-        * @return WebRequest
-        */
-       final public function getRequest() {
-               return $this->getContext()->getRequest();
-       }
-
-       /**
-        * Get the OutputPage being used for this instance
-        *
-        * @return OutputPage
-        */
-       final public function getOutput() {
-               return $this->getContext()->getOutput();
-       }
-
-       /**
-        * Shortcut to get the User being used for this instance
-        *
-        * @return User
-        */
-       final public function getUser() {
-               return $this->getContext()->getUser();
-       }
-
-       /**
-        * Shortcut to get the Skin being used for this instance
-        *
-        * @return Skin
-        */
-       final public function getSkin() {
-               return $this->getContext()->getSkin();
-       }
-
-       /**
-        * Shortcut to get the user Language being used for this instance
-        *
-        * @return Language
-        */
-       final public function getLanguage() {
-               return $this->getContext()->getLanguage();
-       }
-
-       /**
-        * Shortcut to get the user Language being used for this instance
-        *
-        * @deprecated since 1.19 Use getLanguage instead
-        * @return Language
-        */
-       final public function getLang() {
-               wfDeprecated( __METHOD__, '1.19' );
-               return $this->getLanguage();
-       }
-
-       /**
-        * Shortcut to get the Title object from the page
-        * @return Title
-        */
-       final public function getTitle() {
-               return $this->page->getTitle();
-       }
-
-       /**
-        * Get a Message object with context set
-        * Parameters are the same as wfMessage()
-        *
-        * @return Message object
-        */
-       final public function msg() {
-               $params = func_get_args();
-               return call_user_func_array( array( $this->getContext(), 'msg' ), $params );
-       }
-
-       /**
-        * Constructor.
-        *
-        * Only public since 1.21
-        *
-        * @param $page Page
-        * @param $context IContextSource
-        */
-       public function __construct( Page $page, IContextSource $context = null ) {
-               if ( $context === null ) {
-                       wfWarn( __METHOD__ . ' called without providing a Context object.' );
-                       // NOTE: We could try to initialize $context using $page->getContext(),
-                       //      if $page is an Article. That however seems to not work seamlessly.
-               }
-
-               $this->page = $page;
-               $this->context = $context;
-       }
-
-       /**
-        * Return the name of the action this object responds to
-        * @return String lowercase
-        */
-       abstract public function getName();
-
-       /**
-        * Get the permission required to perform this action.  Often, but not always,
-        * the same as the action name
-        * @return String|null
-        */
-       public function getRestriction() {
-               return null;
-       }
-
-       /**
-        * Checks if the given user (identified by an object) can perform this action.  Can be
-        * overridden by sub-classes with more complicated permissions schemes.  Failures here
-        * must throw subclasses of ErrorPageError
-        *
-        * @param $user User: the user to check, or null to use the context user
-        * @throws UserBlockedError|ReadOnlyError|PermissionsError
-        * @return bool True on success
-        */
-       protected function checkCanExecute( User $user ) {
-               $right = $this->getRestriction();
-               if ( $right !== null ) {
-                       $errors = $this->getTitle()->getUserPermissionsErrors( $right, $user );
-                       if ( count( $errors ) ) {
-                               throw new PermissionsError( $right, $errors );
-                       }
-               }
-
-               if ( $this->requiresUnblock() && $user->isBlocked() ) {
-                       $block = $user->getBlock();
-                       throw new UserBlockedError( $block );
-               }
-
-               // This should be checked at the end so that the user won't think the
-               // error is only temporary when he also don't have the rights to execute
-               // this action
-               if ( $this->requiresWrite() && wfReadOnly() ) {
-                       throw new ReadOnlyError();
-               }
-               return true;
-       }
-
-       /**
-        * Whether this action requires the wiki not to be locked
-        * @return Bool
-        */
-       public function requiresWrite() {
-               return true;
-       }
-
-       /**
-        * Whether this action can still be executed by a blocked user
-        * @return Bool
-        */
-       public function requiresUnblock() {
-               return true;
-       }
-
-       /**
-        * Set output headers for noindexing etc.  This function will not be called through
-        * the execute() entry point, so only put UI-related stuff in here.
-        */
-       protected function setHeaders() {
-               $out = $this->getOutput();
-               $out->setRobotPolicy( "noindex,nofollow" );
-               $out->setPageTitle( $this->getPageTitle() );
-               $this->getOutput()->setSubtitle( $this->getDescription() );
-               $out->setArticleRelated( true );
-       }
-
-       /**
-        * Returns the name that goes in the \<h1\> page title
-        *
-        * @return String
-        */
-       protected function getPageTitle() {
-               return $this->getTitle()->getPrefixedText();
-       }
-
-       /**
-        * Returns the description that goes below the \<h1\> tag
-        *
-        * @return String
-        */
-       protected function getDescription() {
-               return $this->msg( strtolower( $this->getName() ) )->escaped();
-       }
-
-       /**
-        * The main action entry point.  Do all output for display and send it to the context
-        * output.  Do not use globals $wgOut, $wgRequest, etc, in implementations; use
-        * $this->getOutput(), etc.
-        * @throws ErrorPageError
-        */
-       abstract public function show();
-
-       /**
-        * Execute the action in a silent fashion: do not display anything or release any errors.
-        * @return Bool whether execution was successful
-        */
-       abstract public function execute();
-}
-
-/**
- * An action which shows a form and does something based on the input from the form
- */
-abstract class FormAction extends Action {
-
-       /**
-        * Get an HTMLForm descriptor array
-        * @return Array
-        */
-       abstract protected function getFormFields();
-
-       /**
-        * Add pre- or post-text to the form
-        * @return String HTML which will be sent to $form->addPreText()
-        */
-       protected function preText() {
-               return '';
-       }
-
-       /**
-        * @return string
-        */
-       protected function postText() {
-               return '';
-       }
-
-       /**
-        * Play with the HTMLForm if you need to more substantially
-        * @param $form HTMLForm
-        */
-       protected function alterForm( HTMLForm $form ) {
-       }
-
-       /**
-        * Get the HTMLForm to control behavior
-        * @return HTMLForm|null
-        */
-       protected function getForm() {
-               $this->fields = $this->getFormFields();
-
-               // Give hooks a chance to alter the form, adding extra fields or text etc
-               wfRunHooks( 'ActionModifyFormFields', array( $this->getName(), &$this->fields, $this->page ) );
-
-               $form = new HTMLForm( $this->fields, $this->getContext(), $this->getName() );
-               $form->setSubmitCallback( array( $this, 'onSubmit' ) );
-
-               // Retain query parameters (uselang etc)
-               $form->addHiddenField( 'action', $this->getName() ); // Might not be the same as the query string
-               $params = array_diff_key(
-                       $this->getRequest()->getQueryValues(),
-                       array( 'action' => null, 'title' => null )
-               );
-               $form->addHiddenField( 'redirectparams', wfArrayToCgi( $params ) );
-
-               $form->addPreText( $this->preText() );
-               $form->addPostText( $this->postText() );
-               $this->alterForm( $form );
-
-               // Give hooks a chance to alter the form, adding extra fields or text etc
-               wfRunHooks( 'ActionBeforeFormDisplay', array( $this->getName(), &$form, $this->page ) );
-
-               return $form;
-       }
-
-       /**
-        * Process the form on POST submission.  If you return false from getFormFields(),
-        * this will obviously never be reached.  If you don't want to do anything with the
-        * form, just return false here
-        * @param  $data Array
-        * @return Bool|Array true for success, false for didn't-try, array of errors on failure
-        */
-       abstract public function onSubmit( $data );
-
-       /**
-        * Do something exciting on successful processing of the form.  This might be to show
-        * a confirmation message (watch, rollback, etc) or to redirect somewhere else (edit,
-        * protect, etc).
-        */
-       abstract public function onSuccess();
-
-       /**
-        * The basic pattern for actions is to display some sort of HTMLForm UI, maybe with
-        * some stuff underneath (history etc); to do some processing on submission of that
-        * form (delete, protect, etc) and to do something exciting on 'success', be that
-        * display something new or redirect to somewhere.  Some actions have more exotic
-        * behavior, but that's what subclassing is for :D
-        */
-       public function show() {
-               $this->setHeaders();
-
-               // This will throw exceptions if there's a problem
-               $this->checkCanExecute( $this->getUser() );
-
-               $form = $this->getForm();
-               if ( $form->show() ) {
-                       $this->onSuccess();
-               }
-       }
-
-       /**
-        * @see Action::execute()
-        *
-        * @param $data array|null
-        * @param $captureErrors bool
-        * @throws ErrorPageError|Exception
-        * @return bool
-        */
-       public function execute( array $data = null, $captureErrors = true ) {
-               try {
-                       // Set a new context so output doesn't leak.
-                       $this->context = clone $this->getContext();
-
-                       // This will throw exceptions if there's a problem
-                       $this->checkCanExecute( $this->getUser() );
-
-                       $fields = array();
-                       foreach ( $this->fields as $key => $params ) {
-                               if ( isset( $data[$key] ) ) {
-                                       $fields[$key] = $data[$key];
-                               } elseif ( isset( $params['default'] ) ) {
-                                       $fields[$key] = $params['default'];
-                               } else {
-                                       $fields[$key] = null;
-                               }
-                       }
-                       $status = $this->onSubmit( $fields );
-                       if ( $status === true ) {
-                               // This might do permanent stuff
-                               $this->onSuccess();
-                               return true;
-                       } else {
-                               return false;
-                       }
-               }
-               catch ( ErrorPageError $e ) {
-                       if ( $captureErrors ) {
-                               return false;
-                       } else {
-                               throw $e;
-                       }
-               }
-       }
-}
-
-/**
- * An action which just does something, without showing a form first.
- */
-abstract class FormlessAction extends Action {
-
-       /**
-        * Show something on GET request.
-        * @return String|null will be added to the HTMLForm if present, or just added to the
-        *     output if not.  Return null to not add anything
-        */
-       abstract public function onView();
-
-       /**
-        * We don't want an HTMLForm
-        * @return bool
-        */
-       protected function getFormFields() {
-               return false;
-       }
-
-       /**
-        * @param $data Array
-        * @return bool
-        */
-       public function onSubmit( $data ) {
-               return false;
-       }
-
-       /**
-        * @return bool
-        */
-       public function onSuccess() {
-               return false;
-       }
-
-       public function show() {
-               $this->setHeaders();
-
-               // This will throw exceptions if there's a problem
-               $this->checkCanExecute( $this->getUser() );
-
-               $this->getOutput()->addHTML( $this->onView() );
-       }
-
-       /**
-        * Execute the action silently, not giving any output.  Since these actions don't have
-        * forms, they probably won't have any data, but some (eg rollback) may do
-        * @param array $data values that would normally be in the GET request
-        * @param bool $captureErrors whether to catch exceptions and just return false
-        * @throws ErrorPageError|Exception
-        * @return Bool whether execution was successful
-        */
-       public function execute( array $data = null, $captureErrors = true ) {
-               try {
-                       // Set a new context so output doesn't leak.
-                       $this->context = clone $this->getContext();
-                       if ( is_array( $data ) ) {
-                               $this->context->setRequest( new FauxRequest( $data, false ) );
-                       }
-
-                       // This will throw exceptions if there's a problem
-                       $this->checkCanExecute( $this->getUser() );
-
-                       $this->onView();
-                       return true;
-               }
-               catch ( ErrorPageError $e ) {
-                       if ( $captureErrors ) {
-                               return false;
-                       } else {
-                               throw $e;
-                       }
-               }
-       }
-}
index 359fd8b..87dc95d 100644 (file)
@@ -29,7 +29,6 @@ global $wgAutoloadLocalClasses;
 
 $wgAutoloadLocalClasses = array(
        # Includes
-       'Action' => 'includes/Action.php',
        'AjaxDispatcher' => 'includes/AjaxDispatcher.php',
        'AjaxResponse' => 'includes/AjaxResponse.php',
        'AlphabeticPager' => 'includes/Pager.php',
@@ -80,8 +79,6 @@ $wgAutoloadLocalClasses = array(
        'FeedUtils' => 'includes/FeedUtils.php',
        'FileDeleteForm' => 'includes/FileDeleteForm.php',
        'ForkController' => 'includes/ForkController.php',
-       'FormlessAction' => 'includes/Action.php',
-       'FormAction' => 'includes/Action.php',
        'FormOptions' => 'includes/FormOptions.php',
        'FormSpecialPage' => 'includes/specialpage/FormSpecialPage.php',
        'GitInfo' => 'includes/GitInfo.php',
@@ -141,6 +138,7 @@ $wgAutoloadLocalClasses = array(
        'MailAddress' => 'includes/UserMailer.php',
        'MediaWiki' => 'includes/Wiki.php',
        'MediaWiki_I18N' => 'includes/SkinTemplate.php',
+       'MediaWikiVersionFetcher' => 'includes/MediaWikiVersionFetcher.php',
        'Message' => 'includes/Message.php',
        'MessageBlobStore' => 'includes/MessageBlobStore.php',
        'MimeMagic' => 'includes/MimeMagic.php',
@@ -237,10 +235,13 @@ $wgAutoloadLocalClasses = array(
        'XmlSelect' => 'includes/Xml.php',
 
        # includes/actions
+       'Action' => 'includes/actions/Action.php',
        'CachedAction' => 'includes/actions/CachedAction.php',
        'CreditsAction' => 'includes/actions/CreditsAction.php',
        'DeleteAction' => 'includes/actions/DeleteAction.php',
        'EditAction' => 'includes/actions/EditAction.php',
+       'FormlessAction' => 'includes/actions/FormlessAction.php',
+       'FormAction' => 'includes/actions/FormAction.php',
        'HistoryAction' => 'includes/actions/HistoryAction.php',
        'HistoryPage' => 'includes/actions/HistoryAction.php',
        'HistoryPager' => 'includes/actions/HistoryAction.php',
@@ -358,6 +359,7 @@ $wgAutoloadLocalClasses = array(
        'ApiRevisionDelete' => 'includes/api/ApiRevisionDelete.php',
        'ApiRollback' => 'includes/api/ApiRollback.php',
        'ApiRsd' => 'includes/api/ApiRsd.php',
+       'ApiRunJobs' => 'includes/api/ApiRunJobs.php',
        'ApiSetNotificationTimestamp' => 'includes/api/ApiSetNotificationTimestamp.php',
        'ApiTokens' => 'includes/api/ApiTokens.php',
        'ApiUnblock' => 'includes/api/ApiUnblock.php',
@@ -396,6 +398,10 @@ $wgAutoloadLocalClasses = array(
        'RedisConnectionPool' => 'includes/clientpool/RedisConnectionPool.php',
        'RedisConnRef' => 'includes/clientpool/RedisConnectionPool.php',
 
+       # includes/composer
+       'ComposerPackageModifier' => 'includes/composer/ComposerPackageModifier.php',
+       'ComposerVersionNormalizer' => 'includes/composer/ComposerVersionNormalizer.php',
+
        # includes/config
        'Config' => 'includes/config/Config.php',
        'GlobalConfig' => 'includes/config/GlobalConfig.php',
@@ -443,6 +449,7 @@ $wgAutoloadLocalClasses = array(
        'DBConnectionError' => 'includes/db/DatabaseError.php',
        'DBConnRef' => 'includes/db/LoadBalancer.php',
        'DBError' => 'includes/db/DatabaseError.php',
+       'DBExpectedError' => 'includes/db/DatabaseError.php',
        'DBObject' => 'includes/db/DatabaseUtility.php',
        'IDatabase'  => 'includes/db/Database.php',
        'IORMRow' => 'includes/db/IORMRow.php',
index 716baef..734c27e 100644 (file)
@@ -4739,6 +4739,8 @@ $wgRateLimits = array(
 
 /**
  * Set to a filename to log rate limiter hits.
+ *
+ * @deprecated since 1.23, use $wgDebugLogGroups['ratelimit'] instead
  */
 $wgRateLimitLog = null;
 
@@ -4951,10 +4953,12 @@ $wgDebugDumpSql = false;
  * of the regular $wgDebugLogFile. Useful for enabling selective logging
  * in production.
  *
- * Log destinations may be string values specifying a filename or URI, or they
- * may be filename or an associative array mapping 'destination' to the desired
- * filename. The associative array may also contain a 'sample' key with an
- * integer value, specifying a sampling factor.
+ * Log destinations may be one of the following:
+ * - false to completely remove from the output, including from $wgDebugLogFile.
+ * - string values specifying a filename or URI.
+ * - associative array mapping 'destination' key to the desired filename or URI.
+ *   The associative array may also contain a 'sample' key with an integer value,
+ *   specifying a sampling factor.
  *
  * @par Example:
  * @code
@@ -5011,6 +5015,11 @@ $wgShowExceptionDetails = false;
 
 /**
  * If true, show a backtrace for database errors
+ *
+ * @note This setting only applies when connection errors and query errors are
+ * reported in the normal manner. $wgShowExceptionDetails applies in other cases,
+ * including those in which an uncaught exception is thrown from within the
+ * exception handler.
  */
 $wgShowDBErrorBacktrace = false;
 
@@ -5102,11 +5111,6 @@ $wgUDPProfilerPort = '3811';
  */
 $wgUDPProfilerFormatString = "%s - %d %f %f %f %f %s\n";
 
-/**
- * Detects non-matching wfProfileIn/wfProfileOut calls
- */
-$wgDebugProfiling = false;
-
 /**
  * Output debug message on every wfProfileIn/wfProfileOut
  */
index 6785d0c..a6f936f 100644 (file)
@@ -1064,6 +1064,9 @@ function wfDebugLog( $logGroup, $text, $dest = 'all' ) {
        }
 
        $logConfig = $wgDebugLogGroups[$logGroup];
+       if ( $logConfig === false ) {
+               return;
+       }
        if ( is_array( $logConfig ) ) {
                if ( isset( $logConfig['sample'] ) && mt_rand( 1, $logConfig['sample'] ) !== 1 ) {
                        return;
diff --git a/includes/MediaWikiVersionFetcher.php b/includes/MediaWikiVersionFetcher.php
new file mode 100644 (file)
index 0000000..1d59ec3
--- /dev/null
@@ -0,0 +1,31 @@
+<?php
+
+/**
+ * Provides access to MediaWiki's version without requiring MediaWiki (or anything else)
+ * being loaded first.
+ *
+ * @licence GNU GPL v2+
+ * @author Jeroen De Dauw < jeroendedauw@gmail.com >
+ */
+class MediaWikiVersionFetcher {
+
+       /**
+        * Returns the MediaWiki version, in the format used by MediaWiki's wgVersion global.
+        *
+        * @return string
+        * @throws RuntimeException
+        */
+       public function fetchVersion() {
+               $defaultSettings = file_get_contents( __DIR__ . '/DefaultSettings.php' );
+
+               $matches = array();
+               preg_match( "/wgVersion = '([0-9a-zA-Z\.]+)';/", $defaultSettings, $matches );
+
+               if ( count( $matches ) !== 2 ) {
+                       throw new RuntimeException( 'Could not extract the MediaWiki version from DefaultSettings.php' );
+               }
+
+               return $matches[1];
+       }
+
+}
\ No newline at end of file
index dd22844..7c9b095 100644 (file)
  * @since 1.17
  */
 class Message {
+
        /**
         * In which language to get this message. True, which is the default,
         * means the current interface language, false content language.
+        *
+        * @var bool
         */
        protected $interface = true;
 
@@ -172,12 +175,12 @@ class Message {
        protected $language = null;
 
        /**
-        * The message key.
+        * @var string|string[] The message key or array of keys.
         */
        protected $key;
 
        /**
-        * List of parameters which will be substituted into the message.
+        * @var array List of parameters which will be substituted into the message.
         */
        protected $parameters = array();
 
@@ -189,21 +192,23 @@ class Message {
         * * block-parse
         * * parse (default)
         * * plain
+        *
+        * @var string
         */
        protected $format = 'parse';
 
        /**
-        * Whether database can be used.
+        * @var bool Whether database can be used.
         */
        protected $useDatabase = true;
 
        /**
-        * Title object to use as context
+        * @var Title Title object to use as context.
         */
        protected $title = null;
 
        /**
-        * Content object representing the message
+        * @var Content Content object representing the message.
         */
        protected $content = null;
 
@@ -213,11 +218,11 @@ class Message {
        protected $message;
 
        /**
-        * Constructor.
         * @since 1.17
-        * @param $key: message key, or array of message keys to try and use the first non-empty message for
-        * @param array $params message parameters
-        * @return Message: $this
+        *
+        * @param string|string[] $key Message key or array of message keys to try and use the first
+        * non-empty message for.
+        * @param array $params Message parameters.
         */
        public function __construct( $key, $params = array() ) {
                global $wgLang;
@@ -227,7 +232,7 @@ class Message {
        }
 
        /**
-        * Returns the message key
+        * Returns the message key or the first from an array of message keys.
         *
         * @since 1.21
         *
@@ -244,18 +249,18 @@ class Message {
        }
 
        /**
-        * Returns the message parameters
+        * Returns the message parameters.
         *
         * @since 1.21
         *
-        * @return string[]
+        * @return array
         */
        public function getParams() {
                return $this->parameters;
        }
 
        /**
-        * Returns the message format
+        * Returns the message format.
         *
         * @since 1.21
         *
@@ -269,10 +274,13 @@ class Message {
         * Factory function that is just wrapper for the real constructor. It is
         * intended to be used instead of the real constructor, because it allows
         * chaining method calls, while new objects don't.
+        *
         * @since 1.17
-        * @param string $key message key
-        * @param Varargs: parameters as Strings
-        * @return Message: $this
+        *
+        * @param string|string[] $key Message key or array of keys.
+        * @param mixed [$param,...] Parameters as strings.
+        *
+        * @return Message
         */
        public static function newFromKey( $key /*...*/ ) {
                $params = func_get_args();
@@ -284,9 +292,13 @@ class Message {
         * Factory function accepting multiple message keys and returning a message instance
         * for the first message which is non-empty. If all messages are empty then an
         * instance of the first message key is returned.
+        *
         * @since 1.18
-        * @param Varargs: message keys (or first arg as an array of all the message keys)
-        * @return Message: $this
+        *
+        * @param string|string[] [$keys,...] Message keys, or first argument as an array of all the
+        * message keys.
+        *
+        * @return Message
         */
        public static function newFallbackSequence( /*...*/ ) {
                $keys = func_get_args();
@@ -304,9 +316,13 @@ class Message {
 
        /**
         * Adds parameters to the parameter list of this message.
+        *
         * @since 1.17
-        * @param Varargs: parameters as Strings, or a single argument that is an array of Strings
-        * @return Message: $this
+        *
+        * @param mixed [$params,...] Parameters as strings, or a single argument that is
+        * an array of strings.
+        *
+        * @return Message $this
         */
        public function params( /*...*/ ) {
                $args = func_get_args();
@@ -323,9 +339,13 @@ class Message {
         * In other words the parsing process cannot access the contents
         * of this type of parameter, and you need to make sure it is
         * sanitized beforehand.  The parser will see "$n", instead.
+        *
         * @since 1.17
-        * @param Varargs: raw parameters as Strings (or single argument that is an array of raw parameters)
-        * @return Message: $this
+        *
+        * @param mixed [$params,...] Raw parameters as strings, or a single argument that is
+        * an array of raw parameters.
+        *
+        * @return Message $this
         */
        public function rawParams( /*...*/ ) {
                $params = func_get_args();
@@ -341,9 +361,13 @@ class Message {
        /**
         * Add parameters that are numeric and will be passed through
         * Language::formatNum before substitution
+        *
         * @since 1.18
-        * @param Varargs: numeric parameters (or single argument that is array of numeric parameters)
-        * @return Message: $this
+        *
+        * @param mixed [$param,...] Numeric parameters, or a single argument that is
+        * an array of numeric parameters.
+        *
+        * @return Message $this
         */
        public function numParams( /*...*/ ) {
                $params = func_get_args();
@@ -359,9 +383,13 @@ class Message {
        /**
         * Add parameters that are durations of time and will be passed through
         * Language::formatDuration before substitution
+        *
         * @since 1.22
-        * @param Varargs: numeric parameters (or single argument that is array of numeric parameters)
-        * @return Message: $this
+        *
+        * @param int|int[] [$param,...] Duration parameters, or a single argument that is
+        * an array of duration parameters.
+        *
+        * @return Message $this
         */
        public function durationParams( /*...*/ ) {
                $params = func_get_args();
@@ -377,9 +405,13 @@ class Message {
        /**
         * Add parameters that are expiration times and will be passed through
         * Language::formatExpiry before substitution
+        *
         * @since 1.22
-        * @param Varargs: numeric parameters (or single argument that is array of numeric parameters)
-        * @return Message: $this
+        *
+        * @param string|string[] [$param,...] Expiry parameters, or a single argument that is
+        * an array of expiry parameters.
+        *
+        * @return Message $this
         */
        public function expiryParams( /*...*/ ) {
                $params = func_get_args();
@@ -395,9 +427,13 @@ class Message {
        /**
         * Add parameters that are time periods and will be passed through
         * Language::formatTimePeriod before substitution
+        *
         * @since 1.22
-        * @param Varargs: numeric parameters (or single argument that is array of numeric parameters)
-        * @return Message: $this
+        *
+        * @param number|number[] [$param,...] Time period parameters, or a single argument that is
+        * an array of time period parameters.
+        *
+        * @return Message $this
         */
        public function timeperiodParams( /*...*/ ) {
                $params = func_get_args();
@@ -413,9 +449,13 @@ class Message {
        /**
         * Add parameters that are file sizes and will be passed through
         * Language::formatSize before substitution
+        *
         * @since 1.22
-        * @param Varargs: numeric parameters (or single argument that is array of numeric parameters)
-        * @return Message: $this
+        *
+        * @param int|int[] [$param,...] Size parameters, or a single argument that is
+        * an array of size parameters.
+        *
+        * @return Message $this
         */
        public function sizeParams( /*...*/ ) {
                $params = func_get_args();
@@ -431,9 +471,13 @@ class Message {
        /**
         * Add parameters that are bitrates and will be passed through
         * Language::formatBitrate before substitution
+        *
         * @since 1.22
-        * @param Varargs: numeric parameters (or single argument that is array of numeric parameters)
-        * @return Message: $this
+        *
+        * @param int|int[] [$param,...] Bit rate parameters, or a single argument that is
+        * an array of bit rate parameters.
+        *
+        * @return Message $this
         */
        public function bitrateParams( /*...*/ ) {
                $params = func_get_args();
@@ -448,9 +492,12 @@ class Message {
 
        /**
         * Set the language and the title from a context object
+        *
         * @since 1.19
+        *
         * @param $context IContextSource
-        * @return Message: $this
+        *
+        * @return Message $this
         */
        public function setContext( IContextSource $context ) {
                $this->inLanguage( $context->getLanguage() );
@@ -464,10 +511,13 @@ class Message {
         * Request the message in any language that is supported.
         * As a side effect interface message status is unconditionally
         * turned off.
+        *
         * @since 1.17
-        * @param $lang Mixed: language code or Language object.
+        *
+        * @param Language|string $lang Language code or Language object.
+        *
+        * @return Message $this
         * @throws MWException
-        * @return Message: $this
         */
        public function inLanguage( $lang ) {
                if ( $lang instanceof Language || $lang instanceof StubUserLang ) {
@@ -489,9 +539,11 @@ class Message {
        /**
         * Request the message in the wiki's content language,
         * unless it is disabled for this message.
+        *
         * @since 1.17
         * @see $wgForceUIMsgAsContentMsg
-        * @return Message: $this
+        *
+        * @return Message $this
         */
        public function inContentLanguage() {
                global $wgForceUIMsgAsContentMsg;
@@ -508,31 +560,40 @@ class Message {
        /**
         * Allows manipulating the interface message flag directly.
         * Can be used to restore the flag after setting a language.
-        * @param $value bool
-        * @return Message: $this
+        *
         * @since 1.20
+        *
+        * @param bool $interface
+        *
+        * @return Message $this
         */
-       public function setInterfaceMessageFlag( $value ) {
-               $this->interface = (bool)$value;
+       public function setInterfaceMessageFlag( $interface ) {
+               $this->interface = (bool)$interface;
                return $this;
        }
 
        /**
         * Enable or disable database use.
+        *
         * @since 1.17
-        * @param $value Boolean
-        * @return Message: $this
+        *
+        * @param bool $useDatabase
+        *
+        * @return Message $this
         */
-       public function useDatabase( $value ) {
-               $this->useDatabase = (bool)$value;
+       public function useDatabase( $useDatabase ) {
+               $this->useDatabase = (bool)$useDatabase;
                return $this;
        }
 
        /**
         * Set the Title object to use as context when transforming the message
+        *
         * @since 1.18
+        *
         * @param $title Title object
-        * @return Message: $this
+        *
+        * @return Message $this
         */
        public function title( $title ) {
                $this->title = $title;
@@ -541,6 +602,7 @@ class Message {
 
        /**
         * Returns the message as a Content object.
+        *
         * @return Content
         */
        public function content() {
@@ -553,8 +615,10 @@ class Message {
 
        /**
         * Returns the message parsed from wikitext to HTML.
+        *
         * @since 1.17
-        * @return String: HTML
+        *
+        * @return string HTML
         */
        public function toString() {
                $string = $this->fetchMessage();
@@ -605,8 +669,10 @@ class Message {
         * Magic method implementation of the above (for PHP >= 5.2.0), so we can do, eg:
         *     $foo = Message::get( $key );
         *     $string = "<abbr>$foo</abbr>";
+        *
         * @since 1.18
-        * @return String
+        *
+        * @return string
         */
        public function __toString() {
                // PHP doesn't allow __toString to throw exceptions and will
@@ -630,9 +696,11 @@ class Message {
        }
 
        /**
-        * Fully parse the text from wikitext to HTML
+        * Fully parse the text from wikitext to HTML.
+        *
         * @since 1.17
-        * @return String parsed HTML
+        *
+        * @return string Parsed HTML.
         */
        public function parse() {
                $this->format = 'parse';
@@ -641,8 +709,10 @@ class Message {
 
        /**
         * Returns the message text. {{-transformation is done.
+        *
         * @since 1.17
-        * @return String: Unescaped message text.
+        *
+        * @return string Unescaped message text.
         */
        public function text() {
                $this->format = 'text';
@@ -651,8 +721,10 @@ class Message {
 
        /**
         * Returns the message text as-is, only parameters are substituted.
+        *
         * @since 1.17
-        * @return String: Unescaped untransformed message text.
+        *
+        * @return string Unescaped untransformed message text.
         */
        public function plain() {
                $this->format = 'plain';
@@ -661,8 +733,10 @@ class Message {
 
        /**
         * Returns the parsed message text which is always surrounded by a block element.
+        *
         * @since 1.17
-        * @return String: HTML
+        *
+        * @return string HTML
         */
        public function parseAsBlock() {
                $this->format = 'block-parse';
@@ -672,8 +746,10 @@ class Message {
        /**
         * Returns the message text. {{-transformation is done and the result
         * is escaped excluding any raw parameters.
+        *
         * @since 1.17
-        * @return String: Escaped message text.
+        *
+        * @return string Escaped message text.
         */
        public function escaped() {
                $this->format = 'escaped';
@@ -682,8 +758,10 @@ class Message {
 
        /**
         * Check whether a message key has been defined currently.
+        *
         * @since 1.17
-        * @return Bool: true if it is and false if not.
+        *
+        * @return bool
         */
        public function exists() {
                return $this->fetchMessage() !== false;
@@ -691,9 +769,11 @@ class Message {
 
        /**
         * Check whether a message does not exist, or is an empty string
+        *
         * @since 1.18
-        * @return Bool: true if is is and false if not
         * @todo FIXME: Merge with isDisabled()?
+        *
+        * @return bool
         */
        public function isBlank() {
                $message = $this->fetchMessage();
@@ -701,9 +781,11 @@ class Message {
        }
 
        /**
-        * Check whether a message does not exist, is an empty string, or is "-"
+        * Check whether a message does not exist, is an empty string, or is "-".
+        *
         * @since 1.18
-        * @return Bool: true if it is and false if not
+        *
+        * @return bool
         */
        public function isDisabled() {
                $message = $this->fetchMessage();
@@ -712,72 +794,89 @@ class Message {
 
        /**
         * @since 1.17
-        * @param $value
-        * @return array
+        *
+        * @param mixed $raw
+        *
+        * @return array Array with a single "raw" key.
         */
-       public static function rawParam( $value ) {
-               return array( 'raw' => $value );
+       public static function rawParam( $raw ) {
+               return array( 'raw' => $raw );
        }
 
        /**
         * @since 1.18
-        * @param $value
-        * @return array
+        *
+        * @param mixed $num
+        *
+        * @return array Array with a single "num" key.
         */
-       public static function numParam( $value ) {
-               return array( 'num' => $value );
+       public static function numParam( $num ) {
+               return array( 'num' => $num );
        }
 
        /**
         * @since 1.22
-        * @param $value
-        * @return array
+        *
+        * @param int $duration
+        *
+        * @return int[] Array with a single "duration" key.
         */
-       public static function durationParam( $value ) {
-               return array( 'duration' => $value );
+       public static function durationParam( $duration ) {
+               return array( 'duration' => $duration );
        }
 
        /**
         * @since 1.22
-        * @param $value
-        * @return array
+        *
+        * @param string $expiry
+        *
+        * @return string[] Array with a single "expiry" key.
         */
-       public static function expiryParam( $value ) {
-               return array( 'expiry' => $value );
+       public static function expiryParam( $expiry ) {
+               return array( 'expiry' => $expiry );
        }
 
        /**
         * @since 1.22
-        * @param $value
-        * @return array
+        *
+        * @param number $period
+        *
+        * @return number[] Array with a single "period" key.
         */
-       public static function timeperiodParam( $value ) {
-               return array( 'period' => $value );
+       public static function timeperiodParam( $period ) {
+               return array( 'period' => $period );
        }
 
        /**
         * @since 1.22
-        * @param $value
-        * @return array
+        *
+        * @param int $size
+        *
+        * @return int[] Array with a single "size" key.
         */
-       public static function sizeParam( $value ) {
-               return array( 'size' => $value );
+       public static function sizeParam( $size ) {
+               return array( 'size' => $size );
        }
 
        /**
         * @since 1.22
-        * @param $value
-        * @return array
+        *
+        * @param int $bitrate
+        *
+        * @return int[] Array with a single "bitrate" key.
         */
-       public static function bitrateParam( $value ) {
-               return array( 'bitrate' => $value );
+       public static function bitrateParam( $bitrate ) {
+               return array( 'bitrate' => $bitrate );
        }
 
        /**
         * Substitutes any parameters into the message text.
+        *
         * @since 1.17
-        * @param string $message the message text
-        * @param string $type either before or after
+        *
+        * @param string $message The message text.
+        * @param string $type Either "before" or "after".
+        *
         * @return String
         */
        protected function replaceParameters( $message, $type = 'before' ) {
@@ -794,9 +893,12 @@ class Message {
 
        /**
         * Extracts the parameter type and preprocessed the value if needed.
+        *
         * @since 1.18
-        * @param string|array $param Parameter as defined in this class.
-        * @return Tuple(type, value)
+        *
+        * @param mixed $param Parameter as defined in this class.
+        *
+        * @return array Array with the parameter type (either "before" or "after") and the value.
         */
        protected function extractParam( $param ) {
                if ( is_array( $param ) ) {
@@ -837,9 +939,12 @@ class Message {
 
        /**
         * Wrapper for what ever method we use to parse wikitext.
+        *
         * @since 1.17
-        * @param string $string Wikitext message contents
-        * @return string Wikitext parsed into HTML
+        *
+        * @param string $string Wikitext message contents.
+        *
+        * @return string Wikitext parsed into HTML.
         */
        protected function parseText( $string ) {
                $out = MessageCache::singleton()->parse( $string, $this->title, /*linestart*/true, $this->interface, $this->language );
@@ -848,8 +953,11 @@ class Message {
 
        /**
         * Wrapper for what ever method we use to {{-transform wikitext.
+        *
         * @since 1.17
-        * @param string $string Wikitext message contents
+        *
+        * @param string $string Wikitext message contents.
+        *
         * @return string Wikitext with {{-constructs replaced with their values.
         */
        protected function transformText( $string ) {
@@ -857,10 +965,12 @@ class Message {
        }
 
        /**
-        * Wrapper for what ever method we use to get message contents
+        * Wrapper for what ever method we use to get message contents.
+        *
         * @since 1.17
-        * @throws MWException
+        *
         * @return string
+        * @throws MWException If message key array is empty.
         */
        protected function fetchMessage() {
                if ( !isset( $this->message ) ) {
@@ -899,13 +1009,15 @@ class Message {
  * @since 1.21
  */
 class RawMessage extends Message {
+
        /**
         * Call the parent constructor, then store the key as
         * the message.
         *
-        * @param string $key Message to use
-        * @param array $params Parameters for the message
         * @see Message::__construct
+        *
+        * @param string|string[] $key Message to use.
+        * @param array $params Parameters for the message.
         */
        public function __construct( $key, $params = array() ) {
                parent::__construct( $key, $params );
@@ -925,4 +1037,5 @@ class RawMessage extends Message {
                }
                return $this->message;
        }
+
 }
index b4f14c2..3d4c464 100644 (file)
@@ -186,7 +186,7 @@ abstract class PoolCounterWork {
         * @return void
         */
        function logError( $status ) {
-               wfDebugLog( 'poolcounter', "Pool key '{$this->key}':"
+               wfDebugLog( 'poolcounter', "Pool key '{$this->key}': "
                        . $status->getMessage()->inLanguage( 'en' )->useDatabase( false )->text() );
        }
 
index 0ae6e9b..209edef 100644 (file)
@@ -452,6 +452,11 @@ if ( !$wgHTCPRouting && $wgHTCPMulticastAddress ) {
        );
 }
 
+// Back compatibility for $wgRateLimitLog deprecated with 1.23
+if ( $wgRateLimitLog && ! array_key_exists( 'ratelimit', $wgDebugLogGroups ) ) {
+       $wgDebugLogGroups['ratelimit'] = $wgRateLimitLog;
+}
+
 wfProfileOut( $fname . '-defaults2' );
 wfProfileIn( $fname . '-misc1' );
 
index 4f0e1fe..066411d 100644 (file)
@@ -104,7 +104,7 @@ class SkinTemplate extends Skin {
         * @param $out OutputPage
         */
        function setupSkinUserCss( OutputPage $out ) {
-               $out->addModuleStyles( array( 'mediawiki.legacy.shared', 'mediawiki.legacy.commonPrint' ) );
+               $out->addModuleStyles( array( 'mediawiki.legacy.shared', 'mediawiki.legacy.commonPrint', 'mediawiki.ui.button' ) );
        }
 
        /**
@@ -1596,7 +1596,7 @@ abstract class BaseTemplate extends QuickTemplate {
                        if ( isset( $plink['active'] ) ) {
                                $ptool['active'] = $plink['active'];
                        }
-                       foreach ( array( 'href', 'class', 'text' ) as $k ) {
+                       foreach ( array( 'href', 'class', 'text', 'dir' ) as $k ) {
                                if ( isset( $plink[$k] ) ) {
                                        $ptool['links'][0][$k] = $plink[$k];
                                }
@@ -1840,7 +1840,7 @@ abstract class BaseTemplate extends QuickTemplate {
         *
         * @param $key string, usually a key from the list you are generating this link from.
         * @param $item array, of list item data containing some of a specific set of keys.
-        * The "id" and "class" keys will be used as attributes for the list item,
+        * The "id", "class" and "itemtitle" keys will be used as attributes for the list item,
         * if "active" contains a value of true a "active" class will also be appended to class.
         *
         * @param $options array
@@ -1857,7 +1857,8 @@ abstract class BaseTemplate extends QuickTemplate {
         * list item directly so they will not be passed to makeLink
         * (however the link will still support a tooltip and accesskey from it)
         * If you need an id or class on a single link you should include a "links"
-        * array with just one link item inside of it.
+        * array with just one link item inside of it. If you want to add a title
+        * to the list item itself, you can set "itemtitle" to the value.
         * $options is also passed on to makeLink calls
         *
         * @return string
@@ -1871,7 +1872,7 @@ abstract class BaseTemplate extends QuickTemplate {
                } else {
                        $link = $item;
                        // These keys are used by makeListItem and shouldn't be passed on to the link
-                       foreach ( array( 'id', 'class', 'active', 'tag' ) as $k ) {
+                       foreach ( array( 'id', 'class', 'active', 'tag', 'itemtitle' ) as $k ) {
                                unset( $link[$k] );
                        }
                        if ( isset( $item['id'] ) && !isset( $item['single-id'] ) ) {
@@ -1896,6 +1897,9 @@ abstract class BaseTemplate extends QuickTemplate {
                        $attrs['class'] .= ' active';
                        $attrs['class'] = trim( $attrs['class'] );
                }
+               if ( isset( $item['itemtitle'] ) ) {
+                       $attrs['title'] = $item['itemtitle'];
+               }
                return Html::rawElement( isset( $options['tag'] ) ? $options['tag'] : 'li', $attrs, $html );
        }
 
index 4b57dd2..e728323 100644 (file)
@@ -1056,7 +1056,8 @@ class User {
                        # Get the token from DB/cache and clean it up to remove garbage padding.
                        # This deals with historical problems with bugs and the default column value.
                        $token = rtrim( $proposedUser->getToken( false ) ); // correct token
-                       $passwordCorrect = ( strlen( $token ) && $token === $request->getCookie( 'Token' ) );
+                       // Make comparison in constant time (bug 61346)
+                       $passwordCorrect = strlen( $token ) && $this->compareSecrets( $token, $request->getCookie( 'Token' ) );
                        $from = 'cookie';
                } else {
                        // No session or persistent login cookie
@@ -1075,6 +1076,25 @@ class User {
                }
        }
 
+       /**
+        * A comparison of two strings, not vulnerable to timing attacks
+        * @param string $answer the secret string that you are comparing against.
+        * @param string $test compare this string to the $answer.
+        * @return bool True if the strings are the same, false otherwise
+        */
+       protected function compareSecrets( $answer, $test ) {
+               if ( strlen( $answer ) !== strlen( $test ) ) {
+                       $passwordCorrect = false;
+               } else {
+                       $result = 0;
+                       for ( $i = 0; $i < strlen( $answer ); $i++ ) {
+                               $result |= ord( $answer{$i} ) ^ ord( $test{$i} );
+                       }
+                       $passwordCorrect = ( $result == 0 );
+               }
+               return $passwordCorrect;
+       }
+
        /**
         * Load user and user_group data from the database.
         * $this->mId must be set, this is how the user is identified.
@@ -1582,7 +1602,7 @@ class User {
                        return false;
                }
 
-               global $wgMemc, $wgRateLimitLog;
+               global $wgMemc;
                wfProfileIn( __METHOD__ );
 
                $limits = $wgRateLimits[$action];
@@ -1645,12 +1665,7 @@ class User {
                        // Already pinged?
                        if ( $count ) {
                                if ( $count >= $max ) {
-                                       wfDebug( __METHOD__ . ": tripped! $key at $count $summary\n" );
-                                       if ( $wgRateLimitLog ) {
-                                               wfSuppressWarnings();
-                                               file_put_contents( $wgRateLimitLog, wfTimestamp( TS_MW ) . ' ' . wfWikiID() . ': ' . $this->getName() . " tripped $key at $count $summary\n", FILE_APPEND );
-                                               wfRestoreWarnings();
-                                       }
+                                       wfDebugLog( 'ratelimit', $this->getName() . " tripped! $key at $count $summary");
                                        $triggered = true;
                                } else {
                                        wfDebug( __METHOD__ . ": ok. $key at $count $summary\n" );
index 99857d9..5c67e5f 100644 (file)
@@ -448,6 +448,7 @@ class MediaWiki {
                        if ( function_exists( 'fastcgi_finish_request' ) ) {
                                fastcgi_finish_request();
                        }
+                       $this->triggerJobs();
                        $this->restInPeace();
                } catch ( Exception $e ) {
                        MWExceptionHandler::handle( $e );
@@ -583,6 +584,7 @@ class MediaWiki {
                        wfProfileOut( 'main-try-filecache' );
                }
 
+               // Actually do the work of the request and build up any output
                $this->performRequest();
 
                // Now commit any transactions, so that unreported errors after
@@ -602,9 +604,6 @@ class MediaWiki {
                // Do any deferred jobs
                DeferredUpdates::doUpdates( 'commit' );
 
-               // Execute a job from the queue
-               $this->doJobs();
-
                // Log profiling data, e.g. in the database or UDP
                wfLogProfilingData();
 
@@ -617,15 +616,19 @@ class MediaWiki {
        }
 
        /**
-        * Do a job from the job queue
+        * Potentially open a socket and sent an HTTP request back to the server
+        * to run a specified number of jobs. This registers a callback to cleanup
+        * the socket once it's done.
         */
-       private function doJobs() {
-               global $wgJobRunRate, $wgPhpCli, $IP;
+       protected function triggerJobs() {
+               global $wgJobRunRate, $wgServer, $wgScriptPath, $wgScriptExtension, $wgEnableAPI;
 
                if ( $wgJobRunRate <= 0 || wfReadOnly() ) {
                        return;
                }
 
+               $section = new ProfileSection( __METHOD__ );
+
                if ( $wgJobRunRate < 1 ) {
                        $max = mt_getrandmax();
                        if ( mt_rand( 0, $max ) > $max * $wgJobRunRate ) {
@@ -636,51 +639,49 @@ class MediaWiki {
                        $n = intval( $wgJobRunRate );
                }
 
-               if ( !wfShellExecDisabled() && is_executable( $wgPhpCli ) ) {
-                       // Start a background process to run some of the jobs
-                       wfProfileIn( __METHOD__ . '-exec' );
-                       $retVal = 1;
-                       $cmd = wfShellWikiCmd( "$IP/maintenance/runJobs.php",
-                               array( '--wiki', wfWikiID(), '--maxjobs', $n ) );
-                       $cmd .= " >" . wfGetNull() . " 2>&1"; // don't hang PHP on pipes
-                       if ( wfIsWindows() ) {
-                               // Using START makes this async and also works around a bug where using
-                               // wfShellExec() with a quoted script name causes a filename syntax error.
-                               $cmd = "START /B \"bg\" $cmd";
-                       } else {
-                               $cmd = "$cmd &";
-                       }
-                       wfShellExec( $cmd, $retVal );
-                       wfProfileOut( __METHOD__ . '-exec' );
+               $query = array( 'action' => 'runjobs',
+                       'tasks' => 'jobs', 'maxjobs' => $n, 'sigexpiry' => time() + 5 );
+               $query['signature'] = ApiRunJobs::getQuerySignature( $query );
+
+               if ( !$wgEnableAPI ) {
+                       ApiRunJobs::executeJobs( $n ); // slow fallback
+                       return;
+               }
+
+               $errno = $errstr = null;
+               $info = wfParseUrl( $wgServer );
+               wfSuppressWarnings();
+               $sock = fsockopen(
+                       $info['host'],
+                       isset( $info['port'] ) ? $info['port'] : 80,
+                       $errno,
+                       $errstr
+               );
+               wfRestoreWarnings();
+               if ( !$sock ) {
+                       wfDebugLog( 'runJobs', "Failed to start cron API (socket error $errno): $errstr\n" );
+                       ApiRunJobs::executeJobs( $n ); // slow fallback
+                       return;
+               }
+
+               $url = wfAppendQuery( "{$wgScriptPath}/api{$wgScriptExtension}", $query );
+               $req = "POST $url HTTP/1.1\r\nHost: {$info['host']}\r\nConnection: Close\r\n\r\n";
+
+               wfDebugLog( 'runJobs', "Running $n job(s) via '$url'\n" );
+               // Send a cron API request to be performed in the background.
+               // Give up if this takes too long to send (which should be rare).
+               stream_set_timeout( $sock, 1 );
+               $bytes = fwrite( $sock, $req );
+               if ( $bytes !== strlen( $req ) ) {
+                       wfDebugLog( 'runJobs', "Failed to start cron API (socket write error)\n" );
                } else {
-                       try {
-                               // Fallback to running the jobs here while the user waits
-                               $group = JobQueueGroup::singleton();
-                               do {
-                                       $job = $group->pop( JobQueueGroup::USE_CACHE ); // job from any queue
-                                       if ( $job ) {
-                                               $output = $job->toString() . "\n";
-                                               $t = - microtime( true );
-                                               wfProfileIn( __METHOD__ . '-' . get_class( $job ) );
-                                               $success = $job->run();
-                                               wfProfileOut( __METHOD__ . '-' . get_class( $job ) );
-                                               $group->ack( $job ); // done
-                                               $t += microtime( true );
-                                               $t = round( $t * 1000 );
-                                               if ( $success === false ) {
-                                                       $output .= "Error: " . $job->getLastError() . ", Time: $t ms\n";
-                                               } else {
-                                                       $output .= "Success, Time: $t ms\n";
-                                               }
-                                               wfDebugLog( 'jobqueue', $output );
-                                       }
-                               } while ( --$n && $job );
-                       } catch ( MWException $e ) {
-                               // We don't want exceptions thrown during job execution to
-                               // be reported to the user since the output is already sent.
-                               // Instead we just log them.
-                               MWExceptionHandler::logException( $e );
+                       // Do not wait for the response (the script should handle client aborts).
+                       // Make sure that we don't close before that script reaches ignore_user_abort().
+                       $status = fgets( $sock );
+                       if ( !preg_match( '#^HTTP/\d\.\d 202 #', $status ) ) {
+                               wfDebugLog( 'runJobs', "Failed to start cron API: received '$status'\n" );
                        }
                }
+               fclose( $sock );
        }
 }
diff --git a/includes/actions/Action.php b/includes/actions/Action.php
new file mode 100644 (file)
index 0000000..1180c5e
--- /dev/null
@@ -0,0 +1,380 @@
+<?php
+/**
+ * Base classes for actions done on pages.
+ *
+ * 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
+ *
+ * @file
+ */
+
+/**
+ * @defgroup Actions Action done on pages
+ */
+
+/**
+ * Actions are things which can be done to pages (edit, delete, rollback, etc).  They
+ * are distinct from Special Pages because an action must apply to exactly one page.
+ *
+ * To add an action in an extension, create a subclass of Action, and add the key to
+ * $wgActions.  There is also the deprecated UnknownAction hook
+ *
+ * Actions generally fall into two groups: the show-a-form-then-do-something-with-the-input
+ * 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 {
+
+       /**
+        * Page on which we're performing the action
+        * @var WikiPage|Article|ImagePage|CategoryPage|Page $page
+        */
+       protected $page;
+
+       /**
+        * IContextSource if specified; otherwise we'll use the Context from the Page
+        * @var IContextSource $context
+        */
+       protected $context;
+
+       /**
+        * The fields used to create the HTMLForm
+        * @var Array $fields
+        */
+       protected $fields;
+
+       /**
+        * Get the Action subclass which should be used to handle this action, false if
+        * the action is disabled, or null if it's not recognised
+        * @param $action String
+        * @param $overrides Array
+        * @return bool|null|string|callable
+        */
+       final private static function getClass( $action, array $overrides ) {
+               global $wgActions;
+               $action = strtolower( $action );
+
+               if ( !isset( $wgActions[$action] ) ) {
+                       return null;
+               }
+
+               if ( $wgActions[$action] === false ) {
+                       return false;
+               } elseif ( $wgActions[$action] === true && isset( $overrides[$action] ) ) {
+                       return $overrides[$action];
+               } elseif ( $wgActions[$action] === true ) {
+                       return ucfirst( $action ) . 'Action';
+               } else {
+                       return $wgActions[$action];
+               }
+       }
+
+       /**
+        * Get an appropriate Action subclass for the given action
+        * @param $action String
+        * @param $page Page
+        * @param $context IContextSource
+        * @return Action|bool|null false if the action is disabled, null
+        *     if it is not recognised
+        */
+       final public static function factory( $action, Page $page, IContextSource $context = null ) {
+               $classOrCallable = self::getClass( $action, $page->getActionOverrides() );
+
+               if ( is_string( $classOrCallable ) ) {
+                       $obj = new $classOrCallable( $page, $context );
+                       return $obj;
+               }
+
+               if ( is_callable( $classOrCallable ) ) {
+                       return call_user_func_array( $classOrCallable, array( $page, $context ) );
+               }
+
+               return $classOrCallable;
+       }
+
+       /**
+        * Get the action that will be executed, not necessarily the one passed
+        * passed through the "action" request parameter. Actions disabled in
+        * $wgActions will be replaced by "nosuchaction".
+        *
+        * @since 1.19
+        * @param $context IContextSource
+        * @return string: action name
+        */
+       final public static function getActionName( IContextSource $context ) {
+               global $wgActions;
+
+               $request = $context->getRequest();
+               $actionName = $request->getVal( 'action', 'view' );
+
+               // Check for disabled actions
+               if ( isset( $wgActions[$actionName] ) && $wgActions[$actionName] === false ) {
+                       $actionName = 'nosuchaction';
+               }
+
+               // Workaround for bug #20966: inability of IE to provide an action dependent
+               // on which submit button is clicked.
+               if ( $actionName === 'historysubmit' ) {
+                       if ( $request->getBool( 'revisiondelete' ) ) {
+                               $actionName = 'revisiondelete';
+                       } else {
+                               $actionName = 'view';
+                       }
+               } elseif ( $actionName == 'editredlink' ) {
+                       $actionName = 'edit';
+               }
+
+               // Trying to get a WikiPage for NS_SPECIAL etc. will result
+               // in WikiPage::factory throwing "Invalid or virtual namespace -1 given."
+               // For SpecialPages et al, default to action=view.
+               if ( !$context->canUseWikiPage() ) {
+                       return 'view';
+               }
+
+               $action = Action::factory( $actionName, $context->getWikiPage(), $context );
+               if ( $action instanceof Action ) {
+                       return $action->getName();
+               }
+
+               return 'nosuchaction';
+       }
+
+       /**
+        * Check if a given action is recognised, even if it's disabled
+        *
+        * @param string $name name of an action
+        * @return Bool
+        */
+       final public static function exists( $name ) {
+               return self::getClass( $name, array() ) !== null;
+       }
+
+       /**
+        * Get the IContextSource in use here
+        * @return IContextSource
+        */
+       final public function getContext() {
+               if ( $this->context instanceof IContextSource ) {
+                       return $this->context;
+               } elseif ( $this->page instanceof Article ) {
+                       // NOTE: $this->page can be a WikiPage, which does not have a context.
+                       wfDebug( __METHOD__ . ': no context known, falling back to Article\'s context.' );
+                       return $this->page->getContext();
+               }
+
+               wfWarn( __METHOD__ . ': no context known, falling back to RequestContext::getMain().' );
+               return RequestContext::getMain();
+       }
+
+       /**
+        * Get the WebRequest being used for this instance
+        *
+        * @return WebRequest
+        */
+       final public function getRequest() {
+               return $this->getContext()->getRequest();
+       }
+
+       /**
+        * Get the OutputPage being used for this instance
+        *
+        * @return OutputPage
+        */
+       final public function getOutput() {
+               return $this->getContext()->getOutput();
+       }
+
+       /**
+        * Shortcut to get the User being used for this instance
+        *
+        * @return User
+        */
+       final public function getUser() {
+               return $this->getContext()->getUser();
+       }
+
+       /**
+        * Shortcut to get the Skin being used for this instance
+        *
+        * @return Skin
+        */
+       final public function getSkin() {
+               return $this->getContext()->getSkin();
+       }
+
+       /**
+        * Shortcut to get the user Language being used for this instance
+        *
+        * @return Language
+        */
+       final public function getLanguage() {
+               return $this->getContext()->getLanguage();
+       }
+
+       /**
+        * Shortcut to get the user Language being used for this instance
+        *
+        * @deprecated since 1.19 Use getLanguage instead
+        * @return Language
+        */
+       final public function getLang() {
+               wfDeprecated( __METHOD__, '1.19' );
+               return $this->getLanguage();
+       }
+
+       /**
+        * Shortcut to get the Title object from the page
+        * @return Title
+        */
+       final public function getTitle() {
+               return $this->page->getTitle();
+       }
+
+       /**
+        * Get a Message object with context set
+        * Parameters are the same as wfMessage()
+        *
+        * @return Message object
+        */
+       final public function msg() {
+               $params = func_get_args();
+               return call_user_func_array( array( $this->getContext(), 'msg' ), $params );
+       }
+
+       /**
+        * Constructor.
+        *
+        * Only public since 1.21
+        *
+        * @param $page Page
+        * @param $context IContextSource
+        */
+       public function __construct( Page $page, IContextSource $context = null ) {
+               if ( $context === null ) {
+                       wfWarn( __METHOD__ . ' called without providing a Context object.' );
+                       // NOTE: We could try to initialize $context using $page->getContext(),
+                       //      if $page is an Article. That however seems to not work seamlessly.
+               }
+
+               $this->page = $page;
+               $this->context = $context;
+       }
+
+       /**
+        * Return the name of the action this object responds to
+        * @return String lowercase
+        */
+       abstract public function getName();
+
+       /**
+        * Get the permission required to perform this action.  Often, but not always,
+        * the same as the action name
+        * @return String|null
+        */
+       public function getRestriction() {
+               return null;
+       }
+
+       /**
+        * Checks if the given user (identified by an object) can perform this action.  Can be
+        * overridden by sub-classes with more complicated permissions schemes.  Failures here
+        * must throw subclasses of ErrorPageError
+        *
+        * @param $user User: the user to check, or null to use the context user
+        * @throws UserBlockedError|ReadOnlyError|PermissionsError
+        * @return bool True on success
+        */
+       protected function checkCanExecute( User $user ) {
+               $right = $this->getRestriction();
+               if ( $right !== null ) {
+                       $errors = $this->getTitle()->getUserPermissionsErrors( $right, $user );
+                       if ( count( $errors ) ) {
+                               throw new PermissionsError( $right, $errors );
+                       }
+               }
+
+               if ( $this->requiresUnblock() && $user->isBlocked() ) {
+                       $block = $user->getBlock();
+                       throw new UserBlockedError( $block );
+               }
+
+               // This should be checked at the end so that the user won't think the
+               // error is only temporary when he also don't have the rights to execute
+               // this action
+               if ( $this->requiresWrite() && wfReadOnly() ) {
+                       throw new ReadOnlyError();
+               }
+               return true;
+       }
+
+       /**
+        * Whether this action requires the wiki not to be locked
+        * @return Bool
+        */
+       public function requiresWrite() {
+               return true;
+       }
+
+       /**
+        * Whether this action can still be executed by a blocked user
+        * @return Bool
+        */
+       public function requiresUnblock() {
+               return true;
+       }
+
+       /**
+        * Set output headers for noindexing etc.  This function will not be called through
+        * the execute() entry point, so only put UI-related stuff in here.
+        */
+       protected function setHeaders() {
+               $out = $this->getOutput();
+               $out->setRobotPolicy( "noindex,nofollow" );
+               $out->setPageTitle( $this->getPageTitle() );
+               $this->getOutput()->setSubtitle( $this->getDescription() );
+               $out->setArticleRelated( true );
+       }
+
+       /**
+        * Returns the name that goes in the \<h1\> page title
+        *
+        * @return String
+        */
+       protected function getPageTitle() {
+               return $this->getTitle()->getPrefixedText();
+       }
+
+       /**
+        * Returns the description that goes below the \<h1\> tag
+        *
+        * @return String
+        */
+       protected function getDescription() {
+               return $this->msg( strtolower( $this->getName() ) )->escaped();
+       }
+
+       /**
+        * The main action entry point.  Do all output for display and send it to the context
+        * output.  Do not use globals $wgOut, $wgRequest, etc, in implementations; use
+        * $this->getOutput(), etc.
+        * @throws ErrorPageError
+        */
+       abstract public function show();
+
+       /**
+        * Execute the action in a silent fashion: do not display anything or release any errors.
+        * @return Bool whether execution was successful
+        */
+       abstract public function execute();
+}
diff --git a/includes/actions/FormAction.php b/includes/actions/FormAction.php
new file mode 100644 (file)
index 0000000..974ee94
--- /dev/null
@@ -0,0 +1,168 @@
+<?php
+/**
+ * Base classes for actions done on pages.
+ *
+ * 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
+ *
+ * @file
+ */
+
+/**
+ * @defgroup Actions Action done on pages
+ */
+
+/**
+ * An action which shows a form and does something based on the input from the form
+ */
+abstract class FormAction extends Action {
+
+       /**
+        * Get an HTMLForm descriptor array
+        * @return Array
+        */
+       abstract protected function getFormFields();
+
+       /**
+        * Add pre- or post-text to the form
+        * @return String HTML which will be sent to $form->addPreText()
+        */
+       protected function preText() {
+               return '';
+       }
+
+       /**
+        * @return string
+        */
+       protected function postText() {
+               return '';
+       }
+
+       /**
+        * Play with the HTMLForm if you need to more substantially
+        * @param $form HTMLForm
+        */
+       protected function alterForm( HTMLForm $form ) {
+       }
+
+       /**
+        * Get the HTMLForm to control behavior
+        * @return HTMLForm|null
+        */
+       protected function getForm() {
+               $this->fields = $this->getFormFields();
+
+               // Give hooks a chance to alter the form, adding extra fields or text etc
+               wfRunHooks( 'ActionModifyFormFields', array( $this->getName(), &$this->fields, $this->page ) );
+
+               $form = new HTMLForm( $this->fields, $this->getContext(), $this->getName() );
+               $form->setSubmitCallback( array( $this, 'onSubmit' ) );
+
+               // Retain query parameters (uselang etc)
+               $form->addHiddenField( 'action', $this->getName() ); // Might not be the same as the query string
+               $params = array_diff_key(
+                       $this->getRequest()->getQueryValues(),
+                       array( 'action' => null, 'title' => null )
+               );
+               $form->addHiddenField( 'redirectparams', wfArrayToCgi( $params ) );
+
+               $form->addPreText( $this->preText() );
+               $form->addPostText( $this->postText() );
+               $this->alterForm( $form );
+
+               // Give hooks a chance to alter the form, adding extra fields or text etc
+               wfRunHooks( 'ActionBeforeFormDisplay', array( $this->getName(), &$form, $this->page ) );
+
+               return $form;
+       }
+
+       /**
+        * Process the form on POST submission.  If you return false from getFormFields(),
+        * this will obviously never be reached.  If you don't want to do anything with the
+        * form, just return false here
+        * @param  $data Array
+        * @return Bool|Array true for success, false for didn't-try, array of errors on failure
+        */
+       abstract public function onSubmit( $data );
+
+       /**
+        * Do something exciting on successful processing of the form.  This might be to show
+        * a confirmation message (watch, rollback, etc) or to redirect somewhere else (edit,
+        * protect, etc).
+        */
+       abstract public function onSuccess();
+
+       /**
+        * The basic pattern for actions is to display some sort of HTMLForm UI, maybe with
+        * some stuff underneath (history etc); to do some processing on submission of that
+        * form (delete, protect, etc) and to do something exciting on 'success', be that
+        * display something new or redirect to somewhere.  Some actions have more exotic
+        * behavior, but that's what subclassing is for :D
+        */
+       public function show() {
+               $this->setHeaders();
+
+               // This will throw exceptions if there's a problem
+               $this->checkCanExecute( $this->getUser() );
+
+               $form = $this->getForm();
+               if ( $form->show() ) {
+                       $this->onSuccess();
+               }
+       }
+
+       /**
+        * @see Action::execute()
+        *
+        * @param $data array|null
+        * @param $captureErrors bool
+        * @throws ErrorPageError|Exception
+        * @return bool
+        */
+       public function execute( array $data = null, $captureErrors = true ) {
+               try {
+                       // Set a new context so output doesn't leak.
+                       $this->context = clone $this->getContext();
+
+                       // This will throw exceptions if there's a problem
+                       $this->checkCanExecute( $this->getUser() );
+
+                       $fields = array();
+                       foreach ( $this->fields as $key => $params ) {
+                               if ( isset( $data[$key] ) ) {
+                                       $fields[$key] = $data[$key];
+                               } elseif ( isset( $params['default'] ) ) {
+                                       $fields[$key] = $params['default'];
+                               } else {
+                                       $fields[$key] = null;
+                               }
+                       }
+                       $status = $this->onSubmit( $fields );
+                       if ( $status === true ) {
+                               // This might do permanent stuff
+                               $this->onSuccess();
+                               return true;
+                       } else {
+                               return false;
+                       }
+               }
+               catch ( ErrorPageError $e ) {
+                       if ( $captureErrors ) {
+                               return false;
+                       } else {
+                               throw $e;
+                       }
+               }
+       }
+}
diff --git a/includes/actions/FormlessAction.php b/includes/actions/FormlessAction.php
new file mode 100644 (file)
index 0000000..6cab4d1
--- /dev/null
@@ -0,0 +1,100 @@
+<?php
+/**
+ * Base classes for actions done on pages.
+ *
+ * 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
+ *
+ * @file
+ */
+
+/**
+ * @defgroup Actions Action done on pages
+ */
+
+/**
+ * An action which just does something, without showing a form first.
+ */
+abstract class FormlessAction extends Action {
+
+       /**
+        * Show something on GET request.
+        * @return String|null will be added to the HTMLForm if present, or just added to the
+        *     output if not.  Return null to not add anything
+        */
+       abstract public function onView();
+
+       /**
+        * We don't want an HTMLForm
+        * @return bool
+        */
+       protected function getFormFields() {
+               return false;
+       }
+
+       /**
+        * @param $data Array
+        * @return bool
+        */
+       public function onSubmit( $data ) {
+               return false;
+       }
+
+       /**
+        * @return bool
+        */
+       public function onSuccess() {
+               return false;
+       }
+
+       public function show() {
+               $this->setHeaders();
+
+               // This will throw exceptions if there's a problem
+               $this->checkCanExecute( $this->getUser() );
+
+               $this->getOutput()->addHTML( $this->onView() );
+       }
+
+       /**
+        * Execute the action silently, not giving any output.  Since these actions don't have
+        * forms, they probably won't have any data, but some (eg rollback) may do
+        * @param array $data values that would normally be in the GET request
+        * @param bool $captureErrors whether to catch exceptions and just return false
+        * @throws ErrorPageError|Exception
+        * @return Bool whether execution was successful
+        */
+       public function execute( array $data = null, $captureErrors = true ) {
+               try {
+                       // Set a new context so output doesn't leak.
+                       $this->context = clone $this->getContext();
+                       if ( is_array( $data ) ) {
+                               $this->context->setRequest( new FauxRequest( $data, false ) );
+                       }
+
+                       // This will throw exceptions if there's a problem
+                       $this->checkCanExecute( $this->getUser() );
+
+                       $this->onView();
+                       return true;
+               }
+               catch ( ErrorPageError $e ) {
+                       if ( $captureErrors ) {
+                               return false;
+                       } else {
+                               throw $e;
+                       }
+               }
+       }
+}
index f90ba98..2cdc875 100644 (file)
@@ -78,6 +78,7 @@ class ApiFeedContributions extends ApiBase {
                        'tagFilter' => $params['tagfilter'],
                        'deletedOnly' => $params['deletedonly'],
                        'topOnly' => $params['toponly'],
+                       'newOnly' => $params['newonly'],
                        'showSizeDiff' => $params['showsizediff'],
                ) );
 
@@ -186,6 +187,7 @@ class ApiFeedContributions extends ApiBase {
                        ),
                        'deletedonly' => false,
                        'toponly' => false,
+                       'newonly' => false,
                        'showsizediff' => false,
                );
        }
@@ -200,6 +202,7 @@ class ApiFeedContributions extends ApiBase {
                        'tagfilter' => 'Filter contributions that have these tags',
                        'deletedonly' => 'Show only deleted contributions',
                        'toponly' => 'Only show edits that are latest revisions',
+                       'newonly' => 'Only show edits that are page creations',
                        'showsizediff' => 'Show the size difference between revisions. Disabled in Miser Mode',
                );
        }
index 63a5502..49a02fe 100644 (file)
@@ -271,12 +271,22 @@ See the <a href='https://www.mediawiki.org/wiki/API'>complete documentation</a>,
                // encode all comments or tags as safe blue strings
                $text = str_replace( '&lt;', '<span style="color:blue;">&lt;', $text );
                $text = str_replace( '&gt;', '&gt;</span>', $text );
+
                // identify requests to api.php
-               $text = preg_replace( "#api\\.php\\?[^ <\n\t]+#", '<a href="\\0">\\0</a>', $text );
+               $text = preg_replace( '#^(\s*)(api\.php\?[^ <\n\t]+)$#m', '\1<a href="\2">\2</a>', $text );
                if ( $this->mHelp ) {
                        // make strings inside * bold
                        $text = preg_replace( "#\\*[^<>\n]+\\*#", '<b>\\0</b>', $text );
                }
+
+               // Armor links (bug 61362)
+               $masked = array();
+               $text = preg_replace_callback( '#<a .*?</a>#', function ( $matches ) use ( &$masked ) {
+                       $sha = sha1( $matches[0] );
+                       $masked[$sha] = $matches[0];
+                       return "<$sha>";
+               }, $text );
+
                // identify URLs
                $protos = wfUrlProtocolsWithoutProtRel();
                // This regex hacks around bug 13218 (&quot; included in the URL)
@@ -286,6 +296,12 @@ See the <a href='https://www.mediawiki.org/wiki/API'>complete documentation</a>,
                        $text
                );
 
+               // Unarmor links
+               $text = preg_replace_callback( '#<([0-9a-f]{40})>#', function ( $matches ) use ( &$masked ) {
+                       $sha = $matches[1];
+                       return isset( $masked[$sha] ) ? $masked[$sha] : $matches[0];
+               }, $text );
+
                /**
                 * Temporary fix for bad links in help messages. As a special case,
                 * XML-escaped metachars are de-escaped one level in the help message
index 2684f51..0939dea 100644 (file)
@@ -67,6 +67,7 @@ class ApiMain extends ApiBase {
                'purge' => 'ApiPurge',
                'setnotificationtimestamp' => 'ApiSetNotificationTimestamp',
                'rollback' => 'ApiRollback',
+               'runjobs' => 'ApiRunJobs',
                'delete' => 'ApiDelete',
                'undelete' => 'ApiUndelete',
                'protect' => 'ApiProtect',
index 6ccc288..30dd741 100644 (file)
@@ -281,8 +281,8 @@ class ApiQueryRecentChanges extends ApiQueryGeneratorBase {
                        /* Add fields to our query if they are specified as a needed parameter. */
                        $this->addFieldsIf( array( 'rc_this_oldid', 'rc_last_oldid' ), $this->fld_ids );
                        $this->addFieldsIf( 'rc_comment', $this->fld_comment || $this->fld_parsedcomment );
-                       $this->addFieldsIf( 'rc_user', $this->fld_user );
-                       $this->addFieldsIf( 'rc_user_text', $this->fld_user || $this->fld_userid );
+                       $this->addFieldsIf( 'rc_user', $this->fld_user || $this->fld_userid );
+                       $this->addFieldsIf( 'rc_user_text', $this->fld_user );
                        $this->addFieldsIf( array( 'rc_minor', 'rc_type', 'rc_bot' ), $this->fld_flags );
                        $this->addFieldsIf( array( 'rc_old_len', 'rc_new_len' ), $this->fld_sizes );
                        $this->addFieldsIf( 'rc_patrolled', $this->fld_patrolled );
index b492d9a..16108a2 100644 (file)
@@ -56,6 +56,11 @@ class ApiQueryContributions extends ApiQueryBase {
                $this->fld_patrolled = isset( $prop['patrolled'] );
                $this->fld_tags = isset( $prop['tags'] );
 
+               // Most of this code will use the 'contributions' group DB, which can map to slaves
+               // with extra user based indexes or partioning by user. The additional metadata
+               // queries should use a regular slave since the lookup pattern is not all by user.
+               $dbSecondary = $this->getDB(); // any random slave
+
                // TODO: if the query is going only against the revision table, should this be done?
                $this->selectNamedDB( 'contributions', DB_SLAVE, 'contributions' );
 
@@ -90,7 +95,7 @@ class ApiQueryContributions extends ApiQueryBase {
                                        $revIds[] = $row->rev_parent_id;
                                }
                        }
-                       $this->parentLens = Revision::getParentLengths( $this->getDB(), $revIds );
+                       $this->parentLens = Revision::getParentLengths( $dbSecondary, $revIds );
                        $res->rewind(); // reset
                }
 
@@ -207,10 +212,16 @@ class ApiQueryContributions extends ApiQueryBase {
                $this->addWhereFld( 'page_namespace', $this->params['namespace'] );
 
                $show = $this->params['show'];
+               if ( $this->params['toponly'] ) { // deprecated/old param
+                       $show[] = 'top';
+               }
                if ( !is_null( $show ) ) {
                        $show = array_flip( $show );
+
                        if ( ( isset( $show['minor'] ) && isset( $show['!minor'] ) )
                                || ( isset( $show['patrolled'] ) && isset( $show['!patrolled'] ) )
+                               || ( isset( $show['top'] ) && isset( $show['!top'] ) )
+                               || ( isset( $show['new'] ) && isset( $show['!new'] ) )
                        ) {
                                $this->dieUsageMsg( 'show' );
                        }
@@ -219,6 +230,10 @@ class ApiQueryContributions extends ApiQueryBase {
                        $this->addWhereIf( 'rev_minor_edit != 0', isset( $show['minor'] ) );
                        $this->addWhereIf( 'rc_patrolled = 0', isset( $show['!patrolled'] ) );
                        $this->addWhereIf( 'rc_patrolled != 0', isset( $show['patrolled'] ) );
+                       $this->addWhereIf( 'rev_id != page_latest', isset( $show['!top'] ) );
+                       $this->addWhereIf( 'rev_id = page_latest', isset( $show['top'] ) );
+                       $this->addWhereIf( 'rev_parent_id != 0', isset( $show['!new'] ) );
+                       $this->addWhereIf( 'rev_parent_id = 0', isset( $show['new'] ) );
                }
                $this->addOption( 'LIMIT', $this->params['limit'] + 1 );
                $index = array( 'revision' => 'usertext_timestamp' );
@@ -294,10 +309,6 @@ class ApiQueryContributions extends ApiQueryBase {
                        $this->addWhereFld( 'ct_tag', $this->params['tag'] );
                }
 
-               if ( $this->params['toponly'] ) {
-                       $this->addWhere( 'rev_id = page_latest' );
-               }
-
                $this->addOption( 'USE INDEX', $index );
        }
 
@@ -477,10 +488,17 @@ class ApiQueryContributions extends ApiQueryBase {
                                        '!minor',
                                        'patrolled',
                                        '!patrolled',
+                                       'top',
+                                       '!top',
+                                       'new',
+                                       '!new',
                                )
                        ),
                        'tag' => null,
-                       'toponly' => false,
+                       'toponly' => array(
+                               ApiBase::PARAM_DFLT => false,
+                               ApiBase::PARAM_DEPRECATED => true,
+                       ),
                );
        }
 
diff --git a/includes/api/ApiRunJobs.php b/includes/api/ApiRunJobs.php
new file mode 100644 (file)
index 0000000..e16dc5d
--- /dev/null
@@ -0,0 +1,168 @@
+<?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
+ * @author Aaron Schulz
+ */
+
+/**
+ * This is a simple class to handle action=runjobs and is only used internally
+ *
+ * @note: this does not requre "write mode" nor tokens due to the signature check
+ *
+ * @ingroup API
+ */
+class ApiRunJobs extends ApiBase {
+       public function execute() {
+               if ( wfReadOnly() ) {
+                       $this->dieUsage( 'Wiki is in read-only mode', 'read_only', 400 );
+               }
+
+               $params = $this->extractRequestParams();
+               $squery = $this->getRequest()->getValues();
+               unset( $squery['signature'] );
+               $cSig = self::getQuerySignature( $squery );
+               $rSig = $params['signature'];
+
+               // Time-insensitive signature verification
+               if ( strlen( $rSig ) !== strlen( $cSig ) ) {
+                       $verified = false;
+               } else {
+                       $result = 0;
+                       for ( $i = 0; $i < strlen( $cSig ); $i++ ) {
+                               $result |= ord( $cSig{$i} ) ^ ord( $rSig{$i} );
+                       }
+                       $verified = ( $result == 0 );
+               }
+
+               if ( !$verified || $params['sigexpiry'] < time() ) {
+                       $this->dieUsage( 'Invalid or stale signature provided', 'bad_signature', 400 );
+               }
+
+               // Client will usually disconnect before checking the response,
+               // but it needs to know when it is safe to disconnect. Until this
+               // reaches ignore_user_abort(), it is not safe as the jobs won't run.
+               ignore_user_abort( true ); // jobs may take a bit of time
+               header( "HTTP/1.0 202 Accepted" );
+               ob_flush();
+        flush();
+               // Once the client receives this response, it can disconnect
+
+               // Do all of the specified tasks...
+               if ( in_array( 'jobs', $params['tasks'] ) ) {
+                       self::executeJobs( $params['maxjobs'] );
+               }
+       }
+
+       /**
+        * @param array $query
+        * @return string
+        */
+       public static function getQuerySignature( array $query ) {
+               global $wgSecretKey;
+
+               ksort( $query ); // stable order
+               return hash_hmac( 'sha1', wfArrayToCgi( $query ), $wgSecretKey );
+       }
+
+       /**
+        * Run jobs from the job queue
+        *
+        * @note: also called from Wiki.php
+        *
+        * @param integer $maxJobs Maximum number of jobs to run
+        * @return void
+        */
+       public static function executeJobs( $maxJobs ) {
+               $n = $maxJobs; // number of jobs to run
+               if ( $n < 1 ) {
+                       return;
+               }
+               try {
+                       // Fallback to running the jobs here while the user waits
+                       $group = JobQueueGroup::singleton();
+                       do {
+                               $job = $group->pop( JobQueueGroup::USE_CACHE ); // job from any queue
+                               if ( $job ) {
+                                       $output = $job->toString() . "\n";
+                                       $t = - microtime( true );
+                                       wfProfileIn( __METHOD__ . '-' . get_class( $job ) );
+                                       $success = $job->run();
+                                       wfProfileOut( __METHOD__ . '-' . get_class( $job ) );
+                                       $group->ack( $job ); // done
+                                       $t += microtime( true );
+                                       $t = round( $t * 1000 );
+                                       if ( $success === false ) {
+                                               $output .= "Error: " . $job->getLastError() . ", Time: $t ms\n";
+                                       } else {
+                                               $output .= "Success, Time: $t ms\n";
+                                       }
+                                       wfDebugLog( 'jobqueue', $output );
+                               }
+                       } while ( --$n && $job );
+               } catch ( MWException $e ) {
+                       // We don't want exceptions thrown during job execution to
+                       // be reported to the user since the output is already sent.
+                       // Instead we just log them.
+                       MWExceptionHandler::logException( $e );
+               }
+       }
+
+       public function mustBePosted() {
+               return true;
+       }
+
+       public function getAllowedParams() {
+               return array(
+                       'tasks' => array(
+                               ApiBase::PARAM_ISMULTI => true,
+                               ApiBase::PARAM_TYPE => array( 'jobs' )
+                       ),
+                       'maxjobs' => array(
+                               ApiBase::PARAM_TYPE => 'integer',
+                               ApiBase::PARAM_DFLT => 0
+                       ),
+                       'signature' =>  array(
+                               ApiBase::PROP_TYPE => 'string',
+                       ),
+                       'sigexpiry' => array(
+                               ApiBase::PARAM_TYPE => 'integer',
+                               ApiBase::PARAM_DFLT => 0 // ~epoch
+                       ),
+               );
+       }
+
+       public function getParamDescription() {
+               return array(
+                       'tasks' => 'List of task types to perform',
+                       'maxjobs' => 'Maximum number of jobs to run',
+                       'signature' => 'HMAC Signature that signs the request',
+                       'sigexpiry' => 'HMAC signature expiry as a UNIX timestamp'
+               );
+       }
+
+       public function getDescription() {
+               return 'Perform periodic tasks or run jobs from the queue';
+       }
+
+       public function getExamples() {
+               return array(
+                       'api.php?action=runjobs&tasks=jobs&maxjobs=3' => 'Run up to 3 jobs from the queue',
+               );
+       }
+}
index 9cb1146..458f21a 100644 (file)
@@ -37,9 +37,6 @@ class OldChangesList extends ChangesList {
                # Should patrol-related stuff be shown?
                $unpatrolled = $this->showAsUnpatrolled( $rc );
 
-               $dateheader = ''; // $s now contains only <li>...</li>, for hooks' convenience.
-               $this->insertDateHeader( $dateheader, $rc->mAttribs['rc_timestamp'] );
-
                $s = '';
                $classes = array();
                // use mw-line-even/mw-line-odd class only if linenumber is given (feature from bug 14468)
@@ -128,6 +125,9 @@ class OldChangesList extends ChangesList {
 
                wfProfileOut( __METHOD__ );
 
+               $dateheader = ''; // $s now contains only <li>...</li>, for hooks' convenience.
+               $this->insertDateHeader( $dateheader, $rc->mAttribs['rc_timestamp'] );
+
                return "$dateheader<li class=\"" . implode( ' ', $classes ) . "\">" . $s . "</li>\n";
        }
 }
diff --git a/includes/composer/ComposerHookHandler.php b/includes/composer/ComposerHookHandler.php
new file mode 100644 (file)
index 0000000..5cf8a9b
--- /dev/null
@@ -0,0 +1,37 @@
+<?php
+
+use Composer\Package\Package;
+use Composer\Script\Event;
+
+$GLOBALS['IP'] = __DIR__ . '/../';
+require_once 'AutoLoader.php';
+
+/**
+ * @licence GNU GPL v2+
+ * @author Jeroen De Dauw < jeroendedauw@gmail.com >
+ */
+class ComposerHookHandler {
+
+       public static function onPreUpdate( Event $event ) {
+               self::handleChangeEvent( $event );
+       }
+
+       public static function onPreInstall( Event $event ) {
+               self::handleChangeEvent( $event );
+       }
+
+       private static function handleChangeEvent( Event $event ) {
+               $package = $event->getComposer()->getPackage();
+
+               if ( $package instanceof Package ) {
+                       $packageModifier = new ComposerPackageModifier(
+                               $package,
+                               new ComposerVersionNormalizer(),
+                               new MediaWikiVersionFetcher()
+                       );
+
+                       $packageModifier->setProvidesMediaWiki();
+               }
+       }
+
+}
diff --git a/includes/composer/ComposerPackageModifier.php b/includes/composer/ComposerPackageModifier.php
new file mode 100644 (file)
index 0000000..ae8baf2
--- /dev/null
@@ -0,0 +1,57 @@
+<?php
+
+use Composer\Package\Link;
+use Composer\Package\LinkConstraint\VersionConstraint;
+use Composer\Package\Package;
+
+/**
+ * @licence GNU GPL v2+
+ * @author Jeroen De Dauw < jeroendedauw@gmail.com >
+ */
+class ComposerPackageModifier {
+
+       const MEDIAWIKI_PACKAGE_NAME = 'mediawiki/mediawiki';
+
+       protected $package;
+       protected $versionNormalizer;
+       protected $versionFetcher;
+
+       public function __construct( Package $package, ComposerVersionNormalizer $versionNormalizer, MediaWikiVersionFetcher $versionFetcher ) {
+               $this->package = $package;
+               $this->versionNormalizer = $versionNormalizer;
+               $this->versionFetcher = $versionFetcher;
+       }
+
+       public function setProvidesMediaWiki() {
+               $this->setLinkAsProvides( $this->newMediaWikiLink() );
+       }
+
+       private function setLinkAsProvides( Link $link ) {
+               $this->package->setProvides( array( $link ) );
+       }
+
+       private function newMediaWikiLink() {
+               $version = $this->getMediaWikiVersionConstraint();
+
+               $link = new Link(
+                       '__root__',
+                       self::MEDIAWIKI_PACKAGE_NAME,
+                       $version,
+                       'provides',
+                       $version->getPrettyString()
+               );
+
+               return $link;
+       }
+
+       private function getMediaWikiVersionConstraint() {
+               $mvVersion = $this->versionFetcher->fetchVersion();
+               $mvVersion = $this->versionNormalizer->normalizeSuffix( $mvVersion );
+
+               $version = new VersionConstraint( '==', $this->versionNormalizer->normalizeLevelCount( $mvVersion ) );
+               $version->setPrettyString( $mvVersion );
+
+               return $version;
+       }
+
+}
diff --git a/includes/composer/ComposerVersionNormalizer.php b/includes/composer/ComposerVersionNormalizer.php
new file mode 100644 (file)
index 0000000..727e142
--- /dev/null
@@ -0,0 +1,67 @@
+<?php
+
+/**
+ * @licence GNU GPL v2+
+ * @author Jeroen De Dauw < jeroendedauw@gmail.com >
+ */
+class ComposerVersionNormalizer {
+
+       /**
+        * Ensures there is a dash in between the version and the stability suffix.
+        *
+        * Examples:
+        * - 1.23RC => 1.23-RC
+        * - 1.23alpha => 1.23-alpha
+        * - 1.23alpha3 => 1.23-alpha3
+        * - 1.23-beta => 1.23-beta
+        *
+        * @param string $version
+        *
+        * @return string
+        * @throws InvalidArgumentException
+        */
+       public function normalizeSuffix( $version ) {
+               if ( !is_string( $version ) ) {
+                       throw new InvalidArgumentException( '$version must be a string' );
+               }
+
+               return preg_replace( '/^(\d[\d\.]*)([a-zA-Z]+)(\d*)$/', '$1-$2$3', $version, 1 );
+       }
+
+       /**
+        * Ensures the version has four levels.
+        * Version suffixes are supported, as long as they start with a dash.
+        *
+        * Examples:
+        * - 1.19 => 1.19.0.0
+        * - 1.19.2.3 => 1.19.2.3
+        * - 1.19-alpha => 1.19.0.0-alpha
+        * - 1337 => 1337.0.0.0
+        *
+        * @param string $version
+        *
+        * @return string
+        * @throws InvalidArgumentException
+        */
+       public function normalizeLevelCount( $version ) {
+               if ( !is_string( $version ) ) {
+                       throw new InvalidArgumentException( '$version must be a string' );
+               }
+
+               $dashPosition = strpos( $version, '-' );
+
+               if ( $dashPosition !== false ) {
+                       $suffix = substr( $version, $dashPosition );
+                       $version = substr( $version, 0, $dashPosition );
+               }
+
+               $version = implode( '.', array_pad( explode( '.', $version ), 4, '0' ) );
+
+               if ( $dashPosition !== false ) {
+                       $version .= $suffix;
+               }
+
+               return $version;
+       }
+
+}
\ No newline at end of file
index e1b1f01..f2f0c9d 100644 (file)
@@ -43,7 +43,7 @@ abstract class AbstractContent implements Content {
        protected $model_id;
 
        /**
-        * @param string|null $modelId
+        * @param string $modelId
         *
         * @since 1.21
         */
@@ -52,23 +52,21 @@ abstract class AbstractContent implements Content {
        }
 
        /**
-        * @see Content::getModel
-        *
         * @since 1.21
+        *
+        * @see Content::getModel
         */
        public function getModel() {
                return $this->model_id;
        }
 
        /**
-        * Throws an MWException if $model_id is not the id of the content model
-        * supported by this Content object.
-        *
         * @since 1.21
         *
         * @param string $modelId The model to check
         *
-        * @throws MWException
+        * @throws MWException If the provided ID is not the ID of the content model supported by this
+        * Content object.
         */
        protected function checkModelID( $modelId ) {
                if ( $modelId !== $this->model_id ) {
@@ -81,40 +79,40 @@ abstract class AbstractContent implements Content {
        }
 
        /**
-        * @see Content::getContentHandler
-        *
         * @since 1.21
+        *
+        * @see Content::getContentHandler
         */
        public function getContentHandler() {
                return ContentHandler::getForContent( $this );
        }
 
        /**
-        * @see Content::getDefaultFormat
-        *
         * @since 1.21
+        *
+        * @see Content::getDefaultFormat
         */
        public function getDefaultFormat() {
                return $this->getContentHandler()->getDefaultFormat();
        }
 
        /**
-        * @see Content::getSupportedFormats
-        *
         * @since 1.21
+        *
+        * @see Content::getSupportedFormats
         */
        public function getSupportedFormats() {
                return $this->getContentHandler()->getSupportedFormats();
        }
 
        /**
-        * @see Content::isSupportedFormat
+        * @since 1.21
         *
         * @param string $format
         *
-        * @since 1.21
+        * @return bool
         *
-        * @return boolean
+        * @see Content::isSupportedFormat
         */
        public function isSupportedFormat( $format ) {
                if ( !$format ) {
@@ -125,13 +123,11 @@ abstract class AbstractContent implements Content {
        }
 
        /**
-        * Throws an MWException if $this->isSupportedFormat( $format ) does not
-        * return true.
-        *
         * @since 1.21
         *
-        * @param string $format
-        * @throws MWException
+        * @param string $format The serialization format to check.
+        *
+        * @throws MWException If the format is not supported by this content handler.
         */
        protected function checkFormat( $format ) {
                if ( !$this->isSupportedFormat( $format ) ) {
@@ -143,48 +139,50 @@ abstract class AbstractContent implements Content {
        }
 
        /**
-        * @see Content::serialize
-        *
-        * @param string|null $format
-        *
         * @since 1.21
         *
+        * @param string $format
+        *
         * @return string
+        *
+        * @see Content::serialize
         */
        public function serialize( $format = null ) {
                return $this->getContentHandler()->serializeContent( $this, $format );
        }
 
        /**
-        * @see Content::isEmpty
-        *
         * @since 1.21
         *
-        * @return boolean
+        * @return bool
+        *
+        * @see Content::isEmpty
         */
        public function isEmpty() {
                return $this->getSize() === 0;
        }
 
        /**
-        * @see Content::isValid
+        * Subclasses may override this to implement (light weight) validation.
         *
         * @since 1.21
         *
-        * @return boolean
+        * @return bool Always true.
+        *
+        * @see Content::isValid
         */
        public function isValid() {
                return true;
        }
 
        /**
-        * @see Content::equals
-        *
         * @since 1.21
         *
-        * @param Content|null $that
+        * @param Content $that
         *
-        * @return boolean
+        * @return bool
+        *
+        * @see Content::equals
         */
        public function equals( Content $that = null ) {
                if ( is_null( $that ) ) {
@@ -214,26 +212,19 @@ abstract class AbstractContent implements Content {
         * Subclasses may override this to determine the secondary data updates more
         * efficiently, preferably without the need to generate a parser output object.
         *
-        * @see Content::getSecondaryDataUpdates()
+        * @since 1.21
         *
-        * @param $title Title The context for determining the necessary updates
-        * @param $old Content|null An optional Content object representing the
-        *    previous content, i.e. the content being replaced by this Content
-        *    object.
-        * @param $recursive boolean Whether to include recursive updates (default:
-        *    false).
-        * @param $parserOutput ParserOutput|null Optional ParserOutput object.
-        *    Provide if you have one handy, to avoid re-parsing of the content.
+        * @param Title $title
+        * @param Content $old
+        * @param bool $recursive
+        * @param ParserOutput $parserOutput
         *
-        * @return Array. A list of DataUpdate objects for putting information
-        *    about this content object somewhere.
+        * @return DataUpdate[]
         *
-        * @since 1.21
+        * @see Content::getSecondaryDataUpdates()
         */
-       public function getSecondaryDataUpdates( Title $title,
-               Content $old = null,
-               $recursive = true, ParserOutput $parserOutput = null
-       ) {
+       public function getSecondaryDataUpdates( Title $title, Content $old = null,
+               $recursive = true, ParserOutput $parserOutput = null ) {
                if ( $parserOutput === null ) {
                        $parserOutput = $this->getParserOutput( $title, null, null, false );
                }
@@ -242,9 +233,11 @@ abstract class AbstractContent implements Content {
        }
 
        /**
-        * @see Content::getRedirectChain
-        *
         * @since 1.21
+        *
+        * @return Title[]|null
+        *
+        * @see Content::getRedirectChain
         */
        public function getRedirectChain() {
                global $wgMaxRedirects;
@@ -277,19 +270,26 @@ abstract class AbstractContent implements Content {
        }
 
        /**
-        * @see Content::getRedirectTarget
+        * Subclasses that implement redirects should override this.
         *
         * @since 1.21
+        *
+        * @return null
+        *
+        * @see Content::getRedirectTarget
         */
        public function getRedirectTarget() {
                return null;
        }
 
        /**
-        * @see Content::getUltimateRedirectTarget
-        * @note: migrated here from Title::newFromRedirectRecurse
+        * @note Migrated here from Title::newFromRedirectRecurse.
         *
         * @since 1.21
+        *
+        * @return Title|null
+        *
+        * @see Content::getUltimateRedirectTarget
         */
        public function getUltimateRedirectTarget() {
                $titles = $this->getRedirectChain();
@@ -298,80 +298,93 @@ abstract class AbstractContent implements Content {
        }
 
        /**
-        * @see Content::isRedirect
-        *
         * @since 1.21
         *
         * @return bool
+        *
+        * @see Content::isRedirect
         */
        public function isRedirect() {
                return $this->getRedirectTarget() !== null;
        }
 
        /**
-        * @see Content::updateRedirect
-        *
         * This default implementation always returns $this.
-        *
-        * @param Title $target
+        * Subclasses that implement redirects should override this.
         *
         * @since 1.21
         *
+        * @param Title $target
+        *
         * @return Content $this
+        *
+        * @see Content::updateRedirect
         */
        public function updateRedirect( Title $target ) {
                return $this;
        }
 
        /**
-        * @see Content::getSection
-        *
         * @since 1.21
+        *
+        * @return null
+        *
+        * @see Content::getSection
         */
        public function getSection( $sectionId ) {
                return null;
        }
 
        /**
-        * @see Content::replaceSection
-        *
         * @since 1.21
+        *
+        * @return null
+        *
+        * @see Content::replaceSection
         */
        public function replaceSection( $section, Content $with, $sectionTitle = '' ) {
                return null;
        }
 
        /**
-        * @see Content::preSaveTransform
-        *
         * @since 1.21
+        *
+        * @return Content $this
+        *
+        * @see Content::preSaveTransform
         */
        public function preSaveTransform( Title $title, User $user, ParserOptions $popts ) {
                return $this;
        }
 
        /**
-        * @see Content::addSectionHeader
-        *
         * @since 1.21
+        *
+        * @return Content $this
+        *
+        * @see Content::addSectionHeader
         */
        public function addSectionHeader( $header ) {
                return $this;
        }
 
        /**
-        * @see Content::preloadTransform
-        *
         * @since 1.21
+        *
+        * @return Content $this
+        *
+        * @see Content::preloadTransform
         */
        public function preloadTransform( Title $title, ParserOptions $popts ) {
                return $this;
        }
 
        /**
-        * @see Content::prepareSave
-        *
         * @since 1.21
+        *
+        * @return Status
+        *
+        * @see Content::prepareSave
         */
        public function prepareSave( WikiPage $page, $flags, $baseRevId, User $user ) {
                if ( $this->isValid() ) {
@@ -382,21 +395,16 @@ abstract class AbstractContent implements Content {
        }
 
        /**
-        * @see Content::getDeletionUpdates
-        *
         * @since 1.21
         *
-        * @param $page WikiPage the deleted page
-        * @param $parserOutput null|ParserOutput optional parser output object
-        *    for efficient access to meta-information about the content object.
-        *    Provide if you have one handy.
+        * @param WikiPage $page
+        * @param ParserOutput $parserOutput
         *
-        * @return array A list of DataUpdate instances that will clean up the
-        *    database after deletion.
+        * @return LinksDeletionUpdate[]
+        *
+        * @see Content::getDeletionUpdates
         */
-       public function getDeletionUpdates( WikiPage $page,
-               ParserOutput $parserOutput = null
-       ) {
+       public function getDeletionUpdates( WikiPage $page, ParserOutput $parserOutput = null ) {
                return array(
                        new LinksDeletionUpdate( $page ),
                );
@@ -406,30 +414,28 @@ abstract class AbstractContent implements Content {
         * This default implementation always returns false. Subclasses may override
         * this to supply matching logic.
         *
-        * @see Content::matchMagicWord
-        *
         * @since 1.21
         *
         * @param MagicWord $word
         *
-        * @return bool
+        * @return bool Always false.
+        *
+        * @see Content::matchMagicWord
         */
        public function matchMagicWord( MagicWord $word ) {
                return false;
        }
 
        /**
-        * @see Content::convert()
-        *
         * This base implementation calls the hook ConvertContent to enable custom conversions.
         * Subclasses may override this to implement conversion for "their" content model.
         *
-        * @param string $toModel the desired content model, use the CONTENT_MODEL_XXX flags.
-        * @param string $lossy flag, set to "lossy" to allow lossy conversion. If lossy conversion is
-        * not allowed, full round-trip conversion is expected to work without losing information.
+        * @param string $toModel
+        * @param string $lossy
+        *
+        * @return Content|bool
         *
-        * @return Content|bool A content object with the content model $toModel, or false if
-        * that conversion is not supported.
+        * @see Content::convert()
         */
        public function convert( $toModel, $lossy = '' ) {
                if ( $this->getModel() === $toModel ) {
index 947e348..075635d 100644 (file)
@@ -32,6 +32,7 @@
  * @ingroup Content
  */
 interface Content {
+
        /**
         * @since 1.21
         *
@@ -64,8 +65,9 @@ interface Content {
         *
         * @since 1.21
         *
-        * @param int $maxLength Maximum length of the summary text
-        * @return string The summary text
+        * @param int $maxLength Maximum length of the summary text.
+        *
+        * @return string The summary text.
         */
        public function getTextForSummary( $maxLength = 250 );
 
@@ -132,7 +134,7 @@ interface Content {
         *
         * @since 1.21
         *
-        * @return Array of supported serialization formats
+        * @return string[] List of supported serialization formats
         */
        public function getSupportedFormats();
 
@@ -147,7 +149,8 @@ interface Content {
         *
         * @since 1.21
         *
-        * @param string $format The format to check
+        * @param string $format The serialization format to check.
+        *
         * @return bool Whether the format is supported
         */
        public function isSupportedFormat( $format );
@@ -159,9 +162,9 @@ interface Content {
         *
         * @since 1.21
         *
-        * @param $format null|string The desired serialization format (or null for
-        *    the default format).
-        * @return string Serialized form of this Content object
+        * @param string $format The desired serialization format, or null for the default format.
+        *
+        * @return string Serialized form of this Content object.
         */
        public function serialize( $format = null );
 
@@ -184,7 +187,7 @@ interface Content {
         *
         * @since 1.21
         *
-        * @return boolean
+        * @return bool
         */
        public function isValid();
 
@@ -207,7 +210,8 @@ interface Content {
         *
         * @since 1.21
         *
-        * @param $that Content The Content object to compare to
+        * @param Content $that The Content object to compare to.
+        *
         * @return bool True if this Content object is equal to $that, false otherwise.
         */
        public function equals( Content $that = null );
@@ -242,7 +246,8 @@ interface Content {
         * @param bool $hasLinks If it is known whether this content contains
         *    links, provide this information here, to avoid redundant parsing to
         *    find out.
-        * @return boolean
+        *
+        * @return bool
         */
        public function isCountable( $hasLinks = null );
 
@@ -256,10 +261,10 @@ interface Content {
         *       generated parser output, implementations of this method
         *       may call ParserOutput::recordOption() on the output object.
         *
-        * @param $title Title The page title to use as a context for rendering
-        * @param $revId null|int The revision being rendered (optional)
-        * @param $options null|ParserOptions Any parser options
-        * @param $generateHtml Boolean Whether to generate HTML (default: true). If false,
+        * @param Title $title The page title to use as a context for rendering.
+        * @param int $revId Optional revision ID being rendered.
+        * @param ParserOptions $options Any parser options.
+        * @param bool $generateHtml Whether to generate HTML (default: true). If false,
         *        the result of calling getText() on the ParserOutput object returned by
         *        this method is undefined.
         *
@@ -267,8 +272,7 @@ interface Content {
         *
         * @return ParserOutput
         */
-       public function getParserOutput( Title $title,
-               $revId = null,
+       public function getParserOutput( Title $title, $revId = null,
                ParserOptions $options = null, $generateHtml = true );
 
        // TODO: make RenderOutput and RenderOptions base classes
@@ -288,24 +292,22 @@ interface Content {
         * Subclasses may implement this to determine the necessary updates more
         * efficiently, or make use of information about the old content.
         *
-        * @param $title Title The context for determining the necessary updates
-        * @param $old Content|null An optional Content object representing the
+        * @param Title $title The context for determining the necessary updates
+        * @param Content $old An optional Content object representing the
         *    previous content, i.e. the content being replaced by this Content
         *    object.
-        * @param $recursive boolean Whether to include recursive updates (default:
+        * @param bool $recursive Whether to include recursive updates (default:
         *    false).
-        * @param $parserOutput ParserOutput|null Optional ParserOutput object.
+        * @param ParserOutput $parserOutput Optional ParserOutput object.
         *    Provide if you have one handy, to avoid re-parsing of the content.
         *
-        * @return Array. A list of DataUpdate objects for putting information
+        * @return DataUpdate[] A list of DataUpdate objects for putting information
         *    about this content object somewhere.
         *
         * @since 1.21
         */
-       public function getSecondaryDataUpdates( Title $title,
-               Content $old = null,
-               $recursive = true, ParserOutput $parserOutput = null
-       );
+       public function getSecondaryDataUpdates( Title $title, Content $old = null,
+               $recursive = true, ParserOutput $parserOutput = null );
 
        /**
         * Construct the redirect destination from this content and return an
@@ -315,7 +317,7 @@ interface Content {
         *
         * @since 1.21
         *
-        * @return Array of Titles, with the destination last
+        * @return Title[]|null List of Titles, with the destination last.
         */
        public function getRedirectChain();
 
@@ -327,7 +329,7 @@ interface Content {
         *
         * @since 1.21
         *
-        * @return Title: The corresponding Title
+        * @return Title|null The corresponding Title.
         */
        public function getRedirectTarget();
 
@@ -344,7 +346,7 @@ interface Content {
         *
         * @since 1.21
         *
-        * @return Title
+        * @return Title|null
         */
        public function getUltimateRedirectTarget();
 
@@ -364,9 +366,9 @@ interface Content {
         *
         * @since 1.21
         *
-        * @param Title $target the new redirect target
+        * @param Title $target The new redirect target
         *
-        * @return Content a new Content object with the updated redirect (or $this
+        * @return Content A new Content object with the updated redirect (or $this
         *   if this Content object isn't a redirect)
         */
        public function updateRedirect( Title $target );
@@ -380,7 +382,8 @@ interface Content {
         *    The ID "0" retrieves the section before the first heading, "1" the
         *    text between the first heading (included) and the second heading
         *    (excluded), etc.
-        * @return Content|Boolean|null The section, or false if no such section
+        *
+        * @return Content|bool|null The section, or false if no such section
         *    exist, or null if sections are not supported.
         */
        public function getSection( $sectionId );
@@ -391,10 +394,11 @@ interface Content {
         *
         * @since 1.21
         *
-        * @param $section null/false or a section number (0, 1, 2, T1, T2...), or "new"
-        * @param $with Content: new content of the section
-        * @param string $sectionTitle new section's subject, only if $section is 'new'
-        * @return string Complete article text, or null if error
+        * @param mixed $section Null/false or a section number (0, 1, 2, T1, T2...), or "new"
+        * @param Content $with New content of the section
+        * @param string $sectionTitle New section's subject, only if $section is 'new'
+        *
+        * @return string|null Complete article text, or null if error
         */
        public function replaceSection( $section, Content $with, $sectionTitle = '' );
 
@@ -404,9 +408,10 @@ interface Content {
         *
         * @since 1.21
         *
-        * @param $title Title
-        * @param $user User
-        * @param $parserOptions null|ParserOptions
+        * @param Title $title
+        * @param User $user
+        * @param ParserOptions $parserOptions
+        *
         * @return Content
         */
        public function preSaveTransform( Title $title, User $user, ParserOptions $parserOptions );
@@ -418,7 +423,8 @@ interface Content {
         *
         * @since 1.21
         *
-        * @param $header string
+        * @param string $header
+        *
         * @return Content
         */
        public function addSectionHeader( $header );
@@ -429,8 +435,9 @@ interface Content {
         *
         * @since 1.21
         *
-        * @param $title Title
-        * @param $parserOptions null|ParserOptions
+        * @param Title $title
+        * @param ParserOptions $parserOptions
+        *
         * @return Content
         */
        public function preloadTransform( Title $title, ParserOptions $parserOptions );
@@ -451,15 +458,15 @@ interface Content {
         * @since 1.21
         *
         * @param WikiPage $page The page to be saved.
-        * @param int $flags bitfield for use with EDIT_XXX constants, see WikiPage::doEditContent()
-        * @param int $baseRevId the ID of the current revision
+        * @param int $flags Bitfield for use with EDIT_XXX constants, see WikiPage::doEditContent()
+        * @param int $baseRevId The ID of the current revision
         * @param User $user
         *
         * @return Status A status object indicating whether the content was
         *   successfully prepared for saving. If the returned status indicates
         *   an error, a rollback will be performed and the transaction aborted.
         *
-        * @see see WikiPage::doEditContent()
+        * @see WikiPage::doEditContent()
         */
        public function prepareSave( WikiPage $page, $flags, $baseRevId, User $user );
 
@@ -470,12 +477,12 @@ interface Content {
         *
         * @since 1.21
         *
-        * @param $page WikiPage the deleted page
-        * @param $parserOutput null|ParserOutput optional parser output object
+        * @param WikiPage $page The deleted page
+        * @param ParserOutput $parserOutput Optional parser output object
         *    for efficient access to meta-information about the content object.
         *    Provide if you have one handy.
         *
-        * @return array A list of DataUpdate instances that will clean up the
+        * @return DataUpdate[] A list of DataUpdate instances that will clean up the
         *    database after deletion.
         */
        public function getDeletionUpdates( WikiPage $page,
@@ -486,9 +493,9 @@ interface Content {
         *
         * @since 1.21
         *
-        * @param MagicWord $word the magic word to match
+        * @param MagicWord $word The magic word to match
         *
-        * @return bool whether this Content object matches the given magic word.
+        * @return bool Whether this Content object matches the given magic word.
         */
        public function matchMagicWord( MagicWord $word );
 
@@ -496,9 +503,10 @@ interface Content {
         * Converts this content object into another content object with the given content model,
         * if that is possible.
         *
-        * @param string $toModel the desired content model, use the CONTENT_MODEL_XXX flags.
-        * @param string $lossy flag, set to "lossy" to allow lossy conversion. If lossy conversion is
-        * not allowed, full round-trip conversion is expected to work without losing information.
+        * @param string $toModel The desired content model, use the CONTENT_MODEL_XXX flags.
+        * @param string $lossy Optional flag, set to "lossy" to allow lossy conversion. If lossy
+        * conversion is not allowed, full round-trip conversion is expected to work without losing
+        * information.
         *
         * @return Content|bool A content object with the content model $toModel, or false if
         * that conversion is not supported.
@@ -509,4 +517,5 @@ interface Content {
        //   [11:59] <vvv> Hooks are ugly; make CodeHighlighter interface and a
        //   config to set the class which handles syntax highlighting
        //   [12:00] <vvv> And default it to a DummyHighlighter
+
 }
index 7c51345..defa7da 100644 (file)
@@ -85,10 +85,11 @@ abstract class ContentHandler {
         *
         * @since 1.21
         *
-        * @param $content Content|null
-        * @return null|string the textual form of $content, if available
-        * @throws MWException if $content is not an instance of TextContent and
-        *   $wgContentHandlerTextFallback was set to 'fail'.
+        * @param Content $content
+        *
+        * @throws MWException If the content is not an instance of TextContent and
+        * wgContentHandlerTextFallback was set to 'fail'.
+        * @return string|null Textual form of the content, if available.
         */
        public static function getContentText( Content $content = null ) {
                global $wgContentHandlerTextFallback;
@@ -127,24 +128,21 @@ abstract class ContentHandler {
         *
         * @since 1.21
         *
-        * @param string $text the textual representation, will be
+        * @param string $text The textual representation, will be
         *    unserialized to create the Content object
-        * @param $title null|Title the title of the page this text belongs to.
+        * @param Title $title The title of the page this text belongs to.
         *    Required if $modelId is not provided.
-        * @param $modelId null|string the model to deserialize to. If not provided,
+        * @param string $modelId The model to deserialize to. If not provided,
         *    $title->getContentModel() is used.
-        * @param $format null|string the format to use for deserialization. If not
+        * @param string $format The format to use for deserialization. If not
         *    given, the model's default format is used.
         *
-        * @throws MWException
-        * @return Content a Content object representing $text
-        *
-        * @throws MWException if $model or $format is not supported or if $text can
-        *    not be unserialized using $format.
+        * @throws MWException If model ID or format is not supported or if the text can not be
+        * unserialized using the format.
+        * @return Content A Content object representing the text.
         */
        public static function makeContent( $text, Title $title = null,
-               $modelId = null, $format = null
-       ) {
+               $modelId = null, $format = null ) {
                if ( is_null( $modelId ) ) {
                        if ( is_null( $title ) ) {
                                throw new MWException( "Must provide a Title object or a content model ID." );
@@ -188,8 +186,9 @@ abstract class ContentHandler {
         *
         * @since 1.21
         *
-        * @param $title Title
-        * @return null|string default model name for the page given by $title
+        * @param Title $title
+        *
+        * @return string Default model name for the page given by $title
         */
        public static function getDefaultModelFor( Title $title ) {
                // NOTE: this method must not rely on $title->getContentModel() directly or indirectly,
@@ -253,7 +252,8 @@ abstract class ContentHandler {
         *
         * @since 1.21
         *
-        * @param $title Title
+        * @param Title $title
+        *
         * @return ContentHandler
         */
        public static function getForTitle( Title $title ) {
@@ -268,7 +268,8 @@ abstract class ContentHandler {
         *
         * @since 1.21
         *
-        * @param $content Content
+        * @param Content $content
+        *
         * @return ContentHandler
         */
        public static function getForContent( Content $content ) {
@@ -303,9 +304,9 @@ abstract class ContentHandler {
         *
         * @param string $modelId The ID of the content model for which to get a
         *    handler. Use CONTENT_MODEL_XXX constants.
-        * @return ContentHandler The ContentHandler singleton for handling the
-        *    model given by $modelId
-        * @throws MWException if no handler is known for $modelId.
+        *
+        * @throws MWException If no handler is known for the model ID.
+        * @return ContentHandler The ContentHandler singleton for handling the model given by the ID.
         */
        public static function getForModelID( $modelId ) {
                global $wgContentHandlers;
@@ -353,8 +354,8 @@ abstract class ContentHandler {
         * @param string $name The content model ID, as given by a CONTENT_MODEL_XXX
         *    constant or returned by Revision::getContentModel().
         *
+        * @throws MWException If the model ID isn't known.
         * @return string The content model's localized name.
-        * @throws MWException if the model id isn't known.
         */
        public static function getLocalizedName( $name ) {
                // Messages: content-model-wikitext, content-model-text,
@@ -389,7 +390,14 @@ abstract class ContentHandler {
 
        // ------------------------------------------------------------------------
 
+       /**
+        * @var string
+        */
        protected $mModelID;
+
+       /**
+        * @var string[]
+        */
        protected $mSupportedFormats;
 
        /**
@@ -398,7 +406,7 @@ abstract class ContentHandler {
         * provided as literals by subclass's constructors.
         *
         * @param string $modelId (use CONTENT_MODEL_XXX constants).
-        * @param array $formats List for supported serialization formats
+        * @param string[] $formats List for supported serialization formats
         *    (typically as MIME types)
         */
        public function __construct( $modelId, $formats ) {
@@ -415,8 +423,9 @@ abstract class ContentHandler {
         *
         * @since 1.21
         *
-        * @param $content Content The Content object to serialize
-        * @param $format null|String The desired serialization format
+        * @param Content $content The Content object to serialize
+        * @param string $format The desired serialization format
+        *
         * @return string Serialized form of the content
         */
        abstract public function serializeContent( Content $content, $format = null );
@@ -426,9 +435,10 @@ abstract class ContentHandler {
         *
         * @since 1.21
         *
-        * @param string $blob serialized form of the content
-        * @param $format null|String the format used for serialization
-        * @return Content the Content object created by deserializing $blob
+        * @param string $blob Serialized form of the content
+        * @param string $format The format used for serialization
+        *
+        * @return Content The Content object created by deserializing $blob
         */
        abstract public function unserializeContent( $blob, $format = null );
 
@@ -454,10 +464,10 @@ abstract class ContentHandler {
         *
         * @since 1.21
         *
-        * @param Title $destination the page to redirect to.
-        * @param string $text text to include in the redirect, if possible.
+        * @param Title $destination The page to redirect to.
+        * @param string $text Text to include in the redirect, if possible.
         *
-        * @return Content
+        * @return Content Always null.
         */
        public function makeRedirectContent( Title $destination, $text = '' ) {
                return null;
@@ -469,21 +479,19 @@ abstract class ContentHandler {
         *
         * @since 1.21
         *
-        * @return String The model ID
+        * @return string The model ID
         */
        public function getModelID() {
                return $this->mModelID;
        }
 
        /**
-        * Throws an MWException if $model_id is not the ID of the content model
-        * supported by this ContentHandler.
-        *
         * @since 1.21
         *
         * @param string $model_id The model to check
         *
-        * @throws MWException
+        * @throws MWException If the model ID is not the ID of the content model supported by this
+        * ContentHandler.
         */
        protected function checkModelID( $model_id ) {
                if ( $model_id !== $this->mModelID ) {
@@ -500,7 +508,7 @@ abstract class ContentHandler {
         *
         * @since 1.21
         *
-        * @return array of serialization formats as MIME type like strings
+        * @return string[] List of serialization formats as MIME type like strings
         */
        public function getSupportedFormats() {
                return $this->mSupportedFormats;
@@ -515,7 +523,7 @@ abstract class ContentHandler {
         *
         * @since 1.21
         *
-        * @return string the name of the default serialization format as a MIME type
+        * @return string The name of the default serialization format as a MIME type
         */
        public function getDefaultFormat() {
                return $this->mSupportedFormats[0];
@@ -530,11 +538,11 @@ abstract class ContentHandler {
         *
         * @since 1.21
         *
-        * @param string $format the serialization format to check
+        * @param string $format The serialization format to check
+        *
         * @return bool
         */
        public function isSupportedFormat( $format ) {
-
                if ( !$format ) {
                        return true; // this means "use the default"
                }
@@ -543,13 +551,11 @@ abstract class ContentHandler {
        }
 
        /**
-        * Throws an MWException if isSupportedFormat( $format ) is not true.
-        * Convenient for checking whether a format provided as a parameter is
-        * actually supported.
+        * Convenient for checking whether a format provided as a parameter is actually supported.
         *
-        * @param string $format the serialization format to check
+        * @param string $format The serialization format to check
         *
-        * @throws MWException
+        * @throws MWException If the format is not supported by this content handler.
         */
        protected function checkFormat( $format ) {
                if ( !$this->isSupportedFormat( $format ) ) {
@@ -568,7 +574,7 @@ abstract class ContentHandler {
         *
         * @since 1.21
         *
-        * @return Array
+        * @return array Always an empty array.
         */
        public function getActionOverrides() {
                return array();
@@ -579,21 +585,18 @@ abstract class ContentHandler {
         *
         * @since 1.21
         *
-        * @param $context IContextSource context to use, anything else will be
-        *    ignored
-        * @param $old Integer Old ID we want to show and diff with.
-        * @param int|string $new String either 'prev' or 'next'.
-        * @param $rcid Integer ??? FIXME (default 0)
-        * @param $refreshCache boolean If set, refreshes the diff cache
-        * @param $unhide boolean If set, allow viewing deleted revs
+        * @param IContextSource $context Context to use, anything else will be ignored.
+        * @param int $old Revision ID we want to show and diff with.
+        * @param int|string $new Either a revision ID or one of the strings 'cur', 'prev' or 'next'.
+        * @param int $rcid FIXME: Deprecated, no longer used. Defaults to 0.
+        * @param bool $refreshCache If set, refreshes the diff cache. Defaults to false.
+        * @param bool $unhide If set, allow viewing deleted revs. Defaults to false.
         *
         * @return DifferenceEngine
         */
-       public function createDifferenceEngine( IContextSource $context,
-               $old = 0, $new = 0,
-               $rcid = 0, # FIXME: use everywhere!
-               $refreshCache = false, $unhide = false
-       ) {
+       public function createDifferenceEngine( IContextSource $context, $old = 0, $new = 0,
+               $rcid = 0, //FIXME: Deprecated, no longer used
+               $refreshCache = false, $unhide = false ) {
                $diffEngineClass = $this->getDiffEngineClass();
 
                return new $diffEngineClass( $context, $old, $new, $rcid, $refreshCache, $unhide );
@@ -613,10 +616,10 @@ abstract class ContentHandler {
         *
         * @since 1.21
         *
-        * @param Title $title the page to determine the language for.
-        * @param Content|null $content the page's content, if you have it handy, to avoid reloading it.
+        * @param Title $title The page to determine the language for.
+        * @param Content $content The page's content, if you have it handy, to avoid reloading it.
         *
-        * @return Language the page's language
+        * @return Language The page's language
         */
        public function getPageLanguage( Title $title, Content $content = null ) {
                global $wgContLang, $wgLang;
@@ -648,10 +651,10 @@ abstract class ContentHandler {
         *
         * @since 1.21
         *
-        * @param Title $title the page to determine the language for.
-        * @param Content|null $content the page's content, if you have it handy, to avoid reloading it.
+        * @param Title $title The page to determine the language for.
+        * @param Content $content The page's content, if you have it handy, to avoid reloading it.
         *
-        * @return Language the page's language for viewing
+        * @return Language The page's language for viewing
         */
        public function getPageViewLanguage( Title $title, Content $content = null ) {
                $pageLang = $this->getPageLanguage( $title, $content );
@@ -680,9 +683,9 @@ abstract class ContentHandler {
         * @note: this calls the ContentHandlerCanBeUsedOn hook which may be used to override which
         * content model can be used where.
         *
-        * @param Title $title the page's title.
+        * @param Title $title The page's title.
         *
-        * @return bool true if content of this kind can be used on the given page, false otherwise.
+        * @return bool True if content of this kind can be used on the given page, false otherwise.
         */
        public function canBeUsedOn( Title $title ) {
                $ok = true;
@@ -704,19 +707,18 @@ abstract class ContentHandler {
        }
 
        /**
-        * Attempts to merge differences between three versions.
-        * Returns a new Content object for a clean merge and false for failure or
-        * a conflict.
+        * Attempts to merge differences between three versions. Returns a new
+        * Content object for a clean merge and false for failure or a conflict.
         *
         * This default implementation always returns false.
         *
         * @since 1.21
         *
-        * @param $oldContent Content|string  String
-        * @param $myContent Content|string   String
-        * @param $yourContent Content|string String
+        * @param Content|string $oldContent The page's previous content.
+        * @param Content|string $myContent One of the page's conflicting contents.
+        * @param Content|string $yourContent One of the page's conflicting contents.
         *
-        * @return Content|Bool
+        * @return Content|bool Always false.
         */
        public function merge3( Content $oldContent, Content $myContent, Content $yourContent ) {
                return false;
@@ -727,13 +729,14 @@ abstract class ContentHandler {
         *
         * @since 1.21
         *
-        * @param $oldContent Content|null: the previous text of the page.
-        * @param $newContent Content|null: The submitted text of the page.
+        * @param Content $oldContent The previous text of the page.
+        * @param Content $newContent The submitted text of the page.
         * @param int $flags Bit mask: a bit mask of flags submitted for the edit.
         *
         * @return string An appropriate auto-summary, or an empty string.
         */
-       public function getAutosummary( Content $oldContent = null, Content $newContent = null, $flags ) {
+       public function getAutosummary( Content $oldContent = null, Content $newContent = null,
+               $flags ) {
                // Decide what kind of auto-summary is needed.
 
                // Redirect auto-summaries
@@ -799,8 +802,9 @@ abstract class ContentHandler {
         *
         * @since 1.21
         *
-        * @param $title Title: the page's title
-        * @param &$hasHistory Boolean: whether the page has a history
+        * @param Title $title The page's title
+        * @param bool &$hasHistory Whether the page has a history
+        *
         * @return mixed String containing deletion reason or empty string, or
         *    boolean false if no revision occurred
         *
@@ -907,9 +911,9 @@ abstract class ContentHandler {
         *
         * @since 1.21
         *
-        * @param $current Revision The current text
-        * @param $undo Revision The revision to undo
-        * @param $undoafter Revision Must be an earlier revision than $undo
+        * @param Revision $current The current text
+        * @param Revision $undo The revision to undo
+        * @param Revision $undoafter Must be an earlier revision than $undo
         *
         * @return mixed String on success, false on failure
         */
@@ -980,7 +984,7 @@ abstract class ContentHandler {
         *
         * @since 1.21
         *
-        * @return bool
+        * @return bool Always false.
         */
        public function isParserCacheSupported() {
                return false;
@@ -993,7 +997,7 @@ abstract class ContentHandler {
         * Content models that return true here should also implement
         * Content::getSection, Content::replaceSection, etc. to handle sections..
         *
-        * @return boolean whether sections are supported.
+        * @return bool Always false.
         */
        public function supportsSections() {
                return false;
@@ -1006,7 +1010,7 @@ abstract class ContentHandler {
         * Content models that return true here should also implement
         * ContentHandler::makeRedirectContent to return a Content object.
         *
-        * @return boolean whether redirects are supported.
+        * @return bool Always false.
         */
        public function supportsRedirects() {
                return false;
@@ -1038,13 +1042,13 @@ abstract class ContentHandler {
         * hook function, a new Content object is constructed from the new
         * text.
         *
-        * @param string $event event name
-        * @param array $args parameters passed to hook functions
-        * @param bool $warn whether to log a warning.
+        * @param string $event Event name
+        * @param array $args Parameters passed to hook functions
+        * @param bool $warn Whether to log a warning.
         *                    Default to self::$enableDeprecationWarnings.
         *                    May be set to false for testing.
         *
-        * @return Boolean True if no handler aborted the hook
+        * @return bool True if no handler aborted the hook
         *
         * @see ContentHandler::$enableDeprecationWarnings
         */
index 03cc2d0..5fc2c9f 100644 (file)
  * @ingroup Content
  */
 class CssContent extends TextContent {
+
+       /**
+        * @param string $text CSS code.
+        */
        public function __construct( $text ) {
                parent::__construct( $text, CONTENT_MODEL_CSS );
        }
@@ -39,10 +43,13 @@ class CssContent extends TextContent {
         * Returns a Content object with pre-save transformations applied using
         * Parser::preSaveTransform().
         *
-        * @param $title Title
-        * @param $user User
-        * @param $popts ParserOptions
-        * @return Content
+        * @param Title $title
+        * @param User $user
+        * @param ParserOptions $popts
+        *
+        * @return CssContent
+        *
+        * @see TextContent::preSaveTransform
         */
        public function preSaveTransform( Title $title, User $user, ParserOptions $popts ) {
                global $wgParser;
@@ -54,6 +61,9 @@ class CssContent extends TextContent {
                return new CssContent( $pst );
        }
 
+       /**
+        * @return string CSS wrapped in a <pre> tag.
+        */
        protected function getHtml() {
                $html = "";
                $html .= "<pre class=\"mw-code mw-css\" dir=\"ltr\">\n";
@@ -62,4 +72,5 @@ class CssContent extends TextContent {
 
                return $html;
        }
+
 }
index 7becabb..85059a8 100644 (file)
  * @ingroup Content
  */
 class CssContentHandler extends TextContentHandler {
+
+       /**
+        * @param string $modelId
+        */
        public function __construct( $modelId = CONTENT_MODEL_CSS ) {
                parent::__construct( $modelId, array( CONTENT_FORMAT_CSS ) );
        }
 
+       /**
+        * @param string $text
+        * @param string $format
+        *
+        * @return CssContent
+        *
+        * @see ContentHandler::unserializeContent()
+        */
        public function unserializeContent( $text, $format = null ) {
                $this->checkFormat( $format );
 
                return new CssContent( $text );
        }
 
+       /**
+        * @return CssContent A new CssContent object with empty text.
+        *
+        * @see ContentHandler::makeEmptyContent()
+        */
        public function makeEmptyContent() {
                return new CssContent( '' );
        }
@@ -47,6 +64,7 @@ class CssContentHandler extends TextContentHandler {
         *
         * @param Title $title
         * @param Content $content
+        *
         * @return Language wfGetLangObj( 'en' )
         *
         * @see ContentHandler::getPageLanguage()
@@ -60,6 +78,7 @@ class CssContentHandler extends TextContentHandler {
         *
         * @param Title $title
         * @param Content $content
+        *
         * @return Language wfGetLangObj( 'en' )
         *
         * @see ContentHandler::getPageViewLanguage()
@@ -67,4 +86,5 @@ class CssContentHandler extends TextContentHandler {
        public function getPageViewLanguage( Title $title, Content $content = null ) {
                return wfGetLangObj( 'en' );
        }
+
 }
index 2ae572b..11a470e 100644 (file)
  * @ingroup Content
  */
 class JavaScriptContent extends TextContent {
+
+       /**
+        * @param string $text JavaScript code.
+        */
        public function __construct( $text ) {
                parent::__construct( $text, CONTENT_MODEL_JAVASCRIPT );
        }
@@ -42,7 +46,8 @@ class JavaScriptContent extends TextContent {
         * @param Title $title
         * @param User $user
         * @param ParserOptions $popts
-        * @return Content
+        *
+        * @return JavaScriptContent
         */
        public function preSaveTransform( Title $title, User $user, ParserOptions $popts ) {
                global $wgParser;
@@ -55,6 +60,9 @@ class JavaScriptContent extends TextContent {
                return new JavaScriptContent( $pst );
        }
 
+       /**
+        * @return string JavaScript wrapped in a <pre> tag.
+        */
        protected function getHtml() {
                $html = "";
                $html .= "<pre class=\"mw-code mw-js\" dir=\"ltr\">\n";
@@ -63,4 +71,5 @@ class JavaScriptContent extends TextContent {
 
                return $html;
        }
+
 }
index 064c422..2e98976 100644 (file)
  * @todo make ScriptContentHandler base class, do highlighting stuff there?
  */
 class JavaScriptContentHandler extends TextContentHandler {
+
+       /**
+        * @param string $modelId
+        */
        public function __construct( $modelId = CONTENT_MODEL_JAVASCRIPT ) {
                parent::__construct( $modelId, array( CONTENT_FORMAT_JAVASCRIPT ) );
        }
 
+       /**
+        * @param string $text
+        * @param string $format
+        *
+        * @return JavaScriptContent
+        *
+        * @see ContentHandler::unserializeContent()
+        */
        public function unserializeContent( $text, $format = null ) {
                $this->checkFormat( $format );
 
                return new JavaScriptContent( $text );
        }
 
+       /**
+        * @return JavaScriptContent A new JavaScriptContent object with empty text.
+        *
+        * @see ContentHandler::makeEmptyContent()
+        */
        public function makeEmptyContent() {
                return new JavaScriptContent( '' );
        }
@@ -47,6 +64,7 @@ class JavaScriptContentHandler extends TextContentHandler {
         *
         * @param Title $title
         * @param Content $content
+        *
         * @return Language wfGetLangObj( 'en' )
         *
         * @see ContentHandler::getPageLanguage()
@@ -60,6 +78,7 @@ class JavaScriptContentHandler extends TextContentHandler {
         *
         * @param Title $title
         * @param Content $content
+        *
         * @return Language wfGetLangObj( 'en' )
         *
         * @see ContentHandler::getPageViewLanguage()
@@ -67,4 +86,5 @@ class JavaScriptContentHandler extends TextContentHandler {
        public function getPageViewLanguage( Title $title, Content $content = null ) {
                return wfGetLangObj( 'en' );
        }
+
 }
index e780846..b601344 100644 (file)
  * @ingroup Content
  */
 class MessageContent extends AbstractContent {
+
        /**
         * @var Message
         */
        protected $mMessage;
 
        /**
-        * @param Message|String $msg A Message object, or a message key
-        * @param array|null $params An optional array of message parameters
+        * @param Message|string $msg A Message object, or a message key.
+        * @param string[] $params An optional array of message parameters.
         */
        public function __construct( $msg, $params = null ) {
                # XXX: messages may be wikitext, html or plain text! and maybe even something else entirely.
@@ -59,18 +60,18 @@ class MessageContent extends AbstractContent {
        }
 
        /**
-        * Returns the message as rendered HTML
+        * Fully parse the text from wikitext to HTML.
         *
-        * @return string The message text, parsed into html
+        * @return string Parsed HTML.
         */
        public function getHtml() {
                return $this->mMessage->parse();
        }
 
        /**
-        * Returns the message as rendered HTML
+        * Returns the message text. {{-transformation is done.
         *
-        * @return string The message text, parsed into html
+        * @return string Unescaped message text.
         */
        public function getWikitext() {
                return $this->mMessage->text();
@@ -87,6 +88,8 @@ class MessageContent extends AbstractContent {
        }
 
        /**
+        * @return string
+        *
         * @see Content::getTextForSearchIndex
         */
        public function getTextForSearchIndex() {
@@ -94,6 +97,8 @@ class MessageContent extends AbstractContent {
        }
 
        /**
+        * @return string
+        *
         * @see Content::getWikitextForTransclusion
         */
        public function getWikitextForTransclusion() {
@@ -101,6 +106,10 @@ class MessageContent extends AbstractContent {
        }
 
        /**
+        * @param int $maxLength Maximum length of the summary text, defaults to 250.
+        *
+        * @return string The summary text.
+        *
         * @see Content::getTextForSummary
         */
        public function getTextForSummary( $maxlength = 250 ) {
@@ -108,18 +117,18 @@ class MessageContent extends AbstractContent {
        }
 
        /**
-        * @see Content::getSize
-        *
         * @return int
+        *
+        * @see Content::getSize
         */
        public function getSize() {
                return strlen( $this->mMessage->plain() );
        }
 
        /**
-        * @see Content::copy
-        *
         * @return Content. A copy of this object
+        *
+        * @see Content::copy
         */
        public function copy() {
                // MessageContent is immutable (because getNativeData() returns a clone of the Message object)
@@ -127,29 +136,28 @@ class MessageContent extends AbstractContent {
        }
 
        /**
-        * @see Content::isCountable
-        *
         * @param bool $hasLinks
-        * @return bool false
+        *
+        * @return bool Always false.
+        *
+        * @see Content::isCountable
         */
        public function isCountable( $hasLinks = null ) {
                return false;
        }
 
        /**
-        * @see Content::getParserOutput
+        * @param Title $title Unused.
+        * @param int $revId Unused.
+        * @param ParserOptions $options Unused.
+        * @param bool $generateHtml Whether to generate HTML (default: true).
         *
-        * @param Title $title
-        * @param int $revId Optional revision ID
-        * @param ParserOptions $options
-        * @param bool $generateHtml Wether to generate HTML
         * @return ParserOutput
+        *
+        * @see Content::getParserOutput
         */
-       public function getParserOutput(
-               Title $title, $revId = null,
-               ParserOptions $options = null, $generateHtml = true
-       ) {
-
+       public function getParserOutput( Title $title, $revId = null,
+               ParserOptions $options = null, $generateHtml = true ) {
                if ( $generateHtml ) {
                        $html = $this->getHtml();
                } else {
@@ -160,4 +168,5 @@ class MessageContent extends AbstractContent {
 
                return $po;
        }
+
 }
index 068b150..b0da62d 100644 (file)
  * @ingroup Content
  */
 class TextContent extends AbstractContent {
+
+       /**
+        * @param string $text
+        * @param string $model_id
+        */
        public function __construct( $text, $model_id = CONTENT_MODEL_TEXT ) {
                parent::__construct( $model_id );
 
@@ -50,6 +55,11 @@ class TextContent extends AbstractContent {
                $this->mText = $text;
        }
 
+       /**
+        * @note Mutable subclasses MUST override this to return a copy!
+        *
+        * @return Content $this
+        */
        public function copy() {
                return $this; # NOTE: this is ok since TextContent are immutable.
        }
@@ -81,10 +91,10 @@ class TextContent extends AbstractContent {
         * Returns true if this content is not a redirect, and $wgArticleCountMethod
         * is "any".
         *
-        * @param bool $hasLinks if it is known whether this content contains links,
+        * @param bool $hasLinks If it is known whether this content contains links,
         * provide this information here, to avoid redundant parsing to find out.
         *
-        * @return bool True if the content is countable
+        * @return bool
         */
        public function isCountable( $hasLinks = null ) {
                global $wgArticleCountMethod;
@@ -103,7 +113,7 @@ class TextContent extends AbstractContent {
        /**
         * Returns the text represented by this Content object, as a string.
         *
-        * @return string: the raw text
+        * @return string The raw text.
         */
        public function getNativeData() {
                $text = $this->mText;
@@ -114,7 +124,7 @@ class TextContent extends AbstractContent {
        /**
         * Returns the text represented by this Content object, as a string.
         *
-        * @return string: the raw text
+        * @return string The raw text.
         */
        public function getTextForSearchIndex() {
                return $this->getNativeData();
@@ -126,7 +136,7 @@ class TextContent extends AbstractContent {
         *
         * @note: this allows any text-based content to be transcluded as if it was wikitext.
         *
-        * @return string|false: the raw text, or null if the conversion failed
+        * @return string|false The raw text, or false if the conversion failed.
         */
        public function getWikitextForTransclusion() {
                $wikitext = $this->convert( CONTENT_MODEL_WIKITEXT, 'lossy' );
@@ -142,9 +152,10 @@ class TextContent extends AbstractContent {
         * Returns a Content object with pre-save transformations applied.
         * This implementation just trims trailing whitespace.
         *
-        * @param $title Title
-        * @param $user User
-        * @param $popts ParserOptions
+        * @param Title $title
+        * @param User $user
+        * @param ParserOptions $popts
+        *
         * @return Content
         */
        public function preSaveTransform( Title $title, User $user, ParserOptions $popts ) {
@@ -159,9 +170,9 @@ class TextContent extends AbstractContent {
         *
         * @since 1.21
         *
-        * @param $that Content: The other content object to compare this content
+        * @param Content $that The other content object to compare this content
         * object to.
-        * @param $lang Language: The language object to use for text segmentation.
+        * @param Language $lang The language object to use for text segmentation.
         *    If not given, $wgContentLang is used.
         *
         * @return Diff A diff representing the changes that would have to be
@@ -194,17 +205,15 @@ class TextContent extends AbstractContent {
         * Returns a generic ParserOutput object, wrapping the HTML returned by
         * getHtml().
         *
-        * @param $title Title Context title for parsing
-        * @param int|null $revId Revision ID (for {{REVISIONID}})
-        * @param $options ParserOptions|null Parser options
+        * @param Title $title Context title for parsing
+        * @param int $revId Revision ID (for {{REVISIONID}})
+        * @param ParserOptions $options Parser options
         * @param bool $generateHtml Whether or not to generate HTML
         *
-        * @return ParserOutput representing the HTML form of the text
+        * @return ParserOutput Representing the HTML form of the text.
         */
-       public function getParserOutput( Title $title,
-               $revId = null,
-               ParserOptions $options = null, $generateHtml = true
-       ) {
+       public function getParserOutput( Title $title, $revId = null,
+               ParserOptions $options = null, $generateHtml = true ) {
                global $wgParser, $wgTextModelsToParse;
 
                if ( !$options ) {
@@ -249,7 +258,7 @@ class TextContent extends AbstractContent {
         * Generates a syntax-highlighted version of the content, as HTML.
         * Used by the default implementation of getHtml().
         *
-        * @return string an HTML representation of the content's markup
+        * @return string A HTML representation of the content's markup
         */
        protected function getHighlightHtml() {
                # TODO: make Highlighter interface, use highlighter here, if available
@@ -257,17 +266,15 @@ class TextContent extends AbstractContent {
        }
 
        /**
-        * @see Content::convert()
-        *
         * This implementation provides lossless conversion between content models based
         * on TextContent.
         *
-        * @param string $toModel the desired content model, use the CONTENT_MODEL_XXX flags.
-        * @param string $lossy flag, set to "lossy" to allow lossy conversion. If lossy conversion is
-        * not allowed, full round-trip conversion is expected to work without losing information.
+        * @param string $toModel
+        * @param string $lossy
         *
-        * @return Content|bool A content object with the content model $toModel, or false if
-        * that conversion is not supported.
+        * @return Content|bool
+        *
+        * @see Content::convert()
         */
        public function convert( $toModel, $lossy = '' ) {
                $converted = parent::convert( $toModel, $lossy );
@@ -286,4 +293,5 @@ class TextContent extends AbstractContent {
 
                return $converted;
        }
+
 }
index 94b5c57..b728d31 100644 (file)
  * @ingroup Content
  */
 class TextContentHandler extends ContentHandler {
+
        // @codingStandardsIgnoreStart bug 57585
        public function __construct( $modelId = CONTENT_MODEL_TEXT,
-               $formats = array( CONTENT_FORMAT_TEXT )
-       ) {
+               $formats = array( CONTENT_FORMAT_TEXT ) ) {
                parent::__construct( $modelId, $formats );
        }
        // @codingStandardsIgnoreEnd
@@ -40,8 +40,9 @@ class TextContentHandler extends ContentHandler {
        /**
         * Returns the content's text as-is.
         *
-        * @param $content Content
-        * @param $format string|null
+        * @param Content $content
+        * @param string $format The serialization format to check
+        *
         * @return mixed
         */
        public function serializeContent( Content $content, $format = null ) {
@@ -59,11 +60,11 @@ class TextContentHandler extends ContentHandler {
         *
         * This text-based implementation uses wfMerge().
         *
-        * @param $oldContent Content|string  String
-        * @param $myContent Content|string   String
-        * @param $yourContent Content|string String
+        * @param Content|string $oldContent The page's previous content.
+        * @param Content|string $myContent One of the page's conflicting contents.
+        * @param Content|string $yourContent One of the page's conflicting contents.
         *
-        * @return Content|Bool
+        * @return Content|bool
         */
        public function merge3( Content $oldContent, Content $myContent, Content $yourContent ) {
                $this->checkModelID( $oldContent->getModel() );
@@ -96,10 +97,10 @@ class TextContentHandler extends ContentHandler {
         *
         * @since 1.21
         *
-        * @param $text   string serialized form of the content
-        * @param $format null|String the format used for serialization
+        * @param string $text Serialized form of the content
+        * @param string $format The format used for serialization
         *
-        * @return Content the TextContent object wrapping $text
+        * @return Content The TextContent object wrapping $text
         */
        public function unserializeContent( $text, $format = null ) {
                $this->checkFormat( $format );
@@ -112,9 +113,10 @@ class TextContentHandler extends ContentHandler {
         *
         * @since 1.21
         *
-        * @return Content
+        * @return Content A new TextContent object with empty text.
         */
        public function makeEmptyContent() {
                return new TextContent( '' );
        }
+
 }
index f495c56..605222e 100644 (file)
  * @ingroup Content
  */
 class WikitextContent extends TextContent {
+
        public function __construct( $text ) {
                parent::__construct( $text, CONTENT_MODEL_WIKITEXT );
        }
 
        /**
+        * @param string $section
+        *
+        * @return Content|bool|null
+        *
         * @see Content::getSection()
         */
        public function getSection( $section ) {
@@ -52,6 +57,13 @@ class WikitextContent extends TextContent {
        }
 
        /**
+        * @param string $section
+        * @param Content $with
+        * @param string $sectionTitle
+        *
+        * @throws MWException
+        * @return Content
+        *
         * @see Content::replaceSection()
         */
        public function replaceSection( $section, Content $with, $sectionTitle = '' ) {
@@ -103,7 +115,8 @@ class WikitextContent extends TextContent {
         * Returns a new WikitextContent object with the given section heading
         * prepended.
         *
-        * @param $header string
+        * @param string $header
+        *
         * @return Content
         */
        public function addSectionHeader( $header ) {
@@ -119,9 +132,10 @@ class WikitextContent extends TextContent {
         * Returns a Content object with pre-save transformations applied using
         * Parser::preSaveTransform().
         *
-        * @param $title Title
-        * @param $user User
-        * @param $popts ParserOptions
+        * @param Title $title
+        * @param User $user
+        * @param ParserOptions $popts
+        *
         * @return Content
         */
        public function preSaveTransform( Title $title, User $user, ParserOptions $popts ) {
@@ -138,8 +152,9 @@ class WikitextContent extends TextContent {
         * Returns a Content object with preload transformations applied (or this
         * object if no transformations apply).
         *
-        * @param $title Title
-        * @param $popts ParserOptions
+        * @param Title $title
+        * @param ParserOptions $popts
+        *
         * @return Content
         */
        public function preloadTransform( Title $title, ParserOptions $popts ) {
@@ -157,7 +172,8 @@ class WikitextContent extends TextContent {
         * @note: migrated here from Title::newFromRedirectInternal()
         *
         * @since 1.23
-        * @return array 2 elements: Title|null and string
+        *
+        * @return array List of two elements: Title|null and string.
         */
        protected function getRedirectTargetAndText() {
                global $wgMaxRedirects;
@@ -195,10 +211,9 @@ class WikitextContent extends TextContent {
        /**
         * Implement redirect extraction for wikitext.
         *
-        * @return null|Title
+        * @return Title|null
         *
         * @see Content::getRedirectTarget
-        * @see AbstractContent::getRedirectTarget
         */
        public function getRedirectTarget() {
                list( $title, ) = $this->getRedirectTargetAndText();
@@ -207,8 +222,6 @@ class WikitextContent extends TextContent {
        }
 
        /**
-        * @see Content::updateRedirect()
-        *
         * This implementation replaces the first link on the page with the given new target
         * if this Content object is a redirect. Otherwise, this method returns $this.
         *
@@ -216,8 +229,9 @@ class WikitextContent extends TextContent {
         *
         * @param Title $target
         *
-        * @return Content a new Content object with the updated redirect (or $this
-        *   if this Content object isn't a redirect)
+        * @return Content
+        *
+        * @see Content::updateRedirect()
         */
        public function updateRedirect( Title $target ) {
                if ( !$this->isRedirect() ) {
@@ -238,14 +252,14 @@ class WikitextContent extends TextContent {
         * Returns true if this content is not a redirect, and this content's text
         * is countable according to the criteria defined by $wgArticleCountMethod.
         *
-        * @param bool $hasLinks if it is known whether this content contains
+        * @param bool $hasLinks If it is known whether this content contains
         *    links, provide this information here, to avoid redundant parsing to
         *    find out (default: null).
-        * @param $title Title: (default: null)
+        * @param Title $title Optional title, defaults to the title from the current main request.
         *
         * @internal param \IContextSource $context context for parsing if necessary
         *
-        * @return bool True if the content is countable
+        * @return bool
         */
        public function isCountable( $hasLinks = null, Title $title = null ) {
                global $wgArticleCountMethod;
@@ -279,6 +293,10 @@ class WikitextContent extends TextContent {
                return false;
        }
 
+       /**
+        * @param int $maxlength
+        * @return string
+        */
        public function getTextForSummary( $maxlength = 250 ) {
                $truncatedtext = parent::getTextForSummary( $maxlength );
 
@@ -294,20 +312,17 @@ class WikitextContent extends TextContent {
         * Returns a ParserOutput object resulting from parsing the content's text
         * using $wgParser.
         *
-        * @since    1.21
+        * @since 1.21
         *
-        * @param $title Title
-        * @param int $revId Revision to pass to the parser (default: null)
-        * @param $options ParserOptions (default: null)
+        * @param Title $title * @param int $revId Revision to pass to the parser (default: null)
+        * @param ParserOptions $options (default: null)
         * @param bool $generateHtml (default: false)
-        *
         * @internal param \IContextSource|null $context
-        * @return ParserOutput representing the HTML form of the text
+        *
+        * @return ParserOutput Representing the HTML form of the text
         */
-       public function getParserOutput( Title $title,
-               $revId = null,
-               ParserOptions $options = null, $generateHtml = true
-       ) {
+       public function getParserOutput( Title $title, $revId = null,
+               ParserOptions $options = null, $generateHtml = true ) {
                global $wgParser;
 
                if ( !$options ) {
@@ -334,6 +349,9 @@ class WikitextContent extends TextContent {
                return $po;
        }
 
+       /**
+        * @throws MWException
+        */
        protected function getHtml() {
                throw new MWException(
                        "getHtml() not implemented for wikitext. "
@@ -342,15 +360,16 @@ class WikitextContent extends TextContent {
        }
 
        /**
-        * @see  Content::matchMagicWord()
-        *
         * This implementation calls $word->match() on the this TextContent object's text.
         *
         * @param MagicWord $word
         *
-        * @return bool whether this Content object matches the given magic word.
+        * @return bool
+        *
+        * @see Content::matchMagicWord()
         */
        public function matchMagicWord( MagicWord $word ) {
                return $word->match( $this->getNativeData() );
        }
+
 }
index 1e8fd05..5ae3e25 100644 (file)
@@ -29,6 +29,7 @@
  * @ingroup Content
  */
 class WikitextContentHandler extends TextContentHandler {
+
        public function __construct( $modelId = CONTENT_MODEL_WIKITEXT ) {
                parent::__construct( $modelId, array( CONTENT_FORMAT_WIKITEXT ) );
        }
@@ -40,9 +41,9 @@ class WikitextContentHandler extends TextContentHandler {
        }
 
        /**
-        * @see ContentHandler::makeEmptyContent
+        * @return Content A new WikitextContent object with empty text.
         *
-        * @return Content
+        * @see ContentHandler::makeEmptyContent
         */
        public function makeEmptyContent() {
                return new WikitextContent( '' );
@@ -51,12 +52,12 @@ class WikitextContentHandler extends TextContentHandler {
        /**
         * Returns a WikitextContent object representing a redirect to the given destination page.
         *
-        * @see ContentHandler::makeRedirectContent
-        *
-        * @param Title $destination the page to redirect to.
-        * @param string $text text to include in the redirect, if possible.
+        * @param Title $destination The page to redirect to.
+        * @param string $text Text to include in the redirect, if possible.
         *
         * @return Content
+        *
+        * @see ContentHandler::makeRedirectContent
         */
        public function makeRedirectContent( Title $destination, $text = '' ) {
                $optionalColon = '';
@@ -84,9 +85,9 @@ class WikitextContentHandler extends TextContentHandler {
        /**
         * Returns true because wikitext supports redirects.
         *
-        * @see ContentHandler::supportsRedirects
+        * @return bool Always true.
         *
-        * @return boolean whether redirects are supported.
+        * @see ContentHandler::supportsRedirects
         */
        public function supportsRedirects() {
                return true;
@@ -95,7 +96,9 @@ class WikitextContentHandler extends TextContentHandler {
        /**
         * Returns true because wikitext supports sections.
         *
-        * @return boolean whether sections are supported.
+        * @return bool Always true.
+        *
+        * @see ContentHandler::supportsSections
         */
        public function supportsSections() {
                return true;
@@ -106,9 +109,13 @@ class WikitextContentHandler extends TextContentHandler {
         * ParserCache mechanism.
         *
         * @since 1.21
-        * @return bool
+        *
+        * @return bool Always true.
+        *
+        * @see ContentHandler::isParserCacheSupported
         */
        public function isParserCacheSupported() {
                return true;
        }
+
 }
index b4c7365..377aca1 100644 (file)
@@ -38,7 +38,16 @@ class DBError extends MWException {
                $this->db = $db;
                parent::__construct( $error );
        }
+}
 
+/**
+ * Base class for the more common types of database errors. These are known to occur
+ * frequently, so we try to give friendly error messages for them.
+ *
+ * @ingroup Database
+ * @since 1.23
+ */
+class DBExpectedError extends DBError {
        /**
         * @return string
         */
@@ -80,14 +89,14 @@ class DBError extends MWException {
         * @return string
         */
        protected function getHTMLContent() {
-               return '<p>' . nl2br( htmlspecialchars( $this->getMessage() ) ) . '</p>';
+               return '<p>' . nl2br( htmlspecialchars( $this->getTextContent() ) ) . '</p>';
        }
 }
 
 /**
  * @ingroup Database
  */
-class DBConnectionError extends DBError {
+class DBConnectionError extends DBExpectedError {
        /** @var string Error text */
        public $error;
 
@@ -313,7 +322,7 @@ EOT;
 /**
  * @ingroup Database
  */
-class DBQueryError extends DBError {
+class DBQueryError extends DBExpectedError {
        public $error, $errno, $sql, $fname;
 
        /**
index e202f8a..635909c 100644 (file)
@@ -281,4 +281,18 @@ class DatabaseMysqli extends DatabaseMysqlBase {
        protected function mysqlPing() {
                return $this->mConn->ping();
        }
+
+       /**
+        * Give an id for the connection
+        *
+        * mysql driver used resource id, but mysqli objects cannot be cast to string.
+        */
+       public function __toString() {
+               if ( $this->mConn instanceof Mysqli ) {
+                       return (string)$this->mConn->thread_id;
+               } else {
+                       // mConn might be false or something.
+                       return (string)$this->mConn;
+               }
+       }
 }
index 543ee18..c12b76a 100644 (file)
@@ -32,7 +32,8 @@ class ArrayDiffFormatter extends DiffFormatter {
 
        /**
         * @param Diff $diff A Diff object.
-        * @return array
+        *
+        * @return array[] List of associative arrays, each describing a difference.
         */
        public function format( $diff ) {
                $oldline = 1;
@@ -77,4 +78,5 @@ class ArrayDiffFormatter extends DiffFormatter {
 
                return $retval;
        }
+
 }
index 351a9dd..61edc1e 100644 (file)
  */
 abstract class DiffOp {
 
+       /**
+        * @var string
+        */
        public $type;
+
+       /**
+        * @var string[]
+        */
        public $orig;
+
+       /**
+        * @var string[]
+        */
        public $closing;
 
+       /**
+        * @return string
+        */
        public function getType() {
                return $this->type;
        }
 
+       /**
+        * @return string[]
+        */
        public function getOrig() {
                return $this->orig;
        }
 
+       /**
+        * @param int $i
+        * @return string|null
+        */
        public function getClosing( $i = null ) {
                if( $i === null ) {
                        return $this->closing;
@@ -195,9 +216,10 @@ class DiffEngine {
        protected $lcs = 0;
 
        /**
-        * @param $from_lines
-        * @param $to_lines
-        * @return array
+        * @param string[] $from_lines
+        * @param string[] $to_lines
+        *
+        * @return DiffOp[]
         */
        public function diff( $from_lines, $to_lines ) {
                wfProfileIn( __METHOD__ );
@@ -256,8 +278,8 @@ class DiffEngine {
        }
 
        /**
-        * @param $from_lines
-        * @param $to_lines
+        * @param string[] $from_lines
+        * @param string[] $to_lines
         */
        private function diffLocal( $from_lines, $to_lines ) {
                global $wgExternalDiffEngine;
@@ -329,7 +351,9 @@ class DiffEngine {
 
        /**
         * Returns the whole line if it's small enough, or the MD5 hash otherwise
-        * @param $line string
+        *
+        * @param string $line
+        *
         * @return string
         */
        private function lineHash( $line ) {
@@ -356,12 +380,14 @@ class DiffEngine {
         * of the two files do not match, and likewise that the last lines do not
         * match.  The caller must trim matching lines from the beginning and end
         * of the portions it is going to specify.
-        * @param $xoff
-        * @param $xlim
-        * @param $yoff
-        * @param $ylim
-        * @param $nchunks
-        * @return array
+        *
+        * @param int $xoff
+        * @param int $xlim
+        * @param int $yoff
+        * @param int $ylim
+        * @param int $nchunks
+        *
+        * @return array List of two elements, integer and array[].
         */
        private function diag( $xoff, $xlim, $yoff, $ylim, $nchunks ) {
                $flip = false;
@@ -398,7 +424,7 @@ class DiffEngine {
                        }
 
                        $x1 = $xoff + (int)( ( $numer + ( $xlim - $xoff ) * $chunk ) / $nchunks );
-                       for ( ; $x < $x1; $x++ ) {
+                       for (; $x < $x1; $x++ ) {
                                $line = $flip ? $this->yv[$x] : $this->xv[$x];
                                if ( empty( $ymatches[$line] ) ) {
                                        continue;
@@ -446,7 +472,8 @@ class DiffEngine {
        }
 
        /**
-        * @param $ypos
+        * @param int $ypos
+        *
         * @return int
         */
        private function lcsPos( $ypos ) {
@@ -488,10 +515,11 @@ class DiffEngine {
         *
         * Note that XLIM, YLIM are exclusive bounds.
         * All line numbers are origin-0 and discarded lines are not counted.
-        * @param $xoff
-        * @param $xlim
-        * @param $yoff
-        * @param $ylim
+        *
+        * @param int $xoff
+        * @param int $xlim
+        * @param int $yoff
+        * @param int $ylim
         */
        private function compareSeq( $xoff, $xlim, $yoff, $ylim ) {
                // Slide down the bottom initial diagonal.
@@ -688,9 +716,9 @@ class Diff {
         * Constructor.
         * Computes diff between sequences of strings.
         *
-        * @param $from_lines array An array of strings.
+        * @param string[] $from_lines An array of strings.
         *   Typically these are lines from a file.
-        * @param $to_lines array An array of strings.
+        * @param string[] $to_lines An array of strings.
         */
        public function __construct( $from_lines, $to_lines ) {
                $eng = new DiffEngine;
@@ -698,7 +726,7 @@ class Diff {
        }
 
        /**
-        * @return array|DiffOp[]
+        * @return DiffOp[]
         */
        public function getEdits() {
                return $this->edits;
@@ -711,6 +739,7 @@ class Diff {
         *
         *    $diff = new Diff($lines1, $lines2);
         *    $rev = $diff->reverse();
+        *
         * @return Object A Diff object representing the inverse of the
         *   original diff.
         */
@@ -764,7 +793,7 @@ class Diff {
         * This reconstructs the $from_lines parameter passed to the
         * constructor.
         *
-        * @return array The original sequence of strings.
+        * @return string[] The original sequence of strings.
         */
        public function orig() {
                $lines = array();
@@ -784,7 +813,7 @@ class Diff {
         * This reconstructs the $to_lines parameter passed to the
         * constructor.
         *
-        * @return array The sequence of strings.
+        * @return string[] The sequence of strings.
         */
        public function closing() {
                $lines = array();
@@ -814,18 +843,15 @@ class MappedDiff extends Diff {
         * case-insensitve diffs, or diffs which ignore
         * changes in white-space.
         *
-        * @param $from_lines array An array of strings.
+        * @param string[] $from_lines An array of strings.
         *   Typically these are lines from a file.
-        *
-        * @param $to_lines array An array of strings.
-        *
-        * @param $mapped_from_lines array This array should
+        * @param string[] $to_lines An array of strings.
+        * @param string[] $mapped_from_lines This array should
         *   have the same size number of elements as $from_lines.
         *   The elements in $mapped_from_lines and
         *   $mapped_to_lines are what is actually compared
         *   when computing the diff.
-        *
-        * @param $mapped_to_lines array This array should
+        * @param string[] $mapped_to_lines This array should
         *   have the same number of elements as $to_lines.
         */
        public function __construct( $from_lines, $to_lines,
@@ -875,7 +901,7 @@ class HWLDFWordAccumulator {
        private $tag = '';
 
        /**
-        * @param $new_tag
+        * @param string $new_tag
         */
        private function flushGroup( $new_tag ) {
                if ( $this->group !== '' ) {
@@ -894,7 +920,7 @@ class HWLDFWordAccumulator {
        }
 
        /**
-        * @param $new_tag
+        * @param string $new_tag
         */
        private function flushLine( $new_tag ) {
                $this->flushGroup( $new_tag );
@@ -908,8 +934,8 @@ class HWLDFWordAccumulator {
        }
 
        /**
-        * @param $words
-        * @param $tag string
+        * @param string[] $words
+        * @param string $tag
         */
        public function addWords( $words, $tag = '' ) {
                if ( $tag != $this->tag ) {
@@ -931,7 +957,7 @@ class HWLDFWordAccumulator {
        }
 
        /**
-        * @return array
+        * @return string[]
         */
        public function getLines() {
                $this->flushLine( '~done' );
@@ -949,8 +975,8 @@ class WordLevelDiff extends MappedDiff {
        const MAX_LINE_LENGTH = 10000;
 
        /**
-        * @param $orig_lines
-        * @param $closing_lines
+        * @param string[] $orig_lines
+        * @param string[] $closing_lines
         */
        public function __construct( $orig_lines, $closing_lines ) {
                wfProfileIn( __METHOD__ );
@@ -964,8 +990,9 @@ class WordLevelDiff extends MappedDiff {
        }
 
        /**
-        * @param $lines
-        * @return array
+        * @param string[] $lines
+        *
+        * @return array[]
         */
        private function split( $lines ) {
                wfProfileIn( __METHOD__ );
@@ -1005,7 +1032,7 @@ class WordLevelDiff extends MappedDiff {
        }
 
        /**
-        * @return array
+        * @return string[]
         */
        public function orig() {
                wfProfileIn( __METHOD__ );
@@ -1025,7 +1052,7 @@ class WordLevelDiff extends MappedDiff {
        }
 
        /**
-        * @return array
+        * @return string[]
         */
        public function closing() {
                wfProfileIn( __METHOD__ );
@@ -1043,4 +1070,5 @@ class WordLevelDiff extends MappedDiff {
 
                return $lines;
        }
+
 }
index d9e1c95..d8a9ba3 100644 (file)
@@ -34,6 +34,7 @@
  * @ingroup DifferenceEngine
  */
 abstract class DiffFormatter {
+
        /** @var int Number of leading context "lines" to preserve.
         *
         * This should be left at zero for this class, but subclasses
@@ -51,7 +52,8 @@ abstract class DiffFormatter {
        /**
         * Format a diff.
         *
-        * @param $diff Diff A Diff object.
+        * @param Diff $diff A Diff object.
+        *
         * @return string The formatted output.
         */
        public function format( $diff ) {
@@ -124,7 +126,8 @@ abstract class DiffFormatter {
         * @param int $ybeg
         * @param int $ylen
         * @param $edits
-        * @throws MWException
+        *
+        * @throws MWException If the edit type is not known.
         */
        protected function block( $xbeg, $xlen, $ybeg, $ylen, &$edits ) {
                wfProfileIn( __METHOD__ );
@@ -161,10 +164,11 @@ abstract class DiffFormatter {
        }
 
        /**
-        * @param $xbeg
-        * @param $xlen
-        * @param $ybeg
-        * @param $ylen
+        * @param int $xbeg
+        * @param int $xlen
+        * @param int $ybeg
+        * @param int $ylen
+        *
         * @return string
         */
        protected function blockHeader( $xbeg, $xlen, $ybeg, $ylen ) {
@@ -178,16 +182,28 @@ abstract class DiffFormatter {
                return $xbeg . ( $xlen ? ( $ylen ? 'c' : 'd' ) : 'a' ) . $ybeg;
        }
 
+       /**
+        * Called at the start of a block of connected edits.
+        * This default implementation writes the header and a newline to the output buffer.
+        *
+        * @param string $header
+        */
        protected function startBlock( $header ) {
                echo $header . "\n";
        }
 
+       /**
+        * Called at the end of a block of connected edits.
+        * This default implementation does nothing.
+        */
        protected function endBlock() {
        }
 
        /**
-        * @param $lines
-        * @param $prefix string
+        * Writes all (optionally prefixed) lines to the output buffer, separated by newlines.
+        *
+        * @param string[] $lines
+        * @param string $prefix
         */
        protected function lines( $lines, $prefix = ' ' ) {
                foreach ( $lines as $line ) {
@@ -196,33 +212,36 @@ abstract class DiffFormatter {
        }
 
        /**
-        * @param $lines
+        * @param string[] $lines
         */
        protected function context( $lines ) {
                $this->lines( $lines );
        }
 
        /**
-        * @param $lines
+        * @param string[] $lines
         */
        protected function added( $lines ) {
                $this->lines( $lines, '>' );
        }
 
        /**
-        * @param $lines
+        * @param string[] $lines
         */
        protected function deleted( $lines ) {
                $this->lines( $lines, '<' );
        }
 
        /**
-        * @param $orig
-        * @param $closing
+        * Writes the two sets of lines to the output buffer, separated by "---" and a newline.
+        *
+        * @param string[] $orig
+        * @param string[] $closing
         */
        protected function changed( $orig, $closing ) {
                $this->deleted( $orig );
                echo "---\n";
                $this->added( $closing );
        }
+
 }
index d6cf694..414b9f8 100644 (file)
@@ -34,6 +34,7 @@ define( 'MW_DIFF_VERSION', '1.11a' );
  * @ingroup DifferenceEngine
  */
 class DifferenceEngine extends ContextSource {
+
        /** @var int */
        public $mOldid;
 
@@ -97,14 +98,14 @@ class DifferenceEngine extends ContextSource {
 
        /**
         * Constructor
-        * @param $context IContextSource context to use, anything else will be ignored
-        * @param $old Integer old ID we want to show and diff with.
-        * @param $new String|int either revision ID or 'prev' or 'next'. Default: 0.
-        * @param $rcid Integer Deprecated, no longer used!
-        * @param $refreshCache boolean If set, refreshes the diff cache
-        * @param $unhide boolean If set, allow viewing deleted revs
+        * @param IContextSource $context context to use, anything else will be ignored
+        * @param int $old old ID we want to show and diff with.
+        * @param string|int $new either revision ID or 'prev' or 'next'. Default: 0.
+        * @param int $rcid Deprecated, no longer used!
+        * @param bool $refreshCache If set, refreshes the diff cache
+        * @param bool $unhide If set, allow viewing deleted revs
         */
-       function __construct( $context = null, $old = 0, $new = 0, $rcid = 0,
+       public function __construct( $context = null, $old = 0, $new = 0, $rcid = 0,
                $refreshCache = false, $unhide = false
        ) {
                if ( $context instanceof IContextSource ) {
@@ -120,16 +121,16 @@ class DifferenceEngine extends ContextSource {
        }
 
        /**
-        * @param $value bool
+        * @param bool $value
         */
-       function setReducedLineNumbers( $value = true ) {
+       public function setReducedLineNumbers( $value = true ) {
                $this->mReducedLineNumbers = $value;
        }
 
        /**
         * @return Language
         */
-       function getDiffLang() {
+       public function getDiffLang() {
                if ( $this->mDiffLang === null ) {
                        # Default language in which the diff text is written.
                        $this->mDiffLang = $this->getTitle()->getPageLanguage();
@@ -141,23 +142,23 @@ class DifferenceEngine extends ContextSource {
        /**
         * @return bool
         */
-       function wasCacheHit() {
+       public function wasCacheHit() {
                return $this->mCacheHit;
        }
 
        /**
         * @return int
         */
-       function getOldid() {
+       public function getOldid() {
                $this->loadRevisionIds();
 
                return $this->mOldid;
        }
 
        /**
-        * @return Bool|int
+        * @return bool|int
         */
-       function getNewid() {
+       public function getNewid() {
                $this->loadRevisionIds();
 
                return $this->mNewid;
@@ -167,10 +168,11 @@ class DifferenceEngine extends ContextSource {
         * Look up a special:Undelete link to the given deleted revision id,
         * as a workaround for being unable to load deleted diffs in currently.
         *
-        * @param int $id revision ID
+        * @param int $id Revision ID
+        *
         * @return mixed URL or false
         */
-       function deletedLink( $id ) {
+       public function deletedLink( $id ) {
                if ( $this->getUser()->isAllowed( 'deletedhistory' ) ) {
                        $dbr = wfGetDB( DB_SLAVE );
                        $row = $dbr->selectRow( 'archive', '*',
@@ -193,10 +195,11 @@ class DifferenceEngine extends ContextSource {
        /**
         * Build a wikitext link toward a deleted revision, if viewable.
         *
-        * @param int $id revision ID
-        * @return string wikitext fragment
+        * @param int $id Revision ID
+        *
+        * @return string Wikitext fragment
         */
-       function deletedIdMarker( $id ) {
+       public function deletedIdMarker( $id ) {
                $link = $this->deletedLink( $id );
                if ( $link ) {
                        return "[$link $id]";
@@ -225,7 +228,7 @@ class DifferenceEngine extends ContextSource {
                        $this->getLanguage()->listToText( $missing ), count( $missing ) );
        }
 
-       function showDiffPage( $diffOnly = false ) {
+       public function showDiffPage( $diffOnly = false ) {
                wfProfileIn( __METHOD__ );
 
                # Allow frames except in certain special cases
@@ -451,7 +454,7 @@ class DifferenceEngine extends ContextSource {
         * Side effect: When the patrol link is build, this method will call
         * OutputPage::preventClickjacking() and load mediawiki.page.patrol.ajax.
         *
-        * @return String
+        * @return string
         */
        protected function markPatrolledLink() {
                global $wgUseRCPatrol, $wgEnableAPI, $wgEnableWriteAPI;
@@ -518,8 +521,9 @@ class DifferenceEngine extends ContextSource {
        }
 
        /**
-        * @param $rev Revision
-        * @return String
+        * @param Revision $rev
+        *
+        * @return string
         */
        protected function revisionDeleteLink( $rev ) {
                $link = Linker::getRevDeleteLink( $this->getUser(), $rev, $rev->getTitle() );
@@ -533,7 +537,7 @@ class DifferenceEngine extends ContextSource {
        /**
         * Show the new revision of the page.
         */
-       function renderNewRevision() {
+       public function renderNewRevision() {
                wfProfileIn( __METHOD__ );
                $out = $this->getOutput();
                $revHeader = $this->getRevisionHeader( $this->mNewRev );
@@ -616,7 +620,7 @@ class DifferenceEngine extends ContextSource {
         *
         * @return bool
         */
-       function showDiff( $otitle, $ntitle, $notice = '' ) {
+       public function showDiff( $otitle, $ntitle, $notice = '' ) {
                $diff = $this->getDiff( $otitle, $ntitle, $notice );
                if ( $diff === false ) {
                        $this->showMissingRevision();
@@ -633,7 +637,7 @@ class DifferenceEngine extends ContextSource {
        /**
         * Add style sheets and supporting JS for diff display.
         */
-       function showDiffStyle() {
+       public function showDiffStyle() {
                $this->getOutput()->addModuleStyles( 'mediawiki.action.history.diff' );
        }
 
@@ -643,9 +647,10 @@ class DifferenceEngine extends ContextSource {
         * @param string|bool $otitle Header for old text or false
         * @param string|bool $ntitle Header for new text or false
         * @param string $notice HTML between diff header and body
+        *
         * @return mixed
         */
-       function getDiff( $otitle, $ntitle, $notice = '' ) {
+       public function getDiff( $otitle, $ntitle, $notice = '' ) {
                $body = $this->getDiffBody();
                if ( $body === false ) {
                        return false;
@@ -747,9 +752,10 @@ class DifferenceEngine extends ContextSource {
        /**
         * Returns the cache key for diff body text or content.
         *
-        * @return string
         * @since 1.23
+        *
         * @throws MWException
+        * @return string
         */
        protected function getDiffBodyCacheKey() {
                if ( !$this->mOldid || !$this->mNewid ) {
@@ -771,14 +777,15 @@ class DifferenceEngine extends ContextSource {
         * perhaps taking advantage of the content's native form. This is required for all content
         * models that are not text based.
         *
-        * @param $old Content: old content
-        * @param $new Content: new content
+        * @since 1.21
+        *
+        * @param Content $old Old content
+        * @param Content $new New content
         *
+        * @throws MWException If old or new content is not an instance of TextContent.
         * @return bool|string
-        * @since 1.21
-        * @throws MWException if $old or $new are not instances of TextContent.
         */
-       function generateContentDiffBody( Content $old, Content $new ) {
+       public function generateContentDiffBody( Content $old, Content $new ) {
                if ( !( $old instanceof TextContent ) ) {
                        throw new MWException( "Diff not implemented for " . get_class( $old ) . "; " .
                                "override generateContentDiffBody to fix this." );
@@ -798,12 +805,13 @@ class DifferenceEngine extends ContextSource {
        /**
         * Generate a diff, no caching
         *
-        * @param string $otext old text, must be already segmented
-        * @param string $ntext new text, must be already segmented
+        * @param string $otext Old text, must be already segmented
+        * @param string $ntext New text, must be already segmented
+        *
         * @return bool|string
         * @deprecated since 1.21, use generateContentDiffBody() instead!
         */
-       function generateDiffBody( $otext, $ntext ) {
+       public function generateDiffBody( $otext, $ntext ) {
                ContentHandler::deprecated( __METHOD__, "1.21" );
 
                return $this->generateTextDiffBody( $otext, $ntext );
@@ -816,9 +824,10 @@ class DifferenceEngine extends ContextSource {
         *
         * @param string $otext old text, must be already segmented
         * @param string $ntext new text, must be already segmented
+        *
         * @return bool|string
         */
-       function generateTextDiffBody( $otext, $ntext ) {
+       public function generateTextDiffBody( $otext, $ntext ) {
                global $wgExternalDiffEngine, $wgContLang;
 
                wfProfileIn( __METHOD__ );
@@ -897,7 +906,7 @@ class DifferenceEngine extends ContextSource {
         * Generate a debug comment indicating diff generating time,
         * server node, and generator backend.
         *
-        * @param String $generator : What diff engine was used
+        * @param string $generator : What diff engine was used
         *
         * @return string
         */
@@ -920,11 +929,11 @@ class DifferenceEngine extends ContextSource {
        /**
         * Replace line numbers with the text in the user's language
         *
-        * @param String $text
+        * @param string $text
         *
         * @return mixed
         */
-       function localiseLineNumbers( $text ) {
+       public function localiseLineNumbers( $text ) {
                return preg_replace_callback(
                        '/<!--LINE (\d+)-->/',
                        array( &$this, 'localiseLineNumbersCb' ),
@@ -932,7 +941,7 @@ class DifferenceEngine extends ContextSource {
                );
        }
 
-       function localiseLineNumbersCb( $matches ) {
+       public function localiseLineNumbersCb( $matches ) {
                if ( $matches[1] === '1' && $this->mReducedLineNumbers ) {
                        return '';
                }
@@ -942,9 +951,10 @@ class DifferenceEngine extends ContextSource {
 
        /**
         * If there are revisions between the ones being compared, return a note saying so.
+        *
         * @return string
         */
-       function getMultiNotice() {
+       public function getMultiNotice() {
                if ( !is_object( $this->mOldRev ) || !is_object( $this->mNewRev ) ) {
                        return '';
                } elseif ( !$this->mOldPage->equals( $this->mNewPage ) ) {
@@ -978,9 +988,11 @@ class DifferenceEngine extends ContextSource {
 
        /**
         * Get a notice about how many intermediate edits and users there are
-        * @param $numEdits int
-        * @param $numUsers int
-        * @param $limit int
+        *
+        * @param int $numEdits
+        * @param int $numUsers
+        * @param int $limit
+        *
         * @return string
         */
        public static function intermediateEditsMsg( $numEdits, $numUsers, $limit ) {
@@ -999,10 +1011,11 @@ class DifferenceEngine extends ContextSource {
        /**
         * Get a header for a specified revision.
         *
-        * @param $rev Revision
+        * @param Revision $rev
         * @param string $complete 'complete' to get the header wrapped depending
         *        the visibility of the revision and a link to edit the page.
-        * @return String HTML fragment
+        *
+        * @return string HTML fragment
         */
        protected function getRevisionHeader( Revision $rev, $complete = '' ) {
                $lang = $this->getLanguage();
@@ -1064,7 +1077,7 @@ class DifferenceEngine extends ContextSource {
         *
         * @return string
         */
-       function addHeader( $diff, $otitle, $ntitle, $multi = '', $notice = '' ) {
+       public function addHeader( $diff, $otitle, $ntitle, $multi = '', $notice = '' ) {
                // shared.css sets diff in interface language/dir, but the actual content
                // is often in a different language, mostly the page content language/dir
                $tableClass = 'diff diff-contentalign-' . htmlspecialchars( $this->getDiffLang()->alignStart() );
@@ -1113,7 +1126,7 @@ class DifferenceEngine extends ContextSource {
         * Use specified text instead of loading from the database
         * @deprecated since 1.21, use setContent() instead.
         */
-       function setText( $oldText, $newText ) {
+       public function setText( $oldText, $newText ) {
                ContentHandler::deprecated( __METHOD__, "1.21" );
 
                $oldContent = ContentHandler::makeContent( $oldText, $this->getTitle() );
@@ -1126,7 +1139,7 @@ class DifferenceEngine extends ContextSource {
         * Use specified text instead of loading from the database
         * @since 1.21
         */
-       function setContent( Content $oldContent, Content $newContent ) {
+       public function setContent( Content $oldContent, Content $newContent ) {
                $this->mOldContent = $oldContent;
                $this->mNewContent = $newContent;
 
@@ -1139,7 +1152,7 @@ class DifferenceEngine extends ContextSource {
         * (Defaults to page content language).
         * @since 1.19
         */
-       function setTextLanguage( $lang ) {
+       public function setTextLanguage( $lang ) {
                $this->mDiffLang = wfGetLangObj( $lang );
        }
 
@@ -1149,7 +1162,8 @@ class DifferenceEngine extends ContextSource {
         *
         * @param int $old Revision id, e.g. from URL parameter 'oldid'
         * @param int|string $new Revision id or strings 'next' or 'prev', e.g. from URL parameter 'diff'
-        * @return array Array of two revision ids, older first, later second.
+        *
+        * @return int[] List of two revision ids, older first, later second.
         *     Zero signifies invalid argument passed.
         *     false signifies that there is no previous/next revision ($old is the oldest/newest one).
         */
@@ -1208,7 +1222,7 @@ class DifferenceEngine extends ContextSource {
         *
         * @return bool
         */
-       function loadRevisionData() {
+       public function loadRevisionData() {
                if ( $this->mRevisionsLoaded ) {
                        return true;
                }
@@ -1288,7 +1302,7 @@ class DifferenceEngine extends ContextSource {
         *
         * @return bool
         */
-       function loadText() {
+       public function loadText() {
                if ( $this->mTextLoaded == 2 ) {
                        return true;
                }
@@ -1322,7 +1336,7 @@ class DifferenceEngine extends ContextSource {
         *
         * @return bool
         */
-       function loadNewText() {
+       public function loadNewText() {
                if ( $this->mTextLoaded >= 1 ) {
                        return true;
                }
@@ -1337,4 +1351,5 @@ class DifferenceEngine extends ContextSource {
 
                return true;
        }
+
 }
index 5f28627..ac8f758 100644 (file)
@@ -31,6 +31,7 @@
  * @ingroup DifferenceEngine
  */
 class TableDiffFormatter extends DiffFormatter {
+
        function __construct() {
                $this->leadingContextLines = 2;
                $this->trailingContextLines = 2;
@@ -38,7 +39,8 @@ class TableDiffFormatter extends DiffFormatter {
 
        /**
         * @static
-        * @param $msg
+        * @param string $msg
+        *
         * @return mixed
         */
        public static function escapeWhiteSpace( $msg ) {
@@ -50,10 +52,11 @@ class TableDiffFormatter extends DiffFormatter {
        }
 
        /**
-        * @param $xbeg
-        * @param $xlen
-        * @param $ybeg
-        * @param $ylen
+        * @param int $xbeg
+        * @param int $xlen
+        * @param int $ybeg
+        * @param int $ylen
+        *
         * @return string
         */
        protected function blockHeader( $xbeg, $xlen, $ybeg, $ylen ) {
@@ -64,7 +67,9 @@ class TableDiffFormatter extends DiffFormatter {
        }
 
        /**
-        * @param $header
+        * Writes the header to the output buffer.
+        *
+        * @param string $header
         */
        protected function startBlock( $header ) {
                echo $header;
@@ -73,12 +78,19 @@ class TableDiffFormatter extends DiffFormatter {
        protected function endBlock() {
        }
 
+       /**
+        * @param string[] $lines
+        * @param string $prefix
+        * @param string $color
+        */
        protected function lines( $lines, $prefix = ' ', $color = 'white' ) {
        }
 
        /**
         * HTML-escape parameter before calling this
-        * @param $line
+        *
+        * @param string $line
+        *
         * @return string
         */
        protected function addedLine( $line ) {
@@ -87,7 +99,9 @@ class TableDiffFormatter extends DiffFormatter {
 
        /**
         * HTML-escape parameter before calling this
-        * @param $line
+        *
+        * @param string $line
+        *
         * @return string
         */
        protected function deletedLine( $line ) {
@@ -96,7 +110,9 @@ class TableDiffFormatter extends DiffFormatter {
 
        /**
         * HTML-escape parameter before calling this
-        * @param $line
+        *
+        * @param string $line
+        *
         * @return string
         */
        protected function contextLine( $line ) {
@@ -104,9 +120,10 @@ class TableDiffFormatter extends DiffFormatter {
        }
 
        /**
-        * @param $marker
-        * @param $class
-        * @param $line
+        * @param string $marker
+        * @param string $class Unused
+        * @param string $line
+        *
         * @return string
         */
        protected function wrapLine( $marker, $class, $line ) {
@@ -126,7 +143,9 @@ class TableDiffFormatter extends DiffFormatter {
        }
 
        /**
-        * @param $lines array
+        * Writes all lines to the output buffer, each enclosed in <tr>.
+        *
+        * @param string[] $lines
         */
        protected function added( $lines ) {
                foreach ( $lines as $line ) {
@@ -137,7 +156,9 @@ class TableDiffFormatter extends DiffFormatter {
        }
 
        /**
-        * @param $lines
+        * Writes all lines to the output buffer, each enclosed in <tr>.
+        *
+        * @param string[] $lines
         */
        protected function deleted( $lines ) {
                foreach ( $lines as $line ) {
@@ -148,7 +169,9 @@ class TableDiffFormatter extends DiffFormatter {
        }
 
        /**
-        * @param $lines
+        * Writes all lines to the output buffer, each enclosed in <tr>.
+        *
+        * @param string[] $lines
         */
        protected function context( $lines ) {
                foreach ( $lines as $line ) {
@@ -159,8 +182,10 @@ class TableDiffFormatter extends DiffFormatter {
        }
 
        /**
-        * @param $orig
-        * @param $closing
+        * Writes the two sets of lines to the output buffer, each enclosed in <tr>.
+        *
+        * @param string[] $orig
+        * @param string[] $closing
         */
        protected function changed( $orig, $closing ) {
                wfProfileIn( __METHOD__ );
@@ -183,4 +208,5 @@ class TableDiffFormatter extends DiffFormatter {
                }
                wfProfileOut( __METHOD__ );
        }
+
 }
index 0a86ccc..32a7605 100644 (file)
@@ -29,6 +29,7 @@
  * @ingroup DifferenceEngine
  */
 class UnifiedDiffFormatter extends DiffFormatter {
+
        /** @var int */
        protected $leadingContextLines = 2;
 
@@ -36,22 +37,22 @@ class UnifiedDiffFormatter extends DiffFormatter {
        protected $trailingContextLines = 2;
 
        /**
-        * @param $lines
+        * @param string[] $lines
         */
        protected function added( $lines ) {
                $this->lines( $lines, '+' );
        }
 
        /**
-        * @param $lines
+        * @param string[] $lines
         */
        protected function deleted( $lines ) {
                $this->lines( $lines, '-' );
        }
 
        /**
-        * @param $orig
-        * @param $closing
+        * @param string[] $orig
+        * @param string[] $closing
         */
        protected function changed( $orig, $closing ) {
                $this->deleted( $orig );
@@ -59,13 +60,15 @@ class UnifiedDiffFormatter extends DiffFormatter {
        }
 
        /**
-        * @param $xbeg
-        * @param $xlen
-        * @param $ybeg
-        * @param $ylen
+        * @param int $xbeg
+        * @param int $xlen
+        * @param int $ybeg
+        * @param int $ylen
+        *
         * @return string
         */
        protected function blockHeader( $xbeg, $xlen, $ybeg, $ylen ) {
                return "@@ -$xbeg,$xlen +$ybeg,$ylen @@";
        }
+
 }
index 7c019b0..7a0f740 100644 (file)
@@ -580,6 +580,7 @@ class WikiDiff3 {
 
                return $this->length;
        }
+
 }
 
 /**
@@ -589,6 +590,7 @@ class WikiDiff3 {
  * @ingroup DifferenceEngine
  */
 class RangeDifference {
+
        /** @var int */
        public $leftstart;
 
@@ -615,4 +617,5 @@ class RangeDifference {
                $this->rightend = $rightend;
                $this->rightlength = $rightend - $rightstart;
        }
+
 }
index a5c835e..706da96 100644 (file)
@@ -617,8 +617,9 @@ class SwiftFileBackend extends FileBackendStore {
        }
 
        protected function doGetFileStat( array $params ) {
-               $params['concurrency'] = 1;
-               $stats = $this->doGetFileStatMulti( array( 'srcs' => array( $params['src'] ) ) + $params );
+               $params = array( 'srcs' => array( $params['src'] ), 'concurrency' => 1 ) + $params;
+               unset( $params['src'] );
+               $stats = $this->doGetFileStatMulti( $params );
 
                return reset( $stats );
        }
index 27d9594..e6d316c 100644 (file)
@@ -522,7 +522,7 @@ abstract class HTMLFormField {
                foreach ( $options as $key => $value ) {
                        $key = $this->msg( $key )->plain();
                        $ret[$key] = is_array( $value )
-                               ? $this->lookupOptionsKeys($field, $value)
+                               ? $this->lookupOptionsKeys( $value )
                                : strval( $value );
                }
                return $ret;
@@ -558,7 +558,7 @@ abstract class HTMLFormField {
                                $this->mOptions = self::forceToStringRecursive( $this->mParams['options'] );
                        } elseif ( array_key_exists( 'options-message', $this->mParams ) ) {
                                /** @todo This is copied from Xml::listDropDown(), deprecate/avoid duplication? */
-                               $message = $this->msg( $this->mParams['options-message'] )->plain();
+                               $message = $this->msg( $this->mParams['options-message'] )->inContentLanguage()->plain();
 
                                $optgroup = false;
                                $this->mOptions = array();
index 2944c24..3cf3188 100644 (file)
@@ -28,6 +28,7 @@ class HTMLMultiSelectField extends HTMLFormField implements HTMLNestedFilterable
        }
 
        function getInputHTML( $value ) {
+               $value = HTMLFormField::forceToStringRecursive( $value );
                $html = $this->formatOptions( $this->getOptions(), $value );
 
                return $html;
@@ -103,11 +104,12 @@ class HTMLMultiSelectField extends HTMLFormField implements HTMLNestedFilterable
        }
 
        function filterDataForSubmit( $data ) {
+               $data = HTMLFormField::forceToStringRecursive( $data );
                $options = HTMLFormField::flattenOptions( $this->getOptions() );
 
                $res = array();
                foreach ( $options as $opt ) {
-                       $res["$opt"] = in_array( $opt, $data );
+                       $res["$opt"] = in_array( $opt, $data, true );
                }
 
                return $res;
index aa0ea5d..c52f0a8 100644 (file)
@@ -17,7 +17,7 @@ class HTMLRadioField extends HTMLFormField {
 
                $validOptions = HTMLFormField::flattenOptions( $this->getOptions() );
 
-               if ( in_array( $value, $validOptions ) ) {
+               if ( in_array( strval( $value ), $validOptions, true ) ) {
                        return true;
                } else {
                        return $this->msg( 'htmlform-select-badoption' )->parse();
@@ -33,7 +33,7 @@ class HTMLRadioField extends HTMLFormField {
         * @return String
         */
        function getInputHTML( $value ) {
-               $html = $this->formatOptions( $this->getOptions(), $value );
+               $html = $this->formatOptions( $this->getOptions(), strval( $value ) );
 
                return $html;
        }
@@ -51,7 +51,7 @@ class HTMLRadioField extends HTMLFormField {
                                $html .= $this->formatOptions( $info, $value );
                        } else {
                                $id = Sanitizer::escapeId( $this->mID . "-$info" );
-                               $radio = Xml::radio( $this->mName, $info, $info == $value, $attribs + array( 'id' => $id ) );
+                               $radio = Xml::radio( $this->mName, $info, $info === $value, $attribs + array( 'id' => $id ) );
                                $radio .= '&#160;' . call_user_func( $elementFunc, 'label', array( 'for' => $id ), $label );
 
                                $html .= ' ' . Html::rawElement(
index 2e91a23..564927f 100644 (file)
@@ -72,7 +72,7 @@ class HTMLSelectAndOtherField extends HTMLSelectField {
 
                        if ( $list == 'other' ) {
                                $final = $text;
-                       } elseif ( !in_array( $list, $this->mFlatOptions ) ) {
+                       } elseif ( !in_array( $list, $this->mFlatOptions, true ) ) {
                                # User has spoofed the select form to give an option which wasn't
                                # in the original offer.  Sulk...
                                $final = $text;
index 0437480..c32b445 100644 (file)
@@ -13,7 +13,7 @@ class HTMLSelectField extends HTMLFormField {
 
                $validOptions = HTMLFormField::flattenOptions( $this->getOptions() );
 
-               if ( in_array( $value, $validOptions ) ) {
+               if ( in_array( strval( $value ), $validOptions, true ) ) {
                        return true;
                } else {
                        return $this->msg( 'htmlform-select-badoption' )->parse();
index 045b8df..e8bcb5b 100644 (file)
@@ -21,7 +21,10 @@ class HTMLSelectOrOtherField extends HTMLTextField {
                $valInSelect = false;
 
                if ( $value !== false ) {
-                       $valInSelect = in_array( $value, HTMLFormField::flattenOptions( $this->getOptions() ) );
+                       $value = strval( $value );
+                       $valInSelect = in_array(
+                               $value, HTMLFormField::flattenOptions( $this->getOptions() ), true
+                       );
                }
 
                $selected = $valInSelect ? $value : 'other';
@@ -67,7 +70,7 @@ class HTMLSelectOrOtherField extends HTMLTextField {
                if ( $request->getCheck( $this->mName ) ) {
                        $val = $request->getText( $this->mName );
 
-                       if ( $val == 'other' ) {
+                       if ( $val === 'other' ) {
                                $val = $request->getText( $this->mName . '-other' );
                        }
 
index 9f39a87..24bc456 100644 (file)
@@ -29,7 +29,7 @@ $1',
        'config-localsettings-incomplete' => 'The existing <code>LocalSettings.php</code> appears to be incomplete.
 The $1 variable is not set.
 Please change <code>LocalSettings.php</code> so that this variable is set, and click "{{int:Config-continue}}".',
-       'config-localsettings-connection-error' => 'An error was encountered when connecting to the database using the settings specified in <code>LocalSettings.php</code> or <code>AdminSettings.php</code>. Please fix these settings and try again.
+       'config-localsettings-connection-error' => 'An error was encountered when connecting to the database using the settings specified in <code>LocalSettings.php</code>. Please fix these settings and try again.
 
 $1',
        'config-session-error'            => 'Error starting session: $1',
@@ -609,7 +609,7 @@ $messages['qqq'] = array(
        'config-localsettings-incomplete' => '{{doc-important|Do not translate <code>LocalSettings.php</code> and <code><nowiki>{{int:Config-continue}}</nowiki><code>.}}
 Parameters:
 * $1 - name of variable (any one of required variables or installer-specific global variables)',
-       'config-localsettings-connection-error' => '{{doc-important|Do not translate <code>LocalSettings.php</code> and <code>AdminSettings.php</code>.}}
+       'config-localsettings-connection-error' => '{{doc-important|Do not translate <code>LocalSettings.php</code>.}}
 Used as error message. Parameters:
 * $1 - (probably empty string)',
        'config-session-error' => 'Parameters:
index 6c56b3a..02116ea 100644 (file)
@@ -96,6 +96,7 @@ class OracleUpdater extends DatabaseUpdater {
                        //1.23
                        array( 'addIndex', 'logging', 'i06', 'patch-logging_user_text_type_time_index.sql' ),
                        array( 'addIndex', 'logging', 'i07', 'patch-logging_user_text_time_index.sql' ),
+                       array( 'addField', 'user', 'user_password_expires', 'patch-user_password_expire.sql' ),
 
                        // KEEP THIS AT THE BOTTOM!!
                        array( 'doRebuildDuplicateFunction' ),
index 52978b8..a537861 100644 (file)
@@ -434,10 +434,10 @@ abstract class JobQueue {
         * that are actually inserted into the queue. For example, "refreshLinks" jobs are
         * spawned when a template is edited. One can think of the task as "update links
         * of pages that use template X" and an instance of that task as a "root job".
-        * However, what actually goes into the queue are potentially many refreshLinks2 jobs.
-        * Since these jobs include things like page ID ranges and DB master positions, and morph
-        * into smaller refreshLinks2 jobs recursively, simple duplicate detection (like job_sha1)
-        * for individual jobs being identical is not useful.
+        * However, what actually goes into the queue are range and leaf job subtypes.
+        * Since these jobs include things like page ID ranges and DB master positions,
+        * and can morph into smaller jobs recursively, simple duplicate detection
+        * for individual jobs being identical (like that of job_sha1) is not useful.
         *
         * In the case of "refreshLinks", if these jobs are still in the queue when the template
         * is edited again, we want all of these old refreshLinks jobs for that template to become
index 3422664..c785cb2 100644 (file)
@@ -71,6 +71,12 @@ class JobQueueRedis extends JobQueue {
        /** @var string Key to prefix the queue keys with (used for testing) */
        protected $key;
 
+       /**
+        * @var null|int maximum seconds between execution of periodic tasks.  Used to speed up
+        * testing but should otherwise be left unset.
+        */
+       protected $maximumPeriodicTaskSeconds;
+
        /**
         * @params include:
         *   - redisConfig : An array of parameters to RedisConnectionPool::__construct().
@@ -79,6 +85,10 @@ class JobQueueRedis extends JobQueue {
         *                   If a hostname is specified but no port, the standard port number
         *                   6379 will be used. Required.
         *   - compression : The type of compression to use; one of (none,gzip).
+        *   - maximumPeriodicTaskSeconds : Maximum seconds between check periodic tasks.  Set to
+        *                   force faster execution of periodic tasks for inegration tests that
+        *                   rely on checkDelay.  Without this the integration tests are very very
+        *                   slow.  This really shouldn't be set in production.
         * @param array $params
         */
        public function __construct( array $params ) {
@@ -87,6 +97,8 @@ class JobQueueRedis extends JobQueue {
                $this->server = $params['redisServer'];
                $this->compression = isset( $params['compression'] ) ? $params['compression'] : 'none';
                $this->redisPool = RedisConnectionPool::singleton( $params['redisConfig'] );
+               $this->maximumPeriodicTaskSeconds = isset( $params['maximumPeriodicTaskSeconds'] ) ?
+                       $params['maximumPeriodicTaskSeconds'] : null;
        }
 
        protected function supportedOrders() {
@@ -724,10 +736,16 @@ LUA;
                if ( $this->checkDelay ) {
                        $periods[] = 300; // 5 minutes
                }
+               $period = min( $periods );
+               $period = max( $period, 30 ); // sanity
+               // Support override for faster testing
+               if ( $this->maximumPeriodicTaskSeconds !== null ) {
+                       $period = min( $period, $this->maximumPeriodicTaskSeconds );
+               }
                return array(
                        'recyclePruneAndUndelayJobs' => array(
                                'callback' => array( $this, 'recyclePruneAndUndelayJobs' ),
-                               'period'   => max( min( $periods ), 30 ) // sanity
+                               'period'   => $period,
                        )
                );
        }
index ee7eff8..9ed626f 100644 (file)
@@ -80,8 +80,7 @@ class JpegHandler extends ExifBitmapHandler {
                        wfDebug( __METHOD__ . ": running jpgtran: $cmd\n" );
                        wfProfileIn( 'jpegtran' );
                        $retval = 0;
-                       // @todo FIXME Undefined variable $env
-                       $err = wfShellExecWithStderr( $cmd, $retval, $env );
+                       $err = wfShellExecWithStderr( $cmd, $retval );
                        wfProfileOut( 'jpegtran' );
                        if ( $retval !== 0 ) {
                                $this->logErrorForExternalProcess( $retval, $err, $cmd );
index 23d5825..68bfe59 100644 (file)
@@ -429,10 +429,11 @@ class ResourceLoaderFileModule extends ResourceLoaderModule {
                foreach ( $styles as $styleFiles ) {
                        $files = array_merge( $files, $styleFiles );
                }
-               $skinFiles = self::tryForKey(
-                       self::collateFilePathListByOption( $this->skinStyles, 'media', 'all' ),
-                       $context->getSkin(),
-                       'default'
+
+               $skinFiles = self::collateFilePathListByOption(
+                       self::tryForKey( $this->skinStyles, $context->getSkin(), 'default' ),
+                       'media',
+                       'all'
                );
                foreach ( $skinFiles as $styleFiles ) {
                        $files = array_merge( $files, $styleFiles );
@@ -614,7 +615,9 @@ class ResourceLoaderFileModule extends ResourceLoaderModule {
                return array_merge_recursive(
                        self::collateFilePathListByOption( $this->styles, 'media', 'all' ),
                        self::collateFilePathListByOption(
-                               self::tryForKey( $this->skinStyles, $context->getSkin(), 'default' ), 'media', 'all'
+                               self::tryForKey( $this->skinStyles, $context->getSkin(), 'default' ),
+                               'media',
+                               'all'
                        )
                );
        }
index d0c3068..207e96b 100644 (file)
@@ -185,6 +185,43 @@ class ResourceLoaderStartUpModule extends ResourceLoaderModule {
                return true;
        }
 
+       /**
+        * Get the load URL of the startup modules.
+        *
+        * This is a helper for getScript(), but can also be called standalone, such
+        * as when generating an AppCache manifest.
+        *
+        * @param $context ResourceLoaderContext
+        * @return string
+        */
+       public static function getStartupModulesUrl( ResourceLoaderContext $context ) {
+               // The core modules:
+               $moduleNames = array( 'jquery', 'mediawiki' );
+               wfRunHooks( 'ResourceLoaderGetStartupModules', array( &$moduleNames ) );
+
+               // Get the latest version
+               $loader = $context->getResourceLoader();
+               $version = 0;
+               foreach ( $moduleNames as $moduleName ) {
+                       $version = max( $version,
+                               $loader->getModule( $moduleName )->getModifiedTime( $context )
+                       );
+               }
+
+               $query = array(
+                       'modules' => ResourceLoader::makePackedModulesString( $moduleNames ),
+                       'only' => 'scripts',
+                       'lang' => $context->getLanguage(),
+                       'skin' => $context->getSkin(),
+                       'debug' => $context->getDebug() ? 'true' : 'false',
+                       'version' => wfTimestamp( TS_ISO_8601_BASIC, $version )
+               );
+               // Ensure uniform query order
+               ksort( $query );
+               return  wfAppendQuery( wfScript( 'load' ), $query );
+       }
+
+
        /**
         * @param $context ResourceLoaderContext
         * @return string
@@ -195,30 +232,6 @@ class ResourceLoaderStartUpModule extends ResourceLoaderModule {
                $out = file_get_contents( "$IP/resources/startup.js" );
                if ( $context->getOnly() === 'scripts' ) {
 
-                       // The core modules:
-                       $moduleNames = array( 'jquery', 'mediawiki' );
-                       wfRunHooks( 'ResourceLoaderGetStartupModules', array( &$moduleNames ) );
-
-                       // Get the latest version
-                       $loader = $context->getResourceLoader();
-                       $version = 0;
-                       foreach ( $moduleNames as $moduleName ) {
-                               $version = max( $version,
-                                       $loader->getModule( $moduleName )->getModifiedTime( $context )
-                               );
-                       }
-                       // Build load query for StartupModules
-                       $query = array(
-                               'modules' => ResourceLoader::makePackedModulesString( $moduleNames ),
-                               'only' => 'scripts',
-                               'lang' => $context->getLanguage(),
-                               'skin' => $context->getSkin(),
-                               'debug' => $context->getDebug() ? 'true' : 'false',
-                               'version' => wfTimestamp( TS_ISO_8601_BASIC, $version )
-                       );
-                       // Ensure uniform query order
-                       ksort( $query );
-
                        // Startup function
                        $configuration = $this->getConfig( $context );
                        $registrations = self::getModuleRegistrations( $context );
@@ -230,7 +243,7 @@ class ResourceLoaderStartUpModule extends ResourceLoaderModule {
                                "};\n";
 
                        // Conditional script injection
-                       $scriptTag = Html::linkedScript( wfAppendQuery( wfScript( 'load' ), $query ) );
+                       $scriptTag = Html::linkedScript( self::getStartupModulesUrl( $context ) );
                        $out .= "if ( isCompatible() ) {\n" .
                                "\t" . Xml::encodeJsCall( 'document.write', array( $scriptTag ) ) .
                                "}\n" .
index debf01b..eea723b 100644 (file)
@@ -896,18 +896,16 @@ class SearchResult {
        }
 
        /**
-        * @param array $terms terms to highlight
         * @return String: highlighted title, '' if not supported
         */
-       function getTitleSnippet( $terms ) {
+       function getTitleSnippet() {
                return '';
        }
 
        /**
-        * @param array $terms terms to highlight
         * @return String: highlighted redirect name (redirect to this page), '' if none or not supported
         */
-       function getRedirectSnippet( $terms ) {
+       function getRedirectSnippet() {
                return '';
        }
 
index b0d1f95..1dd6b16 100644 (file)
@@ -46,6 +46,16 @@ class SiteList extends GenericArrayObject {
         */
        protected $byGlobalId = array();
 
+       /**
+        * Navigational site identifiers alias inter-language prefixes
+        * pointing to their sites offset value.
+        *
+        * @since 1.23
+        *
+        * @var array of string
+        */
+       protected $byNavigationId = array();
+
        /**
         * @see GenericArrayObject::getObjectType
         *
@@ -75,6 +85,11 @@ class SiteList extends GenericArrayObject {
                $this->byGlobalId[$site->getGlobalId()] = $index;
                $this->byInternalId[$site->getInternalId()] = $index;
 
+               $ids = $site->getNavigationIds();
+               foreach ( $ids as $navId ) {
+                       $this->byNavigationId[$navId] = $index;
+               }
+
                return true;
        }
 
@@ -94,6 +109,11 @@ class SiteList extends GenericArrayObject {
 
                        unset( $this->byGlobalId[$site->getGlobalId()] );
                        unset( $this->byInternalId[$site->getInternalId()] );
+
+                       $ids = $site->getNavigationIds();
+                       foreach ( $ids as $navId ) {
+                               unset( $this->byNavigationId[$navId] );
+                       }
                }
 
                parent::offsetUnset( $index );
@@ -196,6 +216,43 @@ class SiteList extends GenericArrayObject {
                $this->offsetUnset( $this->byInternalId[$id] );
        }
 
+       /**
+        * Returns if the list contains the site with the provided navigational site id.
+        *
+        * @param string $id
+        *
+        * @return boolean
+        */
+       public function hasNavigationId( $id ) {
+               return array_key_exists( $id, $this->byNavigationId );
+       }
+
+       /**
+        * Returns the Site with the provided navigational site id.
+        * The site needs to exist, so if not sure, call has first.
+        *
+        * @since 1.23
+        *
+        * @param string $id
+        *
+        * @return Site
+        */
+       public function getSiteByNavigationId( $id ) {
+               return $this->offsetGet( $this->byNavigationId[$id] );
+       }
+
+       /**
+        * Removes the site with the specified navigational site id.
+        * The site needs to exist, so if not sure, call has first.
+        *
+        * @since 1.23
+        *
+        * @param string $id
+        */
+       public function removeSiteByNavigationId( $id ) {
+               $this->offsetUnset( $this->byNavigationId[$id] );
+       }
+
        /**
         * Sets a site in the list. If the site was not there,
         * it will be added. If it was, it will be updated.
index 7df00e2..3642750 100644 (file)
@@ -74,6 +74,7 @@ class SpecialContributions extends IncludableSpecialPage {
                $this->opts['limit'] = $request->getInt( 'limit', $user->getOption( 'rclimit' ) );
                $this->opts['target'] = $target;
                $this->opts['topOnly'] = $request->getBool( 'topOnly' );
+               $this->opts['newOnly'] = $request->getBool( 'newOnly' );
 
                $nt = Title::makeTitleSafe( NS_USER, $target );
                if ( !$nt ) {
@@ -140,6 +141,9 @@ class SpecialContributions extends IncludableSpecialPage {
                if ( $this->opts['topOnly'] ) {
                        $feedParams['toponly'] = true;
                }
+               if ( $this->opts['newOnly'] ) {
+                       $feedParams['newonly'] = true;
+               }
                if ( $this->opts['deletedOnly'] ) {
                        $feedParams['deletedonly'] = true;
                }
@@ -185,6 +189,7 @@ class SpecialContributions extends IncludableSpecialPage {
                                'month' => $this->opts['month'],
                                'deletedOnly' => $this->opts['deletedOnly'],
                                'topOnly' => $this->opts['topOnly'],
+                               'newOnly' => $this->opts['newOnly'],
                                'nsInvert' => $this->opts['nsInvert'],
                                'associated' => $this->opts['associated'],
                        ) );
@@ -414,6 +419,10 @@ class SpecialContributions extends IncludableSpecialPage {
                        $this->opts['topOnly'] = false;
                }
 
+               if ( !isset( $this->opts['newOnly'] ) ) {
+                       $this->opts['newOnly'] = false;
+               }
+
                $form = Html::openElement(
                        'form',
                        array(
@@ -433,6 +442,7 @@ class SpecialContributions extends IncludableSpecialPage {
                        'year',
                        'month',
                        'topOnly',
+                       'newOnly',
                        'associated'
                );
 
@@ -565,10 +575,21 @@ class SpecialContributions extends IncludableSpecialPage {
                                array( 'class' => 'mw-input' )
                        )
                );
+               $checkLabelNewOnly = Html::rawElement(
+                       'span',
+                       array( 'style' => 'white-space: nowrap' ),
+                       Xml::checkLabel(
+                               $this->msg( 'sp-contributions-newonly' )->text(),
+                               'newOnly',
+                               'mw-show-new-only',
+                               $this->opts['newOnly'],
+                               array( 'class' => 'mw-input' )
+                       )
+               );
                $extraOptions = Html::rawElement(
                        'td',
                        array( 'colspan' => 2 ),
-                       $deletedOnlyCheck . $checkLabelTopOnly
+                       $deletedOnlyCheck . $checkLabelTopOnly . $checkLabelNewOnly
                );
 
                $dateSelectionAndSubmit = Xml::tags( 'td', array( 'colspan' => 2 ),
@@ -652,6 +673,7 @@ class ContribsPager extends ReverseChronologicalPager {
 
                $this->deletedOnly = !empty( $options['deletedOnly'] );
                $this->topOnly = !empty( $options['topOnly'] );
+               $this->newOnly = !empty( $options['newOnly'] );
 
                $year = isset( $options['year'] ) ? $options['year'] : false;
                $month = isset( $options['month'] ) ? $options['month'] : false;
@@ -831,6 +853,10 @@ class ContribsPager extends ReverseChronologicalPager {
                        $condition[] = 'rev_id = page_latest';
                }
 
+               if ( $this->newOnly ) {
+                       $condition[] = 'rev_parent_id = 0';
+               }
+
                return array( $tables, $index, $condition, $join_conds );
        }
 
index 4548b63..8137651 100644 (file)
@@ -203,7 +203,7 @@ class SpecialPrefixindex extends SpecialAllpages {
 
                        $n = 0;
                        if ( $res->numRows() > 0 ) {
-                               $out = Xml::openElement( 'table', array( 'id' => 'mw-prefixindex-list-table' ) );
+                               $out = Xml::openElement( 'table', array( 'class' => 'mw-prefixindex-list-table' ) );
 
                                $prefixLength = strlen( $prefix );
                                while ( ( $n < $this->maxPerPage ) && ( $s = $res->fetchObject() ) ) {
index d266e3f..a5710a9 100644 (file)
@@ -713,7 +713,6 @@ class SpecialRecentChanges extends ChangesListSpecialPage {
                $dl = $lang->pipeList( $dl );
 
                // show/hide links
-               $showhide = array( $this->msg( 'show' )->text(), $this->msg( 'hide' )->text() );
                $filters = array(
                        'hideminor' => 'rcshowhideminor',
                        'hidebots' => 'rcshowhidebots',
@@ -721,7 +720,10 @@ class SpecialRecentChanges extends ChangesListSpecialPage {
                        'hideliu' => 'rcshowhideliu',
                        'hidepatrolled' => 'rcshowhidepatr',
                        'hidemyself' => 'rcshowhidemine'
-               );
+                 );
+
+               $showhide = array( 'show', 'hide' );
+
                foreach ( $this->getCustomFilters() as $key => $params ) {
                        $filters[$key] = $params['msg'];
                }
@@ -732,7 +734,18 @@ class SpecialRecentChanges extends ChangesListSpecialPage {
 
                $links = array();
                foreach ( $filters as $key => $msg ) {
-                       $link = $this->makeOptionsLink( $showhide[1 - $options[$key]],
+                       // The following messages are used here:
+                       // rcshowhideminor-show, rcshowhideminor-hide, rcshowhidebots-show, rcshowhidebots-hide,
+                       // rcshowhideanons-show, rcshowhideanons-hide, rcshowhideliu-show, rcshowhideliu-hide,
+                       // rcshowhidepatr-show, rcshowhidepatr-hide, rcshowhidemine-show, rcshowhidemine-hide.
+                       $linkMessage = $this->msg( $msg . '-' . $showhide[1 - $options[$key]] );
+                       // Extensions can define additional filters, but don't need to define the corresponding
+                       // messages. If they don't exist, just fall back to 'show' and 'hide'.
+                       if ( !$linkMessage->exists() ) {
+                               $linkMessage = $this->msg( $showhide[1 - $options[$key]] );
+                       }
+
+                       $link = $this->makeOptionsLink( $linkMessage->text(),
                                array( $key => 1 - $options[$key] ), $nondefaults );
                        $links[] = $this->msg( $msg )->rawParams( $link )->escaped();
                }
@@ -740,13 +753,15 @@ class SpecialRecentChanges extends ChangesListSpecialPage {
                // show from this onward link
                $timestamp = wfTimestampNow();
                $now = $lang->userTimeAndDate( $timestamp, $user );
-               $tl = $this->makeOptionsLink(
-                       $now, array( 'from' => $timestamp ), $nondefaults
-               );
-
+               $timenow = $lang->userTime( $timestamp, $user );
+               $datenow = $lang->userDate( $timestamp, $user );
                $rclinks = $this->msg( 'rclinks' )->rawParams( $cl, $dl, $lang->pipeList( $links ) )
                        ->parse();
-               $rclistfrom = $this->msg( 'rclistfrom' )->rawParams( $tl )->parse();
+               $rclistfrom = $this->makeOptionsLink(
+                       $this->msg( 'rclistfrom' )->rawParams( $now, $timenow, $datenow )->parse(),
+                       array( 'from' => $timestamp ),
+                       $nondefaults
+               );
 
                return "{$note}$rclinks<br />$rclistfrom";
        }
index 537709b..67e33b3 100644 (file)
@@ -223,7 +223,7 @@ class LoginForm extends SpecialPage {
                $status = $this->addNewAccountInternal();
                if ( !$status->isGood() ) {
                        $error = $status->getMessage();
-                       $this->mainLoginForm( $error->toString() );
+                       $this->mainLoginForm( $error->toString(), $status->isOK() ? 'warning' : 'error' );
                        return;
                }
 
@@ -259,7 +259,7 @@ class LoginForm extends SpecialPage {
                $status = $this->addNewAccountInternal();
                if ( !$status->isGood() ) {
                        $error = $status->getMessage();
-                       $this->mainLoginForm( $error->toString() );
+                       $this->mainLoginForm( $error->toString(), $status->isOK() ? 'warning' : 'error' );
                        return false;
                }
 
@@ -401,13 +401,34 @@ class LoginForm extends SpecialPage {
                        return Status::newFatal( 'sorbs_create_account_reason' );
                }
 
-               # Now create a dummy user ($u) and check if it is valid
-               $name = trim( $this->mUsername );
-               $u = User::newFromName( $name, 'creatable' );
+               // Leading/trailing/multiple whitespace characters are never accepted in usernames and users
+               // know that, don't warn if someone accidentally types it. We do warn about underscores.
+               $name = trim( preg_replace( '/\s+/', ' ', $this->mUsername ) );
+
+               // Normalize the name so that silly things don't cause "invalid username" errors.
+               // User::newFromName does some rather strict checking, rejecting e.g. leading/trailing/multiple spaces.
+               $title = Title::makeTitleSafe( NS_USER, $this->mUsername );
+               if ( !is_object( $title ) ) {
+                       return Status::newFatal( 'noname' );
+               }
+
+               // Now create a dummy user ($u) and check if it is valid.
+               $u = User::newFromName( $title->getText(), 'creatable' );
+
                if ( !is_object( $u ) ) {
                        return Status::newFatal( 'noname' );
                } elseif ( 0 != $u->idForName() ) {
                        return Status::newFatal( 'userexists' );
+               } elseif ( $name !== $u->getName() ) {
+                       // User name was adjusted due to technical restrictions (e.g. first letter capitalized).
+                       // This is normally handled by a client-side check, but users with JavaScript disabled get here.
+                       $status = Status::newGood();
+                       $status->warning( 'createacct-normalization', $name, $u->getName() );
+
+                       // Set the form field to the correct name, so the user can just hit the button again.
+                       $this->mUsername = $u->getName();
+
+                       return $status;
                }
 
                if ( $this->mCreateaccountMail ) {
index c38b009..870fa11 100644 (file)
@@ -86,6 +86,9 @@ class SpecialVersion extends SpecialPage {
                                        $file = $this->getExtAuthorsFileName( dirname( $extNode['path'] ) );
                                        if ( $file ) {
                                                $wikiText = file_get_contents( $file );
+                                               if ( substr( $file, -4 ) === '.txt' ) {
+                                                       $wikiText = Html::element( 'pre', array(), $wikiText );
+                                               }
                                        }
                                }
 
index 0cb83d5..aba0d27 100644 (file)
@@ -58,15 +58,23 @@ class UsercreateTemplate extends BaseTemplate {
                        <section class="mw-form-header">
                                <?php $this->html( 'header' ); /* extensions such as ConfirmEdit add form HTML here */ ?>
                        </section>
+                       <!-- This element is used by the mediawiki.special.userlogin.signup.js module. -->
+                       <div
+                               id="mw-createacct-status-area"
+                               <?php if ( $this->data['message'] ) { ?>
+                                       class="<?php echo $this->data['messagetype']; ?>box"
+                               <?php } else { ?>
+                                       style="display: none;"
+                               <?php } ?>
+                       >
                        <?php if ( $this->data['message'] ) { ?>
-                               <div class="<?php $this->text( 'messagetype' ); ?>box">
                                        <?php if ( $this->data['messagetype'] == 'error' ) { ?>
                                                <strong><?php $this->msg( 'createacct-error' ); ?></strong>
                                                <br />
                                        <?php } ?>
                                        <?php $this->html( 'message' ); ?>
-                               </div>
                        <?php } ?>
+                       </div>
 
                        <div>
                                <label for='wpName2'>
index 67bffc3..db7a24e 100644 (file)
@@ -42,7 +42,7 @@ abstract class UploadBase {
        protected $mFilteredName, $mFinalExtension;
        protected $mLocalFile, $mFileSize, $mFileProps;
        protected $mBlackListedExtensions;
-       protected $mJavaDetected;
+       protected $mJavaDetected, $mSVGNSError;
 
        protected static $safeXmlEncodings = array( 'UTF-8', 'ISO-8859-1', 'ISO-8859-2', 'UTF-16', 'UTF-32' );
 
@@ -1168,6 +1168,7 @@ abstract class UploadBase {
         * @return mixed false of the file is verified (does not contain scripts), array otherwise.
         */
        protected function detectScriptInSvg( $filename ) {
+               $this->mSVGNSError = false;
                $check = new XmlTypeCheck(
                        $filename,
                        array( $this, 'checkSvgScriptCallback' ),
@@ -1178,6 +1179,9 @@ abstract class UploadBase {
                        // Invalid xml (bug 58553)
                        return array( 'uploadinvalidxml' );
                } elseif ( $check->filterMatch ) {
+                       if ( $this->mSVGNSError ) {
+                               return array( 'uploadscriptednamespace', $this->mSVGNSError );
+                       }
                        return array( 'uploadscripted' );
                }
                return false;
@@ -1204,7 +1208,51 @@ abstract class UploadBase {
         * @return bool
         */
        public function checkSvgScriptCallback( $element, $attribs ) {
-               $strippedElement = $this->stripXmlNamespace( $element );
+               list( $namespace, $strippedElement ) = $this->splitXmlNamespace( $element );
+
+               static $validNamespaces = array(
+                       '',
+                       'adobe:ns:meta/',
+                       'http://creativecommons.org/ns#',
+                       'http://inkscape.sourceforge.net/dtd/sodipodi-0.dtd',
+                       'http://ns.adobe.com/adobeillustrator/10.0/',
+                       'http://ns.adobe.com/adobesvgviewerextensions/3.0/',
+                       'http://ns.adobe.com/extensibility/1.0/',
+                       'http://ns.adobe.com/flows/1.0/',
+                       'http://ns.adobe.com/illustrator/1.0/',
+                       'http://ns.adobe.com/imagereplacement/1.0/',
+                       'http://ns.adobe.com/pdf/1.3/',
+                       'http://ns.adobe.com/photoshop/1.0/',
+                       'http://ns.adobe.com/saveforweb/1.0/',
+                       'http://ns.adobe.com/variables/1.0/',
+                       'http://ns.adobe.com/xap/1.0/',
+                       'http://ns.adobe.com/xap/1.0/g/',
+                       'http://ns.adobe.com/xap/1.0/g/img/',
+                       'http://ns.adobe.com/xap/1.0/mm/',
+                       'http://ns.adobe.com/xap/1.0/rights/',
+                       'http://ns.adobe.com/xap/1.0/stype/dimensions#',
+                       'http://ns.adobe.com/xap/1.0/stype/font#',
+                       'http://ns.adobe.com/xap/1.0/stype/manifestitem#',
+                       'http://ns.adobe.com/xap/1.0/stype/resourceevent#',
+                       'http://ns.adobe.com/xap/1.0/stype/resourceref#',
+                       'http://ns.adobe.com/xap/1.0/t/pg/',
+                       'http://purl.org/dc/elements/1.1/',
+                       'http://purl.org/dc/elements/1.1',
+                       'http://schemas.microsoft.com/visio/2003/svgextensions/',
+                       'http://sodipodi.sourceforge.net/dtd/sodipodi-0.dtd',
+                       'http://web.resource.org/cc/',
+                       'http://www.freesoftware.fsf.org/bkchem/cdml',
+                       'http://www.inkscape.org/namespaces/inkscape',
+                       'http://www.w3.org/1999/02/22-rdf-syntax-ns#',
+                       'http://www.w3.org/2000/svg',
+               );
+
+               if ( !in_array( $namespace, $validNamespaces ) ) {
+                       wfDebug( __METHOD__ . ": Non-svg namespace '$namespace' in uploaded file.\n" );
+                       // @TODO return a status object to a closure in XmlTypeCheck, for MW1.21+
+                       $this->mSVGNSError = $namespace;
+                       return true;
+               }
 
                /*
                 * check for elements that can contain javascript
@@ -1226,6 +1274,13 @@ abstract class UploadBase {
                        return true;
                }
 
+               # Block iframes, in case they pass the namespace check
+               if ( $strippedElement == 'iframe' ) {
+                       wfDebug( __METHOD__ . ": iframe in uploaded file.\n" );
+                       return true;
+               }
+
+
                foreach ( $attribs as $attrib => $value ) {
                        $stripped = $this->stripXmlNamespace( $attrib );
                        $value = strtolower( $value );
@@ -1299,6 +1354,19 @@ abstract class UploadBase {
                return false; //No scripts detected
        }
 
+       /**
+        * Divide the element name passed by the xml parser to the callback into URI and prifix.
+        * @param $name string
+        * @return array containing the namespace URI and prefix
+        */
+       private static function splitXmlNamespace( $element ) {
+               // 'http://www.w3.org/2000/svg:script' -> array( 'http://www.w3.org/2000/svg', 'script' )
+               $parts = explode( ':', strtolower( $element ) );
+               $name = array_pop( $parts );
+               $ns = implode( ':', $parts );
+               return array( $ns, $name );
+       }
+
        /**
         * @param $name string
         * @return string
index f6f3af7..d333a51 100644 (file)
@@ -699,7 +699,7 @@ $messages = array(
 'articlepage' => 'اعرض صفحة المحتوى',
 'talk' => 'نقاش',
 'views' => 'معاينة',
-'toolbox' => 'اÙ\84أدÙ\88ات',
+'toolbox' => 'أدوات',
 'userpage' => 'طالع صفحة المستخدم',
 'projectpage' => 'طالع صفحة المشروع',
 'imagepage' => 'طالع صفحة الملف',
@@ -1038,7 +1038,7 @@ $2',
 'createacct-another-realname-tip' => 'الاسم الحقيقي اختياري.
 إذا اخترت توفيره فسيستخدم لنسبة عمل المستخدم إليه.',
 'pt-login' => 'تسجيل الدخول',
-'pt-createaccount' => 'أنشئ حساباً',
+'pt-createaccount' => 'أنشئ حسابا',
 'pt-userlogout' => 'تسجيل الخروج',
 
 # Email sending
@@ -1266,10 +1266,10 @@ $2
 في نص التعديل. تم رفض التعديل لمنع فساد نص المقالة.
 هذا يحدث أحيانا عندما تستخدم خدمة بروكسي مجهول معيبة مبنية على الوب.'''",
 'edit_form_incomplete' => "'''بعض أجزاء من نموذج التعديل لم تصل إلى الخادم؛ تأكد من أن تعديلاتك لم تمس وحاول مجددا.'''",
-'editing' => 'تعديل «$1»',
+'editing' => 'تعديل $1',
 'creating' => 'إنشاء «$1»',
-'editingsection' => 'تعديل قسم من «$1»',
-'editingcomment' => 'تعدÙ\8aÙ\84 $1 (Ù\82سÙ\85 Ø¬Ø¯Ù\8aد)',
+'editingsection' => 'تعديل $1 (قسم)',
+'editingcomment' => 'Ø¥Ù\86شاء Ù\82سÙ\85 Ù\85Ù\86 Â«$1»',
 'editconflict' => 'تضارب في التحرير: $1',
 'explainconflict' => "لقد عدل شخص آخر هذه الصفحة بعد أن بدأت أنت بتحريرها.
 صندوق النصوص العلوي يحتوي على النص الموجود حاليا في الصفحة.
@@ -1551,7 +1551,7 @@ $1",
 'mergelogpagetext' => 'بالأسفل قائمة بأحدث عمليات الدمج لتاريخ صفحة ما إلى أخرى.',
 
 # Diffs
-'history-title' => 'تاريخ «$1»',
+'history-title' => 'تاريخ "$1"',
 'difference-title' => '«$1»: الفرق بين المراجعتين',
 'difference-title-multipage' => '«$1» و«$2»: الفرق بين الصفحتين',
 'difference-multipage' => '(الفرق بين الصفحتين)',
@@ -2064,6 +2064,7 @@ $1",
 'uploaddisabledtext' => 'رفع الملفات معطل.',
 'php-uploaddisabledtext' => 'رفع ملفات PHP معطل. من فضلك تحقق من إعدادات رفع الملفات.',
 'uploadscripted' => 'هذا الملف يضم كود HTML أو كود آخر يمكن أن يفسره متصفح الوب بطريقة خاطئة.',
+'uploadinvalidxml' => 'تعذر تحليل XML في الملف المرفوع.',
 'uploadvirus' => 'الملف يحتوي على فيروس! التفاصيل: $1',
 'uploadjava' => 'يحتوي ملف ZIP هذا على ملفات جافا .class.
 لا يسمح برفع ملفات جافا لأنها تتيح تخطي القيود الأمنية.',
@@ -2702,7 +2703,7 @@ $UNWATCHURL
 'excontentauthor' => "المحتوى كان: '$1' (والمساهم الوحيد كان '[[Special:Contributions/$2|$2]]')",
 'exbeforeblank' => "المحتوى قبل الإفراغ كان: '$1'",
 'exblank' => 'الصفحة كانت فارغة',
-'delete-confirm' => 'حذف «$1»',
+'delete-confirm' => 'حذف "$1"',
 'delete-legend' => 'حذف',
 'historywarning' => "'''تحذير:''' الصفحة التي توشك على حذفها لها تاريخ فيه {{PLURAL:$1||مراجعة واحدة|مراجعتان|$1 مراجعات|$1 مراجعة}} تقريبا:",
 'confirmdeletetext' => 'أنت على وشك أن تقوم بحذف صفحة بالإضافة إلى كل تاريخها.
@@ -2765,7 +2766,7 @@ $UNWATCHURL
 'modifiedarticleprotection' => 'غير مستوى حماية "[[$1]]"',
 'unprotectedarticle' => 'أزال الحماية من "[[$1]]"',
 'movedarticleprotection' => 'نقل إعدادات الحماية من "[[$2]]" إلى "[[$1]]"',
-'protect-title' => 'ضبط حماية «$1»',
+'protect-title' => 'ضبط حماية "$1"',
 'protect-title-notallowed' => 'عرض مستوى حماية "$1"',
 'prot_1movedto2' => 'نُقلت [[$1]] إلى [[$2]]',
 'protect-badnamespace-title' => 'نطاق لا يحمى',
@@ -2892,7 +2893,7 @@ $1',
 'contributions' => 'مساهمات {{GENDER:$1|المستخدم|المستخدمة}}',
 'contributions-title' => 'مساهمات {{GENDER:$1|المستخدم|المستخدمة}} $1',
 'mycontris' => 'مساهماتي',
-'contribsub2' => '{{GENDER:$3|$1}} ($2)',
+'contribsub2' => 'ل{{GENDER:$3|$1}} ($2)',
 'nocontribs' => 'لم يتم العثور على تغييرات تطابق هذه المحددات.',
 'uctop' => 'حالي',
 'month' => 'من شهر (وأقدم):',
@@ -3082,7 +3083,7 @@ $1',
 'lockedbyandtime' => '(من $1 على $2 في $3 )',
 
 # Move page
-'move-page' => 'نقل «$1»',
+'move-page' => 'نقل $1',
 'move-page-legend' => 'نقل صفحة',
 'movepagetext' => "باستخدام  الاستمارة بالأسفل بإمكانك أن تغير اسم الصفحة، وأن تنقل تاريخها إلى الاسم الجديد.
 العنوان القديم سيصبح تحويلة للعنوان الجديد.
@@ -4585,6 +4586,4 @@ $5
 'expand_templates_generate_rawhtml' => 'أظهر خام HTML',
 'expand_templates_preview' => 'عرض مسبق',
 
-# Unknown messages
-'uploadinvalidxml' => 'تعذر تحليل XML في الملف المرفوع.',
 );
index 5f5ce39..155b66b 100644 (file)
@@ -649,7 +649,7 @@ Pa completar l'aniciu de sesión, tien de definir una nueva contraseña equí:",
 'resetpass-temp-password' => 'Contraseña temporal:',
 'resetpass-abort-generic' => "Una estensión encaboxó'l cambiu de la contraseña.",
 'resetpass-expired' => "La so contraseña caducó. Defina una nueva contraseña p'aniciar sesión.",
-'resetpass-expired-soft' => 'La so contraseña caducó y tien de reaniciala. Escueya una contraseña nueva o calque encaboxar pa reaniciala más sero.',
+'resetpass-expired-soft' => 'La so contraseña caducó y tien de reaniciala. Escueya una contraseña nueva, o calque «{{int:resetpass-submit-cancel}}» pa reaniciala más sero.',
 
 # Special:PasswordReset
 'passwordreset' => 'Reaniciar contraseña',
@@ -1506,14 +1506,26 @@ Esta información sedrá pública.',
 'recentchanges-legend-heading' => "'''Lleenda:'''",
 'recentchanges-legend-newpage' => '(ver tamién la  [[Special:NewPages|llista de páxines nueves]])',
 'recentchanges-legend-plusminus' => "(''±123'')",
-'rcnotefrom' => "Abaxo tan los cambeos dende '''$2''' (s'amuesen fasta '''$1''').",
+'rcnotefrom' => "Abaxo tan los cambeos dende <strong>$2</strong> (s'amuesen fasta <strong>$1</strong>).",
 'rclistfrom' => 'Amosar los nuevos cambios dende $1',
 'rcshowhideminor' => '$1 ediciones menores',
+'rcshowhideminor-show' => 'Amosar',
+'rcshowhideminor-hide' => 'Anubrir',
 'rcshowhidebots' => '$1 bots',
+'rcshowhidebots-show' => 'Amosar',
+'rcshowhidebots-hide' => 'Anubrir',
 'rcshowhideliu' => '$1 los usuarios rexistraos',
+'rcshowhideliu-show' => 'Amosar',
+'rcshowhideliu-hide' => 'Anubrir',
 'rcshowhideanons' => '$1 usuarios anónimos',
+'rcshowhideanons-show' => 'Amosar',
+'rcshowhideanons-hide' => 'Anubrir',
 'rcshowhidepatr' => '$1 ediciones supervisaes',
+'rcshowhidepatr-show' => 'Amosar',
+'rcshowhidepatr-hide' => 'Anubrir',
 'rcshowhidemine' => '$1 les mios ediciones',
+'rcshowhidemine-show' => 'Amosar',
+'rcshowhidemine-hide' => 'Anubrir',
 'rclinks' => 'Amosar los caberos $1 cambeos de los caberos $2 díes <br />$3',
 'diff' => 'dif',
 'hist' => 'hist',
@@ -1645,6 +1657,8 @@ Deberíes revisar el historial de desaniciu del ficheru enantes de xubilu otra v
 'php-uploaddisabledtext' => 'Les xubíes de ficheros tan desactivaes en PHP.
 Por favor, comprueba la configuración de file_uploads.',
 'uploadscripted' => 'Esti ficheru contién códigu HTML o scripts que se puen interpretar equivocadamente por un navegador.',
+'uploadscriptednamespace' => "Esti ficheru SVG contién l'espaciu de nomes illegal «$1»",
+'uploadinvalidxml' => "Nun pudo interpretase'l XML del ficheru cargáu.",
 'uploadvirus' => '¡El ficheru tien un virus!
 Detalles: $1',
 'uploadjava' => 'El ficheru ye un archivu ZIP que contién un ficheru .class de Java.
@@ -2483,6 +2497,7 @@ La cabera entrada del rexistru de bloqueos s'ufre darréu pa referencia:",
 'sp-contributions-search' => 'Buscar contribuciones',
 'sp-contributions-username' => "Direición IP o nome d'usuariu:",
 'sp-contributions-toponly' => 'Amosar namái les ediciones que son les caberes revisiones',
+'sp-contributions-newonly' => 'Amosar namái les ediciones que son creaciones de páxines',
 'sp-contributions-submit' => 'Buscar',
 
 # What links here
@@ -4025,6 +4040,4 @@ En realidá cuasi tolo qu'apaeza ente llaves dobles.",
 'expand_templates_generate_rawhtml' => 'Ver el HTML en bruto',
 'expand_templates_preview' => 'Vista previa',
 
-# Unknown messages
-'uploadinvalidxml' => "Nun pudo interpretase'l XML del ficheru cargáu.",
 );
index d9a3276..04af676 100644 (file)
@@ -97,7 +97,7 @@ $messages = array(
 'tog-hidepatrolled' => 'Без паказу ўхваленых правак у нядаўніх змяненнях',
 'tog-newpageshidepatrolled' => 'Без паказу ўхваленых правак у пераліку новых старонак',
 'tog-extendwatchlist' => 'Паказваць усе змяненні, а не толькі апошнія',
-'tog-usenewrc' => 'Групаваць змены старонкі ў спісах апошніх зменаў і назіранняў (патрабуе JavaScript)',
+'tog-usenewrc' => 'Групаваць змены па старонках у апошніх зменах і спісе назірання',
 'tog-numberheadings' => 'Аўта-нумараваць падзагалоўкі',
 'tog-showtoolbar' => 'Паказваць рэдактарскую стужку (Яваскрыпт)',
 'tog-editondblclick' => 'Праўка старонак па падвойным пстрыку (Яваскрыпт)',
@@ -231,7 +231,7 @@ $messages = array(
 'cancel' => 'Нічога',
 'moredotdotdot' => 'Яшчэ...',
 'morenotlisted' => 'Больш нічога няма...',
-'mypage' => 'УлаÑ\81наÑ\8f Ñ\81таронка',
+'mypage' => 'Старонка',
 'mytalk' => 'Размовы',
 'anontalk' => 'Размова для гэтага IP',
 'navigation' => 'Навігацыя',
@@ -331,7 +331,7 @@ $1',
 # All link text and link target definitions of links into project namespace that get used by other message strings, with the exception of user group pages (see grouppage).
 'aboutsite' => 'Пра {{GRAMMAR:вінавальны|{{SITENAME}}}}',
 'aboutpage' => 'Project:Пра {{GRAMMAR:вінавальны|{{SITENAME}}}}',
-'copyright' => 'Матэрыял даступны на ўмовах $1.',
+'copyright' => 'Матэрыял даступны на ўмовах $1 (калі не пазначана іншае).',
 'copyrightpage' => '{{ns:project}}:Аўтарскія правы',
 'currentevents' => 'Актуальныя падзеі',
 'currentevents-url' => 'Project:Актуальныя падзеі',
@@ -464,6 +464,7 @@ $2',
 'ns-specialprotected' => 'Не дазволена правіць старонкі ў прасторы назваў {{ns:special}}.',
 'titleprotected' => "Назва засцерагаецца ад стварэння; ахова пастаўлена ўдзельнікам: [[User:$1|$1]].
 Тлумачэнне пастаноўкі пад ахову: ''$2''.",
+'exception-nologin' => 'Вы не ўвайшлі ў сістэму',
 
 # Virus scanner
 'virus-badscanner' => "Некарэктная канфігурацыя: невядомы антывірусны сканер: ''$1''",
@@ -480,6 +481,7 @@ $2',
 'yourname' => 'Імя ўдзельніка',
 'userlogin-yourname' => 'Імя ўліковага запісу',
 'userlogin-yourname-ph' => 'Увядзіце імя вашага ўліковага запісу',
+'createacct-another-username-ph' => 'Увядзіце імя карыстальніка',
 'yourpassword' => 'Пароль',
 'userlogin-yourpassword' => 'Пароль',
 'userlogin-yourpassword-ph' => 'Увядзіце ваш пароль',
@@ -500,18 +502,28 @@ $2',
 'logout' => 'Выйсці з сістэмы',
 'userlogout' => 'Выйсці з сістэмы',
 'notloggedin' => 'Не ўвайшоў',
+'userlogin-noaccount' => 'Не маеце ўліковага запісу?',
 'nologin' => 'Не маеце рахунку? $1.',
 'nologinlink' => 'Завесці рахунак',
 'createaccount' => 'Стварыць рахунак',
 'gotaccount' => "Ужо маеце рахунак? '''$1'''.",
 'gotaccountlink' => 'Увайсці ў сістэму',
 'userlogin-resetlink' => 'Забыліся даныя для ўваходу?',
+'userlogin-resetpassword-link' => 'Забылі пароль?',
+'createacct-emailrequired' => 'Адрас электроннай пошты',
+'createacct-emailoptional' => 'Адрас электроннай пошты (неабавязкова)',
+'createacct-email-ph' => 'Увядзіце ваш адрас электроннай пошты',
+'createacct-another-email-ph' => 'Увядзіце адрас электроннай пошты',
 'createaccountmail' => 'праз эл.пошту',
 'createaccountreason' => 'Прычына:',
+'createacct-reason' => 'Прычына',
+'createacct-imgcaptcha-ph' => 'Увядзіце тэкст, які вы бачыце вышэй',
+'createacct-submit' => 'Стварыць уліковы запіс',
 'badretype' => 'Уведзеныя паролі не аднолькавыя.',
 'userexists' => 'Такое імя ўдзельніка ўжо занятае.
 Калі ласка, выбярыце іншае імя.',
 'loginerror' => 'Памылка ўваходу',
+'createacct-error' => 'Памылка стварэння ўліковага запісу',
 'createaccounterror' => 'Не ўдалося стварыць рахунак: $1',
 'nocookiesnew' => 'Рахунак быў створаны, але ў сістэму вы не ўвайшлі. {{SITENAME}} карыстаецца квіткамі (кукі), каб апрацоўваць уваходы ўдзельнікаў, а гэтая функцыянальнасць адключана ў вашым браўзеры. Уключыце квіткі ў браўзеры, тады ўваходзьце са сваімі новымі імем удзельніка і паролем.',
 'nocookieslogin' => '{{SITENAME}} карыстаецца квіткамі (кукі), каб пазнаваць удзельнікаў. У вашым браўзеры квіткі не дазволены. Дазвольце іх працу і паспрабуйце ізноў.',
@@ -529,7 +541,7 @@ $2',
 'passwordtooshort' => 'Трэба, каб у паролі было найменей {{PLURAL:$1|1 знак|$1 знакаў}}.',
 'password-name-match' => 'Ваш пароль павінен адрознівацца ад імя карыстальніка.',
 'password-login-forbidden' => 'Выкарыстанне гэтага імя карыстальніка і пароля было забаронена.',
-'mailmypassword' => 'Ð\90даÑ\81лаÑ\86Ñ\8c Ð½Ð¾Ð²Ñ\8b Ð¿Ð°Ñ\80олÑ\8c Ñ\8dл.поÑ\88Ñ\82ай',
+'mailmypassword' => 'СкÑ\96нÑ\83Ñ\86Ñ\8c Ð¿Ð°Ñ\80олÑ\8c',
 'passwordremindertitle' => 'Нагаданне пра пароль ад {{SITENAME}}',
 'passwordremindertext' => 'Нехта (магчыма, што вы, з адрасу IP $1) папрасіў выслаць новы пароль для пляцоўкі {{SITENAME}} ($4). Для ўдзельніка "$2" быў створаны тымчасовы пароль: "$3".
 Калі вы хацелі менавіта гэтага, то ўвайдзіце ў сістэму і выберыце сабе новы пароль. Тымчасовы пароль будзе дзейным на працягу {{PLURAL:$5|аднаго дня|$5 дзён}}.
@@ -563,6 +575,9 @@ $2',
 'login-abort-generic' => 'Няўдалая спроба ўвайсці ў сістэму',
 'loginlanguagelabel' => 'Мова: $1',
 'suspicious-userlogout' => 'Ваш запыт на выхад быў адмоўлены, паколькі ён выглядае як накіраваны са зламанага браўзера або кэшаванне проксі-сервераў.',
+'pt-login' => 'Увайсці',
+'pt-createaccount' => 'Стварыць уліковы запіс',
+'pt-userlogout' => 'Выйсці',
 
 # Email sending
 'php-mail-error-unknown' => 'Невядомая памылка ў функцыі PHP-пошты',
@@ -570,13 +585,13 @@ $2',
 
 # Change password dialog
 'changepassword' => 'Пароль',
-'resetpass_announce' => 'Ð\92Ñ\8b Ñ\9eвайÑ\88лÑ\96 Ñ\9e Ñ\81Ñ\96Ñ\81Ñ\82Ñ\8dмÑ\83 Ð¿Ð°Ð´ Ñ\82Ñ\8bмÑ\87аÑ\81овÑ\8bм Ð¿Ð°Ñ\80олем, Ð¿Ñ\80Ñ\8bÑ\81ланÑ\8bм Ñ\8dл.поÑ\88Ñ\82ай. Ð\9aаб Ð¿Ñ\80авÑ\96лÑ\8cна Ð°Ñ\84оÑ\80мÑ\96Ñ\86Ñ\8c Ñ\83ваÑ\85од, Ð½Ð°Ð»ÐµÐ¶Ñ\8bÑ\86Ñ\8c Ð²Ñ\8bзнаÑ\87Ñ\8bÑ\86Ñ\8c Ð½Ð¾Ð²Ñ\8b Ð¿Ð°Ñ\80олÑ\8c Ð²Ð¾Ñ\81Ñ\8c Ñ\82Ñ\83Ñ\82:',
+'resetpass_announce' => 'Ð\9aаб Ð·Ð°Ð²Ñ\8fÑ\80Ñ\88Ñ\8bÑ\86Ñ\8c Ñ\83ваÑ\85од Ñ\83 Ñ\81Ñ\96Ñ\81Ñ\82Ñ\8dмÑ\83, Ð\92Ñ\8b Ð¿Ð°Ð²Ñ\96ннÑ\8b Ñ\9eÑ\81Ñ\82анавÑ\96Ñ\86Ñ\8c Ð½Ð¾Ð²Ñ\8b Ð¿Ð°Ñ\80олÑ\8c.',
 'resetpass_header' => 'Змяніць пароль рахунку',
 'oldpassword' => 'Стары пароль:',
 'newpassword' => 'Новы пароль:',
 'retypenew' => 'Новы пароль паўторна:',
 'resetpass_submit' => 'Наставіць пароль і ўвайсці',
-'changepassword-success' => 'Ваш пароль паспяхова зменены! Цяпер уваходзім...',
+'changepassword-success' => 'Ваш пароль паспяхова зменены!',
 'resetpass_forbidden' => 'Не дазволена мяняць паролі',
 'resetpass-no-info' => 'Трэба ўвайсці ў сістэму, каб звяртацца да гэтай старонкі наўпрост.',
 'resetpass-submit-loggedin' => 'Змяніць пароль',
@@ -1929,12 +1944,12 @@ $1',
 'watchlistanontext' => 'Каб паглядзець ці змяніць спіс назірання, трэба $1.',
 'watchnologin' => 'Без прадстаўлення',
 'watchnologintext' => 'Каб правіць свой спіс назірання, трэба [[Special:UserLogin|ўвайсці ў сістэму]].',
-'addwatch' => 'Дадаць у назіранае',
+'addwatch' => 'Дадаць у спіс назірання',
 'addedwatchtext' => "Старонка \"[[:\$1]]\" была дададзена да [[Special:Watchlist|назіраных]] вамі.
 Змяненні, якія адбудуцца з гэтай старонкай і з Размовай пра яе, будуць паказвацца там, і старонка будзе '''вылучацца шрыфтам''' у [[Special:RecentChanges|спісе нядаўніх змяненняў]], каб лягчэй пазнаваць яе.
 
 Калі вы не пажадаеце больш назіраць за гэтай старонкай, націсніце \"Не назіраць\" у бакоўцы.",
-'removewatch' => 'Выдаліць са спісу назірання',
+'removewatch' => 'Выдаліць са спіса назірання',
 'removedwatchtext' => 'Старонка "[[:$1]]" была вынята з вашага [[Special:Watchlist|спіса назірання]].',
 'watch' => 'Назіраць',
 'watchthispage' => 'Назіраць за гэтай старонкай',
@@ -2009,8 +2024,8 @@ $UNWATCHURL
 Пацвердзіце свой намер зрабіць гэта, сваё разуменне наступстваў, і што вы робіце гэта ў адпаведнасці з [[{{MediaWiki:Policy-url}}|палітыкай (асноўнымі правіламі)]].',
 'actioncomplete' => 'Завершана аперацыя',
 'actionfailed' => 'Памылка дзеяння',
-'deletedtext' => '"$1" было выдалена.
\91аÑ\87 $2 Ð¿Ð° Ð¶Ñ\83Ñ\80нал Ð½Ñ\8fдаÑ\9eнÑ\96Ñ\85 Ð²Ñ\8bдаленнÑ\8fÑ\9e.',
+'deletedtext' => 'Старонка "$1" была выдалена.
\97апÑ\96Ñ\81Ñ\8b Ð°Ð± Ð½Ñ\8fдаÑ\9eнÑ\96Ñ\85 Ð²Ñ\8bдаленнÑ\8fÑ\85 Ð³Ð». Ñ\9e $2.',
 'dellogpage' => 'Журнал сціранняў',
 'dellogpagetext' => 'Ніжэй паказаны спіс самых нядаўніх сціранняў.',
 'deletionlog' => 'журнал сціранняў',
@@ -2139,7 +2154,7 @@ $UNWATCHURL
 'undeletedpage' => "'''$1 была адноўлена'''
 
 Праверце пералік нядаўніх сціранняў і аднаўленняў у [[Special:Log/delete|журнале сціранняў]].",
-'undelete-header' => 'Ð\91аÑ\87 Ð½Ñ\8fдаÑ\9eна Ñ\81Ñ\86Ñ\91Ñ\80Ñ\82Ñ\8bÑ\8f Ñ\81Ñ\82аÑ\80онкÑ\96 Ñ\9e [[Special:Log/delete|журнале сціранняў]].',
+'undelete-header' => 'Ð\9dÑ\8fдаÑ\9eна Ñ\81Ñ\86Ñ\91Ñ\80Ñ\82Ñ\8bÑ\8f Ñ\81Ñ\82аÑ\80онкÑ\96 Ð¼Ð¾Ð¶Ð½Ð° Ð¿Ð°Ð³Ð»Ñ\8fдзеÑ\86Ñ\8c Ñ\83 [[Special:Log/delete|журнале сціранняў]].',
 'undelete-search-title' => 'Пошук выдаленых старонак',
 'undelete-search-box' => 'Знайсці ў сцёртых старонках',
 'undelete-search-prefix' => 'Паказаць старонкі, пачынаючы з:',
@@ -2295,7 +2310,7 @@ $1',
 'blocklog-showlog' => '{{GENDER:$1|Гэты ўдзельнік ужо блакіраваўся|Гэта ўдзельніца ўжо блакіравалася}} раней.
 Ніжэй прыведзены журнал блакіровак:',
 'blocklog-showsuppresslog' => 'Гэты ўдзельнік ужо заблакаваны і скрыты. Журнал утойвання прыведзены ніжэй:',
-'blocklogentry' => 'пастаўлены блок на "[[$1]]", з часам трывання $2 $3',
+'blocklogentry' => 'паставіў блок на "[[$1]]", з часам трывання $2 $3',
 'reblock-logentry' => 'змененыя настройкі блока для [[$1]] з часам згасання $2 $3',
 'blocklogtext' => 'Журнал пастаноўкі і здымання блокаў. Аўтаматычна блакаваныя адрасы IP тут не паказваюцца. Спіс актуальных забарон і блокаў бач у [[Special:BlockList|спісе блокаў IP]].',
 'unblocklogentry' => 'зняты блок з $1',
@@ -3286,15 +3301,15 @@ $5
 'watchlistedit-raw-legend' => 'Правіць нефарматаваны спіс назірання',
 'watchlistedit-raw-explain' => 'Назвы старонак з ліку назіраных паказаныя ніжэй, без афармлення, адна назва на адзін радок; такім чынам, спіс можна правіць як звычайны тэкст. Па сканчэнні націсніце "{{int:Watchlistedit-raw-submit}}". Таксама гэта можна зрабіць праз [[Special:EditWatchlist|стандартны інтэрфейс]].',
 'watchlistedit-raw-titles' => 'Назвы:',
-'watchlistedit-raw-submit' => 'Абнавіць Назіранае',
+'watchlistedit-raw-submit' => 'Абнавіць спіс назірання',
 'watchlistedit-raw-done' => 'Спіс назірання абноўлены.',
 'watchlistedit-raw-added' => 'Дапісаны{{PLURAL:$1| 1 складнік|я $1 складнікаў}}:',
 'watchlistedit-raw-removed' => 'Выняты{{PLURAL:$1| 1 складнік|я $1 складнікаў}}:',
 
 # Watchlist editing tools
 'watchlisttools-view' => 'Паказаць змяненні',
-'watchlisttools-edit' => 'Паказаць назіранае',
-'watchlisttools-raw' => 'Паказаць нефарматаванае назіранае',
+'watchlisttools-edit' => 'Паказаць спіс назірання',
+'watchlisttools-raw' => 'Паказаць нефарматаваны спіс назірання',
 
 # Signatures
 'signature' => '[[{{ns:user}}:$1|$2]] ([[{{ns:user_talk}}:$1|размовы]])',
index 52961d7..7252579 100644 (file)
@@ -828,8 +828,12 @@ $2',
 'resetpass-wrong-oldpass' => 'Няслушны часовы альбо цяперашні пароль.
 Магчыма Вы ўжо пасьпяхова зьмянілі Ваш пароль альбо запыталі новы часовы пароль.',
 'resetpass-recycled' => 'Калі ласка, зьмяніце ваш пароль на нешта адрознае ад вашага цяперашняга паролю.',
+'resetpass-temp-emailed' => 'Вы ўвашлі з дапамогай часовага коду, які быў дасланы праз электронную пошту.
+Каб завершыць уваход, вы мусіце ўвесьці новы пароль:',
 'resetpass-temp-password' => 'Часовы пароль:',
 'resetpass-abort-generic' => 'Зьмяненьне паролю было скасаванае пашырэньнем.',
+'resetpass-expired' => 'Тэрмін дзеяньня вашага паролю скончыўся. Калі ласка, пазначце новы пароль для ўваходу ў сыстэму.',
+'resetpass-expired-soft' => 'Тэрмін дзеяньня вашага паролю скончыўся і ён патрабуе замены. Калі ласка, абярыце новы пароль цяпер або націсьніце «{{int:resetpass-submit-cancel}}», каб зьмяніць яго пазьней.',
 
 # Special:PasswordReset
 'passwordreset' => 'Ачыстка паролю',
@@ -1674,10 +1678,14 @@ $1",
 'recentchanges-label-plusminus' => 'Памер старонкі зьмяніўся на такую колькасьць байтаў',
 'recentchanges-legend-heading' => "'''Легенда:'''",
 'recentchanges-legend-newpage' => '(глядзіце таксама [[Special:NewPages|сьпіс новых старонак]])',
-'rcnotefrom' => "Ніжэй знаходзяцца зьмены з '''$2''' (да '''$1''' на старонку).",
+'rcnotefrom' => 'Ніжэй знаходзяцца зьмены з <strong>$2</strong> (да <strong>$1</strong> на старонку).',
 'rclistfrom' => 'Паказаць зьмены з $1',
 'rcshowhideminor' => '$1 дробныя праўкі',
+'rcshowhideminor-show' => 'Паказаць',
+'rcshowhideminor-hide' => 'Схаваць',
 'rcshowhidebots' => '$1 робатаў',
+'rcshowhidebots-show' => 'Паказаць',
+'rcshowhidebots-hide' => 'Схаваць',
 'rcshowhideliu' => '$1 зарэгістраваных карыстальнікаў',
 'rcshowhideanons' => '$1 ананімаў',
 'rcshowhidepatr' => '$1 патруляваныя праўкі',
@@ -1807,6 +1815,7 @@ $1",
 'uploaddisabledtext' => 'Загрузка файлаў забароненая.',
 'php-uploaddisabledtext' => 'Загрузка файлаў была адключаная ў парамэтрах канфігурацыі PHP. Калі ласка, праверце значэньне парамэтра «file_uploads».',
 'uploadscripted' => 'Гэты файл утрымлівае HTML-код альбо скрыпт, які можа памылкова апрацоўвацца браўзэрам.',
+'uploadinvalidxml' => 'Не атрымалася прааналізаваць XML у загружаным файле.',
 'uploadvirus' => 'Файл утрымлівае вірус! Падрабязнасьці: $1',
 'uploadjava' => 'Файл зьяўляецца ZIP-архівам, які зьмяшчае .class-файл Java.
 Загрузка Java-файлаў забароненая ў мэтах бясьпекі.',
@@ -4004,12 +4013,12 @@ MediaWiki распаўсюджваецца з надзеяй, што будзе
 'logentry-delete-delete' => '$1 {{GENDER:$2|выдаліў|выдаліла}} старонку $3',
 'logentry-delete-restore' => '$1 {{GENDER:$2|аднавіў|аднавіла}} старонку $3',
 'logentry-delete-event' => '$1 {{GENDER:$2|зьмяніў|зьмяніла}} бачнасьць $5 {{PLURAL:$5|1=падзеі ў журнале|падзеяў у журнале}} на $3: $4',
-'logentry-delete-revision' => '$1 {{GENDER:$2|зьмяніў|зьмяніла}} бачнасьць $5 {{PLURAL:$5|1=вэрсіі|вэрсіяў}} старонкі $3: $4',
+'logentry-delete-revision' => '$1 {{GENDER:$2|зьмяніў|зьмяніла}} бачнасьць $5 {{PLURAL:$5|вэрсіі|вэрсіяў}} старонкі $3: $4',
 'logentry-delete-event-legacy' => '$1 {{GENDER:$2|зьмяніў|зьмяніла}} бачнасьць падзеяў у журнале на $3',
 'logentry-delete-revision-legacy' => '$1 {{GENDER:$2|зьмяніў|зьмяніла}} бачнасьць вэрсіяў старонкі $3',
 'logentry-suppress-delete' => '$1 {{GENDER:$2|схаваў|схавала}} старонку $3',
-'logentry-suppress-event' => '$1 прыхавана {{GENDER:$2|зьмяніў|зьмяніла}} бачнасьць $5 {{PLURAL:$5|1=падзеі ў журнале|падзеяў у журнале}} на $3: $4',
-'logentry-suppress-revision' => '$1 прыхавана {{GENDER:$2|зьмяніў|зьмяніла}} бачнасьць $5 {{PLURAL:$5|1=вэрсіі|вэрсіяў}} старонкі $3: $4',
+'logentry-suppress-event' => '$1 прыхавана {{GENDER:$2|зьмяніў|зьмяніла}} бачнасьць $5 {{PLURAL:$5|падзеі ў журнале|падзеяў у журнале}} на $3: $4',
+'logentry-suppress-revision' => '$1 прыхавана {{GENDER:$2|зьмяніў|зьмяніла}} бачнасьць $5 {{PLURAL:$5|вэрсіі|вэрсіяў}} старонкі $3: $4',
 'logentry-suppress-event-legacy' => '$1 прыхавана {{GENDER:$2|зьмяніў|зьмяніла}} бачнасьць падзеяў у журнале на $3',
 'logentry-suppress-revision-legacy' => '$1 прыхавана {{GENDER:$2|зьмяніў|зьмяніоа}} бачнасьць вэрсіяў старонкі $3',
 'revdelete-content-hid' => 'зьмест схаваны',
@@ -4144,6 +4153,4 @@ MediaWiki распаўсюджваецца з надзеяй, што будзе
 'expand_templates_generate_xml' => 'Паказаць дрэва аналізу XML',
 'expand_templates_preview' => 'Папярэдні прагляд',
 
-# Unknown messages
-'uploadinvalidxml' => 'Не атрымалася прааналізаваць XML у загружаным файле.',
 );
index e1057e9..051831d 100644 (file)
@@ -16,6 +16,7 @@
  * @author Kaganer
  * @author MegaAlex
  * @author Milicevic01
+ * @author Mitzev
  * @author Simona
  * @author Spiritia
  * @author Stanqo
@@ -633,6 +634,7 @@ $2',
 
 Администраторът, който го е заключил, е посочил следната причина: „$3“.',
 'exception-nologin-text' => 'За досъп до желаната страница или действие уикито изисква [[Special:Userlogin|влизане в системата]].',
+'exception-nologin-text-manual' => 'За достъп до избраното действие или страница е необходимо $1 в системата.',
 
 # Virus scanner
 'virus-badscanner' => "Лоша конфигурация: непознат скенер за вируси: ''$1''",
@@ -642,8 +644,7 @@ $2',
 # Login and logout pages
 'logouttext' => "'''Излязохте от системата.'''
 
-Можете да продължите да използвате {{SITENAME}} анонимно или да <span class='plainlinks'>[$1 влезете отново]</span> като друг потребител.
-Обърнете внимание, че някои страници все още ще се показват така, сякаш сте влезли, докато не изтриете кеш-паметта на браузъра.",
+Обърнете внимание, че някои страници все още ще се показват така, сякаш сте влезли, докато не изтриете кеша на браузъра.",
 'welcomeuser' => 'Здравейте, $1!',
 'welcomecreation-msg' => 'Вашата сметка беше създадена.
 Можете да промените [[Special:Preferences|настройките на {{SITENAME}}]] според предпочитанията си.',
@@ -659,6 +660,7 @@ $2',
 'createacct-yourpasswordagain' => 'Потвърждаване на паролата',
 'createacct-yourpasswordagain-ph' => 'Въвежда се паролата (повторно)',
 'remembermypassword' => 'Запомняне на паролата на този компютър (най-много за $1 {{PLURAL:$1|ден|дни}})',
+'userlogin-remembermypassword' => 'Запомняне',
 'userlogin-signwithsecure' => 'Използване на защитена връзка',
 'yourdomainname' => 'Домейн:',
 'password-change-forbidden' => 'Не можете да променяте пароли в това уики.',
@@ -691,6 +693,7 @@ $2',
 'createacct-another-join' => 'Попълване на информацията за новата сметка',
 'createacct-emailrequired' => 'Адрес за електронна поща',
 'createacct-emailoptional' => 'Адрес за електронна поща (незадължително)',
+'createacct-email-ph' => 'Въведете Вашия адрес за електронна поща',
 'createacct-another-email-ph' => 'Въвежда се електронна поща',
 'createaccountmail' => 'Използване на случайна временна парола, която се изпраща на електронната поща, посочена по-долу',
 'createacct-realname' => 'Истинско име (незадължително)',
@@ -767,6 +770,11 @@ $2',
 'login-abort-generic' => 'Влизането беше неуспешно - Прекратено',
 'loginlanguagelabel' => 'Език: $1',
 'suspicious-userlogout' => 'Заявката ви за излизане от системата беше отхвърлена, тъй като изглежда е била изпратена погрешка от браузъра или кеширащото прокси.',
+'createacct-another-realname-tip' => 'Истинското име е незадължително.
+В случай, че бъде избрабо да се попълни, ще бъде използвано за да му се приписват приносите в уикито.',
+'pt-login' => 'Влизане',
+'pt-createaccount' => 'Създаване на сметка',
+'pt-userlogout' => 'Излизане',
 
 # Email sending
 'php-mail-error-unknown' => 'Неизвестна грешка в mail() функцията на PHP',
@@ -774,7 +782,7 @@ $2',
 
 # Change password dialog
 'changepassword' => 'Смяна на парола',
-'resetpass_announce' => 'Ð\92лÑ\8fзоÑ\85Ñ\82е Ñ\81 Ð²Ñ\80еменен ÐºÐ¾Ð´, Ð¿Ð¾Ð»Ñ\83Ñ\87ен Ð¿Ð¾ ÐµÐ»ÐµÐºÑ\82Ñ\80оннаÑ\82а Ð¿Ð¾Ñ\89а. Ð¡ÐµÐ³Ð° Ðµ Ð½Ñ\83жно Ð´Ð° Ñ\81и Ð¸Ð·Ð±ÐµÑ\80еÑ\82е Ð½Ð¾Ð²Ð° Ð¿Ð°Ñ\80ола:',
+'resetpass_announce' => 'Ð\97а Ð´Ð° Ñ\81е Ð·Ð°Ð²Ñ\8aÑ\80Ñ\88и Ð¿Ñ\80оÑ\86еÑ\81а Ð½Ð° Ð²Ð»Ð¸Ð·Ð°Ð½Ðµ, Ð½ÐµÐ¾Ð±Ñ\85одимо Ðµ Ð´Ð° Ñ\81е Ð¸Ð·Ð±ÐµÑ\80е Ð½Ð¾Ð²Ð° Ð¿Ð°Ñ\80ола.',
 'resetpass_text' => '<!-- Тук добавете текст -->',
 'resetpass_header' => 'Промяна на парола',
 'oldpassword' => 'Стара парола:',
@@ -1581,11 +1589,23 @@ $1",
 'rcnotefrom' => 'Дадени са промените от <strong>$2</strong> (до <strong>$1</strong> показани).',
 'rclistfrom' => 'Показване на промени, като се започва от $1.',
 'rcshowhideminor' => '$1 на малки промени',
+'rcshowhideminor-show' => 'Показване',
+'rcshowhideminor-hide' => 'Скриване',
 'rcshowhidebots' => '$1 на ботове',
+'rcshowhidebots-show' => 'Показване',
+'rcshowhidebots-hide' => 'Скриване',
 'rcshowhideliu' => '$1 на регистрирани потребители',
+'rcshowhideliu-show' => 'Показване',
+'rcshowhideliu-hide' => 'Скриване',
 'rcshowhideanons' => '$1 на анонимни потребители',
+'rcshowhideanons-show' => 'Показване',
+'rcshowhideanons-hide' => 'Скриване',
 'rcshowhidepatr' => '$1 на проверени редакции',
+'rcshowhidepatr-show' => 'Показване',
+'rcshowhidepatr-hide' => 'Скриване',
 'rcshowhidemine' => '$1 на моите приноси',
+'rcshowhidemine-show' => 'Показване',
+'rcshowhidemine-hide' => 'Скриване',
 'rclinks' => 'Показване на последните $1 промени за последните $2 дни<br />$3',
 'diff' => 'разл',
 'hist' => 'ист',
@@ -1706,6 +1726,7 @@ $1",
 'uploaddisabledtext' => 'Качването на файлове е забранено.',
 'php-uploaddisabledtext' => 'Качванията на файлове са спрени през PHP. Проверете настройката file_uploads.',
 'uploadscripted' => 'Файлът съдържа HTML или скриптов код, който може да бъде погрешно  интерпретиран от браузъра.',
+'uploadscriptednamespace' => 'Този SVG файл съдържа неправилно пространство на имената " $1 "',
 'uploadvirus' => 'Файлът съдържа вирус! Подробности: $1',
 'uploadjava' => 'Файлът е ZIP файл, който съдържа Java .class файл.
 Качването на Java файлове не е позволено, тъй като могат да причинят заобикаляне на ограниченията за сигурност.',
@@ -2006,6 +2027,7 @@ $1',
 'protectedpages-indef' => 'Само безсрочни защити',
 'protectedpages-cascade' => 'Само каскадни защити',
 'protectedpagesempty' => 'В момента няма защитени страници с тези параметри.',
+'protectedpages-reason' => 'Причина',
 'protectedtitles' => 'Защитени заглавия',
 'protectedtitlesempty' => 'В момента няма заглавия, защитени с тези параметри.',
 'listusers' => 'Списък на потребителите',
@@ -2432,6 +2454,7 @@ $1',
 'sp-contributions-search' => 'Търсене на приноси',
 'sp-contributions-username' => 'IP-адрес или потребителско име:',
 'sp-contributions-toponly' => 'Показване само на последните редакции',
+'sp-contributions-newonly' => 'Показване само на редакции свързани с началното създаване на страницата.',
 'sp-contributions-submit' => 'Търсене',
 
 # What links here
@@ -2714,6 +2737,7 @@ $1',
 'allmessages-prefix' => 'Филтриране по представка:',
 'allmessages-language' => 'Език:',
 'allmessages-filter-submit' => 'Отваряне',
+'allmessages-filter-translate' => 'Превеждане',
 
 # Thumbnails
 'thumbnail-more' => 'Увеличаване',
@@ -3572,7 +3596,13 @@ $5
 'version-hook-name' => 'Име на куката',
 'version-hook-subscribedby' => 'Ползвана от',
 'version-version' => '(Версия $1)',
-'version-license' => 'Лиценз',
+'version-license' => 'Лиценз на МедияУики',
+'version-ext-license' => 'Лиценз',
+'version-ext-colheader-version' => 'Версия',
+'version-ext-colheader-license' => 'Лиценз',
+'version-ext-colheader-description' => 'Описание',
+'version-ext-colheader-credits' => 'Автори',
+'version-license-title' => 'Лиценз за $1',
 'version-poweredby-credits' => "Това уики се задвиждва от '''[https://www.mediawiki.org/ MediaWiki]''', copyright © 2001-$1 $2.",
 'version-poweredby-others' => 'други',
 'version-poweredby-translators' => 'преводачи в translatewiki.net',
index 155e30a..2f39b53 100644 (file)
@@ -29,40 +29,44 @@ $digitTransformTable = array(
 
 $messages = array(
 # User preference toggles
-'tog-underline' => 'འོà½\82à¼\8bà½\90ིà½\82à¼\8bའà½\90ེà½\93à¼\8bà½\94།',
-'tog-hideminor' => 'རྩོà½\98à¼\8bསà¾\92ྲིà½\82à¼\8bà½\86ུà½\84à¼\8bà½\9aà½\82སà¼\8bསྦསà¼\8bà½\96།',
-'tog-hidepatrolled' => 'ལà¾\9fà¼\8bà½\9eིà½\96à¼\8bà½\96ྱསà¼\8bà½\94འིà¼\8bརྩོà½\98à¼\8bསà¾\92ྲིà½\82à¼\8bསྦསà¼\8bà½\96།',
-'tog-newpageshidepatrolled' => 'ཤོà½\82à¼\8bà½\84ོསà¼\8bà½\82སརà¼\8bà½\96རà¼\8bལà¾\9fà¼\8bà½\9eིà½\96à¼\8bà½\96ྱསà¼\8bà½\94འིà¼\8bརྩོà½\98à¼\8bསà¾\92ྲིà½\82à¼\8bསྦསà¼\8bà½\96།',
-'tog-extendwatchlist' => 'à½\98à½\89à½\98à¼\8bའà½\87ོà½\82à¼\8bà½\90ོà¼\8bà½\96à½\80ྲà½\98ས་ཏེ་ཉེ་ལམ་ཙམ་མིན་པར་བཟོ་བཅོས་ཡོངས་རྫོགས་སྟོན་ཅིག',
-'tog-usenewrc' => 'ཡརà¼\8bརà¾\92ྱསà¼\8bà½\85à½\93à¼\8bà½\82ྱིà¼\8bà½\89ེà¼\8bà½\96འིà¼\8bà½\96à½\9fོà¼\8bà½\96à½\85ོསà¼\8bà½\96ེà½\91à¼\8bསྤྱོà½\91à¼\8bà½\94à¼\8d(Java à½¡à½²à¼\8bà½\96རྡà¼\8bà½\86à½\91à¼\8bà½\91à½\82ོས)',
+'tog-underline' => 'འོà½\82à¼\8bà½\90ིà½\82à¼\8bà½\85à½\93à¼\8bལà¼\8bསྦྲེལà¼\8bà½\98à½\90ུà½\91།',
+'tog-hideminor' => 'à½\89ེà¼\8bà½\91ུསà¼\8bà½\80ྱིà¼\8bརྩོà½\98à¼\8bསà¾\92ྲིà½\82à¼\8bà½\82ལà¼\8bà½\86ུà½\84à¼\8bà½\82ྱིà¼\8bའà½\82ྱུརà¼\8bལྡོà½\82à¼\8bརྣà½\98སà¼\8bསྦས།',
+'tog-hidepatrolled' => 'à½\89ེà¼\8bà½\91ུསà¼\8bà½\80ྱིà¼\8bལà¾\9fà¼\8bà½\9eིà½\96à¼\8bà½\96ྱསà¼\8bà½\94འིà¼\8bརྩོà½\98à¼\8bསà¾\92ྲིà½\82à¼\8bརྣà½\98སà¼\8bསྦས།',
+'tog-newpageshidepatrolled' => 'ཤོà½\82à¼\8bà½\84ོསà¼\8bà½\82སརà¼\8bà½\96རà¼\8bལà¾\9fà¼\8bà½\9eིà½\96à¼\8bà½\96ྱསà¼\8bà½\94འིà¼\8bརྩོà½\98à¼\8bསà¾\92ྲིà½\82à¼\8bà½\80ྱིà¼\8bཤོà½\82à¼\8bà½\84ོསà¼\8bསྦས།',
+'tog-extendwatchlist' => 'ལà¾\9fà¼\8bà½\9eིà½\96à¼\8bà½\90ོà¼\8bརà¾\92ྱà¼\8bསà¾\90ྱེà½\91་ཏེ་ཉེ་ལམ་ཙམ་མིན་པར་བཟོ་བཅོས་ཡོངས་རྫོགས་སྟོན་ཅིག',
+'tog-usenewrc' => 'à½\89ེà¼\8bà½\96འིà¼\8bà½\96à½\9fོà¼\8bà½\96à½\85ོསà¼\8bà½\91à½\84à¼\8bà½\91à½\82སà¼\8bའà½\91ེà½\98སà¼\8bཤོà½\82à¼\8bà½\84ོསà¼\8bà½\80ྱིà¼\8bà½\96à½\85ོསà¼\8bའà½\82ྱུརà¼\8bརà¾\90ྱེà½\93à¼\8bà½\94སà¼\8bསྡེà¼\8bà½\9aà½\93à¼\8bà½\96à½\85ོསà¼\8bའà½\82ྱུརà¼\8bà½\95ྱིà½\93à¼\8bའà½\91ུà½\82à¼\8d',
 'tog-numberheadings' => 'རང་སྒྲིག་ཨང་རྟགས་འགོ་བརྗོད།',
-'tog-showtoolbar' => 'རྩོམ་སྒྲིག་ལག་ཆ་སྟོན།(JavaScript ཡི་བརྡ་ཆད་དགོས།)',
-'tog-editondblclick' => 'ཤོག་ངོས་རྩོམ་སྒྲིག་བྱེད་པར་ལན་གཉིས་རྡེབ།(JavaScript ཡི་བརྡ་ཆད་དགོས།)',
-'tog-rememberpassword' => 'ངའི་ནང་འཛུལ་བཤར་ལྟ་ཆས་འདི་རུ་མང་མཐའ་ཉིན $1 {{PLURAL:$1}} དྲན་པར་མཛོད།',
-'tog-watchcreations' => 'ངའི་ལྟ་ཐོའི་གྲས་སུ་གསར་བཟོ་བྱས་པ་ལ་ཤོག་ངོས་ཁ་སྣོན།',
-'tog-watchdefault' => 'ངའི་ལྟ་ཐོའི་གྲས་སུ་རྩོམ་སྒྲིག་བྱས་པ་ལ་ཤོག་ངོས་ཁ་སྣོན།',
-'tog-watchmoves' => 'ངའི་ལྟ་ཐོའི་གྲས་སུ་སྤོར་བ་ལ་ཤོག་ངོས་ཁ་སྣོན།',
-'tog-watchdeletion' => 'ངའི་ལྟ་ཐོའི་གྲས་སུ་དོར་བ་ལ་ཤོག་ངོས་ཁ་སྣོན།',
-'tog-previewontop' => 'རྩོམ་སྒྲིག་སྒྲོམ་གྱི་སྔོན་དུ་དཔེ་གཟུགས་སྟོན་པ།',
-'tog-previewonfirst' => 'ཐོག་མའི་རྩོམ་སྒྲིག་སྟེང་དུ་དཔེ་གཟུགས་སྟོན་པ།',
-'tog-enotifwatchlistpages' => 'ངའི་ལྟ་ཐོའི་ཤོག་ངོས་ལ་བཟོ་བཅོས་བྱུང་ཚེ་གློག་འཕྲིན་གཏང་རོགས།',
+'tog-showtoolbar' => 'རྩོམ་སྒྲིག་ལག་ཆ་སྟོན། (JavaScript ཡི་བརྡ་ཆད་དགོས།)',
+'tog-editondblclick' => 'ཤོག་ངོས་རྩོམ་སྒྲིག་བྱེད་པར་ལན་གཉིས་རྡེབ།',
+'tog-editsectiononrightclick' => 'དུམ་འཚམས་ཀྱི་འགོ་འརྗོད་ལ་འཐེབ་གཞོང་གཡས་པ་གནོན་ཏེ་དུམ་འཚམས་བཟོ་འཅོས་བྱེད་རོགས།',
+'tog-rememberpassword' => 'ངའི་ནང་འཛུལ་བཤར་ཆས་འདི་སྟེང་(མང་མཐར་ཉིན $1 དྲན་པར་མཛོད། )',
+'tog-watchcreations' => 'ངས་གསར་བཟོ་བྱས་པའི་ཤོག་ངོས་དང་ཡིག་ཆ་ཡར་འཇུག་བྱས་པ་རྣམས་ངའི་དགའ་འདེམས་ཐོ་ལ་སྣོན་རོགས།',
+'tog-watchdefault' => 'ངས་ཁ་སྣོན་བྱས་པའི་ཤོག་ངོས་དང་ཡིག་ཆ་རྣམས་ངའི་ལྟ་ཞིབ་ཐོ་ནང་སྣོན་རོགས།',
+'tog-watchmoves' => 'ངས་ཤོག་ངོས་དང་ཡིག་ཆ་ཕན་ཚུན་སྤོར་བ་རྣམས་ངའི་ལྟ་ཞིབ་ཐོའི་ནང་སྣོན་རོགས།',
+'tog-watchdeletion' => 'ངས་ཤོག་ངོས་དང་ཡིག་ཆ་སུབ་འདོར་བྱས་པ་རྣམས་ངའི་ལྟ་ཞིབ་ཐོའི་ནང་སྣོན་རོགས།',
+'tog-minordefault' => 'ཁ་སྣོན་རྩོམ་སྒྲིག་རྣམས་རང་འགུལ་གྱིས་རྩོམ་སྒྲིག་ཕལ་པར་རྟགས་རྒྱོབ་རོགས།',
+'tog-previewontop' => 'རྩོམ་སྒྲིག་སྒྲོམ་གྱི་སྟེང་སྔོན་ལྟའི་དཔེ་གཟུགས་སྟོན།',
+'tog-previewonfirst' => 'ཐེངས་དང་པོའི་རྩོམ་སྒྲིག་སྟེང་དུ་སྔོན་ལྟའི་དཔེ་གཟུགས་སྟོན།',
+'tog-enotifwatchlistpages' => 'ངའི་ལྟ་ཞིབ་ཐོ་ནང་གི་ཤོག་ངོས་དང་ཡིག་ཆ་རྣམས་ལ་འགྱུར་ལྡོག་བྱུང་ཚེ་ང་ལ་གློག་འཕྲིན་གཏོང་རོགས།',
 'tog-enotifusertalkpages' => 'ངའི་སྤྱོད་མིའི་གླེང་མོལ་ལ་བཟོ་བཅོས་བྱུང་ཚེ་གློག་འཕྲིན་གཏང་རོགས།',
-'tog-enotifminoredits' => 'རྩོམ་སྒྲིག་ཆུང་ཚགས་རིགས་ལའང་གློག་འཕྲིན་གཏོང་རོགས།',
+'tog-enotifminoredits' => 'རྩོམ་སྒྲིག་དང་ཡིག་ཆར་བཟོ་བཅོས་ཆུང་ཚགས་རིགས་བྱུང་ན་ཡང་གློག་འཕྲིན་གཏོང་རོགས།',
+'tog-enotifrevealaddr' => 'ངའི་གློག་འཕྲིན་ཁ་བྱང་འདི་བརྡ་ཐོའི་ཁ་བྱང་ནང་གསལ་སྟོན་བྱེད་རོགས།',
 'tog-shownumberswatching' => 'ཤོག་ངོས་ལ་ལྟ་བཞིན་པའི་སྤྱོད་མིའི་ཁ་གྲངས་སྟོན།',
 'tog-oldsig' => 'ད་ཡོད་མིང་རྟགས།',
-'tog-watchlisthideown' => 'ངའི་རྩོམ་སྒྲིག་རྣམས་ལྟ་ཐོ་ལས་སྦས་རོགས།',
-'tog-watchlisthideminor' => 'རྩོམ་སྒྲིག་ཕལ་བ་རྣམས་ལྟ་ཐོ་ལས་སྦས་རོགས།',
+'tog-watchlisthideown' => 'ངའི་རྩོམ་སྒྲིག་རྣམས་ལྟ་ཞིབ་ཐོ་ལས་སྦས་རོགས།',
+'tog-watchlisthidebots' => 'རང་འགུལ་འཕྱུལ་ཆས་ཀྱི་བཟོ་འཅོས་བྱས་པ་རྣམས་ངའི་ལྟ་ཞིབ་ཐོ་ལས་སྦས་རོགས།',
+'tog-watchlisthideminor' => 'རྩོམ་སྒྲིག་ཕལ་བ་རྣམས་ལྟ་ཞིབ་ཐོ་ལས་སྦས་རོགས།',
 'tog-watchlisthideliu' => 'ཐོ་འཛུལ་སྤྱོད་མིའི་རྩོམ་སྒྲིག་རྣམས་ལྟ་ཐོ་ལས་སྦས་རོགས།',
 'tog-ccmeonemails' => 'ངས་གཞན་ལ་བཏང་བའི་གློག་འཕྲིན་གྱི་འདྲ་བཤུས་སྐུར་རོགས།',
 'tog-showhiddencats' => 'སྦས་བའི་དཀར་ཆག་སྟོན་རོགས།',
 
-'underline-always' => 'à½\93à½\98à¼\8bཡà½\84à¼\8bà¼\8d',
-'underline-never' => 'à½\93à½\98à¼\8bཡà½\84à¼\8bà½\98ིà½\93།',
-'underline-default' => 'རà¾\92ྱསà¼\8bà½\96à¼\8bའà½\91ྲེà½\93à¼\8bà½\94།',
+'underline-always' => 'à½\91ུསà¼\8bརà¾\92ྱུà½\93à¼\8bà½\91ུà¼\8b',
+'underline-never' => 'à½\82à½\8fà½\93à¼\8bà½\93སà¼\8bà½\98à¼\8bà½\96ྱེà½\91།',
+'underline-default' => 'འཤརà¼\8bà½\86སà¼\8bà½\91à½\84à¼\8bརà¾\92ྱà½\96à¼\8bལà¾\97ོà½\84སà¼\8bརྣà½\98སà¼\8bརà½\84à¼\8bསོརà¼\8bà½\96à½\9eà½\82à¼\8bརོà½\82ས།',
 
 # Font style option in Special:Preferences
-'editfont-style' => 'རྩོམ་སྒྲིག་ཡིག་གཟུགས།',
-'editfont-default' => 'རà¾\92ྱསà¼\8bà½\94à¼\8bའà½\91ྲེà½\93à¼\8bà½\94།',
+'editfont-style' => 'རྩོà½\98à¼\8bསà¾\92ྲིà½\82à¼\8bà½\96à½\9fོà¼\8bའà½\85ོསà¼\8bà½\81ུལà¼\8bà½\82ྱིà¼\8bཡིà½\82à¼\8bà½\82à½\9fུà½\82སà¼\8d',
+'editfont-default' => 'འཤརà¼\8bà½\86སà¼\8bརà½\84à¼\8bསོརà¼\8bà½\96à½\9eà½\82།',
 'editfont-monospace' => 'བར་ཚད་མཉམ་པའི་ཡིག་གཟུགས།',
 'editfont-sansserif' => 'ཡིག་གཟུགས་རྭ་མེད།',
 'editfont-serif' => 'ཡིག་གཟུགས་རྭ་ཅན།',
@@ -82,18 +86,18 @@ $messages = array(
 'thu' => 'གཟའ་ཕུར་བུ།',
 'fri' => 'གཟའ་པ་སངས།',
 'sat' => 'གཟའ་སྤེན་པ།',
-'january' => 'ཟླ་དང་པོ།',
-'february' => 'ཟླ་གཉིས་པ།',
-'march' => 'ཟླ་གསུམ་པ།',
-'april' => 'ཟླ་བཞི་བ།',
-'may_long' => 'ཟྮ་ལྔ་བ།',
-'june' => 'ཟླ་དྲུག་པ།',
-'july' => 'ཟླ་བདུན་པ།',
-'august' => 'ཟླ་བརྒྱད་པ།',
-'september' => 'ཟླ་དགུ་བ།',
-'october' => 'ཟླ་བཅུ་བ།',
-'november' => 'ཟླ་བཅུ་གཅིག་པ།',
-'december' => 'ཟླ་བཅུ་གཉིས་པ།',
+'january' => 'à½\9fླà¼\8bà½\96à¼\8bà½\91à½\84à¼\8bà½\94ོà¼\8d',
+'february' => 'à½\9fླà¼\8bà½\96à¼\8bà½\82à½\89ིསà¼\8bà½\94à¼\8d',
+'march' => 'à½\9fླà¼\8bà½\96à¼\8bà½\82སུà½\98à¼\8bà½\94à¼\8d',
+'april' => 'à½\9fླà¼\8bà½\96à¼\8bà½\96à½\9eིà¼\8bà½\96à¼\8d',
+'may_long' => 'à½\9fྮà¼\8bà½\96à¼\8bལà¾\94à¼\8bà½\96à¼\8d',
+'june' => 'à½\9fླà¼\8bà½\96à¼\8bà½\91ྲུà½\82à¼\8bà½\94à¼\8d',
+'july' => 'à½\9fླà¼\8bà½\96à¼\8bà½\96à½\91ུà½\93à¼\8bà½\94à¼\8d',
+'august' => 'à½\9fླà¼\8bà½\96à¼\8bà½\96རà¾\92ྱà½\91à¼\8bà½\94à¼\8d',
+'september' => 'à½\9fླà¼\8bà½\96à¼\8bà½\91à½\82ུà¼\8bà½\96à¼\8d',
+'october' => 'à½\9fླà¼\8bà½\96à¼\8bà½\96à½\85ུà¼\8bà½\96à¼\8d',
+'november' => 'à½\9fླà¼\8bà½\96à¼\8bà½\96à½\85ུà¼\8bà½\82à½\85ིà½\82à¼\8bà½\94à¼\8d',
+'december' => 'à½\9fླà¼\8bà½\96à¼\8bà½\96à½\85ུà¼\8bà½\82à½\89ིསà¼\8bà½\94à¼\8d',
 'january-gen' => 'ཟླ་དང་པོ།',
 'february-gen' => 'ཟླ་གཉིས་པ།',
 'march-gen' => 'ཟླ་གསུམ་པ།',
@@ -106,9 +110,9 @@ $messages = array(
 'october-gen' => 'ཟླ་བཅུ་བ།',
 'november-gen' => 'ཟླ་བཅུ་གཅིག་པ།',
 'december-gen' => 'ཟླ་བཅུ་གཉིས་པ།',
-'jan' => 'ཟླ་དང་པོ།',
-'feb' => 'ཟླ་གཉིས་པ།',
-'mar' => 'ཟླ་གསུམ་པ།',
+'jan' => 'à½\9fླà¼\8bà½\96à¼\8bà½\91à½\84à¼\8bà½\94ོà¼\8d',
+'feb' => 'à½\9fླà¼\8bà½\96à¼\8bà½\82à½\89ིསà¼\8bà½\94à¼\8d',
+'mar' => 'à½\9fླà¼\8bà½\96à¼\8bà½\82སུà½\98à¼\8bà½\94à¼\8d',
 'apr' => 'ཟླ་བཞི་བ།',
 'may' => 'ཟླ་ལྔ་བ།',
 'jun' => 'ཟླ་དྲུག་པ།',
@@ -118,15 +122,28 @@ $messages = array(
 'oct' => 'ཟླ་བཅུ་བ།',
 'nov' => 'ཟླ་བཅུ་གཅིག་པ།',
 'dec' => 'ཟླ་བཅུ་གཉིས་པ།',
+'january-date' => 'ཟླ་བ་དང་པོ། $1',
+'february-date' => 'ཟླ་བ་གཉིས་པ། $1',
+'march-date' => 'ཟླ་བ་གསུམ་པ། $1',
+'april-date' => 'ཟླ་བ་བཞི་པ། $1',
+'may-date' => 'ཟླ་བ་ལྔ་པ། $1',
+'june-date' => 'ཟླ་བ་དྲུག་པ། $1',
+'july-date' => 'ཟླ་བ་བདུན་པ། $1',
+'august-date' => 'ཟླ་བ་བརྒྱད་པ། $1',
+'september-date' => 'ཟླ་བ་དགུ་པ། $1',
+'october-date' => 'ཟླ་བ་བཅུ་པ། $1',
+'november-date' => 'ཟླ་བ་བཅུ་གཅིག་པ། $1',
+'december-date' => 'ཟླ་བ་བཅུ་གཉིས་པ། $1',
 
 # Categories related messages
 'pagecategories' => '{{PLURAL:|སྡེ་ཚན་|སྡེ་ཚན་ $1}}',
 'category_header' => '"$1"ནང་་གི་ཤོག་ངོས།',
 'subcategories' => 'རིགས་གཏོགས།',
 'category-media-header' => '"$1"ནང་་གི་ཆ་འཕྲིན།',
-'category-empty' => "''སྡེ་ཚན་འདིའི་ནང་དུ་བར་སྐབས་སུ་ཤོག་ངོས་སམ་ཆ་འཕྲིན་མི་འདུག ''",
+'category-empty' => '<em> སྡེ་ཚན་འདིའི་ནང་དུ་བར་སྐབས་སུ་ཤོག་ངོས་སམ་བརྙན་རིས་མི་འདུག། </em>',
 'hidden-categories' => '|སྦས་བའི་སྡེ་ཚན།|སྦས་བའི་སྡེ་ཚན།}}{{PLURAL:$1',
 'hidden-category-category' => 'སྦས་བའི་སྡེ་ཚན།',
+'category-subcat-count' => '{{PLURAL:$2|སྡེ་ཙན་འདི་ནང་ཁྱོན་སྡོམས་པས་ $2 ནས་ གཤམ་གྱི་བྱེ་བྲག་སྡེ་ཚན།{{PLURAL:$1|subcategory|$1 subcategories}}ཙམ་འདུག།}}',
 'category-subcat-count-limited' => 'སྡེ་ཚན་འདིར་གཤམ་གྱི་བྱེ་བྲག་སྡེ་ཚན་{{PLURAL:$1|subcategory|$1 subcategories}}ཡོད།',
 'category-article-count' => '{{PLURAL:$2|སྡེ་ཚན་འདིར་གཤམ་གྱི་ཤོག་ངོས་ཁོ་ན་བསྡུས་ཡོད། |The following {{PLURAL:$1|page is|$1 pages are}} in this category, out of $2 total.}}',
 
@@ -135,7 +152,8 @@ $messages = array(
 'newwindow' => '(སྒེའུ་ཁུང་གསར་བར་ཕྱེ་བ།)',
 'cancel' => 'རྩིས་མེད།',
 'moredotdotdot' => 'དེ་ལས་མང་བ་་་',
-'mypage' => 'ངའི་ཤོག་ངོས།',
+'morenotlisted' => 'ཐོ་གཞུང་འདི་ཆ་ཚང་མེད།',
+'mypage' => 'ཤོག་ངོས།',
 'mytalk' => 'གཏམ་གླེང།',
 'anontalk' => 'IP གནས་ཡུལ་འདི་ལ་གླེང་མོལ།',
 'navigation' => 'ཕྱོགས་ཁྲིད།',
@@ -143,7 +161,8 @@ $messages = array(
 
 # Cologne Blue skin
 'qbfind' => 'འཚོལ་བ།',
-'qbedit' => 'རྩོམ་སྒྲིག',
+'qbbrowse' => 'བཤེར་འཚོལ།',
+'qbedit' => 'བཟོ་འཅོས།',
 'qbpageoptions' => 'ཤོག་ངོས་འདི།',
 'qbmyoptions' => 'ངའི་ཤོག་ངོས།',
 'faq' => 'རྒྱུན་ལྡན་དྲི་བ།',
@@ -153,7 +172,7 @@ $messages = array(
 'vector-action-addsection' => 'བརྗོད་གཞི་ཁ་སྣོན།',
 'vector-action-delete' => 'སུབས།',
 'vector-action-move' => 'སྤོར་བ།',
-'vector-action-protect' => 'སྲུà½\84à¼\8bསà¾\90ྱོà½\96།',
+'vector-action-protect' => 'འà½\82ོà½\82à¼\8bསྲུà½\84།',
 'vector-action-undelete' => 'བསུབས་པ་གསོ་བ།',
 'vector-action-unprotect' => 'སྲུང་སྐྱོབ་གློད་པ།',
 'vector-view-create' => 'གསར་བཟོ།',
@@ -161,22 +180,24 @@ $messages = array(
 'vector-view-history' => 'ལོ་རྒྱུས་ལ་ལྟ་བ།',
 'vector-view-view' => 'ཀློག་པ།',
 'vector-view-viewsource' => 'ཁུངས་ལ་ལྟ་བ།',
-'actions' => 'བྱ་འགུལ།',
-'namespaces' => 'མིང་འགོད་ས།',
+'actions' => 'བྱ་སྤྱོད།',
+'namespaces' => 'མིང་གནས།',
+'variants' => 'འགྱུར་ཚད།',
 
+'navigation-heading' => 'ཕྱོགས་ཁྲིད་འདེམས་བྱང།',
 'errorpagetitle' => 'ནོར་འཁྲུལ།',
 'returnto' => '$1 ལ་བསྐྱར་ལོག་བྱེད་པ།',
 'tagline' => 'ཡོང་ཁུངས་{{SITENAME}}',
-'help' => 'རོà½\82སà¼\8bརà½\98།',
+'help' => 'à½\95à½\93à¼\8bà½\82ྲོà½\82ས།',
 'search' => 'འཚོལ་བ།',
-'searchbutton' => 'འà½\9aོལà¼\8bà½\96à¼\8d',
+'searchbutton' => 'འཚོལ།',
 'go' => 'སོང་།',
 'searcharticle' => 'འཚོལ།',
 'history' => 'ཤོག་ངོས་ལོ་རྒྱུས།',
 'history_short' => 'ལོ་རྒྱུས།',
 'updatedmarker' => 'ཐེངས་སྔོན་མའི་ལྟ་ཀློག་རྗེས་ཀྱི་བཟོ་བཅོས།',
-'printableversion' => 'à½\91à½\94རà¼\8bà½\90ུà½\96à¼\8bà½\94།',
-'permalink' => 'རà¾\9fà½\82à¼\8bà½\96རà¾\9fà½\93à¼\8bà½\82ྱིà¼\8bà½\91ྲà¼\8bའà½\96ྲེལ།',
+'printableversion' => 'à½\94རà¼\8bའà½\91ེà½\96སà¼\8bརུà½\84à¼\8bà½\96འིà¼\8bའà½\82ྱུར།',
+'permalink' => 'à½\96རà¾\9fà½\93à¼\8bའà½\87à½\82སà¼\8bà½\80ྱིà¼\8bསྦྲེལà¼\8bà½\98à½\90ུà½\91།',
 'print' => 'དཔར་བ།',
 'view' => 'ལྟ་བ།',
 'edit' => 'རྩོམ་སྒྲིག',
@@ -185,22 +206,23 @@ $messages = array(
 'create-this-page' => 'ཤོག་ངོས་འདི་སྐྲུན་པ།',
 'delete' => 'སུབས།',
 'deletethispage' => 'ཤོག་ངོས་འདི་འདོར་བ།',
-'undelete_short' => '{{PLURAL:$1|one edit|$1edits}} མ་འདོར་ཞིག',
+'undeletethispage' => 'ཤོག་ངོས་འདི་མི་སུབ་རོགས།',
+'undelete_short' => '{{PLURAL:$1|བཟོ་འཅོས་གཅིག་|བཟོ་འཅོས་ $1}}མ་བསུབ་རོགས།',
 'viewdeleted_short' => '{{བསུབས་པའི་རྩོམ་སྒྲིག PLURAL:$1|བསུབས་པའི་རྩོམ་སྒྲིག $1}}ལ་ལྟ་བ།',
-'protect' => 'སྲུà½\84à¼\8bà½\96།',
+'protect' => 'འà½\82ོà½\82à¼\8bསྲུà½\84།',
 'protect_change' => 'སྒྱུར་བཅོས།',
 'protectthispage' => 'ཤོག་ངོས་འདི་སྲུང་བ།',
 'unprotect' => 'སྲུང་སྐྱོབ་བཅོས་བསྒྱུར།',
 'unprotectthispage' => 'ངོ་ཤོག་འདིའི་སྲུང་སྐྱོབ་བཅོས་བསྒྱུར།',
 'newpage' => 'ཤོག་ངོས་གསར་བ།',
 'talkpage' => 'ཤོག་ངོས་འདིར་གྲོས་སྡུར།',
-'talkpagelinktext' => 'à½\82ླེà½\84à¼\8bà½\98ོལ།',
+'talkpagelinktext' => 'à½\82à½\8fà½\98à¼\8bà½\82ླེà½\84།',
 'specialpage' => 'དམིགས་གསལ་ཤོག་ངོས།',
 'personaltools' => 'སྒེར་ཀྱི་ལག་ཆ།',
 'postcomment' => 'སྡེ་ཚན་གསར་བ།',
 'articlepage' => 'ནང་དོན་ཤོག་ངོས་ལ་ལྟ་བ།',
 'talk' => 'གྲོས་བསྡུར།',
-'views' => 'à½\98à½\90ོà½\84à¼\8bརིས།',
+'views' => 'ལà¾\9fà¼\8bà½\9eིà½\96།',
 'toolbox' => 'ལག་ཆའི་སྒམ།',
 'userpage' => 'སྤྱོད་མིའི་ཤོག་ངོས་ལ་ལྟ་བ།',
 'projectpage' => 'ལས་འཆར་ཤོག་ངོས་ལ་ལྟ་བ།',
@@ -210,61 +232,75 @@ $messages = array(
 'viewhelppage' => 'རོགས་རམ་ཤོག་ངོས་ལ་ལྟ་བ།',
 'categorypage' => 'སྡེ་ཚན་ཤོག་ངོས་སྟོན་ཅིག',
 'viewtalkpage' => 'གྲོས་མོལ་ལ་ལྟ་བ།',
-'otherlanguages' => 'སྐད་རིགས་གཞན།',
+'otherlanguages' => 'སà¾\90à½\91à¼\8bརིà½\82སà¼\8bà½\82à½\9eà½\93à¼\8bà½\90ོà½\82à¼\8d',
 'redirectedfrom' => '$1 ནས་ཁ་ཕྱོགས་བསྐྱར་དུ་བཟོས་པ།',
 'redirectpagesub' => 'རིམ་འགྲེམ་ཤོག་ངོས།',
-'lastmodifiedat' => 'à½\91ྲà¼\8bà½\84ོསà¼\8bའà½\91ིà¼\8bཡིà¼\8bà½\96à½\9fོà¼\8bà½\96à½\85ོསà¼\8bà½\98à½\90འà¼\8bà½\98à¼\8b$1 $2 ལ་རེད།',
+'lastmodifiedat' => 'ཤོà½\82à¼\8bà½\84ོསà¼\8bའà½\91ིà¼\8bཡིà¼\8bà½\96à½\9fོà¼\8bà½\96à½\85ོསà¼\8bà½\98à½\90འà¼\8bà½\98à¼\8b$1 à½\80ྱིà¼\8b $2 ལ་རེད།',
 'protectedpage' => 'སྲུང་སྐྱོབ་བྱས་པའི་ཤོག་ངོས།',
 'jumpto' => 'གནས་སྤོ།',
 'jumptonavigation' => 'ཕྱོགས་ཁྲིད།',
 'jumptosearch' => 'འཚོལ།',
+'view-pool-error' => 'དགོངས་པ་མ་ཚོམས་རོགས། སྤྱོད་མི་མང་དག་ཞིག་གི་ཤོག་ངོས་འདིར་གཟིགས་ཞིང་འདུག་པས། གནས་སྐབས་རིང་ཞབས་ཞུ་འཕྲུལ་ཆས་ཐེག་བརྒལ་བྱས་འདུག། 
+ཤོག་ངོས་འདིར་བསྐྱར་དུ་མ་གཟིགས་གོང་ཡུད་ཙམ་རིང་སྒུག་རོགས་གནང། $1',
+'pool-timeout' => 'ཟྭ་རྒྱག་སྒུག་ཡུན་གྱི་དུས་ཚོད་རྫོགས་སོང།',
+'pool-queuefull' => 'སྤྱི་པའི་ཐེབས་རྩའི་བསྟར་པ་ཁེངས་འདུག།',
 'pool-errorunknown' => 'ངོས་མ་ཟིན་པའི་ནོར་འཁྲུལ།',
 
 # All link text and link target definitions of links into project namespace that get used by other message strings, with the exception of user group pages (see grouppage).
-'aboutsite' => '{{SITENAME}}à½\84ེà½\91à¼\8bà½\80ྱི་སྐོར།',
-'aboutpage' => 'Project: ཡི་སྐོར།',
+'aboutsite' => '{{SITENAME}}ཡི་སྐོར།',
+'aboutpage' => 'Project:སྐོར།',
 'copyright' => 'དྲ་བའི་ནང་དོན་$1སྟེང་དུ་ཡོད།',
 'copyrightpage' => '{{ns:project}}:པར་དབང་།',
-'currentevents' => 'à½\91à¼\8bལà¾\9fའིà¼\8bà½\96ྱà¼\8bà½\96།',
-'currentevents-url' => 'Project:à½\91à¼\8bལà¾\9fའིà¼\8bà½\96ྱà¼\8bà½\96།',
-'disclaimers' => 'à½\91à½\82à½\82à¼\8bà½\96ྱ།',
-'disclaimerpage' => 'Project:སྤྱིའིà¼\8bà½\91à½\82à½\82à¼\8bà½\96ྱ།',
+'currentevents' => 'à½\91à¼\8bལà¾\9fའིà¼\8bà½\91ོà½\93à¼\8bà½\82à½\93à½\91།',
+'currentevents-url' => 'Project:à½\91à¼\8bལà¾\9fའིà¼\8bà½\91ོà½\93à¼\8bà½\82à½\93à½\91།',
+'disclaimers' => 'à½\96à½\91à½\82à¼\8bསྤྲོà½\91à¼\8bའà½\91ོརà¼\8bà½\98à½\81à½\93།',
+'disclaimerpage' => 'Project:ཡོà½\84སà¼\8bà½\81ྱà½\96à¼\8bà½\80ྱིà¼\8bà½\96à½\91à½\82à¼\8bསྤྲོà½\91à¼\8bà½\81ེà¼\8bà½\91à½\96à½\84à¼\8bརྩོà½\91à¼\8bལེà½\93།',
 'edithelp' => 'རྩོམ་སྒྲིག་རོགས་རམ།',
-'helppage' => 'Help:à½\93à½\84à¼\8bà½\91ོà½\93à¼\8b',
-'mainpage' => 'གཙོ་ངོས།',
-'mainpage-description' => 'གཙོ་ངོས།',
+'helppage' => 'Help:à½\93à½\84à¼\8bà½\91ོà½\93à¼\8d',
+'mainpage' => 'à½\82à½\99ོà¼\8bà½\82à½\93à½\91à¼\8bཤོà½\82à¼\8bà½\84ོསà¼\8d',
+'mainpage-description' => 'à½\82à½\99ོà¼\8bà½\82à½\93à½\91à¼\8bཤོà½\82à¼\8bà½\84ོསà¼\8d',
 'policy-url' => 'Project: སྒྲིག་གཞི།',
-'portal' => 'ཁོངས་མི་འདུ་ར།',
-'privacy' => 'སྒེར་ཁྲིམས།',
-'privacypage' => 'Project: སྒེར་ཁྲིམས།',
+'portal' => 'ཁོངས་མི་གཞུང་སྒོ།',
+'portal-url' => 'Project:ཁོངས་མི་འདུ་རའི་གཞུང་སྒོ་',
+'privacy' => 'གསང་དོན་གན་རྒྱ།',
+'privacypage' => 'Project: གསང་དོན་གན་རྒྱ།',
 
 'badaccess' => 'ཆོག་ཆན་ལ་ནོར་འཁྲུལ།',
 
+'versionrequired' => 'ཝེ་ཁེ་བརྒྱུད་ལམ་གྱི་འགྱུར།  MediaWiki Version $1 དེ་དགོས་འདུག།',
+'versionrequiredtext' => 'ཤོག་ངོས་འདི་བེད་སྤྱོད་པར་ཝེ་ཁེ་བརྒྱུད་ལམ་གྱི་འགྱུར་$1འདི་དགོས། [[Special:འགྱུར། |འགྱུར་ཤོག་ངོས།]] འདེར་གཟིགས་རོགས།',
+
 'ok' => 'འགྲིག',
-'retrievedfrom' => '"$1"ལསà¼\8bརà¾\99ེà½\91à¼\8bà½\94།',
+'retrievedfrom' => '"$1"ལསà¼\8bསླརà¼\8bརà¾\99ེà½\91à¼\8bསོà½\84།',
 'youhavenewmessages' => 'ཁྱེད་ལ་འཕྲིན་གསར་$1($2)ཡོད།',
 'youhavenewmessagesmulti' => 'ཁྱེད་ལ་ $1 སྟེང་དུ་འཕྲིན་ཡིག་འདུག',
-'editsection' => 'རྩོམ་སྒྲིག',
+'editsection' => 'རྩོམ་སྒྲིག',
 'editold' => 'རྩོམ་སྒྲིག',
 'viewsourceold' => 'ཁོངས་ལ་ལྟ་བ།',
 'editlink' => 'བཟོ་བཅོས།',
 'viewsourcelink' => 'ཁོངས་ལ་ལྟ་བ།',
-'editsectionhint' => 'རྩོམ་སྒྲིག་སྡེ་ཚན།$1',
-'toc' => 'à½\9fུརà¼\8bà½\98à½\86ན།',
+'editsectionhint' => 'རྩོམ་སྒྲིག་སྡེ་ཚན།$1',
+'toc' => 'à½\93à½\84à¼\8bà½\91ོན།',
 'showtoc' => 'སྟོན།',
 'hidetoc' => 'སྦས།',
 'collapsible-collapse' => 'རྡིབ་སྐྱོན།',
-'viewdeleted' => ' $1 ལ་ལྟའམ།',
+'collapsible-expand' => 'རྒྱ་སྐྱེད།',
+'thisisdeleted' => '$1 ལ་ལྟ་བའམ་རང་ལོགས་བྱེད་རོགས།',
+'viewdeleted' => ' $1 ལ་ལྟ་དགོས་སམ།',
+'feedlinks' => 'འདྲན་ཆས། :',
 'site-rss-feed' => '$1 ཡི་RSS འབྱུང་ཁུངས།',
-'site-atom-feed' => '$1 ཡི་Atom འབྱུང་ཁུངས།',
+'site-atom-feed' => '$1 ཡི་ཆ་ཤས་ཡ་ལན།',
 'page-rss-feed' => '$1 ཡི་RSS འབྱུང་ཁུངས།',
 'page-atom-feed' => '$1 ཡི་Atom འབྱུང་ཁུངས།',
-'red-link-title' => '$1 ( ཤོག་ངོས་མེད་པ།)',
+'red-link-title' => '$1 (ཤོག་ངོས་མེད་པ།)',
+'sort-descending' => 'མར་རིམ་སྒྲིགས་',
+'sort-ascending' => 'ཡར་རིམ་སྒྲིགས།',
 
 # Short words for each namespace, by default used in the namespace tab in monobook
-'nstab-main' => 'རྩོà½\98à¼\8bཡིà½\82',
+'nstab-main' => 'ཤོà½\82à¼\8bà½\84ོསà¼\8d',
 'nstab-user' => 'སྤྱོད་མིའི་ཤོག་ངོས།',
-'nstab-special' => 'དམིཊ་གསལ་ཤོག་ངོས།',
+'nstab-media' => 'འཕྲིན་ལམ་ཤོག་ངོས།',
+'nstab-special' => 'ཆེད་ལས་ཤོག་ངོས།',
 'nstab-project' => 'ལས་འཆར་ཤོག་ངོས།',
 'nstab-image' => 'ཡིག་ཆ།',
 'nstab-mediawiki' => 'སྐད་ཆ།',
@@ -279,6 +315,9 @@ $messages = array(
 # General errors
 'error' => 'ནོར་འཁྲུལ།',
 'readonly' => 'གཞི་གྲངས་མཛོད་ཟྭ་བརྒྱབ་པ།',
+'missing-article' => 'གཞི་གྲངས་མཛོད་ནང་ཤོག་ངོས་ཀྱི་ཡི་གེ་བཙལ་ཐུབ་ཀྱི་མི་འདུག་པས། "$1" $2 
+ཕལ་ཆེར་འདི་གཤམ་ཀྱི་འགོག་རྐྱེན་ལོ་རྒྱུས་སུབ་པ་འམ་དུས་ཡོལ་ཀྱི་ཁྱད་པར་སོགས་ཀྱི་རྒྱུ་རྐྱེན་ཡིན།
+གལ་སྲིད་དེ་ལྟར་མིན་ཚེ། ཕལ་ཆེར་ཁྱེད་ཀྱི་ནོར་སྐྱོན་འཙལ་རྙེད་བྱང་བས།  [[Special:ListUsers/sysop|administrator]], དྲ་རྒྱའི་ས་ཚིགས་འདི་ཐོག་ཞུ་ཡིག་འབུལ་གནང་ཡོང་བ་མཁྱེན།',
 'internalerror' => 'ནང་ལོག་ནོར་སྐྱོན།',
 'internalerror_info' => 'ནང་ལོགས་ནོར་སྐྱོན། $1',
 'filecopyerror' => '"$1" "$2"ལ་འདྲ་བཤུ་བྱེད་མ་ཐུབ།',
@@ -296,7 +335,7 @@ $messages = array(
 # Login and logout pages
 'yourname' => 'སྤྱོད་མིང་།',
 'yourpassword' => 'ལམ་ཡིག',
-'yourpasswordagain' => 'ལà½\98à¼\8bཡིà½\82à¼\8bསà¾\90ྱརà¼\8bà½\82à½\8fà½\82སà¼\8bà½\96ྱོས།',
+'yourpasswordagain' => 'à½\82སà½\84à¼\8bà½\96འིà¼\8bཨà½\84à¼\8bà½\84ོསà¼\8bའà½\9bིà½\93à¼\8bà½\82à½\93à½\84à¼\8bརོà½\82ས།',
 'remembermypassword' => 'ངའི་ལམ་ཡིག་འདིར་(མང་མཐའ་ཉིན $1 {{PLURAL:$1}}) དྲན་པར་བྱས།',
 'login' => 'ནང་འཛུལ།',
 'nav-login-createaccount' => 'ནང་འཛུལ། / ཐོ་འགོད།',
@@ -307,7 +346,9 @@ $messages = array(
 'notloggedin' => 'ནང་འཛུལ་བྱས་མེད།',
 'nologinlink' => 'ཐོ་ཞིག་འགོད་པ།',
 'createaccount' => 'ཐོ་འགོད།',
+'gotaccount' => '$1 སྔོན་ཚུད་ནས་རྩིས་ཁྲ་ཡོད་དམ།',
 'gotaccountlink' => 'ནང་འཛུལ།',
+'userlogin-resetlink' => 'ཁྱེད་ཀྱི་ནང་འཛུལ་ཀྱི་ཞིབ་ཕྲའི་གནད་དོན་བརྗེད་འདུག་གམ།',
 'createaccountmail' => 'གློག་འཕྲིན་སྤྱད་དེ།',
 'createaccountreason' => 'རྒྱུ་མཚན།',
 'badretype' => 'ལམ་ཡིག་གང་བཅུག་པ་ཐོ་ཐུག་མ་བྱུང་།',
@@ -319,12 +360,12 @@ $messages = array(
 'login-userblocked' => 'སྤྱོད་མི་འདི་བཀག་འགོག་བྱས་པས་ནང་འཛུལ་གྱི་ཆོག་མཆན་མེད།',
 'wrongpassword' => 'ལམ་ཡིག་ནོར་འདུག བསྐྱར་དུ་ཚོད་ལྟ་བྱོས།',
 'wrongpasswordempty' => 'ལམ་ཡིག་སྟོང་པ་རེད། བསྐྱར་དུ་ཚོད་ལྟ་བྱོས།',
-'mailmypassword' => 'à½\82ློà½\82à¼\8bའà½\95ྲིà½\93à¼\8bལà½\98à¼\8bཡིà½\82à¼\8bà½\82སརà¼\8bà½\96།',
+'mailmypassword' => 'à½\82སà½\84à¼\8bà½\96འིà¼\8bཨà½\84à¼\8bà½\82ྲà½\84སà¼\8bà½\96སà¾\90ྱརà¼\8bà½\96à½\9fོà¼\8bà½\82à½\93à½\84à¼\8bརོà½\82ས།',
 'loginlanguagelabel' => 'སྐད་རིགས། $1',
 
 # Change password dialog
 'changepassword' => 'ལམ་ཡིག་བརྗེ་བ།',
-'resetpass_announce' => 'à½\81ྱེà½\91à¼\8bà½\80ྱིསà¼\8bà½\84à¼\8bà½\9aོསà¼\8bà½\96à½\8fà½\84à¼\8bà½\96འིà¼\8bà½\82à½\93སà¼\8bསà¾\90à½\96སà¼\8bལà½\98à¼\8bཡིà½\82à¼\8bལà¼\8bà½\96རà¾\9fེà½\93à¼\8bà½\93སà¼\8bà½\93à½\84à¼\8bའà½\9bུལà¼\8bà½\96ྱསà¼\8bའà½\91ུà½\82 à½\93à½\84à¼\8bའà½\9bུལà¼\8bà½\86à¼\8bà½\9aà½\84à¼\8bà½\96à¼\8bà½\96ྱེà½\91à¼\8bà½\94རà¼\8bའà½\91ིརà¼\8bà½\84ེསà¼\8bà½\94རà¼\8bà½\91ུà¼\8bལà½\98à¼\8bཡིà½\82à¼\8bà½\82སརà¼\8bà½\96à¼\8bའà½\87ུà½\82à¼\8bà½\91à½\82ོས།',
+'resetpass_announce' => 'à½\93à½\84à¼\8bའà½\9bུལà¼\8bà½\96ྱེà½\91à¼\8bà½\94རà¼\8d à½\81ྱེà½\91à¼\8bà½\80ྱིསà¼\8bà½\82སà½\84à¼\8bà½\96འིà¼\8bཨà½\84à¼\8bà½\82སརà¼\8bà½\94à¼\8bà½\9eིà½\82à¼\8bའà½\87ུà½\82à¼\8bརོà½\82ས།',
 'oldpassword' => 'ལམ་ཡིག་རྙིང་བ།',
 'newpassword' => 'ལམ་ཡིག་གསར་བ།',
 'retypenew' => 'ལམ་ཡིག་གསར་བ་བསྐྱར་འཇུག་བྱོས།',
@@ -360,6 +401,7 @@ $messages = array(
 'headline_tip' => 'རིམ་པ། ༢ འགོ་ཕྲེང་།',
 'nowiki_sample' => 'རྣམ་བཞག་མེད་པའི་ཡི་གེ་འདྲེན་པ།',
 'nowiki_tip' => 'ཝེ་ཁེའི་རྣམ་གཞག་དོར་བ།',
+'image_tip' => 'བཙུད་འཇུག་ཡིག་ཆ།',
 'media_tip' => 'ཡིག་ཆ་སྦྲེལ་མཐུད།',
 'sig_tip' => 'མིང་རྟགས་མཉམ་དུ་ཟླ་ཚེས་ཐེལ་ཙེ།',
 'hr_tip' => 'ཐད་ཐིག ༼ཆུད་ཟོས་མེད་པར།༽',
@@ -394,13 +436,17 @@ $messages = array(
 'templatesused' => 'ཤོག་ངོས་འདིར་སྤྱད་པའི་ {{PLURAL:$1|དཔེ་པང་།}}',
 'template-protected' => 'སྲུང་སྐྱོབ་འོག་ཡོད་པ།',
 'nocreate-loggedin' => 'ཤོག་ངོས་གསར་བཟོའི་ཆོག་མཆན་མི་འདུག',
+'permissionserrorstext-withaction' => 'གཤམ་ཀྱི་ {{PLURAL:$1|རྒྱུ་རྐྱེན་}}འོག་ཁྱེད་ལ་ $2 ཆོག་མཆན་མིན་འདུག་པས།',
 'recreate-moveddeleted-warn' => "'''ཉེན་བརྡ་:རང་གིས་སུབ་ཚར་བའི་ཤོག་ལེ་ཞིག་བསྐྱར་བཟོ་བྱེད་ཀྱི་འདུག་ '''
 ཁྱེད་རང་གལ་སྲིད་མུ་མཐུད་ཤོག་ལེ་འདི་བཟོ་ཅོས་བྱེད་འདོད་ན་སྟབས་བདེ་ཞིག་ལ་ང་ཚོས་སུབ་བཟིན་པའི་ཤོག་ལེ་འདིར་ཉར་ཡོད།",
 
 # History pages
 'viewpagelogs' => 'ཤོག་ངོས་འདིའི་ཉིན་ཐོ་ལ་ལྟ་བ།',
+'currentrev-asof' => 'མཐའ་འཇུག་ཀྱི་ཞིབ་བཤེར། $1',
 'revisionasof' => '$1 ལ་བཅོས་པ།',
 'previousrevision' => ' ← བཟོ་བཅོས་སྔ་མ།',
+'nextrevision' => 'ཞིབ་བཤེར་གསར་བ་ཁག།',
+'currentrevisionlink' => 'ཉེ་བའི་ཆར་གྱི་ཞིབ་བཤེར།',
 'cur' => 'ད་ལྟ།',
 'next' => 'རྗེས་མ།',
 'last' => 'མཐའ་མ།',
@@ -442,7 +488,8 @@ $messages = array(
 'nextn' => 'རྗེས་མ་{{PLURAL:$1|$1}}',
 'shown-title' => 'མིག་སྔར་སྟོན་པ། $1{{PLURAL:$1|གྲུབ་འབྲས།}}ཤོག་ངོས་ལྟར།',
 'viewprevnext' => '($1 {{int:pipe-separator}} $2) ($3)ལ་ལྟ་བ།',
-'searchmenu-new' => 'ལྦེ་ཁེ་སྟེང་ལ་ཤོག་ལེ་ [[:$1]]བཟོས།',
+'searchmenu-new' => 'ཝེ་ཁི་སྟེང་ལ་ <strong>ཤོག་ངོས་གསར་པ་</strong> "[[:$1]]" བཟོས། {{PLURAL:$2|0=|ཁྱེད་ཀྱི་འཚོལ་ཞིབ་བྱས་པའི་ཤོག་ངོས་རྣམས་ལ་ཡང་གཟིགས་རོགས།.|མ་ཟད་འཚོལ་ཞིབ་བྱས་པའི་གྲུབ་འབྲས་གཞན་རྣམས་ལ་ཡང་གཟིགས་རོགས།}}',
+'searchprofile-articles' => 'ནང་དོན་ཤོག་ངོས།',
 'searchprofile-project' => 'རོགས་རམ་དང་འཆར་གཞིའི་ཤོག་ངོས་',
 'searchprofile-everything' => 'ཚང་མ་',
 'searchprofile-advanced' => 'མཐོ་རིམ་',
@@ -450,7 +497,7 @@ $messages = array(
 'searchprofile-project-tooltip' => '$1ནང་དུ་འཚོལ་བ།',
 'searchprofile-images-tooltip' => 'ཡིག་ཆ་འཚོལ་བ།',
 'searchprofile-everything-tooltip' => 'བརྗོད་དོན་ཚང་མ་འཚོལ་གཞིབ་བྱེད་(གྲོས་མེས་ཤོག་ངོས་ཡང་འཚུད་པ་)',
-'search-result-size' => '$1({{PLURAL:$2|1 word|$2 words}})',
+'search-result-size' => '$1({{PLURAL:$2|1 ཚིག། |$2 ཚིག།}})',
 'search-redirect' => '($1རིམ་འགྲེམ།)',
 'search-section' => '(ཚན་པ $1)',
 'search-suggest' => '$1 ལ་ཟེར་བ་ཡིན་ནམ།',
@@ -458,6 +505,7 @@ $messages = array(
 'search-interwiki-default' => '$1ལས་རྙེད་པ།',
 'search-interwiki-more' => '(དེ་ལས་མང་བ།)',
 'search-relatedarticle' => 'འབྲེལ་ཡོད།',
+'searchrelated' => 'འབྲེལ་ཡོད།',
 'searchall' => 'ཚང་མ།',
 'search-nonefound' => 'ཁྱེད་ཀྱི་འདྲི་ཞིབ་དང་མཐུན་པའི་ལན་མི་འདུག་',
 'powersearch-legend' => 'ཞིབ་ཏུ་འཚོལ་བ།',
@@ -483,7 +531,7 @@ $messages = array(
 'searchresultshead' => 'འཚོལ།',
 'stub-threshold-disabled' => 'ནུས་མེད་དུ་བཟོས་ཟིན།',
 'timezoneregion-africa' => 'ཨ་ཧྥི་རི་ཀ',
-'youremail' => 'à½\91ྲà¼\8bའà½\95ྲིà½\93à¼\8d *:',
+'youremail' => 'à½\82ློà½\82à¼\8bའà½\95ྲིà½\93à¼\8d:',
 'username' => 'དྲ་མིང་།:',
 'uid' => 'ནང་འཛུལ་ཐོ་མིང་།',
 'yourrealname' => 'དངོས་མིང་།',
@@ -493,6 +541,8 @@ $messages = array(
 'gender-male' => 'ཕོ།',
 'gender-female' => 'མོ།',
 'email' => 'དྲ་འཕྲིན།',
+'prefs-help-email' => 'གློག་འཕྲིན་ཁ་བྱང་ནི་རང་མོས་ཡིན། ཡིན་ན་འང་གལ་སྲིད་ཁྱེད་ཀྱི་གསང་བའི་ཨང་གྲངས་འརྗེད་པ་སོགས་བྱུང་ཚེ། གསང་བའི་ཨང་བསྐྱར་སྒྲིག་སྐབས་ངེས་པར་དུ་དགོས།',
+'prefs-help-email-others' => 'ཁྱེད་ཀྱི་ཐད་ཀར་གློག་འཕྲིན་འམ་ཡང་ན་འགྲོ་གླེང་ཤོག་ངོས་བརྒྱུད་སྤྱོད་མི་གཞན་རྣམས་ཀྱི་ཁྱེད་ལ་འབྲེལ་བ་བྱེད་ཐུབ། ཁྱེད་རང་གི་གློག་འཕྲིན་ཁ་བྱང་སྤྱོད་མི་གཞན་གྱི་འབྲེལ་བ་བྱེད་སྐབས་གསང་གཏོལ་བྱེད་མི་སྲིད།',
 'prefs-info' => 'རྨང་གཞིའི་གནས་ཚུལ།',
 'prefs-signature' => 'མིང་རྟགས།',
 
@@ -523,7 +573,7 @@ $messages = array(
 
 # Associated actions - in the sentence "You do not have permission to X"
 'action-read' => 'ཤོག་ངོས་འདི་ཀློག་པ།',
-'action-edit' => 'ཤོà½\82à¼\8bà½\84ོསà¼\8bའà½\91ིà¼\8bརྩོà½\98à¼\8bསà¾\92ྲིà½\82à¼\8bà½\96ྱེà½\91à¼\8bà½\94།',
+'action-edit' => 'ཤོà½\82à¼\8bà½\84ོསà¼\8bའà½\91ིà¼\8bརྩོà½\98à¼\8bསà¾\92ྲིà½\82à¼\8bà½\96ྱེà½\91à¼\8bà½\91à½\84།',
 'action-createpage' => 'ཤོག་ངོས་གསར་བཟོ།',
 'action-move' => 'ཤོག་ངོས་འདི་སྤོར་ཅིག',
 'action-movefile' => 'ཡིག་ཆ་འདི་སྤོར་ཅིག',
@@ -539,13 +589,14 @@ $messages = array(
 'action-userrights-interwiki' => 'ཝེ་ཁེ་གཞན་གྱི་སྤྱོད་མི་ཚོའི་སྤྱོད་མིའི་ཐོབ་ཐང་རྩོམ་སྒྲིག་བྱེད་པ།',
 
 # Recent changes
+'nchanges' => '$1 {{PLURAL:$1|འགྱུར་བཅོས།|འགྱུར་བཅོས།}}',
 'recentchanges' => 'ཉེ་བའི་བཟོ་བཅོས།',
 'recentchanges-legend' => 'ཉེ་བའི་བཟོ་བཅོས་འདེམས་ཚན།',
 'recentchanges-label-newpage' => 'རྩོམ་སྒྲིག་འདིས་ཤོག་ངོས་གསར་བ་ཞིག་བཟོས་འདུག',
 'recentchanges-label-minor' => 'འདི་ནི་རྩོམ་སྒྲིག་ཕལ་བ་ཞིག་ཡིན།',
 'rclistfrom' => '$1 ལས་འགོ་བཙུགས་ཏེ་འགྱུར་བཅོས་གསར་བ་སྟོན་ཅིག',
 'rcshowhideminor' => '$1 རྩོམ་སྒྲིག་ཕལ་བ།',
-'rcshowhideliu' => 'ཐོ་འཛུལ་བྱས་པའི་སྤྱོད་མི་ $1',
+'rcshowhideliu' => '$1 ཐོ་འགོད་སྤྱོད་མི།',
 'rcshowhideanons' => 'མིང་མེད་སྤྱོད་མི $1',
 'rcshowhidemine' => '$1ངའི་རྩོམ་སྒྲིག',
 'rclinks' => 'འདས་བའི་ཉིན་ $2 <br />$3 ནང་ཚུན་གྱི་བཟོ་བཅོས་གཞུག་མ་ $1 སྟོན་ཅིག',
@@ -555,6 +606,7 @@ $messages = array(
 'show' => 'སྟོན།',
 'minoreditletter' => 'སྒྲིག་ཆུང་།',
 'newpageletter' => 'ཤོག་གསར།',
+'boteditletter' => 'རང་འགུལ་འཕྲུལ་ཆས།',
 'rc_categories_any' => 'གང་རུང་།',
 'rc-enhanced-expand' => 'ཞིབ་ཕྲར་སྟོན།',
 'rc-enhanced-hide' => 'ཞིབ་ཕྲ་སྦས་བ།',
@@ -572,7 +624,7 @@ $messages = array(
 'uploadbtn' => 'ཡར་འཇོག',
 'reuploaddesc' => 'ཡར་འཇུག་དོར་ནས་ཡར་འཇུག་རེའུ་མིག་ཏུ་ཕྱིར་ལོག་པ།',
 'uploadnologin' => 'ནང་འཛུལ་བྱས་མེད།',
-'uploadlogpage' => 'རྩོà½\98à¼\8bཡིà½\82་ཡར་འཇུག',
+'uploadlogpage' => 'à½\89ིà½\93à¼\8bà½\90ོ་ཡར་འཇུག',
 'filename' => 'ཡིག་ཆའི་མིང་།',
 'filedesc' => 'བསྡུས་དོན།',
 'fileuploadsummary' => 'བསྡུས་དོན།:',
@@ -590,6 +642,8 @@ $messages = array(
 'uploaddisabled' => 'ཡར་འཇུག་ནུས་མེད་བཟོས་འདུག',
 'watchthisupload' => 'ཡིག་ཆ་འདི་ལ་གཟིགས།',
 
+'license-header' => 'གན་རྒྱ་ནང་ཞུགས་པ།',
+
 # Special:ListFiles
 'imgfile' => 'བརྙན་རིས།',
 'listfiles' => 'ཡིག་ཆའི་ཐོ་གཞུང་།',
@@ -605,6 +659,7 @@ $messages = array(
 'filehist-help' => 'ཟླ་ཚེས་/དུས་ཚོད་གནུན་ཏེ་རྩོམ་ཡིག་ལ་ལྟ་བ།',
 'filehist-deleteall' => 'ཚང་མ་སུབས།',
 'filehist-deleteone' => 'གསུབས།',
+'filehist-revert' => 'ཕྱིར་ལྡོག།',
 'filehist-current' => 'ད་ལྟ།',
 'filehist-datetime' => 'ཚེས་གྲངས། / དུས་ཚོད།',
 'filehist-thumb' => 'བསྡུས་དོན།',
@@ -633,13 +688,18 @@ $messages = array(
 'unusedtemplateswlh' => 'སྦྲེལ་མཐུད་གཞན་དག',
 
 # Random page
-'randompage' => 'རང་མོས་ཤོག་ངོས།',
+'randompage' => 'སྐམས་དོན་ཤོག་ངོས།',
+
+# Statistics
+'statistics' => 'བསྡོམས་རྩིས།',
 
 'brokenredirects-edit' => 'རྩོམ་སྒྲིག',
 'brokenredirects-delete' => 'གསུབ་པ།',
 
 # Miscellaneous special pages
-'nbytes' => '{{PLURAL:$1|ཡིག་ཚགས།}} $1',
+'nbytes' => '{{PLURAL:$1|ཡིག་ཚིགས།}} $1',
+'nmembers' => '$1 {{PLURAL:$1|ཚོགས་མི།|ཚོགས་མི།}}',
+'prefixindex' => 'སྔཽན་སྦྱོར་དང་ལྷན་དུ་ཤོག་ངོས་ཧྲིལ་པོ།',
 'shortpages' => 'ཤོག་ངོས་ཐུང་ངུ་།',
 'newpages' => 'ཤོག་ངོས་གསར་བ།',
 'newpages-username' => 'དྲ་མིང་།:',
@@ -709,7 +769,7 @@ $messages = array(
 'rollbacklink' => 'རྒྱབ་འགྲིལ་གཏོང་བ།',
 
 # Protect
-'protectedarticle' => 'སྲུà½\84à¼\8bསà¾\90ྱོà½\96་བྱས་ཟིན།"[[$1]]"',
+'protectedarticle' => 'འà½\82ོà½\82à¼\8bསྲུà½\84་བྱས་ཟིན།"[[$1]]"',
 'modifiedarticleprotection' => '"[[$1]]" ལ་སྲུང་སྐྱོབ་རིམ་པ་བཟོ་བཅོས་བྱས་བ།',
 'protectcomment' => 'རྒྱུ་མཚན།',
 'protectexpiry' => 'དུས་ཡུན་རྫོགས་ཚད།',
@@ -734,10 +794,10 @@ $messages = array(
 # Namespace form on various pages
 'namespace' => 'མིང་གནས།',
 'invert' => 'གདམ་པའི་ལྡོག་ཕྱོགས།',
-'blanknamespace' => '༼གཙོ་ངོས།༽',
+'blanknamespace' => '(གཙོ་གནད།)',
 
 # Contributions
-'contributions' => 'མཐུན་འགྱུར།',
+'contributions' => '{{GENDER:$1|སྤྱོད་མི།}} མཐུན་འགྱུར།',
 'mycontris' => 'མཐུན་འགྱུར།',
 'month' => 'ཟླ་བ་འདི་ནས།',
 'year' => 'ལོ་འདི་ནས།',
@@ -750,20 +810,25 @@ $messages = array(
 'whatlinkshere-title' => '"$1" ལ སྦྲེལ་ཡོད་པའི་ཤོག་ངོས།',
 'whatlinkshere-page' => 'ཤོག་ངོས།',
 'linkshere' => "གཤམ་གྱི་ཤོག་ངོས་རྣམས་ '''[[:$1]]''': ལ་སྦྲེལ་ཡོད།",
+'nolinkshere' => '<strong>[[:$1]]</strong> ཤོག་ངོས་གཅིག་ཀྱང་སྦྲེལ་མཐུད་མི་འདུག།',
 'isimage' => 'ཡིག་རིས་སྦྲེལ་མཐུད།',
 'whatlinkshere-links' => '← སྦྲེལ་མཐུད།',
+'whatlinkshere-hideredirs' => '$1 ཁ་ཕྱོགས་བསྐྱར་སྟོན།',
 'whatlinkshere-hidelinks' => '$1 སྦྲེལ་མཐུད།',
+'whatlinkshere-hideimages' => '$1 ཡིག་ཆ་སྦྲེལ་མཐུད།',
 'whatlinkshere-filters' => 'ཡིག་ཚགས།',
 
 # Block/unblock
 'blockip' => 'སྤྱོད་མི་འགོག་སྡོམ།',
 'ipbreason' => 'རྒྱུ་མཚན།',
+'ipblocklist' => 'འགོག་སྡོམ་བྱས་པའི་སྤྱོད་མི།',
 'ipblocklist-submit' => 'འཚོལ།',
 'blocklink' => 'འགོག་པ།',
 'unblocklink' => 'བཀག་སྡོམ་གློད་པ།',
 'change-blocklink' => 'བཀག་སྡོམ་བསྒྱུར་བཅོས།',
-'contribslink' => 'à½\96ྱསà¼\8bརà¾\97ེས།',
+'contribslink' => 'à½\98à½\90ུà½\93à¼\8bའà½\82ྱུར།',
 'blocklogpage' => 'རྩོམ་ཡིག་བཀག་འགོག',
+'block-log-flags-nocreate' => 'རྩིས་ཁྲ་གསར་བཟོ་འགོག་འདུག།',
 
 # Move page
 'movearticle' => 'ཤོག་ངོས་སྤོར་བ།',
@@ -791,40 +856,40 @@ $messages = array(
 'tooltip-pt-preferences' => 'ཁྱེད་ཀྱི་ལེགས་སྒྲིག',
 'tooltip-pt-watchlist' => 'ཞུ་དག་གཏོང་བཞིན་པའི་ཤོག་ངོས།',
 'tooltip-pt-mycontris' => 'ངའི་བྱས་རྗེས་སྟོན་པ།',
-'tooltip-pt-login' => 'à½\93à½\84à¼\8bའà½\9bུལ།',
-'tooltip-pt-logout' => 'à½\95ྱིརà¼\8bའà½\96ུà½\91།',
-'tooltip-ca-talk' => 'གྲོས་མོལ།',
-'tooltip-ca-edit' => 'à½\81ྱེà½\91à¼\8bà½\80ྱིསà¼\8bà½\91ྲà¼\8bà½\84ོསà¼\8bའà½\91ིà¼\8bརྩོà½\98à¼\8bསà¾\92ྲིà½\82à¼\8bà½\96ྱེà½\91à¼\8bà½\86ོà½\82 à½\89རà¼\8bà½\9aà½\82སà¼\8bà½\96ྱེà½\91à¼\8bà½\94འིà¼\8bསà¾\94ོà½\93à¼\8bà½\91ུà¼\8bà½\98à½\90ེà½\96à¼\8bà½\82à½\85ུསà¼\8bསà¾\94ོà½\93à¼\8bà½\98à¼\8bསྤྱོà½\91་རོགས།',
+'tooltip-pt-login' => 'à½\81ྱེà½\91à¼\8bརà½\84à¼\8bà½\93à½\84à¼\8bའà½\9bུལà¼\8bà½\82à½\93à½\84à¼\8bà½\96རà¼\8bà½\91à½\82འà¼\8bà½\96སུà¼\8bà½\9eུà¼\8d à½ à½¼à½\93à¼\8bà½\80ྱà½\84à¼\8bའà½\91ིརà¼\8bའà½\82à½\93à¼\8bའà½\81ུརà¼\8bà½\96ྱེà½\91à¼\8bà½\98à½\81à½\93à¼\8bà½\98ེà½\91།',
+'tooltip-pt-logout' => 'à½\95ྱིརà¼\8bà½\91ོà½\93།',
+'tooltip-ca-talk' => 'ཤོà½\82à¼\8bà½\84ོསà¼\8bà½\80ྱིà¼\8bà½\93à½\84à¼\8bà½\91ོà½\93à¼\8bà½\82ྲོསà¼\8bà½\98ོལà¼\8d',
+'tooltip-ca-edit' => 'à½\81ྱེà½\91à¼\8bà½\80ྱིསà¼\8bཤོà½\82à¼\8bà½\84ོསà¼\8bའà½\91ིརà¼\8bརྩོà½\98à¼\8bསà¾\92ྲིà½\82à¼\8bà½\96ྱེà½\91à¼\8bà½\86ོà½\82à¼\8d à½\89རà¼\8bà½\9aà½\82སà¼\8bà½\98à¼\8bà½\96ྱེà½\91à¼\8bà½\82ོà½\84à¼\8bསà¾\94ོà½\93à¼\8bལà¾\9fའིà¼\8bà½\98à½\90ེà½\96à¼\8bà½\82à½\9eོà½\84à¼\8bà½\82à½\93ོà½\93་རོགས།',
 'tooltip-ca-addsection' => 'སྡེ་ཚན་གསར་བ་ཞིག་འགོ་འཛུགས་པ།',
-'tooltip-ca-viewsource' => 'ཤོà½\82à¼\8bà½\84ོསà¼\8bའà½\91ིà¼\8bསྲུà½\84à¼\8bསà¾\90ྱོà½\96à¼\8bའོà½\82à¼\8bཡོà½\91à¼\8d à½\81ྱེà½\91à¼\8bà½\80ྱིསà¼\8bའà½\91ིའིà¼\8bའà½\96ྱུà½\84à¼\8bà½\81ོà½\84སà¼\8bལà¾\9fà¼\8bà½\86ོà½\82',
-'tooltip-ca-history' => 'à½\96à½\9fོ་བཅོས་སྔ་མ།',
+'tooltip-ca-viewsource' => 'ཤོà½\82à¼\8bà½\84ོསà¼\8bའà½\91ིà¼\8bའà½\82ོà½\82à¼\8bསྲུà½\84à¼\8bà½\96ྱསà¼\8bཡོà½\91à¼\8d à½\81ྱེà½\91à¼\8bà½\80ྱིསà¼\8bའà½\91ིའིà¼\8bà½\81ུà½\84སà¼\8bལà¼\8bལà¾\9fà¼\8bà½\86ོà½\82à¼\8d',
+'tooltip-ca-history' => 'ཤོà½\82à¼\8bà½\84ོསà¼\8bའà½\91ིའིà¼\8bà½\96སà¾\90ྱར་བཅོས་སྔ་མ།',
 'tooltip-ca-protect' => 'ཤོག་ངོས་འདི་སྲུངས་ཤིག',
 'tooltip-ca-delete' => 'ཤོག་ངོས་འདི་དོར་ཅིག',
 'tooltip-ca-move' => 'ཤོག་ངོས་འདི་སྤོར་བ།',
 'tooltip-ca-watch' => 'ཤོག་ངོས་འདི་ཁྱོད་ཀྱི་མཉམ་འཇོག་ཐོ་རུ་འཇུག་པ།',
 'tooltip-ca-unwatch' => 'ཤོག་ངོས་འདི་མཉམ་འཇོག་ཐོ་ལས་ལེན་པ།',
-'tooltip-search' => 'ལà½\82à¼\8bà½\86à¼\8bའà½\9aོལà¼\8d',
+'tooltip-search' => 'འà½\9aོལà¼\8d {{SITENAME}}',
 'tooltip-search-go' => 'མིང་ཇི་བཞིན་པའི་ཤོག་ངོས་སྟེང་དུ་སྐྱོད་པ།',
-'tooltip-search-fulltext' => 'à½\9aིà½\82་འདི་འཚོལ།',
-'tooltip-p-logo' => 'à½\82à½\99ོà¼\8bà½\84ོས།',
-'tooltip-n-mainpage' => 'à½\82à½\99ོà¼\8bà½\84ོསà¼\8bལà¼\8bལà¾\9fà¼\8bà½\96།',
-'tooltip-n-mainpage-description' => 'à½\82à½\99ོà¼\8bà½\84ོསà¼\8bལà¼\8bལà¾\9fà¼\8bà½\96།',
-'tooltip-n-portal' => 'ལསà¼\8bའà½\86རà¼\8bསà¾\90ོརà¼\8bà½\91à½\84à¼\8bà½\81ྱེà½\91à¼\8bà½\80ྱིསà¼\8bà½\85ིà¼\8bà½\9eིà½\82à¼\8bà½\96ྱེà½\91à¼\8bà½\93ུསà¼\8bà½\94à¼\8d à½\82à½\84à¼\8bà½\91ུà¼\8bའà½\9aོལà¼\8bà½\91à½\82ོསà¼\8bà½\94།',
+'tooltip-search-fulltext' => 'ཤོà½\82à¼\8bà½\84ོསà¼\8bà½\90ོà½\82à¼\8bཡིà½\82à¼\8bརà¾\90ྱà½\84་འདི་འཚོལ།',
+'tooltip-p-logo' => 'à½\82à½\99ོà¼\8bà½\82à½\93à½\91à¼\8bཤོà½\82à¼\8bà½\84ོསà¼\8bལà¼\8bà½\82à½\9fིà½\82སà¼\8bརོà½\82ས།',
+'tooltip-n-mainpage' => 'à½\82à½\99ོà¼\8bà½\82à½\93à½\91à¼\8bཤོà½\82à¼\8bà½\84ོསà¼\8bལà¼\8bà½\82à½\9fིà½\82སà¼\8bརོà½\82ས།',
+'tooltip-n-mainpage-description' => 'à½\82à½\99ོà¼\8bà½\82à½\93à½\91à¼\8bཤོà½\82à¼\8bà½\84ོསà¼\8bལà¼\8bà½\82à½\9fིà½\82སà¼\8bརོà½\82ས།',
+'tooltip-n-portal' => 'ལསà¼\8bའà½\86རà¼\8bསà¾\90ོརà¼\8d à½\81ྱེà½\91à¼\8bà½\80ྱིསà¼\8bà½\82à½\84à¼\8bà½\96ྱེà½\91à¼\8bà½\90ུà½\96à¼\8bà½\96à½\98à¼\8d à½\82à½\84à¼\8bà½\91ུà¼\8bའà½\9aོལà¼\8bà½\91à½\82ོསà¼\8bསà½\98།',
 'tooltip-n-currentevents' => 'ཉེ་བའི་ལས་དོན་གྱི་རྒྱབ་ལྗོངས་གནས་ཚུལ་འཚོལ་བ།',
-'tooltip-n-recentchanges' => 'à½\9dེà¼\8bà½\81ེà¼\8bསà¾\9fེà½\84à¼\8bà½\82ིà¼\8bà½\89ེà¼\8bà½\96འིà¼\8bà½\96à½\9fོà¼\8bà½\96à½\85ོསà¼\8bà½\80ྱིà¼\8bà½\90ོà¼\8bà½\82à½\9eུà½\84à¼\8b།',
-'tooltip-n-randompage' => 'རà½\84à¼\8bà½\98ོསà¼\8bཤོà½\82à¼\8bà½\84ོསà¼\8bཤིà½\82à¼\8bལེà½\93à¼\8bà½\94།',
+'tooltip-n-recentchanges' => 'à½\9dེà¼\8bà½\81ེà¼\8bསà¾\9fེà½\84à¼\8bà½\82ིà¼\8bà½\89ེà¼\8bà½\86རà¼\8bà½\96à½\9fོà¼\8bà½\96à½\85ོསà¼\8bà½\80ྱིà¼\8bà½\90ོ།',
+'tooltip-n-randompage' => 'སà¾\90à½\96སà¼\8bà½\91ོà½\93à¼\8bཤོà½\82à¼\8bà½\84ོསà¼\8bཤིà½\82à¼\8bà½\95à½\96à¼\8bའà½\87ུà½\82།',
 'tooltip-n-help' => 'གང་དུ་འཚོལ་བའི་གནས།',
-'tooltip-t-whatlinkshere' => 'འà½\91ིà¼\8bལà¼\8bསྦྲེལà¼\8bà½\96འིà¼\8bà½\9dེà¼\8bà½\81ེà¼\8bཤོà½\82à¼\8bà½\84ོསà¼\8bཡོà½\84སà¼\8bརྫོà½\82ས།',
-'tooltip-t-recentchangeslinked' => 'à½\84ོསà¼\8bའà½\91ིà¼\8bà½\91à½\84à¼\8bའà½\96ྲེལà¼\8bà½\96འི་ཉེ་བའི་བཟོ་བཅོས།',
+'tooltip-t-whatlinkshere' => 'འà½\91ིརà¼\8bསྦྲེལà¼\8bཡོà½\91à¼\8bà½\94འིà¼\8bà½\9dེà¼\8bà½\81ེà¼\8bཤོà½\82à¼\8bà½\84ོསà¼\8bཧྲིལà¼\8bà½\94ོའིà¼\8bà½\90ོ།',
+'tooltip-t-recentchangeslinked' => 'ཤོà½\82à¼\8bà½\84ོསà¼\8bའà½\91ིà¼\8bà½\91à½\84à¼\8bསྤྲེལà¼\8bà½\96འིà¼\8bཤོà½\82à¼\8bà½\84ོསà¼\8bà½\82à½\9eà½\93à¼\8bà½\90ོà½\82à¼\8bà½\82ི་ཉེ་བའི་བཟོ་བཅོས།',
 'tooltip-feed-rss' => 'ཤོག་ངོས་འདིའི་RSS འབྱུང་ཁུངས།',
 'tooltip-feed-atom' => 'ཤོག་ངོས་འདིའི་Atom འབྱུང་ཁུངས།',
 'tooltip-t-contributions' => 'བཀོལ་མི་འདིའི་བྱས་རྗེས་སྟོན།',
-'tooltip-t-emailuser' => 'སྤྱོà½\91à¼\8bà½\98ིà¼\8bའà½\91ིརà¼\8bà½\91ྲà¼\8bའà½\95ྲིà½\93à¼\8bསà¾\90ུརà¼\8bà½\96།',
+'tooltip-t-emailuser' => 'སྤྱོà½\91à¼\8bà½\98ིà¼\8bའà½\91ིརà¼\8bà½\82ློà½\82à¼\8bའà½\95ྲིà½\93à¼\8bà½\96སà¾\90ུརà¼\8bརོà½\82ས།',
 'tooltip-t-upload' => 'ཡིག་ཆ་ཡར་འཇུག',
-'tooltip-t-specialpages' => 'à½\91à½\98ིà½\8aà¼\8bà½\82སལ་ཤོག་ངོས་ཀྱི་ཐོ་གཞུང་།',
-'tooltip-t-print' => 'à½\91à½\94རà¼\8bà½\90ུà½\96à¼\8bà½\94འིà¼\8bà½\98ིà¼\8bའà½\91ྲà¼\8bà½\86ོས།',
-'tooltip-t-permalink' => 'རà¾\9fà½\82à¼\8bà½\96རà¾\9fà½\93à¼\8bà½\82ྱིà¼\8bà½\91ྲà¼\8bà½\96རà¼\8bའà½\87ུà½\82à¼\8bà½\94།',
-'tooltip-ca-nstab-main' => 'à½\93à½\84à¼\8bà½\91ོà½\93à¼\8bཤོà½\82à¼\8bà½\84ོསà¼\8bལà¼\8bལà¾\9fà¼\8bà½\96།',
+'tooltip-t-specialpages' => 'à½\86ེà½\91à¼\8bལས་ཤོག་ངོས་ཀྱི་ཐོ་གཞུང་།',
+'tooltip-t-print' => 'ཤོà½\82à¼\8bà½\84ོསà¼\8bའà½\91ིའིà¼\8bà½\91à½\94རà¼\8bརུà½\84à¼\8bà½\96འིà¼\8bའà½\82ྱུར།',
+'tooltip-t-permalink' => 'à½\96à½\9fོà¼\8bའà½\85ོསà¼\8bཤོà½\82à¼\8bà½\84ོསà¼\8bའà½\91ིའིà¼\8bà½\96རà¾\9fà½\93à¼\8bའà½\87à½\82སà¼\8bà½\80ྱིà¼\8bསྦྲེལà¼\8bà½\98à½\90ུà½\91།',
+'tooltip-ca-nstab-main' => 'à½\93à½\84à¼\8bà½\91ོà½\93à¼\8bà½\80ྱིà¼\8bཤོà½\82à¼\8bà½\84ོསà¼\8bལà¼\8bà½\82à½\9fིà½\82སà¼\8bརོà½\82ས།',
 'tooltip-ca-nstab-user' => 'སྤྱོད་མིའི་ཤོག་ངོས་ལ་ལྟ་བ།',
 'tooltip-ca-nstab-special' => 'དྲ་ངོས་འདི་དམིགས་གསལ་བ་ཡིན་པས་བཟོ་བཅོས་རྒྱག་མི་ཆོག',
 'tooltip-ca-nstab-project' => 'ལས་འཆར་ཤོག་ངོས་ལ་ལྟ་བ།',
@@ -835,6 +900,7 @@ $messages = array(
 'tooltip-save' => 'བཟོ་བཅོས་ཉར་ཚགས་བྱོས།',
 'tooltip-preview' => 'ཉར་ཚགས་ཀྱི་སྔོན་དུ་བཟོ་བཅོས་ལ་བསྐྱར་ཞིབ་གནང་རོགས།',
 'tooltip-diff' => 'གང་ལ་བཟོ་བཅོས་བྱས་པའི་ཡིག་འབྲུ་སྟོན་པ།',
+'tooltip-undo' => '"ཕྱིར་འཐེན།" ཞེས་པ་དེས་ཁྱེད་ཀྱི་རྩོམ་སྒྲིག་ཕྱིར་ལྡོག་པ་དང་སྔོན་འཚུད་བལྟ་ཞིབ་ཤོག་ངོས་ཁ་ཕྱེ་རྒྱུ་ཡིན། མཇུག་སྡོམ་ཀྱི་རྒྱུ་རྐྱེན་གླེང་འཇུག་རྒྱུ་ཡིན།',
 'tooltip-summary' => 'ཕྱོགས་བསྡོམས་ཐུང་ངུ་ཞིག་འབྲིས་',
 
 # Browsing diffs
@@ -859,11 +925,12 @@ $messages = array(
 'table_pager_limit_submit' => 'སོང་།',
 
 # Watchlist editing tools
+'watchlisttools-view' => 'འབྲེལ་ཡོད་འགྱུར་བཅོས་ལ་གཟིགས་རོགས།',
 'watchlisttools-edit' => 'མཉམ་འཇོག་ཐོར་ལྟ་བ་དང་བསྒྱུར་བཅོས་བྱེད་པ།',
 'watchlisttools-raw' => 'ལྟ་ཐོའི་གོ་རིམ་བཅོས་སྒྲིག',
 
 # Special:SpecialPages
-'specialpages' => 'à½\91à½\98ིà½\82སà¼\8bà½\82སལ་ཤོག་ངོས།',
+'specialpages' => 'à½\86ེà½\91à¼\8bལས་ཤོག་ངོས།',
 
 # New logging system
 'rightsnone' => '(སྟོང་པ།)',
index db20f8f..ed2dbcb 100644 (file)
@@ -617,7 +617,7 @@ No oblideu de canviar les vostres [[Special:Preferences|preferències de {{SITEN
 'yourname' => "Nom d'usuari",
 'userlogin-yourname' => 'Usuari',
 'userlogin-yourname-ph' => "Introduïu el vostre nom d'usuari",
-'createacct-another-username-ph' => "Introdueix el nom d'usuari",
+'createacct-another-username-ph' => "Introduïu el nom d'usuari",
 'yourpassword' => 'Contrasenya',
 'userlogin-yourpassword' => 'Contrasenya',
 'userlogin-yourpassword-ph' => 'Introduïu la vostra contrasenya',
@@ -654,11 +654,11 @@ No oblideu de canviar les vostres [[Special:Preferences|preferències de {{SITEN
 Feu servir el formulari de sota per iniciar la sessió com un altre usuari.',
 'userlogin-createanother' => 'Crea un altre compte',
 'createacct-join' => 'Introduïu les vostres dades.',
-'createacct-another-join' => 'Introdueix la informació del nou compte a continuació:',
+'createacct-another-join' => 'Introduïu la informació del nou compte a continuació:',
 'createacct-emailrequired' => 'Adreça de correu electrònic',
 'createacct-emailoptional' => 'Adreça de correu electrònic (opcional)',
 'createacct-email-ph' => 'Introduïu la vostra adreça de correu electrònic',
-'createacct-another-email-ph' => 'Introdueix una adreça de correu electrònic',
+'createacct-another-email-ph' => 'Introduïu una adreça de correu electrònic',
 'createaccountmail' => "Utilitza una contrasenya aleatòria temporal i envia-la a l'adreça de correu indicada",
 'createacct-realname' => 'Nom real (opcional)',
 'createaccountreason' => 'Motiu:',
@@ -737,6 +737,7 @@ Espereu $1 abans de tornar-ho a provar.",
 'suspicious-userlogout' => "S'ha denegat la vostra petició per tancar la sessió ja què sembla que va ser enviada per un navegador defectuós o un proxy cau.",
 'createacct-another-realname-tip' => "El nom real és opcional.
 Si decidiu proporcionar-lo, s'utilitzarà per a reconèixer a l'usuari el seu treball.",
+'pt-createaccount' => 'Crea un compte',
 
 # Email sending
 'php-mail-error-unknown' => 'Error desconegut en la funció mail() de PHP',
@@ -767,7 +768,7 @@ Per completar l'inici de sessió heu de definir una contrasenya nova a continuac
 'resetpass-temp-password' => 'Contrasenya temporal:',
 'resetpass-abort-generic' => 'Una extensió ha interromput el canvi de contrasenya.',
 'resetpass-expired' => 'La contrasenya ha vençut. Definiu una contrasenya nova per iniciar la sessió.',
-'resetpass-expired-soft' => 'La contrasenya ha vençut i cal restablir-la. Trieu una contrasenya nova ara, o feu clic a cancel·lat per a restablir-la més endavant.',
+'resetpass-expired-soft' => 'La contrasenya ha vençut i cal restablir-la. Trieu una contrasenya nova ara, o feu clic a «{{int:resetpass-submit-cancel}}» per a restablir-la més endavant.',
 
 # Special:PasswordReset
 'passwordreset' => 'Restablir contrasenya',
@@ -1610,14 +1611,26 @@ Ha de tenir com a molt {{PLURAL:$1|un caràcter|$1 caràcters}}.',
 'recentchanges-legend-heading' => "'''Llegenda:'''",
 'recentchanges-legend-newpage' => '(vegeu també la [[Special:NewPages|llista de pàgines noves]])',
 'recentchanges-legend-plusminus' => "(''±123'')",
-'rcnotefrom' => 'A sota hi ha els canvis des de <b>$2</b> (es mostren fins <b>$1</b>).',
+'rcnotefrom' => 'A sota hi ha els canvis des de <strong>$2</strong> (es mostren fins <strong>$1</strong>).',
 'rclistfrom' => 'Mostra els canvis nous des de $1',
 'rcshowhideminor' => '$1 edicions menors',
+'rcshowhideminor-show' => 'Mostra',
+'rcshowhideminor-hide' => 'Amaga',
 'rcshowhidebots' => '$1 bots',
+'rcshowhidebots-show' => 'Mostra',
+'rcshowhidebots-hide' => 'Amaga',
 'rcshowhideliu' => '$1 usuaris registrats',
+'rcshowhideliu-show' => 'Mostra',
+'rcshowhideliu-hide' => 'Amaga',
 'rcshowhideanons' => '$1 usuaris anònims',
+'rcshowhideanons-show' => 'Mostra',
+'rcshowhideanons-hide' => 'Amaga',
 'rcshowhidepatr' => '$1 edicions supervisades',
+'rcshowhidepatr-show' => 'Mostra',
+'rcshowhidepatr-hide' => 'Amaga',
 'rcshowhidemine' => '$1 edicions pròpies',
+'rcshowhidemine-show' => 'Mostra',
+'rcshowhidemine-hide' => 'Amaga',
 'rclinks' => 'Mostra els darrers $1 canvis en els darrers $2 dies<br />$3',
 'diff' => 'dif',
 'hist' => 'hist',
@@ -1740,6 +1753,8 @@ Si us plau, si encara desitgeu carregar el vostre fitxer, torneu enrera i carreg
 'uploaddisabledtext' => "S'ha inhabilitat la càrrega de fitxers.",
 'php-uploaddisabledtext' => 'La càrrega de fitxer està desactivada al PHP. Comproveu les opcions del fitxer file_uploads.',
 'uploadscripted' => 'Aquest fitxer conté codi HTML o de seqüències que pot ser interpretat equivocadament per un navegador.',
+'uploadscriptednamespace' => 'Aquest fitxer SVG conté un espai de noms "$1" no autoritzat',
+'uploadinvalidxml' => "No s'ha pogut analitzar l'XML del fitxer carregat.",
 'uploadvirus' => 'El fitxer conté un virus! Detalls: $1',
 'uploadjava' => 'El fitxer és un arxiu ZIP que conté un fitxer .class de Java. No està permesa la càrrega de fitxers Java, perquè poden passar per alt les restriccions de seguretat.',
 'upload-source' => 'Fitxer font',
@@ -2552,6 +2567,7 @@ Per més detalls, la última entrada del registre es mostra a continuació:',
 'sp-contributions-search' => 'Cerca les contribucions',
 'sp-contributions-username' => "Adreça IP o nom d'usuari:",
 'sp-contributions-toponly' => 'Mostra només revisions superiors',
+'sp-contributions-newonly' => 'Mostra només modificacions que són creacions de pàgina',
 'sp-contributions-submit' => 'Cerca',
 
 # What links here
@@ -4075,6 +4091,4 @@ També expandeix les funcions sintàctiques, com ara <code><nowiki>{{</nowiki>#l
 'expand_templates_generate_rawhtml' => "Mostra l'HTML sense filtrar",
 'expand_templates_preview' => 'Previsualitza',
 
-# Unknown messages
-'uploadinvalidxml' => "No s'ha pogut analitzar l'XML del fitxer carregat.",
 );
index 1e0931d..1fc077a 100644 (file)
@@ -1501,14 +1501,26 @@ $1",
 'recentchanges-label-unpatrolled' => 'ХӀара нисдар хӀинца цхьано патрулировать дина дац',
 'recentchanges-label-plusminus' => 'байташкахь барам хийцар',
 'recentchanges-legend-newpage' => '(хьажа кхин [[Special:NewPages|керла агӀонийн могӀа]])',
-'rcnotefrom' => "Лахахь гайтина тӀера '''$2''' хийцамаш ('''$1''' къезиг).",
+'rcnotefrom' => 'Лахахь гайтина тӀера <strong>$2</strong> (хийцамаш <strong>$1</strong> кӀезиг).',
 'rclistfrom' => 'Гайта хийцам оцу $1.',
 'rcshowhideminor' => '$1 кегийра нисдарш',
+'rcshowhideminor-show' => 'Гайта',
+'rcshowhideminor-hide' => 'Къайладаха',
 'rcshowhidebots' => '$1 шабелхалой',
+'rcshowhidebots-show' => 'Гайта',
+'rcshowhidebots-hide' => 'Къайлабаха',
 'rcshowhideliu' => '$1 шайн цӀершца болу декъашхой',
+'rcshowhideliu-show' => 'Гайта',
+'rcshowhideliu-hide' => 'Къайлабаха',
 'rcshowhideanons' => '$1 цӀе хьулйина декъашхой',
+'rcshowhideanons-show' => 'Гайта',
+'rcshowhideanons-hide' => 'Къайлабаха',
 'rcshowhidepatr' => '$1 хьажжина нисдарш',
+'rcshowhidepatr-show' => 'Гайта',
+'rcshowhidepatr-hide' => 'Къайладаха',
 'rcshowhidemine' => '$1 айхьа нисдинарш',
+'rcshowhidemine-show' => 'Гайта',
+'rcshowhidemine-hide' => 'Къайладаха',
 'rclinks' => 'Гайта тlаьхьара $1 хийцамаш оцу $2 ден<br />$3',
 'diff' => 'тейп тайпнара',
 'hist' => 'истори',
@@ -1956,6 +1968,7 @@ PICT # тайп тайпан
 'unwatch' => 'Тергамах къаста',
 'notanarticle' => 'Бац яззам',
 'watchlist-details' => 'Хьан тергаме могlамца $1 {{PLURAL:$1|агlо|агlонаш|агlонаш}} ю, дийцаре агlонаша йоцуш.',
+'wlheader-enotif' => 'Электронан почте хаамаш байтар латина ду.',
 'wlheader-showupdated' => "Хийцам бина агӀонаш '''Ӏаьржа''' шрифтцан билгальяха ю.",
 'wlnote2' => 'Лахахьа гайтина {{PLURAL:$1|тӀеххьара сахьт}} чохь бина хийцамаш $2 $3.',
 'wlshowlast' => 'Гайта тlаьххьара $1 сахьташ $2 денош $3',
@@ -2673,6 +2686,9 @@ PICT # тайп тайпан
 'confirm-watch-top' => 'ТӀетоха хӀара агӀо хьан тергаме могӀам юкъа?',
 'confirm-unwatch-top' => 'ДӀаяккха хӀара агӀо хьай тергаме могӀанан юкъар?',
 
+# Separators for various lists, etc.
+'comma-separator' => ',&#32;',
+
 # Multipage image navigation
 'imgmultipageprev' => '← хьалхара агlо',
 'imgmultipagenext' => 'тlаьхьара агlо →',
index c5c3837..173f523 100644 (file)
@@ -802,6 +802,7 @@ Parechji mudelli ùn seranu micca inclusi.",
 'tags-edit' => 'mudificà',
 
 # New logging system
+'logentry-move-move' => '$1 {{GENDER:$2|hà spustatu}} a pagina $3 à $4',
 'rightsnone' => '(nessunu)',
 
 # Special:ExpandTemplates
index 6ac7edd..39ddeb0 100644 (file)
@@ -706,7 +706,7 @@ Správce serveru, který databázi zamkl, poskytl toto zdůvodnění: $1',
 
 Toto je obvykle způsobeno tím, že jste následovali zastaralý odkaz na rozdíl verzí nebo historickou verzi stránky, jež byla smazána.
 
-Pokud toto není váš případ, možná jste nalezli chybu v software. Prosíme, ohlaste to [[Special:ListUsers/sysop|správcům]] spolu s URL této stránky.',
+Není-li toto váš případ, možná jste nalezli chybu v softwaru. Prosíme, ohlaste to [[Special:ListUsers/sysop|správcům]] spolu s URL této stránky.',
 'missingarticle-rev' => '(číslo revize: $1)',
 'missingarticle-diff' => '(Rozdíl: $1, $2)',
 'readonly_lag' => 'Databáze byla automaticky dočasně uzamčena kvůli zpoždění ostatních databázových serverů oproti hlavnímu',
@@ -1782,11 +1782,23 @@ Vaše adresa v takovém případě není prozrazena.',
 'rcnotefrom' => 'Níže {{PLURAL:$1|je|jsou|je}} nejvýše <b>$1</b> {{PLURAL:$1|změna|změny|změn}} od <b>$2</b>.',
 'rclistfrom' => 'Ukázat nové změny, počínaje od $1',
 'rcshowhideminor' => '$1 malé editace',
+'rcshowhideminor-show' => 'Zobrazit',
+'rcshowhideminor-hide' => 'Skrýt',
 'rcshowhidebots' => '$1 roboty',
+'rcshowhidebots-show' => 'Zobrazit',
+'rcshowhidebots-hide' => 'Skrýt',
 'rcshowhideliu' => '$1 registrované uživatele',
+'rcshowhideliu-show' => 'Zobrazit',
+'rcshowhideliu-hide' => 'Skrýt',
 'rcshowhideanons' => '$1 anonymní uživatele',
+'rcshowhideanons-show' => 'Zobrazit',
+'rcshowhideanons-hide' => 'Skrýt',
 'rcshowhidepatr' => '$1 prověřené editace',
+'rcshowhidepatr-show' => 'Zobrazit',
+'rcshowhidepatr-hide' => 'Skrýt',
 'rcshowhidemine' => '$1 moje editace',
+'rcshowhidemine-show' => 'Zobrazit',
+'rcshowhidemine-hide' => 'Skrýt',
 'rclinks' => 'Ukázat $1 posledních změn během posledních $2 dnů<br />
 $3',
 'diff' => 'rozdíl',
@@ -1908,6 +1920,7 @@ Před tím, než soubor znovu nahrajete, byste měli požádat někoho, kdo mů
 'uploaddisabledtext' => 'Načítání souborů je vypnuto.',
 'php-uploaddisabledtext' => 'V PHP je vypnuto načítání souborů. Prosím, zkontrolujte nastavení file_uploads.',
 'uploadscripted' => 'Tento soubor obsahuje HTML nebo kód skriptu, který by mohl být prohlížečem chybně interpretován.',
+'uploadinvalidxml' => 'XML v načteném souboru nelze zpracovat.',
 'uploadvirus' => 'Tento soubor obsahuje virus! Podrobnosti: $1',
 'uploadjava' => 'Tento soubor je ZIP, který obsahuje javový soubor .class.
 Načítání javových souborů není dovoleno, neboť by mohly umožnit obcházení bezpečnostních omezení.',
@@ -4320,6 +4333,4 @@ V podstatě rozbalí prakticky všechno v dvojitých složených závorkách.',
 'expand_templates_generate_rawhtml' => 'Zobrazit surové HTML',
 'expand_templates_preview' => 'Náhled',
 
-# Unknown messages
-'uploadinvalidxml' => 'XML v načteném souboru nelze zpracovat.',
 );
index 9cf9ab9..3e538a3 100644 (file)
@@ -1653,6 +1653,7 @@ Cyn i chi ail-lwytho'r ffeil, dylech holi i rywun â'r gallu ganddo i weld data
 'php-uploaddisabledtext' => 'Anablwyd uwchlwytho ffeiliau yn PHP.
 Gwiriwch y gosodiad ar file_uploads.',
 'uploadscripted' => "Mae'r ffeil hon yn cynnwys HTML neu sgript a all achosi problemau i borwyr gwe.",
+'uploadinvalidxml' => "Ni ellid dosrannu'r XML yn y ffeil a uwchlwythwyd.",
 'uploadvirus' => 'Mae firws gan y ffeil hon! Manylion: $1',
 'uploadjava' => "Ffeil ZIP yw hwn sy'n cynnwys ffeil Java .class.
 Ni chaniateir uwchlwytho ffeiliau Java, oherwydd y gallant osgoi cyfyngiadau diogelwch.",
@@ -3975,6 +3976,4 @@ Defnydd:
 'expand_templates_generate_rawhtml' => 'Dangos HTML crai',
 'expand_templates_preview' => 'Rhagolwg',
 
-# Unknown messages
-'uploadinvalidxml' => "Ni ellid dosrannu'r XML yn y ffeil a uwchlwythwyd.",
 );
index 7d3d493..4ab4fbc 100644 (file)
@@ -199,19 +199,19 @@ $messages = array(
 'tog-hidepatrolled' => 'Skjul patruljerede redigeringer i seneste ændringer',
 'tog-newpageshidepatrolled' => 'Skjul patruljerede sider på listen over nye sider',
 'tog-extendwatchlist' => 'Udvid overvågningslisten til at vise alle ændringer og ikke kun den nyeste',
-'tog-usenewrc' => 'Gruppér ændringerne per side i listen over seneste ændringer og i overvågningslisten',
+'tog-usenewrc' => 'Gruppér ændringer per side i listen over seneste ændringer og i overvågningslisten',
 'tog-numberheadings' => 'Automatisk nummerering af overskrifter',
 'tog-showtoolbar' => 'Vis værktøjslinje til redigering',
 'tog-editondblclick' => 'Redigér sider med dobbeltklik',
 'tog-editsectiononrightclick' => 'Redigér afsnit ved at højreklikke på deres titler',
-'tog-rememberpassword' => 'Husk mig i denne browser (i højst $1 {{PLURAL:$1|dag|dage}})',
+'tog-rememberpassword' => 'Husk min login i denne browser (i højst $1 {{PLURAL:$1|dag|dage}})',
 'tog-watchcreations' => 'Tilføj sider, jeg opretter, og filer, jeg lægger op, til min overvågningsliste',
 'tog-watchdefault' => 'Tilføj sider og filer, jeg redigerer, til min overvågningsliste',
 'tog-watchmoves' => 'Tilføj sider og filer, jeg flytter, til min overvågningsliste',
 'tog-watchdeletion' => 'Tilføj sider og filer, jeg sletter, til min overvågningsliste',
-'tog-minordefault' => 'Markér som standard alle redigeringer som mindre redigeringer',
+'tog-minordefault' => 'Markér som standard alle redigeringer som mindre',
 'tog-previewontop' => 'Vis forhåndsvisning over redigeringsboksen',
-'tog-previewonfirst' => 'Vis forhåndsvisning når du starter med at redigere',
+'tog-previewonfirst' => 'Vis forhåndsvisning ved første redigering',
 'tog-enotifwatchlistpages' => 'Send mig en e-mail ved ændringer til en side eller fil på min overvågningsliste',
 'tog-enotifusertalkpages' => 'Send mig en e-mail når min brugerdiskussionsside ændres',
 'tog-enotifminoredits' => 'Send mig også en e-mail ved mindre ændringer af sider og filer på min overvågningsliste',
@@ -228,7 +228,7 @@ $messages = array(
 'tog-watchlisthideanons' => 'Skjul anonyme brugeres redigeringer i overvågningslisten',
 'tog-watchlisthidepatrolled' => 'Skjul patrujerede ændringer fra overvågningslisten',
 'tog-ccmeonemails' => 'Send mig kopier af e-mails som jeg sender til andre brugere',
-'tog-diffonly' => 'Vis ved versionssammenligninger kun forskelle, ikke hele siden',
+'tog-diffonly' => 'Vis ikke sideindhold neden under versionssammenligninger',
 'tog-showhiddencats' => 'Vis skjulte kategorier',
 'tog-noconvertlink' => 'Slå konvertering af sidetitler fra',
 'tog-norollbackdiff' => 'Vis ikke forskel efter tilbagerulning',
@@ -731,9 +731,9 @@ Vent venligst $1, før du prøver igen.',
 'suspicious-userlogout' => 'Din anmodning om at logge af blev nægtet, fordi det ser ud som den blev sendt af en ødelagt browser eller caching proxy.',
 'createacct-another-realname-tip' => 'Angivelse af rigtigt navn er valgfrit.
 Hvis du vælger at oplyse dit navn, vil det blive brugt til at tilskrive dig dit arbejde.',
-'pt-login' => 'Log ind',
+'pt-login' => 'Log ',
 'pt-createaccount' => 'Opret konto',
-'pt-userlogout' => 'Log ud',
+'pt-userlogout' => 'Log af',
 
 # Email sending
 'php-mail-error-unknown' => 'Ukendt fejl i PHP funktionen mail()',
@@ -742,7 +742,7 @@ Hvis du vælger at oplyse dit navn, vil det blive brugt til at tilskrive dig dit
 
 # Change password dialog
 'changepassword' => 'Skift adgangskode',
-'resetpass_announce' => 'Du loggede på med den via e-mail tilsendte adgangskode. For at afslutte tilmeldingen, skal du nu vælge en ny adgangskode.',
+'resetpass_announce' => 'For at afslutte indlogningen skal du vælge en ny adgangskode.',
 'resetpass_text' => '<!-- Tilføj tekst her -->',
 'resetpass_header' => 'Skift adgangskode',
 'oldpassword' => 'Gammel adgangskode:',
@@ -1242,7 +1242,8 @@ Vær opmæksom på at bevare kontinuiteten i sidehistorikken.
 'showhideselectedversions' => 'Vis/skjul udvalgte versioner',
 'editundo' => 'fjern redigering',
 'diff-empty' => '(Ingen forskel)',
-'diff-multi-sameuser' => '({{PLURAL:$1|En mellem liggende version|$1 mellemliggende versioner}} af den samme bruger, vises ikke',
+'diff-multi-sameuser' => '({{PLURAL:$1|En mellemliggende version|$1 mellemliggende versioner}} af den samme bruger, vises ikke)',
+'diff-multi-otherusers' => '({{PLURAL:$1|En mellemliggende version|$1 mellemliggende versioner}} af {{PLURAL:$2|en anden bruger|$2 andre brugere}} ikke vist)',
 'diff-multi-manyusers' => '({{PLURAL:$1|En mellemliggende version|$1 mellemliggende versioner}} af mere end $2 {{PLURAL:$2|bruger|brugere}} ikke vist)',
 'difference-missing-revision' => '{{PLURAL:$2|En revision|$2 revisioner}} af denne forskel ($1) {{PLURAL:$2|blev|blev}} ikke fundet.
 
@@ -1263,7 +1264,7 @@ Detaljer kan findes i [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}
 'shown-title' => 'Vis $1 {{PLURAL:$1|resultat|resultater}} per side',
 'viewprevnext' => 'Vis ($1 {{int:pipe-separator}} $2) ($3)',
 'searchmenu-exists' => "'''Der er en side med navnet \"[[:\$1]]\" på denne wiki'''",
-'searchmenu-new' => "'''Opret siden \"[[:\$1]]\" i denne wiki'''",
+'searchmenu-new' => '<strong>Opret siden "[[:$1]]" på denne wiki!</strong> {{PLURAL:$2|0=|Se også siden der blev fundet for din søgning.|Se også de søgeresultater der blev fundet.}}',
 'searchprofile-articles' => 'Indholdssider',
 'searchprofile-project' => 'Hjælpe- og projektsider',
 'searchprofile-images' => 'Multimedia',
@@ -1609,11 +1610,23 @@ Vær venlig at gennemse og bekræft dine ændringer.',
 'rcnotefrom' => "Nedenfor er op til '''$1''' ændringer siden '''$2''' vist.",
 'rclistfrom' => 'Vis nye ændringer startende fra $1',
 'rcshowhideminor' => '$1 mindre ændringer',
+'rcshowhideminor-show' => 'Vis',
+'rcshowhideminor-hide' => 'Skjul',
 'rcshowhidebots' => '$1 robotter',
+'rcshowhidebots-show' => 'Vis',
+'rcshowhidebots-hide' => 'Skjul',
 'rcshowhideliu' => '$1 registrerede brugere',
+'rcshowhideliu-show' => 'Vis',
+'rcshowhideliu-hide' => 'Skjul',
 'rcshowhideanons' => '$1 anonyme brugere',
+'rcshowhideanons-show' => 'Vis',
+'rcshowhideanons-hide' => 'Skjul',
 'rcshowhidepatr' => '$1 kontrollerede ændringer',
+'rcshowhidepatr-show' => 'Vis',
+'rcshowhidepatr-hide' => 'Skjul',
 'rcshowhidemine' => '$1 egne bidrag',
+'rcshowhidemine-show' => 'Vis',
+'rcshowhidemine-hide' => 'Skjul',
 'rclinks' => 'Vis seneste $1 ændringer i de sidste $2 dage<br />$3',
 'diff' => 'forskel',
 'hist' => 'historik',
@@ -1738,6 +1751,7 @@ Du bør spørge en person med evnen til at se undertrykte fildata for at gennemg
 'uploaddisabledtext' => 'Oplægning af filer er deaktiveret.',
 'php-uploaddisabledtext' => 'Oplægning af filer er forhindret i PHP. Tjek indstillingen for file_uploads.',
 'uploadscripted' => 'Denne fil indeholder HTML eller script-kode, der i visse tilfælde can fejlfortolkes af en browser.',
+'uploadinvalidxml' => 'XML i den uploadede fil kunne ikke tolkes.',
 'uploadvirus' => 'Denne fil indeholder en virus! Virusnavn: $1',
 'uploadjava' => 'Denne fil er en ZIP-fil, der indeholder en Java .class-fil.
 Det er ikke tilladt at uploade Javafiler, da det kan forårsage, at sikkerhedsrestriktioner bliver sprunget over.',
@@ -2104,10 +2118,20 @@ Hver linje indeholder henvisninger til den første og den anden omdirigering, s
 'deadendpagestext' => 'De følgende sider henviser ikke til andre sider i denne wiki.',
 'protectedpages' => 'Skrivebeskyttede sider',
 'protectedpages-indef' => 'Kun beskyttelser på ubestemt tid',
+'protectedpages-summary' => 'Denne side indeholder en liste over eksisterende sider, der i øjeblikket er beskyttet. For en liste over titler, der er beskyttet fra oprettelse, se [[{{#special:ProtectedTitles}}]].',
 'protectedpages-cascade' => 'Kun nedarvende beskyttelser',
 'protectedpages-noredirect' => 'Skjul omdirigeringer',
 'protectedpagesempty' => 'I øjeblikket er ingen sider beskyttet på denne måde.',
+'protectedpages-timestamp' => 'Tidsstempel',
+'protectedpages-page' => 'Side',
+'protectedpages-expiry' => 'Udløber',
+'protectedpages-performer' => 'Beskyttende bruger',
+'protectedpages-params' => 'Beskyttelsesparametre',
+'protectedpages-reason' => 'Årsag',
+'protectedpages-unknown-timestamp' => 'Ukendt',
+'protectedpages-unknown-performer' => 'Ukendt bruger',
 'protectedtitles' => 'Beskyttede sidenavne',
+'protectedtitles-summary' => 'Denne side indeholder en liste over titler, der i øjeblikket er beskyttet fra oprettelse. For en liste over eksisterende sider, der er beskyttet, se [[{{#special:ProtectedPages}}]].',
 'protectedtitlesempty' => 'Der er ingen sidetitler der er beskyttet med disse parametre.',
 'listusers' => 'Brugerliste',
 'listusers-editsonly' => 'Vis kun brugere med redigeringer',
@@ -2294,6 +2318,7 @@ Fremtidige ændringer af denne side og dens tilknyttede diskussionsside vil bliv
 'watchmethod-list' => 'Tjekker seneste ændringer for sider i din overvågningsliste',
 'watchlistcontains' => 'Din overvågningsliste indeholder $1 {{PLURAL:$1|side|sider}}.',
 'iteminvalidname' => "Problem med '$1', ugyldigt navn...",
+'wlnote2' => 'Nedenfor ses ændringerne i {{PLURAL:$1|den sidste time|de sidste <strong>$1</strong> timer}} op til den $2 kl. $3.',
 'wlshowlast' => 'Vis de seneste $1 timer $2 dage $3',
 'watchlist-options' => 'Indstillinger for overvågningslisten',
 
@@ -2378,7 +2403,7 @@ Bekræft venligst at du virkelig vil gøre dette, at du forstår konsekvenserne,
 'delete-edit-reasonlist' => 'Rediger sletningsårsager',
 'delete-toobig' => 'Denne side har en stor historik, over {{PLURAL:$1|en version|$1 versioner}}. Sletning af sådanne sider er begrænset, for at forhindre utilsigtet forstyrrelse af {{SITENAME}}.',
 'delete-warning-toobig' => 'Denne side har en stor historik, over {{PLURAL:$1|en version|$1 versioner}} versioner, slettes den kan det forstyrre driften af {{SITENAME}}, gå forsigtigt frem.',
-'deleting-backlinks-warning' => "'''Advarsel:''' Andre sider linker til den side, du er ved at slette.",
+'deleting-backlinks-warning' => "'''Advarsel:''' Andre sider linker til eller inkluderer den side, du er ved at slette.",
 
 # Rollback
 'rollback' => 'Fjern redigeringer',
@@ -2554,6 +2579,7 @@ Den seneste post i blokeringsloggen vises nedenfor:',
 'sp-contributions-search' => 'Søg efter bidrag',
 'sp-contributions-username' => 'IP-adresse eller brugernavn:',
 'sp-contributions-toponly' => 'Vis kun redigeringer, der er aktuelle versioner',
+'sp-contributions-newonly' => 'Vis kun redigeringer, der er sideoprettelser',
 'sp-contributions-submit' => 'Søg',
 
 # What links here
@@ -2613,6 +2639,7 @@ Angiv en konkret begrundelse herunder (for eksempel med angivelse af sider der h
 Se [[Special:BlockList|blokeringslisten]] for alle blokeringer.',
 'ipb-blockingself' => 'Du er ved at blokere dig selv! Er du sikker på, du vil gøre det?',
 'ipb-confirmhideuser' => 'Du er ved at blokere en bruger med "skjul bruger" aktiveret. Dette vil skjule brugerens navn på alle lister og logposter. Er du sikker på du vil gøre det?',
+'ipb-confirmaction' => 'Hvis du er sikker på, at du virkelig ønsker at gøre det, kan du markerer feltet "{{int:ipb-confirm}}" nederst.',
 'ipb-edit-dropdown' => 'Rediger blokeringsbegrundelser',
 'ipb-unblock-addr' => 'Ophæv blokeringen af "$1"',
 'ipb-unblock' => 'Frigive IP-adresse/bruger',
@@ -2654,8 +2681,8 @@ Se [[Special:BlockList|blokeringslisten]] for alle blokeringer.',
 'change-blocklink' => 'ændring af blokering',
 'contribslink' => 'bidrag',
 'emaillink' => 'send e-mail',
-'autoblocker' => 'Du er automatisk blokeret, fordi du deler IP-adresse med "[[User:$1|$1]]".
-Begrundelse: "$2".',
+'autoblocker' => 'Du er automatisk blokeret, fordi din IP-adresse for nylig er blevet brugt af "[[User:$1|$1]]".
+Begrundelsen for blokeringen af $1 er "$2".',
 'blocklogpage' => 'Blokeringslog',
 'blocklog-showlog' => 'Denne bruger har tidligere været blokeret.
 Blokeringsloggen vises nedenfor som reference:',
@@ -2677,7 +2704,7 @@ Se [[Special:BlockList|blokeringslisten]] for den nuværende liste med aktuelle
 'range_block_disabled' => 'Sysop-muligheden for at oprette blokeringsklasser er slået fra.',
 'ipb_expiry_invalid' => 'Udløbstiden er ugyldig.',
 'ipb_expiry_temp' => 'Brugernavnet kan kun skjules ved permanente blokeringer.',
-'ipb_hide_invalid' => 'Kan ikke skjule denne konto; den kan have for mange redigeringer.',
+'ipb_hide_invalid' => 'Kan ikke skjule denne konto; den har mere end {{PLURAL:$1|en redigering|$1 redigeringer}}.',
 'ipb_already_blocked' => '„$1“ er allerede blokeret',
 'ipb-needreblock' => '$1 er allerede blokeret. Vil du ændre indstillingerne?',
 'ipb-otherblocks-header' => 'Yderligere {{PLURAL:$1|blokering|blokeringer}}',
@@ -2839,6 +2866,7 @@ Besøg venligst [https://www.mediawiki.org/wiki/Localisation MediaWiki-lokaliser
 'allmessages-prefix' => 'Filtrér efter forstavelse:',
 'allmessages-language' => 'Sprog:',
 'allmessages-filter-submit' => 'Udfør',
+'allmessages-filter-translate' => 'Oversæt',
 
 # Thumbnails
 'thumbnail-more' => 'Forstør',
@@ -2889,7 +2917,7 @@ Alle Transwiki import-aktioner protokolleres i [[Special:Log/import|import-logge
 'importuploaderrortemp' => 'Upload af importfil mislykkedes da en midlertidig mappe mangler.',
 'import-parse-failure' => 'XML fortolkningsfejl under importering',
 'import-noarticle' => 'Der er ingen sider at importere!',
-'import-nonewrevisions' => 'Alle versioner er allerede importeret.',
+'import-nonewrevisions' => 'Ingen versioner importeret (alle var enten allerede til stede, eller blev sprunget over på grund af fejl).',
 'xml-error-string' => '$1 på linje $2, kolonne $3 (byte $4): $5',
 'import-upload' => 'Upload XML-data',
 'import-token-mismatch' => 'Sessionsdata er mistet. Prøv venligst igen.',
@@ -2900,6 +2928,7 @@ Alle Transwiki import-aktioner protokolleres i [[Special:Log/import|import-logge
 'import-error-special' => 'Siden "$1" importeres ikke, da den tilhører et særligt navnerum, der ikke tillader sider.',
 'import-error-invalid' => 'Siden "$1" importeres ikke, da dens navn er ugyldigt.',
 'import-error-unserialize' => 'Ændring $2 af siden "$1" kunne ikke afserialiseres. Ændringen brugte indholdsmodel $3 serialiseret som $4.',
+'import-error-bad-location' => 'Version $2 der bruger indholdsmodellen $3 kan ikke gemmes på "$1" på denne wiki, da denne model ikke understøttes på denne side.',
 'import-options-wrong' => '{{PLURAL:$2|Ugyldig indstilling|Ugyldige indstillinger}}: <nowiki>$1</nowiki>',
 'import-rootpage-invalid' => 'Den rodside der er angivet har en ugyldig titel.',
 'import-rootpage-nosubpage' => 'Navnerummet "$1" tillader ikke undersider af rodsiderne.',
index 1adc184..9e39cfb 100644 (file)
@@ -999,7 +999,7 @@ Um die Anmeldung abzuschließen, musst du jetzt ein neues Passwort festlegen:',
 'resetpass-temp-password' => 'Temporäres Passwort:',
 'resetpass-abort-generic' => 'Die Passwortänderung wurde durch eine Erweiterung abgebrochen.',
 'resetpass-expired' => 'Dein Passwort ist abgelaufen. Bitte lege ein neues Passwort zur Anmeldung fest.',
-'resetpass-expired-soft' => 'Dein Passwort ist abgelaufen und muss zurückgesetzt werden. Bitte wähle jetzt ein neues Passwort aus oder klicke auf „Abbrechen“, um es später zurückzusetzen.',
+'resetpass-expired-soft' => 'Dein Passwort ist abgelaufen und muss zurückgesetzt werden. Bitte wähle jetzt ein neues Passwort aus oder klicke auf „{{int:resetpass-submit-cancel}}“, um es später zurückzusetzen.',
 
 # Special:PasswordReset
 'passwordreset' => 'Passwort zurücksetzen',
@@ -1242,8 +1242,7 @@ Zur Information folgt der aktuelle Logbucheintrag:",
 'sectioneditnotsupported-text' => 'Die Bearbeitung von Abschnitten wird auf dieser Bearbeitungsseite nicht unterstützt.',
 'permissionserrors' => 'Berechtigungsfehler',
 'permissionserrorstext' => 'Du bist nicht berechtigt, die Aktion auszuführen. {{PLURAL:$1|Grund|Gründe}}:',
-'permissionserrorstext-withaction' => 'Du bist nicht berechtigt, $2.
-{{PLURAL:$1|Grund|Gründe}}:',
+'permissionserrorstext-withaction' => 'Du bist aus {{PLURAL:$1|dem folgenden Grund|den folgenden Gründen}} nicht berechtigt, $2:',
 'recreate-moveddeleted-warn' => "'''Achtung: Du erstellst eine Seite, die bereits früher gelöscht wurde.'''
 
 Bitte prüfe sorgfältig, ob die erneute Seitenerstellung den Richtlinien entspricht.
@@ -1844,14 +1843,26 @@ Diese Information ist öffentlich.',
 'recentchanges-legend-heading' => "'''Legende:'''",
 'recentchanges-legend-newpage' => '(siehe auch die [[Special:NewPages|Liste neuer Seiten]])',
 'recentchanges-legend-plusminus' => "''(±123)''",
-'rcnotefrom' => "Angezeigt werden die Änderungen seit '''$2''' (max. '''$1''' Einträge).",
-'rclistfrom' => 'Nur Änderungen seit $1 zeigen.',
+'rcnotefrom' => 'Angezeigt werden die Änderungen seit <strong>$2</strong> (max. <strong>$1</strong> Einträge).',
+'rclistfrom' => 'Nur Änderungen seit $3, $2 Uhr zeigen.',
 'rcshowhideminor' => 'Kleine Änderungen $1',
+'rcshowhideminor-show' => 'anzeigen',
+'rcshowhideminor-hide' => 'ausblenden',
 'rcshowhidebots' => 'Bots $1',
+'rcshowhidebots-show' => 'anzeigen',
+'rcshowhidebots-hide' => 'ausblenden',
 'rcshowhideliu' => 'Registrierte Benutzer $1',
+'rcshowhideliu-show' => 'anzeigen',
+'rcshowhideliu-hide' => 'ausblenden',
 'rcshowhideanons' => 'Unangemeldete Benutzer $1',
+'rcshowhideanons-show' => 'anzeigen',
+'rcshowhideanons-hide' => 'ausblenden',
 'rcshowhidepatr' => 'Kontrollierte Änderungen $1',
+'rcshowhidepatr-show' => 'anzeigen',
+'rcshowhidepatr-hide' => 'ausblenden',
 'rcshowhidemine' => 'Eigene Beiträge $1',
+'rcshowhidemine-show' => 'anzeigen',
+'rcshowhidemine-hide' => 'ausblenden',
 'rclinks' => 'Zeige die letzten $1 Änderungen der letzten $2 Tage.<br />$3',
 'diff' => 'Unterschied',
 'hist' => 'Versionen',
@@ -1976,6 +1987,8 @@ Du solltest jemanden fragen, der die Möglichkeit hat, die unterdrückten Dateid
 'php-uploaddisabledtext' => 'Das Hochladen von Dateien wurde in PHP deaktiviert.
 Bitte überprüfe die <code>file_uploads</code>-Einstellung.',
 'uploadscripted' => 'Diese Datei enthält HTML- oder Scriptcode, der irrtümlich von einem Webbrowser ausgeführt werden könnte.',
+'uploadscriptednamespace' => 'Diese SVG-Datei enthält den ungültigen Namensraum „$1“.',
+'uploadinvalidxml' => 'Das XML in der hochgeladenen Datei konnte nicht geparst werden.',
 'uploadvirus' => 'Diese Datei enthält einen Virus! Details: $1',
 'uploadjava' => 'Dies ist eine ZIP-Datei, die ein CLASS-Datei von Java enthält.
 Das Hochladen von Java-Dateien ist nicht gestattet, da sie die Umgehung von Sicherheitseinschränkungen ermöglichen könnten.',
@@ -2795,6 +2808,7 @@ Zur Information folgt der aktuelle Auszug aus dem Sperr-Logbuch:',
 'sp-contributions-search' => 'Suche nach Benutzerbeiträgen',
 'sp-contributions-username' => 'IP-Adresse oder Benutzername:',
 'sp-contributions-toponly' => 'Nur aktuelle Versionen zeigen',
+'sp-contributions-newonly' => 'Nur Seitenerstellungen anzeigen',
 'sp-contributions-submit' => 'Suchen',
 
 # What links here
@@ -4355,6 +4369,4 @@ faktisch alles was in doppelten geschweiften Klammern enthalten ist.',
 'expand_templates_generate_rawhtml' => 'Rohes HTML anzeigen',
 'expand_templates_preview' => 'Vorschau',
 
-# Unknown messages
-'uploadinvalidxml' => 'Das XML in der hochgeladenen Datei konnte nicht geparst werden.',
 );
index 7df29e4..a1f4dd1 100644 (file)
@@ -633,8 +633,8 @@ $1',
 'feed-atom' => 'Atom',
 'feed-rss' => 'RSS',
 'red-link-title' => '$1 (çınya)',
-'sort-descending' => 'Ratnayışê qemeyayışi',
-'sort-ascending' => 'Ratnayışê Zeydnayışi',
+'sort-descending' => 'Rêzkerdışo kêmbiyaye',
+'sort-ascending' => 'Rêzkerdışo zêdiyaye',
 
 # Short words for each namespace, by default used in the namespace tab in monobook
 'nstab-main' => 'Wesiqe',
@@ -779,7 +779,7 @@ Wexta ke verhafızayê cıgerayoxê şıma pak beno no benate de taye peli de he
 'userlogin-joinproject' => 'Cıkewe {{SITENAME}}',
 'nologin' => "Hesabê şıma çıniyo? '''$1'''.",
 'nologinlink' => 'Yew hesab ake',
-'createaccount' => 'Hesab vıraşten',
+'createaccount' => 'Hesab vıraze',
 'gotaccount' => "Hesabê şıma esto? '''$1'''.",
 'gotaccountlink' => 'Cı kewe',
 'userlogin-resetlink' => 'Melumatê cıkewtışi xo vira kerdê?',
@@ -875,6 +875,9 @@ Bıne vındere u newe ra dest pê bıkere.',
 'suspicious-userlogout' => 'Waştişê tu ya veciyayişi kebul nibiya cunki ihtimal o ke waştiş yew browser ya zi proksiyê heripiyaye ra ameya.',
 'createacct-another-realname-tip' => 'Nameyo raştıkên keyfiyo.
 Şıma nameyo xoyo raştıkên ke bımocnê, seba iştırakanê karberi be ney ra istıfade beno.',
+'pt-login' => 'Cı kewe',
+'pt-createaccount' => 'Hesab vıraze',
+'pt-userlogout' => 'Veciyayış',
 
 # Email sending
 'php-mail-error-unknown' => "PHP's mail() fonksiyoni de xırabin vıcyê.",
@@ -883,7 +886,7 @@ Bıne vındere u newe ra dest pê bıkere.',
 
 # Change password dialog
 'changepassword' => 'Parola bıvurne',
-'resetpass_announce' => 'Şıma pê yew parolayê muweqqet hesab kerd a, qey qedyayişe dekewtış newe yew parola bınuse:',
+'resetpass_announce' => 'Seba temamkerdışê cıkewtışi rê, şıma gani yew parolaya newiye bınusê.',
 'resetpass_text' => 'Parolayê hesab bıvurn',
 'resetpass_header' => 'Parola hesabi bıvurne',
 'oldpassword' => 'Parola kıhane:',
@@ -898,6 +901,7 @@ Bıne vındere u newe ra dest pê bıkere.',
 'resetpass-submit-cancel' => 'Bıtexelne',
 'resetpass-wrong-oldpass' => 'parolayo parola maqbul niyo.
 şıma ya parolaye xo vurnayo ya zi parolayo muwaqqat waşto.',
+'resetpass-recycled' => 'Parolaya şımaya newiye wa paroloya şımaya verêne ra ferqıne bo.',
 'resetpass-temp-password' => 'parolayo muweqet:',
 'resetpass-abort-generic' => 'Parola vurnayış jew derganey ra tepya ibtal biyo',
 
@@ -1046,13 +1050,12 @@ Qey na hesabê newe parola, cıkewtış dıma şıma eşkeni na qısım de ''[[S
 Seba afernayışê pele ra, qutiya metnê cêrêni bıgurene (seba melumati qaytê [[{{MediaWiki:Helppage}}|pela peşti]] ke).
 Eke be ğeletine ameya tiya, wa gocega '''peyser'''i programê xo de bıtıkne.",
 'anontalkpagetext' => "----''No pel, pel o karbero hesab a nêkerdeyan o, ya zi karbero hesab akerdeyan o labele pê hesabê xo nêkewto de. No sebeb ra ma IP adres şuxulneni û ney IP adresan herkes eşkeno bıvino. Eke şıma qayil niye ina bo xo ri [[Special:UserLogin/signup|yew hesab bıvıraze]] veyaxut [[Special:UserLogin|hesab akere]].''",
-'noarticletext' => 'Na per enewke venga.
-Tı şenay na perer, peran de [[Special:Search/{{PAGENAME}}|binan miyan de bıgeyrè]],
-<span class="plainlinks">[{{fullurl:{{#Special:Log}}|page={{FULLPAGENAMEE}}}}  qeyda miyande bıgeyre],
-ya na [{{fullurl:{{FULLPAGENAME}}|action=edit}} ena perer vırazé]</span>.',
-'noarticletext-nopermission' => 'Na pela dı eno metin enewke vengo
-Na sernuşteya şıma [[Special:Search/{{PAGENAME}}|pelanê binan de şeni bıgeyri]]
-ya zi <span class="plainlinks">[{{fullurl:{{#Special:Log}}|page={{FULLPAGENAMEE}}}} itara şeni bıgeyri cı].</span> feqet şıma nişeni biizın teba bıkeri.',
+'noarticletext' => 'Ena pele de hewna theba çıniyo.
+Tı şenay zerreyê pelanê binan de [[Special:Search/{{PAGENAME}}|seba sernameyê ena pele cı geyre]],
+<span class="plainlinks">[{{fullurl:{{#Special:Log}}|page={{FULLPAGENAMEE}}}} qeydan miyan de cı geyre],
+ya zi [{{fullurl:{{FULLPAGENAME}}|action=edit}} ena pele bıvurne]</span>.',
+'noarticletext-nopermission' => 'Ena pele de hewna theba çıniyo.
+Tı şenay zerreyê pelanê binan de [[Special:Search/{{PAGENAME}}|seba sernameyê na pele cı geyre]], ya zi <span class="plainlinks">[{{fullurl:{{#Special:Log}}|page={{FULLPAGENAMEE}}}} qeydan miyan de cı geyre]</span>, ema destur çıniyo ke na pele vırazê.',
 'missing-revision' => 'Rewizyonê name dê pela da #$1 "{{PAGENAME}}" dı çıniyo.
 
 No normal de tarix dê pelanê besterneyan dı ena xırabin asena.
@@ -1155,7 +1158,7 @@ Hewna kerde aseno.',
 'postedit-confirmation' => 'Vurnayışê to qeyd bi.',
 'edit-already-exists' => 'Pelo newe nêvıraziyeno.
 Pel ca ra esto.',
-'defaultmessagetext' => 'Hesıbyaye metne mesaci',
+'defaultmessagetext' => 'Metnê mesacê hesabiyayey',
 'content-failed-to-parse' => 'Qandê madela $3 zereyê $1, $2 sero nêagozyayo',
 'invalid-content-data' => 'Zerrey malumati nêravêrdeyo',
 'content-not-allowed-here' => '"$1" sero per da [[$2]] rê mısade nêdeyêno',
@@ -1742,11 +1745,23 @@ Eka tu wazene ke nameyo raşt xo bide, ma nameyo raşt ti iştirakanê ti de moc
 'rcnotefrom' => "Cêr de '''$2''' ra nata vurnayışiyê asenê (tewr vêşi <b> '''$1'''</b> asenê).",
 'rclistfrom' => '$1 ra tepiya vurnayışanê neweyan bımocne',
 'rcshowhideminor' => 'Vurnayışanê werdiyan $1',
+'rcshowhideminor-show' => 'Bımocne',
+'rcshowhideminor-hide' => 'Bınımne',
 'rcshowhidebots' => 'Botan $1',
+'rcshowhidebots-show' => 'Bımocne',
+'rcshowhidebots-hide' => 'Bınımne',
 'rcshowhideliu' => 'Karberanê qeydbiyayeyan $1',
+'rcshowhideliu-show' => 'Bımocne',
+'rcshowhideliu-hide' => 'Bınımne',
 'rcshowhideanons' => 'Karberanê bênameyan $1',
+'rcshowhideanons-show' => 'Bımocne',
+'rcshowhideanons-hide' => 'Bınımne',
 'rcshowhidepatr' => '$1 vurnayışê ke dewriya geyrayê',
+'rcshowhidepatr-show' => 'Bımocne',
+'rcshowhidepatr-hide' => 'Bınımne',
 'rcshowhidemine' => 'Vurnayışanê mı $1',
+'rcshowhidemine-show' => 'Bımocne',
+'rcshowhidemine-hide' => 'Bınımne',
 'rclinks' => 'Peyniya $2 rocan de $1 vurnayışan bımocne <br />$3',
 'diff' => 'ferq',
 'hist' => 'verên',
@@ -1869,6 +1884,7 @@ Semedê ancia barkerdışi dewamkerdış ra ver tarixê esterışê dosya gani q
 'uploaddisabledtext' => 'Bar kerdişê dosyayî iptal biyo',
 'php-uploaddisabledtext' => 'barkerdışê dosyayê PHP nıka çino. kerem kere eyarê file_uploads korol bıkerê.',
 'uploadscripted' => 'Ena dosya de yew HTML ya zi kodê scriptî este ke belki browserê webî fam nikeno.',
+'uploadinvalidxml' => 'Dosyaya barkerdiye de XML nêgureniya.',
 'uploadvirus' => 'Ena dosya de yew virus estê: Qe detayan: $1',
 'uploadjava' => 'Dosya, zerre de cıdı jew Java .class dosyaya ZIP esta.
 Dosyayn de Java barkerdışi rê icazet nêdeyê, çıkı emeleya merduman nêbena.',
@@ -3092,7 +3108,7 @@ dosyaya emaneti vindbiyo',
 'tooltip-pt-login' => 'Mayê şıma ronıştış akerdışi rê dawet keme; labelê ronıştış mecburi niyo',
 'tooltip-pt-logout' => 'Sistem ra vıcyayış',
 'tooltip-ca-talk' => 'Zerrekê pele sero werênayış',
-'tooltip-ca-edit' => 'Tı şenay na perer bıvurné.Verdé qeyd kerdışi ver gocega verqayti bıkarné.',
+'tooltip-ca-edit' => 'Tı şenay na pele bıvurnê. Kerem ke, qeydkerdış ra ver gocega verqayti bıgurene.',
 'tooltip-ca-addsection' => 'Zu bınnusteya newi ak',
 'tooltip-ca-viewsource' => 'Ena pele kılit biya.
 Şıma şenê çımeyê aye bıvênê',
@@ -3103,7 +3119,7 @@ dosyaya emaneti vindbiyo',
 'tooltip-ca-undelete' => 'peli biyarê halê ver hewnakerdışi',
 'tooltip-ca-move' => 'Ena pele bere',
 'tooltip-ca-watch' => 'Ena pele lista xoya seyrkerdışi ke',
-'tooltip-ca-unwatch' => 'Ena pele listeya seyir-kerdışi xo ra bıvec',
+'tooltip-ca-unwatch' => 'Ena pele lista xoya seyrkerdışi ra vece',
 'tooltip-search' => '{{SITENAME}} miyan de bıvin',
 'tooltip-search-go' => 'Ebe nê namey tami şo yew pela ke esta',
 'tooltip-search-fulltext' => 'Nê  metni peran dı cı geyre',
@@ -3131,7 +3147,7 @@ dosyaya emaneti vindbiyo',
 'tooltip-ca-nstab-special' => 'Na yew pela xasa, şıma nêşenê sero vurnayış bıkerê',
 'tooltip-ca-nstab-project' => 'Pela procey bıvêne',
 'tooltip-ca-nstab-image' => 'Pera dosyayer bıvin',
-'tooltip-ca-nstab-mediawiki' => 'Mesacané sistemi bıvin',
+'tooltip-ca-nstab-mediawiki' => 'Mesacê sistemi bıvêne',
 'tooltip-ca-nstab-template' => 'Şabloni bıvin',
 'tooltip-ca-nstab-help' => 'Pela peşti bıvêne',
 'tooltip-ca-nstab-category' => 'Pela kategoriye bıvêne',
@@ -3140,7 +3156,7 @@ dosyaya emaneti vindbiyo',
 'tooltip-preview' => 'Vurnayışané ğo çımra ravyarné. Verdé qeyd kerdışi eneri bıkarné!',
 'tooltip-diff' => 'Metni sero vurnayışan mocneno',
 'tooltip-compareselectedversions' => 'Ena per de ferqê rewziyonan de dı weçinaya bıvinê',
-'tooltip-watch' => 'Eno pele listey tıyo seyir-kerdişi ri dek',
+'tooltip-watch' => 'Ena pele lista xoya seyrkerdışi ke',
 'tooltip-watchlistedit-normal-submit' => 'Sernuşteya hewad',
 'tooltip-watchlistedit-raw-submit' => 'Listeyê seyri newen ke',
 'tooltip-recreate' => 'pel hewn a bışiyo zi tepiya biya',
@@ -3963,7 +3979,7 @@ Ma rica keno tesdiq bike ke ti raştî wazeno eno pel bivirazo.",
 'imgmultigoto' => 'Şo pela da $1',
 
 # Language selector for translatable SVGs
-'img-lang-default' => '(hesıbyayi zıwan)',
+'img-lang-default' => '(zıwano hesabiyaye)',
 'img-lang-info' => 'Resimé $1, $2 ya teké pé ke.',
 'img-lang-go' => 'Bırş',
 
@@ -4415,6 +4431,4 @@ Eneri Medya wiki sera xo keno.',
 'expand_templates_generate_rawhtml' => "Xam HTML'i bıvin",
 'expand_templates_preview' => 'Verqayt',
 
-# Unknown messages
-'uploadinvalidxml' => 'Dosyaya barkerdiye de XML nêgureniya.',
 );
index 3b076f1..5f61e3d 100644 (file)
@@ -714,7 +714,7 @@ Sy snaź swójo gronidło južo wuspěšnje změnił abo nowe nachylne gronidło
 'resetpass-temp-password' => 'Nachylne gronidło:',
 'resetpass-abort-generic' => 'Změnjanje gronidła jo se pśez rozšyrjenje pśetergnuło.',
 'resetpass-expired' => 'Twójo gronidło jo pśepadnyło. Pšosym póstaj nowe gronidło za pśizjawjenje.',
-'resetpass-expired-soft' => 'Twójo gronidło jo pśepadnyło a musy se slědk stajiś. Pšosym wubjeŕ něnto druge gronidło abo klikni na "Pśetergnuś", aby jo pózdźej slědk stajił.',
+'resetpass-expired-soft' => 'Twójo gronidło jo pśepadnyło a musy se slědk stajiś. Pšosym wubjeŕ něnto druge gronidło abo klikni na "{{int:resetpass-submit-cancel}}", aby jo pózdźej slědk stajił.',
 
 # Special:PasswordReset
 'passwordreset' => 'Gronidło slědk stajiś',
@@ -1542,14 +1542,26 @@ Toś ta informacija buźo zjawna.',
 'recentchanges-legend-heading' => "'''Legenda:'''",
 'recentchanges-legend-newpage' => '(glej teke [[Special:NewPages|lisćinu nowych bokow]])',
 'recentchanges-legend-plusminus' => "(''±123'')",
-'rcnotefrom' => "Dołojce pokazuju se změny wót '''$2''' (maks. '''$1''' zapisow).",
+'rcnotefrom' => 'Dołojce pokazuju se změny wót <strong>$2</strong> (maks. <strong>$1</strong> zapisow).',
 'rclistfrom' => 'Nowe změny wót $1 pokazaś.',
 'rcshowhideminor' => 'Snadne změny $1',
+'rcshowhideminor-show' => 'Pokazaś',
+'rcshowhideminor-hide' => 'Schowaś',
 'rcshowhidebots' => 'awtomatiske programy (boty) $1',
+'rcshowhidebots-show' => 'Pokazaś',
+'rcshowhidebots-hide' => 'Schowaś',
 'rcshowhideliu' => 'Zregistrěrowane wužywarje $1',
+'rcshowhideliu-show' => 'Pokazaś',
+'rcshowhideliu-hide' => 'Schowaś',
 'rcshowhideanons' => 'anonymne wužywarje $1',
+'rcshowhideanons-show' => 'Pokazaś',
+'rcshowhideanons-hide' => 'Schowaś',
 'rcshowhidepatr' => 'kontrolěrowane změny $1',
+'rcshowhidepatr-show' => 'Pokazaś',
+'rcshowhidepatr-hide' => 'Schowaś',
 'rcshowhidemine' => 'móje pśinoski $1',
+'rcshowhidemine-show' => 'Pokazaś',
+'rcshowhidemine-hide' => 'Schowaś',
 'rclinks' => 'Slědne $1 změny slědnych $2 dnjow pokazaś<br />$3',
 'diff' => 'rozdźěl',
 'hist' => 'wersije',
@@ -1673,6 +1685,8 @@ Jolic maš toś ten wobraz w połnem rozeznaśu, nagraj jen, howac změń pšosy
 'uploaddisabledtext' => 'Nagraśa datajow su znjemóžnjone.',
 'php-uploaddisabledtext' => 'Nagraśa PHP-datajow su znjemóžnjone. Pšosym pśekontrolěruj nastajenje file_uploads.',
 'uploadscripted' => 'Toś ta dataja wopśimjejo HTML abo script code, kótaryž móžo wót browsera se zamólnje wuwjasć.',
+'uploadscriptednamespace' => "Toś ta SVG-dataja wopśimujo njedowólony mjenjowy rum '$1'",
+'uploadinvalidxml' => 'XML w nagratej dataji njedajo se parsowaś.',
 'uploadvirus' => 'Toś ta dataja ma wirus! Nadrobnosći: $1',
 'uploadjava' => 'Toś ta dataja jo ZIP-dataja, kótaraž wopśimujo dataju .class z Javy.
 Nagrawanje datajow Javy njejo dowólone, dokulaž mógli wobjeźenje wěstotnych wobgranicowanjow zmóžniś.',
@@ -2489,6 +2503,7 @@ Nejnowšy zapisk protokola blokěrowanjow pódawa se dołojce ako referenca:',
 'sp-contributions-search' => 'Pśinoski pytaś',
 'sp-contributions-username' => 'IP-adresa abo wužywarske mě:',
 'sp-contributions-toponly' => 'Jano wuše wersije pokazaś',
+'sp-contributions-newonly' => 'Jano změny pokazaś, kótarež su napóranja bokow',
 'sp-contributions-submit' => 'Pytaś',
 
 # What links here
@@ -3992,6 +4007,4 @@ Hować móžoš slědujucy jadnory formular wužywaś. Twój komentar pśidajo s
 'expand_templates_generate_rawhtml' => 'Gropny HTML pokazaś',
 'expand_templates_preview' => 'Pśeglěd',
 
-# Unknown messages
-'uploadinvalidxml' => 'XML w nagratej dataji njedajo se parsowaś.',
 );
index 5557021..a68edc3 100644 (file)
@@ -528,6 +528,9 @@ Se l'inscrisiòun l'é stêda fâta per şbâli, es pōl scanşlêr sté mesâg.
 'loginlanguagelabel' => 'Léngva: $1',
 'suspicious-userlogout' => "La tó dmânda per destachêret l'é stēda rifiutêda perchè la sèmbra spidîda da un navigadōr ch' al funsiòuna mìa o da un proxy di caching.",
 'createacct-another-realname-tip' => "Druvêr al nòm vèira l'é 'na siēlta personêla; s' es pèinsa 'd ruvêrel al gnirâ uşê per dêr la paternitê di lavōr spidî.",
+'pt-login' => 'Và dèinter',
+'pt-createaccount' => 'Fà la tó inscrisiòun',
+'pt-userlogout' => 'Và fōra',
 
 # Email sending
 'php-mail-error-unknown' => 'Erōr mìa cngusû int la funsiòun PHP mail().',
@@ -550,8 +553,11 @@ Se l'inscrisiòun l'é stêda fâta per şbâli, es pōl scanşlêr sté mesâg.
 'resetpass-submit-cancel' => 'Scanşèla',
 'resetpass-wrong-oldpass' => "Cêva 'd ingrès pruvişôria o còla 'd adès mìa vâlida.
 La cêva 'd ingrès la pré èser stêda bèle cambiêda, opór n'in pré èser stê dmandê 'na nōva pruvişôria.",
+'resetpass-recycled' => "Mèt dèinter 'na cêva 'd ingrès divêrsa da còla 'd adès.",
 'resetpass-temp-password' => "Cêva 'd ingrès pruvişôria:",
 'resetpass-abort-generic' => "La mudéfica 'd la cêva 'd ingrès l'é stêda fermêda da un şlungamèint.",
+'resetpass-expired' => "La cêva 'd ingrès l'é scadûda. Mèt dèinter 'na cêva 'd ingrès nōva per fêr l'ingrès.",
+'resetpass-expired-soft' => "La tó cêva 'd ingrès l'é scadûda. T'é perghê ed siēlier 'na nōva o clichêr insém a \"{{int:resetpass-submit-cancel}}\" per turnêrla a mèter dèinter in sègvit.",
 
 # Special:PasswordReset
 'passwordreset' => "Câmbia la cêva 'd ingrès",
@@ -604,6 +610,7 @@ Cêva 'd ingrès pruvişôria: $2",
 'resettokens-text' => "Ché 't pō turnêr a impustêr al cêvi ch'ét permèten l'ingrès a precîşi infurmasiòun privêdi lighêdi a la tó utèinsa. Ét duvrés fêrel se per chêş ét j ê spartîdi cun quelchidûn o se al j infurmasiòun ed la tó utèinsa în  in perécol.",
 'resettokens-no-tokens' => "An gh'é mìa di token da turnêr a impustêr.",
 'resettokens-legend' => "Tōrna 'd impustêr la cêva",
+'resettokens-tokens' => ' Token:',
 'resettokens-token-label' => "$1 (valōr 'd adèsa: $2)",
 'resettokens-watchlist-token' => "Token p'r al feed web (Atom/RSS) dal [[Special:Watchlist|mudéfichi al pàgini ch'ét tîn sòt' ôc]]",
 'resettokens-done' => 'Token turnê a impustêr.',
@@ -896,7 +903,7 @@ Per cumditê còst l'é l'èlèinch dal scanşladûri e di spustamèint relatîv
 'recentchanges-label-minor' => "Còsta l'é 'na mudéfica céca",
 'recentchanges-label-bot' => "Cla mudéfica ché l'é stêda fâta da un bot.",
 'recentchanges-label-unpatrolled' => "Cla mudéfica ché an n'é mìa incòra stêda verifichêda.",
-'rcnotefrom' => "Ché sòt a gh'é la lésta dal mudéfichi fâti a partîr da '''$2''' (fîn a '''$1''').",
+'rcnotefrom' => "Ché sòt a gh'é la lésta dal mudéfichi fâti a partîr da <strong>$2</strong>(fîn a <strong>$1</strong>).",
 'rclistfrom' => 'Fà vèder al mudéfichi fâti a partîr da $1.',
 'rcshowhideminor' => '$1 al mudéfichi céchi',
 'rcshowhidebots' => '$1 i bot',
index b1a80a0..772c7f6 100644 (file)
@@ -662,8 +662,8 @@ $1',
 'feed-unavailable' => 'Οι ροές δεδομένων δεν είναι διαθέσιμες',
 'site-rss-feed' => '$1 ροή RSS',
 'site-atom-feed' => '$1 ροή Atom',
-'page-rss-feed' => '«$1» ροή RSS',
-'page-atom-feed' => '«$1» ροή Atom',
+'page-rss-feed' => 'Ροή RSS «$1»',
+'page-atom-feed' => 'Ροή Atom «$1»',
 'red-link-title' => '$1 (η σελίδα δεν υπάρχει)',
 'sort-descending' => 'Φθίνουσα ταξινόμηση',
 'sort-ascending' => 'Αύξουσα ταξινόμηση',
@@ -705,7 +705,7 @@ $1',
 'readonlytext' => 'Η βάση δεδομένων είναι επί του παρόντος κλειδωμένη απέναντι σε νέες καταχωρίσεις και άλλες τροποποιήσεις, πιθανότατα λόγω συντήρησης ρουτίνας, μετά την οποία θα επανέλθει σε κανονική λειτουργία.  
 
 Ο διαχειριστής που την κλείδωσε έδωσε την ακόλουθη εξήγηση: $1',
-'missing-article' => 'Η βάση δεδομένων δεν βρήκε κείμενο μιας σελίδας που θα έπρεπε να βρεθεί, με όνομα "$1" $2.
+'missing-article' => 'Η βάση δεδομένων δεν βρήκε κείμενο μιας σελίδας που θα έπρεπε να βρεθεί, με όνομα «$1» $2.
 
 Αυτό συνήθως προκαλείται ακολουθώντας ένα σύνδεσμο "διαφοράς" ή σύνδεσμο προς ιστορικό μιας σελίδας που έχει διαγραφεί.
 
@@ -716,20 +716,20 @@ $1',
 'readonly_lag' => 'Η βάση δεδομένων έχει κλειδωθεί αυτόματα για να μπορέσουν οι επιμέρους servers των αντιγράφων της βάσης δεδομένων (slaves) να καλύψουν τη διαφορά με τον κεντρικό server του πρωτοτύπου της βάσης (master).',
 'internalerror' => 'Εσωτερικό σφάλμα',
 'internalerror_info' => 'Εσωτερικό σφάλμα: $1',
-'fileappenderrorread' => 'Δεν ήταν δυνατή η ανάγνωση του "$1" κατά τη διάρκεια της επισύναψης.',
-'fileappenderror' => 'Δεν ήταν δυνατή η προσάρτηση του αρχείου "$1" στο "$2".',
-'filecopyerror' => 'Δεν ήταν δυνατή η αντιγραφή του αρχείου "$1" στο "$2".',
-'filerenameerror' => 'Δεν είναι δυνατή η μετονομασία του αρχείου "$1" σε "$2".',
-'filedeleteerror' => 'Δεν ήταν δυνατή η διαγραφή του αρχείου "$1".',
-'directorycreateerror' => 'Δεν μπορούσε να δημιουργηθεί η κατηγορία "$1".',
-'filenotfound' => 'Δεν είναι δυνατή η ανεύρεση του αρχείου "$1".',
-'fileexistserror' => 'Αδύνατον να εγγραφεί στο αρχείο "$1": το αρχείο υπάρχει',
-'unexpected' => 'Μη προσδοκώμενη τιμή: "$1"="$2"',
+'fileappenderrorread' => 'Δεν ήταν δυνατή η ανάγνωση του «$1» κατά τη διάρκεια της επισύναψης.',
+'fileappenderror' => 'Δεν ήταν δυνατή η προσάρτηση του αρχείου «$1» στο «$2».',
+'filecopyerror' => 'Δεν ήταν δυνατή η αντιγραφή του αρχείου «$1» στο «$2».',
+'filerenameerror' => 'Δεν είναι δυνατή η μετονομασία του αρχείου «$1» σε «$2».',
+'filedeleteerror' => 'Δεν ήταν δυνατή η διαγραφή του αρχείου «$1».',
+'directorycreateerror' => 'Δεν μπορούσε να δημιουργηθεί η κατηγορία «$1».',
+'filenotfound' => 'Δεν είναι δυνατή η ανεύρεση του αρχείου «$1».',
+'fileexistserror' => 'Αδύνατον να εγγραφεί στο αρχείο «$1»: το αρχείο υπάρχει',
+'unexpected' => 'Μη προσδοκώμενη τιμή: «$1»=«$2».',
 'formerror' => 'Σφάλμα: Δεν ήταν δυνατή η υποβολή της φόρμας!',
 'badarticleerror' => 'Η ενέργεια αυτή δεν μπορεί να εκτελεσθεί στη συγκεκριμένη σελίδα.',
 'cannotdelete' => 'Η σελίδα ή το αρχείο «$1» δεν μπόρεσε να διαγραφεί.
 Ενδεχομένως να έχει ήδη διαγραφεί από κάποιον άλλον.',
-'cannotdelete-title' => 'Αδύνατη η διαγραφή της σελίδας "$1"',
+'cannotdelete-title' => 'Αδύνατη η διαγραφή της σελίδας «$1»',
 'delete-hook-aborted' => 'Η επεξεργασία ματαιώθηκε από το άγκιστρο του συντακτικού αναλυτή.
 Δεν έδωσε εξήγηση.',
 'badtitle' => 'Ακατάλληλος τίτλος',
@@ -759,11 +759,11 @@ $2',
 'myprivateinfoprotected' => 'Δεν έχετε άδεια για να επεξεργαστείτε τα προσωπικά σας στοιχεία.',
 'mypreferencesprotected' => 'Δεν έχετε άδεια για να επεξεργαστείτε τις προτιμήσεις σας.',
 'ns-specialprotected' => 'Σελίδες στον τομέα {{ns:special}} δεν γίνεται να επεξεργαστούν.',
-'titleprotected' => "Αυτός ο τίτλος έχει προστατευθεί από την δημιουργία από τον [[User:$1|$1]].
-Ο λόγος που δίνεται είναι ''$2''.",
-'filereadonlyerror' => 'Δεν είναι δυνατή η τροποποίηση του αρχείου " $1 " επειδή το αποθετήριο αρχείων " $2 " είναι σε κατάσταση λειτουργίας μόνο για ανάγνωση.
+'titleprotected' => 'Αυτός ο τίτλος έχει προστατευθεί από την δημιουργία από τον [[User:$1|$1]].
+Ο λόγος που δίνεται είναι «$2».',
+'filereadonlyerror' => 'Δεν είναι δυνατή η τροποποίηση του αρχείου «$1» επειδή το αποθετήριο αρχείων «$2» είναι σε κατάσταση λειτουργίας μόνο για ανάγνωση.
 
-Ο διαχειριστής που το κλείδωσε προσφέρει αυτή την αιτιολόγηση: " $3 ".',
+Ο διαχειριστής που το κλείδωσε προσφέρει αυτή την αιτιολόγηση: «$3».',
 'invalidtitle-knownnamespace' => 'Μη έγκυρος τίτλος με χώρο ονομάτων «$2» και κείμενο «$3»',
 'invalidtitle-unknownnamespace' => 'Μη έγκυρος τίτλος με άγνωστο αριθμό χώρου ονομάτων $1 και κείμενο «$2»',
 'exception-nologin' => 'Δεν έχετε συνδεθεί.',
@@ -1082,7 +1082,7 @@ $2
 Αυτό συνήθως προκαλείται από παλιό σύνδεσμο ιστορικού προς σελίδα που έχει διαγραφεί.
 Λεπτομέρειες θα βρείτε στο [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} ημερολόγιο καταγραφής διαγραφών].',
 'userpage-userdoesnotexist' => 'Ο Λογαριασμός του χρήστη "<nowiki>$1</nowiki>" δεν είναι καταχωρημένος. Παρακαλώ δείτε αν θα θέλατε να δημιουργήσετε/επεξεργαστείτε αυτή τη σελίδα.',
-'userpage-userdoesnotexist-view' => 'Ο λογαριασμός χρήστη "$1" δεν είναι εγγεγραμμένος.',
+'userpage-userdoesnotexist-view' => 'Ο λογαριασμός χρήστη «$1» δεν είναι εγγεγραμμένος.',
 'blocked-notice-logextract' => 'Επί του παρόντος, αυτός ο χρήστης έχει υποστεί φραγή. Παρακάτω παρέχεται για αναφορά η πιο πρόσφατη καταχώρηση του αρχείου φραγών.',
 'clearyourcache' => "''' Σημείωση:''' μετά την αποθήκευση, ίσως χρειαστεί να παρακάμψετε την προσωρινή μνήμη του προγράμματος περιήγησής σας για να δείτε τις αλλαγές.
  * '''Firefox / Safari:''' Κρατήστε πατημένο το ''Shift'' κάνοντας ταυτόχρονα κλικ στο κουμπί ''Ανανέωση'' ή πιέστε ''Ctrl-F5'' ή ''Ctrl-R'' ('' ⌘-R'' σε Mac)
@@ -1764,6 +1764,8 @@ $1",
 'rcnotefrom' => "Παρακάτω είναι οι αλλαγές από τις '''$2''' (εμφανίζονται μέχρι '''$1''').",
 'rclistfrom' => 'Εμφάνιση νέων αλλαγών αρχίζοντας από $1',
 'rcshowhideminor' => '$1 μικροεπεξεργασιών',
+'rcshowhideminor-show' => 'Εμφάνιση',
+'rcshowhideminor-hide' => 'Απόκρυψη',
 'rcshowhidebots' => '$1 ρομπότ',
 'rcshowhideliu' => '$1 εγγεγραμμένων χρηστών',
 'rcshowhideanons' => '$1 ανωνύμων χρηστών',
index 917c893..3ff3302 100644 (file)
@@ -808,31 +808,31 @@ future releases. Also note that since each list value is wrapped in a unique
 'and'           => '&#32;and',
 
 # Cologne Blue skin
-'qbfind'         => 'Find',
-'qbbrowse'       => 'Browse',
-'qbedit'         => 'Edit',
-'qbpageoptions'  => 'This page',
-'qbmyoptions'    => 'My pages',
-'faq'            => 'FAQ',
-'faqpage'        => 'Project:FAQ',
-'sitetitle'      => '{{SITENAME}}', # do not translate or duplicate this message to other languages
-'sitesubtitle'   => '', # do not translate or duplicate this message to other languages
+'qbfind'        => 'Find',
+'qbbrowse'      => 'Browse',
+'qbedit'        => 'Edit',
+'qbpageoptions' => 'This page',
+'qbmyoptions'   => 'My pages',
+'faq'           => 'FAQ',
+'faqpage'       => 'Project:FAQ',
+'sitetitle'     => '{{SITENAME}}', # do not translate or duplicate this message to other languages
+'sitesubtitle'  => '', # do not translate or duplicate this message to other languages
 
 # Vector skin
-'vector-action-addsection'       => 'Add topic',
-'vector-action-delete'           => 'Delete',
-'vector-action-move'             => 'Move',
-'vector-action-protect'          => 'Protect',
-'vector-action-undelete'         => 'Undelete',
-'vector-action-unprotect'        => 'Change protection',
-'vector-view-create'             => 'Create',
-'vector-view-edit'               => 'Edit',
-'vector-view-history'            => 'View history',
-'vector-view-view'               => 'Read',
-'vector-view-viewsource'         => 'View source',
-'actions'                        => 'Actions',
-'namespaces'                     => 'Namespaces',
-'variants'                       => 'Variants',
+'vector-action-addsection' => 'Add topic',
+'vector-action-delete'     => 'Delete',
+'vector-action-move'       => 'Move',
+'vector-action-protect'    => 'Protect',
+'vector-action-undelete'   => 'Undelete',
+'vector-action-unprotect'  => 'Change protection',
+'vector-view-create'       => 'Create',
+'vector-view-edit'         => 'Edit',
+'vector-view-history'      => 'View history',
+'vector-view-view'         => 'Read',
+'vector-view-viewsource'   => 'View source',
+'actions'                  => 'Actions',
+'namespaces'               => 'Namespaces',
+'variants'                 => 'Variants',
 
 'navigation-heading' => 'Navigation menu',
 'errorpagetitle'     => 'Error',
@@ -971,8 +971,6 @@ See [[Special:Version|version page]].',
 'red-link-title'               => '$1 (page does not exist)',
 'sort-descending'              => 'Sort descending',
 'sort-ascending'               => 'Sort ascending',
-'interlanguage-link-title'     => '$1 – $2', # only translate this message to other languages if you have to change it
-'interlanguage-link-title-langonly' => '$1', # do not translate or duplicate this message to other languages
 
 # Short words for each namespace, by default used in the namespace tab in monobook
 'nstab-main'      => 'Page',
@@ -1062,7 +1060,7 @@ Changes to this page will affect the appearance of the user interface for other
 To add or change translations for all wikis, please use [//translatewiki.net/ translatewiki.net], the MediaWiki localisation project.',
 'cascadeprotected'              => 'This page has been protected from editing because it is included in the following {{PLURAL:$1|page, which is|pages, which are}} protected with the "cascading" option turned on:
 $2',
-'namespaceprotected'            => "You do not have permission to edit pages in the <strong>$1</strong> namespace.",
+'namespaceprotected'            => 'You do not have permission to edit pages in the <strong>$1</strong> namespace.',
 'customcssprotected'            => "You do not have permission to edit this CSS page because it contains another user's personal settings.",
 'customjsprotected'             => "You do not have permission to edit this JavaScript page because it contains another user's personal settings.",
 'mycustomcssprotected'          => 'You do not have permission to edit this CSS page.',
@@ -1082,14 +1080,14 @@ The administrator who locked it offered this explanation: "$3".',
 'exception-nologin-text-manual' => 'Please $1 to be able to access this page or action.',
 
 # Virus scanner
-'virus-badscanner'     => "Bad configuration: Unknown virus scanner: <em>$1</em>",
+'virus-badscanner'     => 'Bad configuration: Unknown virus scanner: <em>$1</em>',
 'virus-scanfailed'     => 'scan failed (code $1)',
 'virus-unknownscanner' => 'unknown antivirus:',
 
 # Login and logout pages
-'logouttext'                      => "<strong>You are now logged out.</strong>
+'logouttext'                      => '<strong>You are now logged out.</strong>
 
-Note that some pages may continue to be displayed as if you were still logged in, until you clear your browser cache.",
+Note that some pages may continue to be displayed as if you were still logged in, until you clear your browser cache.',
 'welcomeuser'                     => 'Welcome, $1!',
 'welcomecreation-msg'             => 'Your account has been created.
 You can change your {{SITENAME}} [[Special:Preferences|preferences]] if you wish.',
@@ -1163,6 +1161,7 @@ Use the form below to log in as another user.',
 'badretype'                       => 'The passwords you entered do not match.',
 'userexists'                      => 'Username entered already in use.
 Please choose a different name.',
+'createacct-normalization'        => 'Your username will be adjusted to "$2" due to technical restrictions.',
 'loginerror'                      => 'Login error',
 'createacct-error'                => 'Account creation error',
 'createaccounterror'              => 'Could not create account: $1',
@@ -1178,7 +1177,7 @@ Ensure you have cookies enabled, reload this page and try again.',
 'nocookiesforlogin'               => '{{int:nocookieslogin}}', # only translate this message to other languages if you have to change it
 'noname'                          => 'You have not specified a valid username.',
 'loginsuccesstitle'               => 'Login successful',
-'loginsuccess'                    => "<strong>You are now logged in to {{SITENAME}} as \"\$1\".</strong>",
+'loginsuccess'                    => '<strong>You are now logged in to {{SITENAME}} as "$1".</strong>',
 'nosuchuser'                      => 'There is no user by the name "$1".
 Usernames are case sensitive.
 Check your spelling, or [[Special:UserLogin/signup|create a new account]].',
@@ -1254,8 +1253,8 @@ Please wait $1 before trying again.',
 'suspicious-userlogout'           => 'Your request to log out was denied because it looks like it was sent by a broken browser or caching proxy.',
 'createacct-another-realname-tip' => 'Real name is optional.
 If you choose to provide it, this will be used for giving the user attribution for their work.',
-'pt-createaccount'                => 'Create account',
 'pt-login'                        => 'Log in',
+'pt-createaccount'                => 'Create account',
 'pt-userlogout'                   => 'Log out',
 
 # Email sending
@@ -1268,8 +1267,6 @@ If you choose to provide it, this will be used for giving the user attribution f
 # Change password dialog
 'changepassword'            => 'Change password',
 'changepassword-summary'    => '', # do not translate or duplicate this message to other languages
-'changepassword-throttled'  => 'You have made too many recent login attempts.
-Please wait $1 before trying again.',
 'resetpass_announce'        => 'To finish logging in, you must set a new password.',
 'resetpass_text'            => '<!-- Add text here -->', # only translate this message to other languages if you have to change it
 'resetpass_header'          => 'Change account password',
@@ -1278,6 +1275,8 @@ Please wait $1 before trying again.',
 'retypenew'                 => 'Retype new password:',
 'resetpass_submit'          => 'Set password and log in',
 'changepassword-success'    => 'Your password has been changed successfully!',
+'changepassword-throttled'  => 'You have made too many recent login attempts.
+Please wait $1 before trying again.',
 'resetpass_forbidden'       => 'Passwords cannot be changed',
 'resetpass-no-info'         => 'You must be logged in to access this page directly.',
 'resetpass-submit-loggedin' => 'Change password',
@@ -1289,8 +1288,8 @@ You may have already successfully changed your password or requested a new tempo
 To finish logging in, you must set a new password here:',
 'resetpass-temp-password'   => 'Temporary password:',
 'resetpass-abort-generic'   => 'Password change has been aborted by an extension.',
-'resetpass-expired' => 'Your password has expired. Please set a new password to login.',
-'resetpass-expired-soft' => 'Your password has expired, and needs to be reset. Please choose a new password now, or click cancel to reset it later.',
+'resetpass-expired'         => 'Your password has expired. Please set a new password to log in.',
+'resetpass-expired-soft'    => 'Your password has expired and needs to be reset. Please choose a new password now, or click "{{int:resetpass-submit-cancel}}" to reset it later.',
 
 # Special:PasswordReset
 'passwordreset'                    => 'Reset password',
@@ -1333,17 +1332,17 @@ Temporary password: $2',
 'passwordreset-emailerror-capture' => 'A password reset email was generated, which is shown below, but sending it to the {{GENDER:$2|user}} failed: $1',
 
 # Special:ChangeEmail
-'changeemail'          => 'Change email address',
-'changeemail-summary'  => '', # do not translate or duplicate this message to other languages
-'changeemail-header'   => 'Change account email address',
-'changeemail-text'     => 'Complete this form to change your email address. You will need to enter your password to confirm this change.',
-'changeemail-no-info'  => 'You must be logged in to access this page directly.',
-'changeemail-oldemail' => 'Current email address:',
-'changeemail-newemail' => 'New email address:',
-'changeemail-none'     => '(none)',
-'changeemail-password' => 'Your {{SITENAME}} password:',
-'changeemail-submit'   => 'Change email',
-'changeemail-cancel'   => 'Cancel',
+'changeemail'           => 'Change email address',
+'changeemail-summary'   => '', # do not translate or duplicate this message to other languages
+'changeemail-header'    => 'Change account email address',
+'changeemail-text'      => 'Complete this form to change your email address. You will need to enter your password to confirm this change.',
+'changeemail-no-info'   => 'You must be logged in to access this page directly.',
+'changeemail-oldemail'  => 'Current email address:',
+'changeemail-newemail'  => 'New email address:',
+'changeemail-none'      => '(none)',
+'changeemail-password'  => 'Your {{SITENAME}} password:',
+'changeemail-submit'    => 'Change email',
+'changeemail-cancel'    => 'Cancel',
 'changeemail-throttled' => 'You have made too many login attempts.
 Please wait $1 before trying again.',
 
@@ -1382,27 +1381,27 @@ You should do it if you accidentally shared them with someone or if your account
 'hr_tip'          => 'Horizontal line (use sparingly)',
 
 # Edit pages
-'summary'                          => 'Summary:',
-'subject'                          => 'Subject/headline:',
-'minoredit'                        => 'This is a minor edit',
-'watchthis'                        => 'Watch this page',
-'savearticle'                      => 'Save page',
-'preview'                          => 'Preview',
-'showpreview'                      => 'Show preview',
-'showlivepreview'                  => 'Live preview',
-'showdiff'                         => 'Show changes',
-'anoneditwarning'                  => "<strong>Warning:</strong> You are not logged in.
+'summary'                                  => 'Summary:',
+'subject'                                  => 'Subject/headline:',
+'minoredit'                                => 'This is a minor edit',
+'watchthis'                                => 'Watch this page',
+'savearticle'                              => 'Save page',
+'preview'                                  => 'Preview',
+'showpreview'                              => 'Show preview',
+'showlivepreview'                          => 'Live preview',
+'showdiff'                                 => 'Show changes',
+'anoneditwarning'                          => "<strong>Warning:</strong> You are not logged in.
 Your IP address will be recorded in this page's edit history.",
-'anonpreviewwarning'               => "<em>You are not logged in. Saving will record your IP address in this page's edit history.</em>",
-'missingsummary'                   => "<strong>Reminder:</strong> You have not provided an edit summary.
-If you click \"{{int:savearticle}}\" again, your edit will be saved without one.",
-'missingcommenttext'               => 'Please enter a comment below.',
-'missingcommentheader'             => "<strong>Reminder:</strong> You have not provided a subject/headline for this comment.
-If you click \"{{int:savearticle}}\" again, your edit will be saved without one.",
-'summary-preview'                  => 'Summary preview:',
-'subject-preview'                  => 'Subject/headline preview:',
-'blockedtitle'                     => 'User is blocked',
-'blockedtext'                      => "<strong>Your username or IP address has been blocked.</strong>
+'anonpreviewwarning'                       => "<em>You are not logged in. Saving will record your IP address in this page's edit history.</em>",
+'missingsummary'                           => '<strong>Reminder:</strong> You have not provided an edit summary.
+If you click "{{int:savearticle}}" again, your edit will be saved without one.',
+'missingcommenttext'                       => 'Please enter a comment below.',
+'missingcommentheader'                     => '<strong>Reminder:</strong> You have not provided a subject/headline for this comment.
+If you click "{{int:savearticle}}" again, your edit will be saved without one.',
+'summary-preview'                          => 'Summary preview:',
+'subject-preview'                          => 'Subject/headline preview:',
+'blockedtitle'                             => 'User is blocked',
+'blockedtext'                              => '<strong>Your username or IP address has been blocked.</strong>
 
 The block was made by $1.
 The reason given is <em>$2</em>.
@@ -1412,10 +1411,10 @@ The reason given is <em>$2</em>.
 * Intended blockee: $7
 
 You can contact $1 or another [[{{MediaWiki:Grouppage-sysop}}|administrator]] to discuss the block.
-You cannot use the \"email this user\" feature unless a valid email address is specified in your [[Special:Preferences|account preferences]] and you have not been blocked from using it.
+You cannot use the "email this user" feature unless a valid email address is specified in your [[Special:Preferences|account preferences]] and you have not been blocked from using it.
 Your current IP address is $3, and the block ID is #$5.
-Please include all above details in any queries you make.",
-'autoblockedtext'                  => "Your IP address has been automatically blocked because it was used by another user, who was blocked by $1.
+Please include all above details in any queries you make.',
+'autoblockedtext'                          => 'Your IP address has been automatically blocked because it was used by another user, who was blocked by $1.
 The reason given is:
 
 :<em>$2</em>
@@ -1426,168 +1425,168 @@ The reason given is:
 
 You may contact $1 or one of the other [[{{MediaWiki:Grouppage-sysop}}|administrators]] to discuss the block.
 
-Note that you may not use the \"email this user\" feature unless you have a valid email address registered in your [[Special:Preferences|user preferences]] and you have not been blocked from using it.
+Note that you may not use the "email this user" feature unless you have a valid email address registered in your [[Special:Preferences|user preferences]] and you have not been blocked from using it.
 
 Your current IP address is $3, and the block ID is #$5.
-Please include all above details in any queries you make.",
-'blockednoreason'                  => 'no reason given',
-'whitelistedittext'                => 'Please $1 to edit pages.',
-'confirmedittext'                  => 'You must confirm your email address before editing pages.
+Please include all above details in any queries you make.',
+'blockednoreason'                          => 'no reason given',
+'whitelistedittext'                        => 'Please $1 to edit pages.',
+'confirmedittext'                          => 'You must confirm your email address before editing pages.
 Please set and validate your email address through your [[Special:Preferences|user preferences]].',
-'nosuchsectiontitle'               => 'Cannot find section',
-'nosuchsectiontext'                => 'You tried to edit a section that does not exist.
+'nosuchsectiontitle'                       => 'Cannot find section',
+'nosuchsectiontext'                        => 'You tried to edit a section that does not exist.
 It may have been moved or deleted while you were viewing the page.',
-'loginreqtitle'                    => 'Login required',
-'loginreqlink'                     => 'log in',
-'loginreqpagetext'                 => 'Please $1 to view other pages.',
-'accmailtitle'                     => 'Password sent',
-'accmailtext'                      => "A randomly generated password for [[User talk:$1|$1]] has been sent to $2. It can be changed on the <em>[[Special:ChangePassword|change password]]</em> page upon logging in.",
-'newarticle'                       => '(New)',
-'newarticletext'                   => "You have followed a link to a page that does not exist yet.
+'loginreqtitle'                            => 'Login required',
+'loginreqlink'                             => 'log in',
+'loginreqpagetext'                         => 'Please $1 to view other pages.',
+'accmailtitle'                             => 'Password sent',
+'accmailtext'                              => 'A randomly generated password for [[User talk:$1|$1]] has been sent to $2. It can be changed on the <em>[[Special:ChangePassword|change password]]</em> page upon logging in.',
+'newarticle'                               => '(New)',
+'newarticletext'                           => "You have followed a link to a page that does not exist yet.
 To create the page, start typing in the box below (see the [[{{MediaWiki:Helppage}}|help page]] for more info).
 If you are here by mistake, click your browser's <strong>back</strong> button.",
-'newarticletextanon'               => '{{int:newarticletext}}', # do not translate or duplicate this message to other languages
-'talkpagetext'                     => '<!-- MediaWiki:talkpagetext -->', # do not translate or duplicate this message to other languages
-'anontalkpagetext'                 => "----
+'newarticletextanon'                       => '{{int:newarticletext}}', # do not translate or duplicate this message to other languages
+'talkpagetext'                             => '<!-- MediaWiki:talkpagetext -->', # do not translate or duplicate this message to other languages
+'anontalkpagetext'                         => '----
 <em>This is the discussion page for an anonymous user who has not created an account yet, or who does not use it.</em>
 We therefore have to use the numerical IP address to identify him/her.
 Such an IP address can be shared by several users.
-If you are an anonymous user and feel that irrelevant comments have been directed at you, please [[Special:UserLogin/signup|create an account]] or [[Special:UserLogin|log in]] to avoid future confusion with other anonymous users.",
-'noarticletext'                    => 'There is currently no text in this page.
+If you are an anonymous user and feel that irrelevant comments have been directed at you, please [[Special:UserLogin/signup|create an account]] or [[Special:UserLogin|log in]] to avoid future confusion with other anonymous users.',
+'noarticletext'                            => 'There is currently no text in this page.
 You can [[Special:Search/{{PAGENAME}}|search for this page title]] in other pages,
 <span class="plainlinks">[{{fullurl:{{#Special:Log}}|page={{FULLPAGENAMEE}}}} search the related logs],
 or [{{fullurl:{{FULLPAGENAME}}|action=edit}} edit this page]</span>.',
-'noarticletext-nopermission'       => 'There is currently no text in this page.
+'noarticletext-nopermission'               => 'There is currently no text in this page.
 You can [[Special:Search/{{PAGENAME}}|search for this page title]] in other pages, or <span class="plainlinks">[{{fullurl:{{#Special:Log}}|page={{FULLPAGENAMEE}}}} search the related logs]</span>, but you do not have permission to create this page.',
-'noarticletextanon'                => '{{int:noarticletext}}', # do not translate or duplicate this message to other languages
-'missing-revision'                 => 'The revision #$1 of the page named "{{PAGENAME}}" does not exist.
+'noarticletextanon'                        => '{{int:noarticletext}}', # do not translate or duplicate this message to other languages
+'missing-revision'                         => 'The revision #$1 of the page named "{{PAGENAME}}" does not exist.
 
 This is usually caused by following an outdated history link to a page that has been deleted.
 Details can be found in the [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} deletion log].',
-'userpage-userdoesnotexist'        => 'User account "$1" is not registered.
+'userpage-userdoesnotexist'                => 'User account "$1" is not registered.
 Please check if you want to create/edit this page.',
-'userpage-userdoesnotexist-view'   => 'User account "$1" is not registered.',
-'blocked-notice-logextract'        => 'This user is currently blocked.
+'userpage-userdoesnotexist-view'           => 'User account "$1" is not registered.',
+'blocked-notice-logextract'                => 'This user is currently blocked.
 The latest block log entry is provided below for reference:',
-'clearyourcache'                   => "<strong>Note:</strong> After saving, you may have to bypass your browser's cache to see the changes.
+'clearyourcache'                           => "<strong>Note:</strong> After saving, you may have to bypass your browser's cache to see the changes.
 * <strong>Firefox / Safari:</strong> Hold <em>Shift</em> while clicking <em>Reload</em>, or press either <em>Ctrl-F5</em> or <em>Ctrl-R</em> (<em>⌘-R</em> on a Mac)
 * <strong>Google Chrome:</strong> Press <em>Ctrl-Shift-R</em> (<em>⌘-Shift-R</em> on a Mac)
 * <strong>Internet Explorer:</strong> Hold <em>Ctrl</em> while clicking <em>Refresh</em>, or press <em>Ctrl-F5</em>
 * <strong>Opera:</strong> Clear the cache in <em>Tools → Preferences</em>",
-'usercssyoucanpreview'             => "<strong>Tip:</strong> Use the \"{{int:showpreview}}\" button to test your new CSS before saving.",
-'userjsyoucanpreview'              => "<strong>Tip:</strong> Use the \"{{int:showpreview}}\" button to test your new JavaScript before saving.",
-'usercsspreview'                   => "<strong>Remember that you are only previewing your user CSS.
-It has not yet been saved!</strong>",
-'userjspreview'                    => "<strong>Remember that you are only testing/previewing your user JavaScript.
-It has not yet been saved!</strong>",
-'sitecsspreview'                   => "<strong>Remember that you are only previewing this CSS.
-It has not yet been saved!</strong>",
-'sitejspreview'                    => "<strong>Remember that you are only previewing this JavaScript code.
-It has not yet been saved!</strong>",
-'userinvalidcssjstitle'            => "<strong>Warning:</strong> There is no skin \"\$1\".
-Custom .css and .js pages use a lowercase title, e.g. {{ns:user}}:Foo/vector.css as opposed to {{ns:user}}:Foo/Vector.css.",
-'updated'                          => '(Updated)',
-'note'                             => "<strong>Note:</strong>",
-'previewnote'                      => "<strong>Remember that this is only a preview.</strong>
-Your changes have not yet been saved!",
-'continue-editing'                 => 'Go to editing area',
-'previewconflict'                  => 'This preview reflects the text in the upper text editing area as it will appear if you choose to save.',
-'session_fail_preview'             => "<strong>Sorry! We could not process your edit due to a loss of session data.</strong>
+'usercssyoucanpreview'                     => '<strong>Tip:</strong> Use the "{{int:showpreview}}" button to test your new CSS before saving.',
+'userjsyoucanpreview'                      => '<strong>Tip:</strong> Use the "{{int:showpreview}}" button to test your new JavaScript before saving.',
+'usercsspreview'                           => '<strong>Remember that you are only previewing your user CSS.
+It has not yet been saved!</strong>',
+'userjspreview'                            => '<strong>Remember that you are only testing/previewing your user JavaScript.
+It has not yet been saved!</strong>',
+'sitecsspreview'                           => '<strong>Remember that you are only previewing this CSS.
+It has not yet been saved!</strong>',
+'sitejspreview'                            => '<strong>Remember that you are only previewing this JavaScript code.
+It has not yet been saved!</strong>',
+'userinvalidcssjstitle'                    => '<strong>Warning:</strong> There is no skin "$1".
+Custom .css and .js pages use a lowercase title, e.g. {{ns:user}}:Foo/vector.css as opposed to {{ns:user}}:Foo/Vector.css.',
+'updated'                                  => '(Updated)',
+'note'                                     => '<strong>Note:</strong>',
+'previewnote'                              => '<strong>Remember that this is only a preview.</strong>
+Your changes have not yet been saved!',
+'continue-editing'                         => 'Go to editing area',
+'previewconflict'                          => 'This preview reflects the text in the upper text editing area as it will appear if you choose to save.',
+'session_fail_preview'                     => '<strong>Sorry! We could not process your edit due to a loss of session data.</strong>
 Please try again.
-If it still does not work, try [[Special:UserLogout|logging out]] and logging back in.",
-'session_fail_preview_html'        => "<strong>Sorry! We could not process your edit due to a loss of session data.</strong>
+If it still does not work, try [[Special:UserLogout|logging out]] and logging back in.',
+'session_fail_preview_html'                => '<strong>Sorry! We could not process your edit due to a loss of session data.</strong>
 
 <em>Because {{SITENAME}} has raw HTML enabled, the preview is hidden as a precaution against JavaScript attacks.</em>
 
 <strong>If this is a legitimate edit attempt, please try again.</strong>
-If it still does not work, try [[Special:UserLogout|logging out]] and logging back in.",
-'token_suffix_mismatch'            => "<strong>Your edit has been rejected because your client mangled the punctuation characters in the edit token.</strong>
+If it still does not work, try [[Special:UserLogout|logging out]] and logging back in.',
+'token_suffix_mismatch'                    => '<strong>Your edit has been rejected because your client mangled the punctuation characters in the edit token.</strong>
 The edit has been rejected to prevent corruption of the page text.
-This sometimes happens when you are using a buggy web-based anonymous proxy service.",
-'edit_form_incomplete'             => "<strong>Some parts of the edit form did not reach the server; double-check that your edits are intact and try again.</strong>",
-'editing'                          => 'Editing $1',
-'creating'                         => 'Creating $1',
-'editingsection'                   => 'Editing $1 (section)',
-'editingcomment'                   => 'Editing $1 (new section)',
-'editconflict'                     => 'Edit conflict: $1',
-'explainconflict'                  => "Someone else has changed this page since you started editing it.
+This sometimes happens when you are using a buggy web-based anonymous proxy service.',
+'edit_form_incomplete'                     => '<strong>Some parts of the edit form did not reach the server; double-check that your edits are intact and try again.</strong>',
+'editing'                                  => 'Editing $1',
+'creating'                                 => 'Creating $1',
+'editingsection'                           => 'Editing $1 (section)',
+'editingcomment'                           => 'Editing $1 (new section)',
+'editconflict'                             => 'Edit conflict: $1',
+'explainconflict'                          => 'Someone else has changed this page since you started editing it.
 The upper text area contains the page text as it currently exists.
 Your changes are shown in the lower text area.
 You will have to merge your changes into the existing text.
-<strong>Only</strong> the text in the upper text area will be saved when you press \"{{int:savearticle}}\".",
-'yourtext'                         => 'Your text',
-'storedversion'                    => 'Stored revision',
-'nonunicodebrowser'                => "<strong>Warning: Your browser is not Unicode compliant.</strong>
-A workaround is in place to allow you to safely edit pages: Non-ASCII characters will appear in the edit box as hexadecimal codes.",
-'editingold'                       => "<strong>Warning: You are editing an out-of-date revision of this page.</strong>
-If you save it, any changes made since this revision will be lost.",
-'yourdiff'                         => 'Differences',
-'copyrightwarning'                 => "Please note that all contributions to {{SITENAME}} are considered to be released under the $2 (see $1 for details).
+<strong>Only</strong> the text in the upper text area will be saved when you press "{{int:savearticle}}".',
+'yourtext'                                 => 'Your text',
+'storedversion'                            => 'Stored revision',
+'nonunicodebrowser'                        => '<strong>Warning: Your browser is not Unicode compliant.</strong>
+A workaround is in place to allow you to safely edit pages: Non-ASCII characters will appear in the edit box as hexadecimal codes.',
+'editingold'                               => '<strong>Warning: You are editing an out-of-date revision of this page.</strong>
+If you save it, any changes made since this revision will be lost.',
+'yourdiff'                                 => 'Differences',
+'copyrightwarning'                         => 'Please note that all contributions to {{SITENAME}} are considered to be released under the $2 (see $1 for details).
 If you do not want your writing to be edited mercilessly and redistributed at will, then do not submit it here.<br />
 You are also promising us that you wrote this yourself, or copied it from a public domain or similar free resource.
-<strong>Do not submit copyrighted work without permission!</strong>",
-'copyrightwarning2'                => "Please note that all contributions to {{SITENAME}} may be edited, altered, or removed by other contributors.
+<strong>Do not submit copyrighted work without permission!</strong>',
+'copyrightwarning2'                        => 'Please note that all contributions to {{SITENAME}} may be edited, altered, or removed by other contributors.
 If you do not want your writing to be edited mercilessly, then do not submit it here.<br />
 You are also promising us that you wrote this yourself, or copied it from a public domain or similar free resource (see $1 for details).
-<strong>Do not submit copyrighted work without permission!</strong>",
-'editpage-head-copy-warn'          => '-', # do not translate or duplicate this message to other languages
-'editpage-tos-summary'             => '-', # do not translate or duplicate this message to other languages
-'longpage-hint'                    => '-', # do not translate or duplicate this message to other languages
-'longpageerror'                    => "<strong>Error: The text you have submitted is {{PLURAL:$1|one kilobyte|$1 kilobytes}} long, which is longer than the maximum of {{PLURAL:$2|one kilobyte|$2 kilobytes}}.</strong>
-It cannot be saved.",
-'readonlywarning'                  => "<strong>Warning: The database has been locked for maintenance, so you will not be able to save your edits right now.</strong>
+<strong>Do not submit copyrighted work without permission!</strong>',
+'editpage-head-copy-warn'                  => '-', # do not translate or duplicate this message to other languages
+'editpage-tos-summary'                     => '-', # do not translate or duplicate this message to other languages
+'longpage-hint'                            => '-', # do not translate or duplicate this message to other languages
+'longpageerror'                            => '<strong>Error: The text you have submitted is {{PLURAL:$1|one kilobyte|$1 kilobytes}} long, which is longer than the maximum of {{PLURAL:$2|one kilobyte|$2 kilobytes}}.</strong>
+It cannot be saved.',
+'readonlywarning'                          => '<strong>Warning: The database has been locked for maintenance, so you will not be able to save your edits right now.</strong>
 You may wish to copy and paste your text into a text file and save it for later.
 
-The administrator who locked it offered this explanation: $1",
-'protectedpagewarning'             => "<strong>Warning: This page has been protected so that only users with administrator privileges can edit it.</strong>
-The latest log entry is provided below for reference:",
-'semiprotectedpagewarning'         => "<strong>Note:</strong> This page has been protected so that only registered users can edit it.
-The latest log entry is provided below for reference:",
-'cascadeprotectedwarning'          => "<strong>Warning:</strong> This page has been protected so that only users with administrator privileges can edit it because it is included in the following cascade-protected {{PLURAL:$1|page|pages}}:",
-'titleprotectedwarning'            => "<strong>Warning: This page has been protected so that [[Special:ListGroupRights|specific rights]] are needed to create it.</strong>
-The latest log entry is provided below for reference:",
-'templatesused'                    => '{{PLURAL:$1|Template|Templates}} used on this page:',
-'templatesusedpreview'             => '{{PLURAL:$1|Template|Templates}} used in this preview:',
-'templatesusedsection'             => '{{PLURAL:$1|Template|Templates}} used in this section:',
-'template-protected'               => '(protected)',
-'template-semiprotected'           => '(semi-protected)',
-'hiddencategories'                 => 'This page is a member of {{PLURAL:$1|1 hidden category|$1 hidden categories}}:',
-'edittools'                        => '<!-- Text here will be shown below edit and upload forms. -->', # only translate this message to other languages if you have to change it
-'edittools-upload'                 => '-', # only translate this message to other languages if you have to change it
-'nocreatetext'                     => '{{SITENAME}} has restricted the ability to create new pages.
+The administrator who locked it offered this explanation: $1',
+'protectedpagewarning'                     => '<strong>Warning: This page has been protected so that only users with administrator privileges can edit it.</strong>
+The latest log entry is provided below for reference:',
+'semiprotectedpagewarning'                 => '<strong>Note:</strong> This page has been protected so that only registered users can edit it.
+The latest log entry is provided below for reference:',
+'cascadeprotectedwarning'                  => '<strong>Warning:</strong> This page has been protected so that only users with administrator privileges can edit it because it is included in the following cascade-protected {{PLURAL:$1|page|pages}}:',
+'titleprotectedwarning'                    => '<strong>Warning: This page has been protected so that [[Special:ListGroupRights|specific rights]] are needed to create it.</strong>
+The latest log entry is provided below for reference:',
+'templatesused'                            => '{{PLURAL:$1|Template|Templates}} used on this page:',
+'templatesusedpreview'                     => '{{PLURAL:$1|Template|Templates}} used in this preview:',
+'templatesusedsection'                     => '{{PLURAL:$1|Template|Templates}} used in this section:',
+'template-protected'                       => '(protected)',
+'template-semiprotected'                   => '(semi-protected)',
+'hiddencategories'                         => 'This page is a member of {{PLURAL:$1|1 hidden category|$1 hidden categories}}:',
+'edittools'                                => '<!-- Text here will be shown below edit and upload forms. -->', # only translate this message to other languages if you have to change it
+'edittools-upload'                         => '-', # only translate this message to other languages if you have to change it
+'nocreatetext'                             => '{{SITENAME}} has restricted the ability to create new pages.
 You can go back and edit an existing page, or [[Special:UserLogin|log in or create an account]].',
-'nocreate-loggedin'                => 'You do not have permission to create new pages.',
-'sectioneditnotsupported-title'    => 'Section editing not supported',
-'sectioneditnotsupported-text'     => 'Section editing is not supported in this page.',
-'permissionserrors'                => 'Permission error',
-'permissionserrorstext'            => 'You do not have permission to do that, for the following {{PLURAL:$1|reason|reasons}}:',
-'permissionserrorstext-withaction' => 'You do not have permission to $2, for the following {{PLURAL:$1|reason|reasons}}:',
-'recreate-moveddeleted-warn'       => "<strong>Warning: You are recreating a page that was previously deleted.</strong>
+'nocreate-loggedin'                        => 'You do not have permission to create new pages.',
+'sectioneditnotsupported-title'            => 'Section editing not supported',
+'sectioneditnotsupported-text'             => 'Section editing is not supported in this page.',
+'permissionserrors'                        => 'Permission error',
+'permissionserrorstext'                    => 'You do not have permission to do that, for the following {{PLURAL:$1|reason|reasons}}:',
+'permissionserrorstext-withaction'         => 'You do not have permission to $2, for the following {{PLURAL:$1|reason|reasons}}:',
+'recreate-moveddeleted-warn'               => '<strong>Warning: You are recreating a page that was previously deleted.</strong>
 
 You should consider whether it is appropriate to continue editing this page.
-The deletion and move log for this page are provided here for convenience:",
-'moveddeleted-notice'              => 'This page has been deleted.
+The deletion and move log for this page are provided here for convenience:',
+'moveddeleted-notice'                      => 'This page has been deleted.
 The deletion and move log for the page are provided below for reference.',
-'log-fulllog'                      => 'View full log',
-'edit-hook-aborted'                => 'Edit aborted by hook.
+'log-fulllog'                              => 'View full log',
+'edit-hook-aborted'                        => 'Edit aborted by hook.
 It gave no explanation.',
-'edit-gone-missing'                => 'Could not update the page.
+'edit-gone-missing'                        => 'Could not update the page.
 It appears to have been deleted.',
-'edit-conflict'                    => 'Edit conflict.',
-'edit-no-change'                   => 'Your edit was ignored because no change was made to the text.',
-'postedit-confirmation'            => 'Your edit was saved.',
-'edit-already-exists'              => 'Could not create a new page.
+'edit-conflict'                            => 'Edit conflict.',
+'edit-no-change'                           => 'Your edit was ignored because no change was made to the text.',
+'postedit-confirmation'                    => 'Your edit was saved.',
+'edit-already-exists'                      => 'Could not create a new page.
 It already exists.',
-'addsection-preload'               => '', # do not translate or duplicate this message to other languages
-'addsection-editintro'             => '', # do not translate or duplicate this message to other languages
-'defaultmessagetext'               => 'Default message text',
-'content-failed-to-parse'          => 'Failed to parse $2 content for $1 model: $3',
-'invalid-content-data'             => 'Invalid content data',
-'content-not-allowed-here'         => '"$1" content is not allowed on page [[$2]]',
-'editwarning-warning'              => 'Leaving this page may cause you to lose any changes you have made.
+'addsection-preload'                       => '', # do not translate or duplicate this message to other languages
+'addsection-editintro'                     => '', # do not translate or duplicate this message to other languages
+'defaultmessagetext'                       => 'Default message text',
+'content-failed-to-parse'                  => 'Failed to parse $2 content for $1 model: $3',
+'invalid-content-data'                     => 'Invalid content data',
+'content-not-allowed-here'                 => '"$1" content is not allowed on page [[$2]]',
+'editwarning-warning'                      => 'Leaving this page may cause you to lose any changes you have made.
 If you are logged in, you can disable this warning in the "{{int:prefs-editing}}" section of your preferences.',
-'editpage-notsupportedcontentformat-title'=> 'Content format not supported',
-'editpage-notsupportedcontentformat-text' => 'The content format $1 is not supported by the content model $2.',
+'editpage-notsupportedcontentformat-title' => 'Content format not supported',
+'editpage-notsupportedcontentformat-text'  => 'The content format $1 is not supported by the content model $2.',
 
 # Content models
 'content-model-wikitext'   => 'wikitext',
@@ -1596,15 +1595,15 @@ If you are logged in, you can disable this warning in the "{{int:prefs-editing}}
 'content-model-css'        => 'CSS',
 
 # Parser/template warnings
-'expensive-parserfunction-warning'        => "<strong>Warning:</strong> This page contains too many expensive parser function calls.
+'expensive-parserfunction-warning'        => '<strong>Warning:</strong> This page contains too many expensive parser function calls.
 
-It should have less than $2 {{PLURAL:$2|call|calls}}, there {{PLURAL:$1|is now $1 call|are now $1 calls}}.",
+It should have less than $2 {{PLURAL:$2|call|calls}}, there {{PLURAL:$1|is now $1 call|are now $1 calls}}.',
 'expensive-parserfunction-category'       => 'Pages with too many expensive parser function calls',
-'post-expand-template-inclusion-warning'  => "<strong>Warning:</strong> Template include size is too large.
-Some templates will not be included.",
+'post-expand-template-inclusion-warning'  => '<strong>Warning:</strong> Template include size is too large.
+Some templates will not be included.',
 'post-expand-template-inclusion-category' => 'Pages where template include size is exceeded',
-'post-expand-template-argument-warning'   => "<strong>Warning:</strong> This page contains at least one template argument that has a too large expansion size.
-These arguments have been omitted.",
+'post-expand-template-argument-warning'   => '<strong>Warning:</strong> This page contains at least one template argument that has a too large expansion size.
+These arguments have been omitted.',
 'post-expand-template-argument-category'  => 'Pages containing omitted template arguments',
 'parser-template-loop-warning'            => 'Template loop detected: [[$1]]',
 'parser-template-recursion-depth-warning' => 'Template recursion depth limit exceeded ($1)',
@@ -1627,14 +1626,14 @@ Please check the comparison below to verify that this is what you want to do, an
 'undo-summary-username-hidden' => 'Undo revision $1 by a hidden user',
 
 # Account creation failure
-'cantcreateaccounttitle' => 'Cannot create account',
+'cantcreateaccounttitle'       => 'Cannot create account',
+'cantcreateaccount-text'       => 'Account creation from this IP address (<strong>$1</strong>) has been blocked by [[User:$3|$3]].
+
+The reason given by $3 is <em>$2</em>',
 'cantcreateaccount-range-text' => "Account creation from IP addresses in the range '''$1''', which includes your IP address ('''$4'''), has been blocked by [[User:$3|$3]].
 
 The reason given by $3 is ''$2''",
-'cantcreateaccount-text' => "Account creation from this IP address (<strong>$1</strong>) has been blocked by [[User:$3|$3]].
-
-The reason given by $3 is <em>$2</em>",
-'createaccount-hook-aborted' => '$1', # do not translate or duplicate this message to other languages
+'createaccount-hook-aborted'   => '$1', # do not translate or duplicate this message to other languages
 
 # History pages
 'viewpagelogs'           => 'View logs for this page',
@@ -1653,8 +1652,8 @@ The reason given by $3 is <em>$2</em>",
 'last'                   => 'prev',
 'page_first'             => 'first',
 'page_last'              => 'last',
-'histlegend'             => "Diff selection: Mark the radio boxes of the revisions to compare and hit enter or the button at the bottom.<br />
-Legend: <strong>({{int:cur}})</strong> = difference with latest revision, <strong>({{int:last}})</strong> = difference with preceding revision, <strong>{{int:minoreditletter}}</strong> = minor edit.",
+'histlegend'             => 'Diff selection: Mark the radio boxes of the revisions to compare and hit enter or the button at the bottom.<br />
+Legend: <strong>({{int:cur}})</strong> = difference with latest revision, <strong>({{int:last}})</strong> = difference with preceding revision, <strong>{{int:minoreditletter}}</strong> = minor edit.',
 'history-fieldset-title' => 'Browse history',
 'history-show-deleted'   => 'Deleted only',
 'history_copyright'      => '-', # do not translate or duplicate this message to other languages
@@ -1676,31 +1675,31 @@ Try [[Special:Search|searching on the wiki]] for relevant new pages.',
 'rev-deleted-user'            => '(username removed)',
 'rev-deleted-event'           => '(log action removed)',
 'rev-deleted-user-contribs'   => '[username or IP address removed - edit hidden from contributions]',
-'rev-deleted-text-permission' => "This page revision has been <strong>deleted</strong>.
-Details can be found in the [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} deletion log].",
-'rev-deleted-text-unhide'     => "This page revision has been <strong>deleted</strong>.
+'rev-deleted-text-permission' => 'This page revision has been <strong>deleted</strong>.
+Details can be found in the [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} deletion log].',
+'rev-deleted-text-unhide'     => 'This page revision has been <strong>deleted</strong>.
 Details can be found in the [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} deletion log].
-You can still [$1 view this revision] if you wish to proceed.",
-'rev-suppressed-text-unhide'  => "This page revision has been <strong>suppressed</strong>.
+You can still [$1 view this revision] if you wish to proceed.',
+'rev-suppressed-text-unhide'  => 'This page revision has been <strong>suppressed</strong>.
 Details can be found in the [{{fullurl:{{#Special:Log}}/suppress|page={{FULLPAGENAMEE}}}} suppression log].
-You can still [$1 view this revision] if you wish to proceed.",
-'rev-deleted-text-view'       => "This page revision has been <strong>deleted</strong>.
-You can view it; details can be found in the [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} deletion log].",
-'rev-suppressed-text-view'    => "This page revision has been <strong>suppressed</strong>.
-You can view it; details can be found in the [{{fullurl:{{#Special:Log}}/suppress|page={{FULLPAGENAMEE}}}} suppression log].",
-'rev-deleted-no-diff'         => "You cannot view this diff because one of the revisions has been <strong>deleted</strong>.
-Details can be found in the [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} deletion log].",
-'rev-suppressed-no-diff'      => "You cannot view this diff because one of the revisions has been <strong>deleted</strong>.",
-'rev-deleted-unhide-diff'     => "One of the revisions of this diff has been <strong>deleted</strong>.
+You can still [$1 view this revision] if you wish to proceed.',
+'rev-deleted-text-view'       => 'This page revision has been <strong>deleted</strong>.
+You can view it; details can be found in the [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} deletion log].',
+'rev-suppressed-text-view'    => 'This page revision has been <strong>suppressed</strong>.
+You can view it; details can be found in the [{{fullurl:{{#Special:Log}}/suppress|page={{FULLPAGENAMEE}}}} suppression log].',
+'rev-deleted-no-diff'         => 'You cannot view this diff because one of the revisions has been <strong>deleted</strong>.
+Details can be found in the [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} deletion log].',
+'rev-suppressed-no-diff'      => 'You cannot view this diff because one of the revisions has been <strong>deleted</strong>.',
+'rev-deleted-unhide-diff'     => 'One of the revisions of this diff has been <strong>deleted</strong>.
 Details can be found in the [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} deletion log].
-You can still [$1 view this diff] if you wish to proceed.",
-'rev-suppressed-unhide-diff'  => "One of the revisions of this diff has been <strong>suppressed</strong>.
+You can still [$1 view this diff] if you wish to proceed.',
+'rev-suppressed-unhide-diff'  => 'One of the revisions of this diff has been <strong>suppressed</strong>.
 Details can be found in the [{{fullurl:{{#Special:Log}}/suppress|page={{FULLPAGENAMEE}}}} suppression log].
-You can still [$1 view this diff] if you wish to proceed.",
-'rev-deleted-diff-view'       => "One of the revisions of this diff has been <strong>deleted</strong>.
-You can view this diff; details can be found in the [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} deletion log].",
-'rev-suppressed-diff-view'    => "One of the revisions of this diff has been <strong>suppressed</strong>.
-You can view this diff; details can be found in the [{{fullurl:{{#Special:Log}}/suppress|page={{FULLPAGENAMEE}}}} suppression log].",
+You can still [$1 view this diff] if you wish to proceed.',
+'rev-deleted-diff-view'       => 'One of the revisions of this diff has been <strong>deleted</strong>.
+You can view this diff; details can be found in the [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} deletion log].',
+'rev-suppressed-diff-view'    => 'One of the revisions of this diff has been <strong>suppressed</strong>.
+You can view this diff; details can be found in the [{{fullurl:{{#Special:Log}}/suppress|page={{FULLPAGENAMEE}}}} suppression log].',
 'rev-delundel'                => 'change visibility',
 'rev-showdeleted'             => 'show',
 'revisiondelete'              => 'Delete/undelete revisions',
@@ -1710,15 +1709,15 @@ function, the specified revision does not exist, or you are attempting to hide t
 'revdelete-no-file'           => 'The file specified does not exist.',
 'revdelete-show-file-confirm' => 'Are you sure you want to view a deleted revision of the file "<nowiki>$1</nowiki>" from $2 at $3?',
 'revdelete-show-file-submit'  => 'Yes',
-'revdelete-selected'          => "<strong>{{PLURAL:$2|Selected revision|Selected revisions}} of [[:$1]]:</strong>",
-'logdelete-selected'          => "<strong>{{PLURAL:$1|Selected log event|Selected log events}}:</strong>",
-'revdelete-text'              => "<strong>Deleted revisions and events will still appear in the page history and logs, but parts of their content will be inaccessible to the public.</strong>
-Other administrators on {{SITENAME}} will still be able to access the hidden content and can undelete it again through this same interface, unless additional restrictions are set.",
+'revdelete-selected'          => '<strong>{{PLURAL:$2|Selected revision|Selected revisions}} of [[:$1]]:</strong>',
+'logdelete-selected'          => '<strong>{{PLURAL:$1|Selected log event|Selected log events}}:</strong>',
+'revdelete-text'              => '<strong>Deleted revisions and events will still appear in the page history and logs, but parts of their content will be inaccessible to the public.</strong>
+Other administrators on {{SITENAME}} will still be able to access the hidden content and can undelete it again through this same interface, unless additional restrictions are set.',
 'revdelete-confirm'           => 'Please confirm that you intend to do this, that you understand the consequences, and that you are doing this in accordance with [[{{MediaWiki:Policy-url}}|the policy]].',
-'revdelete-suppress-text'     => "Suppression should <strong>only</strong> be used for the following cases:
+'revdelete-suppress-text'     => 'Suppression should <strong>only</strong> be used for the following cases:
 * potentially libelous information
 * inappropriate personal information
-*: <em>home addresses and telephone numbers, national identification numbers, etc.</em>",
+*: <em>home addresses and telephone numbers, national identification numbers, etc.</em>',
 'revdelete-legend'            => 'Set visibility restrictions',
 'revdelete-hide-text'         => 'Revision text',
 'revdelete-hide-image'        => 'Hide file content',
@@ -1733,12 +1732,12 @@ Other administrators on {{SITENAME}} will still be able to access the hidden con
 'revdelete-unsuppress'        => 'Remove restrictions on restored revisions',
 'revdelete-log'               => 'Reason:',
 'revdelete-submit'            => 'Apply to selected {{PLURAL:$1|revision|revisions}}',
-'revdelete-success'           => "<strong>Revision visibility successfully updated.</strong>",
-'revdelete-failure'           => "<strong>Revision visibility could not be updated:</strong>
-$1",
-'logdelete-success'           => "<strong>Log visibility successfully set.</strong>",
-'logdelete-failure'           => "<strong>Log visibility could not be set:</strong>
-$1",
+'revdelete-success'           => '<strong>Revision visibility successfully updated.</strong>',
+'revdelete-failure'           => '<strong>Revision visibility could not be updated:</strong>
+$1',
+'logdelete-success'           => '<strong>Log visibility successfully set.</strong>',
+'logdelete-failure'           => '<strong>Log visibility could not be set:</strong>
+$1',
 'revdel-restore'              => 'change visibility',
 'pagehist'                    => 'Page history',
 'deletedhist'                 => 'Deleted history',
@@ -1749,7 +1748,7 @@ You do not have access to it.',
 'revdelete-modify-no-access'  => 'Error modifying the item dated $2, $1: This item has been marked "restricted".
 You do not have access to it.',
 'revdelete-modify-missing'    => 'Error modifying item ID $1: It is missing from the database!',
-'revdelete-no-change'         => "<strong>Warning:</strong> The item dated $2, $1 already had the requested visibility settings.",
+'revdelete-no-change'         => '<strong>Warning:</strong> The item dated $2, $1 already had the requested visibility settings.',
 'revdelete-concurrent-change' => 'Error modifying the item dated $2, $1: Its status appears to have been changed by someone else while you attempted to modify it.
 Please check the logs.',
 'revdelete-only-restricted'   => 'Error hiding the item dated $2, $1: You cannot suppress items from view by administrators without also selecting one of the other visibility options.',
@@ -1832,8 +1831,8 @@ Details can be found in the [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENA
 'nextn-title'                      => 'Next $1 {{PLURAL:$1|result|results}}',
 'shown-title'                      => 'Show $1 {{PLURAL:$1|result|results}} per page',
 'viewprevnext'                     => 'View ($1 {{int:pipe-separator}} $2) ($3)',
-'searchmenu-exists'                => "<strong>There is a page named \"[[:\$1]]\" on this wiki.</strong> {{PLURAL:$2|0=|See also the other search results found.}}",
-'searchmenu-new'                   => "<strong>Create the page \"[[:\$1]]\" on this wiki!</strong> {{PLURAL:$2|0=|See also the page found with your search.|See also the search results found.}}",
+'searchmenu-exists'                => '<strong>There is a page named "[[:$1]]" on this wiki.</strong> {{PLURAL:$2|0=|See also the other search results found.}}',
+'searchmenu-new'                   => '<strong>Create the page "[[:$1]]" on this wiki!</strong> {{PLURAL:$2|0=|See also the page found with your search.|See also the search results found.}}',
 'searchmenu-new-nocreate'          => '', # do not translate or duplicate this message to other languages
 'searchprofile-articles'           => 'Content pages',
 'searchprofile-project'            => 'Help and Project pages',
@@ -1860,10 +1859,10 @@ Details can be found in the [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENA
 'searcheverything-enable'          => 'Search in all namespaces',
 'searchrelated'                    => 'related',
 'searchall'                        => 'all',
-'showingresults'                   => "Showing below up to {{PLURAL:$1|<strong>1</strong> result|<strong>$1</strong> results}} starting with #<strong>$2</strong>.",
-'showingresultsinrange'            => "Showing below up to {{PLURAL:$1|<strong>1</strong> result|<strong>$1</strong> results}} in range #<strong>$2</strong> to #<strong>$3</strong>.",
-'showingresultsnum'                => "Showing below {{PLURAL:$3|<strong>1</strong> result|<strong>$3</strong> results}} starting with #<strong>$2</strong>.",
-'showingresultsheader'             => "{{PLURAL:$5|Result <strong>$1</strong> of <strong>$3</strong>|Results <strong>$1 - $2</strong> of <strong>$3</strong>}} for <strong>$4</strong>",
+'showingresults'                   => 'Showing below up to {{PLURAL:$1|<strong>1</strong> result|<strong>$1</strong> results}} starting with #<strong>$2</strong>.',
+'showingresultsinrange'            => 'Showing below up to {{PLURAL:$1|<strong>1</strong> result|<strong>$1</strong> results}} in range #<strong>$2</strong> to #<strong>$3</strong>.',
+'showingresultsnum'                => 'Showing below {{PLURAL:$3|<strong>1</strong> result|<strong>$3</strong> results}} starting with #<strong>$2</strong>.',
+'showingresultsheader'             => '{{PLURAL:$5|Result <strong>$1</strong> of <strong>$3</strong>|Results <strong>$1 - $2</strong> of <strong>$3</strong>}} for <strong>$4</strong>',
 'search-nonefound'                 => 'There were no results matching the query.',
 'powersearch-legend'               => 'Advanced search',
 'powersearch-ns'                   => 'Search in namespaces:',
@@ -2025,7 +2024,7 @@ Your email address is not revealed when other users contact you.',
 'userrights-lookup-user'         => 'Manage user groups',
 'userrights-user-editname'       => 'Enter a username:',
 'editusergroup'                  => 'Edit user groups',
-'editinguser'                    => "Changing user rights of user <strong>[[User:$1|$1]]</strong> $2",
+'editinguser'                    => 'Changing user rights of user <strong>[[User:$1|$1]]</strong> $2',
 'userrights-editusergroup'       => 'Edit user groups',
 'saveusergroups'                 => 'Save user groups',
 'userrights-groupsmember'        => 'Member of:',
@@ -2207,15 +2206,27 @@ Your email address is not revealed when other users contact you.',
 'recentchanges-label-plusminus'     => 'The page size changed by this number of bytes',
 'recentchanges-legend-heading'      => "'''Legend:'''",
 'recentchanges-legend-newpage'      => '(also see [[Special:NewPages|list of new pages]])',
-'recentchanges-legend-plusminus'    => "(<em>±123</em>)",
-'rcnotefrom'                        => "Below are the changes since <strong>$2</strong> (up to <strong>$1</strong> shown).",
-'rclistfrom'                        => 'Show new changes starting from $1',
+'recentchanges-legend-plusminus'    => '(<em>±123</em>)', # only translate this message to other languages if you have to change it
+'rcnotefrom'                        => 'Below are the changes since <strong>$2</strong> (up to <strong>$1</strong> shown).',
+'rclistfrom'                        => 'Show new changes starting from $2, $3',
 'rcshowhideminor'                   => '$1 minor edits',
+'rcshowhideminor-show'              => 'Show',
+'rcshowhideminor-hide'              => 'Hide',
 'rcshowhidebots'                    => '$1 bots',
+'rcshowhidebots-show'               => 'Show',
+'rcshowhidebots-hide'               => 'Hide',
 'rcshowhideliu'                     => '$1 registered users',
+'rcshowhideliu-show'                => 'Show',
+'rcshowhideliu-hide'                => 'Hide',
 'rcshowhideanons'                   => '$1 anonymous users',
+'rcshowhideanons-show'              => 'Show',
+'rcshowhideanons-hide'              => 'Hide',
 'rcshowhidepatr'                    => '$1 patrolled edits',
+'rcshowhidepatr-show'               => 'Show',
+'rcshowhidepatr-hide'               => 'Hide',
 'rcshowhidemine'                    => '$1 my edits',
+'rcshowhidemine-show'               => 'Show',
+'rcshowhidemine-hide'               => 'Hide',
 'rclinks'                           => 'Show last $1 changes in last $2 days<br />$3',
 'diff'                              => 'diff',
 'hist'                              => 'hist',
@@ -2241,139 +2252,140 @@ Your email address is not revealed when other users contact you.',
 'recentchangeslinked-feed'    => 'Related changes',
 'recentchangeslinked-toolbox' => 'Related changes',
 'recentchangeslinked-title'   => 'Changes related to "$1"',
-'recentchangeslinked-summary' => "This is a list of changes made recently to pages linked from a specified page (or to members of a specified category).
-Pages on [[Special:Watchlist|your watchlist]] are <strong>bold</strong>.",
+'recentchangeslinked-summary' => 'This is a list of changes made recently to pages linked from a specified page (or to members of a specified category).
+Pages on [[Special:Watchlist|your watchlist]] are <strong>bold</strong>.',
 'recentchangeslinked-page'    => 'Page name:',
 'recentchangeslinked-to'      => 'Show changes to pages linked to the given page instead',
 
 # Upload
-'upload'                      => 'Upload file',
-'uploadbtn'                   => 'Upload file',
-'reuploaddesc'                => 'Cancel upload and return to the upload form',
-'upload-tryagain'             => 'Submit modified file description',
-'uploadnologin'               => 'Not logged in',
-'uploadnologintext'           => 'Please $1 to upload files.',
-'upload_directory_missing'    => 'The upload directory ($1) is missing and could not be created by the webserver.',
-'upload_directory_read_only'  => 'The upload directory ($1) is not writable by the webserver.',
-'uploaderror'                 => 'Upload error',
-'upload-summary'              => '', # do not translate or duplicate this message to other languages
-'upload-recreate-warning'     => "<strong>Warning: A file by that name has been deleted or moved.</strong>
-
-The deletion and move log for this page are provided here for convenience:",
-'uploadtext'                  => "Use the form below to upload files.
+'upload'                         => 'Upload file',
+'uploadbtn'                      => 'Upload file',
+'reuploaddesc'                   => 'Cancel upload and return to the upload form',
+'upload-tryagain'                => 'Submit modified file description',
+'uploadnologin'                  => 'Not logged in',
+'uploadnologintext'              => 'Please $1 to upload files.',
+'upload_directory_missing'       => 'The upload directory ($1) is missing and could not be created by the webserver.',
+'upload_directory_read_only'     => 'The upload directory ($1) is not writable by the webserver.',
+'uploaderror'                    => 'Upload error',
+'upload-summary'                 => '', # do not translate or duplicate this message to other languages
+'upload-recreate-warning'        => '<strong>Warning: A file by that name has been deleted or moved.</strong>
+
+The deletion and move log for this page are provided here for convenience:',
+'uploadtext'                     => 'Use the form below to upload files.
 To view or search previously uploaded files go to the [[Special:FileList|list of uploaded files]], (re)uploads are also logged in the [[Special:Log/upload|upload log]], deletions in the [[Special:Log/delete|deletion log]].
 
 To include a file in a page, use a link in one of the following forms:
 * <strong><code><nowiki>[[</nowiki>{{ns:file}}<nowiki>:File.jpg]]</nowiki></code></strong> to use the full version of the file
-* <strong><code><nowiki>[[</nowiki>{{ns:file}}<nowiki>:File.png|200px|thumb|left|alt text]]</nowiki></code></strong> to use a 200 pixel wide rendition in a box in the left margin with \"alt text\" as description
-* <strong><code><nowiki>[[</nowiki>{{ns:media}}<nowiki>:File.ogg]]</nowiki></code></strong> for directly linking to the file without displaying the file",
-'upload-permitted'            => 'Permitted file types: $1.',
-'upload-preferred'            => 'Preferred file types: $1.',
-'upload-prohibited'           => 'Prohibited file types: $1.',
-'uploadfooter'                => '-', # do not translate or duplicate this message to other languages
-'upload-default-description'  => '-', # do not translate or duplicate this message to other languages
-'uploadlog'                   => 'upload log',
-'uploadlogpage'               => 'Upload log',
-'uploadlogpagetext'           => 'Below is a list of the most recent file uploads.
+* <strong><code><nowiki>[[</nowiki>{{ns:file}}<nowiki>:File.png|200px|thumb|left|alt text]]</nowiki></code></strong> to use a 200 pixel wide rendition in a box in the left margin with "alt text" as description
+* <strong><code><nowiki>[[</nowiki>{{ns:media}}<nowiki>:File.ogg]]</nowiki></code></strong> for directly linking to the file without displaying the file',
+'upload-permitted'               => 'Permitted file types: $1.',
+'upload-preferred'               => 'Preferred file types: $1.',
+'upload-prohibited'              => 'Prohibited file types: $1.',
+'uploadfooter'                   => '-', # do not translate or duplicate this message to other languages
+'upload-default-description'     => '-', # do not translate or duplicate this message to other languages
+'uploadlog'                      => 'upload log',
+'uploadlogpage'                  => 'Upload log',
+'uploadlogpagetext'              => 'Below is a list of the most recent file uploads.
 See the [[Special:NewFiles|gallery of new files]] for a more visual overview.',
-'filename'                    => 'Filename',
-'filedesc'                    => 'Summary',
-'fileuploadsummary'           => 'Summary:',
-'filereuploadsummary'         => 'File changes:',
-'filestatus'                  => 'Copyright status:',
-'filesource'                  => 'Source:',
-'uploadedfiles'               => 'Uploaded files',
-'ignorewarning'               => 'Ignore warning and save file anyway',
-'ignorewarnings'              => 'Ignore any warnings',
-'minlength1'                  => 'Filenames must be at least one letter.',
-'illegalfilename'             => 'The filename "$1" contains characters that are not allowed in page titles.
+'filename'                       => 'Filename',
+'filedesc'                       => 'Summary',
+'fileuploadsummary'              => 'Summary:',
+'filereuploadsummary'            => 'File changes:',
+'filestatus'                     => 'Copyright status:',
+'filesource'                     => 'Source:',
+'uploadedfiles'                  => 'Uploaded files',
+'ignorewarning'                  => 'Ignore warning and save file anyway',
+'ignorewarnings'                 => 'Ignore any warnings',
+'minlength1'                     => 'Filenames must be at least one letter.',
+'illegalfilename'                => 'The filename "$1" contains characters that are not allowed in page titles.
 Please rename the file and try uploading it again.',
-'filename-toolong'            => 'Filenames may not be longer than 240 bytes.',
-'badfilename'                 => 'Filename has been changed to "$1".',
-'filetype-mime-mismatch'      => 'File extension ".$1" does not match the detected MIME type of the file ($2).',
-'filetype-badmime'            => 'Files of the MIME type "$1" are not allowed to be uploaded.',
-'filetype-bad-ie-mime'        => 'Cannot upload this file because Internet Explorer would detect it as "$1", which is a disallowed and potentially dangerous file type.',
-'filetype-unwanted-type'      => "<strong>\".\$1\"</strong> is an unwanted file type.
-Preferred {{PLURAL:\$3|file type is|file types are}} \$2.",
-'filetype-banned-type'        => '<strong>".$1"</strong> {{PLURAL:$4|is not a permitted file type|are not permitted file types}}.
+'filename-toolong'               => 'Filenames may not be longer than 240 bytes.',
+'badfilename'                    => 'Filename has been changed to "$1".',
+'filetype-mime-mismatch'         => 'File extension ".$1" does not match the detected MIME type of the file ($2).',
+'filetype-badmime'               => 'Files of the MIME type "$1" are not allowed to be uploaded.',
+'filetype-bad-ie-mime'           => 'Cannot upload this file because Internet Explorer would detect it as "$1", which is a disallowed and potentially dangerous file type.',
+'filetype-unwanted-type'         => '<strong>".$1"</strong> is an unwanted file type.
+Preferred {{PLURAL:$3|file type is|file types are}} $2.',
+'filetype-banned-type'           => '<strong>".$1"</strong> {{PLURAL:$4|is not a permitted file type|are not permitted file types}}.
 Permitted {{PLURAL:$3|file type is|file types are}} $2.',
-'filetype-missing'            => 'The file has no extension (like ".jpg").',
-'empty-file'                  => 'The file you submitted was empty.',
-'file-too-large'              => 'The file you submitted was too large.',
-'filename-tooshort'           => 'The filename is too short.',
-'filetype-banned'             => 'This type of file is banned.',
-'verification-error'          => 'This file did not pass file verification.',
-'hookaborted'                 => 'The modification you tried to make was aborted by an extension.',
-'illegal-filename'            => 'The filename is not allowed.',
-'overwrite'                   => 'Overwriting an existing file is not allowed.',
-'unknown-error'               => 'An unknown error occurred.',
-'tmp-create-error'            => 'Could not create temporary file.',
-'tmp-write-error'             => 'Error writing temporary file.',
-'large-file'                  => 'It is recommended that files are no larger than $1;
+'filetype-missing'               => 'The file has no extension (like ".jpg").',
+'empty-file'                     => 'The file you submitted was empty.',
+'file-too-large'                 => 'The file you submitted was too large.',
+'filename-tooshort'              => 'The filename is too short.',
+'filetype-banned'                => 'This type of file is banned.',
+'verification-error'             => 'This file did not pass file verification.',
+'hookaborted'                    => 'The modification you tried to make was aborted by an extension.',
+'illegal-filename'               => 'The filename is not allowed.',
+'overwrite'                      => 'Overwriting an existing file is not allowed.',
+'unknown-error'                  => 'An unknown error occurred.',
+'tmp-create-error'               => 'Could not create temporary file.',
+'tmp-write-error'                => 'Error writing temporary file.',
+'large-file'                     => 'It is recommended that files are no larger than $1;
 this file is $2.',
-'largefileserver'             => 'This file is bigger than the server is configured to allow.',
-'emptyfile'                   => 'The file you uploaded seems to be empty.
+'largefileserver'                => 'This file is bigger than the server is configured to allow.',
+'emptyfile'                      => 'The file you uploaded seems to be empty.
 This might be due to a typo in the filename.
 Please check whether you really want to upload this file.',
-'windows-nonascii-filename'   => 'This wiki does not support filenames with special characters.',
-'fileexists'                  => 'A file with this name exists already, please check <strong>[[:$1]]</strong> if you are not sure if you want to change it.
+'windows-nonascii-filename'      => 'This wiki does not support filenames with special characters.',
+'fileexists'                     => 'A file with this name exists already, please check <strong>[[:$1]]</strong> if you are not sure if you want to change it.
 [[$1|thumb]]',
-'filepageexists'              => 'The description page for this file has already been created at <strong>[[:$1]]</strong>, but no file with this name currently exists.
+'filepageexists'                 => 'The description page for this file has already been created at <strong>[[:$1]]</strong>, but no file with this name currently exists.
 The summary you enter will not appear on the description page.
 To make your summary appear there, you will need to manually edit it.
 [[$1|thumb]]',
-'fileexists-extension'        => 'A file with a similar name exists: [[$2|thumb]]
+'fileexists-extension'           => 'A file with a similar name exists: [[$2|thumb]]
 * Name of the uploading file: <strong>[[:$1]]</strong>
 * Name of the existing file: <strong>[[:$2]]</strong>
 Please choose a different name.',
-'fileexists-thumbnail-yes'    => "The file seems to be an image of reduced size <em>(thumbnail)</em>.
+'fileexists-thumbnail-yes'       => 'The file seems to be an image of reduced size <em>(thumbnail)</em>.
 [[$1|thumb]]
 Please check the file <strong>[[:$1]]</strong>.
-If the checked file is the same image of original size it is not necessary to upload an extra thumbnail.",
-'file-thumbnail-no'           => "The filename begins with <strong>$1</strong>.
+If the checked file is the same image of original size it is not necessary to upload an extra thumbnail.',
+'file-thumbnail-no'              => 'The filename begins with <strong>$1</strong>.
 It seems to be an image of reduced size <em>(thumbnail)</em>.
-If you have this image in full resolution upload this one, otherwise change the filename please.",
-'fileexists-forbidden'        => 'A file with this name already exists, and cannot be overwritten.
+If you have this image in full resolution upload this one, otherwise change the filename please.',
+'fileexists-forbidden'           => 'A file with this name already exists, and cannot be overwritten.
 If you still want to upload your file, please go back and use a new name.
 [[File:$1|thumb|center|$1]]',
-'fileexists-shared-forbidden' => 'A file with this name exists already in the shared file repository.
+'fileexists-shared-forbidden'    => 'A file with this name exists already in the shared file repository.
 If you still want to upload your file, please go back and use a new name.
 [[File:$1|thumb|center|$1]]',
-'file-exists-duplicate'       => 'This file is a duplicate of the following {{PLURAL:$1|file|files}}:',
-'file-deleted-duplicate'      => "A file identical to this file ([[:$1]]) has previously been deleted.
+'file-exists-duplicate'          => 'This file is a duplicate of the following {{PLURAL:$1|file|files}}:',
+'file-deleted-duplicate'         => "A file identical to this file ([[:$1]]) has previously been deleted.
 You should check that file's deletion history before proceeding to re-upload it.",
-'file-deleted-duplicate-notitle' => "A file identical to this file has previously been deleted, and the title has been suppressed.
-You should ask someone with the ability to view suppressed file data to review the situation before proceeding to re-upload it.",
-'uploadwarning'               => 'Upload warning',
-'uploadwarning-text'          => 'Please modify the file description below and try again.',
-'savefile'                    => 'Save file',
-'uploadedimage'               => 'uploaded "[[$1]]"',
-'overwroteimage'              => 'uploaded a new version of "[[$1]]"',
-'uploaddisabled'              => 'Uploads disabled.',
-'copyuploaddisabled'          => 'Upload by URL disabled.',
-'uploadfromurl-queued'        => 'Your upload has been queued.',
-'uploaddisabledtext'          => 'File uploads are disabled.',
-'php-uploaddisabledtext'      => 'File uploads are disabled in PHP.
+'file-deleted-duplicate-notitle' => 'A file identical to this file has previously been deleted, and the title has been suppressed.
+You should ask someone with the ability to view suppressed file data to review the situation before proceeding to re-upload it.',
+'uploadwarning'                  => 'Upload warning',
+'uploadwarning-text'             => 'Please modify the file description below and try again.',
+'savefile'                       => 'Save file',
+'uploadedimage'                  => 'uploaded "[[$1]]"',
+'overwroteimage'                 => 'uploaded a new version of "[[$1]]"',
+'uploaddisabled'                 => 'Uploads disabled.',
+'copyuploaddisabled'             => 'Upload by URL disabled.',
+'uploadfromurl-queued'           => 'Your upload has been queued.',
+'uploaddisabledtext'             => 'File uploads are disabled.',
+'php-uploaddisabledtext'         => 'File uploads are disabled in PHP.
 Please check the file_uploads setting.',
-'uploadscripted'              => 'This file contains HTML or script code that may be erroneously interpreted by a web browser.',
-'uploadinvalidxml'            => 'The XML in the uploaded file could not be parsed.',
-'uploadvirus'                 => 'The file contains a virus!
+'uploadscripted'                 => 'This file contains HTML or script code that may be erroneously interpreted by a web browser.',
+'uploadscriptednamespace'        => 'This SVG file contains an illegal namespace "$1"',
+'uploadinvalidxml'               => 'The XML in the uploaded file could not be parsed.',
+'uploadvirus'                    => 'The file contains a virus!
 Details: $1',
-'uploadjava'                  => 'The file is a ZIP file that contains a Java .class file.
+'uploadjava'                     => 'The file is a ZIP file that contains a Java .class file.
 Uploading Java files is not allowed because they can cause security restrictions to be bypassed.',
-'upload-source'               => 'Source file',
-'sourcefilename'              => 'Source filename:',
-'sourceurl'                   => 'Source URL:',
-'destfilename'                => 'Destination filename:',
-'upload-maxfilesize'          => 'Maximum file size: $1',
-'upload-description'          => 'File description',
-'upload-options'              => 'Upload options',
-'watchthisupload'             => 'Watch this file',
-'filewasdeleted'              => 'A file of this name has been previously uploaded and subsequently deleted.
+'upload-source'                  => 'Source file',
+'sourcefilename'                 => 'Source filename:',
+'sourceurl'                      => 'Source URL:',
+'destfilename'                   => 'Destination filename:',
+'upload-maxfilesize'             => 'Maximum file size: $1',
+'upload-description'             => 'File description',
+'upload-options'                 => 'Upload options',
+'watchthisupload'                => 'Watch this file',
+'filewasdeleted'                 => 'A file of this name has been previously uploaded and subsequently deleted.
 You should check the $1 before proceeding to upload it again.',
-'filename-bad-prefix'         => "The name of the file you are uploading begins with <strong>\"\$1\"</strong>, which is a non-descriptive name typically assigned automatically by digital cameras.
-Please choose a more descriptive name for your file.",
-'filename-prefix-blacklist'   => ' #<!-- leave this line exactly as it is --> <pre>
+'filename-bad-prefix'            => 'The name of the file you are uploading begins with <strong>"$1"</strong>, which is a non-descriptive name typically assigned automatically by digital cameras.
+Please choose a more descriptive name for your file.',
+'filename-prefix-blacklist'      => ' #<!-- leave this line exactly as it is --> <pre>
 # Syntax is as follows:
 #   * Everything from a "#" character to the end of the line is a comment
 #   * Every non-blank line is a prefix for typical filenames assigned automatically by digital cameras
@@ -2387,14 +2399,14 @@ JD # Jenoptik
 MGP # Pentax
 PICT # misc.
  #</pre> <!-- leave this line exactly as it is -->', # only translate this message to other languages if you have to change it
-'upload-success-subj'         => 'Successful upload',
-'upload-success-msg'          => 'Your upload from [$2] was successful. It is available here: [[:{{ns:file}}:$1]]',
-'upload-failure-subj'         => 'Upload problem',
-'upload-failure-msg'          => 'There was a problem with your upload from [$2]:
+'upload-success-subj'            => 'Successful upload',
+'upload-success-msg'             => 'Your upload from [$2] was successful. It is available here: [[:{{ns:file}}:$1]]',
+'upload-failure-subj'            => 'Upload problem',
+'upload-failure-msg'             => 'There was a problem with your upload from [$2]:
 
 $1',
-'upload-warning-subj'         => 'Upload warning',
-'upload-warning-msg'          => 'There was a problem with your upload from [$2]. You may return to the [[Special:Upload/stash/$1|upload form]] to correct this problem.',
+'upload-warning-subj'            => 'Upload warning',
+'upload-warning-msg'             => 'There was a problem with your upload from [$2]. You may return to the [[Special:Upload/stash/$1|upload form]] to correct this problem.',
 
 'upload-proto-error'                => 'Incorrect protocol',
 'upload-proto-error-text'           => 'Remote upload requires URLs beginning with <code>http://</code> or <code>ftp://</code>.',
@@ -2581,24 +2593,24 @@ Maybe you want to edit the description on its [$2 file description page] there.'
 # File reversion
 'filerevert'                => 'Revert $1',
 'filerevert-legend'         => 'Revert file',
-'filerevert-intro'          => "You are about to revert the file <strong>[[Media:$1|$1]]</strong> to the [$4 version as of $3, $2].",
+'filerevert-intro'          => 'You are about to revert the file <strong>[[Media:$1|$1]]</strong> to the [$4 version as of $3, $2].',
 'filerevert-comment'        => 'Reason:',
 'filerevert-defaultcomment' => 'Reverted to version as of $2, $1',
 'filerevert-submit'         => 'Revert',
-'filerevert-success'        => "<strong>[[Media:$1|$1]]</strong> has been reverted to the [$4 version as of $3, $2].",
+'filerevert-success'        => '<strong>[[Media:$1|$1]]</strong> has been reverted to the [$4 version as of $3, $2].',
 'filerevert-badversion'     => 'There is no previous local version of this file with the provided timestamp.',
 
 # File deletion
 'filedelete'                   => 'Delete $1',
 'filedelete-legend'            => 'Delete file',
-'filedelete-intro'             => "You are about to delete the file <strong>[[Media:$1|$1]]</strong> along with all of its history.",
-'filedelete-intro-old'         => "You are deleting the version of <strong>[[Media:$1|$1]]</strong> as of [$4 $3, $2].",
+'filedelete-intro'             => 'You are about to delete the file <strong>[[Media:$1|$1]]</strong> along with all of its history.',
+'filedelete-intro-old'         => 'You are deleting the version of <strong>[[Media:$1|$1]]</strong> as of [$4 $3, $2].',
 'filedelete-comment'           => 'Reason:',
 'filedelete-submit'            => 'Delete',
-'filedelete-success'           => "<strong>$1</strong> has been deleted.",
-'filedelete-success-old'       => "The version of <strong>[[Media:$1|$1]]</strong> as of $3, $2 has been deleted.",
-'filedelete-nofile'            => "<strong>$1</strong> does not exist.",
-'filedelete-nofile-old'        => "There is no archived version of <strong>$1</strong> with the specified attributes.",
+'filedelete-success'           => '<strong>$1</strong> has been deleted.',
+'filedelete-success-old'       => 'The version of <strong>[[Media:$1|$1]]</strong> as of $3, $2 has been deleted.',
+'filedelete-nofile'            => '<strong>$1</strong> does not exist.',
+'filedelete-nofile-old'        => 'There is no archived version of <strong>$1</strong> with the specified attributes.',
 'filedelete-otherreason'       => 'Other/additional reason:',
 'filedelete-reason-otherlist'  => 'Other reason',
 'filedelete-reason-dropdown'   => '*Common delete reasons
@@ -2703,113 +2715,113 @@ It now redirects to [[$2]].',
 'fewestrevisions-summary' => '', # do not translate or duplicate this message to other languages
 
 # Miscellaneous special pages
-'nbytes'                          => '$1 {{PLURAL:$1|byte|bytes}}',
-'ncategories'                     => '$1 {{PLURAL:$1|category|categories}}',
-'ninterwikis'                     => '$1 {{PLURAL:$1|interwiki|interwikis}}',
-'nlinks'                          => '$1 {{PLURAL:$1|link|links}}',
-'nmembers'                        => '$1 {{PLURAL:$1|member|members}}',
-'nmemberschanged'                 => '$1 → $2 {{PLURAL:$2|member|members}}',
-'nrevisions'                      => '$1 {{PLURAL:$1|revision|revisions}}',
-'nviews'                          => '$1 {{PLURAL:$1|view|views}}',
-'nimagelinks'                     => 'Used on $1 {{PLURAL:$1|page|pages}}',
-'ntransclusions'                  => 'used on $1 {{PLURAL:$1|page|pages}}',
-'specialpage-empty'               => 'There are no results for this report.',
-'lonelypages'                     => 'Orphaned pages',
-'lonelypages-summary'             => '', # do not translate or duplicate this message to other languages
-'lonelypagestext'                 => 'The following pages are not linked from or transcluded into other pages in {{SITENAME}}.',
-'uncategorizedpages'              => 'Uncategorized pages',
-'uncategorizedpages-summary'      => '', # do not translate or duplicate this message to other languages
-'uncategorizedcategories'         => 'Uncategorized categories',
-'uncategorizedcategories-summary' => '', # do not translate or duplicate this message to other languages
-'uncategorizedimages'             => 'Uncategorized files',
-'uncategorizedimages-summary'     => '', # do not translate or duplicate this message to other languages
-'uncategorizedtemplates'          => 'Uncategorized templates',
-'uncategorizedtemplates-summary'  => '', # do not translate or duplicate this message to other languages
-'unusedcategories'                => 'Unused categories',
-'unusedcategories-summary'        => '', # do not translate or duplicate this message to other languages
-'unusedimages'                    => 'Unused files',
-'unusedimages-summary'            => '', # do not translate or duplicate this message to other languages
-'popularpages'                    => 'Popular pages',
-'popularpages-summary'            => '', # do not translate or duplicate this message to other languages
-'wantedcategories'                => 'Wanted categories',
-'wantedcategories-summary'        => '', # do not translate or duplicate this message to other languages
-'wantedpages'                     => 'Wanted pages',
-'wantedpages-summary'             => '', # do not translate or duplicate this message to other languages
-'wantedpages-badtitle'            => 'Invalid title in result set: $1',
-'wantedfiles'                     => 'Wanted files',
-'wantedfiles-summary'             => '', # do not translate or duplicate this message to other languages
-'wantedfiletext-cat'              => 'The following files are used but do not exist. Files from foreign repositories may be listed despite existing. Any such false positives will be <del>struck out</del>. Additionally, pages that embed files that do not exist are listed in [[:$1]].',
-'wantedfiletext-nocat'            => 'The following files are used but do not exist. Files from foreign repositories may be listed despite existing. Any such false positives will be <del>struck out</del>.',
-'wantedtemplates'                 => 'Wanted templates',
-'wantedtemplates-summary'         => '', # do not translate or duplicate this message to other languages
-'mostlinked'                      => 'Most linked-to pages',
-'mostlinked-summary'              => '', # do not translate or duplicate this message to other languages
-'mostlinkedcategories'            => 'Most linked-to categories',
-'mostlinkedcategories-summary'    => '', # do not translate or duplicate this message to other languages
-'mostlinkedtemplates'             => 'Most linked-to templates',
-'mostlinkedtemplates-summary'     => '', # do not translate or duplicate this message to other languages
-'mostcategories'                  => 'Pages with the most categories',
-'mostcategories-summary'          => '', # do not translate or duplicate this message to other languages
-'mostimages'                      => 'Most linked-to files',
-'mostimages-summary'              => '', # do not translate or duplicate this message to other languages
-'mostinterwikis'                  => 'Pages with the most interwikis',
-'mostinterwikis-summary'          => '', # do not translate or duplicate this message to other languages
-'mostrevisions'                   => 'Pages with the most revisions',
-'mostrevisions-summary'           => '', # do not translate or duplicate this message to other languages
-'prefixindex'                     => 'All pages with prefix',
-'prefixindex-namespace'           => 'All pages with prefix ($1 namespace)',
-'prefixindex-summary'             => '', # do not translate or duplicate this message to other languages
-'prefixindex-strip'               => 'Strip prefix in list',
-'shortpages'                      => 'Short pages',
-'shortpages-summary'              => '', # do not translate or duplicate this message to other languages
-'longpages'                       => 'Long pages',
-'longpages-summary'               => '', # do not translate or duplicate this message to other languages
-'deadendpages'                    => 'Dead-end pages',
-'deadendpages-summary'            => '', # do not translate or duplicate this message to other languages
-'deadendpagestext'                => 'The following pages do not link to other pages in {{SITENAME}}.',
-'protectedpages'                  => 'Protected pages',
-'protectedpages-indef'            => 'Indefinite protections only',
-'protectedpages-summary'          => 'This page lists existing pages that are currently protected. For a list of titles that are protected from creation, see [[{{#special:ProtectedTitles}}]].',
-'protectedpages-cascade'          => 'Cascading protections only',
-'protectedpages-noredirect'       => 'Hide redirects',
-'protectedpagesempty'             => 'No pages are currently protected with these parameters.',
-'protectedpages-timestamp'        => 'Timestamp',
-'protectedpages-page'             => 'Page',
-'protectedpages-expiry'           => 'Expires',
-'protectedpages-performer'        => 'Protecting user',
-'protectedpages-params'           => 'Protection parameters',
-'protectedpages-reason'           => 'Reason',
+'nbytes'                           => '$1 {{PLURAL:$1|byte|bytes}}',
+'ncategories'                      => '$1 {{PLURAL:$1|category|categories}}',
+'ninterwikis'                      => '$1 {{PLURAL:$1|interwiki|interwikis}}',
+'nlinks'                           => '$1 {{PLURAL:$1|link|links}}',
+'nmembers'                         => '$1 {{PLURAL:$1|member|members}}',
+'nmemberschanged'                  => '$1 → $2 {{PLURAL:$2|member|members}}',
+'nrevisions'                       => '$1 {{PLURAL:$1|revision|revisions}}',
+'nviews'                           => '$1 {{PLURAL:$1|view|views}}',
+'nimagelinks'                      => 'Used on $1 {{PLURAL:$1|page|pages}}',
+'ntransclusions'                   => 'used on $1 {{PLURAL:$1|page|pages}}',
+'specialpage-empty'                => 'There are no results for this report.',
+'lonelypages'                      => 'Orphaned pages',
+'lonelypages-summary'              => '', # do not translate or duplicate this message to other languages
+'lonelypagestext'                  => 'The following pages are not linked from or transcluded into other pages in {{SITENAME}}.',
+'uncategorizedpages'               => 'Uncategorized pages',
+'uncategorizedpages-summary'       => '', # do not translate or duplicate this message to other languages
+'uncategorizedcategories'          => 'Uncategorized categories',
+'uncategorizedcategories-summary'  => '', # do not translate or duplicate this message to other languages
+'uncategorizedimages'              => 'Uncategorized files',
+'uncategorizedimages-summary'      => '', # do not translate or duplicate this message to other languages
+'uncategorizedtemplates'           => 'Uncategorized templates',
+'uncategorizedtemplates-summary'   => '', # do not translate or duplicate this message to other languages
+'unusedcategories'                 => 'Unused categories',
+'unusedcategories-summary'         => '', # do not translate or duplicate this message to other languages
+'unusedimages'                     => 'Unused files',
+'unusedimages-summary'             => '', # do not translate or duplicate this message to other languages
+'popularpages'                     => 'Popular pages',
+'popularpages-summary'             => '', # do not translate or duplicate this message to other languages
+'wantedcategories'                 => 'Wanted categories',
+'wantedcategories-summary'         => '', # do not translate or duplicate this message to other languages
+'wantedpages'                      => 'Wanted pages',
+'wantedpages-summary'              => '', # do not translate or duplicate this message to other languages
+'wantedpages-badtitle'             => 'Invalid title in result set: $1',
+'wantedfiles'                      => 'Wanted files',
+'wantedfiles-summary'              => '', # do not translate or duplicate this message to other languages
+'wantedfiletext-cat'               => 'The following files are used but do not exist. Files from foreign repositories may be listed despite existing. Any such false positives will be <del>struck out</del>. Additionally, pages that embed files that do not exist are listed in [[:$1]].',
+'wantedfiletext-nocat'             => 'The following files are used but do not exist. Files from foreign repositories may be listed despite existing. Any such false positives will be <del>struck out</del>.',
+'wantedtemplates'                  => 'Wanted templates',
+'wantedtemplates-summary'          => '', # do not translate or duplicate this message to other languages
+'mostlinked'                       => 'Most linked-to pages',
+'mostlinked-summary'               => '', # do not translate or duplicate this message to other languages
+'mostlinkedcategories'             => 'Most linked-to categories',
+'mostlinkedcategories-summary'     => '', # do not translate or duplicate this message to other languages
+'mostlinkedtemplates'              => 'Most linked-to templates',
+'mostlinkedtemplates-summary'      => '', # do not translate or duplicate this message to other languages
+'mostcategories'                   => 'Pages with the most categories',
+'mostcategories-summary'           => '', # do not translate or duplicate this message to other languages
+'mostimages'                       => 'Most linked-to files',
+'mostimages-summary'               => '', # do not translate or duplicate this message to other languages
+'mostinterwikis'                   => 'Pages with the most interwikis',
+'mostinterwikis-summary'           => '', # do not translate or duplicate this message to other languages
+'mostrevisions'                    => 'Pages with the most revisions',
+'mostrevisions-summary'            => '', # do not translate or duplicate this message to other languages
+'prefixindex'                      => 'All pages with prefix',
+'prefixindex-namespace'            => 'All pages with prefix ($1 namespace)',
+'prefixindex-summary'              => '', # do not translate or duplicate this message to other languages
+'prefixindex-strip'                => 'Strip prefix in list',
+'shortpages'                       => 'Short pages',
+'shortpages-summary'               => '', # do not translate or duplicate this message to other languages
+'longpages'                        => 'Long pages',
+'longpages-summary'                => '', # do not translate or duplicate this message to other languages
+'deadendpages'                     => 'Dead-end pages',
+'deadendpages-summary'             => '', # do not translate or duplicate this message to other languages
+'deadendpagestext'                 => 'The following pages do not link to other pages in {{SITENAME}}.',
+'protectedpages'                   => 'Protected pages',
+'protectedpages-indef'             => 'Indefinite protections only',
+'protectedpages-summary'           => 'This page lists existing pages that are currently protected. For a list of titles that are protected from creation, see [[{{#special:ProtectedTitles}}]].',
+'protectedpages-cascade'           => 'Cascading protections only',
+'protectedpages-noredirect'        => 'Hide redirects',
+'protectedpagesempty'              => 'No pages are currently protected with these parameters.',
+'protectedpages-timestamp'         => 'Timestamp',
+'protectedpages-page'              => 'Page',
+'protectedpages-expiry'            => 'Expires',
+'protectedpages-performer'         => 'Protecting user',
+'protectedpages-params'            => 'Protection parameters',
+'protectedpages-reason'            => 'Reason',
 'protectedpages-unknown-timestamp' => 'Unknown',
 'protectedpages-unknown-performer' => 'Unknown user',
-'protectedpages-unknown-reason'   => '—', # do not translate or duplicate this message to other languages
-'protectedtitles'                 => 'Protected titles',
-'protectedtitles-summary'         => 'This page lists titles that are currently protected from creation. For a list of existing pages that are protected, see [[{{#special:ProtectedPages}}]].',
-'protectedtitlesempty'            => 'No titles are currently protected with these parameters.',
-'listusers'                       => 'User list',
-'listusers-summary'               => '', # do not translate or duplicate this message to other languages
-'listusers-editsonly'             => 'Show only users with edits',
-'listusers-creationsort'          => 'Sort by creation date',
-'listusers-desc'                  => 'Sort in descending order',
-'usereditcount'                   => '$1 {{PLURAL:$1|edit|edits}}',
-'usercreated'                     => '{{GENDER:$3|Created}} on $1 at $2',
-'newpages'                        => 'New pages',
-'newpages-summary'                => '', # do not translate or duplicate this message to other languages
-'newpages-username'               => 'Username:',
-'ancientpages'                    => 'Oldest pages',
-'ancientpages-summary'            => '', # do not translate or duplicate this message to other languages
-'move'                            => 'Move',
-'movethispage'                    => 'Move this page',
-'unusedimagestext'                => 'The following files exist but are not embedded in any page.
+'protectedpages-unknown-reason'    => '—', # do not translate or duplicate this message to other languages
+'protectedtitles'                  => 'Protected titles',
+'protectedtitles-summary'          => 'This page lists titles that are currently protected from creation. For a list of existing pages that are protected, see [[{{#special:ProtectedPages}}]].',
+'protectedtitlesempty'             => 'No titles are currently protected with these parameters.',
+'listusers'                        => 'User list',
+'listusers-summary'                => '', # do not translate or duplicate this message to other languages
+'listusers-editsonly'              => 'Show only users with edits',
+'listusers-creationsort'           => 'Sort by creation date',
+'listusers-desc'                   => 'Sort in descending order',
+'usereditcount'                    => '$1 {{PLURAL:$1|edit|edits}}',
+'usercreated'                      => '{{GENDER:$3|Created}} on $1 at $2',
+'newpages'                         => 'New pages',
+'newpages-summary'                 => '', # do not translate or duplicate this message to other languages
+'newpages-username'                => 'Username:',
+'ancientpages'                     => 'Oldest pages',
+'ancientpages-summary'             => '', # do not translate or duplicate this message to other languages
+'move'                             => 'Move',
+'movethispage'                     => 'Move this page',
+'unusedimagestext'                 => 'The following files exist but are not embedded in any page.
 Please note that other web sites may link to a file with a direct URL, and so may still be listed here despite being in active use.',
-'unusedcategoriestext'            => 'The following category pages exist, although no other page or category makes use of them.',
-'notargettitle'                   => 'No target',
-'notargettext'                    => 'You have not specified a target page or user to perform this function on.',
-'nopagetitle'                     => 'No such target page',
-'nopagetext'                      => 'The target page you have specified does not exist.',
-'pager-newer-n'                   => '{{PLURAL:$1|newer 1|newer $1}}',
-'pager-older-n'                   => '{{PLURAL:$1|older 1|older $1}}',
-'suppress'                        => 'Oversight',
-'querypage-disabled'              => 'This special page is disabled for performance reasons.',
+'unusedcategoriestext'             => 'The following category pages exist, although no other page or category makes use of them.',
+'notargettitle'                    => 'No target',
+'notargettext'                     => 'You have not specified a target page or user to perform this function on.',
+'nopagetitle'                      => 'No such target page',
+'nopagetext'                       => 'The target page you have specified does not exist.',
+'pager-newer-n'                    => '{{PLURAL:$1|newer 1|newer $1}}',
+'pager-older-n'                    => '{{PLURAL:$1|older 1|older $1}}',
+'suppress'                         => 'Oversight',
+'querypage-disabled'               => 'This special page is disabled for performance reasons.',
 
 # Book sources
 'booksources'               => 'Book sources',
@@ -2984,12 +2996,12 @@ Future changes to this page and its associated talk page will be listed there.',
 'notvisiblerev'        => 'The last revision by a different user has been deleted',
 'watchlist-details'    => '{{PLURAL:$1|$1 page|$1 pages}} on your watchlist, not counting talk pages.',
 'wlheader-enotif'      => 'Email notification is enabled.',
-'wlheader-showupdated' => "Pages that have been changed since you last visited them are shown in <strong>bold</strong>.",
+'wlheader-showupdated' => 'Pages that have been changed since you last visited them are shown in <strong>bold</strong>.',
 'watchmethod-recent'   => 'checking recent edits for watched pages',
 'watchmethod-list'     => 'checking watched pages for recent edits',
 'watchlistcontains'    => 'Your watchlist contains $1 {{PLURAL:$1|page|pages}}.',
 'iteminvalidname'      => 'Problem with item "$1", invalid name...',
-'wlnote2'              => "Below are the changes in the last {{PLURAL:$1|hour|<strong>$1</strong> hours}}, as of $2, $3.",
+'wlnote2'              => 'Below are the changes in the last {{PLURAL:$1|hour|<strong>$1</strong> hours}}, as of $2, $3.',
 'wlshowlast'           => 'Show last $1 hours $2 days $3',
 'watchlist-options'    => 'Watchlist options',
 
@@ -3044,41 +3056,41 @@ Feedback and further assistance:
 'changed'                      => 'changed', # only translate this message to other languages if you have to change it
 
 # Delete
-'deletepage'             => 'Delete page',
-'confirm'                => 'Confirm',
-'excontent'              => 'content was: "$1"',
-'excontentauthor'        => 'content was: "$1" (and the only contributor was "[[Special:Contributions/$2|$2]]")',
-'exbeforeblank'          => 'content before blanking was: "$1"',
-'exblank'                => 'page was empty',
-'delete-confirm'         => 'Delete "$1"',
-'delete-legend'          => 'Delete',
-'historywarning'         => "<strong>Warning:</strong> The page you are about to delete has a history with approximately $1 {{PLURAL:$1|revision|revisions}}:",
-'confirmdeletetext'      => 'You are about to delete a page along with all of its history.
+'deletepage'                 => 'Delete page',
+'confirm'                    => 'Confirm',
+'excontent'                  => 'content was: "$1"',
+'excontentauthor'            => 'content was: "$1" (and the only contributor was "[[Special:Contributions/$2|$2]]")',
+'exbeforeblank'              => 'content before blanking was: "$1"',
+'exblank'                    => 'page was empty',
+'delete-confirm'             => 'Delete "$1"',
+'delete-legend'              => 'Delete',
+'historywarning'             => '<strong>Warning:</strong> The page you are about to delete has a history with approximately $1 {{PLURAL:$1|revision|revisions}}:',
+'confirmdeletetext'          => 'You are about to delete a page along with all of its history.
 Please confirm that you intend to do this, that you understand the consequences, and that you are doing this in accordance with [[{{MediaWiki:Policy-url}}|the policy]].',
-'deleting-backlinks-warning' => "'''Warning:''' Other pages link to or transclude from the page you are about to delete.",
-'actioncomplete'         => 'Action complete',
-'actionfailed'           => 'Action failed',
-'deletedtext'            => '"$1" has been deleted.
+'actioncomplete'             => 'Action complete',
+'actionfailed'               => 'Action failed',
+'deletedtext'                => '"$1" has been deleted.
 See $2 for a record of recent deletions.',
-'dellogpage'             => 'Deletion log',
-'dellogpagetext'         => 'Below is a list of the most recent deletions.',
-'deletionlog'            => 'deletion log',
-'reverted'               => 'Reverted to earlier revision',
-'deletecomment'          => 'Reason:',
-'deleteotherreason'      => 'Other/additional reason:',
-'deletereasonotherlist'  => 'Other reason',
-'deletereason-dropdown'  => '* Common delete reasons
+'dellogpage'                 => 'Deletion log',
+'dellogpagetext'             => 'Below is a list of the most recent deletions.',
+'deletionlog'                => 'deletion log',
+'reverted'                   => 'Reverted to earlier revision',
+'deletecomment'              => 'Reason:',
+'deleteotherreason'          => 'Other/additional reason:',
+'deletereasonotherlist'      => 'Other reason',
+'deletereason-dropdown'      => '* Common delete reasons
 ** Spam
 ** Vandalism
 ** Copyright violation
 ** Author request
 ** Broken redirect',
-'delete-edit-reasonlist' => 'Edit deletion reasons',
-'delete-toobig'          => 'This page has a large edit history, over $1 {{PLURAL:$1|revision|revisions}}.
+'delete-edit-reasonlist'     => 'Edit deletion reasons',
+'delete-toobig'              => 'This page has a large edit history, over $1 {{PLURAL:$1|revision|revisions}}.
 Deletion of such pages has been restricted to prevent accidental disruption of {{SITENAME}}.',
-'delete-warning-toobig'  => 'This page has a large edit history, over $1 {{PLURAL:$1|revision|revisions}}.
+'delete-warning-toobig'      => 'This page has a large edit history, over $1 {{PLURAL:$1|revision|revisions}}.
 Deleting it may disrupt database operations of {{SITENAME}};
 proceed with caution.',
+'deleting-backlinks-warning' => "'''Warning:''' Other pages link to or transclude the page you are about to delete.",
 
 # Rollback
 'rollback'                   => 'Roll back edits',
@@ -3126,13 +3138,13 @@ See the [[Special:ProtectedPages|protected pages list]] for the list of currentl
 'protect_expiry_invalid'           => 'Expiry time is invalid.',
 'protect_expiry_old'               => 'Expiry time is in the past.',
 'protect-unchain-permissions'      => 'Unlock further protect options',
-'protect-text'                     => "Here you may view and change the protection level for the page <strong>$1</strong>.",
-'protect-locked-blocked'           => "You cannot change protection levels while blocked.
-Here are the current settings for the page <strong>$1</strong>:",
-'protect-locked-dblock'            => "Protection levels cannot be changed due to an active database lock.
-Here are the current settings for the page <strong>$1</strong>:",
-'protect-locked-access'            => "Your account does not have permission to change page protection levels.
-Here are the current settings for the page <strong>$1</strong>:",
+'protect-text'                     => 'Here you may view and change the protection level for the page <strong>$1</strong>.',
+'protect-locked-blocked'           => 'You cannot change protection levels while blocked.
+Here are the current settings for the page <strong>$1</strong>:',
+'protect-locked-dblock'            => 'Protection levels cannot be changed due to an active database lock.
+Here are the current settings for the page <strong>$1</strong>:',
+'protect-locked-access'            => 'Your account does not have permission to change page protection levels.
+Here are the current settings for the page <strong>$1</strong>:',
 'protect-cascadeon'                => "This page is currently protected because it is included in the following {{PLURAL:$1|page, which has|pages, which have}} cascading protection turned on.
 You can change this page's protection level, but it will not affect the cascading protection.",
 'protect-default'                  => 'Allow all users',
@@ -3179,7 +3191,7 @@ You can change this page's protection level, but it will not affect the cascadin
 'undelete'                     => 'View deleted pages',
 'undelete-summary'             => '', # do not translate or duplicate this message to other languages
 'undeletepage'                 => 'View and restore deleted pages',
-'undeletepagetitle'            => "<strong>The following consists of deleted revisions of [[:$1|$1]]</strong>.",
+'undeletepagetitle'            => '<strong>The following consists of deleted revisions of [[:$1|$1]]</strong>.',
 'viewdeletedpage'              => 'View deleted pages',
 'undeletepagetext'             => 'The following {{PLURAL:$1|page has been deleted but is|$1 pages have been deleted but are}} still in the archive and can be restored.
 The archive may be periodically cleaned out.',
@@ -3208,9 +3220,9 @@ You may have a bad link, or the revision may have been restored or removed from
 'undeletedfiles'               => '{{PLURAL:$1|1 file|$1 files}} restored',
 'cannotundelete'               => 'Undelete failed:
 $1',
-'undeletedpage'                => "<strong>$1 has been restored</strong>
+'undeletedpage'                => '<strong>$1 has been restored</strong>
 
-Consult the [[Special:Log/delete|deletion log]] for a record of recent deletions and restorations.",
+Consult the [[Special:Log/delete|deletion log]] for a record of recent deletions and restorations.',
 'undelete-header'              => 'See [[Special:Log/delete|the deletion log]] for recently deleted pages.',
 'undelete-search-title'        => 'Search deleted pages',
 'undelete-search-box'          => 'Search deleted pages',
@@ -3229,7 +3241,7 @@ It may have already been undeleted.',
 $1',
 'undelete-show-file-confirm'   => 'Are you sure you want to view the deleted revision of the file "<nowiki>$1</nowiki>" from $2 at $3?',
 'undelete-show-file-submit'    => 'Yes',
-'undelete-revision-row'         => '$1 $2 ($3) $4 . . $5 $6 $7 $8 $9', # only translate this message to other languages if you have to change it
+'undelete-revision-row'        => '$1 $2 ($3) $4 . . $5 $6 $7 $8 $9', # only translate this message to other languages if you have to change it
 
 # Namespace form on various pages
 'namespace'                     => 'Namespace:',
@@ -3267,6 +3279,7 @@ The latest block log entry is provided below for reference:',
 'sp-contributions-search'              => 'Search for contributions',
 'sp-contributions-username'            => 'IP address or username:',
 'sp-contributions-toponly'             => 'Only show edits that are latest revisions',
+'sp-contributions-newonly'             => 'Only show edits that are page creations',
 'sp-contributions-submit'              => 'Search',
 'sp-contributions-explain'             => '', # only translate this message to other languages if you have to change it
 'sp-contributions-footer'              => '-', # do not translate or duplicate this message to other languages
@@ -3278,9 +3291,9 @@ The latest block log entry is provided below for reference:',
 'whatlinkshere-title'      => 'Pages that link to "$1"',
 'whatlinkshere-summary'    => '', # do not translate or duplicate this message to other languages
 'whatlinkshere-page'       => 'Page:',
-'linkshere'                => "The following pages link to <strong>[[:$1]]</strong>:",
-'nolinkshere'              => "No pages link to <strong>[[:$1]]</strong>.",
-'nolinkshere-ns'           => "No pages link to <strong>[[:$1]]</strong> in the chosen namespace.",
+'linkshere'                => 'The following pages link to <strong>[[:$1]]</strong>:',
+'nolinkshere'              => 'No pages link to <strong>[[:$1]]</strong>.',
+'nolinkshere-ns'           => 'No pages link to <strong>[[:$1]]</strong> in the chosen namespace.',
 'isredirect'               => 'redirect page',
 'istemplate'               => 'transclusion',
 'isimage'                  => 'file link',
@@ -3448,7 +3461,7 @@ To lock or unlock the database, this needs to be writable by the web server.',
 'move-page'                    => 'Move $1',
 'movepage-summary'             => '', # do not translate or duplicate this message to other languages
 'move-page-legend'             => 'Move page',
-'movepagetext'                 => "Using the form below will rename a page, moving all of its history to the new name.
+'movepagetext'                 => 'Using the form below will rename a page, moving all of its history to the new name.
 The old title will become a redirect page to the new title.
 You can update redirects that point to the original title automatically.
 If you choose not to, be sure to check for [[Special:DoubleRedirects|double]] or [[Special:BrokenRedirects|broken redirects]].
@@ -3459,8 +3472,8 @@ This means that you can rename a page back to where it was renamed from if you m
 
 <strong>Warning!</strong>
 This can be a drastic and unexpected change for a popular page;
-please be sure you understand the consequences of this before proceeding.",
-'movepagetext-noredirectfixer' => "Using the form below will rename a page, moving all of its history to the new name.
+please be sure you understand the consequences of this before proceeding.',
+'movepagetext-noredirectfixer' => 'Using the form below will rename a page, moving all of its history to the new name.
 The old title will become a redirect page to the new title.
 Be sure to check for [[Special:DoubleRedirects|double]] or [[Special:BrokenRedirects|broken redirects]].
 You are responsible for making sure that links continue to point where they are supposed to go.
@@ -3470,14 +3483,14 @@ This means that you can rename a page back to where it was renamed from if you m
 
 <strong>Warning!</strong>
 This can be a drastic and unexpected change for a popular page;
-please be sure you understand the consequences of this before proceeding.",
-'movepagetalktext'             => "The associated talk page will be automatically moved along with it <strong>unless:</strong>
+please be sure you understand the consequences of this before proceeding.',
+'movepagetalktext'             => 'The associated talk page will be automatically moved along with it <strong>unless:</strong>
 *A non-empty talk page already exists under the new name, or
 *You uncheck the box below.
 
-In those cases, you will have to move or merge the page manually if desired.",
+In those cases, you will have to move or merge the page manually if desired.',
 'movearticle'                  => 'Move page:',
-'moveuserpage-warning'         => "<strong>Warning:</strong> You are about to move a user page. Please note that only the page will be moved and the user will <em>not</em> be renamed.",
+'moveuserpage-warning'         => '<strong>Warning:</strong> You are about to move a user page. Please note that only the page will be moved and the user will <em>not</em> be renamed.',
 'movenologintext'              => 'You must be a registered user and [[Special:UserLogin|logged in]] to move a page.',
 'movenotallowed'               => 'You do not have permission to move pages.',
 'movenotallowedfile'           => 'You do not have permission to move files.',
@@ -3528,10 +3541,10 @@ cannot move a page over itself.',
 'imageinvalidfilename'         => 'The target filename is invalid',
 'fix-double-redirects'         => 'Update any redirects that point to the original title',
 'move-leave-redirect'          => 'Leave a redirect behind',
-'protectedpagemovewarning'     => "<strong>Warning:</strong> This page has been protected so that only users with administrator privileges can move it.
-The latest log entry is provided below for reference:",
-'semiprotectedpagemovewarning' => "<strong>Note:</strong> This page has been protected so that only registered users can move it.
-The latest log entry is provided below for reference:",
+'protectedpagemovewarning'     => '<strong>Warning:</strong> This page has been protected so that only users with administrator privileges can move it.
+The latest log entry is provided below for reference:',
+'semiprotectedpagemovewarning' => '<strong>Note:</strong> This page has been protected so that only registered users can move it.
+The latest log entry is provided below for reference:',
 'move-over-sharedrepo'         => '== File exists ==
 [[:$1]] exists on a shared repository. Moving a file to this title will override the shared file.',
 'file-exists-sharedrepo'       => 'The filename chosen is already in use on a shared repository.
@@ -3548,8 +3561,8 @@ To export pages, enter the titles in the text box below, one title per line, and
 In the latter case you can also use a link, for example [[{{#Special:Export}}/{{MediaWiki:Mainpage}}]] for the page "[[{{MediaWiki:Mainpage}}]]".',
 'exportall'         => 'Export all pages',
 'exportcuronly'     => 'Include only the current revision, not the full history',
-'exportnohistory'   => "----
-<strong>Note:</strong> Exporting the full history of pages through this form has been disabled due to performance reasons.",
+'exportnohistory'   => '----
+<strong>Note:</strong> Exporting the full history of pages through this form has been disabled due to performance reasons.',
 'exportlistauthors' => 'Include a full list of contributors for each page',
 'export-submit'     => 'Export',
 'export-addcattext' => 'Add pages from category:',
@@ -3567,7 +3580,7 @@ In the latter case you can also use a link, for example [[{{#Special:Export}}/{{
 'allmessagescurrent'            => 'Current message text',
 'allmessagestext'               => 'This is a list of system messages available in the MediaWiki namespace.
 Please visit [https://www.mediawiki.org/wiki/Localisation MediaWiki Localisation] and [//translatewiki.net translatewiki.net] if you wish to contribute to the generic MediaWiki localisation.',
-'allmessagesnotsupportedDB'     => "This page cannot be used because <strong>\$wgUseDatabaseMessages</strong> has been disabled.",
+'allmessagesnotsupportedDB'     => 'This page cannot be used because <strong>$wgUseDatabaseMessages</strong> has been disabled.',
 'allmessages-filter-legend'     => 'Filter',
 'allmessages-filter'            => 'Filter by customization state:',
 'allmessages-filter-unmodified' => 'Unmodified',
@@ -3579,20 +3592,20 @@ Please visit [https://www.mediawiki.org/wiki/Localisation MediaWiki Localisation
 'allmessages-filter-translate'  => 'Translate',
 
 # Thumbnails
-'thumbnail-more'           => 'Enlarge',
-'filemissing'              => 'File missing',
-'thumbnail_error'          => 'Error creating thumbnail: $1',
-'thumbnail_error_remote'   => 'Error message from $1:
+'thumbnail-more'                => 'Enlarge',
+'filemissing'                   => 'File missing',
+'thumbnail_error'               => 'Error creating thumbnail: $1',
+'thumbnail_error_remote'        => 'Error message from $1:
 $2',
-'djvu_page_error'          => 'DjVu page out of range',
-'djvu_no_xml'              => 'Unable to fetch XML for DjVu file',
-'thumbnail-temp-create'    => 'Unable to create temporary thumbnail file',
-'thumbnail-dest-create'    => 'Unable to save thumbnail to destination',
-'thumbnail_invalid_params' => 'Invalid thumbnail parameters',
-'thumbnail_dest_directory' => 'Unable to create destination directory',
-'thumbnail_image-type'     => 'Image type not supported',
-'thumbnail_gd-library'     => 'Incomplete GD library configuration: Missing function $1',
-'thumbnail_image-missing'  => 'File seems to be missing: $1',
+'djvu_page_error'               => 'DjVu page out of range',
+'djvu_no_xml'                   => 'Unable to fetch XML for DjVu file',
+'thumbnail-temp-create'         => 'Unable to create temporary thumbnail file',
+'thumbnail-dest-create'         => 'Unable to save thumbnail to destination',
+'thumbnail_invalid_params'      => 'Invalid thumbnail parameters',
+'thumbnail_dest_directory'      => 'Unable to create destination directory',
+'thumbnail_image-type'          => 'Image type not supported',
+'thumbnail_gd-library'          => 'Incomplete GD library configuration: Missing function $1',
+'thumbnail_image-missing'       => 'File seems to be missing: $1',
 'thumbnail_image-failure-limit' => 'There have been too many recent failed attempts ($1 or more) to render this thumbnail. Please try again later.',
 
 # Special:Import
@@ -3807,6 +3820,8 @@ You can view its source',
 'tooltip-undo'                        => '"Undo" reverts this edit and opens the edit form in preview mode. It allows adding a reason in the summary.',
 'tooltip-preferences-save'            => 'Save preferences',
 'tooltip-summary'                     => 'Enter a short summary',
+'interlanguage-link-title'            => '$1 – $2', # only translate this message to other languages if you have to change it
+'interlanguage-link-title-langonly'   => '$1', # do not translate or duplicate this message to other languages
 
 # Stylesheets
 'common.css'              => '/* CSS placed here will be applied to all skins */', # only translate this message to other languages if you have to change it
@@ -3850,16 +3865,16 @@ You can view its source',
 'nocredits'        => 'There is no credits info available for this page.',
 
 # Spam protection
-'spamprotectiontitle' => 'Spam protection filter',
-'spamprotectiontext'  => 'The text you wanted to save was blocked by the spam filter.
+'spamprotectiontitle'  => 'Spam protection filter',
+'spamprotectiontext'   => 'The text you wanted to save was blocked by the spam filter.
 This is probably caused by a link to a blacklisted external site.',
-'spamprotectionmatch' => 'The following text is what triggered our spam filter: $1',
-'spambot_username'    => 'MediaWiki spam cleanup',
-'spam_reverting'      => 'Reverting to last revision not containing links to $1',
-'spam_blanking'       => 'All revisions contained links to $1, blanking',
-'spam_deleting'       => 'All revisions contained links to $1, deleting',
-'simpleantispam-label' => "Anti-spam check.
-Do <strong>NOT</strong> fill this in!",
+'spamprotectionmatch'  => 'The following text is what triggered our spam filter: $1',
+'spambot_username'     => 'MediaWiki spam cleanup',
+'spam_reverting'       => 'Reverting to last revision not containing links to $1',
+'spam_blanking'        => 'All revisions contained links to $1, blanking',
+'spam_deleting'        => 'All revisions contained links to $1, deleting',
+'simpleantispam-label' => 'Anti-spam check.
+Do <strong>NOT</strong> fill this in!',
 
 # Info page
 'pageinfo-header'                 => '-', # do not translate or duplicate this message to other languages
@@ -3952,9 +3967,9 @@ $1',
 'nextdiff'     => 'Newer edit →',
 
 # Media information
-'mediawarning'                => "<strong>Warning:</strong> This file type may contain malicious code.
-By executing it, your system may be compromised.",
-'imagemaxsize'                => "Image size limit:<br /><em>(for file description pages)</em>",
+'mediawarning'                => '<strong>Warning:</strong> This file type may contain malicious code.
+By executing it, your system may be compromised.',
+'imagemaxsize'                => 'Image size limit:<br /><em>(for file description pages)</em>',
 'thumbsize'                   => 'Thumbnail size:',
 'widthheight'                 => '$1 × $2', # only translate this message to other languages if you have to change it
 'widthheightpage'             => '$1 × $2, $3 {{PLURAL:$3|page|pages}}',
@@ -3974,12 +3989,12 @@ By executing it, your system may be compromised.",
 'file-info-png-looped'        => 'looped',
 'file-info-png-repeat'        => 'played $1 {{PLURAL:$1|time|times}}',
 'file-info-png-frames'        => '$1 {{PLURAL:$1|frame|frames}}',
-'file-no-thumb-animation'     => "<strong>Note: Due to technical limitations, thumbnails of this file will not be animated.</strong>",
-'file-no-thumb-animation-gif' => "<strong>Note: Due to technical limitations, thumbnails of high resolution GIF images such as this one will not be animated.</strong>",
+'file-no-thumb-animation'     => '<strong>Note: Due to technical limitations, thumbnails of this file will not be animated.</strong>',
+'file-no-thumb-animation-gif' => '<strong>Note: Due to technical limitations, thumbnails of high resolution GIF images such as this one will not be animated.</strong>',
 
 # Special:NewFiles
 'newimages'             => 'Gallery of new files',
-'imagelisttext'         => "Below is a list of <strong>$1</strong> {{PLURAL:$1|file|files}} sorted $2.",
+'imagelisttext'         => 'Below is a list of <strong>$1</strong> {{PLURAL:$1|file|files}} sorted $2.',
 'newimages-summary'     => 'This special page shows the last uploaded files.',
 'newimages-legend'      => 'Filter',
 'newimages-label'       => 'Filename (or a part of it):',
@@ -4100,7 +4115,7 @@ Others will be hidden by default.
 * gpslatitude
 * gpslongitude
 * gpsaltitude',
-'metadata-langitem'         => "<strong>$2:</strong> $1", # only translate this message to other languages if you have to change it
+'metadata-langitem'         => '<strong>$2:</strong> $1', # only translate this message to other languages if you have to change it
 'metadata-langitem-default' => '$1', # only translate this message to other languages if you have to change it
 
 # Exif tags
@@ -4618,10 +4633,10 @@ This confirmation code will expire at $4.',
 'scarytranscludetoolong'           => '[URL is too long]',
 
 # Delete conflict
-'deletedwhileediting'      => "<strong>Warning:</strong> This page was deleted after you started editing!",
-'confirmrecreate'          => "User [[User:$1|$1]] ([[User talk:$1|talk]]) deleted this page after you started editing with reason:
+'deletedwhileediting'      => '<strong>Warning:</strong> This page was deleted after you started editing!',
+'confirmrecreate'          => 'User [[User:$1|$1]] ([[User talk:$1|talk]]) deleted this page after you started editing with reason:
 : <em>$2</em>
-Please confirm that you really want to recreate this page.",
+Please confirm that you really want to recreate this page.',
 'confirmrecreate-noreason' => 'User [[User:$1|$1]] ([[User talk:$1|talk]]) deleted this page after you started editing. Please confirm that you really want to recreate this page.',
 'recreate'                 => 'Recreate',
 
@@ -4657,10 +4672,11 @@ Please confirm that you really want to recreate this page.",
 'imgmultigo'       => 'Go!',
 'imgmultigoto'     => 'Go to page $1',
 
-'img-lang-opt' => '$2 ($1)',
+# Language selector for translatable SVGs
+'img-lang-opt'     => '$2 ($1)', # only translate this message to other languages if you have to change it
 'img-lang-default' => '(default language)',
-'img-lang-info' => 'Render this image in $1. $2',
-'img-lang-go' => 'Go',
+'img-lang-info'    => 'Render this image in $1. $2',
+'img-lang-go'      => 'Go',
 
 # Table pager
 'ascending_abbrev'         => 'asc',
@@ -4850,20 +4866,20 @@ You can also [[Special:EditWatchlist|use the standard editor]].',
 'version-parser-function-hooks'         => 'Parser function hooks',
 'version-hook-name'                     => 'Hook name',
 'version-hook-subscribedby'             => 'Subscribed by',
-'version-version'                       => '($1)',
+'version-version'                       => '($1)', # only translate this message to other languages if you have to change it
 'version-svn-revision'                  => 'r$1', # only translate this message to other languages if you have to change it
 'version-license'                       => 'MediaWiki License',
-'version-license-title'                 => 'License for $1',
-'version-license-not-found'             => 'No detailed license information was found for this extension.',
-'version-credits-title'                 => 'Credits for $1',
-'version-credits-not-found'             => 'No detailed credits information was found for this extension.',
 'version-ext-license'                   => 'License',
 'version-ext-colheader-name'            => 'Extension',
 'version-ext-colheader-version'         => 'Version',
 'version-ext-colheader-license'         => 'License',
 'version-ext-colheader-description'     => 'Description',
 'version-ext-colheader-credits'         => 'Authors',
-'version-poweredby-credits'             => "This wiki is powered by <strong>[https://www.mediawiki.org/ MediaWiki]</strong>, copyright © 2001-$1 $2.",
+'version-license-title'                 => 'License for $1',
+'version-license-not-found'             => 'No detailed license information was found for this extension.',
+'version-credits-title'                 => 'Credits for $1',
+'version-credits-not-found'             => 'No detailed credits information was found for this extension.',
+'version-poweredby-credits'             => 'This wiki is powered by <strong>[https://www.mediawiki.org/ MediaWiki]</strong>, copyright © 2001-$1 $2.',
 'version-poweredby-others'              => 'others',
 'version-poweredby-translators'         => 'translatewiki.net translators',
 'version-credits-summary'               => 'We would like to recognize the following persons for their contribution to [[Special:Version|MediaWiki]].',
@@ -4900,8 +4916,8 @@ You should have received [{{SERVER}}{{SCRIPTPATH}}/COPYING a copy of the GNU Gen
 'redirect-lookup'     => 'Lookup:',
 'redirect-value'      => 'Value:',
 'redirect-user'       => 'User ID',
-'redirect-revision'   => 'Page revision',
 'redirect-page'       => 'Page ID',
+'redirect-revision'   => 'Page revision',
 'redirect-file'       => 'File name',
 'redirect-not-exists' => 'Value not found',
 
@@ -5122,6 +5138,7 @@ Otherwise, you can use the easy form below. Your comment will be added to the pa
 'api-error-overwrite'                     => 'Overwriting an existing file is not allowed.',
 'api-error-stashfailed'                   => 'Internal error: Server failed to store temporary file.',
 'api-error-publishfailed'                 => 'Internal error: Server failed to publish temporary file.',
+'api-error-stasherror'                    => 'There was an error while uploading the file to stash.',
 'api-error-timeout'                       => 'The server did not respond within the expected time.',
 'api-error-unclassified'                  => 'An unknown error occurred.',
 'api-error-unknown-code'                  => 'Unknown error: "$1".',
@@ -5130,7 +5147,6 @@ Otherwise, you can use the easy form below. Your comment will be added to the pa
 'api-error-unknownerror'                  => 'Unknown error: "$1".',
 'api-error-uploaddisabled'                => 'Uploading is disabled on this wiki.',
 'api-error-verification-error'            => 'This file might be corrupt, or have the wrong extension.',
-'api-error-stasherror'                    => 'There was an error while uploading the file to stash.',
 
 # Durations
 'duration-seconds'   => '$1 {{PLURAL:$1|second|seconds}}',
@@ -5165,7 +5181,7 @@ Otherwise, you can use the easy form below. Your comment will be added to the pa
 'limitreport-expensivefunctioncount'       => 'Expensive parser function count',
 'limitreport-expensivefunctioncount-value' => '$1/$2', # only translate this message to other languages if you have to change it
 
-# ExpandTemplates
+# Special:ExpandTemplates
 'expandtemplates'                   => 'Expand templates',
 'expand_templates_intro'            => 'This special page takes text and expands all templates in it recursively.
 It also expands supported parser functions like
@@ -5183,4 +5199,5 @@ In fact, it expands pretty much everything in double-braces.',
 'expand_templates_generate_xml'     => 'Show XML parse tree',
 'expand_templates_generate_rawhtml' => 'Show raw HTML',
 'expand_templates_preview'          => 'Preview',
+
 );
index 40888f6..e2405f4 100644 (file)
@@ -868,6 +868,9 @@ Bonvolu ĝisatendi $1 antaŭ reprovi.',
 'suspicious-userlogout' => 'Via peto por elsaluti estis malpermesita, ĉar verŝajne ĝi estis sendita de trompita retumilo aŭ kaŝiĝanta prokura servilo.',
 'createacct-another-realname-tip' => 'La vera nomo estas nenecesa.
 Se vi decidas indiki ĝin, ĝi estos uzata por montri atribuadon de viaj kontribuoj.',
+'pt-login' => 'Ensaluti',
+'pt-createaccount' => 'Krei novan konton',
+'pt-userlogout' => 'Elsaluti',
 
 # Email sending
 'php-mail-error-unknown' => 'Nekonata eraro en la funkcio mail() de PHP',
@@ -876,7 +879,7 @@ Se vi decidas indiki ĝin, ĝi estos uzata por montri atribuadon de viaj kontrib
 
 # Change password dialog
 'changepassword' => 'Ŝanĝi pasvorton',
-'resetpass_announce' => 'Vi ensalutis kun provizora retpoŝtita pasvorto. Por kompleti ensalutadon, vi devas fari novan pasvorton ĉi tie:',
+'resetpass_announce' => 'Por kompleti ensaluton vi devas agordi novan pasvorton.',
 'resetpass_text' => '<!-- Aldonu tekston ĉi tien -->',
 'resetpass_header' => 'Ŝanĝi kontan pasvorton',
 'oldpassword' => 'Malnova pasvorto',
@@ -884,12 +887,15 @@ Se vi decidas indiki ĝin, ĝi estos uzata por montri atribuadon de viaj kontrib
 'retypenew' => 'Retajpi novan pasvorton',
 'resetpass_submit' => 'Fari pasvorton kaj ensaluti',
 'changepassword-success' => 'Via pasvorto estis sukcese ŝanĝita!',
+'changepassword-throttled' => 'Vi tro ofte provis ensaluti al ĉi tiu konto.
+Bonvolu atendi $1 antaŭ ol reprovi.',
 'resetpass_forbidden' => 'Pasvortoj ne estas ŝanĝeblaj',
 'resetpass-no-info' => 'Vi devas ensaluti por atingi ĉi tiun paĝon rekte.',
 'resetpass-submit-loggedin' => 'Ŝanĝi pasvorton',
 'resetpass-submit-cancel' => 'Nuligi',
 'resetpass-wrong-oldpass' => 'Malvalida provizora aŭ nuna pasvorto.
 Vi eble jam ŝanĝis vian pasvorton aŭ petis novan provizoran pasvorton.',
+'resetpass-recycled' => 'Bonvolu agordi vian novan pasvorton, kiu estu alia ol via nuntempa pasvorto.',
 'resetpass-temp-password' => 'Provizora pasvorto:',
 'resetpass-abort-generic' => 'Ŝanĝo de pasvorto estis nuligita per kromprogramo.',
 
@@ -1719,15 +1725,28 @@ indekso pro troŝarĝita servilo. Intertempe, vi povas serĉi per <i>guglo</i> a
 'recentchanges-label-minor' => 'Ĉi tiu estas eta redakto',
 'recentchanges-label-bot' => 'Ĉi tiu redakto estis farita per roboto.',
 'recentchanges-label-unpatrolled' => 'Ĉi tiu redakto ne jam estis patrolata.',
+'recentchanges-legend-heading' => "'''Klarigo:'''",
 'recentchanges-legend-newpage' => '(vidu ankaŭ [[Special:NewPages|liston de novaj paĝoj]])',
 'rcnotefrom' => "Jen la ŝanĝoj ekde '''$2''' (lastaj ĝis '''$1''').",
 'rclistfrom' => 'Montri novajn ŝanĝojn ekde "$1"',
 'rcshowhideminor' => '$1 redaktetojn',
+'rcshowhideminor-show' => 'Montri',
+'rcshowhideminor-hide' => 'Kaŝi',
 'rcshowhidebots' => '$1 robotojn',
+'rcshowhidebots-show' => 'Montri',
+'rcshowhidebots-hide' => 'Kaŝi',
 'rcshowhideliu' => '$1 registriĝintojn',
+'rcshowhideliu-show' => 'Montri',
+'rcshowhideliu-hide' => 'Kaŝi',
 'rcshowhideanons' => '$1 anonimajn redaktojn',
+'rcshowhideanons-show' => 'Montri',
+'rcshowhideanons-hide' => 'Kaŝi',
 'rcshowhidepatr' => '$1 patrolitajn redaktojn',
+'rcshowhidepatr-show' => 'Montri',
+'rcshowhidepatr-hide' => 'Kaŝi',
 'rcshowhidemine' => '$1 miajn redaktojn',
+'rcshowhidemine-show' => 'Montri',
+'rcshowhidemine-hide' => 'Kaŝi',
 'rclinks' => 'Montri $1 lastajn ŝanĝojn dum la $2 lastaj tagoj.<br />$3',
 'diff' => 'malsamoj',
 'hist' => 'historio',
@@ -1853,6 +1872,7 @@ Se vi ankoraŭ volas alŝuti vian dosieron, bonvolu retroigi kaj uzi novan nomon
 'uploaddisabledtext' => 'Alŝutado de dosieroj estas malebligita.',
 'php-uploaddisabledtext' => 'Dosiera alŝutado estas malŝalta en PHP. Bonvolu kontroli la preferon file_uploads.',
 'uploadscripted' => 'HTML-aĵo aŭ skriptokodaĵo troviĝas en tiu ĉi tiu dosiero, kiun TTT-foliumilo eble interpretus erare.',
+'uploadinvalidxml' => 'Ne eblas interpreti la XML-sintakson en la alŝutita dosiero',
 'uploadvirus' => 'Viruso troviĝas en la dosiero! Detaloj: $1',
 'uploadjava' => 'La dosiero estas ZIP-dosiero kiu enhavas .class-dosieron de Java.
 Alŝutante Java-dosieron estas malpermesita, ĉar ili povas kaŭzi sekureco-limigojn esti preterpasitaj.',
@@ -2196,6 +2216,7 @@ Bonvolu kontroli aliajn ligilojn al la ŝablonoj antaŭ ol forigi ilin.',
 'mostrevisions' => 'Artikoloj kun la plej multaj versioj',
 'prefixindex' => 'Ĉiuj paĝoj kun prefikso',
 'prefixindex-namespace' => 'Ĉiuj paĝoj kun prefikso ($1 nomspaco)',
+'prefixindex-strip' => 'Ne montri prefikson en listo',
 'shortpages' => 'Mallongaj paĝoj',
 'longpages' => 'Longaj paĝoj',
 'deadendpages' => 'Paĝoj sen interna ligilo',
@@ -2203,6 +2224,7 @@ Bonvolu kontroli aliajn ligilojn al la ŝablonoj antaŭ ol forigi ilin.',
 'protectedpages' => 'Protektitaj paĝoj',
 'protectedpages-indef' => 'Nur ĉiamaj protektaĵoj',
 'protectedpages-cascade' => 'Nur kaskadaj protektoj',
+'protectedpages-noredirect' => 'Kaŝi alidirektilojn',
 'protectedpagesempty' => 'Neniuj paĝoj estas momente protektitaj kun ĉi tiuj parametroj.',
 'protectedpages-timestamp' => 'Tempindiko',
 'protectedpages-page' => 'Paĝo',
@@ -2948,6 +2970,7 @@ se vi volus kontribui al la komuna MediaWiki-asimilado.',
 'allmessages-prefix' => 'Filtri laŭ prefikso:',
 'allmessages-language' => 'Lingvo:',
 'allmessages-filter-submit' => 'Ek!',
+'allmessages-filter-translate' => 'Traduki',
 
 # Thumbnails
 'thumbnail-more' => 'Pligrandigi',
@@ -3814,6 +3837,10 @@ Bonvolu konfirmi ke vi ja volas rekrei la paĝon.',
 'imgmultigo' => 'Ek!',
 'imgmultigoto' => 'Iri al paĝo $1',
 
+# Language selector for translatable SVGs
+'img-lang-default' => '(defaŭlta lingvo)',
+'img-lang-go' => 'Ek',
+
 # Table pager
 'ascending_abbrev' => 'sprn',
 'descending_abbrev' => 'subn',
@@ -3949,6 +3976,13 @@ Vi povas ankaŭ [[Special:EditWatchlist|redakti norme]].',
 'version-hook-subscribedby' => 'Abonita de',
 'version-version' => '($1)',
 'version-license' => 'Permesilo de MediaWiki',
+'version-ext-license' => 'Permesilo',
+'version-ext-colheader-version' => 'Versio',
+'version-ext-colheader-license' => 'Permesilo',
+'version-ext-colheader-description' => 'Priskribo',
+'version-ext-colheader-credits' => 'Aŭtoroj',
+'version-license-title' => 'Permesilo por $1',
+'version-credits-title' => 'Agnosko por $1',
 'version-poweredby-credits' => "Ĉi tiu vikio funkcias per '''[https://www.mediawiki.org/ MediaWiki]''', aŭtorrajto ©&thinsp;2001–$1 $2.",
 'version-poweredby-others' => 'aliaj',
 'version-poweredby-translators' => 'tradukantoj de translatewiki.net',
@@ -3966,10 +4000,12 @@ Oni devis doni al vi [{{SERVER}}{{SCRIPTPATH}}/COPYING ekzempleron de la GNU Gen
 'version-entrypoints-header-url' => 'Retadreso',
 
 # Special:Redirect
+'redirect-legend' => 'Alidirektilo al dosiero aŭ paĝo',
 'redirect-submit' => 'Ek',
 'redirect-lookup' => 'Traserĉi:',
 'redirect-value' => 'Valoro:',
 'redirect-user' => 'Salutnomo',
+'redirect-page' => 'Paĝa identigo',
 'redirect-revision' => 'Revizio de la paĝo',
 'redirect-file' => 'Dosiernomo',
 'redirect-not-exists' => 'Valoro ne trovita',
@@ -3987,6 +4023,7 @@ Oni devis doni al vi [{{SERVER}}{{SCRIPTPATH}}/COPYING ekzempleron de la GNU Gen
 
 # Special:SpecialPages
 'specialpages' => 'Specialaj paĝoj',
+'specialpages-note-top' => 'Klarigo',
 'specialpages-note' => '* Normaj specialaj paĝoj.
 * <span class="mw-specialpagerestricted">Limigitaj specialaj paĝoj.</span>',
 'specialpages-group-maintenance' => 'Raportoj pri prizorgado',
@@ -4186,8 +4223,12 @@ Aŭ vi povas uzi la facilan formularon sube. Via komento estos aldonita al la pa
 'rotate-comment' => 'Bildo pivotita $1 {{PLURAL:$1|gradon|gradojn}} dekstren',
 
 # Limit report
+'limitreport-cputime' => 'Uzo de procesora tempo',
 'limitreport-cputime-value' => '$1 {{PLURAL:$1|sekundo|sekundoj}}',
+'limitreport-walltime' => 'Uzo de reala tempo',
 'limitreport-walltime-value' => '$1 {{PLURAL:$1|sekundo|sekundoj}}',
+'limitreport-ppvisitednodes' => 'Nombro da nodoj vizititaj de antaŭtraktilo',
+'limitreport-ppgeneratednodes' => 'Nombro da nodoj kreitaj de antaŭtraktilo',
 'limitreport-postexpandincludesize-value' => '$1/$2 {{PLURAL:$2|bitoko|bitokoj}}',
 'limitreport-templateargumentsize-value' => '$1/$2 {{PLURAL:$2|bitoko|bitokoj}}',
 
@@ -4201,12 +4242,12 @@ Aŭ vi povas uzi la facilan formularon sube. Via komento estos aldonita al la pa
 'expand_templates_input' => 'Enigita teksto:',
 'expand_templates_output' => 'Rezulto',
 'expand_templates_xml_output' => 'XML-eligo',
+'expand_templates_html_output' => 'Kruda eliga HTML',
 'expand_templates_ok' => 'Ek!',
 'expand_templates_remove_comments' => 'Forigi komentojn',
 'expand_templates_remove_nowiki' => 'Nuligi <nowiki> etikedojn en rezulto',
 'expand_templates_generate_xml' => 'Montri XML-sintaksarbon',
+'expand_templates_generate_rawhtml' => 'Montri krudan HTML-n',
 'expand_templates_preview' => 'Antaŭrigardo',
 
-# Unknown messages
-'uploadinvalidxml' => 'Ne eblas interpreti la XML-sintakson en la alŝutita dosiero',
 );
index 21d63d7..d42e385 100644 (file)
@@ -26,6 +26,7 @@
  * @author Candalua
  * @author Capmo
  * @author Carlitosag
+ * @author Carlosz22
  * @author Cerealito
  * @author Ciencia Al Poder
  * @author Clerc
@@ -1813,11 +1814,23 @@ Tu dirección de correo no se revela cuando otros usuarios te contactan.',
 'rcnotefrom' => 'A continuación se muestran los cambios desde <b>$2</b> (hasta <b>$1</b>).',
 'rclistfrom' => 'Mostrar nuevos cambios desde $1',
 'rcshowhideminor' => '$1 ediciones menores',
+'rcshowhideminor-show' => 'Mostrar',
+'rcshowhideminor-hide' => 'Ocultar',
 'rcshowhidebots' => '$1 bots',
+'rcshowhidebots-show' => 'Mostrar',
+'rcshowhidebots-hide' => 'Ocultar',
 'rcshowhideliu' => '$1 usuarios registrados',
+'rcshowhideliu-show' => 'Mostrar',
+'rcshowhideliu-hide' => 'Ocultar',
 'rcshowhideanons' => '$1 usuarios anónimos',
+'rcshowhideanons-show' => 'Mostrar',
+'rcshowhideanons-hide' => 'Ocultar',
 'rcshowhidepatr' => '$1 ediciones patrulladas',
+'rcshowhidepatr-show' => 'Mostrar',
+'rcshowhidepatr-hide' => 'Ocultar',
 'rcshowhidemine' => '$1 mis ediciones',
+'rcshowhidemine-show' => 'Mostrar',
+'rcshowhidemine-hide' => 'Ocultar',
 'rclinks' => 'Ver los últimos $1 cambios en los últimos $2 días.<br />$3',
 'diff' => 'dif',
 'hist' => 'hist',
@@ -1940,6 +1953,8 @@ Si todavía quiere subir su archivo, por favor, regrese a la página anterior y
 'uploaddisabledtext' => 'No es posible subir archivos.',
 'php-uploaddisabledtext' => 'La subida de archivos está deshabilitada en PHP. Por favor compruebe <code>file_uploads</code> en php.ini.',
 'uploadscripted' => 'Este archivo contiene script o código HTML que puede ser interpretado erróneamente por un navegador web.',
+'uploadscriptednamespace' => "Este archivo SVG contiene un espacio de nombre no permitido '$1'",
+'uploadinvalidxml' => 'No se pudo analizar el XML del archivo cargado.',
 'uploadvirus' => '¡El archivo contiene un virus!
 Detalles: $1',
 'uploadjava' => 'El archivo es un ZIP que contiene un archivo .class de Java.
@@ -2311,7 +2326,7 @@ Las entradas <del>tachadas</del> han sido resueltas.',
 'deadendpagestext' => 'Las siguientes páginas no enlazan a otras páginas de {{SITENAME}}.',
 'protectedpages' => 'Páginas protegidas',
 'protectedpages-indef' => 'Sólo protecciones indefinidas',
-'protectedpages-summary' => 'Esta página enumera las páginas existentes que actualmente están protegidas. Para obtener una lista de títulos que están protegidos desde su creación, véase [[{{#special: ProtectedTitles}}]].',
+'protectedpages-summary' => 'Esta página enumera las páginas existentes que actualmente están protegidas. Para obtener una lista de títulos que están protegidos desde su creación, véase [[{{#special:ProtectedTitles}}]].',
 'protectedpages-cascade' => 'Sólo protecciones en cascada',
 'protectedpages-noredirect' => 'Ocultar redirecciones',
 'protectedpagesempty' => 'Actualmente no hay ninguna página protegida con esos parámetros.',
@@ -2324,7 +2339,7 @@ Las entradas <del>tachadas</del> han sido resueltas.',
 'protectedpages-unknown-timestamp' => 'Desconocido',
 'protectedpages-unknown-performer' => 'Usuario desconocido',
 'protectedtitles' => 'Títulos protegidos',
-'protectedtitles-summary' => 'Esta página enumera títulos que actualmente están protegidos desde su creación. Para una lista de las páginas existentes que están protegidos, véase [[{{#special: ProtectedPages}}]].',
+'protectedtitles-summary' => 'Esta página enumera títulos que actualmente están protegidos desde su creación. Para una lista de las páginas existentes que están protegidos, véase [[{{#special:ProtectedPages}}]].',
 'protectedtitlesempty' => 'Actualmente no existen entradas protegidas con esos parámetros.',
 'listusers' => 'Lista de usuarios',
 'listusers-editsonly' => 'Muestra sólo usuarios con ediciones',
@@ -2772,6 +2787,7 @@ A continuación se muestra la última entrada del registro de bloqueos para mayo
 'sp-contributions-search' => 'Buscar contribuciones',
 'sp-contributions-username' => 'Dirección IP o nombre de usuario:',
 'sp-contributions-toponly' => 'Solo mostrar últimas ediciones de página',
+'sp-contributions-newonly' => 'Mostrar solo ediciones que son creaciones de páginas',
 'sp-contributions-submit' => 'Buscar',
 
 # What links here
@@ -4313,6 +4329,4 @@ También expande las funciones sintácticas como <code><nowiki>{{</nowiki>#langu
 'expand_templates_generate_rawhtml' => 'Mostrar HTML en crudo',
 'expand_templates_preview' => 'Previsualización',
 
-# Unknown messages
-'uploadinvalidxml' => 'No se pudo analizar el XML del archivo cargado.',
 );
index 0b96ddd..e7bf3ae 100644 (file)
@@ -18,6 +18,7 @@
  * @author KaidoKikkas
  * @author KalmerE.
  * @author Ker
+ * @author Kristian.kankainen
  * @author Kyng
  * @author Morel
  * @author Nemo bis
@@ -448,7 +449,7 @@ $messages = array(
 'morenotlisted' => 'See loend pole täielik.',
 'mypage' => 'Minu lehekülg',
 'mytalk' => 'Arutelu',
-'anontalk' => 'Selle IP-aadressi artuelu',
+'anontalk' => 'Selle IP-aadressi arutelu',
 'navigation' => 'Navigeerimine',
 'and' => '&#32;ja',
 
@@ -1854,6 +1855,7 @@ Enne kui jätkad uuesti üleslaadimisega, peaksid paluma olukorda hinnata kellel
 'php-uploaddisabledtext' => 'Failide üleslaadmine on PHP seadetes keelatud.
 Palun vaata <code>file_uploads</code> sätet.',
 'uploadscripted' => 'See fail sisaldab HTML- või skriptikoodi, mida veebilehitseja võib valesti kuvada.',
+'uploadinvalidxml' => 'Üleslaaditud failis sisalduvat XMLi ei õnnestunud liigendada.',
 'uploadvirus' => 'Fail sisaldab viirust! Täpsemalt: $1',
 'uploadjava' => 'See fail on ZIP-fail, milles on Java .class-fail.
 Java failide üleslaadimine on keelatud, kuna nende kaudu võidaks turvapiiranguist mööda minna.',
@@ -4176,6 +4178,4 @@ Samuti hõrendab see parserifunktsioonid nagu
 'expand_templates_generate_rawhtml' => 'Näita toor-HTMLi',
 'expand_templates_preview' => 'Eelvaade',
 
-# Unknown messages
-'uploadinvalidxml' => 'Üleslaaditud failis sisalduvat XMLi ei õnnestunud liigendada.',
 );
index f717947..3c786cb 100644 (file)
@@ -862,8 +862,8 @@ Hau batzuetan gertatzen da buggyan oinarritutako web proxy zerbitzua erabiltzean
 'edit_form_incomplete' => "'''Aldaketa formularioaren atal batzuk ez dira iritsi zerbitzarira; bi aldiz ziurtatu zure aldaketak osorik daudela eta berriro saiatu.'''",
 'editing' => '«$1» aldatzen',
 'creating' => '$1 sortzen',
-'editingsection' => '$1 aldatzen (atala)',
-'editingcomment' => '$1 aldatzen (atal berria)',
+'editingsection' => '«$1» aldatzen (atala)',
+'editingcomment' => '«$1» aldatzen (atal berria)',
 'editconflict' => 'Aldaketa gatazka: $1',
 'explainconflict' => "Zu orrialdea aldatzen hasi ondoren beste norbaitek ere aldaketak egin ditu.
 Goiko testu koadroan ikus daiteke orrialdeak uneotan duen edukia.
index e3e987e..a4bce8e 100644 (file)
@@ -1191,7 +1191,7 @@ $2
 'noarticletext-nopermission' => 'این صفحه هم‌اکنون متنی ندارد.
 شما می‌توانید در دیگر صفحه‌ها [[Special:Search/{{PAGENAME}}|این عنوان را جستجو کنید]]،
 یا <span class="plainlinks">[{{fullurl:{{#Special:Log}}|page={{FULLPAGENAMEE}}}} سیاهه‌های مرتبط را بگردید]</span> ولی شما اجازه ایجاد این صفحه را ندارید.',
-'missing-revision' => 'ویرایش #$1 از صفحهٔ "{{PAGENAME}}" موجود نیست.
+'missing-revision' => 'ویرایش #$1 از صفحهٔ «{{PAGENAME}}» موجود نیست.
 
 معمولاً در اثر پیوند به تاریخچهٔ به‌روز نشدهٔ صفحهٔ حذف شده است.
 می‌توانید جزئیات بیشتر را در [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} سیاههٔ حذف] بیابید.',
@@ -1898,11 +1898,23 @@ $1",
 'rcnotefrom' => 'در زیر تغییرات از تاریخ <b>$2</b> آمده‌اند (تا <b>$1</b> مورد نشان داده می‌شود).',
 'rclistfrom' => 'نمایش تغییرات جدید با شروع از $1',
 'rcshowhideminor' => '$1 ویرایش‌های جزئی',
+'rcshowhideminor-show' => 'نمایش',
+'rcshowhideminor-hide' => 'پنهان‌ کردن',
 'rcshowhidebots' => '$1 ربات‌ها',
+'rcshowhidebots-show' => 'نمایش',
+'rcshowhidebots-hide' => 'پنهان کردن',
 'rcshowhideliu' => 'کاربران نسخهٔ $1 ثبت‌نام‌ کردند',
+'rcshowhideliu-show' => 'نمایش',
+'rcshowhideliu-hide' => 'پنهان کردن',
 'rcshowhideanons' => '$1 کاربران ناشناس',
+'rcshowhideanons-show' => 'نمایش',
+'rcshowhideanons-hide' => 'پنهان کردن',
 'rcshowhidepatr' => '$1 ویرایش‌های گشت‌خورده',
+'rcshowhidepatr-show' => 'نمایش',
+'rcshowhidepatr-hide' => 'پنهان کردن',
 'rcshowhidemine' => '$1 ویرایش‌های من',
+'rcshowhidemine-show' => 'نمایش',
+'rcshowhidemine-hide' => 'پنهان کردن',
 'rclinks' => 'نمایش آخرین $1 تغییر در $2 روز اخیر<br />$3',
 'diff' => 'تفاوت',
 'hist' => 'تاریخچه',
@@ -2037,6 +2049,8 @@ $1",
 'php-uploaddisabledtext' => 'بارگذاری پرونده‌های پی‌اچ‌پی غیرفعال است.
 لطفاً تنظیمات file_uploads را بررسی کنید.',
 'uploadscripted' => 'این صفحه حاوی کد اچ‌تی‌ام‌ال یا اسکریپتی است که ممکن است به‌نادرست توسط مرورگر وب تفسیر شود.',
+'uploadscriptednamespace' => "این پوشه اس‌وی‌جی شامل فضای نام غیرقانونی '$1' است",
+'uploadinvalidxml' => 'XML در پروندهٔ بارگذاری‌شده نمی‌تواند تجزیه شود.',
 'uploadvirus' => 'این پرونده ویروس دارد!
 جزئیات : $1',
 'uploadjava' => 'این پرونده یک پرونده زیپ است که حاوی پرونده‌ای از نوع ‎‎.class جاوا است.
@@ -2870,6 +2884,7 @@ $1',
 'sp-contributions-search' => 'جستجوی مشارکت‌ها',
 'sp-contributions-username' => 'نشانی آی‌پی یا نام کاربری:',
 'sp-contributions-toponly' => 'فقط ویرایش‌هایی که آخرین نسخه‌اند نمایش داده شود',
+'sp-contributions-newonly' => 'فقط نمایش ویرایش‌هایی که تولید‌های صفحه هستند',
 'sp-contributions-submit' => 'جستجو',
 
 # What links here
@@ -4462,6 +4477,4 @@ $5
 'expand_templates_generate_rawhtml' => 'نمایش اچ‌تی‌ام‌ال خام',
 'expand_templates_preview' => 'پیش‌نمایش',
 
-# Unknown messages
-'uploadinvalidxml' => 'XML در پروندهٔ بارگذاری‌شده نمی‌تواند تجزیه شود.',
 );
index 88a2d18..ef46af2 100644 (file)
@@ -1727,11 +1727,23 @@ Tämä tieto on julkinen.',
 'rcnotefrom' => 'Alla on muutokset <b>$2</b> lähtien. Enintään <b>$1</b> merkintää näytetään.',
 'rclistfrom' => 'Näytä uudet muutokset $1 alkaen',
 'rcshowhideminor' => '$1 pienet muutokset',
+'rcshowhideminor-show' => 'Näytä',
+'rcshowhideminor-hide' => 'Piilota',
 'rcshowhidebots' => '$1 botit',
+'rcshowhidebots-show' => 'Näytä',
+'rcshowhidebots-hide' => 'Piilota',
 'rcshowhideliu' => '$1 rekisteröityneet käyttäjät',
+'rcshowhideliu-show' => 'Näytä',
+'rcshowhideliu-hide' => 'Piilota',
 'rcshowhideanons' => '$1 anonyymit käyttäjät',
+'rcshowhideanons-show' => 'Näytä',
+'rcshowhideanons-hide' => 'Piilota',
 'rcshowhidepatr' => '$1 tarkastetut muutokset',
+'rcshowhidepatr-show' => 'Näytä',
+'rcshowhidepatr-hide' => 'Piilota',
 'rcshowhidemine' => '$1 omat muutokset',
+'rcshowhidemine-show' => 'Näytä',
+'rcshowhidemine-hide' => 'Piilota',
 'rclinks' => 'Näytä $1 tuoretta muutosta viimeisten $2 päivän ajalta.<br />$3',
 'diff' => 'ero',
 'hist' => 'historia',
@@ -1850,6 +1862,8 @@ Sinun on syytä pyytää jotakuta häivytettyjen tietojen näkemiseen oikeutettu
 'uploaddisabledtext' => 'Tiedostojen tallennus on poistettu käytöstä.',
 'php-uploaddisabledtext' => 'PHP:n tiedostojen lähetys ei ole käytössä. Tarkista asetukset kohdasta file_uploads.',
 'uploadscripted' => 'Tämä tiedosto sisältää HTML-koodia tai skriptejä, jotka selain saattaa virheellisesti suorittaa.',
+'uploadscriptednamespace' => 'Tämä SVG-tiedosto sisältää nimiavaruuden ”$1”, joka ei ole sallittu.',
+'uploadinvalidxml' => 'Ladatun tiedoston XML-koodia ei voitu jäsentää kunnolla.',
 'uploadvirus' => 'Tiedosto sisältää viruksen. Tarkemmat tiedot: $1',
 'uploadjava' => 'Tämä tiedosto on ZIP-tiedosto, joka sisältää Java .class-tiedoston.
 Java-tiedostojen tallentaminen ei ole sallittua, sillä ne saattavat aiheuttaa tietoturvariskejä.',
@@ -2664,6 +2678,7 @@ Alla on viimeisin estolokin tapahtuma:',
 'sp-contributions-search' => 'Etsi muokkauksia',
 'sp-contributions-username' => 'IP-osoite tai käyttäjätunnus',
 'sp-contributions-toponly' => 'Näytä vain muokkaukset, jotka ovat viimeisimpiä versioita',
+'sp-contributions-newonly' => 'Näytä vain muokkaukset, joilla on luotu sivu',
 'sp-contributions-submit' => 'Hae',
 
 # What links here
@@ -4185,6 +4200,4 @@ Käytännössä se laajentaa melkein kaiken, joka on kaksoisaaltosulkeiden sisä
 'expand_templates_generate_rawhtml' => 'Näytä raaka HTML',
 'expand_templates_preview' => 'Esikatselu',
 
-# Unknown messages
-'uploadinvalidxml' => 'Ladatun tiedoston XML-koodia ei voitu jäsentää kunnolla.',
 );
index a90a14a..a0d7211 100644 (file)
@@ -70,6 +70,7 @@
  * @author McDutchie
  * @author Meithal
  * @author Metroitendo
+ * @author Momo50WM
  * @author Moyg
  * @author Nicolas NALLET
  * @author Nicolas Raoul
@@ -420,27 +421,27 @@ $separatorTransformTable = array( ',' => "\xc2\xa0", '.' => ',' );
 
 $messages = array(
 # User preference toggles
-'tog-underline' => 'Souligner les liens :',
+'tog-underline' => 'Lien hypertexte:',
 'tog-hideminor' => 'Masquer les modifications mineures dans les changements récents',
-'tog-hidepatrolled' => 'Masquer les modifications surveillées dans les modifications récentes',
+'tog-hidepatrolled' => 'Masquer les modifications surveillées dans les changements récents',
 'tog-newpageshidepatrolled' => 'Masquer les pages surveillées dans la liste des nouvelles pages',
-'tog-extendwatchlist' => 'Étendre la liste de suivi pour afficher toutes les modifications et pas uniquement les plus récentes',
+'tog-extendwatchlist' => 'Développer la liste de suivi pour voir tous les changements, non seulement le plus récent',
 'tog-usenewrc' => 'Grouper les changements par page dans les modifications récentes et la liste de suivi (nécessite JavaScript)',
 'tog-numberheadings' => 'Numéroter automatiquement les titres de section',
-'tog-showtoolbar' => "Montrer la barre d'outils de modification (nécessite JavaScript)",
+'tog-showtoolbar' => "Afficher la barre d'outils de modification (nécessite JavaScript)",
 'tog-editondblclick' => 'Modifier des pages sur double-clic (nécessite JavaScript)',
 'tog-editsectiononrightclick' => 'Activer la modification de sections par clic droit sur les titres (nécessite JavaScript)',
-'tog-rememberpassword' => 'Se souvenir de mon identification avec ce navigateur (au maximum $1 {{PLURAL:$1|jour|jours}})',
+'tog-rememberpassword' => 'Me reconnecter automatiquement lors des prochaines visites avec ce navigateur (au maximum $1&nbsp;{{PLURAL:$1|jour|jours}})',
 'tog-watchcreations' => "Ajouter les pages que je crée et les fichiers que j'importe à ma liste de suivi",
 'tog-watchdefault' => 'Ajouter les pages et les fichiers que je modifie à ma liste de suivi',
-'tog-watchmoves' => 'Ajouter les pages et les fichiers que je renomme à ma liste de suivi',
+'tog-watchmoves' => 'Ajouter les pages et les fichiers que je déplace à ma liste de suivi',
 'tog-watchdeletion' => 'Ajouter les pages et les fichiers que je supprime à ma liste de suivi',
-'tog-minordefault' => 'Marquer mes modifications comme mineures par défaut',
+'tog-minordefault' => 'Marquer toutes les modifications mineures par défaut',
 'tog-previewontop' => 'Afficher la prévisualisation au-dessus de la zone de modification',
 'tog-previewonfirst' => 'Afficher la prévisualisation lors de la première modification',
 'tog-enotifwatchlistpages' => "M'avertir par courriel lorsqu'une page ou un fichier de ma liste de suivi est modifiée",
 'tog-enotifusertalkpages' => "M'avertir par courriel si ma page de discussion est modifiée",
-'tog-enotifminoredits' => "M'avertir par courriel pour les modifications mineures de pages ou de fichiers également",
+'tog-enotifminoredits' => "M'avertir par courriel également lors des modifications mineures de pages ou de fichiers",
 'tog-enotifrevealaddr' => 'Afficher mon adresse de courriel dans les courriels de notification',
 'tog-shownumberswatching' => "Afficher le nombre d'utilisateurs qui suivent la page",
 'tog-oldsig' => 'Signature existante :',
@@ -463,30 +464,30 @@ $messages = array(
 
 'underline-always' => 'Toujours',
 'underline-never' => 'Jamais',
-'underline-default' => 'Valeur par défaut du navigateur ou du thème',
+'underline-default' => 'Navigateur ou thème par défaut',
 
 # Font style option in Special:Preferences
 'editfont-style' => 'Style de police de la zone de modification :',
-'editfont-default' => 'Police par défaut du navigateur',
-'editfont-monospace' => 'Police à chasse fixe',
-'editfont-sansserif' => 'Police sans empattement',
-'editfont-serif' => 'Police avec empattement',
+'editfont-default' => 'Navigateur par défaut',
+'editfont-monospace' => 'Police Monospaced',
+'editfont-sansserif' => 'Police Sans-serif',
+'editfont-serif' => 'Police Serif',
 
 # Dates
-'sunday' => 'dimanche',
-'monday' => 'lundi',
-'tuesday' => 'mardi',
-'wednesday' => 'mercredi',
-'thursday' => 'jeudi',
-'friday' => 'vendredi',
-'saturday' => 'samedi',
-'sun' => 'dim',
-'mon' => 'lun',
-'tue' => 'mar',
-'wed' => 'mer',
-'thu' => 'jeu',
-'fri' => 'ven',
-'sat' => 'sam',
+'sunday' => 'Dimanche',
+'monday' => 'Lundi',
+'tuesday' => 'Mardi',
+'wednesday' => 'Mercredi',
+'thursday' => 'Jeudi',
+'friday' => 'Vendredi',
+'saturday' => 'Samedi',
+'sun' => 'Dim.',
+'mon' => 'Lun.',
+'tue' => 'Mar.',
+'wed' => 'Mer.',
+'thu' => 'Jeu.',
+'fri' => 'Ven.',
+'sat' => 'Sam.',
 'january' => 'janvier',
 'february' => 'février',
 'march' => 'mars',
@@ -615,7 +616,7 @@ $messages = array(
 'delete' => 'Supprimer',
 'deletethispage' => 'Supprimer cette page',
 'undeletethispage' => 'Annuler la suppression de cette page',
-'undelete_short' => 'Restaurer $1 modification{{PLURAL:$1||s}}',
+'undelete_short' => 'Restaurer {{PLURAL:$1|une modification|$1 modifications}}',
 'viewdeleted_short' => 'Voir {{PLURAL:$1|une modification supprimée|$1 modifications supprimées}}',
 'protect' => 'Protéger',
 'protect_change' => 'modifier',
@@ -632,30 +633,30 @@ $messages = array(
 'talk' => 'Discussion',
 'views' => 'Affichages',
 'toolbox' => 'Outils',
-'userpage' => 'Page utilisateur',
-'projectpage' => 'Page méta',
+'userpage' => 'Voir la page utilisateur',
+'projectpage' => 'Voir la page du projet',
 'imagepage' => 'Voir la page du fichier',
 'mediawikipage' => 'Voir la page du message',
 'templatepage' => 'Voir la page du modèle',
 'viewhelppage' => "Voir la page d'aide",
 'categorypage' => 'Voir la page de catégorie',
-'viewtalkpage' => 'Page de discussion',
+'viewtalkpage' => 'Voir la page de discussion',
 'otherlanguages' => 'Autres langues',
 'redirectedfrom' => '(Redirigé depuis $1)',
 'redirectpagesub' => 'Page de redirection',
 'lastmodifiedat' => 'Dernière modification de cette page le $1 à $2.<br />',
-'viewcount' => 'Cette page a été consultée $1 fois.',
+'viewcount' => 'Cette page a été consultée {{PLURAL:$1|une fois|$1 fois}}.',
 'protectedpage' => 'Page protégée',
 'jumpto' => 'Aller à :',
-'jumptonavigation' => 'Navigation',
+'jumptonavigation' => 'navigation',
 'jumptosearch' => 'rechercher',
 'view-pool-error' => "Désolé, les serveurs sont surchargés en ce moment.
 Trop d'utilisateurs cherchent à consulter cette page.
 Veuillez attendre un moment avant de retenter l'accès à cette page.
 
 $1",
-'pool-timeout' => "Délai dépassé durant l'attente du verrou",
-'pool-queuefull' => 'La file de travail est pleine',
+'pool-timeout' => "Délai d'attente dépassé",
+'pool-queuefull' => "La file d'attente est pleine",
 'pool-errorunknown' => 'Erreur inconnue',
 
 # All link text and link target definitions of links into project namespace that get used by other message strings, with the exception of user group pages (see grouppage).
@@ -679,7 +680,7 @@ $1",
 
 'badaccess' => 'Erreur de permissions',
 'badaccess-group0' => 'Vous n’avez pas les droits suffisants pour réaliser l’action demandée.',
-'badaccess-groups' => 'L’action que vous essayez de réaliser n’est permise qu’aux utilisateurs {{PLURAL:$2|du groupe|des groupes}} : $1.',
+'badaccess-groups' => "L’action que vous essayez de réaliser n’est permise qu’aux utilisateurs {{PLURAL:$2|du groupe|d'un des groupes}} : $1.",
 
 'versionrequired' => 'Version $1 de MediaWiki nécessaire',
 'versionrequiredtext' => 'La version $1 de MediaWiki est nécessaire pour utiliser cette page. Consultez [[Special:Version|la page des versions]]',
@@ -991,7 +992,7 @@ Pour terminer la connexion, vous devez fournir un nouveau mot de passe ici :',
 'resetpass-temp-password' => 'Mot de passe temporaire :',
 'resetpass-abort-generic' => 'La modification du mot de passe a été annulée par une extension.',
 'resetpass-expired' => 'Votre mot de passe a expiré. Veuillez en fournir un nouveau pour vous connecter.',
-'resetpass-expired-soft' => 'Votre mot de passe a expiré, et doit être réinitialisé. Veuillez en choisir un nouveau maintenant, ou cliquer sur annuler pour le faire plus tard.',
+'resetpass-expired-soft' => 'Votre mot de passe a expiré, et doit être réinitialisé. Veuillez en choisir un nouveau maintenant, ou cliquer sur « {{int:resetpass-submit-cancel}} » pour le faire plus tard.',
 
 # Special:PasswordReset
 'passwordreset' => 'Remise à zéro du mot de passe',
@@ -1286,7 +1287,7 @@ Il devrait y avoir moins de $2 appel{{PLURAL:$2||s}}, alors qu'il y en a mainten
 'undo-success' => 'Cette modification va être défaite. Veuillez vérifier les modifications ci-dessous, puis publier si c’est bien ce que vous voulez faire.',
 'undo-failure' => 'Cette modification ne peut pas être défaite : cela entrerait en conflit avec les modifications intermédiaires.',
 'undo-norev' => 'La modification n’a pas pu être défaite parce qu’elle est inexistante ou qu’elle a été supprimée.',
-'undo-nochange' => 'Il semble que la modification aie déjà été annulée.',
+'undo-nochange' => 'Il semblerait que la modification ait déjà été annulée.',
 'undo-summary' => 'Annulation des modifications $1 de [[Special:Contributions/$2|$2]] ([[User talk:$2|discussion]])',
 'undo-summary-username-hidden' => 'Annuler la révision $1 par un utilisateur masqué',
 
@@ -1831,14 +1832,26 @@ Cette information sera publique.',
 'recentchanges-legend-heading' => "'''Légende :'''",
 'recentchanges-legend-newpage' => '(voir aussi la [[Special:NewPages|liste des nouvelles pages]]).',
 'recentchanges-legend-plusminus' => "(''±123'')",
-'rcnotefrom' => "Voici les modifications effectuées depuis le '''$2''' ('''$1''' au maximum).",
+'rcnotefrom' => 'Ci-dessous les modifications effectuées depuis le <strong>$2</strong> (jusqu’à <strong>$1</strong> affichés).',
 'rclistfrom' => 'Afficher les nouvelles modifications depuis le $1.',
 'rcshowhideminor' => '$1 les modifications mineures',
+'rcshowhideminor-show' => 'Afficher',
+'rcshowhideminor-hide' => 'Masquer',
 'rcshowhidebots' => '$1 les robots',
+'rcshowhidebots-show' => 'Afficher',
+'rcshowhidebots-hide' => 'Masquer',
 'rcshowhideliu' => '$1 les utilisateurs enregistrés',
+'rcshowhideliu-show' => 'Afficher',
+'rcshowhideliu-hide' => 'Masquer',
 'rcshowhideanons' => '$1 les utilisateurs anonymes',
+'rcshowhideanons-show' => 'Afficher',
+'rcshowhideanons-hide' => 'Masquer',
 'rcshowhidepatr' => '$1 les modifications surveillées',
+'rcshowhidepatr-show' => 'Afficher',
+'rcshowhidepatr-hide' => 'Masquer',
 'rcshowhidemine' => '$1 mes modifications',
+'rcshowhidemine-show' => 'Afficher',
+'rcshowhidemine-hide' => 'Masquer',
 'rclinks' => 'Afficher les $1 dernières modifications effectuées au cours des $2 derniers jours<br />$3.',
 'diff' => 'diff',
 'hist' => 'hist',
@@ -1965,6 +1978,8 @@ Vous devriez demander à quelqu'un la possibilité de vérifier le journal de ce
 'uploaddisabledtext' => 'L’import de fichiers est désactivé sur ce wiki.',
 'php-uploaddisabledtext' => "L'import de fichiers a été désactivé dans PHP. Vérifiez l'option de configuration file_uploads.",
 'uploadscripted' => 'Ce fichier contient du code HTML ou un script qui pourrait être interprété de façon incorrecte par un navigateur web.',
+'uploadscriptednamespace' => "Ce fichier SVG contient un espace de noms '$1' non autorisé.",
+'uploadinvalidxml' => 'Le XML dans le fichier importé n’a pas pu être analysé.',
 'uploadvirus' => 'Ce fichier contient un virus ! Pour plus de détails, consultez : $1',
 'uploadjava' => 'C’est un fichier ZIP qui contient un fichier Java .class.
 Le téléchargement de fichiers Java n’est pas autorisé, car ils peuvent contourner certaines restrictions de sécurité.',
@@ -2268,7 +2283,7 @@ N’oubliez pas de vérifier s’il n’y a pas d’autres liens vers les modèl
 'pageswithprop-legend' => 'Pages avec une propriété de page',
 'pageswithprop-text' => 'Cette page liste les pages qui utilisent une propriété de page particulière.',
 'pageswithprop-prop' => 'Nom de la propriété :',
-'pageswithprop-submit' => 'Aller',
+'pageswithprop-submit' => 'Lister',
 'pageswithprop-prophidden-long' => 'valeur de propriété de texte long masquée ($1)',
 'pageswithprop-prophidden-binary' => 'valeur de propriété binaire masquée ($1)',
 
@@ -2336,6 +2351,7 @@ Les entrées <del>barrées</del> ont été résolues.',
 'deadendpagestext' => "Les pages suivantes ne contiennent aucun lien vers d'autres pages du wiki.",
 'protectedpages' => 'Pages protégées',
 'protectedpages-indef' => 'Uniquement les protections permanentes',
+'protectedpages-summary' => 'Cette page liste les pages existantes actuellement protégées. Pour une liste des titres protégés depuis leur création, voir [[{{#special:ProtectedTitles}}]].',
 'protectedpages-cascade' => 'Uniquement les protections en cascade',
 'protectedpages-noredirect' => 'Masquer les redirections',
 'protectedpagesempty' => "Aucune page n'est protégée de cette façon.",
@@ -2348,6 +2364,7 @@ Les entrées <del>barrées</del> ont été résolues.',
 'protectedpages-unknown-timestamp' => 'Inconnu',
 'protectedpages-unknown-performer' => 'Utilisateur inconnu',
 'protectedtitles' => 'Titres protégés',
+'protectedtitles-summary' => 'Cette page liste les titres actuellement protégés depuis leur création. Pour une liste des pages  protégées existantes, voir [[{{#special:ProtectedPages}}]].',
 'protectedtitlesempty' => "Aucun titre n'est actuellement protégé avec ces paramètres.",
 'listusers' => 'Liste des utilisateurs',
 'listusers-editsonly' => 'Ne montrer que les utilisateurs ayant au moins une contribution',
@@ -2805,6 +2822,7 @@ La dernière entrée du journal des blocages est indiquée ci-dessous à titre d
 'sp-contributions-search' => 'Rechercher les contributions',
 'sp-contributions-username' => "Adresse IP ou nom d'utilisateur :",
 'sp-contributions-toponly' => 'Ne montrer que les contributions qui sont les dernières des articles',
+'sp-contributions-newonly' => 'Afficher uniquement les modifications qui sont des créations de page',
 'sp-contributions-submit' => 'Rechercher',
 
 # What links here
@@ -4470,6 +4488,4 @@ En fait, elle réalise l'expansion de pratiquement tout ce qui est encadré par
 'expand_templates_generate_rawhtml' => 'Afficher le HTML brut',
 'expand_templates_preview' => 'Aperçu du rendu',
 
-# Unknown messages
-'uploadinvalidxml' => 'Le XML dans le fichier importé n’a pas pu être analysé.',
 );
index 6aa99a5..f8e60e6 100644 (file)
@@ -1555,6 +1555,7 @@ Dü skulst hoker fraage, di ferbürgen nöömer uunluke koon, am tu besnaakin, w
 'php-uploaddisabledtext' => 'Det huuchschüüren faan datein as uun PHP ei aktiwiaret.
 Luke di det iinstelang faan <code>file_uploads</code> uun.',
 'uploadscripted' => 'Uun detdiar datei stäänt HTML- of Scriptcode, an küd ütj fersen faan en browser ütjfeerd wurd.',
+'uploadinvalidxml' => "Det XML uun det huuchschüürd datei küd ei ''parset'' wurd.",
 'uploadvirus' => 'Uun detdiar datei as en wiirus! Details: $1',
 'uploadjava' => 'Detdiar as en ZIP-datei mä en CLASS-datei faan Java.
 Java-datein kön ei tuläät wurd, auer jo det seekerhaid uun fraag stel küd.',
@@ -3838,6 +3839,4 @@ Uk parser-funktjuunen liküs <code><nowiki>{{</nowiki>#language:…}}</code> an
 'expand_templates_generate_rawhtml' => 'Rä HTML uunwise',
 'expand_templates_preview' => 'Föörskau',
 
-# Unknown messages
-'uploadinvalidxml' => "Det XML uun det huuchschüürd datei küd ei ''parset'' wurd.",
 );
index ed3b248..e7a29a9 100644 (file)
@@ -836,6 +836,9 @@ Por favor, agarde $1 antes de probar outra vez.',
 'suspicious-userlogout' => 'Rexeitouse a súa petición de saír do sistema porque semella que a enviou un navegador roto ou a caché dun proxy.',
 'createacct-another-realname-tip' => 'O nome real é opcional.
 Se escolle dalo utilizarase para atribuír ao usuario o seu traballo.',
+'pt-login' => 'Iniciar sesión',
+'pt-createaccount' => 'Crear unha conta',
+'pt-userlogout' => 'Pechar sesión',
 
 # Email sending
 'php-mail-error-unknown' => 'Erro descoñecido na función mail() do PHP.',
@@ -1730,11 +1733,23 @@ Se escolle dalo utilizarase para atribuírlle o seu traballo.',
 'rcnotefrom' => "A continuación móstranse os cambios feitos desde o '''$3''' ás '''$4''' (móstranse '''$1''' como máximo).",
 'rclistfrom' => 'Mostrar os cambios novos desde o $1',
 'rcshowhideminor' => '$1 as edicións pequenas',
+'rcshowhideminor-show' => 'Mostrar',
+'rcshowhideminor-hide' => 'Agochar',
 'rcshowhidebots' => '$1 os bots',
+'rcshowhidebots-show' => 'Mostrar',
+'rcshowhidebots-hide' => 'Agochar',
 'rcshowhideliu' => '$1 os usuarios rexistrados',
+'rcshowhideliu-show' => 'Mostrar',
+'rcshowhideliu-hide' => 'Agochar',
 'rcshowhideanons' => '$1 os usuarios anónimos',
+'rcshowhideanons-show' => 'Mostrar',
+'rcshowhideanons-hide' => 'Agochar',
 'rcshowhidepatr' => '$1 as edicións revisadas',
+'rcshowhidepatr-show' => 'Mostrar',
+'rcshowhidepatr-hide' => 'Agochar',
 'rcshowhidemine' => '$1 as edicións propias',
+'rcshowhidemine-show' => 'Mostrar',
+'rcshowhidemine-hide' => 'Agochar',
 'rclinks' => 'Mostrar os últimos $1 cambios nos últimos $2 días.<br />$3',
 'diff' => 'dif',
 'hist' => 'hist',
@@ -1865,6 +1880,8 @@ Debería contactar con alguén capaz de ver os datos de ficheiros borrados para
 'uploaddisabledtext' => 'A carga de ficheiros está desactivada.',
 'php-uploaddisabledtext' => 'As cargas de ficheiros PHP están desactivadas. Por favor, comprobe a característica file_uploads.',
 'uploadscripted' => 'Este ficheiro contén código HTML ou script que pode producir erros ao ser interpretado polo navegador.',
+'uploadscriptednamespace' => "Este ficheiro SVG contén un espazo de nome non permitido '$1'",
+'uploadinvalidxml' => 'Non se puido analizar o XML do ficheiro cargado.',
 'uploadvirus' => 'O ficheiro contén un virus! Detalles: $1',
 'uploadjava' => 'O ficheiro é un ZIP que contén un ficheiro .class de Java.
 Non están permitidas as cargas de ficheiros Java, dado que poden causar restricións de seguridade.',
@@ -2708,6 +2725,7 @@ Velaquí está a última entrada do rexistro de bloqueos, por se quere consultal
 'sp-contributions-search' => 'Busca de contribucións',
 'sp-contributions-username' => 'Enderezo IP ou nome de usuario:',
 'sp-contributions-toponly' => 'Mostrar só as últimas revisións',
+'sp-contributions-newonly' => 'Mostrar só edicións que son creacións de páxinas',
 'sp-contributions-submit' => 'Procurar',
 
 # What links here
@@ -4254,6 +4272,4 @@ De feito, expande case calquera cousa entre dúas chaves.',
 'expand_templates_generate_rawhtml' => 'Mostrar o HTML en bruto',
 'expand_templates_preview' => 'Vista previa',
 
-# Unknown messages
-'uploadinvalidxml' => 'Non se puido analizar o XML do ficheiro cargado.',
 );
index 84a3e21..ffbcb68 100644 (file)
@@ -1629,6 +1629,7 @@ Wänn Du die Datei einewäg wit uffelade, gang bitte zruck un ändere dr Name.
 'uploaddisabledtext' => 'S Uffelade vu Dateie isch deaktiviert.',
 'php-uploaddisabledtext' => 'S Uffelade vu PHP-Dateie isch deaktiviert wore. Bitte iberprief d file_uploads-Yystellig.',
 'uploadscripted' => 'In däre Datei git s HTML- oder Scriptcode, wu fälschligerwyys vun eme Webbrowser usgfiert chennt were.',
+'uploadinvalidxml' => 'S XML in dr uffegladene Datei het nit chenne parst wäre.',
 'uploadvirus' => 'In däre Datei het s e Virus! Detail: $1',
 'uploadjava' => 'Des isch e ZIP-Datei, wu s e CLASS-Datei vu Java din het.
 S Uffelade vu Java-Dateien isch nit gstattet, wel si s Umgoh vu Sicherheitsyyschränkige chennte megli mache.',
@@ -3799,6 +3800,4 @@ Sunscht chasch au s eifach Formular unte nutze. Dyy Kommentar wird, zämme mit D
 'expand_templates_generate_xml' => 'Zeig XML-Parser-Baum',
 'expand_templates_preview' => 'Vorschou',
 
-# Unknown messages
-'uploadinvalidxml' => 'S XML in dr uffegladene Datei het nit chenne parst wäre.',
 );
index 29c6d92..c31eed9 100644 (file)
@@ -89,30 +89,55 @@ $magicWords = array(
 $messages = array(
 # User preference toggles
 'tog-underline' => 'Kahalalo i nā loulou:',
-'tog-hideminor' => 'E hūnā i nā ho‘opololei iki ma nā loli hou',
-'tog-editondblclick' => 'Ho‘opololei i nā ‘ao‘ao ma ke kōmi pālua (JavaScript)',
-'tog-rememberpassword' => 'Hoʻomanaʻo iaʻu ma kēia lolo uila (no ka palena nui o $1 {{PLURAL:$1|lā|mau lā}})',
-'tog-watchcreations' => 'Ho‘ohui i nā ‘ao‘ao i hana ai au i ka‘u papa nānā pono',
-'tog-watchdefault' => 'Ho‘ohui i nā ‘ao‘ao i ho‘opololei ai au i ka‘u papa nānā pono',
-'tog-watchmoves' => 'Ho‘ohui i nā ‘ao‘ao i ne‘e ai au i ka‘u papa nānā pono',
-'tog-watchdeletion' => 'Ho‘ohui i nā ‘ao‘ao i kāpae ai au i ka‘u papa nānā pono',
-'tog-previewontop' => 'Hō‘ike i ka nāmua mamua o ke kau ho‘opololei',
-'tog-previewonfirst' => 'Hō‘ike i ka nāmua ma ka ho‘ololi mua',
-'tog-enotifwatchlistpages' => 'Ke loli kekahi ‘ao‘ao ma ka‘u papa nānā pono, leka uila ia‘u',
-'tog-enotifusertalkpages' => 'Ke loli ka‘u ʻaoʻao kūkākūkā, leka uila ia‘u',
-'tog-enotifminoredits' => 'No nā ho‘opololei ‘ana, leka uila ia‘u',
-'tog-enotifrevealaddr' => 'Hō‘ike i ko‘u leka uila ma nā leka uila hō‘ike',
-'tog-shownumberswatching' => 'Hō‘ike i ka heluna o nā mea ho‘ohana e nānā ai',
-'tog-fancysig' => 'Nā kākau inoa kūlohelohe (‘a‘ole me ka loulou hana nona iho)',
-'tog-forceeditsummary' => 'Ke kāhuakomo au i kekahi ho‘ulu‘ulu mana‘o ‘ole, ha‘i mai iaʻu',
-'tog-watchlisthideown' => 'Hūnā i ko‘u mau ho‘ololi ma ka papa nānā pono',
-'tog-watchlisthidebots' => 'Hūnā i nā ho‘opololei ‘ana o nā lopako mai ka papa nānā pono',
-'tog-watchlisthideminor' => 'E hūnā i nā ho‘ololi iki ma ka papa nānā pono',
-'tog-ccmeonemails' => 'Hā‘awi mai i nā kope o nā leka uila i hā‘awi ai au i kekahi mau mea ho‘ohana.',
-'tog-showhiddencats' => 'Hō‘ike i nā mahele huna',
-
-'underline-always' => 'Mau',
+'tog-hideminor' => 'E hoʻohūnā i nā ho‘opololei iki ma nā loli hou',
+'tog-hidepatrolled' => 'E hoʻohūnā i nā loli kiaʻi kaʻahele i loko o nā lolina hanawale',
+'tog-newpageshidepatrolled' => 'E hoʻohūnā i nā ʻaoʻao kiaʻi kaʻahele mai ka papahelu ʻaoʻao hou',
+'tog-extendwatchlist' => 'E hoʻākea i ka papa nānā pono no ka hōʻike ʻana i nā loli apau, ʻaʻole nā mea hanawale wale nō',
+'tog-usenewrc' => 'Nā lolina hui mao ka ʻaoʻao ma loko o lolina hanawale a me ka papa nānā pono',
+'tog-numberheadings' => 'E hikahelu i nā poʻo',
+'tog-showtoolbar' => 'E hōʻike i ka pahu hāmeʻa hoʻololi',
+'tog-editondblclick' => 'E ho‘ololi i nā ‘ao‘ao me ke kōmi pālua',
+'tog-editsectiononrightclick' => 'E hoʻokuʻu i ka hoʻololi mahele mao ka paʻina ʻākau ma nā poʻoinoa māhele',
+'tog-rememberpassword' => 'E hoʻomanaʻo iaʻu ma kēia lolo uila (no ka palena nui o $1 {{PLURAL:$1|lā|mau lā}})',
+'tog-watchcreations' => 'E ho‘ohui i nā ‘ao‘ao aʻu i hana ai a me nā faila aʻu i hoʻouka ai i ka‘u papa nānā pono',
+'tog-watchdefault' => 'E ho‘ohui i nā ‘ao‘ao a me nā faila aʻu e hoʻololi ai i ka‘u papa nānā pono',
+'tog-watchmoves' => 'E ho‘ohui i nā ‘ao‘ao a me nā faila aʻu e ne‘e ai i ka‘u papa nānā pono',
+'tog-watchdeletion' => 'E ho‘ohui i nā ‘ao‘ao a me nā faila aʻu e holoi ai i ka‘u papa nānā pono',
+'tog-minordefault' => 'E kaha i nā loli apau i ka loli liʻi mao ka paʻamau',
+'tog-previewontop' => 'E hō‘ike i ka nāmua mamua o ka pahu hoʻololi',
+'tog-previewonfirst' => 'E hō‘ike i ka nāmua ma ka ho‘ololi mua',
+'tog-enotifwatchlistpages' => 'E leka uila iaʻu i ka loli ʻana o kekahi faila aiʻole kekahi ʻaoʻao ma kaʻu papa nānā pono',
+'tog-enotifusertalkpages' => 'E leka uila iaʻu i ka loli ʻana o kaʻu ʻaoʻao kūkākūkā',
+'tog-enotifminoredits' => 'E leka uila iaʻu no nā loli liʻi o nā ʻaoʻao a me nā faila',
+'tog-enotifrevealaddr' => 'E hō‘ike i ko‘u leka uila ma nā leka uila hō‘ike',
+'tog-shownumberswatching' => 'E hō‘ike i ka helu o nā mea ho‘ohana e nānā nei',
+'tog-oldsig' => 'Pūlima hananei:',
+'tog-fancysig' => 'E hana i ka pūlima me he wikitext (me ʻole i ka loulou hanawale)',
+'tog-uselivepreview' => 'E hana i ka nāmua ʻānō (hoʻokolohua)',
+'tog-forceeditsummary' => 'E kono iaʻu i ka hoʻokomo ʻana i kekahi hōʻuluʻulu manaʻo hoʻololi hou',
+'tog-watchlisthideown' => 'E hoʻohūnā i ko‘u mau ho‘ololi mai ka papa nānā pono',
+'tog-watchlisthidebots' => 'E hoʻohūnā i nā loli o nā lopako mai ka papa nānā pono',
+'tog-watchlisthideminor' => 'E hoʻohūnā i nā loli iki mai ka papa nānā pono',
+'tog-watchlisthideliu' => 'E hoʻohūnā i nā loli e nā mea hoʻohana ʻeʻeia mai ka papa nānā pono',
+'tog-watchlisthideanons' => 'E hoʻohūnā i nā loli e nā mea hoʻohana inoaʻole mai ka papa nānā pono',
+'tog-watchlisthidepatrolled' => 'E hoʻohūnā i nā loli kiaʻi kaʻahele mai ka papa nānā pono',
+'tog-ccmeonemails' => 'E hoʻouna mai i nā kope o nā leka uila aʻu i hāʻawi ai i kekahi mau mea hoʻohana.',
+'tog-diffonly' => 'Mai hōʻike i nā mealoko ʻaoʻao ma lolo o ka pōlamu difē',
+'tog-showhiddencats' => 'E hōʻike i nā māhele huna',
+'tog-norollbackdiff' => 'E wehe i ka pōlamu difē ma hope o ka hana hoʻimua',
+'tog-useeditwarning' => 'E aʻo mai iaʻu i kaʻu haʻalele ʻana i ka ʻaoʻao hoʻololi inā loaʻa i nā loli mālamaia ʻole',
+'tog-prefershttps' => 'E hana mau i ka hoʻokuʻi paʻa ma loko o ka ʻeʻe ʻana',
+
+'underline-always' => 'I nā manawa apau',
 'underline-never' => '‘A‘ole loa',
+'underline-default' => 'Paʻamau ʻike aiʻole pōlamu pūnaewele',
+
+# Font style option in Special:Preferences
+'editfont-style' => 'E hoʻololi i kahi ʻanohua:',
+'editfont-default' => 'Paʻamau pōlamu pūnaewele',
+'editfont-monospace' => 'Hua pukakahi',
+'editfont-sansserif' => 'Hua Sanā-selifa',
+'editfont-serif' => 'Hua Selifa',
 
 # Dates
 'sunday' => 'Lāpule',
@@ -122,13 +147,13 @@ $messages = array(
 'thursday' => 'Pō‘ahā',
 'friday' => 'Pō‘alima',
 'saturday' => 'Pō‘aono',
-'sun' => 'Lāpule',
-'mon' => 'Pōʻakahi',
-'tue' => 'Pō‘alua',
-'wed' => 'Pō‘akolu',
-'thu' => 'Pō‘ahā',
-'fri' => 'Pō‘alima',
-'sat' => 'Pō‘aono',
+'sun' => 'LP',
+'mon' => 'P1',
+'tue' => 'P2',
+'wed' => 'P3',
+'thu' => 'P4',
+'fri' => 'P5',
+'sat' => 'P6',
 'january' => 'Ianuali',
 'february' => 'Pepeluali',
 'march' => 'Malaki',
@@ -156,7 +181,7 @@ $messages = array(
 'jan' => 'Ian',
 'feb' => 'Pep',
 'mar' => 'Mal',
-'apr' => 'ʻAp',
+'apr' => 'ʻApe',
 'may' => 'Mei',
 'jun' => 'Iun',
 'jul' => 'Iul',
@@ -165,39 +190,59 @@ $messages = array(
 'oct' => 'ʻOk',
 'nov' => 'Now',
 'dec' => 'Kek',
+'january-date' => 'Ianuali $1',
+'february-date' => 'Pepeluali $1',
+'march-date' => 'Malaki $1',
+'april-date' => 'ʻApelila $1',
+'may-date' => 'Mei $1',
+'june-date' => 'Iune $1',
+'july-date' => 'Iulai $1',
+'august-date' => 'ʻAukake $1',
+'september-date' => 'Kepakemapa $1',
+'october-date' => 'ʻOkakopa $1',
+'november-date' => 'Nowemapa $1',
+'december-date' => 'Kēkēmapa $1',
 
 # Categories related messages
-'pagecategories' => '{{PLURAL:$1|Mahele|Nā mahele}}',
+'pagecategories' => '{{PLURAL:$1|Mahele|hele}}',
 'category_header' => 'Nā ʻaoʻao i loko o ka mahele "$1"',
-'subcategories' => 'Nā māhele lalo',
+'subcategories' => 'Nā māhele laloiho',
 'category-media-header' => 'Nā pāpaho i loko o ka mahele "$1"',
-'category-empty' => "''‘A‘ohe mo‘olelo a me pāpaho o kēia mahele i kēia manawa.''",
-'hidden-categories' => '{{PLURAL:$1|Mahele hūnā|Nā mahele hūnā}}',
-'hidden-category-category' => 'Nā mahele hūnā',
-'listingcontinuesabbrev' => '(ho‘omau ‘ia)',
+'category-empty' => "''ʻAʻohe moʻolelo a me pāpaho o kēia mahele i kēia manawa.''",
+'hidden-categories' => '{{PLURAL:$1|Mahele hūnā|hele hūnā}}',
+'hidden-category-category' => 'Nā māhele hūnā',
+'listingcontinuesabbrev' => '(ho‘omauia)',
 
-'about' => 'E pili ana',
-'newwindow' => '(wehe i loko o kekahi pukaaniani ʻē aʻe)',
+'about' => 'Pilina',
+'newwindow' => '(wehe i loko o kekahi pukaaniani hou)',
 'cancel' => 'Ho‘ōki',
-'moredotdotdot' => 'Hou...',
+'moredotdotdot' => 'Nā mea ʻē aʻe...',
 'mypage' => 'Ko‘u ‘ao‘ao',
 'mytalk' => 'Ka‘u kūkākūkā',
 'anontalk' => 'Ke kūkākūkā no kēia IP',
-'navigation' => 'Ka hoʻokele ʻana',
+'navigation' => 'Kelena',
 'and' => '&#32;a me',
 
 # Cologne Blue skin
 'qbfind' => 'Loa‘a',
-'qbedit' => 'E ho‘ololi',
+'qbbrowse' => 'Kele',
+'qbedit' => 'Hoʻololi',
 'qbpageoptions' => 'Kēia ‘ao‘ao',
 'qbmyoptions' => 'Ka‘u mau ‘ao‘ao',
 
 # Vector skin
-'vector-action-delete' => 'E holoi',
+'vector-action-delete' => 'Holoi',
 'vector-action-move' => 'Neʻe',
 'vector-action-protect' => 'Hoʻomalu',
-'vector-view-edit' => 'E hoʻololi',
+'vector-action-undelete' => 'Holoiʻole',
+'vector-action-unprotect' => 'E hoʻololi i ka hoʻomalu',
+'vector-view-create' => 'Haku',
+'vector-view-edit' => 'Hoʻololi',
+'vector-view-history' => 'Nānā i ka mōʻaukala',
 'vector-view-view' => 'Heluhelu',
+'vector-view-viewsource' => 'Nānā i ke kumu',
+'actions' => 'Hana',
+'namespaces' => 'Lewainoa',
 
 'errorpagetitle' => 'Hewa',
 'returnto' => 'Ho‘i iā $1.',
@@ -213,27 +258,30 @@ $messages = array(
 'permalink' => 'Ka loulou paʻa',
 'print' => 'Pa‘i',
 'view' => 'Nānā',
-'edit' => 'E ho‘ololi',
-'create' => 'Hana',
-'editthispage' => 'E ho‘opololei i kēia ‘ao‘ao',
-'create-this-page' => 'Hana i keia ‘ao‘ao',
-'delete' => 'E kāpae',
-'deletethispage' => 'E kāpae i kēia mo‘olelo',
-'undelete_short' => 'Wehe-kāpae i {{PLURAL:$1|kekahi ho‘opololei|$1 ho‘opololei}}',
-'protect' => 'E ho‘omalu',
+'edit' => 'Hoʻololi',
+'create' => 'Haku',
+'editthispage' => 'E hoʻololi i kēia ‘ao‘ao',
+'create-this-page' => 'E haku i keia ‘ao‘ao',
+'delete' => 'Holoi',
+'deletethispage' => 'E holoi i kēia mo‘olelo',
+'undeletethispage' => 'E holoiʻole i kēia ʻaoʻao',
+'undelete_short' => 'E holoiʻole i {{PLURAL:$1|hoʻokahi loli|$1 mau loli}}',
+'viewdeleted_short' => 'E ʻike i {{{{PLURAL:$1|hoʻokahi loli holoi|$1 mau loli holoi}}',
+'protect' => 'Hoʻomalu',
 'protect_change' => 'hoʻololi',
 'protectthispage' => 'E ho‘omalu i kēia ‘ao‘ao',
-'unprotect' => 'E wehe ho‘omalu',
+'unprotect' => 'E hoʻololi i ka ho‘omalu',
+'unprotectthispage' => 'E hoʻololi i ka hoʻomalu o kēia ʻaoʻao',
 'newpage' => '‘Ao‘ao hou',
 'talkpage' => 'Kūkākūkā i keia ‘ao‘ao',
 'talkpagelinktext' => 'Kūkākūkā',
 'specialpage' => '‘Ao‘ao kūikawā',
-'personaltools' => 'Nā mea hana ponoʻī',
+'personaltools' => 'Hāmeʻa ponoʻī',
 'postcomment' => 'Māhele hou',
 'talk' => 'Kūkākūkā',
 'views' => 'Nā nānaina',
-'toolbox' => 'Pahu mea hana',
-'userpage' => 'Nānā i ka ‘ao‘ao-mea ho‘ohana',
+'toolbox' => 'Hāmeʻa',
+'userpage' => 'Nānā i ka ‘ao‘ao mea ho‘ohana',
 'projectpage' => 'Nānā i ka ‘ao‘ao papahana',
 'imagepage' => 'Nānā i ka ‘ao‘ao pāpaho',
 'mediawikipage' => 'Nānā i ka ‘ao‘ao memo',
@@ -242,61 +290,72 @@ $messages = array(
 'categorypage' => 'Nānā i ka ‘ao‘ao mahele',
 'viewtalkpage' => 'Nānā i ke kūkākūkā',
 'otherlanguages' => 'Ma nā leo ʻē aʻe',
-'redirectedfrom' => '(Hoʻoili mai $1)',
-'redirectpagesub' => '‘Ao‘ao e alaka‘i ai',
+'redirectedfrom' => '(Hoʻoili hou mai $1)',
+'redirectpagesub' => '‘Ao‘ao hoʻoili hou',
 'lastmodifiedat' => 'Ua hoʻololi ʻia kēia ʻaoʻao ma ka lā $1, i ka manawa $2.',
+'viewcount' => 'Ua komo ʻia kēia ʻaoʻao i {{PLURAL:$1|hoʻokahi manawa|$1 mau manawa}}',
 'protectedpage' => '‘Ao‘ao ho‘omalu',
 'jumpto' => 'Lele i:',
-'jumptonavigation' => 'ka ho‘okele ‘ana',
+'jumptonavigation' => 'kelena',
 'jumptosearch' => 'huli',
+'view-pool-error' => 'E kala mai, ua hoʻoili nui ʻino nā pūnaewele i kēia manawa. Hoʻāʻo nā mea hoʻohana nui kā e ʻike i kēia ʻaoʻao. E ʻoluʻolu, e kali no kekahi mau minuke a hana hou. 
+
+$1',
+'pool-errorunknown' => 'Hewa ʻikeʻole',
 
 # All link text and link target definitions of links into project namespace that get used by other message strings, with the exception of user group pages (see grouppage).
 'aboutsite' => 'E pili ana iā {{SITENAME}}',
-'aboutpage' => 'Project:E pili ana',
-'copyrightpage' => '{{ns:project}}:Palapala ho‘okuleana',
-'currentevents' => 'Ka nū hou',
-'currentevents-url' => 'Project:Ka nū hou',
-'disclaimers' => 'Palapala hoʻokuʻu kuleana',
-'disclaimerpage' => 'Project:Palapala hoʻokuʻu kuleana',
-'edithelp' => 'Kōkua me ka ho‘ololi ‘ana',
-'helppage' => 'Help:Papa kuhikuhi',
-'mainpage' => "Kahua pa'a",
-'mainpage-description' => 'Ka papa kinohi',
-'policy-url' => 'Project:Palapala',
-'portal' => 'Ka hui kaiaulu',
-'portal-url' => 'Project:Ka hui kaiaulu',
-'privacy' => 'Kulekele palekana ʻikepili pilikino',
-'privacypage' => 'Project:Palapala pilikino',
-
-'badaccess' => 'Hewa me ka ‘ae',
+'aboutpage' => 'Project:Pilina',
+'copyrightpage' => '{{ns:project}}:Ponokope',
+'currentevents' => 'hou',
+'currentevents-url' => 'Project:hou',
+'disclaimers' => 'Nā Akahele',
+'disclaimerpage' => 'Project:Akahele laulaha',
+'edithelp' => 'Kōkua ho‘ololi',
+'helppage' => 'Help:Papakuhikuhi',
+'mainpage' => 'ʻAoʻao kinohi',
+'mainpage-description' => 'ʻAoʻao kinohi',
+'policy-url' => 'Project:Kulekele',
+'portal' => 'Puka kaiāulu',
+'portal-url' => 'Project:Puka kaiāulu',
+'privacy' => 'Kulekele pilikino',
+'privacypage' => 'Project:Kulekele pilikino',
+
+'badaccess' => 'Hewa ‘aena',
 
 'ok' => 'Hiki nō',
 'retrievedfrom' => 'Kiʻi ʻia mai "$1"',
-'youhavenewmessages' => 'He $1 ($2) kāu.',
-'youhavenewmessagesmulti' => 'He mau memo kou ma $1',
-'editsection' => 'e ho‘ololi',
-'editold' => 'e ho‘ololi',
+'youhavenewmessages' => '$1 {{PLURAL:$3|kāu}} ($2).',
+'youhavenewmessagesfromusers' => '$1 {{PLURAL:$4|kāu}} mai {{PLURAL:$3|kekahi mea hoʻohana ʻē aʻe|$3 mau mea hoʻohana}} ($2).',
+'youhavenewmessagesmanyusers' => '$1 kāu mai nā mea hoʻohana he nui ($2).',
+'newmessageslinkplural' => '{{PLURAl:$1|Hoʻokahi leka|999=He mau leka}}',
+'newmessagesdifflinkplural' => '{{PLURAL:$1|loli|999=mau loli}}',
+'youhavenewmessagesmulti' => '$1 kāu',
+'editsection' => 'ho‘ololi',
+'editold' => 'ho‘ololi',
 'viewsourceold' => 'nānā i ke kumu kanawai',
 'editlink' => 'hoʻololi',
-'viewsourcelink' => 'nānā i ka molekumu',
+'viewsourcelink' => 'nānā i kkumu',
 'editsectionhint' => 'E hoʻololi i ka paukū: $1',
-'toc' => 'Papa kuhikuhi',
+'toc' => 'Papakuhikuhi',
 'showtoc' => 'hō‘ike',
-'hidetoc' => 'hūnā',
+'hidetoc' => 'hoʻohūnā',
+'collapsible-collapse' => 'Hoʻoliʻi',
+'collapsible-expand' => 'Hoʻākea',
 'thisisdeleted' => 'Nānā ai‘ole hō‘āla i $1?',
 'viewdeleted' => 'Nānā i $1?',
-'restorelink' => '{{PLURAL:$1|kekahi ho‘opololei kāpae|nā ho‘opololei kāpae $1}}',
-'site-rss-feed' => 'Hulu RSS o $1',
-'site-atom-feed' => 'Hulu Atom o $1',
-'page-rss-feed' => 'Hulu RSS o "$1"',
-'page-atom-feed' => 'Hulu Atom o "$1"',
-'red-link-title' => '$1 (ʻaʻole i kākau ʻia)',
+'restorelink' => '{{PLURAL:$1|kekahi loli holoi|$1 mau loli holoi}}',
+'site-rss-feed' => 'Hānaīke RSS o $1',
+'site-atom-feed' => 'Hānaīke Atom o $1',
+'page-rss-feed' => 'Hānaīke RSS o "$1"',
+'page-atom-feed' => 'Hānaīke Atom o "$1"',
+'red-link-title' => '$1 (hakuia ʻole)',
 
 # Short words for each namespace, by default used in the namespace tab in monobook
 'nstab-main' => 'ʻAoʻao',
-'nstab-user' => 'Inoa mea ho‘ohana',
+'nstab-user' => 'Mea ho‘ohana',
 'nstab-media' => 'Pāpaho',
-'nstab-special' => 'Papa nui',
+'nstab-special' => 'ʻaoʻao kūikawā',
 'nstab-project' => 'Papahana',
 'nstab-image' => 'Waihona',
 'nstab-mediawiki' => 'Memo',
@@ -306,59 +365,125 @@ $messages = array(
 
 # General errors
 'error' => 'Hewa',
+'databaseerror-query' => 'Nīnau: $1',
+'databaseerror-function' => 'Hana: $1',
+'databaseerror-error' => 'Hewa: $1',
+'laggedslavemode' => '<strong>E akahele:</strong> ʻAʻole loaʻa paha i ka ʻaoʻao na hoʻouka hou hanawale.',
 'readonly' => 'Laka ‘ia ka hōkeo ‘ikepili',
-'missingarticle-diff' => '(Loli hope: $1, $2)',
-'filedeleteerror' => '‘A‘ole hiki ke kāpae i ka waihona "$1".',
-'filenotfound' => '‘A‘ole hiki ke loa‘a waihona "$1".',
+'missingarticle-diff' => '(Difē: $1, $2)',
+'internalerror' => 'Hewa koloko',
+'internalerror_info' => 'Hewa koloko:$1',
+'fileappenderrorread' => 'ʻAʻole hiki ke heluhelu iā "$1" ma loko o ka pākuʻi ʻana.',
+'fileappenderror' => 'ʻAʻole hiki ke pākuʻi "$1" iā "$2".',
+'filecopyerror' => 'ʻAʻole hiki ke kope ka waihona "$1" iā "$2".',
+'filerenameerror' => 'ʻAʻole hiki ke hōʻinoa hou ka waihona "$1" iā "$2".',
+'filedeleteerror' => '‘A‘ole hiki ke holoi i ka waihona "$1".',
+'directorycreateerror' => 'ʻAʻole hiki ke haku ka papakuhi waihona "$1"',
+'filenotfound' => '‘A‘ole hiki ke loa‘a ka waihona "$1".',
+'fileexistserror' => 'ʻAʻole hiki ke kākau i ka waihona "$1": Aia no ia.',
 'badtitle' => 'Inoa ‘ino',
-'viewsource' => 'E nānā i ka molekumu',
+'viewsource' => 'E nānā i kkumu',
 'cascadeprotected' => 'Ho‘omalu ‘ia kēia ‘ao‘ao mai e ho‘opololei ana, no ka mea, hoʻokomo pū ‘ia ‘oia ma aia {{PLURAL:$1|‘ao‘ao|nā ‘ao‘ao}} i lalo, ho‘omalu ‘ia me ka "e wailele ana" koho:
 $2',
-'ns-specialprotected' => '‘A‘ole hiki ke ho‘opololei i nā ‘ao‘ao kūikawā',
+'ns-specialprotected' => '‘A‘ole hiki ke ho‘ololi i nā ‘ao‘ao kūikawā',
 
 # Login and logout pages
-'yourname' => "Inoa mea ho'ohana",
+'welcomeuser' => 'Welina mai e $1!',
+'yourname' => "Inoa mea ho'ohana:",
+'userlogin-yourname' => 'Inoa mea hoʻohana',
+'userlogin-yourname-ph' => 'E kikokiko i kāu inoa mea hoʻohana',
+'createacct-another-username-ph' => 'E kikokiko i ka inoa mea hoʻohana',
 'yourpassword' => 'ʻŌlelo hūnā:',
-'yourpasswordagain' => "Hua'ōlelo huna hou",
+'userlogin-yourpassword' => 'ʻŌlelo hūnā',
+'userlogin-yourpassword-ph' => 'Kikokiko i kāu ʻōlelo hūnā',
+'createacct-yourpassword-ph' => 'Kikokiko i kekahi ʻōlelo hūnā',
+'yourpasswordagain' => 'E kikokiko hou i ka ʻōlelo hūnā:',
+'createacct-yourpasswordagain' => 'E hōʻoia i ka ʻōlelo hūnā',
+'createacct-yourpasswordagain-ph' => 'E kikokiko hou i ka ʻōlelo hūnā',
 'remembermypassword' => 'Hoʻomanaʻo iaʻu ma kēia lolo uila (no ka palena nui o $1 {{PLURAL:$1|lā|mau lā}})',
 'login' => 'ʻEʻe',
-'nav-login-createaccount' => 'ʻEʻe / E kāinoa',
-'loginprompt' => 'Pono ʻoe e hoʻā i nā makana (cookies) no ka ʻeʻe ʻana i {{SITENAME}}.',
-'userlogin' => 'ʻEʻe / E kāinoa',
+'nav-login-createaccount' => 'ʻEʻe / Kāinoa',
+'loginprompt' => 'Pono ʻoe e hoʻā i nā makana (cookies) no ka ʻeʻe ʻana iā {{SITENAME}}.',
+'userlogin' => 'ʻEʻe / Kāinoa',
 'userloginnocreate' => 'ʻEʻe',
-'logout' => 'E haʻalele',
-'userlogout' => 'E haʻalele',
-'notloggedin' => 'Mai ‘e‘e',
+'logout' => 'Haʻalele',
+'userlogout' => 'Haʻalele',
+'notloggedin' => 'ʻE‘e ʻole',
+'userlogin-noaccount' => 'ʻAʻohe āu moʻokāki?',
+'userlogin-joinproject' => 'E komo mai iā {{SITENAME}}',
 'nologin' => "ʻAʻohe āu moʻokāki? '''$1'''.",
 'nologinlink' => 'E kāinoa',
-'createaccount' => 'E hana',
+'createaccount' => 'E kāinoa',
 'gotaccount' => "He moʻokāki kāu? '''$1'''.",
 'gotaccountlink' => 'ʻEʻe',
-'createaccountmail' => 'no ka leka uila',
+'userlogin-resetlink' => 'Ua poina i kāu inoa mea hoʻohana?',
+'userlogin-resetpassword-link' => 'Ua poina i kāu ʻōlelo hūnā?',
+'helplogin-url' => 'Help:ʻEʻe',
+'userlogin-helplink' => '[[{{MediaWiki:helplogin-url}}|Kōkua me ka ʻeʻe ʻana]]',
+'userlogin-createanother' => 'E kāinoa i kekahi moʻokāki ʻē aʻe',
+'createacct-join' => 'E kikokiko i kāu ʻike i lalo.',
+'createacct-another-join' => 'E kikokiko i ka ʻike o ka moʻokāki hou i lalo.',
+'createacct-emailrequired' => 'Wahinoho lekauila',
+'createacct-emailoptional' => 'Wahinoho lekauila (kāpae)',
+'createacct-email-ph' => 'E kikokiko i kāu wahinoho lekauila',
+'createacct-another-email-ph' => 'E kikokiko i ka wahinoho lekauila',
+'createaccountmail' => 'Hana i kekahi ʻōlelo hūnā ponokoho kūikawā a hoʻouna ia i ka wahinoho lekauila i kikokiko ʻia',
+'createacct-realname' => 'Inoa ʻoiaʻiʻo (kāpae)',
 'createaccountreason' => 'Kumu:',
+'createacct-reason' => 'Kumu',
+'createacct-reason-ph' => 'No ke aha mai ke kāinoa nei i kekahi moʻokāki ʻē aʻe',
+'createacct-imgcaptcha-ph' => 'E kikokiko i ke kikokikona  i luna',
+'createacct-submit' => 'Kāinoa',
+'createacct-another-submit' => 'Kāinoa hou',
 'badretype' => 'ʻAʻole like nā ʻōlelo hūnā āu i hoʻokomo ai',
-'userexists' => 'Lilo ka inoa mea ho‘ohana.
-E koho i kekahi inoa, ke ‘olu‘olu.',
+'userexists' => 'Ua kāinoa ʻia ka inoa mea ho‘ohana.
+E koho i kekahi inoa ʻē aʻe, ke ‘olu‘olu.',
 'loginerror' => 'Hewa ʻeʻe',
+'createacct-error' => 'Hewa kāinoa',
+'createaccounterror' => 'ʻAʻole hiki ke kāinoa: $1',
 'loginsuccesstitle' => 'ʻEʻe kūleʻa',
-'loginsuccess' => "'''ʻEʻe ʻia ʻoe, ʻo \"\$1\", iā {{SITENAME}}.'''",
-'nouserspecified' => 'Pono ʻoe e kāhuakomo i ka ʻōlelo ʻeʻe.',
+'loginsuccess' => '<strong>Ua ʻeʻe ʻo "$1" iā {{SITENAME}}.</strong>',
+'nouserspecified' => 'Pono ʻoe e kāhuakomo i ka inoa mea hoʻohana.',
 'wrongpassword' => 'Hewa ka ʻōlelo hūnā.
-E ʻoluʻolu, e kūlia hou.',
+E ʻoluʻolu, e hana hou.',
 'wrongpasswordempty' => 'Hakahaka ka ʻōlelo hūnā.
-E ʻoluʻolu, e kūlia hou.',
-'mailmypassword' => 'Leka uila i ka huaʻōlelo hūnā hou',
+E ʻoluʻolu, e hana hou.',
+'mailmypassword' => 'Kāinoa hou i ka ʻōlelo hūnā',
 'passwordremindertitle' => "He 'ōlelo hūnā kūikawā no {{SITENAME}}",
-'emailauthenticated' => 'Ua hō‘oia ‘ia kāu leka uila ma ka lā $2 i ka hola $3.',
-'emailconfirmlink' => 'E hō‘oia i kāu leka uila',
-'accountcreated' => 'Ua lilo ‘ia ka mea ho‘ohana',
-'accountcreatedtext' => 'Ua lilo ‘ia ka mea ho‘ohana no $1.',
+'emailauthenticated' => 'Ua hō‘oia ‘ia kāu wahinoho lekauila ma ka lā $2 i ka hola $3.',
+'emailnotauthenticated' => 'ʻAʻole hōʻoia ʻia kāu wahinoho lekauila.
+Hoʻouna ʻole i kekahi lekauila no kēia mau helena.',
+'emailconfirmlink' => 'E hō‘oia i kāu wahinoho lekauila',
+'accountcreated' => 'Ua kāinoa',
+'accountcreatedtext' => 'Ua kāinoa ka moʻokāki no [[{{ns:User}}:$1|$1]] ([[{{ns:User talk}}:$1|kūkākūkā]]',
+'createaccount-title' => 'Kāinoa moʻokāki no {{SITENAME}}',
 'loginlanguagelabel' => "Kou 'ōlelo: $1",
+'pt-login' => 'ʻEʻe',
+'pt-createaccount' => 'Kāinoa',
+'pt-userlogout' => 'Haʻalele',
 
 # Change password dialog
-'changepassword' => 'E loli i ka palapala hua‘ōlelo',
+'changepassword' => 'E hoʻololi i ka ʻōlelo hūnā',
+'oldpassword' => 'ʻŌlelo hūnā kahiko:',
 'newpassword' => 'ʻŌlelo hūnā hou:',
-'changepassword-success' => 'Ua loli ‘ia kāu hua‘ōlelo huna! E ‘e‘e iā‘oe...',
+'retypenew' => 'E kikokiko hou i ka ʻōlelo hūnā hou:',
+'resetpass_submit' => 'Kau i ka ʻōlelo hūnā a ʻeʻe',
+'changepassword-success' => 'Ua hoʻololi ‘ia kāu hua‘ōlelo huna!',
+'resetpass-submit-cancel' => 'Hoʻōki',
+'resetpass-temp-password' => 'ʻŌlelo hūnā kūikawā:',
+
+# Special:PasswordReset
+'passwordreset' => 'Kāinoa hou i ka ʻōlelo hūnā',
+'passwordreset-legend' => 'Kāinoa hou i ka ʻōlelo hūnā',
+'passwordreset-username' => "Inoa mea ho'ohana:",
+'passwordreset-email' => 'Wahinoho lekauila:',
+
+# Special:ChangeEmail
+'changeemail-oldemail' => 'Wahinoho lekauila hananei:',
+'changeemail-newemail' => 'Wahinoho lekauila hou:',
+'changeemail-none' => '(ʻaʻohe)',
+'changeemail-password' => 'Kāu ʻōlelo hūnā {{SITENAME}}:',
+'changeemail-cancel' => 'Hoʻōki',
 
 # Edit page toolbar
 'bold_sample' => 'Ho‘okā‘ele',
@@ -366,88 +491,115 @@ E ʻoluʻolu, e kūlia hou.',
 'italic_sample' => 'Ho‘ohiō',
 'italic_tip' => 'Ho‘ohiō',
 'link_sample' => 'Inoa loulou',
-'link_tip' => 'Loulou loko wahi',
+'link_tip' => 'Loulou lokoiho',
+'extlink_sample' => 'http://www.example.com inoa loulou',
 'extlink_tip' => 'Loulou kūwaho (e ho‘omana‘o i ka poʻo pāʻālua http://)',
 'headline_sample' => 'Po‘o‘ōlelo',
 'media_tip' => 'Loulou waihona',
-'sig_tip' => 'Kou kākau inoa a me ka manawa',
-'hr_tip' => 'Laina ‘ilikai (e ho‘ohana pākiko)',
+'sig_tip' => 'Kou pūlima me ka manawa',
+'hr_tip' => 'Laina ‘ilikai (e hana pākiko)',
 
 # Edit pages
 'summary' => 'Hōʻuluʻulu manaʻo:',
 'subject' => 'Kumumanaʻo/poʻo laina:',
-'minoredit' => "He mea i ho'opololei iki 'ia",
-'watchthis' => 'E nānā pono i kēia mea',
-'savearticle' => 'E mālama i ka mea',
+'minoredit' => 'He hoʻololi iki kēia',
+'watchthis' => 'E nānā pono i kēia ʻaoʻao',
+'savearticle' => 'E mālama i ka ʻaoʻao',
 'preview' => 'Nāmua',
 'showpreview' => "E hō'ike i ka nāmua",
-'showdiff' => "E hō'ike hou",
-'anoneditwarning' => "'''Ke aʻo ʻana:''' ʻAʻole ʻoe ʻeʻe.
-E hoʻopaʻa ʻia ana kou IP ma ko kēia ʻaoʻao mōʻaukala.",
-'blockedtitle' => 'Ua ke‘a ‘ia ka mea ho‘ohana',
+'showlivepreview' => 'Nāmua ʻānō',
+'showdiff' => "E hō'ike i nā loli",
+'anoneditwarning' => '<strong>E akahele:</strong> ʻAʻole ʻoe e ʻeʻe nei.
+E hoʻopaʻa ʻia ana kāu IP ma ko kēia ʻaoʻao mōʻaukala hoʻololi.',
+'blockedtitle' => 'Ua pale ‘ia ka mea ho‘ohana',
 'blockednoreason' => '‘a‘ohe kumu',
 'loginreqlink' => 'ʻeʻe',
-'accmailtitle' => 'Ua ho‘ouna ‘ia ka hua‘ōlelo huna',
+'accmailtitle' => 'Ua ho‘ouna ‘ia ka ‘ōlelo hūnā',
 'newarticle' => '(Hou)',
-'anontalkpagetext' => "----''‘O kēia ka ʻaoʻao kūkākūkā no kekahi mea ho‘ohana me ka moʻokāki ʻole. No laila, pono mākou e ho‘ohana i ka wahi noho IP no ka hōʻoia ʻana iā ia.
-Hiki i kekahi mau mea hoʻohana ke hoʻokaʻana i kēia wahi noho IP.
-Inā he mea ho‘ohana ʻoe a ua haʻi ʻia kekahi manaʻo iā ʻoe, [[Special:UserLogin/signup|e hoʻokumu ʻia kekahi moʻokāki]] a i ʻole [[Special:UserLogin|e ʻeʻe]].''",
+'anontalkpagetext' => "----
+<em>ʻO kēia ka ʻaoʻao kūkākūkā no kekahi mea ho‘ohana me ka inoa ʻole.</em>
+No laila, pono mākou e ho‘ohana i ka IP no ka hōʻoia ʻana iā ia a hiki i kekahi mau mea hoʻohana ke hoʻokaʻana i kēia  IP.
+Inā he mea ho‘ohana inoa ʻole ʻoe a loaʻa kekahi mau manaʻo nāuʻole, e ʻoluʻolu [[Special:UserLogin/signup|e kāinoa]] a i ʻole [[Special:UserLogin|e ʻeʻe]].''",
 'noarticletext' => 'ʻAʻohe kikokikona a kēia ʻaoʻao.
 Hiki iā ʻoe ke [[Special:Search/{{PAGENAME}}|huli no kēia inoa ʻaoʻao]] i nā ʻaoʻao ʻē aʻe, <span class="plainlinks">[{{fullurl:SpecialLog|page={{FULLPAGENAMEE}}}} huli i nā moʻolelo pili], a i ʻole [{{fullurl:{{FULLPAGENAME}}|action=edit}} hoʻololi i kēia ʻaoʻao]</span>.',
-'previewnote' => "'''‘O keia ka nāmua;
-‘a‘ole i mālama ‘ia ka ho‘ololi!'''",
+'previewnote' => '<strong>ʻO kēia ka nāmua wale nō.</strong>
+‘A‘ole mālama ‘ia nā ho‘ololi!',
+'continue-editing' => 'Hele i kahi hoʻololi',
 'editing' => 'Ke ho‘ololi nei iā $1',
-'editingsection' => 'Ke ho‘opololei nei iā $1 (mahele)',
+'creating' => 'Ke haku nei iā $1',
+'editingsection' => 'Ke hoʻololi nei iā $1 (mahele)',
 'editingcomment' => 'Ke ho‘ololi nei iā $1 (paukū hou)',
-'yourtext' => 'Ko‘u ‘ōlelo',
+'editconflict' => 'He pilikia hoʻololi: $1',
+'yourtext' => 'Kāu kikokikona',
+'storedversion' => 'Loihape waihoia',
 'yourdiff' => 'Nā mea ‘oko‘a',
-'copyrightwarning' => "Hoʻokuʻu ʻia nā mea lūlū iā {{SITENAME}} ma lalo o ka $2 (no nā mea kikoʻī, kele iā $1).
-Inā ʻaʻole ʻoe makemake i ka hoʻololi ʻana kūnoa i kou kākau ʻana a ʻaʻole ʻoe makemake i ka hoʻomalele ʻana i kāu mau loli, inā mai kākau ma ʻaneʻi.<br />
-Ke hoʻohiki nei ʻoe iā kākou: nou i kākau i kēia kikokikona a i ʻole nou i kope i kēia kikokikona mai ke kūmole kūʻokoʻa.
-'''MAI KĀKAU I NĀ KIKOKIKONA PONOKOPE E NELE AI KA ʻAE!'''",
-'protectedpagewarning' => "'''A‘o ‘ana:  Ua laka ‘ia kēia ‘ao‘ao, pēlā, hiki i nā \"kahu\" ke ho‘opololei wale nō.'''",
+'copyrightwarning' => 'E ʻoluʻolu, hoʻokuʻu ʻia nā mea lūlū iā {{SITENAME}} ma lalo o ka laikini $2 (no nā mea kikoʻī, kele iā $1).
+Inā ʻaʻole ʻoe makemake i ka hoʻololi ʻana kūnoa o kou kākau ʻana a ʻaʻole ʻoe makemake i ka hoʻomalele ʻana i kāu mau loli, a laila mai kākau ma ʻaneʻi.<br />
+Ke hoʻohiki nei ʻoe iā kākou: nāu i kākau i kēia kikokikona aiʻole nau i kope i kēia kikokikona mai ke kūmole kūʻokoʻa.
+<strong>Mai waiho i nā kikokikona ponokope me ka ʻae ʻole!</strong>',
+'protectedpagewarning' => '<strong>E akahele:  Ua hoʻomalu ‘ia kēia ‘ao‘ao, pēlā, hiki i nā "kahu" ke ho‘ololi wale nō.</strong>
+Aia nā loli hanalohi i lalo no ka ʻikena:',
 'templatesusedpreview' => 'Hoʻohana ʻia kēia {{PLURAL:$1|anakuhi|mau anakuhi}} i kēia nāmua:',
 'template-protected' => '(ho‘omalu ‘ia)',
 'template-semiprotected' => '(hapa-ho‘omalu ‘ia)',
 'edittools' => '<!-- Eia ka ‘ōlelo e hō‘ike ‘ia malalo o nā palapala ho‘ololi ame nā palapala ho‘ohui. -->',
-'permissionserrorstext-withaction' => 'ʻAʻohe ou ʻae no $2, no {{PLURAL:$1|ia mea|no ia mau mea}}:',
+'permissionserrorstext-withaction' => 'ʻAʻohe ou ʻae no $2, no {{PLURAL:$1|kumu| mau kumu}}:',
 
 # "Undo" feature
-'undo-success' => 'Hiki iā ʻoe ke hoʻihoʻi mai i kēia loli ʻana.
-E ʻoluʻolu, e hōʻoia i ka hoʻokūkū ʻana i lalo, a laila, e mālama i nā loli i lalo no ka hoʻopau ʻana i ka hoʻihoʻi mai ʻana i ka loli.',
+'undo-success' => 'Hiki iā ʻoe ke hoʻihoʻi i kēia loli.
+E ʻoluʻolu, e hōʻoia i ka hoʻokūkū ʻana i lalo, a laila, e mālama i nā loli i lalo no ka hoʻopau ʻana o ka hoʻihoʻi o ka loli.',
 'undo-summary' => 'Hoʻihoʻi mai i ke kāmua $1 na [[Special:Contributions/$2|$2]] ([[User talk:$2|kūkākūkā]])',
 
 # History pages
 'currentrev' => 'Kāmua hou',
-'revisionasof' => 'Ka loli ʻana ma $1',
+'revisionasof' => 'Kāmua ma $1',
+'revision-info' => 'Kāmua ma $1 na $2',
 'previousrevision' => '← Kāmua mua',
 'nextrevision' => 'Kāmua hou →',
-'currentrevisionlink' => 'Kāmua hou',
-'cur' => 'hou',
-'last' => 'hope',
-'page_first' => 'mua',
-'page_last' => 'hope',
-'histfirst' => 'Kahiko loa',
-'histlast' => 'Hou loa',
-'historysize' => '({{PLURAL:$1|1 ‘ai|$1 ‘ai}})',
-'historyempty' => '(‘ole)',
+'currentrevisionlink' => 'Kāmua hanawale',
+'cur' => 'cur',
+'next' => 'hou aʻe',
+'last' => 'hou nei',
+'page_first' => 'mua loa',
+'page_last' => 'hope loa',
+'history-fieldset-title' => 'Mōʻaukaki Pūnaewele',
+'history-show-deleted' => 'Holoi wale nō',
+'histfirst' => 'kahiko loa',
+'histlast' => 'hou loa',
+'historysize' => '({{PLURAL:$1|1 ‘ai|$1 mau ‘ai}})',
+'historyempty' => '(ʻaʻohe)',
 
 # Revision feed
-'history-feed-item-nocomment' => '$1 ma $2',
+'history-feed-title' => 'Mōʻaukala kāmua',
+'history-feed-description' => 'Mōʻaukala kāmua no kēia ʻaoʻao ma ka wiki',
+'history-feed-item-nocomment' => '$1 ma $3 ma ka hola $4',
 
 # Revision deletion
-'rev-delundel' => 'hō‘ike/hūnā',
+'rev-delundel' => 'hoʻololi ka nānā ʻana',
+'revdelete-show-file-submit' => 'ʻAe',
 'revdelete-radio-same' => '(mai hoʻololi)',
 'revdelete-radio-set' => 'ʻAe',
 'revdelete-radio-unset' => 'ʻAʻole',
+'revdelete-log' => 'Kumu:',
 'revdel-restore' => 'hoʻololi ka nānā ʻana',
+'pagehist' => 'Mōʻaukala ʻaoʻao',
+'deletedhist' => 'Mōʻaukala holoi',
+'revdelete-otherreason' => 'Nā kumu ʻē aʻe',
+'revdelete-reasonotherlist' => 'Nā kumu ʻē aʻe',
+'revdelete-offender' => 'Mea kākau kāmua:',
+
+# History merging
+'mergehistory-from' => 'ʻAoʻao kūmole:',
+'mergehistory-into' => 'ʻAoʻao helewahi:',
+'mergehistory-reason' => 'Kumu:',
 
 # Merge log
-'revertmerge' => 'Mai hoʻokuʻi pū',
+'revertmerge' => 'Hoʻokuʻipū ʻole',
 
 # Diffs
 'lineno' => 'Laina $1:',
-'editundo' => 'hoʻihoʻi mai',
+'editundo' => 'hoʻihoʻi',
+'diff-empty' => '(ʻaʻohe like ʻole)',
 
 # Search results
 'searchresults' => 'Nā hualoaʻa',
@@ -455,13 +607,25 @@ E ʻoluʻolu, e hōʻoia i ka hoʻokūkū ʻana i lalo, a laila, e mālama i nā
 'prevn' => '{{PLURAL:$1|$1}} ma mua',
 'nextn' => '{{PLURAL:$1|$1}} ma hope',
 'viewprevnext' => 'Nānā i nā ($1 {{int:pipe-separator}} $2) ($3)',
-'search-result-size' => '$1 ({{PLURAL:$2|1 huaʻōlelo|$2 huaʻōlelo}})',
+'searchprofile-project' => 'Nā ʻaoʻao Kōkua a me Papahana',
+'searchprofile-everything' => 'Nā mea apau',
+'searchprofile-articles-tooltip' => 'Huli iā $1',
+'searchprofile-project-tooltip' => 'Huli iā $1',
+'searchprofile-images-tooltip' => 'Huli no nā waihona',
+'searchprofile-everything-tooltip' => 'Huli i nā mea apau (nā kūkākūkā nō hoʻi)',
+'search-result-size' => '$1 ({{PLURAL:$2|1 huaʻōlelo|$2 mau huaʻōlelo}})',
+'search-result-category-size' => '{{PLURAL:$1|1 mea hoʻohana|$1 mau mea hoʻohana}} ({{PLURAL:$2|1 mahele lokoiho|$2 mau māhele lokoiho}}, {{PLURAL:$3|1 wahihona|$3 mau waihona}})',
+'search-redirect' => '(hoʻoili hou $1)',
 'search-section' => '(māhele $1)',
 'search-suggest' => 'ʻO kēia paha kou manaʻo: $1',
 'search-interwiki-caption' => 'Nā pāhana ʻē aʻe',
-'searchall' => 'apau',
+'search-interwiki-more' => '(hou aʻe)',
+'searchall' => 'nā mea apau',
 'powersearch-legend' => 'Hulina kūlana kiʻekiʻe',
 'powersearch-ns' => 'Huli i loko o nā wahi inoa:',
+'powersearch-toggleall' => 'Nā mea apau',
+'powersearch-togglenone' => 'ʻAʻohe',
+'search-external' => 'Huli kūwaho',
 
 # Preferences page
 'preferences' => 'Kaʻu makemake',
@@ -469,17 +633,28 @@ E ʻoluʻolu, e hōʻoia i ka hoʻokūkū ʻana i lalo, a laila, e mālama i nā
 'prefs-skin' => 'ʻIli',
 'skin-preview' => 'Nāmua',
 'datedefault' => 'ʻAʻohe makemake',
+'prefs-beta' => 'Helena Beta',
 'prefs-datetime' => 'Ka lā a me ka hola',
-'prefs-personal' => 'ʻAoʻao ʻike mea hoʻohana',
+'prefs-personal' => 'ʻAoʻao mea hoʻohana',
 'prefs-rc' => 'Nā loli hou',
-'prefs-watchlist' => 'Helu nānā',
-'prefs-watchlist-days' => 'Nā lā e hōʻike ana i ka helu nānā:',
+'prefs-watchlist' => 'Papa nānāpono',
+'prefs-watchlist-days' => 'Nā lā e hōʻike ana i ka papa nānāpono:',
 'prefs-watchlist-days-max' => 'Maximum $1 {{PLURAL:$1|day|days}}',
+'prefs-email' => 'Koho lekauila',
+'prefs-rendering' => 'Helena',
 'saveprefs' => 'Mālama',
+'restoreprefs' => 'Hōʻala i nā makemake paʻamau (apau)',
+'prefs-editing' => 'Hoʻololi',
+'rows' => 'Lālani:',
+'columns' => 'Koloma:',
 'searchresultshead' => 'Huli',
 'savedprefs' => 'Ua mālama ‘ia kāu makemake',
+'timezonelegend' => 'Kāʻei hola:',
+'localtime' => 'Hola kamaʻāina:',
+'servertime' => 'Hola pūnaewele:',
+'guesstimezone' => 'Piha mai ka pōlamu pūnaewele',
 'timezoneregion-africa' => 'ʻApelika',
-'timezoneregion-america' => 'Amelika',
+'timezoneregion-america' => 'ʻAmelika',
 'timezoneregion-antarctica' => 'ʻAneʻālika',
 'timezoneregion-arctic' => 'ʻĀlika',
 'timezoneregion-asia' => 'ʻĀkia',
@@ -488,62 +663,131 @@ E ʻoluʻolu, e hōʻoia i ka hoʻokūkū ʻana i lalo, a laila, e mālama i nā
 'timezoneregion-europe' => 'ʻEulopa',
 'timezoneregion-indian' => 'Moana ʻIniana',
 'timezoneregion-pacific' => 'Moana Pakipika',
+'prefs-searchoptions' => 'Huli',
+'prefs-namespaces' => 'Lewainoa',
 'default' => 'paʻamau',
-'youremail' => 'Leka uila:',
-'username' => "Inoa mea ho'ohana:",
-'yourrealname' => 'Inoa maoli:',
+'prefs-files' => 'Waihona',
+'youremail' => 'Lekauila:',
+'username' => '{{GENDER:$1|Inoa mea hoʻohana}}:',
+'uid' => '{{GENDER:$1|Mea hoʻohana}} ID:',
+'prefs-memberingroups' => '{{GENDER:$2|He lālā}} o {{PLURAL:$1|hui|mau hui}}:',
+'prefs-registration' => 'Hola kāinoa:',
+'yourrealname' => 'Inoa ʻoiaʻiʻo:',
 'yourlanguage' => 'Kou ʻōlelo:',
-'yournick' => 'Inoa kapakapa:',
+'yournick' => 'Pūlima hou:',
 'yourgender' => 'Keka:',
+'gender-unknown' => 'Kāpae',
 'gender-male' => 'Kāne',
 'gender-female' => 'Wahine',
-'email' => 'Leka uila',
-'prefs-help-email-required' => 'Koina ka leka uila.',
+'email' => 'Lekauila',
+'prefs-help-email-required' => 'Koi i ka lekauila.',
+'prefs-signature' => 'Pūlima',
+'prefs-advancedediting' => 'Koho paʻamau',
+'prefs-editor' => 'Luna Hoʻoponopono:',
+'prefs-preview' => 'Nāmua',
 
 # User rights
 'userrights' => 'Ho‘oponopono ‘ana o nā kuleana',
+'userrights-groupsmember' => 'He lālā o:',
+'userrights-reason' => 'Kumu:',
 
 # Groups
+'group' => 'Hui:',
+'group-user' => 'Mea hoʻohana',
+'group-bot' => 'Lopako',
 'group-sysop' => 'Nā kahu',
 'group-bureaucrat' => 'Nā kuhina',
-'group-all' => '(āpau)',
+'group-all' => '(Nā mea apau)',
 
-'group-sysop-member' => 'Kahu',
-'group-bureaucrat-member' => 'Kuhina',
+'group-user-member' => '{{GENDER:$1|mea hoʻohana}}',
+'group-bot-member' => '{{GENDER:$1|lopako}}',
+'group-sysop-member' => '{{GENDER:$1|kahu}}',
+'group-bureaucrat-member' => '{{GENDER:$1|kuhina}}',
 
+'grouppage-user' => '{{ns:project}}:Mea hoʻohana',
+'grouppage-bot' => '{{ns:project}}:Lopako',
 'grouppage-sysop' => '{{ns:project}}:Nā kahu',
+'grouppage-bureaucrat' => '{{ns:project}}:Nā kuhina',
+
+# Rights
+'right-read' => 'Heluhelu i nā ʻaoʻao',
+'right-edit' => 'Hoʻololi i nā ʻaoʻao',
+'right-createpage' => 'Haku i nā ʻaoʻao (he kūkākūkā ʻole)',
+'right-createtalk' => 'Haku i ka ʻaoʻao kūkākūkā',
+'right-createaccount' => 'Kāinoa i nā moʻokāki hou',
+'right-minoredit' => 'Kaha i nā loli me he hoʻololi iki',
+'right-move' => 'Hoʻoneʻe i nā ʻaoʻao',
+'right-move-subpages' => 'Hoʻoneʻe i nā ʻaoʻao me nā ʻaoʻao lokoiho',
+'right-movefile' => 'Hoʻoneʻe i nā waihona',
+'right-upload' => 'Hoʻouka i nā waihona',
+'right-upload_by_url' => 'Hoʻouka i nā waihona mai kekahi URL',
+'right-delete' => 'Holoi i nā ʻaoʻao',
+'right-bigdelete' => 'Holoi i nā ʻaoʻao me he mōʻaukala nui',
+'right-browsearchive' => 'Huli i nā ʻaoʻao holoi',
+'right-undelete' => 'Holoi ʻole i kekahi ʻaoʻao',
+'right-block' => 'Pale i nā mea hoʻohana ʻē aʻe mai ka hoʻololi ʻana',
+'right-blockemail' => 'Pale i nā mea hoʻohana ʻē aʻe mai ka lekauila ʻana',
+'right-hideuser' => 'Pale i ka inoa mea hoʻohana, no laila ʻaʻole hōʻike i ka lehulehu',
+'right-unblockself' => 'Paleʻole i kāuiho',
 
 # Associated actions - in the sentence "You do not have permission to X"
 'action-edit' => 'ka hoʻololi ʻana i kēia ʻaoʻao',
 
 # Recent changes
 'nchanges' => '$1 {{PLURAL:$1|loli|mau loli}}',
+'enhancedrc-since-last-visit' => '$1 {{PLURAL:$1|mai kāu kipana aku nei}}',
+'enhancedrc-history' => 'mōʻaukala',
 'recentchanges' => 'Nā loli hou',
-'rcshowhideminor' => '$1 i nā ho‘opololei iki',
+'rcshowhideminor' => '$1 i nā ho‘ololi iki',
+'rcshowhideminor-show' => 'Hōʻike',
+'rcshowhideminor-hide' => 'Hoʻohūnā',
 'rcshowhidebots' => '$1 i nā lopako',
-'rcshowhideliu' => '$1 i nā mea hoʻohana i ʻeʻe ai',
+'rcshowhidebots-show' => 'Hōʻike',
+'rcshowhidebots-hide' => 'Hoʻohūnā',
+'rcshowhideliu' => '$1 i nā mea hoʻohana i kāinoa ʻia',
+'rcshowhideliu-show' => 'Hōʻike',
+'rcshowhideliu-hide' => 'Hoʻohūnā',
 'rcshowhideanons' => '$1 i nā mea hoʻohana i nele ai ka inoa',
+'rcshowhideanons-show' => 'Hōʻike',
+'rcshowhideanons-hide' => 'Hoʻohūnā',
+'rcshowhidepatr' => '$1 i nā hoʻololi kiaʻi kaʻahele',
+'rcshowhidepatr-show' => 'Hōʻike',
+'rcshowhidepatr-hide' => 'Hoʻohūnā',
 'rcshowhidemine' => '$1 i ka‘u mau hoʻololi',
-'diff' => '‘oko‘a',
-'hist' => 'loli',
-'hide' => 'hūnā',
-'show' => 'hō‘ike',
+'rcshowhidemine-show' => 'Hōʻike',
+'rcshowhidemine-hide' => 'Hoʻohūnā',
+'rclinks' => 'E hōʻike i nā loli hanawale, he $1, mai $2 (mau) lā aku nei<br/>$3',
+'diff' => 'ʻokoʻa',
+'hist' => 'mōkala',
+'hide' => 'Hoʻohūnā',
+'show' => 'Hō‘ike',
 'minoreditletter' => 'iki',
-'newpageletter' => 'hou',
-'boteditletter' => 'lopako',
-'rc-enhanced-expand' => 'Hō‘ike i nā ‘ikepili (me JavaScript)',
-'rc-enhanced-hide' => 'Hūnā i nā ‘ikepili',
+'newpageletter' => 'ʻAHou',
+'boteditletter' => 'pako',
+'rc-enhanced-expand' => 'Hō‘ike i nā ‘ikepili',
+'rc-enhanced-hide' => 'Hoʻohūnā i nā ‘ikepili',
 
 # Recent changes linked
 'recentchangeslinked' => 'Nā loli hou ʻālike',
+'recentchangeslinked-feed' => 'Nā loli hou ʻālike',
+'recentchangeslinked-toolbox' => 'Nā loli hou ʻālike',
 'recentchangeslinked-page' => 'Inoa ʻaoʻao:',
 
 # Upload
 'upload' => 'Hoʻouka i ka waihona',
 'uploadbtn' => 'Hoʻouka i ka waihona',
+'uploadnologin' => 'ʻE‘e ʻole',
+'uploaderror' => 'Hewa hoʻouka',
+'filename' => 'Inoa waihona',
 'filedesc' => 'Hōʻuluʻulu manaʻo',
 'fileuploadsummary' => 'Hōʻuluʻulu manaʻo:',
+'filesource' => 'Kumu:',
+'uploadedfiles' => 'Waihona hoʻoukaia',
+'savefile' => 'Waihona mālama',
 'uploadedimage' => 'hoʻouka ʻia iā "[[$1]]"',
+'upload-source' => 'Waihona kūmole',
+'sourcefilename' => 'Inoawaihona kūmole:',
+'sourceurl' => 'URL kūmole:',
 
 # Special:ListFiles
 'listfiles_name' => 'Inoa',
index 0501a60..f8a3a7a 100644 (file)
@@ -950,7 +950,7 @@ $2',
 'resetpass-temp-password' => 'סיסמה זמנית:',
 'resetpass-abort-generic' => 'שינוי הסיסמה בוטל על־ידי הרחבה.',
 'resetpass-expired' => 'סיסמתכם פקעה. אנא הגדירו סיסמה חדשה כדי להיכנס.',
-'resetpass-expired-soft' => 'סיסמתכם פקעה, ויש לאפס אותה. אנא בחרו סיסמה חדשה כעת, או לחצו על "ביטול" כדי לאפס אותה מאוחר יותר.',
+'resetpass-expired-soft' => 'סיסמתכם פקעה ויש לאפס אותה. אנא בחרו סיסמה חדשה כעת, או לחצו על "{{int:resetpass-submit-cancel}}" כדי לאפס אותה מאוחר יותר.',
 
 # Special:PasswordReset
 'passwordreset' => 'איפוס סיסמה',
@@ -1811,14 +1811,26 @@ $1",
 'recentchanges-legend-heading' => "'''מקרא:'''",
 'recentchanges-legend-newpage' => '(ראו גם [[Special:NewPages|רשימת דפים חדשים]])',
 'recentchanges-legend-plusminus' => "(''±123'')",
-'rcnotefrom' => 'להלן <b>$1</b> השינויים האחרונים שבוצעו החל מתאריך <b>$2</b>:',
-'rclistfrom' => 'הצגת שינויים חדשים החל מ־$1',
+'rcnotefrom' => 'להלן השינויים שבוצעו החל מ‏‏֫־<b>$2</b> (עד <b>$1</b> מוצגים).',
+'rclistfrom' => 'הצגת שינויים חדשים החל מ־$2, $3',
 'rcshowhideminor' => '$1 שינויים משניים',
+'rcshowhideminor-show' => 'הצגת',
+'rcshowhideminor-hide' => 'הסתרת',
 'rcshowhidebots' => '$1 בוטים',
+'rcshowhidebots-show' => 'הצגת',
+'rcshowhidebots-hide' => 'הסתרת',
 'rcshowhideliu' => '$1 משתמשים רשומים',
+'rcshowhideliu-show' => 'הצגת',
+'rcshowhideliu-hide' => 'הסתרת',
 'rcshowhideanons' => '$1 משתמשים אנונימיים',
+'rcshowhideanons-show' => 'הצגת',
+'rcshowhideanons-hide' => 'הסתרת',
 'rcshowhidepatr' => '$1 עריכות בדוקות',
+'rcshowhidepatr-show' => 'הצגת',
+'rcshowhidepatr-hide' => 'הסתרת',
 'rcshowhidemine' => '$1 עריכות שלי',
+'rcshowhidemine-show' => 'הצגת',
+'rcshowhidemine-hide' => 'הסתרת',
 'rclinks' => 'הצגת $1 שינויים אחרונים ב־$2 הימים האחרונים.<br /> $3',
 'diff' => 'הבדל',
 'hist' => 'היסטוריה',
@@ -1946,6 +1958,8 @@ $1",
 'uploaddisabledtext' => 'אפשרות העלאת הקבצים מבוטלת.',
 'php-uploaddisabledtext' => 'אפשרות העלאת הקבצים מבוטלת ברמת PHP. אנא בדקו את ההגדרה file_uploads.',
 'uploadscripted' => 'הקובץ כולל קוד סקריפט או HTML שעשוי להתפרש או להתבצע בטעות על ידי הדפדפן.',
+'uploadscriptednamespace' => "קובץ ה‏‏֫־SVG הזה כולל מרחב שם בלתי חוקי: '$1'",
+'uploadinvalidxml' => 'לא ניתן לפרש את ה־XML בקובץ שהועלה.',
 'uploadvirus' => 'הקובץ מכיל וירוס!
 פרטים:
 <div dir="ltr">$1</div>',
@@ -2519,7 +2533,7 @@ $1',
 'watchmethod-list' => 'בודק את העריכות האחרונות בדפים שברשימת המעקב',
 'watchlistcontains' => 'רשימת המעקב כוללת {{PLURAL:$1|דף אחד|$1 דפים}}.',
 'iteminvalidname' => 'בעיה עם $1, שם שגוי…',
-'wlnote2' => '×\9c×\94×\9c×\9f ×\94ש×\99× ×\95×\99×\99×\9d ×\94×\90×\97ר×\95× ×\99×\9d {{PLURAL:$1|×\91שע×\94 ×\94×\90×\97ר×\95× ×\94\91שעת×\99×\99×\9d ×\94×\90×\97ר×\95× ×\95ת|×\91â\80\8fâ\80\8fÖ«Ö¾<strong>$1</strong> ×\94שע×\95ת ×\94×\90×\97ר×\95× ×\95ת}}, ×¢×\93 $3, $2.',
+'wlnote2' => 'להלן השינויים האחרונים {{PLURAL:$1|בשעה האחרונה|בשעתיים האחרונות|ב‏‏־<strong>$1</strong> השעות האחרונות}}, עד $3, $2.',
 'wlshowlast' => '(הצגת $1 שעות אחרונות | $2 ימים אחרונים | $3)',
 'watchlist-options' => 'אפשרויות ברשימת המעקב',
 
@@ -2782,6 +2796,7 @@ $1',
 'sp-contributions-search' => 'חיפוש תרומות',
 'sp-contributions-username' => 'שם משתמש או כתובת IP:',
 'sp-contributions-toponly' => 'הצגת עריכות שהן הגרסאות האחרונות בלבד',
+'sp-contributions-newonly' => 'הצגת עריכות שהן יצירות של דפים בלבד',
 'sp-contributions-submit' => 'חיפוש',
 
 # What links here
@@ -4397,6 +4412,4 @@ $5
 'expand_templates_generate_rawhtml' => 'הצגת HTML גולמי',
 'expand_templates_preview' => 'תצוגה מקדימה',
 
-# Unknown messages
-'uploadinvalidxml' => 'לא ניתן לפרש את ה־XML בקובץ שהועלה.',
 );
index 04d4b58..dffde68 100644 (file)
@@ -473,7 +473,7 @@ $1',
 'editsectionhint' => 'अनुभाग सम्पादन: $1',
 'toc' => 'विषय सूची',
 'showtoc' => 'दिखाएँ',
-'hidetoc' => 'à¤\9bिपाएँ',
+'hidetoc' => 'à¤\9bà¥\81पाएँ',
 'collapsible-collapse' => 'छोटा करें',
 'collapsible-expand' => 'विस्तार करें',
 'thisisdeleted' => '$1 देखें या वापिस लाएँ?',
@@ -750,7 +750,7 @@ $2',
 
 # Change password dialog
 'changepassword' => 'कूटशब्द बदलें',
-'resetpass_announce' => 'लà¥\89à¤\97 à¤\87न à¤\95à¥\8b à¤ªà¥\82रा à¤\95रनà¥\87 à¤\95à¥\87 à¤²à¤¿à¤¯à¥\87 à¤\86पà¤\95à¥\8b à¤¯à¤¹à¤¾à¤\81 à¤\8fà¤\95 à¤¨à¤¯à¤¾ à¤\95à¥\82à¤\9fशबà¥\8dद à¤¦à¥\87ना à¤¹à¥\8bà¤\97ा:',
+'resetpass_announce' => 'लà¥\89à¤\97 à¤\87न à¤¸à¤®à¥\8dपà¥\82रà¥\8dण à¤\95रनà¥\87 à¤\95à¥\87 à¤²à¤¿à¤¯à¥\87 à¤\86पà¤\95à¥\8b à¤\8fà¤\95 à¤¨à¤¯à¤¾ à¤ªà¤¾à¤¸à¤µà¤°à¥\8dड à¤¦à¥\87ना à¤¹à¥\8bà¤\97ा।',
 'resetpass_text' => '<!-- पाठ यहाँ लिखें -->',
 'resetpass_header' => 'खाते का कूटशब्द बदलें',
 'oldpassword' => 'पुराना कूटशब्द:',
@@ -766,13 +766,13 @@ $2',
 'resetpass-submit-cancel' => 'रद्द करें',
 'resetpass-wrong-oldpass' => 'अवैध अस्थायी या वर्तमान कूटशब्द।
 संभव है कि या तो आपने पहले ही सफलतापूर्वक अपना कूटशब्द बदल लिया हो, या आपने एक नए अस्थायी कूटशब्द का अनुरोध किया हो।',
-'resetpass-recycled' => 'à¤\95à¥\83पया à¤\85पना à¤µà¤°à¥\8dतमान à¤ªà¤¾à¤¸à¤µà¤°à¥\8dड à¤\95à¥\87 à¤\85लावा à¤\95िसà¥\80 à¤\85नà¥\8dय à¤®à¥\87à¤\82 à¤°à¤¿à¤¸à¥\87à¤\9f करें।',
-'resetpass-temp-emailed' => 'à¤\86पनà¥\87 à¤\8fà¤\95 à¤\85सà¥\8dथायà¥\80 à¤\95à¥\8bड à¤\88मà¥\87ल à¤\95à¥\87 à¤¸à¤¾à¤¥ à¤²à¥\89à¤\97 à¤\87न à¤\95िया.
-लॉगिंग पूरा करने के लिए, आपको यहाँ एक नया पासवर्ड सेट करना होगा:',
+'resetpass-recycled' => 'रà¥\80सà¥\87à¤\9f à¤\95रनà¥\87 à¤\95à¥\87 à¤²à¤¿à¤\8f à¤¨à¤¯à¥\87 à¤ªà¤¾à¤¸à¤µà¤°à¥\8dड à¤®à¥\87à¤\82 à¤\95à¥\83पया à¤\85पनà¥\87 à¤µà¤°à¥\8dतमान à¤ªà¤¾à¤¸à¤µà¤°à¥\8dड à¤\95à¥\87 à¤\85लावा à¤\95िसà¥\80 à¤\85नà¥\8dय à¤ªà¤¾à¤¸à¤µà¤°à¥\8dड à¤\95ा à¤ªà¥\8dरयà¥\8bà¤\97 करें।',
+'resetpass-temp-emailed' => 'à¤\86पनà¥\87 à¤\8fà¤\95 à¤\85सà¥\8dथायà¥\80 à¤\88मà¥\87ल à¤\95ियà¥\87 à¤\97यà¥\87 à¤\95à¥\8bड à¤\95à¥\87 à¤¸à¤¾à¤¥ à¤²à¥\89à¤\97 à¤\87न à¤\95िया।
+लॉग इन सम्पूर्ण करने के लिए आपको यहाँ एक नया पासवर्ड सेट करना होगा:',
 'resetpass-temp-password' => 'अस्थायी कूटशब्द:',
 'resetpass-abort-generic' => 'कूटशब्द में बदलाव किसी एक्सटेंशन द्वारा रोक दिया गया है।',
-'resetpass-expired' => 'à¤\86पà¤\95à¥\87 à¤ªà¤¾à¤¸à¤µà¤°à¥\8dड à¤\95à¥\80 à¤¸à¤®à¤¯ à¤¸à¥\80मा à¤¸à¤®à¤¾à¤ªà¥\8dत à¤¹à¥\8b à¤\9aà¥\81à¤\95à¥\80 à¤¹à¥\88। à¤\95à¥\83पया à¤²à¥\89à¤\97इन करने के लिए एक नया पासवर्ड सेट करें।',
-'resetpass-expired-soft' => "à¤\86पà¤\95ा à¤ªà¤¾à¤¸à¤µà¤°à¥\8dड à¤¸à¤®à¤¾à¤ªà¥\8dत à¤¹à¥\8b à¤\97या à¤¹à¥\88, à¤\94र à¤°à¥\80सà¥\87à¤\9f à¤\95ियà¥\87 à¤\9cानà¥\87 à¤\95à¥\80 à¤\9cरà¥\82रत à¤¹à¥\88। à¤\95à¥\83पया à¤\85ब à¤\8fà¤\95 à¤¨à¤¯à¤¾ à¤ªà¤¾à¤¸à¤µà¤°à¥\8dड à¤\9aà¥\81नà¥\87à¤\82, à¤¯à¤¾ à¤¬à¤¾à¤¦ à¤®à¥\87à¤\82 à¤ªà¥\81नरà¥\8dसà¥\8dथापित à¤\95रनà¥\87 à¤\95à¥\87 à¤²à¤¿à¤\8f ' à¤°à¤¦à¥\8dद à¤\95रà¥\87à¤\82 ' क्लिक करें।",
+'resetpass-expired' => 'à¤\86पà¤\95à¥\87 à¤ªà¤¾à¤¸à¤µà¤°à¥\8dड à¤\95à¥\80 à¤µà¥\88धता à¤\85वधि à¤¸à¤®à¤¾à¤ªà¥\8dत à¤¹à¥\8b à¤\9aà¥\81à¤\95à¥\80 à¤¹à¥\88। à¤\95à¥\83पया à¤²à¥\89à¤\97 इन करने के लिए एक नया पासवर्ड सेट करें।',
+'resetpass-expired-soft' => "à¤\86पà¤\95ा à¤ªà¤¾à¤¸à¤µà¤°à¥\8dड à¤\95à¥\80 à¤µà¥\88धता à¤\85वधि à¤¸à¤®à¤¾à¤ªà¥\8dत à¤¹à¥\8b à¤\97यà¥\80 à¤¹à¥\88, à¤\94र à¤\89सà¥\87 à¤°à¥\80सà¥\87à¤\9f à¤\95रनà¥\87 à¤\95à¥\80 à¤\9c़रà¥\82रत à¤¹à¥\88। à¤\95à¥\83पया à¤\8fà¤\95 à¤¨à¤¯à¤¾ à¤ªà¤¾à¤¸à¤µà¤°à¥\8dड à¤\9aà¥\81नà¥\87à¤\82, à¤¯à¤¾ à¤¬à¤¾à¤¦ à¤®à¥\87à¤\82 à¤°à¥\80सà¥\87à¤\9f à¤\95रनà¥\87 à¤\95à¥\87 à¤²à¤¿à¤\8f 'रदà¥\8dद à¤\95रà¥\87à¤\82' à¤ªà¤° क्लिक करें।",
 
 # Special:PasswordReset
 'passwordreset' => 'कूटशब्द रीसेट',
@@ -1133,7 +1133,7 @@ $2
 'rev-deleted-comment' => '(सम्पादन सारांश हटाया)',
 'rev-deleted-user' => '(सदस्यनाम हटाया)',
 'rev-deleted-event' => '(लॉग कार्य हटाया)',
-'rev-deleted-user-contribs' => 'संशोधन उपयोगकर्ता योगदान नष्ट',
+'rev-deleted-user-contribs' => '[सदस्यनाम अथवा आइ॰पी पता छुपाया गया - सम्पादन योगदानों में से छुपाया गया]',
 'rev-deleted-text-permission' => 'यह पृष्ठ अवतरण हटाया गया है।
 इसकी अधिक जानकारी [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} हटाने की लॉग] में पाई जा सकती है।',
 'rev-deleted-text-unhide' => 'यह पृष्ठ अवतरण हटाया गया है।
@@ -1635,15 +1635,27 @@ HTML टैग की जाँच करें।',
 'rcnotefrom' => "नीचे '''$2''' के बाद से ('''$1''' तक) हुए बदलाव दर्शाए गये हैं।",
 'rclistfrom' => '$1 से नये बदलाव दिखाएँ',
 'rcshowhideminor' => 'छोटे बदलाव $1',
+'rcshowhideminor-show' => 'दिखाएँ',
+'rcshowhideminor-hide' => 'छुपाएँ',
 'rcshowhidebots' => 'बॉट $1',
+'rcshowhidebots-show' => 'दिखाएँ',
+'rcshowhidebots-hide' => 'छुपाएँ',
 'rcshowhideliu' => 'पंजीकृत सदस्य $1',
+'rcshowhideliu-show' => 'दिखाएँ',
+'rcshowhideliu-hide' => 'छुपाएँ',
 'rcshowhideanons' => 'आइ॰पी सदस्यों के बदलाव $1',
+'rcshowhideanons-show' => 'दिखाएँ',
+'rcshowhideanons-hide' => 'छुपाएँ',
 'rcshowhidepatr' => 'परीक्षित सम्पादन $1',
+'rcshowhidepatr-show' => 'दिखाएँ',
+'rcshowhidepatr-hide' => 'छुपाएँ',
 'rcshowhidemine' => 'मेरे बदलाव $1',
+'rcshowhidemine-show' => 'दिखाएँ',
+'rcshowhidemine-hide' => 'छुपाएँ',
 'rclinks' => 'पिछले $2 दिनों में हुए $1 बदलाव दिखाएँ<br />$3',
 'diff' => 'अंतर',
 'hist' => 'इतिहास',
-'hide' => 'à¤\9bिपाएँ',
+'hide' => 'à¤\9bà¥\81पाएँ',
 'show' => 'दिखाएँ',
 'minoreditletter' => 'छो',
 'newpageletter' => 'न',
@@ -1770,6 +1782,7 @@ HTML टैग की जाँच करें।',
 'php-uploaddisabledtext' => 'पी॰एच॰पी में फ़ाइल अपलोड बंद हैं।
 कृपया file_uploads जमाव की जाँच करें।',
 'uploadscripted' => 'इस फ़ाइल में एच॰टी॰एम॰एल या स्क्रिप्ट कोड है, जो वेब ब्राउज़र द्वारा गलत पढ़ा जा सकता है।',
+'uploadinvalidxml' => 'अपलोड की गई फ़ाइल में स्थित XML पार्स नहीं की जा सकी।',
 'uploadvirus' => 'इस फ़ाइल में व्हाईरस हैं! अधिक जानकारी: $1',
 'uploadjava' => 'यह फ़ाइल एक ज़िप फ़ाइल है जिसमें एक जावा .class फ़ाइल है।
 जावा फ़ाइलों को अपलोड करना वर्जित है, क्योंकि इनके कारण सुरक्षा बाधाएँ पार की जा सकती हैं।',
@@ -2145,13 +2158,16 @@ https://www.mediawiki.org/wiki/Manual:Image_Authorization देखें।',
 'protectedpages-cascade' => 'केवल सोपानी सुरक्षा',
 'protectedpages-noredirect' => 'पुनर्निर्देश छुपाएँ',
 'protectedpagesempty' => 'इस समय इन नियमों द्वारा कोई पृष्ठ सुरक्षित नहीं हैं।',
-'protectedpages-timestamp' => 'à¤\9fाà¤\87म à¤®à¥\8bहर',
+'protectedpages-timestamp' => 'समय à¤®à¥\81हर',
 'protectedpages-page' => 'पृष्ठ',
-'protectedpages-expiry' => 'समाप्ति:',
-'protectedpages-performer' => 'à¤\89पयà¥\8bà¤\97à¤\95रà¥\8dता à¤\95à¥\80 à¤¸à¥\81रà¤\95à¥\8dषा',
-'protectedpages-params' => 'सà¤\82रà¤\95à¥\8dषण à¤ªà¥\88रामà¥\80à¤\9fरà¥\8dस',
+'protectedpages-expiry' => 'समाप्ति',
+'protectedpages-performer' => 'सà¥\81रà¤\95à¥\8dषित à¤\95रनà¥\87 à¤µà¤¾à¤²à¤¾ à¤¸à¤¦à¤¸à¥\8dय',
+'protectedpages-params' => 'सà¥\81रà¤\95à¥\8dषा à¤ªà¥\8dराà¤\9aल',
 'protectedpages-reason' => 'कारण',
+'protectedpages-unknown-timestamp' => 'अज्ञात',
+'protectedpages-unknown-performer' => 'अज्ञात सदस्य',
 'protectedtitles' => 'सुरक्षित शीर्षक',
+'protectedtitles-summary' => 'यह पृष्ठ उन पृष्ठ शीर्षकों की सूची देता है जिन्हें अभी बनाने से सुरक्षित किया गया है। सुरक्षित मौजूदा पृष्ठों की सूची देखने के लिए [[{{#special:ProtectedPages}}]] देखें।',
 'protectedtitlesempty' => 'इन नियमों द्वारा कोई भी शीर्षक सुरक्षित नहीं हैं।',
 'listusers' => 'सदस्यसूची',
 'listusers-editsonly' => 'केवल संपादन कर चुके सदस्य दिखाएँ',
@@ -2337,7 +2353,7 @@ https://www.mediawiki.org/wiki/Manual:Image_Authorization देखें।',
 'watchmethod-list' => 'ध्यानसूची में दिये गये पृष्ठों में हाल में हुए बदलाव देख रहे हैं',
 'watchlistcontains' => 'आपकी ध्यानसूची में $1 {{PLURAL:$1|पृष्ठ}} हैं।',
 'iteminvalidname' => "'$1' के साथ समस्या, अवैध नाम...",
-'wlnote2' => '$2,$3 तक आखरी {{PLURAL:$1|घंटे|<strong>$1</strong>घंटों}} में बदलाव निम्नलिखित हैं।',
+'wlnote2' => '$2,$3 तक आखरी {{PLURAL:$1|घंटे|<strong>$1</strong> घंटों}} में बदलाव निम्नलिखित हैं।',
 'wlshowlast' => 'पिछले $1 घंटे $2 दिन $3 देखें',
 'watchlist-options' => 'ध्यानसूची विकल्प',
 
@@ -2427,6 +2443,7 @@ $UNWATCHURL
 'delete-warning-toobig' => 'इस पृष्ठ का संपादन इतिहास $1 से अधिक {{PLURAL:$1|अवतरण}} होने की वजह से बहुत बड़ा है।
 इसे हटाने से {{SITENAME}} के डाटाबेस की गतिविधियों में व्यवधान आ सकता है;
 कृपया सोच समझ कर आगे बढ़ें।',
+'deleting-backlinks-warning' => "'''चेतावनी:''' जो पृष्ठ आप हटाने जा रहे हैं उससे अन्य पृष्ठ जुड़ते हैं अथवा उसे ट्रांसक्लूड करते हैं।",
 
 # Rollback
 'rollback' => 'संपादन वापिस लें',
@@ -2466,6 +2483,7 @@ $2 द्वारा संपादित अन्तिम अवतरण 
 'prot_1movedto2' => '[[$1]] का नाम बदलकर [[$2]] कर दिया गया है',
 'protect-badnamespace-title' => 'सुरक्षाहीन नामस्थान',
 'protect-badnamespace-text' => 'इस नामस्थान में पृष्ठ सुरक्षित नहीं किये जा सकते हैं।',
+'protect-norestrictiontypes-text' => 'यह पृष्ठ सुरक्षित नहीं किया जा सकता क्योंकि कोई सुरक्षा प्रकार उपलब्ध नहीं हैं।',
 'protect-legend' => 'सुरक्षा निर्धारित करें',
 'protectcomment' => 'कारण:',
 'protectexpiry' => 'समाप्ति:',
@@ -2682,7 +2700,7 @@ $1',
 'blocklist-tempblocks' => 'अस्थाई अवरोध छिपाएं',
 'blocklist-addressblocks' => 'एकल आईपी अवरोध छिपाएं',
 'blocklist-rangeblocks' => 'श्रेणी ब्लॉक छुपाएँ',
-'blocklist-timestamp' => 'à¤\9fाà¤\87मसà¥\8dà¤\9fà¥\88मà¥\8dप',
+'blocklist-timestamp' => 'समय à¤®à¥\81हर',
 'blocklist-target' => 'लक्ष्य',
 'blocklist-expiry' => 'अवसान',
 'blocklist-by' => 'प्रशासक अवरुद्ध',
@@ -2744,7 +2762,8 @@ $1 को अवरोधित करने का कारण है: "$2"',
 कृपया आप अपने इंटरनेट सेवा प्रदान करने वाले से या तकनीकी सहायक से सम्पर्क करें अथवा उन्हें इस भयावह सुरक्षा समस्या के बारे में सूचित करें।',
 'sorbsreason' => '{{SITENAME}} द्वारा इस्तेमालमें लाये जाने वाले DNSBL में आपके आईपी एड्रेसको ओपन प्रॉक्सीमें दर्शाया गया हैं।',
 'sorbs_create_account_reason' => '{{SITENAME}} के DNSBL ने आपका आईपी एड्रेस ओपन प्रोक्सी करके सूचित किया हैं। आप खाता खोल नहीं सकतें।',
-'cant-see-hidden-user' => 'कठबोली छुपा उपयोगकर्ता देखना',
+'cant-see-hidden-user' => 'जिस सदस्य को आप अवरोधित करने की कोशिश कर रहे हैं उसे पहले ही अवरोधित कर के छुपाया जा चुका है।
+चूँकि आपके पास hideuser अधिकार नहीं है, आप इस सदस्य का अवरोधन ना देख सकते हैं और ना ही सम्पादित कर सकते हैं।',
 'ipbblocked' => 'आप अन्य प्रयोक्ताओं को अवरोधित या अनवरोधित नहीं कर सकते, क्योंकि आप स्वयं अवरोधित हैं',
 'ipbnounblockself' => 'आपको स्वयं को अनवरोधित करने की अनुमति नहीं है',
 
@@ -2808,7 +2827,7 @@ $1 को अवरोधित करने का कारण है: "$2"',
 
 इन मामलोंमे आपको स्वयं यह पृष्ठ जोडने पड़ सकते है ।",
 'movearticle' => 'पृष्ठ का नाम बदलें',
-'moveuserpage-warning' => 'चाल उपयोगकर्ता चेतावनी पृष्ठ',
+'moveuserpage-warning' => '<strong>चेतावनी:</strong> आप एक सदस्य पृष्ठ स्थानांतरित करने जा रहे हैं। कृपया ध्यान दें कि केवल पृष्ठ का नाम बदला जाएगा और सदस्यनाम <em>नहीं</em> बदलेगा।',
 'movenologintext' => 'लेख स्थानान्तरित करने के लिये आपका [[Special:UserLogin|लॉग इन]] किया होना आवश्यक हैं।',
 'movenotallowed' => 'आपको पृष्ठ स्थानांतरित करने की अनुमति नहीं है।',
 'movenotallowedfile' => 'आपको फ़ाइलें स्थानांतरित करने की अनुमति नहीं है।',
@@ -2862,7 +2881,8 @@ $1 को अवरोधित करने का कारण है: "$2"',
 नवीनतम लॉग प्रविष्टि संदर्भ के लिये नीचे दी है:",
 'move-over-sharedrepo' => '== फ़ाइल मौजूद है ==
 [[:$1]] एक साझे भंडार पर मौजूद है। इस नाम पर स्थानांतरण से नई फ़ाइल साझा फ़ाइल को ओवरराइड करेगी।',
-'file-exists-sharedrepo' => 'फ़ाइल रेपो साझा मौजूद',
+'file-exists-sharedrepo' => 'चयनित फ़ाइल नाम पहले ही एक साझा भण्डार में प्रयुक्त है।
+कृपया अन्य नाम चुनें।',
 
 # Export
 'export' => 'पन्नों का निर्यात करें',
@@ -3168,7 +3188,8 @@ $1',
 'nextdiff' => 'ताज़ा संपादन →',
 
 # Media information
-'mediawarning' => 'चेतावनी मीडिया',
+'mediawarning' => '<strong>चेतावनी:</strong> इस फ़ाइल प्रकार में हानिकारक कोड हो सकता है।
+संभव है कि इसे चलाने से आपका सिस्टम हैक हो जाये।',
 'imagemaxsize' => "छवि आकार सीमा:<br />''(संचिका वर्णन पन्नों के लिए)''",
 'thumbsize' => 'अंगूठानख आकार:',
 'widthheightpage' => '$1 × $2, $3 {{PLURAL:$3|पृष्ठ|पृष्ठ}}',
@@ -3876,8 +3897,16 @@ $5
 'version-hook-subscribedby' => 'ने सदस्यत्व लिया',
 'version-version' => '($1)',
 'version-license' => 'मीडियाविकि अनुज्ञापत्र',
+'version-ext-license' => 'लाइसेंस',
+'version-ext-colheader-name' => 'एक्सटेंशन',
+'version-ext-colheader-version' => 'संस्करण',
+'version-ext-colheader-license' => 'लाइसेंस',
 'version-ext-colheader-description' => 'विवरण',
 'version-ext-colheader-credits' => 'लेखक',
+'version-license-title' => '$1 के लिए लाइसेंस',
+'version-license-not-found' => 'इस एक्सटेंशन के लिए कोई विस्तृत लाइसेंस जानकारी नहीं पायी गयी।',
+'version-credits-title' => '$1 के लिए श्रेय',
+'version-credits-not-found' => 'इस एक्सटेंशन के लिए कोई विस्तृत श्रेय जानकारी नहीं पायी गयी।',
 'version-poweredby-credits' => "यह विकि  '''[https://www.mediawiki.org/ MediaWiki]''' द्वारा संचालित है, कॉपीराइट © 2001 - $1  $2 ।",
 'version-poweredby-others' => 'अन्य',
 'version-poweredby-translators' => 'translatewiki.net अनुवादक',
@@ -3887,6 +3916,8 @@ $5
 'version-entrypoints-header-url' => 'यू॰आर॰एल',
 
 # Special:Redirect
+'redirect-submit' => 'जायें',
+'redirect-lookup' => 'ढूँढें:',
 'redirect-user' => 'सदस्य आई॰डी',
 'redirect-revision' => 'पृष्ठ अवतरण संख्या',
 'redirect-file' => 'फ़ाइल नाम',
@@ -3943,7 +3974,10 @@ $5
 'tags-tag' => 'चिप्पी का नाम',
 'tags-display-header' => 'बदलाव सूचियों में प्रदर्शन',
 'tags-description-header' => 'अर्थ का पूरा वर्णन',
+'tags-active-header' => 'सक्रिय?',
 'tags-hitcount-header' => 'चिप्पी वाले बदलाव',
+'tags-active-yes' => 'हाँ',
+'tags-active-no' => 'नहीं',
 'tags-edit' => 'सम्पादन',
 'tags-hitcount' => '$1 {{PLURAL:$1|बदलाव|बदलाव}}',
 
@@ -3963,6 +3997,7 @@ $5
 'dberr-problems' => 'क्षमा करें! इस जालस्थल को कुछ तकनीकी परेशानियों का सामना करना पड़ रहा है।',
 'dberr-again' => 'कुछ मिनट रुकने के बाद फिर से चढ़ाएँ।',
 'dberr-info' => '(आँकड़ाकोष सेवक से संपर्क नहीं हो पा रहा:$1)',
+'dberr-info-hidden' => '(डाटाबेस सर्वर से संपर्क नहीं किया जा सका)',
 'dberr-usegoogle' => 'इस बीच आप गूगल से खोज करने की कोशिश कर सकते हैं।',
 'dberr-outofdate' => 'ध्यान दे, हो सकता है कि हमारी सामग्री से संबंधित उनकी सूची बासी हो।',
 'dberr-cachederror' => 'यह अनुरोधित पन्ने की संचित प्रति है, हो सकता है यह ताज़ी न हो।',
@@ -4094,6 +4129,16 @@ $5
 'duration-centuries' => '$1 {{PLURAL:$1|शताब्दी}}',
 'duration-millennia' => '$1 {{PLURAL:$1|सहस्राब्दी}}',
 
+# Limit report
+'limitreport-cputime-value' => '$1 {{PLURAL:$1|सॅकेंड}}',
+'limitreport-walltime-value' => '$1 {{PLURAL:$1|सॅकेंड}}',
+'limitreport-postexpandincludesize' => 'विस्तार उपरांत विकिपाठ आकार',
+'limitreport-postexpandincludesize-value' => '$1/$2 {{PLURAL:$2|बाइट}}',
+'limitreport-templateargumentsize' => 'साँचा प्राचल आकार',
+'limitreport-templateargumentsize-value' => '$1/$2 {{PLURAL:$2|बाइट}}',
+'limitreport-expansiondepth' => 'उच्चतम विस्तार गहराई',
+'limitreport-expensivefunctioncount' => 'महंगे पार्सर फंक्शनों की संख्या',
+
 # Special:ExpandTemplates
 'expandtemplates' => 'साँचा विस्तार',
 'expand_templates_intro' => 'यह विशेष पृष्ठ पाठ इनपुट लेता है और सभी साँचों को विस्तृत करता है।
@@ -4110,6 +4155,4 @@ $5
 'expand_templates_generate_xml' => 'XML का पार्स (parse) वृक्ष दर्शायें',
 'expand_templates_preview' => 'झलक',
 
-# Unknown messages
-'uploadinvalidxml' => 'अपलोड की गई फ़ाइल में स्थित XML पार्स नहीं की जा सकी।',
 );
index eb498f7..e530b37 100644 (file)
@@ -500,7 +500,7 @@ $messages = array(
 'searcharticle' => 'Kreni',
 'history' => 'Stare izmjene',
 'history_short' => 'Stare izmjene',
-'updatedmarker' => 'obnovljeno od zadnjeg posjeta',
+'updatedmarker' => 'obnovljeno od posljednjeg posjeta',
 'printableversion' => 'Inačica za ispis',
 'permalink' => 'Trajna poveznica',
 'print' => 'Ispiši',
@@ -540,7 +540,7 @@ $messages = array(
 'otherlanguages' => 'Drugi jezici',
 'redirectedfrom' => '(Preusmjereno s $1)',
 'redirectpagesub' => 'Preusmjeravanje',
-'lastmodifiedat' => 'Datum zadnje promjene na ovoj stranici: $2, $1',
+'lastmodifiedat' => 'Vrijeme i datum posljednje promjene na ovoj stranici: $2, $1',
 'viewcount' => 'Ova stranica je pogledana {{PLURAL:$1|$1 put|$1 puta}}.',
 'protectedpage' => 'Zaštićena stranica',
 'jumpto' => 'Skoči na:',
@@ -587,7 +587,7 @@ $1',
 'youhavenewmessagesfromusers' => 'Imate $1 {{PLURAL:$3||od $3 suradnika|od $3 suradnika}} ($2).',
 'youhavenewmessagesmanyusers' => 'Imate $1 od više suradnika ($2).',
 'newmessageslinkplural' => '{{PLURAL:$1|novu poruku|$1 nove poruke|$1 novih poruka}}',
-'newmessagesdifflinkplural' => '{{PLURAL:$1|zadnje uređivanje|zadnja $1 uređivanja|zadnjih $1 uređivanja}} na stranici za razgovor',
+'newmessagesdifflinkplural' => '{{PLURAL:$1|posljednje uređivanje|posljednja $1 uređivanja|posljednjih $1 uređivanja}} na stranici za razgovor',
 'youhavenewmessagesmulti' => 'Imate nove poruke na $1',
 'editsection' => 'uredi',
 'editold' => 'uredi',
@@ -675,7 +675,9 @@ Nema obrazloženja ili poruke o pogrješci.',
 'badtitle' => 'Loš naslov',
 'badtitletext' => 'Navedeni naslov stranice nepravilan ili loše formirana interwiki poveznica.',
 'perfcached' => 'Sljedeći podaci su iz međuspremnika i možda nisu najsvježiji. Međuspremnik sadrži $1 {{PLURAL:$1|rezultat|rezultata}} pretraživanja.',
-'perfcachedts' => 'Sljedeći podaci su iz međuspremnika i zadnji puta su ažurirani u $1. Međuspremnik sadrži $4 {{PLURAL:$4|rezultat|rezultata}} pretraživanja.',
+'perfcachedts' => 'Sljedeći podaci su iz međuspremnika i posljednji puta su ažurirani u $1. Međuspremnik sadrži $4 {{PLURAL:$4|rezultat|rezultata}} pretraživanja.
+
+Više o ovoj [[Wikipedija:Posebne stranice|posebnoj stranici]] na [[Razgovor Wikipedija:Special:{{PAGENAME}}]].',
 'querypage-no-updates' => 'Osvježavanje ove stranice je trenutačno onemogućeno. Nove promjene neće biti vidljive.',
 'viewsource' => 'Vidi izvornik',
 'viewsource-title' => 'Vidi kôd stranice $1',
@@ -815,7 +817,7 @@ koristiti staru lozinku.',
 'blocked-mailpassword' => 'Vašoj IP adresi je blokirano uređivanje stranica, a da bi se spriječila nedopuštena radnja, mogućnost zahtijevanja nove lozinke je također onemogućena.',
 'eauthentsent' => 'Na navedenu adresu poslana je e-poruka s potvrdom.
 Prije nego što pošaljemo daljnje poruke, molimo Vas otvorite e-poruku i slijedite u njemu sadržana uputstva kako biste potvrdili da je adresa e-pošte zaista Vaša.',
-'throttled-mailpassword' => 'Već Vam je poslan e-mail za promjenu zaporke, u {{PLURAL:$1|zadnjih sat vremena|zadnja $1 sata|zadnjih $1 sati}}.
+'throttled-mailpassword' => 'Već Vam je poslan e-mail za promjenu zaporke, u {{PLURAL:$1|posljednjih sat vremena|posljednja $1 sata|posljednjih $1 sati}}.
 Da bi spriječili zloupotrebu, moguće je poslati samo jedan e-mail za promjenu zaporke {{PLURAL:$1|svakih sat vremena|svaka $1 sata|svakih $1 sati}}.',
 'mailerror' => 'Pogrješka pri slanju e-pošte: $1',
 'acct_creation_throttle_hit' => 'Posjetitelji ovog wikija koji rabe Vašu IP adresu napravili su {{PLURAL:$1|1 račun|$1 računa}} u posljednjem danu, što je najveći dopušteni broj u tom vremenskom razdoblju.
@@ -1144,7 +1146,7 @@ Neki predlošci neće biti uključeni.',
 'converter-manual-rule-error' => 'Pronađena je pogrješka u pravilu ručnog prijevoda',
 
 # "Undo" feature
-'undo-success' => 'Izmjena je uklonjena (tekst u okviru ispod ne sadrži zadnju izmjenu). Molim sačuvajte stranicu (provjerite sažetak).',
+'undo-success' => 'Izmjena je uklonjena (tekst u okviru ispod ne sadrži posljednju izmjenu). Molim sačuvajte stranicu (provjerite sažetak).',
 'undo-failure' => 'Ova izmjena ne može biti uklonjena zbog postojanja međuinačica.',
 'undo-norev' => 'Izmjena nije mogla biti uklonjena jer ne postoji ili je obrisana.',
 'undo-summary' => 'Uklanjanje izmjene $1 što ju je unio/unijela [[Special:Contributions/$2|$2]] ([[User talk:$2|razgovor]])',
@@ -1588,7 +1590,7 @@ Ne smije biti duži od $1 {{PLURAL:$1|znaka|znaka|znakova}}.',
 'right-viewmyprivateinfo' => 'Vidite svoje privatne podatke (npr. adresu e-pošte, stvarno ime)',
 'right-editmyprivateinfo' => 'Uredite svoje privatne podatke (npr. adresa e-pošte, stvarno ime)',
 'right-editmyoptions' => 'Uredite svoje postavke',
-'right-rollback' => 'Brzo uklanjanje izmjena zadnjeg suradnika na određenoj stranici',
+'right-rollback' => 'Brzo uklanjanje izmjena posljednjeg suradnika na određenoj stranici',
 'right-markbotedits' => 'Označavanje uklonjenih izmjena kao izmjenu bota',
 'right-noratelimit' => 'Bez vremenskog ograničenja uređivanja',
 'right-import' => 'Uvoženje stranica s drugih wikija',
@@ -1677,7 +1679,7 @@ Ne smije biti duži od $1 {{PLURAL:$1|znaka|znaka|znakova}}.',
 'rcshowhideanons' => '$1 neprijavljene suradnike',
 'rcshowhidepatr' => '$1 provjerene promjene',
 'rcshowhidemine' => '$1 moje promjene',
-'rclinks' => 'Prikaži zadnjih $1 promjena u zadnjih $2 dana; $3',
+'rclinks' => 'Prikaži posljednjih $1 promjena {{PLURAL:$2|prethodni dan|u posljednja $2 dana|u posljednjih $2 dana}}<br />$3',
 'diff' => 'razl',
 'hist' => 'pov',
 'hide' => 'sakrij',
@@ -2233,7 +2235,7 @@ Podržani {{PLURAL:$2|protokol|protokoli}}: <code>$1</code> (default je http://
 
 # Special:ActiveUsers
 'activeusers' => 'Popis aktivnih suradnika',
-'activeusers-intro' => 'Ovo je popis suradnika koji su napravili neku aktivnost u {{PLURAL:$1|zadnji $1 dan|zadnja $1 dana|zadnjih $1 dana}}.',
+'activeusers-intro' => 'Ovo je popis suradnika koji su napravili neku aktivnost u {{PLURAL:$1|posljednji $1 dan|posljednja $1 dana|posljednjih $1 dana}}.',
 'activeusers-count' => '{{PLURAL:$1|nedavna $1 izmjena|nedavne $1 izmjene|nedavnih $1 izmjena}} u {{PLURAL:$3|posljednji $3 dan|posljednja $3 dana|posljednjih $3 dana}}',
 'activeusers-from' => 'Prikaži suradnike počevši od:',
 'activeusers-hidebots' => 'Sakrij botove',
@@ -2320,12 +2322,12 @@ Promjene na toj stranici i njenoj stranici za razgovor bit će prikazane na popi
 'notvisiblerev' => 'Izmjena je obrisana',
 'watchlist-details' => '{{PLURAL:$1|$1 stranica|$1 stranice|$1 stranica}} se nalazi na popisu praćenja, ne brojeći stranice za razgovor.',
 'wlheader-enotif' => 'Uključeno je izvješćivanje e-poštom.',
-'wlheader-showupdated' => "Stranice koje su promijenjene od Vašeg zadnjeg posjeta prikazane su '''podebljano'''",
+'wlheader-showupdated' => "Stranice koje su promijenjene od Vašeg posljednjeg posjeta prikazane su '''podebljano'''",
 'watchmethod-recent' => 'provjera nedavnih promjena praćenih stranica',
 'watchmethod-list' => 'provjera praćanih stranica za nedavne promjene',
 'watchlistcontains' => 'Vaš popis praćenja sadrži $1 {{PLURAL:$1|stranicu|stranice|stranica}}.',
 'iteminvalidname' => "Problem s izborom '$1', ime nije valjano...",
-'wlshowlast' => 'Prikaži zadnjih $1 sati $2 dana $3',
+'wlshowlast' => 'Prikaži posljednjih $1 sati $2 dana $3',
 'watchlist-options' => 'Izbornik popisa praćenja',
 
 # Displayed when you click the "watch" button and it is in the process of watching
@@ -2355,11 +2357,11 @@ $PAGEINTRO $NEWPAGE
 
 Sažetak urednika: $PAGESUMMARY $PAGEMINOREDIT
 
-Možete kontaktirati suradnika koji je zadnji uređivao stranicu:
+Možete kontaktirati suradnika koji je posljednji uređivao stranicu:
 mail: $PAGEEDITOR_EMAIL
 wiki: $PAGEEDITOR_WIKI
 
-Do Vašeg ponovnog posjeta stranici nećete dobivati nove obavijesti. Postavke za izvješćivanje možete resetirati za sve praćene stranice svog popisa praćenja.
+Do Vašeg ponovnog posjeta stranici nećete dobivati nove obavijesti. Postavke za izvješćivanje možete vratiti na prvotno zadane za sve praćene stranice svog popisa praćenja.
 
 Vaš sustav izvješćivanja {{SITENAME}}.
 
@@ -2423,10 +2425,10 @@ Sva vremena su prema poslužiteljevom vremenu.',
 
 Posljednju promjenu napravio je [[User:$3|$3]] ([[User talk:$3|Razgovor]]{{int:pipe-separator}}[[Special:Contributions/$3|{{int:contribslink}}]]).',
 'editcomment' => "Sažetak promjene je bio: \"''\$1''\".",
-'revertpage' => 'Uklonjena promjena suradnika $2, vraćeno na zadnju inačicu suradnika $1',
+'revertpage' => 'Uklonjena promjena suradnika $2, vraćeno na posljednju inačicu suradnika $1',
 'revertpage-nouser' => 'Vraćene izmjene suradnika (suradničko ime uklonjeno) na posljednju inačicu suradnika [[User:$1|$1]]',
 'rollback-success' => 'Uklonjeno uređivanje {{GENDER:$1|suradnika|suradnice}} $1
-vraćeno na zadnju inačicu {{GENDER:$2|suradnika|suradnice}} $2.',
+vraćeno na posljednju inačicu {{GENDER:$2|suradnika|suradnice}} $2.',
 
 # Edit tokens
 'sessionfailure-title' => 'Prekid sesije',
@@ -2511,7 +2513,7 @@ Baza se povremeno čisti od ovakvih stranica.',
 Ako želite vratiti određene izmjene, označite ih i kliknite '''''{{int:undeletebtn}}'''''.",
 'undeleterevisions' => '$1 {{PLURAL:$1|inačica je arhivirana|inačice su arhivirane|inačica je arhivirano}}',
 'undeletehistory' => 'Ako vratite izbrisanu stranicu, bit će vraćene i sve prijašnje promjene. Ako je u međuvremenu stvorena nova stranica s istim imenom, vraćena stranica bit će upisana kao prijašnja promjena sadašnje.',
-'undeleterevdel' => 'Vraćanje stranice neće biti izvršeno ako je rezultat toga djelomično brisanje zadnjeg uređivanja.
+'undeleterevdel' => 'Vraćanje stranice neće biti izvršeno ako je rezultat toga djelomično brisanje posljednjeg uređivanja.
 U takvim slučajevima morate isključiti ili otkriti najnovije obrisane promjene.',
 'undeletehistorynoadmin' => 'Ovaj je članak izbrisan. Razlog za brisanje prikazan je u donjem sažetku, zajedno s
 detaljima o suradnicima koji su uređivali ovu stranicu prije brisanja.
@@ -3018,7 +3020,7 @@ Snimite je na svoje računalo i postavite je ovdje.',
 'tooltip-watchlistedit-raw-submit' => 'Osvježi popis praćenja',
 'tooltip-recreate' => 'Vrati stranicu unatoč tome što je obrisana',
 'tooltip-upload' => "Pokreni snimanje (''upload'')",
-'tooltip-rollback' => '"Ukloni" uklanja uređivanja zadnjeg suradnika na ovoj stranici.',
+'tooltip-rollback' => '"Ukloni" uklanja uređivanja posljednjeg suradnika na ovoj stranici.',
 'tooltip-undo' => '"Ukloni ovu izmjenu" uklanja ovu izmjenu i otvara okvir za uređivanje. Omogućava unošenje razloga u sažetak.',
 'tooltip-preferences-save' => 'Spremi postavke',
 'tooltip-summary' => 'Unesite kratki sažetak',
@@ -3038,7 +3040,7 @@ Snimite je na svoje računalo i postavite je ovdje.',
 'anonymous' => 'Neprijavljeni {{PLURAL:$1|suradnik|suradnici}} projekta {{SITENAME}}',
 'siteuser' => 'Suradnik $1 na projektu {{SITENAME}}',
 'anonuser' => '{{SITENAME}} anonimni suradnik $1',
-'lastmodifiedatby' => 'Ovu je stranicu zadnji put mijenjao dana $2, $1 suradnik $3.',
+'lastmodifiedatby' => 'Ovu je stranicu posljednji put {{GENDER:$4|mijenjao suradnik|mijenjala suradnica}} $3 dana $1 u $2.',
 'othercontribs' => 'Temelji se na doprinosu suradnika $1.',
 'others' => 'drugih',
 'siteusers' => '{{SITENAME}} {{PLURAL:$2|suradnik|suradnici}} $1',
@@ -3052,7 +3054,7 @@ Snimite je na svoje računalo i postavite je ovdje.',
 Razlog je vjerojatno vanjska poveznica koja se nalazi na crnom popisu.',
 'spamprotectionmatch' => 'Naš filtar spama reagirao je na sljedeći tekst: $1',
 'spambot_username' => 'MediaWiki zaštita od spama',
-'spam_reverting' => 'Vraćam na zadnju inačicu koja ne sadrži poveznice na $1',
+'spam_reverting' => 'Vraćam na posljednju inačicu koja ne sadrži poveznice na $1',
 'spam_blanking' => 'Sve inačice sadrže poveznice na $1, brišem cjelokupni sadržaj',
 'spam_deleting' => 'Sve inačice sadržale su poveznice na $1, brišem cjelokupni sadržaj',
 'simpleantispam-label' => "Anti-spam provjera.
@@ -3081,10 +3083,10 @@ Razlog je vjerojatno vanjska poveznica koja se nalazi na crnom popisu.',
 'pageinfo-firstuser' => 'Suradnik koji je stvorio stranicu',
 'pageinfo-firsttime' => 'Datum stvaranja stranice',
 'pageinfo-lastuser' => 'Posljednji urednik stranice',
-'pageinfo-lasttime' => 'Datum zadnjeg uređivanja',
+'pageinfo-lasttime' => 'Datum posljednjeg uređivanja',
 'pageinfo-edits' => 'Ukupan broj uređivanja',
 'pageinfo-authors' => 'Broj različitih autora',
-'pageinfo-recent-edits' => 'Broj uređivanja (u zadnjih $1)',
+'pageinfo-recent-edits' => 'Broj uređivanja (u posljednjih $1)',
 'pageinfo-recent-authors' => 'Broj različitih autora u gornjem razdoblju',
 'pageinfo-magic-words' => '{{PLURAL:$1|Magična riječ - varijabla|Magične riječi - varijable}} ($1)',
 'pageinfo-hidden-categories' => '{{PLURAL:$1|Postoji|Postoje|Postoji}} $1 {{PLURAL:$1|skrivena kategorija|skrivene kategorije|skrivenih kategorija}}',
@@ -3167,7 +3169,7 @@ Njegovim izvršavanjem mogli biste oštetiti svoj sustav.",
 # Special:NewFiles
 'newimages' => 'Galerija novih datoteka',
 'imagelisttext' => 'Ispod je popis {{PLURAL:$1|$1 slike|$1 slike|$1 slika}} složen $2.',
-'newimages-summary' => 'Ova posebna stranica pokazuje zadnje nedavno postavljene datoteke.',
+'newimages-summary' => 'Ova posebna stranica pokazuje posljednje nedavno postavljene datoteke.',
 'newimages-legend' => 'Filtar',
 'newimages-label' => 'Naziv datoteke (ili njen dio):',
 'showhidebots' => '($1 botova)',
@@ -3244,7 +3246,7 @@ Svaka sljedeća poveznica u istom retku je izuzetak, npr. kod stranica gdje se s
 'exif-primarychromaticities' => 'Kromaticitet primarnih boja',
 'exif-ycbcrcoefficients' => 'Matrični koeficijenti preobrazbe kolor prostora',
 'exif-referenceblackwhite' => 'Mjesto bijele i crne točke',
-'exif-datetime' => 'Datum zadnje promjene datoteke',
+'exif-datetime' => 'Datum posljednje promjene datoteke',
 'exif-imagedescription' => 'Ime slike',
 'exif-make' => 'Proizvođač kamere',
 'exif-model' => 'Model kamere',
@@ -3374,7 +3376,7 @@ Svaka sljedeća poveznica u istom retku je izuzetak, npr. kod stranica gdje se s
 'exif-serialnumber' => 'Serijski broj kamere',
 'exif-cameraownername' => 'Vlasnik kamere',
 'exif-label' => 'Oznaka',
-'exif-datetimemetadata' => 'Datum zadnje promjene metapodataka',
+'exif-datetimemetadata' => 'Datum posljednje promjene metapodataka',
 'exif-nickname' => 'Neformalni naziv slike',
 'exif-rating' => 'Ocjena (od 5)',
 'exif-rightscertificate' => 'Certifikat za upravljanje pravima',
@@ -3736,8 +3738,8 @@ Potvrdite namjeru vraćanja ovog članka.",
 'livepreview-error' => 'Spajanje nije uspjelo: $1 "$2". Pokušajte normalni pretpregled.',
 
 # Friendlier slave lag warnings
-'lag-warn-normal' => 'Moguće je da izmjene nastale zadnjih $1 {{PLURAL:$1|sekundu|sekundi}} neće biti vidljive na ovom popisu.',
-'lag-warn-high' => 'Zbog kašnjenja baze podataka, moguće je da promjene napravljene u zadnjih $1 {{PLURAL:$1|sekundu|sekunde|sekundi}} nisu prikazane u popisu.',
+'lag-warn-normal' => 'Moguće je da izmjene nastale posljednjih $1 {{PLURAL:$1|sekundu|sekundi}} neće biti vidljive na ovom popisu.',
+'lag-warn-high' => 'Zbog kašnjenja baze podataka, moguće je da promjene napravljene u posljednjih $1 {{PLURAL:$1|sekundu|sekunde|sekundi}} nisu prikazane u popisu.',
 
 # Watchlist editor
 'watchlistedit-numitems' => 'Vaš popis praćenja sadrži {{PLURAL:$1|1 stranicu|$1 stranica}}, bez stranica za razgovor.',
index 183f4e9..c42c9a4 100644 (file)
@@ -715,7 +715,7 @@ Zo by přizjewjenje skónčił, dyrbiš tu nowe hesło postajić:',
 'resetpass-temp-password' => 'Nachwilne hesło:',
 'resetpass-abort-generic' => 'Měnjenje hesła je so přez rozšěrjenje přetorhnyło.',
 'resetpass-expired' => 'Twoje hesło je spadnyło. Prošu postaj nowe hesło za přizjewjenje.',
-'resetpass-expired-soft' => 'Twoje hesło je spadnyło a dyrbi so wróćo stajić. Prošu wubjer nětko druhe hesło abo klikń na "Přetorhnyć", zo by jo pozdźišo wróćo stajił.',
+'resetpass-expired-soft' => 'Twoje hesło je spadnyło a dyrbi so wróćo stajić. Prošu wubjer nětko druhe hesło abo klikń na "{{int:resetpass-submit-cancel}}", zo by jo pozdźišo wróćo stajił.',
 
 # Special:PasswordReset
 'passwordreset' => 'Hesło wróćo stajić',
@@ -1545,14 +1545,26 @@ Tuta informacija budźe zjawna.',
 'recentchanges-legend-heading' => "'''Legenda:'''",
 'recentchanges-legend-newpage' => '(hlej tež [[Special:NewPages|lisćinu nowych stronow]])',
 'recentchanges-legend-plusminus' => "(''±123'')",
-'rcnotefrom' => "Deleka so změny wot '''$2''' pokazuja (hač k '''$1''').",
+'rcnotefrom' => 'Deleka so změny wot <strong>$2</strong> pokazuja (hač k <strong>$1</strong>).',
 'rclistfrom' => 'Nowe změny pokazać, započinajo z $1',
 'rcshowhideminor' => 'snadne změny $1',
+'rcshowhideminor-show' => 'Pokazać',
+'rcshowhideminor-hide' => 'Schować',
 'rcshowhidebots' => 'Boćiki $1',
+'rcshowhidebots-show' => 'Pokazać',
+'rcshowhidebots-hide' => 'Schować',
 'rcshowhideliu' => 'Zregistrowani wužiwarjo $1',
+'rcshowhideliu-show' => 'Pokazać',
+'rcshowhideliu-hide' => 'Schować',
 'rcshowhideanons' => 'Anonymni wužiwarjo $1',
+'rcshowhideanons-show' => 'Pokazać',
+'rcshowhideanons-hide' => 'Schować',
 'rcshowhidepatr' => 'Dohladowane změny $1',
+'rcshowhidepatr-show' => 'Pokazać',
+'rcshowhidepatr-hide' => 'Schować',
 'rcshowhidemine' => 'moje změny $1',
+'rcshowhidemine-show' => 'Pokazać',
+'rcshowhidemine-hide' => 'Schować',
 'rclinks' => 'Poslednje $1 změnow poslednich $2 dnjow pokazać<br />$3',
 'diff' => 'rozdźěl',
 'hist' => 'wersije',
@@ -1678,6 +1690,8 @@ Jeli maš tutón wobraz z połnym rozeznaćom, nahraj tutón, hewak změń proš
 'uploaddisabledtext' => 'Nahraće datajow je znjemóžnjene.',
 'php-uploaddisabledtext' => 'Nahraća PHP-datajow su znjemóžnjene. Prošu skontroluj nastajenje file_uploads.',
 'uploadscripted' => 'Dataja wobsahuje HTML- abo skriptowy kod, kotryž móhł so mylnje přez wobhladowak wuwjesć.',
+'uploadscriptednamespace' => "Tuta SVG-dataja wobsahuje njedowoleny mjenowy rum '$1'",
+'uploadinvalidxml' => 'XML w nahratej dataji njeda so parsować.',
 'uploadvirus' => 'Dataja wirus wobsahuje! Podrobnosće: $1',
 'uploadjava' => 'Tuta dataja je ZIP-dataja, kotraž .class-dataju z Javy wobsahuje.
 Nahraće datajow Javy njeje dowolene, dokelž móhli wobeńdźenje wěstotnych wobmjezowanjow zmóžnić.',
@@ -2493,6 +2507,7 @@ Najnowši zapisk w protokolu blokowanjow so deleka jako referenca podawa:',
 'sp-contributions-search' => 'Přinoški pytać',
 'sp-contributions-username' => 'IP-adresa abo wužiwarske mjeno:',
 'sp-contributions-toponly' => 'Jenož wyše wersije pokazać',
+'sp-contributions-newonly' => 'Jenož změny pokazać, kotrež su wutworjenja stronow',
 'sp-contributions-submit' => 'OK',
 
 # What links here
@@ -3982,6 +3997,4 @@ Hewak móžeš slědowacy jednory formular wužiwać. Twój komentar přida so s
 'expand_templates_generate_rawhtml' => 'Hruby HTML pokazać',
 'expand_templates_preview' => 'Přehlad',
 
-# Unknown messages
-'uploadinvalidxml' => 'XML w nahratej dataji njeda so parsować.',
 );
index 8d18257..ce10c35 100644 (file)
@@ -848,6 +848,9 @@ Várj $1, mielőtt újra próbálkozol.',
 'loginlanguagelabel' => 'Nyelv: $1',
 'suspicious-userlogout' => 'A kijelentkezési kérésed vissza lett utasítva, mert úgy tűnik, hogy egy hibás böngésző vagy gyorsítótárazó proxy küldte.',
 'createacct-another-realname-tip' => 'A valódi nevet nem kötelező megadni, de ha úgy döntesz, hogy megadod, azzal leszel feltüntetve a munkád szerzőjeként.',
+'pt-login' => 'Bejelentkezés',
+'pt-createaccount' => 'Fiók létrehozása',
+'pt-userlogout' => 'Kijelentkezés',
 
 # Email sending
 'php-mail-error-unknown' => 'Ismeretlen hiba a PHP mail() függvényében',
@@ -864,14 +867,20 @@ Várj $1, mielőtt újra próbálkozol.',
 'retypenew' => 'Új jelszó ismét:',
 'resetpass_submit' => 'Add meg a jelszót és jelentkezz be',
 'changepassword-success' => 'A jelszavad megváltoztatása sikeresen befejeződött!',
+'changepassword-throttled' => 'Túl sok hibás bejelentkezés.
+Várj $1, mielőtt újra próbálkozol.',
 'resetpass_forbidden' => 'A jelszavak nem változtathatók meg',
 'resetpass-no-info' => 'Be kell jelentkezned, hogy közvetlenül elérd ezt a lapot.',
 'resetpass-submit-loggedin' => 'Jelszó megváltoztatása',
 'resetpass-submit-cancel' => 'Mégse',
 'resetpass-wrong-oldpass' => 'Nem megfelelő ideiglenes vagy jelenlegi jelszó.
 Lehet, hogy már sikeresen megváltoztattad a jelszavad, vagy pedig időközben új ideiglenes jelszót kértél.',
+'resetpass-recycled' => 'Kérlek más jelszót adjál meg, mint a jelenlegi jelszavad.',
+'resetpass-temp-emailed' => 'Emailben kapott ideiglenes kóddal jelentkeztél be. A végleges bejelentkezéshez új jelszót kell beállítanod itt:',
 'resetpass-temp-password' => 'Ideiglenes jelszó:',
 'resetpass-abort-generic' => 'A jelszómódosítást megszakította egy kiterjesztés.',
+'resetpass-expired' => 'A jelszavad lejárt. Adjál meg egy új jelszót a bejelentkezéshez!',
+'resetpass-expired-soft' => 'A jelszavad lejárt, ezért újat kell beállítanod. Válassz most egy új jelszót, vagy kattints a {{int:resetpass-submit-cancel}} gombra, ha később akarod csak beállítani.',
 
 # Special:PasswordReset
 'passwordreset' => 'Jelszó törlése',
@@ -913,6 +922,17 @@ Ideiglenes jelszó: $2',
 'changeemail-password' => 'A {{SITENAME}} jelszavad:',
 'changeemail-submit' => 'E-mail cím megváltoztatása',
 'changeemail-cancel' => 'Mégse',
+'changeemail-throttled' => 'Túl sok hibás bejelentkezés.
+Várj $1, mielőtt újra próbálkozol.',
+
+# Special:ResetTokens
+'resettokens' => 'Tokenek törlése',
+'resettokens-no-tokens' => 'Nincs újragenerálható token.',
+'resettokens-legend' => 'Tokenek újragenerálása',
+'resettokens-tokens' => 'Tokenek:',
+'resettokens-token-label' => '$1 (jelenlegi érték: $2)',
+'resettokens-done' => 'Tokenek újragenerálva.',
+'resettokens-resetbutton' => 'Kijelőlt tokenek újragenerálása',
 
 # Edit page toolbar
 'bold_sample' => 'Félkövér szöveg',
@@ -1117,6 +1137,7 @@ Már létezik.',
 'content-not-allowed-here' => '"$1" tartalom nem engedélyezett a [[$2]] oldalon',
 'editwarning-warning' => 'A lap elhagyásával az összes itt végzett változtatás elveszhet.
 Ha be vagy jelentkezve letilthatod ezt a figyelmeztetést a beállításaid „{{int:prefs-editing}}” szakaszában.',
+'editpage-notsupportedcontentformat-title' => 'Nem támogatott tartalom formátum',
 
 # Content models
 'content-model-wikitext' => 'wikiszöveg',
@@ -1149,6 +1170,7 @@ Néhány sablon nem fog megjelenni.',
 'undo-success' => 'A szerkesztés visszavonható. Kérlek ellenőrizd alább a változásokat, hogy valóban ezt szeretnéd-e tenni, majd kattints a lap mentése gombra a visszavonás véglegesítéséhez.',
 'undo-failure' => 'A szerkesztést nem lehet automatikusan visszavonni vele ütköző későbbi szerkesztések miatt.',
 'undo-norev' => 'A szerkesztés nem állítható vissza, mert nem létezik vagy törölve lett.',
+'undo-nochange' => 'A szerkesztés már vissza lett állítva.',
 'undo-summary' => 'Visszavontam [[Special:Contributions/$2|$2]] ([[User talk:$2|vita]] | [[Special:Contributions/$2|{{MediaWiki:Contribslink}}]]) szerkesztését (oldid: $1)',
 
 # Account creation failure
@@ -1238,7 +1260,7 @@ A(z) {{SITENAME}} adminisztrátorai továbbra is meg tudják tekinteni az elrejt
 * Illetlen személyes információk
 *: ''otthoni cím, telefonszámok, társadalombiztosítási számok stb.''",
 'revdelete-legend' => 'Korlátozások megadása:',
-'revdelete-hide-text' => 'Változat szövegének elrejtése',
+'revdelete-hide-text' => 'Változat szövege',
 'revdelete-hide-image' => 'A fájl tartalmának elrejtése',
 'revdelete-hide-name' => 'Művelet és cél elrejtése',
 'revdelete-hide-comment' => 'Szerkesztési összefoglaló',
@@ -1661,14 +1683,26 @@ A műveletet nem lehet visszavonni.',
 'recentchanges-label-plusminus' => 'Az oldal mérete ennyi bájttal módosult',
 'recentchanges-legend-heading' => 'Jelmagyarázat:',
 'recentchanges-legend-newpage' => '(lásd még: [[Special:NewPages|Új lapok]])',
-'rcnotefrom' => 'Alább a <b>$2</b> óta történt változtatások láthatóak (<b>$1</b> db).',
+'rcnotefrom' => 'Alább a <b>$2</b> óta történt változtatások láthatóak (legfeljebb <b>$1</b> db).',
 'rclistfrom' => '$1 után történt változtatások megtekintése',
 'rcshowhideminor' => 'apró szerkesztések $1',
+'rcshowhideminor-show' => 'megjelenítése',
+'rcshowhideminor-hide' => 'elrejtése',
 'rcshowhidebots' => 'botok szerkesztéseinek $1',
+'rcshowhidebots-show' => 'megjelenítése',
+'rcshowhidebots-hide' => 'elrejtése',
 'rcshowhideliu' => 'bejelentkezett szerkesztők szerkesztéseinek $1',
+'rcshowhideliu-show' => 'megjelenítése',
+'rcshowhideliu-hide' => 'elrejtése',
 'rcshowhideanons' => 'névtelen szerkesztések $1',
+'rcshowhideanons-show' => 'megjelenítése',
+'rcshowhideanons-hide' => 'elrejtése',
 'rcshowhidepatr' => 'ellenőrzött szerkesztések $1',
+'rcshowhidepatr-show' => 'megjelenítése',
+'rcshowhidepatr-hide' => 'elrejtése',
 'rcshowhidemine' => 'saját szerkesztések $1',
+'rcshowhidemine-show' => 'megjelenítése',
+'rcshowhidemine-hide' => 'elrejtése',
 'rclinks' => 'Az elmúlt $2 nap utolsó $1 változtatása legyen látható<br />$3',
 'diff' => 'eltér',
 'hist' => 'történet',
@@ -2310,8 +2344,8 @@ Feladóként a [[Special:Preferences|beállításaid]]nál megadott e-mail-címe
 'watchnologin' => 'Nem vagy bejelentkezve',
 'watchnologintext' => 'Ahhoz, hogy figyelőlistád lehessen, [[Special:UserLogin|be kell lépned]].',
 'addwatch' => 'Hozzáadás a figyelőlistához',
-'addedwatchtext' => "A(z) „[[:$1]]” lapot hozzáadtam a [[Special:Watchlist|figyelőlistádhoz]].
-Ezután minden, a lapon vagy annak vitalapján történő változást ott fogsz látni, és a lap '''vastagon''' fog szerepelni a [[Special:RecentChanges|friss változtatások]] lapon, hogy könnyen észrevehető legyen.",
+'addedwatchtext' => 'A(z) „[[:$1]]” lapot hozzáadtam a [[Special:Watchlist|figyelőlistádhoz]].
+Ezután minden, a lapon vagy annak vitalapján történő változást ott fogsz látni.',
 'removewatch' => 'Eltávolítás a figyelőlistáról',
 'removedwatchtext' => 'A(z) „[[:$1]]” lapot eltávolítottam a [[Special:Watchlist|figyelőlistáról]].',
 'watch' => 'Lap figyelése',
@@ -2361,9 +2395,9 @@ A szerkesztő elérhetősége:
 e-mail küldése: $PAGEEDITOR_EMAIL
 wiki: $PAGEEDITOR_WIKI
 
-Amíg nem keresed fel az oldalt, addig nem érkeznek újabb értesítések az oldal változásaival kapcsolatban. A figyelőlistádon is beállíthatod, hogy újból kapj értesítéseket, az összes lap után.
+Amíg nem keresed fel az oldalt bejelentkezve, addig nem érkeznek újabb értesítések az oldal változásaival kapcsolatban. A figyelőlistádon is beállíthatod, hogy újból kapj értesítéseket, az összes lap után.
 
-             Baráti üdvözlettel: a(z) {{SITENAME}} értesítő rendszere
+Baráti üdvözlettel: a(z) {{SITENAME}} értesítő rendszere
 
 --
 Az e-mail értesítéseid módosításához keresd fel a 
@@ -2708,7 +2742,7 @@ Add meg a blokkolás okát is (például idézd a blokkolandó személy által v
 'range_block_disabled' => 'A rendszerfelelős tartományblokkolás létrehozási képessége letiltott.',
 'ipb_expiry_invalid' => 'Hibás lejárati dátum.',
 'ipb_expiry_temp' => 'A láthatatlan felhasználóinév-blokkok lehetnek állandóak.',
-'ipb_hide_invalid' => 'A felhasználói fiókot nem lehet elrejteni; lehet, hogy túl sok szerkesztése van.',
+'ipb_hide_invalid' => 'A felhasználói fiókot nem lehet elrejteni; több mint $1 szerkesztése van.',
 'ipb_already_blocked' => '"$1" már blokkolva',
 'ipb-needreblock' => '$1 már blokkolva van. Meg szeretnéd változtatni a beállításokat?',
 'ipb-otherblocks-header' => 'További {{PLURAL:$1|blokk|blokkok}}',
@@ -2931,7 +2965,7 @@ Mentsd el a számítógépedre, majd töltsd fel ide.',
 'importuploaderrortemp' => 'Az importálandó fájl feltöltése nem sikerült. Nem létezik ideiglenes mappa.',
 'import-parse-failure' => 'XML elemzési hiba importáláskor',
 'import-noarticle' => 'Nincs importálandó lap!',
-'import-nonewrevisions' => 'A korábban importált összes változat.',
+'import-nonewrevisions' => 'Nincs változat importálva (mindet korábban importálták vagy a hiba miatt program kihagyta).',
 'xml-error-string' => '$1 a(z) $2. sorban, $3. oszlopban ($4. bájt): $5',
 'import-upload' => 'XML-adatok feltöltése',
 'import-token-mismatch' => 'Elveszett a session adat, próbálkozz újra.',
@@ -3100,7 +3134,7 @@ Ez valószínűleg egy olyan link miatt van, ami egy feketelistán lévő oldalr
 'pageinfo-views' => 'Megtekintések száma',
 'pageinfo-watchers' => 'Figyelők száma',
 'pageinfo-few-watchers' => 'Kevesebb mint $1 szerkesztő figyeli',
-'pageinfo-redirects-name' => 'Átirányítások erre a lapra',
+'pageinfo-redirects-name' => 'Átirányítások száma erre a lapra',
 'pageinfo-subpages-name' => 'A lap allapjai',
 'pageinfo-subpages-value' => '$1 ($2 {{PLURAL:$2|átirányítás}}; $3 {{PLURAL:$3|nem átirányítás}})',
 'pageinfo-firstuser' => 'A lap létrehozója',
@@ -3822,7 +3856,7 @@ minden egyes sor egy figyelt lap címe. Ha kész vagy, kattints a lista alatt ta
 'version-hook-name' => 'Hook neve',
 'version-hook-subscribedby' => 'Használja',
 'version-version' => '(verzió: $1)',
-'version-license' => 'Licenc',
+'version-license' => 'MediaWiki licenc',
 'version-poweredby-credits' => "Ez a wiki '''[https://www.mediawiki.org/ MediaWiki]''' szoftverrel működik, copyright © 2001-$1 $2.",
 'version-poweredby-others' => 'mások',
 'version-poweredby-translators' => 'translatewiki.net fordítók',
@@ -3947,14 +3981,14 @@ A MediaWikit abban a reményben terjesztjük, hogy hasznos lesz, de GARANCIA NÉ
 'logentry-delete-delete' => '$1 törölte a következő lapot: $3',
 'logentry-delete-restore' => '$1 helyreállította a következő lapot: $3',
 'logentry-delete-event' => '$1 megváltoztatta {{PLURAL:$5|egy napló bejegyzés|$5 napló bejegyzés}} láthatóságát a(z) $3 című lapon: $4',
-'logentry-delete-revision' => '$1 módosította a(z) $3 című lap {{PLURAL:$5|egy|$1}} lapváltozatának láthatóságát: $4',
-'logentry-delete-event-legacy' => '$1 módosította a(z) $3 című lap naplóbejegyzéseinek láthatóságát',
-'logentry-delete-revision-legacy' => '$1 módosította a(z) $3 című lap lapváltozatainak láthatóságát',
-'logentry-suppress-delete' => '$1 elrejtette a következő lapot: $3',
-'logentry-suppress-event' => '$1 rejtetten megváltoztatta {{PLURAL:$5|egy napló bejegyzés|$5 napló bejegyzés}} láthatóságát a(z) $3 című lapon: $4',
+'logentry-delete-revision' => '$1 {{GENDER:$2|módosította}} a(z) $3 című lap {{PLURAL:$5|egy|$5}} lapváltozatának láthatóságát: $4',
+'logentry-delete-event-legacy' => '$1 {{GENDER:$2|módosította}} a(z) $3 című lap naplóbejegyzéseinek láthatóságát',
+'logentry-delete-revision-legacy' => '$1 {{GENDER:$2|módosította}} a(z) $3 című lap lapváltozatainak láthatóságát',
+'logentry-suppress-delete' => '$1 {{GENDER:$2|elrejtette}} a következő lapot: $3',
+'logentry-suppress-event' => '$1 rejtetten {{GENDER:$2|megváltoztatta}} {{PLURAL:$5|egy|$5}} naplóbejegyzés láthatóságát a(z) $3 című lapon: $4',
 'logentry-suppress-revision' => '$1 rejtetten megváltoztatta {{PLURAL:$5|egy változat|$5 változat}} láthatóságát a(z) $3 című lapon: $4',
-'logentry-suppress-event-legacy' => '$1 rejtetten megváltoztatta napló bejegyzések láthatóságát a(z) $3 című lapon',
-'logentry-suppress-revision-legacy' => '$1 rejtetten megváltoztatta változatok láthatóságát a(z) $3 lapon',
+'logentry-suppress-event-legacy' => '$1 rejtetten {{GENDER:$2|megváltoztatta}} napló bejegyzések láthatóságát a(z) $3 című lapon',
+'logentry-suppress-revision-legacy' => '$1 rejtetten {{GENDER:$2|megváltoztatta}} változatok láthatóságát a(z) $3 lapon',
 'revdelete-content-hid' => 'tartalom elrejtve',
 'revdelete-summary-hid' => 'szerkesztési összefoglaló elrejtve',
 'revdelete-uname-hid' => 'szerkesztő elrejtve',
@@ -3967,13 +4001,13 @@ A MediaWikit abban a reményben terjesztjük, hogy hasznos lesz, de GARANCIA NÉ
 'logentry-move-move-noredirect' => '$1 átnevezte a(z) $3 lapot $4 lapra átirányítás nélkül',
 'logentry-move-move_redir' => '$1 átnevezte a(z) $3 lapot $4 lapra az átirányítást felülírva',
 'logentry-move-move_redir-noredirect' => '$1 átnevezte a(z) $3 lapot $4 lapra az átirányítást felülírva, átirányítás nélkül',
-'logentry-patrol-patrol' => '$1 a(z) $3 lap $4 változatát ellenőrzöttnek jelölte',
-'logentry-patrol-patrol-auto' => '$1 a(z) $3 lap $4 változatát automatikusan ellenőrzöttnek jelölte',
-'logentry-newusers-newusers' => '$1 felhasználói fiók létrehozva',
+'logentry-patrol-patrol' => '$1 a(z) $3 lap $4 változatát ellenőrzöttnek {{GENDER:$2|jelölte}}',
+'logentry-patrol-patrol-auto' => '$1 a(z) $3 lap $4 változatát automatikusan ellenőrzöttnek {{GENDER:$2|jelölte}}',
+'logentry-newusers-newusers' => '$1 felhasználói fiók {{GENDER:$2|létrehozva}}',
 'logentry-newusers-create' => '$1 felhasználói fiók létrehozva',
 'logentry-newusers-create2' => '$1 létrehozta $3 felhasználói fiókját',
 'logentry-newusers-byemail' => 'Szerkesztői lap $3 néven létrehozva $1 által, jelszó kiküldve emailben.',
-'logentry-newusers-autocreate' => '$1 fiók automatikusan létrehozva',
+'logentry-newusers-autocreate' => '$1 felhasználói fiók automatikusan létrehozva',
 'logentry-rights-rights' => '$1 megváltoztatta $3 csoporttagságát erről: $4 erre: $5',
 'logentry-rights-rights-legacy' => '$1 megváltoztatta $3 csoporttagságát',
 'logentry-rights-autopromote' => '$1 automatikusan előléptetve erről: $4 erre: $5',
@@ -4054,10 +4088,14 @@ A MediaWikit abban a reményben terjesztjük, hogy hasznos lesz, de GARANCIA NÉ
 # Image rotation
 'rotate-comment' => 'Elforgattam a képet $1 fokkal, az óramutató járásával megegyező irányban',
 
+# Limit report
+'limitreport-postexpandincludesize-value' => '$1/$2 {{PLURAL:$2|bájt}}',
+'limitreport-templateargumentsize-value' => '$1/$2 {{PLURAL:$2|bájt}}',
+
 # Special:ExpandTemplates
 'expandtemplates' => 'Sablonok kibontása',
 'expand_templates_intro' => 'Ez a speciális lap a bevitt szövegekben megkeresi a sablonokat és rekurzívan kibontja őket.
-Kibontja az elemző függvényeket (pl. <nowiki>{{</nowiki>#language:...}}), és a változókat (pl. <nowiki>{{</nowiki>CURRENTDAY}}) is – mindent, ami a kettős kapcsos zárójelek között van.',
+Kibontja a támogatott elemző függvényeket (pl. <code><nowiki>{{</nowiki>#language:...}}</code>), és a változókat (pl. <code><nowiki>{{</nowiki>CURRENTDAY}}</code>) is – mindent, ami a kettős kapcsos zárójelek között van.',
 'expand_templates_title' => 'Szöveg címe, például {{FULLPAGENAME}} sablonhoz:',
 'expand_templates_input' => 'Vizsgálandó szöveg',
 'expand_templates_output' => 'Eredmény',
index 4213e01..711de69 100644 (file)
@@ -1606,11 +1606,23 @@ Si tu opta pro dar lo, isto essera usate pro dar te attribution pro tu contribut
 'rcnotefrom' => 'infra es le modificationes a partir de <b>$2</b> (usque a <b>$1</b>).',
 'rclistfrom' => 'Monstrar nove modificationes a partir de $1',
 'rcshowhideminor' => '$1 modificationes minor',
+'rcshowhideminor-show' => 'Monstrar',
+'rcshowhideminor-hide' => 'Celar',
 'rcshowhidebots' => '$1 bots',
+'rcshowhidebots-show' => 'Monstrar',
+'rcshowhidebots-hide' => 'Celar',
 'rcshowhideliu' => '$1 usatores registrate',
+'rcshowhideliu-show' => 'Monstrar',
+'rcshowhideliu-hide' => 'Celar',
 'rcshowhideanons' => '$1 usatores anonyme',
+'rcshowhideanons-show' => 'Monstrar',
+'rcshowhideanons-hide' => 'Celar',
 'rcshowhidepatr' => '$1 modificationes patruliate',
+'rcshowhidepatr-show' => 'Monstrar',
+'rcshowhidepatr-hide' => 'Celar',
 'rcshowhidemine' => '$1 mi modificationes',
+'rcshowhidemine-show' => 'Monstrar',
+'rcshowhidemine-hide' => 'Celar',
 'rclinks' => 'Monstrar le $1 ultime modificationes in le $2 ultime dies<br />$3',
 'diff' => 'diff',
 'hist' => 'hist',
@@ -1740,6 +1752,8 @@ Si tu vole totevia incargar iste file, per favor retorna e usa un nove nomine. [
 'uploaddisabledtext' => 'Le incargamento de files es disactivate.',
 'php-uploaddisabledtext' => 'Le incargamento de files PHP es disactivate. Per favor verifica le configuration file_uploads.',
 'uploadscripted' => 'Iste file contine codice de HTML o de script que pote esser interpretate erroneemente per un navigator del web.',
+'uploadscriptednamespace' => 'Iste file SVG contine un spatio de nomines invalide: "$1"',
+'uploadinvalidxml' => 'Le codice XML in le file incargate non pote esser interpretate.',
 'uploadvirus' => 'Le file contine un virus! Detalios: $1',
 'uploadjava' => 'Iste file es un archivo ZIP que contine un file .class de Java.
 Non es permittite incargar files Java, proque istes pote contornar le restrictiones de securitate.',
@@ -2464,10 +2478,10 @@ Ecce le configurationes actual del pagina '''$1''':",
 Ecce le configurationes actual del pagina '''$1''':",
 'protect-cascadeon' => 'Iste pagina es actualmente protegite proque illo es includite in le sequente {{PLURAL:$1|pagina, le qual|paginas, le quales}} ha activate le protection in cascada.
 Tu pote cambiar le nivello de protection de iste pagina, ma isto non cambiara le effecto del protection in cascada.',
-'protect-default' => 'Permitter tote le usatores',
-'protect-fallback' => 'Permitter solmente usatores con le permission de "$1"',
-'protect-level-autoconfirmed' => 'Permitter solmente usatores autoconfirmate',
-'protect-level-sysop' => 'Permitter solmente administratores',
+'protect-default' => 'Permitter tote le usatores',
+'protect-fallback' => 'Permitter solmente al usatores con le privilegio de "$1"',
+'protect-level-autoconfirmed' => 'Permitter solmente al usatores autoconfirmate',
+'protect-level-sysop' => 'Permitter solmente al administratores',
 'protect-summary-cascade' => 'in cascada',
 'protect-expiring' => 'expira le $1 (UTC)',
 'protect-expiring-local' => 'expira le $1',
@@ -2591,6 +2605,7 @@ Le ultime entrata del registro de blocadas es reproducite hic infra pro informat
 'sp-contributions-search' => 'Cercar contributiones',
 'sp-contributions-username' => 'Adresse IP o nomine de usator:',
 'sp-contributions-toponly' => 'Monstrar solmente le versiones recente',
+'sp-contributions-newonly' => 'Monstrar solmente le modificationes que es creationes de pagina',
 'sp-contributions-submit' => 'Cercar',
 
 # What links here
@@ -3093,7 +3108,7 @@ Le causa es probabilemente un ligamine verso un sito externe que es presente in
 '''NON''' completa isto!",
 
 # Info page
-'pageinfo-title' => 'Informationes pro "$1"',
+'pageinfo-title' => 'Information sur "$1"',
 'pageinfo-not-current' => 'Regrettabilemente, il es impossibile fornir iste information pro versiones ancian.',
 'pageinfo-header-basic' => 'Information de base',
 'pageinfo-header-edits' => 'Historia de modificationes',
@@ -4136,6 +4151,4 @@ De facto, illo expande quasi toto inter accolladas duple.',
 'expand_templates_generate_rawhtml' => 'Monstrar HTML brute',
 'expand_templates_preview' => 'Previsualisation',
 
-# Unknown messages
-'uploadinvalidxml' => 'Le codice XML in le file incargate non pote esser interpretate.',
 );
index 30c11cd..6eb78c3 100644 (file)
@@ -1890,6 +1890,7 @@ Anda harus meminta bantuan seseorang dengan kemampuan untuk melihat data berkas
 'uploaddisabledtext' => 'Pemuatan berkas tidak diizinkan.',
 'php-uploaddisabledtext' => 'Pemuatan berkas dimatikan di PHP. Silakan cek pengaturan file_uploads.',
 'uploadscripted' => 'Berkas ini mengandung HTML atau kode yang dapat diinterpretasikan dengan keliru oleh penjelajah web.',
+'uploadinvalidxml' => 'XML dalam berkas yang diunggah tidak bisa diuraikan.',
 'uploadvirus' => 'Berkas tersebut mengandung virus! Rincian: $1',
 'uploadjava' => 'Berkas ini adalah berkas ZIP yang mengnadung berkas .class Java.
 Penggunggahan berkas Java tidak diperbolehkan karena dapat menyebabkan pengabaian batasan keamanan.',
@@ -4364,6 +4365,4 @@ Jika tidak, Anda dapat menggunakan formulir mudah di bawah ini. Komentar Anda ak
 'expand_templates_generate_rawhtml' => 'Tampilkan HTML mentah',
 'expand_templates_preview' => 'Pratayang',
 
-# Unknown messages
-'uploadinvalidxml' => 'XML dalam berkas yang diunggah tidak bisa diuraikan.',
 );
index c2bcc7a..29e3636 100644 (file)
@@ -1633,6 +1633,7 @@ Nasken nga agdamagka ti addaan ti abilidad a mangkita ti nalapdan a datos ti pap
 'php-uploaddisabledtext' => 'Ti pinag-ipan ti papeles ket naiddep idiay PHP.
 Panngaasi a kitaem ti pannakaikabil ti pinag-ipan ti papeles.',
 'uploadscripted' => 'Daytoy a papeles ket adda nagyanna a HTML wenno panagsurat a kodigo a mabalin nga agpakamali ti panagbasa ti sapot a pagbasabasa.',
+'uploadinvalidxml' => 'Ti XML iti naikarga a papeles ket saan a maiwaswas.',
 'uploadvirus' => 'Addaan ti birus daytoy a papeles! Salaysay: $1',
 'uploadjava' => 'Daytoy a papeles ket ZIP a papeles nga adda nagyanna a Java .a kita ti papeles.
 Saan a mabalin ti pinag-ipan ti Java a papeles, ngamin ket palabsanda dagiti seguridad a pangrestrikto.',
@@ -3981,6 +3982,4 @@ Iti kinapudno, palawaenna amin dagiti adda ti doble a tukol.',
 'expand_templates_generate_rawhtml' => 'Ipakita ti naata a HTML',
 'expand_templates_preview' => 'Pamadasan',
 
-# Unknown messages
-'uploadinvalidxml' => 'Ti XML iti naikarga a papeles ket saan a maiwaswas.',
 );
index 04522fa..ea5b7e7 100644 (file)
@@ -1621,11 +1621,23 @@ Tölvupóstfang þitt er ekki gefið upp þegar aðrir notendur hafa samband vi
 'rcnotefrom' => "Að neðan eru breytingar síðan '''$2''' (allt að '''$1''' sýndar).",
 'rclistfrom' => 'Sýna breytingar frá og með $1',
 'rcshowhideminor' => '$1 minniháttar breytingar',
+'rcshowhideminor-show' => 'Sýna',
+'rcshowhideminor-hide' => 'Fela',
 'rcshowhidebots' => '$1 vélmenni',
+'rcshowhidebots-show' => 'Sýna',
+'rcshowhidebots-hide' => 'Fela',
 'rcshowhideliu' => '$1 skráðir notendur',
+'rcshowhideliu-show' => 'Sýna',
+'rcshowhideliu-hide' => 'Fela',
 'rcshowhideanons' => '$1 óinnskráða notendur',
+'rcshowhideanons-show' => 'Sýna',
+'rcshowhideanons-hide' => 'Fela',
 'rcshowhidepatr' => '$1 vaktaðar breytingar',
+'rcshowhidepatr-show' => 'Sýna',
+'rcshowhidepatr-hide' => 'Fela',
 'rcshowhidemine' => '$1 mínar breytingar',
+'rcshowhidemine-show' => 'Sýna',
+'rcshowhidemine-hide' => 'Fela',
 'rclinks' => 'Sýna síðustu $1 breytingar síðustu $2 daga<br />$3',
 'diff' => 'breyting',
 'hist' => 'breytingaskrá',
@@ -3041,8 +3053,8 @@ Vinsamlegast reyndu aftur.',
 'spam_reverting' => 'Tek aftur síðustu breytingu sem inniheldur ekki tengil á $1',
 'spam_blanking' => 'Allar útgáfur innihéldu tengla á $1, tæmi síðuna',
 'spam_deleting' => 'Allar útgáfur innihéldu tengla á $1, eyði síðunni',
-'simpleantispam-label' => "Kæfuvörn.
-'''EKKI''' fylla þetta út!",
+'simpleantispam-label' => 'Kæfuvörn.
+<strong>EKKI</strong> fylla þetta út!',
 
 # Info page
 'pageinfo-title' => 'Upplýsingar um $1',
index 7e63926..79130d2 100644 (file)
@@ -39,6 +39,7 @@
  * @author Kaganer
  * @author Klutzy
  * @author Marco 27
+ * @author Maria victoria
  * @author Martorell
  * @author Marzedu
  * @author McDutchie
@@ -840,7 +841,7 @@ Attendi $1 e riprova in seguito.',
 
 # Change password dialog
 'changepassword' => 'Cambia password',
-'resetpass_announce' => 'Per completare la registrazione, è necessario impostare una nuova password.',
+'resetpass_announce' => "Per completare l'accesso, è necessario impostare una nuova password.",
 'resetpass_text' => '<!-- Aggiungere il testo qui -->',
 'resetpass_header' => "Cambia la password dell'account",
 'oldpassword' => 'Vecchia password:',
@@ -857,11 +858,11 @@ Attendi $1 e riprova in seguito.',
 'resetpass-wrong-oldpass' => 'Password temporanea o attuale non valida.
 La password potrebbe essere stata già cambiata, oppure potrebbe essere stata richiesta una nuova password temporanea.',
 'resetpass-recycled' => 'Si prega di reimpostare con una password diversa dalla password attuale.',
-'resetpass-temp-emailed' => "L'accesso è stato effettuato con un codice temporaneo, inviato via email. Per completare la registrazione, è necessario impostare una nuova password:",
+'resetpass-temp-emailed' => "L'accesso è stato effettuato con un codice temporaneo, inviato via email. Per completare la registrazione, è necessario impostare una nuova password qui:",
 'resetpass-temp-password' => 'Password temporanea:',
 'resetpass-abort-generic' => "La modifica della password è stata interrotta da un'estensione.",
 'resetpass-expired' => "La password è scaduta. Si prega di impostare una nuova password per effettuare l'accesso.",
-'resetpass-expired-soft' => 'La tua password è scaduta e deve essere reimpostata. Si prega di scegliere una nuova password o fare clic su annulla per reimpostarla successivamente.',
+'resetpass-expired-soft' => 'La tua password è scaduta e deve essere reimpostata. Si prega di scegliere una nuova password o fare clic su "{{int:resetpass-submit-cancel}}" per reimpostarla successivamente.',
 
 # Special:PasswordReset
 'passwordreset' => 'Reimposta password',
@@ -1694,14 +1695,26 @@ Il tuo indirizzo non viene rivelato quando gli altri utenti ti contattano.',
 'recentchanges-legend-heading' => "'''Legenda:'''",
 'recentchanges-legend-newpage' => "(vedi anche [[Special:NewPages|l'elenco delle nuove pagine]])",
 'recentchanges-legend-plusminus' => "(''±123'')",
-'rcnotefrom' => "Di seguito sono elencate le modifiche apportate a partire da '''$2''' (fino a '''$1''').",
+'rcnotefrom' => 'Di seguito sono elencate le modifiche apportate a partire da <strong>$2</strong> (mostrate fino a <strong>$1</strong>).',
 'rclistfrom' => 'Mostra le modifiche apportate a partire da $1',
 'rcshowhideminor' => '$1 le modifiche minori',
+'rcshowhideminor-show' => 'Mostra',
+'rcshowhideminor-hide' => 'Nascondi',
 'rcshowhidebots' => '$1 i bot',
+'rcshowhidebots-show' => 'Mostra',
+'rcshowhidebots-hide' => 'Nascondi',
 'rcshowhideliu' => '$1 gli utenti registrati',
+'rcshowhideliu-show' => 'Mostra',
+'rcshowhideliu-hide' => 'Nascondi',
 'rcshowhideanons' => '$1 gli utenti anonimi',
+'rcshowhideanons-show' => 'Mostra',
+'rcshowhideanons-hide' => 'Nascondi',
 'rcshowhidepatr' => '$1 le modifiche verificate',
+'rcshowhidepatr-show' => 'Mostra',
+'rcshowhidepatr-hide' => 'Nascondi',
 'rcshowhidemine' => '$1 le mie modifiche',
+'rcshowhidemine-show' => 'Mostra',
+'rcshowhidemine-hide' => 'Nascondi',
 'rclinks' => 'Mostra le $1 modifiche più recenti apportate negli ultimi $2 giorni<br />$3',
 'diff' => 'diff',
 'hist' => 'cron',
@@ -1818,6 +1831,8 @@ Se si dispone dell'immagine nella risoluzione originale, si prega di caricarla.
 'uploaddisabledtext' => 'Il caricamento dei file non è attivo.',
 'php-uploaddisabledtext' => 'Il caricamento di file tramite PHP è disabilitato. Controlla la configurazione di file_uploads.',
 'uploadscripted' => 'Questo file contiene codice HTML o di script, che potrebbe essere interpretato erroneamente da un browser web.',
+'uploadscriptednamespace' => "Questo file SVG contiene un namespace '$1' non consentito",
+'uploadinvalidxml' => 'Il codice XML nel file caricato non può essere elaborato.',
 'uploadvirus' => 'Questo file contiene un virus! Dettagli: $1',
 'uploadjava' => "Questo file è un file ZIP che contiene un file .class Java.
 Carica i file Java non è consentito, perché possono causare l'aggiramento delle restrizioni di sicurezza.",
@@ -2189,7 +2204,7 @@ I redirect <del>cancellati</del> sono stati corretti.',
 'protectedpages-timestamp' => 'Data e ora',
 'protectedpages-page' => 'Pagina',
 'protectedpages-expiry' => 'Scadenza',
-'protectedpages-performer' => "Protezione dell'utente",
+'protectedpages-performer' => "Protetta dall'utente",
 'protectedpages-params' => 'Parametri di protezione',
 'protectedpages-reason' => 'Motivo',
 'protectedpages-unknown-timestamp' => 'Sconosciuto',
@@ -2638,6 +2653,7 @@ $1',
 'sp-contributions-search' => 'Ricerca contributi',
 'sp-contributions-username' => 'Indirizzo IP o nome utente:',
 'sp-contributions-toponly' => 'Mostra solo i contributi che sono le ultime revisioni per la pagina',
+'sp-contributions-newonly' => 'Visualizza solo le modifiche che sono creazioni di pagina',
 'sp-contributions-submit' => 'Ricerca',
 
 # What links here
@@ -3069,6 +3085,7 @@ Tutte le operazioni di importazione trans-wiki sono registrate nel [[Special:Log
 'tooltip-undo' => '"Annulla" permette di annullare questa modifica e apre il modulo di modifica in modalità di anteprima. Permette di inserire una motivazione nell\'oggetto della modifica.',
 'tooltip-preferences-save' => 'Salva le preferenze',
 'tooltip-summary' => 'Inserire una breve sintesi',
+'interlanguage-link-title' => '$1 - $2',
 
 # Stylesheets
 'common.css' => '/* Gli stili CSS inseriti qui si applicano a tutte le skin */',
@@ -4172,6 +4189,4 @@ vale a dire praticamente tutto ciò che si trova tra doppie parentesi graffe.',
 'expand_templates_generate_rawhtml' => 'Mostra HTML',
 'expand_templates_preview' => 'Anteprima',
 
-# Unknown messages
-'uploadinvalidxml' => 'Il codice XML nel file caricato non può essere elaborato.',
 );
index 4782f9f..37176ca 100644 (file)
@@ -958,7 +958,7 @@ $1待ってから再度試してください。',
 'resetpass-temp-password' => '仮パスワード:',
 'resetpass-abort-generic' => '拡張機能により、パスワードの変更は取り消されました。',
 'resetpass-expired' => 'パスワードの有効期限が切れました。ログインするには新しいパスワードを設定してください。',
-'resetpass-expired-soft' => 'ã\83\91ã\82¹ã\83¯ã\83¼ã\83\89ã\81®æ\9c\89å\8a¹æ\9c\9fé\99\90ã\81\8cå\88\87ã\82\8cã\81\9fã\81\9fã\82\81ã\80\81å\86\8d設å®\9aã\81\99ã\82\8bå¿\85è¦\81ã\81\8cã\81\82ã\82\8aã\81¾ã\81\99ã\80\82æ\96°ã\81\97ã\81\84ã\83\91ã\82¹ã\83¯ã\83¼ã\83\89ã\82\92ä»\8aã\81\99ã\81\90設å®\9aã\81\99ã\82\8bã\81\8bã\80\81ã\81¾ã\81\9fã\81¯ã\82­ã\83£ã\83³ã\82»ã\83«をクリックしてあとで再設定してください。',
+'resetpass-expired-soft' => 'ã\83\91ã\82¹ã\83¯ã\83¼ã\83\89ã\81®æ\9c\89å\8a¹æ\9c\9fé\99\90ã\81\8cå\88\87ã\82\8cã\81\9fã\81\9fã\82\81ã\80\81å\86\8d設å®\9aã\81\99ã\82\8bå¿\85è¦\81ã\81\8cã\81\82ã\82\8aã\81¾ã\81\99ã\80\82æ\96°ã\81\97ã\81\84ã\83\91ã\82¹ã\83¯ã\83¼ã\83\89ã\82\92ä»\8aã\81\99ã\81\90設å®\9aã\81\99ã\82\8bã\81\8bã\80\81ã\81¾ã\81\9fã\81¯ã\80\8c{{int:resetpass-submit-cancel}}ã\80\8dをクリックしてあとで再設定してください。',
 
 # Special:PasswordReset
 'passwordreset' => 'パスワードの再設定',
@@ -1509,7 +1509,7 @@ $1',
 'searchrelated' => '関連',
 'searchall' => 'すべて',
 'showingresults' => '<strong>$2</strong> 件目以降の最大 {{PLURAL:$1|<strong>$1</strong> 件の結果}}を表示しています。',
-'showingresultsinrange' => '<strong>$2</strong> 件目以降の最大 {{PLURAL:$1|<strong>$1</strong> 件の結果}}を表示しています。',
+'showingresultsinrange' => '<strong>$2</strong> 件目から<strong>$3</strong> 件目までの範囲内で最大 {{PLURAL:$1|<strong>$1</strong> 件の結果}}を表示しています。',
 'showingresultsnum' => '<strong>$2</strong> 件目以降の {{PLURAL:$3|<strong>$3</strong> 件の結果}}を表示しています。',
 'showingresultsheader' => '「<strong>$4</strong>」の検索結果 {{PLURAL:$5|<strong>$3</strong> 件中の <strong>$1</strong> 件目|<strong>$3</strong> 件中の <strong>$1</strong> 件目から <strong>$2</strong> 件目}}',
 'search-nonefound' => '問い合わせに合致する検索結果はありませんでした。',
@@ -1837,13 +1837,25 @@ $1 {{PLURAL:$1|文字}}以下である必要があります。',
 'recentchanges-legend-newpage' => '([[Special:NewPages|新しいページ一覧]]も参照)',
 'recentchanges-legend-plusminus' => '(<em>±123</em>)',
 'rcnotefrom' => '以下は<strong>$2</strong>以降の更新です (最大 <strong>$1</strong> 件)。',
-'rclistfrom' => '$1以降の更新を表示する',
+'rclistfrom' => '$2 $3以降の更新を表示する',
 'rcshowhideminor' => '細部の編集を$1',
+'rcshowhideminor-show' => '表示',
+'rcshowhideminor-hide' => '非表示',
 'rcshowhidebots' => 'ボットを$1',
+'rcshowhidebots-show' => '表示',
+'rcshowhidebots-hide' => '非表示',
 'rcshowhideliu' => '登録利用者を$1',
+'rcshowhideliu-show' => '表示',
+'rcshowhideliu-hide' => '非表示',
 'rcshowhideanons' => '匿名利用者を$1',
+'rcshowhideanons-show' => '表示',
+'rcshowhideanons-hide' => '非表示',
 'rcshowhidepatr' => '巡回された編集を$1',
+'rcshowhidepatr-show' => '表示',
+'rcshowhidepatr-hide' => '非表示',
 'rcshowhidemine' => '自分の編集を$1',
+'rcshowhidemine-show' => '表示',
+'rcshowhidemine-hide' => '非表示',
 'rclinks' => '最近 $2 日間の更新を最大 $1 件表示<br />$3',
 'diff' => '差分',
 'hist' => '履歴',
@@ -1981,6 +1993,8 @@ $1 {{PLURAL:$1|文字}}以下である必要があります。',
 'php-uploaddisabledtext' => 'ファイルのアップロードがPHPで無効化されています。
 file_uploadsの設定を確認してください。',
 'uploadscripted' => 'このファイルは、ウェブブラウザーが誤って解釈してしまうおそれがあるHTMLまたはスクリプトコードを含んでいます。',
+'uploadscriptednamespace' => 'この SVG ファイルは無効な名前空間「$1」を含んでいます',
+'uploadinvalidxml' => 'アップロードされたファイルに含まれる XML が構文解析できませんでした。',
 'uploadvirus' => 'このファイルはウイルスを含んでいます!
 詳細: $1',
 'uploadjava' => 'このファイルは、Javaの.classファイルを含むZIPファイルです。
@@ -2365,8 +2379,11 @@ contenttype/subtypeの形式で入力してください (例: <code>image/jpeg</
 'protectedpages-timestamp' => '日時',
 'protectedpages-page' => 'ページ',
 'protectedpages-expiry' => '有効期限',
+'protectedpages-performer' => '保護の実行者',
+'protectedpages-params' => '保護のパラメーター',
 'protectedpages-reason' => '理由',
 'protectedpages-unknown-timestamp' => '不明',
+'protectedpages-unknown-performer' => '不明な利用者',
 'protectedtitles' => '作成保護されているページ名',
 'protectedtitles-summary' => 'このページでは、現時点で新規作成が禁止されているページ名を列挙します。保護されている既存のページの一覧は、[[{{#special:ProtectedPages}}]] を参照してください。',
 'protectedtitlesempty' => 'これらの引数で現在保護されているページはありません。',
@@ -2832,6 +2849,7 @@ $1',
 'sp-contributions-search' => '投稿の検索',
 'sp-contributions-username' => 'IPアドレスまたは利用者名:',
 'sp-contributions-toponly' => '最新版の編集のみを表示',
+'sp-contributions-newonly' => 'ページ作成を伴う編集のみを表示',
 'sp-contributions-submit' => '検索',
 
 # What links here
@@ -3185,7 +3203,7 @@ $2',
 一時フォルダーがありません。',
 'import-parse-failure' => 'XML取り込みの構文解析に失敗しました',
 'import-noarticle' => '取り込むページがありません!',
-'import-nonewrevisions' => 'すべての版は以前に取り込み済みです。',
+'import-nonewrevisions' => '版のインポートはされませんでした(すべての版が以前に取り込み済みだったか、エラーにより飛ばされたため)。',
 'xml-error-string' => '$1、$2 行の $3 文字目 ($4バイト目): $5',
 'import-upload' => 'XMLデータをアップロード',
 'import-token-mismatch' => 'セッションデータを損失しました。
@@ -4524,6 +4542,4 @@ MediaWikiは、有用であることを期待して配布されていますが
 'expand_templates_generate_rawhtml' => 'HTML ソースを表示',
 'expand_templates_preview' => 'プレビュー',
 
-# Unknown messages
-'uploadinvalidxml' => 'アップロードされたファイルに含まれる XML が構文解析できませんでした。',
 );
index 670622c..5c2af8a 100644 (file)
@@ -19,6 +19,7 @@
  * @author Malafaya
  * @author Nemo bis
  * @author Nodar Kherkheulidze
+ * @author Otogi
  * @author Reedy
  * @author Sopho
  * @author Temuri rajavi
@@ -1215,7 +1216,7 @@ $1",
 
 # Search results
 'searchresults' => 'ძიების შედეგები',
-'searchresults-title' => 'ძიების შედეგები "$1"',
+'searchresults-title' => 'ძიების შედეგები „$1“',
 'toomanymatches' => 'ნაპოვნია ძალიან ბევრი შესაბამისობა, ეცადეთ სხვა მოთხოვნა',
 'titlematches' => 'სტატიის სათაური შეესაბამება',
 'textmatches' => 'გვერდის ტექსტი შესაბამისია',
@@ -4061,11 +4062,18 @@ MediaWiki ვრცელდება იმ იმედით, რომ ი
 'rotate-comment' => 'სურათი მოტრიალებულია $1 {{PLURAL:$1|გრადუსით|გრადუსით}} საათის ისრის მიმართულებით',
 
 # Limit report
+'limitreport-title' => 'მონაცემების პროფილური ანალიზატორი:',
+'limitreport-cputime' => 'პროცესორის დროის გამოყენება',
 'limitreport-cputime-value' => '$1 {{PLURAL:$1|წამი}}',
 'limitreport-walltime' => 'რეალურ დროში გამოყენება',
 'limitreport-walltime-value' => '$1 {{PLURAL:$1|წამი}}',
+'limitreport-ppvisitednodes' => 'პრეპროცესორის მიერ მონახულებადი კვანძების რაოდენობა',
+'limitreport-postexpandincludesize' => 'ღია ჩართვების ზომა',
 'limitreport-postexpandincludesize-value' => '$1/$2 {{PLURAL:$2|ბაიტი}}',
+'limitreport-templateargumentsize' => 'თარგის არგუმენტის ზომა',
 'limitreport-templateargumentsize-value' => '$1/$2 {{PLURAL:$2|ბაიტი}}',
+'limitreport-expansiondepth' => 'გაფართოების უდიდესი სიღრმე',
+'limitreport-expensivefunctioncount' => 'ანალიზატორის „ძვირი“ ფუნქციის რაოდენობა',
 
 # Special:ExpandTemplates
 'expandtemplates' => 'გაშლილი თარგები',
index 50561cc..52a07eb 100644 (file)
@@ -1550,6 +1550,7 @@ Ilaq ad ssutereḍ i yiwen aterras ma yezmer ad yessenqed aɣmis n ufaylu agi ye
 'uploaddisabledtext' => 'Azen n ifuyla yettwakkes deg wiki agi.',
 'php-uploaddisabledtext' => 'Taktert n ifuyla tensa deg PHP. Selken taxtiṛit n tawila  file_uploads.',
 'uploadscripted' => 'Afaylu-yagi yesɛa angal n HTML/script i yexdem agula deg browser/explorateur.',
+'uploadinvalidxml' => 'XML deg ufaylu yekteren ur d-yetwesleḍ ara.',
 'uploadvirus' => 'Afaylu-nni yesɛa anfafad asenselkim (virus)! Ẓer kter: $1',
 'uploadjava' => 'Wagi d afaylu ZIP yesɛan afaylu Java .class.
 Azdam n ifuyla Java ur yesɛa ara turagt, acku zemren ad zizdewen ikyafen n taɣellist.',
@@ -3868,6 +3869,4 @@ Yetexddem aderrec n akkw ayen yella yesegrer s <nowiki>'''{{ }}'''</nowiki>.",
 'expand_templates_generate_rawhtml' => 'Beqqeḍ HTML aneṣli',
 'expand_templates_preview' => 'Azaraskan',
 
-# Unknown messages
-'uploadinvalidxml' => 'XML deg ufaylu yekteren ur d-yetwesleḍ ara.',
 );
index e6329fc..b9358f0 100644 (file)
@@ -660,6 +660,7 @@ $2',
 'invalidtitle-unknownnamespace' => 'ចំណងជើងមិនត្រឹមត្រូវដែលមានលំហឈ្មោះមិនស្គាល់លេខ $1 និងអត្ថបទ "$2"',
 'exception-nologin' => 'មិនទាន់កត់ឈ្មោះចូលទេ',
 'exception-nologin-text' => 'សូម[[Special:Userlogin|lកត់ឈ្មោះចូល]]ដើម្បីចូលអានទំព័រឬធ្វើសកម្មភាពនេះ។',
+'exception-nologin-text-manual' => 'សូម $1 ដើម្បីអាចចូលមើលទំព័រនេះឬធ្វើសកម្មភាពអ្វីមួយ។',
 
 # Virus scanner
 'virus-badscanner' => "ការ​កំណត់​រចនា​សម្ព័ន្ធ​មិន​ល្អ​៖ កម្មវិធី​ស្កេន​មេរោគមិន​ស្គាល់​៖ ''$1''",
@@ -710,6 +711,8 @@ $2',
 'userlogin-resetpassword-link' => 'អ្នកភ្លេចពាក្យសម្ងាត់ហើយ?',
 'helplogin-url' => 'Help:ការកត់ឈ្មោះចូល',
 'userlogin-helplink' => '[[{{MediaWiki:helplogin-url}}|ជំនួយក្នុងការកត់ឈ្មោះចូល]]',
+'userlogin-loggedin' => 'អ្នកបានកត់ឈ្មោះចូលជា {{GENDER:$1|$1}} ហើយ។
+ប្រើសំណុំបែបបទខាងក្រោមដើម្បីកត់ឈ្មោះចូលជាអ្នកប្រើប្រាស់ផ្សេងម្នាក់ទៀត។',
 'userlogin-createanother' => 'បង្កើតគណនីមួយទៀត',
 'createacct-join' => 'បំពេញព័ត៌មានរបស់អ្នកខាងក្រោម។',
 'createacct-another-join' => 'បញ្ចូលព័ត៌មានគណនីថ្មីខាងក្រោម។',
@@ -818,6 +821,9 @@ $2',
 'login-abort-generic' => 'អ្នកចុះឈ្មោះចូលមិនបានសម្រេចទេ។ ការចុះឈ្មោះចូលត្រូវបានបោះបង់។',
 'loginlanguagelabel' => 'ភាសា៖ $1',
 'createacct-another-realname-tip' => 'អ្នកអាចផ្ដល់ឈ្មោះពិតរបស់អ្នកក៏បានមិនផ្ដល់ក៏បាន។ បើអ្នកផ្ដល់ឱ្យ វានឹងត្រូវបានប្រើប្រាស់់ដើម្បីបញ្ជាក់ភាពជាម្ចាស់​លើការរួមចំណែក​នានា​របស់អ្នក។',
+'pt-login' => 'កត់ឈ្មោះចូល',
+'pt-createaccount' => 'បង្កើតគណនី',
+'pt-userlogout' => 'កត់ឈ្មោះចេញ',
 
 # Email sending
 'php-mail-error-unknown' => 'កំហុសមិនស្គាល់នៅក្នុងអនុគមន៍ mail() របស់ PHP',
@@ -826,9 +832,7 @@ $2',
 
 # Change password dialog
 'changepassword' => 'ប្តូរពាក្យសម្ងាត់',
-'resetpass_announce' => 'អ្នកបានកត់ឈ្មោះចូលដោយ​អក្សរកូដ​បណ្តោះអាសន្ន​មួយដែលយើងខ្ញុំបានអ៊ីមែលទៅឱ្យ​។
-
-ដើម្បី​បញ្ចប់​ការកត់ឈ្មោះចូល អ្នកត្រូវតែ​កំណត់​ពាក្យសម្ងាត់ថ្មី​មួយនៅទីនេះ៖',
+'resetpass_announce' => 'ដើម្បី​បញ្ចប់​ការកត់ឈ្មោះចូល អ្នកត្រូវតែ​កំណត់​ពាក្យសម្ងាត់ថ្មី​មួយ។',
 'resetpass_text' => '<!-- បន្ថែមឃ្លានៅទីនេះ -->',
 'resetpass_header' => 'ប្ដូរ​ពាក្យសម្ងាត់​គណនី',
 'oldpassword' => 'ពាក្យសម្ងាត់ចាស់៖',
@@ -836,6 +840,8 @@ $2',
 'retypenew' => 'សូមវាយពាក្យសម្ងាត់ថ្មី​ម្តងទៀត៖',
 'resetpass_submit' => 'ដាក់ប្រើពាក្យសម្ងាត់និង​កត់ឈ្មោះចូល',
 'changepassword-success' => 'ពាក្យសម្ងាត់របស់អ្នកត្រូវបានផ្លាស់ប្តូរបានសំរេចហើយ!',
+'changepassword-throttled' => 'អ្នកបានព្យាយាមកត់ឈ្មោះចូលជាប់ៗគ្នាច្រើនដងពេកហើយ។​
+សូមរង់ចាំរយៈពេល$1 មុនពេលសាកល្បងម្ដងទៀត។',
 'resetpass_forbidden' => 'ពាក្យសម្ងាត់មិនអាចផ្លាស់ប្តូរបានទេ',
 'resetpass-no-info' => 'អ្នក​ចាំបាច់​ត្រូវតែ​កត់ឈ្មោះចូល ដើម្បី​ចូលទៅកាន់​ទំព័រ​នេះ​ដោយផ្ទាល់​។',
 'resetpass-submit-loggedin' => 'ប្តូរពាក្យសម្ងាត់',
@@ -843,7 +849,12 @@ $2',
 'resetpass-wrong-oldpass' => 'ពាក្យ​សម្ងាត់​បណ្ដោះ​អាសន្ន​ ឬ​បច្ចុប្បន្នមិន​ត្រឹមត្រូវ​។
 
 អ្នក​​ប្រហែល​ជា​បាន​ផ្លាស់​ប្ដូរ​ពាក្យសម្ងាត់​រួចហើយ ឬ​បានស្នើ​សុំ​ពាក្យ​សម្ងាត់​​បណ្ដោះ​អាសន្ន​​ថ្មី​មួយ​ហើយ។',
+'resetpass-recycled' => 'សូមកំណត់ពាក្យសម្ងាត់ថ្មីរបស់អ្នក ដែលខុសពីពាក្យសម្ងាត់បច្ចុប្បន្នរបស់អ្នក។',
+'resetpass-temp-emailed' => 'អ្នកបានកត់ឈ្មោះចូលដោយប្រើលេខកូដបណ្ដោះអាសន្នផ្ញើតាមអ៊ីមែល។
+ដើម្បីបញ្ចប់ការកត់ឈ្មោះចូល អ្នកចាំបាច់ត្រូវតែកំណត់ពាក្យសម្ងាត់ថ្មីនៅទីនេះ៖',
 'resetpass-temp-password' => 'ពាក្យសម្ងាត់បណ្តោះអាសន្ន:',
+'resetpass-expired' => 'ពាក្យសម្ងាត់របស់អ្នកហួសសុពលភាពហើយ។ សូមកំណត់ពាក្យសម្ងាត់ថ្មីដើម្បីកត់ឈ្មោះចូល។',
+'resetpass-expired-soft' => 'ពាក្យសម្ងាត់របស់អ្នកហួសសុពលភាពហើយ ហើយអ្នកត្រូវតែកំណត់វាឡើងវិញ។ សូមជ្រើសរើសពាក្យសម្ងាត់ថ្មីឥឡូវនេះ ឬចុចបោះបង់ដើម្បីកំណត់វានៅពេលក្រោយ។',
 
 # Special:PasswordReset
 'passwordreset' => 'កំណត់​ពាក្យសម្ងាត់​សាឡើងវិញ',
@@ -893,6 +904,8 @@ $2
 'changeemail-password' => 'ពាក្យសំងាត់{{SITENAME}}របស់អ្នក:',
 'changeemail-submit' => 'ផ្លាស់ប្ដូរអ៊ីមែល',
 'changeemail-cancel' => 'បោះបង់',
+'changeemail-throttled' => 'អ្នកបានព្យាយាមកត់ឈ្មោះចូលច្រើនដងពេកហើយ។​
+សូមរង់ចាំរយៈពេល$1 មុនពេលសាកល្បងម្ដងទៀត។',
 
 # Edit page toolbar
 'bold_sample' => 'អក្សរដិត',
@@ -1111,7 +1124,7 @@ $2
 'invalid-content-data' => 'ខ្លឹមសារទិន្នន័យគ្មានសុពលភាព',
 'content-not-allowed-here' => 'មិនអនុញ្ញាតិអោយសរសេរខ្លឹមសារ"$1" នៅលើទំព័រ [[$2]] ទេ។',
 'editwarning-warning' => 'ចាកចេញពីទំព័រនេះ នឹងធ្វើឲ្យអ្នកបាត់បង់កំណែប្រែដែលអ្នកបានធ្វើ។
-ប្រសិនបើអ្នកបាន​កត់ឈ្មោះចូលរួចហើយ អ្នកអាច​បិទ​បម្រាម​នេះ​នៅ​ក្នុងផ្នែក​ "កែប្រែ" នៃ​ចំណង់ចំណូល​ចិត្ត​របស់​អ្នក​។',
+ប្រសិនបើអ្នកបាន​កត់ឈ្មោះចូលរួចហើយ អ្នកអាច​បិទ​បម្រាម​នេះ​នៅ​ក្នុងផ្នែក​ "{{int:prefs-editing}}" នៃ​ចំណង់ចំណូល​ចិត្ត​របស់​អ្នក​។',
 
 # Content models
 'content-model-wikitext' => 'អត្ថបទវិគី',
@@ -1665,11 +1678,23 @@ $1",
 'rcnotefrom' => "ខាងក្រោមនេះជាបន្លាស់ប្ដូរនានាគិតចាប់តាំងពី '''$2''' (បង្ហាញអតិបរមាចំនួន '''$1''')។",
 'rclistfrom' => 'បង្ហាញបន្លាស់ប្ដូរថ្មីៗចាប់តាំងពី $1',
 'rcshowhideminor' => '$1កំណែប្រែ​តិចតួច',
+'rcshowhideminor-show' => 'បង្ហាញ​',
+'rcshowhideminor-hide' => 'លាក់',
 'rcshowhidebots' => '$1រូបយន្ត',
+'rcshowhidebots-show' => 'បង្ហាញ​',
+'rcshowhidebots-hide' => 'លាក់',
 'rcshowhideliu' => '$1អ្នកប្រើប្រាស់ដែលបានចុះឈ្មោះរួច',
+'rcshowhideliu-show' => 'បង្ហាញ',
+'rcshowhideliu-hide' => 'លាក់',
 'rcshowhideanons' => '$1អ្នកប្រើប្រាស់អនាមិក',
+'rcshowhideanons-show' => 'បង្ហាញ',
+'rcshowhideanons-hide' => 'លាក់',
 'rcshowhidepatr' => '$1កំណែប្រែដែលបានល្បាត',
+'rcshowhidepatr-show' => 'បង្ហាញ',
+'rcshowhidepatr-hide' => 'លាក់',
 'rcshowhidemine' => '$1កំណែប្រែរបស់ខ្ញុំ',
+'rcshowhidemine-show' => 'បង្ហាញ',
+'rcshowhidemine-hide' => 'លាក់',
 'rclinks' => 'បង្ហាញបន្លាស់ប្ដូរ$1ចុងក្រោយធ្វើឡើងក្នុងរយៈពេល$2ថ្ងៃចុងក្រោយ<br />$3',
 'diff' => 'ប្រៀបធៀប',
 'hist' => 'ប្រវត្តិ',
@@ -2119,9 +2144,20 @@ $1',
 'deadendpagestext' => 'ទំព័រដូចតទៅនេះមិនតភ្ជាប់ទៅទំព័រដទៃទៀតក្នុង {{SITENAME}} ទេ។',
 'protectedpages' => 'ទំព័រដែលត្រូវបានការពារ',
 'protectedpages-indef' => 'សំរាប់តែការការពារដែលមិនកំណត់ប៉ុណ្ណោះ',
+'protectedpages-summary' => 'ទំព័រនេះរាយបញ្ជីទំព័រដែលកំពុងត្រូវបានការពារ។ សម្រាប់បញ្ជីចំណងជើងទាំងឡាយដែលស្ថិននៅក្រោមការការពារមិនអោយបង្កើត សូមមើលនៅ [[{{#special:ProtectedTitles}}]]។',
 'protectedpages-cascade' => 'សំរាប់ការការពារជាថ្នាក់ប៉ុណ្ណោះ​',
+'protectedpages-noredirect' => 'លាក់ការបញ្ជូនបន្ត',
 'protectedpagesempty' => '​មិន​មាន​ទំព័រ​ណា​ដែល​ត្រូវបាន​ការពារ ជាមួយប៉ារ៉ាម៉ែត​ទាំងនេះទេ។',
+'protectedpages-timestamp' => 'ត្រាពេលវេលា',
+'protectedpages-page' => 'ទំព័រ',
+'protectedpages-expiry' => 'ផុតកំណត់',
+'protectedpages-performer' => 'អ្នកប្រើប្រាស់កំពុងការពារ',
+'protectedpages-params' => 'ប៉ារ៉ាម៉ែត្រនៃការការពារ',
+'protectedpages-reason' => 'មូល​ហេតុ',
+'protectedpages-unknown-timestamp' => 'មិនស្គាល់',
+'protectedpages-unknown-performer' => 'អ្នកប្រើប្រាស់មិនស្គាល់',
 'protectedtitles' => 'ចំណងជើងត្រូវបានការពារ',
+'protectedtitles-summary' => 'ទំព័រនេះរាយបញ្ជីចំណងជើងទាំងឡាយដែលស្ថិននៅក្រោមការការពារមិនអោយបង្កើត។ សម្រាប់បញ្ជីទំព័រដែលកំពុងត្រូវបានការពារ សូមមើលនៅ [[{{#special:ProtectedPages}}]]។',
 'protectedtitlesempty' => 'មិន​មាន​ចំណងជើង​ណា​ដែល​ត្រូវ​បាន​ការពារ​ជាមួយនឹង​ប៉ារ៉ាម៉ែត​ទាំងនេះ​ទេ​នាពេលថ្មីៗនេះ។',
 'listusers' => 'បញ្ជីអ្នកប្រើប្រាស់',
 'listusers-editsonly' => 'បង្ហាញតែអ្នកប្រើប្រាស់ដែលបានកែប្រែអត្ថបទប៉ុណ្ណោះ',
@@ -2812,6 +2848,7 @@ $1',
 'exportall' => 'នាំចេញទំព័រទាំងអស់',
 'exportnohistory' => "----
 '''សម្គាល់​:''' ការ​នាំ​ចេញ​នូវ​ប្រវត្តិ​នៃ​ទំព័រ​តាម​រយៈ​សំនុំ​បែប​បទ​នេះ​ មិនត្រូវ​បានអនុញ្ញាត​ដោយ​មូល​ហេតុ​ប៉ះ​ពាល់​ដល់​គុណភាព​ដំឡើរ​ការ​។",
+'exportlistauthors' => 'រួមបញ្ចូលបញ្ជីពេញលេញនៃអ្នករួមចំណែកសម្រាប់ទំព័រនីមួយៗ',
 'export-submit' => 'នាំចេញ',
 'export-addcattext' => 'បន្ថែមទំព័រនានាពីចំណាត់ថ្នាក់ក្រុម៖',
 'export-addcat' => 'បន្ថែម',
@@ -2834,13 +2871,17 @@ $1',
 'allmessages-prefix' => 'តម្រង​តាម​បុព្វបទ​៖',
 'allmessages-language' => 'ភាសា៖',
 'allmessages-filter-submit' => 'ទៅ',
+'allmessages-filter-translate' => 'បកប្រែ',
 
 # Thumbnails
 'thumbnail-more' => 'ពង្រីក',
 'filemissing' => 'ឯកសារបាត់បង់',
 'thumbnail_error' => 'កំហុស​បង្កើត​កូនរូបភាព៖ $1',
+'thumbnail_error_remote' => 'សារប្រាប់បញ្ហាបានពី $1: $2',
 'djvu_page_error' => 'ទំព័រ DjVu ក្រៅដែនកំណត់',
 'djvu_no_xml' => 'មិនអាចនាំយក XML សម្រាប់ឯកសារ DjVu',
+'thumbnail-temp-create' => 'មិនអាចបង្កើតឯកសារកូនរូបភាពបណ្ដោះអាសន្ន',
+'thumbnail-dest-create' => 'មិនអាចរក្សាទុកកូនរូបភាពនៅទីតាំងគោលដៅបានទេ',
 'thumbnail_invalid_params' => 'តួលេខ កូនទំព័រ គ្មានសុពលភាព',
 'thumbnail_dest_directory' => 'មិនអាចបង្កើតថតឯកសារតាមគោលដៅបានទេ',
 'thumbnail_image-type' => 'មិនស្គាល់ប្រើជាមួយឯកសារប្រភេទនេះទេ',
@@ -3711,6 +3752,7 @@ $5
 'logentry-newusers-newusers' => 'គណនីអ្នកប្រើប្រាស់ $1 {{GENDER:$2|ត្រូវបានបង្កើត}}',
 'logentry-newusers-create' => 'គណនីអ្នកប្រើប្រាស់ $1 {{GENDER:$2|ត្រូវបានបង្កើត}}',
 'logentry-newusers-create2' => 'គណនីអ្នកប្រើប្រាស់ $3 {{GENDER:$2|ត្រូវបានបង្កើត}} ដោយ $1',
+'logentry-newusers-byemail' => 'គណនីអ្នកប្រើប្រាស់ $3 ត្រូវបាន {{GENDER:$2|បង្កើត}} ដោយ $1 ហើយពាក្យសម្ងាត់ត្រូវបានផ្ញើរតាមអ៊ីមែល',
 'logentry-newusers-autocreate' => 'គណនីអ្នកប្រើប្រាស់ $1 {{GENDER:$2|ត្រូវបានបង្កើត}} ដោយស្វ័យប្រវត្តិ',
 'logentry-rights-rights' => '$1 {{GENDER:$2|បានផ្លាស់ប្ដូរ}}សមាជិកភាពរបស់ $3 ពី $4 ទៅជា $5',
 'logentry-rights-rights-legacy' => '$1 {{GENDER:$2|បានផ្លាស់ប្ដូរ}}សមាជិកភាពរបស់ $3',
@@ -3723,6 +3765,9 @@ $5
 'feedback-cancel' => 'បោះបង់​',
 'feedback-submit' => 'ដាក់ស្នើមតិយោបល់',
 'feedback-adding' => 'កំពុងបន្ថែមមតិយោបល់ទៅលើទំព័រ...',
+'feedback-error1' => 'បញ្ហា៖ លទ្ធផលមិនស្គាល់ពី API',
+'feedback-error2' => 'បញ្ហា៖ កែប្រែមិនបានសម្រេច',
+'feedback-error3' => 'បញ្ហា៖ គ្មានចម្លើយតបពី API',
 'feedback-thanks' => 'សូមអរគុណ! មតិយោបល់របស់អ្នកត្រូវបានដាក់ផ្សាយនៅលើទំព័រ "[$2 $1]"។',
 'feedback-close' => 'រួចរាល់',
 
@@ -3769,6 +3814,12 @@ $5
 'duration-centuries' => '$1 {{PLURAL:$1|សតវត្សរ៍|សតវត្សរ៍}}',
 'duration-millennia' => '$1 {{PLURAL:$1|សហសវត្សរ៍|សហសវត្សរ៍}}',
 
+# Limit report
+'limitreport-cputime' => 'រយៈពេលប្រើប្រាស់ CPU',
+'limitreport-cputime-value' => '$1 {{PLURAL:$1|វិនាទី|វិនាទី}}',
+'limitreport-walltime' => 'រយៈពេលប្រើប្រាស់ពិតប្រាកដ',
+'limitreport-walltime-value' => '$1 {{PLURAL:$1|វិនាទី|វិនាទី}}',
+
 # Special:ExpandTemplates
 'expandtemplates' => 'ពង្រីកទំព័រគំរូ',
 'expand_templates_input' => 'សរសេរឃ្លា',
index 489d70c..533b122 100644 (file)
@@ -1954,6 +1954,8 @@ $2 {{PLURAL:$3|형식만 사용할 수 있습니다}}.',
 'uploaddisabledtext' => '파일 올리기 기능이 비활성화되어 있습니다.',
 'php-uploaddisabledtext' => 'PHP 파일 올리기가 비활성화되었습니다. 파일 올리기 설정을 확인하십시오.',
 'uploadscripted' => '이 파일에는 HTML이나 다른 스크립트 코드가 포함되어 있어, 웹 브라우저에서 오류를 일으킬 수 있습니다.',
+'uploadscriptednamespace' => "이 SVG 파일은 사용할 수 없는 이름공간 '$1'을 포함하고 있습니다.",
+'uploadinvalidxml' => '업로드된 파일의 XML의 구문을 분석할 수 없습니다.',
 'uploadvirus' => '파일이 바이러스를 포함하고 있습니다!
 자세한 설명: $1',
 'uploadjava' => '이 ZIP 파일은 자바의 .class 파일을 포함하고 있습니다.
@@ -4373,6 +4375,4 @@ $5
 'expand_templates_generate_rawhtml' => '원본 HTML 보이기',
 'expand_templates_preview' => '미리 보기',
 
-# Unknown messages
-'uploadinvalidxml' => '업로드된 파일의 XML의 구문을 분석할 수 없습니다.',
 );
index 4523832..be47fce 100644 (file)
@@ -1894,6 +1894,7 @@ wann De se noch han wells.',
 'php-uploaddisabledtext' => 'Et Dateie Huhlade es en PHP affjeschalldt.
 Bes esu joot un donn noh de Enshtellung <i lang="en">file_uploads</i> loore.',
 'uploadscripted' => 'En dä Datei es HTML dren oder Code vun enem Skripp, dä künnt Dinge Brauser en do verkihrte Hals krije un usführe.',
+'uploadinvalidxml' => 'Dat <i lang="en" xml:lang="en">XML</i> en dä huh jelaade Dattei kunnt wohr nit en Oodenong beim Ongersöhke.',
 'uploadvirus' => 'Esu ene Dress:
 <br />
 En dä Datei stich e Kompjutervirus!
@@ -4420,6 +4421,4 @@ Derbei jehüüere enschtalleete Paaserfunxjuhne, alsu esu jät wi
 'expand_templates_generate_rawhtml' => 'Donn de Röh HTML Ußjaav aanzeije',
 'expand_templates_preview' => 'Vör-Aansich',
 
-# Unknown messages
-'uploadinvalidxml' => 'Dat <i lang="en" xml:lang="en">XML</i> en dä huh jelaade Dattei kunnt wohr nit en Oodenong beim Ongersöhke.',
 );
index 82907f0..ed1b127 100644 (file)
@@ -234,7 +234,7 @@ $messages = array(
 'editfont-serif' => 'Tipografía serif',
 
 # Dates
-'sunday' => 'Alkhad',
+'sunday' => 'Alad',
 'monday' => 'Lunes',
 'tuesday' => 'Martes',
 'wednesday' => 'Miércoles',
@@ -305,9 +305,9 @@ $messages = array(
 'category-empty' => "''Esta kategoría oy día, no contiene ni hojas ni dosyas de multimedya''",
 'hidden-categories' => '{{PLURAL:$1|Kategoría escondida|Kategorías escondidas}}',
 'hidden-category-category' => 'Katēggorías escondidas',
-'category-subcat-count' => '{{PLURAL:$2|Esta katēggoría contiene sólo una baxo-katēggoría:|Esta katēggoría contiene {{PLURAL:$1|esta baxo-katēggoría aquí abaxo|$1 baxo-katēggorías aquí abaxo}}, de un total de $2 baxo-katēggorías:}}',
+'category-subcat-count' => '{{PLURAL:$2|Esta kategoría contiene sólo la su-kategoría venidera.|Esta kategoría contiene {{PLURAL:$1|la su-kategoría venidera|$1 su-kategorías venideras}}, de un total de $2 su-kategorías.}}',
 'category-subcat-count-limited' => 'Esta katēggoría contiene {{PLURAL:$1|la baxo-katēggoría venidera|$1 baxo-katēggorías venideras}}.',
-'category-article-count' => '{{PLURAL:$2|Esta katēggoría contiene sólo la hoja venidera.|{{PLURAL:$1|La hoja venidera apartiene|Las $1 hojas venideras apartienen}} a esta katēggoría, de un total de $2.}}',
+'category-article-count' => '{{PLURAL:$2|Esta kategoría contiene sólo la hoja venidera.|{{PLURAL:$1|La hoja venidera apartiene|Las $1 hojas venideras apartienen}} a esta kategoría, de un total de $2.}}',
 'category-article-count-limited' => '{{PLURAL:$1|La hoja venidera apartiene|Las $1 hojas venideras apartienen}} a esta katēggoría.',
 'category-file-count' => '{{PLURAL:$2|Esta katēggoría contiene sólo la dosya venidera.|{{PLURAL:$1|La dosya venidera apartiene|Las $1 dosyas venideras apartienen}} a esta katēggoría, de un total de $2.}}',
 'category-file-count-limited' => '{{PLURAL:$1|La dosya venidera apartiene|Las $1 dosyas venideras apartienen}} a esta katēggoría.',
@@ -684,8 +684,8 @@ Kontrasenya temporal: $2',
 'showpreview' => 'Echar una ojada',
 'showlivepreview' => 'Previsteo bivo',
 'showdiff' => 'Amostrar los trocamientos',
-'anoneditwarning' => "'''Noticia:''' La sesyón no empeçó con un cuento de usuario.
-Tu adresso de IP va ser enrejjistrado en la istoria de la hoja.",
+'anoneditwarning' => '<strong>Aviso:</strong> No entrates a tu cuento.
+Tu adresso de IP se va a enrejistrar en la istoria de trocamientos de la hoja.',
 'summary-preview' => 'Previsualización del resumen:',
 'blockedtitle' => 'El usador está blokeado',
 'blockednoreason' => 'La razόn no se diό',
@@ -781,7 +781,7 @@ Leyenda: (act) = diferencias con la versión actual,
 
 # Revision deletion
 'rev-deleted-user' => '(se kito el nombre de usuario)',
-'rev-delundel' => 'mostra/esconde',
+'rev-delundel' => 'amostrar/esconder',
 'rev-showdeleted' => 'mostra',
 'revdelete-show-file-submit' => 'Si',
 'revdelete-hide-image' => 'Eskonder el kontenido de archivo',
@@ -949,43 +949,43 @@ Leyenda: (act) = diferencias con la versión actual,
 'nchanges' => '$1 {{PLURAL:$1|trocamiento|trocamientos}}',
 'enhancedrc-history' => 'istoria',
 'recentchanges' => 'Trocamientos freskos',
-'recentchanges-legend' => 'Opciones encima de los trocamientos frescos',
+'recentchanges-legend' => 'Escojimientos de los trocamientos freskos',
 'recentchanges-summary' => 'Perseguid en esta hoja, los trocamientos de alcabo realizados en la Viki.',
 'recentchanges-feed-description' => 'Perseguir los trocamientos más nuevos en el viki en este feed.',
 'recentchanges-label-newpage' => 'Este trocamiento crió una mueva hoja',
-'recentchanges-label-minor' => 'Esta es un trocamiento chiquitico',
-'recentchanges-label-bot' => 'Este trokamiento fue echo por un bot',
-'recentchanges-label-unpatrolled' => 'Este trocamiento no está akavidado',
+'recentchanges-label-minor' => 'Esto es un trocamiento chiquitico',
+'recentchanges-label-bot' => 'Este trocamiento era hecho por la parte de un bot',
+'recentchanges-label-unpatrolled' => 'Este trocamiento no fue patrullado daínda',
 'recentchanges-legend-plusminus' => "(''±123'')",
 'rcnotefrom' => "Debasho se amostran los trokamientos desde '''$2''' (amostrados fina <b>$1</b>)",
-'rclistfrom' => 'Mostra los trocamientos nuevos empeçando desde $1',
+'rclistfrom' => 'Amostrar los trocamientos muevos empeçando el $1',
 'rcshowhideminor' => '$1 trocamientos chiquiticos',
 'rcshowhidebots' => '$1 botes',
 'rcshowhideliu' => '$1 usadores enrejistrados',
 'rcshowhideanons' => '$1 usadores anónimos',
 'rcshowhidepatr' => '$1 trocamientos akavidados',
 'rcshowhidemine' => '$1 mis trocamientos',
-'rclinks' => 'Ver los dal cavo $1 trocamientos en los dal cavo $2 días.<br />$3',
+'rclinks' => 'Ver los $1 trocamientos dalcavo en los $2 días dalcavo<br />$3',
 'diff' => 'dif',
 'hist' => 'ist',
 'hide' => 'Esconder',
 'show' => 'Amostrar',
 'minoreditletter' => 'ch',
-'newpageletter' => 'N',
+'newpageletter' => 'M',
 'boteditletter' => 'b',
 'rc_categories_any' => 'Kualkyer',
-'rc-enhanced-expand' => 'Amostrar los detalyos',
-'rc-enhanced-hide' => 'Guarda los detalyos',
+'rc-enhanced-expand' => 'Amostrar los detalios',
+'rc-enhanced-hide' => 'Esconder los detalios',
 
 # Recent changes linked
-'recentchangeslinked' => 'Trocamientos conectados',
+'recentchangeslinked' => 'Trocamientos atados',
 'recentchangeslinked-feed' => 'Trocamientos conectados',
 'recentchangeslinked-toolbox' => 'Trocamientos atados',
-'recentchangeslinked-title' => 'Los trocamientos relacionados con "$1"',
+'recentchangeslinked-title' => 'Los trocamientos atados a "$1"',
 'recentchangeslinked-summary' => "Esto es una lista de trocamientos dalcavo en las hojas atadas de una hoja partikolara (u en los miembros de una kategoría partikolara).
 Las hojas en tu [[Special:Watchlist|lista de acavidamiento]] son '''reforçadas'''.",
-'recentchangeslinked-page' => 'Nombre de la hoja',
-'recentchangeslinked-to' => 'Amostra los trocamientos freskos en lugar de la hoja indicada',
+'recentchangeslinked-page' => 'Nombre de la hoja:',
+'recentchangeslinked-to' => 'Al lugar de la hoja indikada, amostra los trocamientos en las hojas atadas a esta hoja',
 
 # Upload
 'upload' => 'Suvir una dosya',
@@ -1247,7 +1247,7 @@ A continuación se mostran las opciones actuales de la hoja '''$1''':",
 
 # Namespace form on various pages
 'namespace' => 'Espacio de nombres:',
-'invert' => 'Invertir selección',
+'invert' => 'Aboltar escojimiento',
 'blanknamespace' => '(Prencipal)',
 
 # Contributions
@@ -1385,7 +1385,7 @@ Puedes ver su manadero',
 'tooltip-ca-delete' => 'Efassar esta hoja',
 'tooltip-ca-move' => 'Taşirea esta hoja (troca el nombre desta hoja)',
 'tooltip-ca-watch' => 'Ajusta esta hoja a tu lista de acavidamientos',
-'tooltip-ca-unwatch' => 'Quita esta hoja de tu lista de escojidos',
+'tooltip-ca-unwatch' => 'Quita esta hoja de tu lista de acavidamientos',
 'tooltip-search' => 'Buxca en {{SITENAME}}',
 'tooltip-search-go' => 'Vate a la hoja con este nombre egzakto, si egziste.',
 'tooltip-search-fulltext' => 'Buxca este teksto en las hojas',
@@ -1401,14 +1401,14 @@ Puedes ver su manadero',
 'tooltip-t-recentchangeslinked' => 'Los trocamientos dalcavo en las hojas atadas a la ésta',
 'tooltip-feed-rss' => 'Sindicación RSS de esta hoja',
 'tooltip-feed-atom' => 'Canal Atomo parâ esta hoja',
-'tooltip-t-contributions' => 'Ver la lista de ajustamientos de este usuario',
+'tooltip-t-contributions' => 'Lista de kontribüsyón (ajustamientos) deste usador',
 'tooltip-t-emailuser' => 'A este usuario, mándale una letra electrόnica (ímey)',
 'tooltip-t-upload' => 'Suve dosyas',
 'tooltip-t-specialpages' => 'Lista de todas las hojas especiales',
 'tooltip-t-print' => 'La forma apropiada parâ imprimir esta hoja',
 'tooltip-t-permalink' => 'Atamiento permanente (fikso) a este enderechamiento de la hoja',
 'tooltip-ca-nstab-main' => 'Ve el artíkolo',
-'tooltip-ca-nstab-user' => 'Ver la pajina de usuario',
+'tooltip-ca-nstab-user' => 'Ver la hoja del usador',
 'tooltip-ca-nstab-special' => 'Esta es una hoja especial, la hoja ya no se puede trocar',
 'tooltip-ca-nstab-project' => 'Ver la hoja del prodjekto',
 'tooltip-ca-nstab-image' => 'Ver la hoja de la dosya',
@@ -1479,7 +1479,8 @@ Los atamientos venideros que están en la misma liña se konsidheran como ekseps
 
 # Metadata
 'metadata' => 'Metadados',
-'metadata-help' => 'Esta dosya contiene mas información (metadatos), probablemente ajustada por la kamera dizhital, el eskáner o la proǵrama kullaneado para criarlo o dizhitalizarlo. Si la dosya fue trocada de su estado orizhinal, puede aver pèryido algunos detalyos.',
+'metadata-help' => 'Esta dosya contiene información ajustada (metadados), que la ajustó puede ser la kamerá dijital u el eskáner en cavso si se kulaneó parâ criar u dijitalizar la dosya. 
+Si la dosya fue trocada, algunos detalios pueden amostrar no la dosya trocada, ma la dosya orijinal.',
 'metadata-expand' => 'Mostra los detalyos ekstendidos',
 'metadata-collapse' => 'Esconder los detalyos ekstendidos',
 'metadata-fields' => 'Los campos de metadatos que se listan en este messaje se van a amostrar en la hoja de la deskripsión de la foto daínda cuando la tabla de metadatos está cerrada.
index 99e63d7..9c4272f 100644 (file)
@@ -758,9 +758,11 @@ Waart w.e.g. $1 ier Dir et nach eng Kéier probéiert.',
 'resetpass-wrong-oldpass' => 'Net valabelt temporäert oder aktuellt Passwuert.
 Vläicht hutt Dir Äert Passwuert scho geännert oder en neit temporäert Passwuert ugefrot.',
 'resetpass-recycled' => 'Ännert Äert Passwuert w.e.g. op een anert Passwuert wéi Äert aktuellt Passwuert.',
+'resetpass-temp-emailed' => "Dir hutt Iech mat engem temporären E-Mail-Code ageloggt. Fir d'Aloggen ofzeschléisse musst Dir hei en neit Passwuert astellen:",
 'resetpass-temp-password' => 'Temporäert Passwuert:',
 'resetpass-abort-generic' => "D'Ännere vum Passwuert gouf duerch eng Erweiderung ofgebrach.",
 'resetpass-expired' => 'Äert Passwuert ass ofgelaf. Gitt w.e.g. en neit Passwuert u fir Iech anzeloggen.',
+'resetpass-expired-soft' => 'Äert Passwuert ass ofgelaf a muss zeréckgesat. Sicht w.e.g. elo en neit Passwuert eraus oder klickt  "{{int:resetpass-submit-cancel}}" fir et spéider zeréckzesetzen.',
 
 # Special:PasswordReset
 'passwordreset' => 'Passwuert zrécksetzen',
@@ -1606,11 +1608,23 @@ Dës Informatioun ass ëffentlech.",
 'rcnotefrom' => "Ugewise ginn d'Ännerunge vum '''$2''' un (maximal '''$1''' Ännerunge gi gewisen).",
 'rclistfrom' => 'Nei Ännerunge vu(n) $1 u weisen',
 'rcshowhideminor' => 'Kleng Ännerunge $1',
+'rcshowhideminor-show' => 'Weisen',
+'rcshowhideminor-hide' => 'Verstoppen',
 'rcshowhidebots' => 'Botte $1',
+'rcshowhidebots-show' => 'Weisen',
+'rcshowhidebots-hide' => 'Verstoppen',
 'rcshowhideliu' => 'Ugemellt Benotzer $1',
+'rcshowhideliu-show' => 'Weisen',
+'rcshowhideliu-hide' => 'Verstoppen',
 'rcshowhideanons' => 'Anonym Benotzer $1',
+'rcshowhideanons-show' => 'Weisen',
+'rcshowhideanons-hide' => 'Verstoppen',
 'rcshowhidepatr' => 'iwwerwaacht Ännerunge $1',
+'rcshowhidepatr-show' => 'Weisen',
+'rcshowhidepatr-hide' => 'Verstoppen',
 'rcshowhidemine' => 'Meng Ännerunge $1',
+'rcshowhidemine-show' => 'Weisen',
+'rcshowhidemine-hide' => 'Verstoppen',
 'rclinks' => 'Déi lescht $1 Ännerunge vun de leschten $2 Deeg weisen.<br />$3',
 'diff' => 'Ënnerscheed',
 'hist' => 'Versiounen',
@@ -1737,6 +1751,8 @@ Wann Dir dëse Fichier trotzdeem eropluede wëllt da gitt w.e.g. zréck a luet d
 'uploaddisabledtext' => "D'Eropluede vu Fichieren ass ausgeschalt.",
 'php-uploaddisabledtext' => "D'Eropluede vu Fichieren ass am PHP desaktivéiert. Kuckt w.e.g. d'Astellung ''file_uploads'' no.",
 'uploadscripted' => 'An dësem Fichier ass HTML- oder Scriptcode, dee vun engem Webbrowser falsch interpretéiert kéint ginn.',
+'uploadscriptednamespace' => 'An dësem SVG-Fichier ass en illegalen Nummraum "$1"',
+'uploadinvalidxml' => 'Den XML am eropgelueden Fichier konnt net verschafft ginn.',
 'uploadvirus' => 'An dësem Fichier ass ee Virus! Detailer: $1',
 'uploadjava' => "An dësem ZIP-Fichier ass e JAVA CLASS-Fichier dran.
 D'Eropluede vu JAVA-Fichieren ass net erlaabt, well si d'Ëmgoe vu Sécherheetsmoossnamen erméigleche kënnen.",
@@ -2080,6 +2096,7 @@ An all Rei sti Linken zur éischter an zweeter Viruleedung, souwéi d\'Zil vun d
 'mostrevisions' => 'Säite mat de meeschte Versiounen',
 'prefixindex' => 'All Säite mat Prefix',
 'prefixindex-namespace' => 'All Säite mat Prefix (Nummraum $1)',
+'prefixindex-strip' => 'Prefix an der Lëscht ewechhuelen',
 'shortpages' => 'Kuerz Säiten',
 'longpages' => 'Laang Säiten',
 'deadendpages' => 'Sakgaasse-Säiten',
@@ -2093,6 +2110,7 @@ An all Rei sti Linken zur éischter an zweeter Viruleedung, souwéi d\'Zil vun d
 'protectedpages-timestamp' => 'Zäitstempel',
 'protectedpages-page' => 'Säit',
 'protectedpages-expiry' => 'Spär bis',
+'protectedpages-performer' => 'Spär duerch de Benotzer',
 'protectedpages-params' => 'Parameter vun der Spär',
 'protectedpages-reason' => 'Grond',
 'protectedpages-unknown-timestamp' => 'Onbekannt',
@@ -2552,6 +2570,7 @@ $1',
 'sp-contributions-search' => 'No Kontributioune sichen',
 'sp-contributions-username' => 'IP-Adress oder Benotzernumm:',
 'sp-contributions-toponly' => 'Nëmmen Ännerunge weisen déi déi lescht Versioun sinn',
+'sp-contributions-newonly' => 'Nëmmen Ännerunge weisen déi Säiten uleeën',
 'sp-contributions-submit' => 'Sichen',
 
 # What links here
@@ -4040,6 +4059,4 @@ Faktesch alles wat tëscht duebelen Accolade steet gëtt ausgewäert.',
 'expand_templates_generate_rawhtml' => 'HTML-Format weisen',
 'expand_templates_preview' => 'Kucken ouni ofzespäicheren',
 
-# Unknown messages
-'uploadinvalidxml' => 'Den XML am eropgelueden Fichier konnt net verschafft ginn.',
 );
index 0e6e2e8..845c41d 100644 (file)
@@ -146,12 +146,12 @@ $messages = array(
 'dec' => 'дек',
 
 # Categories related messages
-'pagecategories' => '{{PLURAL:$1|1=Категори|Категорияр}}',
+'pagecategories' => '{{PLURAL:$1|1=Категория|Категорияр}}',
 'category_header' => '«$1» категориядин ччинар',
 'subcategories' => 'агъакатегорияр',
 'category-media-header' => '"$1" категориядин медиа',
 'category-empty' => "''Алай чӀава и категория ичӀи я.\"",
-'hidden-categories' => '{{PLURAL:$1|1=Чуьнуьхай категори|Чуьнуьхай категорияр}}',
+'hidden-categories' => '{{PLURAL:$1|1=Чуьнуьхай категория|Чуьнуьхай категорияр}}',
 'hidden-category-category' => 'Чуьнуьхай категорияр',
 'category-subcat-count' => '{{PLURAL:$2|И категорияда анжах гуьгъуьна авай подкатегория ава.|$2-кай {{PLURAL:$1|1=агъакатегория|$1 агъакатегорияр}} къалурнава }}',
 'category-subcat-count-limited' => 'И категорияда {{PLURAL:$1|1=агъакатегория|$1 агъакатегорияр}} ава.',
@@ -737,7 +737,7 @@ $messages = array(
 'hide' => 'Чуьнуьхун',
 'show' => 'Къалурун',
 'minoreditletter' => 'гъ',
-'newpageletter' => 'ЦI',
+'newpageletter' => 'Цl',
 'boteditletter' => 'б',
 'rc_categories_any' => 'ГЬар са',
 'rc-enhanced-expand' => 'Куьлуь-шуьлуьяр къалурун (JavaScript герекзава)',
@@ -816,7 +816,7 @@ $messages = array(
 'filehist-user' => 'Уртах',
 'filehist-dimensions' => 'Кьадарар',
 'filehist-filesize' => 'Файлдин кьадар',
-'filehist-comment' => 'Ð\9aÑ\8aейд',
+'filehist-comment' => 'Ð\92еÑ\80евиÑ\80д',
 'filehist-missing' => 'Файл авачиз я',
 'imagelinks' => 'Файл кардик кутун',
 'linkstoimage' => 'Къведай {{PLURAL:$1 | ччин | $1 ччинар}} гьа и файлдиз элячlзава',
@@ -866,7 +866,7 @@ $messages = array(
 'withoutinterwiki-submit' => 'Къалурун',
 
 # Miscellaneous special pages
-'nbytes' => '$1 {{PLURAL:$1|баjт|баjтар}}',
+'nbytes' => '$1 {{PLURAL:$1|1=байт|байтар}}',
 'nmembers' => '$1 {{PLURAL:$1|1=уьзви|уьзвияр}}',
 'lonelypages' => 'Eтим xъувун',
 'prefixindex' => 'Префикс галай вири ччинар',
index 4bd2353..4b75b6e 100644 (file)
@@ -1071,6 +1071,7 @@ $2',
 'copyuploaddisabled' => 'سوار کردن وا یو آر ال د کار نئ.',
 'uploadfromurl-queued' => 'سوارکرد تو ها د گئ.',
 'uploaddisabledtext' => 'سوار کرد فایلیا د کار نئ.',
+'uploadinvalidxml' => 'ایکس ام الی که سوار بیه نبوئه نوتیج با.',
 'upload-source' => 'سرچشمه فایل',
 'sourcefilename' => 'سرچشمه نوم جانیا:',
 'sourceurl' => 'سرچشمه يو آر ال:',
@@ -1714,6 +1715,4 @@ $2',
 # Special:ExpandTemplates
 'expand_templates_remove_comments' => 'جا وه جا بیئن ویر و باوریا',
 
-# Unknown messages
-'uploadinvalidxml' => 'ایکس ام الی که سوار بیه نبوئه نوتیج با.',
 );
index 1dc64c6..549b006 100644 (file)
@@ -25,6 +25,7 @@
  * @author Pdxx
  * @author Perkunas
  * @author Pėstininkas
+ * @author Reedy
  * @author Siggis
  * @author Tomasdd
  * @author Urhixidur
@@ -716,6 +717,9 @@ Palaukite prieš bandant vėl.',
 'login-abort-generic' => 'Jūsų prisijungimas buvo nesėkmingas - Nutraukta',
 'loginlanguagelabel' => 'Kalba: $1',
 'suspicious-userlogout' => 'Jūsų prašymas atsijungti buvo atmestas, nes, atrodo, jį klaidingai išsiuntė naršyklė arba spartinantysis tarpinis serveris.',
+'pt-login' => 'Prisijungti',
+'pt-createaccount' => 'Sukurti paskyrą',
+'pt-userlogout' => 'Atsijungti',
 
 # Email sending
 'php-mail-error-unknown' => 'Nežinoma klaida PHP mail() funkcijoje',
@@ -1523,11 +1527,23 @@ teisės",
 'rcnotefrom' => "Žemiau yra pakeitimai pradedant '''$2''' (rodoma iki '''$1''' pakeitimų).",
 'rclistfrom' => 'Rodyti naujus pakeitimus pradedant $1',
 'rcshowhideminor' => '$1 smulkius keitimus',
+'rcshowhideminor-show' => 'Rodyti',
+'rcshowhideminor-hide' => 'Slėpti',
 'rcshowhidebots' => '$1 robotus',
+'rcshowhidebots-show' => 'Rodyti',
+'rcshowhidebots-hide' => 'Slėpti',
 'rcshowhideliu' => '$1 prisijungusius naudotojus',
+'rcshowhideliu-show' => 'Rodyti',
+'rcshowhideliu-hide' => 'Slėpti',
 'rcshowhideanons' => '$1 anoniminius naudotojus',
+'rcshowhideanons-show' => 'Rodyti',
+'rcshowhideanons-hide' => 'Slėpti',
 'rcshowhidepatr' => '$1 patikrintus keitimus',
+'rcshowhidepatr-show' => 'Rodyti',
+'rcshowhidepatr-hide' => 'Slėpti',
 'rcshowhidemine' => '$1 mano keitimus',
+'rcshowhidemine-show' => 'Rodyti',
+'rcshowhidemine-hide' => 'Slėpti',
 'rclinks' => 'Rodyti paskutinius $1 pakeitimų per paskutiniąsias $2 dienų<br />$3',
 'diff' => 'skirt',
 'hist' => 'ist',
@@ -1651,6 +1667,7 @@ Jei visvien norite įkelti savo failą, prašome eiti atgal ir įkelti šį fail
 'php-uploaddisabledtext' => "Failų įkėlimai uždrausti PHP nustatymuose.
 Patikrinkite ''file_uploads'' nustatą.",
 'uploadscripted' => 'Šis failas turi HTML arba programinį kodą, kuris gali būti klaidingai suprastas interneto naršyklės.',
+'uploadscriptednamespace' => "Šis SVG failas turi neteisėtą vietą vardui '$1'",
 'uploadvirus' => 'Šiame faile yra virusas! Smulkiau: $1',
 'uploadjava' => 'Failas yra ZIP failas, kuriame yra Java .class failas.
 Įkelti Java failus neleidžiama, nes jie gali padėti apeiti saugumo apribojimus.',
@@ -1977,6 +1994,9 @@ Kiekvienoje eilutėje yra nuorodos į pirmąjį ir antrąjį peradresavimą, tai
 'protectedpages-indef' => 'Tik neapibrėžtos apsaugos',
 'protectedpages-cascade' => 'Tik pakopinė apsauga',
 'protectedpagesempty' => 'Šiuo metu nėra apsaugotas joks failas su šiais parametrais.',
+'protectedpages-page' => 'Puslapis',
+'protectedpages-expiry' => 'Galioja iki',
+'protectedpages-reason' => 'Priežastis',
 'protectedtitles' => 'Apsaugoti pavadinimai',
 'protectedtitlesempty' => 'Šiuo metu nėra jokių pavadinimų apsaugotų šiais parametrais.',
 'listusers' => 'Naudotojų sąrašas',
index 012ddd9..95d1c2a 100644 (file)
@@ -765,6 +765,9 @@ Andraso $1 alohan'ny mamerina.",
 'suspicious-userlogout' => "Ny fangataham-pialanao dia tsy nekena satria ohatry ny nalfan'ny mpizahan-tsehatra simba izy na kasy ny proxy.",
 'createacct-another-realname-tip' => "Azo tsy atsofoka ny tena anarana.
 Raha misafidy ny hanome azy ianao, ho ampiasaina amin'ny fanehoana ny anjara asan'ilay mpikambana ilay izy.",
+'pt-login' => 'Hiditra',
+'pt-createaccount' => 'Hamorona kaonty',
+'pt-userlogout' => 'Hivoaka',
 
 # Email sending
 'php-mail-error-unknown' => "Hadisoana tsy fantatra tao amin'ny tao mial() an'i PHP.",
@@ -1623,11 +1626,23 @@ Tsy haseho ny adiresy imailakao rehefa manoratra any aminao ny mpikambana hafa."
 'rcnotefrom' => "Ity eto ambany ity ny lisitry ny vao niova manomboka ny <b>$2</b> (hatramin'ny <b>$1</b> no miseho).",
 'rclistfrom' => 'Asehoy izay vao niova manomboka ny $1',
 'rcshowhideminor' => '$1 ny fanovàna kely',
+'rcshowhideminor-show' => 'Haneho',
+'rcshowhideminor-hide' => 'Hanafina',
 'rcshowhidebots' => '$1 ny mpikambana rôbô',
+'rcshowhidebots-show' => 'Haneho',
+'rcshowhidebots-hide' => 'Hanafina',
 'rcshowhideliu' => '$1 ny mpikambana nisoratra anarana',
+'rcshowhideliu-show' => 'Haneho',
+'rcshowhideliu-hide' => 'Hanadina',
 'rcshowhideanons' => '$1 ny mpikambana tsy nisoratra anarana',
+'rcshowhideanons-show' => 'Haneho',
+'rcshowhideanons-hide' => 'Hanafina',
 'rcshowhidepatr' => '$1 ny fanovana voaambina',
+'rcshowhidepatr-show' => 'Haneho',
+'rcshowhidepatr-hide' => 'Hanafina',
 'rcshowhidemine' => '$1 ny fanovàko',
+'rcshowhidemine-show' => 'Haneho',
+'rcshowhidemine-hide' => 'Hanafina',
 'rclinks' => "Asehoy ny $1 niova farany tato anatin'ny $2 andro<br />$3",
 'diff' => 'Fampitahana',
 'hist' => 'tant.',
@@ -1754,6 +1769,7 @@ Raha mbola te-hampiditra io rakitra io foana ianao, miverena any aoriana ary mam
 Marino ny option configuration file_uploads.",
 'uploadscripted' => "
 Misy kialo HTML na fango script mety tsy ho hain'ny navigateur sasany haseho ity rakitra ity.",
+'uploadinvalidxml' => "Tsy afaka vakiana ny XML tao anatin'ilay rakitra nafaranao.",
 'uploadvirus' => 'Misy viriosy io rakitra io! Toy izao ny antsipirihany: $1',
 'uploadjava' => 'Ny rakitra dia rakitra ZIP ahitana rakitra .class Java.
 Voarara ny mandefa rakitra Java satria mety hahavaky ny fepetra mikasika ny antoka ireo rakitra ireo.',
@@ -3699,6 +3715,4 @@ Azonao atao ihany koa ny [[Special:EditWatchlist/raw|manova ilay lisitra amin'ny
 'api-error-uploaddisabled' => "Tsy alefa eto amin'ity wiki ity ny fandefasan-drakita.",
 'api-error-verification-error' => 'Mety tapaka ity rakitra ity, na diso tovan-drakitra.',
 
-# Unknown messages
-'uploadinvalidxml' => "Tsy afaka vakiana ny XML tao anatin'ilay rakitra nafaranao.",
 );
index 042e121..1a2db14 100644 (file)
@@ -938,7 +938,7 @@ $2',
 'resetpass-temp-password' => 'Привремена лозинка:',
 'resetpass-abort-generic' => 'Смената на лозинката е откажана од додаток.',
 'resetpass-expired' => 'Лозинката ви е истечена. Задајте нова лозинка за да се најавите.',
-'resetpass-expired-soft' => 'Ð\9bозинкаÑ\82а Ð²Ð¸ Ðµ Ð¸Ñ\81Ñ\82еÑ\87ена Ð¸ Ñ\9cе Ð¼Ð¾Ñ\80а Ð´Ð° Ð·Ð°Ð´Ð°Ð´ÐµÑ\82е Ð½Ð¾Ð²Ð°. Ð\98збеÑ\80еÑ\82е Ð»Ð¾Ð·Ð¸Ð½ÐºÐ° Ñ\81ега, Ð¸Ð»Ð¸ Ð¿Ð°Ðº Ð¾Ñ\82кажеÑ\82е Ð³Ð¾ за да ја зададете подоцна.',
+'resetpass-expired-soft' => 'Ð\9bозинкаÑ\82а Ð²Ð¸ Ðµ Ð¸Ñ\81Ñ\82еÑ\87ена Ð¸ Ñ\9cе Ð¼Ð¾Ñ\80а Ð´Ð° Ð·Ð°Ð´Ð°Ð´ÐµÑ\82е Ð½Ð¾Ð²Ð°. Ð\9eдбеÑ\80еÑ\82е Ð½Ð¾Ð²Ð° Ñ\81ега, Ð¸Ð»Ð¸ Ð¿Ð°Ðº Ñ\81Ñ\82иÑ\81неÑ\82е Ð½Ð° â\80\9e{{int:resetpass-submit-cancel}}â\80\9c за да ја зададете подоцна.',
 
 # Special:PasswordReset
 'passwordreset' => 'Менување на лозинка',
@@ -1801,14 +1801,26 @@ $1",
 'recentchanges-legend-heading' => "'''Легенда:'''",
 'recentchanges-legend-newpage' => '(погл. и [[Special:NewPages|списокот на нови страници]])',
 'recentchanges-legend-plusminus' => "(''±123'')",
-'rcnotefrom' => 'Ð\9fодолÑ\83 Ñ\81е Ð¿Ñ\80омениÑ\82е Ð¾Ð´ <b>$2</b> (се прикажуваат до <b>$1</b>).',
+'rcnotefrom' => 'Ð\9fодолÑ\83 Ñ\81е Ð¿Ñ\80омениÑ\82е Ð½Ð°Ð¿Ñ\80авени Ð¾Ð´ <strong>$2</strong> Ð½Ð°Ð²Ð°Ð¼Ñ\83 (се прикажуваат до <b>$1</b>).',
 'rclistfrom' => 'Прикажи нови промени почнувајќи од $1',
 'rcshowhideminor' => '$1 ситни промени',
+'rcshowhideminor-show' => 'Прикажи',
+'rcshowhideminor-hide' => 'Скриј',
 'rcshowhidebots' => '$1 ботови',
+'rcshowhidebots-show' => 'Прикажи',
+'rcshowhidebots-hide' => 'Скриј',
 'rcshowhideliu' => '$1 најавени корисници',
+'rcshowhideliu-show' => 'Прикажи',
+'rcshowhideliu-hide' => 'Скриј',
 'rcshowhideanons' => '$1 анонимни корисници',
+'rcshowhideanons-show' => 'Прикажи',
+'rcshowhideanons-hide' => 'Скриј',
 'rcshowhidepatr' => '$1 проверени уредувања',
+'rcshowhidepatr-show' => 'Прикажи',
+'rcshowhidepatr-hide' => 'Скриј',
 'rcshowhidemine' => '$1 мои уредувања',
+'rcshowhidemine-show' => 'Прикажи',
+'rcshowhidemine-hide' => 'Скриј',
 'rclinks' => 'Прикажи скорешни $1 промени во последните $2 дена<br />$3',
 'diff' => 'разл',
 'hist' => 'истор',
@@ -1940,6 +1952,8 @@ $1",
 'php-uploaddisabledtext' => 'Подигањето на податотеки е оневозможено во PHP. 
 Проверете го нагодувањето file_uploads.',
 'uploadscripted' => 'Податотеката содржи HTML-код или сценарио што може погрешно да се протолкува во прелистувачот.',
+'uploadscriptednamespace' => 'Овааа SVG-податотека го содржи недопуштениот именски простор „$1“',
+'uploadinvalidxml' => 'Не можев да го расчленам XML-от што се наоѓа во подигнатата податотека.',
 'uploadvirus' => 'Оваа податотека содржи вирус! Повеќе подробности: $1',
 'uploadjava' => 'Податотеката е од типот ZIP што содржи податотека со наставка .class за Java.
 Подигањето на податотеки за Java не е дозволено, бидејќи со нив можат да се заобиколуваат безбедносните ограничувања.',
@@ -2792,6 +2806,7 @@ $1',
 'sp-contributions-search' => 'Пребарување на придонеси',
 'sp-contributions-username' => 'IP-адреса или корисничко име:',
 'sp-contributions-toponly' => 'Прикажувај само последни ревизии',
+'sp-contributions-newonly' => 'Прикажувај само новосоздадени страници',
 'sp-contributions-submit' => 'Пребарај',
 
 # What links here
@@ -3398,13 +3413,13 @@ $1',
 'file-info' => 'големина: $1, MIME-тип: $2',
 'file-info-size' => '$1 × $2 пиксели, големина: $3, MIME-тип: $4',
 'file-info-size-pages' => '$1 × $2 пиксели, големина: $3, MIME-тип: $4, $5 {{PLURAL:$5|страница|страници}}',
-'file-nohires' => 'Не е достапна поголема резолуција.',
+'file-nohires' => 'Нема верзија со поголема разложеност.',
 'svg-long-desc' => 'SVG податотека, номинално $1 × $2 пиксели, големина: $3',
 'svg-long-desc-animated' => 'Анимирана SVG-податотека, номинално: $1 × $2 пиксели, големина: $3',
 'svg-long-error' => 'Неважечка SVG-податотека: $1',
 'show-big-image' => 'Изворна податотека',
 'show-big-image-preview' => 'Големина на овој преглед: $1.',
-'show-big-image-other' => '{{PLURAL:$2|Ð\94Ñ\80Ñ\83га Ñ\80езолÑ\83Ñ\86иÑ\98а|Ð\94Ñ\80Ñ\83ги Ñ\80езолÑ\83Ñ\86ии}}: $1.',
+'show-big-image-other' => '{{PLURAL:$2|Ð\94Ñ\80Ñ\83га Ñ\80азложеноÑ\81Ñ\82\94Ñ\80Ñ\83ги Ñ\80азложеноÑ\81Ñ\82и}}: $1.',
 'show-big-image-size' => '$1 × $2 пиксели',
 'file-info-gif-looped' => 'кружно',
 'file-info-gif-frames' => '$1 {{PLURAL:$1|кадар|кадри}}',
@@ -3412,7 +3427,7 @@ $1',
 'file-info-png-repeat' => 'пуштено {{PLURAL:$1|еднаш|$1 пати}}',
 'file-info-png-frames' => '$1 {{PLURAL:$1|кадар|кадри}}',
 'file-no-thumb-animation' => "'''Напомена: Поради технички ограничувања, минијатурите на оваа податотека нема да се анимираат.'''",
-'file-no-thumb-animation-gif' => "'''Ð\9dапомена: Ð\9fоÑ\80ади Ñ\82еÑ\85ниÑ\87ки Ð¾Ð³Ñ\80аниÑ\87Ñ\83ваÑ\9aа, Ð¼Ð¸Ð½Ð¸Ñ\98аÑ\82Ñ\83Ñ\80иÑ\82е Ð½Ð° GIF-Ñ\81лики Ñ\81о Ð²Ð¸Ñ\81ока Ñ\80езолÑ\83Ñ\86иÑ\98а како оваа нема да се анимираат.'''",
+'file-no-thumb-animation-gif' => "'''Ð\9dапомена: Ð\9fоÑ\80ади Ñ\82еÑ\85ниÑ\87ки Ð¾Ð³Ñ\80аниÑ\87Ñ\83ваÑ\9aа, Ð¼Ð¸Ð½Ð¸Ñ\98аÑ\82Ñ\83Ñ\80иÑ\82е Ð½Ð° GIF-Ñ\81лики Ñ\81о Ð²Ð¸Ñ\81ока Ñ\80азложеноÑ\81Ñ\82 како оваа нема да се анимираат.'''",
 
 # Special:NewFiles
 'newimages' => 'Галерија на нови податотеки',
@@ -3537,8 +3552,8 @@ Variants for Chinese language
 'exif-planarconfiguration' => 'Распоред на податоците',
 'exif-ycbcrsubsampling' => 'Однос на величината на Y спрема C',
 'exif-ycbcrpositioning' => 'Положби на Y и C',
-'exif-xresolution' => 'ХоÑ\80изонÑ\82ална Ñ\80езолÑ\83Ñ\86иÑ\98а',
-'exif-yresolution' => 'Ð\92еÑ\80Ñ\82икална Ñ\80езолÑ\83Ñ\86иÑ\98а',
+'exif-xresolution' => 'ХоÑ\80изонÑ\82ална Ñ\80азложеноÑ\81Ñ\82',
+'exif-yresolution' => 'Ð\92еÑ\80Ñ\82икална Ñ\80азложеноÑ\81Ñ\82',
 'exif-stripoffsets' => 'Положба на податоците',
 'exif-rowsperstrip' => 'Број на редови по блок',
 'exif-stripbytecounts' => 'Бајти по набиен блок',
@@ -3589,9 +3604,9 @@ Variants for Chinese language
 'exif-focallength-format' => '$1 мм',
 'exif-subjectarea' => 'Положба и површина на објектот',
 'exif-flashenergy' => 'Енергија на блицот',
-'exif-focalplanexresolution' => 'РезолÑ\83Ñ\86иÑ\98а Ð½Ð° Ñ\84окÑ\83Ñ\81наÑ\82а Ñ\80амнина  X',
-'exif-focalplaneyresolution' => 'РезолÑ\83Ñ\86иÑ\98а Ð½Ð° Ñ\84окÑ\83Ñ\81ната рамнина Y',
-'exif-focalplaneresolutionunit' => 'Ð\95диниÑ\86а Ð·Ð° Ñ\80езолÑ\83Ñ\86иÑ\98а Ð½Ð° Ñ\84окÑ\83Ñ\81ната рамнина',
+'exif-focalplanexresolution' => 'РазложеноÑ\81Ñ\82 Ð½Ð° Ð¶Ð°Ñ\80иÑ\88наÑ\82а Ñ\80амнина X',
+'exif-focalplaneyresolution' => 'РазложеноÑ\81Ñ\82 Ð½Ð° Ð¶Ð°Ñ\80иÑ\88ната рамнина Y',
+'exif-focalplaneresolutionunit' => 'Ð\95диниÑ\86а Ð·Ð° Ñ\80азложеноÑ\81Ñ\82 Ð½Ð° Ð¶Ð°Ñ\80иÑ\88ната рамнина',
 'exif-subjectlocation' => 'Положба на субјектот',
 'exif-exposureindex' => 'Индекс на експозицијата',
 'exif-sensingmethod' => 'Метод на сензорот',
@@ -4498,6 +4513,4 @@ $5
 'expand_templates_generate_rawhtml' => 'Прикажувај сиров HTML',
 'expand_templates_preview' => 'Преглед',
 
-# Unknown messages
-'uploadinvalidxml' => 'Не можев да го расчленам XML-от што се наоѓа во подигнатата податотека.',
 );
index a79751c..956b3a6 100644 (file)
@@ -799,7 +799,7 @@ $2',
 'gotaccount' => "താങ്കൾക്ക് അംഗത്വമുണ്ടോ? '''$1'''.",
 'gotaccountlink' => 'പ്രവേശിക്കുക',
 'userlogin-resetlink' => 'താങ്കളുടെ ലോഗിൻ വിവരങ്ങൾ മറന്നു പോയോ?',
-'userlogin-resetpassword-link' => 'താà´\99àµ\8dà´\95à´³àµ\81à´\9fàµ\86 രഹസ്യവാക്ക് മറന്നോ?',
+'userlogin-resetpassword-link' => 'താà´\99àµ\8dà´\95ൾ രഹസ്യവാക്ക് മറന്നോ?',
 'helplogin-url' => 'Help:പ്രവേശനം',
 'userlogin-helplink' => '[[{{MediaWiki:helplogin-url}}|പ്രവേശന സഹായം]]',
 'userlogin-loggedin' => 'താങ്കൾ ഇപ്പോൾ തന്നെ {{GENDER:$1|$1}} ആയി പ്രവേശിച്ചിരിക്കുന്നു.
@@ -919,7 +919,7 @@ $2',
 'resetpass-temp-password' => 'താത്കാലിക രഹസ്യവാക്ക്:',
 'resetpass-abort-generic' => 'രഹസ്യവാക്ക് മാറ്റുന്നത് ഒരു അനുബന്ധം തടഞ്ഞിരിക്കുന്നു.',
 'resetpass-expired' => 'താങ്കളുടെ രഹസ്യവാക്ക് കാലഹരണപ്പെട്ടിരിക്കുന്നു. പ്രവേശിക്കാനായി പുതിയ രഹസ്യവാക്ക് സജ്ജമാക്കുക.',
-'resetpass-expired-soft' => 'താങ്കളുടെ രഹസ്യവാക്ക് കാലഹരണപ്പെട്ടിരിക്കുന്നതിനാൽ പുനഃസജ്ജീകരിക്കേണ്ടതുണ്ട്. ഇപ്പോൾ തന്നെ പുതിയ രഹസ്യവാക്ക് തിരഞ്ഞെടുക്കുക അല്ലെങ്കിൽ പിന്നീട് പുനഃസജ്ജീകരിക്കാനായി റദ്ദാക്കുക ഞെക്കുക.',
+'resetpass-expired-soft' => 'താങ്കളുടെ രഹസ്യവാക്ക് കാലഹരണപ്പെട്ടിരിക്കുന്നതിനാൽ പുനഃസജ്ജീകരിക്കേണ്ടതുണ്ട്. ഇപ്പോൾ തന്നെ പുതിയ രഹസ്യവാക്ക് തിരഞ്ഞെടുക്കുക അല്ലെങ്കിൽ പിന്നീട് പുനഃസജ്ജീകരിക്കാനായി "{{int:resetpass-submit-cancel}}" ഞെക്കുക.',
 
 # Special:PasswordReset
 'passwordreset' => 'രഹസ്യവാക്ക് പുനഃക്രമീകരിക്കുക',
@@ -1755,14 +1755,26 @@ $1",
 'recentchanges-label-plusminus' => 'താളിന്റെ വലിപ്പം ഇത്രയും ബൈറ്റുകൾ മാറിയിരിക്കുന്നു',
 'recentchanges-legend-heading' => "'''സൂചന:'''",
 'recentchanges-legend-newpage' => '([[Special:NewPages|പുതിയ താളുകളുടെ പട്ടികയും]] കാണുക)',
-'rcnotefrom' => '<b>$2</b> മുതലുള്ള മാറ്റങ്ങൾ (<b>$1</b> എണ്ണം വരെ കാണാം).',
+'rcnotefrom' => '<strong>$2</strong> മുതലുള്ള മാറ്റങ്ങൾ (<strong>$1</strong> എണ്ണം വരെ കാണാം).',
 'rclistfrom' => '$1 മുതലുള്ള മാറ്റങ്ങൾ പ്രദർശിപ്പിക്കുക',
 'rcshowhideminor' => 'ചെറുതിരുത്തലുകൾ $1',
+'rcshowhideminor-show' => 'പ്രദർശിപ്പിക്കുക',
+'rcshowhideminor-hide' => 'മറയ്ക്കുക',
 'rcshowhidebots' => 'യന്ത്രങ്ങളെ $1',
+'rcshowhidebots-show' => 'പ്രദർശിപ്പിക്കുക',
+'rcshowhidebots-hide' => 'മറയ്ക്കുക',
 'rcshowhideliu' => 'അംഗത്വമെടുത്തിട്ടുള്ളവരെ $1',
+'rcshowhideliu-show' => 'പ്രദർശിപ്പിക്കുക',
+'rcshowhideliu-hide' => 'മറയ്ക്കുക',
 'rcshowhideanons' => 'അജ്ഞാത ഉപയോക്താക്കളെ $1',
+'rcshowhideanons-show' => 'പ്രദർശിപ്പിക്കുക',
+'rcshowhideanons-hide' => 'മറയ്ക്കുക',
 'rcshowhidepatr' => 'റോന്തു ചുറ്റിയ മാറ്റങ്ങൾ $1',
+'rcshowhidepatr-show' => 'പ്രദർശിപ്പിക്കുക',
+'rcshowhidepatr-hide' => 'മറയ്ക്കുക',
 'rcshowhidemine' => 'എന്റെ തിരുത്തലുകൾ $1',
+'rcshowhidemine-show' => 'പ്രദർശിപ്പിക്കുക',
+'rcshowhidemine-hide' => 'മറയ്ക്കുക',
 'rclinks' => 'കഴിഞ്ഞ $2 ദിവസങ്ങൾക്കുള്ളിലുണ്ടായ $1 മാറ്റങ്ങൾ പ്രദർശിപ്പിക്കുക<br />$3',
 'diff' => 'മാറ്റം',
 'hist' => 'നാൾവഴി',
@@ -1892,6 +1904,8 @@ $2 {{PLURAL:$3|തരത്തിലുള്ള പ്രമാണം|തരങ
 'php-uploaddisabledtext' => 'പി.എച്ച്.പി.യിൽ പ്രമാണ അപ്‌‌ലോഡുകൾ സാദ്ധ്യമല്ലാതാക്കിയിരിക്കുന്നു.
 ദയവായി file_uploads ക്രമീകരണങ്ങൾ പരിശോധിക്കുക.',
 'uploadscripted' => 'ഈ പ്രമാണത്തിൽ വെബ് ബ്രൗസർ തെറ്റായി വ്യാഖ്യാനിച്ചേക്കാവുന്ന എച്ച്.റ്റി.എം.എൽ. അല്ലെങ്കിൽ സ്ക്രിപ്റ്റ് കോഡ് ഉണ്ട്.',
+'uploadscriptednamespace' => 'ഈ എസ്.വി.ജി. പ്രമാണത്തിൽ ഉപയോഗിക്കാൻ പാടില്ലാത്ത നാമമേഖലയായ "$1" ഉണ്ട്',
+'uploadinvalidxml' => 'അപ്‌ലോഡ് ചെയ്ത പ്രമാണത്തിലെ എക്സ്.എം.എൽ. പാഴ്സ് ചെയ്യാൻ കഴിയില്ല.',
 'uploadvirus' => 'പ്രമാണത്തിൽ വൈറസുണ്ട്! വിശദാംശങ്ങൾ: $1',
 'uploadjava' => 'ഇത്, ജാവ .class പ്രമാണങ്ങൾ അടക്കം ചെയ്തിട്ടുള്ള ഒരു സിപ് (ZIP) പ്രമാണം ആണ്.
 സുരക്ഷാതടയലുകൾ മറികടക്കാൻ കഴിയുമെന്ന കാരണത്താൽ ജാവ പ്രമാണങ്ങൾ അപ്‌ലോഡ് ചെയ്യുന്നത് അനുവദിച്ചിട്ടില്ല.',
@@ -2245,6 +2259,7 @@ https://www.mediawiki.org/wiki/Manual:Image_Authorization കാണുക.',
 'deadendpagestext' => 'താഴെക്കാണുന്ന താളുകളിൽനിന്ന് {{SITENAME}} സം‌രംഭത്തിലെ മറ്റൊരു താളിലേയ്ക്കും കണ്ണി ചേർത്തിട്ടില്ല.',
 'protectedpages' => 'സംരക്ഷിക്കപ്പെട്ടിരിക്കുന്ന താളുകൾ',
 'protectedpages-indef' => 'അനന്തകാലത്തേയ്ക്ക് സംരക്ഷിക്കപ്പെട്ടവ മാത്രം',
+'protectedpages-summary' => 'സംരക്ഷിക്കപ്പെട്ടിട്ടുള്ളതും എന്നാൽ നിലവിലുള്ളതുമായ താളുകളുടെ പട്ടിക ഈ താളിൽ കാണാം. സൃഷ്ടിക്കുന്നതിൽ നിന്നും സംരക്ഷിക്കപ്പെട്ടിട്ടുള്ള തലക്കെട്ടുകൾക്കായി [[{{#special:ProtectedTitles}}]] കാണുക.',
 'protectedpages-cascade' => 'നിർഝരിത സംരക്ഷണങ്ങൾ മാത്രം',
 'protectedpages-noredirect' => 'തിരിച്ചുവിടലുകൾ മറയ്ക്കുക',
 'protectedpagesempty' => 'ഈ ചരങ്ങൾ ഉപയോഗിച്ചു താളുകൾ ഒന്നും തന്നെ സം‌രക്ഷിക്കപ്പെട്ടിട്ടില്ല.',
@@ -2257,6 +2272,7 @@ https://www.mediawiki.org/wiki/Manual:Image_Authorization കാണുക.',
 'protectedpages-unknown-timestamp' => 'അജ്ഞാതം',
 'protectedpages-unknown-performer' => 'അജ്ഞാത ഉപയോക്താവ്',
 'protectedtitles' => 'സംരക്ഷിക്കപ്പെട്ടിരിക്കുന്ന തലക്കെട്ടുകൾ',
+'protectedtitles-summary' => 'സൃഷ്ടിക്കുന്നതിൽ നിന്നും സംരക്ഷിക്കപ്പെട്ടിട്ടുള്ള താളുകളുടെ പട്ടിക ഇവിടെ കാണാം. സംരക്ഷിക്കപ്പെട്ടിട്ടുള്ളതും എന്നാൽ നിലവിലുള്ളതുമായ താളുകൾക്കായി [[{{#special:ProtectedPages}}]] കാണുക.',
 'protectedtitlesempty' => 'ഈ ചരങ്ങൾ ഉപയോഗിച്ചു തലക്കെട്ടുകൾ ഒന്നും തന്നെ സം‌രക്ഷിക്കപ്പെട്ടിട്ടില്ല.',
 'listusers' => 'ഉപയോക്താക്കളുടെ പട്ടിക',
 'listusers-editsonly' => 'തിരുത്തലുകൾ ചെയ്തിട്ടുള്ള ഉപയോക്താക്കളെ മാത്രം കാണിക്കുക',
@@ -2707,6 +2723,7 @@ $1',
 'sp-contributions-search' => 'ചെയ്ത സേവനങ്ങൾ',
 'sp-contributions-username' => 'ഐ.പി. വിലാസം അഥവാ ഉപയോക്തൃനാമം:',
 'sp-contributions-toponly' => 'ഒടുവിലത്തെ നാൾപ്പതിപ്പുകൾ മാത്രം പ്രദർശിപ്പിക്കുക',
+'sp-contributions-newonly' => 'താൾ സൃഷ്ടിക്കാനുള്ള തിരുത്തുകൾ മാത്രം പ്രദർശിപ്പിക്കുക',
 'sp-contributions-submit' => 'തിരയൂ',
 
 # What links here
@@ -4240,6 +4257,4 @@ $5
 'expand_templates_generate_rawhtml' => 'അസംസ്കൃത എച്ച്.റ്റി.എം.എൽ. പ്രദർശിപ്പിക്കുക',
 'expand_templates_preview' => 'എങ്ങനെയുണ്ടെന്നു കാണുക',
 
-# Unknown messages
-'uploadinvalidxml' => 'അപ്‌ലോഡ് ചെയ്ത പ്രമാണത്തിലെ എക്സ്.എം.എൽ. പാഴ്സ് ചെയ്യാൻ കഴിയില്ല.',
 );
index 1a2a60a..bc335b8 100644 (file)
@@ -160,15 +160,17 @@ $messages = array(
 
 # Categories related messages
 'pagecategories' => '{{PLURAL:$1|Анги|Ангилал}}',
-'category_header' => 'Ангид хамаарсан хуудас',
+'category_header' => '"$1" ангилал дахь хуудаснууд',
 'subcategories' => 'Ангийн бүлэг',
 'category-media-header' => '"$1" ангийн файл',
 'category-empty' => "''Одоогийн байдлаар энэ ангилалд хуудас, медиа файл байхгүй байна.''",
 'hidden-categories' => '{{PLURAL:$1|Нуугдсан ангилал|Нуугдсан ангиллууд}}',
 'hidden-category-category' => 'Нуугдсан ангиллууд',
-'category-subcat-count' => '{{PLURAL:$2|Энэ анги зөвхөн дараах дэд бүлэгтэй.|Энэ ангийн доторх $2 бүлгээс доор харагдаж буй {{PLURAL:$1| бүлэгтэй.|$1 .}}}}',
+'category-subcat-count' => '{{PLURAL:$2|Энэ ангилалд дараах дэд ангилал л байна.|Энэ ангилалд нийт $2-с дараах $1 дэд ангилал байна.}}',
 'category-subcat-count-limited' => 'Энэ ангилалд {{PLURAL:$1| дэд ангилал|$1-н дэд ангилалууд}} байна.',
-'category-article-count' => '{{PLURAL:$2|Энд нэг хуудас байна.|Энэ ангийн $2 хуудсаас доор харагдаж буй $1.}}',
+'category-article-count' => '{{PLURAL:$2|Энд нэг хуудас байна.|Энэ ангид $2 хуудас байна.}}
+
+{{PLURAL:$2|Энэ ангилалд дараах хуудас л байна.|Энэ ангилалд нийт $2-с дараах $1 хуудас байна.}}',
 'category-article-count-limited' => 'Энэ ангилалд дараах {{PLURAL:$1|хуудас|$1 хуудаснууд}} байна.',
 'category-file-count' => '{{PLURAL:$2|Энэ ангилалд дараах файл л байна.|Энэ ангилалд нийт $2-с дараах $1 файл байна.}}',
 'category-file-count-limited' => 'Энэ ангилалд дараах {{PLURAL:$1|файл|$1 файлнууд}} байна.',
@@ -207,7 +209,7 @@ $messages = array(
 'vector-action-unprotect' => 'Хамгаалалтаа солих',
 'vector-view-create' => 'Үүсгэх',
 'vector-view-edit' => 'Засварлах',
-'vector-view-history' => 'Түүхийг үзэх',
+'vector-view-history' => 'Түүх',
 'vector-view-view' => 'Унших',
 'vector-view-viewsource' => 'Кодыг харах',
 'actions' => 'Үйлдлүүд',
@@ -221,8 +223,8 @@ $messages = array(
 'help' => 'Тусламж',
 'search' => 'Хайлт',
 'searchbutton' => 'Хайх',
-'go' => 'Явах',
-'searcharticle' => 'Хайх',
+'go' => 'Үзэх',
+'searcharticle' => 'Үзэх',
 'history' => 'Хуудасны түүх',
 'history_short' => 'Түүх',
 'updatedmarker' => 'сүүлд зочилсноос хойш шинэчлэгдсэн',
@@ -236,6 +238,7 @@ $messages = array(
 'create-this-page' => 'Энэ хуудсыг үүсгэх',
 'delete' => 'Устгах',
 'deletethispage' => 'Энэ хуудсыг устга',
+'undeletethispage' => 'Энэ хуудсыг бүү устга',
 'undelete_short' => 'Устгагдсан {{PLURAL:$1|нэг засварыг|$1 засваруудыг}} сэргээх',
 'viewdeleted_short' => '{{PLURAL:$1|арилгасан засварыг|арилгасан $1 засваруудыг}} харах',
 'protect' => 'Хамгаалах',
@@ -286,7 +289,7 @@ $1',
 'copyrightpage' => '{{ns:project}}:Зохиогчийн эрх',
 'currentevents' => 'Сүүлийн үеийн мэдээ',
 'currentevents-url' => 'Project:Сүүлийн үеийн мэдээ',
-'disclaimers' => 'ТаÑ\82галзлÑ\83Ñ\83д',
+'disclaimers' => 'ТаÑ\82галзал',
 'disclaimerpage' => 'Project:Ерөнхий татгалзал',
 'edithelp' => 'Засвар хийх тухай тусламж',
 'helppage' => 'Help:Агуулга',
@@ -295,7 +298,7 @@ $1',
 'policy-url' => 'Project:Бодлого баримтлал',
 'portal' => 'Бүлгэмийн портал',
 'portal-url' => 'Project:Бүлгэмийн портал',
-'privacy' => 'Ð¥Ñ\83вийн Ð¼Ñ\8dдÑ\8dÑ\8dллийн Ñ\82алааÑ\80Ñ\85 Ð±Ð°Ñ\80имÑ\82лал',
+'privacy' => 'Ð\9dÑ\83Ñ\83Ñ\86лалÑ\8bн Ð±Ð¾Ð´Ð»Ð¾Ð³Ð¾',
 'privacypage' => 'Project:Хувийн мэдээллийн талаарх баримтлал',
 
 'badaccess' => 'Зөвшөөрлийн алдаа',
@@ -308,12 +311,12 @@ $1',
 'ok' => 'OK',
 'pagetitle' => '$1 - {{SITENAME}}',
 'retrievedfrom' => '"$1" хуудаснаас авсан',
-'youhavenewmessages' => 'Таньд $1 ($2) байна.',
+'youhavenewmessages' => '{{PLURAL:$3|Танд}} $1 ($2) байна.',
 'youhavenewmessagesfromusers' => 'Танд {{PLURAL:$3|өөр нэгэн хэрэглэгчээс |$3 хэрэглэгчээс}} $1 ирсэн байна ($2).',
-'youhavenewmessagesmanyusers' => 'Танд ($2) Ð¾Ð»Ð¾Ð½ Ñ\85Ñ\8dÑ\80Ñ\8dглÑ\8dгÑ\87идÑ\8dÑ\8dÑ\81 $1.',
+'youhavenewmessagesmanyusers' => 'Танд ($2) олон хэрэглэгчдээс $1.',
 'newmessageslinkplural' => '{{PLURAL:$1|шинэ зурвас}}',
 'newmessagesdifflinkplural' => '{{PLURAL:$1|сүүлд хийгдсэн өөрчлөлт}}',
-'youhavenewmessagesmulti' => 'Таньд $1 дээр шинэ мессеж ирсэн байна',
+'youhavenewmessagesmulti' => 'Танд $1 дээр шинэ зурвас ирсэн байна',
 'editsection' => 'засварлах',
 'editold' => 'засварлах',
 'viewsourceold' => 'кодыг харах',
@@ -321,10 +324,10 @@ $1',
 'viewsourcelink' => 'кодыг харах',
 'editsectionhint' => 'Хэсгийг засварлах: $1',
 'toc' => 'Агуулга',
-'showtoc' => 'үзүүлэх',
-'hidetoc' => 'нуух',
-'collapsible-collapse' => 'Ð\91Ñ\83Ñ\83лгах',
-'collapsible-expand' => 'ТÑ\8dлэх',
+'showtoc' => 'дэлгэх',
+'hidetoc' => 'хумих',
+'collapsible-collapse' => 'Ð¥Ñ\83мих',
+'collapsible-expand' => 'Ð\94Ñ\8dлгэх',
 'thisisdeleted' => '$1-г харах эсвэл сэргээх үү?',
 'viewdeleted' => '$1-г харах уу?',
 'restorelink' => '{{PLURAL:$1|арилгасан засвар|арилгасан $1 засварууд}}',
@@ -336,7 +339,7 @@ $1',
 'page-rss-feed' => '"$1"-н RSS фийд',
 'page-atom-feed' => '"$1"-н Atom фийд',
 'feed-atom' => 'Атом',
-'red-link-title' => '$1 (хуудас бичигдээгүй байна)',
+'red-link-title' => '$1 (ийм хуудас байхгүй)',
 'sort-descending' => 'Буурахаар эрэмбэлэх',
 'sort-ascending' => 'Өсөхөөр эрэмбэлэх',
 
@@ -350,7 +353,7 @@ $1',
 'nstab-mediawiki' => 'Мэдэгдэл',
 'nstab-template' => 'Загвар',
 'nstab-help' => 'Тусламж',
-'nstab-category' => 'Анги',
+'nstab-category' => 'Ангилал',
 
 # Main script and global functions
 'nosuchaction' => 'Тийм үйлдэл байхгүй байна',
@@ -398,7 +401,7 @@ $1',
 'cannotdelete-title' => '"$1" хуудсыг устгаж чадсангүй',
 'delete-hook-aborted' => 'Хүк устгалыг зогсоолоо.
 Шалтгаан өгөгдсөнгүй.',
-'badtitle' => 'Ð\91олоÑ\85гүй Ð³Ð°Ñ\80Ñ\87иг',
+'badtitle' => 'Ð¥Ò¯Ñ\87ингүй Ñ\85Ñ\83Ñ\83даÑ\81нÑ\8b Ð½Ñ\8dÑ\80 Ð±Ð°Ð¹Ð½Ð°',
 'badtitletext' => 'Оруулсан хуудасны нэр тань хүчингүй, хоосон, эсвэл буруу холбосон интер-хэл буюу интер-викигийн нэр байна. Нэрэнд хэрэглэгдэж болохгүй тэмдэгт орсон байж болзошгүй.',
 'perfcached' => 'Дараах тоо баримт нь нөөц хуулбар учраас хуучирсан мэдээлэлтэй байж магадгүй. Дээд тал нь {{PLURAL:$1|нэг илэрц|$1 илэрцүүд}} нөөцөд бэлэн байна.',
 'perfcachedts' => 'Дараах тоо баримт нь нөөц хуулбар учраас хуучирсан мэдээлэлтэй байж магадгүй. Дээд тал нь {{PLURAL:$1|нэг илэрц|$1 илэрцүүд}} нөөцөд бэлэн байна.',
@@ -467,7 +470,7 @@ $2',
 'userlogout' => 'Гарах',
 'notloggedin' => 'Нэвтрээгүй байна',
 'userlogin-joinproject' => '{{SITENAME}}-д бүртгүүлэх',
-'nologin' => "Бүртгэлгүй юу? '''$1'''.",
+'nologin' => "Бүртгүүлж амжаагүй юу? '''$1'''.",
 'nologinlink' => 'Бүртгүүлэх',
 'createaccount' => 'Бүртгүүлэх',
 'gotaccount' => "Та бүртгэлтэй юу? '''$1'''",
@@ -637,7 +640,7 @@ $2
 'link_tip' => 'Дотоод холбоос',
 'extlink_sample' => 'http://www.example.com холбоосны нэр',
 'extlink_tip' => 'Гадны холбоос (эхэнд нь http:// бичихээ мартуузай)',
-'headline_sample' => 'Ð\93аÑ\80Ñ\87игийн Ñ\82екÑ\81Ñ\82',
+'headline_sample' => 'Гарчгийн текст',
 'headline_tip' => '2-р түвшний гарчиг',
 'nowiki_sample' => 'Энд хэлбэршүүлээгүй текстээ оруулна уу',
 'nowiki_tip' => 'Вики форматыг хэрэглэхгүй байх',
@@ -878,13 +881,9 @@ $3-н тодорхойлсон шалтгаан нь ''$2''",
 'last' => 'сүүлийн',
 'page_first' => 'эхний',
 'page_last' => 'сүүлийн',
-'histlegend' => "'''Тухайн нэг хувилбарыг одооных, өмнөхтэй нь харьцуулах''': (одоо) = одооныхоос хэр өөр байсныг үзэх
-(өмнөхөөс) = өмнөхөөсөө өөрчлөгдсөн хэсэг
-Б = бага зэргийн засвар
+'histlegend' => 'Радио товчлууруудыг сонгож дарсаны дараа enter товчлуурыг, эсвэл хуудасны доод талд байгаа товчлуур дээр дарж засваруудыг хооронд нь харьцуулна уу.<br />
 
-<br />
-'''Тодорхой хоёр хувилбар сонгон харьцуулах''': 
-Хоёр хувилбар сонгон өмнөх дугуй дүрсийг тэмдэглэж \"enter\" товч дарах буюу доорх товчыг дарна.",
+Тайлбар: strong>({{int:cur}})</strong> = хамгийн шинэ хувилбартай харьцуулалт, <strong>({{int:last}})</strong> = өмнөх хувилбартайх харьцуулалт, <strong>{{int:minoreditletter}}</strong> = бага хэмжээний засвар',
 'history-fieldset-title' => 'Түүх сөхье',
 'history-show-deleted' => 'Зөвхөн устгагдсаныг',
 'histfirst' => 'хамгийн эхэнд',
@@ -1361,9 +1360,9 @@ $1 тэмдэгтээс богино байх ёстой.',
 'recentchanges-feed-description' => 'Вики дахь хамгийн сүүлийн өөрчлөлтүүдийг хянах.',
 'recentchanges-label-newpage' => 'Энэ засвар шинэ хуудсыг үүсгэсэн байна',
 'recentchanges-label-minor' => 'Энэ нь бага зэргийн засвар байна',
-'recentchanges-label-bot' => 'Энэ засварыг бот гүйцэтгэсэн байна',
+'recentchanges-label-bot' => 'Энэ засварыг робот гүйцэтгэсэн байна',
 'recentchanges-label-unpatrolled' => 'Энэ засварыг одоогийн байдлаар манаагүй байна',
-'recentchanges-legend-newpage' => '([[Special:NewPages|Шинэ хуудсуудын жагсаалтыг]] бас үзнэ үү.',
+'recentchanges-legend-newpage' => '([[Special:NewPages|тэдгээрийг жагсааж үзэх]]',
 'rcnotefrom' => "Доорх нь '''$2'''-с хойших өөрчлөлтүүд ('''$1''' хүртэлхийг харуулав) юм.",
 'rclistfrom' => '$1-с хойших шинэ засваруудыг үзүүлэх',
 'rcshowhideminor' => 'Бага зэргийн засваруудыг $1',
@@ -1833,6 +1832,7 @@ URL нь зөв болон сайт ажиллагаатай байгаа эсэ
 'protectedpages-indef' => 'Зөвхөн хугацаагүй хамгаалалтууд',
 'protectedpages-cascade' => 'Зөвхөн давхар хамгаалалтууд',
 'protectedpagesempty' => 'Эдгээр параметрээр хамгаалагдсан хуудас байхгүй байна.',
+'protectedpages-page' => 'Хуудас',
 'protectedtitles' => 'Хамгаалагдсан гарчигууд',
 'protectedtitlesempty' => 'Эдгээр параметрээр хамгаалагдсан гарчиг байхгүй байна.',
 'listusers' => 'Хэрэглэгчдийн жагсаалт',
@@ -1859,7 +1859,7 @@ URL нь зөв болон сайт ажиллагаатай байгаа эсэ
 # Book sources
 'booksources' => 'Номон эх сурвалжууд',
 'booksources-search-legend' => 'Номын эх сурвалж хайх',
-'booksources-go' => 'Явах',
+'booksources-go' => 'Үзэх',
 'booksources-text' => 'Доорх нь шинэ, хуучин ном зардаг өөр сайт руу очих холбоосуудын жагсаалт бөгөөд таны хайж буй номнуудын тухай дэлгэрэнгүй мэдээлэл байх магадлалтай:',
 'booksources-invalid-isbn' => 'Өгөгдсөн ISBN хүчингүй юм шиг байна; эх сурвалжаас зөв хуулсан эсэхээ шалгана уу.',
 
@@ -1892,7 +1892,7 @@ URL нь зөв болон сайт ажиллагаатай байгаа эсэ
 'cachedspecial-refresh-now' => 'Саяханы хуудсыг харах',
 
 # Special:Categories
-'categories' => 'Анги',
+'categories' => 'Ангиллууд',
 'categoriespagetext' => 'Дараах {{PLURAL:$1|ангилалд|ангиллуудад}} хуудас эсвэл медиа файл агуулагдаж байна.
 [[Special:UnusedCategories|Хэрэглэгдэхгүй байгаа]] ангиллуудыг энд харуулсангүй.
 [[Special:WantedCategories|Хэрэгтэй ангиллууд]] гэдгийг харна уу.',
@@ -1927,7 +1927,7 @@ URL нь зөв болон сайт ажиллагаатай байгаа эсэ
 'activeusers-intro' => 'Энэ нь сүүлийн $1 {{PLURAL:$1|өдөрт|өдөрт}} ямар нэг байдлаар үйлдэл хийсэн хэрэглэгчдийн жагсаалт юм.',
 'activeusers-count' => 'Сүүлийн {{PLURAL:$3|нэг өдөрт|$3 өдөрт}} $1 {{PLURAL:$1|засвар|засвар}}',
 'activeusers-from' => 'Хамгийн эхэлж харуулах хэрэглэгч:',
-'activeusers-hidebots' => 'Ботуудыг нуух',
+'activeusers-hidebots' => 'роботуудыг нуух',
 'activeusers-hidesysops' => 'Администраторуудыг нуух',
 'activeusers-noresult' => 'Хэрэглэгч олдсонгүй.',
 
@@ -2245,8 +2245,8 @@ $1',
 'contribsub2' => 'Хэрэглэгч: {{GENDER:$3|$1}} ($2)',
 'nocontribs' => 'Энэ шалгуурт тохирох өөрчилсөн зүйлүүд олдсонгүй.',
 'uctop' => '(одоох)',
-'month' => 'Дараах сараас (өмнөх засварууд нь ч орно):',
-'year' => 'Ð\90Ñ\80Ñ\8bн Ð¶Ð¸Ð»Ñ\8dÑ\8dÑ\81 Ó©Ð¼Ð½Ó©Ñ\85:',
+'month' => 'Дараах сараас урагш:',
+'year' => 'Ð\90Ñ\80Ñ\8bн Ð¾Ð½:',
 
 'sp-contributions-newbies' => 'Зөвхөн шинэ бүртгэлүүдийн хувь нэмрийг харуулах',
 'sp-contributions-newbies-sub' => 'Шинээр бүртгүүлсэн хэрэглэгчид',
@@ -2360,7 +2360,7 @@ $1',
 'blocklink' => 'түгжих',
 'unblocklink' => 'түгжээг тайлах',
 'change-blocklink' => 'түгжээг өөрчлөх',
-'contribslink' => 'хувь нэмэр',
+'contribslink' => 'оруулсан хувь нэмэр',
 'emaillink' => 'цахим шуудан явуулах',
 'autoblocker' => 'Автоматаар түгжигдлээ. Учир нь таны IP хаягийг "[[User:$1|$1]]" нь хэрэглэж байжээ. "$1"-г түгжих болсон шалтгаан нь: "\'\'\'$2\'\'\'"',
 'blocklogpage' => 'Түгжээний лог',
@@ -2631,7 +2631,7 @@ $1',
 'tooltip-search' => '{{SITENAME}}-с хайх',
 'tooltip-search-go' => 'Ийм нэртэй хуудас байгаа эсэхийг үзье',
 'tooltip-search-fulltext' => 'Энэ текстийг хуудсуудаас хайх',
-'tooltip-p-logo' => 'Нүүр хуудас',
+'tooltip-p-logo' => 'Нүүр хуудаст зочлох',
 'tooltip-n-mainpage' => 'Нүүр хуудаст зочлох',
 'tooltip-n-mainpage-description' => 'Нүүр хуудаст зочлох',
 'tooltip-n-portal' => 'Энэ төслийн тухай, түүн дээр юу хийж болох, ба хаана зүйлсийг мэдэж авах тухай',
@@ -2649,7 +2649,7 @@ $1',
 'tooltip-t-specialpages' => 'Тусгай хуудаснуудын жагсаалт',
 'tooltip-t-print' => 'Энэ хуудасны хувилж болох хувилбар',
 'tooltip-t-permalink' => 'Хуудасны одоогийн хувилбар луу очих тогтмол линк',
-'tooltip-ca-nstab-main' => 'Өгүүллийн хуудсыг үзэх',
+'tooltip-ca-nstab-main' => 'Өгүүлж Ð±Ñ\83й Ð³Ð¾Ð» хуудсыг үзэх',
 'tooltip-ca-nstab-user' => 'Хэрэглэгчийн хуудсыг үзэх',
 'tooltip-ca-nstab-media' => 'Медиа хуудсыг үзэх.',
 'tooltip-ca-nstab-special' => 'Энэ бол тусгай хуудас, та үүнийг шууд засварлах боломжгүй.',
@@ -3330,6 +3330,7 @@ $5
 
 # Special:SpecialPages
 'specialpages' => 'Тусгай хуудсууд',
+'specialpages-note-top' => 'Томъёолбор',
 'specialpages-note' => '* Ердийн тусгай хуудсууд.
 * <strong class="mw-specialpagerestricted">Хориотой тусгай хуудсууд.</strong>',
 'specialpages-group-maintenance' => 'Засвар үйлчилгээний тайлангууд',
@@ -3361,7 +3362,7 @@ $5
 
 # Special:Tags
 'tags' => 'Хүчинтэй өөрчлөлтийн тагууд',
-'tag-filter' => '[[Special:Tags|Тагийн]] шүүлтүүр:',
+'tag-filter' => '[[Special:Tags|Үгээр]] шүүх:',
 'tag-filter-submit' => 'Шүүлтүүр',
 'tags-title' => 'Тагууд',
 'tags-intro' => 'Энэхүү хуудсанд програм хангамжийн засвар гэж тэмдэглэх боломжтой тагууд болон тэдний тайлбарыг жагсаан бичив.',
index 59fcdbe..b5d8bf2 100644 (file)
@@ -1814,6 +1814,7 @@ $1",
 'php-uploaddisabledtext' => 'PHP मध्ये संचिका चढवणे प्रतिबंधित केले आहे.
 कृपया file_uploads मांडणी (setting) तपासावी.',
 'uploadscripted' => 'या संचिकेत HTML किंवा स्क्रिप्ट कोडचा आंतर्भाव आहे, त्याचा एखाद्या विचरकाकडून विचित्र अर्थ लावला जाऊ शकतो.',
+'uploadinvalidxml' => 'अपभारीत संचिकेतील XML पार्स करता आले नाही.',
 'uploadvirus' => 'ह्या संचिकेत व्हायरस आहे. अधिक माहिती: $1',
 'uploadjava' => 'ही फाईल झीप ह्या प्रकारातील आहे ज्यामधे जावा .क्लास फाईल. आहे,जावा फाईलचे अपभारणास परवानगी नाही कारण त्याने सुरक्षा-बंधने टाळल्या जाऊ शकतात.',
 'upload-source' => 'स्रोत संचिका',
@@ -4097,6 +4098,4 @@ $5
 'expand_templates_generate_xml' => 'XML चा पार्स (parse) वृक्ष दाखवा',
 'expand_templates_preview' => 'झलक',
 
-# Unknown messages
-'uploadinvalidxml' => 'अपभारीत संचिकेतील XML पार्स करता आले नाही.',
 );
index aa5c08a..c55aa06 100644 (file)
@@ -1724,6 +1724,7 @@ Jika anda memiliki imej ini dalam leraian penuh, sila muat naik fail tersebut. J
 'uploaddisabledtext' => 'Ciri muat naik fail dimatikan.',
 'php-uploaddisabledtext' => 'Pemuatnaikan fail PHP dilumpuhkan. Sila semak tetapan file_uploads.',
 'uploadscripted' => 'Fail ini mengandungi kod HTML atau skrip yang boleh disalahtafsirkan oleh pelayar web.',
+'uploadinvalidxml' => 'XML dalam fail yang dimuat naik ini tidak dapat dihuraikan.',
 'uploadvirus' => 'Fail tersebut mengandungi virus! Butiran: $1',
 'uploadjava' => 'Fail ini ialah fail ZIP yang mengandungi fail .class Java.
 Memuat naik fail Java tidak dibenarkan, kerana boleh menyebabkan sekatan keselamatan dipintas.',
@@ -4074,6 +4075,4 @@ Sebenarnya, ia mengembangkan segalanya dalam tanda kurung panah berganda.',
 'expand_templates_generate_rawhtml' => 'Paparkan HTML mentah',
 'expand_templates_preview' => 'Pralihat',
 
-# Unknown messages
-'uploadinvalidxml' => 'XML dalam fail yang dimuat naik ini tidak dapat dihuraikan.',
 );
index d1c2621..c5a3341 100644 (file)
@@ -1870,6 +1870,7 @@ Om du fortsatt ønsker å laste opp filen, gå tilbake og last den opp under et
 'uploaddisabledtext' => 'Opplasting er slått av.',
 'php-uploaddisabledtext' => 'PHP-filopplasting er deaktivert. Sjekk innstillingen for file_uploads.',
 'uploadscripted' => 'Denne filen inneholder HTML eller skripting som kan feiltolkes av en nettleser.',
+'uploadinvalidxml' => 'XML-en i den opplastede filen kunne ikke tolkes.',
 'uploadvirus' => 'Denne filen inneholder virus! Detaljer: $1',
 'uploadjava' => 'Filen er en ZIP-fil som inneholder en Java-fil av typen .class.
 Det er ikke tillatt å laste opp Java-filer, fordi de kan omgå sikkerhetsrestriksjoner.',
@@ -4236,6 +4237,4 @@ Faktisk utvider den det meste innkapslet i doble krøllparenteser.',
 'expand_templates_generate_rawhtml' => 'Vis ubehandlet HTML',
 'expand_templates_preview' => 'Forhåndsvisning',
 
-# Unknown messages
-'uploadinvalidxml' => 'XML-en i den opplastede filen kunne ikke tolkes.',
 );
index 6928110..80f7426 100644 (file)
@@ -330,7 +330,7 @@ $1',
 'youhavenewmessagesfromusers' => 'तपाईंको लागि  {{PLURAL:$3|प्रयोगकर्ता|$3 प्रयोगकर्ताहरु}} ($2) बाट $1',
 'youhavenewmessagesmanyusers' => 'तपाईँलाई धेरै प्रयोगकर्ताहरू($2) बाट $1 छ ।',
 'newmessageslinkplural' => '{{PLURAL:$1|एउटा नयाँ सन्देश|999=नयाँ सन्देशहरू}}',
-'newmessagesdifflinkplural' => 'à¤\85नà¥\8dतिम {{PLURAL:$1|समà¥\8dपादन|समà¥\8dपादनहरू}}',
+'newmessagesdifflinkplural' => 'à¤\85नà¥\8dतिम {{PLURAL:$1|परिवरà¥\8dतन|999=परिवरà¥\8dतनहरू}}',
 'youhavenewmessagesmulti' => 'तपाईंको लागि $1 मा  नयाँ सन्देशहरू छन्',
 'editsection' => 'सम्पादन',
 'editold' => 'सम्पादन गर्ने',
@@ -422,6 +422,7 @@ $1',
 'cannotdelete-title' => 'पृष्ठ  "$1" लाई मेट्न सकिएन',
 'delete-hook-aborted' => 'हुकले सम्पादनकार्य बन्द गरिदियो ।
 कुनै कारण दिइएन ।',
+'no-null-revision' => '$1 पृष्ठको लागि खालि पुनरावलोकन सिर्जना गर्न सकिएन',
 'badtitle' => 'गलत शीर्षक',
 'badtitletext' => 'अनुरोध गरेको पृष्ठ शीर्षक अमान्य, खाली वा गलत रुपमा अन्तर भाषा वा अन्तर विकी सम्बन्ध गरिएको थियो।  यसमा शीर्षकमा प्रयोग गर्न नमिल्ने एक वा बढी अक्षरहरू रहेका हुनसक्छन् ।',
 'perfcached' => 'तलको डाटाहरु क्याचमा रहेका कुराहरु हुन्। अपटुडेट नहुनपनि सक्छन्।अधिकतम {{PLURAL:$1|नतिजा|$1 नतिजाहरू}} क्यासमा उपलब्ध छ।',
@@ -448,6 +449,8 @@ $2',
 'customjsprotected' => 'तपाईलाई यस जाभास्कृप्ट पृष्ठ सम्पादन गर्ने अनुमति छैन, किनकी यसमा कुनै अर्को प्रयोगकर्ताको व्यक्तिगत अभिरुचीहरु संग्रहित छन् ।',
 'mycustomcssprotected' => 'यस CSSपृष्ठ सम्पादन गर्नको लागि लागि तपाईँलाई अनुमति छैन ।',
 'mycustomjsprotected' => 'यस JavaScript पृष्ठ सम्पादन गर्नको लागि लागि तपाईँलाई अनुमति छैन ।',
+'myprivateinfoprotected' => 'तपाईँसँग तपाईँको निजी जानकारीहरू सम्पादन गर्ने अनुमती छैन',
+'mypreferencesprotected' => 'तपाईँसँग तपाईँको अभिरुचीहरू सम्पादन गर्ने अनुमती छैन',
 'ns-specialprotected' => 'विशेष पृष्ठ सम्पादन गर्न सकिदैन ।',
 'titleprotected' => ' [[User:$1|$1]]द्वारा यो शीर्षक निर्माणहुनबाट जोगाइएको छ।
 कारण   "\'\'$2\'\'" हो ।',
@@ -549,7 +552,7 @@ $2',
 'passwordtooshort' => 'पासवर्ड कम्तिमा {{PLURAL:$1|१ अक्षर |$1 अक्षरहरु}}को हुनुपर्छ ।',
 'password-name-match' => 'तपाईँको प्रवेशशव्द प्रयोगकर्ता नाम भन्दा फरक हुनुपर्छ ।',
 'password-login-forbidden' => 'यो प्रयोगकर्ता नाम र प्रवेश शव्द वर्जित गरिएकोछ ।',
-'mailmypassword' => 'नयाà¤\81 à¤ªà¥\8dरवà¥\87शशवà¥\8dद à¤\87मà¥\87ल गर्नुहोस्',
+'mailmypassword' => 'पासवरà¥\8dड à¤ªà¥\82रà¥\8dवनिरà¥\8dधारित गर्नुहोस्',
 'passwordremindertitle' => '{{SITENAME}}को लागि नयाँ अस्थायी पासवर्ड',
 'passwordremindertext' => 'कसैले (सायद तपाईँ, IP ठेगाना $1 बाट), {{SITENAME}}($4) को लागि नयाँ प्रवेशशव्द अनुरोध गर्नुभएको छ । प्रयोगकर्ता "$2" को लागि नयाँ अस्थायी प्रवेशशव्द "$3"तयार पारिएको छ। यदि यो तपाईको इच्छामा भएको भए अहिले तपाईँले प्रवेशगरी नयाँ प्रवेशशव्द छान्नु पर्ने हुन्छ।
 तपाईको अस्थायी प्रवेशशव्द  {{PLURAL:$5|एक दिन|$5 दिनहरू पछि}} अमान्य हुनेछ ।
@@ -561,8 +564,8 @@ $2',
 'passwordsent' => '"$1" को लागि दर्ता गरिएको ई-मेल ठेगानामा एक प्रवेशशव्द पठाइएको छ।
 कृपया त्यसलाई प्राप्त गरेपछि प्रवेश गर्नुहोला ।',
 'blocked-mailpassword' => 'तपाईको IP ठेगानालाई सम्पादनगर्नबाट रोक लगाइएको छ, र त्यसैले दुरुपयोग रोक्नको लागि प्रवेशशव्द पुनर्लाभ प्रक्रिया प्रयोग गर्न अनुमति छैन ।',
-'eauthentsent' => 'दिइएको इमेल ठेगानामा  किटानी इमेल पठाइएको छ ।
-तपाà¤\88à¤\95à¥\8b à¤\96ातामा à¤\85रà¥\81 à¤\87मà¥\87ल à¤ªà¤ à¤\89नà¥\81 à¤\85à¤\98ि , à¤\87मà¥\87लमा à¤²à¥\87à¤\96िà¤\8fà¤\95à¥\8b à¤®à¤¾à¤°à¥\8dà¤\97दरà¥\8dशन à¤\85नà¥\81सार , à¤¤à¥\8dयà¥\8b à¤\96ाता à¤¤à¤ªà¤¾à¤\88à¤\81à¤\95à¥\88 à¤¹à¥\8b à¤­à¤¨à¥\87र à¤¨à¤¿à¤¶à¥\8dà¤\9aित à¤\97राà¤\89नु पर्नेछ ।',
+'eauthentsent' => 'दिइएको इमेल ठेगानामा इमेल पठाइएको छ ।
+तपाà¤\88à¤\81à¤\95à¥\8b à¤\96ातामा à¤\85रà¥\81 à¤\87मà¥\87ल à¤ªà¤ à¤\89नà¥\81 à¤\85à¤\98ि , à¤\87मà¥\87लमा à¤²à¥\87à¤\96िà¤\8fà¤\95à¥\8b à¤®à¤¾à¤°à¥\8dà¤\97दरà¥\8dशन à¤\85नà¥\81सार , à¤¤à¥\8dयà¥\8b à¤\96ाता à¤¤à¤ªà¤¾à¤\88à¤\81à¤\95à¥\88 à¤¹à¥\8b à¤­à¤¨à¥\87र à¤¨à¤¿à¤¶à¥\8dà¤\9aित à¤\97रà¥\8dनु पर्नेछ ।',
 'throttled-mailpassword' => 'बितेको {{PLURAL:$1|घण्टा|$1 घण्टाहरु}} भित्र एउटा प्रवेशशब्द अनुस्मारक पठाई सकिएको छ।
 दुरुपयोगबाट बचाउकोलागि प्रत्येक {{PLURAL:$1|घण्टा|$1 घण्टाहरु}}मा केवल एउटा प्रवेशशब्द अनुस्मारक पठाइन्छ।',
 'mailerror' => ' चिठी :$1 पठाउँदा त्रुटी भयो',
@@ -1300,6 +1303,8 @@ HTML ट्यागहरु जाँच्नुहोस् ।',
 'right-editusercssjs' => 'प्रयोगकर्ताको CSS र JS फाइलहरु सम्पादन गर्ने',
 'right-editusercss' => 'प्रयोगकर्ताको CSS फाइलहरु सम्पादन गर्ने',
 'right-edituserjs' => 'प्रयोकर्ताको  JS फाइलहरु सम्पादनगर्ने',
+'right-editmyusercss' => 'तपाईँको आफ्नो CSS फाइलहरू सम्पादन गर्नुहोस्',
+'right-editmyuserjs' => 'तपाईँको आफ्नो जाभा स्क्रिप्ट फाइलहरू सम्पादन गर्ने',
 'right-rollback' => 'पछिल्लो प्रयोगकर्ताको सम्पादनहरुको छरितो रुपमा पछाडि पर्काउने',
 'right-markbotedits' => 'पछाडि फर्काउने सम्पादनहरुलाई बोट सम्पादनकारुपमा चिनो लगाउने',
 'right-noratelimit' => 'दर सीमाले  असर नपार्ने',
@@ -1579,6 +1584,7 @@ $1',
 'listfiles_size' => 'आकार',
 'listfiles_description' => 'वर्णन',
 'listfiles_count' => 'संस्करणहरु',
+'listfiles-latestversion' => 'हालको संस्करण',
 'listfiles-latestversion-yes' => 'हो',
 'listfiles-latestversion-no' => 'हैन',
 
@@ -1603,6 +1609,7 @@ $1',
 'linkstoimage' => 'यस फाइलमा निम्न{{PLURAL:$1|पृष्ठ जोडिन्छ|$1 पृष्ठहरु जोडिन्छन}}:',
 'nolinkstoimage' => 'यो फाईलसंग लिंकभएको कुनै पृष्ठ छैन.',
 'morelinkstoimage' => 'हेर्नुहोस् [[Special:WhatLinksHere/$1|थप लिंकहरु]] यो फाइलको।',
+'linkstoimage-redirect' => '$1 (फाइल अनुप्रेषण) $2',
 'sharedupload' => 'यो फाइल $1 को हो र अन्य परियोजनामा प्रयोग गरिएको हुनसक्छ।',
 'filepage-nofile' => 'यस नामको फाइल छैन।',
 'filepage-nofile-link' => 'यस नामको फाइल छैन तर तपाईं [$1 यो उर्ध्वभरण गर्न सक्नुहुन्छ].',
@@ -1610,6 +1617,7 @@ $1',
 'shared-repo-from' => ' $1 बाट',
 'shared-repo' => 'एल साझा भण्डार',
 'shared-repo-name-wikimediacommons' => 'विकिमीडिया कमन्स',
+'upload-disallowed-here' => 'तपाईँले यो फाइल अधिलेखन गर्न सक्नुहुन्न ।',
 
 # File reversion
 'filerevert' => 'पूर्वस्थिति $1 मा फर्काउने',
@@ -1681,6 +1689,8 @@ $1',
 'statistics-users-active-desc' => 'प्रयोगकर्ताहरु जो{{PLURAL:$1|बितेको एक दिन|बितेका $1 दिनहरु}}देखि  जो सक्रिय छन्',
 'statistics-mostpopular' => 'सबैभन्दा धेरै हेरिएको पृष्ठहरु',
 
+'pageswithprop-submit' => 'जाने',
+
 'doubleredirects' => 'दोहोरो अनुप्रेषण',
 'double-redirect-fixed-move' => '[[$1]] सारिएको छ।
 यसले [[$2]] तिर अनुप्रेषित गर्दछ।',
@@ -1737,6 +1747,13 @@ $1',
 'protectedpages-indef' => 'नखुलेको सुरक्षा मात्र',
 'protectedpages-cascade' => 'लामबद्ध सुरक्षाहरु मात्रा',
 'protectedpagesempty' => 'दिइएको प्यारामिटर प्रयोग गरि सुरक्षा गरिएका पृष्ठहरु छैनन् ।',
+'protectedpages-page' => 'पृष्ठ',
+'protectedpages-expiry' => 'सकिनेछ',
+'protectedpages-performer' => 'प्रयोगकर्ता सुरक्षित गरिँदै',
+'protectedpages-params' => 'सुरक्षा प्यारामेटर',
+'protectedpages-reason' => 'कारण',
+'protectedpages-unknown-timestamp' => 'अज्ञात',
+'protectedpages-unknown-performer' => 'अज्ञात प्रयोगकर्ता',
 'protectedtitles' => 'सुरक्षा गरिएका शिर्षकहरु',
 'protectedtitlesempty' => 'दिइएको प्यारामिटर प्रयोग गरि सुरक्षा गरिएका शीर्षकहरु छैनन् ।',
 'listusers' => 'प्रयोगकर्ता सूची',
@@ -1843,6 +1860,7 @@ $1',
 'mailnologin' => 'ईमेल पठाउने ठेगाना नै भएन ।',
 'mailnologintext' => 'तपाईले अरु प्रयोगकर्ताहरुलाई ईमेल पठाउनको लागि आफु पहिले [[Special:UserLogin|प्रवेश(लगइन)गरेको]] हुनुपर्छ र [[Special:Preferences|आफ्नो रोजाइहरुमा]] एउटा वैध ईमेल ठेगाना भएको हुनुपर्छ।',
 'emailuser' => 'यो प्रयोगकर्तालाई ई-मेल पठाउनुहोस्',
+'emailuser-title-notarget' => 'प्रयोगकर्तालाई इमेल गर्नुहोस्',
 'emailpage' => 'प्रयोगकर्तालाई इमेल गर्नुहोस्',
 'usermailererror' => 'मेल अब्जेक्टले देखाएको त्रुटि:',
 'defemailsubject' => '{{SITENAME}} प्रयपोगकर्ता "$1" बाट इमेल',
@@ -1991,6 +2009,9 @@ proceed with caution.',
 'rollback-success' => '$1द्वारा उल्टाइएका सम्पादनहरु;
 पछिल्लो संशोधनमा $2द्वारा परिवर्तन गरि पुनः फर्काइएको।',
 
+# Edit tokens
+'sessionfailure-title' => 'सत्र त्रुटी',
+
 # Protect
 'protectlogpage' => 'सुरक्षण लग',
 'protectedarticle' => '"[[$1]]" लाई सुरक्षित गरियो',
@@ -2016,6 +2037,7 @@ proceed with caution.',
 'protect-level-sysop' => 'प्रबन्धकहरु मात्र',
 'protect-summary-cascade' => 'लाममा राख्ने',
 'protect-expiring' => '$1 (UTC) मा सकिने छ ।',
+'protect-expiring-local' => 'समाप्ति समय $1',
 'protect-expiry-indefinite' => 'अनिश्चित काल',
 'protect-cascade' => 'यो पृष्ठमा संलग्न सुरक्षित पृष्ठहरु(लामबद्द सुरक्षा)',
 'protect-cantedit' => 'तपाईँ यस पृष्ठको सुरक्षा स्तर परिवर्तन गर्न सक्नुहुन्न , किन कि तपाईँलाई यसको सम्पादनको अनुमति छैन ।',
@@ -2080,8 +2102,8 @@ $3द्वारा $1को ($4को  समय $5 मा) मेटाइए
 'undeletedrevisions' => '{{PLURAL:$1|एउटा संशोधन|$1 संशोधनहरु}} पुनर्स्थापित गरियो',
 'undeletedrevisions-files' => '{{PLURAL:$1|एउटा संशोधन|$1 संशोधनहरु}} र {{PLURAL:$2|एउटा फाइल|$2 फाइलहरु}} पुनर्स्थापित गरियो',
 'undeletedfiles' => '{{PLURAL:$1|१ फाइल|$1 फाइलहरु }} पूर्वस्थितिमा ल्याइयो',
-'cannotundelete' => 'मेटाएको रद्द गर्ने काम असफल भयो;
-कसैले पहिले नैं मेटाएको रद्द गरिसकेकोछ।',
+'cannotundelete' => 'मेटाएको रद्द गर्ने काम असफल भयो:
+$1',
 'undeletedpage' => "'''$1लाई पूर्वावस्थामा ल्याइयो'''
 भर्खरै मेटाइएको रिकर्डहरु र पुनर्स्थापनाहरु हेर्न [[Special:Log/delete|मेटाइएको लग]]मा जानुहोस्।",
 'undelete-header' => 'भर्खर मेटिएका पृष्ठहरु हेर्न [[Special:Log/delete|मेटाइएका लग]]मा जानुहोस्।',
@@ -2391,6 +2413,7 @@ $1को बन्देजको कारण : "$2" हो',
 'allmessages-prefix' => 'प्रिफिक्स अनुसार फिल्टर:',
 'allmessages-language' => 'भाषा:',
 'allmessages-filter-submit' => 'जाउ',
+'allmessages-filter-translate' => 'अनुवाद गर्ने',
 
 # Thumbnails
 'thumbnail-more' => 'ठूलो बनाउने',
@@ -2553,12 +2576,18 @@ $1को बन्देजको कारण : "$2" हो',
 'pageinfo-header-properties' => 'पृष्ठ गुणहरू',
 'pageinfo-display-title' => 'प्रदर्शन शिर्षक',
 'pageinfo-views' => 'अवलोकन संख्या',
-'pageinfo-watchers' => 'निगरानी कर्ताहरुको संख्या',
-'pageinfo-edits' => 'सम्पादन संख्या',
-'pageinfo-authors' => 'फरक सम्पादकरुको संख्या',
+'pageinfo-watchers' => 'पृष्ठ निगरानी कर्ताहरुको संख्या',
+'pageinfo-edits' => 'कुल सम्पादन संख्या',
+'pageinfo-authors' => 'कुल फरक सम्पादकरूको संख्या',
+'pageinfo-toolboxlink' => 'पृष्ठ जानकारी',
+'pageinfo-redirectsto' => 'अनुप्रेषित',
 'pageinfo-redirectsto-info' => 'जानकारी',
+'pageinfo-contentpage' => 'सामग्री पृष्ठको रुपमा गणना गरिएको',
 'pageinfo-contentpage-yes' => 'हो',
 'pageinfo-protect-cascading-yes' => 'हो',
+'pageinfo-category-pages' => 'पृष्ठहरूको संख्या',
+'pageinfo-category-subcats' => 'उपश्रेणीहरूको संख्या',
+'pageinfo-category-files' => 'फाइलहरूको संख्या',
 
 # Skin names
 'skinname-cologneblue' => 'कोलोग्ने निलो',
@@ -2641,9 +2670,16 @@ $1',
 'minutes' => '{{PLURAL:$1|$1 मिनेट|$1 मिनेटहरु}}',
 'hours' => '{{PLURAL:$1|$1 घण्टा|$1 घण्टाहरु}}',
 'days' => '{{PLURAL:$1|$1 दिन|$1 दिनहरु}}',
+'weeks' => '{{PLURAL:$1|$1 हप्ता|$1 हप्ताहरू}}',
+'months' => '{{PLURAL:$1|$1 महिना|$1 महिनाहरू}}',
+'years' => '{{PLURAL:$1|$1 वर्ष|$1 वर्षहरू}}',
 'ago' => '$1 पहिले',
+'just-now' => 'भर्खरै',
 
 # Human-readable timestamps
+'hours-ago' => '$1 {{PLURAL:$1|घन्टा|घन्टा}} पहिले',
+'minutes-ago' => '$1 {{PLURAL:$1|मिनेट|मिनेट}} पहिले',
+'seconds-ago' => '$1 {{PLURAL:$1|सेकेन्ड|सेकेन्ड}} पहिले',
 'monday-at' => 'सोमबार $1 मा',
 'tuesday-at' => 'मङ्गलबार $1मा',
 'wednesday-at' => 'बुधबार $1मा',
@@ -2863,7 +2899,7 @@ $8',
 'exif-compression-34712' => 'जेपेग२०००',
 
 'exif-copyrighted-true' => 'प्रकाशन अधिकार सिमित गरिएको',
-'exif-copyrighted-false' => 'पबà¥\8dलिà¤\95 à¤¡à¥\8bमà¥\87न',
+'exif-copyrighted-false' => 'पà¥\8dराà¤\95ाशन à¤\85धिà¤\95ार à¤¨à¤\96à¥\81लाà¤\87à¤\8fà¤\95à¥\8b',
 
 'exif-photometricinterpretation-2' => 'आरजीबी(रातोहरियोनिलो)',
 
@@ -2874,9 +2910,9 @@ $8',
 'exif-orientation-3' => '180° मा घुमाइएको',
 'exif-orientation-4' => 'लंब रुपमा फ्लिप (Flip) गरिएको',
 'exif-orientation-5' => '९०° घडिको उल्टो दिशामाको परिक्रमा र मास्तिर फर्काइएको(फ्लिप)',
-'exif-orientation-6' => '90° CW घुमाइएको',
+'exif-orientation-6' => 'घडीको उल्टो दिशामा ९०° घुमाइएको',
 'exif-orientation-7' => '९०° घडिको दिशामाको परिक्रमा र मास्तिर फर्काइएको(फ्लिप)',
-'exif-orientation-8' => '९०° à¤\98डिà¤\95à¥\8b à¤\89लà¥\8dà¤\9fà¥\8b à¤¦à¤¿à¤¶à¤¾à¤®à¤¾à¤\95à¥\8b à¤ªà¤°à¤¿à¤\95à¥\8dरमा à¤\97रिएको',
+'exif-orientation-8' => 'à¤\98डिà¤\95à¥\8b à¤¦à¤¿à¤¶à¤¾à¤®à¤¾ à¥¯à¥¦Â° à¤\98à¥\81माà¤\87एको',
 
 'exif-planarconfiguration-1' => 'टुक्रे प्रारुप',
 'exif-planarconfiguration-2' => 'प्लानर प्रारुप',
@@ -3316,6 +3352,10 @@ $5
 'version-software-product' => 'उत्पादन',
 'version-software-version' => 'संस्करण',
 
+# Special:Redirect
+'redirect-submit' => 'जाने',
+'redirect-file' => 'फाइल नाम',
+
 # Special:FileDuplicateSearch
 'fileduplicatesearch' => 'नक्कल फाइल खोज्ने',
 'fileduplicatesearch-summary' => 'ह्यास मानको आधारमा दुरुस्त नक्कल फाइहरु खोज्ने ।',
@@ -3369,6 +3409,8 @@ $5
 'tags-display-header' => 'परिवर्तन सूचीहरुमाथि झलक',
 'tags-description-header' => 'पूर्ण अर्थको वर्णन',
 'tags-hitcount-header' => 'ट्याग गरिएक परिवर्तनहरू',
+'tags-active-yes' => 'हो',
+'tags-active-no' => 'हैन',
 'tags-edit' => 'सम्पादन गर्नुहोस्',
 'tags-hitcount' => '$1 {{PLURAL:$1|परिवर्तन|परिवर्तनहरु}}',
 
@@ -3388,6 +3430,7 @@ $5
 'dberr-problems' => 'क्षमा पाउँ! यो साइटमा तकनीकी गड़बड़ी आइपरेकोछ।',
 'dberr-again' => 'केही समय पर्खिएर पुन: लोड हुन दिनुहोस् ।',
 'dberr-info' => '(डेटाबेस सर्वर $1सित सम्पर्क साध्न सकिंदैन)',
+'dberr-info-hidden' => '(डेटावेस सर्भरमा सम्पर्क स्थापना गर्न सकिएन)',
 'dberr-usegoogle' => 'तपाईले अहिले गुगलबाट खोज गर्न प्रयास गर्न सक्नुहुन्छ।',
 'dberr-outofdate' => 'कृपया स्मरणमा राख्नुहोस् हाम्रा लेखहरूको सूची जुन उनीहरूले राखेका छन् त्यो अद्यावधिक नहुन सक्छ ।',
 'dberr-cachederror' => 'यो अनुरोध गरिएको पृष्ठको क्याशमा रहेका प्रतिलिपी हो , र अद्यावधिक नहुन सक्छ ।',
@@ -3403,6 +3446,9 @@ $5
 'htmlform-submit' => 'बुझाउने',
 'htmlform-reset' => 'परिवर्तनहरू परित्याग गर्नुहोस्',
 'htmlform-selectorother-other' => 'अन्य',
+'htmlform-no' => 'हैन',
+'htmlform-yes' => 'हो',
+'htmlform-chosen-placeholder' => 'एक विकल्प छान्नुहोस्',
 
 # SQLite database support
 'sqlite-has-fts' => '$1 पूरा पाठ खोज समर्थन सहित',
@@ -3410,7 +3456,12 @@ $5
 
 # New logging system
 'logentry-delete-restore' => '$3 पृष्ठ $1ले पुनर्स्थापित गरेको हो',
+'revdelete-content-hid' => 'सामग्री लुकाइएको',
+'revdelete-summary-hid' => 'सम्पादन सारांस लुकाइएको',
 'revdelete-uname-hid' => 'प्रयोगकर्ताको नाम लुकाइयो',
+'revdelete-content-unhid' => 'सामग्री देखाइएको',
+'revdelete-summary-unhid' => 'सम्पादन सारांस देखाइएको',
+'revdelete-uname-unhid' => 'प्रयोगकर्ता देखाइएको',
 'revdelete-restricted' => 'प्रबन्धकहरुमाथि सीमितता लागू गरियो',
 'revdelete-unrestricted' => 'प्रवन्धककोलागि निषेधहरु हटाइयो ।',
 'logentry-move-move' => '$1 द्वारा $3 पृष्ठलाई $4 मा सारियो',
@@ -3420,6 +3471,7 @@ $5
 'feedback-subject' => 'विषय:',
 'feedback-message' => 'सन्देश:',
 'feedback-cancel' => 'रद्द गर्ने',
+'feedback-submit' => 'प्रतिकृया बुझाउनुहोस्',
 'feedback-error2' => 'त्रुटि: सम्पादन असफल',
 'feedback-close' => 'गरियो',
 
@@ -3455,4 +3507,9 @@ $5
 'api-error-unknownerror' => 'अज्ञात त्रुटि: "$1".',
 'api-error-uploaddisabled' => 'यस विकिमा अपलोड निस्क्रिय गरिएकोछ।',
 
+# Special:ExpandTemplates
+'expand_templates_output' => 'परिणाम',
+'expand_templates_generate_rawhtml' => 'सुद्ध HTML देखाउने',
+'expand_templates_preview' => 'पूर्वावलोकन',
+
 );
index b7cca6b..d1604ba 100644 (file)
@@ -533,7 +533,7 @@ $messages = array(
 'qbedit' => 'Bewerken',
 'qbpageoptions' => 'Deze pagina',
 'qbmyoptions' => "Mijn pagina's",
-'faq' => 'Veel gestelde vragen',
+'faq' => 'Veelgestelde vragen',
 'faqpage' => 'Project:Veelgestelde vragen',
 
 # Vector skin
@@ -822,7 +822,7 @@ Vergeet niet uw [[Special:Preferences|voorkeuren voor {{SITENAME}}]] aan te pass
 'logout' => 'Afmelden',
 'userlogout' => 'Afmelden',
 'notloggedin' => 'Niet aangemeld',
-'userlogin-noaccount' => 'Hebt u geen gebruiker?',
+'userlogin-noaccount' => 'Hebt u geen account?',
 'userlogin-joinproject' => 'Word lid van {{SITENAME}}',
 'nologin' => 'Nog geen gebruikersnaam? $1.',
 'nologinlink' => 'Registreren',
@@ -1841,11 +1841,23 @@ Als u deze opgeeft, kan deze naam gebruikt worden om u erkenning te geven voor u
 'rcnotefrom' => "Wijzigingen sinds '''$2''' (met een maximum van '''$1''' wijzigingen).",
 'rclistfrom' => 'Wijzigingen bekijken vanaf $1',
 'rcshowhideminor' => 'Kleine wijzigingen $1',
+'rcshowhideminor-show' => 'Weergeven',
+'rcshowhideminor-hide' => 'Verbergen',
 'rcshowhidebots' => 'bots $1',
+'rcshowhidebots-show' => 'Weergeven',
+'rcshowhidebots-hide' => 'Verbergen',
 'rcshowhideliu' => 'geregistreerde gebruikers $1',
+'rcshowhideliu-show' => 'weergeven',
+'rcshowhideliu-hide' => 'verbergen',
 'rcshowhideanons' => 'anonieme gebruikers $1',
+'rcshowhideanons-show' => 'weergeven',
+'rcshowhideanons-hide' => 'verbergen',
 'rcshowhidepatr' => 'gecontroleerde bewerkingen $1',
+'rcshowhidepatr-show' => 'weergeven',
+'rcshowhidepatr-hide' => 'verbergen',
 'rcshowhidemine' => 'mijn bewerkingen $1',
+'rcshowhidemine-show' => 'weergeven',
+'rcshowhidemine-hide' => 'verbergen',
 'rclinks' => 'De $1 laatste wijzigingen bekijken in de laatste $2 dagen<br />$3',
 'diff' => 'wijz',
 'hist' => 'gesch',
@@ -1982,6 +1994,7 @@ Vraag iemand die onderdrukte bestandsgegevens kan bekijken om de situatie opnieu
 'php-uploaddisabledtext' => 'Het uploaden van bestanden is uitgeschakeld in PHP.
 Controleer de instelling "file_uploads".',
 'uploadscripted' => 'Dit bestand bevat HTML- of scriptcode die foutief door uw browser kan worden weergegeven.',
+'uploadinvalidxml' => 'De XML in het geüploade bestand kon niet worden geparst.',
 'uploadvirus' => 'Het bestand bevat een virus! Details: $1',
 'uploadjava' => 'Het bestand is een ZIP-bestand dat een Java .class-bestand bevat.
 Het uploaden van Java-bestanden is niet toegestaan omdat hiermee beveiligingsinstellingen omzeild kunnen worden.',
@@ -2483,7 +2496,7 @@ Heeft tenminste een topleveldomein nodig, zoals bijvoorbeeld "*.org".<br />
 'listgrouprights' => 'Rechten van gebruikersgroepen',
 'listgrouprights-summary' => 'Op deze pagina staan de gebruikersgroepen in deze wiki beschreven, met hun bijbehorende rechten.
 Er kan [[{{MediaWiki:Listgrouprights-helppage}}|extra informatie]] over individuele rechten aanwezig zijn.',
-'listgrouprights-key' => 'Leganda:
+'listgrouprights-key' => 'Legenda:
 * <span class="listgrouprights-granted">Toegewezen recht</span>
 * <span class="listgrouprights-revoked">Ingetrokken recht</span>',
 'listgrouprights-group' => 'Groep',
@@ -2834,6 +2847,7 @@ De laatste regel uit het blokkeerlogboek wordt hieronder ter referentie weergege
 'sp-contributions-search' => 'Zoeken naar bijdragen',
 'sp-contributions-username' => 'IP-adres of gebruikersnaam:',
 'sp-contributions-toponly' => 'Alleen nieuwste versies weergeven',
+'sp-contributions-newonly' => "Alleen nieuwe pagina's weergeven",
 'sp-contributions-submit' => 'Bekijken',
 
 # What links here
@@ -2867,7 +2881,7 @@ Geef hieronder een reden op (bijvoorbeeld welke pagina's gevandaliseerd zijn).",
 'ipadressorusername' => 'IP-adres of gebruikersnaam:',
 'ipbexpiry' => 'Vervalt (maak een keuze):',
 'ipbreason' => 'Reden:',
-'ipbreason-dropdown' => "*Veel voorkomende redenen voor blokkades
+'ipbreason-dropdown' => "*Veelvoorkomende redenen voor blokkades
 ** Foutieve informatie invoeren
 ** Verwijderen van informatie uit pagina's
 ** Spamkoppeling naar externe websites
@@ -4407,6 +4421,4 @@ Vrijwel alle tekst tussen dubbele accolades wordt gesubstitueerd.',
 'expand_templates_generate_rawhtml' => 'Ruwe HTML weergeven',
 'expand_templates_preview' => 'Voorvertoning',
 
-# Unknown messages
-'uploadinvalidxml' => 'De XML in het geüploade bestand kon niet worden geparst.',
 );
index 0371b7b..8f42463 100644 (file)
@@ -2388,6 +2388,7 @@ Attendemelding og hjelp:
 'delete-edit-reasonlist' => 'Endre grunnar til sletting',
 'delete-toobig' => 'Denne sida har ein stor endringsshistorikk, med over {{PLURAL:$1|$1&nbsp;endring|$1&nbsp;endringar}}. Sletting av slike sider er avgrensa for å unngå utilsikta forstyrring av {{SITENAME}}.',
 'delete-warning-toobig' => 'Denne sida har ein lang endringshistorikk, med meir enn {{PLURAL:$1|$1&nbsp;endring|$1&nbsp;endringar}}. Dersom du slettar henne kan det forstyrre handlingar i databasen til {{SITENAME}}, ver varsam.',
+'deleting-backlinks-warning' => "'''Åtvaring''': Andre sider lenkjer til eller inkluderer sida du er i ferd med å sletta.",
 
 # Rollback
 'rollback' => 'Rull attende endringar',
index bfdc4fa..9453467 100644 (file)
@@ -826,6 +826,9 @@ Esperatz $1 abans d’ensajar tornarmai.',
 'suspicious-userlogout' => 'Vòstra demanda de desconnexion es estada refusada perque sembla qu’es estada mandada per un navigador copat o la mesa en escondedor d’un proxy.',
 'createacct-another-realname-tip' => 'Lo nom vertadièr es opcional.
 Se decidissètz de lo provesir, serà utilizat per atribuir a l’utilizaire sos trabalhs.',
+'pt-login' => 'Se connectar',
+'pt-createaccount' => 'Crear un compte',
+'pt-userlogout' => 'Se desconnectar',
 
 # Email sending
 'php-mail-error-unknown' => 'Error desconeguda dins la foncion mail() de PHP.',
@@ -834,7 +837,7 @@ Se decidissètz de lo provesir, serà utilizat per atribuir a l’utilizaire sos
 
 # Change password dialog
 'changepassword' => 'Modificacion del senhal',
-'resetpass_announce' => 'Vos sètz enregistrat amb un senhal temporari mandat per corrièr electronic. Per acabar l’enregistrament, vos cal picar un senhal novèl aicí :',
+'resetpass_announce' => 'Per acabar l’enregistrament, vos cal picar un senhal novèl.',
 'resetpass_text' => '<!-- Apondètz lo tèxte aicí -->',
 'resetpass_header' => 'Modificar lo senhal del compte',
 'oldpassword' => 'Senhal ancian :',
@@ -842,6 +845,8 @@ Se decidissètz de lo provesir, serà utilizat per atribuir a l’utilizaire sos
 'retypenew' => 'Confirmar lo senhal novèl :',
 'resetpass_submit' => 'Cambiar lo senhal e s’enregistrar',
 'changepassword-success' => 'Vòstre senhal es estat cambiat amb succès !',
+'changepassword-throttled' => 'Avètz ensajat un tròp grand nombre de connexions darrièrament.
+Esperatz $1 abans d’ensajar tornarmai.',
 'resetpass_forbidden' => 'Los senhals pòdon pas èsser cambiats',
 'resetpass-no-info' => 'Vos cal èsser connectat per aver accès a aquesta pagina.',
 'resetpass-submit-loggedin' => 'Modificar lo senhal',
@@ -854,7 +859,7 @@ Benlèu ja avètz modificat vòstre senhal o demandat un senhal temporari novèl
 # Special:PasswordReset
 'passwordreset' => 'Remesa a zèro del senhal',
 'passwordreset-text-one' => 'Emplenatz aqueste formulari per reïnicializar vòstre senhal.',
-'passwordreset-text-many' => "{{PLURAL:$1|Completatz un d'aqueles camps per reïnicializar vòstre senhal.}}",
+'passwordreset-text-many' => "{{PLURAL:$1|Completatz un d'aqueles camps per recebre un senhal temporari per corrièr electronic.}}",
 'passwordreset-legend' => 'Reïnicializar lo senhal',
 'passwordreset-disabled' => 'La reïnicializacion dels senhals es estada desactivada sus aqueste wiki.',
 'passwordreset-emaildisabled' => 'Las foncionalitats e-mail son estadas desactivadas sus aqueste wiki.',
@@ -1098,7 +1103,9 @@ Existís ja.',
 'content-failed-to-parse' => "Fracàs de l'analisi del contengut de $2 pel modèl $1: $3",
 'invalid-content-data' => 'Donadas del contengut invalidas',
 'content-not-allowed-here' => 'Lo contengut "$1" es pas autorizat sus la pagina [[$2]]',
-'editwarning-warning' => "Quitar aquesta pagina vos farà pèrdre totas las modificacions qu'avètz fachas. Se sètz connectat amb vòstre compte, podètz levar aqueste avertiment dins la seccion « Modificacion » de vòstras preferéncias.",
+'editwarning-warning' => "Quitar aquesta pagina vos farà pèrdre totas las modificacions qu'avètz fachas.
+Se sètz connectat, podètz desactivar aqueste avertiment dins la seccion « {{int:prefs-editing}} » de vòstras preferéncias.",
+'editpage-notsupportedcontentformat-title' => 'Format de contengut pas pres en carga',
 
 # Content models
 'content-model-wikitext' => 'wikitèxte',
@@ -1343,6 +1350,7 @@ Podètz trobar de detalhs dins lo [{{fullurl:{{#Special:Log}}/delete|page={{FULL
 'search-result-score' => 'Pertinéncia : $1%',
 'search-redirect' => '(redireccion cap a $1)',
 'search-section' => '(seccion $1)',
+'search-file-match' => '(correspond al contengut del fichièr)',
 'search-suggest' => 'Avètz volgut dire : $1',
 'search-interwiki-caption' => 'Projèctes fraires',
 'search-interwiki-default' => '$1 resultats :',
@@ -1671,11 +1679,23 @@ Tanben podètz causir de permetre a d’autres de vos contactar per vòstra pagi
 'rcnotefrom' => "Vaquí los cambiaments efectuats dempuèi lo '''$2''' ('''$1''' al maximum).",
 'rclistfrom' => 'Afichar las modificacions novèlas dempuèi lo $1.',
 'rcshowhideminor' => '$1 los cambiaments menors',
+'rcshowhideminor-show' => 'Afichar',
+'rcshowhideminor-hide' => 'Amagar',
 'rcshowhidebots' => '$1 los robòts',
+'rcshowhidebots-show' => 'Afichar',
+'rcshowhidebots-hide' => 'Amagar',
 'rcshowhideliu' => '$1 los utilizaires enregistrats',
+'rcshowhideliu-show' => 'Afichar',
+'rcshowhideliu-hide' => 'Amagar',
 'rcshowhideanons' => '$1 los utilizaires anonims',
+'rcshowhideanons-show' => 'Afichar',
+'rcshowhideanons-hide' => 'Amagar',
 'rcshowhidepatr' => '$1 las modificacions susvelhadas',
+'rcshowhidepatr-show' => 'Afichar',
+'rcshowhidepatr-hide' => 'Amagar',
 'rcshowhidemine' => '$1 mas modificacions',
+'rcshowhidemine-show' => 'Afichar',
+'rcshowhidemine-hide' => 'Amagar',
 'rclinks' => 'Afichar los $1 darrièrs cambiaments efectuats al cors dels $2 darrièrs jorns; $3 cambiaments menors.',
 'diff' => 'dif',
 'hist' => 'ist',
@@ -2152,6 +2172,14 @@ Las entradas <del>barradas</del> son estadas resolgudas.',
 'protectedpages-cascade' => 'Unicament las proteccions en cascada',
 'protectedpages-noredirect' => 'Amagar las redireccions',
 'protectedpagesempty' => 'Cap de pagina es pas protegida actualament.',
+'protectedpages-timestamp' => 'Orodatatge',
+'protectedpages-page' => 'Pagina',
+'protectedpages-expiry' => 'Expira lo',
+'protectedpages-performer' => 'Proteccion de l’utilizaire',
+'protectedpages-params' => 'Paramètres de proteccion',
+'protectedpages-reason' => 'Motiu',
+'protectedpages-unknown-timestamp' => 'Desconegut',
+'protectedpages-unknown-performer' => 'Utilizaire desconegut',
 'protectedtitles' => 'Títols protegits',
 'protectedtitlesempty' => 'Cap de títol es pas actualament protegit amb aquestes paramètres.',
 'listusers' => 'Lista dels participants',
@@ -2866,6 +2894,7 @@ Visitatz la [https://www.mediawiki.org/wiki/Localisation Localizacion MediaWiki]
 'allmessages-prefix' => 'Filtrar per prefix :',
 'allmessages-language' => 'Lenga :',
 'allmessages-filter-submit' => 'Aplicar',
+'allmessages-filter-translate' => 'Tradusir',
 
 # Thumbnails
 'thumbnail-more' => 'Agrandir',
@@ -3806,7 +3835,13 @@ Ensajatz la previsualizacion normala.',
 'version-hook-name' => 'Nom del croquet',
 'version-hook-subscribedby' => 'Definit per',
 'version-version' => '(Version $1)',
-'version-license' => 'Licéncia',
+'version-license' => 'Licéncia de MediaWiki',
+'version-ext-license' => 'Licéncia',
+'version-ext-colheader-license' => 'Licéncia',
+'version-ext-colheader-description' => 'Descripcion',
+'version-ext-colheader-credits' => 'Autors',
+'version-license-title' => 'Licéncia per $1',
+'version-credits-title' => 'Mercejaments per $1',
 'version-poweredby-credits' => "Aqueste wiki fonciona gràcias a '''[https://www.mediawiki.org/ MediaWiki]''', copyright © 2001-$1 $2.",
 'version-poweredby-others' => 'autres',
 'version-poweredby-translators' => 'traductors de translatewiki.net',
@@ -3818,7 +3853,7 @@ Ensajatz la previsualizacion normala.',
 'version-entrypoints-header-url' => 'URL',
 
 # Special:Redirect
-'redirect' => 'Redirigit per fichièr, utilizaire, o ID de revision',
+'redirect' => 'Redirigit per fichièr, utilizaire, pagina o ID de revision.',
 'redirect-legend' => 'Redirigir cap a una pagina o un fichièr',
 'redirect-submit' => 'Validar',
 'redirect-lookup' => 'Recèrca :',
index 4076b81..5972860 100644 (file)
@@ -23,6 +23,7 @@
  * @author Geitost
  * @author Herr Kriss
  * @author Holek
+ * @author Jacenty359
  * @author Jwitos
  * @author Kaganer
  * @author Kaligula
@@ -317,7 +318,7 @@ $magicWords = array(
 
 $messages = array(
 # User preference toggles
-'tog-underline' => 'Podkreślenie linków',
+'tog-underline' => 'Podkreślenie linków:',
 'tog-hideminor' => 'Ukryj drobne edycje w ostatnich zmianach',
 'tog-hidepatrolled' => 'Ukryj sprawdzone edycje w ostatnich zmianach',
 'tog-newpageshidepatrolled' => 'Ukryj sprawdzone strony na liście nowych stron',
@@ -863,6 +864,9 @@ Odczekaj $1 zanim ponowisz próbę.',
 'suspicious-userlogout' => 'Żądanie wylogowania zostało odrzucone ponieważ wygląda na to, że zostało wysłane przez uszkodzoną przeglądarkę lub buforujący serwer proxy.',
 'createacct-another-realname-tip' => 'Wpisanie imienia i nazwiska nie jest obowiązkowe.
 Jeśli zdecydujesz się je podać, zostaną użyte, by udokumentować Twoje autorstwo.',
+'pt-login' => 'Zaloguj się',
+'pt-createaccount' => 'Utwórz konto',
+'pt-userlogout' => 'Wyloguj',
 
 # Email sending
 'php-mail-error-unknown' => 'Wystąpił nieznany błąd w funkcji PHP mail()',
@@ -887,6 +891,9 @@ Odczekaj $1, zanim ponowisz próbę.',
 'resetpass-submit-cancel' => 'Anuluj',
 'resetpass-wrong-oldpass' => 'Nieprawidłowe tymczasowe lub aktualne hasło.
 Być może właśnie zmienił{{GENDER:|eś|aś|eś(‐aś)}} swoje hasło lub poprosił{{GENDER:|eś|aś|eś(‐aś)}} o nowe tymczasowe hasło.',
+'resetpass-recycled' => 'Zmień swoje hasło na inne niż aktualne.',
+'resetpass-temp-emailed' => 'Zalogowałeś się dzięki tymczasowemu kodowi.
+Aby dokończyć logowanie, musisz ustawić nowe hasło tutaj:',
 'resetpass-temp-password' => 'Tymczasowe hasło:',
 'resetpass-abort-generic' => 'Zmiana hasła została przerwana przez rozszerzenie.',
 'resetpass-expired' => 'Twoje hasło wygasło. Proszę ustawić nowe hasło do logowania.',
@@ -1746,11 +1753,23 @@ Jeśli zdecydujesz się je podać, zostaną użyte, by udokumentować Twoje auto
 'rcnotefrom' => "Poniżej pokazano zmiany wykonane po '''$2''' (nie więcej niż '''$1''' pozycji).",
 'rclistfrom' => 'Pokaż nowe zmiany od $1',
 'rcshowhideminor' => '$1 drobne zmiany',
+'rcshowhideminor-show' => 'Pokaż',
+'rcshowhideminor-hide' => 'Ukryj',
 'rcshowhidebots' => '$1 boty',
+'rcshowhidebots-show' => 'Pokaż',
+'rcshowhidebots-hide' => 'Ukryj',
 'rcshowhideliu' => '$1 zarejestrowanych',
+'rcshowhideliu-show' => 'Pokaż',
+'rcshowhideliu-hide' => 'Ukryj',
 'rcshowhideanons' => '$1 anonimowych',
+'rcshowhideanons-show' => 'Pokaż',
+'rcshowhideanons-hide' => 'Ukryj',
 'rcshowhidepatr' => '$1 sprawdzone',
+'rcshowhidepatr-show' => 'Pokaż',
+'rcshowhidepatr-hide' => 'Ukryj',
 'rcshowhidemine' => '$1 moje edycje',
+'rcshowhidemine-show' => 'Pokaż',
+'rcshowhidemine-hide' => 'Ukryj',
 'rclinks' => 'Pokaż ostatnie $1 zmian w ciągu ostatnich $2 dni.<br />$3',
 'diff' => 'różn.',
 'hist' => 'hist.',
@@ -1879,6 +1898,8 @@ Sprawdź historię usunięć tamtego pliku zanim prześlesz go ponownie.',
 'uploaddisabledtext' => 'Możliwość przesyłania plików została wyłączona.',
 'php-uploaddisabledtext' => 'Przesyłanie plików PHP zostało zablokowane. Sprawdź ustawienie „file_uploads”.',
 'uploadscripted' => 'Plik zawiera kod HTML lub skrypt, który może zostać błędnie zinterpretowany przez przeglądarkę internetową.',
+'uploadscriptednamespace' => "Ten plik SVG zawiera niepoprawną nazwę '$1'",
+'uploadinvalidxml' => 'Nie udało się przeanalizować XML w załadowanym pliku.',
 'uploadvirus' => 'W pliku jest wirus! Szczegóły: $1',
 'uploadjava' => 'Ten plik zawiera deklarację klasy Java skompresowaną ZIP.
 Przesyłanie plików Java nie jest dozwolone, ponieważ mogłoby zostać użyte do obchodzenia zabezpieczeń.',
@@ -2251,6 +2272,7 @@ Każdy wiersz zawiera linki do pierwszego i drugiego przekierowania oraz link, d
 'deadendpagestext' => 'Poniższe strony nie posiadają odnośników do innych stron znajdujących się w {{GRAMMAR:MS.lp|{{SITENAME}}}}.',
 'protectedpages' => 'Strony zabezpieczone',
 'protectedpages-indef' => 'Tylko strony zabezpieczone na zawsze',
+'protectedpages-summary' => 'Ta strona zawiera istniejące strony które są chronione. Aby uzyskać listę tytułów których stworzenie jest zabronione, zobacz [[{{#special:ProtectedTitles}}]].',
 'protectedpages-cascade' => 'Tylko strony zabezpieczone rekursywnie',
 'protectedpages-noredirect' => 'Ukryj przekierowania',
 'protectedpagesempty' => 'Żadna strona nie jest obecnie zabezpieczona z podanymi parametrami.',
@@ -2263,6 +2285,7 @@ Każdy wiersz zawiera linki do pierwszego i drugiego przekierowania oraz link, d
 'protectedpages-unknown-timestamp' => 'Nieznane',
 'protectedpages-unknown-performer' => 'Użytkownik nieznany',
 'protectedtitles' => 'Zabezpieczone nazwy stron',
+'protectedtitles-summary' => 'Ta strona zawiera tytuły, których tworzenie jest zabronione. Aby zobaczyć listę istniejących stron które są chronione, odwiedź tą stronę [[{{#special:ProtectedPages}}]]',
 'protectedtitlesempty' => 'Dla tych ustawień dopuszczalne jest utworzenie stron o dowolnej nazwie.',
 'listusers' => 'Lista użytkowników',
 'listusers-editsonly' => 'Pokaż tylko użytkowników z edycjami',
@@ -2712,6 +2735,7 @@ Poniżej znajduje się ostatni wpis w rejestrze blokowania.',
 'sp-contributions-search' => 'Szukaj wkładu',
 'sp-contributions-username' => 'Adres IP lub nazwa użytkownika',
 'sp-contributions-toponly' => 'Pokaż wyłącznie ostatnie wersje',
+'sp-contributions-newonly' => 'Pokazuj wyłącznie stworzenia stron',
 'sp-contributions-submit' => 'Szukaj',
 
 # What links here
@@ -3072,6 +3096,7 @@ Brak katalogu dla plików tymczasowych.',
 'import-error-special' => 'Strona „$1” nie została zaimportowana, ponieważ należy do specjalnej przestrzeni nazw, która nie zezwala na strony.',
 'import-error-invalid' => 'Strona „$1” nie została zaimportowana, ponieważ jej nazwa jest nieprawidłowa.',
 'import-error-unserialize' => 'Wersja $2 strony "$1" nie może zostać odserializowana. Wersja używa modelu treści $3 zserializowanego jako $4',
+'import-error-bad-location' => 'Zmiana $2 używająca modelu danych $3 nie może zostać zapisana na "$1" na tej wiki, ze względu na to, że ten model danych nie jest wspierany na tej stronie.',
 'import-options-wrong' => '{{PLURAL:$2|Niepoprawna opcja|Niepoprawne opcje}}: <nowiki>$1</nowiki>',
 'import-rootpage-invalid' => 'Wskazana strona główna jest niepoprawna.',
 'import-rootpage-nosubpage' => 'Przestrzeń nazw "$1" strony głównej nie dopuszcza stron podrzędnych.',
@@ -4249,6 +4274,7 @@ W przeciwnym wypadku można użyć prostego formularza poniżej. Komentarz zosta
 'api-error-overwrite' => 'Nadpisanie istniejącego pliku nie jest dopuszczalne.',
 'api-error-stashfailed' => 'Błąd wewnętrzny – serwer nie mógł zapisać pliku tymczasowego.',
 'api-error-publishfailed' => 'Błąd wewnętrzny: serwer nie mógł zapisać pliku tymczasowego.',
+'api-error-stasherror' => 'Wystąpił błąd podczas przesyłania pliku.',
 'api-error-timeout' => 'Serwer nie odpowiedział w oczekiwanym czasie.',
 'api-error-unclassified' => 'Wystąpił nieznany błąd',
 'api-error-unknown-code' => 'Błąd nieznany – „$1”',
@@ -4306,6 +4332,4 @@ W zasadzie rozwijane jest prawie wszystko w podwójnych nawiasach klamrowych.',
 'expand_templates_generate_rawhtml' => 'Pokaż surowy HTML',
 'expand_templates_preview' => 'Podgląd',
 
-# Unknown messages
-'uploadinvalidxml' => 'Nie udało się przeanalizować XML w załadowanym pliku.',
 );
index 7ca9697..f76d06b 100644 (file)
@@ -615,7 +615,7 @@ Për finì ëd rintré ant ël sistema, a dev definì na neuva ciav ambelessì:"
 'resetpass-temp-password' => 'Ciav provisòria:',
 'resetpass-abort-generic' => "La modìfica ëd la ciav a l'é stàita anulà da n'estension.",
 'resetpass-expired' => "Soa ciav a l'é scadùa. Për piasì, ch'a definissa na ciav neuva për rintré ant ël sistema.",
-'resetpass-expired-soft' => "Soa ciav a l'é scadùa e a l'ha damanca d'esse arnovà. Për piasì, ch'a serna na neuva ciav adess o ch'a sgnaca su anulé për cangela pi tard.",
+'resetpass-expired-soft' => "Soa ciav a l'é scadùa e a l'ha damanca d'esse arnovà. Për piasì, ch'a serna na neuva ciav adess o ch'a sgnaca su «{{int:resetpass-submit-cancel}}» për cangela pi tard.",
 
 # Special:PasswordReset
 'passwordreset' => 'Ri-inissialisassion ëd la ciav',
@@ -1464,14 +1464,26 @@ Costa anformassion a sarà pùblica.",
 'recentchanges-legend-heading' => "'''Legend:'''",
 'recentchanges-legend-newpage' => '(vëdde ëdcò [[Special:NewPages|lista dle pàgine neuve]])',
 'recentchanges-legend-plusminus' => "(''±123'')",
-'rcnotefrom' => ' Ambelessì sota a-i é la lista dle modìfiche da <b>$2</b> (fin-a a <b>$1</b>).',
+'rcnotefrom' => 'Ambelessì sota a-i é la lista dle modìfiche da <strong>$2</strong> (mostrà fin-a a <strong>$1</strong>).',
 'rclistfrom' => 'Mostré le modìfiche a parte da $1',
 'rcshowhideminor' => '$1 le modìfiche cite',
+'rcshowhideminor-show' => 'Smon-e',
+'rcshowhideminor-hide' => 'Stërmé',
 'rcshowhidebots' => '$1 ij trigomiro',
+'rcshowhidebots-show' => 'Smon-e',
+'rcshowhidebots-hide' => 'Stërmé',
 'rcshowhideliu' => "$1 j'utent registrà",
+'rcshowhideliu-show' => 'Smon-e',
+'rcshowhideliu-hide' => 'Stërmé',
 'rcshowhideanons' => "$1 j'utent anònim",
+'rcshowhideanons-show' => 'Smon-e',
+'rcshowhideanons-hide' => 'Stërmé',
 'rcshowhidepatr' => '$1 le modìfiche verificà',
+'rcshowhidepatr-show' => 'Smon-e',
+'rcshowhidepatr-hide' => 'Stërmé',
 'rcshowhidemine' => '$1 mie modìfiche',
+'rcshowhidemine-show' => 'Smon-e',
+'rcshowhidemine-hide' => 'Stërmé',
 'rclinks' => "Mostré j'ùltime $1 modìfiche ëd j'ùltim $2 dì<br />$3",
 'diff' => 'dif.',
 'hist' => 'stòria',
@@ -1601,6 +1613,8 @@ A dovrìa ciamé a cheidun con la possibilità ëd vëdde ij dàit dj'archivi el
 'php-uploaddisabledtext' => "Ij cariament d'archivi a son disabilità an PHP.
 Për piasì, ch'a controla l'ampostassion file_uploads.",
 'uploadscripted' => "St'archivi-sì a l'ha andrinta chèich-còs (dël còdes HTML ò pura un senari) che a podrìa esse travajà mal da chèich programa ëd navigassion.",
+'uploadscriptednamespace' => "S'archivi SVG a conten në spassi nominal «1» nen autorisà",
+'uploadinvalidxml' => "L'XML ant l'archivi carià a l'ha nen podù esse analisà.",
 'uploadvirus' => "St'archivi-sì a l'han andrinta un '''vìrus!''' Detaj: $1",
 'uploadjava' => "L'archivi a l'é n'archivi ZIP ch'a conten n'archivi Java .class.
 As peulo pa cariesse dj'archivi Java, përché a peulo causé l'agirament ëd le restrission ëd sicurëssa.",
@@ -2435,6 +2449,7 @@ L'ùltima intrada dël registr dij blocagi a l'é butà sì-sota për arferiment
 'sp-contributions-search' => 'Arserché le contribussion',
 'sp-contributions-username' => "Adrëssa IP ò stranòm dl'utent:",
 'sp-contributions-toponly' => "Mostré mach le modìfiche ch'a son j'ùltime revision",
+'sp-contributions-newonly' => "Mostré mach le modìfiche ch'a son dle creassion ëd pàgina",
 'sp-contributions-submit' => 'Arserché',
 
 # What links here
@@ -3986,6 +4001,4 @@ An efet, a espand praticament tut lòn ch'a-i é antrames dle grafe dobie.",
 'expand_templates_generate_rawhtml' => "Smon-e l'HTML sempi",
 'expand_templates_preview' => 'Preuva',
 
-# Unknown messages
-'uploadinvalidxml' => "L'XML ant l'archivi carià a l'ha nen podù esse analisà.",
 );
index 1bd8be8..8c69d22 100644 (file)
@@ -1063,8 +1063,8 @@ Os detalhes podem ser encontrados no [{{fullurl:{{#Special:Log}}/delete|page={{F
 'userpage-userdoesnotexist' => 'A conta "<nowiki>$1</nowiki>" não se encontra registada.
 Verifique se deseja realmente criar ou editar esta página, por favor.',
 'userpage-userdoesnotexist-view' => 'A conta de utilizador "$1" não está registada.',
-'blocked-notice-logextract' => 'Este utilizador encontra-se atualmente bloqueado.
-Para referência, o último registro de bloqueio é apresentado abaixo:',
+'blocked-notice-logextract' => 'Este utilizador está bloqueado.
+Para referência, o último registo de bloqueio é apresentado abaixo:',
 'clearyourcache' => "'''Nota:''' Após gravar, terá de limpar a ''cache'' do seu browser para ver as alterações.
 *'''Firefox / Safari:''' Pressione ''Shift'' enquanto clica ''Recarregar'', ou pressione ''Ctrl-F5'' ou ''Ctrl-R'' (''⌘-R'' no Mac)
 *'''Google Chrome:''' Pressione ''Ctrl-Shift-R'' (''⌘-Shift-R'' no Mac)
@@ -1444,7 +1444,7 @@ Os detalhes podem ser encontrados no [{{fullurl:{{#Special:Log}}/delete|page={{F
 'searchrelated' => 'relacionados',
 'searchall' => 'todos',
 'showingresults' => "{{PLURAL:$1|É apresentado '''um''' resultado|São apresentados até '''$1''' resultados}} abaixo{{PLURAL:$1||, começando pelo '''$2'''º}}.",
-'showingresultsinrange' => 'Mostrando abaixo até {{PLURAL:$1|<strong>1</strong> resultado|<strong>$1</strong> resultados}} entre #<strong>$2</strong> e #<strong>$3</strong>.',
+'showingresultsinrange' => 'Apresenta-se abaixo {{PLURAL:$1|<strong>1</strong> resultado|até <strong>$1</strong> resultados}} no intervalo #<strong>$2</strong> a #<strong>$3</strong>.',
 'showingresultsnum' => "{{PLURAL:$3|É apresentado '''um''' resultado|São apresentados '''$3''' resultados}} abaixo{{PLURAL:$3||, começando pelo '''$2'''º}}.",
 'showingresultsheader' => "{{PLURAL:$5|Resultado '''$1''' de '''$3'''|Resultados '''$1–$2''' de '''$3'''}} para '''$4'''",
 'search-nonefound' => 'A pesquisa não produziu resultados.',
@@ -1768,11 +1768,23 @@ Se optar por revelá-lo, ele será utilizado para atribuir-lhe crédito pelo seu
 'rcnotefrom' => 'Abaixo estão as mudanças desde <b>$2</b> (mostradas até <b>$1</b>).',
 'rclistfrom' => 'Mostrar as novas mudanças a partir das $1',
 'rcshowhideminor' => '$1 edições menores',
+'rcshowhideminor-show' => 'Mostrar',
+'rcshowhideminor-hide' => 'Esconder',
 'rcshowhidebots' => '$1 robôs',
+'rcshowhidebots-show' => 'Mostrar',
+'rcshowhidebots-hide' => 'Esconder',
 'rcshowhideliu' => '$1 utilizadores registados',
+'rcshowhideliu-show' => 'Mostrar',
+'rcshowhideliu-hide' => 'Esconder',
 'rcshowhideanons' => '$1 utilizadores anónimos',
+'rcshowhideanons-show' => 'Mostrar',
+'rcshowhideanons-hide' => 'Esconder',
 'rcshowhidepatr' => '$1 edições patrulhadas',
+'rcshowhidepatr-show' => 'Mostrar',
+'rcshowhidepatr-hide' => 'Esconder',
 'rcshowhidemine' => '$1 as minhas edições',
+'rcshowhidemine-show' => 'Mostrar',
+'rcshowhidemine-hide' => 'Esconder',
 'rclinks' => 'Mostrar as últimas $1 mudanças nos últimos $2 dias<br />$3',
 'diff' => 'dif',
 'hist' => 'his',
@@ -1815,7 +1827,7 @@ As suas [[Special:Watchlist|páginas vigiadas]] aparecem a '''negrito'''.",
 Para sua conveniência, é apresentado de seguida o registo de eliminação e de movimento da página:",
 'uploadtext' => "Utilize o formulário abaixo para fazer upload de ficheiros novos.
 Para ver ou pesquisar ficheiros anteriormente enviados, consulte a [[Special:FileList|lista de ficheiros]].
-Os reenvios de um ficheiro são também registrados no [[Special:Log/upload|registro de uploads]] e as eliminações no [[Special:Log/delete|registro de eliminações]].
+Os reenvios de um ficheiro são também registados no [[Special:Log/upload|registo de uploads]] e as eliminações no [[Special:Log/delete|registo de eliminações]].
 
 Para utilizar um ficheiro numa página, depois de ter feito o upload, insira um link com um dos seguintes formatos:
 * '''<code><nowiki>[[</nowiki>{{ns:file}}<nowiki>:ficheiro.jpg]]</nowiki></code>''' para mostrar uma imagem nas suas dimensões originais;
@@ -1892,7 +1904,7 @@ Caso deseje, mesmo assim, carregar o seu ficheiro, volte atrás e envie-o com um
 'file-exists-duplicate' => 'Este ficheiro é um duplicado {{PLURAL:$1|do seguinte|dos seguintes}}:',
 'file-deleted-duplicate' => 'Um ficheiro idêntico a este ([[:$1]]) foi eliminado anteriormente.
 Verifique o motivo da eliminação do ficheiro antes de prosseguir com o re-envio.',
-'file-deleted-duplicate-notitle' => 'Um ficheiro idêntico a este foi eliminado anteriormente, e o título foi suprimido. Você deve pedir a alguém capaz de ver os dados de ficheiros eliminados para que revise a situação antes de carregar novamente este ficheiro.',
+'file-deleted-duplicate-notitle' => 'Um ficheiro idêntico já foi eliminado e o seu título suprimido. Devia pedir a alguém capaz de ver os dados dos ficheiros eliminados para verificar a situação antes de carregá-lo novamente.',
 'uploadwarning' => 'Aviso de envio',
 'uploadwarning-text' => 'Modifique a descrição do ficheiro abaixo e tente novamente, por favor.',
 'savefile' => 'Gravar ficheiro',
@@ -1905,6 +1917,8 @@ Verifique o motivo da eliminação do ficheiro antes de prosseguir com o re-envi
 'php-uploaddisabledtext' => 'O carregamento de ficheiros está impossibilitado no PHP.
 Verifique a configuração file_uploads, por favor.',
 'uploadscripted' => 'Este ficheiro contém HTML ou código que pode ser erradamente interpretado por um browser.',
+'uploadscriptednamespace' => "Este ficheiro SVG contém um espaço nominal que não é permitido '$1'",
+'uploadinvalidxml' => 'Erro detectado na análise do XML do ficheiro carregado.',
 'uploadvirus' => 'O ficheiro contém um vírus! Detalhes: $1',
 'uploadjava' => 'Este é um ficheiro ZIP que contém um ficheiro .class de Java.
 Não é permitido o upload de ficheiros Java, porque estes podem contornar as restrições de segurança.',
@@ -2170,6 +2184,7 @@ Talvez queira editar a descrição na [$2 página original de descrição do fic
 'randompage-nopages' => 'Não há páginas {{PLURAL:$2|no seguinte espaço nominal|nos seguintes espaços nominais}}: $1.',
 
 # Random page in category
+'randomincategory' => 'Página aleatória na categoria',
 'randomincategory-invalidcategory' => '"$1" não é um nome de categoria válido',
 'randomincategory-nopages' => 'Não há páginas na categoria [[:Category:$1|$1]].',
 'randomincategory-selectcategory' => 'Obter página aleatória da categoria: $1 $2',
@@ -2235,6 +2250,7 @@ Agora redirecciona para [[$2]].',
 'ninterwikis' => '$1 {{PLURAL:$1|interwiki|interwikis}}',
 'nlinks' => '$1 {{PLURAL:$1|ligação|ligações}}',
 'nmembers' => '$1 {{PLURAL:$1|membro|membros}}',
+'nmemberschanged' => '$1 → $2 {{PLURAL:$2|membro|membros}}',
 'nrevisions' => '$1 {{PLURAL:$1|edição|edições}}',
 'nviews' => '$1 {{PLURAL:$1|visita|visitas}}',
 'nimagelinks' => 'Usada {{PLURAL:$1|numa página|em $1 páginas}}',
@@ -2276,9 +2292,13 @@ Agora redirecciona para [[$2]].',
 'protectedpages-cascade' => 'Apenas proteções em cascata',
 'protectedpages-noredirect' => 'Esconder redirecionamentos',
 'protectedpagesempty' => 'Neste momento, nenhuma das páginas está protegida com estes parâmetros.',
-'protectedpages-timestamp' => 'Timestamp',
+'protectedpages-timestamp' => 'Data e hora',
+'protectedpages-page' => 'Página',
 'protectedpages-expiry' => 'Expira em',
-'protectedpages-params' => 'Parâmetros de protecção',
+'protectedpages-performer' => 'Protetor',
+'protectedpages-params' => 'Parâmetros de proteção',
+'protectedpages-reason' => 'Motivo',
+'protectedpages-unknown-timestamp' => 'Desconhecido',
 'protectedpages-unknown-performer' => 'Utilizador desconhecido',
 'protectedtitles' => 'Títulos protegidos',
 'protectedtitles-summary' => 'Esta página lista os títulos protegidos, cuja criação está impossibilitada. Para ver as páginas protegidas consulte [[{{#special:ProtectedPages}}]].',
@@ -2735,6 +2755,7 @@ Para referência é apresentado abaixo o último registo de bloqueio:',
 'sp-contributions-search' => 'Pesquisar contribuições',
 'sp-contributions-username' => 'Endereço IP ou utilizador:',
 'sp-contributions-toponly' => 'Mostrar somente as revisões mais recentes',
+'sp-contributions-newonly' => 'Mostrar só edições que são criações de páginas',
 'sp-contributions-submit' => 'Pesquisar',
 
 # What links here
@@ -2792,7 +2813,7 @@ Isto só deve ser feito para prevenir vandalismo e de acordo com a [[{{MediaWiki
 'blockipsuccesstext' => '[[Special:Contributions/$1|$1]] foi {{GENDER:$1|bloqueado|bloqueada}}.<br />
 Consulte a [[Special:BlockList|lista de bloqueios]] para rever os bloqueios.',
 'ipb-blockingself' => 'Está prestes a bloquear-se a si próprio. Tem a certeza de que pretende fazê-lo?',
-'ipb-confirmhideuser' => 'Está prestes a bloquear um utilizador com "Ocultar nome de utilizador/IP" ativado. Isto irá suprimir o nome do utilizador de todas as listas e entradas dos registros. Tem a certeza de que pretende fazê-lo?',
+'ipb-confirmhideuser' => 'Está prestes a bloquear um utilizador com "Ocultar nome de utilizador/IP" ativado. Isto irá suprimir o nome do utilizador de todas as listas e entradas dos registos. Tem a certeza de que pretende fazê-lo?',
 'ipb-confirmaction' => 'Se tem a certeza de que quer fazê-lo, marque o campo "{{int:ipb-confirm}}" ao fundo.',
 'ipb-edit-dropdown' => 'Editar motivos de bloqueio',
 'ipb-unblock-addr' => 'Desbloquear $1',
@@ -3093,6 +3114,7 @@ Não há um diretório temporário.',
 'import-error-special' => 'A página "$1" não pode ser importada porque ela pertence a um espaço nominal especial que não permite páginas.',
 'import-error-invalid' => 'A página "$1" não pode ser importada porque seu nome é inválido.',
 'import-error-unserialize' => 'Revisão $2 da página "$1" não pode ser desserializada. Foi relatado que a revisão usava o modelo de conteúdo $3 serializado como $4.',
+'import-error-bad-location' => 'A revisão $2, que usa o modelo de conteúdo $3, não pode ser gravada em "$1" nesta wiki, porque o modelo não é suportado nessa página.',
 'import-options-wrong' => '{{PLURAL:$2|Opção errada|Opções erradas}}: <nowiki>$1</nowiki>',
 'import-rootpage-invalid' => 'A raiz da página dada é um título inválido.',
 'import-rootpage-nosubpage' => 'O domínio "$1" da página de raiz não permite subpáginas.',
@@ -3144,7 +3166,7 @@ Utilize o botão "Antever resultado" antes de gravar, por favor.',
 'tooltip-p-logo' => 'Visite a página principal',
 'tooltip-n-mainpage' => 'Visitar a página principal',
 'tooltip-n-mainpage-description' => 'Visitar a página principal',
-'tooltip-n-portal' => 'Sobre o projeto, o que se pode fazer e onde achar as coisas',
+'tooltip-n-portal' => 'Sobre o projeto, o que se pode fazer e onde encontrar as coisas',
 'tooltip-n-currentevents' => 'Informação temática sobre acontecimentos atuais',
 'tooltip-n-recentchanges' => 'A lista de mudanças recentes nesta wiki.',
 'tooltip-n-randompage' => 'Carregar página aleatória',
@@ -3316,9 +3338,9 @@ $1',
 'nextdiff' => 'Edição posterior →',
 
 # Media information
-'mediawarning' => '<strong>AVISO:</strong> Este tipo de arquivo pode conter código malicioso.
+'mediawarning' => '<strong>Aviso:</strong> Este tipo de ficheiro pode conter código malicioso.
 Se o executar, o seu sistema pode ficar comprometido.',
-'imagemaxsize' => 'Tamanho limite da imagem:<br /><em>(para páginas com descrições de arquivos)</em>',
+'imagemaxsize' => 'Tamanho limite da imagem:<br /><em>(para páginas de descrição de ficheiros)</em>',
 'thumbsize' => 'Tamanho de miniaturas:',
 'widthheightpage' => '$1 × $2, $3 {{PLURAL:$3|página|páginas}}',
 'file-info' => 'tamanho: $1, tipo MIME: $2',
@@ -3328,7 +3350,7 @@ Se o executar, o seu sistema pode ficar comprometido.',
 'svg-long-desc' => 'ficheiro SVG, de $1 × $2 pixels, tamanho: $3',
 'svg-long-desc-animated' => 'ficheiro SVG animado, de $1 × $2 pixels, tamanho: $3',
 'svg-long-error' => 'Ficheiro SVG inválido: $1',
-'show-big-image' => 'Arquivo original',
+'show-big-image' => 'Ficheiro original',
 'show-big-image-preview' => 'Tamanho desta antevisão: $1.',
 'show-big-image-other' => '{{PLURAL:$2|Outra resolução|Outras resoluções}}: $1.',
 'show-big-image-size' => '$1 × $2 pixels',
@@ -3822,7 +3844,7 @@ Pode agora [[Special:UserLogin|autenticar-se]] e desfrutar da wiki.',
 'confirmemail_loggedin' => 'O seu endereço de correio eletrónico foi confirmado.',
 'confirmemail_subject' => 'Confirmação de endereço de correio eletrónico da {{SITENAME}}',
 'confirmemail_body' => 'Alguém, provavelmente você a partir do endereço IP $1,
-registrou uma conta "$2" com este endereço de correio eletrónico na {{SITENAME}}.
+registou uma conta "$2" com este endereço de correio eletrónico na {{SITENAME}}.
 
 Para confirmar que esta conta é realmente sua e ativar
 as funcionalidades de correio eletrónico na {{SITENAME}},
@@ -3894,6 +3916,9 @@ Por favor, confirme que você quer realmente recriar esta página.',
 'confirm-unwatch-button' => 'OK',
 'confirm-unwatch-top' => 'Remover esta página das páginas vigiadas?',
 
+# Separators for various lists, etc.
+'quotation-marks' => '"$1"',
+
 # Multipage image navigation
 'imgmultipageprev' => '← página anterior',
 'imgmultipagenext' => 'página seguinte →',
@@ -3995,6 +4020,7 @@ Também pode [[Special:EditWatchlist|editar a lista da maneira convencional]].',
 'version-ext-colheader-credits' => 'Autores',
 'version-license-title' => 'Licença para $1',
 'version-license-not-found' => 'Não foi encontrada informação detalhada da licença para esta extensão.',
+'version-credits-title' => 'Créditos de autoria da extensão $1',
 'version-credits-not-found' => 'Não foi encontrada informação detalhada dos créditos para esta extensão.',
 'version-poweredby-credits' => 'Esta wiki é potenciada por <strong>[https://www.mediawiki.org/ MediaWiki]</strong>, copyright © 2001-$1 $2.',
 'version-poweredby-others' => 'outros',
@@ -4272,6 +4298,4 @@ Na verdade, expande tudo o que estiver entre chavetas duplas.",
 'expand_templates_generate_rawhtml' => 'Mostrar o HTML puro',
 'expand_templates_preview' => 'Antevisão do resultado',
 
-# Unknown messages
-'uploadinvalidxml' => 'Erro detectado na análise do XML do ficheiro carregado.',
 );
index 592a920..3b0b49a 100644 (file)
@@ -9,6 +9,7 @@
  *
  * @author Alcali
  * @author Alchimista
+ * @author Anaclaudiaml
  * @author Bani
  * @author Brion
  * @author BrunaaAa
@@ -873,6 +874,8 @@ Por favor aguarde $1 antes de tentar novamente.',
 'suspicious-userlogout' => 'Sua solicitação para sair foi negada porque aparentemente foi enviada por um navegador danificado ou por um servidor proxy com cache.',
 'createacct-another-realname-tip' => 'O nome verdadeiro é opcional.
 Se você optar por fornecê-lo, este nome será utilizado para dar ao usuário a atribuição de seu trabalho.',
+'pt-login' => 'Entrar',
+'pt-createaccount' => 'Criar conta',
 
 # Email sending
 'php-mail-error-unknown' => 'Erro desconhecido na função mail() do PHP',
@@ -881,7 +884,7 @@ Se você optar por fornecê-lo, este nome será utilizado para dar ao usuário a
 
 # Change password dialog
 'changepassword' => 'Alterar senha',
-'resetpass_announce' => 'Você foi autenticado através de uma senha temporária. Para prosseguir, será necessário definir uma nova senha.',
+'resetpass_announce' => 'Para completar a autenticação, é necessário definir uma nova senha.',
 'resetpass_text' => '<!-- Adicionar texto aqui -->',
 'resetpass_header' => 'Alterar a senha da conta',
 'oldpassword' => 'Senha antiga',
@@ -897,8 +900,12 @@ Por favor, aguarde $1 antes de tentar novamente.',
 'resetpass-submit-cancel' => 'Cancelar',
 'resetpass-wrong-oldpass' => 'Senha temporária ou atual inválida.
 Você pode já ter alterado com sucesso a sua senha, ou solicitado uma nova senha temporária.',
+'resetpass-recycled' => 'Por favor, redefina sua nova senha para uma diferente da atual.',
+'resetpass-temp-emailed' => 'Você está autenticado com o código temporário enviado. Para finalizar a autenticação, você deve inserir uma nova senha aqui:',
 'resetpass-temp-password' => 'Senha temporária:',
 'resetpass-abort-generic' => 'Uma extensão cancelou a alteração da senha.',
+'resetpass-expired' => 'Sua senha expirou. Por favor insira uma nova senha para autenticar-se.',
+'resetpass-expired-soft' => 'Sua senha expirou e necessita ser resetada. Por favor escolha uma nova agora, ou clique "{{int:resetpass-submit-cancel}}" para resetar mais tarde.',
 
 # Special:PasswordReset
 'passwordreset' => 'Redefinir senha',
@@ -1756,11 +1763,23 @@ Caso decida fornecê-lo, este será utilizado para dar-lhe crédito pelo seu tra
 'rcnotefrom' => "Seguem as alterações desde as '''$4''' de '''$3''' (limitadas a '''$1''').",
 'rclistfrom' => 'Mostrar as novas alterações a partir das $1',
 'rcshowhideminor' => '$1 edições menores',
+'rcshowhideminor-show' => 'Exibir',
+'rcshowhideminor-hide' => 'Ocultar',
 'rcshowhidebots' => '$1 robôs',
+'rcshowhidebots-show' => 'Exibir',
+'rcshowhidebots-hide' => 'Ocultar',
 'rcshowhideliu' => '$1 usuários registrados',
+'rcshowhideliu-show' => 'Exibir',
+'rcshowhideliu-hide' => 'Ocultar',
 'rcshowhideanons' => '$1 usuários anônimos',
+'rcshowhideanons-show' => 'Exibir',
+'rcshowhideanons-hide' => 'Ocultar',
 'rcshowhidepatr' => '$1 edições patrulhadas',
+'rcshowhidepatr-show' => 'Exibir',
+'rcshowhidepatr-hide' => 'Ocultar',
 'rcshowhidemine' => '$1 minhas edições',
+'rcshowhidemine-show' => 'Exibir',
+'rcshowhidemine-hide' => 'Ocultar',
 'rclinks' => 'Exibir as $1 alterações recentes feitas nos últimos $2 dias<br />$3',
 'diff' => 'dif',
 'hist' => 'his',
@@ -1882,6 +1901,7 @@ Se você ainda quer enviar seu arquivo, volte e use um novo nome.
 'file-exists-duplicate' => 'Este arquivo é uma duplicata do seguinte {{PLURAL:$1|arquivo|arquivos}}:',
 'file-deleted-duplicate' => 'Um arquivo idêntico a este ([[:$1]]) foi eliminado anteriormente.
 Verifique o histórico de eliminação de tal arquivo antes de tentar re-enviar.',
+'file-deleted-duplicate-notitle' => 'Um arquivo idêntico a este foi anteriormente excluído, e o título foi suprimido. Você deve comunicar com alguém capaz de visualizar dados suprimidos, para verificar a situação antes de enviá-lo novamente.',
 'uploadwarning' => 'Aviso de envio',
 'uploadwarning-text' => 'Modifique a descrição do arquivo abaixo e tente novamente.',
 'savefile' => 'Salvar arquivo',
@@ -1894,6 +1914,8 @@ Verifique o histórico de eliminação de tal arquivo antes de tentar re-enviar.
 'php-uploaddisabledtext' => 'O envio de arquivos via PHP está desativado.
 Verifique a configuração file_uploads.',
 'uploadscripted' => 'Este arquivo contém HTML ou código que pode ser erroneamente interpretado por um navegador web.',
+'uploadscriptednamespace' => 'Este aruivo SVG contém um espaço nominal probido "$1"',
+'uploadinvalidxml' => 'O XML no arquivo enviado não pôde ser analisado.',
 'uploadvirus' => 'O arquivo contém vírus!
 Detalhes: $1',
 'uploadjava' => 'Este é um arquivo ZIP que contém um arquivo .class de Java.
@@ -4247,6 +4269,4 @@ Na verdade, expande tudo que está entre chaves duplas.',
 'expand_templates_generate_rawhtml' => 'Mostrar HTML puro',
 'expand_templates_preview' => 'Pré-visualização',
 
-# Unknown messages
-'uploadinvalidxml' => 'O XML no arquivo enviado não pôde ser analisado.',
 );
index 8c4ae56..9b0aac2 100644 (file)
  * @author Verdy p
  * @author Vinhtantran
  * @author Vivaelcelta
+ * @author Vriullop
  * @author Waldir
  * @author Whym
  * @author Yekrats
@@ -1435,6 +1436,9 @@ Parameters:
 * $1 - number of contributors (users)',
 'badretype' => 'Used as error message when the new password and its retype do not match.',
 'userexists' => 'Used as error message in creating a user account.',
+'createacct-normalization' => 'Used as warning message on account creation when user name is adjusted silently due to technical restrictions (e.g. first letter capitalized, underscores converted to spaces).
+* $1 - the old username
+* $2 - the new username',
 'loginerror' => 'Used as title of error message.
 {{Identical|Login error}}',
 'createacct-error' => 'Used as heading for the error message.',
@@ -1642,7 +1646,7 @@ Parameters:
 'resetpass-temp-password' => 'The label of the input box for the temporary password (received by email) on the form displayed after logging in with a temporary password.',
 'resetpass-abort-generic' => 'Generic error message shown on [[Special:ChangePassword]] when an extension aborts a password change from a hook.',
 'resetpass-expired' => "Generic error message shown on [[Special:ChangePassword]] when a user's password is expired",
-'resetpass-expired-soft' => 'Generic marning message shown on [[Special:ChangePassword]] when a user needs to reset their password, but they are not prevented from logging in at this time',
+'resetpass-expired-soft' => 'Generic warning message shown on [[Special:ChangePassword]] when a user needs to reset their password, but they are not prevented from logging in at this time',
 
 # Special:PasswordReset
 'passwordreset' => 'Title of [[Special:PasswordReset]].
@@ -3682,35 +3686,107 @@ Preceded by legend example {{msg-mw|Recentchanges-legend-plusminus}}.',
 A plus/minus sign with a number for the legend.',
 'rcnotefrom' => 'This message is displayed at [[Special:RecentChanges]] when viewing recentchanges from some specific time.
 
-The corresponding message is {{msg-mw|Rclistfrom}} (without split of date and time, [[bugzilla:19104|Bug 19104]]).
+The corresponding message is {{msg-mw|Rclistfrom}} (split into date and time).
 
 Parameters:
 * $1 - the maximum number of changes that are displayed
 * $2 - a date and time
 * $3 - (Optional) a date
 * $4 - (Optional) a time',
-'rclistfrom' => 'Used on [[Special:RecentChanges]].
-
-Parameters:
-* $1 - a link to the revision of a specific date and time. The date and the time are the link description (without split of date and time, [[bugzilla:19104|Bug 19104]]).
+'rclistfrom' => 'Used on [[Special:RecentChanges]]. Parameters:
+* $1 - (Optional) date and time. The date and the time adds to the rclistfrom description.
+* $2 - time. The time adds to the rclistfrom link description (with split of date and time).
+* $3 - date. The date adds to the rclistfrom link description (with split of date and time).
 
 The corresponding message is {{msg-mw|Rcnotefrom}}.',
 'rcshowhideminor' => 'Option text in [[Special:RecentChanges]]. Parameters:
-* $1 - the "show/hide" command, with the text taken from either {{msg-mw|Show}} or {{msg-mw|Hide}}',
+* $1 - the "show/hide" command, with the text taken from either {{msg-mw|rcshowhideminor-show}} or {{msg-mw|rcshowhideminor-hide}}',
+'rcshowhideminor-show' => '{{doc-actionlink}}
+Option text in [[Special:RecentChanges]] in conjunction with {{msg-mw|rcshowhideminor}}.
+
+See also:
+* {{msg-mw|rcshowhideminor-hide}}
+{{Identical|Show}}',
+'rcshowhideminor-hide' => '{{doc-actionlink}}
+Option text in [[Special:RecentChanges]] in conjunction with {{msg-mw|rcshowhideminor}}.
+
+See also:
+* {{msg-mw|rcshowhideminor-show}}
+{{Identical|Hide}}',
 'rcshowhidebots' => 'Option text in [[Special:RecentChanges]]. Parameters:
-* $1 - the "show/hide" command, with the text taken from either {{msg-mw|Show}} or {{msg-mw|Hide}}
+* $1 - the "show/hide" command, with the text taken from either {{msg-mw|rcshowhidebots-show}} or {{msg-mw|rcshowhidebots-hide}}
 {{Identical|$1 bots}}',
+'rcshowhidebots-show' => '{{doc-actionlink}}
+Option text in [[Special:RecentChanges]] in conjunction with {{msg-mw|rcshowhidebots}}.
+
+See also:
+* {{msg-mw|rcshowhidebots-show}}
+{{Identical|Show}}',
+'rcshowhidebots-hide' => '{{doc-actionlink}}
+Option text in [[Special:RecentChanges]] in conjunction with {{msg-mw|rcshowhidebots}}.
+
+See also:
+* {{msg-mw|rcshowhidebots-hide}}
+{{Identical|Hide}}',
 'rcshowhideliu' => 'Option text in [[Special:RecentChanges]]. Parameters:
 * $1 - any one of the following messages:
-** {{msg-mw|Show}}
-** {{msg-mw|Hide}}',
+** {{msg-mw|rcshowhideliu-show}}
+** {{msg-mw|rcshowhideliu-hide}}',
+'rcshowhideliu-show' => '{{doc-actionlink}}
+Option text in [[Special:RecentChanges]] in conjunction with {{msg-mw|rcshowhideliu}}.
+
+See also:
+* {{msg-mw|rcshowhideliu-hide}}
+{{Identical|Show}}',
+'rcshowhideliu-hide' => '{{doc-actionlink}}
+Option text in [[Special:RecentChanges]] in conjunction with {{msg-mw|rcshowhideliu}}.
+
+See also:
+* {{msg-mw|rcshowhideliu-show}}
+{{Identical|Hide}}',
 'rcshowhideanons' => 'Option text in [[Special:RecentChanges]]. Parameters:
-* $1 - the "show/hide" command, with the text taken from either {{msg-mw|Show}} or {{msg-mw|Hide}}
+* $1 - the "show/hide" command, with the text taken from either {{msg-mw|rcshowhideanons-show}} or {{msg-mw|showhideanons-hide}}
 {{Identical|Anonymous user}}',
+'rcshowhideanons-show' => '{{doc-actionlink}}
+Option text in [[Special:RecentChanges]] in conjunction with {{msg-mw|rcshowhideanons}}.
+
+See also:
+* {{msg-mw|rcshowhideanons-hide}}
+{{Identical|Hide}}',
+'rcshowhideanons-hide' => '{{doc-actionlink}}
+Option text in [[Special:RecentChanges]] in conjunction with {{msg-mw|rcshowhideanons}}.
+
+See also:
+* {{msg-mw|rcshowhideanons-show}}
+{{Identical|hide}}',
 'rcshowhidepatr' => 'Option text in [[Special:RecentChanges]]. Parameters:
-* $1 - the "show/hide" command, with the text taken from either {{msg-mw|Show}} or {{msg-mw|Hide}}',
+* $1 - the "show/hide" command, with the text taken from either {{msg-mw|rcshowhidepatr-show}} or {{msg-mw|rcshowhidepatr-hide}}',
+'rcshowhidepatr-show' => '{{doc-actionlink}}
+Option text in [[Special:RecentChanges]] in conjunction with {{msg-mw|rcshowhidepatr}}.
+
+See also:
+* {{msg-mw|rcshowhidepatr-hide}}
+{{Identical|Show}}',
+'rcshowhidepatr-hide' => '{{doc-actionlink}}
+Option text in [[Special:RecentChanges]] in conjunction with {{msg-mw|rcshowhidepatr}}.
+
+See also:
+* {{msg-mw|rcshowhidepatr-show}}
+{{Identical|Hide}}',
 'rcshowhidemine' => 'Option text in [[Special:RecentChanges]]. Parameters:
-* $1 - the "show/hide" command, with the text taken from either {{msg-mw|Show}} or {{msg-mw|Hide}}',
+* $1 - the "show/hide" command, with the text taken from either {{msg-mw|rcshowhidemine-show}} or {{msg-mw|rcshowhidemine-hide}}',
+'rcshowhidemine-show' => '{{doc-actionlink}}
+Option text in [[Special:RecentChanges]] in conjunction with {{msg-mw|rcshowhidemine}}.
+
+See also:
+* {{msg-mw|rcshowhidemine-hide}}
+{{Identical|show}}',
+'rcshowhidemine-hide' => '{{doc-actionlink}}
+Option text in [[Special:RecentChanges]] in conjunction with {{msg-mw|rcshowhidemine}}.
+
+See also:
+* {{msg-mw|rcshowhidemine-show}}
+{{Identical|hide}}',
 'rclinks' => "Used on [[Special:RecentChanges]].
 * \$1 - a list of different choices with number of pages to be shown.<br />&nbsp;Example: \"''50{{int:pipe-separator}}100{{int:pipe-separator}}250{{int:pipe-separator}}500\".
 * \$2 - a list of clickable links with a number of days for which recent changes are to be displayed.<br />&nbsp;Example: \"''1{{int:pipe-separator}}3{{int:pipe-separator}}7{{int:pipe-separator}}14{{int:pipe-separator}}30''\".
@@ -4142,6 +4218,15 @@ See also:
 * {{msg-mw|zip-wrong-format}}
 * {{msg-mw|uploadjava}}
 * {{msg-mw|uploadvirus}}',
+'uploadscriptednamespace' => 'Used as error message when uploading a file. This error is specific to SVG files, when they include a namespace that has not been whitelisted.
+
+Parameters:
+* $1 - the invalid namespace name
+See also:
+* {{msg-mw|zip-wrong-format}}
+* {{msg-mw|uploadjava}}
+* {{msg-mw|uploadvirus}}',
+'uploadinvalidxml' => 'Error message displayed when the uploaded file contains XML that cannot be properly parsed and checked.',
 'uploadvirus' => 'Error message displayed when uploaded file contains a virus.
 
 Parameters:
@@ -5038,7 +5123,11 @@ See also:
 This refers to expiry timestamp.
 {{Identical|Expire}}',
 'protectedpages-performer' => 'This is a column header in the table on the page [[Special:ProtectedPages]].',
-'protectedpages-params' => 'This is a column header in the table on the page [[Special:ProtectedPages]].',
+'protectedpages-params' => 'This is a column header in the table on the page [[Special:ProtectedPages]].
+
+Protection parameters are:
+* {{msg-mw|Restriction-level-autoconfirmed}}
+* {{msg-mw|Restriction-level-sysop}}',
 'protectedpages-reason' => 'This is a column header in the table on the page [[Special:ProtectedPages]].
 {{Identical|Reason}}',
 'protectedpages-unknown-timestamp' => 'This is shown, when the date and time is unknown for a protection on the page [[Special:ProtectedPages]].
@@ -5847,7 +5936,19 @@ Parameters:
 {{Related|Protect-locked}}',
 'protect-cascadeon' => 'Used in Protection form.
 * $1 - number of cascade source pages',
-'protect-default' => '{{Identical|Default}}',
+'protect-default' => 'Describes the protection state of a page that allows all users to do a certain thing, like editing or moving the page. Example:
+
+<div style="border: 2px dotted gray; padding: .25cm">
+=={{int:Pageinfo-header-restrictions/en}}==
+{| class="wikitable"
+|-
+| {{int:Restriction-edit/en}}
+| {{int:Protect-default/en}}
+|-
+| {{int:Restriction-move/en}}
+| {{int:Protect-level-autoconfirmed/en}}
+|}
+</div>',
 'protect-fallback' => 'This message is used as an option in the protection form on wikis were extra protection levels have been configured.
 
 Parameters:
@@ -6269,6 +6370,11 @@ Anon version:
 'sp-contributions-username' => 'This message appears whenever someone requests [[Special:Contributions]].
 {{Identical|IP address or username}}',
 'sp-contributions-toponly' => '"top revision" means the "latest revision"',
+'sp-contributions-newonly' => 'Used as checkbox label.
+
+"page creation" means the "first revision" of a page.
+
+Preceded by {{msg-mw|Sp-contributions-toponly}}.',
 'sp-contributions-submit' => '{{Identical|Search}}',
 'sp-contributions-explain' => '{{optional}}',
 
@@ -10750,6 +10856,4 @@ test
 'expand_templates_generate_rawhtml' => 'Used as checkbox label.',
 'expand_templates_preview' => '{{Identical|Preview}}',
 
-# Unknown messages
-'uploadinvalidxml' => 'Error message displayed when the uploaded file contains XML that cannot be properly parsed and checked.',
 );
index f37147d..8f571ef 100644 (file)
@@ -1747,6 +1747,7 @@ Kay churkunayki rikcha hunt'a chhikan kayniyuq kaptinqa, chay hunt'atam churkuy,
 'uploaddisabledtext' => 'Willañiqi churkuyqa manam saqillasqachu.',
 'php-uploaddisabledtext' => "PHP-wan willañiqi churkuyqa hark'asqam. Ama hina kaspa, willañiqi churkuy allinkachinakunata llanchiy.",
 'uploadscripted' => "Kay willañiqiqa wakichi icha HTML qillqayuqmi, llika wamp'unaqa pantalla unanchanmanchá.",
+'uploadinvalidxml' => 'Manam atinichu churkusqa willañiqipi XML-ta kuskiyta.',
 'uploadvirus' => 'Willañiqipiqa añawmi! Yuyay: $1',
 'uploadjava' => 'Kay ZIP willañiqiqa Java .class willañiqiyuqmi.
 Java churkuyqa manam saqillasqachu, qasikanapaq saywachasqa kanman karunchana tiyanman.',
@@ -3992,6 +3993,4 @@ Mana chayqa, kay qatiqpi kaq hunt'ana p'anqatam llamk'achiyta atinki. Willapuyni
 'expand_templates_generate_rawhtml' => 'Chawa HTML-ta rikuchiy',
 'expand_templates_preview' => 'Ñawpaqta qhawallay',
 
-# Unknown messages
-'uploadinvalidxml' => 'Manam atinichu churkusqa willañiqipi XML-ta kuskiyta.',
 );
index 13e0f83..f340f29 100644 (file)
@@ -870,7 +870,7 @@ Pentru a finaliza acțiunea de autentificare, trebuie să setați o parolă nou
 'resetpass-temp-password' => 'Parolă temporară:',
 'resetpass-abort-generic' => 'Schimbarea parolei a fost anulată de către o extensie.',
 'resetpass-expired' => 'Parola dumneavoastră a expirat. Alegeți o parolă nouă pentru a vă autentifica.',
-'resetpass-expired-soft' => 'Parola dumneavoastră a expirat și trebuie schimbată. Alegeți o parolă nouă acum sau apăsați Revocare pentru a o reseta mai târziu.',
+'resetpass-expired-soft' => 'Parola dumneavoastră a expirat și trebuie schimbată. Alegeți o parolă nouă acum sau apăsați „{{int:resetpass-submit-cancel}}” pentru a o reseta mai târziu.',
 
 # Special:PasswordReset
 'passwordreset' => 'Resetare parolă',
@@ -1724,14 +1724,26 @@ Dacă decideți furnizarea sa, acesta va fi folosit pentru a vă atribui munca.'
 'recentchanges-legend-heading' => "'''Legendă:'''",
 'recentchanges-legend-newpage' => '(vedeți și [[Special:NewPages|lista cu pagini noi]])',
 'recentchanges-legend-plusminus' => "(''±123'')",
-'rcnotefrom' => 'Dedesubt sunt modificările de la <b>$2</b> (maxim <b>$1</b> de modificări sunt afișate - schimbă numărul maxim de linii alegând altă valoare mai jos).',
+'rcnotefrom' => 'Dedesubt sunt modificările începând cu <b>$2</b> (maximum <b>$1</b> afișate).',
 'rclistfrom' => 'Se arată modificările începând cu $1',
 'rcshowhideminor' => '$1 modificările minore',
+'rcshowhideminor-show' => 'Arată',
+'rcshowhideminor-hide' => 'Ascunde',
 'rcshowhidebots' => '$1 roboții',
+'rcshowhidebots-show' => 'Arată',
+'rcshowhidebots-hide' => 'Ascunde',
 'rcshowhideliu' => '$1 utilizatorii înregistrați',
+'rcshowhideliu-show' => 'Arată',
+'rcshowhideliu-hide' => 'Ascunde',
 'rcshowhideanons' => '$1 utilizatorii anonimi',
+'rcshowhideanons-show' => 'Arată',
+'rcshowhideanons-hide' => 'Ascunde',
 'rcshowhidepatr' => '$1 modificările patrulate',
+'rcshowhidepatr-show' => 'Arată',
+'rcshowhidepatr-hide' => 'Ascunde',
 'rcshowhidemine' => '$1 contribuțiile mele',
+'rcshowhidemine-show' => 'Arată',
+'rcshowhidemine-hide' => 'Ascunde',
 'rclinks' => 'Se arată ultimele $1 modificări din ultimele $2 zile.<br />
 $3',
 'diff' => 'dif',
@@ -1859,6 +1871,8 @@ Ar trebui să contactați pe cineva care poate vizualiza datele suprimate ale fi
 'php-uploaddisabledtext' => 'Încărcarea de fișiere este dezactivată în PHP.
 Vă rugăm să verificați setările din file_uploads.',
 'uploadscripted' => 'Fișierul conține HTML sau cod script care poate fi interpretat în mod eronat de un browser.',
+'uploadscriptednamespace' => 'Acest fișier SVG conține un spațiu de nume „$1” neautorizat.',
+'uploadinvalidxml' => 'Nu s-a putut analiza conținutul XML din fișierul încărcat.',
 'uploadvirus' => 'Fișierul conține un virus! Detalii: $1',
 'uploadjava' => 'Fișierul de față este o arhivă ZIP care conține un fișier de clasă Java.
 Încărcarea fișierelor Java nu este permisă, întrucât pot evita restricțiile de securitate.',
@@ -2688,6 +2702,7 @@ Iată aici ultima înregistrare relevantă din jurnalul blocărilor:',
 'sp-contributions-search' => 'Căutare contribuții',
 'sp-contributions-username' => 'Adresă IP sau nume de utilizator:',
 'sp-contributions-toponly' => 'Afișează numai versiunile recente',
+'sp-contributions-newonly' => 'Afișează numai modificările care au dus la crearea de pagini',
 'sp-contributions-submit' => 'Căutare',
 
 # What links here
@@ -4208,6 +4223,4 @@ MediaWiki este distribuit în speranța că va fi folositor, dar FĂRĂ VREO GAR
 'expand_templates_generate_rawhtml' => 'Arată HTML brut',
 'expand_templates_preview' => 'Previzualizare',
 
-# Unknown messages
-'uploadinvalidxml' => 'Nu s-a putut analiza conținutul XML din fișierul încărcat.',
 );
index 38255d1..f0fc215 100644 (file)
@@ -1600,6 +1600,7 @@ Avissa verificà 'a storie d'a scangellazzione d'u file apprime de condinuà a c
 'php-uploaddisabledtext' => "Le carecaminde de file sonde disabilitate in PHP.<br />
 Pe piacere verifiche le 'mbostaziune d'u ''file_uploads''.",
 'uploadscripted' => "Stu file condene HTML o codece de script ca ponne essere inderpretete jndr'à 'nu mode sbagliete da le browser.",
+'uploadinvalidxml' => "L'XML jndr'à 'u file carecate non ge pò essere analizzate.",
 'uploadvirus' => "Alanga toje, 'u file condiene 'nu virus! Dettaglie: $1",
 'uploadjava' => "'U file jè 'nu file de tipe ZIP ca condene 'nu file de classe Java.
 'U carecamende de le file Java non g'è permesse, purcé lore ponne causà l'aggiramende de le restriziune de sicurezze.",
@@ -4174,6 +4175,4 @@ In pratiche tutte quidde ca stè jndr'à le doppie parendesi graffe.<br />",
 'expand_templates_generate_xml' => "Fà vedè l'arvule de l'analisi XML",
 'expand_templates_preview' => 'Andeprime',
 
-# Unknown messages
-'uploadinvalidxml' => "L'XML jndr'à 'u file carecate non ge pò essere analizzate.",
 );
index 626286c..9253b4c 100644 (file)
@@ -1020,7 +1020,7 @@ $2',
 'resetpass-temp-password' => 'Временный пароль:',
 'resetpass-abort-generic' => 'Изменение пароля было прервано расширением.',
 'resetpass-expired' => 'Срок действия вашего пароля истёк. Пожалуйста, установите новый пароль для входа в систему.',
-'resetpass-expired-soft' => 'Срок действия вашего пароля истёк, и теперь он должен быть изменён. Пожалуйста, выберите новый пароль или нажмите «Отменить», чтобы изменить его позже.',
+'resetpass-expired-soft' => 'Срок действия вашего пароля истёк, и теперь он должен быть изменён. Пожалуйста, выберите новый пароль или нажмите «{{int:resetpass-submit-cancel}}», чтобы изменить его позже.',
 
 # Special:PasswordReset
 'passwordreset' => 'Сброс пароля',
@@ -1878,14 +1878,26 @@ $1",
 'recentchanges-legend-heading' => "'''Легенда:'''",
 'recentchanges-legend-newpage' => '(см. также [[Special:NewPages|список новых страниц]])',
 'recentchanges-legend-plusminus' => "(''±123'')",
-'rcnotefrom' => "Ниже перечислены изменения с '''$2''' (не более '''$1''').",
+'rcnotefrom' => 'Ниже перечислены изменения с <strong>$2</strong> (показано не более <strong>$1</strong>).',
 'rclistfrom' => 'Показать изменения с $1.',
 'rcshowhideminor' => '$1 малые правки',
+'rcshowhideminor-show' => 'Показать',
+'rcshowhideminor-hide' => 'Скрыть',
 'rcshowhidebots' => '$1 ботов',
+'rcshowhidebots-show' => 'Показать',
+'rcshowhidebots-hide' => 'Скрыть',
 'rcshowhideliu' => '$1 представившихся участников',
+'rcshowhideliu-show' => 'Показать',
+'rcshowhideliu-hide' => 'Скрыть',
 'rcshowhideanons' => '$1 непредставившихся',
+'rcshowhideanons-show' => 'Показать',
+'rcshowhideanons-hide' => 'Скрыть',
 'rcshowhidepatr' => '$1 проверенные правки',
+'rcshowhidepatr-show' => 'Показать',
+'rcshowhidepatr-hide' => 'Скрыть',
 'rcshowhidemine' => '$1 свои правки',
+'rcshowhidemine-show' => 'Показать',
+'rcshowhidemine-hide' => 'Скрыть',
 'rclinks' => 'Показать последние $1 изменений за $2 дней<br />$3',
 'diff' => 'разн.',
 'hist' => 'история',
@@ -2012,6 +2024,8 @@ $1",
 'uploaddisabledtext' => 'Загрузка файлов отключена.',
 'php-uploaddisabledtext' => 'Загрузка файлов отключена в настройках PHP. Пожалуйста, проверьте значение свойства file_uploads.',
 'uploadscripted' => 'Файл содержит HTML-код или скрипт, который может быть ошибочно обработан браузером.',
+'uploadscriptednamespace' => "Этот SVG-файл содержит некорректное пространство имён '$1'",
+'uploadinvalidxml' => 'XML в загруженном файле не может быть проанализирован.',
 'uploadvirus' => 'Файл содержит вирус! См. $1',
 'uploadjava' => 'Файл представляет собой ZIP-архив, содержащий .class файл Java.
 Загрузка Java-файлов не допускается из-за соображений безопасности.',
@@ -2843,6 +2857,7 @@ $1',
 'sp-contributions-search' => 'Поиск вклада',
 'sp-contributions-username' => 'IP-адрес или имя участника:',
 'sp-contributions-toponly' => 'Показывать только правки, являющиеся последними версиями',
+'sp-contributions-newonly' => 'Показывать только правки, являющиеся созданием страниц',
 'sp-contributions-submit' => 'Найти',
 
 # What links here
@@ -3998,10 +4013,10 @@ $5
 
 # Delete conflict
 'deletedwhileediting' => "'''Внимание'''. Эта страница была удалена после того, как вы начали её править!",
-'confirmrecreate' => "{{GENDER:$1|Участник&nbsp;|Участница&nbsp;|}}[[User:$1|$1]] ([[User talk:$1|обс]]) {{GENDER:$1|удалил|удалила}} эту страницу после того, как вы начали её редактировать, по следующей причине:
+'confirmrecreate' => "{{GENDER:$1|Участник|Участница|}}&nbsp;[[User:$1|$1]] ([[User talk:$1|обс]]) {{GENDER:$1|удалил|удалила}} эту страницу после того, как вы начали её редактировать, по следующей причине:
 : ''$2''.
\9fожалÑ\83йÑ\81Ñ\82а, Ð¿Ð¾Ð´Ñ\82веÑ\80диÑ\82е, Ñ\87Ñ\82о Ð²Ñ\8b Ñ\85оÑ\82иÑ\82е Ð²Ð¾Ñ\81Ñ\81Ñ\82ановить эту страницу.",
-'confirmrecreate-noreason' => '{{GENDER:$1|Участник&nbsp;|Участница&nbsp;|}}[[User:$1|$1]] ([[User talk:$1|обс]]) {{GENDER:$1|удалил|удалила}} эту страницу после того, как вы начали её редактировать. Пожалуйста, подтвердите, что вы действительно хотите восстановить эту страницу.',
\9fожалÑ\83йÑ\81Ñ\82а, Ð¿Ð¾Ð´Ñ\82веÑ\80диÑ\82е, Ñ\87Ñ\82о Ð²Ñ\8b Ñ\85оÑ\82иÑ\82е Ð²Ð½Ð¾Ð²Ñ\8c Ñ\81оздать эту страницу.",
+'confirmrecreate-noreason' => '{{GENDER:$1|Участник|Участница|}}&nbsp;[[User:$1|$1]] ([[User talk:$1|обс]]) {{GENDER:$1|удалил|удалила}} эту страницу после того, как вы начали её редактировать. Пожалуйста, подтвердите, что вы действительно хотите вновь создать эту страницу.',
 'recreate' => 'Создать заново',
 
 'unit-pixel' => ' пикс.',
@@ -4471,6 +4486,4 @@ MediaWiki распространяется в надежде, что она бу
 'expand_templates_generate_rawhtml' => 'Показать HTML',
 'expand_templates_preview' => 'Предпросмотр',
 
-# Unknown messages
-'uploadinvalidxml' => 'XML в загруженном файле не может быть проанализирован.',
 );
index 3b869bf..7efa318 100644 (file)
@@ -8,6 +8,7 @@
  * @file
  *
  * @author Andria
+ * @author L2212
  * @author Marzedu
  * @author Node ue
  * @author לערי ריינהארט
index afb1043..f3e5c31 100644 (file)
 $messages = array(
 # User preference toggles
 'tog-underline' => 'Unnerline airtins:',
-'tog-hideminor' => 'Hide smaa edits in recent chynges',
-'tog-hidepatrolled' => 'Hide patrolled edits in recent chynges',
-'tog-newpageshidepatrolled' => 'Hide patrolled pages frae the new page list',
+'tog-hideminor' => 'Skauk smaa eidits in recent chynges',
+'tog-hidepatrolled' => 'Skauk patrolled eidits in recent chynges',
+'tog-newpageshidepatrolled' => 'Skauk patrolled pages frae the new page leet',
 'tog-extendwatchlist' => 'Mak watchleet bigger tae shaw aw chynges,no jyst the maist recent',
 'tog-usenewrc' => 'Groop chynges bi page in recent chynges and watchleet',
 'tog-numberheadings' => 'Auto-nummer heidins',
-'tog-showtoolbar' => 'Shaw edit tuilbar',
-'tog-editondblclick' => 'Edit pages on dooble-clap (JavaScript)',
+'tog-showtoolbar' => 'Shaw eidit tuilbaur',
+'tog-editondblclick' => 'Eidit pages oan dooble-clap (JavaScript)',
 'tog-editsectiononrightclick' => 'Enable section editin bi richt-clapin on section teitles',
 'tog-rememberpassword' => 'Mynd ma password oan this browser (fer ae maximum o $1 {{PLURAL:$1|day|days}})',
-'tog-watchcreations' => 'Add pages that Ah create an files Ah uplaid til ma watchleet',
+'tog-watchcreations' => 'Add pages that Ah mak an files Ah uplaid til ma watchleet',
 'tog-watchdefault' => 'Add pages an files that Ah edit til ma watchleet',
 'tog-watchmoves' => 'Eik pages an files that Ah muiv til ma watchleet',
 'tog-watchdeletion' => 'Eik pages an files that Ah get rid o til ma watchleet',
 'tog-minordefault' => 'Mairk aa edits "smaa" bi defaut',
-'tog-previewontop' => 'Shaw scance afore edit box an no efter it',
-'tog-previewonfirst' => 'Shaw scance on first edit',
+'tog-previewontop' => 'Shaw owerview afore eidit kist an no efter it',
+'tog-previewonfirst' => 'Shaw scance oan firstwhile eidit',
 'tog-enotifwatchlistpages' => 'Wab-mail me whan ae page or file on ma watchleet is chynged',
-'tog-enotifusertalkpages' => 'Send me ae email whan ma uiser talk page is chynged',
+'tog-enotifusertalkpages' => 'Send me ae wab-mail whan ma uiser tauk page is chynged',
 'tog-enotifminoredits' => 'Send me ae wab-mail fer wee edits o pages an files ava',
 'tog-enotifrevealaddr' => 'Shaw ma email address in notification mails',
 'tog-shownumberswatching' => 'Shaw the nummer o watching uisers',
 'tog-fancysig' => 'Treat signature as wikitext (wioot aen autæmatic airtin)',
 'tog-uselivepreview' => 'Uise live preview (experimental)',
-'tog-forceeditsummary' => 'Gie me a jottin when A dinnae put in a edit summary',
-'tog-watchlisthideown' => 'Hide yer ain edits frae yer watchleet',
-'tog-watchlisthidebots' => 'Hide bot edits frae yer watchleet',
-'tog-watchlisthideminor' => 'Dinna shaw sma edits on ma watchleet',
-'tog-watchlisthideliu' => 'Hide edits by loggit in uisers frae the watchleet',
-'tog-watchlisthideanons' => 'Hide edits by nameless uisers frae the watchleet',
-'tog-watchlisthidepatrolled' => 'Hide patrolled edits frae the watchlist',
+'tog-forceeditsummary' => 'Gie me a jottin when A dinnae put in aen eidit owerview',
+'tog-watchlisthideown' => 'Skauk ma eidits frae the watchleet',
+'tog-watchlisthidebots' => 'Skauk bot eidits frae the watchleet',
+'tog-watchlisthideminor' => 'Dinna shaw smaa eidits oan ma watchleet',
+'tog-watchlisthideliu' => 'Skauk eidits bi loggit in uisers frae the watchleet',
+'tog-watchlisthideanons' => 'Skauk eidits bi nameless uisers frae the watchleet',
+'tog-watchlisthidepatrolled' => 'Skauk patrolled eidits frae the watchlist',
 'tog-ccmeonemails' => 'Gie me copies o emails A write tae ither uisers',
 'tog-diffonly' => 'Dinna shaw page contents ablo diffs',
-'tog-showhiddencats' => 'Shaw hidden categories',
+'tog-showhiddencats' => "Shaw Skauk't categeries",
 'tog-norollbackdiff' => 'Lave oot diff efter rowin back',
-'tog-useeditwarning' => 'Warnish me whan a lea aen edit page wi onsaved chynges',
+'tog-useeditwarning' => 'Warnish me whan Ah lea aen eidit page wi onhained chynges',
 'tog-prefershttps' => 'Aye uise ae secure connection whan loggit in',
 
 'underline-always' => 'Aye',
@@ -89,8 +89,8 @@ $messages = array(
 'thu' => 'Thu',
 'fri' => 'Fri',
 'sat' => 'Sat',
-'january' => 'Januar',
-'february' => 'Februar',
+'january' => 'Januair',
+'february' => 'Febuair',
 'march' => 'Mairch',
 'april' => 'Apryle',
 'may_long' => 'Mey',
@@ -101,11 +101,11 @@ $messages = array(
 'october' => 'October',
 'november' => 'November',
 'december' => 'December',
-'january-gen' => 'Januar',
+'january-gen' => 'Januair',
 'february-gen' => 'February',
-'march-gen' => 'March',
+'march-gen' => 'Mairch',
 'april-gen' => 'Apryle',
-'may-gen' => 'May',
+'may-gen' => 'Mey',
 'june-gen' => 'Juin',
 'july-gen' => 'Julie',
 'august-gen' => 'August',
@@ -125,8 +125,8 @@ $messages = array(
 'oct' => 'Oct',
 'nov' => 'Nov',
 'dec' => 'Diz',
-'january-date' => '$1 Januar',
-'february-date' => '$1 Febuar',
+'january-date' => '$1 Januair',
+'february-date' => '$1 Febuair',
 'march-date' => '$1 Mairch',
 'april-date' => '$1 Apryl',
 'may-date' => '$1 Mey',
@@ -144,8 +144,8 @@ $messages = array(
 'subcategories' => 'Subcategories',
 'category-media-header' => 'Eetems in category "$1"',
 'category-empty' => "''This category haes no pages or eetems at the meenit.''",
-'hidden-categories' => '{{PLURAL:$1|Hidden categorie|Hidden categories}}',
-'hidden-category-category' => 'Hidden cætegories',
+'hidden-categories' => "{{PLURAL:$1|Skauk't categerie|Skauk't categeries}}",
+'hidden-category-category' => "Skauk't cætegories",
 'category-subcat-count' => '{{PLURAL:$2|This category juist haes the follaein subcategory.|This category haes the follaein {{PLURAL:$1|subcategory|$1 subcategories}}, oot o $2 awthegither.}}',
 'category-subcat-count-limited' => 'This category haes the follaein {{PLURAL:$1|subcategory|$1 subcategories}}.',
 'category-article-count' => '{{PLURAL:$2|This category contains the ae follaein page.|The follaein {{PLURAL:$1|page|$1 pages}} is in this category, oot o $2 total.}}',
@@ -165,14 +165,14 @@ $messages = array(
 'morenotlisted' => 'This leet isna complete.',
 'mypage' => 'Ma page',
 'mytalk' => 'Ma tauk',
-'anontalk' => 'Talk fer this IP address',
+'anontalk' => 'Tauk fer this IP address',
 'navigation' => 'Navigation',
 'and' => '&#32;an',
 
 # Cologne Blue skin
 'qbfind' => 'Rake',
 'qbbrowse' => 'Brouse',
-'qbedit' => 'Edit',
+'qbedit' => 'Eidit',
 'qbpageoptions' => 'This page',
 'qbmyoptions' => 'Ma pages',
 'faq' => 'ASQ',
@@ -180,13 +180,13 @@ $messages = array(
 
 # Vector skin
 'vector-action-addsection' => 'Add topic',
-'vector-action-delete' => 'Delete',
+'vector-action-delete' => 'Delyte',
 'vector-action-move' => 'Flit',
 'vector-action-protect' => 'Fend',
-'vector-action-undelete' => 'Ondelete',
+'vector-action-undelete' => 'Ondelyte',
 'vector-action-unprotect' => 'Chynge protection',
 'vector-view-create' => 'Mak',
-'vector-view-edit' => 'Edit',
+'vector-view-edit' => 'Eidit',
 'vector-view-history' => 'See history',
 'vector-view-view' => 'Read',
 'vector-view-viewsource' => 'View soorce',
@@ -195,7 +195,7 @@ $messages = array(
 'variants' => 'Variants',
 
 'navigation-heading' => 'Navigâtion menu',
-'errorpagetitle' => 'Error',
+'errorpagetitle' => 'Mistak',
 'returnto' => 'Return tae $1.',
 'tagline' => 'Frae {{SITENAME}}',
 'help' => 'Help',
@@ -210,13 +210,13 @@ $messages = array(
 'permalink' => 'Permanent airtin',
 'print' => 'Prent',
 'view' => 'View.',
-'edit' => 'Edit',
+'edit' => 'Eidit',
 'create' => 'Mak',
-'editthispage' => 'Edit this page',
+'editthispage' => 'Eidit this page',
 'create-this-page' => 'Mak this page',
-'delete' => 'Delete',
-'deletethispage' => 'Delete this page',
-'undeletethispage' => 'Ondelete this page',
+'delete' => 'Delyte',
+'deletethispage' => 'Delyte this page',
+'undeletethispage' => 'Ondelyte this page',
 'undelete_short' => 'Undelete {{PLURAL:$1|ane edit|$1 edits}}',
 'viewdeleted_short' => 'View {{PLURAL:$1|yin deletit eidit|$1 deletit eidits}}',
 'protect' => 'Fend',
@@ -226,7 +226,7 @@ $messages = array(
 'unprotectthispage' => 'Chynge fend fer this page',
 'newpage' => 'New page',
 'talkpage' => 'Blether ower this page',
-'talkpagelinktext' => 'Talk',
+'talkpagelinktext' => 'Tauk',
 'specialpage' => 'Byordinar Page',
 'personaltools' => 'Personal tuils',
 'postcomment' => 'Eik a message',
@@ -258,15 +258,15 @@ Please wait ae while afore ye try tae access this page again.
 $1',
 'pool-timeout' => 'Timeout waitin fer the lock',
 'pool-queuefull' => 'Pool line is ful',
-'pool-errorunknown' => "Onken't error",
+'pool-errorunknown' => 'Onknawn mistak.',
 
 # All link text and link target definitions of links into project namespace that get used by other message strings, with the exception of user group pages (see grouppage).
 'aboutsite' => 'Aboot {{SITENAME}}',
 'aboutpage' => 'Project:Aboot',
 'copyright' => 'Content is available unner $1 onless itherwise noted.',
 'copyrightpage' => '{{ns:project}}:Copyrichts',
-'currentevents' => 'Gaun on the nou',
-'currentevents-url' => 'Project:Gaun on the nou',
+'currentevents' => 'Gaun oan the nou',
+'currentevents-url' => 'Project:Gaun oan the nou',
 'disclaimers' => 'Disclamation',
 'disclaimerpage' => 'Project:General_disclamation',
 'edithelp' => 'Editin help',
@@ -280,7 +280,7 @@ $1',
 'privacypage' => 'Project:Privacy policy',
 
 'badaccess' => 'Permeission mishanter',
-'badaccess-group0' => 'WARNIN: Ye arnae alloued tae dae whit you hae requestit!',
+'badaccess-group0' => "Ye'r no permited tae dae whit ye hae requestit!",
 'badaccess-groups' => 'The action ye hae requestit is limitit tae uisers in {{PLURAL:$2|the group|ane o the groups}}: $1.',
 
 'versionrequired' => 'Version $1 of MediaWiki requirit',
@@ -293,13 +293,13 @@ $1',
 'youhavenewmessagesmanyusers' => 'Ye hae $1 fae moni uisers ($2).',
 'newmessageslinkplural' => '{{PLURAL:$1|ae new message|999=new messages}}',
 'newmessagesdifflinkplural' => 'last {{PLURAL:$1|chynge|999=chynges}}',
-'youhavenewmessagesmulti' => 'Ye hae neow messages on $1',
-'editsection' => 'edit',
-'editold' => 'edit',
+'youhavenewmessagesmulti' => 'Ye hae new messages oan $1',
+'editsection' => 'eidit',
+'editold' => 'eidit',
 'viewsourceold' => 'ken soorce',
-'editlink' => 'edit',
+'editlink' => 'eidit',
 'viewsourcelink' => 'Scance ower the source',
-'editsectionhint' => 'Edit section: $1',
+'editsectionhint' => 'Eidit section: $1',
 'toc' => 'Table o contents',
 'showtoc' => 'shaw',
 'hidetoc' => 'scouk',
@@ -307,7 +307,7 @@ $1',
 'collapsible-expand' => 'Mak mair muckle',
 'thisisdeleted' => 'View or cower $1?',
 'viewdeleted' => 'View $1?',
-'restorelink' => '{{PLURAL:$1|one delete edit|$1 delete edits}}',
+'restorelink' => '{{PLURAL:$1|yin delyte eidit|$1 delyte eidits}}',
 'feedlinks' => 'Feed:',
 'feed-invalid' => "This feeds subscrieve's teep isnae habile.",
 'feed-unavailable' => 'Syndication feeds isna available',
@@ -342,49 +342,49 @@ This micht forby be caused by a bug in the saftware uised by {{SITENAME}}.",
 A leet o valid byordinar pages can be funnd at [[Special:SpecialPages|{{int:specialpages}}]].',
 
 # General errors
-'error' => 'Error',
-'databaseerror' => 'Database error',
+'error' => 'Mistak',
+'databaseerror' => 'Database mistak',
 'databaseerror-text' => 'Ae database speirin mistak has occurred.
 This micht be cause o ae bug in the saffware.',
 'databaseerror-textcl' => 'Ae database speirin mistak has occurred.',
 'databaseerror-query' => 'Speirin: $1',
 'databaseerror-function' => 'Fwnction: $1',
 'databaseerror-error' => 'Mistake: $1',
-'laggedslavemode' => 'Warning: Page micht nae contain recent updates',
+'laggedslavemode' => '<strong>Warnishment:</strong> Page micht no contain recent updates',
 'readonly' => 'Database lockit',
-'enterlockreason' => "Enter a raeson for the lock, includin an estimate o whan the lock'll be lowsed",
+'enterlockreason' => "Enter ae raeson fer the lock, inclædin aen estimate o whan the lock'll be lowsed",
 'readonlytext' => "The databae is lockit tae new entries an ither modifeecations the nou,
 likely for routine database maintenance; efter that it'll be back tae normal.
 The adminstration that lockit it gied this explanation:
 $1",
-'missing-article' => 'The database didna find the text o a page that it shuid hae fund, cawed "$1" $2.
+'missing-article' => 'The database didna fynd the tex o ae page that it shid hae foond, cawed "$1" $2.
 
-Maistly this is caused by follaein an ootdated diff or history link tae a page that haes been delete.
+Maistly this is caused bi follaein aen ootdated diff or histerie link til ae page that haes been delytit.
 
-If this isna the case, you micht hae fund a bug in the saftware.
-Please lat an [[Special:ListUsers/sysop|administrator]] ken aboot this, makin note o the URL.',
-'missingarticle-rev' => '(revision#: $1)',
+Gif this isna the case, ye micht hae foond ae bug in the saffware.
+Please lat aen [[Special:ListUsers/sysop|admeenistrater]] ken aboot this, makin note o the URL.',
+'missingarticle-rev' => '(reveesion#: $1)',
 'missingarticle-diff' => '(Diff: $1, $2)',
 'readonly_lag' => 'The database haes been autaematically lockit while the sclave database servers catch up tae the maister',
 'internalerror' => 'Internal mishanter',
-'internalerror_info' => 'Internal error: $1',
+'internalerror_info' => 'Internal mistak: $1',
 'fileappenderrorread' => 'Coudna read "$1" durin append.',
 'fileappenderror' => 'Coudna append "$1" til "$2".',
 'filecopyerror' => 'Cuidna copy file "$1" tae "$2".',
 'filerenameerror' => 'Cuidna rename file "$1" tae "$2".',
-'filedeleteerror' => 'Cuidna delete file "$1".',
+'filedeleteerror' => 'Cuidna delyte file "$1".',
 'directorycreateerror' => 'Culdnae mak directory "$1".',
 'filenotfound' => 'Cuidna fin file "$1".',
 'fileexistserror' => 'Culdnae write tae file "$1": file is already here',
 'unexpected' => 'Vailyie isnae expectit: "$1"="$2".',
-'formerror' => 'Error: cuidna submit form',
+'formerror' => 'Mistak: cuidna haun in form',
 'badarticleerror' => 'This action canna be duin tae this page.',
-'cannotdelete' => 'The page or file "$1" coudna be deleted.
-It micht awreadie hae been deleted bi some ither bodie.',
-'cannotdelete-title' => 'Canna delete page "$1"',
-'delete-hook-aborted' => 'Deletion stappit bi hook.
-It gae nae explanation.',
-'no-null-revision' => 'Coudna create new null revision fer page "$1"',
+'cannotdelete' => 'The page or file "$1" coudna be delytit.
+It micht awreadie hae been delytit bi some ither bodie.',
+'cannotdelete-title' => 'Canna delyte page "$1"',
+'delete-hook-aborted' => 'Delytion stappit bi huik.
+It gae nae explanâtion.',
+'no-null-revision' => 'Coudna mak new null reveesion fer page "$1"',
 'badtitle' => 'Bad teitle',
 'badtitletext' => 'The requestit page teitle wis invalid, tuim, or a wranglie airtit inter-leid or inter-wiki teitle. It mibbe haes ane or mair chairacters that canna be uised in teitles.',
 'perfcached' => 'The follaeing data is cached an michtna be richt up til date. A maximum o {{PLURAL:$1|yin result is|$1 results ar}} available in the cache.',
@@ -397,12 +397,12 @@ It gae nae explanation.',
 'protectedpagetext' => 'This page haes been protected fer tae prevent eiditing or ither actions.',
 'viewsourcetext' => 'Ye can leuk at an copy the soorce o this page:',
 'viewyourtext' => 'Ye can view an copy the source o <strong>yer eidits</strong> til this page:',
-'protectedinterface' => 'This page provides interface tex fer the saffware on this wiki, an is protected fer tae prevent abuse.
+'protectedinterface' => 'This page provides interface tex fer the saffware oan this wiki, n is protected fer tae prevent abuise.
 Tae add or chynge owersets fer aw wikis, please uise [//translatewiki.net/ translatewiki.net], the MediaWiki localisation project.',
 'editinginterface' => "<strong>Warnishment:</strong> Ye'r eiditing ae page that is uised tae provide interface tex fer the saffware.
 Chynges til this page will affect the appearance o the uiser interface fer ither uisers oan this wiki.
 Tae add or chynge owersets fer aw wikis, please uise [//translatewiki.net/ translatewiki.net], the MediaWiki localisation project.",
-'cascadeprotected' => 'This page haes been protectit fra editin, acause it is includit in the followin {{PLURAL:$1|page|pages}}, that are protectit wi the "cascading" option turnit on:
+'cascadeprotected' => 'This page haes been protectit fae editin, cause it is inclædit in the follaein {{PLURAL:$1|page|pages}}, that ar protectit wi the "cascadin" optie turnit oan:
 $2',
 'namespaceprotected' => "Ye dinna hae permeession tae edit pages in the '''$1''' namespace.",
 'customcssprotected' => "Ye dinna hae permeession tae eidit this CSS page cause it contains anither uiser's personal settings.",
@@ -446,7 +446,7 @@ Ye can chynge yer {{SITENAME}} [[Special:Preferences|preferences]] gif ye like.'
 'yourpasswordagain' => 'Retype passwaird:',
 'createacct-yourpasswordagain' => 'Confirm password.',
 'createacct-yourpasswordagain-ph' => 'Enter password again.',
-'remembermypassword' => 'Mynd ma password oan this browser (for a maximum of $1 {{PLURAL:$1|day|days}})',
+'remembermypassword' => 'Mynd ma login oan this brouser (fer $1 {{PLURAL:$1|day|days}} at the maist)',
 'userlogin-remembermypassword' => 'Keep me loggit in',
 'userlogin-signwithsecure' => 'Uise secure connection',
 'yourdomainname' => 'Yer domain:',
@@ -473,7 +473,7 @@ Ye can chynge yer {{SITENAME}} [[Special:Preferences|preferences]] gif ye like.'
 'userlogin-helplink' => '[[{{MediaWiki:helplogin-url}}|Heelp wi loggin in]]',
 'userlogin-loggedin' => "Ye'r awreadie loggit in as {{GENDER:$1|$1}}.
 Uise the form ablow tae log in as anither uiser.",
-'userlogin-createanother' => 'Create anither accoont',
+'userlogin-createanother' => 'Mak anither accoont',
 'createacct-join' => 'Enter yer information ablow.',
 'createacct-another-join' => "Enter the new accoont's information ablow.",
 'createacct-emailrequired' => 'Wab-mail address',
@@ -487,8 +487,8 @@ Uise the form ablow tae log in as anither uiser.",
 'createacct-reason-ph' => 'Why ar ye creating anither accoont',
 'createacct-captcha' => 'Security check.',
 'createacct-imgcaptcha-ph' => 'Enter the tex ye see abuin',
-'createacct-submit' => 'Create yer accoont',
-'createacct-another-submit' => 'Create anither accoont',
+'createacct-submit' => 'Mak yer accoont',
+'createacct-another-submit' => 'Mak anither accoont',
 'createacct-benefit-heading' => '{{SITENAME}} is made bi fowk like ye.',
 'createacct-benefit-body1' => '{{PLURAL:$1|eidit|eidits}}',
 'createacct-benefit-body2' => '{{PLURAL:$1|page|pages}}.',
@@ -496,8 +496,8 @@ Uise the form ablow tae log in as anither uiser.",
 'badretype' => 'The passwords ye entered disna match.',
 'userexists' => 'The uiser name ye entered is awreadie in uiss. Please chuise ae different name.',
 'loginerror' => 'Login mishanter',
-'createacct-error' => 'Accoont creation mistak',
-'createaccounterror' => 'Coudna create accoont: $1',
+'createacct-error' => 'Accoont cræftin mistak',
+'createaccounterror' => 'Coudna mak accoont: $1',
 'nocookiesnew' => "The uiser accoont wis creatit, but ye'r no loggit in. {{SITENAME}} uises cookies tae log uisers in. Ye hae cookies disabled. Please enable them, than log in wi yer new uisername and password.",
 'nocookieslogin' => '{{SITENAME}} uises cookies tae log in uisers. Ye hae cookies disabled. Please enable thaim an gie it anither shot.',
 'nocookiesfornew' => 'The uiser accoont wisna created, as we couda confirm its source.
@@ -524,16 +524,16 @@ password fer {{SITENAME}} ($4). Ae temporarie password fer uiser "$2" haes been
 Yer temporarie password will expire in {{PLURAL:$5|one day|$5 days}}.
 
 Gif somebodie else made this request, or gif ye hae mindit yer password, an ye nae langer wish tae chynge it, ye can ignore this message an continue uising yer auld password.',
-'noemail' => 'The\'r nae e-mail address recordit for uiser "$1".',
+'noemail' => 'Thaur\'s nae wab-mail address recordit fer uiser "$1".',
 'noemailcreate' => 'Ye need tae provide ae valid wab-mail address.',
 'passwordsent' => 'A new password haes been sent tae the e-mail address registert for "$1". Please log in again efter ye receive it.',
 'blocked-mailpassword' => 'Yer IP address is blockit frae editin, sae it
 canna uise the password recovery function, for tae prevent abuiss.',
 'eauthentsent' => "Ae confirmation wab-mail haes been sent til the speceefied wab-mail address.
-Afore oni ither wab-mail is sent til the accoont, ye'll hae to follae the instructions in the wab-mail, sae as tae confirm that the accoont is reallie yers.",
+Afore oni ither wab-mail is sent til the accoont, ye'll hae tae follae the instructions in the wab-mail, sae as tae confirm that the accoont is reallie yers.",
 'throttled-mailpassword' => 'Ae password reset wab-mail haes awreadie been sent, wiin the laist {{PLURAL:$1|hoor|$1 hoors}}.
 Tae hinder abuiss, yinly the yin password reset wab-mail will be sent per {{PLURAL:$1|hoor|$1 hoors}}.',
-'mailerror' => 'Error sendin mail: $1',
+'mailerror' => 'Mistak sendin mail: $1',
 'acct_creation_throttle_hit' => 'Veesitors tae this wiki uisin yer IP address haev created $1 {{PLURAL:$1|accoont|accoonts}} the day, which is the maist permeettit in that lang.
 Sae veesitors uisin this IP address canna mak ony mair accoonts juist noo.',
 'emailauthenticated' => 'Yer wab-mail address wis confirmed oan $2 at $3.',
@@ -541,17 +541,17 @@ Sae veesitors uisin this IP address canna mak ony mair accoonts juist noo.',
 Nae wab-mail will be sent fer oni o the follaein features.',
 'noemailprefs' => "Nae email address haes been specifee'd, the follaein featurs willna wirk.",
 'emailconfirmlink' => 'Check yer e-mail address',
-'invalidemailaddress' => 'The email address canna be acceptit syne it seems tae be formattit wrang.
-Please enter a weel-formattit address or mak that field tuim.',
+'invalidemailaddress' => 'The wab-mail address canna be acceptit sin it seems tae be formattit wrang.
+Please enter ae weel-formattit address or mak that field tuim.',
 'cannotchangeemail' => 'Accoont wab-mail addresses canna be chynged oan this wiki.',
 'emaildisabled' => 'This site canna send wab-mails.',
 'accountcreated' => 'Accoont creatit',
-'accountcreatedtext' => 'The uiser accoont fer [[{{ns:User}}:$1|$1]] ([[{{ns:User talk}}:$1|talk]]) haes been creatit.',
+'accountcreatedtext' => 'The uiser accoont fer [[{{ns:User}}:$1|$1]] ([[{{ns:User talk}}:$1|tauk]]) haes been cræftit.',
 'createaccount-title' => 'Accoont makin for {{SITENAME}}',
-'createaccount-text' => 'Somebodie creatit aen accoont fer yer wab-mail address oan {{SITENAME}} ($4) named "$2", wi password "$3".
-You should log in and change your password now.
+'createaccount-text' => 'Somebodie cræftit aen accoont fer yer wab-mail address oan {{SITENAME}} ($4) named "$2", wi passwaird "$3".
+Ye shid log in n chynge yer passwaird nou.
 
-Ye can ignore this message, gif this accoont wis creatit bi mistak.',
+Ye can ignore this message, gif this accoont wis cræftit bi mistak.',
 'usernamehasherror' => 'Uisername canna contain hash chairacters',
 'login-throttled' => "Ye'v made ower moni recent login attempts.
 Please wait $1 afore trying again.",
@@ -561,7 +561,7 @@ Please wait $1 afore trying again.",
 'createacct-another-realname-tip' => 'Real name is aen optie.
 Gif ye chuise tae provide it, this will be uised fer giein the uiser attreebution fer their wark.',
 'pt-login' => 'Log in',
-'pt-createaccount' => 'Create accoont',
+'pt-createaccount' => 'Mak accoont',
 'pt-userlogout' => 'Log oot',
 
 # Email sending
@@ -592,7 +592,7 @@ Tae finish loggin in, ye maun set ae new passwaird here:',
 'resetpass-temp-password' => 'Temperie passwaird:',
 'resetpass-abort-generic' => 'Passwaird chynge haes been aborted bi aen extension.',
 'resetpass-expired' => 'Yer passwaird haes expired. Please set ae new passwaird tae log-in.',
-'resetpass-expired-soft' => 'Yer passwaird haes expired, an needs tae be reset. Please chuise ae new passwaird nou, or clap oan cancel tae reset it later.',
+'resetpass-expired-soft' => 'Yer passwaird haes expired n needs tae be reset. Please chuise ae new passwaird nou, or clap oan "{{int:resetpass-submit-cancel}}" tae reset it later.',
 
 # Special:PasswordReset
 'passwordreset' => 'Reset passwaird',
@@ -603,7 +603,7 @@ Tae finish loggin in, ye maun set ae new passwaird here:',
 'passwordreset-emaildisabled' => 'Wab-mail features hae been disabled oan this wiki.',
 'passwordreset-username' => 'Uisername:',
 'passwordreset-capture' => 'View the resultin wab-mail?',
-'passwordreset-capture-help' => 'Gif ye check this box, the wab-mail (wi the temperie passwaird) will be shawn til ye an be sent til the uiser ava.',
+'passwordreset-capture-help' => 'Gif ye check this kist, the wab-mail (wi the temperie passwaird) will be shawn til ye an be sent til the uiser ava.',
 'passwordreset-email' => 'Wab-mail address:',
 'passwordreset-emailtitle' => 'Accoont details oan {{SITENAME}}',
 'passwordreset-emailtext-ip' => "Somebodie (likely ye, fae IP address $1) requested ae reset o yer passwaird fer {{SITENAME}} ($4). The follaein uiser {{PLURAL:$3|accoont is|accoonts ar}}
@@ -656,17 +656,17 @@ Ye shid dae it gif ye accidentally shaired theim wi somebodie or gif yer accoont
 'resettokens-resetbutton' => 'Reset selected tokens.',
 
 # Edit page toolbar
-'bold_sample' => 'Bauld text',
-'bold_tip' => 'Bauld text',
-'italic_sample' => 'Italic text',
-'italic_tip' => 'Italic text',
+'bold_sample' => 'Baud tex',
+'bold_tip' => 'Baud tex',
+'italic_sample' => 'Italic tex',
+'italic_tip' => 'Italic tex',
 'link_sample' => 'Airtin teitle',
 'link_tip' => 'Internal airtin',
 'extlink_sample' => 'http://www.example.com airtin teitle',
 'extlink_tip' => 'Airtin tae an outby steid (mynd the http:// prefix)',
-'headline_sample' => 'Heidline text',
+'headline_sample' => 'Heidline tex',
 'headline_tip' => 'Level 2 heidline',
-'nowiki_sample' => 'Insert non-formattit text here',
+'nowiki_sample' => 'Insert non-formattit tex here',
 'nowiki_tip' => 'Ignore wiki formattin',
 'image_sample' => 'Exemplar.jpg',
 'image_tip' => 'Embeddit eimage',
@@ -678,34 +678,34 @@ Ye shid dae it gif ye accidentally shaired theim wi somebodie or gif yer accoont
 # Edit pages
 'summary' => 'Ootline:',
 'subject' => 'Subject/headline:',
-'minoredit' => 'This is a smaa edit',
+'minoredit' => 'This is ae smaa eidit',
 'watchthis' => 'Leuk ower this page',
 'savearticle' => 'Hain page',
 'preview' => 'Scance',
 'showpreview' => 'Scance ower',
 'showlivepreview' => 'Live leuk ower',
 'showdiff' => 'Shaw chynges',
-'anoneditwarning' => "Ye arna loggit in. Yer IP address will be recordit in this page's edit history.",
+'anoneditwarning' => "<strong>Warnishment:</strong>Ye'r no loggit in. Yer IP address will be recordit in this page's eidit histerie.",
 'anonpreviewwarning' => "<em>Ye'r no loggit in. hainin will record yer IP address in this page's eidit history.</em>",
-'missingsummary' => "'''Mynd:''' Ye hivna gien an edit summary. Gin ye dab on Hain again, yer edit will be haint athoot ane.",
+'missingsummary' => '<strong>Mynd:</strong> Ye\'v no gien aen eidit owerview. Gin ye dab oan "{{int:savearticle}}" again, yer eidit will be haint wioot ane.',
 'missingcommenttext' => 'Please enter a comment ablo.',
-'missingcommentheader' => '<strong>Mynd:</strong> Ye\'v no provided ae subject/headline fer this comment.
-If you clap "{{int:savearticle}}" again, yer edit will be saved wiout yin.',
+'missingcommentheader' => '<strong>Mynd:</strong> Ye\'v no provided ae subject/heidline fer this comment.
+Gif ye clap "{{int:savearticle}}" again, yer eodit will be hained wioot yin.',
 'summary-preview' => 'Ootline leuk ower:',
 'subject-preview' => 'Subject/headline leuk ower:',
 'blockedtitle' => 'Uiser is blockit',
 'blockedtext' => '<strong>Yer uisername or IP address haes been blockit.</strong>
 
-The block wis made bi $1.
+The block wis makit bi $1.
 The raison gieen is <em>$2</em>.
 
-* Stert o block: $8
-* Expiry o block: $6
+* Stairt o block: $8
+* Expirie o block: $6
 * Intended blockee: $7
 
 Ye can contact $1 or anither [[{{MediaWiki:Grouppage-sysop}}|admeenistræter]] tae discuss the block.
 Ye canna uise the "wab-mail this uiser" feature onless ae valid wab-mail address is speceefied in yer [[Special:Preferences|accoont preferences]] an ye\'v no been blockit fae uising it.
-Your current IP address is $3, an the block ID is #$5.
+Your current IP address is $3, n the block ID is #$5.
 Please inclæde aw the abuin details in oni speirins ye mak.',
 'autoblockedtext' => 'Yer IP address haes been autæmaticly blockit cause it wis uised bi anither uiser, wha wis blockit bi $1.
 The raison gieen is:
@@ -727,37 +727,37 @@ Please inclæde aw abuin details in oni speirins ye mak.',
 'confirmedittext' => 'Ye maun confirm yer e-mail address afore editin pages. Please set an validate yer e-mail address throu yer [[Special:Preferences|uiser settins]].',
 'nosuchsectiontitle' => 'Canna find section',
 'nosuchsectiontext' => 'Ye tried tae eidit ae section that disna exist.
-It micht hae been muived or deleted while ye were viewing the page.',
+It micht hae been muived or delytit while ye were viewing the page.',
 'loginreqtitle' => 'Login Requirit!',
 'loginreqlink' => 'log in',
 'loginreqpagetext' => 'Ye maun $1 tae view ither pages.',
 'accmailtitle' => 'Passwaird sent.',
 'accmailtext' => 'Ae randomly generated passwaird fer [[User talk:$1|$1]] haes been sent til $2. It can be chynged oan the <em>[[Special:ChangePassword|chynge passwaird]]</em> page upo loggin in.',
 'newarticle' => '(New)',
-'newarticletext' => "Ye'v follaed an airtin til a page that disna exist yet. Tae create the page, stert typin in the box ablo (see the [[{{MediaWiki:Helppage}}|help page]] for mair info). Gin ye'r here by mistak, juist dab yer brouser's '''back''' button.",
+'newarticletext' => "Ye'v follaed ae link til ae page that disna exist yet. Tae mak the page, stairt typin in the kist ablo (see the [[{{MediaWiki:Helppage}}|heelp page]] fer mair info). Gif ye'r here bi mistak, juist clap yer brouser's '''back''' button.",
 'anontalkpagetext' => "----
-<em>This is the discussion page fer aen anonymous uiser wha's no created aen accoont yet, or wha disna uise it.</em>
-We mauntherefore uise the numerical IP address tae identify him/her.
+<em>This is the discussion page fer aen anonymous uiser wha's no makit aen accoont yet, or wha disna uise it.</em>
+We maun therefore uise the numerical IP address tae identifie him/her.
 Sic aen IP address can be shaired bi several uisers.
-Gif ye'r aen anonymous uiser an feel that irrelevant comments hae been directed at ye, please [[Special:UserLogin/signup|create aen accoont]] or [[Special:UserLogin|log in]] tae avoid future confusion wi ither anonymous uisers.",
-'noarticletext' => 'The\'r nae text on this page the nou. 
-Ye can [[Special:Search/{{PAGENAME}}|rake for this page teitle]] in ither pages,
-<span class="plainlinks">[{{fullurl:{{#Special:Log}}|page={{FULLPAGENAMEE}}}} rake th\' related logs],
- or [{{fullurl:{{FULLPAGENAME}}|action=edit}} edit this page].</span>',
+Gif ye'r aen anonymous uiser an feel that onrelevant comments hae been directed at ye, please [[Special:UserLogin/signup|mak aen accoont]] or [[Special:UserLogin|log in]] tae avoid future confusion wi ither anonymous uisers.",
+'noarticletext' => 'Thaur\'s naw tex oan this page the nou. 
+Ye can [[Special:Search/{{PAGENAME}}|rake fer this page teitle]] in ither pages,
+<span class="plainlinks">[{{fullurl:{{#Special:Log}}|page={{FULLPAGENAMEE}}}} rake the related logs],
+ or [{{fullurl:{{FULLPAGENAME}}|action=edit}} eidit this page].</span>',
 'noarticletext-nopermission' => 'There isna oni tex in this page the nou.
-Ye can [[Special:Search/{{PAGENAME}}|rake fer this page title]] in ither pages, or <span class="plainlinks">[{{fullurl:{{#Special:Log}}|page={{FULLPAGENAMEE}}}} rake the relatit logs]</span>, but ye dina hae permeession tae create this page.',
-'missing-revision' => 'The revision #$1 o the page named "{{PAGENAME}}" disna exist.
+Ye can [[Special:Search/{{PAGENAME}}|rake fer this page title]] in ither pages, or <span class="plainlinks">[{{fullurl:{{#Special:Log}}|page={{FULLPAGENAMEE}}}} rake the relatit logs]</span>, but ye dina hae permeession tae mak this page.',
+'missing-revision' => 'The reveesion #$1 o the page named "{{PAGENAME}}" disna exist.
 
-This is usually caused bi follaein aen ootdated histerie link til ae page that haes been deletit.
-Details can be foond in the [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} deletion log].',
-'userpage-userdoesnotexist' => 'Uiser accoont "<nowiki>$1</nowiki>" hasnae been registerit. Please check gin ye wint tae mak or edit this page.',
+This is usuallie caused bi follaein aen ootdated histerie link til ae page that haes been delytit.
+Details can be foond in the [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} delytion log].',
+'userpage-userdoesnotexist' => 'Uiser accoont "<nowiki>$1</nowiki>" hasnae been registerit. Please check gin ye wint tae mak or eidit this page.',
 'userpage-userdoesnotexist-view' => 'Uiser accoont "$1" isna registered.',
 'blocked-notice-logextract' => 'This uiser is currently blockit.
 The latest block log entry is provided ablow fer reference:',
-'clearyourcache' => "<strong>Tak tent:</strong> Efter hainin, ye micht hae tae bypass yer brouser's cache tae see the chynges.
-* <strong>Firefox / Safari:</strong> Hold <em>Shift</em> while clapin <em>Relaid</em>, or press either <em>Ctrl-F5</em> or <em>Ctrl-R</em> (<em>⌘-R</em> on a Mac)
+'clearyourcache' => "<strong>Tak tent:</strong> Efter hainin, ye micht hae tae bipass yer brouser's cache tae see the chynges.
+* <strong>Firefox / Safari:</strong> Haud <em>Shift</em> while clapin <em>Relaid</em>, or press either <em>Ctrl-F5</em> or <em>Ctrl-R</em> (<em>⌘-R</em> oan ae Mac)
 * <strong>Google Chrome:</strong> Press <em>Ctrl-Shift-R</em> (<em>⌘-Shift-R</em> on a Mac)
-* <strong>Internet Explorer:</strong> Hold <em>Ctrl</em> while clapin <em>Refresh</em>, or press <em>Ctrl-F5</em>
+* <strong>Internet Explorer:</strong> Haud <em>Ctrl</em> while clapin <em>Refresh</em>, or press <em>Ctrl-F5</em>
 * <strong>Opera:</strong> Clear the cache in <em>Tuils → Preferences</em>",
 'usercssyoucanpreview' => '<strong>Tip:</strong> Uise the "{{int:showpreview}}" button tae test yer new CSS afore hainin.',
 'userjsyoucanpreview' => '<strong>Tip:</strong> Uise the "{{int:showpreview}}" button tae test yer new JavaScript afore hainin.',
@@ -768,79 +768,79 @@ It haesna been hained yet!</strong>",
 It's no been hained yet!</strong>",
 'sitejspreview' => "<strong>Mynd that ye'r yinly previewing this JavaScript code.
 It's no been hained yet!</strong>",
-'userinvalidcssjstitle' => "'''Warnin:''' There isnae a skin \"\$1\". Mynd that yer ain .css an .js pages uise a lowercase teetle, e.g. {{ns:user}}:Foo/vector.css instead o {{ns:user}}:Foo/Vector.css.",
+'userinvalidcssjstitle' => '<strong>Warnishment</strong> There isnae ae skin "$1". Mynd that yer ain .css an .js pages uise a lowercase teetle, e.g. {{ns:user}}:Foo/vector.css instead o {{ns:user}}:Foo/Vector.css.',
 'updated' => '(Updatit)',
 'note' => "'''Mynd:'''",
 'previewnote' => '<strong>Mynd that this is yinly ae scænce-ower.</strong>
 Yer chynges hae no been hained yet!',
 'continue-editing' => 'Gae til eiditing area',
-'previewconflict' => 'This scance reflects the text in the upper text editin area like it will kythe gin ye chuise tae save.',
-'session_fail_preview' => "'''Sairy! We culdnae process yer edit acause o a loss o term data.
-Please try again. Gin it disnae wairk still, try loggin oot an loggin in again.'''",
-'session_fail_preview_html' => '<strong>Sairrie! We coudna process yer eidit cause o ae loss o session data.</strong>
-
-<em>Cause {{SITENAME}} haes raw HTML enabled, the preview is hidden aes ae precaution again JavaScript attacks.</em>
-
-<strong>Gif this is ae legitimate eidit attempt, please try again.</strong>
-Gif it still disna wairk, try [[Special:UserLogout|loggin oot]] an loggin back in.',
-'token_suffix_mismatch' => "'''Yer edit haes been rejectit acause yer client made a richt mess o the punctuation characters
-in the edit token. The edit haes been rejectit tae hinder corruption o the page text.
-This whiles happens when ye are uisin a bruken web-based anonymous proxy service.'''",
+'previewconflict' => 'This scance reflects the tex in the upper tex eiditin area like it will kythe gin ye chuise tae hain.',
+'session_fail_preview' => '<strong>Sairy! We culdnae process yer eidit acause o ae loss o term data.</strong>
+Please try again. Gin it disnae wairk still, try [[Secial:UserLogout|login oot]] an loggin in again.',
+'session_fail_preview_html' => "<strong>Sairrie! We coudna process yer eidit cause o ae loss o session data.</strong>
+
+<em>Cause {{SITENAME}} haes raw HTML enabled, the preview is skauk't aes ae precaution again JavaScript attacks.</em>
+
+<strong>Gif this is ae legeetimate eidit attempt, please try again.</strong>
+Gif it still disna wairk, try [[Special:UserLogout|loggin oot]] an loggin back in.",
+'token_suffix_mismatch' => '<strong>Yer eidit haes been rejectit acause yer client made ae richt mess o the punctuation characters in the eidit token.</strong>
+The eidit haes been rejectit tae hinder corruption o the page tex.
+This whiles happens when ye ar uisin ae bruken web-based anonymous proxie service.',
 'edit_form_incomplete' => '<strong>Some pairts o the eidit form didna reach the server; dooble-check that yer eidits ar intact an try again.</strong>',
 'editing' => 'Editin $1',
 'creating' => 'Makin $1',
 'editingsection' => 'Editin $1 (section)',
 'editingcomment' => 'Editin $1 (new section)',
-'editconflict' => 'Edit conflict: $1',
-'explainconflict' => "Some ither body haes chynged this page syne ye stertit editin it.
-The upper text area hauds the page text as it currently exists.
-Yer chynges is shawn in the lower text area.
-Ye'll hae tae merge yer chynges intae the existin text.
-'''Juist''' the text in the upper text area will be hained whan ye press \"{{int:savearticle}}\".",
-'yourtext' => 'Yer text',
+'editconflict' => 'Eidit conflict: $1',
+'explainconflict' => 'Some ither body haes chynged this page syne ye stertit eiditin it.
+The upper tex area hauds the page tex aes it currentlie exeests.
+Yer chynges is shawn in the lower tex area.
+Ye\'ll hae tae merge yer chynges intil the exeestin tex.
+<strong>Juist</strong> the tex in the upper tex area will be hained whan ye press "{{int:savearticle}}".',
+'yourtext' => 'Yer tex',
 'storedversion' => 'Storit version',
-'nonunicodebrowser' => "'''WARNIN: Yer brouser isna unicode compliant.  The'r a wirkaroond tae allou ye tae sauflie edit airticles: non-ASCII characters will kythe in the edit box as hexadecimal codes.'''",
-'editingold' => "'''WARNIN: Ye'r editin an oot-o-date reveision o this page. Gin ye hain it, onie chynges made syne this reveision will be lost.'''",
+'nonunicodebrowser' => "'''Warnishment: Yer brouser isna unicode compliant. Ae warkaroond is in place tae permit ye tae sauflie eidit airticles: no-ASCII chairacters will kythe in the eidit kist aes hexadecimal codes.'''",
+'editingold' => "<strong>Warnishment:</strong> Ye'r eiditin aen oot-o-date reveesion o this page. Gin ye hain it, onie chynges makit sin this reveesion will be lost.",
 'yourdiff' => 'Differs',
-'copyrightwarning' => "Please mynd that aa contreibutions tae {{SITENAME}} is conseidert tae be released unner the $2 (see $1 for details). Gin ye dinna want yer writin tae be editit athoot mercy an redistribute at will, than dinna submit it here.<br /> Forbye thon, ye'r promisin us that ye wrat this yersel, or copied it frae a public domain or siclike free resoorce. '''DINNA SUBMIT COPYRICHTIT WARK ATHOOT PERMEISSION!'''",
-'copyrightwarning2' => "Please mynd that aa contreibutions tae {{SITENAME}} micht be editit, chynged, or remuved bi ither contreibutors.
-Gin ye dinna want yer writin tae be editit athoot mercy and redistribute at will, than dinna submit it here.<br />
-YYe'r promisin us forbye that ye wrat this yersel, or copied it frae a
+'copyrightwarning' => "Please mynd that aa contreebutions til {{SITENAME}} is conseedert tae be released unner the $2 (see $1 for details). Gin ye dinna want yer writin tae be eiditit wioot mercy an redistributed at will, than dinna haun it it here.<br /> Forbye thon, ye'r promisin us that ye wrat this yersel, or copied it frae ae public domain or siclike free resoorce. <strong>DINNA SUBMIT COPIERICHTIT WARK WIOOT PERMEESSION!</strong>",
+'copyrightwarning2' => "Please mynd that aa contreebutions til {{SITENAME}} micht be eiditit, chynged, or remuived bi ither contreebuters.
+Gin ye dinna want yer writin tae be eiditit wioot mercie an redistreebuted at will, than dinna haun it in here.<br />
+Ye'r promisin us forbye that ye wrat this yersel, or copied it frae ae
 public domain or siclike free resoorce (see $1 for details).
-'''DINNA SUBMIT COPYRICHTIT WARK ATHOOT PERMEISSION!'''",
+<strong>DINNA HAUN IN COPIERICHTIT WARK WIOOT PERMEESSION!</strong>",
 'longpageerror' => "<strong>Mistak: The tex ye'v submitted is {{PLURAL:$1|yin kilobyte|$1 kilobytes}} lang, an this is langer nor the maximum o {{PLURAL:$2|yin kilobyte|$2 kilobytes}}.</strong>
 It canna be hained.",
 'readonlywarning' => "<strong>Warnishment: The database haes been lockit fer maintenance, sae ye'll no be able tae hain yer eidits richt nou.</strong>
-You micht wish tae copy an paste yer tex intil ae tex file an hain it fer later.
+Ye micht wish tae cope n paste yer tex intil ae tex file an hain it fer later.
 
 The admeenistræter that lockit it affered this explanation: $1",
-'protectedpagewarning' => '<strong>Warnishment: This page haes been protectit sae that yinly uisers wi admeenistræter privileges can edit it.</strong>
-The latest log entry is provided ablow fer reference:',
+'protectedpagewarning' => '<strong>Warnishment: This page haes been protectit sae that yinly uisers wi admeenistræter preevileges can eidit it.</strong>
+The latest log entrie is provided ablo fer reference:',
 'semiprotectedpagewarning' => '<strong>Note:</strong> This page haes been protected sae that yinly registered uisers can eidit it.
 The latest log entry is provided ablow fer reference:',
-'cascadeprotectedwarning' => "'''Warnin:''' This page haes been lockit sae that only uisers wi sysop richts can edit it, acause it is includit in the followin cascade-protectit {{PLURAL:$1|page|pages}}:",
-'titleprotectedwarning' => '<strong>Warnishment: This page haes been protected sae that [[Special:ListGroupRights|speecific richts]] ar needed tae create it.</strong>
-The latest log entry is provided ablow fer reference:',
-'templatesused' => '{{PLURAL:$1|Template|Templates}} used on this page:',
+'cascadeprotectedwarning' => '<strong>Warnishment:</strong> This page haes been lockit sae that yinlie uisers wi admeenisræter richts can eidit it, acause it is inclædit in the follaein cascade-protectit {{PLURAL:$1|page|pages}}:',
+'titleprotectedwarning' => '<strong>Warnishment: This page haes been protected sae that [[Special:ListGroupRights|speecific richts]] ar needed tae mak it.</strong>
+The laitest log entry is provided ablo fer reference:',
+'templatesused' => '{{PLURAL:$1|Template|Templates}} uised oan this page:',
 'templatesusedpreview' => '{{PLURAL:$1|Template|Templates}} uised in this scænce-ower:',
 'templatesusedsection' => '{{PLURAL:$1|Template|Templates}} uised in this section:',
 'template-protected' => '(protectit)',
 'template-semiprotected' => '(semi-protectit)',
-'hiddencategories' => 'This page is a member of {{PLURAL:$1|1 hidden category|$1 hidden categories}}:',
-'nocreatetext' => '{{SITENAME}} haes restricted the ability tae mak new pages.
-Ye can gae back an edit aen existing page, or [[Special:UserLogin|log in or mak aen accoont]].',
+'hiddencategories' => "This page is ae member o {{PLURAL:$1|1 skauk't categerie|$1 skauk't categeries}}:",
+'nocreatetext' => '{{SITENAME}} haes restricted the abeelitie tae cræft new pages.
+Ye can gae back an eidit aen existin page, or [[Special:UserLogin|log in or mak aen accoont]].',
 'nocreate-loggedin' => 'Ye dinnae hae the richts tae mak new pages.',
 'sectioneditnotsupported-title' => 'Section eiditin isna supported',
 'sectioneditnotsupported-text' => 'Section eiditing isna supported in this page.',
 'permissionserrors' => 'Permission mistak',
 'permissionserrorstext' => 'Ye dinnae hae the richts tae dae that, acause o the followin {{PLURAL:$1|grund|grunds}}:',
-'permissionserrorstext-withaction' => 'Ye dinna hae the richts tae $2, for the follaein {{PLURAL:$1|reason|reasons}}:',
-'recreate-moveddeleted-warn' => "'''Warnin: Ye are makkin a page that haes been deletit.'''
+'permissionserrorstext-withaction' => 'Ye dinna hae the richts tae $2, fer the follaein {{PLURAL:$1|raison|raisons}}:',
+'recreate-moveddeleted-warn' => "'''Warnishment: Ye'r remakin ae page that haes been delytit.'''
 
-Ye shuld check that it is guid tae keep editin this page.
-The deletion and flit log for this page is providit here:",
-'moveddeleted-notice' => 'This page haes bin deletit. 
-The deletion and flit log fur the page are provided below fur reference.',
+Ye shid check that it is guid tae keep eiditin this page.
+The delytion an muiv log fer this page is providit here:",
+'moveddeleted-notice' => 'This page haes bin delytit. 
+The delytion an muiv log fer the page ar provided ablo fer reference.',
 'log-fulllog' => 'View ful log',
 'edit-hook-aborted' => 'Eidit aborted bi huik.
 It gae naw explanation.',
@@ -855,8 +855,8 @@ It awreadie exists.',
 'content-failed-to-parse' => 'Failed tae parse $2 content fer $1 model: $3',
 'invalid-content-data' => 'Onvalid content data',
 'content-not-allowed-here' => '"$1" content isna permited oan the page [[$2]]',
-'editwarning-warning' => 'Leain this page micht cause ye tae lose oni chynges ye\'v made.
-Gif ye\'r loggit in, ye can disable this warning in the "{{int:prefs-editing}}" section o yer preferences.',
+'editwarning-warning' => 'Leain this page micht cause ye tae lose oni chynges that ye\'v makit.
+Gif ye\'r loggit in, ye can disable this warnishment in the "{{int:prefs-editing}}" section o yer preferences.',
 'editpage-notsupportedcontentformat-title' => 'Content format isna supported',
 'editpage-notsupportedcontentformat-text' => 'The content format $1 isna supported bi the content model $2.',
 
@@ -887,29 +887,29 @@ Thir arguments hae been left oot.',
 'converter-manual-rule-error' => 'mistak detected in manual leid conversion rule',
 
 # "Undo" feature
-'undo-success' => 'The edit can be undone. Please check the chynges albo tae check that this is whit ye wint tae dae, an then hain the chynges albo tae be duin undooin the edit.',
+'undo-success' => 'The eidit can be ondun. Please check the chynges albo tae check that this is whit ye wint tae dae, n than hain the chynges albo tae be duin ondaein the eidit.',
 'undo-failure' => 'The edit culdnae be undone acause o conflictin edits inatween.',
 'undo-norev' => 'The eidit coudna be ondone cause it disna exist or wis deletit.',
 'undo-nochange' => 'The edit appears tae hae awready been ondone.',
-'undo-summary' => 'Undo reveision $1 by [[Special:Contributions/$2|$2]] ([[User talk:$2|Talk]])',
-'undo-summary-username-hidden' => 'Ondae revision $1 bi ae hidden uiser',
+'undo-summary' => 'Ondae reveesion $1 bi [[Special:Contributions/$2|$2]] ([[User talk:$2|Tauk]])',
+'undo-summary-username-hidden' => "Ondae reveesion $1 bi ae skauk't uiser",
 
 # Account creation failure
 'cantcreateaccounttitle' => 'Canna mak accoont',
 'cantcreateaccount-text' => "Accoont makkin frae this IP address ('''$1''') haes been blockit by [[User:$3|$3]].
 
 The grund for this, given by $3 is ''$2''",
-'cantcreateaccount-range-text' => "Accoont creation fae IP addresses in the range '''$1''', that inclædes yer IP address ('''$4'''), haes been blockit bi [[User:$3|$3]].
+'cantcreateaccount-range-text' => "Accoont cræftin fae IP addresses in the range '''$1''', that inclædes yer IP address ('''$4'''), haes been blockit bi [[User:$3|$3]].
 
 The raison gien bi $3 is ''$2''",
 
 # History pages
-'viewpagelogs' => 'Leuk at logs for this page',
-'nohistory' => "The'r nae edit history for this page.",
+'viewpagelogs' => 'Leuk at logs fer this page',
+'nohistory' => "Thaur's nae eidit histerie fer this page.",
 'currentrev' => 'Current reveision',
-'currentrev-asof' => 'Latest revision as of $1',
+'currentrev-asof' => 'Latest reveesion aes o $1',
 'revisionasof' => 'Reveision as o $1',
-'revision-info' => 'Revision as o $1 by $2',
+'revision-info' => 'Reveesion aes o $1 bi $2',
 'previousrevision' => '← Aulder reveision',
 'nextrevision' => 'Newer reveision →',
 'currentrevisionlink' => 'see current reveision',
@@ -918,7 +918,8 @@ The raison gien bi $3 is ''$2''",
 'last' => 'hind',
 'page_first' => 'first',
 'page_last' => 'hindermaist',
-'histlegend' => 'Diff selection: mairk the radio boxes o the versions tae compare an press enter or the button at the bottom.<br /> Legend: (cur) = difference frae current version, (last) = difference frae foregaun version, s = smaa edit.',
+'histlegend' => 'Diff selection: Maurk the radio kists o the reveesions tae compare n hit enter or the button at the bottom.<br />
+Legend: <strong>({{int:cur}})</strong> = differance wi laitest reveesion, <strong>({{int:last}})</strong> = differance wi preceedin reveesion, <strong>{{int:minoreditletter}}</strong> = smaa eidit.',
 'history-fieldset-title' => 'Browse history',
 'history-show-deleted' => 'Deletit only',
 'histfirst' => 'auldest',
@@ -927,52 +928,52 @@ The raison gien bi $3 is ''$2''",
 'historyempty' => '(empie)',
 
 # Revision feed
-'history-feed-title' => 'Revision history',
-'history-feed-description' => 'Revision history for this page on the wiki',
+'history-feed-title' => 'Reveesion histerie',
+'history-feed-description' => 'Reveesion histerie fer this page oan the wiki',
 'history-feed-item-nocomment' => '$1 at $2',
-'history-feed-empty' => 'The requestit page disnae exist.
-It micht hae been deletit frae the wiki, or the name micht hae been chynged.
-Try [[Special:Search|rakin on the wiki]] for new pages ye micht be interestit in.',
+'history-feed-empty' => 'The requestit page disnae exeest.
+It micht hae been delytit fae the wiki, or the name micht hae been chynged.
+Try [[Special:Search|rakin oan the wiki]] fer new pages ye micht be interestit in.',
 
 # Revision deletion
 'rev-deleted-comment' => '(eidit summarie remuived)',
 'rev-deleted-user' => '(uisername removit)',
 'rev-deleted-event' => '(log action remuived)',
-'rev-deleted-user-contribs' => '[uisername or IP address remuived - eidit hidden fae contreebutions]',
-'rev-deleted-text-permission' => 'This page revision haes been <strong>deletit</strong>.
-Details can be foond in the [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} deletion log].',
-'rev-deleted-text-unhide' => 'This page revision haes been <strong>deletit</strong>.
-Details can be foond in the [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} deletion log].
-Ye can still [$1 view this revision] gif ye wish tae proceed.',
-'rev-suppressed-text-unhide' => 'This page revision haes been <strong>suppressed</strong>.
+'rev-deleted-user-contribs' => "[uisername or IP address remuived - eidit skauk't fae contreebutions]",
+'rev-deleted-text-permission' => 'This page reveesion haes been <strong>delytit</strong>.
+Details can be foond in the [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} delytion log].',
+'rev-deleted-text-unhide' => 'This page reveesion haes been <strong>delytit</strong>.
+Details can be foond in the [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} delytion log].
+Ye can still [$1 view this reveesion] gif ye wish tae proceed.',
+'rev-suppressed-text-unhide' => 'This page reveesion haes been <strong>suppressed</strong>.
 Details can be foond in the [{{fullurl:{{#Special:Log}}/suppress|page={{FULLPAGENAMEE}}}} suppression log].
-Ye can still [$1 view this revision] gif ye wish tae proceed.',
-'rev-deleted-text-view' => 'This page revision haes been <strong>deletit</strong>.
-You can view it; details can be foond in the [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} deletion log].',
-'rev-suppressed-text-view' => 'This page revision haes been <strong>suppressed</strong>.
+Ye can still [$1 view this reveesion] gif ye wish tae proceed.',
+'rev-deleted-text-view' => 'This page reveesion haes been <strong>delytit</strong>.
+Ye can view it; details can be foond in the [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} delytion log].',
+'rev-suppressed-text-view' => 'This page reveesion haes been <strong>suppressed</strong>.
 Ye can view it; details can be foond in the [{{fullurl:{{#Special:Log}}/suppress|page={{FULLPAGENAMEE}}}} suppression log].',
-'rev-deleted-no-diff' => 'Ye canna view this diff cause yin o the revisions haes been <strong>deletit</strong>.
-Details can be foond in the [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} deletion log].',
+'rev-deleted-no-diff' => 'Ye canna view this diff cause yin o the reveesions haes been <strong>delytit</strong>.
+Details can be foond in the [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} delytion log].',
 'rev-suppressed-no-diff' => 'Ye cannae view this diff cause yin o the revisions haes been <strong>deletit</strong>.',
-'rev-deleted-unhide-diff' => 'Yin o the revisions o this diff haes been <strong>deletit</strong>.
-Details can be foond in the [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} deletion log].
+'rev-deleted-unhide-diff' => 'Yin o the reveesions o this diff haes been <strong>delytit</strong>.
+Details can be foond in the [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} delytion log].
 Ye can still [$1 view this diff] gif ye wish tae proceed.',
-'rev-suppressed-unhide-diff' => 'Yin o the revisions o this diff haes been <strong>suppressed</strong>.
+'rev-suppressed-unhide-diff' => 'Yin o the reveesions o this diff haes been <strong>suppressed</strong>.
 Details can be foond in the [{{fullurl:{{#Special:Log}}/suppress|page={{FULLPAGENAMEE}}}} suppression log].
-Ye can still [$1 view this diff] gif you wish to proceed.',
+Ye can still [$1 view this diff] gif ye wish tee proceed.',
 'rev-suppressed-diff-view' => 'Yin o the revisions o this diff haes been <strong>suppressed</strong>.
 Ye can view this diff; details can be foond in the [{{fullurl:{{#Special:Log}}/suppress|page={{FULLPAGENAMEE}}}} suppression log].',
 'rev-delundel' => 'shaw/scug',
 'rev-showdeleted' => 'shaw',
-'revisiondelete' => 'Delete/undelete revisions',
-'revdelete-nooldid-title' => 'Onvalid target revision',
-'revdelete-nooldid-text' => "Ye'v either no speecified ae target reveesion(s) tae perform this function, the speecified revision disna exist, or ye'r attempting te hide the current reveesion.",
+'revisiondelete' => 'Delyte/ondelyte reveesions',
+'revdelete-nooldid-title' => 'Onvalid target reveesion',
+'revdelete-nooldid-text' => "Ye'v either no speceefied ae target reveesion(s) tae perform this function, the speceefied reveesion disna exeest, or ye'r attemptin tae skauk the current reveesion.",
 'revdelete-no-file' => 'The file speecified disna exist.',
 'revdelete-show-file-confirm' => 'Ar ye sair ye wish tae view ae deletit reveesion o the file "<nowiki>$1</nowiki>" fae $2 at $3?',
 'revdelete-show-file-submit' => 'Ai',
 'revdelete-selected' => '<strong>{{PLURAL:$2|Selected reveesion|Selected reveesions}} o [[:$1]]:</strong>',
-'revdelete-text' => '<strong>Deletit revisions an events will still appear in the page histerie an logs, but pairts o their content will be onaccessible til the public.</strong>
-Ither admeenistraters oan {{SITENAME}} will still be able tae access the hidden content an can ondelete it again through this same interface, onless addeetional restrictions ar set.',
+'revdelete-text' => "<strong>Delytit reveesions an events will still kyth in the page histerie an logs, but pairts o their content will be onaccessible til the public.</strong>
+Ither admeenistraters oan {{SITENAME}} will still be able tae access the skauk't content an can ondelyte it again through this same interface, onless addeetional restreections ar set.",
 'revdelete-confirm' => "Please confirm that ye'r ettlin tae dae this, that ye unnerstaunn the consequences, an that ye'r daein this in accordance wi [[{{MediaWiki:Policy-url}}|the policie]].",
 'revdelete-suppress-text' => 'Suppression shid <strong>yinly</strong> be uised fer the follaein cases:
 * poteentially libeloos information
@@ -980,13 +981,13 @@ Ither admeenistraters oan {{SITENAME}} will still be able tae access the hidden
 *: <em>hame addresses an telephane nummers, national ideentification nummers, etc.</em>',
 'revdelete-legend' => 'Set visibeelitie restreections',
 'revdelete-hide-text' => 'Reveesion tex',
-'revdelete-hide-image' => 'Hide file content.',
-'revdelete-hide-name' => 'Hide aiction an target',
+'revdelete-hide-image' => 'Skauk file content.',
+'revdelete-hide-name' => 'Skauk aiction an target',
 'revdelete-hide-comment' => 'Eidit summarie',
 'revdelete-hide-user' => "Eiditor's uisername/IP address",
 'revdelete-hide-restricted' => 'Suppress data fae admeenistraters aes weel aes ithers',
 'revdelete-radio-same' => '(dinna chynge)',
-'revdelete-radio-set' => 'Hidden',
+'revdelete-radio-set' => "Skauk't",
 'revdelete-radio-unset' => 'Visible',
 'revdelete-suppress' => 'Suppress data fae admeenistraters aes weel aes ithers',
 'revdelete-unsuppress' => 'Remuiv restreections oan restored reveesions',
@@ -1001,8 +1002,8 @@ $1',
 'revdel-restore' => 'change visibility',
 'pagehist' => 'Page history',
 'deletedhist' => 'Deletit histerie',
-'revdelete-hide-current' => 'Mistak hidin the item dated $2, $1: This is the current reveesion.
-It cannna be hidden.',
+'revdelete-hide-current' => "Mistak skaukin the eitem dated $2, $1: This is the current reveesion.
+It cannna be skauk't.",
 'revdelete-show-no-access' => 'Mistak shawin the eitem dated $2, $1: This eitem haes been maurked "restreected".
 Ye dinna hae access til it.',
 'revdelete-modify-no-access' => 'Mistak modifiein the eitem dated $2, $1: This eitem haes been maurked "restreected".
@@ -1019,13 +1020,13 @@ Please check the logs.",
 ** Potentially libelous information',
 'revdelete-otherreason' => 'Ither/addeetional raison:',
 'revdelete-reasonotherlist' => 'Ither raison',
-'revdelete-edit-reasonlist' => 'Eidit delete raisons',
+'revdelete-edit-reasonlist' => 'Eidit delyte raisons',
 'revdelete-offender' => 'Reveesion author:',
 
 # Suppression log
 'suppressionlog' => 'Suppreession log',
-'suppressionlogtext' => 'Ablow is ae leet o deletions an blocks involvin content hidden fae admeenistraters.
-See the [[Special:BlockList|block leet]] fer the leet o currentlie operational bans an blocks.',
+'suppressionlogtext' => "Ablo is ae leet o delytions n blocks involvin content skauk't fae admeenistraters.
+See the [[Special:BlockList|block leet]] fer the leet o currentlie operational bans n blocks.",
 
 # History merging
 'mergehistory' => 'Merge page histeries',
@@ -1059,7 +1060,7 @@ Note that uising the navigâtion links will reset this column.',
 'mergelogpagetext' => 'Ablow is ae leet o the maist recent merges o yin page histerie intil anither.',
 
 # Diffs
-'history-title' => 'Revision histerie o "$1"',
+'history-title' => 'Reveesion histerie o "$1"',
 'difference-title' => 'Difference atween reveesions of "$1"',
 'difference-title-multipage' => 'Difference atween pages "$1" an "$2"',
 'difference-multipage' => '(Difference atween pages)',
@@ -1068,21 +1069,21 @@ Note that uising the navigâtion links will reset this column.',
 'showhideselectedversions' => 'Chynge veesibeelitie o selected reveesions',
 'editundo' => 'undo',
 'diff-empty' => '(Naw difference)',
-'diff-multi-sameuser' => '({{PLURAL:$1|One intermediate revision|$1 intermediate revisions}} bi the same uiser no shown)',
-'diff-multi-otherusers' => '({{PLURAL:$1|One intermediate revision|$1 intermediate revisions}} bi {{PLURAL:$2|one other user|$2 users}} not shown)',
+'diff-multi-sameuser' => '({{PLURAL:$1|yin intermeediate reveesion|$1 intermeediate reveesions}} bi the same uiser no shawn)',
+'diff-multi-otherusers' => '({{PLURAL:$1|yin intermeediate reveesion|$1 intermeediate reveesions}} bi {{PLURAL:$2|yin ither uiser|$2 uisers}} no shawn)',
 'diff-multi-manyusers' => '({{PLURAL:$1|Yin intermeediate reveesion|$1 intermeediate reveesions}} bi mair than $2 {{PLURAL:$2|uiser|uisers}} no shawn)',
-'difference-missing-revision' => '{{PLURAL:$2|Yin reveesion|$2 reveesions}} o this difference ($1) {{PLURAL:$2|was|were}} na fond.
+'difference-missing-revision' => '{{PLURAL:$2|Yin reveesion|$2 reveesions}} o this difference ($1) {{PLURAL:$2|was|were}} no fond.
 
-This is usually caused bi follaein aen ootdated diff link til ae page that haes been deletit.
-Details can be foond in the [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} deletion log].',
+This is usually caused bi follaein aen ootdated diff link til ae page that haes been delytit.
+Details can be foond in the [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} delytion log].',
 
 # Search results
 'searchresults' => 'Rake results',
-'searchresults-title' => 'Rake affcome for "$1"',
+'searchresults-title' => 'Rake affcome fer "$1"',
 'toomanymatches' => 'Ower moni matches were returned, please try ae different speirin',
 'titlematches' => 'Airticle teitle matches',
 'textmatches' => 'Page tex matches',
-'notextmatches' => 'Nae page text matches',
+'notextmatches' => 'Nae page tex matches',
 'prevn' => 'foregaun {{PLURAL:$1|$1}}',
 'nextn' => 'neist {{PLURAL:$1|$1}}',
 'prevn-title' => 'Previous $1 {{PLURAL:$1|ootcome|ootcomes}}',
@@ -1098,8 +1099,8 @@ Details can be foond in the [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENA
 'searchprofile-advanced' => 'Advanced',
 'searchprofile-articles-tooltip' => 'Rake in $1',
 'searchprofile-project-tooltip' => 'Rake in $1',
-'searchprofile-images-tooltip' => 'Rake fur files',
-'searchprofile-everything-tooltip' => 'Rake aw o content (including talk pages)',
+'searchprofile-images-tooltip' => 'Rake fer files',
+'searchprofile-everything-tooltip' => 'Rake aw o content (inclædin tauk pages)',
 'searchprofile-advanced-tooltip' => 'Rake in custom namespaces',
 'search-result-size' => '$1 ({{PLURAL:$2|1 word|$2 words}})',
 'search-result-category-size' => '{{PLURAL:$1|1 member|$1 members}} ({{PLURAL:$2|1 subcategory|$2 subcategories}}, {{PLURAL:$3|1 file|$3 files}})',
@@ -1110,16 +1111,16 @@ Details can be foond in the [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENA
 'search-suggest' => 'Did ye mean: $1',
 'search-interwiki-caption' => "Sister projec's",
 'search-interwiki-default' => "$1 results':",
-'search-interwiki-more' => '(more)',
+'search-interwiki-more' => '(mair)',
 'search-relatedarticle' => 'Relatit',
 'searcheverything-enable' => 'Rake in aw namespaces',
 'searchrelated' => 'related',
 'searchall' => 'aw',
 'showingresults' => "Shawin ablo up tae {{PLURAL:$1|'''1''' result|'''$1''' results}} stertin wi #'''$2'''.",
-'showingresultsinrange' => 'Showin ablow up til {{PLURAL:$1|<strong>1</strong> result|<strong>$1</strong> results}} in range #<strong>$2</strong> to #<strong>$3</strong>.',
+'showingresultsinrange' => 'Shawin ablo up til {{PLURAL:$1|<strong>1</strong> affcome|<strong>$1</strong> affcome}} in range #<strong>$2</strong> til #<strong>$3</strong>.',
 'showingresultsnum' => "Shawin ablo {{PLURAL:$3|'''1''' result|'''$3''' results}} stertin wi #'''$2'''.",
-'showingresultsheader' => "{{PLURAL:$5|Ootcome '''$1''' of '''$3'''|Ootcomes '''$1 - $2''' of '''$3'''}} for '''$4'''",
-'search-nonefound' => "Thare wur na ootcomes matching th' query.",
+'showingresultsheader' => '{{PLURAL:$5|Affcome <strong>$1</strong> o <strong>$3</strong>|Affcomes <strong>$1 - $2</strong> o <strong>$3</strong>}} fer <strong>$4</strong>',
+'search-nonefound' => 'Thaur were naw ootcomes matchin the speiring.',
 'powersearch-legend' => 'Advanced rake',
 'powersearch-ns' => 'Rake in namespaces:',
 'powersearch-redir' => 'Leet redirects',
@@ -1157,7 +1158,7 @@ Details can be foond in the [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENA
 'searchresultshead' => 'Rake result settins',
 'stub-threshold-disabled' => 'Tuckie',
 'recentchangescount' => 'Nummer o eidits tae shaw bi defaut:',
-'prefs-help-watchlist-token2' => 'This is the hidlins key til the wab feed o yer watchleet. Onibodie wha kens this can read yer watchleel, sae dinna share it. Gif ye need to, [[Special:ResetTokens|You ca reset it]].',
+'prefs-help-watchlist-token2' => 'This is the hidlins key til the wab feed o yer watchleet. Onibodie wha kens this can read yer watchleet, sae dinna shair it. Gif ye need to, [[Special:ResetTokens|Ye can reset it]].',
 'savedprefs' => 'Yer preferences haes been hained.',
 'servertime' => 'Server time the nou',
 'guesstimezone' => 'Fill in frae brouser',
@@ -1179,8 +1180,8 @@ Details can be foond in the [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENA
 'badsiglength' => 'Yer nickname is ower lang; it haes tae be $1 {{PLURAL:$1|character|characters}} or less.',
 'email' => 'E-mail',
 'prefs-help-realname' => 'Rael name is optional an gin ye chuise tae provide it this will be uised tae gie ye attreibution for yer wark.',
-'prefs-help-email' => 'E-mail is optional, bit is needed fur password resets, shuid ye forget yer password.',
-'prefs-help-email-others' => 'Ye can chuise tae let ithers contact ye bi wab-mail through ae link on yer uiser or talk page.
+'prefs-help-email' => 'Wab-mail is optional, bit is needed fer passwaird resets, shid ye ferget yer passwaird.',
+'prefs-help-email-others' => 'Ye can chuise tae let ithers contact ye bi wab-mail through ae link oan yer uiser or tauk page.
 Yer wab-mail address isna revealed whan ither uisers contact ye.',
 'prefs-help-email-required' => 'Yer e-mail address is needit.',
 'prefs-diffs' => 'Diffs',
@@ -1188,7 +1189,7 @@ Yer wab-mail address isna revealed whan ither uisers contact ye.',
 # User rights
 'userrights-lookup-user' => 'Manish uiser boorachs',
 'userrights-user-editname' => 'Enter a uisername:',
-'editusergroup' => 'Edit uiser boorach',
+'editusergroup' => 'Eidit uiser boorach',
 'editinguser' => 'Chynging uiser richts o uiser <strong>[[User:$1|$1]]</strong> $2',
 'userrights-groupsmember' => 'Member o:',
 
@@ -1201,17 +1202,17 @@ Yer wab-mail address isna revealed whan ither uisers contact ye.',
 'group-bot-member' => '{{GENDER:$1|bot}}',
 
 # Rights
-'right-delete' => 'Delete pages',
+'right-delete' => 'Delyte pages',
 
 # Special:Log/newusers
-'newuserlogpage' => 'Uiser creation log',
+'newuserlogpage' => 'Uiser cræftin log',
 
 # User rights log
 'rightslog' => 'Uiser richts log',
 'rightslogtext' => 'This is a log o chynges tae uiser richts.',
 
 # Associated actions - in the sentence "You do not have permission to X"
-'action-edit' => 'edit this page',
+'action-edit' => 'eidit this page',
 
 # Recent changes
 'nchanges' => '$1 {{PLURAL:$1|chynge|chynges}}',
@@ -1220,21 +1221,33 @@ Yer wab-mail address isna revealed whan ither uisers contact ye.',
 'recentchanges-summary' => 'Follae the maist recent chynges tae the wiki on this page.',
 'recentchanges-feed-description' => 'Follae the maist recent chynges tae the wiki in this feed.',
 'recentchanges-label-newpage' => 'This edit created a freish page',
-'recentchanges-label-minor' => 'This is a smaa edit',
+'recentchanges-label-minor' => 'This is ae smaa eidit',
 'recentchanges-label-bot' => 'This edit wis performed by a bot',
 'recentchanges-label-unpatrolled' => 'This edit haes nae yet bin patrolled',
-'rcnotefrom' => 'Ablo is the chynges syne <b>$2</b> (up tae <b>$1</b> shawn).',
+'rcnotefrom' => 'Ablo ar the chynges sin <strong>$2</strong> (up til <strong>$1</strong> shawn).',
 'rclistfrom' => 'Shaw new chynges stertin frae $1',
 'rcshowhideminor' => '$1 smaa edits',
+'rcshowhideminor-show' => 'Shaw',
+'rcshowhideminor-hide' => 'Skauk',
 'rcshowhidebots' => '$1 bots',
+'rcshowhidebots-show' => 'Shaw',
+'rcshowhidebots-hide' => 'Skauk',
 'rcshowhideliu' => '$1 registered uisers',
+'rcshowhideliu-show' => 'Shaw',
+'rcshowhideliu-hide' => 'Skauk',
 'rcshowhideanons' => '$1 anonymous uisers',
+'rcshowhideanons-show' => 'Shaw',
+'rcshowhideanons-hide' => 'Skauk',
 'rcshowhidepatr' => '$1 patrolled edits',
+'rcshowhidepatr-show' => 'Shaw',
+'rcshowhidepatr-hide' => 'Skauk',
 'rcshowhidemine' => '$1 ma edits',
+'rcshowhidemine-show' => 'Shaw',
+'rcshowhidemine-hide' => 'Skauk',
 'rclinks' => 'Shaw last $1 chynges in last $2 days<br />$3',
 'diff' => 'diff',
 'hist' => 'hist',
-'hide' => 'Hod',
+'hide' => 'Skauk',
 'show' => 'shaw',
 'minoreditletter' => 's',
 'newpageletter' => 'N',
@@ -1242,17 +1255,17 @@ Yer wab-mail address isna revealed whan ither uisers contact ye.',
 'number_of_watching_users_pageview' => '[$1 watchin {{PLURAL:$1|uiser|uisers}}]',
 'rc_categories_any' => 'Ony',
 'rc-enhanced-expand' => 'Shaw details',
-'rc-enhanced-hide' => 'Hod details',
+'rc-enhanced-hide' => 'Skauk details',
 
 # Recent changes linked
 'recentchangeslinked' => 'Relatit chynges',
 'recentchangeslinked-feed' => 'Relatit chynges',
 'recentchangeslinked-toolbox' => 'Relatit chynges',
-'recentchangeslinked-title' => 'Changes related to "$1"',
-'recentchangeslinked-summary' => "This is a leet o' changes made recently tae pages linked frae a specified page (or tae members o' a specified category).
-Pages on [[Special:Watchlist|your watchleet]] are '''bold'''.",
+'recentchangeslinked-title' => 'Chynges relatit til "$1"',
+'recentchangeslinked-summary' => 'This is ae leet o chynges makit recentlie til pages linked fae ae speceefied page (or til memmers o ae speceefied categerie).
+Pages oan [[Special:Watchlist|yer watchleet]] ar <strong>baud</strong.',
 'recentchangeslinked-page' => 'Page name:',
-'recentchangeslinked-to' => "Shaw changes tae pages linked tae th' given page instead",
+'recentchangeslinked-to' => 'Shaw chynges til pages linked til the gien page instead',
 
 # Upload
 'upload' => 'Uplaid file',
@@ -1260,14 +1273,14 @@ Pages on [[Special:Watchlist|your watchleet]] are '''bold'''.",
 'reuploaddesc' => 'Gang back tae the uplaid form.',
 'uploadnologin' => 'Nae loggit in',
 'uploadnologintext' => 'Please $1 tae uplaid files.',
-'uploaderror' => 'Uplaid error',
-'uploadtext' => 'Uise the form ablow tae uplaid files.
-Tae view or rake previously uplaided files gae til the [[Special:FileList|leet o uplaided files]], (re)uplaids ar loggit in the [[Special:Log/upload|upload log]] ava, deletions in the [[Special:Log/delete|deletion log]].
+'uploaderror' => 'Uplaid mistak',
+'uploadtext' => 'Uise the form ablo tae uplaid files.
+Tae view or rake previooslei uplaided files gang til the [[Special:FileList|leet o uplaided files]], (re)uplaids ar loggit in the [[Special:Log/upload|uplaid log]] ava, delytions in the [[Special:Log/delete|delytion log]].
 
 Tae inclæde ae file in ae page, uise ae link in yin o the follaein forms:
 * <strong><code><nowiki>[[</nowiki>{{ns:file}}<nowiki>:File.jpg]]</nowiki></code></strong> tae uise the ful version o the file
-* <strong><code><nowiki>[[</nowiki>{{ns:file}}<nowiki>:File.png|200px|thumb|left|alt text]]</nowiki></code></strong> tae uise ae 200 pixel wide rendition in ae box in the left margin wi "alt tex" aes description
-* <strong><code><nowiki>[[</nowiki>{{ns:media}}<nowiki>:File.ogg]]</nowiki></code></strong> fer linkin directly til the file wiout displaying the file',
+* <strong><code><nowiki>[[</nowiki>{{ns:file}}<nowiki>:File.png|200px|thumb|left|alt text]]</nowiki></code></strong> tae uise ae 200 pixel wide rendition in ae kist in the cair margin wi "alt tex" aes descreeption
+* <strong><code><nowiki>[[</nowiki>{{ns:media}}<nowiki>:File.ogg]]</nowiki></code></strong> fer linkin directlie til the file wioot displeyin the file',
 'uploadlog' => 'uplaid log',
 'uploadlogpage' => 'Uplaid log',
 'uploadlogpagetext' => 'Ablo is a leet o the maist recent file uplaids.',
@@ -1275,7 +1288,7 @@ Tae inclæde ae file in ae page, uise ae link in yin o the follaein forms:
 'filestatus' => 'Copyricht status:',
 'filesource' => 'Soorce:',
 'uploadedfiles' => 'Uplaidit files',
-'ignorewarning' => 'Ignore warnin an hain file oniewey.',
+'ignorewarning' => 'Ignore warnishment n hain file oniewey.',
 'ignorewarnings' => 'Ignore ony warnins',
 'illegalfilename' => 'The filename "$1" haes characters that isna alloud in page teitles. Please rename the file an gie uplaidin it anither shot.',
 'badfilename' => 'Eimage name haes been chynged tae "$1".',
@@ -1288,11 +1301,12 @@ Gif ye still wish tae uplaid yer file, please gae back an uise ae new name.
 'fileexists-shared-forbidden' => 'Ae file wi this name awreadie exists in the shaired file repository.
 Gif ye still wish tae uplaid yer file, please gae back an uise ae new name.
 [[File:$1|thumb|center|$1]]',
-'uploadwarning' => 'Uplaid warnin',
+'uploadwarning' => 'Uplaid warnishment',
 'savefile' => 'Hain file',
 'uploadedimage' => 'uplaidit "$1"',
 'uploaddisabled' => 'Sorry, uplaidin is disabled.',
 'uploadscripted' => 'This file hauds HTML or script code that micht be wrang interpretit bi a wab brouser.',
+'uploadscriptednamespace' => 'This SVG file contains aen illegal namespace "$1"',
 'uploadvirus' => 'The file hauds a virus! Details: $1',
 'sourcefilename' => 'Soorce filename:',
 
@@ -1310,21 +1324,21 @@ Gif ye still wish tae uplaid yer file, please gae back an uise ae new name.
 # File description page
 'file-anchor-link' => 'Eimage',
 'filehist' => 'File history',
-'filehist-help' => "Click oan a date/time tae view th' file as it appeared at that time.",
-'filehist-deleteone' => 'delete',
+'filehist-help' => 'Clap oan ae date/time tae view the file aes it appeared at that time.',
+'filehist-deleteone' => 'delyte',
 'filehist-revert' => 'revert',
 'filehist-current' => 'current',
 'filehist-datetime' => 'Date/Time',
 'filehist-thumb' => 'Thumbnail',
-'filehist-thumbtext' => 'Thumbnail for version as of $1',
+'filehist-thumbtext' => 'Thumbnail fer version aes o $1',
 'filehist-user' => 'Uiser',
 'filehist-dimensions' => 'Dimensions',
 'filehist-comment' => 'Comment',
 'imagelinks' => 'File uisage',
 'linkstoimage' => 'The follaein {{PLURAL:$1|page airts|$1 pages airt}} tae this file:',
 'nolinkstoimage' => "The'r nae pages airts tae this eimage.",
-'sharedupload-desc-here' => "This file is frae $1 and may be used bi other projects.
-Th' description oan tis [$2 file description page] thare is shown below.",
+'sharedupload-desc-here' => 'This file is frae $1 an micht be uised bi ither projects.
+The descreeption oan its [$2 file descreeption page] thaur is shawn ablo.',
 
 # File reversion
 'filerevert' => 'Revert $1',
@@ -1332,7 +1346,7 @@ Th' description oan tis [$2 file description page] thare is shown below.",
 'filerevert-submit' => 'Revert',
 
 # File deletion
-'filedelete-submit' => 'Delete',
+'filedelete-submit' => 'Delyte',
 
 # MIME search
 'mimetype' => 'MIME type:',
@@ -1347,12 +1361,12 @@ Th' description oan tis [$2 file description page] thare is shown below.",
 'randompage' => 'Wale page allevolie',
 
 # Statistics
-'statistics' => 'Statistics',
-'statistics-header-pages' => 'Page statistics',
-'statistics-header-edits' => 'Edit statistics',
-'statistics-header-views' => 'View statistics',
-'statistics-header-users' => 'Uiser statistics',
-'statistics-header-hooks' => 'Ither statistics',
+'statistics' => 'Stateestics',
+'statistics-header-pages' => 'Page stateestics',
+'statistics-header-edits' => 'Eidit stateestics',
+'statistics-header-views' => 'View stateestics',
+'statistics-header-users' => 'Uiser stateestics',
+'statistics-header-hooks' => 'Ither stateestics',
 'statistics-pages' => 'Pages',
 
 'doubleredirects' => 'Dooble reguidals',
@@ -1362,8 +1376,8 @@ Ilka rou contains airtins til the first and seicont redirect, aes weel aes the t
 
 'brokenredirects' => 'Brucken reguidals',
 'brokenredirectstext' => 'The folling redirects link til non-existent pages:',
-'brokenredirects-edit' => 'edit',
-'brokenredirects-delete' => 'delete',
+'brokenredirects-edit' => 'eidit',
+'brokenredirects-delete' => 'delyte',
 
 'withoutinterwiki' => 'Pages athoot leid links',
 'withoutinterwiki-legend' => 'Prefix',
@@ -1387,10 +1401,10 @@ Ilka rou contains airtins til the first and seicont redirect, aes weel aes the t
 'mostcategories' => 'Airticles wi the maist categories',
 'mostimages' => 'Maist uised eimages',
 'mostrevisions' => 'Maist revised airticles',
-'prefixindex' => 'All pages with prefix',
+'prefixindex' => 'Aw pages wi prefix',
 'longpages' => 'Lang pages',
 'deadendpages' => 'Deid-end pages',
-'protectedpages-summary' => 'This page leets existing pages that are nou protectit. Fer a leet o titles that are protectit fae creation, see [[{{#special:ProtectedTitles}}]].',
+'protectedpages-summary' => 'This page leets existin pages that ar nou protectit. Fer a leet o titles that ar protectit fae cræftin, see [[{{#special:ProtectedTitles}}]].',
 'protectedpages-timestamp' => 'Timestamp.',
 'protectedpages-page' => 'Page.',
 'protectedpages-expiry' => 'Dies',
@@ -1399,9 +1413,9 @@ Ilka rou contains airtins til the first and seicont redirect, aes weel aes the t
 'protectedpages-reason' => 'Raison',
 'protectedpages-unknown-timestamp' => "Onken't",
 'protectedpages-unknown-performer' => "Onken't user",
-'protectedtitles-summary' => 'This page leets titles that are nou protectit fae creation. Fer a leet of exeesting pages that are protectit, see [[{{#special:ProtectedPages}}]].',
+'protectedtitles-summary' => 'This page leets titles that ar nou protectit fae cræftin. Fer a leet of exeesting pages that ar protectit, see [[{{#special:ProtectedPages}}]].',
 'listusers' => 'Uiser leet',
-'usercreated' => '{{GENDER:$3|Created}} on $1 at $2',
+'usercreated' => '{{GENDER:$3|Cræftit}} oan $1 at $2',
 'newpages' => 'New pages',
 'newpages-username' => 'Uisername:',
 'ancientpages' => 'Auldest pages',
@@ -1417,7 +1431,7 @@ Please note that ither wab sites micht airt til ae file wi ae direct URL, an sae
 
 # Book sources
 'booksources' => 'Beuk sources',
-'booksources-search-legend' => 'Search fur book sources',
+'booksources-search-legend' => 'Rake fer buik soorces',
 'booksources-go' => 'Gang',
 
 # Special:Log
@@ -1477,7 +1491,7 @@ See [[Special:WantedCategories|wanted categories]] ava.',
 'watchlist' => 'Ma watchleet',
 'mywatchlist' => 'Ma watchleet',
 'watchlistfor2' => 'For $1 $2',
-'nowatchlist' => 'Ye hivna onie eitems on yer watchleet.',
+'nowatchlist' => "Ye'v nae eitems oan yer watchleet.",
 'watchnologin' => 'Nae loggit in',
 'watchnologintext' => 'Ye maun be [[Special:UserLogin|loggit in]] tae modify yer watchleet.',
 'addedwatchtext' => 'The page "[[:$1]]" haes been added til yer [[Special:Watchlist|watchleet]].
@@ -1487,7 +1501,7 @@ Future chynges til this page an its associated tauk page will be leeted there.',
 'watchthispage' => 'Leuk ower this page',
 'unwatch' => 'Unwatch',
 'notanarticle' => 'No a content page',
-'watchlist-details' => '{{PLURAL:$1|$1 page|$1 pages}} on yer watchleet, no countin talk pages.',
+'watchlist-details' => '{{PLURAL:$1|$1 page|$1 pages}} oan yer watchleet, no coontin tauk pages.',
 'watchlistcontains' => 'Yer watchleet contains $1 {{PLURAL:$1|page|pages}}.',
 'iteminvalidname' => "Trouble wi eitem '$1', invalid name...",
 'wlnote2' => 'Ablow ar the chynges in the hainmaist {{PLURAL:$1|hour|<strong>$1</strong> hours}}, as of $3, $2.',
@@ -1499,44 +1513,45 @@ Future chynges til this page an its associated tauk page will be leeted there.',
 'unwatching' => 'Unwatchin...',
 
 'enotif_reset' => 'Merk aa pages visitit',
-'enotif_lastvisited' => 'Hae a leuk at $1 for aa chynges sin yer last visit.',
+'enotif_lastvisited' => 'Hae ae leuk at $1 fer aa chynges sin yer laist veesit.',
 'created' => 'creatit',
 'changed' => 'chynged',
 
 # Delete
-'deletepage' => 'Delete page',
+'deletepage' => 'Delyte page',
 'excontent' => "content wis: '$1'",
 'excontentauthor' => "content wis: '$1' (an the ae contreibutor wis '[[Special:Contributions/$2|$2]]')",
 'exbeforeblank' => "content afore blankin wis: '$1'",
 'exblank' => 'page wis tuim',
-'delete-confirm' => 'Delete "$1"',
-'delete-legend' => 'Delete',
-'historywarning' => "<strong>Warnishment:</strong> The page ye'r aboot tae delete haes ae histerie wi approximately $1 {{PLURAL:$1|revision|revisions}}:",
+'delete-confirm' => 'Delyte "$1"',
+'delete-legend' => 'Delyte',
+'historywarning' => "<strong>Warnishment:</strong> The page ye'r aboot tae delete haes ae histerie wi approximatelie $1 {{PLURAL:$1|reveesion|reveesions}}:",
 'confirmdeletetext' => "Ye'r aboot tae permanently delete a page or eimage alang wi aa its history frae the database.
 Please confirm that ye intend tae dae this, that ye unnerstaun the consequences,
 an that ye'r daein this in accord wi [[{{MediaWiki:Policy-url}}]].",
 'actioncomplete' => 'Action duin',
 'actionfailed' => 'Action failed',
-'deletedtext' => '"$1" haes been delete. See $2 for a record o recent deletions.',
-'dellogpage' => 'Deletion log',
+'deletedtext' => '"$1" haes been delytit. See $2 fer ae record o recent delytions.',
+'dellogpage' => 'Delytion log',
 'dellogpagetext' => 'Ablo is a leet o the maist recent deletions.',
-'deletionlog' => 'deletion log',
+'deletionlog' => 'delytion log',
 'reverted' => 'Revertit tae aulder reveision',
 'deletecomment' => 'Raeson:',
 'deletereasonotherlist' => 'Ither raeson',
+'deleting-backlinks-warning' => "'''Warnishment:''' ither pages link til or transclude the page ye'r aboot tae delyte.",
 
 # Rollback
 'rollback' => 'Row back edits',
 'rollback_short' => 'Rowback',
 'rollbacklink' => 'rowback',
 'rollbackfailed' => 'Rowback failed',
-'cantrollback' => 'Canna revert edit; last contreibutor is the ae author o this page.',
+'cantrollback' => 'Canna revert eidit; laist contreebuter is the ae auther o this page.',
 'alreadyrolled' => 'Canna rollback laist eidit o [[:$1]] bi [[User:$2|$2]] ([[User talk:$2|tauk]]{{int:pipe-separater}}[[Special:Contributions/$2|{{int:contribslink}}]]);
 some ither bodie haes eidited or rolled back the page awreadie.
 
 The laist eidit til the page wis bi [[User:$3|$3]] ([[User talk:$3|tauk]]{{int:pipe-separater}}[[Special:Contributions/$3|{{int:contribslink}}]]).',
 'editcomment' => "The eidit summarie wis: \"''\$1''\".",
-'revertpage' => 'Reverted eidits bi [[Special:Contributions/$2|$2]] ([[User talk:$2|tauk]]) til laist revision bi [[User:$1|$1]]',
+'revertpage' => 'Reverted eidits bi [[Special:Contributions/$2|$2]] ([[User talk:$2|tauk]]) til laist reveesion bi [[User:$1|$1]]',
 
 # Protect
 'protectlogpage' => 'Fend log',
@@ -1557,32 +1572,31 @@ See the [[Special:ProtectedPages|protected pages leet]] fer the leet o currently
 'protect-expiry-options' => '1 hoor:1 hour,1 day:1 day,1 week:1 week,2 weeks:2 weeks,1 month:1 month,3 months:3 months,6 months:6 months,1 year:1 year,eenfinite:infinite',
 
 # Restrictions (nouns)
-'restriction-edit' => 'Edit',
+'restriction-edit' => 'Eidit',
 'restriction-move' => 'Flit',
 'restriction-create' => 'Mak',
 'restriction-upload' => 'Uplaid',
 
 # Undelete
-'undelete' => 'Restore delete page',
-'undeletepage' => 'View an restore delete pages',
-'viewdeletedpage' => 'View delete pages',
+'undelete' => 'Restore delyte page',
+'undeletepage' => 'View an restore delytit pages',
+'viewdeletedpage' => 'View delyte pages',
 'undeletepagetext' => 'The follaeing {{PLURAL:$1|page haes been deletit but is|$1 pages hae been deletit but ar}} still in the archive an can be restored.
 The archive micht be cleaned oot nou an then.',
 'undeleteextrahelp' => "In order tae restore the page's entire histerie, lea aw checkboxes onselected an clap on <strong><em>{{int:undeletebtn}}</em></strong>.
 Tae perform ae selective restoration, check the boxes corresponding til the revisions tae be restored, an clap on <strong><em>{{int:undeletebtn}}</em></strong>.",
 'undeletehistory' => 'Gif ye restore the page, aw revisions will be restored til the histerie.
-Gif ae new page wi the same name haes been creatit syne the deletion, the restored revisions will appear in the prior histerie.',
-'undeletehistorynoadmin' => 'This airticle haes been delete. The raeson for deletion is
-shawn in the summary ablo, alang wi parteeculars o the uisers that haed editit this page
-afore it wis delete. The actual text o thir deletit reveisions is available tae admeenistrators juist.',
+Gif ae new page wi the same name haes been makit sin the delytion, the restored reveesions will kyth in the prior histerie.',
+'undeletehistorynoadmin' => 'This airticle haes been delytit. The raeson fer delytion is
+shawn in the owerview ablo, alang wi parteeculars o the uisers that haed eiditit this page afore it wis delytit. The actual tex o thir delytit reveesions is available tae admeenistraters juist.',
 'undeletelink' => 'view/restore',
 'undeleteviewlink' => 'view',
 'undeletedrevisions' => '{{PLURAL:$1|1 reveision|$1 reveisions}} restored',
-'cannotundelete' => 'Ondelete failed:
+'cannotundelete' => 'Ondelyte failed:
 $1',
-'undeletedpage' => '<strong>$1 has been restored</strong>
+'undeletedpage' => '<strong>$1 haes been restored</strong>
 
-Consult the [[Special:Log/delete|deletion log]] fer ae record o recent deletions an restorations.',
+Consult the [[Special:Log/delete|delytion log]] fer ae record o recent delytions an restorâtions.',
 
 # Namespace form on various pages
 'namespace' => 'Namespace:',
@@ -1603,15 +1617,16 @@ Consult the [[Special:Log/delete|deletion log]] fer ae record o recent deletions
 'sp-contributions-blocklog' => 'block log',
 'sp-contributions-uploads' => 'uploads',
 'sp-contributions-logs' => 'logs',
-'sp-contributions-talk' => 'talk',
-'sp-contributions-search' => 'Rake fur contreibutions',
+'sp-contributions-talk' => 'tauk',
+'sp-contributions-search' => 'Rake fer contreebutions',
 'sp-contributions-username' => 'IP address or uisername:',
 'sp-contributions-toponly' => 'Ainlie shaw edits that are latest revisions',
+'sp-contributions-newonly' => 'Yinlie shaw eidits that ar page cræftins',
 'sp-contributions-submit' => 'Rake',
 
 # What links here
 'whatlinkshere' => 'Whit airts tae here',
-'whatlinkshere-title' => 'Pages that link to "$1"',
+'whatlinkshere-title' => 'Pages that link til "$1"',
 'whatlinkshere-page' => 'Page:',
 'linkshere' => "The follaein pages airts tae '''[[:$1]]''':",
 'nolinkshere' => "Nae pages airt tae '''[[:$1]]'''.",
@@ -1651,7 +1666,7 @@ tae an afore-blockit IP address or uisername.',
 'unblocklink' => 'unblock',
 'change-blocklink' => 'chynge block',
 'contribslink' => 'contreibs',
-'autoblocker' => 'Autaematically blockit syne yer IP address haes been uised recently bi "[[User:$1|$1]]". The raeson gien fer $1\'s block is "$2"',
+'autoblocker' => 'Autaematicallie blockit sin yer IP address haes been uised recentlie bi "[[User:$1|$1]]". The raeson gien fer $1\'s block is "$2"',
 'blocklogpage' => 'Block log',
 'blocklogentry' => 'blockit [[$1]] wi an expiry time o $2 $3',
 'blocklogtext' => 'This is ae log o uiser blockin an onblockin actions. Autaematically blockit IP addresses isna leetit. See the [[Special:BlockList|block leet]] fer the leet o bans and blocks oan nou.',
@@ -1665,11 +1680,11 @@ Ye canna mak aen accoont.',
 
 # Developer tools
 'unlockdb' => 'Lowse database',
-'lockdbtext' => "Lockin the database will suspend the abeility o aa uisers tae edit pages, chynge thair preferences, edit thair watchleets, an ither things requirin chynges in the database. Please confirm that this is whit ye intend tae dae, an that ye'll unlock the database whan yer maintenance is duin.",
-'unlockdbtext' => 'Lowsin the database will gie back the abeility for aa uisers tae edit pages, chynge their preferences, edit their watchleets, an ither things needin chynges in the database. Please confirm that this is whit ye ettle tae dae.',
+'lockdbtext' => "Lockin the database will suspend the abeelitie o aa uisers tae eidit pages, chynge thair preeferences, eidit thair watchleets, an ither things requirin chynges in the database. Please confirm that this is whit ye'r etlin tae dae, an that ye'll lowse the database whan yer maintenance is duin.",
+'unlockdbtext' => 'Lowsin the database will gie back the abeelitie fer aa uisers tae eidit pages, chynge their preeferences, eidit their watchleets, an ither things needin chynges in the database. Please confirm that this is whit ye ettle tae dae.',
 'lockconfirm' => 'Aye, A raellie want tae lock the database.',
 'unlockconfirm' => 'Aye, A raelly want tae lowse the database.',
-'locknoconfirm' => 'Ye didna tick the confirmation box.',
+'locknoconfirm' => 'Ye didna tick the confirmâtion kist.',
 'lockdbsuccesssub' => 'Database lock fine',
 'unlockdbsuccesssub' => 'Database lowsed',
 'lockdbsuccesstext' => 'The database haes been lockit. <br />Mynd an tak the lock aff efter yer maintenance is feinisht.',
@@ -1678,151 +1693,152 @@ Ye canna mak aen accoont.',
 
 # Move page
 'move-page-legend' => 'Flit page',
-'movepagetext' => "Uisin the form ablow will rename ae page, muiving aw o its histerie til the new name.
-The auld title will become ae redirect page til the new title.
-Ye can update redirects that point til the original title autaematicly.
-Gif ye chuis no tae, be sair tae check fer [[Special:DoubleRedirects|double]] or [[Special:BrokenRedirects|broken redirects]].
-Ye'r responsible fer making sair that airtins continue tae pynt til whaur they'r supposed to gae.
-
-Note that the page will <strong>no</strong> be muived gif there is awready ae page at the new title, onless the latter is ae redirect an has nae past edit history.
-This means that ye can rename ae page back til whaur it wis renamed fae gif ye mak ae mistak, an ye canna o'erwrite aen existing page.
-
-<strong>Warning!</strong>
-This can be ae drastic an onexpected chynge fer ae popular page;
-please be sair ye unnerstaun the consequences o this afore proceeding.",
-'movepagetext-noredirectfixer' => "Uising the form ablow will rename ae page, muiving aw o its histerie til the new name.
-The auld title will become ae redirect page til the new title.
-Be sair tae check fer [[Special:DoubleRedirects|double]] or [[Special:BrokenRedirects|broken redirects]].
-Ye'r responsible fer making sair that airtins continue tae pynt whaur thay'r supposed to gae.
-
-Note that the page will <strong>no</strong> be muived gif there's awready ae page at the new title, onless it is tuim an has naw past edit history.
-This means that you can rename a page back to whaur it wis renamed fae gif ye mak ae mistak, an ye canna o'erwrite an existin page.
-
-<strong>Warnin!</strong>
-This can be ae drastic an onexpectit chynge fer ae popular page;
-please be sair ye unnerstaun the consequences of this afore proceedin.",
-'movepagetalktext' => 'The associated talk page will be autaematically muived alang wi it <strong>onless:</strong>
-*A no-tuim talk page awreadie exists unner the new name, or
-*You oncheck the box ablow.
-
-In thae cases, ye will hae tae muiv or merge the page manually gif ye sae desire.',
+'movepagetext' => "Uisin the form ablo will rename ae page, muivin aw o its histerie til the new name.
+The auld title will become ae reguidal page til the new title.
+Ye can update reguidals that point til the oreeginal title autaematiclie.
+Gif ye chuis no tae, be sair tae check fer [[Special:DoubleRedirects|dooble]] or [[Special:BrokenRedirects|broken reguidals]].
+Ye'r responsible fer makin sair that airtins continue tae pynt til whaur they'r supposed to gae.
+
+Note that the page will <strong>no</strong> be muived gif there is awreadie ae page at the new title, onless the latter is ae reguidal n haes nae past eidit histerie.
+This means that ye can rename ae page back til whaur it wis renamed fae gif ye mak ae mistak, n ye canna owerwrite aen exeestin page.
+
+<strong>Warnishment!</strong>
+This can be ae drastic n onexpected chynge fer ae popular page;
+please be sair ye unnerstaun the consequences o this afore proceedin.",
+'movepagetext-noredirectfixer' => "Uising the form ablo will rename ae page, muivin aw o its histerie til the new name.
+The auld title will become ae reguidal page til the new title.
+Be sair tae check fer [[Special:DoubleRedirects|dooble]] or [[Special:BrokenRedirects|broken reguidals]].
+Ye'r responsible fer makin sair that airtins continue tae pynt whaur thay'r supposed tae gae.
+
+Tak tent that the page will <strong>no</strong> be muived gif thaur's awreadie ae page at the new title, onless it is tuim an haes naw past eidit histerie.
+This means that ye can rename ae page back til whaur it wis renamed fae gif ye mak ae mistak, an ye canna owerwrite an existin page.
+
+<strong>Warnishment!</strong>
+This can be ae drastic n onexpectit chynge fer ae popular page;
+please be sair ye unnerstaun the consequences o this afore preceedin.",
+'movepagetalktext' => 'The associated tauk page will be autaematiclie muived alang wi it <strong>onless:</strong>
+*A no-tuim tauk page awreadie exeests unner the new name, or
+*Ye oncheck the kist ablo.
+
+In thae cases, ye will hae tae muiv or merge the page manuallie gif ye sae desire.',
 'movearticle' => 'Flit page:',
-'moveuserpage-warning' => "<strong>Warning:</strong> Ye'r aboot tae muiv ae uiser page. Please note that yinly the page will be muivd and the uiser will <em>no</em> be renamed.",
+'moveuserpage-warning' => "<strong>Warnishment:</strong> Ye'r aboot tae muiv ae uiser page. Please tak tent that yinly the page will be muivd n the uiser will <em>no</em> be renamed.",
 'movenologintext' => 'Ye maun be a registert uiser an [[Special:UserLogin|loggit in]] tae flit a page.',
 'newtitle' => 'Tae new teitle',
 'movepagebtn' => 'Flit page',
 'pagemovedsub' => 'Flittin succeedit',
 'movepage-moved' => '<strong>"$1" has been muived til "$2"</strong>',
 'articleexists' => "A page o that name aareadies exists, or the name ye'v waled isna guid. Please wale anither name.",
-'movetalk' => 'Muiv associated talk page',
+'movetalk' => 'Muiv associated tauk page',
 'movelogpage' => 'Flit log',
 'movelogpagetext' => "A leet o pages that's flitted is ablo.",
 'movereason' => 'Raeson:',
 'revertmove' => 'revert',
-'delete_and_move' => 'Delete an flit',
-'delete_and_move_text' => '==Deletion caad for==
+'delete_and_move' => 'Delete an muiv',
+'delete_and_move_text' => '==Delytion caad fer==
 
-The destination airticle "[[:$1]]" aareadies exists. Div ye want tae delete it for tae mak wey for the flittin?',
-'delete_and_move_confirm' => 'Aye, delete the page',
+The destination airticle "[[:$1]]" aareadies exists. Div ye want tae delyte it fer tae mak wey fer the muiv?',
+'delete_and_move_confirm' => 'Ai, delyte the page',
 'delete_and_move_reason' => 'Deletit fer tae mak way fer muiv fae "[[$1]]"',
 'selfmove' => 'Ootgaun an incomin teitles is the same; canna flit a page ower itsel.',
-'protectedpagemovewarning' => '<strong>Warning:</strong> This page has been protected sae that yinly uisers wi administrater preevileges can muiv it.
-The hainmaist log entry is provided ablow fer reference:',
+'protectedpagemovewarning' => '<strong>Warnishment:</strong> This page haes been protected sae that yinly uisers wi admeenistrater preevileges can muiv it.
+The latest log entry is provided ablo fer reference:',
 'semiprotectedpagemovewarning' => '<strong>Note:</strong> This page has been protected sae that yinly registered uisers can muiv it.
 The hainmaist log entry is provided ablow fer reference:',
 
 # Export
 'export' => 'Export pages',
-'exporttext' => 'Ye can export the text an editin history o a parteicular page or set o pages wappit in some XML. In the futur, this micht can be importit intae anither wiki runnin MediaWiki saftware, altho the\'r nae support for this featur in the current version.
+'exporttext' => 'Ye can export the tex an eiditin histerie o ae parteecular page or set o pages wrapped in some XML.
+This can be imported intil anither wiki uisin MediaWiki bi waa o the [[Special:Import|import page]].
 
-Tae export airticle pages, enter the teitles in the text box ablo, ae teitle tae ilka line, an wale whither ye want the current version alang wi aa auld versions, wi the page history lines, or the current version juist, wi wittins anent the last edit.
+Tae export pages, enter the titles in the tex kist ablo, yin title per line, an select whether ye want the current reveesion aes weel aes aw auld reveesions, wi the page histerie lines, or the current reveesion wi the info aneat the laist eidit.
 
-In the saicont case ye can uise an airtin forbye, for exemplar [[{{#Special:Export}}/{{MediaWiki:Mainpage}}]] for the airticle "[[{{MediaWiki:Mainpage}}]]".',
-'exportcuronly' => 'Include juist the current revision, no the fou history',
+In the latter case ye can ava uise ae link, fer example [[{{#Special:Export}}/{{MediaWiki:Mainpage}}]] fer the page "[[{{MediaWiki:Mainpage}}]]".',
+'exportcuronly' => 'Inclæde juist the current reveesion, no the ful histerie',
 'exportnohistory' => '----
 <strong>Note:</strong> Exporting the ful histerie o pages through this form has been disabled caus o performance raisons.',
 
 # Namespace 8 related
 'allmessages' => 'Aa seestem messages',
 'allmessagesname' => 'Name',
-'allmessagesdefault' => 'Defaut text',
-'allmessagescurrent' => 'Text the nou',
+'allmessagesdefault' => 'Defaut message tex',
+'allmessagescurrent' => 'Message tex the nou',
 'allmessagestext' => 'This is ae leet o system messages available in the MediaWiki namespace.
 Please visit [https://www.mediawiki.org/wiki/Localisation MediaWiki Localisation] an [//translatewiki.net translatewiki.net] gif ye wish tae contreebute til the generic MediaWiki localisation.',
 'allmessagesnotsupportedDB' => "'''{{ns:special}}:AllMessages''' nae supportit acause '''\$wgUseDatabaseMessages''' is aff.",
-'allmessages-filter-translate' => "O'erset",
+'allmessages-filter-translate' => 'Owerset',
 
 # Thumbnails
 'thumbnail-more' => 'Eik',
 'filemissing' => 'File missin',
-'thumbnail_error' => 'Error creating thumbnail: $1',
-'thumbnail_image-failure-limit' => "There hae been o'er mony recent failed attempts ($1 or more) tae render this thumbnail. Please try again later.",
+'thumbnail_error' => 'Mistak makin thummnail: $1',
+'thumbnail_image-failure-limit' => 'There hae been ower moni recent failed attempts ($1 or mair) tae render this thumbnail. Please try again later.',
 
 # Special:Import
 'importtext' => 'Please export the file fae the soorce wiki uising the [[Special:Export|export utility]].
 Hain it til yer computer an uplaid it here.',
-'importnotext' => 'Tuim or nae text',
+'importnotext' => 'Tuim or nae tex',
 'importsuccess' => 'Importit fine!',
-'importhistoryconflict' => 'Conflictin history revision exists (micht hae importit this page afore)',
+'importhistoryconflict' => 'Conflictin histerie reveesion exeests (micht hae importit this page afore)',
 'importnosources' => 'Nae transwiki import soorces haes been defined an direct history uplaids is disabled.',
 'import-nonewrevisions' => 'Nae revisions imported (aw were either awready present, or skipped cause o errors).',
-'import-error-bad-location' => 'Revision $2 uising content model $3 canna be stored on "$1" on this wiki, syn that model isna supported on that page.',
+'import-error-bad-location' => 'Reveesion $2 uisin content model $3 canna be stored oan "$1" oan this wiki, syn that model isna supported oan that page.',
 
 # Tooltip help for the actions
 'tooltip-pt-userpage' => 'Yer uiser page',
-'tooltip-pt-mytalk' => 'Yer talk page',
+'tooltip-pt-mytalk' => 'Yer tauk page',
 'tooltip-pt-preferences' => 'Ma preferences',
-'tooltip-pt-watchlist' => "Th' leet o' pages yer monitoring fur changes",
+'tooltip-pt-watchlist' => "Ae leet o pages ye'r moniterin fer chynges",
 'tooltip-pt-mycontris' => 'Leet o yer contreibutions',
 'tooltip-pt-login' => "It's a guid idea tae log i, but ye dinna hae tae.",
 'tooltip-pt-logout' => 'Log oot',
-'tooltip-ca-talk' => "Discussion aboot th' content page",
-'tooltip-ca-edit' => "Ye kin edit this page. Please uise th' preview button afore saving",
+'tooltip-ca-talk' => 'Discussion aneat the content page',
+'tooltip-ca-edit' => 'Ye can eidit this page. Please uise the preview button afore Hainin',
 'tooltip-ca-addsection' => 'Start a new section',
 'tooltip-ca-viewsource' => 'This page is protectit.
-You ken view its source',
+Ye can view its soorce',
 'tooltip-ca-history' => "Bygane revisions o' this page",
 'tooltip-ca-protect' => 'Fend this page',
-'tooltip-ca-delete' => 'Delete this page',
+'tooltip-ca-delete' => 'Delyte this page',
 'tooltip-ca-move' => 'Flit this page',
 'tooltip-ca-watch' => 'Add this page tae yer watchleet',
 'tooltip-ca-unwatch' => 'Remove this page frum yer watchleet',
 'tooltip-search' => 'Rake {{SITENAME}}',
-'tooltip-search-go' => "Gang tae a page wi' this exact name if exists",
-'tooltip-search-fulltext' => "Search th' pages fur this text",
+'tooltip-search-go' => 'Gang til ae page wi this exact name gif exists',
+'tooltip-search-fulltext' => 'Rake the pages fer this tex',
 'tooltip-p-logo' => 'Gang tae the Main Page',
 'tooltip-n-mainpage' => 'Gang tae the Main Page',
 'tooltip-n-mainpage-description' => 'Gang tae the Main Page',
-'tooltip-n-portal' => "Aboot th' project, whit ye kin dae, whaur tae fin' things",
+'tooltip-n-portal' => 'Aneat the project, whit ye can dae, whaur tae fynd things',
 'tooltip-n-currentevents' => "Fin' background speirins oan current events",
 'tooltip-n-recentchanges' => 'The leet o recent chynges in the wiki',
-'tooltip-n-randompage' => 'Load a random page',
-'tooltip-n-help' => "Th' steid tae fin' oot",
+'tooltip-n-randompage' => 'Laid ae random page',
+'tooltip-n-help' => 'The steid tae fynd oot',
 'tooltip-t-whatlinkshere' => "List o' a' wiki pages that link 'ere",
 'tooltip-t-recentchangeslinked' => 'Recent changes in pages linked frae this page',
-'tooltip-feed-atom' => 'Atom feed fur this page',
+'tooltip-feed-atom' => 'Atom feed fer this page',
 'tooltip-t-contributions' => "View this uiser's contreibutions",
-'tooltip-t-emailuser' => 'Send an e-mail to this uiser',
+'tooltip-t-emailuser' => 'Send ae wab-mail til this uiser',
 'tooltip-t-upload' => 'Uplaid files',
 'tooltip-t-specialpages' => 'Leet o byordinar pages',
 'tooltip-t-print' => "Printable version o' this page",
-'tooltip-t-permalink' => "Permanent link tae this revision o' th' page",
+'tooltip-t-permalink' => 'Permanent link til this reveesion o the page',
 'tooltip-ca-nstab-main' => 'Leuk at content page',
 'tooltip-ca-nstab-user' => 'View the uiser page',
-'tooltip-ca-nstab-special' => "This is a byordinar page, ye cannae edit th' page itself",
+'tooltip-ca-nstab-special' => "This is ae byordinair page, ye cannae eidit th' page itsel",
 'tooltip-ca-nstab-project' => 'View the project page',
 'tooltip-ca-nstab-image' => 'View the file page',
 'tooltip-ca-nstab-template' => 'View the template',
-'tooltip-ca-nstab-category' => "View th' category page",
+'tooltip-ca-nstab-category' => 'View the categerie page',
 'tooltip-minoredit' => 'Mairk this as a smaa edit',
 'tooltip-save' => 'Hain yer chynges',
 'tooltip-preview' => 'Scance ower yer chynges, please uise this afore hainin!',
-'tooltip-diff' => 'Shaw the chynges that you made tae the text.',
+'tooltip-diff' => 'Shaw the chynges that ye makit til the tex.',
 'tooltip-compareselectedversions' => 'See the differs atween the twa selectit versions o this page.',
 'tooltip-watch' => 'Add this page tae yer watchleet',
-'tooltip-rollback' => '"Rowback" reverts edit(s) tae this page o\' th\' lest contributor in yin click',
-'tooltip-undo' => "\"Undo\" reverts this edit 'n' opens th' edit form in preview mode. It allows adding a reason in th' summary.",
-'tooltip-summary' => 'Enter a short summary',
+'tooltip-rollback' => '"Rowback" reverts eidit(s) til this page o th\' laist contreebuter in yin clap',
+'tooltip-undo' => '"Ondae" reverts this eidit n apens the eidit form in luikower mode. It permits addin ae raison in the owerview.',
+'tooltip-summary' => 'Enter ae short owerview',
 
 # Metadata
 'notacceptable' => 'The wiki server canna provide data in a format yer client can read.',
@@ -1830,15 +1846,15 @@ You ken view its source',
 # Attribution
 'anonymous' => 'Nameless {{PLURAL:$1|uiser|uisers}} o {{SITENAME}}',
 'siteuser' => '{{SITENAME}} uiser $1',
-'othercontribs' => 'Based on wark bi $1.',
+'othercontribs' => 'Based oan wark bi $1.',
 'others' => 'ithers',
 'siteusers' => '{{SITENAME}} {{PLURAL:$2|uiser|uisers}} $1',
-'nocredits' => "The'r nae credit info available for this page.",
+'nocredits' => "Thaur's nae creedit info available fer this page.",
 
 # Spam protection
 'spamprotectiontext' => 'The tex ye wished tae save wis blockit bi the spam filter.
 This is maistlikly caused bi aen airtin til ae blaickleeted external site.',
-'spamprotectionmatch' => 'The follaein text is whit triggered wir spam filter: $1',
+'spamprotectionmatch' => 'The follaein tex is whit triggered wir spam filter: $1',
 'simpleantispam-label' => 'Anti-spam check.
 Dae <strong>NO</strong> ful this in!',
 
@@ -1846,18 +1862,18 @@ Dae <strong>NO</strong> ful this in!',
 'markaspatrolleddiff' => 'Merk as patrolled',
 'markaspatrolledtext' => 'Merk this airticle as patrolled',
 'markedaspatrolled' => 'Merkit as patrolled',
-'markedaspatrolledtext' => 'The selected revision o [[:$1]] haes been maurked aes patrolled.',
+'markedaspatrolledtext' => 'The selected reveesion o [[:$1]] haes been maurked aes patrolled.',
 'rcpatroldisabledtext' => 'The Recent Changes Patrol feature is disabled the nou.',
 
 # Image deletion
-'deletedrevision' => 'Deletit auld revision $1.',
+'deletedrevision' => 'Delytit auld reveesion $1.',
 
 # Browsing diffs
-'previousdiff' => '← Aulder edit',
-'nextdiff' => 'Newer edit →',
+'previousdiff' => '← Aulder eidit',
+'nextdiff' => 'Newer eidit →',
 
 # Media information
-'mediawarning' => '<strong>Warning:</strong> This file type micht contain maleecious code.
+'mediawarning' => '<strong>Warnishment:</strong> This file type micht contain maleecious code.
 Bi executing it, yer system micht be compromised.',
 'imagemaxsize' => 'Eimage size limit:<br /><em>(fer file description pages)</em>',
 'file-info-size' => '$1 × $2 pixels, file size: $3, MIME type: $4',
@@ -1875,27 +1891,27 @@ Bi executing it, yer system micht be compromised.',
 'bydate' => 'bi date',
 
 # Bad image list
-'bad_image_list' => "Th' format is as follows:
+'bad_image_list' => 'The format is aes follaes:
 
-Ainlie list items (lines starting wi' *) are considered. Th' foremaist link oan a line mist be a link tae a ill image. Ony subsequent links oan th' same line are considered tae be exceptions, i,e., pages whaur th' image kin occur inline.",
+Ainlie leet items (lines stairtin wi *) ar considered. The foremaist link oan ae line maun be ae link til aen ill file. Oni subsequent links oan the same line ar considered tae be exceptions, i,e., pages whaur the eimage can occur inline.',
 
 # Metadata
 'metadata' => 'Metadata',
-'metadata-help' => "This file contains additional speirins, likelie added frae th' digital camera or scanner used tae create or digitize it. 
-If th' file haes bin modified frae tis original state, some details kin nae fully reflect th' modified file.",
-'metadata-fields' => "Image metadata fields listed in this message wull be included oan image page display whin th' metadata buird is collapsed. Others wull be hidden by default. 
-*mak
+'metadata-help' => 'This file contains addeetional speirins, likelie added frae the deegital camera or scanner uised tae mak or deegitize it. 
+Gif the file haes bin modified frae its oreeginal state, some details micht no fullie reflect the modified file.',
+'metadata-fields' => "Image metadata fields leeted in this message wull be inclæded oan eimage page displey whan the metadata buird is collaps't. Ithers wull be skauk't bi defaut. 
+* mak
 * model
-* datetimeoriginal
+* datetimeoreeginal
 * exposuretime
-* fnumber
-* isospeedratings
+* fnummer
+* isospeedratins
 * focallength
-* artist
-* copyricht
-* imagedescription
+* airtist
+* copiericht
+* eimagedescreeption
 * gpslatitude
-* gpslongitude
+* gpslangitude
 * gpsaltitude",
 
 # Exif tags
@@ -1927,7 +1943,7 @@ Please check yer wab-mail address fer onvalid chairacters.
 
 Mailer returned: $1',
 'confirmemail_invalid' => 'Confirmation code nae guid. The code haes mibbe expired.',
-'confirmemail_needlogin' => 'Ye maun $1 for tae confirm yer email address.',
+'confirmemail_needlogin' => 'Please $1 fer tae confirm yer wab-mail address.',
 'confirmemail_success' => 'Yer e-mail address haes been confirmed. Ye can nou log in an enjoy the wiki.',
 'confirmemail_loggedin' => 'Yer e-mail address haes noo been confirmed.',
 'confirmemail_body' => 'Somebodie, maist likely ye, fae IP address $1,
@@ -1946,10 +1962,10 @@ $5
 This confirmation code will expire oan $4.',
 
 # Delete conflict
-'deletedwhileediting' => '<strong>Warning:</strong> This page wis deletit efter ye sterted editing!',
-'confirmrecreate' => 'Uiser [[User:$1|$1]] ([[User talk:$1|talk]]) deleted this page efter ye started eiditing wi raison:
+'deletedwhileediting' => '<strong>Warnishment:</strong> This page wis delytit efter ye stairted eiditin!',
+'confirmrecreate' => 'Uiser [[User:$1|$1]] ([[User talk:$1|tauk]]) delytit this page efter ye stairted eiditin wi raison:
 : <em>$2</em>
-Please confirm that ye really want te recreate this page.',
+Please confirm that ye reallie want tae recræft this page.',
 
 # action=purge
 'confirm_purge_button' => 'Aye',
@@ -1971,8 +1987,8 @@ Please confirm that ye really want te recreate this page.',
 
 # Watchlist editing tools
 'watchlisttools-view' => 'View relevant changes',
-'watchlisttools-edit' => 'View an edit watchleet',
-'watchlisttools-raw' => 'Edit raw watchleet',
+'watchlisttools-edit' => 'View aen eidit watchleet',
+'watchlisttools-raw' => 'Eidit raw watchleet',
 
 # Core parser functions
 'duplicate-defaultsort' => '\'\'\'Wairnin:\'\'\' Default sort key "$2" overrides earlier default sort key "$1".',
@@ -1990,19 +2006,19 @@ Please confirm that ye really want te recreate this page.',
 'specialpages-group-pages' => 'leet o pages',
 
 # External image whitelist
-'external_image_whitelist' => ' #Leave this line exactly as it is<pre>
-#Put regular expression fragments (just the part that goes between the //) below
-#These will be matched with the URLs of external (hotlinked) images
-#Those that match will be displayed as images, otherwise only a link to the image will be shown
-#Lines beginning with # are treated as comments
-#This is case-insensitive
+'external_image_whitelist' => ' #Lea this line exactlie aes it is<pre>
+#Put regulair expression fragments (juist the pairt that gaes atween the //) ablo
+#Thir will be matched wi the URLs o external (hotlinked) eimages
+#Thae that match will be displeyed aes eimages, itherwise yinlie ae link til the eimage will be shawn
+#Lines beginnin wi # ar treated aes comments
+#This is case-onsensiteeve
 
-#Put all regex fragments above this line. Leave this line exactly as it is</pre>',
+#Put aw regex fragments abuin this line. Lea this line exactlie aes it is</pre>',
 
 # Special:Tags
 'tag-filter' => '[[Special:Tags|Tag]] filter:',
 'tag-filter-submit' => 'Filter',
-'tags-edit' => 'edit',
+'tags-edit' => 'eidit',
 
 # HTML forms
 'htmlform-selectorother-other' => 'Ither',
index 08d6bab..e216380 100644 (file)
@@ -1568,11 +1568,23 @@ HTML ටැගයන් පිරික්සන්න.',
 'rcnotefrom' => "'''$2''' න් පසු සිදුවී ඇති වෙනස්කම් මෙහි පහත දැක්වේ ('''$1''' ක ප්‍රමාණයක උපරිමයක් පෙන්වා ඇත).",
 'rclistfrom' => '$1 සිට බලපැවැත්වෙන මෑත වෙනස්වීම් පෙන්වන්න',
 'rcshowhideminor' => 'සුළු සංස්කරණ $1',
+'rcshowhideminor-show' => 'පෙන්වන්න',
+'rcshowhideminor-hide' => 'සඟවන්න',
 'rcshowhidebots' => 'රොබෝ $1',
+'rcshowhidebots-show' => 'පෙන්වන්න',
+'rcshowhidebots-hide' => 'සඟවන්න',
 'rcshowhideliu' => 'ලේඛනගත පරිශීලකයෝ $1',
+'rcshowhideliu-show' => 'පෙන්වන්න',
+'rcshowhideliu-hide' => 'සඟවන්න',
 'rcshowhideanons' => 'නිර්නාමික පරිශීලකයන් $1',
+'rcshowhideanons-show' => 'පෙන්වන්න',
+'rcshowhideanons-hide' => 'සඟවන්න',
 'rcshowhidepatr' => 'පරික්‍ෂා කර බැලූ සංස්කරණයන් $1',
+'rcshowhidepatr-show' => 'පෙන්වන්න',
+'rcshowhidepatr-hide' => 'සඟවන්න',
 'rcshowhidemine' => 'මගේ සංස්කරණයන් $1',
+'rcshowhidemine-show' => 'පෙන්වන්න',
+'rcshowhidemine-hide' => 'සඟවන්න',
 'rclinks' => 'අවසන් දින $2 තුලදී සිදුවී ඇති අවසන් වෙනස්වීම් $1 පෙන්නුම් කරන්න<br />$3',
 'diff' => 'වෙනස',
 'hist' => 'ඉති',
index 9130076..e138234 100644 (file)
@@ -769,7 +769,7 @@ Morda ste že uspešno spremenili geslo ali pa ste zahtevali novo začasno geslo
 'resetpass-temp-password' => 'Začasno geslo:',
 'resetpass-abort-generic' => 'Razširitev je prekinila spremembo gesla.',
 'resetpass-expired' => 'Vaše geslo je poteklo. Prosimo, nastavite novo geslo za prijavo.',
-'resetpass-expired-soft' => 'Vaše geslo je poteklo in ga morate ponastaviti. Prosimo, izberite novo geslo zdaj ali kliknite Prekliči, da ga ponastavite pozneje.',
+'resetpass-expired-soft' => 'Vaše geslo je poteklo in ga morate ponastaviti. Prosimo, izberite novo geslo zdaj ali kliknite »{{int:resetpass-submit-cancel}}«, da ga ponastavite pozneje.',
 
 # Special:PasswordReset
 'passwordreset' => 'Ponastavitev gesla',
@@ -1625,14 +1625,26 @@ Ko vas drugi uporabniki kontaktirajo, jim vašega e-poštnega naslova ne bomo ra
 'recentchanges-label-plusminus' => 'uporabnik je velikost strani spremenil za tolikšno število bajtov',
 'recentchanges-legend-heading' => "'''Legenda:'''",
 'recentchanges-legend-newpage' => '(glej tudi [[Special:NewPages|seznam novih strani]])',
-'rcnotefrom' => "Navedene so spremembe od '''$2''' dalje (prikazujem jih do '''$1''').",
+'rcnotefrom' => 'Navedene so spremembe od <strong>$2</strong> dalje (prikazujem jih do <strong>$1</strong>).',
 'rclistfrom' => 'Prikaži spremembe od $1 naprej',
 'rcshowhideminor' => '$1 manjša urejanja',
+'rcshowhideminor-show' => 'Prikaži',
+'rcshowhideminor-hide' => 'Skrij',
 'rcshowhidebots' => '$1 bote',
+'rcshowhidebots-show' => 'Prikaži',
+'rcshowhidebots-hide' => 'Skrij',
 'rcshowhideliu' => '$1 registrirane uporabnike',
+'rcshowhideliu-show' => 'Prikaži',
+'rcshowhideliu-hide' => 'Skrij',
 'rcshowhideanons' => '$1 brezimne uporabnike',
+'rcshowhideanons-show' => 'Prikaži',
+'rcshowhideanons-hide' => 'Skrij',
 'rcshowhidepatr' => '$1 pregledana urejanja',
+'rcshowhidepatr-show' => 'Prikaži',
+'rcshowhidepatr-hide' => 'Skrij',
 'rcshowhidemine' => '$1 moja urejanja',
+'rcshowhidemine-show' => 'Prikaži',
+'rcshowhidemine-hide' => 'Skrij',
 'rclinks' => 'Prikaži zadnjih $1 sprememb v zadnjih $2 dneh<br />$3',
 'diff' => 'prim',
 'hist' => 'zgod',
@@ -1764,6 +1776,8 @@ Poprosite koga, ki ima možnost ogleda podatkov zatrtih datotek, da preveri polo
 'php-uploaddisabledtext' => 'Nalaganje datotek je onemogočeno v PHP.
 Prosimo preverite file_uploads nastavitev.',
 'uploadscripted' => 'Datoteka vsebuje HTML- ali skriptno kodo, ki bi jo lahko brskalnik razlagal napačno.',
+'uploadscriptednamespace' => 'Datoteka SVG vsebuje nedovoljen imenski prostor »$1«',
+'uploadinvalidxml' => 'XML v naloženi datoteki ne moremo razčleniti.',
 'uploadvirus' => 'Datoteka vsebuje virus!
 Podrobnosti: $1',
 'uploadjava' => 'Datoteka je datoteka ZIP, ki vsebuje javansko datoteko .class.
@@ -2608,6 +2622,7 @@ Najnovejši vnos v dnevniku blokad je naveden spodaj:',
 'sp-contributions-search' => 'Išči prispevke',
 'sp-contributions-username' => 'IP-naslov ali uporabniško ime:',
 'sp-contributions-toponly' => 'Prikaži samo vrhnje redakcije',
+'sp-contributions-newonly' => 'Prikaži samo urejanja, ki so ustvarila nove strani',
 'sp-contributions-submit' => 'Išči',
 
 # What links here
@@ -4138,6 +4153,4 @@ Pravzaprav razširi skoraj vse v dvojnih zavitih oklepajih.',
 'expand_templates_generate_rawhtml' => 'Prikaži surovi HTML',
 'expand_templates_preview' => 'Predogled',
 
-# Unknown messages
-'uploadinvalidxml' => 'XML v naloženi datoteki ne moremo razčleniti.',
 );
index d9375c9..e4c82b0 100644 (file)
@@ -7,6 +7,7 @@
  * @ingroup Language
  * @file
  *
+ * @author Amire80
  * @author Andejkendej
  * @author Cradel
  * @author Dashohoxha
@@ -1526,7 +1527,7 @@ Kjo informatë është publike.',
 'rc_categories_any' => 'Të gjitha',
 'rc-change-size-new' => '$1 {{PLURAL:$1|bajt|bajtë}} pas ndryshimit',
 'newsectionsummary' => '/* $1 */ seksion i ri',
-'rc-enhanced-expand' => 'Trego detajet (kërkon JavaScript)',
+'rc-enhanced-expand' => 'Trego detajet',
 'rc-enhanced-hide' => 'Fshih detajet',
 'rc-old-title' => 'fillimisht i krijuar si "$1"',
 
@@ -2401,7 +2402,7 @@ $1',
 'mycontris' => 'Kontributet',
 'contribsub2' => 'Për $1 ($2)',
 'nocontribs' => 'Nuk ka asnjë ndryshim që përputhet me këto kritere.',
-'uctop' => ' (sipër)',
+'uctop' => '(aktual)',
 'month' => 'Nga muaji (dhe më herët):',
 'year' => 'Nga viti (dhe më herët):',
 
index 0f0bb95..7492d73 100644 (file)
@@ -940,6 +940,9 @@ $2',
 'suspicious-userlogout' => 'Ваш захтев за одјаву је одбијен јер је послат од стране неисправног прегледача или посредника.',
 'createacct-another-realname-tip' => 'Право име није обавезно.
 Ако изаберете да га унесете, оно ће бити коришћено за приписивање вашег рада.',
+'pt-login' => 'Пријави ме',
+'pt-createaccount' => 'Отвори налог',
+'pt-userlogout' => 'Одјави ме',
 
 # Email sending
 'php-mail-error-unknown' => 'Непозната грешка у функцији PHP mail().',
@@ -963,8 +966,13 @@ $2',
 'resetpass-submit-cancel' => 'Откажи',
 'resetpass-wrong-oldpass' => 'Неисправна привремена или текућа лозинка.
 Можда сте већ променили лозинку или сте затражили нову привремену лозинку.',
+'resetpass-recycled' => 'Унели сте садашњу лозинку, да би сте ресетовали лозинку морате унети нову.',
+'resetpass-temp-emailed' => 'Пријавили сте се са привременим кодом из е-поште.
+Да бисте завршили пријављивање морате поставити нову лозинку овде:',
 'resetpass-temp-password' => 'Привремена лозинка:',
 'resetpass-abort-generic' => 'Промену лозинке је спречио додатак.',
+'resetpass-expired' => 'Ваша лозинка је истекла. Поставите нову лозинку да бисте се пријавили.',
+'resetpass-expired-soft' => 'Ваша лозинка је истекла и морате поставити нову. Поставите нову лозинку или кликните откажи да је поставите касније.',
 
 # Special:PasswordReset
 'passwordreset' => 'Обнављање лозинке',
@@ -1792,11 +1800,23 @@ $1",
 'rcnotefrom' => 'Испод су измене од <b>$3; $4</b> (до <b>$1</b> измена).',
 'rclistfrom' => 'Прикажи нове измене почев од $1',
 'rcshowhideminor' => '$1 мање измене',
+'rcshowhideminor-show' => 'Прикажи',
+'rcshowhideminor-hide' => 'Сакриј',
 'rcshowhidebots' => '$1 ботове',
+'rcshowhidebots-show' => 'Прикажи',
+'rcshowhidebots-hide' => 'Сакриј',
 'rcshowhideliu' => '$1 пријављене кориснике',
+'rcshowhideliu-show' => 'Прикажи',
+'rcshowhideliu-hide' => 'Сакриј',
 'rcshowhideanons' => '$1 анонимне кориснике',
+'rcshowhideanons-show' => 'Прикажи',
+'rcshowhideanons-hide' => 'Сакриј',
 'rcshowhidepatr' => '$1 патролиране измене',
+'rcshowhidepatr-show' => 'Прикажи',
+'rcshowhidepatr-hide' => 'Сакриј',
 'rcshowhidemine' => '$1 моје измене',
+'rcshowhidemine-show' => 'Прикажи',
+'rcshowhidemine-hide' => 'Сакриј',
 'rclinks' => 'Прикажи последњих $1 измена {{PLURAL:$2|претходни дан|у последња $2 дана|у последњих $2 дана}}<br />$3',
 'diff' => 'разл',
 'hist' => 'ист',
@@ -1930,6 +1950,7 @@ $1",
 'php-uploaddisabledtext' => 'Слање датотека је онемогућено у PHP-у.
 Проверите поставке file_uploads.',
 'uploadscripted' => 'Датотека садржи HTML или скриптни код који може бити погрешно протумачен од стране прегледача.',
+'uploadscriptednamespace' => 'Ова SVG датотека садржи погрешан именски простор „$1“',
 'uploadvirus' => 'Датотека садржи вирус!
 Детаљи: $1',
 'uploadjava' => 'Датотека је формата ZIP који садржи јава .class елемент.
@@ -2745,7 +2766,7 @@ $1',
 'contributions-title' => 'Доприноси {{GENDER:$1|корисника|кориснице}} $1',
 'mycontris' => 'Доприноси',
 'contribsub2' => 'За {{GENDER:$3|$1}} ($2)',
-'nocontribs' => 'Ð\98змене ÐºÐ¾Ñ\98е Ð¾Ð´Ð³Ð¾Ð²Ð°Ñ\80аÑ\98Ñ\83 Ð¾Ð²Ð¸Ð¼ Ñ\83Ñ\81ловима Ð½Ð¸Ñ\81Ñ\83 Ð¿Ñ\80онаÑ\92ене.',
+'nocontribs' => 'Ð\9dема Ð¸Ð·Ð¼ÐµÐ½Ð° ÐºÐ¾Ñ\98е Ð¾Ð´Ð³Ð¾Ð²Ð°Ñ\80аÑ\98Ñ\83 Ð½Ð°Ð²ÐµÐ´ÐµÐ½Ð¸Ð¼ ÐºÑ\80иÑ\82еÑ\80иÑ\98Ñ\83мима.',
 'uctop' => '(последња)',
 'month' => 'од месеца (и раније):',
 'year' => 'од године (и раније):',
@@ -2765,6 +2786,7 @@ $1',
 'sp-contributions-search' => 'Претрага доприноса',
 'sp-contributions-username' => 'ИП адреса или корисничко име:',
 'sp-contributions-toponly' => 'Прикажи само најновије измене',
+'sp-contributions-newonly' => 'Прикажи само измене којима су креиране нове странице',
 'sp-contributions-submit' => 'Претражи',
 
 # What links here
@@ -3062,6 +3084,7 @@ $1',
 'allmessages-prefix' => 'Филтрирај по префиксу:',
 'allmessages-language' => 'Језик:',
 'allmessages-filter-submit' => 'Иди',
+'allmessages-filter-translate' => 'Преведи',
 
 # Thumbnails
 'thumbnail-more' => 'Повећај',
index 3aa4fcd..e6a37f5 100644 (file)
@@ -2602,7 +2602,7 @@ $1',
 'contributions-title' => 'Doprinosi {{GENDER:$1|korisnika|korisnice}} $1',
 'mycontris' => 'Doprinosi',
 'contribsub2' => 'Za {{GENDER:$3|$1}} ($2)',
-'nocontribs' => 'Izmene koje odgovaraju ovim uslovima nisu pronađene.',
+'nocontribs' => 'Nema izmena koje odgovaraju navedenim kriterijumima.',
 'uctop' => '(poslednja)',
 'month' => 'od meseca (i ranije):',
 'year' => 'od godine (i ranije):',
@@ -2919,6 +2919,7 @@ Posetite [https://www.mediawiki.org/wiki/Localisation Medijaviki lokalizaciju] i
 'allmessages-prefix' => 'Filtriraj po prefiksu:',
 'allmessages-language' => 'Jezik:',
 'allmessages-filter-submit' => 'Idi',
+'allmessages-filter-translate' => 'Prevedi',
 
 # Thumbnails
 'thumbnail-more' => 'Povećaj',
index 94430e3..c710c70 100644 (file)
@@ -1753,11 +1753,23 @@ Om du väljer att ange ditt riktiga namn, kommer det att användas för att till
 'rcnotefrom' => "Nedan visas ändringar sedan '''$2''' (upp till '''$1''' ändringar visas).",
 'rclistfrom' => 'Visa ändringar från och med $1',
 'rcshowhideminor' => '$1 mindre ändringar',
+'rcshowhideminor-show' => 'Visa',
+'rcshowhideminor-hide' => 'Dölj',
 'rcshowhidebots' => '$1 robotar',
+'rcshowhidebots-show' => 'Visa',
+'rcshowhidebots-hide' => 'Dölj',
 'rcshowhideliu' => '$1 registrerade användare',
+'rcshowhideliu-show' => 'Visa',
+'rcshowhideliu-hide' => 'Dölj',
 'rcshowhideanons' => '$1 oinloggade användare',
+'rcshowhideanons-show' => 'Visa',
+'rcshowhideanons-hide' => 'Dölj',
 'rcshowhidepatr' => '$1 patrullerade redigeringar',
+'rcshowhidepatr-show' => 'Visa',
+'rcshowhidepatr-hide' => 'Dölj',
 'rcshowhidemine' => '$1 mina ändringar',
+'rcshowhidemine-show' => 'Visa',
+'rcshowhidemine-hide' => 'Dölj',
 'rclinks' => 'Visa senaste $1 ändringar under de senaste $2 dygnen<br />$3',
 'diff' => 'skillnad',
 'hist' => 'historik',
@@ -1885,6 +1897,7 @@ Du borde be någon som kan se undanhållen fildata att granska situationen innan
 'uploaddisabledtext' => 'Uppladdning av filer är avstängd.',
 'php-uploaddisabledtext' => 'PHP filuppladdningar är avaktiverade. Kolla inställningarna för file_uploads.',
 'uploadscripted' => 'Denna fil innehåller HTML eller script som felaktigt kan komma att tolkas av webbläsare.',
+'uploadinvalidxml' => 'XML-koden i den uppladdade filen kunde inte tolkas.',
 'uploadvirus' => 'Filen innehåller virus! Detaljer: $1',
 'uploadjava' => 'Filen är en ZIP-fil som innehåller en Java .class fil.
 Uppladdning av Java filer tillåts inte, eftersom de kan orsaka att säkerhetsbegränsningar kan kringgås.',
@@ -4250,6 +4263,4 @@ Annars kan du använda det enkla formuläret nedan. Din kommentar kommer att lä
 'expand_templates_generate_rawhtml' => 'Visa rå HTML',
 'expand_templates_preview' => 'Förhandsvisning',
 
-# Unknown messages
-'uploadinvalidxml' => 'XML-koden i den uppladdade filen kunde inte tolkas.',
 );
index 8e3e34b..958978f 100644 (file)
@@ -304,7 +304,7 @@ $messages = array(
 'vector-action-delete' => 'తొలగించు',
 'vector-action-move' => 'తరలించు',
 'vector-action-protect' => 'సంరక్షించు',
-'vector-action-undelete' => 'తిరిà°\97à°¿ à°\9aà±\87à°°à±\8dà°\9aà±\81',
+'vector-action-undelete' => 'à°¤à±\8aà°²à°\97à°¿à°\82à°ªà±\81à°¨à±\81 à°°à°¦à±\8dà°¦à±\81à°\9aà±\86à°¯à±\8dయి',
 'vector-action-unprotect' => 'సంరక్షణను మార్చు',
 'vector-view-create' => 'సృష్టించు',
 'vector-view-edit' => 'సవరించు',
@@ -338,7 +338,7 @@ $messages = array(
 'delete' => 'తొలగించు',
 'deletethispage' => 'ఈ పేజీని తొలగించండి',
 'undeletethispage' => 'ఈ పేజీ తొలగింపును ఆపు',
-'undelete_short' => '{{PLURAL:$1|ఒక్క రచనను|$1 రచనలను}} పునఃస్థాపించు',
+'undelete_short' => '{{PLURAL:$1|ఒక్క రచన|$1 రచనల}} తొలగింపును రద్దుచెయ్యి',
 'viewdeleted_short' => '{{PLURAL:$1|తొలగించిన ఒక మార్పు|$1 తొలగించిన మార్పుల}}ను చూడండి',
 'protect' => 'సంరక్షించు',
 'protect_change' => 'మార్చు',
@@ -365,12 +365,12 @@ $messages = array(
 'viewtalkpage' => 'చర్చను చూడు',
 'otherlanguages' => 'ఇతర భాషలలో',
 'redirectedfrom' => '($1 నుండి మళ్ళించబడింది)',
-'redirectpagesub' => 'దారిమారà±\8dà°ªà±\81 à°ªà±\81à°\9f',
+'redirectpagesub' => 'దారిమారà±\8dà°ªà±\81 à°ªà±\87à°\9cà±\80',
 'lastmodifiedat' => 'ఈ పేజీలో చివరి మార్పు $1 న $2 కు జరిగింది.',
 'viewcount' => 'ఈ పేజీ {{PLURAL:$1|ఒక్క సారి|$1 సార్లు}} దర్శించబడింది.',
 'protectedpage' => 'సంరక్షణలోని పేజీ',
 'jumpto' => 'ఇక్కడికి గెంతు:',
-'jumptonavigation' => 'à°ªà±\87à°\9cà±\80à°\95à°¿ à°¸à°\82à°¬à°\82ధిà°\82à°\9aà°¿à°¨ à°²à°¿à°\82à°\95à±\81à°²à±\81',
+'jumptonavigation' => 'మారà±\8dà°\97à°¸à±\82à°\9aà±\80',
 'jumptosearch' => 'వెతుకు',
 'view-pool-error' => 'క్షమించండి, ప్రస్తుతం సర్వర్లన్నీ ఓవర్‌లోడ్ అయిఉన్నాయి.
 చాలామంది వాడుకరులు ఈ పేజీని చూస్తున్నారు.
@@ -385,7 +385,7 @@ $1',
 'aboutsite' => '{{SITENAME}} గురించి',
 'aboutpage' => 'Project:గురించి',
 'copyright' => 'విషయం $1 కి లోబడి లభ్యం, వేరుగా పేర్కొంటే తప్ప.',
-'copyrightpage' => '{{ns:project}}:à°ªà±\8dà°°à°\9aà±\81à°°à°£ హక్కులు',
+'copyrightpage' => '{{ns:project}}:à°\95ాపà±\80హక్కులు',
 'currentevents' => 'వర్తమాన ఘటనలు',
 'currentevents-url' => 'Project:వర్తమాన ఘటనలు',
 'disclaimers' => 'అస్వీకారములు',
@@ -393,7 +393,7 @@ $1',
 'edithelp' => 'దిద్దుబాటు సహాయం',
 'helppage' => 'Help:సూచిక',
 'mainpage' => 'మొదటి పేజీ',
-'mainpage-description' => 'తలపà±\81à°\9f',
+'mainpage-description' => 'à°®à±\8aà°¦à°\9fà°¿ à°ªà±\87à°\9cà±\80',
 'policy-url' => 'Project:విధానం',
 'portal' => 'సముదాయ పందిరి',
 'portal-url' => 'Project:సముదాయ పందిరి',
@@ -402,7 +402,7 @@ $1',
 
 'badaccess' => 'అనుమతి లోపం',
 'badaccess-group0' => 'మీరు చేయతలపెట్టిన పనికి మీకు హక్కులు లేవు.',
-'badaccess-groups' => 'మీరు చేయతలపెట్టిన పని ఈ {{PLURAL:$2|గుంపు|గుంపుల}} లోని వాడుకర్లకు మాత్రమే పరిమితం: $1.',
+'badaccess-groups' => 'మీరు చేయతలపెట్టిన పని ఈ {{PLURAL:$2|గుంపు|గుంపులలో ఒకదాని}} లోని వాడుకర్లకు మాత్రమే పరిమితం: $1.',
 
 'versionrequired' => 'మీడియావికీ సాఫ్టువేరు వెర్షను $1 కావాలి',
 'versionrequiredtext' => 'ఈ పేజీని వాడటానికి మీకు మీడియావికీ సాఫ్టువేరు వెర్షను $1 కావాలి. [[Special:Version|వెర్షను పేజీ]]ని చూడండి.',
@@ -410,15 +410,15 @@ $1',
 'ok' => 'సరే',
 'retrievedfrom' => '"$1" నుండి వెలికితీశారు',
 'youhavenewmessages' => 'మీకు $1 ఉన్నాయి ($2).',
-'youhavenewmessagesfromusers' => 'మీకు {{PLURAL:$3|మరో వాడుకరి|$3 వాడుకరుల}} నుండి $1 ($2).',
-'youhavenewmessagesmanyusers' => 'మీకు చాలా వాడుకరుల నుండి $1 ($2).',
-'newmessageslinkplural' => '{{PLURAL:$1|ఒక కొత్త సందేశం వచ్చింది|999=కొత్త సందేశాలు ఉన్నాయి}}',
+'youhavenewmessagesfromusers' => '{{PLURAL:$4|మీకు}} {{PLURAL:$3|మరో వాడుకరి|$3 వాడుకరుల}} నుండి  $1 ($2).',
+'youhavenewmessagesmanyusers' => 'మీకు చాలా వాడుకరుల నుండి $1 ఉన్నాయి ($2).',
+'newmessageslinkplural' => '{{PLURAL:$1|ఒక కొత్త సందేశం|999=కొత్త సందేశాలు}}',
 'newmessagesdifflinkplural' => 'చివరి {{PLURAL:$1|మార్పు|999=మార్పులు}}',
-'youhavenewmessagesmulti' => '$1లో మీకో సందేశం ఉంది',
+'youhavenewmessagesmulti' => '$1 లో మీకు కొత్త సందేశాలు ఉన్నాయి',
 'editsection' => 'మార్చు',
 'editold' => 'సవరించు',
 'viewsourceold' => 'మూలాన్ని చూడండి',
-'editlink' => 'సవరిà°\82చు',
+'editlink' => 'మారà±\8dచు',
 'viewsourcelink' => 'మూలాన్ని చూడండి',
 'editsectionhint' => 'విభాగాన్ని మార్చు: $1',
 'toc' => 'విషయ సూచిక',
@@ -431,10 +431,10 @@ $1',
 'restorelink' => '{{PLURAL:$1|ఒక తొలగించిన మార్పు|$1 తొలగించిన మార్పులు}}',
 'feedlinks' => 'ఫీడు:',
 'feed-invalid' => 'మీరు కోరిన ఫీడు సరైన రకం కాదు.',
-'feed-unavailable' => 'సిండికేషన్ ఫీడులేమీ అందుబాటులో లేవు.',
+'feed-unavailable' => 'సిండికేషన్ ఫీడులేమీ అందుబాటులో లేవు',
 'site-rss-feed' => '$1 RSS ఫీడు',
 'site-atom-feed' => '$1 ఆటమ్ ఫీడు',
-'page-rss-feed' => '"$1" ఆరెసెస్సు(RSS) ఫీడు',
+'page-rss-feed' => '"$1" RSS ఫీడు',
 'page-atom-feed' => '"$1" ఆటమ్ ఫీడు',
 'feed-atom' => 'యాటమ్',
 'red-link-title' => '$1 (పుట లేదు)',
@@ -450,7 +450,7 @@ $1',
 'nstab-image' => 'దస్త్రం',
 'nstab-mediawiki' => 'సందేశం',
 'nstab-template' => 'మూస',
-'nstab-help' => 'సహాయము',
+'nstab-help' => 'సహాయ పేజీ',
 'nstab-category' => 'వర్గం',
 
 # Main script and global functions
@@ -472,54 +472,54 @@ $1',
 'databaseerror-query' => 'క్వెరీ: $1',
 'databaseerror-function' => 'ఫంక్షన్: $1',
 'databaseerror-error' => 'లోపం: $1',
-'laggedslavemode' => 'హెచ్చరిక: పేజీలో ఇటీవల జరిగిన మార్పులు ఉండకపోవచ్చు.',
+'laggedslavemode' => '<strong>హెచ్చరిక:</strong> పేజీలో ఇటీవల జరిగిన మార్పులు ఉండకపోవచ్చు.',
 'readonly' => 'డేటాబేసు లాక్‌చెయ్యబడింది',
 'enterlockreason' => 'డేటాబేసుకు వేయబోతున్న లాకుకు కారణం తెలుపండి, దానితోపాటే ఎంతసమయం తరువాత ఆ లాకు తీసేస్తారో కూడా తెలుపండి',
 'readonlytext' => 'డేటాబేసు ప్రస్తుతం లాకు చేయబడింది. మార్పులు, చేర్పులు ప్రస్తుతం చెయ్యలేరు. మామూలుగా జరిగే నిర్వహణ కొరకు ఇది జరిగి ఉండవచ్చు; అది పూర్తి కాగానే తిరిగి మామూలుగా పనిచేస్తుంది.
 
 దీనిని లాకు చేసిన నిర్వాహకుడు ఇలా తెలియజేస్తున్నాడు: $1',
-'missing-article' => '"$1" $2 అనే పేజీ పాఠ్యం డేటాబేసులో దొరకలేదు.
+'missing-article' => '"$1" $2 à°\85à°¨à±\87 à°ªà±\87à°\9cà±\80 à°¯à±\8aà°\95à±\8dà°\95 à°ªà°¾à° à±\8dà°¯à°\82 à°¡à±\87à°\9fాబà±\87à°¸à±\81à°²à±\8b à°¦à±\8aà°°à°\95à°²à±\87à°¦à±\81.
 
-à°\95ాలదà±\8bà°·à°\82 à°ªà°\9fà±\8dà°\9fిన తేడా కోసం చూసినపుడుగానీ, తొలగించిన పేజీ చరితం కోసం చూసినపుడుగానీ ఇది సాధారణంగా జరుగుతుంది.
+à°\95ాలà°\82 à°\9aà±\86à°²à±\8dà°²ిన తేడా కోసం చూసినపుడుగానీ, తొలగించిన పేజీ చరితం కోసం చూసినపుడుగానీ ఇది సాధారణంగా జరుగుతుంది.
 
 ఒకవేళ అలా కాకపోతే, మీరో బగ్‌ను కనుక్కున్నట్టే.
-à°\88 URLà°¨à±\81 à°¸à±\82à°\9aà°¿à°¸à±\8dà°¤à±\82, à°¦à±\80à°¨à±\8dని à°\93 [[Special:ListUsers/sysop|నిరà±\8dవాహà°\95à±\81నిà°\95à°¿]] à°¤à±\86లియà°\9cà±\86à°¯à±\8dయండి.',
+à°\88 URLà°¨à±\81 à°¸à±\82à°\9aà°¿à°¸à±\8dà°¤à±\82, à°¦à±\80à°¨à±\8dని à°\93 [[Special:ListUsers/sysop|నిరà±\8dవాహà°\95à±\81నిà°\95à°¿]] à°¤à±\86లియà°\9cà±\87యండి.',
 'missingarticle-rev' => '(కూర్పు#: $1)',
 'missingarticle-diff' => '(తేడా: $1, $2)',
 'readonly_lag' => 'అనుచర (స్లేవ్) డేటాబేసు సర్వర్లు, ప్రధాన (మాస్టరు) సర్వరును అందుకునేందుకుగాను, డేటాబేసు ఆటోమాటిక్‌గా లాకు అయింది.',
 'internalerror' => 'అంతర్గత లోపం',
 'internalerror_info' => 'అంతర్గత లోపం: $1',
 'fileappenderrorread' => 'చేరుస్తున్నప్పుడు "$1"ని చదవలేకపోయాం.',
-'fileappenderror' => '"$1" à°¨à°¿ "$2" à°¤à±\8b à°\95à±\82à°°à±\8dà°\9aà°²à±\87à°\95à°ªà±\8bà°¤à±\81à°¨à±\8dà°¨ాం',
-'filecopyerror' => 'ఫైలు "$1"ని "$2"కు కాపీ చెయ్యటం కుదరలేదు.',
-'filerenameerror' => 'à°«à±\88à°²à±\81 "$1" à°ªà±\87à°°à±\81à°¨à±\81 "$2"à°\97à°¾ à°®à°¾à°°à±\8dà°\9aà°\9fà°\82 à°\95à±\81దరలà±\87à°¦à±\81.',
-'filedeleteerror' => 'à°«à±\88à°²à±\81 "$1"ని à°¤à±\80సివà±\87à°¯à°\9fà°\82 à°\95à±\81దరలà±\87à°¦à±\81.',
-'directorycreateerror' => '"$1" à°\85à°¨à±\87 à°¡à±\88à°°à±\86à°\95à±\8dà°\9fà°°à±\80ని à°¸à±\83à°·à±\8dà°\9fà°¿à°\82à°\9aà°²à±\87à°\95 à°ªà±\8bà°¤à±\81à°¨à±\8dనానà±\81.',
+'fileappenderror' => '"$1" à°¨à°¿ "$2" à°¤à±\8b à°\95à±\82à°°à±\8dà°\9aà°²à±\87à°\95à°ªà±\8bà°¯ాం',
+'filecopyerror' => 'ఫైలు "$1" ను "$2" కు కాపీ చెయ్యలేకపోయాం.',
+'filerenameerror' => 'à°«à±\88à°²à±\81 "$1" à°ªà±\87à°°à±\81à°¨à±\81 "$2"à°\97à°¾ à°®à°¾à°°à±\8dà°\9aà°²à±\87à°\95à°ªà±\8bయాà°\82.',
+'filedeleteerror' => 'à°«à±\88à°²à±\81 "$1"ని à°¤à±\8aà°²à°\97à°¿à°\82à°\9aà°²à±\87à°\95à°ªà±\8bయాà°\82.',
+'directorycreateerror' => '"$1" à°\85à°¨à±\87 à°¡à±\88à°°à±\86à°\95à±\8dà°\9fà°°à±\80ని à°¸à±\83à°·à±\8dà°\9fà°¿à°\82à°\9aà°²à±\87à°\95 à°ªà±\8bయాà°\82.',
 'filenotfound' => 'ఫైలు "$1" కనబడలేదు.',
-'fileexistserror' => '"$1" అనే ఫైలు ఉంది, కాని అందులోకి రాయలేకపోతున్నాను',
+'fileexistserror' => '"$1" అనే ఫైలులోకి రాయలేకపోతున్నాం. అది ఈసరికే ఉంది.',
 'unexpected' => 'అనుకోని విలువ: "$1"="$2".',
-'formerror' => 'à°²à±\8bà°ªà°\82: à°\88 à°«à°¾à°°à°¾à°¨à±\8dని à°ªà°\82పిà°\82à°\9aà°²à±\87à°\95à°ªà±\8bà°¤à±\81à°¨à±\8dనానà±\81',
+'formerror' => 'à°²à±\8bà°ªà°\82: à°\88 à°«à°¾à°°à°¾à°¨à±\8dని à°ªà°\82పిà°\82à°\9aà°²à±\87à°\95à°ªà±\8bయాà°\82.',
 'badarticleerror' => 'ఈ పేజీపై ఈ పని చేయడం కుదరదు.',
 'cannotdelete' => '"$1" అనే పేజీ లేదా ఫైలుని తొలగించలేకపోయాం.
 దాన్ని ఇప్పటికే ఎవరైనా తొలగించి ఉండవచ్చు.',
-'cannotdelete-title' => '"$1" పుటను తొలగించలేరు',
+'cannotdelete-title' => 'పేజీ "$1" ని తొలగించలేరు',
 'delete-hook-aborted' => 'తొలగింపును హుక్ ఆపేసింది.
 వివరణ ఏమీ ఇవ్వలేదు.',
 'no-null-revision' => '"$1" పేజీకి కొత్త శూన్య కూర్పు (నల్ రివిజన్) ను సృష్టించలేకపోయాం',
 'badtitle' => 'తప్పు శీర్షిక',
-'badtitletext' => 'à°®à±\80à°°à±\81 à°\95à±\8bà°°à°¿à°¨ à°ªà±\81à°\9f à°¯à±\8aà°\95à±\8dà°\95 à°ªà±\87à°°à±\81 à°\9aà±\86à°²à±\8dలనిది, à°\96ాళà±\80à°\97à°¾ à°\89à°\82ది, à°²à±\87దా à°¤à°ªà±\8dà°ªà±\81à°\97à°¾ à°\87à°\9aà±\8dà°\9aిన అంతర్వికీ లేదా అంతర-భాషా శీర్షిక అయివుండాలి.
+'badtitletext' => 'à°®à±\80à°°à±\81 à°\95à±\8bà°°à°¿à°¨ à°ªà±\87à°\9cà±\80 à°¯à±\8aà°\95à±\8dà°\95 à°ªà±\87à°°à±\81 à°\9aà±\86à°²à±\8dలనిది, à°\96ాళà±\80à°\97à°¾ à°\89à°\82ది, à°²à±\87దా à°¤à°ªà±\8dà°ªà±\81 à°²à°¿à°\82à°\95à±\81à°¤à±\8b à°\95à±\82à°¡ిన అంతర్వికీ లేదా అంతర-భాషా శీర్షిక అయివుండాలి.
 శీర్షికలలో ఉపయోగించకూడని అక్షరాలు దానిలో ఉండివుండొచ్చు.',
 'perfcached' => 'కింది డేటా ముందే సేకరించి పెట్టుకున్నది. కాబట్టి తాజా డేటాతో పోలిస్తే తేడాలుండవచ్చు. ఈ కాషెలో గరిష్టంగా {{PLURAL:$1|ఒక్క ఫలితం ఉంది|$1 ఫలితాలు ఉన్నాయి}}.',
 'perfcachedts' => 'కింది సమాచారం ముందే సేకరించి పెట్టుకున్నది. దీన్ని $1న చివరిసారిగా తాజాకరించారు. ఈ కాషెలో గరిష్టంగా {{PLURAL:$4|ఒక్క ఫలితం ఉంది|$4 ఫలితాలు ఉన్నాయి}}.',
-'querypage-no-updates' => 'à°ªà±\8dà°°à°¸à±\8dà°¤à±\81à°¤à°\82 à°\88 à°ªà±\81à°\9fకి తాజాకరణలని అచేతనం చేసారు.
-à°\87à°\95à±\8dà°\95à°¡à±\81à°¨à±\8dà°¨ à°­à±\8bà°\97à°\9fà±\8dà°\9fà°¾ à°\95à±\82à°¡à°¾ తాజాకరించబడదు.',
+'querypage-no-updates' => 'à°ªà±\8dà°°à°¸à±\8dà°¤à±\81à°¤à°\82 à°\88 à°ªà±\87à°\9cà±\80కి తాజాకరణలని అచేతనం చేసారు.
+à°\87à°\95à±\8dà°\95à°¡à±\81à°¨à±\8dà°¨ à°¡à±\87à°\9fà°¾ à°\95à±\82à°¡à°¾ à°ªà±\8dà°°à°¸à±\8dà°¤à±\81à°¤à°\82 తాజాకరించబడదు.',
 'viewsource' => 'మూలాన్ని చూపించు',
 'viewsource-title' => '$1 యొక్క సోర్సు చూడండి',
 'actionthrottled' => 'కార్యాన్ని ఆపేసారు',
 'actionthrottledtext' => 'స్పామును తగ్గించటానికి తీసుకున్న నిర్ణయాల వల్ల, మీరు ఈ కార్యాన్ని అతి తక్కువ సమయంలో బోలెడన్ని సార్లు చేయకుండా అడ్డుకుంటున్నాము. కొన్ని నిమిషాలు ఆగి మరలా ప్రయత్నించండి.',
 'protectedpagetext' => 'ఈ పేజీలో మార్పులు వగైరాలు చెయ్యకుండా ఉండేందుకు గాను, సంరక్షించబడింది.',
 'viewsourcetext' => 'మీరీ పేజీ సోర్సును చూడవచ్చు, కాపీ చేసుకోవచ్చు:',
-'viewyourtext' => "ఈ పేజీకి '''మీ మార్పుల''' యొక్క మూలాన్ని చూడవచ్చు లేదా కాపీచేసుకోవచ్చు:",
+'viewyourtext' => 'ఈ పేజీలోని <strong>మీ మార్పుల</strong> యొక్క మూలాన్ని చూడవచ్చు, కాపీచేసుకోవచ్చు:',
 'protectedinterface' => 'ఈ పేజీ, ఈ వికీ యొక్క సాఫ్టువేరు ఇంటరుఫేసుకు చెందిన టెక్స్టును అందిస్తుంది. దుశ్చర్యల నివారణ కోసమై దీన్ని సంరక్షించాం. వికీలన్నిటిలోను అనువాదాలను చేర్చాలన్నా, మార్చాలన్నా మీడియావికీ స్థానికీకరణ ప్రాజెక్టైన [//translatewiki.net/ translatewiki.net] ను వాడండి.',
 'editinginterface' => '<strong>హెచ్చరిక:</strong> సాఫ్టువేరుకు ఇంటరుఫేసు టెక్స్టును అందించేందుకు పనికొచ్చే పేజీని మీరు సరిదిద్దుతున్నారు.
 ఈ పేజీలో చేసే మార్పుల వల్ల ఇతర వాడుకరులకు ఇంటరుఫేసు కనబడే విధానంలో తేడావస్తుంది.
@@ -534,19 +534,19 @@ $2',
 'myprivateinfoprotected' => 'మీ అంతరంగిక సమాచారాన్ని సవరించేందుకు మీకు అనుమతి లేదు.',
 'mypreferencesprotected' => 'మీ అభీష్టాలను సవరించేందుకు మీకు అనుమతి లేదు.',
 'ns-specialprotected' => 'ప్రత్యేక పేజీలపై దిద్దుబాట్లు చేయలేరు.',
-'titleprotected' => "సభà±\8dà°¯à±\81à°²à±\81 [[User:$1|$1]] à°\88 à°ªà±\87à°\9cà±\80ని à°¸à±\83à°·à±\8dà°\9fà°¿à°\82à°\9aనివà±\8dà°µà°\95à±\81à°\82à°¡à°¾ à°¨à°¿à°°à±\8bదిసà±\8dà°¤à±\81à°¨à±\8dనారà±\81.
+'titleprotected' => "à°\88 à°ªà±\87à°\9cà±\80 [[వాడà±\81à°\95à°°à°¿:$1|$1]] à°¸à±\83à°·à±\8dà°\9fà°¿à°\82à°\9aà°\95à±\81à°\82à°¡à°¾ à°¸à°\82à°°à°\95à±\8dà°·à°¿à°\82à°\9aబడిà°\82ది.
 అందుకు ఇచ్చిన కారణం: ''$2''.",
 'filereadonlyerror' => 'ఫైలు ఖజానా "$2" రీడ్-ఓన్లీ స్థితిలో ఉండటం చేత "$1" ఫైలులో మార్పులు చెయ్యలేకపోయాం.
 
 దానికి తాళం వేసిన అధికారి ఇచ్చిన వివరణ ఇది: "$3".',
 'invalidtitle-knownnamespace' => 'పేరుబరి "$2", పాఠ్యము "$3" తో కూడిన ఈ శీర్షిక చెల్లనిది',
 'invalidtitle-unknownnamespace' => 'అపరిచితమైన పేరుబరి సంఖ్య "$1", పాఠ్యము "$2" తో కూడిన ఈ శీర్షిక చెల్లనిది',
-'exception-nologin' => 'à°²à±\8bనిà°\95à°¿ à°ªà±\8dà°°à°µà±\87శిà°\82à°\9aà°¿లేరు',
-'exception-nologin-text' => 'à°\88 à°ªà±\87à°\9cà±\80ని à°\9aà±\82డడానిà°\95à°¿ à°²à±\87దా à°\88 à°\9aà°°à±\8dయనà±\81 à°\9aà±\86à°¯à±\8dయడానిà°\95à°¿ à°¦à°¯à°\9aà±\87సి [[Special:Userlogin|à°ªà±\8dà°°à°µà±\87శిà°\82à°\9aండి]].',
+'exception-nologin' => 'లాà°\97à°¿à°¨à±\88 లేరు',
+'exception-nologin-text' => 'à°\88 à°ªà±\87à°\9cà±\80ని à°\9aà±\82డడానిà°\95à°¿ à°²à±\87దా à°\88 à°ªà°¨à°¿ à°\9aà±\86à°¯à±\8dయడానిà°\95à°¿ [[Special:Userlogin|లాà°\97ినవండి]].',
 'exception-nologin-text-manual' => 'ఈ పేజీ చూసేందుకు లేదా ఈ పని చేసేందుకు $1.',
 
 # Virus scanner
-'virus-badscanner' => "తప్పుడు స్వరూపణం: తెలియని వైరస్ స్కానర్: ''$1''",
+'virus-badscanner' => 'తప్పుడు స్వరూపణం: తెలియని వైరస్ స్కానర్: <em>$1</em>',
 'virus-scanfailed' => 'స్కాన్ విఫలమైంది (సంకేతం $1)',
 'virus-unknownscanner' => 'అజ్ఞాత యాంటీవైరస్:',
 
@@ -564,7 +564,7 @@ $2',
 'yourname' => 'వాడుకరి పేరు:',
 'userlogin-yourname' => 'వాడుకరి పేరు',
 'userlogin-yourname-ph' => 'మీ వాడుకరి పేరును ఇవ్వండి',
-'createacct-another-username-ph' => 'à°®à±\80 à°µà°¾à°¡à±\81à°\95à°°à°¿ à°ªà±\87à°°à±\81à°¨à±\81 à°ªà±\8dà°°à°µà±\87శపà±\86à°\9fà±\8dà°\9fండి',
+'createacct-another-username-ph' => 'à°®à±\80 à°µà°¾à°¡à±\81à°\95à°°à°¿ à°ªà±\87à°°à±\81à°¨à±\81 à°\87à°µà±\8dà°µండి',
 'yourpassword' => 'సంకేతపదం:',
 'userlogin-yourpassword' => 'సంకేతపదం',
 'userlogin-yourpassword-ph' => 'మీ సంకేతపదాన్ని ఇవ్వండి',
@@ -573,30 +573,30 @@ $2',
 'createacct-yourpasswordagain' => 'సంకేతపదాన్ని నిర్ధారించండి',
 'createacct-yourpasswordagain-ph' => 'సంకేతపదాన్ని మళ్ళీ ఇవ్వండి',
 'remembermypassword' => 'ఈ కంప్యూటరులో నా ప్రవేశాన్ని గుర్తుంచుకో (గరిష్ఠంగా $1 {{PLURAL:$1|రోజు|రోజుల}}కి)',
-'userlogin-remembermypassword' => 'ననà±\8dà°¨à±\81 à°ªà±\8dà°°à°µà±\87శిà°\82à°ªà°\9cà±\87సి ఉంచు',
+'userlogin-remembermypassword' => 'ననà±\8dà°¨à±\81 à°²à°¾à°\97à°¿à°¨à±\8d à°\9aà±\87à°¸à±\87 ఉంచు',
 'userlogin-signwithsecure' => 'సురక్షిత కనెక్షను వాడు',
 'yourdomainname' => 'మీ డోమైను',
 'password-change-forbidden' => 'ఈ వికీలో మీరు సంకేతపదాలను మార్చలేరు.',
 'externaldberror' => 'డేటాబేసు అధీకరణలో లోపం జరిగింది లేదా మీ బయటి ఖాతాను తాజాకరించడానికి మీకు అనుమతి లేదు.',
-'login' => 'à°²à±\8bనిà°\95à°¿ à°°ండి',
-'nav-login-createaccount' => 'à°²à±\8bనిà°\95à°¿ à°ªà±\8dà°°à°µà±\87శిà°\82à°\9aండి / ఖాతాని సృష్టించుకోండి',
+'login' => 'లాà°\97ినవండి',
+'nav-login-createaccount' => 'లాà°\97ినవండి / ఖాతాని సృష్టించుకోండి',
 'loginprompt' => '{{SITENAME}}లోకి ప్రవేశించాలంటే మీ విహారిణిలో కూకీలు చేతనమై ఉండాలి.',
-'userlogin' => 'à°ªà±\8dà°°à°µà±\87శిà°\82à°\9aండి / ఖాతాను సృష్టించుకోండి',
+'userlogin' => 'లాà°\97ినవండి / ఖాతాను సృష్టించుకోండి',
 'userloginnocreate' => 'ప్రవేశించండి',
 'logout' => 'నిష్క్రమించు',
-'userlogout' => 'నిషà±\8dà°\95à±\8dరమిà°\82à°\9aà±\81',
-'notloggedin' => 'à°²à±\8bనిà°\95à°¿ à°ªà±\8dà°°à°µà±\87శిà°\82à°\9aà°¿ లేరు',
+'userlogout' => 'లాà°\97à±\8cà°\9fà±\8d',
+'notloggedin' => 'లాà°\97à°¿à°¨à±\8dâ\80\8c à°\85యిలేరు',
 'userlogin-noaccount' => 'మీకు ఖాతా లేదా?',
 'userlogin-joinproject' => '{{SITENAME}}లో చేరండి',
 'nologin' => 'ఖాతా లేదా? $1.',
 'nologinlink' => 'ఖాతాని సృష్టించుకోండి',
 'createaccount' => 'ఖాతాని సృష్టించు',
 'gotaccount' => 'ఇప్పటికే మీకు ఖాతా ఉందా? $1.',
-'gotaccountlink' => 'à°ªà±\8dà°°à°µà±\87శిà°\82à°\9aండి',
-'userlogin-resetlink' => 'à°®à±\80 à°ªà±\8dà°°à°µà±\87à°¶ వివరాలను మరచిపోయారా?',
+'gotaccountlink' => 'లాà°\97ినవండి',
+'userlogin-resetlink' => 'à°®à±\80 à°²à°¾à°\97à°¿à°¨à±\8d వివరాలను మరచిపోయారా?',
 'userlogin-resetpassword-link' => 'మీ సంకేతపదాన్ని మర్చిపోయారా?',
-'helplogin-url' => 'Help:ప్రవేశించడం',
-'userlogin-helplink' => '[[{{MediaWiki:helplogin-url}}|à°ªà±\8dà°°à°µà±\87శిà°\82à°\9aడానిà°\95à°¿ సహాయం]]',
+'helplogin-url' => 'సహాయం:లాగినవడం',
+'userlogin-helplink' => '[[{{MediaWiki:helplogin-url}}|లాà°\97ినవడà°\82à°²à±\8b సహాయం]]',
 'userlogin-loggedin' => 'మీరు ఈసరికే {{GENDER:$1|$1}} గా లాగిన్ అయి ఉన్నారు.
 వేరే వాడుకరిగా లాగినయేందుకు కింది ఫారమును వాడండి.',
 'userlogin-createanother' => 'మరొక ఖాతాను సృష్టించండి',
@@ -615,7 +615,7 @@ $2',
 'createacct-imgcaptcha-ph' => 'పైన కనబడే మాటలను ఇక్కడ ఇవ్వండి',
 'createacct-submit' => 'మీ ఖాతాను సృష్టించుకోండి',
 'createacct-another-submit' => 'మరొక ఖాతాను సృష్టించు',
-'createacct-benefit-heading' => '{{SITENAME}}à°¨à±\81 à°¤à°¯à°¾à°°à±\81à°\9aà±\87à°¸à±\87ది à°®à±\80లాà°\82à°\9fà°¿ à°ªà±\8dà°°à°\9cà°²ే.',
+'createacct-benefit-heading' => '{{SITENAME}}à°¨à±\81 à°¤à°¯à°¾à°°à±\81à°\9aà±\87à°¸à±\8dà°¤à±\81à°¨à±\8dనది à°®à±\80లాà°\82à°\9fà°¿ à°µà°¾à°°ే.',
 'createacct-benefit-body1' => '{{PLURAL:$1|మార్పు|మార్పులు}}',
 'createacct-benefit-body2' => '{{PLURAL:$1|పేజీ|పేజీలు}}',
 'createacct-benefit-body3' => 'ఇటీవలి {{PLURAL:$1|సమర్పకుడు|సమర్పకులు}}',
@@ -623,8 +623,8 @@ $2',
 'userexists' => 'ఇచ్చిన వాడుకరిపేరు ఇప్పటికే వాడుకలో ఉంది.
 వేరే పేరును ఎంచుకోండి.',
 'loginerror' => 'లాగిన్ లోపం',
-'createacct-error' => 'పదà±\8dà°¦à±\81 à°¤à±\86రవడమà±\81à°²à±\8b à°¤à°ªà±\8dà°ªà±\81',
-'createaccounterror' => 'à°\96ాతాని సృష్టించలేకపోయాం: $1',
+'createacct-error' => 'à°\96ాతా à°¸à±\83à°·à±\8dà°\9fà°¿à°\82à°\9aà°¡à°\82à°²à±\8b à°²à±\8bà°ªà°\82',
+'createaccounterror' => 'à°\96ాతానà±\81 సృష్టించలేకపోయాం: $1',
 'nocookiesnew' => 'ఖాతాని సృష్టించాం, కానీ మీరు ఇంకా లోనికి ప్రవేశించలేదు.
 వాడుకరుల ప్రవేశానికి {{SITENAME}} కూకీలను వాడుతుంది.
 మీరు కూకీలని అచేతనం చేసివున్నారు.
@@ -635,40 +635,40 @@ $2',
 'nocookiesfornew' => 'మూలాన్ని కనుక్కోలేకపోయాం కాబట్టి, ఈ వాడుకరి ఖాతాను సృష్టించలేకపోయాం.
 మీ కంప్యూటర్లో కూకీలు చేతనమై ఉన్నాయని నిశ్చయించుకొని, ఈ పేజీని తిరిగి లోడు చేసి, మళ్ళీ ప్రయత్నించండి.',
 'noname' => 'మీరు సరైన వాడుకరిపేరు ఇవ్వలేదు.',
-'loginsuccesstitle' => 'à°ªà±\8dà°°à°µà±\87à°¶à°\82 à°µà°¿à°\9cయవà°\82తమà±\88à°¨ది',
-'loginsuccess' => "'''మీరు ఇప్పుడు {{SITENAME}}లోనికి \"\$1\"గా ప్రవేశించారు.'''",
+'loginsuccesstitle' => 'à°ªà±\8dà°°à°µà±\87à°¶à°\82 à°µà°¿à°\9cయవà°\82తమà±\88à°\82ది',
+'loginsuccess' => '<strong>మీరు ఇప్పుడు {{SITENAME}}లోనికి "$1"గా ప్రవేశించారు.</strong>',
 'nosuchuser' => '"$1" అనే పేరుతో వాడుకరులు లేరు.
 వాడుకరి పేర్లు కేస్ సెన్సిటివ్.
 అక్షరక్రమం సరిచూసుకోండి, లేదా [[Special:UserLogin/signup|కొత్త ఖాతా సృష్టించుకోండి]].',
-'nosuchusershort' => '"$1" à°\85à°¨à±\87 à°ªà±\87à°°à±\81à°¤à±\8b à°¸à°­à±\8dà°¯à±\81à°²à±\81 లేరు. పేరు సరి చూసుకోండి.',
-'nouserspecified' => 'సభà±\8dయనామానà±\8dని à°¤à°ªà±\8dపనిసరిà°\97à°¾ à°\8eà°\82à°\9aà±\81à°\95à±\8bవాలి.',
+'nosuchusershort' => '"$1" à°ªà±\87à°°à±\81à°¤à±\8b à°µà°¾à°¡à±\81à°\95à°°à°¿ à°\8eవరà±\82 లేరు. పేరు సరి చూసుకోండి.',
+'nouserspecified' => 'వాడà±\81à°\95à°°à°¿ à°ªà±\87à°°à±\81à°¨à±\81 à°¤à°ªà±\8dపనిసరిà°\97à°¾ à°\87à°µà±\8dవాలి.',
 'login-userblocked' => 'ఈ వాడుకరిని నిరోధించారు. ప్రవేశానికి అనుమతి లేదు.',
 'wrongpassword' => 'ఈ సంకేతపదం సరైనది కాదు. దయచేసి మళ్లీ ప్రయత్నించండి.',
 'wrongpasswordempty' => 'ఖాళీ సంకేతపదం ఇచ్చారు. మళ్ళీ ప్రయత్నించండి.',
-'passwordtooshort' => 'à°®à±\80 à°¸à°\82à°\95à±\87తపదà°\82 à°\95à°¨à±\80à°¸à°\82 {{PLURAL:$1|1 à°\85à°\95à±\8dà°·à°°à°\82|$1 à°\85à°\95à±\8dషరాల}} à°ªà±\8aà°¡à°µà±\81 ఉండాలి.',
+'passwordtooshort' => 'à°¸à°\82à°\95à±\87తపదà°\82 à°\95à°¨à±\80à°¸à°\82 {{PLURAL:$1|1 à°\85à°\95à±\8dà°·à°°à°\82|$1 à°\85à°\95à±\8dషరాల}} à°¨à°¿à°¡à°¿à°µà°¿ ఉండాలి.',
 'password-name-match' => 'మీ సంకేతపదం మీ వాడుకరిపేరుకి భిన్నంగా ఉండాలి.',
 'password-login-forbidden' => 'ఈ వాడుకరిపేరు మరియు సంకేతపదాలను ఉపయోగించడం నిషిద్ధం.',
 'mailmypassword' => 'సంకేతపదాన్ని మార్చు',
 'passwordremindertitle' => '{{SITENAME}} కోసం కొత్త తాత్కాలిక సంకేతపదం',
 'passwordremindertext' => '{{SITENAME}} ($4) లో కొత్త సంకేతపదం పంపించమని ఎవరో (బహుశ మీరే, ఐ.పీ. చిరునామా $1 నుండి) అడిగారు. వాడుకరి "$2" కొరకు "$3" అనే తాత్కాలిక సంకేతపదం సిద్ధంచేసి ఉంచాం. మీ ఉద్దేశం అదే అయితే, ఇప్పుడు మీరు సైటులోనికి ప్రవేశించి కొత్త సంకేతపదాన్ని ఎంచుకోవచ్చు. మీ తాత్కాలిక సంకేతపదం {{PLURAL:$5|ఒక రోజు|$5 రోజుల}}లో కాలంచెల్లుతుంది.
 
-à°\92à°\95à°µà±\87à°³ à°\88 à°\85à°­à±\8dయరà±\8dథన à°®à±\80à°°à±\81à°\95à°¾à°\95 à°®à°°à±\86వరà±\8b à°\9aà±\87సారనà±\81à°\95à±\81à°¨à±\8dనా à°²à±\87దా à°®à±\80 à°¸à°\82à°\95à±\87తపదà°\82 à°®à±\80à°\95à±\81 à°\97à±\81à°°à±\8dà°¤à±\81à°\95à±\81à°µà°\9aà±\8dà°\9aà°¿ à°¦à°¾à°¨à±\8dని à°®à°¾à°°à±\8dà°\9aà°\95à±\82à°¡à°¦à±\81 à°\85à°¨à±\81à°\95à±\81à°\82à°\9fà±\81à°¨à±\8dనా, à°\88 à°¸à°\82à°¦à±\87శానà±\8dని à°®à°°à±\8dà°\9aà°¿à°ªà±\8bà°¯ి మీ పాత సంకేతపదాన్ని వాడడం కొనసాగించవచ్చు.',
-'noemail' => 'సభà±\8dà°¯à±\81à°²à±\81 "$1"à°\95à±\81 à°\88-మెయిలు చిరునామా నమోదయి లేదు.',
+à°\92à°\95à°µà±\87à°³ à°\88 à°\85à°­à±\8dయరà±\8dథన à°®à±\80à°°à±\81à°\95à°¾à°\95 à°®à°°à±\86వరà±\8b à°\9aà±\87సారనà±\81à°\95à±\81à°¨à±\8dనా à°²à±\87దా à°®à±\80 à°¸à°\82à°\95à±\87తపదà°\82 à°®à±\80à°\95à±\81 à°\97à±\81à°°à±\8dà°¤à±\81à°\95à±\81à°µà°\9aà±\8dà°\9aà°¿ à°¦à°¾à°¨à±\8dని à°®à°¾à°°à±\8dà°\9aà°\95à±\82à°¡à°¦à±\81 à°\85à°¨à±\81à°\95à±\81à°\82à°\9fà±\81à°¨à±\8dనా, à°\88 à°¸à°\82à°¦à±\87శానà±\8dని à°µà°¿à°¸à±\8dమరిà°\82à°\9aి మీ పాత సంకేతపదాన్ని వాడడం కొనసాగించవచ్చు.',
+'noemail' => 'వాడà±\81à°\95à°°à°¿ "$1" à°\95à±\81 à°\88మెయిలు చిరునామా నమోదయి లేదు.',
 'noemailcreate' => 'మీరు సరైన ఈమెయిల్ చిరునామాని ఇవ్వాలి',
 'passwordsent' => '"$1" కొరకు నమోదైన ఈ-మెయిలు చిరునామాకి కొత్త సంకేతపదాన్ని పంపించాం.
 అది అందిన తర్వాత ప్రవేశించి చూడండి.',
-'blocked-mailpassword' => 'దిదà±\8dà°¦à±\81బాà°\9fà±\8dà°²à±\81 à°\9aà±\86à°¯à±\8dà°¯à°\95à±\81à°\82à°¡à°¾ à°\88 à°\90à°ªà±\80à°\85à°¡à±\8dà°°à°¸à±\81à°¨à±\81 à°¨à°¿à°°à±\8bధిà°\82à°\9aà°¾à°\82. à°\85à°\82à°\9aà±\87à°¤, à°¦à±\81à°¶à±\8dà°\9aà°°à±\8dయల à°¨à°¿à°µà°¾à°°à°£ à°\95à±\8bà°¸à°\82 à°\97ానà±\81, à°®à°°à°\9aà°¿à°ªà±\8bయిన à°¸à°\82à°\95à±\87తపదానà±\8dని à°ªà±\8aà°\82à°¦à±\87 à°\85à°\82శానà±\8dని à°\85à°¨à±\81మతిà°\82à°\9aà°®ు.',
+'blocked-mailpassword' => 'దిదà±\8dà°¦à±\81బాà°\9fà±\8dà°²à±\81 à°\9aà±\86à°¯à±\8dà°¯à°\95à±\81à°\82à°¡à°¾ à°®à±\80 à°\90à°ªà±\80à°\85à°¡à±\8dà°°à°¸à±\81à°¨à±\81 à°¨à°¿à°°à±\8bధిà°\82à°\9aà°¾à°\82. à°\85à°\82à°\9aà±\87à°¤, à°¦à±\81à°¶à±\8dà°\9aà°°à±\8dయల à°¨à°¿à°µà°¾à°°à°£ à°\95à±\8bà°¸à°\82 à°\97ానà±\81, à°®à°°à°\9aà°¿à°ªà±\8bయిన à°¸à°\82à°\95à±\87తపదానà±\8dని à°ªà±\8aà°\82à°¦à±\87 à°µà±\80à°²à±\81 à°\88 à°\90à°ªà±\80à°\95à°¿ à°²à±\87à°¦ు.',
 'eauthentsent' => 'ఇచ్చిన ఈ-మెయిలు అడ్రసుకు ధృవీకరణ మెయిలు పంపించాం.
 ఇకపై మేము ఆ ఖాతాకు మెయిలు పంపాలంటే, ముందుగా మీరు ఆ మెయిల్లో సూచించినట్లుగా చేసి, ఈ చిరునామా మీదేనని ధృవీకరించాలి.',
-'throttled-mailpassword' => 'à°\97à°¡à°\9aà°¿à°¨ {{PLURAL:$1|à°\92à°\95 à°\97à°\82à°\9fà°²à±\8b|$1 à°\97à°\82à°\9fà°²à±\8dà°²à±\8b}} à°\87à°ªà±\8dà°ªà°\9fà°¿à°\95à±\87  à°¦à°¾à°\9fà±\81మాà°\9f à°®à°¾à°°à±\8dà°\9aà°¿à°¨à°\9fà±\8dà°²à±\81à°\97à°¾ à°\92à°\95 à°®à±\86యిలà±\8d  పంపించివున్నాం.
-à°¦à±\81à°¶à±\8dà°\9aà°°à±\8dయలనà±\81 à°¨à°¿à°µà°¾à°°à°¿à°\82à°\9aà±\87à°\82à°¦à±\81à°\95à±\81 à°\97ానà±\81, {{PLURAL:$1|à°\92à°\95 à°\97à°\82à°\9fà°\95à°¿|$1 à°\97à°\82à°\9fà°²à°\95à°¿}} à°\92à°\95à±\8dà°\95సారి à°®à°¾à°¤à±\8dà°°à°®à±\87 à°¦à°¾à°\9fà±\81మాà°\9f à°®à°¾à°°à±\8dà°ªà±\81 à°®à±\86యిలà±\8d పంపిస్తాము.',
+'throttled-mailpassword' => 'à°\97à°¡à°\9aà°¿à°¨ {{PLURAL:$1|à°\92à°\95 à°\97à°\82à°\9fà°²à±\8b|$1 à°\97à°\82à°\9fà°²à±\8dà°²à±\8b}} à°¸à°\82à°\95à±\87తపదà°\82 à°®à°¾à°°à±\8dà°\9aà°¿à°¨à°\9fà±\8dà°²à±\81à°\97à°¾ à°\92à°\95 à°®à±\86యిలà±\81 పంపించివున్నాం.
+à°¦à±\81à°¶à±\8dà°\9aà°°à±\8dయలనà±\81 à°¨à°¿à°µà°¾à°°à°¿à°\82à°\9aà±\87à°\82à°¦à±\81à°\95à±\81 à°\97ానà±\81, {{PLURAL:$1|à°\92à°\95 à°\97à°\82à°\9fà°\95à±\81|$1 à°\97à°\82à°\9fà°²à°\95à±\81}} à°\92à°\95à±\8dà°\95సారి à°®à°¾à°¤à±\8dà°°à°®à±\87 à°¸à°\82à°\95à±\87తపదà°\82 à°®à°¾à°°à±\8dà°ªà±\81 à°®à±\86యిలà±\81 పంపిస్తాము.',
 'mailerror' => 'మెయిలు పంపించడంలో లోపం: $1',
 'acct_creation_throttle_hit' => 'మీ ఐపీ చిరునామా వాడుతున్న ఈ వికీ సందర్శకులు గత ఒక్క రోజులో {{PLURAL:$1|1 ఖాతాని|$1 ఖాతాలను}} సృష్టించారు, ఈ కాల వ్యవధిలో అది గరిష్ఠ పరిమితి.
 అందువల్ల, ఈ ఐపీని వాడుతున్న సందర్శకులు ప్రస్తుతానికి ఇంక ఖాతాలని సృష్టించలేరు.',
 'emailauthenticated' => 'మీ ఈ-మెయిలు చిరునామా $2న $3కి ధృవీకరింపబడింది.',
 'emailnotauthenticated' => 'మీ ఈ-మెయిలు చిరునామాను ఇంకా ధృవీకరించలేదు. 
 కింద పేర్కొన్న అంశాలకు సంబంధించి ఎటువంటి ఈ-మెయిలునూ పంపించము.',
-'noemailprefs' => 'à°\95à°¿à°\82ది à°\85à°\82శాలà±\81 à°ªà°¨à°¿ à°\9aà±\86à°¯à±\8dà°¯à°\9fానిà°\95à°¿ à°\88-à°®à±\86యిలà±\81 à°\9aà°¿à°°à±\81నామానà±\81 à°¨à°®à±\8aà°¦à±\81à°\9aà°¯à±\8dà°¯ండి.',
+'noemailprefs' => 'à°\88 à°\85à°\82శాలà±\81 à°ªà°¨à°¿ à°\9aà±\86à°¯à±\8dయడానిà°\95à°¿ à°®à±\80 à°\85à°­à°¿à°°à±\81à°\9aà±\81à°²à±\8dà°²à±\8b à°\88à°®à±\86యిలà±\81 à°\9aà°¿à°°à±\81నామా à°\87à°µà±\8dà°µండి.',
 'emailconfirmlink' => 'మీ ఈ-మెయిలు చిరునామాను ధృవీకరించండి',
 'invalidemailaddress' => 'మీరు ఇచ్చిన ఈ-మెయిలు చిరునామా సరైన రీతిలో లేనందున అంగీకరించటంలేదు.
 దయచేసి ఈ-మెయిలు చిరునామాను సరైన రీతిలో ఇవ్వండి లేదా ఖాళీగా వదిలేయండి.',
@@ -689,7 +689,7 @@ $2',
 'suspicious-userlogout' => 'సరిగా పనిచేయని విహారిణి లేదా కాషింగ్ ప్రాక్సీ వల్ల పంపబడడం చేత, నిష్క్రమించాలనే మీ అభ్యర్థనని నిరాకరించారు.',
 'createacct-another-realname-tip' => 'అసలు పేరు ఐచ్ఛికం.
 మీరు దాన్ని ఇస్తే, వాడుకరి పనుల శ్రేయస్సు ఆ పేరుకు ఆపాదించబడుతుంది.',
-'pt-login' => 'à°ªà±\8dà°°à°µà±\87శిà°\82à°\9aండి',
+'pt-login' => 'లాà°\97ినవండి',
 'pt-createaccount' => 'ఖాతా సృష్టించు',
 'pt-userlogout' => 'నిష్క్రమించు',
 
@@ -700,12 +700,12 @@ $2',
 
 # Change password dialog
 'changepassword' => 'సంకేతపదాన్ని మార్చండి',
-'resetpass_announce' => 'à°ªà±\8dà°°à°µà±\87శానà±\8dని à°ªà±\82à°°à±\8dతిà°\9aà±\87à°¸à±\87à°\82à°¦à±\81à°\95à±\81, à°®à±\80à°°à±\81 à°¤à°ªà±\8dపనిసరిà°\97à°¾ à°\87à°\95à±\8dà°\95à°¡ à°\95à±\8aà°¤à±\8dà°¤ à°¸à°\82à°\95à±\87తపదానà±\8dని à°\85మరà±\8dà°\9aà±\81à°\95à±\8bవాలి:',
+'resetpass_announce' => 'లాà°\97à°¿à°¨à±\8dà°¨à±\81 à°ªà±\82à°°à±\8dతిà°\9aà±\87à°¸à±\87à°\82à°¦à±\81à°\95à±\81, à°¤à°ªà±\8dపనిసరిà°\97à°¾ à°\95à±\8aà°¤à±\8dà°¤ à°¸à°\82à°\95à±\87తపదానà±\8dని à°\87à°µà±\8dవాలి:',
 'resetpass_header' => 'ఖాతా సంకేతపదం మార్పు',
 'oldpassword' => 'పాత సంకేతపదం:',
 'newpassword' => 'కొత్త సంకేతపదం:',
 'retypenew' => 'సంకేతపదం, మళ్ళీ',
-'resetpass_submit' => 'à°¸à°\82à°\95à±\87తపదానà±\8dని à°®à°¾à°°à±\8dà°\9aà°¿ à°²à±\8bనిà°\95à°¿ à°ªà±\8dà°°à°µà±\87శిà°\82à°\9aండి',
+'resetpass_submit' => 'à°¸à°\82à°\95à±\87తపదానà±\8dని à°®à°¾à°°à±\8dà°\9aà°¿ à°²à°¾à°\97ినవండి',
 'changepassword-success' => 'మీ సంకేతపదం విజయవంతంగా మార్చబడింది.',
 'changepassword-throttled' => 'కొద్దిసేపటిగా మీరు చాలా లాగిన్ ప్రయత్నాలు చేసారు.
 మళ్ళీ ప్రయత్నించే ముందు $1 ఆగండి.',
@@ -715,12 +715,12 @@ $2',
 'resetpass-submit-cancel' => 'రద్దుచేయి',
 'resetpass-wrong-oldpass' => 'తప్పుడు తాత్కాలిక లేదా ప్రస్తుత సంకేతపదం.
 మీరు మీ సంకేతపదాన్ని ఇప్పటికే విజయవంతంగా మార్చుకొనివుండవచ్చు లేదా కొత్త తాత్కాలిక సంకేతపదం కోసం అభ్యర్థించారు.',
-'resetpass-recycled' => 'దయà°\9aà±\87సి à°®à±\80 à°ªà±\8dà°°à°¸à±\8dà°¤à±\81à°¤ à°¸à°\82à°\95à±\87తపదà°\82 à°\95à°¾à°\95à±\81à°\82à°¡à°¾ à°µà±\87à°°à±\87 à°¸à°\82à°\95à±\87తపదà°\82 à°\87à°µà±\8dà°µà°\82à°¡à°¿.',
+'resetpass-recycled' => 'à°®à±\80 à°ªà±\8dà°°à°¸à±\8dà°¤à±\81à°¤ à°¸à°\82à°\95à±\87తపదానà±\8dని à°µà±\87à°°à±\87 à°¸à°\82à°\95à±\87తపదà°\82à°¤à±\8b à°®à°¾à°°à±\8dà°\9aà±\81à°\95à±\8bà°\82à°¡à°¿',
 'resetpass-temp-emailed' => 'మీరు మీ ఈమెయిలుకు పంపించిన తాత్కాలిక కోడుతో లోపలికి వచ్చారు. ప్రవేశం పూర్తి కావడానికి, ఇక్కడ మీరు తప్పనిసరిగా కొత్త సంకేతపదం ఇవ్వాలి:',
 'resetpass-temp-password' => 'తాత్కాలిక సంకేతపదం:',
 'resetpass-abort-generic' => 'ఓ పొడిగింత (ఎక్స్టెన్‍షన్) సంకేతపదం మార్పిడిని ఆపేసింది.',
-'resetpass-expired' => 'à°®à±\80 à°¸à°\82à°\95à±\87తపదà°\82 à°\95ాలà°\82 à°\9aà±\86à°²à±\8dలినది. à°¦à°¯à°\9aà±\87సి à°\95à±\8aà°¤à±\8dà°¤ à°ªà°¦à°\82 à°\87à°\9aà±\8dà°\9aà°¿ à°ªà±\8dà°°à°µà±\87శిà°\82à°\9aండి.',
-'resetpass-expired-soft' => 'à°®à±\80 à°¸à°\82à°\95à±\87తపదà°\82 à°\95ాలà°\82 à°\9aà±\86à°²à±\8dలినది, à°\95ాబà°\9fà±\8dà°\9fà°¿ à°\95à±\8aà°¤à±\8dతది à°\87à°µà±\8dవాలి. à°\95à±\8aà°¤à±\8dతది à°\87à°ªà±\8dà°ªà±\81à°¡à±\87 à°\87à°µà±\8dà°µà°\82à°¡à°¿ à°²à±\87దా à°°à°¦à±\8dà°¦à±\81à°\9aà±\87సి à°¤à°°à±\81వాత à°°à±\80à°¸à±\86à°\9fà±\8d à°\9aà±\87à°¯ండి.',
+'resetpass-expired' => 'à°®à±\80 à°¸à°\82à°\95à±\87తపదానిà°\95à°¿ à°\95ాలà°\82 à°\9aà±\86à°²à±\8dలిà°\82ది. à°\95à±\8aà°¤à±\8dà°¤ à°¸à°\82à°\95à±\87తపదà°\82 à°\87à°\9aà±\8dà°\9aà°¿ à°²à°¾à°\97ినవండి.',
+'resetpass-expired-soft' => 'à°®à±\80 à°¸à°\82à°\95à±\87తపదానిà°\95à°¿ à°\95ాలà°\82 à°\9aà±\86à°²à±\8dలిà°\82ది, à°\95ాబà°\9fà±\8dà°\9fà°¿ à°\95à±\8aà°¤à±\8dతది à°\87à°µà±\8dవాలి. à°\95à±\8aà°¤à±\8dతది à°\87à°ªà±\8dà°ªà±\81à°¡à±\87 à°\87à°µà±\8dà°µà°\82à°¡à°¿ à°²à±\87దా à°°à°¦à±\8dà°¦à±\81 à°¨à±\8aà°\95à±\8dà°\95à°¿, à°¤à°°à±\81వాత à°®à°¾à°°à±\8dà°\9aà±\81à°\95à±\8bండి.',
 
 # Special:PasswordReset
 'passwordreset' => 'సంకేతపదాన్ని మార్చుకోండి',
@@ -793,9 +793,9 @@ $2
 'extlink_tip' => 'బయటి లింకు (దీనికి ముందు http:// ఇవ్వటం మరువకండి)',
 'headline_sample' => 'శీర్షిక పాఠ్యం',
 'headline_tip' => '2వ స్థాయి శీర్షిక',
-'nowiki_sample' => 'ఫారà±\8dమాà°\9fà±\81 à°\9aà±\87à°¯à°\95à±\82డని à°ªà°¾à° à±\8dయానà±\8dని à°\87à°\95à±\8dà°\95à°¡ à°\9aà±\87à°°à±\8dà°\9aà°\82à°¡à°¿',
+'nowiki_sample' => 'ఫార్మాటు చేయని పాఠ్యాన్ని ఇక్కడ చేర్చండి',
 'nowiki_tip' => 'వికీ ఫార్మాటును పట్టించుకోవద్దు',
-'image_tip' => 'à°ªà±\8aదిà°\97ిన ఫైలు',
+'image_tip' => 'à°\87మిడà±\8dà°\9aిన ఫైలు',
 'media_tip' => 'దస్త్రపు లంకె',
 'sig_tip' => 'సమయంతో సహా మీ సంతకం',
 'hr_tip' => 'అడ్డగీత (అరుదుగా వాడండి)',
@@ -807,29 +807,29 @@ $2
 'watchthis' => 'ఈ పుట మీద కన్నేసి ఉంచు',
 'savearticle' => 'పేజీని భద్రపరచు',
 'preview' => 'మునుజూపు',
-'showpreview' => 'మునుజూపు',
-'showlivepreview' => 'తాà°\9cà°¾ మునుజూపు',
+'showpreview' => 'మునుజూపు చూపు',
+'showlivepreview' => 'à°¤à°\95à±\8dà°·à°£ మునుజూపు',
 'showdiff' => 'తేడాలను చూపించు',
-'anoneditwarning' => "'''హెచ్చరిక:''' మీరు లోనికి ప్రవేశించలేదు.
-ఈ పేజీ దిద్దుబాటు చరిత్రలో మీ ఐపీ చిరునామా నమోదవుతుంది.",
-'anonpreviewwarning' => "''మీరు లోనికి ప్రవేశించలేదు. భద్రపరిస్తే ఈ పేజీ యొక్క దిద్దుబాటు చరిత్రలో మీ ఐపీ చిరునామా నమోదవుతుంది.''",
-'missingsummary' => "'''గుర్తు చేస్తున్నాం:''' మీరు దిద్దుబాటు సారాంశమేమీ ఇవ్వలేదు. పేజీని మళ్ళీ భద్రపరచమని చెబితే సారాంశమేమీ లేకుండానే దిద్దుబాటును భద్రపరుస్తాం.",
+'anoneditwarning' => '<strong>హెచ్చరిక:</strong> మీరు లాగినవలేదు.
+ఈ పేజీ దిద్దుబాటు చరిత్రలో మీ ఐపీ చిరునామా నమోదవుతుంది.',
+'anonpreviewwarning' => '<em>మీరు లాగినవలేదు. భద్రపరిస్తే ఈ పేజీ యొక్క దిద్దుబాటు చరిత్రలో మీ ఐపీ చిరునామా నమోదవుతుంది.</em>',
+'missingsummary' => '<strong>గుర్తు చేస్తున్నాం:</strong> మీరు దిద్దుబాటు సారాంశమేమీ ఇవ్వలేదు. పేజీని మళ్ళీ భద్రపరచమని చెబితే సారాంశమేమీ లేకుండానే దిద్దుబాటును భద్రపరుస్తాం.',
 'missingcommenttext' => 'కింద ఓ వ్యాఖ్య రాయండి.',
 'missingcommentheader' => "'''గుర్తు చేస్తున్నాం''': ఈ వ్యాఖ్యకు మీరు విషయం/శీర్షిక పెట్టలేదు.
 \"{{int:savearticle}}\"ని మళ్ళీ నొక్కితే, మీ మార్పుకి విషయం/శీర్షిక ఏమీ లేకుండానే భద్రపరుస్తాం.",
-'summary-preview' => 'à°®à±\80à°°à±\81 à°°à°¾à°¸à°¿à°¨ à°¸à°¾à°°à°¾à°\82à°¶à°\82:',
+'summary-preview' => 'సారాà°\82à°¶à°\82 à°®à±\81à°¨à±\81à°\9cà±\82à°ªà±\81:',
 'subject-preview' => 'విషయం/శీర్షిక మునుజూపు:',
-'blockedtitle' => 'సభà±\8dà°¯à±\81నిపà±\88 à°¨à°¿à°°à±\8bà°§à°\82 à°\85మలయిà°\82ది',
-'blockedtext' => "'''మీ వాడుకరి పేరుని లేదా ఐ.పీ. చిరునామాని నిరోధించారు.'''
+'blockedtitle' => 'వాడà±\81à°\95à°°à°¿ à°¨à°¿à°°à±\8bధిà°\82à°\9aబడà±\8dడారà±\81',
+'blockedtext' => "<strong>మీ వాడుకరి పేరు లేదా ఐ.పీ. చిరునామా నిరోధించబడింది.</strong>
 
 నిరోధించినది $1.
-అందుకు ఇచ్చిన కారణం: ''$2''
+అందుకు ఇచ్చిన కారణం: <em>$2</em>.
 
 * నిరోధం మొదలైన సమయం: $8
 * నిరోధించిన కాలం: $6
 * నిరోధానికి గురైనవారు: $7
 
-ఈ నిరోధంపై చర్చించేందుకు మీరు $1ను గాని, మరెవరైనా [[{{MediaWiki:Grouppage-sysop}}|నిర్వాహకులను]] గాని సంప్రదించవచ్చు.
+ఈ నిరోధంపై చర్చించేందుకు మీరు $1 ను గాని, మరెవరైనా [[{{MediaWiki:Grouppage-sysop}}|నిర్వాహకులను]] గాని సంప్రదించవచ్చు.
 మీ [[Special:Preferences|ఖాతా అభిరుచులలో]] సరైన ఈ-మెయిలు చిరునామా ఇచ్చివుండకపోయినా లేదా మిమ్మల్ని  'ఈ వాడుకరికి ఈ-మెయిలు పంపు' సౌలభ్యాన్ని వాడుకోవడం నుండి నిరోధించివున్నా మీరు ఈమెయిలు ద్వారా సంప్రదించలేరు.
 మీ ప్రస్తుత ఐ.పీ. చిరునామా $3, మరియు నిరోధపు ID #$5.
 మీ సంప్రదింపులన్నిటిలోనూ వీటిని పేర్కొనండి.",
@@ -849,14 +849,14 @@ $2
 మీ ప్రస్తుత ఐపీ చిరునామా $3, మరియు నిరోధపు ఐడీ: $5.
 మీ సంప్రదింపులన్నిటిలోను అన్ని పై వివరాలను ఉదహరించండి.',
 'blockednoreason' => 'కారణమేమీ ఇవ్వలేదు',
-'whitelistedittext' => 'పుటలలో మార్పులు చెయ్యడానికి మీరు $1 ఉండాలి.',
+'whitelistedittext' => 'పుటలలో మార్పులు చెయ్యడానికి $1.',
 'confirmedittext' => 'పేజీల్లో మార్పులు చేసేముందు మీ ఈ-మెయిలు చిరునామా ధృవీకరించాలి. [[Special:Preferences|మీ అభిరుచుల]]లో మీ ఈ-మెయిలు చిరునామా రాసి, ధృవీకరించండి.',
 'nosuchsectiontitle' => 'విభాగాన్ని కనగొనలేకపోయాం',
 'nosuchsectiontext' => 'మీరు లేని విభాగాన్ని మార్చడానికి ప్రయత్నించారు.
 మీరు పేజీని చూస్తూన్నప్పుడు దాన్ని ఎవరైనా తరలించి లేదా తొలగించి ఉండవచ్చు.',
-'loginreqtitle' => 'à°ªà±\8dà°°à°µà±\87శమà±\81 తప్పనిసరి',
+'loginreqtitle' => 'లాà°\97ినవడà°\82 తప్పనిసరి',
 'loginreqlink' => 'లాగినవండి',
-'loginreqpagetext' => 'ఇతర పుటలను చూడడానికి మీరు $1 ఉండాలి.',
+'loginreqpagetext' => 'ఇతర పుటలను చూడడానికి $1.',
 'accmailtitle' => 'సంకేతపదం పంపించబడింది.',
 'accmailtext' => "[[User talk:$1|$1]] కొరకు ఒక యాదృచ్ఛిక సంకేతపదాన్ని $2కి పంపించాం. లాగినయ్యాక, ''[[Special:ChangePassword|సంకేతపదాన్ని మార్చుకోండి]]'' అనే పేజీలో ఈ సంకేతపదాన్ని మార్చుకోవచ్చు.",
 'newarticle' => '(కొత్తది)',
@@ -870,7 +870,7 @@ $2
 'noarticletext-nopermission' => 'ప్రస్తుతం ఈ పేజీలో పాఠ్యమేమీ లేదు.
 మీరు ఇతర పేజీలలో [[Special:Search/{{PAGENAME}}|ఈ పేజీ శీర్షిక కోసం వెతకవచ్చు]], లేదా <span class="plainlinks">[{{fullurl:{{#Special:Log}}|page={{FULLPAGENAMEE}}}} సంబంధిత చిట్టాలలో వెతకవచ్చు]</span>, కానీ ఈ పేజీని సృష్టించడానికి మీకు అనుమతి లేదు.',
 'missing-revision' => '"{{PAGENAME}}" అనే పేజీ యొక్క కూర్పు #$1 ఉనికిలో లేదు. సాధారణంగా ఏదైనా తొలగించబడిన పేజీ యొక్క కాలం చెల్లిన చరితం లింకును నొక్కినపుడు ఇది జరుగుతుంది. వివరాలు [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} తొలగింపు లాగ్] లో దొరుకుతాయి.',
-'userpage-userdoesnotexist' => '"<nowiki>$1</nowiki>" అనే వాడుకరి ఖాతా నమోదయిలేదు. మీరు ఈ పేజీని సృష్టించ/సరిదిద్దాలనుకుంటే, సరిచూసుకోండి.',
+'userpage-userdoesnotexist' => '"$1" అనే వాడుకరి ఖాతా నమోదయిలేదు. మీరు ఈ పేజీని సృష్టించాలని/సరిదిద్దాలని అనుకుంటున్నారేమో చూడండి.',
 'userpage-userdoesnotexist-view' => 'వాడుకరి ఖాతా "$1" నమోదుకాలేదు.',
 'blocked-notice-logextract' => 'ప్రస్తుతం ఈ వాడుకరిని నిరోధించారు.
 నిరోధపు చిట్టాలోని చివరి పద్దుని మీ సమాచారం కోసం ఈ క్రింద ఇస్తున్నాం:',
@@ -879,11 +879,11 @@ $2
 * <strong>గూగుల్ క్రోమ్:</strong> <em>Ctrl-Shift-R</em> (మాక్ లో <em>⌘-Shift-R</em>) నొక్కండి
 *<strong>ఇంటర్నెట్ ఎక్ప్లోరర్:</strong> <em>Ctrl</em> ను నొక్కిపట్టి <em>Refresh</em> నొక్కండి లేదా <em>Ctrl-F5</em> నొక్కండి.
 *<em>ఒపెరా:</em> <em>Tools → Preferences</em> ద్వారా కోశాన్ని ఖాళీ చెయ్యండి',
-'usercssyoucanpreview' => "'''చిట్కా:''' భద్రపరిచేముందు మీ కొత్త CSSని పరీక్షించడానికి \"{{int:showpreview}}\" అనే బొత్తాన్ని వాడండి.",
-'userjsyoucanpreview' => "'''చిట్కా:''' భద్రపరిచేముందు మీ కొత్త జావాస్క్రిప్టుని పరీక్షించడానికి \"{{int:showpreview}}\" అనే బొత్తాన్ని వాడండి.",
-'usercsspreview' => "'''మీరు వాడుకరి CSSను కేవలం సరిచూస్తున్నారని గుర్తుంచుకోండి.'''
-'''దాన్నింకా భద్రపరచలేదు!'''",
-'userjspreview' => "'''గుర్తుంచుకోండి, మీరింకా మీ వాడుకరి జావాస్క్రిప్ట్&zwnj;ను భద్రపరచలేదు, కేవలం పరీక్షిస్తున్నారు/సరిచూస్తున్నారు!'''",
+'usercssyoucanpreview' => '<strong>చిట్కా:</strong> భద్రపరిచేముందు మీ కొత్త CSSని పరీక్షించడానికి "{{int:showpreview}}" బొత్తాన్ని వాడండి.',
+'userjsyoucanpreview' => '<strong>చిట్కా:</strong> భద్రపరిచేముందు మీ కొత్త జావాస్క్రిప్టుని పరీక్షించడానికి "{{int:showpreview}}" బొత్తాన్ని వాడండి.',
+'usercsspreview' => '<strong>మీరు వాడుకరి CSSను కేవలం సరిచూస్తున్నారని గుర్తుంచుకోండి.
+దాన్నింకా భద్రపరచలేదు!</strong>',
+'userjspreview' => '<strong>గుర్తుంచుకోండి, మీరింకా మీ వాడుకరి జావాస్క్రిప్ట్&zwnj;ను భద్రపరచలేదు, కేవలం పరీక్షిస్తున్నారు/సరిచూస్తున్నారు!</strong>',
 'sitecsspreview' => "'''మీరు చూస్తున్నది ఈ CSS మునుజూపును మాత్రమేనని గుర్తుంచుకోండి.'''
 '''దీన్నింకా భద్రపరచలేదు!'''",
 'sitejspreview' => "'''మీరు చూస్తున్నది ఈ JavaScript మునుజూపును మాత్రమేనని గుర్తుంచుకోండి.''' 
@@ -891,9 +891,9 @@ $2
 'userinvalidcssjstitle' => "'''హెచ్చరిక:''' \"\$1\" అనే అలంకారం లేదు.
 అభిమత .css మరియు .js పుటల శీర్షికలు ఇంగ్లీషు చిన్నబడి అక్షరాల లోనే ఉండాలని గుర్తుంచుకోండి, ఉదాహరణకు ఇలా {{ns:user}}:Foo/vector.css అంతేగానీ, {{ns:user}}:Foo/Vector.css ఇలా కాదు.",
 'updated' => '(నవీకరించబడింది)',
-'note' => "'''గమనిక:'''",
-'previewnote' => "'''ఇది మునుజూపు మాత్రమేనని గుర్తుంచుకోండి.'''
-మీ మార్పులు ఇంకా భద్రమవ్వలేదు!",
+'note' => '<strong>గమనిక:</strong>',
+'previewnote' => '<strong>ఇది మునుజూపు మాత్రమేనని గుర్తుంచుకోండి.</strong>
+మీ మార్పులు ఇంకా భద్రమవ్వలేదు!',
 'continue-editing' => 'సరిదిద్దే చోటుకి వెళ్ళండి',
 'previewconflict' => 'భద్రపరచిన తరువాత పై టెక్స్ట్‌ ఏరియాలోని టెక్స్టు ఇలాగ కనిపిస్తుంది.',
 'session_fail_preview' => "'''క్షమించండి! సెషను డేటా పోవడం వలన మీ మార్పులను స్వీకరించలేకపోతున్నాం.'''
@@ -906,10 +906,10 @@ $2
 '''మీరు చేసినది సరైన దిద్దుబాటే అయితే, మళ్ళీ ప్రయత్నించండి. అయినా పనిచెయ్యకపోతే, ఓ సారి లాగౌటయ్యి, మళ్ళీ లాగినయి చూడండి.'''",
 'token_suffix_mismatch' => "'''మీ క్లయంటు, దిద్దుబాటు టోకెన్‌లోని వ్యాకరణ గుర్తులను గజిబిజి చేసింది కాబట్టి మీ దిద్దుబాటును తిరస్కరించాం. పేజీలోని పాఠ్యాన్ని చెడగొట్టకుండా ఉండేందుకు గాను, ఆ దిద్దుబాటును రద్దు చేశాం. వెబ్‌లో ఉండే లోపభూయిష్టమైన అజ్ఞాత ప్రాక్సీ సర్వీసులను వాడినపుడు ఒక్కోసారి ఇలా జరుగుతుంది.'''",
 'edit_form_incomplete' => '’’’ఈ ఎడిట్ ఫారంలోని కొన్ని భాగాలు సర్వరును చేరలేదు; మీ మార్పుచేర్పులు భద్రంగా ఉన్నాయని ధృవపరచుకుని, మళ్ళీ ప్రయత్నించండి.’’’',
-'editing' => '$1కి మార్పులు',
+'editing' => '$1 ని సవరిస్తున్నారు',
 'creating' => '$1 పేజీని సృష్టిస్తున్నారు',
-'editingsection' => '$1కు మార్పులు (విభాగం)',
-'editingcomment' => '$1 à°¦à°¿à°¦à±\8dà°¦à±\81బాà°\9fు (కొత్త విభాగం)',
+'editingsection' => '$1 ని సవరిస్తున్నారు (విభాగం)',
+'editingcomment' => '$1 à°¨à°¿ à°¸à°µà°°à°¿à°¸à±\8dà°¤à±\81à°¨à±\8dనారు (కొత్త విభాగం)',
 'editconflict' => 'దిద్దుబాటు ఘర్షణ: $1',
 'explainconflict' => "మీరు మార్పులు చెయ్యడం మొదలుపెట్టిన తరువాత, వేరే ఎవరో ఈ పుటని మార్పారు.
 పైన ఉన్న పాఠ్య పేటికలో ఈ పుట యొక్క ప్రస్తుతపు పాఠ్యం ఉంది.
@@ -918,23 +918,24 @@ $2
 మీరు \"{{int:savearticle}}\"ను నొక్కినపుడు, పై పాఠ్య పేటికలో ఉన్న పాఠ్యం '''మాత్రమే''' భద్రపరచబడుతుంది.",
 'yourtext' => 'మీ పాఠ్యం',
 'storedversion' => 'భద్రపరచిన కూర్పు',
-'nonunicodebrowser' => "'''WARNING: Your browser is not unicode compliant. A workaround is in place to allow you to safely edit pages: non-ASCII characters will appear in the edit box as hexadecimal codes.'''",
-'editingold' => "'''హెచ్చ రిక: ఈ పేజీ యొక్క కాలం చెల్లిన సంచికను మీరు మరుస్తున్నారు. దీనిని భద్రపరిస్తే, ఆ సంచిక తరువాత ఈ పేజీలో జరిగిన మార్పులన్నీ పోతాయి.'''",
+'nonunicodebrowser' => '<strong>హెచ్చరిక: మీ బ్రౌజరు యూనికోడుకు అనుకూలంగా లేదు.</strong>
+పేజీలను క్షేమంగా సవరించేందుకు ఓ దారి ఉంది: ASCII యేతర కారెక్టర్లు ఎడిట్ పెట్టెలో హెక్సాడెసిమల్ కోడ్‍లుగా కనిపిస్తాయి.',
+'editingold' => '<strong>హెచ్చ రిక: ఈ పేజీ యొక్క కాలం చెల్లిన సంచికను మీరు మరుస్తున్నారు.</strong> దీనిని భద్రపరిస్తే, ఆ సంచిక తరువాత జరిగిన మార్పులన్నీ పోతాయి.',
 'yourdiff' => 'తేడాలు',
-'copyrightwarning' => "{{SITENAME}}కు సమర్పించే అన్ని రచనలూ $2కు లోబడి ప్రచురింపబడినట్లుగా భావించబడతాయి (వివరాలకు $1 చూడండి). మీ రచనలను ఎవ్వరూ మార్చ రాదనీ లెదా వేరే ఎవ్వరూ వాడుకో రాదని మీరు భావిస్తే, ఇక్కడ ప్రచురించకండి.<br /> మీ స్వీయ రచనను గాని, సార్వజనీనమైన రచననుగాని, ఇతర ఉచిత వనరుల నుండి సేకరించిన రచననుగాని మాత్రమే ప్రచురిస్తున్నానని కూడా మీరు ప్రమాణం చేస్తున్నారు. '''కాపీహక్కులుగల రచనను తగిన అనుమతి లేకుండా సమర్పించకండి!'''",
+'copyrightwarning' => '{{SITENAME}}కు సమర్పించే అన్ని రచనలూ $2కు లోబడి ప్రచురింపబడినట్లుగా భావించబడతాయి (వివరాలకు $1 చూడండి). మీ రచనలను ఎవ్వరూ మార్చ రాదనీ లెదా వేరే ఎవ్వరూ వాడుకో రాదని మీరు భావిస్తే, ఇక్కడ ప్రచురించకండి.<br /> మీ స్వీయ రచనను గాని, సార్వజనీనమైన రచననుగాని, ఇతర ఉచిత వనరుల నుండి సేకరించిన రచననుగాని మాత్రమే ప్రచురిస్తున్నానని కూడా మీరు ప్రమాణం చేస్తున్నారు. <strong>కాపీహక్కులుగల రచనను తగిన అనుమతి లేకుండా సమర్పించకండి!</strong>',
 'copyrightwarning2' => "{{SITENAME}}లో ప్రచురించే రచనలన్నిటినీ ఇతర రచయితలు సరిదిద్దడం, మార్చడం, తొలగించడం చేసే అవకాశం ఉంది. మీ రచనలను అలా నిర్దాక్షిణ్యంగా దిద్దుబాట్లు చెయ్యడం మీకిష్టం లేకపోతే, వాటిని ఇక్కడ ప్రచురించకండి. <br />
 ఈ రచనను మీరే చేసారని, లేదా ఏదైనా సార్వజనిక వనరు నుండి కాపీ చేసి తెచ్చారని, లేదా అలాంటి ఉచిత, స్వేచ్ఛా వనరు నుండి తెచ్చారని మాకు వాగ్దానం చేస్తున్నారు. (వివరాలకు $1 చూడండి).
 '''తగు అనుమతులు లేకుండా కాపీ హక్కులు గల రచనలను సమర్పించకండి!'''",
-'longpageerror' => "'''పొరపాటు: మీరు సమర్పించిన పాఠ్యం, గరిష్ఠ పరిమితి అయిన {{PLURAL:$2|ఒక కిలోబైటుని|$2 కిలోబైట్లను}} మించి {{PLURAL:$1|ఒక కిలోబైటు|$1 కిలోబైట్ల}} పొడవుంది.'''
- దీన్ని భద్రపరచలేము.",
+'longpageerror' => '<strong>లోపం: మీరు సమర్పించిన పాఠ్యం {{PLURAL:$1|ఒక కిలోబైటు|$1 కిలోబైట్ల}} నిడివి కలిగి ఉంది. ఇది గరిష్ఠ పరిమితి అయిన {{PLURAL:$2|ఒక కిలోబైటుని|$2 కిలోబైట్లను}} మించింది.</strong>
+ దీన్ని భద్రపరచలేము.',
 'readonlywarning' => '<strong>హెచ్చరిక: నిర్వహణ కొరకు డేటాబేసుకి తాళం వేసారు. కాబట్టి మీ మార్పుచేర్పులను ఇప్పుడు భద్రపరచలేరు.</strong> 
 మీ మార్పులను ఒక ఫాఠ్య ఫైలులోకి కాపీ చేసి భద్రపరచుకొని, తరువాత సమర్పించండి.
 
 తాళం వేసిన నిర్వాహకుడి వివరణ ఇదీ: $1',
-'protectedpagewarning' => "'''హెచ్చరిక: ఈ పేజీ సంరక్షించబడినది, కనుక నిర్వాహక అనుమతులు ఉన్న వాడుకరులు మాత్రమే మార్చగలరు.'''
-à°\9aివరి à°\9aà°¿à°\9fà±\8dà°\9fà°¾ à°ªà°¦à±\8dà°¦à±\81ని à°®à±\80 à°¸à°®à°¾à°\9aారà°\82 à°\95à±\8bà°¸à°\82 à°\87à°\95à±\8dà°\95à°¡ à°\87à°¸à±\8dà°¤à±\81à°¨à±\8dనాà°\82:",
-'semiprotectedpagewarning' => "'''గమనిక:''' నమోదయిన వాడుకరులు మాత్రమే మార్పులు చెయ్యగలిగేలా ఈ పేజీకి సంరక్షించారు.
-à°®à±\80 à°¸à°®à°¾à°\9aారà°\82 à°\95à±\8bà°¸à°\82 à°\9aివరి à°\9aà°¿à°\9fà±\8dà°\9fà°¾ à°ªà°¦à±\8dà°¦à±\81ని à°\87à°\95à±\8dà°\95à°¡ à°\87à°¸à±\8dà°¤à±\81à°¨à±\8dనాà°\82:",
+'protectedpagewarning' => '<strong>హెచ్చరిక: ఈ పేజీ సంరక్షించబడింది. కాబట్టి నిర్వాహక అనుమతులు ఉన్న వాడుకరులు మాత్రమే మార్చగలరు.</strong>
+à°\9aివరి à°²à°¾à°\97à±\8d à°ªà°¦à±\8dà°¦à±\81à°¨à±\81 à°®à±\80 à°¸à°®à°¾à°\9aారà°\82 à°\95à±\8bà°¸à°\82 à°\87à°\95à±\8dà°\95à°¡ à°\87à°¸à±\8dà°¤à±\81à°¨à±\8dనాà°\82:',
+'semiprotectedpagewarning' => '<strong>గమనిక:</strong> నమోదయిన వాడుకరులు మాత్రమే మార్పులు చెయ్యగలిగేలా ఈ పేజీకి సంరక్షించారు.
+à°®à±\80 à°¸à°®à°¾à°\9aారà°\82 à°\95à±\8bà°¸à°\82 à°\9aివరి à°²à°¾à°\97à±\8d à°ªà°¦à±\8dà°¦à±\81ని à°\87à°\95à±\8dà°\95à°¡ à°\87à°¸à±\8dà°¤à±\81à°¨à±\8dనాà°\82:',
 'cascadeprotectedwarning' => "'''హెచ్చరిక:''' ఈ పేజీ, కాస్కేడింగు రక్షణలో ఉన్న కింది {{PLURAL:$1|పేజీ|పేజీల్లో}} ఇంక్లూడు అయి ఉంది కాబట్టి, నిర్వాహకులు తప్ప ఇతరులు దిద్దుబాటు చేసే వీలు లేకుండా పేజీని లాకు చేసాం:",
 'titleprotectedwarning' => "హెచ్చరిక:  ఈ పేజీని సంరక్షించారు కాబట్టి దీన్ని సృష్టించడానికి [[Special:ListGroupRights|ప్రత్యేక హక్కులు]] ఉండాలి.'''
 మీ సమాచారం కోసం చివరి చిట్టా పద్దుని ఇక్కడ ఇస్తున్నాం:",
@@ -947,7 +948,7 @@ $2
 'nocreatetext' => '{{SITENAME}}లో కొత్త పేజీలు సృష్టించడాన్ని నియంత్రించారు.
 మీరు వెనక్కి వెళ్ళి వేరే పేజీలు మార్చవచ్చు, లేదా [[Special:UserLogin|లోనికి ప్రవేశించండి లేదా ఖాతా సృష్టించుకోండి]].',
 'nocreate-loggedin' => 'కొత్త పేజీలను సృష్టించేందుకు మీకు అనుమతి లేదు.',
-'sectioneditnotsupported-title' => 'విభాà°\97à°ªà±\81 à°¦à°¿à°¦à±\8dదిబాà°\9fà±\8dà°²à°\95à°¿ à°¤à±\8aడ్పాటు లేదు',
+'sectioneditnotsupported-title' => 'విభాà°\97à°ªà±\81 à°¦à°¿à°¦à±\8dà°¦à±\81బాà°\9fà±\8dà°²à°\95à±\81 à°¤à±\8bడ్పాటు లేదు',
 'sectioneditnotsupported-text' => 'ఈ పేజీలో విభాగాల దిద్దుబాటుకి తోడ్పాటు లేదు.',
 'permissionserrors' => 'అనుమతి లోపం',
 'permissionserrorstext' => 'కింద పేర్కొన్న {{PLURAL:$1|కారణం|కారణాల}} మూలంగా, ఆ పని చెయ్యడానికి మీకు అనుమతిలేదు:',
@@ -963,14 +964,14 @@ $2
 అది ఎటువంటి వివరణా ఇవ్వలేదు.',
 'edit-gone-missing' => 'పేజీని మార్చలేము.
 దీన్ని తొలగించినట్టున్నారు.',
-'edit-conflict' => 'మారà±\8dà°ªà±\81 à°¸à°\82ఘర్షణ.',
+'edit-conflict' => 'దిదà±\8dà°¦à±\81బాà°\9fà±\81 ఘర్షణ.',
 'edit-no-change' => 'పాఠ్యంలో ఏమీ మార్పులు లేవు గనక, మీ మార్పుని పట్టించుకోవట్లేదు.',
 'postedit-confirmation' => 'మీ మార్పు భద్రమయ్యింది.',
 'edit-already-exists' => 'కొత్త పేజీని సృష్టించలేము.
 అది ఇప్పటికే ఉంది.',
 'defaultmessagetext' => 'అప్రమేయ సందేశపు పాఠ్యం',
 'content-failed-to-parse' => '$1 మోడల్ కొరకు $2 పాఠ్యాన్ని పార్స్ చెయ్యలేకపోయాం: $3',
-'invalid-content-data' => 'తపà±\8dà°ªà±\81à°¡à±\81 à°µà°¿à°·à°¯à°\82',
+'invalid-content-data' => 'à°\9aà±\86à°²à±\8dలని à°\95à°\82à°\9fà±\86à°\82à°\9fà±\81 à°¡à±\87à°\9fà°¾',
 'content-not-allowed-here' => '[[$2]] పేజీలో పాఠ్యం "$1" కి అనుమతి లేదు',
 'editwarning-warning' => 'ఈ పేజీని వదిలివెళ్ళడం వల్ల మీరు చేసిన మార్పులను కోల్పోయే అవకాశం ఉంది.
 మీరు లాగిన్ అయివుంటే, ఈ హెచ్చరికని మీ అభిరుచులలోని "{{int:prefs-editing}}"  విభాగంలో అచేతనం చేసుకోవచ్చు.',
@@ -1018,8 +1019,8 @@ $3 ఇచ్చిన కారణం: ''$2''",
 'viewpagelogs' => 'ఈ పేజీకి సంబంధించిన లాగ్‌లను చూడండి',
 'nohistory' => 'ఈ పేజీకి మార్పుల చరిత్ర లేదు.',
 'currentrev' => 'ప్రస్తుతపు సంచిక',
-'currentrev-asof' => '$1 à°¨à°¾à°\9fà°¿ à°ªà±\8dà°°à°¸à±\8dà°¤à±\81à°¤ కూర్పు',
-'revisionasof' => '$1 à°¨à°¾à°\9fà°¿ à°¸à°\82à°\9aà°¿à°\95',
+'currentrev-asof' => '$1 à°¨à°¾à°\9fà°¿ à°\9aà°¿à°\9fà±\8dà°\9fà°\9aివరి కూర్పు',
+'revisionasof' => '$1 à°¨à°¾à°\9fà°¿ à°\95à±\82à°°à±\8dà°ªà±\81',
 'revision-info' => '$1 నాటి కూర్పు. రచయిత: $2',
 'previousrevision' => '← పాత కూర్పు',
 'nextrevision' => 'దీని తరువాతి సంచిక→',
@@ -1033,15 +1034,15 @@ $3 ఇచ్చిన కారణం: ''$2''",
 సూచిక: (ప్రస్తుత) = ప్రస్తుత సంచికతో కల తేడాలు, (గత) = ఇంతకు ముందరి సంచికతో గల తేడాలు, చి = చిన్న మార్పు',
 'history-fieldset-title' => 'చరిత్రలో చూడండి',
 'history-show-deleted' => 'తొలగించినవి మాత్రమే',
-'histfirst' => 'à°¤à±\8aà°\9fà±\8dà°\9fà°¤à±\8aà°²ి',
-'histlast' => 'à°\9aà°¿à°\9fà±\8dà°\9fà°\9aివరి',
+'histfirst' => 'à°\85తి à°ªà°¾à°¤à°µి',
+'histlast' => 'సరిà°\95à±\8aà°¤à±\8dà°¤',
 'historysize' => '({{PLURAL:$1|ఒక బైటు|$1 బైట్లు}})',
 'historyempty' => '(ఖాళీ)',
 
 # Revision feed
 'history-feed-title' => 'కూర్పుల చరిత్ర',
 'history-feed-description' => 'ఈ పేజీకి వికీలో కూర్పుల చరిత్ర',
-'history-feed-item-nocomment' => '$2 à°µà°¦à±\8dà°¦ à°\89à°¨à±\8dà°¨ $1',
+'history-feed-item-nocomment' => '$2 న $1',
 'history-feed-empty' => 'మీరడిగిన పేజీ లేదు.
 దాన్ని వికీలోంచి తొలగించి ఉండొచ్చు, లేదా పేరు మార్చి ఉండొచ్చు.
 సంబంధిత కొత్త పేజీల కోసం [[Special:Search|వికీలో వెతికి చూడండి]].',
@@ -1076,12 +1077,12 @@ $3 ఇచ్చిన కారణం: ''$2''",
 మీరు ఈ తేడాను చూడవచ్చు; [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} తొలగింపు చిట్టా]లోవివరాలు ఉంటాయి.',
 'rev-suppressed-diff-view' => 'ఈ తేడా లోని ఒక కూర్పును <strong>అణచి పెట్టాం</strong>.
 మీరు ఈ తేడాను చూడవచ్చు; [{{fullurl:{{#Special:Log}}/suppress|page={{FULLPAGENAMEE}}}} అణచివేత చిట్టా]లోవివరాలు ఉంటాయి.',
-'rev-delundel' => 'à°\9aà±\82పిà°\82à°\9aà±\81/దాచు',
+'rev-delundel' => 'à°¦à±\83à°¶à±\8dయతనà±\81 à°®à°¾à°°à±\8dచు',
 'rev-showdeleted' => 'చూపించు',
 'revisiondelete' => 'కూర్పులను తొలగించు/తొలగింపును రద్దుచెయ్యి',
 'revdelete-nooldid-title' => 'తప్పుడు లక్ష్యపు కూర్పు',
 'revdelete-nooldid-text' => 'ఈ పని ఏ కూర్పు లేదా కూర్పుల మీద చెయ్యాలో మీరు సూచించలేదు, లేదా మీరు సూచించిన కూర్పు లేదు, లేదా ప్రస్తుత కూర్పునే దాచాలని ప్రయత్నిస్తున్నారు.',
-'revdelete-no-file' => 'à°\86 à°ªà±\87à°°à±\8dà°\95à±\8aà°¨à±\8dà°¨ à°«à±\88à°²à±\81 à°\89నిà°\95à°¿à°²à±\8b à°²à±\87à°¦à±\81.',
+'revdelete-no-file' => 'పేర్కొన్న ఫైలు ఉనికిలో లేదు.',
 'revdelete-show-file-confirm' => 'మీరు నిజంగానే "<nowiki>$1</nowiki>"  ఫైలు యొక్క $2 $3 నాటి తొలగించిన కూర్పుని చూడాలనుకుంటున్నారా?',
 'revdelete-show-file-submit' => 'అవును',
 'revdelete-selected' => "'''[[:$1]] యొక్క {{PLURAL:$2|ఎంచుకున్న కూర్పు|ఎంచుకున్న కూర్పులు}}:'''",
@@ -1107,9 +1108,9 @@ $3 ఇచ్చిన కారణం: ''$2''",
 'revdelete-unsuppress' => 'పునస్థాపిత కూర్పులపై నిబంధనలను తీసివెయ్యి',
 'revdelete-log' => 'కారణం:',
 'revdelete-submit' => 'ఎంచుకున్న {{PLURAL:$1|కూర్పుకు|కూర్పులకు}} ఆపాదించు',
-'revdelete-success' => "'''కూర్పు కనబడే విధానాన్ని జయప్రదంగా తాజాకరించాం.'''",
-'revdelete-failure' => "'''కూర్పు కనబడే పద్ధతిని తాజాపరచలేకపోయాం:'''
-$1",
+'revdelete-success' => '<strong>కూర్పు కనబడే విధానాన్ని జయప్రదంగా తాజాకరించాం.</strong>',
+'revdelete-failure' => '<strong>కూర్పు కనబడే పద్ధతిని తాజాపరచలేకపోయాం:</strong>
+$1',
 'logdelete-success' => "'''ఘటన కనబడే విధానాన్ని జయప్రదంగా సెట్ చేసాం.'''",
 'logdelete-failure' => "'''చిట్టా కనబడే పద్ధతిని అమర్చలేకపోయాం:'''
 $1",
@@ -1165,20 +1166,20 @@ $1",
 'mergehistory-reason' => 'కారణం:',
 
 # Merge log
-'mergelog' => 'à°µà±\80లీనాల చిట్టా',
+'mergelog' => 'విలీనాల చిట్టా',
 'pagemerge-logentry' => '[[$1]] ను [[$2]] లోకి విలీనం చేసాం ($3 కూర్పు దాకా)',
 'revertmerge' => 'విలీనాన్ని రద్దుచెయ్యి',
 'mergelogpagetext' => 'ఒక పేజీ చరితాన్ని మరో పేజీ చరితం లోకి ఇటీవల చేసిన విలీనాల జాబితా ఇది.',
 
 # Diffs
 'history-title' => '"$1" యొక్క కూర్పుల చరిత్ర',
-'difference-title' => '"$1" à°¯à±\8aà°\95à±\8dà°\95 à°¤à°¿à°°à°¿à°\97à°¿à°\9aà±\82à°ªà±\81à°² à°¨à°¡à±\81à°® తేడాలు',
+'difference-title' => '"$1" à°¯à±\8aà°\95à±\8dà°\95 à°\95à±\82à°°à±\8dà°ªà±\81à°² à°®à°§à±\8dà°¯ తేడాలు',
 'difference-title-multipage' => '"$1" మరియు "$2" పేజీల మధ్య తేడా',
 'difference-multipage' => '(పేజీల మధ్య తేడా)',
 'lineno' => 'పంక్తి $1:',
 'compareselectedversions' => 'ఎంచుకున్న సంచికలను పోల్చిచూడు',
 'showhideselectedversions' => 'ఎంచుకున్న కూర్పులను చూపించు/దాచు',
-'editundo' => 'మారà±\8dà°ªà±\81ని à°°à°¦à±\8dà°¦à±\81à°\9aà±\86à°¯à±\8dయి',
+'editundo' => 'రద్దుచెయ్యి',
 'diff-empty' => '(తేడా లేదు)',
 'diff-multi-sameuser' => '(ఇదే వాడుకరి యొక్క {{PLURAL:$1|ఒక మధ్యంతర కూర్పును|$1 మధ్యంతర కూర్పులను}} చూపించలేదు)',
 'diff-multi-otherusers' => '({{PLURAL:$2|మరో వాడుకరి|$2 వాడుకరుల}} యొక్క {{PLURAL:$1|ఒక మధ్యంతర కూర్పును|$1 మధ్యంతర కూర్పులను}} చూపించలేదు)',
@@ -1189,13 +1190,13 @@ $1",
 [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} తొలగింపు లాగ్] లో వివరాలు ఉంటాయి.',
 
 # Search results
-'searchresults' => 'à°µà±\86à°¦ుకులాట ఫలితాలు',
-'searchresults-title' => '"$1"కి అన్వేషణ ఫలితాలు',
+'searchresults' => 'à°µà±\86à°¤ుకులాట ఫలితాలు',
+'searchresults-title' => '"$1" కి వెతుకులాట ఫలితాలు',
 'toomanymatches' => 'చాలా పోలికలు వచ్చాయి, దయచేసి మరో ప్రశ్నని ప్రయత్నించండి',
 'titlematches' => 'వ్యాస శీర్షిక సరిపోయింది',
 'textmatches' => 'పేజిలోని పాఠం సరిపోలింది',
 'notextmatches' => 'పేజీ పాఠ్యమేదీ సరిపోలడం లేదు',
-'prevn' => 'à°\95à±\8dà°°à°¿à°¤à°\82 {{PLURAL:$1|$1}}',
+'prevn' => 'à°\97à°¤ {{PLURAL:$1|$1}}',
 'nextn' => 'తరువాతి {{PLURAL:$1|$1}}',
 'prevn-title' => 'గత $1 {{PLURAL:$1|ఫలితం|ఫలితాలు}}',
 'nextn-title' => 'తరువాతి $1 {{PLURAL:$1|ఫలితం|ఫలితాలు}}',
@@ -1234,7 +1235,7 @@ $1",
 'powersearch-legend' => 'నిశితమైన అన్వేషణ',
 'powersearch-ns' => 'ఈ పేరుబరుల్లో వెతుకు:',
 'powersearch-redir' => 'దారిమార్పులను చూపించు',
-'powersearch-togglelabel' => 'à°\8eà°\82à°\9aà±\81à°\95à±\8bవాలà±\8dసినవి:',
+'powersearch-togglelabel' => 'à°\8eà°\82à°\9aà±\81à°\95à±\8bà°\82à°¡ి:',
 'powersearch-toggleall' => 'అన్నీ',
 'powersearch-togglenone' => 'ఏదీకాదు',
 'search-external' => 'బయటి అన్వేషణ',
@@ -1246,37 +1247,37 @@ $1",
 'mypreferences' => 'అభిరుచులు',
 'prefs-edits' => 'దిద్దుబాట్ల సంఖ్య:',
 'prefsnologintext2' => 'మీ అభిరుచులను మార్చుకునేందుకు $1.',
-'prefs-skin' => 'à°\85à°²à°\82à°\95ారà°\82',
-'skin-preview' => 'à°®à±\81à°¨à±\81à°\9cà±\82à°ªà±\81/సరిà°\9aà±\82à°¡à±\81',
+'prefs-skin' => 'à°°à±\82à°ªà±\81',
+'skin-preview' => 'మునుజూడు',
 'datedefault' => 'ఏదైనా పరవాలేదు',
 'prefs-beta' => 'బీటా సౌలభ్యాలు',
 'prefs-datetime' => 'తేదీ, సమయం',
 'prefs-labs' => 'ప్రయోగాత్మక సౌలభ్యాలు',
 'prefs-user-pages' => 'వాడుకరి పేజీలు',
-'prefs-personal' => 'వాడà±\81à°\95à°°à°¿ à°µà°¿à°µà°°à°¾à°²à±\81',
+'prefs-personal' => 'వాడà±\81à°\95à°°à°¿ à°ªà±\8dరవర',
 'prefs-rc' => 'ఇటీవలి మార్పులు',
 'prefs-watchlist' => 'వీక్షణ జాబితా',
 'prefs-watchlist-days' => 'వీక్షణ జాబితాలో చూపించవలసిన రోజులు:',
-'prefs-watchlist-days-max' => '$1 {{PLURAL:$1|రోజు|రోజులు}} గరిష్ఠం',
+'prefs-watchlist-days-max' => 'గరిష్ఠంగా $1 {{PLURAL:$1|రోజు|రోజులు}}',
 'prefs-watchlist-edits' => 'విస్తృత వీక్షణ జాబితాలో చూపించవలసిన దిద్దుబాట్లు:',
 'prefs-watchlist-edits-max' => 'గరిష్ఠ సంఖ్య: 1000',
 'prefs-watchlist-token' => 'వీక్షణాజాబితా టోకెను:',
-'prefs-misc' => 'à°\87తరాలà±\81',
+'prefs-misc' => 'à°\87తరతà±\8dà°°à°¾',
 'prefs-resetpass' => 'సంకేతపదాన్ని మార్చుకోండి',
 'prefs-changeemail' => 'ఈ-మెయిలు చిరునామా మార్పు',
-'prefs-setemail' => 'à°\92à°\95 à°\88-à°®à±\86యిలà±\8d à°\9aà°¿à°°à±\81నామాని à°\85మరà±\8dà°\9aండి',
+'prefs-setemail' => 'à°\93 à°\88à°®à±\86యిలà±\8d à°\9aà°¿à°°à±\81నామా à°\87à°µà±\8dà°µండి',
 'prefs-email' => 'ఈ-మెయిల్ ఎంపికలు',
 'prefs-rendering' => 'రూపురేఖలు',
 'saveprefs' => 'భద్రపరచు',
 'restoreprefs' => 'అప్రమేయ అమరికలను పునఃస్థాపించు (అన్ని విభాగాల్లోనూ)',
-'prefs-editing' => 'మారà±\8dà°ªà±\81à°²ు',
-'rows' => 'వరà±\81సలà±\81',
-'columns' => 'వరుసలు:',
-'searchresultshead' => 'à°\85à°¨à±\8dà°µà±\87à°·à°£',
+'prefs-editing' => 'సవరిసà±\8dà°¤à±\81à°¨à±\8dనారు',
+'rows' => 'à°\85à°¡à±\8dà°¡à±\81 à°µà°°à±\81సలà±\81:',
+'columns' => 'నిలà±\81à°µà±\81 à°µà°°à±\81సలà±\81:',
+'searchresultshead' => 'à°µà±\86à°¤à±\81à°\95à±\81',
 'stub-threshold' => '<a href="#" class="stub">మొలక లింకు</a> ఫార్మాటింగు కొరకు హద్దు (బైట్లు):',
 'stub-threshold-disabled' => 'అచేతనం',
 'recentchangesdays' => 'ఇటీవలి మార్పులు లో చూపించవలసిన రోజులు:',
-'recentchangesdays-max' => '($1 {{PLURAL:$1|రోజు|రోజులు}} గరిష్ఠం)',
+'recentchangesdays-max' => 'గరిష్ఠంగా $1 {{PLURAL:$1|రోజు|రోజులు}}',
 'recentchangescount' => 'అప్రమేయంగా చూపించాల్సిన దిద్దుబాట్ల సంఖ్య:',
 'prefs-help-recentchangescount' => 'ఇది ఇటీవలి మార్పులు, పేజీ చరిత్రలు, మరియు చిట్టాలకు వర్తిస్తుంది.',
 'prefs-help-watchlist-token2' => 'మీ వీక్షణజాబితా యొక్క జాలవడ్డింపుకు చెందిన రహస్య తాళమిది.
@@ -1295,7 +1296,7 @@ $1",
 'timezoneregion-arctic' => 'ఆర్కిటిక్',
 'timezoneregion-asia' => 'ఆసియా',
 'timezoneregion-atlantic' => 'అట్లాంటిక్ మహాసముద్రం',
-'timezoneregion-australia' => 'à°\86à°·్ట్రేలియా',
+'timezoneregion-australia' => 'à°\86à°¸్ట్రేలియా',
 'timezoneregion-europe' => 'ఐరోపా',
 'timezoneregion-indian' => 'హిందూ మహాసముద్రం',
 'timezoneregion-pacific' => 'పసిఫిక్ మహాసముద్రం',
@@ -1307,10 +1308,10 @@ $1",
 'prefs-files' => 'ఫైళ్ళు',
 'prefs-custom-css' => 'ప్రత్యేక CSS',
 'prefs-custom-js' => 'ప్రత్యేక JS',
-'prefs-common-css-js' => 'à°\85à°¨à±\8dని à°\85à°²à°\82à°\95ారాలà°\95à±\88 à°ªà°\82à°\9aà±\81à°\95à±\8bబడిన CSS/JS:',
+'prefs-common-css-js' => 'à°\85à°¨à±\8dని à°°à±\82à°ªà±\81లలà±\8bà°¨à±\82 à°\89à°¨à±\8dన CSS/JS:',
 'prefs-reset-intro' => 'ఈ పేజీలో, మీ అభిరుచులను సైటు డిఫాల్టు విలువలకు మార్చుకోవచ్చు. మళ్ళీ వెనక్కి తీసుకుపోలేరు.',
 'prefs-emailconfirm-label' => 'ఈ-మెయిల్ నిర్ధారణ:',
-'youremail' => 'à°®à±\80 à°\88-à°®à±\86యిలà±\81*',
+'youremail' => 'à°\88à°®à±\86యిలà±\81:',
 'username' => '{{GENDER:$1|వాడుకరి పేరు}}:',
 'uid' => '{{GENDER:$1|వాడుకరి}} ID:',
 'prefs-memberingroups' => 'ఈ {{PLURAL:$1|గుంపులో|గుంపులలో}} {{GENDER:$2|సభ్యుడు|సభ్యురాలు}}:',
@@ -1319,12 +1320,12 @@ $1",
 'yourlanguage' => 'భాష:',
 'yourvariant' => 'విషయపు భాషా వైవిధ్యం:',
 'prefs-help-variant' => 'ఈ వికీ లోని విషయపు పేజీలను చూపించడానికి మీ అభిమత వైవిధ్యం లేదా ఆర్ధోగ్రఫీ.',
-'yournick' => 'à°®à±\81à°¦à±\8dà°¦à±\81 à°ªà±\87à°°à±\81',
+'yournick' => 'à°\95à±\8aà°¤à±\8dà°¤ à°¸à°\82à°¤à°\95à°\82:',
 'prefs-help-signature' => 'చర్చా పేజీల లోని వ్యాఖ్యలకు "<nowiki>~~~~</nowiki>"తో సంతకం చేస్తే అది మీ సంతకం మరియు కాలముద్రగా మారుతుంది.',
 'badsig' => 'సంతకాన్ని సరిగ్గా ఇవ్వలేదు; HTML ట్యాగులను ఒకసారి పరిశీలించండి.',
 'badsiglength' => 'మీ సంతకం చాలా పెద్దగా ఉంది.
 ఇది తప్పనిసరిగా $1 {{PLURAL:$1|అక్షరం|అక్షరాల}} లోపులోనే ఉండాలి.',
-'yourgender' => 'మిమà±\8dమలà±\8dని à°\8eలా à°¸à°\82à°¬à±\8bధిà°\82à°\9aడానిà°\95à°¿ à°\87à°·à±\8dà°\9fపడతారు?',
+'yourgender' => 'మిమà±\8dమలà±\8dని à°®à±\80à°°à±\81 à°\8eలా à°µà°°à±\8dణిà°\82à°\9aà±\81à°\95à±\81à°\82à°\9fారు?',
 'gender-unknown' => 'వెల్లడించడానికి నేను ఇష్టపడట్లేదు',
 'gender-male' => 'అతను వికీ పేజీలను సరిదిద్దుతాడు',
 'gender-female' => 'ఆమె వికీ పేజీలను సరిదిద్దుతుంది',
@@ -1332,18 +1333,19 @@ $1",
 మిమ్మల్ని సంబోధించేప్పుడూ మిమ్మల్ని పేర్కొనేప్పుడూ వ్యాకరణపరంగా సరైన లింగాన్ని  వాడటానికి ఈ విలువ ఉపయోగపడుతుంది.
 ఈ సమాచారం బహిరంగం.',
 'email' => 'ఈ-మెయిలు',
-'prefs-help-realname' => 'అసలు పేరు (తప్పనిసరి కాదు), మీ అసలు పేరు ఇస్తేగనక, మీ రచనలన్నీ మీ అసలు పేరుతోనే గుర్తిస్తూ ఉంటారు.',
+'prefs-help-realname' => 'అసలు పేరు తప్పనిసరి కాదు. 
+అసలు పేరు ఇస్తే, మీ రచనల శ్రేయస్సు మీ అసలు పేరుకే ఆపాదించబడుతుంది.',
 'prefs-help-email' => 'ఈ-మెయిలు చిరునామా ఐచ్చికం, కానీ మీరు సంకేతపదాన్ని మర్చిపోతే కొత్త సంకేతపదాన్ని మీకు పంపించడానికి అవసరమవుతుంది.',
 'prefs-help-email-others' => 'మీ వాడుకరి లేదా చర్చా పేజీలలో ఉండే లంకె ద్వారా ఇతరులు మిమ్మల్ని ఈ-మెయిలు ద్వారా సంప్రదించే వీలుకల్పించవచ్చు.
 ఇతరులు మిమ్మల్ని సంప్రదించినప్పుడు మీ ఈ-మెయిలు చిరునామా బహిర్గతమవదు.',
 'prefs-help-email-required' => 'ఈ-మెయిలు చిరునామా తప్పనిసరి.',
 'prefs-info' => 'ప్రాథమిక సమాచారం',
-'prefs-i18n' => 'అంతర్జాతీకరణ',
+'prefs-i18n' => 'à°\85à°\82తరà±\8dà°\9cాతà±\80à°¯à°\95à°°à°£',
 'prefs-signature' => 'సంతకం',
 'prefs-dateformat' => 'తేదీ ఆకృతి',
-'prefs-timeoffset' => 'సమయ సవరణ',
+'prefs-timeoffset' => 'సమయపు తేడా',
 'prefs-advancedediting' => 'సాధారణ ఎంపికలు',
-'prefs-editor' => 'à°\95à±\82à°°à±\8dపరి',
+'prefs-editor' => 'à°°à°\9aయిత',
 'prefs-preview' => 'మునుజూపు',
 'prefs-advancedrc' => 'ఉన్నత ఎంపికలు',
 'prefs-advancedrendering' => 'ఉన్నత ఎంపికలు',
@@ -1363,8 +1365,8 @@ $1",
 
 # User rights
 'userrights' => 'వాడుకరి హక్కుల నిర్వహణ',
-'userrights-lookup-user' => 'వాడà±\81à°\95à°°à°¿ à°¸à°®à±\82హాలనà±\81 à°¸à°\82భాళించండి',
-'userrights-user-editname' => 'సభà±\8dయనామానà±\8dని ఇవ్వండి:',
+'userrights-lookup-user' => 'వాడà±\81à°\95à°°à°¿ à°¸à°®à±\82హాలనà±\81 à°¨à°¿à°°à±\8dవహించండి',
+'userrights-user-editname' => 'వాడà±\81à°\95à°°à°¿à°ªà±\87à°°à±\81à°¨à±\81 ఇవ్వండి:',
 'editusergroup' => 'వాడుకరి గుంపులను మార్చు',
 'editinguser' => "వాడుకరి '''[[User:$1|$1]]''' $2 యొక్క వాడుకరి హక్కులను మారుస్తున్నారు",
 'userrights-editusergroup' => 'వాడుకరి సమూహాలను మార్చండి',
@@ -1546,11 +1548,23 @@ $1",
 'rcnotefrom' => '<b>$2</b> నుండి జరిగిన మార్పులు (<b>$1</b> వరకు చూపబడ్డాయి).',
 'rclistfrom' => '$1 నుండి జరిగిన మార్పులను చూపించు',
 'rcshowhideminor' => 'చిన్న మార్పులను $1',
+'rcshowhideminor-show' => 'చూపించు',
+'rcshowhideminor-hide' => 'దాచు',
 'rcshowhidebots' => 'బాట్లను $1',
+'rcshowhidebots-show' => 'చూపించు',
+'rcshowhidebots-hide' => 'దాచు',
 'rcshowhideliu' => 'నమోదైన వాడుకరులను $1',
+'rcshowhideliu-show' => 'చూపించు',
+'rcshowhideliu-hide' => 'దాచు',
 'rcshowhideanons' => 'అజ్ఞాత వాడుకరులను $1',
+'rcshowhideanons-show' => 'చూపించు',
+'rcshowhideanons-hide' => 'దాచు',
 'rcshowhidepatr' => 'నిఘాలో ఉన్న మార్పులను $1',
+'rcshowhidepatr-show' => 'చూపించు',
+'rcshowhidepatr-hide' => 'దాచు',
 'rcshowhidemine' => 'నా మార్పులను $1',
+'rcshowhidemine-show' => 'చూపించు',
+'rcshowhidemine-hide' => 'దాచు',
 'rclinks' => 'గత  $2 రోజుల లోని చివరి $1 మార్పులను చూపించు <br />$3',
 'diff' => 'తేడాలు',
 'hist' => 'చరిత్ర',
@@ -1571,9 +1585,9 @@ $1",
 # Recent changes linked
 'recentchangeslinked' => 'సంబంధిత మార్పులు',
 'recentchangeslinked-feed' => 'సంబంధిత మార్పులు',
-'recentchangeslinked-toolbox' => 'à°ªà±\8aà°\82తనà°\97à°² మార్పులు',
+'recentchangeslinked-toolbox' => 'à°¸à°\82à°¬à°\82ధిత మార్పులు',
 'recentchangeslinked-title' => '$1 కు సంబంధించిన మార్పులు',
-'recentchangeslinked-summary' => "దీనికి లింకై ఉన్న పేజీల్లో జరిగిన చివరి మార్పులు ఇక్కడ చూడవచ్చు. మీ వీక్షణ జాబితాలో ఉన్న పేజీలు '''బొద్దు'''గా ఉంటాయి.",
+'recentchangeslinked-summary' => 'ఏదైనా పేజీకి లింకై ఉన్న పేజీల్లో (లేదా ఏదైనా వర్గంలోని పేజీల్లో) జరిగిన ఇటీవలి మార్పుల జాబితా ఇది.  [[Special:Watchlist|మీ వీక్షణ జాబితా]]లో ఉన్న పేజీలు <strong>బొద్దు</strong>గా ఉంటాయి.',
 'recentchangeslinked-page' => 'పేజీ పేరు:',
 'recentchangeslinked-to' => 'ఇచ్చిన పేజీకి లింకయివున్న పేజీలలో జరిగిన మార్పులను చూపించు',
 
@@ -1675,6 +1689,7 @@ $1",
 'php-uploaddisabledtext' => 'PHPలో ఫైలు ఎక్కింపులు అచేతనమై ఉన్నాయి.
 దయచేసి file_uploads అమరికని చూడండి.',
 'uploadscripted' => 'ఈ ఫైల్లో HTML కోడు గానీ స్క్రిప్టు కోడు గానీ ఉంది. వెబ్ బ్రౌజరు దాన్ని పొరపాటుగా అనువదించే అవకాశం ఉంది.',
+'uploadinvalidxml' => 'ఎక్కించిన ఫైలులోని XML ను పార్సు చెయ్యలేకపోయాం.',
 'uploadvirus' => 'ఈ ఫైలులో వైరస్‌ ఉంది! వివరాలు: $1',
 'uploadjava' => 'ఇదొక ZIP ఫైలు, ఇందులో ఒక Java .class ఫైలు ఉంది.
 Java ఫైళ్ళ వలన భద్రతకు తూట్లు పడే అవకాశం ఉంది కాబట్టి, వాటిని ఎక్కించడానికి అనుమతి లేదు.',
@@ -1849,8 +1864,8 @@ https://www.mediawiki.org/wiki/Manual:Image_Authorization చూడండి.',
 'sharedupload' => 'ఈ ఫైలు $1 నుండి మరియు దీనిని ఇతర ప్రాజెక్టులలో కూడా ఉపయోగిస్తూవుండవచ్చు.',
 'sharedupload-desc-there' => 'ఈ ఫైలు $1 నుండి వచ్చింది అలానే ఇతర ప్రాజెక్టులలో కూడా ఉపయోగిస్తూ ఉండవచ్చు.
 మరింత సమాచారం కోసం, దయచేసి [$2 ఫైలు వివరణ పేజీ]ని చూడండి.',
-'sharedupload-desc-here' => 'à°\88 à°«à±\88à°²à±\81 $1 à°¨à±\81à°\82à°¡à°¿ à°®à°°à°¿à°¯à±\81 à°¦à±\80నిని à°\87తర à°ªà±\8dà°°à°¾à°\9cà±\86à°\95à±\8dà°\9fà±\81లలà±\8b కూడా ఉపయోగిస్తూ ఉండవచ్చు.
-à°¦à±\80ని [$2 à°«à±\88à°²à±\81 à°µà°¿à°µà°°à°£ à°ªà±\87à°\9cà±\80] à°²à±\8b à°\89à°¨à±\8dà°¨ à°µà°¿à°µà°°à°£à°¨à°¿ à°\95à±\8dà°°ింద చూపించాం.',
+'sharedupload-desc-here' => 'à°\88 à°«à±\88à°²à±\81 $1 à°²à±\8bనిది. à°¦à±\80నిని à°\87తర à°ªà±\8dà°°à°¾à°\9cà±\86à°\95à±\8dà°\9fà±\81à°²à±\81 కూడా ఉపయోగిస్తూ ఉండవచ్చు.
+à°\85à°\95à±\8dà°\95à°¡ à°¦à±\80ని [$2 à°«à±\88à°²à±\81 à°µà°¿à°µà°°à°£ à°ªà±\87à°\9cà±\80] à°²à±\8b à°\89à°¨à±\8dà°¨ à°µà°¿à°µà°°à°£à°¨à°¿ à°\95ింద చూపించాం.',
 'sharedupload-desc-edit' => 'ఈ ఫైలు $1 లోనిది. దాన్ని ఇతర ప్రాజెక్టులు కూడా వాడుతూ ఉండి ఉండవచ్చు.
 దాని [$2 ఫైలు వివరణ పేజీ] లోని వివరణను మారుస్తారేమో చూడండి.',
 'sharedupload-desc-create' => 'ఈ ఫైలు $1 లోనిది. దాన్ని ఇతర ప్రాజెక్టులు కూడా వాడుతూ ఉండి ఉండవచ్చు.
@@ -2447,7 +2462,7 @@ $1',
 # Contributions
 'contributions' => '{{GENDER:$1|వాడుకరి}} రచనలు',
 'contributions-title' => '$1 యొక్క మార్పులు-చేర్పులు',
-'mycontris' => 'మారà±\8dà°ªà±\81à°²à±\81 à°\9aà±\87à°°à±\8dà°ªà±\81à°²à±\81',
+'mycontris' => 'మార్పుచేర్పులు',
 'contribsub2' => '{{GENDER:$3|$1}} ($2) కొరకు',
 'nocontribs' => 'ఈ విధమైన మార్పులేమీ దొరకలేదు.',
 'uctop' => '(ప్రస్తుత)',
@@ -2473,7 +2488,7 @@ $1',
 'sp-contributions-submit' => 'వెతుకు',
 
 # What links here
-'whatlinkshere' => 'à°\87à°\95à±\8dà°\95à°¡à°¿à°\95à°¿ à°²à°\82à°\95à±\86à°²à±\81à°¨à±\8dనవి',
+'whatlinkshere' => 'à°\87à°\95à±\8dà°\95à°¡à°¿à°\95à°¿ à°²à°¿à°\82à°\95à±\88నవి',
 'whatlinkshere-title' => '"$1"కి లింకున్న పుటలు',
 'whatlinkshere-page' => 'పేజీ:',
 'linkshere' => "కిందనున్న పేజీల నుండి '''[[:$1]]'''కు లింకులు ఉన్నాయి:",
@@ -2638,15 +2653,14 @@ $1 ను నిరోధించడానికి కారణం: "$2"',
 'movepagetext' => "కింది ఫారం ఉపయోగించి, ఓ పేజీ పేరు మార్చవచ్చు. దాంతో పాటు దాని చరిత్ర అంతా కొత్త పేజీ చరిత్రగా మారుతుంది.
 పాత పేజీ కొత్త దానికి దారిమార్పు పేజీ అవుతుంది.
 పాత పేజీకి ఉన్న దారిమార్పు పేజీలను ఆటోమెటిగ్గా సరిచేయవచ్చు.
-à°\86లా à°\9aà±\87యవదà±\8dదనà±\81à°\95à±\81à°\82à°\9fà±\87, [[Special:DoubleRedirects|à°¦à±\8dà°µà°\82à°¦]] à°²à±\87దా [[Special:BrokenRedirects|పనిà°\9aà±\87యని]] à°¦à°¾à°°à°¿à°®à°¾à°°à±\8dà°ªà±\81à°² à°ªà±\87à°\9cà±\80లలో సరిచూసుకోండి.
+à°\86లా à°\9aà±\87యవదà±\8dదనà±\81à°\95à±\81à°\82à°\9fà±\87, [[Special:DoubleRedirects|à°\9cమిలి]] à°²à±\87దా [[Special:BrokenRedirects|పనిà°\9aà±\87యని à°¦à°¾à°°à°¿à°®à°¾à°°à±\8dà°ªà±\81à°²à±\81]] à°\89à°¨à±\8dనాయà±\87à°®ో సరిచూసుకోండి.
 లింకులన్నీ అనుకున్నట్లుగా చేరవలసిన చోటికే చేరుతున్నాయని నిర్ధారించుకోవలసిన బాధ్యత మీదే.
 
 ఒకవేళ కొత్త పేరుతో ఇప్పటికే ఒక పేజీ ఉండి ఉంటే (అది గత మార్పుల చరిత్ర లేని ఖాళీ పేజీనో లేదా దారిమార్పు పేజీనో కాకపోతే) తరలింపు '''జరగదు'''.
-
 అంటే మీరు పొరపాటు చేస్తే కొత్త పేరును మార్చి తిరిగి పాత పేరుకు తీసుకురాగలరు కానీ ఇప్పటికే వున్న పేజీని తుడిచివేయలేరు.
 
-'''హెచ్చరిక!'''
-à°\88 à°®à°¾à°°à±\8dà°ªà±\81 à°¬à°¾à°\97à°¾ à°\9cనరà°\82à°\9cà°\95à°®à±\88à°¨ à°ªà±\87à°\9cà±\80à°²à°\95à±\81 à°\85à°¨à±\82à°¹à±\8dà°¯à°\82 కావచ్చు;
+<strong>హెచ్చరిక!</strong>
+à°\87ది à°\9cనరà°\82à°\9cà°\95à°®à±\88à°¨ à°ªà±\87à°\9cà±\80à°²à°\95à±\81 à°\85à°¨à±\81à°\95à±\8bని, à°¤à±\80à°µà±\8dà°°à°®à±\88à°¨ à°®à°¾à°°à±\8dà°ªà±\81 కావచ్చు;
 దాని పరిణామాలను అర్ధం చేసుకుని ముందుకుసాగండి.",
 'movepagetext-noredirectfixer' => "కింది ఫారాన్ని వాడి, ఓ పేజీ పేరు మార్చవచ్చు. దాని చరిత్ర పూర్తిగా కొత్త పేరుకు తరలిపోతుంది. 
 పాత శీర్షిక కొత్తదానికి దారిమార్పు పేజీగా మారిపోతుంది.
@@ -2850,14 +2864,14 @@ $2',
 'tooltip-pt-anontalk' => 'ఈ ఐపీ చిరునామా నుండి చేసిన మార్పుల గురించి చర్చ',
 'tooltip-pt-preferences' => 'మీ అభిరుచులు',
 'tooltip-pt-watchlist' => 'మీరు మార్పుల కొరకు గమనిస్తున్న పేజీల జాబితా',
-'tooltip-pt-mycontris' => 'మీ మార్పు-చేర్పుల జాబితా',
-'tooltip-pt-login' => 'à°®à±\80à°°à±\81 à°²à±\8bనిà°\95à°¿ à°ªà±\8dà°°à°µà±\87శిà°\82à°\9aడానà±\8dని à°ªà±\8dà°°à±\8bà°¤à±\8dసహిసà±\8dà°¤à±\81à°¨à±\8dనాà°\82; à°\95ానà±\80 à°\85ది à°¤à°ªà±\8dపనిసరి కాదు.',
-'tooltip-pt-logout' => 'నిషà±\8dà°\95à±\8dరమిà°\82à°\9aండి',
-'tooltip-ca-talk' => 'విషయపà±\81 à°ªà±\81à°\9f గురించి చర్చ',
-'tooltip-ca-edit' => 'à°\88 à°ªà±\87à°\9cà±\80ని à°®à±\80à°°à±\81 à°¸à°°à°¿à°¦à°¿à°¦à±\8dదవà°\9aà±\8dà°\9aà±\81. à°¦à°¾à°\9aà±\87ముందు మునుజూపు బొత్తాన్ని వాడండి.',
+'tooltip-pt-mycontris' => 'మీ మార్పుచేర్పుల జాబితా',
+'tooltip-pt-login' => 'మిమà±\8dమలà±\8dని à°²à°¾à°\97ినవమని à°ªà±\8dà°°à±\8bà°¤à±\8dసహిసà±\8dà°¤à±\81à°¨à±\8dనాà°\82; à°\95ానà±\80 à°\85ది à°¤à°ªà±\8dపనిసరà±\87à°®à±\80 కాదు.',
+'tooltip-pt-logout' => 'లాà°\97à±\8cà°\9fà°µండి',
+'tooltip-ca-talk' => 'విషయపà±\81 à°ªà±\87à°\9cà±\80 గురించి చర్చ',
+'tooltip-ca-edit' => 'à°\88 à°ªà±\87à°\9cà±\80ని à°®à±\80à°°à±\81 à°¸à°°à°¿à°¦à°¿à°¦à±\8dదవà°\9aà±\8dà°\9aà±\81. à°­à°¦à±\8dరపరà°\9aà±\87 ముందు మునుజూపు బొత్తాన్ని వాడండి.',
 'tooltip-ca-addsection' => 'కొత్త విభాగాన్ని మొదలుపెట్టండి',
 'tooltip-ca-viewsource' => 'ఈ పుటని సంరక్షించారు. మీరు దీని మూలాన్ని చూడవచ్చు',
-'tooltip-ca-history' => 'à°\88 à°ªà±\81à°\9f యొక్క వెనుకటి కూర్పులు',
+'tooltip-ca-history' => 'à°\88 à°ªà±\87à°\9cà±\80 యొక్క వెనుకటి కూర్పులు',
 'tooltip-ca-protect' => 'ఈ పేజీని సంరక్షించండి',
 'tooltip-ca-unprotect' => 'ఈ పేజీ సంరక్షణను మార్చండి',
 'tooltip-ca-delete' => 'ఈ పేజీని తొలగించండి',
@@ -2868,25 +2882,25 @@ $2',
 'tooltip-search' => '{{SITENAME}} లో వెతకండి',
 'tooltip-search-go' => 'ఇదే పేరుతో పేజీ ఉంటే అక్కడికి తీసుకెళ్ళు',
 'tooltip-search-fulltext' => 'పేజీలలో ఈ పాఠ్యం కొరకు వెతుకు',
-'tooltip-p-logo' => 'à°®à±\8aà°¦à°\9fà°¿ à°ªà±\81à°\9fà°¨à±\81 à°¦à°°à±\8dశిà°\82à°\9aండి',
-'tooltip-n-mainpage' => 'తలపà±\81à°\9fà°¨à±\81 చూడండి',
-'tooltip-n-mainpage-description' => 'à°®à±\8aà°¦à°\9fà°¿ à°ªà±\81à°\9fà°¨à±\81 చూడండి',
+'tooltip-p-logo' => 'à°®à±\8aà°¦à°\9fà°¿ à°ªà±\87à°\9cà±\80 à°\9aà±\82à°¡ండి',
+'tooltip-n-mainpage' => 'à°®à±\8aà°¦à°\9fà°¿ à°ªà±\87à°\9cà±\80 చూడండి',
+'tooltip-n-mainpage-description' => 'à°®à±\8aà°¦à°\9fà°¿ à°ªà±\87à°\9cà±\80 చూడండి',
 'tooltip-n-portal' => 'ప్రాజెక్టు గురించి, మీరేం చేయవచ్చు, సమాచారం ఎక్కడ దొరుకుతుంది',
 'tooltip-n-currentevents' => 'వర్తమాన ఘటనల యొక్క నేపథ్యాన్ని తెలుసుకోండి',
 'tooltip-n-recentchanges' => 'వికీలో ఇటీవల జరిగిన మార్పుల జాబితా.',
 'tooltip-n-randompage' => 'ఓ యాదృచ్చిక పేజీని చూడండి',
-'tooltip-n-help' => 'à°¤à±\86à°²à±\81à°¸à±\81à°\95à±\8bడానిà°\95à°¿ à°\93 à°®à°\82à°\9aà°¿ à°ªà±\8dà°°à°¦à±\87à°¶à°\82.',
-'tooltip-t-whatlinkshere' => 'à°\87à°\95à±\8dà°\95à°¡à°¿à°¤à±\8b à°®à±\81డిపడియà±\81à°¨à±\8dà°¨ à°\85à°¨à±\8dని à°µà°¿à°\95à±\80 à°ªà±\81à°\9fà°² à°²à°\82à°\95à±\86à°²à±\81',
-'tooltip-t-recentchangeslinked' => 'à°\88 à°ªà±\81à°\9fà°\95à±\81 à°®à±\81డివడియà±\81à°¨à±\8dà°¨ à°ªà±\81à°\9fà°²లో జరిగిన ఇటీవలి మార్పులు',
+'tooltip-n-help' => 'à°¨à±\87à°°à±\8dà°\9aà±\81à°\95à±\81à°¨à±\87 à°\9aà±\8bà°\9fà±\81',
+'tooltip-t-whatlinkshere' => 'à°\87à°\95à±\8dà°\95à°¡à°¿à°\95à°¿ à°²à°¿à°\82à°\95à±\88 à°\89à°¨à±\8dà°¨ à°\85à°¨à±\8dని à°µà°¿à°\95à±\80 à°ªà±\87à°\9cà±\80à°² à°\9cాబితా',
+'tooltip-t-recentchangeslinked' => 'à°\88 à°ªà±\87à°\9cà±\80à°\95à°¿ à°²à°¿à°\82à°\95à±\88 à°\89à°¨à±\8dà°¨ à°ªà±\87à°\9cà±\80à°²à±\8dలో జరిగిన ఇటీవలి మార్పులు',
 'tooltip-feed-rss' => 'ఈ పేజీకి RSS ఫీడు',
 'tooltip-feed-atom' => 'ఈ పేజీకి Atom ఫీడు',
 'tooltip-t-contributions' => 'ఈ వాడుకరి యొక్క రచనల జాబితా చూడండి',
 'tooltip-t-emailuser' => 'ఈ వాడుకరికి ఓ ఈమెయిలు పంపండి',
 'tooltip-t-upload' => 'దస్త్రాలను ఎక్కించండి',
 'tooltip-t-specialpages' => 'అన్ని ప్రత్యేక పుటల యొక్క జాబితా',
-'tooltip-t-print' => 'à°\88 à°ªà±\81à°\9f à°¯à±\8aà°\95à±\8dà°\95 à°\85à°\9aà±\8dà°\9aà±\81à°¤à±\80యదà°\97à±\8dà°\97 à°\95à±\82à°°à±\8dపు',
-'tooltip-t-permalink' => 'à°ªà±\81à°\9f యొక్క ఈ కూర్పుకి శాశ్వత లంకె',
-'tooltip-ca-nstab-main' => 'à°®à±\81à°\9aà±\8dà°\9aà°\9fà±\8dà°² à°ªà±\81à°\9fà°¨à±\81 చూడండి',
+'tooltip-t-print' => 'à°\88 à°ªà±\87à°\9cà±\80 à°¯à±\8aà°\95à±\8dà°\95 à°®à±\81à°¦à±\8dరణా à°°à±\82పు',
+'tooltip-t-permalink' => 'à°ªà±\87à°\9cà±\80 యొక్క ఈ కూర్పుకి శాశ్వత లంకె',
+'tooltip-ca-nstab-main' => 'విషయపà±\81 à°ªà±\87à°\9cà±\80ని చూడండి',
 'tooltip-ca-nstab-user' => 'వాడుకరి పేజీని చూడండి',
 'tooltip-ca-nstab-media' => 'మీడియా పేజీని చూడండి',
 'tooltip-ca-nstab-special' => 'ఇది ఒక ప్రత్యేక పుట, దీన్ని మీరు సరిదిద్దలేరు',
@@ -2906,7 +2920,7 @@ $2',
 'tooltip-watchlistedit-raw-submit' => 'వీక్షణ జాబితాను తాజాకరించు',
 'tooltip-recreate' => 'పేజీ తుడిచివేయబడ్డాకానీ మళ్ళీ సృష్టించు',
 'tooltip-upload' => 'ఎగుమతి మొదలుపెట్టు',
-'tooltip-rollback' => '"à°°à°¦à±\8dà°¦à±\81à°\9aà±\87యి" à°\85à°¨à±\87ది à°\88 à°ªà±\87à°\9cà±\80ని à°\9aివరిà°\97à°¾ à°®à°¾à°°à±\8dà°\9aినవారి à°®à°¾à°°à±\8dà°ªà±\81లని రద్దుచేస్తుంది',
+'tooltip-rollback' => '"à°°à°¦à±\8dà°¦à±\81à°\9aà±\87యి" à°\85à°¨à±\87ది à°\88 à°ªà±\87à°\9cà±\80ని à°\9aివరిà°\97à°¾ à°®à°¾à°°à±\8dà°\9aినవారి à°®à°¾à°°à±\8dà°ªà±\81లనà±\81 à°\92à°\95à±\8dà°\95à°¨à±\8aà°\95à±\8dà°\95à±\81à°¤à±\8b రద్దుచేస్తుంది',
 'tooltip-undo' => '"దిద్దుబాటుని రద్దుచేయి" ఈ మార్పుని రద్దుచేస్తుంది మరియు దిద్దుబాటు ఫారాన్ని మునుజూపులో తెరుస్తుంది.
 సారాంశానికి కారణాన్ని చేర్చే వీలుకల్పిస్తుంది',
 'tooltip-preferences-save' => 'అభిరుచులను భద్రపరచు',
@@ -2975,7 +2989,9 @@ $2',
 'pageinfo-toolboxlink' => 'పేజీ సమాచారం',
 'pageinfo-redirectsto' => 'ఇక్కడికి దారిమార్పు:',
 'pageinfo-redirectsto-info' => 'సమాచారం',
+'pageinfo-contentpage' => 'విషయపు పేజీగా పరిగణింపబడుతుంది',
 'pageinfo-contentpage-yes' => 'అవును',
+'pageinfo-protect-cascading' => 'సంరక్షణ ఇక్కడినుంచి వ్యాపిస్తుంది',
 'pageinfo-protect-cascading-yes' => 'అవును',
 'pageinfo-category-info' => 'వర్గపు సమాచారం',
 'pageinfo-category-pages' => 'పేజీల సంఖ్య',
@@ -3084,8 +3100,9 @@ $1',
 # Bad image list
 'bad_image_list' => 'కింద తెలిపిన తీరులో కలపాలి:
 
-జాబితాలో ఉన్నవాటినే (* గుర్తుతో మొదలయ్యే వాక్యాలు) పరిగణలోకి తీసుకుంటారు. వ్యాక్యంలో ఉన్న మొదటి లింకు ఒక చెడిపోయిన బొమ్మకు లింకు అయ్యుండాలి.
-అదే వాక్యంలో ఈ లింకు తరువాత వచ్చే లింకులను పట్టించుకోదు, ఆ పేజీలలో బొమ్మలు సరిగ్గా చేర్చారని భావిస్తుంది.',
+జాబితాలో ఉన్నవే (* గుర్తుతో మొదలయ్యే వాక్యాలు) పరిగణించబడతాయి.
+వాక్యంలో ఉన్న మొదటి లింకు ఒక చెడిపోయిన ఫైలుకు లింకు అయ్యుండాలి.
+ఆ వాక్యంలో తరువాత వచ్చే లింకులను పట్టించుకోదు. అంటే, ఆ పేజీలలో బొమ్మలు సరిగ్గా చేర్చారని భావిస్తుంది.',
 
 # Metadata
 'metadata' => 'మెటాడేటా',
@@ -3241,6 +3258,7 @@ $1',
 'exif-source' => 'మూలం',
 'exif-editstatus' => 'బొమ్మ యొక్క ఎడిటోరియల్ స్థితి',
 'exif-urgency' => 'ఎంత త్వరగా కావాలి',
+'exif-fixtureidentifier' => 'స్థాపిత వస్తువు పేరు',
 'exif-locationdest' => 'చూపించిన ప్రాంతం',
 'exif-objectcycle' => 'ఈ మాధ్యమం ఉద్దేశించిన సమయం',
 'exif-contact' => 'సంప్రదింపు సమాచారం',
@@ -3294,6 +3312,8 @@ $1',
 'exif-planarconfiguration-1' => 'స్థూల ఆకృతి',
 'exif-planarconfiguration-2' => 'సమతల ఆకృతి',
 
+'exif-colorspace-65535' => 'క్రమాంకితం కానిది',
+
 'exif-componentsconfiguration-0' => 'లేదు',
 
 'exif-exposureprogram-0' => 'అనిర్వచితం',
@@ -3564,6 +3584,7 @@ $5
 
 # Language selector for translatable SVGs
 'img-lang-default' => '(అప్రమేయ భాష)',
+'img-lang-info' => 'ఈ బొమ్మను $1 లో చూపెట్టు. $2',
 'img-lang-go' => 'వెళ్ళు',
 
 # Table pager
@@ -3672,6 +3693,7 @@ $5
 
 # Special:Redirect
 'redirect-submit' => 'వెళ్ళు',
+'redirect-lookup' => 'చూడు:',
 'redirect-value' => 'విలువ:',
 'redirect-user' => 'వాడుకరి ID',
 'redirect-page' => 'పుట ఐడీ',
@@ -3859,7 +3881,9 @@ $5
 'api-error-internal-error' => 'అంతర్గత లోపం: ఈ వికీలో మీ ఎక్కింపును ప్రాసెసు చెయ్యడంలో ఎదో తప్పు జరిగింది.',
 'api-error-invalid-file-key' => 'అంతర్గత దోషము: తాత్కాలిక నిల్వలో ఫైల్ కనపడలేదు.',
 'api-error-missingparam' => 'అంతర్గత దోషం: అభ్యర్ధనలో పరామితులు అన్నీ లేవు.',
+'api-error-missingresult' => 'అంతర్గత లోపం: నకలు తీయడం సఫలమైందో లేదో తెలియడం లేదు.',
 'api-error-mustbeloggedin' => 'దస్త్రాలను ఎక్కించడానికి మీరు ప్రవేశించివుండాలి.',
+'api-error-mustbeposted' => 'అంతర్గత లోపం: అభ్యర్థనకు HTTP POST అవసరం.',
 'api-error-noimageinfo' => 'ఎక్కింపు జయప్రదమైంది. కానీ సర్వరు, ఆ ఫైలు గురించిన సమాచారమేమీ ఇవ్వలేదు.',
 'api-error-nomodule' => 'అంతర్గత దోషము: ఎక్కింపు పర్వికము అమర్చబడలేదు.',
 'api-error-ok-but-empty' => 'అంతర్గత దోషము: సేవకము నుండి ఎటువంటి స్పందనా లేదు.',
@@ -3900,7 +3924,8 @@ $5
 
 # Special:ExpandTemplates
 'expandtemplates' => 'మూసలను విస్తరించు',
-'expand_templates_intro' => 'ఈ ప్రత్యేక పేజీ మీరిచ్చిన మూసలను పూర్తిగా విస్తరించి, చూపిస్తుంది. ఇది <nowiki>{{</nowiki>#language:...}} వంటి పార్సరు ఫంక్షన్లను, <nowiki>{{</nowiki>CURRENTDAY}} వంటి చరరాశులను(వేరియబుల్) కూడా విస్తరిస్తుంది &mdash; నిజానికి జమిలి(మీసాల) బ్రాకెట్లలో ఉన్న ప్రతీదాన్నీ ఇది విస్తరిస్తుంది. మీడియావికీ నుండి సంబంధిత పార్సరు స్టేజిని పిలిచి ఇది ఈ పనిని సాధిస్తుంది.',
+'expand_templates_intro' => 'ఈ ప్రత్యేక పేజీ మీరిచ్చిన మూసలను పూర్తిగా విస్తరించి, చూపిస్తుంది. ఇది <code><nowiki>{{</nowiki>#language:...}}</code> వంటి పార్సరు ఫంక్షన్లను, <code><nowiki>{{</nowiki>CURRENTDAY}}</code> వంటి చరరాశులను (వేరియబుల్) కూడా విస్తరిస్తుంది. 
+నిజానికి ఇది మీసాల బ్రాకెట్లలో ఉన్న ప్రతీదాన్నీ విస్తరిస్తుంది.',
 'expand_templates_title' => '{{FULLPAGENAME}} మొదలగు వాటి కొరకు సందర్భ శీర్షిక:',
 'expand_templates_input' => 'విస్తరించవలసిన పాఠ్యం:',
 'expand_templates_output' => 'ఫలితం',
@@ -3913,6 +3938,4 @@ $5
 'expand_templates_generate_rawhtml' => 'ముడి HTML ను చూపించు',
 'expand_templates_preview' => 'మునుజూపు',
 
-# Unknown messages
-'uploadinvalidxml' => 'ఎక్కించిన ఫైలులోని XML ను పార్సు చెయ్యలేకపోయాం.',
 );
index 7275cec..0fe0f7d 100644 (file)
@@ -560,15 +560,15 @@ Tandaan na may ilang pahinang maaaring magpatuloy na nagpapakitang parang nakala
 Huwag kalimutang baguhin ang iyong [[Special:Preferences|mga kagustuhan sa {{SITENAME}}]].',
 'yourname' => 'Bansag:',
 'userlogin-yourname' => 'Pangngalan',
-'userlogin-yourname-ph' => 'Ilagay ang iyong Pangngalan',
-'createacct-another-username-ph' => 'Ilagay ang Pangngalan',
+'userlogin-yourname-ph' => 'Ilagay ang iyong Pangalan',
+'createacct-another-username-ph' => 'Ilagay ang Pangalan',
 'yourpassword' => 'Hudyat:',
 'userlogin-yourpassword' => 'Hudyat',
 'userlogin-yourpassword-ph' => 'Ipasok ang iyong hudyat',
-'createacct-yourpassword-ph' => 'Ilagay ang hudyat',
+'createacct-yourpassword-ph' => 'Ilagay ang hudyat (password)',
 'yourpasswordagain' => 'Hudyat mo uli:',
 'createacct-yourpasswordagain' => 'Tiyakin ang hudyat',
-'createacct-yourpasswordagain-ph' => 'Muling ilagay ang hudyat',
+'createacct-yourpasswordagain-ph' => 'Muling ilagay ang hudyat (password)',
 'remembermypassword' => 'Tandaan ang paglagda ko sa kompyuter na ito (pinakamarami na ang $1 {{PLURAL:$1|araw|mga araw}})',
 'userlogin-remembermypassword' => 'Panatilihin akong nakalagda',
 'userlogin-signwithsecure' => 'Gumamit ng ligtas na koneksyon',
@@ -591,7 +591,7 @@ Huwag kalimutang baguhin ang iyong [[Special:Preferences|mga kagustuhan sa {{SIT
 'gotaccount' => 'May kuwenta ka na ba? $1.',
 'gotaccountlink' => 'Lumagda',
 'userlogin-resetlink' => 'Nakalimutan mo ang iyong mga detalyeng panglagda?',
-'userlogin-resetpassword-link' => 'Nakalimutan ba ang iyong hudyat?',
+'userlogin-resetpassword-link' => 'Nakalimutan ba ang iyong hudyat (password)?',
 'userlogin-createanother' => 'Lumikha ng iba pang akawnt',
 'createacct-join' => 'Ilagay ang iyong impormasyon sa ibaba.',
 'createacct-another-join' => 'Ilagay ang impormasyon ng bagong akawnt sa ibaba.',
index 757bd50..200d21c 100644 (file)
@@ -37,6 +37,7 @@
  * @author LuCKY
  * @author Mach
  * @author Manco Capac
+ * @author Marmase
  * @author Meelo
  * @author Metal Militia
  * @author Mirzali
@@ -893,6 +894,9 @@ Devam etmeden önce $1 bekleyin.',
 'suspicious-userlogout' => 'Çıkış isteğiniz reddedildi çünkü bozuk bir tarayıcı ya da önbellekli vekil tarafından gönerilmiş gibi görünüyor.',
 'createacct-another-realname-tip' => 'Gerçek adınız isteğe bağlıdır.
 Eğer gerçek adınızı belirtirseniz, çalışmalarınıza atıfta bulunulması için de kullanılacaktır.',
+'pt-login' => 'Giriş yap',
+'pt-createaccount' => 'Hesap oluştur',
+'pt-userlogout' => 'Oturumu kapat',
 
 # Email sending
 'php-mail-error-unknown' => "PHP's mail() fonksiyonunda bilinmeyen hata",
@@ -917,8 +921,11 @@ Lütfen tekrar denemeden önce $1 bekleyin.',
 'resetpass-submit-cancel' => 'İptal',
 'resetpass-wrong-oldpass' => 'Geçersiz geçici veya güncel şifre.
 Şifrenizi zaten başarıyla değiştirdiniz ya da yeni bir geçici şifre istediniz.',
+'resetpass-recycled' => 'Lütfen parolanızı eski parolanızdan farklı olarak değiştirin.',
 'resetpass-temp-password' => 'Geçici parola:',
 'resetpass-abort-generic' => 'Parola değişikliği bir uzantı tarafından iptal edildi.',
+'resetpass-expired' => 'Parolanızın süresi bitti. Lütfen, giriş için yeni bir parola oluşturun.',
+'resetpass-expired-soft' => 'Parolanızın süresi bitti ve değiştirilmesi gerekiyor. Lütfen, yeni bir parola seçin veya daha sonra oluşturmak için "{{int:resetpass-submit-cancel}}" butonuna tıklayın.',
 
 # Special:PasswordReset
 'passwordreset' => 'Parola sıfırlama',
@@ -1764,11 +1771,23 @@ Diğer kullanıcılar sizinle bu yolla iletişime geçtiğinde e-posta adresiniz
 'rcnotefrom' => "'''$2''' tarihinden itibaren yapılan değişiklikler aşağıdadır (en fazla <b>$1</b> tanesi gösterilmektedir).",
 'rclistfrom' => '$1 tarihinden itibaren yeni değişiklikleri göster',
 'rcshowhideminor' => 'Küçük değişiklikleri $1',
+'rcshowhideminor-show' => 'Göster',
+'rcshowhideminor-hide' => 'Gizle',
 'rcshowhidebots' => 'botları $1',
+'rcshowhidebots-show' => 'Göster',
+'rcshowhidebots-hide' => 'Gizle',
 'rcshowhideliu' => 'Kayıtlı kullanıcıları $1',
+'rcshowhideliu-show' => 'Göster',
+'rcshowhideliu-hide' => 'Gizle',
 'rcshowhideanons' => 'Anonim kullanıcıları $1',
+'rcshowhideanons-show' => 'Göster',
+'rcshowhideanons-hide' => 'Gizle',
 'rcshowhidepatr' => 'İzlenmiş değişiklikleri $1',
+'rcshowhidepatr-show' => 'Göster',
+'rcshowhidepatr-hide' => 'Gizle',
 'rcshowhidemine' => 'Değişikliklerimi $1',
+'rcshowhidemine-show' => 'Göster',
+'rcshowhidemine-hide' => 'Gizle',
 'rclinks' => 'Son $2 günde yapılan son $1 değişikliği göster;<br /> $3',
 'diff' => 'fark',
 'hist' => 'geçmiş',
@@ -1893,6 +1912,7 @@ Dosyayı tekrar yüklemeye devam etmeden önce, bastırılmış dosya verisini g
 'uploaddisabledtext' => 'Dosya yüklemeleri devredışı bırakılmıştır.',
 'php-uploaddisabledtext' => 'PHP dosyası yüklemeleri devre dışıdır. Lütfen file_uploads ayarını kontrol edin.',
 'uploadscripted' => 'Bu dosya bir internet tarayıcısı tarafından hatalı çevrilebilecek bir HTML veya script kodu içermektedir.',
+'uploadinvalidxml' => 'Yüklenen dosyadaki XML işlenemedi.',
 'uploadvirus' => 'Bu dosya virüslüdür! Detayları: $1',
 'uploadjava' => 'Dosya, bir Java .classdosyası içeren bir ZIP dosyasıdır.
 Java dosyalarının yüklenmesine izin verilmemektedir, zira güvenlik kısıtlamalarının atlanmasına neden olabilmektedirler.',
@@ -4278,6 +4298,4 @@ Aslında, çift ayraçlı hemen hemen her şeyi genişletir.',
 'expand_templates_generate_rawhtml' => 'Ham HTML göster',
 'expand_templates_preview' => 'Önizleme',
 
-# Unknown messages
-'uploadinvalidxml' => 'Yüklenen dosyadaki XML işlenemedi.',
 );
index 5eb04b6..f854fd2 100644 (file)
@@ -914,6 +914,9 @@ $1',
 'suspicious-userlogout' => 'Ваш запит на завершення сеанса відхилений, оскільки він схожий на запит, відправлений зіпсованим веб-оглядачем або кешуючим проксі-сервером.',
 'createacct-another-realname-tip' => "Справжнє ім'я є необов'язковим.
 Якщо ви вирішите надати його, то воно буде використовуватися для присвоєння користувачу авторства до його роботи.",
+'pt-login' => 'Увійти',
+'pt-createaccount' => 'Створити обліковий запис',
+'pt-userlogout' => 'Вийти',
 
 # Email sending
 'php-mail-error-unknown' => 'Невідома помилка в PHP-функції mail()',
@@ -922,7 +925,7 @@ $1',
 
 # Change password dialog
 'changepassword' => 'Змінити пароль',
-'resetpass_announce' => 'Ð\92и Ð²Ð²Ñ\96йÑ\88ли, Ð²Ð¸ÐºÐ¾Ñ\80иÑ\81Ñ\82овÑ\83Ñ\8eÑ\87и Ñ\82имÑ\87аÑ\81овий Ð¿Ð°Ñ\80олÑ\8c, Ñ\8fкий Ð¾Ñ\82Ñ\80имали ÐµÐ»ÐµÐºÑ\82Ñ\80онноÑ\8e Ð¿Ð¾Ñ\88Ñ\82оÑ\8e. Ð\94лÑ\8f Ð·Ð°Ð²ÐµÑ\80Ñ\88еннÑ\8f Ð²Ñ\85одÑ\83 Ð´Ð¾ Ñ\81иÑ\81Ñ\82еми, Ð²Ð¸ Ð¿Ð¾Ð²Ð¸Ð½Ð½Ñ\96 Ð²ÐºÐ°Ð·Ð°Ñ\82и Ð½Ð¾Ð²Ð¸Ð¹ Ð¿Ð°Ñ\80олÑ\8c Ñ\82Ñ\83Ñ\82:',
+'resetpass_announce' => 'Ð\94лÑ\8f Ð·Ð°Ð²ÐµÑ\80Ñ\88еннÑ\8f Ð²Ñ\85одÑ\83 Ð²Ð¸ Ð¿Ð¾Ð²Ð¸Ð½Ð½Ñ\96 Ð²Ñ\81Ñ\82ановиÑ\82и Ð½Ð¾Ð²Ð¸Ð¹ Ð¿Ð°Ñ\80олÑ\8c.',
 'resetpass_text' => '<!-- Додавайте текст сюди -->',
 'resetpass_header' => 'Змінити пароль облікового запису',
 'oldpassword' => 'Старий пароль:',
@@ -938,8 +941,13 @@ $1',
 'resetpass-submit-cancel' => 'Скасувати',
 'resetpass-wrong-oldpass' => 'Неправильний тимчасовий або поточний пароль.
 Можливо, ви вже успішно змінили пароль або зробили запит на новий тимчасовий пароль.',
+'resetpass-recycled' => 'Змініть свій пароль на щось інше, ніж ваш поточний пароль.',
+'resetpass-temp-emailed' => 'Ви ввійшли, використовуючи тимчасовий пароль, який отримали електронною поштою. 
+Для завершення входу в систему необхідно задати новий пароль:',
 'resetpass-temp-password' => 'Тимчасовий пароль:',
 'resetpass-abort-generic' => 'Зміну пароля було перервано розширенням.',
+'resetpass-expired' => 'Термін дії вашого пароля закінчився. Будь ласка, встановіть новий пароль для входу в систему.',
+'resetpass-expired-soft' => 'Термін дії вашого пароля закінчився, і тепер він повинен бути змінений. Будь ласка, виберіть новий пароль або натисніть «Скасувати», щоб змінити його пізніше.',
 
 # Special:PasswordReset
 'passwordreset' => 'Скинути пароль',
@@ -1802,11 +1810,23 @@ $1",
 'rcnotefrom' => 'Нижче відображені редагування з <strong>$2</strong> (до <strong>$1</strong>).',
 'rclistfrom' => 'Показати редагування починаючи з $1.',
 'rcshowhideminor' => '$1 незначні редагування',
+'rcshowhideminor-show' => 'Показати',
+'rcshowhideminor-hide' => 'Приховати',
 'rcshowhidebots' => '$1 ботів',
+'rcshowhidebots-show' => 'Показати',
+'rcshowhidebots-hide' => 'Приховати',
 'rcshowhideliu' => '$1 зареєстрованих користувачів',
+'rcshowhideliu-show' => 'Показати',
+'rcshowhideliu-hide' => 'Приховати',
 'rcshowhideanons' => '$1 анонімів',
+'rcshowhideanons-show' => 'Показати',
+'rcshowhideanons-hide' => 'Приховати',
 'rcshowhidepatr' => '$1 перевірені',
+'rcshowhidepatr-show' => 'Показати',
+'rcshowhidepatr-hide' => 'Приховати',
 'rcshowhidemine' => '$1 мої редагування',
+'rcshowhidemine-show' => 'Показати',
+'rcshowhidemine-hide' => 'Приховати',
 'rclinks' => 'Показати останні $1 редагувань за $2 днів<br />$3',
 'diff' => 'різн.',
 'hist' => 'історія',
@@ -1942,6 +1962,7 @@ $1",
 'uploaddisabledtext' => 'Можливість завантаження файлів відключена.',
 'php-uploaddisabledtext' => 'Завантаження файлів вимкнене у налаштуваннях PHP. Будь ласка, перевірте значення file_uploads.',
 'uploadscripted' => 'Файл містить HTML-код або скрипт, який може неправильно обробитися браузером.',
+'uploadinvalidxml' => 'Не вдалося проаналізувати XML у завантаженому файлі.',
 'uploadvirus' => 'Файл містить вірус! Див. $1',
 'uploadjava' => 'Файл є ZIP-архівом, що містить .class-файл Java.
 Завантаження Java-файлів не дозволене, бо вони можуть використовуватися для обходу системи безпеки.',
@@ -4480,6 +4501,4 @@ MediaWiki поширюється в надії, що вона буде кори
 'expand_templates_generate_rawhtml' => 'Показати сирий HTML',
 'expand_templates_preview' => 'Попередній перегляд',
 
-# Unknown messages
-'uploadinvalidxml' => 'Не вдалося проаналізувати XML у завантаженому файлі.',
 );
index d9240ce..42a1305 100644 (file)
@@ -954,7 +954,7 @@ Agar keltirsangiz, undan sahifa kim tomonidan tahrirlanganini koʻrsatish uchun
 'recentchanges-label-plusminus' => 'vazni qanchaga oʻzgargani (bayt)',
 'recentchanges-legend-heading' => "'''Izoh:'''",
 'recentchanges-legend-newpage' => '([[Special:NewPages|alohida roʻyxat]])',
-'rcnotefrom' => "Quyida <strong>$2</strong> dan (<strong>$1</strong> gacha) bo'lgan o'zgarishlar keltirilgan.",
+'rcnotefrom' => 'Quyida <strong>$2</strong>dan boshlab boʻlgan oʻzgarishlar keltirilgan (<strong>$1</strong>dan koʻp boʻlmaganlari koʻrsatildi).',
 'rclistfrom' => '$1 dan boshlab yangi oʻzgarishlarni koʻrsat.',
 'rcshowhideminor' => 'Kichik tahrirlarni $1',
 'rcshowhidebots' => 'Botlarni $1',
index b2179c9..3ab410c 100644 (file)
@@ -1749,8 +1749,14 @@ Nếu bạn đồng ý cung cấp, nó sẽ dùng để ghi nhận công lao c
 'rcnotefrom' => "Thay đổi từ '''$2''' (hiển thị tối đa '''$1''' thay đổi).",
 'rclistfrom' => 'Hiển thị các thay đổi từ $1.',
 'rcshowhideminor' => '$1 sửa đổi nhỏ',
+'rcshowhideminor-show' => 'Hiện',
+'rcshowhideminor-hide' => 'Ẩn',
 'rcshowhidebots' => '$1 sửa đổi bot',
+'rcshowhidebots-show' => 'Hiện',
+'rcshowhidebots-hide' => 'Ẩn',
 'rcshowhideliu' => '$1 thành viên đăng ký',
+'rcshowhideliu-show' => 'Hiện',
+'rcshowhideliu-hide' => 'Ẩn',
 'rcshowhideanons' => '$1 sửa đổi vô danh',
 'rcshowhidepatr' => '$1 sửa đổi đã tuần tra',
 'rcshowhidemine' => '$1 sửa đổi của tôi',
@@ -1880,6 +1886,7 @@ Bạn nên xin một người có quyền xem dữ liệu tập tin bị đàn 
 'uploaddisabledtext' => 'Chức năng tải tập tin đã bị tắt.',
 'php-uploaddisabledtext' => 'Việc tải tập tin trong PHP đã bị tắt. Xin hãy kiểm tra lại thiết lập file_uploads.',
 'uploadscripted' => 'Tập tin này có chứa mã HTML hoặc kịch bản có thể khiến trình duyệt web thông dịch sai.',
+'uploadinvalidxml' => 'Không thể phân tích mã XML trong tập tin tải lên.',
 'uploadvirus' => 'Tập tin có virút! Chi tiết: $1',
 'uploadjava' => 'Tập tin ZIP này chứa một tập tin Java .class.
 Không được phép tải lên các tập tin Java, bởi vì chúng có thể vượt qua các hạn chế bảo mật.',
@@ -4356,6 +4363,4 @@ Nếu không thì bạn có thể điền biểu mẫu đơn giản ở dưới.
 'expand_templates_generate_rawhtml' => 'Hiển thị HTML thô',
 'expand_templates_preview' => 'Xem trước',
 
-# Unknown messages
-'uploadinvalidxml' => 'Không thể phân tích mã XML trong tập tin tải lên.',
 );
index ab43ec6..66e7f42 100644 (file)
@@ -747,6 +747,9 @@ $2',
 'suspicious-userlogout' => ' אײַער בקשה אַרויסלאָגירן זיך איז אפגעלייגט געווארן ווייַל אייגנטלעך איז זי געשיקט דורך אַ צעבראכענעם בלעטערער אָדער א פראקסי מיט א זאפאס.',
 'createacct-another-realname-tip' => 'עכטער נאמען איז אפציאנאל.
 אויב איר וויילט אויס צוצושטעלן אים, וועט דאס גענוצט ווערן צו געבן אטריבוציע פאר זייער ארבעט.',
+'pt-login' => 'אַרײַנלאגירן',
+'pt-createaccount' => 'שאַפֿן אַ קאנטע',
+'pt-userlogout' => 'אַרויסלאגירן',
 
 # Email sending
 'php-mail-error-unknown' => 'אומבאַקאַנט טעות אין()mail פֿונקציע פֿון PHP.',
@@ -1626,10 +1629,20 @@ $1",
 'rclistfrom' => 'װײַזן נײַע ענדערונגען פֿון $1',
 'rcshowhideminor' => '$1 מינערדיגע ענדערונגען',
 'rcshowhidebots' => '$1 ראבאטן',
+'rcshowhidebots-show' => 'ווײַזן',
+'rcshowhidebots-hide' => 'באַהאַלטן',
 'rcshowhideliu' => '$1 אײַנגעשריבענע באַניצער',
+'rcshowhideliu-show' => 'ווײַזן',
+'rcshowhideliu-hide' => 'באַהאַלטן',
 'rcshowhideanons' => '$1 אַנאָנימע באַניצער',
+'rcshowhideanons-show' => 'ווײַזן',
+'rcshowhideanons-hide' => 'באַהאַלטן',
 'rcshowhidepatr' => '$1 פאַטראלירטע ענדערונגען',
+'rcshowhidepatr-show' => 'ווײַזן',
+'rcshowhidepatr-hide' => 'באַהאַלטן',
 'rcshowhidemine' => '$1 מײַנע רעדאַקטירוננגען',
+'rcshowhidemine-show' => 'ווײַזן',
+'rcshowhidemine-hide' => 'באַהאַלטן',
 'rclinks' => 'װײַזן די לעצטע $1 ענדערונגען אין די לעצטע $2 טעג.<br />$3',
 'diff' => 'אונטערשייד',
 'hist' => 'היסטאריע',
index ecb074d..0bccc5a 100644 (file)
@@ -73,6 +73,7 @@
  * @author Wrightbus
  * @author Xiaomingyan
  * @author Yfdyh000
+ * @author Zoglun
  * @author 乌拉跨氪
  * @author 御坂美琴
  * @author 燃玉
@@ -937,7 +938,7 @@ $2',
 'resetpass-temp-password' => '临时密码:',
 'resetpass-abort-generic' => '密码更改已被一个扩展插件中止。',
 'resetpass-expired' => '您的密码已经过期。请设置一个新的密码登录。',
-'resetpass-expired-soft' => '您的密码已经过期,并且需要重置。请现在选择一个新密码,或单击取消以便稍后重置。',
+'resetpass-expired-soft' => '您的密码已过期并且需要重置。请现在选择一个新密码,或单击“{{int:resetpass-submit-cancel}}”以便稍后重置。',
 
 # Special:PasswordReset
 'passwordreset' => '重置密码',
@@ -1020,11 +1021,11 @@ $2
 'subject' => '标题:',
 'minoredit' => '标记为小编辑',
 'watchthis' => '监视本页',
-'savearticle' => '保存本页',
+'savearticle' => '保存页面',
 'preview' => '预览',
 'showpreview' => '显示预览',
 'showlivepreview' => '实时预览',
-'showdiff' => '显示差异',
+'showdiff' => '显示更改',
 'anoneditwarning' => "'''警告:'''你没有登录。你的IP地址将被记录在该页面的编辑历史中。",
 'anonpreviewwarning' => "''你没有登录。保存会记录你的IP地址于该页面的编辑历史中。''",
 'missingsummary' => "'''提示:'''你没有提供编辑摘要。如果你再次点击“{{int:savearticle}}”,你的编辑将不带编辑摘要保存。",
@@ -1093,7 +1094,7 @@ $2
 'updated' => '(已更新)',
 'note' => "'''注意:'''",
 'previewnote' => "'''请记住这只是预览。'''你的更改还没有保存!",
-'continue-editing' => 'å¾\80ç¼\96è¾\91æ¡\86',
+'continue-editing' => 'å\89\8då¾\80ç¼\96è¾\91å\8cº',
 'previewconflict' => '该预览反映了上面文字编辑区中的文字在你保存后的显示状况。',
 'session_fail_preview' => "'''对不起!由于会话数据丢失,我们无法处理你的编辑。'''请重试。如果仍然失败,请尝试[[Special:UserLogout|退出登录]]后重新登录。",
 'session_fail_preview_html' => "'''对不起!由于会话数据丢失,我们无法处理你的编辑。'''
@@ -1420,7 +1421,7 @@ $1",
 'powersearch-toggleall' => '全选',
 'powersearch-togglenone' => '全不选',
 'search-external' => '外部搜索',
-'searchdisabled' => '{{SITENAME}}的搜索已被禁用。您可以暂时使用Google进行搜索,须注意他们索引的{{SITENAME}}内容可能会过时。',
+'searchdisabled' => '{{SITENAME}}的搜索已被禁用。您可以暂时使用搜索引擎进行搜索,须注意他们索引的{{SITENAME}}内容可能不是最新的。',
 'search-error' => '搜索时发生错误:$1',
 
 # Preferences page
@@ -1721,14 +1722,26 @@ $1",
 'recentchanges-legend-heading' => "'''说明:'''",
 'recentchanges-legend-newpage' => '(另见[[Special:NewPages|新页面列表]])',
 'recentchanges-legend-plusminus' => "(''±123'')",
-'rcnotefrom' => "下面是'''$2'''之后的更改(最多显示'''$1'''个)。",
+'rcnotefrom' => '下面是<strong>$2</strong>之后的更改(最多显示<strong>$1</strong>个)。',
 'rclistfrom' => '显示$1之后的新更改',
 'rcshowhideminor' => '$1小编辑',
+'rcshowhideminor-show' => '显示',
+'rcshowhideminor-hide' => '隐藏',
 'rcshowhidebots' => '$1机器人',
+'rcshowhidebots-show' => '显示',
+'rcshowhidebots-hide' => '隐藏',
 'rcshowhideliu' => '$1注册用户',
+'rcshowhideliu-show' => '显示',
+'rcshowhideliu-hide' => '隐藏',
 'rcshowhideanons' => '$1匿名用户',
+'rcshowhideanons-show' => '显示',
+'rcshowhideanons-hide' => '隐藏',
 'rcshowhidepatr' => '$1已巡查的编辑',
+'rcshowhidepatr-show' => '显示',
+'rcshowhidepatr-hide' => '隐藏',
 'rcshowhidemine' => '$1我的编辑',
+'rcshowhidemine-show' => '显示',
+'rcshowhidemine-hide' => '隐藏',
 'rclinks' => '显示最后$2天的最后$1个更改<br />$3',
 'diff' => '差异',
 'hist' => '历史',
@@ -1845,6 +1858,8 @@ $1",
 'uploaddisabledtext' => '文件上传已停用。',
 'php-uploaddisabledtext' => 'PHP文件上传停用。请检查file_uploads设置。',
 'uploadscripted' => '该文件包含可能被网络浏览器错误解释的 HTML 或脚本代码。',
+'uploadscriptednamespace' => "此SVG文件包含非法名字空间'$1'",
+'uploadinvalidxml' => '上传文件中的XML无法解析。',
 'uploadvirus' => '该文件包含病毒!
 详情:$1',
 'uploadjava' => '该文件是 ZIP 文件,其中包含 Java 的.class 文件。
@@ -2462,7 +2477,7 @@ $UNWATCHURL
 'delete-edit-reasonlist' => '编辑删除原因',
 'delete-toobig' => '这个页面有一个十分大量的编辑历史,超过$1次修订。删除此类页面的动作已经被限制,以防止在{{SITENAME}}上的意外扰乱。',
 'delete-warning-toobig' => '这个页面有一个十分大量的编辑历史,超过$1次修订。删除它可能会扰乱{{SITENAME}}的数据库操作;在继续此动作前请小心。',
-'deleting-backlinks-warning' => "'''警告:'''有其他页面链接至或transclude自您要删除的页面。",
+'deleting-backlinks-warning' => "'''警告:'''有其他页面链接至或包含您要删除的页面。",
 
 # Rollback
 'rollback' => '回退编辑',
@@ -2632,6 +2647,7 @@ $1',
 'sp-contributions-search' => '搜索贡献',
 'sp-contributions-username' => 'IP地址或用户名:',
 'sp-contributions-toponly' => '仅显示最后版本的编辑',
+'sp-contributions-newonly' => '仅显示创建页面的编辑',
 'sp-contributions-submit' => '搜索',
 
 # What links here
@@ -3085,7 +3101,7 @@ $2',
 'group-bureaucrat.css' => '/* 放置于这里的CSS将只影响机行政员 */',
 
 # Scripts
-'common.js' => '/* 这里的任何JavaScript将为所有用户在每一页面载入加载。 */',
+'common.js' => '/* 这里的任何JavaScript将为所有用户在每次页面载入时加载。 */',
 'cologneblue.js' => '/* 这里的任何JavaScript将为使用科隆香水蓝皮肤的用户加载 */',
 'monobook.js' => '/* 这里的任何JavaScript将为使用MonoBook皮肤的用户加载 */',
 'modern.js' => '/* 这里的任何JavaScript将为使用现代皮肤的用户加载 */',
@@ -3134,7 +3150,7 @@ $2',
 'pageinfo-length' => '页面长度(字节)',
 'pageinfo-article-id' => '页面ID',
 'pageinfo-language' => '页面内容语言',
-'pageinfo-content-model' => '页面内容模式',
+'pageinfo-content-model' => '页面内容类型',
 'pageinfo-robot-policy' => '爬虫索引',
 'pageinfo-robot-index' => '允许',
 'pageinfo-robot-noindex' => '不允许',
@@ -4178,6 +4194,4 @@ MediaWiki发表时预期有用,但对此'''无任何保证''',亦无隐含
 'expand_templates_generate_rawhtml' => '显示原始HTML',
 'expand_templates_preview' => '预览',
 
-# Unknown messages
-'uploadinvalidxml' => '上传文件中的XML无法解析。',
 );
index fe218bb..da4012b 100644 (file)
@@ -837,7 +837,7 @@ $2',
 'resetpass-temp-password' => '臨時密碼:',
 'resetpass-abort-generic' => '擴充元件已中止了更改密碼操作。',
 'resetpass-expired' => '您的密碼已過期。請設置新密碼以登錄。',
-'resetpass-expired-soft' => '您的密碼已過期,現需重置。請設置新密碼以登錄,或點擊取消以稍後重置。',
+'resetpass-expired-soft' => '您的密碼已過期,現需重置。請設置新密碼以登錄,或點擊“{{int:resetpass-submit-cancel}}”以稍後重置。',
 
 # Special:PasswordReset
 'passwordreset' => '重新設定密碼',
@@ -1657,14 +1657,26 @@ $1",
 'recentchanges-legend-heading' => "'''說明:'''",
 'recentchanges-legend-newpage' => '(另見[[Special:NewPages|新頁面列表]])',
 'recentchanges-legend-plusminus' => "(''±123'')",
-'rcnotefrom' => "下面是自'''$2'''(最多顯示'''$1'''):",
+'rcnotefrom' => '下面是自<strong>$2</strong>起之更改(至多顯示<strong>$1</strong>個)。',
 'rclistfrom' => '顯示自 $1 以來的新變更',
 'rcshowhideminor' => '$1小編輯',
+'rcshowhideminor-show' => '顯示',
+'rcshowhideminor-hide' => '隱藏',
 'rcshowhidebots' => '$1機器人的編輯',
+'rcshowhidebots-show' => '顯示',
+'rcshowhidebots-hide' => '隱藏',
 'rcshowhideliu' => '$1已註冊用戶',
+'rcshowhideliu-show' => '顯示',
+'rcshowhideliu-hide' => '隱藏',
 'rcshowhideanons' => '$1匿名用戶的編輯',
+'rcshowhideanons-show' => '顯示',
+'rcshowhideanons-hide' => '隱藏',
 'rcshowhidepatr' => '$1巡查過的編輯',
+'rcshowhidepatr-show' => '顯示',
+'rcshowhidepatr-hide' => '隱藏',
 'rcshowhidemine' => '$1我的編輯',
+'rcshowhidemine-show' => '顯示',
+'rcshowhidemine-hide' => '隱藏',
 'rclinks' => '顯示最近$2天內最新的$1次改動。<br />$3',
 'diff' => '差異',
 'hist' => '歷史',
@@ -1784,6 +1796,8 @@ $1",
 'uploaddisabledtext' => '檔案上傳不可用。',
 'php-uploaddisabledtext' => 'PHP 檔案上載已經停用。請檢查 file_uploads 設定。',
 'uploadscripted' => '該檔案包含可能被網路瀏覽器錯誤解釋的 HTML 或腳本代碼。',
+'uploadscriptednamespace' => "此SVG檔案中包含非法命名空間'$1'",
+'uploadinvalidxml' => '上載檔案中的XML無法解析。',
 'uploadvirus' => '該檔案包含有病毒!
 詳情:$1',
 'uploadjava' => '該檔案是 ZIP 檔案,其中包含 Java 的.class 檔案。
@@ -2419,7 +2433,7 @@ $UNWATCHURL
 'delete-edit-reasonlist' => '編輯刪除理由',
 'delete-toobig' => '這個頁面有一個十分大量的編輯歷史,超過$1次修訂。刪除此類頁面的動作已經被限制,以防止在{{SITENAME}}上的意外擾亂。',
 'delete-warning-toobig' => '這個頁面有一個十分大量的編輯歷史,超過$1次修訂。刪除它可能會擾亂{{SITENAME}}的資料庫操作;在繼續此動作前請小心。',
-'deleting-backlinks-warning' => "'''è­¦å\91\8aï¼\9a'''æ\82¨è¦\81å\88ªé\99¤ç\9a\84é \81é\9d¢æ\9c\89å\85¶ä»\96é \81é\9d¢é\80£æ\8e¥è\87³æ­¤æ\88\96å¾\9eæ­¤é \81é\9d¢transclude。",
+'deleting-backlinks-warning' => "'''è­¦å\91\8aï¼\9a'''æ\82¨è¦\81å\88ªé\99¤ç\9a\84é \81é\9d¢æ\9c\89å\85¶ä»\96é \81é\9d¢é\80£æ\8e¥è\87³æ­¤æ\88\96å\8c\85å\90«æ­¤é \81é\9d¢。",
 
 # Rollback
 'rollback' => '回退編輯',
@@ -2594,6 +2608,7 @@ $1',
 'sp-contributions-search' => '搜尋貢獻記錄',
 'sp-contributions-username' => 'IP位址或用戶名稱:',
 'sp-contributions-toponly' => '只顯示最新修訂版本的編輯',
+'sp-contributions-newonly' => '僅顯示建立頁面之編輯',
 'sp-contributions-submit' => '搜尋',
 
 # What links here
@@ -4138,6 +4153,4 @@ MediaWiki是基於使用目的而加以發佈,然而不負任何擔保責任
 'expand_templates_generate_rawhtml' => '顯示原始HTML',
 'expand_templates_preview' => '預覽',
 
-# Unknown messages
-'uploadinvalidxml' => '上載檔案中的XML無法解析。',
 );
index 46b0362..142727c 100644 (file)
@@ -498,7 +498,6 @@ $wgOptionalMessages = array(
        'limitreport-expensivefunctioncount-value',
        'interlanguage-link-title',
        'img-lang-opt',
-       'quotation-marks',
        'recentchanges-legend-plusminus',
 );
 
index 24554a2..ef00b27 100644 (file)
@@ -503,6 +503,7 @@ $wgMessageStructure = array(
                'createacct-benefit-body3',
                'badretype',
                'userexists',
+               'createacct-normalization',
                'loginerror',
                'createacct-error',
                'createaccounterror',
@@ -810,6 +811,7 @@ $wgMessageStructure = array(
                'cantcreateaccounttitle',
                'cantcreateaccount-text',
                'cantcreateaccount-range-text',
+               'createaccount-hook-aborted',
        ),
        'history' => array(
                'viewpagelogs',
@@ -1326,11 +1328,23 @@ $wgMessageStructure = array(
                'rcnotefrom',
                'rclistfrom',
                'rcshowhideminor',
+               'rcshowhideminor-show',
+               'rcshowhideminor-hide',
                'rcshowhidebots',
+               'rcshowhidebots-show',
+               'rcshowhidebots-hide',
                'rcshowhideliu',
+               'rcshowhideliu-show',
+               'rcshowhideliu-hide',
                'rcshowhideanons',
+               'rcshowhideanons-show',
+               'rcshowhideanons-hide',
                'rcshowhidepatr',
+               'rcshowhidepatr-show',
+               'rcshowhidepatr-hide',
                'rcshowhidemine',
+               'rcshowhidemine-show',
+               'rcshowhidemine-hide',
                'rclinks',
                'diff',
                'hist',
@@ -1436,6 +1450,8 @@ $wgMessageStructure = array(
                'uploaddisabledtext',
                'php-uploaddisabledtext',
                'uploadscripted',
+               'uploadscriptednamespace',
+               'uploadinvalidxml',
                'uploadvirus',
                'uploadjava',
                'upload-source',
@@ -2242,6 +2258,7 @@ $wgMessageStructure = array(
                'sp-contributions-suppresslog',
                'sp-contributions-username',
                'sp-contributions-toponly',
+               'sp-contributions-newonly',
                'sp-contributions-submit',
                'sp-contributions-explain',
                'sp-contributions-footer',
diff --git a/maintenance/oracle/archives/patch-user_password_expire.sql b/maintenance/oracle/archives/patch-user_password_expire.sql
new file mode 100644 (file)
index 0000000..8e752da
--- /dev/null
@@ -0,0 +1,3 @@
+define mw_prefix='{$wgDBprefix}';
+
+ALTER TABLE &mw_prefix.mwuser ADD user_password_expires TIMESTAMP(6) WITH TIME ZONE NULL DEFAULT NULL;
index 52b9aa0..a2958eb 100644 (file)
@@ -759,7 +759,7 @@ return array(
        ),
        'mediawiki.debug' => array(
                'scripts' => 'resources/mediawiki/mediawiki.debug.js',
-               'styles' => 'resources/mediawiki/mediawiki.debug.css',
+               'styles' => 'resources/mediawiki/mediawiki.debug.less',
                'dependencies' => 'jquery.footHovzer',
                'position' => 'bottom',
        ),
@@ -1249,9 +1249,17 @@ return array(
        'mediawiki.special.userlogin.signup.js' => array(
                'scripts' => 'resources/mediawiki.special/mediawiki.special.userlogin.signup.js',
                'messages' => array(
+                       'createacct-error',
                        'createacct-emailrequired',
+                       'createacct-normalization',
+                       'noname',
+                       'userexists',
+               ),
+               'dependencies' => array(
+                       'mediawiki.api',
+                       'mediawiki.jqueryMsg',
+                       'jquery.throttle-debounce',
                ),
-               'dependencies' => 'mediawiki.jqueryMsg',
        ),
        'mediawiki.special.javaScriptTest' => array(
                'scripts' => 'resources/mediawiki.special/mediawiki.special.javaScriptTest.js',
@@ -1369,10 +1377,14 @@ return array(
                'styles' => array(
                        'resources/oojs-ui/oojs-ui.svg.css',
                ),
+               'skinStyles' => array(
+                       'default' => 'resources/oojs-ui/oojs-ui-apex.css',
+               ),
                'messages' => array(
                        'ooui-dialog-action-close',
                        'ooui-outline-control-move-down',
                        'ooui-outline-control-move-up',
+                       'ooui-outline-control-remove',
                        'ooui-toolbar-more',
                ),
                'dependencies' => array(
index 8bc45c9..04f8047 100644 (file)
@@ -14,7 +14,7 @@
                var color;
 
                do {
-                       color = $.curCSS( elem, attr );
+                       color = $.css( elem, attr );
 
                        // Keep going until we find an element that has color, or we hit the body
                        if ( color !== '' && color !== 'transparent' || $.nodeName( elem, 'body' ) ) {
                'outlineColor'
        ], function ( i, attr ) {
                $.fx.step[attr] = function ( fx ) {
-                       if ( fx.state === 0 ) {
+                       if ( !fx.colorInit ) {
                                fx.start = getColor( fx.elem, attr );
                                fx.end = $.colorUtil.getRGB( fx.end );
+                               fx.colorInit = true;
                        }
 
                        fx.elem.style[attr] = 'rgb(' + [
index b3d7bb3..f9ee268 100644 (file)
        function buildHeaders( table, msg ) {
                var maxSeen = 0,
                        colspanOffset = 0,
-                       longest,
                        columns,
                        i,
                        $tableHeaders = $( [] ),
                if ( $tableRows.length <= 1 ) {
                        $tableHeaders = $tableRows.children( 'th' );
                } else {
-                       // We need to find the cells of the row containing the most columns
                        var rowspan,
-                               headersIndex = [];
-                       $tableRows.each( function ( rowIndex ) {
-                               $.each( this.cells, function( index2, cell ) {
+                               colspan,
+                               headerCount,
+                               longestTR,
+                               matrixRowIndex,
+                               matrixColumnIndex,
+                               exploded = [];
+
+                       // Loop through all the dom cells of the thead
+                       $tableRows.each( function ( rowIndex, row ) {
+                               $.each( row.cells, function( columnIndex, cell ) {
                                        rowspan = Number( cell.rowSpan );
-                                       for ( i = 0; i < rowspan; i++ ) {
-                                               if ( headersIndex[rowIndex+i] === undefined ) {
-                                                       headersIndex[rowIndex+i] = $( [] );
+                                       colspan = Number( cell.colSpan );
+
+                                       // Skip the spots in the exploded matrix that are already filled
+                                       while ( exploded[rowIndex] && exploded[rowIndex][columnIndex] !== undefined ) {
+                                               ++columnIndex;
+                                       }
+
+                                       // Find the actual dimensions of the thead, by placing each cell
+                                       // in the exploded matrix rowspan times colspan times, with the proper offsets
+                                       for ( matrixColumnIndex = columnIndex; matrixColumnIndex < columnIndex + colspan; ++matrixColumnIndex ) {
+                                               for ( matrixRowIndex = rowIndex; matrixRowIndex < rowIndex + rowspan; ++matrixRowIndex ) {
+                                                       if ( !exploded[matrixRowIndex] ) {
+                                                               exploded[matrixRowIndex] = [];
+                                                       }
+                                                       exploded[matrixRowIndex][matrixColumnIndex] = cell;
                                                }
-                                               headersIndex[rowIndex+i].push( cell );
                                        }
                                } );
                        } );
-                       $.each( headersIndex, function ( index, cellArray ) {
-                               if ( cellArray.length >= maxSeen ) {
-                                       maxSeen = cellArray.length;
-                                       longest = index;
+                       // We want to find the row that has the most columns (ignoring colspan)
+                       $.each( exploded, function ( index, cellArray ) {
+                               headerCount = $.unique( $(cellArray) ).length;
+                               if ( headerCount >= maxSeen ) {
+                                       maxSeen = headerCount;
+                                       longestTR = index;
                                }
                        } );
-                       $tableHeaders = headersIndex[longest];
+                       // We cannot use $.unique() here because it sorts into dom order, which is undesirable
+                       $tableHeaders = $( uniqueElements( exploded[longestTR] ) );
                }
 
                // as each header can span over multiple columns (using colspan=N),
                return false;
        }
 
+
+       function uniqueElements( array ) {
+               var uniques = [];
+               $.each( array, function( index, elem ) {
+                       if ( elem !== undefined && $.inArray( elem, uniques ) === -1 ) {
+                               uniques.push( elem );
+                       }
+               } );
+               return uniques;
+       }
+
        function setHeadersCss( table, $headers, list, css, msg, columnToHeader ) {
                // Remove all header information and reset titles to default message
                $headers.removeClass( css[0] ).removeClass( css[1] ).attr( 'title', msg[1] );
index d61c1c6..57eda3d 100644 (file)
@@ -3,6 +3,7 @@
  */
 ( function ( mw, $ ) {
 
+       var msg = 'Use of mediawiki.api callback params is deprecated. Use the Promise instead.';
        $.extend( mw.Api.prototype, {
                /**
                 * Determine if a category exists.
                                apiPromise;
 
                        // Backwards compatibility (< MW 1.20)
-                       d.done( ok ).fail( err );
+                       if ( ok || err ) {
+                               mw.track( 'mw.deprecate', 'api.cbParam' );
+                               mw.log.warn( msg );
+                               d.done( ok ).fail( err );
+                       }
 
                        apiPromise = this.get( {
                                        prop: 'categoryinfo',
                                apiPromise;
 
                        // Backwards compatibility (< MW 1.20)
-                       d.done( ok ).fail( err );
+                       if ( ok || err ) {
+                               mw.track( 'mw.deprecate', 'api.cbParam' );
+                               mw.log.warn( msg );
+                               d.done( ok ).fail( err );
+                       }
 
                        // Fetch with allpages to only get categories that have a corresponding description page.
                        apiPromise = this.get( {
                                apiPromise;
 
                        // Backwards compatibility (< MW 1.20)
-                       d.done( ok ).fail( err );
+                       if ( ok || err ) {
+                               mw.track( 'mw.deprecate', 'api.cbParam' );
+                               mw.log.warn( msg );
+                               d.done( ok ).fail( err );
+                       }
 
                        apiPromise = this.get( {
                                        prop: 'categories',
index cc83a4b..91d9b8f 100644 (file)
@@ -3,6 +3,7 @@
  */
 ( function ( mw, $ ) {
 
+       var msg = 'Use of mediawiki.api callback params is deprecated. Use the Promise instead.';
        $.extend( mw.Api.prototype, {
 
                /**
                 * @return {jQuery.Promise} See #post
                 */
                postWithEditToken: function ( params, ok, err ) {
+                       if ( ok || err ) {
+                               mw.track( 'mw.deprecate', 'api.cbParam' );
+                               mw.log.warn( msg );
+                       }
                        return this.postWithToken( 'edit', params ).done( ok ).fail( err );
                },
 
                /**
                 * Api helper to grab an edit token.
                 *
-                * @param {Function} [ok] Success callback
-                * @param {Function} [err] Error callback
+                * @param {Function} [ok] Success callback (deprecated)
+                * @param {Function} [err] Error callback (deprecated)
                 * @return {jQuery.Promise}
                 * @return {Function} return.done
                 * @return {string} return.done.token Received token.
                 */
                getEditToken: function ( ok, err ) {
+                       if ( ok || err ) {
+                               mw.track( 'mw.deprecate', 'api.cbParam' );
+                               mw.log.warn( msg );
+                       }
                        return this.getToken( 'edit' ).done( ok ).fail( err );
                },
 
                 * @param {mw.Title|String} title Target page
                 * @param {string} header
                 * @param {string} message wikitext message
-                * @param {Function} [ok] Success handler
-                * @param {Function} [err] Error handler
+                * @param {Function} [ok] Success handler (deprecated)
+                * @param {Function} [err] Error handler (deprecated)
                 * @return {jQuery.Promise}
                 */
                newSection: function ( title, header, message, ok, err ) {
+                       if ( ok || err ) {
+                               mw.track( 'mw.deprecate', 'api.cbParam' );
+                               mw.log.warn( msg );
+                       }
                        return this.postWithEditToken( {
                                action: 'edit',
                                section: 'new',
@@ -50,7 +63,7 @@
                                title: title.toString(),
                                summary: header,
                                text: message
-                       }, ok, err );
+                       } ).done( ok ).fail( err );
                }
        } );
 
index 3032f78..7490862 100644 (file)
                ajax: function ( parameters, ajaxOptions ) {
                        var token,
                                apiDeferred = $.Deferred(),
+                               msg = 'Use of mediawiki.api callback params is deprecated. Use the Promise instead.',
                                xhr;
 
                        parameters = $.extend( {}, this.defaults.parameters, parameters );
                        // Backwards compatibility: Before MediaWiki 1.20,
                        // callbacks were done with the 'ok' and 'err' property in ajaxOptions.
                        if ( ajaxOptions.ok ) {
+                               mw.track( 'mw.deprecate', 'api.cbParam' );
+                               mw.log.warn( msg );
                                apiDeferred.done( ajaxOptions.ok );
                                delete ajaxOptions.ok;
                        }
                        if ( ajaxOptions.err ) {
+                               mw.track( 'mw.deprecate', 'api.cbParam' );
+                               mw.log.warn( msg );
                                apiDeferred.fail( ajaxOptions.err );
                                delete ajaxOptions.err;
                        }
                        apiPromise = this.get( {
                                        action: 'tokens',
                                        type: type
-                               }, {
-                                       // Due to the API assuming we're logged out if we pass the callback-parameter,
-                                       // we have to disable jQuery's callback system, and instead parse JSON string,
-                                       // by setting 'jsonp' to false.
-                                       // TODO: This concern seems genuine but no other module has it. Is it still
-                                       // needed and/or should we pass this by default?
                                } )
                                .done( function ( data ) {
                                        // If token type is not available for this user,
index c4d23b8..1c04b17 100644 (file)
                                apiPromise;
 
                        // Backwards compatibility (< MW 1.20)
-                       d.done( ok ).fail( err );
+                       if ( ok || err ) {
+                               mw.track( 'mw.deprecate', 'api.cbParam' );
+                               mw.log.warn( 'Use of mediawiki.api callback params is deprecated. Use the Promise instead.' );
+                               d.done( ok ).fail( err );
+                       }
 
                        apiPromise = this.get( {
                                        action: 'parse',
index 49a4c62..fbfe27d 100644 (file)
@@ -8,7 +8,7 @@
         * @private
         * @context mw.Api
         *
-        * @param {String|mw.Title} page Full page name or instance of mw.Title
+        * @param {string|mw.Title|string[]|mw.Title[]} page Full page name or instance of mw.Title or array of pages
         * @param {Function} [ok] Success callback (deprecated)
         * @param {Function} [err] Error callback (deprecated)
         * @return {jQuery.Promise}
         * @return {string} return.done.watch.message Parsed HTML of the confirmational interface message
         */
        function doWatchInternal( page, ok, err, addParams ) {
-               var params,
-                       d = $.Deferred(),
-                       apiPromise;
+               // XXX: Parameter addParams is undocumented because we inherit this
+               // documentation in the public method..
+               var params, apiPromise,
+                       d = $.Deferred();
 
                // Backwards compatibility (< MW 1.20)
-               d.done( ok ).fail( err );
+               if ( ok || err ) {
+                       mw.track( 'mw.deprecate', 'api.cbParam' );
+                       mw.log.warn( 'Use of mediawiki.api callback params is deprecated. Use the Promise instead.' );
+                       d.done( ok ).fail( err );
+               }
 
                params = {
                        action: 'watch',
-                       title: String( page ),
+                       titles: $.isArray( page ) ? page.join( '|' ) : String( page ),
                        token: mw.user.tokens.get( 'watchToken' ),
                        uselang: mw.config.get( 'wgUserLanguage' )
                };
diff --git a/resources/mediawiki.less/mediawiki.mixins.animation.less b/resources/mediawiki.less/mediawiki.mixins.animation.less
new file mode 100644 (file)
index 0000000..ec3cddc
--- /dev/null
@@ -0,0 +1,12 @@
+.animation (...) {
+       -webkit-animation: @arguments;
+       -moz-animation: @arguments;
+       -o-animation: @arguments;
+       animation: @arguments;
+}
+
+.transform-rotate (@deg) {
+       -webkit-transform: rotate(@deg);
+       -moz-transform: rotate(@deg);
+       transform: rotate(@deg);
+}
\ No newline at end of file
index 82de5de..e28b333 100644 (file)
@@ -1,31 +1,33 @@
 // This is a separate file because importing the mixin causes
 // the keyframes blocks to be included in the output, regardless
 // of whether .rotation is used.
-@-webkit-keyframes rotate {
+@import "mediawiki.mixins.animation";
+
+.rotate-frames () {
        from {
-               -webkit-transform:rotate(0deg);
+               .transform-rotate(0deg);
        }
        to {
-               -webkit-transform:rotate(360deg);
+               .transform-rotate(360deg);
        }
 }
 
+@-webkit-keyframes rotate {
+       .rotate-frames;
+}
+
+@-moz-keyframes rotate {
+       .rotate-frames;
+}
+
+@-o-keyframes rotate {
+       .rotate-frames;
+}
+
 @keyframes rotate {
-       from {
-               transform: rotate(0deg);
-       }
-       to {
-               transform: rotate(360deg);
-       }
+       .rotate-frames;
 }
 
-.rotation(@time) {
-       -webkit-animation-name: rotate;
-       -webkit-animation-duration: @time;
-       -webkit-animation-iteration-count: infinite;
-       -webkit-animation-timing-function: linear;
-       animation-name: rotate;
-       animation-duration: @time;
-       animation-iteration-count: infinite;
-       animation-timing-function: linear;
+.rotation( @time ) {
+       .animation(rotate, @time, infinite, linear);
 }
index 3def37c..83c2524 100644 (file)
@@ -45,7 +45,7 @@ function pluralRuleParser(rule, number) {
        */
 
        // we don't evaluate the samples section of the rule. Ignore it.
-       rule = rule.split('@')[0].trim();
+       rule = rule.split('@')[0].replace(/^\s*/, '').replace(/\s*$/, '');
 
        if (!rule.length) {
                // empty rule or 'other' rule.
index 9489403..a491c6a 100644 (file)
@@ -72,7 +72,7 @@
                actionPaths = mw.config.get( 'wgActionPaths' );
 
                // TODO: Does MediaWiki give action path or query param
-               // precedence ? If the former, move this to the bottom
+               // precedence? If the former, move this to the bottom
                action = mw.util.getParamValue( 'action', url );
                if ( action !== null ) {
                        return action;
@@ -81,7 +81,7 @@
                for ( key in actionPaths ) {
                        if ( actionPaths.hasOwnProperty( key ) ) {
                                parts = actionPaths[key].split( '$1' );
-                               for ( i = 0; i < parts.length; i += 1 ) {
+                               for ( i = 0; i < parts.length; i++ ) {
                                        parts[i] = $.escapeRE( parts[i] );
                                }
                                m = new RegExp( parts.join( '(.+)' ) ).exec( url );
                        updateWatchLink( $link, action, 'loading' );
 
                        api = new mw.Api();
-                       api[action]( title )
-                       .done( function ( watchResponse ) {
-                               var otherAction;
 
-                               otherAction = action === 'watch' ? 'unwatch' : 'watch';
+                       api[action]( title )
+                               .done( function ( watchResponse ) {
+                                       var otherAction = action === 'watch' ? 'unwatch' : 'watch';
 
-                               mw.notify( $.parseHTML( watchResponse.message ), {
-                                       tag: 'watch-self'
-                               } );
+                                       mw.notify( $.parseHTML( watchResponse.message ), {
+                                               tag: 'watch-self'
+                                       } );
 
-                               // Set link to opposite
-                               updateWatchLink( $link, otherAction );
+                                       // Set link to opposite
+                                       updateWatchLink( $link, otherAction );
 
-                               // Bug 12395 - update the watch checkbox on edit pages when the
-                               // page is watched or unwatched via the tab.
-                               if ( watchResponse.watched !== undefined ) {
-                                       $( '#wpWatchthis' ).prop( 'checked', true );
-                               } else {
-                                       $( '#wpWatchthis' ).prop( 'checked', false );
-                               }
-                       } )
-                       .fail( function () {
-                               var cleanTitle, msg, link;
-
-                               // Reset link to non-loading mode
-                               updateWatchLink( $link, action );
-
-                               // Format error message
-                               cleanTitle = title.replace( /_/g, ' ' );
-                               link = mw.html.element(
-                                       'a', {
-                                               href: mw.util.getUrl( title ),
-                                               title: cleanTitle
-                                       }, cleanTitle
-                               );
-                               msg = mw.message( 'watcherrortext', link );
-
-                               // Report to user about the error
-                               mw.notify( msg, { tag: 'watch-self' } );
-                       } );
+                                       // Update the "Watch this page" checkbox on action=edit when the
+                                       // page is watched or unwatched via the tab (bug 12395).
+                                       $( '#wpWatchthis' ).prop( 'checked', watchResponse.watched !== undefined );
+                               } )
+                               .fail( function () {
+                                       var cleanTitle, msg, link;
+
+                                       // Reset link to non-loading mode
+                                       updateWatchLink( $link, action );
+
+                                       // Format error message
+                                       cleanTitle = title.replace( /_/g, ' ' );
+                                       link = mw.html.element(
+                                               'a', {
+                                                       href: mw.util.getUrl( title ),
+                                                       title: cleanTitle
+                                               }, cleanTitle
+                                       );
+                                       msg = mw.message( 'watcherrortext', link );
+
+                                       // Report to user about the error
+                                       mw.notify( msg, { tag: 'watch-self' } );
+                               } );
                } );
        } );
 
index ee4fc06..a877b74 100644 (file)
@@ -66,7 +66,8 @@ table.mw-listgrouprights-table tr {
 }
 
 /**** Special:Prefixindex ****/
-table#mw-prefixindex-list-table,
+table#mw-prefixindex-list-table, /* HTML backwards-compatibility, to be removed before 1.23 */
+table.mw-prefixindex-list-table,
 table#mw-prefixindex-nav-table {
        width: 98%;
 }
index c293f65..4fafd6d 100644 (file)
@@ -3,7 +3,7 @@
  */
 ( function ( mw, $ ) {
        // When sending password by email, hide the password input fields.
-       function hidePasswordOnEmail() {
+       $( function () {
                // Always required if checked, otherwise it depends, so we use the original
                var $emailLabel = $( 'label[for="wpEmail"]' ),
                        originalText = $emailLabel.text(),
 
                $createByMailCheckbox.on( 'change', updateForCheckbox );
                updateForCheckbox();
-       }
+       } );
 
-       $( hidePasswordOnEmail );
+       // Show username normalisation warning
+       $( function () {
+               var
+                       // All of these are apparently required to be sure we detect any changes.
+                       events = 'keyup keydown change mouseup cut paste focus blur',
+                       $input = $( '#wpName2' ),
+                       $warningContainer = $( '#mw-createacct-status-area' ),
+                       api = new mw.Api(),
+                       currentRequest,
+                       tweakedUsername;
+
+               // Hide any warnings / errors.
+               function cleanup() {
+                       $warningContainer.slideUp( function () {
+                               $warningContainer
+                                       .removeAttr( 'class' )
+                                       .empty();
+                       } );
+               }
+
+               function updateUsernameStatus() {
+                       var
+                               // Leading/trailing/multiple whitespace characters are never accepted in usernames and users
+                               // know that, don't warn if someone accidentally types it. We do warn about underscores.
+                               username = $.trim( $input.val().replace( /\s+/g, ' ' ) ),
+                               currentRequestInternal;
+
+                       // Abort any pending requests.
+                       if ( currentRequest ) {
+                               currentRequest.abort();
+                       }
+
+                       if ( username === '' ) {
+                               cleanup();
+                               return;
+                       }
+
+                       currentRequest = currentRequestInternal = api.get( {
+                               action: 'query',
+                               list: 'users',
+                               ususers: username // '|' in usernames is handled below
+                       } ).done( function ( resp ) {
+                               var userinfo, state;
+
+                               // Another request was fired in the meantime, the result we got here is no longer current.
+                               // This shouldn't happen as we abort pending requests, but you never know.
+                               if ( currentRequest !== currentRequestInternal ) {
+                                       return;
+                               }
+
+                               tweakedUsername = undefined;
+
+                               userinfo = resp.query.users[0];
+
+                               if ( resp.query.users.length !== 1 ) {
+                                       // Happens if the user types '|' into the field
+                                       state = 'invalid';
+                               } else if ( userinfo.invalid !== undefined ) {
+                                       state = 'invalid';
+                               } else if ( userinfo.userid !== undefined ) {
+                                       state = 'taken';
+                               } else if ( username !== userinfo.name ) {
+                                       state = 'tweaked';
+                               } else {
+                                       state = 'ok';
+                               }
+
+                               if ( state === 'ok' ) {
+                                       cleanup();
+                               } else if ( state === 'tweaked' ) {
+                                       $warningContainer
+                                               .attr( 'class', 'warningbox' )
+                                               .text( mw.message( 'createacct-normalization', username, userinfo.name ).text() )
+                                               .slideDown();
+
+                                       tweakedUsername = userinfo.name;
+                               } else {
+                                       $warningContainer
+                                               .attr( 'class', 'errorbox' )
+                                               .empty()
+                                               .append(
+                                                       $( '<strong>' ).text( mw.message( 'createacct-error' ).text() ),
+                                                       $( '<br>' ) // Ugh
+                                               );
+
+                                       if ( state === 'invalid' ) {
+                                               $warningContainer
+                                                       .attr( 'class', 'errorbox' )
+                                                       .append( document.createTextNode( mw.message( 'noname' ).text() ) )
+                                                       .slideDown();
+                                       } else if ( state === 'taken' ) {
+                                               $warningContainer
+                                                       .attr( 'class', 'errorbox' )
+                                                       .append( document.createTextNode( mw.message( 'userexists' ).text() ) )
+                                                       .slideDown();
+                                       }
+
+                                       $warningContainer.slideDown();
+                               }
+                       } ).fail( function () {
+                               cleanup();
+                       } );
+               }
+
+               $input.on( events, $.debounce( 250, updateUsernameStatus ) );
+
+               $input.closest( 'form' ).on( 'submit', function () {
+                       // If the username has to be adjusted before it's accepted, server-side check will force the
+                       // form to be resubmitted. Let's prevent that.
+                       if ( tweakedUsername !== undefined ) {
+                               $input.val( tweakedUsername );
+                       }
+               } );
+       } );
 }( mediaWiki, jQuery ) );
index 66f4487..5c6aa6a 100644 (file)
@@ -66,7 +66,7 @@
                        .box-sizing(border-box);
                        .agora-label-styling();
                        width: auto;
-                       margin: 0 0 0.2em 0;
+                       margin: 0 0 0.2em;
                        padding: 0;
                }
 
        .error {
                .box-sizing(border-box);
                font-size: 0.9em;
-               margin: 0 0 1em 0;
+               margin: 0 0 1em;
                padding: 0.5em;
                color: #cc0000;
                border: 1px solid #fac5c5;
 // XXX DRY: This repeats earlier styling, use an @include agora-div-styling ?
 .mw-ui-vform-div {
        display: block;
-       margin: 0 0 15px 0;
+       margin: 0 0 15px;
        padding: 0;
        width: 100%;
 }
index b32e4e7..20f42a0 100644 (file)
@@ -12,7 +12,7 @@
                        outline: 0; // Removes OS field focus
                }
 
-               box-shadow: @colorProgressiveShadow 0px 0px 5px;
+               box-shadow: @colorProgressiveShadow 0 0 5px;
 
                border-color: @colorProgressiveShadow;
        }
@@ -46,7 +46,7 @@
        & > input[type="radio"] {
                width: auto;
                height: auto;
-               margin: 0 0.1em 0em 0;
+               margin: 0 0.1em 0 0;
                padding: 0;
                border: 1px solid @colorGrayLight;
                cursor: pointer;
diff --git a/resources/mediawiki/mediawiki.debug.css b/resources/mediawiki/mediawiki.debug.css
deleted file mode 100644 (file)
index 513cb84..0000000
+++ /dev/null
@@ -1,183 +0,0 @@
-.mw-debug {
-       width: 100%;
-       background-color: #eee;
-       border-top: 1px solid #aaa;
-}
-
-.mw-debug pre {
-       font-size: 11px;
-       padding: 0;
-       margin: 0;
-       background: none;
-       border: none;
-}
-
-.mw-debug table {
-       border-spacing: 0;
-       width: 100%;
-       table-layout: fixed;
-}
-
-.mw-debug table tr {
-       background-color: #fff;
-}
-
-.mw-debug table tr:nth-child(even) {
-       background-color: #f9f9f9;
-}
-
-.mw-debug table td, .mw-debug table th  {
-       padding: 4px 10px;
-}
-
-.mw-debug table td {
-       border-bottom: 1px solid #eee;
-       word-wrap: break-word;
-}
-
-.mw-debug table td.nr {
-       text-align: right;
-}
-
-.mw-debug table td span.stats {
-       color: #808080;
-}
-
-.mw-debug ul {
-       margin: 0;
-       list-style: none;
-}
-
-.mw-debug li {
-       padding: 4px 0;
-       width: 100%;
-}
-
-.mw-debug-bits {
-       text-align: center;
-       border-bottom: 1px solid #aaa;
-}
-
-.mw-debug-bit {
-       display: inline-block;
-       padding: 10px 5px;
-       font-size: 13px;
-       /* IE-hack for display: inline-block */
-       zoom: 1;
-       *display:inline;
-}
-
-.mw-debug-panelink {
-       background-color: #eee;
-       border-right: 1px solid #ccc;
-}
-
-.mw-debug-panelink:first-child {
-       border-left: 1px solid #ccc;
-}
-
-.mw-debug-panelink:hover {
-       background-color: #fefefe;
-       cursor: pointer;
-}
-.mw-debug-panelink.current {
-       background-color: #dedede;
-
-}
-a.mw-debug-panelabel,
-a.mw-debug-panelabel:visited {
-       color: #000;
-}
-
-.mw-debug-pane {
-       height: 300px;
-       overflow: scroll;
-       display: none;
-       font-size: 11px;
-       background-color: #e1eff2;
-       box-sizing: border-box;
-}
-
-#mw-debug-pane-debuglog,
-#mw-debug-pane-request {
-       padding: 20px;
-}
-
-#mw-debug-pane-request table {
-       width: 100%;
-       margin: 10px 0 30px;
-}
-
-#mw-debug-pane-request tr,
-#mw-debug-pane-request th,
-#mw-debug-pane-request td,
-#mw-debug-pane-request table {
-       border: 1px solid #D0DBB3;
-       border-collapse: collapse;
-       margin: 0;
-}
-
-#mw-debug-pane-request th,
-#mw-debug-pane-request td {
-       font-size: 12px;
-       padding: 8px 10px;
-}
-
-#mw-debug-pane-request th {
-       background-color: #F1F7E2;
-       font-weight: bold;
-}
-
-#mw-debug-pane-request td {
-       background-color: white;
-}
-
-#mw-debug-console tr td:first-child {
-       font-weight: bold;
-       vertical-align: top;
-}
-
-#mw-debug-console tr td:last-child {
-       vertical-align: top;
-}
-
-.mw-debug-console-log {
-       background-color: #add8e6;
-}
-
-.mw-debug-console-warn {
-       background-color: #ffa07a;
-}
-
-.mw-debug-console-deprecated {
-       background-color: #ffb6c1;
-}
-
-.mw-debug-backtrace {
-       padding: 5px 10px;
-       margin: 5px;
-       background-color: #dedede;
-}
-
-.mw-debug-backtrace span {
-       font-weight: bold;
-       color: #111;
-}
-
-.mw-debug-backtrace ul {
-       padding-left: 10px;
-}
-
-.mw-debug-backtrace li {
-       width: auto;
-       padding: 0;
-       color: #333;
-       font-size: 10px;
-       margin-bottom: 0;
-       line-height: 1em;
-}
-
-/* Cheapo hack to hide the first 3 lines of the backtrace */
-.mw-debug-backtrace li:nth-child(-n+3) {
-       display: none;
-}
diff --git a/resources/mediawiki/mediawiki.debug.less b/resources/mediawiki/mediawiki.debug.less
new file mode 100644 (file)
index 0000000..949c558
--- /dev/null
@@ -0,0 +1,189 @@
+.mw-debug {
+       width: 100%;
+       background-color: #eee;
+       border-top: 1px solid #aaa;
+
+       pre {
+               font-size: 11px;
+               padding: 0;
+               margin: 0;
+               background: none;
+               border: none;
+       }
+
+       table {
+               border-spacing: 0;
+               width: 100%;
+               table-layout: fixed;
+
+               td,
+               th {
+                       padding: 4px 10px;
+               }
+
+               td {
+                       border-bottom: 1px solid #eee;
+                       word-wrap: break-word;
+
+                       &.nr {
+                               text-align: right;
+                       }
+
+                       span.stats {
+                               color: #808080;
+                       }
+               }
+
+               tr {
+                       background-color: #fff;
+
+                       &:nth-child(even) {
+                               background-color: #f9f9f9;
+                       }
+               }
+       }
+
+       ul {
+               margin: 0;
+               list-style: none;
+       }
+
+       li {
+               padding: 4px 0;
+               width: 100%;
+       }
+}
+
+.mw-debug-bits {
+       text-align: center;
+       border-bottom: 1px solid #aaa;
+}
+
+.mw-debug-bit {
+       display: inline-block;
+       padding: 10px 5px;
+       font-size: 13px;
+       /* IE-hack for display: inline-block */
+       zoom: 1;
+       *display:inline;
+}
+
+.mw-debug-panelink {
+       background-color: #eee;
+       border-right: 1px solid #ccc;
+
+       &:first-child {
+               border-left: 1px solid #ccc;
+       }
+
+       &:hover {
+               background-color: #fefefe;
+               cursor: pointer;
+       }
+
+       &.current {
+               background-color: #dedede;
+       }
+}
+
+a.mw-debug-panelabel,
+a.mw-debug-panelabel:visited {
+       color: #000;
+}
+
+.mw-debug-pane {
+       height: 300px;
+       overflow: scroll;
+       display: none;
+       font-size: 11px;
+       background-color: #e1eff2;
+       box-sizing: border-box;
+}
+
+#mw-debug-pane-debuglog,
+#mw-debug-pane-request {
+       padding: 20px;
+}
+
+#mw-debug-pane-request {
+       table {
+               width: 100%;
+               margin: 10px 0 30px;
+       }
+
+       tr,
+       th,
+       td,
+       table {
+               border: 1px solid #D0DBB3;
+               border-collapse: collapse;
+               margin: 0;
+       }
+
+       th,
+       td {
+               font-size: 12px;
+               padding: 8px 10px;
+       }
+
+       th {
+               background-color: #F1F7E2;
+               font-weight: bold;
+       }
+
+       td {
+               background-color: white;
+       }
+}
+
+#mw-debug-console tr td {
+       &:first-child {
+               font-weight: bold;
+               vertical-align: top;
+       }
+
+       &:last-child {
+               vertical-align: top;
+       }
+}
+
+.mw-debug-backtrace {
+       padding: 5px 10px;
+       margin: 5px;
+       background-color: #dedede;
+
+       span {
+               font-weight: bold;
+               color: #111;
+       }
+
+       ul {
+               padding-left: 10px;
+       }
+
+       li {
+               width: auto;
+               padding: 0;
+               color: #333;
+               font-size: 10px;
+               margin-bottom: 0;
+               line-height: 1em;
+       }
+}
+
+.mw-debug-console-log {
+       background-color: #add8e6;
+}
+
+.mw-debug-console-warn {
+       background-color: #ffa07a;
+}
+
+.mw-debug-console-deprecated {
+       background-color: #ffb6c1;
+}
+
+/* Cheapo hack to hide the first 3 lines of the backtrace */
+.mw-debug-backtrace li:nth-child(-n+3) {
+       display: none;
+}
index 8b78370..a7c946d 100644 (file)
@@ -558,20 +558,19 @@ var mw = ( function ( $, undefined ) {
                        log.deprecate = !Object.defineProperty ? function ( obj, key, val ) {
                                obj[key] = val;
                        } : function ( obj, key, val, msg ) {
-                               msg = 'MWDeprecationWarning: Use of "' + key + '" property is deprecated.' +
-                                       ( msg ? ( ' ' + msg ) : '' );
+                               msg = 'Use of "' + key + '" is deprecated.' + ( msg ? ( ' ' + msg ) : '' );
                                try {
                                        Object.defineProperty( obj, key, {
                                                configurable: true,
                                                enumerable: true,
                                                get: function () {
                                                        mw.track( 'mw.deprecate', key );
-                                                       log.warn( msg );
+                                                       mw.log.warn( msg );
                                                        return val;
                                                },
                                                set: function ( newVal ) {
                                                        mw.track( 'mw.deprecate', key );
-                                                       log.warn( msg );
+                                                       mw.log.warn( msg );
                                                        val = newVal;
                                                }
                                        } );
@@ -768,11 +767,11 @@ var mw = ( function ( $, undefined ) {
                                        return;
                                }
 
-                               // By default, always create a new <style>. Appending text
-                               // to a <style> tag means the contents have to be re-parsed (bug 45810).
-                               // Except, of course, in IE below 9, in there we default to
-                               // re-using and appending to a <style> tag due to the
-                               // IE stylesheet limit (bug 31676).
+                               // By default, always create a new <style>. Appending text to a <style>
+                               // tag is bad as it means the contents have to be re-parsed (bug 45810).
+                               //
+                               // Except, of course, in IE 9 and below. In there we default to re-using and
+                               // appending to a <style> tag due to the IE stylesheet limit (bug 31676).
                                if ( 'documentMode' in document && document.documentMode <= 9 ) {
 
                                        $style = getMarker().prev();
@@ -1139,11 +1138,14 @@ var mw = ( function ( $, undefined ) {
                                 */
                                function addLink( media, url ) {
                                        var el = document.createElement( 'link' );
-                                       getMarker().before( el ); // IE: Insert in dom before setting href
+                                       // For IE: Insert in document *before* setting href
+                                       getMarker().before( el );
                                        el.rel = 'stylesheet';
                                        if ( media && media !== 'all' ) {
                                                el.media = media;
                                        }
+                                       // If you end up here from an IE exception "SCRIPT: Invalid property value.",
+                                       // see #addEmbeddedCSS, bug 31676, and bug 47277 for details.
                                        el.href = url;
                                }
 
@@ -1403,7 +1405,7 @@ var mw = ( function ( $, undefined ) {
                                 */
                                work: function () {
                                        var     reqBase, splits, maxQueryLength, q, b, bSource, bGroup, bSourceGroup,
-                                               source, concatSource, group, g, i, modules, maxVersion, sourceLoadScript,
+                                               source, concatSource, origBatch, group, g, i, modules, maxVersion, sourceLoadScript,
                                                currReqBase, currReqBaseLength, moduleMap, l,
                                                lastDotIndex, prefix, suffix, bytesAdded, async;
 
@@ -1433,6 +1435,7 @@ var mw = ( function ( $, undefined ) {
                                        mw.loader.store.init();
                                        if ( mw.loader.store.enabled ) {
                                                concatSource = [];
+                                               origBatch = batch;
                                                batch = $.grep( batch, function ( module ) {
                                                        var source = mw.loader.store.get( module );
                                                        if ( source ) {
@@ -1441,7 +1444,29 @@ var mw = ( function ( $, undefined ) {
                                                        }
                                                        return true;
                                                } );
-                                               $.globalEval( concatSource.join( ';' ) );
+                                               try {
+                                                       $.globalEval( concatSource.join( ';' ) );
+                                               } catch ( err ) {
+                                                       // Not good, the cached mw.loader.implement calls failed! This should
+                                                       // never happen, barring ResourceLoader bugs, browser bugs and PEBKACs.
+                                                       // Depending on how corrupt the string is, it is likely that some
+                                                       // modules' implement() succeeded while the ones after the error will
+                                                       // never run and leave their modules in the 'loading' state forever.
+
+                                                       // Since this is an error not caused by an individual module but by
+                                                       // something that infected the implement call itself, don't take any
+                                                       // risks and clear everything in this cache.
+                                                       mw.loader.store.clear();
+                                                       // Re-add the ones still pending back to the batch and let the server
+                                                       // repopulate these modules to the cache.
+                                                       // This means that at most one module will be useless (the one that had
+                                                       // the error) instead of all of them.
+                                                       log( 'Error while evaluating data from mw.loader.store', err );
+                                                       origBatch = $.grep( origBatch, function ( module ) {
+                                                               return registry[module].state === 'loading';
+                                                       } );
+                                                       batch = batch.concat( origBatch );
+                                               }
                                        }
 
                                        // Early exit if there's nothing to load...
@@ -2091,6 +2116,14 @@ var mw = ( function ( $, undefined ) {
                                                }
                                        },
 
+                                       /**
+                                        * Clear the entire module store right now.
+                                        */
+                                       clear: function () {
+                                               mw.loader.store.items = {};
+                                               localStorage.removeItem( mw.loader.store.getStoreKey() );
+                                       },
+
                                        /**
                                         * Sync modules to localStorage.
                                         *
@@ -2353,7 +2386,8 @@ var mw = ( function ( $, undefined ) {
 }( jQuery ) );
 
 // Alias $j to jQuery for backwards compatibility
-window.$j = jQuery;
+// @deprecated since 1.23 Use $ or jQuery instead
+mw.log.deprecate( window, '$j', jQuery, 'Use $ or jQuery instead.' );
 
 // Attach to window and globally alias
 window.mw = window.mediaWiki = mw;
index 78febd2..8344111 100644 (file)
                 *         expires: 7
                 *     } );
                 *
+                * @deprecated since 1.23
                 * @param {string} key Name of bucket
                 * @param {Object} options Bucket configuration options
                 * @param {Object} options.buckets List of bucket-name/relative-probability pairs (required,
index 959ea23..fe6ea0a 100644 (file)
@@ -9,5 +9,6 @@
     "ooui-dialog-action-close": "Zarrar",
     "ooui-outline-control-move-down": "Mover abaxo l'elementu",
     "ooui-outline-control-move-up": "Mover arriba l'elementu",
+    "ooui-outline-control-remove": "Desaniciar elementu",
     "ooui-toolbar-more": "Más"
 }
\ No newline at end of file
index 67e664b..939719b 100644 (file)
@@ -3,9 +3,11 @@
         "authors": [
             "DCLXVI",
             "Hristofor.mirchev",
-            "පසිඳු කාවින්ද"
+            "පසිඳු කාවින්ද",
+            "Mitzev"
         ]
     },
     "ooui-dialog-action-close": "Затваряне",
+    "ooui-outline-control-remove": "Премахване на обекти",
     "ooui-toolbar-more": "Още"
 }
\ No newline at end of file
index 3a66648..bed2b2c 100644 (file)
@@ -16,5 +16,6 @@
     "ooui-dialog-action-close": "Schließen",
     "ooui-outline-control-move-down": "Element nach unten verschieben",
     "ooui-outline-control-move-up": "Element nach oben verschieben",
+    "ooui-outline-control-remove": "Element entfernen",
     "ooui-toolbar-more": "Mehr"
 }
\ No newline at end of file
index d402de8..5ff9915 100644 (file)
@@ -19,5 +19,6 @@
     "ooui-dialog-action-close": "Close",
     "ooui-outline-control-move-down": "Move item down",
     "ooui-outline-control-move-up": "Move item up",
+    "ooui-outline-control-remove": "Remove item",
     "ooui-toolbar-more": "More"
 }
index eb24b5a..7674d2f 100644 (file)
@@ -31,5 +31,6 @@
     "ooui-dialog-action-close": "Fermer",
     "ooui-outline-control-move-down": "Faire descendre l’élément",
     "ooui-outline-control-move-up": "Faire monter l’élément",
+    "ooui-outline-control-remove": "Supprimer l’élément",
     "ooui-toolbar-more": "Plus"
 }
\ No newline at end of file
index b20c5f3..f674cd2 100644 (file)
@@ -8,5 +8,6 @@
     "ooui-dialog-action-close": "Začinić",
     "ooui-outline-control-move-down": "Zapisk dele přesunyć",
     "ooui-outline-control-move-up": "Zapisk horje přesunyć",
+    "ooui-outline-control-remove": "Zapisk wotstronić",
     "ooui-toolbar-more": "Wjace"
 }
\ No newline at end of file
index f6cb90b..4cb8821 100644 (file)
@@ -8,5 +8,6 @@
     "ooui-dialog-action-close": "Փակել",
     "ooui-outline-control-move-down": "Իջեցնել կետը",
     "ooui-outline-control-move-up": "Բարձրացնել կետը",
+    "ooui-outline-control-remove": "Հեռացնել տարրը",
     "ooui-toolbar-more": "Ավելին"
 }
\ No newline at end of file
index efe0e67..fbdb5d1 100644 (file)
@@ -6,7 +6,7 @@
         ]
     },
     "ooui-dialog-action-close": "Loka",
-    "ooui-outline-control-move-down": "Færa atriða niður",
-    "ooui-outline-control-move-up": "Færa atriða upp",
+    "ooui-outline-control-move-down": "Færa atriði niður",
+    "ooui-outline-control-move-up": "Færa atriði upp",
     "ooui-toolbar-more": "Fleira"
 }
\ No newline at end of file
index 6158cff..747ec79 100644 (file)
@@ -17,5 +17,6 @@
     "ooui-dialog-action-close": "Chiudi",
     "ooui-outline-control-move-down": "Sposta in basso",
     "ooui-outline-control-move-up": "Sposta in alto",
+    "ooui-outline-control-remove": "Rimuovi elemento",
     "ooui-toolbar-more": "Altro"
 }
\ No newline at end of file
index 789fbeb..c7c0851 100644 (file)
@@ -10,5 +10,6 @@
     "ooui-dialog-action-close": "閉じる",
     "ooui-outline-control-move-down": "項目を下に移動させる",
     "ooui-outline-control-move-up": "項目を上に移動させる",
+    "ooui-outline-control-remove": "項目を除去",
     "ooui-toolbar-more": "その他"
 }
\ No newline at end of file
index f1f61df..25749ce 100644 (file)
@@ -11,5 +11,6 @@
     "ooui-dialog-action-close": "닫기",
     "ooui-outline-control-move-down": "항목을 아래로 옮기기",
     "ooui-outline-control-move-up": "항목을 위로 옮기기",
+    "ooui-outline-control-remove": "항목 지우기",
     "ooui-toolbar-more": "더 보기"
 }
\ No newline at end of file
index a18894e..6359026 100644 (file)
@@ -13,5 +13,6 @@
     "ooui-dialog-action-close": "Zoumaachen",
     "ooui-outline-control-move-down": "Element erof réckelen",
     "ooui-outline-control-move-up": "Element erop réckelen",
+    "ooui-outline-control-remove": "Element ewechhuelen",
     "ooui-toolbar-more": "Méi"
 }
\ No newline at end of file
index b3a16e8..db679bc 100644 (file)
@@ -2,8 +2,10 @@
     "@metadata": {
         "authors": [
             "Audriusa",
-            "Eitvys200"
+            "Eitvys200",
+            "Mantak111"
         ]
     },
-    "ooui-dialog-action-close": "Uždaryti"
+    "ooui-dialog-action-close": "Uždaryti",
+    "ooui-outline-control-remove": "Šalinti elementus"
 }
\ No newline at end of file
index b363a45..22fd037 100644 (file)
@@ -9,5 +9,6 @@
     "ooui-dialog-action-close": "Затвори",
     "ooui-outline-control-move-down": "Помести надолу",
     "ooui-outline-control-move-up": "Помести нагоре",
+    "ooui-outline-control-remove": "Отстрани ставка",
     "ooui-toolbar-more": "Повеќе"
 }
\ No newline at end of file
index 75db0a7..549fad2 100644 (file)
             "Saruman",
             "Siebrand",
             "Southparkfan",
-            "सरोज कुमार ढकाल"
+            "सरोज कुमार ढकाल",
+            "Sjoerddebruin"
         ]
     },
     "ooui-dialog-action-close": "Sluiten",
     "ooui-outline-control-move-down": "Item omlaag verplaatsen",
     "ooui-outline-control-move-up": "Item omhoog verplaatsen",
+    "ooui-outline-control-remove": "Item verwijderen",
     "ooui-toolbar-more": "Meer"
 }
\ No newline at end of file
index dca7b7d..cd22c40 100644 (file)
@@ -8,5 +8,6 @@
     "ooui-dialog-action-close": "Cufi",
     "ooui-outline-control-move-down": "Gad buusi",
     "ooui-outline-control-move-up": "Ol baasi",
+    "ooui-outline-control-remove": "Balleessi",
     "ooui-toolbar-more": "Dabalata"
 }
\ No newline at end of file
index ba33322..8798603 100644 (file)
             "Ty221",
             "WTM",
             "Woytecr",
-            "Wpedzich"
+            "Wpedzich",
+            "Jacenty359"
         ]
     },
     "ooui-dialog-action-close": "Zamknij",
     "ooui-outline-control-move-down": "Przenieś niżej",
     "ooui-outline-control-move-up": "Przenieś wyżej",
+    "ooui-outline-control-remove": "Usuń przedmiot",
     "ooui-toolbar-more": "Więcej"
 }
\ No newline at end of file
index 78a70d9..75bbec4 100644 (file)
@@ -22,5 +22,6 @@
     "ooui-dialog-action-close": "Label text for button to exit from dialog.\n\n{{Identical|Close}}",
     "ooui-outline-control-move-down": "Tool tip for a button that moves items in a list down one place",
     "ooui-outline-control-move-up": "Tool tip for a button that moves items in a list up one place",
+    "ooui-outline-control-remove": "Tool tip for a button that removes items from a list.\n{{Identical|Remove item}}",
     "ooui-toolbar-more": "Label for the toolbar group that contains a list of all other available tools.\n{{Identical|More}}"
 }
\ No newline at end of file
index 861b2fe..4892975 100644 (file)
@@ -10,5 +10,6 @@
     "ooui-dialog-action-close": "Închide",
     "ooui-outline-control-move-down": "Mută elementul mai jos",
     "ooui-outline-control-move-up": "Mută elementul mai sus",
+    "ooui-outline-control-remove": "Elimină elementul",
     "ooui-toolbar-more": "Mai mult"
 }
\ No newline at end of file
index be7c6a5..f6e76a6 100644 (file)
@@ -21,5 +21,6 @@
     "ooui-dialog-action-close": "Закрыть",
     "ooui-outline-control-move-down": "Переместить элемент вниз",
     "ooui-outline-control-move-up": "Переместить элемент вверх",
+    "ooui-outline-control-remove": "Удалить пункт",
     "ooui-toolbar-more": "Ещё"
 }
\ No newline at end of file
index d5bffd9..b14d47b 100644 (file)
@@ -10,5 +10,6 @@
     "ooui-dialog-action-close": "Zapri",
     "ooui-outline-control-move-down": "Prestavi predmet nižje",
     "ooui-outline-control-move-up": "Prestavi predmet višje",
+    "ooui-outline-control-remove": "Odstrani vnos",
     "ooui-toolbar-more": "Več"
 }
\ No newline at end of file
index 424f1be..6c31c93 100644 (file)
@@ -1,11 +1,13 @@
 {
     "@metadata": {
         "authors": [
-            "Euriditi"
+            "Euriditi",
+            "Kushtrim"
         ]
     },
     "ooui-dialog-action-close": "Mbylle",
     "ooui-outline-control-move-down": "Zhvendose artikullin më poshtë",
     "ooui-outline-control-move-up": "Zhvendose artikullin më lart",
+    "ooui-outline-control-remove": "Largoje artikullin",
     "ooui-toolbar-more": "Më tepër..."
 }
\ No newline at end of file
index 973baec..7eaaacd 100644 (file)
@@ -9,5 +9,6 @@
     "ooui-dialog-action-close": "Затвори",
     "ooui-outline-control-move-down": "Премести ставку на доле",
     "ooui-outline-control-move-up": "Премести ставку на горе",
+    "ooui-outline-control-remove": "Уклони ставку",
     "ooui-toolbar-more": "Више"
 }
\ No newline at end of file
index 74d654b..f7d6f04 100644 (file)
             "Per",
             "Sendelbach",
             "Skalman",
-            "WikiPhoenix"
+            "WikiPhoenix",
+            "Lokal Profil"
         ]
     },
     "ooui-dialog-action-close": "Stäng",
     "ooui-outline-control-move-down": "Flytta ned objekt",
     "ooui-outline-control-move-up": "Flytta upp objekt",
+    "ooui-outline-control-remove": "Ta bort objekt",
     "ooui-toolbar-more": "Mer"
 }
\ No newline at end of file
index 9a47ad7..42487c9 100644 (file)
@@ -20,5 +20,6 @@
     "ooui-dialog-action-close": "Закрити",
     "ooui-outline-control-move-down": "Перемістити елемент униз",
     "ooui-outline-control-move-up": "Перемістити елемент вгору",
+    "ooui-outline-control-remove": "Видалити елемент",
     "ooui-toolbar-more": "Більше"
 }
\ No newline at end of file
index 46cbae3..58e8ebe 100644 (file)
@@ -21,5 +21,6 @@
     "ooui-dialog-action-close": "关闭",
     "ooui-outline-control-move-down": "下移项",
     "ooui-outline-control-move-up": "上移项",
+    "ooui-outline-control-remove": "移除项",
     "ooui-toolbar-more": "更多"
 }
\ No newline at end of file
index 9aace2f..6e7b12e 100644 (file)
@@ -18,5 +18,6 @@
     "ooui-dialog-action-close": "關閉",
     "ooui-outline-control-move-down": "向下移項",
     "ooui-outline-control-move-up": "向上移項",
+    "ooui-outline-control-remove": "移除項",
     "ooui-toolbar-more": "更多"
 }
\ No newline at end of file
diff --git a/resources/oojs-ui/oojs-ui-apex.css b/resources/oojs-ui/oojs-ui-apex.css
new file mode 100644 (file)
index 0000000..66a8072
--- /dev/null
@@ -0,0 +1,663 @@
+.oo-ui-dialog {
+  background-color: #fff;
+  background-color: rgba(255, 255, 255, 0.5);
+  opacity: 0;
+  -webkit-transition: all 250ms ease-in-out;
+     -moz-transition: all 250ms ease-in-out;
+      -ms-transition: all 250ms ease-in-out;
+       -o-transition: all 250ms ease-in-out;
+          transition: all 250ms ease-in-out;
+}
+
+.oo-ui-dialog .oo-ui-window-frame {
+  background-color: #fff;
+  border: solid 1px #ccc;
+  border-radius: 0.5em;
+  -webkit-transform: scale(0.5);
+     -moz-transform: scale(0.5);
+      -ms-transform: scale(0.5);
+       -o-transform: scale(0.5);
+          transform: scale(0.5);
+  box-shadow: 0 0.2em 1em rgba(0, 0, 0, 0.3);
+  -webkit-transition: all 250ms ease-in-out;
+     -moz-transition: all 250ms ease-in-out;
+      -ms-transition: all 250ms ease-in-out;
+       -o-transition: all 250ms ease-in-out;
+          transition: all 250ms ease-in-out;
+}
+
+.oo-ui-dialog-open {
+  opacity: 1;
+}
+
+.oo-ui-dialog-open .oo-ui-window-frame {
+  -webkit-transform: scale(1);
+     -moz-transform: scale(1);
+      -ms-transform: scale(1);
+       -o-transform: scale(1);
+          transform: scale(1);
+}
+
+.oo-ui-dialog-content .oo-ui-window-body {
+  box-shadow: 0 0 0.66em rgba(0, 0, 0, 0.25);
+}
+
+.oo-ui-toolbar-bar {
+  background: #f8fbfd;
+  background-image: -webkit-gradient(linear, right top, right bottom, color-stop(0%, #ffffff), color-stop(100%, #f1f7fb));
+  background-image: -webkit-linear-gradient(top, #ffffff 0%, #f1f7fb 100%);
+  background-image: -moz-linear-gradient(top, #ffffff 0%, #f1f7fb 100%);
+  background-image: -ms-linear-gradient(top, #ffffff 0%, #f1f7fb 100%);
+  background-image: -o-linear-gradient(top, #ffffff 0%, #f1f7fb 100%);
+  background-image: linear-gradient(top, #ffffff 0%, #f1f7fb 100%);
+  border-bottom: solid 1px #ccc;
+  filter: progid:DXImageTransform.Microsoft.gradient(GradientType=0, startColorstr='#ffffff', endColorstr='#f1f7fb');
+}
+
+.oo-ui-toolbar-bar .oo-ui-toolbar-bar {
+  background: none;
+  border: none;
+}
+
+.oo-ui-toolbar-shadow {
+  bottom: -9px;
+  height: 9px;
+  background-image: /* @embed */ url(images/toolbar-shadow.png);
+  opacity: 0.125;
+  -webkit-transition: opacity 500ms ease-in-out;
+     -moz-transition: opacity 500ms ease-in-out;
+      -ms-transition: opacity 500ms ease-in-out;
+       -o-transition: opacity 500ms ease-in-out;
+          transition: opacity 500ms ease-in-out;
+}
+
+.oo-ui-toolGroup {
+  border: solid 1px transparent;
+  border-radius: 0.25em;
+  -webkit-transition: border-color 300ms ease-in-out;
+     -moz-transition: border-color 300ms ease-in-out;
+      -ms-transition: border-color 300ms ease-in-out;
+       -o-transition: border-color 300ms ease-in-out;
+          transition: border-color 300ms ease-in-out;
+}
+
+.oo-ui-toolGroup:hover {
+  border-color: rgba(0, 0, 0, 0.1);
+}
+
+.oo-ui-toolGroup .oo-ui-tool-link .oo-ui-tool-title {
+  color: #000;
+}
+
+.oo-ui-window-title {
+  color: #333;
+}
+
+.oo-ui-window-overlay {
+  font-family: sans-serif;
+  font-size: 1em;
+  line-height: 1.5em;
+}
+
+.oo-ui-buttonedElement .oo-ui-buttonedElement-button {
+  color: #333;
+}
+
+.oo-ui-buttonedElement.oo-ui-indicatedElement .oo-ui-buttonedElement-button > .oo-ui-indicatedElement-indicator,
+.oo-ui-buttonedElement.oo-ui-iconedElement .oo-ui-buttonedElement-button > .oo-ui-iconedElement-icon {
+  opacity: 0.8;
+}
+
+.oo-ui-buttonedElement-frameless .oo-ui-buttonedElement-button > .oo-ui-iconedElement-icon {
+  -webkit-transition: opacity 200ms;
+     -moz-transition: opacity 200ms;
+      -ms-transition: opacity 200ms;
+       -o-transition: opacity 200ms;
+          transition: opacity 200ms;
+}
+
+.oo-ui-buttonedElement-frameless .oo-ui-buttonedElement-button:hover > .oo-ui-iconedElement-icon,
+.oo-ui-buttonedElement-frameless .oo-ui-buttonedElement-button:focus > .oo-ui-iconedElement-icon {
+  opacity: 1;
+}
+
+.oo-ui-buttonedElement-frameless .oo-ui-buttonedElement-button:hover > .oo-ui-labeledElement-label,
+.oo-ui-buttonedElement-frameless .oo-ui-buttonedElement-button:focus > .oo-ui-labeledElement-label {
+  color: #000;
+}
+
+.oo-ui-buttonedElement-frameless .oo-ui-buttonedElement-button > .oo-ui-labeledElement-label {
+  color: #333;
+}
+
+.oo-ui-buttonedElement-frameless.oo-ui-widget-disabled .oo-ui-buttonedElement-button > .oo-ui-iconedElement-icon {
+  opacity: 0.2;
+}
+
+.oo-ui-buttonedElement-frameless.oo-ui-widget-disabled .oo-ui-buttonedElement-button > .oo-ui-labeledElement-label {
+  color: #ccc;
+}
+
+.oo-ui-buttonedElement-framed .oo-ui-buttonedElement-button {
+  text-shadow: 0 1px 1px rgba(255, 255, 255, 0.5);
+  background: #eeeeee;
+  background-image: -webkit-gradient(linear, right top, right bottom, color-stop(0%, #ffffff), color-stop(100%, #dddddd));
+  background-image: -webkit-linear-gradient(top, #ffffff 0%, #dddddd 100%);
+  background-image: -moz-linear-gradient(top, #ffffff 0%, #dddddd 100%);
+  background-image: -ms-linear-gradient(top, #ffffff 0%, #dddddd 100%);
+  background-image: -o-linear-gradient(top, #ffffff 0%, #dddddd 100%);
+  background-image: linear-gradient(top, #ffffff 0%, #dddddd 100%);
+  border: 1px #c9c9c9 solid;
+  border-radius: 0.3em;
+  filter: progid:DXImageTransform.Microsoft.gradient(GradientType=0, startColorstr='#ffffff', endColorstr='#dddddd');
+  -webkit-transition: border-color 100ms ease-in-out;
+     -moz-transition: border-color 100ms ease-in-out;
+      -ms-transition: border-color 100ms ease-in-out;
+       -o-transition: border-color 100ms ease-in-out;
+          transition: border-color 100ms ease-in-out;
+}
+
+.oo-ui-buttonedElement-framed .oo-ui-buttonedElement-button:hover,
+.oo-ui-buttonedElement-framed .oo-ui-buttonedElement-button:focus {
+  border-color: #aaa;
+}
+
+.oo-ui-buttonedElement-framed .oo-ui-buttonedElement-button.oo-ui-buttonedElement-active,
+.oo-ui-buttonedElement-framed .oo-ui-buttonedElement-button.oo-ui-buttonedElement-pressed {
+  color: black;
+  background: #eeeeee;
+  background-image: -webkit-gradient(linear, right top, right bottom, color-stop(0%, #dddddd), color-stop(100%, #ffffff));
+  background-image: -webkit-linear-gradient(top, #dddddd 0%, #ffffff 100%);
+  background-image: -moz-linear-gradient(top, #dddddd 0%, #ffffff 100%);
+  background-image: -ms-linear-gradient(top, #dddddd 0%, #ffffff 100%);
+  background-image: -o-linear-gradient(top, #dddddd 0%, #ffffff 100%);
+  background-image: linear-gradient(top, #dddddd 0%, #ffffff 100%);
+  border-color: #c9c9c9;
+  filter: progid:DXImageTransform.Microsoft.gradient(GradientType=0, startColorstr='#dddddd', endColorstr='#ffffff');
+  box-shadow: inset 0 1px 4px 0 rgba(0, 0, 0, 0.07);
+}
+
+.oo-ui-buttonedElement-framed.oo-ui-flaggableElement-primary .oo-ui-buttonedElement-button {
+  background: #cde7f4;
+  background-image: -webkit-gradient(linear, right top, right bottom, color-stop(0%, #eaf4fa), color-stop(100%, #b0d9ee));
+  background-image: -webkit-linear-gradient(top, #eaf4fa 0%, #b0d9ee 100%);
+  background-image: -moz-linear-gradient(top, #eaf4fa 0%, #b0d9ee 100%);
+  background-image: -ms-linear-gradient(top, #eaf4fa 0%, #b0d9ee 100%);
+  background-image: -o-linear-gradient(top, #eaf4fa 0%, #b0d9ee 100%);
+  background-image: linear-gradient(top, #eaf4fa 0%, #b0d9ee 100%);
+  border: solid 1px #a6cee1;
+  filter: progid:DXImageTransform.Microsoft.gradient(GradientType=0, startColorstr='#eaf4fa', endColorstr='#b0d9ee');
+}
+
+.oo-ui-buttonedElement-framed.oo-ui-flaggableElement-primary .oo-ui-buttonedElement-button:hover,
+.oo-ui-buttonedElement-framed.oo-ui-flaggableElement-primary .oo-ui-buttonedElement-button:focus {
+  border-color: #9dc2d4;
+}
+
+.oo-ui-buttonedElement-framed.oo-ui-flaggableElement-primary .oo-ui-buttonedElement-button.oo-ui-buttonedElement-active,
+.oo-ui-buttonedElement-framed.oo-ui-flaggableElement-primary .oo-ui-buttonedElement-button.oo-ui-buttonedElement-pressed {
+  background: #cde7f4;
+  background-image: -webkit-gradient(linear, right top, right bottom, color-stop(0%, #b0d9ee), color-stop(100%, #eaf4fa));
+  background-image: -webkit-linear-gradient(top, #b0d9ee 0%, #eaf4fa 100%);
+  background-image: -moz-linear-gradient(top, #b0d9ee 0%, #eaf4fa 100%);
+  background-image: -ms-linear-gradient(top, #b0d9ee 0%, #eaf4fa 100%);
+  background-image: -o-linear-gradient(top, #b0d9ee 0%, #eaf4fa 100%);
+  background-image: linear-gradient(top, #b0d9ee 0%, #eaf4fa 100%);
+  border: solid 1px #a6cee1;
+  filter: progid:DXImageTransform.Microsoft.gradient(GradientType=0, startColorstr='#b0d9ee', endColorstr='#eaf4fa');
+}
+
+.oo-ui-buttonedElement-framed.oo-ui-flaggableElement-constructive .oo-ui-buttonedElement-button {
+  background: #daf0be;
+  background-image: -webkit-gradient(linear, right top, right bottom, color-stop(0%, #f0fbe1), color-stop(100%, #c3e59a));
+  background-image: -webkit-linear-gradient(top, #f0fbe1 0%, #c3e59a 100%);
+  background-image: -moz-linear-gradient(top, #f0fbe1 0%, #c3e59a 100%);
+  background-image: -ms-linear-gradient(top, #f0fbe1 0%, #c3e59a 100%);
+  background-image: -o-linear-gradient(top, #f0fbe1 0%, #c3e59a 100%);
+  background-image: linear-gradient(top, #f0fbe1 0%, #c3e59a 100%);
+  border: solid 1px #b8d892;
+  filter: progid:DXImageTransform.Microsoft.gradient(GradientType=0, startColorstr='#f0fbe1', endColorstr='#c3e59a');
+}
+
+.oo-ui-buttonedElement-framed.oo-ui-flaggableElement-constructive .oo-ui-buttonedElement-button:hover,
+.oo-ui-buttonedElement-framed.oo-ui-flaggableElement-constructive .oo-ui-buttonedElement-button:focus {
+  border-color: #adcb89;
+}
+
+.oo-ui-buttonedElement-framed.oo-ui-flaggableElement-constructive .oo-ui-buttonedElement-button.oo-ui-buttonedElement-active,
+.oo-ui-buttonedElement-framed.oo-ui-flaggableElement-constructive .oo-ui-buttonedElement-button.oo-ui-buttonedElement-pressed {
+  background: #daf0be;
+  background-image: -webkit-gradient(linear, right top, right bottom, color-stop(0%, #c3e59a), color-stop(100%, #f0fbe1));
+  background-image: -webkit-linear-gradient(top, #c3e59a 0%, #f0fbe1 100%);
+  background-image: -moz-linear-gradient(top, #c3e59a 0%, #f0fbe1 100%);
+  background-image: -ms-linear-gradient(top, #c3e59a 0%, #f0fbe1 100%);
+  background-image: -o-linear-gradient(top, #c3e59a 0%, #f0fbe1 100%);
+  background-image: linear-gradient(top, #c3e59a 0%, #f0fbe1 100%);
+  border: solid 1px #b8d892;
+  filter: progid:DXImageTransform.Microsoft.gradient(GradientType=0, startColorstr='#c3e59a', endColorstr='#f0fbe1');
+}
+
+.oo-ui-buttonedElement-framed.oo-ui-flaggableElement-destructive .oo-ui-buttonedElement-button {
+  color: #d45353;
+}
+
+.oo-ui-buttonedElement-framed.oo-ui-widget-disabled .oo-ui-buttonedElement-button,
+.oo-ui-buttonedElement-framed.oo-ui-widget-disabled .oo-ui-buttonedElement-button.oo-ui-buttonedElement-active,
+.oo-ui-buttonedElement-framed.oo-ui-widget-disabled .oo-ui-buttonedElement-button.oo-ui-buttonedElement-pressed {
+  color: #333;
+  background: #eee;
+  opacity: 0.5;
+  box-shadow: none;
+}
+
+.oo-ui-buttonedElement-framed.oo-ui-widget-disabled .oo-ui-buttonedElement-button:hover,
+.oo-ui-buttonedElement-framed.oo-ui-widget-disabled .oo-ui-buttonedElement-button.oo-ui-buttonedElement-active:hover,
+.oo-ui-buttonedElement-framed.oo-ui-widget-disabled .oo-ui-buttonedElement-button.oo-ui-buttonedElement-pressed:hover,
+.oo-ui-buttonedElement-framed.oo-ui-widget-disabled .oo-ui-buttonedElement-button:focus,
+.oo-ui-buttonedElement-framed.oo-ui-widget-disabled .oo-ui-buttonedElement-button.oo-ui-buttonedElement-active:focus,
+.oo-ui-buttonedElement-framed.oo-ui-widget-disabled .oo-ui-buttonedElement-button.oo-ui-buttonedElement-pressed:focus {
+  border-color: #ccc;
+  box-shadow: none;
+}
+
+.oo-ui-bookletLayout > .oo-ui-gridLayout > .oo-ui-panelLayout {
+  -webkit-transition: width 250ms ease-in-out, height 250ms ease-in-out, top 250ms ease-in-out, left 250ms ease-in-out;
+     -moz-transition: width 250ms ease-in-out, height 250ms ease-in-out, top 250ms ease-in-out, left 250ms ease-in-out;
+      -ms-transition: width 250ms ease-in-out, height 250ms ease-in-out, top 250ms ease-in-out, left 250ms ease-in-out;
+       -o-transition: width 250ms ease-in-out, height 250ms ease-in-out, top 250ms ease-in-out, left 250ms ease-in-out;
+          transition: width 250ms ease-in-out, height 250ms ease-in-out, top 250ms ease-in-out, left 250ms ease-in-out;
+}
+
+.oo-ui-bookletLayout-outlinePanel {
+  border-right: solid 1px #ddd;
+}
+
+.oo-ui-bookletLayout-outlinePanel .oo-ui-outlineControlsWidget {
+  box-shadow: 0 0 0.25em rgba(0, 0, 0, 0.25);
+}
+
+.oo-ui-fieldsetLayout {
+  border: none;
+}
+
+.oo-ui-fieldsetLayout > legend.oo-ui-labeledElement-label {
+  font-size: 1.5em;
+}
+
+.oo-ui-barToolGroup .oo-ui-tool {
+  margin: -1px 0 -1px -1px;
+  border: solid 1px transparent;
+}
+
+.oo-ui-barToolGroup .oo-ui-tool:first-child {
+  border-bottom-left-radius: 0.25em;
+  border-top-left-radius: 0.25em;
+}
+
+.oo-ui-barToolGroup .oo-ui-tool:last-child {
+  margin-right: -1px;
+  border-top-right-radius: 0.25em;
+  border-bottom-right-radius: 0.25em;
+}
+
+.oo-ui-barToolGroup .oo-ui-tool.oo-ui-widget-enabled:hover {
+  border-color: rgba(0, 0, 0, 0.2);
+}
+
+.oo-ui-barToolGroup .oo-ui-tool-active.oo-ui-widget-enabled {
+  background: #f8fbfd;
+  background-image: -webkit-gradient(linear, right top, right bottom, color-stop(0%, #f1f7fb), color-stop(100%, #ffffff));
+  background-image: -webkit-linear-gradient(top, #f1f7fb 0%, #ffffff 100%);
+  background-image: -moz-linear-gradient(top, #f1f7fb 0%, #ffffff 100%);
+  background-image: -ms-linear-gradient(top, #f1f7fb 0%, #ffffff 100%);
+  background-image: -o-linear-gradient(top, #f1f7fb 0%, #ffffff 100%);
+  background-image: linear-gradient(top, #f1f7fb 0%, #ffffff 100%);
+  border-color: rgba(0, 0, 0, 0.2);
+  filter: progid:DXImageTransform.Microsoft.gradient(GradientType=0, startColorstr='#f1f7fb', endColorstr='#ffffff');
+  box-shadow: inset 0 0.07em 0.07em 0 rgba(0, 0, 0, 0.07);
+}
+
+.oo-ui-barToolGroup .oo-ui-tool-active.oo-ui-widget-enabled + .oo-ui-tool-active.oo-ui-widget-enabled {
+  border-left-color: rgba(0, 0, 0, 0.1);
+}
+
+.oo-ui-barToolGroup .oo-ui-tool-link .oo-ui-iconedElement-icon {
+  opacity: 0.8;
+}
+
+.oo-ui-barToolGroup .oo-ui-tool.oo-ui-widget-disabled .oo-ui-tool-link .oo-ui-iconedElement-icon {
+  opacity: 0.2;
+}
+
+.oo-ui-barToolGroup .oo-ui-tool.oo-ui-widget-enabled .oo-ui-tool-link .oo-ui-iconedElement-icon {
+  opacity: 0.8;
+}
+
+.oo-ui-barToolGroup .oo-ui-tool.oo-ui-widget-enabled:hover .oo-ui-tool-link .oo-ui-iconedElement-icon {
+  opacity: 1;
+}
+
+.oo-ui-listToolGroup.oo-ui-popupToolGroup-active {
+  border-color: rgba(0, 0, 0, 0.2);
+}
+
+.oo-ui-listToolGroup .oo-ui-tool {
+  margin: -1px 0;
+  border: solid 1px transparent;
+}
+
+.oo-ui-listToolGroup .oo-ui-tool-active.oo-ui-widget-enabled {
+  background: #f8fbfd;
+  background-image: -webkit-gradient(linear, right top, right bottom, color-stop(0%, #f1f7fb), color-stop(100%, #ffffff));
+  background-image: -webkit-linear-gradient(top, #f1f7fb 0%, #ffffff 100%);
+  background-image: -moz-linear-gradient(top, #f1f7fb 0%, #ffffff 100%);
+  background-image: -ms-linear-gradient(top, #f1f7fb 0%, #ffffff 100%);
+  background-image: -o-linear-gradient(top, #f1f7fb 0%, #ffffff 100%);
+  background-image: linear-gradient(top, #f1f7fb 0%, #ffffff 100%);
+  border-color: rgba(0, 0, 0, 0.1);
+  filter: progid:DXImageTransform.Microsoft.gradient(GradientType=0, startColorstr='#f1f7fb', endColorstr='#ffffff');
+  box-shadow: inset 0 0.07em 0.07em 0 rgba(0, 0, 0, 0.07);
+}
+
+.oo-ui-listToolGroup .oo-ui-tool-active.oo-ui-widget-enabled + .oo-ui-tool-active.oo-ui-widget-enabled {
+  border-top-color: rgba(0, 0, 0, 0.1);
+}
+
+.oo-ui-listToolGroup .oo-ui-tool-active.oo-ui-widget-enabled:hover {
+  border-color: rgba(0, 0, 0, 0.2);
+}
+
+.oo-ui-listToolGroup .oo-ui-tool.oo-ui-widget-enabled:hover {
+  border-color: rgba(0, 0, 0, 0.2);
+}
+
+.oo-ui-listToolGroup .oo-ui-tool.oo-ui-widget-enabled .oo-ui-tool-link .oo-ui-iconedElement-icon {
+  opacity: 0.8;
+}
+
+.oo-ui-listToolGroup .oo-ui-tool.oo-ui-widget-enabled:hover .oo-ui-tool-link .oo-ui-iconedElement-icon {
+  opacity: 1;
+}
+
+.oo-ui-listToolGroup .oo-ui-tool.oo-ui-widget-disabled .oo-ui-tool-link .oo-ui-tool-title {
+  color: #ccc;
+}
+
+.oo-ui-listToolGroup .oo-ui-tool.oo-ui-widget-disabled .oo-ui-tool-link .oo-ui-iconedElement-icon {
+  opacity: 0.2;
+}
+
+.oo-ui-menuToolGroup {
+  border-color: rgba(0, 0, 0, 0.1);
+}
+
+.oo-ui-menuToolGroup:hover {
+  border-color: rgba(0, 0, 0, 0.2);
+}
+
+.oo-ui-menuToolGroup.oo-ui-popupToolGroup-active {
+  border-color: rgba(0, 0, 0, 0.25);
+}
+
+.oo-ui-menuToolGroup .oo-ui-tool:hover {
+  background-color: #e1f3ff;
+}
+
+.oo-ui-popupToolGroup-handle .oo-ui-indicatedElement-indicator,
+.oo-ui-popupToolGroup-handle .oo-ui-iconedElement-icon {
+  opacity: 0.8;
+}
+
+.oo-ui-popupToolGroup .oo-ui-toolGroup-tools {
+  background-color: white;
+  border: solid 1px #ccc;
+  box-shadow: 0 0.25em 1em rgba(0, 0, 0, 0.25);
+}
+
+.oo-ui-popupToolGroup-active.oo-ui-widget-enabled {
+  background: #f8fbfd;
+  background-image: -webkit-gradient(linear, right top, right bottom, color-stop(0%, #f1f7fb), color-stop(100%, #ffffff));
+  background-image: -webkit-linear-gradient(top, #f1f7fb 0%, #ffffff 100%);
+  background-image: -moz-linear-gradient(top, #f1f7fb 0%, #ffffff 100%);
+  background-image: -ms-linear-gradient(top, #f1f7fb 0%, #ffffff 100%);
+  background-image: -o-linear-gradient(top, #f1f7fb 0%, #ffffff 100%);
+  background-image: linear-gradient(top, #f1f7fb 0%, #ffffff 100%);
+  border-bottom-right-radius: 0;
+  border-bottom-left-radius: 0;
+  filter: progid:DXImageTransform.Microsoft.gradient(GradientType=0, startColorstr='#f1f7fb', endColorstr='#ffffff');
+  box-shadow: inset 0 0.07em 0.07em 0 rgba(0, 0, 0, 0.07);
+}
+
+.oo-ui-optionWidget-highlighted {
+  background-color: #e1f3ff;
+}
+
+.oo-ui-optionWidget-selected {
+  background-color: #a7dcff;
+}
+
+.oo-ui-menuWidget {
+  margin-top: -1px;
+  background: #fff;
+  border: solid 1px #ccc;
+  border-radius: 0 0 0.25em 0.25em;
+  box-shadow: 0 0.15em 1em 0 rgba(0, 0, 0, 0.2);
+}
+
+.oo-ui-popupWidget-popup {
+  background-color: #fff;
+  border: solid 1px #ccc;
+  border-radius: 0.25em;
+  box-shadow: 0 0.15em 0.5em 0 rgba(0, 0, 0, 0.2);
+}
+
+.oo-ui-popupWidget-tailed .oo-ui-popupWidget-tail {
+  width: 15px;
+  height: 8px;
+  margin-left: -7px;
+  background-image: /* @embed */ url(images/tail.svg);
+}
+
+.oo-ui-popupWidget-transitioning .oo-ui-popupWidget-popup {
+  -webkit-transition: width 100ms ease-in-out, height 100ms ease-in-out, left 100ms ease-in-out;
+     -moz-transition: width 100ms ease-in-out, height 100ms ease-in-out, left 100ms ease-in-out;
+      -ms-transition: width 100ms ease-in-out, height 100ms ease-in-out, left 100ms ease-in-out;
+       -o-transition: width 100ms ease-in-out, height 100ms ease-in-out, left 100ms ease-in-out;
+          transition: width 100ms ease-in-out, height 100ms ease-in-out, left 100ms ease-in-out;
+}
+
+.oo-ui-popupWidget-body {
+  box-shadow: 0 0 0.66em rgba(0, 0, 0, 0.25);
+}
+
+.oo-ui-buttonGroupWidget {
+  display: inline-block;
+  white-space: nowrap;
+}
+
+.oo-ui-buttonOptionWidget.oo-ui-optionWidget-selected,
+.oo-ui-buttonOptionWidget.oo-ui-optionWidget-highlighted {
+  background-color: transparent;
+}
+
+.oo-ui-buttonSelectWidget {
+  border-radius: 0.3em;
+}
+
+.oo-ui-buttonSelectWidget .oo-ui-buttonOptionWidget .oo-ui-buttonedElement-button {
+  margin-left: -1px;
+  border-radius: 0;
+}
+
+.oo-ui-buttonSelectWidget .oo-ui-buttonOptionWidget:first-child .oo-ui-buttonedElement-button {
+  margin-left: 0;
+  border-bottom-left-radius: 0.3em;
+  border-top-left-radius: 0.3em;
+}
+
+.oo-ui-buttonSelectWidget .oo-ui-buttonOptionWidget:last-child .oo-ui-buttonedElement-button {
+  border-top-right-radius: 0.3em;
+  border-bottom-right-radius: 0.3em;
+}
+
+.oo-ui-inlineMenuWidget-handle {
+  border: solid 1px rgba(0, 0, 0, 0.1);
+  border-radius: 0.25em;
+}
+
+.oo-ui-inlineMenuWidget-handle:hover {
+  border-color: rgba(0, 0, 0, 0.2);
+}
+
+.oo-ui-inlineMenuWidget-handle .oo-ui-indicatedElement-indicator,
+.oo-ui-inlineMenuWidget-handle .oo-ui-iconedElement-icon {
+  opacity: 0.8;
+}
+
+.oo-ui-menuItemWidget.oo-ui-optionWidget-highlighted {
+  background-color: #e1f3ff;
+}
+
+.oo-ui-menuSectionItemWidget {
+  color: #888;
+}
+
+.oo-ui-outlineControlsWidget {
+  background-color: #fff;
+}
+
+.oo-ui-outlineControlsWidget > .oo-ui-iconedElement-icon {
+  opacity: 0.2;
+}
+
+.oo-ui-outlineItemWidget {
+  font-size: 1.1em;
+}
+
+.oo-ui-outlineItemWidget.oo-ui-optionWidget-selected {
+  text-shadow: 0 1px 1px rgba(255, 255, 255, 0.5);
+  background-color: #a7dcff;
+}
+
+.oo-ui-outlineItemWidget.oo-ui-flaggableElement-important {
+  font-weight: bold;
+}
+
+.oo-ui-outlineItemWidget.oo-ui-flaggableElement-placeholder {
+  font-style: italic;
+}
+
+.oo-ui-outlineItemWidget.oo-ui-flaggableElement-empty .oo-ui-iconedElement-icon,
+.oo-ui-outlineItemWidget.oo-ui-flaggableElement-empty .oo-ui-indicatedElement-indicator {
+  opacity: 0.5;
+}
+
+.oo-ui-outlineItemWidget.oo-ui-flaggableElement-empty .oo-ui-labeledElement-label {
+  color: #777;
+}
+
+.oo-ui-searchWidget-query {
+  box-shadow: 0 0 0.5em rgba(0, 0, 0, 0.2);
+}
+
+.oo-ui-textInputWidget input,
+.oo-ui-textInputWidget textarea {
+  font-family: sans-serif;
+  font-size: 1em;
+  background-color: #fff;
+  border: solid 1px #ccc;
+  border-radius: 0.25em;
+  box-shadow: 0 0 0 white, inset 0 0.1em 0.2em #ddd;
+  -webkit-transition: border-color 200ms, box-shadow 200ms;
+     -moz-transition: border-color 200ms, box-shadow 200ms;
+      -ms-transition: border-color 200ms, box-shadow 200ms;
+       -o-transition: border-color 200ms, box-shadow 200ms;
+          transition: border-color 200ms, box-shadow 200ms;
+}
+
+.oo-ui-textInputWidget.oo-ui-widget-enabled input:focus,
+.oo-ui-textInputWidget.oo-ui-widget-enabled textarea:focus {
+  border-color: #a7dcff;
+  outline: none;
+  box-shadow: 0 0 0.3em #a7dcff, 0 0 0 white;
+}
+
+.oo-ui-textInputWidget input[readonly],
+.oo-ui-textInputWidget textarea[readonly] {
+  color: #777;
+  text-shadow: 0 1px 1px #fff;
+}
+
+.oo-ui-textInputWidget-pending input,
+.oo-ui-textInputWidget-pending textarea {
+  background-color: transparent;
+}
+
+.oo-ui-textInputWidget.oo-ui-widget-disabled input,
+.oo-ui-textInputWidget.oo-ui-widget-disabled input:focus,
+.oo-ui-textInputWidget.oo-ui-widget-disabled textarea,
+.oo-ui-textInputWidget.oo-ui-widget-disabled textarea:focus {
+  color: #ccc;
+  text-shadow: 0 1px 1px #fff;
+  background-color: #f3f3f3;
+  border-color: #ddd;
+}
+
+.oo-ui-toggleSwitchWidget {
+  background: #eeeeee;
+  background-image: -webkit-gradient(linear, right top, right bottom, color-stop(0%, #dddddd), color-stop(100%, #ffffff));
+  background-image: -webkit-linear-gradient(top, #dddddd 0%, #ffffff 100%);
+  background-image: -moz-linear-gradient(top, #dddddd 0%, #ffffff 100%);
+  background-image: -ms-linear-gradient(top, #dddddd 0%, #ffffff 100%);
+  background-image: -o-linear-gradient(top, #dddddd 0%, #ffffff 100%);
+  background-image: linear-gradient(top, #dddddd 0%, #ffffff 100%);
+  border: solid 1px #ccc;
+  border-radius: 1em;
+  filter: progid:DXImageTransform.Microsoft.gradient(GradientType=0, startColorstr='#dddddd', endColorstr='#ffffff');
+  box-shadow: 0 0 0 white, inset 0 0.1em 0.2em #ddd;
+}
+
+.oo-ui-toggleSwitchWidget.oo-ui-widget-disabled {
+  opacity: 0.5;
+}
+
+.oo-ui-toggleSwitchWidget-grip {
+  background: #eeeeee;
+  background-image: -webkit-gradient(linear, right top, right bottom, color-stop(0%, #ffffff), color-stop(100%, #dddddd));
+  background-image: -webkit-linear-gradient(top, #ffffff 0%, #dddddd 100%);
+  background-image: -moz-linear-gradient(top, #ffffff 0%, #dddddd 100%);
+  background-image: -ms-linear-gradient(top, #ffffff 0%, #dddddd 100%);
+  background-image: -o-linear-gradient(top, #ffffff 0%, #dddddd 100%);
+  background-image: linear-gradient(top, #ffffff 0%, #dddddd 100%);
+  border: 1px #c9c9c9 solid;
+  border-radius: 1em;
+  filter: progid:DXImageTransform.Microsoft.gradient(GradientType=0, startColorstr='#ffffff', endColorstr='#dddddd');
+  box-shadow: 0 0.1em 0.25em rgba(0, 0, 0, 0.1);
+}
+
+.oo-ui-toggleSwitchWidget.oo-ui-widget-enabled:hover,
+.oo-ui-toggleSwitchWidget.oo-ui-widget-enabled:hover .oo-ui-toggleSwitchWidget-grip {
+  border-color: #aaa;
+}
+
+.oo-ui-toggleSwitchWidget .oo-ui-toggleSwitchWidget-glow {
+  background: #cde7f4;
+  background-image: -webkit-gradient(linear, right top, right bottom, color-stop(0%, #b0d9ee), color-stop(100%, #eaf4fa));
+  background-image: -webkit-linear-gradient(top, #b0d9ee 0%, #eaf4fa 100%);
+  background-image: -moz-linear-gradient(top, #b0d9ee 0%, #eaf4fa 100%);
+  background-image: -ms-linear-gradient(top, #b0d9ee 0%, #eaf4fa 100%);
+  background-image: -o-linear-gradient(top, #b0d9ee 0%, #eaf4fa 100%);
+  background-image: linear-gradient(top, #b0d9ee 0%, #eaf4fa 100%);
+  border-radius: 1em;
+  filter: progid:DXImageTransform.Microsoft.gradient(GradientType=0, startColorstr='#b0d9ee', endColorstr='#eaf4fa');
+  box-shadow: inset 0 1px 4px 0 rgba(0, 0, 0, 0.07);
+}
+
+.oo-ui-toggleWidget-on .oo-ui-toggleSwitchWidget-glow {
+  opacity: 1;
+}
+
+.oo-ui-toggleWidget-off .oo-ui-toggleSwitchWidget-glow {
+  display: block;
+  opacity: 0;
+}
\ No newline at end of file
index dcffbbd..c849f56 100644 (file)
@@ -1,12 +1,12 @@
 /*!
- * OOjs UI v0.1.0-pre (064484f9af)
+ * OOjs UI v0.1.0-pre (e1b23620c0)
  * https://www.mediawiki.org/wiki/OOjs_UI
  *
  * Copyright 2011–2014 OOjs Team and other contributors.
  * Released under the MIT license
  * http://oojs.mit-license.org
  *
- * Date: Wed Feb 26 2014 12:12:11 GMT-0800 (PST)
+ * Date: Wed Mar 05 2014 17:18:44 GMT-0800 (PST)
  */
 ( function () {
 
@@ -87,6 +87,8 @@ var messages = {
        'ooui-outline-control-move-down': 'Move item down',
        // Tool tip for a button that moves items in a list up one place
        'ooui-outline-control-move-up': 'Move item up',
+       // Tool tip for a button that removes items from a list
+       'ooui-outline-control-remove': 'Remove item',
        // Label for the toolbar group that contains a list of all other available tools
        'ooui-toolbar-more': 'More'
 };
@@ -1452,12 +1454,22 @@ OO.ui.WindowSet.prototype.getWindow = function ( name ) {
                throw new Error( 'Unknown window: ' + name );
        }
        if ( !( name in this.windows ) ) {
-               win = this.windows[name] = this.factory.create( name, this, { '$': this.$ } );
+               win = this.windows[name] = this.createWindow( name );
                this.addWindow( win );
        }
        return this.windows[name];
 };
 
+/**
+ * Create a window for use in this window set.
+ *
+ * @param {string} name Symbolic name of window
+ * @return {OO.ui.Window} Window with specified name
+ */
+OO.ui.WindowSet.prototype.createWindow = function ( name ) {
+       return this.factory.create( name, { '$': this.$ } );
+};
+
 /**
  * Add a given window to this window set.
  *
@@ -1491,11 +1503,11 @@ OO.ui.WindowSet.prototype.addWindow = function ( win ) {
  * @constructor
  * @param {Object} [config] Configuration options
  * @cfg {boolean} [footless] Hide foot
- * @cfg {boolean} [small] Make the dialog small
+ * @cfg {string} [size='large'] Symbolic name of dialog size, `small`, `medium` or `large`
  */
 OO.ui.Dialog = function OoUiDialog( config ) {
        // Configuration initialization
-       config = config || {};
+       config = $.extend( { 'size': 'large' }, config );
 
        // Parent constructor
        OO.ui.Window.call( this, config );
@@ -1503,7 +1515,7 @@ OO.ui.Dialog = function OoUiDialog( config ) {
        // Properties
        this.visible = false;
        this.footless = !!config.footless;
-       this.small = !!config.small;
+       this.size = null;
        this.onWindowMouseWheelHandler = OO.ui.bind( this.onWindowMouseWheel, this );
        this.onDocumentKeyDownHandler = OO.ui.bind( this.onDocumentKeyDown, this );
 
@@ -1513,6 +1525,7 @@ OO.ui.Dialog = function OoUiDialog( config ) {
 
        // Initialization
        this.$element.addClass( 'oo-ui-dialog' );
+       this.setSize( config.size );
 };
 
 /* Inheritance */
@@ -1531,6 +1544,18 @@ OO.inheritClass( OO.ui.Dialog, OO.ui.Window );
  */
 OO.ui.Dialog.static.name = '';
 
+/**
+ * Map of symbolic size names and CSS classes.
+ *
+ * @static
+ * @property {Object}
+ */
+OO.ui.Dialog.static.sizeCssClasses = {
+       'small': 'oo-ui-dialog-small',
+       'medium': 'oo-ui-dialog-medium',
+       'large': 'oo-ui-dialog-large'
+};
+
 /* Methods */
 
 /**
@@ -1591,6 +1616,29 @@ OO.ui.Dialog.prototype.onOpening = function () {
        this.$element.addClass( 'oo-ui-dialog-open' );
 };
 
+/**
+ * Set dialog size.
+ *
+ * @param {string} [size='large'] Symbolic name of dialog size, `small`, `medium` or `large`
+ */
+OO.ui.Dialog.prototype.setSize = function ( size ) {
+       var name, state, cssClass,
+               sizeCssClasses = OO.ui.Dialog.static.sizeCssClasses;
+
+       if ( !sizeCssClasses[size] ) {
+               size = 'large';
+       }
+       this.size = size;
+       for ( name in sizeCssClasses ) {
+               state = name === size;
+               cssClass = sizeCssClasses[name];
+               this.$element.toggleClass( cssClass, state );
+               if ( this.frame.$content ) {
+                       this.frame.$content.toggleClass( cssClass, state );
+               }
+       }
+};
+
 /**
  * @inheritdoc
  */
@@ -1615,9 +1663,6 @@ OO.ui.Dialog.prototype.initialize = function () {
        if ( this.footless ) {
                this.frame.$content.addClass( 'oo-ui-dialog-content-footless' );
        }
-       if ( this.small ) {
-               this.$frame.addClass( 'oo-ui-window-frame-small' );
-       }
        this.closeButton.$element.addClass( 'oo-ui-window-closeButton' );
        this.$head.append( this.closeButton.$element );
 };
@@ -1774,6 +1819,7 @@ OO.ui.Widget.prototype.setDisabled = function ( disabled ) {
        isDisabled = this.isDisabled();
        if ( isDisabled !== this.wasDisabled ) {
                this.$element.toggleClass( 'oo-ui-widget-disabled', isDisabled );
+               this.$element.toggleClass( 'oo-ui-widget-enabled', !isDisabled );
                this.emit( 'disable', isDisabled );
        }
        this.wasDisabled = isDisabled;
@@ -1789,7 +1835,7 @@ OO.ui.Widget.prototype.setDisabled = function ( disabled ) {
  * @param {jQuery} $button Button node, assigned to #$button
  * @param {Object} [config] Configuration options
  * @cfg {boolean} [frameless] Render button without a frame
- * @cfg {number} [tabIndex] Button's tab index
+ * @cfg {number} [tabIndex=0] Button's tab index, use -1 to prevent tab focusing
  */
 OO.ui.ButtonedElement = function OoUiButtonedElement( $button, config ) {
        // Configuration initialization
@@ -1828,7 +1874,9 @@ OO.ui.ButtonedElement = function OoUiButtonedElement( $button, config ) {
 OO.ui.ButtonedElement.prototype.onMouseDown = function () {
        this.tabIndex = this.$button.attr( 'tabIndex' );
        // Remove the tab-index while the button is down to prevent the button from stealing focus
-       this.$button.removeAttr( 'tabIndex' );
+       this.$button
+               .removeAttr( 'tabIndex' )
+               .addClass( 'oo-ui-buttonedElement-pressed' );
        this.getElementDocument().addEventListener( 'mouseup', this.onMouseUpHandler, true );
 };
 
@@ -1840,7 +1888,9 @@ OO.ui.ButtonedElement.prototype.onMouseDown = function () {
  */
 OO.ui.ButtonedElement.prototype.onMouseUp = function () {
        // Restore the tab-index after the button is up to restore the button's accesssibility
-       this.$button.attr( 'tabIndex', this.tabIndex );
+       this.$button
+               .attr( 'tabIndex', this.tabIndex )
+               .removeClass( 'oo-ui-buttonedElement-pressed' );
        this.getElementDocument().removeEventListener( 'mouseup', this.onMouseUpHandler, true );
 };
 
@@ -1852,7 +1902,7 @@ OO.ui.ButtonedElement.prototype.onMouseUp = function () {
  * @chainable
  */
 OO.ui.ButtonedElement.prototype.setActive = function ( value ) {
-       this.$element.toggleClass( 'oo-ui-buttonedElement-active', !!value );
+       this.$button.toggleClass( 'oo-ui-buttonedElement-active', !!value );
        return this;
 };
 /**
@@ -3835,6 +3885,7 @@ OO.ui.BookletLayout = function OoUiBookletLayout( config ) {
        this.ignoreFocus = false;
        this.stackLayout = new OO.ui.StackLayout( { '$': this.$, 'continuous': !!config.continuous } );
        this.autoFocus = !!config.autoFocus;
+       this.outlineVisible = false;
        this.outlined = !!config.outlined;
        if ( this.outlined ) {
                this.editable = !!config.editable;
@@ -3845,6 +3896,7 @@ OO.ui.BookletLayout = function OoUiBookletLayout( config ) {
                this.gridLayout = new OO.ui.GridLayout(
                        [this.outlinePanel, this.stackLayout], { '$': this.$, 'widths': [1, 2] }
                );
+               this.outlineVisible = true;
                if ( this.editable ) {
                        this.outlineControlsWidget = new OO.ui.OutlineControlsWidget(
                                this.outlineWidget,
@@ -3857,6 +3909,8 @@ OO.ui.BookletLayout = function OoUiBookletLayout( config ) {
        this.stackLayout.connect( this, { 'set': 'onStackLayoutSet' } );
        if ( this.outlined ) {
                this.outlineWidget.connect( this, { 'select': 'onOutlineWidgetSelect' } );
+       }
+       if ( this.autoFocus ) {
                // Event 'focus' does not bubble, but 'focusin' does
                this.stackLayout.onDOMEvent( 'focusin', OO.ui.bind( this.onStackLayoutFocus, this ) );
        }
@@ -3934,6 +3988,7 @@ OO.ui.BookletLayout.prototype.onStackLayoutFocus = function ( e ) {
  */
 OO.ui.BookletLayout.prototype.onStackLayoutSet = function ( page ) {
        if ( page ) {
+               this.stackLayout.$element.find( ':focus' ).blur();
                page.scrollElementIntoView( { 'complete': OO.ui.bind( function () {
                        this.ignoreFocus = true;
                        if ( this.autoFocus ) {
@@ -3976,6 +4031,67 @@ OO.ui.BookletLayout.prototype.isEditable = function () {
        return this.editable;
 };
 
+/**
+ * Check if booklet has editing controls.
+ *
+ * @method
+ * @returns {boolean} Booklet is outlined
+ */
+OO.ui.BookletLayout.prototype.isOutlineVisible = function () {
+       return this.outlined && this.outlineVisible;
+};
+
+/**
+ * Hide or show the outline.
+ *
+ * @param {boolean} [show] Show outline, omit to invert current state
+ * @chainable
+ */
+OO.ui.BookletLayout.prototype.toggleOutline = function ( show ) {
+       if ( this.outlined ) {
+               show = show === undefined ? !this.outlineVisible : !!show;
+               this.outlineVisible = show;
+               this.gridLayout.layout( show ? [ 1, 2 ] : [ 0, 1 ], [ 1 ] );
+       }
+
+       return this;
+};
+
+/**
+ * Get the outline widget.
+ *
+ * @method
+ * @param {OO.ui.PageLayout} page Page to be selected
+ * @returns {OO.ui.PageLayout|null} Closest page to another
+ */
+OO.ui.BookletLayout.prototype.getClosestPage = function ( page ) {
+       var next, prev, level,
+               pages = this.stackLayout.getItems(),
+               index = $.inArray( page, pages );
+
+       if ( index !== -1 ) {
+               next = pages[index + 1];
+               prev = pages[index - 1];
+               // Prefer adjacent pages at the same level
+               if ( this.outlined ) {
+                       level = this.outlineWidget.getItemFromData( page.getName() ).getLevel();
+                       if (
+                               prev &&
+                               level === this.outlineWidget.getItemFromData( prev.getName() ).getLevel()
+                       ) {
+                               return prev;
+                       }
+                       if (
+                               next &&
+                               level === this.outlineWidget.getItemFromData( next.getName() ).getLevel()
+                       ) {
+                               return next;
+                       }
+               }
+       }
+       return prev || next || null;
+};
+
 /**
  * Get the outline widget.
  *
@@ -4030,17 +4146,33 @@ OO.ui.BookletLayout.prototype.getPageName = function () {
  * @chainable
  */
 OO.ui.BookletLayout.prototype.addPages = function ( pages, index ) {
-       var i, len, name, page, item,
-               items = [],
-               remove = [];
+       var i, len, name, page, item, currentIndex,
+               stackLayoutPages = this.stackLayout.getItems(),
+               remove = [],
+               items = [];
 
+       // Remove pages with same names
        for ( i = 0, len = pages.length; i < len; i++ ) {
                page = pages[i];
                name = page.getName();
-               if ( name in this.pages ) {
-                       // Remove page with same name
+
+               if ( Object.prototype.hasOwnProperty.call( this.pages, name ) ) {
+                       // Correct the insertion index
+                       currentIndex = $.inArray( this.pages[name], stackLayoutPages );
+                       if ( currentIndex !== -1 && currentIndex + 1 < index ) {
+                               index--;
+                       }
                        remove.push( this.pages[name] );
                }
+       }
+       if ( remove.length ) {
+               this.removePages( remove );
+       }
+
+       // Add new pages
+       for ( i = 0, len = pages.length; i < len; i++ ) {
+               page = pages[i];
+               name = page.getName();
                this.pages[page.getName()] = page;
                if ( this.outlined ) {
                        item = new OO.ui.OutlineItemWidget( name, page, { '$': this.$ } );
@@ -4048,9 +4180,6 @@ OO.ui.BookletLayout.prototype.addPages = function ( pages, index ) {
                        items.push( item );
                }
        }
-       if ( remove.length ) {
-               this.removePages( remove );
-       }
 
        if ( this.outlined && items.length ) {
                this.outlineWidget.addItems( items, index );
@@ -4129,17 +4258,22 @@ OO.ui.BookletLayout.prototype.setPage = function ( name ) {
        var selectedItem,
                page = this.pages[name];
 
-       if ( this.outlined ) {
-               selectedItem = this.outlineWidget.getSelectedItem();
-               if ( selectedItem && selectedItem.getData() !== name ) {
-                       this.outlineWidget.selectItem( this.outlineWidget.getItemFromData( name ) );
+       if ( name !== this.currentPageName ) {
+               if ( this.outlined ) {
+                       selectedItem = this.outlineWidget.getSelectedItem();
+                       if ( selectedItem && selectedItem.getData() !== name ) {
+                               this.outlineWidget.selectItem( this.outlineWidget.getItemFromData( name ) );
+                       }
+               }
+               if ( page ) {
+                       if ( this.currentPageName && this.pages[this.currentPageName] ) {
+                               this.pages[this.currentPageName].setActive( false );
+                       }
+                       this.currentPageName = name;
+                       this.stackLayout.setItem( page );
+                       page.setActive( true );
+                       this.emit( 'set', page );
                }
-       }
-
-       if ( page ) {
-               this.currentPageName = name;
-               this.stackLayout.setItem( page );
-               this.emit( 'set', page );
        }
 };
 
@@ -4213,6 +4347,7 @@ OO.ui.PageLayout = function OoUiPageLayout( name, config ) {
        // Properties
        this.name = name;
        this.outlineItem = config.outlineItem || null;
+       this.active = false;
 
        // Initialization
        this.$element.addClass( 'oo-ui-pageLayout' );
@@ -4222,6 +4357,13 @@ OO.ui.PageLayout = function OoUiPageLayout( name, config ) {
 
 OO.inheritClass( OO.ui.PageLayout, OO.ui.PanelLayout );
 
+/* Events */
+
+/**
+ * @event active
+ * @param {boolean} active Page is active
+ */
+
 /* Methods */
 
 /**
@@ -4233,6 +4375,15 @@ OO.ui.PageLayout.prototype.getName = function () {
        return this.name;
 };
 
+/**
+ * Check if page is active.
+ *
+ * @returns {boolean} Page is active
+ */
+OO.ui.PageLayout.prototype.isActive = function () {
+       return this.active;
+};
+
 /**
  * Get outline item.
  *
@@ -4252,6 +4403,22 @@ OO.ui.PageLayout.prototype.setOutlineItem = function ( outlineItem ) {
        this.outlineItem = outlineItem;
        return this;
 };
+
+/**
+ * Set page active state.
+ *
+ * @param {boolean} Page is active
+ * @fires active
+ */
+OO.ui.PageLayout.prototype.setActive = function ( active ) {
+       active = !!active;
+
+       if ( active !== this.active ) {
+               this.active = active;
+               this.$element.toggleClass( 'oo-ui-pageLayout-active', active );
+               this.emit( 'active', this.active );
+       }
+};
 /**
  * Layout containing a series of mutually exclusive pages.
  *
@@ -4370,18 +4537,20 @@ OO.ui.StackLayout.prototype.clearItems = function () {
  * @chainable
  */
 OO.ui.StackLayout.prototype.setItem = function ( item ) {
-       if ( !this.continuous ) {
-               this.$items.css( 'display', '' );
-       }
-       if ( $.inArray( item, this.items ) !== -1 ) {
+       if ( item !== this.currentItem ) {
                if ( !this.continuous ) {
-                       item.$element.css( 'display', 'block' );
+                       this.$items.css( 'display', '' );
                }
-       } else {
-               item = null;
+               if ( $.inArray( item, this.items ) !== -1 ) {
+                       if ( !this.continuous ) {
+                               item.$element.css( 'display', 'block' );
+                       }
+               } else {
+                       item = null;
+               }
+               this.currentItem = item;
+               this.emit( 'set', item );
        }
-       this.currentItem = item;
-       this.emit( 'set', item );
 
        return this;
 };
@@ -5476,8 +5645,6 @@ OO.ui.LookupInputWidget.prototype.getLookupMenuItemsFromData = function () {
  * @constructor
  * @param {Mixed} data Option data
  * @param {Object} [config] Configuration options
- * @cfg {boolean} [selected=false] Select option
- * @cfg {boolean} [highlighted=false] Highlight option
  * @cfg {string} [rel] Value for `rel` attribute in DOM, allowing per-option styling
  */
 OO.ui.OptionWidget = function OoUiOptionWidget( data, config ) {
@@ -5505,10 +5672,6 @@ OO.ui.OptionWidget = function OoUiOptionWidget( data, config ) {
                .attr( 'rel', config.rel )
                .addClass( 'oo-ui-optionWidget' )
                .append( this.$label );
-       this.setSelected( config.selected );
-       this.setHighlighted( config.highlighted );
-
-       // Options
        this.$element
                .prepend( this.$icon )
                .append( this.$indicator );
@@ -6512,26 +6675,21 @@ OO.inheritClass( OO.ui.OutlineWidget, OO.ui.SelectWidget );
  * @constructor
  * @param {OO.ui.OutlineWidget} outline Outline to control
  * @param {Object} [config] Configuration options
- * @cfg {Object[]} [adders] List of icons to show as addable item types, each an object with
- *  name, title and icon properties
  */
 OO.ui.OutlineControlsWidget = function OoUiOutlineControlsWidget( outline, config ) {
        // Configuration initialization
-       config = config || {};
+       config = $.extend( { 'icon': 'add-item' }, config );
 
        // Parent constructor
        OO.ui.Widget.call( this, config );
 
+       // Mixin constructors
+       OO.ui.GroupElement.call( this, this.$( '<div>' ), config );
+       OO.ui.IconedElement.call( this, this.$( '<div>' ), config );
+
        // Properties
        this.outline = outline;
-       this.adders = {};
-       this.$adders = this.$( '<div>' );
        this.$movers = this.$( '<div>' );
-       this.addButton = new OO.ui.ButtonWidget( {
-               '$': this.$,
-               'frameless': true,
-               'icon': 'add-item'
-       } );
        this.upButton = new OO.ui.ButtonWidget( {
                '$': this.$,
                'frameless': true,
@@ -6544,6 +6702,12 @@ OO.ui.OutlineControlsWidget = function OoUiOutlineControlsWidget( outline, confi
                'icon': 'expand',
                'title': OO.ui.msg( 'ooui-outline-control-move-down' )
        } );
+       this.removeButton = new OO.ui.ButtonWidget( {
+               '$': this.$,
+               'frameless': true,
+               'icon': 'remove',
+               'title': OO.ui.msg( 'ooui-outline-control-remove' )
+       } );
 
        // Events
        outline.connect( this, {
@@ -6553,23 +6717,24 @@ OO.ui.OutlineControlsWidget = function OoUiOutlineControlsWidget( outline, confi
        } );
        this.upButton.connect( this, { 'click': ['emit', 'move', -1] } );
        this.downButton.connect( this, { 'click': ['emit', 'move', 1] } );
+       this.removeButton.connect( this, { 'click': ['emit', 'remove'] } );
 
        // Initialization
        this.$element.addClass( 'oo-ui-outlineControlsWidget' );
-       this.$adders.addClass( 'oo-ui-outlineControlsWidget-adders' );
+       this.$group.addClass( 'oo-ui-outlineControlsWidget-adders' );
        this.$movers
                .addClass( 'oo-ui-outlineControlsWidget-movers' )
-               .append( this.upButton.$element, this.downButton.$element );
-       this.$element.append( this.$adders, this.$movers );
-       if ( config.adders && config.adders.length ) {
-               this.setupAdders( config.adders );
-       }
+               .append( this.removeButton.$element, this.upButton.$element, this.downButton.$element );
+       this.$element.append( this.$icon, this.$group, this.$movers );
 };
 
 /* Inheritance */
 
 OO.inheritClass( OO.ui.OutlineControlsWidget, OO.ui.Widget );
 
+OO.mixinClass( OO.ui.OutlineControlsWidget, OO.ui.GroupElement );
+OO.mixinClass( OO.ui.OutlineControlsWidget, OO.ui.IconedElement );
+
 /* Events */
 
 /**
@@ -6577,6 +6742,10 @@ OO.inheritClass( OO.ui.OutlineControlsWidget, OO.ui.Widget );
  * @param {number} places Number of places to move
  */
 
+/**
+ * @event remove
+ */
+
 /* Methods */
 
 /**
@@ -6586,12 +6755,12 @@ OO.inheritClass( OO.ui.OutlineControlsWidget, OO.ui.Widget );
  */
 OO.ui.OutlineControlsWidget.prototype.onOutlineChange = function () {
        var i, len, firstMovable, lastMovable,
-               movable = false,
                items = this.outline.getItems(),
-               selectedItem = this.outline.getSelectedItem();
+               selectedItem = this.outline.getSelectedItem(),
+               movable = selectedItem && selectedItem.isMovable(),
+               removable = selectedItem && selectedItem.isRemovable();
 
-       if ( selectedItem && selectedItem.isMovable() ) {
-               movable = true;
+       if ( movable ) {
                i = -1;
                len = items.length;
                while ( ++i < len ) {
@@ -6610,30 +6779,7 @@ OO.ui.OutlineControlsWidget.prototype.onOutlineChange = function () {
        }
        this.upButton.setDisabled( !movable || selectedItem === firstMovable );
        this.downButton.setDisabled( !movable || selectedItem === lastMovable );
-};
-
-/**
- * Setup adders icons.
- *
- * @method
- * @param {Object[]} adders List of configuations for adder buttons, each containing a name, title
- *  and icon property
- */
-OO.ui.OutlineControlsWidget.prototype.setupAdders = function ( adders ) {
-       var i, len, addition, button,
-               $buttons = this.$( [] );
-
-       this.$adders.append( this.addButton.$element );
-       for ( i = 0, len = adders.length; i < len; i++ ) {
-               addition = adders[i];
-               button = new OO.ui.ButtonWidget( {
-                       '$': this.$, 'frameless': true, 'icon': addition.icon, 'title': addition.title
-               } );
-               button.connect( this, { 'click': ['emit', 'add', addition.name] } );
-               this.adders[addition.name] = button;
-               this.$adders.append( button.$element );
-               $buttons = $buttons.add( button.$element );
-       }
+       this.removeButton.setDisabled( !removable );
 };
 /**
  * Creates an OO.ui.OutlineItemWidget object.
@@ -6657,6 +6803,7 @@ OO.ui.OutlineItemWidget = function OoUiOutlineItemWidget( data, config ) {
        // Properties
        this.level = 0;
        this.movable = !!config.movable;
+       this.removable = !!config.removable;
 
        // Initialization
        this.$element.addClass( 'oo-ui-outlineItemWidget' );
@@ -6690,6 +6837,17 @@ OO.ui.OutlineItemWidget.prototype.isMovable = function () {
        return this.movable;
 };
 
+/**
+ * Check if item is removable.
+ *
+ * Removablilty is used by outline controls.
+ *
+ * @returns {boolean} Item is removable
+ */
+OO.ui.OutlineItemWidget.prototype.isRemovable = function () {
+       return this.removable;
+};
+
 /**
  * Get indentation level.
  *
@@ -6712,6 +6870,19 @@ OO.ui.OutlineItemWidget.prototype.setMovable = function ( movable ) {
        return this;
 };
 
+/**
+ * Set removability.
+ *
+ * Removablilty is used by outline controls.
+ *
+ * @param {boolean} movable Item is removable
+ * @chainable
+ */
+OO.ui.OutlineItemWidget.prototype.setRemovable = function ( removable ) {
+       this.removable = !!removable;
+       return this;
+};
+
 /**
  * Set indentation level.
  *
@@ -7278,9 +7449,10 @@ OO.ui.SearchWidget.prototype.getResults = function () {
  * @cfg {string} [icon] Symbolic name of icon
  * @cfg {boolean} [multiline=false] Allow multiple lines of text
  * @cfg {boolean} [autosize=false] Automatically resize to fit content
+ * @cfg {boolean} [maxRows=10] Maximum number of rows to make visible when autosizing
  */
 OO.ui.TextInputWidget = function OoUiTextInputWidget( config ) {
-       config = config || {};
+       config = $.extend( { 'maxRows': 10 }, config );
 
        // Parent constructor
        OO.ui.InputWidget.call( this, config );
@@ -7289,9 +7461,11 @@ OO.ui.TextInputWidget = function OoUiTextInputWidget( config ) {
        this.pending = 0;
        this.multiline = !!config.multiline;
        this.autosize = !!config.autosize;
+       this.maxRows = config.maxRows;
 
        // Events
        this.$input.on( 'keypress', OO.ui.bind( this.onKeyPress, this ) );
+       this.$element.on( 'DOMNodeInsertedIntoDocument', OO.ui.bind( this.onElementAttach, this ) );
 
        // Initialization
        this.$element.addClass( 'oo-ui-textInputWidget' );
@@ -7339,13 +7513,35 @@ OO.ui.TextInputWidget.prototype.onKeyPress = function ( e ) {
        }
 };
 
+/**
+ * Handles element attach events.
+ *
+ * @param {jQuery.Event} e Element attach event
+ */
+OO.ui.TextInputWidget.prototype.onElementAttach = function () {
+       this.adjustSize();
+};
+
 /**
  * @inheritdoc
  */
 OO.ui.TextInputWidget.prototype.onEdit = function () {
-       var $clone, scrollHeight, innerHeight, outerHeight;
+       this.adjustSize();
+
+       // Parent method
+       return OO.ui.InputWidget.prototype.onEdit.call( this );
+};
+
+/**
+ * Automatically adjust the size of the text input.
+ *
+ * This only affects multi-line inputs that are auto-sized.
+ *
+ * @chainable
+ */
+OO.ui.TextInputWidget.prototype.adjustSize = function() {
+       var $clone, scrollHeight, innerHeight, outerHeight, maxInnerHeight, idealHeight;
 
-       // Automatic size adjustment
        if ( this.multiline && this.autosize ) {
                $clone = this.$input.clone()
                        .val( this.$input.val() )
@@ -7357,17 +7553,20 @@ OO.ui.TextInputWidget.prototype.onEdit = function () {
                $clone.css( 'height', '' );
                innerHeight = $clone.innerHeight();
                outerHeight = $clone.outerHeight();
+               // Measure max rows height
+               $clone.attr( 'rows', this.maxRows ).css( 'height', 'auto' );
+               maxInnerHeight = $clone.innerHeight();
+               $clone.removeAttr( 'rows' ).css( 'height', '' );
                $clone.remove();
+               idealHeight = Math.min( maxInnerHeight, scrollHeight );
                // Only apply inline height when expansion beyond natural height is needed
                this.$input.css(
                        'height',
                        // Use the difference between the inner and outer height as a buffer
-                       scrollHeight > outerHeight ? scrollHeight + ( outerHeight - innerHeight ) : ''
+                       idealHeight > outerHeight ? idealHeight + ( outerHeight - innerHeight ) : ''
                );
        }
-
-       // Parent method
-       return OO.ui.InputWidget.prototype.onEdit.call( this );
+       return this;
 };
 
 /**
@@ -7683,18 +7882,18 @@ OO.ui.ToggleSwitchWidget = function OoUiToggleSwitchWidget( config ) {
        this.dragging = false;
        this.dragStart = null;
        this.sliding = false;
-       this.$on = this.$( '<span>' );
+       this.$glow = this.$( '<span>' );
        this.$grip = this.$( '<span>' );
 
        // Events
        this.$element.on( 'click', OO.ui.bind( this.onClick, this ) );
 
        // Initialization
-       this.$on.addClass( 'oo-ui-toggleSwitchWidget-on' );
+       this.$glow.addClass( 'oo-ui-toggleSwitchWidget-glow' );
        this.$grip.addClass( 'oo-ui-toggleSwitchWidget-grip' );
        this.$element
                .addClass( 'oo-ui-toggleSwitchWidget' )
-               .append( this.$on, this.$grip );
+               .append( this.$glow, this.$grip );
 };
 
 /* Inheritance */
index ad435b3..826574e 100644 (file)
 /*!
- * OOjs UI v0.1.0-pre-svg (064484f9af)
+ * OOjs UI v0.1.0-pre (e1b23620c0)
  * https://www.mediawiki.org/wiki/OOjs_UI
  *
  * Copyright 2011–2014 OOjs Team and other contributors.
  * Released under the MIT license
  * http://oojs.mit-license.org
  *
- * Date: Wed Feb 26 2014 12:12:11 GMT-0800 (PST)
+ * Date: Wed Mar 05 2014 17:18:44 GMT-0800 (PST)
  */
-/*csslint vendor-prefix:false */
 
 /* Textures */
 
 .oo-ui-texture-pending {
-       /* @embed */
-       background-image: url(images/textures/pending.gif);
+  background-image: /* @embed */ url(images/textures/pending.gif);
 }
 
 .oo-ui-texture-transparency {
-       /* @embed */
-       background-image: url(images/textures/transparency.png);
+  background-image: /* @embed */ url(images/textures/transparency.png);
 }
 
 /* RTL Definitions */
 
 /* @noflip */
+
 .oo-ui-rtl {
-       direction: rtl;
+  direction: rtl;
 }
+
 /* @noflip */
+
 .oo-ui-ltr {
-       direction: ltr;
+  direction: ltr;
 }
+
 .oo-ui-dialog {
-       position: fixed;
-       top: 0;
-       right: 0;
-       bottom: 0;
-       left: 0;
-       padding: 1em;
-       line-height: 1em;
-       background-color: #fff;
-       background-color: rgba(255,255,255,0.5);
+  position: fixed;
+  top: 0;
+  right: 0;
+  bottom: 0;
+  left: 0;
+  padding: 1em;
+  line-height: 1em;
+  /* Fix for strange opacity-related rendering issues.
+          CAUTION: -webkit-backface-visibility: hidden; is EXTREMELY DANGEROUS.
+          If applied to a VE surface directly, it will break selection of
+          FocusableNodes, and in the past it's caused transparent PNGs to
+          render as opaque black images. For some reason applying it to the dialog
+          wrapper in the main document fixes opacity-related behavior in the iframe
+          document, but doesn't break the surface inside the iframe. */
+
+  -webkit-backface-visibility: hidden;
+          backface-visibility: hidden;
+}
 
-       opacity: 0;
+.oo-ui-dialog .oo-ui-window-frame {
+  position: fixed;
+  top: 1em;
+  right: 0;
+  bottom: 1em;
+  left: 0;
+  min-height: 12em;
+  margin: auto;
+  overflow: hidden;
+}
 
-       -webkit-transition: all 250ms ease-in-out;
-       -moz-transition: all 250ms ease-in-out;
-       -o-transition: all 250ms ease-in-out;
-       transition: all 250ms ease-in-out;
+.oo-ui-dialog-small .oo-ui-window-frame {
+  width: 400px;
+  max-height: 200px;
 }
 
-.oo-ui-dialog .oo-ui-window-frame {
-       position: fixed;
-       top: 1em;
-       right: 0;
-       bottom: 1em;
-       left: 0;
-       margin: auto;
-       width: 800px;
-       min-height: 12em;
-       max-height: 600px;
-       background-color: #fff;
-       border: solid 1px #ccc;
-       border-radius: 0.5em;
-       box-shadow: 0 0.2em 1em rgba(0, 0, 0, 0.3);
-       overflow: hidden;
-
-       -webkit-transform: scale(0.5);
-       -moz-transform: scale(0.5);
-       -ms-transform: scale(0.5);
-       -o-transform: scale(0.5);
-       transform: scale(0.5);
-
-       -webkit-transition: all 250ms ease-in-out;
-       -moz-transition: all 250ms ease-in-out;
-       -o-transition: all 250ms ease-in-out;
-       transition: all 250ms ease-in-out;
-}
-
-.oo-ui-dialog-open {
-       opacity: 1;
-}
-
-.oo-ui-dialog-open .oo-ui-window-frame  {
-       -webkit-transform: scale(1);
-       -moz-transform: scale(1);
-       -ms-transform: scale(1);
-       -o-transform: scale(1);
-       transform: scale(1);
-}
-
-.oo-ui-dialog .oo-ui-window-frame.oo-ui-window-frame-small {
-       max-width: 600px;
-       max-height: 400px;
+.oo-ui-dialog-medium .oo-ui-window-frame {
+  width: 600px;
+  max-height: 400px;
+}
+
+.oo-ui-dialog-large .oo-ui-window-frame {
+  width: 800px;
+  max-height: 600px;
 }
 
 .oo-ui-dialog .oo-ui-frame {
-       width: 100%;
-       height: 100%;
+  width: 100%;
+  height: 100%;
 }
 
 .oo-ui-dialog-content .oo-ui-window-head,
 .oo-ui-dialog-content .oo-ui-window-body,
 .oo-ui-dialog-content .oo-ui-window-foot {
-       position: absolute;
-       left: 0;
-       right: 0;
-       -webkit-box-sizing: border-box;
-       -moz-box-sizing: border-box;
-       box-sizing: border-box;
-       overflow: hidden;
+  position: absolute;
+  right: 0;
+  left: 0;
+  overflow: hidden;
+  -webkit-box-sizing: border-box;
+     -moz-box-sizing: border-box;
+          box-sizing: border-box;
 }
 
 .oo-ui-dialog-content .oo-ui-window-head {
-       top: 0;
-       height: 3.8em;
-       padding: 0.5em;
+  top: 0;
+  height: 3.8em;
+  padding: 0.5em;
 }
 
-.oo-ui-dialog-content .oo-ui-window-foot {
-       bottom: 0;
-       height: 4.8em;
-       padding: 1em;
+.oo-ui-dialog-content .oo-ui-window-title {
+  line-height: 2.8em;
 }
 
-.oo-ui-dialog-content .oo-ui-window-body {
-       box-shadow: 0 0 0.66em rgba(0,0,0,0.25);
-       top: 3.8em;
-       bottom: 4.8em;
+.oo-ui-dialog-content .oo-ui-window-icon {
+  width: 2.4em;
+  height: 2.8em;
+  line-height: 2.8em;
 }
 
-.oo-ui-dialog-content-footless .oo-ui-window-body {
-       bottom: 0;
+.oo-ui-dialog-content .oo-ui-window-closeButton {
+  float: right;
+  margin: 0.25em 0.25em;
 }
 
-.oo-ui-dialog-content-footless .oo-ui-window-foot {
-       display: none;
+.oo-ui-dialog-content .oo-ui-window-body {
+  top: 3.8em;
+  bottom: 4.8em;
 }
 
-.oo-ui-dialog-content .oo-ui-window-icon {
-       width: 2.4em;
-       height: 2.8em;
-       line-height: 2.8em;
+.oo-ui-dialog-content .oo-ui-window-foot {
+  bottom: 0;
+  height: 4.8em;
+  padding: 1em;
 }
 
-.oo-ui-dialog-content .oo-ui-window-title {
-       line-height: 2.8em;
+.oo-ui-dialog-content .oo-ui-window-foot .oo-ui-buttonedElement-framed {
+  float: left;
+  margin: 0.125em 0.25em;
 }
 
-.oo-ui-dialog-content .oo-ui-window-foot .oo-ui-buttonedElement-framed {
-       float: left;
-       margin: 0.125em 0.25em;
+.oo-ui-dialog-content .oo-ui-window-foot .oo-ui-flaggableElement-primary,
+.oo-ui-dialog-content .oo-ui-window-foot .oo-ui-flaggableElement-constructive,
+.oo-ui-dialog-content .oo-ui-window-foot .oo-ui-flaggableElement-destructive {
+  float: right;
 }
 
-.oo-ui-dialog-content .oo-ui-window-foot .oo-ui-buttonedElement-framed.oo-ui-flaggableElement-primary,
-.oo-ui-dialog-content .oo-ui-window-foot .oo-ui-buttonedElement-framed.oo-ui-flaggableElement-constructive,
-.oo-ui-dialog-content .oo-ui-window-foot .oo-ui-buttonedElement-framed.oo-ui-flaggableElement-destructive {
-       float: right;
+.oo-ui-dialog-content-footless .oo-ui-window-body {
+  bottom: 0;
 }
 
-.oo-ui-dialog-content .oo-ui-window-closeButton {
-       float: right;
-       margin: 0.25em 0.25em;
+.oo-ui-dialog-content-footless .oo-ui-window-foot {
+  display: none;
 }
 
-/* OO.ui.ButtonedElement */
+.oo-ui-frame {
+  padding: 0;
+  margin: 0;
+}
 
-a.oo-ui-buttonedElement-button {
-       color: #333;
-       cursor: pointer;
-       display: inline-block;
-       vertical-align: middle;
-       -webkit-touch-callout: none;
-       -webkit-user-select: none;
-       -moz-user-select: none;
-       -ms-user-select: none;
-       user-select: none;
+.oo-ui-frame-body {
+  padding: 0;
+  margin: 0;
+  background: none;
 }
 
-.oo-ui-buttonedElement .oo-ui-buttonedElement-button > .oo-ui-indicatedElement-indicator,
-.oo-ui-buttonedElement .oo-ui-buttonedElement-button > .oo-ui-iconedElement-icon {
-       display: none;
+.oo-ui-frame-content {
+  font-family: sans-serif;
+  font-size: 0.8em;
 }
 
-.oo-ui-buttonedElement.oo-ui-indicatedElement .oo-ui-buttonedElement-button > .oo-ui-indicatedElement-indicator,
-.oo-ui-buttonedElement.oo-ui-iconedElement .oo-ui-buttonedElement-button > .oo-ui-iconedElement-icon {
-       opacity: 0.8;
-       display: inline-block;
-       vertical-align: middle;
-       background-position: center center;
-       background-repeat: no-repeat;
-       width: 1.9em;
-       height: 1.9em;
+.oo-ui-toolbar {
+  clear: both;
 }
 
-.oo-ui-buttonedElement .oo-ui-buttonedElement-button > .oo-ui-iconedElement-icon {
-       margin-left: 0;
+.oo-ui-toolbar-bar {
+  line-height: 1em;
 }
 
-.oo-ui-buttonedElement .oo-ui-buttonedElement-button > .oo-ui-indicatedElement-indicator {
-       margin-right: -0.75em;
+.oo-ui-toolbar-bottom .oo-ui-toolbar-bar {
+  position: absolute;
 }
-.oo-ui-buttonedElement.oo-ui-widget-disabled .oo-ui-buttonedElement-button {
-       cursor: default;
+
+.oo-ui-toolbar-actions {
+  float: right;
 }
 
-.oo-ui-buttonedElement-frameless {
-       display: inline-block;
-       position: relative;
-       -webkit-transition: opacity 200ms;
-       -moz-transition: opacity 200ms;
-       -o-transition: opacity 200ms;
-       transition: opacity 200ms;
+.oo-ui-toolbar-tools {
+  float: left;
 }
 
-.oo-ui-buttonedElement-frameless .oo-ui-buttonedElement-button:hover > .oo-ui-iconedElement-icon,
-.oo-ui-buttonedElement-frameless .oo-ui-buttonedElement-button:focus > .oo-ui-iconedElement-icon {
-       opacity: 1;
+.oo-ui-toolbar-tools,
+.oo-ui-toolbar-actions,
+.oo-ui-toolbar-shadow {
+  -webkit-user-select: none;
+     -moz-user-select: none;
+      -ms-user-select: none;
+          user-select: none;
+  -webkit-touch-callout: none;
 }
 
-.oo-ui-buttonedElement-frameless.oo-ui-widget-disabled .oo-ui-buttonedElement-button > .oo-ui-iconedElement-icon {
-       opacity: 0.2;
+.oo-ui-toolbar-actions .oo-ui-popupWidget {
+  -webkit-user-select: all;
+     -moz-user-select: all;
+      -ms-user-select: all;
+          user-select: all;
+  -webkit-touch-callout: default;
 }
 
-.oo-ui-buttonedElement-frameless .oo-ui-buttonedElement-button > .oo-ui-labeledElement-label {
-       display: inline-block;
-       vertical-align: middle;
-       margin-left: 0.25em;
-       color: #333;
+.oo-ui-toolbar-shadow {
+  position: absolute;
+  width: 100%;
+  pointer-events: none;
+  background-position: left top;
+  background-repeat: repeat-x;
 }
 
-.oo-ui-buttonedElement-frameless .oo-ui-buttonedElement-button:hover > .oo-ui-labeledElement-label,
-.oo-ui-buttonedElement-frameless .oo-ui-buttonedElement-button:focus > .oo-ui-labeledElement-label {
-       color: #000;
+.oo-ui-toolGroup {
+  display: inline-block;
+  margin: 0.3em;
+  vertical-align: middle;
 }
 
-.oo-ui-buttonedElement-frameless.oo-ui-widget-disabled .oo-ui-buttonedElement-button > .oo-ui-labeledElement-label {
-       color: #ccc;
+.oo-ui-toolGroup-empty {
+  display: none;
 }
 
-/* OO.ui.ButtonWidget */
+.oo-ui-toolGroup .oo-ui-tool-link .oo-ui-iconedElement-icon {
+  background-position: center center;
+  background-repeat: no-repeat;
+}
 
-.oo-ui-buttonedElement-framed .oo-ui-buttonedElement-button {
-       display: inline-block;
-       font-size: 1em;
-       margin: 0.1em 0;
-       padding: 0.2em 0.8em;
-       border-radius: 0.3em;
-       vertical-align: top;
-       text-shadow: 0 1px 1px rgba(255, 255, 255, 0.5);
-       text-align: center;
-
-       /* Animation */
-       -webkit-transition: border-color 100ms;
-       -moz-transition: border-color 100ms;
-       -o-transition: border-color 100ms;
-       transition: border-color 100ms;
-
-       /* Gray */
-       border: 1px #c9c9c9 solid;
-       background-color: #dddddd;
-       filter: progid:DXImageTransform.Microsoft.gradient(
-               GradientType=0,startColorstr=#ffffff, endColorstr=#dddddd
-       );
-       background-image: -webkit-gradient(
-               linear, right top, right bottom, color-stop(0%,#ffffff), color-stop(100%,#dddddd)
-       );
-       background-image: -webkit-linear-gradient(top, #ffffff 0%, #dddddd 100%);
-       background-image: -moz-linear-gradient(top, #ffffff 0%, #dddddd 100%);
-       background-image: -ms-linear-gradient(top, #ffffff 0%, #dddddd 100%);
-       background-image: -o-linear-gradient(top, #ffffff 0%, #dddddd 100%);
-       background-image: linear-gradient(top, #ffffff 0%, #dddddd 100%);
-}
-
-.oo-ui-buttonedElement-framed .oo-ui-buttonedElement-button:hover,
-.oo-ui-buttonedElement-framed .oo-ui-buttonedElement-button:focus {
-       border-color: #aaa;
-}
-
-.oo-ui-buttonedElement-framed .oo-ui-buttonedElement-button:active,
-.oo-ui-buttonedElement-framed.oo-ui-buttonedElement-active .oo-ui-buttonedElement-button {
-       box-shadow: inset 0 1px 4px 0 rgba(0, 0, 0, 0.07);
-       color: black;
-
-       /* Gray */
-       border-color: #c9c9c9;
-       background-color: #dddddd;
-       filter: progid:DXImageTransform.Microsoft.gradient(
-               GradientType=0,startColorstr=#dddddd, endColorstr=#ffffff
-       );
-       background-image: -webkit-gradient(
-               linear, right top, right bottom, color-stop(0%,#dddddd), color-stop(100%,#ffffff)
-       );
-       background-image: -webkit-linear-gradient(top, #dddddd 0%, #ffffff 100%);
-       background-image: -moz-linear-gradient(top, #dddddd 0%, #ffffff 100%);
-       background-image: -ms-linear-gradient(top, #dddddd 0%, #ffffff 100%);
-       background-image: -o-linear-gradient(top, #dddddd 0%, #ffffff 100%);
-       background-image: linear-gradient(top, #dddddd 0%, #ffffff 100%);
+.oo-ui-window-head {
+  -webkit-user-select: none;
+     -moz-user-select: none;
+      -ms-user-select: none;
+          user-select: none;
+  -webkit-touch-callout: none;
 }
 
-.oo-ui-buttonedElement-framed.oo-ui-iconedElement .oo-ui-buttonedElement-button > .oo-ui-iconedElement-icon {
-       margin-left: -0.5em;
-       margin-right: -0.5em;
+.oo-ui-window-body {
+  padding: 0 0.75em;
 }
 
-.oo-ui-buttonedElement-framed.oo-ui-iconedElement.oo-ui-labeledElement .oo-ui-buttonedElement-button > .oo-ui-iconedElement-icon {
-       margin-left: -0.5em;
-       margin-right: 0;
+.oo-ui-window-icon {
+  float: left;
+  width: 2em;
+  height: 2em;
+  margin-right: 0.5em;
+  line-height: 2em;
+  background-position: right center;
+  background-repeat: no-repeat;
 }
 
-.oo-ui-buttonedElement-framed .oo-ui-buttonedElement-button > .oo-ui-labeledElement-label {
-       display: inline-block;
-       vertical-align: middle;
-       line-height: 1.9em;
-}
-
-.oo-ui-buttonedElement-framed.oo-ui-flaggableElement-destructive .oo-ui-buttonedElement-button {
-       /* Red text */
-       color: #d45353;
-}
-
-.oo-ui-buttonedElement-framed.oo-ui-flaggableElement-constructive .oo-ui-buttonedElement-button {
-       /* Green */
-       border: solid 1px #b8d892;
-       background-color: #f0fbe1;
-       filter: progid:DXImageTransform.Microsoft.gradient(
-               GradientType=0,startColorstr=#f0fbe1, endColorstr=#c3e59a
-       );
-       background-image: -webkit-gradient(
-               linear, right top, right bottom, color-stop(0%,#f0fbe1), color-stop(100%,#c3e59a)
-       );
-       background-image: -webkit-linear-gradient(top, #f0fbe1 0%, #c3e59a 100%);
-       background-image: -moz-linear-gradient(top, #f0fbe1 0%, #c3e59a 100%);
-       background-image: -ms-linear-gradient(top, #f0fbe1 0%, #c3e59a 100%);
-       background-image: -o-linear-gradient(top, #f0fbe1 0%, #c3e59a 100%);
-       background-image: linear-gradient(top, #f0fbe1 0%, #c3e59a 100%);
-}
-
-.oo-ui-buttonedElement-framed.oo-ui-flaggableElement-constructive .oo-ui-buttonedElement-button:hover,
-.oo-ui-buttonedElement-framed.oo-ui-flaggableElement-constructive .oo-ui-buttonedElement-button:focus {
-       border-color: #adcb89;
-}
-
-.oo-ui-buttonedElement-framed.oo-ui-flaggableElement-constructive .oo-ui-buttonedElement-button:active,
-.oo-ui-buttonedElement-framed.oo-ui-buttonedElement-active.oo-ui-flaggableElement-constructive .oo-ui-buttonedElement-button {
-       /* Green */
-       border: solid 1px #b8d892;
-       background-color: #c3e59a;
-       filter: progid:DXImageTransform.Microsoft.gradient(
-               GradientType=0,startColorstr=#c3e59a, endColorstr=#f0fbe1
-       );
-       background-image: -webkit-gradient(
-               linear, right top, right bottom, color-stop(0%,#c3e59a), color-stop(100%,#f0fbe1)
-       );
-       background-image: -webkit-linear-gradient(top, #c3e59a 0%, #f0fbe1 100%);
-       background-image: -moz-linear-gradient(top, #c3e59a 0%, #f0fbe1 100%);
-       background-image: -ms-linear-gradient(top, #c3e59a 0%, #f0fbe1 100%);
-       background-image: -o-linear-gradient(top, #c3e59a 0%, #f0fbe1 100%);
-       background-image: linear-gradient(top, #c3e59a 0%, #f0fbe1 100%);
-}
-
-.oo-ui-buttonedElement-framed.oo-ui-flaggableElement-primary .oo-ui-buttonedElement-button {
-       /* Blue */
-       border: solid 1px #a6cee1;
-       background-color: #eaf4fa;
-       filter: progid:DXImageTransform.Microsoft.gradient(
-               GradientType=0,startColorstr=#eaf4fa, endColorstr=#b0d9ee
-       );
-       background-image: -webkit-gradient(
-               linear, right top, right bottom, color-stop(0%,#eaf4fa), color-stop(100%,#b0d9ee)
-       );
-       background-image: -webkit-linear-gradient(top, #eaf4fa 0%, #b0d9ee 100%);
-       background-image: -moz-linear-gradient(top, #eaf4fa 0%, #b0d9ee 100%);
-       background-image: -ms-linear-gradient(top, #eaf4fa 0%, #b0d9ee 100%);
-       background-image: -o-linear-gradient(top, #eaf4fa 0%, #b0d9ee 100%);
-       background-image: linear-gradient(top, #eaf4fa 0%, #b0d9ee 100%);
-}
-
-.oo-ui-buttonedElement-framed.oo-ui-flaggableElement-primary .oo-ui-buttonedElement-button:hover,
-.oo-ui-buttonedElement-framed.oo-ui-flaggableElement-primary .oo-ui-buttonedElement-button:focus {
-       border-color: #9dc2d4;
-}
-
-.oo-ui-buttonedElement-framed.oo-ui-flaggableElement-primary .oo-ui-buttonedElement-button:active,
-.oo-ui-buttonedElement-framed.oo-ui-buttonedElement-active.oo-ui-flaggableElement-primary .oo-ui-buttonedElement-button {
-       /* Blue */
-       border: solid 1px #a6cee1;
-       background-color: #b0d9ee;
-       filter: progid:DXImageTransform.Microsoft.gradient(
-               GradientType=0,startColorstr=#b0d9ee, endColorstr=#eaf4fa
-       );
-       background-image: -webkit-gradient(
-               linear, right top, right bottom, color-stop(0%,#b0d9ee), color-stop(100%,#eaf4fa)
-       );
-       background-image: -webkit-linear-gradient(top, #b0d9ee 0%, #eaf4fa 100%);
-       background-image: -moz-linear-gradient(top, #b0d9ee 0%, #eaf4fa 100%);
-       background-image: -ms-linear-gradient(top, #b0d9ee 0%, #eaf4fa 100%);
-       background-image: -o-linear-gradient(top, #b0d9ee 0%, #eaf4fa 100%);
-       background-image: linear-gradient(top, #b0d9ee 0%, #eaf4fa 100%);
+.oo-ui-window-title {
+  float: left;
+  line-height: 2em;
+  white-space: nowrap;
+  cursor: default;
 }
 
-.oo-ui-buttonedElement-framed.oo-ui-widget-disabled .oo-ui-buttonedElement-button,
-.oo-ui-buttonedElement-framed.oo-ui-widget-disabled .oo-ui-buttonedElement-button:active,
-.oo-ui-buttonedElement-framed.oo-ui-buttonedElement-active.oo-ui-widget-disabled .oo-ui-buttonedElement-button:active {
-       opacity: 0.5;
-       cursor: default;
-       box-shadow: none;
-       color: #333;
-       background: #eee;
+.oo-ui-window-overlay {
+  position: absolute;
+  top: 0;
+  left: 0;
 }
 
-.oo-ui-buttonedElement-framed.oo-ui-widget-disabled .oo-ui-buttonedElement-button:hover,
-.oo-ui-buttonedElement-framed.oo-ui-widget-disabled .oo-ui-buttonedElement-button:focus {
-       border-color: #ccc;
-       box-shadow: none;
+.oo-ui-buttonedElement .oo-ui-buttonedElement-button {
+  display: inline-block;
+  vertical-align: middle;
+  cursor: pointer;
+  -webkit-user-select: none;
+     -moz-user-select: none;
+      -ms-user-select: none;
+          user-select: none;
+  -webkit-touch-callout: none;
 }
 
-/* OO.ui.LabeledElement */
+.oo-ui-buttonedElement .oo-ui-buttonedElement-button > .oo-ui-iconedElement-icon {
+  display: none;
+  margin-left: 0;
+}
 
-.oo-ui-labeledElement-label {
-       display: block;
+.oo-ui-buttonedElement .oo-ui-buttonedElement-button > .oo-ui-indicatedElement-indicator {
+  display: none;
+  margin-right: -0.75em;
 }
 
-.oo-ui-clippableElement-clippable {
-       -webkit-box-sizing: border-box;
-       -moz-box-sizing: border-box;
-       box-sizing: border-box;
+.oo-ui-buttonedElement.oo-ui-widget-disabled .oo-ui-buttonedElement-button {
+  cursor: default;
 }
-.oo-ui-frame {
-       margin: 0;
-       padding: 0;
+
+.oo-ui-buttonedElement.oo-ui-indicatedElement .oo-ui-buttonedElement-button > .oo-ui-indicatedElement-indicator,
+.oo-ui-buttonedElement.oo-ui-iconedElement .oo-ui-buttonedElement-button > .oo-ui-iconedElement-icon {
+  display: inline-block;
+  width: 1.9em;
+  height: 1.9em;
+  vertical-align: middle;
+  background-position: center center;
+  background-repeat: no-repeat;
 }
 
-.oo-ui-frame-body {
-       margin: 0;
-       padding: 0;
-       background: none;
+.oo-ui-buttonedElement-frameless {
+  position: relative;
+  display: inline-block;
 }
 
-.oo-ui-frame-content {
-       font-family: sans-serif;
-       font-size: 0.8em;
+.oo-ui-buttonedElement-frameless .oo-ui-buttonedElement-button > .oo-ui-labeledElement-label {
+  display: inline-block;
+  margin-left: 0.25em;
+  vertical-align: middle;
 }
-/* OO.ui.GridLayout */
-/* OO.ui.PanelLayout */
 
-.oo-ui-gridLayout,
-.oo-ui-panelLayout {
-       position: absolute;
-       top: 0;
-       left: 0;
-       right: 0;
-       bottom: 0;
+.oo-ui-buttonedElement-framed .oo-ui-buttonedElement-button {
+  display: inline-block;
+  padding: 0.2em 0.8em;
+  margin: 0.1em 0;
+  text-align: center;
+  vertical-align: top;
 }
 
-.oo-ui-panelLayout-scrollable {
-       overflow-y: auto;
+.oo-ui-buttonedElement-framed .oo-ui-buttonedElement-button > .oo-ui-labeledElement-label {
+  display: inline-block;
+  line-height: 1.9em;
+  vertical-align: middle;
 }
 
-.oo-ui-panelLayout-padded {
-       padding: 2em;
+.oo-ui-buttonedElement-framed.oo-ui-iconedElement .oo-ui-buttonedElement-button > .oo-ui-iconedElement-icon {
+  margin-right: -0.5em;
+  margin-left: -0.5em;
 }
 
-/* OO.ui.FieldsetLayout */
+.oo-ui-buttonedElement-framed.oo-ui-iconedElement.oo-ui-labeledElement .oo-ui-buttonedElement-button > .oo-ui-iconedElement-icon {
+  margin-right: 0;
+  margin-left: -0.5em;
+}
 
-.oo-ui-fieldsetLayout {
-       position: relative;
-       border: none;
-       margin: 0;
-       padding: 0;
+.oo-ui-buttonedElement-framed.oo-ui-widget-disabled .oo-ui-buttonedElement-button,
+.oo-ui-buttonedElement-framed.oo-ui-widget-disabled .oo-ui-buttonedElement-button.oo-ui-buttonedElement-active,
+.oo-ui-buttonedElement-framed.oo-ui-widget-disabled .oo-ui-buttonedElement-button.oo-ui-buttonedElement-pressed {
+  cursor: default;
 }
 
-.oo-ui-fieldsetLayout + .oo-ui-fieldsetLayout {
-       margin-top: 2em;
+.oo-ui-clippableElement-clippable {
+  -webkit-box-sizing: border-box;
+     -moz-box-sizing: border-box;
+          box-sizing: border-box;
 }
 
-.oo-ui-fieldsetLayout-labeled {
-       margin-top: -0.75em;
+.oo-ui-bookletLayout-stackLayout.oo-ui-stackLayout-continuous .oo-ui-panelLayout-scrollable {
+  overflow-y: hidden;
 }
 
-.oo-ui-fieldsetLayout > legend.oo-ui-labeledElement-label {
-       font-size: 1.5em;
-       margin-bottom: 0.5em;
-       padding-left: 0;
+.oo-ui-bookletLayout-stackLayout .oo-ui-panelLayout {
+  width: 100%;
+  padding: 1.5em;
+  -webkit-box-sizing: border-box;
+     -moz-box-sizing: border-box;
+          box-sizing: border-box;
 }
 
-.oo-ui-fieldsetLayout.oo-ui-iconedElement > legend.oo-ui-labeledElement-label {
-       padding-left: 1.75em;
+.oo-ui-bookletLayout-stackLayout .oo-ui-panelLayout-scrollable {
+  overflow-y: auto;
 }
 
-.oo-ui-fieldsetLayout.oo-ui-iconedElement > .oo-ui-iconedElement-icon {
-       display: block;
-       position: absolute;
-       left: 0;
-       top: 0.5em;
-       width: 2em;
-       height: 2em;
-       background-position: center center;
-       background-repeat: no-repeat;
+.oo-ui-bookletLayout-stackLayout .oo-ui-panelLayout-padded {
+  padding: 2em;
 }
 
-/* OO.ui.FieldLayout */
+.oo-ui-bookletLayout-outlinePanel-editable .oo-ui-outlineWidget {
+  position: absolute;
+  top: 0;
+  right: 0;
+  bottom: 3em;
+  left: 0;
+  overflow-y: auto;
+}
+
+.oo-ui-bookletLayout-outlinePanel .oo-ui-outlineControlsWidget {
+  position: absolute;
+  right: 0;
+  bottom: 0;
+  left: 0;
+}
 
 .oo-ui-fieldLayout {
-       margin-bottom: 1em;
+  margin-bottom: 1em;
 }
 
 .oo-ui-fieldLayout:last-child {
-       margin-bottom: 0;
+  margin-bottom: 0;
 }
 
 .oo-ui-fieldLayout:before,
 .oo-ui-fieldLayout:after {
-    content: " ";
-    display: table;
+  display: table;
+  content: " ";
 }
 
 .oo-ui-fieldLayout:after {
-    clear: both;
+  clear: both;
 }
 
 .oo-ui-fieldLayout.oo-ui-fieldLayout-align-left > .oo-ui-labeledElement-label,
 .oo-ui-fieldLayout.oo-ui-fieldLayout-align-right > .oo-ui-labeledElement-label {
-       display: block;
-       float: left;
-       width: 35%;
-       padding-top: 0.5em;
-       margin-right: 5%;
+  display: block;
+  float: left;
+  width: 35%;
+  padding-top: 0.5em;
+  margin-right: 5%;
 }
 
 .oo-ui-fieldLayout.oo-ui-fieldLayout-align-left > .oo-ui-fieldLayout-field,
 .oo-ui-fieldLayout.oo-ui-fieldLayout-align-right > .oo-ui-fieldLayout-field {
-       display: block;
-       float: left;
-       width: 60%;
+  display: block;
+  float: left;
+  width: 60%;
 }
 
 .oo-ui-fieldLayout.oo-ui-fieldLayout-align-right > .oo-ui-labeledElement-label {
-       text-align: right;
+  text-align: right;
 }
 
 .oo-ui-fieldLayout.oo-ui-fieldLayout-align-inline > .oo-ui-labeledElement-label {
-       display: inline-block;
-       vertical-align: middle;
-       padding: 0.75em 0.5em 0.5em 0.5em;
+  display: inline-block;
+  padding: 0.75em 0.5em 0.5em 0.5em;
+  vertical-align: middle;
 }
 
 .oo-ui-fieldLayout.oo-ui-fieldLayout-align-inline > .oo-ui-fieldLayout-field {
-       display: inline-block;
-       vertical-align: middle;
-       padding: 0.5em 0;
+  display: inline-block;
+  padding: 0.5em 0;
+  vertical-align: middle;
 }
 
 .oo-ui-fieldLayout.oo-ui-fieldLayout-align-top > .oo-ui-labeledElement-label {
-       padding: 0.5em 0;
-}
-
-/* OO.ui.BookletLayout */
-
-.oo-ui-bookletLayout-stackLayout .oo-ui-panelLayout {
-       padding: 1.5em;
-       width: 100%;
-       -webkit-box-sizing: border-box;
-       -moz-box-sizing: border-box;
-       box-sizing: border-box;
-}
-
-.oo-ui-bookletLayout-stackLayout .oo-ui-panelLayout-scrollable {
-       overflow-y: auto;
-}
-
-.oo-ui-bookletLayout-stackLayout .oo-ui-panelLayout-padded {
-       padding: 2em;
-}
-
-.oo-ui-bookletLayout-outlinePanel {
-       border-right: solid 1px #ddd;
-}
-
-.oo-ui-bookletLayout-outlinePanel-editable .oo-ui-outlineWidget {
-       position: absolute;
-       top: 0;
-       left: 0;
-       right: 0;
-       bottom: 3em;
-       overflow-y: auto;
-}
-
-.oo-ui-bookletLayout-outlinePanel .oo-ui-outlineControlsWidget {
-       position: absolute;
-       bottom: 0;
-       left: 0;
-       right: 0;
-       box-shadow: 0 0 0.25em rgba(0,0,0,0.25);
-}
-
-.oo-ui-stackLayout > .oo-ui-panelLayout {
-       display: none;
+  padding: 0.5em 0;
 }
 
-.oo-ui-stackLayout-continuous > .oo-ui-panelLayout {
-       display: block;
-       position: relative;
-       margin-bottom: 1em;
-       box-shadow: 0 0 0.5em rgba(0,0,0,0.25);
-}
-
-.oo-ui-stackLayout-continuous > .oo-ui-panelLayout:last-child {
-       margin-bottom: 0;
-}
-/* OO.ui.PopupTool */
-
-.oo-ui-popupTool .oo-ui-popupWidget {
-       margin-left: 1.25em;
-       font-size: 0.8em;
-}
-
-.oo-ui-popupTool .oo-ui-popupWidget-popup,
-.oo-ui-popupTool .oo-ui-popupWidget-tail {
-       z-index: 4;
-}
-.oo-ui-toolbar {
-       clear: both;
+.oo-ui-fieldsetLayout {
+  position: relative;
+  padding: 0;
+  margin: 0;
 }
 
-.oo-ui-toolbar-bar {
-       border-bottom: solid 1px #ccc;
-       background-color: white;
-       /* @embed */
-       background-image: url(images/fade-up.png);
-       background-position: left bottom;
-       background-repeat: repeat-x;
-       padding-bottom: 1px;
-       line-height: 1em;
+.oo-ui-fieldsetLayout + .oo-ui-fieldsetLayout {
+  margin-top: 2em;
 }
 
-.oo-ui-toolbar-bar .oo-ui-toolbar-bar {
-       border: none;
-       background: none;
+.oo-ui-fieldsetLayout-labeled {
+  margin-top: -0.75em;
 }
 
-.oo-ui-toolbar-bottom .oo-ui-toolbar-bar {
-       position: absolute;
+.oo-ui-fieldsetLayout > legend.oo-ui-labeledElement-label {
+  padding: 0.25em 0;
+  margin-bottom: 0.5em;
 }
 
-.oo-ui-toolbar-actions {
-       float: right;
+.oo-ui-fieldsetLayout.oo-ui-iconedElement > legend.oo-ui-labeledElement-label {
+  padding-left: 1.75em;
 }
 
-.oo-ui-toolbar-tools {
-       float: left;
+.oo-ui-fieldsetLayout.oo-ui-iconedElement > .oo-ui-iconedElement-icon {
+  position: absolute;
+  top: 0;
+  left: 0;
+  display: block;
+  width: 2em;
+  height: 2em;
+  background-position: center center;
+  background-repeat: no-repeat;
 }
 
-.oo-ui-toolbar-tools,
-.oo-ui-toolbar-actions,
-.oo-ui-toolbar-shadow {
-       -webkit-user-select: none;
-       -moz-user-select: none;
-       -ms-user-select: none;
-       -o-user-select: none;
-       user-select: none;
+.oo-ui-gridLayout {
+  position: absolute;
+  top: 0;
+  right: 0;
+  bottom: 0;
+  left: 0;
 }
 
-.oo-ui-toolbar-actions .oo-ui-popupWidget {
-       -webkit-touch-callout: default;
-       -webkit-user-select: all;
-       -moz-user-select: all;
-       -ms-user-select: all;
-       user-select: all;
+.oo-ui-labelWidget {
+  padding: 0.5em 0;
 }
 
-.oo-ui-toolbar-shadow {
-       /* @embed */
-       background-image: url(images/toolbar-shadow.png);
-       background-position: left top;
-       background-repeat: repeat-x;
-       position: absolute;
-       bottom: -9px;
-       height: 9px;
-       width: 100%;
-       pointer-events: none;
-       -webkit-transition: opacity 500ms ease-in-out;
-       -moz-transition: opacity 500ms ease-in-out;
-       -o-transition: opacity 500ms ease-in-out;
-       transition: opacity 500ms ease-in-out;
-       opacity: 0.125;
-}
-/* OO.ui.ToolGroup */
-
-.oo-ui-toolGroup {
-       display: inline-block;
-       margin: 0.3em;
-       vertical-align: middle;
-       border-radius: 0.25em;
-       border: solid 1px transparent;
-       -webkit-transition: border-color 300ms;
-       -moz-transition: border-color 300ms;
-       -o-transition: border-color 300ms;
-       transition: border-color 300ms;
+.oo-ui-panelLayout {
+  position: absolute;
+  top: 0;
+  right: 0;
+  bottom: 0;
+  left: 0;
 }
 
-.oo-ui-toolGroup:hover {
-       border-color: rgba(0,0,0,0.1);
+.oo-ui-panelLayout-scrollable {
+  overflow-y: auto;
 }
 
-.oo-ui-toolGroup-empty {
-       display: none;
+.oo-ui-panelLayout-padded {
+  padding: 2em;
 }
 
-.oo-ui-toolGroup .oo-ui-tool-link .oo-ui-tool-title {
-       color: #000;
+.oo-ui-stackLayout > .oo-ui-panelLayout {
+  display: none;
 }
 
-.oo-ui-toolGroup .oo-ui-tool-link .oo-ui-iconedElement-icon {
-       background-position: center center;
-       background-repeat: no-repeat;
+.oo-ui-stackLayout-continuous > .oo-ui-panelLayout {
+  position: relative;
+  display: block;
 }
 
-/* OO.ui.BarToolGroup */
-
 .oo-ui-barToolGroup > .oo-ui-iconedElement-icon,
-.oo-ui-barToolGroup > .oo-ui-iconedElement-label {
-       display: none;
+.oo-ui-barToolGroup > .oo-ui-labeledElement-label {
+  display: none;
 }
 
 .oo-ui-barToolGroup .oo-ui-tool {
-       display: inline-block;
-       position: relative;
-       vertical-align: top;
-       margin: -1px 0 -1px -1px;
-       border: solid 1px transparent;
+  position: relative;
+  display: inline-block;
+  vertical-align: top;
 }
 
 .oo-ui-barToolGroup .oo-ui-tool-link {
-       display: block;
-       height: 1.5em;
-       padding: 0.25em;
-       cursor: pointer;
+  display: block;
+  height: 1.5em;
+  padding: 0.25em;
+  cursor: pointer;
 }
 
-.oo-ui-barToolGroup
-       .oo-ui-tool-active:not(.oo-ui-widget-disabled) +
-       .oo-ui-tool-active:not(.oo-ui-widget-disabled)
-{
-       border-left-color: rgba(0,0,0,0.1);
+.oo-ui-barToolGroup .oo-ui-tool-link .oo-ui-iconedElement-icon {
+  display: block;
+  width: 1.5em;
+  height: 1.5em;
 }
 
-.oo-ui-barToolGroup .oo-ui-tool:first-child {
-       border-top-left-radius: 0.25em;
-       border-bottom-left-radius: 0.25em;
+.oo-ui-barToolGroup .oo-ui-tool-link .oo-ui-tool-title {
+  display: none;
 }
 
-.oo-ui-barToolGroup .oo-ui-tool:last-child {
-       margin-right: -1px;
-       border-top-right-radius: 0.25em;
-       border-bottom-right-radius: 0.25em;
+.oo-ui-barToolGroup .oo-ui-tool.oo-ui-widget-disabled .oo-ui-tool-link {
+  cursor: default;
 }
 
-.oo-ui-barToolGroup .oo-ui-tool:hover:not(.oo-ui-widget-disabled) {
-       border-color: rgba(0,0,0,0.2);
+.oo-ui-barToolGroup .oo-ui-tool-title,
+.oo-ui-barToolGroup .oo-ui-tool-accel {
+  display: none;
 }
 
-.oo-ui-barToolGroup .oo-ui-tool-active:not(.oo-ui-widget-disabled) {
-       border-color: rgba(0,0,0,0.2);
+.oo-ui-listToolGroup .oo-ui-toolGroup-tools {
+  padding: 0.25em;
 }
 
-.oo-ui-barToolGroup .oo-ui-tool-link .oo-ui-iconedElement-icon {
-       display: block;
-       height: 1.5em;
-       width: 1.5em;
-       opacity: 0.8;
+.oo-ui-listToolGroup .oo-ui-tool {
+  display: inline-block;
+  width: 100%;
+  -webkit-box-sizing: border-box;
+     -moz-box-sizing: border-box;
+          box-sizing: border-box;
 }
 
-.oo-ui-barToolGroup .oo-ui-tool-link .oo-ui-tool-title {
-       display: none;
+.oo-ui-listToolGroup .oo-ui-tool-link {
+  display: block;
+  padding-right: 0.5em;
+  white-space: nowrap;
+  cursor: pointer;
 }
 
-.oo-ui-barToolGroup .oo-ui-tool.oo-ui-widget-disabled .oo-ui-tool-link {
-       cursor: default;
+.oo-ui-listToolGroup .oo-ui-tool.oo-ui-widget-disabled .oo-ui-tool-link {
+  cursor: default;
 }
 
-.oo-ui-barToolGroup .oo-ui-tool.oo-ui-widget-disabled .oo-ui-tool-link .oo-ui-iconedElement-icon {
-       opacity: 0.2;
+.oo-ui-menuToolGroup .oo-ui-popupToolGroup-handle {
+  min-width: 8em;
 }
 
-.oo-ui-barToolGroup .oo-ui-tool:not(.oo-ui-widget-disabled) .oo-ui-tool-link .oo-ui-iconedElement-icon {
-       opacity: 0.8;
+.oo-ui-menuToolGroup .oo-ui-tool {
+  display: block;
 }
 
-.oo-ui-barToolGroup .oo-ui-tool:hover:not(.oo-ui-widget-disabled) .oo-ui-tool-link .oo-ui-iconedElement-icon {
-       opacity: 1;
+.oo-ui-menuToolGroup .oo-ui-tool-link {
+  display: block;
+  padding: 0.25em 1em 0.25em 0.25em;
+  white-space: nowrap;
+  cursor: pointer;
 }
 
-.oo-ui-barToolGroup .oo-ui-tool-title {
-       display: none;
+.oo-ui-menuToolGroup .oo-ui-tool-link .oo-ui-iconedElement-icon {
+  background-image: none;
 }
 
-/* OO.ui.PopupToolGroup */
+.oo-ui-menuToolGroup .oo-ui-tool-active .oo-ui-tool-link .oo-ui-iconedElement-icon {
+  background-image: /* @embed */ url(images/icons/check.png);
+}
 
 .oo-ui-popupToolGroup {
-       position: relative;
-       height: 2em;
-       min-width: 2.5em;
+  position: relative;
+  height: 2em;
+  min-width: 2.5em;
 }
 
 .oo-ui-popupToolGroup.oo-ui-indicatedElement.oo-ui-iconedElement {
-       min-width: 3.5em;
+  min-width: 3.5em;
 }
 
 .oo-ui-popupToolGroup-handle {
-       display: block;
-       cursor: pointer;
+  display: block;
+  cursor: pointer;
 }
 
 .oo-ui-popupToolGroup-handle .oo-ui-indicatedElement-indicator,
 .oo-ui-popupToolGroup-handle .oo-ui-iconedElement-icon {
-       position: absolute;
-       top: 0;
-       width: 2em;
-       height: 2em;
-       background-position: center center;
-       background-repeat: no-repeat;
-       opacity: 0.8;
+  position: absolute;
+  top: 0;
+  width: 2em;
+  height: 2em;
+  background-position: center center;
+  background-repeat: no-repeat;
 }
 
 .oo-ui-popupToolGroup-handle .oo-ui-indicatedElement-indicator {
-       right: 0;
+  right: 0;
 }
 
 .oo-ui-popupToolGroup-handle .oo-ui-iconedElement-icon {
-       left: 0.25em;
+  left: 0.25em;
 }
 
 .oo-ui-popupToolGroup-handle .oo-ui-labeledElement-label {
-       line-height: 2.6em;
-       font-size: 0.8em;
-       margin: 0 1em;
+  margin: 0 1em;
+  font-size: 0.8em;
+  line-height: 2.6em;
 }
 
 .oo-ui-popupToolGroup.oo-ui-iconedElement .oo-ui-popupToolGroup-handle .oo-ui-labeledElement-label {
-       margin-left: 3.25em;
+  margin-left: 3.25em;
 }
 
 .oo-ui-popupToolGroup.oo-ui-indicatedElement .oo-ui-popupToolGroup-handle .oo-ui-labeledElement-label {
-       margin-right: 2.25em;
+  margin-right: 2.25em;
 }
 
 .oo-ui-popupToolGroup .oo-ui-toolGroup-tools {
-       display: none;
-       position: absolute;
-       top: 2em;
-       left: -1px;
-       z-index: 4;
-       border: solid 1px #ccc;
-       background-color: white;
-       box-shadow: 0 0.25em 1em rgba(0,0,0,0.25);
+  position: absolute;
+  top: 2em;
+  left: -1px;
+  z-index: 4;
+  display: none;
 }
 
 .oo-ui-popupToolGroup .oo-ui-toolGroup-tools .oo-ui-iconedElement-icon {
-       background-repeat: no-repeat;
-       background-position: center center;
+  background-position: center center;
+  background-repeat: no-repeat;
 }
 
-.oo-ui-popupToolGroup-active:not(.oo-ui-widget-disabled) > .oo-ui-toolGroup-tools {
-       display: block;
-}
-
-.oo-ui-popupToolGroup-active:not(.oo-ui-widget-disabled) {
-       border-bottom-left-radius: 0;
-       border-bottom-right-radius: 0;
+.oo-ui-popupToolGroup-active.oo-ui-widget-enabled > .oo-ui-toolGroup-tools {
+  display: block;
 }
 
 .oo-ui-popupToolGroup .oo-ui-tool-link .oo-ui-iconedElement-icon {
-       display: inline-block;
-       vertical-align: middle;
-       height: 2em;
-       width: 2em;
-       margin-right: 0.5em;
+  display: inline-block;
+  width: 2em;
+  height: 2em;
+  margin-right: 0.5em;
+  vertical-align: middle;
 }
 
 .oo-ui-popupToolGroup .oo-ui-tool-link .oo-ui-tool-title {
-       display: inline-block;
-       vertical-align: middle;
-       line-height: 2em;
-       font-size: 0.8em;
+  display: inline-block;
+  font-size: 0.8em;
+  line-height: 2em;
+  vertical-align: middle;
 }
 
 .oo-ui-popupToolGroup .oo-ui-tool-accel {
-       display: none;
-}
-
-/* OO.ui.ListToolGroup */
-
-.oo-ui-listToolGroup .oo-ui-toolGroup-tools {
-       padding: 0.25em;
-}
-
-.oo-ui-listToolGroup .oo-ui-tool {
-       display: inline-block;
-       width: 100%;
-       -webkit-box-sizing: border-box;
-       -moz-box-sizing: border-box;
-       box-sizing: border-box;
-       border: solid 1px transparent;
-       margin: -1px 0;
-}
-
-.oo-ui-listToolGroup .oo-ui-tool-link {
-       display: block;
-       cursor: pointer;
-       white-space: nowrap;
-       padding-right: 0.5em;
-}
-
-.oo-ui-listToolGroup.oo-ui-popupToolGroup-active {
-       border-color: rgba(0,0,0,0.2);
-}
-
-.oo-ui-listToolGroup
-       .oo-ui-tool-active:not(.oo-ui-widget-disabled) +
-       .oo-ui-tool-active:not(.oo-ui-widget-disabled)
-{
-       border-top-color: rgba(0,0,0,0.1);
-}
-
-.oo-ui-listToolGroup .oo-ui-tool:hover:not(.oo-ui-widget-disabled) {
-       border-color: rgba(0,0,0,0.2);
+  display: none;
 }
 
-.oo-ui-listToolGroup .oo-ui-tool-active:not(.oo-ui-widget-disabled) {
-       border-color: rgba(0,0,0,0.2);
-}
-
-.oo-ui-listToolGroup .oo-ui-tool.oo-ui-widget-disabled .oo-ui-tool-link {
-       cursor: default;
-}
-
-.oo-ui-listToolGroup .oo-ui-tool.oo-ui-widget-disabled .oo-ui-tool-link .oo-ui-tool-title {
-       color: #ccc;
-}
-
-.oo-ui-listToolGroup .oo-ui-tool.oo-ui-widget-disabled .oo-ui-tool-link .oo-ui-iconedElement-icon {
-       opacity: 0.2;
-}
-
-.oo-ui-listToolGroup .oo-ui-tool:not(.oo-ui-widget-disabled) .oo-ui-tool-link .oo-ui-iconedElement-icon {
-       opacity: 0.8;
-}
-
-.oo-ui-listToolGroup .oo-ui-tool:hover:not(.oo-ui-widget-disabled) .oo-ui-tool-link .oo-ui-iconedElement-icon {
-       opacity: 1;
-}
-
-/* OO.ui.MenuToolGroup */
-
-.oo-ui-menuToolGroup {
-       border-color: rgba(0,0,0,0.1);
-}
-
-.oo-ui-menuToolGroup:hover {
-       border-color: rgba(0,0,0,0.2);
-}
-
-.oo-ui-menuToolGroup.oo-ui-popupToolGroup-active {
-       border-color: rgba(0,0,0,0.25);
-}
-
-.oo-ui-menuToolGroup .oo-ui-popupToolGroup-handle {
-       min-width: 8em;
-}
-
-.oo-ui-menuToolGroup .oo-ui-tool {
-       display: block;
-}
-
-.oo-ui-menuToolGroup .oo-ui-tool-link {
-       display: block;
-       cursor: pointer;
-       white-space: nowrap;
-       padding: 0.25em 1em 0.25em 0.25em;
-}
-
-.oo-ui-menuToolGroup .oo-ui-tool-link .oo-ui-iconedElement-icon {
-       background-image: none;
-}
-
-.oo-ui-menuToolGroup .oo-ui-tool-active .oo-ui-tool-link .oo-ui-iconedElement-icon {
-       /* @embed */
-       background-image: url(images/icons/check.png);
-}
-
-.oo-ui-menuToolGroup .oo-ui-tool:hover {
-       background-color: #e1f3ff;
-}
-
-/* Common */
-
-.oo-ui-barToolGroup .oo-ui-tool-active:not(.oo-ui-widget-disabled),
-.oo-ui-listToolGroup .oo-ui-tool-active:not(.oo-ui-widget-disabled),
-.oo-ui-popupToolGroup-active:not(.oo-ui-widget-disabled) {
-       /* @embed */
-       background-image: url(images/fade-down.png);
-       background-position: left top;
-       background-repeat: repeat-x;
-       box-shadow: inset 0 0.07em 0.07em 0 rgba(0, 0, 0, 0.07);
-}
-/* OO.ui.ButtonWidget */
-
-.oo-ui-buttonWidget {
-       display: inline-block;
-       vertical-align: middle;
-}
-
-/* OO.ui.PopupButtonWidget */
-
-.oo-ui-popupButtonWidget {
-       position: relative;
-}
-
-.oo-ui-popupButtonWidget .oo-ui-popupWidget {
-       position: absolute;
-       left: 1em;
-       cursor: auto;
-}
-
-/* OO.ui.ButtonGroupWidget */
-
-.oo-ui-buttonGroupWidget {
-       display: inline-block;
-       white-space: nowrap;
-       border-radius: 0.3em;
-}
-
-.oo-ui-buttonGroupWidget .oo-ui-buttonedElement-framed .oo-ui-buttonedElement-button {
-       border-radius: 0;
-       margin-bottom: -1px;
-       margin-left: -1px;
-}
-
-.oo-ui-buttonGroupWidget .oo-ui-buttonedElement-framed:first-child .oo-ui-buttonedElement-button {
-       border-bottom-left-radius: 0.3em;
-       border-top-left-radius: 0.3em;
-       margin-left: 0;
+.oo-ui-popupTool .oo-ui-popupWidget {
+  margin-left: 1.25em;
+  font-size: 0.8em;
 }
 
-.oo-ui-buttonGroupWidget .oo-ui-buttonedElement-framed:last-child .oo-ui-buttonedElement-button {
-       border-bottom-right-radius: 0.3em;
-       border-top-right-radius: 0.3em;
+.oo-ui-popupTool .oo-ui-popupWidget-popup,
+.oo-ui-popupTool .oo-ui-popupWidget-tail {
+  z-index: 4;
 }
 
-/* OO.ui.SelectWidget */
-
 .oo-ui-selectWidget {
-       list-style: none;
-       margin: 0;
-       padding: 0;
+  padding: 0;
+  margin: 0;
+  list-style: none;
 }
 
-/* OO.ui.OptionWidget */
-
 .oo-ui-optionWidget {
-       position: relative;
-       display: block;
-       border: none;
-       list-style: none;
-       margin: 0;
-       padding: 0.5em 2em 0.5em 3em;
-       cursor: pointer;
-}
-
-.oo-ui-optionWidget .oo-ui-labeledElement-label {
-       line-height: 1.5em;
-       white-space: nowrap;
-       text-overflow: ellipsis;
-       overflow: hidden;
-}
-
-.oo-ui-optionWidget-highlighted {
-       background-color: #e1f3ff;
+  position: relative;
+  display: block;
+  padding: 0.5em 2em 0.5em 3em;
+  margin: 0;
+  list-style: none;
+  cursor: pointer;
+  border: none;
 }
 
-.oo-ui-optionWidget-selected {
-       background-color: #a7dcff;
+.oo-ui-optionWidget.oo-ui-widget-disabled {
+  cursor: default;
 }
 
-.oo-ui-optionWidget.oo-ui-widget-disabled {
-       cursor: default;
+.oo-ui-optionWidget .oo-ui-labeledElement-label {
+  overflow: hidden;
+  line-height: 1.5em;
+  text-overflow: ellipsis;
+  white-space: nowrap;
 }
 
 .oo-ui-optionWidget .oo-ui-iconedElement-icon,
 .oo-ui-optionWidget .oo-ui-indicatedElement-indicator {
-       position: absolute;
-       top: 50%;
-       width: 2em;
-       height: 2em;
-       margin-top: -1em;
-       background-repeat: no-repeat;
-       background-position: center center;
+  position: absolute;
+  top: 50%;
+  width: 2em;
+  height: 2em;
+  margin-top: -1em;
+  background-position: center center;
+  background-repeat: no-repeat;
 }
 
 .oo-ui-optionWidget .oo-ui-iconedElement-icon {
-       left: 0.5em;
+  left: 0.5em;
 }
 
 .oo-ui-optionWidget .oo-ui-indicatedElement-indicator {
-       right: 0.5em;
+  right: 0.5em;
 }
 
-/* OO.ui.OutlineItemWidget */
-
-.oo-ui-outlineItemWidget {
-       position: relative;
-       padding: 0.75em 0.75em 0.75em 3.5em;
-       -webkit-user-select: none;
-       -moz-user-select: none;
-       -ms-user-select: none;
-       user-select: none;
-       cursor: pointer;
-       font-size: 1.1em;
-}
-
-.oo-ui-outlineItemWidget-level-1 {
-       padding-left: 5em;
-}
-
-.oo-ui-outlineItemWidget-level-2 {
-       padding-left: 6.5em;
-}
-
-.oo-ui-outlineItemWidget.oo-ui-optionWidget-selected {
-       background-color: #a7dcff;
-       text-shadow: 0 1px 1px rgba(255,255,255,0.5);
-}
-
-.oo-ui-outlineItemWidget-level-0 .oo-ui-iconedElement-icon {
-       left: 1em;
-}
-
-.oo-ui-outlineItemWidget-level-1 .oo-ui-iconedElement-icon {
-       left: 2.5em;
+.oo-ui-menuWidget {
+  position: absolute;
 }
 
-.oo-ui-outlineItemWidget-level-2 .oo-ui-iconedElement-icon {
-       left: 4em;
+.oo-ui-menuWidget input {
+  position: absolute;
+  width: 0;
+  height: 0;
+  overflow: hidden;
+  opacity: 0;
 }
 
-.oo-ui-outlineItemWidget.oo-ui-flaggableElement-important {
-       font-weight: bold;
+.oo-ui-popupWidget-popup {
+  position: absolute;
+  overflow: hidden;
 }
 
-.oo-ui-outlineItemWidget.oo-ui-flaggableElement-placeholder {
-       font-style: italic;
+.oo-ui-popupWidget-tail {
+  display: none;
 }
 
-.oo-ui-outlineItemWidget.oo-ui-flaggableElement-empty .oo-ui-iconedElement-icon,
-.oo-ui-outlineItemWidget.oo-ui-flaggableElement-empty .oo-ui-indicatedElement-indicator {
-       opacity: 0.5;
-}
-.oo-ui-outlineItemWidget.oo-ui-flaggableElement-empty .oo-ui-labeledElement-label {
-       color: #698AA0;
+.oo-ui-popupWidget-tailed .oo-ui-popupWidget-popup {
+  margin-top: 7px;
 }
 
-/* OO.ui.OutlineControlsWidget */
-
-.oo-ui-outlineControlsWidget {
-       height: 3em;
-       background-color: #fff;
+.oo-ui-popupWidget-tailed .oo-ui-popupWidget-tail {
+  position: absolute;
+  display: block;
+  background-repeat: no-repeat;
 }
 
-.oo-ui-outlineControlsWidget-adders,
-.oo-ui-outlineControlsWidget-movers {
-       float: left;
-       -webkit-box-sizing: border-box;
-       -moz-box-sizing: border-box;
-       box-sizing: border-box;
-       height: 3em;
-       padding: 0.5em;
+.oo-ui-popupWidget-head {
+  height: 2.5em;
+  -webkit-user-select: none;
+     -moz-user-select: none;
+      -ms-user-select: none;
+          user-select: none;
+  -webkit-touch-callout: none;
 }
 
-.oo-ui-outlineControlsWidget-adders {
-       float: left;
-}
-.oo-ui-outlineControlsWidget-movers {
-       float: right;
+.oo-ui-popupWidget-head .oo-ui-buttonWidget {
+  float: right;
+  margin: 0.25em;
 }
 
-.oo-ui-outlineControlsWidget-adders .oo-ui-buttonWidget {
-       float: left;
+.oo-ui-popupWidget-head .oo-ui-labeledElement-label {
+  float: left;
+  margin: 0.75em 1em;
+  cursor: default;
 }
 
-.oo-ui-outlineControlsWidget-movers .oo-ui-buttonWidget {
-       float: right;
+.oo-ui-buttonGroupWidget {
+  border-radius: 0.3em;
 }
 
-.oo-ui-outlineControlsWidget-adders .oo-ui-buttonWidget:first-child,
-.oo-ui-outlineControlsWidget-adders .oo-ui-buttonWidget:first-child:hover {
-       opacity: 0.25;
-       cursor: default;
+.oo-ui-buttonGroupWidget .oo-ui-buttonedElement-framed .oo-ui-buttonedElement-button {
+  margin-bottom: -1px;
+  margin-left: -1px;
+  border-radius: 0;
 }
 
-/* OO.ui.LabelWidget */
-
-.oo-ui-labelWidget {
-       padding: 0.5em 0;
+.oo-ui-buttonGroupWidget .oo-ui-buttonedElement-framed:first-child .oo-ui-buttonedElement-button {
+  margin-left: 0;
+  border-bottom-left-radius: 0.3em;
+  border-top-left-radius: 0.3em;
 }
 
-/* OO.ui.TextInputWidget */
-
-.oo-ui-textInputWidget {
-       -webkit-box-sizing: border-box;
-       -moz-box-sizing: border-box;
-       box-sizing: border-box;
-       width: 20em;
-       position: relative;
+.oo-ui-buttonGroupWidget .oo-ui-buttonedElement-framed:last-child .oo-ui-buttonedElement-button {
+  border-top-right-radius: 0.3em;
+  border-bottom-right-radius: 0.3em;
 }
 
-.oo-ui-textInputWidget input,
-.oo-ui-textInputWidget input:focus[readonly],
-.oo-ui-widget-disabled.oo-ui-textInputWidget input:focus,
-.oo-ui-textInputWidget textarea,
-.oo-ui-textInputWidget textarea:focus[readonly],
-.oo-ui-widget-disabled.oo-ui-textInputWidget textarea:focus {
-       display: inline-block;
-       font-size: 1em;
-       font-family: sans-serif;
-       background-color: #fff;
-       border: solid 1px #ccc;
-       box-shadow: 0 0 0 white, inset 0 0.1em 0.2em #ddd;
-       padding: 0.5em;
-       border-radius: 0.25em;
-       -webkit-box-sizing: border-box;
-       -moz-box-sizing: border-box;
-       box-sizing: border-box;
-       width: 100%;
-       resize: none;
-
-       /* Animation */
-       -webkit-transition: border-color 200ms, box-shadow 200ms;
-       -moz-transition: border-color 200ms, box-shadow 200ms;
-       -o-transition: border-color 200ms, box-shadow 200ms;
-       transition: border-color 200ms, box-shadow 200ms;
-}
-
-.oo-ui-textInputWidget-pending input,
-.oo-ui-textInputWidget-pending textarea {
-       background-color: transparent;
-}
-
-.oo-ui-textInputWidget input:focus,
-.oo-ui-textInputWidget textarea:focus {
-       outline: none;
-       border-color: #a7dcff;
-       box-shadow: 0 0 0.3em #a7dcff, 0 0 0 white;
-}
-
-.oo-ui-textInputWidget input[readonly],
-.oo-ui-textInputWidget textarea[readonly] {
-       color: #777;
-       text-shadow: 0 1px 1px #fff;
-}
-
-.oo-ui-widget-disabled.oo-ui-textInputWidget input,
-.oo-ui-widget-disabled.oo-ui-textInputWidget input:focus,
-.oo-ui-widget-disabled.oo-ui-textInputWidget textarea,
-.oo-ui-widget-disabled.oo-ui-textInputWidget textarea:focus {
-       color: #ccc;
-       border-color: #ddd;
-       text-shadow: 0 1px 1px #fff;
+.oo-ui-buttonOptionWidget {
+  display: inline-block;
+  padding: 0;
+  background-color: transparent;
 }
 
-.oo-ui-textInputWidget-decorated input,
-.oo-ui-textInputWidget-decorated textarea {
-       padding-left: 2em;
+.oo-ui-buttonOptionWidget .oo-ui-buttonedElement-button {
+  position: relative;
+  height: 1.9em;
 }
 
-.oo-ui-textInputWidget-icon {
-       position: absolute;
-       top: 0;
-       left: 0;
-       width: 2em;
-       height: 100%;
-       background-position: right center;
-       background-repeat: no-repeat;
+.oo-ui-buttonOptionWidget.oo-ui-iconedElement .oo-ui-iconedElement-icon,
+.oo-ui-buttonOptionWidget.oo-ui-indicatedElement .oo-ui-indicatedElement-indicator {
+  position: static;
+  display: inline-block;
+  height: 1.9em;
+  margin-top: 0;
+  vertical-align: middle;
 }
 
-/* OO.ui.MenuWidget */
-
-.oo-ui-menuWidget {
-       position: absolute;
-       background: #fff;
-       margin-top: -1px;
-       border: solid 1px #ccc;
-       border-radius: 0 0 0.25em 0.25em;
-       box-shadow: 0 0.15em 1em 0 rgba(0, 0, 0, 0.2);
+.oo-ui-buttonSelectWidget {
+  display: inline-block;
+  white-space: nowrap;
 }
 
-.oo-ui-menuWidget input {
-       position: absolute;
-       width: 0;
-       height: 0;
-       overflow: hidden;
-       opacity: 0;
+.oo-ui-buttonWidget {
+  display: inline-block;
+  vertical-align: middle;
 }
 
-/* OO.ui.InlineMenuWidget */
-
 .oo-ui-inlineMenuWidget {
-       position: relative;
-       display: inline-block;
-       margin: 0.25em 0;
-       min-width: 20em;
+  position: relative;
+  display: inline-block;
+  min-width: 20em;
+  margin: 0.25em 0;
 }
 
 .oo-ui-inlineMenuWidget-handle {
-       display: inline-block;
-       width: 100%;
-       height: 2.5em;
-       border: solid 1px rgba(0,0,0,0.1);
-       border-radius: 0.25em;
-       -webkit-box-sizing: border-box;
-       -moz-box-sizing: border-box;
-       box-sizing: border-box;
-       -webkit-touch-callout: none;
-       -webkit-user-select: none;
-       -moz-user-select: none;
-       -ms-user-select: none;
-       user-select: none;
-       cursor: pointer;
-}
-
-.oo-ui-inlineMenuWidget-handle:hover {
-       border-color: rgba(0,0,0,0.2);
+  display: inline-block;
+  width: 100%;
+  height: 2.5em;
+  cursor: pointer;
+  -webkit-box-sizing: border-box;
+     -moz-box-sizing: border-box;
+          box-sizing: border-box;
+  -webkit-user-select: none;
+     -moz-user-select: none;
+      -ms-user-select: none;
+          user-select: none;
+  -webkit-touch-callout: none;
 }
 
 .oo-ui-inlineMenuWidget-handle .oo-ui-indicatedElement-indicator,
 .oo-ui-inlineMenuWidget-handle .oo-ui-iconedElement-icon {
-       position: absolute;
-       top: 0;
-       width: 2.5em;
-       height: 2.5em;
-       background-position: center center;
-       background-repeat: no-repeat;
-       opacity: 0.8;
+  position: absolute;
+  top: 0;
+  width: 2.5em;
+  height: 2.5em;
+  background-position: center center;
+  background-repeat: no-repeat;
 }
 
 .oo-ui-inlineMenuWidget-handle .oo-ui-indicatedElement-indicator {
-       right: 0;
+  right: 0;
 }
 
 .oo-ui-inlineMenuWidget-handle .oo-ui-iconedElement-icon {
-       left: 0.25em;
+  left: 0.25em;
 }
 
 .oo-ui-inlineMenuWidget-handle .oo-ui-labeledElement-label {
-       line-height: 2.5em;
-       margin: 0 0.5em;
+  margin: 0 0.5em;
+  line-height: 2.5em;
 }
 
 .oo-ui-inlineMenuWidget.oo-ui-iconedElement .oo-ui-inlineMenuWidget-handle .oo-ui-labeledElement-label {
-       margin-left: 3em;
+  margin-left: 3em;
 }
 
 .oo-ui-inlineMenuWidget.oo-ui-indicatedElement .oo-ui-inlineMenuWidget-handle .oo-ui-labeledElement-label {
-       margin-right: 2em;
+  margin-right: 2em;
 }
 
 .oo-ui-inlineMenuWidget .oo-ui-menuWidget {
-       width: 100%;
+  width: 100%;
 }
 
-/* OO.ui.MenuItemWidget */
-
 .oo-ui-menuItemWidget {
-       position: relative;
+  position: relative;
 }
 
 .oo-ui-menuItemWidget .oo-ui-iconedElement-icon {
-       display: none;
-}
-
-.oo-ui-menuItemWidget.oo-ui-optionWidget-selected .oo-ui-iconedElement-icon {
-       display: block;
+  display: none;
 }
 
 .oo-ui-menuItemWidget.oo-ui-optionWidget-selected {
-       background-color: transparent;
+  background-color: transparent;
 }
 
-.oo-ui-menuItemWidget.oo-ui-optionWidget-highlighted {
-       background-color: #e1f3ff;
+.oo-ui-menuItemWidget.oo-ui-optionWidget-selected .oo-ui-iconedElement-icon {
+  display: block;
 }
 
-/* OO.ui.MenuSectionItemWidget */
-
 .oo-ui-menuSectionItemWidget {
-       padding: 0.33em 0.75em;
-       color: #888;
-       cursor: default;
+  padding: 0.33em 0.75em;
+  cursor: default;
 }
 
-/* OO.ui.ButtonSelectWidget */
-
-.oo-ui-buttonSelectWidget {
-       display: inline-block;
-       white-space: nowrap;
-       border-radius: 0.3em;
+.oo-ui-outlineControlsWidget {
+  height: 3em;
 }
 
-.oo-ui-buttonSelectWidget .oo-ui-buttonOptionWidget .oo-ui-buttonedElement-button {
-       border-radius: 0;
-       margin-left: -1px;
+.oo-ui-outlineControlsWidget-adders,
+.oo-ui-outlineControlsWidget-movers {
+  float: left;
+  height: 2em;
+  padding: 0;
+  margin: 0.5em;
+  -webkit-box-sizing: border-box;
+     -moz-box-sizing: border-box;
+          box-sizing: border-box;
 }
 
-.oo-ui-buttonSelectWidget .oo-ui-buttonOptionWidget:first-child .oo-ui-buttonedElement-button {
-       border-bottom-left-radius: 0.3em;
-       border-top-left-radius: 0.3em;
-       margin-left: 0;
+.oo-ui-outlineControlsWidget > .oo-ui-iconedElement-icon {
+  float: left;
+  width: 1.5em;
+  height: 2em;
+  margin: 0.5em 0 0.5em 0.5em;
+  background-position: right center;
+  background-repeat: no-repeat;
 }
 
-.oo-ui-buttonSelectWidget .oo-ui-buttonOptionWidget:last-child .oo-ui-buttonedElement-button {
-       border-bottom-right-radius: 0.3em;
-       border-top-right-radius: 0.3em;
+.oo-ui-outlineControlsWidget-adders {
+  float: left;
+  margin-left: 0;
 }
 
-/* OO.ui.ButtonOptionWidget */
-
-.oo-ui-buttonOptionWidget {
-       display: inline-block;
-       padding: 0;
-       background-color: transparent;
+.oo-ui-outlineControlsWidget-adders .oo-ui-buttonWidget {
+  float: left;
 }
 
-.oo-ui-buttonOptionWidget .oo-ui-buttonedElement-button {
-       position: relative;
-       height: 1.9em;
+.oo-ui-outlineControlsWidget-movers {
+  float: right;
 }
 
-.oo-ui-buttonOptionWidget.oo-ui-iconedElement .oo-ui-iconedElement-icon,
-.oo-ui-buttonOptionWidget.oo-ui-indicatedElement .oo-ui-indicatedElement-indicator {
-       position: static;
-       display: inline-block;
-       vertical-align: middle;
-       height: 1.9em;
-       margin-top: 0;
+.oo-ui-outlineControlsWidget-movers .oo-ui-buttonWidget {
+  float: right;
 }
 
-/* OO.ui.PopupWidget */
+.oo-ui-outlineItemWidget {
+  position: relative;
+  padding: 0.75em;
+  cursor: pointer;
+  -webkit-user-select: none;
+     -moz-user-select: none;
+      -ms-user-select: none;
+          user-select: none;
+  -webkit-touch-callout: none;
+}
 
-.oo-ui-popupWidget-popup {
-       position: absolute;
-       overflow: hidden;
-       border: solid 1px #ccc;
-       border-radius: 0.25em;
-       background-color: #fff;
-       box-shadow: 0 0.15em 0.5em 0 rgba(0, 0, 0, 0.2);
+.oo-ui-outlineItemWidget.oo-ui-indicatedElement .oo-ui-labeledElement-label {
+  padding-right: 1.5em;
 }
 
-.oo-ui-popupWidget-tail {
-       display: none;
+.oo-ui-outlineItemWidget-level-0 {
+  padding-left: 3.5em;
 }
 
-.oo-ui-popupWidget-tailed .oo-ui-popupWidget-popup {
-       margin-top: 7px;
+.oo-ui-outlineItemWidget-level-0 .oo-ui-iconedElement-icon {
+  left: 1em;
 }
 
-.oo-ui-popupWidget-tailed .oo-ui-popupWidget-tail {
-       display: block;
-       position: absolute;
-       /* @embed */
-       background-image: url(images/tail.svg);
-       background-repeat: no-repeat;
-       width: 15px;
-       height: 8px;
-       margin-left: -7px;
-}
-
-.oo-ui-popupWidget-transitioning .oo-ui-popupWidget-popup {
-       -webkit-transition: width 100ms, height 100ms, left 100ms;
-       -moz-transition: width 100ms, height 100ms, left 100ms;
-       -o-transition: width 100ms, height 100ms, left 100ms;
-       transition: width 100ms, height 100ms, left 100ms;
-       -webkit-transition-timing-function: ease-in-out;
-       -moz-transition-timing-function: ease-in-out;
-       -o-transition-timing-function: ease-in-out;
-       transition-timing-function: ease-in-out;
+.oo-ui-outlineItemWidget-level-1 {
+  padding-left: 5em;
 }
 
-.oo-ui-popupWidget-head {
-       height: 2.5em;
-       -webkit-touch-callout: none;
-       -webkit-user-select: none;
-       -moz-user-select: none;
-       -ms-user-select: none;
-       user-select: none;
+.oo-ui-outlineItemWidget-level-1 .oo-ui-iconedElement-icon {
+  left: 2.5em;
 }
 
-.oo-ui-popupWidget-head .oo-ui-buttonWidget {
-       float: right;
-       margin: 0.25em;
+.oo-ui-outlineItemWidget-level-2 {
+  padding-left: 6.5em;
 }
 
-.oo-ui-popupWidget-head .oo-ui-labeledElement-label {
-       float: left;
-       margin: 0.75em 1em;
-       cursor: default;
+.oo-ui-outlineItemWidget-level-2 .oo-ui-iconedElement-icon {
+  left: 4em;
 }
 
-.oo-ui-popupWidget-body {
-       box-shadow: 0 0 0.66em rgba(0,0,0,0.25);
+.oo-ui-popupButtonWidget {
+  position: relative;
 }
 
-/* OO.ui.SearchWidget */
+.oo-ui-popupButtonWidget .oo-ui-popupWidget {
+  position: absolute;
+  left: 1em;
+  cursor: auto;
+}
 
 .oo-ui-searchWidget-query {
-       position: absolute;
-       top: 0;
-       left: 0;
-       right: 0;
-       height: 4em;
-       padding: 0 1em;
-       box-shadow: 0 0 0.5em rgba(0,0,0,0.2);
+  position: absolute;
+  top: 0;
+  right: 0;
+  left: 0;
+  height: 4em;
+  padding: 0 1em;
 }
 
 .oo-ui-searchWidget-query .oo-ui-textInputWidget {
-       width: 100%;
-       margin: 0.75em 0;
+  width: 100%;
+  margin: 0.75em 0;
 }
 
 .oo-ui-searchWidget-results {
-       position: absolute;
-       top: 4em;
-       bottom: 0;
-       left: 0;
-       right: 0;
-       padding: 1em;
-       overflow-x: hidden;
-       overflow-y: auto;
-       line-height: 0;
+  position: absolute;
+  top: 4em;
+  right: 0;
+  bottom: 0;
+  left: 0;
+  padding: 1em;
+  overflow-x: hidden;
+  overflow-y: auto;
+  line-height: 0;
 }
 
-/* OO.ui.ToggleSwitchWidget */
-
-.oo-ui-toggleSwitchWidget {
-       position: relative;
-       display: inline-block;
-       vertical-align: middle;
-       height: 2em;
-       width: 3em;
-       border-radius: 1em;
-       overflow: hidden;
-       box-shadow: 0 0 0 white, inset 0 0.1em 0.2em #ddd;
-       border: solid 1px #ccc;
-       cursor: pointer;
-       -webkit-box-sizing: border-box;
-       -moz-box-sizing: border-box;
-       box-sizing: border-box;
-       -webkit-transform: translateZ(0px);
-       -moz-transform: translateZ(0px);
-       -ms-transform: translateZ(0px);
-       -o-transform: translateZ(0px);
-       transform: translateZ(0px);
-
-       /* Gray */
-       background-color: #dddddd;
-       filter: progid:DXImageTransform.Microsoft.gradient(
-               GradientType=0,startColorstr=#dddddd, endColorstr=#ffffff
-       );
-       background-image: -webkit-gradient(
-               linear, right top, right bottom, color-stop(0%,#dddddd), color-stop(100%,#ffffff)
-       );
-       background-image: -webkit-linear-gradient(top, #dddddd 0%, #ffffff 100%);
-       background-image: -moz-linear-gradient(top, #dddddd 0%, #ffffff 100%);
-       background-image: -ms-linear-gradient(top, #dddddd 0%, #ffffff 100%);
-       background-image: -o-linear-gradient(top, #dddddd 0%, #ffffff 100%);
-       background-image: linear-gradient(top, #dddddd 0%, #ffffff 100%);
+.oo-ui-textInputWidget {
+  position: relative;
+  width: 20em;
+  -webkit-box-sizing: border-box;
+     -moz-box-sizing: border-box;
+          box-sizing: border-box;
 }
 
-.oo-ui-toggleSwitchWidget.oo-ui-widget-disabled {
-       opacity: 0.5;
-       cursor: default;
+.oo-ui-textInputWidget input,
+.oo-ui-textInputWidget textarea {
+  display: inline-block;
+  width: 100%;
+  padding: 0.5em;
+  -webkit-box-sizing: border-box;
+     -moz-box-sizing: border-box;
+          box-sizing: border-box;
+  resize: none;
 }
 
-.oo-ui-toggleSwitchWidget-grip {
-       -webkit-transition: left 200ms ease-in-out, margin-left 200ms ease-in-out;
-       -moz-transition: left 200ms ease-in-out, margin-left 200ms ease-in-out;
-       -o-transition: left 200ms ease-in-out, margin-left 200ms ease-in-out;
-       transition: left 200ms ease-in-out, margin-left 200ms ease-in-out;
+.oo-ui-textInputWidget-decorated input,
+.oo-ui-textInputWidget-decorated textarea {
+  padding-left: 2em;
 }
 
-.oo-ui-toggleSwitchWidget-grip {
-       position: absolute;
-       display: block;
-       top: 0.25em;
-       left: 0.25em;
-       width: 1.5em;
-       height: 1.5em;
-       border-radius: 1em;
-       box-shadow: 0 0.1em 0.25em rgba(0, 0, 0, 0.1);
-       -webkit-box-sizing: border-box;
-       -moz-box-sizing: border-box;
-       box-sizing: border-box;
-
-       /* Gray */
-       border: 1px #c9c9c9 solid;
-       background-color: #ffffff;
-       filter: progid:DXImageTransform.Microsoft.gradient(
-               GradientType=0,startColorstr=#ffffff, endColorstr=#dddddd
-       );
-       background-image: -webkit-gradient(
-               linear, right top, right bottom, color-stop(0%,#ffffff), color-stop(100%,#dddddd)
-       );
-       background-image: -webkit-linear-gradient(top, #ffffff 0%, #dddddd 100%);
-       background-image: -moz-linear-gradient(top, #ffffff 0%, #dddddd 100%);
-       background-image: -ms-linear-gradient(top, #ffffff 0%, #dddddd 100%);
-       background-image: -o-linear-gradient(top, #ffffff 0%, #dddddd 100%);
-       background-image: linear-gradient(top, #ffffff 0%, #dddddd 100%);
-}
-
-.oo-ui-toggleSwitchWidget:not(.oo-ui-widget-disabled):hover,
-.oo-ui-toggleSwitchWidget:not(.oo-ui-widget-disabled):hover .oo-ui-toggleSwitchWidget-grip {
-       border-color: #aaa;
+.oo-ui-textInputWidget-icon {
+  position: absolute;
+  top: 0;
+  left: 0;
+  width: 2em;
+  height: 100%;
+  background-position: right center;
+  background-repeat: no-repeat;
 }
 
-.oo-ui-toggleWidget-on .oo-ui-toggleSwitchWidget-grip {
-       left: 1.25em;
-       margin-left: -2px;
+.oo-ui-toggleSwitchWidget {
+  position: relative;
+  display: inline-block;
+  width: 3em;
+  height: 2em;
+  overflow: hidden;
+  vertical-align: middle;
+  cursor: pointer;
+  -webkit-transform: translateZ(0);
+     -moz-transform: translateZ(0);
+      -ms-transform: translateZ(0);
+       -o-transform: translateZ(0);
+          transform: translateZ(0);
+  -webkit-box-sizing: border-box;
+     -moz-box-sizing: border-box;
+          box-sizing: border-box;
 }
 
-.oo-ui-toggleWidget-off .oo-ui-toggleSwitchWidget-grip {
-       left: 0.25em;
-       margin-left: 0;
-}
-
-.oo-ui-toggleSwitchWidget .oo-ui-toggleSwitchWidget-on {
-       position: absolute;
-       top: 0;
-       bottom: 0;
-       right: 0;
-       left: 0;
-       border-radius: 1em;
-       box-shadow: inset 0 1px 4px 0 rgba(0, 0, 0, 0.07);
-       -webkit-touch-callout: none;
-       -webkit-user-select: none;
-       -moz-user-select: none;
-       -ms-user-select: none;
-       user-select: none;
-
-       -webkit-transition: opacity 200ms ease-in-out;
-       -moz-transition: opacity 200ms ease-in-out;
-       -o-transition: opacity 200ms ease-in-out;
-       transition: opacity 200ms ease-in-out;
-
-       /* Blue */
-       background-color: #eaf4fa;
-       filter: progid:DXImageTransform.Microsoft.gradient(
-               GradientType=0,startColorstr=#b0d9ee, endColorstr=#eaf4fa
-       );
-       background-image: -webkit-gradient(
-               linear, right top, right bottom, color-stop(0%,#b0d9ee), color-stop(100%,#eaf4fa)
-       );
-       background-image: -webkit-linear-gradient(top, #b0d9ee 0%, #eaf4fa 100%);
-       background-image: -moz-linear-gradient(top, #b0d9ee 0%, #eaf4fa 100%);
-       background-image: -ms-linear-gradient(top, #b0d9ee 0%, #eaf4fa 100%);
-       background-image: -o-linear-gradient(top, #b0d9ee 0%, #eaf4fa 100%);
-       background-image: linear-gradient(top, #b0d9ee 0%, #eaf4fa 100%);
-}
-
-.oo-ui-toggleWidget-on .oo-ui-toggleSwitchWidget-on {
-       opacity: 1;
-}
-
-.oo-ui-toggleWidget-off .oo-ui-toggleSwitchWidget-on {
-       opacity: 0;
-}
-.oo-ui-window-head {
-       -webkit-touch-callout: none;
-       -webkit-user-select: none;
-       -moz-user-select: none;
-       -ms-user-select: none;
-       user-select: none;
+.oo-ui-toggleSwitchWidget.oo-ui-widget-disabled {
+  cursor: default;
 }
 
-.oo-ui-window-body {
-       padding: 0 0.75em;
+.oo-ui-toggleSwitchWidget-grip {
+  position: absolute;
+  top: 0.25em;
+  left: 0.25em;
+  display: block;
+  width: 1.5em;
+  height: 1.5em;
+  -webkit-box-sizing: border-box;
+     -moz-box-sizing: border-box;
+          box-sizing: border-box;
+  -webkit-transition: left 200ms ease-in-out, margin-left 200ms ease-in-out;
+     -moz-transition: left 200ms ease-in-out, margin-left 200ms ease-in-out;
+      -ms-transition: left 200ms ease-in-out, margin-left 200ms ease-in-out;
+       -o-transition: left 200ms ease-in-out, margin-left 200ms ease-in-out;
+          transition: left 200ms ease-in-out, margin-left 200ms ease-in-out;
+}
+
+.oo-ui-toggleSwitchWidget .oo-ui-toggleSwitchWidget-glow {
+  position: absolute;
+  top: 0;
+  right: 0;
+  bottom: 0;
+  left: 0;
+  -webkit-transition: opacity 200ms ease-in-out;
+     -moz-transition: opacity 200ms ease-in-out;
+      -ms-transition: opacity 200ms ease-in-out;
+       -o-transition: opacity 200ms ease-in-out;
+          transition: opacity 200ms ease-in-out;
+  -webkit-user-select: none;
+     -moz-user-select: none;
+      -ms-user-select: none;
+          user-select: none;
+  -webkit-touch-callout: none;
 }
 
-.oo-ui-window-icon {
-       float: left;
-       width: 2em;
-       height: 2em;
-       line-height: 2em;
-       margin-right: 0.5em;
-       background-position: right center;
-       background-repeat: no-repeat;
+.oo-ui-toggleWidget-on .oo-ui-toggleSwitchWidget-grip {
+  left: 1.25em;
+  margin-left: -2px;
 }
 
-.oo-ui-window-title {
-       float: left;
-       line-height: 2em;
-       color: #333;
-       white-space: nowrap;
-       cursor: default;
+.oo-ui-toggleWidget-off .oo-ui-toggleSwitchWidget-grip {
+  left: 0.25em;
+  margin-left: 0;
 }
 
-.oo-ui-window-overlay {
-       font-family: sans-serif;
-       line-height: 1.5em;
-       font-size: 1em;
-       position: absolute;
-       top: 0;
-       left: 0;
+.oo-ui-toggleWidget-off .oo-ui-toggleSwitchWidget-glow {
+  display: none;
 }
+
 /* Icons */
 
 .oo-ui-icon-add-item {
-       /* @embed */
-       background-image: url(images/icons/add-item.svg);
+  background-image: /* @embed */ url(images/icons/add-item.svg);
 }
 
 .oo-ui-icon-advanced {
-       /* @embed */
-       background-image: url(images/icons/advanced.svg);
+  background-image: /* @embed */ url(images/icons/advanced.svg);
 }
 
 .oo-ui-icon-alert {
-       /* @embed */
-       background-image: url(images/icons/alert.svg);
+  background-image: /* @embed */ url(images/icons/alert.svg);
 }
 
 .oo-ui-icon-check {
-       /* @embed */
-       background-image: url(images/icons/check.svg);
+  background-image: /* @embed */ url(images/icons/check.svg);
 }
 
 .oo-ui-icon-clear {
-       /* @embed */
-       background-image: url(images/icons/clear.svg);
+  background-image: /* @embed */ url(images/icons/clear.svg);
 }
 
 .oo-ui-icon-close {
-       /* @embed */
-       background-image: url(images/icons/close.svg);
+  background-image: /* @embed */ url(images/icons/close.svg);
 }
 
 .oo-ui-icon-code {
-       /* @embed */
-       background-image: url(images/icons/code.svg);
+  background-image: /* @embed */ url(images/icons/code.svg);
 }
 
 .oo-ui-icon-collapse {
-       /* @embed */
-       background-image: url(images/icons/collapse.svg);
+  background-image: /* @embed */ url(images/icons/collapse.svg);
 }
 
 .oo-ui-icon-comment {
-       /* @embed */
-       background-image: url(images/icons/comment.svg);
+  background-image: /* @embed */ url(images/icons/comment.svg);
 }
 
 .oo-ui-icon-expand {
-       /* @embed */
-       background-image: url(images/icons/expand.svg);
+  background-image: /* @embed */ url(images/icons/expand.svg);
 }
 
 .oo-ui-icon-help {
-       /* @embed */
-       background-image: url(images/icons/help.svg);
+  background-image: /* @embed */ url(images/icons/help.svg);
 }
 
 .oo-ui-icon-link {
-       /* @embed */
-       background-image: url(images/icons/link.svg);
+  background-image: /* @embed */ url(images/icons/link.svg);
 }
 
 .oo-ui-icon-menu {
-       /* @embed */
-       background-image: url(images/icons/menu.svg);
+  background-image: /* @embed */ url(images/icons/menu.svg);
 }
 
 .oo-ui-icon-next {
-       /* @embed */
-       background-image: url(images/icons/move-ltr.svg);
+  background-image: /* @embed */ url(images/icons/move-ltr.svg);
 }
 
 .oo-ui-icon-picture {
-       /* @embed */
-       background-image: url(images/icons/picture.svg);
+  background-image: /* @embed */ url(images/icons/picture.svg);
 }
 
 .oo-ui-icon-previous {
-       /* @embed */
-       background-image: url(images/icons/move-rtl.svg);
+  background-image: /* @embed */ url(images/icons/move-rtl.svg);
 }
 
 .oo-ui-icon-redo {
-       /* @embed */
-       background-image: url(images/icons/arched-arrow-ltr.svg);
+  background-image: /* @embed */ url(images/icons/arched-arrow-ltr.svg);
 }
 
 .oo-ui-icon-remove {
-       /* @embed */
-       background-image: url(images/icons/remove.svg);
+  background-image: /* @embed */ url(images/icons/remove.svg);
 }
 
 .oo-ui-icon-search {
-       /* @embed */
-       background-image: url(images/icons/search.svg);
+  background-image: /* @embed */ url(images/icons/search.svg);
 }
 
 .oo-ui-icon-settings {
-       /* @embed */
-       background-image: url(images/icons/settings.svg);
+  background-image: /* @embed */ url(images/icons/settings.svg);
 }
 
 .oo-ui-icon-tag {
-       /* @embed */
-       background-image: url(images/icons/tag.svg);
+  background-image: /* @embed */ url(images/icons/tag.svg);
 }
 
 .oo-ui-icon-undo {
-       /* @embed */
-       background-image: url(images/icons/arched-arrow-rtl.svg);
+  background-image: /* @embed */ url(images/icons/arched-arrow-rtl.svg);
 }
 
 .oo-ui-icon-window {
-       /* @embed */
-       background-image: url(images/icons/window.svg);
+  background-image: /* @embed */ url(images/icons/window.svg);
 }
 
 /* Indicators */
 
 .oo-ui-indicator-down {
-       /* @embed */
-       background-image: url(images/indicators/down.svg);
+  background-image: /* @embed */ url(images/indicators/down.svg);
 }
 
 .oo-ui-indicator-required {
-       /* @embed */
-       background-image: url(images/indicators/required.svg);
+  background-image: /* @embed */ url(images/indicators/required.svg);
 }
 
 .oo-ui-indicator-up {
-       /* @embed */
-       background-image: url(images/indicators/up.svg);
-}
+  background-image: /* @embed */ url(images/indicators/up.svg);
+}
\ No newline at end of file
index 66536bb..6cf631f 100755 (executable)
@@ -37,6 +37,11 @@ fi
 # Undo any changes in the oojs-ui directory
 git reset resources/oojs-ui/
 git checkout resources/oojs-ui/
+
+git fetch origin
+# Create a branch of MW if needed, and reset it to master
+git checkout -B update-oojsui origin/master
+
 # Get the old oojs-ui version
 OLDVERSION=$(oojsuihash)
 if [ "x$OLDVERSION" == "x" ]
@@ -64,7 +69,8 @@ then
        exit 0
 fi
 # Build the distribution
-grunt
+npm install || exit 1
+grunt || exit 1
 # Get the list of changes
 NEWCHANGES=$(git log $OLDVERSION.. --oneline --no-merges --reverse --color=never)
 NEWCHANGESDISPLAY=$(git log $OLDVERSION.. --oneline --no-merges --reverse --color=always)
@@ -72,7 +78,7 @@ NEWCHANGESDISPLAY=$(git log $OLDVERSION.. --oneline --no-merges --reverse --colo
 cd -
 
 # Copy files from dist/ to resources/oojs-ui
-cp -a $1/dist/{oojs-ui.js,oojs-ui.svg.css,images,i18n} resources/oojs-ui/
+cp -a $1/dist/{oojs-ui.js,oojs-ui.svg.css,oojs-ui-apex.css,images,i18n} resources/oojs-ui/
 # Figure out what the new version is
 NEWVERSION=$(oojsuiversion)
 # Generate commit summary
index 0bdea23..57c7625 100755 (executable)
@@ -37,6 +37,11 @@ fi
 # Undo any changes in the oojs directory
 git reset resources/oojs/
 git checkout resources/oojs/
+
+git fetch origin
+# Create a branch of MW if needed, and reset it to master
+git checkout -B update-oojs origin/master
+
 # Get the old oojs version
 OLDVERSION=$(oojshash)
 if [ "x$OLDVERSION" == "x" ]
@@ -64,7 +69,8 @@ then
        exit 0
 fi
 # Build the distribution
-grunt
+npm install || exit 1
+grunt || exit 1
 # Get the list of changes
 NEWCHANGES=$(git log $OLDVERSION.. --oneline --no-merges --reverse --color=never)
 NEWCHANGESDISPLAY=$(git log $OLDVERSION.. --oneline --no-merges --reverse --color=always)
diff --git a/resources/sinonjs/sinon-1.8.1.js b/resources/sinonjs/sinon-1.8.1.js
deleted file mode 100644 (file)
index 3e9865e..0000000
+++ /dev/null
@@ -1,4721 +0,0 @@
-/**
- * Sinon.JS 1.8.1, 2014/02/02
- *
- * @author Christian Johansen (christian@cjohansen.no)
- * @author Contributors: https://github.com/cjohansen/Sinon.JS/blob/master/AUTHORS
- *
- * (The BSD License)
- * 
- * Copyright (c) 2010-2013, Christian Johansen, christian@cjohansen.no
- * All rights reserved.
- * 
- * Redistribution and use in source and binary forms, with or without modification,
- * are permitted provided that the following conditions are met:
- * 
- *     * Redistributions of source code must retain the above copyright notice,
- *       this list of conditions and the following disclaimer.
- *     * Redistributions in binary form must reproduce the above copyright notice,
- *       this list of conditions and the following disclaimer in the documentation
- *       and/or other materials provided with the distribution.
- *     * Neither the name of Christian Johansen nor the names of his contributors
- *       may be used to endorse or promote products derived from this software
- *       without specific prior written permission.
- * 
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
- * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
- * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-this.sinon = (function () {
-var samsam, formatio;
-function define(mod, deps, fn) { if (mod == "samsam") { samsam = deps(); } else { formatio = fn(samsam); } }
-define.amd = true;
-((typeof define === "function" && define.amd && function (m) { define("samsam", m); }) ||
- (typeof module === "object" &&
-      function (m) { module.exports = m(); }) || // Node
- function (m) { this.samsam = m(); } // Browser globals
-)(function () {
-    var o = Object.prototype;
-    var div = typeof document !== "undefined" && document.createElement("div");
-
-    function isNaN(value) {
-        // Unlike global isNaN, this avoids type coercion
-        // typeof check avoids IE host object issues, hat tip to
-        // lodash
-        var val = value; // JsLint thinks value !== value is "weird"
-        return typeof value === "number" && value !== val;
-    }
-
-    function getClass(value) {
-        // Returns the internal [[Class]] by calling Object.prototype.toString
-        // with the provided value as this. Return value is a string, naming the
-        // internal class, e.g. "Array"
-        return o.toString.call(value).split(/[ \]]/)[1];
-    }
-
-    /**
-     * @name samsam.isArguments
-     * @param Object object
-     *
-     * Returns ``true`` if ``object`` is an ``arguments`` object,
-     * ``false`` otherwise.
-     */
-    function isArguments(object) {
-        if (typeof object !== "object" || typeof object.length !== "number" ||
-                getClass(object) === "Array") {
-            return false;
-        }
-        if (typeof object.callee == "function") { return true; }
-        try {
-            object[object.length] = 6;
-            delete object[object.length];
-        } catch (e) {
-            return true;
-        }
-        return false;
-    }
-
-    /**
-     * @name samsam.isElement
-     * @param Object object
-     *
-     * Returns ``true`` if ``object`` is a DOM element node. Unlike
-     * Underscore.js/lodash, this function will return ``false`` if ``object``
-     * is an *element-like* object, i.e. a regular object with a ``nodeType``
-     * property that holds the value ``1``.
-     */
-    function isElement(object) {
-        if (!object || object.nodeType !== 1 || !div) { return false; }
-        try {
-            object.appendChild(div);
-            object.removeChild(div);
-        } catch (e) {
-            return false;
-        }
-        return true;
-    }
-
-    /**
-     * @name samsam.keys
-     * @param Object object
-     *
-     * Return an array of own property names.
-     */
-    function keys(object) {
-        var ks = [], prop;
-        for (prop in object) {
-            if (o.hasOwnProperty.call(object, prop)) { ks.push(prop); }
-        }
-        return ks;
-    }
-
-    /**
-     * @name samsam.isDate
-     * @param Object value
-     *
-     * Returns true if the object is a ``Date``, or *date-like*. Duck typing
-     * of date objects work by checking that the object has a ``getTime``
-     * function whose return value equals the return value from the object's
-     * ``valueOf``.
-     */
-    function isDate(value) {
-        return typeof value.getTime == "function" &&
-            value.getTime() == value.valueOf();
-    }
-
-    /**
-     * @name samsam.isNegZero
-     * @param Object value
-     *
-     * Returns ``true`` if ``value`` is ``-0``.
-     */
-    function isNegZero(value) {
-        return value === 0 && 1 / value === -Infinity;
-    }
-
-    /**
-     * @name samsam.equal
-     * @param Object obj1
-     * @param Object obj2
-     *
-     * Returns ``true`` if two objects are strictly equal. Compared to
-     * ``===`` there are two exceptions:
-     *
-     *   - NaN is considered equal to NaN
-     *   - -0 and +0 are not considered equal
-     */
-    function identical(obj1, obj2) {
-        if (obj1 === obj2 || (isNaN(obj1) && isNaN(obj2))) {
-            return obj1 !== 0 || isNegZero(obj1) === isNegZero(obj2);
-        }
-    }
-
-
-    /**
-     * @name samsam.deepEqual
-     * @param Object obj1
-     * @param Object obj2
-     *
-     * Deep equal comparison. Two values are "deep equal" if:
-     *
-     *   - They are equal, according to samsam.identical
-     *   - They are both date objects representing the same time
-     *   - They are both arrays containing elements that are all deepEqual
-     *   - They are objects with the same set of properties, and each property
-     *     in ``obj1`` is deepEqual to the corresponding property in ``obj2``
-     *
-     * Supports cyclic objects.
-     */
-    function deepEqualCyclic(obj1, obj2) {
-
-        // used for cyclic comparison
-        // contain already visited objects
-        var objects1 = [],
-            objects2 = [],
-        // contain pathes (position in the object structure)
-        // of the already visited objects
-        // indexes same as in objects arrays
-            paths1 = [],
-            paths2 = [],
-        // contains combinations of already compared objects
-        // in the manner: { "$1['ref']$2['ref']": true }
-            compared = {};
-
-        /**
-         * used to check, if the value of a property is an object
-         * (cyclic logic is only needed for objects)
-         * only needed for cyclic logic
-         */
-        function isObject(value) {
-
-            if (typeof value === 'object' && value !== null &&
-                    !(value instanceof Boolean) &&
-                    !(value instanceof Date)    &&
-                    !(value instanceof Number)  &&
-                    !(value instanceof RegExp)  &&
-                    !(value instanceof String)) {
-
-                return true;
-            }
-
-            return false;
-        }
-
-        /**
-         * returns the index of the given object in the
-         * given objects array, -1 if not contained
-         * only needed for cyclic logic
-         */
-        function getIndex(objects, obj) {
-
-            var i;
-            for (i = 0; i < objects.length; i++) {
-                if (objects[i] === obj) {
-                    return i;
-                }
-            }
-
-            return -1;
-        }
-
-        // does the recursion for the deep equal check
-        return (function deepEqual(obj1, obj2, path1, path2) {
-            var type1 = typeof obj1;
-            var type2 = typeof obj2;
-
-            // == null also matches undefined
-            if (obj1 === obj2 ||
-                    isNaN(obj1) || isNaN(obj2) ||
-                    obj1 == null || obj2 == null ||
-                    type1 !== "object" || type2 !== "object") {
-
-                return identical(obj1, obj2);
-            }
-
-            // Elements are only equal if identical(expected, actual)
-            if (isElement(obj1) || isElement(obj2)) { return false; }
-
-            var isDate1 = isDate(obj1), isDate2 = isDate(obj2);
-            if (isDate1 || isDate2) {
-                if (!isDate1 || !isDate2 || obj1.getTime() !== obj2.getTime()) {
-                    return false;
-                }
-            }
-
-            if (obj1 instanceof RegExp && obj2 instanceof RegExp) {
-                if (obj1.toString() !== obj2.toString()) { return false; }
-            }
-
-            var class1 = getClass(obj1);
-            var class2 = getClass(obj2);
-            var keys1 = keys(obj1);
-            var keys2 = keys(obj2);
-
-            if (isArguments(obj1) || isArguments(obj2)) {
-                if (obj1.length !== obj2.length) { return false; }
-            } else {
-                if (type1 !== type2 || class1 !== class2 ||
-                        keys1.length !== keys2.length) {
-                    return false;
-                }
-            }
-
-            var key, i, l,
-                // following vars are used for the cyclic logic
-                value1, value2,
-                isObject1, isObject2,
-                index1, index2,
-                newPath1, newPath2;
-
-            for (i = 0, l = keys1.length; i < l; i++) {
-                key = keys1[i];
-                if (!o.hasOwnProperty.call(obj2, key)) {
-                    return false;
-                }
-
-                // Start of the cyclic logic
-
-                value1 = obj1[key];
-                value2 = obj2[key];
-
-                isObject1 = isObject(value1);
-                isObject2 = isObject(value2);
-
-                // determine, if the objects were already visited
-                // (it's faster to check for isObject first, than to
-                // get -1 from getIndex for non objects)
-                index1 = isObject1 ? getIndex(objects1, value1) : -1;
-                index2 = isObject2 ? getIndex(objects2, value2) : -1;
-
-                // determine the new pathes of the objects
-                // - for non cyclic objects the current path will be extended
-                //   by current property name
-                // - for cyclic objects the stored path is taken
-                newPath1 = index1 !== -1
-                    ? paths1[index1]
-                    : path1 + '[' + JSON.stringify(key) + ']';
-                newPath2 = index2 !== -1
-                    ? paths2[index2]
-                    : path2 + '[' + JSON.stringify(key) + ']';
-
-                // stop recursion if current objects are already compared
-                if (compared[newPath1 + newPath2]) {
-                    return true;
-                }
-
-                // remember the current objects and their pathes
-                if (index1 === -1 && isObject1) {
-                    objects1.push(value1);
-                    paths1.push(newPath1);
-                }
-                if (index2 === -1 && isObject2) {
-                    objects2.push(value2);
-                    paths2.push(newPath2);
-                }
-
-                // remember that the current objects are already compared
-                if (isObject1 && isObject2) {
-                    compared[newPath1 + newPath2] = true;
-                }
-
-                // End of cyclic logic
-
-                // neither value1 nor value2 is a cycle
-                // continue with next level
-                if (!deepEqual(value1, value2, newPath1, newPath2)) {
-                    return false;
-                }
-            }
-
-            return true;
-
-        }(obj1, obj2, '$1', '$2'));
-    }
-
-    var match;
-
-    function arrayContains(array, subset) {
-        if (subset.length === 0) { return true; }
-        var i, l, j, k;
-        for (i = 0, l = array.length; i < l; ++i) {
-            if (match(array[i], subset[0])) {
-                for (j = 0, k = subset.length; j < k; ++j) {
-                    if (!match(array[i + j], subset[j])) { return false; }
-                }
-                return true;
-            }
-        }
-        return false;
-    }
-
-    /**
-     * @name samsam.match
-     * @param Object object
-     * @param Object matcher
-     *
-     * Compare arbitrary value ``object`` with matcher.
-     */
-    match = function match(object, matcher) {
-        if (matcher && typeof matcher.test === "function") {
-            return matcher.test(object);
-        }
-
-        if (typeof matcher === "function") {
-            return matcher(object) === true;
-        }
-
-        if (typeof matcher === "string") {
-            matcher = matcher.toLowerCase();
-            var notNull = typeof object === "string" || !!object;
-            return notNull &&
-                (String(object)).toLowerCase().indexOf(matcher) >= 0;
-        }
-
-        if (typeof matcher === "number") {
-            return matcher === object;
-        }
-
-        if (typeof matcher === "boolean") {
-            return matcher === object;
-        }
-
-        if (getClass(object) === "Array" && getClass(matcher) === "Array") {
-            return arrayContains(object, matcher);
-        }
-
-        if (matcher && typeof matcher === "object") {
-            var prop;
-            for (prop in matcher) {
-                if (!match(object[prop], matcher[prop])) {
-                    return false;
-                }
-            }
-            return true;
-        }
-
-        throw new Error("Matcher was not a string, a number, a " +
-                        "function, a boolean or an object");
-    };
-
-    return {
-        isArguments: isArguments,
-        isElement: isElement,
-        isDate: isDate,
-        isNegZero: isNegZero,
-        identical: identical,
-        deepEqual: deepEqualCyclic,
-        match: match,
-        keys: keys
-    };
-});
-((typeof define === "function" && define.amd && function (m) {
-    define("formatio", ["samsam"], m);
-}) || (typeof module === "object" && function (m) {
-    module.exports = m(require("samsam"));
-}) || function (m) { this.formatio = m(this.samsam); }
-)(function (samsam) {
-    
-    var formatio = {
-        excludeConstructors: ["Object", /^.$/],
-        quoteStrings: true
-    };
-
-    var hasOwn = Object.prototype.hasOwnProperty;
-
-    var specialObjects = [];
-    if (typeof global !== "undefined") {
-        specialObjects.push({ object: global, value: "[object global]" });
-    }
-    if (typeof document !== "undefined") {
-        specialObjects.push({
-            object: document,
-            value: "[object HTMLDocument]"
-        });
-    }
-    if (typeof window !== "undefined") {
-        specialObjects.push({ object: window, value: "[object Window]" });
-    }
-
-    function functionName(func) {
-        if (!func) { return ""; }
-        if (func.displayName) { return func.displayName; }
-        if (func.name) { return func.name; }
-        var matches = func.toString().match(/function\s+([^\(]+)/m);
-        return (matches && matches[1]) || "";
-    }
-
-    function constructorName(f, object) {
-        var name = functionName(object && object.constructor);
-        var excludes = f.excludeConstructors ||
-                formatio.excludeConstructors || [];
-
-        var i, l;
-        for (i = 0, l = excludes.length; i < l; ++i) {
-            if (typeof excludes[i] === "string" && excludes[i] === name) {
-                return "";
-            } else if (excludes[i].test && excludes[i].test(name)) {
-                return "";
-            }
-        }
-
-        return name;
-    }
-
-    function isCircular(object, objects) {
-        if (typeof object !== "object") { return false; }
-        var i, l;
-        for (i = 0, l = objects.length; i < l; ++i) {
-            if (objects[i] === object) { return true; }
-        }
-        return false;
-    }
-
-    function ascii(f, object, processed, indent) {
-        if (typeof object === "string") {
-            var qs = f.quoteStrings;
-            var quote = typeof qs !== "boolean" || qs;
-            return processed || quote ? '"' + object + '"' : object;
-        }
-
-        if (typeof object === "function" && !(object instanceof RegExp)) {
-            return ascii.func(object);
-        }
-
-        processed = processed || [];
-
-        if (isCircular(object, processed)) { return "[Circular]"; }
-
-        if (Object.prototype.toString.call(object) === "[object Array]") {
-            return ascii.array.call(f, object, processed);
-        }
-
-        if (!object) { return String((1/object) === -Infinity ? "-0" : object); }
-        if (samsam.isElement(object)) { return ascii.element(object); }
-
-        if (typeof object.toString === "function" &&
-                object.toString !== Object.prototype.toString) {
-            return object.toString();
-        }
-
-        var i, l;
-        for (i = 0, l = specialObjects.length; i < l; i++) {
-            if (object === specialObjects[i].object) {
-                return specialObjects[i].value;
-            }
-        }
-
-        return ascii.object.call(f, object, processed, indent);
-    }
-
-    ascii.func = function (func) {
-        return "function " + functionName(func) + "() {}";
-    };
-
-    ascii.array = function (array, processed) {
-        processed = processed || [];
-        processed.push(array);
-        var i, l, pieces = [];
-        for (i = 0, l = array.length; i < l; ++i) {
-            pieces.push(ascii(this, array[i], processed));
-        }
-        return "[" + pieces.join(", ") + "]";
-    };
-
-    ascii.object = function (object, processed, indent) {
-        processed = processed || [];
-        processed.push(object);
-        indent = indent || 0;
-        var pieces = [], properties = samsam.keys(object).sort();
-        var length = 3;
-        var prop, str, obj, i, l;
-
-        for (i = 0, l = properties.length; i < l; ++i) {
-            prop = properties[i];
-            obj = object[prop];
-
-            if (isCircular(obj, processed)) {
-                str = "[Circular]";
-            } else {
-                str = ascii(this, obj, processed, indent + 2);
-            }
-
-            str = (/\s/.test(prop) ? '"' + prop + '"' : prop) + ": " + str;
-            length += str.length;
-            pieces.push(str);
-        }
-
-        var cons = constructorName(this, object);
-        var prefix = cons ? "[" + cons + "] " : "";
-        var is = "";
-        for (i = 0, l = indent; i < l; ++i) { is += " "; }
-
-        if (length + indent > 80) {
-            return prefix + "{\n  " + is + pieces.join(",\n  " + is) + "\n" +
-                is + "}";
-        }
-        return prefix + "{ " + pieces.join(", ") + " }";
-    };
-
-    ascii.element = function (element) {
-        var tagName = element.tagName.toLowerCase();
-        var attrs = element.attributes, attr, pairs = [], attrName, i, l, val;
-
-        for (i = 0, l = attrs.length; i < l; ++i) {
-            attr = attrs.item(i);
-            attrName = attr.nodeName.toLowerCase().replace("html:", "");
-            val = attr.nodeValue;
-            if (attrName !== "contenteditable" || val !== "inherit") {
-                if (!!val) { pairs.push(attrName + "=\"" + val + "\""); }
-            }
-        }
-
-        var formatted = "<" + tagName + (pairs.length > 0 ? " " : "");
-        var content = element.innerHTML;
-
-        if (content.length > 20) {
-            content = content.substr(0, 20) + "[...]";
-        }
-
-        var res = formatted + pairs.join(" ") + ">" + content +
-                "</" + tagName + ">";
-
-        return res.replace(/ contentEditable="inherit"/, "");
-    };
-
-    function Formatio(options) {
-        for (var opt in options) {
-            this[opt] = options[opt];
-        }
-    }
-
-    Formatio.prototype = {
-        functionName: functionName,
-
-        configure: function (options) {
-            return new Formatio(options);
-        },
-
-        constructorName: function (object) {
-            return constructorName(this, object);
-        },
-
-        ascii: function (object, processed, indent) {
-            return ascii(this, object, processed, indent);
-        }
-    };
-
-    return Formatio.prototype;
-});
-/*jslint eqeqeq: false, onevar: false, forin: true, nomen: false, regexp: false, plusplus: false*/
-/*global module, require, __dirname, document*/
-/**
- * Sinon core utilities. For internal use only.
- *
- * @author Christian Johansen (christian@cjohansen.no)
- * @license BSD
- *
- * Copyright (c) 2010-2013 Christian Johansen
- */
-
-var sinon = (function (formatio) {
-    var div = typeof document != "undefined" && document.createElement("div");
-    var hasOwn = Object.prototype.hasOwnProperty;
-
-    function isDOMNode(obj) {
-        var success = false;
-
-        try {
-            obj.appendChild(div);
-            success = div.parentNode == obj;
-        } catch (e) {
-            return false;
-        } finally {
-            try {
-                obj.removeChild(div);
-            } catch (e) {
-                // Remove failed, not much we can do about that
-            }
-        }
-
-        return success;
-    }
-
-    function isElement(obj) {
-        return div && obj && obj.nodeType === 1 && isDOMNode(obj);
-    }
-
-    function isFunction(obj) {
-        return typeof obj === "function" || !!(obj && obj.constructor && obj.call && obj.apply);
-    }
-
-    function mirrorProperties(target, source) {
-        for (var prop in source) {
-            if (!hasOwn.call(target, prop)) {
-                target[prop] = source[prop];
-            }
-        }
-    }
-
-    function isRestorable (obj) {
-        return typeof obj === "function" && typeof obj.restore === "function" && obj.restore.sinon;
-    }
-
-    var sinon = {
-        wrapMethod: function wrapMethod(object, property, method) {
-            if (!object) {
-                throw new TypeError("Should wrap property of object");
-            }
-
-            if (typeof method != "function") {
-                throw new TypeError("Method wrapper should be function");
-            }
-
-            var wrappedMethod = object[property],
-                error;
-
-            if (!isFunction(wrappedMethod)) {
-                error = new TypeError("Attempted to wrap " + (typeof wrappedMethod) + " property " +
-                                    property + " as function");
-            }
-
-            if (wrappedMethod.restore && wrappedMethod.restore.sinon) {
-                error = new TypeError("Attempted to wrap " + property + " which is already wrapped");
-            }
-
-            if (wrappedMethod.calledBefore) {
-                var verb = !!wrappedMethod.returns ? "stubbed" : "spied on";
-                error = new TypeError("Attempted to wrap " + property + " which is already " + verb);
-            }
-
-            if (error) {
-                if (wrappedMethod._stack) {
-                    error.stack += '\n--------------\n' + wrappedMethod._stack;
-                }
-                throw error;
-            }
-
-            // IE 8 does not support hasOwnProperty on the window object and Firefox has a problem
-            // when using hasOwn.call on objects from other frames.
-            var owned = object.hasOwnProperty ? object.hasOwnProperty(property) : hasOwn.call(object, property);
-            object[property] = method;
-            method.displayName = property;
-            // Set up a stack trace which can be used later to find what line of
-            // code the original method was created on.
-            method._stack = (new Error('Stack Trace for original')).stack;
-
-            method.restore = function () {
-                // For prototype properties try to reset by delete first.
-                // If this fails (ex: localStorage on mobile safari) then force a reset
-                // via direct assignment.
-                if (!owned) {
-                    delete object[property];
-                }
-                if (object[property] === method) {
-                    object[property] = wrappedMethod;
-                }
-            };
-
-            method.restore.sinon = true;
-            mirrorProperties(method, wrappedMethod);
-
-            return method;
-        },
-
-        extend: function extend(target) {
-            for (var i = 1, l = arguments.length; i < l; i += 1) {
-                for (var prop in arguments[i]) {
-                    if (arguments[i].hasOwnProperty(prop)) {
-                        target[prop] = arguments[i][prop];
-                    }
-
-                    // DONT ENUM bug, only care about toString
-                    if (arguments[i].hasOwnProperty("toString") &&
-                        arguments[i].toString != target.toString) {
-                        target.toString = arguments[i].toString;
-                    }
-                }
-            }
-
-            return target;
-        },
-
-        create: function create(proto) {
-            var F = function () {};
-            F.prototype = proto;
-            return new F();
-        },
-
-        deepEqual: function deepEqual(a, b) {
-            if (sinon.match && sinon.match.isMatcher(a)) {
-                return a.test(b);
-            }
-            if (typeof a != "object" || typeof b != "object") {
-                return a === b;
-            }
-
-            if (isElement(a) || isElement(b)) {
-                return a === b;
-            }
-
-            if (a === b) {
-                return true;
-            }
-
-            if ((a === null && b !== null) || (a !== null && b === null)) {
-                return false;
-            }
-
-            var aString = Object.prototype.toString.call(a);
-            if (aString != Object.prototype.toString.call(b)) {
-                return false;
-            }
-
-            if (aString == "[object Date]") {
-                return a.valueOf() === b.valueOf();
-            }
-
-            var prop, aLength = 0, bLength = 0;
-
-            if (aString == "[object Array]" && a.length !== b.length) {
-                return false;
-            }
-
-            for (prop in a) {
-                aLength += 1;
-
-                if (!deepEqual(a[prop], b[prop])) {
-                    return false;
-                }
-            }
-
-            for (prop in b) {
-                bLength += 1;
-            }
-
-            return aLength == bLength;
-        },
-
-        functionName: function functionName(func) {
-            var name = func.displayName || func.name;
-
-            // Use function decomposition as a last resort to get function
-            // name. Does not rely on function decomposition to work - if it
-            // doesn't debugging will be slightly less informative
-            // (i.e. toString will say 'spy' rather than 'myFunc').
-            if (!name) {
-                var matches = func.toString().match(/function ([^\s\(]+)/);
-                name = matches && matches[1];
-            }
-
-            return name;
-        },
-
-        functionToString: function toString() {
-            if (this.getCall && this.callCount) {
-                var thisValue, prop, i = this.callCount;
-
-                while (i--) {
-                    thisValue = this.getCall(i).thisValue;
-
-                    for (prop in thisValue) {
-                        if (thisValue[prop] === this) {
-                            return prop;
-                        }
-                    }
-                }
-            }
-
-            return this.displayName || "sinon fake";
-        },
-
-        getConfig: function (custom) {
-            var config = {};
-            custom = custom || {};
-            var defaults = sinon.defaultConfig;
-
-            for (var prop in defaults) {
-                if (defaults.hasOwnProperty(prop)) {
-                    config[prop] = custom.hasOwnProperty(prop) ? custom[prop] : defaults[prop];
-                }
-            }
-
-            return config;
-        },
-
-        format: function (val) {
-            return "" + val;
-        },
-
-        defaultConfig: {
-            injectIntoThis: true,
-            injectInto: null,
-            properties: ["spy", "stub", "mock", "clock", "server", "requests"],
-            useFakeTimers: true,
-            useFakeServer: true
-        },
-
-        timesInWords: function timesInWords(count) {
-            return count == 1 && "once" ||
-                count == 2 && "twice" ||
-                count == 3 && "thrice" ||
-                (count || 0) + " times";
-        },
-
-        calledInOrder: function (spies) {
-            for (var i = 1, l = spies.length; i < l; i++) {
-                if (!spies[i - 1].calledBefore(spies[i]) || !spies[i].called) {
-                    return false;
-                }
-            }
-
-            return true;
-        },
-
-        orderByFirstCall: function (spies) {
-            return spies.sort(function (a, b) {
-                // uuid, won't ever be equal
-                var aCall = a.getCall(0);
-                var bCall = b.getCall(0);
-                var aId = aCall && aCall.callId || -1;
-                var bId = bCall && bCall.callId || -1;
-
-                return aId < bId ? -1 : 1;
-            });
-        },
-
-        log: function () {},
-
-        logError: function (label, err) {
-            var msg = label + " threw exception: ";
-            sinon.log(msg + "[" + err.name + "] " + err.message);
-            if (err.stack) { sinon.log(err.stack); }
-
-            setTimeout(function () {
-                err.message = msg + err.message;
-                throw err;
-            }, 0);
-        },
-
-        typeOf: function (value) {
-            if (value === null) {
-                return "null";
-            }
-            else if (value === undefined) {
-                return "undefined";
-            }
-            var string = Object.prototype.toString.call(value);
-            return string.substring(8, string.length - 1).toLowerCase();
-        },
-
-        createStubInstance: function (constructor) {
-            if (typeof constructor !== "function") {
-                throw new TypeError("The constructor should be a function.");
-            }
-            return sinon.stub(sinon.create(constructor.prototype));
-        },
-
-        restore: function (object) {
-            if (object !== null && typeof object === "object") {
-                for (var prop in object) {
-                    if (isRestorable(object[prop])) {
-                        object[prop].restore();
-                    }
-                }
-            }
-            else if (isRestorable(object)) {
-                object.restore();
-            }
-        }
-    };
-
-    var isNode = typeof module !== "undefined" && module.exports;
-    var isAMD = typeof define === 'function' && typeof define.amd === 'object' && define.amd;
-
-    if (isAMD) {
-        define(function(){
-            return sinon;
-        });
-    } else if (isNode) {
-        try {
-            formatio = require("formatio");
-        } catch (e) {}
-        module.exports = sinon;
-        module.exports.spy = require("./sinon/spy");
-        module.exports.spyCall = require("./sinon/call");
-        module.exports.behavior = require("./sinon/behavior");
-        module.exports.stub = require("./sinon/stub");
-        module.exports.mock = require("./sinon/mock");
-        module.exports.collection = require("./sinon/collection");
-        module.exports.assert = require("./sinon/assert");
-        module.exports.sandbox = require("./sinon/sandbox");
-        module.exports.test = require("./sinon/test");
-        module.exports.testCase = require("./sinon/test_case");
-        module.exports.assert = require("./sinon/assert");
-        module.exports.match = require("./sinon/match");
-    }
-
-    if (formatio) {
-        var formatter = formatio.configure({ quoteStrings: false });
-        sinon.format = function () {
-            return formatter.ascii.apply(formatter, arguments);
-        };
-    } else if (isNode) {
-        try {
-            var util = require("util");
-            sinon.format = function (value) {
-                return typeof value == "object" && value.toString === Object.prototype.toString ? util.inspect(value) : value;
-            };
-        } catch (e) {
-            /* Node, but no util module - would be very old, but better safe than
-             sorry */
-        }
-    }
-
-    return sinon;
-}(typeof formatio == "object" && formatio));
-
-/* @depend ../sinon.js */
-/*jslint eqeqeq: false, onevar: false, plusplus: false*/
-/*global module, require, sinon*/
-/**
- * Match functions
- *
- * @author Maximilian Antoni (mail@maxantoni.de)
- * @license BSD
- *
- * Copyright (c) 2012 Maximilian Antoni
- */
-
-(function (sinon) {
-    var commonJSModule = typeof module !== 'undefined' && module.exports;
-
-    if (!sinon && commonJSModule) {
-        sinon = require("../sinon");
-    }
-
-    if (!sinon) {
-        return;
-    }
-
-    function assertType(value, type, name) {
-        var actual = sinon.typeOf(value);
-        if (actual !== type) {
-            throw new TypeError("Expected type of " + name + " to be " +
-                type + ", but was " + actual);
-        }
-    }
-
-    var matcher = {
-        toString: function () {
-            return this.message;
-        }
-    };
-
-    function isMatcher(object) {
-        return matcher.isPrototypeOf(object);
-    }
-
-    function matchObject(expectation, actual) {
-        if (actual === null || actual === undefined) {
-            return false;
-        }
-        for (var key in expectation) {
-            if (expectation.hasOwnProperty(key)) {
-                var exp = expectation[key];
-                var act = actual[key];
-                if (match.isMatcher(exp)) {
-                    if (!exp.test(act)) {
-                        return false;
-                    }
-                } else if (sinon.typeOf(exp) === "object") {
-                    if (!matchObject(exp, act)) {
-                        return false;
-                    }
-                } else if (!sinon.deepEqual(exp, act)) {
-                    return false;
-                }
-            }
-        }
-        return true;
-    }
-
-    matcher.or = function (m2) {
-        if (!isMatcher(m2)) {
-            throw new TypeError("Matcher expected");
-        }
-        var m1 = this;
-        var or = sinon.create(matcher);
-        or.test = function (actual) {
-            return m1.test(actual) || m2.test(actual);
-        };
-        or.message = m1.message + ".or(" + m2.message + ")";
-        return or;
-    };
-
-    matcher.and = function (m2) {
-        if (!isMatcher(m2)) {
-            throw new TypeError("Matcher expected");
-        }
-        var m1 = this;
-        var and = sinon.create(matcher);
-        and.test = function (actual) {
-            return m1.test(actual) && m2.test(actual);
-        };
-        and.message = m1.message + ".and(" + m2.message + ")";
-        return and;
-    };
-
-    var match = function (expectation, message) {
-        var m = sinon.create(matcher);
-        var type = sinon.typeOf(expectation);
-        switch (type) {
-        case "object":
-            if (typeof expectation.test === "function") {
-                m.test = function (actual) {
-                    return expectation.test(actual) === true;
-                };
-                m.message = "match(" + sinon.functionName(expectation.test) + ")";
-                return m;
-            }
-            var str = [];
-            for (var key in expectation) {
-                if (expectation.hasOwnProperty(key)) {
-                    str.push(key + ": " + expectation[key]);
-                }
-            }
-            m.test = function (actual) {
-                return matchObject(expectation, actual);
-            };
-            m.message = "match(" + str.join(", ") + ")";
-            break;
-        case "number":
-            m.test = function (actual) {
-                return expectation == actual;
-            };
-            break;
-        case "string":
-            m.test = function (actual) {
-                if (typeof actual !== "string") {
-                    return false;
-                }
-                return actual.indexOf(expectation) !== -1;
-            };
-            m.message = "match(\"" + expectation + "\")";
-            break;
-        case "regexp":
-            m.test = function (actual) {
-                if (typeof actual !== "string") {
-                    return false;
-                }
-                return expectation.test(actual);
-            };
-            break;
-        case "function":
-            m.test = expectation;
-            if (message) {
-                m.message = message;
-            } else {
-                m.message = "match(" + sinon.functionName(expectation) + ")";
-            }
-            break;
-        default:
-            m.test = function (actual) {
-              return sinon.deepEqual(expectation, actual);
-            };
-        }
-        if (!m.message) {
-            m.message = "match(" + expectation + ")";
-        }
-        return m;
-    };
-
-    match.isMatcher = isMatcher;
-
-    match.any = match(function () {
-        return true;
-    }, "any");
-
-    match.defined = match(function (actual) {
-        return actual !== null && actual !== undefined;
-    }, "defined");
-
-    match.truthy = match(function (actual) {
-        return !!actual;
-    }, "truthy");
-
-    match.falsy = match(function (actual) {
-        return !actual;
-    }, "falsy");
-
-    match.same = function (expectation) {
-        return match(function (actual) {
-            return expectation === actual;
-        }, "same(" + expectation + ")");
-    };
-
-    match.typeOf = function (type) {
-        assertType(type, "string", "type");
-        return match(function (actual) {
-            return sinon.typeOf(actual) === type;
-        }, "typeOf(\"" + type + "\")");
-    };
-
-    match.instanceOf = function (type) {
-        assertType(type, "function", "type");
-        return match(function (actual) {
-            return actual instanceof type;
-        }, "instanceOf(" + sinon.functionName(type) + ")");
-    };
-
-    function createPropertyMatcher(propertyTest, messagePrefix) {
-        return function (property, value) {
-            assertType(property, "string", "property");
-            var onlyProperty = arguments.length === 1;
-            var message = messagePrefix + "(\"" + property + "\"";
-            if (!onlyProperty) {
-                message += ", " + value;
-            }
-            message += ")";
-            return match(function (actual) {
-                if (actual === undefined || actual === null ||
-                        !propertyTest(actual, property)) {
-                    return false;
-                }
-                return onlyProperty || sinon.deepEqual(value, actual[property]);
-            }, message);
-        };
-    }
-
-    match.has = createPropertyMatcher(function (actual, property) {
-        if (typeof actual === "object") {
-            return property in actual;
-        }
-        return actual[property] !== undefined;
-    }, "has");
-
-    match.hasOwn = createPropertyMatcher(function (actual, property) {
-        return actual.hasOwnProperty(property);
-    }, "hasOwn");
-
-    match.bool = match.typeOf("boolean");
-    match.number = match.typeOf("number");
-    match.string = match.typeOf("string");
-    match.object = match.typeOf("object");
-    match.func = match.typeOf("function");
-    match.array = match.typeOf("array");
-    match.regexp = match.typeOf("regexp");
-    match.date = match.typeOf("date");
-
-    if (commonJSModule) {
-        module.exports = match;
-    } else {
-        sinon.match = match;
-    }
-}(typeof sinon == "object" && sinon || null));
-
-/**
-  * @depend ../sinon.js
-  * @depend match.js
-  */
-/*jslint eqeqeq: false, onevar: false, plusplus: false*/
-/*global module, require, sinon*/
-/**
-  * Spy calls
-  *
-  * @author Christian Johansen (christian@cjohansen.no)
-  * @author Maximilian Antoni (mail@maxantoni.de)
-  * @license BSD
-  *
-  * Copyright (c) 2010-2013 Christian Johansen
-  * Copyright (c) 2013 Maximilian Antoni
-  */
-
-(function (sinon) {
-    var commonJSModule = typeof module !== 'undefined' && module.exports;
-    if (!sinon && commonJSModule) {
-        sinon = require("../sinon");
-    }
-
-    if (!sinon) {
-        return;
-    }
-
-    function throwYieldError(proxy, text, args) {
-        var msg = sinon.functionName(proxy) + text;
-        if (args.length) {
-            msg += " Received [" + slice.call(args).join(", ") + "]";
-        }
-        throw new Error(msg);
-    }
-
-    var slice = Array.prototype.slice;
-
-    var callProto = {
-        calledOn: function calledOn(thisValue) {
-            if (sinon.match && sinon.match.isMatcher(thisValue)) {
-                return thisValue.test(this.thisValue);
-            }
-            return this.thisValue === thisValue;
-        },
-
-        calledWith: function calledWith() {
-            for (var i = 0, l = arguments.length; i < l; i += 1) {
-                if (!sinon.deepEqual(arguments[i], this.args[i])) {
-                    return false;
-                }
-            }
-
-            return true;
-        },
-
-        calledWithMatch: function calledWithMatch() {
-            for (var i = 0, l = arguments.length; i < l; i += 1) {
-                var actual = this.args[i];
-                var expectation = arguments[i];
-                if (!sinon.match || !sinon.match(expectation).test(actual)) {
-                    return false;
-                }
-            }
-            return true;
-        },
-
-        calledWithExactly: function calledWithExactly() {
-            return arguments.length == this.args.length &&
-                this.calledWith.apply(this, arguments);
-        },
-
-        notCalledWith: function notCalledWith() {
-            return !this.calledWith.apply(this, arguments);
-        },
-
-        notCalledWithMatch: function notCalledWithMatch() {
-            return !this.calledWithMatch.apply(this, arguments);
-        },
-
-        returned: function returned(value) {
-            return sinon.deepEqual(value, this.returnValue);
-        },
-
-        threw: function threw(error) {
-            if (typeof error === "undefined" || !this.exception) {
-                return !!this.exception;
-            }
-
-            return this.exception === error || this.exception.name === error;
-        },
-
-        calledWithNew: function calledWithNew() {
-            return this.thisValue instanceof this.proxy;
-        },
-
-        calledBefore: function (other) {
-            return this.callId < other.callId;
-        },
-
-        calledAfter: function (other) {
-            return this.callId > other.callId;
-        },
-
-        callArg: function (pos) {
-            this.args[pos]();
-        },
-
-        callArgOn: function (pos, thisValue) {
-            this.args[pos].apply(thisValue);
-        },
-
-        callArgWith: function (pos) {
-            this.callArgOnWith.apply(this, [pos, null].concat(slice.call(arguments, 1)));
-        },
-
-        callArgOnWith: function (pos, thisValue) {
-            var args = slice.call(arguments, 2);
-            this.args[pos].apply(thisValue, args);
-        },
-
-        "yield": function () {
-            this.yieldOn.apply(this, [null].concat(slice.call(arguments, 0)));
-        },
-
-        yieldOn: function (thisValue) {
-            var args = this.args;
-            for (var i = 0, l = args.length; i < l; ++i) {
-                if (typeof args[i] === "function") {
-                    args[i].apply(thisValue, slice.call(arguments, 1));
-                    return;
-                }
-            }
-            throwYieldError(this.proxy, " cannot yield since no callback was passed.", args);
-        },
-
-        yieldTo: function (prop) {
-            this.yieldToOn.apply(this, [prop, null].concat(slice.call(arguments, 1)));
-        },
-
-        yieldToOn: function (prop, thisValue) {
-            var args = this.args;
-            for (var i = 0, l = args.length; i < l; ++i) {
-                if (args[i] && typeof args[i][prop] === "function") {
-                    args[i][prop].apply(thisValue, slice.call(arguments, 2));
-                    return;
-                }
-            }
-            throwYieldError(this.proxy, " cannot yield to '" + prop +
-                "' since no callback was passed.", args);
-        },
-
-        toString: function () {
-            var callStr = this.proxy.toString() + "(";
-            var args = [];
-
-            for (var i = 0, l = this.args.length; i < l; ++i) {
-                args.push(sinon.format(this.args[i]));
-            }
-
-            callStr = callStr + args.join(", ") + ")";
-
-            if (typeof this.returnValue != "undefined") {
-                callStr += " => " + sinon.format(this.returnValue);
-            }
-
-            if (this.exception) {
-                callStr += " !" + this.exception.name;
-
-                if (this.exception.message) {
-                    callStr += "(" + this.exception.message + ")";
-                }
-            }
-
-            return callStr;
-        }
-    };
-
-    callProto.invokeCallback = callProto.yield;
-
-    function createSpyCall(spy, thisValue, args, returnValue, exception, id) {
-        if (typeof id !== "number") {
-            throw new TypeError("Call id is not a number");
-        }
-        var proxyCall = sinon.create(callProto);
-        proxyCall.proxy = spy;
-        proxyCall.thisValue = thisValue;
-        proxyCall.args = args;
-        proxyCall.returnValue = returnValue;
-        proxyCall.exception = exception;
-        proxyCall.callId = id;
-
-        return proxyCall;
-    }
-    createSpyCall.toString = callProto.toString; // used by mocks
-
-    if (commonJSModule) {
-        module.exports = createSpyCall;
-    } else {
-        sinon.spyCall = createSpyCall;
-    }
-}(typeof sinon == "object" && sinon || null));
-
-
-/**
-  * @depend ../sinon.js
-  * @depend call.js
-  */
-/*jslint eqeqeq: false, onevar: false, plusplus: false*/
-/*global module, require, sinon*/
-/**
-  * Spy functions
-  *
-  * @author Christian Johansen (christian@cjohansen.no)
-  * @license BSD
-  *
-  * Copyright (c) 2010-2013 Christian Johansen
-  */
-
-(function (sinon) {
-    var commonJSModule = typeof module !== 'undefined' && module.exports;
-    var push = Array.prototype.push;
-    var slice = Array.prototype.slice;
-    var callId = 0;
-
-    if (!sinon && commonJSModule) {
-        sinon = require("../sinon");
-    }
-
-    if (!sinon) {
-        return;
-    }
-
-    function spy(object, property) {
-        if (!property && typeof object == "function") {
-            return spy.create(object);
-        }
-
-        if (!object && !property) {
-            return spy.create(function () { });
-        }
-
-        var method = object[property];
-        return sinon.wrapMethod(object, property, spy.create(method));
-    }
-
-    function matchingFake(fakes, args, strict) {
-        if (!fakes) {
-            return;
-        }
-
-        for (var i = 0, l = fakes.length; i < l; i++) {
-            if (fakes[i].matches(args, strict)) {
-                return fakes[i];
-            }
-        }
-    }
-
-    function incrementCallCount() {
-        this.called = true;
-        this.callCount += 1;
-        this.notCalled = false;
-        this.calledOnce = this.callCount == 1;
-        this.calledTwice = this.callCount == 2;
-        this.calledThrice = this.callCount == 3;
-    }
-
-    function createCallProperties() {
-        this.firstCall = this.getCall(0);
-        this.secondCall = this.getCall(1);
-        this.thirdCall = this.getCall(2);
-        this.lastCall = this.getCall(this.callCount - 1);
-    }
-
-    var vars = "a,b,c,d,e,f,g,h,i,j,k,l";
-    function createProxy(func) {
-        // Retain the function length:
-        var p;
-        if (func.length) {
-            eval("p = (function proxy(" + vars.substring(0, func.length * 2 - 1) +
-                ") { return p.invoke(func, this, slice.call(arguments)); });");
-        }
-        else {
-            p = function proxy() {
-                return p.invoke(func, this, slice.call(arguments));
-            };
-        }
-        return p;
-    }
-
-    var uuid = 0;
-
-    // Public API
-    var spyApi = {
-        reset: function () {
-            this.called = false;
-            this.notCalled = true;
-            this.calledOnce = false;
-            this.calledTwice = false;
-            this.calledThrice = false;
-            this.callCount = 0;
-            this.firstCall = null;
-            this.secondCall = null;
-            this.thirdCall = null;
-            this.lastCall = null;
-            this.args = [];
-            this.returnValues = [];
-            this.thisValues = [];
-            this.exceptions = [];
-            this.callIds = [];
-            if (this.fakes) {
-                for (var i = 0; i < this.fakes.length; i++) {
-                    this.fakes[i].reset();
-                }
-            }
-        },
-
-        create: function create(func) {
-            var name;
-
-            if (typeof func != "function") {
-                func = function () { };
-            } else {
-                name = sinon.functionName(func);
-            }
-
-            var proxy = createProxy(func);
-
-            sinon.extend(proxy, spy);
-            delete proxy.create;
-            sinon.extend(proxy, func);
-
-            proxy.reset();
-            proxy.prototype = func.prototype;
-            proxy.displayName = name || "spy";
-            proxy.toString = sinon.functionToString;
-            proxy._create = sinon.spy.create;
-            proxy.id = "spy#" + uuid++;
-
-            return proxy;
-        },
-
-        invoke: function invoke(func, thisValue, args) {
-            var matching = matchingFake(this.fakes, args);
-            var exception, returnValue;
-
-            incrementCallCount.call(this);
-            push.call(this.thisValues, thisValue);
-            push.call(this.args, args);
-            push.call(this.callIds, callId++);
-
-            try {
-                if (matching) {
-                    returnValue = matching.invoke(func, thisValue, args);
-                } else {
-                    returnValue = (this.func || func).apply(thisValue, args);
-                }
-
-                var thisCall = this.getCall(this.callCount - 1);
-                if (thisCall.calledWithNew() && typeof returnValue !== 'object') {
-                    returnValue = thisValue;
-                }
-            } catch (e) {
-                exception = e;
-            }
-
-            push.call(this.exceptions, exception);
-            push.call(this.returnValues, returnValue);
-
-            createCallProperties.call(this);
-
-            if (exception !== undefined) {
-                throw exception;
-            }
-
-            return returnValue;
-        },
-
-        getCall: function getCall(i) {
-            if (i < 0 || i >= this.callCount) {
-                return null;
-            }
-
-            return sinon.spyCall(this, this.thisValues[i], this.args[i],
-                                    this.returnValues[i], this.exceptions[i],
-                                    this.callIds[i]);
-        },
-
-        getCalls: function () {
-            var calls = [];
-            var i;
-
-            for (i = 0; i < this.callCount; i++) {
-                calls.push(this.getCall(i));
-            }
-
-            return calls;
-        },
-
-        calledBefore: function calledBefore(spyFn) {
-            if (!this.called) {
-                return false;
-            }
-
-            if (!spyFn.called) {
-                return true;
-            }
-
-            return this.callIds[0] < spyFn.callIds[spyFn.callIds.length - 1];
-        },
-
-        calledAfter: function calledAfter(spyFn) {
-            if (!this.called || !spyFn.called) {
-                return false;
-            }
-
-            return this.callIds[this.callCount - 1] > spyFn.callIds[spyFn.callCount - 1];
-        },
-
-        withArgs: function () {
-            var args = slice.call(arguments);
-
-            if (this.fakes) {
-                var match = matchingFake(this.fakes, args, true);
-
-                if (match) {
-                    return match;
-                }
-            } else {
-                this.fakes = [];
-            }
-
-            var original = this;
-            var fake = this._create();
-            fake.matchingAguments = args;
-            fake.parent = this;
-            push.call(this.fakes, fake);
-
-            fake.withArgs = function () {
-                return original.withArgs.apply(original, arguments);
-            };
-
-            for (var i = 0; i < this.args.length; i++) {
-                if (fake.matches(this.args[i])) {
-                    incrementCallCount.call(fake);
-                    push.call(fake.thisValues, this.thisValues[i]);
-                    push.call(fake.args, this.args[i]);
-                    push.call(fake.returnValues, this.returnValues[i]);
-                    push.call(fake.exceptions, this.exceptions[i]);
-                    push.call(fake.callIds, this.callIds[i]);
-                }
-            }
-            createCallProperties.call(fake);
-
-            return fake;
-        },
-
-        matches: function (args, strict) {
-            var margs = this.matchingAguments;
-
-            if (margs.length <= args.length &&
-                sinon.deepEqual(margs, args.slice(0, margs.length))) {
-                return !strict || margs.length == args.length;
-            }
-        },
-
-        printf: function (format) {
-            var spy = this;
-            var args = slice.call(arguments, 1);
-            var formatter;
-
-            return (format || "").replace(/%(.)/g, function (match, specifyer) {
-                formatter = spyApi.formatters[specifyer];
-
-                if (typeof formatter == "function") {
-                    return formatter.call(null, spy, args);
-                } else if (!isNaN(parseInt(specifyer, 10))) {
-                    return sinon.format(args[specifyer - 1]);
-                }
-
-                return "%" + specifyer;
-            });
-        }
-    };
-
-    function delegateToCalls(method, matchAny, actual, notCalled) {
-        spyApi[method] = function () {
-            if (!this.called) {
-                if (notCalled) {
-                    return notCalled.apply(this, arguments);
-                }
-                return false;
-            }
-
-            var currentCall;
-            var matches = 0;
-
-            for (var i = 0, l = this.callCount; i < l; i += 1) {
-                currentCall = this.getCall(i);
-
-                if (currentCall[actual || method].apply(currentCall, arguments)) {
-                    matches += 1;
-
-                    if (matchAny) {
-                        return true;
-                    }
-                }
-            }
-
-            return matches === this.callCount;
-        };
-    }
-
-    delegateToCalls("calledOn", true);
-    delegateToCalls("alwaysCalledOn", false, "calledOn");
-    delegateToCalls("calledWith", true);
-    delegateToCalls("calledWithMatch", true);
-    delegateToCalls("alwaysCalledWith", false, "calledWith");
-    delegateToCalls("alwaysCalledWithMatch", false, "calledWithMatch");
-    delegateToCalls("calledWithExactly", true);
-    delegateToCalls("alwaysCalledWithExactly", false, "calledWithExactly");
-    delegateToCalls("neverCalledWith", false, "notCalledWith",
-        function () { return true; });
-    delegateToCalls("neverCalledWithMatch", false, "notCalledWithMatch",
-        function () { return true; });
-    delegateToCalls("threw", true);
-    delegateToCalls("alwaysThrew", false, "threw");
-    delegateToCalls("returned", true);
-    delegateToCalls("alwaysReturned", false, "returned");
-    delegateToCalls("calledWithNew", true);
-    delegateToCalls("alwaysCalledWithNew", false, "calledWithNew");
-    delegateToCalls("callArg", false, "callArgWith", function () {
-        throw new Error(this.toString() + " cannot call arg since it was not yet invoked.");
-    });
-    spyApi.callArgWith = spyApi.callArg;
-    delegateToCalls("callArgOn", false, "callArgOnWith", function () {
-        throw new Error(this.toString() + " cannot call arg since it was not yet invoked.");
-    });
-    spyApi.callArgOnWith = spyApi.callArgOn;
-    delegateToCalls("yield", false, "yield", function () {
-        throw new Error(this.toString() + " cannot yield since it was not yet invoked.");
-    });
-    // "invokeCallback" is an alias for "yield" since "yield" is invalid in strict mode.
-    spyApi.invokeCallback = spyApi.yield;
-    delegateToCalls("yieldOn", false, "yieldOn", function () {
-        throw new Error(this.toString() + " cannot yield since it was not yet invoked.");
-    });
-    delegateToCalls("yieldTo", false, "yieldTo", function (property) {
-        throw new Error(this.toString() + " cannot yield to '" + property +
-            "' since it was not yet invoked.");
-    });
-    delegateToCalls("yieldToOn", false, "yieldToOn", function (property) {
-        throw new Error(this.toString() + " cannot yield to '" + property +
-            "' since it was not yet invoked.");
-    });
-
-    spyApi.formatters = {
-        "c": function (spy) {
-            return sinon.timesInWords(spy.callCount);
-        },
-
-        "n": function (spy) {
-            return spy.toString();
-        },
-
-        "C": function (spy) {
-            var calls = [];
-
-            for (var i = 0, l = spy.callCount; i < l; ++i) {
-                var stringifiedCall = "    " + spy.getCall(i).toString();
-                if (/\n/.test(calls[i - 1])) {
-                    stringifiedCall = "\n" + stringifiedCall;
-                }
-                push.call(calls, stringifiedCall);
-            }
-
-            return calls.length > 0 ? "\n" + calls.join("\n") : "";
-        },
-
-        "t": function (spy) {
-            var objects = [];
-
-            for (var i = 0, l = spy.callCount; i < l; ++i) {
-                push.call(objects, sinon.format(spy.thisValues[i]));
-            }
-
-            return objects.join(", ");
-        },
-
-        "*": function (spy, args) {
-            var formatted = [];
-
-            for (var i = 0, l = args.length; i < l; ++i) {
-                push.call(formatted, sinon.format(args[i]));
-            }
-
-            return formatted.join(", ");
-        }
-    };
-
-    sinon.extend(spy, spyApi);
-
-    spy.spyCall = sinon.spyCall;
-
-    if (commonJSModule) {
-        module.exports = spy;
-    } else {
-        sinon.spy = spy;
-    }
-}(typeof sinon == "object" && sinon || null));
-
-/**
- * @depend ../sinon.js
- */
-/*jslint eqeqeq: false, onevar: false*/
-/*global module, require, sinon, process, setImmediate, setTimeout*/
-/**
- * Stub behavior
- *
- * @author Christian Johansen (christian@cjohansen.no)
- * @author Tim Fischbach (mail@timfischbach.de)
- * @license BSD
- *
- * Copyright (c) 2010-2013 Christian Johansen
- */
-
-(function (sinon) {
-    var commonJSModule = typeof module !== 'undefined' && module.exports;
-
-    if (!sinon && commonJSModule) {
-        sinon = require("../sinon");
-    }
-
-    if (!sinon) {
-        return;
-    }
-
-    var slice = Array.prototype.slice;
-    var join = Array.prototype.join;
-    var proto;
-
-    var nextTick = (function () {
-        if (typeof process === "object" && typeof process.nextTick === "function") {
-            return process.nextTick;
-        } else if (typeof setImmediate === "function") {
-            return setImmediate;
-        } else {
-            return function (callback) {
-                setTimeout(callback, 0);
-            };
-        }
-    })();
-
-    function throwsException(error, message) {
-        if (typeof error == "string") {
-            this.exception = new Error(message || "");
-            this.exception.name = error;
-        } else if (!error) {
-            this.exception = new Error("Error");
-        } else {
-            this.exception = error;
-        }
-
-        return this;
-    }
-
-    function getCallback(behavior, args) {
-        var callArgAt = behavior.callArgAt;
-
-        if (callArgAt < 0) {
-            var callArgProp = behavior.callArgProp;
-
-            for (var i = 0, l = args.length; i < l; ++i) {
-                if (!callArgProp && typeof args[i] == "function") {
-                    return args[i];
-                }
-
-                if (callArgProp && args[i] &&
-                    typeof args[i][callArgProp] == "function") {
-                    return args[i][callArgProp];
-                }
-            }
-
-            return null;
-        }
-
-        return args[callArgAt];
-    }
-
-    function getCallbackError(behavior, func, args) {
-        if (behavior.callArgAt < 0) {
-            var msg;
-
-            if (behavior.callArgProp) {
-                msg = sinon.functionName(behavior.stub) +
-                    " expected to yield to '" + behavior.callArgProp +
-                    "', but no object with such a property was passed.";
-            } else {
-                msg = sinon.functionName(behavior.stub) +
-                    " expected to yield, but no callback was passed.";
-            }
-
-            if (args.length > 0) {
-                msg += " Received [" + join.call(args, ", ") + "]";
-            }
-
-            return msg;
-        }
-
-        return "argument at index " + behavior.callArgAt + " is not a function: " + func;
-    }
-
-    function callCallback(behavior, args) {
-        if (typeof behavior.callArgAt == "number") {
-            var func = getCallback(behavior, args);
-
-            if (typeof func != "function") {
-                throw new TypeError(getCallbackError(behavior, func, args));
-            }
-
-            if (behavior.callbackAsync) {
-                nextTick(function() {
-                    func.apply(behavior.callbackContext, behavior.callbackArguments);
-                });
-            } else {
-                func.apply(behavior.callbackContext, behavior.callbackArguments);
-            }
-        }
-    }
-
-    proto = {
-        create: function(stub) {
-            var behavior = sinon.extend({}, sinon.behavior);
-            delete behavior.create;
-            behavior.stub = stub;
-
-            return behavior;
-        },
-
-        isPresent: function() {
-            return (typeof this.callArgAt == 'number' ||
-                    this.exception ||
-                    typeof this.returnArgAt == 'number' ||
-                    this.returnThis ||
-                    this.returnValueDefined);
-        },
-
-        invoke: function(context, args) {
-            callCallback(this, args);
-
-            if (this.exception) {
-                throw this.exception;
-            } else if (typeof this.returnArgAt == 'number') {
-                return args[this.returnArgAt];
-            } else if (this.returnThis) {
-                return context;
-            }
-
-            return this.returnValue;
-        },
-
-        onCall: function(index) {
-            return this.stub.onCall(index);
-        },
-
-        onFirstCall: function() {
-            return this.stub.onFirstCall();
-        },
-
-        onSecondCall: function() {
-            return this.stub.onSecondCall();
-        },
-
-        onThirdCall: function() {
-            return this.stub.onThirdCall();
-        },
-
-        withArgs: function(/* arguments */) {
-            throw new Error('Defining a stub by invoking "stub.onCall(...).withArgs(...)" is not supported. ' +
-                            'Use "stub.withArgs(...).onCall(...)" to define sequential behavior for calls with certain arguments.');
-        },
-
-        callsArg: function callsArg(pos) {
-            if (typeof pos != "number") {
-                throw new TypeError("argument index is not number");
-            }
-
-            this.callArgAt = pos;
-            this.callbackArguments = [];
-            this.callbackContext = undefined;
-            this.callArgProp = undefined;
-            this.callbackAsync = false;
-
-            return this;
-        },
-
-        callsArgOn: function callsArgOn(pos, context) {
-            if (typeof pos != "number") {
-                throw new TypeError("argument index is not number");
-            }
-            if (typeof context != "object") {
-                throw new TypeError("argument context is not an object");
-            }
-
-            this.callArgAt = pos;
-            this.callbackArguments = [];
-            this.callbackContext = context;
-            this.callArgProp = undefined;
-            this.callbackAsync = false;
-
-            return this;
-        },
-
-        callsArgWith: function callsArgWith(pos) {
-            if (typeof pos != "number") {
-                throw new TypeError("argument index is not number");
-            }
-
-            this.callArgAt = pos;
-            this.callbackArguments = slice.call(arguments, 1);
-            this.callbackContext = undefined;
-            this.callArgProp = undefined;
-            this.callbackAsync = false;
-
-            return this;
-        },
-
-        callsArgOnWith: function callsArgWith(pos, context) {
-            if (typeof pos != "number") {
-                throw new TypeError("argument index is not number");
-            }
-            if (typeof context != "object") {
-                throw new TypeError("argument context is not an object");
-            }
-
-            this.callArgAt = pos;
-            this.callbackArguments = slice.call(arguments, 2);
-            this.callbackContext = context;
-            this.callArgProp = undefined;
-            this.callbackAsync = false;
-
-            return this;
-        },
-
-        yields: function () {
-            this.callArgAt = -1;
-            this.callbackArguments = slice.call(arguments, 0);
-            this.callbackContext = undefined;
-            this.callArgProp = undefined;
-            this.callbackAsync = false;
-
-            return this;
-        },
-
-        yieldsOn: function (context) {
-            if (typeof context != "object") {
-                throw new TypeError("argument context is not an object");
-            }
-
-            this.callArgAt = -1;
-            this.callbackArguments = slice.call(arguments, 1);
-            this.callbackContext = context;
-            this.callArgProp = undefined;
-            this.callbackAsync = false;
-
-            return this;
-        },
-
-        yieldsTo: function (prop) {
-            this.callArgAt = -1;
-            this.callbackArguments = slice.call(arguments, 1);
-            this.callbackContext = undefined;
-            this.callArgProp = prop;
-            this.callbackAsync = false;
-
-            return this;
-        },
-
-        yieldsToOn: function (prop, context) {
-            if (typeof context != "object") {
-                throw new TypeError("argument context is not an object");
-            }
-
-            this.callArgAt = -1;
-            this.callbackArguments = slice.call(arguments, 2);
-            this.callbackContext = context;
-            this.callArgProp = prop;
-            this.callbackAsync = false;
-
-            return this;
-        },
-
-
-        "throws": throwsException,
-        throwsException: throwsException,
-
-        returns: function returns(value) {
-            this.returnValue = value;
-            this.returnValueDefined = true;
-
-            return this;
-        },
-
-        returnsArg: function returnsArg(pos) {
-            if (typeof pos != "number") {
-                throw new TypeError("argument index is not number");
-            }
-
-            this.returnArgAt = pos;
-
-            return this;
-        },
-
-        returnsThis: function returnsThis() {
-            this.returnThis = true;
-
-            return this;
-        }
-    };
-
-    // create asynchronous versions of callsArg* and yields* methods
-    for (var method in proto) {
-        // need to avoid creating anotherasync versions of the newly added async methods
-        if (proto.hasOwnProperty(method) &&
-            method.match(/^(callsArg|yields)/) &&
-            !method.match(/Async/)) {
-            proto[method + 'Async'] = (function (syncFnName) {
-                return function () {
-                    var result = this[syncFnName].apply(this, arguments);
-                    this.callbackAsync = true;
-                    return result;
-                };
-            })(method);
-        }
-    }
-
-    if (commonJSModule) {
-        module.exports = proto;
-    } else {
-        sinon.behavior = proto;
-    }
-}(typeof sinon == "object" && sinon || null));
-/**
- * @depend ../sinon.js
- * @depend spy.js
- * @depend behavior.js
- */
-/*jslint eqeqeq: false, onevar: false*/
-/*global module, require, sinon*/
-/**
- * Stub functions
- *
- * @author Christian Johansen (christian@cjohansen.no)
- * @license BSD
- *
- * Copyright (c) 2010-2013 Christian Johansen
- */
-
-(function (sinon) {
-    var commonJSModule = typeof module !== 'undefined' && module.exports;
-
-    if (!sinon && commonJSModule) {
-        sinon = require("../sinon");
-    }
-
-    if (!sinon) {
-        return;
-    }
-
-    function stub(object, property, func) {
-        if (!!func && typeof func != "function") {
-            throw new TypeError("Custom stub should be function");
-        }
-
-        var wrapper;
-
-        if (func) {
-            wrapper = sinon.spy && sinon.spy.create ? sinon.spy.create(func) : func;
-        } else {
-            wrapper = stub.create();
-        }
-
-        if (!object && typeof property === "undefined") {
-            return sinon.stub.create();
-        }
-
-        if (typeof property === "undefined" && typeof object == "object") {
-            for (var prop in object) {
-                if (typeof object[prop] === "function") {
-                    stub(object, prop);
-                }
-            }
-
-            return object;
-        }
-
-        return sinon.wrapMethod(object, property, wrapper);
-    }
-
-    function getDefaultBehavior(stub) {
-        return stub.defaultBehavior || getParentBehaviour(stub) || sinon.behavior.create(stub);
-    }
-
-    function getParentBehaviour(stub) {
-        return (stub.parent && getCurrentBehavior(stub.parent));
-    }
-
-    function getCurrentBehavior(stub) {
-        var behavior = stub.behaviors[stub.callCount - 1];
-        return behavior && behavior.isPresent() ? behavior : getDefaultBehavior(stub);
-    }
-
-    var uuid = 0;
-
-    sinon.extend(stub, (function () {
-        var proto = {
-            create: function create() {
-                var functionStub = function () {
-                    return getCurrentBehavior(functionStub).invoke(this, arguments);
-                };
-
-                functionStub.id = "stub#" + uuid++;
-                var orig = functionStub;
-                functionStub = sinon.spy.create(functionStub);
-                functionStub.func = orig;
-
-                sinon.extend(functionStub, stub);
-                functionStub._create = sinon.stub.create;
-                functionStub.displayName = "stub";
-                functionStub.toString = sinon.functionToString;
-
-                functionStub.defaultBehavior = null;
-                functionStub.behaviors = [];
-
-                return functionStub;
-            },
-
-            resetBehavior: function () {
-                var i;
-
-                this.defaultBehavior = null;
-                this.behaviors = [];
-
-                delete this.returnValue;
-                delete this.returnArgAt;
-                this.returnThis = false;
-
-                if (this.fakes) {
-                    for (i = 0; i < this.fakes.length; i++) {
-                        this.fakes[i].resetBehavior();
-                    }
-                }
-            },
-
-            onCall: function(index) {
-                if (!this.behaviors[index]) {
-                    this.behaviors[index] = sinon.behavior.create(this);
-                }
-
-                return this.behaviors[index];
-            },
-
-            onFirstCall: function() {
-                return this.onCall(0);
-            },
-
-            onSecondCall: function() {
-                return this.onCall(1);
-            },
-
-            onThirdCall: function() {
-                return this.onCall(2);
-            }
-        };
-
-        for (var method in sinon.behavior) {
-            if (sinon.behavior.hasOwnProperty(method) &&
-                !proto.hasOwnProperty(method) &&
-                method != 'create' &&
-                method != 'withArgs' &&
-                method != 'invoke') {
-                proto[method] = (function(behaviorMethod) {
-                    return function() {
-                        this.defaultBehavior = this.defaultBehavior || sinon.behavior.create(this);
-                        this.defaultBehavior[behaviorMethod].apply(this.defaultBehavior, arguments);
-                        return this;
-                    };
-                }(method));
-            }
-        }
-
-        return proto;
-    }()));
-
-    if (commonJSModule) {
-        module.exports = stub;
-    } else {
-        sinon.stub = stub;
-    }
-}(typeof sinon == "object" && sinon || null));
-
-/**
- * @depend ../sinon.js
- * @depend stub.js
- */
-/*jslint eqeqeq: false, onevar: false, nomen: false*/
-/*global module, require, sinon*/
-/**
- * Mock functions.
- *
- * @author Christian Johansen (christian@cjohansen.no)
- * @license BSD
- *
- * Copyright (c) 2010-2013 Christian Johansen
- */
-
-(function (sinon) {
-    var commonJSModule = typeof module !== 'undefined' && module.exports;
-    var push = [].push;
-    var match;
-
-    if (!sinon && commonJSModule) {
-        sinon = require("../sinon");
-    }
-
-    if (!sinon) {
-        return;
-    }
-
-    match = sinon.match;
-
-    if (!match && commonJSModule) {
-        match = require("./match");
-    }
-
-    function mock(object) {
-        if (!object) {
-            return sinon.expectation.create("Anonymous mock");
-        }
-
-        return mock.create(object);
-    }
-
-    sinon.mock = mock;
-
-    sinon.extend(mock, (function () {
-        function each(collection, callback) {
-            if (!collection) {
-                return;
-            }
-
-            for (var i = 0, l = collection.length; i < l; i += 1) {
-                callback(collection[i]);
-            }
-        }
-
-        return {
-            create: function create(object) {
-                if (!object) {
-                    throw new TypeError("object is null");
-                }
-
-                var mockObject = sinon.extend({}, mock);
-                mockObject.object = object;
-                delete mockObject.create;
-
-                return mockObject;
-            },
-
-            expects: function expects(method) {
-                if (!method) {
-                    throw new TypeError("method is falsy");
-                }
-
-                if (!this.expectations) {
-                    this.expectations = {};
-                    this.proxies = [];
-                }
-
-                if (!this.expectations[method]) {
-                    this.expectations[method] = [];
-                    var mockObject = this;
-
-                    sinon.wrapMethod(this.object, method, function () {
-                        return mockObject.invokeMethod(method, this, arguments);
-                    });
-
-                    push.call(this.proxies, method);
-                }
-
-                var expectation = sinon.expectation.create(method);
-                push.call(this.expectations[method], expectation);
-
-                return expectation;
-            },
-
-            restore: function restore() {
-                var object = this.object;
-
-                each(this.proxies, function (proxy) {
-                    if (typeof object[proxy].restore == "function") {
-                        object[proxy].restore();
-                    }
-                });
-            },
-
-            verify: function verify() {
-                var expectations = this.expectations || {};
-                var messages = [], met = [];
-
-                each(this.proxies, function (proxy) {
-                    each(expectations[proxy], function (expectation) {
-                        if (!expectation.met()) {
-                            push.call(messages, expectation.toString());
-                        } else {
-                            push.call(met, expectation.toString());
-                        }
-                    });
-                });
-
-                this.restore();
-
-                if (messages.length > 0) {
-                    sinon.expectation.fail(messages.concat(met).join("\n"));
-                } else {
-                    sinon.expectation.pass(messages.concat(met).join("\n"));
-                }
-
-                return true;
-            },
-
-            invokeMethod: function invokeMethod(method, thisValue, args) {
-                var expectations = this.expectations && this.expectations[method];
-                var length = expectations && expectations.length || 0, i;
-
-                for (i = 0; i < length; i += 1) {
-                    if (!expectations[i].met() &&
-                        expectations[i].allowsCall(thisValue, args)) {
-                        return expectations[i].apply(thisValue, args);
-                    }
-                }
-
-                var messages = [], available, exhausted = 0;
-
-                for (i = 0; i < length; i += 1) {
-                    if (expectations[i].allowsCall(thisValue, args)) {
-                        available = available || expectations[i];
-                    } else {
-                        exhausted += 1;
-                    }
-                    push.call(messages, "    " + expectations[i].toString());
-                }
-
-                if (exhausted === 0) {
-                    return available.apply(thisValue, args);
-                }
-
-                messages.unshift("Unexpected call: " + sinon.spyCall.toString.call({
-                    proxy: method,
-                    args: args
-                }));
-
-                sinon.expectation.fail(messages.join("\n"));
-            }
-        };
-    }()));
-
-    var times = sinon.timesInWords;
-
-    sinon.expectation = (function () {
-        var slice = Array.prototype.slice;
-        var _invoke = sinon.spy.invoke;
-
-        function callCountInWords(callCount) {
-            if (callCount == 0) {
-                return "never called";
-            } else {
-                return "called " + times(callCount);
-            }
-        }
-
-        function expectedCallCountInWords(expectation) {
-            var min = expectation.minCalls;
-            var max = expectation.maxCalls;
-
-            if (typeof min == "number" && typeof max == "number") {
-                var str = times(min);
-
-                if (min != max) {
-                    str = "at least " + str + " and at most " + times(max);
-                }
-
-                return str;
-            }
-
-            if (typeof min == "number") {
-                return "at least " + times(min);
-            }
-
-            return "at most " + times(max);
-        }
-
-        function receivedMinCalls(expectation) {
-            var hasMinLimit = typeof expectation.minCalls == "number";
-            return !hasMinLimit || expectation.callCount >= expectation.minCalls;
-        }
-
-        function receivedMaxCalls(expectation) {
-            if (typeof expectation.maxCalls != "number") {
-                return false;
-            }
-
-            return expectation.callCount == expectation.maxCalls;
-        }
-
-        function verifyMatcher(possibleMatcher, arg){
-            if (match && match.isMatcher(possibleMatcher)) {
-                return possibleMatcher.test(arg);
-            } else {
-                return true;
-            }
-        }
-
-        return {
-            minCalls: 1,
-            maxCalls: 1,
-
-            create: function create(methodName) {
-                var expectation = sinon.extend(sinon.stub.create(), sinon.expectation);
-                delete expectation.create;
-                expectation.method = methodName;
-
-                return expectation;
-            },
-
-            invoke: function invoke(func, thisValue, args) {
-                this.verifyCallAllowed(thisValue, args);
-
-                return _invoke.apply(this, arguments);
-            },
-
-            atLeast: function atLeast(num) {
-                if (typeof num != "number") {
-                    throw new TypeError("'" + num + "' is not number");
-                }
-
-                if (!this.limitsSet) {
-                    this.maxCalls = null;
-                    this.limitsSet = true;
-                }
-
-                this.minCalls = num;
-
-                return this;
-            },
-
-            atMost: function atMost(num) {
-                if (typeof num != "number") {
-                    throw new TypeError("'" + num + "' is not number");
-                }
-
-                if (!this.limitsSet) {
-                    this.minCalls = null;
-                    this.limitsSet = true;
-                }
-
-                this.maxCalls = num;
-
-                return this;
-            },
-
-            never: function never() {
-                return this.exactly(0);
-            },
-
-            once: function once() {
-                return this.exactly(1);
-            },
-
-            twice: function twice() {
-                return this.exactly(2);
-            },
-
-            thrice: function thrice() {
-                return this.exactly(3);
-            },
-
-            exactly: function exactly(num) {
-                if (typeof num != "number") {
-                    throw new TypeError("'" + num + "' is not a number");
-                }
-
-                this.atLeast(num);
-                return this.atMost(num);
-            },
-
-            met: function met() {
-                return !this.failed && receivedMinCalls(this);
-            },
-
-            verifyCallAllowed: function verifyCallAllowed(thisValue, args) {
-                if (receivedMaxCalls(this)) {
-                    this.failed = true;
-                    sinon.expectation.fail(this.method + " already called " + times(this.maxCalls));
-                }
-
-                if ("expectedThis" in this && this.expectedThis !== thisValue) {
-                    sinon.expectation.fail(this.method + " called with " + thisValue + " as thisValue, expected " +
-                        this.expectedThis);
-                }
-
-                if (!("expectedArguments" in this)) {
-                    return;
-                }
-
-                if (!args) {
-                    sinon.expectation.fail(this.method + " received no arguments, expected " +
-                        sinon.format(this.expectedArguments));
-                }
-
-                if (args.length < this.expectedArguments.length) {
-                    sinon.expectation.fail(this.method + " received too few arguments (" + sinon.format(args) +
-                        "), expected " + sinon.format(this.expectedArguments));
-                }
-
-                if (this.expectsExactArgCount &&
-                    args.length != this.expectedArguments.length) {
-                    sinon.expectation.fail(this.method + " received too many arguments (" + sinon.format(args) +
-                        "), expected " + sinon.format(this.expectedArguments));
-                }
-
-                for (var i = 0, l = this.expectedArguments.length; i < l; i += 1) {
-
-                    if (!verifyMatcher(this.expectedArguments[i],args[i])) {
-                        sinon.expectation.fail(this.method + " received wrong arguments " + sinon.format(args) +
-                            ", didn't match " + this.expectedArguments.toString());
-                    }
-
-                    if (!sinon.deepEqual(this.expectedArguments[i], args[i])) {
-                        sinon.expectation.fail(this.method + " received wrong arguments " + sinon.format(args) +
-                            ", expected " + sinon.format(this.expectedArguments));
-                    }
-                }
-            },
-
-            allowsCall: function allowsCall(thisValue, args) {
-                if (this.met() && receivedMaxCalls(this)) {
-                    return false;
-                }
-
-                if ("expectedThis" in this && this.expectedThis !== thisValue) {
-                    return false;
-                }
-
-                if (!("expectedArguments" in this)) {
-                    return true;
-                }
-
-                args = args || [];
-
-                if (args.length < this.expectedArguments.length) {
-                    return false;
-                }
-
-                if (this.expectsExactArgCount &&
-                    args.length != this.expectedArguments.length) {
-                    return false;
-                }
-
-                for (var i = 0, l = this.expectedArguments.length; i < l; i += 1) {
-                    if (!verifyMatcher(this.expectedArguments[i],args[i])) {
-                        return false;
-                    }
-
-                    if (!sinon.deepEqual(this.expectedArguments[i], args[i])) {
-                        return false;
-                    }
-                }
-
-                return true;
-            },
-
-            withArgs: function withArgs() {
-                this.expectedArguments = slice.call(arguments);
-                return this;
-            },
-
-            withExactArgs: function withExactArgs() {
-                this.withArgs.apply(this, arguments);
-                this.expectsExactArgCount = true;
-                return this;
-            },
-
-            on: function on(thisValue) {
-                this.expectedThis = thisValue;
-                return this;
-            },
-
-            toString: function () {
-                var args = (this.expectedArguments || []).slice();
-
-                if (!this.expectsExactArgCount) {
-                    push.call(args, "[...]");
-                }
-
-                var callStr = sinon.spyCall.toString.call({
-                    proxy: this.method || "anonymous mock expectation",
-                    args: args
-                });
-
-                var message = callStr.replace(", [...", "[, ...") + " " +
-                    expectedCallCountInWords(this);
-
-                if (this.met()) {
-                    return "Expectation met: " + message;
-                }
-
-                return "Expected " + message + " (" +
-                    callCountInWords(this.callCount) + ")";
-            },
-
-            verify: function verify() {
-                if (!this.met()) {
-                    sinon.expectation.fail(this.toString());
-                } else {
-                    sinon.expectation.pass(this.toString());
-                }
-
-                return true;
-            },
-
-            pass: function(message) {
-              sinon.assert.pass(message);
-            },
-            fail: function (message) {
-                var exception = new Error(message);
-                exception.name = "ExpectationError";
-
-                throw exception;
-            }
-        };
-    }());
-
-    if (commonJSModule) {
-        module.exports = mock;
-    } else {
-        sinon.mock = mock;
-    }
-}(typeof sinon == "object" && sinon || null));
-
-/**
- * @depend ../sinon.js
- * @depend stub.js
- * @depend mock.js
- */
-/*jslint eqeqeq: false, onevar: false, forin: true*/
-/*global module, require, sinon*/
-/**
- * Collections of stubs, spies and mocks.
- *
- * @author Christian Johansen (christian@cjohansen.no)
- * @license BSD
- *
- * Copyright (c) 2010-2013 Christian Johansen
- */
-
-(function (sinon) {
-    var commonJSModule = typeof module !== 'undefined' && module.exports;
-    var push = [].push;
-    var hasOwnProperty = Object.prototype.hasOwnProperty;
-
-    if (!sinon && commonJSModule) {
-        sinon = require("../sinon");
-    }
-
-    if (!sinon) {
-        return;
-    }
-
-    function getFakes(fakeCollection) {
-        if (!fakeCollection.fakes) {
-            fakeCollection.fakes = [];
-        }
-
-        return fakeCollection.fakes;
-    }
-
-    function each(fakeCollection, method) {
-        var fakes = getFakes(fakeCollection);
-
-        for (var i = 0, l = fakes.length; i < l; i += 1) {
-            if (typeof fakes[i][method] == "function") {
-                fakes[i][method]();
-            }
-        }
-    }
-
-    function compact(fakeCollection) {
-        var fakes = getFakes(fakeCollection);
-        var i = 0;
-        while (i < fakes.length) {
-          fakes.splice(i, 1);
-        }
-    }
-
-    var collection = {
-        verify: function resolve() {
-            each(this, "verify");
-        },
-
-        restore: function restore() {
-            each(this, "restore");
-            compact(this);
-        },
-
-        verifyAndRestore: function verifyAndRestore() {
-            var exception;
-
-            try {
-                this.verify();
-            } catch (e) {
-                exception = e;
-            }
-
-            this.restore();
-
-            if (exception) {
-                throw exception;
-            }
-        },
-
-        add: function add(fake) {
-            push.call(getFakes(this), fake);
-            return fake;
-        },
-
-        spy: function spy() {
-            return this.add(sinon.spy.apply(sinon, arguments));
-        },
-
-        stub: function stub(object, property, value) {
-            if (property) {
-                var original = object[property];
-
-                if (typeof original != "function") {
-                    if (!hasOwnProperty.call(object, property)) {
-                        throw new TypeError("Cannot stub non-existent own property " + property);
-                    }
-
-                    object[property] = value;
-
-                    return this.add({
-                        restore: function () {
-                            object[property] = original;
-                        }
-                    });
-                }
-            }
-            if (!property && !!object && typeof object == "object") {
-                var stubbedObj = sinon.stub.apply(sinon, arguments);
-
-                for (var prop in stubbedObj) {
-                    if (typeof stubbedObj[prop] === "function") {
-                        this.add(stubbedObj[prop]);
-                    }
-                }
-
-                return stubbedObj;
-            }
-
-            return this.add(sinon.stub.apply(sinon, arguments));
-        },
-
-        mock: function mock() {
-            return this.add(sinon.mock.apply(sinon, arguments));
-        },
-
-        inject: function inject(obj) {
-            var col = this;
-
-            obj.spy = function () {
-                return col.spy.apply(col, arguments);
-            };
-
-            obj.stub = function () {
-                return col.stub.apply(col, arguments);
-            };
-
-            obj.mock = function () {
-                return col.mock.apply(col, arguments);
-            };
-
-            return obj;
-        }
-    };
-
-    if (commonJSModule) {
-        module.exports = collection;
-    } else {
-        sinon.collection = collection;
-    }
-}(typeof sinon == "object" && sinon || null));
-
-/*jslint eqeqeq: false, plusplus: false, evil: true, onevar: false, browser: true, forin: false*/
-/*global module, require, window*/
-/**
- * Fake timer API
- * setTimeout
- * setInterval
- * clearTimeout
- * clearInterval
- * tick
- * reset
- * Date
- *
- * Inspired by jsUnitMockTimeOut from JsUnit
- *
- * @author Christian Johansen (christian@cjohansen.no)
- * @license BSD
- *
- * Copyright (c) 2010-2013 Christian Johansen
- */
-
-if (typeof sinon == "undefined") {
-    var sinon = {};
-}
-
-(function (global) {
-    var id = 1;
-
-    function addTimer(args, recurring) {
-        if (args.length === 0) {
-            throw new Error("Function requires at least 1 parameter");
-        }
-
-        if (typeof args[0] === "undefined") {
-            throw new Error("Callback must be provided to timer calls");
-        }
-
-        var toId = id++;
-        var delay = args[1] || 0;
-
-        if (!this.timeouts) {
-            this.timeouts = {};
-        }
-
-        this.timeouts[toId] = {
-            id: toId,
-            func: args[0],
-            callAt: this.now + delay,
-            invokeArgs: Array.prototype.slice.call(args, 2)
-        };
-
-        if (recurring === true) {
-            this.timeouts[toId].interval = delay;
-        }
-
-        return toId;
-    }
-
-    function parseTime(str) {
-        if (!str) {
-            return 0;
-        }
-
-        var strings = str.split(":");
-        var l = strings.length, i = l;
-        var ms = 0, parsed;
-
-        if (l > 3 || !/^(\d\d:){0,2}\d\d?$/.test(str)) {
-            throw new Error("tick only understands numbers and 'h:m:s'");
-        }
-
-        while (i--) {
-            parsed = parseInt(strings[i], 10);
-
-            if (parsed >= 60) {
-                throw new Error("Invalid time " + str);
-            }
-
-            ms += parsed * Math.pow(60, (l - i - 1));
-        }
-
-        return ms * 1000;
-    }
-
-    function createObject(object) {
-        var newObject;
-
-        if (Object.create) {
-            newObject = Object.create(object);
-        } else {
-            var F = function () {};
-            F.prototype = object;
-            newObject = new F();
-        }
-
-        newObject.Date.clock = newObject;
-        return newObject;
-    }
-
-    sinon.clock = {
-        now: 0,
-
-        create: function create(now) {
-            var clock = createObject(this);
-
-            if (typeof now == "number") {
-                clock.now = now;
-            }
-
-            if (!!now && typeof now == "object") {
-                throw new TypeError("now should be milliseconds since UNIX epoch");
-            }
-
-            return clock;
-        },
-
-        setTimeout: function setTimeout(callback, timeout) {
-            return addTimer.call(this, arguments, false);
-        },
-
-        clearTimeout: function clearTimeout(timerId) {
-            if (!this.timeouts) {
-                this.timeouts = [];
-            }
-
-            if (timerId in this.timeouts) {
-                delete this.timeouts[timerId];
-            }
-        },
-
-        setInterval: function setInterval(callback, timeout) {
-            return addTimer.call(this, arguments, true);
-        },
-
-        clearInterval: function clearInterval(timerId) {
-            this.clearTimeout(timerId);
-        },
-
-        setImmediate: function setImmediate(callback) {
-            var passThruArgs = Array.prototype.slice.call(arguments, 1);
-
-            return addTimer.call(this, [callback, 0].concat(passThruArgs), false);
-        },
-
-        clearImmediate: function clearImmediate(timerId) {
-            this.clearTimeout(timerId);
-        },
-
-        tick: function tick(ms) {
-            ms = typeof ms == "number" ? ms : parseTime(ms);
-            var tickFrom = this.now, tickTo = this.now + ms, previous = this.now;
-            var timer = this.firstTimerInRange(tickFrom, tickTo);
-
-            var firstException;
-            while (timer && tickFrom <= tickTo) {
-                if (this.timeouts[timer.id]) {
-                    tickFrom = this.now = timer.callAt;
-                    try {
-                      this.callTimer(timer);
-                    } catch (e) {
-                      firstException = firstException || e;
-                    }
-                }
-
-                timer = this.firstTimerInRange(previous, tickTo);
-                previous = tickFrom;
-            }
-
-            this.now = tickTo;
-
-            if (firstException) {
-              throw firstException;
-            }
-
-            return this.now;
-        },
-
-        firstTimerInRange: function (from, to) {
-            var timer, smallest = null, originalTimer;
-
-            for (var id in this.timeouts) {
-                if (this.timeouts.hasOwnProperty(id)) {
-                    if (this.timeouts[id].callAt < from || this.timeouts[id].callAt > to) {
-                        continue;
-                    }
-
-                    if (smallest === null || this.timeouts[id].callAt < smallest) {
-                        originalTimer = this.timeouts[id];
-                        smallest = this.timeouts[id].callAt;
-
-                        timer = {
-                            func: this.timeouts[id].func,
-                            callAt: this.timeouts[id].callAt,
-                            interval: this.timeouts[id].interval,
-                            id: this.timeouts[id].id,
-                            invokeArgs: this.timeouts[id].invokeArgs
-                        };
-                    }
-                }
-            }
-
-            return timer || null;
-        },
-
-        callTimer: function (timer) {
-            if (typeof timer.interval == "number") {
-                this.timeouts[timer.id].callAt += timer.interval;
-            } else {
-                delete this.timeouts[timer.id];
-            }
-
-            try {
-                if (typeof timer.func == "function") {
-                    timer.func.apply(null, timer.invokeArgs);
-                } else {
-                    eval(timer.func);
-                }
-            } catch (e) {
-              var exception = e;
-            }
-
-            if (!this.timeouts[timer.id]) {
-                if (exception) {
-                  throw exception;
-                }
-                return;
-            }
-
-            if (exception) {
-              throw exception;
-            }
-        },
-
-        reset: function reset() {
-            this.timeouts = {};
-        },
-
-        Date: (function () {
-            var NativeDate = Date;
-
-            function ClockDate(year, month, date, hour, minute, second, ms) {
-                // Defensive and verbose to avoid potential harm in passing
-                // explicit undefined when user does not pass argument
-                switch (arguments.length) {
-                case 0:
-                    return new NativeDate(ClockDate.clock.now);
-                case 1:
-                    return new NativeDate(year);
-                case 2:
-                    return new NativeDate(year, month);
-                case 3:
-                    return new NativeDate(year, month, date);
-                case 4:
-                    return new NativeDate(year, month, date, hour);
-                case 5:
-                    return new NativeDate(year, month, date, hour, minute);
-                case 6:
-                    return new NativeDate(year, month, date, hour, minute, second);
-                default:
-                    return new NativeDate(year, month, date, hour, minute, second, ms);
-                }
-            }
-
-            return mirrorDateProperties(ClockDate, NativeDate);
-        }())
-    };
-
-    function mirrorDateProperties(target, source) {
-        if (source.now) {
-            target.now = function now() {
-                return target.clock.now;
-            };
-        } else {
-            delete target.now;
-        }
-
-        if (source.toSource) {
-            target.toSource = function toSource() {
-                return source.toSource();
-            };
-        } else {
-            delete target.toSource;
-        }
-
-        target.toString = function toString() {
-            return source.toString();
-        };
-
-        target.prototype = source.prototype;
-        target.parse = source.parse;
-        target.UTC = source.UTC;
-        target.prototype.toUTCString = source.prototype.toUTCString;
-
-        for (var prop in source) {
-            if (source.hasOwnProperty(prop)) {
-                target[prop] = source[prop];
-            }
-        }
-
-        return target;
-    }
-
-    var methods = ["Date", "setTimeout", "setInterval",
-                   "clearTimeout", "clearInterval"];
-
-    if (typeof global.setImmediate !== "undefined") {
-        methods.push("setImmediate");
-    }
-
-    if (typeof global.clearImmediate !== "undefined") {
-        methods.push("clearImmediate");
-    }
-
-    function restore() {
-        var method;
-
-        for (var i = 0, l = this.methods.length; i < l; i++) {
-            method = this.methods[i];
-
-            if (global[method].hadOwnProperty) {
-                global[method] = this["_" + method];
-            } else {
-                try {
-                    delete global[method];
-                } catch (e) {}
-            }
-        }
-
-        // Prevent multiple executions which will completely remove these props
-        this.methods = [];
-    }
-
-    function stubGlobal(method, clock) {
-        clock[method].hadOwnProperty = Object.prototype.hasOwnProperty.call(global, method);
-        clock["_" + method] = global[method];
-
-        if (method == "Date") {
-            var date = mirrorDateProperties(clock[method], global[method]);
-            global[method] = date;
-        } else {
-            global[method] = function () {
-                return clock[method].apply(clock, arguments);
-            };
-
-            for (var prop in clock[method]) {
-                if (clock[method].hasOwnProperty(prop)) {
-                    global[method][prop] = clock[method][prop];
-                }
-            }
-        }
-
-        global[method].clock = clock;
-    }
-
-    sinon.useFakeTimers = function useFakeTimers(now) {
-        var clock = sinon.clock.create(now);
-        clock.restore = restore;
-        clock.methods = Array.prototype.slice.call(arguments,
-                                                   typeof now == "number" ? 1 : 0);
-
-        if (clock.methods.length === 0) {
-            clock.methods = methods;
-        }
-
-        for (var i = 0, l = clock.methods.length; i < l; i++) {
-            stubGlobal(clock.methods[i], clock);
-        }
-
-        return clock;
-    };
-}(typeof global != "undefined" && typeof global !== "function" ? global : this));
-
-sinon.timers = {
-    setTimeout: setTimeout,
-    clearTimeout: clearTimeout,
-    setImmediate: (typeof setImmediate !== "undefined" ? setImmediate : undefined),
-    clearImmediate: (typeof clearImmediate !== "undefined" ? clearImmediate: undefined),
-    setInterval: setInterval,
-    clearInterval: clearInterval,
-    Date: Date
-};
-
-if (typeof module !== 'undefined' && module.exports) {
-    module.exports = sinon;
-}
-
-/*jslint eqeqeq: false, onevar: false*/
-/*global sinon, module, require, ActiveXObject, XMLHttpRequest, DOMParser*/
-/**
- * Minimal Event interface implementation
- *
- * Original implementation by Sven Fuchs: https://gist.github.com/995028
- * Modifications and tests by Christian Johansen.
- *
- * @author Sven Fuchs (svenfuchs@artweb-design.de)
- * @author Christian Johansen (christian@cjohansen.no)
- * @license BSD
- *
- * Copyright (c) 2011 Sven Fuchs, Christian Johansen
- */
-
-if (typeof sinon == "undefined") {
-    this.sinon = {};
-}
-
-(function () {
-    var push = [].push;
-
-    sinon.Event = function Event(type, bubbles, cancelable, target) {
-        this.initEvent(type, bubbles, cancelable, target);
-    };
-
-    sinon.Event.prototype = {
-        initEvent: function(type, bubbles, cancelable, target) {
-            this.type = type;
-            this.bubbles = bubbles;
-            this.cancelable = cancelable;
-            this.target = target;
-        },
-
-        stopPropagation: function () {},
-
-        preventDefault: function () {
-            this.defaultPrevented = true;
-        }
-    };
-
-    sinon.EventTarget = {
-        addEventListener: function addEventListener(event, listener) {
-            this.eventListeners = this.eventListeners || {};
-            this.eventListeners[event] = this.eventListeners[event] || [];
-            push.call(this.eventListeners[event], listener);
-        },
-
-        removeEventListener: function removeEventListener(event, listener) {
-            var listeners = this.eventListeners && this.eventListeners[event] || [];
-
-            for (var i = 0, l = listeners.length; i < l; ++i) {
-                if (listeners[i] == listener) {
-                    return listeners.splice(i, 1);
-                }
-            }
-        },
-
-        dispatchEvent: function dispatchEvent(event) {
-            var type = event.type;
-            var listeners = this.eventListeners && this.eventListeners[type] || [];
-
-            for (var i = 0; i < listeners.length; i++) {
-                if (typeof listeners[i] == "function") {
-                    listeners[i].call(this, event);
-                } else {
-                    listeners[i].handleEvent(event);
-                }
-            }
-
-            return !!event.defaultPrevented;
-        }
-    };
-}());
-
-/**
- * @depend ../../sinon.js
- * @depend event.js
- */
-/*jslint eqeqeq: false, onevar: false*/
-/*global sinon, module, require, ActiveXObject, XMLHttpRequest, DOMParser*/
-/**
- * Fake XMLHttpRequest object
- *
- * @author Christian Johansen (christian@cjohansen.no)
- * @license BSD
- *
- * Copyright (c) 2010-2013 Christian Johansen
- */
-
-// wrapper for global
-(function(global) {
-
-    if (typeof sinon === "undefined") {
-        global.sinon = {};
-    }
-    sinon.xhr = { XMLHttpRequest: global.XMLHttpRequest };
-
-    var xhr = sinon.xhr;
-    xhr.GlobalXMLHttpRequest = global.XMLHttpRequest;
-    xhr.GlobalActiveXObject = global.ActiveXObject;
-    xhr.supportsActiveX = typeof xhr.GlobalActiveXObject != "undefined";
-    xhr.supportsXHR = typeof xhr.GlobalXMLHttpRequest != "undefined";
-    xhr.workingXHR = xhr.supportsXHR ? xhr.GlobalXMLHttpRequest : xhr.supportsActiveX
-                                     ? function() { return new xhr.GlobalActiveXObject("MSXML2.XMLHTTP.3.0") } : false;
-    xhr.supportsCORS = 'withCredentials' in (new sinon.xhr.GlobalXMLHttpRequest());
-
-    /*jsl:ignore*/
-    var unsafeHeaders = {
-        "Accept-Charset": true,
-        "Accept-Encoding": true,
-        "Connection": true,
-        "Content-Length": true,
-        "Cookie": true,
-        "Cookie2": true,
-        "Content-Transfer-Encoding": true,
-        "Date": true,
-        "Expect": true,
-        "Host": true,
-        "Keep-Alive": true,
-        "Referer": true,
-        "TE": true,
-        "Trailer": true,
-        "Transfer-Encoding": true,
-        "Upgrade": true,
-        "User-Agent": true,
-        "Via": true
-    };
-    /*jsl:end*/
-
-    function FakeXMLHttpRequest() {
-        this.readyState = FakeXMLHttpRequest.UNSENT;
-        this.requestHeaders = {};
-        this.requestBody = null;
-        this.status = 0;
-        this.statusText = "";
-        this.upload = new UploadProgress();
-        if (sinon.xhr.supportsCORS) {
-            this.withCredentials = false;
-        }
-
-
-        var xhr = this;
-        var events = ["loadstart", "load", "abort", "loadend"];
-
-        function addEventListener(eventName) {
-            xhr.addEventListener(eventName, function (event) {
-                var listener = xhr["on" + eventName];
-
-                if (listener && typeof listener == "function") {
-                    listener(event);
-                }
-            });
-        }
-
-        for (var i = events.length - 1; i >= 0; i--) {
-            addEventListener(events[i]);
-        }
-
-        if (typeof FakeXMLHttpRequest.onCreate == "function") {
-            FakeXMLHttpRequest.onCreate(this);
-        }
-    }
-
-    // An upload object is created for each
-    // FakeXMLHttpRequest and allows upload
-    // events to be simulated using uploadProgress
-    // and uploadError.
-    function UploadProgress() {
-        this.eventListeners = {
-            "progress": [],
-            "load": [],
-            "abort": [],
-            "error": []
-        }
-    }
-
-    UploadProgress.prototype.addEventListener = function(event, listener) {
-        this.eventListeners[event].push(listener);
-    };
-
-    UploadProgress.prototype.removeEventListener = function(event, listener) {
-        var listeners = this.eventListeners[event] || [];
-
-        for (var i = 0, l = listeners.length; i < l; ++i) {
-            if (listeners[i] == listener) {
-                return listeners.splice(i, 1);
-            }
-        }
-    };
-
-    UploadProgress.prototype.dispatchEvent = function(event) {
-        var listeners = this.eventListeners[event.type] || [];
-
-        for (var i = 0, listener; (listener = listeners[i]) != null; i++) {
-            listener(event);
-        }
-    };
-
-    function verifyState(xhr) {
-        if (xhr.readyState !== FakeXMLHttpRequest.OPENED) {
-            throw new Error("INVALID_STATE_ERR");
-        }
-
-        if (xhr.sendFlag) {
-            throw new Error("INVALID_STATE_ERR");
-        }
-    }
-
-    // filtering to enable a white-list version of Sinon FakeXhr,
-    // where whitelisted requests are passed through to real XHR
-    function each(collection, callback) {
-        if (!collection) return;
-        for (var i = 0, l = collection.length; i < l; i += 1) {
-            callback(collection[i]);
-        }
-    }
-    function some(collection, callback) {
-        for (var index = 0; index < collection.length; index++) {
-            if(callback(collection[index]) === true) return true;
-        }
-        return false;
-    }
-    // largest arity in XHR is 5 - XHR#open
-    var apply = function(obj,method,args) {
-        switch(args.length) {
-        case 0: return obj[method]();
-        case 1: return obj[method](args[0]);
-        case 2: return obj[method](args[0],args[1]);
-        case 3: return obj[method](args[0],args[1],args[2]);
-        case 4: return obj[method](args[0],args[1],args[2],args[3]);
-        case 5: return obj[method](args[0],args[1],args[2],args[3],args[4]);
-        }
-    };
-
-    FakeXMLHttpRequest.filters = [];
-    FakeXMLHttpRequest.addFilter = function(fn) {
-        this.filters.push(fn)
-    };
-    var IE6Re = /MSIE 6/;
-    FakeXMLHttpRequest.defake = function(fakeXhr,xhrArgs) {
-        var xhr = new sinon.xhr.workingXHR();
-        each(["open","setRequestHeader","send","abort","getResponseHeader",
-              "getAllResponseHeaders","addEventListener","overrideMimeType","removeEventListener"],
-             function(method) {
-                 fakeXhr[method] = function() {
-                   return apply(xhr,method,arguments);
-                 };
-             });
-
-        var copyAttrs = function(args) {
-            each(args, function(attr) {
-              try {
-                fakeXhr[attr] = xhr[attr]
-              } catch(e) {
-                if(!IE6Re.test(navigator.userAgent)) throw e;
-              }
-            });
-        };
-
-        var stateChange = function() {
-            fakeXhr.readyState = xhr.readyState;
-            if(xhr.readyState >= FakeXMLHttpRequest.HEADERS_RECEIVED) {
-                copyAttrs(["status","statusText"]);
-            }
-            if(xhr.readyState >= FakeXMLHttpRequest.LOADING) {
-                copyAttrs(["responseText"]);
-            }
-            if(xhr.readyState === FakeXMLHttpRequest.DONE) {
-                copyAttrs(["responseXML"]);
-            }
-            if(fakeXhr.onreadystatechange) fakeXhr.onreadystatechange.call(fakeXhr, { target: fakeXhr });
-        };
-        if(xhr.addEventListener) {
-          for(var event in fakeXhr.eventListeners) {
-              if(fakeXhr.eventListeners.hasOwnProperty(event)) {
-                  each(fakeXhr.eventListeners[event],function(handler) {
-                      xhr.addEventListener(event, handler);
-                  });
-              }
-          }
-          xhr.addEventListener("readystatechange",stateChange);
-        } else {
-          xhr.onreadystatechange = stateChange;
-        }
-        apply(xhr,"open",xhrArgs);
-    };
-    FakeXMLHttpRequest.useFilters = false;
-
-    function verifyRequestSent(xhr) {
-        if (xhr.readyState == FakeXMLHttpRequest.DONE) {
-            throw new Error("Request done");
-        }
-    }
-
-    function verifyHeadersReceived(xhr) {
-        if (xhr.async && xhr.readyState != FakeXMLHttpRequest.HEADERS_RECEIVED) {
-            throw new Error("No headers received");
-        }
-    }
-
-    function verifyResponseBodyType(body) {
-        if (typeof body != "string") {
-            var error = new Error("Attempted to respond to fake XMLHttpRequest with " +
-                                 body + ", which is not a string.");
-            error.name = "InvalidBodyException";
-            throw error;
-        }
-    }
-
-    sinon.extend(FakeXMLHttpRequest.prototype, sinon.EventTarget, {
-        async: true,
-
-        open: function open(method, url, async, username, password) {
-            this.method = method;
-            this.url = url;
-            this.async = typeof async == "boolean" ? async : true;
-            this.username = username;
-            this.password = password;
-            this.responseText = null;
-            this.responseXML = null;
-            this.requestHeaders = {};
-            this.sendFlag = false;
-            if(sinon.FakeXMLHttpRequest.useFilters === true) {
-                var xhrArgs = arguments;
-                var defake = some(FakeXMLHttpRequest.filters,function(filter) {
-                    return filter.apply(this,xhrArgs)
-                });
-                if (defake) {
-                  return sinon.FakeXMLHttpRequest.defake(this,arguments);
-                }
-            }
-            this.readyStateChange(FakeXMLHttpRequest.OPENED);
-        },
-
-        readyStateChange: function readyStateChange(state) {
-            this.readyState = state;
-
-            if (typeof this.onreadystatechange == "function") {
-                try {
-                    this.onreadystatechange();
-                } catch (e) {
-                    sinon.logError("Fake XHR onreadystatechange handler", e);
-                }
-            }
-
-            this.dispatchEvent(new sinon.Event("readystatechange"));
-
-            switch (this.readyState) {
-                case FakeXMLHttpRequest.DONE:
-                    this.dispatchEvent(new sinon.Event("load", false, false, this));
-                    this.dispatchEvent(new sinon.Event("loadend", false, false, this));
-                    this.upload.dispatchEvent(new sinon.Event("load", false, false, this));
-                    this.upload.dispatchEvent(new ProgressEvent("progress", {loaded: 100, total: 100}));
-                    break;
-            }
-        },
-
-        setRequestHeader: function setRequestHeader(header, value) {
-            verifyState(this);
-
-            if (unsafeHeaders[header] || /^(Sec-|Proxy-)/.test(header)) {
-                throw new Error("Refused to set unsafe header \"" + header + "\"");
-            }
-
-            if (this.requestHeaders[header]) {
-                this.requestHeaders[header] += "," + value;
-            } else {
-                this.requestHeaders[header] = value;
-            }
-        },
-
-        // Helps testing
-        setResponseHeaders: function setResponseHeaders(headers) {
-            this.responseHeaders = {};
-
-            for (var header in headers) {
-                if (headers.hasOwnProperty(header)) {
-                    this.responseHeaders[header] = headers[header];
-                }
-            }
-
-            if (this.async) {
-                this.readyStateChange(FakeXMLHttpRequest.HEADERS_RECEIVED);
-            } else {
-                this.readyState = FakeXMLHttpRequest.HEADERS_RECEIVED;
-            }
-        },
-
-        // Currently treats ALL data as a DOMString (i.e. no Document)
-        send: function send(data) {
-            verifyState(this);
-
-            if (!/^(get|head)$/i.test(this.method)) {
-                if (this.requestHeaders["Content-Type"]) {
-                    var value = this.requestHeaders["Content-Type"].split(";");
-                    this.requestHeaders["Content-Type"] = value[0] + ";charset=utf-8";
-                } else {
-                    this.requestHeaders["Content-Type"] = "text/plain;charset=utf-8";
-                }
-
-                this.requestBody = data;
-            }
-
-            this.errorFlag = false;
-            this.sendFlag = this.async;
-            this.readyStateChange(FakeXMLHttpRequest.OPENED);
-
-            if (typeof this.onSend == "function") {
-                this.onSend(this);
-            }
-
-            this.dispatchEvent(new sinon.Event("loadstart", false, false, this));
-        },
-
-        abort: function abort() {
-            this.aborted = true;
-            this.responseText = null;
-            this.errorFlag = true;
-            this.requestHeaders = {};
-
-            if (this.readyState > sinon.FakeXMLHttpRequest.UNSENT && this.sendFlag) {
-                this.readyStateChange(sinon.FakeXMLHttpRequest.DONE);
-                this.sendFlag = false;
-            }
-
-            this.readyState = sinon.FakeXMLHttpRequest.UNSENT;
-
-            this.dispatchEvent(new sinon.Event("abort", false, false, this));
-
-            this.upload.dispatchEvent(new sinon.Event("abort", false, false, this));
-
-            if (typeof this.onerror === "function") {
-                this.onerror();
-            }
-        },
-
-        getResponseHeader: function getResponseHeader(header) {
-            if (this.readyState < FakeXMLHttpRequest.HEADERS_RECEIVED) {
-                return null;
-            }
-
-            if (/^Set-Cookie2?$/i.test(header)) {
-                return null;
-            }
-
-            header = header.toLowerCase();
-
-            for (var h in this.responseHeaders) {
-                if (h.toLowerCase() == header) {
-                    return this.responseHeaders[h];
-                }
-            }
-
-            return null;
-        },
-
-        getAllResponseHeaders: function getAllResponseHeaders() {
-            if (this.readyState < FakeXMLHttpRequest.HEADERS_RECEIVED) {
-                return "";
-            }
-
-            var headers = "";
-
-            for (var header in this.responseHeaders) {
-                if (this.responseHeaders.hasOwnProperty(header) &&
-                    !/^Set-Cookie2?$/i.test(header)) {
-                    headers += header + ": " + this.responseHeaders[header] + "\r\n";
-                }
-            }
-
-            return headers;
-        },
-
-        setResponseBody: function setResponseBody(body) {
-            verifyRequestSent(this);
-            verifyHeadersReceived(this);
-            verifyResponseBodyType(body);
-
-            var chunkSize = this.chunkSize || 10;
-            var index = 0;
-            this.responseText = "";
-
-            do {
-                if (this.async) {
-                    this.readyStateChange(FakeXMLHttpRequest.LOADING);
-                }
-
-                this.responseText += body.substring(index, index + chunkSize);
-                index += chunkSize;
-            } while (index < body.length);
-
-            var type = this.getResponseHeader("Content-Type");
-
-            if (this.responseText &&
-                (!type || /(text\/xml)|(application\/xml)|(\+xml)/.test(type))) {
-                try {
-                    this.responseXML = FakeXMLHttpRequest.parseXML(this.responseText);
-                } catch (e) {
-                    // Unable to parse XML - no biggie
-                }
-            }
-
-            if (this.async) {
-                this.readyStateChange(FakeXMLHttpRequest.DONE);
-            } else {
-                this.readyState = FakeXMLHttpRequest.DONE;
-            }
-        },
-
-        respond: function respond(status, headers, body) {
-            this.setResponseHeaders(headers || {});
-            this.status = typeof status == "number" ? status : 200;
-            this.statusText = FakeXMLHttpRequest.statusCodes[this.status];
-            this.setResponseBody(body || "");
-        },
-
-        uploadProgress: function uploadProgress(progressEventRaw) {
-            this.upload.dispatchEvent(new ProgressEvent("progress", progressEventRaw));
-        },
-
-        uploadError: function uploadError(error) {
-            this.upload.dispatchEvent(new CustomEvent("error", {"detail": error}));
-        }
-    });
-
-    sinon.extend(FakeXMLHttpRequest, {
-        UNSENT: 0,
-        OPENED: 1,
-        HEADERS_RECEIVED: 2,
-        LOADING: 3,
-        DONE: 4
-    });
-
-    // Borrowed from JSpec
-    FakeXMLHttpRequest.parseXML = function parseXML(text) {
-        var xmlDoc;
-
-        if (typeof DOMParser != "undefined") {
-            var parser = new DOMParser();
-            xmlDoc = parser.parseFromString(text, "text/xml");
-        } else {
-            xmlDoc = new ActiveXObject("Microsoft.XMLDOM");
-            xmlDoc.async = "false";
-            xmlDoc.loadXML(text);
-        }
-
-        return xmlDoc;
-    };
-
-    FakeXMLHttpRequest.statusCodes = {
-        100: "Continue",
-        101: "Switching Protocols",
-        200: "OK",
-        201: "Created",
-        202: "Accepted",
-        203: "Non-Authoritative Information",
-        204: "No Content",
-        205: "Reset Content",
-        206: "Partial Content",
-        300: "Multiple Choice",
-        301: "Moved Permanently",
-        302: "Found",
-        303: "See Other",
-        304: "Not Modified",
-        305: "Use Proxy",
-        307: "Temporary Redirect",
-        400: "Bad Request",
-        401: "Unauthorized",
-        402: "Payment Required",
-        403: "Forbidden",
-        404: "Not Found",
-        405: "Method Not Allowed",
-        406: "Not Acceptable",
-        407: "Proxy Authentication Required",
-        408: "Request Timeout",
-        409: "Conflict",
-        410: "Gone",
-        411: "Length Required",
-        412: "Precondition Failed",
-        413: "Request Entity Too Large",
-        414: "Request-URI Too Long",
-        415: "Unsupported Media Type",
-        416: "Requested Range Not Satisfiable",
-        417: "Expectation Failed",
-        422: "Unprocessable Entity",
-        500: "Internal Server Error",
-        501: "Not Implemented",
-        502: "Bad Gateway",
-        503: "Service Unavailable",
-        504: "Gateway Timeout",
-        505: "HTTP Version Not Supported"
-    };
-
-    sinon.useFakeXMLHttpRequest = function () {
-        sinon.FakeXMLHttpRequest.restore = function restore(keepOnCreate) {
-            if (xhr.supportsXHR) {
-                global.XMLHttpRequest = xhr.GlobalXMLHttpRequest;
-            }
-
-            if (xhr.supportsActiveX) {
-                global.ActiveXObject = xhr.GlobalActiveXObject;
-            }
-
-            delete sinon.FakeXMLHttpRequest.restore;
-
-            if (keepOnCreate !== true) {
-                delete sinon.FakeXMLHttpRequest.onCreate;
-            }
-        };
-        if (xhr.supportsXHR) {
-            global.XMLHttpRequest = sinon.FakeXMLHttpRequest;
-        }
-
-        if (xhr.supportsActiveX) {
-            global.ActiveXObject = function ActiveXObject(objId) {
-                if (objId == "Microsoft.XMLHTTP" || /^Msxml2\.XMLHTTP/i.test(objId)) {
-
-                    return new sinon.FakeXMLHttpRequest();
-                }
-
-                return new xhr.GlobalActiveXObject(objId);
-            };
-        }
-
-        return sinon.FakeXMLHttpRequest;
-    };
-
-    sinon.FakeXMLHttpRequest = FakeXMLHttpRequest;
-
-})(typeof global === "object" ? global : this);
-
-if (typeof module !== 'undefined' && module.exports) {
-    module.exports = sinon;
-}
-
-/**
- * @depend fake_xml_http_request.js
- */
-/*jslint eqeqeq: false, onevar: false, regexp: false, plusplus: false*/
-/*global module, require, window*/
-/**
- * The Sinon "server" mimics a web server that receives requests from
- * sinon.FakeXMLHttpRequest and provides an API to respond to those requests,
- * both synchronously and asynchronously. To respond synchronuously, canned
- * answers have to be provided upfront.
- *
- * @author Christian Johansen (christian@cjohansen.no)
- * @license BSD
- *
- * Copyright (c) 2010-2013 Christian Johansen
- */
-
-if (typeof sinon == "undefined") {
-    var sinon = {};
-}
-
-sinon.fakeServer = (function () {
-    var push = [].push;
-    function F() {}
-
-    function create(proto) {
-        F.prototype = proto;
-        return new F();
-    }
-
-    function responseArray(handler) {
-        var response = handler;
-
-        if (Object.prototype.toString.call(handler) != "[object Array]") {
-            response = [200, {}, handler];
-        }
-
-        if (typeof response[2] != "string") {
-            throw new TypeError("Fake server response body should be string, but was " +
-                                typeof response[2]);
-        }
-
-        return response;
-    }
-
-    var wloc = typeof window !== "undefined" ? window.location : {};
-    var rCurrLoc = new RegExp("^" + wloc.protocol + "//" + wloc.host);
-
-    function matchOne(response, reqMethod, reqUrl) {
-        var rmeth = response.method;
-        var matchMethod = !rmeth || rmeth.toLowerCase() == reqMethod.toLowerCase();
-        var url = response.url;
-        var matchUrl = !url || url == reqUrl || (typeof url.test == "function" && url.test(reqUrl));
-
-        return matchMethod && matchUrl;
-    }
-
-    function match(response, request) {
-        var requestUrl = request.url;
-
-        if (!/^https?:\/\//.test(requestUrl) || rCurrLoc.test(requestUrl)) {
-            requestUrl = requestUrl.replace(rCurrLoc, "");
-        }
-
-        if (matchOne(response, this.getHTTPMethod(request), requestUrl)) {
-            if (typeof response.response == "function") {
-                var ru = response.url;
-                var args = [request].concat(ru && typeof ru.exec == "function" ? ru.exec(requestUrl).slice(1) : []);
-                return response.response.apply(response, args);
-            }
-
-            return true;
-        }
-
-        return false;
-    }
-
-    function log(response, request) {
-        var str;
-
-        str =  "Request:\n"  + sinon.format(request)  + "\n\n";
-        str += "Response:\n" + sinon.format(response) + "\n\n";
-
-        sinon.log(str);
-    }
-
-    return {
-        create: function () {
-            var server = create(this);
-            this.xhr = sinon.useFakeXMLHttpRequest();
-            server.requests = [];
-
-            this.xhr.onCreate = function (xhrObj) {
-                server.addRequest(xhrObj);
-            };
-
-            return server;
-        },
-
-        addRequest: function addRequest(xhrObj) {
-            var server = this;
-            push.call(this.requests, xhrObj);
-
-            xhrObj.onSend = function () {
-                server.handleRequest(this);
-
-                if (server.autoRespond && !server.responding) {
-                    setTimeout(function () {
-                        server.responding = false;
-                        server.respond();
-                    }, server.autoRespondAfter || 10);
-
-                    server.responding = true;
-                }
-            };
-        },
-
-        getHTTPMethod: function getHTTPMethod(request) {
-            if (this.fakeHTTPMethods && /post/i.test(request.method)) {
-                var matches = (request.requestBody || "").match(/_method=([^\b;]+)/);
-                return !!matches ? matches[1] : request.method;
-            }
-
-            return request.method;
-        },
-
-        handleRequest: function handleRequest(xhr) {
-            if (xhr.async) {
-                if (!this.queue) {
-                    this.queue = [];
-                }
-
-                push.call(this.queue, xhr);
-            } else {
-                this.processRequest(xhr);
-            }
-        },
-
-        respondWith: function respondWith(method, url, body) {
-            if (arguments.length == 1 && typeof method != "function") {
-                this.response = responseArray(method);
-                return;
-            }
-
-            if (!this.responses) { this.responses = []; }
-
-            if (arguments.length == 1) {
-                body = method;
-                url = method = null;
-            }
-
-            if (arguments.length == 2) {
-                body = url;
-                url = method;
-                method = null;
-            }
-
-            push.call(this.responses, {
-                method: method,
-                url: url,
-                response: typeof body == "function" ? body : responseArray(body)
-            });
-        },
-
-        respond: function respond() {
-            if (arguments.length > 0) this.respondWith.apply(this, arguments);
-            var queue = this.queue || [];
-            var requests = queue.splice(0);
-            var request;
-
-            while(request = requests.shift()) {
-                this.processRequest(request);
-            }
-        },
-
-        processRequest: function processRequest(request) {
-            try {
-                if (request.aborted) {
-                    return;
-                }
-
-                var response = this.response || [404, {}, ""];
-
-                if (this.responses) {
-                    for (var l = this.responses.length, i = l - 1; i >= 0; i--) {
-                        if (match.call(this, this.responses[i], request)) {
-                            response = this.responses[i].response;
-                            break;
-                        }
-                    }
-                }
-
-                if (request.readyState != 4) {
-                    log(response, request);
-
-                    request.respond(response[0], response[1], response[2]);
-                }
-            } catch (e) {
-                sinon.logError("Fake server request processing", e);
-            }
-        },
-
-        restore: function restore() {
-            return this.xhr.restore && this.xhr.restore.apply(this.xhr, arguments);
-        }
-    };
-}());
-
-if (typeof module !== 'undefined' && module.exports) {
-    module.exports = sinon;
-}
-
-/**
- * @depend fake_server.js
- * @depend fake_timers.js
- */
-/*jslint browser: true, eqeqeq: false, onevar: false*/
-/*global sinon*/
-/**
- * Add-on for sinon.fakeServer that automatically handles a fake timer along with
- * the FakeXMLHttpRequest. The direct inspiration for this add-on is jQuery
- * 1.3.x, which does not use xhr object's onreadystatehandler at all - instead,
- * it polls the object for completion with setInterval. Dispite the direct
- * motivation, there is nothing jQuery-specific in this file, so it can be used
- * in any environment where the ajax implementation depends on setInterval or
- * setTimeout.
- *
- * @author Christian Johansen (christian@cjohansen.no)
- * @license BSD
- *
- * Copyright (c) 2010-2013 Christian Johansen
- */
-
-(function () {
-    function Server() {}
-    Server.prototype = sinon.fakeServer;
-
-    sinon.fakeServerWithClock = new Server();
-
-    sinon.fakeServerWithClock.addRequest = function addRequest(xhr) {
-        if (xhr.async) {
-            if (typeof setTimeout.clock == "object") {
-                this.clock = setTimeout.clock;
-            } else {
-                this.clock = sinon.useFakeTimers();
-                this.resetClock = true;
-            }
-
-            if (!this.longestTimeout) {
-                var clockSetTimeout = this.clock.setTimeout;
-                var clockSetInterval = this.clock.setInterval;
-                var server = this;
-
-                this.clock.setTimeout = function (fn, timeout) {
-                    server.longestTimeout = Math.max(timeout, server.longestTimeout || 0);
-
-                    return clockSetTimeout.apply(this, arguments);
-                };
-
-                this.clock.setInterval = function (fn, timeout) {
-                    server.longestTimeout = Math.max(timeout, server.longestTimeout || 0);
-
-                    return clockSetInterval.apply(this, arguments);
-                };
-            }
-        }
-
-        return sinon.fakeServer.addRequest.call(this, xhr);
-    };
-
-    sinon.fakeServerWithClock.respond = function respond() {
-        var returnVal = sinon.fakeServer.respond.apply(this, arguments);
-
-        if (this.clock) {
-            this.clock.tick(this.longestTimeout || 0);
-            this.longestTimeout = 0;
-
-            if (this.resetClock) {
-                this.clock.restore();
-                this.resetClock = false;
-            }
-        }
-
-        return returnVal;
-    };
-
-    sinon.fakeServerWithClock.restore = function restore() {
-        if (this.clock) {
-            this.clock.restore();
-        }
-
-        return sinon.fakeServer.restore.apply(this, arguments);
-    };
-}());
-
-/**
- * @depend ../sinon.js
- * @depend collection.js
- * @depend util/fake_timers.js
- * @depend util/fake_server_with_clock.js
- */
-/*jslint eqeqeq: false, onevar: false, plusplus: false*/
-/*global require, module*/
-/**
- * Manages fake collections as well as fake utilities such as Sinon's
- * timers and fake XHR implementation in one convenient object.
- *
- * @author Christian Johansen (christian@cjohansen.no)
- * @license BSD
- *
- * Copyright (c) 2010-2013 Christian Johansen
- */
-
-if (typeof module !== 'undefined' && module.exports) {
-    var sinon = require("../sinon");
-    sinon.extend(sinon, require("./util/fake_timers"));
-}
-
-(function () {
-    var push = [].push;
-
-    function exposeValue(sandbox, config, key, value) {
-        if (!value) {
-            return;
-        }
-
-        if (config.injectInto && !(key in config.injectInto) ) {
-            config.injectInto[key] = value;
-        } else {
-            push.call(sandbox.args, value);
-        }
-    }
-
-    function prepareSandboxFromConfig(config) {
-        var sandbox = sinon.create(sinon.sandbox);
-
-        if (config.useFakeServer) {
-            if (typeof config.useFakeServer == "object") {
-                sandbox.serverPrototype = config.useFakeServer;
-            }
-
-            sandbox.useFakeServer();
-        }
-
-        if (config.useFakeTimers) {
-            if (typeof config.useFakeTimers == "object") {
-                sandbox.useFakeTimers.apply(sandbox, config.useFakeTimers);
-            } else {
-                sandbox.useFakeTimers();
-            }
-        }
-
-        return sandbox;
-    }
-
-    sinon.sandbox = sinon.extend(sinon.create(sinon.collection), {
-        useFakeTimers: function useFakeTimers() {
-            this.clock = sinon.useFakeTimers.apply(sinon, arguments);
-
-            return this.add(this.clock);
-        },
-
-        serverPrototype: sinon.fakeServer,
-
-        useFakeServer: function useFakeServer() {
-            var proto = this.serverPrototype || sinon.fakeServer;
-
-            if (!proto || !proto.create) {
-                return null;
-            }
-
-            this.server = proto.create();
-            return this.add(this.server);
-        },
-
-        inject: function (obj) {
-            sinon.collection.inject.call(this, obj);
-
-            if (this.clock) {
-                obj.clock = this.clock;
-            }
-
-            if (this.server) {
-                obj.server = this.server;
-                obj.requests = this.server.requests;
-            }
-
-            return obj;
-        },
-
-        create: function (config) {
-            if (!config) {
-                return sinon.create(sinon.sandbox);
-            }
-
-            var sandbox = prepareSandboxFromConfig(config);
-            sandbox.args = sandbox.args || [];
-            var prop, value, exposed = sandbox.inject({});
-
-            if (config.properties) {
-                for (var i = 0, l = config.properties.length; i < l; i++) {
-                    prop = config.properties[i];
-                    value = exposed[prop] || prop == "sandbox" && sandbox;
-                    exposeValue(sandbox, config, prop, value);
-                }
-            } else {
-                exposeValue(sandbox, config, "sandbox", value);
-            }
-
-            return sandbox;
-        }
-    });
-
-    sinon.sandbox.useFakeXMLHttpRequest = sinon.sandbox.useFakeServer;
-
-    if (typeof module !== 'undefined' && module.exports) {
-        module.exports = sinon.sandbox;
-    }
-}());
-
-/**
- * @depend ../sinon.js
- * @depend stub.js
- * @depend mock.js
- * @depend sandbox.js
- */
-/*jslint eqeqeq: false, onevar: false, forin: true, plusplus: false*/
-/*global module, require, sinon*/
-/**
- * Test function, sandboxes fakes
- *
- * @author Christian Johansen (christian@cjohansen.no)
- * @license BSD
- *
- * Copyright (c) 2010-2013 Christian Johansen
- */
-
-(function (sinon) {
-    var commonJSModule = typeof module !== 'undefined' && module.exports;
-
-    if (!sinon && commonJSModule) {
-        sinon = require("../sinon");
-    }
-
-    if (!sinon) {
-        return;
-    }
-
-    function test(callback) {
-        var type = typeof callback;
-
-        if (type != "function") {
-            throw new TypeError("sinon.test needs to wrap a test function, got " + type);
-        }
-
-        return function () {
-            var config = sinon.getConfig(sinon.config);
-            config.injectInto = config.injectIntoThis && this || config.injectInto;
-            var sandbox = sinon.sandbox.create(config);
-            var exception, result;
-            var args = Array.prototype.slice.call(arguments).concat(sandbox.args);
-
-            try {
-                result = callback.apply(this, args);
-            } catch (e) {
-                exception = e;
-            }
-
-            if (typeof exception !== "undefined") {
-                sandbox.restore();
-                throw exception;
-            }
-            else {
-                sandbox.verifyAndRestore();
-            }
-
-            return result;
-        };
-    }
-
-    test.config = {
-        injectIntoThis: true,
-        injectInto: null,
-        properties: ["spy", "stub", "mock", "clock", "server", "requests"],
-        useFakeTimers: true,
-        useFakeServer: true
-    };
-
-    if (commonJSModule) {
-        module.exports = test;
-    } else {
-        sinon.test = test;
-    }
-}(typeof sinon == "object" && sinon || null));
-
-/**
- * @depend ../sinon.js
- * @depend test.js
- */
-/*jslint eqeqeq: false, onevar: false, eqeqeq: false*/
-/*global module, require, sinon*/
-/**
- * Test case, sandboxes all test functions
- *
- * @author Christian Johansen (christian@cjohansen.no)
- * @license BSD
- *
- * Copyright (c) 2010-2013 Christian Johansen
- */
-
-(function (sinon) {
-    var commonJSModule = typeof module !== 'undefined' && module.exports;
-
-    if (!sinon && commonJSModule) {
-        sinon = require("../sinon");
-    }
-
-    if (!sinon || !Object.prototype.hasOwnProperty) {
-        return;
-    }
-
-    function createTest(property, setUp, tearDown) {
-        return function () {
-            if (setUp) {
-                setUp.apply(this, arguments);
-            }
-
-            var exception, result;
-
-            try {
-                result = property.apply(this, arguments);
-            } catch (e) {
-                exception = e;
-            }
-
-            if (tearDown) {
-                tearDown.apply(this, arguments);
-            }
-
-            if (exception) {
-                throw exception;
-            }
-
-            return result;
-        };
-    }
-
-    function testCase(tests, prefix) {
-        /*jsl:ignore*/
-        if (!tests || typeof tests != "object") {
-            throw new TypeError("sinon.testCase needs an object with test functions");
-        }
-        /*jsl:end*/
-
-        prefix = prefix || "test";
-        var rPrefix = new RegExp("^" + prefix);
-        var methods = {}, testName, property, method;
-        var setUp = tests.setUp;
-        var tearDown = tests.tearDown;
-
-        for (testName in tests) {
-            if (tests.hasOwnProperty(testName)) {
-                property = tests[testName];
-
-                if (/^(setUp|tearDown)$/.test(testName)) {
-                    continue;
-                }
-
-                if (typeof property == "function" && rPrefix.test(testName)) {
-                    method = property;
-
-                    if (setUp || tearDown) {
-                        method = createTest(property, setUp, tearDown);
-                    }
-
-                    methods[testName] = sinon.test(method);
-                } else {
-                    methods[testName] = tests[testName];
-                }
-            }
-        }
-
-        return methods;
-    }
-
-    if (commonJSModule) {
-        module.exports = testCase;
-    } else {
-        sinon.testCase = testCase;
-    }
-}(typeof sinon == "object" && sinon || null));
-
-/**
- * @depend ../sinon.js
- * @depend stub.js
- */
-/*jslint eqeqeq: false, onevar: false, nomen: false, plusplus: false*/
-/*global module, require, sinon*/
-/**
- * Assertions matching the test spy retrieval interface.
- *
- * @author Christian Johansen (christian@cjohansen.no)
- * @license BSD
- *
- * Copyright (c) 2010-2013 Christian Johansen
- */
-
-(function (sinon, global) {
-    var commonJSModule = typeof module !== "undefined" && module.exports;
-    var slice = Array.prototype.slice;
-    var assert;
-
-    if (!sinon && commonJSModule) {
-        sinon = require("../sinon");
-    }
-
-    if (!sinon) {
-        return;
-    }
-
-    function verifyIsStub() {
-        var method;
-
-        for (var i = 0, l = arguments.length; i < l; ++i) {
-            method = arguments[i];
-
-            if (!method) {
-                assert.fail("fake is not a spy");
-            }
-
-            if (typeof method != "function") {
-                assert.fail(method + " is not a function");
-            }
-
-            if (typeof method.getCall != "function") {
-                assert.fail(method + " is not stubbed");
-            }
-        }
-    }
-
-    function failAssertion(object, msg) {
-        object = object || global;
-        var failMethod = object.fail || assert.fail;
-        failMethod.call(object, msg);
-    }
-
-    function mirrorPropAsAssertion(name, method, message) {
-        if (arguments.length == 2) {
-            message = method;
-            method = name;
-        }
-
-        assert[name] = function (fake) {
-            verifyIsStub(fake);
-
-            var args = slice.call(arguments, 1);
-            var failed = false;
-
-            if (typeof method == "function") {
-                failed = !method(fake);
-            } else {
-                failed = typeof fake[method] == "function" ?
-                    !fake[method].apply(fake, args) : !fake[method];
-            }
-
-            if (failed) {
-                failAssertion(this, fake.printf.apply(fake, [message].concat(args)));
-            } else {
-                assert.pass(name);
-            }
-        };
-    }
-
-    function exposedName(prefix, prop) {
-        return !prefix || /^fail/.test(prop) ? prop :
-            prefix + prop.slice(0, 1).toUpperCase() + prop.slice(1);
-    }
-
-    assert = {
-        failException: "AssertError",
-
-        fail: function fail(message) {
-            var error = new Error(message);
-            error.name = this.failException || assert.failException;
-
-            throw error;
-        },
-
-        pass: function pass(assertion) {},
-
-        callOrder: function assertCallOrder() {
-            verifyIsStub.apply(null, arguments);
-            var expected = "", actual = "";
-
-            if (!sinon.calledInOrder(arguments)) {
-                try {
-                    expected = [].join.call(arguments, ", ");
-                    var calls = slice.call(arguments);
-                    var i = calls.length;
-                    while (i) {
-                        if (!calls[--i].called) {
-                            calls.splice(i, 1);
-                        }
-                    }
-                    actual = sinon.orderByFirstCall(calls).join(", ");
-                } catch (e) {
-                    // If this fails, we'll just fall back to the blank string
-                }
-
-                failAssertion(this, "expected " + expected + " to be " +
-                              "called in order but were called as " + actual);
-            } else {
-                assert.pass("callOrder");
-            }
-        },
-
-        callCount: function assertCallCount(method, count) {
-            verifyIsStub(method);
-
-            if (method.callCount != count) {
-                var msg = "expected %n to be called " + sinon.timesInWords(count) +
-                    " but was called %c%C";
-                failAssertion(this, method.printf(msg));
-            } else {
-                assert.pass("callCount");
-            }
-        },
-
-        expose: function expose(target, options) {
-            if (!target) {
-                throw new TypeError("target is null or undefined");
-            }
-
-            var o = options || {};
-            var prefix = typeof o.prefix == "undefined" && "assert" || o.prefix;
-            var includeFail = typeof o.includeFail == "undefined" || !!o.includeFail;
-
-            for (var method in this) {
-                if (method != "export" && (includeFail || !/^(fail)/.test(method))) {
-                    target[exposedName(prefix, method)] = this[method];
-                }
-            }
-
-            return target;
-        }
-    };
-
-    mirrorPropAsAssertion("called", "expected %n to have been called at least once but was never called");
-    mirrorPropAsAssertion("notCalled", function (spy) { return !spy.called; },
-                          "expected %n to not have been called but was called %c%C");
-    mirrorPropAsAssertion("calledOnce", "expected %n to be called once but was called %c%C");
-    mirrorPropAsAssertion("calledTwice", "expected %n to be called twice but was called %c%C");
-    mirrorPropAsAssertion("calledThrice", "expected %n to be called thrice but was called %c%C");
-    mirrorPropAsAssertion("calledOn", "expected %n to be called with %1 as this but was called with %t");
-    mirrorPropAsAssertion("alwaysCalledOn", "expected %n to always be called with %1 as this but was called with %t");
-    mirrorPropAsAssertion("calledWithNew", "expected %n to be called with new");
-    mirrorPropAsAssertion("alwaysCalledWithNew", "expected %n to always be called with new");
-    mirrorPropAsAssertion("calledWith", "expected %n to be called with arguments %*%C");
-    mirrorPropAsAssertion("calledWithMatch", "expected %n to be called with match %*%C");
-    mirrorPropAsAssertion("alwaysCalledWith", "expected %n to always be called with arguments %*%C");
-    mirrorPropAsAssertion("alwaysCalledWithMatch", "expected %n to always be called with match %*%C");
-    mirrorPropAsAssertion("calledWithExactly", "expected %n to be called with exact arguments %*%C");
-    mirrorPropAsAssertion("alwaysCalledWithExactly", "expected %n to always be called with exact arguments %*%C");
-    mirrorPropAsAssertion("neverCalledWith", "expected %n to never be called with arguments %*%C");
-    mirrorPropAsAssertion("neverCalledWithMatch", "expected %n to never be called with match %*%C");
-    mirrorPropAsAssertion("threw", "%n did not throw exception%C");
-    mirrorPropAsAssertion("alwaysThrew", "%n did not always throw exception%C");
-
-    if (commonJSModule) {
-        module.exports = assert;
-    } else {
-        sinon.assert = assert;
-    }
-}(typeof sinon == "object" && sinon || null, typeof window != "undefined" ? window : (typeof self != "undefined") ? self : global));
-
-return sinon;}.call(typeof window != 'undefined' && window || {}));
diff --git a/resources/sinonjs/sinon-1.9.0.js b/resources/sinonjs/sinon-1.9.0.js
new file mode 100644 (file)
index 0000000..428b729
--- /dev/null
@@ -0,0 +1,4794 @@
+/**
+ * Sinon.JS 1.9.0, 2014/03/05
+ *
+ * @author Christian Johansen (christian@cjohansen.no)
+ * @author Contributors: https://github.com/cjohansen/Sinon.JS/blob/master/AUTHORS
+ *
+ * (The BSD License)
+ * 
+ * Copyright (c) 2010-2014, Christian Johansen, christian@cjohansen.no
+ * All rights reserved.
+ * 
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ * 
+ *     * Redistributions of source code must retain the above copyright notice,
+ *       this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright notice,
+ *       this list of conditions and the following disclaimer in the documentation
+ *       and/or other materials provided with the distribution.
+ *     * Neither the name of Christian Johansen nor the names of his contributors
+ *       may be used to endorse or promote products derived from this software
+ *       without specific prior written permission.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+this.sinon = (function () {
+var samsam, formatio;
+function define(mod, deps, fn) { if (mod == "samsam") { samsam = deps(); } else { formatio = fn(samsam); } }
+define.amd = true;
+((typeof define === "function" && define.amd && function (m) { define("samsam", m); }) ||
+ (typeof module === "object" &&
+      function (m) { module.exports = m(); }) || // Node
+ function (m) { this.samsam = m(); } // Browser globals
+)(function () {
+    var o = Object.prototype;
+    var div = typeof document !== "undefined" && document.createElement("div");
+
+    function isNaN(value) {
+        // Unlike global isNaN, this avoids type coercion
+        // typeof check avoids IE host object issues, hat tip to
+        // lodash
+        var val = value; // JsLint thinks value !== value is "weird"
+        return typeof value === "number" && value !== val;
+    }
+
+    function getClass(value) {
+        // Returns the internal [[Class]] by calling Object.prototype.toString
+        // with the provided value as this. Return value is a string, naming the
+        // internal class, e.g. "Array"
+        return o.toString.call(value).split(/[ \]]/)[1];
+    }
+
+    /**
+     * @name samsam.isArguments
+     * @param Object object
+     *
+     * Returns ``true`` if ``object`` is an ``arguments`` object,
+     * ``false`` otherwise.
+     */
+    function isArguments(object) {
+        if (typeof object !== "object" || typeof object.length !== "number" ||
+                getClass(object) === "Array") {
+            return false;
+        }
+        if (typeof object.callee == "function") { return true; }
+        try {
+            object[object.length] = 6;
+            delete object[object.length];
+        } catch (e) {
+            return true;
+        }
+        return false;
+    }
+
+    /**
+     * @name samsam.isElement
+     * @param Object object
+     *
+     * Returns ``true`` if ``object`` is a DOM element node. Unlike
+     * Underscore.js/lodash, this function will return ``false`` if ``object``
+     * is an *element-like* object, i.e. a regular object with a ``nodeType``
+     * property that holds the value ``1``.
+     */
+    function isElement(object) {
+        if (!object || object.nodeType !== 1 || !div) { return false; }
+        try {
+            object.appendChild(div);
+            object.removeChild(div);
+        } catch (e) {
+            return false;
+        }
+        return true;
+    }
+
+    /**
+     * @name samsam.keys
+     * @param Object object
+     *
+     * Return an array of own property names.
+     */
+    function keys(object) {
+        var ks = [], prop;
+        for (prop in object) {
+            if (o.hasOwnProperty.call(object, prop)) { ks.push(prop); }
+        }
+        return ks;
+    }
+
+    /**
+     * @name samsam.isDate
+     * @param Object value
+     *
+     * Returns true if the object is a ``Date``, or *date-like*. Duck typing
+     * of date objects work by checking that the object has a ``getTime``
+     * function whose return value equals the return value from the object's
+     * ``valueOf``.
+     */
+    function isDate(value) {
+        return typeof value.getTime == "function" &&
+            value.getTime() == value.valueOf();
+    }
+
+    /**
+     * @name samsam.isNegZero
+     * @param Object value
+     *
+     * Returns ``true`` if ``value`` is ``-0``.
+     */
+    function isNegZero(value) {
+        return value === 0 && 1 / value === -Infinity;
+    }
+
+    /**
+     * @name samsam.equal
+     * @param Object obj1
+     * @param Object obj2
+     *
+     * Returns ``true`` if two objects are strictly equal. Compared to
+     * ``===`` there are two exceptions:
+     *
+     *   - NaN is considered equal to NaN
+     *   - -0 and +0 are not considered equal
+     */
+    function identical(obj1, obj2) {
+        if (obj1 === obj2 || (isNaN(obj1) && isNaN(obj2))) {
+            return obj1 !== 0 || isNegZero(obj1) === isNegZero(obj2);
+        }
+    }
+
+
+    /**
+     * @name samsam.deepEqual
+     * @param Object obj1
+     * @param Object obj2
+     *
+     * Deep equal comparison. Two values are "deep equal" if:
+     *
+     *   - They are equal, according to samsam.identical
+     *   - They are both date objects representing the same time
+     *   - They are both arrays containing elements that are all deepEqual
+     *   - They are objects with the same set of properties, and each property
+     *     in ``obj1`` is deepEqual to the corresponding property in ``obj2``
+     *
+     * Supports cyclic objects.
+     */
+    function deepEqualCyclic(obj1, obj2) {
+
+        // used for cyclic comparison
+        // contain already visited objects
+        var objects1 = [],
+            objects2 = [],
+        // contain pathes (position in the object structure)
+        // of the already visited objects
+        // indexes same as in objects arrays
+            paths1 = [],
+            paths2 = [],
+        // contains combinations of already compared objects
+        // in the manner: { "$1['ref']$2['ref']": true }
+            compared = {};
+
+        /**
+         * used to check, if the value of a property is an object
+         * (cyclic logic is only needed for objects)
+         * only needed for cyclic logic
+         */
+        function isObject(value) {
+
+            if (typeof value === 'object' && value !== null &&
+                    !(value instanceof Boolean) &&
+                    !(value instanceof Date)    &&
+                    !(value instanceof Number)  &&
+                    !(value instanceof RegExp)  &&
+                    !(value instanceof String)) {
+
+                return true;
+            }
+
+            return false;
+        }
+
+        /**
+         * returns the index of the given object in the
+         * given objects array, -1 if not contained
+         * only needed for cyclic logic
+         */
+        function getIndex(objects, obj) {
+
+            var i;
+            for (i = 0; i < objects.length; i++) {
+                if (objects[i] === obj) {
+                    return i;
+                }
+            }
+
+            return -1;
+        }
+
+        // does the recursion for the deep equal check
+        return (function deepEqual(obj1, obj2, path1, path2) {
+            var type1 = typeof obj1;
+            var type2 = typeof obj2;
+
+            // == null also matches undefined
+            if (obj1 === obj2 ||
+                    isNaN(obj1) || isNaN(obj2) ||
+                    obj1 == null || obj2 == null ||
+                    type1 !== "object" || type2 !== "object") {
+
+                return identical(obj1, obj2);
+            }
+
+            // Elements are only equal if identical(expected, actual)
+            if (isElement(obj1) || isElement(obj2)) { return false; }
+
+            var isDate1 = isDate(obj1), isDate2 = isDate(obj2);
+            if (isDate1 || isDate2) {
+                if (!isDate1 || !isDate2 || obj1.getTime() !== obj2.getTime()) {
+                    return false;
+                }
+            }
+
+            if (obj1 instanceof RegExp && obj2 instanceof RegExp) {
+                if (obj1.toString() !== obj2.toString()) { return false; }
+            }
+
+            var class1 = getClass(obj1);
+            var class2 = getClass(obj2);
+            var keys1 = keys(obj1);
+            var keys2 = keys(obj2);
+
+            if (isArguments(obj1) || isArguments(obj2)) {
+                if (obj1.length !== obj2.length) { return false; }
+            } else {
+                if (type1 !== type2 || class1 !== class2 ||
+                        keys1.length !== keys2.length) {
+                    return false;
+                }
+            }
+
+            var key, i, l,
+                // following vars are used for the cyclic logic
+                value1, value2,
+                isObject1, isObject2,
+                index1, index2,
+                newPath1, newPath2;
+
+            for (i = 0, l = keys1.length; i < l; i++) {
+                key = keys1[i];
+                if (!o.hasOwnProperty.call(obj2, key)) {
+                    return false;
+                }
+
+                // Start of the cyclic logic
+
+                value1 = obj1[key];
+                value2 = obj2[key];
+
+                isObject1 = isObject(value1);
+                isObject2 = isObject(value2);
+
+                // determine, if the objects were already visited
+                // (it's faster to check for isObject first, than to
+                // get -1 from getIndex for non objects)
+                index1 = isObject1 ? getIndex(objects1, value1) : -1;
+                index2 = isObject2 ? getIndex(objects2, value2) : -1;
+
+                // determine the new pathes of the objects
+                // - for non cyclic objects the current path will be extended
+                //   by current property name
+                // - for cyclic objects the stored path is taken
+                newPath1 = index1 !== -1
+                    ? paths1[index1]
+                    : path1 + '[' + JSON.stringify(key) + ']';
+                newPath2 = index2 !== -1
+                    ? paths2[index2]
+                    : path2 + '[' + JSON.stringify(key) + ']';
+
+                // stop recursion if current objects are already compared
+                if (compared[newPath1 + newPath2]) {
+                    return true;
+                }
+
+                // remember the current objects and their pathes
+                if (index1 === -1 && isObject1) {
+                    objects1.push(value1);
+                    paths1.push(newPath1);
+                }
+                if (index2 === -1 && isObject2) {
+                    objects2.push(value2);
+                    paths2.push(newPath2);
+                }
+
+                // remember that the current objects are already compared
+                if (isObject1 && isObject2) {
+                    compared[newPath1 + newPath2] = true;
+                }
+
+                // End of cyclic logic
+
+                // neither value1 nor value2 is a cycle
+                // continue with next level
+                if (!deepEqual(value1, value2, newPath1, newPath2)) {
+                    return false;
+                }
+            }
+
+            return true;
+
+        }(obj1, obj2, '$1', '$2'));
+    }
+
+    var match;
+
+    function arrayContains(array, subset) {
+        if (subset.length === 0) { return true; }
+        var i, l, j, k;
+        for (i = 0, l = array.length; i < l; ++i) {
+            if (match(array[i], subset[0])) {
+                for (j = 0, k = subset.length; j < k; ++j) {
+                    if (!match(array[i + j], subset[j])) { return false; }
+                }
+                return true;
+            }
+        }
+        return false;
+    }
+
+    /**
+     * @name samsam.match
+     * @param Object object
+     * @param Object matcher
+     *
+     * Compare arbitrary value ``object`` with matcher.
+     */
+    match = function match(object, matcher) {
+        if (matcher && typeof matcher.test === "function") {
+            return matcher.test(object);
+        }
+
+        if (typeof matcher === "function") {
+            return matcher(object) === true;
+        }
+
+        if (typeof matcher === "string") {
+            matcher = matcher.toLowerCase();
+            var notNull = typeof object === "string" || !!object;
+            return notNull &&
+                (String(object)).toLowerCase().indexOf(matcher) >= 0;
+        }
+
+        if (typeof matcher === "number") {
+            return matcher === object;
+        }
+
+        if (typeof matcher === "boolean") {
+            return matcher === object;
+        }
+
+        if (getClass(object) === "Array" && getClass(matcher) === "Array") {
+            return arrayContains(object, matcher);
+        }
+
+        if (matcher && typeof matcher === "object") {
+            var prop;
+            for (prop in matcher) {
+                if (!match(object[prop], matcher[prop])) {
+                    return false;
+                }
+            }
+            return true;
+        }
+
+        throw new Error("Matcher was not a string, a number, a " +
+                        "function, a boolean or an object");
+    };
+
+    return {
+        isArguments: isArguments,
+        isElement: isElement,
+        isDate: isDate,
+        isNegZero: isNegZero,
+        identical: identical,
+        deepEqual: deepEqualCyclic,
+        match: match,
+        keys: keys
+    };
+});
+((typeof define === "function" && define.amd && function (m) {
+    define("formatio", ["samsam"], m);
+}) || (typeof module === "object" && function (m) {
+    module.exports = m(require("samsam"));
+}) || function (m) { this.formatio = m(this.samsam); }
+)(function (samsam) {
+    
+    var formatio = {
+        excludeConstructors: ["Object", /^.$/],
+        quoteStrings: true
+    };
+
+    var hasOwn = Object.prototype.hasOwnProperty;
+
+    var specialObjects = [];
+    if (typeof global !== "undefined") {
+        specialObjects.push({ object: global, value: "[object global]" });
+    }
+    if (typeof document !== "undefined") {
+        specialObjects.push({
+            object: document,
+            value: "[object HTMLDocument]"
+        });
+    }
+    if (typeof window !== "undefined") {
+        specialObjects.push({ object: window, value: "[object Window]" });
+    }
+
+    function functionName(func) {
+        if (!func) { return ""; }
+        if (func.displayName) { return func.displayName; }
+        if (func.name) { return func.name; }
+        var matches = func.toString().match(/function\s+([^\(]+)/m);
+        return (matches && matches[1]) || "";
+    }
+
+    function constructorName(f, object) {
+        var name = functionName(object && object.constructor);
+        var excludes = f.excludeConstructors ||
+                formatio.excludeConstructors || [];
+
+        var i, l;
+        for (i = 0, l = excludes.length; i < l; ++i) {
+            if (typeof excludes[i] === "string" && excludes[i] === name) {
+                return "";
+            } else if (excludes[i].test && excludes[i].test(name)) {
+                return "";
+            }
+        }
+
+        return name;
+    }
+
+    function isCircular(object, objects) {
+        if (typeof object !== "object") { return false; }
+        var i, l;
+        for (i = 0, l = objects.length; i < l; ++i) {
+            if (objects[i] === object) { return true; }
+        }
+        return false;
+    }
+
+    function ascii(f, object, processed, indent) {
+        if (typeof object === "string") {
+            var qs = f.quoteStrings;
+            var quote = typeof qs !== "boolean" || qs;
+            return processed || quote ? '"' + object + '"' : object;
+        }
+
+        if (typeof object === "function" && !(object instanceof RegExp)) {
+            return ascii.func(object);
+        }
+
+        processed = processed || [];
+
+        if (isCircular(object, processed)) { return "[Circular]"; }
+
+        if (Object.prototype.toString.call(object) === "[object Array]") {
+            return ascii.array.call(f, object, processed);
+        }
+
+        if (!object) { return String((1/object) === -Infinity ? "-0" : object); }
+        if (samsam.isElement(object)) { return ascii.element(object); }
+
+        if (typeof object.toString === "function" &&
+                object.toString !== Object.prototype.toString) {
+            return object.toString();
+        }
+
+        var i, l;
+        for (i = 0, l = specialObjects.length; i < l; i++) {
+            if (object === specialObjects[i].object) {
+                return specialObjects[i].value;
+            }
+        }
+
+        return ascii.object.call(f, object, processed, indent);
+    }
+
+    ascii.func = function (func) {
+        return "function " + functionName(func) + "() {}";
+    };
+
+    ascii.array = function (array, processed) {
+        processed = processed || [];
+        processed.push(array);
+        var i, l, pieces = [];
+        for (i = 0, l = array.length; i < l; ++i) {
+            pieces.push(ascii(this, array[i], processed));
+        }
+        return "[" + pieces.join(", ") + "]";
+    };
+
+    ascii.object = function (object, processed, indent) {
+        processed = processed || [];
+        processed.push(object);
+        indent = indent || 0;
+        var pieces = [], properties = samsam.keys(object).sort();
+        var length = 3;
+        var prop, str, obj, i, l;
+
+        for (i = 0, l = properties.length; i < l; ++i) {
+            prop = properties[i];
+            obj = object[prop];
+
+            if (isCircular(obj, processed)) {
+                str = "[Circular]";
+            } else {
+                str = ascii(this, obj, processed, indent + 2);
+            }
+
+            str = (/\s/.test(prop) ? '"' + prop + '"' : prop) + ": " + str;
+            length += str.length;
+            pieces.push(str);
+        }
+
+        var cons = constructorName(this, object);
+        var prefix = cons ? "[" + cons + "] " : "";
+        var is = "";
+        for (i = 0, l = indent; i < l; ++i) { is += " "; }
+
+        if (length + indent > 80) {
+            return prefix + "{\n  " + is + pieces.join(",\n  " + is) + "\n" +
+                is + "}";
+        }
+        return prefix + "{ " + pieces.join(", ") + " }";
+    };
+
+    ascii.element = function (element) {
+        var tagName = element.tagName.toLowerCase();
+        var attrs = element.attributes, attr, pairs = [], attrName, i, l, val;
+
+        for (i = 0, l = attrs.length; i < l; ++i) {
+            attr = attrs.item(i);
+            attrName = attr.nodeName.toLowerCase().replace("html:", "");
+            val = attr.nodeValue;
+            if (attrName !== "contenteditable" || val !== "inherit") {
+                if (!!val) { pairs.push(attrName + "=\"" + val + "\""); }
+            }
+        }
+
+        var formatted = "<" + tagName + (pairs.length > 0 ? " " : "");
+        var content = element.innerHTML;
+
+        if (content.length > 20) {
+            content = content.substr(0, 20) + "[...]";
+        }
+
+        var res = formatted + pairs.join(" ") + ">" + content +
+                "</" + tagName + ">";
+
+        return res.replace(/ contentEditable="inherit"/, "");
+    };
+
+    function Formatio(options) {
+        for (var opt in options) {
+            this[opt] = options[opt];
+        }
+    }
+
+    Formatio.prototype = {
+        functionName: functionName,
+
+        configure: function (options) {
+            return new Formatio(options);
+        },
+
+        constructorName: function (object) {
+            return constructorName(this, object);
+        },
+
+        ascii: function (object, processed, indent) {
+            return ascii(this, object, processed, indent);
+        }
+    };
+
+    return Formatio.prototype;
+});
+/*jslint eqeqeq: false, onevar: false, forin: true, nomen: false, regexp: false, plusplus: false*/
+/*global module, require, __dirname, document*/
+/**
+ * Sinon core utilities. For internal use only.
+ *
+ * @author Christian Johansen (christian@cjohansen.no)
+ * @license BSD
+ *
+ * Copyright (c) 2010-2013 Christian Johansen
+ */
+
+var sinon = (function (formatio) {
+    var div = typeof document != "undefined" && document.createElement("div");
+    var hasOwn = Object.prototype.hasOwnProperty;
+
+    function isDOMNode(obj) {
+        var success = false;
+
+        try {
+            obj.appendChild(div);
+            success = div.parentNode == obj;
+        } catch (e) {
+            return false;
+        } finally {
+            try {
+                obj.removeChild(div);
+            } catch (e) {
+                // Remove failed, not much we can do about that
+            }
+        }
+
+        return success;
+    }
+
+    function isElement(obj) {
+        return div && obj && obj.nodeType === 1 && isDOMNode(obj);
+    }
+
+    function isFunction(obj) {
+        return typeof obj === "function" || !!(obj && obj.constructor && obj.call && obj.apply);
+    }
+
+    function mirrorProperties(target, source) {
+        for (var prop in source) {
+            if (!hasOwn.call(target, prop)) {
+                target[prop] = source[prop];
+            }
+        }
+    }
+
+    function isRestorable (obj) {
+        return typeof obj === "function" && typeof obj.restore === "function" && obj.restore.sinon;
+    }
+
+    var sinon = {
+        wrapMethod: function wrapMethod(object, property, method) {
+            if (!object) {
+                throw new TypeError("Should wrap property of object");
+            }
+
+            if (typeof method != "function") {
+                throw new TypeError("Method wrapper should be function");
+            }
+
+            var wrappedMethod = object[property],
+                error;
+
+            if (!isFunction(wrappedMethod)) {
+                error = new TypeError("Attempted to wrap " + (typeof wrappedMethod) + " property " +
+                                    property + " as function");
+            }
+
+            if (wrappedMethod.restore && wrappedMethod.restore.sinon) {
+                error = new TypeError("Attempted to wrap " + property + " which is already wrapped");
+            }
+
+            if (wrappedMethod.calledBefore) {
+                var verb = !!wrappedMethod.returns ? "stubbed" : "spied on";
+                error = new TypeError("Attempted to wrap " + property + " which is already " + verb);
+            }
+
+            if (error) {
+                if (wrappedMethod._stack) {
+                    error.stack += '\n--------------\n' + wrappedMethod._stack;
+                }
+                throw error;
+            }
+
+            // IE 8 does not support hasOwnProperty on the window object and Firefox has a problem
+            // when using hasOwn.call on objects from other frames.
+            var owned = object.hasOwnProperty ? object.hasOwnProperty(property) : hasOwn.call(object, property);
+            object[property] = method;
+            method.displayName = property;
+            // Set up a stack trace which can be used later to find what line of
+            // code the original method was created on.
+            method._stack = (new Error('Stack Trace for original')).stack;
+
+            method.restore = function () {
+                // For prototype properties try to reset by delete first.
+                // If this fails (ex: localStorage on mobile safari) then force a reset
+                // via direct assignment.
+                if (!owned) {
+                    delete object[property];
+                }
+                if (object[property] === method) {
+                    object[property] = wrappedMethod;
+                }
+            };
+
+            method.restore.sinon = true;
+            mirrorProperties(method, wrappedMethod);
+
+            return method;
+        },
+
+        extend: function extend(target) {
+            for (var i = 1, l = arguments.length; i < l; i += 1) {
+                for (var prop in arguments[i]) {
+                    if (arguments[i].hasOwnProperty(prop)) {
+                        target[prop] = arguments[i][prop];
+                    }
+
+                    // DONT ENUM bug, only care about toString
+                    if (arguments[i].hasOwnProperty("toString") &&
+                        arguments[i].toString != target.toString) {
+                        target.toString = arguments[i].toString;
+                    }
+                }
+            }
+
+            return target;
+        },
+
+        create: function create(proto) {
+            var F = function () {};
+            F.prototype = proto;
+            return new F();
+        },
+
+        deepEqual: function deepEqual(a, b) {
+            if (sinon.match && sinon.match.isMatcher(a)) {
+                return a.test(b);
+            }
+            if (typeof a != "object" || typeof b != "object") {
+                return a === b;
+            }
+
+            if (isElement(a) || isElement(b)) {
+                return a === b;
+            }
+
+            if (a === b) {
+                return true;
+            }
+
+            if ((a === null && b !== null) || (a !== null && b === null)) {
+                return false;
+            }
+
+            if (a instanceof RegExp && b instanceof RegExp) {
+              return (a.source === b.source) && (a.global === b.global) && 
+                (a.ignoreCase === b.ignoreCase) && (a.multiline === b.multiline);
+            }
+
+            var aString = Object.prototype.toString.call(a);
+            if (aString != Object.prototype.toString.call(b)) {
+                return false;
+            }
+
+            if (aString == "[object Date]") {
+                return a.valueOf() === b.valueOf();
+            }
+
+            var prop, aLength = 0, bLength = 0;
+
+            if (aString == "[object Array]" && a.length !== b.length) {
+                return false;
+            }
+
+            for (prop in a) {
+                aLength += 1;
+
+                if (!deepEqual(a[prop], b[prop])) {
+                    return false;
+                }
+            }
+
+            for (prop in b) {
+                bLength += 1;
+            }
+
+            return aLength == bLength;
+        },
+
+        functionName: function functionName(func) {
+            var name = func.displayName || func.name;
+
+            // Use function decomposition as a last resort to get function
+            // name. Does not rely on function decomposition to work - if it
+            // doesn't debugging will be slightly less informative
+            // (i.e. toString will say 'spy' rather than 'myFunc').
+            if (!name) {
+                var matches = func.toString().match(/function ([^\s\(]+)/);
+                name = matches && matches[1];
+            }
+
+            return name;
+        },
+
+        functionToString: function toString() {
+            if (this.getCall && this.callCount) {
+                var thisValue, prop, i = this.callCount;
+
+                while (i--) {
+                    thisValue = this.getCall(i).thisValue;
+
+                    for (prop in thisValue) {
+                        if (thisValue[prop] === this) {
+                            return prop;
+                        }
+                    }
+                }
+            }
+
+            return this.displayName || "sinon fake";
+        },
+
+        getConfig: function (custom) {
+            var config = {};
+            custom = custom || {};
+            var defaults = sinon.defaultConfig;
+
+            for (var prop in defaults) {
+                if (defaults.hasOwnProperty(prop)) {
+                    config[prop] = custom.hasOwnProperty(prop) ? custom[prop] : defaults[prop];
+                }
+            }
+
+            return config;
+        },
+
+        format: function (val) {
+            return "" + val;
+        },
+
+        defaultConfig: {
+            injectIntoThis: true,
+            injectInto: null,
+            properties: ["spy", "stub", "mock", "clock", "server", "requests"],
+            useFakeTimers: true,
+            useFakeServer: true
+        },
+
+        timesInWords: function timesInWords(count) {
+            return count == 1 && "once" ||
+                count == 2 && "twice" ||
+                count == 3 && "thrice" ||
+                (count || 0) + " times";
+        },
+
+        calledInOrder: function (spies) {
+            for (var i = 1, l = spies.length; i < l; i++) {
+                if (!spies[i - 1].calledBefore(spies[i]) || !spies[i].called) {
+                    return false;
+                }
+            }
+
+            return true;
+        },
+
+        orderByFirstCall: function (spies) {
+            return spies.sort(function (a, b) {
+                // uuid, won't ever be equal
+                var aCall = a.getCall(0);
+                var bCall = b.getCall(0);
+                var aId = aCall && aCall.callId || -1;
+                var bId = bCall && bCall.callId || -1;
+
+                return aId < bId ? -1 : 1;
+            });
+        },
+
+        log: function () {},
+
+        logError: function (label, err) {
+            var msg = label + " threw exception: ";
+            sinon.log(msg + "[" + err.name + "] " + err.message);
+            if (err.stack) { sinon.log(err.stack); }
+
+            setTimeout(function () {
+                err.message = msg + err.message;
+                throw err;
+            }, 0);
+        },
+
+        typeOf: function (value) {
+            if (value === null) {
+                return "null";
+            }
+            else if (value === undefined) {
+                return "undefined";
+            }
+            var string = Object.prototype.toString.call(value);
+            return string.substring(8, string.length - 1).toLowerCase();
+        },
+
+        createStubInstance: function (constructor) {
+            if (typeof constructor !== "function") {
+                throw new TypeError("The constructor should be a function.");
+            }
+            return sinon.stub(sinon.create(constructor.prototype));
+        },
+
+        restore: function (object) {
+            if (object !== null && typeof object === "object") {
+                for (var prop in object) {
+                    if (isRestorable(object[prop])) {
+                        object[prop].restore();
+                    }
+                }
+            }
+            else if (isRestorable(object)) {
+                object.restore();
+            }
+        }
+    };
+
+    var isNode = typeof module !== "undefined" && module.exports;
+    var isAMD = typeof define === 'function' && typeof define.amd === 'object' && define.amd;
+
+    if (isAMD) {
+        define(function(){
+            return sinon;
+        });
+    } else if (isNode) {
+        try {
+            formatio = require("formatio");
+        } catch (e) {}
+        module.exports = sinon;
+        module.exports.spy = require("./sinon/spy");
+        module.exports.spyCall = require("./sinon/call");
+        module.exports.behavior = require("./sinon/behavior");
+        module.exports.stub = require("./sinon/stub");
+        module.exports.mock = require("./sinon/mock");
+        module.exports.collection = require("./sinon/collection");
+        module.exports.assert = require("./sinon/assert");
+        module.exports.sandbox = require("./sinon/sandbox");
+        module.exports.test = require("./sinon/test");
+        module.exports.testCase = require("./sinon/test_case");
+        module.exports.assert = require("./sinon/assert");
+        module.exports.match = require("./sinon/match");
+    }
+
+    if (formatio) {
+        var formatter = formatio.configure({ quoteStrings: false });
+        sinon.format = function () {
+            return formatter.ascii.apply(formatter, arguments);
+        };
+    } else if (isNode) {
+        try {
+            var util = require("util");
+            sinon.format = function (value) {
+                return typeof value == "object" && value.toString === Object.prototype.toString ? util.inspect(value) : value;
+            };
+        } catch (e) {
+            /* Node, but no util module - would be very old, but better safe than
+             sorry */
+        }
+    }
+
+    return sinon;
+}(typeof formatio == "object" && formatio));
+
+/* @depend ../sinon.js */
+/*jslint eqeqeq: false, onevar: false, plusplus: false*/
+/*global module, require, sinon*/
+/**
+ * Match functions
+ *
+ * @author Maximilian Antoni (mail@maxantoni.de)
+ * @license BSD
+ *
+ * Copyright (c) 2012 Maximilian Antoni
+ */
+
+(function (sinon) {
+    var commonJSModule = typeof module !== 'undefined' && module.exports;
+
+    if (!sinon && commonJSModule) {
+        sinon = require("../sinon");
+    }
+
+    if (!sinon) {
+        return;
+    }
+
+    function assertType(value, type, name) {
+        var actual = sinon.typeOf(value);
+        if (actual !== type) {
+            throw new TypeError("Expected type of " + name + " to be " +
+                type + ", but was " + actual);
+        }
+    }
+
+    var matcher = {
+        toString: function () {
+            return this.message;
+        }
+    };
+
+    function isMatcher(object) {
+        return matcher.isPrototypeOf(object);
+    }
+
+    function matchObject(expectation, actual) {
+        if (actual === null || actual === undefined) {
+            return false;
+        }
+        for (var key in expectation) {
+            if (expectation.hasOwnProperty(key)) {
+                var exp = expectation[key];
+                var act = actual[key];
+                if (match.isMatcher(exp)) {
+                    if (!exp.test(act)) {
+                        return false;
+                    }
+                } else if (sinon.typeOf(exp) === "object") {
+                    if (!matchObject(exp, act)) {
+                        return false;
+                    }
+                } else if (!sinon.deepEqual(exp, act)) {
+                    return false;
+                }
+            }
+        }
+        return true;
+    }
+
+    matcher.or = function (m2) {
+        if (!arguments.length) {
+            throw new TypeError("Matcher expected");
+        } else if (!isMatcher(m2)) {
+            m2 = match(m2);
+        }
+        var m1 = this;
+        var or = sinon.create(matcher);
+        or.test = function (actual) {
+            return m1.test(actual) || m2.test(actual);
+        };
+        or.message = m1.message + ".or(" + m2.message + ")";
+        return or;
+    };
+
+    matcher.and = function (m2) {
+        if (!arguments.length) {
+            throw new TypeError("Matcher expected");
+        } else if (!isMatcher(m2)) {
+            m2 = match(m2);
+        }
+        var m1 = this;
+        var and = sinon.create(matcher);
+        and.test = function (actual) {
+            return m1.test(actual) && m2.test(actual);
+        };
+        and.message = m1.message + ".and(" + m2.message + ")";
+        return and;
+    };
+
+    var match = function (expectation, message) {
+        var m = sinon.create(matcher);
+        var type = sinon.typeOf(expectation);
+        switch (type) {
+        case "object":
+            if (typeof expectation.test === "function") {
+                m.test = function (actual) {
+                    return expectation.test(actual) === true;
+                };
+                m.message = "match(" + sinon.functionName(expectation.test) + ")";
+                return m;
+            }
+            var str = [];
+            for (var key in expectation) {
+                if (expectation.hasOwnProperty(key)) {
+                    str.push(key + ": " + expectation[key]);
+                }
+            }
+            m.test = function (actual) {
+                return matchObject(expectation, actual);
+            };
+            m.message = "match(" + str.join(", ") + ")";
+            break;
+        case "number":
+            m.test = function (actual) {
+                return expectation == actual;
+            };
+            break;
+        case "string":
+            m.test = function (actual) {
+                if (typeof actual !== "string") {
+                    return false;
+                }
+                return actual.indexOf(expectation) !== -1;
+            };
+            m.message = "match(\"" + expectation + "\")";
+            break;
+        case "regexp":
+            m.test = function (actual) {
+                if (typeof actual !== "string") {
+                    return false;
+                }
+                return expectation.test(actual);
+            };
+            break;
+        case "function":
+            m.test = expectation;
+            if (message) {
+                m.message = message;
+            } else {
+                m.message = "match(" + sinon.functionName(expectation) + ")";
+            }
+            break;
+        default:
+            m.test = function (actual) {
+              return sinon.deepEqual(expectation, actual);
+            };
+        }
+        if (!m.message) {
+            m.message = "match(" + expectation + ")";
+        }
+        return m;
+    };
+
+    match.isMatcher = isMatcher;
+
+    match.any = match(function () {
+        return true;
+    }, "any");
+
+    match.defined = match(function (actual) {
+        return actual !== null && actual !== undefined;
+    }, "defined");
+
+    match.truthy = match(function (actual) {
+        return !!actual;
+    }, "truthy");
+
+    match.falsy = match(function (actual) {
+        return !actual;
+    }, "falsy");
+
+    match.same = function (expectation) {
+        return match(function (actual) {
+            return expectation === actual;
+        }, "same(" + expectation + ")");
+    };
+
+    match.typeOf = function (type) {
+        assertType(type, "string", "type");
+        return match(function (actual) {
+            return sinon.typeOf(actual) === type;
+        }, "typeOf(\"" + type + "\")");
+    };
+
+    match.instanceOf = function (type) {
+        assertType(type, "function", "type");
+        return match(function (actual) {
+            return actual instanceof type;
+        }, "instanceOf(" + sinon.functionName(type) + ")");
+    };
+
+    function createPropertyMatcher(propertyTest, messagePrefix) {
+        return function (property, value) {
+            assertType(property, "string", "property");
+            var onlyProperty = arguments.length === 1;
+            var message = messagePrefix + "(\"" + property + "\"";
+            if (!onlyProperty) {
+                message += ", " + value;
+            }
+            message += ")";
+            return match(function (actual) {
+                if (actual === undefined || actual === null ||
+                        !propertyTest(actual, property)) {
+                    return false;
+                }
+                return onlyProperty || sinon.deepEqual(value, actual[property]);
+            }, message);
+        };
+    }
+
+    match.has = createPropertyMatcher(function (actual, property) {
+        if (typeof actual === "object") {
+            return property in actual;
+        }
+        return actual[property] !== undefined;
+    }, "has");
+
+    match.hasOwn = createPropertyMatcher(function (actual, property) {
+        return actual.hasOwnProperty(property);
+    }, "hasOwn");
+
+    match.bool = match.typeOf("boolean");
+    match.number = match.typeOf("number");
+    match.string = match.typeOf("string");
+    match.object = match.typeOf("object");
+    match.func = match.typeOf("function");
+    match.array = match.typeOf("array");
+    match.regexp = match.typeOf("regexp");
+    match.date = match.typeOf("date");
+
+    if (commonJSModule) {
+        module.exports = match;
+    } else {
+        sinon.match = match;
+    }
+}(typeof sinon == "object" && sinon || null));
+
+/**
+  * @depend ../sinon.js
+  * @depend match.js
+  */
+/*jslint eqeqeq: false, onevar: false, plusplus: false*/
+/*global module, require, sinon*/
+/**
+  * Spy calls
+  *
+  * @author Christian Johansen (christian@cjohansen.no)
+  * @author Maximilian Antoni (mail@maxantoni.de)
+  * @license BSD
+  *
+  * Copyright (c) 2010-2013 Christian Johansen
+  * Copyright (c) 2013 Maximilian Antoni
+  */
+
+(function (sinon) {
+    var commonJSModule = typeof module !== 'undefined' && module.exports;
+    if (!sinon && commonJSModule) {
+        sinon = require("../sinon");
+    }
+
+    if (!sinon) {
+        return;
+    }
+
+    function throwYieldError(proxy, text, args) {
+        var msg = sinon.functionName(proxy) + text;
+        if (args.length) {
+            msg += " Received [" + slice.call(args).join(", ") + "]";
+        }
+        throw new Error(msg);
+    }
+
+    var slice = Array.prototype.slice;
+
+    var callProto = {
+        calledOn: function calledOn(thisValue) {
+            if (sinon.match && sinon.match.isMatcher(thisValue)) {
+                return thisValue.test(this.thisValue);
+            }
+            return this.thisValue === thisValue;
+        },
+
+        calledWith: function calledWith() {
+            for (var i = 0, l = arguments.length; i < l; i += 1) {
+                if (!sinon.deepEqual(arguments[i], this.args[i])) {
+                    return false;
+                }
+            }
+
+            return true;
+        },
+
+        calledWithMatch: function calledWithMatch() {
+            for (var i = 0, l = arguments.length; i < l; i += 1) {
+                var actual = this.args[i];
+                var expectation = arguments[i];
+                if (!sinon.match || !sinon.match(expectation).test(actual)) {
+                    return false;
+                }
+            }
+            return true;
+        },
+
+        calledWithExactly: function calledWithExactly() {
+            return arguments.length == this.args.length &&
+                this.calledWith.apply(this, arguments);
+        },
+
+        notCalledWith: function notCalledWith() {
+            return !this.calledWith.apply(this, arguments);
+        },
+
+        notCalledWithMatch: function notCalledWithMatch() {
+            return !this.calledWithMatch.apply(this, arguments);
+        },
+
+        returned: function returned(value) {
+            return sinon.deepEqual(value, this.returnValue);
+        },
+
+        threw: function threw(error) {
+            if (typeof error === "undefined" || !this.exception) {
+                return !!this.exception;
+            }
+
+            return this.exception === error || this.exception.name === error;
+        },
+
+        calledWithNew: function calledWithNew() {
+            return this.proxy.prototype && this.thisValue instanceof this.proxy;
+        },
+
+        calledBefore: function (other) {
+            return this.callId < other.callId;
+        },
+
+        calledAfter: function (other) {
+            return this.callId > other.callId;
+        },
+
+        callArg: function (pos) {
+            this.args[pos]();
+        },
+
+        callArgOn: function (pos, thisValue) {
+            this.args[pos].apply(thisValue);
+        },
+
+        callArgWith: function (pos) {
+            this.callArgOnWith.apply(this, [pos, null].concat(slice.call(arguments, 1)));
+        },
+
+        callArgOnWith: function (pos, thisValue) {
+            var args = slice.call(arguments, 2);
+            this.args[pos].apply(thisValue, args);
+        },
+
+        "yield": function () {
+            this.yieldOn.apply(this, [null].concat(slice.call(arguments, 0)));
+        },
+
+        yieldOn: function (thisValue) {
+            var args = this.args;
+            for (var i = 0, l = args.length; i < l; ++i) {
+                if (typeof args[i] === "function") {
+                    args[i].apply(thisValue, slice.call(arguments, 1));
+                    return;
+                }
+            }
+            throwYieldError(this.proxy, " cannot yield since no callback was passed.", args);
+        },
+
+        yieldTo: function (prop) {
+            this.yieldToOn.apply(this, [prop, null].concat(slice.call(arguments, 1)));
+        },
+
+        yieldToOn: function (prop, thisValue) {
+            var args = this.args;
+            for (var i = 0, l = args.length; i < l; ++i) {
+                if (args[i] && typeof args[i][prop] === "function") {
+                    args[i][prop].apply(thisValue, slice.call(arguments, 2));
+                    return;
+                }
+            }
+            throwYieldError(this.proxy, " cannot yield to '" + prop +
+                "' since no callback was passed.", args);
+        },
+
+        toString: function () {
+            var callStr = this.proxy.toString() + "(";
+            var args = [];
+
+            for (var i = 0, l = this.args.length; i < l; ++i) {
+                args.push(sinon.format(this.args[i]));
+            }
+
+            callStr = callStr + args.join(", ") + ")";
+
+            if (typeof this.returnValue != "undefined") {
+                callStr += " => " + sinon.format(this.returnValue);
+            }
+
+            if (this.exception) {
+                callStr += " !" + this.exception.name;
+
+                if (this.exception.message) {
+                    callStr += "(" + this.exception.message + ")";
+                }
+            }
+
+            return callStr;
+        }
+    };
+
+    callProto.invokeCallback = callProto.yield;
+
+    function createSpyCall(spy, thisValue, args, returnValue, exception, id) {
+        if (typeof id !== "number") {
+            throw new TypeError("Call id is not a number");
+        }
+        var proxyCall = sinon.create(callProto);
+        proxyCall.proxy = spy;
+        proxyCall.thisValue = thisValue;
+        proxyCall.args = args;
+        proxyCall.returnValue = returnValue;
+        proxyCall.exception = exception;
+        proxyCall.callId = id;
+
+        return proxyCall;
+    }
+    createSpyCall.toString = callProto.toString; // used by mocks
+
+    if (commonJSModule) {
+        module.exports = createSpyCall;
+    } else {
+        sinon.spyCall = createSpyCall;
+    }
+}(typeof sinon == "object" && sinon || null));
+
+
+/**
+  * @depend ../sinon.js
+  * @depend call.js
+  */
+/*jslint eqeqeq: false, onevar: false, plusplus: false*/
+/*global module, require, sinon*/
+/**
+  * Spy functions
+  *
+  * @author Christian Johansen (christian@cjohansen.no)
+  * @license BSD
+  *
+  * Copyright (c) 2010-2013 Christian Johansen
+  */
+
+(function (sinon) {
+    var commonJSModule = typeof module !== 'undefined' && module.exports;
+    var push = Array.prototype.push;
+    var slice = Array.prototype.slice;
+    var callId = 0;
+
+    if (!sinon && commonJSModule) {
+        sinon = require("../sinon");
+    }
+
+    if (!sinon) {
+        return;
+    }
+
+    function spy(object, property) {
+        if (!property && typeof object == "function") {
+            return spy.create(object);
+        }
+
+        if (!object && !property) {
+            return spy.create(function () { });
+        }
+
+        var method = object[property];
+        return sinon.wrapMethod(object, property, spy.create(method));
+    }
+
+    function matchingFake(fakes, args, strict) {
+        if (!fakes) {
+            return;
+        }
+
+        for (var i = 0, l = fakes.length; i < l; i++) {
+            if (fakes[i].matches(args, strict)) {
+                return fakes[i];
+            }
+        }
+    }
+
+    function incrementCallCount() {
+        this.called = true;
+        this.callCount += 1;
+        this.notCalled = false;
+        this.calledOnce = this.callCount == 1;
+        this.calledTwice = this.callCount == 2;
+        this.calledThrice = this.callCount == 3;
+    }
+
+    function createCallProperties() {
+        this.firstCall = this.getCall(0);
+        this.secondCall = this.getCall(1);
+        this.thirdCall = this.getCall(2);
+        this.lastCall = this.getCall(this.callCount - 1);
+    }
+
+    var vars = "a,b,c,d,e,f,g,h,i,j,k,l";
+    function createProxy(func) {
+        // Retain the function length:
+        var p;
+        if (func.length) {
+            eval("p = (function proxy(" + vars.substring(0, func.length * 2 - 1) +
+                ") { return p.invoke(func, this, slice.call(arguments)); });");
+        }
+        else {
+            p = function proxy() {
+                return p.invoke(func, this, slice.call(arguments));
+            };
+        }
+        return p;
+    }
+
+    var uuid = 0;
+
+    // Public API
+    var spyApi = {
+        reset: function () {
+            this.called = false;
+            this.notCalled = true;
+            this.calledOnce = false;
+            this.calledTwice = false;
+            this.calledThrice = false;
+            this.callCount = 0;
+            this.firstCall = null;
+            this.secondCall = null;
+            this.thirdCall = null;
+            this.lastCall = null;
+            this.args = [];
+            this.returnValues = [];
+            this.thisValues = [];
+            this.exceptions = [];
+            this.callIds = [];
+            if (this.fakes) {
+                for (var i = 0; i < this.fakes.length; i++) {
+                    this.fakes[i].reset();
+                }
+            }
+        },
+
+        create: function create(func) {
+            var name;
+
+            if (typeof func != "function") {
+                func = function () { };
+            } else {
+                name = sinon.functionName(func);
+            }
+
+            var proxy = createProxy(func);
+
+            sinon.extend(proxy, spy);
+            delete proxy.create;
+            sinon.extend(proxy, func);
+
+            proxy.reset();
+            proxy.prototype = func.prototype;
+            proxy.displayName = name || "spy";
+            proxy.toString = sinon.functionToString;
+            proxy._create = sinon.spy.create;
+            proxy.id = "spy#" + uuid++;
+
+            return proxy;
+        },
+
+        invoke: function invoke(func, thisValue, args) {
+            var matching = matchingFake(this.fakes, args);
+            var exception, returnValue;
+
+            incrementCallCount.call(this);
+            push.call(this.thisValues, thisValue);
+            push.call(this.args, args);
+            push.call(this.callIds, callId++);
+
+            try {
+                if (matching) {
+                    returnValue = matching.invoke(func, thisValue, args);
+                } else {
+                    returnValue = (this.func || func).apply(thisValue, args);
+                }
+
+                var thisCall = this.getCall(this.callCount - 1);
+                if (thisCall.calledWithNew() && typeof returnValue !== 'object') {
+                    returnValue = thisValue;
+                }
+            } catch (e) {
+                exception = e;
+            }
+
+            push.call(this.exceptions, exception);
+            push.call(this.returnValues, returnValue);
+
+            createCallProperties.call(this);
+
+            if (exception !== undefined) {
+                throw exception;
+            }
+
+            return returnValue;
+        },
+
+        getCall: function getCall(i) {
+            if (i < 0 || i >= this.callCount) {
+                return null;
+            }
+
+            return sinon.spyCall(this, this.thisValues[i], this.args[i],
+                                    this.returnValues[i], this.exceptions[i],
+                                    this.callIds[i]);
+        },
+
+        getCalls: function () {
+            var calls = [];
+            var i;
+
+            for (i = 0; i < this.callCount; i++) {
+                calls.push(this.getCall(i));
+            }
+
+            return calls;
+        },
+
+        calledBefore: function calledBefore(spyFn) {
+            if (!this.called) {
+                return false;
+            }
+
+            if (!spyFn.called) {
+                return true;
+            }
+
+            return this.callIds[0] < spyFn.callIds[spyFn.callIds.length - 1];
+        },
+
+        calledAfter: function calledAfter(spyFn) {
+            if (!this.called || !spyFn.called) {
+                return false;
+            }
+
+            return this.callIds[this.callCount - 1] > spyFn.callIds[spyFn.callCount - 1];
+        },
+
+        withArgs: function () {
+            var args = slice.call(arguments);
+
+            if (this.fakes) {
+                var match = matchingFake(this.fakes, args, true);
+
+                if (match) {
+                    return match;
+                }
+            } else {
+                this.fakes = [];
+            }
+
+            var original = this;
+            var fake = this._create();
+            fake.matchingAguments = args;
+            fake.parent = this;
+            push.call(this.fakes, fake);
+
+            fake.withArgs = function () {
+                return original.withArgs.apply(original, arguments);
+            };
+
+            for (var i = 0; i < this.args.length; i++) {
+                if (fake.matches(this.args[i])) {
+                    incrementCallCount.call(fake);
+                    push.call(fake.thisValues, this.thisValues[i]);
+                    push.call(fake.args, this.args[i]);
+                    push.call(fake.returnValues, this.returnValues[i]);
+                    push.call(fake.exceptions, this.exceptions[i]);
+                    push.call(fake.callIds, this.callIds[i]);
+                }
+            }
+            createCallProperties.call(fake);
+
+            return fake;
+        },
+
+        matches: function (args, strict) {
+            var margs = this.matchingAguments;
+
+            if (margs.length <= args.length &&
+                sinon.deepEqual(margs, args.slice(0, margs.length))) {
+                return !strict || margs.length == args.length;
+            }
+        },
+
+        printf: function (format) {
+            var spy = this;
+            var args = slice.call(arguments, 1);
+            var formatter;
+
+            return (format || "").replace(/%(.)/g, function (match, specifyer) {
+                formatter = spyApi.formatters[specifyer];
+
+                if (typeof formatter == "function") {
+                    return formatter.call(null, spy, args);
+                } else if (!isNaN(parseInt(specifyer, 10))) {
+                    return sinon.format(args[specifyer - 1]);
+                }
+
+                return "%" + specifyer;
+            });
+        }
+    };
+
+    function delegateToCalls(method, matchAny, actual, notCalled) {
+        spyApi[method] = function () {
+            if (!this.called) {
+                if (notCalled) {
+                    return notCalled.apply(this, arguments);
+                }
+                return false;
+            }
+
+            var currentCall;
+            var matches = 0;
+
+            for (var i = 0, l = this.callCount; i < l; i += 1) {
+                currentCall = this.getCall(i);
+
+                if (currentCall[actual || method].apply(currentCall, arguments)) {
+                    matches += 1;
+
+                    if (matchAny) {
+                        return true;
+                    }
+                }
+            }
+
+            return matches === this.callCount;
+        };
+    }
+
+    delegateToCalls("calledOn", true);
+    delegateToCalls("alwaysCalledOn", false, "calledOn");
+    delegateToCalls("calledWith", true);
+    delegateToCalls("calledWithMatch", true);
+    delegateToCalls("alwaysCalledWith", false, "calledWith");
+    delegateToCalls("alwaysCalledWithMatch", false, "calledWithMatch");
+    delegateToCalls("calledWithExactly", true);
+    delegateToCalls("alwaysCalledWithExactly", false, "calledWithExactly");
+    delegateToCalls("neverCalledWith", false, "notCalledWith",
+        function () { return true; });
+    delegateToCalls("neverCalledWithMatch", false, "notCalledWithMatch",
+        function () { return true; });
+    delegateToCalls("threw", true);
+    delegateToCalls("alwaysThrew", false, "threw");
+    delegateToCalls("returned", true);
+    delegateToCalls("alwaysReturned", false, "returned");
+    delegateToCalls("calledWithNew", true);
+    delegateToCalls("alwaysCalledWithNew", false, "calledWithNew");
+    delegateToCalls("callArg", false, "callArgWith", function () {
+        throw new Error(this.toString() + " cannot call arg since it was not yet invoked.");
+    });
+    spyApi.callArgWith = spyApi.callArg;
+    delegateToCalls("callArgOn", false, "callArgOnWith", function () {
+        throw new Error(this.toString() + " cannot call arg since it was not yet invoked.");
+    });
+    spyApi.callArgOnWith = spyApi.callArgOn;
+    delegateToCalls("yield", false, "yield", function () {
+        throw new Error(this.toString() + " cannot yield since it was not yet invoked.");
+    });
+    // "invokeCallback" is an alias for "yield" since "yield" is invalid in strict mode.
+    spyApi.invokeCallback = spyApi.yield;
+    delegateToCalls("yieldOn", false, "yieldOn", function () {
+        throw new Error(this.toString() + " cannot yield since it was not yet invoked.");
+    });
+    delegateToCalls("yieldTo", false, "yieldTo", function (property) {
+        throw new Error(this.toString() + " cannot yield to '" + property +
+            "' since it was not yet invoked.");
+    });
+    delegateToCalls("yieldToOn", false, "yieldToOn", function (property) {
+        throw new Error(this.toString() + " cannot yield to '" + property +
+            "' since it was not yet invoked.");
+    });
+
+    spyApi.formatters = {
+        "c": function (spy) {
+            return sinon.timesInWords(spy.callCount);
+        },
+
+        "n": function (spy) {
+            return spy.toString();
+        },
+
+        "C": function (spy) {
+            var calls = [];
+
+            for (var i = 0, l = spy.callCount; i < l; ++i) {
+                var stringifiedCall = "    " + spy.getCall(i).toString();
+                if (/\n/.test(calls[i - 1])) {
+                    stringifiedCall = "\n" + stringifiedCall;
+                }
+                push.call(calls, stringifiedCall);
+            }
+
+            return calls.length > 0 ? "\n" + calls.join("\n") : "";
+        },
+
+        "t": function (spy) {
+            var objects = [];
+
+            for (var i = 0, l = spy.callCount; i < l; ++i) {
+                push.call(objects, sinon.format(spy.thisValues[i]));
+            }
+
+            return objects.join(", ");
+        },
+
+        "*": function (spy, args) {
+            var formatted = [];
+
+            for (var i = 0, l = args.length; i < l; ++i) {
+                push.call(formatted, sinon.format(args[i]));
+            }
+
+            return formatted.join(", ");
+        }
+    };
+
+    sinon.extend(spy, spyApi);
+
+    spy.spyCall = sinon.spyCall;
+
+    if (commonJSModule) {
+        module.exports = spy;
+    } else {
+        sinon.spy = spy;
+    }
+}(typeof sinon == "object" && sinon || null));
+
+/**
+ * @depend ../sinon.js
+ */
+/*jslint eqeqeq: false, onevar: false*/
+/*global module, require, sinon, process, setImmediate, setTimeout*/
+/**
+ * Stub behavior
+ *
+ * @author Christian Johansen (christian@cjohansen.no)
+ * @author Tim Fischbach (mail@timfischbach.de)
+ * @license BSD
+ *
+ * Copyright (c) 2010-2013 Christian Johansen
+ */
+
+(function (sinon) {
+    var commonJSModule = typeof module !== 'undefined' && module.exports;
+
+    if (!sinon && commonJSModule) {
+        sinon = require("../sinon");
+    }
+
+    if (!sinon) {
+        return;
+    }
+
+    var slice = Array.prototype.slice;
+    var join = Array.prototype.join;
+    var proto;
+
+    var nextTick = (function () {
+        if (typeof process === "object" && typeof process.nextTick === "function") {
+            return process.nextTick;
+        } else if (typeof setImmediate === "function") {
+            return setImmediate;
+        } else {
+            return function (callback) {
+                setTimeout(callback, 0);
+            };
+        }
+    })();
+
+    function throwsException(error, message) {
+        if (typeof error == "string") {
+            this.exception = new Error(message || "");
+            this.exception.name = error;
+        } else if (!error) {
+            this.exception = new Error("Error");
+        } else {
+            this.exception = error;
+        }
+
+        return this;
+    }
+
+    function getCallback(behavior, args) {
+        var callArgAt = behavior.callArgAt;
+
+        if (callArgAt < 0) {
+            var callArgProp = behavior.callArgProp;
+
+            for (var i = 0, l = args.length; i < l; ++i) {
+                if (!callArgProp && typeof args[i] == "function") {
+                    return args[i];
+                }
+
+                if (callArgProp && args[i] &&
+                    typeof args[i][callArgProp] == "function") {
+                    return args[i][callArgProp];
+                }
+            }
+
+            return null;
+        }
+
+        return args[callArgAt];
+    }
+
+    function getCallbackError(behavior, func, args) {
+        if (behavior.callArgAt < 0) {
+            var msg;
+
+            if (behavior.callArgProp) {
+                msg = sinon.functionName(behavior.stub) +
+                    " expected to yield to '" + behavior.callArgProp +
+                    "', but no object with such a property was passed.";
+            } else {
+                msg = sinon.functionName(behavior.stub) +
+                    " expected to yield, but no callback was passed.";
+            }
+
+            if (args.length > 0) {
+                msg += " Received [" + join.call(args, ", ") + "]";
+            }
+
+            return msg;
+        }
+
+        return "argument at index " + behavior.callArgAt + " is not a function: " + func;
+    }
+
+    function callCallback(behavior, args) {
+        if (typeof behavior.callArgAt == "number") {
+            var func = getCallback(behavior, args);
+
+            if (typeof func != "function") {
+                throw new TypeError(getCallbackError(behavior, func, args));
+            }
+
+            if (behavior.callbackAsync) {
+                nextTick(function() {
+                    func.apply(behavior.callbackContext, behavior.callbackArguments);
+                });
+            } else {
+                func.apply(behavior.callbackContext, behavior.callbackArguments);
+            }
+        }
+    }
+
+    proto = {
+        create: function(stub) {
+            var behavior = sinon.extend({}, sinon.behavior);
+            delete behavior.create;
+            behavior.stub = stub;
+
+            return behavior;
+        },
+
+        isPresent: function() {
+            return (typeof this.callArgAt == 'number' ||
+                    this.exception ||
+                    typeof this.returnArgAt == 'number' ||
+                    this.returnThis ||
+                    this.returnValueDefined);
+        },
+
+        invoke: function(context, args) {
+            callCallback(this, args);
+
+            if (this.exception) {
+                throw this.exception;
+            } else if (typeof this.returnArgAt == 'number') {
+                return args[this.returnArgAt];
+            } else if (this.returnThis) {
+                return context;
+            }
+
+            return this.returnValue;
+        },
+
+        onCall: function(index) {
+            return this.stub.onCall(index);
+        },
+
+        onFirstCall: function() {
+            return this.stub.onFirstCall();
+        },
+
+        onSecondCall: function() {
+            return this.stub.onSecondCall();
+        },
+
+        onThirdCall: function() {
+            return this.stub.onThirdCall();
+        },
+
+        withArgs: function(/* arguments */) {
+            throw new Error('Defining a stub by invoking "stub.onCall(...).withArgs(...)" is not supported. ' +
+                            'Use "stub.withArgs(...).onCall(...)" to define sequential behavior for calls with certain arguments.');
+        },
+
+        callsArg: function callsArg(pos) {
+            if (typeof pos != "number") {
+                throw new TypeError("argument index is not number");
+            }
+
+            this.callArgAt = pos;
+            this.callbackArguments = [];
+            this.callbackContext = undefined;
+            this.callArgProp = undefined;
+            this.callbackAsync = false;
+
+            return this;
+        },
+
+        callsArgOn: function callsArgOn(pos, context) {
+            if (typeof pos != "number") {
+                throw new TypeError("argument index is not number");
+            }
+            if (typeof context != "object") {
+                throw new TypeError("argument context is not an object");
+            }
+
+            this.callArgAt = pos;
+            this.callbackArguments = [];
+            this.callbackContext = context;
+            this.callArgProp = undefined;
+            this.callbackAsync = false;
+
+            return this;
+        },
+
+        callsArgWith: function callsArgWith(pos) {
+            if (typeof pos != "number") {
+                throw new TypeError("argument index is not number");
+            }
+
+            this.callArgAt = pos;
+            this.callbackArguments = slice.call(arguments, 1);
+            this.callbackContext = undefined;
+            this.callArgProp = undefined;
+            this.callbackAsync = false;
+
+            return this;
+        },
+
+        callsArgOnWith: function callsArgWith(pos, context) {
+            if (typeof pos != "number") {
+                throw new TypeError("argument index is not number");
+            }
+            if (typeof context != "object") {
+                throw new TypeError("argument context is not an object");
+            }
+
+            this.callArgAt = pos;
+            this.callbackArguments = slice.call(arguments, 2);
+            this.callbackContext = context;
+            this.callArgProp = undefined;
+            this.callbackAsync = false;
+
+            return this;
+        },
+
+        yields: function () {
+            this.callArgAt = -1;
+            this.callbackArguments = slice.call(arguments, 0);
+            this.callbackContext = undefined;
+            this.callArgProp = undefined;
+            this.callbackAsync = false;
+
+            return this;
+        },
+
+        yieldsOn: function (context) {
+            if (typeof context != "object") {
+                throw new TypeError("argument context is not an object");
+            }
+
+            this.callArgAt = -1;
+            this.callbackArguments = slice.call(arguments, 1);
+            this.callbackContext = context;
+            this.callArgProp = undefined;
+            this.callbackAsync = false;
+
+            return this;
+        },
+
+        yieldsTo: function (prop) {
+            this.callArgAt = -1;
+            this.callbackArguments = slice.call(arguments, 1);
+            this.callbackContext = undefined;
+            this.callArgProp = prop;
+            this.callbackAsync = false;
+
+            return this;
+        },
+
+        yieldsToOn: function (prop, context) {
+            if (typeof context != "object") {
+                throw new TypeError("argument context is not an object");
+            }
+
+            this.callArgAt = -1;
+            this.callbackArguments = slice.call(arguments, 2);
+            this.callbackContext = context;
+            this.callArgProp = prop;
+            this.callbackAsync = false;
+
+            return this;
+        },
+
+
+        "throws": throwsException,
+        throwsException: throwsException,
+
+        returns: function returns(value) {
+            this.returnValue = value;
+            this.returnValueDefined = true;
+
+            return this;
+        },
+
+        returnsArg: function returnsArg(pos) {
+            if (typeof pos != "number") {
+                throw new TypeError("argument index is not number");
+            }
+
+            this.returnArgAt = pos;
+
+            return this;
+        },
+
+        returnsThis: function returnsThis() {
+            this.returnThis = true;
+
+            return this;
+        }
+    };
+
+    // create asynchronous versions of callsArg* and yields* methods
+    for (var method in proto) {
+        // need to avoid creating anotherasync versions of the newly added async methods
+        if (proto.hasOwnProperty(method) &&
+            method.match(/^(callsArg|yields)/) &&
+            !method.match(/Async/)) {
+            proto[method + 'Async'] = (function (syncFnName) {
+                return function () {
+                    var result = this[syncFnName].apply(this, arguments);
+                    this.callbackAsync = true;
+                    return result;
+                };
+            })(method);
+        }
+    }
+
+    if (commonJSModule) {
+        module.exports = proto;
+    } else {
+        sinon.behavior = proto;
+    }
+}(typeof sinon == "object" && sinon || null));
+/**
+ * @depend ../sinon.js
+ * @depend spy.js
+ * @depend behavior.js
+ */
+/*jslint eqeqeq: false, onevar: false*/
+/*global module, require, sinon*/
+/**
+ * Stub functions
+ *
+ * @author Christian Johansen (christian@cjohansen.no)
+ * @license BSD
+ *
+ * Copyright (c) 2010-2013 Christian Johansen
+ */
+
+(function (sinon) {
+    var commonJSModule = typeof module !== 'undefined' && module.exports;
+
+    if (!sinon && commonJSModule) {
+        sinon = require("../sinon");
+    }
+
+    if (!sinon) {
+        return;
+    }
+
+    function stub(object, property, func) {
+        if (!!func && typeof func != "function") {
+            throw new TypeError("Custom stub should be function");
+        }
+
+        var wrapper;
+
+        if (func) {
+            wrapper = sinon.spy && sinon.spy.create ? sinon.spy.create(func) : func;
+        } else {
+            wrapper = stub.create();
+        }
+
+        if (!object && typeof property === "undefined") {
+            return sinon.stub.create();
+        }
+
+        if (typeof property === "undefined" && typeof object == "object") {
+            for (var prop in object) {
+                if (typeof object[prop] === "function") {
+                    stub(object, prop);
+                }
+            }
+
+            return object;
+        }
+
+        return sinon.wrapMethod(object, property, wrapper);
+    }
+
+    function getDefaultBehavior(stub) {
+        return stub.defaultBehavior || getParentBehaviour(stub) || sinon.behavior.create(stub);
+    }
+
+    function getParentBehaviour(stub) {
+        return (stub.parent && getCurrentBehavior(stub.parent));
+    }
+
+    function getCurrentBehavior(stub) {
+        var behavior = stub.behaviors[stub.callCount - 1];
+        return behavior && behavior.isPresent() ? behavior : getDefaultBehavior(stub);
+    }
+
+    var uuid = 0;
+
+    sinon.extend(stub, (function () {
+        var proto = {
+            create: function create() {
+                var functionStub = function () {
+                    return getCurrentBehavior(functionStub).invoke(this, arguments);
+                };
+
+                functionStub.id = "stub#" + uuid++;
+                var orig = functionStub;
+                functionStub = sinon.spy.create(functionStub);
+                functionStub.func = orig;
+
+                sinon.extend(functionStub, stub);
+                functionStub._create = sinon.stub.create;
+                functionStub.displayName = "stub";
+                functionStub.toString = sinon.functionToString;
+
+                functionStub.defaultBehavior = null;
+                functionStub.behaviors = [];
+
+                return functionStub;
+            },
+
+            resetBehavior: function () {
+                var i;
+
+                this.defaultBehavior = null;
+                this.behaviors = [];
+
+                delete this.returnValue;
+                delete this.returnArgAt;
+                this.returnThis = false;
+
+                if (this.fakes) {
+                    for (i = 0; i < this.fakes.length; i++) {
+                        this.fakes[i].resetBehavior();
+                    }
+                }
+            },
+
+            onCall: function(index) {
+                if (!this.behaviors[index]) {
+                    this.behaviors[index] = sinon.behavior.create(this);
+                }
+
+                return this.behaviors[index];
+            },
+
+            onFirstCall: function() {
+                return this.onCall(0);
+            },
+
+            onSecondCall: function() {
+                return this.onCall(1);
+            },
+
+            onThirdCall: function() {
+                return this.onCall(2);
+            }
+        };
+
+        for (var method in sinon.behavior) {
+            if (sinon.behavior.hasOwnProperty(method) &&
+                !proto.hasOwnProperty(method) &&
+                method != 'create' &&
+                method != 'withArgs' &&
+                method != 'invoke') {
+                proto[method] = (function(behaviorMethod) {
+                    return function() {
+                        this.defaultBehavior = this.defaultBehavior || sinon.behavior.create(this);
+                        this.defaultBehavior[behaviorMethod].apply(this.defaultBehavior, arguments);
+                        return this;
+                    };
+                }(method));
+            }
+        }
+
+        return proto;
+    }()));
+
+    if (commonJSModule) {
+        module.exports = stub;
+    } else {
+        sinon.stub = stub;
+    }
+}(typeof sinon == "object" && sinon || null));
+
+/**
+ * @depend ../sinon.js
+ * @depend stub.js
+ */
+/*jslint eqeqeq: false, onevar: false, nomen: false*/
+/*global module, require, sinon*/
+/**
+ * Mock functions.
+ *
+ * @author Christian Johansen (christian@cjohansen.no)
+ * @license BSD
+ *
+ * Copyright (c) 2010-2013 Christian Johansen
+ */
+
+(function (sinon) {
+    var commonJSModule = typeof module !== 'undefined' && module.exports;
+    var push = [].push;
+    var match;
+
+    if (!sinon && commonJSModule) {
+        sinon = require("../sinon");
+    }
+
+    if (!sinon) {
+        return;
+    }
+
+    match = sinon.match;
+
+    if (!match && commonJSModule) {
+        match = require("./match");
+    }
+
+    function mock(object) {
+        if (!object) {
+            return sinon.expectation.create("Anonymous mock");
+        }
+
+        return mock.create(object);
+    }
+
+    sinon.mock = mock;
+
+    sinon.extend(mock, (function () {
+        function each(collection, callback) {
+            if (!collection) {
+                return;
+            }
+
+            for (var i = 0, l = collection.length; i < l; i += 1) {
+                callback(collection[i]);
+            }
+        }
+
+        return {
+            create: function create(object) {
+                if (!object) {
+                    throw new TypeError("object is null");
+                }
+
+                var mockObject = sinon.extend({}, mock);
+                mockObject.object = object;
+                delete mockObject.create;
+
+                return mockObject;
+            },
+
+            expects: function expects(method) {
+                if (!method) {
+                    throw new TypeError("method is falsy");
+                }
+
+                if (!this.expectations) {
+                    this.expectations = {};
+                    this.proxies = [];
+                }
+
+                if (!this.expectations[method]) {
+                    this.expectations[method] = [];
+                    var mockObject = this;
+
+                    sinon.wrapMethod(this.object, method, function () {
+                        return mockObject.invokeMethod(method, this, arguments);
+                    });
+
+                    push.call(this.proxies, method);
+                }
+
+                var expectation = sinon.expectation.create(method);
+                push.call(this.expectations[method], expectation);
+
+                return expectation;
+            },
+
+            restore: function restore() {
+                var object = this.object;
+
+                each(this.proxies, function (proxy) {
+                    if (typeof object[proxy].restore == "function") {
+                        object[proxy].restore();
+                    }
+                });
+            },
+
+            verify: function verify() {
+                var expectations = this.expectations || {};
+                var messages = [], met = [];
+
+                each(this.proxies, function (proxy) {
+                    each(expectations[proxy], function (expectation) {
+                        if (!expectation.met()) {
+                            push.call(messages, expectation.toString());
+                        } else {
+                            push.call(met, expectation.toString());
+                        }
+                    });
+                });
+
+                this.restore();
+
+                if (messages.length > 0) {
+                    sinon.expectation.fail(messages.concat(met).join("\n"));
+                } else {
+                    sinon.expectation.pass(messages.concat(met).join("\n"));
+                }
+
+                return true;
+            },
+
+            invokeMethod: function invokeMethod(method, thisValue, args) {
+                var expectations = this.expectations && this.expectations[method];
+                var length = expectations && expectations.length || 0, i;
+
+                for (i = 0; i < length; i += 1) {
+                    if (!expectations[i].met() &&
+                        expectations[i].allowsCall(thisValue, args)) {
+                        return expectations[i].apply(thisValue, args);
+                    }
+                }
+
+                var messages = [], available, exhausted = 0;
+
+                for (i = 0; i < length; i += 1) {
+                    if (expectations[i].allowsCall(thisValue, args)) {
+                        available = available || expectations[i];
+                    } else {
+                        exhausted += 1;
+                    }
+                    push.call(messages, "    " + expectations[i].toString());
+                }
+
+                if (exhausted === 0) {
+                    return available.apply(thisValue, args);
+                }
+
+                messages.unshift("Unexpected call: " + sinon.spyCall.toString.call({
+                    proxy: method,
+                    args: args
+                }));
+
+                sinon.expectation.fail(messages.join("\n"));
+            }
+        };
+    }()));
+
+    var times = sinon.timesInWords;
+
+    sinon.expectation = (function () {
+        var slice = Array.prototype.slice;
+        var _invoke = sinon.spy.invoke;
+
+        function callCountInWords(callCount) {
+            if (callCount == 0) {
+                return "never called";
+            } else {
+                return "called " + times(callCount);
+            }
+        }
+
+        function expectedCallCountInWords(expectation) {
+            var min = expectation.minCalls;
+            var max = expectation.maxCalls;
+
+            if (typeof min == "number" && typeof max == "number") {
+                var str = times(min);
+
+                if (min != max) {
+                    str = "at least " + str + " and at most " + times(max);
+                }
+
+                return str;
+            }
+
+            if (typeof min == "number") {
+                return "at least " + times(min);
+            }
+
+            return "at most " + times(max);
+        }
+
+        function receivedMinCalls(expectation) {
+            var hasMinLimit = typeof expectation.minCalls == "number";
+            return !hasMinLimit || expectation.callCount >= expectation.minCalls;
+        }
+
+        function receivedMaxCalls(expectation) {
+            if (typeof expectation.maxCalls != "number") {
+                return false;
+            }
+
+            return expectation.callCount == expectation.maxCalls;
+        }
+
+        function verifyMatcher(possibleMatcher, arg){
+            if (match && match.isMatcher(possibleMatcher)) {
+                return possibleMatcher.test(arg);
+            } else {
+                return true;
+            }
+        }
+
+        return {
+            minCalls: 1,
+            maxCalls: 1,
+
+            create: function create(methodName) {
+                var expectation = sinon.extend(sinon.stub.create(), sinon.expectation);
+                delete expectation.create;
+                expectation.method = methodName;
+
+                return expectation;
+            },
+
+            invoke: function invoke(func, thisValue, args) {
+                this.verifyCallAllowed(thisValue, args);
+
+                return _invoke.apply(this, arguments);
+            },
+
+            atLeast: function atLeast(num) {
+                if (typeof num != "number") {
+                    throw new TypeError("'" + num + "' is not number");
+                }
+
+                if (!this.limitsSet) {
+                    this.maxCalls = null;
+                    this.limitsSet = true;
+                }
+
+                this.minCalls = num;
+
+                return this;
+            },
+
+            atMost: function atMost(num) {
+                if (typeof num != "number") {
+                    throw new TypeError("'" + num + "' is not number");
+                }
+
+                if (!this.limitsSet) {
+                    this.minCalls = null;
+                    this.limitsSet = true;
+                }
+
+                this.maxCalls = num;
+
+                return this;
+            },
+
+            never: function never() {
+                return this.exactly(0);
+            },
+
+            once: function once() {
+                return this.exactly(1);
+            },
+
+            twice: function twice() {
+                return this.exactly(2);
+            },
+
+            thrice: function thrice() {
+                return this.exactly(3);
+            },
+
+            exactly: function exactly(num) {
+                if (typeof num != "number") {
+                    throw new TypeError("'" + num + "' is not a number");
+                }
+
+                this.atLeast(num);
+                return this.atMost(num);
+            },
+
+            met: function met() {
+                return !this.failed && receivedMinCalls(this);
+            },
+
+            verifyCallAllowed: function verifyCallAllowed(thisValue, args) {
+                if (receivedMaxCalls(this)) {
+                    this.failed = true;
+                    sinon.expectation.fail(this.method + " already called " + times(this.maxCalls));
+                }
+
+                if ("expectedThis" in this && this.expectedThis !== thisValue) {
+                    sinon.expectation.fail(this.method + " called with " + thisValue + " as thisValue, expected " +
+                        this.expectedThis);
+                }
+
+                if (!("expectedArguments" in this)) {
+                    return;
+                }
+
+                if (!args) {
+                    sinon.expectation.fail(this.method + " received no arguments, expected " +
+                        sinon.format(this.expectedArguments));
+                }
+
+                if (args.length < this.expectedArguments.length) {
+                    sinon.expectation.fail(this.method + " received too few arguments (" + sinon.format(args) +
+                        "), expected " + sinon.format(this.expectedArguments));
+                }
+
+                if (this.expectsExactArgCount &&
+                    args.length != this.expectedArguments.length) {
+                    sinon.expectation.fail(this.method + " received too many arguments (" + sinon.format(args) +
+                        "), expected " + sinon.format(this.expectedArguments));
+                }
+
+                for (var i = 0, l = this.expectedArguments.length; i < l; i += 1) {
+
+                    if (!verifyMatcher(this.expectedArguments[i],args[i])) {
+                        sinon.expectation.fail(this.method + " received wrong arguments " + sinon.format(args) +
+                            ", didn't match " + this.expectedArguments.toString());
+                    }
+
+                    if (!sinon.deepEqual(this.expectedArguments[i], args[i])) {
+                        sinon.expectation.fail(this.method + " received wrong arguments " + sinon.format(args) +
+                            ", expected " + sinon.format(this.expectedArguments));
+                    }
+                }
+            },
+
+            allowsCall: function allowsCall(thisValue, args) {
+                if (this.met() && receivedMaxCalls(this)) {
+                    return false;
+                }
+
+                if ("expectedThis" in this && this.expectedThis !== thisValue) {
+                    return false;
+                }
+
+                if (!("expectedArguments" in this)) {
+                    return true;
+                }
+
+                args = args || [];
+
+                if (args.length < this.expectedArguments.length) {
+                    return false;
+                }
+
+                if (this.expectsExactArgCount &&
+                    args.length != this.expectedArguments.length) {
+                    return false;
+                }
+
+                for (var i = 0, l = this.expectedArguments.length; i < l; i += 1) {
+                    if (!verifyMatcher(this.expectedArguments[i],args[i])) {
+                        return false;
+                    }
+
+                    if (!sinon.deepEqual(this.expectedArguments[i], args[i])) {
+                        return false;
+                    }
+                }
+
+                return true;
+            },
+
+            withArgs: function withArgs() {
+                this.expectedArguments = slice.call(arguments);
+                return this;
+            },
+
+            withExactArgs: function withExactArgs() {
+                this.withArgs.apply(this, arguments);
+                this.expectsExactArgCount = true;
+                return this;
+            },
+
+            on: function on(thisValue) {
+                this.expectedThis = thisValue;
+                return this;
+            },
+
+            toString: function () {
+                var args = (this.expectedArguments || []).slice();
+
+                if (!this.expectsExactArgCount) {
+                    push.call(args, "[...]");
+                }
+
+                var callStr = sinon.spyCall.toString.call({
+                    proxy: this.method || "anonymous mock expectation",
+                    args: args
+                });
+
+                var message = callStr.replace(", [...", "[, ...") + " " +
+                    expectedCallCountInWords(this);
+
+                if (this.met()) {
+                    return "Expectation met: " + message;
+                }
+
+                return "Expected " + message + " (" +
+                    callCountInWords(this.callCount) + ")";
+            },
+
+            verify: function verify() {
+                if (!this.met()) {
+                    sinon.expectation.fail(this.toString());
+                } else {
+                    sinon.expectation.pass(this.toString());
+                }
+
+                return true;
+            },
+
+            pass: function(message) {
+              sinon.assert.pass(message);
+            },
+            fail: function (message) {
+                var exception = new Error(message);
+                exception.name = "ExpectationError";
+
+                throw exception;
+            }
+        };
+    }());
+
+    if (commonJSModule) {
+        module.exports = mock;
+    } else {
+        sinon.mock = mock;
+    }
+}(typeof sinon == "object" && sinon || null));
+
+/**
+ * @depend ../sinon.js
+ * @depend stub.js
+ * @depend mock.js
+ */
+/*jslint eqeqeq: false, onevar: false, forin: true*/
+/*global module, require, sinon*/
+/**
+ * Collections of stubs, spies and mocks.
+ *
+ * @author Christian Johansen (christian@cjohansen.no)
+ * @license BSD
+ *
+ * Copyright (c) 2010-2013 Christian Johansen
+ */
+
+(function (sinon) {
+    var commonJSModule = typeof module !== 'undefined' && module.exports;
+    var push = [].push;
+    var hasOwnProperty = Object.prototype.hasOwnProperty;
+
+    if (!sinon && commonJSModule) {
+        sinon = require("../sinon");
+    }
+
+    if (!sinon) {
+        return;
+    }
+
+    function getFakes(fakeCollection) {
+        if (!fakeCollection.fakes) {
+            fakeCollection.fakes = [];
+        }
+
+        return fakeCollection.fakes;
+    }
+
+    function each(fakeCollection, method) {
+        var fakes = getFakes(fakeCollection);
+
+        for (var i = 0, l = fakes.length; i < l; i += 1) {
+            if (typeof fakes[i][method] == "function") {
+                fakes[i][method]();
+            }
+        }
+    }
+
+    function compact(fakeCollection) {
+        var fakes = getFakes(fakeCollection);
+        var i = 0;
+        while (i < fakes.length) {
+          fakes.splice(i, 1);
+        }
+    }
+
+    var collection = {
+        verify: function resolve() {
+            each(this, "verify");
+        },
+
+        restore: function restore() {
+            each(this, "restore");
+            compact(this);
+        },
+
+        verifyAndRestore: function verifyAndRestore() {
+            var exception;
+
+            try {
+                this.verify();
+            } catch (e) {
+                exception = e;
+            }
+
+            this.restore();
+
+            if (exception) {
+                throw exception;
+            }
+        },
+
+        add: function add(fake) {
+            push.call(getFakes(this), fake);
+            return fake;
+        },
+
+        spy: function spy() {
+            return this.add(sinon.spy.apply(sinon, arguments));
+        },
+
+        stub: function stub(object, property, value) {
+            if (property) {
+                var original = object[property];
+
+                if (typeof original != "function") {
+                    if (!hasOwnProperty.call(object, property)) {
+                        throw new TypeError("Cannot stub non-existent own property " + property);
+                    }
+
+                    object[property] = value;
+
+                    return this.add({
+                        restore: function () {
+                            object[property] = original;
+                        }
+                    });
+                }
+            }
+            if (!property && !!object && typeof object == "object") {
+                var stubbedObj = sinon.stub.apply(sinon, arguments);
+
+                for (var prop in stubbedObj) {
+                    if (typeof stubbedObj[prop] === "function") {
+                        this.add(stubbedObj[prop]);
+                    }
+                }
+
+                return stubbedObj;
+            }
+
+            return this.add(sinon.stub.apply(sinon, arguments));
+        },
+
+        mock: function mock() {
+            return this.add(sinon.mock.apply(sinon, arguments));
+        },
+
+        inject: function inject(obj) {
+            var col = this;
+
+            obj.spy = function () {
+                return col.spy.apply(col, arguments);
+            };
+
+            obj.stub = function () {
+                return col.stub.apply(col, arguments);
+            };
+
+            obj.mock = function () {
+                return col.mock.apply(col, arguments);
+            };
+
+            return obj;
+        }
+    };
+
+    if (commonJSModule) {
+        module.exports = collection;
+    } else {
+        sinon.collection = collection;
+    }
+}(typeof sinon == "object" && sinon || null));
+
+/*jslint eqeqeq: false, plusplus: false, evil: true, onevar: false, browser: true, forin: false*/
+/*global module, require, window*/
+/**
+ * Fake timer API
+ * setTimeout
+ * setInterval
+ * clearTimeout
+ * clearInterval
+ * tick
+ * reset
+ * Date
+ *
+ * Inspired by jsUnitMockTimeOut from JsUnit
+ *
+ * @author Christian Johansen (christian@cjohansen.no)
+ * @license BSD
+ *
+ * Copyright (c) 2010-2013 Christian Johansen
+ */
+
+if (typeof sinon == "undefined") {
+    var sinon = {};
+}
+
+(function (global) {
+    var id = 1;
+
+    function addTimer(args, recurring) {
+        if (args.length === 0) {
+            throw new Error("Function requires at least 1 parameter");
+        }
+
+        if (typeof args[0] === "undefined") {
+            throw new Error("Callback must be provided to timer calls");
+        }
+
+        var toId = id++;
+        var delay = args[1] || 0;
+
+        if (!this.timeouts) {
+            this.timeouts = {};
+        }
+
+        this.timeouts[toId] = {
+            id: toId,
+            func: args[0],
+            callAt: this.now + delay,
+            invokeArgs: Array.prototype.slice.call(args, 2)
+        };
+
+        if (recurring === true) {
+            this.timeouts[toId].interval = delay;
+        }
+
+        return toId;
+    }
+
+    function parseTime(str) {
+        if (!str) {
+            return 0;
+        }
+
+        var strings = str.split(":");
+        var l = strings.length, i = l;
+        var ms = 0, parsed;
+
+        if (l > 3 || !/^(\d\d:){0,2}\d\d?$/.test(str)) {
+            throw new Error("tick only understands numbers and 'h:m:s'");
+        }
+
+        while (i--) {
+            parsed = parseInt(strings[i], 10);
+
+            if (parsed >= 60) {
+                throw new Error("Invalid time " + str);
+            }
+
+            ms += parsed * Math.pow(60, (l - i - 1));
+        }
+
+        return ms * 1000;
+    }
+
+    function createObject(object) {
+        var newObject;
+
+        if (Object.create) {
+            newObject = Object.create(object);
+        } else {
+            var F = function () {};
+            F.prototype = object;
+            newObject = new F();
+        }
+
+        newObject.Date.clock = newObject;
+        return newObject;
+    }
+
+    sinon.clock = {
+        now: 0,
+
+        create: function create(now) {
+            var clock = createObject(this);
+
+            if (typeof now == "number") {
+                clock.now = now;
+            }
+
+            if (!!now && typeof now == "object") {
+                throw new TypeError("now should be milliseconds since UNIX epoch");
+            }
+
+            return clock;
+        },
+
+        setTimeout: function setTimeout(callback, timeout) {
+            return addTimer.call(this, arguments, false);
+        },
+
+        clearTimeout: function clearTimeout(timerId) {
+            if (!this.timeouts) {
+                this.timeouts = [];
+            }
+
+            if (timerId in this.timeouts) {
+                delete this.timeouts[timerId];
+            }
+        },
+
+        setInterval: function setInterval(callback, timeout) {
+            return addTimer.call(this, arguments, true);
+        },
+
+        clearInterval: function clearInterval(timerId) {
+            this.clearTimeout(timerId);
+        },
+
+        setImmediate: function setImmediate(callback) {
+            var passThruArgs = Array.prototype.slice.call(arguments, 1);
+
+            return addTimer.call(this, [callback, 0].concat(passThruArgs), false);
+        },
+
+        clearImmediate: function clearImmediate(timerId) {
+            this.clearTimeout(timerId);
+        },
+
+        tick: function tick(ms) {
+            ms = typeof ms == "number" ? ms : parseTime(ms);
+            var tickFrom = this.now, tickTo = this.now + ms, previous = this.now;
+            var timer = this.firstTimerInRange(tickFrom, tickTo);
+
+            var firstException;
+            while (timer && tickFrom <= tickTo) {
+                if (this.timeouts[timer.id]) {
+                    tickFrom = this.now = timer.callAt;
+                    try {
+                      this.callTimer(timer);
+                    } catch (e) {
+                      firstException = firstException || e;
+                    }
+                }
+
+                timer = this.firstTimerInRange(previous, tickTo);
+                previous = tickFrom;
+            }
+
+            this.now = tickTo;
+
+            if (firstException) {
+              throw firstException;
+            }
+
+            return this.now;
+        },
+
+        firstTimerInRange: function (from, to) {
+            var timer, smallest = null, originalTimer;
+
+            for (var id in this.timeouts) {
+                if (this.timeouts.hasOwnProperty(id)) {
+                    if (this.timeouts[id].callAt < from || this.timeouts[id].callAt > to) {
+                        continue;
+                    }
+
+                    if (smallest === null || this.timeouts[id].callAt < smallest) {
+                        originalTimer = this.timeouts[id];
+                        smallest = this.timeouts[id].callAt;
+
+                        timer = {
+                            func: this.timeouts[id].func,
+                            callAt: this.timeouts[id].callAt,
+                            interval: this.timeouts[id].interval,
+                            id: this.timeouts[id].id,
+                            invokeArgs: this.timeouts[id].invokeArgs
+                        };
+                    }
+                }
+            }
+
+            return timer || null;
+        },
+
+        callTimer: function (timer) {
+            if (typeof timer.interval == "number") {
+                this.timeouts[timer.id].callAt += timer.interval;
+            } else {
+                delete this.timeouts[timer.id];
+            }
+
+            try {
+                if (typeof timer.func == "function") {
+                    timer.func.apply(null, timer.invokeArgs);
+                } else {
+                    eval(timer.func);
+                }
+            } catch (e) {
+              var exception = e;
+            }
+
+            if (!this.timeouts[timer.id]) {
+                if (exception) {
+                  throw exception;
+                }
+                return;
+            }
+
+            if (exception) {
+              throw exception;
+            }
+        },
+
+        reset: function reset() {
+            this.timeouts = {};
+        },
+
+        Date: (function () {
+            var NativeDate = Date;
+
+            function ClockDate(year, month, date, hour, minute, second, ms) {
+                // Defensive and verbose to avoid potential harm in passing
+                // explicit undefined when user does not pass argument
+                switch (arguments.length) {
+                case 0:
+                    return new NativeDate(ClockDate.clock.now);
+                case 1:
+                    return new NativeDate(year);
+                case 2:
+                    return new NativeDate(year, month);
+                case 3:
+                    return new NativeDate(year, month, date);
+                case 4:
+                    return new NativeDate(year, month, date, hour);
+                case 5:
+                    return new NativeDate(year, month, date, hour, minute);
+                case 6:
+                    return new NativeDate(year, month, date, hour, minute, second);
+                default:
+                    return new NativeDate(year, month, date, hour, minute, second, ms);
+                }
+            }
+
+            return mirrorDateProperties(ClockDate, NativeDate);
+        }())
+    };
+
+    function mirrorDateProperties(target, source) {
+        if (source.now) {
+            target.now = function now() {
+                return target.clock.now;
+            };
+        } else {
+            delete target.now;
+        }
+
+        if (source.toSource) {
+            target.toSource = function toSource() {
+                return source.toSource();
+            };
+        } else {
+            delete target.toSource;
+        }
+
+        target.toString = function toString() {
+            return source.toString();
+        };
+
+        target.prototype = source.prototype;
+        target.parse = source.parse;
+        target.UTC = source.UTC;
+        target.prototype.toUTCString = source.prototype.toUTCString;
+
+        for (var prop in source) {
+            if (source.hasOwnProperty(prop)) {
+                target[prop] = source[prop];
+            }
+        }
+
+        return target;
+    }
+
+    var methods = ["Date", "setTimeout", "setInterval",
+                   "clearTimeout", "clearInterval"];
+
+    if (typeof global.setImmediate !== "undefined") {
+        methods.push("setImmediate");
+    }
+
+    if (typeof global.clearImmediate !== "undefined") {
+        methods.push("clearImmediate");
+    }
+
+    function restore() {
+        var method;
+
+        for (var i = 0, l = this.methods.length; i < l; i++) {
+            method = this.methods[i];
+
+            if (global[method].hadOwnProperty) {
+                global[method] = this["_" + method];
+            } else {
+                try {
+                    delete global[method];
+                } catch (e) {}
+            }
+        }
+
+        // Prevent multiple executions which will completely remove these props
+        this.methods = [];
+    }
+
+    function stubGlobal(method, clock) {
+        clock[method].hadOwnProperty = Object.prototype.hasOwnProperty.call(global, method);
+        clock["_" + method] = global[method];
+
+        if (method == "Date") {
+            var date = mirrorDateProperties(clock[method], global[method]);
+            global[method] = date;
+        } else {
+            global[method] = function () {
+                return clock[method].apply(clock, arguments);
+            };
+
+            for (var prop in clock[method]) {
+                if (clock[method].hasOwnProperty(prop)) {
+                    global[method][prop] = clock[method][prop];
+                }
+            }
+        }
+
+        global[method].clock = clock;
+    }
+
+    sinon.useFakeTimers = function useFakeTimers(now) {
+        var clock = sinon.clock.create(now);
+        clock.restore = restore;
+        clock.methods = Array.prototype.slice.call(arguments,
+                                                   typeof now == "number" ? 1 : 0);
+
+        if (clock.methods.length === 0) {
+            clock.methods = methods;
+        }
+
+        for (var i = 0, l = clock.methods.length; i < l; i++) {
+            stubGlobal(clock.methods[i], clock);
+        }
+
+        return clock;
+    };
+}(typeof global != "undefined" && typeof global !== "function" ? global : this));
+
+sinon.timers = {
+    setTimeout: setTimeout,
+    clearTimeout: clearTimeout,
+    setImmediate: (typeof setImmediate !== "undefined" ? setImmediate : undefined),
+    clearImmediate: (typeof clearImmediate !== "undefined" ? clearImmediate: undefined),
+    setInterval: setInterval,
+    clearInterval: clearInterval,
+    Date: Date
+};
+
+if (typeof module !== 'undefined' && module.exports) {
+    module.exports = sinon;
+}
+
+/*jslint eqeqeq: false, onevar: false*/
+/*global sinon, module, require, ActiveXObject, XMLHttpRequest, DOMParser*/
+/**
+ * Minimal Event interface implementation
+ *
+ * Original implementation by Sven Fuchs: https://gist.github.com/995028
+ * Modifications and tests by Christian Johansen.
+ *
+ * @author Sven Fuchs (svenfuchs@artweb-design.de)
+ * @author Christian Johansen (christian@cjohansen.no)
+ * @license BSD
+ *
+ * Copyright (c) 2011 Sven Fuchs, Christian Johansen
+ */
+
+if (typeof sinon == "undefined") {
+    this.sinon = {};
+}
+
+(function () {
+    var push = [].push;
+
+    sinon.Event = function Event(type, bubbles, cancelable, target) {
+        this.initEvent(type, bubbles, cancelable, target);
+    };
+
+    sinon.Event.prototype = {
+        initEvent: function(type, bubbles, cancelable, target) {
+            this.type = type;
+            this.bubbles = bubbles;
+            this.cancelable = cancelable;
+            this.target = target;
+        },
+
+        stopPropagation: function () {},
+
+        preventDefault: function () {
+            this.defaultPrevented = true;
+        }
+    };
+
+    sinon.ProgressEvent = function ProgressEvent(type, progressEventRaw, target) {
+        this.initEvent(type, false, false, target);
+        this.loaded = progressEventRaw.loaded || null;
+        this.total = progressEventRaw.total || null;
+    };
+
+    sinon.ProgressEvent.prototype = new sinon.Event();
+
+    sinon.ProgressEvent.prototype.constructor =  sinon.ProgressEvent;
+
+    sinon.CustomEvent = function CustomEvent(type, customData, target) {
+        this.initEvent(type, false, false, target);
+        this.detail = customData.detail || null;
+    };
+
+    sinon.CustomEvent.prototype = new sinon.Event();
+
+    sinon.CustomEvent.prototype.constructor =  sinon.CustomEvent;
+
+    sinon.EventTarget = {
+        addEventListener: function addEventListener(event, listener) {
+            this.eventListeners = this.eventListeners || {};
+            this.eventListeners[event] = this.eventListeners[event] || [];
+            push.call(this.eventListeners[event], listener);
+        },
+
+        removeEventListener: function removeEventListener(event, listener) {
+            var listeners = this.eventListeners && this.eventListeners[event] || [];
+
+            for (var i = 0, l = listeners.length; i < l; ++i) {
+                if (listeners[i] == listener) {
+                    return listeners.splice(i, 1);
+                }
+            }
+        },
+
+        dispatchEvent: function dispatchEvent(event) {
+            var type = event.type;
+            var listeners = this.eventListeners && this.eventListeners[type] || [];
+
+            for (var i = 0; i < listeners.length; i++) {
+                if (typeof listeners[i] == "function") {
+                    listeners[i].call(this, event);
+                } else {
+                    listeners[i].handleEvent(event);
+                }
+            }
+
+            return !!event.defaultPrevented;
+        }
+    };
+}());
+
+/**
+ * @depend ../../sinon.js
+ * @depend event.js
+ */
+/*jslint eqeqeq: false, onevar: false*/
+/*global sinon, module, require, ActiveXObject, XMLHttpRequest, DOMParser*/
+/**
+ * Fake XMLHttpRequest object
+ *
+ * @author Christian Johansen (christian@cjohansen.no)
+ * @license BSD
+ *
+ * Copyright (c) 2010-2013 Christian Johansen
+ */
+
+// wrapper for global
+(function(global) {
+    if (typeof sinon === "undefined") {
+        global.sinon = {};
+    }
+
+    var supportsProgress = typeof ProgressEvent !== "undefined";
+    var supportsCustomEvent = typeof CustomEvent !== "undefined";
+    sinon.xhr = { XMLHttpRequest: global.XMLHttpRequest };
+    var xhr = sinon.xhr;
+    xhr.GlobalXMLHttpRequest = global.XMLHttpRequest;
+    xhr.GlobalActiveXObject = global.ActiveXObject;
+    xhr.supportsActiveX = typeof xhr.GlobalActiveXObject != "undefined";
+    xhr.supportsXHR = typeof xhr.GlobalXMLHttpRequest != "undefined";
+    xhr.workingXHR = xhr.supportsXHR ? xhr.GlobalXMLHttpRequest : xhr.supportsActiveX
+                                     ? function() { return new xhr.GlobalActiveXObject("MSXML2.XMLHTTP.3.0") } : false;
+    xhr.supportsCORS = 'withCredentials' in (new sinon.xhr.GlobalXMLHttpRequest());
+
+    /*jsl:ignore*/
+    var unsafeHeaders = {
+        "Accept-Charset": true,
+        "Accept-Encoding": true,
+        "Connection": true,
+        "Content-Length": true,
+        "Cookie": true,
+        "Cookie2": true,
+        "Content-Transfer-Encoding": true,
+        "Date": true,
+        "Expect": true,
+        "Host": true,
+        "Keep-Alive": true,
+        "Referer": true,
+        "TE": true,
+        "Trailer": true,
+        "Transfer-Encoding": true,
+        "Upgrade": true,
+        "User-Agent": true,
+        "Via": true
+    };
+    /*jsl:end*/
+
+    function FakeXMLHttpRequest() {
+        this.readyState = FakeXMLHttpRequest.UNSENT;
+        this.requestHeaders = {};
+        this.requestBody = null;
+        this.status = 0;
+        this.statusText = "";
+        this.upload = new UploadProgress();
+        if (sinon.xhr.supportsCORS) {
+            this.withCredentials = false;
+        }
+
+
+        var xhr = this;
+        var events = ["loadstart", "load", "abort", "loadend"];
+
+        function addEventListener(eventName) {
+            xhr.addEventListener(eventName, function (event) {
+                var listener = xhr["on" + eventName];
+
+                if (listener && typeof listener == "function") {
+                    listener.call(this, event);
+                }
+            });
+        }
+
+        for (var i = events.length - 1; i >= 0; i--) {
+            addEventListener(events[i]);
+        }
+
+        if (typeof FakeXMLHttpRequest.onCreate == "function") {
+            FakeXMLHttpRequest.onCreate(this);
+        }
+    }
+
+    // An upload object is created for each
+    // FakeXMLHttpRequest and allows upload
+    // events to be simulated using uploadProgress
+    // and uploadError.
+    function UploadProgress() {
+        this.eventListeners = {
+            "progress": [],
+            "load": [],
+            "abort": [],
+            "error": []
+        }
+    }
+
+    UploadProgress.prototype.addEventListener = function(event, listener) {
+        this.eventListeners[event].push(listener);
+    };
+
+    UploadProgress.prototype.removeEventListener = function(event, listener) {
+        var listeners = this.eventListeners[event] || [];
+
+        for (var i = 0, l = listeners.length; i < l; ++i) {
+            if (listeners[i] == listener) {
+                return listeners.splice(i, 1);
+            }
+        }
+    };
+
+    UploadProgress.prototype.dispatchEvent = function(event) {
+        var listeners = this.eventListeners[event.type] || [];
+
+        for (var i = 0, listener; (listener = listeners[i]) != null; i++) {
+            listener(event);
+        }
+    };
+
+    function verifyState(xhr) {
+        if (xhr.readyState !== FakeXMLHttpRequest.OPENED) {
+            throw new Error("INVALID_STATE_ERR");
+        }
+
+        if (xhr.sendFlag) {
+            throw new Error("INVALID_STATE_ERR");
+        }
+    }
+
+    // filtering to enable a white-list version of Sinon FakeXhr,
+    // where whitelisted requests are passed through to real XHR
+    function each(collection, callback) {
+        if (!collection) return;
+        for (var i = 0, l = collection.length; i < l; i += 1) {
+            callback(collection[i]);
+        }
+    }
+    function some(collection, callback) {
+        for (var index = 0; index < collection.length; index++) {
+            if(callback(collection[index]) === true) return true;
+        }
+        return false;
+    }
+    // largest arity in XHR is 5 - XHR#open
+    var apply = function(obj,method,args) {
+        switch(args.length) {
+        case 0: return obj[method]();
+        case 1: return obj[method](args[0]);
+        case 2: return obj[method](args[0],args[1]);
+        case 3: return obj[method](args[0],args[1],args[2]);
+        case 4: return obj[method](args[0],args[1],args[2],args[3]);
+        case 5: return obj[method](args[0],args[1],args[2],args[3],args[4]);
+        }
+    };
+
+    FakeXMLHttpRequest.filters = [];
+    FakeXMLHttpRequest.addFilter = function(fn) {
+        this.filters.push(fn)
+    };
+    var IE6Re = /MSIE 6/;
+    FakeXMLHttpRequest.defake = function(fakeXhr,xhrArgs) {
+        var xhr = new sinon.xhr.workingXHR();
+        each(["open","setRequestHeader","send","abort","getResponseHeader",
+              "getAllResponseHeaders","addEventListener","overrideMimeType","removeEventListener"],
+             function(method) {
+                 fakeXhr[method] = function() {
+                   return apply(xhr,method,arguments);
+                 };
+             });
+
+        var copyAttrs = function(args) {
+            each(args, function(attr) {
+              try {
+                fakeXhr[attr] = xhr[attr]
+              } catch(e) {
+                if(!IE6Re.test(navigator.userAgent)) throw e;
+              }
+            });
+        };
+
+        var stateChange = function() {
+            fakeXhr.readyState = xhr.readyState;
+            if(xhr.readyState >= FakeXMLHttpRequest.HEADERS_RECEIVED) {
+                copyAttrs(["status","statusText"]);
+            }
+            if(xhr.readyState >= FakeXMLHttpRequest.LOADING) {
+                copyAttrs(["responseText"]);
+            }
+            if(xhr.readyState === FakeXMLHttpRequest.DONE) {
+                copyAttrs(["responseXML"]);
+            }
+            if(fakeXhr.onreadystatechange) fakeXhr.onreadystatechange.call(fakeXhr, { target: fakeXhr });
+        };
+        if(xhr.addEventListener) {
+          for(var event in fakeXhr.eventListeners) {
+              if(fakeXhr.eventListeners.hasOwnProperty(event)) {
+                  each(fakeXhr.eventListeners[event],function(handler) {
+                      xhr.addEventListener(event, handler);
+                  });
+              }
+          }
+          xhr.addEventListener("readystatechange",stateChange);
+        } else {
+          xhr.onreadystatechange = stateChange;
+        }
+        apply(xhr,"open",xhrArgs);
+    };
+    FakeXMLHttpRequest.useFilters = false;
+
+    function verifyRequestOpened(xhr) {
+        if (xhr.readyState != FakeXMLHttpRequest.OPENED) {
+            throw new Error("INVALID_STATE_ERR - " + xhr.readyState);
+        }
+    }
+
+    function verifyRequestSent(xhr) {
+        if (xhr.readyState == FakeXMLHttpRequest.DONE) {
+            throw new Error("Request done");
+        }
+    }
+
+    function verifyHeadersReceived(xhr) {
+        if (xhr.async && xhr.readyState != FakeXMLHttpRequest.HEADERS_RECEIVED) {
+            throw new Error("No headers received");
+        }
+    }
+
+    function verifyResponseBodyType(body) {
+        if (typeof body != "string") {
+            var error = new Error("Attempted to respond to fake XMLHttpRequest with " +
+                                 body + ", which is not a string.");
+            error.name = "InvalidBodyException";
+            throw error;
+        }
+    }
+
+    sinon.extend(FakeXMLHttpRequest.prototype, sinon.EventTarget, {
+        async: true,
+
+        open: function open(method, url, async, username, password) {
+            this.method = method;
+            this.url = url;
+            this.async = typeof async == "boolean" ? async : true;
+            this.username = username;
+            this.password = password;
+            this.responseText = null;
+            this.responseXML = null;
+            this.requestHeaders = {};
+            this.sendFlag = false;
+            if(sinon.FakeXMLHttpRequest.useFilters === true) {
+                var xhrArgs = arguments;
+                var defake = some(FakeXMLHttpRequest.filters,function(filter) {
+                    return filter.apply(this,xhrArgs)
+                });
+                if (defake) {
+                  return sinon.FakeXMLHttpRequest.defake(this,arguments);
+                }
+            }
+            this.readyStateChange(FakeXMLHttpRequest.OPENED);
+        },
+
+        readyStateChange: function readyStateChange(state) {
+            this.readyState = state;
+
+            if (typeof this.onreadystatechange == "function") {
+                try {
+                    this.onreadystatechange();
+                } catch (e) {
+                    sinon.logError("Fake XHR onreadystatechange handler", e);
+                }
+            }
+
+            this.dispatchEvent(new sinon.Event("readystatechange"));
+
+            switch (this.readyState) {
+                case FakeXMLHttpRequest.DONE:
+                    this.dispatchEvent(new sinon.Event("load", false, false, this));
+                    this.dispatchEvent(new sinon.Event("loadend", false, false, this));
+                    this.upload.dispatchEvent(new sinon.Event("load", false, false, this));
+                    if (supportsProgress) {
+                        this.upload.dispatchEvent(new sinon.ProgressEvent('progress', {loaded: 100, total: 100}));
+                    }
+                    break;
+            }
+        },
+
+        setRequestHeader: function setRequestHeader(header, value) {
+            verifyState(this);
+
+            if (unsafeHeaders[header] || /^(Sec-|Proxy-)/.test(header)) {
+                throw new Error("Refused to set unsafe header \"" + header + "\"");
+            }
+
+            if (this.requestHeaders[header]) {
+                this.requestHeaders[header] += "," + value;
+            } else {
+                this.requestHeaders[header] = value;
+            }
+        },
+
+        // Helps testing
+        setResponseHeaders: function setResponseHeaders(headers) {
+            verifyRequestOpened(this);
+            this.responseHeaders = {};
+
+            for (var header in headers) {
+                if (headers.hasOwnProperty(header)) {
+                    this.responseHeaders[header] = headers[header];
+                }
+            }
+
+            if (this.async) {
+                this.readyStateChange(FakeXMLHttpRequest.HEADERS_RECEIVED);
+            } else {
+                this.readyState = FakeXMLHttpRequest.HEADERS_RECEIVED;
+            }
+        },
+
+        // Currently treats ALL data as a DOMString (i.e. no Document)
+        send: function send(data) {
+            verifyState(this);
+
+            if (!/^(get|head)$/i.test(this.method)) {
+                if (this.requestHeaders["Content-Type"]) {
+                    var value = this.requestHeaders["Content-Type"].split(";");
+                    this.requestHeaders["Content-Type"] = value[0] + ";charset=utf-8";
+                } else {
+                    this.requestHeaders["Content-Type"] = "text/plain;charset=utf-8";
+                }
+
+                this.requestBody = data;
+            }
+
+            this.errorFlag = false;
+            this.sendFlag = this.async;
+            this.readyStateChange(FakeXMLHttpRequest.OPENED);
+
+            if (typeof this.onSend == "function") {
+                this.onSend(this);
+            }
+
+            this.dispatchEvent(new sinon.Event("loadstart", false, false, this));
+        },
+
+        abort: function abort() {
+            this.aborted = true;
+            this.responseText = null;
+            this.errorFlag = true;
+            this.requestHeaders = {};
+
+            if (this.readyState > sinon.FakeXMLHttpRequest.UNSENT && this.sendFlag) {
+                this.readyStateChange(sinon.FakeXMLHttpRequest.DONE);
+                this.sendFlag = false;
+            }
+
+            this.readyState = sinon.FakeXMLHttpRequest.UNSENT;
+
+            this.dispatchEvent(new sinon.Event("abort", false, false, this));
+
+            this.upload.dispatchEvent(new sinon.Event("abort", false, false, this));
+
+            if (typeof this.onerror === "function") {
+                this.onerror();
+            }
+        },
+
+        getResponseHeader: function getResponseHeader(header) {
+            if (this.readyState < FakeXMLHttpRequest.HEADERS_RECEIVED) {
+                return null;
+            }
+
+            if (/^Set-Cookie2?$/i.test(header)) {
+                return null;
+            }
+
+            header = header.toLowerCase();
+
+            for (var h in this.responseHeaders) {
+                if (h.toLowerCase() == header) {
+                    return this.responseHeaders[h];
+                }
+            }
+
+            return null;
+        },
+
+        getAllResponseHeaders: function getAllResponseHeaders() {
+            if (this.readyState < FakeXMLHttpRequest.HEADERS_RECEIVED) {
+                return "";
+            }
+
+            var headers = "";
+
+            for (var header in this.responseHeaders) {
+                if (this.responseHeaders.hasOwnProperty(header) &&
+                    !/^Set-Cookie2?$/i.test(header)) {
+                    headers += header + ": " + this.responseHeaders[header] + "\r\n";
+                }
+            }
+
+            return headers;
+        },
+
+        setResponseBody: function setResponseBody(body) {
+            verifyRequestSent(this);
+            verifyHeadersReceived(this);
+            verifyResponseBodyType(body);
+
+            var chunkSize = this.chunkSize || 10;
+            var index = 0;
+            this.responseText = "";
+
+            do {
+                if (this.async) {
+                    this.readyStateChange(FakeXMLHttpRequest.LOADING);
+                }
+
+                this.responseText += body.substring(index, index + chunkSize);
+                index += chunkSize;
+            } while (index < body.length);
+
+            var type = this.getResponseHeader("Content-Type");
+
+            if (this.responseText &&
+                (!type || /(text\/xml)|(application\/xml)|(\+xml)/.test(type))) {
+                try {
+                    this.responseXML = FakeXMLHttpRequest.parseXML(this.responseText);
+                } catch (e) {
+                    // Unable to parse XML - no biggie
+                }
+            }
+
+            if (this.async) {
+                this.readyStateChange(FakeXMLHttpRequest.DONE);
+            } else {
+                this.readyState = FakeXMLHttpRequest.DONE;
+            }
+        },
+
+        respond: function respond(status, headers, body) {
+            this.status = typeof status == "number" ? status : 200;
+            this.statusText = FakeXMLHttpRequest.statusCodes[this.status];
+            this.setResponseHeaders(headers || {});
+            this.setResponseBody(body || "");
+        },
+
+        uploadProgress: function uploadProgress(progressEventRaw) {
+            if (supportsProgress) {
+                this.upload.dispatchEvent(new sinon.ProgressEvent("progress", progressEventRaw));
+            }
+        },
+
+        uploadError: function uploadError(error) {
+            if (supportsCustomEvent) {
+                this.upload.dispatchEvent(new sinon.CustomEvent("error", {"detail": error}));
+            }
+        }
+    });
+
+    sinon.extend(FakeXMLHttpRequest, {
+        UNSENT: 0,
+        OPENED: 1,
+        HEADERS_RECEIVED: 2,
+        LOADING: 3,
+        DONE: 4
+    });
+
+    // Borrowed from JSpec
+    FakeXMLHttpRequest.parseXML = function parseXML(text) {
+        var xmlDoc;
+
+        if (typeof DOMParser != "undefined") {
+            var parser = new DOMParser();
+            xmlDoc = parser.parseFromString(text, "text/xml");
+        } else {
+            xmlDoc = new ActiveXObject("Microsoft.XMLDOM");
+            xmlDoc.async = "false";
+            xmlDoc.loadXML(text);
+        }
+
+        return xmlDoc;
+    };
+
+    FakeXMLHttpRequest.statusCodes = {
+        100: "Continue",
+        101: "Switching Protocols",
+        200: "OK",
+        201: "Created",
+        202: "Accepted",
+        203: "Non-Authoritative Information",
+        204: "No Content",
+        205: "Reset Content",
+        206: "Partial Content",
+        300: "Multiple Choice",
+        301: "Moved Permanently",
+        302: "Found",
+        303: "See Other",
+        304: "Not Modified",
+        305: "Use Proxy",
+        307: "Temporary Redirect",
+        400: "Bad Request",
+        401: "Unauthorized",
+        402: "Payment Required",
+        403: "Forbidden",
+        404: "Not Found",
+        405: "Method Not Allowed",
+        406: "Not Acceptable",
+        407: "Proxy Authentication Required",
+        408: "Request Timeout",
+        409: "Conflict",
+        410: "Gone",
+        411: "Length Required",
+        412: "Precondition Failed",
+        413: "Request Entity Too Large",
+        414: "Request-URI Too Long",
+        415: "Unsupported Media Type",
+        416: "Requested Range Not Satisfiable",
+        417: "Expectation Failed",
+        422: "Unprocessable Entity",
+        500: "Internal Server Error",
+        501: "Not Implemented",
+        502: "Bad Gateway",
+        503: "Service Unavailable",
+        504: "Gateway Timeout",
+        505: "HTTP Version Not Supported"
+    };
+
+    sinon.useFakeXMLHttpRequest = function () {
+        sinon.FakeXMLHttpRequest.restore = function restore(keepOnCreate) {
+            if (xhr.supportsXHR) {
+                global.XMLHttpRequest = xhr.GlobalXMLHttpRequest;
+            }
+
+            if (xhr.supportsActiveX) {
+                global.ActiveXObject = xhr.GlobalActiveXObject;
+            }
+
+            delete sinon.FakeXMLHttpRequest.restore;
+
+            if (keepOnCreate !== true) {
+                delete sinon.FakeXMLHttpRequest.onCreate;
+            }
+        };
+        if (xhr.supportsXHR) {
+            global.XMLHttpRequest = sinon.FakeXMLHttpRequest;
+        }
+
+        if (xhr.supportsActiveX) {
+            global.ActiveXObject = function ActiveXObject(objId) {
+                if (objId == "Microsoft.XMLHTTP" || /^Msxml2\.XMLHTTP/i.test(objId)) {
+
+                    return new sinon.FakeXMLHttpRequest();
+                }
+
+                return new xhr.GlobalActiveXObject(objId);
+            };
+        }
+
+        return sinon.FakeXMLHttpRequest;
+    };
+
+    sinon.FakeXMLHttpRequest = FakeXMLHttpRequest;
+
+})(typeof global === "object" ? global : this);
+
+if (typeof module !== 'undefined' && module.exports) {
+    module.exports = sinon;
+}
+
+/**
+ * @depend fake_xml_http_request.js
+ */
+/*jslint eqeqeq: false, onevar: false, regexp: false, plusplus: false*/
+/*global module, require, window*/
+/**
+ * The Sinon "server" mimics a web server that receives requests from
+ * sinon.FakeXMLHttpRequest and provides an API to respond to those requests,
+ * both synchronously and asynchronously. To respond synchronuously, canned
+ * answers have to be provided upfront.
+ *
+ * @author Christian Johansen (christian@cjohansen.no)
+ * @license BSD
+ *
+ * Copyright (c) 2010-2013 Christian Johansen
+ */
+
+if (typeof sinon == "undefined") {
+    var sinon = {};
+}
+
+sinon.fakeServer = (function () {
+    var push = [].push;
+    function F() {}
+
+    function create(proto) {
+        F.prototype = proto;
+        return new F();
+    }
+
+    function responseArray(handler) {
+        var response = handler;
+
+        if (Object.prototype.toString.call(handler) != "[object Array]") {
+            response = [200, {}, handler];
+        }
+
+        if (typeof response[2] != "string") {
+            throw new TypeError("Fake server response body should be string, but was " +
+                                typeof response[2]);
+        }
+
+        return response;
+    }
+
+    var wloc = typeof window !== "undefined" ? window.location : {};
+    var rCurrLoc = new RegExp("^" + wloc.protocol + "//" + wloc.host);
+
+    function matchOne(response, reqMethod, reqUrl) {
+        var rmeth = response.method;
+        var matchMethod = !rmeth || rmeth.toLowerCase() == reqMethod.toLowerCase();
+        var url = response.url;
+        var matchUrl = !url || url == reqUrl || (typeof url.test == "function" && url.test(reqUrl));
+
+        return matchMethod && matchUrl;
+    }
+
+    function match(response, request) {
+        var requestUrl = request.url;
+
+        if (!/^https?:\/\//.test(requestUrl) || rCurrLoc.test(requestUrl)) {
+            requestUrl = requestUrl.replace(rCurrLoc, "");
+        }
+
+        if (matchOne(response, this.getHTTPMethod(request), requestUrl)) {
+            if (typeof response.response == "function") {
+                var ru = response.url;
+                var args = [request].concat(ru && typeof ru.exec == "function" ? ru.exec(requestUrl).slice(1) : []);
+                return response.response.apply(response, args);
+            }
+
+            return true;
+        }
+
+        return false;
+    }
+
+    function log(response, request) {
+        var str;
+
+        str =  "Request:\n"  + sinon.format(request)  + "\n\n";
+        str += "Response:\n" + sinon.format(response) + "\n\n";
+
+        sinon.log(str);
+    }
+
+    return {
+        create: function () {
+            var server = create(this);
+            this.xhr = sinon.useFakeXMLHttpRequest();
+            server.requests = [];
+
+            this.xhr.onCreate = function (xhrObj) {
+                server.addRequest(xhrObj);
+            };
+
+            return server;
+        },
+
+        addRequest: function addRequest(xhrObj) {
+            var server = this;
+            push.call(this.requests, xhrObj);
+
+            xhrObj.onSend = function () {
+                server.handleRequest(this);
+
+                if (server.autoRespond && !server.responding) {
+                    setTimeout(function () {
+                        server.responding = false;
+                        server.respond();
+                    }, server.autoRespondAfter || 10);
+
+                    server.responding = true;
+                }
+            };
+        },
+
+        getHTTPMethod: function getHTTPMethod(request) {
+            if (this.fakeHTTPMethods && /post/i.test(request.method)) {
+                var matches = (request.requestBody || "").match(/_method=([^\b;]+)/);
+                return !!matches ? matches[1] : request.method;
+            }
+
+            return request.method;
+        },
+
+        handleRequest: function handleRequest(xhr) {
+            if (xhr.async) {
+                if (!this.queue) {
+                    this.queue = [];
+                }
+
+                push.call(this.queue, xhr);
+            } else {
+                this.processRequest(xhr);
+            }
+        },
+
+        respondWith: function respondWith(method, url, body) {
+            if (arguments.length == 1 && typeof method != "function") {
+                this.response = responseArray(method);
+                return;
+            }
+
+            if (!this.responses) { this.responses = []; }
+
+            if (arguments.length == 1) {
+                body = method;
+                url = method = null;
+            }
+
+            if (arguments.length == 2) {
+                body = url;
+                url = method;
+                method = null;
+            }
+
+            push.call(this.responses, {
+                method: method,
+                url: url,
+                response: typeof body == "function" ? body : responseArray(body)
+            });
+        },
+
+        respond: function respond() {
+            if (arguments.length > 0) this.respondWith.apply(this, arguments);
+            var queue = this.queue || [];
+            var requests = queue.splice(0);
+            var request;
+
+            while(request = requests.shift()) {
+                this.processRequest(request);
+            }
+        },
+
+        processRequest: function processRequest(request) {
+            try {
+                if (request.aborted) {
+                    return;
+                }
+
+                var response = this.response || [404, {}, ""];
+
+                if (this.responses) {
+                    for (var l = this.responses.length, i = l - 1; i >= 0; i--) {
+                        if (match.call(this, this.responses[i], request)) {
+                            response = this.responses[i].response;
+                            break;
+                        }
+                    }
+                }
+
+                if (request.readyState != 4) {
+                    log(response, request);
+
+                    request.respond(response[0], response[1], response[2]);
+                }
+            } catch (e) {
+                sinon.logError("Fake server request processing", e);
+            }
+        },
+
+        restore: function restore() {
+            return this.xhr.restore && this.xhr.restore.apply(this.xhr, arguments);
+        }
+    };
+}());
+
+if (typeof module !== 'undefined' && module.exports) {
+    module.exports = sinon;
+}
+
+/**
+ * @depend fake_server.js
+ * @depend fake_timers.js
+ */
+/*jslint browser: true, eqeqeq: false, onevar: false*/
+/*global sinon*/
+/**
+ * Add-on for sinon.fakeServer that automatically handles a fake timer along with
+ * the FakeXMLHttpRequest. The direct inspiration for this add-on is jQuery
+ * 1.3.x, which does not use xhr object's onreadystatehandler at all - instead,
+ * it polls the object for completion with setInterval. Dispite the direct
+ * motivation, there is nothing jQuery-specific in this file, so it can be used
+ * in any environment where the ajax implementation depends on setInterval or
+ * setTimeout.
+ *
+ * @author Christian Johansen (christian@cjohansen.no)
+ * @license BSD
+ *
+ * Copyright (c) 2010-2013 Christian Johansen
+ */
+
+(function () {
+    function Server() {}
+    Server.prototype = sinon.fakeServer;
+
+    sinon.fakeServerWithClock = new Server();
+
+    sinon.fakeServerWithClock.addRequest = function addRequest(xhr) {
+        if (xhr.async) {
+            if (typeof setTimeout.clock == "object") {
+                this.clock = setTimeout.clock;
+            } else {
+                this.clock = sinon.useFakeTimers();
+                this.resetClock = true;
+            }
+
+            if (!this.longestTimeout) {
+                var clockSetTimeout = this.clock.setTimeout;
+                var clockSetInterval = this.clock.setInterval;
+                var server = this;
+
+                this.clock.setTimeout = function (fn, timeout) {
+                    server.longestTimeout = Math.max(timeout, server.longestTimeout || 0);
+
+                    return clockSetTimeout.apply(this, arguments);
+                };
+
+                this.clock.setInterval = function (fn, timeout) {
+                    server.longestTimeout = Math.max(timeout, server.longestTimeout || 0);
+
+                    return clockSetInterval.apply(this, arguments);
+                };
+            }
+        }
+
+        return sinon.fakeServer.addRequest.call(this, xhr);
+    };
+
+    sinon.fakeServerWithClock.respond = function respond() {
+        var returnVal = sinon.fakeServer.respond.apply(this, arguments);
+
+        if (this.clock) {
+            this.clock.tick(this.longestTimeout || 0);
+            this.longestTimeout = 0;
+
+            if (this.resetClock) {
+                this.clock.restore();
+                this.resetClock = false;
+            }
+        }
+
+        return returnVal;
+    };
+
+    sinon.fakeServerWithClock.restore = function restore() {
+        if (this.clock) {
+            this.clock.restore();
+        }
+
+        return sinon.fakeServer.restore.apply(this, arguments);
+    };
+}());
+
+/**
+ * @depend ../sinon.js
+ * @depend collection.js
+ * @depend util/fake_timers.js
+ * @depend util/fake_server_with_clock.js
+ */
+/*jslint eqeqeq: false, onevar: false, plusplus: false*/
+/*global require, module*/
+/**
+ * Manages fake collections as well as fake utilities such as Sinon's
+ * timers and fake XHR implementation in one convenient object.
+ *
+ * @author Christian Johansen (christian@cjohansen.no)
+ * @license BSD
+ *
+ * Copyright (c) 2010-2013 Christian Johansen
+ */
+
+if (typeof module !== 'undefined' && module.exports) {
+    var sinon = require("../sinon");
+    sinon.extend(sinon, require("./util/fake_timers"));
+}
+
+(function () {
+    var push = [].push;
+
+    function exposeValue(sandbox, config, key, value) {
+        if (!value) {
+            return;
+        }
+
+        if (config.injectInto && !(key in config.injectInto)) {
+            config.injectInto[key] = value;
+            sandbox.injectedKeys.push(key);
+        } else {
+            push.call(sandbox.args, value);
+        }
+    }
+
+    function prepareSandboxFromConfig(config) {
+        var sandbox = sinon.create(sinon.sandbox);
+
+        if (config.useFakeServer) {
+            if (typeof config.useFakeServer == "object") {
+                sandbox.serverPrototype = config.useFakeServer;
+            }
+
+            sandbox.useFakeServer();
+        }
+
+        if (config.useFakeTimers) {
+            if (typeof config.useFakeTimers == "object") {
+                sandbox.useFakeTimers.apply(sandbox, config.useFakeTimers);
+            } else {
+                sandbox.useFakeTimers();
+            }
+        }
+
+        return sandbox;
+    }
+
+    sinon.sandbox = sinon.extend(sinon.create(sinon.collection), {
+        useFakeTimers: function useFakeTimers() {
+            this.clock = sinon.useFakeTimers.apply(sinon, arguments);
+
+            return this.add(this.clock);
+        },
+
+        serverPrototype: sinon.fakeServer,
+
+        useFakeServer: function useFakeServer() {
+            var proto = this.serverPrototype || sinon.fakeServer;
+
+            if (!proto || !proto.create) {
+                return null;
+            }
+
+            this.server = proto.create();
+            return this.add(this.server);
+        },
+
+        inject: function (obj) {
+            sinon.collection.inject.call(this, obj);
+
+            if (this.clock) {
+                obj.clock = this.clock;
+            }
+
+            if (this.server) {
+                obj.server = this.server;
+                obj.requests = this.server.requests;
+            }
+
+            return obj;
+        },
+
+        restore: function () {
+            sinon.collection.restore.apply(this, arguments);
+            this.restoreContext();
+        },
+
+        restoreContext: function () {
+            if (this.injectedKeys) {
+                for (var i = 0, j = this.injectedKeys.length; i < j; i++) {
+                    delete this.injectInto[this.injectedKeys[i]];
+                }
+                this.injectedKeys = [];
+            }
+        },
+
+        create: function (config) {
+            if (!config) {
+                return sinon.create(sinon.sandbox);
+            }
+
+            var sandbox = prepareSandboxFromConfig(config);
+            sandbox.args = sandbox.args || [];
+            sandbox.injectedKeys = [];
+            sandbox.injectInto = config.injectInto;
+            var prop, value, exposed = sandbox.inject({});
+
+            if (config.properties) {
+                for (var i = 0, l = config.properties.length; i < l; i++) {
+                    prop = config.properties[i];
+                    value = exposed[prop] || prop == "sandbox" && sandbox;
+                    exposeValue(sandbox, config, prop, value);
+                }
+            } else {
+                exposeValue(sandbox, config, "sandbox", value);
+            }
+
+            return sandbox;
+        }
+    });
+
+    sinon.sandbox.useFakeXMLHttpRequest = sinon.sandbox.useFakeServer;
+
+    if (typeof module !== 'undefined' && module.exports) {
+        module.exports = sinon.sandbox;
+    }
+}());
+
+/**
+ * @depend ../sinon.js
+ * @depend stub.js
+ * @depend mock.js
+ * @depend sandbox.js
+ */
+/*jslint eqeqeq: false, onevar: false, forin: true, plusplus: false*/
+/*global module, require, sinon*/
+/**
+ * Test function, sandboxes fakes
+ *
+ * @author Christian Johansen (christian@cjohansen.no)
+ * @license BSD
+ *
+ * Copyright (c) 2010-2013 Christian Johansen
+ */
+
+(function (sinon) {
+    var commonJSModule = typeof module !== 'undefined' && module.exports;
+
+    if (!sinon && commonJSModule) {
+        sinon = require("../sinon");
+    }
+
+    if (!sinon) {
+        return;
+    }
+
+    function test(callback) {
+        var type = typeof callback;
+
+        if (type != "function") {
+            throw new TypeError("sinon.test needs to wrap a test function, got " + type);
+        }
+
+        return function () {
+            var config = sinon.getConfig(sinon.config);
+            config.injectInto = config.injectIntoThis && this || config.injectInto;
+            var sandbox = sinon.sandbox.create(config);
+            var exception, result;
+            var args = Array.prototype.slice.call(arguments).concat(sandbox.args);
+
+            try {
+                result = callback.apply(this, args);
+            } catch (e) {
+                exception = e;
+            }
+
+            if (typeof exception !== "undefined") {
+                sandbox.restore();
+                throw exception;
+            }
+            else {
+                sandbox.verifyAndRestore();
+            }
+
+            return result;
+        };
+    }
+
+    test.config = {
+        injectIntoThis: true,
+        injectInto: null,
+        properties: ["spy", "stub", "mock", "clock", "server", "requests"],
+        useFakeTimers: true,
+        useFakeServer: true
+    };
+
+    if (commonJSModule) {
+        module.exports = test;
+    } else {
+        sinon.test = test;
+    }
+}(typeof sinon == "object" && sinon || null));
+
+/**
+ * @depend ../sinon.js
+ * @depend test.js
+ */
+/*jslint eqeqeq: false, onevar: false, eqeqeq: false*/
+/*global module, require, sinon*/
+/**
+ * Test case, sandboxes all test functions
+ *
+ * @author Christian Johansen (christian@cjohansen.no)
+ * @license BSD
+ *
+ * Copyright (c) 2010-2013 Christian Johansen
+ */
+
+(function (sinon) {
+    var commonJSModule = typeof module !== 'undefined' && module.exports;
+
+    if (!sinon && commonJSModule) {
+        sinon = require("../sinon");
+    }
+
+    if (!sinon || !Object.prototype.hasOwnProperty) {
+        return;
+    }
+
+    function createTest(property, setUp, tearDown) {
+        return function () {
+            if (setUp) {
+                setUp.apply(this, arguments);
+            }
+
+            var exception, result;
+
+            try {
+                result = property.apply(this, arguments);
+            } catch (e) {
+                exception = e;
+            }
+
+            if (tearDown) {
+                tearDown.apply(this, arguments);
+            }
+
+            if (exception) {
+                throw exception;
+            }
+
+            return result;
+        };
+    }
+
+    function testCase(tests, prefix) {
+        /*jsl:ignore*/
+        if (!tests || typeof tests != "object") {
+            throw new TypeError("sinon.testCase needs an object with test functions");
+        }
+        /*jsl:end*/
+
+        prefix = prefix || "test";
+        var rPrefix = new RegExp("^" + prefix);
+        var methods = {}, testName, property, method;
+        var setUp = tests.setUp;
+        var tearDown = tests.tearDown;
+
+        for (testName in tests) {
+            if (tests.hasOwnProperty(testName)) {
+                property = tests[testName];
+
+                if (/^(setUp|tearDown)$/.test(testName)) {
+                    continue;
+                }
+
+                if (typeof property == "function" && rPrefix.test(testName)) {
+                    method = property;
+
+                    if (setUp || tearDown) {
+                        method = createTest(property, setUp, tearDown);
+                    }
+
+                    methods[testName] = sinon.test(method);
+                } else {
+                    methods[testName] = tests[testName];
+                }
+            }
+        }
+
+        return methods;
+    }
+
+    if (commonJSModule) {
+        module.exports = testCase;
+    } else {
+        sinon.testCase = testCase;
+    }
+}(typeof sinon == "object" && sinon || null));
+
+/**
+ * @depend ../sinon.js
+ * @depend stub.js
+ */
+/*jslint eqeqeq: false, onevar: false, nomen: false, plusplus: false*/
+/*global module, require, sinon*/
+/**
+ * Assertions matching the test spy retrieval interface.
+ *
+ * @author Christian Johansen (christian@cjohansen.no)
+ * @license BSD
+ *
+ * Copyright (c) 2010-2013 Christian Johansen
+ */
+
+(function (sinon, global) {
+    var commonJSModule = typeof module !== "undefined" && module.exports;
+    var slice = Array.prototype.slice;
+    var assert;
+
+    if (!sinon && commonJSModule) {
+        sinon = require("../sinon");
+    }
+
+    if (!sinon) {
+        return;
+    }
+
+    function verifyIsStub() {
+        var method;
+
+        for (var i = 0, l = arguments.length; i < l; ++i) {
+            method = arguments[i];
+
+            if (!method) {
+                assert.fail("fake is not a spy");
+            }
+
+            if (typeof method != "function") {
+                assert.fail(method + " is not a function");
+            }
+
+            if (typeof method.getCall != "function") {
+                assert.fail(method + " is not stubbed");
+            }
+        }
+    }
+
+    function failAssertion(object, msg) {
+        object = object || global;
+        var failMethod = object.fail || assert.fail;
+        failMethod.call(object, msg);
+    }
+
+    function mirrorPropAsAssertion(name, method, message) {
+        if (arguments.length == 2) {
+            message = method;
+            method = name;
+        }
+
+        assert[name] = function (fake) {
+            verifyIsStub(fake);
+
+            var args = slice.call(arguments, 1);
+            var failed = false;
+
+            if (typeof method == "function") {
+                failed = !method(fake);
+            } else {
+                failed = typeof fake[method] == "function" ?
+                    !fake[method].apply(fake, args) : !fake[method];
+            }
+
+            if (failed) {
+                failAssertion(this, fake.printf.apply(fake, [message].concat(args)));
+            } else {
+                assert.pass(name);
+            }
+        };
+    }
+
+    function exposedName(prefix, prop) {
+        return !prefix || /^fail/.test(prop) ? prop :
+            prefix + prop.slice(0, 1).toUpperCase() + prop.slice(1);
+    }
+
+    assert = {
+        failException: "AssertError",
+
+        fail: function fail(message) {
+            var error = new Error(message);
+            error.name = this.failException || assert.failException;
+
+            throw error;
+        },
+
+        pass: function pass(assertion) {},
+
+        callOrder: function assertCallOrder() {
+            verifyIsStub.apply(null, arguments);
+            var expected = "", actual = "";
+
+            if (!sinon.calledInOrder(arguments)) {
+                try {
+                    expected = [].join.call(arguments, ", ");
+                    var calls = slice.call(arguments);
+                    var i = calls.length;
+                    while (i) {
+                        if (!calls[--i].called) {
+                            calls.splice(i, 1);
+                        }
+                    }
+                    actual = sinon.orderByFirstCall(calls).join(", ");
+                } catch (e) {
+                    // If this fails, we'll just fall back to the blank string
+                }
+
+                failAssertion(this, "expected " + expected + " to be " +
+                              "called in order but were called as " + actual);
+            } else {
+                assert.pass("callOrder");
+            }
+        },
+
+        callCount: function assertCallCount(method, count) {
+            verifyIsStub(method);
+
+            if (method.callCount != count) {
+                var msg = "expected %n to be called " + sinon.timesInWords(count) +
+                    " but was called %c%C";
+                failAssertion(this, method.printf(msg));
+            } else {
+                assert.pass("callCount");
+            }
+        },
+
+        expose: function expose(target, options) {
+            if (!target) {
+                throw new TypeError("target is null or undefined");
+            }
+
+            var o = options || {};
+            var prefix = typeof o.prefix == "undefined" && "assert" || o.prefix;
+            var includeFail = typeof o.includeFail == "undefined" || !!o.includeFail;
+
+            for (var method in this) {
+                if (method != "export" && (includeFail || !/^(fail)/.test(method))) {
+                    target[exposedName(prefix, method)] = this[method];
+                }
+            }
+
+            return target;
+        },
+
+        match: function match(actual, expectation) {
+            var matcher = sinon.match(expectation);
+            if (matcher.test(actual)) {
+                assert.pass("match");
+            } else {
+                var formatted = [
+                    "expected value to match",
+                    "    expected = " + sinon.format(expectation),
+                    "    actual = " + sinon.format(actual)
+                ]
+                failAssertion(this, formatted.join("\n"));
+            }
+        }
+    };
+
+    mirrorPropAsAssertion("called", "expected %n to have been called at least once but was never called");
+    mirrorPropAsAssertion("notCalled", function (spy) { return !spy.called; },
+                          "expected %n to not have been called but was called %c%C");
+    mirrorPropAsAssertion("calledOnce", "expected %n to be called once but was called %c%C");
+    mirrorPropAsAssertion("calledTwice", "expected %n to be called twice but was called %c%C");
+    mirrorPropAsAssertion("calledThrice", "expected %n to be called thrice but was called %c%C");
+    mirrorPropAsAssertion("calledOn", "expected %n to be called with %1 as this but was called with %t");
+    mirrorPropAsAssertion("alwaysCalledOn", "expected %n to always be called with %1 as this but was called with %t");
+    mirrorPropAsAssertion("calledWithNew", "expected %n to be called with new");
+    mirrorPropAsAssertion("alwaysCalledWithNew", "expected %n to always be called with new");
+    mirrorPropAsAssertion("calledWith", "expected %n to be called with arguments %*%C");
+    mirrorPropAsAssertion("calledWithMatch", "expected %n to be called with match %*%C");
+    mirrorPropAsAssertion("alwaysCalledWith", "expected %n to always be called with arguments %*%C");
+    mirrorPropAsAssertion("alwaysCalledWithMatch", "expected %n to always be called with match %*%C");
+    mirrorPropAsAssertion("calledWithExactly", "expected %n to be called with exact arguments %*%C");
+    mirrorPropAsAssertion("alwaysCalledWithExactly", "expected %n to always be called with exact arguments %*%C");
+    mirrorPropAsAssertion("neverCalledWith", "expected %n to never be called with arguments %*%C");
+    mirrorPropAsAssertion("neverCalledWithMatch", "expected %n to never be called with match %*%C");
+    mirrorPropAsAssertion("threw", "%n did not throw exception%C");
+    mirrorPropAsAssertion("alwaysThrew", "%n did not always throw exception%C");
+
+    if (commonJSModule) {
+        module.exports = assert;
+    } else {
+        sinon.assert = assert;
+    }
+}(typeof sinon == "object" && sinon || null, typeof window != "undefined" ? window : (typeof self != "undefined") ? self : global));
+
+return sinon;}.call(typeof window != 'undefined' && window || {}));
diff --git a/resources/sinonjs/sinon-ie-1.8.1.js b/resources/sinonjs/sinon-ie-1.8.1.js
deleted file mode 100644 (file)
index f92e9db..0000000
+++ /dev/null
@@ -1,86 +0,0 @@
-/**
- * Sinon.JS 1.8.1, 2014/02/02
- *
- * @author Christian Johansen (christian@cjohansen.no)
- * @author Contributors: https://github.com/cjohansen/Sinon.JS/blob/master/AUTHORS
- *
- * (The BSD License)
- * 
- * Copyright (c) 2010-2013, Christian Johansen, christian@cjohansen.no
- * All rights reserved.
- * 
- * Redistribution and use in source and binary forms, with or without modification,
- * are permitted provided that the following conditions are met:
- * 
- *     * Redistributions of source code must retain the above copyright notice,
- *       this list of conditions and the following disclaimer.
- *     * Redistributions in binary form must reproduce the above copyright notice,
- *       this list of conditions and the following disclaimer in the documentation
- *       and/or other materials provided with the distribution.
- *     * Neither the name of Christian Johansen nor the names of his contributors
- *       may be used to endorse or promote products derived from this software
- *       without specific prior written permission.
- * 
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
- * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
- * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/*global sinon, setTimeout, setInterval, clearTimeout, clearInterval, Date*/
-/**
- * Helps IE run the fake timers. By defining global functions, IE allows
- * them to be overwritten at a later point. If these are not defined like
- * this, overwriting them will result in anything from an exception to browser
- * crash.
- *
- * If you don't require fake timers to work in IE, don't include this file.
- *
- * @author Christian Johansen (christian@cjohansen.no)
- * @license BSD
- *
- * Copyright (c) 2010-2013 Christian Johansen
- */
-function setTimeout() {}
-function clearTimeout() {}
-function setImmediate() {}
-function clearImmediate() {}
-function setInterval() {}
-function clearInterval() {}
-function Date() {}
-
-// Reassign the original functions. Now their writable attribute
-// should be true. Hackish, I know, but it works.
-setTimeout = sinon.timers.setTimeout;
-clearTimeout = sinon.timers.clearTimeout;
-setImmediate = sinon.timers.setImmediate;
-clearImmediate = sinon.timers.clearImmediate;
-setInterval = sinon.timers.setInterval;
-clearInterval = sinon.timers.clearInterval;
-Date = sinon.timers.Date;
-
-/*global sinon*/
-/**
- * Helps IE run the fake XMLHttpRequest. By defining global functions, IE allows
- * them to be overwritten at a later point. If these are not defined like
- * this, overwriting them will result in anything from an exception to browser
- * crash.
- *
- * If you don't require fake XHR to work in IE, don't include this file.
- *
- * @author Christian Johansen (christian@cjohansen.no)
- * @license BSD
- *
- * Copyright (c) 2010-2013 Christian Johansen
- */
-function XMLHttpRequest() {}
-
-// Reassign the original function. Now its writable attribute
-// should be true. Hackish, I know, but it works.
-XMLHttpRequest = sinon.xhr.XMLHttpRequest || undefined;
diff --git a/resources/sinonjs/sinon-ie-1.9.0.js b/resources/sinonjs/sinon-ie-1.9.0.js
new file mode 100644 (file)
index 0000000..c9fbd9d
--- /dev/null
@@ -0,0 +1,86 @@
+/**
+ * Sinon.JS 1.9.0, 2014/03/05
+ *
+ * @author Christian Johansen (christian@cjohansen.no)
+ * @author Contributors: https://github.com/cjohansen/Sinon.JS/blob/master/AUTHORS
+ *
+ * (The BSD License)
+ * 
+ * Copyright (c) 2010-2014, Christian Johansen, christian@cjohansen.no
+ * All rights reserved.
+ * 
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ * 
+ *     * Redistributions of source code must retain the above copyright notice,
+ *       this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright notice,
+ *       this list of conditions and the following disclaimer in the documentation
+ *       and/or other materials provided with the distribution.
+ *     * Neither the name of Christian Johansen nor the names of his contributors
+ *       may be used to endorse or promote products derived from this software
+ *       without specific prior written permission.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*global sinon, setTimeout, setInterval, clearTimeout, clearInterval, Date*/
+/**
+ * Helps IE run the fake timers. By defining global functions, IE allows
+ * them to be overwritten at a later point. If these are not defined like
+ * this, overwriting them will result in anything from an exception to browser
+ * crash.
+ *
+ * If you don't require fake timers to work in IE, don't include this file.
+ *
+ * @author Christian Johansen (christian@cjohansen.no)
+ * @license BSD
+ *
+ * Copyright (c) 2010-2013 Christian Johansen
+ */
+function setTimeout() {}
+function clearTimeout() {}
+function setImmediate() {}
+function clearImmediate() {}
+function setInterval() {}
+function clearInterval() {}
+function Date() {}
+
+// Reassign the original functions. Now their writable attribute
+// should be true. Hackish, I know, but it works.
+setTimeout = sinon.timers.setTimeout;
+clearTimeout = sinon.timers.clearTimeout;
+setImmediate = sinon.timers.setImmediate;
+clearImmediate = sinon.timers.clearImmediate;
+setInterval = sinon.timers.setInterval;
+clearInterval = sinon.timers.clearInterval;
+Date = sinon.timers.Date;
+
+/*global sinon*/
+/**
+ * Helps IE run the fake XMLHttpRequest. By defining global functions, IE allows
+ * them to be overwritten at a later point. If these are not defined like
+ * this, overwriting them will result in anything from an exception to browser
+ * crash.
+ *
+ * If you don't require fake XHR to work in IE, don't include this file.
+ *
+ * @author Christian Johansen (christian@cjohansen.no)
+ * @license BSD
+ *
+ * Copyright (c) 2010-2013 Christian Johansen
+ */
+function XMLHttpRequest() {}
+
+// Reassign the original function. Now its writable attribute
+// should be true. Hackish, I know, but it works.
+XMLHttpRequest = sinon.xhr.XMLHttpRequest || undefined;
index ec0b2fa..365995d 100644 (file)
@@ -55,18 +55,21 @@ div#simpleSearch {
 
                // These rules MAY NOT be merged because of how CSS requires browsers
                // to parse unrecognized selectors!
+               // Note these rules ensure that placeholder text can be distinguished from
+               // standard text. In browsers which make this distinction clear these rules
+               // are not necessary.
+               // For inputs that use jquery.placeholder.js e.g. IE9-
                &.placeholder {
                        color: #999;
                }
+               // Distinguish placeholder text in IE10+
                &:-ms-input-placeholder {
                        color: #999;
                }
+               // Distinguish placeholder text in Firefox 18-
                &:-moz-placeholder {
                        color: #999;
                }
-               &::-webkit-input-placeholder {
-                       color: #999;
-               }
 
                // Undo the styles Webkit browsers apply to type=search fields,
                // we provide our own
index a868214..bbfea6a 100644 (file)
@@ -1657,7 +1657,7 @@ parsoid
 !!input
 <p><pre>foo</pre></p>
 !!result
-<p data-parsoid='{"stx":"html","autoInsertedEnd":true,"dsr":[0,3,3,0]}'></p><pre data-parsoid='{"stx":"html","dsr":[3,17,5,6]}'>foo</pre><p data-parsoid='{"autoInsertedStart":true,"stx":"html","dsr":[17,21,0,null]}'></p>
+<p data-parsoid='{"stx":"html","autoInsertedEnd":true}'></p><pre data-parsoid='{"stx":"html"}'>foo</pre><p data-parsoid='{"autoInsertedStart":true,"stx":"html"}'></p>
 !!end
 
 !!test
@@ -2156,7 +2156,7 @@ c
 !!end
 
 !!test
-3c. Indent-Pre and block tags (multi-line html)
+3b. Indent-Pre and block tags (multi-line html)
 !!input
  a <span>foo</span>
  b <div> foo </div>
@@ -2168,7 +2168,7 @@ c
 !!end
 
 !!test
-3b. Indent-Pre and block tags (pre-content on separate line)
+3c. Indent-Pre and block tags (pre-content on separate line)
 !!input
 <p>
  foo
@@ -2231,6 +2231,78 @@ foo
 
 !!end
 
+!!test
+4. Indent-Pre and extension tags
+!!input
+ a <gallery>
+File:foobar.jpg
+</gallery>
+!!result
+ a <ul class="gallery mw-gallery-traditional">
+               <li class="gallerybox" style="width: 155px"><div style="width: 155px">
+                       <div class="thumb" style="width: 150px;"><div style="margin:68px auto;"><a href="/wiki/File:Foobar.jpg" class="image"><img alt="Foobar.jpg" src="http://example.com/images/thumb/3/3a/Foobar.jpg/120px-Foobar.jpg" width="120" height="14" /></a></div></div>
+                       <div class="gallerytext">
+                       </div>
+               </div></li>
+</ul>
+
+!!end
+
+!! test
+Leading pipes outside of tables
+!! options
+parsoid
+!! input
+| foo
+!! result
+<p>| foo</p>
+!! end
+
+!! test
+Leading pipes outside of tables 2
+!! options
+parsoid
+!! input
+a
+| foo
+b
+!! result
+<p>a
+| foo
+b</p>
+!! end
+
+!! test
+Leading pipes outside of tables 3
+!! options
+parsoid
+!! input
+a
+| class="foo bar" | baz
+b
+!! result
+<p>a
+| class="foo bar" | baz
+b</p>
+!! end
+
+!!test
+Render paragraphs when indent-pre is suppressed in blocklevels
+!!input
+<blockquote>
+ foo
+
+ bar
+</blockquote>
+!! result
+<blockquote>
+<p> foo
+</p><p> bar
+</p>
+</blockquote>
+
+!!end
+
 !!test
 4. Multiple spaces at start-of-line
 !!input
@@ -4153,9 +4225,9 @@ parsoid
 
 (http://example.com<!-- hi -->)
 !! result
-<p>(<a data-mw='{"attribs":[[{"txt":"href"},{"html":"http://example.com/&lt;span about=\"#mwt1\" typeof=\"mw:Transclusion\" data-mw=\"{&amp;quot;parts&amp;quot;:[{&amp;quot;template&amp;quot;:{&amp;quot;target&amp;quot;:{&amp;quot;wt&amp;quot;:&amp;quot;echo&amp;quot;,&amp;quot;href&amp;quot;:&amp;quot;./Template:Echo&amp;quot;},&amp;quot;params&amp;quot;:{&amp;quot;1&amp;quot;:{&amp;quot;wt&amp;quot;:&amp;quot;hi&amp;quot;}},&amp;quot;i&amp;quot;:0}}]}\" data-parsoid=\"{&amp;quot;dsr&amp;quot;:[20,31,null,null],&amp;quot;pi&amp;quot;:[[{&amp;quot;k&amp;quot;:&amp;quot;1&amp;quot;,&amp;quot;spc&amp;quot;:[&amp;quot;&amp;quot;,&amp;quot;&amp;quot;,&amp;quot;&amp;quot;,&amp;quot;&amp;quot;]}]]}\">hi&lt;/span>"}]]}' typeof="mw:ExpandedAttrs" about="#mwt2" rel="mw:ExtLink" href="http://example.com/hi" data-parsoid='{"stx":"url","a":{"href":"http://example.com/hi"},"sa":{"href":"http://example.com/{{echo|hi}}"},"dsr":[1,31,0,0]}'>http://example.com/hi</a>)</p>
+<p>(<a data-mw='{"attribs":[[{"txt":"href"},{"html":"http://example.com/&lt;span about=\"#mwt1\" typeof=\"mw:Transclusion\" data-mw=\"{&amp;quot;parts&amp;quot;:[{&amp;quot;template&amp;quot;:{&amp;quot;target&amp;quot;:{&amp;quot;wt&amp;quot;:&amp;quot;echo&amp;quot;,&amp;quot;href&amp;quot;:&amp;quot;./Template:Echo&amp;quot;},&amp;quot;params&amp;quot;:{&amp;quot;1&amp;quot;:{&amp;quot;wt&amp;quot;:&amp;quot;hi&amp;quot;}},&amp;quot;i&amp;quot;:0}}]}\" data-parsoid=\"{&amp;quot;dsr&amp;quot;:[20,31,null,null],&amp;quot;pi&amp;quot;:[[{&amp;quot;k&amp;quot;:&amp;quot;1&amp;quot;,&amp;quot;spc&amp;quot;:[&amp;quot;&amp;quot;,&amp;quot;&amp;quot;,&amp;quot;&amp;quot;,&amp;quot;&amp;quot;]}]]}\">hi&lt;/span>"}]]}' typeof="mw:ExpandedAttrs" about="#mwt2" rel="mw:ExtLink" href="http://example.com/hi" data-parsoid='{"stx":"url","a":{"href":"http://example.com/hi"},"sa":{"href":"http://example.com/{{echo|hi}}"}}'>http://example.com/hi</a>)</p>
 
-<p>(<a rel="mw:ExtLink" href="http://example.com" data-parsoid='{"stx":"url","a":{"href":"http://example.com"},"sa":{"href":"http://example.com&lt;!-- hi -->"},"dsr":[35,64,0,0]}'>http://example.com</a>)</p>
+<p>(<a rel="mw:ExtLink" href="http://example.com" data-parsoid='{"stx":"url","a":{"href":"http://example.com"},"sa":{"href":"http://example.com&lt;!-- hi -->"}}'>http://example.com</a>)</p>
 !! end
 
 ###
@@ -5174,9 +5246,18 @@ Link with HTML entity in suffix / tail
 !! test
 Link with 3 brackets
 !! input
-[[[main page]]]
+[[[Main Page]]]
+!! result
+<p>[[[Main Page]]]
+</p>
+!! end
+
+!! test
+Link with 4 brackets
+!! input
+[[[[Main Page]]]]
 !! result
-<p>[[[main page]]]
+<p>[[<a href="/wiki/Main_Page" title="Main Page">Main Page</a>]]
 </p>
 !! end
 
@@ -5599,6 +5680,36 @@ language=kaa
 </p>
 !! end
 
+!! test
+1. Interaction of linktrail and template encapsulation
+!! options
+parsoid
+!! input
+{{echo|[[Foo]]}}l
+!! result
+<p><a rel="mw:WikiLink" href="Foo" typeof="mw:Transclusion" data-mw='{"parts":[{"template":{"target":{"wt":"echo","href":"./Template:Echo"},"params":{"1":{"wt":"[[Foo]]"}},"i":0}},"l"]}'>Fool</a></p>
+!! end
+
+!! test
+2. Interaction of linktrail and template encapsulation
+!! options
+parsoid
+!! input
+{{echo|Some [[Fool]]}}s
+!! result
+<p data-parsoid='{}'><span about="#mwt1" typeof="mw:Transclusion" data-mw='{"parts":[{"template":{"target":{"wt":"echo","href":"./Template:Echo"},"params":{"1":{"wt":"Some [[Fool]]"}},"i":0}},"s"]}' data-parsoid='{"pi":[[{"k":"1","spc":["","","",""]}]]}'>Some </span><a rel="mw:WikiLink" href="./Fool" about="#mwt1" data-parsoid='{"stx":"simple","a":{"href":"./Fool"},"sa":{"href":"Fool"},"tail":"s"}'>Fools</a></p>
+!! end
+
+!! test
+3. Interaction of linktrail and template encapsulation
+!! options
+parsoid
+!! input
+{{echo|Some [[Fool]]s are '''bold and foolish'''}}
+!! result
+<p about="#mwt1" typeof="mw:Transclusion" data-mw='{"parts":[{"template":{"target":{"wt":"echo","href":"./Template:Echo"},"params":{"1":{"wt":"Some [[Fool]]s are &#39;&#39;&#39;bold and foolish&#39;&#39;&#39;"}},"i":0}}]}' data-parsoid='{"pi":[[{"k":"1","spc":["","","",""]}]]}'>Some <a rel="mw:WikiLink" href="./Fool" data-parsoid='{"stx":"simple","a":{"href":"./Fool"},"sa":{"href":"Fool"},"tail":"s"}'>Fools</a> are <b data-parsoid="{}">bold and foolish</b></p>
+!! end
+
 !! article
 Söfnuður
 !! text
@@ -5687,7 +5798,7 @@ parsoid
 !! input
 [[Foo|{{echo|a}} b {{echo|c}}]]
 !! result
-<p data-parsoid='{"dsr":[0,20,0,0]}'><a rel="mw:WikiLink" href="Foo"><span about="#mwt2" typeof="mw:Transclusion" data-mw='{"parts":[{"template":{"target":{"wt":"echo","href":"./Template:Echo"},"params":{"1":{"wt":"a"}},"i":0}}]}'>a</span> b <span about="#mwt3" typeof="mw:Transclusion" data-mw='{"parts":[{"template":{"target":{"wt":"echo","href":"./Template:Echo"},"params":{"1":{"wt":"c"}},"i":0}}]}'>c</span></a></p>
+<p><a rel="mw:WikiLink" href="Foo"><span about="#mwt2" typeof="mw:Transclusion" data-mw='{"parts":[{"template":{"target":{"wt":"echo","href":"./Template:Echo"},"params":{"1":{"wt":"a"}},"i":0}}]}'>a</span> b <span about="#mwt3" typeof="mw:Transclusion" data-mw='{"parts":[{"template":{"target":{"wt":"echo","href":"./Template:Echo"},"params":{"1":{"wt":"c"}},"i":0}}]}'>c</span></a></p>
 !! end
 
 ###
@@ -5746,10 +5857,9 @@ parsoid
 
 [[:en:Foo]]
 !! result
-<p data-parsoid='{"dsr":[0,17,0,0]}'><a rel="mw:ExtLink" href="http://en.wikipedia.org/wiki/Foo" data-parsoid='{"stx":"simple","a":{"href":"http://en.wikipedia.org/wiki/Foo"},"sa":{"href":"wikipedia:Foo"},"isIW":true,"dsr":[0,17,null,1]}'>wikipedia:Foo</a></p>
-
+<p><a rel="mw:ExtLink" href="http://en.wikipedia.org/wiki/Foo" data-parsoid='{"stx":"simple","a":{"href":"http://en.wikipedia.org/wiki/Foo"},"sa":{"href":"wikipedia:Foo"},"isIW":true}'>wikipedia:Foo</a></p>
 
-<p data-parsoid='{"dsr":[19,30,0,0]}'><a rel="mw:ExtLink" href="//en.wikipedia.org/wiki/Foo" data-parsoid='{"stx":"simple","a":{"href":"//en.wikipedia.org/wiki/Foo"},"sa":{"href":":en:Foo"},"isIW":true,"dsr":[19,30,null,1]}'>en:Foo</a></p>
+<p><a rel="mw:ExtLink" href="//en.wikipedia.org/wiki/Foo" data-parsoid='{"stx":"simple","a":{"href":"//en.wikipedia.org/wiki/Foo"},"sa":{"href":":en:Foo"},"isIW":true}'>en:Foo</a></p>
 !! end
 
 !! test
@@ -5771,6 +5881,15 @@ parsoid
 <a rel="mw:ExtLink" href="http://de.wikipedia.org/wiki/#foo">is just fragment</a></p>
 !! end
 
+!! test
+Interwiki links: trail
+!! options
+parsoid
+!! input
+[[wikipedia:Foo|Ba]]r
+!! result
+<p data-parsoid='{}'><a rel="mw:ExtLink" href="http://en.wikipedia.org/wiki/Foo" data-parsoid='{"stx":"piped","a":{"href":"http://en.wikipedia.org/wiki/Foo"},"sa":{"href":"wikipedia:Foo"},"isIW":true,"tail":"r"}'>Bar</a></p>
+!! end
 
 ###
 ### Interlanguage links
@@ -5856,10 +5975,9 @@ parsoid
 
 [[constructor:foo]]
 !! result
-<p data-parsoid="{&quot;dsr&quot;:[0,15,0,0]}"><a rel="mw:WikiLink" href="./Constructor" data-parsoid="{&quot;stx&quot;:&quot;simple&quot;,&quot;a&quot;:{&quot;href&quot;:&quot;./Constructor&quot;},&quot;sa&quot;:{&quot;href&quot;:&quot;constructor&quot;},&quot;dsr&quot;:[0,15,2,2]}">constructor</a></p>
+<p><a rel="mw:WikiLink" href="./Constructor" data-parsoid="{&quot;stx&quot;:&quot;simple&quot;,&quot;a&quot;:{&quot;href&quot;:&quot;./Constructor&quot;},&quot;sa&quot;:{&quot;href&quot;:&quot;constructor&quot;}}">constructor</a></p>
 
-
-<p data-parsoid="{&quot;dsr&quot;:[17,36,0,0]}"><a rel="mw:WikiLink" href="./Foo" data-parsoid="{&quot;stx&quot;:&quot;simple&quot;,&quot;a&quot;:{&quot;href&quot;:&quot;./Foo&quot;},&quot;sa&quot;:{&quot;href&quot;:&quot;constructor:foo&quot;},&quot;dsr&quot;:[17,36,2,2]}">constructor:foo</a></p>
+<p><a rel="mw:WikiLink" href="./Foo" data-parsoid="{&quot;stx&quot;:&quot;simple&quot;,&quot;a&quot;:{&quot;href&quot;:&quot;./Foo&quot;},&quot;sa&quot;:{&quot;href&quot;:&quot;constructor:foo&quot;}}">constructor:foo</a></p>
 !! end
 
 !! test
@@ -5883,11 +6001,21 @@ parsoid
 <p><a rel="mw:ExtLink" href="//ko.wikipedia.org/wiki/">ko:</a></p>
 !! end
 
+!! test
+Parsoid: Bug #45209, handle interwiki links pointing to the current wiki as plain wiki links
+!! options
+parsoid
+!! input
+[[en:Foo]]
+!! result
+<p><a rel="mw:WikiLink" href="./Foo" data-parsoid='{"stx":"simple","a":{"href":"./Foo"},"sa":{"href":"en:Foo"}}'>Foo</a></p>
+!! end
+
 ###
 ### Redirects, Parsoid-only
 ###
 !! test
-Simple redirect to page
+1. Simple redirect to page
 !! options
 parsoid
 !! input
@@ -5896,6 +6024,19 @@ parsoid
 <link rel="mw:PageProp/redirect" href="./Main_Page">
 !! end
 
+# Only wt2html and html2html since "Main_Page" will serialize to "Main Page"
+!! test
+2. Other redirect variants
+!! options
+parsoid=wt2html,wt2wt
+!! input
+#REDIRECT [[Main_Page]]
+#REDIRECT [[<nowiki>[[Bar]]</nowiki>]]
+!! result
+<link rel="mw:PageProp/redirect" href="./Main_Page">
+<link rel="mw:PageProp/redirect" href="./%5B%5BBar%5D%5D">
+!! end
+
 !! test
 Optional colon in #REDIRECT
 !! options
@@ -6017,6 +6158,17 @@ language=is
 <link rel="mw:PageProp/redirect" href="./Main_Page">
 !! end
 
+!! test
+New redirect
+!! options
+parsoid=html2wt
+!! input
+Foo
+#REDIRECT [[Foo]]
+!! result
+<p>Foo<link rel="mw:PageProp/redirect" href="./Foo"></p>
+!! end
+
 ##
 ## XHTML tidiness
 ###
@@ -7513,6 +7665,39 @@ hi+world%3F%21
 </p>
 !! end
 
+!! test
+Magic Word: prioritize type info over data-parsoid
+!! options
+parsoid=html2wt
+!! input
+__FORCETOC__
+!! result
+<meta property="mw:PageProp/forcetoc" data-parsoid='{"src":"__NOTOC__","magicSrc":"__NOTOC__"}'/>
+!! end
+
+!! test
+Magic Word: serialize on separate line (parsoid)
+!! options
+parsoid=wt2wt,html2wt
+!! input
+foo
+__NOTOC__
+bar
+!! result
+foo<meta property="mw:PageProp/notoc"/>bar
+!! end
+
+!! test
+Magic Word: rt non-english wikis
+!! options
+parsoid=wt2wt
+language=de
+!! input
+__NOEDITSECTION__
+!! result
+<meta property="mw:PageProp/noeditsection" data-parsoid='{"src":"__NOEDITSECTION__","magicSrc":"__NOEDITSECTION__"}'/>
+!! end
+
 ###
 ### Magic links
 ###
@@ -7583,6 +7768,27 @@ Template with invalid target containing unclosed tag
 </p>
 !! end
 
+!! test
+Template with invalid target containing wikilink (php)
+!! options
+php
+!! input
+{{[[Main Page]]}}
+!! result
+<p>{{<a href="/wiki/Main_Page" title="Main Page">Main Page</a>}}
+</p>
+!! end
+
+!! test
+Template with invalid target containing wikilink (parsoid)
+!! options
+parsoid
+!! input
+{{[[Main Page]]}}
+!! result
+<p><span typeof="mw:Transclusion" about="#mwt1" data-mw='{"parts":[{"template":{"target":{"wt":"[[Main Page]]"},"params":{},"i":0}}]}'>{{</span><a rel="mw:WikiLink" href="./Main_Page" about="#mwt1">Main Page</a><span about="#mwt1">}}</span></p>
+!! end
+
 !! article
 Template:test
 !! text
@@ -8874,8 +9080,8 @@ parsoid
 <tbody>
 <tr>
 <td>foo</td></tr></tbody></table><span about="#mwt1">
-</span><span about="#mwt1">bar</span><span about="#mwt1">
-</span>
+</span><span about="#mwt1">|bar</span><span about="#mwt1">
+|}</span>
 !!end
 
 !!test
@@ -9767,6 +9973,31 @@ parsoid
 <figure class="mw-default-size mw-halign-right" typeof="mw:Image"><a href="File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" height="220" width="1941"></a><figcaption>Caption page=stuff</figcaption></figure>
 !! end
 
+!! test
+Allow empty links in image captions (Bug 60753) (parsoid)
+!! options
+parsoid
+!!input
+[[File:Foobar.jpg|thumb|Caption [[Link1]]
+[[]]
+[[Link2]]
+]]
+!! result
+<figure class="mw-default-size" typeof="mw:Image/Thumb" data-parsoid='{"optList":[{"ck":"thumbnail","ak":"thumb"},{"ck":"caption","ak":"Caption [[Link1]]\n[[]]\n[[Link2]]\n"}],"dsr":[0,59,2,2]}'><a href="./File:Foobar.jpg" data-parsoid='{"a":{"href":"./File:Foobar.jpg"},"dsr":[2,null,null,null]}'><img resource="./File:Foobar.jpg" src="//example.com/images/thumb/3/3a/Foobar.jpg/220px-Foobar.jpg" height="25" width="220" data-parsoid='{"a":{"resource":"./File:Foobar.jpg","height":"25","width":"220"},"sa":{"resource":"File:Foobar.jpg"}}'/></a><figcaption data-parsoid='{"dsr":[null,57,null,null]}'>Caption <a rel="mw:WikiLink" href="./Link1" data-parsoid='{"stx":"simple","a":{"href":"./Link1"},"sa":{"href":"Link1"},"dsr":[32,41,2,2]}'>Link1</a>
+[[]]
+<a rel="mw:WikiLink" href="./Link2" data-parsoid='{"stx":"simple","a":{"href":"./Link2"},"sa":{"href":"Link2"},"dsr":[47,56,2,2]}'>Link2</a>
+</figcaption></figure>
+!! end
+
+!! test
+Link with empty target
+!! input
+[[]]
+!! result
+<p>[[]]
+</p>
+!! end
+
 !! test
 Image with empty attribute (php)
 !! options
@@ -9789,7 +10020,37 @@ parsoid=wt2html
 !! end
 
 !! test
-Image with attributes from template (php)
+1. Block image with individual attributes from templates
+!! options
+parsoid
+!! input
+[[File:Foobar.jpg|thumb|{{echo|137px}}|This is a caption]]
+!! result
+<figure typeof="mw:Image/Thumb mw:ExpandedAttrs" data-mw='{"attribs":[["thumbnail",{"html":"thumb"}],["width",{"html":"&lt;span about=\"#mwt1\" typeof=\"mw:Transclusion\" data-mw=\"{&amp;quot;parts&amp;quot;:[{&amp;quot;template&amp;quot;:{&amp;quot;target&amp;quot;:{&amp;quot;wt&amp;quot;:&amp;quot;echo&amp;quot;,&amp;quot;href&amp;quot;:&amp;quot;./Template:Echo&amp;quot;},&amp;quot;params&amp;quot;:{&amp;quot;1&amp;quot;:{&amp;quot;wt&amp;quot;:&amp;quot;137px&amp;quot;}},&amp;quot;i&amp;quot;:0}}]}\" data-parsoid=\"{&amp;quot;dsr&amp;quot;:[24,38,null,null],&amp;quot;pi&amp;quot;:[[{&amp;quot;k&amp;quot;:&amp;quot;1&amp;quot;,&amp;quot;spc&amp;quot;:[&amp;quot;&amp;quot;,&amp;quot;&amp;quot;,&amp;quot;&amp;quot;,&amp;quot;&amp;quot;]}]]}\">137px&lt;/span>"}]]}'><a href="File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" height="16" width="137"/></a><figcaption>This is a caption</figcaption></figure>
+!! end
+
+!! test
+2. Block Image with individual attributes from templates
+!! options
+parsoid
+!! input
+[[File:Foobar.jpg|{{echo|thumb}}|{{echo|137px}}|This is a caption]]
+!! result
+<figure typeof="mw:Image/Thumb mw:ExpandedAttrs" data-mw='{"attribs":[["thumbnail",{"html":"&lt;span about=\"#mwt1\" typeof=\"mw:Transclusion\" data-mw=\"{&amp;quot;parts&amp;quot;:[{&amp;quot;template&amp;quot;:{&amp;quot;target&amp;quot;:{&amp;quot;wt&amp;quot;:&amp;quot;echo&amp;quot;,&amp;quot;href&amp;quot;:&amp;quot;./Template:Echo&amp;quot;},&amp;quot;params&amp;quot;:{&amp;quot;1&amp;quot;:{&amp;quot;wt&amp;quot;:&amp;quot;thumb&amp;quot;}},&amp;quot;i&amp;quot;:0}}]}\" data-parsoid=\"{&amp;quot;dsr&amp;quot;:[18,32,null,null],&amp;quot;pi&amp;quot;:[[{&amp;quot;k&amp;quot;:&amp;quot;1&amp;quot;,&amp;quot;spc&amp;quot;:[&amp;quot;&amp;quot;,&amp;quot;&amp;quot;,&amp;quot;&amp;quot;,&amp;quot;&amp;quot;]}]]}\">thumb&lt;/span>"}],["width",{"html":"&lt;span about=\"#mwt2\" typeof=\"mw:Transclusion\" data-mw=\"{&amp;quot;parts&amp;quot;:[{&amp;quot;template&amp;quot;:{&amp;quot;target&amp;quot;:{&amp;quot;wt&amp;quot;:&amp;quot;echo&amp;quot;,&amp;quot;href&amp;quot;:&amp;quot;./Template:Echo&amp;quot;},&amp;quot;params&amp;quot;:{&amp;quot;1&amp;quot;:{&amp;quot;wt&amp;quot;:&amp;quot;137px&amp;quot;}},&amp;quot;i&amp;quot;:0}}]}\" data-parsoid=\"{&amp;quot;dsr&amp;quot;:[33,47,null,null],&amp;quot;pi&amp;quot;:[[{&amp;quot;k&amp;quot;:&amp;quot;1&amp;quot;,&amp;quot;spc&amp;quot;:[&amp;quot;&amp;quot;,&amp;quot;&amp;quot;,&amp;quot;&amp;quot;,&amp;quot;&amp;quot;]}]]}\">137px&lt;/span>"}]]}'><a href="File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" height="16" width="137"/></a><figcaption>This is a caption</figcaption></figure>
+!! end
+
+!! test
+3. Inline image with individual attributes from templates
+!! options
+parsoid
+!! input
+[[File:Foobar.jpg|{{echo|50px}}]]
+!! result
+<p><span typeof="mw:Image mw:ExpandedAttrs" about="#mwt2" data-mw='{"attribs":[["width",{"html":"&lt;span about=\"#mwt1\" typeof=\"mw:Transclusion\" data-mw=\"{&amp;quot;parts&amp;quot;:[{&amp;quot;template&amp;quot;:{&amp;quot;target&amp;quot;:{&amp;quot;wt&amp;quot;:&amp;quot;echo&amp;quot;,&amp;quot;href&amp;quot;:&amp;quot;./Template:Echo&amp;quot;},&amp;quot;params&amp;quot;:{&amp;quot;1&amp;quot;:{&amp;quot;wt&amp;quot;:&amp;quot;50px&amp;quot;}},&amp;quot;i&amp;quot;:0}}]}\" data-parsoid=\"{&amp;quot;dsr&amp;quot;:[18,31,null,null],&amp;quot;pi&amp;quot;:[[{&amp;quot;k&amp;quot;:&amp;quot;1&amp;quot;,&amp;quot;spc&amp;quot;:[&amp;quot;&amp;quot;,&amp;quot;&amp;quot;,&amp;quot;&amp;quot;,&amp;quot;&amp;quot;]}]]}\">50px&lt;/span>"}]]}' data-parsoid='{"optList":[{"ck":"width","ak":"{{echo|50px}}"}]}'><a href="./File:Foobar.jpg" data-parsoid='{"a":{"href":"./File:Foobar.jpg"}}'><img resource="./File:Foobar.jpg" src="//example.com/images/thumb/3/3a/Foobar.jpg/50px-Foobar.jpg" height="6" width="50" data-parsoid='{"a":{"resource":"./File:Foobar.jpg","height":"6","width":"50"},"sa":{"resource":"File:Foobar.jpg"}}'/></a></span></p>
+!! end
+
+!! test
+Image with multiple attributes from the same template (php)
 !! options
 php
 !! input
@@ -9799,14 +10060,16 @@ php
 
 !! end
 
+## Parsoid does not provide editing support for images where templates produce multiple image attributes.
+## To signal this, we add a 'mw:Placeholder' type to such images. This could change in the future.
 !! test
-Image with attributes from template (parsoid)
+Image with multiple attributes from the same template (parsoid)
 !! options
 parsoid
 !! input
 [[File:Foobar.jpg|{{image_attribs}}]]
 !! result
-<figure class="mw-default-size mw-halign-right" typeof="mw:Image"><a href="File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" height="220" width="1941"></a><figcaption>Caption text</figcaption></figure>
+<figure class="mw-default-size mw-halign-right" typeof="mw:Image mw:Placeholder"><a href="File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" height="220" width="1941"></a><figcaption>Caption text</figcaption></figure>
 !! end
 
 !! test
@@ -9836,7 +10099,7 @@ parsoid
 !! result
 <p>123<span class="mw-default-size" typeof="mw:Image"><a href="File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" height="220" width="1941"></a></span>456</p>
 123<figure class="mw-default-size mw-halign-right" typeof="mw:Image"><a href="File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" height="220" width="1941"></a></figure>456
-123<figure class="mw-default-size" typeof="mw:Image/Thumb"><a href="File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/thumb/3/3a/Foobar.jpg/180px-Foobar.jpg" height="20" width="180"></a></figure>456
+123<figure class="mw-default-size" typeof="mw:Image/Thumb"><a href="File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/thumb/3/3a/Foobar.jpg/180px-Foobar.jpg" height="25" width="220"></a></figure>456
 !! end
 
 !! test
@@ -9860,6 +10123,54 @@ parsoid
 <figure class="mw-default-size mw-halign-right" typeof="mw:Image"><a href="File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" height="220" width="1941"></a><figcaption>Caption3 - accepted</figcaption></figure>
 !! end
 
+!! test
+Image with multiple widths -- use last (php)
+!! options
+php
+!! input
+[[File:Foobar.jpg|200px|300px|caption]]
+!! result
+<p><a href="/wiki/File:Foobar.jpg" class="image" title="caption"><img alt="caption" src="http://example.com/images/thumb/3/3a/Foobar.jpg/300px-Foobar.jpg" width="300" height="34" srcset="http://example.com/images/thumb/3/3a/Foobar.jpg/450px-Foobar.jpg 1.5x, http://example.com/images/thumb/3/3a/Foobar.jpg/600px-Foobar.jpg 2x" /></a>
+</p>
+!! end
+
+!! test
+Image with multiple widths -- use last (parsoid)
+!! options
+parsoid
+!! input
+[[File:Foobar.jpg|200px|300px|caption]]
+!! result
+<p><span typeof="mw:Image" data-mw='{"caption":"caption"}'><a href="File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" height="34" width="300"/></a></span></p>
+!! end
+
+!! test
+Image with multiple alignments -- use first (bug 48664) (php)
+!! options
+php
+!! input
+[[File:Foobar.jpg|thumb|left|right|center|caption]]
+
+[[File:Foobar.jpg|middle|text-top|caption]]
+!! result
+<div class="thumb tleft"><div class="thumbinner" style="width:182px;"><a href="/wiki/File:Foobar.jpg" class="image"><img alt="" src="http://example.com/images/thumb/3/3a/Foobar.jpg/180px-Foobar.jpg" width="180" height="20" class="thumbimage" srcset="http://example.com/images/thumb/3/3a/Foobar.jpg/270px-Foobar.jpg 1.5x, http://example.com/images/thumb/3/3a/Foobar.jpg/360px-Foobar.jpg 2x" /></a>  <div class="thumbcaption"><div class="magnify"><a href="/wiki/File:Foobar.jpg" class="internal" title="Enlarge"><img src="/skins/common/images/magnify-clip.png" width="15" height="11" alt="" /></a></div>caption</div></div></div>
+<p><a href="/wiki/File:Foobar.jpg" class="image" title="caption"><img alt="caption" src="http://example.com/images/3/3a/Foobar.jpg" width="1941" height="220" style="vertical-align: middle" /></a>
+</p>
+!! end
+
+!! test
+Image with multiple alignments -- use first (bug 48664) (parsoid)
+!! options
+parsoid
+!! input
+[[File:Foobar.jpg|thumb|left|right|center|caption]]
+
+[[File:Foobar.jpg|middle|text-top|caption]]
+!! result
+<figure class="mw-default-size mw-halign-left" typeof="mw:Image/Thumb"><a href="File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" height="25" width="220"/></a><figcaption>caption</figcaption></figure>
+<p><span class="mw-default-size mw-valign-middle" typeof="mw:Image" data-mw='{"caption":"caption"}'><a href="File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" height="220" width="1941"/></a></span></p>
+!! end
+
 !! test
 Image with width attribute at different positions (php)
 !! options
@@ -9880,15 +10191,40 @@ Image with width attribute at different positions (parsoid)
 !! options
 parsoid
 !! input
-[[File:Foobar.jpg|200px|right|Caption]]
-[[File:Foobar.jpg|right|200px|Caption]]
-[[File:Foobar.jpg|right|Caption|200px]]
+[[File:Foobar.jpg|200x200px|right|Caption]]
+[[File:Foobar.jpg|right|200x200px|Caption]]
+[[File:Foobar.jpg|right|Caption|200x200px]]
 !! result
 <figure class="mw-halign-right" typeof="mw:Image"><a href="File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/thumb/3/3a/Foobar.jpg/200px-Foobar.jpg" height="23" width="200"></a><figcaption>Caption</figcaption></figure>
 <figure class="mw-halign-right" typeof="mw:Image"><a href="File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/thumb/3/3a/Foobar.jpg/200px-Foobar.jpg" height="23" width="200"></a><figcaption>Caption</figcaption></figure>
 <figure class="mw-halign-right" typeof="mw:Image"><a href="File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/thumb/3/3a/Foobar.jpg/200px-Foobar.jpg" height="23" width="200"></a><figcaption>Caption</figcaption></figure>
 !! end
 
+# a sad bit of backward-compatibility
+!! test
+Image with size specified with pxpx (bug 13500, 51628) (php)
+!! options
+php
+!! input
+[[File:Foobar.jpg|20pxpx]]
+[[File:Foobar.jpg|200x20pxpx]]
+!! result
+<p><a href="/wiki/File:Foobar.jpg" class="image"><img alt="Foobar.jpg" src="http://example.com/images/thumb/3/3a/Foobar.jpg/20px-Foobar.jpg" width="20" height="2" srcset="http://example.com/images/thumb/3/3a/Foobar.jpg/30px-Foobar.jpg 1.5x, http://example.com/images/thumb/3/3a/Foobar.jpg/40px-Foobar.jpg 2x" /></a>
+<a href="/wiki/File:Foobar.jpg" class="image"><img alt="Foobar.jpg" src="http://example.com/images/thumb/3/3a/Foobar.jpg/177px-Foobar.jpg" width="177" height="20" srcset="http://example.com/images/thumb/3/3a/Foobar.jpg/265px-Foobar.jpg 1.5x, http://example.com/images/thumb/3/3a/Foobar.jpg/353px-Foobar.jpg 2x" /></a>
+</p>
+!! end
+
+!! test
+Image with size specified with pxpx (bug 13500, 51628) (parsoid)
+!! options
+parsoid=wt2html,wt2wt
+!! input
+[[File:Foobar.jpg|20pxpx]]
+[[File:Foobar.jpg|200x20pxpx]]
+!! result
+<p><span typeof="mw:Image"><a href="File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" height="2" width="20"/></a></span><span typeof="mw:Image"><a href="File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" height="20" width="177"/></a></span></p>
+!! end
+
 !! test
 Image with link parameter, wiki target (php)
 !! options
@@ -10360,6 +10696,45 @@ Parsoid: Image caption containing leading space
 
 !!end
 
+!! test
+Image caption containing a table (php)
+!! options
+php
+!! input
+[[Image:Foobar.jpg|thumb|200px|This is an example image thumbnail caption with a table
+{|
+! Foo !! Bar
+|-
+| Foo1 || Bar1
+|}
+and some more text.]]
+!! result
+<div class="thumb tright"><div class="thumbinner" style="width:202px;"><a href="/wiki/File:Foobar.jpg" class="image"><img alt="" src="http://example.com/images/thumb/3/3a/Foobar.jpg/200px-Foobar.jpg" width="200" height="23" class="thumbimage" srcset="http://example.com/images/thumb/3/3a/Foobar.jpg/300px-Foobar.jpg 1.5x, http://example.com/images/thumb/3/3a/Foobar.jpg/400px-Foobar.jpg 2x" /></a>  <div class="thumbcaption"><div class="magnify"><a href="/wiki/File:Foobar.jpg" class="internal" title="Enlarge"><img src="/skins/common/images/magnify-clip.png" width="15" height="11" alt="" /></a></div>This is an example image thumbnail caption with a table <table> <tr> <th> Foo </th> <th> Bar </th></tr> <tr> <td> Foo1 </td> <td> Bar1 </td></tr></table> and some more text.</div></div></div>
+
+!!end
+
+!! test
+Image caption containing a table (parsoid)
+!! options
+parsoid
+!! input
+[[Image:Foobar.jpg|thumb|200px|This is an example image thumbnail caption with a table
+{|
+! Foo !! Bar
+|-
+| Foo1 || Bar1
+|}
+and some more text.]]
+!! result
+<figure typeof="mw:Image/Thumb"><a href="File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" height="23" width="200"/></a><figcaption>This is an example image thumbnail caption with a table
+<table>
+<tbody>
+<tr><th>Foo </th><th>Bar</th></tr>
+<tr>
+<td>Foo1 </td>
+<td>Bar1</td></tr></tbody></table>and some more text.</figcaption></figure>
+!! end
+
 !! test
 Bug 3090: External links other than http: in image captions
 !! input
@@ -10447,10 +10822,9 @@ Parsoid-specific image handling - simple image with size and middle alignment
 !! options
 parsoid
 !! input
-[[Image:Foobar.jpg|50px|middle]]
+[[File:Foobar.jpg|middle|50px]]
 !! result
-<p>
-<span class="mw-valign-middle" typeof="mw:Image">
+<p><span class="mw-valign-middle" typeof="mw:Image">
 <a href="File:Foobar.jpg">
 <img resource="./File:Foobar.jpg" src="//example.com/images/thumb/3/3a/Foobar.jpg/50px-Foobar.jpg" height="6" width="50">
 </a>
@@ -10459,30 +10833,41 @@ parsoid
 !! end
 
 !! test
-Parsoid-specific image handling - simple image with both sizes, a baseline alignment, and a caption
+Parsoid-specific image handling - simple image with size, middle alignment,
+non-standard namespace alias
 !! options
-parsoid
+parsoid=wt2wt,wt2html,html2html
 !! input
-[[Image:Foobar.jpg|500x10px|baseline|caption]]
+[[Image:Foobar.jpg|middle|50px]]
 !! result
-<p>
-<span class="mw-valign-baseline" typeof="mw:Image" data-mw="{&quot;caption&quot;:&quot;caption&quot;}">
+<p><span class="mw-valign-middle" typeof="mw:Image">
 <a href="File:Foobar.jpg">
-<img resource="./File:Foobar.jpg" src="//example.com/images/thumb/3/3a/Foobar.jpg/89px-Foobar.jpg" height="10" width="89">
+<img resource="./File:Foobar.jpg" src="//example.com/images/thumb/3/3a/Foobar.jpg/50px-Foobar.jpg" height="6" width="50">
 </a>
 </span>
 </p>
 !! end
 
 !! test
-Parsoid-specific image handling - simple image with border and size spec
+Parsoid-specific image handling - simple image with size and middle alignment
+(existing content)
 !! options
 parsoid
 !! input
-[[Image:Foobar.jpg|50px|border|caption]]
+[[File:Foobar.jpg|50px|middle]]
 !! result
-<p>
-<span class="mw-image-border" typeof="mw:Image" data-mw="{&quot;caption&quot;:&quot;caption&quot;}">
+<p><span class="mw-valign-middle" typeof="mw:Image" data-parsoid='{"optList":[{"ck":"width","ak":"50px"},{"ck":"middle","ak":"middle"}]}'><a href="./File:Foobar.jpg" data-parsoid='{"a":{"href":"./File:Foobar.jpg"}}'><img resource="./File:Foobar.jpg" src="//example.com/images/thumb/3/3a/Foobar.jpg/50px-Foobar.jpg" height="6" width="50" data-parsoid='{"a":{"resource":"./File:Foobar.jpg","height":"6","width":"50"},"sa":{"resource":"File:Foobar.jpg"}}'/></a></span></p>
+!! end
+
+!! test
+Parsoid-specific image handling - simple image with size and middle alignment
+and non-standard namespace name
+!! options
+parsoid=wt2html,wt2wt,html2html
+!! input
+[[Image:Foobar.jpg|50px|middle]]
+!! result
+<p><span class="mw-valign-middle" typeof="mw:Image">
 <a href="File:Foobar.jpg">
 <img resource="./File:Foobar.jpg" src="//example.com/images/thumb/3/3a/Foobar.jpg/50px-Foobar.jpg" height="6" width="50">
 </a>
@@ -10490,27 +10875,58 @@ parsoid
 </p>
 !! end
 
+!! test
+Parsoid-specific image handling - simple image with both sizes, a baseline alignment, and a caption
+!! options
+parsoid
+!! input
+[[File:Foobar.jpg|500x10px|baseline|caption]]
+!! result
+<p><span class="mw-valign-baseline" typeof="mw:Image" data-mw='{"caption":"caption"}' data-parsoid='{"optList":[{"ck":"width","ak":"500x10px"},{"ck":"baseline","ak":"baseline"},{"ck":"caption","ak":"caption"}],"size":"500x10"}'><a href="./File:Foobar.jpg" data-parsoid='{"a":{"href":"./File:Foobar.jpg"}}'><img resource="./File:Foobar.jpg" src="//example.com/images/thumb/3/3a/Foobar.jpg/89px-Foobar.jpg" height="10" width="89" data-parsoid='{"a":{"resource":"./File:Foobar.jpg","height":"10","width":"89"},"sa":{"resource":"File:Foobar.jpg"}}'/></a></span></p>
+!! end
+
+!! test
+Parsoid-specific image handling - simple image with border and size spec
+!! options
+parsoid
+!! input
+[[File:Foobar.jpg|50px|border|caption]]
+!! result
+<p><span class="mw-image-border" typeof="mw:Image" data-mw='{"caption":"caption"}' data-parsoid='{"optList":[{"ck":"width","ak":"50px"},{"ck":"border","ak":"border"},{"ck":"caption","ak":"caption"}]}'><a href="./File:Foobar.jpg" data-parsoid='{"a":{"href":"./File:Foobar.jpg"}}'><img resource="./File:Foobar.jpg" src="//example.com/images/thumb/3/3a/Foobar.jpg/50px-Foobar.jpg" height="6" width="50" data-parsoid='{"a":{"resource":"./File:Foobar.jpg","height":"6","width":"50"},"sa":{"resource":"File:Foobar.jpg"}}'/></a></span></p>
+!! end
+
 !! test
 Parsoid-specific image handling - thumbnail with halign, valign, and caption
 !! options
 parsoid
 !! input
-[[Image:Foobar.jpg|thumb|left|baseline|caption content]]
+[[File:Foobar.jpg|left|baseline|thumb|caption content]]
 !! result
 <figure class="mw-default-size mw-halign-left mw-valign-baseline" typeof="mw:Image/Thumb">
 <a href="File:Foobar.jpg">
-<img resource="./File:Foobar.jpg" src="//example.com/images/thumb/3/3a/Foobar.jpg/180px-Foobar.jpg" height="21" width="180" />
+<img resource="./File:Foobar.jpg" src="//example.com/images/thumb/3/3a/Foobar.jpg/180px-Foobar.jpg" height="25" width="220" />
 </a>
 <figcaption>caption content</figcaption>
 </figure>
 !! end
 
+!! test
+Parsoid-specific image handling - thumbnail with halign, valign, and caption
+(existing content)
+!! options
+parsoid
+!! input
+[[File:Foobar.jpg|thumb|left|baseline|caption content]]
+!! result
+<figure class="mw-default-size mw-halign-left mw-valign-baseline" typeof="mw:Image/Thumb" data-parsoid='{"optList":[{"ck":"thumbnail","ak":"thumb"},{"ck":"left","ak":"left"},{"ck":"baseline","ak":"baseline"},{"ck":"caption","ak":"caption content"}]}'><a href="./File:Foobar.jpg" data-parsoid='{"a":{"href":"./File:Foobar.jpg"}}'><img resource="./File:Foobar.jpg" src="//example.com/images/thumb/3/3a/Foobar.jpg/180px-Foobar.jpg" height="25" width="220" data-parsoid='{"a":{"resource":"./File:Foobar.jpg","height":"25","width":"220"},"sa":{"resource":"File:Foobar.jpg"}}'/></a><figcaption>caption content</figcaption></figure>
+!! end
+
 !! test
 Parsoid-specific image handling - thumbnail with specific size, halign, valign, and caption
 !! options
 parsoid
 !! input
-[[Image:Foobar.jpg|thumb|50x50px|right|middle|caption]]
+[[Image:Foobar.jpg|right|middle|thumb|50x50px|caption]]
 !! result
 <figure class="mw-halign-right mw-valign-middle" typeof="mw:Image/Thumb">
 <a href="File:Foobar.jpg">
@@ -10520,12 +10936,23 @@ parsoid
 </figure>
 !! end
 
+!! test
+Parsoid-specific image handling - thumbnail with specific size, halign,
+valign, and caption (existing content)
+!! options
+parsoid
+!! input
+[[File:Foobar.jpg|thumb|50x50px|right|middle|caption]]
+!! result
+<figure class="mw-halign-right mw-valign-middle" typeof="mw:Image/Thumb" data-parsoid='{"optList":[{"ck":"thumbnail","ak":"thumb"},{"ck":"width","ak":"50x50px"},{"ck":"right","ak":"right"},{"ck":"middle","ak":"middle"},{"ck":"caption","ak":"caption"}],"size":"50x50"}'><a href="./File:Foobar.jpg" data-parsoid='{"a":{"href":"./File:Foobar.jpg"}}'><img resource="./File:Foobar.jpg" src="//example.com/images/thumb/3/3a/Foobar.jpg/50px-Foobar.jpg" height="6" width="50" data-parsoid='{"a":{"resource":"./File:Foobar.jpg","height":"6","width":"50"},"sa":{"resource":"File:Foobar.jpg"}}'/></a><figcaption>caption</figcaption></figure>
+!! end
+
 !! test
 Parsoid-specific image handling - framed image with specific size and caption
 !! options
 parsoid
 !! input
-[[Image:Foobar.jpg|500x50px|frame|caption]]
+[[Image:Foobar.jpg|frame|500x50px|caption]]
 !! result
 <figure typeof="mw:Image/Frame">
 <a href="File:Foobar.jpg">
@@ -10535,12 +10962,23 @@ parsoid
 </figure>
 !! end
 
+!! test
+Parsoid-specific image handling - framed image with specific size and caption
+(existing content)
+!! options
+parsoid
+!! input
+[[File:Foobar.jpg|442x50px|frame|caption]]
+!! result
+<figure typeof="mw:Image/Frame" data-parsoid='{"optList":[{"ck":"width","ak":"442x50px"},{"ck":"framed","ak":"frame"},{"ck":"caption","ak":"caption"}],"size":"442x50"}'><a href="./File:Foobar.jpg" data-parsoid='{"a":{"href":"./File:Foobar.jpg"}}'><img resource="./File:Foobar.jpg" src="//example.com/images/thumb/3/3a/Foobar.jpg/442px-Foobar.jpg" height="50" width="442" data-parsoid='{"a":{"resource":"./File:Foobar.jpg","height":"50","width":"442"},"sa":{"resource":"File:Foobar.jpg"}}'/></a><figcaption>caption</figcaption></figure>
+!! end
+
 !! test
 Parsoid-specific image handling - framed image with specific size, halign, valign, and caption
 !! options
 parsoid
 !! input
-[[Image:Foobar.jpg|500x50px|frame|left|baseline|caption]]
+[[Image:Foobar.jpg|left|baseline|frame|500x50px|caption]]
 !! result
 <figure class="mw-halign-left mw-valign-baseline" typeof="mw:Image/Frame">
 <a href="File:Foobar.jpg">
@@ -10550,43 +10988,46 @@ parsoid
 </figure>
 !! end
 
+!! test
+Parsoid-specific image handling - framed image with specific size, halign,
+valign, and caption (existing content)
+!! options
+parsoid
+!! input
+[[File:Foobar.jpg|442x50px|frame|left|baseline|caption]]
+!! result
+<figure class="mw-halign-left mw-valign-baseline" typeof="mw:Image/Frame" data-parsoid='{"optList":[{"ck":"width","ak":"442x50px"},{"ck":"framed","ak":"frame"},{"ck":"left","ak":"left"},{"ck":"baseline","ak":"baseline"},{"ck":"caption","ak":"caption"}],"size":"442x50"}'><a href="./File:Foobar.jpg" data-parsoid='{"a":{"href":"./File:Foobar.jpg"}}'><img resource="./File:Foobar.jpg" src="//example.com/images/thumb/3/3a/Foobar.jpg/442px-Foobar.jpg" height="50" width="442" data-parsoid='{"a":{"resource":"./File:Foobar.jpg","height":"50","width":"442"},"sa":{"resource":"File:Foobar.jpg"}}'/></a><figcaption>caption</figcaption></figure>
+!! end
+
 !! test
 Parsoid-specific image handling - frameless image with specific size, border, and caption
 !! options
 parsoid
 !! input
-[[Image:Foobar.jpg|frameless|500x50px|border|caption]]
+[[File:Foobar.jpg|frameless|442x50px|border|caption]]
 !! result
-<p>
-<span class="mw-image-border" typeof="mw:Image/Frameless" data-mw="{&quot;caption&quot;:&quot;caption&quot;}">
-<a href="File:Foobar.jpg">
-<img resource="./File:Foobar.jpg" src="//example.com/images/thumb/3/3a/Foobar.jpg/442px-Foobar.jpg" height="50" width="442" />
-</a>
-</p>
+<p><span class="mw-image-border" typeof="mw:Image/Frameless" data-mw='{"caption":"caption"}' data-parsoid='{"optList":[{"ck":"frameless","ak":"frameless"},{"ck":"width","ak":"442x50px"},{"ck":"border","ak":"border"},{"ck":"caption","ak":"caption"}],"size":"442x50"}'><a href="./File:Foobar.jpg" data-parsoid='{"a":{"href":"./File:Foobar.jpg"}}'><img resource="./File:Foobar.jpg" src="//example.com/images/thumb/3/3a/Foobar.jpg/442px-Foobar.jpg" height="50" width="442" data-parsoid='{"a":{"resource":"./File:Foobar.jpg","height":"50","width":"442"},"sa":{"resource":"File:Foobar.jpg"}}'/></a></span></p>
 !! end
 
-#!! test
-#Parsoid-specific image handling - simple image with a formatted caption
-#!! options
-#parsoid
-#!! input
-#[[Image:Foobar.jpg|<table><tr><td>a</td><td>b</td></tr><tr><td>c</td></tr></table>]]
-#!! result
-#<p>
-#<span typeof="mw:Image">
-#<a class="mw-default-size" href="Image:Foobar.jpg">
-#<img alt="Foobar.jpg" class="mw-default-size" src="http://example.com/images/3/3a/Foobar.jpg" height="220" width="1941">
-#</a>
-#<span>abc</span>
-#</span>
-#</p>
+!! test
+Parsoid-specific image handling - simple image with a formatted caption
+!! options
+parsoid
+!! input
+[[File:Foobar.jpg|<table><tr><td>a</td><td>b</td></tr><tr><td>c</td></tr></table>]]
+!! result
+<p><span class="mw-default-size" typeof="mw:Image" data-mw='{"caption":"&lt;table>&lt;tr>&lt;td>a&lt;/td>&lt;td>b&lt;/td>&lt;/tr>&lt;tr>&lt;td>c&lt;/td>&lt;/tr>&lt;/table>"}'>
+<a href="File:Foobar.jpg">
+<img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" height="220" width="1941">
+</a></span></p>
+!! end
 
 !! test
 Parsoid-specific image handling - caption with a template in it
 !! options
 parsoid
 !! input
-[[File:Foobar.jpg|thumb|200x200px|This caption has a {{echo|transclusion}} in it.]]
+[[File:Foobar.jpg|thumb|200x23px|This caption has a {{echo|transclusion}} in it.]]
 !! result
 <figure typeof="mw:Image/Thumb"><a href="./File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/thumb/3/3a/Foobar.jpg/200px-Foobar.jpg" height="23" width="200"></a><figcaption>This caption has a <span about="#mwt1" typeof="mw:Transclusion" data-mw="{&quot;parts&quot;:[{&quot;template&quot;:{&quot;target&quot;:{&quot;wt&quot;:&quot;echo&quot;,&quot;href&quot;:&quot;./Template:Echo&quot;},&quot;params&quot;:{&quot;1&quot;:{&quot;wt&quot;:&quot;transclusion&quot;}},&quot;i&quot;:0}}]}">transclusion</span> in it.</figcaption></figure>
 !! end
@@ -10605,6 +11046,40 @@ bar
 <p>bar</p>
 !! end
 
+!! test
+Parsoid-specific image handling - empty caption
+!! options
+parsoid
+!! input
+[[File:Foobar.jpg|thumb|]]
+!! result
+<figure class="mw-default-size" typeof="mw:Image/Thumb"><a href="File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" height="25" width="220"/></a><figcaption></figcaption></figure>
+!! end
+
+!! test
+Parsoid-specific image handling - whitespace caption
+!! options
+parsoid
+!! input
+[[File:Foobar.jpg|thumb| ]]
+!! result
+<figure class="mw-default-size" typeof="mw:Image/Thumb"><a href="File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" height="25" width="220"/></a><figcaption> </figcaption></figure>
+!! end
+
+!! test
+Parsoid-specific image handling - lang option
+!! options
+parsoid
+!! input
+foo
+[[File:Foobar.svg|lang=de|caption]]
+bar
+!! result
+<p>foo
+<span class="mw-default-size" typeof="mw:Image" data-mw='{"caption":"caption"}'><a href="./File:Foobar.svg"><img resource="./File:Foobar.svg" src="//example.com/images/f/ff/Foobar.svg" lang="de" height="180" width="240"/></a></span>
+bar</p>
+!! end
+
 
 ###
 ### Subpages
@@ -13163,7 +13638,7 @@ Special page transclusion
 !! input
 {{Special:Prefixindex/Xyzzyx}}
 !! result
-<table id="mw-prefixindex-list-table"><tr><td><a href="/wiki/Xyzzyx" title="Xyzzyx">Xyzzyx</a></td></tr></table>
+<table class="mw-prefixindex-list-table"><tr><td><a href="/wiki/Xyzzyx" title="Xyzzyx">Xyzzyx</a></td></tr></table>
 
 !! end
 
@@ -13174,8 +13649,8 @@ Special page transclusion twice (bug 5021)
 {{Special:Prefixindex/Xyzzyx}}
 {{Special:Prefixindex/Xyzzyx}}
 !! result
-<table id="mw-prefixindex-list-table"><tr><td><a href="/wiki/Xyzzyx" title="Xyzzyx">Xyzzyx</a></td></tr></table>
-<table id="mw-prefixindex-list-table"><tr><td><a href="/wiki/Xyzzyx" title="Xyzzyx">Xyzzyx</a></td></tr></table>
+<table class="mw-prefixindex-list-table"><tr><td><a href="/wiki/Xyzzyx" title="Xyzzyx">Xyzzyx</a></td></tr></table>
+<table class="mw-prefixindex-list-table"><tr><td><a href="/wiki/Xyzzyx" title="Xyzzyx">Xyzzyx</a></td></tr></table>
 
 !! end
 
@@ -14442,6 +14917,15 @@ ISBN ISBN 1234567890
 </p>
 !! end
 
+!! test
+ISBN with an X
+!! input
+ISBN 3-462-04561-X
+!! result
+<p><a href="/wiki/Special:BookSources/346204561X" class="internal mw-magiclink-isbn">ISBN 3-462-04561-X</a>
+</p>
+!! end
+
 !! test
 Bug 22905: <abbr> followed by ISBN followed by </a>
 !! input
@@ -17036,10 +17520,10 @@ A <ref>
 
 <references />
 !!result
-<p>A <span about="#mwt2" class="reference" data-mw='{"name":"ref","body":{"html":"This is a &lt;b data-parsoid=&#39;{\"dsr\":[19,40,3,3]}&#39;>&lt;a rel=\"mw:WikiLink\" href=\"./Bolded_link\" data-parsoid=&#39;{\"stx\":\"simple\",\"a\":{\"href\":\"./Bolded_link\"},\"sa\":{\"href\":\"bolded link\"},\"dsr\":[22,37,2,2]}&#39;>bolded link&lt;/a>&lt;/b> and this is a &lt;span about=\"#mwt5\" typeof=\"mw:Transclusion\" data-mw=&#39;{\"parts\":[{\"template\":{\"target\":{\"wt\":\"echo\",\"href\":\"./Template:Echo\"},\"params\":{\"1\":{\"wt\":\"transclusion\"}},\"i\":0}}]}&#39; data-parsoid=&#39;{\"dsr\":[55,76,null,null],\"pi\":[[{\"k\":\"1\",\"spc\":[\"\",\"\",\"\",\"\"]}]]}&#39;>transclusion&lt;/span>\n"},"attrs":{}}' id="cite_ref-1-0" rel="dc:references" typeof="mw:Extension/ref"><a href="#cite_note-1">[1]</a></span></p>
+<p>A <span about="#mwt2" class="reference" data-mw='{"name":"ref","body":{"html":"This is a &lt;b data-parsoid=&#39;{\"dsr\":[19,40,3,3]}&#39;>&lt;a rel=\"mw:WikiLink\" href=\"./Bolded_link\" data-parsoid=&#39;{\"stx\":\"simple\",\"a\":{\"href\":\"./Bolded_link\"},\"sa\":{\"href\":\"bolded link\"},\"dsr\":[22,37,2,2]}&#39;>bolded link&lt;/a>&lt;/b> and this is a &lt;span about=\"#mwt3\" typeof=\"mw:Transclusion\" data-mw=&#39;{\"parts\":[{\"template\":{\"target\":{\"wt\":\"echo\",\"href\":\"./Template:Echo\"},\"params\":{\"1\":{\"wt\":\"transclusion\"}},\"i\":0}}]}&#39; data-parsoid=&#39;{\"dsr\":[55,76,null,null],\"pi\":[[{\"k\":\"1\",\"spc\":[\"\",\"\",\"\",\"\"]}]]}&#39;>transclusion&lt;/span>\n"},"attrs":{}}' id="cite_ref-1-0" rel="dc:references" typeof="mw:Extension/ref"><a href="#cite_note-1">[1]</a></span></p>
 
 <ol class="references" typeof="mw:Extension/references" about="#mwt4" data-mw='{"name":"references","attrs":{}}'>
-<li about="#cite_note-1" id="cite_note-1"><span rel="mw:referencedBy"><a href="#cite_ref-1-0">↑</a></span> This is a <b><a rel="mw:WikiLink" href="./Bolded_link">bolded link</a></b> and this is a <span about="#mwt5" typeof="mw:Transclusion" data-mw='{"parts":[{"template":{"target":{"wt":"echo","href":"./Template:Echo"},"params":{"1":{"wt":"transclusion"}},"i":0}}]}'>transclusion</span>
+<li about="#cite_note-1" id="cite_note-1"><span rel="mw:referencedBy"><a href="#cite_ref-1-0">↑</a></span> This is a <b><a rel="mw:WikiLink" href="./Bolded_link">bolded link</a></b> and this is a <span about="#mwt3" typeof="mw:Transclusion" data-mw='{"parts":[{"template":{"target":{"wt":"echo","href":"./Template:Echo"},"params":{"1":{"wt":"transclusion"}},"i":0}}]}'>transclusion</span>
 </li>
 </ol>
 !!end
@@ -17142,11 +17626,11 @@ A <ref> <b> foo </ref> B C
 
 <references />
 !!result
-<p data-parsoid='{"dsr":[0,26,0,0]}'>A <span about="#mwt2" class="reference" data-mw='{"name":"ref","body":{"html":"&lt;b data-parsoid=&#39;{\"stx\":\"html\",\"autoInsertedEnd\":true,\"dsr\":[8,16,3,0]}&#39;> foo &lt;/b>"},"attrs":{}}' id="cite_ref-1-0" rel="dc:references" typeof="mw:Extension/ref" data-parsoid='{"src":"&lt;ref> &lt;b> foo &lt;/ref>","dsr":[2,22,5,6]}'><a href="#cite_note-1">[1]</a></span> B C</p>
+<p>A <span about="#mwt2" class="reference" data-mw='{"name":"ref","body":{"html":"&lt;b data-parsoid=&#39;{\"stx\":\"html\",\"autoInsertedEnd\":true,\"dsr\":[8,16,3,0]}&#39;> foo &lt;/b>"},"attrs":{}}' id="cite_ref-1-0" rel="dc:references" typeof="mw:Extension/ref" data-parsoid='{"src":"&lt;ref> &lt;b> foo &lt;/ref>"}'><a href="#cite_note-1">[1]</a></span> B C</p>
 
 
-<ol class="references" typeof="mw:Extension/references" about="#mwt4" data-parsoid='{"src":"&lt;references />","dsr":[28,42,2,2]}' data-mw='{"name":"references","attrs":{}}'>
-<li about="#cite_note-1" id="cite_note-1" data-parsoid="{}"><span rel="mw:referencedBy"><a href="#cite_ref-1-0">↑</a></span> <b data-parsoid='{"stx":"html","autoInsertedEnd":true,"dsr":[8,16,3,0]}'> foo </b></li>
+<ol class="references" typeof="mw:Extension/references" about="#mwt4" data-parsoid='{"src":"&lt;references />"}' data-mw='{"name":"references","attrs":{}}'>
+<li about="#cite_note-1" id="cite_note-1" data-parsoid="{}"><span rel="mw:referencedBy"><a href="#cite_ref-1-0">↑</a></span> <b data-parsoid='{"stx":"html","autoInsertedEnd":true}'> foo </b></li>
 </ol>
 !!end
 
@@ -17158,8 +17642,8 @@ parsoid
 A <ref>foo</ref> B
 C <ref>bar</ref> D
 !!result
-<p data-parsoid='{"dsr":[0,37,0,0]}'>A <span about="#mwt2" class="reference" data-mw='{"name":"ref","body":{"html":"foo"},"attrs":{}}' id="cite_ref-1-0" rel="dc:references" typeof="mw:Extension/ref" data-parsoid='{"src":"&lt;ref>foo&lt;/ref>","dsr":[2,16,5,6]}'><a href="#cite_note-1">[1]</a></span> B
-C <span about="#mwt4" class="reference" data-mw='{"name":"ref","body":{"html":"bar"},"attrs":{}}' id="cite_ref-2-0" rel="dc:references" typeof="mw:Extension/ref" data-parsoid='{"src":"&lt;ref>bar&lt;/ref>","dsr":[21,35,5,6]}'><a href="#cite_note-2">[2]</a></span> D</p>
+<p>A <span about="#mwt2" class="reference" data-mw='{"name":"ref","body":{"html":"foo"},"attrs":{}}' id="cite_ref-1-0" rel="dc:references" typeof="mw:Extension/ref" data-parsoid='{"src":"&lt;ref>foo&lt;/ref>"}'><a href="#cite_note-1">[1]</a></span> B
+C <span about="#mwt4" class="reference" data-mw='{"name":"ref","body":{"html":"bar"},"attrs":{}}' id="cite_ref-2-0" rel="dc:references" typeof="mw:Extension/ref" data-parsoid='{"src":"&lt;ref>bar&lt;/ref>"}'><a href="#cite_note-2">[2]</a></span> D</p>
 !!end
 
 !!test
@@ -17206,9 +17690,9 @@ parsoid
 
 <references />
 !!result
-<p data-parsoid='{"dsr":[0,33,0,0]}'><span about="#mwt2" class="reference" data-mw='{"name":"ref","body":{"html":"foo &amp;lt;ref>bar&amp;lt;/ref> baz"},"attrs":{}}' id="cite_ref-1-0" rel="dc:references" typeof="mw:Extension/ref" data-parsoid='{"src":"&lt;ref>foo &lt;ref>bar&lt;/ref> baz&lt;/ref>","dsr":[0,33,5,6]}'><a href="#cite_note-1">[1]</a></span></p>
+<p><span about="#mwt2" class="reference" data-mw='{"name":"ref","body":{"html":"foo &amp;lt;ref>bar&amp;lt;/ref> baz"},"attrs":{}}' id="cite_ref-1-0" rel="dc:references" typeof="mw:Extension/ref" data-parsoid='{"src":"&lt;ref>foo &lt;ref>bar&lt;/ref> baz&lt;/ref>"}'><a href="#cite_note-1">[1]</a></span></p>
 
-<ol class="references" typeof="mw:Extension/references" about="#mwt5" data-parsoid='{"src":"&lt;references />","dsr":[35,49,2,2]}' data-mw='{"name":"references","attrs":{}}'>
+<ol class="references" typeof="mw:Extension/references" about="#mwt5" data-parsoid='{"src":"&lt;references />"}' data-mw='{"name":"references","attrs":{}}'>
 <li about="#cite_note-1" id="cite_note-1" data-parsoid="{}"><span rel="mw:referencedBy"><a href="#cite_ref-1-0">↑</a></span> foo &lt;ref>bar&lt;/ref> baz</li>
 </ol>
 !!end
@@ -17267,7 +17751,7 @@ B <ref group="b">bar</ref>
 <references group="a" />
 !!result
 <p>A <span about="#mwt2" class="reference" data-mw='{"name":"ref","body":{"html":"foo"},"attrs":{"group":"a"}}' id="cite_ref-1-0" rel="dc:references" typeof="mw:Extension/ref"><a href="#cite_note-1">[a 1]</a></span>
-B <span about="#mwt4" class="reference" data-mw='{"name":"ref","body":{"html":"bar"},"attrs":{"group":"b"}}' id="cite_ref-1-0" rel="dc:references" typeof="mw:Extension/ref"><a href="#cite_note-1">[b 1]</a></span></p>
+B <span about="#mwt4" class="reference" data-mw='{"name":"ref","body":{"html":"bar"},"attrs":{"group":"b"}}' id="cite_ref-2-0" rel="dc:references" typeof="mw:Extension/ref"><a href="#cite_note-2">[b 1]</a></span></p>
 
 <ol about="#mwt6" class="references" typeof="mw:Extension/references" data-mw='{"name":"references","attrs":{"group":"a"}}'><li about="#cite_note-1" id="cite_note-1"><span rel="mw:referencedBy"><a href="#cite_ref-1-0">↑</a></span> foo</li>
 </ol>
@@ -17291,9 +17775,9 @@ B <ref>bar</ref>
 <ol about="#mwt4" class="references" typeof="mw:Extension/references" data-mw='{"name":"references","attrs":{}}'><li about="#cite_note-1" id="cite_note-1"><span rel="mw:referencedBy"><a href="#cite_ref-1-0">↑</a></span> foo</li>
 </ol>
 
-<p>B <span about="#mwt6" class="reference" data-mw='{"name":"ref","body":{"html":"bar"},"attrs":{}}' id="cite_ref-1-0" rel="dc:references" typeof="mw:Extension/ref"><a href="#cite_note-1">[1]</a></span></p>
+<p>B <span about="#mwt6" class="reference" data-mw='{"name":"ref","body":{"html":"bar"},"attrs":{}}' id="cite_ref-2-0" rel="dc:references" typeof="mw:Extension/ref"><a href="#cite_note-2">[1]</a></span></p>
 
-<ol about="#mwt8" class="references" typeof="mw:Extension/references" data-mw='{"name":"references","attrs":{}}'><li about="#cite_note-1" id="cite_note-1"><span rel="mw:referencedBy"><a href="#cite_ref-1-0">↑</a></span> bar</li>
+<ol about="#mwt8" class="references" typeof="mw:Extension/references" data-mw='{"name":"references","attrs":{}}'><li about="#cite_note-2" id="cite_note-2"><span rel="mw:referencedBy"><a href="#cite_ref-2-0">↑</a></span> bar</li>
 </ol>
 !!end
 
@@ -17312,14 +17796,14 @@ C <ref>cfoo</ref>
 <references />
 !!result
 <p>A <span about="#mwt2" class="reference" data-mw='{"name":"ref","body":{"html":"afoo"},"attrs":{"group":"a"}}' id="cite_ref-1-0" rel="dc:references" typeof="mw:Extension/ref"><a href="#cite_note-1">[a 1]</a></span>
-B <span about="#mwt4" class="reference" data-mw='{"name":"ref","body":{"html":"bfoo"},"attrs":{}}' id="cite_ref-1-0" rel="dc:references" typeof="mw:Extension/ref" data-parsoid='{"src":"<ref>bfoo</ref>","dsr":[30,45,5,6]}'><a href="#cite_note-1">[1]</a></span></p>
+B <span about="#mwt4" class="reference" data-mw='{"name":"ref","body":{"html":"bfoo"},"attrs":{}}' id="cite_ref-2-0" rel="dc:references" typeof="mw:Extension/ref" data-parsoid='{"src":"<ref>bfoo</ref>"}'><a href="#cite_note-2">[1]</a></span></p>
 
 <ol about="#mwt6" class="references" typeof="mw:Extension/references" data-mw='{"name":"references","attrs":{"group":"a"}}'><li about="#cite_note-1" id="cite_note-1"><span rel="mw:referencedBy"><a href="#cite_ref-1-0">↑</a></span> afoo</li>
 </ol>
 
-<p>C <span about="#mwt8" class="reference" data-mw='{"name":"ref","body":{"html":"cfoo"},"attrs":{}}' id="cite_ref-2-0" rel="dc:references" typeof="mw:Extension/ref"><a href="#cite_note-2">[2]</a></span></p>
+<p>C <span about="#mwt8" class="reference" data-mw='{"name":"ref","body":{"html":"cfoo"},"attrs":{}}' id="cite_ref-3-0" rel="dc:references" typeof="mw:Extension/ref"><a href="#cite_note-3">[2]</a></span></p>
 
-<ol about="#mwt10" class="references" typeof="mw:Extension/references" data-mw='{"name":"references","attrs":{}}'><li about="#cite_note-1" id="cite_note-1"><span rel="mw:referencedBy"><a href="#cite_ref-1-0">↑</a></span> bfoo</li><li about="#cite_note-2" id="cite_note-2"><span rel="mw:referencedBy"><a href="#cite_ref-2-0">↑</a></span> cfoo</li>
+<ol about="#mwt10" class="references" typeof="mw:Extension/references" data-mw='{"name":"references","attrs":{}}'><li about="#cite_note-2" id="cite_note-2"><span rel="mw:referencedBy"><a href="#cite_ref-2-0">↑</a></span> bfoo</li><li about="#cite_note-3" id="cite_note-3"><span rel="mw:referencedBy"><a href="#cite_ref-3-0">↑</a></span> cfoo</li>
 </ol>
 !!end
 
@@ -17336,11 +17820,11 @@ B <ref name="b">bar</ref>
 This should just get lost.
 </references>
 !!result
-<p data-parsoid='{"dsr":[0,57,0,0]}'>A <span about="#mwt2" class="reference" data-mw='{"name":"ref","attrs":{"name":"a"}}' id="cite_ref-a-1-0" rel="dc:references" typeof="mw:Extension/ref" data-parsoid='{"src":"&lt;ref name=\"a\" />","dsr":[2,18,16,0]}'><a href="#cite_note-a-1">[1]</a></span>
-B <span about="#mwt4" class="reference" data-mw='{"name":"ref","body":{"html":"bar"},"attrs":{"name":"b"}}' id="cite_ref-b-2-0" rel="dc:references" typeof="mw:Extension/ref" data-parsoid='{"src":"&lt;ref name=\"b\">bar&lt;/ref>","dsr":[21,44,14,6]}'><a href="#cite_note-b-2">[2]</a></span></p>
+<p>A <span about="#mwt2" class="reference" data-mw='{"name":"ref","attrs":{"name":"a"}}' id="cite_ref-a-1-0" rel="dc:references" typeof="mw:Extension/ref" data-parsoid='{"src":"&lt;ref name=\"a\" />"}'><a href="#cite_note-a-1">[1]</a></span>
+B <span about="#mwt4" class="reference" data-mw='{"name":"ref","body":{"html":"bar"},"attrs":{"name":"b"}}' id="cite_ref-b-2-0" rel="dc:references" typeof="mw:Extension/ref" data-parsoid='{"src":"&lt;ref name=\"b\">bar&lt;/ref>"}'><a href="#cite_note-b-2">[2]</a></span></p>
 
 
-<ol class="references" typeof="mw:Extension/references" about="#mwt6" data-parsoid='{"src":"&lt;references>\n&lt;ref name=\"a\">foo&lt;/ref>\nThis should just get lost.\n&lt;/references>","dsr":[46,123,2,2]}' data-mw='{"name":"references","body":{"extsrc":"&lt;ref name=\"a\">foo&lt;/ref>\nThis should just get lost.","html":"\n&lt;span about=\"#mwt8\" class=\"reference\" data-mw=&#39;{\"name\":\"ref\",\"body\":{\"html\":\"foo\"},\"attrs\":{\"name\":\"a\"}}&#39; rel=\"dc:references\" typeof=\"mw:Extension/ref\">&lt;a href=\"#cite_note-a-1\">[1]&lt;/a>&lt;/span>\n"},"attrs":{}}'>
+<ol class="references" typeof="mw:Extension/references" about="#mwt6" data-parsoid='{"src":"&lt;references>\n&lt;ref name=\"a\">foo&lt;/ref>\nThis should just get lost.\n&lt;/references>"}' data-mw='{"name":"references","body":{"extsrc":"&lt;ref name=\"a\">foo&lt;/ref>\nThis should just get lost.","html":"\n&lt;span about=\"#mwt8\" class=\"reference\" data-mw=&#39;{\"name\":\"ref\",\"body\":{\"html\":\"foo\"},\"attrs\":{\"name\":\"a\"}}&#39; rel=\"dc:references\" typeof=\"mw:Extension/ref\">&lt;a href=\"#cite_note-a-1\">[1]&lt;/a>&lt;/span>\n"},"attrs":{}}'>
 <li about="#cite_note-a-1" id="cite_note-a-1" data-parsoid="{}"><span rel="mw:referencedBy"><a href="#cite_ref-a-1-0">↑</a></span> foo</li>
 <li about="#cite_note-b-2" id="cite_note-b-2" data-parsoid="{}"><span rel="mw:referencedBy"><a href="#cite_ref-b-2-0">↑</a></span> bar</li>
 </ol>
@@ -17370,20 +17854,49 @@ B <ref name="b" />
 <ref name="b">foo</ref>
 </references>
 !! result
-<p data-parsoid='{"dsr":[0,45,0,0]}'>A <span about="#mwt2" class="reference" data-mw='{"name":"ref","body":{"html":"foo bar for a"},"attrs":{}}' id="cite_ref-1-0" rel="dc:references" typeof="mw:Extension/ref" data-parsoid='{"src":"&lt;ref>foo bar for a&lt;/ref>","dsr":[2,26,5,6]}'><a href="#cite_note-1">[1]</a></span>
-B <span about="#mwt4" class="reference" data-mw='{"name":"ref","attrs":{"name":"b"}}' id="cite_ref-b-2-0" rel="dc:references" typeof="mw:Extension/ref" data-parsoid='{"src":"&lt;ref name=\"b\" />","dsr":[29,45,16,0]}'><a href="#cite_note-b-2">[2]</a></span></p>
+<p>A <span about="#mwt2" class="reference" data-mw='{"name":"ref","body":{"html":"foo bar for a"},"attrs":{}}' id="cite_ref-1-0" rel="dc:references" typeof="mw:Extension/ref" data-parsoid='{"src":"&lt;ref>foo bar for a&lt;/ref>"}'><a href="#cite_note-1">[1]</a></span>
+B <span about="#mwt4" class="reference" data-mw='{"name":"ref","attrs":{"name":"b"}}' id="cite_ref-b-2-0" rel="dc:references" typeof="mw:Extension/ref" data-parsoid='{"src":"&lt;ref name=\"b\" />"}'><a href="#cite_note-b-2">[2]</a></span></p>
 
 
-<ol class="references" typeof="mw:Extension/references" about="#mwt6" data-parsoid='{"src":"&lt;references />","dsr":[47,61,2,2]}' data-mw='{"name":"references","attrs":{}}'>
+<ol class="references" typeof="mw:Extension/references" about="#mwt6" data-parsoid='{"src":"&lt;references />"}' data-mw='{"name":"references","attrs":{}}'>
 <li about="#cite_note-1" id="cite_note-1" data-parsoid="{}"><span rel="mw:referencedBy"><a href="#cite_ref-1-0">↑</a></span> foo bar for a</li>
 <li about="#cite_note-b-2" id="cite_note-b-2" data-parsoid="{}"><span rel="mw:referencedBy"><a href="#cite_ref-b-2-0">↑</a></span> </li></ol>
 
 
-<ol class="references" typeof="mw:Extension/references" about="#mwt8" data-parsoid='{"src":"&lt;references>\n&lt;ref name=\"b\">foo&lt;/ref>\n&lt;/references>","dsr":[63,113,2,2]}' data-mw='{"name":"references","body":{"extsrc":"&lt;ref name=\"b\">foo&lt;/ref>","html":"\n&lt;span about=\"#mwt10\" class=\"reference\" data-mw=&#39;{\"name\":\"ref\",\"body\":{\"html\":\"foo\"},\"attrs\":{\"name\":\"b\"}}&#39; rel=\"dc:references\" typeof=\"mw:Extension/ref\">&lt;a href=\"#cite_note-b-1\">[1]&lt;/a>&lt;/span>\n"},"attrs":{}}'>
-<li about="#cite_note-b-1" id="cite_note-b-1" data-parsoid="{}"><span rel="mw:referencedBy">↑</span> foo</li>
+<ol class="references" typeof="mw:Extension/references" about="#mwt8" data-parsoid='{"src":"&lt;references>\n&lt;ref name=\"b\">foo&lt;/ref>\n&lt;/references>"}' data-mw='{"name":"references","body":{"extsrc":"&lt;ref name=\"b\">foo&lt;/ref>","html":"\n&lt;span about=\"#mwt10\" class=\"reference\" data-mw=&#39;{\"name\":\"ref\",\"body\":{\"html\":\"foo\"},\"attrs\":{\"name\":\"b\"}}&#39; rel=\"dc:references\" typeof=\"mw:Extension/ref\">&lt;a href=\"#cite_note-b-3\">[1]&lt;/a>&lt;/span>\n"},"attrs":{}}'>
+<li about="#cite_note-b-3" id="cite_note-b-3" data-parsoid="{}"><span rel="mw:referencedBy">↑</span> foo</li>
 </ol>
 !! end
 
+# This test is wt2html only because we're permitting the serializer to produce
+# dirty diffs, normalizing the unclosed references to the self-closed version.
+!! test
+Generate references for unclosed references tag
+!! options
+parsoid=wt2html
+!! input
+a<ref>foo</ref>
+
+<references>
+!! result
+<p data-parsoid='{}'>a<span about="#mwt2" class="reference" data-mw='{"name":"ref","body":{"html":"foo"},"attrs":{}}' id="cite_ref-1-0" rel="dc:references" typeof="mw:Extension/ref" data-parsoid='{"src":"&lt;ref>foo&lt;/ref>"}'><a href="#cite_note-1" data-parsoid="{}">[1]</a></span></p>
+
+
+<ol class="references" typeof="mw:Extension/references" about="#mwt4" data-parsoid='{"src":"&lt;references>"}' data-mw='{"name":"references","attrs":{}}'>
+<li about="#cite_note-1" id="cite_note-1" data-parsoid="{}"><span rel="mw:referencedBy" data-parsoid="{}"><a href="#cite_ref-1-0" data-parsoid="{}">↑</a></span> foo</li></ol>
+!! end
+
+!! test
+New reference serializes on its own line
+!! options
+parsoid=wt2wt,html2wt
+!! input
+foo
+<references />
+!! result
+foo<ol class="references" typeof="mw:Extension/references" about="#mwt2" data-mw='{"name":"references","attrs":{}}'></ol>
+!! end
+
 #### ----------------------------------------------------------------
 #### The following section of tests are primarily to test
 #### wikitext escaping capabilities of Parsoid.  Given that
@@ -18111,6 +18624,21 @@ parsoid
 </tbody></table>
 !! end
 
+!! test
+Tables: Digest broken attributes on table and tr tag
+!! options
+parsoid=wt2html
+!! input
+{| || |} ++
+|- || || ++ --
+|}
+!! result
+<table>
+<tbody>
+<tr></tr>
+</tbody></table>
+!! end
+
 #### --------------- Links ----------------
 #### 1. Quote marks in link text
 #### 2. Wikilinks: Escapes needed
@@ -18133,15 +18661,17 @@ Links 2. WikiLinks: Escapes needed
 !! options
 parsoid
 !! input
-[[Foo|<nowiki>[Foobar]</nowiki>]]
+[[Foo|[Foobar]]]
 [[Foo|<nowiki>Foobar]</nowiki>]]
 [[Foo|x [Foobar] x]]
-[[Foo|<nowiki>x [http://google.com g] x</nowiki>]]
+[[Foo|x <nowiki>[http://google.com g]</nowiki> x]]
 [[Foo|<nowiki>[[Bar]]</nowiki>]]
 [[Foo|<nowiki>x [[Bar]] x</nowiki>]]
 [[Foo|<nowiki>|Bar</nowiki>]]
 [[Foo|<nowiki>]]bar</nowiki>]]
 [[Foo|<nowiki>[[bar</nowiki>]]
+[[Foo|<nowiki>x [[ y</nowiki>]]
+[[Foo|<nowiki>x ]] y</nowiki>]]
 [[Foo|<nowiki>x ]] y [[ z</nowiki>]]
 !! result
 <a href="Foo" rel="mw:WikiLink">[Foobar]</a>
@@ -18153,6 +18683,8 @@ parsoid
 <a href="Foo" rel="mw:WikiLink">|Bar</a>
 <a href="Foo" rel="mw:WikiLink">]]bar</a>
 <a href="Foo" rel="mw:WikiLink">[[bar</a>
+<a href="Foo" rel="mw:WikiLink">x [[ y</a>
+<a href="Foo" rel="mw:WikiLink">x ]] y</a>
 <a href="Foo" rel="mw:WikiLink">x ]] y [[ z</a>
 !! end
 
@@ -18829,7 +19361,7 @@ plain text
 !!end
 
 !!test
-Ensure fostered text content is wrapped in spans
+1. Ensure fostered text content is wrapped in spans
 !!options
 parsoid=wt2html
 !!input
@@ -18841,6 +19373,24 @@ parsoid=wt2html
 <table></table>
 !!end
 
+!!test
+2. Ensure fostered text content is wrapped in spans (traps regressions around fostered marker on the span getting lost)
+!!options
+parsoid=wt2html,wt2wt
+!!input
+<table>
+<tr> || ||
+<td> a
+</table>
+!!result
+<span> || ||</span>
+<table>
+<tbody>
+<tr>
+<td> a</td></tr>
+</tbody></table>
+!!end
+
 !!test
 Encapsulation properly handles null DSR information from foster box
 !!options
@@ -19023,14 +19573,24 @@ parsoid=wt2html,wt2wt
 </div>
 |}
 !!result
-<div about="#mwt1" typeof="mw:Transclusion" data-mw='{"parts":[{"template":{"target":{"wt":"OpenTable","href":"./Template:OpenTable"},"params":{},"i":0}},"\n&lt;div>"]}' data-parsoid='{"stx":"html","autoInsertedEnd":true,"dsr":[0,19,null,null],"src":"{{OpenTable}}\n&lt;div>","pi":[[]]}'></div><span about="#mwt1" data-parsoid="{}">
+<div about="#mwt1" typeof="mw:Transclusion" data-mw='{"parts":[{"template":{"target":{"wt":"OpenTable","href":"./Template:OpenTable"},"params":{},"i":0}},"\n&lt;div>"]}' data-parsoid='{"stx":"html","autoInsertedEnd":true,"pi":[[]]}'></div><span about="#mwt1" data-parsoid="{}">
 </span>
-<table about="#mwt1" data-parsoid='{"autoInsertedEnd":true,"dsr":[null,19,2,0]}'></table>
+<table about="#mwt1" data-parsoid='{"autoInsertedEnd":true}'></table>
 
-<table data-parsoid='{"dsr":[20,25,2,2]}'>
+<table>
 </table>
 !!end
 
+!!test
+Support <object> element with .data attribute
+!!options
+parsoid=html2wt
+!!input
+<object data="test.swf"></object>
+!!result
+<object data="test.swf"></object>
+!!end
+
 # -----------------------------------------------------------------
 # The following section of tests are primarily to spec requirements
 # around serialization of new/edited content.
@@ -19039,25 +19599,134 @@ parsoid=wt2html,wt2wt
 # ----------------------------------------------------------------
 
 !! test
-Image: Modifying size of an image
+Image: Modifying size of an image (1)
+!! options
+parsoid=html2wt
+!! input
+[[Image:Foobar.jpg|200x200px]]
+!! result
+<p><span typeof="mw:Image" data-parsoid='{"optList":[{"ck":"width","ak":"230x230px"}]}'><a href="./File:Foobar.jpg" data-parsoid='{"a":{"href":"./File:Foobar.jpg"}}'><img resource="./File:Foobar.jpg" src="//example.com/images/thumb/3/3a/Foobar.jpg/230px-Foobar.jpg" height="22" width="200" data-parsoid='{"a":{"resource":"./File:Foobar.jpg","height":"26","width":"230"},"sa":{"resource":"Image:Foobar.jpg"}}'/></a></span></p>
+!!end
+
+!! test
+Image: Modifying size of an image (2)
+!! options
+parsoid=html2wt
+!! input
+[[Image:Foobar.jpg|500x500px]]
+!! result
+<p><span typeof="mw:Image" data-parsoid='{"optList":[{"ck":"width","ak":"230x230px"}]}'><a href="./File:Foobar.jpg" data-parsoid='{"a":{"href":"./File:Foobar.jpg"}}'><img resource="./File:Foobar.jpg" src="//example.com/images/thumb/3/3a/Foobar.jpg/230px-Foobar.jpg" height="100" width="500" data-parsoid='{"a":{"resource":"./File:Foobar.jpg","height":"26","width":"230"},"sa":{"resource":"Image:Foobar.jpg"}}'/></a></span></p>
+!!end
+
+# note that the data-parsoid value conflicts with the figure's class
+!! test
+Image: Modifying alignment of an image (bug 48665)
+!! options
+parsoid=html2wt
+!! input
+[[Image:Foobar.jpg|thumb|caption|left]]
+!! result
+<figure class="mw-default-size mw-halign-left" typeof="mw:Image/Thumb" data-parsoid='{"optList":[{"ck":"thumbnail","ak":"thumb"},{"ck":"caption","ak":"caption"},{"ck":"right","ak":"right"}]}'><a href="./File:Foobar.jpg" data-parsoid='{"a":{"href":"./File:Foobar.jpg"}}'><img resource="./File:Foobar.jpg" src="//example.com/images/thumb/3/3a/Foobar.jpg/180px-Foobar.jpg" height="20" width="180" data-parsoid='{"a":{"resource":"./File:Foobar.jpg","height":"20","width":"180"},"sa":{"resource":"Image:Foobar.jpg"}}'/></a><figcaption>caption</figcaption></figure>
+!! end
+
+!! test
+Image: Modifying valign of an image (bug 49221)
 !! options
 parsoid=html2wt
 !! input
-[[Image:Wiki.png|230x230px]]
+[[File:Foobar.jpg|20px|text-top]]
 !! result
-<p data-parsoid='{"dsr":[0,24,0,0]}'><span typeof="mw:Image" data-parsoid='{"optList":[{"ck":"width","ak":"100px"}],"cacheKey":"[[Image:Wiki.png|100px]]","img":{"h":115,"w":100,"wdset":true},"dsr":[0,24,null,null]}'><a href="./File:Wiki.png" data-parsoid='{"a":{"href":"./File:Wiki.png"}}'><img resource="./File:Wiki.png" src="//upload.wikimedia.org/wikipedia/en/thumb/b/bc/Wiki.png/100px-Wiki.png" height="230" width="200" data-parsoid='{"a":{"resource":"./File:Wiki.png"},"sa":{"resource":"Image:Wiki.png"}}'></a></span></p>
+<p><span class="mw-valign-text-top" typeof="mw:Image" data-parsoid='{"optList":[{"ck":"width","ak":"20px"},{"ck":"text_top","ak":"text-top"}]}'><a href="./File:Foobar.jpg" data-parsoid='{"a":{"href":"./File:Foobar.jpg"}}'><img resource="./File:Foobar.jpg" src="//example.com/images/thumb/3/3a/Foobar.jpg/20px-Foobar.jpg" height="2" width="20" data-parsoid='{"a":{"resource":"./File:Foobar.jpg","height":"2","width":"20"},"sa":{"resource":"File:Foobar.jpg"}}'/></a></span></p>
+!! end
+
+!! test
+Image: Modifying alt attribute of an image (bug 56400)
+!! options
+parsoid=html2wt
+!! input
+[[File:Foobar.jpg|thumb|some caption|alt=some alternate edited text]]
+!! result
+<figure class="mw-default-size" typeof="mw:Image/Thumb" data-parsoid='{"optList":[{"ck":"thumbnail","ak":"thumb"},{"ck":"caption","ak":"some caption"},{"ck":"alt","ak":"alt=some alternate text"}]}'><a href="./File:Foobar.jpg" data-parsoid='{"a":{"href":"./File:Foobar.jpg"}}'><img alt="some alternate edited text" resource="./File:Foobar.jpg" src="//example.com/images/thumb/3/3a/Foobar.jpg/180px-Foobar.jpg" height="20" width="180" data-parsoid='{"a":{"alt":"some alternate edited text","resource":"./File:Foobar.jpg","height":"20","width":"180"},"sa":{"alt":"alt=some alternate edited text","resource":"File:Foobar.jpg"}}'/></a><figcaption>some caption</figcaption></figure>
 !!end
 
 !! test
-Image: New block level image should have \n before and after
+Image: Modifying caption of an image
 !! options
 parsoid=html2wt
 !! input
+[[Image:Foobar.jpg|thumb|new caption]]
+!! result
+<figure class="mw-default-size" typeof="mw:Image/Thumb" data-parsoid='{"optList":[{"ck":"thumbnail","ak":"thumb"},{"ck":"caption","ak":"original caption"}]}'><a href="./File:Foobar.jpg" data-parsoid='{"a":{"href":"./File:Foobar.jpg"}}'><img resource="./File:Foobar.jpg" src="//example.com/images/thumb/3/3a/Foobar.jpg/180px-Foobar.jpg" height="20" width="180" data-parsoid='{"a":{"resource":"./File:Foobar.jpg","height":"20","width":"180"},"sa":{"resource":"Image:Foobar.jpg"}}'/></a><figcaption>new caption</figcaption></figure>
+!!end
+
+!! test
+Image: empty alt attribute (bug 48924)
+!! options
+parsoid
+!! input
+[[File:Foobar.jpg|thumb|alt=|bar]]
+!! result
+<figure class="mw-default-size" typeof="mw:Image/Thumb" data-parsoid='{"optList":[{"ck":"thumbnail","ak":"thumb"},{"ck":"alt","ak":"alt="},{"ck":"caption","ak":"bar"}]}'><a href="./File:Foobar.jpg" data-parsoid='{"a":{"href":"./File:Foobar.jpg"}}'><img alt="" resource="./File:Foobar.jpg" src="//example.com/images/thumb/3/3a/Foobar.jpg/220px-Foobar.jpg" height="25" width="220" data-parsoid='{"a":{"alt":"","resource":"./File:Foobar.jpg","height":"25","width":"220"},"sa":{"alt":"alt=","resource":"File:Foobar.jpg"}}'/></a><figcaption>bar</figcaption></figure>
+!! end
+
+#!! test
+#Image: new attributes should be serialized in wiki's language for RTL languages (bug 51852)
+#!! options
+#parsoid=html2wt
+#language=ar
+#!! input
+#[[Imagen:Foobar.jpg|derecha|miniaturadeimagen]]
+#!! result
+#<figure class="mw-default-size mw-halign-right" typeof="mw:Image/Thumb"><a href="Imagen:Foobar.jpg"><img resource="./Imagen:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" height="20" width="180"/></a></figure>
+#!! end
+
+!! test
+Image: Block level image should have \n before and after
+!! options
+parsoid
+!! input
+123
+[[File:Foobar.jpg|right|thumb|150x150px]]
+456
+!! result
+<p>123</p><figure typeof="mw:Image/Thumb" class="mw-halign-right"><a href="./File:Foobar.png"><img src="http://192.168.142.128/mw/images/thumb/b/bc/Foobar.png/131px-Foobar.png" width="131" height="150" resource="./File:Foobar.png" data-parsoid='{"a":{"resource":"./File:Foobar.png","width":"131"},"sa":{"resource":"File:Foobar.png","width":"150"}}'></a></figure><p>456</p>
+!!end
+
+!! test
+Image: New block level image should have \n before and after (existing
+content)
+!! options
+parsoid
+!! input
 123
-[[File:Wiki.png|right|thumb|150x150px]]
+[[File:Foobar.jpg|right|thumb|150x150px]]
 456
 !! result
-<p>123</p><figure typeof="mw:Image/Thumb" class="mw-halign-right"><a href="./File:Wiki.png"><img src="http://192.168.142.128/mw/images/thumb/b/bc/Wiki.png/131px-Wiki.png" width="131" height="150" resource="./File:Wiki.png"></a></figure><p>456</p>
+<p data-parsoid='{"dsr":[0,3,0,0]}'>123</p>
+<figure class="mw-halign-right" typeof="mw:Image/Thumb" data-parsoid='{"optList":[{"ck":"right","ak":"right"},{"ck":"thumbnail","ak":"thumb"},{"ck":"width","ak":"150x150px"}],"dsr":[4,45,2,2]}'><a href="./File:Foobar.jpg" data-parsoid='{"a":{"href":"./File:Foobar.jpg"},"dsr":[6,43,null,null]}'><img resource="./File:Foobar.jpg" src="//example.com/images/thumb/3/3a/Foobar.jpg/150px-Foobar.jpg" height="17" width="150" data-parsoid='{"a":{"resource":"./File:Foobar.jpg","height":"17","width":"150"},"sa":{"resource":"File:Foobar.jpg"}}'/></a></figure>
+<p data-parsoid='{"dsr":[46,49,0,0]}'>456</p>
+!!end
+
+!! test
+Images: upright option (parsoid)
+!! options
+parsoid
+!! input
+[[File:Foobar.jpg|thumb|upright|caption]]
+[[File:Foobar.jpg|thumb|upright=0.5|caption]]
+[[File:Foobar.jpg|thumb|500x500px|upright=0.5|caption]]
+!! result
+<figure class="mw-default-size" typeof="mw:Image/Thumb"><a href="File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" height="19" width="170"/></a><figcaption>caption</figcaption></figure><figure class="mw-default-size" typeof="mw:Image/Thumb"><a href="File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" height="19" width="170"/></a><figcaption>caption</figcaption></figure><figure typeof="mw:Image/Thumb"><a href="File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" height="57" width="500"/></a><figcaption>caption</figcaption></figure>
+!!end
+
+!! test
+Images: upright option is ignored on inline and frame images (parsoid)
+!! options
+parsoid
+!! input
+[[File:Foobar.jpg|500x500px|upright=0.5|caption]]
+!! result
+<p><span typeof="mw:Image" data-mw='{"caption":"caption"}'><a href="File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" height="57" width="500"/></a></span></p>
 !!end
 
 !! test
@@ -19414,6 +20083,16 @@ parsoid=html2wt
 <a href="//www.ncbi.nlm.nih.gov/pubmed/123?dopt=Abstract" rel="mw:ExtLink">New PMID</a>
 !! end
 
+!! test
+Edited Redirect link should emit a non-piped wikitext link
+!! options
+parsoid=html2wt
+!! input
+#REDIRECT [[Bar]]
+!! result
+<link rel="mw:PageProp/redirect" href="Bar" data-parsoid='{"src":"#REDIRECT ","a":{"href":"./Foo"},"sa":{"href":"Foo"}}'>
+!! end
+
 # -----------------------------------------------------------------
 # End of section for Parsoid-only html2wt tests for serialization
 # of new content
index 87e214c..4d64d05 100644 (file)
@@ -312,7 +312,17 @@ abstract class MediaWikiTestCase extends PHPUnit_Framework_TestCase {
                        // setMwGlobals() on the same global would override the original
                        // value.
                        if ( !array_key_exists( $key, $this->mwGlobals ) ) {
-                               $this->mwGlobals[$key] = $GLOBALS[$key];
+                               // NOTE: we serialize then unserialize the value in case it is an object
+                               // this stops any objects being passed by reference. We could use clone
+                               // and if is_object but this does account for objects within objects!
+                               try{
+                                       $this->mwGlobals[$key] = unserialize( serialize( $GLOBALS[$key] ) );
+                               }
+                               // NOTE; some things such as Closures are not serializable
+                               // in this case just set the value!
+                               catch( Exception $e ) {
+                                       $this->mwGlobals[$key] = $GLOBALS[$key];
+                               }
                        }
 
                        // Override the global
index b37ff2e..33643ac 100644 (file)
@@ -1,7 +1,6 @@
 <?php
 
 /**
- *
  * @group Database
  * ^--- make sure temporary tables are used.
  */
@@ -53,9 +52,10 @@ class LinksUpdateTest extends MediaWikiTestCase {
        }
 
        /**
-        * @covers LinksUpdate::addLink
+        * @covers ParserOutput::addLink
         */
        public function testUpdate_pagelinks() {
+               /** @var ParserOutput $po */
                list( $t, $po ) = $this->makeTitleAndParserOutput( "Testing", 111 );
 
                $po->addLink( Title::newFromText( "Foo" ) );
@@ -90,9 +90,10 @@ class LinksUpdateTest extends MediaWikiTestCase {
        }
 
        /**
-        * @covers LinksUpdate::addExternalLink
+        * @covers ParserOutput::addExternalLink
         */
        public function testUpdate_externallinks() {
+               /** @var ParserOutput $po */
                list( $t, $po ) = $this->makeTitleAndParserOutput( "Testing", 111 );
 
                $po->addExternalLink( "http://testing.com/wiki/Foo" );
@@ -103,9 +104,10 @@ class LinksUpdateTest extends MediaWikiTestCase {
        }
 
        /**
-        * @covers LinksUpdate::addCategory
+        * @covers ParserOutput::addCategory
         */
        public function testUpdate_categorylinks() {
+               /** @var ParserOutput $po */
                $this->setMwGlobals( 'wgCategoryCollation', 'uppercase' );
 
                list( $t, $po ) = $this->makeTitleAndParserOutput( "Testing", 111 );
@@ -118,9 +120,10 @@ class LinksUpdateTest extends MediaWikiTestCase {
        }
 
        /**
-        * @covers LinksUpdate::addInterwikiLink
+        * @covers ParserOutput::addInterwikiLink
         */
        public function testUpdate_iwlinks() {
+               /** @var ParserOutput $po */
                list( $t, $po ) = $this->makeTitleAndParserOutput( "Testing", 111 );
 
                $target = Title::makeTitleSafe( NS_MAIN, "Foo", '', 'linksupdatetest' );
@@ -132,9 +135,10 @@ class LinksUpdateTest extends MediaWikiTestCase {
        }
 
        /**
-        * @covers LinksUpdate::addTemplate
+        * @covers ParserOutput::addTemplate
         */
        public function testUpdate_templatelinks() {
+               /** @var ParserOutput $po */
                list( $t, $po ) = $this->makeTitleAndParserOutput( "Testing", 111 );
 
                $po->addTemplate( Title::newFromText( "Template:Foo" ), 23, 42 );
@@ -145,9 +149,10 @@ class LinksUpdateTest extends MediaWikiTestCase {
        }
 
        /**
-        * @covers LinksUpdate::addImage
+        * @covers ParserOutput::addImage
         */
        public function testUpdate_imagelinks() {
+               /** @var ParserOutput $po */
                list( $t, $po ) = $this->makeTitleAndParserOutput( "Testing", 111 );
 
                $po->addImage( "Foo.png" );
@@ -158,9 +163,10 @@ class LinksUpdateTest extends MediaWikiTestCase {
        }
 
        /**
-        * @covers LinksUpdate::addLanguageLink
+        * @covers ParserOutput::addLanguageLink
         */
        public function testUpdate_langlinks() {
+               /** @var ParserOutput $po */
                list( $t, $po ) = $this->makeTitleAndParserOutput( "Testing", 111 );
 
                $po->addLanguageLink( Title::newFromText( "en:Foo" )->getFullText() );
@@ -171,9 +177,10 @@ class LinksUpdateTest extends MediaWikiTestCase {
        }
 
        /**
-        * @covers LinksUpdate::setProperty
+        * @covers ParserOutput::setProperty
         */
        public function testUpdate_page_props() {
+               /** @var ParserOutput $po */
                list( $t, $po ) = $this->makeTitleAndParserOutput( "Testing", 111 );
 
                $po->setProperty( "foo", "bar" );
diff --git a/tests/phpunit/includes/MediaWikiVersionFetcherTest.php b/tests/phpunit/includes/MediaWikiVersionFetcherTest.php
new file mode 100644 (file)
index 0000000..bbb83da
--- /dev/null
@@ -0,0 +1,21 @@
+<?php
+
+/**
+ * Note: this is not a unit test, as it touches the file system and reads an actual file.
+ * If unit tests are added for MediaWikiVersionFetcher, this should be done in a distinct test case.
+ *
+ * @covers MediaWikiVersionFetcher
+ *
+ * @group ComposerHooks
+ *
+ * @licence GNU GPL v2+
+ * @author Jeroen De Dauw < jeroendedauw@gmail.com >
+ */
+class MediaWikiVersionFetcherTest extends PHPUnit_Framework_TestCase {
+
+       public function testReturnsResult() {
+               $versionFetcher = new MediaWikiVersionFetcher();
+               $this->assertInternalType( 'string', $versionFetcher->fetchVersion() );
+       }
+
+}
\ No newline at end of file
diff --git a/tests/phpunit/includes/SkinTemplateTest.php b/tests/phpunit/includes/SkinTemplateTest.php
new file mode 100644 (file)
index 0000000..8f54714
--- /dev/null
@@ -0,0 +1,38 @@
+<?php
+
+/**
+ * @covers SkinTemplate
+ *
+ * @group Output
+ *
+ * @licence GNU GPL v2+
+ * @author Bene* < benestar.wikimedia@gmail.com >
+ */
+
+class SkinTemplateTest extends MediaWikiTestCase {
+
+       /**
+        * @dataProvider makeListItemProvider
+        */
+       public function testMakeListItem( $expected, $key, $item, $options, $message ) {
+               $template = $this->getMockForAbstractClass( 'BaseTemplate' );
+
+               $this->assertEquals(
+                       $expected,
+                       $template->makeListItem( $key, $item, $options ),
+                       $message
+               );
+       }
+
+       public function makeListItemProvider() {
+               return array(
+                       array(
+                               '<li class="class" title="itemtitle"><a href="url" title="title">text</a></li>',
+                               '',
+                               array( 'class' => 'class', 'itemtitle' => 'itemtitle', 'href' => 'url', 'title' => 'title', 'text' => 'text' ),
+                               array(),
+                               'Test makteListItem with normal values'
+                       )
+               );
+       }
+}
index 209b54c..4386770 100644 (file)
@@ -371,11 +371,20 @@ class StatusTest extends MediaWikiLangTestCase {
        /**
         * @dataProvider provideGetMessage
         * @covers Status::getMessage
-        * @todo test long and short context messages generated through this method
+        * @todo test with multiple messages at once
         */
-       public function testGetMessage( Status $status, $expectedParams = array(), $expectedKey ) {
-               $message = $status->getMessage();
+       public function testGetMessage( Status $status, $expectedParams = array(), $expectedKey, $shortContext = false, $longContext = false ) {
+               $message = $status->getMessage( $shortContext, $longContext );
                $this->assertInstanceOf( 'Message', $message );
+
+               // Loop through until we get to the appropriate depth for the message
+               $loops = $shortContext ? 1 : ( $longContext ? 2 : 0 );
+               for( $i = 1; $i <= $loops; $i++ ) {
+                       $params = $message->getParams();
+                       $this->assertInstanceOf( 'Message', $params[0] );
+                       $message = $params[0];
+               }
+
                $this->assertEquals( $expectedParams, $message->getParams() );
                $this->assertEquals( $expectedKey, $message->getKey() );
        }
@@ -383,7 +392,7 @@ class StatusTest extends MediaWikiLangTestCase {
        /**
         * @return array of arrays with values;
         *    0 => status object
-        *    1 => expected Message Params (with no context)
+        *    1 => expected Message Params
         */
        public static function provideGetMessage() {
                $testCases = array();
@@ -402,6 +411,21 @@ class StatusTest extends MediaWikiLangTestCase {
                        'internalerror_info'
                );
 
+               $testCases[ 'GoodButNoErrorShortContext' ] = array(
+                       $status,
+                       array( "Status::getMessage: Invalid result object: no error text but not OK\n" ),
+                       'internalerror_info',
+                       true
+               );
+
+               $testCases[ 'GoodButNoErrorLongContext' ] = array(
+                       $status,
+                       array( "Status::getMessage: Invalid result object: no error text but not OK\n" ),
+                       'internalerror_info',
+                       false,
+                       true
+               );
+
                $status = new Status();
                $status->warning( 'fooBar!' );
                $testCases[ '1StringWarning' ] = array(
@@ -438,6 +462,33 @@ class StatusTest extends MediaWikiLangTestCase {
 //                     "",
 //             );
 
+               $status = new Status();
+               $status->error( new Message( 'fooBar!', array( 'foo', 'bar' )  ) );
+               $testCases[ '1MessageError' ] = array(
+                       $status,
+                       array( 'foo', 'bar' ),
+                       "fooBar!",
+               );
+
+               $status = new Status();
+               $status->error( new Message( 'fooBar!', array( 'foo', 'bar' )  ) );
+               $testCases[ '1MessageErrorShortContext' ] = array(
+                       $status,
+                       array( 'foo', 'bar' ),
+                       "fooBar!",
+                       true,
+               );
+
+               $status = new Status();
+               $status->error( new Message( 'fooBar!', array( 'foo', 'bar' )  ) );
+               $testCases[ '1MessageErrorLongContext' ] = array(
+                       $status,
+                       array( 'foo', 'bar' ),
+                       "fooBar!",
+                       false,
+                       true,
+               );
+
                return $testCases;
        }
 
diff --git a/tests/phpunit/includes/composer/ComposerVersionNormalizerTest.php b/tests/phpunit/includes/composer/ComposerVersionNormalizerTest.php
new file mode 100644 (file)
index 0000000..8de8be1
--- /dev/null
@@ -0,0 +1,156 @@
+<?php
+
+/**
+ * @covers ComposerVersionNormalizer
+ *
+ * @group ComposerHooks
+ *
+ * @licence GNU GPL v2+
+ * @author Jeroen De Dauw < jeroendedauw@gmail.com >
+ */
+class ComposerVersionNormalizerTest extends PHPUnit_Framework_TestCase {
+
+       /**
+        * @dataProvider nonStringProvider
+        */
+       public function testGivenNonString_normalizeThrowsInvalidArgumentException( $nonString ) {
+               $normalizer = new ComposerVersionNormalizer();
+
+               $this->setExpectedException( 'InvalidArgumentException' );
+               $normalizer->normalizeSuffix( $nonString );
+       }
+
+       public function nonStringProvider() {
+               return array(
+                       array( null ),
+                       array( 42 ),
+                       array( array() ),
+                       array( new stdClass() ),
+                       array( true ),
+               );
+       }
+
+       /**
+        * @dataProvider simpleVersionProvider
+        */
+       public function testGivenSimpleVersion_normalizeSuffixReturnsAsIs( $simpleVersion ) {
+               $this->assertRemainsUnchanged( $simpleVersion );
+       }
+
+       protected function assertRemainsUnchanged( $version ) {
+               $normalizer = new ComposerVersionNormalizer();
+
+               $this->assertEquals(
+                       $version,
+                       $normalizer->normalizeSuffix( $version )
+               );
+       }
+
+       public function simpleVersionProvider() {
+               return array(
+                       array( '1.22.0' ),
+                       array( '1.19.2' ),
+                       array( '1.19.2.0' ),
+                       array( '1.9' ),
+                       array( '123.321.456.654' ),
+               );
+       }
+
+       /**
+        * @dataProvider complexVersionProvider
+        */
+       public function testGivenComplexVersionWithoutDash_normalizeSuffixAddsDash( $withoutDash, $withDash ) {
+               $normalizer = new ComposerVersionNormalizer();
+
+               $this->assertEquals(
+                       $withDash,
+                       $normalizer->normalizeSuffix( $withoutDash )
+               );
+       }
+
+       public function complexVersionProvider() {
+               return array(
+                       array( '1.22.0alpha', '1.22.0-alpha' ),
+                       array( '1.22.0RC', '1.22.0-RC' ),
+                       array( '1.19beta', '1.19-beta' ),
+                       array( '1.9RC4', '1.9-RC4' ),
+                       array( '1.9.1.2RC4', '1.9.1.2-RC4' ),
+                       array( '1.9.1.2RC', '1.9.1.2-RC' ),
+                       array( '123.321.456.654RC9001', '123.321.456.654-RC9001' ),
+               );
+       }
+
+       /**
+        * @dataProvider complexVersionProvider
+        */
+       public function testGivenComplexVersionWithDash_normalizeSuffixReturnsAsIs( $withoutDash, $withDash ) {
+               $this->assertRemainsUnchanged( $withDash );
+       }
+
+       /**
+        * @dataProvider fourLevelVersionsProvider
+        */
+       public function testGivenFourLevels_levelCountNormalizationDoesNothing( $version ) {
+               $normalizer = new ComposerVersionNormalizer();
+
+               $this->assertEquals(
+                       $version,
+                       $normalizer->normalizeLevelCount( $version )
+               );
+       }
+
+       public function fourLevelVersionsProvider() {
+               return array(
+                       array( '1.22.0.0' ),
+                       array( '1.19.2.4' ),
+                       array( '1.19.2.0' ),
+                       array( '1.9.0.1' ),
+                       array( '123.321.456.654' ),
+                       array( '123.321.456.654RC4' ),
+                       array( '123.321.456.654-RC4' ),
+               );
+       }
+
+       /**
+        * @dataProvider levelNormalizationProvider
+        */
+       public function testGivenFewerLevels_levelCountNormalizationEnsuresFourLevels( $expected, $version ) {
+               $normalizer = new ComposerVersionNormalizer();
+
+               $this->assertEquals(
+                       $expected,
+                       $normalizer->normalizeLevelCount( $version )
+               );
+       }
+
+       public function levelNormalizationProvider() {
+               return array(
+                       array( '1.22.0.0', '1.22' ),
+                       array( '1.22.0.0', '1.22.0' ),
+                       array( '1.19.2.0', '1.19.2' ),
+                       array( '12345.0.0.0', '12345' ),
+                       array( '12345.0.0.0-RC4', '12345-RC4' ),
+                       array( '12345.0.0.0-alpha', '12345-alpha' ),
+               );
+       }
+
+       /**
+        * @dataProvider invalidVersionProvider
+        */
+       public function testGivenInvalidVersion_normalizeSuffixReturnsAsIs( $invalidVersion ) {
+               $this->assertRemainsUnchanged( $invalidVersion );
+       }
+
+       public function invalidVersionProvider() {
+               return array(
+                       array( '1.221-a' ),
+                       array( '1.221-' ),
+                       array( '1.22rc4a' ),
+                       array( 'a1.22rc' ),
+                       array( '.1.22rc' ),
+                       array( 'a' ),
+                       array( 'alpha42' ),
+               );
+       }
+
+}
\ No newline at end of file
diff --git a/tests/phpunit/includes/exception/ErrorPageErrorTest.php b/tests/phpunit/includes/exception/ErrorPageErrorTest.php
new file mode 100644 (file)
index 0000000..4cfcd83
--- /dev/null
@@ -0,0 +1,67 @@
+<?php
+
+/**
+ * @covers ErrorPageError
+ * @author Adam Shorland
+ */
+class ErrorPageErrorTest extends MediaWikiTestCase {
+
+       private $wgOut;
+
+       protected function setUp() {
+               parent::setUp();
+               global $wgOut;
+               $this->wgOut = clone $wgOut;
+       }
+
+       protected function tearDown() {
+               global $wgOut;
+               $wgOut = $this->wgOut;
+               parent::tearDown();
+       }
+
+       private function getMockMessage() {
+               $mockMessage = $this->getMockBuilder( 'Message' )
+                       ->disableOriginalConstructor()
+                       ->getMock();
+               $mockMessage->expects( $this->once() )
+                       ->method( 'inLanguage' )
+                       ->will( $this->returnValue( $mockMessage ) );
+               $mockMessage->expects(  $this->once() )
+                       ->method( 'useDatabase' )
+                       ->will( $this->returnValue( $mockMessage ) );
+               return $mockMessage;
+       }
+
+       public function testConstruction() {
+               $mockMessage = $this->getMockMessage();
+               $title = 'Foo';
+               $params = array( 'Baz' );
+               $e = new ErrorPageError( $title, $mockMessage, $params );
+               $this->assertEquals( $title, $e->title );
+               $this->assertEquals( $mockMessage, $e->msg );
+               $this->assertEquals( $params, $e->params );
+       }
+
+       public function testReport() {
+               $mockMessage = $this->getMockMessage();
+               $title = 'Foo';
+               $params = array( 'Baz' );
+
+               global $wgOut;
+               $wgOut = $this->getMockBuilder( 'OutputPage' )
+                       ->disableOriginalConstructor()
+                       ->getMock();
+               $wgOut->expects( $this->once() )
+                       ->method( 'showErrorPage' )
+                       ->with( $title, $mockMessage, $params );
+               $wgOut->expects( $this->once() )
+                       ->method( 'output' );
+
+               $e = new ErrorPageError( $title, $mockMessage, $params );
+               $e->report();
+       }
+
+
+
+}
index f1ddc17..2dc4850 100644 (file)
@@ -15,6 +15,132 @@ class MWExceptionTest extends MediaWikiTestCase {
                throw new MWException();
        }
 
+       /**
+        * @dataProvider provideTextUseOutputPage
+        * @covers MWException::useOutputPage
+        */
+       public function testUseOutputPage( $expected, $wgLang, $wgFullyInitialised, $wgOut ) {
+               $this->setMwGlobals( array(
+                       'wgLang' => $wgLang,
+                       'wgFullyInitialised' => $wgFullyInitialised,
+                       'wgOut' => $wgOut,
+               ) );
+
+               $e = new MWException();
+               $this->assertEquals( $expected, $e->useOutputPage() );
+       }
+
+       public function provideTextUseOutputPage() {
+               return array(
+                       // expected, wgLang, wgFullyInitialised, wgOut
+                       array( false, null, null, null ),
+                       array( false, $this->getMockLanguage(), null, null ),
+                       array( false, $this->getMockLanguage(), true, null ),
+                       array( false, null, true, null ),
+                       array( false, null, null, true ),
+                       array( true, $this->getMockLanguage(), true, true ),
+               );
+       }
+
+       private function getMockLanguage() {
+               return $this->getMockBuilder( 'Language' )
+                       ->disableOriginalConstructor()
+                       ->getMock();
+       }
+
+       /**
+        * @dataProvider provideUseMessageCache
+        * @covers MWException::useMessageCache
+        */
+       public function testUseMessageCache( $expected, $wgLang ) {
+               $this->setMwGlobals( array(
+                       'wgLang' => $wgLang,
+               ) );
+               $e = new MWException();
+               $this->assertEquals( $expected, $e->useMessageCache() );
+       }
+
+       public function provideUseMessageCache() {
+               return array(
+                       array( false, null ),
+                       array( true, $this->getMockLanguage() ),
+               );
+       }
+
+       /**
+        * @covers MWException::isLoggable
+        */
+       public function testIsLogable() {
+               $e = new MWException();
+               $this->assertTrue( $e->isLoggable() );
+       }
+
+       /**
+        * @dataProvider provideRunHooks
+        * @covers MWException::runHooks
+        */
+       public function testRunHooks( $wgExceptionHooks, $name, $args, $expectedReturn ) {
+               $this->setMwGlobals( array(
+                       'wgExceptionHooks' => $wgExceptionHooks,
+               ) );
+               $e = new MWException();
+               $this->assertEquals( $expectedReturn, $e->runHooks( $name, $args ) );
+       }
+
+       public function provideRunHooks() {
+               return array(
+                       array( null, null, null, null ),
+                       array( array(), 'name', array(), null ),
+                       array( array( 'name' => false ), 'name', array(), null ),
+                       array(
+                               array( 'mockHook' => array( 'MWExceptionTest::mockHook' ) ),
+                               'mockHook', array(), 'YAY.[]'
+                       ),
+                       array(
+                               array( 'mockHook' => array( 'MWExceptionTest::mockHook' ) ),
+                               'mockHook', array( 'a' ), 'YAY.{"1":"a"}'
+                       ),
+                       array(
+                               array( 'mockHook' => array( 'MWExceptionTest::mockHook' ) ),
+                               'mockHook', array( null ), null
+                       ),
+               );
+       }
+
+       /**
+        * Used in conjunction with provideRunHooks and testRunHooks as a mock callback for a hook
+        */
+       public static function mockHook() {
+               $args = func_get_args();
+               if( !$args[0] instanceof MWException ) {
+                       return '$caller not instance of MWException';
+               }
+               unset( $args[0] );
+               if( array_key_exists( 1, $args ) && $args[1] === null ) {
+                       return null;
+               }
+               return 'YAY.' . json_encode( $args );
+       }
+
+       /**
+        * @dataProvider provideIsCommandLine
+        * @covers MWException::isCommandLine
+        */
+       public function testisCommandLine( $expected, $wgCommandLineMode ) {
+               $this->setMwGlobals( array(
+                       'wgCommandLineMode' => $wgCommandLineMode,
+               ) );
+               $e = new MWException();
+               $this->assertEquals( $expected, $e->isCommandLine() );
+       }
+
+       public function provideIsCommandLine() {
+               return array(
+                       array( false, null ),
+                       array( true, true ),
+               );
+       }
+
        /**
         * Verify the exception classes are JSON serializabe.
         *
diff --git a/tests/phpunit/includes/exception/ReadOnlyErrorTest.php b/tests/phpunit/includes/exception/ReadOnlyErrorTest.php
new file mode 100644 (file)
index 0000000..352ec65
--- /dev/null
@@ -0,0 +1,16 @@
+<?php
+
+/**
+ * @covers ReadOnlyError
+ * @author Adam Shorland
+ */
+class ReadOnlyErrorTest extends MediaWikiTestCase {
+
+       public function testConstruction() {
+               $e = new ReadOnlyError();
+               $this->assertEquals( 'readonly', $e->title );
+               $this->assertEquals( 'readonlytext', $e->msg );
+               $this->assertEquals( wfReadOnlyReason()?: array(), $e->params );
+       }
+
+}
diff --git a/tests/phpunit/includes/exception/UserNotLoggedInTest.php b/tests/phpunit/includes/exception/UserNotLoggedInTest.php
new file mode 100644 (file)
index 0000000..591a0fa
--- /dev/null
@@ -0,0 +1,16 @@
+<?php
+
+/**
+ * @covers UserNotLoggedIn
+ * @author Adam Shorland
+ */
+class UserNotLoggedInTest extends MediaWikiTestCase {
+
+       public function testConstruction() {
+               $e = new UserNotLoggedIn();
+               $this->assertEquals( 'exception-nologin', $e->title );
+               $this->assertEquals( 'exception-nologin-text', $e->msg );
+               $this->assertEquals( array(), $e->params );
+       }
+
+}
index 8af2fc1..b41f647 100644 (file)
@@ -80,16 +80,14 @@ class SiteListTest extends MediaWikiTestCase {
         * @covers SiteList::getSite
         */
        public function testGetSiteByGlobalId( SiteList $sites ) {
-               if ( $sites->isEmpty() ) {
-                       $this->assertTrue( true );
-               } else {
-                       /**
-                        * @var Site $site
-                        */
-                       foreach ( $sites as $site ) {
-                               $this->assertEquals( $site, $sites->getSite( $site->getGlobalId() ) );
-                       }
+               /**
+                * @var Site $site
+                */
+               foreach ( $sites as $site ) {
+                       $this->assertEquals( $site, $sites->getSite( $site->getGlobalId() ) );
                }
+
+               $this->assertTrue( true );
        }
 
        /**
@@ -110,6 +108,25 @@ class SiteListTest extends MediaWikiTestCase {
                $this->assertTrue( true );
        }
 
+       /**
+        * @dataProvider siteListProvider
+        * @param SiteList $sites
+        * @covers SiteList::getSiteByNavigationId
+        */
+       public function testGetSiteByNavigationId( $sites ) {
+               /**
+                * @var Site $site
+                */
+               foreach ( $sites as $site ) {
+                       $ids = $site->getNavigationIds();
+                       foreach ( $ids as $navId ) {
+                               $this->assertEquals( $site, $sites->getSiteByNavigationId( $navId ) );
+                       }
+               }
+
+               $this->assertTrue( true );
+       }
+
        /**
         * @dataProvider siteListProvider
         * @param SiteList $sites
@@ -147,6 +164,25 @@ class SiteListTest extends MediaWikiTestCase {
                $this->assertFalse( $sites->hasInternalId( -1 ) );
        }
 
+       /**
+        * @dataProvider siteListProvider
+        * @param SiteList $sites
+        * @covers SiteList::hasNavigationId
+        */
+       public function testHasNavigationId( $sites ) {
+               /**
+                * @var Site $site
+                */
+               foreach ( $sites as $site ) {
+                       $ids = $site->getNavigationIds();
+                       foreach ( $ids as $navId ) {
+                               $this->assertTrue( $sites->hasNavigationId( $navId ) );
+                       }
+               }
+
+               $this->assertFalse( $sites->hasNavigationId( 'non-existing-navigation-id' ) );
+       }
+
        /**
         * @dataProvider siteListProvider
         * @param SiteList $sites
diff --git a/tests/phpunit/languages/SpecialPageAliasTest.php b/tests/phpunit/languages/SpecialPageAliasTest.php
new file mode 100644 (file)
index 0000000..8865f68
--- /dev/null
@@ -0,0 +1,63 @@
+<?php
+
+/**
+ * Verifies that special page aliases are valid, with no slashes.
+ *
+ * @group Language
+ * @group SpecialPageAliases
+ * @group SystemTest
+ * @group medium
+ *
+ * @licence GNU GPL v2+
+ * @author Katie Filbert < aude.wiki@gmail.com >
+ */
+class SpecialPageAliasTest extends MediaWikiTestCase {
+
+       /**
+        * @dataProvider validSpecialPageAliasesProvider
+        */
+       public function testValidSpecialPageAliases( $code, $specialPageAliases ) {
+               foreach( $specialPageAliases as $specialPage => $aliases ) {
+                       foreach( $aliases as $alias ) {
+                               $msg = "$specialPage alias '$alias' in $code is valid with no slashes";
+                               $this->assertRegExp( '/^[^\/]*$/', $msg );
+                       }
+               }
+       }
+
+       public function validSpecialPageAliasesProvider() {
+               $codes = array_keys( Language::fetchLanguageNames( 'mwfile' ) );
+
+               $data = array();
+
+               foreach( $codes as $code ) {
+                       $specialPageAliases = $this->getSpecialPageAliases( $code );
+
+                       if ( $specialPageAliases !== array() ) {
+                               $data[] = array( $code, $specialPageAliases );
+                       }
+               }
+
+               return $data;
+       }
+
+       /**
+        * @param string $code
+        *
+        * @return array
+        */
+       protected function getSpecialPageAliases( $code ) {
+               $file = Language::getMessagesFileName( $code );
+
+               if ( is_readable( $file ) ) {
+                       include $file;
+
+                       if ( isset( $specialPageAliases ) && $specialPageAliases !== null ) {
+                               return $specialPageAliases;
+                       }
+               }
+
+               return array();
+       }
+
+}
index 63f610f..58509c1 100644 (file)
@@ -8,8 +8,8 @@ return array(
 
        'test.sinonjs' => array(
                'scripts' => array(
-                       'resources/sinonjs/sinon-1.8.1.js',
-                       'resources/sinonjs/sinon-ie-1.8.1.js',
+                       'resources/sinonjs/sinon-1.9.0.js',
+                       'resources/sinonjs/sinon-ie-1.9.0.js',
                ),
                'targets' => array( 'desktop', 'mobile' ),
        ),
@@ -42,8 +42,8 @@ return array(
                        'tests/qunit/suites/resources/jquery/jquery.byteLength.test.js',
                        'tests/qunit/suites/resources/jquery/jquery.byteLimit.test.js',
                        'tests/qunit/suites/resources/jquery/jquery.client.test.js',
+                       'tests/qunit/suites/resources/jquery/jquery.color.test.js',
                        'tests/qunit/suites/resources/jquery/jquery.colorUtil.test.js',
-                       'tests/qunit/suites/resources/jquery/jquery.delayedBind.test.js',
                        'tests/qunit/suites/resources/jquery/jquery.getAttrs.test.js',
                        'tests/qunit/suites/resources/jquery/jquery.hidpi.test.js',
                        'tests/qunit/suites/resources/jquery/jquery.highlightText.test.js',
@@ -74,6 +74,7 @@ return array(
                        'jquery.byteLength',
                        'jquery.byteLimit',
                        'jquery.client',
+                       'jquery.color',
                        'jquery.colorUtil',
                        'jquery.delayedBind',
                        'jquery.getAttrs',
diff --git a/tests/qunit/suites/resources/jquery/jquery.color.test.js b/tests/qunit/suites/resources/jquery/jquery.color.test.js
new file mode 100644 (file)
index 0000000..b644a3c
--- /dev/null
@@ -0,0 +1,15 @@
+( function ( $ ) {
+       QUnit.module( 'jquery.color', QUnit.newMwEnvironment() );
+
+       QUnit.asyncTest( 'animate', 3, function ( assert ) {
+               var $canvas = $( '<div>' ).css( 'background-color', '#fff' );
+
+               $canvas.animate( { backgroundColor: '#000' }, 4 ).promise().then( function() {
+                       var endColors = $.colorUtil.getRGB( $canvas.css( 'background-color' ) );
+                       assert.strictEqual( endColors[0], 0 );
+                       assert.strictEqual( endColors[1], 0 );
+                       assert.strictEqual( endColors[2], 0 );
+                       QUnit.start();
+               } );
+       } );
+}( jQuery ) );
diff --git a/tests/qunit/suites/resources/jquery/jquery.delayedBind.test.js b/tests/qunit/suites/resources/jquery/jquery.delayedBind.test.js
deleted file mode 100644 (file)
index 234b19c..0000000
+++ /dev/null
@@ -1,37 +0,0 @@
-( function ( $ ) {
-       QUnit.asyncTest( 'jquery.delayedBind with data option', 2, function ( assert ) {
-               var $fixture = $( '<div>' ).appendTo( '#qunit-fixture' ),
-                       data = {
-                               magic: 'beeswax'
-                       },
-                       delay = 50;
-
-               $fixture.delayedBind( delay, 'testevent', data, function ( e ) {
-                       assert.ok( true, 'testevent fired' );
-                       assert.ok( e.data === data, 'data is passed through delayedBind' );
-                       QUnit.start();
-               } );
-
-               // We'll trigger it thrice, but it should only happen once.
-               $fixture.trigger( 'testevent', {} );
-               $fixture.trigger( 'testevent', {} );
-               $fixture.trigger( 'testevent', {} );
-               $fixture.trigger( 'testevent', {} );
-       } );
-
-       QUnit.asyncTest( 'jquery.delayedBind without data option', 1, function ( assert ) {
-               var $fixture = $( '<div>' ).appendTo( '#qunit-fixture' ),
-                       delay = 50;
-
-               $fixture.delayedBind( delay, 'testevent', function () {
-                       assert.ok( true, 'testevent fired' );
-                       QUnit.start();
-               } );
-
-               // We'll trigger it thrice, but it should only happen once.
-               $fixture.trigger( 'testevent', {} );
-               $fixture.trigger( 'testevent', {} );
-               $fixture.trigger( 'testevent', {} );
-               $fixture.trigger( 'testevent', {} );
-       } );
-}( jQuery ) );
index 3c508d4..bfb857d 100644 (file)
 
        // This test is first because if it fails, then almost all of the latter tests are meaningless.
        QUnit.asyncTest( 'testing hooks/triggers', 4, function ( assert ) {
-               var $collapsible, $content, $toggle;
-               $collapsible = prepareCollapsible(
-                       '<div class="mw-collapsible">' + loremIpsum + '</div>'
-               );
-               $content = $collapsible.find( '.mw-collapsible-content' );
-               $toggle = $collapsible.find( '.mw-collapsible-toggle' );
+               var $collapsible = prepareCollapsible(
+                               '<div class="mw-collapsible">' + loremIpsum + '</div>'
+                       ),
+                       $content = $collapsible.find( '.mw-collapsible-content' ),
+                       $toggle = $collapsible.find( '.mw-collapsible-toggle' );
 
                // In one full collapse-expand cycle, each event will be fired once
 
@@ -34,7 +33,6 @@
                        } );
                        $collapsible.on( 'afterExpand.mw-collapsible', function () {
                                assert.assertTrue( $content.is( ':visible' ), 'second afterCollapseExpand: content is visible' );
-
                                QUnit.start();
                        } );
 
        } );
 
        QUnit.asyncTest( 'basic operation (<div>)', 5, function ( assert ) {
-               var $collapsible, $content, $toggle;
-               $collapsible = prepareCollapsible(
-                       '<div class="mw-collapsible">' + loremIpsum + '</div>'
-               );
-               $content = $collapsible.find( '.mw-collapsible-content' );
-               $toggle = $collapsible.find( '.mw-collapsible-toggle' );
+               var $collapsible = prepareCollapsible(
+                               '<div class="mw-collapsible">' + loremIpsum + '</div>'
+                       ),
+                       $content = $collapsible.find( '.mw-collapsible-content' ),
+                       $toggle = $collapsible.find( '.mw-collapsible-toggle' );
 
                assert.equal( $content.length, 1, 'content is present' );
                assert.equal( $content.find( $toggle ).length, 0, 'toggle is not a descendant of content' );
        } );
 
        QUnit.asyncTest( 'basic operation (<table>)', 7, function ( assert ) {
-               var $collapsible, $headerRow, $contentRow, $toggle;
-               $collapsible = prepareCollapsible(
-                       '<table class="mw-collapsible">' +
-                               '<tr><td>' + loremIpsum + '</td><td>' + loremIpsum + '</td></tr>' +
-                               '<tr><td>' + loremIpsum + '</td><td>' + loremIpsum + '</td></tr>' +
-                               '<tr><td>' + loremIpsum + '</td><td>' + loremIpsum + '</td></tr>' +
-                       '</table>'
-               );
-               $headerRow = $collapsible.find( 'tr:first' );
-               $contentRow = $collapsible.find( 'tr:last' );
+               var $collapsible = prepareCollapsible(
+                               '<table class="mw-collapsible">' +
+                                       '<tr><td>' + loremIpsum + '</td><td>' + loremIpsum + '</td></tr>' +
+                                       '<tr><td>' + loremIpsum + '</td><td>' + loremIpsum + '</td></tr>' +
+                                       '<tr><td>' + loremIpsum + '</td><td>' + loremIpsum + '</td></tr>' +
+                               '</table>'
+                       ),
+                       $headerRow = $collapsible.find( 'tr:first' ),
+                       $contentRow = $collapsible.find( 'tr:last' ),
+                       $toggle = $headerRow.find( 'td:last .mw-collapsible-toggle' );
 
-               $toggle = $headerRow.find( 'td:last .mw-collapsible-toggle' );
                assert.equal( $toggle.length, 1, 'toggle is added to last cell of first row' );
 
                assert.assertTrue( $headerRow.is( ':visible' ), 'headerRow is visible' );
        } );
 
        function tableWithCaptionTest( $collapsible, assert ) {
-               var $caption, $headerRow, $contentRow, $toggle;
+               var $caption = $collapsible.find( 'caption' ),
+                       $headerRow = $collapsible.find( 'tr:first' ),
+                       $contentRow = $collapsible.find( 'tr:last' ),
+                       $toggle = $caption.find( '.mw-collapsible-toggle' );
 
-               $caption = $collapsible.find( 'caption' );
-               $headerRow = $collapsible.find( 'tr:first' );
-               $contentRow = $collapsible.find( 'tr:last' );
-
-               $toggle = $caption.find( '.mw-collapsible-toggle' );
                assert.equal( $toggle.length, 1, 'toggle is added to the end of the caption' );
 
                assert.assertTrue( $caption.is( ':visible' ), 'caption is visible' );
        } );
 
        function listTest( listType, assert ) {
-               var $collapsible, $toggleItem, $contentItem, $toggle;
-               $collapsible = prepareCollapsible(
-                       '<' + listType + ' class="mw-collapsible">' +
-                               '<li>' + loremIpsum + '</li>' +
-                               '<li>' + loremIpsum + '</li>' +
-                       '</' + listType + '>'
-               );
-               $toggleItem = $collapsible.find( 'li.mw-collapsible-toggle-li:first-child' );
-               $contentItem = $collapsible.find( 'li:last' );
-
-               $toggle = $toggleItem.find( '.mw-collapsible-toggle' );
+               var $collapsible = prepareCollapsible(
+                               '<' + listType + ' class="mw-collapsible">' +
+                                       '<li>' + loremIpsum + '</li>' +
+                                       '<li>' + loremIpsum + '</li>' +
+                               '</' + listType + '>'
+                       ),
+                       $toggleItem = $collapsible.find( 'li.mw-collapsible-toggle-li:first-child' ),
+                       $contentItem = $collapsible.find( 'li:last' ),
+                       $toggle = $toggleItem.find( '.mw-collapsible-toggle' );
+
                assert.equal( $toggle.length, 1, 'toggle is present, added inside new zeroth list item' );
 
                assert.assertTrue( $toggleItem.is( ':visible' ), 'toggleItem is visible' );
        } );
 
        QUnit.test( 'basic operation when synchronous (options.instantHide)', 2, function ( assert ) {
-               var $collapsible, $content;
-               $collapsible = prepareCollapsible(
-                       '<div class="mw-collapsible">' + loremIpsum + '</div>',
-                       { instantHide: true }
-               );
-               $content = $collapsible.find( '.mw-collapsible-content' );
+               var $collapsible = prepareCollapsible(
+                               '<div class="mw-collapsible">' + loremIpsum + '</div>',
+                               { instantHide: true }
+                       ),
+                       $content = $collapsible.find( '.mw-collapsible-content' );
 
                assert.assertTrue( $content.is( ':visible' ), 'content is visible' );
 
        } );
 
        QUnit.test( 'mw-made-collapsible data added', 1, function ( assert ) {
-               var $collapsible;
-               $collapsible = prepareCollapsible(
-                       '<div>' + loremIpsum + '</div>'
-               );
+               var $collapsible = prepareCollapsible(
+                               '<div>' + loremIpsum + '</div>'
+                       );
+
                assert.equal( $collapsible.data( 'mw-made-collapsible' ), true, 'mw-made-collapsible data present' );
        } );
 
        QUnit.test( 'mw-collapsible added when missing', 1, function ( assert ) {
-               var $collapsible;
-               $collapsible = prepareCollapsible(
-                       '<div>' + loremIpsum + '</div>'
-               );
+               var $collapsible = prepareCollapsible(
+                               '<div>' + loremIpsum + '</div>'
+                       );
+
                assert.assertTrue( $collapsible.hasClass( 'mw-collapsible' ), 'mw-collapsible class present' );
        } );
 
        QUnit.test( 'mw-collapsed added when missing', 1, function ( assert ) {
-               var $collapsible;
-               $collapsible = prepareCollapsible(
+               var $collapsible = prepareCollapsible(
                        '<div>' + loremIpsum + '</div>',
-                       { collapsed: true }
-               );
+                               { collapsed: true }
+                       );
+
                assert.assertTrue( $collapsible.hasClass( 'mw-collapsed' ), 'mw-collapsed class present' );
        } );
 
        QUnit.asyncTest( 'initial collapse (mw-collapsed class)', 2, function ( assert ) {
-               var $collapsible, $content;
-               $collapsible = prepareCollapsible(
-                       '<div class="mw-collapsible mw-collapsed">' + loremIpsum + '</div>'
-               );
-               $content = $collapsible.find( '.mw-collapsible-content' );
+               var $collapsible = prepareCollapsible(
+                               '<div class="mw-collapsible mw-collapsed">' + loremIpsum + '</div>'
+                       ),
+                       $content = $collapsible.find( '.mw-collapsible-content' );
 
                // Synchronous - mw-collapsed should cause instantHide: true to be used on initial collapsing
                assert.assertTrue( $content.is( ':hidden' ), 'content is hidden' );
        } );
 
        QUnit.asyncTest( 'initial collapse (options.collapsed)', 2, function ( assert ) {
-               var $collapsible, $content;
-               $collapsible = prepareCollapsible(
-                       '<div class="mw-collapsible">' + loremIpsum + '</div>',
-                       { collapsed: true }
-               );
-               $content = $collapsible.find( '.mw-collapsible-content' );
+               var $collapsible = prepareCollapsible(
+                               '<div class="mw-collapsible">' + loremIpsum + '</div>',
+                               { collapsed: true }
+                       ),
+                       $content = $collapsible.find( '.mw-collapsible-content' );
 
                // Synchronous - collapsed: true should cause instantHide: true to be used on initial collapsing
                assert.assertTrue( $content.is( ':hidden' ), 'content is hidden' );
        } );
 
        QUnit.test( 'clicks on links inside toggler pass through (options.linksPassthru)' , 2, function ( assert ) {
-               var $collapsible, $content;
-
-               $collapsible = prepareCollapsible(
-                       '<div class="mw-collapsible">' +
-                               '<div class="mw-collapsible-toggle">' +
-                                       'Toggle <a href="#top">toggle</a> toggle <b>toggle</b>' +
-                               '</div>' +
-                               '<div class="mw-collapsible-content">' + loremIpsum + '</div>' +
-                       '</div>',
-                       // Can't do asynchronous because we're testing that the event *doesn't* happen
-                       { instantHide: true }
-               );
-               $content = $collapsible.find( '.mw-collapsible-content' );
+               var $collapsible = prepareCollapsible(
+                               '<div class="mw-collapsible">' +
+                                       '<div class="mw-collapsible-toggle">' +
+                                               'Toggle <a href="#top">toggle</a> toggle <b>toggle</b>' +
+                                       '</div>' +
+                                       '<div class="mw-collapsible-content">' + loremIpsum + '</div>' +
+                               '</div>',
+                               // Can't do asynchronous because we're testing that the event *doesn't* happen
+                               { instantHide: true }
+                       ),
+                       $content = $collapsible.find( '.mw-collapsible-content' );
 
                $collapsible.find( '.mw-collapsible-toggle a' ).trigger( 'click' );
                assert.assertTrue( $content.is( ':visible' ), 'click event on link inside toggle passes through (content not toggled)' );
        } );
 
        QUnit.asyncTest( 'collapse/expand text (data-collapsetext, data-expandtext)', 2, function ( assert ) {
-               var $collapsible, $toggleLink;
-               $collapsible = prepareCollapsible(
-                       '<div class="mw-collapsible" data-collapsetext="Collapse me!" data-expandtext="Expand me!">' +
-                               loremIpsum +
-                       '</div>'
-               );
-               $toggleLink = $collapsible.find( '.mw-collapsible-toggle a' );
+               var $collapsible = prepareCollapsible(
+                               '<div class="mw-collapsible" data-collapsetext="Collapse me!" data-expandtext="Expand me!">' +
+                                       loremIpsum +
+                               '</div>'
+                       ),
+                       $toggleLink = $collapsible.find( '.mw-collapsible-toggle a' );
 
                assert.equal( $toggleLink.text(), 'Collapse me!', 'data-collapsetext is respected' );
 
        } );
 
        QUnit.asyncTest( 'collapse/expand text (options.collapseText, options.expandText)', 2, function ( assert ) {
-               var $collapsible, $toggleLink;
-               $collapsible = prepareCollapsible(
-                       '<div class="mw-collapsible">' + loremIpsum + '</div>',
-                       { collapseText: 'Collapse me!', expandText: 'Expand me!' }
-               );
-               $toggleLink = $collapsible.find( '.mw-collapsible-toggle a' );
+               var $collapsible = prepareCollapsible(
+                               '<div class="mw-collapsible">' + loremIpsum + '</div>',
+                               { collapseText: 'Collapse me!', expandText: 'Expand me!' }
+                       ),
+                       $toggleLink = $collapsible.find( '.mw-collapsible-toggle a' );
 
                assert.equal( $toggleLink.text(), 'Collapse me!', 'options.collapseText is respected' );
 
index f73fd7b..d9801d9 100644 (file)
@@ -1,7 +1,161 @@
 ( function ( $, mw ) {
-       /*jshint onevar: false */
+       var config, header,
 
-       var config = {
+               // Data set "simple"
+               a1 = [ 'A', '1' ],
+               a2 = [ 'A', '2' ],
+               a3 = [ 'A', '3' ],
+               b1 = [ 'B', '1' ],
+               b2 = [ 'B', '2' ],
+               b3 = [ 'B', '3' ],
+               simple = [a2, b3, a1, a3, b2, b1],
+               simpleAsc = [a1, a2, a3, b1, b2, b3],
+               simpleDescasc = [b1, b2, b3, a1, a2, a3],
+
+               // Data set "colspan"
+               aaa1 = [ 'A', 'A', 'A', '1' ],
+               aab5 = [ 'A', 'A', 'B', '5' ],
+               abc3 = [ 'A', 'B', 'C', '3' ],
+               bbc2 = [ 'B', 'B', 'C', '2' ],
+               caa4 = [ 'C', 'A', 'A', '4' ],
+               colspanInitial = [ aab5, aaa1, abc3, bbc2, caa4 ],
+
+               // Data set "planets"
+               mercury = [ 'Mercury', '2439.7' ],
+               venus = [ 'Venus', '6051.8' ],
+               earth = [ 'Earth', '6371.0' ],
+               mars = [ 'Mars', '3390.0' ],
+               jupiter = [ 'Jupiter', '69911' ],
+               saturn = [ 'Saturn', '58232' ],
+               planets = [mercury, venus, earth, mars, jupiter, saturn],
+               planetsAscName = [earth, jupiter, mars, mercury, saturn, venus],
+               planetsAscRadius = [mercury, mars, venus, earth, saturn, jupiter],
+               planetsRowspan,
+               planetsRowspanII,
+               planetsAscNameLegacy,
+
+               // Data set "ipv4"
+               ipv4 = [
+                       // Some randomly generated fake IPs
+                       ['45.238.27.109'],
+                       ['44.172.9.22'],
+                       ['247.240.82.209'],
+                       ['204.204.132.158'],
+                       ['170.38.91.162'],
+                       ['197.219.164.9'],
+                       ['45.68.154.72'],
+                       ['182.195.149.80']
+               ],
+               ipv4Sorted = [
+                       // Sort order should go octet by octet
+                       ['44.172.9.22'],
+                       ['45.68.154.72'],
+                       ['45.238.27.109'],
+                       ['170.38.91.162'],
+                       ['182.195.149.80'],
+                       ['197.219.164.9'],
+                       ['204.204.132.158'],
+                       ['247.240.82.209']
+               ],
+
+               // Data set "umlaut"
+               umlautWords = [
+                       ['Günther'],
+                       ['Peter'],
+                       ['Björn'],
+                       ['Bjorn'],
+                       ['Apfel'],
+                       ['Äpfel'],
+                       ['Strasse'],
+                       ['Sträßschen']
+               ],
+               umlautWordsSorted = [
+                       ['Äpfel'],
+                       ['Apfel'],
+                       ['Björn'],
+                       ['Bjorn'],
+                       ['Günther'],
+                       ['Peter'],
+                       ['Sträßschen'],
+                       ['Strasse']
+               ],
+
+               complexMDYDates = [
+                       ['January, 19 2010'],
+                       ['April 21 1991'],
+                       ['04 22 1991'],
+                       ['5.12.1990'],
+                       ['December 12 \'10']
+               ],
+               complexMDYSorted = [
+                       ['5.12.1990'],
+                       ['April 21 1991'],
+                       ['04 22 1991'],
+                       ['January, 19 2010'],
+                       ['December 12 \'10']
+               ],
+
+               currencyUnsorted = [
+                       ['1.02 $'],
+                       ['$ 3.00'],
+                       ['€ 2,99'],
+                       ['$ 1.00'],
+                       ['$3.50'],
+                       ['$ 1.50'],
+                       ['€ 0.99']
+               ],
+               currencySorted = [
+                       ['€ 0.99'],
+                       ['$ 1.00'],
+                       ['1.02 $'],
+                       ['$ 1.50'],
+                       ['$ 3.00'],
+                       ['$3.50'],
+                       // Comma's sort after dots
+                       // Not intentional but test to detect changes
+                       ['€ 2,99']
+               ],
+
+               numbers = [
+                       [ '12'    ],
+                       [  '7'    ],
+                       [ '13,000'],
+                       [  '9'    ],
+                       [ '14'    ],
+                       [  '8.0'  ]
+               ],
+               numbersAsc = [
+                       [  '7'    ],
+                       [  '8.0'  ],
+                       [  '9'    ],
+                       [ '12'    ],
+                       [ '14'    ],
+                       [ '13,000']
+               ],
+
+               correctDateSorting1 = [
+                       ['01 January 2010'],
+                       ['05 February 2010'],
+                       ['16 January 2010']
+               ],
+               correctDateSortingSorted1 = [
+                       ['01 January 2010'],
+                       ['16 January 2010'],
+                       ['05 February 2010']
+               ],
+
+               correctDateSorting2 = [
+                       ['January 01 2010'],
+                       ['February 05 2010'],
+                       ['January 16 2010']
+               ],
+               correctDateSortingSorted2 = [
+                       ['January 01 2010'],
+                       ['January 16 2010'],
+                       ['February 05 2010']
+               ];
+
+       config = {
                wgMonthNames: ['', 'January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'],
                wgMonthNamesShort: ['', 'Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'],
                wgDefaultDateFormat: 'dmy',
         */
        function tableTest( msg, header, data, expected, callback ) {
                QUnit.test( msg, 1, function ( assert ) {
-                       var $table = tableCreate( header, data );
+                       var extracted,
+                               $table = tableCreate( header, data );
 
                        // Give caller a chance to set up sorting and manipulate the table.
                        callback( $table );
 
                        // Table sorting is done synchronously; if it ever needs to change back
                        // to asynchronous, we'll need a timeout or a callback here.
-                       var extracted = tableExtract( $table );
+                       extracted = tableExtract( $table );
                        assert.deepEqual( extracted, expected, msg );
                } );
        }
         */
        function tableTestHTML( msg, html, expected, callback ) {
                QUnit.test( msg, 1, function ( assert ) {
-                       var $table = $( html );
+                       var extracted,
+                               $table = $( html );
 
                        // Give caller a chance to set up sorting and manipulate the table.
                        if ( callback ) {
 
                        // Table sorting is done synchronously; if it ever needs to change back
                        // to asynchronous, we'll need a timeout or a callback here.
-                       var extracted = tableExtract( $table );
+                       extracted = tableExtract( $table );
                        assert.deepEqual( extracted, expected, msg );
                } );
        }
        }
 
        // Sample data set using planets named and their radius
-       var header = [ 'Planet' , 'Radius (km)'],
-               mercury = [ 'Mercury', '2439.7' ],
-               venus = [ 'Venus'  , '6051.8' ],
-               earth = [ 'Earth'  , '6371.0' ],
-               mars = [ 'Mars'   , '3390.0' ],
-               jupiter = [ 'Jupiter', '69911' ],
-               saturn = [ 'Saturn' , '58232' ];
-
-       // Initial data set
-       var planets = [mercury, venus, earth, mars, jupiter, saturn];
-       var ascendingName = [earth, jupiter, mars, mercury, saturn, venus];
-       var ascendingRadius = [mercury, mars, venus, earth, saturn, jupiter];
+       header = [ 'Planet', 'Radius (km)'];
 
        tableTest(
                'Basic planet table: sorting initially - ascending by name',
                header,
                planets,
-               ascendingName,
+               planetsAscName,
                function ( $table ) {
                        $table.tablesorter( { sortList: [
                                { 0: 'asc' }
                'Basic planet table: sorting initially - descending by radius',
                header,
                planets,
-               reversed( ascendingRadius ),
+               reversed( planetsAscRadius ),
                function ( $table ) {
                        $table.tablesorter( { sortList: [
                                { 1: 'desc' }
                'Basic planet table: ascending by name',
                header,
                planets,
-               ascendingName,
+               planetsAscName,
                function ( $table ) {
                        $table.tablesorter();
                        $table.find( '.headerSort:eq(0)' ).click();
                'Basic planet table: ascending by name a second time',
                header,
                planets,
-               ascendingName,
+               planetsAscName,
                function ( $table ) {
                        $table.tablesorter();
                        $table.find( '.headerSort:eq(0)' ).click();
                'Basic planet table: ascending by name (multiple clicks)',
                header,
                planets,
-               ascendingName,
+               planetsAscName,
                function ( $table ) {
                        $table.tablesorter();
                        $table.find( '.headerSort:eq(0)' ).click();
                'Basic planet table: descending by name',
                header,
                planets,
-               reversed( ascendingName ),
+               reversed( planetsAscName ),
                function ( $table ) {
                        $table.tablesorter();
                        $table.find( '.headerSort:eq(0)' ).click().click();
                'Basic planet table: ascending radius',
                header,
                planets,
-               ascendingRadius,
+               planetsAscRadius,
                function ( $table ) {
                        $table.tablesorter();
                        $table.find( '.headerSort:eq(1)' ).click();
                'Basic planet table: descending radius',
                header,
                planets,
-               reversed( ascendingRadius ),
+               reversed( planetsAscRadius ),
                function ( $table ) {
                        $table.tablesorter();
                        $table.find( '.headerSort:eq(1)' ).click().click();
                }
        );
 
-       // Sample data set to test multiple column sorting
-       header = [ 'column1' , 'column2'];
-       var
-               a1 = [ 'A', '1' ],
-               a2 = [ 'A', '2' ],
-               a3 = [ 'A', '3' ],
-               b1 = [ 'B', '1' ],
-               b2 = [ 'B', '2' ],
-               b3 = [ 'B', '3' ];
-       var initial = [a2, b3, a1, a3, b2, b1];
-       var asc = [a1, a2, a3, b1, b2, b3];
-       var descasc = [b1, b2, b3, a1, a2, a3];
+       header = [ 'column1', 'column2' ];
 
        tableTest(
                'Sorting multiple columns by passing sort list',
                header,
-               initial,
-               asc,
+               simple,
+               simpleAsc,
                function ( $table ) {
                        $table.tablesorter(
                                { sortList: [
        tableTest(
                'Sorting multiple columns by programmatically triggering sort()',
                header,
-               initial,
-               descasc,
+               simple,
+               simpleDescasc,
                function ( $table ) {
                        $table.tablesorter();
                        $table.data( 'tablesorter' ).sort(
        tableTest(
                'Reset to initial sorting by triggering sort() without any parameters',
                header,
-               initial,
-               asc,
+               simple,
+               simpleAsc,
                function ( $table ) {
                        $table.tablesorter(
                                { sortList: [
        tableTest(
                'Sort via click event after having initialized the tablesorter with initial sorting',
                header,
-               initial,
-               descasc,
+               simple,
+               simpleDescasc,
                function ( $table ) {
                        $table.tablesorter(
                                { sortList: [ { 0: 'asc' }, { 1: 'asc' } ] }
        tableTest(
                'Multi-sort via click event after having initialized the tablesorter with initial sorting',
                header,
-               initial,
-               asc,
+               simple,
+               simpleAsc,
                function ( $table ) {
                        $table.tablesorter(
                                { sortList: [ { 0: 'desc' }, { 1: 'desc' } ] }
                }
        );
        QUnit.test( 'Reset sorting making table appear unsorted', 3, function ( assert ) {
-               var $table = tableCreate( header, initial );
+               var $table = tableCreate( header, simple );
                $table.tablesorter(
                        { sortList: [
                                { 0: 'desc' },
        } );
 
        // Sorting with colspans
-       header = [ 'column1a' , 'column1b', 'column1c', 'column2' ];
-       var
-               aaa1 = [ 'A', 'A', 'A', '1' ],
-               aab5 = [ 'A', 'A', 'B', '5' ],
-               abc3 = [ 'A', 'B', 'C', '3' ],
-               bbc2 = [ 'B', 'B', 'C', '2' ],
-               caa4 = [ 'C', 'A', 'A', '4' ];
-       // initial is already declared above
-       initial = [ aab5, aaa1, abc3, bbc2, caa4 ];
+       header = [ 'column1a', 'column1b', 'column1c', 'column2' ];
+
        tableTest( 'Sorting with colspanned headers: spanned column',
                header,
-               initial,
+               colspanInitial,
                [ aaa1, aab5, abc3, bbc2, caa4 ],
                function ( $table ) {
                        // Make colspanned header for test
        );
        tableTest( 'Sorting with colspanned headers: sort spanned column twice',
                header,
-               initial,
+               colspanInitial,
                [ caa4, bbc2, abc3, aab5, aaa1 ],
                function ( $table ) {
                        // Make colspanned header for test
        );
        tableTest( 'Sorting with colspanned headers: subsequent column',
                header,
-               initial,
+               colspanInitial,
                [ aaa1, bbc2, abc3, caa4, aab5 ],
                function ( $table ) {
                        // Make colspanned header for test
        );
        tableTest( 'Sorting with colspanned headers: sort subsequent column twice',
                header,
-               initial,
+               colspanInitial,
                [ aab5, caa4, abc3, bbc2, aaa1 ],
                function ( $table ) {
                        // Make colspanned header for test
                }
        );
 
-
        tableTest(
                'Basic planet table: one unsortable column',
                header,
                }
        );
 
-       var ipv4 = [
-               // Some randomly generated fake IPs
-               ['45.238.27.109'],
-               ['44.172.9.22'],
-               ['247.240.82.209'],
-               ['204.204.132.158'],
-               ['170.38.91.162'],
-               ['197.219.164.9'],
-               ['45.68.154.72'],
-               ['182.195.149.80']
-       ];
-       var ipv4Sorted = [
-               // Sort order should go octet by octet
-               ['44.172.9.22'],
-               ['45.68.154.72'],
-               ['45.238.27.109'],
-               ['170.38.91.162'],
-               ['182.195.149.80'],
-               ['197.219.164.9'],
-               ['204.204.132.158'],
-               ['247.240.82.209']
-       ];
-
        tableTest(
                'Bug 17141: IPv4 address sorting',
                ['IP'],
                }
        );
 
-       var umlautWords = [
-               // Some words with Umlauts
-               ['Günther'],
-               ['Peter'],
-               ['Björn'],
-               ['Bjorn'],
-               ['Apfel'],
-               ['Äpfel'],
-               ['Strasse'],
-               ['Sträßschen']
-       ];
-
-       var umlautWordsSorted = [
-               // Some words with Umlauts
-               ['Äpfel'],
-               ['Apfel'],
-               ['Björn'],
-               ['Bjorn'],
-               ['Günther'],
-               ['Peter'],
-               ['Sträßschen'],
-               ['Strasse']
-       ];
-
        tableTest(
                'Accented Characters with custom collation',
                ['Name'],
                );
        } );
 
-       var planetsRowspan = [
+       planetsRowspan = [
                [ 'Earth', '6051.8' ],
                jupiter,
                [ 'Mars', '6051.8' ],
                saturn,
                venus
        ];
-       var planetsRowspanII = [ jupiter, mercury, saturn, venus, [ 'Venus', '6371.0' ], [ 'Venus', '3390.0' ] ];
+       planetsRowspanII = [ jupiter, mercury, saturn, venus, [ 'Venus', '6371.0' ], [ 'Venus', '3390.0' ] ];
 
        tableTest(
                'Basic planet table: same value for multiple rows via rowspan',
                }
        );
 
-       var complexMDYDates = [
-               // Some words with Umlauts
-               ['January, 19 2010'],
-               ['April 21 1991'],
-               ['04 22 1991'],
-               ['5.12.1990'],
-               ['December 12 \'10']
-       ];
-
-       var complexMDYSorted = [
-               ['5.12.1990'],
-               ['April 21 1991'],
-               ['04 22 1991'],
-               ['January, 19 2010'],
-               ['December 12 \'10']
-       ];
-
        tableTest(
                'Complex date parsing I',
                ['date'],
                }
        );
 
-       var currencyUnsorted = [
-               ['1.02 $'],
-               ['$ 3.00'],
-               ['€ 2,99'],
-               ['$ 1.00'],
-               ['$3.50'],
-               ['$ 1.50'],
-               ['€ 0.99']
-       ];
-
-       var currencySorted = [
-               ['€ 0.99'],
-               ['$ 1.00'],
-               ['1.02 $'],
-               ['$ 1.50'],
-               ['$ 3.00'],
-               ['$3.50'],
-               // Comma's sort after dots
-               // Not intentional but test to detect changes
-               ['€ 2,99']
-       ];
-
        tableTest(
                'Currency parsing I',
                ['currency'],
                }
        );
 
-       var ascendingNameLegacy = ascendingName.slice( 0 );
-       ascendingNameLegacy[4] = ascendingNameLegacy[5];
-       ascendingNameLegacy.pop();
+       planetsAscNameLegacy = planetsAscName.slice( 0 );
+       planetsAscNameLegacy[4] = planetsAscNameLegacy[5];
+       planetsAscNameLegacy.pop();
 
        tableTest(
                'Legacy compat with .sortbottom',
                header,
                planets,
-               ascendingNameLegacy,
+               planetsAscNameLegacy,
                function ( $table ) {
                        $table.find( 'tr:last' ).addClass( 'sortbottom' );
                        $table.tablesorter();
 
        } );
 
-       var numbers = [
-               [ '12'    ],
-               [  '7'    ],
-               [ '13,000'],
-               [  '9'    ],
-               [ '14'    ],
-               [  '8.0'  ]
-       ];
-       var numbersAsc = [
-               [  '7'    ],
-               [  '8.0'  ],
-               [  '9'    ],
-               [ '12'    ],
-               [ '14'    ],
-               [ '13,000']
-       ];
-
        tableTest( 'bug 8115: sort numbers with commas (ascending)',
                ['Numbers'], numbers, numbersAsc,
                function ( $table ) {
                );
        } );
 
-
-       var correctDateSorting1 = [
-               ['01 January 2010'],
-               ['05 February 2010'],
-               ['16 January 2010']
-       ];
-
-       var correctDateSortingSorted1 = [
-               ['01 January 2010'],
-               ['16 January 2010'],
-               ['05 February 2010']
-       ];
-
        tableTest(
                'Correct date sorting I',
                ['date'],
                }
        );
 
-       var correctDateSorting2 = [
-               ['January 01 2010'],
-               ['February 05 2010'],
-               ['January 16 2010']
-       ];
-
-       var correctDateSortingSorted2 = [
-               ['January 01 2010'],
-               ['January 16 2010'],
-               ['February 05 2010']
-       ];
-
        tableTest(
                'Correct date sorting II',
                ['date'],
                );
        } );
 
+       QUnit.test( 'holes in the table headers should not throw JS errors', 2, function ( assert ) {
+               var $table = $(
+                       '<table class="sortable">' +
+                               '<thead>' +
+                               '<tr><th id="A1">A1</th><th>B1</th><th id="C1" rowspan="2">C1</th></tr>' +
+                               '<tr><th id="A2">A2</th></tr>' +
+                               '</thead>' +
+                               '<tr><td>A</td><td>Aa</td><td>Aaa</td></tr>' +
+                               '<tr><td>B</td><td>Ba</td><td>Bbb</td></tr>' +
+                               '</table>'
+               );
+               $table.tablesorter();
+               assert.equal( 0,
+                       $table.find( '#A2' ).prop( 'headerIndex' ),
+                       'A2 should be a sort header'
+               );
+               assert.equal( 1, // should be 2
+                       $table.find( '#C1' ).prop( 'headerIndex' ),
+                       'C1 should be a sort header, but will sort the wrong column'
+               );
+       } );
+
        // bug 41889 - exploding rowspans in more complex cases
        tableTestHTML(
                'Rowspan exploding with row headers',
                ]
        );
 
+       // bug 53211 - exploding rowspans in more complex cases
+       QUnit.test(
+               'Rowspan exploding with row headers and colspans', 1, function ( assert ) {
+               var $table = $( '<table class="sortable">' +
+                       '<thead><tr><th rowspan="2">n</th><th colspan="2">foo</th><th rowspan="2">baz</th></tr>' +
+                       '<tr><th>foo</th><th>bar</th></tr></thead>' +
+                       '<tbody>' +
+                       '<tr><td>1</td><td>foo</td><td>bar</td><td>baz</td></tr>' +
+                       '<tr><td>2</td><td>foo</td><td>bar</td><td>baz</td></tr>' +
+                       '</tbody></table>' );
+
+                       $table.tablesorter();
+                       assert.equal( 2, $table.find( 'tr:eq(1) th:eq(1)').prop('headerIndex'), 'Incorrect index of sort header' );
+               }
+       );
+
        tableTestHTML(
                'Rowspan exploding with colspanned cells',
                '<table class="sortable">' +
index 2bed9b9..70bcaf9 100644 (file)
@@ -1,28 +1,29 @@
-( function ( mw, $ ) {
-       QUnit.module( 'mediawiki.api.parse', QUnit.newMwEnvironment() );
+( function ( mw ) {
+       QUnit.module( 'mediawiki.api.parse', QUnit.newMwEnvironment( {
+               setup: function () {
+                       this.clock = this.sandbox.useFakeTimers();
+                       this.server = this.sandbox.useFakeServer();
+               },
+               teardown: function () {
+                       this.clock.tick( 1 );
+               }
+       } ) );
 
-       QUnit.asyncTest( 'Hello world', function ( assert ) {
-               var api;
-               QUnit.expect( 6 );
+       QUnit.test( 'Hello world', function ( assert ) {
+               QUnit.expect( 1 );
 
-               api = new mw.Api();
+               var api = new mw.Api();
 
-               api.parse( '\'\'\'Hello world\'\'\'' )
-                       .done( function ( html ) {
-                               // Parse into a document fragment instead of comparing HTML, due to
-                               // presence of Tidy influencing whitespace.
-                               // Html also contains "NewPP report" comment.
-                               var $res = $( '<div>' ).html( html ).children(),
-                                       res = $res.get( 0 );
-                               assert.equal( $res.length, 1, 'Response contains 1 element' );
-                               assert.equal( res.nodeName.toLowerCase(), 'p', 'Response is a paragraph' );
-                               assert.equal( $res.children().length, 1, 'Response has 1 child element' );
-                               assert.equal( $res.children().get( 0 ).nodeName.toLowerCase(), 'b', 'Child element is a bold tag' );
-                               // Trim since Tidy may or may not mess with the spacing here
-                               assert.equal( $.trim( $res.text() ), 'Hello world', 'Response contains given text' );
-                               assert.equal( $res.find( 'b' ).text(), 'Hello world', 'Bold tag wraps the entire, same, text' );
+               api.parse( '\'\'\'Hello world\'\'\'' ).done( function ( html ) {
+                       assert.equal( html, '<p><b>Hello world</b></p>' );
+               } );
 
-                               QUnit.start();
-                       } );
+               this.server.respondWith( /action=parse.*&text='''Hello\+world'''/, function ( request ) {
+                       request.respond( 200, { 'Content-Type': 'application/json' },
+                               '{ "parse": { "text": { "*": "<p><b>Hello world</b></p>" } } }'
+                       );
+               } );
+
+               this.server.respond();
        } );
-}( mediaWiki, jQuery ) );
+}( mediaWiki ) );
index c903193..2ad7622 100644 (file)
@@ -7,7 +7,7 @@
                teardown: function () {
                        this.clock.tick( 1 );
                }
-       }) );
+       } ) );
 
        QUnit.test( 'Basic functionality', function ( assert ) {
                QUnit.expect( 2 );