Merge "Set autofocus on Special:Unblock"
authorjenkins-bot <jenkins-bot@gerrit.wikimedia.org>
Fri, 11 Jul 2014 14:39:47 +0000 (14:39 +0000)
committerGerrit Code Review <gerrit@wikimedia.org>
Fri, 11 Jul 2014 14:39:47 +0000 (14:39 +0000)
448 files changed:
.travis.yml
RELEASE-NOTES-1.24
StartProfiler.sample
api.php
docs/hooks.txt
docs/scripts.txt
includes/AutoLoader.php
includes/Block.php
includes/ChangeTags.php
includes/DefaultSettings.php
includes/EditPage.php
includes/GitInfo.php
includes/GlobalFunctions.php
includes/Hooks.php
includes/Html.php
includes/MWTimestamp.php
includes/Message.php
includes/MimeMagic.php
includes/Namespace.php
includes/OutputPage.php
includes/PHPVersionError.php
includes/Preferences.php
includes/Revision.php
includes/Sanitizer.php
includes/Setup.php
includes/SiteConfiguration.php
includes/Skin.php
includes/SkinTemplate.php
includes/StubObject.php
includes/Title.php
includes/User.php
includes/UserMailer.php
includes/WebStart.php
includes/actions/EditAction.php
includes/actions/HistoryAction.php
includes/actions/RevertAction.php
includes/api/ApiBase.php
includes/api/ApiImageRotate.php
includes/api/ApiParse.php
includes/api/ApiPurge.php
includes/api/ApiQuery.php
includes/api/ApiQueryAllUsers.php
includes/api/ApiQueryBase.php
includes/api/ApiQueryDeletedrevs.php
includes/api/ApiQueryRecentChanges.php
includes/api/ApiQuerySiteinfo.php
includes/api/ApiQueryUserContributions.php
includes/api/ApiResult.php
includes/api/ApiSetNotificationTimestamp.php
includes/api/ApiWatch.php
includes/cache/CacheDependency.php
includes/cache/LocalisationCache.php
includes/clientpool/RedisConnectionPool.php
includes/content/ContentHandler.php
includes/db/Database.php
includes/db/DatabaseMssql.php
includes/db/DatabasePostgres.php
includes/db/LBFactorySingle.php
includes/debug/Debug.php
includes/diff/TableDiffFormatter.php
includes/filebackend/FSFileBackend.php
includes/filerepo/FileRepo.php
includes/filerepo/ForeignAPIRepo.php
includes/filerepo/RepoGroup.php
includes/filerepo/file/File.php
includes/gallery/ImageGalleryBase.php
includes/htmlform/HTMLCheckField.php [changed mode: 0755->0644]
includes/htmlform/HTMLForm.php
includes/htmlform/HTMLSelectAndOtherField.php
includes/htmlform/HTMLSelectField.php
includes/htmlform/HTMLSelectOrOtherField.php
includes/installer/DatabaseUpdater.php
includes/installer/Installer.php
includes/installer/MssqlInstaller.php
includes/installer/MssqlUpdater.php
includes/installer/PostgresInstaller.php
includes/installer/WebInstallerPage.php
includes/installer/i18n/bar.json
includes/installer/i18n/br.json
includes/installer/i18n/ce.json
includes/installer/i18n/cs.json
includes/installer/i18n/de.json
includes/installer/i18n/en.json
includes/installer/i18n/es.json
includes/installer/i18n/fr.json
includes/installer/i18n/haw.json
includes/installer/i18n/he.json
includes/installer/i18n/mk.json
includes/installer/i18n/nb.json
includes/installer/i18n/pt-br.json
includes/installer/i18n/qqq.json
includes/installer/i18n/ru.json
includes/installer/i18n/sv.json
includes/installer/i18n/yi.json
includes/installer/i18n/zh-hans.json
includes/jobqueue/JobQueueRedis.php
includes/libs/CSSMin.php
includes/libs/HashRing.php
includes/libs/HttpStatus.php
includes/logging/PatrolLog.php
includes/media/Bitmap.php
includes/media/FormatMetadata.php
includes/media/ImageHandler.php
includes/media/Jpeg.php
includes/media/MediaHandler.php
includes/media/PNG.php
includes/media/XCF.php
includes/media/XMP.php
includes/mime.info
includes/mime.types
includes/page/ImagePage.php
includes/page/WikiPage.php
includes/parser/CoreParserFunctions.php
includes/parser/LinkHolderArray.php
includes/parser/Parser.php
includes/parser/ParserOptions.php
includes/poolcounter/PoolCounterRedis.php
includes/revisiondelete/RevisionDeleteUser.php
includes/search/SearchMySQL.php
includes/search/SearchResultSet.php
includes/search/SearchSqlite.php
includes/specialpage/FormSpecialPage.php
includes/specialpage/RedirectSpecialPage.php
includes/specials/SpecialActiveusers.php
includes/specials/SpecialContributions.php
includes/specials/SpecialCreateAccount.php
includes/specials/SpecialLinkSearch.php
includes/specials/SpecialListfiles.php
includes/specials/SpecialMovepage.php
includes/specials/SpecialPagesWithProp.php
includes/specials/SpecialRevisiondelete.php
includes/specials/SpecialSearch.php
includes/specials/SpecialUpload.php
includes/specials/SpecialVersion.php
includes/specials/SpecialWantedfiles.php
includes/title/MediaWikiTitleCodec.php
includes/upload/UploadBase.php
index.php
languages/Language.php
languages/Names.php
languages/classes/LanguageRu.php
languages/i18n/ar.json
languages/i18n/az.json
languages/i18n/bar.json
languages/i18n/bcl.json
languages/i18n/be-tarask.json
languages/i18n/be.json
languages/i18n/bho.json
languages/i18n/bn.json
languages/i18n/br.json
languages/i18n/bs.json
languages/i18n/ca.json
languages/i18n/ce.json
languages/i18n/ckb.json
languages/i18n/cs.json
languages/i18n/cy.json
languages/i18n/da.json
languages/i18n/de.json
languages/i18n/diq.json
languages/i18n/el.json
languages/i18n/en.json
languages/i18n/eo.json
languages/i18n/es.json
languages/i18n/et.json
languages/i18n/fa.json
languages/i18n/fi.json
languages/i18n/fo.json
languages/i18n/fr.json
languages/i18n/frr.json
languages/i18n/gan-hans.json
languages/i18n/gd.json
languages/i18n/he.json
languages/i18n/hr.json
languages/i18n/hu.json
languages/i18n/ia.json
languages/i18n/is.json
languages/i18n/it.json
languages/i18n/ja.json
languages/i18n/kk-cyrl.json
languages/i18n/ksh.json
languages/i18n/lb.json
languages/i18n/lv.json
languages/i18n/mk.json
languages/i18n/ml.json
languages/i18n/mt.json
languages/i18n/nan.json
languages/i18n/nb.json
languages/i18n/nds-nl.json
languages/i18n/nl.json
languages/i18n/pa.json
languages/i18n/pl.json
languages/i18n/pt-br.json
languages/i18n/pt.json
languages/i18n/qqq.json
languages/i18n/ro.json
languages/i18n/ru.json
languages/i18n/scn.json
languages/i18n/sl.json
languages/i18n/sq.json
languages/i18n/sr-ec.json
languages/i18n/sr-el.json
languages/i18n/sv.json
languages/i18n/th.json
languages/i18n/tr.json
languages/i18n/uk.json
languages/i18n/vi.json
languages/i18n/wuu.json
languages/i18n/yi.json
languages/i18n/zh-hans.json
languages/i18n/zh-hant.json
load.php
maintenance/install.php
maintenance/mssql/archives/named_constraints.sql [new file with mode: 0644]
maintenance/mssql/tables.sql
maintenance/update.php
mw-config/index.php
resources/lib/es5-shim/es5-shim.js
resources/lib/jquery.ui/themes/smoothness/images/ui-bg_flat_0_aaaaaa_40x100.png [changed mode: 0755->0644]
resources/lib/jquery.ui/themes/smoothness/images/ui-bg_flat_75_ffffff_40x100.png [changed mode: 0755->0644]
resources/lib/jquery.ui/themes/smoothness/images/ui-bg_glass_55_fbf9ee_1x400.png [changed mode: 0755->0644]
resources/lib/jquery.ui/themes/smoothness/images/ui-bg_glass_65_ffffff_1x400.png [changed mode: 0755->0644]
resources/lib/jquery.ui/themes/smoothness/images/ui-bg_glass_75_dadada_1x400.png [changed mode: 0755->0644]
resources/lib/jquery.ui/themes/smoothness/images/ui-bg_glass_75_e6e6e6_1x400.png [changed mode: 0755->0644]
resources/lib/jquery.ui/themes/smoothness/images/ui-bg_glass_95_fef1ec_1x400.png [changed mode: 0755->0644]
resources/lib/jquery.ui/themes/smoothness/images/ui-bg_highlight-soft_75_cccccc_1x100.png [changed mode: 0755->0644]
resources/lib/jquery.ui/themes/smoothness/images/ui-icons_222222_256x240.png [changed mode: 0755->0644]
resources/lib/jquery.ui/themes/smoothness/images/ui-icons_2e83ff_256x240.png [changed mode: 0755->0644]
resources/lib/jquery.ui/themes/smoothness/images/ui-icons_454545_256x240.png [changed mode: 0755->0644]
resources/lib/jquery.ui/themes/smoothness/images/ui-icons_888888_256x240.png [changed mode: 0755->0644]
resources/lib/jquery.ui/themes/smoothness/images/ui-icons_cd0a0a_256x240.png [changed mode: 0755->0644]
resources/lib/oojs-ui/i18n/lv.json
resources/lib/oojs-ui/images/icons/accept.svg
resources/lib/oojs-ui/images/icons/add-item.svg
resources/lib/oojs-ui/images/icons/advanced.svg
resources/lib/oojs-ui/images/icons/alert.svg
resources/lib/oojs-ui/images/icons/arched-arrow-ltr.svg
resources/lib/oojs-ui/images/icons/arched-arrow-rtl.svg
resources/lib/oojs-ui/images/icons/check.svg
resources/lib/oojs-ui/images/icons/clear.svg
resources/lib/oojs-ui/images/icons/close.svg
resources/lib/oojs-ui/images/icons/code.svg
resources/lib/oojs-ui/images/icons/collapse.svg
resources/lib/oojs-ui/images/icons/comment.svg
resources/lib/oojs-ui/images/icons/expand.svg
resources/lib/oojs-ui/images/icons/help.svg
resources/lib/oojs-ui/images/icons/history.svg
resources/lib/oojs-ui/images/icons/info.svg
resources/lib/oojs-ui/images/icons/link.svg
resources/lib/oojs-ui/images/icons/menu.svg
resources/lib/oojs-ui/images/icons/move-ltr.svg
resources/lib/oojs-ui/images/icons/move-rtl.svg
resources/lib/oojs-ui/images/icons/picture.svg
resources/lib/oojs-ui/images/icons/remove-item.svg
resources/lib/oojs-ui/images/icons/remove.svg
resources/lib/oojs-ui/images/icons/search.svg
resources/lib/oojs-ui/images/icons/settings.svg
resources/lib/oojs-ui/images/icons/tag.svg
resources/lib/oojs-ui/images/icons/window.svg
resources/lib/oojs-ui/images/indicators/alert.svg
resources/lib/oojs-ui/images/indicators/arrow-down.svg
resources/lib/oojs-ui/images/indicators/arrow-ltr.svg
resources/lib/oojs-ui/images/indicators/arrow-rtl.svg
resources/lib/oojs-ui/images/indicators/arrow-up.svg
resources/lib/oojs-ui/images/indicators/required.svg
resources/lib/oojs-ui/oojs-ui-agora.css
resources/lib/oojs-ui/oojs-ui-apex.css
resources/lib/oojs-ui/oojs-ui.js
resources/lib/oojs-ui/oojs-ui.svg.css
resources/lib/sinonjs/sinon-1.10.3.js [new file with mode: 0644]
resources/lib/sinonjs/sinon-1.9.0.js [deleted file]
resources/lib/sinonjs/sinon-ie-1.10.3.js [new file with mode: 0644]
resources/lib/sinonjs/sinon-ie-1.9.0.js [deleted file]
resources/src/es5-skip.js
resources/src/jquery.json-deprecate.js
resources/src/jquery.ui-themes/vector/jquery.ui.core.css
resources/src/jquery/jquery.makeCollapsible.js
resources/src/jquery/jquery.qunit.completenessTest.js
resources/src/mediawiki.language/languages/ru.js
resources/src/mediawiki.less/mediawiki.mixins.less
resources/src/mediawiki.page/mediawiki.page.gallery.js
resources/src/mediawiki.skinning/content.parsoid.less
resources/src/mediawiki.special/mediawiki.special.block.css
resources/src/mediawiki.special/mediawiki.special.css
resources/src/mediawiki.special/mediawiki.special.search.css
resources/src/mediawiki/mediawiki.feedback.js
resources/src/mediawiki/mediawiki.js
resources/src/mediawiki/mediawiki.searchSuggest.js
skins/MonoBook/i18n/es.json
skins/MonoBook/i18n/fa.json
skins/MonoBook/i18n/gd.json [new file with mode: 0644]
skins/MonoBook/i18n/ia.json
skins/MonoBook/i18n/lb.json
skins/MonoBook/i18n/nl.json
skins/MonoBook/i18n/pl.json
skins/MonoBook/i18n/pt.json
skins/MonoBook/i18n/ru.json
skins/MonoBook/i18n/uk.json
skins/MonoBook/i18n/vi.json
skins/MonoBook/i18n/zh-hans.json
skins/Vector/components/common.less
skins/Vector/i18n/af.json
skins/Vector/i18n/aln.json
skins/Vector/i18n/an.json
skins/Vector/i18n/ar.json
skins/Vector/i18n/arz.json
skins/Vector/i18n/ase.json
skins/Vector/i18n/ast.json
skins/Vector/i18n/ba.json
skins/Vector/i18n/bar.json
skins/Vector/i18n/be-tarask.json
skins/Vector/i18n/be.json
skins/Vector/i18n/bg.json
skins/Vector/i18n/bn.json
skins/Vector/i18n/bpy.json
skins/Vector/i18n/br.json
skins/Vector/i18n/ca.json
skins/Vector/i18n/ce.json
skins/Vector/i18n/cs.json
skins/Vector/i18n/cy.json
skins/Vector/i18n/da.json
skins/Vector/i18n/diq.json
skins/Vector/i18n/dsb.json
skins/Vector/i18n/el.json
skins/Vector/i18n/eo.json
skins/Vector/i18n/es.json
skins/Vector/i18n/et.json
skins/Vector/i18n/eu.json
skins/Vector/i18n/fa.json
skins/Vector/i18n/fi.json
skins/Vector/i18n/frp.json
skins/Vector/i18n/frr.json
skins/Vector/i18n/gd.json
skins/Vector/i18n/gl.json
skins/Vector/i18n/gsw.json
skins/Vector/i18n/gu.json
skins/Vector/i18n/he.json
skins/Vector/i18n/hr.json
skins/Vector/i18n/hsb.json
skins/Vector/i18n/hu.json
skins/Vector/i18n/ia.json
skins/Vector/i18n/id.json
skins/Vector/i18n/ilo.json
skins/Vector/i18n/is.json
skins/Vector/i18n/ja.json
skins/Vector/i18n/jv.json
skins/Vector/i18n/ka.json
skins/Vector/i18n/kk-cyrl.json
skins/Vector/i18n/krc.json
skins/Vector/i18n/ksh.json
skins/Vector/i18n/lb.json
skins/Vector/i18n/li.json
skins/Vector/i18n/lv.json
skins/Vector/i18n/min.json
skins/Vector/i18n/ml.json
skins/Vector/i18n/mr.json
skins/Vector/i18n/ms.json
skins/Vector/i18n/mt.json
skins/Vector/i18n/nb.json
skins/Vector/i18n/nds-nl.json
skins/Vector/i18n/nl.json
skins/Vector/i18n/oc.json
skins/Vector/i18n/or.json
skins/Vector/i18n/pl.json
skins/Vector/i18n/pms.json
skins/Vector/i18n/pnb.json
skins/Vector/i18n/pt-br.json
skins/Vector/i18n/qu.json
skins/Vector/i18n/ro.json
skins/Vector/i18n/roa-tara.json
skins/Vector/i18n/ru.json
skins/Vector/i18n/rue.json
skins/Vector/i18n/sa.json
skins/Vector/i18n/sah.json
skins/Vector/i18n/si.json
skins/Vector/i18n/sk.json
skins/Vector/i18n/sl.json
skins/Vector/i18n/sr-ec.json
skins/Vector/i18n/sr-el.json
skins/Vector/i18n/sw.json
skins/Vector/i18n/tl.json
skins/Vector/i18n/uk.json
skins/Vector/i18n/ur.json
skins/Vector/i18n/vec.json
skins/Vector/i18n/vi.json
skins/Vector/i18n/wa.json
skins/Vector/i18n/zh-hant.json
skins/common/images/icons/fileicon-xcf.png [new file with mode: 0644]
skins/common/images/tipsy-arrow.gif [deleted file]
skins/common/shared.css
tests/browser/Gemfile
tests/browser/Gemfile.lock
tests/browser/features/create_account.feature
tests/browser/features/create_and_follow_wiki_link.feature
tests/browser/features/edit_page.feature
tests/browser/features/file.feature [new file with mode: 0644]
tests/browser/features/login.feature [new file with mode: 0644]
tests/browser/features/main_page_links.feature
tests/browser/features/preferences.feature
tests/browser/features/step_definitions/edit_page_steps.rb
tests/browser/features/step_definitions/file_steps.rb [new file with mode: 0644]
tests/browser/features/step_definitions/login_steps.rb [new file with mode: 0644]
tests/browser/features/step_definitions/preferences_appearance_steps.rb
tests/browser/features/support/env.rb
tests/browser/features/support/pages/edit_page.rb
tests/browser/features/support/pages/file_does_not_exist_page.rb [new file with mode: 0644]
tests/browser/features/support/pages/login_error_page.rb [new file with mode: 0644]
tests/browser/features/support/pages/preferences_appearance_page.rb
tests/browser/features/support/pages/preferences_page.rb
tests/browser/features/view_history.feature
tests/parser/parserTests.txt
tests/phpunit/ResourceLoaderTestCase.php
tests/phpunit/data/media/README
tests/phpunit/data/media/say-test.ogg [new file with mode: 0644]
tests/phpunit/includes/GitInfoTest.php
tests/phpunit/includes/GlobalFunctions/GlobalTest.php
tests/phpunit/includes/HtmlTest.php
tests/phpunit/includes/ImagePage404Test.php [new file with mode: 0644]
tests/phpunit/includes/ImagePageTest.php [new file with mode: 0644]
tests/phpunit/includes/LinkerTest.php
tests/phpunit/includes/LinksUpdateTest.php
tests/phpunit/includes/MimeMagicTest.php [new file with mode: 0644]
tests/phpunit/includes/OutputPageTest.php
tests/phpunit/includes/SampleTest.php
tests/phpunit/includes/TitlePermissionTest.php
tests/phpunit/includes/TitleTest.php
tests/phpunit/includes/UserTest.php
tests/phpunit/includes/WikiPageTest.php
tests/phpunit/includes/api/ApiOptionsTest.php
tests/phpunit/includes/api/query/ApiQueryTest.php
tests/phpunit/includes/content/TextContentTest.php
tests/phpunit/includes/debug/MWDebugTest.php
tests/phpunit/includes/filerepo/RepoGroupTest.php [new file with mode: 0644]
tests/phpunit/includes/filerepo/file/FileTest.php [new file with mode: 0644]
tests/phpunit/includes/libs/CSSMinTest.php
tests/phpunit/includes/libs/MWMessagePackTest.php
tests/phpunit/includes/media/MediaWikiMediaTestCase.php
tests/phpunit/includes/media/XCFTest.php [new file with mode: 0644]
tests/phpunit/includes/normal/CleanUpTest.php
tests/phpunit/includes/site/MediaWikiSiteTest.php
tests/phpunit/includes/title/MediaWikiPageLinkRendererTest.php
tests/phpunit/includes/title/MediaWikiTitleCodecTest.php
tests/phpunit/languages/LanguageRuTest.php
tests/qunit/QUnitTestResources.php
tests/qunit/data/testrunner.js
tests/qunit/suites/resources/jquery/jquery.client.test.js
tests/qunit/suites/resources/mediawiki/mediawiki.language.test.js
tests/testHelpers.inc
thumb.php

index 64075f1..dedb4e1 100644 (file)
@@ -38,6 +38,7 @@ script:
   - php tests/phpunit/phpunit.php
 
 notifications:
+  email: false
   irc:
     channels:
       - "chat.freenode.net#mediawiki-core"
index 7cc8b13..bdbd611 100644 (file)
@@ -1,5 +1,5 @@
-Security reminder: MediaWiki does not require PHP's register_globals. If you
-have it on, turn it '''off''' if you can.
+Security reminder: If you have PHP's register_globals option set, you must
+turn it off. MediaWiki will no longer work with it enabled.
 
 == MediaWiki 1.24 ==
 
@@ -9,6 +9,9 @@ MediaWiki 1.24 is an alpha-quality branch and is not recommended for use in
 production.
 
 === Configuration changes in 1.24 ===
+* MediaWiki will no longer run if register_globals is enabled. It has been
+  deprecated for 5 years now, and was removed in PHP 5.4. For more information
+  about why, see <https://www.mediawiki.org/wiki/register_globals>.
 * The server's canonical hostname is available as $wgServerName, which is
   exposed in both mw.config and ApiQuerySiteInfo.
 * Introduced $wgPagePropsHaveSortkey as a backwards-compatibility switch,
@@ -26,6 +29,12 @@ production.
   prefixes (i.e. turned into interlanguage links when $wgInterwikiMagic is set
   to true).
 * $wgParserTestRemote has been removed.
+* $wgCountTotalSearchHits has been removed. If you're concerned about efficiency
+  of search, you should use something like CirrusSearch instead of built in
+  search.
+* Users in the 'sysop' group have access to Special:MergeHistory by default.
+* $wgFileStore was removed after having been deprecated in 1.17. Alternative
+  configurations are $wgDeletedDirectory and $wgHashedUploadDirectory.
 
 === New features in 1.24 ===
 * Added a new hook, "WhatLinksHereProps", to allow extensions to annotate
@@ -101,6 +110,9 @@ production.
   The feature needs to be enabled with $wgPageLanguageUseDB=true and
   permission needs to be set for 'pagelang'.
 * Upgrade Moment.js to v2.7.0.
+* (bug 67042) Added support for the HTML5 <rtc> tag for East Asian typography.
+* Upgrade Sinon.JS to 1.10.3.
+* Added the es5-shim polyfill for older or non-compliant javascript engines.
 
 === Bug fixes in 1.24 ===
 * (bug 49116) Footer copyright notice is now always displayed in user language
@@ -124,6 +136,9 @@ production.
   however delete the redirect page.
 * (bug 22683) {{msgnw:}} and other uses of PPFrame::RECOVER_ORIG will correctly
   recover the original code of extension tags.
+* (bug 65757) MSSQL: Update script drops unnamed constraints to be prepared
+  for future updates. Because it's doing so heuristically, it may fail or drop
+  wrong constraints.
 
 === Web API changes in 1.24 ===
 * action=parse API now supports prop=modules, which provides the list of
@@ -144,6 +159,12 @@ production.
   The old format is still used if prop isn't provided, but this is deprecated.
 * meta=userinfo can now return the count of unread pages on the watchlist.
 * list=watchlist can now filter by unread status.
+* The deprecated action=parse&prop=languageshtml has been removed.
+* (bug 48071) action=setnotificationtimestamp no longer throws PHP or database
+  errors when no pages are given.
+* (bug 60734) Actions that use ApiPageSet (e.g. purge, watch,
+  setnotificationtimestamp) will now include continuation information when
+  using a generator.
 
 === Languages updated in 1.24 ===
 
@@ -200,6 +221,21 @@ changes to languages because of Bugzilla reports.
 * BREAKING CHANGE: The undocumented Special{$this->getName()}BeforeFormDisplay
   set of hooks has been removed and replaced by a single new hook
   SpecialPageBeforeFormDisplay.
+* (bug 65781) Removed block warning on included {{Special:Contributions}}
+* Removed Skin::makeGlobalVariablesScript. (deprecated since 1.19)
+* Removed MWNamespace::isMain(). (deprecated since 1.19)
+* Removed Preferences::loadOldSearchNs(). (deprecated since 1.19)
+* Removed OutputPage::getStatusMessage(). (deprecated since 1.18)
+* Removed OutputPage::isUserJsAllowed(). (deprecated since 1.18)
+* Removed Title::updateTitleProtection(). (deprecated since 1.19)
+* Removed ParserOptions::setSkin(). (deprecated since 1.19)
+* Removed Title::escapeCanonicalURL(). (deprecated since 1.19)
+* Removed Title::escapeLocalURL(). (deprecated since 1.19)
+* Removed Title::escapeFullURL(). (deprecated since 1.19)
+* Removed User::isValidEmailAddr(). (deprecated since 1.18)
+* Removed Title::getEscapedText(). (deprecated since 1.19)
+* Removed Language::getFallbackLanguageCode(). (deprecated since 1.19)
+* Removed WikiPage::isBigDeletion(). (deprecated since 1.19)
 
 ==== Renamed classes ====
 * CLDRPluralRuleConverter_Expression to CLDRPluralRuleConverterExpression
@@ -242,6 +278,7 @@ changes to languages because of Bugzilla reports.
 ==== Removed classes ====
 * IPBlockForm - Use SpecialBlock directly
 * WatchlistEditor - Use SpecialEditWatchlist directly
+* FormatExif - Use FormatMetadata directly
 
 == Compatibility ==
 
index db5e0ff..d9b5288 100644 (file)
@@ -2,13 +2,22 @@
 
 /**
  * To use a profiler, copy this file to StartProfiler.php,
- * and add something like this:
+ * and add either:
  *
- *   $wgProfiler['class'] = 'Profiler';
+ *   // Does not support the debugging toolbar
+ *   // Stores profiling information in the database
+ *   // Requires running maintenance/archives/patch-profiling.sql
+ *   $wgProfiler['class'] = 'ProfilerSimpleDB'
+ *
+ * or:
+ *
+ *   // Supports the debugging toolbar
+ *   // Does not store profiling information in the database
+ *   $wgProfiler['class'] = 'ProfilerStandard';
  *
  * Or for a sampling profiler:
  *   if ( !mt_rand( 0, 100 ) ) {
- *       $wgProfiler['class'] = 'Profiler';
+ *       $wgProfiler['class'] = 'ProfilerSimpleDB';
  *   } else {
  *       $wgProfiler['class'] = 'ProfilerStub';
  *   }
diff --git a/api.php b/api.php
index e55ec75..e8a911e 100644 (file)
--- a/api.php
+++ b/api.php
@@ -34,7 +34,7 @@
 define( 'MW_API', true );
 
 // Bail if PHP is too low
-if ( !function_exists( 'version_compare' ) || version_compare( phpversion(), '5.3.2' ) < 0 ) {
+if ( !function_exists( 'version_compare' ) || version_compare( PHP_VERSION, '5.3.2' ) < 0 ) {
        // We need to use dirname( __FILE__ ) here cause __DIR__ is PHP5.3+
        require dirname( __FILE__ ) . '/includes/PHPVersionError.php';
        wfPHPVersionError( 'api.php' );
index 1673f06..e4474c5 100644 (file)
@@ -326,6 +326,13 @@ $revCount: Number of revisions in the XML file
 $sRevCount: Number of successfully imported revisions
 $pageInfo: associative array of page information
 
+'AfterParserFetchFileAndTitle': After an image gallery is formed by Parser,
+just before adding its HTML to parser output.
+$parser: Parser object that called the hook
+$ig: Gallery, an object of one of the gallery classes (inheriting from
+ImageGalleryBase)
+$html: HTML generated by the gallery
+
 'AjaxAddScript': Called in output page just before the initialisation
 of the javascript ajax engine. The hook is only called when ajax
 is enabled ( $wgUseAjax = true; ).
@@ -1705,8 +1712,8 @@ $refreshLinks: RefreshLinks object
 'MagicWordwgVariableIDs': When defining new magic words IDs.
 $variableIDs: array of strings
 
-'MakeGlobalVariablesScript': Called right before Skin::makeVariablesScript is
-executed. Ideally, this hook should only be used to add variables that depend on
+'MakeGlobalVariablesScript': Called at end of OutputPage::getJSVars.
+Ideally, this hook should only be used to add variables that depend on
 the current page/request; static configuration should be added through
 ResourceLoaderGetConfigVars instead.
 &$vars: variable (or multiple variables) to be added into the output of
@@ -1750,6 +1757,30 @@ caches.
 $title: name of the page changed.
 $text: new contents of the page.
 
+'MimeMagicInit': Before processing the list mapping MIME types to media types
+and the list mapping MIME types to file extensions.
+As an extension author, you are encouraged to submit patches to MediaWiki's
+core to add new MIME types to mime.types.
+$mimeMagic: Instance of MimeMagic.
+  Use $mimeMagic->addExtraInfo( $stringOfInfo );
+  for adding new MIME info to the list.
+  Use $mimeMagic->addExtraTypes( $stringOfTypes );
+  for adding new MIME types to the list.
+
+'MimeMagicImproveFromExtension': Allows MW extensions to further improve the
+MIME type detected by considering the file extension.
+$mimeMagic: Instance of MimeMagic.
+$ext: File extension.
+&$mime: MIME type (in/out).
+
+'MimeMagicGuessFromContent': Allows MW extensions guess the MIME by content.
+$mimeMagic: Instance of MimeMagic.
+&$head: First 1024 bytes of the file in a string (in - Do not alter!).
+&$tail: More or equal than last 65558 bytes of the file in a string
+  (in - Do not alter!).
+$file: File path.
+&$mime: MIME type (out).
+
 'ModifyExportQuery': Modify the query used by the exporter.
 $db: The database object to be queried.
 &$tables: Tables in the query.
@@ -2889,6 +2920,15 @@ to be switched to HTTPS.
 $user: User in question.
 &$https: Boolean whether $user should be switched to HTTPS.
 
+'UserResetAllOptions': Called in User::resetOptions() when user preferences
+have been requested to be reset. This hook can be used to exclude certain
+options from being reset even when the user has requested all prefs to be reset,
+because certain options might be stored in the user_properties database table
+despite not being visible and editable via Special:Preferences.
+$user: the User (object) whose preferences are being reset
+&$newOptions: array of new (site default) preferences
+$options: array of the user's old preferences
+$resetKinds: array containing the kinds of preferences to reset
 
 'UserRetrieveNewTalks': Called when retrieving "You have new messages!"
 message(s).
@@ -2929,6 +2969,11 @@ invalidated and GetExtendedMetadata hook called again).
 $timestamp: The timestamp metadata was generated
 $file: The file the metadata is for
 
+'UserMailerChangeReturnPath': Called to generate a VERP return address
+when UserMailer sends an email, with a bounce handling extension.
+$to: Array of MailAddress objects for the recipients
+&$returnPath: The return address string
+
 'WantedPages::getQueryInfo': Called in WantedPagesPage::getQueryInfo(), can be
 used to alter the SQL query which gets the list of wanted pages.
 &$wantedPages: WantedPagesPage object
index 4f16709..c6fa674 100644 (file)
@@ -40,7 +40,7 @@ Primary scripts:
 
     To enable the profileinfo.php itself, you'll need to set $wgDBadminuser
     and $wgDBadminpassword in your LocalSettings.php, as well as $wgEnableProfileInfo 
-    See also https://www.mediawiki.org/wiki/How_to_debug#Profiling.
+    See also https://www.mediawiki.org/wiki/Manual:Profiling .
 
   thumb.php
     Script used to resize images if it is configured to be done when the web
index 1417db0..67f9a1c 100644 (file)
@@ -738,7 +738,6 @@ $wgAutoloadLocalClasses = array(
        'DjVuImage' => 'includes/media/DjVuImage.php',
        'Exif' => 'includes/media/Exif.php',
        'ExifBitmapHandler' => 'includes/media/ExifBitmap.php',
-       'FormatExif' => 'includes/media/FormatMetadata.php',
        'FormatMetadata' => 'includes/media/FormatMetadata.php',
        'GIFHandler' => 'includes/media/GIF.php',
        'GIFMetadataExtractor' => 'includes/media/GIFMetadataExtractor.php',
index 3896369..c393a79 100644 (file)
@@ -1368,7 +1368,7 @@ class Block {
                        $this->getId(),
                        $lang->formatExpiry( $this->mExpiry ),
                        (string)$intended,
-                       $lang->timeanddate( wfTimestamp( TS_MW, $this->mTimestamp ), true ),
+                       $lang->userTimeAndDate( $this->mTimestamp, $context->getUser() ),
                );
        }
 }
index 28db8a1..f51a5a8 100644 (file)
@@ -77,9 +77,9 @@ class ChangeTags {
         * Add tags to a change given its rc_id, rev_id and/or log_id
         *
         * @param string|array $tags Tags to add to the change
-        * @param int $rc_id rc_id of the change to add the tags to
-        * @param int $rev_id rev_id of the change to add the tags to
-        * @param int $log_id Log_id of the change to add the tags to
+        * @param int|null $rc_id rc_id of the change to add the tags to
+        * @param int|null $rev_id rev_id of the change to add the tags to
+        * @param int|null $log_id Log_id of the change to add the tags to
         * @param string $params params to put in the ct_params field of table 'change_tag'
         *
         * @throws MWException
@@ -143,7 +143,7 @@ class ChangeTags {
                        'ts_log_id' => $log_id )
                );
 
-               ## Update the summary row.
+               // Update the summary row.
                // $prevTags can be out of date on slaves, especially when addTags is called consecutively,
                // causing loss of tags added recently in tag_summary table.
                $prevTags = $dbw->selectField( 'tag_summary', 'ts_tags', $tsConds, __METHOD__ );
index 4f170f3..96ef14f 100644 (file)
@@ -355,11 +355,6 @@ $wgEnableAsyncUploads = false;
  */
 $wgIllegalFileChars = ":";
 
-/**
- * @deprecated since 1.17 use $wgDeletedDirectory
- */
-$wgFileStore = array();
-
 /**
  * What directory to place deleted uploads in.
  * Defaults to "{$wgUploadDirectory}/deleted".
@@ -1217,6 +1212,33 @@ $wgThumbLimits = array(
        300
 );
 
+/**
+ * When defined, is an array of image widths used as buckets for thumbnail generation.
+ * The goal is to save resources by generating thumbnails based on reference buckets instead of
+ * always using the original. This will incur a speed gain but cause a quality loss.
+ *
+ * The buckets generation is chained, with each bucket generated based on the above bucket
+ * when possible. File handlers have to opt into using that feature. For now only BitmapHandler
+ * supports it.
+ */
+$wgThumbnailBuckets = null;
+
+/**
+ * When using thumbnail buckets as defined above, this sets the minimum distance with the bucket
+ * above the requested size. The distance represents how pany extra pixels of width the bucket needs
+ * in order to be used as the reference for a given thumbnail. For example, with the following buckets:
+ *
+ * $wgThumbnailBuckets = array ( 128, 256, 512 );
+ *
+ * and a distance of 50:
+ *
+ * $wgThumbnailMinimumBucketDistance = 50;
+ *
+ * If we want to render a thumbnail of width 220px, the 512px bucket will be used,
+ * because 220 + 50 = 270 and the closest bucket bigger than 270px is 512.
+ */
+$wgThumbnailMinimumBucketDistance = 0;
+
 /**
  * Default parameters for the "<gallery>" tag
  */
@@ -1514,7 +1536,7 @@ $wgUsersNotifiedOnAllChanges = array();
 $wgDBserver = 'localhost';
 
 /**
- * Database port number (for PostgreSQL)
+ * Database port number (for PostgreSQL and Microsoft SQL Server).
  */
 $wgDBport = 5432;
 
@@ -1540,11 +1562,21 @@ $wgDBtype = 'mysql';
 
 /**
  * Whether to use SSL in DB connection.
+ *
+ * This setting is only used $wgLBFactoryConf['class'] is set to
+ * 'LBFactorySimple' and $wgDBservers is an empty array; otherwise
+ * the DBO_SSL flag must be set in the 'flags' option of the database
+ * connection to achieve the same functionality.
  */
 $wgDBssl = false;
 
 /**
  * Whether to use compression in DB connection.
+ *
+ * This setting is only used $wgLBFactoryConf['class'] is set to
+ * 'LBFactorySimple' and $wgDBservers is an empty array; otherwise
+ * the DBO_COMPRESS flag must be set in the 'flags' option of the database
+ * connection to achieve the same functionality.
  */
 $wgDBcompress = false;
 
@@ -1652,7 +1684,7 @@ $wgSharedTables = array( 'user', 'user_properties' );
  *   - dbname:      Default database name
  *   - user:        DB user
  *   - password:    DB password
- *   - type:        "mysql" or "postgres"
+ *   - type:        DB type
  *
  *   - load:        Ratio of DB_SLAVE load, must be >=0, the sum of all loads must be >0.
  *                  If this is zero for any given server, no normal query traffic will be
@@ -2153,6 +2185,12 @@ $wgCachePages = true;
  */
 $wgCacheEpoch = '20030516000000';
 
+/**
+ * Directory where GitInfo will look for pre-computed cache files. If false,
+ * $wgCacheDirectory/gitinfo will be used.
+ */
+$wgGitInfoCacheDirectory = false;
+
 /**
  * Bump this number when changing the global style sheets and JavaScript.
  *
@@ -4354,7 +4392,7 @@ $wgGroupPermissions['sysop']['unblockself'] = true;
 $wgGroupPermissions['sysop']['suppressredirect'] = true;
 #$wgGroupPermissions['sysop']['pagelang'] = true;
 #$wgGroupPermissions['sysop']['upload_by_url'] = true;
-#$wgGroupPermissions['sysop']['mergehistory'] = true;
+$wgGroupPermissions['sysop']['mergehistory'] = true;
 
 // Permission to change users' group assignments
 $wgGroupPermissions['bureaucrat']['userrights'] = true;
@@ -4971,7 +5009,12 @@ $wgDebugComments = false;
 $wgDebugDBTransactions = false;
 
 /**
- * Write SQL queries to the debug log
+ * Write SQL queries to the debug log.
+ *
+ * This setting is only used $wgLBFactoryConf['class'] is set to
+ * 'LBFactorySimple' and $wgDBservers is an empty array; otherwise
+ * the DBO_DEBUG flag must be set in the 'flags' option of the database
+ * connection to achieve the same functionality.
  */
 $wgDebugDumpSql = false;
 
@@ -5263,18 +5306,6 @@ $wgAdvancedSearchHighlighting = false;
  */
 $wgSearchHighlightBoundaries = '[\p{Z}\p{P}\p{C}]';
 
-/**
- * Set to true to have the search engine count total
- * search matches to present in the Special:Search UI.
- * Not supported by every search engine shipped with MW.
- *
- * This could however be slow on larger wikis, and is pretty flaky
- * with the current title vs content split. Recommend avoiding until
- * that's been worked out cleanly; but this may aid in testing the
- * search UI and API to confirm that the result count works.
- */
-$wgCountTotalSearchHits = false;
-
 /**
  * Template for OpenSearch suggestions, defaults to API action=opensearch
  *
@@ -5586,9 +5617,11 @@ $wgRC2UDPOmitBots = false;
  * Destinations to which notifications about recent changes
  * should be sent.
  *
- * As of MediaWiki 1.22, the only supported 'engine' parameter option in core
- * is 'UDPRCFeedEngine', which is used to send recent changes over UDP to the
- * specified server.
+ * As of MediaWiki 1.22, there are 2 supported 'engine' parameter option in core:
+ *   * 'UDPRCFeedEngine', which is used to send recent changes over UDP to the
+ *      specified server.
+ *   * 'RedisPubSubFeedEngine', which is used to send recent changes to Redis.
+ *
  * The common options are:
  *   * 'uri' -- the address to which the notices are to be sent.
  *   * 'formatter' -- the class name (implementing RCFeedFormatter) which will
@@ -5598,10 +5631,12 @@ $wgRC2UDPOmitBots = false;
  *   * 'omit_user' -- whether edits by registered users should be in the feed
  *   * 'omit_minor' -- whether minor edits should be in the feed
  *   * 'omit_patrolled' -- whether patrolled edits should be in the feed
+ *
  *  The IRC-specific options are:
  *   * 'add_interwiki_prefix' -- whether the titles should be prefixed with
  *     the first entry in the $wgLocalInterwikis array (or the value of
  *     $wgLocalInterwiki, if set)
+ *
  *  The JSON-specific options are:
  *   * 'channel' -- if set, the 'channel' parameter is also set in JSON values.
  *
index 03e50fc..3d57e95 100644 (file)
@@ -3839,46 +3839,34 @@ HTML
        public function getEditButtons( &$tabindex ) {
                $buttons = array();
 
-               // @todo FIXME: Hardcoded square brackets.
-               $temp = array(
+               $attribs = array(
                        'id' => 'wpSave',
                        'name' => 'wpSave',
                        'type' => 'submit',
                        'tabindex' => ++$tabindex,
                        'value' => wfMessage( 'savearticle' )->text(),
-                       'accesskey' => wfMessage( 'accesskey-save' )->text(),
-                       'title' => wfMessage( 'tooltip-save' )->text()
-                               . ' [' . wfMessage( 'accesskey-save' )->text() . ']',
-               );
-               $buttons['save'] = Xml::element( 'input', $temp, '' );
+               ) + Linker::tooltipAndAccesskeyAttribs( 'save' );
+               $buttons['save'] = Xml::element( 'input', $attribs, '' );
 
                ++$tabindex; // use the same for preview and live preview
-               // @todo FIXME: Hardcoded square brackets.
-               $temp = array(
+               $attribs = array(
                        'id' => 'wpPreview',
                        'name' => 'wpPreview',
                        'type' => 'submit',
                        'tabindex' => $tabindex,
                        'value' => wfMessage( 'showpreview' )->text(),
-                       'accesskey' => wfMessage( 'accesskey-preview' )->text(),
-                       'title' => wfMessage( 'tooltip-preview' )->text()
-                               . ' [' . wfMessage( 'accesskey-preview' )->text() . ']',
-               );
-               $buttons['preview'] = Xml::element( 'input', $temp, '' );
+               ) + Linker::tooltipAndAccesskeyAttribs( 'preview' );
+               $buttons['preview'] = Xml::element( 'input', $attribs, '' );
                $buttons['live'] = '';
 
-               // @todo FIXME: Hardcoded square brackets.
-               $temp = array(
+               $attribs = array(
                        'id' => 'wpDiff',
                        'name' => 'wpDiff',
                        'type' => 'submit',
                        'tabindex' => ++$tabindex,
                        'value' => wfMessage( 'showdiff' )->text(),
-                       'accesskey' => wfMessage( 'accesskey-diff' )->text(),
-                       'title' => wfMessage( 'tooltip-diff' )->text()
-                               . ' [' . wfMessage( 'accesskey-diff' )->text() . ']',
-               );
-               $buttons['diff'] = Xml::element( 'input', $temp, '' );
+               ) + Linker::tooltipAndAccesskeyAttribs( 'diff' );
+               $buttons['diff'] = Xml::element( 'input', $attribs, '' );
 
                wfRunHooks( 'EditPageBeforeEditButtons', array( &$this, &$buttons, &$tabindex ) );
                return $buttons;
index 304c1bc..acf1bf6 100644 (file)
@@ -57,6 +57,9 @@ class GitInfo {
         */
        public function __construct( $repoDir, $usePrecomputed = true ) {
                $this->cacheFile = self::getCacheFilePath( $repoDir );
+               wfDebugLog( 'gitinfo',
+                       "Computed cacheFile={$this->cacheFile} for {$repoDir}"
+               );
                if ( $usePrecomputed &&
                        $this->cacheFile !== null &&
                        is_readable( $this->cacheFile )
@@ -65,9 +68,11 @@ class GitInfo {
                                file_get_contents( $this->cacheFile ),
                                true
                        );
+                       wfDebugLog( 'gitinfo', "Loaded git data from cache for {$repoDir}" );
                }
 
                if ( !$this->cacheIsComplete() ) {
+                       wfDebugLog( 'gitinfo', "Cache incomplete for {$repoDir}" );
                        $this->basedir = $repoDir . DIRECTORY_SEPARATOR . '.git';
                        if ( is_readable( $this->basedir ) && !is_dir( $this->basedir ) ) {
                                $GITfile = file_get_contents( $this->basedir );
@@ -90,24 +95,31 @@ class GitInfo {
         * Compute the path to the cache file for a given directory.
         *
         * @param string $repoDir The root directory of the repo where .git can be found
-        * @return string Path to GitInfo cache file in $wgCacheDirectory or null if
-        * $wgCacheDirectory is false (cache disabled).
+        * @return string Path to GitInfo cache file in $wgGitInfoCacheDirectory or
+        * null if $wgGitInfoCacheDirectory is false (cache disabled).
+        * @since 1.24
         */
        protected static function getCacheFilePath( $repoDir ) {
-               global $IP, $wgCacheDirectory;
-               if ( $wgCacheDirectory ) {
-                       // Transform path to git repo to something we can safely embed in a filename
-                       $repoName = $repoDir;
-                       if ( strpos( $repoName, $IP ) === 0 ) {
+               global $IP, $wgGitInfoCacheDirectory;
+
+               if ( $wgGitInfoCacheDirectory ) {
+                       // Convert both $IP and $repoDir to canonical paths to protect against
+                       // $IP having changed between the settings files and runtime.
+                       $realIP = realpath( $IP );
+                       $repoName = realpath( $repoDir );
+                       if ( $repoName === false ) {
+                               // Unit tests use fake path names
+                               $repoName = $repoDir;
+                       }
+                       if ( strpos( $repoName, $realIP ) === 0 ) {
                                // Strip $IP from path
-                               $repoName = substr( $repoName, strlen( $IP ) );
+                               $repoName = substr( $repoName, strlen( $realIP ) );
                        }
+                       // Transform path to git repo to something we can safely embed in
+                       // a filename
                        $repoName = strtr( $repoName, DIRECTORY_SEPARATOR, '-' );
                        $fileName = 'info' . $repoName . '.json';
-                       return implode(
-                               DIRECTORY_SEPARATOR,
-                               array( $wgCacheDirectory, 'gitinfo', $fileName )
-                       );
+                       return "{$wgGitInfoCacheDirectory}/{$fileName}";
                }
                return null;
        }
@@ -330,7 +342,9 @@ class GitInfo {
                        $this->getRemoteUrl();
 
                        if ( !$this->cacheIsComplete() ) {
-                               wfDebugLog( "Failed to compute GitInfo for \"{$this->basedir}\"" );
+                               wfDebugLog( 'gitinfo',
+                                       "Failed to compute GitInfo for \"{$this->basedir}\""
+                               );
                                return;
                        }
 
index c1908af..cb5b7fd 100644 (file)
@@ -2580,10 +2580,12 @@ function wfIsHHVM() {
 /**
  * Swap two variables
  *
+ * @deprecated since 1.24
  * @param mixed $x
  * @param mixed $y
  */
 function swap( &$x, &$y ) {
+       wfDeprecated( __FUNCTION__, '1.24' );
        $z = $x;
        $x = $y;
        $y = $z;
index 89457e8..77486b2 100644 (file)
@@ -48,7 +48,7 @@ class Hooks {
         * Attach an event handler to a given hook.
         *
         * @param string $name Name of hook
-        * @param mixed $callback Callback function to attach
+        * @param callable $callback Callback function to attach
         *
         * @since 1.18
         */
index 5262ffe..5f4655c 100644 (file)
@@ -386,7 +386,7 @@ class Html {
         * For instance, it will omit quotation marks if $wgWellFormedXml is false,
         * and will treat boolean attributes specially.
         *
-        * Attributes that should contain space-separated lists (such as 'class') array
+        * Attributes that can contain space-separated lists ('class', 'accesskey' and 'rel') array
         * values are allowed as well, which will automagically be normalized
         * and converted to a space-separated string. In addition to a numerical
         * array, the attribute value may also be an associative array. See the
@@ -413,6 +413,8 @@ class Html {
         *   A value of false means to omit the attribute.  For boolean attributes,
         *   you can omit the key, e.g., array( 'checked' ) instead of
         *   array( 'checked' => 'checked' ) or such.
+        *
+        * @throws MWException if an attribute that doesn't allow lists is set to an array
         * @return string HTML fragment that goes between element name and '>'
         *   (starting with a space if at least one attribute is output)
         */
@@ -500,6 +502,8 @@ class Html {
 
                                // Remove duplicates and create the string
                                $value = implode( ' ', array_unique( $value ) );
+                       } else if ( is_array( $value ) ) {
+                               throw new MWException( "HTML attribute $key can not contain a list of values" );
                        }
 
                        // See the "Attributes" section in the HTML syntax part of HTML5,
index 447dde3..ad3228d 100644 (file)
@@ -268,7 +268,7 @@ class MWTimestamp {
                // first value.
                if ( $data[0] == 'System' ) {
                        // First value is System, so use the system offset.
-                       if ( isset( $wgLocalTZoffset ) ) {
+                       if ( $wgLocalTZoffset !== null ) {
                                $diff = $wgLocalTZoffset;
                        }
                } elseif ( $data[0] == 'Offset' ) {
index 826d55b..950bcd5 100644 (file)
@@ -995,7 +995,7 @@ class Message {
         * @throws MWException If message key array is empty.
         */
        protected function fetchMessage() {
-               if ( !isset( $this->message ) ) {
+               if ( $this->message === null ) {
                        $cache = MessageCache::singleton();
                        if ( is_array( $this->key ) ) {
                                if ( !count( $this->key ) ) {
@@ -1054,7 +1054,7 @@ class RawMessage extends Message {
         */
        public function fetchMessage() {
                // Just in case the message is unset somewhere.
-               if ( !isset( $this->message ) ) {
+               if ( $this->message === null ) {
                        $this->message = $this->key;
                }
                return $this->message;
index f4d4697..b4d3ab1 100644 (file)
@@ -164,6 +164,14 @@ class MimeMagic {
         */
        protected $mIEAnalyzer;
 
+       /** @var string Extra MIME types, set for example by media handling extensions
+        */
+       private $mExtraTypes = '';
+
+       /** @var string Extra MIME info, set for example by media handling extensions
+        */
+       private $mExtraInfo = '';
+
        /** @var MimeMagic The singleton instance
         */
        private static $instance = null;
@@ -179,6 +187,9 @@ class MimeMagic {
 
                global $wgMimeTypeFile, $IP;
 
+               # Allow media handling extensions adding MIME-types and MIME-info
+               wfRunHooks( 'MimeMagicInit', array( $this ) );
+
                $types = MM_WELL_KNOWN_MIME_TYPES;
 
                if ( $wgMimeTypeFile == 'includes/mime.types' ) {
@@ -197,11 +208,13 @@ class MimeMagic {
                        wfDebug( __METHOD__ . ": no mime types file defined, using build-ins only.\n" );
                }
 
+               $types .= "\n" . $this->mExtraTypes;
+
                $types = str_replace( array( "\r\n", "\n\r", "\n\n", "\r\r", "\r" ), "\n", $types );
                $types = str_replace( "\t", " ", $types );
 
                $this->mMimeToExt = array();
-               $this->mToMime = array();
+               $this->mExtToMime = array();
 
                $lines = explode( "\n", $types );
                foreach ( $lines as $s ) {
@@ -272,6 +285,8 @@ class MimeMagic {
                        wfDebug( __METHOD__ . ": no mime info file defined, using build-ins only.\n" );
                }
 
+               $info .= "\n" . $this->mExtraInfo;
+
                $info = str_replace( array( "\r\n", "\n\r", "\n\n", "\r\r", "\r" ), "\n", $info );
                $info = str_replace( "\t", " ", $info );
 
@@ -342,6 +357,26 @@ class MimeMagic {
                return self::$instance;
        }
 
+       /**
+        * Adds to the list mapping MIME to file extensions.
+        * As an extension author, you are encouraged to submit patches to
+        * MediaWiki's core to add new MIME types to mime.types.
+        * @param string $types
+        */
+       public function addExtraTypes( $types ) {
+               $this->mExtraTypes .= "\n" . $types;
+       }
+
+       /**
+        * Adds to the list mapping MIME to media type.
+        * As an extension author, you are encouraged to submit patches to
+        * MediaWiki's core to add new MIME info to mime.info.
+        * @param string $info
+        */
+       public function addExtraInfo( $info ) {
+               $this->mExtraInfo .= "\n" . $info;
+       }
+
        /**
         * Returns a list of file extensions for a given mime type as a space
         * separated string or null if the mime type was unrecognized. Resolves
@@ -485,14 +520,6 @@ class MimeMagic {
         * by looking at the file extension. Typically, this method would be called on the
         * result of guessMimeType().
         *
-        * Currently, this method does the following:
-        *
-        * If $mime is "unknown/unknown" and isRecognizableExtension( $ext ) returns false,
-        * return the result of guessTypesForExtension($ext).
-        *
-        * If $mime is "application/x-opc+zip" and isMatchingExtension( $ext, $mime )
-        * gives true, return the result of guessTypesForExtension($ext).
-        *
         * @param string $mime The mime type, typically guessed from a file's content.
         * @param string $ext The file extension, as taken from the file name
         *
@@ -518,8 +545,17 @@ class MimeMagic {
                                        ".$ext is not a known OPC extension.\n" );
                                $mime = 'application/zip';
                        }
+               } elseif ( $mime === 'text/plain' && $this->findMediaType( ".$ext" ) === MEDIATYPE_TEXT ) {
+                       // Textual types are sometimes not recognized properly.
+                       // If detected as text/plain, and has an extension which is textual
+                       // improve to the extension's type. For example, csv and json are often
+                       // misdetected as text/plain.
+                       $mime = $this->guessTypesForExtension( $ext );
                }
 
+               # Media handling extensions can improve the MIME detected
+               wfRunHooks( 'MimeMagicImproveFromExtension', array( $this, $ext, &$mime ) );
+
                if ( isset( $this->mMimeTypeAliases[$mime] ) ) {
                        $mime = $this->mMimeTypeAliases[$mime];
                }
@@ -746,7 +782,17 @@ class MimeMagic {
                        return 'image/vnd.djvu';
                }
 
-               return false;
+               # Media handling extensions can guess the MIME by content
+               # It's intentionally here so that if core is wrong about a type (false positive),
+               # people will hopefully nag and submit patches :)
+               $mime = false;
+               # Some strings by reference for performance - assuming well-behaved hooks
+               wfRunHooks(
+                       'MimeMagicGuessFromContent',
+                       array( $this, &$head, &$tail, $file, &$mime )
+               );
+
+               return $mime;
        }
 
        /**
@@ -994,7 +1040,7 @@ class MimeMagic {
                        $head = fread( $f, 256 );
                        fclose( $f );
 
-                       $head = strtolower( $head );
+                       $head = str_replace( 'ffmpeg2theora', '', strtolower( $head ) );
 
                        // This is an UGLY HACK, file should be parsed correctly
                        if ( strpos( $head, 'theora' ) !== false ) {
index 4edddbc..392f558 100644 (file)
@@ -88,16 +88,6 @@ class MWNamespace {
                return !self::isTalk( $index );
        }
 
-       /**
-        * @see self::isSubject
-        * @deprecated since 1.19 Please use the more consistently named isSubject
-        * @return bool
-        */
-       public static function isMain( $index ) {
-               wfDeprecated( __METHOD__, '1.19' );
-               return self::isSubject( $index );
-       }
-
        /**
         * Is the given namespace a talk namespace?
         *
index 2a96891..8967938 100644 (file)
@@ -885,10 +885,7 @@ class OutputPage extends ContextSource {
         * @return string
         */
        public function getPageTitleActionText() {
-               if ( isset( $this->mPageTitleActionText ) ) {
-                       return $this->mPageTitleActionText;
-               }
-               return '';
+               return $this->mPageTitleActionText;
        }
 
        /**
@@ -1345,18 +1342,6 @@ class OutputPage extends ContextSource {
                );
        }
 
-       /**
-        * Return whether user JavaScript is allowed for this page
-        * @deprecated since 1.18 Load modules with ResourceLoader, and origin and
-        *     trustworthiness is identified and enforced automagically.
-        * @return bool
-        */
-       public function isUserJsAllowed() {
-               wfDeprecated( __METHOD__, '1.18' );
-               return $this->getAllowedModules( ResourceLoaderModule::TYPE_SCRIPTS ) >=
-                       ResourceLoaderModule::ORIGIN_USER_INDIVIDUAL;
-       }
-
        /**
         * Show what level of JavaScript / CSS untrustworthiness is allowed on this page
         * @see ResourceLoaderModule::$origin
@@ -2069,19 +2054,6 @@ class OutputPage extends ContextSource {
                }
        }
 
-       /**
-        * Get the message associated with the HTTP response code $code
-        *
-        * @param int $code Status code
-        * @return string|null Message or null if $code is not in the list of messages
-        *
-        * @deprecated since 1.18 Use HttpStatus::getMessage() instead.
-        */
-       public static function getStatusMessage( $code ) {
-               wfDeprecated( __METHOD__, '1.18' );
-               return HttpStatus::getMessage( $code );
-       }
-
        /**
         * Finally, all the text has been munged and accumulated into
         * the object, let's actually output it:
@@ -3112,16 +3084,13 @@ $templates
        /**
         * Get an array containing the variables to be set in mw.config in JavaScript.
         *
-        * DO NOT CALL THIS FROM OUTSIDE OF THIS CLASS OR Skin::makeGlobalVariablesScript().
-        * This is only public until that function is removed. You have been warned.
-        *
         * Do not add things here which can be evaluated in ResourceLoaderStartUpModule
         * - in other words, page-independent/site-wide variables (without state).
         * You will only be adding bloat to the html page and causing page caches to
         * have to be purged on configuration changes.
         * @return array
         */
-       public function getJSVars() {
+       private function getJSVars() {
                global $wgContLang;
 
                $curRevisionId = 0;
index 0fb3952..0f5a6fc 100644 (file)
@@ -32,6 +32,7 @@
  *   - index.php
  *   - load.php
  *   - api.php
+ *   - mw-config/index.php
  *   - cli
  *
  * @note Since we can't rely on anything, the minimum PHP versions and MW current
@@ -41,7 +42,7 @@ function wfPHPVersionError( $type ) {
        $mwVersion = '1.24';
        $minimumVersionPHP = '5.3.2';
 
-       $phpVersion = phpversion();
+       $phpVersion = PHP_VERSION;
        $protocol = isset( $_SERVER['SERVER_PROTOCOL'] ) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0';
        $message = "MediaWiki $mwVersion requires at least "
                . "PHP version $minimumVersionPHP, you are using PHP $phpVersion.";
@@ -50,10 +51,15 @@ function wfPHPVersionError( $type ) {
                $finalOutput = "You are using PHP version $phpVersion "
                        . "but MediaWiki $mwVersion needs PHP $minimumVersionPHP or higher. ABORTING.\n"
                        . "Check if you have a newer php executable with a different name, such as php5.\n";
-       } elseif ( $type == 'index.php' ) {
+       } elseif ( $type == 'index.php' || $type == 'mw-config/index.php' ) {
                $pathinfo = pathinfo( $_SERVER['SCRIPT_NAME'] );
+               if ( $type == 'mw-config/index.php' ) {
+                       $dirname = dirname( $pathinfo['dirname'] );
+               } else {
+                       $dirname = $pathinfo['dirname'];
+               }
                $encLogo = htmlspecialchars(
-                       str_replace( '//', '/', $pathinfo['dirname'] . '/' ) .
+                       str_replace( '//', '/', $dirname . '/' ) .
                        'skins/common/images/mediawiki.png'
                );
 
index 081315e..fdb1a9d 100644 (file)
@@ -98,6 +98,20 @@ class Preferences {
 
                wfRunHooks( 'GetPreferences', array( $user, &$defaultPreferences ) );
 
+               self::loadPreferenceValues( $user, $context, $defaultPreferences );
+               self::$defaultPreferences = $defaultPreferences;
+               return $defaultPreferences;
+       }
+
+       /**
+        * Loads existing values for a given array of preferences
+        * @throws MWException
+        * @param User $user
+        * @param IContextSource $context
+        * @param array defaultPreferences to load values for
+        * @return array|null
+        */
+       static function loadPreferenceValues( $user, $context, &$defaultPreferences ) {
                ## Remove preferences that wikis don't want to use
                global $wgHiddenPrefs;
                foreach ( $wgHiddenPrefs as $pref ) {
@@ -138,8 +152,6 @@ class Preferences {
                        }
                }
 
-               self::$defaultPreferences = $defaultPreferences;
-
                return $defaultPreferences;
        }
 
@@ -1463,27 +1475,6 @@ class Preferences {
                        return array( $result, 'mailerror' );
                }
        }
-
-       /**
-        * @deprecated since 1.19
-        * @param User $user
-        * @return array
-        */
-       public static function loadOldSearchNs( $user ) {
-               wfDeprecated( __METHOD__, '1.19' );
-
-               $searchableNamespaces = SearchEngine::searchableNamespaces();
-               // Back compat with old format
-               $arr = array();
-
-               foreach ( $searchableNamespaces as $ns => $name ) {
-                       if ( $user->getOption( 'searchNs' . $ns ) ) {
-                               $arr[] = $ns;
-                       }
-               }
-
-               return $arr;
-       }
 }
 
 /** Some tweaks to allow js prefs to work */
index 06f5bd0..de69827 100644 (file)
@@ -41,6 +41,11 @@ class Revision implements IDBAccessObject {
        protected $mParentId;
        protected $mComment;
        protected $mText;
+       protected $mTextId;
+
+       /**
+        * @var stdClass|null
+        */
        protected $mTextRow;
 
        /**
@@ -299,7 +304,7 @@ class Revision implements IDBAccessObject {
        private static function newFromConds( $conditions, $flags = 0 ) {
                $db = wfGetDB( ( $flags & self::READ_LATEST ) ? DB_MASTER : DB_SLAVE );
                $rev = self::loadFromConds( $db, $conditions, $flags );
-               if ( is_null( $rev ) && wfGetLB()->getServerCount() > 1 ) {
+               if ( $rev === null && wfGetLB()->getServerCount() > 1 ) {
                        if ( !( $flags & self::READ_LATEST ) ) {
                                $dbw = wfGetDB( DB_MASTER );
                                $rev = self::loadFromConds( $dbw, $conditions, $flags );
@@ -566,13 +571,13 @@ class Revision implements IDBAccessObject {
                                $this->mTitle = null;
                        }
 
-                       if ( !isset( $row->rev_content_model ) || is_null( $row->rev_content_model ) ) {
+                       if ( !isset( $row->rev_content_model ) ) {
                                $this->mContentModel = null; # determine on demand if needed
                        } else {
                                $this->mContentModel = strval( $row->rev_content_model );
                        }
 
-                       if ( !isset( $row->rev_content_format ) || is_null( $row->rev_content_format ) ) {
+                       if ( !isset( $row->rev_content_format ) ) {
                                $this->mContentFormat = null; # determine on demand if needed
                        } else {
                                $this->mContentFormat = strval( $row->rev_content_format );
@@ -652,7 +657,7 @@ class Revision implements IDBAccessObject {
                                $this->mContentHandler = null;
 
                                $this->mText = $handler->serializeContent( $row['content'], $this->getContentFormat() );
-                       } elseif ( !is_null( $this->mText ) ) {
+                       } elseif ( $this->mText !== null ) {
                                $handler = $this->getContentHandler();
                                $this->mContent = $handler->unserializeContent( $this->mText );
                        }
@@ -674,7 +679,7 @@ class Revision implements IDBAccessObject {
 
                        // If we still have no length, see it we have the text to figure it out
                        if ( !$this->mSize ) {
-                               if ( !is_null( $this->mContent ) ) {
+                               if ( $this->mContent !== null ) {
                                        $this->mSize = $this->mContent->getSize();
                                } else {
                                        #NOTE: this should never happen if we have either text or content object!
@@ -684,7 +689,7 @@ class Revision implements IDBAccessObject {
 
                        // Same for sha1
                        if ( $this->mSha1 === null ) {
-                               $this->mSha1 = is_null( $this->mText ) ? null : self::base36Sha1( $this->mText );
+                               $this->mSha1 = $this->mText === null ? null : self::base36Sha1( $this->mText );
                        }
 
                        // force lazy init
@@ -759,11 +764,11 @@ class Revision implements IDBAccessObject {
         * @return Title|null
         */
        public function getTitle() {
-               if ( isset( $this->mTitle ) ) {
+               if ( $this->mTitle !== null ) {
                        return $this->mTitle;
                }
                //rev_id is defined as NOT NULL, but this revision may not yet have been inserted.
-               if ( !is_null( $this->mId ) ) {
+               if ( $this->mId !== null ) {
                        $dbr = wfGetDB( DB_SLAVE );
                        $row = $dbr->selectRow(
                                array( 'page', 'revision' ),
@@ -776,7 +781,7 @@ class Revision implements IDBAccessObject {
                        }
                }
 
-               if ( !$this->mTitle && !is_null( $this->mPage ) && $this->mPage > 0 ) {
+               if ( !$this->mTitle && $this->mPage !== null && $this->mPage > 0 ) {
                        $this->mTitle = Title::newFromID( $this->mPage );
                }
 
@@ -1031,7 +1036,7 @@ class Revision implements IDBAccessObject {
         * @return string
         */
        public function getSerializedData() {
-               if ( is_null( $this->mText ) ) {
+               if ( $this->mText === null ) {
                        $this->mText = $this->loadText();
                }
 
@@ -1048,9 +1053,9 @@ class Revision implements IDBAccessObject {
         * @return Content|null The Revision's content, or null on failure.
         */
        protected function getContentInternal() {
-               if ( is_null( $this->mContent ) ) {
+               if ( $this->mContent === null ) {
                        // Revision is immutable. Load on demand:
-                       if ( is_null( $this->mText ) ) {
+                       if ( $this->mText === null ) {
                                $this->mText = $this->loadText();
                        }
 
@@ -1184,7 +1189,7 @@ class Revision implements IDBAccessObject {
         * @return int
         */
        private function getPreviousRevisionId( $db ) {
-               if ( is_null( $this->mPage ) ) {
+               if ( $this->mPage === null ) {
                        return 0;
                }
                # Use page_latest if ID is not given
@@ -1355,7 +1360,7 @@ class Revision implements IDBAccessObject {
                }
 
                # Record the text (or external storage URL) to the text table
-               if ( !isset( $this->mTextId ) ) {
+               if ( $this->mTextId === null ) {
                        $old_id = $dbw->nextSequenceValue( 'text_old_id_seq' );
                        $dbw->insert( 'text',
                                array(
@@ -1372,7 +1377,7 @@ class Revision implements IDBAccessObject {
                }
 
                # Record the edit in revisions
-               $rev_id = isset( $this->mId )
+               $rev_id = $this->mId !== null
                        ? $this->mId
                        : $dbw->nextSequenceValue( 'revision_rev_id_seq' );
                $row = array(
@@ -1386,10 +1391,10 @@ class Revision implements IDBAccessObject {
                        'rev_timestamp'  => $dbw->timestamp( $this->mTimestamp ),
                        'rev_deleted'    => $this->mDeleted,
                        'rev_len'        => $this->mSize,
-                       'rev_parent_id'  => is_null( $this->mParentId )
+                       'rev_parent_id'  => $this->mParentId === null
                                ? $this->getPreviousRevisionId( $dbw )
                                : $this->mParentId,
-                       'rev_sha1'       => is_null( $this->mSha1 )
+                       'rev_sha1'       => $this->mSha1 === null
                                ? Revision::base36Sha1( $this->mText )
                                : $this->mSha1,
                );
@@ -1419,7 +1424,7 @@ class Revision implements IDBAccessObject {
 
                $dbw->insert( 'revision', $row, __METHOD__ );
 
-               $this->mId = !is_null( $rev_id ) ? $rev_id : $dbw->insertId();
+               $this->mId = $rev_id !== null ? $rev_id : $dbw->insertId();
 
                wfRunHooks( 'RevisionInsertComplete', array( &$this, $data, $flags ) );
 
@@ -1508,7 +1513,7 @@ class Revision implements IDBAccessObject {
                }
 
                // If we kept data for lazy extraction, use it now...
-               if ( isset( $this->mTextRow ) ) {
+               if ( $this->mTextRow !== null ) {
                        $row = $this->mTextRow;
                        $this->mTextRow = null;
                } else {
index 6a568c2..ec17a08 100644 (file)
@@ -383,7 +383,7 @@ class Sanitizer {
                                'h2', 'h3', 'h4', 'h5', 'h6', 'cite', 'code', 'em', 's',
                                'strike', 'strong', 'tt', 'var', 'div', 'center',
                                'blockquote', 'ol', 'ul', 'dl', 'table', 'caption', 'pre',
-                               'ruby', 'rt', 'rb', 'rp', 'p', 'span', 'abbr', 'dfn',
+                               'ruby', 'rb', 'rp', 'rt', 'rtc', 'p', 'span', 'abbr', 'dfn',
                                'kbd', 'samp', 'data', 'time', 'mark'
                        );
                        $htmlsingle = array(
@@ -1685,10 +1685,10 @@ class Sanitizer {
                        # http://www.whatwg.org/html/text-level-semantics.html#the-ruby-element
                        'ruby'       => $common,
                        # rbc
-                       # rtc
                        'rb'         => $common,
-                       'rt'         => $common, #array_merge( $common, array( 'rbspan' ) ),
                        'rp'         => $common,
+                       'rt'         => $common, #array_merge( $common, array( 'rbspan' ) ),
+                       'rtc'         => $common,
 
                        # MathML root element, where used for extensions
                        # 'title' may not be 100% valid here; it's XHTML
index 783ef3f..38a16c5 100644 (file)
@@ -78,6 +78,14 @@ if ( $wgExtensionAssetsPath === false ) {
        $wgExtensionAssetsPath = "$wgScriptPath/extensions";
 }
 
+// Enable default skins. Temporary, to be removed before 1.24 release.
+// This is hacky and bad, the require_once calls should eventually be generated by the installer
+// and placed in LocalSettings.php.
+// While this is in Setup.php, it needs to be done as soon as possible, as some of the setup code
+// depends on all extensions and skins being already required (bug 67318).
+require_once "$wgStyleDirectory/MonoBook/MonoBook.php";
+require_once "$wgStyleDirectory/Vector/Vector.php";
+
 if ( $wgLogo === false ) {
        $wgLogo = "$wgStylePath/common/images/wiki.png";
 }
@@ -98,15 +106,15 @@ if ( $wgDeletedDirectory === false ) {
        $wgDeletedDirectory = "{$wgUploadDirectory}/deleted";
 }
 
-if ( isset( $wgFileStore['deleted']['directory'] ) ) {
-       $wgDeletedDirectory = $wgFileStore['deleted']['directory'];
+if ( $wgGitInfoCacheDirectory === false && $wgCacheDirectory !== false ) {
+       $wgGitInfoCacheDirectory = "{$wgCacheDirectory}/gitinfo";
 }
 
 if ( isset( $wgFooterIcons['copyright'] )
        && isset( $wgFooterIcons['copyright']['copyright'] )
        && $wgFooterIcons['copyright']['copyright'] === array()
 ) {
-       if ( isset( $wgCopyrightIcon ) && $wgCopyrightIcon ) {
+       if ( $wgCopyrightIcon ) {
                $wgFooterIcons['copyright']['copyright'] = $wgCopyrightIcon;
        } elseif ( $wgRightsIcon || $wgRightsText ) {
                $wgFooterIcons['copyright']['copyright'] = array(
@@ -161,11 +169,7 @@ $wgLockManagers[] = array(
  * Initialise $wgLocalFileRepo from backwards-compatible settings
  */
 if ( !$wgLocalFileRepo ) {
-       if ( isset( $wgFileStore['deleted']['hash'] ) ) {
-               $deletedHashLevel = $wgFileStore['deleted']['hash'];
-       } else {
-               $deletedHashLevel = $wgHashedUploadDirectory ? 3 : 0;
-       }
+       $deletedHashLevel = $wgHashedUploadDirectory ? 3 : 0;
        $wgLocalFileRepo = array(
                'class' => 'LocalRepo',
                'name' => 'local',
@@ -573,26 +577,33 @@ if ( !defined( 'MW_NO_SESSION' ) && !$wgCommandLineMode &&
 wfProfileOut( $fname . '-session' );
 wfProfileIn( $fname . '-globals' );
 
+/**
+ * @var Language $wgContLang
+ */
 $wgContLang = Language::factory( $wgLanguageCode );
 $wgContLang->initEncoding();
 $wgContLang->initContLang();
 
 // Now that variant lists may be available...
 $wgRequest->interpolateTitle();
+
+/**
+ * @var User $wgUser
+ */
 $wgUser = RequestContext::getMain()->getUser(); // BackCompat
 
 /**
- * @var $wgLang Language
+ * @var Language $wgLang
  */
 $wgLang = new StubUserLang;
 
 /**
- * @var OutputPage
+ * @var OutputPage $wgOut
  */
 $wgOut = RequestContext::getMain()->getOutput(); // BackCompat
 
 /**
- * @var $wgParser Parser
+ * @var Parser $wgParser
  */
 $wgParser = new StubObject( 'wgParser', $wgParserConf['class'], array( $wgParserConf ) );
 
@@ -601,16 +612,32 @@ if ( !is_object( $wgAuth ) ) {
        wfRunHooks( 'AuthPluginSetup', array( &$wgAuth ) );
 }
 
-# Placeholders in case of DB error
+/**
+ * @var Title $wgTitle
+ */
 $wgTitle = null;
 
 $wgDeferredUpdateList = array();
 
-// Enable default skins.
-// This is hacky and bad, the require_once calls should eventually be generated by the installer
-// and placed in LocalSettings.php.
-require_once "$wgStyleDirectory/MonoBook/MonoBook.php";
-require_once "$wgStyleDirectory/Vector/Vector.php";
+// Disable all other email settings automatically if $wgEnableEmail
+// is set to false. - bug 63678
+if ( !$wgEnableEmail ) {
+       $wgAllowHTMLEmail = false;
+       $wgEmailAuthentication = false; // do not require auth if you're not sending email anyway
+       $wgEnableUserEmail = false;
+       $wgEnotifFromEditor = false;
+       $wgEnotifImpersonal = false;
+       $wgEnotifMaxRecips = 0;
+       $wgEnotifMinorEdits = false;
+       $wgEnotifRevealEditorAddress = false;
+       $wgEnotifUseJobQ = false;
+       $wgEnotifUseRealName = false;
+       $wgEnotifUserTalk = false;
+       $wgEnotifWatchlist = false;
+       unset( $wgGroupPermissions['user']['sendemail'] );
+       $wgUserEmailUseReplyTo = false;
+       $wgUsersNotifiedOnAllChanges = array();
+}
 
 wfProfileOut( $fname . '-globals' );
 wfProfileIn( $fname . '-extensions' );
index b99840f..b877544 100644 (file)
@@ -191,7 +191,7 @@ class SiteConfiguration {
         * @param array $params Array of parameters.
         * @return mixed The value of the setting requested.
         */
-       protected function getSetting( $settingName, $wiki, /*array*/ $params ) {
+       protected function getSetting( $settingName, $wiki, array $params ) {
                $retval = null;
                if ( array_key_exists( $settingName, $this->settings ) ) {
                        $thisSetting =& $this->settings[$settingName];
@@ -207,14 +207,14 @@ class SiteConfiguration {
                                // Do tag settings
                                foreach ( $params['tags'] as $tag ) {
                                        if ( array_key_exists( $tag, $thisSetting ) ) {
-                                               if ( isset( $retval ) && is_array( $retval ) && is_array( $thisSetting[$tag] ) ) {
+                                               if ( is_array( $retval ) && is_array( $thisSetting[$tag] ) ) {
                                                        $retval = self::arrayMerge( $retval, $thisSetting[$tag] );
                                                } else {
                                                        $retval = $thisSetting[$tag];
                                                }
                                                break 2;
                                        } elseif ( array_key_exists( "+$tag", $thisSetting ) && is_array( $thisSetting["+$tag"] ) ) {
-                                               if ( !isset( $retval ) ) {
+                                               if ( $retval === null ) {
                                                        $retval = array();
                                                }
                                                $retval = self::arrayMerge( $retval, $thisSetting["+$tag"] );
@@ -224,7 +224,7 @@ class SiteConfiguration {
                                $suffix = $params['suffix'];
                                if ( !is_null( $suffix ) ) {
                                        if ( array_key_exists( $suffix, $thisSetting ) ) {
-                                               if ( isset( $retval ) && is_array( $retval ) && is_array( $thisSetting[$suffix] ) ) {
+                                               if ( is_array( $retval ) && is_array( $thisSetting[$suffix] ) ) {
                                                        $retval = self::arrayMerge( $retval, $thisSetting[$suffix] );
                                                } else {
                                                        $retval = $thisSetting[$suffix];
@@ -233,7 +233,7 @@ class SiteConfiguration {
                                        } elseif ( array_key_exists( "+$suffix", $thisSetting )
                                                && is_array( $thisSetting["+$suffix"] )
                                        ) {
-                                               if ( !isset( $retval ) ) {
+                                               if ( $retval === null ) {
                                                        $retval = array();
                                                }
                                                $retval = self::arrayMerge( $retval, $thisSetting["+$suffix"] );
@@ -450,7 +450,7 @@ class SiteConfiguration {
         * @param array $wikiTags The tags assigned to the wiki.
         * @return array
         */
-       protected function mergeParams( $wiki, $suffix, /*array*/ $params, /*array*/ $wikiTags ) {
+       protected function mergeParams( $wiki, $suffix, array $params, array $wikiTags ) {
                $ret = $this->getWikiParams( $wiki );
 
                if ( is_null( $ret['suffix'] ) ) {
index 177e2b1..bc30eff 100644 (file)
@@ -421,21 +421,6 @@ abstract class Skin extends ContextSource {
                }
        }
 
-       /**
-        * Make a "<script>" tag containing global variables
-        *
-        * @deprecated since 1.19
-        * @param mixed $unused
-        * @return string HTML fragment
-        */
-       public static function makeGlobalVariablesScript( $unused ) {
-               global $wgOut;
-
-               wfDeprecated( __METHOD__, '1.19' );
-
-               return self::makeVariablesScript( $wgOut->getJSVars() );
-       }
-
        /**
         * Get the query to generate a dynamic stylesheet
         *
@@ -875,7 +860,7 @@ abstract class Skin extends ContextSource {
 
                $out = '';
 
-               if ( isset( $wgCopyrightIcon ) && $wgCopyrightIcon ) {
+               if ( $wgCopyrightIcon ) {
                        $out = $wgCopyrightIcon;
                } elseif ( $wgRightsIcon ) {
                        $icon = htmlspecialchars( $wgRightsIcon );
index f9799a5..97c0ec4 100644 (file)
@@ -112,7 +112,6 @@ class SkinTemplate extends Skin {
         * Generates array of language links for the current page
         *
         * @return array
-        * @public
         */
        public function getLanguages() {
                global $wgHideInterlanguageLinks;
@@ -1098,7 +1097,7 @@ class SkinTemplate extends Skin {
                                        /**
                                         * The following actions use messages which, if made particular to
                                         * the any specific skins, would break the Ajax code which makes this
-                                        * action happen entirely inline. Skin::makeGlobalVariablesScript
+                                        * action happen entirely inline. OutputPage::getJSVars
                                         * defines a set of messages in a javascript object - and these
                                         * messages are assumed to be global for all skins. Without making
                                         * a change to that procedure these messages will have to remain as
index 6508bce..fb9b3e4 100644 (file)
@@ -83,9 +83,9 @@ class StubObject {
         * @param object $obj Object to check.
         * @return void
         */
-       static function unstub( $obj ) {
+       static function unstub( &$obj ) {
                if ( $obj instanceof StubObject ) {
-                       $obj->_unstub( 'unstub', 3 );
+                       $obj = $obj->_unstub( 'unstub', 3 );
                }
        }
 
@@ -134,6 +134,7 @@ class StubObject {
         * @param string $name Name of the method called in this object.
         * @param int $level Level to go in the stack trace to get the function
         *   who called this function.
+        * @return The unstubbed version of itself
         * @throws MWException
         */
        function _unstub( $name = '_unstub', $level = 2 ) {
@@ -157,6 +158,7 @@ class StubObject {
                        $GLOBALS[$this->global] = $this->_newObject();
                        --$recursionLevel;
                        wfProfileOut( $fname );
+                       return $GLOBALS[$this->global];
                }
        }
 }
index e038cc7..477373a 100644 (file)
@@ -1371,7 +1371,6 @@ class Title {
         *
         * @param string $name The text
         * @return string The prefixed text
-        * @private
         */
        private function prefix( $name ) {
                $p = '';
@@ -1547,18 +1546,6 @@ class Title {
                return Title::makeTitleSafe( $this->getNamespace(), $this->getText() . '/' . $text );
        }
 
-       /**
-        * Get the HTML-escaped displayable text form.
-        * Used for the title field in <a> tags.
-        *
-        * @return string The text, including any prefixes
-        * @deprecated since 1.19
-        */
-       public function getEscapedText() {
-               wfDeprecated( __METHOD__, '1.19' );
-               return htmlspecialchars( $this->getPrefixedText() );
-       }
-
        /**
         * Get a URL-encoded form of the subpage text
         *
@@ -1776,34 +1763,6 @@ class Title {
                return $ret;
        }
 
-       /**
-        * Get an HTML-escaped version of the URL form, suitable for
-        * using in a link, without a server name or fragment
-        *
-        * @see self::getLocalURL for the arguments.
-        * @param string $query
-        * @param bool|string $query2
-        * @return string The URL
-        * @deprecated since 1.19
-        */
-       public function escapeLocalURL( $query = '', $query2 = false ) {
-               wfDeprecated( __METHOD__, '1.19' );
-               return htmlspecialchars( $this->getLocalURL( $query, $query2 ) );
-       }
-
-       /**
-        * Get an HTML-escaped version of the URL form, suitable for
-        * using in a link, including the server name and fragment
-        *
-        * @see self::getLocalURL for the arguments.
-        * @return string The URL
-        * @deprecated since 1.19
-        */
-       public function escapeFullURL( $query = '', $query2 = false ) {
-               wfDeprecated( __METHOD__, '1.19' );
-               return htmlspecialchars( $this->getFullURL( $query, $query2 ) );
-       }
-
        /**
         * Get the URL form for an internal link.
         * - Used in various Squid-related code, in case we have a different
@@ -1843,19 +1802,6 @@ class Title {
                return $url;
        }
 
-       /**
-        * HTML-escaped version of getCanonicalURL()
-        *
-        * @see self::getLocalURL for the arguments.
-        * @since 1.18
-        * @return string
-        * @deprecated since 1.19
-        */
-       public function escapeCanonicalURL( $query = '', $query2 = false ) {
-               wfDeprecated( __METHOD__, '1.19' );
-               return htmlspecialchars( $this->getCanonicalURL( $query, $query2 ) );
-       }
-
        /**
         * Get the edit URL for this Title
         *
@@ -2569,7 +2515,7 @@ class Title {
                        return false;
                }
 
-               if ( !isset( $this->mTitleProtection ) ) {
+               if ( $this->mTitleProtection === null ) {
                        $dbr = wfGetDB( DB_SLAVE );
                        $res = $dbr->select(
                                'protected_titles',
@@ -2584,30 +2530,6 @@ class Title {
                return $this->mTitleProtection;
        }
 
-       /**
-        * Update the title protection status
-        *
-        * @deprecated since 1.19; use WikiPage::doUpdateRestrictions() instead.
-        * @param string $create_perm Permission required for creation
-        * @param string $reason Reason for protection
-        * @param string $expiry Expiry timestamp
-        * @return bool
-        */
-       public function updateTitleProtection( $create_perm, $reason, $expiry ) {
-               wfDeprecated( __METHOD__, '1.19' );
-
-               global $wgUser;
-
-               $limit = array( 'create' => $create_perm );
-               $expiry = array( 'create' => $expiry );
-
-               $page = WikiPage::factory( $this );
-               $cascade = false;
-               $status = $page->doUpdateRestrictions( $limit, $expiry, $cascade, $reason, $wgUser );
-
-               return $status->isOK();
-       }
-
        /**
         * Remove any title protection due to page existing
         */
@@ -2722,7 +2644,7 @@ class Title {
         * @since 1.23
         */
        public function areCascadeProtectionSourcesLoaded( $getPages = true ) {
-               return $getPages ? isset( $this->mCascadeSources ) : isset( $this->mHasCascadingRestrictions );
+               return $getPages ? $this->mCascadeSources !== null : $this->mHasCascadingRestrictions !== null;
        }
 
        /**
@@ -2742,9 +2664,9 @@ class Title {
                global $wgContLang;
                $pagerestrictions = array();
 
-               if ( isset( $this->mCascadeSources ) && $getPages ) {
+               if ( $this->mCascadeSources !== null && $getPages ) {
                        return array( $this->mCascadeSources, $this->mCascadingRestrictions );
-               } elseif ( isset( $this->mHasCascadingRestrictions ) && !$getPages ) {
+               } elseif ( $this->mHasCascadingRestrictions !== null && !$getPages ) {
                        return array( $this->mHasCascadingRestrictions, $pagerestrictions );
                }
 
@@ -3090,7 +3012,7 @@ class Title {
                # alone to cache the result.  There's no point in having it hanging
                # around uninitialized in every Title object; therefore we only add it
                # if needed and don't declare it statically.
-               if ( !isset( $this->mHasSubpages ) ) {
+               if ( $this->mHasSubpages === null ) {
                        $this->mHasSubpages = false;
                        $subpages = $this->getSubpages( 1 );
                        if ( $subpages instanceof TitleArray ) {
@@ -4779,7 +4701,9 @@ class Title {
         * @return string Last-touched timestamp
         */
        public function getTouched( $db = null ) {
-               $db = isset( $db ) ? $db : wfGetDB( DB_SLAVE );
+               if ( $db === null ) {
+                       $db = wfGetDB( DB_SLAVE );
+               }
                $touched = $db->selectField( 'page', 'page_touched', $this->pageCond(), __METHOD__ );
                return $touched;
        }
index 67ee7f9..62e35e8 100644 (file)
@@ -892,38 +892,6 @@ class User implements IDBAccessObject {
                return $this->mPasswordExpires;
        }
 
-       /**
-        * Does a string look like an e-mail address?
-        *
-        * This validates an email address using an HTML5 specification found at:
-        * http://www.whatwg.org/html/states-of-the-type-attribute.html#valid-e-mail-address
-        * Which as of 2011-01-24 says:
-        *
-        *     A valid e-mail address is a string that matches the ABNF production
-        *   1*( atext / "." ) "@" ldh-str *( "." ldh-str ) where atext is defined
-        *   in RFC 5322 section 3.2.3, and ldh-str is defined in RFC 1034 section
-        *   3.5.
-        *
-        * This function is an implementation of the specification as requested in
-        * bug 22449.
-        *
-        * Client-side forms will use the same standard validation rules via JS or
-        * HTML 5 validation; additional restrictions can be enforced server-side
-        * by extensions via the 'isValidEmailAddr' hook.
-        *
-        * Note that this validation doesn't 100% match RFC 2822, but is believed
-        * to be liberal enough for wide use. Some invalid addresses will still
-        * pass validation here.
-        *
-        * @param string $addr E-mail address
-        * @return bool
-        * @deprecated since 1.18 call Sanitizer::isValidEmail() directly
-        */
-       public static function isValidEmailAddr( $addr ) {
-               wfDeprecated( __METHOD__, '1.18' );
-               return Sanitizer::validateEmail( $addr );
-       }
-
        /**
         * Given unvalidated user input, return a canonical username, or false if
         * the username is invalid.
@@ -2778,6 +2746,8 @@ class User implements IDBAccessObject {
                        }
                }
 
+               wfRunHooks( 'UserResetAllOptions', array( $this, &$newOptions, $this->mOptions, $resetKinds ) );
+
                $this->mOptions = $newOptions;
                $this->mOptionsLoaded = true;
        }
@@ -2946,7 +2916,7 @@ class User implements IDBAccessObject {
                        return null;
                }
 
-               if ( !isset( $this->mEditCount ) ) {
+               if ( $this->mEditCount === null ) {
                        /* Populate the count, if it has not been populated yet */
                        wfProfileIn( __METHOD__ );
                        $dbr = wfGetDB( DB_SLAVE );
index d73f6b4..c9db90f 100644 (file)
@@ -239,7 +239,17 @@ class UserMailer {
                # -- hashar 20120218
 
                $headers['From'] = $from->toString();
-               $headers['Return-Path'] = $from->address;
+               $returnPath = $from->address;
+               $extraParams = $wgAdditionalMailParams;
+
+               // Hook to generate custom VERP address for 'Return-Path'
+               wfRunHooks( 'UserMailerChangeReturnPath', array( $to, &$returnPath ) );
+               # Add the envelope sender address using the -f command line option when PHP mail() is used.
+               # Will default to the $from->address when the UserMailerChangeReturnPath hook fails and the
+               # generated VERP address when the hook runs effectively.
+               $extraParams .= ' -f ' . $returnPath;
+
+               $headers['Return-Path'] = $returnPath;
 
                if ( $replyto ) {
                        $headers['Reply-To'] = $replyto->toString();
@@ -371,7 +381,7 @@ class UserMailer {
                                                        self::quotedPrintable( $subject ),
                                                        $body,
                                                        $headers,
-                                                       $wgAdditionalMailParams
+                                                       $extraParams
                                                );
                                        }
                                }
index 09f01c0..71454f0 100644 (file)
  * @file
  */
 
-# Protect against register_globals
+# Die if register_globals is enabled (PHP <=5.3)
 # This must be done before any globals are set by the code
 if ( ini_get( 'register_globals' ) ) {
-       if ( isset( $_REQUEST['GLOBALS'] ) || isset( $_FILES['GLOBALS'] ) ) {
-               die( '<a href="http://www.hardened-php.net/globals-problem">'
-                       . '$GLOBALS overwrite vulnerability</a>' );
-       }
-
-       $verboten = array(
-               'GLOBALS',
-               '_SERVER',
-               'HTTP_SERVER_VARS',
-               '_GET',
-               'HTTP_GET_VARS',
-               '_POST',
-               'HTTP_POST_VARS',
-               '_COOKIE',
-               'HTTP_COOKIE_VARS',
-               '_FILES',
-               'HTTP_POST_FILES',
-               '_ENV',
-               'HTTP_ENV_VARS',
-               '_REQUEST',
-               '_SESSION',
-               'HTTP_SESSION_VARS'
-       );
-
-       foreach ( $_REQUEST as $name => $value ) {
-               if ( in_array( $name, $verboten ) ) {
-                       header( "HTTP/1.1 500 Internal Server Error" );
-                       echo "register_globals security paranoia: trying to overwrite superglobals, aborting.";
-                       die( -1 );
-               }
-               unset( $GLOBALS[$name] );
-       }
+       die( 'MediaWiki does not support installations where register_globals is enabled. '
+               . 'Please see <a href="https://www.mediawiki.org/wiki/register_globals">mediawiki.org</a> '
+               . 'for help on how to disable it.' );
 }
 
 # bug 15461: Make IE8 turn off content sniffing. Everybody else should ignore this
index 72210a9..31f58b8 100644 (file)
@@ -26,8 +26,7 @@
 /**
  * Page edition handler
  *
- * This is a wrapper that will call the EditPage class, or ExternalEdit
- * if $wgUseExternalEditor is set to true and requested by the user.
+ * This is a wrapper that will call the EditPage class or a custom editor from an extension.
  *
  * @ingroup Actions
  */
index f1e3c26..c946184 100644 (file)
@@ -782,7 +782,7 @@ class HistoryPager extends ReverseChronologicalPager {
         */
        function lastLink( $prevRev, $next ) {
                $last = $this->historyPage->message['last'];
-               # $next may either be a Row, null, or "unkown"
+               # $next may either be a Row, null, or "unknown"
                $nextRev = is_object( $next ) ? new Revision( $next ) : $next;
                if ( is_null( $next ) ) {
                        # Probably no next row
index cdd139e..92428cf 100644 (file)
@@ -86,6 +86,7 @@ class RevertFileAction extends FormAction {
                $form->setWrapperLegendMsg( 'filerevert-legend' );
                $form->setSubmitTextMsg( 'filerevert-submit' );
                $form->addHiddenField( 'oldimage', $this->getRequest()->getText( 'oldimage' ) );
+               $form->setTokenSalt( array( 'revert', $this->getTitle()->getPrefixedDBkey() ) );
        }
 
        protected function getFormFields() {
index d221799..4f4d051 100644 (file)
@@ -1189,9 +1189,9 @@ abstract class ApiBase extends ContextSource {
         * @param mixed $value The value being parsed
         * @param bool $allowMultiple Can $value contain more than one value
         *  separated by '|'?
-        * @param mixed $allowedValues An array of values to check against. If
+        * @param string[]|null $allowedValues An array of values to check against. If
         *  null, all values are accepted.
-        * @return mixed (allowMultiple ? an_array_of_values : a_single_value)
+        * @return string|string[] (allowMultiple ? an_array_of_values : a_single_value)
         */
        protected function parseMultiValue( $valueName, $value, $allowMultiple, $allowedValues ) {
                if ( trim( $value ) === '' && $allowMultiple ) {
index b8e16ab..c932a74 100644 (file)
@@ -52,6 +52,8 @@ class ApiImageRotate extends ApiBase {
                $params = $this->extractRequestParams();
                $rotation = $params['rotation'];
 
+               $this->getResult()->beginContinuation( $params['continue'], array(), array() );
+
                $pageSet = $this->getPageSet();
                $pageSet->execute();
 
@@ -131,6 +133,7 @@ class ApiImageRotate extends ApiBase {
                $apiResult = $this->getResult();
                $apiResult->setIndexedTagName( $result, 'page' );
                $apiResult->addValue( null, $this->getModuleName(), $result );
+               $apiResult->endContinuation();
        }
 
        /**
@@ -185,6 +188,7 @@ class ApiImageRotate extends ApiBase {
                                ApiBase::PARAM_TYPE => 'string',
                                ApiBase::PARAM_REQUIRED => true
                        ),
+                       'continue' => '',
                );
                if ( $flags ) {
                        $result += $this->getPageSet()->getFinalParams( $flags );
@@ -199,6 +203,7 @@ class ApiImageRotate extends ApiBase {
                return $pageSet->getFinalParamDescription() + array(
                        'rotation' => 'Degrees to rotate image clockwise',
                        'token' => 'Edit token. You can get one of these through action=tokens',
+                       'continue' => 'When more results are available, use this to continue',
                );
        }
 
index 9dc4d03..b906b59 100644 (file)
@@ -270,7 +270,7 @@ class ApiParse extends ApiBase {
                        );
                }
 
-               if ( isset( $prop['langlinks'] ) || isset( $prop['languageshtml'] ) ) {
+               if ( isset( $prop['langlinks'] ) ) {
                        $langlinks = $p_result->getLanguageLinks();
 
                        if ( $params['effectivelanglinks'] ) {
@@ -286,12 +286,6 @@ class ApiParse extends ApiBase {
                if ( isset( $prop['langlinks'] ) ) {
                        $result_array['langlinks'] = $this->formatLangLinks( $langlinks );
                }
-               if ( isset( $prop['languageshtml'] ) ) {
-                       $languagesHtml = $this->languagesHtml( $langlinks );
-
-                       $result_array['languageshtml'] = array();
-                       ApiResult::setContent( $result_array['languageshtml'], $languagesHtml );
-               }
                if ( isset( $prop['categories'] ) ) {
                        $result_array['categories'] = $this->formatCategoryLinks( $p_result->getCategories() );
                }
@@ -563,46 +557,6 @@ class ApiParse extends ApiBase {
                return $context->getSkin()->getCategories();
        }
 
-       /**
-        * @deprecated since 1.18 No modern skin generates language links this way,
-        * please use language links data to generate your own HTML.
-        * @param array $languages
-        * @return string
-        */
-       private function languagesHtml( $languages ) {
-               wfDeprecated( __METHOD__, '1.18' );
-               $this->setWarning( '"action=parse&prop=languageshtml" is deprecated ' .
-                       'and will be removed in MediaWiki 1.24. Use "prop=langlinks" ' .
-                       'to generate your own HTML.' );
-
-               global $wgContLang;
-
-               if ( $this->getConfig()->get( 'HideInterlanguageLinks' ) || count( $languages ) == 0 ) {
-                       return '';
-               }
-
-               $s = htmlspecialchars( wfMessage( 'otherlanguages' )->text() .
-                       wfMessage( 'colon-separator' )->text() );
-
-               $langs = array();
-               foreach ( $languages as $l ) {
-                       $nt = Title::newFromText( $l );
-                       $text = Language::fetchLanguageName( $nt->getInterwiki() );
-
-                       $langs[] = Html::element( 'a',
-                               array( 'href' => $nt->getFullURL(), 'title' => $nt->getText(), 'class' => 'external' ),
-                               $text == '' ? $l : $text );
-               }
-
-               $s .= implode( wfMessage( 'pipe-separator' )->escaped(), $langs );
-
-               if ( $wgContLang->isRTL() ) {
-                       $s = Html::rawElement( 'span', array( 'dir' => 'LTR' ), $s );
-               }
-
-               return $s;
-       }
-
        private function formatLinks( $links ) {
                $result = array();
                foreach ( $links as $ns => $nslinks ) {
@@ -723,7 +677,6 @@ class ApiParse extends ApiBase {
                                ApiBase::PARAM_TYPE => array(
                                        'text',
                                        'langlinks',
-                                       'languageshtml',
                                        'categories',
                                        'categorieshtml',
                                        'links',
@@ -782,8 +735,6 @@ class ApiParse extends ApiBase {
                                ' langlinks      - Gives the language links in the parsed wikitext',
                                ' categories     - Gives the categories in the parsed wikitext',
                                ' categorieshtml - Gives the HTML version of the categories',
-                               ' languageshtml  - DEPRECATED. Will be removed in MediaWiki 1.24.',
-                               '                  Gives the HTML version of the language links',
                                ' links          - Gives the internal links in the parsed wikitext',
                                ' templates      - Gives the templates in the parsed wikitext',
                                ' images         - Gives the images in the parsed wikitext',
@@ -804,7 +755,7 @@ class ApiParse extends ApiBase {
                        ),
                        'effectivelanglinks' => array(
                                'Includes language links supplied by extensions',
-                               '(for use with prop=langlinks|languageshtml)',
+                               '(for use with prop=langlinks)',
                        ),
                        'pst' => array(
                                'Do a pre-save transform on the input before parsing it',
index 981dc18..3399843 100644 (file)
@@ -38,6 +38,8 @@ class ApiPurge extends ApiBase {
        public function execute() {
                $params = $this->extractRequestParams();
 
+               $this->getResult()->beginContinuation( $params['continue'], array(), array() );
+
                $forceLinkUpdate = $params['forcelinkupdate'];
                $forceRecursiveLinkUpdate = $params['forcerecursivelinkupdate'];
                $pageSet = $this->getPageSet();
@@ -102,6 +104,8 @@ class ApiPurge extends ApiBase {
                if ( $values ) {
                        $apiResult->addValue( null, 'redirects', $values );
                }
+
+               $apiResult->endContinuation();
        }
 
        /**
@@ -128,7 +132,8 @@ class ApiPurge extends ApiBase {
        public function getAllowedParams( $flags = 0 ) {
                $result = array(
                        'forcelinkupdate' => false,
-                       'forcerecursivelinkupdate' => false
+                       'forcerecursivelinkupdate' => false,
+                       'continue' => '',
                );
                if ( $flags ) {
                        $result += $this->getPageSet()->getFinalParams( $flags );
@@ -143,6 +148,7 @@ class ApiPurge extends ApiBase {
                                'forcelinkupdate' => 'Update the links tables',
                                'forcerecursivelinkupdate' => 'Update the links table, and update ' .
                                        'the links tables for any page that uses this page as a template',
+                               'continue' => 'When more results are available, use this to continue',
                        );
        }
 
index a2f4121..cd6a840 100644 (file)
@@ -118,8 +118,6 @@ class ApiQuery extends ApiBase {
        private $mParams;
        private $mNamedDB = array();
        private $mModuleMgr;
-       private $mGeneratorContinue;
-       private $mUseLegacyContinue;
 
        /**
         * @param ApiMain $main
@@ -245,23 +243,24 @@ class ApiQuery extends ApiBase {
        public function execute() {
                $this->mParams = $this->extractRequestParams();
 
-               // $pagesetParams is a array of parameter names used by the pageset generator
-               //   or null if pageset has already finished and is no longer needed
-               // $completeModules is a set of complete modules with the name as key
-               $this->initContinue( $pagesetParams, $completeModules );
-
                // Instantiate requested modules
                $allModules = array();
                $this->instantiateModules( $allModules, 'prop' );
-               $propModules = $allModules; // Keep a copy
+               $propModules = array_keys( $allModules );
                $this->instantiateModules( $allModules, 'list' );
                $this->instantiateModules( $allModules, 'meta' );
 
                // Filter modules based on continue parameter
-               $modules = $this->initModules( $allModules, $completeModules, $pagesetParams !== null );
+               list( $generatorDone, $modules ) = $this->getResult()->beginContinuation(
+                       $this->mParams['continue'], $allModules, $propModules
+               );
 
-               // Execute pageset if in legacy mode or if pageset is not done
-               if ( $completeModules === null || $pagesetParams !== null ) {
+               if ( !$generatorDone ) {
+                       // Query modules may optimize data requests through the $this->getPageSet()
+                       // object by adding extra fields from the page table.
+                       foreach ( $modules as $module ) {
+                               $module->requestExtraData( $this->mPageSet );
+                       }
                        // Populate page/revision information
                        $this->mPageSet->execute();
                        // Record page information (title, namespace, if exists, etc)
@@ -287,135 +286,10 @@ class ApiQuery extends ApiBase {
                // Set the cache mode
                $this->getMain()->setCacheMode( $cacheMode );
 
-               if ( $completeModules === null ) {
-                       return; // Legacy continue, we are done
-               }
-
-               // Reformat query-continue result section
-               $result = $this->getResult();
-               $qc = $result->getData();
-               if ( isset( $qc['query-continue'] ) ) {
-                       $qc = $qc['query-continue'];
-                       $result->unsetValue( null, 'query-continue' );
-               } elseif ( $this->mGeneratorContinue !== null ) {
-                       $qc = array();
-               } else {
-                       // no more "continue"s, we are done!
-                       return;
-               }
-
-               // we are done with all the modules that do not have result in query-continue
-               $completeModules = array_merge( $completeModules, array_diff_key( $modules, $qc ) );
-               if ( $pagesetParams !== null ) {
-                       // The pageset is still in use, check if all props have finished
-                       $incompleteProps = array_intersect_key( $propModules, $qc );
-                       if ( count( $incompleteProps ) > 0 ) {
-                               // Properties are not done, continue with the same pageset state - copy current parameters
-                               $main = $this->getMain();
-                               $contValues = array();
-                               foreach ( $pagesetParams as $param ) {
-                                       // The param name is already prefix-encoded
-                                       $contValues[$param] = $main->getVal( $param );
-                               }
-                       } elseif ( $this->mGeneratorContinue !== null ) {
-                               // Move to the next set of pages produced by pageset, properties need to be restarted
-                               $contValues = $this->mGeneratorContinue;
-                               $pagesetParams = array_keys( $contValues );
-                               $completeModules = array_diff_key( $completeModules, $propModules );
-                       } else {
-                               // Done with the pageset, finish up with the the lists and meta modules
-                               $pagesetParams = null;
-                       }
-               }
-
-               $continue = '||' . implode( '|', array_keys( $completeModules ) );
-               if ( $pagesetParams !== null ) {
-                       // list of all pageset parameters to use in the next request
-                       $continue = implode( '|', $pagesetParams ) . $continue;
-               } else {
-                       // we are done with the pageset
-                       $contValues = array();
-                       $continue = '-' . $continue;
-               }
-               $contValues['continue'] = $continue;
-               foreach ( $qc as $qcModule ) {
-                       foreach ( $qcModule as $qcKey => $qcValue ) {
-                               $contValues[$qcKey] = $qcValue;
-                       }
-               }
-               $this->getResult()->addValue( null, 'continue', $contValues );
-       }
-
-       /**
-        * Parse 'continue' parameter into the list of complete modules and a list of generator parameters
-        * @param array|null $pagesetParams Returns list of generator params or null if pageset is done
-        * @param array|null $completeModules Returns list of finished modules (as keys), or null if legacy
-        */
-       private function initContinue( &$pagesetParams, &$completeModules ) {
-               $pagesetParams = array();
-               $continue = $this->mParams['continue'];
-               if ( $continue !== null ) {
-                       $this->mUseLegacyContinue = false;
-                       if ( $continue !== '' ) {
-                               // Format: ' pagesetParam1 | pagesetParam2 || module1 | module2 | module3 | ...
-                               // If pageset is done, use '-'
-                               $continue = explode( '||', $continue );
-                               $this->dieContinueUsageIf( count( $continue ) !== 2 );
-                               if ( $continue[0] === '-' ) {
-                                       $pagesetParams = null; // No need to execute pageset
-                               } elseif ( $continue[0] !== '' ) {
-                                       // list of pageset params that might need to be repeated
-                                       $pagesetParams = explode( '|', $continue[0] );
-                               }
-                               $continue = $continue[1];
-                       }
-                       if ( $continue !== '' ) {
-                               $completeModules = array_flip( explode( '|', $continue ) );
-                       } else {
-                               $completeModules = array();
-                       }
-               } else {
-                       $this->mUseLegacyContinue = true;
-                       $completeModules = null;
-               }
-       }
-
-       /**
-        * Validate sub-modules, filter out completed ones, and do requestExtraData()
-        * @param array $allModules An dict of name=>instance of all modules requested by the client
-        * @param array|null $completeModules List of finished modules, or null if legacy continue
-        * @param bool $usePageset True if pageset will be executed
-        * @return array Array of modules to be processed during this execution
-        */
-       private function initModules( $allModules, $completeModules, $usePageset ) {
-               $modules = $allModules;
-               $tmp = $completeModules;
-               $wasPosted = $this->getRequest()->wasPosted();
-
-               /** @var $module ApiQueryBase */
-               foreach ( $allModules as $moduleName => $module ) {
-                       if ( !$wasPosted && $module->mustBePosted() ) {
-                               $this->dieUsageMsgOrDebug( array( 'mustbeposted', $moduleName ) );
-                       }
-                       if ( $completeModules !== null && array_key_exists( $moduleName, $completeModules ) ) {
-                               // If this module is done, mark all its params as used
-                               $module->extractRequestParams();
-                               // Make sure this module is not used during execution
-                               unset( $modules[$moduleName] );
-                               unset( $tmp[$moduleName] );
-                       } elseif ( $completeModules === null || $usePageset ) {
-                               // Query modules may optimize data requests through the $this->getPageSet()
-                               // object by adding extra fields from the page table.
-                               // This function will gather all the extra request fields from the modules.
-                               $module->requestExtraData( $this->mPageSet );
-                       } else {
-                               // Error - this prop module must have finished before generator is done
-                               $this->dieContinueUsageIf( $this->mModuleMgr->getModuleGroup( $moduleName ) === 'prop' );
-                       }
-               }
-               $this->dieContinueUsageIf( $completeModules !== null && count( $tmp ) !== 0 );
-
-               return $modules;
+               // Write the continuation data into the result
+               $this->getResult()->endContinuation(
+                       $this->mParams['continue'] === null ? 'raw' : 'standard'
+               );
        }
 
        /**
@@ -447,12 +321,16 @@ class ApiQuery extends ApiBase {
         * @param string $param Parameter name to read modules from
         */
        private function instantiateModules( &$modules, $param ) {
+               $wasPosted = $this->getRequest()->wasPosted();
                if ( isset( $this->mParams[$param] ) ) {
                        foreach ( $this->mParams[$param] as $moduleName ) {
                                $instance = $this->mModuleMgr->getModule( $moduleName, $param );
                                if ( $instance === null ) {
                                        ApiBase::dieDebug( __METHOD__, 'Error instantiating module' );
                                }
+                               if ( !$wasPosted && $instance->mustBePosted() ) {
+                                       $this->dieUsageMsgOrDebug( array( 'mustbeposted', $moduleName ) );
+                               }
                                // Ignore duplicates. TODO 2.0: die()?
                                if ( !array_key_exists( $moduleName, $modules ) ) {
                                        $modules[$moduleName] = $instance;
@@ -563,22 +441,16 @@ class ApiQuery extends ApiBase {
         * This method is called by the generator base when generator in the smart-continue
         * mode tries to set 'query-continue' value. ApiQuery stores those values separately
         * until the post-processing when it is known if the generation should continue or repeat.
+        * @deprecated @since 1.24
         * @param ApiQueryGeneratorBase $module Generator module
         * @param string $paramName
         * @param mixed $paramValue
         * @return bool True if processed, false if this is a legacy continue
         */
        public function setGeneratorContinue( $module, $paramName, $paramValue ) {
-               if ( $this->mUseLegacyContinue ) {
-                       return false;
-               }
-               $paramName = $module->encodeParamName( $paramName );
-               if ( $this->mGeneratorContinue === null ) {
-                       $this->mGeneratorContinue = array();
-               }
-               $this->mGeneratorContinue[$paramName] = $paramValue;
-
-               return true;
+               wfDeprecated( __METHOD__, '1.24' );
+               $this->getResult()->setGeneratorContinueParam( $module, $paramName, $paramValue );
+               return $this->getParameter( 'continue' ) !== null;
        }
 
        /**
index e32104f..d0980e6 100644 (file)
@@ -45,9 +45,15 @@ class ApiQueryAllUsers extends ApiQueryBase {
        }
 
        public function execute() {
-               $db = $this->getDB();
                $params = $this->extractRequestParams();
 
+               if ( $params['activeusers'] ) {
+                       // Update active user cache
+                       SpecialActiveUsers::mergeActiveUsers( 600 );
+               }
+
+               $db = $this->getDB();
+
                $prop = $params['prop'];
                if ( !is_null( $prop ) ) {
                        $prop = array_flip( $prop );
@@ -71,9 +77,9 @@ class ApiQueryAllUsers extends ApiQueryBase {
                $from = is_null( $params['from'] ) ? null : $this->getCanonicalUserName( $params['from'] );
                $to = is_null( $params['to'] ) ? null : $this->getCanonicalUserName( $params['to'] );
 
-               # MySQL doesn't seem to use 'equality propagation' here, so like the
-               # ActiveUsers special page, we have to use rc_user_text for some cases.
-               $userFieldToSort = $params['activeusers'] ? 'rc_user_text' : 'user_name';
+               # MySQL can't figure out that 'user_name' and 'qcc_title' are the same
+               # despite the JOIN condition, so manually sort on the correct one.
+               $userFieldToSort = $params['activeusers'] ? 'qcc_title' : 'user_name';
 
                $this->addWhereRange( $userFieldToSort, $dir, $from, $to );
 
@@ -155,19 +161,32 @@ class ApiQueryAllUsers extends ApiQueryBase {
                }
 
                if ( $params['activeusers'] ) {
-                       $this->addTables( 'recentchanges' );
-
-                       $this->addJoinConds( array( 'recentchanges' => array(
-                               'INNER JOIN', 'rc_user_text=user_name'
+                       $activeUserSeconds = $this->getConfig()->get( 'ActiveUserDays' ) * 86400;
+
+                       // Filter query to only include users in the active users cache
+                       $this->addTables( 'querycachetwo' );
+                       $this->addJoinConds( array( 'querycachetwo' => array(
+                               'INNER JOIN', array(
+                                       'qcc_type' => 'activeusers',
+                                       'qcc_namespace' => NS_USER,
+                                       'qcc_title=user_name',
+                               ),
                        ) ) );
 
-                       $this->addFields( array( 'recentedits' => 'COUNT(*)' ) );
-
-                       $this->addWhere( 'rc_log_type IS NULL OR rc_log_type != ' . $db->addQuotes( 'newusers' ) );
-                       $timestamp = $db->timestamp( wfTimestamp( TS_UNIX ) - $this->getConfig()->get( 'ActiveUserDays' ) * 24 * 3600 );
-                       $this->addWhere( 'rc_timestamp >= ' . $db->addQuotes( $timestamp ) );
-
-                       $this->addOption( 'GROUP BY', $userFieldToSort );
+                       // Actually count the actions using a subquery (bug 64505 and bug 64507)
+                       $timestamp = $db->timestamp( wfTimestamp( TS_UNIX ) - $activeUserSeconds );
+                       $this->addFields( array(
+                               'recentactions' => '(' . $db->selectSQLText(
+                                       'recentchanges',
+                                       'COUNT(*)',
+                                       array(
+                                               'rc_user_text = user_name',
+                                               'rc_type != ' . $db->addQuotes( RC_EXTERNAL ), // no wikidata
+                                               'rc_log_type IS NULL OR rc_log_type != ' . $db->addQuotes( 'newusers' ),
+                                               'rc_timestamp >= ' . $db->addQuotes( $timestamp ),
+                                       )
+                               ) . ')'
+                       ) );
                }
 
                $this->addOption( 'LIMIT', $sqlLimit );
@@ -203,8 +222,13 @@ class ApiQueryAllUsers extends ApiQueryBase {
                        if ( $lastUser !== $row->user_name ) {
                                // Save the last pass's user data
                                if ( is_array( $lastUserData ) ) {
-                                       $fit = $result->addValue( array( 'query', $this->getModuleName() ),
-                                               null, $lastUserData );
+                                       if ( $params['activeusers'] && $lastUserData['recentactions'] === 0 ) {
+                                               // activeusers cache was out of date
+                                               $fit = true;
+                                       } else {
+                                               $fit = $result->addValue( array( 'query', $this->getModuleName() ),
+                                                       null, $lastUserData );
+                                       }
 
                                        $lastUserData = null;
 
@@ -241,7 +265,9 @@ class ApiQueryAllUsers extends ApiQueryBase {
                                        $lastUserData['editcount'] = intval( $row->user_editcount );
                                }
                                if ( $params['activeusers'] ) {
-                                       $lastUserData['recenteditcount'] = intval( $row->recentedits );
+                                       $lastUserData['recentactions'] = intval( $row->recentactions );
+                                       // @todo 'recenteditcount' is set for BC, remove in 1.25
+                                       $lastUserData['recenteditcount'] = $lastUserData['recentactions'];
                                }
                                if ( $fld_registration ) {
                                        $lastUserData['registration'] = $row->user_registration ?
@@ -302,7 +328,9 @@ class ApiQueryAllUsers extends ApiQueryBase {
                        }
                }
 
-               if ( is_array( $lastUserData ) ) {
+               if ( is_array( $lastUserData ) &&
+                       !( $params['activeusers'] && $lastUserData['recentactions'] === 0 )
+               ) {
                        $fit = $result->addValue( array( 'query', $this->getModuleName() ),
                                null, $lastUserData );
                        if ( !$fit ) {
@@ -397,7 +425,7 @@ class ApiQueryAllUsers extends ApiQueryBase {
                        '' => array(
                                'userid' => 'integer',
                                'name' => 'string',
-                               'recenteditcount' => array(
+                               'recentactions' => array(
                                        ApiBase::PROP_TYPE => 'integer',
                                        ApiBase::PROP_NULLABLE => true
                                )
index 8e014df..fb88201 100644 (file)
@@ -75,8 +75,8 @@ abstract class ApiQueryBase extends ApiBase {
 
        /**
         * Add a set of tables to the internal array
-        * @param mixed $tables Table name or array of table names
-        * @param mixed $alias Table alias, or null for no alias. Cannot be
+        * @param string|string[] $tables Table name or array of table names
+        * @param string|null $alias Table alias, or null for no alias. Cannot be
         *  used with multiple tables
         */
        protected function addTables( $tables, $alias = null ) {
@@ -398,15 +398,10 @@ abstract class ApiQueryBase extends ApiBase {
        /**
         * Set a query-continue value
         * @param string $paramName Parameter name
-        * @param string $paramValue Parameter value
+        * @param string|array $paramValue Parameter value
         */
        protected function setContinueEnumParameter( $paramName, $paramValue ) {
-               $paramName = $this->encodeParamName( $paramName );
-               $msg = array( $paramName => $paramValue );
-               $result = $this->getResult();
-               $result->disableSizeCheck();
-               $result->addValue( 'query-continue', $this->getModuleName(), $msg, ApiResult::ADD_ON_TOP );
-               $result->enableSizeCheck();
+               $this->getResult()->setContinueParam( $this, $paramName, $paramValue );
        }
 
        /**
@@ -667,16 +662,14 @@ abstract class ApiQueryGeneratorBase extends ApiQueryBase {
        }
 
        /**
-        * Overrides base in case of generator & smart continue to
-        * notify ApiQueryMain instead of adding them to the result right away.
+        * Overridden to set the generator param if in generator mode
         * @param string $paramName Parameter name
-        * @param string $paramValue Parameter value
+        * @param string|array $paramValue Parameter value
         */
        protected function setContinueEnumParameter( $paramName, $paramValue ) {
-               // If this is a generator and query->setGeneratorContinue() returns false, treat as before
-               if ( $this->mGeneratorPageSet === null
-                       || !$this->getQuery()->setGeneratorContinue( $this, $paramName, $paramValue )
-               ) {
+               if ( $this->mGeneratorPageSet !== null ) {
+                       $this->getResult()->setGeneratorContinueParam( $this, $paramName, $paramValue );
+               } else {
                        parent::setContinueEnumParameter( $paramName, $paramValue );
                }
        }
index af0d938..6994cd4 100644 (file)
@@ -134,11 +134,17 @@ class ApiQueryDeletedrevs extends ApiQueryBase {
                }
 
                if ( $fld_content ) {
+                       // Modern MediaWiki has the content for deleted revs in the 'text'
+                       // table using fields old_text and old_flags. But revisions deleted
+                       // pre-1.5 store the content in the 'archive' table directly using
+                       // fields ar_text and ar_flags, and no corresponding 'text' row. So
+                       // we have to LEFT JOIN and fetch all four fields, plus ar_text_id
+                       // to be able to tell the difference.
                        $this->addTables( 'text' );
                        $this->addJoinConds(
-                               array( 'text' => array( 'INNER JOIN', array( 'ar_text_id=old_id' ) ) )
+                               array( 'text' => array( 'LEFT JOIN', array( 'ar_text_id=old_id' ) ) )
                        );
-                       $this->addFields( array( 'ar_text', 'ar_text_id', 'old_text', 'old_flags' ) );
+                       $this->addFields( array( 'ar_text', 'ar_flags', 'ar_text_id', 'old_text', 'old_flags' ) );
 
                        // This also means stricter restrictions
                        if ( !$user->isAllowedAny( 'undelete', 'deletedtext' ) ) {
@@ -353,7 +359,12 @@ class ApiQueryDeletedrevs extends ApiQueryBase {
                                        $anyHidden = true;
                                }
                                if ( Revision::userCanBitfield( $row->ar_deleted, Revision::DELETED_TEXT, $user ) ) {
-                                       ApiResult::setContent( $rev, Revision::getRevisionText( $row ) );
+                                       if ( isset( $row->ar_text ) && !$row->ar_text_id ) {
+                                               // Pre-1.5 ar_text row (if condition from Revision::newFromArchiveRow)
+                                               ApiResult::setContent( $rev, Revision::getRevisionText( $row, 'ar_' ) );
+                                       } else {
+                                               ApiResult::setContent( $rev, Revision::getRevisionText( $row ) );
+                                       }
                                }
                        }
 
index e4078d5..c35d39b 100644 (file)
@@ -405,7 +405,7 @@ class ApiQueryRecentChanges extends ApiQueryGeneratorBase {
        /**
         * Extracts from a single sql row the data needed to describe one recent change.
         *
-        * @param mixed $row The row from which to extract the data.
+        * @param stdClass $row The row from which to extract the data.
         * @return array An array mapping strings (descriptors) to their respective string values.
         * @access public
         */
index aacf091..089ce04 100644 (file)
@@ -136,7 +136,7 @@ class ApiQuerySiteinfo extends ApiQueryBase {
 
                $data['generator'] = "MediaWiki {$config->get( 'Version' )}";
 
-               $data['phpversion'] = phpversion();
+               $data['phpversion'] = PHP_VERSION;
                $data['phpsapi'] = PHP_SAPI;
                $data['dbtype'] = $config->get( 'DBtype' );
                $data['dbversion'] = $this->getDB()->getServerVersion();
index 24c4c20..5f93071 100644 (file)
@@ -326,7 +326,7 @@ class ApiQueryContributions extends ApiQueryBase {
        /**
         * Extract fields from the database row and append them to a result array
         *
-        * @param mixed $row
+        * @param stdClass $row
         * @return array
         */
        private function extractRowInfo( $row ) {
index 7d0a15a..b30d9dd 100644 (file)
@@ -60,6 +60,13 @@ class ApiResult extends ApiBase {
 
        private $mData, $mIsRawMode, $mSize, $mCheckingSize;
 
+       private $continueAllModules = array();
+       private $continueGeneratedModules = array();
+       private $continuationData = array();
+       private $generatorContinuationData = array();
+       private $generatorParams = array();
+       private $generatorDone = false;
+
        /**
         * @param ApiMain $main
         */
@@ -437,4 +444,181 @@ class ApiResult extends ApiBase {
        public function execute() {
                ApiBase::dieDebug( __METHOD__, 'execute() is not supported on Result object' );
        }
+
+       /**
+        * Parse a 'continue' parameter and return status information.
+        *
+        * This must be balanced by a call to endContinuation().
+        *
+        * @since 1.24
+        * @param string|null $continue The "continue" parameter, if any
+        * @param array $allModules Contains ApiBase instances that will be executed
+        * @param array $generatedModules Names of modules that depend on the generator
+        * @return array Two elements: a boolean indicating if the generator is done,
+        *   and an array of modules to actually execute.
+        */
+       public function beginContinuation(
+               $continue, array $allModules = array(), array $generatedModules = array()
+       ) {
+               $this->continueGeneratedModules = $generatedModules
+                       ? array_combine( $generatedModules, $generatedModules )
+                       : array();
+               $this->continuationData = array();
+               $this->generatorContinuationData = array();
+               $this->generatorParams = array();
+
+               $skip = array();
+               if ( is_string( $continue ) && $continue !== '' ) {
+                       $continue = explode( '||', $continue );
+                       $this->dieContinueUsageIf( count( $continue ) !== 2 );
+                       $this->generatorDone = ( $continue[0] === '-' );
+                       if ( !$this->generatorDone ) {
+                               $this->generatorParams = explode( '|', $continue[0] );
+                       }
+                       $skip = explode( '|', $continue[1] );
+               }
+
+               $this->continueAllModules = array();
+               $runModules = array();
+               foreach ( $allModules as $module ) {
+                       $name = $module->getModuleName();
+                       if ( in_array( $name, $skip ) ) {
+                               $this->continueAllModules[$name] = false;
+                               // Prevent spurious "unused parameter" warnings
+                               $module->extractRequestParams();
+                       } else {
+                               $this->continueAllModules[$name] = true;
+                               $runModules[] = $module;
+                       }
+               }
+
+               return array(
+                       $this->generatorDone,
+                       $runModules,
+               );
+       }
+
+       /**
+        * Set the continuation parameter for a module
+        *
+        * @since 1.24
+        * @param ApiBase $module
+        * @param string $paramName
+        * @param string|array $paramValue
+        */
+       public function setContinueParam( ApiBase $module, $paramName, $paramValue ) {
+               $name = $module->getModuleName();
+               if ( !isset( $this->continueAllModules[$name] ) ) {
+                       throw new MWException(
+                               "Module '$name' called ApiResult::setContinueParam but was not " .
+                               'passed to ApiResult::beginContinuation'
+                       );
+               }
+               if ( !$this->continueAllModules[$name] ) {
+                       throw new MWException(
+                               "Module '$name' was not supposed to have been executed, but " .
+                               'it was executed anyway'
+                       );
+               }
+               $paramName = $module->encodeParamName( $paramName );
+               if ( is_array( $paramValue ) ) {
+                       $paramValue = join( '|', $paramValue );
+               }
+               $this->continuationData[$name][$paramName] = $paramValue;
+       }
+
+       /**
+        * Set the continuation parameter for the generator module
+        *
+        * @since 1.24
+        * @param ApiBase $module
+        * @param string $paramName
+        * @param string|array $paramValue
+        */
+       public function setGeneratorContinueParam( ApiBase $module, $paramName, $paramValue ) {
+               $name = $module->getModuleName();
+               $paramName = $module->encodeParamName( $paramName );
+               if ( is_array( $paramValue ) ) {
+                       $paramValue = join( '|', $paramValue );
+               }
+               $this->generatorContinuationData[$name][$paramName] = $paramValue;
+       }
+
+       /**
+        * Close continuation, writing the data into the result
+        *
+        * @since 1.24
+        * @param string $style 'standard' for the new style since 1.21, 'raw' for
+        *   the style used in 1.20 and earlier.
+        */
+       public function endContinuation( $style = 'standard' ) {
+               if ( $style === 'raw' ) {
+                       $key = 'query-continue';
+                       $data = array_merge_recursive(
+                               $this->continuationData, $this->generatorContinuationData
+                       );
+               } else {
+                       $key = 'continue';
+                       $data = array();
+
+                       $finishedModules = array_diff(
+                               array_keys( $this->continueAllModules ),
+                               array_keys( $this->continuationData )
+                       );
+
+                       // First, grab the non-generator-using continuation data
+                       $continuationData = array_diff_key(
+                               $this->continuationData, $this->continueGeneratedModules
+                       );
+                       foreach ( $continuationData as $module => $kvp ) {
+                               $data += $kvp;
+                       }
+
+                       // Next, handle the generator-using continuation data
+                       $continuationData = array_intersect_key(
+                               $this->continuationData, $this->continueGeneratedModules
+                       );
+                       if ( $continuationData ) {
+                               // Some modules are unfinished: include those params, and copy
+                               // the generator params.
+                               foreach ( $continuationData as $module => $kvp ) {
+                                       $data += $kvp;
+                               }
+                               $data += array_intersect_key(
+                                       $this->getMain()->getRequest()->getValues(),
+                                       array_flip( $this->generatorParams )
+                               );
+                       } else if ( $this->generatorContinuationData ) {
+                               // All the generator-using modules are complete, but the
+                               // generator isn't. Continue the generator and restart the
+                               // generator-using modules
+                               $this->generatorParams = array();
+                               foreach ( $this->generatorContinuationData as $kvp ) {
+                                       $this->generatorParams = array_merge(
+                                               $this->generatorParams, array_keys( $kvp )
+                                       );
+                                       $data += $kvp;
+                               }
+                               $finishedModules = array_diff(
+                                       $finishedModules, $this->continueGeneratedModules
+                               );
+                       } else {
+                               // Generator and prop modules are all done. Mark it so.
+                               $this->generatorDone = true;
+                       }
+
+                       // Set 'continue' if any continuation data is set or if the generator
+                       // still needs to run
+                       if ( $data || !$this->generatorDone ) {
+                               $data['continue'] =
+                                       ( $this->generatorDone ? '-' : join( '|', $this->generatorParams ) ) .
+                                       '||' . join( '|', $finishedModules );
+                       }
+               }
+               if ( $data ) {
+                       $this->disableSizeCheck();
+                       $this->addValue( null, $key, $data, ApiResult::ADD_ON_TOP );
+                       $this->enableSizeCheck();
+               }
+       }
 }
index dc593e5..04be450 100644 (file)
@@ -46,6 +46,8 @@ class ApiSetNotificationTimestamp extends ApiBase {
                $params = $this->extractRequestParams();
                $this->requireMaxOneParameter( $params, 'timestamp', 'torevid', 'newerthanrevid' );
 
+               $this->getResult()->beginContinuation( $params['continue'], array(), array() );
+
                $pageSet = $this->getPageSet();
                if ( $params['entirewatchlist'] && $pageSet->getDataSource() !== null ) {
                        $this->dieUsage(
@@ -70,22 +72,26 @@ class ApiSetNotificationTimestamp extends ApiBase {
                                $this->dieUsage( 'torevid may only be used with a single page', 'multpages' );
                        }
                        $title = reset( $pageSet->getGoodTitles() );
-                       $timestamp = Revision::getTimestampFromId( $title, $params['torevid'] );
-                       if ( $timestamp ) {
-                               $timestamp = $dbw->timestamp( $timestamp );
-                       } else {
-                               $timestamp = null;
+                       if ( $title ) {
+                               $timestamp = Revision::getTimestampFromId( $title, $params['torevid'] );
+                               if ( $timestamp ) {
+                                       $timestamp = $dbw->timestamp( $timestamp );
+                               } else {
+                                       $timestamp = null;
+                               }
                        }
                } elseif ( isset( $params['newerthanrevid'] ) ) {
                        if ( $params['entirewatchlist'] || $pageSet->getGoodTitleCount() > 1 ) {
                                $this->dieUsage( 'newerthanrevid may only be used with a single page', 'multpages' );
                        }
                        $title = reset( $pageSet->getGoodTitles() );
-                       $revid = $title->getNextRevisionID( $params['newerthanrevid'] );
-                       if ( $revid ) {
-                               $timestamp = $dbw->timestamp( Revision::getTimestampFromId( $title, $revid ) );
-                       } else {
-                               $timestamp = null;
+                       if ( $title ) {
+                               $revid = $title->getNextRevisionID( $params['newerthanrevid'] );
+                               if ( $revid ) {
+                                       $timestamp = $dbw->timestamp( Revision::getTimestampFromId( $title, $revid ) );
+                               } else {
+                                       $timestamp = null;
+                               }
                        }
                }
 
@@ -124,51 +130,55 @@ class ApiSetNotificationTimestamp extends ApiBase {
                                $result[] = $rev;
                        }
 
-                       // Now process the valid titles
-                       $lb = new LinkBatch( $pageSet->getTitles() );
-                       $dbw->update( 'watchlist', array( 'wl_notificationtimestamp' => $timestamp ),
-                               array( 'wl_user' => $user->getID(), $lb->constructSet( 'wl', $dbw ) ),
-                               __METHOD__
-                       );
-
-                       // Query the results of our update
-                       $timestamps = array();
-                       $res = $dbw->select(
-                               'watchlist',
-                               array( 'wl_namespace', 'wl_title', 'wl_notificationtimestamp' ),
-                               array( 'wl_user' => $user->getID(), $lb->constructSet( 'wl', $dbw ) ),
-                               __METHOD__
-                       );
-                       foreach ( $res as $row ) {
-                               $timestamps[$row->wl_namespace][$row->wl_title] = $row->wl_notificationtimestamp;
-                       }
+                       if ( $pageSet->getTitles() ) {
+                               // Now process the valid titles
+                               $lb = new LinkBatch( $pageSet->getTitles() );
+                               $dbw->update( 'watchlist', array( 'wl_notificationtimestamp' => $timestamp ),
+                                       array( 'wl_user' => $user->getID(), $lb->constructSet( 'wl', $dbw ) ),
+                                       __METHOD__
+                               );
 
-                       // Now, put the valid titles into the result
-                       /** @var $title Title */
-                       foreach ( $pageSet->getTitles() as $title ) {
-                               $ns = $title->getNamespace();
-                               $dbkey = $title->getDBkey();
-                               $r = array(
-                                       'ns' => intval( $ns ),
-                                       'title' => $title->getPrefixedText(),
+                               // Query the results of our update
+                               $timestamps = array();
+                               $res = $dbw->select(
+                                       'watchlist',
+                                       array( 'wl_namespace', 'wl_title', 'wl_notificationtimestamp' ),
+                                       array( 'wl_user' => $user->getID(), $lb->constructSet( 'wl', $dbw ) ),
+                                       __METHOD__
                                );
-                               if ( !$title->exists() ) {
-                                       $r['missing'] = '';
+                               foreach ( $res as $row ) {
+                                       $timestamps[$row->wl_namespace][$row->wl_title] = $row->wl_notificationtimestamp;
                                }
-                               if ( isset( $timestamps[$ns] ) && array_key_exists( $dbkey, $timestamps[$ns] ) ) {
-                                       $r['notificationtimestamp'] = '';
-                                       if ( $timestamps[$ns][$dbkey] !== null ) {
-                                               $r['notificationtimestamp'] = wfTimestamp( TS_ISO_8601, $timestamps[$ns][$dbkey] );
+
+                               // Now, put the valid titles into the result
+                               /** @var $title Title */
+                               foreach ( $pageSet->getTitles() as $title ) {
+                                       $ns = $title->getNamespace();
+                                       $dbkey = $title->getDBkey();
+                                       $r = array(
+                                               'ns' => intval( $ns ),
+                                               'title' => $title->getPrefixedText(),
+                                       );
+                                       if ( !$title->exists() ) {
+                                               $r['missing'] = '';
                                        }
-                               } else {
-                                       $r['notwatched'] = '';
+                                       if ( isset( $timestamps[$ns] ) && array_key_exists( $dbkey, $timestamps[$ns] ) ) {
+                                               $r['notificationtimestamp'] = '';
+                                               if ( $timestamps[$ns][$dbkey] !== null ) {
+                                                       $r['notificationtimestamp'] = wfTimestamp( TS_ISO_8601, $timestamps[$ns][$dbkey] );
+                                               }
+                                       } else {
+                                               $r['notwatched'] = '';
+                                       }
+                                       $result[] = $r;
                                }
-                               $result[] = $r;
                        }
 
                        $apiResult->setIndexedTagName( $result, 'page' );
                }
                $apiResult->addValue( null, $this->getModuleName(), $result );
+
+               $apiResult->endContinuation();
        }
 
        /**
@@ -214,6 +224,7 @@ class ApiSetNotificationTimestamp extends ApiBase {
                        'newerthanrevid' => array(
                                ApiBase::PARAM_TYPE => 'integer'
                        ),
+                       'continue' => '',
                );
                if ( $flags ) {
                        $result += $this->getPageSet()->getFinalParams( $flags );
@@ -229,6 +240,7 @@ class ApiSetNotificationTimestamp extends ApiBase {
                        'torevid' => 'Revision to set the notification timestamp to (one page only)',
                        'newerthanrevid' => 'Revision to set the notification timestamp newer than (one page only)',
                        'token' => 'A token previously acquired via prop=info',
+                       'continue' => 'When more results are available, use this to continue',
                );
        }
 
index 6dfb1b4..c5aa90e 100644 (file)
@@ -43,6 +43,9 @@ class ApiWatch extends ApiBase {
                }
 
                $params = $this->extractRequestParams();
+
+               $this->getResult()->beginContinuation( $params['continue'], array(), array() );
+
                $pageSet = $this->getPageSet();
                // by default we use pageset to extract the page to work on.
                // title is still supported for backward compatibility
@@ -88,6 +91,7 @@ class ApiWatch extends ApiBase {
                        $res = $this->watchTitle( $title, $user, $params, true );
                }
                $this->getResult()->addValue( null, $this->getModuleName(), $res );
+               $this->getResult()->endContinuation();
        }
 
        private function watchTitle( Title $title, User $user, array $params,
@@ -180,6 +184,7 @@ class ApiWatch extends ApiBase {
                                ApiBase::PARAM_TYPE => 'string',
                                ApiBase::PARAM_REQUIRED => true
                        ),
+                       'continue' => '',
                );
                if ( $flags ) {
                        $result += $this->getPageSet()->getFinalParams( $flags );
@@ -196,6 +201,7 @@ class ApiWatch extends ApiBase {
                        'unwatch' => 'If set the page will be unwatched rather than watched',
                        'uselang' => 'Language to show the message in',
                        'token' => 'A token previously acquired via prop=info',
+                       'continue' => 'When more results are available, use this to continue',
                );
        }
 
index 7b83990..15d7c89 100644 (file)
@@ -101,7 +101,7 @@ class DependencyWrapper {
         * @param BagOStuff $cache A cache object such as $wgMemc
         * @param string $key The cache key
         * @param int $expiry The expiry timestamp or interval in seconds
-        * @param bool|array $callback The callback for generating the value, or false
+        * @param bool|callable $callback The callback for generating the value, or false
         * @param array $callbackParams The function parameters for the callback
         * @param array $deps The dependencies to store on a cache miss. Note: these
         *    are not the dependencies used on a cache hit! Cache hits use the stored
index 1153fd2..ec36cfb 100644 (file)
@@ -1155,11 +1155,11 @@ class LCStoreDB implements LCStore {
        private $currentLang;
        private $writesDone = false;
 
-       /**
-        * @var DatabaseBase
-        */
+       /** @var DatabaseBase */
        private $dbw;
-       private $batch;
+       /** @var Array */
+       private $batch = array();
+
        private $readOnly = false;
 
        public function get( $code, $key ) {
@@ -1180,26 +1180,11 @@ class LCStoreDB implements LCStore {
        public function startWrite( $code ) {
                if ( $this->readOnly ) {
                        return;
-               }
-
-               if ( !$code ) {
+               } elseif ( !$code ) {
                        throw new MWException( __METHOD__ . ": Invalid language \"$code\"" );
                }
 
                $this->dbw = wfGetDB( DB_MASTER );
-               try {
-                       $this->dbw->begin( __METHOD__ );
-                       $this->dbw->delete( 'l10n_cache', array( 'lc_lang' => $code ), __METHOD__ );
-               } catch ( DBQueryError $e ) {
-                       if ( $this->dbw->wasReadOnlyError() ) {
-                               $this->readOnly = true;
-                               $this->dbw->rollback( __METHOD__ );
-
-                               return;
-                       } else {
-                               throw $e;
-                       }
-               }
 
                $this->currentLang = $code;
                $this->batch = array();
@@ -1208,37 +1193,42 @@ class LCStoreDB implements LCStore {
        public function finishWrite() {
                if ( $this->readOnly ) {
                        return;
+               } elseif ( is_null( $this->currentLang ) ) {
+                       throw new MWException( __CLASS__ . ': must call startWrite() before finishWrite()' );
                }
 
-               if ( $this->batch ) {
-                       $this->dbw->insert( 'l10n_cache', $this->batch, __METHOD__ );
+               $this->dbw->begin( __METHOD__ );
+               try {
+                       $this->dbw->delete( 'l10n_cache',
+                               array( 'lc_lang' => $this->currentLang ), __METHOD__ );
+                       foreach ( array_chunk( $this->batch, 500 ) as $rows ) {
+                               $this->dbw->insert( 'l10n_cache', $rows, __METHOD__ );
+                       }
+                       $this->writesDone = true;
+               } catch ( DBQueryError $e ) {
+                       if ( $this->dbw->wasReadOnlyError() ) {
+                               $this->readOnly = true; // just avoid site down time
+                       } else {
+                               throw $e;
+                       }
                }
-
                $this->dbw->commit( __METHOD__ );
+
                $this->currentLang = null;
-               $this->dbw = null;
                $this->batch = array();
-               $this->writesDone = true;
        }
 
        public function set( $key, $value ) {
                if ( $this->readOnly ) {
                        return;
-               }
-
-               if ( is_null( $this->currentLang ) ) {
-                       throw new MWException( __CLASS__ . ': must call startWrite() before calling set()' );
+               } elseif ( is_null( $this->currentLang ) ) {
+                       throw new MWException( __CLASS__ . ': must call startWrite() before set()' );
                }
 
                $this->batch[] = array(
                        'lc_lang' => $this->currentLang,
                        'lc_key' => $key,
                        'lc_value' => $this->dbw->encodeBlob( serialize( $value ) ) );
-
-               if ( count( $this->batch ) >= 100 ) {
-                       $this->dbw->insert( 'l10n_cache', $this->batch, __METHOD__ );
-                       $this->batch = array();
-               }
        }
 }
 
index 36d2731..d2c504a 100644 (file)
@@ -101,7 +101,7 @@ class RedisConnectionPool {
                        $options['connectTimeout'] = 1;
                }
                if ( !isset( $options['readTimeout'] ) ) {
-                       $options['readTimeout'] = 31; // handles up to 30 second blocking commands
+                       $options['readTimeout'] = 1;
                }
                if ( !isset( $options['persistent'] ) ) {
                        $options['persistent'] = false;
@@ -120,7 +120,7 @@ class RedisConnectionPool {
         *                      Optional, default is 1 second.
         *   - readTimeout    : The timeout for operation reads, in seconds.
         *                      Commands like BLPOP can fail if told to wait longer than this.
-        *                      Optional, default is 60 seconds.
+        *                      Optional, default is 1 second.
         *   - persistent     : Set this to true to allow connections to persist across
         *                      multiple web requests. False by default.
         *   - password       : The authentication password, will be sent to Redis in clear text.
@@ -342,6 +342,16 @@ class RedisConnectionPool {
                return true;
        }
 
+       /**
+        * Adjust or reset the connection handle read timeout value
+        *
+        * @param Redis $conn
+        * @param integer $timeout Optional
+        */
+       public function resetTimeout( Redis $conn, $timeout = null ) {
+               $conn->setOption( Redis::OPT_READ_TIMEOUT, $timeout ?: $this->readTimeout );
+       }
+
        /**
         * Make sure connections are closed for sanity
         */
@@ -401,17 +411,34 @@ class RedisConnRef {
        public function __call( $name, $arguments ) {
                $conn = $this->conn; // convenience
 
+               // Work around https://github.com/nicolasff/phpredis/issues/70
+               $lname = strtolower( $name );
+               if ( ( $lname === 'blpop' || $lname == 'brpop' )
+                       && is_array( $arguments[0] ) && isset( $arguments[1] )
+               ) {
+                       $this->pool->resetTimeout( $conn, $arguments[1] + 1 );
+               } elseif ( $lname === 'brpoplpush' && isset( $arguments[2] ) ) {
+                       $this->pool->resetTimeout( $conn, $arguments[2] + 1 );
+               }
+
                $conn->clearLastError();
-               $res = call_user_func_array( array( $conn, $name ), $arguments );
-               if ( preg_match( '/^ERR operation not permitted\b/', $conn->getLastError() ) ) {
-                       $this->pool->reauthenticateConnection( $this->server, $conn );
-                       $conn->clearLastError();
+               try {
                        $res = call_user_func_array( array( $conn, $name ), $arguments );
-                       wfDebugLog( 'redis', "Used automatic re-authentication for method '$name'." );
+                       if ( preg_match( '/^ERR operation not permitted\b/', $conn->getLastError() ) ) {
+                               $this->pool->reauthenticateConnection( $this->server, $conn );
+                               $conn->clearLastError();
+                               $res = call_user_func_array( array( $conn, $name ), $arguments );
+                               wfDebugLog( 'redis', "Used automatic re-authentication for method '$name'." );
+                       }
+               } catch ( RedisException $e ) {
+                       $this->pool->resetTimeout( $conn ); // restore
+                       throw $e;
                }
 
                $this->lastError = $conn->getLastError() ?: $this->lastError;
 
+               $this->pool->resetTimeout( $conn ); // restore
+
                return $res;
        }
 
index b5b4d13..e077c77 100644 (file)
@@ -460,7 +460,7 @@ abstract class ContentHandler {
         * Apply import transformation (per default, returns $blob unchanged).
         * This gives subclasses an opportunity to transform data blobs on import.
         *
-        * @singe 1.24
+        * @since 1.24
         *
         * @param string $blob
         * @param string|null $format
index 699ab71..7d8fbe9 100644 (file)
@@ -1022,7 +1022,7 @@ abstract class DatabaseBase implements IDatabase, DatabaseType {
                $this->mLastQuery = $sql;
                if ( !$this->mDoneWrites && $this->isWriteQuery( $sql ) ) {
                        # Set a flag indicating that writes have been done
-                       wfDebug( __METHOD__ . ": Writes done: $sql\n" );
+                       wfDebug( __METHOD__ . ': Writes done: ' . DatabaseBase::generalizeSQL( $sql ) . "\n" );
                        $this->mDoneWrites = true;
                }
 
index 1d05bf6..be01f1a 100644 (file)
@@ -1004,6 +1004,11 @@ class DatabaseMssql extends DatabaseBase {
                        return false;
                }
 
+               if ( $schema === false ) {
+                       global $wgDBmwschema;
+                       $schema = $wgDBmwschema;
+               }
+
                $res = $this->query( "SELECT 1 FROM INFORMATION_SCHEMA.TABLES
                        WHERE TABLE_TYPE = 'BASE TABLE'
                        AND TABLE_SCHEMA = '$schema' AND TABLE_NAME = '$table'" );
@@ -1295,9 +1300,6 @@ class DatabaseMssql extends DatabaseBase {
                        : array();
        }
 
-       /**
-        * @void
-        */
        private function populateColumnCaches() {
                $res = $this->select( 'INFORMATION_SCHEMA.COLUMNS', '*',
                        array(
@@ -1344,7 +1346,7 @@ class DatabaseMssql extends DatabaseBase {
                        // Used internally, we want the schema split off from the table name and returned
                        // as a list with 3 elements (database, schema, table)
                        $table = explode( '.', $table );
-                       if ( count( $table ) == 2 ) {
+                       while ( count( $table ) < 3 ) {
                                array_unshift( $table, false );
                        }
                }
index 3d7267a..fe5fa1f 100644 (file)
@@ -827,6 +827,8 @@ __INDEXATTR__;
         * In Postgres when using FOR UPDATE, only the main table and tables that are inner joined
         * can be locked. That means tables in an outer join cannot be FOR UPDATE locked. Trying to do
         * so causes a DB error. This wrapper checks which tables can be locked and adjusts it accordingly.
+        * 
+        * MySQL uses "ORDER BY NULL" as an optimization hint, but that syntax is illegal in PostgreSQL.
         */
        function selectSQLText( $table, $vars, $conds = '', $fname = __METHOD__,
                $options = array(), $join_conds = array()
@@ -842,6 +844,10 @@ __INDEXATTR__;
                                        }
                                }
                        }
+
+                       if ( isset( $options['ORDER BY'] ) && $options['ORDER BY'] == 'NULL' ) {
+                               unset( $options['ORDER BY'] );
+                       }
                }
 
                return parent::selectSQLText( $table, $vars, $conds, $fname, $options, $join_conds );
index 6219573..3a4d829 100644 (file)
@@ -71,7 +71,7 @@ class LBFactorySingle extends LBFactory {
        }
 
        /**
-        * @param string|array $callback
+        * @param string|callable $callback
         * @param array $params
         */
        function forEachLB( $callback, $params = array() ) {
index 2117010..0cea658 100644 (file)
@@ -513,6 +513,7 @@ class MWDebug {
                $result->setIndexedTagName( $debugInfo['debugLog'], 'msg' );
                $result->setIndexedTagName( $debugInfo['queries'], 'query' );
                $result->setIndexedTagName( $debugInfo['includes'], 'queries' );
+               $result->setIndexedTagName( $debugInfo['profile'], 'function' );
                $result->addValue( null, 'debuginfo', $debugInfo );
        }
 
index ac8f758..db7318f 100644 (file)
@@ -60,6 +60,8 @@ class TableDiffFormatter extends DiffFormatter {
         * @return string
         */
        protected function blockHeader( $xbeg, $xlen, $ybeg, $ylen ) {
+               // '<!--LINE \d+ -->' get replaced by a localised line number
+               // in DifferenceEngine::localiseLineNumbers
                $r = '<tr><td colspan="2" class="diff-lineno"><!--LINE ' . $xbeg . "--></td>\n" .
                        '<td colspan="2" class="diff-lineno"><!--LINE ' . $ybeg . "--></td></tr>\n";
 
index 3f81a94..e7c1f6f 100644 (file)
@@ -792,7 +792,7 @@ class FSFileOpHandle extends FileBackendStoreOpHandle {
        /**
         * @param FSFileBackend $backend
         * @param array $params
-        * @param callback $call
+        * @param callable $call
         * @param string $cmd
         * @param int|null $chmodPath
         */
index 4c250ba..8598005 100644 (file)
@@ -1583,7 +1583,7 @@ class FileRepo {
         * This only acts on the current version of files, not any old versions.
         * May use either the database or the filesystem.
         *
-        * @param array|string $callback
+        * @param callable $callback
         * @return void
         */
        public function enumFiles( $callback ) {
@@ -1594,7 +1594,7 @@ class FileRepo {
         * Call a callback function for every public file in the repository.
         * May use either the database or the filesystem.
         *
-        * @param array|string $callback
+        * @param callable $callback
         * @return void
         */
        protected function enumFilesInStorage( $callback ) {
index 7f25a00..6924f0a 100644 (file)
@@ -575,7 +575,7 @@ class ForeignAPIRepo extends FileRepo {
        }
 
        /**
-        * @param array|string $callback
+        * @param callable $callback
         * @throws MWException
         */
        function enumFiles( $callback ) {
index 103e78e..65637df 100644 (file)
@@ -367,6 +367,9 @@ class RepoGroup {
         * @return bool
         */
        function forEachForeignRepo( $callback, $params = array() ) {
+               if ( !$this->reposInitialised ) {
+                       $this->initialiseRepos();
+               }
                foreach ( $this->foreignRepos as $repo ) {
                        $args = array_merge( array( $repo ), $params );
                        if ( call_user_func_array( $callback, $args ) ) {
@@ -382,6 +385,9 @@ class RepoGroup {
         * @return bool
         */
        function hasForeignRepos() {
+               if ( !$this->reposInitialised ) {
+                       $this->initialiseRepos();
+               }
                return (bool)$this->foreignRepos;
        }
 
index 1103e38..e970e38 100644 (file)
@@ -149,6 +149,9 @@ abstract class File {
        /** @var string Required Repository class type */
        protected $repoClass = 'FileRepo';
 
+       /** @var array Cache of tmp filepaths pointing to generated bucket thumbnails, keyed by width */
+       protected $tmpBucketedThumbCache = array();
+
        /**
         * Call this constructor from child classes.
         *
@@ -456,6 +459,50 @@ abstract class File {
                return false;
        }
 
+       /**
+        * Return the smallest bucket from $wgThumbnailBuckets which is at least
+        * $wgThumbnailMinimumBucketDistance larger than $desiredWidth. The returned bucket, if any,
+        * will always be bigger than $desiredWidth.
+        *
+        * @param int $desiredWidth
+        * @param int $page
+        * @return bool|int
+        */
+       public function getThumbnailBucket( $desiredWidth, $page = 1 ) {
+               global $wgThumbnailBuckets, $wgThumbnailMinimumBucketDistance;
+
+               $imageWidth = $this->getWidth( $page );
+
+               if ( $imageWidth === false ) {
+                       return false;
+               }
+
+               if ( $desiredWidth > $imageWidth ) {
+                       return false;
+               }
+
+               if ( !$wgThumbnailBuckets ) {
+                       return false;
+               }
+
+               $sortedBuckets = $wgThumbnailBuckets;
+
+               sort( $sortedBuckets );
+
+               foreach ( $sortedBuckets as $bucket ) {
+                       if ( $bucket > $imageWidth ) {
+                               return false;
+                       }
+
+                       if ( $bucket - $wgThumbnailMinimumBucketDistance > $desiredWidth ) {
+                               return $bucket;
+                       }
+               }
+
+               // Image is bigger than any available bucket
+               return false;
+       }
+
        /**
         * Returns ID or name of user who uploaded the file
         * STUB
@@ -877,9 +924,9 @@ abstract class File {
                        return null;
                }
                $extension = $this->getExtension();
-               list( $thumbExt, ) = $this->handler->getThumbType(
+               list( $thumbExt, ) = $this->getHandler()->getThumbType(
                        $extension, $this->getMimeType(), $params );
-               $thumbName = $this->handler->makeParamString( $params ) . '-' . $name;
+               $thumbName = $this->getHandler()->makeParamString( $params ) . '-' . $name;
                if ( $thumbExt != $extension ) {
                        $thumbName .= ".$thumbExt";
                }
@@ -947,7 +994,7 @@ abstract class File {
         * @return MediaTransformOutput|bool False on failure
         */
        function transform( $params, $flags = 0 ) {
-               global $wgUseSquid, $wgIgnoreImageErrors, $wgThumbnailEpoch;
+               global $wgThumbnailEpoch;
 
                wfProfileIn( __METHOD__ );
                do {
@@ -1004,64 +1051,221 @@ abstract class File {
                                } elseif ( $flags & self::RENDER_FORCE ) {
                                        wfDebug( __METHOD__ . " forcing rendering per flag File::RENDER_FORCE\n" );
                                }
-                       }
 
-                       // If the backend is ready-only, don't keep generating thumbnails
-                       // only to return transformation errors, just return the error now.
-                       if ( $this->repo->getReadOnlyReason() !== false ) {
-                               $thumb = $this->transformErrorOutput( $thumbPath, $thumbUrl, $params, $flags );
-                               break;
+                               // If the backend is ready-only, don't keep generating thumbnails
+                               // only to return transformation errors, just return the error now.
+                               if ( $this->repo->getReadOnlyReason() !== false ) {
+                                       $thumb = $this->transformErrorOutput( $thumbPath, $thumbUrl, $params, $flags );
+                                       break;
+                               }
                        }
 
-                       // Create a temp FS file with the same extension and the thumbnail
-                       $thumbExt = FileBackend::extensionFromPath( $thumbPath );
-                       $tmpFile = TempFSFile::factory( 'transform_', $thumbExt );
+                       $tmpFile = $this->makeTransformTmpFile( $thumbPath );
+
                        if ( !$tmpFile ) {
                                $thumb = $this->transformErrorOutput( $thumbPath, $thumbUrl, $params, $flags );
-                               break;
+                       } else {
+                               $thumb = $this->generateAndSaveThumb( $tmpFile, $params, $flags );
                        }
-                       $tmpThumbPath = $tmpFile->getPath(); // path of 0-byte temp file
-
-                       // Actually render the thumbnail...
-                       wfProfileIn( __METHOD__ . '-doTransform' );
-                       $thumb = $handler->doTransform( $this, $tmpThumbPath, $thumbUrl, $params );
-                       wfProfileOut( __METHOD__ . '-doTransform' );
-                       $tmpFile->bind( $thumb ); // keep alive with $thumb
-
-                       if ( !$thumb ) { // bad params?
-                               $thumb = false;
-                       } elseif ( $thumb->isError() ) { // transform error
-                               $this->lastError = $thumb->toText();
-                               // Ignore errors if requested
-                               if ( $wgIgnoreImageErrors && !( $flags & self::RENDER_NOW ) ) {
-                                       $thumb = $handler->getTransform( $this, $tmpThumbPath, $thumbUrl, $params );
-                               }
-                       } elseif ( $this->repo && $thumb->hasFile() && !$thumb->fileIsSource() ) {
-                               // Copy the thumbnail from the file system into storage...
-                               $disposition = $this->getThumbDisposition( $thumbName );
-                               $status = $this->repo->quickImport( $tmpThumbPath, $thumbPath, $disposition );
-                               if ( $status->isOK() ) {
-                                       $thumb->setStoragePath( $thumbPath );
-                               } else {
-                                       $thumb = $this->transformErrorOutput( $thumbPath, $thumbUrl, $params, $flags );
+               } while ( false );
+
+               wfProfileOut( __METHOD__ );
+
+               return is_object( $thumb ) ? $thumb : false;
+       }
+
+       /**
+        * Generates a thumbnail according to the given parameters and saves it to storage
+        * @param TempFSFile $tmpFile Temporary file where the rendered thumbnail will be saved
+        * @param array $transformParams
+        * @param int $flags
+        * @return bool|MediaTransformOutput
+        */
+       public function generateAndSaveThumb( $tmpFile, $transformParams, $flags ) {
+               global $wgUseSquid, $wgIgnoreImageErrors;
+
+               $handler = $this->getHandler();
+
+               $normalisedParams = $transformParams;
+               $handler->normaliseParams( $this, $normalisedParams );
+
+               $thumbName = $this->thumbName( $normalisedParams );
+               $thumbUrl = $this->getThumbUrl( $thumbName );
+               $thumbPath = $this->getThumbPath( $thumbName ); // final thumb path
+
+               $tmpThumbPath = $tmpFile->getPath();
+
+               if ( $handler->supportsBucketing() ) {
+                       $this->generateBucketsIfNeeded( $normalisedParams, $flags );
+               }
+
+               // Actually render the thumbnail...
+               wfProfileIn( __METHOD__ . '-doTransform' );
+               $thumb = $handler->doTransform( $this, $tmpThumbPath, $thumbUrl, $transformParams );
+               wfProfileOut( __METHOD__ . '-doTransform' );
+               $tmpFile->bind( $thumb ); // keep alive with $thumb
+
+               if ( !$thumb ) { // bad params?
+                       $thumb = false;
+               } elseif ( $thumb->isError() ) { // transform error
+                       $this->lastError = $thumb->toText();
+                       // Ignore errors if requested
+                       if ( $wgIgnoreImageErrors && !( $flags & self::RENDER_NOW ) ) {
+                               $thumb = $handler->getTransform( $this, $tmpThumbPath, $thumbUrl, $transformParams );
+                       }
+               } elseif ( $this->repo && $thumb->hasFile() && !$thumb->fileIsSource() ) {
+                       // Copy the thumbnail from the file system into storage...
+                       $disposition = $this->getThumbDisposition( $thumbName );
+                       $status = $this->repo->quickImport( $tmpThumbPath, $thumbPath, $disposition );
+                       if ( $status->isOK() ) {
+                               $thumb->setStoragePath( $thumbPath );
+                       } else {
+                               $thumb = $this->transformErrorOutput( $thumbPath, $thumbUrl, $transformParams, $flags );
+                       }
+                       // Give extensions a chance to do something with this thumbnail...
+                       wfRunHooks( 'FileTransformed', array( $this, $thumb, $tmpThumbPath, $thumbPath ) );
+               }
+
+               // Purge. Useful in the event of Core -> Squid connection failure or squid
+               // purge collisions from elsewhere during failure. Don't keep triggering for
+               // "thumbs" which have the main image URL though (bug 13776)
+               if ( $wgUseSquid ) {
+                       if ( !$thumb || $thumb->isError() || $thumb->getUrl() != $this->getURL() ) {
+                               SquidUpdate::purge( array( $thumbUrl ) );
+                       }
+               }
+
+               return $thumb;
+       }
+
+       /**
+        * Generates chained bucketed thumbnails if needed
+        * @param array $params
+        * @param int $flags
+        * @return bool Whether at least one bucket was generated
+        */
+       protected function generateBucketsIfNeeded( $params, $flags = 0 ) {
+               if ( !$this->repo
+                       || !isset( $params['physicalWidth'] )
+                       || !isset( $params['physicalHeight'] )
+                       || !( $bucket = $this->getThumbnailBucket( $params['physicalWidth'] ) )
+                       || $bucket == $params['physicalWidth'] ) {
+                       return false;
+               }
+
+               $bucketPath = $this->getBucketThumbPath( $bucket );
+
+               if ( $this->repo->fileExists( $bucketPath ) ) {
+                       return false;
+               }
+
+               $params['physicalWidth'] = $bucket;
+               $params['width'] = $bucket;
+
+               $params = $this->getHandler()->sanitizeParamsForBucketing( $params );
+
+               $bucketName = $this->getBucketThumbName( $bucket );
+
+               $tmpFile = $this->makeTransformTmpFile( $bucketPath );
+
+               if ( !$tmpFile ) {
+                       return false;
+               }
+
+               $thumb = $this->generateAndSaveThumb( $tmpFile, $params, $flags );
+
+               if ( !$thumb || $thumb->isError() ) {
+                       return false;
+               }
+
+               $this->tmpBucketedThumbCache[ $bucket ] = $tmpFile->getPath();
+               // For the caching to work, we need to make the tmp file survive as long as
+               // this object exists
+               $tmpFile->bind( $this );
+
+               return true;
+       }
+
+       /**
+        * Returns the most appropriate source image for the thumbnail, given a target thumbnail size
+        * @param array $params
+        * @return array source path and width/height of the source
+        */
+       public function getThumbnailSource( $params ) {
+               if ( $this->repo
+                       && $this->getHandler()->supportsBucketing()
+                       && isset( $params['physicalWidth'] )
+                       && $bucket = $this->getThumbnailBucket( $params['physicalWidth'] )
+               ) {
+                       if ( $this->getWidth() != 0 ) {
+                               $bucketHeight = round( $this->getHeight() * ( $bucket / $this->getWidth() ) );
+                       } else {
+                               $bucketHeight = 0;
+                       }
+
+                       // Try to avoid reading from storage if the file was generated by this script
+                       if ( isset( $this->tmpBucketedThumbCache[ $bucket ] ) ) {
+                               $tmpPath = $this->tmpBucketedThumbCache[ $bucket ];
+
+                               if ( file_exists( $tmpPath ) ) {
+                                       return array(
+                                               'path' => $tmpPath,
+                                               'width' => $bucket,
+                                               'height' => $bucketHeight
+                                       );
                                }
-                               // Give extensions a chance to do something with this thumbnail...
-                               wfRunHooks( 'FileTransformed', array( $this, $thumb, $tmpThumbPath, $thumbPath ) );
                        }
 
-                       // Purge. Useful in the event of Core -> Squid connection failure or squid
-                       // purge collisions from elsewhere during failure. Don't keep triggering for
-                       // "thumbs" which have the main image URL though (bug 13776)
-                       if ( $wgUseSquid ) {
-                               if ( !$thumb || $thumb->isError() || $thumb->getUrl() != $this->getURL() ) {
-                                       SquidUpdate::purge( array( $thumbUrl ) );
+                       $bucketPath = $this->getBucketThumbPath( $bucket );
+
+                       if ( $this->repo->fileExists( $bucketPath ) ) {
+                               $fsFile = $this->repo->getLocalReference( $bucketPath );
+
+                               if ( $fsFile ) {
+                                       return array(
+                                               'path' => $fsFile->getPath(),
+                                               'width' => $bucket,
+                                               'height' => $bucketHeight
+                                       );
                                }
                        }
-               } while ( false );
+               }
 
-               wfProfileOut( __METHOD__ );
+               // Original file
+               return array(
+                       'path' => $this->getLocalRefPath(),
+                       'width' => $this->getWidth(),
+                       'height' => $this->getHeight()
+               );
+       }
 
-               return is_object( $thumb ) ? $thumb : false;
+       /**
+        * Returns the repo path of the thumb for a given bucket
+        * @param int $bucket
+        * @return string
+        */
+       protected function getBucketThumbPath( $bucket ) {
+               $thumbName = $this->getBucketThumbName( $bucket );
+               return $this->getThumbPath( $thumbName );
+       }
+
+       /**
+        * Returns the name of the thumb for a given bucket
+        * @param int $bucket
+        * @return string
+        */
+       protected function getBucketThumbName( $bucket ) {
+               return $this->thumbName( array( 'physicalWidth' => $bucket ) );
+       }
+
+       /**
+        * Creates a temp FS file with the same extension and the thumbnail
+        * @param string $thumbPath Thumbnail path
+        * @returns TempFSFile
+        */
+       protected function makeTransformTmpFile( $thumbPath ) {
+               $thumbExt = FileBackend::extensionFromPath( $thumbPath );
+               return TempFSFile::factory( 'transform_', $thumbExt );
        }
 
        /**
@@ -1741,7 +1945,7 @@ abstract class File {
                        return false;
                }
 
-               return $this->handler->getImageSize( $this, $filePath );
+               return $this->getHandler()->getImageSize( $this, $filePath );
        }
 
        /**
index 8d2b949..837a731 100644 (file)
@@ -258,6 +258,14 @@ abstract class ImageGalleryBase extends ContextSource {
                array_unshift( $this->mImages, array( &$title, $html, $alt, $link, $handlerOpts ) );
        }
 
+       /**
+        * Returns the list of images this gallery contains
+        * @return array
+        */
+       public function getImages() {
+               return $this->mImages;
+       }
+
        /**
         * isEmpty() returns true if the gallery contains no images
         * @return bool
old mode 100755 (executable)
new mode 100644 (file)
index 296de96..3334694 100644 (file)
@@ -171,6 +171,12 @@ class HTMLForm extends ContextSource {
 
        protected $mWrapperLegend = false;
 
+       /**
+        * Salt for the edit token.
+        * @var string|array
+        */
+       protected $mTokenSalt = '';
+
        /**
         * If true, sections that contain both fields and subsections will
         * render their subsections before their fields.
@@ -397,7 +403,7 @@ class HTMLForm extends ContextSource {
                                // Session tokens for logged-out users have no security value.
                                // However, if the user gave one, check it in order to give a nice
                                // "session expired" error instead of "permission denied" or such.
-                               $submit = $this->getUser()->matchEditToken( $editToken );
+                               $submit = $this->getUser()->matchEditToken( $editToken, $this->mTokenSalt );
                        } else {
                                $submit = true;
                        }
@@ -434,9 +440,12 @@ class HTMLForm extends ContextSource {
         * Validate all the fields, and call the submission callback
         * function if everything is kosher.
         * @throws MWException
-        * @return mixed Bool true == Successful submission, Bool false
-        *     == No submission attempted, anything else == Error to
-        *     display.
+        * @return bool|string|array|Status
+        *     - Bool true or a good Status object indicates success,
+        *     - Bool false indicates no submission was attempted,
+        *     - Anything else indicates failure. The value may be a fatal Status
+        *       object, an HTML string, or an array of arrays (message keys and
+        *       params) or strings (message keys)
         */
        function trySubmit() {
                $this->mWasSubmitted = true;
@@ -503,10 +512,9 @@ class HTMLForm extends ContextSource {
         * Set a callback to a function to do something with the form
         * once it's been successfully validated.
         *
-        * @param string $cb Function name.  The function will be passed
-        *     the output from HTMLForm::filterDataForSubmit, and must
-        *     return Bool true on success, Bool false if no submission
-        *     was attempted, or String HTML output to display on error.
+        * @param callable $cb The function will be passed the output from
+        *   HTMLForm::filterDataForSubmit and this HTMLForm object, and must
+        *   return as documented for HTMLForm::trySubmit
         *
         * @return HTMLForm $this for chaining calls (since 1.20)
         */
@@ -726,6 +734,21 @@ class HTMLForm extends ContextSource {
                return $this;
        }
 
+       /**
+        * Set the salt for the edit token.
+        *
+        * Only useful when the method is "post".
+        *
+        * @since 1.24
+        * @param string|array Salt to use
+        * @return HTMLForm $this for chaining calls
+        */
+       public function setTokenSalt( $salt ) {
+               $this->mTokenSalt = $salt;
+
+               return $this;
+       }
+
        /**
         * Display the form (sending to the context's OutputPage object), with an
         * appropriate error message or stack of messages, and any validation errors, etc.
@@ -734,7 +757,7 @@ class HTMLForm extends ContextSource {
         * Moreover, when doing method chaining this should be the very last method
         * call just after prepareForm().
         *
-        * @param mixed $submitResult Mixed output from HTMLForm::trySubmit()
+        * @param bool|string|array|Status $submitResult Output from HTMLForm::trySubmit()
         *
         * @return Nothing, should be last call
         */
@@ -745,7 +768,7 @@ class HTMLForm extends ContextSource {
        /**
         * Returns the raw HTML generated by the form
         *
-        * @param mixed $submitResult Mixed output from HTMLForm::trySubmit()
+        * @param bool|string|array|Status $submitResult Output from HTMLForm::trySubmit()
         *
         * @return string
         */
@@ -821,7 +844,7 @@ class HTMLForm extends ContextSource {
                if ( $this->getMethod() == 'post' ) {
                        $html .= Html::hidden(
                                'wpEditToken',
-                               $this->getUser()->getEditToken(),
+                               $this->getUser()->getEditToken( $this->mTokenSalt ),
                                array( 'id' => 'wpEditToken' )
                        ) . "\n";
                        $html .= Html::hidden( 'title', $this->getTitle()->getPrefixedText() ) . "\n";
index 19b2f7c..65176dd 100644 (file)
@@ -26,7 +26,8 @@ class HTMLSelectAndOtherField extends HTMLSelectField {
                        throw new MWException( 'HTMLSelectAndOtherField called without any options' );
                }
                if ( !in_array( 'other', $this->mOptions, true ) ) {
-                       $this->mOptions[$params['other']] = 'other';
+                       // Have 'other' always as first element
+                       $this->mOptions = array( $params['other'] => 'other' ) + $this->mOptions;
                }
                $this->mFlatOptions = self::flattenOptions( $this->getOptions() );
 
index c32b445..2bf9f8b 100644 (file)
@@ -27,8 +27,10 @@ class HTMLSelectField extends HTMLFormField {
                        $select->setAttribute( 'disabled', 'disabled' );
                }
 
-               if ( isset( $this->mParams['tabindex'] ) ) {
-                       $select->setAttribute( 'tabindex', $this->mParams['tabindex'] );
+               $allowedParams = array( 'tabindex', 'size' );
+               $customParams = $this->getAttributes( $allowedParams );
+               foreach( $customParams as $name => $value ) {
+                       $select->setAttribute( $name, $value );
                }
 
                if ( $this->mClass !== '' ) {
index a001c43..cbf7d12 100644 (file)
@@ -12,7 +12,8 @@ class HTMLSelectOrOtherField extends HTMLTextField {
                                isset( $params['other'] )
                                        ? $params['other']
                                        : wfMessage( 'htmlform-selectorother-other' )->text();
-                       $this->mOptions[$msg] = 'other';
+                       // Have 'other' always as first element
+                       $this->mOptions = array( $msg => 'other' ) + $this->mOptions;
                }
 
        }
index 82a358e..28dac46 100644 (file)
@@ -476,7 +476,8 @@ abstract class DatabaseUpdater {
        public function updateRowExists( $key ) {
                $row = $this->db->selectRow(
                        'updatelog',
-                       '1',
+                       # Bug 65813
+                       '1 AS X',
                        array( 'ul_key' => $key ),
                        __METHOD__
                );
index 88478f4..4f40693 100644 (file)
@@ -38,9 +38,6 @@
  */
 abstract class Installer {
 
-       // This is the absolute minimum PHP version we can support
-       const MINIMUM_PHP_VERSION = '5.3.2';
-
        /**
         * The oldest version of PCRE we can support.
         *
@@ -380,26 +377,15 @@ abstract class Installer {
                        $this->settings[$var] = $GLOBALS[$var];
                }
 
-               $compiledDBs = array();
+               $this->compiledDBs = array();
                foreach ( self::getDBTypes() as $type ) {
                        $installer = $this->getDBInstaller( $type );
 
                        if ( !$installer->isCompiled() ) {
                                continue;
                        }
-                       $compiledDBs[] = $type;
-
-                       $defaults = $installer->getGlobalDefaults();
-
-                       foreach ( $installer->getGlobalNames() as $var ) {
-                               if ( isset( $defaults[$var] ) ) {
-                                       $this->settings[$var] = $defaults[$var];
-                               } else {
-                                       $this->settings[$var] = $GLOBALS[$var];
-                               }
-                       }
+                       $this->compiledDBs[] = $type;
                }
-               $this->compiledDBs = $compiledDBs;
 
                $this->parserTitle = Title::newFromText( 'Installer' );
                $this->parserOptions = new ParserOptions; // language will be wrong :(
@@ -429,25 +415,17 @@ abstract class Installer {
         * @return Status
         */
        public function doEnvironmentChecks() {
-               $phpVersion = phpversion();
-               if ( version_compare( $phpVersion, self::MINIMUM_PHP_VERSION, '>=' ) ) {
-                       $this->showMessage( 'config-env-php', $phpVersion );
-                       $good = true;
-               } else {
-                       $this->showMessage( 'config-env-php-toolow', $phpVersion, self::MINIMUM_PHP_VERSION );
-                       $good = false;
-               }
+               // Php version has already been checked by entry scripts
+               // Show message here for information purposes
+               $this->showMessage( 'config-env-php', PHP_VERSION );
 
+               $good = true;
                // Must go here because an old version of PCRE can prevent other checks from completing
-               if ( $good ) {
-                       list( $pcreVersion ) = explode( ' ', PCRE_VERSION, 2 );
-                       if ( version_compare( $pcreVersion, self::MINIMUM_PCRE_VERSION, '<' ) ) {
-                               $this->showError( 'config-pcre-old', self::MINIMUM_PCRE_VERSION, $pcreVersion );
-                               $good = false;
-                       }
-               }
-
-               if ( $good ) {
+               list( $pcreVersion ) = explode( ' ', PCRE_VERSION, 2 );
+               if ( version_compare( $pcreVersion, self::MINIMUM_PCRE_VERSION, '<' ) ) {
+                       $this->showError( 'config-pcre-old', self::MINIMUM_PCRE_VERSION, $pcreVersion );
+                       $good = false;
+               } else {
                        foreach ( $this->envChecks as $check ) {
                                $status = $this->$check();
                                if ( $status === false ) {
@@ -726,11 +704,15 @@ abstract class Installer {
 
        /**
         * Environment check for register_globals.
+        * Prevent installation if enabled
         */
        protected function envCheckRegisterGlobals() {
                if ( wfIniGetBool( 'register_globals' ) ) {
-                       $this->showMessage( 'config-register-globals' );
+                       $this->showMessage( 'config-register-globals-error' );
+                       return false;
                }
+
+               return true;
        }
 
        /**
@@ -1531,8 +1513,8 @@ abstract class Installer {
        /**
         * Actually perform the installation.
         *
-        * @param array $startCB A callback array for the beginning of each step
-        * @param array $endCB A callback array for the end of each step
+        * @param callable $startCB A callback array for the beginning of each step
+        * @param callable $endCB A callback array for the end of each step
         *
         * @return array Array of Status objects
         */
@@ -1747,7 +1729,7 @@ abstract class Installer {
        /**
         * Add an installation step following the given step.
         *
-        * @param array $callback A valid installation callback array, in this form:
+        * @param callable $callback A valid installation callback array, in this form:
         *    array( 'name' => 'some-unique-name', 'callback' => array( $obj, 'function' ) );
         * @param string $findStep The step to find. Omit to put the step at the beginning
         */
index 51db148..83681b6 100644 (file)
@@ -218,6 +218,7 @@ class MssqlInstaller extends DatabaseInstaller {
                                'password' => $password,
                                'dbname' => false,
                                'flags' => 0,
+                               'schema' => $this->getVar( 'wgDBmwschema' ),
                                'tablePrefix' => $this->getVar( 'wgDBprefix' ) ) );
                        $db->prepareStatements( false );
                        $db->scrollableCursor( false );
@@ -648,6 +649,14 @@ class MssqlInstaller extends DatabaseInstaller {
                return $status;
        }
 
+       public function getGlobalDefaults() {
+               // The default $wgDBmwschema is null, which breaks Postgres and other DBMSes that require
+               // the use of a schema, so we need to set it here
+               return array(
+                       'wgDBmwschema' => 'mediawiki',
+               );
+       }
+
        /**
         * Try to see if the login exists
         * @param string $user Username to check
index 0054573..d590a70 100644 (file)
@@ -42,6 +42,88 @@ class MssqlUpdater extends DatabaseUpdater {
 
                        // 1.24
                        array( 'addField', 'page', 'page_lang', 'patch-page-page_lang.sql'),
+                       // Constraint updates
+                       array( 'updateConstraints', 'category_types', 'categorylinks', 'cl_type' ),
+                       array( 'updateConstraints', 'major_mime', 'filearchive', 'fa_major_mime' ),
+                       array( 'updateConstraints', 'media_type', 'filearchive', 'fa_media_type' ),
+                       array( 'updateConstraints', 'major_mime', 'oldimage', 'oi_major_mime' ),
+                       array( 'updateConstraints', 'media_type', 'oldimage', 'oi_media_type' ),
+                       array( 'updateConstraints', 'major_mime', 'image', 'img_major_mime' ),
+                       array( 'updateConstraints', 'media_type', 'image', 'img_media_type' ),
+                       array( 'updateConstraints', 'media_type', 'uploadstash', 'us_media_type' ),
+                       // END: Constraint updates
                );
        }
+
+       /**
+        * Drops unnamed and creates named constraints following the pattern
+        * <column>_ckc
+        *
+        * @param string $constraintType
+        * @param string $table Name of the table to which the field belongs
+        * @param string $field Name of the field to modify
+        * @return bool False if patch is skipped.
+        */
+       protected function updateConstraints( $constraintType, $table, $field ) {
+               if ( !$this->doTable( $table ) ) {
+                       return true;
+               }
+
+               $this->output( "...updating constraints on [$table].[$field] ..." );
+               $updateKey = "$field-$constraintType-ck";
+               if ( !$this->db->tableExists( $table, __METHOD__ ) ) {
+                       $this->output( "...$table table does not exist, skipping modify field patch.\n" );
+                       return true;
+               } elseif ( !$this->db->fieldExists( $table, $field, __METHOD__ ) ) {
+                       $this->output( "...$field field does not exist in $table table, " .
+                               "skipping modify field patch.\n" );
+                       return true;
+               } elseif ( $this->updateRowExists( $updateKey ) ) {
+                       $this->output( "...$field in table $table already patched.\n" );
+                       return true;
+               }
+
+               # After all checks passed, start the update
+               $this->insertUpdateRow( $updateKey );
+               $path = 'named_constraints.sql';
+               $constraintMap = array(
+                       'category_types' =>
+                               "($field in('page', 'subcat', 'file'))",
+                       'major_mime'     =>
+                               "($field in('unknown', 'application', 'audio', 'image', 'text', 'video'," .
+                               " 'message', 'model', 'multipart'))",
+                       'media_type'     =>
+                               "($field in('UNKNOWN', 'BITMAP', 'DRAWING', 'AUDIO', 'VIDEO', 'MULTIMEDIA'," .
+                               "'OFFICE', 'TEXT', 'EXECUTABLE', 'ARCHIVE'))"
+               );
+               $constraint = $constraintMap[$constraintType];
+
+               # and hack-in those variables that should be replaced
+               # in our template file right now
+               $this->db->setSchemaVars( array(
+                       'tableName'       => $table,
+                       'fieldName'       => $field,
+                       'checkConstraint' => $constraint,
+                       'wgDBname'        => $wgDBname,
+                       'wgDBmwschema'    => $wgDBmwschema,
+               ) );
+
+               # Full path from file name
+               $path = $this->db->patchPath( $path );
+
+               # No need for a cursor allowing result-iteration; just apply a patch
+               # store old value for re-setting later
+               $wasScrollable = $this->db->scrollableCursor( false );
+
+               # Apply patch
+               $this->db->sourceFile( $path );
+
+               # Reset DB instance to have original state
+               $this->db->setSchemaVars( false );
+               $this->db->scrollableCursor( $wasScrollable );
+
+               $this->output( "done.\n" );
+
+               return true;
+       }
 }
index 9e25f47..89a6978 100644 (file)
@@ -152,17 +152,18 @@ class PostgresInstaller extends DatabaseInstaller {
         * @param string $user User name
         * @param string $password Password
         * @param string $dbName Database name
+        * @param string $schema Database schema
         * @return Status
         */
-       protected function openConnectionWithParams( $user, $password, $dbName ) {
+       protected function openConnectionWithParams( $user, $password, $dbName, $schema ) {
                $status = Status::newGood();
                try {
-                       $db = new DatabasePostgres(
-                               $this->getVar( 'wgDBserver' ),
-                               $user,
-                               $password,
-                               $dbName
-                       );
+                       $db = Database::factory( 'postgres', array(
+                               'host' => $this->getVar( 'wgDBserver' ),
+                               'user' => $user,
+                               'password' => $password,
+                               'dbname' => $dbName,
+                               'schema' => $schema ) );
                        $status->value = $db;
                } catch ( DBConnectionError $e ) {
                        $status->fatal( 'config-connection-error', $e->getMessage() );
@@ -230,7 +231,8 @@ class PostgresInstaller extends DatabaseInstaller {
                                return $this->openConnectionWithParams(
                                        $this->getVar( '_InstallUser' ),
                                        $this->getVar( '_InstallPassword' ),
-                                       $this->getVar( 'wgDBname' ) );
+                                       $this->getVar( 'wgDBname' ),
+                                       $this->getVar( 'wgDBmwschema' ) );
                        case 'create-tables':
                                $status = $this->openPgConnection( 'create-schema' );
                                if ( $status->isOK() ) {
@@ -260,11 +262,11 @@ class PostgresInstaller extends DatabaseInstaller {
                $status = Status::newGood();
                foreach ( $dbs as $db ) {
                        try {
-                               $conn = new DatabasePostgres(
-                                       $this->getVar( 'wgDBserver' ),
+                               $conn = $this->openConnectionWithParams(
                                        $user,
                                        $password,
-                                       $db );
+                                       $db,
+                                       $this->getVar( 'wgDBmwschema' ) );
                        } catch ( DBConnectionError $error ) {
                                $conn = false;
                                $status->fatal( 'config-pg-test-error', $db,
@@ -622,6 +624,14 @@ class PostgresInstaller extends DatabaseInstaller {
                return $status;
        }
 
+       public function getGlobalDefaults() {
+               // The default $wgDBmwschema is null, which breaks Postgres and other DBMSes that require
+               // the use of a schema, so we need to set it here
+               return array(
+                       'wgDBmwschema' => 'mediawiki',
+               );
+       }
+
        public function setupPLpgSQL() {
                // Connect as the install user, since it owns the database and so is
                // the user that needs to run "CREATE LANGAUGE"
index 06b561b..677af4f 100644 (file)
@@ -1230,6 +1230,8 @@ class WebInstallerOptions extends WebInstallerPage {
                        'wgEmailAuthentication', 'wgMainCacheType', '_MemCachedServers',
                        'wgUseInstantCommons' ) );
 
+               $retVal = true;
+
                if ( !array_key_exists( $this->getVar( '_RightsProfile' ), $this->parent->rightsProfiles )
                ) {
                        reset( $this->parent->rightsProfiles );
@@ -1240,8 +1242,7 @@ class WebInstallerOptions extends WebInstallerPage {
                if ( $code == 'cc-choose' ) {
                        if ( !$this->getVar( '_CCDone' ) ) {
                                $this->parent->showError( 'config-cc-not-chosen' );
-
-                               return false;
+                               $retVal = false;
                        }
                } elseif ( array_key_exists( $code, $this->parent->licenses ) ) {
                        // Messages:
@@ -1265,7 +1266,8 @@ class WebInstallerOptions extends WebInstallerPage {
                $extsAvailable = $this->parent->findExtensions();
                $extsToInstall = array();
                foreach ( $extsAvailable as $ext ) {
-                       if ( $this->parent->request->getCheck( 'config_ext-' . $ext ) ) {
+                       $this->parent->setVarsFromRequest( array( "ext-$ext" ) );
+                       if ( $this->getVar( "ext-$ext" ) ) {
                                $extsToInstall[] = $ext;
                        }
                }
@@ -1275,8 +1277,7 @@ class WebInstallerOptions extends WebInstallerPage {
                        $memcServers = explode( "\n", $this->getVar( '_MemCachedServers' ) );
                        if ( !$memcServers ) {
                                $this->parent->showError( 'config-memcache-needservers' );
-
-                               return false;
+                               $retVal = false;
                        }
 
                        foreach ( $memcServers as $server ) {
@@ -1286,21 +1287,18 @@ class WebInstallerOptions extends WebInstallerPage {
                                                && ( gethostbyname( $memcParts[0] ) == $memcParts[0] ) )
                                ) {
                                        $this->parent->showError( 'config-memcache-badip', $memcParts[0] );
-
-                                       return false;
+                                       $retVal = false;
                                } elseif ( !isset( $memcParts[1] ) ) {
                                        $this->parent->showError( 'config-memcache-noport', $memcParts[0] );
-
-                                       return false;
+                                       $retVal = false;
                                } elseif ( $memcParts[1] < 1 || $memcParts[1] > 65535 ) {
                                        $this->parent->showError( 'config-memcache-badport', 1, 65535 );
-
-                                       return false;
+                                       $retVal = false;
                                }
                        }
                }
 
-               return true;
+               return $retVal;
        }
 
 }
index 86db20f..d949a8d 100644 (file)
@@ -1,9 +1,13 @@
 {
        "@metadata": {
                "authors": [
-                       "Mucalexx"
+                       "Mucalexx",
+                       "Matthias Klostermayr"
                ]
        },
+       "config-desc": "As Installationsprogramm vo MediaWiki",
+       "config-title": "Installation vo MediaWiki $1",
+       "config-information": "Information",
        "mainpagetext": "'''MediaWiki is erfoigreich installird worn.'''",
        "mainpagedocfooter": "A Hüf zur da Benützung und Konfigurazion voh da Wiki-Software findst auf [//meta.wikimedia.org/wiki/Help:Contents Benützerhåndbuach].\n\n== Starthüfe ==\n\n* [//www.mediawiki.org/wiki/Special:MyLanguage/Manual:Configuration_settings Listen voh de Konfigurazionsvariaablen]\n* [//www.mediawiki.org/wiki/Special:MyLanguage/Manual:FAQ MediaWiki-FAQ]\n* [https://lists.wikimedia.org/mailman/listinfo/mediawiki-announce Mailinglisten voh de neichen MediaWiki-Versionen]"
 }
index ca6b37d..f4b75db 100644 (file)
        "config-ns-invalid": "Direizh eo an esaouenn anv \"<nowiki>$1</nowiki>\" spisaet.\nMerkit un esaouenn anv disheñvel evit ar raktres.",
        "config-ns-conflict": "Tabut zo etre an esaouenn anv spisaet \"<nowiki>$1</nowiki>\" hag un esaouenn anv dre ziouer eus MediaWiki.\nSpisait un anv raktres esaouenn anv all.",
        "config-admin-box": "Kont merour",
-       "config-admin-name": "Hoc'h anv-implijer :",
+       "config-admin-name": "Hoc'h anv implijer :",
        "config-admin-password": "Ger-tremen :",
        "config-admin-password-confirm": "Adskrivañ ar ger-tremen :",
        "config-admin-help": "Merkit hoc'h anv implijer amañ, da skouer \"Yann Vlog\".\nHemañ eo an anv a implijot evit kevreañ d'ar wiki-mañ.",
index 72b6f73..56b2732 100644 (file)
@@ -12,6 +12,7 @@
        "config-localsettings-key": "Карлаяккхаран догӀа:",
        "config-localsettings-badkey": "Ахьа яздина нийса доцу догӀа",
        "config-your-language": "Хьан мотт:",
+       "config-wiki-language": "Вики чохь лелор болу мотт",
        "config-back": "← Юха",
        "config-continue": "Кхин дӀа →",
        "config-page-language": "Мотт",
index dbfef20..59ad98e 100644 (file)
@@ -60,7 +60,7 @@
        "config-no-db": "Nepodařilo se nalézt vhodný databázový ovladač! Musíte do PHP nainstalovat databázový ovladač.\nJsou podporovány následující typy databází: $1.\n\nPokud jste si PHP přeložili sami, překonfigurujte ho se zapnutým databázovým klientem, například pomocí <code>./configure --with-mysql</code>.\nPokud jste PHP nainstalovali z balíčku Debian či Ubuntu, potřebujete nainstalovat také modul php5-mysql.",
        "config-outdated-sqlite": "'''Upozornění''': Máte SQLite $1, které je starší než minimálně vyžadovaná verze $2. SQLite nebude dostupné.",
        "config-no-fts3": "'''Upozornění''': SQLite bylo přeloženo bez [//sqlite.org/fts3.html modulu FTS3], funkce pro vyhledávání zde nebudou dostupné.",
-       "config-register-globals": "'''Upozornění: Je zapnuta PHP volba <code>[http://php.net/register_globals register_globals]</code>.'''\n'''Pokud můžete, vypněte ji.'''\nMediaWiki bude fungovat, ale váš server je vystaven potenciálním bezpečnostním hrozbám.",
+       "config-register-globals-error": "<strong>Chyba: PHP nastavení <code>[http://php.net/register_globals register_globals]</code> je zapnuto. Pro pokračování v instalaci musí být vypnuto.</strong>\nRady, jak toho dosáhnout, najdete na [https://www.mediawiki.org/wiki/Register_globals https://www.mediawiki.org/wiki/register_globals].",
        "config-magic-quotes-runtime": "'''Kritická chyba: Je zapnuto [http://www.php.net/manual/en/ref.info.php#ini.magic-quotes-runtime magic_quotes_runtime]!'''\nToto nastavení nepředvídatelně poškozuje vstupní data.\nMediaWiki nelze nainstalovat ani používat, dokud není toto nastavení vypnuto.",
        "config-magic-quotes-sybase": "'''Kritická chyba: Je zapnuto [http://www.php.net/manual/en/ref.info.php#ini.magic-quotes-sybase magic_quotes_sybase]!'''\nToto nastavení nepředvídatelně poškozuje vstupní data.\nMediaWiki nelze nainstalovat ani používat, dokud není toto nastavení vypnuto.",
        "config-mbstring": "'''Kritická chyba: Je zapnuto [http://www.php.net/manual/en/ref.mbstring.php#mbstring.overload mbstring.func_overload]!'''\nToto nastavení způsobuje chyby a může nepředvídatelně poškozovat vstupní data.\nMediaWiki nelze nainstalovat ani používat, dokud není toto nastavení vypnuto.",
index cd18c92..ac8daaf 100644 (file)
@@ -66,7 +66,7 @@
        "config-no-db": "Es konnte kein adäquater Datenbanktreiber gefunden werden. Es muss daher ein Datenbanktreiber für PHP installiert werden.\nDie folgenden Datenbanksysteme werden unterstützt: $1\n\nWenn du PHP selbst kompiliert hast, konfiguriere es erneut mit einem aktivierten Datenbankclient, zum Beispiel durch Verwendung von <code>./configure --with-mysqli</code>.\nWenn du PHP von einem Debian- oder Ubuntu-Paket installiert hast, dann musst du auch beispielsweise das <code>php5-mysql</code>-Paket installieren.",
        "config-outdated-sqlite": "'''Warnung:''' SQLite $1 ist installiert. Allerdings benötigt MediaWiki SQLite $2 oder höher. SQLite wird daher nicht verfügbar sein.",
        "config-no-fts3": "'''Warnung:''' SQLite wurde ohne das [//sqlite.org/fts3.html FTS3-Modul] kompiliert, sodass keine Suchfunktionen für dieses Datenbanksystem zur Verfügung stehen werden.",
-       "config-register-globals": "'''Warnung: Der Parameter <code>[http://php.net/register_globals register_globals]</code> von PHP ist aktiviert.'''\n'''Sie sollte deaktiviert werden, sofern dies möglich ist.'''\nDie MediaWiki-Installation wird zwar laufen, wobei aber der Server für potentielle Sicherheitsprobleme anfällig ist.",
+       "config-register-globals-error": "<strong>Fehler: Die PHP-Option <code>[http://php.net/register_globals register_globals]</code> ist aktiviert.\nSie muss deaktiviert sein, um mit der Installation fortzufahren.</strong>\nSiehe [https://www.mediawiki.org/wiki/register_globals https://www.mediawiki.org/wiki/register_globals] für Hilfe.",
        "config-magic-quotes-runtime": "'''Fataler Fehler: Der Parameter <code>[http://www.php.net/manual/de/function.set-magic-quotes-runtime.php set_magic_quotes_runtime]</code> von PHP ist aktiviert!'''\nDiese Einstellung führt zu unvorhersehbaren Problemen bei der Dateneingabe.\nMediaWiki kann nicht installiert werden, solange dieser Parameter nicht deaktiviert wurde.",
        "config-magic-quotes-sybase": "<strong>Fataler Fehler: Der Parameter <code>[http://www.php.net/manual/de/sybase.configuration.php#ini.magic-quotes-sybase magic_quotes_sybase]</code> von PHP ist aktiviert!</strong>\nDiese Einstellung führt zu unvorhersehbaren Problemen bei der Dateneingabe.\nMediaWiki kann nicht installiert werden, solange dieser Parameter nicht deaktiviert wurde.",
        "config-mbstring": "'''Fataler Fehler: Der Parameter <code>[http://www.php.net/manual/en/ref.mbstring.php#mbstring.overload mbstring.func_overload]</code> von PHP ist aktiviert!'''\nDiese Einstellung verursacht Fehler und führt zu unvorhersehbaren Problemen bei der Dateneingabe.\nMediaWiki kann nicht installiert werden, solange dieser Parameter nicht deaktiviert wurde.",
index b19bdc0..e0cd1bf 100644 (file)
@@ -44,7 +44,6 @@
        "config-env-good": "The environment has been checked.\nYou can install MediaWiki.",
        "config-env-bad": "The environment has been checked.\nYou cannot install MediaWiki.",
        "config-env-php": "PHP $1 is installed.",
-       "config-env-php-toolow": "PHP $1 is installed.\nHowever, MediaWiki requires PHP $2 or higher.",
        "config-unicode-using-utf8": "Using Brion Vibber's utf8_normalize.so for Unicode normalization.",
        "config-unicode-using-intl": "Using the [http://pecl.php.net/intl intl PECL extension] for Unicode normalization.",
        "config-unicode-pure-php-warning": "<strong>Warning:</strong> The [http://pecl.php.net/intl intl PECL extension] is not available to handle Unicode normalization, falling back to slow pure-PHP implementation.\nIf you run a high-traffic site, you should read a little on [//www.mediawiki.org/wiki/Special:MyLanguage/Unicode_normalization_considerations Unicode normalization].",
@@ -52,7 +51,7 @@
        "config-no-db": "Could not find a suitable database driver! You need to install a database driver for PHP.\nThe following database types are supported: $1.\n\nIf you compiled PHP yourself, reconfigure it with a database client enabled, for example, using <code>./configure --with-mysqli</code>.\nIf you installed PHP from a Debian or Ubuntu package, then you also need to install, for example, the <code>php5-mysql</code> package.",
        "config-outdated-sqlite": "<strong>Warning:</strong> you have SQLite $1, which is lower than minimum required version $2. SQLite will be unavailable.",
        "config-no-fts3": "<strong>Warning:</strong> SQLite is compiled without the [//sqlite.org/fts3.html FTS3 module], search features will be unavailable on this backend.",
-       "config-register-globals": "<strong>Warning: PHP's <code>[http://php.net/register_globals register_globals]</code> option is enabled.\nDisable it if you can.</strong>\nMediaWiki will work, but your server is exposed to potential security vulnerabilities.",
+       "config-register-globals-error": "<strong>Error: PHP's <code>[http://php.net/register_globals register_globals]</code> option is enabled.\nIt must be disabled to continue with installation.</strong>\nSee [https://www.mediawiki.org/wiki/register_globals https://www.mediawiki.org/wiki/register_globals] for help on how to do so.",
        "config-magic-quotes-runtime": "<strong>Fatal: [http://www.php.net/manual/en/ref.info.php#ini.magic-quotes-runtime magic_quotes_runtime] is active!'</strong>\nThis option corrupts data input unpredictably.\nYou cannot install or use MediaWiki unless this option is disabled.",
        "config-magic-quotes-sybase": "<strong>Fatal: [http://www.php.net/manual/en/ref.info.php#ini.magic-quotes-sybase magic_quotes_sybase] is active!</strong>\nThis option corrupts data input unpredictably.\nYou cannot install or use MediaWiki unless this option is disabled.",
        "config-mbstring": "<strong>Fatal: [http://www.php.net/manual/en/ref.mbstring.php#mbstring.overload mbstring.func_overload] is active!</strong>\nThis option causes errors and may corrupt data unpredictably.\nYou cannot install or use MediaWiki unless this option is disabled.",
index b37a1b7..edb3f27 100644 (file)
@@ -75,7 +75,6 @@
        "config-no-db": "¡No fue posible encontrar un controlador adecuado para la base de datos! Necesitas instalar un controlador de base de datos para PHP.\nLos siguientes sistemas gestores de bases de datos están soportados: $1.\n\nSi compilaste PHP tú mismo, debes reconfigurarlo habilitando un cliente de base de datos, por ejemplo, usando <code>./configure --with-mysqli</code>.\nSi instalaste PHP desde un paquete Debian o Ubuntu, entonces también necesitas instalar, por ejemplo, el paquete <code>php5-mysql</code>.",
        "config-outdated-sqlite": "''' Advertencia ''': tiene la versión SQLite $1, que es inferior a la mínima versión requerida: $2 . SQLite no estará disponible.",
        "config-no-fts3": "'''Advertencia''': SQLite está compilado sin el [//sqlite.org/fts3.html módulo FTS3]. Las funcionalidades de búsqueda no estarán disponibles en esta instalación.",
-       "config-register-globals": "'''Advertencia: La opción de <code>[http://php.net/register_globals register_globals]</code> de PHP está habilitada.'''\n'''Desactívela si puede.'''\nMediaWiki funcionará, pero tu servidor quedará expuesto a vulnerabilidades de seguridad potenciales.",
        "config-magic-quotes-runtime": "'''Fatal: ¡[http://www.php.net/manual/en/ref.info.php#ini.magic-quotes-runtime magic_quotes_runtime] está activada!'''\nEsta opción causa la imprevisible corrupción de la entrada de datos.\nNo puedes instalar o utilizar MediaWiki a menos que esta opción esté inhabilitada.",
        "config-magic-quotes-sybase": "'''Fatal: ¡[http://www.php.net/manual/en/ref.info.php#ini.magic-quotes-sybase magic_quotes_sybase] está activada!'''\nEsta opción causa la imprevisible corrupción de la entrada de datos.\nNo puedes instalar o utilizar MediaWiki a menos que esta opción esté inhabilitada.",
        "config-mbstring": "'''Fatal: La opción [http://www.php.net/manual/en/ref.mbstring.php#mbstring.overload mbstring.func_overload] está activada!'''\nEsta opción causa errores y puede corromper los datos de una forma imprevisible.\nNo se puede instalar o usar MediaWiki a menos que esta opción sea desactivada.",
index d9ef1ef..308418f 100644 (file)
@@ -74,7 +74,7 @@
        "config-no-db": "Impossible de trouver un pilote de base de données approprié ! Vous devez installer un pilote de base de données pour PHP. Les types de bases de données suivants sont reconnus : $1.\n\nSi vous avez compilé PHP vous-même, reconfigurez-le avec un client de base de données activé, par exemple en utilisant <code>./configure --with-mysqli</code>. Si vous avez installé PHP depuis un paquet Debian ou Ubuntu, alors vous devrez aussi installer, par exemple, le paquet <code>php5-mysql</code>.",
        "config-outdated-sqlite": "'''Attention''': vous avez SQLite $1, qui est inférieur à la version minimale requise $2. SQLite sera indisponible.",
        "config-no-fts3": "'''Attention :''' SQLite est compilé sans le module [//sqlite.org/fts3.html FTS3] ; les fonctions de recherche ne seront pas disponibles sur ce moteur.",
-       "config-register-globals": "'''Attention : l'option <code>[http://php.net/register_globals register_globals]</code> de PHP est activée.'''\n'''Désactivez-la si vous le pouvez.'''\nMediaWiki fonctionnera, mais votre serveur sera exposé à de potentielles failles de sécurité.",
+       "config-register-globals-error": "<strong>Erreur : L’option <code>[http://php.net/register_globals register_globals]</code> de PHP est activée.\nElle doit être désactivée pour poursuivre l’installation.</strong>\nVoyez [https://www.mediawiki.org/wiki/register_globals https://www.mediawiki.org/wiki/register_globals] pour avoir de l’aide sur la manière de faire cela.",
        "config-magic-quotes-runtime": "'''Erreur fatale : [http://www.php.net/manual/en/ref.info.php#ini.magic-quotes-runtime magic_quotes_runtime] est activé !'''\nCette option corrompt les données de manière imprévisible.\nVous ne pouvez pas installer ou utiliser MediaWiki tant que cette option est activée.",
        "config-magic-quotes-sybase": "'''Erreur fatale : [http://www.php.net/manual/en/ref.info.php#ini.magic-quotes-sybase magic_quotes_sybasee] est activé !'''\nCette option corrompt les données de manière imprévisible.\nVous ne pouvez pas installer ou utiliser MediaWiki tant que cette option est activée.",
        "config-mbstring": "'''Erreur fatale : [http://www.php.net/manual/en/ref.mbstring.php#mbstring.overload mbstring.func_overload] est activé !'''\nCette option provoque des erreurs et peut corrompre les données de manière imprévisible.\nVous ne pouvez pas installer ou utiliser MediaWiki tant que cette option est activée.",
index a4cb9eb..5a7d148 100644 (file)
@@ -7,8 +7,11 @@
        "config-desc": "Ka polokalamu hoʻonoho no MekiaWiki",
        "config-title": "Ka hoʻonoho MekiaWiki $1",
        "config-information": "ʻIke",
+       "config-localsettings-upgrade": "Ua hōʻike ʻia kekahi waihona <code>LocalSettings.php</code>.\nNo ka hoʻopuka hou ʻana o kēia hoʻonohona, e ʻoluʻolu, e kikokiko i ka helu o <code>$wgUpgradeKey</code> i loko o ka pahu i lalo.\nAia ia ma <code>LocalSettings.php</code>.",
+       "config-localsettings-cli-upgrade": "Ua hōʻike ʻia kekahi waihona <code>LocalSettings.php</code>.\nNo ka hoʻopuka hou ʻana o kēia hoʻonohona, e hana iā <code>update.php</code> ke ʻoluʻolu.",
        "config-localsettings-key": "Pihi hoʻopuka hou:",
        "config-localsettings-badkey": "Hewa ka pihi.",
+       "config-upgrade-key-missing": "Loaʻa he hoʻonohona mai mua o MīkiaWiki mai mua.\nNo ka hoʻopuka hou ʻana o kēia hoʻonohona, e ʻoluʻolu, e kau i kēia laina lalo ma lalo o kāu <code>LocalSettings.php</code>:\n\n$1",
        "config-your-language": "Kāu ʻōlelo:",
        "config-your-language-help": "E koho i kekahi ʻōlelo no ka hoʻohana ʻana ma loko o ka hana hoʻonohona.",
        "config-wiki-language": "ʻŌlelo Wiki:",
index 5d4ba21..582e463 100644 (file)
@@ -59,7 +59,7 @@
        "config-no-db": "לא נמצא דרייבר מסד נתונים מתאים. יש להתקין דרייבר מסד נתונים ל־PHP.\nנתמכים הסוגים הבאים של מסדי נתונים: $1.\n\nאם קִמפלת את PHP בעצמך, יש להגדיר אותו מחדש ולהפעיל את לקוח מסד נתונים, למשל באמצעות <code dir=\"ltr\">./configure --with-mysqli</code>.\nאם התקנת את PHP מחבילה של דביאן או של אובונטו, יש להתקין, למשל, גם את המודול <code dir=\"ltr\">php5-mysql</code>.",
        "config-outdated-sqlite": "'''אזהרה''': במערכת מתוקן SQLite $1. גרסה זו לא נתמכת ולשימוש ב־SQLite נדרשת גרסה $2 לפחות. SQLlite לא יהיה זמין.",
        "config-no-fts3": "'''אזהרה''': SQLite מקומפל ללא [//sqlite.org/fts3.html מודול FTS]. יכולות חיפוש לא יהיו זמינות בהתקנה הזאת.",
-       "config-register-globals": "'''אזהרה: האפשרות <code>[http://php.net/register_globals register_globals]</code> של PHP מופעלת.'''\n'''כבו אותה אם זה אפשרי.'''\nמדיה־ויקי תעבוד, אבל השרת שלך חשוף לפגיעות אבטחה.",
+       "config-register-globals-error": "<strong>שגיאה: האפשרות <code>[http://php.net/register_globals register_globals]</code> של PHP מופעלת.\nצריך לכבות אותה כדי להמשיך בהתקנה.</strong>\nר' [https://www.mediawiki.org/wiki/register_globals https://www.mediawiki.org/wiki/register_globals] להסבר איך לעשות את זה.",
        "config-magic-quotes-runtime": "<strong>שגיאה סופנית: האפשרות [http://www.php.net/manual/en/ref.info.php#ini.magic-quotes-runtime magic_quotes_runtime] פעילה!</strong>\nהאפשרות הזאת מעוותת את נתוני הקלט באופן בלתי־צפוי.\nלא ניתן להתקין את מדיה־ויקי אלא אם האפשרות הזאת תכובה.",
        "config-magic-quotes-sybase": "'''שגיאה סופנית''': האפשרות [http://www.php.net/manual/en/ref.info.php#ini.magic-quotes-sybase magic_quotes_sybase] פעילה!'''\nהאפשרות הזאת מעוותת את נתוני הקלט באופן בלתי־צפוי.\nלא ניתן להתקין את מדיה־ויקי או להשתמש בה אלא אם האפשרות הזאת תכובה.",
        "config-mbstring": "'''שגיאה סופנית''': האפשרות [http://www.php.net/manual/en/ref.mbstring.php#mbstring.overload mbstring.func_overload] פעילה!'''\nהאפשרות הזאת גורמת לשגיאות ומעוותת את נתוני הקלט באופן בלתי־צפוי.\nלא ניתן להתקין את מדיה־ויקי או להשתמש בה אלא אם האפשרות הזאת תכובה.",
index e236af5..87ab22e 100644 (file)
@@ -55,7 +55,7 @@
        "config-no-db": "Не можев да најдам соодветен двигател за базата на податоци! Ќе треба да воспоставите двигател за PHP-база.\nПоддржани се следниве видови бази: $1.\n\nДоколку самите го срочивте овој PHP, овозможете го базниот клиент во поставките — на пр. со <code>./configure --with-mysqli</code>.\nАко овој PHP го воспоставите од пакет на Debian или Ubuntu, тогаш ќе треба исто така да го воспоставите, на пр., пакетот <code>php5-mysql</code>.",
        "config-outdated-sqlite": "'''Предупредување''': имате SQLite $1. Најстарата допуштена верзија е $2. Затоа, SQLite ќе биде недостапен.",
        "config-no-fts3": "'''Предупредување''': SQLite iе составен без модулот [//sqlite.org/fts3.html FTS3] - за оваа база нема да има можност за пребарување.",
-       "config-register-globals": "'''Предупредување: Можноста <code>[http://php.net/register_globals register_globals]</code> за PHP е овозможена.'''\n'''Оневозможете ја ако е можно.'''\nМедијаВики ќе работи, но опслужувачот ви е изложен на безбедносни ризици.",
+       "config-register-globals-error": "<strong>Грешка: Вклучена е можноста <code>[http://php.net/register_globals register_globals]</code> за PHP.\nМора да се исклучи за да продолжите со воспоставката.</strong>\nКако да го направите тоа можете да прочитате на [https://www.mediawiki.org/wiki/register_globals https://www.mediawiki.org/wiki/register_globals].",
        "config-magic-quotes-runtime": "'''Кобно: [http://www.php.net/manual/en/ref.info.php#ini.magic-quotes-runtime magic_quotes_runtime] е активно!'''\nОваа можност непредвидливо го расипува вносот на податоци.\nОваа можност мора да е исклучена. Во спротивно нема да можете да го воспоставите и користите МедијаВики.",
        "config-magic-quotes-sybase": "'''Кобно: [http://www.php.net/manual/en/ref.info.php#ini.magic-quotes-sybase magic_quotes_sybase] е активно!'''\nОваа можност непредвидливо го расипува вносот на податоци.\nОваа можност мора да е исклучена. Во спротивно нема да можете да го воспоставите и користите МедијаВики.",
        "config-mbstring": "'''Кобно: [http://www.php.net/manual/en/ref.mbstring.php#mbstring.overload mbstring.func_overload] е активно!'''\nОваа можност предизвикува грешки и може непредвидиво да го расипува вносот на податоци.\nОваа можност мора да е исклучена. Во спротивно нема да можете да го воспоставите и користите МедијаВики.",
        "config-db-account-lock": "Користи го истото корисничко име и лозинка за редовна работа",
        "config-db-wiki-account": "Корисничко име за редовна работа",
        "config-db-wiki-help": "Внесете корисничко име и лозинка што ќе се користат за поврзување со базата на податоци во текот на редовната работа со викито.\nАко сметката не постои, а инсталационата сметка има доволно привилегии, тогаш оваа корисничка сметка ќе биде создадена со минималните привилегии потребни за работа со викито.",
-       "config-db-prefix": "Ð\9fÑ\80еÑ\84икÑ\81 на табелата на базата:",
-       "config-db-prefix-help": "Ð\90ко Ñ\82Ñ\80еба Ð´Ð° Ð´ÐµÐ»Ð¸Ñ\82е ÐµÐ´Ð½Ð° Ð±Ð°Ð·Ð° Ð½Ð° Ð¿Ð¾Ð´Ð°Ñ\82оÑ\86и Ñ\81о Ð¿Ð¾Ð²ÐµÑ\9cе Ð²Ð¸ÐºÐ¸Ñ\98а, Ð¸Ð»Ð¸ Ñ\81о Ð\9cедиÑ\98аÐ\92ики Ð¸ Ð´Ñ\80Ñ\83г Ð¼Ñ\80ежен Ð¿Ñ\80огÑ\80ам, Ñ\82огаÑ\88 Ð¼Ð¾Ð¶ÐµÑ\82е Ð´Ð° Ð´Ð¾Ð´Ð°Ð´ÐµÑ\82е Ð¿Ñ\80еÑ\84икÑ\81 на сите називи на табелите за да спречите проблематични ситуации.\nНе користете празни простори.\n\nОва поле обично се остава празно.",
+       "config-db-prefix": "Ð\9fÑ\80еÑ\82Ñ\81Ñ\82авка на табелата на базата:",
+       "config-db-prefix-help": "Ð\90ко Ñ\82Ñ\80еба Ð´Ð° Ð´ÐµÐ»Ð¸Ñ\82е ÐµÐ´Ð½Ð° Ð±Ð°Ð·Ð° Ð½Ð° Ð¿Ð¾Ð´Ð°Ñ\82оÑ\86и Ñ\81о Ð¿Ð¾Ð²ÐµÑ\9cе Ð²Ð¸ÐºÐ¸Ñ\98а, Ð¸Ð»Ð¸ Ñ\81о Ð\9cедиÑ\98аÐ\92ики Ð¸ Ð´Ñ\80Ñ\83г Ð¼Ñ\80ежен Ð¿Ñ\80огÑ\80ам, Ñ\82огаÑ\88 Ð¼Ð¾Ð¶ÐµÑ\82е Ð´Ð° Ð´Ð¾Ð´Ð°Ð´ÐµÑ\82е Ð¿Ñ\80еÑ\82Ñ\81Ñ\82авка на сите називи на табелите за да спречите проблематични ситуации.\nНе користете празни простори.\n\nОва поле обично се остава празно.",
        "config-db-charset": "Збир знаци за базата",
        "config-charset-mysql5-binary": "Бинарен за MySQL 4.1/5.0",
        "config-charset-mysql5": "UTF-8 за MySQL 4.1/5.0",
        "config-missing-db-server-oracle": "Мора да внесете вредност за „{{int:config-db-host-oracle}}“.",
        "config-invalid-db-server-oracle": "Неважечки TNS „$1“.\nКористете или „TNS Name“ или низата „Easy Connect“ ([http://docs.oracle.com/cd/E11882_01/network.112/e10836/naming.htm Методи на именување за Oracle])",
        "config-invalid-db-name": "Неважечко име на базата „$1“.\nКористете само ASCII-букви (a-z, A-Z), бројки (0-9), долни црти (_) и цртички (-).",
-       "config-invalid-db-prefix": "Ð\9dеважеÑ\87ки Ð¿Ñ\80еÑ\84икÑ\81 за базата „$1“.\nКористете само ASCII-букви (a-z, A-Z), бројки (0-9), долни црти (_) и цртички (-).",
+       "config-invalid-db-prefix": "Ð\9dеважеÑ\87ка Ð¿Ñ\80еÑ\82Ñ\81Ñ\82авка за базата „$1“.\nКористете само ASCII-букви (a-z, A-Z), бројки (0-9), долни црти (_) и цртички (-).",
        "config-connection-error": "$1.\n\nПроверете го долунаведениот домаќин, корисничко име и лозинка и обидете се повторно.",
        "config-invalid-schema": "Неважечка шема за МедијаВики „$1“.\nКористете само букви, бројки и долни црти.",
        "config-db-sys-create-oracle": "Воспоставувачот поддржува само употреба на SYSDBA-сметка за создавање на нова сметка.",
index c95e9df..be78096 100644 (file)
@@ -58,7 +58,7 @@
        "config-no-db": "Fant ingen passende databasedriver! Du må installere en databasedriver for PHP.\nFølgende databasetyper støttes: $1\n\nOm du kompilerte PHP selv, rekonfigurer den med en aktivert databaseklient, for eksempel ved å bruke <code>./configure --with-mysql</code>.\nOm du installerte PHP fra en Debian- eller Ubuntu-pakke, må du også installere for eksempel <code>php5-mysql</code>-pakken.",
        "config-outdated-sqlite": "'''Advarsel''': Du har SQLite $1, som er en eldre versjon enn minimumskravet SQLite $2. SQLite vil ikke være tilgjengelig.",
        "config-no-fts3": "'''Advarsel''': SQLite er kompilert uten [//sqlite.org/fts3.html FTS3-modulen], søkefunksjoner vil ikke være tilgjengelig på dette bakstykket.",
-       "config-register-globals": "'''Advarsel: PHPs <code>[http://php.net/register_globals register_globals]</code>-alternativ er aktivert.'''\n'''Deaktiver det om du kan.'''\nMediaWiki vil fungere, men tjeneren din er utsatt for potensielle sikkerhetssårbarheter.",
+       "config-register-globals-error": "<strong>Feil: PHPs <code>[http://php.net/register_globals register_globals]</code>-valg er aktivt.\nDet må deaktiveres for å kunne fortsette med installeringen.</strong>\nSe [https://www.mediawiki.org/wiki/register_globals https://www.mediawiki.org/wiki/register_globals] for å få hjelp til å gjøre dette.",
        "config-magic-quotes-runtime": "'''Kritisk: [http://www.php.net/manual/en/ref.info.php#ini.magic-quotes-runtime magic_quotes_runtime] er aktiv!'''\nDette alternativet ødelegger inndata på en uforutsigbar måte.\nDu kan ikke installere eller bruke MediaWiki med mindre dette alternativet deaktiveres.",
        "config-magic-quotes-sybase": "'''Kritisk: [http://www.php.net/manual/en/ref.info.php#ini.magic-quotes-sybase magic_quotes_sybase] er aktiv!'''\nDette alternativet ødelegger inndata på en uforutsigbar måte.\nDu kan ikke installere eller bruke MediaWiki med mindre dette alternativet deaktiveres.",
        "config-mbstring": "'''Kritisk: [http://www.php.net/manual/en/ref.mbstring.php#mbstring.overload mbstring.func_overload] er aktiv!'''\nDette alternativet fører til feil og kan ødelegge data på en uforutsigbar måte.\nDu kan ikke installere eller bruke MediaWiki med mindre dette alternativet deaktiveres.",
index 20f0b3e..79969e8 100644 (file)
@@ -65,7 +65,6 @@
        "config-no-db": "Não foi possível encontrar um driver de banco de dados adequado! É necessário instalar um driver de banco de dados para o PHP.\nSão suportados os seguintes tipos de bancos de dados: $1.\n\nSe você mesmo tiver compilado o PHP, reconfigure-o com um cliente de banco de dados ativado usando, por exemplo <code>./configure --with-mysqli</code>.\nSe você instalou o PHP a partir de um pacote do Debian ou do Ubuntu, então será também necessário instalar, por exemplo, o pacote <code>php5-mysql</code>.",
        "config-outdated-sqlite": "<strong>Aviso:</strong> você tem o SQLite versão $1, que é menor do que a versão mínima necessária $2. O SQLite não estará disponível.",
        "config-no-fts3": "<strong>Aviso</strong> O SQLite foi compilado sem o [//sqlite.org/fts3.html módulo FTS3], as funcionalidades de pesquisa não estarão disponíveis nesta instalação.",
-       "config-register-globals": "<strong>Aviso: A opção <code>[http://php.net/register_globals register_globals]</code> do PHP está ativada.\nDesative-a se puder.</strong>\nO MediaWiki funcionará mesmo assim, mas o seu servidor ficará exposto a potenciais vulnerabilidades de segurança.",
        "config-magic-quotes-runtime": "<strong>Erro fatal: A opção [http://www.php.net/manual/en/ref.info.php#ini.magic-quotes-runtime magic_quotes_runtime] está ativada!</strong>\nEsta opção causa corrupção dos dados de entrada de forma imprevisível.\nVocê não pode instalar ou utilizar o MediaWiki a menos que esta opção seja desativada.",
        "config-magic-quotes-sybase": "<strong>Erro fatal: A opção [http://www.php.net/manual/en/ref.info.php#ini.magic-quotes-sybase magic_quotes_sybase] está ativada!</strong>\nEsta opção corrompe os dados de entrada de forma imprevisível.\nVocê não pode instalar ou utilizar o MediaWiki a menos que esta opção seja desativada.",
        "config-mbstring": "<strong>Erro fatal: A opção [http://www.php.net/manual/en/ref.mbstring.php#mbstring.overload mbstring.func_overload] está ativada!</strong>\nEsta opção causa erros e pode corromper os dados de forma imprevisível.\nVocê não pode instalar ou utilizar o MediaWiki a menos que esta opção seja desativada.",
index 3a16079..b57ebf9 100644 (file)
@@ -70,7 +70,7 @@
        "config-no-db": "{{doc-important|Do not translate \"<code>./configure --with-mysqli</code>\" and \"<code>php5-mysql</code>\".}}\nParameters:\n* $1 is comma separated list of database types supported by MediaWiki.",
        "config-outdated-sqlite": "Used as warning. Parameters:\n* $1 - the version of SQLite that has been installed\n* $2 - minimum version",
        "config-no-fts3": "A \"[[:wikipedia:Front and back ends|backend]]\" is a system or component that ordinary users don't interact with directly and don't need to know about, and that is responsible for a distinct task or service - for example, a storage back-end is a generic system for storing data which other applications can use. Possible alternatives for back-end are \"system\" or \"service\", or (depending on context and language) even leave it untranslated.",
-       "config-register-globals": "Status message in the MediaWiki installer environment checks.",
+       "config-register-globals-error": "Error message in the MediaWiki installer environment checks.",
        "config-magic-quotes-runtime": "{{Related|Config-fatal}}",
        "config-magic-quotes-sybase": "{{Related|Config-fatal}}",
        "config-mbstring": "{{Related|Config-fatal}}",
index 17f5fbc..1bc4d08 100644 (file)
@@ -70,7 +70,7 @@
        "config-no-db": "Не удалось найти подходящие драйвера баз данных! Вам необходимо установить драйвера базы данных для PHP.\nПоддерживаются следующие типы баз данных: $1.\nЕсли вы скомпилировали PHP сами, перенастройте его с включением клиента баз данных, например, с помощью <code>./configure --with-mysqli</code>.\nЕсли вы скомпилировали PHP сами, сконфигурируйте его снова с включенным клиентом базы данных, например, с помощью <code>./configure --with-mysql</code>.\nЕсли вы установили PHP из пакетов Debian или Ubuntu, то вам также необходимо установить, например, пакет <code>php5-mysql</code>.",
        "config-outdated-sqlite": "'''Предупреждение''': у Вас установлен SQLite  $1, версия которого ниже требуемой $2 . SQLite будет недоступен.",
        "config-no-fts3": "'''Внимание''': SQLite собран без модуля [//sqlite.org/fts3.html FTS3] — поиск не будет работать для этой базы данных.",
-       "config-register-globals": "'''Внимание: PHP-опция <code>[http://php.net/register_globals register_globals]</code> включена.'''\n'''Отключите её, если это возможно.'''\nMediaWiki будет работать, но это снизит безопасность сервера и увеличит риск проникновения извне.",
+       "config-register-globals-error": "<strong>Ошибка: Параметр PHP <code>[http://php.net/register_globals register_globals]</code> включен.\nОн должен быть отключен для того, чтобы можно было продолжить установку.</strong>\nПолучить справку о том, как это сделать, можно по адресу [https://www.mediawiki.org/wiki/register_globals https://www.mediawiki.org/wiki/register_globals].",
        "config-magic-quotes-runtime": "'''Проблема: включена опция PHP [http://www.php.net/manual/ru/function.magic-quotes-runtime.php magic_quotes_runtime]!'''\nЭто приводит к непредсказуемой порче вводимых данных.\nУстановка и использование MediaWiki без выключения этой опции невозможно.",
        "config-magic-quotes-sybase": "'''Проблема: включена опция PHP [http://www.php.net/manual/en/ref.info.php#ini.magic-quotes-sybase magic_quotes_sybase]!'''\nЭто приводит к непредсказуемой порче вводимых данных.\nУстановка и использование MediaWiki без выключения этой опции невозможно.",
        "config-mbstring": "'''Проблема: включена опция PHP [http://www.php.net/manual/en/ref.mbstring.php#mbstring.overload mbstring.func_overload]!'''\nЭто приводит к ошибкам и непредсказуемой порче вводимых данных.\nУстановка и использование MediaWiki без выключения этой опции невозможно.",
index c04765b..4f1c9c9 100644 (file)
@@ -59,7 +59,6 @@
        "config-no-db": "Kunde inte hitta en lämplig databasdrivrutin! Du måste installera en databasdrivrutin för PHP.\nFöljande databastyper stöds: $1.\n\nI du själv kompilerat din PHP, konfigurera den med en databasklient aktiverad genom att t.ex. använda <code>./configure --with-mysqli</code>.\nOm du installerade PHP från ett Debian- eller Ubuntupaket måste du även installera, t.ex. <code>php5-mysql</code>-paketet.",
        "config-outdated-sqlite": "'''Varning:''' du har SQLite $1, vilket är lägre än minimikravet version $2. SQLite kommer inte att vara tillgänglig.",
        "config-no-fts3": "'''Varning:''' SQLite kompileras utan [//sqlite.org/fts3.html FTS3-modulen], sökfunktioner kommer att vara otillgängliga på denna backend.",
-       "config-register-globals": "'''Varning: PHP:s <code>[http://php.net/register_globals register_globals]</code>-tillval är aktiverat.'''\n'''Inaktivera den om du kan.'''\nMediaWiki kommer att fungera, men din server exponeras för potentiella säkerhetshål.",
        "config-magic-quotes-runtime": "'''Kritiskt: [http://www.php.net/manual/en/ref.info.php#ini.magic-quotes-runtime magic_quotes_runtime] är aktiv!'''\nDetta alternativ korrumperar inmatad data oförutsägbart.\nDu kan inte installera eller använda MediaWiki om detta alternativ är aktiverat.",
        "config-magic-quotes-sybase": "'''Kritiskt: [http://www.php.net/manual/en/ref.info.php#ini.magic-quotes-sybase magic_quotes_sybase] är aktiv!'''\nDetta alternativ korrumperar inmatad data oförutsägbart.\nDu kan inte installera eller använda MediaWiki om detta alternativ är aktiverat.",
        "config-mbstring": "'''Kritiskt: [http://www.php.net/manual/en/ref.mbstring.php#mbstring.overload mbstring.func_overload] är aktiv!'''\nDetta alternativ orsakar fel och kan korrumpera data oförutsägbart.\nDu kan inte installera eller använda MediaWiki om detta alternativ är aktiverat.",
@@ -99,6 +98,7 @@
        "config-db-name": "Databasnamn:",
        "config-db-name-help": "Välj ett namn som identifierar din wiki.\nDet bör inte innehålla mellanslag.\n\nOm du använder ett delat webbhotell kan de antingen ge dig ett särskilt databasnamn att använda eller så kan de låta dig skapa en databas via kontrollpanelen.",
        "config-db-name-oracle": "Databasschema:",
+       "config-db-account-oracle-warn": "Det finns tre stödda scenarier för installationen av Oracle som en backend-databas:\n\nOm du vill skapa ett databaskonto som en del av installationen, ange ett konto med SYSDBA-roll som databaskonto under installationen och ange de önskade autentiseringsuppgifterna för kontot med webb-åtkomst, annars kan du antingen skapa ett konto med webb-åtkomst manuellt och ange enbart detta konto (om den har behörighet att skapa schema-objekt) eller ange två olika konton, en med create-behörighet och en begränsad för webb-åtkomst.\n\nSkript för att skapa ett konto med de korrekta behörigheterna kan hittas i \"maintenance/oracle/\"-katalogen för denna installation. Tänk på att användningen av ett begränsat konto inaktiverar all underhållsmöjlighet med standardkontot.",
        "config-db-install-account": "Användarkonto för installation",
        "config-db-username": "Databas-användarnamn:",
        "config-db-password": "Databas-lösenord:",
        "config-db-schema-help": "Det här schemat blir oftast bra.\nÄndra det endast om du vet att du behöver.",
        "config-pg-test-error": "Kan inte ansluta till databas '''$1''': $2",
        "config-sqlite-dir": "SQLite data-katalog:",
+       "config-sqlite-dir-help": "SQLite lagrar all data i en enda fil.\n\nDen katalog du anger måste vara skrivbar av webbservern under installationen.\n\nDet bör <strong>inte</strong> vara tillgänglig via webben; Det är därför vi inte lägger den där dina PHP-filer är.\n\nInstallationsprogrammet kommer att skriva en <code>.htaccess</code>-fil tillsammans med den, men om det misslyckas kan någon få tillgång till den råa databasen.\nVlken innehåller rå användardata (e-postadresser, hashade lösenord) samt borttagna revideringar och annan begränsad data på wiki.\n\nÖverväga att lägga databasen någon helt annanstans, till exempel i <code>/var/lib/mediawiki/yourwiki</code>.",
+       "config-oracle-def-ts": "Standardtabellutrymme (tablespace):",
+       "config-oracle-temp-ts": "Tillfälligt tabellutrymme (tablespace):",
        "config-type-mysql": "MySQL (eller kompatibelt)",
        "config-type-mssql": "Microsoft SQL Server",
        "config-support-info": "MediaWiki stöder följande databassystem:\n\n$1\n\nOm du inte ser det databassystem som du försöker använda nedanstående, följ då instruktionerna länkade ovan för aktivera stöd för det.",
        "config-dbsupport-mysql": "* [{{int:version-db-mysql-url}} MySQL] är det primära målet för MediaWiki och det stöds bäst. MediaWiki fungerar även med [{{int:version-db-mariadb-url}} MariaDB] och [{{int:version-db-percona-url}} Percona Server], som är kompatibla med MySQL. ([http://www.php.net/manual/en/mysqli.installation.php Hur man kompilerar PHP med stöd för MySQL])",
+       "config-dbsupport-postgres": "* [{{int:version-db-postgres-url}} PostgreSQL] är ett populärt databassystem med öppen källkod som ett alternativ till MySQL. Det kan finnas några mindre kvarvarande buggar, och den rekommenderas inte för användning i en produktionsmiljö. ([http://www.php.net/manual/en/pgsql.installation.php Hur man kompilerar PHP med PostgreSQL stöd])",
+       "config-dbsupport-sqlite": "* [{{int:version-db-sqlite-url}} SQLite] är en lättviktsdatabassystem med väldigt bra stöd. ([http://www.php.net/manual/en/pdo.installation.php Hur man kompilerar PHP med SQLite stöd], använder PDO)",
+       "config-dbsupport-oracle": "* [{{int:version-db-oracle-url}} Oracle] är en kommersiellt databas för företag. ([http://www.php.net/manual/en/oci8.installation.php Hur man kompilerar PHP med OCI8 stöd])",
+       "config-dbsupport-mssql": "* [{{int:version-db-mssql-url}} Microsoft SQL Server] är en kommersiellt databas för företag för Windows. ([http://www.php.net/manual/en/sqlsrv.installation.php Hur man kompilerar PHP med SQLSRV stöd])",
        "config-header-mysql": "MySQL-inställningar",
        "config-header-postgres": "PostgreSQL-inställningar",
        "config-header-sqlite": "SQLite-inställningar",
        "config-missing-db-name": "Du måste ange ett värde för \"{{int:config-db-name}}\".",
        "config-missing-db-host": "Du måste ange ett värde för \"{{int:config-db-host}}\".",
        "config-missing-db-server-oracle": "Du måste ange ett värde för \"{{int:config-db-host-oracle}}\".",
+       "config-invalid-db-server-oracle": "Ogiltig databas-TNS \"$1\".\nAnvända antingen \"TNS Name\" eller en \"Easy Connect\"-sträng ([http://docs.oracle.com/cd/E11882_01/network.112/e10836/naming.htm Oracles namngivningsmetoder]).",
        "config-invalid-db-name": "\"$1\" är ett ogiltigt databasnamn.\nAnvänd bara ASCII-bokstäver (a-z, A-Z), siffror (0-9), understreck (_) och bindestreck (-).",
        "config-invalid-db-prefix": "\"$1\" är ett ogiltigt databasprefix.\nAnvänd bara ASCII-bokstäver (a-z, A-Z), siffror (0-9), understreck (_) och bindestreck (-).",
        "config-connection-error": "$1.\n\nKontrollera värd, användarnamn och lösenord och försök igen.",
        "config-postgres-old": "PostgreSQL $1 eller senare krävs, du har $2.",
        "config-mssql-old": "Microsoft SQL-server $1 eller senare krävs. Du har $2.",
        "config-sqlite-name-help": "Välja ett namn som identifierar din wiki.\nAnvänd inte mellanslag eller bindestreck.\nDetta kommer att användas för SQLite-data filnamnet.",
+       "config-sqlite-parent-unwritable-group": "Kan inte skapa datakatalogen <code><nowiki>$1</nowiki></code>, då den överordnade katalogen <code><nowiki>$2</nowiki></code> inte är skrivbar för webbservern.\n\nInstallationen har avgjort vilken användare din webbserver körs som.\nGör <code><nowiki>$3</nowiki></code>-katalogen skrivbar för den för att fortsätta.\nPå ett Unix/Linux system gör:\n\n<pre>cd $2\nmkdir $3\nchgrp $4 $3\nchmod g+w $3</pre>",
+       "config-sqlite-parent-unwritable-nogroup": "Kan inte skapa datakatalogen <code><nowiki>$1</nowiki></code>, då den överordnade katalogen <code><nowiki>$2</nowiki></code> inte är skrivbar för webbservern.\n\nInstallationen kunde inte avgöra vilken användare din webbserver körs som.\nGör <code><nowiki>$3</nowiki></code>-katalogen skrivbar för den (och andra!) för att fortsätta.\nPå ett Unix/Linux system gör:\n\n<pre>cd $2\nmkdir $3\nchmod g+w $3</pre>",
        "config-sqlite-mkdir-error": "Fel uppstod när datakatalogen \"$1\" skulle skapas.\nKontrollera platsen och försök igen.",
+       "config-sqlite-dir-unwritable": "Kunde inte skriva till katalogen \"$1\".\nÄndra dess behörighet så att webbservern kan skriva till den och försök igen.",
+       "config-sqlite-connection-error": "$1.\n\nKontrollera datakatalogen och databasnamnet nedan och försök igen.",
        "config-sqlite-readonly": "Filen <code>$1</code> är inte skrivbar.",
        "config-sqlite-cant-create-db": "Kunde inte skapa databasfilen <code>$1</code>.",
        "config-sqlite-fts3-downgrade": "PHP saknar stöd för FTS3, nedgraderar tabeller",
        "config-upgrade-done": "Uppgraderingen slutfördes.\n\nDu kan nu [$1 börja använda din wiki].\n\nOm du vill förnya din <code>LocalSettings.php</code>-fil, klicka på knappen nedan.\nDetta '''rekommenderas inte''' om du har problem med din wiki.",
        "config-upgrade-done-no-regenerate": "Uppgraderingen slutfördes.\n\nDu kan nu [$1 börja använda din wiki].",
        "config-regenerate": "Återskapa LocalSettings.php →",
+       "config-show-table-status": "<code>SHOW TABLE STATUS</code>-förfrågan misslyckades!",
        "config-unknown-collation": "'''Varning:''' Databasen använder en okänd sortering.",
        "config-db-web-account": "Databaskonto för webbaccess",
        "config-db-web-help": "Välj det användarnamn och lösenord som webbservern använder för att ansluta till databasservern, under ordinarie drift av wikin.",
        "config-mysql-utf8": "UTF-8",
        "config-mysql-charset-help": "I '''binärt läge''' lagrar MediaWiki UTF-8 text till databasen i binära fält.\nDetta är mer effektivt än MySQLs UTF-8-läge, och den tillåter dig att använda den fulla uppsättningen av Unicode-tecken.\n\nI '''UTF-8-läge''' vet MySQL vilket teckenuppsättning din data är i och kan presentera och konvertera den på ett lämpligt sätt, men den tillåter dig inte att lagra tecken över [//en.wikipedia.org/wiki/Mapping_of_Unicode_character_planes Basic Multilingual Plane].",
        "config-mssql-auth": "Autentiseringstyp:",
+       "config-mssql-install-auth": "Välj autentiseringstypen som kommer att användas för att ansluta till databasen under installationsprocessen.\nOm du väljer \"{{int:config-mssql-windowsauth}}\", kommer autentiseringsuppgifterna för den användare webbservern körs som att användas.",
+       "config-mssql-web-auth": "Välj autentiseringstypen som kommer att användas för att ansluta till databasen under ordinarie drift av wikin.\nOm du väljer \"{{int:config-mssql-windowsauth}}\", kommer autentiseringsuppgifterna för den användare webbservern körs som att användas.",
        "config-mssql-sqlauth": "SQL Server-autentisering",
        "config-mssql-windowsauth": "Windows-autentisering",
        "config-site-name": "Namnet på wikin:",
        "config-ns-site-name": "Samma som wikinamnet: $1",
        "config-ns-other": "Annan (specificera)",
        "config-ns-other-default": "MinWiki",
+       "config-project-namespace-help": "Per Wikipedias exempel håller många wikis sina policy-sidor separata från innehållssidorna i en \"'''projektnamnrymd'''\".\nAlla sidtitlar i denna namnrymd startar med ett visst prefix vilket du specificerar här.\nVanligtvis kan detta namn härledas från namnet på wikin, men den får inte innehålla interpunktionstecken som exempelvis \"#\" eller \":\".",
        "config-ns-invalid": "Den angivna namnrymden \"<nowiki>$1</nowiki>\" är ogiltig.\nAnge en annan namnrymd för projektet.",
        "config-ns-conflict": "Den angivna namnrymden \"<nowiki>$1</nowiki>\" står i konflikt med en standardnamnrymd för MediaWiki.\nAnge en annan namnrymd för projektet.",
        "config-admin-box": "Administratörskonto",
        "config-admin-error-password": "Internt fel lösenordet för administratören \"<nowiki>$1</nowiki>\" ställdes in: <pre>$2</pre>",
        "config-admin-error-bademail": "Du har angivit en ogiltig e-postadress.",
        "config-subscribe": "Prenumerera på [https://lists.wikimedia.org/mailman/listinfo/mediawiki-announce e-postlistan för kungörelser av nya versioner].",
+       "config-subscribe-help": "Detta är en e-postlista med låg volym vilken används för meddelanden om nya versionssläpp, inklusive viktiga säkerhetsmeddelanden.\nDu bör prenumerera på den och uppdatera din MediaWiki-installation när nya versioner kommer ut.",
+       "config-subscribe-noemail": "Du försökte att prenumerera på e-postlistan för versionssläppsmeddelanden utan att tillhandahålla en e-postadress.\nAnge en e-postadress om du vill prenumerera på e-postlistan.",
        "config-almost-done": "Du är nästan färdig!\nDu kan nu hoppa över återstående konfigurationer och installera wikin direkt.",
        "config-optional-continue": "Ställ fler frågor till mig.",
        "config-optional-skip": "Jag är redan uttråkad, bara installera wiki.",
+       "config-profile": "Profil för användarrättigheter:",
        "config-profile-wiki": "Öppen wiki",
        "config-profile-no-anon": "Kontoskapande krävs",
        "config-profile-fishbowl": "Endast auktoriserade redigerare",
        "config-profile-private": "Privat wiki",
+       "config-profile-help": "Wikis fungerar bäst när du låter som många människor som möjligt redigera dem.\nI MediaWiki, är det lätt att granska de senaste ändringarna och återställa alla skador som utförs av naiva eller illvilliga användare.\n\nMen många har funnit MediaWiki användbart i en mängd olika roller, och ibland är det inte lätt att övertyga alla fördelarna med wiki-sättet.\nSå valet är ditt.\n\nModellen <strong>{{int:config-profil-wiki}}</strong> tillåter vem som helst att redigera, utan att ens behöva logga in.\nEn wiki med <strong>{{int:config-profil-ingen-anon}}</strong> ger extra ansvarskänsla, men kan avskräcka tillfälliga bidragsgivare.\n\nScenariot <strong>{{int:config-profil-fishbowl}}</strong> tillåter godkända användare att redigera, men allmänheten kan se sidorna, inklusive historik.\nA <strong>{{int:config-profil-privat}}</strong> tillåter endast godkända användare att se sidor, samma grupp får även redigera.\n\nMer komplexa användarrättighetskonfigurationer finns tillgängliga efter installationen, se [//www.mediawiki.org/wiki/Special:MyLanguage/Manual:User_rights avsnittet i manualen].",
        "config-license": "Upphovsrätt och licens:",
        "config-license-none": "Ingen licenssidfot",
        "config-license-cc-by-sa": "Creative Commons Erkännande-DelaLika",
        "config-license-gfdl": "GNU Free Documentation License 1.3 eller senare",
        "config-license-pd": "Public Domain",
        "config-license-cc-choose": "Välj en anpassad Creative Commons-licens",
+       "config-license-help": "Många publika wikis släpper alla bidrag under en  [http://freedomdefined.org/Definition fri licens].\nDetta bidrar till en känsla av gemensamt ägandeskap och uppmuntrar till långsiktiga bidrag.\nDet är i allmänhet inte nödvändigt för en privat eller företagswiki.\n\nOm du vill kunna använda text från Wikipedia, och du vill att Wikipedia ska kunna acceptera text kopierad ifrån din wiki bör du välja <strong>Creative Commons Erkännande-DelaLika</strong>.\n\nWikipedia använde tidigare  GNU Free Documentation License.\nGFDL är en giltig licens, men svår att förstå.\nDet är även svårt att återanvända innehåll som licensierats under GFDL.",
        "config-email-settings": "E-postinställningar",
        "config-enable-email": "Aktivera utgående e-post",
+       "config-enable-email-help": "Om du vill att e-post ska fungera behöver,[http://www.php.net/manual/en/mail.configuration.php PHPs e-postinställningar] vara konfigurerad på rätt sätt.\nOm du inte vill ha några e-postfunktioner, kan du inaktivera dem här.",
        "config-email-user": "Aktivera e-post mellan användare",
        "config-email-user-help": "Tillåta alla användare att skicka e-post till varandra om de har aktiverat det i sina inställningar.",
        "config-email-usertalk": "Aktivera meddelanden för användardiskussionssidor",
+       "config-email-usertalk-help": "Tillåt användare att få meddelanden när användardiskussionssidor ändras, om de har aktiverat detta i sina inställningar.",
        "config-email-watchlist": "Aktivera meddelanden för bevakningslistan",
+       "config-email-watchlist-help": "Tillåt användare att få meddelanden när deras bevakade sidor ändras, om de har aktiverat detta i sina inställningar.",
        "config-email-auth": "Aktivera autentisering via e-post",
+       "config-email-auth-help": "Om detta alternativ är aktiverat, måste användare bekräfta sin e-postadress via en länk som skickas till dem när de ställer in eller ändra den.\nEndast autentiserade e-postadresser kan ta emot e-post från andra användare eller ändra aviserings-e-post.\nDet här alternativet är <strong>rekommenderat</strong> för offentliga wikis på grund av potentiellt missbruk av e-postfunktionerna.",
+       "config-email-sender": "Returadress för e-post:",
+       "config-email-sender-help": "Ange den e-postadressen som ska användas som returadress på utgående e-post.\nDetta är dit studsar skickas.\nMånga mailservrar kräver att minst domännamndelen är giltigt.",
        "config-upload-settings": "Bild- och filuppladdningar",
        "config-upload-enable": "Aktivera filuppladdningar",
+       "config-upload-help": "Filuppladdning utsätter potentiellt din server för säkerhetsrisker.\nFör mer information, Läs  [//www.mediawiki.org/wiki/Special:MyLanguage/Manual:Security säkerhetsavsnittet] i manualen.\n\nFör att aktivera filuppladdning, ändra läget för <code>images</code>-underkatalogen under rotkatalogen för MediaWiki så att webbservern kan skriva till den.\nAktivera sedan detta alternativ.",
        "config-upload-deleted": "Katalog för raderade filer:",
+       "config-upload-deleted-help": "Välja en katalog i vilken raderade filer arkiveras.\nHelst bör denna inte vara tillgängliga från webben.",
        "config-logo": "Logotyp-URL:",
        "config-logo-help": "MediaWikis standardutseende innehåller ett mellanrum för en 135x160 bildpunkter stor logotyp ovanför sidofältsmenyn.\nLadda upp en bild med lämplig storlek och ange webbadressen här.\n\nDu kan använda <code>$wgStylePath</code> eller <code>$wgScriptPath</code> om din logotyp är relativ till dessa sökvägar.\n\nOm du inte vill ha en logotyp kan du lämna detta fält tomt.",
        "config-instantcommons": "Aktivera Instant Commons",
+       "config-instantcommons-help": "[//www.mediawiki.org/wiki/InstantCommons Instant Commons] är en funktion som gör det möjligt för wikis att använda bilder, ljud och andra media som finns på [//commons.wikimedia.org/ Wikimedia Commons]-webbplatsen.\nFör att göra detta, kräver MediaWiki tillgång till Internet.\n\nFör mer information om denna funktion, inklusive instruktioner om hur man ställer in den för andra wikis än Wikimedia Commons, se [//www.mediawiki.org/wiki/Special:MyLanguage/Manual:$wgForeignFileRepos manualen].",
        "config-cc-error": "Creative Commons-licens-väljaren gav inget resultat.\nAnge licensnamnet manuellt.",
        "config-cc-again": "Välj igen...",
        "config-cc-not-chosen": "Välj vilken Creative Commons-licens du vill ha och klicka på \"gå vidare\".",
        "config-advanced-settings": "Avancerad konfiguration",
+       "config-cache-options": "Inställningar för cachelagring av objekt:",
+       "config-cache-help": "Cachelagring av objekt används för att förbättra hastigheten på MediaWiki genom att cachelagra data som används ofta.\nMedelstora till stora webbplatser är starkt uppmuntrade att aktivera detta, och små webbplatser kommer även att se fördelar.",
+       "config-cache-none": "Ingen cachelagring (ingen funktionalitet tas bort, men hastighet kan påverkas på större wiki-webbplatser)",
+       "config-cache-accel": "Cachelagring av PHP-objekt (APC, XCache eller WinCache)",
+       "config-cache-memcached": "Använda Memcached (kräver ytterligare inställningar och konfiguration)",
+       "config-memcached-servers": "Memcached-servrar:",
+       "config-memcached-help": "Lista över IP-adresser som ska användas för Memcached.\nBör ange en per rad och specificera den port som ska användas. Till exempel:\n 127.0.0.1:11211\n 192.168.1.25:1234",
+       "config-memcache-needservers": "Du valde Memcached som din cachelagringstyp men angav inte några servrar.",
+       "config-memcache-badip": "Du har angett en ogiltig IP-adress för Memcached: $1.",
+       "config-memcache-noport": "Du angav inte en port som ska användas för Memcached-server: $1.\nOm du inte vet porten, är standard 11211.",
+       "config-memcache-badport": "Memcached-portnummer bör vara mellan $1 och $2.",
        "config-extensions": "Tillägg",
+       "config-extensions-help": "Tilläggen ovan upptäcktes i din <code>./extensions</code>-katalog.\n\nDe kan kräva ytterligare konfiguration, men du kan aktivera dem nu.",
        "config-install-alreadydone": "''' Varning:''' Du verkar redan ha installerat MediaWiki och försöker installera det igen.\nVänligen fortsätt till nästa sida.",
        "config-install-begin": "Genom att trycka på \"{{int:config-continue}}\", påbörjar du installationen av MediaWiki.\nOm du fortfarande vill göra ändringar tryck på \"{{int:config-back}}\".",
        "config-install-step-done": "klar",
        "config-install-pg-plpgsql": "Kontroll för språket PL/pgSQL",
        "config-pg-no-plpgsql": "Du måste installera språket PL/pgSQL i databasen $1",
        "config-pg-no-create-privs": "Det konto som du har angett för installationen har inte tillräcklig behörighet för att skapa ett konto.",
+       "config-pg-not-in-role": "Det konto du angav för webbanvändaren finns redan.\nKontot du angav för installationen är inte en superanvändare (superuser) och är inte en medlem av webbanvändarens roll, därför kan den inte skapa objekt som ägs av webbanvändaren.\n\nMediaWiki kräver för närvarande att tabellerna ägs av webbanvändaren. Vänligen ange ett annat webbkontonamn, eller klicka \"tillbaka\" och ange en installationsanvändare med passande behörigheter.",
        "config-install-user": "Skapar databasanvändare",
        "config-install-user-alreadyexists": "Användaren \"$1\" finns redan",
        "config-install-user-create-failed": "Misslyckades att skapa användare \"$1\": $2",
        "config-install-tables-failed": "'''Fel:''' Skapandet av tabell misslyckades med följande fel: $1",
        "config-install-interwiki": "Lägger till standardtabell för interwiki",
        "config-install-interwiki-list": "Kunde inte läsa filen <code>interwiki.list</code>.",
+       "config-install-interwiki-exists": "<strong>Varning:</strong> Interwiki-tabellen verkar redan innehålla poster.\nHoppar över standardlistan.",
        "config-install-stats": "Initierar statistik",
        "config-install-keys": "Genererar hemliga nycklar",
        "config-insecure-keys": "'''Varning:''' {{PLURAL:$2|En säkerhetsnyckel|Säkerhetsnycklar}} ($1) som generades under installationen är inte helt {{PLURAL:$2|säker|säkra}} . Överväg att ändra {{PLURAL:$2|den|dem}} manuellt.",
index f04fd5d..47749b7 100644 (file)
@@ -8,6 +8,7 @@
        "config-desc": "דער אינסטאלירער פאר מעדיעוויקי",
        "config-title": "מעדיעוויקי $1 אינסטאלירונג",
        "config-information": "אינפֿארמאציע",
+       "config-localsettings-badkey": "דעם שליסל וואס איר האט אײַנגעגעבן איז פאלש.",
        "config-session-error": "פֿעלער ביים אנהייבן סעסיע:$1",
        "config-your-language": "אײַער שפראך:",
        "config-your-language-help": "קלויבט א שפראך צו ניצן ביים אינסטאלירונג פראצעס.",
@@ -29,6 +30,9 @@
        "config-page-releasenotes": "ווערסיע־הערות",
        "config-page-copying": "קאפיע",
        "config-page-upgradedoc": "ראנג־העכערן",
+       "config-page-existingwiki": "עקזיסטירנדע וויקי",
+       "config-help-restart": "צי ווילט איר אפראמען די גארע געשפייכלערטע דאטן וואס איר האט אײַנגעגעבן און ווידער אנהייבן דעם אינסטאלאציע־פראצעס?",
+       "config-restart": "יא, ווידעראמאל אנהייבן",
        "config-env-php": "PHP $1 איז אינצטאלירט.",
        "config-apc": "[http://www.php.net/apc APC] איז אינסטאלירט",
        "config-wincache": "[http://www.iis.net/download/WinCacheForPhp WinCache] איז אינסטאלירט",
index fcb7a3e..6f67613 100644 (file)
@@ -19,7 +19,8 @@
                        "Qiyue2001",
                        "Kuailong",
                        "Zjzengdongyang",
-                       "Mywood"
+                       "Mywood",
+                       "Impersonator 1"
                ]
        },
        "config-desc": "MediaWiki安装程序",
@@ -72,7 +73,6 @@
        "config-no-db": "找不到合适的数据库驱动!您需要为PHP安装数据库驱动。目前支持以下数据库:$1。如果您是自己编译的PHP,请重新配置他与数据库客户端将其启用,诸如,使用<code>./configure --with-mysqli</code>。如果您从Debian或Ubuntu包安装了PHP,之后您仍需要安装诸如<code>php5-mysql</code>包。",
        "config-outdated-sqlite": "'''警告''':您已安装SQLite $1,但是它的版本低于最低要求版本$2。因此您无法选择SQLite。",
        "config-no-fts3": "'''警告''':已编译的SQLite不包含[//sqlite.org/fts3.html FTS3模块],后台搜索功能将不可用。",
-       "config-register-globals": "'''警告:PHP的<code>[http://php.net/register_globals register_globals]</code>选项被启用。请尽量禁用该功能,'''虽然不会影响MediaWiki的运行,但您的服务器会被暴露给潜在的安全漏洞。",
        "config-magic-quotes-runtime": "'''毁灭性错误:[http://www.php.net/manual/en/ref.info.php#ini.magic-quotes-runtime magic_quotes_runtime]已启用!'''\n此选项会无法预测地破坏输入的数据,请将其禁用,否则您将不能安装或使用MediaWiki。",
        "config-magic-quotes-sybase": "'''毁灭性错误:[http://www.php.net/manual/en/ref.info.php#ini.magic-quotes-runtime magic_quotes_sybase]已启用!'''\n此选项会无法预测地破坏输入的数据,请将其禁用,否则您将不能安装或使用MediaWiki。",
        "config-mbstring": "'''毁灭性错误:[http://www.php.net/manual/en/ref.mbstring.php#mbstring.overload mbstring.func_overload]已启用!'''\n此选项会导致错误并不可预测地破坏数据,请将其禁用,否则您将不能安装或使用MediaWiki。",
        "config-license-gfdl": "GNU自由文档许可证1.3或更高版本",
        "config-license-pd": "公有领域",
        "config-license-cc-choose": "选择自定义的知识共享许可证",
-       "config-license-help": "许多公共wiki会以[http://freedomdefined.org/Definition 自由许可证]的方式释放出编者的所有贡献。这有助于构建社区的主人翁意识,并能鼓励长期贡献。对于非公共wiki或公司wiki,这并非必要条件。\n\n如果您希望使用来自维基百科的内容,并希望维基百科能接受复制自您的wiki的内容,请选择'''知识共享署名-相同方式共享'''。\n\nGNU自由文档许可证是维基百科曾经使用过的许可证,并迄今有效。然而,该许可证难以理解,并会增加重用内容的难度。",
+       "config-license-help": "许多公共wiki会以[http://freedomdefined.org/Definition 自由许可证]的方式释放出编者的所有贡献。这有助于构建社区的主人翁意识,并能鼓励长期贡献。对于非公共wiki或公司wiki,这并非必要条件。\n\n如果您希望使用来自维基百科的内容,并希望维基百科能接受复制自您的wiki的内容,您应当选择<strong>知识共享-署名-相同方式共享</strong>。\n\nGNU自由文档许可证是维基百科曾经使用过的许可证,并迄今有效。然而,该许可证难以理解,并会增加重用内容的难度。",
        "config-email-settings": "电子邮件设置",
        "config-enable-email": "启用出站电子邮件",
        "config-enable-email-help": "如果您希望使用电子邮件功能,请正确配置[http://www.php.net/manual/en/mail.configuration.php PHP的邮件设定]。如果您不需要任何电子邮件功能,请在此处禁用它。",
index 6739a84..088f447 100644 (file)
@@ -313,7 +313,7 @@ LUA;
                                } else {
                                        $blob = $this->popAndDeleteBlob( $conn );
                                }
-                               if ( $blob === false ) {
+                               if ( !is_string( $blob ) ) {
                                        break; // no jobs; nothing to do
                                }
 
@@ -703,6 +703,7 @@ LUA;
                                $count += $released + $pruned + $undelayed;
                                JobQueue::incrStats( 'job-recycle', $this->type, $released, $this->wiki );
                                JobQueue::incrStats( 'job-abandon', $this->type, $abandoned, $this->wiki );
+                               JobQueue::incrStats( 'job-undelay', $this->type, $undelayed, $this->wiki );
                        }
                } catch ( RedisException $e ) {
                        $this->throwRedisException( $conn, $e );
index 10277e6..6b10ae4 100644 (file)
@@ -40,6 +40,7 @@ class CSSMin {
        const EMBED_SIZE_LIMIT = 24576;
        const URL_REGEX = 'url\(\s*[\'"]?(?P<file>[^\?\)\'"]*?)(?P<query>\?[^\)\'"]*?|)[\'"]?\s*\)';
        const EMBED_REGEX = '\/\*\s*\@embed\s*\*\/';
+       const COMMENT_REGEX = '\/\*.*?\*\/';
 
        /* Protected Static Members */
 
@@ -203,13 +204,31 @@ class CSSMin {
                        $remote = substr( $remote, 0, -1 );
                }
 
+               // Replace all comments by a placeholder so they will not interfere
+               // with the remapping
+               // Warning: This will also catch on anything looking like the start of
+               // a comment between quotation marks (e.g. "foo /* bar").
+               $comments = array();
+               $placeholder = uniqid( '', true );
+
+               $pattern = '/(?!' . CSSMin::EMBED_REGEX . ')(' . CSSMin::COMMENT_REGEX . ')/s';
+
+               $source = preg_replace_callback(
+                       $pattern,
+                       function ( $match ) use ( &$comments, $placeholder ) {
+                               $comments[] = $match[ 0 ];
+                               return $placeholder . ( count( $comments ) - 1 ) . 'x';
+                       },
+                       $source
+               );
+
                // Note: This will not correctly handle cases where ';', '{' or '}'
                // appears in the rule itself, e.g. in a quoted string. You are advised
                // not to use such characters in file names. We also match start/end of
                // the string to be consistent in edge-cases ('@import url(…)').
                $pattern = '/(?:^|[;{])\K[^;{}]*' . CSSMin::URL_REGEX . '[^;}]*(?=[;}]|$)/';
 
-               return preg_replace_callback(
+               $source = preg_replace_callback(
                        $pattern,
                        function ( $matchOuter ) use ( $local, $remote, $embedData ) {
                                $rule = $matchOuter[0];
@@ -262,6 +281,15 @@ class CSSMin {
                                        return $ruleWithRemapped;
                                }
                        }, $source );
+
+               // Re-insert comments
+               $pattern = '/' . $placeholder . '(\d+)x/';
+               $source = preg_replace_callback( $pattern, function( $match ) use ( &$comments ) {
+                       return $comments[ $match[1] ];
+               }, $source );
+
+               return $source;
+
        }
 
        /**
index df99098..2022b22 100644 (file)
@@ -198,7 +198,7 @@ class HashRing {
                        }
                }
                if ( !$this->liveRing ) {
-                       throw UnexpectedValueException( "The live ring is currently empty." );
+                       throw new UnexpectedValueException( "The live ring is currently empty." );
                }
 
                return $this->liveRing;
index d72ffca..809bfdf 100644 (file)
@@ -28,8 +28,6 @@ class HttpStatus {
        /**
         * Get the message associated with HTTP response code $code
         *
-        * Replace OutputPage::getStatusMessage( $code )
-        *
         * @param $code Integer: status code
         * @return String or null: message or null if $code is not in the list of
         *         messages
index bcef433..4f2a565 100644 (file)
@@ -30,7 +30,7 @@ class PatrolLog {
        /**
         * Record a log event for a change being patrolled
         *
-        * @param mixed $rc Change identifier or RecentChange object
+        * @param int|RecentChange $rc Change identifier or RecentChange object
         * @param bool $auto Was this patrol event automatic?
         * @param User $user User performing the action or null to use $wgUser
         *
index 44be178..9a3e927 100644 (file)
@@ -117,6 +117,7 @@ class BitmapHandler extends ImageHandler {
                if ( !$this->normaliseParams( $image, $params ) ) {
                        return new TransformParameterError( $params );
                }
+
                # Create a parameter array to pass to the scaler
                $scalerParams = array(
                        # The size to which the image will be resized
@@ -187,7 +188,12 @@ class BitmapHandler extends ImageHandler {
                }
 
                # Transform functions and binaries need a FS source file
-               $scalerParams['srcPath'] = $image->getLocalRefPath();
+               $thumbnailSource = $image->getThumbnailSource( $params );
+
+               $scalerParams['srcPath'] = $thumbnailSource['path'];
+               $scalerParams['srcWidth'] = $thumbnailSource['width'];
+               $scalerParams['srcHeight'] = $thumbnailSource['height'];
+
                if ( $scalerParams['srcPath'] === false ) { // Failed to get local copy
                        wfDebugLog( 'thumbnail',
                                sprintf( 'Thumbnail failed on %s: could not get local copy of "%s"',
@@ -354,7 +360,30 @@ class BitmapHandler extends ImageHandler {
                                }
                        }
                } elseif ( $params['mimeType'] == 'image/x-xcf' ) {
-                       $animation_post = array( '-layers', 'merge' );
+                       // Before merging layers, we need to set the background
+                       // to be transparent to preserve alpha, as -layers merge
+                       // merges all layers on to a canvas filled with the
+                       // background colour. After merging we reset the background
+                       // to be white for the default background colour setting
+                       // in the PNG image (which is used in old IE)
+                       $animation_post = array(
+                               '-background', 'transparent',
+                               '-layers', 'merge',
+                               '-background', 'white',
+                       );
+                       wfSuppressWarnings();
+                       $xcfMeta = unserialize( $image->getMetadata() );
+                       wfRestoreWarnings();
+                       if ( $xcfMeta
+                               && isset( $xcfMeta['colorType'] )
+                               && $xcfMeta['colorType'] === 'greyscale-alpha'
+                               && version_compare( $this->getMagickVersion(), "6.8.9-3" ) < 0
+                       ) {
+                               // bug 66323 - Greyscale images not rendered properly.
+                               // So only take the "red" channel.
+                               $channelOnly = array( '-channel', 'R', '-separate' );
+                               $animation_post = array_merge( $animation_post, $channelOnly );
+                       }
                }
 
                // Use one thread only, to avoid deadlock bugs on OOM
@@ -845,7 +874,7 @@ class BitmapHandler extends ImageHandler {
        }
 
        /**
-        * Rerurns whether the file needs to be rendered. Returns true if the
+        * Returns whether the file needs to be rendered. Returns true if the
         * file requires rotation and we are able to rotate it.
         *
         * @param File $file
index fca1c6d..4200541 100644 (file)
@@ -1302,7 +1302,6 @@ class FormatMetadata extends ContextSource {
         * @param int $a Numerator
         * @param int $b Denominator
         * @return int
-        * @private
         */
        private function gcd( $a, $b ) {
                /*
@@ -1871,29 +1870,3 @@ class FormatMetadata extends ContextSource {
                return $priorityLanguages;
        }
 }
-
-/** For compatability with old FormatExif class
- * which some extensions use.
- *
- * @deprecated since 1.18
- *
- */
-class FormatExif {
-       /** @var array */
-       private $meta;
-
-       /**
-        * @param array $meta
-        */
-       function __construct( $meta ) {
-               wfDeprecated( __METHOD__, '1.18' );
-               $this->meta = $meta;
-       }
-
-       /**
-        * @return array
-        */
-       function getFormattedData() {
-               return FormatMetadata::getFormattedData( $this->meta );
-       }
-}
index 8a12e7e..6dd0453 100644 (file)
@@ -269,4 +269,20 @@ abstract class ImageHandler extends MediaHandler {
                                ->numParams( $file->getWidth(), $file->getHeight() )->text();
                }
        }
+
+       public function sanitizeParamsForBucketing( $params ) {
+               $params = parent::sanitizeParamsForBucketing( $params );
+
+               // We unset the height parameters in order to let normaliseParams recalculate them
+               // Otherwise there might be a height discrepancy
+               if ( isset( $params['height'] ) ) {
+                       unset( $params['height'] );
+               }
+
+               if ( isset( $params['physicalHeight'] ) ) {
+                       unset( $params['physicalHeight'] );
+               }
+
+               return $params;
+       }
 }
index a0f7acb..918d4ae 100644 (file)
@@ -158,4 +158,19 @@ class JpegHandler extends ExifBitmapHandler {
                        return parent::rotate( $file, $params );
                }
        }
+
+       public function supportsBucketing() {
+               return true;
+       }
+
+       public function sanitizeParamsForBucketing( $params ) {
+               $params = parent::sanitizeParamsForBucketing( $params );
+
+               // Quality needs to be cleared for bucketing. Buckets need to be default quality
+               if ( isset( $params['quality'] ) ) {
+                       unset( $params['quality'] );
+               }
+
+               return $params;
+       }
 }
index f6717cd..c4aab7b 100644 (file)
@@ -831,4 +831,24 @@ abstract class MediaHandler {
        public function isExpensiveToThumbnail( $file ) {
                return false;
        }
+
+       /**
+        * Returns whether or not this handler supports the chained generation of thumbnails according
+        * to buckets
+        * @return boolean
+        * @since  1.24
+        */
+       public function supportsBucketing() {
+               return false;
+       }
+
+       /**
+        * Returns a normalised params array for which parameters have been cleaned up for bucketing
+        * purposes
+        * @param array $params
+        * @return array
+        */
+       public function sanitizeParamsForBucketing( $params ) {
+               return $params;
+       }
 }
index 968db10..d879c12 100644 (file)
@@ -173,4 +173,8 @@ class PNGHandler extends BitmapHandler {
 
                return $wgLang->commaList( $info );
        }
+
+       public function supportsBucketing() {
+               return true;
+       }
 }
index 41e6f03..b303a01 100644 (file)
@@ -61,7 +61,28 @@ class XCFHandler extends BitmapHandler {
         * @return array
         */
        function getImageSize( $image, $filename ) {
-               return self::getXCFMetaData( $filename );
+               $header = self::getXCFMetaData( $filename );
+               if ( !$header ) {
+                       return false;
+               }
+
+               # Forge a return array containing metadata information just like getimagesize()
+               # See PHP documentation at: http://www.php.net/getimagesize
+               $metadata = array();
+               $metadata[0] = $header['width'];
+               $metadata[1] = $header['height'];
+               $metadata[2] = null; # IMAGETYPE constant, none exist for XCF.
+               $metadata[3] = sprintf(
+                       'height="%s" width="%s"', $header['height'], $header['width']
+               );
+               $metadata['mime'] = 'image/x-xcf';
+               $metadata['channels'] = null;
+               $metadata['bits'] = 8; # Always 8-bits per color
+
+               assert( '7 == count($metadata); ' .
+                       '# return array must contains 7 elements just like getimagesize() return' );
+
+               return $metadata;
        }
 
        /**
@@ -124,23 +145,61 @@ class XCFHandler extends BitmapHandler {
                wfDebug( __METHOD__ .
                        ": canvas size of '$filename' is {$header['width']} x {$header['height']} px\n" );
 
-               # Forge a return array containing metadata information just like getimagesize()
-               # See PHP documentation at: http://www.php.net/getimagesize
+               return $header;
+       }
+
+       /**
+        * Store the channel type
+        *
+        * Greyscale files need different command line options.
+        *
+        * @param File $file The image object, or false if there isn't one.
+        *   Warning, FSFile::getPropsFromPath might pass an (object)array() instead (!)
+        * @param string $path The filename
+        * @return string
+        */
+       public function getMetadata( $file, $filename ) {
+               $header = self::getXCFMetadata( $filename );
                $metadata = array();
-               $metadata[0] = $header['width'];
-               $metadata[1] = $header['height'];
-               $metadata[2] = null; # IMAGETYPE constant, none exist for XCF.
-               $metadata[3] = sprintf(
-                       'height="%s" width="%s"', $header['height'], $header['width']
-               );
-               $metadata['mime'] = 'image/x-xcf';
-               $metadata['channels'] = null;
-               $metadata['bits'] = 8; # Always 8-bits per color
+               if ( $header ) {
+                       // Try to be consistent with the names used by PNG files.
+                       // Unclear from base media type if it has an alpha layer,
+                       // so just assume that it does since it "potentially" could.
+                       switch( $header['base_type'] ) {
+                       case 0:
+                               $metadata['colorType'] = 'truecolour-alpha';
+                               break;
+                       case 1:
+                               $metadata['colorType'] = 'greyscale-alpha';
+                               break;
+                       case 2:
+                               $metadata['colorType'] = 'index-coloured';
+                               break;
+                       default:
+                               $metadata['colorType'] = 'unknown';
 
-               assert( '7 == count($metadata); ' .
-                       '# return array must contains 7 elements just like getimagesize() return' );
+                       }
+               } else {
+                       // Marker to prevent repeated attempted extraction
+                       $metadata['error'] = true;
+               }
+               return serialize( $metadata );
+       }
 
-               return $metadata;
+       /**
+        * Should we refresh the metadata
+        *
+        * @param File $file The file object for the file in question
+        * @param string $metadata Serialized metadata
+        * @return bool One of the self::METADATA_(BAD|GOOD|COMPATIBLE) constants
+        */
+       public function isMetadataValid( $file, $metadata ) {
+               if ( !$metadata ) {
+                       // Old metadata when we just put an empty string in there
+                       return self::METADATA_BAD;
+               } else {
+                       return self::METADATA_GOOD;
+               }
        }
 
        /**
@@ -153,4 +212,20 @@ class XCFHandler extends BitmapHandler {
        protected static function getScalerType( $dstPath, $checkDstPath = true ) {
                return "im";
        }
+
+       /**
+        * Can we render this file?
+        *
+        * Image magick doesn't support indexed xcf files as of current
+        * writing (as of 6.8.9-3)
+        */
+       public function canRender( $file ) {
+               wfSuppressWarnings();
+               $xcfMeta = unserialize( $file->getMetadata() );
+               wfRestoreWarnings();
+               if ( isset( $xcfMeta['colorType'] ) && $xcfMeta['colorType'] === 'index-coloured' ) {
+                       return false;
+               }
+               return parent::canRender( $file );
+       }
 }
index 55d5319..a74b701 100644 (file)
@@ -23,7 +23,7 @@
 
 /**
  * Class for reading xmp data containing properties relevant to
- * images, and spitting out an array that FormatExif accepts.
+ * images, and spitting out an array that FormatMetadata accepts.
  *
  * Note, this is not meant to recognize every possible thing you can
  * encode in XMP. It should recognize all the properties we want.
index c798187..7a4de3b 100644 (file)
@@ -65,6 +65,9 @@ text/plain    [TEXT]
 text/html application/xhtml+xml        [TEXT]
 application/xml text/xml       [TEXT]
 text   [TEXT]
+application/json       [TEXT]
+text/csv       [TEXT]
+text/tab-separated-values      [TEXT]
 
 application/zip application/x-zip      [ARCHIVE]
 application/x-gzip     [ARCHIVE]
@@ -108,3 +111,8 @@ application/vnd.ms-excel.template.macroEnabled.12                           [OFFICE]
 application/vnd.ms-excel.addin.macroEnabled.12                                 [OFFICE]
 application/vnd.ms-excel.sheet.binary.macroEnabled.12                          [OFFICE]
 application/acad application/x-acad application/autocad_dwg image/x-dwg application/dwg application/x-dwg application/x-autocad image/vnd.dwg drawing/dwg [DRAWING]
+chemical/x-mdl-molfile     [DRAWING]
+chemical/x-mdl-sdfile      [DRAWING]
+chemical/x-mdl-rxnfile     [DRAWING]
+chemical/x-mdl-rdfile      [DRAWING]
+chemical/x-mdl-rgfile      [DRAWING]
index 61f7ff5..ae6ca4d 100644 (file)
@@ -35,6 +35,7 @@ application/x-gzip gz
 application/x-hdf hdf
 application/x-jar jar
 application/x-javascript js
+application/json json
 application/x-koan skp skd skt skm
 application/x-latex latex
 application/x-netcdf nc cdf
@@ -109,6 +110,7 @@ model/mesh msh mesh silo
 model/vrml wrl vrml
 text/calendar ics ifb
 text/css css
+text/csv csv
 text/html html htm
 text/plain txt
 text/richtext rtx
@@ -169,3 +171,8 @@ application/vnd.ms-excel.sheet.binary.macroEnabled.12 xlsb
 model/vnd.dwfx+xps dwfx
 application/vnd.ms-xpsdocument xps
 application/x-opc+zip docx dotx docm dotm potx ppsx pptx ppam pptm potm ppsm xlsx xltx xlsm xltm xlam xlsb dwfx xps
+chemical/x-mdl-molfile mol
+chemical/x-mdl-sdfile sdf
+chemical/x-mdl-rxnfile rxn
+chemical/x-mdl-rdfile rd
+chemical/x-mdl-rgfile rg
index 60db202..89ca241 100644 (file)
@@ -296,7 +296,7 @@ class ImagePage extends Article {
        }
 
        protected function openShowImage() {
-               global $wgImageLimits, $wgEnableUploads, $wgSend404Code;
+               global $wgEnableUploads, $wgSend404Code;
 
                $this->loadFile();
                $out = $this->getContext()->getOutput();
@@ -341,49 +341,17 @@ class ImagePage extends Article {
 
                        if ( $this->displayImg->allowInlineDisplay() ) {
                                # image
-
                                # "Download high res version" link below the image
                                # $msgsize = wfMessage( 'file-info-size', $width_orig, $height_orig,
                                #   Linker::formatSize( $this->displayImg->getSize() ), $mime )->escaped();
                                # We'll show a thumbnail of this image
-                               if ( $width > $maxWidth || $height > $maxHeight ) {
-                                       # Calculate the thumbnail size.
-                                       # First case, the limiting factor is the width, not the height.
-                                       /** @todo // FIXME: Possible division by 0. bug 36911 */
-                                       if ( $width / $height >= $maxWidth / $maxHeight ) {
-                                               /** @todo // FIXME: Possible division by 0. bug 36911 */
-                                               $height = round( $height * $maxWidth / $width );
-                                               $width = $maxWidth;
-                                               # Note that $height <= $maxHeight now.
-                                       } else {
-                                               /** @todo // FIXME: Possible division by 0. bug 36911 */
-                                               $newwidth = floor( $width * $maxHeight / $height );
-                                               /** @todo // FIXME: Possible division by 0. bug 36911 */
-                                               $height = round( $height * $newwidth / $width );
-                                               $width = $newwidth;
-                                               # Note that $height <= $maxHeight now, but might not be identical
-                                               # because of rounding.
-                                       }
+                               if ( $width > $maxWidth || $height > $maxHeight || $this->displayImg->isVectorized() ) {
+                                       list( $width, $height ) = $this->getDisplayWidthHeight(
+                                               $maxWidth, $maxHeight, $width, $height
+                                       );
                                        $linktext = wfMessage( 'show-big-image' )->escaped();
-                                       if ( $this->displayImg->getRepo()->canTransformVia404() ) {
-                                               $thumbSizes = $wgImageLimits;
-                                               // Also include the full sized resolution in the list, so
-                                               // that users know they can get it. This will link to the
-                                               // original file asset if mustRender() === false. In the case
-                                               // that we mustRender, some users have indicated that they would
-                                               // find it useful to have the full size image in the rendered
-                                               // image format.
-                                               $thumbSizes[] = array( $width_orig, $height_orig );
-                                       } else {
-                                               # Creating thumb links triggers thumbnail generation.
-                                               # Just generate the thumb for the current users prefs.
-                                               $thumbSizes = array( $this->getImageLimitsFromOption( $user, 'thumbsize' ) );
-                                               if ( !$this->displayImg->mustRender() ) {
-                                                       // We can safely include a link to the "full-size" preview,
-                                                       // without actually rendering.
-                                                       $thumbSizes[] = array( $width_orig, $height_orig );
-                                               }
-                                       }
+
+                                       $thumbSizes = $this->getThumbSizes( $width, $height, $width_orig, $height_orig );
                                        # Generate thumbnails or thumbnail links as needed...
                                        $otherSizes = array();
                                        foreach ( $thumbSizes as $size ) {
@@ -393,7 +361,10 @@ class ImagePage extends Article {
                                                // the current thumbnail's size ($width/$height)
                                                // since that is added to the message separately, so
                                                // it can be denoted as the current size being shown.
-                                               if ( $size[0] <= $width_orig && $size[1] <= $height_orig
+                                               // Vectorized images are "infinitely" big, so all thumb
+                                               // sizes are shown.
+                                               if ( ( ($size[0] <= $width_orig && $size[1] <= $height_orig)
+                                                               || $this->displayImg->isVectorized() )
                                                        && $size[0] != $width && $size[1] != $height
                                                ) {
                                                        $sizeLink = $this->makeSizeLink( $params, $size[0], $size[1] );
@@ -403,6 +374,7 @@ class ImagePage extends Article {
                                                }
                                        }
                                        $otherSizes = array_unique( $otherSizes );
+
                                        $msgsmall = '';
                                        $sizeLinkBigImagePreview = $this->makeSizeLink( $params, $width, $height );
                                        if ( $sizeLinkBigImagePreview ) {
@@ -421,9 +393,6 @@ class ImagePage extends Article {
                                        # Some sort of audio file that doesn't have dimensions
                                        # Don't output a no hi res message for such a file
                                        $msgsmall = '';
-                               } elseif ( $this->displayImg->isVectorized() ) {
-                                       # For vectorized images, full size is just the frame size
-                                       $msgsmall = '';
                                } else {
                                        # Image is small enough to show full size on image page
                                        $msgsmall = wfMessage( 'file-nohires' )->parse();
@@ -1084,6 +1053,81 @@ EOT
                );
                return $langSelectLine;
        }
+
+       /**
+        * Get the width and height to display image at.
+        *
+        * @note This method assumes that it is only called if one
+        *  of the dimensions are bigger than the max, or if the
+        *  image is vectorized.
+        *
+        * @param $maxWidth integer Max width to display at
+        * @param $maxHeight integer Max height to display at
+        * @param $width integer Actual width of the image
+        * @param $height integer Actual height of the image
+        * @throws MWException
+        * @return Array (width, height)
+        */
+       protected function getDisplayWidthHeight( $maxWidth, $maxHeight, $width, $height ) {
+               if ( !$maxWidth || !$maxHeight ) {
+                       // should never happen
+                       throw new MWException( 'Using a choice from $wgImageLimits that is 0x0' );
+               }
+
+               if ( !$width || !$height ) {
+                       return array( 0, 0 );
+               }
+
+               # Calculate the thumbnail size.
+               if ( $width <= $maxWidth && $height <= $maxHeight ) {
+                       // Vectorized image, do nothing.
+               } elseif ( $width / $height >= $maxWidth / $maxHeight ) {
+                       # The limiting factor is the width, not the height.
+                       $height = round( $height * $maxWidth / $width );
+                       $width = $maxWidth;
+                       # Note that $height <= $maxHeight now.
+               } else {
+                       $newwidth = floor( $width * $maxHeight / $height );
+                       $height = round( $height * $newwidth / $width );
+                       $width = $newwidth;
+                       # Note that $height <= $maxHeight now, but might not be identical
+                       # because of rounding.
+               }
+               return array( $width, $height );
+       }
+
+       /**
+        * Get alternative thumbnail sizes.
+        *
+        * @note This will only list several alternatives if thumbnails are rendered on 404
+        * @param $origWidth Actual width of image
+        * @param $origHeight Actual height of image
+        * @return Array An array of [width, height] pairs.
+        */
+       protected function getThumbSizes( $origWidth, $origHeight ) {
+               global $wgImageLimits;
+               if ( $this->displayImg->getRepo()->canTransformVia404() ) {
+                       $thumbSizes = $wgImageLimits;
+                       // Also include the full sized resolution in the list, so
+                       // that users know they can get it. This will link to the
+                       // original file asset if mustRender() === false. In the case
+                       // that we mustRender, some users have indicated that they would
+                       // find it useful to have the full size image in the rendered
+                       // image format.
+                       $thumbSizes[] = array( $origWidth, $origHeight );
+               } else {
+                       # Creating thumb links triggers thumbnail generation.
+                       # Just generate the thumb for the current users prefs.
+                       $thumbSizes = array( $this->getImageLimitsFromOption( $this->getContext()->getUser(), 'thumbsize' ) );
+                       if ( !$this->displayImg->mustRender() ) {
+                               // We can safely include a link to the "full-size" preview,
+                               // without actually rendering.
+                               $thumbSizes[] = array( $origWidth, $origHeight );
+                       }
+               }
+               return $thumbSizes;
+       }
+
 }
 
 /**
index 7c412ea..2bcf276 100644 (file)
@@ -3503,17 +3503,6 @@ class WikiPage implements Page, IDBAccessObject {
                return $wgParser->preSaveTransform( $text, $this->mTitle, $user, $popts );
        }
 
-       /**
-        * Check whether the number of revisions of this page surpasses $wgDeleteRevisionsLimit
-        *
-        * @deprecated since 1.19; use Title::isBigDeletion() instead.
-        * @return bool
-        */
-       public function isBigDeletion() {
-               wfDeprecated( __METHOD__, '1.19' );
-               return $this->mTitle->isBigDeletion();
-       }
-
        /**
         * Get the  approximate revision count of this page.
         *
index cde7a2d..79c8ade 100644 (file)
@@ -378,7 +378,7 @@ class CoreParserFunctions {
                // list of disallowed tags for DISPLAYTITLE
                // these will be escaped even though they are allowed in normal wiki text
                $bad = array( 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'div', 'blockquote', 'ol', 'ul', 'li', 'hr',
-                       'table', 'tr', 'th', 'td', 'dl', 'dd', 'caption', 'p', 'ruby', 'rb', 'rt', 'rp', 'br' );
+                       'table', 'tr', 'th', 'td', 'dl', 'dd', 'caption', 'p', 'ruby', 'rb', 'rt', 'rtc', 'rp', 'br' );
 
                // disallow some styles that could be used to bypass $wgRestrictDisplayTitle
                if ( $wgRestrictDisplayTitle ) {
index 8546348..648667b 100644 (file)
 class LinkHolderArray {
        var $internals = array(), $interwikis = array();
        var $size = 0;
+
+       /**
+        * @var Parser
+        */
        var $parent;
        protected $tempIdOffset;
 
+       /**
+        * @param Parser $parent
+        */
        function __construct( $parent ) {
                $this->parent = $parent;
        }
@@ -144,6 +151,10 @@ class LinkHolderArray {
                return $texts;
        }
 
+       /**
+        * @param array $m
+        * @return string
+        */
        protected function mergeForeignCallback( $m ) {
                return $m[1] . ( $m[2] + $this->tempIdOffset ) . $m[3];
        }
@@ -297,6 +308,7 @@ class LinkHolderArray {
                $queries = array();
                foreach ( $this->internals as $ns => $entries ) {
                        foreach ( $entries as $entry ) {
+                               /** @var Title $title */
                                $title = $entry['title'];
                                $pdbk = $entry['pdbk'];
 
@@ -329,7 +341,7 @@ class LinkHolderArray {
                                $where[] = $dbr->makeList(
                                        array(
                                                'page_namespace' => $ns,
-                                               'page_title' => $pages,
+                                               'page_title' => array_unique( $pages ),
                                        ),
                                        LIST_AND
                                );
@@ -490,6 +502,7 @@ class LinkHolderArray {
                // Then add variants of links to link batch
                $parentTitle = $this->parent->getTitle();
                foreach ( $titlesAttrs as $i => $attrs ) {
+                       /** @var Title $title */
                        list( $index, $title ) = $attrs;
                        $ns = $title->getNamespace();
                        $text = $title->getText();
index eb7bd1b..e5917b8 100644 (file)
@@ -5013,9 +5013,9 @@ class Parser {
         * private variables.**
         *
         * @param string $tag The tag to use, e.g. 'hook' for "<hook>"
-        * @param mixed $callback The callback function (and object) to use for the tag
+        * @param callable $callback The callback function (and object) to use for the tag
         * @throws MWException
-        * @return mixed|null The old value of the mTagHooks array associated with the hook
+        * @return callable|null The old value of the mTagHooks array associated with the hook
         */
        public function setHook( $tag, $callback ) {
                $tag = strtolower( $tag );
@@ -5044,9 +5044,9 @@ class Parser {
         * @todo better document or deprecate this
         *
         * @param string $tag The tag to use, e.g. 'hook' for "<hook>"
-        * @param mixed $callback The callback function (and object) to use for the tag
+        * @param callable $callback The callback function (and object) to use for the tag
         * @throws MWException
-        * @return mixed|null The old value of the mTagHooks array associated with the hook
+        * @return callable|null The old value of the mTagHooks array associated with the hook
         */
        function setTransparentTagHook( $tag, $callback ) {
                $tag = strtolower( $tag );
@@ -5085,7 +5085,7 @@ class Parser {
         *   isHTML                    The returned text is HTML, armour it against wikitext transformation
         *
         * @param string $id The magic word ID
-        * @param mixed $callback The callback function (and object) to use
+        * @param callable $callback The callback function (and object) to use
         * @param int $flags A combination of the following flags:
         *     SFH_NO_HASH   No leading hash, i.e. {{plural:...}} instead of {{#if:...}}
         *
@@ -5369,6 +5369,7 @@ class Parser {
                        $ig->add( $title, $label, $alt, $link, $handlerOptions );
                }
                $html = $ig->toHTML();
+               wfRunHooks( 'AfterParserFetchFileAndTitle', array( $this, $ig, &$html ) );
                wfProfileOut( __METHOD__ );
                return $html;
        }
index 90617b3..2cd208c 100644 (file)
@@ -422,11 +422,6 @@ class ParserOptions {
                return wfSetVar( $this->mTidy, $x );
        }
 
-       /** @deprecated since 1.19 */
-       function setSkin( $x ) {
-               wfDeprecated( __METHOD__, '1.19' );
-       }
-
        function setInterfaceMessage( $x ) {
                return wfSetVar( $this->mInterfaceMessage, $x );
        }
index 093fe49..2b37b0b 100644 (file)
@@ -154,8 +154,12 @@ class PoolCounterRedis extends PoolCounter {
                if rSlot ~= 'w' and redis.call('exists',kSlotsNextRelease) == 1 then
                        if 1*redis.call('zScore',kSlotsNextRelease,rSlot) ~= (rSlotTime + rExpiry) then
                                -- Slot lock expired and was released already
-                       elseif redis.call('lLen',kSlots) >= (1*rMaxWorkers - 1) then
-                               -- Clear list to save space; it will re-init as needed
+                       elseif redis.call('lLen',kSlots) >= 1*rMaxWorkers then
+                               -- Slots somehow got out of sync; reset the list for sanity
+                               redis.call('del',kSlots,kSlotsNextRelease)
+                       elseif redis.call('lLen',kSlots) == (1*rMaxWorkers - 1) and redis.call('zCard',kWaiting) == 0 then
+                               -- Slot list will be made full; clear it to save space (it re-inits as needed)
+                               -- since nothing is waiting on being unblocked by a push to the list
                                redis.call('del',kSlots,kSlotsNextRelease)
                        else
                                -- Add slot back to pool and update the "next release" time
index 7b82b7b..55c46c5 100644 (file)
@@ -55,8 +55,8 @@ class RevisionDeleteUser {
                $delUser = Revision::DELETED_USER | Revision::DELETED_RESTRICTED;
                $delAction = LogPage::DELETED_ACTION | Revision::DELETED_RESTRICTED;
                if ( $op == '&' ) {
-                       $delUser = "~{$delUser}";
-                       $delAction = "~{$delAction}";
+                       $delUser = $dbw->bitNot( $delUser );
+                       $delAction = $dbw->bitNot( $delAction );
                }
 
                # Normalize user name
@@ -66,14 +66,14 @@ class RevisionDeleteUser {
                # Hide name from live edits
                $dbw->update(
                        'revision',
-                       array( "rev_deleted = rev_deleted $op $delUser" ),
+                       array( self::buildSetBitDeletedField( 'rev_deleted', $op, $delUser, $dbw ) ),
                        array( 'rev_user' => $userId ),
                        __METHOD__ );
 
                # Hide name from deleted edits
                $dbw->update(
                        'archive',
-                       array( "ar_deleted = ar_deleted $op $delUser" ),
+                       array( self::buildSetBitDeletedField( 'ar_deleted', $op, $delUser, $dbw ) ),
                        array( 'ar_user_text' => $name ),
                        __METHOD__
                );
@@ -81,28 +81,28 @@ class RevisionDeleteUser {
                # Hide name from logs
                $dbw->update(
                        'logging',
-                       array( "log_deleted = log_deleted $op $delUser" ),
-                       array( 'log_user' => $userId, "log_type != 'suppress'" ),
+                       array( self::buildSetBitDeletedField( 'log_deleted', $op, $delUser, $dbw ) ),
+                       array( 'log_user' => $userId, 'log_type != ' . $dbw->addQuotes( 'suppress' ) ),
                        __METHOD__
                );
                $dbw->update(
                        'logging',
-                       array( "log_deleted = log_deleted $op $delAction" ),
+                       array( self::buildSetBitDeletedField( 'log_deleted', $op, $delAction, $dbw ) ),
                        array( 'log_namespace' => NS_USER, 'log_title' => $userDbKey,
-                               "log_type != 'suppress'" ),
+                               'log_type != ' . $dbw->addQuotes( 'suppress' ) ),
                        __METHOD__
                );
 
                # Hide name from RC
                $dbw->update(
                        'recentchanges',
-                       array( "rc_deleted = rc_deleted $op $delUser" ),
+                       array( self::buildSetBitDeletedField( 'rc_deleted', $op, $delUser, $dbw ) ),
                        array( 'rc_user_text' => $name ),
                        __METHOD__
                );
                $dbw->update(
                        'recentchanges',
-                       array( "rc_deleted = rc_deleted $op $delAction" ),
+                       array( self::buildSetBitDeletedField( 'rc_deleted', $op, $delAction, $dbw ) ),
                        array( 'rc_namespace' => NS_USER, 'rc_title' => $userDbKey, 'rc_logid > 0' ),
                        __METHOD__
                );
@@ -110,7 +110,7 @@ class RevisionDeleteUser {
                # Hide name from live images
                $dbw->update(
                        'oldimage',
-                       array( "oi_deleted = oi_deleted $op $delUser" ),
+                       array( self::buildSetBitDeletedField( 'oi_deleted', $op, $delUser, $dbw ) ),
                        array( 'oi_user_text' => $name ),
                        __METHOD__
                );
@@ -118,7 +118,7 @@ class RevisionDeleteUser {
                # Hide name from deleted images
                $dbw->update(
                        'filearchive',
-                       array( "fa_deleted = fa_deleted $op $delUser" ),
+                       array( self::buildSetBitDeletedField( 'fa_deleted', $op, $delUser, $dbw ) ),
                        array( 'fa_user_text' => $name ),
                        __METHOD__
                );
@@ -126,6 +126,12 @@ class RevisionDeleteUser {
                return true;
        }
 
+       private static function buildSetBitDeletedField( $field, $op, $value, $dbw ) {
+               return $field . ' = ' . ( $op === '&'
+                       ? $dbw->bitAnd( $field, $value )
+                       : $dbw->bitOr( $field, $value ) );
+       }
+
        public static function suppressUserName( $name, $userId, $dbw = null ) {
                return self::setUsernameBitfields( $name, $userId, '|', $dbw );
        }
index 8ff2640..581d8bc 100644 (file)
@@ -174,8 +174,6 @@ class SearchMySQL extends SearchDatabase {
        }
 
        protected function searchInternal( $term, $fulltext ) {
-               global $wgCountTotalSearchHits;
-
                // This seems out of place, why is this called with empty term?
                if ( trim( $term ) === '' ) {
                        return null;
@@ -189,19 +187,17 @@ class SearchMySQL extends SearchDatabase {
                );
 
                $total = null;
-               if ( $wgCountTotalSearchHits ) {
-                       $query = $this->getCountQuery( $filteredTerm, $fulltext );
-                       $totalResult = $this->db->select(
-                               $query['tables'], $query['fields'], $query['conds'],
-                               __METHOD__, $query['options'], $query['joins']
-                       );
-
-                       $row = $totalResult->fetchObject();
-                       if ( $row ) {
-                               $total = intval( $row->c );
-                       }
-                       $totalResult->free();
+               $query = $this->getCountQuery( $filteredTerm, $fulltext );
+               $totalResult = $this->db->select(
+                       $query['tables'], $query['fields'], $query['conds'],
+                       __METHOD__, $query['options'], $query['joins']
+               );
+
+               $row = $totalResult->fetchObject();
+               if ( $row ) {
+                       $total = intval( $row->c );
                }
+               $totalResult->free();
 
                return new SqlSearchResultSet( $resultSet, $this->searchTerms, $total );
        }
index f430dd0..698f93c 100644 (file)
@@ -173,7 +173,12 @@ class SqlSearchResultSet extends SearchResultSet {
        }
 
        function getTotalHits() {
-               return $this->totalHits;
+               if ( !is_null( $this->totalHits ) ) {
+                       return $this->totalHits;
+               } else {
+                       // Special:Search expects a number here.
+                       return $this->numRows();
+               }
        }
 }
 
index 8e820f3..05d5ca0 100644 (file)
@@ -164,7 +164,7 @@ class SearchSqlite extends SearchDatabase {
        }
 
        protected function searchInternal( $term, $fulltext ) {
-               global $wgCountTotalSearchHits, $wgContLang;
+               global $wgContLang;
 
                if ( !$this->fulltextSearchSupported() ) {
                        return null;
@@ -174,14 +174,12 @@ class SearchSqlite extends SearchDatabase {
                $resultSet = $this->db->query( $this->getQuery( $filteredTerm, $fulltext ) );
 
                $total = null;
-               if ( $wgCountTotalSearchHits ) {
-                       $totalResult = $this->db->query( $this->getCountQuery( $filteredTerm, $fulltext ) );
-                       $row = $totalResult->fetchObject();
-                       if ( $row ) {
-                               $total = intval( $row->c );
-                       }
-                       $totalResult->free();
+               $totalResult = $this->db->query( $this->getCountQuery( $filteredTerm, $fulltext ) );
+               $row = $totalResult->fetchObject();
+               if ( $row ) {
+                       $total = intval( $row->c );
                }
+               $totalResult->free();
 
                return new SqlSearchResultSet( $resultSet, $this->searchTerms, $total );
        }
index 1d8f57a..bf86ab2 100644 (file)
@@ -114,9 +114,10 @@ abstract class FormSpecialPage extends SpecialPage {
        /**
         * Process the form on POST submission.
         * @param array $data
-        * @return bool|array True for success, false for didn't-try, array of errors on failure
+        * @param HTMLForm $form
+        * @return bool|string|array|Status As documented for HTMLForm::trySubmit.
         */
-       abstract public function onSubmit( array $data );
+       abstract public function onSubmit( array $data /* $form = null */ );
 
        /**
         * Do something exciting on successful processing of the form, most likely to show a
index 3bdbc3c..cd41a1c 100644 (file)
@@ -153,10 +153,6 @@ abstract class SpecialRedirectToSpecial extends RedirectSpecialPage {
  * preference, useful for preloaded edits where you know preview wouldn't be
  * useful.
  *
- * - internaledit, externaledit, mode: Allows forcing the use of the
- * internal/external editor, e.g. to force the internal editor for
- * short/simple preloaded edits.
- *
  * - redlink: Affects the message the user sees if their talk page/user talk
  * page does not currently exist. Avoids confusion for newbies with no user
  * pages over why they got a "permission error" following this link:
@@ -194,7 +190,7 @@ abstract class RedirectSpecialArticle extends RedirectSpecialPage {
                        # Options for preloaded edits
                        'preload', 'editintro', 'preloadtitle', 'summary', 'nosummary',
                        # Options for overriding user settings
-                       'preview', 'internaledit', 'externaledit', 'mode', 'minor', 'watchthis',
+                       'preview', 'minor', 'watchthis',
                        # Options for history/diffs
                        'section', 'oldid', 'diff', 'dir',
                        'limit', 'offset', 'feed',
index c42c089..8dc4b3c 100644 (file)
@@ -92,12 +92,16 @@ class ActiveUsersPager extends UsersPager {
        function getQueryInfo() {
                $dbr = $this->getDatabase();
 
+               $activeUserSeconds = $this->getConfig()->get( 'ActiveUserDays' ) * 86400;
+               $timestamp = $dbr->timestamp( wfTimestamp( TS_UNIX ) - $activeUserSeconds );
                $conds = array(
                        'qcc_type' => 'activeusers',
                        'qcc_namespace' => NS_USER,
                        'user_name = qcc_title',
                        'rc_user_text = qcc_title',
-                       'rc_type != ' . $dbr->addQuotes( RC_EXTERNAL ) // Don't count wikidata.
+                       'rc_type != ' . $dbr->addQuotes( RC_EXTERNAL ), // Don't count wikidata.
+                       'rc_log_type IS NULL OR rc_log_type != ' . $dbr->addQuotes( 'newusers' ),
+                       'rc_timestamp >= ' . $dbr->addQuotes( $timestamp ),
                );
                if ( $this->requestedUser != '' ) {
                        $conds[] = 'qcc_title >= ' . $dbr->addQuotes( $this->requestedUser );
index a1e8d2b..05bbb5a 100644 (file)
@@ -270,30 +270,32 @@ class SpecialContributions extends IncludableSpecialPage {
                        // Show a note if the user is blocked and display the last block log entry.
                        // Do not expose the autoblocks, since that may lead to a leak of accounts' IPs,
                        // and also this will display a totally irrelevant log entry as a current block.
-                       $block = Block::newFromTarget( $userObj, $userObj );
-                       if ( !is_null( $block ) && $block->getType() != Block::TYPE_AUTO ) {
-                               if ( $block->getType() == Block::TYPE_RANGE ) {
-                                       $nt = MWNamespace::getCanonicalName( NS_USER ) . ':' . $block->getTarget();
-                               }
+                       if ( !$this->including() ) {
+                               $block = Block::newFromTarget( $userObj, $userObj );
+                               if ( !is_null( $block ) && $block->getType() != Block::TYPE_AUTO ) {
+                                       if ( $block->getType() == Block::TYPE_RANGE ) {
+                                               $nt = MWNamespace::getCanonicalName( NS_USER ) . ':' . $block->getTarget();
+                                       }
 
-                               $out = $this->getOutput(); // showLogExtract() wants first parameter by reference
-                               LogEventsList::showLogExtract(
-                                       $out,
-                                       'block',
-                                       $nt,
-                                       '',
-                                       array(
-                                               'lim' => 1,
-                                               'showIfEmpty' => false,
-                                               'msgKey' => array(
-                                                       $userObj->isAnon() ?
-                                                               'sp-contributions-blocked-notice-anon' :
-                                                               'sp-contributions-blocked-notice',
-                                                       $userObj->getName() # Support GENDER in 'sp-contributions-blocked-notice'
-                                               ),
-                                               'offset' => '' # don't use WebRequest parameter offset
-                                       )
-                               );
+                                       $out = $this->getOutput(); // showLogExtract() wants first parameter by reference
+                                       LogEventsList::showLogExtract(
+                                               $out,
+                                               'block',
+                                               $nt,
+                                               '',
+                                               array(
+                                                       'lim' => 1,
+                                                       'showIfEmpty' => false,
+                                                       'msgKey' => array(
+                                                               $userObj->isAnon() ?
+                                                                       'sp-contributions-blocked-notice-anon' :
+                                                                       'sp-contributions-blocked-notice',
+                                                               $userObj->getName() # Support GENDER in 'sp-contributions-blocked-notice'
+                                                       ),
+                                                       'offset' => '' # don't use WebRequest parameter offset
+                                               )
+                                       );
+                               }
                        }
                }
 
index f3af312..30e3833 100644 (file)
@@ -43,7 +43,7 @@ class SpecialCreateAccount extends SpecialRedirectToSpecial {
        }
 
        public function isRestricted() {
-               return true;
+               return !User::groupHasPermission( '*', 'createaccount' );
        }
 
        public function userCanExecute( User $user ) {
index b88e196..aec1257 100644 (file)
@@ -132,7 +132,11 @@ class LinkSearchPage extends QueryPage {
                                'target',
                                'target',
                                50,
-                               $target
+                               $target,
+                               array(
+                                       // URLs are always ltr
+                                       'dir' => 'ltr',
+                               )
                        ) . "\n";
 
                if ( !$wgMiserMode ) {
index 3715b8b..1faa013 100644 (file)
@@ -460,6 +460,19 @@ class ImageListPager extends TablePager {
                                        );
                                        $download = $this->msg( 'parentheses' )->rawParams( $download )->escaped();
 
+                                       // Add delete links if allowed
+                                       // From https://github.com/Wikia/app/pull/3859
+                                       if ( $filePage->userCan( 'delete', $this->getUser() ) ) {
+                                               $deleteMsg = $this->msg( 'listfiles-delete' )->escaped();
+
+                                               $delete = Linker::linkKnown(
+                                                       $filePage, $deleteMsg, array(), array( 'action' => 'delete' )
+                                               );
+                                               $delete = $this->msg( 'parentheses' )->rawParams( $delete )->escaped();
+
+                                               return "$link $download $delete";
+                                       }
+
                                        return "$link $download";
                                } else {
                                        return htmlspecialchars( $value );
index dce5ad9..7223efd 100644 (file)
@@ -567,10 +567,14 @@ class MovePageForm extends UnlistedSpecialPage {
                $oldLink = Linker::link(
                        $ot,
                        null,
-                       array(),
+                       array( 'id' => 'movepage-oldlink' ),
                        array( 'redirect' => 'no' )
                );
-               $newLink = Linker::linkKnown( $nt );
+               $newLink = Linker::linkKnown(
+                       $nt,
+                       null,
+                       array( 'id' => 'movepage-newlink' )
+               );
                $oldText = $ot->getPrefixedText();
                $newText = $nt->getPrefixedText();
 
index e22b42a..05f0b2b 100644 (file)
@@ -30,6 +30,7 @@
  */
 class SpecialPagesWithProp extends QueryPage {
        private $propName = null;
+       private $existingPropNames = null;
 
        function __construct( $name = 'PagesWithProp' ) {
                parent::__construct( $name );
@@ -47,18 +48,7 @@ class SpecialPagesWithProp extends QueryPage {
                $request = $this->getRequest();
                $propname = $request->getVal( 'propname', $par );
 
-               $dbr = wfGetDB( DB_SLAVE );
-               $res = $dbr->select(
-                       'page_props',
-                       'pp_propname',
-                       '',
-                       __METHOD__,
-                       array( 'DISTINCT', 'ORDER BY' => 'pp_propname' )
-               );
-               $propnames = array();
-               foreach ( $res as $row ) {
-                       $propnames[$row->pp_propname] = $row->pp_propname;
-               }
+               $propnames = $this->getExistingPropNames();
 
                $form = new HTMLForm( array(
                        'propname' => array(
@@ -88,6 +78,18 @@ class SpecialPagesWithProp extends QueryPage {
                parent::execute( $data['propname'] );
        }
 
+       /**
+        * Return an array of subpages beginning with $search that this special page will accept.
+        *
+        * @param string $search Prefix to search for
+        * @param integer $limit Maximum number of results to return
+        * @return string[] Matching subpages
+        */
+       public function prefixSearchSubpages( $search, $limit = 10 ) {
+               $subpages = array_keys( $this->getExistingPropNames() );
+               return self::prefixSearchArray( $search, $limit, $subpages );
+       }
+
        /**
         * Disable RSS/Atom feeds
         * @return bool
@@ -150,6 +152,25 @@ class SpecialPagesWithProp extends QueryPage {
                return $ret;
        }
 
+       public function getExistingPropNames() {
+               if ( $this->existingPropNames === null ) {
+                       $dbr = wfGetDB( DB_SLAVE );
+                       $res = $dbr->select(
+                               'page_props',
+                               'pp_propname',
+                               '',
+                               __METHOD__,
+                               array( 'DISTINCT', 'ORDER BY' => 'pp_propname' )
+                       );
+                       $propnames = array();
+                       foreach ( $res as $row ) {
+                               $propnames[$row->pp_propname] = $row->pp_propname;
+                       }
+                       $this->existingPropNames = $propnames;
+               }
+               return $this->existingPropNames;
+       }
+
        protected function getGroupName() {
                return 'pages';
        }
index d3b168b..b90026a 100644 (file)
@@ -417,7 +417,7 @@ class SpecialRevisionDelete extends UnlistedSpecialPage {
                                                Xml::listDropDown( 'wpRevDeleteReasonList',
                                                        $this->msg( 'revdelete-reason-dropdown' )->inContentLanguage()->text(),
                                                        $this->msg( 'revdelete-reasonotherlist' )->inContentLanguage()->text(),
-                                                       $this->getRequest()->getText( 'wpRevDeleteReasonList', 'other' ), 'wpReasonDropDown', 1
+                                                       $this->getRequest()->getText( 'wpRevDeleteReasonList', 'other' ), 'wpReasonDropDown'
                                                ) .
                                        '</td>' .
                                "</tr><tr>\n" .
index 4f8cabd..15a7b59 100644 (file)
@@ -114,7 +114,7 @@ class SpecialSearch extends SpecialPage {
         */
        public function load() {
                $request = $this->getRequest();
-               list( $this->limit, $this->offset ) = $request->getLimitOffset( 20 );
+               list( $this->limit, $this->offset ) = $request->getLimitOffset( 20, '' );
                $this->mPrefix = $request->getVal( 'prefix', '' );
 
                $user = $this->getUser();
@@ -207,8 +207,7 @@ class SpecialSearch extends SpecialPage {
 
                $profile = new ProfileSection( __METHOD__ );
                $search = $this->getSearchEngine();
-               // Request an extra result to determine whether a "next page" link is useful
-               $search->setLimitOffset( $this->limit + 1, $this->offset );
+               $search->setLimitOffset( $this->limit, $this->offset );
                $search->setNamespaces( $this->namespaces );
                $this->saveNamespaces();
                $search->prefix = $this->mPrefix;
@@ -352,7 +351,7 @@ class SpecialSearch extends SpecialPage {
                                        $this->offset,
                                        $this->limit,
                                        $this->powerSearchOptions() + array( 'search' => $term ),
-                                       max( $titleMatchesNum, $textMatchesNum ) <= $this->limit
+                                       $this->limit + $this->offset >= $totalRes
                                );
                        }
                        wfRunHooks( 'SpecialSearchResults', array( $term, &$titleMatches, &$textMatches ) );
@@ -512,7 +511,11 @@ class SpecialSearch extends SpecialPage {
 
                if ( $user->isLoggedIn() &&
                        !is_null( $request->getVal( 'nsRemember' ) ) &&
-                       $user->matchEditToken( $request->getVal( 'nsToken' ) )
+                       $user->matchEditToken(
+                               $request->getVal( 'nsToken' ),
+                               'searchnamespace',
+                               $request
+                       )
                ) {
                        // Reset namespace preferences: namespaces are not searched
                        // when they're not mentioned in the URL parameters.
@@ -547,11 +550,9 @@ class SpecialSearch extends SpecialPage {
 
                $out = "<ul class='mw-search-results'>\n";
                $result = $matches->next();
-               $count = 0;
-               while ( $result && $count < $this->limit ) {
+               while ( $result ) {
                        $out .= $this->showHit( $result, $terms );
                        $result = $matches->next();
-                       $count++;
                }
                $out .= "</ul>\n";
 
@@ -713,7 +714,7 @@ class SpecialSearch extends SpecialPage {
                                                $thumb->toHtml( array( 'desc-link' => true ) ) .
                                                '</td>' .
                                                '<td style="vertical-align: top;">' .
-                                               "{$link} {$fileMatch}" .
+                                               "{$link} {$redirect} {$section} {$fileMatch}" .
                                                $extract .
                                                "<div class='mw-search-result-data'>{$score}{$desc} - {$date}{$related}</div>" .
                                                '</td>' .
@@ -892,9 +893,7 @@ class SpecialSearch extends SpecialPage {
                        }
 
                        $rows[$subject] .=
-                               Xml::openElement(
-                                       'td', array( 'style' => 'white-space: nowrap' )
-                               ) .
+                               Xml::openElement( 'td' ) .
                                Xml::checkLabel(
                                        $name,
                                        "ns{$namespace}",
@@ -936,7 +935,13 @@ class SpecialSearch extends SpecialPage {
                $remember = '';
                $user = $this->getUser();
                if ( $user->isLoggedIn() ) {
-                       $remember .= Html::hidden( 'nsToken', $user->getEditToken() ) .
+                       $remember .= Html::hidden(
+                               'nsToken',
+                               $user->getEditToken(
+                                       'searchnamespace',
+                                       $this->getRequest()
+                               )
+                       ) .
                        Xml::checkLabel(
                                wfMessage( 'powersearch-remember' )->text(),
                                'nsRemember',
@@ -946,10 +951,7 @@ class SpecialSearch extends SpecialPage {
                }
 
                // Return final output
-               return Xml::openElement(
-                       'fieldset',
-                       array( 'id' => 'mw-searchoptions', 'style' => 'margin:0em;' )
-               ) .
+               return Xml::openElement( 'fieldset', array( 'id' => 'mw-searchoptions' ) ) .
                        Xml::element( 'legend', null, $this->msg( 'powersearch-legend' )->text() ) .
                        Xml::tags( 'h4', null, $this->msg( 'powersearch-ns' )->parse() ) .
                        Html::element( 'div', array( 'id' => 'mw-search-togglebox' ) ) .
@@ -1094,7 +1096,8 @@ class SpecialSearch extends SpecialPage {
                                ->params( wfEscapeWikiText( $term ) )
                                ->numParams( $resultsShown )
                                ->parse();
-                       $out .= Xml::tags( 'div', array( 'class' => 'results-info' ), $top );
+                       $out .= Xml::tags( 'div', array( 'class' => 'results-info' ), $top ) .
+                               Xml::element( 'div', array( 'style' => 'clear:both' ), '', false );
                }
 
                return $out . $this->didYouMeanHtml;
index 01c0aaf..976294b 100644 (file)
@@ -827,7 +827,7 @@ class UploadForm extends HTMLForm {
                }
 
                $canUploadByUrl = UploadFromUrl::isEnabled()
-                       && UploadFromUrl::isAllowed( $this->getUser() )
+                       && ( UploadFromUrl::isAllowed( $this->getUser() ) === true )
                        && $wgCopyUploadsFromSpecialUpload;
                $radio = $canUploadByUrl;
                $selectedSourceType = strtolower( $this->getRequest()->getText( 'wpSourceType', 'File' ) );
index c9e2e18..576b625 100644 (file)
@@ -211,7 +211,9 @@ class SpecialVersion extends SpecialPage {
                // wikimarkup can be used.
                $software = array();
                $software['[https://www.mediawiki.org/ MediaWiki]'] = self::getVersionLinked();
-               $software['[http://www.php.net/ PHP]'] = phpversion() . " (" . PHP_SAPI . ")";
+               $phpKey = wfIsHHVM() ? '[http://hhvm.com/ HHVM]' :
+                       '[http://www.php.net/ PHP]';
+               $software[$phpKey] = PHP_VERSION . " (" . PHP_SAPI . ")";
                $software[$dbr->getSoftwareLink()] = $dbr->getServerInfo();
 
                // Allow a hook to add/remove items.
index fa68504..ea526de 100644 (file)
@@ -49,23 +49,44 @@ class WantedFilesPage extends WantedQueryPage {
                        $category = false;
                }
 
+               $noForeign = '';
+               if ( !$this->likelyToHaveFalsePositives() ) {
+                       // Additional messages for grep:
+                       // wantedfiletext-cat-noforeign, wantedfiletext-nocat
+                       $noForeign = '-noforeign';
+               }
+
                if ( $category ) {
                        return $this
-                               ->msg( 'wantedfiletext-cat' )
+                               ->msg( 'wantedfiletext-cat' . $noForeign )
                                ->params( $category->getFullText() )
                                ->parseAsBlock();
                } else {
                        return $this
-                               ->msg( 'wantedfiletext-nocat' )
+                               ->msg( 'wantedfiletext-nocat' . $noForeign )
                                ->parseAsBlock();
                }
        }
 
+       /**
+        * Whether foreign repos are likely to cause false positives
+        *
+        * In its own function to allow subclasses to override.
+        * @see SpecialWantedFilesGUOverride in GlobalUsage extension.
+        * @since 1.24
+        */
+       protected function likelyToHaveFalsePositives() {
+               return RepoGroup::singleton()->hasForeignRepos();
+       }
+
        /**
         * KLUGE: The results may contain false positives for files
         * that exist e.g. in a shared repo.  Setting this at least
         * keeps them from showing up as redlinks in the output, even
         * if it doesn't fix the real problem (bug 6220).
+        *
+        * @note could also have existing links here from broken file
+        * redirects.
         * @return bool
         */
        function forceExistenceCheck() {
@@ -74,17 +95,39 @@ class WantedFilesPage extends WantedQueryPage {
 
        function getQueryInfo() {
                return array(
-                       'tables' => array( 'imagelinks', 'image' ),
+                       'tables' => array(
+                               'imagelinks',
+                               'page',
+                               'redirect',
+                               'img1' => 'image',
+                               'img2' => 'image',
+                       ),
                        'fields' => array(
                                'namespace' => NS_FILE,
                                'title' => 'il_to',
                                'value' => 'COUNT(*)'
                        ),
-                       'conds' => array( 'img_name IS NULL' ),
+                       'conds' => array(
+                               'img1.img_name' => null,
+                               // We also need to exclude file redirects
+                               'img2.img_name' => null,
+                        ),
                        'options' => array( 'GROUP BY' => 'il_to' ),
-                       'join_conds' => array( 'image' =>
-                               array( 'LEFT JOIN',
-                                       array( 'il_to = img_name' )
+                       'join_conds' => array(
+                               'img1' => array( 'LEFT JOIN',
+                                       'il_to = img1.img_name'
+                               ),
+                               'page' => array( 'LEFT JOIN', array(
+                                       'il_to = page_title',
+                                       'page_namespace' => NS_FILE,
+                               ) ),
+                               'redirect' => array( 'LEFT JOIN', array(
+                                       'page_id = rd_from',
+                                       'rd_namespace' => NS_FILE,
+                                       'rd_interwiki' => ''
+                               ) ),
+                               'img2' => array( 'LEFT JOIN',
+                                       'rd_title = img2.img_name'
                                )
                        )
                );
index d6c666a..8798de5 100644 (file)
@@ -277,8 +277,16 @@ class MediaWikiTitleCodec implements TitleFormatter, TitleParser {
                                        foreach ( $this->localInterwikis as $localIW ) {
                                                if ( 0 == strcasecmp( $parts['interwiki'], $localIW ) ) {
                                                        if ( $dbkey == '' ) {
-                                                               # Can't have an empty self-link
-                                                               throw new MalformedTitleException( 'Local interwiki with empty title: ' . $text );
+                                                               # Empty self-links should point to the Main Page, to ensure
+                                                               # compatibility with cross-wiki transclusions and the like.
+                                                               $mainPage = Title::newMainPage();
+                                                               return array(
+                                                                       'interwiki' => $mainPage->getInterwiki(),
+                                                                       'fragment' => $mainPage->getFragment(),
+                                                                       'namespace' => $mainPage->getNamespace(),
+                                                                       'dbkey' => $mainPage->getDBkey(),
+                                                                       'user_case_dbkey' => $mainPage->getUserCaseDBKey()
+                                                               );
                                                        }
                                                        $parts['interwiki'] = '';
 
index ac894ae..5defd45 100644 (file)
@@ -118,7 +118,7 @@ abstract class UploadBase {
         * Can be overridden by subclasses.
         *
         * @param User $user
-        * @return bool
+        * @return bool|string
         */
        public static function isAllowed( $user ) {
                foreach ( array( 'upload', 'edit' ) as $permission ) {
@@ -435,7 +435,7 @@ abstract class UploadBase {
                }
 
                $this->mFileProps = FSFile::getPropsFromPath( $this->mTempPath, $this->mFinalExtension );
-               $mime = $this->mFileProps['file-mime'];
+               $mime = $this->mFileProps['mime'];
 
                if ( $wgVerifyMimeType ) {
                        # XXX: Missing extension will be caught by validateName() via getTitle()
index bc46111..b35967b 100644 (file)
--- a/index.php
+++ b/index.php
@@ -34,7 +34,7 @@
 # has structures (try/catch, foo()->bar(), etc etc) which throw parse errors in
 # PHP 4. Setup.php and ObjectCache.php have structures invalid in PHP 5.0 and
 # 5.1, respectively.
-if ( !function_exists( 'version_compare' ) || version_compare( phpversion(), '5.3.2' ) < 0 ) {
+if ( !function_exists( 'version_compare' ) || version_compare( PHP_VERSION, '5.3.2' ) < 0 ) {
        // We need to use dirname( __FILE__ ) here cause __DIR__ is PHP5.3+
        require dirname( __FILE__ ) . '/includes/PHPVersionError.php';
        wfPHPVersionError( 'index.php' );
index bf30455..0a19d61 100644 (file)
@@ -443,17 +443,6 @@ class Language {
        function initContLang() {
        }
 
-       /**
-        * Same as getFallbacksFor for current language.
-        * @return array|bool
-        * @deprecated since 1.19
-        */
-       function getFallbackLanguageCode() {
-               wfDeprecated( __METHOD__, '1.19' );
-
-               return self::getFallbackFor( $this->mCode );
-       }
-
        /**
         * @return array
         * @since 1.19
@@ -857,6 +846,11 @@ class Language {
                        include "$IP/languages/Names.php";
                }
 
+               // If passed an invalid language code to use, fallback to en
+               if ( $inLanguage !== null && !Language::isValidCode( $inLanguage ) ) {
+                       $inLanguage = 'en';
+               }
+
                $names = array();
 
                if ( $inLanguage ) {
index 9c46ab1..c9e75e0 100644 (file)
        'tt-latn' => 'tatarça',        # Tatar (Latin script)
        'tum' => 'chiTumbuka',  # Tumbuka
        'tw' => 'Twi',                  # Twi, (FIXME!)
-       'ty' => 'Reo Mā`ohi',  # Tahitian
+       'ty' => 'reo tahiti',   # Tahitian
        'tyv' => 'тыва дыл',     # Tyvan
        'udm' => 'удмурт',        # Udmurt
        'ug' => 'ئۇيغۇرچە / Uyghurche', # Uyghur (multiple scripts - defaults to Arabic)
index 740663f..226e313 100644 (file)
@@ -65,6 +65,8 @@ class LanguageRu extends Language {
                                                $word = join( '', array_slice( $chars[0], 0, -2 ) ) . 'тей';
                                        } elseif ( join( '', array_slice( $chars[0], -2 ) ) === 'ды' ) {
                                                $word = join( '', array_slice( $chars[0], 0, -2 ) ) . 'дов';
+                                       } elseif ( join( '', array_slice( $chars[0], -1 ) ) === 'д' ) {
+                                               $word = join( '', array_slice( $chars[0], 0, -1 ) ) . 'да';
                                        } elseif ( join( '', array_slice( $chars[0], -3 ) ) === 'ник' ) {
                                                $word = join( '', array_slice( $chars[0], 0, -3 ) ) . 'ника';
                                        } elseif ( join( '', array_slice( $chars[0], -3 ) ) === 'ные' ) {
@@ -91,6 +93,8 @@ class LanguageRu extends Language {
                                                $word = join( '', array_slice( $chars[0], 0, -2 ) ) . 'тях';
                                        } elseif ( join( '', array_slice( $chars[0], -2 ) ) === 'ды' ) {
                                                $word = join( '', array_slice( $chars[0], 0, -2 ) ) . 'дах';
+                                       } elseif ( join( '', array_slice( $chars[0], -1 ) ) === 'д' ) {
+                                               $word = join( '', array_slice( $chars[0], 0, -1 ) ) . 'де';
                                        } elseif ( join( '', array_slice( $chars[0], -3 ) ) === 'ник' ) {
                                                $word = join( '', array_slice( $chars[0], 0, -3 ) ) . 'нике';
                                        } elseif ( join( '', array_slice( $chars[0], -3 ) ) === 'ные' ) {
index 4a8a589..2ba72df 100644 (file)
        "viewsourcetext": "تمكنك مطالعة و نسخ مصدر هذه الصفحة:",
        "viewyourtext": "يمكنك استعراض و نسخ مصدر ''' تعديلاتك ''' في هذه الصفحة:",
        "protectedinterface": "توفر هذه الصفحة نص الواجهة للبرنامج على هذا الويكي، وهي محمية لمنع سوء أستخدامها.\nلإضافة أو تغيير الترجمات لجميع مشاريع الويكي، رجاءً أستخدم [//translatewiki.net/ translatewiki.net]، مشروع الترجمة الخاص بميدياويكي.",
-       "editinginterface": "'''تحذير:''' أنت تقوم بتحرير صفحة تستخدم في الواجهة النصية للبرنامج.\nسوف تؤثر التغييرات في هذه الصفحة على مظهر واجهة المستخدم للمستخدمين الآخرين على هذا الويكي.\nلإضافة أو تغيير الترجمات في جميع مشاريع الويكي، رجاءً استخدم [//translatewiki.net/ translatewiki.net]، مشروع الترجمة الخاص بميدياويكي.",
+       "editinginterface": "<strong>تنبيه:</strong> تعديل هذه الصفحة سيحفظ في هذا الويكي فقط. لتعميم التعديل على جميع مشاريع ميدياويكي، عدلها في [//translatewiki.net/ مشروع ترجمة الويكي].",
        "cascadeprotected": "تمت حماية هذه الصفحة من التعديل لأنها مدمجة في {{PLURAL:$1||الصفحة التالية، والتي|الصفحتين التاليتين، واللتين|الصفحات التالية، والتي}} تم استعمال خاصية \"حماية الصفحات المدمجة\" {{PLURAL:$1||بها|بهما|بها}}:\n$2",
        "namespaceprotected": "لا تمتلك الصلاحية لتعديل الصفحات في نطاق '''$1'''.",
        "customcssprotected": "أنت لا تمتلك السماح لتعديل صفحة الCSS هذه، لأنها تحتوي على الإعدادات الشخصية لمستخدم آخر.",
        "virus-badscanner": "ضبط سيء: ماسح فيروسات غير معروف: ''$1''",
        "virus-scanfailed": "فشل المسح (كود $1)",
        "virus-unknownscanner": "مضاد فيروسات غير معروف:",
-       "logouttext": "'''أنت الآن غير مسجل الدخول.'''\n\nقد ترى بعض الصفحات كما لو أنك ما زلت مسجل الدخول، وذلك حتى تفرغ التخزين المؤقت في متصفحك.",
+       "logouttext": "<strong>أنت الآن غير مسجل الدخول.</strong> قد ترى بعض الصفحات كما لو أنك ما زلت مسجل الدخول، وذلك حتى تفرغ التخزين المؤقت في متصفحك.",
        "welcomeuser": "أهلاً بك يا $1!",
        "welcomecreation-msg": "تم إنشاء حسابك.\nلا تنس تعديل [[Special:Preferences|تفضيلاتك في {{SITENAME}}]].",
        "yourname": "اسم المستخدم:",
        "exbeforeblank": "المحتوى قبل الإفراغ كان: '$1'",
        "delete-confirm": "حذف \"$1\"",
        "delete-legend": "حذف",
-       "historywarning": "'''تحذير:''' الصفحة التي توشك على حذفها لها تاريخ فيه {{PLURAL:$1||مراجعة واحدة|مراجعتان|$1 مراجعات|$1 مراجعة}} تقريبا:",
+       "historywarning": "'''تنبيه:''' الصفحة التي تريد حذفها بها {{PLURAL:$1|نسخة|نسخة واحدة|نسختان|$1 نسخ|$1 نسخة}}. انظر",
        "confirmdeletetext": "أنت على وشك أن تقوم بحذف صفحة بالإضافة إلى كل تاريخها.\nمن فضلك التأكد من عزمك على الحذف، وبأنك مدرك للعواقب، وبأنك تقوم بهذا بالتوافق مع [[{{MediaWiki:Policy-url}}|السياسة]].",
        "actioncomplete": "انتهاء العملية",
        "actionfailed": "الفعل فشل",
        "delete-edit-reasonlist": "عدل أسباب الحذف",
        "delete-toobig": "لهذه الصفحة تاريخ تعديل طويل، أكثر من {{PLURAL:$1||مراجعة واحدة|مراجعتين|$1 مراجعات|$1 مراجعة}}.\nقُيّد محذف مثل هذه الصفحات لمنع الاضطراب المفاجئة في {{SITENAME}}.",
        "delete-warning-toobig": "لهذه الصفحة تاريخ تعديل طويل، أكثر من {{PLURAL:$1||مراجعة واحدة|مراجعتين|$1 مراجعات|$1 مراجعة}}.\nقد يؤدي حذفها إلى اضطراب عمليات قاعدة البيانات في {{SITENAME}}؛\nاستمر مع الحذر.",
-       "deleting-backlinks-warning": "'''تحذير:''' ترتبط [[Special:WhatLinksHere/{{FULLPAGENAME}}|صفحات أخرى]] بالصفحة التي أنت على وشك حذفها.",
+       "deleting-backlinks-warning": "[[Special:WhatLinksHere/{{FULLPAGENAME}}|تتصل صفحات أخرى]] بالصفحة التي تريد حذفها.",
        "rollback": "استرجاع التعديلات",
        "rollback_short": "استرجع",
        "rollbacklink": "استرجع",
index 6954042..c7d66d8 100644 (file)
@@ -23,7 +23,8 @@
                        "Wertuose",
                        "לערי ריינהארט",
                        "아라",
-                       "Arystanbek"
+                       "Arystanbek",
+                       "Dağlı95"
                ]
        },
        "tog-underline": "Keçidlərin altını xətlə:",
        "showhideselectedversions": "Seçilən versiyaları göstər/gizlə",
        "editundo": "əvvəlki halına qaytar",
        "diff-multi-manyusers": "({{PLURAL:$2|Bir istifadəçi|$2 istifadəçi}} tərəfindən edilən {{PLURAL:$1|bir ara redaktə|$1 ara redaktə}} göstərilmir)",
+       "difference-missing-revision": "Səhifənin  {{PLURAL:$2|bu versiyasının|$2 versiyalarının}} müqayisəsi ($1) tapılmadı.\nBu xəta adətən, köhnəlmiş səhifələrin müqayisə versiyalarından keçid edildikdə baş verir.\nDaha ətraflı məlumat üçün [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} silmə qeydlərinə] baxın.",
        "searchresults": "Axtarış nəticələri",
        "searchresults-title": "''$1'' üçün axtarış nəticələri",
        "titlematches": "Səhifə adı eynidir",
        "recentchanges-label-minor": "Bu kiçik redaktədir",
        "recentchanges-label-bot": "Bu redaktə bot tərəfindən edilmişdir",
        "recentchanges-label-unpatrolled": "Bu redaktə hələ nəzərdən keçirilməmişdir",
+       "recentchanges-label-plusminus": "Səhifənin ölçüsü bayt miqdarı ilə təyin edilir",
        "recentchanges-legend-newpage": "$1 - yeni səhifə",
        "rcnotefrom": "Aşağıda <strong>$2</strong>-dən bu yana olan dəyişikliklər göstərilib (<strong>$1</strong>-dən çox olmayaraq).",
        "rclistfrom": "$3 $2 vaxtından başlayaraq yeni dəyişiklikləri göstər",
        "badfilename": "Faylın adı dəyişildi. Yeni adı: \"$1\".",
        "filetype-mime-mismatch": "\".$1\" fayl uzantısı faylın MIME tipinə ($2) uyğun gəlmir.",
        "filetype-badmime": "\"$1\" MIME tipindəki faylların yüklənməsinə icazə verilmir.",
+       "filetype-banned-type": "'''\".$1\"''' {{PLURAL:$4|icazə verilən fayl formatı deyil}}. İcazə verilən {{PLURAL:$3|fayl formatı|fayl formatı bunlardır:}} $2.",
        "filetype-missing": "Faylın heç bir uzantısı yoxdur (məsələn, \".jpg\").",
        "empty-file": "Göndərdiyiniz fayl boşdur.",
        "file-too-large": "Göndərdiyiniz fayl çox böyükdür.",
        "largefileserver": "Faylın ölçüsü yol verilən həddi aşır.",
        "emptyfile": "Yüklədiyiniz fayl boşdur. Bu faylın adında olan hərf səhvi ilə bağlı ola bilər. Xahiş olunur ki, doğurdan da bu faylı yükləmək istədiyinizi yoxlayasınız.",
        "fileexists": "Yükləmək istədiyiniz adda fayl mövcuddur.\nLütfən <strong>[[:$1]]</strong> keçidini yoxlayın və bu faylı yükləmək istədiyinizdən əmin olun.\n[[$1|thumb]]",
+       "fileexists-extension": "Bu adda başqa bir fayl mövcuddur: [[$2|thumb]]\n* Yüklənilən faylın adı: <strong>[[:$1]]</strong>\n* Mövcud faylın adı: <strong>[[:$2]]</strong>\nXahiş edirik, başqa ad seçin.",
        "uploadwarning": "Yükləmə xəbərdarlığı",
        "savefile": "Faylı qeyd et",
        "uploadedimage": "\"[[$1]]\" yükləndi",
        "upload-description": "Faylın izahı",
        "upload-options": "Yükləmə parametrləri",
        "watchthisupload": "Bu faylı izlə",
+       "filename-bad-prefix": "Yüklədiyiniz faylın adı, çox güman ki, rəqəmsal kameralar tərəfindən avtomatik olaraq əlavə edilən və heç bir açıqlaması olmayan '''\"$1\"''' ilə başlayır.\nXahiş edirik faylın adını daha düzgün seçin.",
        "filename-prefix-blacklist": " #<!-- Bu sətrə toxunmayın --> <pre>\n# Sintaksis aşağıdakı kimi görünür:\n#   * \"#\" simvolundan sətrin sonuna kimi yazılar şərhdir\n#   * Tipik fayl adları üçün olan prefiksdəki hər bir boş olmayan sətir rəqəmli kamera trəfindən avtomatik qeydə alınır\nCIMG # Casio\nDSC_ # Nikon\nDSCF # Fuji\nDSCN # Nikon\nDUW # digər mobil telefonlar\nIMG # generic\nJD # Jenoptik\nMGP # Pentax\nPICT # misc.\n #</pre> <!-- Bu sətrə toxunmayın -->",
        "upload-success-subj": "Yükləmə tamamlandı",
        "upload-failure-subj": "Yükləmə problemi",
        "linkstoimage-redirect": "$1 (fayl istiqamətləndirilir) $2",
        "sharedupload": "Bu fayl $1-dandır və ola bilsin ki, başqa layihələrdə də istifadə edilir.",
        "sharedupload-desc-here": "Bu fayl $1dandır və başqa layihələrdə də istifadə edilə bilər.\nFaylın [$2 təsvir səhifəsindəki] məlumat aşağıda göstərilib.",
+       "filepage-nofile": "Bu adda fayl mövcud deyil.",
+       "filepage-nofile-link": "Bu adda fayl mövcud deyil, amma bu faylı siz [$1 yükləyə bilərsiz]",
        "uploadnewversion-linktext": "Bu faylın yeni versiyasını yüklə",
        "shared-repo-from": "$1-dən",
        "shared-repo": "ümumi fayl anbarı",
        "filedelete": "$1 adlı faylı sil",
        "filedelete-legend": "Faylı sil",
        "filedelete-intro": "'''[[Media:$1|$1]]''' faylını və onunla bağlı bütün tarixçəni silmək ərəfəsindəsiniz.",
+       "filedelete-intro-old": "'''[[Media:$1|$1]]''' faylının [$4 $3, $2] tarixli versiyasını silirsiz.",
        "filedelete-comment": "Səbəb:",
        "filedelete-submit": "Sil",
        "filedelete-success": "'''$1''' silinmişdir.",
        "filedelete-reason-otherlist": "Başqa səbəb",
        "filedelete-reason-dropdown": "*Əsas silmə səbəbi\n** Müəllif hüququ pozuntusu\n** Dublikat fayl\n** Keyfiyyətsiz şəkil\n** İstifadəsiz fayl\n** Qeyri-ensiklopedik şəxs\n** Lisenziyasız fayl\n** Azad şəkillə əvəz olundu\n** Müəllif istəyi",
        "filedelete-edit-reasonlist": "Silmə səbəblərini redaktə et",
+       "filedelete-maintenance": "Texniki işlər səbəbindən faylların silinməsi və bərpası müvəqqəti olaraq bağlanmışdır.",
+       "filedelete-maintenance-title": "Faylı silmək mümkün olmadı.",
        "mimesearch": "MIME axtar",
        "mimetype": "MIME tipi:",
        "download": "Yüklə",
        "filedeleteerror-short": "Fayl silinərkən xəta: $1",
        "filedeleteerror-long": "Fayl silinərkən üzə çıxan xətalar:\n\n$1",
        "filedelete-missing": "\"$1\" faylı mövcud olmadığından silinə bilinmir.",
+       "filedelete-old-unregistered": "Göstərilən faylın \"$1\" versiyası verilənlər bazasında mövcud deyil.",
        "filedelete-current-unregistered": "Göstərilən \"$1\" faylı verilənlər bazasında yoxdur.",
        "filedelete-archive-read-only": "\"$1\" kataloqunun arxivi veb-server yazıları üçün qapalıdır.",
        "previousdiff": "← Əvvəlki redaktə",
        "widthheightpage": "$1 × $2, $3 {{PLURAL:$3|səhifə|səhifələr}}",
        "file-info": "faylın ölçüsü: $1, MIME tipi: $2",
        "file-info-size": "$1 × $2 piksel, fayl həcmi: $3, MIME növü: $4",
+       "file-info-size-pages": "$1 × $2 piksel, faylın ölçüsü: $3, MIME-tipi: $4, $5 {{PLURAL:$5|səhifə|səhifələr}}",
        "file-nohires": "Daha dəqiq versiyası yoxdur.",
        "svg-long-desc": "SVG fayl, nominal olaraq $1 × $2 piksel, faylın ölçüsü: $3",
        "show-big-image": "Faylın əsli",
        "file-info-gif-frames": "$1 {{PLURAL:$1|frame|çərçivə}}",
        "file-info-png-looped": "ilmələnib",
        "file-info-png-frames": "$1 {{PLURAL:$1|frame|çərçivə}}",
+       "file-no-thumb-animation": "'''Qeyd. Texniki səbəblərdən bu fayl tipinin animasiyası mümkün deyil.'''",
+       "file-no-thumb-animation-gif": "'''Qeyd. Yüksək ayırdetmə dəqiqliyinə malik belə GIF-təsvirlərinin animasiyası texniki səbəblərdən mümkün deyil.'''",
        "newimages": "Yeni faylların siyahısı",
        "newimages-legend": "Filtrlər",
        "newimages-label": "Faylın (və ya onun bir hissəsinin) adı:",
        "duplicate-defaultsort": "<strong>Diqqət:</strong> Susmaya görə \"$2\" çeşidləmə açarı susmaya görə əvvəlki \"$1\" çeşidləmə açarını inkar edir.",
        "version": "Versiya",
        "version-extensions": "NIzamlanmış genişlənmələr",
+       "version-skins": "Üzlük",
        "version-specialpages": "Xüsusi səhifələr",
        "version-parserhooks": "Parser hooks",
        "version-variables": "Dəyişkənlər",
        "version-antispam": "Spam önləmə",
-       "version-skins": "Üzlük",
        "version-other": "Digər",
        "version-hooks": "Çəngəllər",
        "version-hook-name": "Çəngəlin adı",
        "fileduplicatesearch-legend": "Dublikatı axtar",
        "fileduplicatesearch-filename": "Fayl adı:",
        "fileduplicatesearch-submit": "Axtar",
+       "fileduplicatesearch-result-1": "\"$1\" faylı hər hansı eyni dublikata malik deyil.",
+       "fileduplicatesearch-result-n": "\"$1\" faylı  $2 {{PLURAL:$2|eyni duplikata|eyni duplikatlara}} malikdir.",
        "fileduplicatesearch-noresults": "\"$1\" adında fayl tapılmadı.",
        "specialpages": "Xüsusi səhifələr",
        "specialpages-group-maintenance": "Cari məruzələr",
index a566c25..e2194eb 100644 (file)
@@ -22,9 +22,9 @@
        "tog-hidepatrolled": "Kontroilirde Änderrungen in dé „Létzten Änderrungen“ ausblenden",
        "tog-newpageshidepatrolled": "Kóntróilirde Seiten auf da Listen „Neiche Seiten“ vaberng",
        "tog-extendwatchlist": "Daweiterde Beówochtungslisten",
-       "tog-usenewrc": "Daweiterde Dorstöung voh d' létzden Änderrungen (JavaScript werd braucht)",
+       "tog-usenewrc": "Endarunga vo \"Lezde Endarunga\" und vo \"Mei Beobochtd\" noch Seitn gruppian",
        "tog-numberheadings": "Ywerschriften autómaatisch nummerrirn",
-       "tog-showtoolbar": "Beorweiten-Werkzeigleisten åzoang (JavaScript werd braucht)",
+       "tog-showtoolbar": "Zoag de Edit Toolbar (JavaScript nedig)",
        "tog-editondblclick": "Seiten mid am Dóppedrucker beorweiden (JavaScript werd braucht)",
        "tog-editsectiononrightclick": "Oahzelne Obschnitt mid am Rechtsdrucker beorweiten (JavaScript werd braucht)",
        "tog-watchcreations": "Voh mir söwer eihgstöde Seiten autómaatisch beówochten",
        "mainpage-description": "Hoamseitn",
        "policy-url": "Project:Richtlinien",
        "portal": "Autornportal",
-       "portal-url": "Project:Autornportal",
+       "portal-url": "Project:AutornPortal",
        "privacy": "Datnschutz",
        "privacypage": "Project:Datnschutz",
        "badaccess": "Koane ausreichenden Rechtt",
        "cannotdelete-title": "Seiten „$1“ kå néd gléschd wern",
        "badtitle": "koa gitiga Titl",
        "badtitletext": "Da Titl voh da ogfordatn Seitn is ned gitig, laar oda a ungitiga Sprochlink vonam andan Wiki.",
-       "perfcached": "Dé fóigernden Daaten staummern aus'm Cache und san méglicherweis nimmer aktuö. Maximoi {{PLURAL:$1|oah Ergebnis is|$1 Ergebniss san}} im Cache vafiagbor.",
-       "perfcachedts": "Dé Daaten staummern aus 'm Cache. Da Zeidbunkt voh da létzden Aktualisiarung: $1. Maximoi {{PLURAL:$4|oah Ergebnis is|$4 Ergebniss san}} im Cache vafiagbor.",
+       "perfcached": "De foigandn Datn stamma ausm Cache und san meglichaweis neama aktuäi. Maximoi {{PLURAL:$1|oa Eagebnis is|$1 Ergebniss san}} im Cache vafigboar.",
+       "perfcachedts": "De Datn stamma ausm Cache. Da Zeidpunkt vo da lezzdn Aktualisiarung: $2, $3 Uah. Maximoi {{PLURAL:$4|oa Ergebnis is|$4 Ergebniss san}} im Cache vafigboar.",
        "querypage-no-updates": "'''Dé Aktualisiarungsfunkzión voh derer Seiten is derzeid deaktivird. Dé Daaten wern bis auf Weiders néd daneiert.'''",
        "viewsource": "Quejtext ozoagn",
        "viewsource-title": "Quöntext voh da Seiten $1 auhschauh",
        "yourpassword": "Passwort:",
        "yourpasswordagain": "Es Passwort no amoi eigebm",
        "remembermypassword": "Mitm Brausa dauahoft ogmejd bleibm (maximoi $1 {{PLURAL:$1|Dog|Dog}})",
-       "yourdomainname": "Eanerne Domain:",
+       "yourdomainname": "Dei Domain:",
        "externaldberror": "Entweder es ligt a Feeler bai da externen Authentifiziarung vur oder du derfst dai externs Benytzerkonto ned aktualisirn.",
        "login": "Eilogga",
        "nav-login-createaccount": "Eilogga / Konto olegn",
        "wrongpassword": "Des Posswort is foisch! Bitschee prowirs nuamoi.",
        "wrongpasswordempty": "Es is koa Posswort ned aigeem worn. Bittschee prowirs nuamoi.",
        "mailmypassword": "Neichs Passwort zuaschicka",
-       "passwordremindertitle": "Naichs Posswort fyra {{SITENAME}}-Benytzerkonto",
+       "passwordremindertitle": "A neichs Kennwoat fiar a {{SITENAME}}-Nutzakonto",
        "acct_creation_throttle_hit": "Du host scho $1 {{PLURAL:$1|Benytzerkonto|Benytzerkonten}} und kååst jetzad koane mer åleeng.",
        "emailconfirmlink": "E-Póst-Adressen bstäting (Authentifiziarung)",
        "accountcreated": "Benytzerkonto is erstöid worn",
        "resetpass-submit-loggedin": "Posswort ändern",
        "resetpass-submit-cancel": "Obbrechen",
        "passwordreset": "Passwoat zrucksetzn",
-       "passwordreset-username": "Benutzernåm:",
+       "passwordreset-username": "Nutzanama:",
        "bold_sample": "Fetta Text",
        "bold_tip": "Fetta Text",
        "italic_sample": "Kursiva Text",
        "post-expand-template-inclusion-warning": "Obocht: De Gress vo eibundne Vorlong is z gross.\nA poar Vorlogn wean ned eibundn.",
        "post-expand-template-inclusion-category": "Seitn, wo d Gress vo de eibundnan Vorlogn ibaschrittn is",
        "post-expand-template-argument-warning": "'''Obocht:''' De Seitn enthoit mindastns oa Argument in da Vorlog, wo expandiat z grouss is. \nDe Parameta wean ignoriad.",
-       "post-expand-template-argument-category": "Seiten, dé ignorirde Vurlongargumentt enthoiden",
+       "post-expand-template-argument-category": "Seitn mid ignoriadn Voalognparametan",
        "undo-summary": "Änderrung $1 voh [[Special:Contributions/$2|$2]] ([[User talk:$2|Diskussión]]) ryckgängig gmocht.",
        "cantcreateaccounttitle": "Benutzerkonto kå ned erstöd wern",
        "viewpagelogs": "Logbiacha fia de Datei ozoagn",
        "doubleredirects": "Doppede Weiderloatungen",
        "brokenredirects-edit": "werkeln",
        "brokenredirects-delete": "léschen",
-       "withoutinterwiki": "Seiten óne an Link zua åndre Sproochen",
+       "withoutinterwiki": "Seitn ohne Sprochlinks",
        "withoutinterwiki-summary": "D' foiganden Seiten valinken néd auf a åndre Sproochversion",
-       "withoutinterwiki-legend": "Präfix",
+       "withoutinterwiki-legend": "Prefix",
        "withoutinterwiki-submit": "Zoag",
        "fewestrevisions": "Seiten mid d' weenigsten Versiónen",
        "nbytes": "$1 {{PLURAL:$1|Byte|Bytes}}",
        "mostcategories": "Seiten mid dé haiffigsten Kategorien",
        "mostimages": "Haiffig brauchde Daatein",
        "mostrevisions": "Seiten mid d' haiffigsten Versiónen",
-       "prefixindex": "Olle Seien (mit Präfix)",
+       "prefixindex": "Olle Seitn (mit Prefix)",
        "shortpages": "Kurze Seiten",
        "longpages": "Långe Seiten",
        "deadendpages": "Néd valinkende Seiten",
        "listgrouprights-addgroup-self-all": "Kauh olle Gruppm zum oagern Kóntó dazuadoah",
        "mailnologin": "Du bist néd auhgmödt",
        "emailuser": "Mail an den Nutza",
-       "emailpage": "E-Mail aun Benutzer",
-       "noemailtitle": "Koah E-Mail-Adress",
+       "emailpage": "E-Mail an Nutza",
+       "noemailtitle": "Koa Mail-Adress",
        "emailfrom": "Voh:",
        "emailto": "Aun:",
        "emailsubject": "Bedreff:",
        "ipbreason-dropdown": "* Oigmoahne Sperrgrynd\n** Eihfyng voh voische Informaziónen\n** Laarn voh Seiten\n** Massenweiss Eihfyng voh externe Links\n** Eihstön voh unsinnige Inhoite auf Seiten\n** néd åbrochts Vahoiden\n** Missbrauch mid mererne Benutzerkontós\n** néd geigneter Benutzernåm",
        "ipb-hardblock": "Auhgmödte Benutzer dodrauh hindern, daas Beorweitungen unter derer IP-Adress vurgnummer wern",
        "ipbcreateaccount": "D' Erstöung voh Benutzerkóntós vahindern",
-       "ipbemailban": "E-Mail-Vasånd sperrn",
+       "ipbemailban": "E-Mail-Vasand spean",
        "ipbenableautoblock": "Sperr dé aktuö voh dém Benutzer gnutzde IP-Adress sówia autómaatisch olle fóiganden, voh dénen aus er Beorweitungen óder 's Auhléng voh Benutzerkóntós vasuacht.",
        "ipbsubmit": "IP-Adress/Benutzer sperrn",
        "ipbother": "Åndre Dauer (auf englisch):",
        "unblocklink": "Freigebm",
        "change-blocklink": "Sperr endan",
        "contribslink": "Beidreg",
-       "emaillink": "E-Póst schicker",
+       "emaillink": "E-Mail vaschicka",
        "autoblocker": "Autómaatische Sperr, wei du a gmoahsaume IP-Adress mim [[User:$1|$1]] bnutzd. Grund voh da Benutzersperrn: „$2“.",
        "blocklogpage": "Sperrlogbuach",
        "blocklog-showlog": "{{GENDER:$1|Der Benutzer|Dé Benutzerrin|Der Benutzer}} do is schoh friarer gsperrd worn. Es fóigt a Eihtrog aus'm Benutzersperrlogbiaché:",
        "block-log-flags-anononly": "netter Anónyme",
        "block-log-flags-nocreate": "Es Olegn vo Nutzakontn is gsperrt",
        "block-log-flags-noautoblock": "Autóblóck deaktivierd",
-       "block-log-flags-noemail": "E-Post vaschicka gspead",
+       "block-log-flags-noemail": "Mail vaschicka gspead",
        "unlockdb": "Daatenbaunk freigeem",
        "unlockconfirm": "Ja, i mecht de Datenbank freigem.",
        "unlockbtn": "Datenbank freigem",
index 7edefda..f5fb077 100644 (file)
        "rclistfrom": "Ipahiling an baguhon na mga kaliwatan magpoon kan $3 $2",
        "rcshowhideminor": "$1 saradit na mga pagliwat",
        "rcshowhideminor-show": "Ipatanaw",
-       "rcshowhideminor-hide": "Tagoa",
+       "rcshowhideminor-hide": "Itago",
        "rcshowhidebots": "$1 mga gantaw",
        "rcshowhidebots-show": "Ipatanaw",
-       "rcshowhidebots-hide": "Tagoa",
+       "rcshowhidebots-hide": "Itago",
        "rcshowhideliu": "$1 rehistradong mga paragamit",
        "rcshowhideliu-show": "Ipatanaw",
-       "rcshowhideliu-hide": "Tagoa",
+       "rcshowhideliu-hide": "Itago",
        "rcshowhideanons": "$1 mga dae bistong paragamit",
        "rcshowhideanons-show": "Ipatanaw",
-       "rcshowhideanons-hide": "Tagoa",
+       "rcshowhideanons-hide": "Itago",
        "rcshowhidepatr": "$1 patrolyadong mga pagliwat",
        "rcshowhidepatr-show": "Ipatanaw",
        "rcshowhidepatr-hide": "Tagoa",
        "rcshowhidemine": "$1 sakong mga pagliliwat",
        "rcshowhidemine-show": "Ipatanaw",
-       "rcshowhidemine-hide": "Tagoa",
+       "rcshowhidemine-hide": "Itago",
        "rclinks": "Ipahilíng an $1 huring mga kaliwatan sa laog nin huring $2 na mga aldaw<br />$3",
        "diff": "kalaenan",
        "hist": "sagaysay",
        "duplicate-defaultsort": "'''Patanid tabi:''' An susing panugmad kan salansan na \"$2\" minasalimbaw sa dating susing panugmad kan salansan na \"$1\".",
        "version": "Bersyon",
        "version-extensions": "Instaladong mga ekstensyon",
+       "version-skins": "Mga kublit",
        "version-specialpages": "Espesyal na mga pahina",
        "version-parserhooks": "Mga pangawil kan parser",
        "version-variables": "Mga kabalanggayahan",
        "version-antispam": "Pan-spam na pangataman",
-       "version-skins": "Mga kublit",
        "version-other": "An iba pa",
        "version-mediahandlers": "Mga Midyang Tagakapot",
        "version-hooks": "Mga pangawil",
index 98a9201..f49c47e 100644 (file)
        "expand_templates_remove_nowiki": "Падаўляць тэгі <nowiki> у выніку",
        "expand_templates_generate_xml": "Паказаць дрэва аналізу XML",
        "expand_templates_generate_rawhtml": "Паказаць HTML",
-       "expand_templates_preview": "Папярэдні прагляд"
+       "expand_templates_preview": "Папярэдні прагляд",
+       "pagelanguage": "Выбар мовы старонкі",
+       "pagelang-name": "Старонка",
+       "pagelang-language": "Мова",
+       "pagelang-use-default": "Ужываць мову па змоўчаньні",
+       "pagelang-select-lang": "Абярыце мову",
+       "right-pagelang": "Зьмяніць мову старонкі",
+       "action-pagelang": "зьмену мовы старонкі"
 }
index ecf778d..58022e7 100644 (file)
        "nospecialpagetext": "<strong>Вы звярнуліся па няправільную адмысловую старонку.</strong>\n\nПералік правільных адмысловых старонак ёсць на [[Special:SpecialPages|{{int:specialpages}}]].",
        "error": "Памылка",
        "databaseerror": "Памылка базы дадзеных",
+       "databaseerror-text": "Здарылася памылка запыту да базы звестак.\nГэта можа ўказваць на няспраўнасць у праграме.",
+       "databaseerror-textcl": "Здарылася памылка запыту да базы звестак.",
        "databaseerror-query": "Запыт: $1",
        "databaseerror-function": "Функцыя: $1",
        "databaseerror-error": "Памылка: $1",
        "laggedslavemode": "<strong>Увага:</strong> Старонка можа не ўтрымліваць апошніх змен.",
-       "readonly": "База звестак заблакаваная",
+       "readonly": "База звестак зачынена",
        "enterlockreason": "Упішыце прычыну зачынення, а таксама меркаваны час адчынення",
        "readonlytext": "База даных не прыймае новых старонак і іншых змяненняў, таму што яна зараз зачынена, відаць, дзеля абслугоўвання, пасля чаго будзе вернута да нармальнай працы.\n\nАдміністратар, які зачыняў базу, растлумачыў гэта так: $1",
        "missing-article": "Не ўдалося знайсці тэксту старонкі ў базе даных, хаця ён мусіць там быць, з назвай \"$1\" $2.\n\nЗвычайна так бывае, калі адкрываюць састарэлую розніцу (diff) або спасылку з гісторыі сцёртай старонкі.\n\nКалі гэта не так, то, магчыма, гэта памылка ў праграмах.\nПаведамце пра гэта, разам з праблемным URL, аднаму з [[Special:ListUsers/sysop|адміністратараў]].",
        "resetpass-submit-cancel": "Нічога",
        "resetpass-wrong-oldpass": "Недапушчальны тымчасовы ці актуальны пароль.\nМагчыма, вы ўжо змянілі свой пароль ці папрасілі новы тымчасовы.",
        "resetpass-recycled": "Калі ласка, змяніце свой пароль на нешта іншае, чым ваш цяперашні пароль.",
+       "resetpass-temp-emailed": "Вы ўвайшлі ў сістэму з дапамогаю тымчасовага коду, дасланага па эл.пошце.\nКаб завершыць уваход, неабходна ўстанавіць новы пароль:",
        "resetpass-temp-password": "Тымчасовы пароль:",
+       "resetpass-abort-generic": "Змяненне пароля было спынена прыстаўкаю.",
        "resetpass-expired": "Ваш пароль пратэрмінаваны. Калі ласка, устанавіце новы пароль для ўваходу ў сістэму.",
        "resetpass-expired-soft": "Ваш пароль пратэрмінаваны, яго трэба замяніць. Калі ласка, выберыце новы пароль зараз, ці націсніце \"{{int:resetpass-submit-cancel}}\", каб змяніць яго пазней.",
        "resetpass-validity-soft": "Ваш пароль недапушчальны: $1\n\nКалі ласка, выберыце новы пароль зараз, або націсніце \"{{int:resetpass-submit-cancel}}\", каб скінуць яго пазней.",
        "content-not-allowed-here": "\"$1\" не дазволены на старонцы [[$2]]",
        "editwarning-warning": "Пераход на іншую старонку можа прывесці да страты правак, зробленых Вамі. \nКалі Вы ўвайшлі ў сістэму, Вы можаце адключыць гэта папярэджанне ў раздзеле \"{{int:prefs-editing}}\" Вашых настроек.",
        "editpage-notsupportedcontentformat-title": "Фармат змесціва не падтрымліваецца",
+       "editpage-notsupportedcontentformat-text": "Фармат змесціва $1 не падтрымліваецца мадэллю змесціва $2.",
        "content-model-wikitext": "вікі-тэкст",
        "content-model-text": "звычайны тэкст",
        "content-model-javascript": "JavaScript",
        "parser-template-loop-warning": "Цыклічнае ўключэнне шаблона: [[$1]]",
        "parser-template-recursion-depth-warning": "Вычарпаны ліміт глыбіні ўключэння шаблонаў ($1)",
        "language-converter-depth-warning": "Перавышана глыбіня моўнага канвертэра ($1)",
+       "node-count-exceeded-category": "Старонкі, якія перасягнулі колькасць вузлоў",
+       "node-count-exceeded-category-desc": "Катэгорыя для старонак, у якіх перавышана колькасць вузлоў.",
+       "node-count-exceeded-warning": "Старонка перасягнула колькасць вузлоў",
+       "expansion-depth-exceeded-category": "Старонкі, якія перасягнулі глыбіню разгортвання",
+       "expansion-depth-exceeded-category-desc": "Гэта катэгорыя для старонак, у якіх перасягнута глыбіня разгортвання.",
+       "expansion-depth-exceeded-warning": "Старонка перасягнула глыбіню разгортвання",
+       "parser-unstrip-loop-warning": "Выяўлены закальцаваны unstrip",
+       "parser-unstrip-recursion-limit": "Перавышаны ліміт рэкурсіі unstrip ($1)",
+       "converter-manual-rule-error": "Выяўлена памылка ў ручным правіле моўнага канвертара",
        "undo-success": "Праўку можна адкаціць, але праверце папярэдні паказ, што ніжэй, каб упэўніцца ў адпаведнасці будучых змяненняў, і толькі тады запішыце іх, каб завершыць адкат праўкі.",
        "undo-failure": "Немагчыма адкаціць праўку, таму што перашкаджаюць праўкі, што былі перад ёй.",
        "undo-norev": "Не ўдалося адкаціць праўку, таму што яна не існуе або была сцёрта.",
+       "undo-nochange": "Выглядае на тое, што праўка ўжо была адкочаная.",
        "undo-summary": "Адкат версіі $1 аўтарства [[Special:Contributions/$2|$2]] ([[User talk:$2|размова]])",
        "undo-summary-username-hidden": "Адкат версіі $1 схаванага ўдзельніка",
        "cantcreateaccounttitle": "Немагчыма стварыць рахунак",
        "cantcreateaccount-text": "Стварэнне рахункаў было забаронена для гэтага адрасу IP ('''$1''').\n\nЗабарона зроблена ўдзельнікам [[User:$3|$3]], з такім тлумачэннем: ''$2''",
+       "cantcreateaccount-range-text": "Стварэнне ўліковага запісу ўдзельніка з IP-адрасоў у дыяпазоне '''$1''', што ўключае ваш адрас IP ('''$4'''), было забаронена {{GENDER:$3|ўдзельнікам|ўдзельніцай}} [[User:$3|$3]].\n\n$3 {{GENDER:$3|патлумачыў|патлумачыла}} гэта так: ''$2''",
        "viewpagelogs": "Паказаць журналы для гэтай старонкі",
        "nohistory": "Старонка не мае гісторыі правак.",
        "currentrev": "Актуальная версія",
        "mergehistory-empty": "Няма версій, якія можна аб'яднаць.",
        "mergehistory-success": "$3 {{PLURAL:$3|версія|версій}} [[:$1]] паспяхова аб'яднаныя ў склад [[:$2]].",
        "mergehistory-fail": "Немагчыма аб'яднаць гісторыі, праверце зададзеныя назву і час.",
+       "mergehistory-fail-toobig": "Немагчыма выканаць зліццё гісторый, таму што больш за ліміт у $1 {{PLURAL:$1|версію|версіі|версій}} трэба пераносіць.",
        "mergehistory-no-source": "Не існуе крынічная старонка $1.",
        "mergehistory-no-destination": "Не існуе мэтавая старонка $1.",
        "mergehistory-invalid-source": "Крынічная старонка павінна мець карэктную назву.",
        "diff-multi-sameuser": "(Не паказана{{PLURAL:$1|адна прамежкавая версія|$1 прамежкавыя версіі|$1 прамежкавых версій}} таго ж удзельніка)",
        "diff-multi-otherusers": "(Не паказана {{PLURAL:$1|адна прамежкавая версія|$1 прамежкавыя версіі|$1 прамежкавых версій}} {{PLURAL:$2|яшчэ аднаго ўдзельніка|$2 удзельнікаў}})",
        "diff-multi-manyusers": "({{PLURAL:$1|не паказана $1 прамежкавая версія|не паказаны $1 прамежкавыя версіі|не паказаны $1 прамежкавых версій}}, зробленыя больш чым {{PLURAL:$2|$1 удзельнікам|$2 удзельнікамі}})",
+       "difference-missing-revision": "{{PLURAL:$2|$2 версія|$2 версіі|$2 версій}} гэтай розніцы ($1) {{PLURAL:$2|не знойдзена|не знойдзены}}.\n\nЗвычайна такое здараецца з-за пераходу па састарэлай спасылцы на розніцу ў старонцы, якая была сцёрта.\nПадрабязнасці могуць быць у [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} журнале сціранняў].",
        "searchresults": "Вынікі пошуку",
        "searchresults-title": "Вынікі пошуку «$1»",
        "titlematches": "Знойдзена ў назвах",
        "recentchangesdays-max": "(найбольш $1 {{PLURAL:$1|дзень|дзён}})",
        "recentchangescount": "Прадвызначаная колькасць правак дзеля паказу:",
        "prefs-help-recentchangescount": "Гэта ўключае ў сябе апошнія змены, гісторыі старонак, журналы.",
+       "prefs-help-watchlist-token2": "Гэта сакрэтны ключ к сеціўнай стужцы з вашага спісу назірання.\nКожны, хто ведае гэты ключ, будзе мець магчымасць чытаць ваш спіс назірання, таму не дзяліцеся ім.\nКалі трэба, можна [[Special:ResetTokens|скінуць яго]].",
        "savedprefs": "Настройкі замацаваныя.",
        "timezonelegend": "Часавы пояс:",
        "localtime": "Мясцовы час:",
        "lockmanager-fail-releaselock": "Не ўдалося разблакіраваць \"$1\"",
        "lockmanager-fail-db-bucket": "Не атрымалася звязацца з дастатковай колькасцю баз блакаванняў у сегменце $1.",
        "lockmanager-fail-db-release": "Не атрымалася зняць блакаванне базы дадзеных $1.",
+       "lockmanager-fail-svr-acquire": "Не ўдалося атрымаць блакаванні на серверы $1.",
        "lockmanager-fail-svr-release": "Не атрымалася зняць блакаванні на серверы $1.",
        "zip-file-open-error": "Адбылася памылка пры адкрыцці файла для праверкі архіва.",
        "zip-wrong-format": "Указаны файл не з'яўляецца файлам ZIP.",
        "http-invalid-url": "Памылковы URL: $1",
        "http-invalid-scheme": "Не падтрымліваюцца адрасы са схемай \"$1\"",
        "http-request-error": "Не атрымалася выканаць HTTP-запыт з-за невядомай памылкі",
-       "http-read-error": "Памылка чытання HTTP",
+       "http-read-error": "Памылка чытання HTTP.",
        "http-timed-out": "Мінуў час чакання HTTP-запыту.",
        "http-curl-error": "Памылка звароту да URL: $1",
        "http-bad-status": "Пад час апрацоўкі HTTP-запыту выяўлена праблема: $1 $2",
        "license-nopreview": "(без перадпаказу)",
        "upload_source_url": " (сапраўдны, публічна дасягальны URL)",
        "upload_source_file": " (файл на вашай машыне)",
+       "listfiles-delete": "сцерці",
        "listfiles-summary": "Гэтая службовая старонка паказвае ўсе загружаныя файлы.",
        "listfiles_search_for": "Знайсці назву выявы:",
        "imgfile": "файл",
        "sharedupload-desc-there": "Гэты файл з $1 і можа выкарыстоўвацца ў іншых праектах.\nДадатковую інфармацыю можна знайсці на [$2 старонцы апісання файла].",
        "sharedupload-desc-here": "Гэты файл з $1 і можа выкарыстоўвацца іншымі праектамі. Апісанне на яго [$2 старонцы размоў] прыведзена ніжэй",
        "sharedupload-desc-edit": "Гэты файл з $1 і можа выкарыстоўвацца ў іншых праектах.\nМажліва, вы хочаце правіць апісанне на [$2 старонцы апісання файла] там.",
+       "sharedupload-desc-create": "Гэты файл з $1 і можа выкарыстоўвацца ў іншых праектах.\nПравіць яго апісанне можна на гэнай [$2 старонцы апісання файла].",
        "filepage-nofile": "Не знойдзены файл з такой назвай.",
        "filepage-nofile-link": "Не знойдзены файл з такой назвай, але можна [$1 яго ўкласці].",
        "uploadnewversion-linktext": "Укласці новую версію гэтага файла",
        "listgrouprights-namespaceprotection-header": "Абмежаванні прасторы назваў",
        "listgrouprights-namespaceprotection-namespace": "Прастора назваў",
        "listgrouprights-namespaceprotection-restrictedto": "Дазвол(ы), неабходныя для праўкі",
-       "trackingcategories": "Ð\9aаÑ\82Ñ\8dгоÑ\80Ñ\8bÑ\96 Ð°Ð´сочвання",
-       "trackingcategories-summary": "На гэтай старонцы пералічаны катэгорыі для адсочвання, якія аўтаматычна напаўняюцца праграмным забеспячэннем MediaWiki. Іх можна перайменаваць, змяніўшы адпаведныя сістэмныя паведамленні ў прасторы назваў {{ns:8}}.",
-       "trackingcategories-msg": "Катэгорыя для адсочвання",
+       "trackingcategories": "Ð\9aаÑ\82Ñ\8dгоÑ\80Ñ\8bÑ\96 Ð´Ð»Ñ\8f Ð°сочвання",
+       "trackingcategories-summary": "На гэтай старонцы пералічаны катэгорыі для асочвання, якія аўтаматычна напаўняюцца праграмным забеспячэннем MediaWiki. Іх можна перайменаваць, змяніўшы адпаведныя сістэмныя паведамленні ў прасторы назваў {{ns:8}}.",
+       "trackingcategories-msg": "Катэгорыя для асочвання",
        "trackingcategories-name": "Назва паведамлення",
        "trackingcategories-desc": "Крытэрый уключэння ў катэгорыю",
+       "noindex-category-desc": "Старонка не індэксуецца пошукавымі робатамі, таму што на ёй ёсць магічнае слова <code><nowiki>__NOINDEX__</nowiki></code> і яна знаходзіцца ў прасторы назваў, дзе гэты сцяг дазволены.",
+       "index-category-desc": "На старонцы ёсць магічнае слова <code><nowiki>__INDEX__</nowiki></code> (і старонка знаходзіцца ў прасторы назваў, дзе гэты сцяг дазволены), таму яна індэксуецца пошукавымі робатамі у выпадках, калі гэтага звычайна не адбываецца.",
+       "post-expand-template-inclusion-category-desc": "Пасля разгортвання ўсіх шаблонаў памер старонкі перавышае <code>$wgMaxArticleSize</code>, таму некаторыя шаблоны пакінуты неразгорнутымі.",
+       "post-expand-template-argument-category-desc": "Пасля разгортвання аргумента шаблона (штосьці ў патройных фігурных дужках, напрыклад, <code>{{{Foo}}}</code>), памер старонкі перавышае <code>$wgMaxArticleSize</code>.",
+       "expensive-parserfunction-category-desc": "Занадта шмат працаёмкіх зваротаў да функцый парсера (напрыклад, <code>#ifexist</code>) уключана ў старонку. Гл. [https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:$wgExpensiveParserFunctionLimit Manual:$wgExpensiveParserFunctionLimit].",
+       "broken-file-category-desc": "Катэгорыя дадаецца, калі старонка ўтрымлівае няспраўную спасылку на файл (спасылку на ўкладзены файл, якога няма).",
+       "hidden-category-category-desc": "Гэта катэгорыя змяшчае <code><nowiki>__HIDDENCAT__</nowiki></code>, што паводле прадвызначэння засцерагае яе ад паказу ў спісе катэгорый на старонках.",
        "trackingcategories-nodesc": "Апісанне адсутнічае.",
        "trackingcategories-disabled": "Катэгорыя адключана",
        "mailnologin": "Няма эл.адрасу",
        "protect-badnamespace-title": "Прастора імёнаў без аховы",
        "protect-badnamespace-text": "Старонкі ў гэтай прасторы імёнаў не могуць знаходзіцца пад аховай.",
        "protect-norestrictiontypes-text": "Старонка не можа ахоўвацца, таму што недаступны тыпы абмежавання.",
+       "protect-norestrictiontypes-title": "Неахоўвальная старонка",
        "protect-legend": "Пацверджанне пачатку аховы",
        "protectcomment": "Прычына:",
        "protectexpiry": "Канчаецца:",
        "immobile-target-namespace-iw": "Нельга пераносіць старонку на месца спасылкі інтэрвікі.",
        "immobile-source-page": "Нельга пераносіць гэтую старонку.",
        "immobile-target-page": "Нельга пераносіць пад гэтую назву.",
+       "bad-target-model": "Пажаданая мэта ўжывае іншую мадэль змесціва. Немагчыма пераўтварыць $1 у $2.",
        "imagenocrossnamespace": "Нельга пераносіць у не-файлавую прастору назваў",
        "nonfile-cannot-move-to-file": "Немагчыма пераназываць старонкі ў выявы",
        "imagetypemismatch": "Новы канчатак назвы файла не адпавядае яго тыпу",
        "thumbnail_image-type": "Дадзены тып выявы не падтрымліваецца",
        "thumbnail_gd-library": "Няпоўная канфігурацыя бібліятэкі GD, адсутнічае функцыя $1",
        "thumbnail_image-missing": "Хутчэй за ўсё, адсутнічае файл $1",
+       "thumbnail_image-failure-limit": "Занадта шмат няўдалых спробаў ($1 ці болей) стварыць гэту мініяцюру, за апошні час. Калі ласка, паспрабуйце пазней.",
        "import": "Імпартаваць старонкі",
        "importinterwiki": "Імпарт Transwiki",
        "import-interwiki-text": "Выбар вікі і назвы старонкі дзеля імпарту.\nДаты версій і імёны аўтараў будуць захаваныя.\nУсе транс-вікавыя імпарты запісваюцца ў [[Special:Log/import|журнале імпартаў]].",
        "import-interwiki-templates": "Разам з усімі шаблонамі",
        "import-interwiki-submit": "Імпартаваць",
        "import-interwiki-namespace": "У прастору назваў:",
+       "import-interwiki-rootpage": "Мэтавая каранёвая старонка (неабавязкова):",
        "import-upload-filename": "Назва файла:",
        "import-comment": "Каментарый:",
        "importtext": "Калі ласка, экспартуйце файл з крынічнай вікі з дапамогай [[Special:Export|прылады экспарту]].\nЗахавайце яго на свой камп'ютар, а потым загрузіце сюды.",
        "import-error-interwiki": "Старонка «$1» не была імпартаваная, таму што гэтая назва зарэзерваваная для інтэрвікі.",
        "import-error-special": "Старонка «$1» не была імпартаваная, таму што яна належыць да спецыяльнай прасторы назваў, старонкі ў якой не дазволеныя.",
        "import-error-invalid": "Старонка «$1» не была імпартаваная з-за няслушнасці назвы.",
+       "import-error-unserialize": "Немагчыма дэсерыялізаваць версію $2 старонкі \"$1\". Меркавалася, што версія выкарыстоўвае мадэль змесціва $3, серыялізавана як $4.",
+       "import-error-bad-location": "Версія $2, якая выкарыстоўвае мадэль змесціва $3, не можа быць запісана на старонцы \"$1\" гэтай вікі, паколькі такая мадэль не падтрымліваецца на гэтай старонцы.",
+       "import-rootpage-invalid": "Пазначаная назва каранёвай старонкі недапушчальная.",
+       "import-rootpage-nosubpage": "У прастора назваў \"$1\" каранёвай старонкі падстаронкі не дазволены.",
        "importlogpage": "Журнал імпартаванняў",
        "importlogpagetext": "Адміністрацыйныя імпартаванні старонак з іншых вікі, разам з гісторыямі правак.",
        "import-logentry-upload": "імпартавана [[$1]] праз файлавы ўклад",
        "spambot_username": "Чыстка спаму MediaWiki",
        "spam_reverting": "Вяртаемся да апошняй версіі без спасылак на $1",
        "spam_blanking": "Усе версіі ўтрымлівалі спасылкі на $1, чысцім",
+       "spam_deleting": "Усе версіі ўтрымлівалі спасылкі на $1, сціраем",
+       "simpleantispam-label": "Праверка анты-спаму.\n<strong>НЕ</strong> ўпісвайце тут нічога!",
        "pageinfo-title": "Інфармацыя для \"$1\"",
+       "pageinfo-not-current": "Выбачайце, немагчыма даць гэтыя звесткі для старых версій.",
        "pageinfo-header-basic": "Агульныя звесткі",
        "pageinfo-header-edits": "Гісторыя правак",
        "pageinfo-header-restrictions": "Ахова старонкі",
        "pageinfo-authors": "Агульная колькасць розных аўтараў",
        "pageinfo-recent-edits": "Колькасць нядаўніх правак (за апошнія $1)",
        "pageinfo-recent-authors": "Колькасць аўтараў за апошні час",
+       "pageinfo-magic-words": "{{PLURAL:$1|1=Магічнае слова|Магічныя словы}} ($1)",
        "pageinfo-hidden-categories": "Схаван{{PLURAL:$1|ая катэгорыя|ыя катэгорыі}} ($1)",
        "pageinfo-templates": "Выкарыстаны {{PLURAL:$1|шаблон|шаблоны}} ($1)",
        "pageinfo-transclusions": "Выкарыстаны на {{PLURAL:$1|старонцы|старонках}} ($1)",
        "file-info-size-pages": "$1 × $2 пікселяў, памер файла: $3, MIME-тип: $4, $5 {{PLURAL:$5|старонка|старонкі|старонак}}",
        "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.",
        "file-info-png-looped": "бясконца",
        "file-info-png-repeat": "паўтараецца $1 {{PLURAL:$1|раз|разоў}}",
        "file-info-png-frames": "$1 {{PLURAL:$1|кадр|кадраў}}",
+       "file-no-thumb-animation": "<strong>Заўвага: З-за тэхнічных абмежаванняў мініяцюры гэтага файла не будуць анімаванымі.</strong>",
+       "file-no-thumb-animation-gif": "<strong>Заўвага: З-за тэхнічных абмежаванняў мініяцюры файлаў GIF высокага разрознення, такіх як гэты, ствараюцца без анімацыі.</strong>",
        "newimages": "Новыя файлы",
        "imagelisttext": "Ніжэй даецца спіс з '''$1''' {{PLURAL:$1|файла|файлаў}} у парадку $2.",
        "newimages-summary": "Тут паказаныя нядаўна ўкладзеныя файлы.",
        "imgmultigo": "Пераход!",
        "imgmultigoto": "На старонку $1",
        "img-lang-default": "(прадвызначаная мова)",
+       "img-lang-info": "Паказаць гэту выяву на мове $1. $2",
+       "img-lang-go": "Перайсці",
        "ascending_abbrev": "да больш.",
        "descending_abbrev": "да менш.",
        "table_pager_next": "Наступная старонка",
        "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",
+       "version-credits-summary": "Мы хацелі б адзначыць наступных асоб, якія зрабілі ўнёсак у [[Special:Version|MediaWiki]].",
        "version-license-info": "MediaWiki з'яўляецца свабодным праграмным забеспячэннем. Такім чынам, вы можаце паўторна распаўсюджваць прадукт і(або) змяняць яго на ўмовах пагаднення GNU General Public License у тым выглядзе, у якім яно публікуецца фондам Free Software Foundation; сілу мае версія (выпуск) 2 гэтага пагаднення або, на ваш выбар, навейшая версія (выпуск) пагаднення.\n\nMediaWiki распаўсюджваецца, спадзеючыся на прыдатнасць прадукта, але БЕЗ ЯКІХ-НЕБУДЗЬ ГАРАНТЫЙ, у тым ліку, без імплікаваных гарантый СПАЖЫВЕЦКАЙ ВАРТАСЦІ або ПРЫДАТНАСЦІ ДЛЯ ЯКОЙ-НЕБУДЗЬ МЭТЫ. Больш падрабязна гл. пагадненне GNU General Public License.\n\nРазам з гэтым праграмным забеспячэннем вы павінны былі атрымаць [{{SERVER}}{{SCRIPTPATH}}/COPYING копію пагаднення GNU General Public License]. Калі гэта не так, паведамце аб гэтым у фонд Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA або [//www.gnu.org/licenses/old-licenses/gpl-2.0.html атрымайце яе з Інтэрнэту].",
        "version-software": "Устаноўленыя праграмныя прадукты",
        "version-software-product": "Прадукт",
        "version-software-version": "Версія",
+       "version-entrypoints": "Уваходныя адрасы",
        "version-entrypoints-header-entrypoint": "Кропка ўваходу",
        "version-entrypoints-header-url": "URL",
+       "redirect": "Перасылка да файла, ID удзельніка, старонкі ці версіі",
        "redirect-legend": "Перасылка да файла ці старонкі",
+       "redirect-summary": "Гэта адмысловая старонка перасылае да файла (з назвы файла), на старонку (з ідэнтыфікатара версіі ці старонкі), ці на старонку ўдзельніка (калі дадзены лічбавы ID удзельніка). Ужыванне: [[{{#Special:Redirect}}/file/Example.jpg]], [[{{#Special:Redirect}}/page/64308]], [[{{#Special:Redirect}}/revision/328429]], ці [[{{#Special:Redirect}}/user/101]].",
        "redirect-submit": "Перайсці",
        "redirect-lookup": "Шукаць:",
        "redirect-value": "Значэнне:",
        "htmlform-reset": "Адкаціць змяненні",
        "htmlform-selectorother-other": "Рознае",
        "htmlform-no": "Не",
+       "htmlform-yes": "Так",
        "htmlform-cloner-create": "Дадаць яшчэ",
        "htmlform-cloner-delete": "Сцерці",
        "htmlform-cloner-required": "Неабходна хаця б адно значэнне.",
        "api-error-overwrite": "Замена існуючага файла не дапускаецца.",
        "api-error-stashfailed": "Унутраная памылка: сервер не змог захаваць часовы файл.",
        "api-error-publishfailed": "Унутраная памылка: сервер не змог апублікаваць тымчасовы файл.",
+       "api-error-stasherror": "У час укладання файла ў сховішча здарылася памылка.",
        "api-error-timeout": "Сервер не адказаў у чаканы тэрмін.",
        "api-error-unclassified": "Узнікла невядомая памылка",
        "api-error-unknown-code": "Невядомая памылка: «$1».",
        "duration-decades": "$1 {{PLURAL:$1|дзесяцігоддзе|дзесяцігоддзі|дзесяцігоддзяў}}",
        "duration-centuries": "$1 {{PLURAL:$1|стагоддзе|стагоддзі|стагоддзяў}}",
        "duration-millennia": "$1 {{PLURAL:$1|тысячагоддзе|тысячагоддзі|тысячагоддзяў}}",
+       "rotate-comment": "Выява павернута на $1 {{PLURAL:$1|градус|градусы|градусаў}} па гадзіннікавай стрэлцы",
+       "limitreport-title": "Звесткі прафілявання парсера:",
+       "limitreport-cputime": "Выкарыстанне часу ЦП",
        "limitreport-cputime-value": "$1 {{PLURAL:$1|секунда|секунды|секундаў}}",
        "limitreport-walltime-value": "$1 {{PLURAL:$1|секунда|секунды|секундаў}}",
+       "limitreport-ppvisitednodes": "Колькасць вузлоў, наведаных прэпрацэсарам",
+       "limitreport-ppgeneratednodes": "Колькасць вузлоў, створаных прэпрацэсарам",
+       "limitreport-postexpandincludesize": "Памер уключэнняў па разгортванні",
        "limitreport-postexpandincludesize-value": "$1/$2 {{PLURAL:$2|байт|байты|байтаў}}",
        "limitreport-templateargumentsize": "Памер аргументаў шаблона",
        "limitreport-templateargumentsize-value": "$1/$2 {{PLURAL:$2|байт|байты|байтаў}}",
        "limitreport-expansiondepth": "Найбольшая глыбіня разгортвання",
+       "limitreport-expensivefunctioncount": "Колькасць працаёмкіх зваротаў да функцый парсера",
+       "expandtemplates": "Разгортванне шаблонаў",
+       "expand_templates_intro": "Гэта адмысловая старонка бярэ тэкст і разгортвае ў ім усе шаблоны рэкурсіўна.\nТаксама разгортвае падтрыманыя функцыі парсера кшталту\n<code><nowiki>{{</nowiki>#language:…}}</code> і зменныя віду\n<code><nowiki>{{</nowiki>CURRENTDAY}}</code>.\nФактычна, яна разгортвае ў пэўнай ступені ўсё ў двайных фігурных дужках.",
+       "expand_templates_title": "Загаловак старонкі, для {{FULLPAGENAME}} і г.д.:",
        "expand_templates_input": "Уваходны тэкст:",
        "expand_templates_output": "Вынік",
+       "expand_templates_xml_output": "Выніковы XML",
+       "expand_templates_html_output": "Выніковы зыходны код HTML",
+       "expand_templates_ok": "Добра",
        "expand_templates_remove_comments": "Сцерці каментарыі",
-       "expand_templates_preview": "Перадпаказ"
+       "expand_templates_remove_nowiki": "Прыбраць тэгі <nowiki> з выніку",
+       "expand_templates_generate_xml": "Паказаць дрэва сінтаксічнага аналізу XML",
+       "expand_templates_generate_rawhtml": "Паказаць зыходны код HTML",
+       "expand_templates_preview": "Перадпаказ",
+       "pagelanguage": "Выбар мовы старонкі",
+       "pagelang-name": "Старонка",
+       "pagelang-language": "Мова",
+       "pagelang-use-default": "Прадвызначаная мова",
+       "pagelang-select-lang": "Выберыце мову",
+       "right-pagelang": "Змяняць мову старонкі",
+       "action-pagelang": "змяняць мову старонкі",
+       "log-name-pagelang": "Журнал змянення мовы",
+       "log-description-pagelang": "Гэта журнал змяненняў у мовах старонкі.",
+       "logentry-pagelang-pagelang": "$1 {{GENDER:$2|змяніў|змяніла}} мову старонкі $3 з $4 на $5."
 }
index 2231bd2..bd3d464 100644 (file)
        "tog-hidepatrolled": "हाल के परिवर्तन में मामूली संपादन छुपाईं",
        "tog-newpageshidepatrolled": "नयका पृष्ठ के सूची में से जाँचल पृष्क के छुपाँई",
        "tog-extendwatchlist": "मात्र हाल के परिवर्तन ही नाही,बल्कि सब परिवर्तन के देखावे खातिर ध्यान सूची के विस्तारित करीं",
-       "tog-usenewrc": "तà¥\81रà¤\82त à¤­à¤\88ल à¤ªà¤°à¤¿à¤µà¤°à¥\8dतन à¤\86 à¤§à¥\8dयानसà¥\82à¤\9aà¥\80 à¤ªà¤°à¤¿à¤µà¤°à¥\8dतनà¥\8bà¤\82 à¤\95à¥\87 à¤ªà¤¨à¥\8dना à¤\95à¥\87 à¤\85नà¥\81सार à¤¸à¤®à¥\82ह à¤®à¥\87à¤\82 à¤¬à¤¾à¤\81à¤\9fà¥\80 (à¤\9cावासà¥\8dà¤\95à¥\8dरिपà¥\8dà¤\9f à¤\86वशà¥\8dयà¤\95)",
+       "tog-usenewrc": "तà¥\81रà¤\82त à¤­à¤\88ल à¤ªà¤°à¤¿à¤µà¤°à¥\8dतन à¤®à¥\87à¤\82 à¤\86 à¤§à¥\8dयानसà¥\82à¤\9aà¥\80 à¤®à¥\87à¤\82 à¤­à¤\88ल à¤ªà¤°à¤¿à¤µà¤°à¥\8dतनन à¤\95à¥\87 à¤ªà¤¨à¥\8dना à¤\85नà¥\81सार à¤¸à¤®à¥\82ह à¤®à¥\87à¤\82 à¤¬à¤¾à¤\82à¤\9fà¥\80",
        "tog-numberheadings": "स्वयं-सांख्यिकी शिर्षक",
-       "tog-showtoolbar": "समà¥\8dपादन à¤\94à¤\9cारà¥\8d à¤¬à¤\95à¥\8dसा à¤\95à¥\87 à¤¦à¤¿à¤\96ाà¤\87लà¥\8d à¤\9cाà¤\8f",
-       "tog-editondblclick": "दà¥\81à¤\88 à¤\95à¥\8dलिà¤\95 à¤ªà¤° à¤ªà¥\83षà¥\8dठ à¤¸à¤\82पादित à¤\95रà¥\80à¤\82 (à¤\9cावासà¥\8dà¤\95à¥\8dरिपà¥\8dà¤\9f à¤\86वशà¥\8dयà¤\95 à¤¬à¤¾)",
-       "tog-editsectiononrightclick": "अनुभाग शीर्षक पर दायाँ क्लिक कर अनुभाग सम्पादित करीं (जावास्क्रिप्ट आवश्यक बा)",
+       "tog-showtoolbar": "समà¥\8dपादन à¤\94à¤\9cारपà¤\9fà¥\8dà¤\9fà¥\80 à¤\95à¥\87 à¤¦à¤¿à¤\96ावल à¤\9cाव",
+       "tog-editondblclick": "दà¥\81à¤\88 à¤\95à¥\8dलिà¤\95 à¤ªà¤° à¤ªà¤¨à¥\8dना à¤¸à¤\82पादन à¤\95रà¥\80à¤\82",
+       "tog-editsectiononrightclick": "अनुभाग शीर्षक पर दायाँ क्लिक कर अनुभाग सम्पादित करीं",
        "tog-watchcreations": "हमरा द्वारा निर्मित पृष्ठ आ हमरा द्वारा लादल फ़ाइलन के हमार ध्यानसूची में जोड़ी",
        "tog-watchdefault": "हमरा द्वारा निर्मित पृष्ठ आ हमरा द्वारा लादल फ़ाइलन के हमार ध्यानसूची में जोड़ी",
        "tog-watchmoves": "हमरा द्वारा स्थानांतरित पृष्ठ आ लादल फाईल के हमरा ध्यानसूची में जोड़ी",
@@ -31,7 +31,7 @@
        "tog-shownumberswatching": "ध्यान रखे वालन सदस्यन के देखावल जाव",
        "tog-oldsig": "वर्तमान हस्ताक्षर:",
        "tog-fancysig": "हस्ताक्षर के विकी पाठ के रुप में उपयोग करीं (बिना स्वचालित कड़ी के)",
-       "tog-uselivepreview": "लाà¤\88व à¤ªà¥\81रà¥\8dवालà¥\8bà¤\95न à¤\95à¥\87 à¤ªà¥\8dरयà¥\8bà¤\97 à¤\95रà¥\80à¤\82 (à¤\9cावासà¥\8dà¤\95à¥\8dरिपà¥\8dà¤\9f à¤¹à¥\8bà¤\96à¥\87 à¤\95à¥\87 à¤\9aाहà¥\80à¤\82) (पà¥\8dरयà¥\8bà¤\97à¤\95à¥\8dषम)",
+       "tog-uselivepreview": "लाà¤\87व à¤ªà¥\81रà¥\8dवालà¥\8bà¤\95न à¤\95à¥\87 à¤ªà¥\8dरयà¥\8bà¤\97 à¤\95रà¥\80à¤\82 (पà¥\8dरयà¥\8bà¤\97ातà¥\8dमà¤\95)",
        "tog-forceeditsummary": "यदि सम्पादन सारांश ना दिहल होखे त हमके सूचित करब",
        "tog-watchlisthideown": "हमार ध्यान दिहल पन्ना के सूची से हमरा खातिर परिवर्तन छिपाईं",
        "tog-watchlisthidebots": "हमार ध्यान सूची से बोट द्वारा करल गईल परिवर्तन के छिपाईं",
        "category-empty": "''इ श्रेणी में इ समय कउनो पन्ना या मीडिया नइखे।''",
        "hidden-categories": "{{PLURAL:$1|छुपावल गईल श्रेणी|छुपावल गईल श्रेणीं}}",
        "hidden-category-category": "छुपावल गइल श्रेणीं",
-       "category-subcat-count": "{{PLURAL:$2|à¤\87 à¤¶à¥\8dरà¥\87णà¥\80 à¤®à¥\87à¤\82 à¤®à¤¾à¤¤à¥\8dर à¤¨à¤¿à¤®à¥\8dनलिà¤\96ित à¤\89पशà¥\8dरà¥\87णà¥\80 à¤¬à¤¾|à¤\87 à¤¶à¥\8dरà¥\87णà¥\80 à¤®à¥\87à¤\82 à¤¨à¤¿à¤®à¥\8dनलिà¤\96ित {{PLURAL:$1|à¤\89पशà¥\8dरà¥\87णà¥\80|$1 à¤\89पशà¥\8dरà¥\87णà¥\80याà¤\82}} à¤¬à¤¾à¤¡à¤¼à¥\87, à¤\95à¥\81ल à¤\89पशà¥\8dरà¥\87णà¥\80याà¤\82 $2 à¤¬à¤¾à¤¡à¤¼à¥\87।}}",
+       "category-subcat-count": "{{PLURAL:$2|à¤\87 à¤¶à¥\8dरà¥\87णà¥\80 à¤®à¥\87à¤\82 à¤®à¤¾à¤¤à¥\8dर à¤¨à¤¿à¤®à¥\8dनलिà¤\96ित à¤\89पशà¥\8dरà¥\87णà¥\80 à¤¬à¤¾|à¤\87 à¤¶à¥\8dरà¥\87णà¥\80 à¤®à¥\87à¤\82 à¤¨à¤¿à¤®à¥\8dनलिà¤\96ित {{PLURAL:$1|à¤\89पशà¥\8dरà¥\87णà¥\80|$1 à¤\89पशà¥\8dरà¥\87णियाà¤\82}} à¤¬à¤¾à¤¡à¤¼à¥\87, à¤\95à¥\81ल à¤\89पशà¥\8dरà¥\87णियाà¤\81$2}}",
        "category-subcat-count-limited": "इ श्रेणी में निम्नलिखित {{PLURAL:$1|उपश्रेणी बा|$1 उपश्रेणीं बाड़े}}।",
-       "category-article-count": "{{PLURAL:$2|इ श्रेणी में मात्र निम्नलिखित पन्ना बा।|इ श्रेणी में निम्नलिखित {{PLURAL:$1|पन्ना बा|$1 पन्नें}}, कुल पन्नें $2 बाड़े।}}",
+       "category-article-count": "{{PLURAL:$2|इ श्रेणी में मात्र निम्नलिखित पन्न बा।|इ श्रेणी में निम्नलिखित {{PLURAL:$1|पन्ना बा|$1 पन्ना बाड़े}, कुल पन्ना $2}}",
        "category-article-count-limited": "निम्नलिखित {{PLURAL:$1|पन्ना|$1 पन्ना}} इ श्रेणीं में बा।",
        "category-file-count": "{{PLURAL:$2|इ श्रेणी में मात्र निम्नलिखित फ़ाइल बा।|इ श्रेणी में निम्नलिखित {{PLURAL:$1|फ़ाइल|$1 फ़ाइलं}} बाड़े, कुल फ़ाइलं $2}}",
        "category-file-count-limited": "वर्तमान में निम्नलिखित {{PLURAL:$1|पन्ना|$1 पन्नां}} इ श्रेणीं में बाड़े।",
        "newwindow": "(नया विंडो में खोलीं)",
        "cancel": "निरस्त",
        "moredotdotdot": "अउर...",
-       "morenotlisted": "à¤\85धिà¤\95 à¤¸à¥\82à¤\9aà¥\80बदà¥\8dध à¤¨à¤\87à¤\96à¥\87...",
+       "morenotlisted": "à¤\87 à¤¸à¥\82à¤\9aà¥\80 à¤ªà¥\82रà¥\8dण à¤¨à¤\87à¤\96à¥\87।",
        "mypage": "पन्ना",
        "mytalk": "राउर बात",
        "anontalk": "इ आइ॰पी खातिर वार्ता",
        "permalink": "स्थायी लिंक",
        "print": "छापीं",
        "view": "देखीं",
+       "view-foreign": "$1 पर देखीं",
        "edit": "सम्पादन",
+       "edit-local": "क्षेत्रीय विवरण देखीं",
        "create": "बनाईं",
+       "create-local": "क्षेत्रीय विवरण जोड़ीं",
        "editthispage": "ई पन्ना के सम्पादन करीं",
        "create-this-page": "ई पन्ना के निर्माण करीं",
        "delete": "मिटाईं",
        "articlepage": "सामग्री पन्ना देखीं",
        "talk": "बात-चीत",
        "views": "विचारसूची",
-       "toolbox": "à¤\94à¤\9cार-पà¥\87à¤\9fà¥\80",
+       "toolbox": "à¤\89पà¤\95रण",
        "userpage": "प्रयोगकर्ता पन्ना देखीं",
        "projectpage": "परियोजना पन्ना देखीं",
        "imagepage": "फाईल पन्ना देखीँ",
        "jumptonavigation": "परिभ्रमण",
        "jumptosearch": "खोजीं",
        "view-pool-error": "क्षमा करीं, ई समय सर्वर पर बहुत ज्यादा लोड बढ़ गईल बा।\nई पन्ना के बहुते प्रयोगकर्ता लोग देखे के कोशिश कर रहल बानी।\nई पन्ना के फिर से देखे से पहिले कृपया कुछ देर तक इन्तजार करीं।\n\n$1",
+       "generic-pool-error": "क्षमा करीं, ई समय सर्वर पर बहुत ज्यादा लोड बढ़ गईल बा।\nई संसाधन के बहुते प्रयोगकर्ता लोग देखे के कोशिश कर रहल बानी।\nई संसाधन तक पहुँच बनावे के कोशिश से पहिले कृपया कुछ देर तक इन्तजार करीं।",
        "pool-timeout": "तालाबन्दी खातिर प्रतीक्षा समय समाप्त",
        "pool-queuefull": "पूल पंक्ति भर गइल",
        "pool-errorunknown": "अज्ञात त्रुटि",
+       "pool-servererror": "पूल काउंटर सेवा उपलब्ध नाही बा ($1)।",
        "aboutsite": "{{SITENAME}} के बारे में",
        "aboutpage": "Project:बारे में",
-       "copyright": "सामà¤\97à¥\8dरà¥\80 $1 à¤\95à¥\87 à¤¤à¤¹à¤¤ à¤\89पलबà¥\8dध à¤¬à¤¾।",
+       "copyright": "à¤\89पलबà¥\8dध à¤¸à¤¾à¤®à¤\97à¥\8dरà¥\80 $1 à¤\95à¥\87 à¤\85धà¥\80न à¤\89पलबà¥\8dध à¤¬à¤¾ à¤\9cब à¤¤à¤\95 à¤\95à¥\80 à¤\85लà¤\97 à¤¸à¥\87 à¤\89लà¥\8dलà¥\87à¤\96 à¤¨à¤¾ à¤\95रल à¤\97à¤\88ल à¤¹à¥\8bà¤\96à¥\87 ।",
        "copyrightpage": "{{ns:project}}:लेखाधिकार",
        "currentevents": "हाल के घटना",
        "currentevents-url": "Project:हाल के घटना",
        "youhavenewmessages": "रउआ लगे बा $1 ($2).",
        "youhavenewmessagesfromusers": "रउआ खातिर {{PLURAL:$3|एगो अन्य सदस्य|$3 अन्य सदस्यन}} के $1 बा। ($2)",
        "youhavenewmessagesmanyusers": "रउआ खातिर कई सदस्यन द्वारा $1 बा। ($2)",
-       "newmessageslinkplural": "{{PLURAL:$1|à¤\8fà¤\97à¥\8b à¤¨à¤¯à¤¾ à¤¸à¤¨à¥\8dदà¥\87श à¤¬à¤¾|नया à¤¸à¤¨à¥\8dदà¥\87श à¤¬à¤¾à¤¡à¤¼à¤¨}}",
-       "newmessagesdifflinkplural": "{{PLURAL:$1|पिछला|पिछलका}} बदलाव",
+       "newmessageslinkplural": "{{PLURAL:$1|à¤\8fà¤\95 à¤¨à¤¯à¤¾ à¤¸à¤¨à¥\8dदà¥\87श|999=नयà¤\95ा à¤¸à¤¨à¥\8dदà¥\87श}}",
+       "newmessagesdifflinkplural": "पिछला {{PLURAL:$1|बदलाव|999=बदलावं}}",
        "youhavenewmessagesmulti": "रउआ लगे $1 पर नया सन्देश बा",
        "editsection": "सम्पादन",
        "editold": "सम्पादन",
        "nospecialpagetext": "<strong>रउआ एगो अवैद्य विशेष पन्ना के अनुरोध कईले बानी।</strong>\n\nवैद्य विशेष पन्ना के सूची मिल सकत बा [[Special:SpecialPages|{{int:specialpages}}]] पर।",
        "error": "त्रुटी",
        "databaseerror": "डेटाबेस त्रुटी",
+       "databaseerror-text": "डाटाबेस अनुरोध त्रुटि  भइल बा।\nसंभवतः सॉफ़्टवेयर में गड़बड़ी बा।",
+       "databaseerror-textcl": "डाटाबेस अनुरोध त्रुटि उत्त्पन्न हो गईल बा।",
+       "databaseerror-query": "अनुरोध: $1",
+       "databaseerror-function": "फ़ंक्शन: $1",
+       "databaseerror-error": "त्रुटि: $1",
        "laggedslavemode": "'''चेतावनी:''' इ पन्ना पर हाल के बदलाव ना होखे के आशंका बा।",
        "readonly": "डेटाबेस लॉक बा",
        "enterlockreason": "लॉक करे के कारण दिहीं, साथे लॉक खुले के समय के लगभग आकलन दिहीं।",
        "invalidtitle-knownnamespace": "\"$2\" नामस्थान आ \"$3\" पाठ्य वाला गलत शीर्षक",
        "invalidtitle-unknownnamespace": "अज्ञात नामस्थान संख्या $1 आ नाम \"$2\" वाला गलत शीर्षक",
        "exception-nologin": "खाता में प्रवेश नईखीं भईल",
-       "exception-nologin-text": "इ पन्ना अथवा कार्य खातिर रउआ विकि प्रवेश (लॉग इन) होना आवश्यक है।",
+       "exception-nologin-text": "इ पन्ना अथवा कार्य के सक्षम करे खातिर कृपया [[Special:Userlogin|लॉग इन]] करीं।",
+       "exception-nologin-text-manual": "इ पन्ना अथवा कार्य के सक्षम करे खातिर कृपया $1 करीं।",
        "virus-badscanner": "गलत जमाव: अज्ञात वायरस जाँचक: ''$1''",
        "virus-scanfailed": "जाँच विफल (कोड $1)",
        "virus-unknownscanner": "अज्ञात ऐंटीवायरस:",
        "gotaccount": "का पहिले से एगो खाता बा? $1.",
        "gotaccountlink": "खाता में प्रवेश",
        "userlogin-resetlink": "का रउआ आपन प्रवेश जानकारी भूला गइल बानी?",
-       "userlogin-resetpassword-link": "आपन गुप्तशब्द के फिर से बहाल करीं",
+       "userlogin-resetpassword-link": "आपन गुप्तशब्द भूला गईनी का?",
+       "userlogin-helplink2": "खाता प्रवेश साथ मदद",
+       "userlogin-loggedin": "रउआ {{GENDER:$1|$1}} के रूप में पहिले से लॉग्ड इन बानीं।\nकौनो अन्य सदस्य के रूप में लॉग इन करे खातिर निम्नलिखित फ़ॉर्म के प्रयोग करीं।",
+       "userlogin-createanother": "एगो दोसर खाता बनाईं",
        "createacct-emailrequired": "ई-मेल पता",
        "createacct-emailoptional": "ई-मेल पता (वैकल्पिक)",
        "createacct-email-ph": "आपन ई-मेल पता लिखीं",
        "passwordtooshort": "गुप्त-शब्द कम से कम {{PLURAL:$1|1 अक्षर|$1 अक्षर}} के होवे के चाहीं।",
        "password-name-match": "राउर गुप्त-शब्द राउर प्रयोगकर्ता नाम से अलग होवे के चाहीं।",
        "password-login-forbidden": "इस सदस्यनाम आ गुप्तशब्द के प्रयोग वर्जित बा।",
-       "mailmypassword": "नया à¤\97à¥\81पà¥\8dत-शबà¥\8dद à¤\88-मà¥\87ल à¤ªà¤° à¤­à¥\87à¤\9cीं",
+       "mailmypassword": "à¤\97à¥\81पà¥\8dतशबà¥\8dद à¤°à¤¿à¤¸à¥\87à¤\9f à¤\95रीं",
        "passwordremindertitle": "{{SITENAME}} खातिर नया अस्थायी गुप्त-शब्द",
        "passwordremindertext": "केहु (शायद रउए, $1 आइ॰पी पता से) {{SITENAME}} ($4) पर प्रयोग खातिर नया गुप्तशब्द के निवेदन कईले बानी। सदस्य \"$2\" खातिर एगो अस्थायी गुप्तशब्द बना दिहल गईल बा, आ ई अभी \"$3\" बा। यदि ई राउरे आशय रहल, त अब रउआ खाता प्रवेश खातिर एगो नया गुप्तशब्द चुने के पड़ी।\nराउर अस्थायी गुप्तशब्द के अवधि {{PLURAL:$5|एक दिन|$5 दिनं}} में समाप्त हो जाई।\n\nयदि इ निवेदन केहु अउर कइले रहल, या रउआ आपन पुरान गुप्तशब्द अब नइखी बदले के चाहत काहे कि रउआ राउर पुरनका गुप्तशब्द के स्मरण हो आइल बा, त रउआ इ संदेश के अनदेखा कर सकत बानी, आ आपन पुरान गुप्तशब्द के प्रयोग पहिले हि जइसन कर सकत बानी।",
        "noemail": "\"$1\" सदस्य खातिर कउनो भी ई-मेल पता दर्ज नइखे करल गइल।",
        "noemailcreate": "रउआ एगो जायज ई-मेल पता उपलब्ध करावे के पड़ी।",
        "passwordsent": "\"$1\" के ई-मेल पता पर एगो नया गुप्तशब्द भेज दिहल गइल बा।\nई-मेल पावे के बाद कृपया दुबारा खाता में प्रवेश करब।",
        "blocked-mailpassword": "राउर आइ॰पी पता के सम्पादन करे से वंचित कर दिहल गइल बा, आ गलत प्रयोग रोके खातिर गुप्तशब्द पुनः प्राप्ति के सुविधा इ आइ॰पी पर बंद कर दिहल गइल बा।",
-       "eauthentsent": "दरà¥\8dà¤\9c à¤\95रावल à¤\97à¤\87ल à¤\88-मà¥\87ल à¤ªà¤¤à¤¾ à¤ªà¤° à¤\8fà¤\97à¥\8b à¤ªà¥\81षà¥\8dà¤\9fिà¤\95रण à¤\88-मà¥\87ल à¤­à¥\87à¤\9c à¤¦à¤¿à¤¹à¤² à¤\97à¤\87ल à¤¬à¤¾à¥¤\nरà¤\89à¤\86 à¤\89 à¤\88-मà¥\87ल à¤ªà¤° à¤¦à¤¿à¤¹à¤² à¤\97à¤\87ल à¤¨à¤¿à¤°à¥\8dदà¥\87श à¤\95à¥\87 à¤\85नà¥\81सरण à¤\95र à¤\95à¥\87 à¤\88-मà¥\87ल à¤ªà¤¤à¤¾ à¤\95à¥\87 à¤ªà¥\81षà¥\8dà¤\9fिà¤\95रण à¤\95रावà¥\87 à¤\95à¥\87 à¤ªà¤¡à¤¼à¥\80, à¤\93à¤\95रा à¤¬à¤¾à¤¦à¥\87 à¤\85हिà¤\9cा à¤¸à¥\87 à¤\95à¤\89नà¥\8b à¤¦à¥\82सर à¤\88-मà¥\87ल à¤­à¥\87à¤\9cल à¤\9cाà¤\88।",
+       "eauthentsent": "दरà¥\8dà¤\9c à¤\95रावल à¤\97à¤\87ल à¤\88-मà¥\87ल à¤ªà¤¤à¤¾ à¤ªà¤° à¤\8fà¤\97à¥\8b à¤ªà¥\81षà¥\8dà¤\9fिà¤\95रण à¤\88-मà¥\87ल à¤­à¥\87à¤\9c à¤¦à¤¿à¤¹à¤² à¤\97à¤\87ल à¤¬à¤¾à¥¤\nà¤\89 à¤\96ाता à¤ªà¤° à¤\95à¥\8cनà¥\8b à¤¦à¥\81सर à¤\88मà¥\87ल à¤­à¥\87à¤\9cल à¤\9cाà¤\93 à¤\89 à¤¸à¥\87 à¤ªà¤¹à¤¿à¤²à¥\87, à¤°à¤\89à¤\86 à¤­à¥\87à¤\9cल à¤\97à¤\88ल à¤\88-मà¥\87ल à¤ªà¤° à¤¦à¤¿à¤¹à¤² à¤\97à¤\87ल à¤¨à¤¿à¤°à¥\8dदà¥\87श à¤\95à¥\87 à¤\85नà¥\81सरण à¤\95र à¤\95à¥\87 à¤\88-मà¥\87ल à¤ªà¤¤à¤¾ à¤\95à¥\87 à¤ªà¥\81षà¥\8dà¤\9fिà¤\95रण à¤\95रावà¥\87 à¤\95à¥\87 à¤ªà¤¡à¤¼à¥\80 à¤¤à¤¾à¤\95ि à¤ªà¤¤à¤¾ à¤\9aलà¥\87 à¤\95à¥\80 à¤¸à¤¹à¥\80 à¤®à¥\87à¤\82 à¤\89 à¤°à¤¾à¤\89रà¥\87 à¤\96ाता à¤¹।",
        "throttled-mailpassword": "पिछला {{PLURAL:$1|एक घंटा|$1 घंटा}} के अंदर एगो गुप्तशब्द पुनर्स्थापन ई-मेल भेजल जा चुकल बा।\nदुरुपयोग से बचावे खातिर {{PLURAL:$1|एक घंटा|$1 घंटा}} में सिर्फ एगो गुप्तशब्द पुनर्स्थापन ई-मेल भेजल जाई।",
        "mailerror": "ई-मेल भेजे में त्रुटि: $1",
        "acct_creation_throttle_hit": "राउर आइ॰पी पता से आईल आगंतुक पिछला चौबीस घंटा में इ विकि पर {{PLURAL:$1|एक खाता|$1 खाता}} बना चुकल बानी, इ समयावधि में इहे अधिकतम सीमा बा।\nअतः इ समय इ आइ॰पी पता के प्रयोग करे वाला आगंतुक अउर अधिक खाता नइखन बना सकत।",
-       "emailauthenticated": "राउर ई-मेल पता के पुष्ट दिनांक $2 के $3 बजे हो चुकल रहे।",
-       "emailnotauthenticated": "राउर ई-मेल पता के अभी तक प्रमाणिकरण नइखे भईल।\nनिम्नलिखित कउनो भी सुविधा खातिर रउआ ई-मेल ना भेजल जाई।",
+       "emailauthenticated": "$2 के $3 पर राउर ई-मेल पता के पुष्टीकरण हो चुकल बा।",
+       "emailnotauthenticated": "राà¤\89र à¤\88-मà¥\87ल à¤ªà¤¤à¤¾ à¤\95à¥\87 à¤\85भà¥\80 à¤¤à¤\95 à¤ªà¥\8dरमाणिà¤\95रण à¤¨à¤\87à¤\96à¥\87 à¤­à¤\88ल।\nनिमà¥\8dनलिà¤\96ित à¤\95à¤\89नà¥\8b à¤­à¥\80 à¤¸à¥\81विधा à¤\96ातिर à¤°à¤\89à¤\86 à¤\95à¥\87 à¤\95à¥\8cनà¥\8b à¤­à¥\80 à¤\88-मà¥\87ल à¤¨à¤¾ à¤­à¥\87à¤\9cल à¤\9cाà¤\88।",
        "noemailprefs": "इ सुविधा के प्रयोग करे खातिर आपन वरियता में एगो ई-मेल पता दिहीं।",
        "emailconfirmlink": "अपना ई-मेल पता कन्फर्म करीं",
        "invalidemailaddress": "राउर ई-मेल पता स्वीकार करल नइखे जा सकत काहे कि ई-मेल के जउन रुप दिखाई दे रहल बा उ गलत लागत बा।\nकृपया एगो सहि ई-मेल पता उपलब्ध कराईं या उ जगह के खाली छोड़ दिहीं।",
        "loginlanguagelabel": "भाषा: $1",
        "suspicious-userlogout": "राउर खाता से बाहर जाये के अनुरोध अस्वीकृत कर दिहल गइल बा काहे कि  अइसन लग रहल बा कि इ कउनो खराब ब्राउज़र या कैश करे वाली प्रॉक्सी द्वारा भेजल गईल रहल।",
        "createacct-another-realname-tip": "असली नाम वैकल्पिक बा।\nयदि रउआ इ के उपलब्ध करावे के चुनत बानी त, एकर प्रयोग सदस्य के ओकरा काम के अधिकार देवे खातिर होखी।",
+       "pt-login": "खाता में प्रवेश",
+       "pt-login-button": "खाता में प्रवेश",
+       "pt-createaccount": "खाता बनाईं",
+       "pt-userlogout": "खाता से बाहर",
        "php-mail-error-unknown": "PHP के mail() फ़ंक्शन में अज्ञात त्रुटि बा।",
        "user-mail-no-addy": "बिना कउनो ई-मेल पता के ई-मेल भेजे के प्रयत्न भईल बा।",
        "user-mail-no-body": "एगो खाली अथवा बहुत छोट ई-मेल भेजे के प्रयत्न भईल बा।",
        "changepassword": "गुप्त शब्द बदलीं",
-       "resetpass_announce": "रà¤\89à¤\86 à¤\88-मà¥\87ल à¤¸à¥\87 à¤ªà¥\8dरापà¥\8dत à¤\85सà¥\8dथायà¥\80 à¤\95à¥\8bड à¤¸à¥\87 à¤\96ाता à¤®à¥\87à¤\82 à¤ªà¥\8dरवà¥\87श à¤­à¤\88ल à¤¬à¤¾à¤¨à¥\80।\nà¤\96ाता à¤ªà¥\8dरवà¥\87श à¤\95à¥\87 à¤ªà¥\82रा à¤\95रà¥\87 à¤\96ातिर à¤°à¤\89à¤\86 à¤\87हाà¤\81 à¤\8fà¤\97à¥\8b à¤¨à¤¯à¤¾ à¤\97à¥\81पà¥\8dतशबà¥\8dद à¤¦à¥\87वà¥\87 à¤\95à¥\87 à¤ªà¤¡à¤¼à¥\80:",
+       "resetpass_announce": "लà¥\89à¤\97 à¤\87न à¤¸à¤®à¥\8dपà¥\82रà¥\8dण à¤\95रà¥\87 à¤\96ातिर à¤°à¤\89à¤\86 à¤\8fà¤\97à¥\8b à¤¨à¤¯à¤¾ à¤ªà¤¾à¤¸à¤µà¤°à¥\8dड à¤¦à¥\87वà¥\87 à¤\95à¥\87 à¤¹à¥\8bà¤\88।",
        "resetpass_header": "खाता के गुप्तशब्द बदलीं",
        "oldpassword": "पुराना गुप्त-शब्द:",
        "newpassword": "नया गुप्त-शब्द:",
        "retypenew": "नया गुप्त-शब्द पुन: डालीं:",
        "resetpass_submit": "गुप्तशब्द बनाईं आ खाता में प्रवेश करीं",
        "changepassword-success": "राउर गुप्तशब्द सफलतापुर्वक बदल दिहल गईल बा!",
+       "changepassword-throttled": "रउआ हाले में कईयन बार खाता में प्रवेश करे के कोशिश कर चुकल बानी।\nकृपया $1 प्रतिक्षा करला के बाद फिर से प्रयास करब।",
        "resetpass_forbidden": "गुप्तशब्द बदलल नइखे जा सकत",
        "resetpass-no-info": "इ पन्ना के सिधे प्रयोग करे खातिर रउआ पहिले खाता में प्रवेश करे के पड़ी।",
        "resetpass-submit-loggedin": "गुप्त शब्द बदलीं",
        "resetpass-submit-cancel": "रद्द करीं",
        "resetpass-wrong-oldpass": "अवैद्य अस्थायी या वर्तमान गुप्तशब्द।\nरउआ पहिले हिं सफलतापूर्वक आपन गुप्तशब्द बदल चुकल बानी, या रउआ एगो अस्थायी गुप्तशब्द के अनुरोध कइले होखब।",
+       "resetpass-recycled": "रीसेट करे खातिर नया पासवर्ड में कृपया आपन वर्तमान पासवर्ड के अलावा कौनो अन्य पासवर्ड के प्रयोग करीं।",
+       "resetpass-temp-emailed": "अस्थाई ईमेल कोड के द्वारा रउआ लॉग इन भइल बानी।\nलॉग इन पूरा करे खातिर, रउआ एगो नया पासवर्ड सेट करे के पड़ी:",
        "resetpass-temp-password": "अस्थायी गुप्तशब्द:",
        "resetpass-abort-generic": "कउनो एक्सटेंशन द्वारा गुप्तशब्द में बदलाव रोक दिहल गईल बा।",
+       "resetpass-expired": "राउर पासवर्ड की वैधता अवधि समाप्त हो चुकल बा। कृपया लॉग इन करे खातिर एगो नया पासवर्ड सेट करीं।",
        "passwordreset": "गुप्तशब्द रिसेट करीं",
        "passwordreset-text-one": "आपन गुप्तशब्द के पुनर्स्थापित करे खातिर इ फॉर्म भरीं।",
        "passwordreset-text-many": "{{PLURAL:$1|आपन गुप्तशब्द पुनर्स्थापित करे खातिर निम्न में से कउनो एगो स्थान भरीं।}}",
        "permissionserrors": "अनुमति त्रुटी",
        "log-fulllog": "पूरा लॉग देखीं",
        "edit-conflict": "संपादन अंतर्विरोध",
+       "postedit-confirmation-created": "पन्ना बना दिहल गईल।",
        "postedit-confirmation-saved": "राउर सम्पादन सुरक्षित कर दिहल गईल।",
        "invalid-content-data": "अवैध डाटा सामग्री",
        "content-model-wikitext": "विकीपाठ्य",
        "prefs-editing": "संपादन",
        "searchresultshead": "खोज",
        "savedprefs": "राउर वरीयताएँ सुरक्षित कर दिहल गईल।",
+       "timezoneregion-africa": "अफ़्रीका",
+       "timezoneregion-america": "अमेरिका",
+       "timezoneregion-antarctica": "अंटार्कटिका",
+       "timezoneregion-arctic": "आर्कटिक",
        "timezoneregion-asia": "एशिया",
+       "timezoneregion-atlantic": "एटलांटिक महासागर",
        "timezoneregion-australia": "अस्ट्रेलिया",
        "timezoneregion-europe": "यूरोप",
        "timezoneregion-indian": "हिंद महासागर",
        "yourrealname": "असली नाम",
        "yourlanguage": "भाषा:",
        "prefs-preview": "पूर्वावलोकन",
+       "action-move": "ई पन्ना के स्थांतरण करीं",
+       "action-delete": "ई पन्ना के मिटाईं",
        "recentchanges": "तुरंत भईल परिवर्तन",
        "recentchanges-legend": "हाल के परिवर्तन संबंधी विकल्प",
        "recentchanges-label-newpage": "ई सम्पादन से एगो नवका पृष्ठ तैयार हो गइल बा",
        "recentchanges-label-minor": "ई एगो छोटा सम्पाद बा",
+       "recentchanges-legend-heading": "'''कुंजी:'''",
        "rcshowhideminor": "$1 छोट सम्पादन",
+       "rcshowhideminor-show": "दिखाईं",
+       "rcshowhideminor-hide": "छुपाँई",
        "diff": "अन्तर",
        "hist": "इति",
        "hide": "छुपाँई",
        "recentchangeslinked": "सम्बन्धित बदलाव",
        "recentchangeslinked-feed": "सम्बन्धित बदलाव",
        "recentchangeslinked-toolbox": "सम्बन्धित बदलाव",
+       "recentchangeslinked-page": "पन्ना नाम:",
        "upload": "फाईल लादीं",
+       "filedesc": "सारांश",
+       "fileuploadsummary": "सारांश:",
+       "filesource": "स्रोत:",
+       "unknown-error": "अज्ञात त्रुटि उत्पन्न हो गईल बा।",
        "file-anchor-link": "फ़ाइल",
        "filehist": "पन्ना के इतिहास",
        "filehist-deleteall": "सब मिटाईं",
index e7cce5c..434cf28 100644 (file)
        "duplicate-defaultsort": "' ' ' সাবধান: ' ' '  ডিফল্ট সাজানোর কীঃ \"$2\" পূর্বে ডিফল্ট সাজানোর কীঃ \"$1\" কে অগ্রাহ্য করে।",
        "version": "সংস্করণ",
        "version-extensions": "ইন্সটলকৃত এক্সটেনশনসমূহ",
+       "version-skins": "ইনস্টল করা স্কিনসমূহ",
        "version-specialpages": "বিশেষ পাতাসমূহ",
        "version-parserhooks": "পার্সার হুক",
        "version-variables": "চলক",
        "version-antispam": "স্প্যাম প্রতিরোধ",
-       "version-skins": "আবরণসমূহ (Skin)",
        "version-other": "অন্য",
        "version-mediahandlers": "মিডিয়া ব্যবস্থাপক",
        "version-hooks": "হুক",
        "version-hook-name": "হুকের নাম",
        "version-hook-subscribedby": "সাবস্ক্রাইব করেছেন",
        "version-version": "(সংস্করণ $1)",
+       "version-no-ext-name": "[নাম নেই]",
        "version-license": "মিডিয়াউইকি লাইসেন্স",
        "version-ext-license": "লাইসেন্স",
        "version-ext-colheader-name": "এক্সটেনশন",
+       "version-skin-colheader-name": "স্কিন",
        "version-ext-colheader-version": "সংস্করণ",
        "version-ext-colheader-license": "লাইসেন্স",
        "version-ext-colheader-description": "বিবরণ",
index 2c731aa..0198e96 100644 (file)
        "wrongpasswordempty": "Ger-tremen ebet. Lakait unan mar plij.",
        "passwordtooshort": "{{PLURAL:$1|1 arouezenn|$1 arouezenn}} hir a rank bezañ ar gerioù-tremen da nebeutañ.",
        "password-name-match": "Rankout a ra ho ker-tremen bezañ disheñvel diouzh hoc'h anv implijer.",
-       "password-login-forbidden": "Berzet eo ober gant an anv-implijer hag ar ger-tremen-mañ.",
+       "password-login-forbidden": "Berzet eo ober gant an anv implijer hag ar ger-tremen-mañ.",
        "mailmypassword": "Adderaouekaat ar ger-tremen",
        "passwordremindertitle": "Ho ker-tremen berrbad nevez evit {{SITENAME}}",
        "passwordremindertext": "Unan bennak (c'hwi moarvat gant ar chomlec'h IP $1)\nen deus goulennet ma vo kaset dezhañ ur ger-tremen nevez evit {{SITENAME}} ($4).\nSavet ez eus bet ur ger-tremen da c'hortoz evit an implijer \"$2\" hag a zo \"$3\".\nMard eo se a felle deoc'h ober e vo ret deoc'h kevreañ ha cheñch ho ker-tremen bremañ. Didalvez e vo ho ker ker-tremen da c'hortoz a-benn {{PLURAL:$5|un devezh|$5 devezh}}\n\nMard eo bet graet ar goulenn gant unan bennak all, pe m'hoc'h eus soñj eus ho ker-tremen bremañ ha\nma ne fell ket deoc'h cheñch anezhañ ken, e c'hallit leuskel ar postel-mañ a-gostez ha kenderc'hel d'ober gant ho ker-tremen kozh.",
        "duplicate-defaultsort": "Diwallit : Frikañ a ra an alc'hwez dre ziouer \"$2\" an hini a oa a-raok \"$1\".",
        "version": "Stumm",
        "version-extensions": "Astennoù staliet",
-       "version-skins": "Gwiskadurioù",
+       "version-skins": "Gwiskadurioù staliet",
        "version-specialpages": "Pajennoù dibar",
        "version-parserhooks": "Galvoù dielfennañ",
        "version-variables": "Argemmennoù",
        "expand_templates_remove_nowiki": "Diverkañ a ra ar balizennoù <nowiki> en disoc'h",
        "expand_templates_generate_xml": "Gwelet ar gwezennadur XML",
        "expand_templates_generate_rawhtml": "Diskouez an HTML kriz",
-       "expand_templates_preview": "Rakwelet"
+       "expand_templates_preview": "Rakwelet",
+       "pagelang-name": "Pajenn",
+       "pagelang-language": "Yezh",
+       "pagelang-use-default": "Implijout ar yezh dre ziouer",
+       "pagelang-select-lang": "Dibab ar yezh",
+       "right-pagelang": "Cheñch yezh ar bajenn"
 }
index 926aad5..0c30961 100644 (file)
        "pageinfo-lasttime": "Datum posljednje izmjene",
        "pageinfo-edits": "Ukupan broj izmjena",
        "pageinfo-authors": "Ukupan broj različitih autora",
-       "pageinfo-recent-edits": "Broj nedavnih izmjena (u poslednjih $1)",
+       "pageinfo-recent-edits": "Broj nedavnih izmjena (u posljednjih $1)",
        "pageinfo-recent-authors": "Broj nedavnih različitih autora",
        "pageinfo-magic-words": "{{PLURAL:$1|Čarobna riječ|Čarobne riječi}} ($1)",
        "pageinfo-hidden-categories": "{{PLURAL:$1|Sakrivena kategorija|Sakrivene kategorije}} ($1)",
index 4876c6d..a01a3c1 100644 (file)
        "token_suffix_mismatch": "'''S'ha rebutjat la vostra modificació perquè el vostre client ha fet malbé els caràcters de puntuació en el testimoni d'edició. S'ha rebutjat la modificació per a evitar la corrupció del text de la pàgina. Açò passa a vegades quan s'utilitza un servei web de servidor intermediari anònim amb problemes.'''",
        "edit_form_incomplete": "'''Certes parts del formulari de modificació no han arribat al servidor, verifiqueu que les vostres modificacions estan intactes i proveu-ho de nou.'''",
        "editing": "Edició de la pàgina «$1»",
-       "creating": "S'està creant $1",
-       "editingsection": "Edició de «$1» (secció)",
-       "editingcomment": "Edició de «$1» (secció nova)",
+       "creating": "Creació de la pàgina «$1»",
+       "editingsection": "Edició de la pàgina «$1» (secció)",
+       "editingcomment": "Edició de la pàgina «$1» (secció nova)",
        "editconflict": "Conflicte d'edició: $1",
        "explainconflict": "Algú més ha canviat aquesta pàgina des que l'heu editada.\nL'àrea de text superior conté el text de la pàgina com existeix actualment.\nEls vostres canvis es mostren en l'àrea de text inferior.\nHaureu de fusionar els vostres canvis en el text existent.\n'''Només''' el text de l'àrea superior es desarà quan premeu el botó «{{int:savearticle}}».",
        "yourtext": "El vostre text",
        "move-page-legend": "Reanomena la pàgina",
        "movepagetext": "Amb el formulari següent reanomenareu una pàgina, movent tot el seu historial al nou nom.\nEl títol anterior es convertirà en una pàgina de redirecció al nou títol.\nPodeu actualitzar automàticament les redireccions que apuntin al títol original.\nSi no ho feu, assegureu-vos de verificar les redireccions [[Special:DoubleRedirects|dobles]] o [[Special:BrokenRedirects|trencades]].\nSerà de la vostra responsabilitat verificar que els enllaços segueixin apuntant cap a on se suposa que ho han de fer.\n\nTingueu en compte que la pàgina '''no''' serà traslladada si ja existeix una pàgina amb el títol nou, tret que sigui una redirecció sense més historial.\nAixò significa que podeu reanomenar de nou una pàgina al seu títol original si cometeu un error, i que no podeu sobreescriure una pàgina existent.\n\n'''Atenció!'''\nAçò pot ser un canvi dràstic i inesperat en una pàgina que sigui popular; \nassegureu-vos d'entendre les conseqüències que comporta abans de seguir endavant.",
        "movepagetext-noredirectfixer": "Amb el formulari següent podeu reanomenar una pàgina movent tot el seu historial al nom nou.\nEl títol anterior es convertirà en una pàgina de redirecció al nou títol. \nAssegureu-vos de verificar les redireccions [[Special:DoubleRedirects|dobles]] o [[Special:BrokenRedirects|trencades]].\nÉs responsabilitat vostra assegurar que els enllaços continuen apuntant cap a on se suposa que han d'anar. \n\nTingueu en compte que la pàgina '''no''' serà traslladada si ja existeix una pàgina amb el títol nou, tret que sigui una redirecció i no tingui més historial. \nAixò significa que podeu reanomenar de nou una pàgina al seu títol original si cometeu un error, i que no podeu sobreescriure una pàgina existent.\n \n'''Atenció!''' \nAixò pot ser un canvi dràstic i inesperat per una pàgina popular; \nassegureu-vos que sabeu el que feu abans de continuar.",
-       "movepagetalktext": "La pàgina de discussió associada també serà traslladada automàticament '''tret que''':\n* Ja existeix una pàgina de discussió no buida amb el nou nom, o\n* Desactiveu la opció de més avall.\n\nEn aquests casos, haureu de traslladar o fusionar la pàgina manualment si ho desitgeu.",
+       "movepagetalktext": "La pàgina de discussió associada també serà traslladada automàticament '''tret que''':\n* Ja existeixi una pàgina de discussió no buida amb el nou nom, o\n* Desactiveu l'opció de més avall.\n\nEn aquests casos, haureu de traslladar o fusionar la pàgina manualment si ho desitgeu.",
        "movearticle": "Reanomena la pàgina",
        "moveuserpage-warning": "'''Atenció:''' Esteu a punt de moure una pàgina d'usuari. Tingueu en compte que només la pàgina es desplaçarà i que el compte d'usuari ''no'' canviarà de nom.",
        "movecategorypage-warning": "<strong>Avís:</strong> Esteu a punt de moure una pàgina de categoria. Tingueu en compte que només es moure la pàgina i qualsevol de les pàgines a l'antiga categoria <em>no</em> es recategoritzarà automàticament en la nova.",
        "version-license": "Llicència del MediaWiki",
        "version-ext-license": "Llicència",
        "version-ext-colheader-name": "Extensió",
+       "version-skin-colheader-name": "Aparença",
        "version-ext-colheader-version": "Versió",
        "version-ext-colheader-license": "Llicència",
        "version-ext-colheader-description": "Descripció",
        "expand_templates_remove_nowiki": "Suprimeix l'etiqueta <nowiki> en el resultat",
        "expand_templates_generate_xml": "Mostra l'arbre XML",
        "expand_templates_generate_rawhtml": "Mostra l'HTML sense filtrar",
-       "expand_templates_preview": "Previsualitza"
+       "expand_templates_preview": "Previsualitza",
+       "pagelanguage": "Selector de l'idioma de les pàgines",
+       "pagelang-name": "Pàgina",
+       "pagelang-language": "Idioma",
+       "pagelang-use-default": "Utilitza l'idioma per defecte",
+       "pagelang-select-lang": "Selecciona un idioma",
+       "right-pagelang": "Canvia l'idioma de la pàgina",
+       "action-pagelang": "canvia l'idioma de la pàgina"
 }
index 91752be..2a13114 100644 (file)
@@ -7,7 +7,8 @@
                        "Mega programmer",
                        "Sasan700",
                        "Умар",
-                       "아라"
+                       "아라",
+                       "Kaganer"
                ]
        },
        "tog-underline": "КӀел сиз хьакха хьажорган:",
        "login-abort-generic": "Сестемин довзийта тарцаделира",
        "loginlanguagelabel": "Мотт: $1",
        "suspicious-userlogout": "Хьан сеанс чекхъяккха дина дехаш кхочуш цадина, иза нийса йоцу браузерца дар бахьнехь я прокси кэш еш хилар бахьнехь.",
+       "createacct-another-realname-tip": "Декъашхочун бакъ цӀе (яз ца йича мега).\nАхьа и язяхь, агӀона хийцам бича хьан цӀе гуш хира ю.",
        "pt-login": "ЧугӀо",
        "pt-login-button": "ЧугӀо",
        "pt-createaccount": "Кхолла декъашхочун дӀаяздар",
        "accmailtitle": "Пароль дlаяхьийтина.",
        "accmailtext": "Пароль декъашхочуьнан [[User talk:$1|$1]], йина ша шех хитта делла чу элпашах, дӀаяхийтина хьокху $2 адрес тӀе.\n\nЧуваьлла/яла чул тӀехьа , кху гӀирса чохь шуьга хийцалур ю ''[[Special:ChangePassword|шай пароль]]''.",
        "newarticle": "(Kерла)",
-       "newarticletext": "Хьо веана хьажоригци хӀокху агӀон тӀе, хӀара агӀо хӀинца йоцаш ю.\nНагахь иза кхолла лаахь, хӀотта де лахо гуш долу корехь йоза (мадарра хьажа. [$1 гӀон агӀон чу]).\nНагахь гӀалат даьлла цахууш кхечехь кхузе, атта тӀе тӀаӀа йе '''юха йоккхуриг''' хьай гӀирса тӀехь.",
+       "newarticletext": "ХӀара агӀо хӀинца йоцаш ю.\nНагахь иза кхолла лаахь, хӀотта де лахо гуш долу корехь йоза (мадарра хьажа. [$1 гӀон агӀон чу]).\nНагахь гӀалат даьлла цахууш кхечехь кхузе, атта тӀе тӀаӀа йе '''юха йоккхуриг''' хьай браузеран тӀехь.",
        "anontalkpagetext": "----''ХӀара дийцаре агӀо къайлаха декъашхочуьна ю, хӀинца дӀаяздар доцу, я лелош воцуш/йоцуш.\nЦундела иза вовзийта/йовзийта лелош ду терахьца IP-адрес.\nИза терахь долу меттиг хила мега кхечу декъашхойчух терра.\nНагахь хьо къайлах волу декъашхо валахь хьайна хаам кхаьчна аьлла хеташн, хьуна хьажийна доцуш, дехар до, кхолла хьай меттиг кху чохь[[Special:UserLogin/signup|дӀаяздар кхоллар]] я [[Special:UserLogin|системин чугӀо]],",
        "noarticletext": "Хlокх хан чохь кху агlонца йоза дац.\nШуьга далундерг [[Special:Search/{{PAGENAME}}|лахар ишта хьехош йолу цlе]] кхечу яззамашкахь,\n<span class=\"plainlinks\">[{{fullurl:{{#Special:Log}}|page={{FULLPAGENAMEE}}}} лахар кхечу тептаршкахь],\nйа '''[{{fullurl:{{FULLPAGENAME}}|action=edit}} кхолла ишта цlе йолу агlо]'''</span>.",
        "noarticletext-nopermission": "ХӀокх хан чохь кху агӀонца йоза дац.\nШуьга далундерг [[Special:Search/{{PAGENAME}}|лахар ишта хьехош йолу цӀе]] кхечу яззамашкахь,\nйа <span class=\"plainlinks\">[{{fullurl:{{#Special:Log}}|page={{FULLPAGENAMEE}}}} лаха оцуьнах терадерг кхечу тептаршкахь].</span>",
        "copyrightwarning": "Тергаме хьажа, массо яззаман чутухуш долу йозан хийцам хьажарехь бу, арахоьцушсанна оцу бакъойалар хьоляхь $2 (хьаж. $1).\nНагахь хьо лууш вацахь хьай йозанаш маьрша даржа а кхечаьрга хийцам байта, мадаха уьш кху чу.<br />\nИшта чlагlо йой ахьа, айхьа далош долучуьн хьо куьг да ву аьлла, йа хьаэцна цхьан\nхьостера, хийцам ба а дlаса даржада а чулацам болуш.<br />\n'''МАТОХИЙШ БАКЪО ЙОЦУ ГlИРСАШ КХУ ЧУ, КУЬГ ДЕ БАКЪО ЛАР ЙЕШ ЙОЛУ!'''",
        "readonlywarning": "'''ДӀАХЬЕДО. ГӀирса бух блоктоьхна оьшуш долучу хьаштан, цундера хӀинц хьоьга дӀа ца йазло хийцам.\nХила мега, ахьа Ӏалаш дан дезаш хьайн йоза, юха тӀаьхьо леладан иза йоза.'''\n\nКуьйгалхочо блоктоьхна гӀирса бух, цо битина кхетош хӀара хаам: $1",
        "protectedpagewarning": "'''Дlахьедар. Хlара агlо гlаролла дина ю хийцам цабайта, иза хийца йа нисйа а бакъо йолуш адаманкуьйгалла лелош болу декъашхой бе бац.'''\nЛахахьа гойту хаамаш тlаьхьара бина болу хийцамна тептар чура:",
+       "semiprotectedpagewarning": "'''ДӀахьедо.''' ХӀара агӀо гӀаролла йина ю; дӀабазбиначу декъашхошка бе цӀе хийцалуш яц.\nЛахахьа тептаро балийна тӀаьхьаралера дӀаязбина хаам:",
        "cascadeprotectedwarning": "<div id=\"cascadeprotectedwarning\" style=\"border:1px solid #ee0; padding:10px; background:#ffa; margin-bottom:1em\">[[file:Padlock.svg|left|25px|ДовгӀа|link=]]\nХӀара агӀо тада бакъо йолуш [[Project:Куьйгалхой|куьйгалхой]] бу, хӀунда аьлча и агӀо латийна кхечу агӀонашца хӀоттделлачу гӀаролле:</div>",
        "templatesused": "{{PLURAL:$1|1=Кеп, лелийна|Кепаш, лелош ю}} хӀокху агон башхонца:",
        "templatesusedpreview": "{{PLURAL:$1|1=Кеп, лелошдолу|Кепаш, лелойлу}} оцу хьалх хьожучу агӀонца:",
        "revdelete-reason-dropdown": "Даржина долу дӀаяккхаран баьхьанаш \n** Авторан бакъонаш талхор\n** Бита йиш йоцу шех лаьцна хаам\n** Бакъдоцург зуламан хаам",
        "revdelete-otherreason": "Кхин бахьна/тӀетохар:",
        "revdelete-reasonotherlist": "Кхин бахьна",
-       "revdelete-edit-reasonlist": "Бахьанин список нисяр",
+       "revdelete-edit-reasonlist": "Бахьанин могӀам нисбар",
        "revdelete-offender": "АгӀона версен автор:",
        "suppressionlog": "Хьулдаран тептар",
        "mergehistory": "Нисдарин истори цхьаьнатохар",
        "showingresultsheader": "{{PLURAL:$5|1=Хилам '''$1''' кху '''$3'''|Хиламаш '''$1 — $2''' кху '''$3'''}} оцун '''$4'''",
        "search-nonefound": "Дехаре терра цхьа хӀума ца карийна.",
        "powersearch-legend": "Шуьро лахар",
-       "powersearch-ns": "Цlераши анахь лахар:",
+       "powersearch-ns": "ЦӀерийн меттигашкахь лахар:",
        "powersearch-togglelabel": "Билгалдан:",
        "powersearch-toggleall": "Массо",
        "powersearch-togglenone": "ХӀумма цаоьшу",
+       "powersearch-remember": "Дагахь дита хаьржинарг кхечу хенахь лаха",
        "search-external": "Арахула лахар",
        "search-error": "Лохуш гӀалат даьлла: $1",
        "preferences": "ГӀирс нисбан",
        "http-read-error": "Ешаран гӀалат HTTP.",
        "http-timed-out": "Хьежаран хан чекхели HTTP-жоп дехаран.",
        "http-curl-error": "URLан гӀалат: $1",
+       "upload-curl-error6": "Билгал дина адресе хьажа цало.",
        "upload-curl-error28": "Чуйоккху хан чеккхелла",
        "license": "Бакъойалар:",
        "license-header": "Бакъойалар",
        "filedelete-otherreason": "Кхин бахьна:",
        "filedelete-reason-otherlist": "Кхин бахьна",
        "filedelete-reason-dropdown": "* Даржина долу дӀаяккхаран баьхьанаш \n** Авторан бакъонаш талхор\n** ЦхӀатера файлаш хилар",
-       "filedelete-edit-reasonlist": "Бахьанин список нисяр",
+       "filedelete-edit-reasonlist": "Бахьанин могӀам нисбар",
        "filedelete-maintenance-title": "Файл дӀаяккха цало",
        "mimesearch": "MIME хула лаха",
        "mimesearch-summary": "ХӀокху агӀоно йиш хуьлуьйту MIME-тайпан файлаш харжа. Яздеш долу формат: чулацаман тайп/бухара тайп, масала  <code>image/jpeg</code>.",
        "unusedtemplateswlh": "кхин хьажоргаш",
        "randompage": "Цахууш нисъелла агӀо",
        "randomincategory": "Категори чу цахууш нисъелла  агӀо",
+       "randomincategory-nopages": "[[:Category:$1]] категори чохь агӀонаш яц.",
        "randomincategory-selectcategory": "Категори чу цахууш нийса елла агӀона чу гӀо: $1 $2.",
        "randomincategory-selectcategory-submit": "Дехьа гӀо",
        "randomredirect": "Цахууш нисделла дIасахьажор",
+       "randomredirect-nopages": "«$1» цӀерийн меттиган чохь дӀасахьажораш яц.",
        "statistics": "Статистика",
        "statistics-header-pages": "АгӀонийн жамӀ",
        "statistics-header-edits": "Нисдаран жамӀ",
        "pageswithprop-text": "Кхузахь гойтуш ю агӀонаш цхьадолу къастамаш куьйга юху билгал даьхнарш.",
        "pageswithprop-prop": "Къастаман цӀе:",
        "pageswithprop-submit": "Лаха",
+       "pageswithprop-prophidden-long": "деха йозан хӀуман маьӀна хьулйина ($1)",
+       "pageswithprop-prophidden-binary": "шалха маьӀна долу хӀума хьулйина ($1)",
        "doubleredirects": "Шалха дIасахьажийнарш",
        "doubleredirectstext": "ХӀокху агӀонехь ю дӀасахьажорашан тӀе хьажийна йолу дӀасахьажораш.\n<del>ТӀехула сиз хаькхна </del>нисйина чарна.",
        "double-redirect-fixed-move": "АгӀон [[$1]] цӀе хийцина, хӀинца иза дӀахьажийна оцу [[$2]]",
        "email-legend": "{{grammar:genitive|{{SITENAME}}}} кхечу декъашхочунга кехат дахьийтар",
        "emailfrom": "Хьаьнгара",
        "emailto": "Хьаьнга:",
+       "emailsubject": "Къамел:",
        "emailmessage": "Хаам:",
        "emailsend": "ДӀадахьийта",
        "emailccme": "Соьга а кхосса хааман копи.",
        "deleteotherreason": "Кхин бахьна/тӀетохар:",
        "deletereasonotherlist": "Кхин бахьна",
        "deletereason-dropdown": "* Даржина долу дӀаяккхаран баьхьанаш \n** зулма  \n** авторан лаамца\n** авторан бакъонаш талхор",
-       "delete-edit-reasonlist": "Бахьанин список нисяр",
+       "delete-edit-reasonlist": "Бахьанин могӀам нисбар",
        "deleting-backlinks-warning": "'''ДӀахьедар:''' Ахьа дӀайоккхуш йолчун тӀе товжийна [[Special:WhatLinksHere/{{FULLPAGENAME}}|кхин агӀонаш]] ю.",
        "rollback": "Юхабаккха хийцам",
        "rollback_short": "Юхаяккхар",
        "modifiedarticleprotection": "агlонан гlаролли локхалла хийцина «[[$1]]»",
        "unprotectedarticle": "ГӀоролла дӀадаьстина «[[$1]]»",
        "movedarticleprotection": "«[[$2]]» агӀона тӀера гӀаролла «[[$1]]» агӀона тӀе даьккхина",
-       "protect-title": "Оцунна «$1» гӀоралла дар",
+       "protect-title": "ГӀоралла хӀоттор: «$1»",
+       "protect-title-notallowed": "ГӀораллин бараме хьажар «$1»",
        "prot_1movedto2": "«[[$1]]» цӀе хийцина → «[[$2]]»",
+       "protect-badnamespace-title": "ГӀораладан цалуш йолу цӀерийн меттиг",
+       "protect-badnamespace-text": "ХӀокху цӀерийн меттигехь йолу агӀонашна гӀараладан цало.",
+       "protect-norestrictiontypes-title": "ГӀараладан цалуш йолу агӀо",
        "protect-legend": "Бакъде гӀоралла дар",
        "protectcomment": "Бахьна:",
        "protectexpiry": "Чекхйолу:",
        "protect-otherreason": "Кхин бахьна/тӀетохар:",
        "protect-otherreason-op": "Кхин бахьна",
        "protect-dropdown": "* ГӀоралла дарна баьхьаш \n** сих-сиха зулам дар \n** дуккха спам хилар\n** нисдаршан тӀом \n** гӀараялл агӀо",
-       "protect-edit-reasonlist": "Бахьанин список нисяр",
+       "protect-edit-reasonlist": "Бахьанин могӀам нисбар",
        "protect-expiry-options": "1 сахьт:1 hour,1 де:1 day,1 кӀиран:1 week,2 кӀиран:2 weeks,1 бутт:1 month,3 бутт:3 months,6 бутт:6 months,1 шо:1 year,цlкъа:infinite",
        "restriction-type": "Бакъонаш:",
        "restriction-level": "ТӀекхочаран локхалла:",
        "contribsub2": "Къинхьегам $1 ($2)",
        "contributions-userdoesnotexist": "«$1» декъашхочун дӀаяздар дӀаяздина яц.",
        "nocontribs": "Дехарца хийцамаш цакарий.",
-       "uctop": " (тlаьхьара)",
+       "uctop": "(карара)",
        "month": "Баттаца (я хьалхе):",
        "year": "Шерачохь (я хьалхе):",
        "sp-contributions-newbies": "Гайта бекъ къинхьегам, керла дlабазбиначара бина болу",
        "istemplate": "юкъаялийнарш",
        "isimage": "Файлан хьажораг",
        "whatlinkshere-prev": "{{PLURAL:$1|1=хьалхайодарг|хьалхайодарш}} $1",
-       "whatlinkshere-next": "{{PLURAL:$1|тlаьхьайогlург|тlаьхьайогlурш|тlаьхьайогlурш}} $1",
+       "whatlinkshere-next": "{{PLURAL:$1|тӀаьхьайогӀург|тӀаьхьайогӀурш}} $1",
        "whatlinkshere-links": "← хьажоргаш",
        "whatlinkshere-hideredirs": "$1 дӀасахьажорш",
        "whatlinkshere-hidetrans": "$1 латораш",
        "ipaddressorusername": "IP-адрес я декъашхочун цӀе:",
        "ipbexpiry": "Хан чекхйолу:",
        "ipbreason": "Бахьна:",
-       "ipbreason-dropdown": "* Белхан некъ дӀакъовлар бахьанаш:\n** Харца хаам бар\n** АгӀонан чураниг дӀаяккхар\n** Спам-хьажоргаш арахьара сайташна\n** МаьӀна доцу текст тӀетохар\n** Декъашхой хьийзабар, кхерамаш тийсар\n** Масийтта лараман яздар зуламан лелаяр\n** Магийтина йоцу декъашхочун цӀе",
+       "ipbreason-dropdown": "* Белхан некъ дӀакъовлар бахьанаш:\n** Харца хаам бар\n** АгӀонан чураниг дӀаяккхар\n** Спам-хьажоргаш арахьара сайташна\n** МаьӀна доцу йоза тӀетохар\n** Декъашхой хьийзабар, кхерамаш тийсар\n** Масийтта лараман яздар зуламан лелаяр\n** Магийтина йоцу декъашхочун цӀе",
        "ipb-hardblock": "Шаш довзийтина болу декъашхошна бехкам бе хӀокху IP-адресца тадарш дан",
        "ipbcreateaccount": "Цамаго керла декъашхочун дӀаяздарш кхолла",
        "ipbemailban": "Цамагдо декъашхошка хааман кехаташ кхехьийта",
        "ipbsubmit": "Блоктоха хӀокху декъашхочун/адресна",
        "ipbother": "Кхин хан:",
        "ipboptions": "2 сахьат:2 hours,1 де:1 day,3 де:3 days,1 кlиран:1 week,2 кlиран:2 weeks,1 бутт:1 month,3 бутт:3 months,6 бутт:6 months,1 шо:1 year,цӀкъа:infinite",
+       "ipbhidename": "Нисдарийн а могӀаман а чура декъашхочун цӀе хьул йе",
        "ipbwatchuser": "ТӀетоха тергаме могӀам юкъа цуьнан долахь йолу агӀо а цуьнан дийцаре агӀо а",
        "ipb-disableusertalk": "Цамагдо шин дийцаре агӀо та я блоктоьхна хан чекхъяллалц",
        "ipb-change-block": "Юхаблоктоха декъашхочун оьцу хийцамашца",
        "blockipsuccesssub": "Блоктохар чакхдели",
        "blockipsuccesstext": "[[Special:Contributions/$1|«$1»]] {{GENDER:$1|блоктоьхна}}.<br />\nХьажа. [[Special:BlockList|блоктоьхна IP-адресийнн могӀам]].",
        "ipb-blockingself": "Хьо хьайна блоктоха гӀерта! Лаьий хьона и кхочушдан?",
-       "ipb-edit-dropdown": "Бахьанин список нисяр",
+       "ipb-edit-dropdown": "Бахьанин могӀам нисбар",
        "ipb-unblock-addr": "ДӀаякхаблок $1",
        "ipb-unblock": "дӀаякхаблок декъашхонтӀера я IP-адрес тӀера",
        "ipb-blocklist": "Блоктоьхнарш",
        "blocklogentry": "блоктоьхна [[$1]] цхьана ханна $2 $3",
        "reblock-logentry": "Хийцина  блоктоьхна хан [[$1]] $2 $3",
        "blocklogtext": "Блоктохаршна а блокдӀаякхаршна а тептар. Ша блоккхеташ долу IP-адресаш кхузахь гойтуш дац. Кхин. [[Special:BlockList|хӀийнца блоктоьха берш]].",
-       "unblocklogentry": "дӀаякхинаблок $1",
+       "unblocklogentry": "дӀаяькхинаблок $1",
        "block-log-flags-anononly": "Къайлаха берш",
        "block-log-flags-nocreate": "цамагдо керла дӏаяздарш кхоллар",
        "block-log-flags-noautoblock": "ша блоктухарг дӏаяйина",
        "block-log-flags-noemail": "цамаго кехаташ кхехӀита",
        "block-log-flags-nousertalk": "шин дийцаре агӀо тая лууш дац",
+       "block-log-flags-angry-autoblock": "латина шуьйра автоблоктохар",
        "block-log-flags-hiddenname": "декъашхочун цӀе къайлаяьккхина",
+       "range_block_disabled": "Куьйгалхошна диапазонашна блоктоха цамага до.",
        "ipb_expiry_invalid": "Дешдерг дан нийса йоцу хан.",
        "ipb_already_blocked": "«$1» хӀинцале блоктоьхна ю.",
        "ipb-needreblock": "ХӀокху $1 декъашхочун {{GENDER:$1|блоктоьхна ю}}. Лаьий хьуна блоктохаран параметраш хийца?",
        "ipb_cant_unblock": "ГӀалат: блоктохар цакарий $1. Иза хӀинцале дӀаяьккхина хила мега.",
        "ip_range_invalid": "IP-адресийн магийна йоцу диапазон.",
        "proxyblocker": "Проксин блоктохар",
+       "lockdb": "Хаамийн база еша бен цалуш йе",
+       "unlockdb": "Хаамийн базан чу дӀаяздарш дан аьтту меттахӀотта бе",
+       "lockbtn": "Хаамийн база еша бен цалуш йе",
+       "unlockbtn": "Хаамийн базан чу дӀаяздарш дан аьтту меттахӀотта бе",
+       "locknoconfirm": "Ахьа бакъдеш йолу меттиге билгало йилина яц.",
+       "lockdbsuccesssub": "Хаамийн базан блоктоьхна",
+       "unlockdbsuccesssub": "Хаамийн базан тӀера блокдӀаяьккхина",
        "move-page": "$1 — цӀе хийцар",
        "move-page-legend": "ЦӀe хийца яр",
        "movepagetext": "Бухахь йолу форманца агӀон цӀе хийцало. Цул совнах цуьна хийцаман тептар кхоьчу метте доккха. Хьалхалера цӀарахь хиръю керла кхоьллина агӀонан хьажораг.\n\nХьовсалаш [[Special:DoubleRedirects|шалха]] а [[Special:BrokenRedirects|йохна хьажоргаш]] юй техь аьлла.\n\nШу жоьпехь ду хьажоргаш нийса некъ гойтуш хиларан.\n\nТидам бе хьалхалера агӀон цӀе ‘’’хийцалур яц’’’ иштта цӀе йолу агӀо йолуш елахь. Юкъардаккхар: йолуш йолу агӀо кхоьчухьа хьажораг елахь, я еса елахь а, цуьна хийцаме истори яцахь а.\n\nИ бохург ду шун агӀонан цӀе юха а хьалха хилларгчунтӀе хийца йиш ю, амма йолуш йолу агӀо дӀаяккха йиш яц.\n\n'''ДӀАХЬЕДАР!'''\n\nЦӀе хийцар бахьнехь гӀаръяьлла агӀонашна дукха дагахь боцу хийцамаш хила тарло. Цундела цӀе хийцале шеш хила тарлучу тӀехьонашах кхета аьлла тешна хила.",
        "semiprotectedpagemovewarning": "'''ДӀахьедо.''' ХӀара агӀо гӀаролла йина ю; дӀабазбиначу декъашхошка бе цӀе хийцалуш яц.\nЛахахьа тептаро балийна тӀаьхьаралера дӀаязбина хаам:",
        "export": "АгӀонаш араяхар",
        "exporttext": "Шуьга далур ду кхечу меттера чудахарш, йоза а хийцаме тептарш билгалла йолу агӀонаш йа гулдина йолу агӀонаш хӀокх XML барамца, юха тӀяхьа чура [[Special:Import|хьаэцалурдолш]] кхечу вики-хьалхен, болх беш йолу хlокху MediaWiki гlирсаца.\n\nКхечу меттера яззамаш чуйаха, чуязйе цӀе тадечу метте, цӀхьа могӀан цӀе могӀаршкахь, юха харжа лаьи шуна Кхечу меттер чуйаха массо яззамашна истори хийцамбарш йа тӀяхьаралера яззамна башхо.\n\nШуьга кхи даландерг, лелаеш йолу меттиг къастаман машан хьажораг кхечу меттер чудаха тӀаьхьарлерачу башхон яззамаш. Масала оцу яззамна [[{{MediaWiki:Mainpage}}]] хӀара хира ю хьажораг [[{{#Special:Export}}/{{MediaWiki:Mainpage}}]].",
+       "exportall": "Массо агӀонаш экспорт ян",
        "exportcuronly": "Карара верси бен юкъа ма тоха, юзийна хьалхалерра истори йоцуш",
        "export-submit": "Экспорт ян",
        "export-addcattext": "ТӀетоха агӀонаш категори чура:",
        "filemissing": "Файл цакарий",
        "thumbnail_error": "Миниатюра кхолларна гӀалат: $1",
        "thumbnail_error_remote": "ГӀалатах хаам $1:\n$2",
+       "thumbnail_image-missing": "$1 файл йоцчух тера ду",
        "import": "АгӀонаш чуяхар",
+       "importinterwiki": "Викиюкъахь-импорт",
        "import-interwiki-source": "Вики-хьост/агlо:",
+       "import-interwiki-history": "ХӀокху агӀона ерриг хийцаман истори копи ян",
        "import-interwiki-templates": "Юкъайихка массо кепаш",
        "import-interwiki-submit": "Импорт ян",
+       "import-interwiki-namespace": "Коьрта цӀерийн меттиг:",
+       "import-interwiki-rootpage": "Коьрта агӀо (тӀехь дац):",
        "import-upload-filename": "Файлан цӀе:",
        "import-comment": "Билгалдаккхар:",
        "importstart": "АгӀонаш импорт яр…",
        "importnopages": "Импорт ян агӀонаш яц.",
        "imported-log-entries": "{{PLURAL:$1|Тептар чура импорт дина $1 дӀаяздар|Тептар чура импорт дина $1 дӀаяздарш}}.",
        "importfailed": "Импорт ян цаелира: $1",
+       "importcantopen": "Цатарло импорт еш йолу файл елла.",
+       "importbadinterwiki": "Нийса йоцу юкъаравики-хьажорг",
+       "importsuccess": "Импорт яр кхочушдина!",
        "importnosources": "Юкъаравики-импортан хьост хаьржина яцара, дуьхьала хийцамашан истори чуяккхар дӀадайина ду.",
+       "importnofile": "Импорт еш йолу файл чуяьккхина яц.",
        "import-noarticle": "Импорт ян агӀонаш яц!",
        "xml-error-string": "$1 $2 могӀан чохь, позицеш $3 (байт $4): $5",
        "import-upload": "Чуяха XML-хаамаш",
        "tooltip-ca-nstab-template": "Куцкепа агlо",
        "tooltip-ca-nstab-help": "ГӀоьна агӀо",
        "tooltip-ca-nstab-category": "Категорешан агӀо",
-       "tooltip-minoredit": "Къастам бé хlокху хийцамна кlеззиг боуш санна",
+       "tooltip-minoredit": "Къастам бé хӀокху хийцамна кӀеззиг болуш санна",
        "tooltip-save": "Хьан хийцамаш lалашбой",
        "tooltip-preview": "Дехар до, агlо lалаш йарал хьалха хьажа муха йу яз!",
        "tooltip-diff": "Гайта долуш долу йозанах бина болу хийцам.",
        "minutes-abbrev": "$1 мин",
        "hours-abbrev": "$1 сахь.",
        "seconds": "{{PLURAL:$1|$1 секунд}}",
-       "minutes": "{{PLURAL:$1|$1 минут}}",
+       "minutes": "$1 минут",
        "hours": "{{PLURAL:$1|сахьат}}",
        "days": "{{PLURAL:$1|$1 де}}",
        "weeks": "{{PLURAL:$1|$1 кӀира}}",
        "years": "$1 {{PLURAL:$1|шо}}",
        "ago": "$1 хьалха",
        "just-now": "хӀинца",
-       "hours-ago": "$1 {{PLURAL:$1|сахьт}} хьалха",
+       "hours-ago": "$1 {{PLURAL:$1|сахьт}}",
        "minutes-ago": "$1 {{PLURAL:$1|минут}} хьалха",
        "seconds-ago": "$1 {{PLURAL:$1|секунд}} хьалха",
        "monday-at": "оршотан дийнахь $1",
        "exif-whitebalance": "Къайн баланс",
        "exif-digitalzoomratio": "Терхьаш дукха хиларан коэффициент",
        "exif-scenecapturetype": "Сурт доккхуш йолу меттиган тайп",
+       "exif-contrast": "Къастам",
+       "exif-saturation": "Ӏаьбна",
+       "exif-sharpness": "Къаьсташ хилар",
+       "exif-devicesettingdescription": "Камеран хьолахь лаьцна",
+       "exif-subjectdistancerange": "Сурт тӀехь йолучун хӀуман юкъ",
        "exif-imageuniqueid": "Суьртан номер (ID)",
+       "exif-gpslatituderef": "Шораллин индекс",
        "exif-gpslatitude": "Шоралла",
+       "exif-gpslongituderef": "Дохаллин индекс",
        "exif-gpslongitude": "Дохалла",
+       "exif-gpsaltituderef": "Локхаллин индекс",
        "exif-gpsaltitude": "Локхалла",
+       "exif-gpstimestamp": "UTC-ца нийса хан",
        "exif-gpsdestlatitude": "Объектан дохалла",
        "exif-gpsdatestamp": "Терахь",
        "exif-jpegfilecomment": "JPEG-файлан билгалдаккхар",
        "exif-headline": "Корта",
        "exif-credit": "Кхоьхьург, хьа делла сурт",
        "exif-source": "Хьост",
+       "exif-urgency": "Керлачу хенахь",
+       "exif-fixtureidentifier": "МогӀан цӀе",
+       "exif-locationdest": "Сурт тӀера меттиг",
+       "exif-locationdestcode": "Сурт тӀера меттиган код",
+       "exif-contact": "Контактан хаам",
+       "exif-writer": "Йозан автор",
        "exif-languagecode": "Мотт",
        "exif-iimversion": "Верси IIM",
+       "exif-iimcategory": "Категори",
+       "exif-iimsupplementalcategory": "Кхин тӀе категореш",
+       "exif-datetimeexpires": "Ма лелае тӀехьа",
+       "exif-datetimereleased": "Араяларан терахь",
        "exif-originaltransmissionref": "ДӀадолалун меттиган код",
+       "exif-identifier": "ID",
+       "exif-lens": "ID",
+       "exif-serialnumber": "Камеран серин номер",
+       "exif-cameraownername": "Камера ерг",
        "exif-label": "Билгало",
        "exif-datetimemetadata": "ТӀехьара метахаамаш хийцина терахь",
+       "exif-nickname": "ЧӀагӀъелла йоцу суьртан цӀе",
+       "exif-rating": "Мах хадор (5 нах)",
+       "exif-rightscertificate": "Бакъонийн урхалладаран сертификат",
+       "exif-copyrighted": "Авторийн-бакъонийн статус:",
        "exif-copyrightowner": "Авторийн бакъонаш ерг",
        "exif-usageterms": "Лелоран хьал",
+       "exif-webstatement": "Интернет чохь долу авторийн бакъонийн хьал",
+       "exif-originaldocumentid": "ДӀадолалун документан ша тайпа ID",
+       "exif-licenseurl": "Авторийн лицензин URL",
+       "exif-morepermissionsurl": "Альтернативан лицензин хаам",
        "exif-pngfilecomment": "PNG-файлан билгалдаккхар",
+       "exif-disclaimer": "Бехк тӀе ца эцар",
+       "exif-contentwarning": "Чулацамах лаьцна дӀахьедар",
        "exif-giffilecomment": "GIF-файлан билгалдаккхар",
+       "exif-intellectualgenre": "ХӀуман тайп",
+       "exif-subjectnewscode": "Теман код",
+       "exif-scenecode": "IPTC сценан код",
+       "exif-event": "Сурт тӀе даьккхина хиларг",
+       "exif-organisationinimage": "Сурт тӀера организаци",
+       "exif-personinimage": "Сурт тӀера адам",
        "exif-compression-1": "ТIеIовдан яц",
        "exif-copyrighted-false": "Юкъараллин хьал",
        "exif-unknowndate": "Хууш доцу терахь",
        "exif-whitebalance-0": "Къайн автоматически баланс",
        "exif-whitebalance-1": "Куьйга хӀоттийна къайн баланс",
        "exif-scenecapturetype-0": "Стандартан",
+       "exif-scenecapturetype-3": "Буса даьккхина сурт",
        "exif-gaincontrol-0": "Яц",
+       "exif-gaincontrol-1": "Жим докха дар",
+       "exif-gaincontrol-2": "Дукху доккха дар",
+       "exif-gaincontrol-3": "Дуккху жим дар",
+       "exif-gaincontrol-4": "Дукху жим дар",
        "exif-contrast-0": "Лартӏахь",
+       "exif-contrast-1": "КӀеда айина",
+       "exif-contrast-2": "ЧӀогӀа айина",
        "exif-saturation-0": "Лартӏахь",
+       "exif-saturation-1": "КӀезиг Ӏаьбна",
+       "exif-saturation-2": "Докха Ӏаьбна",
        "exif-sharpness-0": "Лартӏахь",
+       "exif-sharpness-1": "КӀеда айина",
+       "exif-sharpness-2": "ЧӀогӀа айина",
+       "exif-subjectdistancerange-0": "Хууш дац",
+       "exif-subjectdistancerange-1": "Макро сурт даккхар",
+       "exif-subjectdistancerange-2": "Уллера сурт даккхар",
+       "exif-subjectdistancerange-3": "Генара сурт даккхар",
+       "exif-gpslatitude-n": "къилбседера шоралла",
+       "exif-gpslatitude-s": "къилбера шоралла",
+       "exif-gpslongitude-e": "малхбалера дохалла",
+       "exif-gpslongitude-w": "малхбузера шоралла",
        "exif-gpsaltitude-above-sealevel": "Хи хIоттарал локхалла $1 {{PLURAL:$1|метр}}",
        "exif-gpsaltitude-below-sealevel": "Хи хIоттарал локхаллин $1 {{PLURAL:$1|метр}} лахахь",
+       "exif-gpsstatus-a": "Дустар чекх даьлла дац",
+       "exif-gpsstatus-v": "Хаам дӀабала кичча ю",
+       "exif-gpsmeasuremode-2": "Дустар 2-х координаташ",
+       "exif-gpsmeasuremode-3": "Дустар 3-х координаташ",
        "exif-gpsspeed-k": "км/сахьтехь",
        "exif-gpsspeed-m": "миль/сахьтехь",
        "exif-gpsspeed-n": "шеддаш",
        "exif-dc-type": "Медиан тайп",
        "exif-rating-rejected": "ДӀайайина",
        "exif-isospeedratings-overflow": "65535 дукха",
+       "exif-iimcategory-ace": "Исбаьхьалла, культура а синкъерам а",
+       "exif-iimcategory-clj": "Зулам дар а Ӏедал а",
+       "exif-iimcategory-dis": "Ирча бохам а авари а",
+       "exif-iimcategory-fin": "Экономика а бизнес а",
+       "exif-iimcategory-edu": "Дешна хилар",
+       "exif-iimcategory-lab": "Къинхьегам",
+       "exif-iimcategory-rel": "Дин а тешар а",
+       "exif-iimcategory-sci": "Ӏилма а техника а",
+       "exif-iimcategory-soi": "Социалан хаттарш",
+       "exif-iimcategory-wea": "Хенан хӀоттам",
+       "exif-urgency-normal": "Диканиг ($1)",
+       "exif-urgency-low": "Лахара ($1)",
+       "exif-urgency-high": "Лакхара ($1)",
+       "exif-urgency-other": "Декъашхочо билгалйина приоритет ($1)",
        "watchlistall2": "массо",
        "namespacesall": "массо",
        "monthsall": "массо",
+       "confirmemail": "Электронан почтан адрес бакъдар",
+       "confirmemail_noemail": "Ахьа нийса электронан почтан адрес яздина дац [[Special:Preferences|гӀирсан чохь]].",
        "confirmrecreate": "Декъашхочо [[User:$1|$1]] ([[User talk:$1|дийцаре]]) хӀара агӀо дӀаяьккхина, ахьа иза тая йолийча, дӀаяккхарна бахьна:\n: ''$2''\nДехар до, тешал де, хьо иза агӀо меттахӀотто лууш ву/ю але.",
        "confirmrecreate-noreason": "Декъашхочо [[User:$1|$1]] ([[User talk:$1|дийцаре]]) хӀара агӀо дӀаяьккхина, ахьа иза тая йолийча. Дехар до, тешал де, хьо иза агӀо меттахӀотто лууш ву/ю але.",
        "recreate": "Юха кхолла",
        "signature": "[[{{ns:user}}:$1|$2]] ([[{{ns:user_talk}}:$1|дийцаре]])",
        "version": "Верси MediaWiki",
        "version-extensions": "ДӀахӀоттийна шордарш",
-       "version-skins": "Ð\9aечяран темаш",
+       "version-skins": "Ð\94Ó\80аÑ\85Ó\80оÑ\82Ñ\82ийна Ðºечяран темаш",
        "version-specialpages": "Белхан агӀонаш",
        "version-parserhooks": "Cинтаксисан къастор схьалоцурш",
        "version-variables": "Хийцаме",
        "version-other": "Кхин",
        "version-mediahandlers": "Медиа кеч ерраш",
+       "version-hooks": "Схьалуьцарш",
        "version-parser-extensiontags": "Cинтаксисан къасторан шораллин тегаш",
        "version-parser-function-hooks": "Cинтаксисан къасторан функци схьалоцурш",
+       "version-hook-name": "Схьалуьцачун цӀе",
+       "version-hook-subscribedby": "ДӀабазбелла тӀе",
        "version-version": "(Верси $1)",
-       "version-license": "Бакъо",
+       "version-no-ext-name": "[цӀе йоцуш]",
+       "version-license": "MediaWiki Лицензи",
        "version-ext-license": "Лицензи",
        "version-ext-colheader-name": "Шордарш",
+       "version-skin-colheader-name": "Кечяран тема",
        "version-ext-colheader-version": "Верси",
        "version-ext-colheader-license": "Лицензи",
        "version-ext-colheader-description": "Цуьнах лаьцна",
        "version-ext-colheader-credits": "Автораш",
+       "version-license-title": "Лицензи цу $1",
+       "version-credits-title": "Авторийн могӀам цу $1",
        "version-poweredby-credits": "ХӀара вики болх беш ю '''[https://www.mediawiki.org/ MediaWiki]''' движок тӀехь, copyright © 2001-$1 $2.",
        "version-poweredby-others": "кхин",
        "version-poweredby-translators": "гочдархой translatewiki.net",
        "version-license-info": "MediaWiki ю маьрша программин латораг, шу йиш ю фондас арахецна йолу GNU General Public License лицензица и яржо я хийца а.\n\nMediaWiki яржош ю и шуна пайдане хир яц те аьлла, амма  ЦХЬА ЮКЪАРАХИЛАР ДОЦУШ. Хь. кхин. лицензи мадарра GNU General Public License .\n\nШоьга кхача езаш яра [{{SERVER}}{{SCRIPTPATH}}/COPYING копи GNU General Public License] хӀокху программица, кхаьчна яцахь язъе Free Software Foundation, Inc., адрес тӀе: 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA я [//www.gnu.org/licenses/old-licenses/gpl-2.0.html еша и онлайнехь].",
        "version-software": "ДӀахӀоттийна программин латтор",
+       "version-software-product": "Сурсат",
        "version-software-version": "Верси",
        "version-entrypoints": "ЧугӀо адресин тӀадамаш",
        "version-entrypoints-header-entrypoint": "Яздаран тӀадам",
        "redirect-lookup": "Лаха:",
        "redirect-value": "МаьӀна:",
        "redirect-user": "Декъашхочун ID",
+       "redirect-page": "АгӀона ID",
        "redirect-revision": "АгӀона верси",
        "redirect-file": "Файлан цӀе",
+       "redirect-not-exists": "МаьӀна цакарий",
        "fileduplicatesearch": "Лаха цхьатера йолу файлаш",
        "fileduplicatesearch-summary": "Лаха цхьатера йолу файлаш хэш-кодаца.",
        "fileduplicatesearch-legend": "Цхьатера ерш лахар",
        "fileduplicatesearch-filename": "Файлан цӀе:",
        "fileduplicatesearch-submit": "Лаха",
        "fileduplicatesearch-info": "$1 × $2 пиксель<br />Файлан барам: $3<br />MIME-тайп: $4",
+       "fileduplicatesearch-result-1": "«$1» файлах тера хӀума яц.",
        "fileduplicatesearch-noresults": "ЦӀе «$1» йолуш файл цакарий.",
        "specialpages": "Леррина агlонаш",
        "specialpages-note": "* Гуттарлера белха агlонаш.\n* <strong class=\"mw-specialpagerestricted\">Кlеззиг таронаш йолу леррина агlонаш.</strong>",
        "htmlform-no": "ХӀахӀа",
        "htmlform-yes": "ХӀаъ",
        "htmlform-chosen-placeholder": "Харжа кеп",
+       "htmlform-cloner-create": "ТӀетоха кхин",
+       "htmlform-cloner-delete": "ДӀаяккха",
        "logentry-delete-delete": "$1 {{GENDER:$2|дӀаяьккхина}} агӀо $3",
        "logentry-delete-restore": "$1 {{GENDER:$2|меттахӀоттайина|меттахӀоттайина}} агӀо $3",
        "logentry-delete-event": "$1 {{GENDER:$2|хийцина}} гуш хилар {{PLURAL:$5|1=$5 дӀаяздаран|$5 дӀаяздаршан}} тептаран → $3: $4",
        "logentry-delete-revision": "$1 {{GENDER:$2|хийцина}} {{PLURAL:$5|1=$5 верси|$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|хийцина}} тептаран {{PLURAL:$5|1=$5 дӀаяздар|$5 дӀаяздарш}} гуш хилар $3: $4 чохь",
        "logentry-suppress-revision": "$1 къайлаха {{GENDER:$2|хийцина}} {{PLURAL:$5|1=$5 верси|$5 версеш}} $3: $4 чохь гуш хилар",
        "logentry-suppress-event-legacy": "$1 къайлаха {{GENDER:$2|хийцина}} $3 тептар чура дӀаяздарш гуш хилар",
        "logentry-move-move-noredirect": "$1 {{GENDER:$2|цӀе хийцина}} $3 → $4 дӀасахьажийнарг цаюьтуш",
        "logentry-move-move_redir": "$1 {{GENDER:$2|цӀе хийцина}} $3 → $4 дӀасахьажоран тӀохул",
        "logentry-move-move_redir-noredirect": "$1 {{GENDER:$2|цӀе хийцина}} $3 → $4 дӀасахьажоран тӀохул а дӀасахьажийнарг цаюьтуш а",
+       "logentry-patrol-patrol": "$1 {{GENDER:$2|хьаьжина}}  агӀона $3 $4 версега",
        "logentry-patrol-patrol-auto": "$1 автоматически {{GENDER:$2|хьаьжина}} $3 агӀона версега $4",
        "logentry-newusers-newusers": "{{GENDER:$2|ДӀавазвелла|ДӀаязелла}} керла декъашхо $1",
        "logentry-newusers-create": "{{GENDER:$2|ДӀавазвелла|ДӀаязелла}} керла декъашхо $1",
+       "logentry-newusers-create2": "$1 {{GENDER:$2|кхоьллина}} декъашхочун дӀаяздапр $3",
+       "logentry-newusers-byemail": "$1 {{GENDER:$2|кхоьллина}} декъашхочун дӀаяздар $3 пароль электронан почте яхьийтина",
        "logentry-newusers-autocreate": "Автоматически кхоьллина {{GENDER:$2|декъашхочун}} $1 дӀаяздар",
        "logentry-rights-rights": "$1 {{GENDER:$2|хийцина}} $3 бакъо $4 → $5",
        "logentry-rights-rights-legacy": "$1 {{GENDER:$2|хийцина}} хӏокхуна $3 бакъо",
+       "logentry-rights-autopromote": "$1 {{GENDER:$2|вара|яра}} автоматически {{GENDER:$2|сихьа ваьлла|сихьа яьлла}} $4 $5 чу",
        "rightsnone": "(яц)",
+       "feedback-bugornote": "Хьайн техникин халонах лаьцна яздан хӀума делахь, дехар до, [$1 хаам бе тхоьга].\nДацахь хьан йиш ю хӀокху атта кепаца «[$3 $2]» агӀонг къамел тӀетоха хьан декъашхочун цӀарца, кхин лелош йолу браузер билгал еш.",
+       "feedback-subject": "Къамел:",
+       "feedback-message": "Хаам:",
        "feedback-cancel": "Цаоьшу",
+       "feedback-submit": "Дахьийта хетарг",
+       "feedback-adding": "АгӀона хетарг тӀетохар...",
        "feedback-close": "Кийчча ю",
        "searchsuggest-search": "Лаха",
        "searchsuggest-containing": "чуьраниг…",
        "api-error-duplicate": "Иштта чулацам болу {{PLURAL:$1|1=[$2 кхин файл]|[$2 кхин файлаш]}} йолуш ю",
        "api-error-duplicate-popup-title": "{{PLURAL:$1|1=Файлан|Файлийн}} дубликат.",
        "api-error-empty-file": "Ахьа яхьийтина файл еса ю.",
+       "api-error-mustbeposted": "Чоьхьара гӀалат: дехаро хьехам схьабоьху HTTP POST.",
        "api-error-noimageinfo": "Кхиамца чуяьккхина, амма серверо файлахь лаьцна цхьаа хаам битина бац.",
        "api-error-nomodule": "Чоьхьара гӀалат: чуйокху модуль нисйина яц.",
        "api-error-ok-but-empty": "Чоьхьара гӀалат: серверара жоп дац.",
        "limitreport-cputime": "Процессоран хан лелор",
        "limitreport-cputime-value": "$1 {{PLURAL:$1|секунд}}",
        "limitreport-walltime": "Йодуш йолу хенахь лелор",
-       "limitreport-walltime-value": "$1 {{PLURAL:$1|секунд}}",
+       "limitreport-walltime-value": "$1 секунд",
        "limitreport-ppvisitednodes": "Препроцессор хьаьжна шадин дукхалла",
        "limitreport-ppgeneratednodes": "Препроцессорс сгенерировать бина шадин дукхалла",
        "limitreport-postexpandincludesize": "Схьаяьстина юккъерчаран барам",
        "expand_templates_remove_nowiki": "ДӀайоху тегаш <nowiki> хилча",
        "expand_templates_generate_xml": "Гойту дитта цу XML",
        "expand_templates_generate_rawhtml": "Гайта HTML",
-       "expand_templates_preview": "Хьалха муха ю хьажа"
+       "expand_templates_preview": "Хьалха муха ю хьажа",
+       "pagelanguage": "АгӀона мотт харжар",
+       "pagelang-name": "АгӀо",
+       "pagelang-language": "Мотт",
+       "pagelang-use-default": "Ӏад битарца мотт",
+       "pagelang-select-lang": "Харжа мотт",
+       "right-pagelang": "АгӀона мотт хийца",
+       "action-pagelang": "агӀона мотт хийца",
+       "log-name-pagelang": "Мотт хийцаран тептар",
+       "log-description-pagelang": "ХӀара агӀонашкахь мотт хийцаран тептар ду.",
+       "logentry-pagelang-pagelang": "$1 {{GENDER:$2|хийцина}} агӀона мотт $3 $4 → $5."
 }
index 85fa4f8..42f53e3 100644 (file)
        "action-userrights-interwiki": "دەستکاری مافەکانی بەکارهێنەریی بەکارهێنەران لە ویکی‌یەکانی دیکە‌دا",
        "action-siteadmin": "داخستن یا کردنەوەی بنکەدراو",
        "action-sendemail": "ناردنی ئیمەیلەکان",
+       "action-editmywatchlist": "دیتنی پێرستی چاودێریت",
        "action-viewmywatchlist": "دیتنی پێرستی چاودێریت",
        "nchanges": "$1 {{PLURAL:$1|گۆڕانکاری}}",
        "enhancedrc-history": "مێژوو",
        "pageswithprop-submit": "بڕۆ",
        "doubleredirects": "دووجار ڕەوانەکراوەکان",
        "doubleredirectstext": "ئەم پەڕە لیستی ئەو پەڕانەیە کە ڕەوانەکراون بۆ پەڕەیەکی ڕەوانەکراوی دیکە.\nهەر ڕیزێک، بەستەرەکانی ڕەوانەکردنەوەی یەکەم و دووەم و ھەروەھا ئامانجی ڕەوانەکراوی دووەمی تێدایە کە حاڵەتی ئاساییدا مەبەستی «ڕاستی»ی ڕەوانەکراوی یەکەمیش دەبێ بۆ ئەوێ بێت.\nئەوانەی <del>هێڵیان بەسەردا کێشراوە</del> چارەسەر کراون.",
-       "double-redirect-fixed-move": "[[$1]] گوێسترایەوە.\nئێستا ڕەوانکەرە بۆ [[$2]].",
+       "double-redirect-fixed-move": "[[$1]] گوازرایەوە.\nخۆگەڕ نوێ کرایەوە و ئێستا ڕەوانەکەرە بۆ [[$2]].",
        "double-redirect-fixer": "چارەسەرکەری ڕەوانکەر",
        "brokenredirects": "ڕەوانەکەرە شکاوەکان",
        "brokenredirectstext": "ئەم ڕەوانەکراوانە بەستەرن بۆ ئەو پەڕانە کە بوونیان نییە:",
        "restriction-create": "دروستکردن",
        "restriction-upload": "بارکردن",
        "restriction-level-sysop": "تەواو پارێزراو",
-       "restriction-level-autoconfirmed": "نیوەپارێزراو - ئاستی ١",
+       "restriction-level-autoconfirmed": "نیوەپارێزراو",
        "restriction-level-all": "هەر ئاستێک",
        "undelete": "پەڕە سڕاوەکان ببینە",
        "undeletepage": "پەڕە سڕاوەکان ببینە و بھێنەوە",
        "exif-countrycodedest": "کۆدی وڵاتی نیشان دراو",
        "exif-provinceorstatedest": "پارێزگا یان ویلایەتی نیشان دراو",
        "exif-citydest": "شاری نیشان دراو",
-       "exif-objectname": "سەردێری کورت",
+       "exif-objectname": "سەردێڕی کورت",
        "exif-specialinstructions": "ڕیسای کاری تایبەت",
-       "exif-headline": "سەردێر",
+       "exif-headline": "سەردێڕ",
        "exif-source": "سەرچاوە",
        "exif-contact": "زانیاری پەیوەندیکردن",
        "exif-writer": "نووسەر",
        "exif-flash-mode-3": "شێوازی خۆکار",
        "exif-flash-function-1": "فەنکشێنی فلاش نیە",
        "exif-flash-redeye-1": "شێوازی کەم‌کردنەوەی سوور-چاو",
-       "exif-focalplaneresolutionunit-2": "ئینج",
+       "exif-focalplaneresolutionunit-2": "ئینچ",
        "exif-sensingmethod-1": "دیاری نەکراو",
        "exif-sensingmethod-2": "یەک چیپی هەستەوەری بەشی ڕەنگ",
        "exif-sensingmethod-3": "دوو چیپی هەستەوەری بەشی ڕەنگ",
        "imgmultipagenext": "پەڕەی داهاتوو →",
        "imgmultigo": "بڕۆ!",
        "imgmultigoto": "بڕۆ بۆ پەڕەی $1",
+       "img-lang-go": "بڕۆ",
        "ascending_abbrev": "بەرەوە ژوور",
        "descending_abbrev": "بەرەوە ژێر",
        "table_pager_next": "پەڕەی داهاتوو",
        "duplicate-defaultsort": "'''ئاگاداری''' کلیلی پۆلێنکردنی \"$2'' چووەتە شوێنی کلیلی پۆلێنکردنی  \"$1\"",
        "version": "وەشان",
        "version-extensions": "پێوەکراوە دامەزراوەکان",
+       "version-skins": "پێستەکان",
        "version-specialpages": "پەڕە تایبەتەکان",
        "version-parserhooks": "قولاپە لێککەرەکان",
        "version-variables": "گۆڕاوەکان",
-       "version-skins": "پێستەکان",
        "version-other": "Other",
        "version-mediahandlers": "Media handlers",
        "version-hooks": "قولاپەکان",
        "version-hook-subscribedby": "بەشداربوو لە لایەن",
        "version-version": "(وەشانی $1)",
        "version-license": "مۆڵەتنامە",
+       "version-ext-colheader-version": "وەشان",
+       "version-ext-colheader-description": "وەسف",
        "version-poweredby-others": "دیکە",
        "version-software": "نەرمەکاڵای دامەزراو",
        "version-software-product": "بەرهەم",
        "version-software-version": "وەشان",
        "version-entrypoints-header-url": "ناونیشانی ئینتەرنێتی",
+       "redirect-submit": "بڕۆ",
        "fileduplicatesearch": "گەڕان بۆ پەڕگە دووپات کراوەکان",
        "fileduplicatesearch-summary": "گەڕان بۆ پەڕگە دووبارەکراوەکان لەسەر بنەمای نرخی hash.",
        "fileduplicatesearch-legend": "گەڕان بۆ دووبارەکردنێک",
index f87c2e2..1478fda 100644 (file)
        "license-nopreview": "(Náhled není dostupný)",
        "upload_source_url": " (platné, veřejně přístupné URL)",
        "upload_source_file": " (soubor ve vašem počítači)",
+       "listfiles-delete": "smazat",
        "listfiles-summary": "Tato speciální stránka zobrazuje všechny načtené soubory.",
        "listfiles_search_for": "Hledat soubor podle názvu:",
        "imgfile": "soubor",
        "expand_templates_remove_nowiki": "Potlačit ve výsledku značky <nowiki>",
        "expand_templates_generate_xml": "Zobrazit syntaktický strom v XML",
        "expand_templates_generate_rawhtml": "Zobrazit surové HTML",
-       "expand_templates_preview": "Náhled"
+       "expand_templates_preview": "Náhled",
+       "pagelanguage": "Volba jazyka stránky",
+       "pagelang-name": "Stránka",
+       "pagelang-language": "Jazyk",
+       "pagelang-use-default": "Použít implicitní jazyk",
+       "pagelang-select-lang": "Vybrat jazyk",
+       "right-pagelang": "Změnit jazyk stránky",
+       "action-pagelang": "měnit jazyk stránky",
+       "log-name-pagelang": "Kniha změn jazyků",
+       "log-description-pagelang": "Toto je protokol změn jazyků stránek.",
+       "logentry-pagelang-pagelang": "$1 {{GENDER:$2|změnil|změnila}} jazyk stránky $3 z $4 na $5."
 }
index 4a891b2..e66b267 100644 (file)
        "createacct-another-realname-tip": "Gallwch ddewis roi eich enw go iawn.\nOs y gwnewch, fe gaiff yr enw go iawn ei defnyddio wrth dadogi'ch gwaith.",
        "pt-login": "Mewngofnodi",
        "pt-login-button": "Mewngofnoder",
-       "pt-createaccount": "Creu cyfri",
+       "pt-createaccount": "Crëwch gyfrif",
        "pt-userlogout": "Allgofnodi",
        "php-mail-error-unknown": "Gwall anhysbys yng ngweithrediad post() PHP",
        "user-mail-no-addy": "Wedi ceisio anfon e-bost heb gyfeiriad e-bost",
        "duplicate-defaultsort": "Rhybudd: Mae'r allwedd trefnu diofyn \"$2\" yn gwrthwneud yr allwedd trefnu diofyn blaenorol \"$1\".",
        "version": "Fersiwn",
        "version-extensions": "Estyniadau gosodedig",
+       "version-skins": "Gweddau",
        "version-specialpages": "Tudalennau arbennig",
        "version-parserhooks": "Bachau dosrannydd",
        "version-variables": "Newidynnau",
        "version-antispam": "Atal sbam",
-       "version-skins": "Gweddau",
        "version-other": "Arall",
        "version-mediahandlers": "Trinyddion cyfryngau",
        "version-hooks": "Bachau",
index 028f1c7..797b8b6 100644 (file)
        "right-move": "Flytte sider",
        "right-move-subpages": "Flytte sider og undersider",
        "right-move-rootuserpages": "Flytte hovedbrugersider",
+       "right-move-categorypages": "Flytte kategorisider",
        "right-movefile": "Flytte filer",
        "right-suppressredirect": "Flytte sider uden at oprette en omdirigering fra det gamle navn",
        "right-upload": "Lægge filer op",
        "action-move": "flytte denne side",
        "action-move-subpages": "flytte denne side og dens undersider",
        "action-move-rootuserpages": "flytte hovedbrugersider",
+       "action-move-categorypages": "flytte kategorisider",
        "action-movefile": "flytte denne fil",
        "action-upload": "lægge denne fil op",
        "action-reupload": "overskrive den nuværende fil",
        "duplicate-defaultsort": "Advarsel: Standardsorteringsnøglen \"$2\" tilsidesætter den tidligere sorteringsnøgle \"$1\".",
        "version": "Information om MediaWiki",
        "version-extensions": "Installerede udvidelser",
+       "version-skins": "Udseender",
        "version-specialpages": "Specialsider",
        "version-parserhooks": "Parserfunktioner",
        "version-variables": "Variabler",
        "version-antispam": "Spamforebyggelse",
-       "version-skins": "Udseender",
        "version-other": "Andet",
        "version-mediahandlers": "Specialhåndtering af mediefiler",
        "version-hooks": "Funktionstilføjelser",
index 9083d44..b2bf75f 100644 (file)
        "license-nopreview": "(es ist keine Vorschau verfügbar)",
        "upload_source_url": " (gültige, öffentlich zugängliche URL)",
        "upload_source_file": " (eine Datei auf deinem Computer)",
+       "listfiles-delete": "löschen",
        "listfiles-summary": "Diese Spezialseite listet alle hochgeladenen Dateien auf.",
        "listfiles_search_for": "Suche nach Datei:",
        "imgfile": "Datei",
        "expand_templates_remove_nowiki": "<nowiki>-Tags in der Ausgabe unterdrücken",
        "expand_templates_generate_xml": "XML-Parser-Baum zeigen",
        "expand_templates_generate_rawhtml": "Rohes HTML anzeigen",
-       "expand_templates_preview": "Vorschau"
+       "expand_templates_preview": "Vorschau",
+       "pagelanguage": "Seitensprachenauswahl",
+       "pagelang-name": "Seite",
+       "pagelang-language": "Sprache",
+       "pagelang-use-default": "Standardsprache verwenden",
+       "pagelang-select-lang": "Sprache auswählen",
+       "right-pagelang": "Seitensprache ändern",
+       "action-pagelang": "die Seitensprache zu ändern",
+       "log-name-pagelang": "Sprachenänderungs-Logbuch",
+       "log-description-pagelang": "Dies ist ein Logbuch mit Änderungen an Seitensprachen.",
+       "logentry-pagelang-pagelang": "$1 {{GENDER:$2|änderte}} die Seitensprache für $3 von $4 nach $5."
 }
index 2313c1f..4250606 100644 (file)
        "personaltools": "Hacetê şexsiy",
        "postcomment": "Qısımo newe",
        "articlepage": "Pela zerreki bıvêne",
-       "talk": "Vatenkerdış",
+       "talk": "Werênayış",
        "views": "Asayışi",
        "toolbox": "Haceti",
        "userpage": "Pela karberi bıvêne",
        "created": "viraziya",
        "changed": "vurneya",
        "deletepage": "Pele bestere",
-       "confirm": "Testiq ke",
+       "confirm": "Tesdiq ke",
        "excontent": "Zerreko verén: '$1'",
        "excontentauthor": "Zerrey cı: '$1' no/na ('[[Special:Contributions/$2|$2]]'  teyna iştıraq kerdo)",
        "exbeforeblank": "behsê verê esteriyayişi: '$1'",
        "duplicate-defaultsort": "'''Tembe:''' Hesıbyaye sırmey ratnayış de \"$2\" sırmey ratnayış de \"$1\"i nêhesıbneno.",
        "version": "Versiyon",
        "version-extensions": "Ekstensiyonî ke ronaye",
+       "version-skins": "Cıldi",
        "version-specialpages": "Pelanê xasiyan",
        "version-parserhooks": "Çengelê Parserî",
        "version-variables": "Vurnayeyî",
        "version-antispam": "Spam vındarnayış",
-       "version-skins": "Cıldi",
        "version-api": "API",
        "version-other": "Bin",
        "version-mediahandlers": "Kulbê medyayî",
index 0c7869c..c7bd536 100644 (file)
@@ -37,7 +37,8 @@
                        "לערי ריינהארט",
                        "Kolega2357",
                        "아라",
-                       "Calak"
+                       "Calak",
+                       "Auslaender"
                ]
        },
        "tog-underline": "Υπογράμμιση συνδέσμων:",
        "recentchanges-label-unpatrolled": "Αυτή η επεξεργασία δεν έχει ελεγχθεί ακόμα",
        "recentchanges-label-plusminus": "Μεταβολή του μεγέθους της σελίδας σε bytes",
        "recentchanges-legend-heading": "'''Υπόμνημα:'''",
-       "recentchanges-legend-newpage": "{{int:recentchanges-label-newpage}} (δείÏ\84ε [[Special:NewPages|Î\9dέεÏ\82 Ï\83ελίδεÏ\82]])",
+       "recentchanges-legend-newpage": "{{int:recentchanges-label-newpage}} (δείÏ\84ε [[Special:NewPages|καÏ\84άλογοÏ\82 Î½Î­Ï\89ν Ï\83ελίδÏ\89ν]])",
        "rcnotefrom": "Παρακάτω είναι οι αλλαγές από τις <strong>$2</strong>  (εμφανίζονται μέχρι <strong>$1</strong> ).",
        "rclistfrom": "Εμφάνιση νέων αλλαγών αρχίζοντας από $3 $2",
        "rcshowhideminor": "$1 μικροεπεξεργασιών",
        "watchlistedit-raw-added": "{{PLURAL:$1|1 σελίδα|$1 σελίδες}} προστέθηκαν:",
        "watchlistedit-raw-removed": "{{PLURAL:$1|1 σελίδα|$1 σελίδες}} αφαιρέθηκαν:",
        "watchlistedit-clear-titles": "Τίτλοι:",
-       "watchlistedit-clear-submit": "Καταργήστε τη λίστα παρακολούθησης (αυτό είναι μόνιμο!)",
-       "watchlistedit-too-many": "Î¥Ï\80άÏ\81Ï\87οÏ\85ν Ï\80άÏ\81α Ï\80ολλέÏ\82 Ï\83ελίδεÏ\82 Î³Î¹Î± Î½Î± ÎµÎ¼Ï\86ανίÏ\83εÏ\84ε εδώ.",
+       "watchlistedit-clear-submit": "Καθαρίστε τη λίστα παρακολούθησης (αυτό είναι μόνιμο!)",
+       "watchlistedit-too-many": "Î¥Ï\80άÏ\81Ï\87οÏ\85ν Ï\85Ï\80εÏ\81βολικά Ï\80ολλέÏ\82 Ï\83ελίδεÏ\82 ÎºÎ±Î¹ Î´ÎµÎ½ Î¼Ï\80οÏ\81οÏ\8dν Î½Î± ÎµÎ¼Ï\86ανιÏ\83Ï\84οÏ\8dν εδώ.",
        "watchlisttools-view": "Προβολή σχετικών αλλαγών",
        "watchlisttools-edit": "Προβολή και επεξεργασία λίστας παρακολούθησης",
        "watchlisttools-raw": "Επεξεργασία πρωτογενούς λίστας παρακολούθησης",
index 1be50b4..962f6d4 100644 (file)
        "talkpagelinktext": "Talk",
        "specialpage": "Special page",
        "personaltools": "Personal tools",
-       "postcomment": "New section",
        "addsection": "+",
        "articlepage": "View content page",
        "talk": "Discussion",
        "license-nopreview": "(Preview not available)",
        "upload_source_url": "(a valid, publicly accessible URL)",
        "upload_source_file": "(a file on your computer)",
+       "listfiles-delete": "delete",
        "listfiles-summary": "This special page shows all uploaded files.",
        "listfiles_search_for": "Search for media name:",
        "imgfile": "file",
        "wantedfiles": "Wanted files",
        "wantedfiles-summary": "",
        "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-cat-noforeign": "The following files are used but do not exist. 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>.",
+       "wantedfiletext-nocat-noforeign": "The following files are used but do not exist.",
        "wantedtemplates": "Wanted templates",
        "wantedtemplates-summary": "",
        "mostlinked": "Most linked-to pages",
index c9d9b54..45dc6b7 100644 (file)
        "edit-gone-missing": "Ne eblis ĝisdatigi la paĝon.\nVerŝajne ĝi estis forigita.",
        "edit-conflict": "Redakto-konflikto.",
        "edit-no-change": "Via redakto estis ignorita, ĉar neniu ŝanĝo estis farita al la teksto.",
+       "postedit-confirmation-created": "La paĝo estis kreita.",
+       "postedit-confirmation-restored": "La paĝo estis restarigita.",
        "postedit-confirmation-saved": "Via redakto estis konservita.",
        "edit-already-exists": "Ne eblis krei novan paĝon.\nĜi jam ekzistas.",
        "defaultmessagetext": "Defaŭlta teksto",
        "currentrev": "Aktuala versio",
        "currentrev-asof": "Nuna versio ekde $1",
        "revisionasof": "Kiel registrite je $1",
-       "revision-info": "Redakto de $1 de $2",
+       "revision-info": "Revizio de $1 fare de {{GENDER:$6|$2}}$7",
        "previousrevision": "← Antaŭa versio",
        "nextrevision": "Sekva versio →",
        "currentrevisionlink": "Rigardi nunan version",
        "largefileserver": "Ĉi tiu dosiero estas pli granda ol permesas la servilaj preferoj.",
        "emptyfile": "La dosiero kiun vi alŝutis ŝajnas malplena. Tio povas esti kaŭzita sde tajperaro en la titolo. Bonvolu kontroli ĉu vi vere volas alŝuti tiun dosieron.",
        "windows-nonascii-filename": "Ĉi tiu vikio ne subtenas dosiernomoj kun specialaj signoj.",
-       "fileexists": "Dosiero kun tia ĉi nomo jam ekzistas.\nBonvolu kontroli <strong>[[:$1]]</strong> krom se vi certas ke vi konscie volas ŝanĝi ĝuste tiun.\n[[$1|thumb]]",
+       "fileexists": "Dosiero kun tiu ĉi nomo jam ekzistas.\nBonvolu kontroli <strong>[[:$1]]</strong> krom se vi certas ke {{GENDER:|vi}} konscie volas ŝanĝi ĝuste tiun.\n[[$1|thumb]]",
        "filepageexists": "La priskriba paĝo por ĉi tiu dosiero jam estis kreita ĉe <strong>[[:$1]]</strong>, sed neniu dosiero kun ĉi tiu nomo nune ekzistas.\nLa resumo kiun vi entajpos ne aperos en la priskribo-paĝo.\nPor aperigi vian resumon, vi devos permane redakti ĝin.\n[[$1|thumb]]",
-       "fileexists-extension": "Dosiero kun simila nomo ekzistas: [[$2|thumb]]\n* Nomo de la alŝuta dosiero: <strong>[[:$1]]</strong>\n* Nomo de la ekzistanta dosiero: <strong>[[:$2]]</strong>\nBonvolu elekti malsaman nomon.",
+       "fileexists-extension": "Dosiero kun simila nomo ekzistas: [[$2|thumb]]\n* Nomo de la alŝutanta dosiero: <strong>[[:$1]]</strong>\n* Nomo de la ekzistanta dosiero: <strong>[[:$2]]</strong>\nBonvolu elekti malsaman nomon.",
        "fileexists-thumbnail-yes": "Ĉi tiu dosiero ŝajnas kiel bildo de malkreskigita grandeco ''(bildeto)''. [[$1|thumb]]\nBonvolu kontroli la dosieron <strong>[[:$1]]</strong>.\nSe la kontrolita dosiero estas la sama bildo kiel la originala grandeco, ĝi ne nepras alŝuti plian bideton.",
        "file-thumbnail-no": "La dosiernomo komencas kun <strong>$1</strong>.\nĜi ŝajnas kiel bildo de malgrandigita grandeco ''(thumbnail)''.\nSe vi havas ĉi tiun bildon en plena distingivo, alŝutu ĉi tiun, alikaze bonvolu ŝanĝi la dosieran nomon.",
        "fileexists-forbidden": "Dosiero kun ĉi tiu nomo jam ekzistas kaj ne povas anstataŭigi ĝin.\nSe vi ankoraŭ volas alŝuti vian dosieron, bonvolu reprovi kun nova nomo.\n[[File:$1|thumb|center|$1]]",
        "filedelete-maintenance": "Forigado kaj restarigado de dosieroj provizore malŝaltis dum funkciteno.",
        "filedelete-maintenance-title": "Ne povas forigi dosieron",
        "mimesearch": "MIME-serĉilo",
-       "mimesearch-summary": "Ĉi tiu paĝo ebligas la filtradon de dosieroj por ties MIME-tipo. Enigu: enhavo-tipo/subtipo, ekz. <code>image/jpeg</code>.",
+       "mimesearch-summary": "Ĉi tiu paĝo ebligas la filtradon de dosieroj por ties MIME-tipo. \nEnigu: enhavo-tipo/subtipo, aŭ enhavo-tipo/* - ekz. <code>image/jpeg</code>.",
        "mimetype": "MIME-tipo:",
        "download": "elŝuti",
        "unwatchedpages": "Neatentataj paĝoj",
        "doubleredirects": "Duoblaj alidirektadoj",
        "doubleredirectstext": "Ĉi tiu paĝo montras paĝojn kiuj alidirektas al aliaj alidirektiloj.\nĈiu vico enhavas ligilojn ĉe la unua kaj dua alidirektadoj, kaj la unua linio de la dua alidirektado, kiu ĝenerale montras la \"veran\" celpaĝon, kiu celu la unuan alidirektadon.\n<del>Forstrekitaj</del> listeroj estis riparitaj.",
        "double-redirect-fixed-move": "[[$1]] estis alinomigita. Ĝi estis ĝisdatigita kaj nun ĝi alidirektas al [[$2]].",
-       "double-redirect-fixed-maintenance": "Riparas duoblan alidirektilon de [[$1]] al [[$2]].",
+       "double-redirect-fixed-maintenance": "Aŭtomate riparas duoblan alidirektilon de [[$1]] al [[$2]] dum prizorga tasko.",
        "double-redirect-fixer": "Alidirektila riparilo",
        "brokenredirects": "Rompitaj alidirektadoj",
        "brokenredirectstext": "La jenaj alidirektadoj ligas al neekzistantaj paĝoj:",
        "listgrouprights-namespaceprotection-header": "Nomspacaj restriktoj",
        "listgrouprights-namespaceprotection-namespace": "Nomspaco",
        "listgrouprights-namespaceprotection-restrictedto": "Rajtoj, kiuj permesas al uzanto redakti",
+       "trackingcategories-name": "Nomo de mesaĝo",
        "trackingcategories-nodesc": "Neniu priskribo estas disponebla.",
        "trackingcategories-disabled": "Kategorio estas malaktivigita",
        "mailnologin": "Neniu alsendota adreso",
        "duplicate-defaultsort": "'''Averto:''' Defaŭlta ordiga ŝlosilo \"$2\" anstataŭigas pli fruan defaŭltan ordigan ŝlosilon \"$1\".",
        "version": "Versio",
        "version-extensions": "Instalitaj kromprogramoj",
-       "version-skins": "Etosoj",
+       "version-skins": "Instalitaj etosoj",
        "version-specialpages": "Specialaj paĝoj",
        "version-parserhooks": "Sintaksaj hokoj",
        "version-variables": "Variabloj",
index 295a54f..fa41f55 100644 (file)
                        "Mcervera",
                        "Wifidel",
                        "Macofe",
-                       "Koavf"
+                       "Koavf",
+                       "Themasterriot"
                ]
        },
        "tog-underline": "Subrayar los enlaces:",
        "tog-prefershttps": "Utilizar una conexión segura siempre que haya iniciado una sesión",
        "underline-always": "Siempre",
        "underline-never": "Nunca",
-       "underline-default": "Aspecto (skin) o valor predeterminado del navegador",
+       "underline-default": "Tema o valor predeterminado del navegador",
        "editfont-style": "Estilo de tipografía del área de edición:",
        "editfont-default": "Predeterminado del navegador",
        "editfont-monospace": "Tipo de letra monoespaciado",
        "right-editprotected": "Editar páginas protegidas como «{{int:protect-level-sysop}}»",
        "right-editsemiprotected": "Editar páginas protegidas como «{{int:protect-level-autoconfirmed}}»",
        "right-editinterface": "Editar la interfaz de usuario",
-       "right-editusercssjs": "Editar las páginas de CSS y JS de otros usuarios",
+       "right-editusercssjs": "Editar las páginas de CSS y JavaScript de otros usuarios",
        "right-editusercss": "Editar las páginas de CSS de otros usuarios",
-       "right-edituserjs": "Editar las páginas de JS de otros usuarios",
+       "right-edituserjs": "Editar las páginas de JavaScript de otros usuarios",
        "right-editmyusercss": "Editar tus archivos de usuario CSS",
        "right-editmyuserjs": "Editar tus propios archivos JavaScript de usuario",
        "right-viewmywatchlist": "Ver tu lista de seguimiento",
        "recentchanges-summary": "Sigue los cambios más recientes de la wiki en esta página.",
        "recentchanges-noresult": "No hubo cambios durante el período seleccionado que respondan a esos criterios.",
        "recentchanges-feed-description": "Realiza un seguimiento de los cambios más recientes en el wiki en este canal.",
-       "recentchanges-label-newpage": "Esta edición inició una página",
+       "recentchanges-label-newpage": "Esta edición creó una página",
        "recentchanges-label-minor": "Esta es una edición menor",
        "recentchanges-label-bot": "Esta edición fue realizada por un robot",
        "recentchanges-label-unpatrolled": "Esta edición todavía no se ha patrullado",
        "nolicense": "Ninguna seleccionada",
        "license-nopreview": "(Previsualización no disponible)",
        "upload_source_url": " (una URL válida y accesible públicamente)",
-       "upload_source_file": " (un archivo en tu disco)",
+       "upload_source_file": "(un archivo en tu computadora)",
        "listfiles-summary": "Esta página especial muestra todos los archivos subidos.\nCuando el usuario la filtra, solo se muestran los archivos cargados por el usuario en su versión más reciente.",
        "listfiles_search_for": "Buscar por nombre de imagen:",
        "imgfile": "archivo",
        "patrol-log-header": "Este es un registro de revisiones patrulladas.",
        "log-show-hide-patrol": "$1 registro de patrullaje",
        "deletedrevision": "Borrada revisión antigua $1",
-       "filedeleteerror-short": "Se produjo un error al borrar el archivo: $1",
+       "filedeleteerror-short": "Error al borrar el archivo: $1",
        "filedeleteerror-long": "Se han producido errores mientras se borraba el archivo:\n\n$1",
        "filedelete-missing": "No se pudo borrar el archivo \"$1\" porque no existe.",
        "filedelete-old-unregistered": "La revisión de archivo \"$1\" no está en la base de datos.",
        "watchlistedit-clear-removed": "{{PLURAL:$1|un título fue removido|Los títulos $1 fueron removidos}}:",
        "watchlistedit-too-many": "Hay demasiadas páginas para mostrar aquí.",
        "watchlisttools-clear": "Limpiar la lista de seguimiento",
-       "watchlisttools-view": "Ver cambios",
+       "watchlisttools-view": "Ver cambios relevantes",
        "watchlisttools-edit": "Ver y editar tu lista de seguimiento",
        "watchlisttools-raw": "Editar lista de seguimiento en crudo",
        "signature": "[[{{ns:user}}:$1|$2]] ([[{{ns:user_talk}}:$1|discusión]])",
        "duplicate-defaultsort": "'''Atención:''' La clave de ordenamiento predeterminada «$2» anula la clave de ordenamiento anterior «$1».",
        "version": "Versión",
        "version-extensions": "Extensiones instaladas",
-       "version-skins": "Apariencias",
+       "version-skins": "Temas instalados",
        "version-specialpages": "Páginas especiales",
        "version-parserhooks": "Extensiones del analizador sintáctico",
        "version-variables": "Variables",
        "version-license": "Licencia de MediaWiki",
        "version-ext-license": "Licencia",
        "version-ext-colheader-name": "Extensión",
+       "version-skin-colheader-name": "Tema",
        "version-ext-colheader-version": "Versión",
        "version-ext-colheader-license": "Licencia",
        "version-ext-colheader-description": "Descripción",
        "api-error-filetype-banned": "Este tipo de archivo está prohibido.",
        "api-error-filetype-banned-type": "$1 {{PLURAL:$4|no es un tipo de archivo permitido|no son tipos de archivos permitidos}}. {{PLURAL:$3|El tipo de archivo permitido es|Los tipos de archivos permitidos son}} $2.",
        "api-error-filetype-missing": "El archivo no tiene extensión de archivo.",
-       "api-error-hookaborted": "La modificación que intentaste hacer fue cancelada por un gancho de extensión.",
+       "api-error-hookaborted": "La modificación que intentaste hacer fue cancelada por una extensión.",
        "api-error-http": "Error interno: No se puede conectar al servidor.",
        "api-error-illegal-filename": "El nombre de archivo no está permitido.",
        "api-error-internal-error": "Error interno: Algo salió mal al procesar tu subida en el wiki.",
        "expand_templates_remove_nowiki": "Suprimir <nowiki> etiquetas en resultado",
        "expand_templates_generate_xml": "Mostrar el árbol XML.",
        "expand_templates_generate_rawhtml": "Mostrar HTML en crudo",
-       "expand_templates_preview": "Previsualización"
+       "expand_templates_preview": "Previsualización",
+       "pagelanguage": "Selector de idioma de página",
+       "pagelang-name": "Página",
+       "pagelang-language": "Idioma",
+       "pagelang-use-default": "Utilizar el idioma predeterminado",
+       "pagelang-select-lang": "Seleccionar idioma",
+       "right-pagelang": "Cambiar el idioma de la página",
+       "action-pagelang": "cambiar el idioma de la página",
+       "log-name-pagelang": "Registro de cambios en idiomas",
+       "log-description-pagelang": "Este es un registro de los cambios en los idiomas de las páginas.",
+       "logentry-pagelang-pagelang": "$1 {{GENDER:$2|cambió}} el idioma de la página «$3» del $4 al $5."
 }
index b7e217c..05c0e32 100644 (file)
        "duplicate-defaultsort": "'''Hoiatus:''' Järjestamisvõti \"$2\" tühistab eespool oleva järjestamisvõtme \"$1\".",
        "version": "Versioon",
        "version-extensions": "Paigaldatud lisad",
-       "version-skins": "Kujundused",
+       "version-skins": "Paigaldatud kujundused",
        "version-specialpages": "Erileheküljed",
        "version-parserhooks": "Parserihaagid",
        "version-variables": "Muutujad",
        "version-license": "MediaWiki litsents",
        "version-ext-license": "Litsents",
        "version-ext-colheader-name": "Lisa",
+       "version-skin-colheader-name": "Kujundus",
        "version-ext-colheader-version": "Versioon",
        "version-ext-colheader-license": "Litsents",
        "version-ext-colheader-description": "Kirjeldus",
        "expand_templates_remove_nowiki": "Ära näita tulemuses <nowiki>-silte",
        "expand_templates_generate_xml": "Näita XML-liigenduspuud",
        "expand_templates_generate_rawhtml": "Näita toor-HTMLi",
-       "expand_templates_preview": "Eelvaade"
+       "expand_templates_preview": "Eelvaade",
+       "pagelanguage": "Lehekülje keele valik",
+       "pagelang-name": "Lehekülg",
+       "pagelang-language": "Keel",
+       "pagelang-use-default": "Kasuta vaikekeelt",
+       "pagelang-select-lang": "Vali keel",
+       "right-pagelang": "Muuta lehekülje keelt",
+       "action-pagelang": "muuta lehekülje keelt",
+       "log-name-pagelang": "Keele muutmise logi",
+       "log-description-pagelang": "Siia on logitud lehekülgede keele muutmised.",
+       "logentry-pagelang-pagelang": "$1 {{GENDER:$2|muutis}} lehekülje \"$3\" keelt: $4 → $5."
 }
index 2ae3059..77c1b16 100644 (file)
        "duplicate-defaultsort": "هشدار: ترتیب پیش‌فرض «$2» ترتیب پیش‌فرض قبلی «$1» را باطل می‌کند.",
        "version": "نسخه",
        "version-extensions": "افزونه‌های نصب‌شده",
-       "version-skins": "پوسته‌ها",
+       "version-skins": "پوسته‌های نصب شده",
        "version-specialpages": "صفحه‌های ویژه",
        "version-parserhooks": "قلاب‌های تجزیه‌گر",
        "version-variables": "متغیرها",
        "version-hook-name": "نام قلاب",
        "version-hook-subscribedby": "وارد شده توسط",
        "version-version": "(نسخه  $1)",
+       "version-no-ext-name": "[بدون نام]",
        "version-svn-revision": "(&رلم;r$2)",
        "version-license": "اجازه‌نامهٔ مدیاویکی",
        "version-ext-license": "مجوزها",
        "version-ext-colheader-name": "گستره‌ها",
+       "version-skin-colheader-name": "پوسته",
        "version-ext-colheader-version": "نسخه",
        "version-ext-colheader-license": "مجوز",
        "version-ext-colheader-description": "توصیفات",
        "expand_templates_remove_nowiki": "خنثی کردن تگ‌های <nowiki> در نتیجه",
        "expand_templates_generate_xml": "نمایش درخت تجزیهٔ XML",
        "expand_templates_generate_rawhtml": "نمایش اچ‌تی‌ام‌ال خام",
-       "expand_templates_preview": "پیش‌نمایش"
+       "expand_templates_preview": "پیش‌نمایش",
+       "pagelanguage": "صفحه انتخاب زبان",
+       "pagelang-name": "صفحه",
+       "pagelang-language": "زبان",
+       "pagelang-use-default": "استفاده از زبان پیش‌فرض",
+       "pagelang-select-lang": "انتخاب زبان",
+       "right-pagelang": "تغییر صفحهٔ زبان",
+       "action-pagelang": "تغییر زبان صفحه",
+       "log-name-pagelang": "تغییر سیاههٔ زبان",
+       "log-description-pagelang": "این سیاههٔ تغییرات صفحهٔ زبان‌ها است.",
+       "logentry-pagelang-pagelang": "$1 {{GENDER:$2| تغییریافت}} زبان صفحه برای  $3  از  $4  به  $5 ."
 }
index 4a2b184..d554fe6 100644 (file)
        "mergehistory-box": "Yhdistä kahden sivun muutoshistoria",
        "mergehistory-from": "Lähdesivu",
        "mergehistory-into": "Kohdesivu",
-       "mergehistory-list": "Liitettävissä olevat muutokset",
+       "mergehistory-list": "Sivuhistoria, joka voidaan yhdistää",
        "mergehistory-merge": "Seuraavat sivun [[:$1]] muutokset voidaan liittää sivun [[:$2]] muutoshistoriaan. Voit valita version, jota myöhempiä muutoksia ei liitetä. Selainlinkkien käyttäminen kadottaa tämän valinnan.",
        "mergehistory-go": "Etsi muutokset",
        "mergehistory-submit": "Yhdistä versiot",
        "mergehistory-autocomment": "Yhdisti sivun [[:$1]] sivuun [[:$2]]",
        "mergehistory-comment": "Yhdisti sivun [[:$1]] sivuun [[:$2]]: $3",
        "mergehistory-same-destination": "Lähde- ja kohdesivut eivät voi olla samat",
-       "mergehistory-reason": "Syy",
+       "mergehistory-reason": "Syy:",
        "mergelog": "Yhdistämisloki",
        "pagemerge-logentry": "liitti sivun [[$1]] sivuun [[$2]] (muokkaukseen $3 asti)",
        "revertmerge": "Kumoa yhdistäminen",
        "deletedcontributions-title": "Poistetut muokkaukset",
        "sp-deletedcontributions-contribs": "muokkaukset",
        "linksearch": "Etsi ulkoisia linkkejä",
-       "linksearch-pat": "Osoite",
-       "linksearch-ns": "Nimiavaruus",
+       "linksearch-pat": "Hakuehto:",
+       "linksearch-ns": "Nimiavaruus:",
        "linksearch-ok": "Etsi",
        "linksearch-text": "Jokerimerkkejä, kuten \"*.wikipedia.org\", voidaan käyttää.\nVaaditaan vähintään ylätason verkkotunnus, esimerkiksi \"*.org\".<br />\n{{PLURAL:$2|Tuettu protokolla|Tuetut protokollat}}: <code>$1</code> (oletuksena on <code>http://</code>, jos protokollaa ei määritetä).",
        "linksearch-line": "$1 on linkitetty sivulta $2",
        "undelete-error-long": "Tiedoston palauttaminen epäonnistui:\n\n$1",
        "undelete-show-file-confirm": "Haluatko varmasti nähdä poistetun version tiedostosta <nowiki>$1</nowiki>, joka on tallennettu $2 kello $3?",
        "undelete-show-file-submit": "Kyllä",
-       "namespace": "Nimiavaruus",
+       "namespace": "Nimiavaruus:",
        "invert": "Käänteinen valinta",
        "tooltip-invert": "Valitse tämä kohta, jos haluat piilottaa muutokset sivuihin valitussa nimiavaruudessa (ja liittyviin nimiavaruuksiin, jos valittu)",
-       "namespace_association": "Liitetty nimiavaruus",
-       "tooltip-namespace_association": "Valitse tämä kohta, jos haluat sisällyttää myös keskustelu- tai aihe-nimiavaruudet, jotka on liitetty valittuun nimiavaruuteen",
+       "namespace_association": "Liittyvä nimiavaruus",
+       "tooltip-namespace_association": "Valitse tämä kohta, jos haluat sisällyttää ne keskustelu- tai aihe-nimiavaruudet, jotka liittyvät valittuun nimiavaruuteen",
        "blanknamespace": "(sivut)",
        "contributions": "{{GENDER:$1|Käyttäjän}} muokkaukset",
        "contributions-title": "Käyttäjän $1 muokkaukset",
        "blockip-legend": "Estä käyttäjä",
        "blockiptext": "Tällä toiminnolla voit estää käyttäjätunnusta tai IP-osoitetta muokkaamasta.<br />\nTällainen muokkausesto pitäisi asettaa vain vandalismin torjumiseksi ja [[{{MediaWiki:Policy-url}}|käytännön]] mukaisesti.\nKirjoita eston syy alla olevaan kenttään.",
        "ipaddressorusername": "IP-osoite tai käyttäjätunnus",
-       "ipbexpiry": "Kesto",
-       "ipbreason": "Syy",
+       "ipbexpiry": "Vanhentuu:",
+       "ipbreason": "Syy:",
        "ipbreason-dropdown": "*Yleiset estosyyt\n** Väärän tiedon lisääminen\n** Sisällön poistaminen\n** Mainoslinkkien lisääminen\n** Sotkeminen tai roskan lisääminen\n** Häiriköinti\n** Useamman käyttäjätunnuksen väärinkäyttö\n** Sopimaton käyttäjätunnus",
        "ipb-hardblock": "Estä sisäänkirjautuneita käyttäjiä muokkaamasta tästä IP-osoitteesta",
        "ipbcreateaccount": "Estä tunnusten luonti",
        "allmessages-filter-unmodified": "Muuttamaton",
        "allmessages-filter-all": "Kaikki",
        "allmessages-filter-modified": "Muutettu",
-       "allmessages-prefix": "Suodata etuliitteellä",
+       "allmessages-prefix": "Suodata etuliitteellä:",
        "allmessages-language": "Kieli:",
        "allmessages-filter-submit": "Siirry",
        "allmessages-filter-translate": "Käännä",
        "siteuser": "{{GRAMMAR:genitive|{{SITENAME}}}} käyttäjä $1",
        "anonuser": "{{GRAMMAR:genitive|{{SITENAME}}}} anonyymi käyttäjä $1",
        "lastmodifiedatby": "Tätä sivua muokkasi viimeksi $3 $1 kello $2.",
-       "othercontribs": "Perustuu työlle, jonka teki $1.",
+       "othercontribs": "Perustuu seuraavien tekijöiden työhön: $1.",
        "others": "muut",
        "siteusers": "{{GRAMMAR:genitive|{{SITENAME}}}} {{PLURAL:$2|käyttäjä|käyttäjät}} $1",
        "anonusers": "{{GRAMMAR:genitive|{{SITENAME}}}} {{PLURAL:$2|anonyymi käyttäjä|anonyymit käyttäjät}} $1",
        "pageinfo-display-title": "Sivun otsikko",
        "pageinfo-default-sort": "Oletuslajitteluavain",
        "pageinfo-length": "Sivun pituus (tavuina)",
-       "pageinfo-article-id": "Sivun tunniste",
+       "pageinfo-article-id": "Sivun tunnistenumero",
        "pageinfo-language": "Sivun sisällön kieli",
        "pageinfo-content-model": "Sivun sisällön muoto",
        "pageinfo-robot-policy": "Hakukonemerkinnät",
        "pageinfo-toolboxlink": "Sivun tiedot",
        "pageinfo-redirectsto": "Ohjaus sivulle",
        "pageinfo-redirectsto-info": "tiedot",
-       "pageinfo-contentpage": "Lasketaan sisältösivuksi",
+       "pageinfo-contentpage": "Kohdellaan sisältösivuna",
        "pageinfo-contentpage-yes": "Kyllä",
        "pageinfo-protect-cascading": "Tämä on tarttuvan suojauksen lähdesivu",
        "pageinfo-protect-cascading-yes": "Kyllä",
        "intentionallyblankpage": "Tämä sivu on tarkoituksellisesti tyhjä.",
        "external_image_whitelist": " #Älä muuta tätä riviä lainkaan.<pre>\n#Laita säännöllisten lausekkeiden palaset (vain osa, joka menee //-merkkien väliin) alle\n#Niitä verrataan ulkoisten (suoralinkitettyjen) kuvien URLeihin\n#Ne jotka sopivat, näytetään kuvina, muutoin kuviin näytetään vain linkit\n#Rivit, jotka alkavat #-merkillä ovat kommentteja\n#Tämä on riippumaton kirjainkoosta\n\n#Laita kaikki säännöllisten lausekkeiden palaset tämän rivit yläpuolelle. Älä muuta tätä riviä lainkaan</pre>",
        "tags": "Voimassa olevat muutosmerkinnät",
-       "tag-filter": "[[Special:Tags|Merkintäsuodatin]]",
+       "tag-filter": "[[Special:Tags|Merkintä]]suodatin:",
        "tag-filter-submit": "Suodata",
        "tag-list-wrapper": "([[Special:Tags|{{PLURAL:$1|Merkintä|Merkinnät}}]]: $2)",
        "tags-title": "Merkinnät",
        "expand_templates_remove_nowiki": "Poista <nowiki>-tagit tulosteesta",
        "expand_templates_generate_xml": "Näytä XML-jäsennyspuu",
        "expand_templates_generate_rawhtml": "Näytä raaka HTML",
-       "expand_templates_preview": "Esikatselu"
+       "expand_templates_preview": "Esikatselu",
+       "pagelanguage": "Sivun kielen valinta",
+       "pagelang-name": "Sivu",
+       "pagelang-language": "Kieli",
+       "pagelang-use-default": "Käytä oletuskieltä",
+       "pagelang-select-lang": "Valitse kieli",
+       "right-pagelang": "Vaihda sivun kieli",
+       "action-pagelang": "muuttaa sivun kieliasetuksia",
+       "log-name-pagelang": "Kielenvaihtoloki",
+       "log-description-pagelang": "Tämä on loki, johon merkitään muutokset sivujen kieliasetuksissa.",
+       "logentry-pagelang-pagelang": "$1 {{GENDER:$2|muutti}} sivun kieltä sivulla $3 kielestä $4 kieleksi $5."
 }
index 4d0716c..2e56326 100644 (file)
        "gotaccountlink": "Rita inn",
        "userlogin-resetlink": "Hevur tú gloymt tínar logg inn upplýsingar",
        "userlogin-resetpassword-link": "Hevur tú gloymt títt loyniorð?",
+       "userlogin-helplink2": "Hjálp til innritan",
        "userlogin-loggedin": "Tú ert longu innritað/ur sum {{GENDER:$1|$1}}.\nNýt formularin niðanfyri fyri at rita inn sum ein annar brúkari.",
        "userlogin-createanother": "Stovna eina aðra kontu",
        "createacct-emailrequired": "Teldupost adressa",
        "resetpass-submit-loggedin": "Broyt loyniorð",
        "resetpass-submit-cancel": "Ógildað",
        "resetpass-wrong-oldpass": "Ógyldug fyribils ella verandi loyniorð.\nMøguliga hevur tú longu broytt títt loyniorð ella biðið um eitt nýtt fyribils loyniorð.",
+       "resetpass-recycled": "Vinarliga broyt títt loyniorð til okkurt annað enn tað tú hevur í løtuni.",
+       "resetpass-temp-emailed": "Tú hevur ritað inn við einum fyribils loyniorði frá telduposti. \nFyri at gjøgnumføra innritanina, so mást tú velja tær eitt nýtt loyniorð og skriva tað her:",
        "resetpass-temp-password": "Fyribils loyniorð",
        "resetpass-abort-generic": "Broyting av loyniorði bleiv avbrotin av einari víðkan.",
+       "resetpass-expired": "Títt loyniorð er útgingið. Vinarliga vel tær eitt nýtt, so tú kanst rita inn.",
+       "resetpass-expired-soft": "Títt loyniorð er útgingið og má broytast. Vinarliga vel tær eitt nýtt nú ella trýst á \"{{int:resetpass-submit-cancel}}\" fyri at broyta tað seinni.",
        "passwordreset": "Nullstilla loyniorðið",
        "passwordreset-text-one": "Útfyll henda teigin fyri at nullstilla títt loyniorð.",
        "passwordreset-text-many": "{{PLURAL:$1|Útfyll í ein av teigunum fyri at móttaka eitt fyribils loyniorð við telduposti.}}",
        "edit-gone-missing": "Tað var ikki møguligt at dagføra síðuna.\nTað sær út til at hon er blivin strikað.",
        "edit-conflict": "Rættingar trupulleiki (konflikt).",
        "edit-no-change": "Tín rætting var sæð burtur frá, tí ongin broyting varð gjørd í tekstinum.",
+       "postedit-confirmation-created": "Síðan er upprættað.",
+       "postedit-confirmation-restored": "Síðan er endurskapað.",
        "postedit-confirmation-saved": "Tín rætting varð goymd.",
        "edit-already-exists": "Tað var ikki møguligt at upprætta nýggja síðu.\nSíðan er longu til.",
        "defaultmessagetext": "Standard boðtekstur",
        "undo-summary-username-hidden": "Angra versjón $1 sum ein fjaldur brúkari hevur gjørt",
        "cantcreateaccounttitle": "Tað ber ikki til at upprætta konto",
        "cantcreateaccount-text": "Upprættan frá hesi IP adressuni ('''$1''') er blivin sperrað av [[User:$3|$3]]. Orsøkin til sperringina sigst vera ''$2''\n\n$3 sigur orsøkina vera ''$2''",
+       "cantcreateaccount-range-text": "IP adressur í intervallinum '''$1''', sum fevnir um tína IP adressu ('''$4'''), eru sperraðar fyri upprættan av nýggjari konto av [[User:$3|$3]].\n\n$3 segði orsøkina vera ''$2''",
        "viewpagelogs": "Sí logg fyri hesa grein",
        "nohistory": "Eingin broytisøga er til hesa síðuna.",
        "currentrev": "Núverandi endurskoðan",
        "currentrev-asof": "Seinasta endurskoðan sum var $1",
        "revisionasof": "Endurskoðan frá $1",
-       "revision-info": "Versjón frá $1 av $2",
+       "revision-info": "Versjón frá $1 av {{GENDER:$6|$2}}$7",
        "previousrevision": "←Eldri endurskoðan",
        "nextrevision": "Nýggjari endurskoðan→",
        "currentrevisionlink": "Skoða verandi endurskoðan",
        "search-section": "(sektión $1)",
        "search-suggest": "Meinti tú: $1",
        "search-interwiki-caption": "Líknandi verkætlanir",
-       "search-interwiki-default": "$1 úrslit:",
+       "search-interwiki-default": "Úrslit frá $1:",
        "search-interwiki-more": "(meira)",
        "search-relatedarticle": "Líknandi",
        "searchrelated": "líknandi",
        "searchall": "alt",
        "showingresults": "Niðanfyri standa upp til {{PLURAL:$1|'''$1''' úrslit, sum byrjar|'''$1''' úrslit, sum byrja}} við #<b>$2</b>.",
+       "showingresultsinrange": "Niðanfyri verða víst upp til {{PLURAL:$1|<strong>1</strong> úrslit|<strong>$1</strong> úrslit}} í økinum #<strong>$2</strong> til #<strong>$3</strong>.",
        "showingresultsheader": "{{PLURAL:$5|Úrslit '''$1''' av '''$3'''|Úrslit '''$1 - $2''' av '''$3'''}} fyri '''$4'''",
        "search-nonefound": "Leitingin gav onki úrslit.",
        "powersearch-legend": "Víðkað leitan",
        "powersearch-togglelabel": "Kanna eftir:",
        "powersearch-toggleall": "Alt",
        "powersearch-togglenone": "Ongi",
+       "powersearch-remember": "Minst til tað valda til framtíðar leitingar",
        "search-external": "Uttanhýsis leitan",
        "searchdisabled": "{{SITENAME}} leitan er sett úr gildi.\nTú kanst leita via Google ímeðan.\nLegg til merkis, at teirra innihaldsyvirlit av {{SITENAME}} kann vera gamalt og ikki dagført.",
        "search-error": "Ein feilur hendi undir leitanini: $1",
        "preferences": "Innstillingar",
        "mypreferences": "Innstillingar",
        "prefs-edits": "Tal av rættingum:",
+       "prefsnologintext2": "Vinarliga $1 fyri at broyta tínar innstillingat.",
        "prefs-skin": "Hamur",
        "skin-preview": "Forskoðan",
        "datedefault": "Ongi serlig ynskir",
        "right-move": "Flyt síður",
        "right-move-subpages": "Flyt síður saman við undirsíðum teirra",
        "right-move-rootuserpages": "Flyta høvuðs brúkarasíður",
+       "right-move-categorypages": "Flyt bólkasíður",
        "right-movefile": "Flyt fílur",
        "right-suppressredirect": "Flyta síður uttan at upprætta víðaristilling frá tí gomlu síðuni.",
        "right-upload": "Legg upp fílur",
        "action-createpage": "upprætta síður",
        "action-createtalk": "upprætta kjak síður",
        "action-createaccount": "upprætta hesa brúkarakontuna",
+       "action-history": "vís søguna hjá hesi síðu",
        "action-minoredit": "marka hesa rætting sum lítla",
        "action-move": "flyt hesa síðu",
        "action-move-subpages": "flyt hesa síðu og undirsíður hennara",
        "action-move-rootuserpages": "flyt høvuðs brúkarasíður",
+       "action-move-categorypages": "Flyt bólkasíður",
        "action-movefile": "flyt hesa fílu",
        "action-upload": "send hesa fílu upp",
        "action-reupload": "yvirskriva hesa verandi fíluna",
        "recentchanges-label-minor": "Hetta er ein lítil rætting",
        "recentchanges-label-bot": "Henda rætting varð gjørd av einum botti",
        "recentchanges-label-unpatrolled": "Henda rætting er ikki blivin eftirkannað enn",
+       "recentchanges-label-plusminus": "Støddin á síðuni broyttist við hesum talinum av bytes",
        "recentchanges-legend-heading": "'''Teknfrágreiðing:'''",
        "recentchanges-legend-newpage": "{{int:recentchanges-label-newpage}} (sí eisini [[Special:NewPages|yvirlit yvir nýggjar síður]])",
-       "rcnotefrom": "Niðanfyri standa broytingarnar síðani '''$2''', (upp til '''$1''' er sýndar).",
+       "rcnotefrom": "Niðanfyri verða broytingar síðan <strong>$2</strong> (upp til <strong>$1</strong> vístar).",
        "rclistfrom": "Sýn nýggjar broytingar byrjandi við $3 $2",
        "rcshowhideminor": "$1 minni rættingar",
+       "rcshowhideminor-show": "Vís",
+       "rcshowhideminor-hide": "Fjal",
        "rcshowhidebots": "$1 bottar",
+       "rcshowhidebots-show": "Vís",
+       "rcshowhidebots-hide": "Fjal",
        "rcshowhideliu": "$1 skrásettir brúkarar",
+       "rcshowhideliu-show": "Vís",
+       "rcshowhideliu-hide": "Fjal",
        "rcshowhideanons": "$1 navnleysar brúkarar",
+       "rcshowhideanons-show": "Vís",
+       "rcshowhideanons-hide": "Fjal",
        "rcshowhidepatr": "$1 eftirhugdar rættingar",
+       "rcshowhidepatr-show": "Vís",
+       "rcshowhidepatr-hide": "Fjal",
        "rcshowhidemine": "$1 mínar rættingar",
+       "rcshowhidemine-show": "Vís",
+       "rcshowhidemine-hide": "Fjal",
        "rclinks": "Sýn seinastu $1 broytingarnar seinastu $2 dagarnar<br />$3",
        "diff": "munur",
        "hist": "søga",
        "lockmanager-fail-svr-acquire": "Kundi ikki skaffa lás til dátagrunnin $1.",
        "lockmanager-fail-svr-release": "Kundi ikki loysa lásini í ambætaranum $1.",
        "uploadstash": "Legg út stash",
+       "uploadstash-clear": "Rudda burtur stashaðar fílur",
        "uploadstash-refresh": "Uppfrískað listan við fílum",
        "img-auth-accessdenied": "Atgongd noktað",
        "img-auth-badtitle": "Tað bar ikki til at gera eitt heiti útfrá \"$1\".",
index 2508e23..5f57d75 100644 (file)
                        "아라",
                        "Scoopfinder",
                        "Akeron",
-                       "Linedwell"
+                       "Linedwell",
+                       "Yona b"
                ]
        },
        "tog-underline": "Souligner les liens :",
        "license-nopreview": "(Prévisualisation non disponible)",
        "upload_source_url": " (une URL valide et accessible publiquement)",
        "upload_source_file": " (un fichier sur votre ordinateur)",
+       "listfiles-delete": "supprimer",
        "listfiles-summary": "Cette page spéciale permet de lister tous les fichiers importés.",
        "listfiles_search_for": "Rechercher un nom de média :",
        "imgfile": "fichier",
        "expand_templates_remove_nowiki": "Supprime les marqueurs <nowiki> dans le résultat",
        "expand_templates_generate_xml": "Voir l’arborescence d’analyse XML",
        "expand_templates_generate_rawhtml": "Afficher le HTML brut",
-       "expand_templates_preview": "Aperçu du rendu"
+       "expand_templates_preview": "Aperçu du rendu",
+       "pagelanguage": "Sélecteur de langue de la page",
+       "pagelang-name": "Page",
+       "pagelang-language": "Langue",
+       "pagelang-use-default": "Utiliser la langue par défaut",
+       "pagelang-select-lang": "Sélectionner la langue",
+       "right-pagelang": "Changer la langue de la page",
+       "action-pagelang": "changer la langue de la page",
+       "log-name-pagelang": "Tracer les changements de langue",
+       "log-description-pagelang": "Ceci est un journal des changements dans les langues des pages.",
+       "logentry-pagelang-pagelang": "$1 {{GENDER:$2|a changé}} la langue de la page $3 de $4 à $5."
 }
index ae9dfde..6bb0457 100644 (file)
        "permalink": "Permanent link",
        "print": "Drük",
        "view": "Lees",
+       "view-foreign": "Üüb $1 uunluke",
        "edit": "Bewerke",
+       "edit-local": "Lokaal beskriiwang bewerke",
        "create": "Maage",
+       "create-local": "Lokaal beskriiwang diartudu",
        "editthispage": "Sidj bewerke",
        "create-this-page": "Nei sidj maage",
        "delete": "Strik",
        "jumptonavigation": "Nawigatjuun",
        "jumptosearch": "Schük",
        "view-pool-error": "Det dää üs iarag, a servers san auerläästet.\nTuföl brükern ferschük, det sidj tu beschüken.\nWees so gud an teew en uugenblak, iar dü det noch ans ferschükst.\n\n$1",
+       "generic-pool-error": "Det dää üs iarag, a servers san tu tidj auerläästet.\nTuföl brükern ferschük, det sidj tu beschüken.\nWees so gud an teew en uugenblak, iar dü det noch ans weder ferschükst.",
        "pool-timeout": "Tidj uflepen bi't teewen üüb't sperang",
        "pool-queuefull": "Pool as auerläästet",
        "pool-errorunknown": "Ünbekäänd feeler",
        "edit-gone-missing": "Detdiar sidj küd ei aktualisiaret wurd. Ferlicht as det stregen wurden.",
        "edit-conflict": "Konflikt bi't bewerkin (BK).",
        "edit-no-change": "Din feranrang woort ei seekert, auer dü di tekst ei feranert heest.",
+       "postedit-confirmation-created": "Det sidj as maaget wurden.",
+       "postedit-confirmation-restored": "Det sidj as weder turaghaalet wurden.",
        "postedit-confirmation-saved": "Din feranrang as seekert wurden.",
        "edit-already-exists": "Det nei sidj küd ei iinracht wurd. Son sidj as al diar.",
        "defaultmessagetext": "Standard tekst",
        "parser-template-recursion-depth-warning": "Tuföl föörlaagen uun föörlaagen ($1)",
        "language-converter-depth-warning": "Spriakenkonwerter auerläästet ($1)",
        "node-count-exceeded-category": "Jodiar sidjen haa tuföl ferbinjangen (nodes)",
+       "node-count-exceeded-category-desc": "En kategorii för sidjen mä tuföl knooter (nodes).",
        "node-count-exceeded-warning": "Detdiar sidj hää tuföl ferbinjangen (nodes)",
        "expansion-depth-exceeded-category": "Jodiar sidjen haa tuföl ütjwidjangen (expansion)",
+       "expansion-depth-exceeded-category-desc": "Det as en kategorii för sidjen mä tuföl ütjwidjangen.",
        "expansion-depth-exceeded-warning": "Detdiar sidj hää tuföl ütjwidjangen (expansion)",
        "parser-unstrip-loop-warning": "Diar as en jinsidjag ferwisang",
        "parser-unstrip-recursion-limit": "Tuföl jinsidjag ferwisangen bi $1",
        "currentrev": "Leetst werjuun",
        "currentrev-asof": "Leetst werjuun faan di $2, am a klook $3",
        "revisionasof": "Werjuun faan a $2, klook $3",
-       "revision-info": "Werjuun faan di $4 am a klook $5 faan $2",
+       "revision-info": "Werjuun faan di $4, am a klook $5 faan {{GENDER:$6|$2}}$7",
        "previousrevision": "← Naistääler werjuun:",
        "nextrevision": "Naistjonger werjuun →",
        "currentrevisionlink": "Leetst werjuun",
        "mergehistory-empty": "Nian werjuunen kön tuupfeerd wurd.",
        "mergehistory-success": "$3 {{PLURAL:$3|werjuun|werjuunen}} faan [[:$1]] tuupfeerd tu [[:$2]].",
        "mergehistory-fail": "Werjuunen kön ei tuupfeerd wurd. Luke noch ans efter at sidj an a tidjen.",
+       "mergehistory-fail-toobig": "A werjuunen küd ei tuupfeerd wurd, auer muar üs {{PLURAL:$1|ian werjuun|$1 werjuunen}} fersköwen {{PLURAL:$1|wurd skul|wurd skul}}.",
        "mergehistory-no-source": "Det iarst sidj \"$1\" as ai diar.",
        "mergehistory-no-destination": "Det ööder sidj „$1“ as ei diar.",
        "mergehistory-invalid-source": "Jurtkamstsid mötj en gülti sidnoome heewe.",
        "powersearch-togglelabel": "Schük uun:",
        "powersearch-toggleall": "Aaltumaal",
        "powersearch-togglenone": "Nianen",
+       "powersearch-remember": "Ütjwool mark för leeder schükuunfraagen",
        "search-external": "Schük ekstern",
        "searchdisabled": "Det schüken üüb {{SITENAME}} as ei aktiif. Dü könst uuntesken mä Google schük. Seenk diaram, dat Google sin steegwurden miast ei üüb a leetst stant san.",
        "search-error": "Diar as wat skiaf gingen bi't schüken: $1",
        "right-move": "Sidjen fersküüw",
        "right-move-subpages": "Sidjen mä onersidjen fersküüw",
        "right-move-rootuserpages": "Hood-brükersidj fersküüw",
+       "right-move-categorypages": "Kategoriisidjen fersküüw",
        "right-movefile": "Datein fersküüw",
        "right-suppressredirect": "Bi't fersküüwen nian widjerfeerang iinracht",
        "right-upload": "Datein huuchschüür",
        "action-createpage": "nei sidjen tu maagin",
        "action-createtalk": "diskusjuunssidjen maage",
        "action-createaccount": "jüdeer brükerkonto mååge",
+       "action-history": "di ferluup faan detdiar sidj uuntulukin.",
        "action-minoredit": "detdiar feranrang üs letj kääntiakne",
        "action-move": "an fersküüw det diar sidj",
        "action-move-subpages": "an fersküüw detdiar sidj mä hör onersidjen",
        "action-move-rootuserpages": "hood-brükersidj fersküüw",
+       "action-move-categorypages": "kategoriisidjen uuntulukin",
        "action-movefile": "an fersküüw detdiar datei",
        "action-upload": "Datein huuchschüür",
        "action-reupload": "det datei auerskriiw",
        "windows-nonascii-filename": "Detheer wiki läät nian dateinöömer mä aparte tiakens tu.",
        "fileexists": "En datei mä didiar nööm jaft at al. Luke noch ans efter <strong>[[:$1]]</strong>, wan dü ei gans seeker beest, of dü det anre wel.\n[[$1|thumb]]",
        "filepageexists": "En beskriiwangssidj för <strong>[[:$1]]</strong> as al diar, oober nian datei. Din beskriiwang woort ei apnimen. Det beskriiwangssidj mut do man efter't huuchschüüren noch ans efterluket wurd.\n[[$1|thumb]]",
-       "fileexists-extension": "Diar as al en datei mä di nööm: [[$2|thumb]]\n* Nööm faan det nei datei: <strong>[[:$1]]</strong>\n* Nööm faan det ual datei: <strong>[[:$2]]</strong>\nWees so gud an nem en öödern nööm.",
+       "fileexists-extension": "Diar as al en datei mä di nööm: [[$2|thumb]]\n* Nööm faan det nei datei: <strong>[[:$1]]</strong>\n* Nööm faan det ual datei: <strong>[[:$2]]</strong>\nWel dü ei ferlicht en beedern nööm brük?",
        "fileexists-thumbnail-yes": "Detdiar datei as was en sümnaielbil ''(thumbnail)''. [[$1|thumb]]\nLuke di det datei <strong>[[:$1]]</strong> noch ans uun.\nWan det det originaal bil as, säärst dü nian sümnaielbil huuchschüür.",
        "file-thumbnail-no": "Di dateinööm begant mä <strong>$1</strong>. Det as was en sümnaielbil ''(thumbnail)''.\nLuke noch ans efter, of dü det bil uun fol grate diar heest, an do schüür det huuch.",
        "fileexists-forbidden": "En datei mä didiar nööm jaft at al an koon ei auerskrewen wurd.\nGung noch ans turag an schüür det datei mä en öödern nööm huuch.\n[[File:$1|thumb|center|$1]]",
        "filedelete-maintenance": "Det striken of turaghaalin faan datein gongt uun uugenblak ei.",
        "filedelete-maintenance-title": "Det datei koon ei stregen wurd",
        "mimesearch": "Efter MIME-Typ schük",
-       "mimesearch-summary": "Üüb detheer sidj könst dü datein efter hör MIME-Typ filtre.\nDet formoot as leewen slach/onerslach üs uun det bispal: <code>image/jpeg</code>.",
+       "mimesearch-summary": "Üüb detheer sidj könst dü datein efter hör MIME-Typ filtre.\nDet formoot as leewen slach/onerslach üs uun det bispal: <code>image/jpeg</code> of uk <code>image/*</code>.",
        "mimetype": "MIME-Typ:",
        "download": "Deelloose",
        "unwatchedpages": "Sidjen, diar näämen uun't uug hää",
        "pageswithprop-prophidden-binary": "Binär eegenskapswäärs ferbürgen ($1)",
        "doubleredirects": "Dobelt widjerfeerangen",
        "doubleredirectstext": "Detheer list feert widjerfeerangen ap, diar üüb widjerfeerangen widjer feer.\nUun arke rä stun ferwisangen tu't iarst an ööder widjerfeerang an uk tu det sidj, huar det ööder widjerfeerang üüb ferwiset. <del>Trochstregen</del> iindracher san al bewerket wurden.",
-       "double-redirect-fixed-move": "[[$1]] as fersköwen wurden an feert nü widjer tu [[$2]].",
+       "double-redirect-fixed-move": "[[$1]] as fersköwen wurden. Hat feert nü widjer tu [[$2]].",
        "double-redirect-fixed-maintenance": "Dobelt widjerfeerang faan [[$1]] tu [[$2]] as apredet wurden.",
        "double-redirect-fixer": "Bot för widjerfeerangen",
        "brokenredirects": "Uunstaken widjerfeerangen",
        "wantedtemplates": "Föörlaagen, diar brükt wurd",
        "mostlinked": "Sidjen, huar a miast ööder sidjen üüb ferwise",
        "mostlinkedcategories": "Miast brükt kategoriin",
-       "mostlinkedtemplates": "Miast brükt föörlaagen",
+       "mostlinkedtemplates": "Miast iinbünjen sidjen",
        "mostcategories": "Sidjen mä a miast kategoriin",
        "mostimages": "Datein, huar a miast sidjen üüb ferwise",
        "mostinterwikis": "Sidjen mä a miast ferwisangen tu ööder spriaken",
        "listgrouprights-removegroup-self": "Aanj brükerkonto faan {{PLURAL:$2|detdiar skööl|jodiar sköölen}} wechnem: $1",
        "listgrouprights-addgroup-self-all": "Koon aal a sköölen tu't aanj brükerkonto tuwise",
        "listgrouprights-removegroup-self-all": "Koon aal a sköölen faan't aanj brükerkonto wechnem",
+       "listgrouprights-namespaceprotection-header": "Nöömrüm mögelkhaiden",
+       "listgrouprights-namespaceprotection-namespace": "Nöömrüm",
+       "listgrouprights-namespaceprotection-restrictedto": "Rochten faan di brüker tu bewerkin",
        "trackingcategories": "Kategoriin ferfulge",
        "trackingcategories-summary": "Üüb detdiar sidj stun ferfulagt kategoriin, diar faan't MediaWiki-software iindraanj wurden san. Hör nöömer kön feranert wurd, wan dü a süsteem-noorachten uun a {{ns:8}}-nöömrüm feranerst.",
        "trackingcategories-msg": "Kategorii ferfulge",
        "watchnologin": "Ei uunmeldet",
        "addwatch": "Uk uun't uug behual",
        "addedwatchtext": "Det sidj „[[:$1]]“ wel dü [[Special:Watchlist|uun't uug behual]].\nFeranrangen faan detdiar sidj wurd üüb detdiar list fäästhäälen.",
+       "addedwatchtext-short": "Det sidj „$1“ kaam tu din sidjen, diar dü uun't uug behual wel.",
        "removewatch": "Ei muar uun't uug behual",
        "removedwatchtext": "Det sidj „[[:$1]]“ as faan a sidjen, diar dü [[Special:Watchlist|uun't uug behual]] wel, wechnimen wurden.",
+       "removedwatchtext-short": "Det sidj „$1“ woort ei muar faan di uun't uug behäälen.",
        "watch": "Uun't uug behual",
        "watchthispage": "Detdiar sidj uun't uug behual",
        "unwatch": "Ei muar uun't uug behual",
        "unwatchthispage": "Ei muar uun't uug behual",
        "notanarticle": "Nään artiikel",
        "notvisiblerev": "Det werjuun faan en öödern brüker as stregen wurden.",
-       "watchlist-details": "Dü heest {{PLURAL:$1|1 sidj|$1 sidjen}} uun't uug.",
+       "watchlist-details": "Dü behäälst {{PLURAL:$1|1 sidj|$1 sidjen}} uun't uug, diarbi wurd diskuschuunsidjen ei mätääld.",
        "wlheader-enotif": "Di e-mail siinst as aktiif.",
        "wlheader-showupdated": "Nei feranert sidjen wurd '''fäät''' uunwiset.",
        "wlnote2": "Diar stun a feranrangen faan a leetst {{PLURAL:$1|stünj|<strong>$1</strong> stünjen}}, üüb a stant faan $2, $3.",
        "contributions-title": "Brükerbidracher för \"$1\"",
        "mycontris": "Bidracher",
        "contribsub2": "För {{GENDER:$3|$1}} ($2)",
+       "contributions-userdoesnotexist": "Son brükerkonto \"$1\" jaft at ei.",
        "nocontribs": "Diar wiar nian paasin brükerbidracher",
        "uctop": "(aktuel)",
        "month": "faan muun (of iarer):",
        "movepagetalktext": "Uk det diskusjuunssidj woort fersköwen, wan det diar as, '''oober ei, wan:'''\n*Diar al en diskusjuunssidj mä didiar nööm as, of\n*Dü detdiar mögelkhaid ütjslotst.\n\nUun didiar faal skel dü a diskusjuunssidjen faan hun tuupfeer.\n\nDreeg di '''nei''' tiitel bi '''ööder sidj''' iin, an diaroner '''en grünj''' för't amnäämen.",
        "movearticle": "Sidj fersküüw:",
        "moveuserpage-warning": "'''Paase üüb:''' Dü wel en brükersidj fersküüw. Seenk diaram, dat bluas det brükersidj amnäämd woort, oober '''ei''' di brüker. Hi behäält san ual nööm.",
+       "movecategorypage-warning": "<strong>Paase üüb:</strong> Dü wel jüst en kategoriisidj fersküüw. Seenk diaram, dat bluas det sidj fersköwen woort. A sidjen uun det kategorii wurd <em>ei</em> nei kategorisiaret.",
        "movenologintext": "Dü skel registriaret an [[Special:UserLogin|uunmeldet]] wees, am en sidj tu fersküüwen.",
        "movenotallowed": "Dü mutst nian sidjen fersküüw.",
        "movenotallowedfile": "Dü mutst nian datein fersküüw.",
        "cant-move-user-page": "Dü mutst nian brükersidjen fersküüw (bluas onersidjen).",
        "cant-move-to-user-page": "Dü mutst nian sidjen üüb en brükersidj fersküüw (bluas üüb onersidjen).",
+       "cant-move-category-page": "Dü mutst nian kategoriisidjen fersküüw.",
+       "cant-move-to-category-page": "Dü mutst nian sidj tu en kategoriisidj fersküüw.",
        "newtitle": "Müülj:",
        "move-watch": "Jodiar sidjen uun't uug behual",
        "movepagebtn": "Sidj fersküüw",
        "newimages-summary": "Detdiar spezial-sidj wiset a tuleetst huuchschüürd datein uun.",
        "newimages-legend": "Filter",
        "newimages-label": "Dateinööm (of en dial diarfaan):",
+       "newimages-showbots": "Faan bots huuchschüürd sidjen uunwise.",
        "noimages": "Niks tu sen.",
        "ilsubmit": "Schük",
        "bydate": "efter dootem",
        "watchlistedit-raw-done": "Det list mä sidjen, diar dü uun't uug behual wel, as nü üüb di neist stant.",
        "watchlistedit-raw-added": "{{PLURAL:$1|Ään iindrach as|$1 iindracher san}} diartu skrewen wurden:",
        "watchlistedit-raw-removed": "{{PLURAL:$1|Ään iindrach as|$1 iindracher san}} wechnimen wurden:",
+       "watchlistedit-clear-title": "Nian sidjen muar uun't uug behual",
+       "watchlistedit-clear-legend": "Nian sidjen muar uun't uug behual",
+       "watchlistedit-clear-explain": "Aal a sidjennöömer wel dü ei muar uun't uug behual",
+       "watchlistedit-clear-titles": "Sidjennöömer:",
+       "watchlistedit-clear-submit": "Sidjen, diar dü uun't uug behual wel, strik (permanent)",
+       "watchlistedit-clear-done": "Det list mä sidjen, diar dü uun't uug behual wel, as nü leesag maaget wurden.",
+       "watchlistedit-clear-removed": "{{PLURAL:$1|Ään iindrach as|$1 iindracher san}} wechnimen wurden:",
+       "watchlistedit-too-many": "Diar san tuföl sidjen tu uunwisin heer.",
+       "watchlisttools-clear": "Nian sidjen muar uun't uug behual",
        "watchlisttools-view": "Uun't uug behual: Feranrangen",
        "watchlisttools-edit": "Normool bewerke",
        "watchlisttools-raw": "Uun't listenformoot bewerke",
        "duplicate-defaultsort": "'''Paase üüb:''' Di sortiarkai \"$2\" auerskraft di ual sortiarkai \"$1\"",
        "version": "Werjuun",
        "version-extensions": "Instaliaret ütjwidjangen",
+       "version-skins": "Instaliaret brükerskaker",
        "version-specialpages": "Spezial-sidjen",
        "version-parserhooks": "Ütjwidjet parserfunktjuunen",
        "version-variables": "Wariaabeln",
        "version-antispam": "''Spam''seekerangen",
-       "version-skins": "Brükerskaker",
        "version-other": "Ööders wat",
        "version-mediahandlers": "Ütjwidjet medien-funktjuunen",
        "version-hooks": "Hooks",
        "version-hook-name": "Hook nööm",
        "version-hook-subscribedby": "Aprepen faan",
        "version-version": "($1)",
+       "version-no-ext-name": "[saner nööm]",
        "version-license": "MediaWiki-lisens",
        "version-ext-license": "Lisens",
        "version-ext-colheader-name": "Ütjwidjang",
+       "version-skin-colheader-name": "Skak",
        "version-ext-colheader-version": "Werjuun",
        "version-ext-colheader-license": "Lisens",
        "version-ext-colheader-description": "Beskriiwang",
        "htmlform-no": "Naan",
        "htmlform-yes": "Ja",
        "htmlform-chosen-placeholder": "Schük ütj",
+       "htmlform-cloner-create": "Muar diartudu",
+       "htmlform-cloner-delete": "Wechnem",
+       "htmlform-cloner-required": "Dü skel tumanst ään wäärs uundu.",
        "sqlite-has-fts": "Werjuun $1 mä halep för't schüken uun di hialer tekst.",
        "sqlite-no-fts": "Werjuun $1 saner halep för't schüken uun di hialer tekst.",
        "logentry-delete-delete": "$1 {{Gender:$2}} hää det sidj $3 stregen",
        "expand_templates_remove_nowiki": "<nowiki>-tags uun't resultaat ei uunwise",
        "expand_templates_generate_xml": "XML-parser-buum uunwise",
        "expand_templates_generate_rawhtml": "Rä HTML uunwise",
-       "expand_templates_preview": "Föörskau"
+       "expand_templates_preview": "Föörskau",
+       "pagelanguage": "Ütjwool faan sidjenspriaken",
+       "pagelang-name": "Sidj",
+       "pagelang-language": "Spriak",
+       "pagelang-use-default": "Standard spriak brük",
+       "pagelang-select-lang": "Spriak ütjschük",
+       "right-pagelang": "Sidjenspriak feranre",
+       "action-pagelang": "det sidjenspriak tu feranrin",
+       "log-name-pagelang": "Logbuk för spriak-feranrangen",
+       "log-description-pagelang": "Det as en logbuk för sidjenspriak-feranrangen",
+       "logentry-pagelang-pagelang": "$1 {{GENDER:$2|hää}} det sidjenspriak för $3 faan $4 tu $5 feranert."
 }
index 670f610..b15deea 100644 (file)
@@ -12,7 +12,9 @@
                        "Vipuser",
                        "Xiaomingyan",
                        "아라",
-                       "Mywood"
+                       "Mywood",
+                       "Duolaimi",
+                       "Impersonator 1"
                ]
        },
        "tog-underline": "下划链接",
        "viewsourcetext": "倷可以眵吖或复制个页𠮶源代码:",
        "protectedinterface": "个页给正嘞软件𠮶界面文本,佢拖锁到怕人乱扤。",
        "editinginterface": "'''Warning:''' You are editing a page which is used to provide interface text for the software.\nChanges to this page will affect the appearance of the user interface for other users.\nFor translations, please consider using [//translatewiki.net/wiki/Main_Page?setlang=en translatewiki.net], the MediaWiki localisation project.",
-       "cascadeprotected": "个页已拖保护,因为佢拖“联锁保护”𠮶{{PLURAL:$1|一只|几只}}拖保护页包到:\n$2",
+       "cascadeprotected": "个页已拖保护,因为佢拖“级联”𠮶{{PLURAL:$1|一只|几只}}拖保护页包到:\n$2",
        "namespaceprotected": "倷冇权编写'''$1'''空间里度𠮶页面。",
        "ns-specialprotected": "编写伓正{{ns:special}}空间𠮶页面。",
        "virus-unknownscanner": "不晓得𠮶防病毒:",
        "readonlywarning": "'''警告: 数据库锁到嘞进行定期修护,眼下倷存伓正倷𠮶改动。倷可以拿佢存到文档再著。'''",
        "protectedpagewarning": "'''警告: 个页拕锁到哩,单就管理员许可权𠮶用户才改得正。'''\n下首系供得汝参考𠮶最晏𠮶日志。",
        "semiprotectedpagewarning": "'''注意:'''个页拕锁到哩,单就注册用户编得正。\n下首系供得汝参考𠮶最晏𠮶日志。",
-       "cascadeprotectedwarning": "警告: 个页已经受保护,单只管理员权限𠮶用户才改得正,因为个页同底下𠮶连锁保护𠮶{{PLURAL:$1|一只|多只}}页面包到嘞:",
+       "cascadeprotectedwarning": "警告: 个页已经受保护,单只管理员权限𠮶用户才改得正,因为个页同底下𠮶级联保护𠮶{{PLURAL:$1|一只|多只}}页面包到嘞:",
        "titleprotectedwarning": "'''警告:个只页锁到哩,需要[[Special:ListGroupRights|指定𠮶权限]]才建立得正。'''\n下首系供得汝参考𠮶最晏𠮶日志。",
        "templatesused": "个只页面使用𠮶有{{PLURAL:$1|模板|模板}}:",
        "templatesusedpreview": "个只预览使用𠮶有{{PLURAL:$1|模板|模板}}",
        "protect-fallback": "非要“$1”𠮶许可",
        "protect-level-autoconfirmed": "禁止冇注册𠮶用户",
        "protect-level-sysop": "只限操作员",
-       "protect-summary-cascade": "联锁",
+       "protect-summary-cascade": "级联",
        "protect-expiring": "$1 (UTC)到期",
-       "protect-cascade": "保护个页含到𠮶页面 (连锁保护)",
+       "protect-cascade": "保护个页含到𠮶页面 (级联保护)",
        "protect-cantedit": "倷改伓正个页𠮶保护程度,因为倷冇搦到编辑授权。",
        "protect-expiry-options": "两个钟头:2 hours,一日:1 day,三日:3 days,一个礼拜:1 week,两个礼拜:2 weeks,一个月:1 month,三个月:3 months,六个月:6 months,一年:1 year,一世:infinite",
        "restriction-type": "权限:",
index 0eb68ef..8e18888 100644 (file)
@@ -20,7 +20,7 @@
        "tog-numberheadings": "Cuir àireamhan ri ceann-sgrìobhaidhean leis fhèin",
        "tog-showtoolbar": "Seall am bàr-inneal deasachaidh",
        "tog-editondblclick": "Tòisich air deasachadh duilleige le briogadh dùbailte",
-       "tog-editsectiononrightclick": "Cuir an comas deasachadh earrainn le briogadh deas air tiotal de dh'earrainn",
+       "tog-editsectiononrightclick": "Cuir an comas deasachadh earrainn le briogadh deas air tiotal na h-earrainn",
        "tog-watchcreations": "Cuir duilleagan a chruthaicheas mi air a' chlàr-fhaire agam",
        "tog-watchdefault": "Cuir duilleagan a dheasaicheas mi air a' chlàr-fhaire agam",
        "tog-watchmoves": "Cuir duilleagan a ghluaiseas mi air a' chlàr-fhaire agam",
@@ -48,7 +48,7 @@
        "tog-showhiddencats": "Seall na roinnean-seòrsa falaichte",
        "tog-norollbackdiff": "Na seall na diofaran às dèidh roladh air ais",
        "tog-useeditwarning": "Thoir rabhadh dhomh ma bhios mi an impis duilleag deasachaidh fhàgail mus do shàbhail mi na mùthaidhean agam",
-       "tog-prefershttps": "Cleachd ceangal tèarainte an-còmhnaidh nuair a bhios mi clàraichte a-staigh",
+       "tog-prefershttps": "Cleachd ceangal tèarainte an-còmhnaidh nuair a bhios mi air logadh a-steach",
        "underline-always": "An-còmhnaidh",
        "underline-never": "Na dèan seo idir",
        "underline-default": "Bun-roghainn a' bhrabhsair no a' chraicinn",
        "help": "Cobhair",
        "search": "Lorg",
        "searchbutton": "Lorg",
-       "go": "Rach",
-       "searcharticle": "Rach",
+       "go": "Siuthad",
+       "searcharticle": "Siuthad",
        "history": "Eachdraidh na duilleige",
        "history_short": "Eachdraidh",
        "updatedmarker": "air ùrachadh on turas mu dheireadh a thadhail mi air",
        "aboutsite": "Mu dhèidhinn {{SITENAME}}",
        "aboutpage": "Project:Mu dhèidhinn",
        "copyright": "Tha susbaint ri làimh fo $1 mur eil an caochladh 'ga innse.",
-       "copyrightpage": "{{ns:project}}:Còraichean-lethbhreac",
+       "copyrightpage": "{{ns:project}}:Còir-lethbhreac",
        "currentevents": "Cùisean an latha",
        "currentevents-url": "Project:Cùisean an latha",
        "disclaimers": "Aithrisean-àichidh",
        "filereadonlyerror": "Cha ghabh am faidhle \"$1\" atharrachadh a chionn 's gu bheil ionad-tasgaidh fhaidhlichean \"$2\" ri leughadh a-mhàin.\nThug an rianaire a ghlais e seachad an t-adhbhar a leanas: \"$3\".",
        "invalidtitle-knownnamespace": "Tiotal mì-dhligheach leis an ainm-spàs \"$2\" agus an teacsa \"$3\"",
        "invalidtitle-unknownnamespace": "Tiotal mì-dhligheach leis an àireamh ainm-spàis $1 agus an teacsa \"$2\"",
-       "exception-nologin": "Chan eil thu air clàradh a-steach",
-       "exception-nologin-text": "Feumaidh tu [[Special:Userlogin|clàradh a-steach]] mus fhaic thu an duilleag seo no mus urrainn dhut seo a dhèanamh.",
+       "exception-nologin": "Chan eil thu air logadh a-steach",
+       "exception-nologin-text": "Feumaidh tu [[Special:Userlogin|logadh a-steach]] mus fhaic thu an duilleag seo no mus urrainn dhut seo a dhèanamh.",
        "exception-nologin-text-manual": "Ma tha thu ag iarraidh cothrom air an duilleag no air a' ghnìomh seo, $1.",
        "virus-badscanner": "Droch cho-dhealbhachd: sganair bhìorasan neo-aithnichte: <em>$1</em>",
        "virus-scanfailed": "dh'fhàillig an sganadh (còd $1)",
        "virus-unknownscanner": "sganair bhìorasan neo-aithnichte:",
-       "logouttext": "<strong>Chaidh do chlàradh a-mach.</strong>\n\nThoir an aire gum bi coltas air cuid dhe na duilleagan mar gum biodh tu air clàradh a-steach gus am falamhaich thu tasgadan a' bhrabhsair agad.",
+       "logouttext": "<strong>Chaidh do logadh a-mach.</strong>\n\nThoir an aire gum bi coltas air cuid dhe na duilleagan mar gum biodh tu air logadh a-steach gus am falamhaich thu tasgadan a' bhrabhsair agad.",
        "welcomeuser": "Fàilte ort, $1",
        "welcomecreation-msg": "Chaidh an cunntas agad a chruthachadh.\nNa dìochuimhnich na [[Special:Preferences|roghainnean agad air {{SITENAME}}]] a ghleusadh dhut fhèin.",
        "yourname": "Ainm-cleachdaiche:",
        "userlogin-yourname": "Ainm-cleachdaiche",
        "userlogin-yourname-ph": "Cuir a-steach an t-ainm-cleachdaiche agad",
        "createacct-another-username-ph": "Cuir a-steach an t-ainm-cleachdaiche",
-       "yourpassword": "Am facal-faire agad",
+       "yourpassword": "Facal-faire:",
        "userlogin-yourpassword": "Facal-faire",
        "userlogin-yourpassword-ph": "Cuir a-steach am facal-faire agad",
        "createacct-yourpassword-ph": "Cuir a-steach facal-faire",
        "createacct-yourpasswordagain": "Dearbh am facal-faire",
        "createacct-yourpasswordagain-ph": "Cuir a-steach am facal-faire a-rithist",
        "remembermypassword": "Cuimhnich gu bheil mi air logadh a-steach air a' choimpiutair seo (suas gu $1 {{PLURAL:$1|latha|latha|làithean|latha}})",
-       "userlogin-remembermypassword": "Cum clàraichte a-staigh mi",
+       "userlogin-remembermypassword": "Cum air logadh a-steach mi",
        "userlogin-signwithsecure": "Cleachd ceangal tèarainte",
        "yourdomainname": "An àrainn-lìn agad:",
        "password-change-forbidden": "Chan urrainn dhut faclan-faire atharrachadh air an uicipeid seo.",
        "gotaccountlink": "Log a-steach",
        "userlogin-resetlink": "Na dhìochuimhnich thu d' ainm is facal-faire?",
        "userlogin-resetpassword-link": "Na dhìochuimhnich thu am facal-faire agad?",
-       "userlogin-helplink2": "Taic le clàradh a-steach",
-       "userlogin-loggedin": "Chaidh do chlàradh mar $1 mu thràth.\nCleachd am foirm gu h-ìosal airson clàradh a-steach mar chleachdaiche eile.",
+       "userlogin-helplink2": "Taic le logadh a-steach",
+       "userlogin-loggedin": "Chaidh do logadh a-steach mar $1 mu thràth.\nCleachd am foirm gu h-ìosal airson logadh a-steach mar chleachdaiche eile.",
        "userlogin-createanother": "Cruthaich cunntas eile",
        "createacct-emailrequired": "Seòladh puist-d",
        "createacct-emailoptional": "Seòladh puist-d (roghainneil)",
        "password-login-forbidden": "Tha an t-ainm-cleachdaiche 's am facal-faire seo toirmisgte.",
        "mailmypassword": "Ath-shuidhich am facal-faire",
        "passwordremindertitle": "Facal-faire sealach ùr airson {{SITENAME}}",
-       "passwordremindertext": "Dh'iarr cuideigin ('s mathaid gun do dh'iarr thusa seo on t-seòladh IP $1) facal-faire ùr airson {{SITENAME}} ($4). Chaidh facal-faire sealach a chruthachadh airson \"$2\" a tha 'na \"$3\".\nMa bha sin fa-near dhut, bidh agad ri clàradh a-steach agus facal-faire ùr a thaghadh\nan-dràsta fhèin. Falbhaidh an ùine air an fhacal-fhaire sealach agad ann an {{PLURAL:$5|$5 latha|$5 latha|$5 làithean|$5 latha}}.\n\nMa dh'iarr cuideigin eile seo no ma chuimhnich thu am facal-faire agad 's mur eil thu\nairson atharrachadh tuilleadh, 's urrainn dhut an teachdaireachd seo a leigeil seachad\nagus leantainn ort leis an t-seann fhacal-faire.",
+       "passwordremindertext": "Dh'iarr cuideigin ('s mathaid gun do dh'iarr thusa seo on t-seòladh IP $1) facal-faire ùr airson {{SITENAME}} ($4). Chaidh facal-faire sealach a chruthachadh airson \"$2\" a tha 'na \"$3\".\nMa bha sin fa-near dhut, bidh agad ri logadh a-steach agus facal-faire ùr a thaghadh\nan-dràsta fhèin. Falbhaidh an ùine air an fhacal-fhaire sealach agad ann an {{PLURAL:$5|$5 latha|$5 latha|$5 làithean|$5 latha}}.\n\nMa dh'iarr cuideigin eile seo no ma chuimhnich thu am facal-faire agad 's mur eil thu\nairson atharrachadh tuilleadh, 's urrainn dhut an teachdaireachd seo a leigeil seachad\nagus leantainn ort leis an t-seann fhacal-faire.",
        "noemail": "Cha deach post-d a chlàradh airson a' chleachdaiche \"$1\".",
        "noemailcreate": "Feumaidh tu post-d dligheach a chur ann",
-       "passwordsent": "Chaidh facal-faire ùr a chur dhan phost-d a chaidh a chlàradh airson \"$1\".\nClàraich a-steach a-rithist nuair a gheibh thu e.",
+       "passwordsent": "Chaidh facal-faire ùr a chur dhan phost-d a chaidh a chlàradh airson \"$1\".\nDèan logadh a-steach a-rithist nuair a gheibh thu e.",
        "blocked-mailpassword": "Chaidh bacadh a chur air an t-seòladh IP agad 's chan eil cead deasachaidh agad agus chan urrainn dhut an gleus a chum aiseag an fhacail-fhaire a chleachdadh gus casg a chur air mì-ghnàthachadh.",
        "eauthentsent": "Chaidh post-d dearbhaidh a chur dhan phost-d a chaidh ainmeachadh.\nMus dèid post-d sam bith eile a chur dhan chunntas, feumaidh tu leantainn ris an stiùireadh sa phost-d mar dhearbhadh gur ann agadsa a tha an cunntas.",
        "throttled-mailpassword": "Chaidh post-d a chur airson ath-shuidheachadh facail-fhaire mu thràth $1 {{PLURAL:$1|uair|uair|uairean|uair}} a thìde air ais.\nGus casg a chur air mì-ghnàthachadh, cha chuir sinn ach aon chuimhneachan facail-fhaire gach $1 {{PLURAL:$1|uair|uair|uairean|uair}} a thìde.",
        "accountcreated": "Cunntas cruthaichte",
        "accountcreatedtext": "Chaidh an cunntas cleachdaiche airson [[{{ns:User}}:$1|$1]] ([[{{ns:User talk}}:$1|na deasbaireachd]]) a chruthachadh.",
        "createaccount-title": "Cruthachadh cunntais airson {{SITENAME}}",
-       "createaccount-text": "Chruthaich cuideigin cunntas airson a' phost-d agad air {{SITENAME}} ($4) air a bheil \"$2\", leis an fhacal-fhaire \"$3\".\nBu chòir dhut clàradh a-steach agus am facal-faire agad atharrachadh gu h-ìosal an-dràsta.\n\n'S urrainn dhut an teachdaireachd seo a leigeil seachad ma chaidh an cunntas a chruthachadh air mhearachd.",
-       "login-throttled": "Dh'fheuch thu ri clàradh a-steach ro thric o chionn ghoirid.\nFuirich ort $1 mus feuch thu ris a-rithist.",
-       "login-abort-generic": "Cha do shoirbhich leat leis a' chlàradh a-steach - Chaidh sgur dheth",
+       "createaccount-text": "Chruthaich cuideigin cunntas airson a' phost-d agad air {{SITENAME}} ($4) air a bheil \"$2\", leis an fhacal-fhaire \"$3\".\nBu chòir dhut logadh a-steach agus am facal-faire agad atharrachadh gu h-ìosal an-dràsta.\n\n'S urrainn dhut an teachdaireachd seo a leigeil seachad ma chaidh an cunntas a chruthachadh air mhearachd.",
+       "login-throttled": "Dh'fheuch thu ri logadh a-steach ro thric o chionn ghoirid.\nFuirich ort $1 mus feuch thu ris a-rithist.",
+       "login-abort-generic": "Cha do shoirbhich leat leis an logadh a-steach - Chaidh sgur dheth",
        "loginlanguagelabel": "Cànan: $1",
-       "suspicious-userlogout": "Chaidh d' iarrtas airson clàradh a-mach a dhiùltadh a chionn 's gu bheil coltas gun deach a chur le brabhsair briste no le progsaidh tasglannaidh.",
+       "suspicious-userlogout": "Chaidh d' iarrtas airson logadh a-mach a dhiùltadh a chionn 's gu bheil coltas gun deach a chur le brabhsair briste no le progsaidh tasglannaidh.",
        "createacct-another-realname-tip": "Cha leig thu leas innse dè am fìor-ainm a tha ort.\nMa bheir thu seachad e, thèid seo a chleachdadh gus urram a thoirt dha na h-ùghdaran airson an cuid obrach.",
        "pt-login": "Log a-steach",
        "pt-login-button": "Log a-steach",
        "user-mail-no-addy": "Cha do ghabh am post-d a chur leis nach robh seòladh puist-d ann.",
        "user-mail-no-body": "Bha bodhaig na teachdaireachd bàn no air leth goirid.",
        "changepassword": "Atharraich facal-faire",
-       "resetpass_announce": "Gus an clàradh a-steach a choileanadh, tha agad ri facal-faire ùr a shuidheachadh.",
+       "resetpass_announce": "Gus an logadh a-steach a choileanadh, tha agad ri facal-faire ùr a shuidheachadh.",
        "resetpass_text": "<!-- Cuir teacsa an-seo -->",
        "resetpass_header": "Atharraich facal-faire a' chunntais",
        "oldpassword": "Seann fhacal-faire",
        "newpassword": "Facal-faire ùr",
        "retypenew": "Ath-sgrìobh am facal-faire ùr",
-       "resetpass_submit": "Suidhich am facal-faire 's clàraich a-steach",
+       "resetpass_submit": "Suidhich am facal-faire 's dèan logadh a-steach",
        "changepassword-success": "Chaidh am facal-faire agad atharrachadh!",
-       "changepassword-throttled": "Dh'fheuch thu ri clàradh a-steach ro thric o chionn ghoirid.\nFuirich ort $1 mus feuch thu ris a-rithist.",
+       "changepassword-throttled": "Dh'fheuch thu ri logadh a-steach ro thric o chionn ghoirid.\nFuirich ort $1 mus feuch thu ris a-rithist.",
        "resetpass_forbidden": "Cha ghabh na faclan-faire atharrachadh",
-       "resetpass-no-info": "Feumaidh tu clàradh a-steach mus dèan thu inntrigeadh dìreach dhan duilleag seo.",
+       "resetpass-no-info": "Feumaidh tu logadh a-steach mus dèan thu inntrigeadh dìreach dhan duilleag seo.",
        "resetpass-submit-loggedin": "Atharraich am facal-faire",
        "resetpass-submit-cancel": "Sguir dheth",
        "resetpass-wrong-oldpass": "Tha am facal-faire sealach no làithreach mì-dhligheach.\nSaoil an do dh'atharraich thu am facal-faire agad mu thràth no an do dh'iarr thu facal-faire sealach ùr?",
        "resetpass-recycled": "Tagh facal-faire ùr nach eil co-ionnann ris an fhacal-fhaire a tha agad an-dràsta.",
-       "resetpass-temp-emailed": "Rinn thu clàradh a-steach le còd sealach a fhuair thu air a' phost-d.\nAirson clàradh a-steach slàn a dhèanamh, feumaidh tu facal-faire ùr a shuidheachadh an-seo:",
+       "resetpass-temp-emailed": "Rinn thu logadh a-steach le còd sealach a fhuair thu air a' phost-d.\nAirson logadh a-steach slàn a dhèanamh, feumaidh tu facal-faire ùr a shuidheachadh an-seo:",
        "resetpass-temp-password": "Facal-faire sealach:",
        "resetpass-abort-generic": "Chuir leudachan crìoch air atharrachadh an fhacail-fhaire.",
-       "resetpass-expired": "Dh'fhalbh an ùine air an fhacal-fhaire agad. Suidhich facal-faire ùr airson clàradh a-steach.",
+       "resetpass-expired": "Dh'fhalbh an ùine air an fhacal-fhaire agad. Suidhich facal-faire ùr airson logadh a-steach.",
        "resetpass-expired-soft": "Dh'fhalbh an ùine air an fhacal-fhaire agad is feumaidh tu ath-shuidheachadh. Tagh fear ùr no briog air \"{{int:resetpass-submit-cancel}}\" gus ath-shuidheachadh às a dhèidh seo.",
        "resetpass-validity-soft": "Chan eil am facal-faire seo dligheach: $1\n\nTagh facal-faire ùr an-dràsta no briog air \"{{int:resetpass-submit-cancel}}\" gus ath-shuidheachadh às a dhèidh seo.",
        "passwordreset": "Ath-shuidhich am facal-faire",
        "passwordreset-capture-help": "Ma chuireas tu cromag sa bhogsa seo, chì thusa am post-d (leis an fhacal-fhaire sealach) agus gheibh an cleachdaiche e cuideachd.",
        "passwordreset-email": "Seòladh puist-d:",
        "passwordreset-emailtitle": "Dàta a' chunntais air {{SITENAME}}",
-       "passwordreset-emailtext-ip": "Dh'iarr cuideigin (thu fhèin, 's mathaid, on t-seòladh IP $1) am facal-faire airson {{SITENAME}} ($4) ath-shuidheachadh. Tha {{PLURAL:$3|an cunntas|na cunntasan}} a leanas co-cheangailte ris a' phost-d seo:\n\n$2\n\nFalbhaidh an ùine air {{PLURAL:$3|an fhacal-fhaire shealach|na faclan-faire sealach}} seo an ceann $5 {{PLURAL:$5|latha|latha|làithean|latha}}.\nBu chòir dhut clàradh a-steach agus facal-faire ùr a thaghadh an-dràsta. Ma dh'iarr cuideigin eile seo no ma chuimhnich thu air an fhacal-fhaire agad 's mur eil thu airson atharrachadh tuilleadh, leig seachad an teachdaireachd seo 's lean ort leis an t-seann fhacal-fhaire.",
-       "passwordreset-emailtext-user": "Dh'iarr an cleachdaiche $1 air {{SITENAME}} ath-shuidheachadh an fhacail-fhaire air {{SITENAME}} ($4). Tha {{PLURAL:$3|an cunntas-cleachdaiche|na cunntasan-cleachdaiche}} a leanas co-cheangailte ris an t-seòladh puist-d seo:\n\n$2\n\nFalbhaidh an ùine air {{PLURAL:$3|an fhacal-fhaire shealach|na faclan-faire sealach}} seo an ceann $5 {{PLURAL:$5|latha|latha|làithean|latha}}.\nBu chòir dhut clàradh a-steach agus facal-faire ùr a thaghadh an-dràsta. Ma dh'iarr cuideigin eile seo no ma chuimhnich thu air an fhacal-fhaire agad 's mur eil thu airson atharrachadh tuilleadh, leig seachad an teachdaireachd seo 's lean ort leis an t-seann fhacal-fhaire.",
+       "passwordreset-emailtext-ip": "Dh'iarr cuideigin (thu fhèin, 's mathaid, on t-seòladh IP $1) am facal-faire airson {{SITENAME}} ($4) ath-shuidheachadh. Tha {{PLURAL:$3|an cunntas|na cunntasan}} a leanas co-cheangailte ris a' phost-d seo:\n\n$2\n\nFalbhaidh an ùine air {{PLURAL:$3|an fhacal-fhaire shealach|na faclan-faire sealach}} seo an ceann $5 {{PLURAL:$5|latha|latha|làithean|latha}}.\nBu chòir dhut logadh a-steach agus facal-faire ùr a thaghadh an-dràsta. Ma dh'iarr cuideigin eile seo no ma chuimhnich thu air an fhacal-fhaire agad 's mur eil thu airson atharrachadh tuilleadh, leig seachad an teachdaireachd seo 's lean ort leis an t-seann fhacal-fhaire.",
+       "passwordreset-emailtext-user": "Dh'iarr an cleachdaiche $1 air {{SITENAME}} ath-shuidheachadh an fhacail-fhaire air {{SITENAME}} ($4). Tha {{PLURAL:$3|an cunntas-cleachdaiche|na cunntasan-cleachdaiche}} a leanas co-cheangailte ris an t-seòladh puist-d seo:\n\n$2\n\nFalbhaidh an ùine air {{PLURAL:$3|an fhacal-fhaire shealach|na faclan-faire sealach}} seo an ceann $5 {{PLURAL:$5|latha|latha|làithean|latha}}.\nBu chòir dhut logadh a-steach agus facal-faire ùr a thaghadh an-dràsta. Ma dh'iarr cuideigin eile seo no ma chuimhnich thu air an fhacal-fhaire agad 's mur eil thu airson atharrachadh tuilleadh, leig seachad an teachdaireachd seo 's lean ort leis an t-seann fhacal-fhaire.",
        "passwordreset-emailelement": "Ainm-cleachdaiche: $1\nFacal-faire sealach: $2",
        "passwordreset-emailsent": "Chaidh post-d airson ath-shuidheachadh an fhacail-fhaire a chur.",
        "passwordreset-emailsent-capture": "Chaidh post-d a chum ath-shuidheachadh an fhacail-fhaire a chur agus chì thu sin gu h-ìosal.",
        "changeemail": "Atharraich am post-d",
        "changeemail-header": "Atharraich cunntas a' phuist-d",
        "changeemail-text": "Lìon am foirm seo gus am post-d agad atharrachadh. Feumaidh tu am facal-faire agad a chur a-steach a-rithist gus a dhearbhadh.",
-       "changeemail-no-info": "Feumaidh tu clàradh a-steach mus dèan thu inntrigeadh dìreach dhan duilleag seo.",
+       "changeemail-no-info": "Feumaidh tu logadh a-steach mus dèan thu inntrigeadh dìreach dhan duilleag seo.",
        "changeemail-oldemail": "An seòladh puist-d làithreach:",
        "changeemail-newemail": "An seòladh puist-d ùr:",
        "changeemail-none": "(chan eil gin)",
        "changeemail-password": "Am facal-faire agad air {{SITENAME}}:",
        "changeemail-submit": "Atharraich am post-d",
        "changeemail-cancel": "Sguir dheth",
-       "changeemail-throttled": "Dh'fheuch thu ri clàradh a-steach ro thric.\nFuirich ort $1 mus feuch thu ris a-rithist.",
+       "changeemail-throttled": "Dh'fheuch thu ri logadh a-steach ro thric.\nFuirich ort $1 mus feuch thu ris a-rithist.",
        "resettokens": "Ath-shuidhich na tòcanan",
        "resettokens-text": "'S urrainn dhut tòcanan ath-shuidheachadh a bheir cothrom dhut air cuid a dhàta prìobhaideach a tha co-cheangailte ris a' chunntas agad.\n\nBu chòir dhut seo a dhèanamh ma thug thu do chuideigin e air mhearachd no ma bhris cuideigin a-steach air a' chunntas agad.",
        "resettokens-no-tokens": "Chan eil tòcan ann a ghabhas ath-shuidheachadh.",
        "preview": "Ro-shealladh",
        "showpreview": "Seall an ro-shealladh",
        "showdiff": "Seall na mùthaidhean",
-       "anoneditwarning": "<strong>Rabhadh:</strong> Chan eil thu air logadh a-steach.\nThèid an seòladh IP agad a chlàrachadh ann an eachdraidh na duilleige seo.",
-       "anonpreviewwarning": "<em>Chan eil thu air clàradh a-steach. Ma nì thu sàbhaladh, thèid an seòladh IP agad a chlàradh ann an eachdraidh deasachadh na duilleige seo.</em>",
+       "anoneditwarning": "<strong>Rabhadh:</strong> Chan eil thu air logadh a-steach.\nThèid an seòladh IP agad a chlàradh ann an eachdraidh na duilleige seo.",
+       "anonpreviewwarning": "<em>Chan eil thu air logadh a-steach. Ma nì thu sàbhaladh, thèid an seòladh IP agad a chlàradh ann an eachdraidh deasachadh na duilleige seo.</em>",
        "missingsummary": "<strong>Cuimhnich:</strong> Cha dug thu seachad gearr-chunntas air na dh'atharraich thu.\nMa bhriogas tu air \"{{int:savearticle}}\" a-rithist, thèid na dheasaich thu a shàbhaladh as aonais gearr-chunntais.",
        "missingcommenttext": "Cuir a-steach beachd gu h-ìosal.",
        "missingcommentheader": "<strong>Cuimhnich:</strong> Cha dug thu seachad cuspair/ceann airson a' bheachd seo.\nMa bhriogas tu air \"{{int:savearticle}}\" a-rithist, thèid na dheasaich thu a shàbhaladh as aonais.",
        "confirmedittext": "Feumaidh tu am post-d agad a dhearbhadh mus urrainn dhut duilleagan a dheasachadh.\nSuidhich is dearbhaich am post-d agad ann an [[Special:Preferences|roghainnean a' chleachdaiche]]",
        "nosuchsectiontitle": "Cha ghabh an earrann a lorg",
        "nosuchsectiontext": "Dh'fheuch thu ri earrann a dheasachadh nach eil ann.\nDh'fhaoidte gun deach a ghluasad no a sguabadh às fhad 's a bha thu a' coimhead air an duilleag.",
-       "loginreqtitle": "Feumaidh tu clàradh a-steach",
+       "loginreqtitle": "Feumaidh tu logadh a-steach",
        "loginreqlink": "log a-steach",
        "loginreqpagetext": "Feumaidh tu $1 mus urrainn dhut coimhead air duilleagan eile.",
        "accmailtitle": "Facal-faire air a chur.",
-       "accmailtext": "Chaidh facal-faire a chruthachadh air thuaiream airson [[User talk:$1|$1]] 's a chur gu $2.\n\nGabhaidh am facal-faire airson a' chunntais ùir seo atharrachadh air an fo <em>[[Special:ChangePassword|atharraich facal-faire]]</em> às dèidh dhan chleachdaiche clàradh a-steach.",
+       "accmailtext": "Chaidh facal-faire a chruthachadh air thuaiream airson [[User talk:$1|$1]] 's a chur gu $2.\n\nGabhaidh am facal-faire airson a' chunntais ùir seo atharrachadh air an fo <em>[[Special:ChangePassword|atharraich facal-faire]]</em> às dèidh dhan chleachdaiche logadh a-steach.",
        "newarticle": "(Ùr)",
        "newarticletext": "Lean thu ri ceangal gu duilleag nach eil ann fhathast.\nCuir teacs sa bhogsa gu h-ìosal gus an duilleag seo a chruthachadh (seall air [$1 duilleag na cobharach] airson barrachd fiosrachaidh).\nMura robh dùil agad ris an duilleag seo a ruigsinn, briog air a' phutan <strong>air ais</strong> 'nad bhrabhsair.",
-       "anontalkpagetext": "----\n<em>Seo an duilleag deasbaireachd aig cleachdaiche gun urra nach do chruthaich cunntas fhathast no nach eil 'ga chleachdadh.</em>\nFeumaidh sinn an àireamh IP aca a chleachdadh air sgàth sin.\nFaodadh grunn chleachdaichean seòladh IP mar a chleachdadh còmhla.\nMas e cleachdaiche gun urra a tha annad 's ma tha thu dhen bheachd nach eil na beachdan seo a' buntainn riut, nach [[Special:UserLogin/signup|clàraich thu]] no [[Special:UserLogin|clàraich a-steach]] gus bùrach mar seo a sheachnadh san àm ri teachd?",
+       "anontalkpagetext": "----\n<em>Seo an duilleag deasbaireachd aig cleachdaiche gun urra nach do chruthaich cunntas fhathast no nach eil 'ga chleachdadh.</em>\nFeumaidh sinn an àireamh IP aca a chleachdadh air sgàth sin.\nFaodadh grunn chleachdaichean seòladh IP mar a chleachdadh còmhla.\nMas e cleachdaiche gun urra a tha annad 's ma tha thu dhen bheachd nach eil na beachdan seo a' buntainn riut, nach [[Special:UserLogin/signup|clàraich thu]] no nach dèan thu [[Special:UserLogin|logadh a-steach]] gus bùrach mar seo a sheachnadh san àm ri teachd?",
        "noarticletext": "Chan eil teacsa sam bith anns an duilleag seo an-dràsta.\n'S urrainn dhut [[Special:Search/{{PAGENAME}}|an tiotal seo a lorg]] ann an duilleagan eile,\n<span class=\"plainlinks\">[{{fullurl:{{#Special:Log}}|page={{FULLPAGENAMEE}}}} na logaichean co-cheangailte a rannsachadh],\nno [{{fullurl:{{FULLPAGENAME}}|action=edit}} an duilleag seo a dheasachadh]</span>.",
        "noarticletext-nopermission": "Chan eil teacsa sam bith san duilleag seo an-dràsta.\n'S urrainn dhut [[Special:Search/{{PAGENAME}}|tiotal na duilleige seo a lorg]] ann an duilleagan eile, no <span class=\"plainlinks\">[{{fullurl:{{#Special:Log}}|page={{FULLPAGENAMEE}}}} na logaichean co-cheangailte a rannsachadh]</span> ach chan eil cead agad an duilleag seo a chruthachadh.",
        "missing-revision": "Chan eil mùthadh #$1 na duilleige \"{{FULLPAGENAME}}\" ann.\n\nMar is trice, tachraidh seo ma leanas tu ceangal san eachdraidh a tha fìor aosta 's a tha a' dol gu duilleag a chaidh a sguabadh às.\nGheibh thu mion-fhiosrachadh ann an [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} loga nan duilleagan a chaidh a sguabadh às].",
        "previewnote": "<strong>Cuimhnich nach eil ann ach ro-shealladh.</strong>\nCha deach na mùthaidhean agad a shàbhaladh fhathast!",
        "continue-editing": "Rach gun raon deasachaidh",
        "previewconflict": "Tha an ro-shealladh seo a' sealltainn dhut an teacsa san raon teacsa gu h-àrd mar a nochdas e ma shàbhaileas tu an-dràsta.",
-       "session_fail_preview": "<strong>Duilich! Cha b' urrainn dhuinn na dheasaich thu a làimhseachadh air sgàth call dàta an t-seisein.</strong>\nNach fheuch thu ris a-rithist?\nMur obraich e fhathast, feuch is [[Special:UserLogout|clàraich a-mach]] is a-steach a-rithist an uairsin.",
-       "session_fail_preview_html": "<strong>Duilich! Cha b' urrainn dhuinn na dheasaich thu a làimhseachadh air sgàth call dàta an t-seisein.</strong>\n\n<em>A chionn 's gun do chuir {{SITENAME}} còd HTML an comas, tha an ro-shealladh falaichte mar dhìon an aghaidh ionnsaighean JavaScript.</em>\n\n<strong>Mas e deasachadh dligheach a tha seo, feuch ris a-rithist.</strong>\nMur obraich e fhathast, feuch is [[Special:UserLogout|clàraich a-mach]] is a-steach a-rithist an uairsin.",
+       "session_fail_preview": "<strong>Duilich! Cha b' urrainn dhuinn na dheasaich thu a làimhseachadh air sgàth call dàta an t-seisein.</strong>\nNach fheuch thu ris a-rithist?\nMur obraich e fhathast, feuch is [[Special:UserLogout|log a-mach]] is a-steach a-rithist an uairsin.",
+       "session_fail_preview_html": "<strong>Duilich! Cha b' urrainn dhuinn na dheasaich thu a làimhseachadh air sgàth call dàta an t-seisein.</strong>\n\n<em>A chionn 's gun do chuir {{SITENAME}} còd HTML an comas, tha an ro-shealladh falaichte mar dhìon an aghaidh ionnsaighean JavaScript.</em>\n\n<strong>Mas e deasachadh dligheach a tha seo, feuch ris a-rithist.</strong>\nMur obraich e fhathast, feuch is dèan [[Special:UserLogout|logadh a-mach]] is a-steach a-rithist an uairsin.",
        "token_suffix_mismatch": "<strong>Dhiùlt sinn na dheasaich thu a chionn 's gun do chuir an cliant agad na caractaran puingeachaidh tro chèile san tòcan deasachaidh.</strong>\nDhiùlt sinn na dheasaich thu air eagal 's gun coirbeadh e teacsa na duilleige.\nTachraidh seo uaireannan ma chleachdar seirbheis-lìn progsaidh gun urra a tha làn de mhearachdan.",
        "edit_form_incomplete": "<strong>Cha do ràinig cuid dhen fhoirm deasachaidh am frithealaichte; dèan cinnteach gu bheil gach deasachadh agad slàn is feuch ris a-rithist.</strong>",
        "editing": "A' deasachadh $1",
        "protectedpagewarning": "<strong>Rabhadh: Chaidh an duilleag seo a dhìon 's chan urrainn ach dhan fheadhainn aig a bheil ùghdarras rianaire a dheasachadh.</strong>\nChì thu an clàr mu dheireadh san loga mar fhiosrachadh dhut gu h-ìosal:",
        "semiprotectedpagewarning": "<strong>An aire:</strong> Chaidh an duilleag seo a dhìon 's chan fhaod ach cleachdaichean clàraichte a dheasachadh.\nSeo an rud mu dheireadh san loga mar fhiosrachadh dhut:",
        "cascadeprotectedwarning": "<strong>Rabhadh:</strong> Chaidh an duilleag seo a dhìon 's chan fhaod ach rianairean a dheasachadh a chionn 's gun robh e am broinn {{PLURAL:$1|na duilleige|nan duilleagan}} a leanas a tha dìonta o bhith mar eas.",
-       "titleprotectedwarning": "<strong>Rabhadh: Chaidh an duilleag seo a dhìon 's feumar [[Special:ListGroupRights|còraichean sònraichte]] gus a dheasachadh.</strong>\nSeo an rud mu dheireadh san loga mar fhiosrachadh dhut:",
+       "titleprotectedwarning": "<strong>Rabhadh: Chaidh an duilleag seo a dhìon 's feumar [[Special:ListGroupRights|ceadan sònraichte]] gus a dheasachadh.</strong>\nSeo an rud mu dheireadh san loga mar fhiosrachadh dhut:",
        "templatesused": "Tha {{PLURAL:$1|teamplaid 'ga cleachdadh|teamplaidean 'gan cleachdadh}} air an duilleag seo:",
        "templatesusedpreview": "Tha {{PLURAL:$1|teamplaid 'ga cleachdadh|teamplaidean 'gan cleachdadh}} san ro-shealladh seo:",
        "templatesusedsection": "Tha {{PLURAL:$1|teamplaid 'ga cleachdadh|teamplaidean 'gan cleachdadh}} san earrann seo:",
        "hiddencategories": "Tha an duilleag seo 'na ball de {{PLURAL:$1|$1 roinn-seòrsa fhalaichte|$1 roinn-seòrsa fhalaichte|$1 roinnean-seòrsa falaichte|$1 roinn-seòrsa fhalaichte}}:",
        "edittools": "<!-- Nochdaidh an teacsa seo fo fhoirmean deasachaidh 's luchdaidh suas. -->",
        "edittools-upload": "-",
-       "nocreatetext": "Chuir {{SITENAME}} bacadh air cruthachadh de dhuilleagan ùra.\n'S urrainn dhut tilleadh is duilleag a tha ann mu thràth a dheasachadh no [[Special:UserLogin|clàradh a-steach no cunntas a chruthachadh]].",
+       "nocreatetext": "Chuir {{SITENAME}} bacadh air cruthachadh de dhuilleagan ùra.\n'S urrainn dhut tilleadh is duilleag a tha ann mu thràth a dheasachadh no [[Special:UserLogin|logadh a-steach no cunntas a chruthachadh]].",
        "nocreate-loggedin": "Chan eil cead agad duilleagan ùra a chruthachadh.",
        "sectioneditnotsupported-title": "Chan eil taic ri deasachadh earrannan",
        "sectioneditnotsupported-text": "Chan eil taic ri deasachadh earrannan air an duilleag seo.",
        "mergehistory-empty": "Chan eil mùthadh sam bith ann a ghabhas a cho-aonadh.",
        "mergehistory-success": "Chaidh $3 {{PLURAL:$3|mhùthadh|mhùthadh|mùthaidhean|mùthadh}} air [[:$1]] a cho-aonadh dha [[:$2]].",
        "mergehistory-fail": "Cha ghabh an eachdraidh a cho-aonadh, thoir sùil air paramadairean na duilleige 's an ama.",
+       "mergehistory-fail-toobig": "Cha b' urrainn dhuinn an eachdraidh a cho-aonachadh on a bhiodh barrachd na tha ceadaichte de $1 {{PLURAL:$1|mhùthadh|mhùthadh|mùthaidhean|mùthadh}} a ghluasad.",
        "mergehistory-no-source": "Chan eil an tùs-duilleag $1 ann.",
        "mergehistory-no-destination": "Chan eil an an duilleag targaide $1 ann.",
        "mergehistory-invalid-source": "Feumaidh an tùs-duilleag a bhith 'na thiotal dligheach.",
        "datedefault": "Gun roghainnean",
        "prefs-labs": "Feartan nan deuchainn-lannan",
        "prefs-user-pages": "Duilleagan a' chleachdaiche",
-       "prefs-personal": "Pròifil a' chleachdaiche",
+       "prefs-personal": "Pròifil",
        "prefs-rc": "Mùthaidhean ùra",
        "prefs-watchlist": "An clàr-faire",
        "prefs-watchlist-days": "Co mheud latha a sheallar air a' chlàr-fhaire:",
        "prefs-rendering": "Coltas",
        "saveprefs": "Sàbhail",
        "restoreprefs": "Aisig na roghainnean bunaiteach uile (anns gach earrann)",
-       "prefs-editing": "A' deasachadh",
+       "prefs-editing": "Deasachadh",
        "rows": "Sreathan",
        "columns": "Colbhan",
        "searchresultshead": "Lorg",
        "prefs-memberingroups-type": "$1",
        "prefs-registration": "Àm clàraidh:",
        "prefs-registration-date-time": "$1",
-       "yourrealname": "An dearbh ainm a th' ort:",
+       "yourrealname": "D' fhìor-ainm:",
        "yourlanguage": "Cànan:",
        "yourvariant": "Eug-samhail cànan na susbaint:",
        "prefs-help-variant": "Do roghainn eug-samhail sgrìobhaidh a thèid duilleagan na h-uicipeid seo a shealltainn innte.",
        "prefs-help-signature": "Bu chòir dhut d' ainm a chur ri beachdan air duilleagan deasbaireachd le \"<nowiki>~~~~</nowiki>\" agus chithear d' ainm agus stampa ama 'na àite an uairsin.",
        "badsig": "Tha co-chàradh an t-soidhnidh mì-dhligheach.\nThoir sùil air na tagaichean HTML.",
        "badsiglength": "Tha an t-earr-sgrìobhadh agad ro fhada.\nChan fhaod e a bhith nas fhaide na $1 {{PLURAL:$1|charactar|charactar|caractaran|caractar}}.",
-       "yourgender": "Dè a' ghnè a tha annad:",
+       "yourgender": "Do ghnè:",
        "gender-unknown": "B' fhearr leam gun a bhith 'ga leigeil ris",
        "gender-male": "Deasaichidh e duilleagan na h-uicidh",
        "gender-female": "Deasaichidh i duilleagan na h-Uicipeid",
        "right-passwordreset": "Cead gus puist-d ath-shuidheachadh nam facal-faire a shealltainn",
        "newuserlogpage": "Loga cruthachadh nan cleachdaichean",
        "newuserlogpagetext": "Seo loga nan cleachdaichean a chaidh a chruthachadh.",
-       "rightslog": "Loga còraichean a' chleachdaiche",
+       "rightslog": "Loga ceadan a' chleachdaiche",
        "rightslogtext": "Seo loga nan atharraichean air ceadan nan cleachdaichean.",
        "action-read": "leugh an duilleag seo",
        "action-edit": "deasaich an duilleag seo",
        "recentchangeslinked-feed": "Mùthaidhean buntainneach",
        "recentchangeslinked-toolbox": "Mùthaidhean buntainneach",
        "recentchangeslinked-title": "Mùthaidhean co-cheangailte ri \"$1\"",
-       "recentchangeslinked-summary": "Seo liosta nam mùthaidhean a chaidh a chur air duilleagan a tha a' ceangal o dhuilleag shònraichte (no ri buill ann an roinn-seòrsa sònraichte).\nTha duilleagan air [[Special:Watchlist|do chlàr-faire]] ann an litrichean <strong>troma</strong>.",
+       "recentchangeslinked-summary": "Seo liosta nam mùthaidhean a chaidh a chur air duilleagan a tha a' ceangal o dhuilleag shònraichte (no ri buill ann an roinn-seòrsa sònraichte).\nTha duilleagan air a' [[Special:Watchlist|chlàr-fhaire]] agad ann an litrichean <strong>troma</strong>.",
        "recentchangeslinked-page": "Ainm na duilleige:",
        "recentchangeslinked-to": "Seall mùthaidhean nan duilleagan a tha a' ceangal ris an duilleag sin 'na àite",
        "upload": "Luchdaich suas faidhle",
        "filetype-unwanted-type": "Cha ghabh sinn ris an seòrsa faidhle <strong>\".$1\"</strong>.\nIs docha leinn {{PLURAL:$3|an seòrsa faidhle|na seòrsaichean faidhle}} $2.",
        "filetype-banned-type": "Chan eil <strong>\".$1\"</strong> {{PLURAL:$4|'na seòrsa faidhle|'nan seòrsaichean faidhle}} ceadaichte.\nIs $2 {{PLURAL:$3|an seòrsa faidhle|na seòrsaichean faidhle}} ceadaichte.",
        "filetype-missing": "Chan eil leudachan aig an fhaidhle (can \".jpg\").",
-       "empty-file": "Cha am faidhle a chuir thu a-null falamh.",
-       "file-too-large": "Cha am faidhle a chuir thu a-null ro mhòr.",
+       "empty-file": "Tha am faidhle a chuir thu a-null falamh.",
+       "file-too-large": "Tha am faidhle a chuir thu a-null ro mhòr.",
        "filename-tooshort": "Tha ainm an fhaidhle a chuir thu a-null ro ghoirid.",
        "filetype-banned": "Tha an seòrsa faidhle seo toirmisgte.",
        "verification-error": "Dh'fhàillig am faidhle seo an dearbhadh.",
        "windows-nonascii-filename": "Cha chuir an uicidh seo taic ri ainm faidhle sa bheil caractaran sònraichte.",
        "fileexists": "Tha faidhle ann mu thràth air a bheil an t-ainm seo, thoir sùil air <strong>[[:$1]]</strong> mur eil thu buileach cinnteach a bheil thu airson atharrachadh.\n[[$1|thumb]]",
        "filepageexists": "Chaidh duilleag an tuairisgeil airson na duilleige seo a chruthachadh air <strong>[[:$1]]</strong> mar-thà ach chan eil faidhle air a bheil an t-ainm seo ann an-dràsta.\nCha nochd an gearr-chunntas a chuireas tu a-steach air duilleag an tuairisgeil.\nFeumaidh tu a dheasachadh a làimh ach an nochd an gearr-chunntas agad an-siud.\n[[$1|thumb]]",
-       "fileexists-extension": "Tha faidhle ann air a bheil ainm a tha coltach ris: [[$2|thumb]]\n* Ainm an fhaidhle 'ga luchdadh suas: <strong>[[:$1]]</strong>\n* Ainm an fhaidhle a tha ann: <strong>[[:$2]]</strong>\nFeuch an tagh thu ainm eile.",
+       "fileexists-extension": "Tha faidhle ann air a bheil ainm a tha coltach ris: [[$2|thumb]]\n* Ainm an fhaidhle 'ga luchdadh suas: <strong>[[:$1]]</strong>\n* Ainm an fhaidhle a tha ann: <strong>[[:$2]]</strong>\nNach tagh thu ainm nas diofraichte uaithe?",
        "fileexists-thumbnail-yes": "Tha coltas an deilbh le meud lùghdaichte <em>(dealbhag)</em> air an fhaidhle seo.\n[[$1|thumb]]\nThoir sùil air an fhaidhle <strong>[[:$1]]</strong>.\nMas e an aon dealbh a tha san fhaidhle sin ach air meud tùsail, cha leig thu leas dealbhag a bharrachd a luchdadh suas.",
        "file-thumbnail-no": "Tha ainm an fhaidhle a' tòiseachadh le <strong>$1</strong>.\nTha coltas an deilbh le meud lùghdaichte <em>(dealbhag)</em> air.\nMa tha an dealbh agad le dùmhlachd-bhreacaidh shlàn, feuch an luchdaich thu am fear ud suas 's mur eil, feuch an atharraich thu ainm an fhaidhle.",
        "fileexists-forbidden": "Tha faidhle air a bheil an t-ainm seo ann mar-thà 's cha ghabh sgrìobhadh thairis air.\nMa tha thu airson am faidhle agad a luchdadh suas fhathast, rach air ais 's cleachd ainm ùr.\n[[File:$1|thumb|center|$1]]",
        "backend-fail-store": "Cha b' urrainn dhuinn am faidhle \"$1\" a stòradh air \"$2\".",
        "backend-fail-copy": "Cha b' urrainn dhuinn lethbhreac dhen fhaidhle \"$1\" a chur gu \"$2\".",
        "backend-fail-move": "Cha b' urrainn dhuinn am faidhle \"$1\" a ghluasad gu \"$2\".",
-       "backend-fail-opentemp": "Cha deach leinn faidhle sealach fhosgladh.",
+       "backend-fail-opentemp": "Cha deach leinn faidhle sealach fhosgladh.",
        "backend-fail-writetemp": "Cha deach leinn sgrìobhadh san fhaidhle sealach.",
        "backend-fail-closetemp": "Cha deach leinn am faidhle sealach a dhùnadh.",
        "backend-fail-read": "Cha b' urrainn dhuinn am faidhle \"$1\" a leughadh.",
        "backend-fail-create": "Cha b' urrainn dhuinn sgrìobhadh san fhaidhle \"$1\".",
        "backend-fail-maxsize": "Cha b' urrainn dhuinn am faidhle \"$1\" a sgrìobhadh on a tha e nas motha na $2 {{PLURAL:$2|bhaidht|bhaidht|baidhtichean|baidht}}.",
        "backend-fail-readonly": "Chan eil backend an stòraidh \"$1\" ach ri leughadh a-mhàin an-dràsta. Seo as adhbhar: \"<em>$2</em>\"",
-       "backend-fail-synced": "Cha am faidhle \"$1\" ann an staid mì-chòrdail a thaobh nam backends stòraidh inntearnail.",
+       "backend-fail-synced": "Tha am faidhle \"$1\" ann an staid mì-chòrdail a thaobh nam backends stòraidh inntearnail.",
        "backend-fail-connect": "Cha deach leinn ceangal ri backend an stòraidh \"$1\".",
        "backend-fail-internal": "Chathair mearachd neo-aithnichte le backend an stòraidh \"$1\".",
        "backend-fail-contenttype": "Cha deach leinn faighinn a-mach dè an seòrsa susbaint a tha san fhaidhle ri stòradh air \"$1\".",
        "zip-bad": "Tha am faidhle ZIP coirbte no cha ghabh a leughadh air adhbhar eile air choireigin.\nChan urrainn dhuinn dearbhadh mar bu chòir a bheil e tèarainte gus nach eil.",
        "zip-unsupported": "Tha am faidhle ZIP seo a' chleachdadh feartan ZIP ris nach cuir MediaWiki taic.\nChan urrainn dhuinn dearbhadh mar bu chòir a bheil e tèarainte gus nach eil.",
        "uploadstash": "Tasgadan an luchdaidh suas",
+       "uploadstash-summary": "Bheir an duilleag seo inntrigeadh dhut a dh'fhaidhlichean a chaidh a luchdadh suas no a tha 'gan luchdadh suas ach nach deach fhoillseachadh air an uicidh fhathast. Chan fhaic duine na faidhlichean seo ach an cleachdaiche a rinn an luchdadh suas.",
        "uploadstash-clear": "Glan na faidhlichean ann an tasgadan an luchdaidh suas",
        "uploadstash-nofiles": "Chan eil faidhle agad ann an tasgadan an luchdaidh suas.",
+       "uploadstash-badtoken": "Cha deach an gnìomh seo a choileanadh, 's dòcha air sgàth 's gun do dh'fhalbh an ùine air an teisteanas deasachaidh agad. Am feuch thu ris a-rithist?",
        "uploadstash-errclear": "Cha deach leinn na faidhlichean a ghlanadh air falbh.",
        "uploadstash-refresh": "Ath-nuadhaich liosta nam faidhlichean",
+       "invalid-chunk-offset": "Frith-àireamh a' chnaip mhì-dhligheach",
        "img-auth-accessdenied": "Chaidh an t-inntrigeadh a dhiùltadh",
        "img-auth-nopathinfo": "Tha PATH_INFO a dhìth.\nCha deach am frithealaiche agad a shuidheachadh ach an doireadh e am fiosrachadh seo seachad.\nDh'fhaoidte gu bheil e stèidhichte air CGI 's chan urrainn dha taic a chur ri img_auth.\nFaic https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:Image_Authorization.",
        "img-auth-notindir": "Chan eil an t-slighe a chaidh iarraidh san t-slighe luchdaidh suas a chaidh a rèiteachadh.",
        "img-auth-nofile": "Chan eil am faidhle \"$1\" ann.",
        "img-auth-isdir": "Tha thu a' feuchainn ris a' phasgan \"$1\" inntrigeadh.\nChan fhaod thu ach faidhlichean inntrigeadh.",
        "img-auth-streaming": "A' sruthadh \"$1\".",
+       "img-auth-public": "Nì img_auth.php às-chur airson faidhlichean o uicidh phrìobhaideach.\nChaidh an uicidh seo a rèiteachadh mar thè phoblach.\nChaidh img_auth.php a chur à comas a chum tèarainteachd.",
        "img-auth-noread": "Chan eil cead inntrigidh aig a' chleachdaiche gus \"$1\" a leughadh.",
        "http-invalid-url": "URL mì-dhligheach: $1",
        "http-invalid-scheme": "Cha chuirear taic ri URLaichean leis an sgeama \"$1\".",
        "upload-curl-error6": "Cha deach leinn an URL a ruigsinn",
        "upload-curl-error6-text": "Cha deach leinn an URL a chaidh a thoirt seachad a ruigsinn.\nDearbhaich gu bheil an URL mar bu chòir 's gu bheil an làrach ag obair.",
        "upload-curl-error28": "Dh'fhalbh an ùine air an luchdadh suas",
+       "upload-curl-error28-text": "Thug an làrach seo ro fhada gus freagairt a thoirt.\nDearbhaich gu bheil an àrach ag obrachadh, fuirich greiseag 's feuch ris a-rithist.\n'S dòcha gum b' fheairrde thu feuchainn a-rithist nuair nach eil i cho trang.",
        "license": "Ceadachadh:",
        "license-header": "Ceadachadh",
        "nolicense": "Cha deach gin a thaghadh",
        "pageswithprop-prophidden-long": "chaidh luach fada aig buadh teacsa fhalach ($1)",
        "pageswithprop-prophidden-binary": "chaidh luach bìnearaidh fhalach ($1)",
        "doubleredirects": "Ath-seòlaidhean dùbailte",
+       "doubleredirectstext": "Seallaidh an duilleag seo na duilleagan dhut a nì ath-stiùireadh gu duilleag eile a tha 'na t-ath-stiùireadh.\nTha ceanglaichean dhan chiad 's dàrna ath-stiùireadh anns gach ràgh cho math ri ceann-uidhe an dàrna ath-stiùiridh a tha 'na \"fhìor\" dhuilleag-uidhe ris am bu chòir a' chiad duilleag a thomhadh mar as trice.\nChaidh innteartan le <del>loidhne tromhpa</del> fhuasgladh.",
        "double-redirect-fixed-move": "Chaidh [[$1]] a ghluasad.\nChaidh ùrachadh gu fèin-obrachail 's nì e ath-stiùireadh gu [[$2]] a-nis.",
        "double-redirect-fixed-maintenance": "A' càradh ath-stiùireadh dùblaichte o [[$1]] gu [[$2]] gu fèin-obrachail le obair-càraidh.",
        "double-redirect-fixer": "Càraichear nan ath-stiùiridhean",
        "wantedpages": "Duilleagan a thathar 'gan iarraidh",
        "wantedpages-badtitle": "Tha tiotal mì-dhligheach am measg nan toraidhean: $1",
        "wantedfiles": "Faidhlichean a thathar 'gan iarraidh",
+       "wantedfiletext-cat": "Tha na faidhlichean a leanas 'gan cleachdadh ach chan eil iad ann. Dh'fhaoidte gum bi faidhlichean o ionadan-tasgaidh cèine 'gan sealltainn an-seo ged a tha iad ann. Bidh <del>loidhne tro</del> na toraidhean a bharrachd seo. A bharrachd air sin, chì thu na duilleagan sa bhios faidhlichean nach eil ann leabaichte air [[:$1]].",
+       "wantedfiletext-nocat": "Tha na faidhlichean a leanas 'gan cleachdadh ach chan eil iad ann. Dh'fhaoidte gum bi faidhlichean o ionadan-tasgaidh cèine 'gan sealltainn an-seo ged a tha iad ann. Bidh <del>loidhne tro</del> na toraidhean a bharrachd seo.",
        "wantedtemplates": "Teamplaidean a thathar 'gan iarraidh",
        "mostlinked": "Na duilleagan ris a bheil an àireamh as motha de cheanglaichean",
        "mostlinkedcategories": "Na roinnean-seòrsa ris a bheil an àireamh as motha de cheanglaichean",
        "deadendpagestext": "Cha dèan na duilleagan seo ceangal gu duilleag sam bith eile air {{SITENAME}}.",
        "protectedpages": "Duilleagan fo dhìon",
        "protectedpages-indef": "Dìonan buana a-mhàin",
+       "protectedpages-summary": "Chì thu na duilleagan a tha ann 's gan dìon an-seo. Faic [[{{#special:ProtectedTitles}}|{{int:protectedtitles}}]] airson liosta dhe na tiotalan a tha 'gan dìon o chruthachadh.",
        "protectedpages-cascade": "Dìonan o bhith mar eas a-mhàin",
        "protectedpages-noredirect": "Falaich ath-sheòlaidhean",
        "protectedpagesempty": "Chan eil duilleag 'ga dhìon leis na paramadairean seo aig an àm seo.",
        "ancientpages": "Duilleagan as sìne",
        "move": "Gluais",
        "movethispage": "Gluais an duilleag seo",
+       "unusedimagestext": "Tha na faidhlichean a leanas ann ach cha deach an leabachadh ann an duilleag sam bith.\nThoir an aire gun dèan làraichean-lìn eile ceangal gu faidhlichean ma dh'fhaoidte le URL dìreach 's mar sin dh'fhaoidte gun dèid an cleachdadh fhathast ged a nochdas iad an-seo.",
        "unusedcategoriestext": "Tha na duilleagan roinn-seòrsa seo ann ged nach cleachd duilleag no roinn-seòrsa sam bith eile iad.",
        "notargettitle": "Gun cheann-uidhe",
+       "notargettext": "Cha dug thu seachad duilleag-uidhe no cleachdaiche air an dèanamaid an gnìomh seo.",
+       "nopagetitle": "Chan eil an duilleag-uidhe ann",
+       "nopagetext": "Chan eil an duilleag-uidhe a thug thu seachad ann.",
        "pager-newer-n": "{{PLURAL:$1|an $1 nas ùire|na $1 nas ùire}}",
        "pager-older-n": "{{PLURAL:$1|an $1 nas sine|na $1 nas sine}}",
        "suppress": "Marasgal",
+       "querypage-disabled": "Chaidh an duilleag shònraichte seo a chur à comas a chum dèanadais.",
        "booksources": "Tùsan a tha 'nan leabhraichean",
        "booksources-search-legend": "Lorg tùsan a tha 'nan leabhraichean",
+       "booksources-isbn": "ISBN:",
        "booksources-go": "Siuthad",
+       "booksources-text": "Chì thu liosta dhe cheanglaichean gu làraichean eile a reiceas leabhraichean ùra 's cleachdte gu h-ìosal 's ma dh'fhaoidte gum faigh thu barrachd fiosrachaidh orra mu leabhraichean a tha thu a' sireadh:",
+       "booksources-invalid-isbn": "Tha coltas mì-dhligheach air an ISBN a chaidh a thoirt seachad; dearbhaich gun deach lethbhreac a dhèanamh dheth on tùs gun mhearachd.",
+       "specialloguserlabel": "Cò rinn e:",
+       "speciallogtitlelabel": "Ceann-uidhe (tiotal no cleachdaiche):",
        "log": "Logaichean",
        "all-logs-page": "A h-uile loga poblach",
+       "alllogstext": "Sealladh co-mheasgaichte dhen a h-uile loga aig {{SITENAME}} a tha ri làimh.\n'S urrainn dhut an sealladh a chuingeachadh 's tu a' taghadh seòrsa an loga, ainm a' chleachdaiche (le aire do litrichean mòra 's beaga) no an duilleag a tha fo bhuaidh (le aire do litrichean mòra 's beaga).",
        "logempty": "Chan eil rud sam bith san loga a tha 'ga mhaidseadh.",
+       "log-title-wildcard": "Lorg sna tiotalan a thòisicheas leis an teacsa seo",
        "showhideselectedlogentries": "Seall/Falaich innteartan an loga a thagh thu",
        "allpages": "A h-uile duilleag",
        "nextpage": "An ath dhuilleag ($1)",
        "prevpage": "An duilleag roimhe ($1)",
-       "allpagesfrom": "Seall duilleagan a tha a' tòiseachadh aig:",
+       "allpagesfrom": "Seall duilleagan o seo a-mach:",
        "allpagesto": "Seall duilleagan a tha a' crìochnachadh aig:",
        "allarticles": "A h-uile duilleag",
        "allinnamespace": "A h-uile duilleag (ainm-spàs $1)",
-       "allpagessubmit": "Rach",
+       "allpagessubmit": "Siuthad",
+       "allpagesprefix": "Seall na duilleagan leis an ro-leasachan:",
+       "allpagesbadtitle": "Chaidh tiotal duilleige mì-dhligheach a thoirt seachad no bha ro-leasachan eadar-cànain no eadar-uicidh aige.\nFaodaidh gu bheil aon no barrachd charactaran ann nach urrainn dhut a chleachdadh ann an tiotal.",
        "allpages-bad-ns": "Chan eil an t-ainm-spàs \"$1\" aig {{SITENAME}}.",
+       "allpages-hide-redirects": "Falaich ath-sheòlaidhean",
+       "cachedspecial-viewing-cached-ttl": "Chì thu an tionndadh dhen duilleag seo a tha san tasgadan 's a tha suas ri $1 a dh'aois, ma dh'fhaoidte.",
+       "cachedspecial-viewing-cached-ts": "Chì thu an tionndadh dhen duilleag seo a tha san tasgadan 's a tha caran sean, ma dh'fhaoidte.",
+       "cachedspecial-refresh-now": "Seall an tionndadh as ùire.",
        "categories": "Roinnean-seòrsa",
        "categoriespagetext": "Tha duilleagan no meadhan {{PLURAL:$1|san roinn-seòrsa|sna roinnean-seòrsa|}} a leanas.\nChan fhaicear [[Special:UnusedCategories|roinnean-seòrsa gun chleachdadh an-seo]].\nThoir sùil air na [[Special:WantedCategories|roinnean-seòrsa a thathar 'gan iarraidh cuideachd]].",
-       "categoriesfrom": "Seall roinnean-seòrsa a tha a' tòiseachadh aig:",
+       "categoriesfrom": "Seall roinnean-seòrsa o seo a-mach:",
+       "special-categories-sort-count": "seòrsaich a-rèir an uireid",
+       "special-categories-sort-abc": "seòrsaich a rèir na h-aibidil",
        "deletedcontributions": "Obair air a sguabadh às",
        "deletedcontributions-title": "Obair air a sguabadh às",
        "sp-deletedcontributions-contribs": "obair",
        "linksearch": "Lorg sna ceanglaichean dhan taobh a-muigh",
+       "linksearch-pat": "Pàtran an luirg:",
        "linksearch-ns": "Ainm-spàs:",
+       "linksearch-ok": "Lorg",
+       "linksearch-text": "'S urrainn dhut saoragan mar \"*.wikipedia.org\" a chleachdadh.\nBidh feum air air co-dhiù aon àrainn aig ìre as àirde, can \"*.org\".<br />\n{{PLURAL:$2|pròtacal|pròtacalan}} ris an cuirear taic: <code>$1</code> (http:// a ghnáth mur dèid pròtacal a shònrachadh).",
        "linksearch-line": "Tha $1 a' ceangal an-seo o $2",
+       "linksearch-error": "Chan fhaod saorag nochdadh ach aig toiseach ainm an òstair.",
+       "listusersfrom": "Seall cleachdaichean o seo a-mach:",
+       "listusers-submit": "Seall",
+       "listusers-noresult": "Cha deach cleachdaiche a lorg.",
+       "listusers-blocked": "('ga bhacadh)",
+       "activeusers": "Na cleachdaichean gnìomhach",
+       "activeusers-intro": "Seo liosta dhe na cleachdaichean a rinn gnìomh air choireigin am broinn {{PLURAL:$1|an $1 latha|an $1 latha|nan $1 làithean|an $1 latha}} mu dheireadh.",
+       "activeusers-count": "$1 {{PLURAL:$1|ghnìomh|ghnìomh|gnìomhan|gnìomh}} am broinn {{PLURAL:$3|an $3 latha|an $3 latha|nan $3 làithean|an $3 latha}} mu dheireadh.",
+       "activeusers-from": "Seall cleachdaichean o seo a-mach:",
+       "activeusers-hidebots": "Falaich na botaichean",
+       "activeusers-hidesysops": "Falaich na rianairean",
+       "activeusers-noresult": "Cha deach cleachdaiche a lorg.",
+       "listgrouprights": "Ceadan nam buidhnean chleachdaichean",
+       "listgrouprights-summary": "chì thu liosta dhe na buidhnean chleachdaichean a tha san uicidh seo 's na ceadan inntrigidh aca.\nDh'fhaoidte gu bheil [[{{MediaWiki:Listgrouprights-helppage}}|barrachd fiosrachaidh]] mu cheadan fa leth ann.",
        "listgrouprights-key": "Treòir:\n* <span class=\"listgrouprights-granted\">Cead a fhuair iad</span>\n* <span class=\"listgrouprights-revoked\">Cead air a thoirt uapa</span>",
+       "listgrouprights-group": "Buidheann",
+       "listgrouprights-rights": "Ceadan",
+       "listgrouprights-helppage": "Help:Ceadan nam buidhnean",
        "listgrouprights-members": "(liosta de bhuill)",
+       "listgrouprights-right-display": "<span class=\"listgrouprights-granted\">$1 <code>($2)</code></span>",
+       "listgrouprights-right-revoked": "<span class=\"listgrouprights-revoked\">$1 <code>($2)</code></span>",
+       "listgrouprights-addgroup": "Cuir {{PLURAL:$2|buidheann|buidhnean}} ris: $1",
+       "listgrouprights-removegroup": "Thoir {{PLURAL:$2|buidheann|buidhnean}} ar falbh: $1",
+       "listgrouprights-addgroup-all": "Cuir a h-uile buidheann ris",
+       "listgrouprights-removegroup-all": "Thoir a h-uile buidheann air falbh",
+       "listgrouprights-addgroup-self": "Cuir {{PLURAL:$2|buidheann|buidhnean}} ris a' chunntas agad fhèin: $1",
+       "listgrouprights-removegroup-self": "Thoir {{PLURAL:$2|buidheann|buidhnean}} air falbh on chunntas agad fhèin: $1",
+       "listgrouprights-addgroup-self-all": "Cuir a h-uile buidheann ris a' chunntas agad fhèin",
+       "listgrouprights-removegroup-self-all": "Thoir a h-uile buidheann air falbh on chunntas agad fhèin",
        "listgrouprights-namespaceprotection-header": "Cuingeachaidhean air ainm-spàs",
        "listgrouprights-namespaceprotection-namespace": "Ainm-spàs",
+       "listgrouprights-namespaceprotection-restrictedto": "Na bheir cead deasachaidh dhan chleachdaiche",
        "trackingcategories": "Roinnean-seòrsa tracaidh",
        "trackingcategories-summary": "Chì thu na roinnean-seòrsa tracaidh air an duilleag seo a thèid a chur riutha gu fèin-obrachail leis a' bhathar-bhog MediaWiki. 'S urrainn dhut na h-ainmean a tha orra atharrachadh 's tu ag atharrachadh teachdaireachdan an t-siostaim iomchaidh san ainm-spàs {{ns:8}}.",
        "trackingcategories-msg": "Roinn-seòrsa tracaidh",
+       "trackingcategories-name": "Ainm na teachdaireachd",
        "trackingcategories-desc": "Cuspairean-deuchainn gus roinnean-seòrsa a chur ris",
        "noindex-category-desc": "Cha dèid an duilleag seo a chur ris an inneacs luirg le botaichean on a tha am facal draoidheach <code><nowiki>__NOINDEX__</nowiki></code> air 's a tha i ann an ainm-spàs far a bheil a' bhratach seo ceadaichte.",
        "index-category-desc": "Tha <code><nowiki>__INDEX__</nowiki></code> air an duilleag seo ('s tha i ann an ainm-spàs far a bheil a' bhratach seo ceadaichte) 's mar sin thèid a chur ri inneacsan luirg le botaichean ged nach tachradh seo gu h-àbhaisteach.",
+       "post-expand-template-inclusion-category-desc": "Bhiodh an duilleag nas motha na <code>$wgMaxArticleSize</code> às dèidh a h-uile teamplaid a leudachadh 's mar sin cha deach a h-uile teamplaid a leudachadh.",
+       "post-expand-template-argument-category-desc": "Bidh an duilleag nas motha na  <code>$wgMaxArticleSize</code> às dèidh argamaid teamplaid a leudachadh (rudeigin eadar camagan dualach trìoblaichte, can <code>{{{Foo}}}</code>).",
+       "expensive-parserfunction-category-desc": "Tha cus foincseanan cosgail a' pharsair (can <code>#ifexist</code>) am broinn duilleige. Faic [https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:$wgExpensiveParserFunctionLimit Manual:$wgExpensiveParserFunctionLimit].",
        "broken-file-category-desc": "Thèid an roinn-seòrsa seo a chur ris nuair a bhios ceangal gu faidhle briste am broinn na duilleige (ceangal gus faidhle a leabachadh mur eil am faidhle ann).",
        "hidden-category-category-desc": "Seo ronn-seòrsa le <code><nowiki>__HIDDENCAT__</nowiki></code> oirre ach nach nochd i ann am bogsa nan ceanglaichean gu roinnean-seòrsa air na duilleagan o thùs.",
        "trackingcategories-nodesc": "Chan eil tuairisgeul ri làimh.",
        "trackingcategories-disabled": "Tha an roinn-seòrsa à comas",
+       "mailnologin": "Gun seòladh an t-seòladair",
+       "mailnologintext": "Feumaidh tu [[Special:UserLogin|logadh a-steach]] 's seòladh puist-d dligheach a bhith sna [[Special:Preferences|roghainnean]] agad mus cuir thu post-d gu cleachdaiche eile.",
        "emailuser": "Cuir post-dealain dhan chleachdaiche seo",
        "emailuser-title-target": "Cuir post-d dhan chleachdaiche seo",
+       "emailuser-title-notarget": "Cuir post-d gu cleachdaiche",
+       "emailpage": "Cuir post-d gun chleachdaiche",
+       "emailpagetext": "'S urrainn dhut am foirm gu h-ìosal a chleachdadh gus post-d a chur dhan chleachdaiche seo.\nNochdaidh an seòladh a chuir thu a-steach [[Special:Preferences|sna roghainnean agad]] mar an seòladh \"O\" sa post-d, mar sin 's urrainn dhan fhaightear freagairt a chur thugad gu dìreach.",
+       "defemailsubject": "Post-d on chleachdaiche \"$1\" air {{SITENAME}}",
+       "usermaildisabled": "Chaidh post-d nan cleachdaichean a chur à comas.",
+       "usermaildisabledtext": "Chan urrainn dhut post-d a chur gu cleachdaiche eile air an uicidh seo",
+       "noemailtitle": "Gun seòladh puist-d",
+       "noemailtext": "Cha dug an cleachdaiche seo seòladh puist-d dligheach seachad.",
+       "nowikiemailtext": "Chuir an cleachdaiche seo roimhe nach fhaigh e post-d o chleachdaiche eile.",
+       "emailnotarget": "Chan eil ainm-cleachdaiche an fhaighteir ann no tha e mì-dhligheach.",
+       "emailtarget": "Cuir a-steach ainm-cleachdaiche an fhaighteir",
        "emailusername": "Ainm-cleachdaiche:",
        "emailusernamesubmit": "Air adhart",
+       "email-legend": "Cuir post-d gu cleachdaiche eile air {{SITENAME}}",
        "emailfrom": "O:",
        "emailto": "Gu:",
        "emailsubject": "Cuspair:",
        "emailmessage": "Teachdaireachd:",
        "emailsend": "Cuir",
+       "emailccme": "Cuir lethbhreac dhen phost-d thugam.",
+       "emailccsubject": "Lethbhreac dhen teachdaireachd agad gu $1: $2",
+       "emailsent": "Post-d air a chur",
+       "emailsenttext": "Chaidh an teachdaireachd puist-d agad a chur.",
+       "emailuserfooter": "Chaidh am post-d seo a chur o $1 gu $2 leis an fheart \"cuir post-d gu cleachdaiche\" air {{SITENAME}}.",
+       "usermessage-summary": "A' fàgail teachdaireachd an t-siostaim.",
+       "usermessage-editor": "Teachdaire an t-siostaim",
+       "usermessage-template": "MediaWiki:UserMessage",
        "watchlist": "An clàr-faire",
        "mywatchlist": "An clàr-faire",
        "watchlistfor2": "aig $1 $2",
        "nowatchlist": "Chan eil rud sam bith air a' chlàr-fhaire agad.",
        "watchlistanontext": "$1 gus nithean air a' chlàr-fhaire agad a shealltainn no a dheasachadh.",
+       "watchnologin": "Chan eil thu air logadh a-steach",
        "addwatch": "Cuir air a' chlàr-fhaire",
-       "addedwatchtext": "Chaidh an duilleag \"[[:$1]]\" a chur ri [[Special:Watchlist|do chlàr-faire]].\nNochdaidh mùthaidhean a nithear air an duilleag seo 's air an duilleag deasbaireachd a tha co-cheangailte ris an-seo san àm ri teachd.",
+       "addedwatchtext": "Chaidh an duilleag \"[[:$1]]\" a chur ris a' [[Special:Watchlist|chlàr-fhaire]] agad.\nNochdaidh mùthaidhean a nithear air an duilleag seo 's air an duilleag deasbaireachd a tha co-cheangailte ris an-seo san àm ri teachd.",
        "addedwatchtext-short": "Chaidh an duilleag \"$1\" a chur ris a' chlàr-fhaire agad.",
        "removewatch": "Thoir air falbh on chlàr-fhaire",
-       "removedwatchtext": "Chaidh an duilleag \"[[:$1]]\" a thoirt air falbh o [[Special:Watchlist|do chlàr-faire]].",
+       "removedwatchtext": "Chaidh an duilleag \"[[:$1]]\" a thoirt air falbh on [[Special:Watchlist|chlàr-fhaire]] agad.",
        "removedwatchtext-short": "Chaidh an duilleag \"$1\" a thoirt ait falbh on chlàr-fhaire agad.",
        "watch": "Cum sùil air",
        "watchthispage": "Cum sùil air an duilleag seo",
        "enotif_body_intro_moved": "Chaidh duilleag $1 air {{SITENAME}} a ghluasad le $2 $PAGEEDITDATE, faic $3 airson a' mhùthaidh làithrich.",
        "enotif_body_intro_restored": "Chaidh duilleag $1 air {{SITENAME}} aiseag le $2 $PAGEEDITDATE, faic $3 airson a' mhùthaidh làithrich.",
        "enotif_body_intro_changed": "Chaidh duilleag $1 air {{SITENAME}} atharrachadh le $2 $PAGEEDITDATE, faic $3 airson a' mhùthaidh làithrich.",
+       "enotif_lastvisited": "Faic $1 airson gach atharrachadh on turas mu dheireadh a thadhail thu an-seo.",
+       "enotif_lastdiff": "Faic $1 gus coimhead air an atharrachadh seo.",
+       "enotif_anon_editor": "ball gun ainm $1",
        "enotif_body": "$WATCHINGUSERNAME, a charaid,\n\n$PAGEINTRO $NEWPAGE\n\nGearr-chunntas an deasaiche: $PAGESUMMARY $PAGEMINOREDIT\n\nCuir fios gun deasaiche:\npost-d: $PAGEEDITOR_EMAIL\nuicidh: $PAGEEDITOR_WIKI\n\nChan fhaigh thu brath-naidheachd eile air gnìomhan ach ma thadhaileas tu air an duilleag 's tu air logadh a-steach. 'S urrainn dhut cuideachd brataich nam brathan-naidheachd aiseag airson nan duilleagan uile a tha air a' chlàr-fhaire agad.\n\nSiostam càirdeil nam brath aig {{SITENAME}}\n\n--\nGus roghainnean nam brathan a gheibh thu air a' phost-d atharrachadh, tadhail air\n{{canonicalurl:{{#special:Preferences}}}}\n\nGus roghainnean a' chlàir-fhaire agad atharrachadh, tadhail air\n{{canonicalurl:{{#special:EditWatchlist}}}}\n\nGus duilleagan a thoirt far a' chlàir-fhaire agad, tadhail air\n$UNWATCHURL\n\nBeachdan thugainn 's barrachd taice:\n$HELPPAGE",
+       "created": "air a chruthachadh",
+       "changed": "air atharrachadh",
        "deletepage": "Sguab às duilleag",
        "confirm": "Daingnich",
        "excontent": "stuth a bh' ann: '$1'",
        "excontentauthor": "b' e: \"$1\" an t-susbaint (is \"[[Special:Contributions/$2|$2]]\" an aon deasaiche)",
+       "exbeforeblank": "an t-susbaint mus deach a bànachadh: \"$1\"",
        "delete-confirm": "Sguab às \"$1\"",
        "delete-legend": "Sguab às",
        "historywarning": "<strong>Rabhadh:</strong> Tha eachdraidh air an duilleag a tha thu airson sguabadh às sa bheil mu $1 {{PLURAL:$1|mhùthadh|mhùthadh|mùthaidhean|mùthadh}}:",
        "actionfailed": "Dh'fhàillig ort",
        "deletedtext": "Chaidh \"$1\" a sguabadh às.\nSeall air $2 airson clàr de dhuilleagan a chaidh a sguabadh às o chionn ghoirid.",
        "dellogpage": "Loga an sguabaidh às",
+       "dellogpagetext": "Seo liosta dhe na chaidh a sguabadh às o chionn goirid.",
+       "deletionlog": "loga an sguabaidh às",
        "reverted": "Air aiseag gu mùthadh nas sine",
        "deletecomment": "Adhbhar:",
        "deleteotherreason": "Adhbhar eile/a bharrachd:",
        "delete-edit-reasonlist": "Deasaich adhbharan sguabadh às",
        "delete-toobig": "Tha eachdraidh deasachaidh mòr aig an duilleag seo sa bheil barrachd air $1 {{PLURAL:$1|mhùthadh|mhùthadh|mùthaidhean|mùthadh}}.\nChaidh sguabadh às nan duilleagan dhen leithid a chuingeachadh ach na dèid cron a dhèanamh air {{SITENAME}} le mearachd.",
        "delete-warning-toobig": "Tha eachdraidh deasachaidh mòr aig an duilleag seo sa bheil barrachd air $1 {{PLURAL:$1|mhùthadh|mhùthadh|mùthaidhean|mùthadh}}.\nMa sguabas tu às dhi, dh'fhaoidte gun dèan thu cron air na gnìomhan stòr-dàta aig {{SITENAME}}; mar sin, thoir an aire.",
+       "deleting-backlinks-warning": "'''Rabhadh:''' Tha [[Special:WhatLinksHere/{{FULLPAGENAME}}|duilleag eile]] a' ceangal ris an duilleag a tha thu airson sguabadh às no 'ga gabhail a-steach 'na h-iomradh.",
        "rollback": "Roilig atharraichean air ais",
        "rollback_short": "Roladh air ais",
        "rollbacklink": "roilig air ais",
        "revertpage": "Deasachaidhean a chaidh a thilleadh leis [[Special:Contributions/$2|$2]] ([[User talk:$2|an deasbaireachd]]) dhan mhùthadh mu dheireadh le [[User:$1|$1]]",
        "revertpage-nouser": "Deasachaidhean a chaidh a thilleadh le cleachdaiche falaichte dhan mhùthadh mu dheireadh le [[User:$1|$1]]",
        "rollback-success": "Na deasachaidhean a chaidh a thilleadh le $1;\nchaidh an tilleadh gun mhùthadh mu dheireadh le $2.",
+       "sessionfailure-title": "Trioblaid leis an t-seisean",
+       "sessionfailure": "Tha duilgheadas ann leis an seisean logaidh a-steach agad a-rèir coltais;\nchaidh sgur dhen ghnìomh seo a chum dìon o session hijacking.\nTill dhan duilleag roimhpe, ath-luchdaich an duilleag ud 's feuch ris a-rithist an uairsin.",
        "protectlogpage": "Loga an dìon",
        "protectlogtext": "Tha liosta na chaidh a dhìon gu h-ìosal.\nCuir sùil air [[Special:ProtectedPages|liosta nan duilleagan fo dhìon]] airson liosta na fheadhainn a tha fo dhìon an-dràsta fhèin.",
        "protectedarticle": "\"[[$1]]\" air a dhìon",
        "modifiedarticleprotection": "a dh'atharraich an ìre dìon de \"[[$1]]\"",
        "unprotectedarticle": "a neo-dhìon \"[[$1]]\"",
-       "protect-title": "A' dìonadh \"$1\"",
-       "prot_1movedto2": "[[$1]] gluaiste ri [[$2]]",
+       "movedarticleprotection": "chaidh roghainn an dìona a ghluasad o \"[[$2]]\" gu \"[[$1]]\"",
+       "protect-title": "Atharraich an dìon airson \"$1\"",
+       "protect-title-notallowed": "Seall an dìon airson \"$1\"",
+       "prot_1movedto2": "chaidh [[$1]] a ghluasad gu [[$2]]",
        "protect-badnamespace-title": "Cha ghabh an t-ainm-spàs seo a dhìon",
        "protect-badnamespace-text": "Cha ghabh duilleagan san ainm-spàs seo a dhìon.",
+       "protect-norestrictiontypes-text": "Cha ghabh an duilleag seo a dhìon o nach eil seòrsa cuingeachaidh sam bith ri làimh.",
        "protect-norestrictiontypes-title": "Cha ghabh an duilleag seo a dhìon",
        "protect-legend": "Daingnich dìonadh",
        "protectcomment": "Adhbhar:",
        "protectexpiry": "Falbhaidh an ùine air:",
        "protect_expiry_invalid": "Tha an t-àm-crìochnachaidh mì-dhligheach.",
        "protect_expiry_old": "Tha an t-àm crìochnachaidh seachad mu thràth.",
+       "protect-unchain-permissions": "Thoir a' ghlas far na roghainnean dìona a bharrachd",
        "protect-text": "Chì thu an ìre dìon dhen duilleag <strong>$1</strong> an-seo agus is urrainn dhut atharrachadh an-seo.",
+       "protect-locked-blocked": "Chan urrainn dhut ìre an dìon atharrachadh rè bacaidh.\nSeo na roghainnean aig an duilleag <strong>$1</strong>:",
+       "protect-locked-dblock": "Chan urrainn dhut ìre an dìon atharrachadh on a tha an stòr-dàta glaiste an-dràsta.\nSeo na roghainnean aig an duilleag <strong>$1</strong>:",
        "protect-locked-access": "Chan eil cead aig a' chunntas agad an ìre dìon de dhuilleag atharrachadh.\nSeo roghainnean làithreach na duilleige <strong>$1</strong>:",
        "protect-cascadeon": "Tha an duilleag seo fo dhìon an-dràsta a chionn 's gu bheil e air a ghabhail a-steach {{PLURAL:$1|$1 duilleag|$1 dhuilleag|$1 duilleagan|$1 duilleag}} a leanas aig a bheil dìon o bhith mar eas air.\n'S urrainn dhut ìre dìon na duilleige seo atharrachadh ach cha bhi buaidh air an dìon o bhith mar eas.",
        "protect-default": "Ceadaich a h-uile cleachdaiche",
        "undelete": "Seal na duilleagan air an sguabadh às",
        "undeletepage": "Seall 's aisig duilleagan air an sguabadh às",
        "undeletepagetitle": "<strong>Chan e ach mùthaidhean de [[:$1|$1]] a chaidh a sguabadh às a tha sna leanas</strong>.",
+       "viewdeletedpage": "Seal na duilleagan air an sguabadh às",
+       "undeletepagetext": "Chaidh {{PLURAL:$1|an $1 duilleag|an $1 dhuilleag|na $1 duilleagan|am $1 duilleag}} a sguabadh às ach tha {{PLURAL:$1|i|iad}} san tasglann fhathast 's gabhaidh {{PLURAL:$1|a h-aiseag|an aiseag}}.\nDh'fhaoidte gun dèid an tasglann a ghlanadh gu cunbhalach.",
        "undelete-fieldset-title": "Aisig mùthaidhean",
+       "undeleteextrahelp": "Gus eachdraidh shlàn na duilleige aiseag, fàg gach bogsa bàn 's briog air <strong><em>{{int:undeletebtn}}</em></strong>.\nGus cuid dheth aiseag, cuir cromag sna bogsaichean airson nam mùthaidhean a tha thu airson aiseag 's briog air <strong><em>{{int:undeletebtn}}</em></strong>.",
        "undeleterevisions": "Chaidh {{PLURAL:$1|$1 mhùthadh|$1 mhùthadh|$1 mùthaidhean|$1 mùthadh}} a chur san tasg-lann",
+       "undeletehistory": "Ma dh'aisigeas tu an duilleag, thèid gach mùthadh aiseag dhan eachdraidh.\nMa chaidh duilleag air a bheil an aon ainm a chruthachadh às dèidh an sguabaidh às, nochdaidh na mùthaidhean air an aiseag san eachdraidh roimhpe.",
+       "undeleterevdel": "Cha dèid an sguabadh às a neo-dhèanamh ma sguabadh seo às pàirt de mhùthadh na duilleige no an fhaidhle as ùire.\nMas e seo na thachradh, feumaidh tu a' chromag a thoirt far a' mhùthaidh as ùire a chaidh a sguabadh às no gun a bhith 'ga fhalach tuilleadh.",
        "undeletehistorynoadmin": "Chaidh an duilleag seo a sguabadh às.\nChì thu adhbhar an sguabaidh às sa ghearr-chunntas gu h-ìosal cho math ri fiosrachadh mu na chleachdaichean a dheasaich an duilleag seo mus deach a sguabadh às.\nChan fhaic ach rianairean an teacsa fhèin aig na mùthaidhean air an sguabadh às.",
+       "undelete-revision": "Mùthadh de $1 air a sguabadh às (o $4 $5) le $3:",
+       "undeleterevision-missing": "Mùthadh mì-dhligheach no a dhìth.\n'S dòcha gu bheil droch cheangal agad no gun deach am mùthadh aiseag no a thoirt far na tasglainn.",
+       "undelete-nodiff": "Cha deach mùthadh as sine a lorg.",
+       "undeletebtn": "Aisig",
        "undeletelink": "seall/aisig",
        "undeleteviewlink": "seall",
+       "undeleteinvert": "Ais-thionndaidh na thagh thu",
+       "undeletecomment": "Adhbhar:",
+       "undeletedrevisions": "Chaidh $1 {{PLURAL:$1|mhùthadh|mhùthadh|mùthaidhean|mùthadh}} aiseag",
+       "undeletedrevisions-files": "Chaidh $1 {{PLURAL:$1|mhùthadh|mhùthadh|mùthaidhean|mùthadh}} agus $2 {{PLURAL:$2|fhaidhle|fhaidhle|faidhlichean|faidhle}} aiseag",
+       "undeletedfiles": "Chaidh $1 {{PLURAL:$1|fhaidhle|fhaidhle|faidhlichean|faidhle}} aiseag",
+       "cannotundelete": "Cha deach leinn an sguabadh às a neo-dhèanamh:\n$1",
+       "undeletedpage": "<strong>Chaidh $1 aiseag</strong>\n\nThoir sùil air [[Special:Log/delete|loga an sguabaidh às]] airson clàr air na chaidh a sguabadh às no aiseag o chionn goirid.",
+       "undelete-header": "Faic [[Special:Log/delete|loga an sguabaidh às]] airson duilleagan a chaidh a sguabadh às o chionn goirid.",
+       "undelete-search-title": "Lorg sna duilleagan air an sguabadh às",
+       "undelete-search-box": "Lorg sna duilleagan air an sguabadh às",
+       "undelete-search-prefix": "Seall na duilleagan a thòisicheas le:",
+       "undelete-search-submit": "Lorg",
+       "undelete-no-results": "Cha deach duilleag a dh'fhreagradh a lorg ann an tasglann nan sguabaidhean às.",
+       "undelete-filename-mismatch": "Cha ghabh mùthadh an fhaidhle aiseag air a bheil an stampa-tìde $1: Chan fhreagair ainmean nam faidhlichean ri chèile.",
+       "undelete-bad-store-key": "Cha ghabh mùthadh an fhaidhle aiseag air a bheil an stampa-tìde $1: Bha am faidhle a dhìth mar-thà mus deach a sguabadh às.",
+       "undelete-cleanup-error": "Mearachd a' sguabadh às faidhle tasglainn \"$1\" nach eil 'ga chleachdadh.",
+       "undelete-missing-filearchive": "Cha ghabh tasglann an fhaidhle air a bheil an ID $1 aiseag o nach eil e san stòr-dàta.\n'S dòcha gun deach an sguabadh às a neo-dhèanamh mar-thà.",
+       "undelete-error": "Mearachd a' neo-dhèanamh sguabadh às na duilleige",
+       "undelete-error-short": "Mearachd a' neo-dhèanamh sguabadh às an fhaidhle: $1",
+       "undelete-error-long": "Thachair mearachd le neo-dhèanamh sguabadh às an fhaidhle:\n\n$1",
+       "undelete-show-file-confirm": "A bheil thu cinnteach gu bheil thu airson coimhead air mùthadh an fhaidhle \"<nowiki>$1</nowiki>\" a chaidh a sguabadh às $2 aig $3?",
+       "undelete-show-file-submit": "Tha",
+       "undelete-revision-row": "$1 $2 ($3) $4 . . $5 $6 $7 $8 $9",
        "namespace": "Ainm-spàs:",
        "invert": "Cuir na thagh mi bun os cionn",
        "tooltip-invert": "Cuir cromag sa bhogsa seo gus atharraichean air an duilleag seo fhalach am broinn an ainm-spàs a thagh thu ('s an ainm-spàs co-cheangailte riutha ma tha cromag ris)",
        "contributions-title": "Obair a rinn $1",
        "mycontris": "M' obair",
        "contribsub2": "Airson $1 ($2)",
+       "contributions-userdoesnotexist": "Cha deach an cunntas cleachdaiche \"$1\" a chlàradh.",
+       "nocontribs": "Cha deach atharrachadh a lorg a dh'fhreagradh ris na cuspairean-luirg seo.",
        "uctop": "(làithreach)",
        "month": "On mhìos (agus na bu tràithe):",
        "year": "On bhliadhna (agus na bu tràithe):",
        "sp-contributions-newbies": "Seall obair le cunntasan ùra a-mhàin",
+       "sp-contributions-newbies-sub": "Airson cunntasan ùra",
        "sp-contributions-newbies-title": "Obair le cunntasan ùra",
        "sp-contributions-blocklog": "an loga bacaidh",
        "sp-contributions-suppresslog": "obair a chaidh a mhùchadh",
        "sp-contributions-logs": "logaichean",
        "sp-contributions-talk": "deasbaireachd",
        "sp-contributions-userrights": "stiùireadh ceadan a' chleachdaiche",
+       "sp-contributions-blocked-notice": "Tha an cleachdaiche seo 'ga bhacadh an-dràsta.\nSeo dhut loga a' bhacaidh mu dheireadh gu h-ìosal:",
+       "sp-contributions-blocked-notice-anon": "Tha an seòladh IP seo 'ga bhacadh an-dràsta.\nSeo dhut loga a' bhacaidh mu dheireadh gu h-ìosal:",
        "sp-contributions-search": "Lorg airson obair a rinneadh",
        "sp-contributions-username": "Seòladh IP no ainm-cleachdaiche:",
        "sp-contributions-toponly": "Na seall deasachaidhean ach na mùthaidhean as ùire",
+       "sp-contributions-newonly": "Na seall ach na deasachaidhean a tha 'nan cruthachadh duilleige",
        "sp-contributions-submit": "Lorg",
        "whatlinkshere": "Na tha a' ceangal a-nall an-seo",
        "whatlinkshere-title": "Duilleagan a tha a' ceangal ri \"$1\"",
        "whatlinkshere-hidelinks": "$1 ceanglaichean",
        "whatlinkshere-hideimages": "$1 ceanglaichean nam faidhlichean",
        "whatlinkshere-filters": "Criathairean",
+       "autoblockid": "Fèin-bhacadh $1",
        "block": "Bac an cleachdaiche",
        "unblock": "Neo-bhac an cleachdaiche",
        "blockip": "Bac an cleachdaiche",
+       "blockip-legend": "Bac an cleachdaiche",
+       "blockiptext": "Cleachd am foirm gu h-ìosal gus seòladh IP no cleachdaiche sònraichte a bhacadh o sgrìobhadh.\nNa dèan seo ach gus dìon o bhandalachd agus a-rèir [[{{MediaWiki:Policy-url}}|a' phoileasaidh]].\nLìon an t-adhbhar sònraichte gu h-ìosal (mar eisimpleir le iomradh air na duilleagan le bhandalachd orra).",
+       "ipaddressorusername": "Seòladh IP no ainm-cleachdaiche:",
+       "ipbexpiry": "Falbhaidh an ùine air:",
        "ipbreason": "Adhbhar:",
+       "ipbreason-dropdown": "*Adhbharan bacaidh cumanta\n** Cur fiosrachadh cearr a-steach\n** Toirt susbaint far duilleagan\n** Cur ceanglaichean-spama gu làraichean a-muigh ris\n** Cur a-steach amaideas/mablais air duilleagan\n** Smàdadh/sàrachadh\n** Ana-chleachdadh air iomadh cunntas\n** Ainm-cleachdaiche neo-thaitneach",
+       "ipb-hardblock": "Bac cleachdaichean on deasachadh a nì logadh a-steach on t-seòladh IP seo",
+       "ipbcreateaccount": "Bac cruthachadh cunntais",
+       "ipbemailban": "Bac cleachdaiche o chur puist-d",
+       "ipbenableautoblock": "Bac an seòladh IP mu dheireadh a chleachd an cleachdaiche seo gu fèin-obrachail 's gach seòladh IP a dh'fheuchas e ri deasachadh uaithe an uairsin",
        "ipbsubmit": "Bac an cleachdaiche seo",
+       "ipbother": "Àm eile:",
        "ipboptions": "2 uair a thìde:2 hours, 1 latha:1 day, 3 làithean:3 days, 1 seachdain:1 week, 2 sheachdain:2 weeks, 1 mhìos:1 month, 3 mìosan:3 months, 6 mìosan:6 months, 1 bhliadhna:1 year,buan:infinite",
+       "ipbhidename": "Falaich an t-ainm-cleachdaiche o dheasachaidhean 's liostaichean",
        "ipbwatchuser": "Cum sùil air duilleagan a' chleachdaiche 's deasbaireachd aig a' chleachdaiche seo",
        "ipb-disableusertalk": "Chan fhaod an cleachdaiche seo an duilleag deasbaireachd aige fhèin a dheasachadh fhad 's a bhios e bacte",
+       "ipb-change-block": "Bac an cleachdaiche a-rithist leis na roghainnean seo",
+       "ipb-confirm": "Dearbhaich am bacadh",
        "badipaddress": "Chan eil an seòladh IP aig a' cleachdair seo iomchaidh",
        "blockipsuccesssub": "Shoirbhich leat leis a' bhacadh",
        "blockipsuccesstext": "Chaidh [[Special:Contributions/$1|$1]] a bhacadh.\n<br />Faic [[Special:BlockList|liosta nan IP bacte]] gus sùile a thoirt air na bacaidhean.",
+       "ipb-blockingself": "Chuir thu romhad thu fhèin a bhacadh! A bheil thu cinnteach gu bheil thu airson seo a dhèanamh?",
        "ipb-confirmhideuser": "Cha thu an impis cleachdaiche a bhacadh le \"falaich cleachdaiche\" an comas. Mùchaidh seo ainm a' chleachdaiche anns gach uile liosta 's nì loga. A bheil thu cinnteach gu bheil thu airson seo a dhèanamh?",
+       "ipb-confirmaction": "Ma tha thu cinnteach gu bheil thu airson seo a dhèanamh, cuir cromag san raon \"{{int:ipb-confirm}}\" aig a' bhonn.",
+       "ipb-edit-dropdown": "Deasaich adhbharan a' bhacaidh",
+       "ipb-unblock-addr": "Neo-bhac $1",
+       "ipb-unblock": "Neo-bhac ainm-chleachdaiche no seòladh IP",
+       "ipb-blocklist": "Seall na bacaidhean a tha ann",
        "ipb-blocklist-contribs": "Obair a rinn $1",
        "unblockip": "Neo-bhac an cleachdaiche",
+       "unblockiptext": "Cleachd am foirm gu h-ìosal gus cead sgrìobhaidh aiseag gu seòladh IP no ainm-cleachdaiche a chaidh a bhacadh roimhe.",
        "ipusubmit": "Thoir air falbh am bacadh seo",
+       "unblocked": "Chaidh [[User:$1|$1]] a neo-bhacadh.",
+       "unblocked-range": "Chaidh $1 a neo-bhacadh.",
+       "unblocked-id": "Chaidh am bacadh $1 a thoirt air falbh.",
+       "blocklist": "Cleachdaichean a chaidh a bhacadh",
        "ipblocklist": "Cleachdaichean a chaidh a bhacadh",
+       "ipblocklist-legend": "Lorg cleachdaiche a chaidh a bhacadh",
+       "blocklist-userblocks": "Falaich bacaidhean cunntais",
+       "blocklist-tempblocks": "Falaich bacaidhean sealach",
+       "blocklist-addressblocks": "Falaich bacaidhean air aon IP",
+       "blocklist-rangeblocks": "Falaich bacaidhean air rainse",
+       "blocklist-timestamp": "Stampa-tìde",
+       "blocklist-target": "Amas",
+       "blocklist-expiry": "Falbhaidh an ùine air",
+       "blocklist-by": "Rianaire a rinn bacadh",
+       "blocklist-params": "Roghainnean a' bhacaidh",
+       "blocklist-reason": "Adhbhar",
+       "ipblocklist-submit": "Lorg",
+       "ipblocklist-localblock": "Bacadh ionadail",
+       "ipblocklist-otherblocks": "{{PLURAL:$1|Bacadh|Bacaidhean}} eile",
+       "infiniteblock": "buan",
+       "expiringblock": "falbhaidh an ùine air $1 $2",
+       "anononlyblock": "gun ainm a-mhàin",
+       "noautoblockblock": "chaidh fèin-bhacadh a chur à comas",
+       "createaccountblock": "chaidh cruthachadh chunntasan ùra a chur à comas",
+       "emailblock": "chaidh puist-d a chur à comas",
        "blocklist-nousertalk": "chan fhaod e an duilleag deasbaireachd aige fhèin a dheasachadh",
+       "ipblocklist-empty": "Tha liosta nam bacaidhean falamh.",
+       "ipblocklist-no-results": "Cha deach an seòladh IP no ainm-cleachdaiche a dh'iarradh bacadh.",
        "blocklink": "bac",
        "unblocklink": "neo-bhac",
        "change-blocklink": "mùth bacadh",
        "contribslink": "mùthaidhean",
+       "emaillink": "cuir post-d",
+       "autoblocker": "Chaidh do bhacadh gu fèin-obrachail on a chaidh an seòladh IP agad a cleachdadh le \"[[User:$1|$1]]\" o chionn goirid.\nIs \"$2\" an t-adhbhar a chaidh $1 a bhacadh",
        "blocklogpage": "Loga nam bacadh",
+       "blocklog-showlog": "Chaidh an cleachdaiche seo a bhacadh roimhe.\nSeo dhut loga a' bhacaidh:",
        "blocklog-showsuppresslog": "Chaidh an cleachdaiche seo a bhacadh 's a mhùchadh roimhe.\nSeo dhut loga a' mhùchaidh:",
        "blocklogentry": "Chaidh bacadh a chrìochnaicheas ann an $2 a chur air [[$1]] $3",
+       "reblock-logentry": "chaidh roghainnean a' bhacaidh atharrachadh airson [[$1]] 's falbhaidh an ùine air $2 $3",
+       "blocklogtext": "Seo loga dhe na bacaidhean 's neo-bhacaidhean air cleachdaichean.\nCha nochd na seòlaidhean IP a chaidh a bhacadh gu fèin-obrachail an-seo.\nFaic [[Special:BlockList|liosta nam bacaidhean]] airson nan toirmeasgan 's bacaidhean a tha gnìomhach an-dràsta.",
        "unblocklogentry": "\"$1\" air a neo-bhacadh",
+       "block-log-flags-anononly": "buill gun ainm a-mhàin",
        "block-log-flags-nocreate": "cruthachadh de chunntasan ùra à comas",
+       "block-log-flags-noautoblock": "chaidh fèin-bhacadh a chur à comas",
+       "block-log-flags-noemail": "chaidh puist-d a chur à comas",
        "block-log-flags-nousertalk": "chan fhaod e an duilleag deasbaireachd aige fhèin a dheasachadh",
+       "block-log-flags-angry-autoblock": "chaidh am fèin-bhacadh adhartach a chur an comas",
+       "block-log-flags-hiddenname": "chaidh an t-ainm-cleachdaiche fhalach",
+       "range_block_disabled": "Tha comas nan rianairean gus bacadh le rainse a chruthachadh a chur à comas.",
        "ipb_expiry_invalid": "Tha an t-àm-crìochnachaidh mì-dhligheach.",
+       "ipb_expiry_temp": "Feumaidh bacadh air ainm-cleachdaiche falaichte a bhith buan.",
        "ipb_hide_invalid": "Cha ghabh an cunntas seo a mhùchadh on a tha barrachd air $1 {{PLURAL:$1|deasachadh|dheasachadh|deasachaidhean|deasachadh}} aige.",
+       "ipb_already_blocked": "Chaidh \"$1\" a bhacadh mar-thà.",
+       "ipb-needreblock": "Chaidh $1 a bhacadh mar-thà. A bheil thu airson na roghainnean atharrachadh?",
+       "ipb-otherblocks-header": "{{PLURAL:$1|Bacadh|Bacaidhean}} eile",
+       "unblock-hideuser": "Chan urrainn dhut an cleachdaiche seo a neo-bhacadh on a chaidh ainm-cleachdaiche fhalach.",
+       "ipb_cant_unblock": "Mearachd: Cha deach am bacadh air a bheil an ID $1 a lorg. Dh'fhaoidte gun deach a neo-bhacadh mar-thà.",
+       "ipb_blocked_as_range": "Mearachd: Cha deach an t-seòladh IP $1 a bhacadh gu dìreach 's cha ghabh a neo-bhacadh.\nChaidh a bhacadh 'na phàirt dhen rainse $2 co-dhiù a ghabhas neo-bhacadh.",
        "ip_range_invalid": "Raon IP neo-iomchaidh.",
+       "ip_range_toolarge": "Chan eil bacadh le rainse nas motha na /$1 ceadaichte.",
+       "proxyblocker": "Bacaiche nam progsaidh",
+       "proxyblockreason": "Chaidh an seòladh IP agad a bhacadh air sgàth 's gur e progsaidh fhosgailte a th' ann.\nCuir fios gu solaraiche seirbheis eadar-lìn no sgioba taice a' bhuidhinn agad 's innis dhaibh mun duilgheadas mhòr leis an tèarainteachd a tha seo.",
+       "sorbs": "DNSBL",
+       "sorbsreason": "Nochdaidh an seòladh IP agad mar phrogsaidh fhosgailte air an liosta DNSBL a tha 'ga chleachdadh le {{SITENAME}}.",
+       "sorbs_create_account_reason": "Nochdaidh an seòladh IP agad mar phrogsaidh fhosgailte air an liosta DNSBL a tha 'ga chleachdadh le {{SITENAME}}.\nChan urrainn dhut cunntas a chruthachadh.",
+       "xffblockreason": "Chaidh seòladh IP a tha sa bhann-chinn X-Forwarded-For a bhacadh, seo an t-seòladh agad fhèin no fear aig frithealaiche progsaidh a tha thu a' chleachdadh. Seo adhbhar a' bhacaidh thùsail: $1",
+       "cant-see-hidden-user": "Chaidh an cleachdaiche a tha thu airson bacadh a bhacadh no fhalach mar-thà.\nChan urrainn dhut am bacadh aig a' chleachdaiche a shealltainn no a dheasachadh air sgath 's nach eil cead agad gus cleachdaiche fhalach.",
+       "ipbblocked": "Chan urrainn dhut cleachdaichean eile a bhacadh no a neo-bhacadh on a chaidh do bacadh fhèin.",
+       "ipbnounblockself": "Chan fhaod thu thu fhèin a neo-bhacadh.",
        "lockdb": "Glais an stòr-dàta",
-       "lockconfirm": "Seadh, is ann a tha mi ag iarraidh an stòr-dàta a ghlasadh.",
+       "unlockdb": "Thoir a' ghlas far an stòr-dàta",
+       "lockdbtext": "Ma ghlaiseas tu an stòr-dàta, chan urrainn do chleachdaiche sam bith duilleagan a dheasachadh, na roghainnean aige atharrachadh, an clàr-faire aige a dheasachadh no rud sam bith eile a dhèanamh a rinneadh atharrachadh air an stòr-dàta.\nDearbhaich gur e seo na tha thu airson dèanamh is gun toir thu a' ghlas far an stòr-dàta nuair a bhios tu deiseil le do chuid obrach-glèidhidh.",
+       "unlockdbtext": "Ma bheirh thu a' ghlas far an stòir-dhàta, 's urrainn do chleachdaiche sam bith duilleagan a dheasachadh, na roghainnean aige atharrachadh, an clàr-faire aige a dheasachadh no rud sam bith eile a dhèanamh a rinneadh atharrachadh air an stòr-dàta.\nDearbhaich gur e seo na tha thu airson dèanamh.",
+       "lockconfirm": "Seadh, is ann a tha mi airson an stòr-dàta a ghlasadh.",
+       "unlockconfirm": "Seadh, is ann a tha mi airson a' ghlas a thoirt far an stòir-dhàta.",
        "lockbtn": "Glais an stòr-dàta",
+       "unlockbtn": "Thoir a' ghlas far an stòr-dàta",
+       "locknoconfirm": "Cha dug thu cromag sa bhogsa dhearbhaidh.",
        "lockdbsuccesssub": "Shoirbhich leat le glasadh an stòir-dhàta",
+       "unlockdbsuccesssub": "Thug thu a' ghlas far an stòir-dhàta",
+       "lockdbsuccesstext": "Chaidh an stòr-dàta a ghlasadh.<br />\nCuimhnich gun [[Special:UnlockDB|doir thu a' ghlas far an stòir-dhàta]] nuair a bhios do chuid obrach-glèidhidh dèanta.",
+       "unlockdbsuccesstext": "Chaidh a' ghlas a thoirt far an stòir-dhàta.",
+       "lockfilenotwritable": "Cha ghabh sgrìobhadh ann am faidhle glasaidh an stòir-dhàta.\nFeumaidh comas sgrìobhaidh leis an fhrithealaiche-lìn a bhith ann ach an gabh an stòr-dàta a ghlasadh no a' ghlas a thoirt fo bharr.",
+       "databasenotlocked": "Chan eil an stòr-dàta glaiste.",
        "lockedbyandtime": "(le $1 $2 $3)",
+       "move-page": "Gluais $1",
        "move-page-legend": "Gluais duilleag",
        "movepagetext": "Ma chleachdas tu am foirm gu h-ìosal, cuiridh tu ainm ùr air 's gluaisidh tu a h-eachdraidh gu lèir dhan ainm ùr.\nBidh an seann tiotal 'na ath-sheòladh dhan tiotal ùr an uairsin.\n'S urrainn dhut ath-sheòladh sam bith a tha a' dol dhan tiotal tùsail ùrachadh leis fhèin.\nMura dèan thu sin, dèan cinnteach gun cuir thu sùil air eagal 's gum bi [[Special:DoubleRedirects|ath-sheòlaidhean dùbailte]] no [[Special:BrokenRedirects|briste]] ann.\n'S ann ort-sa a tha an t-uallach airson dèanamh cinntach gu bheil na ceanglaichean a' dol dha na h-àitichean ceart.\n\nThoir an aire <strong>nach dèid</strong> an duilleag a ghluasad ma tha duilleag air an tiotal ùr mu thràth ach ma bhios e falamh no 'na ath-sheòladh 's mur eil eachdraidh deasachaidh ann.\n'S ciall dha seo gun urrainn dhut ainm duilleige a thilleadh dhan ainm a bha air roimhe ma rinn thu mearachd agus nach urrainn dhut sgrìobhadh thairis air duilleag a tha ann.\n\n<strong>Rabhadh!</strong>\nFaodaidh seo a bhith 'na atharrachadh mòr ris nach bi dùil air duilleag air a bheil fèill mhòr;\ndèan cinnteach gu bheil thu a' tuigsinn dè a' bhuaidh a bhios agad mus dèid thu air adhart.",
+       "movepagetext-noredirectfixer": "Ma chleachdas tu am foirm gu h-ìosal, cuiridh tu ainm ùr air 's gluaisidh tu a h-eachdraidh gu lèir dhan ainm ùr.\nBidh an seann tiotal 'na ath-stiùireadh dhan tiotal ùr an uairsin.\nDearbhaich nach bi ath-sheòlaidhean [[Special:DoubleRedirects|dùbailte]] no [[Special:BrokenRedirects|briste]] ann.\n'S ann ort-sa a tha an t-uallach airson dèanamh cinnteach gu bheil na ceanglaichean a' dol dha na h-àitichean a bu chòir.\n\nThoir an aire <strong>nach dèid</strong> an duilleag a ghluasad ma tha duilleag air an tiotal ùr mu thràth ach ma bhios e falamh no 'na ath-sheòladh 's mur eil eachdraidh deasachaidh ann.\n'S ciall dha seo gur urrainn dhut ainm duilleige a thilleadh dhan ainm a bha air roimhe ma rinn thu mearachd agus nach urrainn dhut sgrìobhadh thairis air duilleag a tha ann.\n\n<strong>Rabhadh!</strong>\nFaodaidh seo a bhith 'na atharrachadh mòr ris nach bi dùil air duilleag air a bheil fèill mhòr;\ndèan cinnteach gu bheil thu a' tuigsinn dè a' bhuaidh a bhios agad mus dèid thu air adhart.",
        "movepagetalktext": "Thèid an duilleag deasbaireachd a tha co-cheangailte ris a ghluasad 'na cois <strong>ach:</strong>\n*Ma tha duilleag deasbaireachd nach eil falamh aig an ainm ùr mu thràth, no\n*Ma bheir thu air falbh a' chromag on bhogsa gu h-ìosal\n\nMa thachras seo, feumaidh to an duilleag a ghluasad no cho-aonachadh a làimh, ma tha sin fa-near dhut.",
        "movearticle": "Gluais duilleag:",
-       "movecategorypage-warning": "<strong>Rachadh:</strong> Tha thu airson duilleag roinn-seòrsa a ghluasad. Thoir an aire nach dèid ach an duilleag a ghluasad 's <em>gur ann nach dèid</em> gach duilleag a tha san t-seann roinn-seòrsa a chur ris an roinn-seòrsa ùr.",
+       "moveuserpage-warning": "<strong>Rabhadh:</strong> Tha thu airson duilleag cleachdaiche a ghluasad. Thoir an aire nach dèid ach an duilleag a ghluasad 's <em>gur ann nach dèid</em> ainm ùr a thoirt air a' chleachdaiche.",
+       "movecategorypage-warning": "<strong>Rabhadh:</strong> Tha thu airson duilleag roinn-seòrsa a ghluasad. Thoir an aire nach dèid ach an duilleag a ghluasad 's <em>gur ann nach dèid</em> gach duilleag a tha san t-seann roinn-seòrsa a chur ris an roinn-seòrsa ùr.",
+       "movenologintext": "Feumaidh tu a bhith 'nad bhall clàraichte 's air [[Special:UserLogin|logadh a-steach]] mus gluais thu duilleag.",
+       "movenotallowed": "Chan eil cead agad duilleagan a ghluasad.",
+       "movenotallowedfile": "Chan eil cead agad faidhlichean a ghluasad.",
+       "cant-move-user-page": "Chan eil cead agad duilleagan cleachdaiche a ghluasad (ach fo-dhuilleagan).",
+       "cant-move-to-user-page": "Chan eil cead agad duilleag a ghluasad gu duilleag cleachdaiche (ach gu fo-dhuilleag cleachdaiche).",
        "cant-move-category-page": "Chan eil cead agad duilleagan roinn-seòrsa a ghluasad.",
        "cant-move-to-category-page": "Chan eil cead agad duilleag a ghluasad gu duilleag roinn-seòrsa.",
        "newtitle": "Dhan tiotal ùr:",
        "movepagebtn": "Gluais duilleag",
        "pagemovedsub": "Shoirbhich leat leis a' ghluasad",
        "movepage-moved": "<strong>Chaidh \"$1\" a ghluasad a \"$2\"</strong>",
+       "movepage-moved-redirect": "Chaidh ath-stiùireadh a chruthachadh.",
        "movepage-moved-noredirect": "Chaidh cruthachadh an ath-stiùiridh seo a mhùchadh.",
        "articleexists": "Tha duilleag ann mu thràth air a bheil an t-ainm seo no chan eil an t-ainm a thagh thu dligheachd.\nNach tagh thu ainm eile?",
+       "cantmove-titleprotected": "Chan urrainn dhut duilleag a ghluasad dhan ionad seo on a chaidh an tiotal ùr a dhìon o chruthachadh",
        "movetalk": "Gluais an duilleag deasbaireachd a tha co-cheangailte ris",
+       "move-subpages": "Gluais fo-duilleagan (suas ri $1)",
        "move-talk-subpages": "Gluais na fo-dhuilleagan aig duilleag deasbaireachd (suas ri $1)",
+       "movepage-page-exists": "Chan duilleag air a bheil $1 ann mar-thà 's cha ghabh sgrìobhadh thairis oirre gu fèin-obrachail.",
+       "movepage-page-moved": "Chaidh duilleag $1 a ghluasad gu $2.",
+       "movepage-page-unmoved": "Cha b' urrainn dhuinn duilleag $1 a ghluasad gu $2.",
+       "movepage-max-pages": "Tha na tha ceadaichte de $1 {{PLURAL:$1|duilleag|dhuilleag|duilleagan|duilleag}} a ghluasad 's cha dèid a bharrachd dhiubh a ghluasad gu fèin-obrachail.",
        "movelogpage": "Loga nan gluasadan",
+       "movelogpagetext": "Chì thu liosta dhe na duilleagan a chaidh gluasad gu h-ìosal.",
        "movesubpage": "{{PLURAL:$1|Fo-dhuilleag|Fo-dhuilleagan}}",
+       "movesubpagetext": "Tha $1 {{PLURAL:$1|fho-dhuilleag|fho-dhuilleag|fo-dhuilleagan|fo-dhuilleag}} aig an duilleag seo a chì thu gu h-ìosal.",
+       "movenosubpage": "Chan eil fo-dhuilleag aig an duilleag seo.",
        "movereason": "Adhbhar:",
        "revertmove": "till",
        "delete_and_move": "Sguab às agus gluais",
+       "delete_and_move_text": "== Tha sguabadh às a dhìth ==\nTha an duilleag-uidhe \"[[:$1]]\" ann mar-thà.\nA bheil thu airson a sguabadh às ach am bidh rum airson a' ghluasaid ann?",
        "delete_and_move_confirm": "Siuthad, sguab às an duilleag",
+       "delete_and_move_reason": "Chaidh a sguabadh às gus rum a airson a' ghluasaid o \"[[$1]]\" a chruthachadh",
+       "selfmove": "Tha tiotalan an tùis a' chinn-uidhe co-ionnann;\nchan urrainn dhut duilleag a ghluasad dhan ionad aice fhèin.",
        "immobile-source-namespace": "Cha ghabh duilleagan a ghluasad san ainm-spàs \"$1\"",
        "immobile-target-namespace": "Cha ghabh duilleagan a ghluasad dhan ainm-spàs \"$1\"",
+       "immobile-target-namespace-iw": "Chan eil ceangal eadar-uicidh 'na cheann-uidhe dligheach airson gluasad duilleige.",
+       "immobile-source-page": "Cha ghabh an duilleag seo gluasad.",
+       "immobile-target-page": "Cha ghabh gluasad gu tiotal a' chinn-uidhe seo.",
+       "bad-target-model": "Tha an ceann-uidhe a dh'iarr thu a' chleachdadh modail susbainte eadar-dhealaichte. Cha ghabh iompachadh o $1 gu $2,",
        "imagenocrossnamespace": "Cha ghabh faidhle a ghluasad gu ainm-spàs nach eil 'na fhaidhle",
        "nonfile-cannot-move-to-file": "Cha ghabh rud nach eil 'na fhaidhle a ghluasad gu ainm-spàs a bheil 'na fhaidhle",
+       "imagetypemismatch": "Cha fhreagair leudachan an fhaidhle ùir ri a sheòrsa",
+       "imageinvalidfilename": "Tha ainm-uidhe an fhaidhle mì-dhligheach",
+       "fix-double-redirects": "Ùraich gach ath-stiùireadh a thomhas ris an tiotail tùsail",
+       "move-leave-redirect": "Fàg ath-stiùireadh ann",
+       "protectedpagemovewarning": "<strong>Rabhadh: Chaidh an duilleag seo a dhìon 's chan urrainn ach dhan fheadhainn aig a bheil ùghdarras rianaire a ghluasad.</strong>\nChì thu an clàr mu dheireadh san loga mar fhiosrachadh dhut gu h-ìosal:",
+       "semiprotectedpagemovewarning": "<strong>An aire:</strong> Chaidh an duilleag seo a dhìon 's chan fhaod ach cleachdaichean clàraichte a ghluasad.\nSeo an rud mu dheireadh san loga mar fhiosrachadh dhut:",
        "move-over-sharedrepo": "== Tha am faidhle ann ==\nTha [[:$1]] ann an ionad-tasgaidh co-roinnte. Thèid tar-àithneadh air an fhaidhle cho-roinnte ma ghluaiseas tu faidhle gun tiotal seo.",
        "file-exists-sharedrepo": "Tha ainm an fhaidhle a thagh thu 'ga chleachdadh ann an ionad-tasgaidh co-roinnte mar-thà.\nFeuch an tagh thu ainm eile.",
        "export": "Às-phortaich duilleagan",
+       "exporttext": "'S urrainn dhut teacsa is eachdraidh an deasachaidh aig duilleag no duilleagan sònraichte às-phortachadh le XML timcheall air.\nGabhaidh seo ion-phortachadh gu uicidh eile a chleachdas MediaWiki air an [[Special:Import|duilleag ion-phortachaidh]].\n\nGus duilleagan às-phortachadh, cuir a-steach na tiotalan sa bhogsa-teacsa gu h-ìosal, gach tiotal air loidhne fa leth, agus tagh a bheil thu ag iarraidh am mùthadh làithreach cho math ri seann mhùthaidhean le loidhnichean eachdraidh nan duilleagan no a bheil thu ag iarraidh am mùthadh làithreach le fiosrachadh mun deasachadh mu dheireadh.\n\nMa chuir thu an roghainn eile romhad, 's urrainn dhut ceangal a chleachdadh cuideachd, mar eisimpleir [[{{#Special:Export}}/{{MediaWiki:Mainpage}}]] airson na duilleige \"[[{{MediaWiki:Mainpage}}]]\".",
+       "exportall": "Às-phortaich na duilleagan uile",
+       "exportcuronly": "Cha ghabh a-steach ach an tionndadh làithreach seach an eachdraidh slàn",
+       "exportnohistory": "----\n<strong>An aire:</strong> Chaidh às-phortachadh na h-eachdraidh slàin aig na duilleagan seo leis an foirm seo a chur à comas air sàilleibh dèanadais.",
        "exportlistauthors": "Cuir liosta shlàn dhe na deasaichean ris gach duilleag",
+       "export-submit": "Às-phortaich",
        "export-addcattext": "Cuir duilleagan ris o roinn-seòrsa:",
+       "export-addcat": "Cuir ris",
        "export-addnstext": "A h-uile duilleag on ainm-spàs:",
+       "export-addns": "Cuir ris",
+       "export-download": "Sàbhail mar fhaidhle",
+       "export-templates": "Gabh a-steach na teamplaidean",
+       "export-pagelinks": "Gabh a-steach na duilleagan ceangailte gu doimhe de:",
        "allmessages": "Teachdaireachdan an t-siostaim",
        "allmessagesname": "Ainm",
        "allmessagesdefault": "Teacsa bunaiteach na teachdaireachd",
+       "allmessagescurrent": "Teacsa na teachdaireachd an-dràsta",
        "allmessagestext": "Seo liosta de theachdaireachdan an t-siostaim a tha ri làimh ann an ainm-spàs MediaWiki.\nTadhail air [https://www.mediawiki.org/wiki/Special:MyLanguage/Localisation Ionadaileadh MediaWiki] is [//translatewiki.net translatewiki.net] ma tha thu airson pàirt a ghabhail ann an ionadaileadh MediaWiki.",
+       "allmessagesnotsupportedDB": "Cha ghabh an duilleag seo cleachdadh on a chaidh <strong>$wgUseDatabaseMessages</strong> a chur à comas.",
+       "allmessages-filter-legend": "Criathrag",
+       "allmessages-filter": "Criathraich le staid a' ghnàthachaidh:",
+       "allmessages-filter-unmodified": "Gun atharrachadh",
+       "allmessages-filter-all": "Na h-uile",
+       "allmessages-filter-modified": "Air atharrachadh",
+       "allmessages-prefix": "Criathraich le ro-leasachan:",
+       "allmessages-language": "Cànan:",
+       "allmessages-filter-submit": "Siuthad",
+       "allmessages-filter-translate": "Eadar-theangachaich",
        "thumbnail-more": "Meudaich",
        "filemissing": "Faidhle a dhìth",
        "thumbnail_error": "Mearachd le cruthachadh na dealbhaige: $1",
+       "thumbnail_error_remote": "Teachdaireachd na mearachd o $1:\n$2",
+       "djvu_page_error": "Tha duilleag DjVu a-mach às an rainse",
+       "djvu_no_xml": "Cha b' urrainn dhuinn an XML fhaighinn airson an fhaidhle DjVu",
        "thumbnail-temp-create": "Cha deach leinn faidhle sealach na dealbhaige a chruthachadh",
        "thumbnail-dest-create": "Cha deach leinn an dealbhag a shàbhaladh gun cheann-uidhe",
        "thumbnail_invalid_params": "Paramadairean na dealbhaige mì-dhligheach",
+       "thumbnail_dest_directory": "Cha b' urrainn dhuinn am pasgan-uidhe a chruthachadh",
+       "thumbnail_image-type": "Cha chuirear taic ris an t-seòrsa deilbh",
+       "thumbnail_gd-library": "Chan eil rèiteachadh na tasglainn GD coileanta: Tha am foincsean $1 a dhìth",
+       "thumbnail_image-missing": "Tha faidhle a dhìth a-rèit coltais: $1",
        "thumbnail_image-failure-limit": "Chaidh feuchainn cus tursan ($1 no a bharrachd) o chionn goirid gus an dealbhag seo a reandaradh. Feuch ris a-rithist uaireigin eile.",
+       "import": "Ion-phortaich duilleagan",
+       "importinterwiki": "Ion-phortachadh tar-uicidh",
+       "import-interwiki-text": "Tagh uicidh 's tiotal na duilleige airson ion-phortachadh.\nThèid cinn-là nam mùthaidhean 's ainmean nan deasaichean a ghlèidheadh.\nThèid gach gnìomh ion-phortachadh tar-uicidh a chur ris an [[Special:Log/import|loga ion-phortachaidh]].",
+       "import-interwiki-source": "An uicidh/duilleag thùsail:",
+       "import-interwiki-history": "Dèan lethbhreac de dh'eachdraidh nam mùthaidhean slàna airson na duilleige seo",
+       "import-interwiki-templates": "Gabh a-steach na teamplaidean uile",
+       "import-interwiki-submit": "Ion-phortaich",
        "import-interwiki-namespace": "Ainm-spàs-uidhe:",
+       "import-interwiki-rootpage": "Duilleag freumha a' chinn-uidhe (roghainneil):",
+       "import-upload-filename": "Ainm an fhaidhle:",
+       "import-comment": "Beachd:",
+       "importtext": "Às-phortaich am faidhle on uicidh tùsail le [[Special:Export|goireas an às-phortachaidh]].\nSàbhail e air a' choimpiutair agad is luchdaich suas e an-seo.",
+       "importstart": "Af ion-phortachadh duilleagan...",
        "import-revision-count": "$1 {{PLURAL:$1|mhùthadh|mhùthadh|mùthaidhean|mhùthadh}}",
+       "importnopages": "Chan eil duilleag ri ion-phortachadh ann.",
+       "imported-log-entries": "Chaidh $1 {{PLURAL:$1|innteart|innteart|innteartan|innteart}} an loga ion-phortachadh.",
+       "importfailed": "Dh'fhàillig leis an ion-phortachadh: <nowiki>$1</nowiki>",
+       "importunknownsource": "Chan aithnich sinn seòrsa an tùis airson an ion-phortachaidh",
+       "importcantopen": "Cha deach leinn am faidhle ion-phortachaidh fhosgladh.",
+       "importbadinterwiki": "Droch cheangal eadar-uicodh",
+       "importsuccess": "Tha an t-ion-phortachadh coileanta!",
+       "importnosources": "Cha deach tùs ion-phortachadh tar-uicidh a mhìneachadh agus tha luchdadh suas dìreach nan eachdraidhean à comas.",
+       "importnofile": "Cha deach faidhle ion-phortachaidh a luchdadh suas.",
+       "importuploaderrorsize": "Dh'fhàillig le luchdadh suas an fhaidhle ion-phortachaidh.\nTha am faidhle nas motha na tha ceadaichte.",
+       "importuploaderrorpartial": "Dh'fhàillig le luchdadh suas an fhaidhle ion-phortachaidh.\nCha deach ach pàirt dhen fhaidhle a luchdadh suas.",
+       "importuploaderrortemp": "Dh'fhàillig le luchdadh suas an fhaidhle ion-phortachaidh.\nTha pasgan sealach a dhìth.",
+       "import-parse-failure": "Dh'fhàillig le parsadh an XML ion-phortachaidh",
+       "import-noarticle": "Chan eil duilleag ri ion-phortachadh ann!",
+       "import-nonewrevisions": "Cha deach mùthadh ion-phortachadh (bha iad uile ann roimhe no chaidh an leigeil seachad ri linn mhearachdan).",
+       "xml-error-string": "$1 air loidhne $2, colbh $3 (baidht $4): $5",
+       "import-upload": "Luchdaich suas dàta XML",
+       "import-token-mismatch": "Chaidh dàta an t-seisein air chall.\nFeuch ris a-rithist.",
+       "import-invalid-interwiki": "Cha ghabh ion-phortachadh in uicidh a shònraich thu.",
+       "import-error-edit": "Cha deach an duilleag \"$1\" ion-phortachadh o nach fhaod thu a deasachadh.",
+       "import-error-create": "Cha deach an duilleag \"$1\" ion-phortachadh o nach fhaod thu a cruthachadh.",
+       "import-error-interwiki": "Cha deach an duilleag \"$1\" ion-phortachadh on a chaidh ainm a ghlèidheadh airson ceangal a-mach (eadar-uicidh).",
        "import-error-special": "Cha deach an duilleag \"$1\" ion-phortadh on a bhuineas i ri ainm-spàs sònraichte nach ceadaich duilleagan.",
+       "import-error-invalid": "Cha deach an duilleag \"$1\" ion-phortachadh on a tha ainm mì-dhligheach.",
+       "import-error-unserialize": "Cha ghabh mùthadh $2 dhen duilleag \"$1\" a thogail on tionndadh serialized. Chaidh aithris gun cleachd am mùthadh modail susbaint $3 a tha serialized mar $4.",
+       "import-error-bad-location": "Cha ghabh am mùthadh $2 a chleachdas modail susbainte $3 a stòradh air \"$1\" air an uicidh seo o nach cuir an duilleag ud taic ris a' mhodail seo.",
+       "import-options-wrong": "{{PLURAL:$2|Roghainn cearr|Roghainnean cearra}}: <nowiki>$1</nowiki>",
+       "import-rootpage-invalid": "Tha an duilleag freumha a chaidh a thoirt seachad 'na thiotal mì-dhligheach.",
        "import-rootpage-nosubpage": "Cha cheadaich an t-ainm-spàs \"$1\" aig an duilleag freumha fo-duilleagan.",
+       "importlogpage": "Loga an ion-phortachaidh",
+       "importlogpagetext": "Ion-phortachadh rianachd de dhuilleagan aig a bheil eachdraidh mhùthaidhean o uicidhean eile.",
+       "import-logentry-upload": "chaidh [[$1]] ion-phortachadh le luchdadh suas faidhle",
        "import-logentry-upload-detail": "$1 {{PLURAL:$1|mhùthadh|mùthadh|mùthaidhean|mùthadh}}",
+       "import-logentry-interwiki": "air fhaighinn 'na thar-uicidh $1",
        "import-logentry-interwiki-detail": "$1 {{PLURAL:$1|mhùthadh|mhùthadh|mùthaidhean|mùthadh}} o $2",
+       "javascripttest": "Deuchainn air JavaScript",
+       "javascripttest-title": "A' ruith deuchainnean aig $1",
+       "javascripttest-pagetext-noframework": "Tha an duilleag seo glèidhte airson deuchainnean JavaScript a ruith.",
+       "javascripttest-pagetext-unknownframework": "Framework deuchainn \"$1\" neo-aithnichte.",
+       "javascripttest-pagetext-frameworks": "Feuch an tagh thu aon dhe na frameworks deuchainn seo: $1",
+       "javascripttest-pagetext-skins": "Tagh craiceann airson ruith nan deuchainnean:",
+       "javascripttest-qunit-intro": "Faic [$1 docamaideadh nan deuchainnean] air mediawiki.org.",
+       "javascripttest-qunit-heading": "MediaWiki JavaScript QUnit test suite",
        "tooltip-pt-userpage": "An duilleag phearsanta agad",
+       "tooltip-pt-anonuserpage": "Duilleag a' chleachdaiche airson an t-seòlaidh IP leis a bheil thu a' deasachadh",
        "tooltip-pt-mytalk": "Duilleag do dheasbaireachd",
+       "tooltip-pt-anontalk": "deasbaireachd mu dheasachaidhean on t-seòladh IP seo",
        "tooltip-pt-preferences": "Do roghainnean",
        "tooltip-pt-watchlist": "Seo liosta nan duilleagan a tha thu a' cumail sùil orra a thaobh mhùthaidhean a nithear orra",
        "tooltip-pt-mycontris": "Liosta na h-obrach a rinn thu",
        "tooltip-ca-viewsource": "Tha an duilleag seo fo dhìon.\n'S urrainn dhut a tùs fhaicinn",
        "tooltip-ca-history": "Seann mhùthaidhean na duilleige seo",
        "tooltip-ca-protect": "Dìon an duilleag seo",
+       "tooltip-ca-unprotect": "Atharraich dìon na duilleige seo",
        "tooltip-ca-delete": "Sguab às an duilleag seo",
+       "tooltip-ca-undelete": "Aisig na deasachaidhean a chaidh a dhèanamh air an duilleag seo mus deach a sguabadh às",
        "tooltip-ca-move": "Gluais an duilleag seo",
        "tooltip-ca-watch": "Cuir an duilleag seo air mo chlàr-faire",
        "tooltip-ca-unwatch": "Thoir an duilleag seo far mo chlàir-fhaire",
        "tooltip-t-permalink": "Dèan ceangal buan gu mùthadh seo na duilleige",
        "tooltip-ca-nstab-main": "Seall duilleag na susbainte",
        "tooltip-ca-nstab-user": "Seall duilleag a' chleachdaiche",
+       "tooltip-ca-nstab-media": "Seall duilleag a' mheadhain",
        "tooltip-ca-nstab-special": "Seo duilleag shònraichte, chan urrainn dhut an duilleag fhèin a dheasachadh",
        "tooltip-ca-nstab-project": "Seall duilleag a' phròiseict",
        "tooltip-ca-nstab-image": "Seall duilleag an fhaidhle",
+       "tooltip-ca-nstab-mediawiki": "Seall teachdaireachd an t-siostaim",
        "tooltip-ca-nstab-template": "Seall an teamplaid",
+       "tooltip-ca-nstab-help": "Seall duilleag na cobharach",
        "tooltip-ca-nstab-category": "Seall duilleag na roinn-seòrsa",
        "tooltip-minoredit": "Comharraich seo mar dheasachadh beag",
        "tooltip-save": "Sàbhail na mùthaidhean agad",
        "tooltip-preview": "Ro-sheall na mùthaidhean agad; saoil an cleachd thu seo mus sàbhail thu iad?",
        "tooltip-diff": "Seall na mùthaidhean a chuir mi air an teacs",
        "tooltip-compareselectedversions": "Seall an diofar eadar an dà mhùthadh dhen duilleag seo a thagh thu",
-       "tooltip-watch": "Cuir an duilleag seo air do chlàr-faire",
+       "tooltip-watch": "Cuir an duilleag seo ris a' chlàr-fhaire agad",
+       "tooltip-watchlistedit-normal-submit": "Thoir tiotalan air falbh",
        "tooltip-watchlistedit-raw-submit": "Ùraich an clàr-faire",
+       "tooltip-recreate": "Ath-chruthaich an duilleag seo ged a chaidh a sguabadh às",
+       "tooltip-upload": "Tòisich air an luchdadh suas",
        "tooltip-rollback": "Ma chleachdas tu \"Roilig air ais\", tillidh thu gach mùthadh a rinn deasaiche àraid le aon bhriogadh",
        "tooltip-undo": "Tillidh \"Neo-dhèan\" am mùthadh seo 's fosglaidh e am foirm mùthaidh ann am modh an ro-sheallaidh. 'S urrainn dhut adhbhar a chur an cèill sa ghearr-chunntas air an dòigh seo.",
+       "tooltip-preferences-save": "Sàbhail na roghainnean",
        "tooltip-summary": "Cuir a-steach gearr-chunntas",
+       "interlanguage-link-title": "$1 – $2",
+       "interlanguage-link-title-nonlang": "$1 – $2",
+       "common.css": "/* Thèid an CSS a chuireas tu an-seo a chur an sàs air a h-uile craiceann */",
+       "print.css": "/* Bidh buaidh aig an CSS a chuireas tu an-seo air às-chur a' clò-bhualaidh */",
+       "noscript.css": "/* Bidh buaidh aig an CSS a chuireas tu an-seo air na daoine aig a bheil JavaScript à comas */",
+       "group-autoconfirmed.css": "/* Cha bhi buaidh aig an CSS a chuireas tu an-seo ach air cleachdaichean fèin-dearbhte */",
+       "group-user.css": "/* Cha bhi buaidh aig an CSS a chuireas tu an-seo ach air cleachdaichean clàraichte */",
+       "group-bot.css": "/* Cha bhi buaidh aig an CSS a chuireas tu an-seo ach air botaichean */",
+       "group-sysop.css": "/* Cha bhi buaidh aig an CSS a chuireas tu an-seo ach air rianairean */",
+       "group-bureaucrat.css": "/* Cha bhi buaidh aig an CSS a chuireas tu an-seo ach air biurocratan */",
+       "common.js": "/* Thèid gach JavaScript a chuireas tu an-seo a luchdadh leis gach luchdadh duilleige airson a h-uile cleachdaiche. */",
+       "group-autoconfirmed.js": "/* Cha dèid an JavaScript a chuireas tu an-seo a luchdadh ach airson nan cleachdaichean fèin-dearbhte */",
+       "group-user.js": "/* Cha dèid an JavaScript a chuireas tu an-seo a luchdadh ach airson nan cleachdaichean clàraichte */",
+       "group-bot.js": "/* Cha dèid an JavaScript a chuireas tu an-seo a luchdadh ach airson botaichean */",
+       "group-sysop.js": "/* Cha dèid an JavaScript a chuireas tu an-seo a luchdadh ach airson rianairean */",
+       "group-bureaucrat.js": "/* Cha dèid an JavaScript a chuireas tu an-seo a luchdadh ach airson biurocratan */",
        "anonymous": "{{PLURAL:$1|Cleachdaiche|Cleachdaichean}} gun ainm o {{SITENAME}}",
        "siteuser": "cleachdaiche {{SITENAME}} $1",
+       "anonuser": "{{SITENAME}} cleachdaiche gun ainm $1",
+       "lastmodifiedatby": "Chaidh an duilleag seo a mhùthadh $1 $2 le $3 an turas mu dheireadh.",
        "othercontribs": "Stèidhichte air obair le $1.",
        "others": "eile",
        "siteusers": "{{PLURAL:$2|Cleachdaiche|Cleachdaichean}} {{SITENAME}} $1",
+       "anonusers": "{{PLURAL:$2|Cleachdaiche|Cleachdaichean}} {{SITENAME}} gun ainm $1",
+       "creditspage": "Cliù airson na duilleige",
+       "nocredits": "Chan eil fiosrachadh cliùtha ri làimh airson na duilleige seo.",
+       "spamprotectiontitle": "Chriathrag dìona o spama",
+       "spamprotectiontext": "Chaidh an teacsa a bha thu airson a shàbhaladh a bhacadh le criathrag an spama.\nDh'fhaoidte gun do dh'adhbharaich ceangal seo a cheanglas ri làrach a-muigh a tha air an dubh-liosta.",
+       "spamprotectionmatch": "Seo an teacsa a thug aire air a' chriathrag spama againn: $1",
+       "spambot_username": "Sgioblachadh spama aig MediaWiki",
+       "spam_reverting": "A' tilleadh dhan mhùthadh mu dheireadh anns nach eil ceangal gu $1",
+       "spam_blanking": "Cha ceangal gu $1 anns gach mùthadh, 'ga bhànachadh",
+       "spam_deleting": "Cha ceangal gu $1 anns gach mùthadh, 'ga sguabadh às",
+       "simpleantispam-label": "Dearbhadh an aghaidh spama.\n<strong>NA</strong> lìon seo!",
+       "pageinfo-title": "Fiosrachadh airson \"$1\"",
+       "pageinfo-not-current": "Duilich, ach cha ghabh am fiosrachadh seo a thoirt seachad airson seann mhùthaidhean.",
+       "pageinfo-header-basic": "Fiosrachadh bunasach",
+       "pageinfo-header-edits": "Eachdraidh an deasachaidh",
+       "pageinfo-header-restrictions": "Dìon na duilleige",
+       "pageinfo-header-properties": "Roghainnean na duilleige",
+       "pageinfo-display-title": "Tiotal a thèid a shealltainn",
+       "pageinfo-default-sort": "Iuchair bunaiteach an t-seòrsachaidh \\",
+       "pageinfo-length": "Faid na duilleige (ann am baidhtichean)",
+       "pageinfo-article-id": "ID na duilleige",
+       "pageinfo-language": "Cànan susbaint na duilleige",
+       "pageinfo-content-model": "Modail susbaint na duilleige",
+       "pageinfo-robot-policy": "Inneacsadh le robotairean",
+       "pageinfo-robot-index": "Ceadaichte",
+       "pageinfo-robot-noindex": "Neo-cheadaichte",
+       "pageinfo-views": "Air a sealltainn",
+       "pageinfo-watchers": "A' cumail sùil air",
+       "pageinfo-few-watchers": "Tha nas lugha na $1 a' cumail sùil air",
+       "pageinfo-redirects-name": "Ath-stiùiridhean dhan duilleag seo",
+       "pageinfo-redirects-value": "$1",
+       "pageinfo-subpages-name": "Fo-dhuilleagan",
+       "pageinfo-subpages-value": "$1 ($2 {{PLURAL:$2|ath-stiùireadh|ath-stiùireadh|ath-stiùiridhean|ath-stiùireadh}}; $3 {{PLURAL:$3|nach eil 'na ath-stiùireadh|nach eil 'nan ath-stiùireadh}})",
+       "pageinfo-firstuser": "Cruthaichear na duilleige",
+       "pageinfo-firsttime": "Ceann-là a chaidh a chruthachadh",
+       "pageinfo-lastuser": "An deasaiche mu deireadh",
+       "pageinfo-lasttime": "Ceann-là an deasachaidh mu dheireadh",
+       "pageinfo-edits": "Uiread nan deasachaidhean",
+       "pageinfo-authors": "Uiread nan ùghdaran fa leth",
+       "pageinfo-recent-edits": "Uiread nan deasachaidhean o chionn goirid (o chionn $1)",
+       "pageinfo-recent-authors": "Uiread nan ùghdaran fa leth o chionn goirid",
+       "pageinfo-magic-words": "{{PLURAL:$1|Facal|Faclan}} draoidheach ($1)",
        "pageinfo-hidden-categories": "{{PLURAL:$1|Roinn-seòrsa fhalaichte|Roinnean-seòrsa falaichte}} ($1)",
+       "pageinfo-templates": "{{PLURAL:$1|Teamplaid 'ga gabhail a-steach 'na iomradh|Teamplaidean 'gan gabhail a-steach 'nan iomradh}} ($1)",
+       "pageinfo-transclusions": "{{PLURAL:$1|Duilleag 'ga gabhail a-steach 'na iomradh|Duilleagan 'gan gabhail a-steach 'nan iomradh}} air ($1)",
        "pageinfo-toolboxlink": "Fiosrachadh mun duilleag",
+       "pageinfo-redirectsto": "'Na ath-stiùireadh gu",
+       "pageinfo-redirectsto-info": "fiosrachadh",
+       "pageinfo-contentpage": "'Ga chunntadh 'na duilleag susbainte",
+       "pageinfo-contentpage-yes": "Seadh",
        "pageinfo-protect-cascading": "'Ga dhìon o bhith mar eas on a sheo",
+       "pageinfo-protect-cascading-yes": "Seadh",
        "pageinfo-protect-cascading-from": "'Ga dhìon o bhith mar eas uaithe",
        "pageinfo-category-info": "Fiosrachadh mun roinn-seòrsa",
+       "pageinfo-category-pages": "Àireamh de dhuilleagan",
        "pageinfo-category-subcats": "Àireamh de fho-roinnean-seòrsa",
+       "pageinfo-category-files": "Àireamh de dh'fhaidhlichean",
        "markaspatrolleddiff": "Cuir comharra freiceadain ris",
        "markaspatrolledtext": "Cuir comharra freiceadain ris an duilleag seo",
        "markedaspatrolled": "Comharra freiceadain ris",
        "patrol-log-page": "Loga nam freiceadan",
        "patrol-log-header": "Seo loga nam mùthaidhean le comharra freiceadain riutha.",
        "log-show-hide-patrol": "$1 loga nam freiceadan",
+       "deletedrevision": "Chaidh an seann mhùthadh $1 a sguabadh às",
+       "filedeleteerror-short": "Mearachd a' sguabadh às an fhaidhle: $1",
+       "filedeleteerror-long": "Thachair mearachd le sguabadh às an fhaidhle:\n\n$1",
+       "filedelete-missing": "cha ghabh am faidhle \"$1\" a sguabadh às o nach eil e ann.",
+       "filedelete-old-unregistered": "chan eil am mùthadh \"$1\" aig an fhaidhle san stòr-dàta.",
+       "filedelete-current-unregistered": "chan eil am faidhle \"$1\" a chaidh a thoirt seachad san stòr-dàta.",
+       "filedelete-archive-read-only": "Chan urrainn dhan fhrithealaiche-lìn sgrìobhadh sa phasgan tasglainn \"$1\".",
        "previousdiff": "← Mùthadh nas sine",
        "nextdiff": "Deasachadh nas ùire →",
+       "mediawarning": "<strong>Rabhadh:</strong> dh'fhaoidte gu bheil còd droch-rùnach am broinn an t-seòrsa faidhle seo.\nDh'fhaoidte gun tèid tèarainteachd an t-siostaim agad a bhriseadh ma ruitheas tu e.",
        "imagemaxsize": "Crìochan air meud an deilbh:<br /><em>(airson duilleagan tuairisgeul an fhaidhle)</em>",
        "thumbsize": "Meud na dealbhaige:",
+       "widthheight": "$1 × $2",
+       "widthheightpage": "$1 × $2, $3 {{PLURAL:$3|duilleag|dhuilleag|duilleagan|duilleag}}",
+       "file-info": "meud an fhaidhle: $1, seòrsa MIME: $2",
        "file-info-size": "$1 × $2 pixel, meud an fhaidhle: $3, seòrsa MIME: $4",
+       "file-info-size-pages": "$1 × $2 piogsail, meud an fhaidhle: $3, seòrsa MIME: $4, $5 {{PLURAL:$5|duilleag|dhuilleag|duilleagan|duilleag}}",
        "file-nohires": "Chan eil dùmhlachd-bhreacaidh nas fhearr ri fhaighinn.",
        "svg-long-desc": "Faidhle SVG, a-rèir ainm $1 × $2 pixel, meud faidhle: $3",
+       "svg-long-desc-animated": "Faidhle SVG beòthaichte, a-rèir ainm $1 × $2 pixel, meud faidhle: $3",
+       "svg-long-error": "Faidhle SVG mì-dhligheach: $1",
        "show-big-image": "Am faidhle tùsail",
+       "show-big-image-preview": "Meud an ro-sheallaidh seo: $1.",
+       "show-big-image-other": "{{PLURAL:$2|Dùmhlachd-bhreacaidh|Dùmhlachdan-breacaidh}} eile: $1.",
+       "show-big-image-size": "$1 × $2 piogsail",
+       "file-info-gif-looped": "lùbte",
+       "file-info-gif-frames": "$1 {{PLURAL:$1|fhrèam|fhrèam|frèaman|frèam}}",
+       "file-info-png-looped": "lùbte",
+       "file-info-png-repeat": "air a chluich $1 {{PLURAL:$1|turas|thuras|tursan|turas}}",
+       "file-info-png-frames": "$1 {{PLURAL:$1|fhrèam|fhrèam|frèaman|frèam}}",
        "file-no-thumb-animation": "<strong>An aire: Cha bhi beòthachadh air dealbhagan an fhaidhle seo ri linn cuingeachaidhean teicnigeach.</strong>",
        "file-no-thumb-animation-gif": "<strong>An aire: Cha bhi beòthachadh air dealbhagan airson dealbhan GIF le dùmhlachd-bhreacaidh àrd mar an tè seo ri linn cuingeachaidhean teicnigeach.</strong>",
+       "newimages": "Gailearaidh nan dealbhan ùra",
+       "imagelisttext": "Chì thu liosta dhe <strong>$1</strong> {{PLURAL:$1|fhaidhle|fhaidhle|faidhlichean|faidhle}} gu h-ìosal air {{PLURAL:$1|a sheòrsachadh|an seòrsachadh}} $2.",
+       "newimages-summary": "Seallaidh an duilleag shònraichte seo na faidhlichean as ùire a chaidh a luchdadh suas.",
+       "newimages-legend": "Criathrag",
+       "newimages-label": "Ainm faidhle (no pàirt dheth):",
+       "newimages-showbots": "Seall luchdaidhean suas le botaichean",
+       "noimages": "Chan eil dad ri fhaicinn an-seo.",
        "ilsubmit": "Rannsaich",
        "bydate": "air ceann-latha",
+       "sp-newimages-showfrom": "Seall na faidhlichean ùra a-mach o $1 $2",
+       "video-dims": "$1, $2 × $3",
+       "seconds-abbrev": "$1 diog",
+       "minutes-abbrev": "$1 mion",
+       "hours-abbrev": "$1 uair",
+       "days-abbrev": "$1 là",
+       "seconds": "{{PLURAL:$1|$1 diog|$1 dhiog|$1 diogan|$1 diog}}",
+       "minutes": "{{PLURAL:$1|$1 mhionaid|$1 mhionaid|$1 mionaidean|$1 mionaid}}",
+       "hours": "{{PLURAL:$1|$1 uair|$1 uair|$1 uairean|$1 uair}}",
+       "days": "{{PLURAL:$1|$1 latha|$1 latha|$1 làithean|$1 latha}}",
+       "weeks": "{{PLURAL:$1|$1 seachdain|$1 sheachdain|$1 seachdainean|$1 seachdain}}",
+       "months": "{{PLURAL:$1|$1 mhìos|$1 mhìos|$1 mìosan|$1 mìos}}",
+       "years": "{{PLURAL:$1|$1 bhliadhna|$1 bhliadhna|$1 bliadhnaichean|$1 bliadhna}}",
+       "ago": "o chionn $1",
+       "just-now": "an-dràsta fhèin",
+       "hours-ago": "o chionn $1 {{PLURAL:$1|uair|uair|uairean|uair}}",
+       "minutes-ago": "o chionn $1 {{PLURAL:$1|mhionaid|mhionaid|mionaidean|mionaid}}",
+       "seconds-ago": "o chionn $1 {{PLURAL:$1|diog|dhiog|diogan|diog}}",
+       "monday-at": "DiLuain $1",
+       "tuesday-at": "DiMàirt $1",
+       "wednesday-at": "DiChiadain $1",
+       "thursday-at": "DiarDaoin $1",
+       "friday-at": "DihAoine $1",
+       "saturday-at": "DiSathairne $1",
+       "sunday-at": "DiDòmhnaich $1",
+       "yesterday-at": "An-dè $1",
        "bad_image_list": "Seo mar a tha am fòrmat:\n\nCha bheachdaichear ach air buill liosta (loidhniche a tha * air am beulaibh).\nFeumaidh a' chiad cheangal air loidhne a bhith 'na cheangal ri droch fhaidhle.\nThathar a' coimhead air ceangal sam bith eile san loidhne sin mar eisgeachdan, 's e sin duilleagan far am faod am faidhle a bhith sa loidhne.",
        "metadata": "Metadata",
        "metadata-help": "Tha fiosrachadh a bharrachd san fhaidhle seo, 's mathaid o chamara digiteach no sganair a chaidh a chleachdadh gus a chruthachadh no a dhigiteachadh.\nMa chaidh am faidhle tùsail atharrachadh, faodaidh nach eil cuid dhen fhiosrachadh ceart a thaobh an fhaidhle atharraichte tuilleadh.",
        "metadata-expand": "Seall am fiosrachadh a bharrachd",
        "metadata-collapse": "Cuir am fiosrachadh a bharrachd am falach",
        "metadata-fields": "Thèid raointean meata-dhàta nan dealbhan a tha ainmichte san teachdaireachd seo a ghabhail a-steach air duilleag an deilbh nuair a bhios clàr a' mheata-dàta air a dhùmhlachadh.\nBidh an fheadhainn eile falaichte a ghnàth.\n* make\n* model\n* datetimeoriginal\n* exposuretime\n* fnumber\n* isospeedratings\n* focallength\n* artist\n* copyright\n* imagedescription\n* gpslatitude\n* gpslongitude\n* gpsaltitude",
+       "metadata-langitem": "<strong>$2:</strong> $1",
+       "metadata-langitem-default": "$1",
+       "exif-imagewidth": "Leud",
+       "exif-imagelength": "Àirde",
+       "exif-bitspersample": "Biod sa cho-phàirt",
+       "exif-compression": "Sgeama an dùmhlachaidh",
+       "exif-photometricinterpretation": "Co-dhèanamh nam piogsail",
+       "exif-orientation": "Comhair",
+       "exif-samplesperpixel": "Àireamh nan co-phàirtean",
+       "exif-planarconfiguration": "Rian an dàta",
+       "exif-xresolution": "Dùmhlachd-bhreacaidh chòmhnard",
+       "exif-yresolution": "Dùmhlachd-bhreacaidh inghearach",
+       "exif-stripoffsets": "Ionad dàta an deilbh",
+       "exif-jpeginterchangeformat": "Frith-àireamh gu JPEG SOI",
+       "exif-jpeginterchangeformatlength": "Baidhtichean de dhàta JPEG",
+       "exif-ycbcrcoefficients": "Co-èifeachdan a' mheatraigs atharrachaidh airson an spàs datha",
+       "exif-referenceblackwhite": "Càraid de luachan iomraidh dubh is geal",
+       "exif-datetime": "Ceann-là 's àm aig atharrachadh an fhaidhle",
+       "exif-imagedescription": "Tiotal an deilbh",
+       "exif-make": "Dèanadair a' chamara",
+       "exif-model": "Modail a' chamara",
+       "exif-software": "Am bathar-bog a chleachdadh",
+       "exif-artist": "Ùghdar",
        "exif-copyright": "Seilbheadair na còrach-lethbhreac",
+       "exif-exifversion": "Tionndadh de Exif",
+       "exif-flashpixversion": "An tionndadh de Flashpix ris an cuirear taic",
+       "exif-colorspace": "Spàs datha",
+       "exif-componentsconfiguration": "Ciall aig gach co-phàirt",
+       "exif-compressedbitsperpixel": "Modh dùmhlachd-bhreacaidh an deilbh",
+       "exif-pixelydimension": "Leud an deilbh",
+       "exif-pixelxdimension": "Àirde an deilbh",
+       "exif-usercomment": "Beachdan nan cleachdaichean",
+       "exif-relatedsoundfile": "Faidhle fuaime co-cheangailte ris",
+       "exif-datetimeoriginal": "Ceann-là 's àm a chaidh an dàta a chruthachadh",
+       "exif-datetimedigitized": "Ceann-là 's àm a chaidh cruth digiteach a chur air an dàta",
+       "exif-subsectime": "Fo-dhiogan cinn-là 's ama",
+       "exif-subsectimeoriginal": "Fo-dhiogan cinn-là 's ama thùsail",
+       "exif-subsectimedigitized": "Fo-dhiogan cinn-là 's ama an dreach digitich",
+       "exif-exposuretime": "Ùine deisearais",
+       "exif-exposuretime-format": "$1 diog ($2)",
+       "exif-fnumber": "Àireamh F",
+       "exif-fnumber-format": "f/$1",
+       "exif-exposureprogram": "Prògram deisearais",
+       "exif-spectralsensitivity": "Mothalachd speictreach",
+       "exif-isospeedratings": "Rangachadh astar ISO",
+       "exif-shutterspeedvalue": "Luaths siutair APEX",
+       "exif-aperturevalue": "Fosgladh APEX",
+       "exif-brightnessvalue": "Soilleireachd APEX",
+       "exif-exposurebiasvalue": "Claonadh deisearais APEX",
+       "exif-subjectdistance": "Astar a' chuspair",
+       "exif-meteringmode": "Modh meidheachaidh",
+       "exif-lightsource": "Tùs an t-solais",
+       "exif-flash": "Solas-boillsgidh",
+       "exif-focallength": "Faid fòcas an lionsa",
+       "exif-focallength-format": "$1 mm",
+       "exif-subjectarea": "Raon a' chuspair",
+       "exif-flashenergy": "Lùths an t-solais boillsgidh",
+       "exif-focalplanexresolution": "Dùmhlachd-bhreacaidh X aig plèana an fhòcais",
+       "exif-focalplaneyresolution": "Dùmhlachd-bhreacaidh Y aig plèana an fhòcais",
+       "exif-focalplaneresolutionunit": "Aonad dùmhlachd-breacaidh aig plèana an fhòcais",
+       "exif-subjectlocation": "Ionad a' chuspair",
+       "exif-exposureindex": "Inneacs deisearais",
+       "exif-sensingmethod": "Dòigh a' mhothaicheir",
+       "exif-filesource": "Tùs an fhaidhle",
+       "exif-scenetype": "Seòrsa an t-seallaidh",
+       "exif-customrendered": "Pròiseasadh gnàthaichte an deilbh",
+       "exif-exposuremode": "Modh deisearais",
+       "exif-whitebalance": "Meidh na gile",
+       "exif-digitalzoomratio": "Co-mheas an t-sùma dhigitich",
+       "exif-focallengthin35mmfilm": "Faid fòcas an am film 35 mm",
+       "exif-scenecapturetype": "Seòrsa glacaidh-sgrìn",
+       "exif-gaincontrol": "Smachd air an t-seallaidh",
+       "exif-contrast": "Iomsgaradh",
+       "exif-saturation": "Sàthachd",
+       "exif-sharpness": "Geurad",
        "exif-devicesettingdescription": "Tuairisgeul aig roghainnean an uidheim",
+       "exif-subjectdistancerange": "Rainse astar a' chuspair",
+       "exif-imageuniqueid": "ID fa leth an deilbh",
+       "exif-gpsversionid": "Tionndadh dhen taga GPS",
+       "exif-gpslatituderef": "Domhan-leud tuath no deas",
+       "exif-gpslatitude": "Domhan-leud",
+       "exif-gpslongituderef": "Domhan-fhad ear no siar",
+       "exif-gpslongitude": "Domhan-fhad",
+       "exif-gpsaltituderef": "Iomradh na h-àirde",
+       "exif-gpsaltitude": "Àirde",
+       "exif-gpstimestamp": "Àm GPS (uaireadair atomach)",
+       "exif-gpssatellites": "Saidealan a chaidh a chleachdadh airson an tomhais",
+       "exif-gpsstatus": "Staid a' ghlacadair",
+       "exif-gpsmeasuremode": "Modh an tomhais",
+       "exif-gpsdop": "Pongalachd an tomhais",
+       "exif-gpsspeedref": "Aonad an luaiths",
+       "exif-gpsspeed": "Luaths a' ghlacadair GPS",
+       "exif-gpstrackref": "Iomradh airson comhair a' ghluasaid",
+       "exif-gpstrack": "Comhair a' ghluasaid",
+       "exif-gpsimgdirectionref": "Iomradh airson comhair an deilbh",
+       "exif-gpsimgdirection": "Comhair an deilbh",
+       "exif-gpsdestlatituderef": "Iomradh airson domhan-leud a' chinn-uidhe",
+       "exif-gpsdestlatitude": "Domhan-leud a' chinn-uidhe",
+       "exif-gpsdestlongituderef": "Iomradh airson domhan-fhad a' chinn-uidhe",
+       "exif-gpsdestlongitude": "Domhan-fhad a' chinn-uidhe",
+       "exif-gpsdestbearingref": "Iomradh airson comhair a' chinn-uidhe",
+       "exif-gpsdestbearing": "Comhair a' chinn-uidhe",
+       "exif-gpsdestdistanceref": "Iomradh airson astar on cheann-uidhe",
+       "exif-gpsdestdistance": "Astar on cheann-uidhe",
+       "exif-gpsprocessingmethod": "Ainm air modh pròiseasadh GPS",
+       "exif-gpsareainformation": "Ainm raon GPS",
+       "exif-gpsdatestamp": "Ceann-là GPS",
+       "exif-gpsdifferential": "Ceartachadh diofarail GPS",
+       "exif-coordinate-format": "$1° $2′ $3″ $4",
+       "exif-jpegfilecomment": "Beachd faidhle JPEG",
+       "exif-keywords": "Facalan-luirg",
+       "exif-worldregioncreated": "An roinn-dùthcha san deach an dealbh a thogail",
+       "exif-countrycreated": "An dùthaich san deach an dealbh a thogail",
+       "exif-countrycodecreated": "Còd na dùthcha san deach an dealbh a thogail",
+       "exif-provinceorstatecreated": "An t-siorrachd no còigeamh san deach an dealbh a thogail",
+       "exif-citycreated": "Am baile san deach an dealbh a thogail",
+       "exif-sublocationcreated": "An t-ionad sa bhaile san deach an dealbh a thogail",
+       "exif-worldregiondest": "Tha an roinn-dùthcha 'ga sealltainn",
+       "exif-countrydest": "Tha an dùthaich 'ga sealltainn",
+       "exif-countrycodedest": "Tha còd na dùthcha air 'ga sealltainn",
+       "exif-provinceorstatedest": "Tha an t-siorrachd no còigeamh 'ga sealltainn",
+       "exif-citydest": "Tha am baile 'ga shealltainn",
+       "exif-sublocationdest": "Tha an t-ionad sa bhaile 'ga shealltainn",
+       "exif-objectname": "Tiotal goirid",
+       "exif-specialinstructions": "Stiùireadh sònraichte",
+       "exif-headline": "Ceann-sgrìobhadh",
+       "exif-credit": "Cliù/Solaraiche",
+       "exif-source": "Tùs",
+       "exif-editstatus": "Staid deasachaidh an deilbh",
+       "exif-urgency": "Èiginneachd",
+       "exif-fixtureidentifier": "Ainm nì shocraichte",
+       "exif-locationdest": "An t-ionad san dealbh",
+       "exif-locationdestcode": "Còs an ionaid san dealbh",
+       "exif-objectcycle": "Àm an latha iomchaidh airson a' mheadhain",
+       "exif-contact": "Fiosrachadh conaltraidh",
+       "exif-writer": "Sgrìobhadair",
+       "exif-languagecode": "Cànan",
+       "exif-iimversion": "Tionndadh de IIM",
        "exif-iimcategory": "Roinn-seòrsa",
        "exif-iimsupplementalcategory": "Roinnean-seòrsa foirlionach",
+       "exif-datetimeexpires": "Na cleachd às dèidh",
+       "exif-datetimereleased": "'Ga sgaoileadh o",
+       "exif-originaltransmissionref": "Còd ionaid tùsail an tar-chuir",
+       "exif-identifier": "Aithnichear",
+       "exif-lens": "An lionsa a chaidh a chleachdadh",
+       "exif-serialnumber": "Àireamh shreathach a' chamara",
+       "exif-cameraownername": "Seilbheadair a' chamara",
+       "exif-label": "Leubail",
+       "exif-datetimemetadata": "An ceann-là a chaidh am meata-dàta atharrachadh an turas mu dheireadh",
+       "exif-nickname": "Ainm neo-fhoirmeil an deilbh",
+       "exif-rating": "Rangachadh (a-mach à 5)",
+       "exif-rightscertificate": "Teisteanas rianachd chòraichean",
        "exif-copyrighted": "Staid na còrach-lethbhreac",
        "exif-copyrightowner": "Seilbheadair na còrach-lethbhreac",
+       "exif-usageterms": "Teirmichean a' chleachdaidh",
        "exif-webstatement": "Aithris na còrach-lethbhreac air loidhne",
+       "exif-originaldocumentid": "ID fa leth na sgrìobhainn tùsail",
        "exif-licenseurl": "URL airson ceadachas na còrach-lethbhreac",
+       "exif-morepermissionsurl": "Fiosrachadh ceadachais eile",
+       "exif-attributionurl": "Nuair a chleachdas sibh an obair seo, dèanaibh ceangal gu",
+       "exif-preferredattributionname": "Nuair a chleachdas sibh an obair seo, thoiribh cliù do",
+       "exif-pngfilecomment": "Beachd faidhle PNG",
+       "exif-disclaimer": "Aithris-àichidh",
+       "exif-contentwarning": "Rabhadh susbainte",
+       "exif-giffilecomment": "Beachd faidhle GIF",
+       "exif-intellectualgenre": "Seòrsa na susbainte",
+       "exif-subjectnewscode": "Còd a' chuspair",
+       "exif-scenecode": "Còd seallaidh IPTC",
+       "exif-event": "Tachartas san dealbh",
+       "exif-organisationinimage": "Buidheann san dealbh",
+       "exif-personinimage": "Neach sa dealbh",
+       "exif-originalimageheight": "Àirde an deilbh mus deach a bhearradh",
+       "exif-originalimagewidth": "Leud an deilbh mus deach a bhearradh",
        "exif-contact-value": "$1\n\n$2\n<div class=\"adr\">\n$3\n\n$4, $5, $6 $7\n</div>\n$8",
        "exif-subjectnewscode-value": "$2 ($1)",
        "exif-compression-1": "Gun dùmhlachadh",
+       "exif-compression-3": "Còdachadh facs CCITT Group 3",
+       "exif-compression-4": "Còdachadh facs CCITT Group 4",
        "exif-compression-5": "LZW",
        "exif-compression-6": "JPEG (sean)",
        "exif-compression-7": "JPEG",
        "exif-exposureprogram-0": "Gun mhìneachadh",
        "exif-exposureprogram-1": "A làimh",
        "exif-exposureprogram-2": "Prògram àbhaisteach",
+       "exif-exposureprogram-3": "Prìomhachas fosglaidh",
+       "exif-exposureprogram-4": "Prìomhachas siutair",
+       "exif-exposureprogram-5": "Prògram cruthachail (le claonadh gu doimhne an raoin)",
+       "exif-exposureprogram-6": "Prògram gluasaid (le claonadh gu siutair luath)",
+       "exif-exposureprogram-7": "Modh portraid (airson dealbhan faisg gun fhòcas air a' chùlaibh)",
+       "exif-exposureprogram-8": "Modh crutha-tìre (airson dealbhan crutha-tìre le fòcas air a' chùlaibh)",
        "exif-subjectdistance-value": "$1 {{PLURAL:$1|mheatair|mheatair|meatairean|meatair}}",
        "exif-meteringmode-0": "Chan eil fhios",
        "exif-meteringmode-1": "Cuibheasach",
+       "exif-meteringmode-2": "Cuibheas le cuideam sa bheadhan",
+       "exif-meteringmode-3": "Spot",
+       "exif-meteringmode-4": "Iomadh-spot",
+       "exif-meteringmode-5": "Pàtran",
+       "exif-meteringmode-6": "Leth-phàirteach",
        "exif-meteringmode-255": "Eile",
        "exif-lightsource-0": "Chan eil fhios",
+       "exif-lightsource-1": "Eile",
+       "exif-lightsource-2": "Fluaraiseach",
+       "exif-lightsource-3": "Tungstan (solas-dealain)",
+       "exif-lightsource-4": "Solas-boillsgidh",
+       "exif-lightsource-9": "Deagh shìde",
+       "exif-lightsource-10": "Sìde neulach",
+       "exif-lightsource-11": "Sgàil",
+       "exif-lightsource-12": "Fluaraiseach solas an latha (D 5700 – 7100K)",
+       "exif-lightsource-13": "Fluaraiseach geal an latha (N 4600 – 5400K)",
+       "exif-lightsource-14": "Fluaraiseach geal fuair (W 3900 – 4500K)",
+       "exif-lightsource-15": "Fluaraiseach geal (WW 3200 – 3700K)",
+       "exif-lightsource-17": "Solas stannardach A",
+       "exif-lightsource-18": "Solas stannardach B",
+       "exif-lightsource-19": "Solas stannardach C",
        "exif-lightsource-20": "D55",
        "exif-lightsource-21": "D65",
        "exif-lightsource-22": "D75",
        "exif-lightsource-23": "D50",
-       "exif-flash-mode-2": "bacadh riatanach air an t-solas-boillsgidh",
+       "exif-lightsource-24": "Tungstan stiùideo ISO",
+       "exif-lightsource-255": "Tùs solais eile",
+       "exif-flash-fired-0": "Cha deach an solas-boillsgidh air",
+       "exif-flash-fired-1": "Chaidh an solas-boillsgidh air",
+       "exif-flash-return-0": "gun fhoincsean mothachaidh airson an t-solais-bhoillsgidh",
+       "exif-flash-return-2": "cha deach solas-boillsgidh a mhothachadh",
+       "exif-flash-return-3": "chaidh solas-boillsgidh a mhothachadh",
+       "exif-flash-mode-1": "solas-boillsgidh riatanach",
+       "exif-flash-mode-2": "bacadh riatanach air an t-solas-bhoillsgidh",
        "exif-flash-mode-3": "modh fèin-obrachail",
+       "exif-flash-function-1": "Gun solas-boillsgidh",
+       "exif-flash-redeye-1": "modh lùghdachadh nan sùilean dearga",
        "exif-focalplaneresolutionunit-2": "òirleach",
        "exif-sensingmethod-1": "Gun mhìneachadh",
+       "exif-sensingmethod-2": "Mothaichear raon datha aon-sgeilbe",
+       "exif-sensingmethod-3": "Mothaichear raon datha dà-sgeilbe",
+       "exif-sensingmethod-4": "Mothaichear raon datha trì-sgeilbe",
+       "exif-sensingmethod-5": "Mothaichear raon datha sreathach",
+       "exif-sensingmethod-7": "Mothaichear trì-loidhneach",
+       "exif-sensingmethod-8": "Mothaichear datha sreathach loidhneach",
+       "exif-filesource-3": "Camara dhealbhan digiteach",
+       "exif-scenetype-1": "Dealbh a chaidh a thogail gu dìreach",
+       "exif-customrendered-0": "Pròiseas àbhaisteach",
+       "exif-customrendered-1": "Pròiseas gnàthaichte",
+       "exif-exposuremode-0": "Deisearas fèin-obrachail",
+       "exif-exposuremode-1": "Deisearas a làimh",
+       "exif-exposuremode-2": "Bracaid fèin-obrachail",
+       "exif-whitebalance-0": "Meidh na gile fèin-obrachail",
+       "exif-whitebalance-1": "Meidh na gile a làimh",
+       "exif-scenecapturetype-0": "Stannardach",
+       "exif-scenecapturetype-1": "Dreach-tìre",
+       "exif-scenecapturetype-2": "Portraid",
+       "exif-scenecapturetype-3": "Sealladh oidhche",
        "exif-gaincontrol-0": "Chan eil gin",
+       "exif-gaincontrol-1": "Buannachd ìosal suas",
+       "exif-gaincontrol-2": "Buannachd àrd suas",
+       "exif-gaincontrol-3": "Buannachd ìosal sìos",
+       "exif-gaincontrol-4": "Buannachd àrd sìos",
+       "exif-contrast-0": "Àbhaisteach",
+       "exif-contrast-1": "Lag",
+       "exif-contrast-2": "Cruaidh",
+       "exif-saturation-0": "Àbhaisteach",
+       "exif-saturation-1": "Sàthachd ìosal",
+       "exif-saturation-2": "Sàthachd àrd",
+       "exif-sharpness-0": "Àbhaisteach",
+       "exif-sharpness-1": "Lag",
+       "exif-sharpness-2": "Cruaidh",
+       "exif-subjectdistancerange-0": "Chan eil fios",
+       "exif-subjectdistancerange-1": "Macro",
+       "exif-subjectdistancerange-2": "Sealladh dlùth",
+       "exif-subjectdistancerange-3": "Sealladh aig astar",
+       "exif-gpslatitude-n": "Domhan-leud tuath",
+       "exif-gpslatitude-s": "Domhan-leud deas",
+       "exif-gpslongitude-e": "Domhan-fhad ear",
+       "exif-gpslongitude-w": "Domhan-fhad siar",
+       "exif-gpsaltitude-above-sealevel": "$1 {{PLURAL:$1|mheatair|mheatair|meatairean|meatair}} os cionn àirde na mara",
+       "exif-gpsaltitude-below-sealevel": "$1 {{PLURAL:$1|mheatair|mheatair|meatairean|meatair}} fo àirde na mara",
+       "exif-gpsstatus-a": "'Ga thomhas",
+       "exif-gpsstatus-v": "Comas eadar-obrachadh an tomhais",
+       "exif-gpsmeasuremode-2": "Tomhas air 2 dhimeinsean",
+       "exif-gpsmeasuremode-3": "Tomhas air 3 dimeinseanan",
        "exif-gpsspeed-k": "Cilemeatair san uair",
        "exif-gpsspeed-m": "Mìle gach uair",
        "exif-gpsspeed-n": "Mìle-mara san uair",
        "exif-gpsdestdistance-k": "Cilemeatair",
        "exif-gpsdestdistance-m": "Mìle",
        "exif-gpsdestdistance-n": "Mìle-mara",
+       "exif-gpsdop-excellent": "Sgoinneil ($1)",
+       "exif-gpsdop-good": "Math ($1)",
+       "exif-gpsdop-moderate": "Meadhanach ($1)",
+       "exif-gpsdop-fair": "Ceart gu leòr ($1)",
+       "exif-gpsdop-poor": "Dona ($1)",
+       "exif-objectcycle-a": "Sa madainn a-mhàin",
+       "exif-objectcycle-p": "Feasgar a-mhàin",
+       "exif-objectcycle-b": "An dà chuid sa mhadainn 's feasgar",
+       "exif-gpsdirection-t": "Fìor-chomhair",
+       "exif-gpsdirection-m": "Comhair mhagnaiteach",
+       "exif-ycbcrpositioning-1": "Meadhanaichte",
        "exif-dc-contributor": "Deasaichean",
+       "exif-dc-coverage": "Sgòp na h-aite no ama aig a' mheadhan",
        "exif-dc-date": "Ceann-là",
        "exif-dc-publisher": "Foillsichear",
        "exif-dc-relation": "Meadhanan co-cheangailte",
        "exif-rating-rejected": "Air a dhiùltadh",
        "exif-isospeedratings-overflow": "Nas motha na 65535",
        "exif-maxaperturevalue-value": "$1 APEX (f/$2)",
-       "watchlistall2": "a h-uile",
-       "namespacesall": "uile",
-       "monthsall": "uile",
+       "exif-iimcategory-ace": "Na h-ealain, cultar 's dibhearsan",
+       "exif-iimcategory-clj": "Eucoir 's lagha",
+       "exif-iimcategory-dis": "Dunaidh 's tubhaistean",
+       "exif-iimcategory-fin": "Eaconamaidh 's gnìomhachas",
+       "exif-iimcategory-edu": "Foghlam",
+       "exif-iimcategory-evn": "An àrainneachd",
+       "exif-iimcategory-hth": "Slàinte",
+       "exif-iimcategory-hum": "Daoine",
+       "exif-iimcategory-lab": "Obair",
+       "exif-iimcategory-lif": "Dòigh-bheatha 's cur-seachad",
+       "exif-iimcategory-pol": "Polataigs",
+       "exif-iimcategory-rel": "Creideamh",
+       "exif-iimcategory-sci": "Saidheans 's teicneolas",
+       "exif-iimcategory-soi": "Cuspairean sòisealta",
+       "exif-iimcategory-spo": "Spòrs",
+       "exif-iimcategory-war": "Cogadh, còmhstri 's aramach",
+       "exif-iimcategory-wea": "Aimsir",
+       "exif-urgency-normal": "Àbhaisteach ($1)",
+       "exif-urgency-low": "Ìosal ($1)",
+       "exif-urgency-high": "Àrd ($1)",
+       "exif-urgency-other": "Prìomhachas gnàthaiche ($1)",
+       "watchlistall2": "na h-uile",
+       "namespacesall": "na h-uile",
+       "monthsall": "na h-uile",
+       "confirmemail": "Dearbh an seòladh puist-dhealain",
+       "confirmemail_noemail": "Cha dug thu seachad seòladh puist-d dligheach ann an [[Special:Preferences|roghainnean a' chleachdaiche]] agad.",
+       "confirmemail_text": "Iarraidh {{SITENAME}} ort gun dearbh thu an seòladh puist-d agad mus cleachd thu feartan puist-d.\nCleachd am putan gu h-ìosal gus post-d dearbhaidh a chur dhan t-seòladh agad.\nBidh ceangal le còd sa phost-d ud;\nluchdaich an ceangal sa bhrabhsair agad airson dearbhadh gu bheil an seòladh puist-d agad dligheach.",
+       "confirmemail_pending": "Chaidh còd dearbhaidh a chur thugad air a' phost-d mar-thà;\nma tha thu air a' chunntas agad a chruthachadh o chionn goirid, 's math dh'fhaoidte gum b' feairrde thu feitheamh mionaid no dhà ach an ruig e thu mus iarr thu còd ùr.",
+       "confirmemail_send": "Cuir còd dearbhaidh thugam",
+       "confirmemail_sent": "Chaidh post-d dearbhaidh a chur.",
+       "confirmemail_oncreate": "Chaidh còd dearbhaidh a chur dhan t-seòladh puist-d agad.\nChan eil thu feumach air a' chòd seo airson logadh a-steach, ach feumaidh tu a thoirt seachad mus cleachd thu feart sam bith san uicidh a chleachdas post-d.",
+       "confirmemail_sendfailed": "Cha deach le {{SITENAME}} post-d dearbhaidh a chur thugad.\nDearbhaich nach eil caractar mì-dhligheach san t-seòladh puist-d agad.\n\nSeo na thill an t-inneal puist-d: $1",
+       "confirmemail_invalid": "Tha an còd dearbhaidh mì-dhligheach.\n'S dòcha gun do dh'fhalbh an ùine air.",
+       "confirmemail_needlogin": "$1 gus an seòladh puist-d agad a dhearbhadh.",
+       "confirmemail_success": "Chaidh an seòladh puist-d agad a dhearbhadh.\nFaodaidh tu [[Special:UserLogin|logadh a-steach]] a-nis 's tlachd a ghabhail às an uicidh.",
+       "confirmemail_loggedin": "Tha an seòladh puist-d agad air a dhearbhadh a-nis.",
+       "confirmemail_subject": "Dearbhadh an t-seòlaidh puist-d air {{SITENAME}}",
+       "confirmemail_body": "Chlàraich chuideigin - 's sinne an dùil gur e tusa a bh' ann - cunntas \"$2\"\nair {{SITENAME}} leis an t-seòladh puist-d seo on t-seòladh IP $1.\n\nGus dearbhadh gur an agad fhèin a tha an cunntas seo agus gus na feartan puist-d\na ghnìomhachadh air {{SITENAME}}, fosgail an ceangal seo sa bhrabhsair agad:\n\n$3\n\nMur e *tusa* a bh' ann a chlàraich an cunntas seo, lean air a' cheangal seo\ngus sgur dhen dearbhadh leis a' phost-d:\n\n$5\n\nFalbhaidh an ùine air a' chòd dearbhaidh seo $4.",
+       "confirmemail_body_changed": "Dh'atharraich chuideigin - 's sinne an dùil gur e tusa a bh' ann - an seòladh puist-d\naig a' chunntas \"$2\" air {{SITENAME}} dhan t-seòladh puist-d seo on t-seòladh IP $1.\n\nGus dearbhadh gur an agad fhèin a tha an cunntas seo agus gus na feartan puist-d\na ghnìomhachadh às ùr air {{SITENAME}}, fosgail an ceangal seo sa bhrabhsair agad:\n\n$3\n\nMur e *tusa* a bh' ann a chlàraich an cunntas seo, lean air a' cheangal seo\ngus sgur dhen dearbhadh leis a' phost-d:\n\n$5\n\nFalbhaidh an ùine air a' chòd dearbhaidh seo $4.",
+       "confirmemail_body_set": "Shuidhich chuideigin - 's sinne an dùil gur e tusa a bh' ann - an seòladh puist-d\naig a' chunntas \"$2\" air {{SITENAME}} dhan t-seòladh puist-d seo on t-seòladh IP $1.\n\nGus dearbhadh gur an agad fhèin a tha an cunntas seo agus gus na feartan puist-d\na ghnìomhachadh air {{SITENAME}}, fosgail an ceangal seo sa bhrabhsair agad:\n\n$3\n\nMur e *tusa* a bh' ann a chlàraich an cunntas seo, lean air a' cheangal seo\ngus sgur dhen dearbhadh leis a' phost-d:\n\n$5\n\nFalbhaidh an ùine air a' chòd dearbhaidh seo $4.",
+       "confirmemail_invalidated": "Chaidh sgur de dhearbhadh an t-seòlaidh puist-d",
+       "invalidateemail": "Sguir de dhearbhadh an t-seòlaidh puist-d",
+       "scarytranscludedisabled": "[Tha gabhail a-steach 'na iomradh eadar-uicidh à comas]",
+       "scarytranscludefailed": "[Dh'fhàillig le fhaighinn na teamplaid airson $1]",
+       "scarytranscludefailed-httpstatus": "[Dh'fhàillig le fhaighinn na teamplaid airson $1: HTTP $2]",
+       "scarytranscludetoolong": "[Tha an URL ro fhada]",
+       "deletedwhileediting": "<strong>Rabhadh:</strong> Chaidh an duilleag seo a sguabadh às às dèidh do thòiseachadh leis an deasachadh oirre!",
        "confirmrecreate": "Sguab [[User:$1|$1]] ([[User talk:$1|an deasbaireachd]]) an duilleag seo às às dèidh do thòiseachadh air an deasachadh air an adhbhar seo:\n: <em>$2</em>\nDearbhaich gu bheil thu airson an duilleag seo ath-chruthachadh dha-rìribh.",
        "confirmrecreate-noreason": "Sguab [[User:$1|$1]] ([[User talk:$1|an deasbaireachd]]) an duilleag seo às às dèidh do thòiseachadh air an deasachadh.\nDearbhaich gu bheil thu airson an duilleag seo ath-chruthachadh dha-rìribh.",
+       "recreate": "Ath-chruthaich",
+       "unit-pixel": "px",
+       "confirm_purge_button": "Ceart ma-thà",
+       "confirm-purge-top": "A bheil thu airson tasgadan na duilleige seo a ghlanadh?",
+       "confirm-purge-bottom": "Ma ghlanas tu duilleag, falamhaichidh seo an tasgadan 's bheir e air am mùthadh as ùire gun nochd e.",
+       "confirm-watch-button": "Ceart ma-thà",
        "confirm-watch-top": "A bheil thu airson an duilleag seo a chur ris a' chlàr-fhaire agad?",
+       "confirm-unwatch-button": "Ceart ma-thà",
        "confirm-unwatch-top": "A bheil thu airson an duilleag seo a thoirt air falbh on chlàr-fhaire agad?",
+       "semicolon-separator": ";&#32;",
+       "comma-separator": ",&#32;",
+       "colon-separator": ":&#32;",
+       "pipe-separator": "&#32;|&#32;",
+       "word-separator": "&#32;",
+       "ellipsis": "...",
+       "percent": "$1%",
+       "parentheses": "($1)",
+       "brackets": "[$1]",
+       "quotation-marks": "\"$1\"",
+       "imgmultipageprev": "← an duilleag roimhpe",
+       "imgmultipagenext": "an ath-dhuilleag →",
+       "imgmultigo": "Siuthad!",
+       "imgmultigoto": "Rach gu duilleag $1",
+       "img-lang-opt": "$2 ($1)",
+       "img-lang-default": "(an cànan tùsail)",
+       "img-lang-info": "Reandaraich an dealbh seo sa: $1. $2",
+       "img-lang-go": "Siuthad",
+       "ascending_abbrev": "a' dìreadh",
+       "descending_abbrev": "a' teàrnadh",
+       "table_pager_next": "An ath-dhuilleag",
+       "table_pager_prev": "An duilleag roimhpe",
+       "table_pager_first": "A' chiad duilleag",
+       "table_pager_last": "An duilleag mu dheireadh",
+       "table_pager_limit": "Seall $1 nithean air gach duilleag",
+       "table_pager_limit_label": "Nithean air gach duilleag:",
+       "table_pager_limit_submit": "Siuthad",
+       "table_pager_empty": "Gun toradh",
+       "autosumm-blank": "Chaidh an duilleag a bhànachadh",
+       "autosumm-replace": "Chaidh \"$1\" a chur an àite na susbaint",
+       "autoredircomment": "Chaidh an duilleag ath-stiùireadh gu [[$1]]",
+       "autosumm-new": "Chaidh duilleag le \"$1\" a chruthachadh",
+       "size-bytes": "$1 B",
+       "size-kilobytes": "$1 KB",
+       "size-megabytes": "$1 MB",
+       "size-gigabytes": "$1 GB",
+       "size-terabytes": "$1 TB",
+       "size-petabytes": "$1 PB",
+       "size-exabytes": "$1 EB",
+       "size-zetabytes": "$1 ZB",
+       "size-yottabytes": "$1 YB",
+       "bitrate-bits": "$1 bps",
+       "bitrate-kilobits": "$1 kbps",
+       "bitrate-megabits": "$1 Mbps",
+       "bitrate-gigabits": "$1 Gbps",
+       "bitrate-terabits": "$1 Tbps",
+       "bitrate-petabits": "$1 Pbps",
+       "bitrate-exabits": "$1 Ebps",
+       "bitrate-zetabits": "$1 Zbps",
+       "bitrate-yottabits": "$1 Ybps",
+       "lag-warn-normal": "Dh'fhaoidte nach nochd atharraichean nas ùire na $1 {{PLURAL:$1|diog|dhiog|diogan|diog}} air an liosta seo.",
+       "lag-warn-high": "Air sàilleibh eallach air frithealaiche an stòir-dhàta, dh'fhaoidte nach nochd atharraichean nas ùire na $1 {{PLURAL:$1|diog|dhiog|diogan|diog}} air an liosta seo.",
        "watchlistedit-normal-title": "Deasaich an clàr-faire",
        "watchlistedit-normal-legend": "Thoir tiotalan air falbh on chlàr-fhaire",
        "watchlistedit-normal-explain": "Chì thu na tiotalan a tha air a' chlàr-fhaire agad gu h-ìosal.\nGus tiotal a thoirt air falbh, cuir cromag sa bhogsa ri thaobh 's briog air \"{{int:Watchlistedit-normal-submit}}\".\n'S urrainn dhut [[Special:EditWatchlist/raw|còd an liosta a dheasachadh]] cuideachd.",
        "watchlistedit-normal-done": "Chaidh {{PLURAL:$1|$1 tiotal|$1 thiotal|$1 tiotalan|$1 tiotal}} a thoirt far a' chlàir-fhaire agad:",
        "watchlistedit-raw-title": "Deasaich còd a' chlàir-fhaire",
        "watchlistedit-raw-legend": "Deasaich còd a' chlàir-fhaire",
+       "watchlistedit-raw-explain": "Chì thu na tiotalan air a' chlàr-fhaire agad gu h-ìosal agus 's urrainn dhut an deasachadh 's tu an cur ris 's a thoirt air falbh on liosta;\naon tiotal air gach loidhne.\nNuair a bhios tu deiseil, briog air \"{{int:Watchlistedit-raw-submit}}\".\n'S urrainn dhut [[Special:EditWatchlist|an deasaiche àbhaisteach]] a cleachdadh cuideachd.",
+       "watchlistedit-raw-titles": "Tiotalan:",
        "watchlistedit-raw-submit": "Ùraich an clàr-faire",
+       "watchlistedit-raw-done": "Chaidh an clàr-faire agad ùrachadh.",
+       "watchlistedit-raw-added": "Chaidh $1 {{PLURAL:$1|tiotal|thiotal|tiotalan|tiotal}} a chur ris:",
+       "watchlistedit-raw-removed": "Chaidh $1 {{PLURAL:$1|tiotal|thiotal|tiotalan|tiotal}} a thoirt air falbh:",
+       "watchlistedit-clear-title": "Clàr-faire air a ghlanadh",
+       "watchlistedit-clear-legend": "Glan an clàr-faire",
+       "watchlistedit-clear-explain": "Thèid a h-uile tiotal a thoirt far a' chlàr-fhaire agad",
+       "watchlistedit-clear-titles": "Tiotalan:",
+       "watchlistedit-clear-submit": "Glan an clàr-faire (falbhaidh iad gu buan!)",
+       "watchlistedit-clear-done": "Chaidh an clàr-faire agad a ghlanadh.",
+       "watchlistedit-clear-removed": "Chaidh $1 {{PLURAL:$1|tiotal|thiotal|tiotalan|tiotal}} a thoirt air falbh:",
+       "watchlistedit-too-many": "Tha cus duilleagan ann gus an sealltainn an-seo.",
+       "watchlisttools-clear": "Glan an clàr-faire",
        "watchlisttools-view": "Seall na mùthaidhean iomchaidh",
        "watchlisttools-edit": "Seall is deasaich mo chlàr-faire",
        "watchlisttools-raw": "Deasaich còd a' chlàir-fhaire",
        "signature": "[[{{ns:user}}:$1|$2]] ([[{{ns:user_talk}}:$1|an deasbaireachd]])",
+       "timezone-utc": "UTC",
+       "unknown_extension_tag": "Taga leudachain \"$1\" neo-aithnichte",
        "duplicate-defaultsort": "<strong>Rabhadh:</strong> Tha an iuchair seòrsachaidh bhunaiteach \"$2\" a' dol thairis air seann iuchair eile, \"$1\".",
        "version": "Tionndadh",
+       "version-extensions": "Leudachain air an stàladh",
+       "version-skins": "Craicnean",
+       "version-specialpages": "Duilleagan sònraichte",
+       "version-parserhooks": "Hooks a' pharsair",
+       "version-variables": "Caochladairean",
+       "version-antispam": "Dìon o spama",
+       "version-api": "API",
+       "version-other": "Eile",
+       "version-mediahandlers": "Làimhsichearan mheadhanan",
+       "version-hooks": "Hooks",
+       "version-parser-extensiontags": "Tagaichean leudachadh a' pharsair",
+       "version-parser-function-hooks": "Hooks foincsean a' pharsair",
+       "version-hook-name": "Ainm a' hook",
+       "version-hook-subscribedby": "'Ga fho-sgrìobhadh le",
+       "version-version": "($1)",
+       "version-no-ext-name": "[gun ainm]",
+       "version-svn-revision": "r$1",
+       "version-license": "Ceadachas MediaWiki",
+       "version-ext-license": "Ceadachas",
+       "version-ext-colheader-name": "Leudachan",
+       "version-skin-colheader-name": "Craiceann",
+       "version-ext-colheader-version": "Tionndadh",
+       "version-ext-colheader-license": "Ceadachas",
        "version-ext-colheader-description": "Tuairisgeul",
+       "version-ext-colheader-credits": "Ùghdaran",
+       "version-license-title": "Ceadachas airson $1",
+       "version-license-not-found": "Cha deach fiosrachadh mionaideach a' cheadachais a lorg airson an leudachain seo.",
+       "version-credits-title": "Cliù airson $1",
+       "version-credits-not-found": "Cha deach fiosrachadh mionaideach a' chliùtha a lorg airson an leudachain seo.",
        "version-poweredby-credits": "Tha an uicidh seo 'ga toirt dhut le cumhachd <strong>[https://www.mediawiki.org/ MediaWiki]</strong>, còir-lethbhreac © 2001-$1 $2.",
+       "version-poweredby-others": "eile",
+       "version-poweredby-translators": "eadar-theangadairean translatewiki.net",
        "version-credits-summary": "Bu toigh leinn urram a thoirt air na daoine a leanas air sgàth 's an cuid obrach airson [[Special:Version|MediaWiki]].",
+       "version-software": "Bathar-bog air a stàladh",
+       "version-software-product": "Bathar",
+       "version-software-version": "Tionndadh",
+       "version-entrypoints": "URLaichean puing-inntrigidh",
+       "version-entrypoints-header-entrypoint": "Puing-inntrigidh",
+       "version-entrypoints-header-url": "URL",
+       "version-entrypoints-articlepath": "[https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:$wgArticlePath Slighe artaigil]",
+       "version-entrypoints-scriptpath": "[https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:$wgScriptPath slighe sgriobt]",
+       "redirect": "Ath-stiùireadh le faidhle, cleachdaiche, duilleag no ID a' mhùthaidh",
+       "redirect-legend": "Cruthaich ath-stiùireadh gu faidhle no duilleag",
+       "redirect-summary": "Nì an duilleag shònraichte seo ath-stiùireadh gu faidhle (le ainm faidhle), duilleag (le ID a' mhùthaidh no ID na duilleige) no duilleag cleachdaiche (le àireamh ID a' chleachdaiche). Seo mar a chleachdas tu e: [[{{#Special:Redirect}}/file/Ball-eisimpleir.jpg]], [[{{#Special:Redirect}}/page/64308]], [[{{#Special:Redirect}}/revision/328429]] no [[{{#Special:Redirect}}/user/101]].",
+       "redirect-submit": "Siuthad",
+       "redirect-lookup": "Rannsaich:",
+       "redirect-value": "Luach:",
+       "redirect-user": "ID a' chleachdaiche",
+       "redirect-page": "ID na duilleige",
+       "redirect-revision": "Mùthadh na duilleige",
+       "redirect-file": "Ainm am fhaidhle",
+       "redirect-not-exists": "Cha deach an luach a lorg",
+       "fileduplicatesearch": "Lorg airson faidhlichean dùblaichte",
+       "fileduplicatesearch-summary": "Lorg airson faidhlichean dùblaichte, stèidhichte air luachan hais.",
+       "fileduplicatesearch-legend": "Lorg airson dùblachadh",
+       "fileduplicatesearch-filename": "Ainm an fhaidhle:",
+       "fileduplicatesearch-submit": "Lorg",
+       "fileduplicatesearch-info": "$1 × $2 piogsail<br />Meud an fhaidhle: $3<br />Seòrsa MIME: $4",
+       "fileduplicatesearch-result-1": "Chan eil dùblachadh co-ionnann aig an fhaidhle \"$1\".",
+       "fileduplicatesearch-result-n": "Tha $2 {{PLURAL:$2|dùblachadh co-ionnann|dhùblachadh co-ionnann|dùblachaidhean co-ionnann|dùblachadh co-ionnann}} aig an fhaidhle \"$1\".",
+       "fileduplicatesearch-noresults": "Cha deach faidhle air a bheil \"$1\" a lorg.",
        "specialpages": "Duilleagan sònraichte",
        "specialpages-note-top": "Treòir",
+       "specialpages-note": "* Duilleagan sònraichte coitcheann.\n* <span class=\"mw-specialpagerestricted\">Duilleagan sònraichte cuingichte.</span>",
+       "specialpages-group-maintenance": "Aithrisean na h-obrach-glèidhidh",
+       "specialpages-group-other": "Duilleagan sònraichte eile",
+       "specialpages-group-login": "Log a-steach / cruthaich cunntas",
+       "specialpages-group-changes": "Atharraichean 's logaichean o chionn goirid",
+       "specialpages-group-media": "Aithrisean mheadhanan 's luchdaidhean suas",
+       "specialpages-group-users": "Cleachdaichean 's ceadan",
+       "specialpages-group-highuse": "Duilleagan 'gan cleachdadh gu tric",
+       "specialpages-group-pages": "Liosta dhe na duilleagan",
+       "specialpages-group-pagetools": "Innealan nan duilleag",
+       "specialpages-group-wiki": "Ceann-là 's innealan",
+       "specialpages-group-redirects": "Duilleagan sònraichte a nì ath-stiùireadh",
+       "specialpages-group-spam": "Innealan spama",
+       "blankpage": "Duilleag bhàn",
+       "intentionallyblankpage": "Tha an duilleag seo bàn a dh'aona-ghothach.",
        "external_image_whitelist": " #Fàg an loidhne seo dìreach mar a tha e<pre>\n#Cuir mìrean nan regular expressions (dìreach a' phàirt eadar //) gu hìosal\n#Thèid seisean URL a lorg dhaibh am measg nan dealbhan air an taobh a-muigh (hotlinks)\n#Chithear an fheadhainn a tha a' freagairt ri seise a shealltainn air neo chithear ceangal dhan dealbh a-mhàin\n#Chan eil ann an loidhnichean a tha a' tòiseachadh le # ach beachdan\n#Chan eil aire do litrichean mòra no beaga\n\n#Cuir gach mì regex os cionn na loidhne seo. Fàg an loidhne seo dìreach mar a tha e</pre>",
+       "tags": "Tagaichean atharrachaidh dligheach",
        "tag-filter": "Criathrag [[Special:Tags|thagaichean]]:",
+       "tag-filter-submit": "Criathraich",
+       "tag-list-wrapper": "([[Special:Tags|{{PLURAL:$1|Taga|Tagaichean}}]]: $2)",
+       "tags-title": "Tagaichean",
+       "tags-intro": "Seallaidh an duilleag seo na tagaichean a chleachdas am bathar-bog gus deasachadh a chomharrachadh 's an ciall a th' orra.",
+       "tags-tag": "Ainm an taga",
+       "tags-display-header": "Dreach air liostaichean nan atharraichean",
        "tags-description-header": "Tuairisgeul slàn a' chèill",
+       "tags-active-header": "Gnìomhach?",
+       "tags-hitcount-header": "Atharraichean le tagaichean riutha",
+       "tags-active-yes": "Seadh",
+       "tags-active-no": "Chan eadh",
+       "tags-edit": "deasaich",
+       "tags-hitcount": "$1 {{PLURAL:$1|atharrachadh|atharrachadh|atharraichean|atharrachadh}}",
+       "comparepages": "Coimeas duillegan",
+       "compare-page1": "Duilleag 1",
+       "compare-page2": "Duilleag 2",
+       "compare-rev1": "Mùthadh 1",
+       "compare-rev2": "Mùthadh 2",
+       "compare-submit": "Coimeas",
+       "compare-invalid-title": "Tha an tiotal a shònraich thu mì-dhligheach.",
+       "compare-title-not-exists": "Chan eil an tiotal a shònraich thu ann.",
+       "compare-revision-not-exists": "Chan eil am mùthadh a shònraich thu ann.",
+       "dberr-problems": "Duilich! Tha trioblaid teicnigeach aig an làrach seo.",
+       "dberr-again": "Feitheamh mionaid no dhà 's ath-luchdaich i.",
+       "dberr-info": "(Chan obraich an conaltradh ri frithealaiche an stòir-dhàta: $1)",
+       "dberr-info-hidden": "(Chan obraich an conaltradh ri frithealaiche an stòir-dhàta)",
+       "dberr-usegoogle": "Feuch lorg le Google san eadar-àm.",
+       "dberr-outofdate": "Thoir an aire nach eil an clàr acasan air an t-susbaint againn cho ùr sa ghabhas ma dh'fhaoidte.",
+       "dberr-cachederror": "Seo lethbhreac dhen duilleag a dh'iarr thu on tasgadan 's chan eil e cho ùr 's a ghabhas, ma dh'fhaoidte.",
+       "htmlform-invalid-input": "Cha duilgheadas le cuid dhe na chuir thu a-steach.",
+       "htmlform-select-badoption": "Chan eil an luach a thug thu seachad 'na roghainn dhligheach.",
+       "htmlform-int-invalid": "Chan eil an luach a thug thu seachad 'na àireamh shlàn.",
+       "htmlform-float-invalid": "Chan eil an luach a thug thu seachad 'na àireamh.",
+       "htmlform-int-toolow": "Tha an luach a thug thu seachad ro bheag on a tha e nas lugha na $1.",
+       "htmlform-int-toohigh": "Tha an luach a thug thu seachad ro mhòr on a tha e nas motha na $1.",
+       "htmlform-required": "Tha an luach seo riatanach.",
+       "htmlform-submit": "Cuir a-null",
+       "htmlform-reset": "Neo-dhèan na h-atharraichean",
+       "htmlform-selectorother-other": "Eile",
+       "htmlform-no": "Chan eil",
+       "htmlform-yes": "Tha",
+       "htmlform-chosen-placeholder": "Tagh roghainn",
+       "htmlform-cloner-create": "Cuir barrachd ris",
+       "htmlform-cloner-delete": "Thoir air falbh",
+       "htmlform-cloner-required": "Tha luach a dhìth.",
+       "sqlite-has-fts": "$1 le taic ri lorg teacsa shlàin",
+       "sqlite-no-fts": "$1 gun taic ri lorg teacsa shlàin",
        "logentry-delete-delete": "Sguab $1 às duilleag $3",
        "logentry-delete-restore": "Dh'aisig $1 duilleag $3",
        "logentry-delete-event": "Dh'atharraich $1 an fhaicsinneachd aig $5 {{PLURAL:$5|tachartas|thachartas|tachartasan|tachartas}} an loga air $3: $4",
        "logentry-suppress-revision": "Dh'atharraich $1 an fhaicsinneachd aig $5 {{PLURAL:$5|mhùthadh|mhùthadh|mùthaidhean|mùthadh}} air $3 gu dìomhair: $4",
        "logentry-suppress-event-legacy": "Dh'atharraich $1 an fhaicsinneachd aig tachartasan an loga air $3 gu dìomhair",
        "logentry-suppress-revision-legacy": "Dh'atharraich $1 an fhaicsinneachd aig mùthaidhean air $3 gu dìomhair",
+       "revdelete-content-hid": "chaidh susbaint fhalach",
        "revdelete-summary-hid": "chaidh gearr-chunntas an deasachaidh fhalach",
+       "revdelete-uname-hid": "chaidh ainm-cleachdaiche fhalach",
+       "revdelete-content-unhid": "chaidh susbaint a neo-fhalach",
        "revdelete-summary-unhid": "chaidh gearr-chunntas an deasachaidh a nochdadh",
+       "revdelete-uname-unhid": "chaidh ainm-cleachdaiche a neo-fhalach",
+       "revdelete-restricted": "chaidh cuingeachaidhean a chur an sàs air rianairean",
+       "revdelete-unrestricted": "chaidh cuingeachaidhean a thoirt air falbh airson rianairean",
        "logentry-move-move": "Ghluais $1 duilleag $3 gu $4",
        "logentry-move-move-noredirect": "Ghluais $1 duilleag $3 gu $4 's cha do {{GENDER:$2|dh'fhàg e|dh'fhàg i|dh'fhàgadh}} ath-stiùireadh ann",
        "logentry-move-move_redir": "Ghluais $1 duilleag $3 gu $4 slighe ath-stiùiridh",
        "logentry-rights-rights-legacy": "Dh'atharraich $1 {{GENDER:$2|a bhallrachd|a ballrachd}} ann am buidheann airson $3",
        "logentry-rights-autopromote": "Chaidh $1 àrdachadh o $4 gu $5 gu fèin-obrachail",
        "rightsnone": "(chan eil gin)",
+       "feedback-bugornote": "Ma tha fiosrachadh mionaideach agad air duilgheadas teicnigeach, feuch an dèan thu [$1 aithris air buga].\nMur eil, 's urrainn dhut am foirm furasta a chleachdadh gu h-ìosal. Thèid do bheachd a chur ris an duilleag \"[$3 $2]\" is d' ainm-cleachdaiche a chur ris.",
+       "feedback-subject": "Cuspair:",
+       "feedback-message": "Teachdaireachd:",
+       "feedback-cancel": "Sguir dheth",
+       "feedback-submit": "Cuir do bheachd a-null",
+       "feedback-adding": "A' cur beachd ri duilleag...",
+       "feedback-error1": "Mearachd: Chan aithnich sinn toradh an API",
+       "feedback-error2": "Mearachd: Dh'fhàillig leis an deasachadh",
+       "feedback-error3": "Mearachd: Cha d' fhuair sinn freagairt on API",
+       "feedback-thanks": "Mòran taing! Chaidh do bheachd a phostadh air an duilleag \"[$2 $1]\".",
+       "feedback-close": "Dèanta",
+       "feedback-bugcheck": "Taghta! Dearbh nach eil e air [$1 liosta nam bugaichean air a bheil sinn eòlach] mar-thà.",
+       "feedback-bugnew": "Dhearbh mi seo. Dèan aithris air buga ur",
+       "searchsuggest-search": "Lorg",
        "searchsuggest-containing": "anns a bheil...",
+       "api-error-badaccess-groups": "Chan eil cead agad gus faidhlichean a luchdadh suas dhan uicidh seo.",
+       "api-error-badtoken": "Mearachd taobh a-staigh: Droch thòcan.",
+       "api-error-copyuploaddisabled": "Tha luchdadh suas le URL à comas air an fhrithealaiche seo.",
+       "api-error-duplicate": "Tha {{PLURAL:$1|[$2 faidhle eile]|are [$2 faidhlichean eile]}} air an làrach seo mar-thà sa bheil an aon susbaint.",
+       "api-error-duplicate-archive": "Tha {{PLURAL:$1|[$2 faidhle eile]|are [$2 faidhlichean eile]}} air an làrach seo mar-thà sa bheil an aon susbaint ach chaidh {{PLURAL:$1|a sguabadh|an sguabadh}} às.",
+       "api-error-duplicate-archive-popup-title": "Bha {{PLURAL:$1|am faidhle|na faidhlichean}} dùblaichte air {{PLURAL:$1|a|an}} sguabadh às mar-thà.",
+       "api-error-duplicate-popup-title": "{{PLURAL:$1|Faidhle|Faidhlichean}} dùblaichte.",
+       "api-error-empty-file": "Tha am faidhle a chuir thu a-null falamh.",
+       "api-error-emptypage": "Chan fhaodar duilleagan falamh ùra a chruthachadh.",
+       "api-error-fetchfileerror": "Mearachd taobh a-staigh: Chaidh rudeigin cearr le faighinn an fhaidhle.",
+       "api-error-fileexists-forbidden": "Tha faidhle air a bheil \"$1\" ann mar-thà 's cha ghabh sgrìobhadh thairis air.",
        "api-error-fileexists-shared-forbidden": "Tha faidhle air a bheil \"$1\" san ionad-tasgaich cho-roinnte mar-thà 's cha ghabh sgrìobhadh thairis air.",
+       "api-error-file-too-large": "Tha am faidhle a chuir thu a-null ro mhòr.",
+       "api-error-filename-tooshort": "Tha ainm an fhaidhle ro ghoirid.",
+       "api-error-filetype-banned": "Tha an seòrsa faidhle seo toirmisgte.",
+       "api-error-filetype-banned-type": "Chan eil $1 {{PLURAL:$4|'na seòrsa faidhle|'nan seòrsaichean faidhle}} ceadaichte. Is $2 {{PLURAL:$3|an seòrsa faidhle|na seòrsaichean faidhle}} ceadaichte.",
+       "api-error-filetype-missing": "Tha leudachan a dhìth air an fhaidhle.",
+       "api-error-hookaborted": "Chaidh sgur dhen atharrachadh a dh'fheuch thu ri dèanamh le leudachan.",
+       "api-error-http": "Mearachd taobh a-staigh: Cha b' urrainn dhuinn ceangal ris an fhrithealaiche.",
+       "api-error-illegal-filename": "Chan eil ainm an fhaidhle ceadaichte.",
+       "api-error-internal-error": "Mearachd tabh a-staigh: chaidh rudeigin cearr rè an luchdaidh suas agad dhan uicidh.",
+       "api-error-invalid-file-key": "Mearachd taobh a-staigh: Cha deach am faidhle a lorg san stòras shealach.",
+       "api-error-missingparam": "Mearachd taobh a-staigh: Tha paramadair a dhìth air an iarrtas.",
+       "api-error-missingresult": "Mearachd taobh a-staigh: Cha d' fhuair sinn a-mach co-dhiù an do shoirbhich leis an lethbhreac gus nach do shoirbhich.",
+       "api-error-mustbeloggedin": "Feumaidh tu logadh a-steach mus luchdaich thu suas faidhle.",
+       "api-error-mustbeposted": "Mearachd taobh a-staigh: Tha an t-iarrtas ag iarraidh HTTP POST.",
+       "api-error-noimageinfo": "Shoirbhich leis an luchdadh suas, ach cha dug am frithealaiche fiosrachadh sam bith dhuinn mun fhaidhle.",
+       "api-error-nomodule": "Mearachd taobh a-staigh: cha deach mòideal luchdaidh suas a shuidheachadh.",
+       "api-error-ok-but-empty": "Mearachd taobh a-staigh: Cha d' fhuair sinn freagairt on fhrithealaiche.",
+       "api-error-overwrite": "Chan fhaodar sgrìobhadh thairis air faidhle a tha ann mar-thà.",
+       "api-error-stashfailed": "Mearachd taobh a-staigh: Cha deach leis an fhrithealaiche faidhle sealach a stòradh.",
+       "api-error-publishfailed": "Mearachd taobh a-staigh: Cha deach leis an fhrithealaiche faidhle sealach fhoillseachadh.",
        "api-error-stasherror": "Thachair mearachd le luchdadh suas an fhaidhle dhan tasgadan.",
-       "expand_templates_remove_nowiki": "Mùch tagaichean <nowiki> san toradh"
+       "api-error-timeout": "Cha d' fhuair sinn freagairt on fhrithealaiche ri àm.",
+       "api-error-unclassified": "Thachair mearachd neo-aithnichte.",
+       "api-error-unknown-code": "Mearachd neo-aithnichte: \"$1\".",
+       "api-error-unknown-error": "Mearachd tabh a-staigh: Chaidh rudeigin cearr rè luchdadh suas an fhaidhle agad.",
+       "api-error-unknown-warning": "Rabhadh neo-aithnichte: \"$1\".",
+       "api-error-unknownerror": "Mearachd neo-aithnichte: \"$1\".",
+       "api-error-uploaddisabled": "Tha luchdadh suas à comas air an uicidh seo.",
+       "api-error-verification-error": "Dh'fhaoidte gu bheil am faidhle seo coirbte no gu bheil an leudachan cearr air.",
+       "duration-seconds": "$1 {{PLURAL:$1|diog|dhiog|diogan|diog}}",
+       "duration-minutes": "$1 {{PLURAL:$1|mhionaid|mhionaid|mionaidean|mionaid}}",
+       "duration-hours": "$1 {{PLURAL:$1|uair|uair|uairean|uair}}",
+       "duration-days": "$1 {{PLURAL:$1|latha|latha|làithean|latha}}",
+       "duration-weeks": "$1 {{PLURAL:$1|seachdain|sheachdain|seachdainean|seachdain}}",
+       "duration-years": "$1 {{PLURAL:$1|bhliadhna|bhliadhna|bliadhnaichean|bliadhna}}",
+       "duration-decades": "$1 {{PLURAL:$1|deichead|dheichead|deicheadan|deichead}}",
+       "duration-centuries": "$1 {{PLURAL:$1|linn|linn|linntean|linn}}",
+       "duration-millennia": "$1 {{PLURAL:$1|mhìle bliadhna|mhìle bliadhna|mìle bliadhna|mìle bliadhna}}",
+       "rotate-comment": "Chaidh an dealbh a chuairteachadh le $1 {{PLURAL:$1|cheum|cheum|ceuman|ceum}} gu tuathal",
+       "limitreport-cputime-value": "$1 {{PLURAL:$1|diog|dhiog|diogan|diog}}",
+       "limitreport-walltime-value": "$1 {{PLURAL:$1|diog|dhiog|diogan|diog}}",
+       "limitreport-ppvisitednodes-value": "$1/$2",
+       "limitreport-ppgeneratednodes-value": "$1/$2",
+       "limitreport-postexpandincludesize-value": "$1/$2 {{PLURAL:$2|bhaidht|bhaidht|baidhtichean|baidht}}",
+       "limitreport-templateargumentsize-value": "$1/$2 {{PLURAL:$2|bhaidht|bhaidht|baidhtichean|baidht}}",
+       "limitreport-expansiondepth-value": "$1/$2",
+       "limitreport-expensivefunctioncount-value": "$1/$2",
+       "expandtemplates": "Leudaich na templaidean",
+       "expand_templates_intro": "Gabhaidh an duilleag shònraichte seo ri teacsa agus leudaichidh i a h-uile teamplaid na broinn gu ath-chùrsach.\nLeudaichidh i cuideachd foincseanan parsair ris a chuirear taic, can\n<code><nowiki>{{</nowiki>#language:…}}</code> agus caochladairean mar\n<code><nowiki>{{</nowiki>CURRENTDAY}}</code>.\nAir deireadh na sgeòil, leudaichidh i cha mhòr gach rud eadar camagan dualach dùbailte.",
+       "expand_templates_title": "Tiotal a' cho-theacsa airson {{FULLPAGENAME}} is msaa.:",
+       "expand_templates_input": "Teacsa ion-chuir:",
+       "expand_templates_output": "Toradh",
+       "expand_templates_xml_output": "Às-chur XML",
+       "expand_templates_html_output": "Bun-tùs a' chòd HTML",
+       "expand_templates_ok": "Ceart ma-thà",
+       "expand_templates_remove_comments": "Thoir na beachdan air falbh",
+       "expand_templates_remove_nowiki": "Mùch tagaichean <nowiki> san toradh",
+       "expand_templates_generate_xml": "Seall craobh parsaidh an XML",
+       "expand_templates_generate_rawhtml": "Seall bun-tùs an HTML",
+       "expand_templates_preview": "Ro-sheall",
+       "pagelanguage": "Roghnaichear cànan nan duilleag",
+       "pagelang-name": "Duilleag",
+       "pagelang-language": "Cànan",
+       "pagelang-use-default": "Cleachd an cànan tùsail",
+       "pagelang-select-lang": "Tagh cànan",
+       "right-pagelang": "Atharraich cànan nan duilleagan",
+       "action-pagelang": "atharraich cànan nan duilleagan",
+       "log-name-pagelang": "Loga air atharrachadh nan cànan",
+       "log-description-pagelang": "Seo loga dhe na h-atharraichean air cànanan nan duilleagan.",
+       "logentry-pagelang-pagelang": "Dh'atharraich $1 cànan nan duilleagan airson $3 o $4 gu $5."
 }
index a9a4933..6116884 100644 (file)
        "license-nopreview": "(תצוגה מקדימה לא זמינה)",
        "upload_source_url": "(כתובת URL תקפה ונגישה)",
        "upload_source_file": "(קובץ במחשב שלך)",
+       "listfiles-delete": "מחיקה",
        "listfiles-summary": "דף מיוחד זה מציג את כל הקבצים שהועלו.",
        "listfiles_search_for": "חיפוש קובץ מדיה בשם:",
        "imgfile": "קובץ",
        "expand_templates_remove_nowiki": "הסרת תגי <nowiki> בתוצאה",
        "expand_templates_generate_xml": "הצגת עץ הפענוח של XML",
        "expand_templates_generate_rawhtml": "הצגת HTML גולמי",
-       "expand_templates_preview": "תצוגה מקדימה"
+       "expand_templates_preview": "תצוגה מקדימה",
+       "pagelanguage": "בורר שפת הדף",
+       "pagelang-name": "דף",
+       "pagelang-language": "שפה",
+       "pagelang-use-default": "להשתמש בשפה הרגילה",
+       "pagelang-select-lang": "בחירת שפה",
+       "right-pagelang": "שינוי שפת הדף",
+       "action-pagelang": "לשנות את שפת הדף",
+       "log-name-pagelang": "יומן שינוי שפה",
+       "log-description-pagelang": "זהו יומן של שינויים בשפות של הדפים.",
+       "logentry-pagelang-pagelang": "$1 {{GENDER:$2|שינה|שינתה}} את שפת הדף $3 מ$4 ל$5."
 }
index 53180a8..f2cf581 100644 (file)
        "powersearch-togglelabel": "Uključi:",
        "powersearch-toggleall": "Sve",
        "powersearch-togglenone": "Ništa",
+       "powersearch-remember": "Zapamti izbor za buduća pretraživanja",
        "search-external": "Vanjski pretraživač",
        "searchdisabled": "<p>Oprostite! Pretraga po cjelokupnoj bazi je zbog bržeg rada projekta {{SITENAME}} trenutačno onemogućena. Možete se poslužiti tražilicom Google.</p>",
        "preferences": "Postavke",
index bebd2e6..6f410c1 100644 (file)
@@ -34,7 +34,8 @@
                        "Tgr",
                        "Xbspiro",
                        "아라",
-                       "Csega"
+                       "Csega",
+                       "ViDam"
                ]
        },
        "tog-underline": "Hivatkozások aláhúzása:",
@@ -53,7 +54,7 @@
        "tog-watchdeletion": "Az általam törölt lapok és fájlok felvétele a figyelőlistámra",
        "tog-minordefault": "Alapértelmezetten minden szerkesztésemet jelölje aprónak",
        "tog-previewontop": "Előnézet megjelenítése a szerkesztőablak előtt",
-       "tog-previewonfirst": "Előnézet első szerkesztésnél",
+       "tog-previewonfirst": "Előnézet mutatása az első szerkesztésnél",
        "tog-enotifwatchlistpages": "Kapjak értesítést e-mailben, ha egy általam figyelt lap vagy fájl megváltozik",
        "tog-enotifusertalkpages": "Kapjak értesítést e-mailben, ha megváltozik a vitalapom",
        "tog-enotifminoredits": "Kapjak értesítést e-mailben a lapok és fájlok apró változtatásairól",
        "currentrev": "Aktuális változat",
        "currentrev-asof": "A lap jelenlegi, $1-kori változata",
        "revisionasof": "A lap $1-kori változata",
-       "revision-info": "A lap korábbi változatát látod, amilyen {{GENDER:$6|$2}} $1-kor történt szerkesztése$7 után volt.",
+       "revision-info": "A lap korábbi változatát látod, amilyen {{GENDER:$6|$2}} $1-kor történt szerkesztése után volt.$7",
        "previousrevision": "←Régebbi változat",
        "nextrevision": "Újabb változat→",
        "currentrevisionlink": "Aktuális változat",
        "duplicate-defaultsort": "Figyelem: a(z) „$2” rendezőkulcs felülírja a korábbit („$1”).",
        "version": "Névjegy",
        "version-extensions": "Telepített kiterjesztések",
-       "version-skins": "Felületek",
+       "version-skins": "Telepített felületek",
        "version-specialpages": "Speciális lapok",
        "version-parserhooks": "Értelmező hookok",
        "version-variables": "Változók",
        "version-license": "MediaWiki licenc",
        "version-ext-license": "Licenc",
        "version-ext-colheader-name": "Kiterjesztés",
+       "version-skin-colheader-name": "Felület",
        "version-ext-colheader-version": "Verzió",
        "version-ext-colheader-license": "Licenc",
        "version-ext-colheader-description": "Leírás",
        "expand_templates_remove_nowiki": "<nowiki> tagek mellőzése az eredményben",
        "expand_templates_generate_xml": "XML elemzési fa mutatása",
        "expand_templates_generate_rawhtml": "Nyers HTML megjelenítése",
-       "expand_templates_preview": "Előnézet"
+       "expand_templates_preview": "Előnézet",
+       "pagelanguage": "Oldalnyelv-választó",
+       "pagelang-name": "Oldal",
+       "pagelang-language": "Nyelv",
+       "pagelang-use-default": "Alapértelmezett nyelv használata",
+       "pagelang-select-lang": "Nyelv kiválasztása",
+       "right-pagelang": "Oldal nyelvének megváltoztatása",
+       "action-pagelang": "oldal nyelvének módosítása",
+       "log-name-pagelang": "Nyelvváltoztatások naplója",
+       "log-description-pagelang": "Ebben a naplóban a lap nyelvének változásait követheted nyomon."
 }
index 52baff6..ca955f2 100644 (file)
@@ -11,7 +11,8 @@
                        "Shirayuki",
                        "Yfdyh000",
                        "לערי ריינהארט",
-                       "아라"
+                       "아라",
+                       "Carlosedepaula"
                ]
        },
        "tog-underline": "Sublinear ligamines:",
        "duplicate-defaultsort": "Attention: Le clave de ordination predefinite \"$2\" supplanta le anterior clave de ordination predefinite \"$1\".",
        "version": "Version",
        "version-extensions": "Extensiones installate",
-       "version-skins": "Apparentias",
+       "version-skins": "Apparentias installate",
        "version-specialpages": "Paginas special",
        "version-parserhooks": "Uncinos del analysator syntactic",
        "version-variables": "Variabiles",
        "version-license": "Licentia pro MediaWiki",
        "version-ext-license": "Licentia",
        "version-ext-colheader-name": "Extension",
+       "version-skin-colheader-name": "Apparentia",
        "version-ext-colheader-version": "Version",
        "version-ext-colheader-license": "Licentia",
        "version-ext-colheader-description": "Description",
        "expand_templates_remove_nowiki": "Supprimer le etiquettas <nowiki> in le resultato",
        "expand_templates_generate_xml": "Monstrar arbore syntactic XML",
        "expand_templates_generate_rawhtml": "Monstrar HTML brute",
-       "expand_templates_preview": "Previsualisation"
+       "expand_templates_preview": "Previsualisation",
+       "pagelanguage": "Selector de lingua de pagina",
+       "pagelang-name": "Pagina",
+       "pagelang-language": "Lingua",
+       "pagelang-use-default": "Usar lingua predefinite",
+       "pagelang-select-lang": "Selige lingua",
+       "right-pagelang": "Cambiar lingua del pagina",
+       "action-pagelang": "Cambiar lingua del pagina",
+       "log-name-pagelang": "Registro de cambios de lingua",
+       "log-description-pagelang": "Isto es un registro de cambios de lingua in paginas.",
+       "logentry-pagelang-pagelang": "$1 {{GENDER:$2|cambiava}} le lingua del pagina $3 de $4 a $5."
 }
index 6f2334c..2837738 100644 (file)
        "content-failed-to-parse": "Gat ekki þáttað $2 efni samkvæmt $1 líkani: $3",
        "invalid-content-data": "Ógild efnisgögn.",
        "content-not-allowed-here": "„$1“ efni er ekki leyfilegt á síðunni [[$2]]",
-       "editwarning-warning": "Ef farið er frá þessari síðu gætu þær breytingar sem þú hefur gert tapast.\nEf þú ert skráður inn, þá getur þú óvirkjað þessi skilaboð í „Breytingarflipanum\" undir stillingum.",
+       "editwarning-warning": "Ef farið er frá þessari síðu gætu þær breytingar sem þú hefur gert tapast.\nEf þú ert skráður inn, þá getur þú óvirkjað þessi skilaboð í „{{int:prefs-editing}}\" undir stillingum.",
        "content-model-wikitext": "wiki-texti",
        "content-model-text": "hreinn texti",
        "content-model-javascript": "JavaScript",
        "currentrev": "Núverandi útgáfa",
        "currentrev-asof": "Núverandi breyting frá og með $1",
        "revisionasof": "Útgáfa síðunnar $1",
-       "revision-info": "Útgáfa frá $1 eftir $2",
+       "revision-info": "Útgáfa frá $1 eftir $2\nÚtgáfa frá $1 eftir {{GENDER:$6|$2}}$7",
        "previousrevision": "←Fyrri útgáfa",
        "nextrevision": "Næsta útgáfa→",
        "currentrevisionlink": "Núverandi útgáfa",
        "gender-unknown": "Ég vil heldur ekki gefa upp",
        "gender-male": "Hann breytir wikisíðum",
        "gender-female": "Hún breytir wikisíðum",
-       "prefs-help-gender": "Valfrjálst: notað til að aðgreina kynin í meldingum hugbúnaðarins. Þessar upplýsingar verða aðgengilegar öllum.",
+       "prefs-help-gender": "Þessi stilling er valfrjáls. Notað til að aðgreina kynin í meldingum hugbúnaðarins. Þessar upplýsingar verða aðgengilegar öllum.",
        "email": "Tölvupóstur",
        "prefs-help-realname": "Alvöru nafn er valfrjálst.\nEf þú kýst að gefa það upp, verður það notað til að gefa þér heiður af verkum þínum.",
        "prefs-help-email": "Tölvupóstfang er valfrjálst, en gerir þér kleift að fá nýtt lykilorð ef þú gleymir lykilorðinu þínu.",
        "right-reupload-shared": "Hunsa skrár á sameiginlegu myndasafni staðbundið",
        "right-upload_by_url": "Hlaða inn skrám frá vefslóð",
        "right-purge": "Hreinsa skyndiminni síðu án staðfestingar",
-       "right-autoconfirmed": "Breyta hálfvernduðum síðum",
+       "right-autoconfirmed": "Sneiða hjá takmörkunum vistfanga",
        "right-bot": "Eru meðhöndlaðir eins og sjálfvirk aðgerð",
        "right-nominornewtalk": "Ekki láta minniháttar breytingar á spjallsíðum kveða upp áminningu um ný skilaboð",
        "right-apihighlimits": "Setja hærri mörk á fjölda API fyrirspurna",
        "windows-nonascii-filename": "Þessi wiki styður ekki skráarnöfn með sérstökum stöfum",
        "fileexists": "Skrá með þessu nafni er þegar til, skoðaðu <strong>[[:$1]]</strong> ef þú ert óviss um hvort þú viljir breyta henni, ekki verður skrifað yfir gömlu skránna hlaðiru inn nýrri með sama nafni heldur verður núverandi útgáfa geymd í útgáfusögu.\n[[$1|thumb]]",
        "filepageexists": "Myndasíðan fyrir þessa síðu hefur þegar verið búin til <strong>[[:$1]]</strong>, en engin skrá er til með þessu nafni.\nLýsingin sem þú skrifaðir verður ekki birt á myndasíðunni.\nTil þess að lýsingin geti birst á síðunni, þá þarft þú að breyta síðunni sérstaklega.\n[[$1|thumb]]",
-       "fileexists-extension": "Skrá með svipuðu nafni er til: [[$2|thumb]]\n*Nafn skráarinnar sem hlaða á inn: <strong>[[:$1]]</strong>\n*Nafn skráarinnar sem er þegar til: <strong>[[:$2]]</strong>\nVinsamlegast veldu annað skráarnafn.",
+       "fileexists-extension": "Skrá með svipuðu nafni er til: [[$2|thumb]]\n*Nafn skráarinnar sem hlaða á inn: <strong>[[:$1]]</strong>\n*Nafn skráarinnar sem er þegar til: <strong>[[:$2]]</strong>\nVilt þú kanski nota annað nafn sem er meira lýsandi fyrir skránna ?",
        "fileexists-thumbnail-yes": "Skráin virðist vera smámynd [[$1|thumb]]\nVinsamlegast athugaðu skránna <strong>[[:$1]]</strong>.\nEf skráin er sama myndin í upprunalegri stærð er ekki þörf á annari smámynd.",
        "file-thumbnail-no": "Skráin er líklega smámynd, því skráarnafnið byrjar á <strong>$1</strong>.\nEf skráin er í fullri upplausn haltu þá áfram að hlaða henni inn, en ef ekki breyttu þá skráarnafninu.",
        "fileexists-forbidden": "Skrá með þessu nafni er þegar til og ekki er hægt að skrifa yfir skránna.\nEf þú villt hlaða inn skránni þinni engu að síður, farðu þá til baka og veldu annað skráarnafn.\n[[File:$1|thumb|center|$1]]",
        "pageswithprop-submit": "Áfram",
        "doubleredirects": "Tvöfaldar tilvísanir",
        "doubleredirectstext": "Þessi síða er listi yfir skrár sem eru tilvísanir á aðrar tilvísanir.\nHver lína inniheldur tengla á fyrstu og aðra tilvísun auk þeirrar síðu sem seinni tilvísunin beinist að, sem er oftast sú síða sem allar tilvísanirnar eiga að benda á.\n<del>Yfirstrikaðar</del> færslur hafa verið leiðréttar.",
-       "double-redirect-fixed-move": "[[$1]] hefur verið færð.\nHún er tilvísun á [[$2]].",
-       "double-redirect-fixed-maintenance": "Laga tvöfalda tilvísun frá [[$1]] til [[$2]].",
+       "double-redirect-fixed-move": "[[$1]] hefur verið færð.\nHún var uppfærð sjálfkrafa og tilvísar núna á [[$2]].",
+       "double-redirect-fixed-maintenance": "Laga sjálfvirkt tvöfalda tilvísun frá [[$1]] til [[$2]] í viðhalds aðgerð.",
        "double-redirect-fixer": "Laga tilvísun",
        "brokenredirects": "Brotnar tilvísanir",
        "brokenredirectstext": "Eftirfarandi tilvísanir vísa á síður sem ekki eru til:",
        "wantedtemplates": "Eftirsótt snið",
        "mostlinked": "Mest ítengdu síður",
        "mostlinkedcategories": "Mest ítengdu flokkar",
-       "mostlinkedtemplates": "Mest ítengdu snið",
+       "mostlinkedtemplates": "Mest ítengdu síður",
        "mostcategories": "Mest flokkaðar greinar",
        "mostimages": "Mest ítengdu skrárnar",
        "mostinterwikis": "Síður með flestm tungumálatenglum",
        "pageinfo-length": "Lengd síðunnar (í bætum)",
        "pageinfo-article-id": "Einkennisnúmer síðunnar",
        "pageinfo-language": "Tungumál síðunnar",
-       "pageinfo-robot-policy": "Leitarvélastaða",
+       "pageinfo-robot-policy": "Attriðaskráning af vélmennum",
        "pageinfo-robot-index": "Heimilað",
        "pageinfo-robot-noindex": "Ekki heimilað",
        "pageinfo-views": "Fjöldi innlita",
        "duplicate-defaultsort": "'''Viðvörun:''' Sjálfgildur flýtihnappur \"$2\" tekur yfir fyrri flýtihnapp \"$1\".",
        "version": "Útgáfa",
        "version-extensions": "Uppsettar viðbætur",
+       "version-skins": "Uppsett þemu",
        "version-specialpages": "Kerfissíður",
        "version-variables": "Breytur",
        "version-antispam": "Amapósts sía",
-       "version-skins": "Þemu",
        "version-other": "Aðrar",
        "version-mediahandlers": "Rekill margmiðlunarskráa",
        "version-parser-extensiontags": "Þáttuð smáforrita tög",
index 6e0c06f..7172181 100644 (file)
        "license-nopreview": "(Anteprima non disponibile)",
        "upload_source_url": " (una URL corretta e accessibile)",
        "upload_source_file": " (un file sul proprio computer)",
+       "listfiles-delete": "cancella",
        "listfiles-summary": "Questa pagina speciale mostra tutti i file caricati.",
        "listfiles_search_for": "Ricerca immagini per nome:",
        "imgfile": "file",
        "expand_templates_remove_nowiki": "Elimina il tag <nowiki> nel risultato",
        "expand_templates_generate_xml": "Mostra albero sintattico XML",
        "expand_templates_generate_rawhtml": "Mostra HTML",
-       "expand_templates_preview": "Anteprima"
+       "expand_templates_preview": "Anteprima",
+       "pagelanguage": "Seleziona lingua della pagina",
+       "pagelang-name": "Pagina",
+       "pagelang-language": "Lingua",
+       "pagelang-use-default": "Utilizza la lingua predefinita",
+       "pagelang-select-lang": "Seleziona lingua",
+       "right-pagelang": "Modifica la lingua della pagina",
+       "action-pagelang": "modificare la lingua della pagina",
+       "log-name-pagelang": "Modifiche lingua",
+       "log-description-pagelang": "Questo è un registro delle modifiche alla lingua delle pagine.",
+       "logentry-pagelang-pagelang": "$1 {{GENDER:$2|ha modificato}} la lingua della pagina $3 da $4 a $5."
 }
index f9d5778..4457755 100644 (file)
@@ -59,7 +59,8 @@
                        "青子守歌",
                        "아라",
                        "Rxy",
-                       "Mfuji"
+                       "Mfuji",
+                       "Takot"
                ]
        },
        "tog-underline": "リンクの下線:",
        "resetpass-abort-generic": "拡張機能により、パスワードの変更は取り消されました。",
        "resetpass-expired": "パスワードの有効期限が切れました。ログインするには新しいパスワードを設定してください。",
        "resetpass-expired-soft": "パスワードの有効期限が切れたため、再設定する必要があります。新しいパスワードを今すぐ設定するか、または「{{int:resetpass-submit-cancel}}」をクリックしてあとで再設定してください。",
+       "resetpass-validity-soft": "あなたのパスワードは無効です: $1\n\n今すぐ新しいパスワードに変更するか、「{{int:resetpass-submit-cancel}}」をクリックして後で再設定してください。",
        "passwordreset": "パスワードの再設定",
        "passwordreset-text-one": "仮パスワードをメールで受け取るにはこのフォームに記入してください。",
        "passwordreset-text-many": "{{PLURAL:$1|仮パスワードをメールで受け取るにはいずれかの欄に記入してください。}}",
        "revdelete-show-file-confirm": "ファイル「<nowiki>$1</nowiki>」の削除された$2$3の版を本当に閲覧しますか?",
        "revdelete-show-file-submit": "はい",
        "revdelete-selected-text": "[[:$2]] の{{PLURAL:$1|選択された版}}:",
+       "revdelete-selected-file": "[[:$2]] の{{PLURAL:$1|選択された版}}:",
        "logdelete-selected": "{{PLURAL:$1|選択された記録項目}}:",
        "revdelete-text-text": "削除された版は履歴に表示され続けますが、一般の利用者が内容を閲覧できなくなります。",
        "revdelete-text-file": "削除されたファイルの版はファイルの履歴に表示されつづけますが、一般の利用者はその内容の一部を閲覧できなくなります。",
        "powersearch-togglelabel": "チェックを入れる:",
        "powersearch-toggleall": "すべて",
        "powersearch-togglenone": "すべて外す",
+       "powersearch-remember": "この選択を今後の検索のために記憶させる",
        "search-external": "外部検索",
        "searchdisabled": "{{SITENAME}}の検索機能は無効化されています。\nさしあたってはGoogleなどで検索できます。\nただし外部の検索エンジンの索引にある{{SITENAME}}のコンテンツは古い場合があります。",
        "search-error": "検索する際にエラーが発生しました: $1",
        "windows-nonascii-filename": "このウィキではファイル名に特殊文字を使用できません。",
        "fileexists": "この名前のファイルは既に存在します。{{GENDER:|}}置き換えていいかどうか確信が持てない場合は、<strong>[[:$1]]</strong>を確認してください。\n[[$1|thumb]]",
        "filepageexists": "このファイルのための説明ページは既に<strong>[[:$1]]</strong>に作成されていますが、現在、ファイルが存在しません。\n入力した概要は説明ページに反映されません。\n新しい概要を表示させるには、説明ページを手動で編集する必要があります。\n[[$1|thumb]]",
-       "fileexists-extension": "類似した名前のファイルが既に存在します: [[$2|thumb]]\n* アップロード中のファイルの名前: <strong>[[:$1]]</strong>\n* 既存ファイルの名前: <strong>[[:$2]]</strong>\n違う名前を選択してください。",
+       "fileexists-extension": "類似した名前のファイルが既に存在します: [[$2|thumb]]\n* アップロード中のファイルの名前: <strong>[[:$1]]</strong>\n* 既存ファイルの名前: <strong>[[:$2]]</strong>\nもう少し分かりやすい名前を付けますか?",
        "fileexists-thumbnail-yes": "このファイルは元の画像から縮小されたもの <em>(サムネイル)</em> のようです。\n[[$1|thumb]]\nファイル <strong>[[:$1]]</strong> を確認してください。\n確認したファイルが同じ画像の元のサイズの版の場合は、サムネイルを別途アップロードする必要はありません。",
        "file-thumbnail-no": "ファイル名が <strong>$1</strong> で始まっています。\n他の画像から縮小されたもの <em>(サムネイル)</em> のようです。\nより高精細な画像をお持ちの場合はそれをアップロードしてください。お持ちではない場合はファイル名を変更してください。",
        "fileexists-forbidden": "この名前のファイルは既に存在しており、上書きできません。\nアップロードを継続したい場合は、前のページに戻り、別のファイル名を使用してください。\n[[File:$1|thumb|center|$1]]",
        "pageswithprop-prophidden-binary": "プロパティ値のバイナリが長いため非表示 ($1)",
        "doubleredirects": "二重転送",
        "doubleredirectstext": "このページでは、転送ページへの転送ページを列挙します。\n最初の転送ページ、その転送先にある転送ページ、さらにその転送先にあるページ、それぞれへのリンクを各行に表示しています。多くの場合は最終的な転送先が「正しい」転送先であり、最初の転送ページの転送先は最終的な転送先に直接向けるべきです。\n<del>取り消し線</del>が入った項目は解決済みです。",
-       "double-redirect-fixed-move": "[[$1]]を移動しました。\n今後は[[$2]]に転送されます。",
+       "double-redirect-fixed-move": "[[$1]]を移動しました。\n自動的に更新され、今後は[[$2]]に転送されます。",
        "double-redirect-fixed-maintenance": "メンテナンス作業の一環として[[$1]]から[[$2]]への二重転送を自動的に修正します。",
        "double-redirect-fixer": "転送修正係",
        "brokenredirects": "迷子のリダイレクト",
        "import-error-special": "ページ「$1」は、ページが許可されない特別名前空間に属しているため取り込みません。",
        "import-error-invalid": "名前が正しくないため、ページ「$1」を取り込みませんでした。",
        "import-error-unserialize": "ページ「$1」の版 $2 はシリアライズ解除できませんでした。この版は $4 としてシリアライズされたコンテンツモデル $3 を使用していると報告されています。",
+       "import-error-bad-location": "コンテンツモデル $3 はこのページではサポート外のため、モデル $3 を使用している版 $2 はこのウィキ上の「$1」に保存できません。",
        "import-options-wrong": "間違った{{PLURAL:$2|オプション}}です: <nowiki>$1</nowiki>",
        "import-rootpage-invalid": "入力したルートページの名前は無効です。",
        "import-rootpage-nosubpage": "ルートページの名前空間「$1」では、下位ページが許可されていません。",
        "htmlform-no": "いいえ",
        "htmlform-yes": "はい",
        "htmlform-chosen-placeholder": "選択してください",
+       "htmlform-cloner-create": "さらに追加",
        "htmlform-cloner-delete": "除去",
+       "htmlform-cloner-required": "少なくとも 1 つの値が必要です。",
        "sqlite-has-fts": "$1 (全文検索あり)",
        "sqlite-no-fts": "$1 (全文検索なし)",
        "logentry-delete-delete": "$1 がページ「$3」を{{GENDER:$2|削除しました}}",
        "expand_templates_remove_nowiki": "結果に含まれる <nowiki> タグを表示しない",
        "expand_templates_generate_xml": "XML 構文解析ツリーを表示",
        "expand_templates_generate_rawhtml": "HTML ソースを表示",
-       "expand_templates_preview": "プレビュー"
+       "expand_templates_preview": "プレビュー",
+       "pagelanguage": "ページ言語選択",
+       "pagelang-name": "ページ",
+       "pagelang-language": "言語",
+       "pagelang-use-default": "既定の言語を使用",
+       "pagelang-select-lang": "言語を選択",
+       "right-pagelang": "ページの言語を変更",
+       "action-pagelang": "ページの言語の変更",
+       "log-name-pagelang": "言語変更記録",
+       "log-description-pagelang": "これはページ言語の変更の記録です。",
+       "logentry-pagelang-pagelang": "$1 がページ $3 の言語を $4 から $5 に{{GENDER:$2|変更しました}}"
 }
index 498437f..f962fa6 100644 (file)
        "watchthis": "Бұл бетті бақылау",
        "savearticle": "Бетті сақтау",
        "preview": "Қарап шығу",
-       "showpreview": "Алдын ала қарау",
+       "showpreview": "Алдын-ала қарау",
        "showdiff": "Өзгерістерді көрсет",
        "anoneditwarning": "<strong> Ескерту:</strong>  Сіз жүйеге кірмегенсіз.\nIP мекенжайыңыз бұл беттің өңделу тарихында жазылып алынады.",
        "anonpreviewwarning": "<em>Сіз жүйеге кірмегенсіз. IP мекенжайыңыз бұл беттің өңделу тарихында жазылып алынады.</em>",
        "rev-suppressed-unhide-diff": "Бір түзетуі (нұсқасы) <strong>жасырылған</strong>.\nЕгжей-тегжейін [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} жою журналынан] таба аласыз.\nЕгер жалғастырсаңыз [$1 бұл айырмашылықты] көре аласыз.",
        "rev-deleted-diff-view": "Бұл нұсқалар айырмасының бір нұсқасы <strong>жойылған</strong>.\n[{{fullurl:{{#special:Log}}/delete|page={{FULLPAGENAMEE}}}} Жою журналынан] егжей-тегжейін таба аласыз.",
        "rev-suppressed-diff-view": "Бұл нұсқалар айырмасының бір нұсқасы <strong>жасырылған</strong>.\n[{{fullurl:{{#special:Log}}/delete|page={{FULLPAGENAMEE}}}} Жасыру журналынан] егжей-тегжейін таба аласыз.",
-       "rev-delundel": "көÑ\80Ñ\96нÑ\96Ñ\81Ñ\96н Ó©Ð·Ð³ÐµÑ\80Ñ\82Ñ\83",
+       "rev-delundel": "көÑ\80Ñ\81еÑ\82/жаÑ\81Ñ\8bÑ\80",
        "rev-showdeleted": "көрсету",
        "revisiondelete": "Нұсқаларды жою/жоюды болдырмау",
        "revdelete-nooldid-title": "Нысана түзету жарамсыз",
        "revdelete-success": "'''Түзету көрінісі сәтті жаңартылды.'''",
        "revdelete-failure": "'''Түзету көрінісі жаңартылмады:'''\n$1",
        "logdelete-success": "'''Журнал көрінісі сәтті қойылды.'''",
-       "revdel-restore": "Ð\9aөрінісін өзгерту",
+       "revdel-restore": "көрінісін өзгерту",
        "pagehist": "Бет тарихы",
        "deletedhist": "Жойылған тарихы",
        "revdelete-otherreason": "Басқа/қосымша себеп:",
        "search-section": "(бөлім $1)",
        "search-suggest": "Мүмкін осы болар: $1",
        "search-interwiki-caption": "Бауырлас жобалар",
-       "search-interwiki-default": "$1 нәтиже:",
+       "search-interwiki-default": "$1 Ð´ÐµÐ³ÐµÐ½Ð½ÐµÐ½ Ð½Ó\99Ñ\82иже:",
        "search-interwiki-more": "(көбірек)",
        "search-relatedarticle": "Қатысты",
        "searchrelated": "қатысты",
        "powersearch-togglelabel": "Белгілеу:",
        "powersearch-toggleall": "Барлығы",
        "powersearch-togglenone": "Ешқандай",
+       "powersearch-remember": "Келесі іздеулер үшін таңдалғанды есте сақтау",
        "search-external": "Сыртқы іздеу",
        "searchdisabled": "{{SITENAME}} іздеу қызметі өшірілген.\nӘзірше Google арқылы іздеуге болады.\nАңғартпа: {{SITENAME}} торабының мағлұмат тізбелері ескірген болуы мүмкін.",
        "search-error": "Іздеген кезде қате кездесті: $1",
        "right-move": "Беттерді жылжыту",
        "right-move-subpages": "Беттерді олардың бағынышты беттерін қоса жылжыту",
        "right-move-rootuserpages": "Қатысушы беттерін түбірімен жылжыту",
+       "right-move-categorypages": "Санат беттерінің атауын өзгерту",
        "right-movefile": "Файлдарды жылжыту",
        "right-suppressredirect": "Тиісті атауға бетті жылжытқанда айдағышты жасамау",
        "right-upload": "Файлдарды жүктеу",
        "action-createpage": "беттерді бастау",
        "action-createtalk": "талқылау беттерін бастау",
        "action-createaccount": "Бұл қатысушы тіркелгісін жасау",
+       "action-history": "бұл беттің өңделу тарихын қарау",
        "action-minoredit": "бұл өңдемені шағын деп белгілеу",
        "action-move": "бұл бетті жылжыту",
        "action-move-subpages": "бұл бетті және оның төменгі беттерін жылжыту",
        "action-move-rootuserpages": "қатысушы беттерін түбірімен жылжыту",
+       "action-move-categorypages": "санат беттерінің атауын өзгерту",
        "action-movefile": "Бұл файлды жылжыту",
        "action-upload": "бұл файлды жүктеу",
        "action-reupload": "бұл бар файлдың үстіне жазу",
        "backend-fail-read": "«$1» файлы оқылмайды.",
        "backend-fail-create": "«$1» файлы жазылмайды.",
        "backend-fail-maxsize": "\"$1\" файлы жазылмайды, себебі {{PLURAL:$2|1 байттан|$2 байттан}} үлкенірек.",
+       "img-auth-accessdenied": "Қатынау шектелген",
        "http-invalid-url": "Жарамсыз URL: $1",
        "http-read-error": "HTTP оқудағы қате.",
        "upload-curl-error6": "URL жетілмеді",
        "pageswithprop-submit": "Өту",
        "doubleredirects": "Екі мәрте айдағыштар",
        "doubleredirectstext": "Бұл бетте басқа айдату беттерге сілтейтін беттер тізімделінеді. Әрбір жолақта бірінші және екінші айдағышқа сілтемелер бар, сонымен бірге екінші айдағыш нысанасы бар, әдетте бұл бірінші айдағыш бағыттайтын «нақты» нысана бет атауы болуы керек.",
-       "double-redirect-fixed-move": "[[$1]] Ð¶Ñ\8bлжÑ\8bÑ\82Ñ\8bлдÑ\8b.\nоÒ\93ан Ò\9bазÑ\96Ñ\80 [[$2]] Ð´ÐµÐ³ÐµÐ½Ð³Ðµ Ð°Ð¹Ð´Ð°Ñ\82Ñ\8bлды.",
+       "double-redirect-fixed-move": "[[$1]] Ð¶Ñ\8bлжÑ\8bÑ\82Ñ\8bлдÑ\8b.\nÐ\9eл Ó©Ð·Ð´Ñ\96кÑ\82Ñ\96 Ñ\82Ò¯Ñ\80де Ð¶Ð°Ò£Ð°Ñ\80Ñ\82Ñ\8bладÑ\8b Ð¶Ó\99не Ð¾Ò\93ан Ò\9bазÑ\96Ñ\80 [[$2]] Ð´ÐµÐ³ÐµÐ½Ð³Ðµ Ð±Ð°Ò\93Ñ\8bÑ\82Ñ\82алады.",
        "brokenredirects": "Сынық айдағыштар",
        "brokenredirectstext": "Келесі айдағыштар жоқ беттерге сілтейді:",
        "brokenredirects-edit": "өңдеу",
        "wantedtemplates": "Басталмаған үлгілер",
        "mostlinked": "Ең көп сілтенген беттер",
        "mostlinkedcategories": "Ең көп сілтенген санаттар",
-       "mostlinkedtemplates": "Ең көп сілтенген үлгілер",
+       "mostlinkedtemplates": "Ең көп кірістірілген (қолданылған) үлгілер",
        "mostcategories": "Ең көп санаты бар беттер",
        "mostimages": "Ең көп сілтенген файлдар",
        "mostinterwikis": "Ең көп интеруикилері бар беттер",
        "listgrouprights-removegroup-self": "Өз тіркелгіңізді {{PLURAL:$2|топтан|топтардан}} алып тастау: $1",
        "listgrouprights-addgroup-self-all": "Өз тіркелгіңізге барлық топтарды қосу",
        "listgrouprights-removegroup-self-all": "Өз тіркелгіңізден барлық топтарды алып тастау",
+       "listgrouprights-namespaceprotection-namespace": "Атау кеңістігі",
+       "trackingcategories-name": "Хабарлама атауы",
+       "trackingcategories-nodesc": "Сипаттамасы қолжетімді емес.",
+       "trackingcategories-disabled": "Санат өшірілген",
        "mailnologin": "Еш мекенжай жөнелтілген жоқ",
        "mailnologintext": "Басқа қатысушыға хат жөнелту үшін [[Special:UserLogin|кіруіңіз]] жөн, және [[Special:Preferences|бапталымдарыңызда]] жарамды е-пошта мекенжайы болуы жөн.",
        "emailuser": "Қатысушыға хат жазу",
        "usermaildisabledtext": "Бұл уикиде басқа қатысушыларға хат жібере алмайсыз",
        "noemailtitle": "Еш е-пошта мекенжайы жоқ",
        "noemailtext": "Бұл қатысушы жарамды е-пошта мекенжайын келтірмеген.",
+       "nowikiemailtext": "Бұл қатысушы басқа қатысушылардан хат хабылдамауды таңдаған.",
        "emailusername": "Қатысушы аты:",
        "emailusernamesubmit": "Жіберу",
        "email-legend": "Басқа {{SITENAME}} қатысушысына хат жіберу",
        "watchnologin": "Кірмегенсіз",
        "addwatch": "Бақылау тізіміңізге қосу",
        "addedwatchtext": "«[[:$1]]» беті [[Special:Watchlist|бақылау тізіміңізге]] қосылды.\nБұл беттің және байланысты талқылау бетінің келешектегі өзгерістері сонда тізімделеді.",
+       "addedwatchtext-short": "«$1» беті бақылау тізіміңізге қосылды.",
        "removewatch": "Бақылау тізіміңізден аластату",
        "removedwatchtext": "«[[:$1]]» беті [[Special:Watchlist|бақылау тізіміңізден]] аласталды.",
+       "removedwatchtext-short": "«$1» беті бақылау тізіміңізден аласталды",
        "watch": "Бақылау",
        "watchthispage": "Бұл бетті бақылау",
        "unwatch": "Бақыламау",
        "contributions-title": "$1 есімді қатысушының үлесі",
        "mycontris": "Үлесім",
        "contribsub2": "{{GENDER:$3|$1}} ($2) үлесі",
+       "contributions-userdoesnotexist": "«$1» қатысушы акаунты тіркелмеді.",
        "nocontribs": "Осы іздеу шартына сәйкес өзгерістер табылған жоқ.",
        "uctop": "(соңғы)",
        "month": "Мына айдан (және ертеректен):",
        "nolinkshere": "'''[[:$1]]''' дегенге еш бет сілтемейді.",
        "nolinkshere-ns": "Таңдалған есім кеңістігінде '''[[:$1]]''' дегенге ешқандай бет сілтемейді.",
        "isredirect": "бағыттау беті",
-       "istemplate": "кірікбет",
+       "istemplate": "кіріcтірілген",
        "isimage": "файл сілтемесі",
        "whatlinkshere-prev": "{{PLURAL:$1|алдыңғы|алдыңғы $1}}",
        "whatlinkshere-next": "{{PLURAL:$1|келесі|келесі $1}}",
        "whatlinkshere-links": "← сілтемелер",
-       "whatlinkshere-hideredirs": "Ð\91аÒ\93Ñ\8bÑ\82Ñ\82аÑ\83Ñ\88Ñ\8bлаÑ\80дÑ\8b $1",
+       "whatlinkshere-hideredirs": "баÒ\93Ñ\8bÑ\82Ñ\82аÑ\83 Ð±ÐµÑ\82Ñ\82еÑ\80Ñ\96н $1",
        "whatlinkshere-hidetrans": "кіріcтірілген беттерді $1",
        "whatlinkshere-hidelinks": "сілтемелерді $1",
        "whatlinkshere-hideimages": "файл сілтемелерін $1",
        "ipblocklist-empty": "Бұғаттау тізімі бос.",
        "ipblocklist-no-results": "Сұратылған IP мекенжай немесе қатысушы аты бұғатталмаған.",
        "blocklink": "бұғаттау",
-       "unblocklink": "бұÒ\93аÑ\82Ñ\82амау",
+       "unblocklink": "бұÒ\93аÑ\82Ñ\8bнан Ñ\88Ñ\8bÒ\93аÑ\80у",
        "change-blocklink": "бұғаттауын өзгерту",
        "contribslink": "үлесі",
        "emaillink": "хат жіберу",
        "movepagetalktext": "Келесі жағдай орын алса, қатысты талқылау беті '''жылжытылмайды''':\n*жаңа атаумен аталатын беттің талқылау беті әлдеқашан бар болған кезде (бұл жағдайда талқылауын қолмен көшіруге болады, бірақ түйіндемесіне қай беттен көшірілгендігін міндетті түрде жазыңыз)\n*төмендегі қорапшадан құсбелгі алынып тасталғанда.\n\nАл мақаланың атауын өзгертем деп мағлұматын қолмен көшіруге болмайды, себебі беттің түзету тарихын өшіреді.",
        "movearticle": "Бетті жылжыту:",
        "moveuserpage-warning": "<strong>Ескерту:</strong> Сіз қатысушы бетін жылжытпақшысыз. Назар аударыңыз, қатысушы беті ғана жылжытылуы мүмкін және қатысушы аты <em>өзгертілмейді</em>.",
+       "movecategorypage-warning": "<strong>Ескерту:</strong> Сіз санат бетінің атауын өзгерткелі жатырсыз. Бұл әрекетіңізде санат атауы ғана өзгерте аласыз сондықтан санаттың бұрыңғы атауындағы қандай да бір бет санаттың жаңа атауына өздігінен <em>санатталмайтыны</em> есіңізде болсын. Санаттың бұрыңғы атауындағы беттері мен санатшаларын жаңа атауына қайта санаттап шығуға тура келеді.",
        "movenologintext": "Бетті жылжыту үшін тіркелген қатысуышы болуыңыз және [[Special:UserLogin|кіруіңіз]] керек.",
        "movenotallowed": "{{SITENAME}} жобасында беттерді жылжытуға рұқсатыңыз жоқ.",
        "movenotallowedfile": "Файлдарды жылжытуға рұқсатыңыз жоқ.",
        "cant-move-user-page": "Қатысушы беттерін жылжытуға рұқсатыңыз жоқ (төменгі беттерінен басқа).",
        "cant-move-to-user-page": "Бетті қатысушы бетіне жылжытуға рұқсатыңыз жоқ (төменгі беттерін қоспағанда).",
+       "cant-move-category-page": "Сізде санат беттерінің атауын өзгертуге рұқсатыңыз жоқ.",
+       "cant-move-to-category-page": "Сізде бетті санат бетіне жылжытуға рұқсатыңыз жоқ.",
        "newtitle": "Жаңа бет атауы:",
        "move-watch": "Бұл бетті бақылау",
        "movepagebtn": "Бетті жылжыту",
        "watchlistedit-raw-done": "Бақылау тізіміңіз жаңартылды.",
        "watchlistedit-raw-added": "$1 тақырып аты үстелді:",
        "watchlistedit-raw-removed": "$1 тақырып аты аласталды:",
+       "watchlistedit-clear-title": "Бақылау тізіміңіз тазартылды",
+       "watchlistedit-clear-legend": "Бақылау тізімін тазарту",
+       "watchlistedit-clear-explain": "Барлық атаулар бақылау тізіміңізден аласталды",
+       "watchlistedit-clear-titles": "Тақырып аттары:",
+       "watchlistedit-clear-submit": "Бақылау тізімді тазарту (Бұл қайтадан өзгермейді!)",
+       "watchlistedit-clear-done": "Бақылау тізіміңіз тазартылды.",
+       "watchlistedit-clear-removed": "{{PLURAL:$1|1 бет атауы|$1 бет атауы}} аласталды:",
+       "watchlistedit-too-many": "Мұнда өте көп беттер көрсетілген.",
+       "watchlisttools-clear": "Бақылау тізімін тазарту",
        "watchlisttools-view": "Қатысты өзгерістерді қарау",
        "watchlisttools-edit": "Бақылау тізімді қарау және өңдеу",
        "watchlisttools-raw": "Бақылау тізімін өңдеу",
        "unknown_extension_tag": "Белгісіз кеңейтпе белгісі \"$1\"",
        "version": "Нұсқа",
        "version-extensions": "Орнатылған кеңейтімдер",
-       "version-skins": "Ð\9cәнерлер",
+       "version-skins": "Ð\9eÑ\80наÑ\82Ñ\8bлÒ\93ан Ð¼әнерлер",
        "version-specialpages": "Арнайы беттер",
        "version-parserhooks": "Құрылымдық талдатқыштың тұзақтары",
        "version-variables": "Айнымалылар",
        "version-hook-name": "Тұзақ атауы",
        "version-hook-subscribedby": "Тұзақ тартқыштары",
        "version-version": "(Нұсқасы: $1)",
+       "version-no-ext-name": "[аты жоқ]",
        "version-license": "MediaWiki Лицензиясы",
        "version-ext-license": "Лицензия",
        "version-ext-colheader-name": "Кеңейтілім",
+       "version-skin-colheader-name": "Мәнер",
        "version-ext-colheader-version": "Нұсқасы",
        "version-ext-colheader-license": "Лицензиясы",
        "version-ext-colheader-description": "Сипаттамасы",
        "htmlform-selectorother-other": "Басқа",
        "htmlform-no": "Жоқ",
        "htmlform-yes": "Иә",
+       "htmlform-cloner-create": "Тағы қосу",
+       "htmlform-cloner-delete": "Аластау",
        "logentry-delete-delete": "$1 $3 деген бетті {{GENDER:$2|жойды}}",
        "logentry-delete-restore": "$1 $3 деген бетті {{GENDER:$2|қалпына келтірді}}",
        "logentry-delete-event": "$1 $3 бетіндегі {{PLURAL:$5|журнал оқиғасы|$5 журнал оқиғасы}} көрінісін {{GENDER:$2|өзгертті}}: $4",
index aba2a76..583b573 100644 (file)
        "pagecategories": "{{PLURAL:$1|Saachjrupp|Saachjruppe}}",
        "category_header": "Atikkele en dä Saachjrupp „$1“",
        "subcategories": "Ungerjruppe",
-       "category-media-header": "Dateie en de Saachjrupp \"$1\"",
+       "category-media-header": "Dateije en dä Saachjropp „$1“",
        "category-empty": "''En dä Saachjrupp heh sin kein Sigge un kein Dateie.''",
        "hidden-categories": "Verstoche Saachjrupp{{PLURAL:$1||e|e}}",
        "hidden-category-category": "Verstoche Saachjruppe",
        "duplicate-defaultsort": "'''Opjepaß:'''\nDä Shtanndat-Zoot-Schlößel „$1“ övverschriif dä älldere Zoot-Schlößel „$2“.",
        "version": "Väsjohn vun de Wiki Soffwär zeije",
        "version-extensions": "Installeete Erjänzunge un Zohsätz",
+       "version-skins": "Ovverflääsche",
        "version-specialpages": "{{int:nstab-special}}e",
        "version-parserhooks": "De Parser-Hooke",
        "version-variables": "Variable",
        "version-antispam": "SPAM verhendere",
-       "version-skins": "Ovverflääsche",
        "version-api": "<i lang=\"en\">API</i>",
        "version-other": "Söns",
        "version-mediahandlers": "Medije-Handler",
index 5b1754c..f261368 100644 (file)
        "license-nopreview": "(Kucken ouni ofzespäichere geet net)",
        "upload_source_url": " (gëlteg, ëffentlech zougänglech URL)",
        "upload_source_file": " (e Fichier op Ärem Computer)",
+       "listfiles-delete": "läschen",
        "listfiles-summary": "Op dëser Spezialsäit stinn all déi eropgeluede Fichieren.",
        "listfiles_search_for": "Sicht nom Fichier:",
        "imgfile": "Fichier",
        "duplicate-defaultsort": "'''Opgepasst:''' Den Zortéierschlëssel \"$2\" iwwerschreift de virege Standard-Zortéierschlëssel \"$1\".",
        "version": "Versioun",
        "version-extensions": "Installéiert Erweiderungen",
-       "version-skins": "Skins/Layout",
+       "version-skins": "Installéiert Skins/Layout",
        "version-specialpages": "Spezialsäiten",
        "version-parserhooks": "Parser-Erweiderungen",
        "version-variables": "Variabelen",
        "version-license": "MediaWiki-Lizenz",
        "version-ext-license": "Lizenz",
        "version-ext-colheader-name": "Erweiderung",
+       "version-skin-colheader-name": "Ausgesinn",
        "version-ext-colheader-version": "Versioun",
        "version-ext-colheader-license": "Lizenz",
        "version-ext-colheader-description": "Beschreiwung",
        "expand_templates_remove_nowiki": "<nowiki>-Taggen am Resultat suppriméieren",
        "expand_templates_generate_xml": "Weis d'Struktur vum XML",
        "expand_templates_generate_rawhtml": "HTML-Format weisen",
-       "expand_templates_preview": "Kucken ouni ofzespäicheren"
+       "expand_templates_preview": "Kucken ouni ofzespäicheren",
+       "pagelanguage": "Eraussiche vun der Sprooch vun der Säit",
+       "pagelang-name": "Säit",
+       "pagelang-language": "Sprooch",
+       "pagelang-use-default": "Standard-Sprooch benotzen",
+       "pagelang-select-lang": "Sprooch eraussichen",
+       "right-pagelang": "Sprooch vun der Säit änneren",
+       "action-pagelang": "d'Sprooch vun der Säit änneren",
+       "log-description-pagelang": "Dëst ass a Log mat den Ännerunge vun de Sprooche vun de Säiten."
 }
index 7f12e61..70c362e 100644 (file)
        "toc": "Satura rādītājs",
        "showtoc": "parādīt",
        "hidetoc": "paslēpt",
-       "collapsible-collapse": "Sakļaut",
-       "collapsible-expand": "Izplest",
+       "collapsible-collapse": "paslēpt",
+       "collapsible-expand": "rādīt",
        "thisisdeleted": "Apskatīt vai atjaunot $1?",
        "viewdeleted": "Skatīt $1?",
        "restorelink": "$1 {{PLURAL:$1|dzēsto versiju|dzēstās versijas}}",
        "duplicate-defaultsort": "'''Brīdinājums:''' Noklusējuma kārtošanas atslēga \"$2\" ignorē kārtošanas atslēga \"$1\".",
        "version": "Versija",
        "version-extensions": "Ieinstalētie paplašinājumi",
+       "version-skins": "Apdares",
        "version-specialpages": "Īpašās lapas",
        "version-variables": "Mainīgie",
        "version-antispam": "Spama aizsardzība",
-       "version-skins": "Apdares",
        "version-other": "Cita",
        "version-hooks": "Aizķeres",
        "version-hook-name": "Aizķeres nosaukums",
index 82af772..684b2a0 100644 (file)
        "emptyfile": "Податотеката што ја подигнавте е празна.\nОва може да се должи на грешка во нејзиното име.\nПроверете дали навистина сакате да ја подигнете ваквата податотека.",
        "windows-nonascii-filename": "Опслужувачот не поддржува податотечни имиња со специјални знаци.",
        "fileexists": "Податотека со ова име веќе постои. Проверете <strong>[[:$1]]</strong> ако не {{GENDER:|сте}} сигурни дали сакате да ја промените.\n[[$1|thumb]]",
-       "filepageexists": "СÑ\82Ñ\80аниÑ\86аÑ\82а Ð·Ð° Ð¾Ð¿Ð¸Ñ\81 Ð½Ð° Ð¾Ð²Ð°Ð° Ð¿Ð¾Ð´Ð°Ñ\82оÑ\82ека Ðµ Ð²ÐµÑ\9cе Ñ\81оздадена Ð½Ð° <strong>[[:$1]]</strong>, Ð½Ð¾ Ð½Ðµ Ð¿Ð¾Ñ\81Ñ\82ои Ð¿Ð¾Ð´Ð°Ñ\82оÑ\82ека Ñ\81о Ñ\82оа Ð¸Ð¼Ðµ.\nÐ\9eпиÑ\81оÑ\82 ÐºÐ¾Ñ\98 Ð³Ð¾ Ð²Ð½ÐµÑ\81овÑ\82е Ð½ÐµÐ¼Ð° Ð´Ð° Ñ\81Ñ\82ои Ð½Ð° Ñ\81Ñ\82Ñ\80аниÑ\86аÑ\82а Ð·Ð° Ð¾Ð¿Ð¸Ñ\81.\nДоколку сакате описот да стои тука, ќе морате да го уредите рачно.\n[[$1|thumb]]",
+       "filepageexists": "Ð\9eпиÑ\81наÑ\82а Ñ\81Ñ\82Ñ\80аниÑ\86а Ð½Ð° Ð¾Ð²Ð°Ð° Ð¿Ð¾Ð´Ð°Ñ\82оÑ\82ека Ðµ Ð²ÐµÑ\9cе Ñ\81оздадена Ð½Ð° <strong>[[:$1]]</strong>, Ð½Ð¾ Ð½Ðµ Ð¿Ð¾Ñ\81Ñ\82ои Ð¿Ð¾Ð´Ð°Ñ\82оÑ\82ека Ñ\81о Ñ\82оа Ð¸Ð¼Ðµ.\nÐ\9eпиÑ\81оÑ\82 ÐºÐ¾Ñ\98 Ð³Ð¾ Ð²Ð½ÐµÑ\81овÑ\82е Ð½ÐµÐ¼Ð° Ð´Ð° Ñ\81Ñ\82ои Ð½Ð° Ð¾Ð¿Ð¸Ñ\81наÑ\82а Ñ\81Ñ\82Ñ\80аниÑ\86а.\nДоколку сакате описот да стои тука, ќе морате да го уредите рачно.\n[[$1|thumb]]",
        "fileexists-extension": "Податотека со слично име веќе постои: [[$2|thumb]]\n* Име на податотека која се подигнува: <strong>[[:$1]]</strong>\n* Име на постоечката податотека: <strong>[[:$2]]</strong>\nДали можеби би сакале да користите покарактеристично име.",
        "fileexists-thumbnail-yes": "Се чини дека податотеката е слика со намалена големина ''(минијатура)''. [[$1|thumb]]\nПроверете ја податотеката <strong>[[:$1]]</strong>.\nАко податотеката која ја проверувате е истата слика во својата изворна големина тогаш не мора да ја подигате дополнително.",
        "file-thumbnail-no": "Името на податотеката почнува со <strong>$1</strong>.\nИзгледа дека е слика со намалена големина ''(мини, thumbnail)''.\nАко ја имате оваа слика во изворна големина, подигнете ја неја. Во спротивно сменете го името на податотеката.",
        "license-nopreview": "(Прегледот не е достапен)",
        "upload_source_url": " (важечка, јавно достапна URL-адреса)",
        "upload_source_file": "(податотека на вашиот компјутер)",
+       "listfiles-delete": "избриши",
        "listfiles-summary": "Оваа специјална страница ги прикажува сите подигнати податотеки.",
        "listfiles_search_for": "Побарај име на податотека:",
        "imgfile": "податотека",
        "linkstoimage-redirect": "$1 (пренасочување) $2",
        "duplicatesoffile": "{{PLURAL:$1|Следната податотека е дупликат|$1 Следните податотеки се дупликати}} на оваа податотека ([[Special:FileDuplicateSearch/$2|повеќе информации]]):",
        "sharedupload": "Оваа податотека е од $1 и може да се користи во други проекти.",
-       "sharedupload-desc-there": "Оваа податотека е од $1 и може да се користи во други проекти.\nПогледнете ја [$2 страницата за опис на податотеката] за повеќе информации.",
-       "sharedupload-desc-here": "Оваа податотека е од $1 и може да се користи во други проекти.\nОписот од нејзината [$2 страница за опис] е прикажан подолу.",
+       "sharedupload-desc-there": "Оваа податотека е од $1 и може да се користи во други проекти.\nПогледнете ја [$2 описната страница  на податотеката] за повеќе информации.",
+       "sharedupload-desc-here": "Оваа податотека е од $1 и може да се користи во други проекти.\nОписот од нејзината [$2 описна страница] е прикажан подолу.",
        "sharedupload-desc-edit": "Оваа податотека е од $1 и може да се користи во други проекти.\nНејзиниот опис можете да го уредите на [$2 соодветната страница].",
        "sharedupload-desc-create": "Оваа податотека е од $1 и може да се користи во други проекти.\nНејзиниот опис можете да го уредите на [$2 соодветната страница].",
        "filepage-nofile": "Не постои податотека со ова име.",
        "shared-repo-from": "од $1",
        "shared-repo": "заедничко складиште",
        "shared-repo-name-wikimediacommons": "Ризницата",
-       "filepage.css": "/* Тука поставените каскадни стилски страници (CSS) се вклучени во страницата за опис на податотеката, како и на клиентските викија */",
+       "filepage.css": "/* Тука поставените каскадни стилски страници (CSS) се вклучени во описната страница на податотеката, како и на клиентските викија */",
        "upload-disallowed-here": "Нажалост, не можете да презапишете врз сликава.",
        "filerevert": "Врати $1",
        "filerevert-legend": "Врати податотека",
        "mostinterwikis": "Страници со најмногу меѓувики",
        "mostrevisions": "Статии со најмногу верзии",
        "prefixindex": "Сите страници (со претставка)",
-       "prefixindex-namespace": "СиÑ\82е Ñ\81Ñ\82Ñ\80аниÑ\86и Ñ\81о Ð¿Ñ\80еÑ\84икÑ\81 (именски простор $1)",
+       "prefixindex-namespace": "СиÑ\82е Ñ\81Ñ\82Ñ\80аниÑ\86и Ñ\81о Ð¿Ñ\80еÑ\82Ñ\81Ñ\82авка (именски простор $1)",
        "prefixindex-strip": "Отстрани ја претставката во списокот",
        "shortpages": "Кратки страници",
        "longpages": "Долги страници",
        "allmessages-filter-unmodified": "Неизменети",
        "allmessages-filter-all": "Сите",
        "allmessages-filter-modified": "Изменети",
-       "allmessages-prefix": "ФилÑ\82Ñ\80иÑ\80аÑ\98 Ð¿Ð¾ Ð¿Ñ\80еÑ\84икÑ\81:",
+       "allmessages-prefix": "ФилÑ\82Ñ\80иÑ\80аÑ\98 Ð¿Ð¾ Ð¿Ñ\80еÑ\82Ñ\81Ñ\82авка:",
        "allmessages-language": "Јазик:",
        "allmessages-filter-submit": "Оди",
        "allmessages-filter-translate": "Преведување",
        "expand_templates_remove_nowiki": "Притаи <nowiki> ознаки во резултатот",
        "expand_templates_generate_xml": "Прикажи XML-дрво на расчленувањето",
        "expand_templates_generate_rawhtml": "Прикажувај сиров HTML",
-       "expand_templates_preview": "Преглед"
+       "expand_templates_preview": "Преглед",
+       "pagelanguage": "Изборник за јазик на страницата",
+       "pagelang-name": "Страница",
+       "pagelang-language": "Јазик",
+       "pagelang-use-default": "Користи стандарден јазик",
+       "pagelang-select-lang": "Одберете јазик",
+       "right-pagelang": "Менување јазик на страница",
+       "action-pagelang": "менување јазик на страница",
+       "log-name-pagelang": "Дневник на менување на јазикот",
+       "log-description-pagelang": "Ова е дневник на менувања на јазикот на страницата.",
+       "logentry-pagelang-pagelang": "$1 {{GENDER:$2|го смени}} јазикот на страницата $3 од $4 на $5."
 }
index 2244079..56c62e6 100644 (file)
        "duplicate-defaultsort": "'''മുന്നറിയിപ്പ്:''' ക്രമപ്പെടുത്താനുള്ള ചാവിയായ \"$2\" മുമ്പ് ക്രമപ്പെടുത്താനുള്ള ചാവിയായിരുന്ന \"$1\" എന്നതിനെ അതിലംഘിക്കുന്നു.",
        "version": "പതിപ്പ്",
        "version-extensions": "ഇൻസ്റ്റോൾ ചെയ്തിട്ടുള്ള അനുബന്ധങ്ങൾ",
-       "version-skins": "ദൃശ്യരൂപങ്ങൾ",
+       "version-skins": "à´\87ൻസàµ\8dà´±àµ\8dà´±àµ\8bൾ à´\9aàµ\86à´¯àµ\8dതിà´\9fàµ\8dà´\9fàµ\81à´³àµ\8dà´³ à´¦àµ\83à´¶àµ\8dയരàµ\82à´ªà´\99àµ\8dà´\99ൾ",
        "version-specialpages": "പ്രത്യേക താളുകൾ",
        "version-parserhooks": "പാഴ്‌സർ കൊളുത്തുകൾ",
        "version-variables": "ചരങ്ങൾ",
        "version-license": "മീഡിയവിക്കി ഉപയോഗാനുമതി",
        "version-ext-license": "അനുമതി",
        "version-ext-colheader-name": "അനുബന്ധം",
+       "version-skin-colheader-name": "ദൃശ്യരൂപം",
        "version-ext-colheader-version": "പതിപ്പ്",
        "version-ext-colheader-license": "ഉപയോഗാനുമതി",
        "version-ext-colheader-description": "വിവരണം",
        "expand_templates_remove_nowiki": "ഫലങ്ങളിലെ <nowiki> റ്റാഗുകൾ ഒതുക്കുക",
        "expand_templates_generate_xml": "എക്സ്.എം.എൽ. പാഴ്‌സർ ട്രീ പ്രദർശിപ്പിക്കുക",
        "expand_templates_generate_rawhtml": "അസംസ്കൃത എച്ച്.റ്റി.എം.എൽ. പ്രദർശിപ്പിക്കുക",
-       "expand_templates_preview": "എങ്ങനെയുണ്ടെന്നു കാണുക"
+       "expand_templates_preview": "എങ്ങനെയുണ്ടെന്നു കാണുക",
+       "pagelanguage": "താളിന്റെ ഭാഷാ തിരഞ്ഞെടുപ്പ് സൗകര്യം",
+       "pagelang-name": "താൾ",
+       "pagelang-language": "ഭാഷ",
+       "pagelang-use-default": "സ്വതേയുള്ള ഭാഷ ഉപയോഗിക്കുക",
+       "pagelang-select-lang": "ഭാഷ തിരഞ്ഞെടുക്കുക",
+       "right-pagelang": "താളിന്റെ ഭാഷ മാറ്റുക",
+       "action-pagelang": "താളിന്റെ ഭാഷ മാറ്റുക",
+       "log-name-pagelang": "ഭാഷ മാറ്റലിന്റെ രേഖ",
+       "log-description-pagelang": "താളുകളുടെ ഭാഷകൾ മാറ്റിയതിന്റെ രേഖകൾ ഇവിടെക്കാണാം.",
+       "logentry-pagelang-pagelang": "$3 എന്ന താളിന്റെ ഭാഷയായിരുന്ന $4, $1 $5 ആയി {{GENDER:$2|മാറ്റി}}."
 }
index c578188..d707821 100644 (file)
        "powersearch-togglelabel": "Agħżel:",
        "powersearch-toggleall": "Kollha",
        "powersearch-togglenone": "Ebda",
+       "powersearch-remember": "Ftakar l-għażla għal tfittxijiet oħra",
        "search-external": "Tfittxija esterna",
        "searchdisabled": "It-Tfittxija fil-{{SITENAME}} mhux attiva.\nSadanittant, tista' tipprova tfittex bil-Google.\nInnota però li l-werreja tal-kontenut ta' {{SITENAME}} f'dawn is-siti, jistgħu ma jkunux aġġornati.",
        "preferences": "Preferenzi",
        "duplicate-defaultsort": "'''Twissija:''' iċ-ċavetta tal-issortjar oriġinali \"$2\" tissostitwixxi dik preċedenti \"$1\".",
        "version": "Verżjoni",
        "version-extensions": "Estensjonijiet installati",
+       "version-skins": "Aspetti",
        "version-specialpages": "Paġni speċjali",
        "version-parserhooks": "Hook tal-parser",
        "version-variables": "Varjabili",
        "version-antispam": "Prevenzjoni tal-ispam",
-       "version-skins": "Aspetti",
        "version-other": "Oħrajn",
        "version-mediahandlers": "Imradd tal-medja",
        "version-hooks": "Hook",
index 0a2d3ab..f29574c 100644 (file)
        "editinginterface": "'''Sè-jī:''' Lí tng teh siu-kái 1 bīn thê-kiong nńg-thé kài-bīn bûn-jī ê ia̍h. Jīn-hô kái-piàn to ē éng-hióng tio̍h kî-thaⁿ iōng-chiá ê sú-iōng kài-bīn. Nā beh kái hoan-e̍k, chhiaⁿ khì Ûi-ki Mûi-thé chāi-tē-hoà sū-kang [//translatewiki.net/ translatewiki.net] hiâ.",
        "cascadeprotected": "Chit-ê ia̍h í-keng hông pó-hō͘ bē kái tit. In-ūi i tī ē-bīn {{PLURAL:$1|ê|ê}} liân-só pó-hō͘ lāi-té:\n$2",
        "namespaceprotected": "Lí bô khoân-lī kái '''$1'''  miâ-khong-kan ê ia̍h",
+       "exception-nologin": "Bô teng-ji̍p",
+       "exception-nologin-text": "請先[[Special:Userlogin|登入]]了才有法度看這頁抑對這頁做動作。",
+       "exception-nologin-text-manual": "請先$1,才有法度看這頁抑對這頁做動作。",
+       "virus-badscanner": "設定毋著:你的病毒掃描程式阮毋知:<em>$1</em>",
+       "virus-scanfailed": "掃病毒無成功(代碼$1)",
        "virus-unknownscanner": "M̄-chai siáⁿ pēⁿ-to̍k:",
        "logouttext": "'''Lí í-keng teng-chhut.'''\nChhiaⁿ chù-ì: ū-kóa ia̍h ū khó-lêng khoàⁿ-tio̍h bē-su lí iáu teng-ji̍p tī leh; che chi-iàu piàⁿ tiāu liû-lám-khì ê khoài-chhú-khu, tiō ē chèng-siông.",
        "welcomeuser": "Hoan-gêng, $1!",
+       "welcomecreation-msg": "你的口座以經開好矣,\n你若有需要,會使去改你佇{{SITENAME}}的設定。",
        "yourname": "Lí ê iōng-chiá miâ-chheng:",
        "userlogin-yourname": "Iōng-chiá miâ-chheng",
+       "userlogin-yourname-ph": "拍你的用者名稱",
+       "createacct-another-username-ph": "拍你的用者名稱",
        "yourpassword": "Lí ê bi̍t-bé:",
        "userlogin-yourpassword": "Bi̍t-bé",
+       "userlogin-yourpassword-ph": "拍密碼",
        "createacct-yourpassword-ph": "拍密碼",
        "yourpasswordagain": "Têng phah bi̍t-bé:",
        "createacct-yourpasswordagain": "確認密碼",
        "userlogin-loggedin": "你已經用{{GENDER:$1|$1}}登入,用下跤的表,登入別个名。",
        "userlogin-createanother": "開另外一个口座",
        "createacct-emailrequired": "電子批地址",
+       "createacct-emailoptional": "電子批地址(無一定愛寫)",
        "createacct-email-ph": "拍你的電子批地址",
        "createacct-another-email-ph": "拍你的電子批地址",
        "createaccountmail": "Iōng chi̍t-ê lîm-sî loān-sò͘ sán-seng ê bi̍t-bé , kià khì goá chí-tēng ê tiān-chú-phoe tē-chí.",
        "loginerror": "Teng-ji̍p chhò-gō·",
        "createacct-error": "開口座無成功",
        "createaccounterror": "Bô hoat-tō͘ khui kháu-chō: $1",
+       "nocookiesnew": "你的用者口座已經開好矣,毋過你猶未登入,{{SITENAME}}有用Cookies做記錄登入的用者,你無允准用Cookies,請先共阻擋提掉,才閣用你的用者名稱佮密碼登入。",
+       "nocookieslogin": "{{SITENAME}}有用cookies做記錄用者,毋過你無允準用cookies,等你改做會當了後,才閣試。",
        "loginsuccesstitle": "Teng-ji̍p sêng-kong",
        "loginsuccess": "Lí hiān-chhú-sî í-keng teng-ji̍p {{SITENAME}} chò \"$1\".",
        "nosuchuser": "Chia bô iōng-chiá hō-chò \"$1\".\nIiōng-chiá hō-chò ū hun toā-jī sè-jī.\nChhiáⁿ kiám-cha lí ê phèng-im, a̍h-sī  [[Special:UserLogin/signup|khui sin iōng-chiá ê kháu-chō.]]",
index 2aea667..51f192a 100644 (file)
        "mergehistory-empty": "Ingen revisjoner kan flettes.",
        "mergehistory-success": "{{PLURAL:$3|Én revisjon|$3 revisjoner}} av [[:$1]] ble flettet til [[:$2]].",
        "mergehistory-fail": "Klarte ikke å utføre historikkfletting; sjekk siden og tidsparameterne igjen.",
+       "mergehistory-fail-toobig": "Det er ikke mulig å utføre historikk-fletting fordi flere enn tillatte $1 {{PLURAL:$1|revisjon|revisjoner}} ville blitt flyttet.",
        "mergehistory-no-source": "Kildesiden $1 finnes ikke.",
        "mergehistory-no-destination": "Målsiden $1 finnes ikke.",
        "mergehistory-invalid-source": "Kildesiden må ha en gyldig tittel.",
        "license-nopreview": "(Forhåndsvisning ikke tilgjengelig)",
        "upload_source_url": " (en gyldig, offentlig tilgjengelig adresse)",
        "upload_source_file": " (en fil på din datamaskin)",
+       "listfiles-delete": "slett",
        "listfiles-summary": "Denne spesialsiden viser alle opplastede filer.",
        "listfiles_search_for": "Søk etter filnavn:",
        "imgfile": "fil",
        "duplicate-defaultsort": "Advarsel: Standardsorteringen «$2» tar over for den tidligere sorteringen «$1».",
        "version": "Versjon",
        "version-extensions": "Installerte utvidelser",
-       "version-skins": "Drakter",
+       "version-skins": "Installerte drakter",
        "version-specialpages": "Spesialsider",
        "version-parserhooks": "Parsertillegg",
        "version-variables": "Variabler",
        "version-hook-name": "Navn",
        "version-hook-subscribedby": "Brukes av",
        "version-version": "(versjon $1)",
+       "version-no-ext-name": "[uten navn]",
        "version-license": "Lisens",
        "version-ext-license": "Lisens",
        "version-ext-colheader-name": "Utvidelse",
+       "version-skin-colheader-name": "Drakt",
        "version-ext-colheader-version": "Versjon",
        "version-ext-colheader-license": "Lisens",
        "version-ext-colheader-description": "Beskrivelse",
        "expand_templates_remove_nowiki": "Ikke vis <nowiki>-merkelapper i resultatet",
        "expand_templates_generate_xml": "Vis parsetre som XML",
        "expand_templates_generate_rawhtml": "Vis ubehandlet HTML",
-       "expand_templates_preview": "Forhåndsvisning"
+       "expand_templates_preview": "Forhåndsvisning",
+       "pagelanguage": "Valg av sidespråk",
+       "pagelang-name": "Side",
+       "pagelang-language": "Språk",
+       "pagelang-use-default": "Bruk standardspråk",
+       "pagelang-select-lang": "Velg språk",
+       "right-pagelang": "Endre sidespråk",
+       "action-pagelang": "endre sidespråket",
+       "log-name-pagelang": "Endre språklogg",
+       "log-description-pagelang": "Dette er en logg som viser endringer i sidespråk",
+       "logentry-pagelang-pagelang": "$1 {{GENDER:$2|endret}} sidespråk for $3 fra $4 til $5."
 }
index b5d554d..d3c08bb 100644 (file)
        "rcnotefrom": "Dit bin de wiezigingen sinds <strong>$2</strong> (maximum van <strong>$1</strong> wiezigingen).",
        "rclistfrom": "Bekiek wiezigingen vanaof $3 $2",
        "rcshowhideminor": "$1 kleine wiezigingen",
-       "rcshowhideminor-show": "Bekieken",
-       "rcshowhideminor-hide": "Verbargen",
+       "rcshowhideminor-show": "Bekiek",
+       "rcshowhideminor-hide": "Verbarg",
        "rcshowhidebots": "$1 botgebrukers",
-       "rcshowhidebots-show": "Bekieken",
-       "rcshowhidebots-hide": "Verbargen",
+       "rcshowhidebots-show": "Bekiek",
+       "rcshowhidebots-hide": "Verbarg",
        "rcshowhideliu": "$1 eregistreerden gebrukers",
-       "rcshowhideliu-show": "Bekieken",
-       "rcshowhideliu-hide": "Verbargen",
+       "rcshowhideliu-show": "Bekiek",
+       "rcshowhideliu-hide": "Verbarg",
        "rcshowhideanons": "$1 anonieme gebrukers",
-       "rcshowhideanons-show": "Bekieken",
-       "rcshowhideanons-hide": "Verbargen",
+       "rcshowhideanons-show": "Bekiek",
+       "rcshowhideanons-hide": "Verbarg",
        "rcshowhidepatr": "$1 nao-ekeken bewarkingen",
-       "rcshowhidepatr-show": "Bekieken",
-       "rcshowhidepatr-hide": "Verbargen",
+       "rcshowhidepatr-show": "Bekiek",
+       "rcshowhidepatr-hide": "Verbarg",
        "rcshowhidemine": "$1 mien bewarkingen",
-       "rcshowhidemine-show": "Bekieken",
-       "rcshowhidemine-hide": "Verbargen",
+       "rcshowhidemine-show": "Bekiek",
+       "rcshowhidemine-hide": "Verbarg",
        "rclinks": "Bekiek de leste $1 wiezigingen van de aofgeleupen $2 dagen<br />$3",
        "diff": "wiezig",
        "hist": "gesch",
        "download": "binnenhaolen",
        "unwatchedpages": "Ziejen die niet evolgd wörden",
        "listredirects": "Lieste van deurverwiezingen",
+       "listduplicatedfiles": "Lieste mit bestaanden mit duplikaoten",
        "unusedtemplates": "Ongebruukten mallen",
        "unusedtemplatestext": "Hieronder staon alle ziejen in de naamruumte \"{{ns:template}}\" die nargens gebruukt wörden.\nVergeet niet de verwiezingen nao te kieken veurda'j de mal vortdoon.",
        "unusedtemplateswlh": "aandere verwiezingen",
        "listgrouprights-removegroup-self": "Kan {{PLURAL:$2|groep|groepen}} vortdoon van eigen gebruker: $1",
        "listgrouprights-addgroup-self-all": "Kan alle groepen bie de eigen gebruker doon",
        "listgrouprights-removegroup-self-all": "Kan alle groepen vortdoon van eigen gebruker",
+       "trackingcategories": "Volgkategorieën",
        "mailnologin": "Niet an-emeld.",
        "mailnologintext": "Je mutten [[Special:UserLogin|an-emeld]] ween en n geldig e-mailadres in \"[[Special:Preferences|mien veurkeuren]]\" invoeren um disse funksie te kunnen gebruken.",
        "emailuser": "n Bericht sturen",
index 9631879..fc941fa 100644 (file)
@@ -57,7 +57,8 @@
                        "לערי ריינהארט",
                        "아라",
                        "Mar(c)",
-                       "Calak"
+                       "Calak",
+                       "Arg"
                ]
        },
        "tog-underline": "Koppelingen onderstrepen:",
        "license-nopreview": "(Voorvertoning niet beschikbaar)",
        "upload_source_url": " (een geldige, publiek toegankelijke URL)",
        "upload_source_file": " (een bestand op uw computer)",
+       "listfiles-delete": "verwijderen",
        "listfiles-summary": "Op deze speciale pagina zijn alle toegevoegde bestanden te bekijken.",
        "listfiles_search_for": "Zoeken naar bestand:",
        "imgfile": "bestand",
        "duplicate-defaultsort": "'''Waarschuwing:''' de standaardsortering \"$2\" krijgt voorrang voor de sortering \"$1\".",
        "version": "Versie",
        "version-extensions": "Geïnstalleerde uitbreidingen",
-       "version-skins": "Vormgevingen",
+       "version-skins": "Geïnstalleerde vormgevingen",
        "version-specialpages": "Speciale pagina's",
        "version-parserhooks": "Parserhooks",
        "version-variables": "Variabelen",
        "version-license": "Licentie voor MediaWiki",
        "version-ext-license": "Licentie",
        "version-ext-colheader-name": "Uitbreiding",
+       "version-skin-colheader-name": "Vormgeving",
        "version-ext-colheader-version": "Versie",
        "version-ext-colheader-license": "Licentie",
        "version-ext-colheader-description": "Beschrijving",
        "expand_templates_remove_nowiki": "Tags <nowiki> in resultaat onderdrukken",
        "expand_templates_generate_xml": "XML-parserboom bekijken",
        "expand_templates_generate_rawhtml": "Ruwe HTML weergeven",
-       "expand_templates_preview": "Voorvertoning"
+       "expand_templates_preview": "Voorvertoning",
+       "pagelang-name": "Pagina",
+       "pagelang-language": "Taal",
+       "pagelang-select-lang": "Taal selecteren"
 }
index 82754c4..d66eb12 100644 (file)
@@ -28,7 +28,7 @@
        "tog-hidepatrolled": "ਤਾਜ਼ਾ ਤਬਦੀਲੀਆਂ ਵਿੱਚੋਂ ਜਾਂਚੀਆਂ ਸੋਧਾਂ ਲੁਕਾਓ",
        "tog-newpageshidepatrolled": "ਨਵੀਂ ਸਫ਼ਾ ਸੂਚੀ ਵਿੱਚੋਂ ਜਾਂਚੇ ਸਫ਼ੇ ਲੁਕਾਓ",
        "tog-extendwatchlist": "ਸਿਰਫ਼ ਤਾਜ਼ਾ ਹੀ ਨਹੀਂ, ਸਗੋਂ ਸਾਰੀਆਂ ਤਬਦੀਲੀਆਂ ਨੂੰ ਵਖਾਉਣ ਲਈ ਨਿਗਰਾਨੀ-ਲਿਸਟ ਨੂੰ ਵਧਾਓ",
-       "tog-usenewrc": "ਤਾà¨\9c਼ਾ à¨¤à¨¬à¨¦à©\80ਲà©\80à¨\86à¨\82 à¨\85ਤà©\87 à¨¨à¨¿à¨\97ਰਾਨà©\80-ਲਿਸà¨\9f à¨µà¨¿à©±à¨\9a à¨¸à¨«à¨¼à©\87 à¨®à©\81ਤਾਬà¨\95 à¨¤à¨¬à¨¦à©\80ਲà©\80à¨\86à¨\82 à¨¦à©\87 à¨\97ਰà©\81ੱà¨\95 ਬਣਾਓ (ਜਾਵਾਸਕਰਿਪਟ ਲੋੜੀਂਦੀ ਹੈ)",
+       "tog-usenewrc": "ਹਾਲà©\80à¨\86 à¨¤à¨¬à¨¦à©\80ਲà©\80à¨\86à¨\82 à¨\85ਤà©\87 à¨¨à¨¿à¨\97ਰਾਨà©\80-ਲਿਸà¨\9f à¨µà¨¿à©±à¨\9a à¨¸à¨«à¨¼à©\87 à¨®à©\81ਤਾਬà¨\95 à¨¤à¨¬à¨¦à©\80ਲà©\80à¨\86à¨\82 à¨¦à©\87 à¨\97ਰà©\81ੱਪ ਬਣਾਓ (ਜਾਵਾਸਕਰਿਪਟ ਲੋੜੀਂਦੀ ਹੈ)",
        "tog-numberheadings": "ਆਟੋ-ਨੰਬਰ ਸਿਰਨਾਵੇਂ",
        "tog-showtoolbar": "ਸੋਧ ਸੰਦਬਕਸਾ ਵੇਖੋ",
        "tog-editondblclick": "ਦੋ ਵਾਰ ਕਲਿੱਕ ਕਰਨ 'ਤੇ ਸਫ਼ੇ ਸੋਧੋ",
        "mypreferencesprotected": "ਤੁਹਾਨੂੰ ਆਪਣੀਆਂ ਪਸੰਦਾਂ ਵਿੱਚ ਸੋਧ ਕਰਨ ਦੀ ਇਜਾਜ਼ਤ ਨਹੀਂ ਹੈ।",
        "ns-specialprotected": "ਖ਼ਾਸ ਸਫ਼ਿਆਂ ’ਚ ਫੇਰ-ਬਦਲ ਨਹੀਂ ਹੋ ਸਕਦੇ।",
        "titleprotected": "ਇਹ ਸਿਰਲੇਖ [[User:$1|$1]] ਵੱਲੋਂ ਸੁਰੱਖਿਅਤ ਕੀਤਾ ਗਿਆ ਹੈ ਅਤੇ ਵਰਤਿਆ ਨਹੀਂ ਜਾ ਸਕਦਾ। ਦਿੱਤਾ ਹੋਇਆ ਕਾਰਨ ਹੈ, \"''$2''\"।",
-       "filereadonlyerror": "\"$1\" à¨«à¨¼à¨¾à¨\88ਲ à¨µà¨¿à©±à¨\9a à¨¤à¨¬à¨¦à©\80ਲà©\80 à¨¨à¨¹à©\80à¨\82 à¨¹à©\8b à¨°à¨¹à©\80 à¨\95ਿà¨\89à¨\82à¨\95ਿ à¨«à¨¼à¨¾à¨\88ਲ à¨­à©°à¨¡à¨¾à¨° \"$2\" à¨¸à¨¿à¨°à¨«à¨¼ à¨ªà©\9cà©\8dਹਨਯà©\8bà¨\97 à¨°à©\82ਪ à¨µà¨¿à¨\9a à¨¹à©\88।\n\nà¨\89ਹ à¨ªà©\8dਰਸ਼ਾਸà¨\95, à¨\9cਿਹਨà©\87 à¨\87ਹ à¨°à©\8bà¨\95 à¨²à¨¾à¨\88 à¨¹à©\88, à¨¦à¨¾ à¨\95ਹਿਣਾ à¨¹à©\88:",
+       "filereadonlyerror": "\"$1\" à¨«à¨¼à¨¾à¨\88ਲ à¨µà¨¿à©±à¨\9a à¨¤à¨¬à¨¦à©\80ਲà©\80 à¨¨à¨¹à©\80à¨\82 à¨¹à©\8b à¨¸à¨\95ਦà©\80 à¨\95ਿà¨\89à¨\82à¨\95ਿ à¨«à¨¼à¨¾à¨\88ਲ à¨­à©°à¨¡à¨¾à¨° \"$2\" à¨¸à¨¿à¨°à¨«à¨¼ à¨µà©\87à¨\96ਣਯà©\8bà¨\97 à¨°à©\82ਪ à¨µà¨¿à¨\9a à¨¹à©\88।\n\nà¨\89ਹ à¨ªà©\8dਰਬੰਧà¨\95, à¨\9cਿਹਨà©\87 à¨\87ਹ à¨°à©\8bà¨\95 à¨²à¨¾à¨\88 à¨¹à©\88, à¨¦à¨¾ à¨\95ਹਿਣਾ à¨¹à©\88: ''$3''",
        "invalidtitle-knownnamespace": "ਥਾਂ-ਨਾਮ \"$2\" ਅਤੇ ਲਿਖਤ \"$3\" ਵਾਲ਼ਾ ਗ਼ਲਤ ਸਿਰਲੇਖ",
        "invalidtitle-unknownnamespace": "ਅਣਜਾਣ ਨਾਂ-ਸਥਾਨ ਗਿਣਤੀ $1 ਅਤੇ ਲਿਖਤ $2 ਵਾਲ਼ਾ ਗ਼ਲਤ ਸਿਰਲੇਖ",
        "exception-nologin": "ਲਾਗਇਨ ਨਹੀਂ ਕੀਤਾ",
        "virus-badscanner": "ਮੰਦਾ ਪ੍ਰਬੰਧ: ਅਣਜਾਣ ਵਾਇਰਸ ਸਕੈਨਰ: ''$1''",
        "virus-scanfailed": "ਸਕੈਨ ਫੇਲ੍ਹ ਹੈ (ਕੋਡ $1)",
        "virus-unknownscanner": "ਅਣਪਛਾਤਾ ਐਂਟੀਵਾਇਰਸ:",
-       "logouttext": "'''ਹੁਣ ਤੁਸੀਂ ਵਿਦਾਈ ਲੈ ਚੁੱਕੇ ਹੋ।'''\n\nਤੁਸੀਂ {{SITENAME}} ਦੀ ਵਰਤੋਂ ਗੁਮਨਾਮ ਰਹਿ ਕੇ ਕਰ ਸਕਦੇ ਹੋ ਜਾਂ ਦੁਬਾਰਾ ਇਹੋ ਜਾਂ ਵੱਖਰੇ ਵਰਤੋਂਕਾਰ ਵਜੋਂ ਦਾਖ਼ਲਾ ਲੈ ਸਕਦੇ ਹੋ।\nਧਿਆਨ ਦਿਉ ਕਿ ਜਿੰਨੀ ਦੇਰ ਤੱਕ ਤੁਸੀਂ ਆਪਣੇ ਬਰਾਊਜ਼ਰ ਦਾ ਕੈਸ਼ ਸਾਫ਼ ਨਹੀਂ ਕਰਦੇ, ਕੁਝ ਸਫ਼ੇ ਇੱਦਾਂ ਵਿਖਣਗੇ ਜਿਵੇਂ ਤੁਸੀਂ ਅਜੇ ਵੀ ਦਾਖ਼ਲ ਹੀ ਹੋ।",
+       "logouttext": "<strong>ਹੁਣ ਤੁਸੀਂ ਵਿਦਾਈ ਲੈ ਚੁੱਕੇ ਹੋ।</strong> ਧਿਆਨ ਦਿਉ ਕਿ ਜਦੋਂ ਤੱਕ ਤੁਸੀਂ ਆਪਣੇ ਬਰਾਊਜ਼ਰ ਦਾ ਕੈਸ਼ ਸਾਫ਼ ਨਹੀਂ ਕਰਦੇ, ਕੁਝ ਸਫ਼ੇ ਏਦਾਂ ਵਿਖਾਈ ਦੇ ਸਕਦੇ ਹਨ ਕਿ ਜਿਵੇਂ ਤੁਸੀਂ ਅਜੇ ਵੀ ਲਾਗਇਨ ਹੀ ਹੋ।",
        "welcomeuser": "$1 ਜੀ ਆਇਆਂ ਨੂੰ!",
        "welcomecreation-msg": "ਤੁਹਾਡਾ ਖਾਤਾ ਬਣ ਚੁੱਕਾ ਹੈ। ਆਪਣੀਆਂ [[Special:Preferences|{{SITENAME}} ਪਸੰਦ]] ਬਦਲਣੀ ਨਾ ਭੁੱਲੋ।",
        "yourname": "ਵਰਤੋਂਕਾਰ-ਨਾਂ:",
        "createacct-benefit-body3": "ਹਾਲੀਆ {{PLURAL:$1|ਯੋਗਦਾਨੀ}}",
        "badretype": "ਤੁਹਾਡੇ ਵਲੋਂ ਦਿੱਤੇ ਪਾਸਵਰਡ ਮਿਲਦੇ ਨਹੀਂ ਹਨ।",
        "userexists": "ਯੂਜ਼ਰ-ਨਾਂ ਪਹਿਲਾਂ ਹੀ ਮੌਜੂਦ ਹੈ। ਵੱਖਰਾ ਨਾਂ ਚੁਣੋ ਜੀ।",
-       "loginerror": "ਲਾਗਇਨ ਗਲਤੀ",
+       "loginerror": "ਲਾà¨\97à¨\87ਨ à¨\97਼ਲਤà©\80",
        "createacct-error": "ਖਾਤਾ ਬਣਾਉਣ ਵਿਚ ਗਲਤੀ",
        "createaccounterror": "ਖਾਤਾ ਬਣਾਇਆ ਨਹੀਂ ਜਾ ਸਕਿਆ: $1",
        "nocookiesnew": "ਯੂਜ਼ਰ ਅਕਾਊਂਟ ਬਣਾਇਆ ਗਿਆ ਹੈ, ਪਰ ਤੁਸੀਂ ਲਾਗਇਨ ਨਹੀਂ ਕੀਤਾ ਹੈ।{{SITENAME}} uses cookies to log in users. You have cookies disabled. Please enable them, then log in with your new username and password.",
        "user-mail-no-addy": "ਬਿਨਾਂ ਈ-ਮੇਲ ਪਤਾ ਦਿੱਤੇ ਈ-ਮੇਲ ਭੇਜਣ ਦੀ ਕੋਸ਼ਿਸ਼ ਕੀਤੀ।",
        "user-mail-no-body": "ਖ਼ਾਲੀ ਜਾਂ ਬਹੁਤੀ ਛੋਟੀ ਸਮੱਗਰੀ ਨਾਲ਼ ਈਮੇਲ ਭੇਜਣ ਦੀ ਕੋਸ਼ਿਸ਼ ਕੀਤੀ ਗਈ",
        "changepassword": "ਪਾਸਵਰਡ ਬਦਲੋ",
-       "resetpass_announce": "ਤà©\81ਸà©\80à¨\82 à¨\87ੱà¨\95 à¨\86ਰà¨\9c਼à©\80 à¨\88-ਮà©\87ਲ à¨\95à©\80ਤà©\87 à¨\95à©\8bਡ à¨¨à¨¾à¨² à¨²à¨¾à¨\97à¨\87ਨ à¨\95à©\80ਤਾ à¨¹à©\88। à¨²à¨¾à¨\97à¨\87ਨ à¨ªà©\82ਰਾ à¨\95ਰਨ à¨²à¨\88, à¨¤à©\81ਹਾਨà©\82à©° à¨\87ੱਥà©\87 à¨¨à¨µà¨¾à¨\82 à¨ªà¨¾à¨¸à¨µà¨°à¨¡ à¨¦à©\87ਣਾ à¨ªà¨µà©\87à¨\97ਾ:",
+       "resetpass_announce": "ਲਾà¨\97à¨\87ਨ à¨ªà©\82ਰਾ à¨\95ਰਨ à¨²à¨\88 à¨¤à©\81ਹਾਨà©\82à©° à¨¨à¨µà¨¾à¨\82 à¨ªà¨¾à¨¸à¨µà¨°à¨¡ à¨¬à¨£à¨¾à¨\89ਣਾ à¨ªà¨µà©\87à¨\97ਾ।",
        "resetpass_header": "ਅਕਾਊਂਟ ਪਾਸਵਰਡ ਬਦਲੋ",
        "oldpassword": "ਪੁਰਾਣਾ ਪਾਸਵਰਡ:",
        "newpassword": "ਨਵਾਂ ਪਾਸਵਰਡ:",
        "resetpass-abort-generic": "ਇੱਕ ਐਕਸਟੈਂਸ਼ਨ ਵੱਲੋਂ ਪਾਸਵਰਡ ਦੀ ਤਬਦੀਲੀ ਰੱਦ ਕੀਤੀ ਗਈ",
        "passwordreset": "ਪਾਸਵਰਡ ਮੁੜ-ਸੈੱਟ ਕਰੋ",
        "passwordreset-text-one": "ਪਾਸਵਰਡ ਦੁਬਾਰਾ ਬਣਾਉਣ ਲਈ ਇਹ ਫ਼ਾਰਮ ਭਰੋ।",
-       "passwordreset-text-many": "{{PLURAL:$1|à¨\86ਪਣਾ à¨ªà¨¾à¨¸à¨µà¨°à¨¡ à¨®à©\81à©\9c à¨¬à¨£à¨¾à¨\89ਣ ਲਈ ਕੋਈ ਇੱਕ ਥਾਂ ਭਰੋ।}}",
+       "passwordreset-text-many": "{{PLURAL:$1|à¨\88-ਮà©\87ਲ à¨\9c਼ਰà©\80à¨\8f à¨\86ਪਣਾ à¨\86ਰà¨\9c਼à©\80 à¨ªà¨¾à¨¸à¨µà¨°à¨¡ à¨¹à¨¾à¨¸à¨² à¨\95ਰਨ ਲਈ ਕੋਈ ਇੱਕ ਥਾਂ ਭਰੋ।}}",
        "passwordreset-legend": "ਪਾਸਵਰਡ ਮੁੜ-ਸੈੱਟ ਕਰੋ",
        "passwordreset-disabled": "ਇਸ ਵਿਕੀ ਤੇ ਪਾਸਵਰਡ ਰੀਸੈੱਟ ਬੰਦ ਕੀਤੇ ਗਏ ਹਨ।",
        "passwordreset-emaildisabled": "ਇਹ ਵਿਕਿ ਉੱਤੇ ਈਮੇਲ ਫੀਚਰ ਬੰਦ ਕੀਤਾ ਹੋਇਆ ਹੈ।",
        "currentrev": "ਮੌਜੂਦਾ ਰੀਵਿਜ਼ਨ",
        "currentrev-asof": "$1 ਮੁਤਾਬਕ ਸਭ ਤੋਂ ਨਵਾਂ ਰੀਵਿਜਨ",
        "revisionasof": "$1 ਦਾ ਰੀਵਿਜਨ",
-       "revision-info": "$2 ਦਾ ਬਣਾਇਆ $1 ਦਾ ਰੀਵਿਜਨ",
+       "revision-info": "{{GENDER:$6|$2}}$7 ਦਾ ਬਣਾਇਆ $1 ਦਾ ਰੀਵਿਜ੍ਹਨ",
        "previousrevision": "←ਪੁਰਾਣਾ ਰੀਵਿਜਨ",
        "nextrevision": "ਨਵਾਂ ਰੀਵਿਜਨ →",
        "currentrevisionlink": "ਸਭ ਤੋ ਨਵਾਂ ਰੀਵਿਜਨ",
        "searchprofile-images": "ਮਲਟੀਮੀਡੀਆ",
        "searchprofile-everything": "ਸਭ ਕੁਝ",
        "searchprofile-advanced": "ਉੱਨਤ",
-       "searchprofile-articles-tooltip": "$1 ਵਿੱਚ ਖੋਜ",
+       "searchprofile-articles-tooltip": "$1 ਵਿੱਚ ਖੋਜ",
        "searchprofile-images-tooltip": "ਫ਼ਾਈਲਾਂ ਖੋਜੋ",
        "searchprofile-everything-tooltip": "ਸਾਰੀ ਸਮੱਗਰੀ ਵਿੱਚੋਂ ਖੋਜੋ (ਗੱਲ-ਬਾਤ ਸਫ਼ਿਆਂ ਸਮੇਤ)",
        "searchprofile-advanced-tooltip": "ਆਪਣੀਆਂ ਬਣਾਈਆਂ ਨਾਂ-ਥਾਂਵਾਂ ਵਿੱਚ ਖੋਜੋ",
        "watchlisttools-raw": "ਕੱਚੀ ਨਿਗਰਾਨ-ਸੂਚੀ ਸੋਧੋ",
        "duplicate-defaultsort": "ਪੁਰਾਣੀ ਮੂਲ ਕਰਮਾਂਕਨ ਕੁੰਜੀ $1 ਦੇ ਬਜਾਏ ਹੁਣ ਮੂਲ ਕਰਮਾਂਕਨ ਕੁੰਜੀ $2 ਹੋਵੇਗੀ।",
        "version": "ਵਰਜਨ",
-       "version-specialpages": "ਖ਼ਾਸ ਸਫ਼ੇ",
        "version-skins": "ਸਕਿਨਾਂ",
+       "version-specialpages": "ਖ਼ਾਸ ਸਫ਼ੇ",
        "version-other": "ਹੋਰ",
        "version-hooks": "ਹੁੱਕਾਂ",
        "version-hook-name": "ਹੁੱਕ ਦਾ ਨਾਂ",
index c6b9987..776d7bc 100644 (file)
        "mergehistory-empty": "Brak historii zmian do scalenia.",
        "mergehistory-success": "$3 {{PLURAL:$3|zmiana|zmiany|zmian}} w [[:$1]] zostało scalonych z [[:$2]].",
        "mergehistory-fail": "Scalenie historii zmian jest niewykonalne. Zmień ustawienia parametrów.",
+       "mergehistory-fail-toobig": "Nie można połączyć historii, gdyż wymagałoby to przeniesienia więcej niż maksymalnej dopuszczalnej liczby $1 {{PLURAL:$1|wersji}}.",
        "mergehistory-no-source": "Strona źródłowa $1 nie istnieje.",
        "mergehistory-no-destination": "Strona docelowa $1 nie istnieje.",
        "mergehistory-invalid-source": "Strona źródłowa musi mieć poprawną nazwę.",
        "right-passwordreset": "Sprawdzanie treści e‐maila o resetowaniu hasła",
        "newuserlogpage": "Nowi użytkownicy",
        "newuserlogpagetext": "To jest rejestr ostatnio utworzonych kont użytkowników",
-       "rightslog": "Rejestr uprawnień",
+       "rightslog": "Uprawnienia",
        "rightslogtext": "Rejestr zmian uprawnień użytkowników.",
        "action-read": "przeglądania tej strony",
        "action-edit": "edytowania tej strony",
        "expand_templates_remove_nowiki": "Ukrywaj w wyniku znaczniki <nowiki>",
        "expand_templates_generate_xml": "Pokaż drzewo analizatora składni w formacie XML",
        "expand_templates_generate_rawhtml": "Pokaż surowy HTML",
-       "expand_templates_preview": "Podgląd"
+       "expand_templates_preview": "Podgląd",
+       "pagelanguage": "Wybór języka strony",
+       "pagelang-name": "Strona",
+       "pagelang-language": "Język",
+       "pagelang-use-default": "Użyj domyślnego języka",
+       "pagelang-select-lang": "Wybierz język",
+       "right-pagelang": "Zmiana języka strony",
+       "action-pagelang": "zmiany języka strony",
+       "log-name-pagelang": "Rejestr zmian języka",
+       "log-description-pagelang": "Rejestr zmian języków przypisanych do poszczególnych stron",
+       "logentry-pagelang-pagelang": "$1 {{GENDER:$2|zmienił|zmieniła}} język strony $3 z „$4” na „$5”."
 }
index 93a3514..ff4c931 100644 (file)
        "unprotectthispage": "Alterar a proteção desta página",
        "newpage": "Página nova",
        "talkpage": "Dialogar sobre esta página",
-       "talkpagelinktext": "Discussão",
+       "talkpagelinktext": "discussão",
        "specialpage": "Página especial",
        "personaltools": "Ferramentas pessoais",
        "postcomment": "Nova seção",
        "duplicate-defaultsort": "Aviso: A chave de ordenação padrão \"$2\" sobrepõe-se à anterior chave de ordenação padrão \"$1\".",
        "version": "Versão",
        "version-extensions": "Extensões instaladas",
-       "version-skins": "Temas",
+       "version-skins": "Temas instalados",
        "version-specialpages": "Páginas especiais",
        "version-parserhooks": "Hooks do analisador (parser)",
        "version-variables": "Variáveis",
        "expand_templates_remove_nowiki": "Suprima marcações <nowiki> no resultado",
        "expand_templates_generate_xml": "Mostrar árvore de análise (parse) do XML",
        "expand_templates_generate_rawhtml": "Mostrar HTML puro",
-       "expand_templates_preview": "Pré-visualização"
+       "expand_templates_preview": "Pré-visualização",
+       "pagelang-select-lang": "Selecionar idioma",
+       "right-pagelang": "Mudar idioma da página",
+       "action-pagelang": "mudar idioma da página",
+       "log-name-pagelang": "Mudar idioma do log"
 }
index 38474a4..8d8abfa 100644 (file)
        "edit": "Editar",
        "edit-local": "Editar descrição local",
        "create": "Criar",
-       "create-local": "Adicionar descrição do local",
+       "create-local": "Adicionar descrição local",
        "editthispage": "Editar esta página",
        "create-this-page": "Criar esta página",
        "delete": "Eliminar",
        "unprotectthispage": "Alterar a proteção desta página",
        "newpage": "Página nova",
        "talkpage": "Discutir esta página",
-       "talkpagelinktext": "Discussão",
+       "talkpagelinktext": "discussão",
        "specialpage": "Página especial",
        "personaltools": "Ferramentas pessoais",
        "postcomment": "Seção nova",
        "mergehistory-empty": "Não existem revisões fundíveis.",
        "mergehistory-success": "Foram fundidas $3 {{PLURAL:$3|edição|edições}} de [[:$1]] em [[:$2]].",
        "mergehistory-fail": "Não foi possível fundir os históricos; verifique a página e os parâmetros de tempo, por favor.",
+       "mergehistory-fail-toobig": "Não é possível mesclar o histórico, já que um número de revisão(ões) acima do limite ($1 {{PLURAL:$1|revisão|revisões}}) seriam movidos.",
        "mergehistory-no-source": "A página de origem $1 não existe.",
        "mergehistory-no-destination": "A página de destino $1 não existe.",
        "mergehistory-invalid-source": "A página de origem precisa ser um título válido.",
        "license-nopreview": "(Antevisão indisponível)",
        "upload_source_url": " (uma URL válida, publicamente acessível)",
        "upload_source_file": " (um ficheiro no seu computador)",
+       "listfiles-delete": "eliminar",
        "listfiles-summary": "Esta página especial mostra todos os ficheiros carregados.",
        "listfiles_search_for": "Pesquisar por nome de imagem:",
        "imgfile": "ficheiro",
        "filedelete-maintenance": "Eliminação e restauro de ficheiros foram temporariamente impossibilitadas durante a manutenção.",
        "filedelete-maintenance-title": "Não é possível eliminar o ficheiro",
        "mimesearch": "Pesquisa MIME",
-       "mimesearch-summary": "Esta página permite pesquisar os ficheiros da wiki, filtrando-os a partir do seu tipo MIME. O tipo MIME deve ser especificado na forma: tipo/subtipo. Alguns exemplos de tipos frequentes: <code>image/jpeg</code>, <code>image/gif</code>, <code>image/png</code>, <code>application/pdf</code>, <code>application/vnd.ms-excel</code>, <code>application/zip</code>, <code>application/vnd.ms-powerpoint</code>.",
+       "mimesearch-summary": "Esta página permite a filtragem de ficheiros pelo seu tipo MIME. Entrada: contenttype/subtype ou contenttype/*, ex. <code>image/jpeg</code>.",
        "mimetype": "Tipo MIME:",
        "download": "descarregar",
        "unwatchedpages": "Páginas não vigiadas",
        "uctop": "(atual)",
        "month": "Até o mês:",
        "year": "Até o ano:",
-       "sp-contributions-newbies": "Mostrar só as contribuições das contas recentes",
+       "sp-contributions-newbies": "Mostrar só as contribuições de contas recentes",
        "sp-contributions-newbies-sub": "Para contas novas",
        "sp-contributions-newbies-title": "Contribuições de contas novas",
        "sp-contributions-blocklog": "registo de bloqueios",
        "expand_templates_remove_nowiki": "Suprimir marcações <nowiki> no resultado",
        "expand_templates_generate_xml": "Mostrar a árvore de análise sintáctica do XML",
        "expand_templates_generate_rawhtml": "Mostrar o HTML puro",
-       "expand_templates_preview": "Antevisão do resultado"
+       "expand_templates_preview": "Antevisão do resultado",
+       "pagelanguage": "Seletor de idioma da página",
+       "pagelang-name": "Página",
+       "pagelang-language": "Idioma",
+       "pagelang-use-default": "Usar idioma pré-definido",
+       "pagelang-select-lang": "Escolher o idioma",
+       "right-pagelang": "Alterar o idioma da página",
+       "action-pagelang": "alterar o idioma da página",
+       "log-name-pagelang": "Alterar registo de idioma",
+       "log-description-pagelang": "Este é um registo de alterações aos idiomas das páginas.",
+       "logentry-pagelang-pagelang": "$1 {{GENDER:$2|alterou}} o idioma da página $3 de $4 para $5."
 }
index c8586fc..2dc9235 100644 (file)
        "anonnotice": "{{notranslate}}",
        "newsectionheaderdefaultlevel": "{{notranslate}}\nParameters:\n* $1 - section name",
        "red-link-title": "Title for red hyperlinks. Indicates, that the page is empty, not written yet.\n\nParameters:\n* $1 - page title",
-       "sort-descending": "JavaScript message. Used by sortable table script.",
-       "sort-ascending": "JavaScript message. Used by sortable table script.",
+       "sort-descending": "JavaScript message. Used by sortable table script.\n\nSee also:\n* {{msg-mw|Sort-ascending}}",
+       "sort-ascending": "JavaScript message. Used by sortable table script.\n\nSee also:\n* {{msg-mw|Sort-descending}}\n{{Identical|Sort ascending}}",
        "nstab-main": "The name for the tab of the main namespace. Example: [[Example]]\n\nSee also:\n* {{msg-mw|Nstab-main}}\n* {{msg-mw|Accesskey-ca-nstab-main}}\n* {{msg-mw|Tooltip-ca-nstab-main}}\n{{Identical|Page}}",
        "nstab-user": "The name for the tab of the user namespace. Example: [[User:Example]]. It is possible to use <nowiki>{{GENDER:{{ROOTPAGENAME}}|male form|female form}}</nowiki> if needed.\n\nSee also:\n* {{msg-mw|Nstab-user}}\n* {{msg-mw|Accesskey-ca-nstab-user}}\n* {{msg-mw|Tooltip-ca-nstab-user}}\n{{Identical|User page}}",
        "nstab-media": "The name for the tab of the media namespace. Example: [[Media:Example]]\n\nSee also:\n* {{msg-mw|Nstab-media}}\n* {{msg-mw|Accesskey-ca-nstab-media}}\n* {{msg-mw|Tooltip-ca-nstab-media}}",
        "yourpasswordagain": "Since 1.22 no longer used in core, but may be used by some extensions. DEPRECATED",
        "createacct-yourpasswordagain": "In create account form, label for field to re-enter password\n\nSee example: [{{canonicalurl:Special:UserLogin|type=signup}} Special:UserLogin?type=signup]\n{{Identical|Confirm password}}",
        "createacct-yourpasswordagain-ph": "Placeholder text in create account form for re-enter password field.\n\nSee example: [{{canonicalurl:Special:UserLogin|type=signup}} Special:UserLogin?type=signup]",
-       "remembermypassword": "Used as checkbox label in [[Special:UserLogin]]. Parameters:\n* $1 - number of days\n{{Identical|Remember my login on this computer}}",
+       "remembermypassword": "Used as checkbox label on [[Special:ChangePassword]]. Parameters:\n* $1 - number of days\n{{Identical|Remember my login on this computer}}",
        "userlogin-remembermypassword": "The text for a check box in [[Special:UserLogin]].",
        "userlogin-signwithsecure": "Text of link to HTTPS login form.\n\nSee example: [[Special:UserLogin]]",
        "yourdomainname": "Used as label for listbox.",
        "passwordreset-disabled": "Used as error message in changing password.",
        "passwordreset-emaildisabled": "Used as error message in changing password when site's email feature is disabled.",
        "passwordreset-username": "{{Identical|Username}}",
-       "passwordreset-domain": "A domain like used in Domain Name System (DNS) or more specifically like a domain component in the Lightweight Directory Access Protocol (LDAP)",
+       "passwordreset-domain": "A domain like used in Domain Name System (DNS) or more specifically like a domain component in the Lightweight Directory Access Protocol (LDAP).\n{{Identical|Domain}}",
        "passwordreset-capture": "Label for checkbox asking the user whether they want to see the contents of the password reset email (only shown if they have the <code>passwordreset</code> permission).",
        "passwordreset-capture-help": "Longer explanatory message for the capture checkbox label.",
        "passwordreset-email": "{{Identical|E-mail address}}",
        "license-nopreview": "Error message when a certain license does not exist",
        "upload_source_url": "Used in [[Special:Upload]].\n\nSee also:\n* {{msg-mw|Sourcefilename|label}}\n* {{msg-mw|Sourceurl|label}}\n* {{msg-mw|Upload source file}}\n* {{msg-mw|Upload-maxfilesize}}",
        "upload_source_file": "Used in [[Special:Upload]].\n\nSee also:\n* {{msg-mw|Sourcefilename|label}}\n* {{msg-mw|Sourceurl|label}}\n* {{msg-mw|Upload source url}}\n* {{msg-mw|Upload-maxfilesize}}",
+       "listfiles-delete": "Text of the delete links next to the entries on [[Special:ListFiles]], surrounded by parentheses.\n{{Identical|Delete}}",
        "listfiles-summary": "This message is displayed at the top of [[Special:ImageList]] to explain how to use that special page.",
        "listfiles_search_for": "Input label for the form displayed on [[Special:ListFiles]].",
        "imgfile": "{{Identical|File}}",
        "popularpages-summary": "{{doc-specialpagesummary|popularpages}}",
        "wantedcategories": "{{doc-special|WantedCategories}}",
        "wantedcategories-summary": "{{doc-specialpagesummary|wantedcategories}}",
-       "wantedpages": "{{doc-special|WantedPages}}",
+       "wantedpages": "{{doc-special|WantedPages}}\n{{Identical|Wanted page}}",
        "wantedpages-summary": "{{doc-specialpagesummary|wantedpages}}",
        "wantedpages-badtitle": "Error message shown when [[Special:WantedPages]] is listing a page with a title that shouldn't exist.\n\nParameters:\n* $1 - a page title",
        "wantedfiles": "{{doc-special|WantedFiles}}",
        "wantedfiles-summary": "{{doc-specialpagesummary|wantedfiles}}",
-       "wantedfiletext-cat": "Message displayed at top of [[special:WantedFiles]]. $1 contains the name of the tracking category for broken files (Including Category prefix). {{msg-mw|wantedfiletext-nocat}} is used if the tracking category is disabled.",
-       "wantedfiletext-nocat": "Message displayed at top of [[special:WantedFiles]] when broken file tracking category is disabled. See {{msg-mw|wantedfiletext-cat}}.",
+       "wantedfiletext-cat": "Message displayed at top of [[special:WantedFiles]] when false positives from foreign file repositories (like commons) are likely. $1 contains the name of the tracking category for broken files (Including Category prefix). {{msg-mw|wantedfiletext-nocat}} is used if the tracking category is disabled.\n\nSee also: {{msg-mw|wantedfiletext-cat-noforeign}}, {{msg-mw|wantedfiletext-nocat}}",
+       "wantedfiletext-cat-noforeign": "Message displayed at top of [[special:WantedFiles]] when the wiki has no foreign repositories. See also {{mwg-mw|wantedfilestext-cat}}. $1 contains the name of the tracking category for broken files (Including Category prefix). {{msg-mw|wantedfiletext-nocat}} is used if the tracking category is disabled.",
+       "wantedfiletext-nocat": "Message displayed at top of [[special:WantedFiles]] when broken file tracking category is disabled and false positives from foreign file repositories (like commons) are likely. See {{msg-mw|wantedfiletext-cat}}.",
+       "wantedfiletext-nocat-noforeign": "Message displayed at top of [[special:WantedFiles]] when broken file tracking category is disabled and their are no foreign file repositories enabled on the wiki. See {{msg-mw|wantedfiletext-cat}}, {{msg-mw|wantedfiletext-nocat}}.",
        "wantedtemplates": "{{doc-special|WantedTemplates}}",
        "wantedtemplates-summary": "{{doc-specialpagesummary|wantedtemplates}}",
        "mostlinked": "{{doc-special|MostLinked}}",
        "categoriespagetext": "{{doc-important|Do not translate or change links.}}\nText displayed in [[Special:Categories]].\n\nIn order to translate \"Unused categories\" and \"wanted categories\" see {{msg-mw|Unusedcategories}} and {{msg-mw|Wantedcategories}}.\n\nParameters:\n* $1 - number of categories",
        "categoriesfrom": "Used as label for the input box in [[Special:Categories]].\n\nThis message follows the fieldset label {{msg-mw|categories}}, and is followed by the input box.",
        "special-categories-sort-count": "Commented out at this time.\n\nThis message is used on [[Special:Categories]] to sort the list by the number of members in the categories.\n\nSee also:\n* {{msg-mw|Special-categories-sort-abc}}",
-       "special-categories-sort-abc": "Commented out at this time.\n\nThis message is used on [[Special:Categories]] to sort the list by the category name.\n\nSee also:\n* {{msg-mw|Special-categories-sort-count}}",
+       "special-categories-sort-abc": "Commented out at this time.\n\nThis message is used on [[Special:Categories]] to sort the list by the category name.\n\nSee also:\n* {{msg-mw|Special-categories-sort-count}}\n{{Identical|Sort alphabetically}}",
        "deletedcontributions": "The message is shown as a link on [[Special:SpecialPages]] to [[Special:DeletedContributions]].\n\n{{Identical|Deleted user contributions}}",
        "deletedcontributions-summary": "{{doc-specialpagesummary|deletedcontributions}}",
        "deletedcontributions-title": "Title of [[Special:DeletedContributions]] (extension), a special page with a list of edits to pages which were deleted. Only viewable by sysops.\n\n{{Identical|Deleted user contributions}}",
        "expand_templates_generate_rawhtml": "Used as checkbox label.",
        "expand_templates_preview": "{{Identical|Preview}}",
        "pagelanguage": "Title for page Special:PageLanguage",
-       "pagelang-name": "Input label for page name on Special:PageLanguage",
-       "pagelang-language": "Language selector label for Special:PageLanguage",
+       "pagelang-name": "Input label for page name on Special:PageLanguage\n{{Identical|Page}}",
+       "pagelang-language": "Language selector label for Special:PageLanguage\n{{Identical|Language}}",
        "pagelang-use-default": "Radio label for selector on Special:PageLanguage for default language",
-       "pagelang-select-lang": "Radio label for selector on Special:PageLanguage for language selection",
+       "pagelang-select-lang": "Radio label for selector on Special:PageLanguage for language selection\n{{Identical|Select language}}",
        "right-pagelang": "{{Doc-right|pagelang}}\nRight to change page language on Special:PageLanguage",
        "action-pagelang": "{{Doc-action|pagelang}}",
        "log-name-pagelang": "Display entry for log name for changes in page language in Special:Log.",
        "log-description-pagelang": "Display description for log name for changes in page language in Special:Log.",
-       "logentry-pagelang-pagelang": "Log entry for page language changes in Special:Log."
+       "logentry-pagelang-pagelang": "{{Logentry}}\nAdditional parameters:\n* $4 - old language code, or \"[def]\" (hard-coded)\n* $5 - new language code, or \"[def]\" (hard-coded)"
 }
index de9b5cf..1b49b95 100644 (file)
        "license-nopreview": "(Previzualizare indisponibilă)",
        "upload_source_url": " (un URL valid, accesibil public)",
        "upload_source_file": " (un fișier de pe computerul dv.)",
+       "listfiles-delete": "șterge",
        "listfiles-summary": "Această pagină specială listează toate fișierele încărcate.",
        "listfiles_search_for": "Căutare fișiere după nume:",
        "imgfile": "fișier",
        "expand_templates_remove_nowiki": "Suprimă etichetele <nowiki> în rezultat",
        "expand_templates_generate_xml": "Arată arborele de analiză XML",
        "expand_templates_generate_rawhtml": "Arată HTML brut",
-       "expand_templates_preview": "Previzualizare"
+       "expand_templates_preview": "Previzualizare",
+       "pagelanguage": "Selector limbă pagină",
+       "pagelang-name": "Pagină",
+       "pagelang-language": "Limbă",
+       "pagelang-use-default": "Folosește limba implicită",
+       "pagelang-select-lang": "Alege limba",
+       "right-pagelang": "Modifică limba paginii",
+       "action-pagelang": "modificați limba paginii",
+       "log-name-pagelang": "Jurnal modificare limbă",
+       "log-description-pagelang": "Acesta este un jurnal cu modificări ale limbii paginilor.",
+       "logentry-pagelang-pagelang": "$1 {{GENDER:$2|a modificat}} limba paginii pentru $3 din $4 în $5."
 }
index b1bc29b..45846c3 100644 (file)
        "license-nopreview": "(Предпросмотр недоступен)",
        "upload_source_url": " (правильный, публично доступный интернет-адрес)",
        "upload_source_file": " (файл на вашем компьютере)",
+       "listfiles-delete": "удалить",
        "listfiles-summary": "Эта служебная страница показывает все загруженные файлы.",
        "listfiles_search_for": "Поиск по имени файла:",
        "imgfile": "файл",
        "duplicate-defaultsort": "Внимание. Ключ сортировки по умолчанию «$2» переопределяет прежний ключ сортировки по умолчанию «$1».",
        "version": "Версия",
        "version-extensions": "Установленные расширения",
-       "version-skins": "Темы оформления",
+       "version-skins": "УÑ\81Ñ\82ановленнÑ\8bе Ñ\82емы оформления",
        "version-specialpages": "Служебные страницы",
        "version-parserhooks": "Перехватчики синтаксического анализатора",
        "version-variables": "Переменные",
        "version-license": "Лицензия MediaWiki",
        "version-ext-license": "Лицензия",
        "version-ext-colheader-name": "Расширение",
+       "version-skin-colheader-name": "Тема оформления",
        "version-ext-colheader-version": "Версия",
        "version-ext-colheader-license": "Лицензия",
        "version-ext-colheader-description": "Описание",
        "expand_templates_remove_nowiki": "Подавлять теги <nowiki> в результате",
        "expand_templates_generate_xml": "Показать дерево разбора XML",
        "expand_templates_generate_rawhtml": "Показать HTML",
-       "expand_templates_preview": "Предпросмотр"
+       "expand_templates_preview": "Предпросмотр",
+       "pagelanguage": "Выбор языка страницы",
+       "pagelang-name": "Страница",
+       "pagelang-language": "Язык",
+       "pagelang-use-default": "Использовать язык по умолчанию",
+       "pagelang-select-lang": "Выберите язык",
+       "right-pagelang": "Изменить язык страницы",
+       "action-pagelang": "изменять язык страницы",
+       "log-name-pagelang": "Журнал изменения языка",
+       "log-description-pagelang": "Это журнал изменений в языках страницы.",
+       "logentry-pagelang-pagelang": "$1 изменил{{GENDER:$2||а}} язык страницы для $3 с $4 на $5."
 }
index b9ea08d..62f3650 100644 (file)
        "tog-hidepatrolled": "Ammuccia li mudìfichi fatti ntâ l'ùrtimi canciamenti",
        "tog-newpageshidepatrolled": "Ammuccia li pàggini virificati di l'alencu dî pàgging cchiù novi",
        "tog-extendwatchlist": "Attiva tutti li funzioni avanzati pi l'ossirvati spiciali, nun sulu l'ultima",
-       "tog-usenewrc": "Utilizza Ùrtimi canciamenti avanzati (richiedi JavaScript)",
+       "tog-usenewrc": "Raggruppa li canci pi pàggina ntê canciamenti ricenti e ntâ lista dî taliati spiciali",
        "tog-numberheadings": "Nummirazzioni automàtica dî tìtuli di paràgrafu",
        "tog-showtoolbar": "Ammustra la barra dî strumenta pi lu canciamentu",
-       "tog-editondblclick": "Duppiu click pi canciari l'artìculu (richiedi Javascript)",
-       "tog-editsectiononrightclick": "Abbìlita lu canciamentu dî sezzioni tràmiti duppiu click supra lu tìtulu dâ sezzioni (richiedi Javascript)",
-       "tog-watchcreations": "Agghiunci li pàggini criati a l'ossirvati spiciali",
+       "tog-editondblclick": "Duppiu click pi canciari l'artìculu",
+       "tog-editsectiononrightclick": "Abbìlita lu canciamentu dî sizzioni tràmiti duppiu click a manu dritta supra lu tìtulu dâ sezzioni",
+       "tog-watchcreations": "Agghiunci li pàggini criati e li files â lista dî taliati",
        "tog-watchdefault": "Agghiunci li pàggini canciati a l'ossirvati spiciali",
        "tog-watchmoves": "Agghiunci li pàggini spustati a l'ossirvati spiciali",
        "tog-watchdeletion": "Agghiunci li pàggini di mìa cancillati a l'ossirvati spiciali",
index b2d4751..719ce57 100644 (file)
        "license-nopreview": "(Predogled ni na voljo)",
        "upload_source_url": " (veljaven, javnosti dostopen URL)",
        "upload_source_file": " (datoteka na vašem računalniku)",
+       "listfiles-delete": "izbriši",
        "listfiles-summary": "Ta posebna stran prikazuje vse naložene datoteke.",
        "listfiles_search_for": "Išči po imenu datoteke:",
        "imgfile": "dat.",
        "expand_templates_remove_nowiki": "V rezultatu odstrani oznake <nowiki>",
        "expand_templates_generate_xml": "Pokaži razčlenitveno drevo XML",
        "expand_templates_generate_rawhtml": "Prikaži surovi HTML",
-       "expand_templates_preview": "Predogled"
+       "expand_templates_preview": "Predogled",
+       "pagelanguage": "Izbirnik jezika strani",
+       "pagelang-name": "Stran",
+       "pagelang-language": "Jezik",
+       "pagelang-use-default": "Uporabi privzeti jezik",
+       "pagelang-select-lang": "Izberite jezik",
+       "right-pagelang": "Spreminjanje jezika strani",
+       "action-pagelang": "spreminjanje jezika strani",
+       "log-name-pagelang": "Dnevnik spreminjanja jezika",
+       "log-description-pagelang": "Dnevnik sprememb jezika strani.",
+       "logentry-pagelang-pagelang": "$1 je {{GENDER:$2|spremenil|spremenila|spremenil(-a)}} jezik strani $3 z jezika $4 na jezik $5."
 }
index c52a32c..384a630 100644 (file)
@@ -24,7 +24,9 @@
                        "Urhixidur",
                        "Vinie007",
                        "לערי ריינהארט",
-                       "아라"
+                       "아라",
+                       "Gertakapllani",
+                       "OrvenBregu"
                ]
        },
        "tog-underline": "Nënvizo lidhjet:",
@@ -44,7 +46,7 @@
        "tog-minordefault": "Shëno të gjitha redaktimet si të vogla automatikisht",
        "tog-previewontop": "Vendose kutinë e bocetit sipër kutisë së redaktimeve",
        "tog-previewonfirst": "Tregoje bocetin në redaktimin e parë",
-       "tog-enotifwatchlistpages": "Më njofto me e-mail kur ndryshohet një faqe apo skedaë nga lista ime e faqeve nën mbikqyrje",
+       "tog-enotifwatchlistpages": "Më njofto me e-mail kur ndryshohet një faqe apo skedarë nga lista ime e faqeve nën mbikqyrje",
        "tog-enotifusertalkpages": "Më njofto me e-mail kur faqja ime e dikutimeve të përdoruesit ndryshohet",
        "tog-enotifminoredits": "Më njofto me e-mail edhe kur ka redaktime të vogla në faqe dhe skedave",
        "tog-enotifrevealaddr": "Tregoje adresën time të e-mail-it në e-mail-et njoftuese",
        "thu": "Enj",
        "fri": "Pr",
        "sat": "Sht",
-       "january": "janar",
-       "february": "shkurt",
-       "march": "mars",
-       "april": "prill",
-       "may_long": "maj",
-       "june": "qershor",
-       "july": "korrik",
-       "august": "gusht",
-       "september": "shtator",
-       "october": "tetor",
-       "november": "nëntor",
-       "december": "dhjetor",
-       "january-gen": "janar",
-       "february-gen": "shkurt",
-       "march-gen": "mars",
-       "april-gen": "prill",
-       "may-gen": "maj",
-       "june-gen": "qershor",
+       "january": "Janar",
+       "february": "Shkurt",
+       "march": "Mars",
+       "april": "Prill",
+       "may_long": "Maj",
+       "june": "Qershor",
+       "july": "Korrik",
+       "august": "Gusht",
+       "september": "Shtator",
+       "october": "Tetor",
+       "november": "Nëntor",
+       "december": "Dhjetor",
+       "january-gen": "Janar",
+       "february-gen": "Shkurt",
+       "march-gen": "Mars",
+       "april-gen": "Prill",
+       "may-gen": "Maj",
+       "june-gen": "Qershor",
        "july-gen": "korrik",
-       "august-gen": "gusht",
-       "september-gen": "shtator",
-       "october-gen": "tetor",
-       "november-gen": "nëntor",
-       "december-gen": "dhjetor",
+       "august-gen": "Gusht",
+       "september-gen": "Shtator",
+       "october-gen": "Tetor",
+       "november-gen": "Nëntor",
+       "december-gen": "Dhjetor",
        "jan": "Jan",
        "feb": "Shku",
        "mar": "Mar",
        "oct": "Tet",
        "nov": "Nën",
        "dec": "Dhje",
-       "january-date": "$1 janar",
-       "february-date": "$1 shkurt",
-       "march-date": "$1 mars",
-       "april-date": "$1 prill",
-       "may-date": "$1 maj",
-       "june-date": "$1 qershor",
-       "july-date": "$1 korrik",
-       "august-date": "$1 gusht",
-       "september-date": "$1 shtator",
-       "october-date": "$1 tetor",
-       "november-date": "$1 nëntor",
-       "december-date": "$1 dhjetor",
+       "january-date": "$1 Janar",
+       "february-date": "Shkurt, <span class=\"notranslate\" translate=\"asnjë\">$1</span>",
+       "march-date": "Mars <span class=\"notranslate\" translate=\"asnjë\">$1</span>",
+       "april-date": "Prill <span class=\"notranslate\" translate=\"asnjë\">$1</span>",
+       "may-date": "$1 Maj",
+       "june-date": "$1 Qershor",
+       "july-date": "$1 Korrik",
+       "august-date": "$1 Gusht",
+       "september-date": "$1 Shtator",
+       "october-date": "$1 Tetor",
+       "november-date": "$1 Nëntor",
+       "december-date": "$1 Dhjetor",
        "pagecategories": "{{PLURAL:$1|Kategoria|Kategoritë}}",
        "category_header": "Artikuj në kategorinë \"$1\"",
        "subcategories": "Nën-kategori",
        "anontalk": "Diskutimet për këtë IP",
        "navigation": "Shfleto",
        "and": "&#32;dhe",
-       "qbfind": "Kërko",
+       "qbfind": "Gjeni",
        "qbbrowse": "Shfletoni",
        "qbedit": "Redaktoni",
        "qbpageoptions": "Kjo faqe",
        "qbmyoptions": "Faqet e mia",
        "faq": "Pyetje që bëhen shpesh",
-       "faqpage": "Project: Pyetje që bëhen shpesh",
+       "faqpage": "Projekt: Pyetje që bëhen shpesh",
        "actions": "Veprimet",
        "namespaces": "Hapsirat e emrit",
        "variants": "Variante",
        "invalidtitle-knownnamespace": "Titull jo i vlefshëm me hapësirën \"$2\" dhe teksti \"$3\"",
        "invalidtitle-unknownnamespace": "Titull jo i vlefshëm me numrin e panjohur të hapësirës së emrit $1 dhe tekstit \"$2\"",
        "exception-nologin": "I paqasur",
-       "exception-nologin-text": "Kjo faqe ose ky veprim ju kërkon që të qaseni në këtë wiki.",
+       "exception-nologin-text": "Ju lutem [[Special:Userlogin|hyni brënda]] për të qenë  në gjendje të hyni në këtë faqe ose veprim.",
        "exception-nologin-text-manual": "Ju lutem <span class=\"notranslate\" translate=\"asnjë\">$1</span> që të jeni në gjendje për të hyrë në këtë faqe ose të veproni.",
        "virus-badscanner": "Konfiguracion i parregullt: Skaner i panjohur virusesh: ''$1''",
        "virus-scanfailed": "skani dështoi (code $1)",
        "createacct-benefit-heading": "{{SITENAME}} është bërë nga njerëz si ju.",
        "createacct-benefit-body1": "$1 {{PLURAL:$1|redaktim|redaktime}}",
        "createacct-benefit-body2": "\n{{Plural: $ 1 | faqe | faqe}}",
+       "createacct-benefit-body3": "kohët e fundit <span class=\"notranslate\" translate=\"asnjë\">{{PLURAL:$1|</span>kontribues|kontribuesit}}",
        "badretype": "Fjalëkalimet nuk janë njësoj.",
        "userexists": "Emri i përdoruesit që kërkuat është në përdorim. \nZgjidhni një emër tjetër.",
        "loginerror": "Gabim gjatë identifikimit",
+       "createacct-error": "krijim gabim llogarie",
        "createaccounterror": "I pamundur krijimi i llogarisë: $1",
        "nocookiesnew": "Llogaria e përdoruesit u krijua por ju nuk jeni identifikuar ende.\n{{SITENAME}} shfrytëzon \"cookies\" për të identifikuar përdoruesit.\nJu nuk mundësoni lejimin e \"cookies\".\nJu lutemi, mundësojini ato, pastaj identifikohuni me anë të të dhënave tuaja të reja: emri i përdoruesit dhe fjalëkalimi.",
        "nocookieslogin": "{{SITENAME}} shfrytëzon \"cookies\" për identifikimin e përdoruesve.\nYou nuk lejoni shfrytëzimin e \"cookies\".\nJu lutemi, lejoni shfrytëzimin e \"cookies\" dhe provojeni përsëri.",
        "passwordtooshort": "Fjalëkalimi juaj është i pavlefshëm ose tepër i shkurtër. Ai duhet të ketë së paku {{PLURAL:$1|1 shkronjë|$1 shkronja}} dhe duhet të jetë i ndryshëm nga emri i përdoruesit.",
        "password-name-match": "Fjalëkalimi juaj duhet të jetë i ndryshëm nga emri juaj.",
        "password-login-forbidden": "Përdorimi i kësaj nofke dhe fjalëkalimi është i ndaluar.",
-       "mailmypassword": "Më dërgo një fjalëkalim të ri tek adresa ime",
+       "mailmypassword": "Ridergo fjalekalimin",
        "passwordremindertitle": "Kërkesë për fjalëkalim të ri tek {{SITENAME}}",
        "passwordremindertext": "Dikush (sigurisht ju, nga adresa IP adresa $1) kërkoi një fjalëkalim të ri për hyrje tek {{SITENAME}} ($4). U krijua fjalëkalimi i përkohshëm për përdoruesin \"$2\" dhe u dërgua tek \"$3\". Nëse ky ishte tentimi juaj duhet që të kyçeni dhe ndërroni fjalëkalimin tani. Fjalëkalimi juaj i përkohshëm do të skadojë {{PLURAL:$5|një dite|$5 ditësh}}.\n\nNëse ndokush tjetër ka bërë këtë kërkesë, ose nëse ju kujtohet fjalëkalimin dhe nuk doni që ta ndërroni, mund të e injoroni këtë porosi dhe të vazhdoni të përdorni  fjalëkalimin e vjetër.",
        "noemail": "Regjistri nuk ka adresë për përdoruesin \"$1\".",
        "noemailcreate": "Ju duhet të sigurojë një adresë e e-mailit të saktë.",
        "passwordsent": "Një fjalëkalim i ri është dërguar tek adresa e regjistruar për \"$1\". Provojeni përsëri hyrjen mbasi ta keni marrë fjalëkalimin.",
        "blocked-mailpassword": "IP adresa juaj është bllokuar , si e tillë nuk lejohet të përdor funksionin pë rikthim të fjalkalimit , në mënyrë që të parandalohet abuzimi.",
-       "eauthentsent": "Një eMail konfirmues u dërgua te adresa e dhënë.\nPara se të pranohen eMail nga përdoruesit e tjerë, duhet që adressa e juaj të vërtetohet.\nJu lutemi ndiqni këshillat në eMailin e pranuar.",
+       "eauthentsent": "Një email konfirmimi është dërguar në adresën e caktuar  të e-mailit.\nParase te dergohen emaile të tjerë  në llogarinë tuaj, duhet të ndiqni udhëzimet në email, për të konfirmuar se llogaria është  vërtetë e juaja.",
        "throttled-mailpassword": "Një kujtesë e fjalëkalimit është dërguar gjatë {{PLURAL:$1|orës|$1 orëve}} të kaluara. Për t'u mbrojtur nga abuzime vetëm një kujtesë dërgohet çdo {{PLURAL:$1|orë|$1 orë}}.",
        "mailerror": "Gabim duke dërguar postën: $1",
        "acct_creation_throttle_hit": "Nuk lejoheni të krijoni më llogari pasi keni krijuar {{PLURAL:$1|1|$1}}.",
        "accountcreatedtext": "Llogarija e Përdoruesit për $1 u krijua",
        "createaccount-title": "Hapja e llogarive për {{SITENAME}}",
        "createaccount-text": "Dikush ka përdorur adresën tuaj për të hapur një llogari tek {{SITENAME}} ($4) të quajtur \"$2\" me fjalëkalimin \"$3\".\nDuhet të hyni brenda dhe të ndërroni fjalëkalimin tani nëse ky person jeni ju. Përndryshe shpërfilleni këtë mesazh.",
-       "login-throttled": "Keni bërë shumë tentime të njëpasnjëshme në fjalëkalimin e kësaj llogarie. Ju lutemi prisni para tentimit përsëri.",
+       "login-throttled": "Keni bërë shumë tentime të njëpasnjëshme në fjalëkalimin e kësaj llogarie. Ju lutemi prisni para se te tentoni përsëri.",
        "login-abort-generic": "login juaj ishte i pasuksesshëm - Ndërpre",
        "loginlanguagelabel": "Gjuha: $1",
        "suspicious-userlogout": "Kërkesa juaj për të shkëputet u mohua sepse duket sikur është dërguar nga një shfletues të thyer ose caching proxy.",
+       "createacct-another-realname-tip": "* Emri i vërtetë nuk është i domosdoshëm: Nëse e jepni do të përmendeni si kontribues për punën që ke bërë.",
+       "pt-login": "Hyni",
+       "pt-login-button": "Hyni",
+       "pt-createaccount": "Krijo llogari",
+       "pt-userlogout": "Dil",
        "php-mail-error-unknown": "Gabim i panjohur në funksionin e postës PHP ()",
        "user-mail-no-addy": "Provuat të dërgoni një korrespondencë pa adresë elektronike",
+       "user-mail-no-body": "U përpoqët të dërgonio email me një përmbajtje të shkurtër dhe të paarsyeshme.",
        "changepassword": "Ndërroni fjalëkalimin",
-       "resetpass_announce": "Ju keni hyrë me një kod të përkohshëm.\nPër të hyrë tërësisht duhet të vendosni një fjalëkalim të ri këtu:",
+       "resetpass_announce": "Për të përfunduar regjistrimin, ju duhet të vendosni një fjalëkalim të ri.",
        "resetpass_header": "Ndrysho fjalëkalimin e llogarisë",
        "oldpassword": "I vjetri",
        "newpassword": "I riu",
        "retypenew": "I riu përsëri",
        "resetpass_submit": "Ndrysho fjalëkalimin dhe hyni brenda",
-       "changepassword-success": "Fjalëkalimi juaj është ndryshuar me sukses! Mund të hyni brenda...",
+       "changepassword-success": "Fjalëkalimin juaj ka ndryshuar me sukses!",
+       "changepassword-throttled": "Keni bërë shumë tentime të njëpasnjëshme në fjalëkalimin e kësaj llogarie. Ju lutemi prisni para se te tentoni përsëri.",
        "resetpass_forbidden": "Fjalëkalimet nuk mund të ndryshohen",
        "resetpass-no-info": "Duhet të jeni i kyçur që të keni qasje direkte në këtë faqe.",
        "resetpass-submit-loggedin": "Ndrysho fjalëkalimin",
        "resetpass-submit-cancel": "Anulo",
        "resetpass-wrong-oldpass": "Fjalëkalimi momental ose i përkohshëm nuk është i vlefshëm. Ndoshta tanimë me sukses keni ndërruar fjalëkalimin, ose keni kërkuar fjalëkalim të përkohshëm.",
+       "resetpass-recycled": "Ju lutemi rivendosni fjalëkalimin tuaj për diçka tjetër përveç fjalëkalimin tuaj të tanishme.",
+       "resetpass-temp-emailed": "Ju keni hyrë në me një koditë përkohshme të dërguar me email .\nPër të përfundojë logging in, ju duhet të vendosni një fjalëkalim të ri këtu:",
        "resetpass-temp-password": "Fjalëkalimi i përkohshëm:",
+       "resetpass-abort-generic": "Ndryshimi i fjalëkalimi  dështoi nga një zgjerim.",
        "resetpass-expired": "Fjalëkalimin tuaj ka skaduar. Ju lutem vendosni një fjalëkalim të ri për të hyr.",
        "resetpass-expired-soft": "Fjalëkalimi juaj ka skaduar dhe duhet të rivendoset. Ju lutem zgjidhni një fjalëkalim të ri tani, ose klikoni \"{{int:resetpass-submit-cancel}}\" për ta rivendosur më vonë.",
+       "resetpass-validity-soft": "Fjalëkalimi juaj ka skaduar dhe duhet të rivendoset. Ju lutem zgjidhni një fjalëkalim të ri tani, ose klikoni \"{{int:resetpass-submit-cancel}}\" për ta rivendosur më vonë.",
        "passwordreset": "Ndrysho fjalkalimin",
+       "passwordreset-text-one": "Plotësoni këtë formular për të marrë një fjalëkalim të përkohshëm nëpërmjet postës elektronike.",
+       "passwordreset-text-many": "<span class=\"notranslate\" translate=\"asnjë\">{{PLURAL:$1|</span>Mbush një nga fushat për të marrë një fjalëkalim të përkohshëm nëpërmjet postës elektronike.}}",
        "passwordreset-legend": "Ndrysho fjalkalimin",
        "passwordreset-disabled": "Rivendosja e fjalëkalimit është deaktivizuar në këtë wiki.",
+       "passwordreset-emaildisabled": "Karakteristikat e  Email janë të paaftë në këtë wiki.",
        "passwordreset-username": "Nofka:",
        "passwordreset-domain": "Domain:",
        "passwordreset-capture": "Dëshiron të shikosh e-mail-in që rezulton?",
        "edit-gone-missing": "Faqja nuk mund t freskohet.\nDuket se është grisur.",
        "edit-conflict": "Konflikt në redaktim.",
        "edit-no-change": "Redaktimi juaj është anashkaluar pasi që asnjë ndryshim nuk u bë në tekst.",
+       "postedit-confirmation-created": "Faqja eshte krijuar",
+       "postedit-confirmation-restored": "Faqja eshte kthyer",
+       "postedit-confirmation-saved": "Redaktimi juaj eshte ruajtur.",
        "edit-already-exists": "Faqja nuk mundej të hapet.\nAjo tanimë ekziston.",
        "defaultmessagetext": "Teksti i porosisë së parazgjedhur",
-       "editwarning-warning": "Lënia e kësaj faqeje mund t'ju shkaktojë humbjen e çdo ndryshimi që keni bërë.\nNëse keni hyrë brenda, ju mund ta hiqni këtë paralajmërim në seksionin \"Redaktimi\" tek preferencat tuaja.",
+       "invalid-content-data": "Të pavlefshme të dhënave e përmbajtjes",
+       "editwarning-warning": "Duke e lënë këtë faqe mund të shkaktojë ju për të humbur të gjitha ndryshimet që keni bërë ju.\nNëse ju jeni regjistruar, ju mund të çaktivizoni këtë paralajmërim në \"{{int:prefs-editing}}\" seksionin e preferencave tuaja.",
        "content-model-text": "tekst i thejshtë",
        "expensive-parserfunction-warning": "Kujdes: Kjo faqe ka shumë kërkesa që kërkojnë analizë gramatikore të kushtueshme për sistemin.\n\nDuhet të ketë më pakë se $2, {{PLURAL:$2|kërkesë|kërkesa}}, kurse tani {{PLURAL:$1|është $1 kërkesë|janë $1 kërkesa}}.",
        "expensive-parserfunction-category": "Faqe me shumë shprehje të kushtueshmë për analizë gramatikore",
        "license-nopreview": "(Nuk ka parapamje)",
        "upload_source_url": " (URL e vlefshme, publikisht e përdorshme)",
        "upload_source_file": " (skeda në kompjuterin tuaj)",
+       "listfiles-delete": "fshije",
        "listfiles-summary": "Kjo faqe speciale tregon tërë skedat e ngarkuara.\nFillimisht skedat e ngarkuara së fundmi jepen më sipër.\nShtypni kolonat e tjera për të ndryshuar radhitjen.",
        "listfiles_search_for": "Kërko për emrin e figurës:",
        "imgfile": "skeda",
index e7dc0d6..83ee30b 100644 (file)
@@ -58,7 +58,7 @@
        "tog-watchlisthideminor": "Сакриј мање измене са списка надгледања",
        "tog-watchlisthideliu": "Сакриј измене пријављених корисника са списка надгледања",
        "tog-watchlisthideanons": "Сакриј измене анонимних корисника са списка надгледања",
-       "tog-watchlisthidepatrolled": "Сакриј прегледане измене са списка надгледања",
+       "tog-watchlisthidepatrolled": "Сакриј патролиране измене са списка надгледања",
        "tog-ccmeonemails": "Пошаљи ми копије е-порука које пошаљем другим корисницима",
        "tog-diffonly": "Не приказуј садржај странице испод разлика",
        "tog-showhiddencats": "Прикажи скривене категорије",
        "resetpass-expired-soft": "Ваша лозинка је истекла и морате поставити нову. Поставите нову лозинку или кликните „{{int:resetpass-submit-cancel}}“ да је поставите касније.",
        "resetpass-validity-soft": "Ваша лозинка није ваљана: $1\n\nМолимо изаберите нову или кликните „{{int:resetpass-submit-cancel}}“ да ресетујете касније.",
        "passwordreset": "Обнављање лозинке",
-       "passwordreset-text-one": "Попуните овај образац да бисте ресетовали лозинку.",
+       "passwordreset-text-one": "Попуните овај образац да бисте добили привремену лозинку на е-пошту.",
        "passwordreset-text-many": "{{PLURAL:$1|Испуните једно од поља како би сте добили привремену лозинку на е-пошту.}}",
        "passwordreset-legend": "Поништи лозинку",
        "passwordreset-disabled": "Обнављање лозинке је онемогућено на овом викију.",
        "mergehistory-empty": "Нема измена за спајање.",
        "mergehistory-success": "$3 {{PLURAL:$3|измена странице [[:$1]] је спојена|измене странице [[:$1]] су спојене|измена странице [[:$1]] је спојено}} у [[:$2]].",
        "mergehistory-fail": "Не могу да спојим историје. Проверите страницу и временске параметре.",
-       "mergehistory-fail-toobig": "Није могуће спојити историје јер више од $1 {{PLURAL:$1|измене|измена}} ће бити премештено.",
+       "mergehistory-fail-toobig": "Није могуће спојити историје јер више од $1 {{PLURAL:$1|измене ће бити премештене|измена ће бити премештено}}.",
        "mergehistory-no-source": "Изворна страница $1 не постоји.",
        "mergehistory-no-destination": "Одредишна страница $1 не постоји.",
        "mergehistory-invalid-source": "Изворна страница мора имати исправан наслов.",
        "showhideselectedversions": "Прикажи/сакриј изабране измене",
        "editundo": "поништи",
        "diff-empty": "(Нема разлике)",
-       "diff-multi-sameuser": "({{PLURAL:$1|Једна међуизмена истог корисника није приказана|$1 међуизмена истог корисника није приказано}})",
-       "diff-multi-otherusers": "({{PLURAL:$1|Једна међуизмена|$1 међуизмена}} од стране {{PLURAL:$2|још једног корисника није приказана|$2 корисника није приказано}})",
+       "diff-multi-sameuser": "({{PLURAL:$1|Ð\88една Ð¼ÐµÑ\92Ñ\83измена Ð¸Ñ\81Ñ\82ог ÐºÐ¾Ñ\80иÑ\81ника Ð½Ð¸Ñ\98е Ð¿Ñ\80иказана|$1 Ð¼ÐµÑ\92Ñ\83измене Ð¸Ñ\81Ñ\82ог ÐºÐ¾Ñ\80иÑ\81ника Ð½Ð¸Ñ\98е Ð¿Ñ\80иказано|$1 Ð¼ÐµÑ\92Ñ\83измена Ð¸Ñ\81Ñ\82ог ÐºÐ¾Ñ\80иÑ\81ника Ð½Ð¸Ñ\98е Ð¿Ñ\80иказано}})",
+       "diff-multi-otherusers": "({{PLURAL:$1|Ð\88една Ð¼ÐµÑ\92Ñ\83измена|$1 Ð¼ÐµÑ\92Ñ\83измене|$1 Ð¼ÐµÑ\92Ñ\83измена}} Ð¾Ð´ Ñ\81Ñ\82Ñ\80ане {{PLURAL:$2|Ñ\98оÑ\88 Ñ\98едног ÐºÐ¾Ñ\80иÑ\81ника Ð½Ð¸Ñ\98е Ð¿Ñ\80иказана|$2 ÐºÐ¾Ñ\80иÑ\81ника Ð½Ð¸Ñ\98е Ð¿Ñ\80иказано}})",
        "diff-multi-manyusers": "({{PLURAL:$1|Није приказана међуизмена|Нису приказане $1 међуизмене|Није приказано $1 међуизмена}} од више од $2 корисника)",
        "difference-missing-revision": "Не могу да пронађем {{PLURAL:$2|једну измену|$2 измене|$2 измена}} од ове разлике ($1).\n\nОво се обично дешава када пратите застарелу везу до странице која је обрисана.\nВише информација можете пронаћи у [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} дневнику брисања].",
        "searchresults": "Резултати претраге",
        "license-nopreview": "(преглед није доступан)",
        "upload_source_url": " (исправна и јавно доступна адреса)",
        "upload_source_file": "(датотека на вашем рачунару)",
+       "listfiles-delete": "обриши",
        "listfiles-summary": "Ова посебна страница приказује све послате датотеке.",
        "listfiles_search_for": "Назив датотеке:",
        "imgfile": "датотека",
        "expand_templates_input": "Унос:",
        "expand_templates_output": "Резултат",
        "expand_templates_xml_output": "XML излаз",
-       "expand_templates_html_output": "Сиров ХТМЛ излаз",
+       "expand_templates_html_output": "Сиров HTML излаз",
        "expand_templates_ok": "У реду",
        "expand_templates_remove_comments": "Уклони коментаре",
        "expand_templates_remove_nowiki": "Поништава ефекат <nowiki> тагова у приказу чланака",
-       "expand_templates_generate_xml": "прикажи XML стабло",
-       "expand_templates_generate_rawhtml": "Покажи сиров ХТМЛ",
-       "expand_templates_preview": "Приказ"
+       "expand_templates_generate_xml": "Прикажи XML стабло",
+       "expand_templates_generate_rawhtml": "Прикажи сиров HTML",
+       "expand_templates_preview": "Приказ",
+       "pagelang-name": "Страница",
+       "pagelang-language": "Језик",
+       "pagelang-select-lang": "Изабери језик",
+       "right-pagelang": "промена језика странице",
+       "action-pagelang": "промену језика странице"
 }
index c60af1f..799eaea 100644 (file)
@@ -50,7 +50,7 @@
        "tog-watchlisthideminor": "Sakrij manje izmene sa spiska nadgledanja",
        "tog-watchlisthideliu": "Sakrij izmene prijavljenih korisnika sa spiska nadgledanja",
        "tog-watchlisthideanons": "Sakrij izmene anonimnih korisnika sa spiska nadgledanja",
-       "tog-watchlisthidepatrolled": "Sakrij pregledane izmene sa spiska nadgledanja",
+       "tog-watchlisthidepatrolled": "Sakrij patrolirane izmene sa spiska nadgledanja",
        "tog-ccmeonemails": "Pošalji mi primerke e-poruka koje pošaljem drugim korisnicima",
        "tog-diffonly": "Ne prikazuj sadržaj stranice ispod razlika",
        "tog-showhiddencats": "Prikaži skrivene kategorije",
        "resetpass-expired-soft": "Vaša lozinka je istekla i morate postaviti novu. Postavite novu lozinku ili kliknite „{{int:resetpass-submit-cancel}}“ da je postavite kasnije.",
        "resetpass-validity-soft": "Vaša lozinka nije valjana: $1\n\nMolimo izaberite novu ili kliknite „{{int:resetpass-submit-cancel}}“ da resetujete kasnije.",
        "passwordreset": "Obnavljanje lozinke",
-       "passwordreset-text-one": "Popunite ovaj obrazac da biste resetovali lozinku.",
+       "passwordreset-text-one": "Popunite ovaj obrazac da biste dobili privremenu lozinku na e-poštu.",
        "passwordreset-text-many": "{{PLURAL:$1|Ispunite jedno od polja kako bi ste dobili privremenu lozinku na e-poštu.}}",
        "passwordreset-legend": "Poništi lozinku",
        "passwordreset-disabled": "Obnavljanje lozinke je onemogućeno na ovom vikiju.",
        "showhideselectedversions": "Prikaži/sakrij izabrane izmene",
        "editundo": "poništi",
        "diff-empty": "(Nema razlike)",
-       "diff-multi-sameuser": "({{PLURAL:$1|Jedna međuizmena istog korisnika nije prikazana|$1 međuizmena istog korisnika nije prikazano}})",
-       "diff-multi-otherusers": "({{PLURAL:$1|Jedna međuizmena|$1 međuizmena}} od strane {{PLURAL:$2|još jednog korisnika nije prikazana|$2 korisnika nije prikazano}})",
+       "diff-multi-sameuser": "({{PLURAL:$1|Jedna međuizmena istog korisnika nije prikazana|$1 međuizmene istog korisnika nije prikazano|$1 međuizmena istog korisnika nije prikazano}})",
+       "diff-multi-otherusers": "({{PLURAL:$1|Jedna međuizmena|$1 međuizmene|$1 međuizmena}} od strane {{PLURAL:$2|još jednog korisnika nije prikazana|$2 korisnika nije prikazano}})",
        "diff-multi-manyusers": "({{PLURAL:$1|Nije prikazana međuizmena|Nisu prikazane $1 međuizmene|Nije prikazano $1 međuizmena}} od više od $2 korisnika)",
        "difference-missing-revision": "Ne mogu da pronađem {{PLURAL:$2|jednu izmenu|$2 izmene|$2 izmena}} od ove razlike ($1).\n\nOvo se obično dešava kada pratite zastarelu vezu do stranice koja je obrisana.\nViše informacija možete pronaći u [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} dnevniku brisanja].",
        "searchresults": "Rezultati pretrage",
        "expand_templates_ok": "U redu",
        "expand_templates_remove_comments": "Ukloni komentare",
        "expand_templates_remove_nowiki": "Poništava efekat <nowiki> tagova u prikazu članaka",
-       "expand_templates_generate_xml": "prikaži XML stablo",
+       "expand_templates_generate_xml": "Prikaži XML stablo",
        "expand_templates_preview": "Prikaz"
 }
index 024635e..6dc5f90 100644 (file)
        "subject": "Ämne/rubrik:",
        "minoredit": "Mindre ändring (m)",
        "watchthis": "Bevaka denna sida",
-       "savearticle": "Spara sida",
+       "savearticle": "Spara sidan",
        "preview": "Förhandsgranska",
        "showpreview": "Visa förhandsgranskning",
        "showdiff": "Visa ändringar",
        "allinnamespace": "Alla sidor (i namnrymden $1)",
        "allpagessubmit": "Visa",
        "allpagesprefix": "Visa sidor med prefixet:",
-       "allpagesbadtitle": "Den sökta sidtiteln var ogiltig eller så innehöll den ett prefix för annan språkversion eller interwiki-prefix. Titeln kan innehålla bokstäver som inte är tillåtna i sidtitlar.",
+       "allpagesbadtitle": "Den angivna sidtiteln var ogiltig eller innehöll ett prefix för annan språkversion eller ett interwiki-prefix.\nDen kan innehålla en eller fler tecken som inte är tillåtna i titlar.",
        "allpages-bad-ns": "Namnrymden \"$1\" finns inte på {{SITENAME}}.",
        "allpages-hide-redirects": "Göm omdirigeringar",
        "cachedspecial-viewing-cached-ttl": "Du visar en cachad version av denna sida, som kan vara upp till $1 gammal.",
        "expand_templates_remove_nowiki": "Undertryck <nowiki> taggar i resultatet",
        "expand_templates_generate_xml": "Visa parseträd som XML",
        "expand_templates_generate_rawhtml": "Visa rå HTML",
-       "expand_templates_preview": "Förhandsvisning"
+       "expand_templates_preview": "Förhandsvisning",
+       "pagelanguage": "Sidspråksväljare",
+       "pagelang-name": "Sida",
+       "pagelang-language": "Språk",
+       "pagelang-use-default": "Använd standardspråk",
+       "pagelang-select-lang": "Välj språk",
+       "right-pagelang": "Ändra sidans språk",
+       "action-pagelang": "ändra sidspråket",
+       "log-name-pagelang": "Språkändringslogg",
+       "log-description-pagelang": "Detta är en logg över ändringar i sidspråken.",
+       "logentry-pagelang-pagelang": "$1 {{GENDER:$2|ändrade}} sidspråket för $3 från $4 till $5."
 }
index acc6e63..083efdd 100644 (file)
        "wantedtemplates": "แม่แบบที่ต้องการ",
        "mostlinked": "หน้าที่มีการเชื่อมโยงหามากที่สุด",
        "mostlinkedcategories": "หมวดหมู่ที่มีการเชื่อมโยงหามากที่สุด",
-       "mostlinkedtemplates": "à¹\81มà¹\88à¹\81à¸\9aà¸\9aที่มีการเชื่อมโยงหามากที่สุด",
+       "mostlinkedtemplates": "หà¸\99à¹\89าที่มีการเชื่อมโยงหามากที่สุด",
        "mostcategories": "หน้าที่มีหมวดหมู่มากที่สุด",
        "mostimages": "ภาพที่มีการโยงไปหามากที่สุด",
        "mostinterwikis": "หน้าที่มีลิงก์ข้ามโครงการมากที่สุด",
        "pageinfo-length": "ความยาวหน้า (ไบต์)",
        "pageinfo-article-id": "หมายเลขประจำหน้า",
        "pageinfo-language": "ภาษาเนื้อหาของหน้า",
+       "pageinfo-content-model": "ตัวแบบเนื้อหาของหน้า",
        "pageinfo-robot-policy": "การทำดัชนีโดยบอต",
        "pageinfo-robot-index": "อนุญาต",
        "pageinfo-robot-noindex": "ไม่อนุญาต",
        "duplicate-defaultsort": "คำเตือน: หลักเรียงลำดับปริยาย \"$2\" ได้ลบล้างหลักเรียงลำดับปริยาย \"$1\" ที่มีอยู่ก่อนหน้า",
        "version": "รุ่นซอฟต์แวร์",
        "version-extensions": "ส่วนขยายเพิ่ม (extension) ที่ติดตั้ง",
-       "version-skins": "รูปลักษณ์",
+       "version-skins": "รูปลักษณ์ที่ติดตั้ง",
        "version-specialpages": "หน้าพิเศษ",
        "version-parserhooks": "ฮุกที่มีการพาร์สค่า",
        "version-variables": "ตัวแปร",
index 5b9b74a..00479fe 100644 (file)
        "expand_templates_remove_nowiki": "Sonuçlarda <nowiki> etiketlerini bastır",
        "expand_templates_generate_xml": "XML derleyici ağacını göster",
        "expand_templates_generate_rawhtml": "Ham HTML göster",
-       "expand_templates_preview": "Önizleme"
+       "expand_templates_preview": "Önizleme",
+       "pagelang-language": "Dil",
+       "pagelang-use-default": "Varsayılan dili kullan",
+       "pagelang-select-lang": "Dil seçin",
+       "right-pagelang": "Sayfa dilini değiştir"
 }
index b3a08bc..95d9f26 100644 (file)
@@ -50,7 +50,7 @@
                        "Calak"
                ]
        },
-       "tog-underline": "Підкреслювати посилання:\nПідкреслювання посилань:",
+       "tog-underline": "Підкреслювання посилань:",
        "tog-hideminor": "Приховати незначні редагування у списку останніх змін",
        "tog-hidepatrolled": "Приховувати патрульовані редагування у списку нових редагувань",
        "tog-newpageshidepatrolled": "Приховувати патрульовані сторінки у списку нових сторінок",
        "unexpected": "Неочікуване значення: «$1»=«$2».",
        "formerror": "Помилка: неможливо передати дані форми",
        "badarticleerror": "Ця дія не може бути виконана на цій сторінці.",
-       "cannotdelete": "Неможливо вилучити сторінку або файл \"$1\".\nМожливо, її (його) вже вилучив хтось інший.",
+       "cannotdelete": "Неможливо вилучити сторінку або файл «$1».\nМожливо, її (його) вже вилучив хтось інший.",
        "cannotdelete-title": "Не вдається видалити сторінку «$1»",
        "delete-hook-aborted": "Вилучення було скасовано процедурою-перехоплювачем. \nНіяких поясненень надано не було.",
        "no-null-revision": "Не вдалося створити нульову версію сторінки «$1»",
        "namespaceprotected": "У вас нема дозволу редагувати сторінки в просторі назв «$1».",
        "customcssprotected": "У вас немає прав на редагування цієї CSS-сторінки, так як вона містить особисті налаштування іншого користувача.",
        "customjsprotected": "У вас немає дозволу на редагування цієї JavaScript-сторінки, так як вона містить особисті налаштування іншого користувача.",
-       "mycustomcssprotected": "У Ð²ас немає прав для редагування цієї CSS сторінки.",
+       "mycustomcssprotected": "У Ð\92ас немає прав для редагування цієї CSS сторінки.",
        "mycustomjsprotected": "Ви не маєте дозволу для редагування цієї сторінки JavaScript.",
        "myprivateinfoprotected": "У Вас немає дозволу на редагування своєї приватної інформації.",
        "mypreferencesprotected": "У Вас немає дозволу на редагування своїх налаштувань.",
        "currentrev": "Поточна версія",
        "currentrev-asof": "Поточна версія на $1",
        "revisionasof": "Версія за $1",
-       "revision-info": "Версія від $1; $2",
+       "revision-info": "Версія від $1, створена {{GENDER:$6|$2}}$7",
        "previousrevision": "← Попередня версія",
        "nextrevision": "Новіша версія →",
        "currentrevisionlink": "Поточна версія",
        "mergehistory-empty": "Не знайдені редагування для об'єднання.",
        "mergehistory-success": "$3 {{PLURAL:$3|редагування|редагування|редагувань}} з [[:$1]] успішно перенесені до [[:$2]].",
        "mergehistory-fail": "Не вдалося здійснити об'єднання історій сторінок, будь ласка, перевірте параметри сторінки й часу.",
+       "mergehistory-fail-toobig": "Не вдалося виконати злиття історії оскільки буде перейменовано більше, ніж ліміт у $1 {{PLURAL:$1|версію|версії|версій}}.",
        "mergehistory-no-source": "Вихідна сторінка «$1» не існує.",
        "mergehistory-no-destination": "Цільова сторінка «$1» не існує.",
        "mergehistory-invalid-source": "Джерело повинне мати правильний заголовок.",
        "userrights": "Керування правами користувачів",
        "userrights-lookup-user": "Керування групами користувача",
        "userrights-user-editname": "Введіть ім'я користувача:",
-       "editusergroup": "Редагувати групи користувача",
+       "editusergroup": "Редагувати групи користувачів",
        "editinguser": "Зміна прав користувача '''[[User:$1|$1]]''' $2",
-       "userrights-editusergroup": "Змінити групи користувача",
+       "userrights-editusergroup": "Змінити групи користувачів",
        "saveusergroups": "Зберегти групи користувача",
        "userrights-groupsmember": "Член груп:",
        "userrights-groupsmember-auto": "Неявний член:",
        "largefileserver": "Розмір файлу більший за максимальнодозволений.",
        "emptyfile": "Завантажений вами файл ймовірно порожній. Можливо, це сталося через помилку при введенні імені файлу. Будь-ласка, перевірте, чи справді ви бажаєте звантажити цей файл.",
        "windows-nonascii-filename": "Ця вікі не підтримує імена файлів зі спеціальними символами.",
-       "fileexists": "Файл з такою назвою вже існує.\nБудь ласка, перевірте <strong>[[:$1]]</strong>, якщо ви не впевнені, чи хочете замінити його.\n[[$1|thumb]]",
+       "fileexists": "Файл з такою назвою вже існує.\nБудь ласка, перевірте <strong>[[:$1]]</strong>, якщо {{GENDER:|ви}} не впевнені, чи хочете замінити його.\n[[$1|thumb]]",
        "filepageexists": "Сторінка опису цього файлу вже створена як <strong>[[:$1]]</strong>, але файлу з такою назвою немає. Уведений опис не з'явиться на сторінці опису зображення. Щоб додати новий опис, вам доведеться змінити його вручну. [[$1|thumb]]",
-       "fileexists-extension": "Ð\86Ñ\81нÑ\83Ñ\94 Ñ\84айл Ð·Ñ\96 Ñ\81Ñ\85ожоÑ\8e Ð½Ð°Ð·Ð²Ð¾Ñ\8e: [[$2|thumb]]\n* Ð\9dазва Ð·Ð°Ð²Ð°Ð½Ñ\82аженого Ñ\84айлÑ\83: <strong>[[:$1]]</strong>\n* Ð\9dазва Ñ\96Ñ\81нÑ\83Ñ\8eÑ\87ого Ñ\84айлÑ\83: <strong>[[:$2]]</strong>\nÐ\91Ñ\83дÑ\8cÑ\82е Ð»Ð°Ñ\81кавÑ\96, Ð²Ð¸Ð±ÐµÑ\80Ñ\96Ñ\82Ñ\8c Ñ\96нÑ\88Ñ\83 Ð½Ð°Ð·Ð²Ñ\83.",
+       "fileexists-extension": "Ð\86Ñ\81нÑ\83Ñ\94 Ñ\84айл Ð·Ñ\96 Ñ\81Ñ\85ожоÑ\8e Ð½Ð°Ð·Ð²Ð¾Ñ\8e: [[$2|thumb]]\n* Ð\9dазва Ð·Ð°Ð²Ð°Ð½Ñ\82аженого Ñ\84айлÑ\83: <strong>[[:$1]]</strong>\n* Ð\9dазва Ñ\96Ñ\81нÑ\83Ñ\8eÑ\87ого Ñ\84айлÑ\83: <strong>[[:$2]]</strong>\nÐ\9cожливо, Ð²Ð¸ Ñ\85оÑ\87еÑ\82е Ð¾Ð±Ñ\80аÑ\82и Ð½Ð°Ð·Ð²Ñ\83, Ñ\89о Ð±Ñ\83де Ð±Ñ\96лÑ\8cÑ\88е Ð²Ñ\96дÑ\80Ñ\96знÑ\8fÑ\82иÑ\81Ñ\8f?",
        "fileexists-thumbnail-yes": "Можливо, файл є зменшеною копією (мініатюрою). [[$1|thumb]]\nБудь ласка, перевірте файл <strong>[[:$1]]</strong>.\nЯкщо вказаний файл є тим самим зображенням, не варто окремо завантажувати його зменшену копію.",
        "file-thumbnail-no": "Назва файлу починається на <strong>$1</strong>.\nМожливо, це зменшена копія зображення ''(мініатюра)''.\nЯкщо у вас є це зображення в повному розмірі, завантажте його, інакше змініть назву файлу.",
        "fileexists-forbidden": "Файл з такою назвою вже існує і не може бути перезаписаний.\nЯкщо ви все одно хочете завантажити цей файл, будь ласка, поверніться назад і оберіть іншу назву.\n[[File:$1|thumb|center|$1]]",
        "filedelete-maintenance": "Вилучення та відновлення файлів відімкнене на час технічних робіт.",
        "filedelete-maintenance-title": "Не вдається видалити файл",
        "mimesearch": "Пошук по MIME",
-       "mimesearch-summary": "Ця сторінка дозволяє вибирати файли за їх MIME-типом. Формат вводу: тип_вмісту/підтип, наприклад <code>image/jpeg</code>.",
+       "mimesearch-summary": "Ця сторінка дозволяє вибирати файли за їх MIME-типом. Формат вводу: тип_вмісту/підтип або тип_вмісту/* тощо, наприклад <code>image/jpeg</code>.",
        "mimetype": "MIME-тип:",
        "download": "завантажити",
        "unwatchedpages": "Сторінки, за якими ніхто не спостерігає",
        "wantedtemplates": "Необхідні шаблони",
        "mostlinked": "Сторінки, на які найбільше посилань",
        "mostlinkedcategories": "Найбільші категорії",
-       "mostlinkedtemplates": "Ð\9dайÑ\83живанÑ\96Ñ\88Ñ\96 Ñ\88аблони",
+       "mostlinkedtemplates": "Ð\9dайÑ\87аÑ\81Ñ\82Ñ\96Ñ\88е Ð²ÐºÐ»Ñ\8eÑ\87енÑ\96 Ñ\81Ñ\82оÑ\80Ñ\96нки",
        "mostcategories": "Статті з найбільшою кількістю категорій",
        "mostimages": "Найуживаніші зображення",
        "mostinterwikis": "Сторінки з найбільшою кількістю інтервікі-посилань",
        "watchlistedit-clear-titles": "Сторінки:",
        "watchlistedit-clear-submit": "Очистити список спостереження (це безповоротньо!)",
        "watchlistedit-clear-done": "Ваш список спостереження було очищено.",
+       "watchlistedit-clear-removed": "Було видалено {{PLURAL:$1|1 запис|$1 записів|$1 записи}}:",
        "watchlistedit-too-many": "Забагато сторінок для відображення тут.",
        "watchlisttools-clear": "Очистити список спостереження",
        "watchlisttools-view": "Зміни на сторінках зі списку",
        "duplicate-defaultsort": "Увага. Ключ сортування «$2» перекриває попередній ключ сортування «$1».",
        "version": "Версія MediaWiki",
        "version-extensions": "Установлені розширення",
-       "version-skins": "Ð\9eформлення",
+       "version-skins": "Ð\92Ñ\81Ñ\82ановленÑ\96 Ñ\82еми Ð¾формлення",
        "version-specialpages": "Спеціальні сторінки",
        "version-parserhooks": "Перехоплювачі синтаксичного аналізатора",
        "version-variables": "Змінні",
        "version-hook-name": "Ім'я перехоплювача",
        "version-hook-subscribedby": "Підписаний на",
        "version-version": "($1)",
+       "version-no-ext-name": "[без назви]",
        "version-svn-revision": "(r$2)",
        "version-license": "Ліцензія MediaWik",
        "version-ext-license": "Ліцензія",
        "version-ext-colheader-name": "Розширення",
+       "version-skin-colheader-name": "Тема оформлення",
        "version-ext-colheader-version": "Версія",
        "version-ext-colheader-license": "Ліцензія",
        "version-ext-colheader-description": "Опис",
        "expand_templates_remove_nowiki": "Ігнорувати теги <nowiki> в результаті",
        "expand_templates_generate_xml": "Показати дерево аналізу XML",
        "expand_templates_generate_rawhtml": "Показати сирий HTML",
-       "expand_templates_preview": "Попередній перегляд"
+       "expand_templates_preview": "Попередній перегляд",
+       "pagelanguage": "Вибір мови сторінки",
+       "pagelang-name": "Сторінка",
+       "pagelang-language": "Мова",
+       "pagelang-use-default": "Мова за замовчуванням",
+       "pagelang-select-lang": "Оберіть мову",
+       "right-pagelang": "Змінити мову сторінки",
+       "action-pagelang": "змінити мову сторінки",
+       "log-name-pagelang": "Журнал змін мови",
+       "log-description-pagelang": "Це журнал змін мови сторінок.",
+       "logentry-pagelang-pagelang": "$1 {{GENDER:$2|змінив|змінила}} мову сторінки для $3 з $4 на $5."
 }
index ed99e48..a262641 100644 (file)
@@ -44,7 +44,7 @@
        "tog-watchdeletion": "Tự động theo dõi các trang và tập tin tôi xóa",
        "tog-minordefault": "Mặc định đánh dấu tất cả sửa đổi của tôi là sửa đổi nhỏ",
        "tog-previewontop": "Hiển thị phần xem trước nằm trên hộp sửa đổi",
-       "tog-previewonfirst": "Hiện xem trước tại lần sửa đầu tiên",
+       "tog-previewonfirst": "Hiện xem trước tại ngay khi bắt đầu sửa đổi",
        "tog-enotifwatchlistpages": "Gửi thư cho tôi khi có thay đổi tại trang hoặc tập tin tôi theo dõi",
        "tog-enotifusertalkpages": "Gửi thư cho tôi khi có thay đổi tại trang thảo luận của tôi",
        "tog-enotifminoredits": "Gửi thư cho tôi cả những thay đổi nhỏ trong trang và tập tin",
        "nextn-title": "$1 {{PLURAL:$1|kết quả|kết quả}} sau",
        "shown-title": "Hiển thị $1 {{PLURAL:$1|kết quả|kết quả}} mỗi trang",
        "viewprevnext": "Xem ($1 {{int:pipe-separator}} $2) ($3).",
-       "searchmenu-exists": "* Trang '''[[$1]]'''",
-       "searchmenu-new": "'''Tạo trang “[[:$1]]” trên wiki này!''' {{PLURAL:$2|0=|Hãy xem {{PLURAL:$2|kết quả|các kết quả}} tìm kiếm:}}",
+       "searchmenu-exists": "<strong>Có trang với tên “[[:$1]]” trên wiki này.</strong> {{PLURAL:$2|0=|Xem thêm các kết quả tìm kiếm bên dưới:}}",
+       "searchmenu-new": "'''Tạo trang “[[:$1]]” trên wiki này!''' {{PLURAL:$2|0=|Xem thêm {{PLURAL:$2|kết quả|các kết quả}} tìm kiếm:}}",
        "searchprofile-articles": "Trang nội dung",
        "searchprofile-images": "Đa phương tiện",
        "searchprofile-everything": "Tất cả",
        "enhancedrc-history": "lịch sử",
        "recentchanges": "Thay đổi gần đây",
        "recentchanges-legend": "Tùy chọn thay đổi gần đây",
-       "recentchanges-summary": "Xem các thay đổi gần đây nhất tại wiki trên trang này.",
+       "recentchanges-summary": "Xem các thay đổi gần đây nhất trên wiki này tại đây.",
        "recentchanges-noresult": "Không có thay đổi trong khoảng thời gian phù hợp với các tiêu chí này.",
        "recentchanges-feed-description": "Theo dõi các thay đổi gần đây nhất của wiki dùng nguồn cấp dữ liệu này.",
        "recentchanges-label-newpage": "Bản sửa này tạo ra trang mới",
        "expand_templates_remove_nowiki": "Bỏ qua thẻ <nowiki> trong kết quả",
        "expand_templates_generate_xml": "Xem cây phân tích XML",
        "expand_templates_generate_rawhtml": "Hiển thị HTML thô",
-       "expand_templates_preview": "Xem trước"
+       "expand_templates_preview": "Xem trước",
+       "pagelanguage": "Chọn ngôn ngữ trang",
+       "pagelang-name": "Trang",
+       "pagelang-language": "Ngôn ngữ",
+       "pagelang-use-default": "Sử dụng ngôn ngữ mặc định",
+       "pagelang-select-lang": "Chọn ngôn ngữ",
+       "right-pagelang": "Thay đổi ngôn ngữ của trang",
+       "action-pagelang": "thay đổi ngôn ngữ của trang",
+       "log-name-pagelang": "Nhật trình thay đổi ngôn ngữ",
+       "log-description-pagelang": "Nhật trình này ghi các thay đổi ngôn ngữ của các trang.",
+       "logentry-pagelang-pagelang": "$1 {{GENDER:$2}}đã đổi ngôn ngữ của trang $3 từ $4 thành $5."
 }
index a9aaf52..5778823 100644 (file)
@@ -12,7 +12,9 @@
                        "十弌",
                        "아라",
                        "Mywood",
-                       "Cwek"
+                       "Cwek",
+                       "Duolaimi",
+                       "Impersonator 1"
                ]
        },
        "tog-underline": "鏈接下橫線:",
        "viewyourtext": "你侬好望也好畀'''你侬编个'''复制到箇页:",
        "protectedinterface": "箇页为箇维基个软件提供界面文本,锁牢定防乱用。\n加改全部维基个译文,用[//translatewiki.net/ translatewiki.net],MediaWiki软件个本地化计划。",
        "editinginterface": "'''警告:''' 侬来里编写个页面是畀软件用个界面文本。箇页变化会影响各许人个界面样子。假使要畀全部维基翻译,用 [//translatewiki.net/wiki/Main_Page?setlang=zh-hans translatewiki.net],MediaWiki软件个本地化计划。",
-       "cascadeprotected": "箇只页面拨保护拉许,因为箇只页面拨下底已经标注“联锁保护”个{{PLURAL:$1|一只|多只}}被保护页面包含:\n$2",
+       "cascadeprotected": "箇只页面拨保护拉许,因为箇只页面拨下底已经标注“级联保护”个{{PLURAL:$1|一只|多只}}被保护页面包含:\n$2",
        "namespaceprotected": "侬无没编辑'''$1'''名字空间里向页面个权限。",
        "customcssprotected": "箇CSS页你呒处编,箇页有各许用户个私人设置。",
        "customjsprotected": "箇JavaScript页你呒处编,箇页有各许用户个私人设置。",
        "readonlywarning": "'''警告:数据库锁定垃许维护,侬箇歇弗好保存侬个修改。'''侬作兴希望先拿本段文字复制并保存到文本文件,等歇再修改。\n\n管理员有如下解释:$1",
        "protectedpagewarning": "'''警告:此页已经畀保护,只有拥有管理员权限个用户再好修改。'''\n最近个日志垃拉下底提供以便参考:",
        "semiprotectedpagewarning": "'''注意:''' 本页面畀锁定,仅限注册用户编辑。\n最近个日志垃拉下底提供以便参考:",
-       "cascadeprotectedwarning": "警告:本页已经畀保护,只有拥有管理员权限个用户再好修改,因为本页已畀下底眼连锁保护个{{PLURAL:$1|一只|多只}}页面所包含:",
+       "cascadeprotectedwarning": "警告:本页已经畀保护,只有拥有管理员权限个用户再好修改,因为本页已畀下底眼级联保护个{{PLURAL:$1|一只|多只}}页面所包含:",
        "titleprotectedwarning": "'''警告:本页面已畀锁定,需要[[Special:ListGroupRights|指定权限]]方可创建。'''\n最近个日志垃拉下底提供以便参考:",
        "templatesused": "箇页有{{PLURAL:$1|个模板}}:",
        "templatesusedpreview": "{{PLURAL:$1|只模板}}垃拉箇趟预览里向拨使用:",
        "prefixindex": "全部带前缀个页面",
        "shortpages": "短页面",
        "longpages": "长页面",
-       "protectedpages": "å·²保护页面",
-       "protectedtitles": "å·²保护个标题",
+       "protectedpages": "å\8f\97保护页面",
+       "protectedtitles": "å\8f\97保护个标题",
        "listusers": "用户列表",
        "listusers-creationsort": "照建個日子排",
        "newpages": "新页",
        "rollbackfailed": "恢复失败",
        "revertpage": "恢复[[Special:Contributions/$2|$2]] ([[User talk:$2|讲张]])个改动;恢复到[[User:$1|$1]]个上一版本",
        "protectlogpage": "保护日志",
-       "protectedarticle": "保护“[[$1]]”",
+       "protectedarticle": "保护“[[$1]]”",
        "modifiedarticleprotection": "“[[$1]]”个保护等级改好哉",
        "prot_1movedto2": "[[$1]]捅到[[$2]]",
        "protectcomment": "理由:",
        "protect-fallback": "需要“$1”个许可",
        "protect-level-autoconfirmed": "弗准新用戶搭還朆註冊個用戶",
        "protect-level-sysop": "只准管理員",
-       "protect-summary-cascade": "联锁",
+       "protect-summary-cascade": "级联",
        "protect-expiring": "终止于$1(UTC)",
-       "protect-cascade": "保护本页里向包含个页面(连锁保护)",
+       "protect-cascade": "保护本页里向包含个页面(级联保护)",
        "protect-cantedit": "侬呒此更改迭只页面个保护等级,因为侬呒没权限编辑渠。",
        "protect-othertime": "各許時間:",
        "protect-othertime-op": "各許時間",
index baa905b..816bf32 100644 (file)
        "searchrelated": "פארבינדן",
        "searchall": "אלץ",
        "showingresults": "ווייזן ביז {{PLURAL:$1|רעזולטאט '''איינס'''|'''$1''' רעזולטאטן}} אנגעפאנגן פון נומער #'''$2''':",
+       "showingresultsinrange": "ווײַזן אונטן ביז {{PLURAL:$1|<strong>1</strong> רעזולטאט|<strong>$1</strong> רעזולטאטן}} אין גרייך #<strong>$2</strong> ביז #<strong>$3</strong>.",
        "showingresultsheader": "{{PLURAL:$5|רעזולטאַט '''$1''' פֿון '''$3'''| רעזולטאַטן '''$1 - $2''' פֿון '''$3'''}} פֿאַר '''$4'''",
        "search-nonefound": "נישטא קיין רעזולטאטן פֿאַר דער שאלה.",
        "powersearch-legend": "ווײַטהאלטן זוכן",
        "prefs-tokenwatchlist": "טאקן",
        "prefs-diffs": "צווישנשיידן",
        "prefs-help-prefershttps": "דער פרעפערענץ וועט ארבעטן ביי אײַער נעקסטער ארײַנלאגירונג.",
+       "prefs-tabs-navigation-hint": "טיפ: איר קענט ניצן די רעכטס און לינקס פייל־קלאווישן צו נאוויגירן צווישן די צינגלעך אין דער צינגלעך־ליסטע.",
        "email-address-validity-valid": "ע-פּאָסט אַדרעס זעט אויס גילטיק",
        "email-address-validity-invalid": "לייגט אַרײַן א גילטיקן ע־פאסט אַדרעס",
        "userrights": "באַניצער רעכטן פֿאַרוואַלטערשאפט",
        "recentchanges-feed-description": "גייט נאך די לעצטע ענדערונגען צו דער וויקי אין דעם בלאט.",
        "recentchanges-label-newpage": "די רעדאַקטירונג האט באשאפֿן א נײַעם בלאַט",
        "recentchanges-label-minor": "דאָס איז אַ מינערדיקע רעדאַקטירונג",
-       "recentchanges-label-bot": " די רעדאַקטירונג האט אויסגעפירט א באט",
+       "recentchanges-label-bot": "די רעדאַקטירונג האט אויסגעפירט א באט",
        "recentchanges-label-unpatrolled": "די רעדאקטירונג איז נאך נישט נאכגעקוקט",
        "recentchanges-label-plusminus": "בלאט גרייס געענדערט מיט דער צאל בייטן",
        "recentchanges-legend-heading": "'''לעגענדע:'''",
        "uploadstash-errclear": "אוועקנעמען די טעקעס דורכגעפאלן.",
        "uploadstash-refresh": "דערפֿרישן די רשימה פון טעקעס",
        "img-auth-accessdenied": "צוטריט אָפגעזאָגט",
+       "img-auth-notindir": "געשיכטעס שטעג איז נישט אין דער קאנפיגורטער ארויפלאד־דירעקטאריע.",
        "img-auth-badtitle": "קען נישט שאפֿן א גילטיקן טיטל פֿון \"$1\"",
        "img-auth-nologinnWL": "איר זענט נישט ארײַנלאגירט און \"$1\" איז נישט אין דער ווײַסער ליסטע.",
        "img-auth-nofile": "טעקע \"$1\" עקזיסטירט נישט.",
        "double-redirect-fixer": "מתקן ווײַטערפֿירונגען",
        "brokenredirects": "צעבראָכענע ווײַטערפֿירונגען",
        "brokenredirectstext": "די פֿאלגנדע ווײַטערפֿירונגען פֿאַרבינדן צו בלעטער וואס עקזיסטירן נאך נישט:",
-       "brokenredirects-edit": "×¢× ×\93×¢רן",
+       "brokenredirects-edit": "רע×\93×\90ַק×\98×\99רן",
        "brokenredirects-delete": "אויסמעקן",
        "withoutinterwiki": "בלעטער אן שפראך פֿארבינדונגען",
        "withoutinterwiki-summary": "די פֿאלגנדע בלעטער פֿאַרבינדן נישט מיט אַנדערע שפראַך ווערסיעס",
        "creditspage": "בלאט קרעדיטס",
        "nocredits": "נישט פאראן קיין אינפארמאציע פאר דעם בלאט.",
        "spamprotectiontitle": "ספעם באשיצונג פילטער",
+       "spamprotectionmatch": "די פאלגנדער טעקסט האט געלאזט אין גאנג אונזער ספאם־פילטער: $1",
        "spambot_username": "מעדיעוויקי ספאם פוצן",
        "spam_reverting": "צוריקגעשטעלט צו דער לעצטער ווערסיע אן לינקען צו $1",
        "spam_blanking": "אלע רעוויזיעס האבן לינקען צו $1, אויסליידיקן",
        "spam_deleting": "אלע רעוויזיעס האבן לינקען צו $1, אויסמעקן",
+       "simpleantispam-label": "אנטי־ספאם קאנטראלע.\n'''נישט''' אײַנגעבן קיין אײַנגאב דא!",
        "pageinfo-title": "אינפֿאָרמאַציע פֿאַר \"$1\"",
        "pageinfo-not-current": "קען ווייזן אינפארמאציע נאר פאר דער לויפיקער רעוויזיע.",
        "pageinfo-header-basic": "גרונטלעכע אינפֿארמאַציע",
        "exif-giffilecomment": "GIF טעקע הערה",
        "exif-intellectualgenre": "ארט  איינהייט",
        "exif-subjectnewscode": "טעמע קאד",
+       "exif-scenecode": "IPTC סצענע־קאד",
+       "exif-event": "געוויזענער געשעעניש",
        "exif-organisationinimage": "אויסגעשטעלטע ארגאניזאציע",
        "exif-personinimage": "אויסגעשטעלטער מענטש",
+       "exif-originalimageheight": "בילד־הייך פארן צעשנײַדן",
+       "exif-originalimagewidth": "בילד־ברייט פארן צעשנײַדן",
        "exif-compression-1": "אומ-צאמגעקוועטשט",
        "exif-copyrighted-true": "געשיצט מיט קאפירעכט",
        "exif-copyrighted-false": "קאפירעכט סטאטוס נישט געשטעלט",
        "exif-lightsource-9": "פֿייַן וועטער",
        "exif-lightsource-10": "פאַרוואָלקנטער וועטער",
        "exif-lightsource-11": "שאָטן",
+       "exif-lightsource-255": "אנדער ליכטקוואל",
+       "exif-flash-fired-0": "קיין פלאש",
        "exif-flash-mode-3": "אויטא מאדע",
        "exif-flash-function-1": "קיין בליץ־פונקציע",
        "exif-flash-redeye-1": "רויט־אויג רעדוקציע",
        "watchlistedit-raw-done": "אייער אויפֿפאַסונג ליסטע איז געווארן דערהײַנטיקט",
        "watchlistedit-raw-added": "{{PLURAL:$1|1 טיטל איז|$1 טיטלען זענען}} געווען צוגעלייגט:",
        "watchlistedit-raw-removed": "{{PLURAL:$1|1 טיטל איז|$1 טיטלען זענען}} געווען אַראָפגענומען:",
+       "watchlistedit-clear-title": "אפגעראמט די אויפפאסן ליסטע",
        "watchlistedit-clear-legend": "ליידיקן די אויפפאסן ליסטע",
+       "watchlistedit-clear-explain": "אלע בלעטער וועט מען אראפנעמען פון אײַער אויפפאסונג־ליסטע",
        "watchlistedit-clear-titles": "טיטלען:",
        "watchlisttools-clear": "ליידיקן די אויפפאסן ליסטע",
        "watchlisttools-view": "ווייזן שייכדיגע ענדערונגען",
        "version-parser-extensiontags": "פארזער פארברייטערן טאַגן",
        "version-hook-name": "נאמען פון hook",
        "version-version": "(ווערסיע $1)",
+       "version-no-ext-name": "[קיין נאמען]",
        "version-license": "מעדיעוויקי ליצענץ",
        "version-ext-license": "ליצענץ",
        "version-ext-colheader-name": "פארברייטערונג",
+       "version-skin-colheader-name": "סקין",
        "version-ext-colheader-version": "ווערסיע",
        "version-ext-colheader-license": "ליצענץ",
        "version-ext-colheader-description": "באַשרײַבונג",
        "version-ext-colheader-credits": "שרייבער",
+       "version-license-title": "ליצענץ פאר $1",
        "version-poweredby-others": "אַנדערע",
        "version-poweredby-translators": "translatewiki.net איבערזעצער",
        "version-credits-summary": "מיר ווילן אנערקענען די פֿאלגנדע מענטשן פֿאר זייער בײַשטײַערוג צו [[Special:Version|מעדיעוויקי]].",
index 2b01033..8139cf8 100644 (file)
@@ -75,7 +75,9 @@
                        "阿pp",
                        "Hudafu",
                        "아라",
-                       "Mywood"
+                       "Mywood",
+                       "Impersonator 1",
+                       "Duolaimi"
                ]
        },
        "tog-underline": "链接下划线:",
        "viewyourtext": "您可以查看并复制<strong>您对此页面作出编辑后</strong>的源代码:",
        "protectedinterface": "该页提供此wiki软件的界面文字,它已被保护以防止恶意修改。\n如欲修改所有wiki的翻译,请到[//translatewiki.net/ translatewiki.net]上的MediaWiki本地化计划。",
        "editinginterface": "'''警告:'''您正在编辑的页面是用于提供软件的界面文字。\n改变此页将影响其他在此wiki上的用户界面外观。\n如欲修改所有wiki的翻译,请到[//translatewiki.net/ translatewiki.net]上的MediaWiki本地化计划。",
-       "cascadeprotected": "此页é\9d¢å·²è¢«ä¿\9dæ\8a¤ï¼\8cå\9b ä¸ºè¿\99个页é\9d¢è¢«ä»¥ä¸\8bå·²æ \87注â\80\9cè\81\94é\94\81ä¿\9dæ\8a¤â\80\9dç\9a\84{{PLURAL:$1|ä¸\80个|å¤\9a个}}被ä¿\9dæ\8a¤é¡µé\9d¢å\8c\85å\90«ï¼\9a\n$2",
+       "cascadeprotected": "æ\9c¬é¡µé\9d¢å·²ç»\8få\8f\97å\88°ä¿\9dæ\8a¤ï¼\8cä¸\8dè\83½ç¼\96è¾\91ï¼\8cå\9b ä¸ºå®\83被åµ\8cå\85¥äº\86以ä¸\8bå\90¯ç\94¨â\80\9c级è\81\94â\80\9dé\80\89项ç\9a\84å\8f\97ä¿\9dæ\8a¤{{PLURAL:$1|页é\9d¢}}ï¼\9a$2",
        "namespaceprotected": "您没有权限编辑'''$1'''名字空间内的页面。",
        "customcssprotected": "您没有权限编辑此CSS页面,因为它包含另一位用户的个人设置。",
        "customjsprotected": "您没有权限编辑此JavaScript页面,因为它包含另一位用户的个人设置。",
        "readonlywarning": "警告:数据库被锁定以进行维护,所以您目前将无法保存您的修改。'''您或许希望将本段文字先剪贴并保存到文本文件,并在稍后进行修改。\n\n锁定数据库的管理员有如下解释:$1",
        "protectedpagewarning": "'''警告:本页面已被保护,只有拥有管理员权限的用户可以编辑。'''下面提供最后的日志条目以供参考:",
        "semiprotectedpagewarning": "'''注意:'''本页面已被保护,只有注册用户可以编辑。下面提供最后的日志条目以供参考:",
-       "cascadeprotectedwarning": "'''警告:'''本页面已被保护,只有拥有管理员权限的用户可以编辑,因为其包含于以下受连锁保护的{{PLURAL:$1|页面}}:",
+       "cascadeprotectedwarning": "<strong>警告:</strong>本页面已经被保护,只有拥有管理员权限的用户可以编辑,因为它被嵌入了以下启用级联保护的{{PLURAL:$1|页面}}:",
        "titleprotectedwarning": "'''警告:本页面已被保护,创建本页面需要[[Special:ListGroupRights|特定权限]]。'''下面提供最后的日志条目以供参考:",
        "templatesused": "该页面使用的{{PLURAL:$1|模板}}:",
        "templatesusedpreview": "本预览使用的{{PLURAL:$1|模板}}:",
        "templatesusedsection": "该段落使用的{{PLURAL:$1|模板}}:",
-       "template-protected": "ï¼\88å·²保护)",
-       "template-semiprotected": "(半保护)",
+       "template-protected": "ï¼\88å\8f\97保护)",
+       "template-semiprotected": "ï¼\88å\8f\97å\8d\8aä¿\9dæ\8a¤ï¼\89",
        "hiddencategories": "该页面属于$1个隐藏分类:",
        "edittools": "<!-- 这里的文字将显示在编辑和上传表格下面。 -->",
        "nocreatetext": "{{SITENAME}}已经限制创建新页面功能。你可以返回编辑现有页面或[[Special:UserLogin|登录或创建账户]]。",
        "email": "电子邮件",
        "prefs-help-realname": "真实姓名是选填项目。如果你选择提供它,它将会用于贡献署名。",
        "prefs-help-email": "电子邮件地址是选填项,但是当你忘记你的密码要重置密码时,需要该信息。",
-       "prefs-help-email-others": "您也可以选择让其他用户通过您的用户页或讨论页上的链接用电子邮件联系您。其他用户联系您时您的电子邮件地址不会显示。",
+       "prefs-help-email-others": "您也可以选择让其他用户通过您的用户或讨论页面上的链接用电子邮件联系您。其他用户联系您时您的电子邮件地址不会显示。",
        "prefs-help-email-required": "电子邮件地址是必填项目。",
        "prefs-info": "基本信息",
        "prefs-i18n": "语言",
        "right-ipblock-exempt": "绕过IP封禁、自动封禁和段封禁",
        "right-proxyunbannable": "避开代理服务器的自动封禁",
        "right-unblockself": "自我解封",
-       "right-protect": "更改保护级别和编辑受连锁保护的页面",
+       "right-protect": "更改保护级别和编辑受级联保护页面",
        "right-editprotected": "编辑保护级别为“{{int:protect-level-sysop}}”的页面",
        "right-editsemiprotected": "编辑保护级别为“{{int:protect-level-autoconfirmed}}”的页面",
        "right-editinterface": "编辑用户界面",
        "license-nopreview": "(无预览可用)",
        "upload_source_url": "(有效、可以公开访问的URL)",
        "upload_source_file": "(您计算机上的一个文件)",
+       "listfiles-delete": "删除",
        "listfiles-summary": "本特殊页面展示所有上传的文件。",
        "listfiles_search_for": "按媒体名称搜索:",
        "imgfile": "文件",
        "filehist-comment": "备注",
        "imagelinks": "文件用途",
        "linkstoimage": "以下$1个页面链接至本文件:",
-       "linkstoimage-more": "超过$1个页面连接到这个文件。\n此处只列出首$1个链接到该文件的页面。\n您也可以查看[[Special:WhatLinksHere/$2|完整的列表]]。",
+       "linkstoimage-more": "超过$1个{{PLURAL:$1|页面链接至}}本文件。下面的列表只显示链接至本文件的{{PLURAL:$1|首个页面|前$1个页面}}。[[Special:WhatLinksHere/$2|完整列表]]。",
        "nolinkstoimage": "没有页面链接到本文件。",
        "morelinkstoimage": "查看连接到这个文件的[[Special:WhatLinksHere/$1|更多链接]]。",
        "linkstoimage-redirect": "$1(文件重定向)$2",
        "protectedpages": "受保护页面",
        "protectedpages-indef": "仅无限期保护",
        "protectedpages-summary": "本页面列出当前受保护的页面。要浏览受限制创建的标题列表,请参见[[{{#special:ProtectedTitles}}|{{int:protectedtitles}}]]。",
-       "protectedpages-cascade": "仅连锁保护",
+       "protectedpages-cascade": "仅级联保护",
        "protectedpages-noredirect": "隐藏重定向",
        "protectedpagesempty": "在这些参数下没有页面正在保护。",
        "protectedpages-timestamp": "时间戳",
        "protect-locked-blocked": "您不能在被封禁时更改保护级别。以下是页面'''$1'''的当前设置:",
        "protect-locked-dblock": "您不能在数据库锁定时更改保护级别。以下是页面'''$1'''的当前设置:",
        "protect-locked-access": "您的帐户没有足够的权限去更改保护级别。以下是页面'''$1'''的当前设置:",
-       "protect-cascadeon": "以下$1个页面包含本页面的同时,启动了连锁保护,因此此页面也被保护。您可以设置本页面的保护级别,但这并不会对连锁保护有所影响。",
+       "protect-cascadeon": "该页面目前受到保护,因为它被嵌入了以下启用级联保护的{{PLURAL:$1|页面}}。更改该页面的保护级别不会影响级联保护。",
        "protect-default": "允许所有用户",
        "protect-fallback": "仅允许拥有“$1”权限的用户",
        "protect-level-autoconfirmed": "仅允许自动确认用户",
        "protect-level-sysop": "仅允许管理员",
        "protect-summary-desc": "[$1=$2]($3)",
-       "protect-summary-cascade": "联锁",
+       "protect-summary-cascade": "级联",
        "protect-expiring": "终止于$1(UTC)",
        "protect-expiring-local": "终止于$1",
        "protect-expiry-indefinite": "无限期",
-       "protect-cascade": "保护本页中包含的页面(连锁保护)",
+       "protect-cascade": "保护嵌入该页面的页面(级联保护)",
        "protect-cantedit": "您无法更改这个页面的保护等级,因为您没有权限去编辑它。",
        "protect-othertime": "其它时间:",
        "protect-othertime-op": "其它时间",
        "pageinfo-redirectsto-info": "信息",
        "pageinfo-contentpage": "计为内容页面",
        "pageinfo-contentpage-yes": "是",
-       "pageinfo-protect-cascading": "保护连锁自此",
+       "pageinfo-protect-cascading": "保护级联自这里",
        "pageinfo-protect-cascading-yes": "是",
-       "pageinfo-protect-cascading-from": "保护连锁自",
+       "pageinfo-protect-cascading-from": "保护级联自",
        "pageinfo-category-info": "分类信息",
        "pageinfo-category-pages": "页面数",
        "pageinfo-category-subcats": "子分类数",
        "expand_templates_remove_nowiki": "在结果中隐藏<nowiki>标签",
        "expand_templates_generate_xml": "显示XML语法树",
        "expand_templates_generate_rawhtml": "显示原始HTML",
-       "expand_templates_preview": "预览"
+       "expand_templates_preview": "预览",
+       "pagelanguage": "页面语言选择器",
+       "pagelang-name": "页面",
+       "pagelang-language": "语言",
+       "pagelang-use-default": "使用默认语言",
+       "pagelang-select-lang": "选择语言",
+       "right-pagelang": "更改页面语言",
+       "action-pagelang": "更改页面语言",
+       "log-name-pagelang": "更改语言日志",
+       "log-description-pagelang": "这是页面语言更改的日志。",
+       "logentry-pagelang-pagelang": "$1{{GENDER:$2|更改}}$3的页面语言:从$4改为$5。"
 }
index 3e2fc18..2dbb891 100644 (file)
@@ -53,7 +53,9 @@
                        "아라",
                        "Vincent Liu",
                        "Mywood",
-                       "Cwek"
+                       "Cwek",
+                       "Impersonator 1",
+                       "LNDDYL"
                ]
        },
        "tog-underline": "連結底線:",
@@ -73,9 +75,9 @@
        "tog-minordefault": "預設標記所有的編輯為小修訂",
        "tog-previewontop": "顯示預覽於編輯框上方",
        "tog-previewonfirst": "第一次編輯時顯示預覽",
-       "tog-enotifwatchlistpages": "當我的監視清單中的頁面或檔案有變更時,送電子郵件通知我",
-       "tog-enotifusertalkpages": "當我的對話頁面有變更時,送電子郵件通知我",
-       "tog-enotifminoredits": "當頁面與檔案有小修訂時,送電子郵件通知我",
+       "tog-enotifwatchlistpages": "當我的監視清單中的頁面或檔案有變更時,送電子郵件通知我",
+       "tog-enotifusertalkpages": "當我的對話頁面有變更時,送電子郵件通知我",
+       "tog-enotifminoredits": "當頁面與檔案有小修訂時,送電子郵件通知我",
        "tog-enotifrevealaddr": "在通知信件中顯示我的電子郵件位址",
        "tog-shownumberswatching": "顯示正在監視的使用者數",
        "tog-oldsig": "現有簽名:",
@@ -88,7 +90,7 @@
        "tog-watchlisthideliu": "隱藏監視清單中已登入使用者的編輯",
        "tog-watchlisthideanons": "隱藏監視清單中匿名使用者的編輯",
        "tog-watchlisthidepatrolled": "隱藏監視清單中已巡查的編輯",
-       "tog-ccmeonemails": "送郵件給他人時,也送一份副本到我的電子郵件信箱",
+       "tog-ccmeonemails": "送郵件給他人時,也送一份副本到我的電子郵件信箱",
        "tog-diffonly": "比對版本差異時下面不顯示頁面內容",
        "tog-showhiddencats": "顯示隱藏分類",
        "tog-norollbackdiff": "執行還原後略過差異比對",
        "categorypage": "檢視分類頁面",
        "viewtalkpage": "檢視討論頁面",
        "otherlanguages": "其他語言",
-       "redirectedfrom": "(重定向自$1)",
-       "redirectpagesub": "重向頁面",
+       "redirectedfrom": "(已重新導向自 $1)",
+       "redirectpagesub": "重新導向頁面",
        "lastmodifiedat": "此頁面最後修訂於 $1 $2。",
        "viewcount": "此頁面已被檢視過 $1 次。",
        "protectedpage": "受保護頁面",
        "mainpage-description": "首頁",
        "policy-url": "Project:方針",
        "portal": "社群主頁",
-       "portal-url": "Project:社專頁",
+       "portal-url": "Project:社專頁",
        "privacy": "隱私政策",
        "privacypage": "Project:Privacy policy",
        "badaccess": "權限錯誤",
        "createacct-emailoptional": "電子郵件位址 (選填)",
        "createacct-email-ph": "輸入您的電子郵件位址",
        "createacct-another-email-ph": "輸入電子郵件位址",
-       "createaccountmail": "使用臨時的隨機密碼,並將它發送到指定的電子郵件地址",
+       "createaccountmail": "使用臨時的隨機密碼,並將它到指定的電子郵件地址",
        "createacct-realname": "真實姓名 (選填)",
        "createaccountreason": "原因:",
        "createacct-reason": "原因",
        "createacct-captcha": "安全驗證",
        "createacct-imgcaptcha-ph": "輸入您在上方看到的文字",
        "createacct-submit": "建立您的帳號",
-       "createacct-another-submit": "建立另一帳號",
+       "createacct-another-submit": "建ç«\8bå\8f¦ä¸\80å\80\8b帳è\99\9f",
        "createacct-benefit-heading": "{{SITENAME}} 是由像您一樣貢獻的人所建立的。",
        "createacct-benefit-body1": " {{PLURAL:$1|次編輯}}",
        "createacct-benefit-body2": " $1 頁",
        "mailmypassword": "重設密碼",
        "passwordremindertitle": "{{SITENAME}} 的新臨時密碼",
        "passwordremindertext": "不明人士 (可能是您自己,來自 IP 位址 $1) 要求重設在 {{SITENAME}} ($4) 的密碼。\n給使用者 \"$2\" 的臨時密碼設為 \"$3\"。\n如果這個動作是您做的,您需要立即登入並設定一個新的密碼,\n您的臨時密碼將於{{PLURAL:$5|一|$5}}天內過期。\n\n如果不是您要求重設密碼,或您已想起密碼,並不準備修改,\n您可以忽略此訊息並且繼續使用您原本的密碼。",
-       "noemail": "使用者 \"$1\" 未登記電子郵件址。",
-       "noemailcreate": "您需要提供一個有效的電子郵件址。",
-       "passwordsent": "使用者 \"$1\" 的新密碼已寄至當出登記的電子郵件地址,\n請稍後收到信件後再登入。",
+       "noemail": "使用者 \"$1\" 未登記電子郵件址。",
+       "noemailcreate": "您需要提供一個有效的電子郵件址。",
+       "passwordsent": "使用者 \"$1\" 的新密碼已寄至當出登記的電子郵件地址,\n請稍後收到信件後再登入。",
        "blocked-mailpassword": "您的 IP 位址已被封鎖不允許編輯,密碼復原的功能也同樣被禁止使用以防止被濫用。",
-       "eauthentsent": "以發送一封確認信到您所設定的電子郵件地址。\n在未收到其它電子郵件前,您必須先依照信件中的指示,確認這個帳號確實是您本人。",
-       "throttled-mailpassword": "密碼重設的電子郵件已經在最近 $1 小時內送出。\n為防止濫用,$1 小時內只能發送一次密碼重設信件。",
-       "mailerror": "發送郵件錯誤:$1",
-       "acct_creation_throttle_hit": "使用您目前的 IP 位址的參觀者在最近一天建立了 {{PLURAL:$1|1 個帳號|$1 個帳號}},已超出系統允許的上限。\n因此,目前無法讓使用此 IP 位址的參觀者建立帳號。",
+       "eauthentsent": "已寄出一封確認信到您所設定的電子郵件位址。\n在未收到其它電子郵件前,您必須先依照信件中的指示,確認這個帳號確實是您本人。",
+       "throttled-mailpassword": "密碼重設的電子郵件已經在最近 $1 小時內寄出。\n為防止濫用,$1 小時內只能寄出一次密碼重設信件。",
+       "mailerror": "寄出電子郵件錯誤:$1",
+       "acct_creation_throttle_hit": "使用您目前的 IP 位址的訪客在最近一天建立了 {{PLURAL:$1|1 個帳號|$1 個帳號}},已超出系統允許的上限。\n因此,目前無法讓使用此 IP 位址的訪客建立帳號。",
        "emailauthenticated": "您的電子郵件位址已確認於 $2 的 $3。",
-       "emailnotauthenticated": "您的電子郵件地址尚未確認,\n尚不會發送以下功能的電子郵件給您。",
+       "emailnotauthenticated": "您的電子郵件地址尚未確認,\n尚不會寄出以下功能的電子郵件給您。",
        "noemailprefs": "在您的偏好設定中設定電子郵件地址,讓您可以使用這些功能。",
        "emailconfirmlink": "確認您的電子郵件位址",
        "invalidemailaddress": "無法接受格式不正確的電子郵件地址,\n請輸入正確的電子郵件地址格式或略過填寫該欄位。",
        "cannotchangeemail": "此 Wiki 不允許更改帳號的電子郵件位址。",
-       "emaildisabled": "此網站不能發送電子郵件。",
+       "emaildisabled": "此網站不能寄出電子郵件。",
        "accountcreated": "已建立帳號",
        "accountcreatedtext": "使用者帳號 [[{{ns:User}}:$1|$1]] ([[{{ns:User talk}}:$1|對話]]) 已建立。",
        "createaccount-title": "{{SITENAME}} 的帳號建立",
        "pt-createaccount": "建立帳號",
        "pt-userlogout": "登出",
        "php-mail-error-unknown": "PHP 的 mail() 函數發生不明錯誤。",
-       "user-mail-no-addy": "試圖發送沒有電子郵件地址的電子郵件。",
-       "user-mail-no-body": "試圖發送一個空的或異常簡短的電子郵件。",
+       "user-mail-no-addy": "試圖寄出沒有電子郵件位址的信件。",
+       "user-mail-no-body": "試圖寄出一個空的或異常簡短的電子郵件。",
        "changepassword": "變更密碼",
        "resetpass_announce": "要完成登入,您必須設定一個新密碼。",
        "resetpass_text": "<!-- 在此處加入文字 -->",
        "resetpass-submit-cancel": "取消",
        "resetpass-wrong-oldpass": "無效的臨時或現有密碼。\n您可能早已成功地更改了您的密碼,或者已經請求一個新的臨時密碼。",
        "resetpass-recycled": "請重設您的密碼為一個與目前不同的密碼。",
-       "resetpass-temp-emailed": "您使用臨時電子郵件送的代碼登入。\n要完成登入,您必須在這裡設定一個新密碼:",
+       "resetpass-temp-emailed": "您使用臨時電子郵件送的代碼登入。\n要完成登入,您必須在這裡設定一個新密碼:",
        "resetpass-temp-password": "臨時密碼:",
        "resetpass-abort-generic": "擴充套件已中止了變更密碼的操作。",
        "resetpass-expired": "您的密碼已過期。請設定一個新的密碼以登入。",
        "passwordreset-username": "使用者名稱:",
        "passwordreset-domain": "網域名稱:",
        "passwordreset-capture": "檢視電子郵件內容?",
-       "passwordreset-capture-help": "若您勾選此核選方塊,電子郵件 (包含臨時密碼) 將直接顯示,並發送給使用者。",
+       "passwordreset-capture-help": "若您勾選此核選方塊,電子郵件 (包含臨時密碼) 將直接顯示,並給使用者。",
        "passwordreset-email": "電子郵件位址:",
        "passwordreset-emailtitle": "於 {{SITENAME}} 的帳號詳細資訊",
-       "passwordreset-emailtext-ip": "不明人士 (可能是您自己,來自 IP 位址 $1) 要求重設在 {{SITENAME}} ($4) 的密碼,下列是與此電子郵件址有關的使用者{{PLURAL:$3|帳號}}:\n\n$2\n\n{{PLURAL:$3|這個臨時密碼|這些臨時密碼}}將會在{{PLURAL:$5|一天|$5 天}}內到期,\n您應立即登入並更改新的密碼。如果不是您要求重設密碼,或您已想起密碼,並不準備修改,\n您可以忽略此訊息並且繼續使用您原本的密碼。",
-       "passwordreset-emailtext-user": "使用者 $1 要求重設在 {{SITENAME}} ($4) 的密碼,下列是與此電子郵件址有關的使用者{{PLURAL:$3|帳號}}:\n\n$2\n\n{{PLURAL:$3|這個臨時密碼|這些臨時密碼}}將會在{{PLURAL:$5|一天|$5 天}}內到期,\n您應立即登入並更改新的密碼。如果不是您要求重設密碼,或您已想起密碼,並不準備修改,\n您可以忽略此訊息並且繼續使用您原本的密碼。",
+       "passwordreset-emailtext-ip": "不明人士 (可能是您自己,來自 IP 位址 $1) 要求重設在 {{SITENAME}} ($4) 的密碼,下列是與此電子郵件址有關的使用者{{PLURAL:$3|帳號}}:\n\n$2\n\n{{PLURAL:$3|這個臨時密碼|這些臨時密碼}}將會在{{PLURAL:$5|一天|$5 天}}內到期,\n您應立即登入並更改新的密碼。如果不是您要求重設密碼,或您已想起密碼,並不準備修改,\n您可以忽略此訊息並且繼續使用您原本的密碼。",
+       "passwordreset-emailtext-user": "使用者 $1 要求重設在 {{SITENAME}} ($4) 的密碼,下列是與此電子郵件址有關的使用者{{PLURAL:$3|帳號}}:\n\n$2\n\n{{PLURAL:$3|這個臨時密碼|這些臨時密碼}}將會在{{PLURAL:$5|一天|$5 天}}內到期,\n您應立即登入並更改新的密碼。如果不是您要求重設密碼,或您已想起密碼,並不準備修改,\n您可以忽略此訊息並且繼續使用您原本的密碼。",
        "passwordreset-emailelement": "使用者名稱:$1\n臨時密碼:$2",
-       "passwordreset-emailsent": "已發送重設密碼的電子郵件。",
-       "passwordreset-emailsent-capture": "已發送重設密碼的電子郵件,並在下面顯示。",
-       "passwordreset-emailerror-capture": "產生的重設密碼的電子郵件如下所示,但送給{{GENDER:$2|使用者}}失敗:$1",
+       "passwordreset-emailsent": "已寄出重設密碼的電子郵件。",
+       "passwordreset-emailsent-capture": "已寄出重設密碼的電子郵件,並在下面顯示。",
+       "passwordreset-emailerror-capture": "產生的重設密碼的電子郵件如下所示,但送給{{GENDER:$2|使用者}}失敗:$1",
        "changeemail": "變更電子郵件位址",
        "changeemail-header": "變更帳號的電子郵件位址",
-       "changeemail-text": "填寫表格以修改您的電子郵件址。您需要輸入密碼以確認此次變更。",
-       "changeemail-no-info": "您必須登入方可直接訪問此頁面。",
+       "changeemail-text": "填寫表格以修改您的電子郵件址。您需要輸入密碼以確認此次變更。",
+       "changeemail-no-info": "您必須登入方可直接存取此頁面。",
        "changeemail-oldemail": "目前的電子郵件位址:",
        "changeemail-newemail": "新的電子郵件位址:",
        "changeemail-none": "(無)",
        "summary-preview": "摘要預覽:",
        "subject-preview": "主旨/標題預覽:",
        "blockedtitle": "使用者已被封鎖",
-       "blockedtext": "<strong>您的使用者名稱或 IP 位址以被封鎖。</strong>\n\n您被 $1 封鎖,\n原因爲 <em>$2</em>。\n\n* 封鎖開始時間:$8\n* 封鎖結束時間:$6\n* 相關封鎖對象:$7\n\n您可以聯繫 $1 或其他的 [[{{MediaWiki:Grouppage-sysop}}|管理員]] 討論封鎖的相關問題。\n若您已在 [[Special:Preferences|偏好設定]] 中設定了一個有效的電子郵件地址,且尚未被封鎖郵件功能,則您可透過 \"送電子郵件給這位使用者\" 的功能來聯絡相關管理員。\n您目刖的 IP 位址是 $3,此次封鎖的 ID 爲 #$5。\n請您在詢問時附註以上詳細訊息。",
-       "autoblockedtext": "因先前的另一位使用者被 $1 封鎖,您的 IP 位址已被自動封鎖。\n原因是:\n\n:<em>$2</em>\n\n* 封鎖開始時間:$8\n* 封鎖結束時間:$6\n* 相關封鎖對象:$7\n\n您可以聯繫 $1 或其他的 [[{{MediaWiki:Grouppage-sysop}}|管理員]] 討論封鎖的相關問題。\n若您已在 [[Special:Preferences|偏好設定]] 中設定了一個有效的電子郵件地址,且尚未被封鎖郵件功能,則您可透過 \"送電子郵件給這位使用者\" 的功能來聯絡相關管理員。\n您目刖的 IP 位址是 $3,此次封鎖的 ID 爲 #$5。\n請您在詢問時附註以上詳細訊息。",
+       "blockedtext": "<strong>您的使用者名稱或 IP 位址以被封鎖。</strong>\n\n您被 $1 封鎖,\n原因爲 <em>$2</em>。\n\n* 封鎖開始時間:$8\n* 封鎖結束時間:$6\n* 相關封鎖對象:$7\n\n您可以聯繫 $1 或其他的 [[{{MediaWiki:Grouppage-sysop}}|管理員]] 討論封鎖的相關問題。\n若您已在 [[Special:Preferences|偏好設定]] 中設定了一個有效的電子郵件地址,且尚未被封鎖郵件功能,則您可透過 \"送電子郵件給這位使用者\" 的功能來聯絡相關管理員。\n您目刖的 IP 位址是 $3,此次封鎖的 ID 爲 #$5。\n請您在詢問時附註以上詳細訊息。",
+       "autoblockedtext": "因先前的另一位使用者被 $1 封鎖,您的 IP 位址已被自動封鎖。\n原因是:\n\n:<em>$2</em>\n\n* 封鎖開始時間:$8\n* 封鎖結束時間:$6\n* 相關封鎖對象:$7\n\n您可以聯繫 $1 或其他的 [[{{MediaWiki:Grouppage-sysop}}|管理員]] 討論封鎖的相關問題。\n若您已在 [[Special:Preferences|偏好設定]] 中設定了一個有效的電子郵件地址,且尚未被封鎖郵件功能,則您可透過 \"送電子郵件給這位使用者\" 的功能來聯絡相關管理員。\n您目刖的 IP 位址是 $3,此次封鎖的 ID 爲 #$5。\n請您在詢問時附註以上詳細訊息。",
        "blockednoreason": "未說明原因",
        "whitelistedittext": "請先 $1 才可編輯頁面。",
        "confirmedittext": "在編輯此頁之前您必須確認您的電子郵件位址。\n請透過 [[Special:Preferences|偏好設定]] 設定並驗證您的電子郵件位址。",
        "nosuchsectiontitle": "找不到章節",
-       "nosuchsectiontext": "æ\82¨å\98\97試編輯ç\9a\84ç« ç¯\80並ä¸\8då­\98å\9c¨ã\80\82\nå\8f¯è\83½å\9c¨æ\82¨æ\9f¥ç\9c\8b頁面時已經移動或刪除。",
+       "nosuchsectiontext": "æ\82¨å\98\97試編輯ç\9a\84ç« ç¯\80並ä¸\8då­\98å\9c¨ã\80\82\nå\8f¯è\83½å\9c¨æ\82¨æª¢è¦\96頁面時已經移動或刪除。",
        "loginreqtitle": "需要登入",
        "loginreqlink": "登入",
        "loginreqpagetext": "您必須 $1 才能檢視其它頁面。",
        "accmailtext": "[[User talk:$1|$1]] 的隨機密碼已經寄送至 $2,可登入後至 <em>[[Special:ChangePassword|變更密碼]] 頁面更改</em>。",
        "newarticle": "(新)",
        "newarticletext": "您正連結至一頁不存在頁面。\n要建立該頁面,請在下方的編輯框中輸入內容 (詳情請參考 [$1 説明頁面])。\n如果您是不小心來到此頁面,請點選瀏覽器的 <strong>返回</strong> 按鈕。",
-       "anontalkpagetext": "----\n<em>此討論頁面是給尚未建立帳號的匿名使用者使用</em>\n因此我們必須使用 IP 位址來辨識身份,但相同的 IP 位可能由許多不同的使用者所共用。\n如果您是匿名使用者並且覺得評論的內容與您無關,請 [[Special:UserLogin/signup|建立新帳號]] 或 [[Special:UserLogin|登入]] 避免與其他匿名使用者混淆。",
+       "anontalkpagetext": "----\n<em>此討論頁面是給尚未建立帳號的匿名使用者使用</em>\n因此我們必須使用 IP 位址來辨識身份,但相同的 IP 位可能由許多不同的使用者所共用。\n如果您是匿名使用者並且覺得評論的內容與您無關,請 [[Special:UserLogin/signup|建立新帳號]] 或 [[Special:UserLogin|登入]] 避免與其他匿名使用者混淆。",
        "noarticletext": "此頁面目前沒有內容,\n您可以在其它頁面中 [[Special:Search/{{PAGENAME}}|搜尋此頁面標題]],\n<span class=\"plainlinks\">[{{fullurl:{{#Special:Log}}|page={{FULLPAGENAMEE}}}} 搜尋相關日誌],\n或 [{{fullurl:{{FULLPAGENAME}}|action=edit}} 編輯此頁]</span>。",
        "noarticletext-nopermission": "此頁面目前沒有內容,\n您可以在其它頁面中 [[Special:Search/{{PAGENAME}}|搜尋此頁面標題]],或 <span class=\"plainlinks\">[{{fullurl:{{#Special:Log}}|page={{FULLPAGENAMEE}}}} 搜尋相關日誌]</span>,但您沒有權限建立此頁面。",
        "missing-revision": "頁面名稱 \"{{FULLPAGENAME}}\" 的 #$1 修訂版本不存在。\n\n通常是因連結到過期的歷史頁面,該頁面已被刪除。\n詳情請參考 [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} 刪除日誌]。",
        "session_fail_preview": "<strong>很抱歉!由於連線階段的資料遺失,我們無法處理您的編輯動作。</strong>\n請再試一次。\n如果仍然失敗,請 [[Special:UserLogout|登出]] 後重新登入。",
        "session_fail_preview_html": "<strong>很抱歉!由於連線階段的資料遺失,我們無法處理您的編輯動作。</strong>\n\n<em>由於 {{SITENAME}} 開啟了原始 HTML 模式,將不會顯示預覽畫面以避免 JavaScript 攻擊。</em>\n\n<strong>若這是符合規範的編輯動作,請再試一次。</strong>\n如果仍然有問題,請 [[Special:UserLogout|登出]] 後再重新登入一次。",
        "token_suffix_mismatch": "<strong>您使用的瀏覽器刪除了編輯資訊中的特殊符號,已拒絕此編輯動作。</strong>\n為了避免破壞頁面內容,已拒絕此編輯動作,\n這通常是因為您使用了有問題的匿名網頁代理伺服器。",
-       "edit_form_incomplete": "<strong>部份編輯的內容未送至伺服器,請檢查您的編輯內容是否完整並再試一次。</strong>",
+       "edit_form_incomplete": "<strong>部份編輯的內容未送至伺服器,請檢查您的編輯內容是否完整並再試一次。</strong>",
        "editing": "正在編輯 $1",
        "creating": "正在建立 $1",
        "editingsection": "正在編輯 $1 (章節)",
        "explainconflict": "在您開始編輯之後已有其他人儲存了此頁面。\n上方的文字框內顯示了目前頁面中的文字內容,\n您所變更的文字內容顯示在下方文字框中。\n您須要將您所變更的文字內容合併到已儲存的文字內容當中。\n若您直接點選 \"{{int:savearticle}}\" <strong>只有</strong> 上方文字框中的內容會被儲存。",
        "yourtext": "您的文字",
        "storedversion": "已儲存修訂",
-       "nonunicodebrowser": "<strong>警告:您的瀏覽器不相容 Unicode。</strong>\n暫時解決的方式是先在您可安全編輯頁面的地方編輯:非 ASCII 字元在編輯框中會以 16 進位編碼顯示。",
+       "nonunicodebrowser": "<strong>警告:您的瀏覽器與 Unicode 不相容。</strong>\n暫時解決的方式是先在您可安全編輯頁面的地方編輯:非 ASCII 字元在編輯框中會以 16 進位編碼顯示。",
        "editingold": "<strong>警告:您目前正編輯頁面的舊修訂版本。</strong>\n若您儲存,在此修訂之後變更的任何內容將會遺失。",
        "yourdiff": "差異",
        "copyrightwarning": "請注意,所有於 {{SITENAME}} 所做的貢獻會依據 $2 授權條款發佈 (詳情請見 $1)。\n若您不希望您的著作被任意修改與散佈,請勿在此發表文章。<br />\n您同時向我們保証在此的著作內容是您自行撰寫,或是取自不受版權保護的公開領域或自由資源。\n<strong>請勿在未經授權的情況下發表文章!</strong>",
        "search-result-size": "$1 ($2 個字)",
        "search-result-category-size": "$1 位成員 ($2 個子分類,$3 個檔案)",
        "search-result-score": "相關度:$1%",
-       "search-redirect": "(重定向自 $1)",
+       "search-redirect": "(重新導向 $1)",
        "search-section": "(章節 $1)",
        "search-file-match": "(符合檔案內容)",
        "search-suggest": "您指的是不是:$1",
        "right-move-rootuserpages": "移動根使用者頁面",
        "right-move-categorypages": "移動分類頁面",
        "right-movefile": "移動檔案",
-       "right-suppressredirect": "移動頁面時不在原頁面建立重定向",
+       "right-suppressredirect": "移動頁面時不在原頁面位置建立重新導向頁面",
        "right-upload": "上傳檔案",
        "right-reupload": "覆蓋現有的檔案",
        "right-reupload-own": "覆蓋自己上傳的檔案",
        "right-suppressrevision": "複查與還原由管理員隱藏的修訂",
        "right-suppressionlog": "檢視非公開日誌",
        "right-block": "封鎖其他使用者的編輯權限",
-       "right-blockemail": "封鎖使用者送電子郵件的權限",
+       "right-blockemail": "封鎖使用者送電子郵件的權限",
        "right-hideuser": "封鎖使用者名稱,避免公開顯示",
        "right-ipblock-exempt": "略過 IP 封鎖、自動封鎖及範圍封鎖檢查",
        "right-proxyunbannable": "略過 Proxy 自動封鎖檢查",
        "right-userrights-interwiki": "編輯使用者在其它 Wiki 上的權限",
        "right-siteadmin": "鎖定和解除鎖定資料庫",
        "right-override-export-depth": "匯出頁面包含連結內容,深度上限為 5 層",
-       "right-sendemail": "送電子郵件給其他使用者",
+       "right-sendemail": "送電子郵件給其他使用者",
        "right-passwordreset": "檢視重設密碼電子郵件",
        "newuserlogpage": "建立使用者日誌",
        "newuserlogpagetext": "此為建立使用者的日誌。",
        "action-userrights": "編輯所有使用者的權限",
        "action-userrights-interwiki": "編輯在其它 Wiki 上的使用者權限",
        "action-siteadmin": "鎖定和解除鎖定資料庫",
-       "action-sendemail": "送電子郵件",
+       "action-sendemail": "送電子郵件",
        "action-editmywatchlist": "編輯您的監視清單",
-       "action-viewmywatchlist": "æ\9f¥ç\9c\8b您的監視清單",
+       "action-viewmywatchlist": "檢è¦\96您的監視清單",
        "action-viewmyprivateinfo": "查看您的個人資料",
        "action-editmyprivateinfo": "編輯您的個人資料",
        "nchanges": "$1 次變更",
        "upload-file-error-text": "嘗試在伺服器上建立臨時檔案時發生內部錯誤。\n請連絡 [[Special:ListUsers/sysop|管理員]]。",
        "upload-misc-error": "不明的上傳錯誤",
        "upload-misc-error-text": "上傳時發生不明錯誤。\n請檢查您的 URL 是否有效且可存取,然後再重試一次。\n如果仍有問題,請聯絡 [[Special:ListUsers/sysop|管理員]]。",
-       "upload-too-many-redirects": "URL 中包含太多重定向",
+       "upload-too-many-redirects": "該 URL 重新導向至太多其他位址",
        "upload-http-error": "發生 HTTP 錯誤:$1",
        "upload-copy-upload-invalid-domain": "此網域不允許複製上傳的檔案。",
        "backend-fail-stream": "無法傳輸檔案 \"$1\"。",
        "linkstoimage-more": "超過$1個頁面連接到這個檔案。\n此處只列出首$1個連接到此檔案的頁面。\n您也可以查看[[Special:WhatLinksHere/$2|完整的清單]]。",
        "nolinkstoimage": "沒有頁面連接到本檔案。",
        "morelinkstoimage": "檢視連接到這個檔案的[[Special:WhatLinksHere/$1|更多連結]]。",
-       "linkstoimage-redirect": "$1(檔案重定向)$2",
+       "linkstoimage-redirect": "$1 (檔案重新導向) $2",
        "duplicatesoffile": "以下 $1 個檔案與此檔案重覆 ([[Special:FileDuplicateSearch/$2|了解詳細資訊]]):",
        "sharedupload": "此檔案來自 $1 且可能被其他專案所使用。",
        "sharedupload-desc-there": "此檔案來自 $1 且可能被其他專案所使用。\n請參考 [$2 檔案描述頁面] 了解進一步資訊。",
        "mimetype": "MIME 類型:",
        "download": "下載",
        "unwatchedpages": "未監視的頁面",
-       "listredirects": "重向頁面清單",
+       "listredirects": "重新導向頁面清單",
        "listduplicatedfiles": "重複檔案列表",
        "listduplicatedfiles-summary": "以下列表中某檔案之最新版本與其他檔案之最新版本重複。進包含本地檔案",
        "listduplicatedfiles-entry": "[[:File:$1|$1]] 有[[$3|其他 $2 個重複檔案]]。",
        "randomincategory-nopages": "[[:Category:$1]]中沒有頁面。",
        "randomincategory-selectcategory": "從分類中獲取隨機頁面:$1 $2",
        "randomincategory-selectcategory-submit": "執行",
-       "randomredirect": "隨機重向",
-       "randomredirect-nopages": "在命名空間\"$1\"中沒有任何重定向頁面。",
+       "randomredirect": "隨機重新導向",
+       "randomredirect-nopages": "在命名空間 \"$1\" 中沒有任何重新導向頁面。",
        "statistics": "統計",
        "statistics-header-pages": "頁面統計",
        "statistics-header-edits": "編輯統計",
        "statistics-header-hooks": "其它統計",
        "statistics-articles": "內容頁面",
        "statistics-pages": "頁面",
-       "statistics-pages-desc": "在 wiki 上所有的頁面,包括對話頁面、重定向頁面等。",
+       "statistics-pages-desc": "在 Wiki 上所有的頁面,包括對話頁面、重新導向頁面等。",
        "statistics-files": "已經上傳的檔案",
        "statistics-edits": "自 {{SITENAME}} 成立以來的頁面編輯數",
        "statistics-edits-average": "每頁平均編輯數",
        "pageswithprop-submit": "執行",
        "pageswithprop-prophidden-long": "已隱藏過長的屬性值 ($1)",
        "pageswithprop-prophidden-binary": "已隱藏二進位屬性值 ($1)",
-       "doubleredirects": "雙重重定向",
-       "doubleredirectstext": "這一頁列出所有重定向頁面重定向到另一個重定向頁的頁面。每一行都包含到第一和第二個重定向頁面的連結,以及第二個重定向頁面的目標,通常顯示的都會是\"真正\"的目標頁面,也就是第一個重定向頁面應該指向的頁面。\n<del>已劃去</del>的為已經解決之項目。",
-       "double-redirect-fixed-move": "[[$1]] 已完成移動。\n此頁面已自動更新並重向至 [[$2]]。",
-       "double-redirect-fixed-maintenance": "作為維護工作自動修復於[[$1]]至[[$2]]之雙重重定向。",
-       "double-redirect-fixer": "重向修正者",
-       "brokenredirects": "損壞的重定向頁面",
-       "brokenredirectstext": "以下的重定向頁面均指向不存在的頁面:",
+       "doubleredirects": "雙重的重新導向",
+       "doubleredirectstext": "此頁列出所有重新導向頁面連結到另一個重新導向頁面的頁面清單。每一列都包含第一次和第二次重新導向頁面的連結,以及第二次重新導向之後的目標,第二次重新導向之後的目標通常是 \"實際\" 的目標頁面,也是第一個重新導向頁面應該指向的頁面。\n<del>刪節線</del> 代表該項目的問題已經解決。",
+       "double-redirect-fixed-move": "[[$1]] 已完成移動。\n此頁面已自動更新並重新導向至 [[$2]]。",
+       "double-redirect-fixed-maintenance": "在維護作業時自動修正雙重的重新導向自 [[$1]] 至 [[$2]]。",
+       "double-redirect-fixer": "重新導向修正者",
+       "brokenredirects": "損壞的重新導向",
+       "brokenredirectstext": "以下的重新導向頁面連結的頁面不存在:",
        "brokenredirects-edit": "編輯",
        "brokenredirects-delete": "刪除",
        "withoutinterwiki": "未有語言連結的頁面",
        "protectedpages-indef": "只顯示無限期的保護頁面",
        "protectedpages-summary": "此頁面列出目前受保護的頁面。 欲查詢受保護標題清單,請參考 [[{{#special:ProtectedTitles}}|{{int:protectedtitles}}]]。",
        "protectedpages-cascade": "只顯示連鎖的保護頁面",
-       "protectedpages-noredirect": "隱藏重向頁面",
+       "protectedpages-noredirect": "隱藏重新導向頁面",
        "protectedpagesempty": "在這些參數下沒有頁面正在保護。",
        "protectedpages-timestamp": "日期時間",
        "protectedpages-page": "頁面",
        "allpagesprefix": "顯示以此為字首頁面:",
        "allpagesbadtitle": "指定的頁面標題無效、包含內部語言或內部 Wiki 的字首。\n它可能包含一個或多個的不能用於標題的字元。",
        "allpages-bad-ns": "{{SITENAME}} 沒有 \"$1\" 命名空間。",
-       "allpages-hide-redirects": "隱藏重向頁面",
+       "allpages-hide-redirects": "隱藏重新導向頁面",
        "cachedspecial-viewing-cached-ttl": "你正在瀏覽本頁的緩存版本,至多可能存在$1的延遲。",
        "cachedspecial-viewing-cached-ts": "您正在閱讀此頁的緩存版本,這可能不是完整的版本。",
        "cachedspecial-refresh-now": "查看最新。",
        "linksearch-pat": "搜尋網址:",
        "linksearch-ns": "命名空間:",
        "linksearch-ok": "搜尋",
-       "linksearch-text": "可使用通配符,如“*.wikipedia.org”。至少需要一個頂級域名,例如“*.org”。<br />\n支持的{{PLURAL:$2|協議}}:<code>$1</code>(若沒有指定協議,預設為http://)。",
+       "linksearch-text": "可使用萬用字元如 \"*.wikipedia.org\"。\n萬用字元必須使用在最上層網域,例如 \"*.org\".<br />\n支援的{{PLURAL:$2|通訊協定|通訊協定}}有:<code>$1</code> (若未指定則預設使用 http:// 通訊協定)。",
        "linksearch-line": "$1 連自 $2",
        "linksearch-error": "萬用字元僅可在主機名稱的開頭使用。",
        "listusersfrom": "顯示使用者開始自:",
        "listgrouprights-removegroup": "移除的{{PLURAL:$2|一個|多個}}群組: $1",
        "listgrouprights-addgroup-all": "加入所有群組",
        "listgrouprights-removegroup-all": "移除所有群組",
-       "listgrouprights-addgroup-self": "在自己的賬戶中加入的{{PLURAL:$2|一個|多個}}群組: $1",
-       "listgrouprights-removegroup-self": "在自己的賬戶中移除的{{PLURAL:$2|一個|多個}}群組: $1",
-       "listgrouprights-addgroup-self-all": "在自己的賬戶中加入所有群組",
-       "listgrouprights-removegroup-self-all": "在自己的賬戶中移除所有群組",
+       "listgrouprights-addgroup-self": "在自己的帳號中加入的{{PLURAL:$2|一個|多個}}群組: $1",
+       "listgrouprights-removegroup-self": "在自己的帳號中移除的{{PLURAL:$2|一個|多個}}群組: $1",
+       "listgrouprights-addgroup-self-all": "在自己的帳號中加入所有群組",
+       "listgrouprights-removegroup-self-all": "在自己的帳號中移除所有群組",
        "listgrouprights-namespaceprotection-header": "命名空間限制",
        "listgrouprights-namespaceprotection-namespace": "命名空間",
        "listgrouprights-namespaceprotection-restrictedto": "允許使用者編輯的權限",
        "hidden-category-category-desc": "此分類帶有<code><nowiki>__HIDDENCAT__</nowiki></code>,它預設防止於頁面分類連接盒中顯示。",
        "trackingcategories-nodesc": "並無說明。",
        "trackingcategories-disabled": "分類被禁用",
-       "mailnologin": "沒有送位址",
-       "mailnologintext": "您必須先 [[Special:UserLogin|登入]]\n並在 [[Special:Preferences|偏好設定]]\n中設定一個有效的電子郵件地址才可以送信件給其他使用者。",
+       "mailnologin": "沒有送位址",
+       "mailnologintext": "您必須先 [[Special:UserLogin|登入]]\n並在 [[Special:Preferences|偏好設定]]\n中設定一個有效的電子郵件地址才可以送信件給其他使用者。",
        "emailuser": "寄信給此使用者",
        "emailuser-title-target": "寄信給此{{GENDER:$1|使用者}}",
        "emailuser-title-notarget": "寄信給使用者",
        "emailpage": "E-mail 給使用者",
-       "emailpagetext": "您可以使用以下表格送電子郵件給這位 {{Gender:$1|使用者}}。\n您在 [[Special:Preferences|偏好設定]] 中所輸入的電子郵件地址將會作為郵件的 \"寄件人\",因此該使用者可直接回覆您。",
-       "defemailsubject": "來自使用者 \"$1\" 於 {{SITENAME}} 發送的電子郵件",
+       "emailpagetext": "您可以使用以下表格送電子郵件給這位 {{Gender:$1|使用者}}。\n您在 [[Special:Preferences|偏好設定]] 中所輸入的電子郵件地址將會作為郵件的 \"寄件人\",因此該使用者可直接回覆您。",
+       "defemailsubject": "來自使用者 \"$1\" 於 {{SITENAME}} 寄來的電子郵件",
        "usermaildisabled": "使用者電子郵件已停用",
-       "usermaildisabledtext": "您不可送信件到這個 Wiki 上的其他使用者",
-       "noemailtitle": "沒有電子郵件址",
-       "noemailtext": "此使用者尚未指定一個有效的電子郵件址。",
+       "usermaildisabledtext": "您不可送信件到這個 Wiki 上的其他使用者",
+       "noemailtitle": "沒有電子郵件址",
+       "noemailtext": "此使用者尚未指定一個有效的電子郵件址。",
        "nowikiemailtext": "此使用者選擇不接收其他使用者的信件。",
        "emailnotarget": "收件人不存在或無效的使用者名稱。",
        "emailtarget": "輸入收件人使用者名稱",
        "emailusername": "使用者名稱:",
        "emailusernamesubmit": "送出",
-       "email-legend": "送電子郵件給另一位 {{SITENAME}} 使用者",
+       "email-legend": "送電子郵件給另一位 {{SITENAME}} 使用者",
        "emailfrom": "寄件人:",
        "emailto": "收件人:",
        "emailsubject": "主題:",
        "emailmessage": "訊息:",
-       "emailsend": "送",
-       "emailccme": "送一份副本到我的電子郵件信箱。",
-       "emailccsubject": "您發送給 $1 的訊息副本:$2",
-       "emailsent": "電子郵件已發送",
+       "emailsend": "送",
+       "emailccme": "送一份副本到我的電子郵件信箱。",
+       "emailccsubject": "您給 $1 的訊息副本:$2",
+       "emailsent": "電子郵件已送出",
        "emailsenttext": "您的電子郵件訊息已經送出。",
-       "emailuserfooter": "這封電子郵件是由 $1 透過 {{SITENAME}} 的 \"送信件給使用者\" 功能寄給 $2。",
+       "emailuserfooter": "這封電子郵件是由 $1 透過 {{SITENAME}} 的 \"送信件給使用者\" 功能寄給 $2。",
        "usermessage-summary": "留給系統訊息。",
        "usermessage-editor": "系統訊息",
        "watchlist": "監視清單",
        "deletecomment": "原因:",
        "deleteotherreason": "其它/額外的原因:",
        "deletereasonotherlist": "其它理由",
-       "deletereason-dropdown": "* 常見的刪除原因\n** 濫發廣告訊息\n** 破壞\n** 侵犯版權\n** 作者請求\n** 損壞的重定向",
+       "deletereason-dropdown": "* 常見的刪除原因\n** 濫發廣告訊息\n** 破壞\n** 侵犯版權\n** 作者請求\n** 損壞的重新導向連結",
        "delete-edit-reasonlist": "編輯刪除理由",
        "delete-toobig": "這個頁面有一個十分大量的編輯歷史,超過$1次修訂。刪除此類頁面的動作已經被限制,以防止在{{SITENAME}}上的意外擾亂。",
        "delete-warning-toobig": "這個頁面有一個十分大量的編輯歷史,超過$1次修訂。刪除它可能會擾亂{{SITENAME}}的資料庫操作;在繼續此動作前請小心。",
        "linkshere": "以下頁面連結到[[:$1]]:",
        "nolinkshere": "沒有頁面連結到[[:$1]]。",
        "nolinkshere-ns": "已選擇的命名空間中沒有頁面連結到 [[:$1]]。",
-       "isredirect": "重向頁面",
+       "isredirect": "重新導向頁面",
        "istemplate": "引用",
        "isimage": "檔案連結",
        "whatlinkshere-prev": "前 $1 筆",
        "whatlinkshere-next": "後 $1 筆",
        "whatlinkshere-links": "← 連入",
-       "whatlinkshere-hideredirs": "$1 重向頁面",
+       "whatlinkshere-hideredirs": "$1 重新導向頁面",
        "whatlinkshere-hidetrans": "$1 引用",
        "whatlinkshere-hidelinks": "$1 連結",
        "whatlinkshere-hideimages": "$1 檔案連結",
        "ipbreason-dropdown": "*常見的封鎖原因\n** 填寫不實資訊\n** 刪除頁面內容\n** 散佈外部廣告連結\n** 在頁面填寫無意義文字\n** 無禮的行為、攻擊/騷擾別人\n** 濫用多個帳號\n** 使用不受歡迎的使用者名稱",
        "ipb-hardblock": "避免使用此 IP 位址登入的使用者編輯",
        "ipbcreateaccount": "禁止建立帳號",
-       "ipbemailban": "禁止使用者送電子郵件",
-       "ipbenableautoblock": "自動封鎖此使用者最後使用的 IP 位,以及所有之後嘗試編輯使用的 IP 位址",
-       "ipbsubmit": "查封該地址",
+       "ipbemailban": "禁止使用者送電子郵件",
+       "ipbenableautoblock": "自動封鎖此使用者最後使用的 IP 位,以及所有之後嘗試編輯使用的 IP 位址",
+       "ipbsubmit": "封禁該使用者",
        "ipbother": "其它時間:",
        "ipboptions": "2小時:2 hours,1天:1 day,3天:3 days,1周:1 week,2周:2 weeks,1個月:1 month,3個月:3 months,6個月:6 months,1年:1 year,無限期:infinite",
        "ipbhidename": "在編輯及清單中隱藏使用者名稱",
        "unblocklink": "解除封鎖",
        "change-blocklink": "變更封鎖",
        "contribslink": "貢獻",
-       "emaillink": "送電子郵件",
+       "emaillink": "送電子郵件",
        "autoblocker": "您的 IP 位址因最近被 [[User:$1|$1]] 使用過而被自動封鎖。\n封鎖 $1 的原因為 \"$2\"",
        "blocklogpage": "查封日誌",
        "blocklog-showlog": "此使用者先前被封鎖過。\n以下為封鎖紀錄以供參考:",
        "proxyblocker": "代理封鎖器",
        "proxyblockreason": "因您的 IP 位址是開放代理伺服器,已被封鎖。\n請聯繫您的網路服務供應商或您所在組織的技術支援,告知他們此嚴重的安全性問題。",
        "sorbsreason": "您的IP位址在{{SITENAME}}中被 DNSBL列為屬於開放代理服務器。",
-       "sorbs_create_account_reason": "您連線到 {{SITENAME}} 的 IP 位址被 DNSBL 列為開放代理伺服。\n您不能建立帳號。",
+       "sorbs_create_account_reason": "您連線到 {{SITENAME}} 的 IP 位址被 DNSBL 列為開放代理伺服。\n您不能建立帳號。",
        "xffblockreason": "您的 IP 位址使用 X-Forwarded-For 標頭,您或您使用的代理伺服器已被封鎖。\n封鎖的原因為:$1",
        "cant-see-hidden-user": "您欲封鎖的使用者已經被封鎖並且隱藏。\n您沒有隱藏使用者的權限,您無法檢視或編輯該使用者的封鎖狀態。",
        "ipbblocked": "因您已被封鎖,故無法封鎖或解除封鎖其他使用者。",
        "lockedbyandtime": "(由 {{GENDER:$1|$1}} 於 $2 的 $3)",
        "move-page": "移動 $1",
        "move-page-legend": "移動頁面",
-       "movepagetext": "以下表格可以用來重新命名頁面,並將該頁面的所有歷史記錄一併移至擁有新名稱的頁面。\n舊標題的頁面將會變成重定向頁面,指向使用新標題的頁面。\n您可以選擇自動更新所有指向舊頁面的重定向,讓它們改為指向新頁面。\n若您選擇不自動更新,請檢查有沒有[[Special:DoubleRedirects|雙重重定向]]或[[Special:BrokenRedirects|損壞的重定向]]需要修正。\n您有責任讓連結繼續指向正確的地方。\n\n請注意,若新的頁面名稱已經被使用,則此頁面將<strong>不會</strong>移動至該處,除非新名稱下是個重定向頁面而且沒有任何編輯記錄。\n即是說,您可以將錯誤移動至其他名稱的頁面還原到原有名稱,但不能覆蓋任何現有的頁面。\n\n<strong>警告!</strong>\n這個動作對受歡迎的頁面來說可能是重大而唐突的更改;\n在行動前請先確認您了解移動可能帶來的後果。",
-       "movepagetext-noredirectfixer": "以下表格可以用來重新命名頁面,並將該頁面的所有歷史記錄一併移至擁有新名稱的頁面。\n舊標題的頁面將會變成重定向頁面,指向使用新標題的頁面。\n請檢查有沒有[[Special:DoubleRedirects|雙重重定向]]或[[Special:BrokenRedirects|損壞的重定向]]需要修正。\n您有責任讓連結繼續指向正確的地方。\n\n請注意,若新的頁面名稱已經被使用,則此頁面將<strong>不會</strong>移動至該處,除非新名稱下是個重定向頁面而且沒有任何編輯記錄。\n即是說,您可以將錯誤移動至其他名稱的頁面還原到原有名稱,但不能覆蓋任何現有的頁面。\n\n<strong>警告!</strong>\n這個動作對受歡迎的頁面來說可能是重大而唐突的更改;\n在行動前請先確認您了解移動可能帶來的後果。",
+       "movepagetext": "以下表格可以用來重新命名頁面,並將該頁面的所有歷史記錄一併移至擁有新名稱的頁面。\n舊標題的頁面將會變成重新導向頁面,指向使用新標題的頁面。\n您可以選擇自動更新所有指向舊頁面的重新導向,讓它們改為指向新頁面。\n若您選擇不自動更新,請檢查有沒有[[Special:DoubleRedirects|雙重重新導向]]或[[Special:BrokenRedirects|損壞的重新導向]]需要修正。\n您有責任讓連結繼續指向正確的地方。\n\n請注意,若新的頁面名稱已經被使用,則此頁面將<strong>不會</strong>移動至該處,除非新名稱下是個重新導向頁面而且沒有任何編輯記錄。\n即是說,您可以將錯誤移動至其他名稱的頁面還原到原有名稱,但不能覆蓋任何現有的頁面。\n\n<strong>警告!</strong>\n這個動作對受歡迎的頁面來說可能是重大而唐突的更改;\n在行動前請先確認您了解移動可能帶來的後果。",
+       "movepagetext-noredirectfixer": "以下表格可以用來重新命名頁面,並將該頁面的所有歷史記錄一併移至擁有新名稱的頁面。\n舊標題的頁面將會變成重新導向頁面,指向使用新標題的頁面。\n請檢查有沒有[[Special:DoubleRedirects|雙重重新導向]]或[[Special:BrokenRedirects|損壞的重新導向]]需要修正。\n您有責任讓連結繼續指向正確的地方。\n\n請注意,若新的頁面名稱已經被使用,則此頁面將<strong>不會</strong>移動至該處,除非新名稱下是個重新導向頁面而且沒有任何編輯記錄。\n即是說,您可以將錯誤移動至其他名稱的頁面還原到原有名稱,但不能覆蓋任何現有的頁面。\n\n<strong>警告!</strong>\n這個動作對受歡迎的頁面來說可能是重大而唐突的更改;\n在行動前請先確認您了解移動可能帶來的後果。",
        "movepagetalktext": "相關的的對話頁面 (如果有的話) 會自動與該頁面一起移動,<strong>除非:</strong>\n*新的名稱已有一個存在的對話頁面,或\n*您未勾選此核選方塊。\n\n在上述情況下,若有必要您必須手動移動或合併已存在的頁面。",
        "movearticle": "移動頁面:",
        "moveuserpage-warning": "<strong>警告:</strong>您正要移動使用者頁面,請注意只有使用者頁面會變更名稱,並<em>不會</em>重新命名使用者。",
        "movepagebtn": "移動頁面",
        "pagemovedsub": "移動成功",
        "movepage-moved": "<strong>已移動 \"$1\" 至 \"$2\"</strong>",
-       "movepage-moved-redirect": "已建立重向頁面。",
-       "movepage-moved-noredirect": "已禁止建立重向頁面。",
+       "movepage-moved-redirect": "已建立重新導向頁面。",
+       "movepage-moved-noredirect": "已禁止建立重新導向頁面。",
        "articleexists": "該頁面名稱已存在,或您選擇的名稱無效。\n請改選擇其他名稱。",
        "cantmove-titleprotected": "您選擇的新標題已被禁止使用,您不可移動頁面到該位置。",
        "movetalk": "移動相關的對話頁面",
        "nonfile-cannot-move-to-file": "不可以移動非檔案到檔案命名空間",
        "imagetypemismatch": "新的檔案副檔名不符合該檔案的類型",
        "imageinvalidfilename": "目標檔案名稱無效",
-       "fix-double-redirects": "更新所有指向原標題的重定向",
-       "move-leave-redirect": "留下重向頁面",
+       "fix-double-redirects": "更新所有指向原標題的重新導向頁面",
+       "move-leave-redirect": "留下重新導向頁面",
        "protectedpagemovewarning": "<strong>警告:</strong>本頁已經被保護,只有擁有管理員權限的使用者才可移動。\n以下提供最近的日誌以便參考:",
        "semiprotectedpagemovewarning": "<strong>注意:</strong>本頁已經被保護,只有已註冊的使用者才可移動。\n以下提供最近的日誌以便參考:",
        "move-over-sharedrepo": "== 檔案已存在 ==\n[[:$1]] 已存在於共用檔案庫,將檔案移動到此標題會覆蓋該共用檔案。",
        "tooltip-feed-rss": "訂閱此頁面的 RSS feed",
        "tooltip-feed-atom": "訂閱此頁面的 Atom feed",
        "tooltip-t-contributions": "此使用者的貢獻清單",
-       "tooltip-t-emailuser": "送電子郵件給這個使用者",
+       "tooltip-t-emailuser": "送電子郵件給這個使用者",
        "tooltip-t-upload": "上傳檔案",
        "tooltip-t-specialpages": "全部特殊頁面的列表",
        "tooltip-t-print": "此頁面的可列印版本",
        "pageinfo-views": "檢視次數",
        "pageinfo-watchers": "頁面監視者數",
        "pageinfo-few-watchers": "少於 $1 名監視者",
-       "pageinfo-redirects-name": "指向此頁面的重定向數量",
+       "pageinfo-redirects-name": "指向此頁面的重新導向頁面數量",
        "pageinfo-subpages-name": "此頁面的子頁面",
-       "pageinfo-subpages-value": "$1($2 個重定向頁面; $3 個非重定向頁面)",
+       "pageinfo-subpages-value": "$1 ($2 個重新導向頁面; $3 個非重新導向頁面)",
        "pageinfo-firstuser": "頁面的建立者",
        "pageinfo-firsttime": "頁面創建日期",
        "pageinfo-lastuser": "最近編輯者",
        "pageinfo-templates": "引用的樣版 ($1)",
        "pageinfo-transclusions": "頁面被引用於 ($1)",
        "pageinfo-toolboxlink": "頁面資訊",
-       "pageinfo-redirectsto": "重向至",
+       "pageinfo-redirectsto": "重新導向至",
        "pageinfo-redirectsto-info": "資訊",
        "pageinfo-contentpage": "作為內容頁面計算",
        "pageinfo-contentpage-yes": "是",
        "table_pager_empty": "沒有結果",
        "autosumm-blank": "清空頁面",
        "autosumm-replace": "使用 \"$1\" 取代內容",
-       "autoredircomment": "頁面已重向至 [[$1]]",
+       "autoredircomment": "頁面已重新導向至 [[$1]]",
        "autosumm-new": "已建立頁面,內容為 \"$1\"",
        "size-bytes": "$1 位元組",
        "lag-warn-normal": "此清單可能不會顯示最近 $1 {{PLURAL:$1|秒}}內的變更。",
        "duplicate-defaultsort": "<strong>警告:</strong>預設的排序鍵 \"$2\" 會覆蓋先前預設的排序鍵 \"$1\"。",
        "version": "版本",
        "version-extensions": "已安裝的擴充套件",
-       "version-skins": "外觀",
+       "version-skins": "å·²è£\9då¤\96è§\80",
        "version-specialpages": "特殊頁面",
        "version-parserhooks": "語法連結(Hook)",
        "version-variables": "變數",
        "version-license": "MediaWiki 授權條款",
        "version-ext-license": "授權條款",
        "version-ext-colheader-name": "擴充套件",
+       "version-skin-colheader-name": "外觀",
        "version-ext-colheader-version": "版本",
        "version-ext-colheader-license": "授權條款",
        "version-ext-colheader-description": "說明",
        "version-entrypoints-header-entrypoint": "入口",
        "version-entrypoints-header-url": "URL",
        "version-entrypoints-articlepath": "[https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:$wgArticlePath 條目路徑]",
-       "redirect": "指向檔案、使用者、頁面或修訂 ID 的重定向",
-       "redirect-legend": "重向至檔案或頁面",
-       "redirect-summary": "此特殊頁面可用來建立重定向,指向任何檔案(指定檔案名)、頁面(指定修訂 ID 或頁面 ID)或使用者頁面(指定使用者 ID)。用法:[[{{#Special:Redirect}}/file/Example.jpg]]、[[{{#Special:Redirect}}/page/64308]]、[[{{#Special:Redirect}}/revision/328429]] 或 [[{{#Special:Redirect}}/user/101]]。",
+       "redirect": "重新導向至檔案、使用者、頁面或修訂 ID",
+       "redirect-legend": "重新導向至檔案或頁面",
+       "redirect-summary": "此特殊頁面可用來重新導向至檔案 (指定檔案名稱)、頁面 (指定修訂 ID 或頁面 ID) 或使用者頁面 (指定使用者 ID)。用法:[[{{#Special:Redirect}}/file/Example.jpg]]、[[{{#Special:Redirect}}/page/64308]]、[[{{#Special:Redirect}}/revision/328429]] 或 [[{{#Special:Redirect}}/user/101]]。",
        "redirect-submit": "執行",
        "redirect-lookup": "尋找:",
        "redirect-value": "值:",
        "specialpages-group-pages": "頁面清單",
        "specialpages-group-pagetools": "頁面工具",
        "specialpages-group-wiki": "資料和工具",
-       "specialpages-group-redirects": "重定向到別處的特殊頁面",
+       "specialpages-group-redirects": "重新導向相關特殊頁面",
        "specialpages-group-spam": "反垃圾訊息工具",
        "blankpage": "空白頁面",
        "intentionallyblankpage": "此頁面被故意設為空白。",
        "revdelete-restricted": "已套用對管理員的限制",
        "revdelete-unrestricted": "已移除對管理員的限制",
        "logentry-move-move": "$1 {{GENDER:$2|已移動}}頁面 $3 至 $4",
-       "logentry-move-move-noredirect": "$1 已移動頁面 $3 至 $4,不留重定向",
-       "logentry-move-move_redir": "$1 已移動頁面 $3 至 $4 並覆蓋原有重向",
-       "logentry-move-move_redir-noredirect": "$1 已移動頁面 $3 至 $4 並覆蓋原有重定向,不留重定向",
+       "logentry-move-move-noredirect": "$1 已移動頁面 $3 至 $4,不留重新導向頁面",
+       "logentry-move-move_redir": "$1 已移動頁面 $3 至 $4 並覆蓋原有重新導向",
+       "logentry-move-move_redir-noredirect": "$1 {{GENDER:$2|已移動}}頁面 $3 覆蓋重新導向頁面至 $4,未留重新導向頁面",
        "logentry-patrol-patrol": "$1 {{GENDER:$2|已標記}}頁面 $3 的修訂 $4 為已巡查",
        "logentry-patrol-patrol-auto": "$1 已自動{{GENDER:$2|標記}}頁面 $3 的修訂 $4 為已巡查",
        "logentry-newusers-newusers": "已{{GENDER:$2|建立}}使用者帳號 $1",
        "expand_templates_remove_nowiki": "在結果中禁止顯示 <nowiki> 標籤",
        "expand_templates_generate_xml": "顯示 XML 解析樹",
        "expand_templates_generate_rawhtml": "顯示原始 HTML",
-       "expand_templates_preview": "預覽"
+       "expand_templates_preview": "預覽",
+       "pagelanguage": "頁面語言選擇器",
+       "pagelang-name": "頁面",
+       "pagelang-language": "語言",
+       "pagelang-use-default": "使用預設語言",
+       "pagelang-select-lang": "選擇語言",
+       "right-pagelang": "更改頁面語言",
+       "action-pagelang": "更改頁面語言",
+       "log-name-pagelang": "更改語言日誌",
+       "log-description-pagelang": "這是頁面語言更改日誌。",
+       "logentry-pagelang-pagelang": "$1{{GENDER:$2|更改}}$3頁面語言從$4到$5。"
 }
index 1790f48..1dd1a89 100644 (file)
--- a/load.php
+++ b/load.php
@@ -23,7 +23,7 @@
  */
 
 // Bail if PHP is too low
-if ( !function_exists( 'version_compare' ) || version_compare( phpversion(), '5.3.2' ) < 0 ) {
+if ( !function_exists( 'version_compare' ) || version_compare( PHP_VERSION, '5.3.2' ) < 0 ) {
        // We need to use dirname( __FILE__ ) here cause __DIR__ is PHP5.3+
        require dirname( __FILE__ ) . '/includes/PHPVersionError.php';
        wfPHPVersionError( 'load.php' );
index 5a3e00c..3b29452 100644 (file)
@@ -21,7 +21,7 @@
  * @ingroup Maintenance
  */
 
-if ( !function_exists( 'version_compare' ) || ( version_compare( phpversion(), '5.3.2' ) < 0 ) ) {
+if ( !function_exists( 'version_compare' ) || ( version_compare( PHP_VERSION, '5.3.2' ) < 0 ) ) {
        require_once dirname( __FILE__ ) . '/../includes/PHPVersionError.php';
        wfPHPVersionError( 'cli' );
 }
@@ -85,8 +85,8 @@ class CommandLineInstaller extends Maintenance {
                        true
                );
                $this->addOption( 'confpath', "Path to write LocalSettings.php to ($IP)", false, true );
+               $this->addOption( 'dbschema', 'The schema for the MediaWiki DB in PostgreSQL/Microsoft SQL Server (mediawiki)', false, true );
                /*
-               $this->addOption( 'dbschema', 'The schema for the MediaWiki DB in pg (mediawiki)', false, true );
                $this->addOption( 'namespace', 'The project namespace (same as the "name" argument)', false, true );
                */
                $this->addOption( 'env-checks', "Run environment checks only, don't change anything" );
diff --git a/maintenance/mssql/archives/named_constraints.sql b/maintenance/mssql/archives/named_constraints.sql
new file mode 100644 (file)
index 0000000..94b77ea
--- /dev/null
@@ -0,0 +1,38 @@
+DECLARE @fullyQualifiedTableName nvarchar(max),
+@tableName sysname,
+@fieldName sysname,
+@constr sysname,
+@constrNew sysname,
+@sqlcmd nvarchar(max),
+@sqlcreate nvarchar(max)
+
+SET @fullyQualifiedTableName = '/*_*//*$tableName*/'
+SET @tableName = '/*$tableName*/'
+SET @fieldName = '/*$fieldName*/'
+
+SELECT @constr = CONSTRAINT_NAME
+FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS
+WHERE TABLE_NAME = @tableName
+AND CONSTRAINT_CATALOG = '/*$wgDBname*/'
+AND CONSTRAINT_SCHEMA = '/*$wgDBmwschema*/'
+AND CONSTRAINT_TYPE = 'CHECK'
+AND CONSTRAINT_NAME LIKE ('CK__' + left(@tableName,9) + '__' + left(@fieldName,5) + '%')
+
+SELECT @constrNew = CONSTRAINT_NAME
+FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS
+WHERE TABLE_NAME = @tableName
+AND CONSTRAINT_CATALOG = '/*$wgDBname*/'
+AND CONSTRAINT_SCHEMA = '/*$wgDBmwschema*/'
+AND CONSTRAINT_TYPE = 'CHECK'
+AND CONSTRAINT_NAME = (@fieldName + '_ckc')
+
+IF @constr IS NOT NULL
+BEGIN
+  SET @sqlcmd =  'ALTER TABLE ' + @fullyQualifiedTableName + ' DROP CONSTRAINT [' + @constr + ']'
+  EXECUTE sp_executesql @sqlcmd
+END
+IF @constrNew IS NULL
+BEGIN
+  SET @sqlcreate =  'ALTER TABLE ' + @fullyQualifiedTableName + ' WITH NOCHECK ADD CONSTRAINT ' + @fieldName + '_ckc CHECK /*$checkConstraint*/;'
+  EXECUTE sp_executesql @sqlcreate
+END
\ No newline at end of file
index fa189ff..daaa81e 100644 (file)
@@ -299,8 +299,9 @@ CREATE TABLE /*_*/categorylinks (
   -- paginate the three categories separately.  This never has to be updated
   -- after the page is created, since none of these page types can be moved to
   -- any other.
+  cl_type varchar(10) NOT NULL default 'page',
   -- SQL server doesn't have enums, so we approximate with this
-  cl_type varchar(10) NOT NULL default 'page' CHECK (cl_type IN('page', 'subcat', 'file'))
+  CONSTRAINT cl_type_ckc CHECK (cl_type IN('page', 'subcat', 'file'))
 );
 
 CREATE UNIQUE INDEX /*i*/cl_from ON /*_*/categorylinks (cl_from,cl_to);
@@ -567,11 +568,11 @@ CREATE TABLE /*_*/image (
   img_bits int NOT NULL default 0,
 
   -- Media type as defined by the MEDIATYPE_xxx constants
-  img_media_type varchar(16) default null check (img_media_type in('UNKNOWN', 'BITMAP', 'DRAWING', 'AUDIO', 'VIDEO', 'MULTIMEDIA', 'OFFICE', 'TEXT', 'EXECUTABLE', 'ARCHIVE')),
+  img_media_type varchar(16) default null,
 
   -- major part of a MIME media type as defined by IANA
   -- see http://www.iana.org/assignments/media-types/
-  img_major_mime varchar(16) not null default 'unknown' check (img_major_mime IN('unknown', 'application', 'audio', 'image', 'text', 'video', 'message', 'model', 'multipart')),
+  img_major_mime varchar(16) not null default 'unknown',
 
   -- minor part of a MIME media type as defined by IANA
   -- the minor parts are not required to adher to any standard
@@ -591,7 +592,10 @@ CREATE TABLE /*_*/image (
   img_timestamp nvarchar(14) NOT NULL default '',
 
   -- SHA-1 content hash in base-36
-  img_sha1 nvarchar(32) NOT NULL default ''
+  img_sha1 nvarchar(32) NOT NULL default '',
+
+  CONSTRAINT img_major_mime_ckc check (img_major_mime IN('unknown', 'application', 'audio', 'image', 'text', 'video', 'message', 'model', 'multipart')),
+  CONSTRAINT img_media_type_ckc check (img_media_type in('UNKNOWN', 'BITMAP', 'DRAWING', 'AUDIO', 'VIDEO', 'MULTIMEDIA', 'OFFICE', 'TEXT', 'EXECUTABLE', 'ARCHIVE'))
 );
 
 CREATE INDEX /*i*/img_usertext_timestamp ON /*_*/image (img_user_text,img_timestamp);
@@ -629,11 +633,14 @@ CREATE TABLE /*_*/oldimage (
   oi_timestamp varchar(14) NOT NULL default '',
 
   oi_metadata nvarchar(max) NOT NULL,
-  oi_media_type varchar(16) default null check (oi_media_type IN('UNKNOWN', 'BITMAP', 'DRAWING', 'AUDIO', 'VIDEO', 'MULTIMEDIA', 'OFFICE', 'TEXT', 'EXECUTABLE', 'ARCHIVE')),
-  oi_major_mime varchar(16) not null default 'unknown' check (oi_major_mime IN('unknown', 'application', 'audio', 'image', 'text', 'video', 'message', 'model', 'multipart')),
+  oi_media_type varchar(16) default null,
+  oi_major_mime varchar(16) not null default 'unknown',
   oi_minor_mime nvarchar(100) NOT NULL default 'unknown',
   oi_deleted tinyint NOT NULL default 0,
-  oi_sha1 nvarchar(32) NOT NULL default ''
+  oi_sha1 nvarchar(32) NOT NULL default '',
+
+  CONSTRAINT oi_major_mime_ckc check (oi_major_mime IN('unknown', 'application', 'audio', 'image', 'text', 'video', 'message', 'model', 'multipart')),
+  CONSTRAINT oi_media_type_ckc check (oi_media_type IN('UNKNOWN', 'BITMAP', 'DRAWING', 'AUDIO', 'VIDEO', 'MULTIMEDIA', 'OFFICE', 'TEXT', 'EXECUTABLE', 'ARCHIVE'))
 );
 
 CREATE INDEX /*i*/oi_usertext_timestamp ON /*_*/oldimage (oi_user_text,oi_timestamp);
@@ -679,8 +686,8 @@ CREATE TABLE /*_*/filearchive (
   fa_height int default 0,
   fa_metadata nvarchar(max),
   fa_bits int default 0,
-  fa_media_type varchar(16) default null check (fa_media_type in('UNKNOWN', 'BITMAP', 'DRAWING', 'AUDIO', 'VIDEO', 'MULTIMEDIA', 'OFFICE', 'TEXT', 'EXECUTABLE', 'ARCHIVE')),
-  fa_major_mime varchar(16) not null default 'unknown' check (fa_major_mime in('unknown', 'application', 'audio', 'image', 'text', 'video', 'message', 'model', 'multipart')),
+  fa_media_type varchar(16) default null,
+  fa_major_mime varchar(16) not null default 'unknown',
   fa_minor_mime nvarchar(100) default 'unknown',
   fa_description nvarchar(255),
   fa_user int default 0 REFERENCES /*_*/mwuser(user_id) ON DELETE SET NULL,
@@ -691,7 +698,10 @@ CREATE TABLE /*_*/filearchive (
   fa_deleted tinyint NOT NULL default 0,
 
   -- sha1 hash of file content
-  fa_sha1 nvarchar(32) NOT NULL default ''
+  fa_sha1 nvarchar(32) NOT NULL default '',
+
+  CONSTRAINT fa_major_mime_ckc check (fa_major_mime in('unknown', 'application', 'audio', 'image', 'text', 'video', 'message', 'model', 'multipart')),
+  CONSTRAINT fa_media_type_ckc check (fa_media_type in('UNKNOWN', 'BITMAP', 'DRAWING', 'AUDIO', 'VIDEO', 'MULTIMEDIA', 'OFFICE', 'TEXT', 'EXECUTABLE', 'ARCHIVE'))
 );
 
 -- pick out by image name
@@ -746,12 +756,13 @@ CREATE TABLE /*_*/uploadstash (
   us_sha1 nvarchar(31) NOT NULL,
   us_mime nvarchar(255),
   -- Media type as defined by the MEDIATYPE_xxx constants, should duplicate definition in the image table
-  us_media_type varchar(16) default null check (us_media_type in('UNKNOWN', 'BITMAP', 'DRAWING', 'AUDIO', 'VIDEO', 'MULTIMEDIA', 'OFFICE', 'TEXT', 'EXECUTABLE', 'ARCHIVE')),
+  us_media_type varchar(16) default null,
   -- image-specific properties
   us_image_width int,
   us_image_height int,
-  us_image_bits smallint
+  us_image_bits smallint,
 
+  CONSTRAINT us_media_type_ckc check (us_media_type in('UNKNOWN', 'BITMAP', 'DRAWING', 'AUDIO', 'VIDEO', 'MULTIMEDIA', 'OFFICE', 'TEXT', 'EXECUTABLE', 'ARCHIVE'))
 );
 
 -- sometimes there's a delete for all of a user's stuff.
index a51564a..046d73c 100755 (executable)
@@ -26,7 +26,7 @@
  * @ingroup Maintenance
  */
 
-if ( !function_exists( 'version_compare' ) || ( version_compare( phpversion(), '5.3.2' ) < 0 ) ) {
+if ( !function_exists( 'version_compare' ) || ( version_compare( PHP_VERSION, '5.3.2' ) < 0 ) ) {
        require dirname( __FILE__ ) . '/../includes/PHPVersionError.php';
        wfPHPVersionError( 'cli' );
 }
index 56c1308..be176c7 100644 (file)
  * @file
  */
 
+// Bail if PHP is too low
+if ( !function_exists( 'version_compare' ) || version_compare( PHP_VERSION, '5.3.2' ) < 0 ) {
+       // We need to use dirname( __FILE__ ) here cause __DIR__ is PHP5.3+
+       require dirname( dirname( __FILE__ ) ) . '/includes/PHPVersionError.php';
+       wfPHPVersionError( 'mw-config/index.php' );
+}
+
 define( 'MW_CONFIG_CALLBACK', 'Installer::overrideConfig' );
 define( 'MEDIAWIKI_INSTALL', true );
 
index 02048c0..4595994 100644 (file)
@@ -366,7 +366,6 @@ var spliceWorksWithEmptyObject = (function () {
     ArrayPrototype.splice.call(obj, 0, 0, 1);
     return obj.length === 1;
 }());
-var omittingSecondSpliceArgIsNoop = [1].splice(0).length === 0;
 defineProperties(ArrayPrototype, {
     splice: function splice(start, deleteCount) {
         if (arguments.length === 0) { return []; }
@@ -375,14 +374,14 @@ defineProperties(ArrayPrototype, {
         if (arguments.length > 0 && typeof deleteCount !== 'number') {
             args = _Array_slice_.call(arguments);
             if (args.length < 2) {
-                args.push(toInteger(deleteCount));
+                args.push(this.length - start);
             } else {
                 args[1] = toInteger(deleteCount);
             }
         }
         return array_splice.apply(this, args);
     }
-}, !omittingSecondSpliceArgIsNoop || !spliceWorksWithEmptyObject);
+}, !spliceWorksWithEmptyObject);
 
 // ES5 15.4.4.12
 // http://es5.github.com/#x15.4.4.13
@@ -674,7 +673,7 @@ defineProperties(ArrayPrototype, {
 // ES5 15.4.4.14
 // http://es5.github.com/#x15.4.4.14
 // https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/indexOf
-var hasFirefox2IndexOfBug = [0, 1].indexOf(1, 2) !== -1;
+var hasFirefox2IndexOfBug = Array.prototype.indexOf && [0, 1].indexOf(1, 2) !== -1;
 defineProperties(ArrayPrototype, {
     indexOf: function indexOf(sought /*, fromIndex */ ) {
         var self = splitString && isString(this) ? this.split('') : toObject(this),
@@ -703,7 +702,7 @@ defineProperties(ArrayPrototype, {
 // ES5 15.4.4.15
 // http://es5.github.com/#x15.4.4.15
 // https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/lastIndexOf
-var hasFirefox2LastIndexOfBug = [0, 1].lastIndexOf(0, -3) !== -1;
+var hasFirefox2LastIndexOfBug = Array.prototype.lastIndexOf && [0, 1].lastIndexOf(0, -3) !== -1;
 defineProperties(ArrayPrototype, {
     lastIndexOf: function lastIndexOf(sought /*, fromIndex */) {
         var self = splitString && isString(this) ? this.split('') : toObject(this),
@@ -1082,7 +1081,7 @@ if (!Date.now) {
 // http://es5.github.com/#x15.7.4.5
 var hasToFixedBugs = NumberPrototype.toFixed && (
   (0.00008).toFixed(3) !== '0.000'
-  || (0.9).toFixed(0) === '0'
+  || (0.9).toFixed(0) !== '1'
   || (1.255).toFixed(2) !== '1.25'
   || (1000000000000000128).toFixed(0) !== "1000000000000000128"
 );
index 8b0bee4..7ad74dc 100644 (file)
@@ -11,5 +11,9 @@
        "ooui-dialog-action-close": "Aizvērt",
        "ooui-outline-control-move-down": "Pārvietot vienumu uz leju",
        "ooui-outline-control-move-up": "Pārvietot vienumu uz augšu",
-       "ooui-toolbar-more": "Vairāk"
+       "ooui-toolbar-more": "Vairāk",
+       "ooui-dialog-confirm-title": "Apstiprināt",
+       "ooui-dialog-confirm-default-prompt": "Vai esat pārliecināts?",
+       "ooui-dialog-confirm-default-ok": "Labi",
+       "ooui-dialog-confirm-default-cancel": "Atcelt"
 }
index df78186..ff52c32 100644 (file)
@@ -1,8 +1,6 @@
 <?xml version="1.0" encoding="iso-8859-1"?>
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="24px"
-        height="24px" viewBox="0 0 24 24" style="enable-background:new 0 0 24 24;" xml:space="preserve">
-<g id="apply" style="opacity:0.75;">
-       <polygon id="check" style="fill-rule:evenodd;clip-rule:evenodd;" points="19.062,5.139 17.418,4 8.867,16.357 5.413,12.903 4,14.316 9.021,19.338"/>
-</g>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+    <g id="apply" opacity=".75">
+        <path id="check" fill-rule="evenodd" clip-rule="evenodd" d="M19.062 5.139l-1.644-1.139-8.551 12.357-3.454-3.454-1.413 1.413 5.021 5.022z"/>
+    </g>
 </svg>
index 2620e76..b25d5b7 100644 (file)
@@ -1,8 +1,6 @@
 <?xml version="1.0" encoding="iso-8859-1"?>
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="24px"
-        height="24px" viewBox="0 0 24 24" style="enable-background:new 0 0 24 24;" xml:space="preserve">
-<g id="apply" style="opacity:0.75;">
-       <path d="M13,8 L11,8 L11,11 L8,11 L8,13 L11,13 L11,16 L13,16 L13,13 L16,13 L16,11 L13,11 z"/>
-</g>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+    <g id="apply" opacity=".75">
+        <path d="M13 8h-2v3h-3v2h3v3h2v-3h3v-2h-3z"/>
+    </g>
 </svg>
index 3e87cab..223b7fc 100644 (file)
@@ -1,17 +1,6 @@
 <?xml version="1.0" encoding="iso-8859-1"?>
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="24px"
-        height="24px" viewBox="0 0 24 24" style="enable-background:new 0 0 24 24;" xml:space="preserve">
-<g id="settings" style="opacity:0.75;">
-       <path id="gear" style="fill-rule:evenodd;clip-rule:evenodd;" d="M20.869,13.476C20.948,12.994,21,12.504,21,12
-               s-0.052-0.994-0.131-1.476l-2.463-0.259c-0.149-0.556-0.367-1.082-0.648-1.57l1.558-1.924c-0.576-0.806-1.281-1.511-2.087-2.087
-               l-1.924,1.558c-0.488-0.281-1.015-0.499-1.57-0.648l-0.259-2.463C12.994,3.052,12.504,3,12,3s-0.994,0.052-1.476,0.131
-               l-0.259,2.463C9.71,5.743,9.184,5.961,8.695,6.242L6.771,4.685C5.966,5.261,5.261,5.966,4.685,6.771l1.558,1.924
-               c-0.281,0.488-0.499,1.015-0.648,1.57l-2.463,0.259C3.052,11.006,3,11.496,3,12s0.052,0.994,0.131,1.476l2.463,0.259
-               c0.149,0.556,0.367,1.082,0.648,1.57l-1.558,1.924c0.576,0.806,1.281,1.511,2.087,2.087l1.924-1.558
-               c0.488,0.281,1.015,0.499,1.57,0.648l0.259,2.463C11.006,20.948,11.496,21,12,21s0.994-0.052,1.476-0.131l0.259-2.463
-               c0.556-0.149,1.082-0.367,1.57-0.648l1.924,1.558c0.806-0.576,1.511-1.281,2.087-2.087l-1.558-1.924
-               c0.281-0.488,0.499-1.015,0.648-1.57L20.869,13.476z M12,15.998c-2.209,0-3.998-1.789-3.998-3.998S9.791,8.002,12,8.002
-               S15.998,9.791,15.998,12S14.209,15.998,12,15.998z"/>
-</g>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+    <g id="settings" opacity=".75">
+        <path id="gear" d="M20.869 13.476c.079-.482.131-.972.131-1.476s-.052-.994-.131-1.476l-2.463-.259c-.149-.556-.367-1.082-.648-1.57l1.558-1.924c-.576-.806-1.281-1.511-2.087-2.087l-1.924 1.558c-.488-.281-1.015-.499-1.57-.648l-.259-2.463c-.482-.079-.972-.131-1.476-.131s-.994.052-1.476.131l-.259 2.463c-.555.149-1.081.367-1.57.648l-1.924-1.557c-.805.576-1.51 1.281-2.086 2.086l1.558 1.924c-.281.488-.499 1.015-.648 1.57l-2.463.259c-.08.482-.132.972-.132 1.476s.052.994.131 1.476l2.463.259c.149.556.367 1.082.648 1.57l-1.558 1.924c.576.806 1.281 1.511 2.087 2.087l1.924-1.558c.488.281 1.015.499 1.57.648l.259 2.463c.482.079.972.131 1.476.131s.994-.052 1.476-.131l.259-2.463c.556-.149 1.082-.367 1.57-.648l1.924 1.558c.806-.576 1.511-1.281 2.087-2.087l-1.558-1.924c.281-.488.499-1.015.648-1.57l2.463-.259zm-8.869 2.522c-2.209 0-3.998-1.789-3.998-3.998s1.789-3.998 3.998-3.998 3.998 1.789 3.998 3.998-1.789 3.998-3.998 3.998z" fill-rule="evenodd" clip-rule="evenodd"/>
+    </g>
 </svg>
index 886a7c0..fb25766 100644 (file)
@@ -1,10 +1,8 @@
 <?xml version="1.0" encoding="iso-8859-1"?>
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="24px"
-        height="24px" viewBox="0 0 24 24" style="enable-background:new 0 0 24 24;" xml:space="preserve">
-<g id="alert" style="opacity:0.75;">
-       <rect id="point" x="11" y="16" style="fill-rule:evenodd;clip-rule:evenodd;" width="2" height="2"/>
-       <polygon id="stroke" style="fill-rule:evenodd;clip-rule:evenodd;" points="13.516,10 10.516,10 11,15 13,15"/>
-       <path id="triangle" d="M12.017,5.974L19.536,19H4.496L12.017,5.974 M12.017,3.5c-0.544,0-1.088,0.357-1.5,1.071L2.532,18.402 C1.707,19.831,2.382,21,4.032,21H20c1.65,0,2.325-1.169,1.5-2.599L13.517,4.572C13.104,3.857,12.561,3.5,12.017,3.5L12.017,3.5z"/>
-</g>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+    <g id="alert" opacity=".75">
+        <path id="point" fill-rule="evenodd" clip-rule="evenodd" d="M11 16h2v2h-2z"/>
+        <path id="stroke" fill-rule="evenodd" clip-rule="evenodd" d="M13.516 10h-3l.484 5h2z"/>
+        <path id="triangle" d="M12.017 5.974l7.519 13.026h-15.04l7.521-13.026m0-2.474c-.544 0-1.088.357-1.5 1.071l-7.985 13.831c-.825 1.429-.15 2.598 1.5 2.598h15.968c1.65 0 2.325-1.169 1.5-2.599l-7.983-13.829c-.413-.715-.956-1.072-1.5-1.072z"/>
+    </g>
 </svg>
index 5b343a5..88a6a40 100644 (file)
@@ -1,8 +1,6 @@
 <?xml version="1.0" encoding="iso-8859-1"?>
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="24px"
-        height="24px" viewBox="0 0 24 24" style="enable-background:new 0 0 24 24;" xml:space="preserve">
-<g id="arched-arrow-ltr" style="opacity:0.75;">
-       <path id="arrow" style="fill-rule:evenodd;clip-rule:evenodd;" d="M19.925,14.937l-2.391-6.901l-1.48,2.329 c-0.964-0.845-2.699-1.85-5.513-1.823c-4.887,0.046-6.524,4.244-6.524,4.244s2.753-2.639,6.925-1.949 c1.729,0.286,3.007,1.206,3.675,1.791l-1.474,2.319L19.925,14.937z"/>
-</g>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+    <g id="arched-arrow-ltr" opacity=".75">
+        <path id="arrow" d="M19.925 14.937l-2.391-6.901-1.48 2.329c-.964-.845-2.699-1.85-5.513-1.823-4.887.046-6.524 4.244-6.524 4.244s2.753-2.639 6.925-1.949c1.729.286 3.007 1.206 3.675 1.791l-1.474 2.319 6.782-.01z" fill-rule="evenodd" clip-rule="evenodd"/>
+    </g>
 </svg>
index bb5f10e..50541d2 100644 (file)
@@ -1,8 +1,6 @@
 <?xml version="1.0" encoding="iso-8859-1"?>
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="24px"
-        height="24px" viewBox="0 0 24 24" style="enable-background:new 0 0 24 24;" xml:space="preserve">
-<g id="arched-arrow-rtl" style="opacity:0.75;">
-       <path id="arrow" style="fill-rule:evenodd;clip-rule:evenodd;" d="M13.401,8.542c-2.814-0.027-4.549,0.978-5.513,1.823 l-1.48-2.329l-2.391,6.901l6.782,0.009l-1.474-2.319c0.668-0.584,1.945-1.504,3.675-1.791c4.172-0.69,6.925,1.949,6.925,1.949 S18.288,8.588,13.401,8.542z"/>
-</g>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+    <g id="arched-arrow-rtl" opacity=".75">
+        <path id="arrow" d="M13.401 8.542c-2.814-.027-4.549.978-5.513 1.823l-1.48-2.329-2.391 6.901 6.782.009-1.474-2.319c.668-.584 1.945-1.504 3.675-1.791 4.172-.69 6.925 1.949 6.925 1.949s-1.637-4.197-6.524-4.243z" fill-rule="evenodd" clip-rule="evenodd"/>
+    </g>
 </svg>
index e67cd6c..8d4a1f8 100644 (file)
@@ -1,8 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="24" height="24" viewBox="0, 0, 24, 24">
-  <g id="check">
-    <path d="M7.105,13.473 L8.527,12.05 L10.428,13.952 L15.238,7 L16.895,8.148 L10.635,17 z" fill="#000000"/>
-  </g>
-  <defs/>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0, 0, 24, 24">
+    <g id="check">
+        <path d="M7.105 13.473l1.422-1.423 1.901 1.902 4.81-6.952 1.657 1.148-6.26 8.852z"/>
+    </g>
 </svg>
index d83eb02..484a104 100644 (file)
@@ -1,8 +1,6 @@
 <?xml version="1.0" encoding="iso-8859-1"?>
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="24px"
-        height="24px" viewBox="0 0 24 24" style="enable-background:new 0 0 24 24;" xml:space="preserve">
-<g id="clear" style="opacity:0.75;">
-       <path id="circle_with_strike" style="fill-rule:evenodd;clip-rule:evenodd;" d="M11.999,5.022c-3.853,0-6.977,3.124-6.977,6.978 c0,3.853,3.124,6.978,6.977,6.978c3.854,0,6.979-3.125,6.979-6.978C18.978,8.146,15.853,5.022,11.999,5.022z M6.886,12 c0-1.092,0.572-3.25,0.93-2.929l7.113,7.113c0.488,0.525-1.837,0.931-2.93,0.931C9.174,17.114,6.886,14.824,6.886,12z M16.184,14.929L9.07,7.816c-0.445-0.483,1.837-0.931,2.929-0.931c2.827,0,5.115,2.289,5.115,5.114 C17.114,13.092,16.75,15.542,16.184,14.929z"/>
-</g>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+    <g id="clear" opacity=".75">
+        <path id="circle_with_strike" d="M11.999 5.022c-3.853 0-6.977 3.124-6.977 6.978 0 3.853 3.124 6.978 6.977 6.978 3.854 0 6.979-3.125 6.979-6.978 0-3.854-3.125-6.978-6.979-6.978zm-5.113 6.978c0-1.092.572-3.25.93-2.929l7.113 7.113c.488.525-1.837.931-2.93.931-2.825-.001-5.113-2.291-5.113-5.115zm9.298 2.929l-7.114-7.113c-.445-.483 1.837-.931 2.929-.931 2.827 0 5.115 2.289 5.115 5.114 0 1.093-.364 3.543-.93 2.93z" fill-rule="evenodd" clip-rule="evenodd"/>
+    </g>
 </svg>
index a0118c2..15278e9 100644 (file)
@@ -1,8 +1,6 @@
 <?xml version="1.0" encoding="iso-8859-1"?>
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="24px"
-        height="24px" viewBox="0 0 24 24" style="enable-background:new 0 0 24 24;" xml:space="preserve">
-<g id="close" style="opacity:0.75;">
-       <polygon id="x" style="fill-rule:evenodd;clip-rule:evenodd;" points="18.717,6.697 17.303,5.283 12,10.586 6.697,5.283 5.283,6.697 10.586,12 5.283,17.303 6.697,18.717 12,13.414 17.303,18.717 18.717,17.303 13.414,12            "/>
-</g>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+    <g id="close" opacity=".75">
+        <path id="x" fill-rule="evenodd" clip-rule="evenodd" d="M18.717 6.697l-1.414-1.414-5.303 5.303-5.303-5.303-1.414 1.414 5.303 5.303-5.303 5.303 1.414 1.414 5.303-5.303 5.303 5.303 1.414-1.414-5.303-5.303z"/>
+    </g>
 </svg>
index 6f1ed53..a45ab1e 100644 (file)
@@ -1,14 +1,7 @@
 <?xml version="1.0" encoding="utf-8"?>
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
-        width="24px" height="24px" viewBox="0 0 24 24" enable-background="new 0 0 24 24" xml:space="preserve">
-<g id="code" opacity="0.75">
-       <path id="left-bracket" d="M4,12v-1h1c1,0,1,0,1-1V7.614C6,7.1,6.024,6.718,6.073,6.472C6.127,6.22,6.212,6.009,6.33,5.839
-               C6.534,5.56,6.803,5.364,7.138,5.255C7.473,5.14,8.01,5,8.973,5H10v1H9.248c-0.457,0-0.77,0.191-0.936,0.408
-               C8.145,6.623,8,6.853,8,7.476v1.857c0,0.729-0.041,1.18-0.244,1.493c-0.2,0.307-0.562,0.529-1.09,0.667
-               c0.535,0.155,0.9,0.385,1.096,0.688C7.961,12.484,8,12.938,8,13.665v1.862c0,0.619,0.145,0.848,0.312,1.062
-               c0.166,0.22,0.479,0.407,0.936,0.407L10,17l0,0v1H8.973c-0.963,0-1.5-0.133-1.835-0.248c-0.335-0.109-0.604-0.307-0.808-0.591
-               c-0.118-0.165-0.203-0.374-0.257-0.625C6.024,16.283,6,15.9,6,15.387V13c0-1,0-1-1-1H4z"/>
-       <use transform="matrix(-1,0,0,1,24,0)" id="right-bracket" x="0" y="0" width="24" height="24" xlink:href="#left-bracket" />
-</g>
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="24" height="24" viewBox="0 0 24 24">
+    <g id="code" opacity=".75">
+        <path id="left-bracket" d="M4 12v-1h1c1 0 1 0 1-1v-2.386c0-.514.024-.896.073-1.142.054-.252.139-.463.257-.633.204-.279.473-.475.808-.584.335-.115.872-.255 1.835-.255h1.027v1h-.752c-.457 0-.77.191-.936.408-.167.215-.312.445-.312 1.068v1.857c0 .729-.041 1.18-.244 1.493-.2.307-.562.529-1.09.667.535.155.9.385 1.096.688.199.303.238.757.238 1.484v1.862c0 .619.145.848.312 1.062.166.22.479.407.936.407l.752.004v1h-1.027c-.963 0-1.5-.133-1.835-.248-.335-.109-.604-.307-.808-.591-.118-.165-.203-.374-.257-.625-.049-.253-.073-.636-.073-1.149v-2.387c0-1 0-1-1-1h-1z"/>
+        <use transform="matrix(-1 0 0 1 24 0)" id="right-bracket" width="24" height="24" xlink:href="#left-bracket"/>
+    </g>
 </svg>
index a89cebf..97bdc50 100644 (file)
@@ -1,8 +1,6 @@
 <?xml version="1.0" encoding="iso-8859-1"?>
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="24px"
-        height="24px" viewBox="0 0 24 24" style="enable-background:new 0 0 24 24;" xml:space="preserve">
-<g id="collapse" style="opacity:0.75;">
-       <polygon id="arrow" style="fill-rule:evenodd;clip-rule:evenodd;" points="6.697,15.714 12,10.412 17.303,15.714 18.717,14.3 12,7.583 5.283,14.3"/>
-</g>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+    <g id="collapse" opacity=".75">
+        <path id="arrow" fill-rule="evenodd" clip-rule="evenodd" d="M6.697 15.714l5.303-5.302 5.303 5.302 1.414-1.414-6.717-6.717-6.717 6.717z"/>
+    </g>
 </svg>
index e052935..ebb038e 100644 (file)
@@ -1,8 +1,6 @@
 <?xml version="1.0" encoding="iso-8859-1"?>
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="24px"
-        height="24px" viewBox="0 0 24 24" style="enable-background:new 0 0 24 24;" xml:space="preserve">
-<g id="comment" style="opacity:0.75;">
-       <path id="speech_bubble" style="fill-rule:evenodd;clip-rule:evenodd;" d="M15,6H9C7.343,6,6,7.344,6,9v4c0,1.656,1.343,3,3,3v3 l3-3h3c1.657,0,3-1.344,3-3V9C18,7.344,16.657,6,15,6z"/>
-</g>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+    <g id="comment" opacity=".75">
+        <path id="speech_bubble" d="M15 6h-6c-1.657 0-3 1.344-3 3v4c0 1.656 1.343 3 3 3v3l3-3h3c1.657 0 3-1.344 3-3v-4c0-1.656-1.343-3-3-3z" fill-rule="evenodd" clip-rule="evenodd"/>
+    </g>
 </svg>
index b542f5f..81c2ec0 100644 (file)
@@ -1,8 +1,6 @@
 <?xml version="1.0" encoding="iso-8859-1"?>
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="24px"
-        height="24px" viewBox="0 0 24 24" style="enable-background:new 0 0 24 24;" xml:space="preserve">
-<g id="expand" style="opacity:0.75;">
-       <polygon id="arrow" style="fill-rule:evenodd;clip-rule:evenodd;" points="17.303,8.283 12,13.586 6.697,8.283 5.283,9.697 12,16.414 18.717,9.697"/>
-</g>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+    <g id="expand" opacity=".75">
+        <path id="arrow" fill-rule="evenodd" clip-rule="evenodd" d="M17.303 8.283l-5.303 5.303-5.303-5.303-1.414 1.414 6.717 6.717 6.717-6.717z"/>
+    </g>
 </svg>
index c68bdda..09117e1 100644 (file)
@@ -1,12 +1,10 @@
 <?xml version="1.0" encoding="iso-8859-1"?>
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="24px"
-        height="24px" viewBox="0 0 24 24" style="enable-background:new 0 0 24 24;" xml:space="preserve">
-<g id="help" style="opacity:0.75;">
-       <path id="circle" style="fill-rule:evenodd;clip-rule:evenodd;" d="M12.001,2.085c-5.478,0-9.916,4.438-9.916,9.916 c0,5.476,4.438,9.914,9.916,9.914c5.476,0,9.914-4.438,9.914-9.914C21.915,6.523,17.477,2.085,12.001,2.085z M12.002,20.085 c-4.465,0-8.084-3.619-8.084-8.083c0-4.465,3.619-8.084,8.084-8.084c4.464,0,8.083,3.619,8.083,8.084 C20.085,16.466,16.466,20.085,12.002,20.085z"/>
-       <g id="question_mark">
-               <path id="top" style="fill-rule:evenodd;clip-rule:evenodd;" d="M11.766,6.688c-2.5,0-3.219,2.188-3.219,2.188l1.411,0.854 c0,0,0.298-0.791,0.901-1.229c0.516-0.375,1.625-0.625,2.219,0.125c0.701,0.885-0.17,1.587-1.078,2.719 C11.047,12.531,11,15,11,15h1.969c0,0,0.135-2.318,1.041-3.381c0.603-0.707,1.443-1.338,1.443-2.494S14.266,6.688,11.766,6.688z"/>
-               <rect id="bottom" x="11" y="16" style="fill-rule:evenodd;clip-rule:evenodd;" width="2" height="2"/>
-       </g>
-</g>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+    <g id="help" opacity=".75" fill-rule="evenodd" clip-rule="evenodd">
+        <path id="circle" d="M12.001 2.085c-5.478 0-9.916 4.438-9.916 9.916 0 5.476 4.438 9.914 9.916 9.914 5.476 0 9.914-4.438 9.914-9.914 0-5.478-4.438-9.916-9.914-9.916zm.001 18c-4.465 0-8.084-3.619-8.084-8.083 0-4.465 3.619-8.084 8.084-8.084 4.464 0 8.083 3.619 8.083 8.084 0 4.464-3.619 8.083-8.083 8.083z"/>
+        <g id="question_mark">
+            <path id="top" d="M11.766 6.688c-2.5 0-3.219 2.188-3.219 2.188l1.411.854s.298-.791.901-1.229c.516-.375 1.625-.625 2.219.125.701.885-.17 1.587-1.078 2.719-.953 1.186-1 3.655-1 3.655h1.969s.135-2.318 1.041-3.381c.603-.707 1.443-1.338 1.443-2.494s-1.187-2.437-3.687-2.437z"/>
+            <path id="bottom" d="M11 16h2v2h-2z"/>
+        </g>
+    </g>
 </svg>
index 40c0ae3..a89e257 100644 (file)
@@ -1,9 +1,7 @@
 <?xml version="1.0" encoding="iso-8859-1"?>
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="24px"
-        height="24px" viewBox="0 0 24 24" style="enable-background:new 0 0 24 24;" xml:space="preserve">
-<g id="history" style="opacity:0.75;">
-       <path id="clock_hands" style="fill-rule:evenodd;clip-rule:evenodd;" d="M17.26,15.076c0,0-2.385-1.935-4.005-3.062 c0.72-2.397,1.702-6.559,1.702-6.559s-4.35,5.363-4.877,6.699c-0.463,1.168,1.459,2.209,2.346,1.678 C14.326,14.383,17.26,15.076,17.26,15.076z"/>
-       <path id="arrow" style="fill-rule:evenodd;clip-rule:evenodd;" d="M12.086,2.085c-5.478,0-9.916,4.438-9.916,9.916 c0,1.783,0.476,3.454,1.301,4.898l-2.223,2.04h5.688v-5.219l-2.066,1.896c-0.55-1.088-0.866-2.312-0.866-3.615 c0-4.465,3.619-8.084,8.084-8.084c4.464,0,8.083,3.619,8.083,8.084c0,4.464-3.619,8.083-8.083,8.083 c-1.145,0-2.228-0.247-3.213-0.678l-0.833,1.634c1.235,0.557,2.602,0.874,4.045,0.874c5.476,0,9.914-4.438,9.914-9.914 C22,6.523,17.562,2.085,12.086,2.085z"/>
-</g>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+    <g id="history" opacity=".75" fill-rule="evenodd" clip-rule="evenodd">
+        <path id="clock_hands" d="M17.26 15.076s-2.385-1.935-4.005-3.062c.72-2.397 1.702-6.559 1.702-6.559s-4.35 5.363-4.877 6.699c-.463 1.168 1.459 2.209 2.346 1.678 1.9.551 4.834 1.244 4.834 1.244z"/>
+        <path id="arrow" d="M12.086 2.085c-5.478 0-9.916 4.438-9.916 9.916 0 1.783.476 3.454 1.301 4.898l-2.223 2.04h5.688v-5.219l-2.066 1.896c-.55-1.088-.866-2.312-.866-3.615 0-4.465 3.619-8.084 8.084-8.084 4.464 0 8.083 3.619 8.083 8.084 0 4.464-3.619 8.083-8.083 8.083-1.145 0-2.228-.247-3.213-.678l-.833 1.634c1.235.557 2.602.874 4.045.874 5.476 0 9.914-4.438 9.914-9.914-.001-5.477-4.439-9.915-9.915-9.915z"/>
+    </g>
 </svg>
index 8c5672a..22ad9be 100644 (file)
@@ -1,10 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="24" height="24" viewBox="0, 0, 24, 24">
-  <g id="help" opacity="0.75">
-    <path d="M11.499,17 C8.463,17 6,14.536 6,11.5 C6,8.463 8.462,6 11.499,6 C14.536,6 17,8.462 17,11.5 C17,14.536 14.536,17 11.499,17 z M11.501,5 C7.91,5 5,7.91 5,11.5 C5,15.09 7.91,18 11.501,18 C15.089,18 18,15.089 18,11.5 C18,7.911 15.089,5 11.501,5 z" fill="#000000"/>
-    <path d="M12,10 L12,14 L13,14 L13,15 L10,15 L10,14 L11,14 L11,11 L10,11 L10,10 z" fill="#000000"/>
-    <path d="M11,8 L12,8 L12,9 L11,9 z" fill="#000000"/>
-  </g>
-  <defs/>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0, 0, 24, 24">
+    <g id="help" opacity=".75">
+        <path d="M11.499 17c-3.036 0-5.499-2.464-5.499-5.5 0-3.037 2.462-5.5 5.499-5.5 3.037 0 5.501 2.462 5.501 5.5 0 3.036-2.464 5.5-5.501 5.5zm.002-12c-3.591 0-6.501 2.91-6.501 6.5s2.91 6.5 6.501 6.5c3.588 0 6.499-2.911 6.499-6.5s-2.911-6.5-6.499-6.5zM12 10v4h1v1h-3v-1h1v-3h-1v-1zM11 8h1v1h-1z"/>
+    </g>
 </svg>
index dadf69c..7d8a1ef 100644 (file)
@@ -1,15 +1,8 @@
 <?xml version="1.0" encoding="iso-8859-1"?>
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="24px"
-        height="24px" viewBox="0 0 24 24" style="enable-background:new 0 0 24 24;" xml:space="preserve">
-<g id="link" style="opacity:0.75;">
-       <path id="right" d="M19.188,12.001c0,1.1-0.891,2.015-1.988,2.015l-4.195-0.015C13.543,15.089,13.968,16,15.002,16h3
-               C19.658,16,21,13.657,21,12s-1.342-4-2.998-4h-3c-1.034,0-1.459,0.911-1.998,1.999l4.195-0.015
-               C18.297,9.984,19.188,10.901,19.188,12.001z"/>
-       <path id="center" d="M8,12c0,0.535,0.42,1,0.938,1h6.109c0.518,0,0.938-0.465,0.938-1c0-0.534-0.42-1-0.938-1H8.938
-               C8.42,11,8,11.466,8,12z"/>
-       <path id="left" d="M4.816,11.999c0-1.1,0.891-2.015,1.988-2.015L11,9.999C10.461,8.911,10.036,8,9.002,8h-3
-               c-1.656,0-2.998,2.343-2.998,4s1.342,4,2.998,4h3c1.034,0,1.459-0.911,1.998-1.999l-4.195,0.015
-               C5.707,14.016,4.816,13.099,4.816,11.999z"/>
-</g>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+    <g id="link" opacity=".75">
+        <path id="right" d="M19.188 12.001c0 1.1-.891 2.015-1.988 2.015l-4.195-.015c.538 1.088.963 1.999 1.997 1.999h3c1.656 0 2.998-2.343 2.998-4s-1.342-4-2.998-4h-3c-1.034 0-1.459.911-1.998 1.999l4.195-.015c1.098 0 1.989.917 1.989 2.017z"/>
+        <path id="center" d="M8 12c0 .535.42 1 .938 1h6.109c.518 0 .938-.465.938-1 0-.534-.42-1-.938-1h-6.109c-.518 0-.938.466-.938 1z"/>
+        <path id="left" d="M4.816 11.999c0-1.1.891-2.015 1.988-2.015l4.196.015c-.539-1.088-.964-1.999-1.998-1.999h-3c-1.656 0-2.998 2.343-2.998 4s1.342 4 2.998 4h3c1.034 0 1.459-.911 1.998-1.999l-4.195.015c-1.098 0-1.989-.917-1.989-2.017z"/>
+    </g>
 </svg>
index 657fab2..75866f6 100644 (file)
@@ -1,10 +1,6 @@
 <?xml version="1.0" encoding="iso-8859-1"?>
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="24px"
-        height="24px" viewBox="0 0 24 24" style="enable-background:new 0 0 24 24;" xml:space="preserve">
-<g id="menu" style="opacity:0.75;">
-       <path id="lines" d="M6,15h12c0.553,0,1,0.447,1,1v1c0,0.553-0.447,1-1,1H6c-0.553,0-1-0.447-1-1v-1C5,15.447,5.447,15,6,15z M5,11v1
-               c0,0.553,0.447,1,1,1h12c0.553,0,1-0.447,1-1v-1c0-0.553-0.447-1-1-1H6C5.447,10,5,10.447,5,11z M5,6v1c0,0.553,0.447,1,1,1h12
-               c0.553,0,1-0.447,1-1V6c0-0.553-0.447-1-1-1H6C5.447,5,5,5.447,5,6z"/>
-</g>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+    <g id="menu" opacity=".75">
+        <path id="lines" d="M6 15h12c.553 0 1 .447 1 1v1c0 .553-.447 1-1 1h-12c-.553 0-1-.447-1-1v-1c0-.553.447-1 1-1zm-1-4v1c0 .553.447 1 1 1h12c.553 0 1-.447 1-1v-1c0-.553-.447-1-1-1h-12c-.553 0-1 .447-1 1zm0-5v1c0 .553.447 1 1 1h12c.553 0 1-.447 1-1v-1c0-.553-.447-1-1-1h-12c-.553 0-1 .447-1 1z"/>
+    </g>
 </svg>
index a378a5d..3c19c4f 100644 (file)
@@ -1,9 +1,6 @@
 <?xml version="1.0" encoding="iso-8859-1"?>
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="24px"
-        height="24px" viewBox="0 0 24 24" style="enable-background:new 0 0 24 24;" xml:space="preserve">
-<g id="move-ltr" style="opacity:0.75;">
-       <polygon id="arrow" style="fill-rule:evenodd;clip-rule:evenodd;" points="8.935,7.181 14.237,12.483 8.935,17.786
-               10.349,19.2 17.065,12.483 10.349,5.767"/>
-</g>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+    <g id="move-ltr" opacity=".75">
+        <path id="arrow" fill-rule="evenodd" clip-rule="evenodd" d="M8.935 7.181l5.302 5.302-5.302 5.303 1.414 1.414 6.716-6.717-6.716-6.716z"/>
+    </g>
 </svg>
index c0b334b..d9f35c1 100644 (file)
@@ -1,9 +1,6 @@
 <?xml version="1.0" encoding="iso-8859-1"?>
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="24px"
-        height="24px" viewBox="0 0 24 24" style="enable-background:new 0 0 24 24;" xml:space="preserve">
-<g id="move-rtl" style="opacity:0.75;">
-       <polygon id="arrow_9_" style="fill-rule:evenodd;clip-rule:evenodd;" points="15.065,17.786 9.763,12.483 15.065,7.181
-               13.651,5.767 6.935,12.483 13.651,19.2"/>
-</g>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+    <g id="move-rtl" opacity=".75">
+        <path id="arrow_9_" fill-rule="evenodd" clip-rule="evenodd" d="M15.065 17.786l-5.302-5.303 5.302-5.302-1.414-1.414-6.716 6.716 6.716 6.717z"/>
+    </g>
 </svg>
index 078ce10..cd4c0f7 100644 (file)
@@ -1,12 +1,8 @@
 <?xml version="1.0" encoding="iso-8859-1"?>
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="24px"
-        height="24px" viewBox="0 0 24 24" style="enable-background:new 0 0 24 24;" xml:space="preserve">
-<g id="picture" style="opacity:0.75;">
-       <path id="frame" style="fill-rule:evenodd;clip-rule:evenodd;" d="M18,4H6C4,3.993,3,4.993,3,6.993L3.014,16C3,18,4,18.988,6,19h12
-               c2-0.012,2.994-1,3-3.006V6.993C20.994,4.993,20,3.993,18,4z M19,17H5V6h14V17z"/>
-       <polygon id="mountains" style="fill-rule:evenodd;clip-rule:evenodd;" points="6,13.5 9.5,10 11.828,12.312 10.516,13.406
-               11.391,14.438 15.5,11 18,13 18,16 6,16"/>
-       <polygon id="sky" style="fill-rule:evenodd;clip-rule:evenodd;" points="6,12 9.516,7.844 12.562,11.016 15.5,9 18,11 18,7 6,7"/>
-</g>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+    <g id="picture" opacity=".75" fill-rule="evenodd" clip-rule="evenodd">
+        <path id="frame" d="M18 4h-12c-2-.007-3 .993-3 2.993l.014 9.007c-.014 2 .986 2.988 2.986 3h12c2-.012 2.994-1 3-3.006v-9.001c-.006-2-1-3-3-2.993zm1 13h-14v-11h14v11z"/>
+        <path id="mountains" d="M6 13.5l3.5-3.5 2.328 2.312-1.312 1.094.875 1.032 4.109-3.438 2.5 2v3h-12z"/>
+        <path id="sky" d="M6 12l3.516-4.156 3.046 3.172 2.938-2.016 2.5 2v-4h-12z"/>
+    </g>
 </svg>
index b95e7d3..5dd607b 100644 (file)
@@ -1,8 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="24" height="24" viewBox="0, 0, 24, 24">
-  <g id="remove-item">
-    <path d="M8,11 L16,11 L16,13 L8,13 z" fill="#000000"/>
-  </g>
-  <defs/>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0, 0, 24, 24">
+    <g id="remove-item">
+        <path d="M8 11h8v2h-8z"/>
+    </g>
 </svg>
index 17c8d39..06c89d7 100644 (file)
@@ -1,9 +1,6 @@
 <?xml version="1.0" encoding="iso-8859-1"?>
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="24px"
-        height="24px" viewBox="0 0 24 24" style="enable-background:new 0 0 24 24;" xml:space="preserve">
-<g id="remove" style="opacity:0.75;">
-       <path id="trash_can" style="fill-rule:evenodd;clip-rule:evenodd;" d="M12,10h-1v6h1V10z M10,10H9v6h1V10z M14,10h-1v6h1V10z
-                M14,6V5H9v1H6v3h1v7.966l1,1.031v-0.074V18h6.984L15,17.982v0.015l1-1.031V9h1V6H14z M15,17H8V9h7V17z M16,8H7V7h9V8z"/>
-</g>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+    <g id="remove" opacity=".75">
+        <path id="trash_can" d="M12 10h-1v6h1v-6zm-2 0h-1v6h1v-6zm4 0h-1v6h1v-6zm0-4v-1h-5v1h-3v3h1v7.966l1 1.031v-.074.077h6.984l.016-.018v.015l1-1.031v-7.966h1v-3h-3zm1 11h-7v-8h7v8zm1-9h-9v-1h9v1z" fill-rule="evenodd" clip-rule="evenodd"/>
+    </g>
 </svg>
index 37feda4..ff7144c 100644 (file)
@@ -1,13 +1,6 @@
 <?xml version="1.0" encoding="iso-8859-1"?>
-<!-- Generator: Adobe Illustrator 16.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0)  -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="24px"
-        height="24px" viewBox="0 0 24 24" style="enable-background:new 0 0 24 24;" xml:space="preserve">
-<g id="search" style="opacity:0.75;">
-       <path id="magnifying_glass" d="M16.021,15.96l-2.374-2.375c-0.048-0.047-0.105-0.079-0.169-0.099c0.403-0.566,0.643-1.26,0.643-2.009
-               C14.12,9.557,12.563,8,10.644,8c-1.921,0-3.478,1.557-3.478,3.478c0,1.92,1.557,3.477,3.478,3.477c0.749,0,1.442-0.239,2.01-0.643
-               c0.019,0.063,0.051,0.121,0.098,0.169l2.375,2.374c0.19,0.189,0.543,0.143,0.79-0.104S16.21,16.15,16.021,15.96z M10.644,13.69
-               c-1.221,0-2.213-0.991-2.213-2.213c0-1.221,0.992-2.213,2.213-2.213c1.222,0,2.213,0.992,2.213,2.213
-               C12.856,12.699,11.865,13.69,10.644,13.69z"/>
-</g>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+    <g id="search" opacity=".75">
+        <path id="magnifying_glass" d="M16.021 15.96l-2.374-2.375-.169-.099c.403-.566.643-1.26.643-2.009-.001-1.92-1.558-3.477-3.477-3.477-1.921 0-3.478 1.557-3.478 3.478 0 1.92 1.557 3.477 3.478 3.477.749 0 1.442-.239 2.01-.643l.098.169 2.375 2.374c.19.189.543.143.79-.104s.293-.601.104-.791zm-5.377-2.27c-1.221 0-2.213-.991-2.213-2.213 0-1.221.992-2.213 2.213-2.213 1.222 0 2.213.992 2.213 2.213-.001 1.222-.992 2.213-2.213 2.213z"/>
+    </g>
 </svg>
index 1464a79..cbc4efc 100644 (file)
@@ -1,16 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="24" height="24" viewBox="0, 0, 24, 24">
-  <g id="settings" opacity="0.75">
-    <path d="M3,4 L6,4 L6,6 L3,6 z" fill="#000000"/>
-    <path d="M12,4 L21,4 L21,6 L12,6 z" fill="#000000"/>
-    <path d="M8,3 L10,3 C10.552,3 11,3.448 11,4 L11,6 C11,6.552 10.552,7 10,7 L8,7 C7.448,7 7,6.552 7,6 L7,4 C7,3.448 7.448,3 8,3 z" fill="#000000"/>
-    <path d="M3,11 L12,11 L12,13 L3,13 z" fill="#000000"/>
-    <path d="M18,11 L21,11 L21,13 L18,13 z" fill="#000000"/>
-    <path d="M14,10 L16,10 C16.552,10 17,10.448 17,11 L17,13 C17,13.552 16.552,14 16,14 L14,14 C13.448,14 13,13.552 13,13 L13,11 C13,10.448 13.448,10 14,10 z" fill="#000000"/>
-    <path d="M3,18 L9,18 L9,20 L3,20 z" fill="#000000"/>
-    <path d="M15,18 L21,18 L21,20 L15,20 z" fill="#000000"/>
-    <path d="M11,17 L13,17 C13.552,17 14,17.448 14,18 L14,20 C14,20.552 13.552,21 13,21 L11,21 C10.448,21 10,20.552 10,20 L10,18 C10,17.448 10.448,17 11,17 z" fill="#000000"/>
-  </g>
-  <defs/>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0, 0, 24, 24">
+    <g id="settings" opacity=".75">
+        <path d="M3 4h3v2h-3zM12 4h9v2h-9zM8 3h2c.552 0 1 .448 1 1v2c0 .552-.448 1-1 1h-2c-.552 0-1-.448-1-1v-2c0-.552.448-1 1-1zM3 11h9v2h-9zM18 11h3v2h-3zM14 10h2c.552 0 1 .448 1 1v2c0 .552-.448 1-1 1h-2c-.552 0-1-.448-1-1v-2c0-.552.448-1 1-1zM3 18h6v2h-6zM15 18h6v2h-6zM11 17h2c.552 0 1 .448 1 1v2c0 .552-.448 1-1 1h-2c-.552 0-1-.448-1-1v-2c0-.552.448-1 1-1z"/>
+    </g>
 </svg>
index d21e5e3..496e7fc 100644 (file)
@@ -1,11 +1,6 @@
 <?xml version="1.0" encoding="iso-8859-1"?>
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="24px"
-        height="24px" viewBox="0 0 24 24" style="enable-background:new 0 0 24 24;" xml:space="preserve">
-<g id="tag" style="opacity:0.75;">
-       <path d="M18.748,11.717c0.389,0.389,0.389,1.025,0,1.414l-4.949,4.95c-0.389,0.389-1.025,0.389-1.414,0l-6.01-6.01
-               c-0.389-0.389-0.707-1.157-0.707-1.707L5.667,6c0-0.55,0.45-1,1-1h4.364c0.55,0,1.318,0.318,1.707,0.707L18.748,11.717z
-                M8.104,7.456C7.525,8.032,7.526,8.97,8.103,9.549c0.578,0.577,1.516,0.577,2.095,0.001c0.576-0.578,0.576-1.517,0-2.095
-               C9.617,6.879,8.68,6.878,8.104,7.456z"/>
-</g>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+    <g id="tag" opacity=".75">
+        <path d="M18.748 11.717c.389.389.389 1.025 0 1.414l-4.949 4.95c-.389.389-1.025.389-1.414 0l-6.01-6.01c-.389-.389-.707-1.157-.707-1.707l-.001-4.364c0-.55.45-1 1-1h4.364c.55 0 1.318.318 1.707.707l6.01 6.01zm-10.644-4.261c-.579.576-.578 1.514-.001 2.093.578.577 1.516.577 2.095.001.576-.578.576-1.517 0-2.095-.581-.576-1.518-.577-2.094.001z"/>
+    </g>
 </svg>
index 621cf2c..ad12773 100644 (file)
@@ -1,10 +1,7 @@
 <?xml version="1.0" encoding="iso-8859-1"?>
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="24px"
-        height="24px" viewBox="0 0 24 24" style="enable-background:new 0 0 24 24;" xml:space="preserve">
-<g id="window" style="opacity:0.75;">
-       <rect id="title" x="7" y="10" width="10" height="1"/>
-       <path id="window" d="M16,19H8c-2.206,0-4-1.794-4-4V9c0-2.206,1.794-4,4-4h8c2.206,0,4,1.794,4,4v6C20,17.206,18.206,19,16,19z
-                M8,7C6.897,7,6,7.897,6,9v6c0,1.103,0.897,2,2,2h8c1.103,0,2-0.897,2-2V9c0-1.103-0.897-2-2-2H8z"/>
-</g>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+    <g id="window" opacity=".75">
+        <path id="title" d="M7 10h10v1h-10z"/>
+        <path id="window" d="M16 19h-8c-2.206 0-4-1.794-4-4v-6c0-2.206 1.794-4 4-4h8c2.206 0 4 1.794 4 4v6c0 2.206-1.794 4-4 4zm-8-12c-1.103 0-2 .897-2 2v6c0 1.103.897 2 2 2h8c1.103 0 2-.897 2-2v-6c0-1.103-.897-2-2-2h-8z"/>
+    </g>
 </svg>
index e549b17..7cfde44 100644 (file)
@@ -1,9 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="12px"
-        height="12px" viewBox="0 0 12 12">
-  <g id="deprecated" opacity="0.75">
-    <path d="M6,12 C2.686,12 -0,9.314 -0,6 C-0,2.686 2.686,-0 6,-0 C9.314,-0 12,2.686 12,6 C12,9.314 9.314,12 6,12 z M5,7 L7,7 L7,2 L5,2 z M5,10 L7,10 L7,8 L5,8 z"/>
-  </g>
-  <defs/>
+<svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 12 12">
+    <g id="deprecated" opacity=".75">
+        <path d="M6 12c-3.314 0-6-2.686-6-6s2.686-6 6-6 6 2.686 6 6-2.686 6-6 6zm-1-5h2v-5h-2zm0 3h2v-2h-2z"/>
+    </g>
 </svg>
index 89c21e3..d345ec0 100644 (file)
@@ -1,8 +1,6 @@
 <?xml version="1.0" encoding="iso-8859-1"?>
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="12px"
-        height="12px" viewBox="0 0 12 12">
-<g id="down" style="opacity:0.75;">
-       <polygon id="arrow" points="2,3 5.5,9 9,3"/>
-</g>
+<svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 12 12">
+    <g id="down" opacity=".75">
+        <path id="arrow" d="M2 3l3.5 6 3.5-6z"/>
+    </g>
 </svg>
index ad87640..5092d88 100644 (file)
@@ -1,8 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="12px"
-        height="12px" viewBox="0 0 12 12">
-<g id="ltr" opacity="0.75">
-       <path id="arrow" d="M3,9 L3,2 L9,5.5 z"/>
-</g>
+<svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 12 12">
+    <g id="ltr" opacity=".75">
+        <path id="arrow" d="M3 9v-7l6 3.5z"/>
+    </g>
 </svg>
index 010b24e..8d39de8 100644 (file)
@@ -1,8 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="12px"
-        height="12px" viewBox="0 0 12 12">
-<g id="rtl" opacity="0.75">
-       <path id="arrow" d="M3,5.5 L9,9 L9,2 z"/>
-</g>
+<svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 12 12">
+    <g id="rtl" opacity=".75">
+        <path id="arrow" d="M3 5.5l6 3.5v-7z"/>
+    </g>
 </svg>
index bbc2b3c..78e0115 100644 (file)
@@ -1,8 +1,6 @@
 <?xml version="1.0" encoding="iso-8859-1"?>
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="12px"
-        height="12px" viewBox="0 0 12 12">
-<g id="up" style="opacity:0.75;">
-       <polygon id="arrow" points="5.5,2 2,8 9,8"/>
-</g>
+<svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 12 12">
+    <g id="up" opacity=".75">
+        <path id="arrow" d="M5.5 2l-3.5 6h7z"/>
+    </g>
 </svg>
index d8b36b1..45035f4 100644 (file)
@@ -1,11 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="12px"
-        height="12px" viewBox="0 0 12 12">
-  <g id="required" opacity="0.75">
-    <path d="M5,1 L7,1 L7,11 L5,11 z"/>
-    <path d="M9.83,2.634 L10.83,4.366 L2.17,9.366 L1.17,7.634 z"/>
-    <path d="M1.17,4.366 L2.17,2.634 L10.83,7.634 L9.83,9.366 z"/>
-  </g>
-  <defs/>
+<svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 12 12">
+    <g id="required" opacity=".75">
+        <path d="M5 1h2v10h-2zM9.83 2.634l1 1.732-8.66 5-1-1.732zM1.17 4.366l1-1.732 8.66 5-1 1.732z"/>
+    </g>
 </svg>
index 3e0bfb9..dc999cd 100644 (file)
@@ -1,12 +1,12 @@
 /*!
- * OOjs UI v0.1.0-pre (a63f03882e)
+ * OOjs UI v0.1.0-pre (85cfc2e735)
  * 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: 2014-06-27T23:51:18Z
+ * Date: 2014-07-03T02:33:09Z
  */
 .oo-ui-dialog-content .oo-ui-window-closeButton {
   position: absolute;
index e651ff0..7018b52 100644 (file)
@@ -1,12 +1,12 @@
 /*!
- * OOjs UI v0.1.0-pre (a63f03882e)
+ * OOjs UI v0.1.0-pre (85cfc2e735)
  * 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: 2014-06-27T23:51:18Z
+ * Date: 2014-07-03T02:33:09Z
  */
 .oo-ui-dialog {
   background-color: #fff;
index 0262042..f2e3202 100644 (file)
@@ -1,12 +1,12 @@
 /*!
- * OOjs UI v0.1.0-pre (a63f03882e)
+ * OOjs UI v0.1.0-pre (85cfc2e735)
  * 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: 2014-06-27T23:51:18Z
+ * Date: 2014-07-03T02:33:09Z
  */
 ( function ( OO ) {
 
@@ -750,6 +750,9 @@ OO.ui.Frame.static.transplantStyles = function ( parentDoc, frameDoc, timeout )
 
        for ( i = 0, numSheets = parentDoc.styleSheets.length; i < numSheets; i++ ) {
                styleNode = parentDoc.styleSheets[i].ownerNode;
+               if ( styleNode.disabled ) {
+                       continue;
+               }
                if ( styleNode.nodeName.toLowerCase() === 'link' ) {
                        // External stylesheet
                        // Create a node with a unique ID that we're going to monitor to see when the CSS
@@ -2136,11 +2139,12 @@ OO.ui.ButtonedElement = function OoUiButtonedElement( $button, config ) {
        this.$button.on( 'mousedown', OO.ui.bind( this.onMouseDown, this ) );
 
        // Initialization
-       this.$element.addClass( 'oo-ui-buttonedElement' );
+       this.$element
+               .addClass( 'oo-ui-buttonedElement' )
+               .prop( 'tabIndex', config.tabIndex || 0 );
        this.$button
                .addClass( 'oo-ui-buttonedElement-button' )
-               .attr( 'role', 'button' )
-               .prop( 'tabIndex', config.tabIndex || 0 );
+               .attr( 'role', 'button' );
        if ( config.frameless ) {
                this.$element.addClass( 'oo-ui-buttonedElement-frameless' );
        } else {
@@ -3118,7 +3122,9 @@ OO.ui.Tool = function OoUiTool( toolGroup, config ) {
        this.$title.addClass( 'oo-ui-tool-title' );
        this.$link
                .addClass( 'oo-ui-tool-link' )
-               .append( this.$icon, this.$title );
+               .append( this.$icon, this.$title )
+               .prop( 'tabIndex', 0 )
+               .attr( 'role', 'button' );
        this.$element
                .data( 'oo-ui-tool', this )
                .addClass(
index a568a6d..a249314 100644 (file)
@@ -1,12 +1,12 @@
 /*!
- * OOjs UI v0.1.0-pre (a63f03882e)
+ * OOjs UI v0.1.0-pre (85cfc2e735)
  * 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: 2014-06-27T23:51:18Z
+ * Date: 2014-07-03T02:33:09Z
  */
 /* Textures */
 
diff --git a/resources/lib/sinonjs/sinon-1.10.3.js b/resources/lib/sinonjs/sinon-1.10.3.js
new file mode 100644 (file)
index 0000000..703414d
--- /dev/null
@@ -0,0 +1,5073 @@
+/**
+ * Sinon.JS 1.10.3, 2014/07/11
+ *
+ * @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 if (typeof fn === "function") { formatio = fn(samsam); } }
+define.amd = {};
+((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 isReallyNaN(val) {
+        return typeof val === 'number' && isNaN(val);
+    }
+
+    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");
+            } else if (wrappedMethod.restore && wrappedMethod.restore.sinon) {
+                error = new TypeError("Attempted to wrap " + property + " which is already wrapped");
+            } else 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 && 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') {
+                if (isReallyNaN(a) && isReallyNaN(b)) {
+                    return true;
+                } else {
+                    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 (!(prop in b)) {
+                    return false;
+                }
+
+                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 && typeof require == "function";
+    var isAMD = typeof define === 'function' && typeof define.amd === 'object' && define.amd;
+
+    function makePublicAPI(require, exports, module) {
+        module.exports = sinon;
+        sinon.spy = require("./sinon/spy");
+        sinon.spyCall = require("./sinon/call");
+        sinon.behavior = require("./sinon/behavior");
+        sinon.stub = require("./sinon/stub");
+        sinon.mock = require("./sinon/mock");
+        sinon.collection = require("./sinon/collection");
+        sinon.assert = require("./sinon/assert");
+        sinon.sandbox = require("./sinon/sandbox");
+        sinon.test = require("./sinon/test");
+        sinon.testCase = require("./sinon/test_case");
+        sinon.match = require("./sinon/match");
+    }
+
+    if (isAMD) {
+        define(makePublicAPI);
+    } else if (isNode) {
+        try {
+            formatio = require("formatio");
+        } catch (e) {}
+        makePublicAPI(require, exports, module);
+    }
+
+    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 && typeof require == "function";
+
+    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");
+
+    sinon.match = match;
+
+    if (typeof define === "function" && define.amd) {
+        define(["module"], function(module) { module.exports = match; });
+    } else if (commonJSModule) {
+        module.exports = 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 && typeof require == "function";
+    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
+
+    sinon.spyCall = createSpyCall;
+
+    if (typeof define === "function" && define.amd) {
+        define(["module"], function(module) { module.exports = createSpyCall; });
+    } else if (commonJSModule) {
+        module.exports = 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 && typeof require == "function";
+    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++);
+
+            // Make call properties available from within the spied function:
+            createCallProperties.call(this);
+
+            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);
+
+            // Make return value and exception available in the calls:
+            createCallProperties.call(this);
+
+            if (exception !== undefined) {
+                throw exception;
+            }
+
+            return returnValue;
+        },
+
+        named: function named(name) {
+            this.displayName = name;
+            return this;
+        },
+
+        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;
+    sinon.spy = spy;
+
+    if (typeof define === "function" && define.amd) {
+        define(["module"], function(module) { module.exports = spy; });
+    } else if (commonJSModule) {
+        module.exports = 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 && typeof require == "function";
+
+    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);
+        }
+    }
+
+    sinon.behavior = proto;
+
+    if (typeof define === "function" && define.amd) {
+        define(["module"], function(module) { module.exports = proto; });
+    } else if (commonJSModule) {
+        module.exports = 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 && typeof require == "function";
+
+    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;
+    }()));
+
+    sinon.stub = stub;
+
+    if (typeof define === "function" && define.amd) {
+        define(["module"], function(module) { module.exports = stub; });
+    } else if (commonJSModule) {
+        module.exports = 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 && typeof require == "function";
+    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;
+            }
+        };
+    }());
+
+    sinon.mock = mock;
+
+    if (typeof define === "function" && define.amd) {
+        define(["module"], function(module) { module.exports = mock; });
+    } else if (commonJSModule) {
+        module.exports = 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 && typeof require == "function";
+    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;
+        }
+    };
+
+    sinon.collection = collection;
+
+    if (typeof define === "function" && define.amd) {
+        define(["module"], function(module) { module.exports = collection; });
+    } else if (commonJSModule) {
+        module.exports = 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) {
+    // node expects setTimeout/setInterval to return a fn object w/ .ref()/.unref()
+    // browsers, a number.
+    // see https://github.com/cjohansen/Sinon.JS/pull/436
+    var timeoutResult = setTimeout(function() {}, 0);
+    var addTimerReturnsObject = typeof timeoutResult === 'object';
+    clearTimeout(timeoutResult);
+
+    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;
+        }
+
+        if (addTimerReturnsObject) {
+            return {
+                id: toId,
+                ref: function() {},
+                unref: function() {}
+            };
+        }
+        else {
+            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 (!timerId) {
+                // null appears to be allowed in most browsers, and appears to be relied upon by some libraries, like Bootstrap carousel
+                return;
+            }
+            if (!this.timeouts) {
+                this.timeouts = [];
+            }
+            // in Node, timerId is an object with .ref()/.unref(), and
+            // its .id field is the actual timer id.
+            if (typeof timerId === 'object') {
+              timerId = timerId.id
+            }
+            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 = xhr.supportsXHR && '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;
+
+})((function(){ return 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;
+    }
+
+    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);
+            }
+        },
+
+        log: function(response, request) {
+            var str;
+
+            str =  "Request:\n"  + sinon.format(request)  + "\n\n";
+            str += "Response:\n" + sinon.format(response) + "\n\n";
+
+            sinon.log(str);
+        },
+
+        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, queue.length);
+            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) {
+                    sinon.fakeServer.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 && typeof require == "function") {
+    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 define === "function" && define.amd) {
+        define(["module"], function(module) { module.exports = sinon.sandbox; });
+    } else 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 && typeof require == "function";
+
+    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);
+        }
+
+        function sinonSandboxedTest() {
+            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;
+        };
+
+        if (callback.length) {
+            return function sinonAsyncSandboxedTest(callback) {
+                return sinonSandboxedTest.apply(this, arguments);
+            };
+        }
+
+        return sinonSandboxedTest;
+    }
+
+    test.config = {
+        injectIntoThis: true,
+        injectInto: null,
+        properties: ["spy", "stub", "mock", "clock", "server", "requests"],
+        useFakeTimers: true,
+        useFakeServer: true
+    };
+
+    sinon.test = test;
+
+    if (typeof define === "function" && define.amd) {
+        define(["module"], function(module) { module.exports = test; });
+    } else if (commonJSModule) {
+        module.exports = 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 && typeof require == "function";
+
+    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;
+    }
+
+    sinon.testCase = testCase;
+
+    if (typeof define === "function" && define.amd) {
+        define(["module"], function(module) { module.exports = testCase; });
+    } else if (commonJSModule) {
+        module.exports = 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 && typeof require == "function";
+    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");
+
+    sinon.assert = assert;
+
+    if (typeof define === "function" && define.amd) {
+        define(["module"], function(module) { module.exports = assert; });
+    } else if (commonJSModule) {
+        module.exports = assert;
+    }
+}(typeof sinon == "object" && sinon || null, typeof window != "undefined" ? window : (typeof self != "undefined") ? self : global));
+
+/**
+ * @depend ../../sinon.js
+ * @depend event.js
+ */
+/*jslint eqeqeq: false, onevar: false*/
+/*global sinon, module, require, XDomainRequest*/
+/**
+ * Fake XDomainRequest object
+ */
+
+if (typeof sinon == "undefined") {
+    this.sinon = {};
+}
+sinon.xdr = { XDomainRequest: this.XDomainRequest };
+
+// wrapper for global
+(function (global) {
+    var xdr = sinon.xdr;
+    xdr.GlobalXDomainRequest = global.XDomainRequest;
+    xdr.supportsXDR = typeof xdr.GlobalXDomainRequest != "undefined";
+    xdr.workingXDR = xdr.supportsXDR ? xdr.GlobalXDomainRequest :  false;
+
+    function FakeXDomainRequest() {
+        this.readyState = FakeXDomainRequest.UNSENT;
+        this.requestBody = null;
+        this.requestHeaders = {};
+        this.status = 0;
+        this.timeout = null;
+
+        if (typeof FakeXDomainRequest.onCreate == "function") {
+            FakeXDomainRequest.onCreate(this);
+        }
+    }
+
+    function verifyState(xdr) {
+        if (xdr.readyState !== FakeXDomainRequest.OPENED) {
+            throw new Error("INVALID_STATE_ERR");
+        }
+
+        if (xdr.sendFlag) {
+            throw new Error("INVALID_STATE_ERR");
+        }
+    }
+
+    function verifyRequestSent(xdr) {
+        if (xdr.readyState == FakeXDomainRequest.UNSENT) {
+            throw new Error("Request not sent");
+        }
+        if (xdr.readyState == FakeXDomainRequest.DONE) {
+            throw new Error("Request done");
+        }
+    }
+
+    function verifyResponseBodyType(body) {
+        if (typeof body != "string") {
+            var error = new Error("Attempted to respond to fake XDomainRequest with " +
+                                  body + ", which is not a string.");
+            error.name = "InvalidBodyException";
+            throw error;
+        }
+    }
+
+    sinon.extend(FakeXDomainRequest.prototype, sinon.EventTarget, {
+        open: function open(method, url) {
+            this.method = method;
+            this.url = url;
+
+            this.responseText = null;
+            this.sendFlag = false;
+
+            this.readyStateChange(FakeXDomainRequest.OPENED);
+        },
+
+        readyStateChange: function readyStateChange(state) {
+            this.readyState = state;
+            var eventName = '';
+            switch (this.readyState) {
+            case FakeXDomainRequest.UNSENT:
+                break;
+            case FakeXDomainRequest.OPENED:
+                break;
+            case FakeXDomainRequest.LOADING:
+                if (this.sendFlag){
+                    //raise the progress event
+                    eventName = 'onprogress';
+                }
+                break;
+            case FakeXDomainRequest.DONE:
+                if (this.isTimeout){
+                    eventName = 'ontimeout'
+                }
+                else if (this.errorFlag || (this.status < 200 || this.status > 299)) {
+                    eventName = 'onerror';
+                }
+                else {
+                    eventName = 'onload'
+                }
+                break;
+            }
+
+            // raising event (if defined)
+            if (eventName) {
+                if (typeof this[eventName] == "function") {
+                    try {
+                        this[eventName]();
+                    } catch (e) {
+                        sinon.logError("Fake XHR " + eventName + " handler", e);
+                    }
+                }
+            }
+        },
+
+        send: function send(data) {
+            verifyState(this);
+
+            if (!/^(get|head)$/i.test(this.method)) {
+                this.requestBody = data;
+            }
+            this.requestHeaders["Content-Type"] = "text/plain;charset=utf-8";
+
+            this.errorFlag = false;
+            this.sendFlag = true;
+            this.readyStateChange(FakeXDomainRequest.OPENED);
+
+            if (typeof this.onSend == "function") {
+                this.onSend(this);
+            }
+        },
+
+        abort: function abort() {
+            this.aborted = true;
+            this.responseText = null;
+            this.errorFlag = true;
+
+            if (this.readyState > sinon.FakeXDomainRequest.UNSENT && this.sendFlag) {
+                this.readyStateChange(sinon.FakeXDomainRequest.DONE);
+                this.sendFlag = false;
+            }
+        },
+
+        setResponseBody: function setResponseBody(body) {
+            verifyRequestSent(this);
+            verifyResponseBodyType(body);
+
+            var chunkSize = this.chunkSize || 10;
+            var index = 0;
+            this.responseText = "";
+
+            do {
+                this.readyStateChange(FakeXDomainRequest.LOADING);
+                this.responseText += body.substring(index, index + chunkSize);
+                index += chunkSize;
+            } while (index < body.length);
+
+            this.readyStateChange(FakeXDomainRequest.DONE);
+        },
+
+        respond: function respond(status, contentType, body) {
+            // content-type ignored, since XDomainRequest does not carry this
+            // we keep the same syntax for respond(...) as for FakeXMLHttpRequest to ease
+            // test integration across browsers
+            this.status = typeof status == "number" ? status : 200;
+            this.setResponseBody(body || "");
+        },
+
+        simulatetimeout: function(){
+            this.status = 0;
+            this.isTimeout = true;
+            // Access to this should actually throw an error
+            this.responseText = undefined;
+            this.readyStateChange(FakeXDomainRequest.DONE);
+        }
+    });
+
+    sinon.extend(FakeXDomainRequest, {
+        UNSENT: 0,
+        OPENED: 1,
+        LOADING: 3,
+        DONE: 4
+    });
+
+    sinon.useFakeXDomainRequest = function () {
+        sinon.FakeXDomainRequest.restore = function restore(keepOnCreate) {
+            if (xdr.supportsXDR) {
+                global.XDomainRequest = xdr.GlobalXDomainRequest;
+            }
+
+            delete sinon.FakeXDomainRequest.restore;
+
+            if (keepOnCreate !== true) {
+                delete sinon.FakeXDomainRequest.onCreate;
+            }
+        };
+        if (xdr.supportsXDR) {
+            global.XDomainRequest = sinon.FakeXDomainRequest;
+        }
+        return sinon.FakeXDomainRequest;
+    };
+
+    sinon.FakeXDomainRequest = FakeXDomainRequest;
+})(this);
+
+if (typeof module == "object" && typeof require == "function") {
+    module.exports = sinon;
+}
+
+return sinon;}.call(typeof window != 'undefined' && window || {}));
diff --git a/resources/lib/sinonjs/sinon-1.9.0.js b/resources/lib/sinonjs/sinon-1.9.0.js
deleted file mode 100644 (file)
index 428b729..0000000
+++ /dev/null
@@ -1,4794 +0,0 @@
-/**
- * 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/lib/sinonjs/sinon-ie-1.10.3.js b/resources/lib/sinonjs/sinon-ie-1.10.3.js
new file mode 100644 (file)
index 0000000..de8c23d
--- /dev/null
@@ -0,0 +1,100 @@
+/**
+ * Sinon.JS 1.10.3, 2014/07/11
+ *
+ * @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;
+/*global sinon*/
+/**
+ * Helps IE run the fake XDomainRequest. 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 XDR to work in IE, don't include this file.
+ */
+function XDomainRequest() {}
+
+// Reassign the original function. Now its writable attribute
+// should be true. Hackish, I know, but it works.
+XDomainRequest = sinon.xdr.XDomainRequest || undefined;
diff --git a/resources/lib/sinonjs/sinon-ie-1.9.0.js b/resources/lib/sinonjs/sinon-ie-1.9.0.js
deleted file mode 100644 (file)
index c9fbd9d..0000000
+++ /dev/null
@@ -1,86 +0,0 @@
-/**
- * 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 d14c64b..a4039d8 100644 (file)
@@ -2,14 +2,17 @@
  * Skip function for es5-shim module.
  *
  * Test for strict mode as a proxy for full ES5 function support (but not syntax)
- * Per http://kangax.github.io/compat-table/es5/ this is a reasonable short-cut
- * that still allows this to be as short as possible (there are no function "No"s
- * for non-"obsolete" real browsers where strict support is available).
+ * Per http://kangax.github.io/compat-table/es5/ this is a reasonable shortcut
+ * that still allows this to be as short as possible (there are no browsers we
+ * support that have strict mode, but lack other features).
  *
- * Note that this will cause IE9 users to get the shim (which should be close to
- * a no-op but will increase page payload).
+ * Do explicitly test for Function#bind because of PhantomJS (which implements
+ * strict mode, but lacks Function#bind).
+ *
+ * IE9 supports all features except strict mode, so loading es5-shim should be close to
+ * a no-op but does increase page payload).
  */
 return ( function () {
        'use strict';
-       return !this;
+       return !this && !!Function.prototype.bind;
 }() );
index 485d9c0..915cd85 100644 (file)
@@ -2,5 +2,5 @@
        mw.log.deprecate( $, 'toJSON', $.toJSON, 'Use JSON.stringify instead (module "json" for polyfill).' );
        mw.log.deprecate( $, 'evalJSON', $.evalJSON, 'Use JSON.parse instead (module "json" for polyfill).' );
        mw.log.deprecate( $, 'secureEvalJSON', $.secureEvalJSON, 'Use JSON.parse instead (module "json" for polyfill).' );
-       mw.log.deprecate( $, 'quoteString', $.quoteString, 'Use JSON.parse instead (module "json" for polyfill).' );
+       mw.log.deprecate( $, 'quoteString', $.quoteString, 'Use JSON.stringify instead (module "json" for polyfill).' );
 }( mediaWiki, jQuery ) );
index b3e8193..1931aad 100644 (file)
@@ -7,7 +7,7 @@
 /* Layout helpers
 ----------------------------------*/
 .ui-helper-hidden { display: none; }
-.ui-helper-hidden-accessible { position: absolute; left: -99999999px; }
+.ui-helper-hidden-accessible { border: 0; clip: rect(0 0 0 0); height: 1px; margin: -1px; overflow: hidden; padding: 0; position: absolute; width: 1px; }
 .ui-helper-reset { margin: 0; padding: 0; border: 0; outline: 0; line-height: 1.3; text-decoration: none; font-size: 100%; list-style: none; }
 .ui-helper-clearfix:after { content: "."; display: block; height: 0; clear: both; visibility: hidden; }
 .ui-helper-clearfix { display: inline-block; }
index 05745f8..a4dc33b 100644 (file)
                        } else {
                                collapsibleId = $collapsible.attr( 'id' ) || '';
                                if ( collapsibleId.indexOf( 'mw-customcollapsible-' ) === 0 ) {
-                                       $customTogglers = $( '.' + collapsibleId.replace( 'mw-customcollapsible', 'mw-customtoggle' ) );
-                                       $customTogglers.addClass( 'mw-customtoggle' );
+                                       $customTogglers = $( '.' + collapsibleId.replace( 'mw-customcollapsible', 'mw-customtoggle' ) )
+                                               .addClass( 'mw-customtoggle' );
                                }
                        }
 
                                        togglingHandler( $( this ), $collapsible, e, opts );
                                };
 
-                               $toggleLink = $customTogglers;
-                               $toggleLink.on( 'click.mw-collapsible keypress.mw-collapsible', actionHandler );
+                               $toggleLink = $customTogglers
+                                       .on( 'click.mw-collapsible keypress.mw-collapsible', actionHandler )
+                                       .prop( 'tabIndex', 0 );
 
                        } else {
                                // If this is not a custom case, do the default: wrap the
                                                        $toggleLink = buildDefaultToggleLink().appendTo( $caption );
                                                } else {
                                                        actionHandler = premadeToggleHandler;
-                                                       $toggleLink = $toggle.on( 'click.mw-collapsible keypress.mw-collapsible', actionHandler );
+                                                       $toggleLink = $toggle.on( 'click.mw-collapsible keypress.mw-collapsible', actionHandler )
+                                                               .prop( 'tabIndex', 0 );
                                                }
                                        } else {
                                                // The toggle-link will be in one the the cells (td or th) of the first row
                                                        $toggleLink = buildDefaultToggleLink().prependTo( $firstItem.eq( -1 ) );
                                                } else {
                                                        actionHandler = premadeToggleHandler;
-                                                       $toggleLink = $toggle.on( 'click.mw-collapsible keypress.mw-collapsible', actionHandler );
+                                                       $toggleLink = $toggle.on( 'click.mw-collapsible keypress.mw-collapsible', actionHandler )
+                                                               .prop( 'tabIndex', 0 );
                                                }
                                        }
 
                                                $toggleLink.wrap( '<li class="mw-collapsible-toggle-li"></li>' ).parent().prependTo( $collapsible );
                                        } else {
                                                actionHandler = premadeToggleHandler;
-                                               $toggleLink = $toggle.on( 'click.mw-collapsible keypress.mw-collapsible', actionHandler );
+                                               $toggleLink = $toggle.on( 'click.mw-collapsible keypress.mw-collapsible', actionHandler )
+                                                       .prop( 'tabIndex', 0 );
                                        }
 
                                } else { // <div>, <p> etc.
                                                $toggleLink = buildDefaultToggleLink().prependTo( $collapsible );
                                        } else {
                                                actionHandler = premadeToggleHandler;
-                                               $toggleLink = $toggle.on( 'click.mw-collapsible keypress.mw-collapsible', actionHandler );
+                                               $toggleLink = $toggle.on( 'click.mw-collapsible keypress.mw-collapsible', actionHandler )
+                                                       .prop( 'tabIndex', 0 );
                                        }
                                }
                        }
 
-                       // Attributes for accessibility. This isn't necessary when the toggler is already
-                       // an <a> or a <button> etc., but it doesn't hurt either, and it's consistent.
-                       $toggleLink.prop( 'tabIndex', 0 );
-
                        // Initial state
                        if ( options.collapsed || $collapsible.hasClass( 'mw-collapsed' ) ) {
                                // One toggler can hook to multiple elements, and one element can have
index d6dfedd..8d38401 100644 (file)
@@ -12,7 +12,7 @@
  *
  * @author Timo Tijhof, 2011-2012
  */
-( function ( $ ) {
+( function ( mw, $ ) {
        'use strict';
 
        var util,
@@ -64,6 +64,8 @@
         *  were not called from that instance.
         */
        function CompletenessTest( masterVariable, ignoreFn ) {
+               var warn,
+                       that = this;
 
                // Keep track in these objects. Keyed by strings with the
                // method names (ie. 'my.foo', 'my.bar', etc.) values are boolean true.
                this.lazyLimit = 2000;
                this.lazyCounter = 0;
 
-               var that = this;
-
                // Bind begin and end to QUnit.
                QUnit.begin( function () {
-                       that.walkTheObject( null, masterVariable, masterVariable, [], CompletenessTest.ACTION_INJECT );
-                       log( 'CompletenessTest/walkTheObject/ACTION_INJECT', that );
+                       // Suppress warnings (e.g. deprecation notices for accessing the properties)
+                       warn = mw.log.warn;
+                       mw.log.warn = $.noop;
+
+                       that.walkTheObject( masterVariable, null, masterVariable, [] );
+                       log( 'CompletenessTest/walkTheObject', that );
+
+                       // Restore warnings
+                       mw.log.warn = warn;
+                       warn = undefined;
                });
 
                QUnit.done( function () {
                return this;
        }
 
-       /* Static members */
-       CompletenessTest.ACTION_INJECT = 500;
-       CompletenessTest.ACTION_CHECK = 501;
-
        /* Public methods */
        CompletenessTest.fn = CompletenessTest.prototype = {
 
                 *  Initially this is the same as currVar.
                 * @param parentPathArray {Array} Array of names that indicate our breadcrumb path starting at
                 *  masterVariable. Not including currName.
-                * @param action {Number} What is this function supposed to do (ACTION_INJECT or ACTION_CHECK)
                 */
-               walkTheObject: function ( currName, currVar, masterVariable, parentPathArray, action ) {
-                       var key, value, currPathArray,
-                               type = util.type( currVar ),
-                               that = this;
+               walkTheObject: function ( currObj, currName, masterVariable, parentPathArray ) {
+                       var key, currVal, type,
+                               ct = this,
+                               currPathArray = parentPathArray;
 
-                       currPathArray = parentPathArray;
                        if ( currName ) {
                                currPathArray.push( currName );
+                               currVal = currObj[currName];
+                       } else {
+                               currName = '(root)';
+                               currVal = currObj;
                        }
 
+                       type = util.type( currVal );
+
                        // Hard ignores
-                       if ( this.ignoreFn( currVar, that, currPathArray ) ) {
+                       if ( this.ignoreFn( currVal, this, currPathArray ) ) {
                                return null;
                        }
 
 
                        // Functions
                        if ( type === 'function' ) {
-
-                               if ( !currVar.prototype || util.isEmptyObject( currVar.prototype ) ) {
-
-                                       if ( action === CompletenessTest.ACTION_INJECT ) {
-
-                                               that.injectionTracker[ currPathArray.join( '.' ) ] = true;
-                                               that.injectCheck( masterVariable, currPathArray, function () {
-                                                       that.methodCallTracker[ currPathArray.join( '.' ) ] = true;
-                                               } );
-                                       }
-
-                               // We don't support checking object constructors yet...
-                               // ...we can check the prototypes fine, though.
-                               } else {
-                                       if ( action === CompletenessTest.ACTION_INJECT ) {
-
-                                               for ( key in currVar.prototype ) {
-                                                       if ( hasOwn.call( currVar.prototype, key ) ) {
-                                                               value = currVar.prototype[key];
-                                                               if ( key === 'constructor' ) {
-                                                                       continue;
-                                                               }
-
-                                                               that.walkTheObject( key, value, masterVariable, currPathArray.concat( 'prototype' ), action );
-                                                       }
-                                               }
-
-                                       }
+                               // Don't put a spy in constructor functions as it messes with
+                               // instanceof etc.
+                               if ( !currVal.prototype || util.isEmptyObject( currVal.prototype ) ) {
+                                       this.injectionTracker[ currPathArray.join( '.' ) ] = true;
+                                       this.injectCheck( currObj, currName, function () {
+                                               ct.methodCallTracker[ currPathArray.join( '.' ) ] = true;
+                                       } );
                                }
-
                        }
 
                        // Recursively. After all, this is the *completeness* test
-                       if ( type === 'function' || type === 'object' ) {
-                               for ( key in currVar ) {
-                                       if ( hasOwn.call( currVar, key ) ) {
-                                               value = currVar[key];
-
-                                               that.walkTheObject( key, value, masterVariable, currPathArray.slice(), action );
+                       // This also traverses static properties and the prototype of a constructor
+                       if ( type === 'object' || type === 'function' ) {
+                               for ( key in currVal ) {
+                                       if ( hasOwn.call( currVal, key ) ) {
+                                               this.walkTheObject( currVal, key, masterVariable, currPathArray.slice() );
                                        }
                                }
                        }
                 * @param objectPathArray {Array}
                 * @param injectFn {Function}
                 */
-               injectCheck: function ( masterVariable, objectPathArray, injectFn ) {
-                       var i, len, prev, memberName, lastMember,
-                               curr = masterVariable;
-
-                       // Get the object in question through the path from the master variable,
-                       // We can't pass the value directly because we need to re-define the object
-                       // member and keep references to the parent object, member name and member
-                       // value at all times.
-                       for ( i = 0, len = objectPathArray.length; i < len; i++ ) {
-                               memberName = objectPathArray[i];
-
-                               prev = curr;
-                               curr = prev[memberName];
-                               lastMember = memberName;
-                       }
+               injectCheck: function ( obj, key, injectFn ) {
+                       var spy,
+                               val = obj[ key ];
 
-                       // Objects are by reference, members (unless objects) are not.
-                       prev[lastMember] = function () {
+                       spy = function () {
                                injectFn();
-                               return curr.apply( this, arguments );
+                               return val.apply( this, arguments );
                        };
+
+                       // Make the spy inherit from the original so that its static methods are also
+                       // visible in the spy (e.g. when we inject a check into mw.log, mw.log.warn
+                       // must remain accessible).
+                       /*jshint proto:true */
+                       spy.__proto__ = val;
+
+                       // Objects are by reference, members (unless objects) are not.
+                       obj[ key ] = spy;
                }
        };
 
        /* Expose */
        window.CompletenessTest = CompletenessTest;
 
-}( jQuery ) );
+}( mediaWiki, jQuery ) );
index e66b9cd..b6ba59f 100644 (file)
@@ -25,6 +25,8 @@ mediaWiki.language.convertGrammar = function ( word, form ) {
                                word = word.substr(0, word.length - 2 ) + 'тей';
                        } else if ( word.substr( word.length - 2 ) === 'ды' ) {
                                word = word.substr(0, word.length - 2 ) + 'дов';
+                       } else if ( word.substr( word.length - 1 ) === 'д' ) {
+                               word = word.substr(0, word.length - 1 ) + 'да';
                        } else if ( word.substr( word.length - 3 ) === 'ные' ) {
                                word = word.substr(0, word.length - 3 ) + 'ных';
                        } else if ( word.substr( word.length - 3 ) === 'ник' ) {
@@ -42,6 +44,8 @@ mediaWiki.language.convertGrammar = function ( word, form ) {
                                word = word.substr(0, word.length - 2 ) + 'тях';
                        } else if ( word.substr( word.length - 2 ) === 'ды' ) {
                                word = word.substr(0, word.length - 2 ) + 'дах';
+                       } else if ( word.substr( word.length - 1 ) === 'д' ) {
+                               word = word.substr(0, word.length - 1 ) + 'де';
                        } else if ( word.substr( word.length - 3 ) === 'ные' ) {
                                word = word.substr(0, word.length - 3 ) + 'ных';
                        } else if ( word.substr( word.length - 3 ) === 'ник' ) {
index 67e2f33..b65a62b 100644 (file)
@@ -61,7 +61,6 @@
 }
 
 .transition(@value) {
-       -webkit-backface-visibility: hidden; // fixes Chrome 1px movement bug
        -webkit-transition: @value;
        -moz-transition: @value;
        -o-transition: @value;
index e7c962f..1892967 100644 (file)
@@ -2,7 +2,7 @@
  * Show gallery captions when focused. Copied directly from jquery.mw-jump.js.
  * Also Dynamically resize images to justify them.
  */
-( function ( $, mw ) {
+( function ( $ ) {
        $( function () {
                var isTouchScreen,
                        gettingFocus,
@@ -93,7 +93,6 @@
                                        $imageElm,
                                        imageElm,
                                        $caption,
-                                       hookInfo,
                                        i,
                                        j,
                                        avgZoom,
                                                }
 
                                                if ( curRow[j].aspect === 0 || !isFinite( curRow[j].aspect ) ) {
-                                                       mw.log( 'Skipping item ' + j + ' due to aspect: ' + curRow[j].aspect );
                                                        // One of the dimensions are 0. Probably should
                                                        // not try to resize.
                                                        combinedPadding += curRow[j].width;
                                                // Also on the off chance there is a bug in this
                                                // code, would prevent accidentally expanding to
                                                // be 10 billion pixels wide.
-                                               mw.log( 'mw.page.gallery: Cannot fit row, aspect is ' + preferredHeight / curRowHeight );
                                                if ( i === rows.length - 1 ) {
                                                        // If its the last row, and we can't fit it,
                                                        // don't make the entire row huge.
                                        }
                                        if ( !isFinite( preferredHeight ) ) {
                                                // This *definitely* should not happen.
-                                               mw.log( 'mw.page.gallery: Trying to resize row ' + i + ' to ' + preferredHeight + '?!' );
                                                // Skip this row.
                                                continue;
                                        }
                                        if ( preferredHeight < 5 ) {
                                                // Well something clearly went wrong...
-                                               mw.log( {
-                                                       maxWidth: maxWidth,
-                                                       combinedPadding: combinedPadding,
-                                                       combinedAspect: combinedAspect,
-                                                       wantedWidth: wantedWidth
-                                               } );
-                                               mw.log( 'mw.page.gallery: [BUG!] Fitting row ' + i + ' to too small a size: ' + preferredHeight );
                                                // Skip this row.
                                                continue;
                                        }
 
                                                if ( newWidth < 60 || !isFinite( newWidth ) ) {
                                                        // Making something skinnier than this will mess up captions,
-                                                       mw.log( 'mw.page.gallery: Tried to make image ' + newWidth + 'px wide but too narrow.' );
                                                        if ( newWidth < 1 || !isFinite( newWidth ) ) {
                                                                $innerDiv.height( preferredHeight );
                                                                // Don't even try and touch the image size if it could mean
                                                        $caption.width( curRow[j].captionWidth + ( newWidth - curRow[j].imgWidth ) );
                                                }
 
-                                               hookInfo = {
-                                                       fullWidth: newWidth + padding,
-                                                       imgWidth: newWidth,
-                                                       imgHeight: preferredHeight,
-                                                       $innerDiv: $innerDiv,
-                                                       $imageDiv: $imageDiv,
-                                                       $outerDiv: $outerDiv,
-                                                       // Whether the hook took action
-                                                       resolved: false
-                                               };
-
-                                               /**
-                                                * Gallery resize.
-                                                *
-                                                * If your handler resizes an image, it should also set the resolved
-                                                * property to true. Additionally, because this module only exposes this
-                                                * logic temporarily, you should load your module in position top to
-                                                * ensure it is registered before this runs (FIXME: Don't use mw.hook)
-                                                *
-                                                * See TimedMediaHandler for an example.
-                                                *
-                                                * @event mediawiki_page_gallery_resize
-                                                * @member mw.hook
-                                                * @param {Object} hookInfo
-                                                */
-                                               mw.hook( 'mediawiki.page.gallery.resize' ).fire( hookInfo );
-
-                                               if ( !hookInfo.resolved ) {
-                                                       if ( imageElm ) {
-                                                               // We don't always have an img, e.g. in the case of an invalid file.
-                                                               imageElm.width = newWidth;
-                                                               imageElm.height = preferredHeight;
-                                                       } else {
-                                                               // Not a file box.
-                                                               $imageDiv.height( preferredHeight );
-                                                       }
+                                               if ( imageElm ) {
+                                                       // We don't always have an img, e.g. in the case of an invalid file.
+                                                       imageElm.width = newWidth;
+                                                       imageElm.height = preferredHeight;
+                                               } else {
+                                                       // Not a file box.
+                                                       $imageDiv.height( preferredHeight );
                                                }
                                        }
                                }
                        }() );
                } );
        } );
-}( jQuery, mediaWiki ) );
+}( jQuery ) );
index ebd6b92..2f1b795 100644 (file)
@@ -68,6 +68,12 @@ figure[typeof*='mw:Image'] {
                float: left;
        }
 
+       &.mw-halign-none {
+               margin: 0;
+               clear: none;
+               float: none;
+       }
+
        &.mw-halign-center {
                margin: 0 auto .5em auto;
                display: table;
@@ -99,7 +105,6 @@ figure[typeof~='mw:Image/Frame'] {
        display: table;
        overflow: auto;
        text-align: center;
-       padding: 3px;
        border: 1px solid #ccc;
        border-bottom: 0; // No border to caption
        border-collapse: collapse;
@@ -115,7 +120,7 @@ figure[typeof~='mw:Image/Thumb'] > *:first-child > img,
 figure[typeof~='mw:Image/Frame'] > *:first-child > img,
 .mw-image-border > *:first-child > img {
        border: 1px solid #cccccc;
-       margin: 4px;
+       margin: 3px;
 }
 
 /* Hide the caption for frameless and plain floated images */
index a805f3e..a30a15d 100644 (file)
@@ -5,3 +5,7 @@
 label[for="mw-input-wpConfirm"] {
        font-weight: bold;
 }
+
+tr.mw-block-hideuser {
+       font-weight: bold;
+}
index 5860adf..7ac8154 100644 (file)
@@ -27,11 +27,6 @@ table.mw-allpages-table-form tr {
        vertical-align: top;
 }
 
-/* Special:Block */
-tr.mw-block-hideuser {
-       font-weight: bold;
-}
-
 /* Special:BlockList */
 table.mw-blocklist span.mw-usertoollinks,
 span.mw-blocklist-actions {
@@ -71,166 +66,6 @@ td#mw-prefixindex-nav-form {
        text-align: right;
 }
 
-
-/* Special:Search */
-.searchresults {
-}
-
-.searchresults p {
-       margin-left: 0.4em;
-       margin-top: 1em;
-       margin-bottom: 1.2em;
-}
-div.searchresult {
-       font-size: 95%;
-       width: 38em;
-}
-.mw-search-results {
-       margin-left: 0.4em;
-}
-.mw-search-results li {
-       padding-bottom: 1.2em;
-       list-style: none;
-       list-style-image: none;
-}
-.mw-search-results li a {
-       font-size: 108%;
-}
-.mw-search-result-data {
-       color: green;
-       font-size: 97%;
-}
-.mw-search-formheader {
-       background-color: #f3f3f3;
-       margin-top: 1em;
-       border: 1px solid silver;
-}
-.mw-search-formheader div.search-types {
-       float: left;
-       padding-left: 0.25em;
-}
-.mw-search-formheader div.search-types ul {
-       margin: 0 !important;
-       padding: 0 !important;
-       list-style: none !important;
-}
-.mw-search-formheader div.search-types ul li {
-       float: left;
-       margin: 0;
-       padding: 0;
-}
-.mw-search-formheader div.search-types ul li a {
-       display: block;
-       padding: 0.5em;
-}
-.mw-search-formheader div.search-types ul li.current a {
-       color: #333333;
-       cursor: default;
-}
-.mw-search-formheader div.search-types ul li.current a:hover {
-       text-decoration: none;
-}
-#mw-search-top-table div.results-info {
-       float: right;
-       padding: 0.5em;
-       padding-right: 0.75em;
-       color: #666;
-       font-size: 95%;
-}
-
-fieldset#mw-searchoptions {
-       margin: 0;
-       padding: 0.5em 0.75em 0.75em 0.75em !important;
-       border: none;
-       background-color: #f9f9f9;
-       border: 1px solid silver !important;
-       border-top-width: 0 !important;
-}
-fieldset#mw-searchoptions legend {
-       display: none;
-}
-fieldset#mw-searchoptions h4 {
-       padding: 0;
-       margin: 0;
-       float: left;
-}
-fieldset#mw-searchoptions div#mw-search-togglebox {
-       float: right;
-}
-fieldset#mw-searchoptions div#mw-search-togglebox label {
-       margin-right: 0.25em;
-}
-fieldset#mw-searchoptions div#mw-search-togglebox input {
-       margin-left: 0.25em;
-}
-fieldset#mw-searchoptions table {
-       float: left;
-       margin-right: 3em;
-}
-fieldset#mw-searchoptions table td {
-       padding-right: 1em;
-}
-fieldset#mw-searchoptions div.divider {
-       clear: both;
-       border-bottom: 1px solid #DDDDDD;
-       padding-top: 0.5em;
-       margin-bottom: 0.5em;
-}
-td#mw-search-menu {
-       padding-left:6em;
-       font-size:85%;
-}
-div#mw-search-interwiki {
-       float: right;
-       width: 18em;
-       border: 1px solid #AAAAAA;
-       margin-top: 2ex;
-}
-div#mw-search-interwiki li {
-       font-size: 95%;
-}
-.mw-search-interwiki-more {
-       float: right;
-       font-size: 90%;
-}
-div#mw-search-interwiki-caption {
-       text-align: center;
-       font-weight: bold;
-       font-size: 95%;
-}
-.mw-search-interwiki-project {
-       font-size: 97%;
-       text-align: left;
-       padding: 0.15em 0.15em 0.2em 0.2em;
-       background-color: #ececec;
-       border-top: 1px solid #BBBBBB;
-}
-span.searchalttitle {
-       font-size: 95%;
-}
-div.searchdidyoumean {
-       font-size: 127%;
-       margin-top: 0.8em;
-       /* Note that this color won't affect the link, as desired. */
-       color: #c00;
-}
-div.searchdidyoumean em {
-       font-weight: bold;
-}
-.searchmatch {
-       font-weight: bold;
-}
-/* Advanced PowerSearch box */
-td#mw-search-togglebox {
-       text-align: right;
-}
-table#mw-search-powertable {
-       width: 100%;
-}
-form#powersearch {
-       clear: both;
-}
-
 /* Special:Specialpages */
 .mw-specialpagerestricted {
        font-weight: bold;
index f6ed82c..ef95507 100644 (file)
@@ -1,3 +1,5 @@
+/* Special:Search */
+
 /*
  * Fixes sister projects box moving down the extract
  * of the first result (bug #16886).
 .searchresult {
        display: inline !ie;
 }
+.searchresults {
+}
+.searchresults p {
+       margin-left: 0.4em;
+       margin-top: 1em;
+       margin-bottom: 1.2em;
+}
+div.searchresult {
+       font-size: 95%;
+       width: 38em;
+}
+.mw-search-results {
+       margin-left: 0.4em;
+}
+.mw-search-results li {
+       padding-bottom: 1.2em;
+       list-style: none;
+       list-style-image: none;
+}
+.mw-search-results li a {
+       font-size: 108%;
+}
+.mw-search-result-data {
+       color: green;
+       font-size: 97%;
+}
+.mw-search-formheader {
+       background-color: #f3f3f3;
+       margin-top: 1em;
+       border: 1px solid silver;
+}
+.mw-search-formheader div.search-types {
+       float: left;
+       padding-left: 0.25em;
+}
+.mw-search-formheader div.search-types ul {
+       margin: 0 !important;
+       padding: 0 !important;
+       list-style: none !important;
+}
+.mw-search-formheader div.search-types ul li {
+       float: left;
+       margin: 0;
+       padding: 0;
+}
+.mw-search-formheader div.search-types ul li a {
+       display: block;
+       padding: 0.5em;
+}
+.mw-search-formheader div.search-types ul li.current a {
+       color: #333333;
+       cursor: default;
+}
+.mw-search-formheader div.search-types ul li.current a:hover {
+       text-decoration: none;
+}
+#mw-search-top-table div.results-info {
+       float: right;
+       padding: 0.5em;
+       padding-right: 0.75em;
+       color: #666;
+       font-size: 95%;
+}
+
+fieldset#mw-searchoptions {
+       margin: 0;
+       padding: 0.5em 0.75em 0.75em 0.75em !important;
+       border: none;
+       background-color: #f9f9f9;
+       border: 1px solid silver !important;
+       border-top-width: 0 !important;
+}
+fieldset#mw-searchoptions legend {
+       display: none;
+}
+fieldset#mw-searchoptions h4 {
+       padding: 0;
+       margin: 0;
+       float: left;
+}
+fieldset#mw-searchoptions div#mw-search-togglebox {
+       float: right;
+}
+fieldset#mw-searchoptions div#mw-search-togglebox label {
+       margin-right: 0.25em;
+}
+fieldset#mw-searchoptions div#mw-search-togglebox input {
+       margin-left: 0.25em;
+}
+fieldset#mw-searchoptions table {
+       float: left;
+       margin-right: 3em;
+}
+fieldset#mw-searchoptions table td {
+       padding-right: 1em;
+       white-space: nowrap;
+}
+fieldset#mw-searchoptions div.divider {
+       clear: both;
+       border-bottom: 1px solid #DDDDDD;
+       padding-top: 0.5em;
+       margin-bottom: 0.5em;
+}
+td#mw-search-menu {
+       padding-left:6em;
+       font-size:85%;
+}
+div#mw-search-interwiki {
+       float: right;
+       width: 18em;
+       border: 1px solid #AAAAAA;
+       margin-top: 2ex;
+}
+div#mw-search-interwiki li {
+       font-size: 95%;
+}
+.mw-search-interwiki-more {
+       float: right;
+       font-size: 90%;
+}
+div#mw-search-interwiki-caption {
+       text-align: center;
+       font-weight: bold;
+       font-size: 95%;
+}
+.mw-search-interwiki-project {
+       font-size: 97%;
+       text-align: left;
+       padding: 0.15em 0.15em 0.2em 0.2em;
+       background-color: #ececec;
+       border-top: 1px solid #BBBBBB;
+}
+span.searchalttitle {
+       font-size: 95%;
+}
+div.searchdidyoumean {
+       font-size: 127%;
+       margin-top: 0.8em;
+       /* Note that this color won't affect the link, as desired. */
+       color: #c00;
+}
+div.searchdidyoumean em {
+       font-weight: bold;
+}
+.searchmatch {
+       font-weight: bold;
+}
+/* Advanced PowerSearch box */
+td#mw-search-togglebox {
+       text-align: right;
+}
+table#mw-search-powertable {
+       width: 100%;
+}
+form#powersearch {
+       clear: both;
+}
index e160579..6533db1 100644 (file)
 
                        this.displaySubmitting();
 
-                       this.api.newSection( this.title, subject, message, ok, err );
+                       this.api.newSection( this.title, subject, message ).done( ok ).fail( err );
                },
 
                /**
index c1f1844..12888bd 100644 (file)
                                                } catch ( e ) {
                                                        // A user-defined callback raised an exception.
                                                        // Swallow it to protect our state machine!
-                                                       log( 'Exception thrown by job.error', e );
+                                                       log( 'Exception thrown by user callback', e );
                                                }
                                        }
                                }
index a314dcb..a214cb3 100644 (file)
@@ -22,8 +22,9 @@
                        konqueror: [['>=', '4.11']],
                        docomo: false,
                        blackberry: false,
-                       ipod: false,
-                       iphone: false
+                       // Support for iOS 6 or higher. It has not been tested on iOS 5 or lower
+                       ipod: [['>=', 6]],
+                       iphone: [['>=', 6]]
                };
 
                if ( !$.client.test( map ) ) {
index 9792754..48d424c 100644 (file)
@@ -2,10 +2,12 @@
        "@metadata": {
                "authors": [
                        "Sanbec",
-                       "Vivaelcelta"
+                       "Vivaelcelta",
+                       "Fitoschido"
                ]
        },
        "skinname-monobook": "MonoBook",
+       "monobook-desc": "El tema clásico de MediaWiki desde 2004, cuyo nombre viene de la foto en blanco y negro de un libro en el fondo",
        "monobook.css": "/* El CSS colocado en esta página afectará a los usuarios que usen la apariencia \"MonoBook\" */",
        "monobook.js": "/* El código JavaScript que se ponga aquí será cargado por los usuarios de la apariencia MonoBook */"
 }
index 8e278d3..02a0185 100644 (file)
@@ -1,4 +1,10 @@
 {
+       "@metadata": {
+               "authors": [
+                       "Reza1615"
+               ]
+       },
        "skinname-monobook": "مونوبوک",
+       "monobook-desc": "پوسته کلاسیک مدیاویکی از سال ۲۰۰۴ از عکس سیاه و سفید در زمینه صفحه  کتاب نام گرفت",
        "monobook.css": "/* دستورات این بخش کاربرانی را که از پوستهٔ مونوبوک استفاده کنند تحت تاثیر قرار می‌دهند. */"
 }
diff --git a/skins/MonoBook/i18n/gd.json b/skins/MonoBook/i18n/gd.json
new file mode 100644 (file)
index 0000000..f5bd154
--- /dev/null
@@ -0,0 +1,8 @@
+{
+       "@metadata": {
+               "authors": [
+                       "GunChleoc"
+               ]
+       },
+       "monobook-desc": "Craiceann MediaWiki clasaigeach o 2004 a chaidh ainmeachadh a-rèir dealbh de leabhar ann an dubh 's geal air cùlaibh nan duilleagan"
+}
index 023a21e..39a703c 100644 (file)
@@ -5,6 +5,7 @@
                ]
        },
        "skinname-monobook": "MonoBook",
+       "monobook-desc": "Le apparentia classic de MediaWiki depost 2004, nominate assi pro le imagine in nigro e blanco (\"mono\") de un libro (\"book\") in le fundo del pagina.",
        "monobook.css": "/* Le CSS placiate hic afficera le usatores del apparentia MonoBook */",
        "monobook.js": "/* Omne JavaScript hic se executara pro le usatores del apparentia MonoBook */"
 }
index b19d0a0..95ba71a 100644 (file)
@@ -1,4 +1,10 @@
 {
+       "@metadata": {
+               "authors": [
+                       "Robby"
+               ]
+       },
        "skinname-monobook": "MonoBook",
+       "monobook-desc": "De klassesche Look vu MediaWiki zanter 2004, benannt no der Schwaarzwäissfoto vun engem Buch am Hannergrond vun der Säit",
        "monobook.css": "/* Dës CSS huet nëmmen Afloss op de Skin ''Monobook''  */"
 }
index 89b72e4..b08e117 100644 (file)
@@ -1,10 +1,12 @@
 {
        "@metadata": {
                "authors": [
-                       "Siebrand"
+                       "Siebrand",
+                       "Sjoerddebruin"
                ]
        },
        "skinname-monobook": "Monobook",
+       "monobook-desc": "De klassieke MediaWiki-vormgeving sinds 2004, genoemd naar de zwart-witfoto van een boek op de achtergrond van de pagina",
        "monobook.css": "/* CSS die hier wordt geplaatst heeft alleen invloed op de skin Monobook */",
        "monobook.js": "/* JavaScript die hier wordt geplaatst heeft alleen invloed op gebruikers die de skin Monobook gebruiken */"
 }
index 0f3b618..4c7031a 100644 (file)
@@ -1,10 +1,12 @@
 {
        "@metadata": {
                "authors": [
-                       "Sp5uhe"
+                       "Sp5uhe",
+                       "Matma Rex"
                ]
        },
        "skinname-monobook": "Książka",
+       "monobook-desc": "Klasyczna skórka MediaWiki, stworzona w 2004 roku, nazwana od czarno-białego zdjęcia książki w tle strony",
        "monobook.css": "/* Umieszczony tutaj kod CSS wpłynie na wygląd skórki Książka */",
        "monobook.js": "/* Umieszczony tutaj kod JavaScript zostanie załadowany wyłącznie przez użytkowników korzystających ze skórki Książka */"
 }
index d31e55d..0425b83 100644 (file)
@@ -1,10 +1,12 @@
 {
        "@metadata": {
                "authors": [
-                       "Hamilton Abreu"
+                       "Hamilton Abreu",
+                       "Fúlvio"
                ]
        },
        "skinname-monobook": "MonoBook",
+       "monobook-desc": "A clássica skin do MediaWiki desde 2004, tendo este nome devido a uma imagem em preto-e-branco de um livro no plano de fundo da página",
        "monobook.css": "/* Código CSS colocado aqui afectará os utilizadores do tema Monobook */",
        "monobook.js": "/* Código Javascript colocado aqui será carregado para utilizadores do tema Monobook */"
 }
index 13c2ac2..c3b1d46 100644 (file)
@@ -2,9 +2,11 @@
        "@metadata": {
                "authors": [
                        "AlexSm",
-                       "Kaganer"
+                       "Kaganer",
+                       "Okras"
                ]
        },
+       "monobook-desc": "Классическая тема оформления MediaWiki, созданная в 2004 году и названая в честь чёрно-белой фотографии книги с фонового изображения страницы",
        "monobook.css": "/* Размещённый здесь CSS будет применяться к теме оформления Monobook */",
        "monobook.js": "/* Размещённый здесь код JavaScript будет загружаться пользователям, использующим тему оформления MonoBook */"
 }
index 249c1f5..289f50e 100644 (file)
@@ -2,10 +2,12 @@
        "@metadata": {
                "authors": [
                        "Dim Grits",
-                       "Matma Rex"
+                       "Matma Rex",
+                       "Ата"
                ]
        },
        "skinname-monobook": "Моно-книга",
+       "monobook-desc": "Класична тема оформлення MediaWiki з 2004 року, названа за чорно-білим фото книги на фоні сторінки",
        "monobook.css": "/* Розміщений тут CSS буде застосовуватися до всіх тем оформлення Monobook */",
        "monobook.js": "/* Розміщений тут код JavaScript буде завантажений для всіх користувачів, що використовують тему оформлення Моно-книга */"
 }
index 960807a..67566f6 100644 (file)
@@ -4,6 +4,7 @@
                        "Minh Nguyen"
                ]
        },
+       "monobook-desc": "Giao diện MediaWiki cổ điển năm 2004, được đặt tên theo bức hình nền cuốn sách đen trắng",
        "monobook.css": "/* Mã CSS đặt ở đây sẽ ảnh hưởng đến thành viên sử dụng giao diện MonoBook */",
        "monobook.js": "/* Mã JavaScript tại đây sẽ được tải khi người dùng sử dụng giao diện MonoBook */"
 }
index 3b870ec..fc3f368 100644 (file)
@@ -2,10 +2,11 @@
        "@metadata": {
                "authors": [
                        "Xiaomingyan",
-                       "Cwek"
+                       "Cwek",
+                       "Liuxinyu970226"
                ]
        },
-       "monobook-desc": "自2004年就出现的经典MediaWiki皮肤,",
+       "monobook-desc": "自2004年就出现的经典MediaWiki皮肤,命名依据一本书中某页面的黑白照片背景",
        "monobook.css": "/* 放置于这里的CSS将影响使用MonoBook皮肤的用户 */",
        "monobook.js": "/* 这里的任何JavaScript将为使用MonoBook皮肤的用户加载 */"
 }
index f70c7a4..33cd230 100644 (file)
@@ -127,8 +127,6 @@ pre, .mw-code {
        vertical-align: text-bottom;
 }
 
-/* TODO: Remove #bodyContent selector (kept for backwards compatibility with cached html) */
-#bodyContent,
 .mw-body-content {
        position: relative;
        line-height: @content-line-height;
index b046e25..8bd949e 100644 (file)
@@ -5,7 +5,6 @@
                        "Naudefj"
                ]
        },
-       "vector-desc": "Verbeter die gebruikerskoppelvlak-elemente van die Vektor omslag (skin).",
        "vector-action-addsection": "Nuwe onderwerp",
        "vector-action-delete": "Skrap",
        "vector-action-move": "Skuif",
index 77b74a2..a5cc022 100644 (file)
@@ -4,7 +4,6 @@
                        "Bresta"
                ]
        },
-       "vector-desc": "Në elementet përmirëson ndërfaqen e përdoruesit të lëkurës Vektor.",
        "vector.css": "/* CSSi i vednosun këtu ka me i prekë shfrytëzuesit e dukjes Vector */",
        "vector.js": "/* Çdo JavaScript këtu ka me u ngarkue për shfrytëzuesit që përdorin dukjen Vector */",
        "vector-action-addsection": "Shto temë",
index 190784e..a4b5f0c 100644 (file)
@@ -5,7 +5,6 @@
                ]
        },
        "skinname-vector": "Vector",
-       "vector-desc": "Milloras en os elementos d'interficie d'usuario de l'aparencia Vector.",
        "vector.css": "/* Os estilos CSS colocaus aquí s'aplicarán ta totz os usuarios que faigan servir l'apariencia Vector */",
        "vector.js": "/* Qualsiquier codigo Javascript escrito aquí se cargará ta totz os usuarios que usen a piel Vector */",
        "vector-action-addsection": "Adhibir nueva sección",
index 3d87dcf..9c07d9b 100644 (file)
@@ -11,7 +11,6 @@
                ]
        },
        "skinname-vector": "فكتور",
-       "vector-desc": "تحسينات في عناصر واجهة المستخدم لواجهة فكتور.",
        "vector.css": "/* الأنماط المتراصة CSS المعروضة هنا ستؤثر على مستخدمي واجهة فكتور */",
        "vector.js": "/* أي جافاسكريبت هنا سيتم تحميلها للمستخدمين الذين يستعملون واجهة فكتور */",
        "vector-action-addsection": "أضف موضوعا",
index 0b62a8d..3541b15 100644 (file)
@@ -6,7 +6,6 @@
                        "Ramsis II"
                ]
        },
-       "vector-desc": "تحسينات فى عناصر واجهه المستخدم لواجهه فكتور.",
        "vector.css": "/* CSS اللى هنا حتأثر على اليوزرز اللى بيستخدموا واجهة فكتور */",
        "vector.js": "/* اى جافاسكريبت هنا حتتحمل لكل يوزر بيستخدم واجهة فكتور */",
        "vector-action-addsection": "ضيف موضوع",
index 37d5c67..97a3500 100644 (file)
@@ -4,13 +4,20 @@
                        "Icemandeaf"
                ]
        },
+       "skinname-vector": "M509x575S10e20494x425S14a20493x459S16d20492x478S1fb20494x502S17620493x525S11a20493x545",
+       "vector-skin-desc": "M535x520S19a00507x481S19a08465x481S22f14465x506S22f04509x506 M515x598S18d20494x403S17620499x432S11920493x452S17620499x482S14720500x502S17620499x528S17620499x548S14020485x568 M521x508S1f748479x493S1f740501x493 M532x517S15a16505x505S2880f468x484S20e00491x495S1821d503x492 M534x547S2ff00482x483S10001513x517S2e305488x487 S38700463x496 M535x536S20300516x521S20308470x521S26500516x502S26510470x502S14c30511x465S14c38465x465 M526x522S15a56499x510S11520503x479S20e00489x496S26a02474x489 M520x540S37606481x460S15a40508x513S28801499x491S20500488x492",
+       "vector.css": "/* M509x529S16d20492x471S20320493x495S20320493x514 M535x523S14c50508x492S14c58469x492S22520503x477S22520465x477 M525x525S10004510x475S22a04511x510S1000c476x475S22a14477x510 M534x518S2ff00482x483S15a10522x486S2b700514x458 M521x532S10609498x496S10621487x512S21100500x483S2df20479x468 M526x522S15a56499x510S11520503x479S20e00489x496S26a02474x489 M521x508S1f748479x493S1f740501x493 M509x575S10e20494x425S14a20493x459S16d20492x478S1fb20494x502S17620493x525S11a20493x545 M517x524S15a02484x477S15a20489x484S21100504x492S22a04504x509 */",
+       "vector.js": "/* M520x523S1f540480x477S2a204497x495 M519x527S19220498x489S2a20c482x473S20320498x512 M525x525S10004510x475S22a04511x510S1000c476x475S22a14477x510 M534x518S2ff00482x483S15a10522x486S2b700514x458 M524x539S14402493x485S1440a486x461S22b00508x509S22b10476x483 M536x521S2ff00482x483S10011515x491S28108515x461 M526x522S15a56499x510S11520503x479S20e00489x496S26a02474x489 M509x575S10e20494x425S14a20493x459S16d20492x478S1fb20494x502S17620493x525S11a20493x545 M517x524S15a02484x477S15a20489x484S21100504x492S22a04504x509 */",
        "vector-action-addsection": "M532x517S15a16505x505S2880f468x484S20e00491x495S1821d503x492 M522x522S15a37478x479S10041485x492S20600500x492",
        "vector-action-delete": "M527x532S1ea40473x511S1f540512x478S22a07497x504S2f700512x468",
        "vector-action-move": "M552x509S18520488x494S18528449x494S26626522x492",
        "vector-action-protect": "M512x519S15a19488x482S15a11489x482S20600488x508",
+       "vector-action-undelete": "M515x538S15a0a486x463S10050500x467S2330b485x516S20e00491x501 M527x532S1ea40473x511S1f540512x478S22a07497x504S2f700512x468",
+       "vector-action-unprotect": "M521x532S10609498x496S10621487x512S21100500x483S2df20479x468 M512x519S15a19488x482S15a11489x482S20600488x508",
        "vector-view-create": "M532x519S20302493x485S2030a489x502S21100509x504S26900516x482S26910468x501",
        "vector-view-edit": "M521x532S10609498x496S10621487x512S21100500x483S2df20479x468",
        "vector-view-history": "M525x524S2ff00482x483S10e00507x494S26500511x474 M514x523S11541487x478S22f04489x509",
        "vector-view-view": "M513x540S15a06486x459S10e50494x474S22b04493x510",
-       "vector-view-viewsource": "M525x524S2ff00482x483S10e00507x494S26500511x474 M509x545S16d20492x456S17620493x480S10120493x497S14a20494x530"
+       "vector-view-viewsource": "M525x524S2ff00482x483S10e00507x494S26500511x474 M509x545S16d20492x456S17620493x480S10120493x497S14a20494x530",
+       "vector-more-actions": "M526x508S18510501x493S18518475x493"
 }
index 1a1d80a..bd3703f 100644 (file)
@@ -5,7 +5,6 @@
                        "Xuacu"
                ]
        },
-       "vector-desc": "Ameyora la interfaz d'usuariu al usar l'aspeutu Vector.",
        "vector.css": "/* Los CSS allugaos equí afeutarán a los usuarios del aspeutu Vector */",
        "vector.js": "/* Cualesquier JavaScript que tea equí se cargará pa los usuarios del aspeutu Vector */",
        "vector-action-addsection": "Amestar seición",
index b97bb2c..30969f7 100644 (file)
@@ -6,7 +6,6 @@
                ]
        },
        "skinname-vector": "Векторлы",
-       "vector-desc": "\"Векторлы\" күренешенең ҡулланыусы интерфейсында яҡшыртыуҙар.",
        "vector-action-addsection": "Тема өҫтәргә",
        "vector-action-delete": "Юйырға",
        "vector-action-move": "Исемен үҙгәртергә",
index 79ef2c9..0c085b1 100644 (file)
@@ -5,7 +5,6 @@
                        "Mucalexx"
                ]
        },
-       "vector-desc": "Vabesserrungen an da Vektor-Benutzerowerflächen",
        "vector-action-addsection": "An Obschnitt dazua doa",
        "vector-action-delete": "Leschn",
        "vector-action-move": "Vaschiabm",
index af21db2..4bbef69 100644 (file)
@@ -7,7 +7,6 @@
                ]
        },
        "skinname-vector": "Вэктар",
-       "vector-desc": "Паляпшае элемэнты інтэрфэйсу карыстальніка для афармленьня «Вэктар»",
        "vector-action-addsection": "Дадаць тэму",
        "vector-action-delete": "Выдаліць",
        "vector-action-move": "Перанесьці",
index cb17708..b84c18f 100644 (file)
@@ -7,7 +7,6 @@
                        "Хомелка"
                ]
        },
-       "vector-desc": "Паляпшае элементы інтэрфэйсу ўдзельніка для кажуха Vector",
        "vector-action-addsection": "Дадаць тэму",
        "vector-action-delete": "Сцерці",
        "vector-action-move": "Перанесці",
index 879374c..9a2858c 100644 (file)
@@ -6,7 +6,6 @@
                        "Spiritia"
                ]
        },
-       "vector-desc": "Подобрява елементите от потребителския интерфейс на облик Вектор.",
        "vector-action-addsection": "Добавяне на тема",
        "vector-action-delete": "Изтриване",
        "vector-action-move": "Преместване",
index 6f08d91..a2c37b3 100644 (file)
@@ -10,7 +10,6 @@
                ]
        },
        "skinname-vector": "ভেক্টর",
-       "vector-desc": "ভেক্টর স্কিনের ইন্টারফেস উপাদানের উন্নতি সাধন",
        "vector-action-addsection": "বিষয় যোগ",
        "vector-action-delete": "অপসারণ",
        "vector-action-move": "স্থানান্তর",
index 0ea5aa9..3124363 100644 (file)
@@ -4,7 +4,6 @@
                        "Usingha"
                ]
        },
-       "vector-desc": "ভেক্টর স্কিনর ইন্টারফেস মাথেলর উন্নতি করানি।",
        "vector-action-addsection": "বিষয় তিলকর",
        "vector-action-delete": "পুসে বেলা",
        "vector-action-move": "থেইকর",
index 32705ea..9cf579b 100644 (file)
@@ -6,7 +6,6 @@
                ]
        },
        "skinname-vector": "Vektor",
-       "vector-desc": "Gwellaat a ra elfennoù eus ar gwiskadur Vector war an etrefas implijer.",
        "vector.css": "/* Talvezout a raio ar CSS lakaet amañ evit implijerien ar gwiskadur Vektor */",
        "vector.js": "/* Kement JavaScript amañ a vo karget evit an implijerien a ra gant ar gwiskadur Vektor */",
        "vector-action-addsection": "Rannbennad nevez",
index 2bc0b68..a371374 100644 (file)
@@ -9,7 +9,6 @@
                        "Vriullop"
                ]
        },
-       "vector-desc": "Millores en els elements d'interfície d'usuari de l'aparença Vector.",
        "vector-action-addsection": "Nova secció",
        "vector-action-delete": "Esborra",
        "vector-action-move": "Reanomena",
index ed44124..75053d7 100644 (file)
@@ -10,7 +10,7 @@
        "vector-action-delete": "ДӀаяккха",
        "vector-action-move": "ЦӀе хийца",
        "vector-action-protect": "Гlаролла дé",
-       "vector-action-undelete": "Меттахlоттадé",
+       "vector-action-undelete": "МеттахӀоттае",
        "vector-action-unprotect": "ГӀароллех къаста",
        "vector-view-create": "Кхоллар",
        "vector-view-edit": "Нисъе",
index 0b73c40..081783b 100644 (file)
@@ -5,7 +5,7 @@
                ]
        },
        "skinname-vector": "Vektor",
-       "vector-desc": "Vylepšuje uživatelské rozhraní při užití vzhledu Vektor",
+       "vector-skin-desc": "Moderní verze MonoBooku s novějším vzhledem a vylepšenou použitelností",
        "vector.css": "/* Zde uvedené CSS bude ovlivňovat pouze styl „Vektor“ */",
        "vector.js": "/* JavaScript pro uživatele používající vzhled „Vektor“ */",
        "vector-action-addsection": "Přidat téma",
index a7206db..99d4dc3 100644 (file)
@@ -4,7 +4,6 @@
                        "Lloffiwr"
                ]
        },
-       "vector-desc": "Yn gwella ar y rhyngwyneb yn y wedd Vector.",
        "vector-action-addsection": "Ychwanegu adran",
        "vector-action-delete": "Dileu",
        "vector-action-move": "Symud",
@@ -15,5 +14,6 @@
        "vector-view-edit": "Golygu",
        "vector-view-history": "Gweld yr hanes",
        "vector-view-view": "Darllen",
-       "vector-view-viewsource": "Dangos côd y dudalen"
+       "vector-view-viewsource": "Dangos côd y dudalen",
+       "vector-more-actions": "Rhagor"
 }
index 288132a..ad56101 100644 (file)
@@ -6,7 +6,6 @@
                        "Peter Alberti"
                ]
        },
-       "vector-desc": "Forbedrer brugerfladen, når Vector-udseendet er i brug.",
        "vector-action-addsection": "Nyt emne",
        "vector-action-delete": "Slet",
        "vector-action-move": "Flyt",
index 4d0c8ec..5ba4455 100644 (file)
@@ -8,7 +8,6 @@
                ]
        },
        "skinname-vector": "Vektor",
-       "vector-desc": "Yeweniya asayışa vektori da rıasayışe karberi keno weş.",
        "vector-action-addsection": "Mewzu vıraze",
        "vector-action-delete": "Bestere",
        "vector-action-move": "Bere",
index e51cf30..7220f36 100644 (file)
@@ -4,7 +4,6 @@
                        "Michawiki"
                ]
        },
-       "vector-desc": "!Pólěpša wužywarski pówjerch za drastwu Vector.",
        "vector-action-addsection": "Temu pśidaś",
        "vector-action-delete": "Wulašowaś",
        "vector-action-move": "Pśesunuś",
index dfd6091..06fa36b 100644 (file)
@@ -9,7 +9,6 @@
                        "ZaDiak"
                ]
        },
-       "vector-desc": "Παρέχει βελτίωση στα στοιχεία διεπαφής χρήστη του skin Vector.",
        "vector.css": "/* Το τοποθετημένο εδώ CSS θα επηρεάσει χρήστες του Vector skin */",
        "vector.js": "/* Οποιοσδήποτε κώδικας JavaScript εδώ θα φορτωθεί για χρήστες που χρησιμοποιούν το Vector skin */",
        "vector-action-addsection": "Προσθήκη θέματος",
index 936faf3..5f92fe8 100644 (file)
@@ -7,7 +7,6 @@
                ]
        },
        "skinname-vector": "Vektoro",
-       "vector-desc": "Plibonigas la uzula interfaco kiam oni lernas Vector-etoson.",
        "vector.css": "/* La jena CSS influos la paĝaspekton por uzantoj de la Vektora temo. */",
        "vector.js": "/* La jena Ĝavaskripto ŝargiĝos por uzantoj de la Vektora temo. */",
        "vector-action-addsection": "Aldoni temon",
index 8304e96..75352a5 100644 (file)
                ]
        },
        "skinname-vector": "Vector",
-       "vector-desc": "Mejora la interfaz de usuario cuando se utiliza Vector como aspecto",
+       "vector-skin-desc": "Versión moderna de MonoBook, con un aspecto actualizado y muchas mejoras de usabilidad",
        "vector.css": "/* El CSS colocado en esta página afectará a los usuarios que usen la apariencia \"Vector\" */",
        "vector.js": "/* Cualquier código JavaScript escrito aquí se cargará para todos los usuarios que usen la apariencia Vector */",
-       "vector-action-addsection": "Nueva sección",
+       "vector-action-addsection": "Sección nueva",
        "vector-action-delete": "Borrar",
        "vector-action-move": "Trasladar",
        "vector-action-protect": "Proteger",
index 4d9c589..718b93c 100644 (file)
@@ -7,7 +7,6 @@
                ]
        },
        "skinname-vector": "Vektor",
-       "vector-desc": "Täiustab Vectori-kujunduse kasutajaliidest.",
        "vector-action-addsection": "Lisa teema",
        "vector-action-delete": "Kustuta",
        "vector-action-move": "Teisalda",
index 5eb3cca..856742c 100644 (file)
@@ -2,10 +2,10 @@
        "@metadata": {
                "authors": [
                        "Unai Fdz. de Betoño",
-                       "Xabier Armendaritz"
+                       "Xabier Armendaritz",
+                       "Fitoschido"
                ]
        },
-       "vector-desc": "Vector skin-eko lankidearen interfazeko elementuak hobetzen ditu.",
        "vector-action-addsection": "Gehitu atala",
        "vector-action-delete": "Ezabatu",
        "vector-action-move": "Mugitu",
@@ -16,5 +16,6 @@
        "vector-view-edit": "Aldatu",
        "vector-view-history": "Ikusi historia",
        "vector-view-view": "Irakurri",
-       "vector-view-viewsource": "Kodea ikusia"
+       "vector-view-viewsource": "Kodea ikusia",
+       "vector-more-actions": "Gehiago"
 }
index d014e2f..1d329ff 100644 (file)
@@ -9,7 +9,7 @@
                ]
        },
        "skinname-vector": "برداری",
-       "vector-desc": "بهبود در عناصر رابط کاربری در زمان استفاده از پوستهٔ وکتور",
+       "vector-skin-desc": "نسخه مدرن منوبوک با نگاه تازه و بهبود قابلیت استفاده",
        "vector-action-addsection": "افزودن بخش",
        "vector-action-delete": "حذف",
        "vector-action-move": "انتقال",
index d707cc3..7533689 100644 (file)
@@ -7,7 +7,6 @@
                        "Pxos"
                ]
        },
-       "vector-desc": "Parantaa käyttöliittymää Vector-ulkoasua käytettäessä.",
        "vector.css": "/* Tämä sivu sisältää Vector-ulkoasua muuttavia tyylejä. */",
        "vector.js": "/* Tämän sivun JavaScript-koodi liitetään Vector-tyyliin */",
        "vector-action-addsection": "Lisää aihe",
index 2fa5449..4f0c3bc 100644 (file)
@@ -5,7 +5,6 @@
                ]
        },
        "skinname-vector": "Vèctor",
-       "vector-desc": "Mèlyoracions des èlèments de l’entèrface usanciér de l’habelyâjo « Vèctor ».",
        "vector.css": "/* Lo code CSS betâ ique afècterat los usanciérs de l’habelyâjo « Vèctor ». */",
        "vector.js": "/* Tot code JavaScript betâ ique serat chargiê per los usanciérs de l’habelyâjo « Vèctor ». */",
        "vector-action-addsection": "Apondre na chousa",
index 4365ed4..f9ff0a3 100644 (file)
@@ -5,7 +5,7 @@
                        "Pyt"
                ]
        },
-       "vector-desc": "Muar ferbeedrangen för di skak „Vector“ mögelk maage",
+       "vector-skin-desc": "Modern werjuun faan Monobook mä frisk skak an föl muar mögelkhaiden",
        "vector-action-addsection": "Nei kirew began",
        "vector-action-delete": "Strik",
        "vector-action-move": "Fersküüw",
@@ -16,5 +16,6 @@
        "vector-view-edit": "Bewerke",
        "vector-view-history": "Ferluup uunluke",
        "vector-view-view": "Lees",
-       "vector-view-viewsource": "Kweltekst uunluke"
+       "vector-view-viewsource": "Kweltekst uunluke",
+       "vector-more-actions": "Muar"
 }
index 6c78ad5..04fa42b 100644 (file)
@@ -5,7 +5,7 @@
                        "GunChleoc"
                ]
        },
-       "vector-desc": "Cuiridh seo piseach air eileamaidean eadar-aghaidh nan cleachdaichean san chraiceann Vector.",
+       "vector-skin-desc": "Tionndadh ùr-nodha de MonoBook le dreach ùr air 's iomadh leasachadh air a sho-chleachdachd",
        "vector-action-addsection": "Cuir ris cuspair",
        "vector-action-delete": "Sguab às",
        "vector-action-move": "Gluais",
index 86bc06b..de19c39 100644 (file)
@@ -6,7 +6,6 @@
                        "Vivaelcelta"
                ]
        },
-       "vector-desc": "Mellora a interface de usuario ao usar a aparencia Vector",
        "vector.css": "/* O CSS que se coloque aquí afectará a quen use a aparencia Vector */",
        "vector.js": "/* Calquera JavaScript que haxa aquí será cargado para os usuarios que usen a aparencia Vector */",
        "vector-action-addsection": "Nova sección",
index 0db8e32..90b3e73 100644 (file)
@@ -4,7 +4,6 @@
                        "Als-Holder"
                ]
        },
-       "vector-desc": "Verbesserige an dr Elemänt vu dr Benutzeroberflechi bim Vector-skin",
        "vector-action-addsection": "Abschnitt zuefiege",
        "vector-action-delete": "Lesche",
        "vector-action-move": "Verschiebe",
index 9636a4e..6d7dc1d 100644 (file)
@@ -6,7 +6,6 @@
                        "Dsvyas"
                ]
        },
-       "vector-desc": "વેક્ટર સ્કીનના યુઝર ઈંટરફેઝ ના તત્વોને સુધારે છે",
        "vector-action-addsection": "નવી ચર્ચા",
        "vector-action-delete": "રદ કરો",
        "vector-action-move": "ખસેડો",
index 468f636..08a9023 100644 (file)
@@ -6,7 +6,6 @@
                ]
        },
        "skinname-vector": "וקטור",
-       "vector-desc": "הרחבת ממשק המשתמש בעת השימוש בעיצוב וקטור",
        "vector.css": "/* הסגנונות הנכתבים כאן ישפיעו על העיצוב Vector בלבד */",
        "vector.js": "/* כל סקריפט JavaScript שנכתב כאן ירוץ רק עבור המשתמשים בעיצוב Vector */",
        "vector-action-addsection": "הוספת נושא",
index aa49ad7..1887ee5 100644 (file)
@@ -5,7 +5,6 @@
                        "Tivek"
                ]
        },
-       "vector-desc": "Poboljšava elemente korisničkog sučelja stila Vector.",
        "vector-action-addsection": "Dodaj temu",
        "vector-action-delete": "Izbriši",
        "vector-action-move": "Premjesti",
index b39b715..a46105c 100644 (file)
@@ -4,7 +4,6 @@
                        "Michawiki"
                ]
        },
-       "vector-desc": "Polěpša wužiwarski powjerch drasty Vector",
        "vector-action-addsection": "Temu přidać",
        "vector-action-delete": "wušmórnyć",
        "vector-action-move": "přesunyć",
index 3e2e3ea..a144ece 100644 (file)
@@ -9,7 +9,6 @@
                        "Tgr"
                ]
        },
-       "vector-desc": "Fejlesztések a Vector felület felhasználói felületének elemein.",
        "vector.css": "/* Az ide elhelyezett CSS hatással lesz a Vector felület használóira */",
        "vector.js": "/* A Vector felületet használó szerkesztők számára betöltendő JavaScriptek */",
        "vector-action-addsection": "Új téma nyitása",
index 8ae3a28..c1281fc 100644 (file)
@@ -4,7 +4,7 @@
                        "McDutchie"
                ]
        },
-       "vector-desc": "Meliora le elementos del interfacie de usator del apparentia Vector.",
+       "vector-skin-desc": "Version moderne de MonoBook con aspecto rejuvenescite e multe meliorationes de usabilitate.",
        "vector.css": "/* Le CSS placiate hic afficera le usatores del apparentia Vector */",
        "vector.js": "/* Omne JavaScript hic se executara pro le usatores del apparentia Vector */",
        "vector-action-addsection": "Adder topico",
index 45e72a8..3116632 100644 (file)
@@ -9,7 +9,6 @@
                ]
        },
        "skinname-vector": "Vektor",
-       "vector-desc": "Meningkatkan antarmuka pengguna dengan menggunakan kulit vektor",
        "vector.css": "/* CSS nan ado di siko diterapkan pado kulik Vektor. */",
        "vector.js": "/* Semua JavaScript di sini akan dimuatkan untuk para pengguna yang menggunakan kulit Vector */",
        "vector-action-addsection": "Bagian baru",
index c35f907..817c75f 100644 (file)
@@ -5,7 +5,6 @@
                        "Saluyot"
                ]
        },
-       "vector-desc": "Pasayaatenna ti interface ti agar-aramat no agusar ti kudil a Vector",
        "vector-action-addsection": "Agnayon ti topiko",
        "vector-action-delete": "Ikkaten",
        "vector-action-move": "Iyalis",
index f93f04b..dc54f1b 100644 (file)
@@ -7,7 +7,6 @@
                        "Ævar Arnfjörð Bjarmason"
                ]
        },
-       "vector-desc": "Endurbætir notanda viðmót Vector sniðsins.",
        "vector-action-addsection": "Bæta við umræðu",
        "vector-action-delete": "Eyða",
        "vector-action-move": "Færa",
index e8b98f6..7bfa57e 100644 (file)
@@ -10,7 +10,6 @@
                ]
        },
        "skinname-vector": "ベクター",
-       "vector-desc": "ベクター外装の使用時にユーザーインターフェイスを強化する",
        "vector.css": "/* ここに記述したCSSはベクター外装の利用者に影響します */",
        "vector.js": "/* ここにあるすべてのJavaScriptは、ベクター外装を使用している利用者に対して読み込まれます */",
        "vector-action-addsection": "話題追加",
index 356c352..7af6b95 100644 (file)
@@ -4,7 +4,6 @@
                        "Pras"
                ]
        },
-       "vector-desc": "Benahi unsur antarmuka panganggo saka kulit Vector.",
        "vector-action-addsection": "Tambah topik",
        "vector-action-delete": "Busak",
        "vector-action-move": "Pindhahna",
index d03fe9c..a08fe71 100644 (file)
@@ -7,7 +7,6 @@
                ]
        },
        "skinname-vector": "ვექტორული",
-       "vector-desc": "აუმჯობესებს მომხმარებლის ინტერფეისს გაფორმების ვექტორული თემისათვის",
        "vector.css": "/* აქ ჩასმული CSS გამოყენებული იქნება ვექტორული გაფორმების თემაში */",
        "vector-action-addsection": "თემის ჩამატება",
        "vector-action-delete": "წაშლა",
index 1970fa0..3593350 100644 (file)
@@ -12,7 +12,7 @@
        "vector-action-move": "Атауын өзгерту",
        "vector-action-protect": "Қорғау",
        "vector-action-undelete": "Жоймау",
-       "vector-action-unprotect": "Ò\9aоÑ\80Ò\93анÑ\8bÑ\81Ñ\82Ñ\8b өзгерту",
+       "vector-action-unprotect": "Ò\9aоÑ\80Ò\93анÑ\8bÑ\81Ñ\8bн өзгерту",
        "vector-view-create": "Бастау",
        "vector-view-edit": "Өңдеу",
        "vector-view-history": "Өңделу тарихы",
index 97e4757..cdb2f55 100644 (file)
@@ -6,7 +6,6 @@
                ]
        },
        "skinname-vector": "Вектор",
-       "vector-desc": "«Вектор» темагъа къошулуучу интерфейсни игилендириулери",
        "vector-action-addsection": "Джангы тема къош",
        "vector-action-delete": "Кетер",
        "vector-action-move": "Атын ауушдур",
index a480dd6..7d91fae 100644 (file)
@@ -5,7 +5,6 @@
                ]
        },
        "skinname-vector": "Vektor",
-       "vector-desc": "Verbäßert de Schnettschtäll för der Minsch met dä Vektor Bovverfläsch.",
        "vector.css": "/* CSS heh aan dä Stell wirrek nur op de Ovverflääsch „Vector“ */",
        "vector.js": "/* De JavaSkrippte fun hee krijje alle Sigge met de Ovverflääsch \"Vector\" jescheck */",
        "vector-action-addsection": "Ne neue Afschnet onge draan!",
index bc9d7bf..cb26439 100644 (file)
@@ -4,7 +4,7 @@
                        "Robby"
                ]
        },
-       "vector-desc": "Verbessert am Benotzer-Interface Elementer wann d'Ausgesinn ''Vector'' benotzt gëtt.",
+       "vector-skin-desc": "Modern Versioun vu Monobook mat frëschem Look a ville Verbesserunge vun der Benotzerfrëndlechkeet",
        "vector-action-addsection": "Sujet derbäisetzen",
        "vector-action-delete": "Läschen",
        "vector-action-move": "Réckelen",
index 06a5286..8fe7e26 100644 (file)
@@ -4,7 +4,6 @@
                        "Ooswesthoesbes"
                ]
        },
-       "vector-desc": "Verbaetertj de vectorgebroekersinterface-illemente",
        "vector-action-addsection": "Voog köpke toe",
        "vector-action-delete": "Ewegsjaffe",
        "vector-action-move": "Verplaats",
index 8c560ff..697d1eb 100644 (file)
@@ -5,7 +5,6 @@
                        "Papuass"
                ]
        },
-       "vector-desc": "Uzlabo lietotāja saskarsnes elementus Vector apdarē.",
        "vector-action-addsection": "Jauna sadaļa",
        "vector-action-delete": "Dzēst",
        "vector-action-move": "Pārvietot",
index a8ad4da..bf5a735 100644 (file)
@@ -7,7 +7,6 @@
                ]
        },
        "skinname-vector": "Vektor",
-       "vector-desc": "Maningkekan antamuka pangguno bilo mamakai kulik Vektor",
        "vector-action-addsection": "Bagian baru",
        "vector-action-delete": "Hapuih",
        "vector-action-move": "Pindahkan",
index 0df6e2a..6ca34a1 100644 (file)
@@ -6,7 +6,6 @@
                ]
        },
        "skinname-vector": "വെക്റ്റർ",
-       "vector-desc": "വെക്റ്റർ ദൃശ്യരൂപം ഉപയോഗിക്കുമ്പോൾ ഉപയോക്തൃസമ്പർക്കമുഖം മെച്ചപ്പെടുത്തുന്നു",
        "vector.css": "/* ഇവിടെ നൽകുന്ന സി.എസ്.എസ്. വെക്റ്റർ ദൃശ്യരൂപത്തിനു ബാധകമായിരിക്കും*/",
        "vector.js": "/*ഇവിടെ നൽകുന്ന ജാവാസ്ക്രിപ്റ്റ് വെക്റ്റർ ദൃശ്യരൂപം ഉപയോഗിക്കുന്ന ഉപയോക്താക്കൾക്ക് ബാധകമായിരിക്കും*/",
        "vector-action-addsection": "വിഷയം ചേർക്കുക",
index b669c69..ab7e322 100644 (file)
@@ -6,7 +6,6 @@
                ]
        },
        "skinname-vector": "सदिश",
-       "vector-desc": "व्हेक्टर त्वचा वापरताना उपयोगकर्ता-इंटरफेस घटकांमध्ये सुधारणा करते",
        "vector-action-addsection": "विषय जोडा",
        "vector-action-delete": "वगळा",
        "vector-action-move": "स्थानांतरण",
index 9997857..2795e44 100644 (file)
@@ -7,7 +7,6 @@
                ]
        },
        "skinname-vector": "Vector",
-       "vector-desc": "Meningkatkan antara muka pengguna ketika menggunakan kulit Vector",
        "vector.css": "/* CSS yang terletak di sini akan mempengaruhi pengguna kulit Vector */",
        "vector-action-addsection": "Buka topik",
        "vector-action-delete": "Hapus",
index c6b5275..32c9f1a 100644 (file)
@@ -4,7 +4,6 @@
                        "Chrisportelli"
                ]
        },
-       "vector-desc": "Ittejjeb l-elementi tal-interfaċċa tal-utent tal-aspett grafiku Vector.",
        "vector-action-addsection": "Żid diskussjoni",
        "vector-action-delete": "Ħassar",
        "vector-action-move": "Mexxi",
index 4dcd025..0ef82e0 100644 (file)
@@ -6,7 +6,7 @@
                        "Nghtwlkr"
                ]
        },
-       "vector-desc": "Forbedrer brukergrensesnittet for Vector-utseendet.",
+       "vector-skin-desc": "Moderne versjon av MonoBook med et friskt utseende og mange bruksforbedringer",
        "vector-action-addsection": "Nytt emne",
        "vector-action-delete": "Slett",
        "vector-action-move": "Flytt",
index bf15d4c..be846db 100644 (file)
@@ -4,7 +4,6 @@
                        "Servien"
                ]
        },
-       "vector-desc": "Verbetert t gebrukersuterlik van Vector",
        "vector-action-addsection": "Niej onderwarp",
        "vector-action-delete": "Vortdoon",
        "vector-action-move": "Herneumen",
index 3ae43f5..07c18d9 100644 (file)
@@ -5,11 +5,12 @@
                        "Romaine",
                        "SPQRobin",
                        "Siebrand",
-                       "Troefkaart"
+                       "Troefkaart",
+                       "Sjoerddebruin"
                ]
        },
        "skinname-vector": "Vector",
-       "vector-desc": "Verbetert de gebruikersinterface van het uiterlijk Vector",
+       "vector-skin-desc": "Moderne versie van MonoBook met een fris uiterlijk en verbeteringen op het gebied van gebruiksvriendelijkheid",
        "vector.css": "/* CSS die hier wordt geplaatst heeft alleen invloed op de skin Vector */",
        "vector.js": "/* JavaScript die hier wordt geplaatst heeft alleen invloed op gebruikers die de skin Vector gebruiken */",
        "vector-action-addsection": "Kopje toevoegen",
index 0ce78d1..2aa517e 100644 (file)
@@ -5,7 +5,6 @@
                        "Cedric31"
                ]
        },
-       "vector-desc": "Melhoraments dels elements de l'interfàcia d'utilizaire de l'abilhatge Vector.",
        "vector.css": "/* Lo CSS plaçat aicí afectarà los utilizaires de l’abilhatge Vector */",
        "vector.js": "/* Tot JavaScript aicí serà cargat amb las paginas accedidas pels utilizaires de l’abilhatge Vector unicament. */",
        "vector-action-addsection": "Apondre un subjècte",
index 6854e93..289cc3c 100644 (file)
@@ -5,7 +5,6 @@
                        "Psubhashish"
                ]
        },
-       "vector-desc": "ଭେକ୍ଟର ଆବରଣରେ ବ୍ୟବହାର କରୁଥିବା ବେଳେ ଇଉଜର ଇଣ୍ଟରଫେସକୁ ଉନ୍ନତ କରିବେ ।",
        "vector-action-addsection": "ନୂଆ ଯୋଡ଼ନ୍ତୁ",
        "vector-action-delete": "ଲିଭାଇବେ",
        "vector-action-move": "ଘୁଞ୍ଚାଇବେ",
index 794d608..5cf2082 100644 (file)
@@ -6,7 +6,7 @@
                ]
        },
        "skinname-vector": "Wektor",
-       "vector-desc": "Usprawnia elementy interfejsu użytkownika skórki Wektor",
+       "vector-skin-desc": "Odświeżona wersja skórki Książka, z nowym wyglądem i usprawnieniami",
        "vector.css": "/* Umieszczony tutaj kod CSS wpłynie na wygląd skórki Wektor */",
        "vector.js": "/* Umieszczony tutaj kod JavaScript zostanie załadowany wyłącznie przez użytkowników korzystających ze skórki Wektor */",
        "vector-action-addsection": "Dodaj temat",
index 0e8710d..79627b0 100644 (file)
@@ -4,7 +4,6 @@
                        "Borichèt"
                ]
        },
-       "vector-desc": "A ameliora l'antërfacia utent quand as deuvra la pel Vector",
        "vector-action-addsection": "Gionté n'argoment",
        "vector-action-delete": "Scancelé",
        "vector-action-move": "Tramudé",
index 8594b4e..601f513 100644 (file)
@@ -5,7 +5,6 @@
                        "Khalid Mahmood"
                ]
        },
-       "vector-desc": "ورتن والے دے وکھالے",
        "vector-action-addsection": "مضمون پاؤ",
        "vector-action-delete": "مکاؤ",
        "vector-action-move": "ٹرو",
index 9a88e7c..db47675 100644 (file)
@@ -8,7 +8,6 @@
                        555
                ]
        },
-       "vector-desc": "Melhora a interface do usuário ao utilizar o tema Vector",
        "vector.js": "/* Qualquer JavaScript aqui colocado afetará os usuários do skin Vector */",
        "vector-action-addsection": "Adicionar tópico",
        "vector-action-delete": "Eliminar",
index b2176c7..789fd27 100644 (file)
@@ -4,7 +4,6 @@
                        "AlimanRuna"
                ]
        },
-       "vector-desc": "Vector qarawan llamk'aptiykiqa ruraqpaq uyapuratam allinchan.",
        "vector-action-addsection": "Allwiyta yapay",
        "vector-action-delete": "Qulluy",
        "vector-action-move": "Astay",
index 4b80d07..96725c0 100644 (file)
@@ -9,7 +9,6 @@
                ]
        },
        "skinname-vector": "Vector",
-       "vector-desc": "Îmbunătățiri ale interfeței când se utilizează interfața Vector.",
        "vector.css": "/* CSS plasate aici vor afecta utilizatorii stilului Vector */",
        "vector-action-addsection": "Mesaj nou",
        "vector-action-delete": "Ștergere",
index b103517..c5721e7 100644 (file)
@@ -5,7 +5,6 @@
                ]
        },
        "skinname-vector": "Vettore",
-       "vector-desc": "Migliore l'elemende de l'inderfacce utende quanne ause 'a visualizzazzione Vector",
        "vector.css": "/* 'U CSS ca se iacchie aqquà 'u 'ndrucane le utinde d'a masckere Vettore */",
        "vector.js": "/* Ogne JavaScript aqquà avène carecate pe le utinde ca ausane 'a masckere Vettore */",
        "vector-action-addsection": "Aggiunge 'na discussiona",
index 994446f..cd344b9 100644 (file)
@@ -10,7 +10,7 @@
                ]
        },
        "skinname-vector": "Векторное",
-       "vector-desc": "Улучшает пользовательский интерфейс для темы оформления «Векторное»",
+       "vector-skin-desc": "Современная версия MonoBook с обновлённым оформлением и многими улучшениями в юзабилити",
        "vector.css": "/* Размещённый здесь CSS будет применяться к векторной теме оформления  */",
        "vector.js": "/* Размещённый здесь код JavaScript будет загружаться пользователям, использующим тему оформления Vector */",
        "vector-action-addsection": "Добавить тему",
index 5920632..2147f80 100644 (file)
@@ -4,7 +4,6 @@
                        "Gazeb"
                ]
        },
-       "vector-desc": "Здоконалює елементы хосновательского інтерфейсу Вектор.",
        "vector-action-addsection": "Придати тему",
        "vector-action-delete": "Вымазати",
        "vector-action-move": "Переменовати",
index 069fb45..610ba3e 100644 (file)
@@ -5,7 +5,6 @@
                        "Shubha"
                ]
        },
-       "vector-desc": "आकृतिचर्मणः योजकमध्यस्थांशेषु प्रगतिः",
        "vector-action-addsection": "विषयः योज्यताम्",
        "vector-action-delete": "अपाक्रियताम्",
        "vector-action-move": "शीर्षकं परिवर्त्यताम्",
index 1cafbfe..9d44db5 100644 (file)
@@ -4,7 +4,6 @@
                        "HalanTul"
                ]
        },
-       "vector-desc": "Вектор диэн тиэмэ туттар интерфейсын тупсарыы",
        "vector-action-addsection": "Тиэмэ эбии",
        "vector-action-delete": "Сот",
        "vector-action-move": "Аатын уларыт",
index 77e87e9..640874f 100644 (file)
@@ -7,7 +7,6 @@
                        "සුරනිමල"
                ]
        },
-       "vector-desc": "දෛශික පෘෂ්ඨයේ පරිශීලක අතුරු මුහුණත් මූලිකාංග මත දියුණු කරයි",
        "vector-action-addsection": "මාතෘකාව එක්කරන්න",
        "vector-action-delete": "මකන්න",
        "vector-action-move": "ගෙනයන්න",
index 8f0fd8a..06bf290 100644 (file)
@@ -7,7 +7,6 @@
                ]
        },
        "skinname-vector": "Vector",
-       "vector-desc": "Vylepšuje prvky používateľského rozhrania témy vzhľady Vector",
        "vector.css": "/* Tu umiestnené CSS bude ovplyvňovať používateľov štýlu Vector */",
        "vector.js": "/* Tu sa nachádzajúci JavaScript sa načíta používateľom vzhľadu Vector */",
        "vector-action-addsection": "Pridať tému",
index 957f8d0..85e8574 100644 (file)
@@ -6,7 +6,6 @@
                        "Yerpo"
                ]
        },
-       "vector-desc": "Izboljša uporabniški vmesnik pri uporabi kože Vector.",
        "vector-action-addsection": "Dodaj temo",
        "vector-action-delete": "Izbriši",
        "vector-action-move": "Prestavi",
index db90b3e..e33b69c 100644 (file)
@@ -8,7 +8,6 @@
                ]
        },
        "skinname-vector": "Векторско",
-       "vector-desc": "Побољшава корисничке елементе сучеља за пресвлаку Вектор.",
        "vector.css": "/* CSS постављен овде ће утицати на све кориснике теме „Векторско“ */",
        "vector.js": "/* Јаваскрипт постављен овде ће се учитати за све оне који користе тему „Векторско“ */",
        "vector-action-addsection": "Додај тему",
index dda6c27..38f17ad 100644 (file)
@@ -8,7 +8,6 @@
                ]
        },
        "skinname-vector": "Vektorsko",
-       "vector-desc": "Poboljšava korisničke elemente sučelja za presvlaku Vektor.",
        "vector.css": "/* CSS postavljen ovde će uticati na sve korisnike teme „Vektorsko“ */",
        "vector.js": "/* Javaskript postavljen ovde će se učitati za sve one koji koriste temu „Vektorsko“ */",
        "vector-action-addsection": "Dodaj temu",
index 4a8cc2e..cb511ba 100644 (file)
@@ -5,7 +5,6 @@
                        "Muddyb Blast Producer"
                ]
        },
-       "vector-desc": "Inaboresha kusano kwa ajili ya watumiaji wa umbo la Vector.",
        "vector-action-addsection": "Weka mada",
        "vector-action-delete": "Futa",
        "vector-action-move": "Hamisha",
index da1a691..2a0495d 100644 (file)
@@ -6,7 +6,6 @@
                ]
        },
        "skinname-vector": "Vector",
-       "vector-desc": "Nagpapainam sa mga sangkap ng dugtungang-mukha na pangtatagamit ng pabalat ng Vector.",
        "vector.css": "/* Ang inilagay na CSS dito ay makakaapekto sa mga tagagamit ng pabalat na Vector */",
        "vector.js": "/* Ang anumang JavaScript dito ay ikakarga para sa mga tagagamit na gumagamit ng pabalat na Vector */",
        "vector-action-addsection": "Magdagdag ng paksa",
index ce907be..2bf1407 100644 (file)
@@ -8,11 +8,12 @@
                        "Dim Grits",
                        "NickK",
                        "Prima klasy4na",
-                       "Тест"
+                       "Тест",
+                       "Ата"
                ]
        },
        "skinname-vector": "Векторне",
-       "vector-desc": "Покращує інтерфейс користувача для оформлення «Вектор»",
+       "vector-skin-desc": "Сучасна версія MonoBook зі свіжим виглядом і багатьма зручними покращеннями",
        "vector.css": "/* Розміщений тут CSS-код буде використаний в темі оформлення Векторне */",
        "vector.js": "/* Розміщений тут код JavaScript буде завантажений для всіх користувачів, що використовують векторну тему оформлення */",
        "vector-action-addsection": "Додати тему",
index 22f8dcd..595477e 100644 (file)
@@ -8,7 +8,6 @@
                        "محبوب عالم"
                ]
        },
-       "vector-desc": "صارف انٹرفیس کے عناصر ویکٹر جلد کے پر بہتر ہے.",
        "vector-action-addsection": "نیا موضوع",
        "vector-action-delete": "حذف کرو",
        "vector-action-move": "منتقل کرو",
index 0580fc2..9622828 100644 (file)
@@ -8,7 +8,6 @@
                        "Vajotwo"
                ]
        },
-       "vector-desc": "Potensia l'interfacia utente có se dopara el tema Vector",
        "vector-action-addsection": "Zonta discusion",
        "vector-action-delete": "Scanseła",
        "vector-action-move": "Sposta",
index 04becc3..a59d9b4 100644 (file)
@@ -7,6 +7,7 @@
                ]
        },
        "skinname-vector": "Vectơ",
+       "vector-skin-desc": "Giao diện làm lại từ MonoBook có màu tươi và khả dụng hơn",
        "vector.css": "/* Mã CSS đặt ở đây sẽ ảnh hưởng đến thành viên sử dụng giao diện Vectơ */",
        "vector.js": "/* Mã JavaScript tại đây sẽ được tải khi người dùng sử dụng giao diện Vectơ */",
        "vector-action-addsection": "Thêm chủ đề",
index b5b6706..0401884 100644 (file)
@@ -4,7 +4,6 @@
                        "Srtxg"
                ]
        },
-       "vector-desc": "Amidraedjes pol pea d' eterface d' uzeu «Vector»",
        "vector-action-addsection": "Radjouter on sudjet",
        "vector-action-delete": "Disfacer",
        "vector-action-move": "Displaecî",
index e12d4e1..3e67c21 100644 (file)
@@ -7,7 +7,6 @@
                        "Mark85296341"
                ]
        },
-       "vector-desc": "改善Vector外觀的使用者介面元素。",
        "vector.css": "/* 此 CSS 會影響使用 Vector 介面外觀的使用者 */",
        "vector.js": "/* 此 JavaScript 會用於使用 Vector 介面外觀使用者 */",
        "vector-action-addsection": "加入主題",
diff --git a/skins/common/images/icons/fileicon-xcf.png b/skins/common/images/icons/fileicon-xcf.png
new file mode 100644 (file)
index 0000000..1037b50
Binary files /dev/null and b/skins/common/images/icons/fileicon-xcf.png differ
diff --git a/skins/common/images/tipsy-arrow.gif b/skins/common/images/tipsy-arrow.gif
deleted file mode 100644 (file)
index 9f1a15b..0000000
Binary files a/skins/common/images/tipsy-arrow.gif and /dev/null differ
index a5612e2..e72b252 100644 (file)
@@ -1128,37 +1128,6 @@ ol:lang(or) li {
        margin-left: 20px;
 }
 
-.tipsy {
-       padding: 5px 5px 10px;
-       font-size: 12px;
-       position: absolute;
-       z-index: 100000;
-       overflow: visible;
-}
-
-.tipsy-inner {
-       padding: 5px 8px 4px 8px;
-       background-color: #d6f3ff;
-       color: black;
-       border: 1px solid #5dc9f4;
-       max-width: 300px;
-       text-align: left;
-}
-
-.tipsy-arrow {
-       position: absolute;
-       /* @embed */
-       background: url(images/tipsy-arrow.gif) no-repeat top left;
-       width: 13px;
-       height: 13px;
-}
-
-.tipsy-se .tipsy-arrow {
-       bottom: -2px;
-       right: 10px;
-       background-position: 0% 100%;
-}
-
 #mw-clearyourcache,
 #mw-sitecsspreview,
 #mw-sitejspreview,
index fd6803e..3be33b7 100755 (executable)
@@ -1,7 +1,7 @@
-#ruby=ruby-2.1.1
+#ruby=ruby-2.1.2
+#ruby-gemset=core
 
 source "https://rubygems.org"
 
-gem "chunky_png"
 gem "mediawiki_api"
 gem "mediawiki_selenium"
index 6ec2493..92784bf 100644 (file)
@@ -4,7 +4,6 @@ GEM
     builder (3.2.2)
     childprocess (0.5.3)
       ffi (~> 1.0, >= 1.0.11)
-    chunky_png (1.3.1)
     cucumber (1.3.15)
       builder (>= 2.1.2)
       diff-lcs (>= 1.1.3)
@@ -32,7 +31,7 @@ GEM
       domain_name (~> 0.5)
     i18n (0.6.9)
     json (1.8.1)
-    mediawiki_api (0.1.2)
+    mediawiki_api (0.1.3)
       faraday (~> 0.9, >= 0.9.0)
       faraday-cookie_jar (~> 0.0, >= 0.0.6)
     mediawiki_selenium (0.2.25)
@@ -57,7 +56,7 @@ GEM
       mime-types (>= 1.16)
     rspec-expectations (2.99.1)
       diff-lcs (>= 1.1.3, < 2.0)
-    rubyzip (1.1.4)
+    rubyzip (1.1.5)
     selenium-webdriver (2.42.0)
       childprocess (>= 0.5.0)
       multi_json (~> 1.0)
@@ -76,6 +75,5 @@ PLATFORMS
   ruby
 
 DEPENDENCIES
-  chunky_png
   mediawiki_api
   mediawiki_selenium
index a8a96d6..d6745ad 100644 (file)
@@ -1,3 +1,4 @@
+@chrome @clean @en.wikipedia.beta.wmflabs.org @firefox @phantomjs @test2.wikipedia.org
 Feature: Create account
 
   Scenario Outline: Go to Create account page
index f5f0ce0..29dd1c1 100644 (file)
@@ -1,4 +1,4 @@
-
+@chrome @clean @en.wikipedia.beta.wmflabs.org @firefox @login @phantomjs @test2.wikipedia.org
 Feature: Create Page With Wiki Link
 
   Scenario: Create Page With Wiki Link
@@ -6,4 +6,4 @@ Feature: Create Page With Wiki Link
       And I go to the "Link Source Test Page" page with content "This is a [[Link Target Test Page|link to the test target page]] right here."
     When I click the Link Target link
     Then I should be on the Link Target Test Page
-      And the page content should contain "Link Target Test Page"
\ No newline at end of file
+      And the page content should contain "Link Target Test Page"
index 53efd6b..c190a78 100644 (file)
@@ -1,8 +1,11 @@
+@chrome @clean @en.wikipedia.beta.wmflabs.org @firefox @login @phantomjs @test2.wikipedia.org
 Feature: Edit Page
 
   Scenario: Create and edit page
     Given I go to the "Editing Test Page" page with content "This is a page to test editing"
     When I click Edit
       And I edit the page with "Edited and a random string"
+      And I click Preview
+      And I click Show Changes
       And I save the edit
     Then the edited page content should contain "Edited and a random string"
diff --git a/tests/browser/features/file.feature b/tests/browser/features/file.feature
new file mode 100644 (file)
index 0000000..2d3b708
--- /dev/null
@@ -0,0 +1,23 @@
+#
+# This file is subject to the license terms in the LICENSE file found in the
+# qa-browsertests top-level directory and at
+# https://git.wikimedia.org/blob/qa%2Fbrowsertests/HEAD/LICENSE. No part of
+# qa-browsertests, including this file, may be copied, modified, propagated, or
+# distributed except according to the terms contained in the LICENSE file.
+#
+# Copyright 2012-2014 by the Mediawiki developers. See the CREDITS file in the
+# qa-browsertests top-level directory and at
+# https://git.wikimedia.org/blob/qa%2Fbrowsertests/HEAD/CREDITS
+#
+@chrome @en.wikipedia.beta.wmflabs.org @firefox @internet_explorer_6 @internet_explorer_7 @internet_explorer_8 @internet_explorer_9 @internet_explorer_10 @phantomjs @test2.wikipedia.org
+Feature: File
+
+ Scenario: Anonymous goes to file that does not exist
+   Given I am at file that does not exist
+   Then page should show that no such file exists
+
+ @login
+ Scenario: Logged-in user goes to file that does not exist
+   Given I am logged in
+     And I am at file that does not exist
+   Then page should show that no such file exists
\ No newline at end of file
diff --git a/tests/browser/features/login.feature b/tests/browser/features/login.feature
new file mode 100644 (file)
index 0000000..9ff2a2a
--- /dev/null
@@ -0,0 +1,42 @@
+#
+# This file is subject to the license terms in the LICENSE file found in the
+# qa-browsertests top-level directory and at
+# https://git.wikimedia.org/blob/qa%2Fbrowsertests/HEAD/LICENSE. No part of
+# qa-browsertests, including this file, may be copied, modified, propagated, or
+# distributed except according to the terms contained in the LICENSE file.
+#
+# Copyright 2012-2014 by the Mediawiki developers. See the CREDITS file in the
+# qa-browsertests top-level directory and at
+# https://git.wikimedia.org/blob/qa%2Fbrowsertests/HEAD/CREDITS
+#
+@chrome @en.wikipedia.beta.wmflabs.org @firefox @internet_explorer_6 @internet_explorer_7 @internet_explorer_8 @internet_explorer_9 @internet_explorer_10 @phantomjs @test2.wikipedia.org
+Feature: Log in
+
+  Background:
+    Given I am at Log in page
+
+  Scenario: Go to Log in page
+    Then Username element should be there
+      And Password element should be there
+      And Log in element should be there
+
+  Scenario: Log in without entering credentials
+    When I log in without entering credentials
+    Then error box should be visible
+
+  Scenario: Log in without entering password
+    When I log in without entering password
+    Then error box should be visible
+
+  Scenario: Log in with incorrect username
+    When I log in with incorrect username
+    Then error box should be visible
+
+  Scenario: Log in with incorrect password
+    When I log in with incorrect password
+    Then error box should be visible
+
+  @login
+  Scenario: Log in with valid credentials
+    When I am logged in
+    Then error box should not be visible
\ No newline at end of file
index 053ee62..561fe53 100644 (file)
@@ -1,3 +1,4 @@
+@chrome @clean @en.wikipedia.beta.wmflabs.org @firefox @phantomjs @test2.wikipedia.org
 Feature: Main Page View History Links
 
   Background:
index 2eb5de8..1a958bb 100644 (file)
@@ -9,7 +9,7 @@
 # qa-browsertests top-level directory and at
 # https://git.wikimedia.org/blob/qa%2Fbrowsertests/HEAD/CREDITS
 #
-@chrome @en.wikipedia.beta.wmflabs.org @firefox @internet_explorer_6 @internet_explorer_7 @internet_explorer_8 @internet_explorer_9 @internet_explorer_10 @login @phantomjs @test2.wikipedia.org
+@chrome @clean @en.wikipedia.beta.wmflabs.org @firefox @internet_explorer_6 @internet_explorer_7 @internet_explorer_8 @internet_explorer_9 @internet_explorer_10 @login @phantomjs @test2.wikipedia.org
 Feature: Preferences
 
   Scenario: Preferences Appearance
@@ -25,7 +25,7 @@ Feature: Preferences
       And I can click Save
       And I can restore default settings
       And I can select date format
-      And I can see server time
+      And I can see time offset section
       And I can see local time
       And I can select my time zone
 
index 5af097b..5ab02be 100644 (file)
@@ -2,6 +2,14 @@ When(/^I click Edit$/) do
   on(MainPage).edit_link
 end
 
+When(/^I click Preview$/) do
+  on(EditPage).preview_button
+end
+
+When(/^I click Show Changes$/) do
+  on(EditPage).show_changes_button
+end
+
 When(/^I edit the page with "(.*?)"$/) do |edit_content|
   on(EditPage).edit_page_content_element.send_keys(edit_content + @random_string)
 end
diff --git a/tests/browser/features/step_definitions/file_steps.rb b/tests/browser/features/step_definitions/file_steps.rb
new file mode 100644 (file)
index 0000000..a2ed1bf
--- /dev/null
@@ -0,0 +1,18 @@
+#
+# This file is subject to the license terms in the LICENSE file found in the
+# qa-browsertests top-level directory and at
+# https://git.wikimedia.org/blob/qa%2Fbrowsertests/HEAD/LICENSE. No part of
+# qa-browsertests, including this file, may be copied, modified, propagated, or
+# distributed except according to the terms contained in the LICENSE file.
+#
+# Copyright 2012-2014 by the Mediawiki developers. See the CREDITS file in the
+# qa-browsertests top-level directory and at
+# https://git.wikimedia.org/blob/qa%2Fbrowsertests/HEAD/CREDITS
+#
+Given(/^I am at file that does not exist$/) do
+  visit(FileDoesNotExistPage, using_params: {page_name: @random_string})
+end
+
+Then(/^page should show that no such file exists$/) do
+  on(FileDoesNotExistPage).file_does_not_exist_message_element.should be_visible
+end
diff --git a/tests/browser/features/step_definitions/login_steps.rb b/tests/browser/features/step_definitions/login_steps.rb
new file mode 100644 (file)
index 0000000..b654b2d
--- /dev/null
@@ -0,0 +1,65 @@
+#
+# This file is subject to the license terms in the LICENSE file found in the
+# qa-browsertests top-level directory and at
+# https://git.wikimedia.org/blob/qa%2Fbrowsertests/HEAD/LICENSE. No part of
+# qa-browsertests, including this file, may be copied, modified, propagated, or
+# distributed except according to the terms contained in the LICENSE file.
+#
+# Copyright 2012-2014 by the Mediawiki developers. See the CREDITS file in the
+# qa-browsertests top-level directory and at
+# https://git.wikimedia.org/blob/qa%2Fbrowsertests/HEAD/CREDITS
+#
+Given(/^I am at Log in page$/) do
+  visit LoginPage
+end
+
+When(/^I log in with incorrect password$/) do
+  on(LoginPage).login_with(ENV["MEDIAWIKI_USER"], "incorrect password", false)
+end
+
+When(/^I log in with incorrect username$/) do
+  on(LoginPage).login_with("incorrect username", ENV["MEDIAWIKI_PASSWORD"], false)
+end
+
+When(/^I log in without entering credentials$/) do
+  on(LoginPage).login_with("", "", false)
+end
+
+When(/^I log in without entering password$/) do
+  on(LoginPage).login_with(ENV["MEDIAWIKI_USER"], "", false)
+end
+
+Then(/^error box should be visible$/) do
+  on(LoginErrorPage).error_box_element.should be_visible
+end
+
+Then(/^error box should not be visible$/) do
+  on(LoginErrorPage).error_box_element.should_not be_visible
+end
+
+Then(/^feedback should be (.+)$/) do |feedback|
+  on(LoginPage) do |page|
+    page.feedback_element.when_present.click
+    page.feedback.should match Regexp.escape(feedback)
+  end
+end
+
+Then(/^Log in element should be there$/) do
+  on(LoginPage).login_element.should exist
+end
+
+Then(/^main page should open$/) do
+  @browser.url.should == on(MainPage).class.url
+end
+
+Then(/^Password element should be there$/) do
+  on(LoginPage).password_element.should exist
+end
+
+Then(/^there should be a link to (.+)$/) do |text|
+  on(LoginPage).username_displayed_element.when_present.text.should == text
+end
+
+Then(/^Username element should be there$/) do
+  on(LoginPage).username_element.should exist
+end
index d3e275e..0046af6 100644 (file)
@@ -18,7 +18,7 @@ When(/^I navigate to Preferences$/) do
 end
 
 Then(/^I can click Save$/) do
-  on(PreferencesAppearancePage).save_button_element.should exist
+  on(PreferencesPage).save_button_element.should exist
 end
 
 Then(/^I can restore default settings$/) do
@@ -26,12 +26,11 @@ Then(/^I can restore default settings$/) do
 end
 
 Then(/^I can see local time$/) do
-  @browser.text.should match Regexp.escape("Local time")
   on(PreferencesAppearancePage).local_time_span_element.should exist
 end
 
-Then(/^I can see server time$/) do
-  @browser.text.should match Regexp.escape("Server time")
+Then(/^I can see time offset section$/) do
+  on(PreferencesAppearancePage).time_offset_table_element.should be_visible
 end
 
 Then(/^I can select date format$/) do
@@ -49,7 +48,6 @@ Then(/^I can select image size$/) do
 end
 
 Then(/^I can select my time zone$/) do
-  @browser.text.should match Regexp.escape("Time zone")
   on(PreferencesAppearancePage) do |page|
     page.time_offset_select_element.should exist
     page.other_offset_element.should exist
index 4ffef5e..7c12236 100644 (file)
@@ -1,2 +1,2 @@
-require "mediawiki_selenium"
 require "mediawiki_api"
+require "mediawiki_selenium"
index 594ac73..b619c34 100644 (file)
@@ -2,6 +2,7 @@ class EditPage
   include PageObject
 
   text_area(:edit_page_content, id: "wpTextbox1")
+  button(:preview_button, id: "wpPreview")
+  button(:show_changes_button, id: "wpDiff")
   button(:save_button, id: "wpSave")
-
 end
\ No newline at end of file
diff --git a/tests/browser/features/support/pages/file_does_not_exist_page.rb b/tests/browser/features/support/pages/file_does_not_exist_page.rb
new file mode 100644 (file)
index 0000000..c8491f3
--- /dev/null
@@ -0,0 +1,19 @@
+#
+# This file is subject to the license terms in the LICENSE file found in the
+# qa-browsertests top-level directory and at
+# https://git.wikimedia.org/blob/qa%2Fbrowsertests/HEAD/LICENSE. No part of
+# qa-browsertests, including this file, may be copied, modified, propagated, or
+# distributed except according to the terms contained in the LICENSE file.
+#
+# Copyright 2012-2014 by the Mediawiki developers. See the CREDITS file in the
+# qa-browsertests top-level directory and at
+# https://git.wikimedia.org/blob/qa%2Fbrowsertests/HEAD/CREDITS
+#
+class FileDoesNotExistPage
+  include PageObject
+
+  include URL
+  page_url URL.url("File:<%=params[:page_name]%>")
+
+  div(:file_does_not_exist_message, id: "mw-imagepage-nofile")
+end
diff --git a/tests/browser/features/support/pages/login_error_page.rb b/tests/browser/features/support/pages/login_error_page.rb
new file mode 100644 (file)
index 0000000..4fc9ca7
--- /dev/null
@@ -0,0 +1,5 @@
+class LoginErrorPage
+  include PageObject
+
+  div(:error_box, class: "errorbox")
+end
\ No newline at end of file
index c01aab4..e7b64cd 100644 (file)
@@ -29,11 +29,11 @@ class PreferencesAppearancePage
   radio_button(:monobook, id: "mw-input-wpskin-monobook")
   radio_button(:no_preference_radio, id: "mw-input-wpdate-default")
   text_field(:other_offset, id: "mw-input-wptimecorrection-other")
-  a(:restore_default_link, text:/Restore all default settings/)
-  button(:save_button, text: "Save")
+  a(:restore_default_link, href: /reset/)
   select_list(:size_select, id: "mw-input-wpimagesize")
   select_list(:threshold_select, id: "mw-input-wpstubthreshold")
   select_list(:time_offset_select, id: "mw-input-wptimecorrection")
+  table(:time_offset_table, id: "mw-htmlform-timeoffset")
   select_list(:thumb_select, id: "mw-input-wpthumbsize")
   select_list(:underline_select, id: "mw-input-wpunderline")
   radio_button(:vector, id: "mw-input-wpskin-vector")
index b581ca4..919ba27 100644 (file)
@@ -15,14 +15,8 @@ class PreferencesPage
   include URL
   page_url URL.url("Special:Preferences")
 
-  a(:appearance_link, text: "Appearance")
-  a(:date_and_time_link, text: "Date and time")
-  a(:editing_link, text: "Editing")
-  a(:gadgets_link, text: "Gadgets")
-  a(:misc_link, text: "Misc")
-  a(:pending_changes_link, text: "Pending changes")
-  a(:recent_changes_link, text: "Recent changes")
-  a(:search_link, text: "Search")
-  a(:user_profile_link, text: "User profile")
-  a(:watchlist_link, text: "Watchlist")
+  a(:appearance_link, id: "preftab-rendering")
+  a(:editing_link, id: "preftab-editing")
+  a(:user_profile_link, id: "preftab-personal")
+  button(:save_button, id: "prefcontrol")
 end
index 82bc813..7b42639 100644 (file)
@@ -1,3 +1,4 @@
+@chrome @clean @en.wikipedia.beta.wmflabs.org @firefox @phantomjs @test2.wikipedia.org
 Feature: View History
 
   Scenario: Edit page and view history
index e4d9324..4a3889d 100644 (file)
@@ -1087,7 +1087,7 @@ Non-html5 tags should be accepted
 </p>
 !! end
 
-## a,rtc not permitted
+## a not permitted
 ## i,b,br omitted
 !! test
 Text-level semantic html elements in wikitext
@@ -1109,7 +1109,7 @@ Text-level semantic html elements in wikitext
 <sub>text</sub>
 <u>text</u>
 <mark>text</mark>
-<ruby><rb>明日<rp>(</rp><rt>Ashita</rt><rp>)</rp></rb></ruby>
+<ruby><rb>明日</rb><rp>(</rp><rt>Ashita</rt><rp> </rp><rtc>あした</rtc><rp>)</rp></ruby>
 <bdi>text</bdi>
 <bdo>text</bdo>
 <span>text</span>
@@ -1132,7 +1132,7 @@ Text-level semantic html elements in wikitext
 <sub>text</sub>
 <u>text</u>
 <mark>text</mark>
-<ruby><rb>明日<rp>(</rp><rt>Ashita</rt><rp>)</rp></rb></ruby>
+<ruby><rb>明日</rb><rp>(</rp><rt>Ashita</rt><rp> </rp><rtc>あした</rtc><rp>)</rp></ruby>
 <bdi>text</bdi>
 <bdo>text</bdo>
 <span>text</span>
@@ -1140,6 +1140,45 @@ Text-level semantic html elements in wikitext
 </p>
 !! end
 
+# test cases taken from
+# http://www.w3.org/TR/html5/text-level-semantics.html#the-ruby-element
+!! test
+Ruby markup (W3C-style)
+!! wikitext
+; Mono-ruby for individual base characters
+: <ruby>日<rt>に</rt>本<rt>ほん</rt>語<rt>ご</rt></ruby>
+; Group ruby
+: <ruby>今日<rt>きょう</rt></ruby>
+; Jukugo ruby
+: <ruby>法<rb>華</rb><rb>経</rb><rt>ほ</rt><rt>け</rt><rt>きょう</rt></ruby>
+; Inline ruby
+: <ruby>東<rb>京</rb><rp>(</rp><rt>とう</rt><rt>きょう</rt><rp>)</rp></ruby>
+; Double-sided ruby
+: <ruby><rb>旧</rb><rb>金</rb><rb>山</rb><rt>jiù</rt><rt>jīn</rt><rt>shān</rt><rtc>San Francisco</rtc></ruby>
+<ruby>
+<rb>♥</rb><rtc><rt>Heart</rt></rtc><rtc lang="fr"><rt>Cœur</rt></rtc>
+<rb>☘</rb><rtc><rt>Shamrock</rt></rtc><rtc lang="fr"><rt>Trèfle</rt></rtc>
+<rb>✶</rb><rtc><rt>Star</rt></rtc><rtc lang="fr"><rt>Étoile</rt></rtc>
+</ruby>
+!! html
+<dl><dt> Mono-ruby for individual base characters</dt>
+<dd> <ruby>日<rt>に</rt>本<rt>ほん</rt>語<rt>ご</rt></ruby></dd>
+<dt> Group ruby</dt>
+<dd> <ruby>今日<rt>きょう</rt></ruby></dd>
+<dt> Jukugo ruby</dt>
+<dd> <ruby>法<rb>華</rb><rb>経</rb><rt>ほ</rt><rt>け</rt><rt>きょう</rt></ruby></dd>
+<dt> Inline ruby</dt>
+<dd> <ruby>東<rb>京</rb><rp>(</rp><rt>とう</rt><rt>きょう</rt><rp>)</rp></ruby></dd>
+<dt> Double-sided ruby</dt>
+<dd> <ruby><rb>旧</rb><rb>金</rb><rb>山</rb><rt>jiù</rt><rt>jīn</rt><rt>shān</rt><rtc>San Francisco</rtc></ruby></dd></dl>
+<p><ruby>
+<rb>♥</rb><rtc><rt>Heart</rt></rtc><rtc lang="fr"><rt>Cœur</rt></rtc>
+<rb>☘</rb><rtc><rt>Shamrock</rt></rtc><rtc lang="fr"><rt>Trèfle</rt></rtc>
+<rb>✶</rb><rtc><rt>Star</rt></rtc><rtc lang="fr"><rt>Étoile</rt></rtc>
+</ruby>
+</p>
+!! end
+
 !! test
 Non-word characters don't terminate tag names (bug 17663, 40670, 52022)
 !! wikitext
@@ -2583,41 +2622,28 @@ File:foobar.jpg
 !!end
 
 !! test
-Leading pipes outside of tables
-!! options
-parsoid
-!! wikitext
-| foo
-!! html
-<p>| foo</p>
-!! end
-
-!! test
-Leading pipes outside of tables 2
-!! options
-parsoid
-!! wikitext
-a
-| foo
-b
-!! html
-<p>a
-| foo
-b</p>
-!! end
-
-!! test
-Leading pipes outside of tables 3
-!! options
-parsoid
+Table wikitext syntax outside wiki-tables
 !! wikitext
 a
+! not a table heading
+|- not a table row
+| not a table cell
 | class="foo bar" | baz
 b
+|}
+|-
+c
 !! html
 <p>a
+! not a table heading
+|- not a table row
+| not a table cell
 | class="foo bar" | baz
-b</p>
+b
+|}
+|-
+c
+</p>
 !! end
 
 !!test
@@ -6129,6 +6155,16 @@ Link with multiple ":" in a subpage-supporting namespace (bug 63636)
 <p><a rel="mw:WikiLink" href="./User:Foo/Test/63636:Bar">Test</a></p>
 !! end
 
+!! test
+Purely hash wikilink
+!! options
+title=[[User:test/123]]
+!! wikitext
+[[#a|b]]
+!! html/parsoid
+<p data-parsoid='{}'><a rel="mw:WikiLink" href="../User:Test/123#a" data-parsoid='{"stx":"piped","a":{"href":"../User:Test/123#a"},"sa":{"href":"#a"}}'>b</a></p>
+!! end
+
 !! test
 1. Interaction of linktrail and template encapsulation
 !! options
@@ -6366,9 +6402,12 @@ Interlanguage link
 !! wikitext
 Blah blah blah
 [[zh:Chinese]]
-!! html
+!! html/php
 <p>Blah blah blah
 </p>
+!! html/parsoid
+<p>Blah blah blah
+<link rel="mw:PageProp/Language" href="//zh.wikipedia.org/wiki/Chinese"/></p>
 !! end
 
 !! test
@@ -6377,9 +6416,13 @@ Double interlanguage link
 Blah blah blah
 [[es:Spanish]]
 [[zh:Chinese]]
-!! html
+!! html/php
 <p>Blah blah blah
 </p>
+!! html/parsoid
+<p>Blah blah blah
+<link rel="mw:PageProp/Language" href="//es.wikipedia.org/wiki/Spanish"/>
+<link rel="mw:PageProp/Language" href="//zh.wikipedia.org/wiki/Chinese"/></p>
 !! end
 
 !! test
@@ -6389,9 +6432,12 @@ language=ln
 !! wikitext
 Blah blah blah
 [[zh:Chinese]]
-!! html
+!! html/php
 <p>Blah blah blah
 </p>
+!! html/parsoid
+<p>Blah blah blah
+<link rel="mw:PageProp/Language" href="//zh.wikipedia.org/wiki/Chinese"/></p>
 !! end
 
 !! test
@@ -6402,19 +6448,26 @@ language=ln
 Blah blah blah
 [[es:Spanish]]
 [[zh:Chinese]]
-!! html
+!! html/php
 <p>Blah blah blah
 </p>
+!! html/parsoid
+<p>Blah blah blah
+<link rel="mw:PageProp/Language" href="//es.wikipedia.org/wiki/Spanish"/>
+<link rel="mw:PageProp/Language" href="//zh.wikipedia.org/wiki/Chinese"/></p>
 !! end
 
 !! test
 "Extra" interlanguage links (bug 32189 / gerrit 111390)
 !! wikitext
 Blah blah blah
-[[mul:Multilingual]]
-!! html
+[[mul:Article]]
+!! html/php
 <p>Blah blah blah
 </p>
+!! html/parsoid
+<p>Blah blah blah
+<link rel="mw:PageProp/Language" title="Multilingual" href="//wikisource.org/wiki/Article"/></p>
 !! end
 
 !! test
@@ -8674,6 +8727,42 @@ Un-closed <includeonly>
 !! html
 !! end
 
+!! test
+Includes and comments at SOL
+!! wikitext
+<!-- comment --><noinclude><!-- comment --></noinclude><!-- comment -->== hu ==
+
+<noinclude>
+some
+</noinclude>* stuff
+* here
+
+<includeonly>can have stuff</includeonly>=== here ===
+
+!! html/php
+<h2><span class="mw-headline" id="hu">hu</span></h2>
+<p>some
+</p>
+<ul><li> stuff</li>
+<li> here</li></ul>
+<h3><span class="mw-headline" id="here">here</span></h3>
+
+!! html/parsoid
+<!-- comment --><meta typeof="mw:Includes/NoInclude" data-parsoid='{"src":"&lt;noinclude>"}'/><!-- comment --><meta typeof="mw:Includes/NoInclude/End" data-parsoid='{"src":"&lt;/noinclude>"}'/><!-- comment -->
+<h2 data-parsoid='{}'> hu </h2>
+
+<meta typeof="mw:Includes/NoInclude" data-parsoid='{"src":"&lt;noinclude>"}'/>
+
+<p data-parsoid='{}'>some</p>
+<meta typeof="mw:Includes/NoInclude/End" data-parsoid='{"src":"&lt;/noinclude>"}'/>
+<ul data-parsoid='{}'>
+<li data-parsoid='{}'> stuff</li>
+
+<li data-parsoid='{}'> here</li></ul>
+
+<h3 data-parsoid='{}'> here </h3>
+!! end
+
 # TODO: test with DOM fragment reuse!
 !! test
 Parsoid: DOM fragment reuse
@@ -8843,9 +8932,10 @@ parsoid=wt2html,wt2wt
 |c
 |}
 !!html/parsoid
-<meta typeof="mw:Includes/IncludeOnly" data-parsoid='{"src":"&lt;includeonly>a&lt;/includeonly>"}'/><meta typeof="mw:Includes/IncludeOnly/End" data-parsoid='{"src":"&lt;/includeonly>"}'/><span data-parsoid='{"fostered":true,"autoInsertedEnd":true,"autoInsertedStart":true}'>{{{b}}}</span><table about="#mwt1" typeof="mw:Param" data-parsoid='{"a":{" ":null},"sa":{" ":""},"src":"{| {{{b}}}\n|c\n|}"}'>
+<meta typeof="mw:Includes/IncludeOnly" data-parsoid='{"src":"&lt;includeonly>a&lt;/includeonly>"'/><meta typeof="mw:Includes/IncludeOnly/End" data-parsoid='{"src":""}'/><table about="#mwt2" typeof="mw:ExpandedAttrs" data-mw='{"attribs":[[{"txt":"{{{b}}}","html":"&lt;span about=\"#mwt1\" typeof=\"mw:Param\" data-parsoid=\"{&amp;quot;dsr&amp;quot;:[31,38,null,null],&amp;quot;src&amp;quot;:&amp;quot;{{{b}}}&amp;quot;}\">{{{b}}}&lt;/span>"},{"html":""}]]}' data-parsoid='{"a":{"{{{b}}}":null},"sa":{"{{{b}}}":""}}'>
 <tbody><tr><td>c</td></tr>
 </tbody></table>
+
 !!end
 
 ###
@@ -11886,15 +11976,19 @@ parsoid
 ### Inter-language links
 ###
 !! test
-Inter-language links
+Interlanguage links
 !! options
 ill
 !! wikitext
 [[es:Alimento]]
 [[fr:Nourriture]]
-[[zh:&#39135;&#21697;]]
-!! html
+[[zh:食品]]
+!! html/php
 es:Alimento fr:Nourriture zh:食品
+!! html/parsoid
+<p><link rel="mw:PageProp/Language" href="//es.wikipedia.org/wiki/Alimento"/>
+<link rel="mw:PageProp/Language" href="//fr.wikipedia.org/wiki/Nourriture"/>
+<link rel="mw:PageProp/Language" href="//zh.wikipedia.org/wiki/食品"/></p>
 !! end
 
 !! test
@@ -11906,8 +12000,13 @@ ill
 [[es:2]]
 [[fr:1]]
 [[fr:2]]
-!! html
+!! html/php
 es:1 fr:1
+!! html/parsoid
+<p><link rel="mw:PageProp/Language" href="//es.wikipedia.org/wiki/1"/>
+<link rel="mw:PageProp/Language" href="//es.wikipedia.org/wiki/2"/>
+<link rel="mw:PageProp/Language" href="//fr.wikipedia.org/wiki/1"/>
+<link rel="mw:PageProp/Language" href="//fr.wikipedia.org/wiki/2"/></p>
 !! end
 
 ###
@@ -18436,12 +18535,12 @@ B <ref group="X" name="b" />
 <ref name="b">foo</ref>
 </references>
 !! html
-<p>A <span about="#mwt2" class="reference" data-mw='{"name":"ref","body":{"html":"foo bar for a"},"attrs":{}}' id="cite_ref-2-0" rel="dc:references" typeof="mw:Extension/ref" data-parsoid='{"src":"&lt;ref>foo bar for a&lt;/ref>"}'><a href="#cite_note-2" data-parsoid="{}">[2]</a></span>
-B <span about="#mwt4" class="reference" data-mw='{"name":"ref","attrs":{"group":"X","name":"b"}}' id="cite_ref-b-3-0" rel="dc:references" typeof="mw:Extension/ref" data-parsoid='{"src":"&lt;ref name=\"b\" group=\"X\" />"}'><a href="#cite_note-b-3" data-parsoid="{}">[X 1]</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" data-parsoid="{}">[1]</a></span>
+B <span about="#mwt4" class="reference" data-mw='{"name":"ref","attrs":{"group":"X","name":"b"}}' id="cite_ref-b-2-0" rel="dc:references" typeof="mw:Extension/ref" data-parsoid='{"src":"&lt;ref group=\"X\" name=\"b\" />"}'><a href="#cite_note-b-2" data-parsoid="{}">[X 1]</a></span></p>
 
-<ol class="references" typeof="mw:Extension/references" about="#mwt6" data-parsoid='{"src":"&lt;references />"}' data-mw='{"name":"references","attrs":{}}'><li about="#cite_note-b-1" id="cite_note-b-1" data-parsoid="{}"><span rel="mw:referencedBy" data-parsoid="{}">↑</span> foo</li><li about="#cite_note-2" id="cite_note-2" data-parsoid="{}"><span rel="mw:referencedBy" data-parsoid="{}"><a href="#cite_ref-2-0" data-parsoid="{}">↑</a></span> foo bar for a</li></ol>
+<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" data-parsoid="{}"><a href="#cite_ref-1-0" data-parsoid="{}">↑</a></span> foo bar for a</li></ol>
 
-<ol class="references" typeof="mw:Extension/references" about="#mwt8" data-parsoid='{"src":"&lt;references group=\"X\">\n&lt;ref name=\"b\">foo&lt;/ref>\n&lt;/references>","group":"X"}' 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":{"group":"X"}}'><li about="#cite_note-b-3" id="cite_note-b-3" data-parsoid="{}"><span rel="mw:referencedBy" data-parsoid="{}"><a href="#cite_ref-b-3-0" data-parsoid="{}">↑</a></span> </li></ol>
+<ol class="references" typeof="mw:Extension/references" about="#mwt8" data-parsoid='{"src":"&lt;references group=\"X\">\n&lt;ref name=\"b\">foo&lt;/ref>\n&lt;/references>","group":"X"}' 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-2\">[X 1]&lt;/a>&lt;/span>\n"},"attrs":{"group":"X"}}'><li about="#cite_note-b-2" id="cite_note-b-2" data-parsoid="{}"><span rel="mw:referencedBy" data-parsoid="{}"><a href="#cite_ref-b-2-0" data-parsoid="{}">↑</a></span> foo</li></ol>
 !! end
 
 !! test
@@ -19582,6 +19681,16 @@ parsoid
  <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>caption</figcaption></figure>
 !! end
 
+!! test
+5. Nowiki escaping should account for indent-pres
+!! options
+parsoid=html2wt
+!! html
+<pre>==foo==</pre>
+!! wikitext
+ ==foo==
+!! end
+
 #### --------------- Behavior Switches --------------------
 !! test
 1. Valid behavior switches should be escaped
@@ -20374,6 +20483,17 @@ parsoid=html2wt
 # All these tests are marked Parsoid html2wt and html2html only
 # ----------------------------------------------------------------
 
+!! test
+Serialize interwiki links pointing to the current wiki as plain wiki links (bug 65869)
+!! options
+parsoid=html2wt
+language=es
+!! wikitext
+[[Foo]]
+!! html
+<p><a rel="mw:ExtLink" href="http://es.wikipedia.org/wiki/Foo">Foo</a></p>
+!! end
+
 !! test
 Image: Modifying size of an image (1)
 !! options
index daf4bd9..f316f56 100644 (file)
@@ -43,6 +43,8 @@ class ResourceLoaderTestModule extends ResourceLoaderModule {
        protected $dependencies = array();
        protected $group = null;
        protected $source = 'local';
+       protected $script = '';
+       protected $styles = '';
        protected $skipFunction = null;
        protected $targets = array( 'test' );
 
@@ -52,6 +54,14 @@ class ResourceLoaderTestModule extends ResourceLoaderModule {
                }
        }
 
+       public function getScript( ResourceLoaderContext $context ) {
+               return $this->script;
+       }
+
+       public function getStyles( ResourceLoaderContext $context ) {
+               return array( '' => $this->styles );
+       }
+
        public function getDependencies() {
                return $this->dependencies;
        }
index ca132a4..9913f68 100644 (file)
@@ -55,3 +55,7 @@ Bishzilla_blink.gif
 https://commons.wikimedia.org/wiki/File:Bishzilla_blink.gif
 Public domain
 Bishonen
+
+say-test.ogg
+Public domain
+Brian Wolff
diff --git a/tests/phpunit/data/media/say-test.ogg b/tests/phpunit/data/media/say-test.ogg
new file mode 100644 (file)
index 0000000..5d814fb
Binary files /dev/null and b/tests/phpunit/data/media/say-test.ogg differ
index 7c684d5..e22f505 100644 (file)
@@ -6,7 +6,7 @@ class GitInfoTest extends MediaWikiTestCase {
 
        protected function setUp() {
                parent::setUp();
-               $this->setMwGlobals( 'wgCacheDirectory', __DIR__ . '/../data' );
+               $this->setMwGlobals( 'wgGitInfoCacheDirectory', __DIR__ . '/../data/gitinfo' );
        }
 
        public function testValidJsonData() {
index 06b512d..91b531d 100644 (file)
@@ -369,6 +369,8 @@ class GlobalTest extends MediaWikiTestCase {
         * @covers ::swap
         */
        public function testSwapVarsTest() {
+               $this->hideDeprecated( 'swap' );
+
                $var1 = 1;
                $var2 = 2;
 
index e934965..c561e70 100644 (file)
@@ -112,7 +112,8 @@ class HtmlTest extends MediaWikiTestCase {
                        Html::expandAttributes( array( 'foo' => false ) ),
                        'skip keys with false value'
                );
-               $this->assertNotEmpty(
+               $this->assertEquals(
+                       ' foo=""',
                        Html::expandAttributes( array( 'foo' => '' ) ),
                        'keep keys with an empty string'
                );
@@ -153,6 +154,33 @@ class HtmlTest extends MediaWikiTestCase {
                );
        }
 
+       /**
+        * @covers HTML::expandAttributes
+        */
+       public function testExpandAttributesForNumbers() {
+               $this->assertEquals(
+                       ' value=1',
+                       Html::expandAttributes( array( 'value' => 1 ) ),
+                       'Integer value is cast to a string'
+               );
+               $this->assertEquals(
+                       ' value=1.1',
+                       Html::expandAttributes( array( 'value' => 1.1 ) ),
+                       'Float value is cast to a string'
+               );
+       }
+
+       /**
+        * @covers HTML::expandAttributes
+        */
+       public function testExpandAttributesForObjects() {
+               $this->assertEquals(
+                       ' value=stringValue',
+                       Html::expandAttributes( array( 'value' => new HtmlTestValue() ) ),
+                       'Object value is converted to a string'
+               );
+       }
+
        /**
         * Test for Html::expandAttributes()
         * Please note it output a string prefixed with a space!
@@ -299,6 +327,21 @@ class HtmlTest extends MediaWikiTestCase {
                );
        }
 
+       /**
+        * @covers Html::expandAttributes
+        * @expectedException MWException
+        */
+       public function testExpandAttributes_ArrayOnNonListValueAttribute_ThrowsException() {
+               // Real-life test case found in the Popups extension (see Gerrit cf0fd64),
+               // when used with an outdated BetaFeatures extension (see Gerrit deda1e7)
+               Html::expandAttributes( array(
+                       'src' => array(
+                               'ltr' => 'ltr.svg',
+                               'rtl' => 'rtl.svg'
+                       )
+               ) );
+       }
+
        /**
         * @covers Html::namespaceSelector
         */
@@ -665,3 +708,9 @@ class HtmlTest extends MediaWikiTestCase {
                );
        }
 }
+
+class HtmlTestValue {
+       function __toString() {
+               return 'stringValue';
+       }
+}
diff --git a/tests/phpunit/includes/ImagePage404Test.php b/tests/phpunit/includes/ImagePage404Test.php
new file mode 100644 (file)
index 0000000..3660456
--- /dev/null
@@ -0,0 +1,53 @@
+<?php
+/**
+ * For doing Image Page tests that rely on 404 thumb handling
+ */
+class ImagePage404Test extends MediaWikiMediaTestCase {
+
+       protected function getRepoOptions() {
+               return parent::getRepoOptions() + array( 'transformVia404' => true );
+       }
+
+       function setUp() {
+               $this->setMwGlobals( 'wgImageLimits', array(
+                       array( 320, 240 ),
+                       array( 640, 480 ),
+                       array( 800, 600 ),
+                       array( 1024, 768 ),
+                       array( 1280, 1024 )
+               ) );
+               parent::setUp();
+       }
+
+       function getImagePage( $filename ) {
+               $title = Title::makeTitleSafe( NS_FILE, $filename );
+               $file = $this->dataFile( $filename );
+               $iPage = new ImagePage( $title );
+               $iPage->setFile( $file );
+               return $iPage;
+       }
+
+       /**
+        * @dataProvider providerGetThumbSizes
+        * @param $filename String
+        * @param $expectedNumberThumbs integer How many thumbnails to show
+        */
+       function testGetThumbSizes( $filename, $expectedNumberThumbs ) {
+               $iPage = $this->getImagePage( $filename );
+               $reflection = new ReflectionClass( $iPage );
+               $reflMethod = $reflection->getMethod( 'getThumbSizes' );
+               $reflMethod->setAccessible( true );
+
+               $actual = $reflMethod->invoke( $iPage, 545, 700 );
+               $this->assertEquals( count( $actual ), $expectedNumberThumbs );
+       }
+
+       function providerGetThumbSizes() {
+               return array(
+                       array( 'animated.gif', 6 ),
+                       array( 'Toll_Texas_1.svg', 6 ),
+                       array( '80x60-Greyscale.xcf', 6 ),
+                       array( 'jpeg-comment-binary.jpg', 6 ),
+               );
+       }
+}
diff --git a/tests/phpunit/includes/ImagePageTest.php b/tests/phpunit/includes/ImagePageTest.php
new file mode 100644 (file)
index 0000000..d5ecb95
--- /dev/null
@@ -0,0 +1,90 @@
+<?php
+class ImagePageTest extends MediaWikiMediaTestCase {
+
+       function setUp() {
+               $this->setMwGlobals( 'wgImageLimits', array(
+                       array( 320, 240 ),
+                       array( 640, 480 ),
+                       array( 800, 600 ),
+                       array( 1024, 768 ),
+                       array( 1280, 1024 )
+               ) );
+               parent::setUp();
+       }
+
+       function getImagePage( $filename ) {
+               $title = Title::makeTitleSafe( NS_FILE, $filename );
+               $file = $this->dataFile( $filename );
+               $iPage = new ImagePage( $title );
+               $iPage->setFile( $file );
+               return $iPage;
+       }
+
+       /**
+        * @dataProvider providerGetDisplayWidthHeight
+        * @param $dimensions Array [maxWidth, maxHeight, width, height]
+        * @param $expected Array [width, height] The width and height we expect to display at
+        */
+       function testGetDisplayWidthHeight( $dim, $expected ) {
+               $iPage = $this->getImagePage( 'animated.gif' );
+               $reflection = new ReflectionClass( $iPage );
+               $reflMethod = $reflection->getMethod( 'getDisplayWidthHeight' );
+               $reflMethod->setAccessible( true );
+
+               $actual = $reflMethod->invoke( $iPage, $dim[0], $dim[1], $dim[2], $dim[3] );
+               $this->assertEquals( $actual, $expected );
+       }
+
+       function providerGetDisplayWidthHeight() {
+               return array(
+                       array(
+                               array( 1024.0, 768.0, 600.0, 600.0 ),
+                               array( 600.0, 600.0 )
+                       ),
+                       array(
+                               array( 1024.0, 768.0, 1600.0, 600.0 ),
+                               array( 1024.0, 384.0 )
+                       ),
+                       array(
+                               array( 1024.0, 768.0, 1024.0, 768.0 ),
+                               array( 1024.0, 768.0 )
+                       ),
+                       array(
+                               array( 1024.0, 768.0, 800.0, 1000.0 ),
+                               array( 614.0, 768.0 )
+                       ),
+                       array(
+                               array( 1024.0, 768.0, 0, 1000 ),
+                               array( 0, 0 )
+                       ),
+                       array(
+                               array( 1024.0, 768.0, 2000, 0 ),
+                               array( 0, 0 )
+                       ),
+               );
+       }
+
+       /**
+        * @dataProvider providerGetThumbSizes
+        * @param $filename String
+        * @param $expectedNumberThumbs integer How many thumbnails to show
+        */
+       function testGetThumbSizes( $filename, $expectedNumberThumbs ) {
+               $iPage = $this->getImagePage( $filename );
+               $reflection = new ReflectionClass( $iPage );
+               $reflMethod = $reflection->getMethod( 'getThumbSizes' );
+               $reflMethod->setAccessible( true );
+
+               $actual = $reflMethod->invoke( $iPage, 545, 700 );
+               $this->assertEquals( count( $actual ), $expectedNumberThumbs );
+       }
+
+       function providerGetThumbSizes() {
+               return array(
+                       array( 'animated.gif', 2 ),
+                       array( 'Toll_Texas_1.svg', 1 ),
+                       array( '80x60-Greyscale.xcf', 1 ),
+                       array( 'jpeg-comment-binary.jpg', 2 ),
+               );
+       }
+}
index 4d62cc7..72114e9 100644 (file)
@@ -94,6 +94,7 @@ class LinkerTest extends MediaWikiLangTestCase {
                        'wgScript' => '/wiki/index.php',
                        'wgArticlePath' => '/wiki/$1',
                        'wgWellFormedXml' => true,
+                       'wgCapitalLinks' => true,
                ) );
 
                if ( $title === false ) {
index 9ff547c..a5dac8d 100644 (file)
@@ -186,6 +186,10 @@ class LinksUpdateTest extends MediaWikiTestCase {
         * @covers ParserOutput::addLanguageLink
         */
        public function testUpdate_langlinks() {
+               $this->setMwGlobals( array(
+                       'wgCapitalLinks' => true,
+               ) );
+
                /** @var ParserOutput $po */
                list( $t, $po ) = $this->makeTitleAndParserOutput( "Testing", 111 );
 
diff --git a/tests/phpunit/includes/MimeMagicTest.php b/tests/phpunit/includes/MimeMagicTest.php
new file mode 100644 (file)
index 0000000..a164ff9
--- /dev/null
@@ -0,0 +1,48 @@
+<?php
+class MimeMagicTest extends MediaWikiTestCase {
+
+       /** @var MimeMagic */
+       private $mimeMagic;
+
+       function setUp() {
+               $this->mimeMagic = MimeMagic::singleton();
+               parent::setUp();
+       }
+
+       /**
+        * @dataProvider providerImproveTypeFromExtension
+        * @param $ext String File extension (no leading dot)
+        * @param $oldMime String Initially detected mime
+        * @param $expectedMime String Mime type after taking extension into account
+        */
+       function testImproveTypeFromExtension( $ext, $oldMime, $expectedMime ) {
+               $actualMime = $this->mimeMagic->improveTypeFromExtension( $oldMime, $ext );
+               $this->assertEquals( $expectedMime, $actualMime );
+       }
+
+       function providerImproveTypeFromExtension() {
+               return array(
+                       array( 'gif', 'image/gif', 'image/gif' ),
+                       array( 'gif', 'unknown/unknown', 'unknown/unknown' ),
+                       array( 'wrl', 'unknown/unknown', 'model/vrml' ),
+                       array( 'txt', 'text/plain', 'text/plain' ),
+                       array( 'csv', 'text/plain', 'text/csv' ),
+                       array( 'tsv', 'text/plain', 'text/tab-separated-values' ),
+                       array( 'json', 'text/plain', 'application/json' ),
+                       array( 'foo', 'application/x-opc+zip', 'application/zip' ),
+                       array( 'docx', 'application/x-opc+zip', 'application/vnd.openxmlformats-officedocument.wordprocessingml.document' ),
+                       array( 'djvu', 'image/x-djvu', 'image/vnd.djvu' ),
+                       array( 'wav', 'audio/wav', 'audio/wav' ),
+               );
+       }
+
+       /**
+        * Test to make sure that encoder=ffmpeg2theora doesn't trigger
+        * MEDIATYPE_VIDEO (bug 63584)
+        */
+       function testOggRecognize() {
+               $oggFile = __DIR__ . '/../data/media/say-test.ogg';
+               $actualType = $this->mimeMagic->getMediaType( $oggFile, 'application/ogg' );
+               $this->assertEquals( $actualType, MEDIATYPE_AUDIO );
+       }
+}
index 385cee5..542b3d6 100644 (file)
@@ -135,4 +135,88 @@ class OutputPageTest extends MediaWikiTestCase {
                        'message' => 'On request with handheld querystring and media is screen, returns null'
                ) );
        }
+
+       public static function provideMakeResourceLoaderLink() {
+               return array(
+                       // Load module script only
+                       array(
+                               array( 'test.foo', ResourceLoaderModule::TYPE_SCRIPTS ),
+                               '<script src="http://127.0.0.1:8080/w/load.php?debug=false&amp;lang=en&amp;modules=test.foo&amp;only=scripts&amp;skin=vector&amp;*"></script>
+'
+                       ),
+                       // Load module styles only
+                       // This also tests the order the modules are put into the url
+                       array(
+                               array( array( 'test.baz', 'test.foo', 'test.bar' ), ResourceLoaderModule::TYPE_STYLES ),
+                               '<link rel=stylesheet href="http://127.0.0.1:8080/w/load.php?debug=false&amp;lang=en&amp;modules=test.bar%2Cbaz%2Cfoo&amp;only=styles&amp;skin=vector&amp;*">
+'
+                       ),
+                       // Load private module (combined)
+                       array(
+                               array( 'test.quux', ResourceLoaderModule::TYPE_COMBINED ),
+                               '<script>if(window.mw){
+mw.loader.implement("test.quux",function($,jQuery){mw.test.baz({token:123});},{"css":[".mw-icon{transition:none}\n/* cache key: wiki:resourceloader:filter:minify-css:7:fd8ea20b3336b2bfb230c789d430067a */"]},{});
+/* cache key: wiki:resourceloader:filter:minify-js:7:274ccee17be73cd5f4dda5dc2a819188 */
+}</script>
+'
+                       ),
+                       // Load module script with with ESI
+                       array(
+                               array( 'test.foo', ResourceLoaderModule::TYPE_SCRIPTS, true ),
+                               '<script><esi:include src="http://127.0.0.1:8080/w/load.php?debug=false&amp;lang=en&amp;modules=test.foo&amp;only=scripts&amp;skin=vector&amp;*" /></script>
+'
+                       ),
+                       // Load module styles with with ESI
+                       array(
+                               array( 'test.foo', ResourceLoaderModule::TYPE_STYLES, true ),
+                               '<style><esi:include src="http://127.0.0.1:8080/w/load.php?debug=false&amp;lang=en&amp;modules=test.foo&amp;only=styles&amp;skin=vector&amp;*" /></style>
+',
+                       ),
+               );
+       }
+
+
+       /**
+        * @dataProvider provideMakeResourceLoaderLink
+        * @covers OutputPage::makeResourceLoaderLink
+        */
+       public function testMakeResourceLoaderLink( $args, $expectedHtml) {
+               $this->setMwGlobals( array(
+                       'wgResourceLoaderUseESI' => true,
+                       'wgLoadScript' => 'http://127.0.0.1:8080/w/load.php',
+                       // Affects whether CDATA is inserted
+                       'wgWellFormedXml' => false,
+                       // Cache key is based on database name, and affects output;
+                       // this test should not touch the database anyways.
+                       'wgDBname' => 'wiki',
+                       'wgDBprefix' => '',
+               ) );
+               $class = new ReflectionClass( 'OutputPage' );
+               $method = $class->getMethod( 'makeResourceLoaderLink' );
+               $method->setAccessible( true );
+               $ctx = new RequestContext();
+               $out = new OutputPage( $ctx );
+               $rl = $out->getResourceLoader();
+               $rl->register( array(
+                       'test.foo' => new ResourceLoaderTestModule(array(
+                               'script' => 'mw.test.foo( { a: true } );',
+                               'styles' => '.mw-test-foo { content: "style"; }',
+                       )),
+                       'test.bar' => new ResourceLoaderTestModule(array(
+                               'script' => 'mw.test.bar( { a: true } );',
+                               'styles' => '.mw-test-bar { content: "style"; }',
+                       )),
+                       'test.baz' => new ResourceLoaderTestModule(array(
+                               'script' => 'mw.test.baz( { a: true } );',
+                               'styles' => '.mw-test-baz { content: "style"; }',
+                       )),
+                       'test.quux' => new ResourceLoaderTestModule(array(
+                               'script' => 'mw.test.baz( { token: 123 } );',
+                               'styles' => '/* pref-animate=off */ .mw-icon { transition: none; }',
+                               'group' => 'private',
+                       )),
+               ) );
+               $links = $method->invokeArgs( $out, $args );
+               $this->assertEquals( $expectedHtml, $links['html'] );
+       }
 }
index 758c2e2..6fdc239 100644 (file)
@@ -16,6 +16,7 @@ class TestSample extends MediaWikiLangTestCase {
                $this->setMwGlobals( array(
                        'wgContLang' => Language::factory( 'en' ),
                        'wgLanguageCode' => 'en',
+                       'wgCapitalLinks' => true,
                ) );
        }
 
index ac80a9a..988a4a4 100644 (file)
@@ -41,6 +41,9 @@ class TitlePermissionTest extends MediaWikiLangTestCase {
                                NS_MEDIAWIKI => 'editinterface',
                        ),
                ) );
+               // Without this testUserBlock will use a non-English context on non-English MediaWiki
+               // installations (because of how Title::checkUserBlock is implemented) and fail.
+               RequestContext::resetMain();
 
                $this->userName = 'Useruser';
                $this->altUserName = 'Altuseruser';
index 1c7b662..6871582 100644 (file)
@@ -87,6 +87,7 @@ class TitleTest extends MediaWikiTestCase {
                        str_repeat( 'x', 252 ),
                        // interwiki prefix
                        'localtestiw: #anchor',
+                       'localtestiw:',
                        'localtestiw:foo',
                        'localtestiw: foo # anchor',
                        'localtestiw: Talk: Sandbox # anchor',
@@ -147,7 +148,6 @@ class TitleTest extends MediaWikiTestCase {
                        'Category: ',
                        'Category: #bar',
                        // interwiki prefix
-                       'localtestiw:',
                        'localtestiw: Talk: # anchor',
                        'localtestiw: Talk:'
                ) as $text ) {
index a19d035..36de114 100644 (file)
@@ -125,6 +125,31 @@ class UserTest extends MediaWikiTestCase {
                );
        }
 
+       /**
+        * @dataProvider provideIPs
+        * @covers User::isIP
+        */
+       public function testIsIP( $value, $result, $message ) {
+               $this->assertEquals( $this->user->isIP( $value ), $result, $message );
+       }
+
+       public static function provideIPs() {
+               return array(
+                       array( '', false, 'Empty string' ),
+                       array( ' ', false, 'Blank space' ),
+                       array( '10.0.0.0', true, 'IPv4 private 10/8' ),
+                       array( '10.255.255.255', true, 'IPv4 private 10/8' ),
+                       array( '192.168.1.1', true, 'IPv4 private 192.168/16' ),
+                       array( '203.0.113.0', true, 'IPv4 example' ),
+                       array( '2002:ffff:ffff:ffff:ffff:ffff:ffff:ffff', true, 'IPv6 example' ),
+                       // Not valid IPs but classified as such by MediaWiki for negated asserting
+                       // of whether this might be the identifier of a logged-out user or whether
+                       // to allow usernames like it.
+                       array( '300.300.300.300', true, 'Looks too much like an IPv4 address' ),
+                       array( '203.0.113.xxx', true, 'Assigned by UseMod to cloaked logged-out users' ),
+               );
+       }
+
        /**
         * @dataProvider provideUserNames
         * @covers User::isValidUserName
@@ -148,6 +173,9 @@ class UserTest extends MediaWikiTestCase {
                        array( 'Abcdകഖഗഘ', true, ' Mixed scripts' ),
                        array( 'ജോസ്‌തോമസ്', false, 'ZWNJ- Format control character' ),
                        array( 'Ab cd', false, ' Ideographic space' ),
+                       array( '300.300.300.300', false, 'Looks too much like an IPv4 address' ),
+                       array( '302.113.311.900', false, 'Looks too much like an IPv4 address' ),
+                       array( '203.0.113.xxx', false, 'Reserved for usage by UseMod for cloaked logged-out users' ),
                );
        }
 
@@ -157,7 +185,7 @@ class UserTest extends MediaWikiTestCase {
         * Extensions and core
         */
        public function testAllRightsWithMessage() {
-               //Getting all user rights, for core: User::$mCoreRights, for extensions: $wgAvailableRights
+               // Getting all user rights, for core: User::$mCoreRights, for extensions: $wgAvailableRights
                $allRights = User::getAllRights();
                $allMessageKeys = Language::getMessageKeysFor( 'en' );
 
index 78457d2..7f7945b 100644 (file)
@@ -499,6 +499,10 @@ class WikiPageTest extends MediaWikiLangTestCase {
         * @covers WikiPage::getRedirectTarget
         */
        public function testGetRedirectTarget( $title, $model, $text, $target ) {
+               $this->setMwGlobals( array(
+                       'wgCapitalLinks' => true,
+               ) );
+
                $page = $this->createPage( $title, $text, $model );
 
                # sanity check, because this test seems to fail for no reason for some people.
index e031ce3..5f955bb 100644 (file)
@@ -17,7 +17,7 @@ class ApiOptionsTest extends MediaWikiLangTestCase {
        /** @var DerivativeContext */
        private $mContext;
 
-       private $mOldGetPreferencesHooks = false;
+       private $mOldGetPreferencesHooks;
 
        private static $Success = array( 'options' => 'success' );
 
@@ -61,10 +61,8 @@ class ApiOptionsTest extends MediaWikiLangTestCase {
        protected function tearDown() {
                global $wgHooks;
 
-               if ( $this->mOldGetPreferencesHooks !== false ) {
-                       $wgHooks['GetPreferences'] = $this->mOldGetPreferencesHooks;
-                       $this->mOldGetPreferencesHooks = false;
-               }
+               $wgHooks['GetPreferences'] = $this->mOldGetPreferencesHooks;
+               $this->mOldGetPreferencesHooks = false;
 
                parent::tearDown();
        }
index ea0b323..7b686a3 100644 (file)
@@ -36,9 +36,12 @@ class ApiQueryTest extends ApiTestCase {
        }
 
        public function testTitlesGetNormalized() {
-
                global $wgMetaNamespace;
 
+               $this->setMwGlobals( array(
+                       'wgCapitalLinks' => true,
+               ) );
+
                $data = $this->doApiRequest( array(
                        'action' => 'query',
                        'titles' => 'Project:articleA|article_B' ) );
@@ -97,6 +100,10 @@ class ApiQueryTest extends ApiTestCase {
         * @dataProvider provideTestTitlePartToKey
         */
        function testTitlePartToKey( $titlePart, $namespace, $expected, $expectException ) {
+               $this->setMwGlobals( array(
+                       'wgCapitalLinks' => true,
+               ) );
+
                $api = new MockApiQueryBase();
                $exceptionCaught = false;
                try {
index 03cbbc0..2f81109 100644 (file)
@@ -31,6 +31,7 @@ class TextContentTest extends MediaWikiLangTestCase {
                        ),
                        'wgUseTidy' => false,
                        'wgAlwaysUseTidy' => false,
+                       'wgCapitalLinks' => true,
                ) );
 
                // bypass hooks that force custom rendering
index 91399be..e642177 100644 (file)
@@ -80,4 +80,62 @@ class MWDebugTest extends MediaWikiTestCase {
                        "Only one deprecated warning per function should be kept"
                );
        }
+
+       /**
+        * @covers MWDebug::appendDebugInfoToApiResult
+        */
+       public function testAppendDebugInfoToApiResultXmlFormat() {
+               $request = $this->newApiRequest(
+                       array( 'action' => 'help', 'format' => 'xml' ),
+                       '/api.php?action=help&format=xml'
+               );
+
+               $context = new RequestContext();
+               $context->setRequest( $request );
+
+               $apiMain = new ApiMain( $context );
+
+               $result = new ApiResult( $apiMain );
+               $result->setRawMode( true );
+
+               MWDebug::appendDebugInfoToApiResult( $context, $result );
+
+               $this->assertInstanceOf( 'ApiResult', $result );
+               $data = $result->getData();
+
+               $expectedKeys = array( 'mwVersion', 'phpVersion', 'gitRevision', 'gitBranch',
+                       'gitViewUrl', 'time', 'log', 'debugLog', 'queries', 'request', 'memory',
+                       'memoryPeak', 'includes', 'profile', '_element' );
+
+               foreach( $expectedKeys as $expectedKey ) {
+                       $this->assertArrayHasKey( $expectedKey, $data['debuginfo'], "debuginfo has $expectedKey" );
+               }
+
+               $xml = ApiFormatXml::recXmlPrint( 'help', $data );
+
+               // exception not thrown
+               $this->assertInternalType( 'string', $xml );
+       }
+
+       /**
+        * @param string[] $params
+        * @param string $requestUrl
+        *
+        * @return FauxRequest
+        */
+       private function newApiRequest( array $params, $requestUrl ) {
+               $request = $this->getMockBuilder( 'FauxRequest' )
+                       ->setMethods( array( 'getRequestURL' ) )
+                       ->setConstructorArgs( array(
+                               $params
+                       ) )
+                       ->getMock();
+
+               $request->expects( $this->any() )
+                       ->method( 'getRequestURL' )
+                       ->will( $this->returnValue( $requestUrl ) );
+
+               return $request;
+       }
+
 }
diff --git a/tests/phpunit/includes/filerepo/RepoGroupTest.php b/tests/phpunit/includes/filerepo/RepoGroupTest.php
new file mode 100644 (file)
index 0000000..2c52338
--- /dev/null
@@ -0,0 +1,57 @@
+<?php
+class RepoGroupTest extends MediaWikiTestCase {
+
+       function testHasForeignRepoNegative() {
+               $this->setMWGlobals( 'wgForeignFileRepos', array() );
+               RepoGroup::destroySingleton();
+               FileBackendGroup::destroySingleton();
+               $this->assertFalse( RepoGroup::singleton()->hasForeignRepos() );
+       }
+
+       function testHasForeignRepoPositive() {
+               $this->setUpForeignRepo();
+               $this->assertTrue( RepoGroup::singleton()->hasForeignRepos() );
+       }
+
+       function testForEachForeignRepo() {
+               $this->setUpForeignRepo();
+               $fakeCallback = $this->getMock( 'RepoGroupTestHelper' );
+               $fakeCallback->expects( $this->once() )->method( 'callback' );
+               RepoGroup::singleton()->forEachForeignRepo( array( $fakeCallback, 'callback' ), array( array() ) );
+       }
+
+       function testForEachForeignRepoNone() {
+               $this->setMWGlobals( 'wgForeignFileRepos', array() );
+               RepoGroup::destroySingleton();
+               FileBackendGroup::destroySingleton();
+               $fakeCallback = $this->getMock( 'RepoGroupTestHelper' );
+               $fakeCallback->expects( $this->never() )->method( 'callback' );
+               RepoGroup::singleton()->forEachForeignRepo( array( $fakeCallback, 'callback' ), array( array() ) );
+       }
+
+       private function setUpForeignRepo() {
+               global $wgUploadDirectory;
+               $this->setMWGlobals( 'wgForeignFileRepos', array( array(
+                       'class' => 'ForeignAPIRepo',
+                       'name' => 'wikimediacommons',
+                       'backend' => 'wikimediacommons-backend',
+                       'apibase' => 'https://commons.wikimedia.org/w/api.php',
+                       'hashLevels' => 2,
+                       'fetchDescription' => true,
+                       'descriptionCacheExpiry' => 43200,
+                       'apiThumbCacheExpiry' => 86400,
+                       'directory' => $wgUploadDirectory
+               ) ) );
+               RepoGroup::destroySingleton();
+               FileBackendGroup::destroySingleton();
+       }
+}
+
+/**
+ * Quick helper class to use as a mock callback for RepoGroup::singleton()->forEachForeignRepo.
+ */
+class RepoGroupTestHelper {
+       function callback( FileRepo $repo, array $foo ) {
+               return true;
+       }
+}
diff --git a/tests/phpunit/includes/filerepo/file/FileTest.php b/tests/phpunit/includes/filerepo/file/FileTest.php
new file mode 100644 (file)
index 0000000..9232ce4
--- /dev/null
@@ -0,0 +1,348 @@
+<?php
+
+class FileRepoFileTest extends MediaWikiMediaTestCase {
+       /**
+        * @dataProvider getThumbnailBucketProvider
+        * @covers File::getThumbnailBucket
+        */
+       public function testGetThumbnailBucket( $data ) {
+               $this->setMwGlobals( 'wgThumbnailBuckets', $data['buckets'] );
+               $this->setMwGlobals( 'wgThumbnailMinimumBucketDistance', $data['minimumBucketDistance'] );
+
+               $fileMock = $this->getMockBuilder( 'File' )
+                       ->setConstructorArgs( array( 'fileMock', false ) )
+                       ->setMethods( array( 'getWidth' ) )
+                       ->getMockForAbstractClass();
+
+               $fileMock->expects( $this->any() )->method( 'getWidth' )->will(
+                       $this->returnValue( $data['width'] ) );
+
+               $this->assertEquals(
+                       $data['expectedBucket'],
+                       $fileMock->getThumbnailBucket( $data['requestedWidth'] ),
+                       $data['message'] );
+       }
+
+       public function getThumbnailBucketProvider() {
+               $defaultBuckets = array( 256, 512, 1024, 2048, 4096 );
+
+               return array(
+                       array( array(
+                               'buckets' => $defaultBuckets,
+                               'minimumBucketDistance' => 0,
+                               'width' => 3000,
+                               'requestedWidth' => 120,
+                               'expectedBucket' => 256,
+                               'message' => 'Picking bucket bigger than requested size'
+                       ) ),
+                       array( array(
+                               'buckets' => $defaultBuckets,
+                               'minimumBucketDistance' => 0,
+                               'width' => 3000,
+                               'requestedWidth' => 300,
+                               'expectedBucket' => 512,
+                               'message' => 'Picking bucket bigger than requested size'
+                       ) ),
+                       array( array(
+                               'buckets' => $defaultBuckets,
+                               'minimumBucketDistance' => 0,
+                               'width' => 3000,
+                               'requestedWidth' => 1024,
+                               'expectedBucket' => 2048,
+                               'message' => 'Picking bucket bigger than requested size'
+                       ) ),
+                       array( array(
+                               'buckets' => $defaultBuckets,
+                               'minimumBucketDistance' => 0,
+                               'width' => 3000,
+                               'requestedWidth' => 2048,
+                               'expectedBucket' => false,
+                               'message' => 'Picking no bucket because none is bigger than the requested size'
+                       ) ),
+                       array( array(
+                               'buckets' => $defaultBuckets,
+                               'minimumBucketDistance' => 0,
+                               'width' => 3000,
+                               'requestedWidth' => 3500,
+                               'expectedBucket' => false,
+                               'message' => 'Picking no bucket because requested size is bigger than original'
+                       ) ),
+                       array( array(
+                               'buckets' => array( 1024 ),
+                               'minimumBucketDistance' => 0,
+                               'width' => 3000,
+                               'requestedWidth' => 1024,
+                               'expectedBucket' => false,
+                               'message' => 'Picking no bucket because requested size equals biggest bucket'
+                       ) ),
+                       array( array(
+                               'buckets' => null,
+                               'minimumBucketDistance' => 0,
+                               'width' => 3000,
+                               'requestedWidth' => 1024,
+                               'expectedBucket' => false,
+                               'message' => 'Picking no bucket because no buckets have been specified'
+                       ) ),
+                       array( array(
+                               'buckets' => array( 256, 512 ),
+                               'minimumBucketDistance' => 10,
+                               'width' => 3000,
+                               'requestedWidth' => 245,
+                               'expectedBucket' => 256,
+                               'message' => 'Requested width is distant enough from next bucket for it to be picked'
+                       ) ),
+                       array( array(
+                               'buckets' => array( 256, 512 ),
+                               'minimumBucketDistance' => 10,
+                               'width' => 3000,
+                               'requestedWidth' => 246,
+                               'expectedBucket' => 512,
+                               'message' => 'Requested width is too close to next bucket, picking next one'
+                       ) ),
+               );
+       }
+
+       /**
+        * @dataProvider getThumbnailSourceProvider
+        * @covers File::getThumbnailSource
+        */
+       public function testGetThumbnailSource( $data ) {
+               $backendMock = $this->getMockBuilder( 'FSFileBackend' )
+                       ->setConstructorArgs( array( array( 'name' => 'backendMock', 'wikiId' => wfWikiId() ) ) )
+                       ->getMock();
+
+               $repoMock = $this->getMockBuilder( 'FileRepo' )
+                       ->setConstructorArgs( array( array( 'name' => 'repoMock', 'backend' => $backendMock ) ) )
+                       ->setMethods( array( 'fileExists', 'getLocalReference' ) )
+                       ->getMock();
+
+               $fsFile = new FSFile( 'fsFilePath' );
+
+               $repoMock->expects( $this->any() )->method( 'fileExists' )->will(
+                       $this->returnValue( true ) );
+
+               $repoMock->expects( $this->any() )->method( 'getLocalReference' )->will(
+                       $this->returnValue( $fsFile ) );
+
+               $handlerMock = $this->getMock( 'BitmapHandler', array( 'supportsBucketing' ) );
+               $handlerMock->expects( $this->any() )->method( 'supportsBucketing' )->will(
+                       $this->returnValue( $data['supportsBucketing'] ) );
+
+               $fileMock = $this->getMockBuilder( 'File' )
+                       ->setConstructorArgs( array( 'fileMock', $repoMock ) )
+                       ->setMethods( array( 'getThumbnailBucket', 'getLocalRefPath', 'getHandler' ) )
+                       ->getMockForAbstractClass();
+
+               $fileMock->expects( $this->any() )->method( 'getThumbnailBucket' )->will(
+                       $this->returnValue( $data['thumbnailBucket'] ) );
+
+               $fileMock->expects( $this->any() )->method( 'getLocalRefPath' )->will(
+                       $this->returnValue( 'localRefPath' ) );
+
+               $fileMock->expects( $this->any() )->method( 'getHandler' )->will(
+                       $this->returnValue( $handlerMock ) );
+
+               $reflection = new ReflectionClass( $fileMock );
+               $reflection_property = $reflection->getProperty( 'handler' );
+               $reflection_property->setAccessible( true );
+               $reflection_property->setValue( $fileMock, $handlerMock );
+
+               if ( !is_null( $data['tmpBucketedThumbCache'] ) ) {
+                       $reflection_property = $reflection->getProperty( 'tmpBucketedThumbCache' );
+                       $reflection_property->setAccessible( true );
+                       $reflection_property->setValue( $fileMock, $data['tmpBucketedThumbCache'] );
+               }
+
+               $result = $fileMock->getThumbnailSource(
+                       array( 'physicalWidth' => $data['physicalWidth'] ) );
+
+               $this->assertEquals( $data['expectedPath'], $result['path'], $data['message'] );
+       }
+
+       public function getThumbnailSourceProvider() {
+               return array(
+                       array( array(
+                               'supportsBucketing' => true,
+                               'tmpBucketedThumbCache' => null,
+                               'thumbnailBucket' => 1024,
+                               'physicalWidth' => 2048,
+                               'expectedPath' => 'fsFilePath',
+                               'message' => 'Path downloaded from storage'
+                       ) ),
+                       array( array(
+                               'supportsBucketing' => true,
+                               'tmpBucketedThumbCache' => array( 1024 => '/tmp/shouldnotexist' + rand() ),
+                               'thumbnailBucket' => 1024,
+                               'physicalWidth' => 2048,
+                               'expectedPath' => 'fsFilePath',
+                               'message' => 'Path downloaded from storage because temp file is missing'
+                       ) ),
+                       array( array(
+                               'supportsBucketing' => true,
+                               'tmpBucketedThumbCache' => array( 1024 => '/tmp' ),
+                               'thumbnailBucket' => 1024,
+                               'physicalWidth' => 2048,
+                               'expectedPath' => '/tmp',
+                               'message' => 'Temporary path because temp file was found'
+                       ) ),
+                       array( array(
+                               'supportsBucketing' => false,
+                               'tmpBucketedThumbCache' => null,
+                               'thumbnailBucket' => 1024,
+                               'physicalWidth' => 2048,
+                               'expectedPath' => 'localRefPath',
+                               'message' => 'Original file path because bucketing is unsupported by handler'
+                       ) ),
+                       array( array(
+                               'supportsBucketing' => true,
+                               'tmpBucketedThumbCache' => null,
+                               'thumbnailBucket' => false,
+                               'physicalWidth' => 2048,
+                               'expectedPath' => 'localRefPath',
+                               'message' => 'Original file path because no width provided'
+                       ) ),
+               );
+       }
+
+       /**
+        * @dataProvider generateBucketsIfNeededProvider
+        * @covers File::generateBucketsIfNeeded
+        */
+       public function testGenerateBucketsIfNeeded( $data ) {
+               $this->setMwGlobals( 'wgThumbnailBuckets', $data['buckets'] );
+
+               $backendMock = $this->getMockBuilder( 'FSFileBackend' )
+                       ->setConstructorArgs( array( array( 'name' => 'backendMock', 'wikiId' => wfWikiId() ) ) )
+                       ->getMock();
+
+               $repoMock = $this->getMockBuilder( 'FileRepo' )
+                       ->setConstructorArgs( array( array( 'name' => 'repoMock', 'backend' => $backendMock ) ) )
+                       ->setMethods( array( 'fileExists', 'getLocalReference' ) )
+                       ->getMock();
+
+               $fileMock = $this->getMockBuilder( 'File' )
+                       ->setConstructorArgs( array( 'fileMock', $repoMock ) )
+                       ->setMethods( array( 'getWidth', 'getBucketThumbPath', 'makeTransformTmpFile', 'generateAndSaveThumb', 'getHandler' ) )
+                       ->getMockForAbstractClass();
+
+               $handlerMock = $this->getMock( 'JpegHandler', array( 'supportsBucketing' ) );
+               $handlerMock->expects( $this->any() )->method( 'supportsBucketing' )->will(
+                       $this->returnValue( true ) );
+
+               $fileMock->expects( $this->any() )->method( 'getHandler' )->will(
+                       $this->returnValue( $handlerMock ) );
+
+               $reflectionMethod = new ReflectionMethod( 'File', 'generateBucketsIfNeeded' );
+               $reflectionMethod->setAccessible( true );
+
+               $fileMock->expects( $this->any() )
+                       ->method( 'getWidth' )
+                       ->will( $this->returnValue( $data['width'] ) );
+
+               $fileMock->expects( $data['expectedGetBucketThumbPathCalls'] )
+                       ->method( 'getBucketThumbPath' );
+
+               $repoMock->expects( $data['expectedFileExistsCalls'] )
+                       ->method( 'fileExists' )
+                       ->will( $this->returnValue( $data['fileExistsReturn'] ) );
+
+               $fileMock->expects( $data['expectedMakeTransformTmpFile'] )
+                       ->method( 'makeTransformTmpFile' )
+                       ->will( $this->returnValue( $data['makeTransformTmpFileReturn'] ) );
+
+               $fileMock->expects( $data['expectedGenerateAndSaveThumb'] )
+                       ->method( 'generateAndSaveThumb' )
+                       ->will( $this->returnValue( $data['generateAndSaveThumbReturn'] ) );
+
+               $this->assertEquals( $data['expectedResult'],
+                       $reflectionMethod->invoke(
+                               $fileMock,
+                               array(
+                                       'physicalWidth' => $data['physicalWidth'],
+                                       'physicalHeight' => $data['physicalHeight'] )
+                               ),
+                               $data['message'] );
+       }
+
+       public function generateBucketsIfNeededProvider() {
+               $defaultBuckets = array( 256, 512, 1024, 2048, 4096 );
+
+               return array(
+                       array( array(
+                               'buckets' => $defaultBuckets,
+                               'width' => 256,
+                               'physicalWidth' => 256,
+                               'physicalHeight' => 100,
+                               'expectedGetBucketThumbPathCalls' => $this->never(),
+                               'expectedFileExistsCalls' => $this->never(),
+                               'fileExistsReturn' => null,
+                               'expectedMakeTransformTmpFile' => $this->never(),
+                               'makeTransformTmpFileReturn' => false,
+                               'expectedGenerateAndSaveThumb' => $this->never(),
+                               'generateAndSaveThumbReturn' => false,
+                               'expectedResult' => false,
+                               'message' => 'No bucket found, nothing to generate'
+                       ) ),
+                       array( array(
+                               'buckets' => $defaultBuckets,
+                               'width' => 5000,
+                               'physicalWidth' => 300,
+                               'physicalHeight' => 200,
+                               'expectedGetBucketThumbPathCalls' => $this->once(),
+                               'expectedFileExistsCalls' => $this->once(),
+                               'fileExistsReturn' => true,
+                               'expectedMakeTransformTmpFile' => $this->never(),
+                               'makeTransformTmpFileReturn' => false,
+                               'expectedGenerateAndSaveThumb' => $this->never(),
+                               'generateAndSaveThumbReturn' => false,
+                               'expectedResult' => false,
+                               'message' => 'File already exists, no reason to generate buckets'
+                       ) ),
+                       array( array(
+                               'buckets' => $defaultBuckets,
+                               'width' => 5000,
+                               'physicalWidth' => 300,
+                               'physicalHeight' => 200,
+                               'expectedGetBucketThumbPathCalls' => $this->once(),
+                               'expectedFileExistsCalls' => $this->once(),
+                               'fileExistsReturn' => false,
+                               'expectedMakeTransformTmpFile' => $this->once(),
+                               'makeTransformTmpFileReturn' => false,
+                               'expectedGenerateAndSaveThumb' => $this->never(),
+                               'generateAndSaveThumbReturn' => false,
+                               'expectedResult' => false,
+                               'message' => 'Cannot generate temp file for bucket'
+                       ) ),
+                       array( array(
+                               'buckets' => $defaultBuckets,
+                               'width' => 5000,
+                               'physicalWidth' => 300,
+                               'physicalHeight' => 200,
+                               'expectedGetBucketThumbPathCalls' => $this->once(),
+                               'expectedFileExistsCalls' => $this->once(),
+                               'fileExistsReturn' => false,
+                               'expectedMakeTransformTmpFile' => $this->once(),
+                               'makeTransformTmpFileReturn' => new TempFSFile( '/tmp/foo' ),
+                               'expectedGenerateAndSaveThumb' => $this->once(),
+                               'generateAndSaveThumbReturn' => false,
+                               'expectedResult' => false,
+                               'message' => 'Bucket image could not be generated'
+                       ) ),
+                       array( array(
+                               'buckets' => $defaultBuckets,
+                               'width' => 5000,
+                               'physicalWidth' => 300,
+                               'physicalHeight' => 200,
+                               'expectedGetBucketThumbPathCalls' => $this->once(),
+                               'expectedFileExistsCalls' => $this->once(),
+                               'fileExistsReturn' => false,
+                               'expectedMakeTransformTmpFile' => $this->once(),
+                               'makeTransformTmpFileReturn' => new TempFSFile( '/tmp/foo' ),
+                               'expectedGenerateAndSaveThumb' => $this->once(),
+                               'generateAndSaveThumbReturn' => new ThumbnailImage( false, 'bar', false, false ),
+                               'expectedResult' => true,
+                               'message' => 'Bucket image could not be generated'
+                       ) ),
+               );
+       }
+}
index bb5e398..2b4d60d 100644 (file)
@@ -291,6 +291,41 @@ class CSSMinTest extends MediaWikiTestCase {
                                '@import url(//localhost/styles.css?query=yes)',
                                '@import url(//localhost/styles.css?query=yes)',
                        ),
+                       array(
+                               'Simple case with comments before url',
+                               'foo { prop: /* some {funny;} comment */ url(bar.png); }',
+                               'foo { prop: /* some {funny;} comment */ url(http://localhost/w/bar.png); }',
+                       ),
+                       array(
+                               'Simple case with comments after url',
+                               'foo { prop: url(red.gif)/* some {funny;} comment */ ; }',
+                               'foo { prop: url(http://localhost/w/red.gif?timestamp)/* some {funny;} comment */ ; }',
+                       ),
+                       array(
+                               'Embedded file with comment before url',
+                               'foo { /* @embed */ background: /* some {funny;} comment */ url(red.gif); }',
+                               "foo { background: /* some {funny;} comment */ url($red); background: /* some {funny;} comment */ url(http://localhost/w/red.gif?timestamp)!ie; }",
+                       ),
+                       array(
+                               'Embedded file with comments inside and outside the rule',
+                               'foo { /* @embed */ background: url(red.gif) /* some {foo;} comment */; /* some {bar;} comment */ }',
+                               "foo { background: url($red) /* some {foo;} comment */; background: url(http://localhost/w/red.gif?timestamp) /* some {foo;} comment */!ie; /* some {bar;} comment */ }",
+                       ),
+                       array(
+                               'Embedded file with comment outside the rule',
+                               'foo { /* @embed */ background: url(red.gif); /* some {funny;} comment */ }',
+                               "foo { background: url($red); background: url(http://localhost/w/red.gif?timestamp)!ie; /* some {funny;} comment */ }",
+                       ),
+                       array(
+                               'Rule with two urls, each with comments',
+                               '{ background: /*asd*/ url(something.png); background: /*jkl*/ url(something.png); }',
+                               '{ background: /*asd*/ url(http://localhost/w/something.png); background: /*jkl*/ url(http://localhost/w/something.png); }',
+                       ),
+                       array(
+                               'Sanity check for offending line from jquery.ui.theme.css (bug 60077)',
+                               '.ui-state-default, .ui-widget-content .ui-state-default, .ui-widget-header .ui-state-default { border: 1px solid #d3d3d3/*{borderColorDefault}*/; background: #e6e6e6/*{bgColorDefault}*/ url(images/ui-bg_glass_75_e6e6e6_1x400.png)/*{bgImgUrlDefault}*/ 50%/*{bgDefaultXPos}*/ 50%/*{bgDefaultYPos}*/ repeat-x/*{bgDefaultRepeat}*/; font-weight: normal/*{fwDefault}*/; color: #555555/*{fcDefault}*/; }',
+                               '.ui-state-default, .ui-widget-content .ui-state-default, .ui-widget-header .ui-state-default { border: 1px solid #d3d3d3/*{borderColorDefault}*/; background: #e6e6e6/*{bgColorDefault}*/ url(http://localhost/w/images/ui-bg_glass_75_e6e6e6_1x400.png)/*{bgImgUrlDefault}*/ 50%/*{bgDefaultXPos}*/ 50%/*{bgDefaultYPos}*/ repeat-x/*{bgDefaultRepeat}*/; font-weight: normal/*{fwDefault}*/; color: #555555/*{fcDefault}*/; }',
+                       ),
                );
        }
 
index b99ef86..334d5b5 100644 (file)
@@ -14,7 +14,7 @@ class MWMessagePackTest extends MediaWikiTestCase {
         * serialization function.
         */
        public function provider() {
-               return array(
+               $tests = array(
                        array( 'nil', null, 'c0' ),
                        array( 'bool', true, 'c3' ),
                        array( 'bool', false, 'c2' ),
@@ -25,16 +25,12 @@ class MWMessagePackTest extends MediaWikiTestCase {
                        array( 'uint 8', 128, 'cc80' ),
                        array( 'uint 16', 1000, 'cd03e8' ),
                        array( 'uint 32', 100000, 'ce000186a0' ),
-                       array( 'uint 64', 10000000000, 'cf00000002540be400' ),
                        array( 'negative fixnum', -1, 'ff' ),
                        array( 'negative fixnum', -2, 'fe' ),
                        array( 'int 8', -128, 'd080' ),
                        array( 'int 8', -35, 'd0dd' ),
                        array( 'int 16', -1000, 'd1fc18' ),
                        array( 'int 32', -100000, 'd2fffe7960' ),
-                       array( 'int 64', -10000000000, 'd3fffffffdabf41c00' ),
-                       array( 'int 64', -223372036854775807, 'd3fce66c50e2840001' ),
-                       array( 'int 64', -9223372036854775807, 'd38000000000000001' ),
                        array( 'double', 0.1, 'cb3fb999999999999a' ),
                        array( 'double', 1.1, 'cb3ff199999999999a' ),
                        array( 'double', 123.456, 'cb405edd2f1a9fbe77' ),
@@ -56,6 +52,15 @@ class MWMessagePackTest extends MediaWikiTestCase {
                                '82a36f6e6501a374776f02'
                        ),
                );
+
+               if ( PHP_INT_SIZE > 4 ) {
+                       $tests[] = array( 'uint 64', 10000000000, 'cf00000002540be400' );
+                       $tests[] = array( 'int 64', -10000000000, 'd3fffffffdabf41c00' );
+                       $tests[] = array( 'int 64', -223372036854775807, 'd3fce66c50e2840001' );
+                       $tests[] = array( 'int 64', -9223372036854775807, 'd38000000000000001' );
+               }
+
+               return $tests;
        }
 
        /**
@@ -65,6 +70,6 @@ class MWMessagePackTest extends MediaWikiTestCase {
         */
        public function testPack( $type, $value, $expected ) {
                $actual = bin2hex( MWMessagePack::pack( $value ) );
-               $this->assertEquals( $actual, $expected, $type );
+               $this->assertEquals( $expected, $actual, $type );
        }
 }
index 96347d9..7b64dfd 100644 (file)
@@ -29,11 +29,18 @@ abstract class MediaWikiMediaTestCase extends MediaWikiTestCase {
                        'wikiId' => wfWikiId(),
                        'containerPaths' => $containers
                ) );
-               $this->repo = new FSRepo( array(
+               $this->repo = new FSRepo( $this->getRepoOptions() );
+       }
+
+       /**
+        * @return Array Argument for FSRepo constructor
+        */
+       protected function getRepoOptions() {
+               return array(
                        'name' => 'temp',
                        'url' => 'http://localhost/thumbtest',
                        'backend' => $this->backend
-               ) );
+               );
        }
 
        /**
diff --git a/tests/phpunit/includes/media/XCFTest.php b/tests/phpunit/includes/media/XCFTest.php
new file mode 100644 (file)
index 0000000..ae4fa8b
--- /dev/null
@@ -0,0 +1,74 @@
+<?php
+class XCFHandlerTest extends MediaWikiMediaTestCase {
+
+       /** @var XCFHandler */
+       protected $handler;
+
+       protected function setUp() {
+               parent::setUp();
+               $this->handler = new XCFHandler();
+       }
+
+
+       /**
+        * @param string $filename
+        * @param int $expectedWidth width
+        * @param int $expectedHeigh height
+        * @dataProvider provideGetImageSize
+        * @covers XCFHandler::getImageSize
+        */
+       public function testGetImageSize( $filename, $expectedWidth, $expectedHeight ) {
+               $file = $this->dataFile( $filename, 'image/x-xcf' );
+               $actual = $this->handler->getImageSize( $file, $file->getLocalRefPath() );
+               $this->assertEquals( $expectedWidth, $actual[0] );
+               $this->assertEquals( $expectedHeight, $actual[1] );
+       }
+
+       public static function provideGetImageSize() {
+               return array(
+                       array( '80x60-2layers.xcf', 80, 60 ),
+                       array( '80x60-RGB.xcf', 80, 60 ),
+                       array( '80x60-Greyscale.xcf', 80, 60 ),
+               );
+       }
+
+       /**
+        * @param string $metadata Serialized metadata
+        * @param int $expected One of the class constants of XCFHandler
+        * @dataProvider provideIsMetadataValid
+        * @covers XCFHandler::isMetadataValid
+        */
+       public function testIsMetadataValid( $metadata, $expected ) {
+               $actual = $this->handler->isMetadataValid( null, $metadata );
+               $this->assertEquals( $expected, $actual );
+       }
+
+       public static function provideIsMetadataValid() {
+               return array(
+                       array( '', XCFHandler::METADATA_BAD ),
+                       array( serialize( array( 'error' => true ) ), XCFHandler::METADATA_GOOD ),
+                       array( false, XCFHandler::METADATA_BAD ),
+                       array( serialize( array( 'colorType' => 'greyscale-alpha' ) ), XCFHandler::METADATA_GOOD ),
+               );
+       }
+
+       /**
+        * @param string $filename
+        * @param string $expected Serialized array
+        * @dataProvider provideGetMetadata
+        * @covers XCFHandler::getMetadata
+        */
+       public function testGetMetadata( $filename, $expected ) {
+               $file = $this->dataFile( $filename, 'image/png' );
+               $actual = $this->handler->getMetadata( $file, "$this->filePath/$filename" );
+               $this->assertEquals( $expected, $actual );
+       }
+
+       public static function provideGetMetadata() {
+               return array(
+                       array( '80x60-2layers.xcf', 'a:1:{s:9:"colorType";s:16:"truecolour-alpha";}' ),
+                       array( '80x60-RGB.xcf', 'a:1:{s:9:"colorType";s:16:"truecolour-alpha";}' ),
+                       array( '80x60-Greyscale.xcf', 'a:1:{s:9:"colorType";s:15:"greyscale-alpha";}' ),
+               );
+       }
+}
index dff31c1..97b76fe 100644 (file)
@@ -110,15 +110,20 @@ class CleanUpTest extends MediaWikiTestCase {
        }
 
        /** @todo document */
-       public function testAllBytes() {
-               $this->doTestBytes( '', '' );
-               $this->doTestBytes( 'x', '' );
-               $this->doTestBytes( '', 'x' );
-               $this->doTestBytes( 'x', 'x' );
+       public function provideAllBytes() {
+               return array(
+                       array( '', '' ),
+                       array( 'x', '' ),
+                       array( '', 'x' ),
+                       array( 'x', 'x' ),
+               );
        }
 
-       /** @todo document */
-       function doTestBytes( $head, $tail ) {
+       /**
+        * @dataProvider provideAllBytes
+        * @todo document
+        */
+       function testBytes( $head, $tail ) {
                for ( $i = 0x0; $i < 256; $i++ ) {
                        $char = $head . chr( $i ) . $tail;
                        $clean = UtfNormal::cleanUp( $char );
@@ -149,18 +154,11 @@ class CleanUpTest extends MediaWikiTestCase {
                }
        }
 
-       /** @todo document */
-       public function testDoubleBytes() {
-               $this->doTestDoubleBytes( '', '' );
-               $this->doTestDoubleBytes( 'x', '' );
-               $this->doTestDoubleBytes( '', 'x' );
-               $this->doTestDoubleBytes( 'x', 'x' );
-       }
-
        /**
+        * @dataProvider provideAllBytes
         * @todo document
         */
-       function doTestDoubleBytes( $head, $tail ) {
+       function testDoubleBytes( $head, $tail ) {
                for ( $first = 0xc0; $first < 0x100; $first += 2 ) {
                        for ( $second = 0x80; $second < 0x100; $second += 2 ) {
                                $char = $head . chr( $first ) . chr( $second ) . $tail;
@@ -202,16 +200,11 @@ class CleanUpTest extends MediaWikiTestCase {
                }
        }
 
-       /** @todo document */
-       public function testTripleBytes() {
-               $this->doTestTripleBytes( '', '' );
-               $this->doTestTripleBytes( 'x', '' );
-               $this->doTestTripleBytes( '', 'x' );
-               $this->doTestTripleBytes( 'x', 'x' );
-       }
-
-       /** @todo document */
-       function doTestTripleBytes( $head, $tail ) {
+       /**
+        * @dataProvider provideAllBytes
+        * @todo document
+        */
+       function testTripleBytes( $head, $tail ) {
                for ( $first = 0xc0; $first < 0x100; $first += 2 ) {
                        for ( $second = 0x80; $second < 0x100; $second += 2 ) {
                                #for( $third = 0x80; $third < 0x100; $third++ ) {
index 15b8865..c3fd155 100644 (file)
 class MediaWikiSiteTest extends SiteTest {
 
        public function testNormalizePageTitle() {
+               $this->setMwGlobals( array(
+                       'wgCapitalLinks' => true,
+               ) );
+
                $site = new MediaWikiSite();
                $site->setGlobalId( 'enwiki' );
 
index 73d7ff9..358b0fe 100644 (file)
  */
 class MediaWikiPageLinkRendererTest extends MediaWikiTestCase {
 
+       protected function setUp() {
+               parent::setUp();
+
+               $this->setMwGlobals( array(
+                       'wgContLang' => Language::factory( 'en' ),
+               ) );
+       }
+
        /**
         * Returns a mock GenderCache that will return "female" always.
         *
index 1e5aca9..2cf8663 100644 (file)
@@ -40,6 +40,7 @@ class MediaWikiTitleCodecTest extends MediaWikiTestCase {
                        'wgAllowUserJs' => false,
                        'wgDefaultLanguageVariant' => false,
                        'wgLocalInterwikis' => array( 'localtestiw' ),
+                       'wgCapitalLinks' => true,
 
                        // NOTE: this is why global state is evil.
                        // TODO: refactor access to the interwiki codes so it can be injected.
index 792cf72..f64fc72 100644 (file)
@@ -95,6 +95,16 @@ class LanguageRuTest extends LanguageClassesTestCase {
                                'Викитека',
                                'prepositional',
                        ),
+                       array(
+                               'Викисклада',
+                               'Викисклад',
+                               'genitive',
+                       ),
+                       array(
+                               'Викискладе',
+                               'Викисклад',
+                               'prepositional',
+                       ),
                        array(
                                'Викиданных',
                                'Викиданные',
index b2b5322..34007ed 100644 (file)
@@ -8,14 +8,14 @@ return array(
 
        'test.sinonjs' => array(
                'scripts' => array(
-                       'resources/lib/sinonjs/sinon-1.9.0.js',
+                       'resources/lib/sinonjs/sinon-1.10.3.js',
                        // We want tests to work in IE, but can't include this as it
                        // will break the placeholders in Sinon because the hack it uses
                        // to hijack IE globals relies on running in the global scope
                        // and in ResourceLoader this won't be running in the global scope.
                        // Including it results (among other things) in sandboxed timers
                        // being broken due to Date inheritance being undefined.
-                       // 'resources/lib/sinonjs/sinon-ie-1.9.0.js',
+                       // 'resources/lib/sinonjs/sinon-ie-1.10.3.js',
                ),
                'targets' => array( 'desktop', 'mobile' ),
        ),
index ab9aab1..50e89da 100644 (file)
                                return true;
                        }
 
+                       // Don't iterate over the module registry (the 'script' references would
+                       // be listed as untested methods otherwise)
+                       if ( val === mw.loader.moduleRegistry ) {
+                               return true;
+                       }
+
                        return false;
                };
 
index df800bc..c6dd91c 100644 (file)
@@ -4,7 +4,6 @@
 
        var uacount = 0,
                // Object keyed by userAgent. Value is an array (human-readable name, client-profile object, navigator.platform value)
-               // Info based on results from http://toolserver.org/~krinkle/testswarm/job/174/
                uas = {
                        // Internet Explorer 6
                        // Internet Explorer 7
index 9ca434f..3bfabe4 100644 (file)
                                expected: 'доводах',
                                description: 'Grammar test for prepositional case, доводы -> доводах'
                        },
+                       {
+                               word: 'Викисклад',
+                               grammarForm: 'prepositional',
+                               expected: 'Викискладе',
+                               description: 'Grammar test for prepositional case, Викисклад -> Викискладе'
+                       },
+                       {
+                               word: 'Викисклад',
+                               grammarForm: 'genitive',
+                               expected: 'Викисклада',
+                               description: 'Grammar test for genitive case, Викисклад -> Викисклада'
+                       },
                        {
                                word: 'песчаник',
                                grammarForm: 'prepositional',
index d2e7f6e..8c24f39 100644 (file)
@@ -318,7 +318,7 @@ class DbTestRecorder extends DbTestPreviewer {
                        array(
                                'tr_date' => $this->db->timestamp(),
                                'tr_mw_version' => $this->version,
-                               'tr_php_version' => phpversion(),
+                               'tr_php_version' => PHP_VERSION,
                                'tr_db_version' => $this->db->getServerVersion(),
                                'tr_uname' => php_uname()
                        ),
index c611dc3..89cc834 100644 (file)
--- a/thumb.php
+++ b/thumb.php
@@ -118,7 +118,7 @@ function wfStreamThumb( array $params ) {
        }
        if ( isset( $params['width'] ) && substr( $params['width'], -2 ) == 'px' ) {
                // strip the px (pixel) suffix, if found
-               $params['width'] = substr( $width, 0, strlen( $width ) - 2 );
+               $params['width'] = substr( $params['width'], 0, -2 );
        }
        if ( isset( $params['p'] ) ) {
                $params['page'] = $params['p'];
@@ -367,7 +367,7 @@ function wfGenerateThumbnail( File $file, array $params, $thumbName, $thumbPath
        global $wgMemc, $wgAttemptFailureEpoch;
 
        $key = wfMemcKey( 'attempt-failures', $wgAttemptFailureEpoch,
-               $file->getRepo()->getName(), md5( $file->getName() ), md5( $thumbName ) );
+               $file->getRepo()->getName(), $file->getSha1(), md5( $thumbName ) );
 
        // Check if this file keeps failing to render
        if ( $wgMemc->get( $key ) >= 4 ) {