Merge "Made QueryPage use startAtomic() for trx handling"
authorjenkins-bot <jenkins-bot@gerrit.wikimedia.org>
Thu, 18 Sep 2014 23:16:49 +0000 (23:16 +0000)
committerGerrit Code Review <gerrit@wikimedia.org>
Thu, 18 Sep 2014 23:16:49 +0000 (23:16 +0000)
201 files changed:
RELEASE-NOTES-1.24
assets/file-type-icons/COPYING [deleted file]
assets/file-type-icons/fileicon-c.png [deleted file]
assets/file-type-icons/fileicon-cpp.png [deleted file]
assets/file-type-icons/fileicon-deb.png [deleted file]
assets/file-type-icons/fileicon-djvu.png [deleted file]
assets/file-type-icons/fileicon-djvu.xcf [deleted file]
assets/file-type-icons/fileicon-dvi.png [deleted file]
assets/file-type-icons/fileicon-exe.png [deleted file]
assets/file-type-icons/fileicon-h.png [deleted file]
assets/file-type-icons/fileicon-html.png [deleted file]
assets/file-type-icons/fileicon-iso.png [deleted file]
assets/file-type-icons/fileicon-java.png [deleted file]
assets/file-type-icons/fileicon-mid.png [deleted file]
assets/file-type-icons/fileicon-mov.png [deleted file]
assets/file-type-icons/fileicon-o.png [deleted file]
assets/file-type-icons/fileicon-ogg.png [deleted file]
assets/file-type-icons/fileicon-ogg.xcf [deleted file]
assets/file-type-icons/fileicon-pdf.png [deleted file]
assets/file-type-icons/fileicon-ps.png [deleted file]
assets/file-type-icons/fileicon-psd.png [deleted file]
assets/file-type-icons/fileicon-rm.png [deleted file]
assets/file-type-icons/fileicon-rpm.png [deleted file]
assets/file-type-icons/fileicon-svg.png [deleted file]
assets/file-type-icons/fileicon-tar.png [deleted file]
assets/file-type-icons/fileicon-tex.png [deleted file]
assets/file-type-icons/fileicon-ttf.png [deleted file]
assets/file-type-icons/fileicon-txt.png [deleted file]
assets/file-type-icons/fileicon-xcf.png [deleted file]
assets/file-type-icons/fileicon.png [deleted file]
assets/licenses/cc-0.png [deleted file]
assets/licenses/cc-by-nc-sa.png [deleted file]
assets/licenses/cc-by-sa.png [deleted file]
assets/licenses/cc-by.png [deleted file]
assets/licenses/gnu-fdl.png [deleted file]
assets/licenses/public-domain.png [deleted file]
assets/mediawiki.png [deleted file]
assets/poweredby_mediawiki_88x31.png [deleted file]
docs/hooks.txt
docs/kss/styleguide-template/public/kss.less
includes/AutoLoader.php
includes/DefaultSettings.php
includes/GlobalFunctions.php
includes/Linker.php
includes/PHPVersionError.php
includes/Preferences.php
includes/PrefixSearch.php
includes/ProtectionForm.php
includes/Setup.php
includes/Title.php
includes/api/ApiMain.php
includes/api/ApiQuery.php
includes/api/ApiQueryBacklinksprop.php [new file with mode: 0644]
includes/api/ApiQueryImageInfo.php
includes/api/ApiQueryRedirects.php [deleted file]
includes/api/ApiQuerySiteinfo.php
includes/cache/bloom/BloomCacheRedis.php
includes/config/Config.php
includes/config/GlobalVarConfig.php
includes/config/HashConfig.php [new file with mode: 0644]
includes/config/MultiConfig.php [new file with mode: 0644]
includes/content/AbstractContent.php
includes/content/WikitextContent.php
includes/filerepo/file/File.php
includes/htmlform/HTMLForm.php
includes/installer/CliInstaller.php
includes/installer/Installer.php
includes/installer/WebInstallerPage.php
includes/installer/i18n/be.json
includes/installer/i18n/fi.json
includes/mail/EmailNotification.php
includes/media/TransformationalImageHandler.php
includes/parser/ParserOptions.php
includes/profiler/ProfilerSimpleDB.php
includes/resourceloader/ResourceLoaderFileModule.php
includes/site/SiteSQLStore.php
includes/skins/Skin.php
includes/specialpage/SpecialPageFactory.php
includes/specials/SpecialChangeEmail.php
includes/specials/SpecialPreferences.php
includes/specials/SpecialRecentchanges.php
includes/templates/NoLocalSettings.php
languages/i18n/be-tarask.json
languages/i18n/be.json
languages/i18n/ce.json
languages/i18n/ckb.json
languages/i18n/cs.json
languages/i18n/de.json
languages/i18n/egl.json
languages/i18n/en.json
languages/i18n/et.json
languages/i18n/he.json
languages/i18n/hr.json
languages/i18n/it.json
languages/i18n/ja.json
languages/i18n/lrc.json
languages/i18n/lv.json
languages/i18n/mk.json
languages/i18n/ml.json
languages/i18n/pl.json
languages/i18n/pms.json
languages/i18n/qqq.json
languages/i18n/ru.json
languages/i18n/sc.json
languages/i18n/sl.json
languages/i18n/sr-ec.json
languages/i18n/sr-el.json
languages/i18n/su.json
languages/i18n/vi.json
languages/i18n/zh-hans.json
languages/i18n/zh-hant.json
resources/Resources.php
resources/assets/file-type-icons/COPYING [new file with mode: 0644]
resources/assets/file-type-icons/fileicon-c.png [new file with mode: 0644]
resources/assets/file-type-icons/fileicon-cpp.png [new file with mode: 0644]
resources/assets/file-type-icons/fileicon-deb.png [new file with mode: 0644]
resources/assets/file-type-icons/fileicon-djvu.png [new file with mode: 0644]
resources/assets/file-type-icons/fileicon-djvu.xcf [new file with mode: 0644]
resources/assets/file-type-icons/fileicon-dvi.png [new file with mode: 0644]
resources/assets/file-type-icons/fileicon-exe.png [new file with mode: 0644]
resources/assets/file-type-icons/fileicon-h.png [new file with mode: 0644]
resources/assets/file-type-icons/fileicon-html.png [new file with mode: 0644]
resources/assets/file-type-icons/fileicon-iso.png [new file with mode: 0644]
resources/assets/file-type-icons/fileicon-java.png [new file with mode: 0644]
resources/assets/file-type-icons/fileicon-mid.png [new file with mode: 0644]
resources/assets/file-type-icons/fileicon-mov.png [new file with mode: 0644]
resources/assets/file-type-icons/fileicon-o.png [new file with mode: 0644]
resources/assets/file-type-icons/fileicon-ogg.png [new file with mode: 0644]
resources/assets/file-type-icons/fileicon-ogg.xcf [new file with mode: 0644]
resources/assets/file-type-icons/fileicon-pdf.png [new file with mode: 0644]
resources/assets/file-type-icons/fileicon-ps.png [new file with mode: 0644]
resources/assets/file-type-icons/fileicon-psd.png [new file with mode: 0644]
resources/assets/file-type-icons/fileicon-rm.png [new file with mode: 0644]
resources/assets/file-type-icons/fileicon-rpm.png [new file with mode: 0644]
resources/assets/file-type-icons/fileicon-svg.png [new file with mode: 0644]
resources/assets/file-type-icons/fileicon-tar.png [new file with mode: 0644]
resources/assets/file-type-icons/fileicon-tex.png [new file with mode: 0644]
resources/assets/file-type-icons/fileicon-ttf.png [new file with mode: 0644]
resources/assets/file-type-icons/fileicon-txt.png [new file with mode: 0644]
resources/assets/file-type-icons/fileicon-xcf.png [new file with mode: 0644]
resources/assets/file-type-icons/fileicon.png [new file with mode: 0644]
resources/assets/licenses/cc-0.png [new file with mode: 0644]
resources/assets/licenses/cc-by-nc-sa.png [new file with mode: 0644]
resources/assets/licenses/cc-by-sa.png [new file with mode: 0644]
resources/assets/licenses/cc-by.png [new file with mode: 0644]
resources/assets/licenses/gnu-fdl.png [new file with mode: 0644]
resources/assets/licenses/public-domain.png [new file with mode: 0644]
resources/assets/mediawiki.png [new file with mode: 0644]
resources/assets/poweredby_mediawiki_88x31.png [new file with mode: 0644]
resources/lib/oojs-ui/i18n/hy.json
resources/lib/oojs-ui/oojs-ui-apex.css
resources/lib/oojs-ui/oojs-ui-minerva.css
resources/lib/oojs-ui/oojs-ui.js
resources/lib/oojs-ui/oojs-ui.svg.css
resources/src/mediawiki.action/mediawiki.action.view.redirectPage.css
resources/src/mediawiki.legacy/wikibits.js
resources/src/mediawiki.less/mediawiki.ui/variables.less
resources/src/mediawiki.page/mediawiki.page.ready.js
resources/src/mediawiki.skinning/content.parsoid.less
resources/src/mediawiki.ui/components/buttons.less
resources/src/mediawiki.ui/components/checkbox.less
resources/src/mediawiki.ui/components/inputs.less
resources/src/mediawiki/mediawiki.util.js
tests/phpunit/includes/EditPageTest.php
tests/phpunit/includes/LinkerTest.php
tests/phpunit/includes/MWTimestampTest.php
tests/phpunit/includes/MessageTest.php
tests/phpunit/includes/SampleTest.php
tests/phpunit/includes/TitleArrayFromResultTest.php
tests/phpunit/includes/TitleTest.php
tests/phpunit/includes/UserArrayFromResultTest.php
tests/phpunit/includes/UserTest.php
tests/phpunit/includes/XmlJsTest.php
tests/phpunit/includes/actions/ActionTest.php
tests/phpunit/includes/changes/OldChangesListTest.php
tests/phpunit/includes/changes/TestRecentChangesHelper.php
tests/phpunit/includes/config/GlobalVarConfigTest.php
tests/phpunit/includes/config/HashConfigTest.php [new file with mode: 0644]
tests/phpunit/includes/config/MultiConfigTest.php [new file with mode: 0644]
tests/phpunit/includes/content/JsonContentTest.php
tests/phpunit/includes/content/WikitextContentTest.php
tests/phpunit/includes/exception/MWExceptionTest.php
tests/phpunit/includes/libs/IPSetTest.php
tests/phpunit/includes/libs/MWMessagePackTest.php
tests/phpunit/includes/media/GIFTest.php
tests/phpunit/includes/media/PNGTest.php
tests/phpunit/includes/media/SVGTest.php
tests/phpunit/includes/normal/CleanUpTest.php
tests/phpunit/includes/parser/TidyTest.php
tests/phpunit/includes/password/BcryptPasswordTest.php
tests/phpunit/includes/password/LayeredParameterizedPasswordTest.php
tests/phpunit/includes/password/PasswordTestCase.php
tests/phpunit/includes/password/Pbkdf2PasswordTest.php
tests/phpunit/includes/resourceloader/ResourceLoaderWikiModuleTest.php
tests/phpunit/includes/specialpage/SpecialPageFactoryTest.php [new file with mode: 0644]
tests/phpunit/includes/specials/ImageListPagerTest.php
tests/phpunit/includes/specials/SpecialMIMESearchTest.php
tests/phpunit/includes/specials/SpecialMyLanguageTest.php
tests/phpunit/includes/title/MediaWikiPageLinkRendererTest.php
tests/phpunit/includes/title/MediaWikiTitleCodecTest.php
tests/phpunit/includes/upload/UploadStashTest.php

index 0cd1131..ce083e0 100644 (file)
@@ -47,6 +47,8 @@ production.
 * $wgCompiledFiles has been removed.
 * $wgSortSpecialPages was removed, the listing on Special:SpecialPages is
   now always sorted.
+* $wgSpecialPages may now use callback functions as an alternative to plain class names.
+  This allows more control over constructor parameters.
 * $wgHTCPMulticastAddress, $wgHTCPMulticastRouting and $wgHTCPPort were removed.
 * $wgRC2UDPAddress, $wgRC2UDPInterwikiPrefix, $wgRC2UDPOmitBots, $wgRC2UDPPort
   and $wgRC2UDPPrefix have been removed.
@@ -183,6 +185,12 @@ production.
 * Added HTMLAutoCompleteSelectField.
 * Added a new hook, "SkinPreloadExistence", to allow extensions to add titles to
   link existence cache before the page is rendered.
+* Config::set() was moved to its own interface, MutableConfig. GlobalVarConfig::set()
+  is now deprecated, does not implement MutableConfig.
+* A MutableConfig named HashConfig was added, that stores an array of configuration
+  settings.
+* (bug 69418) A MultiConfig implementation was added that supports fallback
+  to multiple Config instances.
 
 === Bug fixes in 1.24 ===
 * (bug 50572) MediaWiki:Blockip should support gender
@@ -260,6 +268,11 @@ production.
   deprecated in favor of cmstarthexsortkey and cmendhexsortkey.
 * (bug 63326) Add blockedtimestamp field to output of blockinfo property for
   the list=allusers and list=users modules.
+* prop=imageinfo no longer requires iiurlwidth to be set when using iiurlparam.
+* Added prop=linkshere, prop=fileusage, and prop=transcludedin, which are
+  roughly equivalent to list=backlinks, list=imageusage, and list=embeddedin
+  but can work on a list of titles (including titles from a generator).
+* prop=redirects can now filter returned redirects by namespace.
 
 === Action API internal changes in 1.24 ===
 * Methods for handling continuation are added to ApiResult, so actions other
@@ -289,6 +302,8 @@ production.
     ApiTokensGetTokenTypes are deprecated, but are still called to support
     backwards-compatible token access.
 * ApiBase::validateLimit and ApiBase::validateTimestamp are now protected.
+* ApiQueryRedirects was removed; prop=redirects is now implemented by
+  ApiQueryBacklinksProp along with the newly-added prop modules.
 * The following methods have been deprecated and may be removed in a future
   release:
   * ApiBase::getResultProperties
@@ -440,6 +455,8 @@ changes to languages because of Bugzilla reports.
   meaning that JavaScript is no longer executed in these browser versions.
 * Browser support for Opera 11 lowered from Grade A to Grade C.
 * Removed IEFixes module which existed purely to provide support for MSIE versions
+* Deprecated SpecialPageFactory::getList() in favor of
+  SpecialPageFactory::getNames()
   below 7 (conditionally loaded only for those browsers).
 * Action::checkCanExecute() no longer has a return value.
 * Removed cleanupForIRC(), loadFromCurRow(), newFromCurRow(), notifyRC2UDP()
@@ -466,6 +483,9 @@ changes to languages because of Bugzilla reports.
   and "jquery" modules. In the past, this behavior was undefined, now it will
   throw an error.
 * Removed BagOStuff::replace(). (deprecated since 1.23)
+* In Linker.php, link(), linkText() and makeBrokenImageLinkObj() now display
+  warnings if their first parameter is not a Title object. Also makeImageLink()
+  now requires a Parser as its first parameter.
 
 ==== Renamed classes ====
 * CLDRPluralRuleConverter_Expression to CLDRPluralRuleConverterExpression
@@ -517,7 +537,8 @@ changes to languages because of Bugzilla reports.
 
 == Compatibility ==
 
-MediaWiki 1.24 requires PHP 5.3.2 or later.
+MediaWiki 1.24 requires PHP 5.3.2 or later. There is experimental support for
+HHVM 3.3.0.
 
 MySQL is the recommended DBMS. PostgreSQL or SQLite can also be used, but
 support for them is somewhat less mature. There is experimental support for
diff --git a/assets/file-type-icons/COPYING b/assets/file-type-icons/COPYING
deleted file mode 100644 (file)
index 136530a..0000000
+++ /dev/null
@@ -1,43 +0,0 @@
-The icons used here are derived from the crystalsvg icons in the the
-pics/crystalsvg/ directory of kdelibs-3.4.0 they were modified on 2005-05-15
-by Ævar Arnfjörð Bjarmason for use in MediaWiki.
-
-What follows is the contents of the LICENSE.crystalsvg file found in the pics/
-subdirectory of kdelibs-3.4.0:
-
-++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
-This copyright and license notice covers all CrystalSVG images.
-Note the license notice contains an add-on.
-********************************************************************************
-KDE Crystal theme icons.
-Copyright (C) 2002 and following years KDE Artists
-This library is free software; you can redistribute it and/or
-modify it under the terms of the GNU Lesser General Public
-License as published by the Free Software Foundation,
-version 2.1 of the License.
-This library is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-Lesser General Public License for more details.
-You should have received a copy of the GNU Lesser General Public
-License along with this library; if not, write to the Free Software
-Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
-    **** NOTE THIS ADD-ON ****
-The GNU Lesser General Public License or LGPL is written for software libraries
-in the first place. We expressly want the LGPL to be valid for this artwork
-library too.
-KDE Crystal theme icons is a special kind of software library, it is an
-artwork library, it's elements can be used in a Graphical User Interface, or
-GUI.
-Source code, for this library means:
- - for vectors svg;
- - for pixels, if applicable, the multi-layered formats xcf or psd, or
-otherwise png.
-The LGPL in some sections obliges you to make the files carry
-notices. With images this is in some cases impossible or hardly useful.
-With this library a notice is placed at a prominent place in the directory
-containing the elements. You may follow this practice.
-The exception in section 6 of the GNU Lesser General Public License covers
-the use of elements of this art library in a GUI.
-kde-artists [at] kde.org
-++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
diff --git a/assets/file-type-icons/fileicon-c.png b/assets/file-type-icons/fileicon-c.png
deleted file mode 100644 (file)
index 0d603b7..0000000
Binary files a/assets/file-type-icons/fileicon-c.png and /dev/null differ
diff --git a/assets/file-type-icons/fileicon-cpp.png b/assets/file-type-icons/fileicon-cpp.png
deleted file mode 100644 (file)
index 123688f..0000000
Binary files a/assets/file-type-icons/fileicon-cpp.png and /dev/null differ
diff --git a/assets/file-type-icons/fileicon-deb.png b/assets/file-type-icons/fileicon-deb.png
deleted file mode 100644 (file)
index 87ca3fa..0000000
Binary files a/assets/file-type-icons/fileicon-deb.png and /dev/null differ
diff --git a/assets/file-type-icons/fileicon-djvu.png b/assets/file-type-icons/fileicon-djvu.png
deleted file mode 100644 (file)
index 1da2276..0000000
Binary files a/assets/file-type-icons/fileicon-djvu.png and /dev/null differ
diff --git a/assets/file-type-icons/fileicon-djvu.xcf b/assets/file-type-icons/fileicon-djvu.xcf
deleted file mode 100644 (file)
index 8043dcd..0000000
Binary files a/assets/file-type-icons/fileicon-djvu.xcf and /dev/null differ
diff --git a/assets/file-type-icons/fileicon-dvi.png b/assets/file-type-icons/fileicon-dvi.png
deleted file mode 100644 (file)
index f37878d..0000000
Binary files a/assets/file-type-icons/fileicon-dvi.png and /dev/null differ
diff --git a/assets/file-type-icons/fileicon-exe.png b/assets/file-type-icons/fileicon-exe.png
deleted file mode 100644 (file)
index dc020eb..0000000
Binary files a/assets/file-type-icons/fileicon-exe.png and /dev/null differ
diff --git a/assets/file-type-icons/fileicon-h.png b/assets/file-type-icons/fileicon-h.png
deleted file mode 100644 (file)
index 339bf02..0000000
Binary files a/assets/file-type-icons/fileicon-h.png and /dev/null differ
diff --git a/assets/file-type-icons/fileicon-html.png b/assets/file-type-icons/fileicon-html.png
deleted file mode 100644 (file)
index f28f8a2..0000000
Binary files a/assets/file-type-icons/fileicon-html.png and /dev/null differ
diff --git a/assets/file-type-icons/fileicon-iso.png b/assets/file-type-icons/fileicon-iso.png
deleted file mode 100644 (file)
index c73d229..0000000
Binary files a/assets/file-type-icons/fileicon-iso.png and /dev/null differ
diff --git a/assets/file-type-icons/fileicon-java.png b/assets/file-type-icons/fileicon-java.png
deleted file mode 100644 (file)
index a1b4f22..0000000
Binary files a/assets/file-type-icons/fileicon-java.png and /dev/null differ
diff --git a/assets/file-type-icons/fileicon-mid.png b/assets/file-type-icons/fileicon-mid.png
deleted file mode 100644 (file)
index ce2bebb..0000000
Binary files a/assets/file-type-icons/fileicon-mid.png and /dev/null differ
diff --git a/assets/file-type-icons/fileicon-mov.png b/assets/file-type-icons/fileicon-mov.png
deleted file mode 100644 (file)
index 952de1f..0000000
Binary files a/assets/file-type-icons/fileicon-mov.png and /dev/null differ
diff --git a/assets/file-type-icons/fileicon-o.png b/assets/file-type-icons/fileicon-o.png
deleted file mode 100644 (file)
index f3523d9..0000000
Binary files a/assets/file-type-icons/fileicon-o.png and /dev/null differ
diff --git a/assets/file-type-icons/fileicon-ogg.png b/assets/file-type-icons/fileicon-ogg.png
deleted file mode 100644 (file)
index ef4d801..0000000
Binary files a/assets/file-type-icons/fileicon-ogg.png and /dev/null differ
diff --git a/assets/file-type-icons/fileicon-ogg.xcf b/assets/file-type-icons/fileicon-ogg.xcf
deleted file mode 100644 (file)
index a91024b..0000000
Binary files a/assets/file-type-icons/fileicon-ogg.xcf and /dev/null differ
diff --git a/assets/file-type-icons/fileicon-pdf.png b/assets/file-type-icons/fileicon-pdf.png
deleted file mode 100644 (file)
index 8c8da92..0000000
Binary files a/assets/file-type-icons/fileicon-pdf.png and /dev/null differ
diff --git a/assets/file-type-icons/fileicon-ps.png b/assets/file-type-icons/fileicon-ps.png
deleted file mode 100644 (file)
index e872833..0000000
Binary files a/assets/file-type-icons/fileicon-ps.png and /dev/null differ
diff --git a/assets/file-type-icons/fileicon-psd.png b/assets/file-type-icons/fileicon-psd.png
deleted file mode 100644 (file)
index 598f190..0000000
Binary files a/assets/file-type-icons/fileicon-psd.png and /dev/null differ
diff --git a/assets/file-type-icons/fileicon-rm.png b/assets/file-type-icons/fileicon-rm.png
deleted file mode 100644 (file)
index 81dbe0b..0000000
Binary files a/assets/file-type-icons/fileicon-rm.png and /dev/null differ
diff --git a/assets/file-type-icons/fileicon-rpm.png b/assets/file-type-icons/fileicon-rpm.png
deleted file mode 100644 (file)
index 1903aac..0000000
Binary files a/assets/file-type-icons/fileicon-rpm.png and /dev/null differ
diff --git a/assets/file-type-icons/fileicon-svg.png b/assets/file-type-icons/fileicon-svg.png
deleted file mode 100644 (file)
index b782113..0000000
Binary files a/assets/file-type-icons/fileicon-svg.png and /dev/null differ
diff --git a/assets/file-type-icons/fileicon-tar.png b/assets/file-type-icons/fileicon-tar.png
deleted file mode 100644 (file)
index e5fd1b7..0000000
Binary files a/assets/file-type-icons/fileicon-tar.png and /dev/null differ
diff --git a/assets/file-type-icons/fileicon-tex.png b/assets/file-type-icons/fileicon-tex.png
deleted file mode 100644 (file)
index a437284..0000000
Binary files a/assets/file-type-icons/fileicon-tex.png and /dev/null differ
diff --git a/assets/file-type-icons/fileicon-ttf.png b/assets/file-type-icons/fileicon-ttf.png
deleted file mode 100644 (file)
index 1ed4e74..0000000
Binary files a/assets/file-type-icons/fileicon-ttf.png and /dev/null differ
diff --git a/assets/file-type-icons/fileicon-txt.png b/assets/file-type-icons/fileicon-txt.png
deleted file mode 100644 (file)
index 9e988e7..0000000
Binary files a/assets/file-type-icons/fileicon-txt.png and /dev/null differ
diff --git a/assets/file-type-icons/fileicon-xcf.png b/assets/file-type-icons/fileicon-xcf.png
deleted file mode 100644 (file)
index 1037b50..0000000
Binary files a/assets/file-type-icons/fileicon-xcf.png and /dev/null differ
diff --git a/assets/file-type-icons/fileicon.png b/assets/file-type-icons/fileicon.png
deleted file mode 100644 (file)
index 59696a3..0000000
Binary files a/assets/file-type-icons/fileicon.png and /dev/null differ
diff --git a/assets/licenses/cc-0.png b/assets/licenses/cc-0.png
deleted file mode 100644 (file)
index 9d3fe5f..0000000
Binary files a/assets/licenses/cc-0.png and /dev/null differ
diff --git a/assets/licenses/cc-by-nc-sa.png b/assets/licenses/cc-by-nc-sa.png
deleted file mode 100644 (file)
index 0d24a71..0000000
Binary files a/assets/licenses/cc-by-nc-sa.png and /dev/null differ
diff --git a/assets/licenses/cc-by-sa.png b/assets/licenses/cc-by-sa.png
deleted file mode 100644 (file)
index 518fb64..0000000
Binary files a/assets/licenses/cc-by-sa.png and /dev/null differ
diff --git a/assets/licenses/cc-by.png b/assets/licenses/cc-by.png
deleted file mode 100644 (file)
index 9cca2f9..0000000
Binary files a/assets/licenses/cc-by.png and /dev/null differ
diff --git a/assets/licenses/gnu-fdl.png b/assets/licenses/gnu-fdl.png
deleted file mode 100644 (file)
index 3feaf57..0000000
Binary files a/assets/licenses/gnu-fdl.png and /dev/null differ
diff --git a/assets/licenses/public-domain.png b/assets/licenses/public-domain.png
deleted file mode 100644 (file)
index ebf0107..0000000
Binary files a/assets/licenses/public-domain.png and /dev/null differ
diff --git a/assets/mediawiki.png b/assets/mediawiki.png
deleted file mode 100644 (file)
index 8c42118..0000000
Binary files a/assets/mediawiki.png and /dev/null differ
diff --git a/assets/poweredby_mediawiki_88x31.png b/assets/poweredby_mediawiki_88x31.png
deleted file mode 100644 (file)
index 30e1d2e..0000000
Binary files a/assets/poweredby_mediawiki_88x31.png and /dev/null differ
index d5fb2af..f4b8ef2 100644 (file)
@@ -2594,6 +2594,10 @@ database result.
 &$titleArray: set this to an object to override the default object returned
 $res: database result used to create the object
 
+'TitleExists': Called when determining whether a page exists at a given title.
+$title: The title being tested.
+&$exists: Whether the title exists.
+
 'TitleQuickPermissions': Called from Title::checkQuickPermissions to add to
 or override the quick permissions check.
 $title: The Title object being accessed
index c30322e..eeea1a8 100644 (file)
@@ -141,6 +141,10 @@ nav {
                        display: block;
                        margin: 0;
                        margin-left: 20px;
+
+                       div {
+                               margin-bottom: 5px;
+                       }
                }
        }
 }
index f8617c0..3a68ff1 100644 (file)
@@ -267,6 +267,7 @@ $wgAutoloadLocalClasses = array(
        'ApiQueryAllPages' => 'includes/api/ApiQueryAllPages.php',
        'ApiQueryAllUsers' => 'includes/api/ApiQueryAllUsers.php',
        'ApiQueryBacklinks' => 'includes/api/ApiQueryBacklinks.php',
+       'ApiQueryBacklinksprop' => 'includes/api/ApiQueryBacklinksprop.php',
        'ApiQueryBase' => 'includes/api/ApiQueryBase.php',
        'ApiQueryBlocks' => 'includes/api/ApiQueryBlocks.php',
        'ApiQueryCategories' => 'includes/api/ApiQueryCategories.php',
@@ -300,7 +301,6 @@ $wgAutoloadLocalClasses = array(
        'ApiQueryRandom' => 'includes/api/ApiQueryRandom.php',
        'ApiQueryRecentChanges' => 'includes/api/ApiQueryRecentChanges.php',
        'ApiQueryFileRepoInfo' => 'includes/api/ApiQueryFileRepoInfo.php',
-       'ApiQueryRedirects' => 'includes/api/ApiQueryRedirects.php',
        'ApiQueryRevisions' => 'includes/api/ApiQueryRevisions.php',
        'ApiQuerySearch' => 'includes/api/ApiQuerySearch.php',
        'ApiQuerySiteinfo' => 'includes/api/ApiQuerySiteinfo.php',
@@ -372,6 +372,8 @@ $wgAutoloadLocalClasses = array(
        'ConfigException' => 'includes/config/ConfigException.php',
        'ConfigFactory' => 'includes/config/ConfigFactory.php',
        'GlobalVarConfig' => 'includes/config/GlobalVarConfig.php',
+       'HashConfig' => 'includes/config/HashConfig.php',
+       'MultiConfig' => 'includes/config/MultiConfig.php',
        'MutableConfig' => 'includes/config/MutableConfig.php',
 
        # includes/content
index 8b29733..9f1b4c7 100644 (file)
@@ -3102,7 +3102,7 @@ $wgFooterIcons = array(
        ),
        "poweredby" => array(
                "mediawiki" => array(
-                       "src" => null, // Defaults to "$wgScriptPath/assets/poweredby_mediawiki_88x31.png"
+                       "src" => null, // Defaults to "$wgResourceBasePath/resources/assets/poweredby_mediawiki_88x31.png"
                        "url" => "//www.mediawiki.org/",
                        "alt" => "Powered by MediaWiki",
                )
@@ -6189,8 +6189,10 @@ $wgEnableParserLimitReporting = true;
 $wgValidSkinNames = array();
 
 /**
- * Special page list.
- * See the top of SpecialPage.php for documentation.
+ * Special page list. This is an associative array mapping the (canonical) names of
+ * special pages to either a class name to be instantiated, or a callback to use for
+ * creating the special page object. In both cases, the result must be an instance of
+ * SpecialPage.
  */
 $wgSpecialPages = array();
 
index 20398a5..490df24 100644 (file)
@@ -1407,7 +1407,7 @@ function wfGetLangObj( $langcode = false ) {
  *
  * This function replaces all old wfMsg* functions.
  *
- * @param string $key Message key
+ * @param string|string[] $key Message key, or array of keys
  * @param mixed $params,... Normal message parameters
  * @return Message
  *
index 012bc1b..be850d0 100644 (file)
@@ -192,11 +192,11 @@ class Linker {
        public static function link(
                $target, $html = null, $customAttribs = array(), $query = array(), $options = array()
        ) {
-               wfProfileIn( __METHOD__ );
                if ( !$target instanceof Title ) {
-                       wfProfileOut( __METHOD__ );
+                       wfWarn( __METHOD__ . ': Requires $target to be a Title object.' );
                        return "<!-- ERROR -->$html";
                }
+               wfProfileIn( __METHOD__ );
 
                if ( is_string( $query ) ) {
                        // some functions withing core using this still hand over query strings
@@ -380,11 +380,10 @@ class Linker {
         * @return string
         */
        private static function linkText( $target ) {
-               // We might be passed a non-Title by make*LinkObj().  Fail gracefully.
                if ( !$target instanceof Title ) {
+                       wfWarn( __METHOD__ . ': Requires $target to be a Title object.' );
                        return '';
                }
-
                // If the target is just a fragment, with no title, we return the fragment
                // text.  Otherwise, we return the title text itself.
                if ( $target->getPrefixedText() === '' && $target->hasFragment() ) {
@@ -544,7 +543,7 @@ class Linker {
         * @since 1.20
         * @return string HTML for an image, with links, wrappers, etc.
         */
-       public static function makeImageLink( /*Parser*/ $parser, Title $title,
+       public static function makeImageLink( Parser $parser, Title $title,
                $file, $frameParams = array(), $handlerParams = array(), $time = false,
                $query = "", $widthOption = null
        ) {
@@ -637,13 +636,7 @@ class Linker {
                        # If a thumbnail width has not been provided, it is set
                        # to the default user option as specified in Language*.php
                        if ( $fp['align'] == '' ) {
-                               if ( $parser instanceof Parser ) {
-                                       $fp['align'] = $parser->getTargetLanguage()->alignEnd();
-                               } else {
-                                       # backwards compatibility, remove with makeImageLink2()
-                                       global $wgContLang;
-                                       $fp['align'] = $wgContLang->alignEnd();
-                               }
+                               $fp['align'] = $parser->getTargetLanguage()->alignEnd();
                        }
                        return $prefix . self::makeThumbLink2( $title, $file, $fp, $hp, $time, $query ) . $postfix;
                }
@@ -932,10 +925,12 @@ class Linker {
        public static function makeBrokenImageLinkObj( $title, $label = '',
                $query = '', $unused1 = '', $unused2 = '', $time = false
        ) {
-               global $wgEnableUploads, $wgUploadMissingFileUrl, $wgUploadNavigationUrl;
                if ( !$title instanceof Title ) {
+                       wfWarn( __METHOD__ . ': Requires $title to be a Title object.' );
                        return "<!-- ERROR -->" . htmlspecialchars( $label );
                }
+
+               global $wgEnableUploads, $wgUploadMissingFileUrl, $wgUploadNavigationUrl;
                wfProfileIn( __METHOD__ );
                if ( $label == '' ) {
                        $label = $title->getPrefixedText();
index 44038a5..f481650 100644 (file)
@@ -60,7 +60,7 @@ function wfPHPVersionError( $type ) {
                }
                $encLogo = htmlspecialchars(
                        str_replace( '//', '/', $dirname . '/' ) .
-                       'assets/mediawiki.png'
+                       'resources/assets/mediawiki.png'
                );
 
                header( "$protocol 500 MediaWiki configuration Error" );
index e0d5ed7..cb978b1 100644 (file)
@@ -1539,6 +1539,9 @@ class PreferencesForm extends HTMLForm {
         * @return string
         */
        function getButtons() {
+               global $wgUseMediaWikiUIEverywhere;
+               $attrs = $wgUseMediaWikiUIEverywhere ? array( 'class' => 'mw-ui-button mw-ui-quiet' ) : array();
+
                if ( !$this->getModifiedUser()->isAllowedAny( 'editmyprivateinfo', 'editmyoptions' ) ) {
                        return '';
                }
@@ -1548,7 +1551,8 @@ class PreferencesForm extends HTMLForm {
                if ( $this->getModifiedUser()->isAllowed( 'editmyoptions' ) ) {
                        $t = SpecialPage::getTitleFor( 'Preferences', 'reset' );
 
-                       $html .= "\n" . Linker::link( $t, $this->msg( 'restoreprefs' )->escaped() );
+                       $html .= "\n" . Linker::link( $t, $this->msg( 'restoreprefs' )->escaped(),
+                               $attrs );
 
                        $html = Xml::tags( 'div', array( 'class' => 'mw-prefs-buttons' ), $html );
                }
index 295183c..718750f 100644 (file)
@@ -195,12 +195,12 @@ abstract class PrefixSearch {
                // Unlike SpecialPage itself, we want the canonical forms of both
                // canonical and alias title forms...
                $keys = array();
-               foreach ( SpecialPageFactory::getList() as $page => $class ) {
+               foreach ( SpecialPageFactory::getNames() as $page  ) {
                        $keys[$wgContLang->caseFold( $page )] = $page;
                }
 
                foreach ( $wgContLang->getSpecialPageAliases() as $page => $aliases ) {
-                       if ( !array_key_exists( $page, SpecialPageFactory::getList() ) ) {# bug 20885
+                       if ( !in_array( $page, SpecialPageFactory::getNames() ) ) {# bug 20885
                                continue;
                        }
 
index 35352d6..7bad8b5 100644 (file)
@@ -384,13 +384,18 @@ class ProtectionForm {
                        );
 
                        $expiryFormOptions = '';
-                       if ( $this->mExistingExpiry[$action] && $this->mExistingExpiry[$action] != 'infinity' ) {
-                               $timestamp = $lang->timeanddate( $this->mExistingExpiry[$action], true );
-                               $d = $lang->date( $this->mExistingExpiry[$action], true );
-                               $t = $lang->time( $this->mExistingExpiry[$action], true );
+                       if ( $this->mExistingExpiry[$action] ) {
+                               if ( $this->mExistingExpiry[$action] == 'infinity' ) {
+                                       $existingExpiryMessage = wfMessage( 'protect-existing-expiry-infinity' );
+                               } else {
+                                       $timestamp = $lang->timeanddate( $this->mExistingExpiry[$action], true );
+                                       $d = $lang->date( $this->mExistingExpiry[$action], true );
+                                       $t = $lang->time( $this->mExistingExpiry[$action], true );
+                                       $existingExpiryMessage = wfMessage( 'protect-existing-expiry', $timestamp, $d, $t );
+                               }
                                $expiryFormOptions .=
                                        Xml::option(
-                                               wfMessage( 'protect-existing-expiry', $timestamp, $d, $t )->text(),
+                                               $existingExpiryMessage->text(),
                                                'existing',
                                                $this->mExpirySelection[$action] == 'existing'
                                        ) . "\n";
index 78a41d5..253d25b 100644 (file)
@@ -77,6 +77,9 @@ if ( $wgStyleDirectory === false ) {
 if ( $wgExtensionAssetsPath === false ) {
        $wgExtensionAssetsPath = "$wgScriptPath/extensions";
 }
+if ( $wgResourceBasePath === null ) {
+       $wgResourceBasePath = $wgScriptPath;
+}
 
 if ( $wgLogo === false ) {
        $wgLogo = "$wgStylePath/common/images/wiki.png";
@@ -106,7 +109,7 @@ if ( $wgGitInfoCacheDirectory === false && $wgCacheDirectory !== false ) {
 if ( $wgRightsIcon ) {
        $wgRightsIcon = str_replace(
                "{$wgStylePath}/common/images/",
-               "{$wgScriptPath}/assets/licenses/",
+               "{$wgResourceBasePath}/resources/assets/licenses/",
                $wgRightsIcon
        );
 }
@@ -133,7 +136,7 @@ if ( isset( $wgFooterIcons['poweredby'] )
        && $wgFooterIcons['poweredby']['mediawiki']['src'] === null
 ) {
        $wgFooterIcons['poweredby']['mediawiki']['src'] =
-               "$wgScriptPath/assets/poweredby_mediawiki_88x31.png";
+               "$wgResourceBasePath/resources/assets/poweredby_mediawiki_88x31.png";
 }
 
 /**
index 8727b74..74d78ba 100644 (file)
@@ -4333,7 +4333,9 @@ class Title {
         * @return bool
         */
        public function exists() {
-               return $this->getArticleID() != 0;
+               $exists = $this->getArticleID() != 0;
+               wfRunHooks( 'TitleExists', array( $this, &$exists ) );
+               return $exists;
        }
 
        /**
index 0d677b1..bd20b14 100644 (file)
@@ -783,10 +783,12 @@ class ApiMain extends ApiBase {
                                $this->dieUsageMsg( array( 'missingparam', 'token' ) );
                        }
 
-                       if ( array_key_exists(
-                               $module->encodeParamName( 'token' ),
-                               $this->getRequest()->getQueryValues()
-                       ) ) {
+                       if ( !$this->getConfig()->get( 'DebugAPI' ) &&
+                               array_key_exists(
+                                       $module->encodeParamName( 'token' ),
+                                       $this->getRequest()->getQueryValues()
+                               )
+                       ) {
                                $this->dieUsage(
                                        "The '{$module->encodeParamName( 'token' )}' parameter was found in the query string, but must be in the POST body",
                                        'mustposttoken'
index 8407fad..7c750e4 100644 (file)
@@ -47,17 +47,20 @@ class ApiQuery extends ApiBase {
                'contributors' => 'ApiQueryContributors',
                'duplicatefiles' => 'ApiQueryDuplicateFiles',
                'extlinks' => 'ApiQueryExternalLinks',
+               'fileusage' => 'ApiQueryBacklinksprop',
                'images' => 'ApiQueryImages',
                'imageinfo' => 'ApiQueryImageInfo',
                'info' => 'ApiQueryInfo',
                'links' => 'ApiQueryLinks',
+               'linkshere' => 'ApiQueryBacklinksprop',
                'iwlinks' => 'ApiQueryIWLinks',
                'langlinks' => 'ApiQueryLangLinks',
                'pageprops' => 'ApiQueryPageProps',
-               'redirects' => 'ApiQueryRedirects',
+               'redirects' => 'ApiQueryBacklinksprop',
                'revisions' => 'ApiQueryRevisions',
                'stashimageinfo' => 'ApiQueryStashImageInfo',
                'templates' => 'ApiQueryLinks',
+               'transcludedin' => 'ApiQueryBacklinksprop',
        );
 
        /**
diff --git a/includes/api/ApiQueryBacklinksprop.php b/includes/api/ApiQueryBacklinksprop.php
new file mode 100644 (file)
index 0000000..cd68261
--- /dev/null
@@ -0,0 +1,472 @@
+<?php
+/**
+ * API module to handle links table back-queries
+ *
+ * Created on Aug 19, 2014
+ *
+ * Copyright © 2014 Brad Jorsch <bjorsch@wikimedia.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ *
+ * @file
+ * @since 1.24
+ */
+
+/**
+ * This implements prop=redirects, prop=linkshere, prop=catmembers,
+ * prop=transcludedin, and prop=fileusage
+ *
+ * @ingroup API
+ * @since 1.24
+ */
+class ApiQueryBacklinksprop extends ApiQueryGeneratorBase {
+
+       // Data for the various modules implemented by this class
+       private static $settings = array(
+               'redirects' => array(
+                       'code' => 'rd',
+                       'prefix' => 'rd',
+                       'linktable' => 'redirect',
+                       'what' => 'redirects to',
+                       'description' => 'Returns all redirects to the given pages.',
+                       'props' => array(
+                               'fragment' => 'Fragment of each redirect, if any',
+                       ),
+                       'showredirects' => false,
+                       'show' => array(
+                               'fragment' => 'Only show redirects with a fragment',
+                               '!fragment' => 'Only show redirects without a fragment',
+                       ),
+               ),
+               'linkshere' => array(
+                       'code' => 'lh',
+                       'prefix' => 'pl',
+                       'linktable' => 'pagelinks',
+                       'from_namespace' => true,
+                       'what' => 'pages linking to',
+                       'description' => 'Find all pages that link to the given pages.',
+                       'showredirects' => true,
+               ),
+               'transcludedin' => array(
+                       'code' => 'ti',
+                       'prefix' => 'tl',
+                       'linktable' => 'templatelinks',
+                       'from_namespace' => true,
+                       'what' => 'pages transcluding',
+                       'description' => 'Find all pages that transclude the given pages.',
+                       'showredirects' => true,
+               ),
+               'fileusage' => array(
+                       'code' => 'fu',
+                       'prefix' => 'il',
+                       'linktable' => 'imagelinks',
+                       'from_namespace' => true,
+                       'to_namespace' => NS_FILE,
+                       'what' => 'pages using',
+                       'exampletitle' => 'File:Example.jpg',
+                       'description' => 'Find all pages that use the given files.',
+                       'showredirects' => true,
+               ),
+       );
+
+       public function __construct( ApiQuery $query, $moduleName ) {
+               parent::__construct( $query, $moduleName, self::$settings[$moduleName]['code'] );
+       }
+
+       public function execute() {
+               $this->run();
+       }
+
+       public function executeGenerator( $resultPageSet ) {
+               $this->run( $resultPageSet );
+       }
+
+       /**
+        * @param ApiPageSet $resultPageSet
+        */
+       private function run( ApiPageSet $resultPageSet = null ) {
+               $settings = self::$settings[$this->getModuleName()];
+
+               $db = $this->getDB();
+               $params = $this->extractRequestParams();
+               $prop = array_flip( $params['prop'] );
+               $emptyString = $db->addQuotes( '' );
+
+               $pageSet = $this->getPageSet();
+               $titles = $pageSet->getGoodTitles() + $pageSet->getMissingTitles();
+               $map = $pageSet->getAllTitlesByNamespace();
+
+               // Determine our fields to query on
+               $p = $settings['prefix'];
+               $hasNS = !isset( $settings['to_namespace'] );
+               if ( $hasNS ) {
+                       $bl_namespace = "{$p}_namespace";
+                       $bl_title = "{$p}_title";
+               } else {
+                       $bl_namespace = $settings['to_namespace'];
+                       $bl_title = "{$p}_to";
+
+                       $titles = array_filter( $titles, function ( $t ) use ( $bl_namespace ) {
+                               return $t->getNamespace() === $bl_namespace;
+                       } );
+                       $map = array_intersect_key( $map, array( $bl_namespace => true ) );
+               }
+               $bl_from = "{$p}_from";
+
+               if ( !$titles ) {
+                       return; // nothing to do
+               }
+
+               // Figure out what we're sorting by, and add associated WHERE clauses.
+               // MySQL's query planner screws up if we include a field in ORDER BY
+               // when it's constant in WHERE, so we have to test that for each field.
+               $sortby = array();
+               if ( $hasNS && count( $map ) > 1 ) {
+                       $sortby[$bl_namespace] = 'ns';
+               }
+               $theTitle = null;
+               foreach ( $map as $nsTitles ) {
+                       reset( $nsTitles );
+                       $key = key( $nsTitles );
+                       if ( $theTitle === null ) {
+                               $theTitle = $key;
+                       }
+                       if ( count( $nsTitles ) > 1 || $key !== $theTitle ) {
+                               $sortby[$bl_title] = 'title';
+                               break;
+                       }
+               }
+               $miser_ns = null;
+               if ( $params['namespace'] !== null ) {
+                       if ( empty( $settings['from_namespace'] ) && $this->getConfig()->get( 'MiserMode' ) ) {
+                               $miser_ns = $params['namespace'];
+                       } else {
+                               $this->addWhereFld( "{$p}_from_namespace", $params['namespace'] );
+                               if ( !empty( $settings['from_namespace'] ) && count( $params['namespace'] ) > 1 ) {
+                                       $sortby["{$p}_from_namespace"] = 'int';
+                               }
+                       }
+               }
+               $sortby[$bl_from] = 'int';
+
+               // Now use the $sortby to figure out the continuation
+               if ( !is_null( $params['continue'] ) ) {
+                       $cont = explode( '|', $params['continue'] );
+                       $this->dieContinueUsageIf( count( $cont ) != count( $sortby ) );
+                       $where = '';
+                       $i = count( $sortby ) - 1;
+                       $cont_ns = 0;
+                       $cont_title = '';
+                       foreach ( array_reverse( $sortby, true ) as $field => $type ) {
+                               $v = $cont[$i];
+                               switch ( $type ) {
+                                       case 'ns':
+                                               $cont_ns = (int)$v;
+                                               /* fall through */
+                                       case 'int':
+                                               $v = (int)$v;
+                                               $this->dieContinueUsageIf( $v != $cont[$i] );
+                                               break;
+
+                                       case 'title':
+                                               $cont_title = $v;
+                                               /* fall through */
+                                       default:
+                                               $v = $db->addQuotes( $v );
+                                               break;
+                               }
+
+                               if ( $where === '' ) {
+                                       $where = "$field >= $v";
+                               } else {
+                                       $where = "$field > $v OR ($field = $v AND ($where))";
+                               }
+
+                               $i--;
+                       }
+                       $this->addWhere( $where );
+               }
+
+               // Populate the rest of the query
+               $this->addTables( array( $settings['linktable'], 'page' ) );
+               $this->addWhere( "$bl_from = page_id" );
+
+               if ( $this->getModuleName() === 'redirects' ) {
+                       $this->addWhere( "rd_interwiki = $emptyString OR rd_interwiki IS NULL" );
+               }
+
+               $this->addFields( array_keys( $sortby ) );
+               $this->addFields( array( 'bl_namespace' => $bl_namespace, 'bl_title' => $bl_title ) );
+               if ( is_null( $resultPageSet ) ) {
+                       $fld_pageid = isset( $prop['pageid'] );
+                       $fld_title = isset( $prop['title'] );
+                       $fld_redirect = isset( $prop['redirect'] );
+
+                       $this->addFieldsIf( 'page_id', $fld_pageid );
+                       $this->addFieldsIf( array( 'page_title', 'page_namespace' ), $fld_title );
+                       $this->addFieldsIf( 'page_is_redirect', $fld_redirect );
+
+                       // prop=redirects
+                       $fld_fragment = isset( $prop['fragment'] );
+                       $this->addFieldsIf( 'rd_fragment', $fld_fragment );
+               } else {
+                       $this->addFields( $resultPageSet->getPageTableFields() );
+               }
+
+               $this->addFieldsIf( 'page_namespace', $miser_ns !== null );
+
+               if ( $hasNS ) {
+                       $lb = new LinkBatch( $titles );
+                       $this->addWhere( $lb->constructSet( $p, $db ) );
+               } else {
+                       $where = array();
+                       foreach ( $titles as $t ) {
+                               if ( $t->getNamespace() == $bl_namespace ) {
+                                       $where[] = "$bl_title = " . $db->addQuotes( $t->getDBkey() );
+                               }
+                       }
+                       $this->addWhere( $db->makeList( $where, LIST_OR ) );
+               }
+
+               if ( $params['show'] !== null ) {
+                       // prop=redirects only
+                       $show = array_flip( $params['show'] );
+                       if ( isset( $show['fragment'] ) && isset( $show['!fragment'] ) ||
+                               isset( $show['redirect'] ) && isset( $show['!redirect'] )
+                       ) {
+                               $this->dieUsageMsg( 'show' );
+                       }
+                       $this->addWhereIf( "rd_fragment != $emptyString", isset( $show['fragment'] ) );
+                       $this->addWhereIf(
+                               "rd_fragment = $emptyString OR rd_fragment IS NULL",
+                               isset( $show['!fragment'] )
+                       );
+                       $this->addWhereIf( array( 'page_is_redirect' => 1 ), isset( $show['redirect'] ) );
+                       $this->addWhereIf( array( 'page_is_redirect' => 0 ), isset( $show['!redirect'] ) );
+               }
+
+               // Override any ORDER BY from above with what we calculated earlier.
+               $this->addOption( 'ORDER BY', array_keys( $sortby ) );
+
+               $this->addOption( 'LIMIT', $params['limit'] + 1 );
+
+               $res = $this->select( __METHOD__ );
+
+               if ( is_null( $resultPageSet ) ) {
+                       $count = 0;
+                       foreach ( $res as $row ) {
+                               if ( ++$count > $params['limit'] ) {
+                                       // We've reached the one extra which shows that
+                                       // there are additional pages to be had. Stop here...
+                                       $this->setContinue( $row, $sortby );
+                                       break;
+                               }
+
+                               if ( $miser_ns !== null && !in_array( $row->page_namespace, $miser_ns ) ) {
+                                       // Miser mode namespace check
+                                       continue;
+                               }
+
+                               // Get the ID of the current page
+                               $id = $map[$row->bl_namespace][$row->bl_title];
+
+                               $vals = array();
+                               if ( $fld_pageid ) {
+                                       $vals['pageid'] = $row->page_id;
+                               }
+                               if ( $fld_title ) {
+                                       ApiQueryBase::addTitleInfo( $vals,
+                                               Title::makeTitle( $row->page_namespace, $row->page_title )
+                                       );
+                               }
+                               if ( $fld_fragment && $row->rd_fragment !== null && $row->rd_fragment !== '' ) {
+                                       $vals['fragment'] = $row->rd_fragment;
+                               }
+                               if ( $fld_redirect && $row->page_is_redirect ) {
+                                       $vals['redirect'] = '';
+                               }
+                               $fit = $this->addPageSubItem( $id, $vals );
+                               if ( !$fit ) {
+                                       $this->setContinue( $row, $sortby );
+                                       break;
+                               }
+                       }
+               } else {
+                       $titles = array();
+                       $count = 0;
+                       foreach ( $res as $row ) {
+                               if ( ++$count > $params['limit'] ) {
+                                       // We've reached the one extra which shows that
+                                       // there are additional pages to be had. Stop here...
+                                       $this->setContinue( $row, $sortby );
+                                       break;
+                               }
+                               $titles[] = Title::makeTitle( $row->page_namespace, $row->page_title );
+                       }
+                       $resultPageSet->populateFromTitles( $titles );
+               }
+       }
+
+       private function setContinue( $row, $sortby ) {
+               $cont = array();
+               foreach ( $sortby as $field => $v ) {
+                       $cont[] = $row->$field;
+               }
+               $this->setContinueEnumParameter( 'continue', join( '|', $cont ) );
+       }
+
+       public function getCacheMode( $params ) {
+               return 'public';
+       }
+
+       public function getAllowedParams() {
+               $settings = self::$settings[$this->getModuleName()];
+
+               $ret = array(
+                       'prop' => array(
+                               ApiBase::PARAM_TYPE => array(
+                                       'pageid',
+                                       'title',
+                               ),
+                               ApiBase::PARAM_ISMULTI => true,
+                               ApiBase::PARAM_DFLT => 'pageid|title',
+                       ),
+                       'namespace' => array(
+                               ApiBase::PARAM_ISMULTI => true,
+                               ApiBase::PARAM_TYPE => 'namespace',
+                       ),
+                       'limit' => array(
+                               ApiBase::PARAM_DFLT => 10,
+                               ApiBase::PARAM_TYPE => 'limit',
+                               ApiBase::PARAM_MIN => 1,
+                               ApiBase::PARAM_MAX => ApiBase::LIMIT_BIG1,
+                               ApiBase::PARAM_MAX2 => ApiBase::LIMIT_BIG2
+                       ),
+                       'continue' => null,
+               );
+
+               if ( !empty( $settings['showredirects'] ) ) {
+                       $ret['prop'][ApiBase::PARAM_TYPE][] = 'redirect';
+                       $ret['prop'][ApiBase::PARAM_DFLT] .= '|redirect';
+               }
+               if ( isset( $settings['props'] ) ) {
+                       $ret['prop'][ApiBase::PARAM_TYPE] = array_merge(
+                               $ret['prop'][ApiBase::PARAM_TYPE], array_keys( $settings['props'] )
+                       );
+               }
+
+               $show = array();
+               if ( !empty( $settings['showredirects'] ) ) {
+                       $show[] = 'redirect';
+                       $show[] = '!redirect';
+               }
+               if ( isset( $settings['show'] ) ) {
+                       $show = array_merge( $show, array_keys( $settings['show'] ) );
+               }
+               if ( $show ) {
+                       $ret['show'] = array(
+                               ApiBase::PARAM_TYPE => $show,
+                               ApiBase::PARAM_ISMULTI => true,
+                       );
+               }
+
+               return $ret;
+       }
+
+       public function getParamDescription() {
+               $settings = self::$settings[$this->getModuleName()];
+               $p = $this->getModulePrefix();
+
+               $ret = array(
+                       'prop' => array(
+                               'Which properties to get:',
+                       ),
+                       'show' => array(
+                               'Show only items that meet this criteria.',
+                       ),
+                       'namespace' => 'Only include pages in these namespaces',
+                       'limit' => 'How many to return',
+                       'continue' => 'When more results are available, use this to continue',
+               );
+
+               if ( empty( $settings['from_namespace'] ) && $this->getConfig()->get( 'MiserMode' ) ) {
+                       $ret['namespace'] = array(
+                               $ret['namespace'],
+                               "NOTE: Due to \$wgMiserMode, using this may result in fewer than \"{$p}limit\" results",
+                               'returned before continuing; in extreme cases, zero results may be returned.',
+                       );
+                       if ( isset( $ret['type'] ) ) {
+                               $ret['namespace'][] = "Note that you can use {$p}type=subcat or {$p}type=file " .
+                                       "instead of {$p}namespace=14 or 6.";
+                       }
+               }
+
+               $props = array(
+                       'pageid' => 'Adds the ID of page',
+                       'title' => 'Adds the title and namespace ID of the page',
+               );
+               if ( !empty( $settings['showredirects'] ) ) {
+                       $props['redirect'] = 'Indicate if the page is a redirect';
+               }
+               if ( isset( $settings['props'] ) ) {
+                       $props += $settings['props'];
+               }
+               foreach ( $props as $k => $v ) {
+                       $ret['props'][] = sprintf( "%-9s - %s", $k, $v );
+               }
+
+               $show = array();
+               if ( !empty( $settings['showredirects'] ) ) {
+                       $show += array(
+                               'redirect' => 'Only show redirects',
+                               '!redirect' => 'Only show non-redirects',
+                       );
+               }
+               if ( isset( $settings['show'] ) ) {
+                       $show += $settings['show'];
+               }
+               foreach ( $show as $k => $v ) {
+                       $ret['show'][] = sprintf( "%-9s - %s", $k, $v );
+               }
+
+               return $ret;
+       }
+
+       public function getDescription() {
+               return self::$settings[$this->getModuleName()]['description'];
+       }
+
+       public function getExamples() {
+               $settings = self::$settings[$this->getModuleName()];
+               $name = $this->getModuleName();
+               $what = $settings['what'];
+               $title = isset( $settings['exampletitle'] ) ? $settings['exampletitle'] : 'Main Page';
+               $etitle = rawurlencode( $title );
+
+               return array(
+                       "api.php?action=query&prop={$name}&titles={$etitle}"
+                               => "Get a list of $what [[$title]]",
+                       "api.php?action=query&generator={$name}&titles={$etitle}&prop=info"
+                               => "Get information about $what [[$title]]",
+               );
+       }
+
+       public function getHelpUrls() {
+               $name = $this->getModuleName();
+               $prefix = $this->getModulePrefix();
+               return "https://www.mediawiki.org/wiki/API:Properties#{$name}_.2F_{$prefix}";
+       }
+}
index 5cc1454..945374b 100644 (file)
@@ -237,9 +237,11 @@ class ApiQueryImageInfo extends ApiQueryBase {
                        $scale = array();
                        $scale['height'] = $params['urlheight'];
                } else {
-                       $scale = null;
                        if ( $params['urlparam'] ) {
-                               $this->dieUsage( "{$p}urlparam requires {$p}urlwidth", "urlparam_no_width" );
+                               // Audio files might not have a width/height.
+                               $scale = array();
+                       } else {
+                               $scale = null;
                        }
                }
 
@@ -256,6 +258,10 @@ class ApiQueryImageInfo extends ApiQueryBase {
         * @return array Array of parameters for transform.
         */
        protected function mergeThumbParams( $image, $thumbParams, $otherParams ) {
+               if ( $thumbParams === null ) {
+                       // No scaling requested
+                       return null;
+               }
                if ( !isset( $thumbParams['width'] ) && isset( $thumbParams['height'] ) ) {
                        // We want to limit only by height in this situation, so pass the
                        // image's full width as the limiting width. But some file types
@@ -269,6 +275,7 @@ class ApiQueryImageInfo extends ApiQueryBase {
                }
 
                if ( !$otherParams ) {
+                       $this->checkParameterNormalise( $image, $thumbParams );
                        return $thumbParams;
                }
                $p = $this->getModulePrefix();
@@ -289,11 +296,11 @@ class ApiQueryImageInfo extends ApiQueryBase {
                        // handlers.
                        $this->setWarning( "Could not parse {$p}urlparam for " . $image->getName()
                                . '. Using only width and height' );
-
+                       $this->checkParameterNormalise( $image, $thumbParams );
                        return $thumbParams;
                }
 
-               if ( isset( $paramList['width'] ) ) {
+               if ( isset( $paramList['width'] ) && isset( $thumbParams['width'] ) ) {
                        if ( intval( $paramList['width'] ) != intval( $thumbParams['width'] ) ) {
                                $this->setWarning( "Ignoring width value set in {$p}urlparam ({$paramList['width']}) "
                                        . "in favor of width value derived from {$p}urlwidth/{$p}urlheight "
@@ -307,7 +314,33 @@ class ApiQueryImageInfo extends ApiQueryBase {
                        }
                }
 
-               return $thumbParams + $paramList;
+               $finalParams = $thumbParams + $paramList;
+               $this->checkParameterNormalise( $image, $finalParams );
+               return $finalParams;
+       }
+
+       /**
+        * Verify that the final image parameters can be normalised.
+        *
+        * This doesn't use the normalised parameters, since $file->transform
+        * expects the pre-normalised parameters, but doing the normalisation
+        * allows us to catch certain error conditions early (such as missing
+        * required parameter).
+        *
+        * @param $image File
+        * @param $finalParams array List of parameters to transform image with
+        */
+       protected function checkParameterNormalise( $image, $finalParams ) {
+               $h = $image->getHandler();
+               if ( !$h ) {
+                       return;
+               }
+               // Note: normaliseParams modifies the array in place, but we aren't interested
+               // in the actual normalised version, only if we can actually normalise them,
+               // so we use the functions scope to throw away the normalisations.
+               if ( !$h->normaliseParams( $image, $finalParams ) ) {
+                       $this->dieUsage( "Could not normalise image parameters for " . $image->getName(), "urlparamnormal" );
+               }
        }
 
        /**
@@ -391,6 +424,13 @@ class ApiQueryImageInfo extends ApiQueryBase {
                        if ( $pageCount !== false ) {
                                $vals['pagecount'] = $pageCount;
                        }
+
+                       // length as in how many seconds long a video is.
+                       $length = $file->getLength();
+                       if ( $length ) {
+                               // Call it duration, because "length" can be ambiguous.
+                               $vals['duration'] = (float)$length;
+                       }
                }
 
                $pcomment = isset( $prop['parsedcomment'] );
@@ -666,8 +706,8 @@ class ApiQueryImageInfo extends ApiQueryBase {
                        'parsedcomment' =>  ' parsedcomment - Parse the comment on the version',
                        'canonicaltitle' => ' canonicaltitle - Adds the canonical title of the image file',
                        'url' =>            ' url           - Gives URL to the image and the description page',
-                       'size' =>           ' size          - Adds the size of the image in bytes ' .
-                               'and the height, width and page count (if applicable)',
+                       'size' =>           ' size          - Adds the size of the image in bytes, ' .
+                               'its height and its width. Page count and duration are added if applicable',
                        'dimensions' =>     ' dimensions    - Alias for size', // B/C with Allimages
                        'sha1' =>           ' sha1          - Adds SHA-1 hash for the image',
                        'mime' =>           ' mime          - Adds MIME type of the image',
@@ -716,8 +756,10 @@ class ApiQueryImageInfo extends ApiQueryBase {
                                        'no more than ' . self::TRANSFORM_LIMIT . ' scaled images will be returned.'
                        ),
                        'urlheight' => "Similar to {$p}urlwidth.",
-                       'urlparam' => array( "A handler specific parameter string. For example, pdf's ",
-                               "might use 'page15-100px'. {$p}urlwidth must be used and be consistent with {$p}urlparam" ),
+                       'urlparam' => array(
+                               "A handler specific parameter string. For example, pdf's ",
+                               "might use 'page15-100px'."
+                       ),
                        'limit' => 'How many image revisions to return per image',
                        'start' => 'Timestamp to start listing from',
                        'end' => 'Timestamp to stop listing at',
diff --git a/includes/api/ApiQueryRedirects.php b/includes/api/ApiQueryRedirects.php
deleted file mode 100644 (file)
index afb2c56..0000000
+++ /dev/null
@@ -1,270 +0,0 @@
-<?php
-/**
- * API module to return redirects to a page
- *
- * Created on Dec 30, 2013
- *
- * Copyright © 2013 Brad Jorsch <bjorsch@wikimedia.org>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- * http://www.gnu.org/copyleft/gpl.html
- *
- * @file
- * @since 1.23
- */
-
-/**
- * This query lists redirects to the given pages.
- *
- * @ingroup API
- */
-class ApiQueryRedirects extends ApiQueryGeneratorBase {
-
-       public function __construct( ApiQuery $query, $moduleName ) {
-               parent::__construct( $query, $moduleName, 'rd' );
-       }
-
-       public function execute() {
-               $this->run();
-       }
-
-       public function executeGenerator( $resultPageSet ) {
-               $this->run( $resultPageSet );
-       }
-
-       /**
-        * @param ApiPageSet $resultPageSet
-        */
-       private function run( ApiPageSet $resultPageSet = null ) {
-               $db = $this->getDB();
-               $params = $this->extractRequestParams();
-               $emptyString = $db->addQuotes( '' );
-
-               $pageSet = $this->getPageSet();
-               $titles = $pageSet->getGoodTitles() + $pageSet->getMissingTitles();
-
-               if ( !is_null( $params['continue'] ) ) {
-                       $cont = explode( '|', $params['continue'] );
-                       $this->dieContinueUsageIf( count( $cont ) != 3 );
-                       $rd_namespace = (int)$cont[0];
-                       $this->dieContinueUsageIf( $rd_namespace != $cont[0] );
-                       $rd_title = $db->addQuotes( $cont[1] );
-                       $rd_from = (int)$cont[2];
-                       $this->dieContinueUsageIf( $rd_from != $cont[2] );
-                       $this->addWhere(
-                               "rd_namespace > $rd_namespace OR " .
-                               "(rd_namespace = $rd_namespace AND " .
-                               "(rd_title > $rd_title OR " .
-                               "(rd_title = $rd_title AND " .
-                               "rd_from >= $rd_from)))"
-                       );
-
-                       // Remove titles that we're past already
-                       $titles = array_filter( $titles, function ( $t ) use ( $rd_namespace, $rd_title ) {
-                               $ns = $t->getNamespace();
-                               return ( $ns > $rd_namespace ||
-                                       $ns == $rd_namespace && $t->getDBKey() >= $rd_title
-                               );
-                       } );
-               }
-
-               if ( !$titles ) {
-                       return; // nothing to do
-               }
-
-               $this->addTables( array( 'redirect', 'page' ) );
-               $this->addFields( array(
-                       'rd_from',
-                       'rd_namespace',
-                       'rd_title',
-               ) );
-
-               if ( is_null( $resultPageSet ) ) {
-                       $prop = array_flip( $params['prop'] );
-                       $fld_pageid = isset( $prop['pageid'] );
-                       $fld_title = isset( $prop['title'] );
-                       $fld_fragment = isset( $prop['fragment'] );
-
-                       $this->addFieldsIf( 'rd_fragment', $fld_fragment );
-                       $this->addFieldsIf( array( 'page_namespace', 'page_title' ), $fld_title );
-               } else {
-                       $this->addFields( array( 'page_namespace', 'page_title' ) );
-               }
-
-               $lb = new LinkBatch( $titles );
-               $this->addWhere( array(
-                       'rd_from = page_id',
-                       "rd_interwiki = $emptyString OR rd_interwiki IS NULL",
-                       $lb->constructSet( 'rd', $db ),
-               ) );
-
-               if ( $params['show'] !== null ) {
-                       $show = array_flip( $params['show'] );
-                       if ( isset( $show['fragment'] ) && isset( $show['!fragment'] ) ) {
-                               $this->dieUsageMsg( 'show' );
-                       }
-                       $this->addWhereIf( "rd_fragment != $emptyString", isset( $show['fragment'] ) );
-                       $this->addWhereIf(
-                               "rd_fragment = $emptyString OR rd_fragment IS NULL",
-                               isset( $show['!fragment'] )
-                       );
-               }
-
-               $map = $pageSet->getAllTitlesByNamespace();
-
-               // Why, MySQL? Why do you do this to us?
-               $sortby = array();
-               if ( count( $map ) > 1 ) {
-                       $sortby[] = 'rd_namespace';
-               }
-               $theTitle = null;
-               foreach ( $map as $nsTitles ) {
-                       reset( $nsTitles );
-                       $key = key( $nsTitles );
-                       if ( $theTitle === null ) {
-                               $theTitle = $key;
-                       }
-                       if ( count( $nsTitles ) > 1 || $key !== $theTitle ) {
-                               $sortby[] = 'rd_title';
-                               break;
-                       }
-               }
-               $sortby[] = 'rd_from';
-               $this->addOption( 'ORDER BY', $sortby );
-
-               $this->addOption( 'LIMIT', $params['limit'] + 1 );
-
-               $res = $this->select( __METHOD__ );
-
-               if ( is_null( $resultPageSet ) ) {
-                       $count = 0;
-                       foreach ( $res as $row ) {
-                               if ( ++$count > $params['limit'] ) {
-                                       // We've reached the one extra which shows that
-                                       // there are additional pages to be had. Stop here...
-                                       $this->setContinueEnumParameter( 'continue',
-                                               "$row->rd_namespace|$row->rd_title|$row->rd_from"
-                                       );
-                                       break;
-                               }
-
-                               # Get the ID of the current page
-                               $id = $map[$row->rd_namespace][$row->rd_title];
-
-                               $vals = array();
-                               if ( $fld_pageid ) {
-                                       $vals['pageid'] = $row->rd_from;
-                               }
-                               if ( $fld_title ) {
-                                       ApiQueryBase::addTitleInfo( $vals,
-                                               Title::makeTitle( $row->page_namespace, $row->page_title )
-                                       );
-                               }
-                               if ( $fld_fragment && $row->rd_fragment !== null && $row->rd_fragment !== '' ) {
-                                       $vals['fragment'] = $row->rd_fragment;
-                               }
-                               $fit = $this->addPageSubItem( $id, $vals );
-                               if ( !$fit ) {
-                                       $this->setContinueEnumParameter( 'continue',
-                                               "$row->rd_namespace|$row->rd_title|$row->rd_from"
-                                       );
-                                       break;
-                               }
-                       }
-               } else {
-                       $titles = array();
-                       $count = 0;
-                       foreach ( $res as $row ) {
-                               if ( ++$count > $params['limit'] ) {
-                                       // We've reached the one extra which shows that
-                                       // there are additional pages to be had. Stop here...
-                                       $this->setContinueEnumParameter( 'continue',
-                                               "$row->rd_namespace|$row->rd_title|$row->rd_from"
-                                       );
-                                       break;
-                               }
-                               $titles[] = Title::makeTitle( $row->page_namespace, $row->page_title );
-                       }
-                       $resultPageSet->populateFromTitles( $titles );
-               }
-       }
-
-       public function getCacheMode( $params ) {
-               return 'public';
-       }
-
-       public function getAllowedParams() {
-               return array(
-                       'prop' => array(
-                               ApiBase::PARAM_TYPE => array(
-                                       'pageid',
-                                       'title',
-                                       'fragment',
-                               ),
-                               ApiBase::PARAM_ISMULTI => true,
-                               ApiBase::PARAM_DFLT => 'pageid|title',
-                       ),
-                       'show' => array(
-                               ApiBase::PARAM_TYPE => array(
-                                       'fragment', '!fragment',
-                               ),
-                               ApiBase::PARAM_ISMULTI => true,
-                       ),
-                       'limit' => array(
-                               ApiBase::PARAM_DFLT => 10,
-                               ApiBase::PARAM_TYPE => 'limit',
-                               ApiBase::PARAM_MIN => 1,
-                               ApiBase::PARAM_MAX => ApiBase::LIMIT_BIG1,
-                               ApiBase::PARAM_MAX2 => ApiBase::LIMIT_BIG2
-                       ),
-                       'continue' => null,
-               );
-       }
-
-       public function getParamDescription() {
-               return array(
-                       'prop' => array(
-                               'Which properties to get:',
-                               ' pageid   - Page id of each redirect',
-                               ' title    - Title of each redirect',
-                               ' fragment - Fragment of each redirect, if any',
-                       ),
-                       'show' => array(
-                               'Show only items that meet this criteria.',
-                               ' fragment  - Only show redirects with a fragment',
-                               ' !fragment - Only show redirects without a fragment',
-                       ),
-                       'limit' => 'How many redirects to return',
-                       'continue' => 'When more results are available, use this to continue',
-               );
-       }
-
-       public function getDescription() {
-               return 'Returns all redirects to the given page(s).';
-       }
-
-       public function getExamples() {
-               return array(
-                       'api.php?action=query&prop=redirects&titles=Main%20Page'
-                               => 'Get a list of redirects to the [[Main Page]]',
-                       'api.php?action=query&generator=redirects&titles=Main%20Page&prop=info'
-                               => 'Get information about all redirects to the [[Main Page]]',
-               );
-       }
-
-       public function getHelpUrls() {
-               return 'https://www.mediawiki.org/wiki/API:Properties#redirects_.2F_rd';
-       }
-}
index fd0c429..311438f 100644 (file)
@@ -344,7 +344,7 @@ class ApiQuerySiteinfo extends ApiQueryBase {
                global $wgContLang;
                $data = array();
                $aliases = $wgContLang->getSpecialPageAliases();
-               foreach ( SpecialPageFactory::getList() as $specialpage => $stuff ) {
+               foreach ( SpecialPageFactory::getNames() as $specialpage ) {
                        if ( isset( $aliases[$specialpage] ) ) {
                                $arr = array( 'realname' => $specialpage, 'aliases' => $aliases[$specialpage] );
                                $this->getResult()->setIndexedTagName( $arr['aliases'], 'alias' );
index 7bafc99..212e5e8 100644 (file)
  */
 
 /**
- * Bloom filter implented using Redis
+ * Bloom filter implemented using Redis
  *
  * The Redis server must be >= 2.6 and should have volatile-lru or volatile-ttl
  * if there is any eviction policy. It should not be allkeys-* in any case. Also,
- * this can be used in a simple master/slave setup or with Redis Sentinal preferably.
+ * this can be used in a simple master/slave setup or with Redis Sentinel preferably.
  *
  * Some bits are based on https://github.com/ErikDubbelboer/redis-lua-scaling-bloom-filter
  * but are simplified to use a single filter instead of up to 32 filters.
index 03d2cb9..38f589d 100644 (file)
@@ -35,4 +35,13 @@ interface Config {
         * @throws ConfigException
         */
        public function get( $name );
+
+       /**
+        * Check whether a configuration option is set for the given name
+        *
+        * @param string $name Name of configuration option
+        * @return bool
+        * @since 1.24
+        */
+       public function has( $name );
 }
index 1144384..39d6e8e 100644 (file)
@@ -49,9 +49,19 @@ class GlobalVarConfig implements Config {
         * @see Config::get
         */
        public function get( $name ) {
+               if ( !$this->has( $name ) ) {
+                       throw new ConfigException( __METHOD__ . ": undefined option: '$name'" );
+               }
                return $this->getWithPrefix( $this->prefix, $name );
        }
 
+       /**
+        * @see Config::has
+        */
+       public function has( $name ) {
+               return $this->hasWithPrefix( $this->prefix, $name );
+       }
+
        /**
         * @see MutableConfig::set
         * @deprecated since 1.24
@@ -66,15 +76,22 @@ class GlobalVarConfig implements Config {
         *
         * @param string $prefix Prefix to use on the variable, if one.
         * @param string $name Variable name without prefix
-        * @throws ConfigException
         * @return mixed
         */
        protected function getWithPrefix( $prefix, $name ) {
+               return $GLOBALS[$prefix . $name];
+       }
+
+       /**
+        * Check if a variable with a given prefix is set
+        *
+        * @param string $prefix Prefix to use on the variable
+        * @param string $name Variable name without prefix
+        * @return bool
+        */
+       protected function hasWithPrefix( $prefix, $name ) {
                $var = $prefix . $name;
-               if ( !array_key_exists( $var, $GLOBALS ) ) {
-                       throw new ConfigException( __METHOD__ . ": undefined variable: '$var'" );
-               }
-               return $GLOBALS[$var];
+               return array_key_exists( $var, $GLOBALS );
        }
 
        /**
diff --git a/includes/config/HashConfig.php b/includes/config/HashConfig.php
new file mode 100644 (file)
index 0000000..a09a0a4
--- /dev/null
@@ -0,0 +1,75 @@
+<?php
+/**
+ * Copyright 2014
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ *
+ * @file
+ */
+
+/**
+ * A Config instance which stores all settings as a member variable
+ *
+ * @since 1.24
+ */
+class HashConfig implements Config, MutableConfig {
+
+       /**
+        * Array of config settings
+        *
+        * @var array
+        */
+       private $settings;
+
+       /**
+        * @return HashConfig
+        */
+       public static function newInstance() {
+               return new HashConfig;
+       }
+
+       /**
+        * @param array $settings Any current settings to pre-load
+        */
+       public function __construct( array $settings = array() ) {
+               $this->settings = $settings;
+       }
+
+       /**
+        * @see Config::get
+        */
+       public function get( $name ) {
+               if ( !$this->has( $name ) ) {
+                       throw new ConfigException( __METHOD__ . ": undefined option: '$name'" );
+               }
+
+               return $this->settings[$name];
+       }
+
+       /**
+        * @see Config::has
+        */
+       public function has( $name ) {
+               return array_key_exists( $name, $this->settings );
+       }
+
+       /**
+        * @see Config::set
+        */
+       public function set( $name, $value ) {
+               $this->settings[$name] = $value;
+       }
+}
diff --git a/includes/config/MultiConfig.php b/includes/config/MultiConfig.php
new file mode 100644 (file)
index 0000000..cbb65aa
--- /dev/null
@@ -0,0 +1,72 @@
+<?php
+/**
+ * Copyright 2014
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ *
+ * @file
+ */
+
+/**
+ * Provides a fallback sequence for Config objects
+ *
+ * @since 1.24
+ */
+class MultiConfig implements Config {
+
+       /**
+        * Array of Config objects to use
+        * Order matters, the Config objects
+        * will be checked in order to see
+        * whether they have the requested setting
+        *
+        * @var Config[]
+        */
+       private $configs;
+
+       /**
+        * @param Config[] $configs
+        */
+       public function __construct( array $configs ) {
+               $this->configs = $configs;
+       }
+
+       /**
+        * @see Config::get
+        */
+       public function get( $name ) {
+               foreach ( $this->configs as $config ) {
+                       if ( $config->has( $name ) ) {
+                               return $config->get( $name );
+                       }
+               }
+
+               throw new ConfigException( __METHOD__ . ": undefined option: '$name'" );
+       }
+
+       /**
+        * @see Config::has
+        */
+       public function has( $name ) {
+               foreach ( $this->configs as $config ) {
+                       if ( $config->has( $name ) ) {
+                               return true;
+                       }
+               }
+
+               return false;
+       }
+}
index 683c959..9d257a6 100644 (file)
@@ -483,7 +483,12 @@ abstract class AbstractContent implements Content {
                if ( wfRunHooks( 'ContentGetParserOutput',
                        array( $this, $title, $revId, $options, $generateHtml, &$po ) ) ) {
 
+                       // Save and restore the old value, just in case something is reusing
+                       // the ParserOptions object in some weird way.
+                       $oldRedir = $options->getRedirectTarget();
+                       $options->setRedirectTarget( $this->getRedirectTarget() );
                        $this->fillParserOutput( $title, $revId, $options, $generateHtml, $po );
+                       $options->setRedirectTarget( $oldRedir );
                }
 
                return $po;
index 3ab6a6d..9a8ab3a 100644 (file)
@@ -31,6 +31,7 @@
  * @ingroup Content
  */
 class WikitextContent extends TextContent {
+       private $redirectTargetAndText = null;
 
        public function __construct( $text ) {
                parent::__construct( $text, CONTENT_MODEL_WIKITEXT );
@@ -178,10 +179,17 @@ class WikitextContent extends TextContent {
         */
        protected function getRedirectTargetAndText() {
                global $wgMaxRedirects;
+
+               if ( $this->redirectTargetAndText !== null ) {
+                       return $this->redirectTargetAndText;
+               }
+
                if ( $wgMaxRedirects < 1 ) {
                        // redirects are disabled, so quit early
-                       return array( null, $this->getNativeData() );
+                       $this->redirectTargetAndText = array( null, $this->getNativeData() );
+                       return $this->redirectTargetAndText;
                }
+
                $redir = MagicWord::get( 'redirect' );
                $text = ltrim( $this->getNativeData() );
                if ( $redir->matchStartAndRemove( $text ) ) {
@@ -199,14 +207,17 @@ class WikitextContent extends TextContent {
                                $title = Title::newFromText( $m[1] );
                                // If the title is a redirect to bad special pages or is invalid, return null
                                if ( !$title instanceof Title || !$title->isValidRedirectTarget() ) {
-                                       return array( null, $this->getNativeData() );
+                                       $this->redirectTargetAndText = array( null, $this->getNativeData() );
+                                       return $this->redirectTargetAndText;
                                }
 
-                               return array( $title, substr( $text, strlen( $m[0] ) ) );
+                               $this->redirectTargetAndText = array( $title, substr( $text, strlen( $m[0] ) ) );
+                               return $this->redirectTargetAndText;
                        }
                }
 
-               return array( null, $this->getNativeData() );
+               $this->redirectTargetAndText = array( null, $this->getNativeData() );
+               return $this->redirectTargetAndText;
        }
 
        /**
index 11a3e5c..b574c5e 100644 (file)
@@ -1328,9 +1328,9 @@ abstract class File {
         * @return ThumbnailImage
         */
        function iconThumb() {
-               global $wgScriptPath, $IP;
-               $assetsPath = "$wgScriptPath/assets/file-type-icons/";
-               $assetsDirectory = "$IP/assets/file-type-icons/";
+               global $wgResourceBasePath, $IP;
+               $assetsPath = "$wgResourceBasePath/resources/assets/file-type-icons/";
+               $assetsDirectory = "$IP/resources/assets/file-type-icons/";
 
                $try = array( 'fileicon-' . $this->getExtension() . '.png', 'fileicon.png' );
                foreach ( $try as $icon ) {
index 5fda7bd..d582da3 100644 (file)
@@ -139,6 +139,7 @@ class HTMLForm extends ContextSource {
        protected $mFieldTree;
        protected $mShowReset = false;
        protected $mShowSubmit = true;
+       protected $mSubmitModifierClass = 'mw-ui-constructive';
 
        protected $mSubmitCallback;
        protected $mValidationErrorMessage;
@@ -897,7 +898,7 @@ class HTMLForm extends ContextSource {
                        $attribs['class'] = array( 'mw-htmlform-submit' );
 
                        if ( $this->isVForm() || $useMediaWikiUIEverywhere ) {
-                               array_push( $attribs['class'], 'mw-ui-button', 'mw-ui-constructive' );
+                               array_push( $attribs['class'], 'mw-ui-button', $this->mSubmitModifierClass );
                        }
 
                        if ( $this->isVForm() ) {
@@ -1042,6 +1043,14 @@ class HTMLForm extends ContextSource {
                return $this;
        }
 
+       /**
+        * Identify that the submit button in the form has a destructive action
+        *
+        */
+       public function setSubmitDestructive() {
+               $this->mSubmitModifierClass = 'mw-ui-destructive';
+       }
+
        /**
         * Set the text for the submit button to a message
         * @since 1.19
index 1c7762b..7290740 100644 (file)
@@ -107,6 +107,15 @@ class CliInstaller extends Installer {
                if ( isset( $option['pass'] ) ) {
                        $this->setVar( '_AdminPassword', $option['pass'] );
                }
+
+               // Set up the default skins
+               $skins = $this->findExtensions( 'skins' );
+               $this->setVar( '_Skins', $skins );
+
+               if ( $skins ) {
+                       $skinNames = array_map( 'strtolower', $skins );
+                       $this->setVar( 'wgDefaultSkin', $this->getDefaultSkin( $skinNames ) );
+               }
        }
 
        /**
index 544efb6..f84ed00 100644 (file)
@@ -286,27 +286,27 @@ abstract class Installer {
        public $licenses = array(
                'cc-by' => array(
                        'url' => 'http://creativecommons.org/licenses/by/3.0/',
-                       'icon' => '{$wgScriptPath}/assets/licenses/cc-by.png',
+                       'icon' => '{$wgResourceBasePath}/resources/assets/licenses/cc-by.png',
                ),
                'cc-by-sa' => array(
                        'url' => 'http://creativecommons.org/licenses/by-sa/3.0/',
-                       'icon' => '{$wgScriptPath}/assets/licenses/cc-by-sa.png',
+                       'icon' => '{$wgResourceBasePath}/resources/assets/licenses/cc-by-sa.png',
                ),
                'cc-by-nc-sa' => array(
                        'url' => 'http://creativecommons.org/licenses/by-nc-sa/3.0/',
-                       'icon' => '{$wgScriptPath}/assets/licenses/cc-by-nc-sa.png',
+                       'icon' => '{$wgResourceBasePath}/resources/assets/licenses/cc-by-nc-sa.png',
                ),
                'cc-0' => array(
                        'url' => 'https://creativecommons.org/publicdomain/zero/1.0/',
-                       'icon' => '{$wgScriptPath}/assets/licenses/cc-0.png',
+                       'icon' => '{$wgResourceBasePath}/resources/assets/licenses/cc-0.png',
                ),
                'pd' => array(
                        'url' => '',
-                       'icon' => '{$wgScriptPath}/assets/licenses/public-domain.png',
+                       'icon' => '{$wgResourceBasePath}/resources/assets/licenses/public-domain.png',
                ),
                'gfdl' => array(
                        'url' => 'http://www.gnu.org/copyleft/fdl.html',
-                       'icon' => '{$wgScriptPath}/assets/licenses/gnu-fdl.png',
+                       'icon' => '{$wgResourceBasePath}/resources/assets/licenses/gnu-fdl.png',
                ),
                'none' => array(
                        'url' => '',
@@ -1468,6 +1468,22 @@ abstract class Installer {
                return $exts;
        }
 
+       /**
+        * Returns a default value to be used for $wgDefaultSkin: the preferred skin, if available among
+        * the installed skins, or any other one otherwise.
+        *
+        * @param string[] $skinNames Names of installed skins.
+        * @return string
+        */
+       public function getDefaultSkin( array $skinNames ) {
+               $defaultSkin = $GLOBALS['wgDefaultSkin'];
+               if ( in_array( $defaultSkin, $skinNames ) ) {
+                       return $defaultSkin;
+               } else {
+                       return $skinNames[0];
+               }
+       }
+
        /**
         * Installs the auto-detected extensions.
         *
index 2a9c54c..2e31e41 100644 (file)
@@ -1037,7 +1037,7 @@ class WebInstallerOptions extends WebInstallerPage {
                                'var' => 'wgDefaultSkin',
                                'itemLabels' => array_fill_keys( $skinNames, 'config-skins-use-as-default' ),
                                'values' => $skinNames,
-                               'value' => $this->getVar( 'wgDefaultSkin', $this->getDefaultSkin( $skinNames ) ),
+                               'value' => $this->getVar( 'wgDefaultSkin', $this->parent->getDefaultSkin( $skinNames ) ),
                        ) );
 
                        foreach ( $skins as $skin ) {
@@ -1254,22 +1254,6 @@ class WebInstallerOptions extends WebInstallerPage {
                $this->addHTML( $this->getCCDoneBox() );
        }
 
-       /**
-        * Returns a default value to be used for $wgDefaultSkin: the preferred skin, if available among
-        * the installed skins, or any other one otherwise.
-        *
-        * @param string[] $skinNames Names of installed skins.
-        * @return string
-        */
-       public function getDefaultSkin( array $skinNames ) {
-               $defaultSkin = $GLOBALS['wgDefaultSkin'];
-               if ( in_array( $defaultSkin, $skinNames ) ) {
-                       return $defaultSkin;
-               } else {
-                       return $skinNames[0];
-               }
-       }
-
        /**
         * If the user skips this installer page, we still need to set up the default skins, but ignore
         * everything else.
@@ -1282,7 +1266,7 @@ class WebInstallerOptions extends WebInstallerPage {
 
                if ( $skins ) {
                        $skinNames = array_map( 'strtolower', $skins );
-                       $this->parent->setVar( 'wgDefaultSkin', $this->getDefaultSkin( $skinNames ) );
+                       $this->parent->setVar( 'wgDefaultSkin', $this->parent->getDefaultSkin( $skinNames ) );
                }
 
                return true;
index 7f353ec..028ef62 100644 (file)
@@ -1,5 +1,20 @@
 {
-       "@metadata": [],
+       "@metadata": {
+               "authors": [
+                       "Чаховіч Уладзіслаў"
+               ]
+       },
+       "config-desc": "Інсталятар MediaWiki",
+       "config-information": "Інфармацыя",
+       "config-localsettings-key": "Ключ абнаўлення:",
+       "config-your-language": "Ваша мова:",
+       "config-wiki-language": "Мова Вікі:",
+       "config-back": "← Назад",
+       "config-page-language": "Мова",
+       "config-page-welcome": "Сардэчна запрашаем у MediaWiki!",
+       "config-page-name": "Назва",
+       "config-page-options": "Настройкі",
+       "config-upload-settings": "Загрузка выяў і файлаў",
        "mainpagetext": "'''MediaWiki паспяхова ўсталяваная.'''",
        "mainpagedocfooter": "Гл. [//meta.wikimedia.org/wiki/Help:Contents Дапаможнік карыстальніка (англ.)] па далейшыя звесткі аб карыстанні вікі-праграмамі.\n\n== З чаго пачаць ==\n\n* [//www.mediawiki.org/wiki/Special:MyLanguage/Manual:Configuration_settings Пералік параметраў канфігурацыі (англ.)]\n* [//www.mediawiki.org/wiki/Special:MyLanguage/Manual:FAQ ЧАПЫ MediaWiki (англ.)]\n* [https://lists.wikimedia.org/mailman/listinfo/mediawiki-announce Ліставанне аб выпусках MediaWiki (англ.)]"
 }
index 0835f41..c40544d 100644 (file)
@@ -12,7 +12,8 @@
                        "아라",
                        "Elseweyr",
                        "Lliehu",
-                       "Syreeni"
+                       "Syreeni",
+                       "Stryn"
                ]
        },
        "config-desc": "MediaWiki-asennin",
@@ -56,6 +57,7 @@
        "config-env-good": "Asennusympäristö on tarkastettu.\nVoit asentaa MediaWikin.",
        "config-env-bad": "Asennusympäristö on tarkastettu.\nEt voi asentaa MediaWikiä.",
        "config-env-php": "PHP $1 on asennettu.",
+       "config-env-hhvm": "HHVM $1 on asennettu.",
        "config-no-db": "Sopivaa tietokanta-ajuria ei löytynyt! Sinun täytyy asentaa tietokanta-ajurit PHP:lle.\nSeuraavat tietokantatyypit ovat tuettuja: $1.",
        "config-outdated-sqlite": "<strong>Varoitus:</strong> sinulla on käytössä SQLite $1, joke on vanhempi kuin vähintään vaadittava versio $2. SQLite ei ole saatavilla.",
        "config-safe-mode": "'''Varoitus:''' PHP:n [http://www.php.net/features.safe-mode safe mode] -tila on aktiivinen.\nSe voi aiheuttaa ongelmia erityisesti tiedostojen tallentamisen ja matemaattisten kaavojen kanssa.",
index 9219c3a..8215403 100644 (file)
@@ -57,6 +57,57 @@ class EmailNotification {
         */
        protected $editor;
 
+       /**
+        * @param User $editor The editor that triggered the update.  Their notification
+        *  timestamp will not be updated(they have already seen it)
+        * @param Title $title The title to update timestamps for
+        * @param string $timestamp Set the upate timestamp to this value
+        * @return int[]
+        */
+       public static function updateWatchlistTimestamp( User $editor, Title $title, $timestamp ) {
+               global $wgEnotifWatchlist, $wgShowUpdatedMarker;
+
+               if ( !$wgEnotifWatchlist && !$wgShowUpdatedMarker ) {
+                       return array();
+               }
+
+               $dbw = wfGetDB( DB_MASTER );
+               $res = $dbw->select( array( 'watchlist' ),
+                       array( 'wl_user' ),
+                       array(
+                               'wl_user != ' . intval( $editor->getID() ),
+                               'wl_namespace' => $title->getNamespace(),
+                               'wl_title' => $title->getDBkey(),
+                               'wl_notificationtimestamp IS NULL',
+                       ), __METHOD__
+               );
+
+               $watchers = array();
+               foreach ( $res as $row ) {
+                       $watchers[] = intval( $row->wl_user );
+               }
+
+               if ( $watchers ) {
+                       // Update wl_notificationtimestamp for all watching users except the editor
+                       $fname = __METHOD__;
+                       $dbw->onTransactionIdle(
+                               function () use ( $dbw, $timestamp, $watchers, $title, $fname ) {
+                                       $dbw->update( 'watchlist',
+                                               array( /* SET */
+                                                       'wl_notificationtimestamp' => $dbw->timestamp( $timestamp )
+                                               ), array( /* WHERE */
+                                                       'wl_user' => $watchers,
+                                                       'wl_namespace' => $title->getNamespace(),
+                                                       'wl_title' => $title->getDBkey(),
+                                               ), $fname
+                                       );
+                               }
+                       );
+               }
+
+               return $watchers;
+       }
+
        /**
         * Send emails corresponding to the user $editor editing the page $title.
         * Also updates wl_notificationtimestamp.
@@ -74,47 +125,14 @@ class EmailNotification {
        public function notifyOnPageChange( $editor, $title, $timestamp, $summary,
                $minorEdit, $oldid = false, $pageStatus = 'changed'
        ) {
-               global $wgEnotifUseJobQ, $wgEnotifWatchlist, $wgShowUpdatedMarker, $wgEnotifMinorEdits,
-                      $wgUsersNotifiedOnAllChanges, $wgEnotifUserTalk;
+               global $wgEnotifUseJobQ, $wgEnotifMinorEdits, $wgUsersNotifiedOnAllChanges, $wgEnotifUserTalk;
 
                if ( $title->getNamespace() < 0 ) {
                        return;
                }
 
-               // Build a list of users to notify
-               $watchers = array();
-               if ( $wgEnotifWatchlist || $wgShowUpdatedMarker ) {
-                       $dbw = wfGetDB( DB_MASTER );
-                       $res = $dbw->select( array( 'watchlist' ),
-                               array( 'wl_user' ),
-                               array(
-                                       'wl_user != ' . intval( $editor->getID() ),
-                                       'wl_namespace' => $title->getNamespace(),
-                                       'wl_title' => $title->getDBkey(),
-                                       'wl_notificationtimestamp IS NULL',
-                               ), __METHOD__
-                       );
-                       foreach ( $res as $row ) {
-                               $watchers[] = intval( $row->wl_user );
-                       }
-                       if ( $watchers ) {
-                               // Update wl_notificationtimestamp for all watching users except the editor
-                               $fname = __METHOD__;
-                               $dbw->onTransactionIdle(
-                                       function () use ( $dbw, $timestamp, $watchers, $title, $fname ) {
-                                               $dbw->update( 'watchlist',
-                                                       array( /* SET */
-                                                               'wl_notificationtimestamp' => $dbw->timestamp( $timestamp )
-                                                       ), array( /* WHERE */
-                                                               'wl_user' => $watchers,
-                                                               'wl_namespace' => $title->getNamespace(),
-                                                               'wl_title' => $title->getDBkey(),
-                                                       ), $fname
-                                               );
-                                       }
-                               );
-                       }
-               }
+               // update wl_notificationtimestamp for watchers
+               $watchers = self::updateWatchlistTimestamp( $editor, $title, $timestamp );
 
                $sendEmail = true;
                // If nobody is watching the page, and there are no users notified on all changes
index 13fb52b..3e3be3d 100644 (file)
@@ -163,8 +163,14 @@ abstract class TransformationalImageHandler extends ImageHandler {
                # Determine scaler type
                $scaler = $this->getScalerType( $dstPath );
 
+               if ( is_array( $scaler ) ) {
+                       $scalerName = get_class( $scaler[0] );
+               } else {
+                       $scalerName = $scaler;
+               }
+
                wfDebug( __METHOD__ . ": creating {$scalerParams['physicalDimensions']} " .
-                       "thumbnail at $dstPath using scaler $scaler\n" );
+                       "thumbnail at $dstPath using scaler $scalerName\n" );
 
                if ( !$image->mustRender() &&
                        $scalerParams['physicalWidth'] == $scalerParams['srcWidth']
@@ -571,7 +577,7 @@ abstract class TransformationalImageHandler extends ImageHandler {
         */
        public function rotate( $file, $params ) {
                return new MediaTransformError( 'thumbnail_error', 0, 0,
-                       "$scaler rotation not implemented" );
+                       get_class( $this ) . ' rotation not implemented' );
        }
 
        /**
index 2ca9d50..7e4059b 100644 (file)
@@ -211,6 +211,13 @@ class ParserOptions {
         */
        protected $onAccessCallback = null;
 
+       /**
+        * If the page being parsed is a redirect, this should hold the redirect
+        * target.
+        * @var Title|null
+        */
+       private $redirectTarget = null;
+
        public function getInterwikiMagic() {
                return $this->mInterwikiMagic;
        }
@@ -515,6 +522,30 @@ class ParserOptions {
                return wfSetVar( $this->mIsPrintable, $x );
        }
 
+       /**
+        * Set the redirect target.
+        *
+        * Note that setting or changing this does not *make* the page a redirect
+        * or change its target, it merely records the information for reference
+        * during the parse.
+        *
+        * @since 1.24
+        * @param Title|null $title
+        */
+       function setRedirectTarget( $title ) {
+               $this->redirectTarget = $title;
+       }
+
+       /**
+        * Get the previously-set redirect target.
+        *
+        * @since 1.24
+        * @return Title|null
+        */
+       function getRedirectTarget() {
+               return $this->redirectTarget;
+       }
+
        /**
         * Extra key that should be present in the parser cache key.
         * @param string $key
index 38a6436..7ef0ad0 100644 (file)
@@ -58,7 +58,7 @@ class ProfilerSimpleDB extends ProfilerStandard {
                        $dbw = wfGetDB( DB_MASTER );
                        $useTrx = ( $dbw->getType() === 'sqlite' ); // much faster
                        if ( $useTrx ) {
-                               $dbw->begin();
+                               $dbw->startAtomic( __METHOD__ );
                        }
                        foreach ( $this->mCollated as $name => $data ) {
                                $eventCount = $data['count'];
@@ -103,7 +103,7 @@ class ProfilerSimpleDB extends ProfilerStandard {
                                //     "pf_time=pf_time + VALUES(pf_time)";
                        }
                        if ( $useTrx ) {
-                               $dbw->commit();
+                               $dbw->endAtomic( __METHOD__ );
                        }
                } catch ( DBError $e ) {
                }
index fee78d1..137ff62 100644 (file)
@@ -168,7 +168,7 @@ class ResourceLoaderFileModule extends ResourceLoaderModule {
         * @param string $localBasePath Base path to prepend to all local paths in $options. Defaults
         *     to $IP
         * @param string $remoteBasePath Base path to prepend to all remote paths in $options. Defaults
-        *     to $wgScriptPath
+        *     to $wgResourceBasePath
         *
         * Below is a description for the $options array:
         * @throws MWException
@@ -177,7 +177,7 @@ class ResourceLoaderFileModule extends ResourceLoaderModule {
         *     array(
         *         // Base path to prepend to all local paths in $options. Defaults to $IP
         *         'localBasePath' => [base path],
-        *         // Base path to prepend to all remote paths in $options. Defaults to $wgScriptPath
+        *         // Base path to prepend to all remote paths in $options. Defaults to $wgResourceBasePath
         *         'remoteBasePath' => [base path],
         *         // Equivalent of remoteBasePath, but relative to $wgExtensionAssetsPath
         *         'remoteExtPath' => [base path],
@@ -291,7 +291,7 @@ class ResourceLoaderFileModule extends ResourceLoaderModule {
         * @param string $localBasePath Path to use if not provided in module definition. Defaults
         *     to $IP
         * @param string $remoteBasePath Path to use if not provided in module definition. Defaults
-        *     to $wgScriptPath
+        *     to $wgResourceBasePath
         * @return array Array( localBasePath, remoteBasePath )
         */
        public static function extractBasePaths(
@@ -299,14 +299,14 @@ class ResourceLoaderFileModule extends ResourceLoaderModule {
                $localBasePath = null,
                $remoteBasePath = null
        ) {
-               global $IP, $wgScriptPath, $wgResourceBasePath;
+               global $IP, $wgResourceBasePath;
 
                // The different ways these checks are done, and their ordering, look very silly,
                // but were preserved for backwards-compatibility just in case. Tread lightly.
 
                $localBasePath = $localBasePath === null ? $IP : $localBasePath;
                if ( $remoteBasePath === null ) {
-                       $remoteBasePath = $wgResourceBasePath === null ? $wgScriptPath : $wgResourceBasePath;
+                       $remoteBasePath = $wgResourceBasePath;
                }
 
                if ( isset( $options['remoteExtPath'] ) ) {
index 944e9e2..d133468 100644 (file)
@@ -392,18 +392,10 @@ class SiteSQLStore implements SiteStore {
                wfProfileIn( __METHOD__ );
                $dbw = $this->sitesTable->getWriteDbConnection();
 
-               $trx = $dbw->trxLevel();
-
-               if ( $trx == 0 ) {
-                       $dbw->begin( __METHOD__ );
-               }
-
+               $dbw->startAtomic( __METHOD__ );
                $ok = $dbw->delete( 'sites', '*', __METHOD__ );
                $ok = $dbw->delete( 'site_identifiers', '*', __METHOD__ ) && $ok;
-
-               if ( $trx == 0 ) {
-                       $dbw->commit( __METHOD__ );
-               }
+               $dbw->endAtomic( __METHOD__);
 
                $this->reset();
 
index 7cabf50..2f6a710 100644 (file)
@@ -827,9 +827,9 @@ abstract class Skin extends ContextSource {
         * @return string
         */
        function getPoweredBy() {
-               global $wgScriptPath;
+               global $wgResourceBasePath;
 
-               $url = htmlspecialchars( "$wgScriptPath/assets/poweredby_mediawiki_88x31.png" );
+               $url = htmlspecialchars( "$wgResourceBasePath/resources/assets/poweredby_mediawiki_88x31.png" );
                $text = '<a href="//www.mediawiki.org/"><img src="' . $url
                        . '" height="31" width="88" alt="Powered by MediaWiki" /></a>';
                wfRunHooks( 'SkinGetPoweredBy', array( &$text, $this ) );
index 0138cf9..e0737a0 100644 (file)
@@ -176,11 +176,43 @@ class SpecialPageFactory {
        private static $aliases;
 
        /**
-        * Get the special page list
+        * Reset the internal list of special pages. Useful when changing $wgSpecialPages after
+        * the internal list has already been initialized, e.g. during testing.
+        */
+       public static function resetList() {
+               self::$list = null;
+               self::$aliases = null;
+       }
+
+       /**
+        * Returns a list of canonical special page names.
+        * May be used to iterate over all registered special pages.
+        *
+        * @return string[]
+        */
+       public static function getNames() {
+               return array_keys( get_object_vars( self::getListObject() ) );
+       }
+
+       /**
+        * Get the special page list as an object, with each special page represented by a member
+        * field in the object.
         *
-        * @return array
+        * @deprecated since 1.24, use getNames() instead.
+        * @return object
         */
-       static function getList() {
+       public static function getList() {
+               wfDeprecated( __FUNCTION__, '1.24' );
+               return self::getListObject();
+       }
+
+       /**
+        * Get the special page list as an object, with each special page represented by a member
+        * field in the object.
+        *
+        * @return object
+        */
+       private static function getListObject() {
                global $wgSpecialPages;
                global $wgDisableCounters, $wgDisableInternalSearch, $wgEmailAuthentication;
                global $wgEnableEmail, $wgEnableJavaScriptTest;
@@ -223,6 +255,8 @@ class SpecialPageFactory {
                        // This hook can be used to remove undesired built-in special pages
                        wfRunHooks( 'SpecialPage_initList', array( &self::$list ) );
 
+                       self::$list = (object)self::$list;
+
                        wfProfileOut( __METHOD__ );
                }
 
@@ -237,12 +271,13 @@ class SpecialPageFactory {
         * contain at least one entry (English fallbacks will be added if necessary).
         * @return object
         */
-       static function getAliasList() {
+       private static function getAliasListObject() {
                if ( !is_object( self::$aliases ) ) {
                        global $wgContLang;
                        $aliases = $wgContLang->getSpecialPageAliases();
 
-                       $missingPages = self::getList();
+                       // Objects are passed by reference by default, need to create a copy
+                       $missingPages = clone self::getListObject();
 
                        self::$aliases = array();
                        // Check for $aliases being an array since Language::getSpecialPageAliases can return null
@@ -279,8 +314,8 @@ class SpecialPageFactory {
 
                $caseFoldedAlias = $wgContLang->caseFold( $bits[0] );
                $caseFoldedAlias = str_replace( ' ', '_', $caseFoldedAlias );
-               if ( isset( self::getAliasList()->$caseFoldedAlias ) ) {
-                       $name = self::getAliasList()->$caseFoldedAlias;
+               if ( isset( self::getAliasListObject()->$caseFoldedAlias ) ) {
+                       $name = self::getAliasListObject()->$caseFoldedAlias;
                } else {
                        return array( null, null );
                }
@@ -331,8 +366,7 @@ class SpecialPageFactory {
        public static function exists( $name ) {
                list( $title, /*...*/ ) = self::resolveAlias( $name );
 
-               $specialPageList = self::getList();
-               return isset( $specialPageList[$title] );
+               return property_exists( self::getListObject(), $title );
        }
 
        /**
@@ -343,22 +377,36 @@ class SpecialPageFactory {
         */
        public static function getPage( $name ) {
                list( $realName, /*...*/ ) = self::resolveAlias( $name );
-               $specialPageList = self::getList();
-               if ( isset( $specialPageList[$realName] ) ) {
-                       $rec = $specialPageList[$realName];
+               if ( property_exists( self::getListObject(), $realName ) ) {
+                       $rec = self::getListObject()->$realName;
+
                        if ( is_string( $rec ) ) {
                                $className = $rec;
-
-                               return new $className;
+                               $page = new $className;
+                       } elseif ( is_callable( $rec ) ) {
+                               // Use callback to instantiate the special page
+                               $page = call_user_func( $rec );
                        } elseif ( is_array( $rec ) ) {
                                $className = array_shift( $rec );
                                // @deprecated, officially since 1.18, unofficially since forever
                                wfDeprecated( "Array syntax for \$wgSpecialPages is deprecated ($className), " .
                                        "define a subclass of SpecialPage instead.", '1.18' );
-                               $specialPageList[$realName] = MWFunction::newObj( $className, $rec );
+                               $page = MWFunction::newObj( $className, $rec );
+                       } elseif ( $rec instanceof SpecialPage ) {
+                               $page = $rec; //XXX: we should deep clone here
+                       } else {
+                               $page = null;
+                       }
+
+                       if ( $page instanceof SpecialPage ) {
+                               return $page;
+                       } else {
+                               // It's not a classname, nor a callback, nor a legacy constructor array,
+                               // nor a special page object. Give up.
+                               wfLogWarning( "Cannot instantiate special page $realName: bad spec!" );
+                               return null;
                        }
 
-                       return $specialPageList[$realName];
                } else {
                        return null;
                }
@@ -378,7 +426,7 @@ class SpecialPageFactory {
                        global $wgUser;
                        $user = $wgUser;
                }
-               foreach ( self::getList() as $name => $rec ) {
+               foreach ( self::getListObject() as $name => $rec ) {
                        $page = self::getPage( $name );
                        if ( $page ) { // not null
                                $page->setContext( RequestContext::getMain() );
@@ -400,7 +448,7 @@ class SpecialPageFactory {
         */
        public static function getRegularPages() {
                $pages = array();
-               foreach ( self::getList() as $name => $rec ) {
+               foreach ( self::getListObject() as $name => $rec ) {
                        $page = self::getPage( $name );
                        if ( $page->isListed() && !$page->isRestricted() ) {
                                $pages[$name] = $page;
@@ -423,7 +471,7 @@ class SpecialPageFactory {
                        global $wgUser;
                        $user = $wgUser;
                }
-               foreach ( self::getList() as $name => $rec ) {
+               foreach ( self::getListObject() as $name => $rec ) {
                        $page = self::getPage( $name );
                        if (
                                $page->isListed()
@@ -532,7 +580,7 @@ class SpecialPageFactory {
         * @param IContextSource $context
         * @return string HTML fragment
         */
-       static function capturePath( Title $title, IContextSource $context ) {
+       public static function capturePath( Title $title, IContextSource $context ) {
                global $wgOut, $wgTitle, $wgRequest, $wgUser, $wgLang;
 
                // Save current globals
@@ -569,7 +617,7 @@ class SpecialPageFactory {
         * @param string|bool $subpage
         * @return string
         */
-       static function getLocalNameFor( $name, $subpage = false ) {
+       public static function getLocalNameFor( $name, $subpage = false ) {
                global $wgContLang;
                $aliases = $wgContLang->getSpecialPageAliases();
 
@@ -608,7 +656,7 @@ class SpecialPageFactory {
         * @param string $alias
         * @return Title|null Title or null if there is no such alias
         */
-       static function getTitleForAlias( $alias ) {
+       public static function getTitleForAlias( $alias ) {
                list( $name, $subpage ) = self::resolveAlias( $alias );
                if ( $name != null ) {
                        return SpecialPage::getTitleFor( $name, $subpage );
index a3b02f5..e0be838 100644 (file)
@@ -107,13 +107,11 @@ class SpecialChangeEmail extends FormSpecialPage {
        }
 
        protected function alterForm( HTMLForm $form ) {
+               $form->setDisplayFormat( 'vform' );
                $form->setId( 'mw-changeemail-form' );
                $form->setTableId( 'mw-changeemail-table' );
-               $form->setWrapperLegendMsg( 'changeemail-header' );
+               $form->setWrapperLegend( false );
                $form->setSubmitTextMsg( 'changeemail-submit' );
-               $form->addButton( 'wpCancel', $this->msg( 'changeemail-cancel' )->text(),
-                       null, array( 'formnovalidate')
-               );
                $form->addHiddenField( 'returnto', $this->getRequest()->getVal( 'returnto' ) );
        }
 
index 4cfd445..cea00fa 100644 (file)
@@ -73,6 +73,7 @@ class SpecialPreferences extends SpecialPage {
                $htmlForm = new HTMLForm( array(), $context, 'prefs-restore' );
 
                $htmlForm->setSubmitTextMsg( 'restoreprefs' );
+               $htmlForm->setSubmitDestructive();
                $htmlForm->setSubmitCallback( array( $this, 'submitReset' ) );
                $htmlForm->suppressReset();
 
index 17d7664..e6d8f1c 100644 (file)
@@ -732,7 +732,7 @@ class SpecialRecentChanges extends ChangesListSpecialPage {
 
                        $link = $this->makeOptionsLink( $linkMessage->text(),
                                array( $key => 1 - $options[$key] ), $nondefaults );
-                       $links[] = $this->msg( $msg )->rawParams( $link )->escaped();
+                       $links[] = "<span class=\"$msg rcshowhideoption\">" . $this->msg( $msg )->rawParams( $link )->escaped() . '</span>';
                }
 
                // show from this onward link
@@ -740,13 +740,16 @@ class SpecialRecentChanges extends ChangesListSpecialPage {
                $now = $lang->userTimeAndDate( $timestamp, $user );
                $timenow = $lang->userTime( $timestamp, $user );
                $datenow = $lang->userDate( $timestamp, $user );
-               $rclinks = $this->msg( 'rclinks' )->rawParams( $cl, $dl, $lang->pipeList( $links ) )
-                       ->parse();
-               $rclistfrom = $this->makeOptionsLink(
+               $pipedLinks = '<span class="rcshowhide">' . $lang->pipeList( $links ) . '</span>';
+
+               $rclinks = '<span class="rclinks">' . $this->msg( 'rclinks' )->rawParams( $cl, $dl, $pipedLinks )
+                       ->parse() . '</span>';
+
+               $rclistfrom = '<span class="rclistfrom">' . $this->makeOptionsLink(
                        $this->msg( 'rclistfrom' )->rawParams( $now, $timenow, $datenow )->parse(),
                        array( 'from' => $timestamp ),
                        $nondefaults
-               );
+               ) . '</span>';
 
                return "{$note}$rclinks<br />$rclistfrom";
        }
index 0f9a6ba..5b88dfd 100644 (file)
@@ -72,7 +72,7 @@ if ( !function_exists( 'session_name' ) ) {
                </style>
        </head>
        <body>
-               <img src="<?php echo htmlspecialchars( $path ) ?>assets/mediawiki.png" alt='The MediaWiki logo' />
+               <img src="<?php echo htmlspecialchars( $path ) ?>resources/assets/mediawiki.png" alt='The MediaWiki logo' />
 
                <h1>MediaWiki <?php echo htmlspecialchars( $wgVersion ) ?></h1>
                <div class='error'>
index 667c5df..b246e89 100644 (file)
        "protect-othertime": "Іншы тэрмін:",
        "protect-othertime-op": "іншы тэрмін",
        "protect-existing-expiry": "Наяўны час сканчэньня: $3, $2",
+       "protect-existing-expiry-infinity": "Наяўны тэрмін сканчэньня: бясконца",
        "protect-otherreason": "Іншая/дадатковая прычына:",
        "protect-otherreason-op": "Іншая прычына",
        "protect-dropdown": "*Звычайныя прычыны абароны\n** Часты вандалізм\n** Празьмерны спам\n** Непрадуктыўная вайна рэдагаваньняў\n** Папулярная старонка",
index fd2d3c4..2da49f9 100644 (file)
        "otherlanguages": "На іншых мовах",
        "redirectedfrom": "(Пасля перасылкі з $1)",
        "redirectpagesub": "Старонка-перасылка",
+       "redirectto": "Перасылае да",
        "lastmodifiedat": "Апошняе змяненне старонкі адбылося $2, $1.",
        "viewcount": "Гэту старонку адкрывалі {{PLURAL:$1|адзін раз|$1 разы|$1 разоў}}.",
        "protectedpage": "Старонка пад аховай",
        "searchall": "усе",
        "showingresults": "Ніжэй паказаны да {{PLURAL:$1|'''$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": "Падрабязны пошук",
        "powersearch-ns": "Шукаць у прасторах назваў:",
index 97c7482..6890b24 100644 (file)
        "viewtalkpage": "Хьажа дийцаре",
        "otherlanguages": "Кхечу маттахь дерш",
        "redirectedfrom": "(ДӀасахьажийна кху $1)",
-       "redirectpagesub": "Ð\90гÓ\80о-дÓ\80аÑ\81аÑ\85Ñ\8cажайаÑ\80",
+       "redirectpagesub": "Ð\90гÓ\80о-дÓ\80аÑ\81аÑ\85Ñ\8cажоÑ\80г",
        "redirectto": "ДӀасахьажор тӀе:",
        "lastmodifiedat": "ХӀокху агӀон тӀаьххьаралера хийцам: $2, $1.",
        "viewcount": "ХӀокху агӀонг хьовсийна $1 {{PLURAL:$1|за}}.",
        "right-createtalk": "Дийцаре агӀонаш кхоллар",
        "right-createaccount": "декъашхошна керла дӀаяздарш кхоллар",
        "right-minoredit": "«къезиг хийцам» аьлла билгало хӀоттор",
-       "right-move": "Ð\90гÓ\80онаÑ\88ан цӀераш хийцар",
+       "right-move": "Ð\90гÓ\80онийн цӀераш хийцар",
        "right-move-subpages": "АгӀонашан цӀераш хийцар цера бухара агӀонашцан",
        "right-move-rootuserpages": "декъашхочун ораман агӀонийн цӀераш хийцар",
        "right-move-categorypages": "Категорийн агӀонийн цӀераш хийцар",
        "right-movefile": "Файлийн цӀе хийцар",
-       "right-suppressredirect": "агÓ\80она Ñ\86Ó\80е Ñ\85Ñ\83Ñ\8cйÑ\86Ñ\83Ñ\88 Ñ\88иÑ\80Ñ\87Ñ\83 Ñ\86Ó\80аÑ\80аÑ\85 Ð¼Ð° ÐºÑ\85олла Ð´Ó\80аÑ\81аÑ\85Ñ\8cажаÑ\8fÑ\80",
+       "right-suppressredirect": "агÓ\80она Ñ\86Ó\80е Ñ\85Ñ\83Ñ\8cйÑ\86Ñ\83Ñ\88 Ñ\88иÑ\80Ñ\87Ñ\83 Ñ\86Ó\80аÑ\80аÑ\85 Ð¼Ð° ÐºÑ\85олла Ð´Ó\80аÑ\81аÑ\85Ñ\8cажоÑ\80г",
        "right-upload": "Файлаш чуйаьхар",
        "right-reupload": "йолуш йолу чера тӀехула файлаш дӀаязъяр",
        "right-reupload-own": "тохарлеррачу декъашхочо файлаш юху дӀаязъяр",
        "deletecomment": "Бахьна:",
        "deleteotherreason": "Кхин бахьна/тӀетохар:",
        "deletereasonotherlist": "Кхин бахьна",
-       "deletereason-dropdown": "* Даржина долу дӀаяккхаран баьхьанаш \n** зулма  \n** авторан лаамца\n** авторан бакъонаш талхор",
+       "deletereason-dropdown": "* Даржина долу дӀаяккхаран баьхьанаш \n** спам\n** зулма  \n** авторан лаамца\n** авторан бакъонаш талхор\n** болх цабо дӀасхьажорг",
        "delete-edit-reasonlist": "Бахьанин могӀам нисбар",
        "deleting-backlinks-warning": "'''ДӀахьедар:''' Ахьа дӀайоккхуш йолчун тӀе товжийна [[Special:WhatLinksHere/{{FULLPAGENAME}}|кхин агӀонаш]] ю.",
        "rollback": "Юхабаккха хийцам",
        "linkshere": "ТӀаьхьайогӀу агӀонаш оцу '''[[:$1]]''': хьажорагца ю",
        "nolinkshere": "ХӀокху '''[[:$1]]''' агӀона тӀе кхечу агӀонашкахь хьажоргаш яц.",
        "nolinkshere-ns": "Хаьржинчу анахь яц '''[[:$1]]''' цӀе йолу агӀонаш",
-       "isredirect": "агÓ\80о-дÓ\80аÑ\81аÑ\85Ñ\8cажайаÑ\80",
+       "isredirect": "агÓ\80о-дÓ\80аÑ\81аÑ\85Ñ\8cажоÑ\80г",
        "istemplate": "юкъаялийнарш",
        "isimage": "Файлан хьажораг",
        "whatlinkshere-prev": "{{PLURAL:$1|1=хьалхайодарг|хьалхайодарш}} $1",
        "movepagetext": "Бухахь йолу форманца агӀон цӀе хийцало. Цул совнах цуьна хийцаман тептар кхоьчу метте доккха. Хьалхалера цӀарахь хиръю керла кхоьллина агӀонан хьажораг.\n\nХьовсалаш [[Special:DoubleRedirects|шалха]] а [[Special:BrokenRedirects|йохна хьажоргаш]] юй техь аьлла.\n\nШу жоьпехь ду хьажоргаш нийса некъ гойтуш хиларан.\n\nТидам бе хьалхалера агӀон цӀе ‘’’хийцалур яц’’’ иштта цӀе йолу агӀо йолуш елахь. Юкъардаккхар: йолуш йолу агӀо кхоьчухьа хьажораг елахь, я еса елахь а, цуьна хийцаме истори яцахь а.\n\nИ бохург ду шун агӀонан цӀе юха а хьалха хилларгчунтӀе хийца йиш ю, амма йолуш йолу агӀо дӀаяккха йиш яц.\n\n'''ДӀАХЬЕДАР!'''\n\nЦӀе хийцар бахьнехь гӀаръяьлла агӀонашна дукха дагахь боцу хийцамаш хила тарло. Цундела цӀе хийцале шеш хила тарлучу тӀехьонашах кхета аьлла тешна хила.",
        "movepagetext-noredirectfixer": "Бухахь йолу форманца агӀон цӀе хийцало. Цул совнах цуьна хийцаман тептар кхоьчу метте доккха. Хьалхалера цӀарахь хиръю керла кхоьллина агӀонан хьажораг.\n\nХьовсалаш [[Special:DoubleRedirects|шалха]] а [[Special:BrokenRedirects|йохна хьажоргаш]] юй техь аьлла.\n\nШу жоьпехь ду хьажоргаш нийса некъ гойтуш хиларан.\n\nТидам бе хьалхалера агӀон цӀе ‘’’хийцалур яц’’’ иштта цӀе йолу агӀо йолуш елахь. Юкъардаккхар: йолуш йолу агӀо кхоьчухьа хьажораг елахь, я еса елахь а, цуьна хийцаме истори яцахь а.\n\nИ бохург ду шун агӀонан цӀе юха а хьалха хилларгчунтӀе хийца йиш ю, амма йолуш йолу агӀо дӀаяккха йиш яц.\n\n'''ДӀАХЬЕДАР!'''\n\nЦӀе хийцар бахьнехь гӀаръяьлла агӀонашна дукха дагахь боцу хийцамаш хила тарло. Цундела цӀе хийцале шеш хила тарлучу тӀехьонашах кхета аьлла тешна хила.",
        "movepagetalktext": "ТӀе хӀоьттина йолу дийцаре агӀо ишта цӀе хийцина хира ю, '''цхьа йолу ханчохь, маца:'''\n\n*Йаьсса йоцу дийцаре агӀо йолуш ю оцу цӀарца йа\n*Ахьа къастаман харжам цабиняхь а къастам хӀотточехь.\n\nИшта чу ханчохь, ахьа дехьа яккха йезар ю йа куьйга хӀоттайар, нагахь иза хьашт йалахь.",
-       "movearticle": "Цle хийца хlокху агlон",
+       "movearticle": "ЦӀе хийца хӀокху агӀон",
        "moveuserpage-warning": "'''Тергам бе.''' Хьо декъашхочун агӀона цӀе хийца гӀерта. Дехар до, тергам бе, декъашхочун агӀона цӀе бен хийца лур яц, декъашхочун дӀаяздаран цӀе хийца лур яц.",
        "movecategorypage-warning": "<strong>ДӀахьедар:</strong> Хьо категорин агӀон цӀе хийца гӀерта. Дехар до, терго йе, хӀокху агӀона бен цӀе хуьйцур яц, шира чу категори чура массо агӀонаш керла категори чу йохур <em>яц</em>.",
        "movenologintext": "АгӀона цӀе хийца [[Special:UserLogin|системин чугӀо]].",
        "movepage-moved-noredirect": "ДӀасхьажорг кхоллар дохина.",
        "articleexists": "ХӀарасанна цӀе йолу агӀо йолуш ю йа ахьа гойтуш йолу цӀе магош яц.\nДехар до, харжа кхин цӀе.",
        "movetalk": "Цуьнца йогӀуш йолу дийцаре агӀон цӀе хийцар",
-       "move-subpages": "ЦӀeрш хийцае бухара агӀонаши ($1 кхаччалц)",
+       "move-subpages": "ЦӀераш хийца бухара агӀонийн ($1 кхаччалц)",
        "move-talk-subpages": "ЦӀе хийца бухара агӀонаши а агӀонашан дийцаре а ($1  кхаччалц)",
        "movepage-page-exists": "Агӏо $1 йолуш ю цундела и ша юху дӏаязъян йиш яц.",
        "movepage-page-moved": "АгӀона $1 цӀе хийцина → $2.",
index 327d973..981a32c 100644 (file)
        "resetpass-submit-cancel": "ھەڵوەشاندنەوە",
        "resetpass-wrong-oldpass": "تێپەڕوشەی ھەنووکەیی یان تێپەڕوشەی کاتی ھەڵەیە.\nوا دیارە تێپەڕوشەکەت بە سەرکەوتوویی گۆڕدراوە یان داوای تێپەڕوشەیەکی نوێت کردووە.",
        "resetpass-temp-password": "تێپەڕوشەی کاتی:",
-       "passwordreset": "دووبارە ڕێکخستنەوەی تێپەڕوشە",
+       "passwordreset": "ڕێکخستنەوەی تێپەڕوشە",
        "passwordreset-legend": "دووبارە ڕێکخستنەوەی تێپەڕوشە",
        "passwordreset-username": "ناوی بەکارھێنەری:",
        "passwordreset-domain": "پاوان:",
        "passwordreset-emailsent": "ئیمەیلێکی ڕیسێتکردنەوەی تێپەڕوشە نێردرا.",
        "passwordreset-emailsent-capture": "ئیمەیلێکی ڕیسێتکردنەوەی تێپەڕوشە نێردرا، کە لە ژێرەوە نیشان دراوە.",
        "passwordreset-emailerror-capture": "ئیمەیلێکی ڕیسێتکردنەوەی تێپەڕوشە نێردرا، کە لە ژێرەوە نیشان دراوە، بەڵام ناردنەکەی بۆ {{GENDER:$2|بەکارھێنەر}} سەرکەوتوو نەبوو: $1",
-       "changeemail": "ناونیشانی ئیمەیل بگۆڕە",
+       "changeemail": "گۆڕینی ناونیشانی ئیمەیل",
        "changeemail-header": "ناونیشانی ئیمەیلی ھەژمار بگۆڕە",
        "changeemail-no-info": "بۆ گەیشتنی راستەوخۆ بەم پەڕە دەبێت بچیتە ژوورەوە.",
        "changeemail-oldemail": "ئەدرەسی ئیمەیڵی ئێستا:",
        "mimesearch-summary": "ئەم لاپەڕە پاڵێوتنی هەیە بۆ جۆرەکانی MIME.\nناودراو: جۆرەی ناوەڕۆک\\ژێرجۆرە، وەک <code>image/jpeg</code>.",
        "mimetype": "جۆرەی MIME:",
        "download": "داگرتن",
-       "unwatchedpages": "پەڕە چاودێرینەکراوەکان",
+       "unwatchedpages": "پەڕە چاودێری نەکراوەکان",
        "listredirects": "پێرستی ڕەوانەکەرەکان",
-       "unusedtemplates": "داڕێژە بەکارنەھێنراوەکان",
+       "unusedtemplates": "داڕێژە بەکارنەھاتووەکان",
        "unusedtemplatestext": "ئەم پەڕە هەموو پەڕەکانی بۆشاییی ناوی {{ns:template}} بە لیست دەکات کە لە پەڕەی تردا بەکارنەھێنراون.\nلە بیری نەکەی پێش سڕینەوەیان پشکنینی بەستەرەکانی تر بۆ داڕێژەکان بکەی.",
        "unusedtemplateswlh": "بەستەرەکانی تر",
        "randompage": "پەڕەی ھەڕەمەکی",
        "withoutinterwiki-summary": "ئەم پەڕانە بەستەریان بۆ وەشانەکانی زمانەکانی تر نیە.",
        "withoutinterwiki-legend": "پێشگر",
        "withoutinterwiki-submit": "پیشاندان",
-       "fewestrevisions": "پەڕەکان بە کەمترین پێداچوونەوەکان",
+       "fewestrevisions": "پەڕەکان بە کەمترین پێداچوونەوە",
        "nbytes": "$1 {{PLURAL:$1|بایت|بایت}}",
        "ncategories": "$1 {{PLURAL:$1|ھاوپۆل|ھاوپۆل}}",
        "ninterwikis": "$1 {{PLURAL:$1|نێوانویکی}}",
        "uncategorizedimages": "پەڕگە پۆلێن نەکراوەکان",
        "uncategorizedtemplates": "داڕێژە پۆلێن نەکراوەکان",
        "unusedcategories": "پۆلە بەکارنەھێنراوەکان",
-       "unusedimages": "پەڕگە بەکارنەھێنراوەکان",
+       "unusedimages": "پەڕگە بەکارنەھاتووەکان",
        "popularpages": "پەڕە مەحبووبەکان",
        "wantedcategories": "پۆلە داواکراوەکان",
        "wantedpages": "پەڕە داواکراوەکان",
        "protectedpages-page": "پەڕە",
        "protectedpages-params": "پارامەترەکانی پاراستن",
        "protectedpages-reason": "ھۆکار",
-       "protectedtitles": "سەرناوە پارێزراوەکان",
+       "protectedtitles": "سەردێڕە پارێزراوەکان",
        "protectedtitlesempty": "ھیچ سەرناوێک بەم سنوورانەوە ئێستا نەپارێزراوە.",
        "listusers": "پێرستی بەکارھێنەران",
        "listusers-editsonly": "تەنیا ئەو بەکارھێنەرانە نیشان بدە کە دەستکارییان کردووە",
        "listusers-submit": "نیشانیبدە",
        "listusers-noresult": "ھیچ بەکارھێنەرێک نەدۆزرایەوە.",
        "listusers-blocked": "(بەربەست کراوە)",
-       "activeusers": "پێرستی بەکارھێنەرە چالاکەکان",
+       "activeusers": "پێرستی بەکارھێنەرانی چالاک",
        "activeusers-intro": "ئەمە لیستێکی ئەو بەکارھێنەرانەیە کە لە  $1 {{PLURAL:$1|ڕۆژ|ڕۆژ}}ی ڕابردوودا بە جۆرێک چالاکییەکیان ھەبووە.",
        "activeusers-count": "$1 {{PLURAL:$1|کردەوە}} لە دوایین {{PLURAL:$3|ڕۆژ|$3 ڕۆژ}}دا",
        "activeusers-from": "نیشاندانی بەکارھێنەران بە دەستپێکردن لە:",
        "listgrouprights-namespaceprotection-header": "سنوورداریی بۆشایی ناو",
        "listgrouprights-namespaceprotection-namespace": "بۆشایی ناو",
        "listgrouprights-namespaceprotection-restrictedto": "مافی رێ‌پێدراوی بەکارھێنەر بۆ دەستکاری",
+       "trackingcategories": "پۆلەکانی شوێنکەوتن",
        "trackingcategories-name": "ناوی پەیام",
        "mailnologin": "ناونیشان بۆ ناردن نییه‌",
        "mailnologintext": "ده‌بێ له‌ [[Special:UserLogin|ژووره‌وه‌]] بیت و ناونیشانێکی بڕواپێ‌کراوی ئی‌مه‌یلت له‌ ناو [[Special:Preferences|هه‌ڵبژارده‌کان]] دیاری کردبێت تا بتوانی ئی‌مه‌یل بنێریت بۆ به‌کارهێنه‌رانی دیکه‌.",
        "whatlinkshere-hidelinks": "$1 بەستەر",
        "whatlinkshere-hideimages": "$1 بەستەرەکانی پەڕگە",
        "whatlinkshere-filters": "پاڵێوکەکان",
-       "block": "بەربەستکردنی بەکارھێنەر",
+       "block": "بەربەستنی بەکارھێنەر",
        "unblock": "لە بەربەست‌دەرهێنانی بەکارهێنەر",
        "blockip": "بەربەستنی بەکارھێنەر",
        "blockip-legend": "بەربەست‌کردنی بەکارهێنەر",
        "ipusubmit": "لابردنی ئەم بەربەستە",
        "unblocked": "[[User:$1|$1]] لە بەربەست دەرهێنرا",
        "unblocked-id": "بەربەستی $1 لابرا",
-       "blocklist": "بەکارھێنەر بەربەستکراوەکان",
+       "blocklist": "بەکارھێنەرانی بەربەسراو",
        "ipblocklist": "بەکارھێنەرە بەربەستکراوەکان",
        "ipblocklist-legend": "دۆزینەوەی بەکارهێنەرێکی بەربەست‌کراو",
        "blocklist-userblocks": "ھەژمارە بەربەستکراوەکان بشارەوە",
        "version-software-version": "وەشان",
        "version-entrypoints-header-url": "ناونیشانی ئینتەرنێتی",
        "redirect": "ڕەوانەکەر بە پێی پەڕگە، بەکارھێنەر، پەڕە یان پێناسەی پێداچوونەوە",
+       "redirect-legend": "ڕەوانەکەر بۆ پەڕگە یان پەڕەیەک",
+       "redirect-summary": "ئەم پەڕە تایبەتە ڕەوانە دەکرێ بۆ پەڕگەیەک (ناوی پەڕگەکە)، پەڕەیەک (پێناسەی پێداچوونەوەیەک یان پێناسەی پەڕە) یان پەڕەیەکی بەکارھێنەر (پێناسەیەکی  ژمارەیی بەکارھێنەر). بەکارھێنان: [[{{#Special:Redirect}}/file/Example.jpg]]، [[{{#Special:Redirect}}/page/64308]]، [[{{#Special:Redirect}}/revision/328429]] یان [[{{#Special:Redirect}}/user/101]].",
        "redirect-submit": "بڕۆ",
+       "redirect-lookup": "گەڕان لە:",
+       "redirect-value": "نرخ:",
+       "redirect-user": "پێناسەی بەکارھێنەر",
+       "redirect-page": "پێناسەی پەڕە",
+       "redirect-revision": "پێداچوونەوەی پەڕە",
+       "redirect-file": "ناوی پەڕگە",
        "fileduplicatesearch": "گەڕان بۆ پەڕگە دووپات کراوەکان",
        "fileduplicatesearch-summary": "گەڕان بۆ پەڕگە دووبارەکراوەکان لەسەر بنەمای نرخی hash.",
        "fileduplicatesearch-legend": "گەڕان بۆ دووبارەکردنێک",
        "fileduplicatesearch-noresults": "پەڕگەیەک بە ناوی «$1» نەدۆزرایەوە.",
        "specialpages": "پەڕە تایبەتەکان",
        "specialpages-note": "* پەڕە تایبەتە ئاسایییەکان.\n* <span class=\"mw-specialpagerestricted\">پەڕە تایبەتە بەرگری‌لێکراوەکان.</span>",
-       "specialpages-group-maintenance": "Ú\95اپÛ\86رتÛ\95کاÙ\86Û\8c Ú\86اکسازÛ\8c",
+       "specialpages-group-maintenance": "Ú\95اپÛ\86رتÛ\95کاÙ\86Û\8c Ú\95اگرتÙ\86",
        "specialpages-group-other": "پەڕە تایبەتەکانی دیکە",
        "specialpages-group-login": "چوونەژوورەوە / دروستکردنی ھەژمار",
        "specialpages-group-changes": "دوایین گۆڕانکارییەکان و لۆگەکان",
        "blankpage": "پەڕەی واڵا",
        "intentionallyblankpage": "ئەم پەڕەیە لەقەست واڵا ھێڵراوەتەوە.",
        "external_image_whitelist": " #ئەم دێڕ ھەر بەم جۆرە کە ھەیە بەجێبێڵە<pre>\n#کەرتەکانی regular expression (تەنیا ئە بەشە کە لە نێوان // دا دێت) لە خوارەوە دابنێ\n#These will be matched with the URLs of external (hotlinked) images\n#Those that match will be displayed as images, otherwise only a link to the image will be shown\n#ئەو دێڕانە بە # دەست پێدەکەن وەک شرۆڤە (comments) مامەڵەیان لەگەڵ دەکرێ\n#بە گەورە و بچووکی پیتەکان ھەستیارە (case-insensitive)\n\n#گشت کەرتەکانی regex لە سەرەوەی ئەم دێرەدا دابنێ. ئەم دێڕ ھەر بەم جۆرە کە ھەیە بەجێبێڵە</pre>",
-       "tags": "گۆڕانکاری گونجاوی تاگەکان",
+       "tags": "تاگەکانی گۆڕانکاریی گونجاو",
        "tag-filter": "پاڵێوی [[Special:Tags|تاگ]]:",
        "tag-filter-submit": "پاڵاوتن",
        "tag-list-wrapper": "([[Special:Tags|{{PLURAL:$1|تاگ|تاگەکان}}]]: $2)",
        "feedback-message": "پەیام:",
        "feedback-cancel": "ھەڵیوەشێنەوە",
        "feedback-submit": "تێبینییەکان بنێرە",
-       "feedback-close": "ئەنجام درا",
+       "feedback-close": "کرا",
        "searchsuggest-search": "گەڕان",
        "searchsuggest-containing": "بە لەبەرگرتنەوەی ...",
        "api-error-empty-file": "ئەو پەڕگەیە کە ناردووتە واڵا بوو.",
index 9650e6f..06edb64 100644 (file)
        "protect-othertime": "Jiný čas vypršení:",
        "protect-othertime-op": "jiný čas",
        "protect-existing-expiry": "Současný čas vypršení: $2, $3",
+       "protect-existing-expiry-infinity": "Současný čas vypršení: do odvolání",
        "protect-otherreason": "Jiný/další důvod:",
        "protect-otherreason-op": "Jiný důvod",
        "protect-dropdown": "*Obvyklé důvody zamčení\n** Opakovaný vandalismus\n** Vkládání reklamních externích odkazů\n** Editační válka\n** Často používaná stránka",
        "tooltip-pt-anonuserpage": "Uživatelská stránka pro IP adresu, ze které editujete",
        "tooltip-pt-mytalk": "Vaše diskusní stránka",
        "tooltip-pt-anontalk": "Diskuse o editacích provedených z této IP adresy",
-       "tooltip-pt-preferences": "Moje nastavení",
-       "tooltip-pt-watchlist": "Seznam stránek, jejichž změny sleduji",
+       "tooltip-pt-preferences": "Vaše nastavení",
+       "tooltip-pt-watchlist": "Seznam stránek, jejichž změny sledujete",
        "tooltip-pt-mycontris": "Seznam vašich příspěvků",
        "tooltip-pt-login": "Doporučujeme vám přihlásit se, ovšem není to povinné.",
        "tooltip-pt-logout": "Odhlásit se",
index 0c16519..d062017 100644 (file)
        "protect-othertime": "Andere Sperrdauer:",
        "protect-othertime-op": "andere Sperrdauer",
        "protect-existing-expiry": "Aktuelles Seitenschutzende: $2, $3 Uhr",
+       "protect-existing-expiry-infinity": "Vorhandene Ablaufzeit: unbeschränkt",
        "protect-otherreason": "Anderer/ergänzender Grund:",
        "protect-otherreason-op": "Anderer Grund",
        "protect-dropdown": "* Allgemeine Schutzgründe\n** Edit-War\n** Wiederkehrender Vandalismus\n** Wiederholtes Einstellen von Werbung\n** Häufig eingebundene Vorlage\n** Seite mit hoher Besucherzahl",
index d9370d7..65d63d8 100644 (file)
        "prefs-help-email-others": "Ét pō ânca sernîr ed lasêr che chiêter a 's mèten in cuntât  tēgh cun la pôsta eletrônica cun al colegamèint da la tó pàgina utèint o da còla 'd discusiòun.  Al tó indirés al vîn mìa fât savèir a quî ch'ét 's mèten in cuntât tēgh.",
        "prefs-help-email-required": "L'indirés ed pôsta eletrônica l'é ubligatôri.",
        "prefs-info": "Infurmasiòun necesâri",
+       "prefs-i18n": "Internalişasiòun",
        "prefs-signature": "Fîrma",
        "prefs-dateformat": "Fōrma 'd la dâta",
        "prefs-timeoffset": "Ōri 'd diferèinsa",
        "saveusergroups": "Sêlva gróp utèint",
        "userrights-groupsmember": "Al fà pêrt {{PLURAL:$1|al gróp|ai gróp}}:",
        "userrights-groupsmember-auto": "Al fà pêrt ed sicûr a:",
+       "userrights-groups-help": "L'é pusébil mudifichêr i gróp in dó fà pêrt l'utèint. \n*'Na caşèla sernîda la sègna a che gróp al fà pêrt l'utèint. \n*'Na caşèla mìa serrnîda la sègna che l'utèin al fà mìa pêrt al gróp. \n*Al sègn * al sègna ch' an n'é m'a pusébil scanşlêr che l'utèin al fà pêrt al gróp dōp avèirel sgnê (o invicivêrsa).",
        "userrights-reason": "Mutîv:",
+       "userrights-no-interwiki": "An es gh'à mìa i permès necesâri per cambiêr i dirét ed j utèint in sém a êter sît.",
+       "userrights-nodatabase": "Al databēş $1 al gh'é mìa o an n' mìa un databêş lochêl.",
+       "userrights-nologin": "Per dêr i dirét a j utèint l'é necesâri [[Special:UserLogin|fêr l'ingrès]] cme aministardōr.",
+       "userrights-notallowed": "An 't gh'ê mìa al permès per zuntêr o tōr via i permès utèint.",
+       "userrights-changeable-col": "Gróp ch'es pōlen mudifichêr.",
+       "userrights-unchangeable-col": "Gróp ch'an 's pōlen mìa mudifichêr.",
+       "userrights-conflict": "Cuntrâst ed mudéfica di dirét utèint! Cuntròla e cunfērma al tó mudéfichi.",
+       "userrights-removed-self": "T'é tôt via cun sucès i tō dirét. E dòunca, an 't prê pió andêr dèinter a cla pàgina ché.",
        "group": "Gróp:",
        "group-user": "Utèint",
        "group-autoconfirmed": "Utèint cunvalidê da per ló",
        "grouppage-suppress": "{{ns:project}}:Oversight",
        "right-read": "Al lēş al pàgini",
        "right-edit": "Mudéfica pàgini",
+       "right-createpage": "Ét pō fêr al pàgini (fōra che 'l pàgini 'd discusiòun).",
+       "right-createtalk": "Fà 'l pàgini 'd discusiòun.",
+       "right-createaccount": "Fà dal j utèinsi nōvi.",
+       "right-minoredit": "Sègna 'l mudéfichi cme céchi.",
+       "right-move": "Spôsta 'l pàgini",
+       "right-move-subpages": "Spôsta 'l pàgini insèm al relatîvi sòt pàgini",
+       "right-move-rootuserpages": "Spôsta 'l pàgini principêli 'd j utèint",
+       "right-move-categorypages": "Spôsta 'l categoréi",
+       "right-movefile": "Spôsta i file",
+       "right-suppressredirect": "An fà mìa un indirés nōv in atvomâtich quând a se spôsta 'na pàgina",
+       "right-upload": "Cârga un file",
+       "right-reupload": "Al scré in sém a 'n file ch' al gh'é bèle",
+       "right-reupload-own": "Al scré in sém a 'n file ch' al gh'é bèle carghê da l'istès utèint",
        "newuserlogpage": "Utèint nōv",
        "action-read": "lēzer cla pàgina ché",
        "action-edit": "Mudifichêr cla pàgina ché",
index bc1c6a1..e56789a 100644 (file)
        "preferences-summary": "",
        "mypreferences": "Preferences",
        "prefs-edits": "Number of edits:",
-       "prefsnologintext2": "Please login to change your preferences.",
+       "prefsnologintext2": "Please log in to change your preferences.",
        "prefs-skin": "Skin",
        "skin-preview": "Preview",
        "datedefault": "No preference",
        "mywatchlist": "Watchlist",
        "watchlistfor2": "For $1 $2",
        "nowatchlist": "You have no items on your watchlist.",
-       "watchlistanontext": "Please login to view or edit items on your watchlist.",
+       "watchlistanontext": "Please log in to view or edit items on your watchlist.",
        "watchnologin": "Not logged in",
        "addwatch": "Add to watchlist",
        "addedwatchtext": "The page \"[[:$1]]\" has been added to your [[Special:Watchlist|watchlist]].\nFuture changes to this page and its associated talk page will be listed there.",
        "protect-othertime": "Other time:",
        "protect-othertime-op": "other time",
        "protect-existing-expiry": "Existing expiry time: $3, $2",
+       "protect-existing-expiry-infinity": "Existing expiry time: infinite",
        "protect-otherreason": "Other/additional reason:",
        "protect-otherreason-op": "Other reason",
        "protect-dropdown": "*Common protection reasons\n** Excessive vandalism\n** Excessive spamming\n** Counter-productive edit warring\n** High traffic page",
index a98fcf5..6ae8c6b 100644 (file)
        "category-file-count": "{{PLURAL:$2|Selles kategoorias on ainult järgmine fail.|{{PLURAL:$1|Järgmine fail |Järgmised $1 faili}} on selles kategoorias (kokku $2).}}",
        "category-file-count-limited": "{{PLURAL:$1|Järgmine fail|Järgmised $1 faili}} on selles kategoorias.",
        "listingcontinuesabbrev": "jätk",
-       "index-category": "Indeksiga leheküljed",
+       "index-category": "Indekseeritud leheküljed",
        "noindex-category": "Indekseerimata leheküljed",
        "broken-file-category": "Katkiste pildilinkidega leheküljed",
        "about": "Tiitelandmed",
        "searchall": "kõik",
        "showingresults": "Allpool näidatakse '''{{PLURAL:$1|ühte|$1}}''' tulemust alates '''$2'''. tulemusest.",
        "showingresultsinrange": "Allpool näidatakse {{PLURAL:$1|<strong>üht</strong>|<strong>$1</strong>}} tulemust vahemikus <strong>$2</strong>–<strong>$3</strong>.",
+       "search-showingresults": "{{PLURAL:$4|<strong>$1</strong>. tulemus <strong>$3</strong>-st|Tulemused <strong>$1–$2</strong> <strong>$3</strong>-st}}",
        "search-nonefound": "Päringule ei leitud vasteid.",
        "powersearch-legend": "Täpsem otsing",
        "powersearch-ns": "Otsing nimeruumidest:",
        "unblocked": "Kasutaja [[User:$1|$1]] blokeering on eemaldatud",
        "unblocked-range": "Vahemiku $1 blokeering on eemaldatud",
        "unblocked-id": "Blokeerimine $1 on lõpetatud",
+       "unblocked-ip": "IP-aadressi [[Special:Contributions/$1|$1]] blokeering on eemaldatud.",
        "blocklist": "Blokeeritud kasutajad",
        "ipblocklist": "Blokeeritud kasutajad",
        "ipblocklist-legend": "Leia blokeeritud kasutaja",
        "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.",
-       "default-skin-not-found": "Oih! Sinu viki vaikekujundus (<code>$wgDefaultSkin</code>) <code>$1</code> pole saadaval.\n\nPaistab, et sinu install sisaldab järgmisi kujundusi. Vaata [https://www.mediawiki.org/wiki/Manual:Skin_configuration kujunduste häälestusjuhendist], kuidas neid lubada ja kuidas valida vaikekujundus.\n\n$2\n\n; Kui oled MediaWiki just paigaldanud:\n: Paigaldasid tarkvara ilmselt Giti kaudu või otse lähtekoodist või mõnel muul viisil. See on ootuspärane. Proovi [https://www.mediawiki.org/wiki/Category:All_skins mediawiki.org-i kujunduste kataloogist] mõni kujundus paigaldada. Selleks saad:\n:* laadida alla [https://www.mediawiki.org/wiki/Download lintarhiivi paigaldaja], mis sisaldab mitut kujundust ja tarkvaralisa. Saad sealt kleepimiseks kopeerida kausta <code>skins/</code>;\n:* kopeerida Giti kaudu ühe hoidla (<code>mediawiki/skins/*</code>) oma MediaWiki installi kausta <code>skins/</code>.\n: Selle tegemine ei tohiks häirida Giti hoidlat, kui oled MediaWiki arendaja.\n\n; Kui oled MediaWikit just täiendanud:\n: MediaWiki 1.24-s ja uuemates versioonides pole paigaldatud kujundused enam automaatselt lubatud (vaata juhendist [https://www.mediawiki.org/wiki/Manual:Skin_autodiscovery kujunduste automaatse leidmise] kohta). Saad kleepida järgmised read leheküljele <code>LocalSettings.php</code>, et lubada kõik praegu paigaldatud kujundused:\n\n<pre>$3</pre>\n\n; Kui oled lehekülge <code>LocalSettings.php</code> just muutnud:\n: Kontrolli üle, ega kujunduste nimedes pole trükivigu.",
-       "default-skin-not-found-no-skins": "Oih! Sinu viki vaikekujundus (<code>$wgDefaultSkin</code>) <code>$1</code> pole saadaval.\n\nÜhtegi kujundust pole paigaldatud.\n\n; Kui oled MediaWiki just paigaldanud või täiendasid seda:\n: Paigaldasid tarkvara ilmselt Giti kaudu või otse lähtekoodist või mõnel muul viisil. See on ootuspärane. MediaWiki 1.24 ja uuemad versioonid ei sisalda peahoidlas ühtegi kujundust. Proovi [https://www.mediawiki.org/wiki/Category:All_skins mediawiki.org-i kujunduste kataloogist] mõni kujundus paigaldada. Selleks saad:\n:* laadida alla [https://www.mediawiki.org/wiki/Download lintarhiivi paigaldaja], mis sisaldab mitut kujundust ja tarkvaralisa. Saad sealt kleepimiseks kopeerida kausta <code>skins/</code>;\n:* kopeerida Giti kaudu ühe hoidla (<code>mediawiki/skins/*</code>) oma MediaWiki installi kausta <code>skins/</code>.\n: Selle tegemine ei tohiks häirida Giti hoidlat, kui oled MediaWiki arendaja. Vaata [https://www.mediawiki.org/wiki/Manual:Skin_configuration kujunduste häälestusjuhendist], kuidas kujundusi lubada ja kuidas valida vaikekujundus.",
+       "default-skin-not-found": "Oih! Sinu viki vaikekujundus, milleks muutuja <code dir=\"ltr\">$wgDefaultSkin</code> järgi on <code>$1</code>, pole saadaval.\n\nPaistab, et sinu install sisaldab järgmisi kujundusi. Vaata [https://www.mediawiki.org/wiki/Manual:Skin_configuration kujunduste häälestusjuhendist], kuidas neid lubada ja kuidas valida vaikekujundus.\n\n$2\n\n; Kui oled MediaWiki just paigaldanud:\n: Paigaldasid tarkvara ilmselt Giti kaudu või otse lähtekoodist või mõnel muul viisil. See on ootuspärane. Proovi [https://www.mediawiki.org/wiki/Category:All_skins mediawiki.org-i kujunduste kataloogist] mõni kujundus paigaldada. Selleks saad:\n:* laadida alla [https://www.mediawiki.org/wiki/Download lintarhiivi paigaldaja], mis sisaldab mitut kujundust ja tarkvaralisa. Saad sealt kleepimiseks kopeerida kausta <code dir=\"ltr\">skins/</code>;\n:* kopeerida Giti kaudu ühe hoidla (<code>mediawiki/skins/*</code>) oma MediaWiki installi kausta <code>skins/</code>.\n: Selle tegemine ei tohiks häirida Giti hoidlat, kui oled MediaWiki arendaja.\n\n; Kui oled MediaWikit just täiendanud:\n: MediaWiki 1.24-s ja uuemates versioonides pole paigaldatud kujundused enam automaatselt lubatud (vaata juhendist [https://www.mediawiki.org/wiki/Manual:Skin_autodiscovery kujunduste automaatse leidmise] kohta). Saad kleepida järgmised read leheküljele <code>LocalSettings.php</code>, et lubada kõik praegu paigaldatud kujundused:\n\n<pre dir=\"ltr\">$3</pre>\n\n; Kui oled lehekülge <code>LocalSettings.php</code> just muutnud:\n: Kontrolli üle, ega kujunduste nimedes pole trükivigu.",
+       "default-skin-not-found-no-skins": "Oih! Sinu viki vaikekujundus, milleks muutuja <code dir=\"ltr\">$wgDefaultSkin</code> järgi on <code>$1</code>, pole saadaval.\n\nÜhtegi kujundust pole paigaldatud.\n\n; Kui oled MediaWiki just paigaldanud või täiendasid seda:\n: Paigaldasid tarkvara ilmselt Giti kaudu või otse lähtekoodist või mõnel muul viisil. See on ootuspärane. MediaWiki 1.24 ja uuemad versioonid ei sisalda peahoidlas ühtegi kujundust. Proovi [https://www.mediawiki.org/wiki/Category:All_skins mediawiki.org-i kujunduste kataloogist] mõni kujundus paigaldada. Selleks saad:\n:* laadida alla [https://www.mediawiki.org/wiki/Download lintarhiivi paigaldaja], mis sisaldab mitut kujundust ja tarkvaralisa. Saad sealt kleepimiseks kopeerida kausta <code dir=\"ltr\">skins/</code>;\n:* kopeerida Giti kaudu ühe hoidla (<code>mediawiki/skins/*</code>) oma MediaWiki installi kausta <code>skins/</code>.\n: Selle tegemine ei tohiks häirida Giti hoidlat, kui oled MediaWiki arendaja. Vaata [https://www.mediawiki.org/wiki/Manual:Skin_configuration kujunduste häälestusjuhendist], kuidas kujundusi lubada ja kuidas valida vaikekujundus.",
        "default-skin-not-found-row-enabled": "* <code>$1</code> / $2 (lubatud)",
        "default-skin-not-found-row-disabled": "* <code>$1</code> / $2 ('''keelatud''')"
 }
index a39efc3..dd08523 100644 (file)
        "protect-othertime": "זמן אחר:",
        "protect-othertime-op": "זמן אחר",
        "protect-existing-expiry": "זמן פקיעה נוכחי: $3, $2",
+       "protect-existing-expiry-infinity": "זמן תפוגה נוכחי: אינסופי",
        "protect-otherreason": "סיבה אחרת/נוספת:",
        "protect-otherreason-op": "סיבה אחרת",
        "protect-dropdown": "* סיבות הגנה נפוצות\n** השחתה רבה\n** ספאם רב\n** מלחמת עריכה בלתי מועילה\n** דף בשימוש רב",
index c68547b..f72f831 100644 (file)
        "hidetoc": "sakrij",
        "collapsible-collapse": "sklopi stablo",
        "collapsible-expand": "raširi stablo",
+       "confirmable-confirm": "Jeste li sigurni?",
+       "confirmable-yes": "Da",
+       "confirmable-no": "Ne",
        "thisisdeleted": "Vidi ili vrati $1?",
        "viewdeleted": "Vidi $1?",
        "restorelink": "{{PLURAL:$1|$1 pobrisanu izmjenu|$1 pobrisane izmjene|$1 pobrisanih izmjena}}",
index 0eab06d..8c7547a 100644 (file)
        "protect-othertime": "Durata non in elenco:",
        "protect-othertime-op": "durata non in elenco",
        "protect-existing-expiry": "Scadenza attuale: $2, $3",
+       "protect-existing-expiry-infinity": "Scadenza attuale: infinito",
        "protect-otherreason": "Altri motivi/dettagli:",
        "protect-otherreason-op": "Altra motivazione",
        "protect-dropdown": "*Motivi comuni di protezione\n** Reiterati vandalismi\n** Reiterati inserimenti di spam\n** Edit war\n** Pagina molto usata",
index 66f0fea..8c0c195 100644 (file)
        "signature": "[[{{ns:user}}:$1|$2]] ([[{{ns:user_talk}}:$1|トーク]])",
        "unknown_extension_tag": "不明な拡張機能タグ「$1」です",
        "duplicate-defaultsort": "<strong>警告:</strong> 既定のソートキー「$2」が、その前に書かれている既定のソートキー「$1」を上書きしています。",
-       "duplicate-displaytitle": "<strong>警告:</strong> 既定のDISPLAYTITLE「$2」が、その前に書かれている既定のDISPLAYTITLE「$1」を上書きしています。",
+       "duplicate-displaytitle": "<strong>警告:</strong> DISPLAYTITLE「$2」が、その前に書かれているDISPLAYTITLE「$1」を上書きしています。",
        "version": "バージョン情報",
        "version-extensions": "インストール済み拡張機能",
        "version-skins": "インストール済み外装",
index a51a615..051c930 100644 (file)
        "protectedarticle": "حفاظت بيه [[$1]]",
        "modifiedarticleprotection": "ریتراز حفاظت د \"[[$1]]\" آلشت بیه",
        "protect-title": "ریتراز حفاظت د \"$1\" آلشت بیه",
+       "protect-title-notallowed": "دیئن ریتراز پر و پیم \"$1\"",
        "prot_1movedto2": "[[$1]] د [[$2]] جا وه جا بی",
+       "protect-badnamespace-title": "نوم جا بی پر و پیم",
        "protect-norestrictiontypes-title": "بلگه بی حامین گر",
        "protect-legend": "پشت راس کردن حامین گری",
        "protectcomment": "دلیل:",
        "protect_expiry_invalid": "گات تموم بیین نامعتوره.",
        "protect_expiry_old": "گات تموم بیین مال دماتره.",
        "protect-default": "همه کاروریا اجازه دارن",
+       "protect-level-sysop": "فقط دیوونداریا",
        "protect-summary-desc": "[$1=$2] ($3)",
        "protect-summary-cascade": "د حال و بال تافنمایی",
        "protect-expiring": "گات تموم بیین $1 (یو تی سی)",
        "badipaddress": "تیرنشون نامعتور آی پی",
        "blockipsuccesssub": "قلف کردن د خوئی انجوم بی",
        "ipb-edit-dropdown": "ویرایشت دلیلیا نهاگرتن",
+       "ipb-unblock-addr": "وا کردن قلف $1",
        "unblockip": "کارور منع نبیه",
        "ipusubmit": "ای قلف نه ؤردار",
        "blocklist": "كاروريا منع بيه",
        "ipblocklist": "كاروريا منع بيه",
        "ipblocklist-legend": "یه گل کارور منع بیه بجوریت",
        "blocklist-timestamp": "چسب ون وخت",
+       "blocklist-expiry": "تموم بين",
        "blocklist-reason": "دلیل",
        "ipblocklist-submit": "پی جوری",
        "ipblocklist-localblock": "نهاگری ولات نشینی",
        "import": "وامین اوردن بلگه یا",
        "import-interwiki-sourcewiki": "سرچشمه ویکی:",
        "import-interwiki-sourcepage": "بلگه سرچشمه:",
+       "import-interwiki-templates": "همه چوئه یا",
        "import-interwiki-submit": "وامین اوردن",
        "import-interwiki-namespace": "نومجا مقصد:",
        "import-upload-filename": "نوم جانیا:",
index dc9e449..a0dbccd 100644 (file)
        "mywatchlist": "Uzraugāmie raksti",
        "watchlistfor2": "Priekš $1 ($2)",
        "nowatchlist": "Tavā uzraugāmo rakstu sarakstā nav neviena raksta.",
-       "watchlistanontext": "Lūdzu $1, lai apskatītu vai labotu savu uzraugāmo rakstu saraksta saturu.",
+       "watchlistanontext": "Lūdzu pieslēdzies, lai apskatītu vai labotu savu uzraugāmo rakstu saraksta saturu.",
        "watchnologin": "Neesi iegājis",
        "addwatch": "Pievienot uzraugāmo lapu sarakstam",
        "addedwatchtext": "Lapa \"[[:$1]]\" ir pievienota [[Special:Watchlist|tevis uzraudzītajām lapām]], kur tiks parādītas izmaiņas, kas izdarītas šajā lapā vai šīs lapas diskusiju lapā, kā arī šī lapa tiks iezīmēta '''pustrekna''' [[Special:RecentChanges|pēdējo izmaiņu lapā]], lai to būtu vieglāk pamanīt.\n\nJa vēlāk pārdomāsi un nevēlēsies vairs uzraudzīt šo lapu, klikšķini uz saites '''neuzraudzīt''' rīku joslā.",
index 1ff5e3c..4a563c5 100644 (file)
        "allpagesbadtitle": "Дадениот наслов е неважечки или има меѓујазичен или меѓувики-претставка. Може да содржи повеќе знаци кои не смеат да се користат во наслови.",
        "allpages-bad-ns": "Википедија не содржи именски простор „$1“.",
        "allpages-hide-redirects": "Скриј пренасочувања",
-       "cachedspecial-viewing-cached-ttl": "Ð\93ледаÑ\82е ÐºÐµÑ\88ирана верзија на оваа страница, која може да е стара $1.",
-       "cachedspecial-viewing-cached-ts": "Ð\93ледаÑ\82е ÐºÐµÑ\88ирана верзија на оваа страница, која може да се разликува од тековната.",
+       "cachedspecial-viewing-cached-ttl": "Ð\93ледаÑ\82е Ð¼ÐµÑ\93Ñ\83Ñ\81кладирана верзија на оваа страница, која може да е стара $1.",
+       "cachedspecial-viewing-cached-ts": "Ð\93ледаÑ\82е Ð¼ÐµÑ\93Ñ\83Ñ\81кладирана верзија на оваа страница, која може да се разликува од тековната.",
        "cachedspecial-refresh-now": "Погл. најновата.",
        "categories": "Категории",
        "categoriespagetext": "{{PLURAL:$1|Следната категорија содржи|Следните категории содржат}} страници или мултимедијални податотеки.\n[[Special:UnusedCategories|Неискористените категории]] не се прикажани овде.\nПогледајте ги и [[Special:WantedCategories|потребните категории]].",
        "protect-othertime": "Друго време:",
        "protect-othertime-op": "друго време",
        "protect-existing-expiry": "Постоечки рок на истекување: $3, $2",
+       "protect-existing-expiry-infinity": "Постоечки рок: бесконечен",
        "protect-otherreason": "Друга/дополнителна причина:",
        "protect-otherreason-op": "Друга причина",
        "protect-dropdown": "*Вообичаени причини за заштита\n** Зачестен вандализам\n** Зачестен спам\n** Непродуктивна уредувачка војна\n** Страница со зачестена посета\n** Сеприсутност на шаблонот/превметнувањето\n** Административна постапка",
        "dberr-info-hidden": "(Не може да се добие опслужувачот на базата на податоци)",
        "dberr-usegoogle": "Во меѓувреме можете да се обидете да пребарувате со Google.",
        "dberr-outofdate": "Да напоменеме дека нивните индекси на нашата содржина можат да бидат застарени.",
-       "dberr-cachederror": "Следнава Ñ\81одÑ\80жина Ðµ ÐºÐµÑ\88иÑ\80ана ÐºÐ¾Ð¿Ð¸Ñ\98а Ð½Ð° Ð±Ð°Ñ\80анаÑ\82а Ñ\81Ñ\82Ñ\80аниÑ\86а, ÐºÐ¾Ñ\98а Ð¼Ð¾Ð¶Ðµ Ð´Ð° Ðµ Ð·Ð°Ñ\81Ñ\82аÑ\80ена.",
+       "dberr-cachederror": "Следнава Ñ\81одÑ\80жина Ðµ Ð¼ÐµÑ\93Ñ\83Ñ\81кладиÑ\80ан Ð¿Ñ\80имеÑ\80ок Ð½Ð° Ð±Ð°Ñ\80анаÑ\82а Ñ\81Ñ\82Ñ\80аниÑ\86а, ÐºÐ¾Ñ\98 Ð¼Ð¾Ð¶Ðµ Ð´Ð° Ðµ Ð·Ð°Ñ\81Ñ\82аÑ\80ен.",
        "htmlform-invalid-input": "Има проблеми со дел од вашиот внос",
        "htmlform-select-badoption": "Укажаната вредност е неважечка како можност.",
        "htmlform-int-invalid": "Вредноста која ја наведовте не е цел број.",
index 3de847e..cf72932 100644 (file)
        "otherlanguages": "ഇതരഭാഷകളിൽ",
        "redirectedfrom": "($1 എന്ന താളിൽ നിന്നും തിരിച്ചുവിട്ടതു പ്രകാരം)",
        "redirectpagesub": "തിരിച്ചുവിടൽ താൾ",
+       "redirectto": "തിരിച്ചുവിടുന്നു:",
        "lastmodifiedat": "ഈ താൾ അവസാനം തിരുത്തപ്പെട്ടത്: $2, $1.",
        "viewcount": "ഈ താൾ {{PLURAL:$1|ഒരു തവണ|$1 തവണ}} സന്ദർശിക്കപ്പെട്ടിട്ടുണ്ട്.",
        "protectedpage": "സംരക്ഷിത താൾ",
        "createaccount-text": "{{SITENAME}} സംരംഭത്തിൽ ($4) താങ്കളുടെ ഇമെയിൽ വിലാസത്തിൽ ആരോ ഒരു അംഗത്വം \"$2\" എന്ന ഉപയോക്തൃനാമത്തിൽ ഉണ്ടാക്കിയിരിക്കുന്നു (രഹസ്യവാക്ക്: \"$3\").  താങ്കൾ ഇപ്പോൾ ലോഗിൻ ചെയ്തു രഹസ്യവാക്ക് മാറ്റേണ്ടതാകുന്നു.\n\nഅംഗത്വം അബദ്ധവശാൽ ഉണ്ടാക്കിയതാണെങ്കിൽ താങ്കൾക്ക് ഈ സന്ദേശം നിരാകരിക്കാവുന്നതാണ്‌.",
        "login-throttled": "താങ്കൾ നിരവധി പ്രാവശ്യം ലോഗിൻ ചെയ്യാൻ ശ്രമിച്ചിരിക്കുന്നു.\nപുതിയതായി ശ്രമിക്കുന്നതിനു മുമ്പ് $1 ദയവായി കാത്തിരിക്കുക.",
        "login-abort-generic": "താങ്കളുടെ പ്രവേശിക്കൽ പരാജയപ്പെട്ടു - റദ്ദാക്കപ്പെട്ടിരിക്കുന്നു",
+       "login-migrated-generic": "താങ്കളുടെ അംഗത്വം പ്രവാസത്തിലാണ്, ഉപയോക്തൃനാമം ഈ വിക്കിയിൽ നിലവിലില്ല.",
        "loginlanguagelabel": "ഭാഷ: $1",
        "suspicious-userlogout": "ലോഗൗട്ട് ചെയ്യാനുള്ള താങ്കളുടെ അഭ്യർത്ഥന നിരസിച്ചിരിക്കുന്നു, കാരണം അത് കേടായ ബ്രൗസറിൽ നിന്നോ കാഷിങ് പ്രോക്സിയിൽ നിന്നോ ഉണ്ടായതുപോലെ അനുഭവപ്പെടുന്നു.",
        "createacct-another-realname-tip": "താങ്കളുടെ യഥാർത്ഥ പേര്‌ നൽകണമെന്നു നിർബന്ധമില്ല.\n\nഎങ്കിലും അങ്ങനെ ചെയ്താൽ, ഉപയോക്താക്കൾക്ക് അവരരവരുടെ പേരിൽ തന്നെ തങ്ങളുടെ സൃഷ്ടിക്ക് കടപ്പാട് ലഭിക്കുന്നതാണ്.",
        "searchall": "എല്ലാം",
        "showingresults": "'''$2''' മുതലുള്ള {{PLURAL:$1|'''ഒരു''' ഫലം|'''$1''' ഫലങ്ങൾ}} താഴെ പ്രദർശിപ്പിക്കുന്നു.",
        "showingresultsinrange": "#<strong>$2</strong> മുതൽ #<strong>$3</strong> വരെയുള്ള പരിധിയിലെ {{PLURAL:$1|<strong>ഒരു</strong> ഫലം|<strong>$1</strong> ഫലങ്ങൾ}} താഴെ പ്രദർശിപിക്കുന്നു.",
-       "showingresultsheader": "'''$4''' എന്ന പദത്തിനു ആകെ ലഭിച്ച {{PLURAL:$5| '''$3''' ഫലത്തിൽ '''$1''' എണ്ണം|'''$3''' ഫലത്തിൽ '''$1 മുതൽ $2''' വരെയുള്ളവ}}",
+       "search-showingresults": "{{PLURAL:$4|<strong>$3</strong> ഫലത്തിൽ<strong>$1</strong>|<strong>$3</strong> ഫലത്തിൽ <strong>$1 മുതൽ $2</strong> വരെയുള്ളവ}}",
        "search-nonefound": "താങ്കൾ തിരഞ്ഞ പദത്തിനു യോജിച്ച ഫലങ്ങളൊന്നും ലഭിച്ചില്ല.",
        "powersearch-legend": "വിപുലീകൃത തിരച്ചിൽ",
        "powersearch-ns": "തിരയേണ്ട നാമമേഖലകൾ",
        "unblockiptext": "മുൻപ് തടയപ്പെട്ട ഐ.പി.യുടേയും ഉപയോക്താവിന്റേയും തിരുത്തൽ അവകാശം പുനഃസ്ഥാപിക്കാൻ താഴെയുള്ള ഫോം ഉപയോഗിക്കുക.",
        "ipusubmit": "ഈ വിലക്ക് ഒഴിവാക്കുക",
        "unblocked": "[[User:$1|$1]] എന്ന ഉപയോക്താവിനുണ്ടായിരുന്ന തടയൽ നീക്കിയിരിക്കുന്നു",
-       "unblocked-range": "$1 എന്ന പരിധിയുടെ തടയൽ നീക്കപ്പെട്ടിരിക്കുന്നു",
-       "unblocked-id": "$1 എന്ന തടയൽ നീക്കം ചെയ്തിരിക്കുന്നു",
+       "unblocked-range": "$1 എന്ന പരിധിയുടെ തടയൽ നീക്കിയിരിക്കുന്നു.",
+       "unblocked-id": "$1 എന്ന തടയൽ നീക്കിയിരിക്കുന്നു.",
+       "unblocked-ip": "[[Special:Contributions/$1|$1]] എന്ന വിലാസത്തിനുണ്ടായിരുന്ന തടയൽ നീക്കിയിരിക്കുന്നു.",
        "blocklist": "തടയപ്പെട്ട ഉപയോക്താക്കൾ",
        "ipblocklist": "തടയപ്പെട്ട ഉപയോക്താക്കൾ",
        "ipblocklist-legend": "തടഞ്ഞ ഒരു ഉപയോക്താവിനെ തിരയുക",
        "log-name-pagelang": "ഭാഷ മാറ്റലിന്റെ രേഖ",
        "log-description-pagelang": "താളുകളുടെ ഭാഷകൾ മാറ്റിയതിന്റെ രേഖകൾ ഇവിടെക്കാണാം.",
        "logentry-pagelang-pagelang": "$3 എന്ന താളിന്റെ ഭാഷയായിരുന്ന $4, $1 $5 ആയി {{GENDER:$2|മാറ്റി}}.",
-       "default-skin-not-found": "അയ്യോ! താങ്കളുടെ വിക്കിയുടെ സ്വതേയുള്ള ദൃശ്യരൂപമായ (<code>$wgDefaultSkin</code>), <code>$1</code>, ലഭ്യമല്ല.\n\nതാങ്കളുടെ ഇൻസ്റ്റലേഷനിൽ താഴെക്കൊടുക്കുന്ന ദൃശ്യരൂപങ്ങൾ ഉണ്ടാകേണ്ടതാണ്. അവ എങ്ങനെ ക്രമീകരിക്കാം എന്നും സ്വതേ വേണ്ടത് എങ്ങനെ സജ്ജമാക്കാം എന്നും [https://www.mediawiki.org/wiki/Manual:Skin_configuration ദൃശ്യരൂപം സജ്ജമാക്കൽ സഹായിയിൽ] കാണുക.\n\n$2\n\n; താങ്കൾ മീഡിയവിക്കി ഇൻസ്റ്റോൾ ചെയ്തതേ ഉള്ളുവെങ്കിൽ:\n: ഗിറ്റിൽ നിന്ന് അല്ലെങ്കിൽ മറ്റെങ്കിലും മാർഗ്ഗം ഉപയോഗിച്ച് സോഴ്സ് കോഡ് നേരിട്ട് ഉപയോഗിക്കുകയായിരിന്നെങ്കിൽ ഇത് സംഭവിച്ചേക്കാം. [https://www.mediawiki.org/wiki/Category:All_skins mediawiki.org's ദൃശ്യരൂപ ഡയറക്ടറിയിൽ നിന്ന്], ഇനിക്കൊടുക്കുന്ന മാർഗ്ഗങ്ങൾ ഉപയോഗിച്ച് ഏതാനം ദൃശ്യരൂപങ്ങൾ ഇൻസ്റ്റോൾ ചെയ്യാൻ നോക്കുക:\n:* [https://www.mediawiki.org/wiki/Download ടാർബോൾ ഇൻസ്റ്റോളർ] ഡൗൺലോഡ് ചെയ്യുക, അതിൽ നിരവധി ദൃശ്യരൂപങ്ങളും അനുബന്ധങ്ങളും ഉൾപ്പെടുത്തിയിരിക്കുന്നു. അതിൽ നിന്നും താങ്കൾക്ക് <code>skins/</code> ഡയറക്ടറി പകർത്താവുന്നതാണ്.\n:* താങ്കളുടെ മീഡിയവിക്കി ഇൻസ്റ്റലേഷന്റെ <code>skins/</code> ഡയറക്ടറിയിലേക്ക് ഗിറ്റ് ഉപയോഗിച്ച് <code>mediawiki/skins/*</code> റെപ്പോസിറ്ററികളിലൊന്ന് ക്ലോൺ ചെയ്യുക.\n: താങ്കളൊരു മീഡിയവിക്കി ഡവലപ്പറാണെങ്കിൽ ഇത് താങ്കളുടെ ഗിറ്റ് ഡെപ്പോസിറ്ററിയെ ബാധിക്കുന്നതല്ല.\n\n; മീഡിയവിക്കി താങ്കൾ അപ്ഗ്രേഡ് ചെയ്തതേ ഉള്ളുവെങ്കിൽ:\n: മീഡിയവിക്കി 1.24 ഒപ്പം അതിനു ശേഷമുള്ളവയും ഇൻസ്റ്റോൾ ചെയ്തിട്ടുള്ള ദൃശ്യരൂപങ്ങൾ സ്വതേ സജ്ജമാക്കുന്നില്ല ([https://www.mediawiki.org/wiki/Manual:Skin_autodiscovery ദൃശ്യരൂപം ഓട്ടോഡിസ്കവറി സഹായം] കാണുക). ഇൻസ്റ്റോൾ ചെയ്തിട്ടുള്ള ദൃശ്യരൂപങ്ങൾ സജ്ജമാക്കുന്നതിനായി ഇനിക്കൊടുക്കുന്ന വരികൾ <code>LocalSettings.php</code> എന്നതിലോട്ട് പകർത്തുക:\n\n<pre>$3</pre>\n\n; <code>LocalSettings.php</code> താളിൽ മാറ്റം വരുത്തിയതേയുള്ളുവെങ്കിൽ:\n: ദൃശ്യരൂപങ്ങളുടെ പേരിൽ അക്ഷരപിശകുകളുണ്ടോയെന്ന് ആവർത്തിച്ച് പരിശോധിക്കുക.",
-       "default-skin-not-found-no-skins": "അയ്യോ! താങ്കളുടെ വിക്കിയുടെ സ്വതേയുള്ള ദൃശ്യരൂപമായ (<code>$wgDefaultSkin</code>), <code>$1</code>, ലഭ്യമല്ല.\n\nതാങ്കൾ ദൃശ്യരൂപങ്ങളൊന്നും ഇൻസ്റ്റോൾ ചെയ്തിട്ടില്ല.\n\n; താങ്കൾ മീഡിയവിക്കി ഇൻസ്റ്റോൾ ചെയ്തതേ അല്ലെങ്കിൽ അപ്‌ഗ്രേഡ് ചെയ്തതേ ഉള്ളുവെങ്കിൽ:\n: ഗിറ്റിൽ നിന്ന് അല്ലെങ്കിൽ മറ്റെങ്കിലും മാർഗ്ഗം ഉപയോഗിച്ച് സോഴ്സ് കോഡ് നേരിട്ട് ഉപയോഗിക്കുകയായിരിന്നെങ്കിൽ ഇത് സംഭവിച്ചേക്കാം. [https://www.mediawiki.org/wiki/Category:All_skins mediawiki.org's ദൃശ്യരൂപ ഡയറക്ടറിയിൽ നിന്ന്], ഇനിക്കൊടുക്കുന്ന മാർഗ്ഗങ്ങൾ ഉപയോഗിച്ച് ഏതാനം ദൃശ്യരൂപങ്ങൾ ഇൻസ്റ്റോൾ ചെയ്യാൻ നോക്കുക:\n:* [https://www.mediawiki.org/wiki/Download ടാർബോൾ ഇൻസ്റ്റോളർ] ഡൗൺലോഡ് ചെയ്യുക, അതിൽ നിരവധി ദൃശ്യരൂപങ്ങളും അനുബന്ധങ്ങളും ഉൾപ്പെടുത്തിയിരിക്കുന്നു. അതിൽ നിന്നും താങ്കൾക്ക് <code>skins/</code> ഡയറക്ടറി പകർത്താവുന്നതാണ്.\n:* താങ്കളുടെ മീഡിയവിക്കി ഇൻസ്റ്റലേഷന്റെ <code>skins/</code> ഡയറക്ടറിയിലേക്ക് ഗിറ്റ് ഉപയോഗിച്ച് <code>mediawiki/skins/*</code> റെപ്പോസിറ്ററികളിലൊന്ന് ക്ലോൺ ചെയ്യുക.\n: താങ്കളൊരു മീഡിയവിക്കി ഡവലപ്പറാണെങ്കിൽ ഇത് താങ്കളുടെ ഗിറ്റ് ഡെപ്പോസിറ്ററിയെ ബാധിക്കുന്നതല്ല. ദൃശ്യരൂപങ്ങൾ എങ്ങനെ ക്രമീകരിക്കാം എന്നും സ്വതേ വേണ്ടത് എങ്ങനെ സജ്ജമാക്കാം എന്നും [https://www.mediawiki.org/wiki/Manual:Skin_configuration ദൃശ്യരൂപം സജ്ജമാക്കൽ സഹായിയിൽ] കാണുക.",
+       "default-skin-not-found": "അയ്യോ! <code dir=\"ltr\"> $wgDefaultSkin</code> നിർവചിക്കപ്പെട്ടതുപ്രകാരമുള്ള താങ്കളുടെ വിക്കിയുടെ സ്വതേയുള്ള ദൃശ്യരൂപമായ <code>$1</code>, ലഭ്യമല്ല.\n\nതാങ്കളുടെ ഇൻസ്റ്റലേഷനിൽ താഴെക്കൊടുക്കുന്ന ദൃശ്യരൂപങ്ങൾ ഉണ്ടാകേണ്ടതാണ്. അവ എങ്ങനെ ക്രമീകരിക്കാം എന്നും സ്വതേ വേണ്ടത് എങ്ങനെ സജ്ജമാക്കാം എന്നും [https://www.mediawiki.org/wiki/Manual:Skin_configuration ദൃശ്യരൂപം സജ്ജമാക്കൽ സഹായിയിൽ] കാണുക.\n\n$2\n\n; താങ്കൾ മീഡിയവിക്കി ഇൻസ്റ്റോൾ ചെയ്തതേ ഉള്ളുവെങ്കിൽ:\n: ഗിറ്റിൽ നിന്ന് അല്ലെങ്കിൽ മറ്റെങ്കിലും മാർഗ്ഗം ഉപയോഗിച്ച് സോഴ്സ് കോഡ് നേരിട്ട് ഉപയോഗിക്കുകയായിരിന്നെങ്കിൽ ഇത് സംഭവിച്ചേക്കാം. [https://www.mediawiki.org/wiki/Category:All_skins mediawiki.org's ദൃശ്യരൂപ ഡയറക്ടറിയിൽ നിന്ന്], ഇനിക്കൊടുക്കുന്ന മാർഗ്ഗങ്ങൾ ഉപയോഗിച്ച് ഏതാനം ദൃശ്യരൂപങ്ങൾ ഇൻസ്റ്റോൾ ചെയ്യാൻ നോക്കുക:\n:* [https://www.mediawiki.org/wiki/Download ടാർബോൾ ഇൻസ്റ്റോളർ] ഡൗൺലോഡ് ചെയ്യുക, അതിൽ നിരവധി ദൃശ്യരൂപങ്ങളും അനുബന്ധങ്ങളും ഉൾപ്പെടുത്തിയിരിക്കുന്നു. അതിൽ നിന്നും താങ്കൾക്ക് <code>skins/</code> ഡയറക്ടറി പകർത്താവുന്നതാണ്.\n:* താങ്കളുടെ മീഡിയവിക്കി ഇൻസ്റ്റലേഷന്റെ <code dir=\"ltr\">skins/</code> ഡയറക്ടറിയിലേക്ക് ഗിറ്റ് ഉപയോഗിച്ച് <code>mediawiki/skins/*</code> റെപ്പോസിറ്ററികളിലൊന്ന് ക്ലോൺ ചെയ്യുക.\n: താങ്കളൊരു മീഡിയവിക്കി ഡവലപ്പറാണെങ്കിൽ ഇത് താങ്കളുടെ ഗിറ്റ് ഡെപ്പോസിറ്ററിയെ ബാധിക്കുന്നതല്ല.\n\n; മീഡിയവിക്കി താങ്കൾ അപ്ഗ്രേഡ് ചെയ്തതേ ഉള്ളുവെങ്കിൽ:\n: മീഡിയവിക്കി 1.24 ഒപ്പം അതിനു ശേഷമുള്ളവയും ഇൻസ്റ്റോൾ ചെയ്തിട്ടുള്ള ദൃശ്യരൂപങ്ങൾ സ്വതേ സജ്ജമാക്കുന്നില്ല ([https://www.mediawiki.org/wiki/Manual:Skin_autodiscovery ദൃശ്യരൂപം ഓട്ടോഡിസ്കവറി സഹായം] കാണുക). ഇൻസ്റ്റോൾ ചെയ്തിട്ടുള്ള ദൃശ്യരൂപങ്ങൾ സജ്ജമാക്കുന്നതിനായി ഇനിക്കൊടുക്കുന്ന വരികൾ <code>LocalSettings.php</code> എന്നതിലോട്ട് പകർത്തുക:\n\n<pre dir=\"ltr\">$3</pre>\n\n; <code>LocalSettings.php</code> താളിൽ മാറ്റം വരുത്തിയതേയുള്ളുവെങ്കിൽ:\n: ദൃശ്യരൂപങ്ങളുടെ പേരിൽ അക്ഷരപിശകുകളുണ്ടോയെന്ന് ആവർത്തിച്ച് പരിശോധിക്കുക.",
+       "default-skin-not-found-no-skins": "അയ്യോ! <code dir=\"ltr\"> $wgDefaultSkin</code> നിർവചിക്കപ്പെട്ടതുപ്രകാരമുള്ള താങ്കളുടെ വിക്കിയുടെ സ്വതേയുള്ള ദൃശ്യരൂപമായ <code>$1</code>, ലഭ്യമല്ല.\n\nതാങ്കൾ ദൃശ്യരൂപങ്ങളൊന്നും ഇൻസ്റ്റോൾ ചെയ്തിട്ടില്ല.\n\n; താങ്കൾ മീഡിയവിക്കി ഇൻസ്റ്റോൾ ചെയ്തതേ അല്ലെങ്കിൽ അപ്‌ഗ്രേഡ് ചെയ്തതേ ഉള്ളുവെങ്കിൽ:\n: ഗിറ്റിൽ നിന്ന് അല്ലെങ്കിൽ മറ്റെങ്കിലും മാർഗ്ഗം ഉപയോഗിച്ച് സോഴ്സ് കോഡ് നേരിട്ട് ഉപയോഗിക്കുകയായിരിന്നെങ്കിൽ ഇത് സംഭവിച്ചേക്കാം. [https://www.mediawiki.org/wiki/Category:All_skins mediawiki.org's ദൃശ്യരൂപ ഡയറക്ടറിയിൽ നിന്ന്], ഇനിക്കൊടുക്കുന്ന മാർഗ്ഗങ്ങൾ ഉപയോഗിച്ച് ഏതാനം ദൃശ്യരൂപങ്ങൾ ഇൻസ്റ്റോൾ ചെയ്യാൻ നോക്കുക:\n:* [https://www.mediawiki.org/wiki/Download ടാർബോൾ ഇൻസ്റ്റോളർ] ഡൗൺലോഡ് ചെയ്യുക, അതിൽ നിരവധി ദൃശ്യരൂപങ്ങളും അനുബന്ധങ്ങളും ഉൾപ്പെടുത്തിയിരിക്കുന്നു. അതിൽ നിന്നും താങ്കൾക്ക് <code>skins/</code> ഡയറക്ടറി പകർത്താവുന്നതാണ്.\n:* താങ്കളുടെ മീഡിയവിക്കി ഇൻസ്റ്റലേഷന്റെ <code dir=\"ltr\">skins/</code> ഡയറക്ടറിയിലേക്ക് ഗിറ്റ് ഉപയോഗിച്ച് <code>mediawiki/skins/*</code> റെപ്പോസിറ്ററികളിലൊന്ന് ക്ലോൺ ചെയ്യുക.\n: താങ്കളൊരു മീഡിയവിക്കി ഡവലപ്പറാണെങ്കിൽ ഇത് താങ്കളുടെ ഗിറ്റ് ഡെപ്പോസിറ്ററിയെ ബാധിക്കുന്നതല്ല. ദൃശ്യരൂപങ്ങൾ എങ്ങനെ ക്രമീകരിക്കാം എന്നും സ്വതേ വേണ്ടത് എങ്ങനെ സജ്ജമാക്കാം എന്നും [https://www.mediawiki.org/wiki/Manual:Skin_configuration ദൃശ്യരൂപം സജ്ജമാക്കൽ സഹായിയിൽ] കാണുക.",
        "default-skin-not-found-row-enabled": "* <code>$1</code> / $2 (സജ്ജം)",
        "default-skin-not-found-row-disabled": "* <code>$1</code> / $2 ('''സജ്ജമല്ല''')"
 }
index a65ecb6..963283c 100644 (file)
        "protect-othertime": "Inny okres",
        "protect-othertime-op": "inny okres",
        "protect-existing-expiry": "Obecny czas wygaśnięcia: $2 o $3",
+       "protect-existing-expiry-infinity": "Obecny czas wygaśnięcia: nieskończony",
        "protect-otherreason": "Inny lub dodatkowy powód",
        "protect-otherreason-op": "Inny powód",
        "protect-dropdown": "*Najczęstsze powody zabezpieczenia\n** Częste wandalizmy\n** Częste spamowanie\n** Wojna edycyjna\n** Wygłupy",
index 8a34252..32895d7 100644 (file)
        "movepagetalktext": "La pàgina ëd discussion tacà a costa pàgina d'artìcol, se a-i é, a sarà tramudà n'automatich ansema a l'artìcol, '''gavà costi cas-sì''':\n*quand as tramuda la pàgina tra diferent spassi nominaj,\n*quand na pàgina ëd discussion nen veujda a-i é già për ël nòm neuv, ò pura\n*a l'ha desselessionà ël quadrèt ëd conferma ambelessì-sota.\n\nAnt costi cas-sì, se a chërd dë felo, a-j farà da manca dë tramudesse la pàgina ëd discussion daspërchiel, a man.",
        "movearticle": "Cangeje nòm a l'artìcol:",
        "moveuserpage-warning": "'''Atension:''' A sta për tramudé na pàgina d'utent. Për piasì ch'a nòta che a sarà tramudà mach la pàgina e che l'utent a sarà ''pa'' arbatjà.",
+       "movecategorypage-warning": "<strong>Atension:</strong> A l'é a brus ëd tramudé na pàgina ëd categorìa. Për piasì, ch'a ten-a da ment che mach la pàgina a sarà tramudà e che tute le pàgine ant la veja categorìa a saran <em>nen</em> tramudà an cola neuva.",
        "movenologintext": "A venta esse n'Utent registrà e esse [[Special:UserLogin|rintrà ant ël sistema]]\npër podèj tramudé na pàgina.",
        "movenotallowed": "A l'ha pa ij përmess dont a fa da manca për tramudé le pàgine.",
        "movenotallowedfile": "A l'ha pa ij përmess për tramudé j'archivi.",
        "cant-move-user-page": "A l'ha pa ij përmess për tramudé le pàgine d'utent (gavà le sot-pàgine).",
        "cant-move-to-user-page": "A l'ha pa ël përmess për tramudé na pàgina a na pàgina utent (gavà a na sot-pàgina utent).",
+       "cant-move-category-page": "A l'ha nen ël përmess ëd tramudé le pàgine ëd categorìa.",
+       "cant-move-to-category-page": "A l'ha nen ël përmess ëd tramudé na pàgina a na pàgina ëd categorìa.",
        "newtitle": "Neuv tìtol ëd",
        "move-watch": "Ten-e sot-euj la pàgina sorgiss e la pàgina selessionà",
        "movepagebtn": "Tramudé la pàgina",
        "import": "Amportassion ëd pàgine",
        "importinterwiki": "Amportassion da wiki diferente",
        "import-interwiki-text": "Che a selession-a na wiki e ël tìtol dla pàgina da amporté.\nDate dle revision e stranòm dj'editor a resteran piàjit sù 'cò lor.\nTute j'amportassion antra wiki diferente a resto marcà ant ël [[Special:Log/import|Registr dj'amportassion]].",
+       "import-interwiki-sourcewiki": "Wiki sorgiss:",
+       "import-interwiki-sourcepage": "Pàgina sorgiss:",
        "import-interwiki-history": "Copié tute le revision ëd la stòria ëd costa pàgina",
        "import-interwiki-templates": "Anserì tùit jë stamp",
        "import-interwiki-submit": "Amporté",
        "import-upload": "Cariament ëd dat XML",
        "import-token-mismatch": "Pèrdita dij dat ëd session.\nPër piasì, ch'a preuva torna.",
        "import-invalid-interwiki": "As peul pa amportesse da la wiki spessificà.",
-       "import-error-edit": "La pàgina «$1» a l'é pa stàita amportà përchè chiel a peul pa modifichela.",
+       "import-error-edit": "La pàgina «$1» a l'era pa stàita amportà përchè chiel a peul pa modifichela.",
        "import-error-create": "La pàgina «$1» a l'é pa stàita amportà përchè chiel a peul pa creela.",
        "import-error-interwiki": "La pàgina «$1» a l'é pa amportà përchè sò nòm a l'é arzervà për na liura esterna (antërwiki).",
        "import-error-special": "La pàgina «$1» a l'é pa amportà përchè a ponta a në spassi nominal ch'a përmët pa dle pàgine.",
index 956849e..5c5683a 100644 (file)
        "protect-cantedit": "Used as error message when changing the protection levels of the page.",
        "protect-othertime": "Used on the page protection form as label for the following input field (text)\n{{Identical|Other time}}",
        "protect-othertime-op": "Used on the page protection form in the drop down menu\n{{Identical|Other time}}",
-       "protect-existing-expiry": "Shows the existing expiry time in the drop down menu of the protection form ([{{canonicalurl:User:Raymond/test|action=unprotect}} example])\n\nParameters:\n* $1 - (Unused) date and time of the existing expiry time (kept for backward compatibility purposes)\n* $2 - date of the existing expiry time\n* $3 - time of the existing expiry time",
+       "protect-existing-expiry": "Shows the existing expiry time in the drop down menu of the protection form ([{{canonicalurl:User:Raymond/test|action=unprotect}} example])\n\nParameters:\n* $1 - (Unused) date and time of the existing expiry time (kept for backward compatibility purposes)\n* $2 - date of the existing expiry time\n* $3 - time of the existing expiry time\n\nSee also:\n* {{msg-mw|protect-existing-expiry-infinity}}",
+       "protect-existing-expiry-infinity": "Shows the existing expiry time in the drop down menu of the protection form, in the special case that it is infinity\n\nSee also:\n* {{msg-mw|protect-existing-expiry}}",
        "protect-otherreason": "Shown on the page protection form as label for the following input field (text)\n{{Identical|Other/additional reason}}",
        "protect-otherreason-op": "Shown on the page protection form in the drop down menu\n{{Identical|Other reason}}",
        "protect-dropdown": "Shown on the page protection form as drop down menu for protection reasons.\n\n* <code><nowiki>* Groupname</nowiki></code> - defines a new group\n* <code><nowiki>** Reason</nowiki></code> - defines a reason in this group",
index 586237a..8bb3a02 100644 (file)
        "protect-othertime": "Другое время:",
        "protect-othertime-op": "другое время",
        "protect-existing-expiry": "Текущее время окончания: $2, $3",
+       "protect-existing-expiry-infinity": "Текущее время окончания: бесконечно",
        "protect-otherreason": "Другая причина/дополнение:",
        "protect-otherreason-op": "Другая причина",
        "protect-dropdown": "* Типовые причины защиты\n** частый вандализм\n** чрезмерный спам\n** непродуктивная война правок\n** популярная страница",
index 0dd8089..076b671 100644 (file)
        "revdelete-hide-text": "Testu de sa versione",
        "revdelete-hide-image": "Cua su cuntènnidu de su documentu",
        "revdelete-hide-comment": "Modìfica s'ogetu",
+       "revdelete-radio-same": "(non cambiare)",
        "revdelete-radio-set": "Cua",
        "revdelete-radio-unset": "Ammustra",
        "revdelete-log": "Motivu:",
        "prefs-watchlist-edits-max": "Cantidade màssima: 1000",
        "prefs-misc": "Àteras preferèntzias",
        "prefs-resetpass": "Càmbia password",
+       "prefs-changeemail": "Càmbia indiritzu email",
        "prefs-email": "Sèberos pro sa email",
        "prefs-rendering": "Aparèntzia",
        "saveprefs": "Sarva preferèntzias",
        "sourceurl": "Diretzione originària:",
        "destfilename": "Nùmene de su file de destinatzione:",
        "upload-description": "Descritzione de su file",
+       "watchthisupload": "Annota custu documentu",
        "upload-success-subj": "Carrigamentu acabau",
        "upload-failure-subj": "Problema de carrimentu",
        "upload-file-error": "Faddina a intru",
        "listfiles_size": "Mannesa in byte",
        "listfiles_description": "Descritzione",
        "listfiles_count": "Versiones",
+       "listfiles-latestversion": "Versione atuale",
        "listfiles-latestversion-yes": "Eja",
        "listfiles-latestversion-no": "No",
        "file-anchor-link": "File",
        "filedelete-success": "Su file '''$1''' est istadu fuliau.",
        "filedelete-otherreason": "Motivu diversu o agiuntivu:",
        "filedelete-reason-otherlist": "Àteru motivu",
+       "filedelete-edit-reasonlist": "Càmbia is motivos de sa burradura",
        "mimesearch": "Chirca MIME",
        "mimetype": "Genia MIME:",
        "download": "scàrriga",
+       "unwatchedpages": "Pàginas no annotadas",
        "listredirects": "Lista de totu is redirects",
+       "listduplicatedfiles": "Lista de documentos dopios",
+       "unusedtemplates": "Templates no impreados",
        "unusedtemplateswlh": "àteros ligòngios",
        "randompage": "Pàgina a sa tzurpa",
        "randomincategory-category": "Categoria:",
        "statistics": "Statìsticas",
        "statistics-header-pages": "Statìsticas subra is pàginas",
+       "statistics-header-edits": "Càmbia is statìsticas",
+       "statistics-header-views": "Càstia is statìsticas",
        "statistics-header-users": "Statìsticas subra is usuàrios",
+       "statistics-header-hooks": "Àteras statìsticas",
+       "statistics-articles": "Pàginas de càbidos",
        "statistics-pages": "Pàginas",
+       "statistics-files": "Documentos carrigados",
        "pageswithprop-submit": "Bae",
        "doubleredirects": "Redirects dòpios",
        "doubleredirectstext": "Custa pàgina cuntenet una lista de pàginas ki re-indiritzant a àteras pàginas de re-indiritzamentu.\nOgni lìnia cuntenet ligàmines a su primu e a su de duos re-indiritzamentu, aici comente sa prima lìnia de sa de duos re-indiritzamentos, chi de sòlitu adòbiat s'artìculu \"beru\", a sa cale fintzas su primu re-indiritzamentu dia depet puntare.\nIs re-indiritzamentos <del>cantzellados</del> sunt stados curretos.",
        "withoutinterwiki-submit": "Ammustra",
        "nbytes": "$1 {{PLURAL:$1|byte|bytes}}",
        "ncategories": "$1 {{PLURAL:$1|categoria|categorias}}",
+       "ninterwikis": "$1 {{PLURAL:$1|interwiki|interwikis}}",
        "nlinks": "$1 {{PLURAL:$1|ligàmene|ligàmenes}}",
        "nmembers": "$1 {{PLURAL:$1|cumponente|cumponentes}}",
        "nrevisions": "$1 {{PLURAL:$1|revisione|revisiones}}",
index 4e9bb7c..3bb33d4 100644 (file)
        "protect-othertime": "Drugačen čas:",
        "protect-othertime-op": "drugačen čas",
        "protect-existing-expiry": "Obstoječ čas izteka: $3, $2",
+       "protect-existing-expiry-infinity": "Obstoječ čas izteka: neskončno",
        "protect-otherreason": "Drug/dodaten razlog:",
        "protect-otherreason-op": "Drug razlog",
        "protect-dropdown": "*Pogosti razlogi za zaščito\n** Prekomeren vandalizem\n** Vztrajno dodajanje reklamnih povezav\n** Neproduktivne urejevalske vojne\n** Zelo obiskana stran",
index 7176391..67c0882 100644 (file)
        "undeleteinvert": "Обрни избор",
        "undeletecomment": "Разлог:",
        "undeletedrevisions": "{{PLURAL:$1|Измена је враћена|$1 измене су враћене|$1 измена је враћено}}",
-       "undeletedrevisions-files": "$1 {{PLURAL:$1|измена|измене|измена}} и $2 {{PLURAL:$2|датотека|датотеке|датотека}} је враћено",
+       "undeletedrevisions-files": "$1 {{PLURAL:$1|1 измена|измене|измена}} и $2 {{PLURAL:$2|1 датотека је враћена|датотеке су враћене|датотека је враћено}}",
        "undeletedfiles": "{{PLURAL:$1|Датотека је враћена|$1 датотеке су враћене|$1 датотека је враћено}}",
        "cannotundelete": "Враћање није успело:\n$1",
        "undeletedpage": "'''Страница $1 је враћена'''\n\nПогледајте [[Special:Log/delete|историју брисања]] за записе о скорашњим брисањима и враћањима.",
        "watchlistedit-clear-titles": "Наслови:",
        "watchlistedit-clear-submit": "Испразни списак надгледања (Ово је трајно!)",
        "watchlistedit-clear-done": "Ваш списак надгледања је испражњен.",
-       "watchlistedit-clear-removed": "{{PLURAL:$1|1 наслов је уклоњен|$1 наслова је уклоњено}}:",
+       "watchlistedit-clear-removed": "{{PLURAL:$1|1 Ð½Ð°Ñ\81лов Ñ\98е Ñ\83клоÑ\9aен|$1 Ð½Ð°Ñ\81лова Ñ\81Ñ\83 Ñ\83клоÑ\9aена|$1 Ð½Ð°Ñ\81лова Ñ\98е Ñ\83клоÑ\9aено}}:",
        "watchlistedit-too-many": "Има превише страница за приказ овде.",
        "watchlisttools-clear": "испразни списак надгледања",
        "watchlisttools-view": "прикажи сродне измене",
index dadc80d..c13f5c5 100644 (file)
        "undeleteinvert": "Obrni izbor",
        "undeletecomment": "Razlog:",
        "undeletedrevisions": "{{PLURAL:$1|Izmena je vraćena|$1 izmene su vraćene|$1 izmena je vraćeno}}",
-       "undeletedrevisions-files": "$1 {{PLURAL:$1|izmena|izmene|izmena}} i $2 {{PLURAL:$2|datoteka|datoteke|datoteka}} je vraćeno",
+       "undeletedrevisions-files": "$1 {{PLURAL:$1|1 izmena|izmene|izmena}} i $2 {{PLURAL:$2|1 datoteka je vraćena|datoteke su vraćene|datoteka je vraćeno}}",
        "undeletedfiles": "{{PLURAL:$1|Datoteka je vraćena|$1 datoteke su vraćene|$1 datoteka je vraćeno}}",
        "cannotundelete": "Vraćanje nije uspelo:\n$1",
        "undeletedpage": "'''Stranica $1 je vraćena'''\n\nPogledajte [[Special:Log/delete|istoriju brisanja]] za zapise o skorašnjim brisanjima i vraćanjima.",
        "watchlistedit-clear-titles": "Naslovi:",
        "watchlistedit-clear-submit": "Isprazni spisak nadgledanja (Ovo je trajno!)",
        "watchlistedit-clear-done": "Vaš spisak nadgledanja je ispražnjen.",
-       "watchlistedit-clear-removed": "{{PLURAL:$1|1 naslov je uklonjen|$1 naslova je uklonjeno}}:",
+       "watchlistedit-clear-removed": "{{PLURAL:$1|1 naslov je uklonjen|$1 naslova su uklonjena|$1 naslova je uklonjeno}}:",
        "watchlisttools-clear": "isprazni spisak nadgledanja",
        "watchlisttools-view": "prikaži srodne izmene",
        "watchlisttools-edit": "prikaži i uredi spisak nadgledanja",
index 0002de3..4d9e037 100644 (file)
@@ -20,9 +20,9 @@
        "tog-extendwatchlist": "Legaan béréndélan ngarah sakabéh parobahanana kaawaskeun",
        "tog-usenewrc": "Parobahan grup dumasar kaca dina béréndélan anyar robah jeung awaskeuneun (maké JavaScript)",
        "tog-numberheadings": "Nomeran lulugu sacara otomatis",
-       "tog-showtoolbar": "Témbongkeun ''toolbar'' édit (JavaScript)",
-       "tog-editondblclick": "Édit kaca ku klik ganda (JavaScript)",
-       "tog-editsectiononrightclick": "Fungsikeun ngédit sub-bagean kalawan klik-katuhu dina judul bagean (JavaScript)",
+       "tog-showtoolbar": "Témbongkeun tulbar édit",
+       "tog-editondblclick": "Édit kaca ku klik ganda",
+       "tog-editsectiononrightclick": "Fungsikeun ngédit sub-bagean kalawan klik-katuhu dina judul bagéan",
        "tog-watchcreations": "Tambahkeun kaca-kaca jieunan kuring jeung berkas muatan kuring kana awaskeuneun",
        "tog-watchdefault": "Tambahkeun kaca jeung berkas anu diédit ku kuring kana awaskeuneun",
        "tog-watchmoves": "Tambahkeun kaca jeung berkas anu dipindahkeun ka awaskeuneun",
@@ -37,7 +37,7 @@
        "tog-shownumberswatching": "Témbongkeun jumlah nu ngawaskeun",
        "tog-oldsig": "Paraf nu geus aya:",
        "tog-fancysig": "Témbongkeun paraf salaku wikitext (tanpa tumbu otomatis)",
-       "tog-uselivepreview": "Paké pramidang saharita (JavaScript) (ujicoba)",
+       "tog-uselivepreview": "Paké pramidang saharita (ujicoba)",
        "tog-forceeditsummary": "Mun kotak ringkesan éditan masih kosong, béjaan!",
        "tog-watchlisthideown": "Sumputkeun éditan kuring dina daptar awaskeuneun",
        "tog-watchlisthidebots": "Sumputkeun éditan bot dina daptar awaskeuneun",
@@ -50,6 +50,7 @@
        "tog-showhiddencats": "Témbongkeun kategori nyumput",
        "tog-norollbackdiff": "Liwat béda sanggeus malikkeun révisi",
        "tog-useeditwarning": "Béjaan kuring lamun ninggalkeun kaca édit anu parobahanana can disimpen",
+       "tog-prefershttps": "Salawasna paké sambungan aman nalika asup log",
        "underline-always": "Salawasna",
        "underline-never": "Ulah",
        "underline-default": "Luyu jeung buhunna panyungsi",
@@ -65,7 +66,7 @@
        "thursday": "Kemis",
        "friday": "Jumaah",
        "saturday": "Saptu",
-       "sun": "Min",
+       "sun": "Ming",
        "mon": "Sen",
        "tue": "Sal",
        "wed": "Reb",
        "oct": "Okt",
        "nov": "Nop",
        "dec": "Dés",
+       "january-date": "$1 Januari",
+       "february-date": "$1 Pébruari",
+       "march-date": "$1 Maret",
+       "april-date": "$1 April",
+       "may-date": "$1 Méi",
+       "june-date": "$1 Juni",
+       "july-date": "$1 Juli",
+       "august-date": "$1 Agustus",
+       "september-date": "$1 Séptémber",
+       "october-date": "$1 Oktober",
+       "november-date": "$1 Nopémber",
+       "december-date": "$1 Désémber",
        "pagecategories": "{{PLURAL:$1|Kategori|Kategori}}",
        "category_header": "Artikel-artikel na kategori \"$1\"",
        "subcategories": "Subkategori",
        "newwindow": "(buka na jandéla anyar)",
        "cancel": "Bolay",
        "moredotdotdot": "Deui...",
-       "mypage": "Kaca kuring",
+       "morenotlisted": "Ieu béréndélan tacan lengkep.",
+       "mypage": "Kaca",
        "mytalk": "Obrolan",
        "anontalk": "Obrolan pikeun IP ieu",
        "navigation": "Pituduh",
        "actions": "Peta",
        "namespaces": "Spasi ngaran",
        "variants": "Varian",
+       "navigation-heading": "Ménu navigasi",
        "errorpagetitle": "Kasalahan",
        "returnto": "Balik deui ka $1.",
        "tagline": "Ti {{SITENAME}}",
        "permalink": "Tutumbu permanén",
        "print": "Citak",
        "view": "Tempo",
+       "view-foreign": "Tempo di $1",
        "edit": "Édit",
+       "edit-local": "Edit déskripsi lokal",
        "create": "Jieun",
+       "create-local": "Tambah déskripsi lokal",
        "editthispage": "Édit kaca ieu",
        "create-this-page": "Jieun kaca ieu",
        "delete": "Hapus",
        "deletethispage": "Hapus kaca ieu",
+       "undeletethispage": "Bolaykeun ngahapus ieu kaca",
        "undelete_short": "Bolaykeun ngahapus {{PLURAL:$1|hiji éditan|$1 éditan}}",
        "viewdeleted_short": "Témbongkeun {{PLURAL:$1|hiji éditan nu dihapus|$1 éditan nu dihapus}}",
        "protect": "Konci",
        "articlepage": "Témbongkeun kaca eusi",
        "talk": "Sawala",
        "views": "Témbongan",
-       "toolbox": "Kotak parabot",
+       "toolbox": "Parabot",
        "userpage": "Témbongkeun kaca pamaké",
        "projectpage": "Témbongkeun kaca proyék",
        "imagepage": "Tempo kaca gambar",
        "otherlanguages": "Dina séjén basa",
        "redirectedfrom": "(dipindahkeun ti $1)",
        "redirectpagesub": "Kaca alihan",
+       "redirectto": "Alihkeun ka:",
        "lastmodifiedat": "Kaca ieu panungtungan dirobah $2, $1.",
        "viewcount": "Kaca ieu geus dibuka {{PLURAL:$1|sakali|$1 kali}}.<br />",
        "protectedpage": "Kaca nu dikonci",
        "ok": "Heug",
        "retrievedfrom": "Disalin ti \"$1\"",
        "youhavenewmessages": "Anjeun boga $1 ($2).",
+       "youhavenewmessagesfromusers": "{{PLURAL:$4|Anjeun boga}} $1 ti {{PLURAL:$3|pamaké séjén|$3 pamaké}} ($2).",
+       "youhavenewmessagesmanyusers": "Anjeun boga $1 ti pamaké lian ($2).",
+       "newmessageslinkplural": "{{PLURAL:$1|obrolan anyar|obrolan anyar}}",
+       "newmessagesdifflinkplural": "{{PLURAL:$1|parobahan|999=parobahan}} panungtung",
        "youhavenewmessagesmulti": "Anjeun boga talatah anyar di $1",
        "editsection": "édit",
        "editold": "édit",
        "hidetoc": "sumputkeun",
        "collapsible-collapse": "Tilepkeun",
        "collapsible-expand": "Amparkeun",
+       "confirmable-confirm": "{{GENDER:$1|Anjeun}} geus yakin?",
+       "confirmable-yes": "Enya",
+       "confirmable-no": "Henteu",
        "thisisdeleted": "Témbongkeun atawa simpen deui $1?",
        "viewdeleted": "Témbongkeun $1?",
        "restorelink": "$1 {{PLURAL:$1|éditan|éditan}} dihapus",
        "nospecialpagetext": "<strong>Anjeun ménta kaca husus nu teu dipikawanoh.</strong>\nKaca husus anu bener bisa ditempo béréndélanana dina [[Special:SpecialPages|{{int:specialpages}}]].",
        "error": "Kasalahan",
        "databaseerror": "Kasalahan gudang data",
+       "databaseerror-query": "Kueri: $1",
+       "databaseerror-function": "Fungsi: $1",
+       "databaseerror-error": "Eror: $1",
        "laggedslavemode": "Awas: kandungan kaca bisa baé teu mutahir.",
        "readonly": "pangkalan data dikonci",
        "enterlockreason": "Asupkeun alesan pikeun ngonci, kaasup kira-kira iraha konci ieu rék dibuka",
        "viewsource-title": "Témbongkeun sumber pikeun $1",
        "actionthrottled": "Peta diwates",
        "actionthrottledtext": "Salaku tetengger anti-spam, anjeun teu diwenangkeun loba kitu peta dina jangka waktu anu sakitu heureutna. Mangga lajengkeun deui sanggeus sababaraha menit ka payun.",
-       "protectedpagetext": "Ieu kaca dikonci ngarah teu bisa dirobah.",
+       "protectedpagetext": "Ieu kaca dijaga tina éditan atawa peta lianna.",
        "viewsourcetext": "Anjeun bisa némbongkeun sarta nyalin sumber ieu kaca:",
        "viewyourtext": "Anjeun bisa némbongkeun sarta nyalin sumber '''éditan anjeun''' ka ieu kaca:",
        "protectedinterface": "Kaca ieu eusina teks antarmuka pikeun dipaké ku pakakas beyé sarta geus dikunci pikeun ngahindar ti kasalahan.",
        "namespaceprotected": "Anjeun teu ngabogaan hak pikeun ngédit kaca di ngaranspasi '''$1'''.",
        "customcssprotected": "Anjeun teu teu diwenangkeun pikeun ngédit ieu kaca CSS, sabab ngandung setélan pribadi kontributor séjén.",
        "customjsprotected": "Anjeun teu teu diwenangkeun pikeun ngédit ieu kaca JavaScript, sabab ngandung setélan pribadi kontributor séjén.",
+       "mycustomcssprotected": "Anjeun teu boga kawenangan pikeun ngédit kaca CSS ieu.",
+       "mycustomjsprotected": "Anjeun teu boga kawenangan pikeun ngédit kaca JavaScript ieu.",
+       "myprivateinfoprotected": "Anjeun teu boga kawenangan pikeun ngédit émbaran pribadi anjeun.",
+       "mypreferencesprotected": "Anjeun teu boga kawenangan pikeun ngédit préferénsi anjeun.",
        "ns-specialprotected": "Kaca dina ngaranspasi {{ns:special}} teu bisa di édit.",
        "titleprotected": "Ieu judul dikonci ku [[User:$1|$1]] kalawan alesan ''$2''.",
+       "filereadonlyerror": "Berkas \"$1\" teu bisa dirobah kusabab répositori \"$2\" keur dina mode ukur-maca.\n\nKuncén anu ngonci méré alesan: \"$3\".",
+       "exception-nologin": "Henteu asup log",
+       "exception-nologin-text": "Mangga asup log pikeun bisa asup atawa ngarobah ieu kaca.",
        "virus-badscanner": "Kasalahan konfigurasi: panyekén virus teu dipikawanoh: ''$1''",
        "virus-scanfailed": "nyekén gagal (kode $1)",
        "virus-unknownscanner": "antivirus teu dipikawanoh:",
        "logouttext": "'''Anjeun ayeuna geus kaluar log.'''\n\nAnjeun bisa tetep migunakeun {{SITENAME}} bari anonim, atawa bisa <span class='plainlinks'>[$1 asup log deui]</span> salaku pamaké nu sarua atawa nu séjén deui.\nMangkahadé, sababaraha kaca bakal tetep némbongkeun saolah-olah anjeun asup log kénéh nepi ka anjeun ngosongkeun ''cache'' panyungsi anjeun.",
+       "welcomeuser": "Bagéa, $1!",
+       "welcomecreation-msg": "Akun anjeun geus dijieun.\nLamun minat, Anjeun bisa ngarobah [[Special:Preferences|préferénsi]] {{SITENAME}}.",
        "yourname": "Sandiasma:",
+       "userlogin-yourname": "Sandiasma",
+       "userlogin-yourname-ph": "Asupkeun sandiasma anjeun",
+       "createacct-another-username-ph": "Asupkeun sandiasma",
        "yourpassword": "Sandi anjeun",
+       "userlogin-yourpassword": "Kecap sandi",
+       "userlogin-yourpassword-ph": "Asupkeun kecap sandi anjeun",
+       "createacct-yourpassword-ph": "Asupkeun kecap sandi",
        "yourpasswordagain": "Ketik deui sandi anjeun",
+       "createacct-yourpasswordagain": "Konfirmasi kecap sandi",
+       "createacct-yourpasswordagain-ph": "Asupkeun deui kecap sandi",
        "remembermypassword": "Apalkeun login kuring dina ieu komputer (pikeun paling lila $1 {{PLURAL:$1|poé|poé}})",
+       "userlogin-signwithsecure": "Paké sambungan aman",
        "yourdomainname": "Domain anjeun",
+       "password-change-forbidden": "Anjeun teu bisa ngarobah kecap sandi dina ieu wiki.",
        "externaldberror": "Aya kasalahan dina pangkalan data oténtikasi luar, atawa anjeun mémang teu diwenangkeun pikeun ngaropéa rekening luar anjeun.",
        "login": "Asup log",
        "nav-login-createaccount": "Nyieun akun/asup log",
        "logout": "Kaluar log",
        "userlogout": "Kaluar log",
        "notloggedin": "Can asup log",
+       "userlogin-noaccount": "Teu boga akun?",
+       "userlogin-joinproject": "Ngiluan {{SITENAME}}",
        "nologin": "Teu boga akun? '''$1'''.",
        "nologinlink": "Jieun akun",
        "createaccount": "Jieun akun",
        "gotaccount": "Geus boga akun? '''$1'''.",
        "gotaccountlink": "Asup log",
        "userlogin-resetlink": "Poho akun sorangan?",
-       "createaccountmail": "ku surélék",
+       "userlogin-resetpassword-link": "Poho kecap sandi?",
+       "userlogin-helplink2": "Pitulung asup log",
+       "createacct-emailrequired": "Alamat surélék:",
+       "createacct-emailoptional": "Alamat surélék (teu wajib)",
+       "createacct-email-ph": "Asupkeun alamat surélék anjeun",
+       "createacct-another-email-ph": "Asupkeun alamat surélék",
+       "createaccountmail": "Paké kecap sandi acak sarta kirim ka alamat surélék",
+       "createacct-realname": "Ngaran asli (teu wajib)",
        "createaccountreason": "Alesan:",
+       "createacct-reason": "Alesan",
+       "createacct-reason-ph": "Naha bet nyieun akun séjén",
+       "createacct-captcha": "Pamariksaan kaamanan",
+       "createacct-imgcaptcha-ph": "Asupkeun téks anu kabaca di luhur",
+       "createacct-submit": "Jieun akun anjeun",
+       "createacct-another-submit": "Jieun akun séjén",
+       "createacct-benefit-heading": "{{SITENAME}} téh dijieun ku jalma-jalma siga anjeun.",
+       "createacct-benefit-body1": "{{PLURAL:$1|édit|édit}}",
+       "createacct-benefit-body2": "{{PLURAL:$1|kaca|kaca}}",
+       "createacct-benefit-body3": "{{PLURAL:$1|kontributor|kontributor}} panungtung",
        "badretype": "Sandi nu diasupkeun teu cocog.",
        "userexists": "Sandiasma nu diasupkeun geus aya nu maké.\nMangga pilih sandiasma nu séjén.",
        "loginerror": "Kasalahan asup log",
        "passwordtooshort": "Sandina kudu diwangun ku sahanteuna {{PLURAL:$1|1 karakter|$1 karakter}}.",
        "password-name-match": "Sandi anjeun kudu béda ti landihan.",
        "password-login-forbidden": "Sandiasma jeung sandina teu bisa dipaké.",
-       "mailmypassword": "Kirim sandi anyar ngaliwatan surélék",
+       "mailmypassword": "Setél ulang kecap sandi",
        "passwordremindertitle": "Pangéling sandi ti {{SITENAME}}",
        "passwordremindertext": "Aya (jigana anjeun ti alamat IP $1) nu ménta sangkan dikiriman sandi anyar asup log {{SITENAME}} ($4). Saheulaanan, sandi anyar keur pamaké \"$2\" ayeuna diganti jadi \"$3\". Anjeun kudu asup log sarta ngarobah sandi anjeun ayeuna. Ieu sandi bakal kadaluwarsa dina {{PLURAL:$5|sapoé|$5 poé}}.\n\nMun pamundut ieu datang ti nu séjén, atawa mun anjeun geus inget sandi anu tadina poho, sarta teu hayang ngarobah sandina, anjeun teu kudu ngawaro kana ieu surat sarta bisa tetep maké sandi anu ti heula.",
        "noemail": "Teu aya alamat surélék karékam pikeun \"$1\".",
        "noemailcreate": "Anjeun kudu nyadiakeun alamat surélék anu bener",
        "passwordsent": "Sandi anyar geus dikirim ka alamat surélék nu kadaptar pikeun \"$1\". Mangga asup log deui satutasna katarima.",
        "blocked-mailpassword": "Alamat IP anjeun dipeungpeuk, moal bisa ngédit, and so\nis not allowed to use the password recovery function to prevent abuse.",
-       "eauthentsent": "Surélék konfirmasi geus dikirim ka alamat bieu. Méméh aya surat séjén asup ka rekeningna, anjeun kudu nuturkeun pituduh na surélékna pikeun ngonfirmasi yén rekening éta téh bener nu anjeun.",
+       "eauthentsent": "Surélék konfirmasi geus dikirim ka alamat bieu.\nMéméh aya surat séjén asup ka akunna, anjeun kudu nuturkeun pituduh dina surélékna pikeun mastikeun yén akun éta téh bener boga anjeun.",
        "throttled-mailpassword": "Hiji panginget kecap sandi geus dikirimkeun dina {{PLURAL:$1|jam|$1 jam}} pamungkas.\nPikeun ngahindar disalahgunakeun, ngan hiji kecap sandi anu baris dikirimkeun saban {{PLURAL:$1|jam|$1 jam}}.",
        "mailerror": "Kasalahan ngirim surat: $1",
        "acct_creation_throttle_hit": "Punten,pamaké alamat IP anjeun geus nyieun {{PLURAL:$1|1 rekening|$1 rekening}} dina sapoé ieu. mangrupa jumlah nu di idinan dina sapoé.\nanjeun teu bisa nyieun deui samentara waktu.",
-       "emailauthenticated": "Alamat surélék anjeun geus dioténtikasi dina $3, $2.",
-       "emailnotauthenticated": "Alamat surélék anjeun <strong>can dioténtikasi</strong>. Moal aya surélék nu bakal dikirim pikeun fitur-fitur di handap ieu.",
+       "emailauthenticated": "Alamat surélék anjeun geus dikonfirmasi $2 tabuh $3.",
+       "emailnotauthenticated": "Alamat surélék anjeun can dikonfirmasi.\nMoal aya surélék nu bakal dikirim pikeun fitur-fitur di handap ieu.",
        "noemailprefs": "Teu aya alamat surélék, fitur di handap moal bisa jalan.",
        "emailconfirmlink": "Konfirmasi alamat surélék anjeun",
        "invalidemailaddress": "Alamat surélék teu bisa ditarima sabab formatna salah.\nMangga lebetkeun alamat nu formatna bener atawa kosongkeun baé.",
        "cannotchangeemail": "Alamat surat-é akun hanteu bisa dirobah di ieu wiki.",
+       "emaildisabled": "Ieu loka teu bisa ngirim surélék.",
        "accountcreated": "Rekening geus dijieun.",
        "accountcreatedtext": "Rekening pamaké pikeun $1 geus dijieun.",
        "createaccount-title": "Nyieun rekening keur {{SITENAME}}",
        "login-abort-generic": "Login gagal - Dibolaykeun",
        "loginlanguagelabel": "Basa: $1",
        "suspicious-userlogout": "Pamundut anjeun pikeun kaluar log ditolak ku sabab sigana dikirim ku pangaprak buntu atawa ''cache'' proxi.",
+       "pt-login": "Asup log",
+       "pt-login-button": "Asup log",
+       "pt-createaccount": "Jieun akun",
+       "pt-userlogout": "Kaluar log",
        "php-mail-error-unknown": "Kasalahan nu teu kanyahoan dina fungsi PHP surélék().",
        "user-mail-no-addy": "Nyobaan ngirim surélék tanpa alamat.",
        "changepassword": "Robah sandi",
        "changeemail-oldemail": "Alamat surélék ayeuna:",
        "changeemail-newemail": "Alamat surélék anyar:",
        "changeemail-none": "(euweuh)",
+       "changeemail-password": "Kecap sandi {{SITENAME}} Anjeun:",
        "changeemail-submit": "Ganti surélék",
        "changeemail-cancel": "Bolay",
+       "resettokens-tokens": "Token:",
        "bold_sample": "Téks kandel",
        "bold_tip": "Téks kandel",
        "italic_sample": "Tulisan déngdék",
        "token_suffix_mismatch": "'''Éditan anjeun ditolak sabab aplikasi klien Anjeun ngarobah karakter tanda baca dina éditan. Éditan kasebut ditolak keur nyegah kasalahan dina artikel téks. Hal ieu kadang-kadang kajadian lamun Anjeun maké proksi anonim basis web nu masalah.'''",
        "edit_form_incomplete": "'''Sawatara bagian tina wangun éditan teu nepi ka sérver; pariksa deui naha éditan Anjeun tetep gembleng sarta cobaan deui.'''",
        "editing": "Ngédit $1",
+       "creating": "Nyieun $1",
        "editingsection": "Ngédit $1 (bagian)",
        "editingcomment": "Ngédit $1 (bagian anyar)",
        "editconflict": "Konflik éditan: $1",
        "edit-gone-missing": "Kaca teu bisa dianyarkeun,\nsigana kusabab geus dihapus.",
        "edit-conflict": "Éditan bantrok",
        "edit-no-change": "Éditan anjeun teu diwaro, kusabab taya nu robah dina tulisanana.",
+       "postedit-confirmation-saved": "Éditan anjeun tos disimpen.",
        "edit-already-exists": "Teu bisa nyieun kaca anyar.\nArtikelna geus aya.",
+       "defaultmessagetext": "Téks ti dituna",
+       "invalid-content-data": "Data eusi henteu valid",
+       "content-not-allowed-here": "Eusi \"$1\" teu diijinan di kaca [[$2]]",
+       "content-model-wikitext": "wikitéks",
+       "content-model-text": "téks polos",
+       "content-model-javascript": "JavaScript",
+       "content-model-css": "CSS",
        "expensive-parserfunction-warning": "Inget!: Kaca ieu ngandung réa teuing maké fungsi ''parser''.\n\nAyeuna aya {{PLURAL:$1|$1 panggilan|$1 panggilan}}, sakuduna kurang ti $2 {{PLURAL:$2|panggilan|panggilan}}.",
        "expensive-parserfunction-category": "Kaca kalawan réa teuing maké fungsi parser",
        "post-expand-template-inclusion-warning": "Inget! : Ukuran citakan anu dipaké badag teuing.\nSawatara citakan baris teu diasupkeun.",
        "histlegend": "Pilihan béda: tandaan wadah buleud vérsina pikeun ngabandingkeun sarta pencét énter atawa tombol di handap.<br />\nKaterangan: (kiw) = bédana jeung vérsi kiwari,\n(ahir) = bédana jeung vérsi nu harita, m = éditan minor.",
        "history-fieldset-title": "Sungsi jujutan",
        "history-show-deleted": "Ukur nu dihapus",
-       "histfirst": "Pangheubeulna",
-       "histlast": "Pangahirna",
+       "histfirst": "pangheubeulna",
+       "histlast": "panganyarna",
        "historysize": "($1 {{PLURAL:$1|bit|bit}})",
        "historyempty": "(kosong)",
        "history-feed-title": "Sajarah révisi",
        "revdelete-confirm": "Mangga geura konfirmasi yen Anjeun gaduh maksad pikeun ngalakukeun hal ieu, paham kana konsekwensina, tur nu dilakukeun ieu teh luyu sareng [[{{MediaWiki:Policy-url}}|kawijakanana]]",
        "revdelete-suppress-text": "Nyumputkeun revisi '''ukur''' bisa digunakeun keur kasus-kasus di handap ieu:\n* Informasi nu boga potensi mitenah\n* Informasi pribadi nu teu pantes\n*: ''alamat imah katut nomer telepon, nomer kartu identitas, jeung lian-liana.''",
        "revdelete-legend": "Setél réstriksi révisi:",
-       "revdelete-hide-text": "Sumputkeun téks révisi",
+       "revdelete-hide-text": "Téks révisi",
        "revdelete-hide-image": "Sumputkeun eusi gambar",
        "revdelete-hide-name": "Sumputkeun lampah sarta udagan",
        "revdelete-hide-comment": "Sumputkeun koméntar ngédit",
        "revdelete-hide-user": "Sumputkeun ngaran pamaké/IP éditor",
        "revdelete-hide-restricted": "Sumputkeun data boh ti kuncén atawa nu séjénna",
        "revdelete-radio-same": "(ulah dirobah)",
-       "revdelete-radio-set": "Enya",
-       "revdelete-radio-unset": "Ulah",
+       "revdelete-radio-set": "Nyumput",
+       "revdelete-radio-unset": "Némbongan",
        "revdelete-suppress": "Sumputkeun ogé ti kuncén",
        "revdelete-unsuppress": "Hapus watesan kana révisi anu geus dipulangkeun",
        "revdelete-log": "Alesan:",
        "revdelete-submit": "Larapkeun kana {{PLURAL:$1|révisi|révisi}} nu dipilih",
-       "revdelete-success": "Pangaturan nyumpukeun révisi junun dilarapkeun.",
+       "revdelete-success": "<strong>Visibilitas révisi geus dimutahirkeun.</strong>",
        "revdelete-failure": "'''Visibilitas révisi teu bisa diapdét:'''\n$1",
        "logdelete-success": "Log pangatur nyumputkeun junun dilarapkeun.",
        "logdelete-failure": "'''Visibilitas log teu bisa disét:'''\n$1",
        "search-section": "(bagean $1)",
        "search-suggest": "Meureun maksud Anjeun nyaéta: $1",
        "search-interwiki-caption": "Proyék sawargi",
-       "search-interwiki-default": "$1 hasil:",
+       "search-interwiki-default": "Hasil ti $1:",
        "search-interwiki-more": "(saterusna)",
        "search-relatedarticle": "Patula-patali",
        "searchrelated": "patula-patali",
        "searchall": "sadayana",
        "showingresults": "Di handap ieu némbongkeun {{PLURAL:$1|'''1''' hasil|'''$1''' hasil}}, dimimitianku  #'''$2'''.",
-       "showingresultsheader": "{{PLURAL:$5|Hasil '''$1''' ti '''$3'''|Hasil '''$1 - $2''' ti '''$3'''}} pikeun '''$4'''",
        "search-nonefound": "Euweuh hasil nu cocog jeung kueri.",
        "powersearch-legend": "Panéangan tuluy",
        "powersearch-ns": "Téangan di ngaranspasi:",
        "skin-preview": "Pramidang",
        "datedefault": "Tanpa préferénsi",
        "prefs-labs": "Fitur Labs",
+       "prefs-user-pages": "Kaca pamaké",
        "prefs-personal": "Data pamaké",
        "prefs-rc": "Panémbong robahan anyar jeung tukung",
        "prefs-watchlist": "Awaskeuneun",
        "timezoneregion-indian": "Samudra Indonésia",
        "timezoneregion-pacific": "Samudra Pasifik",
        "allowemail": "Buka koropak pikeun nampa surélék ti nu séjén",
-       "prefs-searchoptions": "Piliheun Panéangan",
+       "prefs-searchoptions": "Paluruh",
        "prefs-namespaces": "Ngaranspasi",
        "default": "ti dituna",
        "prefs-files": "Koropak",
        "prefs-reset-intro": "Anjeun bisa maké ieu kaca pikeun mulangkeun préferénsi anjeun ka nu baku.\nMun geus anggeus teu bisa dibolaykeun.",
        "prefs-emailconfirm-label": "Konfirmasi surélék:",
        "youremail": "Surélék:",
-       "username": "Landihan:",
-       "prefs-memberingroups": "Anggota {{PLURAL:$1|jumplukan|jumplukan}}:",
+       "username": "{{GENDER:$1|Sandiasma}}:",
+       "prefs-memberingroups": "{{GENDER:$2|Anggota}} {{PLURAL:$1|kelompok|kelompok}}:",
        "prefs-registration": "Waktu daptar:",
        "yourrealname": "Ngaran anjeun*",
        "yourlanguage": "Basa antarbeungeut",
        "badsig": "Parafna teu valid; pariksa tag HTML-na geura.",
        "badsiglength": "Tawis leungeun panjang teuing. Kuduna kurang ti $1 {{PLURAL:$1|karaktér|karaktér}}.",
        "yourgender": "Jenis kelamin:",
-       "gender-unknown": "Teu nyebutkeun",
-       "gender-male": "Lalaki",
-       "gender-female": "Awéwé",
+       "gender-unknown": "Moal béja-béja",
+       "gender-male": "Manéhna ngédit kaca wiki",
+       "gender-female": "Manéhna ngédit kaca wiki",
        "email": "Surélék",
        "prefs-help-realname": "* Ngaran asli (pilihan): mun anjeun milih ngeusian, bakal dipaké pikeun nandaan kontribusi anjeun.",
        "prefs-help-email": "Surélék sipatna pilihan, tapi diperlukeun pikeun nyetél ulang sandi lamun anjeun poho.",
        "prefs-signature": "Tandatangan",
        "prefs-dateformat": "Format titimangsa",
        "prefs-timeoffset": "Format waktu",
-       "prefs-advancedediting": "Pilihan lengkep",
+       "prefs-advancedediting": "Pilihan umum",
+       "prefs-editor": "Éditor",
+       "prefs-preview": "Pratayang",
        "prefs-advancedrc": "Pilihan lengkep",
        "prefs-advancedrendering": "Pilihan lengkep",
        "prefs-advancedsearchoptions": "Pilihan lengkep",
        "prefs-advancedwatchlist": "Pilihan lengkep",
        "prefs-displayrc": "Pilihan pidangan",
        "prefs-displaywatchlist": "Pilihan pidangan",
+       "prefs-tokenwatchlist": "Token",
        "prefs-diffs": "Béda",
        "email-address-validity-valid": "Alamat surélék sigana bener",
        "email-address-validity-invalid": "Asupkeun alamat ratron nu bener",
        "right-move": "Mindahkeun kaca",
        "right-move-subpages": "Pindahkeun kaca katut sakabéh subkacana",
        "right-move-rootuserpages": "Mindahkeun akar kaca kontributor",
+       "right-move-categorypages": "Pindahkeun kaca kategori",
        "right-movefile": "Mindahkeun berkas",
        "right-suppressredirect": "Henteu nyieun hiji alihan ti ngaran lila sabot mindahkeun kaca",
        "right-upload": "Muatkeun koropak",
        "right-browsearchive": "Sungsi kaca nu geus dihapus",
        "right-undelete": "Balikeun deui kaca",
        "right-suppressrevision": "Mariksa jeung mulangkeun révisi anu disumputkeun ti kuncén",
+       "right-viewsuppressed": "Témbongkeun révisi anu disumputkeun ti pamaké lianna",
        "right-suppressionlog": "Nempo log privat",
        "right-block": "Peungpeuk pamaké lain tina ngédit",
        "right-blockemail": "Halangan pamaké keur ngirim Surélék",
        "right-hideuser": "Peungpeuk pamaké, tong ditingalikeun ka nulain",
        "right-ipblock-exempt": "Narabas peungpeuk IP, peungpeuk-otomatis, jeung peungpeuk rentang",
        "right-proxyunbannable": "Abaikeun pengpeuk otomatis keur proxy",
-       "right-unblockself": "Muka peungpeuk ka dirina sorangan",
-       "right-protect": "Ngarobah hambalan konci jeung ngédit kaca anu dikonci",
-       "right-editprotected": "Ngédit kaca anu dikonci (tanpa ngarobah protéksi)",
+       "right-unblockself": "buka peungpeuk sorangan",
+       "right-protect": "Ngarobah hambalan protéksi jeung édit kaca anu dikonci",
+       "right-editprotected": "Edit kaca anu dikonci salaku \"{{int:protect-level-sysop}}\"",
        "right-editinterface": "Édit antarbenget pamaké",
        "right-editusercssjs": "Édit berkas CSS jeung JS pamaké séjén",
        "right-editusercss": "Édit berkas CSS pamaké séjén",
        "right-edituserjs": "Ngédit berkas JS pamaké séjén",
+       "right-viewmywatchlist": "Tempo awaskeuneun anjeun",
+       "right-viewmyprivateinfo": "Tempo data pribadi anjeun (alamat surélék, ngaran asli)",
+       "right-editmyprivateinfo": "Robah data pribadi anjeun (alamat surélék, ngaran asli)",
+       "right-editmyoptions": "Robah préferénsi anjeun",
        "right-import": "Ngimpor kaca ti wiki séjén",
        "right-importupload": "Ngimpor kaca tina hiji koropak nu dimuat",
        "right-patrol": "Nandaan éditan pamaké séjén minangka geus dipatroli",
        "action-createpage": "mitembeyan kaca anyar",
        "action-createtalk": "mitembeyan kaca obrolan",
        "action-createaccount": "nyieun rekening pamaké ieu",
+       "action-history": "tempo jujutan ieu kaca",
        "action-minoredit": "nandaan ieu éditan salaku minor",
        "action-move": "mindahkeun ieu kaca",
        "action-move-subpages": "mindahkeun ieu kaca katut bagian-bagianana",
        "action-move-rootuserpages": "mindahkeun kaca utama kontributor",
+       "action-move-categorypages": "pindahkeun kaca kategori",
        "action-movefile": "mindahkeun ieu berkas",
        "action-upload": "ngamuat ieu berkas",
        "action-reupload": "nimpah berkas nu geus aya ieu",
        "action-suppressionlog": "nempo ieu log pribadi",
        "action-block": "meungpeuk ieu pamaké tina ngédit",
        "action-protect": "ngarobah hambalan konci ieu kaca",
-       "action-import": "impor ieu kaca ti séjén wiki",
+       "action-import": "impor kaca ti wiki séjén",
        "action-patrol": "Nandaan éditan séjén minangka geus diroris",
        "action-autopatrol": "tandaan éditan anjeun salaku geus diroris",
        "action-unwatchedpages": "témbongkeun béréndélan kaca nu teu diawaskeun",
        "action-userrights-interwiki": "ngarobah hak pamaké di wiki lianna",
        "action-siteadmin": "ngonci atawa muka konci databés",
        "action-sendemail": "ngirim surélék",
+       "action-editmywatchlist": "robah awaskeuneun anjeun",
+       "action-viewmyprivateinfo": "tempo émbaran pribadi anjeun",
+       "action-editmyprivateinfo": "robah émbaran pribadi anjeun",
        "nchanges": "$1 {{PLURAL:$1|parobahan|parobahan}}",
+       "enhancedrc-history": "jujutan",
        "recentchanges": "Anyar robah",
        "recentchanges-legend": "Pilihan parobahan anyar",
        "recentchanges-summary": "Lacak parobahan ka wiki panganyarna na kaca ieu.",
        "recentchanges-label-minor": "Ieu éditan minor",
        "recentchanges-label-bot": "Ieu parobahan dijieun ku bot",
        "recentchanges-label-unpatrolled": "Ieu éditan can karoris",
+       "recentchanges-legend-heading": "'''Pedaran:'''",
        "recentchanges-legend-newpage": "$1 - kaca anyar",
        "rcnotefrom": "Di handap ieu parobahan saprak <b>$2</b> (nu ditémbongkeun nepi ka <b>$1</b>).",
        "rclistfrom": "Témbongkeun nu anyar robah nepi ka $3 $2",
        "rcshowhideminor": "$1 éditan minor",
+       "rcshowhideminor-show": "Témbongkeun",
+       "rcshowhideminor-hide": "Sumputkeun",
        "rcshowhidebots": "$1 bot",
-       "rcshowhideliu": "$1 kontributor nu asup log",
+       "rcshowhidebots-show": "Témbongkeun",
+       "rcshowhidebots-hide": "Sumputkeun",
+       "rcshowhideliu": "$1 pamaké kadaptar",
+       "rcshowhideliu-show": "Témbongkeun",
+       "rcshowhideliu-hide": "Sumputkeun",
        "rcshowhideanons": "$1 kontributor anonim",
+       "rcshowhideanons-show": "Témbongkeun",
+       "rcshowhideanons-hide": "Sumputkeun",
        "rcshowhidepatr": "$1 éditan karoris",
+       "rcshowhidepatr-show": "Témbongkeun",
+       "rcshowhidepatr-hide": "Sumputkeun",
        "rcshowhidemine": "$1 éditan kuring",
+       "rcshowhidemine-show": "Témbongkeun",
+       "rcshowhidemine-hide": "Sumputkeun",
        "rclinks": "Témbongkeun $1 parobahan ahir dina $2 poé ahir<br />$3",
        "diff": "béda",
        "hist": "juj",
        "newsectionsummary": "/* $1 */ bagean anyar",
        "rc-enhanced-expand": "Témbongkeun rincian (butuh JavaScript)",
        "rc-enhanced-hide": "Sumputkeun rincian",
+       "rc-old-title": "Mimitina dijieun salaku \"$1\"",
        "recentchangeslinked": "Parobahan nu patali",
        "recentchangeslinked-feed": "Parobahan nu patali",
        "recentchangeslinked-toolbox": "Parobahan nu patali",
        "uploadbtn": "Muatkeun koropak",
        "reuploaddesc": "Balik ka formulir muatan.",
        "uploadnologin": "Can asup log",
-       "uploadnologintext": "Anjeun kudu [[Special:UserLogin|asup log]] pikeun ngamuat koropak.",
+       "uploadnologintext": "Mangga $1 pikeun ngunggah berkas.",
        "upload_directory_read_only": "Diréktori muatan ($1) teu bisa ditulis ku server ramat.",
        "uploaderror": "Kasalahan muat",
        "upload-recreate-warning": "'''Awas: berkas nu ngaranna kitu geus kungsi dihapus atawa dipindahkeun.'''\n\nLog hahapus jeung pipindah pikeun ieu kaca dipidangkeun di handap:",
        "uploadwarning-text": "Ropéa pedaran berkas di handap terus cobaan deui.",
        "savefile": "Simpen koropak",
        "uploaddisabled": "Punten, ngamuat ayeuna ditumpurkeun.",
+       "copyuploaddisabled": "Unggahan dumasar URL ditumpurkeun.",
        "uploaddisabledtext": "Fungsi ngamuat koropak ditumpurkeun.",
        "uploadscripted": "Koropak ieu ngandung kode HTML atawa skrip nu bisa dibaca ngaco ku panyungsi ramat (''web browser'').",
        "uploadvirus": "Koropakna ngandung virus! Katrangan: $1",
        "lockmanager-fail-db-release": "Teu bisa ngaleupaskeun konci dina databés $1.",
        "lockmanager-fail-svr-release": "Teu bisa ngaleupaskeun konci dina server $1.",
        "zip-wrong-format": "Berkas anu dipilih lain berkas ZIP.",
+       "img-auth-accessdenied": "Aksés ditolak",
        "img-auth-nofile": "Berkas \"$1\" henteu aya.",
        "img-auth-noread": "Pamaké teu boga kawenangan maca \"$1\".",
        "http-invalid-url": "URL teu bener: $1",
        "license": "Lisénsi:",
        "license-header": "Lisénsi",
        "nolicense": "Taya nu dipilih",
+       "licenses-edit": "Robah pilihan lisénsi",
        "license-nopreview": "(euweuh pramidang)",
        "upload_source_url": "(URL nu sohéh sarta bisa dibuka ku umum)",
        "upload_source_file": " (koropak dina komputer salira)",
+       "listfiles-delete": "hapus",
+       "listfiles-summary": "Ieu kaca husus némbongkeun sakabéh berkas anu geus diunggah.",
        "listfiles_search_for": "Sungsi ngaran média:",
        "imgfile": "koropak",
        "listfiles": "Daptar gambar",
        "listfiles_size": "Badagna",
        "listfiles_description": "Pedaran",
        "listfiles_count": "Vérsi",
+       "listfiles-latestversion": "Vérsi ayeuna",
+       "listfiles-latestversion-yes": "Enya",
+       "listfiles-latestversion-no": "Henteu",
        "file-anchor-link": "Gambar",
        "filehist": "Sajarah gambar",
        "filehist-help": "Klik dina titimangsa pikeun nempo koropak nu aya dina mangsa éta.",
        "filedelete-reason-otherlist": "Alesan séjén",
        "filedelete-reason-dropdown": "*Alesan nu ilahar\n** Ngarumpak hak cipta\n** Koropak geus aya",
        "filedelete-edit-reasonlist": "Alesan ngahapus éditan",
+       "filedelete-maintenance-title": "Henteu bisa ngahapus berkas",
        "mimesearch": "Sungsi MIME",
        "mimesearch-summary": "Ieu kaca bisa dipaké nyaring koropak dumasar tipeu MIME-na. Asupan: contenttype/subtype, contona <code>image/jpeg</code>.",
        "mimetype": "Tipeu MIME:",
        "unusedtemplateswlh": "tumbu lianna",
        "randompage": "Kaca acak",
        "randompage-nopages": "Euweuh kaca dina ieu spasi ngaran \"$1\".",
+       "randomincategory-category": "Kategori:",
        "randomredirect": "Alihan acak",
        "randomredirect-nopages": "Euweuh alihan dina ieu spasi ngaran \"$1\".",
        "statistics": "Statistik",
        "statistics-users-active": "Pamaké getol",
        "statistics-users-active-desc": "Kontributor nu ngoprék salila {{PLURAL:$1|poé|$1 poé}} panungtung",
        "statistics-mostpopular": "Kaca nu pangmindengna dibuka",
+       "pageswithprop-submit": "Jung",
        "doubleredirects": "Alihan ganda",
        "doubleredirectstext": "Ieu kaca ngabéréndélkeun kaca-kaca alihan ka kaca alihan lianna. Unggal baris ngandung tutumbu ka alihan kahiji jeung kadua, ogé tujul alihan kadua anu biasana tujul kaca anu \"bener\", anu sakuduna dituju ku alihan kahiji. Ëntri nu <del>dicorét</del> geus diropéa.",
        "double-redirect-fixed-move": "[[$1]] geus pindah, dialihkeun ka [[$2]].",
        "fewestrevisions": "Artikel nu pangjarangna dirévisi",
        "nbytes": "$1 {{PLURAL:$1|bait|bait}}",
        "ncategories": "$1 {{PLURAL:$1|kategori|kategori}}",
+       "ninterwikis": "$1 {{PLURAL:$1|interwiki|interwiki}}",
        "nlinks": "$1 {{PLURAL:$1|tumbu|tumbu}}",
        "nmembers": "$1 {{PLURAL:$1|kontributor|kontributor}}",
+       "nmemberschanged": "$1 → $2 {{PLURAL:$2|anggota|anggota}}",
        "nrevisions": "$1 {{PLURAL:$1|révisi|révisi}}",
        "nviews": "$1 {{PLURAL:$1|témbongan|témbongan}}",
        "nimagelinks": "Dipaké di $1 {{PLURAL:$1|kaca|kaca}}",
        "protectedpages": "Kaca-kaca nu dikonci",
        "protectedpages-indef": "Ngan pikeun panangtayungan kalawan waktu nuteu kawates",
        "protectedpagesempty": "Dina danget ieu, teu aya kaca nu dikonci dumasar kana ieu paraméter.",
+       "protectedpages-timestamp": "Cap titimangsa",
+       "protectedpages-page": "Kaca",
+       "protectedpages-expiry": "Kadaluwarsa",
+       "protectedpages-params": "Paraméter protéksi",
+       "protectedpages-reason": "Alesan",
+       "protectedpages-unknown-timestamp": "Teu kanyahoan",
+       "protectedpages-unknown-performer": "Pamaké henteu dipikawanoh",
        "protectedtitles": "Judul nu dikonci",
        "protectedtitlesempty": "Dina danget ieu, euweuh judul nu keur dikonci tina paraméter-paraméter éta.",
        "listusers": "Daptar pamaké",
        "booksources-text": "Di handap ieu ngabéréndélkeun tumbu ka loka-loka nu ngical buku, boh nu anyar atawa loakan, nu sugan uninga kana buku anu nuju dipilari:",
        "booksources-invalid-isbn": "ISBN-na sigana henteu bener; pariksa deui bisi aya salah salin ti sumber aslina.",
        "specialloguserlabel": "Pamaké:",
-       "speciallogtitlelabel": "Judul:",
+       "speciallogtitlelabel": "Sasaran (judul atawa pamaké):",
        "log": "Log",
        "all-logs-page": "Sakabéh log umum",
        "alllogstext": "Béréndélan sakabéh log nu aya di {{SITENAME}}.\nBisa dipondokkeun ku cara milih tipe log, ngaran pamaké, atawa kaca nu dimaksud.",
        "emailuser": "Surélékan pamaké ieu",
        "emailpage": "Surélékan pamaké",
        "emailpagetext": "Anjeun bisa maké formulir di handap pikeun ngirim surélék ka ieu pamaké.\nAlamat surélék nu diasupkeun kana [[Special:Preferences|préferénsi pamaké anjeun]] bakal katémbong salaku alamat \"Ti\" dina surélékna, sahingga nu dituju bisa males langsung.",
-       "defemailsubject": "Surélék {{SITENAME}}",
+       "defemailsubject": "Surélék {{SITENAME}} ti pamaké \"$1\"",
        "usermaildisabled": "Surélék kontributor ditumpurkeun",
        "usermaildisabledtext": "Anjeun teu bisa ngirim surélék ka kontributor séjén di ieu wiki",
        "noemailtitle": "Teu aya alamat surélék",
        "noemailtext": "Ieu pamaké ieu teu méré alamat surélék nu sah.",
        "nowikiemailtext": "Ieu kontributor milih teu nampa surélék ti kontributor séjén.",
+       "emailnotarget": "Sandiasma panarima henteu valid atawa henteu aya.",
+       "emailtarget": "ASupkeun sandiasma panarima",
        "emailusername": "Sandiasma:",
        "emailusernamesubmit": "Kirim",
        "email-legend": "Kirim surélék ka kontributor {{SITENAME}} lianna",
        "emailsent": "Surélék geus dikirim",
        "emailsenttext": "Surélék anjeun geus dikirim.",
        "emailuserfooter": "Ieu surélék dikirim ku $1 ka $2 migunakeun fungsi \"Surélékan pamaké ieu\" di {{SITENAME}}.",
+       "usermessage-summary": "Ninggalkeun talatah sistem.",
        "watchlist": "Awaskeuneun",
        "mywatchlist": "Awaskeuneun",
        "watchlistfor2": "Pikeun $1 $2",
        "nowatchlist": "Anjeun teu boga awaskeuneun.",
-       "watchlistanontext": "Mangga $1 pikeun némbongkeun atawa ngarobah béréndélan awaskeuneun anjeun.",
+       "watchlistanontext": "Mangga asup log pikeun nempo atawa ngarobah béréndélan awaskeuneun anjeun.",
        "watchnologin": "Can asup log",
        "addedwatchtext": "Kaca \"[[:$1]]\" geus ditambahkeun ka [[Special:Watchlist|awaskeuneun]] anjeun.\nJaga, parobahan na kaca ieu katut kaca obrolanana bakal dibéréndélkeun di dinya, sarta kacana bakal katémbong '''dikandelan''' dina kaca [[Special:RecentChanges|Nu anyar robah]] sangkan leuwih gampang ngawaskeunana.\n\n<p>Mun jaga anjeun moal deui ngawaskeun parobahan na kaca éta, klik tumbu \"Eureun ngawaskeun\" na lajursisi.",
+       "removewatch": "Piceun tina béréndélan awaskeuneun",
        "removedwatchtext": "Kaca \"[[:$1]]\" geus dikaluarkeun tina [[Special:Watchlist|daptar awaskeuneun]] anjeun.",
+       "removedwatchtext-short": "Kaca \"$1\" geus dipiceun tina béréndélan awaskeuneun.",
        "watch": "awaskeun",
        "watchthispage": "Awaskeun kaca ieu",
        "unwatch": "Eureun ngawaskeun",
        "unwatchthispage": "Eureun ngawaskeun",
        "notanarticle": "Sanés kaca eusi",
        "notvisiblerev": "Révisi geus dihapus",
-       "watchlist-details": "Aya {{PLURAL:$1|$1 kaca|$1 kaca}} nu ku anjeun diawaskeun, teu kaasup kaca obrolan/sawala.",
+       "watchlist-details": "Aya {{PLURAL:$1|$1 kaca|$1 kaca}} dina béréndélan awaskeuneun, teu kaasup kaca obrolan/sawala.",
        "wlheader-enotif": "Pangémbar surélék difungsikeun.",
        "wlheader-showupdated": "Kaca nu robah ti panungtungan anjeun sindang ditémbongkeun kalawan '''kandel'''",
        "wlnote": "Di handap ieu mangrupa $1 {{PLURAL:$1|robahan|robahan}} ahir salila '''$2''' jam.",
        "unwatching": "Eureun ngawaskeun...",
        "enotif_reset": "Tandaan sadaya kaca nu geus dilongok",
        "enotif_impersonal_salutation": "Pamaké {{SITENAME}}",
+       "enotif_subject_deleted": "Kaca {{SITENAME}} $1 geus {{GENDER:$2|dihapus}} ku $2",
        "enotif_lastvisited": "Tempo $1 pikeun sadaya parobahan ti saprak anjeun ninggalkeun ieu kaca.",
        "enotif_lastdiff": "Buka $1 pikeun nempo ieu parobahan.",
        "enotif_anon_editor": "pamaké anonim $1",
        "protect-level-sysop": "Ngan bisa ku kuncén",
        "protect-summary-cascade": "ngaruntuykeun",
        "protect-expiring": "kadaluwarsa $1",
+       "protect-expiring-local": "kadaluwarsa $1",
        "protect-expiry-indefinite": "tanpa wates",
        "protect-cascade": "Konci kaca nu kawengku dina ieu kaca (pangonci ngaruntuy).",
        "protect-cantedit": "Anjeung teu wenang ngarobah hambalan ngonci ieu kaca.",
        "protect-othertime": "Séjén waktu",
+       "protect-othertime-op": "séjén waktu",
        "protect-existing-expiry": "Waktu mungkas nu aya: $3, $2",
+       "protect-existing-expiry-infinity": "Waktu kadaluwarsa nu aya: taya wates",
        "protect-otherreason": "Alesan panambah/lianna:",
        "protect-otherreason-op": "Alesan séjén",
        "protect-dropdown": "*Alesan ngonci nu ilahar\n** Vandalismeu kamalinaan\n** Spamming kamalinaan\n** Perang éditan\n** Kaca loba pisan diédit",
        "contributions": "Kontribusi ti kontributor",
        "contributions-title": "Sumbangan tulisan ti $1",
        "mycontris": "Kontribusi",
-       "contribsub2": "Pikeun $1 ($2)",
+       "contribsub2": "Pikeun {{GENDER:$3|$1}} ($2)",
+       "contributions-userdoesnotexist": "Akun pamaké \"$1\" teu aya dina daptar.",
        "nocontribs": "Taya robahan nu kapanggih cocog jeung patokan ieu.",
-       "uctop": "(pangluhurna)",
+       "uctop": "(ayeuna)",
        "month": "Ti bulan (jeung saméméhna):",
        "year": "Ti taun (jeung saméméhna):",
        "sp-contributions-newbies": "Témbongkeun kontribusi ti akun anyar wungkul",
        "unblocklink": "buka blokir",
        "change-blocklink": "Robah status blokir",
        "contribslink": "kontribusi",
+       "emaillink": "kirim surélék",
        "autoblocker": "Otomatis dipeungpeuk kusabab alamat IP anjeun dipaké ku \"[[User:$1|$1]]\".\nAlesan: \"$2\"",
        "blocklogpage": "Log_peungpeuk",
        "blocklog-showlog": "Ieu pamaké saméméhna geus kungsi dipeungpeuk.\nPikeun rujukan, logna dipidangkeun di handap ieu:",
        "import": "Impor kaca",
        "importinterwiki": "Impor transwiki",
        "import-interwiki-text": "Pilih wiki jeung judul kaca nu rék diimpor.\nTanggal révisi katut ngaran nu ngédit bakal dipertahankeun.\nSadaya aktivitas impor transwiki baris kacatet dina [[Special:Log/import|log impor]].",
-       "import-interwiki-source": "Wiki/kaca sumber:",
+       "import-interwiki-sourcewiki": "Wiki sumber:",
+       "import-interwiki-sourcepage": "Kaca sumber:",
        "import-interwiki-history": "Salin sakabéh vérsi jujutan pikeun ieu kaca",
        "import-interwiki-templates": "Kaasup sakabéh citakan",
        "import-interwiki-submit": "Impor",
        "import-logentry-upload-detail": "$1 {{PLURAL:$1|vérsi heubeul}}",
        "import-logentry-interwiki": "$1 geus ditranswikikeun",
        "import-logentry-interwiki-detail": "$1 {{PLURAL:$1|vérsi heubel}} ti $2",
+       "javascripttest": "Nguji JavaScript",
        "tooltip-pt-userpage": "Kaca kontributor Anjeun",
        "tooltip-pt-anonuserpage": "Kaca pamaké pikeun IP nu ku anjeun keur diédit",
        "tooltip-pt-mytalk": "Kaca obrolan Anjeun",
        "spamprotectiontitle": "Saringan spam",
        "spamprotectiontext": "Kaca nu rék disimpen dipeungpeuk ku saringan spam.\nSigana mah ieu téh alatan tumbu ka loka luar.",
        "pageinfo-title": "Émbaran pikeun \"$1\"",
-       "pageinfo-header-edits": "Éditan",
+       "pageinfo-header-basic": "Émbaran dasar",
+       "pageinfo-header-edits": "Jujutan édit",
+       "pageinfo-header-restrictions": "Protéksi kaca",
        "pageinfo-watchers": "Jumlah nu ngawaskeun",
        "pageinfo-edits": "Jumlah éditan",
        "pageinfo-authors": "Jumlah kontributor nu béda",
+       "pageinfo-contentpage-yes": "Enya",
+       "pageinfo-protect-cascading-yes": "Enya",
        "markaspatrolleddiff": "Tandaan salaku geus diriksa",
        "markaspatrolledtext": "Tandaan artikel ieu salaku geus diriksa",
        "markedaspatrolled": "Tandaan salaku geus diriksa",
index 6163709..e3ddc2c 100644 (file)
        "searchall": "tất cả",
        "showingresults": "Dưới đây là {{PLURAL:$1|'''1'''|'''$1'''}} kết quả bắt đầu từ #'''$2'''.",
        "showingresultsinrange": "Dưới đây là cho tới <strong>$1</strong> kết quả từ #<strong>$2</strong> đến #<strong>$3</strong>.",
+       "search-showingresults": "{{PLURAL:$4|Kết quả thứ <strong>$1</strong> trong tổng số <strong>$3</strong>|Các kết quả <strong>$1–$2</strong> trong tổng số <strong>$3</strong>}}",
        "search-nonefound": "Không có kết quả nào khớp với câu truy vấn.",
        "powersearch-legend": "Tìm kiếm nâng cao",
        "powersearch-ns": "Tìm trong không gian tên:",
        "unblocked": "[[User:$1|$1]] đã hết bị cấm",
        "unblocked-range": "$1 đã được bỏ cấm",
        "unblocked-id": "$1 đã hết bị cấm",
+       "unblocked-ip": "[[Special:Contributions/$1|$1]] đã được bỏ cấm.",
        "blocklist": "Người dùng bị cấm",
        "ipblocklist": "Người dùng bị cấm",
        "ipblocklist-legend": "Tìm một thành viên bị cấm",
index b1f6786..b73b405 100644 (file)
        "protect-othertime": "其它时间:",
        "protect-othertime-op": "其它时间",
        "protect-existing-expiry": "现有的终止时间:$2 $3",
+       "protect-existing-expiry-infinity": "当前到期时间:无限期",
        "protect-otherreason": "其他/附加原因:",
        "protect-otherreason-op": "其他原因",
        "protect-dropdown": "*常见保护原因\n** 过度破坏\n** 过多垃圾信息\n** 负面的编辑战\n** 高流量页面",
index c3ccd27..d0649b9 100644 (file)
@@ -61,7 +61,7 @@
                ]
        },
        "tog-underline": "連結顯示底線:",
-       "tog-hideminor": "é\9a±è\97\8fæ\9c\80è¿\91è®\8aæ\9b´ä¸­ç\9a\84å°\8fä¿®è¨\82",
+       "tog-hideminor": "é\9a±è\97\8fæ\9c\80è¿\91è®\8aæ\9b´ä»¥ä¾\86ç\9a\84å°\8f編輯",
        "tog-hidepatrolled": "隱藏最近變更中巡查過的編輯",
        "tog-newpageshidepatrolled": "隱藏新頁面清單中巡查過的頁面",
        "tog-extendwatchlist": "展開監視清單顯示包含最近以外的所有變更",
        "headline_tip": "第 2 層標題文字",
        "nowiki_sample": "插入非格式化文字",
        "nowiki_tip": "忽略 Wiki 格式化語法",
+       "image_sample": "範例.jpg",
        "image_tip": "附加檔案",
        "media_tip": "檔案連結",
        "sig_tip": "您的簽名與日期時間",
index 9f64da4..2f961e6 100644 (file)
@@ -1175,11 +1175,11 @@ return array(
        'mediawiki.page.ready' => array(
                'scripts' => 'resources/src/mediawiki.page/mediawiki.page.ready.js',
                'dependencies' => array(
+                       'jquery.accessKeyLabel',
                        'jquery.checkboxShiftClick',
                        'jquery.makeCollapsible',
                        'jquery.placeholder',
                        'jquery.mw-jump',
-                       'mediawiki.util',
                ),
                'targets' => array( 'desktop', 'mobile' ),
        ),
@@ -1464,38 +1464,48 @@ return array(
        /* MediaWiki UI */
 
        'mediawiki.ui' => array(
-               'styles' => array(
-                       'resources/src/mediawiki.ui/default.less',
+               'skinStyles' => array(
+                       'default' => array(
+                               'resources/src/mediawiki.ui/default.less',
+                       ),
                ),
                'position' => 'top',
                'targets' => array( 'desktop', 'mobile' ),
        ),
        'mediawiki.ui.checkbox' => array(
-               'styles' => array(
-                       'resources/src/mediawiki.ui/components/checkbox.less',
+               'skinStyles' => array(
+                       'default' => array(
+                               'resources/src/mediawiki.ui/components/checkbox.less',
+                       ),
                ),
                'position' => 'top',
                'targets' => array( 'desktop', 'mobile' ),
        ),
        // Lightweight module for anchor styles
        'mediawiki.ui.anchor' => array(
-               'styles' => array(
-                       'resources/src/mediawiki.ui/components/anchors.less',
+               'skinStyles' => array(
+                       'default' => array(
+                               'resources/src/mediawiki.ui/components/anchors.less',
+                       ),
                ),
                'position' => 'top',
                'targets' => array( 'desktop', 'mobile' ),
        ),
        // Lightweight module for button styles
        'mediawiki.ui.button' => array(
-               'styles' => array(
-                       'resources/src/mediawiki.ui/components/buttons.less',
+               'skinStyles' => array(
+                       'default' => array(
+                               'resources/src/mediawiki.ui/components/buttons.less',
+                       ),
                ),
                'position' => 'top',
                'targets' => array( 'desktop', 'mobile' ),
        ),
        'mediawiki.ui.input' => array(
-               'styles' => array(
-                       'resources/src/mediawiki.ui/components/inputs.less',
+               'skinStyles' => array(
+                       'default' => array(
+                               'resources/src/mediawiki.ui/components/inputs.less',
+                       ),
                ),
                'position' => 'top',
                'targets' => array( 'desktop', 'mobile' ),
diff --git a/resources/assets/file-type-icons/COPYING b/resources/assets/file-type-icons/COPYING
new file mode 100644 (file)
index 0000000..136530a
--- /dev/null
@@ -0,0 +1,43 @@
+The icons used here are derived from the crystalsvg icons in the the
+pics/crystalsvg/ directory of kdelibs-3.4.0 they were modified on 2005-05-15
+by Ævar Arnfjörð Bjarmason for use in MediaWiki.
+
+What follows is the contents of the LICENSE.crystalsvg file found in the pics/
+subdirectory of kdelibs-3.4.0:
+
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+This copyright and license notice covers all CrystalSVG images.
+Note the license notice contains an add-on.
+********************************************************************************
+KDE Crystal theme icons.
+Copyright (C) 2002 and following years KDE Artists
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation,
+version 2.1 of the License.
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+Lesser General Public License for more details.
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+    **** NOTE THIS ADD-ON ****
+The GNU Lesser General Public License or LGPL is written for software libraries
+in the first place. We expressly want the LGPL to be valid for this artwork
+library too.
+KDE Crystal theme icons is a special kind of software library, it is an
+artwork library, it's elements can be used in a Graphical User Interface, or
+GUI.
+Source code, for this library means:
+ - for vectors svg;
+ - for pixels, if applicable, the multi-layered formats xcf or psd, or
+otherwise png.
+The LGPL in some sections obliges you to make the files carry
+notices. With images this is in some cases impossible or hardly useful.
+With this library a notice is placed at a prominent place in the directory
+containing the elements. You may follow this practice.
+The exception in section 6 of the GNU Lesser General Public License covers
+the use of elements of this art library in a GUI.
+kde-artists [at] kde.org
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
diff --git a/resources/assets/file-type-icons/fileicon-c.png b/resources/assets/file-type-icons/fileicon-c.png
new file mode 100644 (file)
index 0000000..0d603b7
Binary files /dev/null and b/resources/assets/file-type-icons/fileicon-c.png differ
diff --git a/resources/assets/file-type-icons/fileicon-cpp.png b/resources/assets/file-type-icons/fileicon-cpp.png
new file mode 100644 (file)
index 0000000..123688f
Binary files /dev/null and b/resources/assets/file-type-icons/fileicon-cpp.png differ
diff --git a/resources/assets/file-type-icons/fileicon-deb.png b/resources/assets/file-type-icons/fileicon-deb.png
new file mode 100644 (file)
index 0000000..87ca3fa
Binary files /dev/null and b/resources/assets/file-type-icons/fileicon-deb.png differ
diff --git a/resources/assets/file-type-icons/fileicon-djvu.png b/resources/assets/file-type-icons/fileicon-djvu.png
new file mode 100644 (file)
index 0000000..1da2276
Binary files /dev/null and b/resources/assets/file-type-icons/fileicon-djvu.png differ
diff --git a/resources/assets/file-type-icons/fileicon-djvu.xcf b/resources/assets/file-type-icons/fileicon-djvu.xcf
new file mode 100644 (file)
index 0000000..8043dcd
Binary files /dev/null and b/resources/assets/file-type-icons/fileicon-djvu.xcf differ
diff --git a/resources/assets/file-type-icons/fileicon-dvi.png b/resources/assets/file-type-icons/fileicon-dvi.png
new file mode 100644 (file)
index 0000000..f37878d
Binary files /dev/null and b/resources/assets/file-type-icons/fileicon-dvi.png differ
diff --git a/resources/assets/file-type-icons/fileicon-exe.png b/resources/assets/file-type-icons/fileicon-exe.png
new file mode 100644 (file)
index 0000000..dc020eb
Binary files /dev/null and b/resources/assets/file-type-icons/fileicon-exe.png differ
diff --git a/resources/assets/file-type-icons/fileicon-h.png b/resources/assets/file-type-icons/fileicon-h.png
new file mode 100644 (file)
index 0000000..339bf02
Binary files /dev/null and b/resources/assets/file-type-icons/fileicon-h.png differ
diff --git a/resources/assets/file-type-icons/fileicon-html.png b/resources/assets/file-type-icons/fileicon-html.png
new file mode 100644 (file)
index 0000000..f28f8a2
Binary files /dev/null and b/resources/assets/file-type-icons/fileicon-html.png differ
diff --git a/resources/assets/file-type-icons/fileicon-iso.png b/resources/assets/file-type-icons/fileicon-iso.png
new file mode 100644 (file)
index 0000000..c73d229
Binary files /dev/null and b/resources/assets/file-type-icons/fileicon-iso.png differ
diff --git a/resources/assets/file-type-icons/fileicon-java.png b/resources/assets/file-type-icons/fileicon-java.png
new file mode 100644 (file)
index 0000000..a1b4f22
Binary files /dev/null and b/resources/assets/file-type-icons/fileicon-java.png differ
diff --git a/resources/assets/file-type-icons/fileicon-mid.png b/resources/assets/file-type-icons/fileicon-mid.png
new file mode 100644 (file)
index 0000000..ce2bebb
Binary files /dev/null and b/resources/assets/file-type-icons/fileicon-mid.png differ
diff --git a/resources/assets/file-type-icons/fileicon-mov.png b/resources/assets/file-type-icons/fileicon-mov.png
new file mode 100644 (file)
index 0000000..952de1f
Binary files /dev/null and b/resources/assets/file-type-icons/fileicon-mov.png differ
diff --git a/resources/assets/file-type-icons/fileicon-o.png b/resources/assets/file-type-icons/fileicon-o.png
new file mode 100644 (file)
index 0000000..f3523d9
Binary files /dev/null and b/resources/assets/file-type-icons/fileicon-o.png differ
diff --git a/resources/assets/file-type-icons/fileicon-ogg.png b/resources/assets/file-type-icons/fileicon-ogg.png
new file mode 100644 (file)
index 0000000..ef4d801
Binary files /dev/null and b/resources/assets/file-type-icons/fileicon-ogg.png differ
diff --git a/resources/assets/file-type-icons/fileicon-ogg.xcf b/resources/assets/file-type-icons/fileicon-ogg.xcf
new file mode 100644 (file)
index 0000000..a91024b
Binary files /dev/null and b/resources/assets/file-type-icons/fileicon-ogg.xcf differ
diff --git a/resources/assets/file-type-icons/fileicon-pdf.png b/resources/assets/file-type-icons/fileicon-pdf.png
new file mode 100644 (file)
index 0000000..8c8da92
Binary files /dev/null and b/resources/assets/file-type-icons/fileicon-pdf.png differ
diff --git a/resources/assets/file-type-icons/fileicon-ps.png b/resources/assets/file-type-icons/fileicon-ps.png
new file mode 100644 (file)
index 0000000..e872833
Binary files /dev/null and b/resources/assets/file-type-icons/fileicon-ps.png differ
diff --git a/resources/assets/file-type-icons/fileicon-psd.png b/resources/assets/file-type-icons/fileicon-psd.png
new file mode 100644 (file)
index 0000000..598f190
Binary files /dev/null and b/resources/assets/file-type-icons/fileicon-psd.png differ
diff --git a/resources/assets/file-type-icons/fileicon-rm.png b/resources/assets/file-type-icons/fileicon-rm.png
new file mode 100644 (file)
index 0000000..81dbe0b
Binary files /dev/null and b/resources/assets/file-type-icons/fileicon-rm.png differ
diff --git a/resources/assets/file-type-icons/fileicon-rpm.png b/resources/assets/file-type-icons/fileicon-rpm.png
new file mode 100644 (file)
index 0000000..1903aac
Binary files /dev/null and b/resources/assets/file-type-icons/fileicon-rpm.png differ
diff --git a/resources/assets/file-type-icons/fileicon-svg.png b/resources/assets/file-type-icons/fileicon-svg.png
new file mode 100644 (file)
index 0000000..b782113
Binary files /dev/null and b/resources/assets/file-type-icons/fileicon-svg.png differ
diff --git a/resources/assets/file-type-icons/fileicon-tar.png b/resources/assets/file-type-icons/fileicon-tar.png
new file mode 100644 (file)
index 0000000..e5fd1b7
Binary files /dev/null and b/resources/assets/file-type-icons/fileicon-tar.png differ
diff --git a/resources/assets/file-type-icons/fileicon-tex.png b/resources/assets/file-type-icons/fileicon-tex.png
new file mode 100644 (file)
index 0000000..a437284
Binary files /dev/null and b/resources/assets/file-type-icons/fileicon-tex.png differ
diff --git a/resources/assets/file-type-icons/fileicon-ttf.png b/resources/assets/file-type-icons/fileicon-ttf.png
new file mode 100644 (file)
index 0000000..1ed4e74
Binary files /dev/null and b/resources/assets/file-type-icons/fileicon-ttf.png differ
diff --git a/resources/assets/file-type-icons/fileicon-txt.png b/resources/assets/file-type-icons/fileicon-txt.png
new file mode 100644 (file)
index 0000000..9e988e7
Binary files /dev/null and b/resources/assets/file-type-icons/fileicon-txt.png differ
diff --git a/resources/assets/file-type-icons/fileicon-xcf.png b/resources/assets/file-type-icons/fileicon-xcf.png
new file mode 100644 (file)
index 0000000..1037b50
Binary files /dev/null and b/resources/assets/file-type-icons/fileicon-xcf.png differ
diff --git a/resources/assets/file-type-icons/fileicon.png b/resources/assets/file-type-icons/fileicon.png
new file mode 100644 (file)
index 0000000..59696a3
Binary files /dev/null and b/resources/assets/file-type-icons/fileicon.png differ
diff --git a/resources/assets/licenses/cc-0.png b/resources/assets/licenses/cc-0.png
new file mode 100644 (file)
index 0000000..9d3fe5f
Binary files /dev/null and b/resources/assets/licenses/cc-0.png differ
diff --git a/resources/assets/licenses/cc-by-nc-sa.png b/resources/assets/licenses/cc-by-nc-sa.png
new file mode 100644 (file)
index 0000000..0d24a71
Binary files /dev/null and b/resources/assets/licenses/cc-by-nc-sa.png differ
diff --git a/resources/assets/licenses/cc-by-sa.png b/resources/assets/licenses/cc-by-sa.png
new file mode 100644 (file)
index 0000000..518fb64
Binary files /dev/null and b/resources/assets/licenses/cc-by-sa.png differ
diff --git a/resources/assets/licenses/cc-by.png b/resources/assets/licenses/cc-by.png
new file mode 100644 (file)
index 0000000..9cca2f9
Binary files /dev/null and b/resources/assets/licenses/cc-by.png differ
diff --git a/resources/assets/licenses/gnu-fdl.png b/resources/assets/licenses/gnu-fdl.png
new file mode 100644 (file)
index 0000000..3feaf57
Binary files /dev/null and b/resources/assets/licenses/gnu-fdl.png differ
diff --git a/resources/assets/licenses/public-domain.png b/resources/assets/licenses/public-domain.png
new file mode 100644 (file)
index 0000000..ebf0107
Binary files /dev/null and b/resources/assets/licenses/public-domain.png differ
diff --git a/resources/assets/mediawiki.png b/resources/assets/mediawiki.png
new file mode 100644 (file)
index 0000000..8c42118
Binary files /dev/null and b/resources/assets/mediawiki.png differ
diff --git a/resources/assets/poweredby_mediawiki_88x31.png b/resources/assets/poweredby_mediawiki_88x31.png
new file mode 100644 (file)
index 0000000..30e1d2e
Binary files /dev/null and b/resources/assets/poweredby_mediawiki_88x31.png differ
index a6705d0..ebb2860 100644 (file)
@@ -2,12 +2,17 @@
        "@metadata": {
                "authors": [
                        "Vacio",
-                       "Xelgen"
+                       "Xelgen",
+                       "Դավիթ Սարոյան"
                ]
        },
-       "ooui-dialog-action-close": "Փակել",
        "ooui-outline-control-move-down": "Իջեցնել կետը",
        "ooui-outline-control-move-up": "Բարձրացնել կետը",
        "ooui-outline-control-remove": "Հեռացնել տարրը",
-       "ooui-toolbar-more": "Ավելին"
+       "ooui-toolbar-more": "Ավելին",
+       "ooui-dialog-message-accept": "Լավ",
+       "ooui-dialog-message-reject": "Չեղարկել",
+       "ooui-dialog-process-error": "Ինչ-որ սխալ է տեղի ունեցել",
+       "ooui-dialog-process-dismiss": "Փակել",
+       "ooui-dialog-process-retry": "Կրկին փորձել"
 }
index 53e46d6..b10bb25 100644 (file)
@@ -1,12 +1,12 @@
 /*!
- * OOjs UI v0.1.0-pre (49b64bdba7)
+ * OOjs UI v0.1.0-pre (ec785c2c64)
  * 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-09-15T22:18:37Z
+ * Date: 2014-09-18T01:30:17Z
  */
 /*
  * Blank theme mixins.
index e817142..bad16ec 100644 (file)
@@ -1,12 +1,12 @@
 /*!
- * OOjs UI v0.1.0-pre (49b64bdba7)
+ * OOjs UI v0.1.0-pre (ec785c2c64)
  * 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-09-15T22:18:37Z
+ * Date: 2014-09-18T01:30:17Z
  */
 /*
  * Blank theme mixins.
index a3e2375..525e5a1 100644 (file)
@@ -1,12 +1,12 @@
 /*!
- * OOjs UI v0.1.0-pre (49b64bdba7)
+ * OOjs UI v0.1.0-pre (ec785c2c64)
  * 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-09-15T22:18:37Z
+ * Date: 2014-09-18T01:30:17Z
  */
 ( function ( OO ) {
 
@@ -2293,7 +2293,7 @@ OO.ui.Dialog.prototype.getActionProcess = function ( action ) {
  * @inheritdoc
  *
  * @param {Object} [data] Dialog opening data
- * @param {jQuery|string|Function|null} [data.label] Dialog label, omit to use #static-label
+ * @param {jQuery|string|Function|null} [data.title] Dialog title, omit to use #static-title
  * @param {Object[]} [data.actions] List of OO.ui.ActionWidget configuration options for each
  *   action item, omit to use #static-actions
  */
@@ -4725,7 +4725,7 @@ OO.ui.ClippableElement.prototype.isClippedVertically = function () {
 };
 
 /**
- * Set the ideal size.
+ * Set the ideal size. These are the dimensions the element will have when it's not being clipped.
  *
  * @param {number|string} [width] Width as a number of pixels or CSS string with unit suffix
  * @param {number|string} [height] Height as a number of pixels or CSS string with unit suffix
@@ -4733,6 +4733,12 @@ OO.ui.ClippableElement.prototype.isClippedVertically = function () {
 OO.ui.ClippableElement.prototype.setIdealSize = function ( width, height ) {
        this.idealWidth = width;
        this.idealHeight = height;
+
+       if ( !this.clipping ) {
+               // Update dimensions
+               this.$clippable.css( { width: width, height: height } );
+       }
+       // While clipping, idealWidth and idealHeight are not considered
 };
 
 /**
@@ -11091,6 +11097,13 @@ OO.ui.TextInputMenuWidget.prototype.toggle = function ( visible ) {
 
        var change = visible !== this.isVisible();
 
+       if ( change && visible ) {
+               // Make sure the width is set before the parent method runs.
+               // After this we have to call this.position(); again to actually
+               // position ourselves correctly.
+               this.position();
+       }
+
        // Parent method
        OO.ui.TextInputMenuWidget.super.prototype.toggle.call( this, visible );
 
@@ -11102,6 +11115,7 @@ OO.ui.TextInputMenuWidget.prototype.toggle = function ( visible ) {
                        this.$( this.getElementWindow() ).off( 'resize', this.onWindowResizeHandler );
                }
        }
+
        return this;
 };
 
index 913d5fd..6c55898 100644 (file)
@@ -1,12 +1,12 @@
 /*!
- * OOjs UI v0.1.0-pre (49b64bdba7)
+ * OOjs UI v0.1.0-pre (ec785c2c64)
  * 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-09-15T22:18:37Z
+ * Date: 2014-09-18T01:30:17Z
  */
 /*
  * Blank theme mixins.
index 8feca4a..fdbb655 100644 (file)
@@ -3,7 +3,7 @@
  */
 
 /* Hide, but keep accessible for screen-readers. */
-.redirectTo {
+.redirectMsg p {
        overflow: hidden;
        height: 0;
        zoom: 1;
index 5c6e63b..a403996 100644 (file)
@@ -144,15 +144,18 @@ mw.log.deprecate( win, 'jsMsg', function ( message ) {
 /**
  * Misc. utilities
  *
- * @deprecated since 1.17 Use mediawiki.util instead
+ * @deprecated since 1.17 Use mediawiki.util or jquery.accessKeyLabel instead
  */
 msg = 'Use mediawiki.util instead.';
-mw.log.deprecate( win, 'updateTooltipAccessKeys', mw.util.updateTooltipAccessKeys, msg );
 mw.log.deprecate( win, 'addPortletLink', mw.util.addPortletLink, msg );
 mw.log.deprecate( win, 'appendCSS', mw.util.addCSS, msg );
 msg = 'Use jquery.accessKeyLabel instead.';
 mw.log.deprecate( win, 'tooltipAccessKeyPrefix', 'alt-', msg );
 mw.log.deprecate( win, 'tooltipAccessKeyRegexp', /\[(alt-)?(.)\]$/, msg );
+// mw.util.updateTooltipAccessKeys already generates a deprecation message.
+win.updateTooltipAccessKeys = function () {
+       return mw.util.updateTooltipAccessKeys.apply( null, arguments );
+};
 
 /**
  * Wikipage import methods
index 17bf683..e91302b 100644 (file)
@@ -57,3 +57,6 @@
 @colorGrayLight: #ccc;
 @colorGrayLighter: #ddd;
 @colorGrayLightest: #eee;
+
+// Global border radius to be used to buttons and inputs
+@borderRadius: 2px;
index a05a054..246cc81 100644 (file)
@@ -36,6 +36,7 @@
 
        // Things outside the wikipage content
        $( function () {
+               var $nodes;
 
                if ( !supportsPlaceholder ) {
                        // Exclude content to avoid hitting it twice for the (first) wikipage content
                }
 
                // Add accesskey hints to the tooltips
-               mw.util.updateTooltipAccessKeys();
+               if ( document.querySelectorAll ) {
+                       // If we're running on a browser where we can do this efficiently,
+                       // just find all elements that have accesskeys. We can't use jQuery's
+                       // polyfill for the selector since looping over all elements on page
+                       // load might be too slow.
+                       $nodes = $( document.querySelectorAll( '[accesskey]' ) );
+               } else {
+                       // Otherwise go through some elements likely to have accesskeys rather
+                       // than looping over all of them. Unfortunately this will not fully
+                       // work for custom skins with different HTML structures. Input, label
+                       // and button should be rare enough that no optimizations are needed.
+                       $nodes = $( '#column-one a, #mw-head a, #mw-panel a, #p-logo a, input, label, button' );
+               }
+               $nodes.updateTooltipAccessKeys();
 
        } );
 
index 3211dea..a6515d2 100644 (file)
@@ -31,7 +31,7 @@
  * Styleguide 1.1.
  */
 span.reference {
-       font-size: smaller;
+       font-size: 80%;
        line-height: 1;
        vertical-align: super;
        unicode-bidi: -moz-isolate;
index 7142d4d..f6a44fd 100644 (file)
 //
 // Styleguide 2.
 
-@buttonBorderRadius: 3px;
 @transitionDuration: .1s;
 @transitionFunction: ease-in-out;
 
 // Neutral button styling
 //
 // Markup:
-// <button class="mw-ui-button">.mw-ui-button</button>
-// <button class="mw-ui-button" disabled>.mw-ui-button</button>
+// <div>
+//   <button class="mw-ui-button">.mw-ui-button</button>
+// </div>
+// <div>
+//   <button class="mw-ui-button" disabled>.mw-ui-button</button>
+// </div>
 //
 // Styleguide 2.1.
 .mw-ui-button {
@@ -43,7 +46,8 @@
 
        // Container styling
        .button-colors(#FFF);
-       border-radius: @buttonBorderRadius;
+       border-radius: @borderRadius;
+       min-width: 80px;
 
        // Ensure that buttons and inputs are nicely aligned when they have differing heights
        vertical-align: middle;
        // using the mw-ui-big class.
        //
        // Markup:
-       // <button class="mw-ui-button mw-ui-big">.mw-ui-button</button>
-       // <button class="mw-ui-button mw-ui-progressive mw-ui-big">.mw-ui-progressive</button>
-       // <button class="mw-ui-button mw-ui-constructive mw-ui-big">.mw-ui-constructive</button>
-       // <button class="mw-ui-button mw-ui-destructive mw-ui-big">.mw-ui-destructive</button>
+       // <div>
+       //   <button class="mw-ui-button mw-ui-big">.mw-ui-button</button>
+       // </div>
+       // <div>
+       //   <button class="mw-ui-button mw-ui-progressive mw-ui-big">.mw-ui-progressive</button>
+       // </div>
+       // <div>
+       //   <button class="mw-ui-button mw-ui-constructive mw-ui-big">.mw-ui-constructive</button>
+       // </div>
+       // <div>
+       //   <button class="mw-ui-button mw-ui-destructive mw-ui-big">.mw-ui-destructive</button>
+       // </div>
        //
        // Styleguide 2.1.6.
        &.mw-ui-big {
        // Some buttons might need to be stacked.
        //
        // Markup:
-       // <button class="mw-ui-button mw-ui-block">.mw-ui-button</button>
-       // <button class="mw-ui-button mw-ui-progressive mw-ui-block">.mw-ui-progressive</button>
-       // <button class="mw-ui-button mw-ui-constructive mw-ui-block">.mw-ui-constructive</button>
-       // <button class="mw-ui-button mw-ui-destructive mw-ui-block">.mw-ui-destructive</button>
+       // <div>
+       //   <button class="mw-ui-button mw-ui-block">.mw-ui-button</button>
+       // </div>
+       // <div>
+       //   <button class="mw-ui-button mw-ui-progressive mw-ui-block">.mw-ui-progressive</button>
+       // </div>
+       // <div>
+       //   <button class="mw-ui-button mw-ui-constructive mw-ui-block">.mw-ui-constructive</button>
+       // </div>
+       // <div>
+       //   <button class="mw-ui-button mw-ui-destructive mw-ui-block">.mw-ui-destructive</button>
+       // </div>
        //
        // Styleguide 2.1.5.
        &.mw-ui-block {
        // .mw-ui-primary is deprecated, kept for compatibility.
        //
        // Markup:
-       // <button class="mw-ui-button mw-ui-progressive">.mw-ui-progressive</button>
-       // <button class="mw-ui-button mw-ui-progressive" disabled>.mw-ui-progressive</button>
+       // <div>
+       //   <button class="mw-ui-button mw-ui-progressive">.mw-ui-progressive</button>
+       // </div>
+       // <div>
+       //   <button class="mw-ui-button mw-ui-progressive" disabled>.mw-ui-progressive</button>
+       // </div>
        //
        // Styleguide 2.1.1.
        &.mw-ui-progressive,
        // e.g. save changes button
        //
        // Markup:
-       // <button class="mw-ui-button mw-ui-constructive">.mw-ui-constructive</button>
-       // <button class="mw-ui-button mw-ui-constructive" disabled>.mw-ui-constructive</button>
+       // <div>
+       //   <button class="mw-ui-button mw-ui-constructive">.mw-ui-constructive</button>
+       // </div>
+       // <div>
+       //   <button class="mw-ui-button mw-ui-constructive" disabled>.mw-ui-constructive</button>
+       // </div>
        //
        // Styleguide 2.1.2.
        &.mw-ui-constructive {
        // This should not be used for cancel buttons.
        //
        // Markup:
-       // <button class="mw-ui-button mw-ui-destructive">.mw-ui-destructive</button>
-       // <button class="mw-ui-button mw-ui-destructive" disabled>.mw-ui-destructive</button>
+       // <div>
+       //   <button class="mw-ui-button mw-ui-destructive">.mw-ui-destructive</button>
+       // </div>
+       // <div>
+       //   <button class="mw-ui-button mw-ui-destructive" disabled>.mw-ui-destructive</button>
+       // </div>
        //
        // Styleguide 2.1.3.
        &.mw-ui-destructive {
        // Use quiet buttons when they are less important and alongisde other progressive/destructive/progressive buttons.
        //
        // Markup:
-       // <button class="mw-ui-button mw-ui-quiet">.mw-ui-button</button>
-       // <button class="mw-ui-button mw-ui-constructive mw-ui-quiet">.mw-ui-constructive</button>
-       // <button class="mw-ui-button mw-ui-constructive mw-ui-quiet" disabled>.mw-ui-constructive</button>
-       // <button class="mw-ui-button mw-ui-destructive mw-ui-quiet">.mw-ui-destructive</button>
-       // <button class="mw-ui-button mw-ui-destructive mw-ui-quiet" disabled>.mw-ui-destructive</button>
-       // <button class="mw-ui-button mw-ui-progressive mw-ui-quiet">.mw-ui-progressive</button>
-       // <button class="mw-ui-button mw-ui-progressive mw-ui-quiet" disabled>.mw-ui-progressive</button>
+       // <div>
+       //   <button class="mw-ui-button mw-ui-quiet">.mw-ui-button</button>
+       // </div>
+       // <div>
+       //   <button class="mw-ui-button mw-ui-constructive mw-ui-quiet">.mw-ui-constructive</button>
+       // </div>
+       // <div>
+       //   <button class="mw-ui-button mw-ui-constructive mw-ui-quiet" disabled>.mw-ui-constructive</button>
+       // </div>
+       // <div>
+       //   <button class="mw-ui-button mw-ui-destructive mw-ui-quiet">.mw-ui-destructive</button>
+       // </div>
+       // <div>
+       //   <button class="mw-ui-button mw-ui-destructive mw-ui-quiet" disabled>.mw-ui-destructive</button>
+       // </div>
+       // <div>
+       //   <button class="mw-ui-button mw-ui-progressive mw-ui-quiet">.mw-ui-progressive</button>
+       // </div>
+       // <div>
+       //   <button class="mw-ui-button mw-ui-progressive mw-ui-quiet" disabled>.mw-ui-progressive</button>
+       // </div>
        //
        // Styleguide 2.1.4.
        &.mw-ui-quiet {
@@ -215,8 +261,8 @@ a.mw-ui-button {
        float: left;
 
        &:first-child {
-               border-top-left-radius: @buttonBorderRadius;
-               border-bottom-left-radius: @buttonBorderRadius;
+               border-top-left-radius: @borderRadius;
+               border-bottom-left-radius: @borderRadius;
        }
 
        &:not(:first-child) {
@@ -224,7 +270,7 @@ a.mw-ui-button {
        }
 
        &:last-child{
-               border-top-right-radius: @buttonBorderRadius;
-               border-bottom-right-radius: @buttonBorderRadius;
+               border-top-right-radius: @borderRadius;
+               border-bottom-right-radius: @borderRadius;
        }
 }
index 6d6fdde..e39646b 100644 (file)
@@ -1,4 +1,5 @@
 @import "mediawiki.mixins";
+@import "mediawiki.ui/variables";
 
 // Checkbox
 //
 
                // the pseudo before element of the label after the checkbox now looks like a checkbox
                & + label {
+                       cursor: pointer;
+
                        &::before {
                                                content: '';
                                                position: absolute;
                                                left: 0;
                                                display: inline-block;
-                                               border-radius: 2px;
+                                               border-radius: @borderRadius;
                                                margin-right: 18px;
                                                width: @checkboxSize;
                                                height: @checkboxSize;
                                                background-color: #fff;
-                                               cursor: pointer;
                                                border: 1px solid grey;
                                        }
                }
                }
 
                // disabled checked boxes have a gray background
-               &:disabled + label::before {
-                       background-color: lightgrey;
+               &:disabled + label {
+                       cursor: default;
+
+                       &::before {
+                               background-color: lightgrey;
+                       }
                }
        }
 }
index 7108fae..1da42a4 100644 (file)
        border: 1px solid @colorFieldBorder;
        .box-sizing(border-box);
        width: 100%;
-       padding: .3em .3em .3em .6em;
+       padding: .4em .3em .2em .6em;
        display: block;
        vertical-align: middle;
+       border-radius: @borderRadius;
        // Override user agent stylesheet properties. Instead use parent element.
        color: inherit;
        font-family: inherit;
@@ -85,6 +86,7 @@ textarea.mw-ui-input {
 // <button class="mw-ui-button mw-ui-constructive">go</button>
 //
 // Styleguide 1.2.
+input[type="number"],
 .mw-ui-input-inline {
        display: inline-block;
        width: auto;
index 887885e..2662913 100644 (file)
                        return null;
                },
 
-               /**
-                * Add the appropriate prefix to the accesskey shown in the tooltip.
-                *
-                * If the `$nodes` parameter is given, only those nodes are updated;
-                * otherwise, depending on browser support, we update either all elements
-                * with accesskeys on the page or a bunch of elements which are likely to
-                * have them on core skins.
-                *
-                * @param {Array|jQuery} [$nodes] A jQuery object, or array of nodes to update.
-                */
-               updateTooltipAccessKeys: function ( $nodes ) {
-                       if ( !$nodes ) {
-                               if ( document.querySelectorAll ) {
-                                       // If we're running on a browser where we can do this efficiently,
-                                       // just find all elements that have accesskeys. We can't use jQuery's
-                                       // polyfill for the selector since looping over all elements on page
-                                       // load might be too slow.
-                                       $nodes = $( document.querySelectorAll( '[accesskey]' ) );
-                               } else {
-                                       // Otherwise go through some elements likely to have accesskeys rather
-                                       // than looping over all of them. Unfortunately this will not fully
-                                       // work for custom skins with different HTML structures. Input, label
-                                       // and button should be rare enough that no optimizations are needed.
-                                       $nodes = $( '#column-one a, #mw-head a, #mw-panel a, #p-logo a, input, label, button' );
-                               }
-                       } else if ( !( $nodes instanceof $ ) ) {
-                               $nodes = $( $nodes );
-                       }
-
-                       $nodes.updateTooltipAccessKeys();
-               },
-
                /**
                 * The content wrapper of the skin (e.g. `.mw-body`).
                 *
         */
        mw.log.deprecate( util, 'tooltipAccessKeyRegexp', /\[(ctrl-)?(option-)?(alt-)?(shift-)?(esc-)?(.)\]$/, 'Use jquery.accessKeyLabel instead.' );
 
+       /**
+        * Add the appropriate prefix to the accesskey shown in the tooltip.
+        *
+        * If the `$nodes` parameter is given, only those nodes are updated;
+        * otherwise, depending on browser support, we update either all elements
+        * with accesskeys on the page or a bunch of elements which are likely to
+        * have them on core skins.
+        *
+        * @method updateTooltipAccessKeys
+        * @param {Array|jQuery} [$nodes] A jQuery object, or array of nodes to update.
+        * @deprecated since 1.24 Use the module jquery.accessKeyLabel instead.
+        */
+       mw.log.deprecate( util, 'updateTooltipAccessKeys', function ( $nodes ) {
+               if ( !$nodes ) {
+                       if ( document.querySelectorAll ) {
+                               // If we're running on a browser where we can do this efficiently,
+                               // just find all elements that have accesskeys. We can't use jQuery's
+                               // polyfill for the selector since looping over all elements on page
+                               // load might be too slow.
+                               $nodes = $( document.querySelectorAll( '[accesskey]' ) );
+                       } else {
+                               // Otherwise go through some elements likely to have accesskeys rather
+                               // than looping over all of them. Unfortunately this will not fully
+                               // work for custom skins with different HTML structures. Input, label
+                               // and button should be rare enough that no optimizations are needed.
+                               $nodes = $( '#column-one a, #mw-head a, #mw-panel a, #p-logo a, input, label, button' );
+                       }
+               } else if ( !( $nodes instanceof $ ) ) {
+                       $nodes = $( $nodes );
+               }
+
+               $nodes.updateTooltipAccessKeys();
+       }, 'Use jquery.accessKeyLabel instead.' );
+
        /**
         * Add a little box at the top of the screen to inform the user of
         * something, replacing any previous message.
index 185ffa4..702fce4 100644 (file)
@@ -180,7 +180,7 @@ class EditPageTest extends MediaWikiLangTestCase {
                return $page;
        }
 
-       public function provideCreatePages() {
+       public static function provideCreatePages() {
                return array(
                        array( 'expected article being created',
                                'EditPageTest_testCreatePage',
index 72114e9..7b84107 100644 (file)
@@ -1,5 +1,9 @@
 <?php
 
+/**
+ * @group Database
+ */
+
 class LinkerTest extends MediaWikiLangTestCase {
 
        /**
index c82dc42..dcb9856 100644 (file)
@@ -29,7 +29,7 @@ class MWTimestampTest extends MediaWikiLangTestCase {
                $this->assertEquals( '1406833268', $timestamp->__toString() );
        }
 
-       public function provideValidTimestampDifferences() {
+       public static function provideValidTimestampDifferences() {
                return array(
                        array( '1406833268', '1406833269', '00 00 00 01' ),
                        array( '1406833268', '1406833329', '00 00 01 01' ),
index c2acec0..f3d2a84 100644 (file)
@@ -34,7 +34,7 @@ class MessageTest extends MediaWikiLangTestCase {
                $this->assertEquals( $expectedLang, $langProperty->getValue( $message ) );
        }
 
-       public function provideConstructor() {
+       public static function provideConstructor() {
                $langDe = Language::factory( 'de' );
                $langEn = Language::factory( 'en' );
 
@@ -45,7 +45,7 @@ class MessageTest extends MediaWikiLangTestCase {
                );
        }
 
-       public function provideTestParams() {
+       public static function provideTestParams() {
                return array(
                        array( array() ),
                        array( array( 'foo' ), 'foo' ),
index 86e8e8b..2585811 100644 (file)
@@ -47,7 +47,7 @@ class TestSample extends MediaWikiLangTestCase {
         * If you want to run a the same test with a variety of data, use a data provider.
         * see: http://www.phpunit.de/manual/3.4/en/writing-tests-for-phpunit.html
         */
-       public function provideTitles() {
+       public static function provideTitles() {
                return array(
                        array( 'Text', NS_MEDIA, 'Media:Text' ),
                        array( 'Text', null, 'Text' ),
index e4c7623..0f7069a 100644 (file)
@@ -64,7 +64,7 @@ class TitleArrayFromResultTest extends MediaWikiTestCase {
                $this->assertEquals( $title, $object->current->mTextform );
        }
 
-       public function provideNumberOfRows() {
+       public static function provideNumberOfRows() {
                return array(
                        array( 0 ),
                        array( 1 ),
index 97f6146..53c22b4 100644 (file)
@@ -39,7 +39,7 @@ class TitleTest extends MediaWikiTestCase {
                }
        }
 
-       public function provideValidSecureAndSplit() {
+       public static function provideValidSecureAndSplit() {
                return array(
                        array( 'Sandbox' ),
                        array( 'A "B"' ),
@@ -76,7 +76,7 @@ class TitleTest extends MediaWikiTestCase {
                );
        }
 
-       public function provideInvalidSecureAndSplit() {
+       public static function provideInvalidSecureAndSplit() {
                return array(
                        array( '' ),
                        array( ':' ),
@@ -288,10 +288,7 @@ class TitleTest extends MediaWikiTestCase {
                }
        }
 
-       /**
-        * Provides test parameter values for testIsValidMoveOperation()
-        */
-       public function dataTestIsValidMoveOperation() {
+       public static function provideTestIsValidMoveOperation() {
                return array(
                        array( 'Test', 'Test', 'selfmove' ),
                        array( 'File:Test.jpg', 'Page', 'imagenocrossnamespace' )
@@ -415,13 +412,6 @@ class TitleTest extends MediaWikiTestCase {
                return $result;
        }
 
-       public static function provideTestIsValidMoveOperation() {
-               return array(
-                       array( 'Test', 'Test', 'selfmove' ),
-                       array( 'File:Test.jpg', 'Page', 'imagenocrossnamespace' )
-               );
-       }
-
        /**
         * @dataProvider provideGetPageViewLanguage
         * @covers Title::getPageViewLanguage
@@ -548,7 +538,7 @@ class TitleTest extends MediaWikiTestCase {
                );
        }
 
-       public function provideNewFromTitleValue() {
+       public static function provideNewFromTitleValue() {
                return array(
                        array( new TitleValue( NS_MAIN, 'Foo' ) ),
                        array( new TitleValue( NS_MAIN, 'Foo', 'bar' ) ),
@@ -568,7 +558,7 @@ class TitleTest extends MediaWikiTestCase {
                $this->assertEquals( $value->getFragment(), $title->getFragment() );
        }
 
-       public function provideGetTitleValue() {
+       public static function provideGetTitleValue() {
                return array(
                        array( 'Foo' ),
                        array( 'Foo#bar' ),
@@ -589,7 +579,7 @@ class TitleTest extends MediaWikiTestCase {
                $this->assertEquals( $title->getFragment(), $value->getFragment() );
        }
 
-       public function provideGetFragment() {
+       public static function provideGetFragment() {
                return array(
                        array( 'Foo', '' ),
                        array( 'Foo#bar', 'bar' ),
@@ -629,7 +619,7 @@ class TitleTest extends MediaWikiTestCase {
                $this->assertEquals( $isKnown, $title->isAlwaysKnown() );
        }
 
-       public function provideIsAlwaysKnown() {
+       public static function provideIsAlwaysKnown() {
                return array(
                        array( 'Some nonexistent page', false ),
                        array( 'UTPage', false ),
index ea44f36..62989fa 100644 (file)
@@ -61,7 +61,7 @@ class UserArrayFromResultTest extends MediaWikiTestCase {
                $this->assertEquals( $username, $object->current->mName );
        }
 
-       public function provideNumberOfRows() {
+       public static function provideNumberOfRows() {
                return array(
                        array( 0 ),
                        array( 1 ),
index cabbf10..933fed0 100644 (file)
@@ -338,7 +338,7 @@ class UserTest extends MediaWikiTestCase {
                }
        }
 
-       public function provideGetCanonicalName() {
+       public static function provideGetCanonicalName() {
                return array(
                        array( ' trailing space ', array( 'creatable' => 'Trailing space' ), 'Trailing spaces' ),
                        // @todo FIXME: Maybe the createable name should be 'Talk:Username' or false to reject?
index 907ce79..0dbb010 100644 (file)
@@ -14,7 +14,7 @@ class XmlJs extends MediaWikiTestCase {
                $this->assertEquals( $value, $obj->value );
        }
 
-       public function provideConstruction() {
+       public static function provideConstruction() {
                return array(
                        array( null ),
                        array( '' ),
index eb370d9..cc6fb11 100644 (file)
@@ -7,6 +7,7 @@
  * @author Thiemo Mättig
  *
  * @group Action
+ * @group Database
  */
 class ActionTest extends MediaWikiTestCase {
 
index 3a36b9f..2ea9f33 100644 (file)
@@ -29,7 +29,8 @@ class OldChangesListTest extends MediaWikiLangTestCase {
                parent::setUp();
 
                $this->setMwGlobals( array(
-                       'wgArticlePath' => '/wiki/$1'
+                       'wgArticlePath' => '/wiki/$1',
+                       'wgLang' => Language::factory( 'qqx' )
                ) );
        }
 
@@ -76,12 +77,9 @@ class OldChangesListTest extends MediaWikiLangTestCase {
 
                $line = $oldChangesList->recentChangesLine( $recentChange, false, 1 );
 
-               $message = new Message( 'dellogpage' );
-               $expectedLinkText = $message->inLanguage( 'en' )->text();
-
                $this->assertRegExp( '/href="\/wiki\/Special:Log\/delete/', $line, 'link has href attribute' );
                $this->assertRegExp( '/title="Special:Log\/delete/', $line, 'link has title attribute' );
-               $this->assertRegExp( "/$expectedLinkText/", $line, 'link text' );
+               $this->assertRegExp( "/dellogpage/", $line, 'link text' );
        }
 
        public function testRecentChangesLine_DiffHistLinks() {
@@ -110,14 +108,14 @@ class OldChangesListTest extends MediaWikiLangTestCase {
 
                $line = $oldChangesList->recentChangesLine( $recentChange, false, 1 );
 
-               $this->assertRegExp(
-                       "/<abbr class='newpage' title='This edit created a new page'>N<\/abbr>/",
+               $this->assertContains(
+                       "<abbr class='newpage' title='(recentchanges-label-newpage)'>(newpageletter)</abbr>",
                        $line,
                        'new page flag'
                );
 
-               $this->assertRegExp(
-                       "/<abbr class='botedit' title='This edit was performed by a bot'>b<\/abbr>/",
+               $this->assertContains(
+                       "<abbr class='botedit' title='(recentchanges-label-bot)'>(boteditletter)</abbr>",
                        $line,
                        'bot flag'
                );
@@ -181,9 +179,7 @@ class OldChangesListTest extends MediaWikiLangTestCase {
        private function getContext() {
                $user = $this->getTestUser();
                $context = $this->testRecentChangesHelper->getTestContext( $user );
-
-               $title = Title::newFromText( 'RecentChanges', NS_SPECIAL );
-               $context->setTitle( $title );
+               $context->setLanguage( Language::factory( 'qqx' ) );
 
                return $context;
        }
index 0da0775..ad64327 100644 (file)
@@ -129,6 +129,9 @@ class TestRecentChangesHelper {
 
                $context->setUser( $user );
 
+               $title = Title::newFromText( 'RecentChanges', NS_SPECIAL );
+               $context->setTitle( $title );
+
                return $context;
        }
 }
index b15ffa7..70b9e68 100644 (file)
@@ -38,7 +38,19 @@ class GlobalVarConfigTest extends MediaWikiTestCase {
                );
        }
 
-       public function provideGet() {
+       /**
+        * @covers GlobalVarConfig::has
+        */
+       public function testHas() {
+               $this->maybeStashGlobal( 'wgGlobalVarConfigTestHas' );
+               $GLOBALS['wgGlobalVarConfigTestHas'] = wfRandomString();
+               $this->maybeStashGlobal( 'wgGlobalVarConfigTestNotHas' );
+               $config = new GlobalVarConfig();
+               $this->assertTrue( $config->has( 'GlobalVarConfigTestHas' ) );
+               $this->assertFalse( $config->has( 'GlobalVarConfigTestNotHas' ) );
+       }
+
+       public static function provideGet() {
                $set = array(
                        'wgSomething' => 'default1',
                        'wgFoo' => 'default2',
@@ -70,7 +82,7 @@ class GlobalVarConfigTest extends MediaWikiTestCase {
        public function testGet( $name, $prefix, $expected ) {
                $config = new GlobalVarConfig( $prefix );
                if ( $expected === false ) {
-                       $this->setExpectedException( 'ConfigException', 'GlobalVarConfig::getWithPrefix: undefined variable:' );
+                       $this->setExpectedException( 'ConfigException', 'GlobalVarConfig::get: undefined option:' );
                }
                $this->assertEquals( $config->get( $name ), $expected );
        }
diff --git a/tests/phpunit/includes/config/HashConfigTest.php b/tests/phpunit/includes/config/HashConfigTest.php
new file mode 100644 (file)
index 0000000..3ad3bfb
--- /dev/null
@@ -0,0 +1,63 @@
+<?php
+
+class HashConfigTest extends MediaWikiTestCase {
+
+       /**
+        * @covers HashConfig::newInstance
+        */
+       public function testNewInstance() {
+               $conf = HashConfig::newInstance();
+               $this->assertInstanceOf( 'HashConfig', $conf );
+       }
+
+       /**
+        * @covers HashConfig::__construct
+        */
+       public function testConstructor() {
+               $conf = new HashConfig();
+               $this->assertInstanceOf( 'HashConfig', $conf );
+
+               // Test passing arguments to the constructor
+               $conf2 = new HashConfig( array(
+                       'one' => '1',
+               ) );
+               $this->assertEquals( '1', $conf2->get( 'one' ) );
+       }
+
+       /**
+        * @covers HashConfig::get
+        */
+       public function testGet() {
+               $conf = new HashConfig( array(
+                       'one' => '1',
+               ));
+               $this->assertEquals( '1', $conf->get( 'one' ) );
+               $this->setExpectedException( 'ConfigException', 'HashConfig::get: undefined option' );
+               $conf->get( 'two' );
+       }
+
+       /**
+        * @covers HashConfig::has
+        */
+       public function testHas() {
+               $conf = new HashConfig( array(
+                       'one' => '1',
+               ) );
+               $this->assertTrue( $conf->has( 'one' ) );
+               $this->assertFalse( $conf->has( 'two' ) );
+       }
+
+       /**
+        * @covers HashConfig::set
+        */
+       public function testSet() {
+               $conf = new HashConfig( array(
+                       'one' => '1',
+               ) );
+               $conf->set( 'two', '2' );
+               $this->assertEquals( '2', $conf->get( 'two' ) );
+               // Check that set overwrites
+               $conf->set( 'one', '3' );
+               $this->assertEquals( '3', $conf->get( 'one' ) );
+       }
+}
\ No newline at end of file
diff --git a/tests/phpunit/includes/config/MultiConfigTest.php b/tests/phpunit/includes/config/MultiConfigTest.php
new file mode 100644 (file)
index 0000000..158da46
--- /dev/null
@@ -0,0 +1,38 @@
+<?php
+
+class MultiConfigTest extends MediaWikiTestCase {
+
+       /**
+        * Tests that settings are fetched in the right order
+        *
+        * @covers MultiConfig::get
+        */
+       public function testGet() {
+               $multi = new MultiConfig( array(
+                       new HashConfig( array( 'foo' => 'bar' ) ),
+                       new HashConfig( array( 'foo' => 'baz', 'bar' => 'foo' ) ),
+                       new HashConfig( array( 'bar' => 'baz' ) ),
+               ) );
+
+               $this->assertEquals( 'bar', $multi->get( 'foo' ) );
+               $this->assertEquals( 'foo', $multi->get( 'bar' ) );
+               $this->setExpectedException( 'ConfigException', 'MultiConfig::get: undefined option:' );
+               $multi->get( 'notset' );
+       }
+
+       /**
+        * @covers MultiConfig::has
+        */
+       public function testHas() {
+               $conf = new MultiConfig( array(
+                       new HashConfig( array( 'foo' => 'foo' ) ),
+                       new HashConfig( array( 'something' => 'bleh' ) ),
+                       new HashConfig( array( 'meh' => 'eh' ) ),
+               ) );
+
+               $this->assertTrue( $conf->has( 'foo' ) );
+               $this->assertTrue( $conf->has( 'something' ) );
+               $this->assertTrue( $conf->has( 'meh' ) );
+               $this->assertFalse( $conf->has( 'what' ) );
+       }
+}
index 6c77d1a..77b542f 100644 (file)
@@ -15,7 +15,7 @@ class JsonContentTest extends MediaWikiLangTestCase {
                $this->assertEquals( $expected, $obj->getJsonData() );
        }
 
-       public function provideValidConstruction() {
+       public static function provideValidConstruction() {
                return array(
                        array( 'foo', CONTENT_MODEL_JSON, false, null ),
                        array( FormatJson::encode( array() ), CONTENT_MODEL_JSON, true, array() ),
@@ -31,7 +31,7 @@ class JsonContentTest extends MediaWikiLangTestCase {
                $this->assertEquals( FormatJson::encode( $data, true ), $obj->beautifyJSON() );
        }
 
-       public function provideDataToEncode() {
+       public static function provideDataToEncode() {
                return array(
                        array( array() ),
                        array( array( 'foo' ) ),
@@ -74,11 +74,10 @@ class JsonContentTest extends MediaWikiLangTestCase {
                $obj = new JsonContent( FormatJson::encode( $data ) );
                $parserOutput = $obj->getParserOutput( $this->getMockTitle(), null, null, true );
                $this->assertInstanceOf( 'ParserOutput', $parserOutput );
-//             var_dump( $parserOutput->getText(), "\n" );
                $this->assertEquals( $expected, $parserOutput->getText() );
        }
 
-       public function provideDataAndParserText() {
+       public static function provideDataAndParserText() {
                return array(
                        array(
                                array(),
index bd4ae35..7becd6f 100644 (file)
@@ -361,6 +361,52 @@ just a test"
                $this->assertEquals( CONTENT_MODEL_WIKITEXT, $content->getContentHandler()->getModelID() );
        }
 
+       public function testRedirectParserOption() {
+               $title = Title::newFromText( 'testRedirectParserOption' );
+
+               // Set up hook and its reporting variables
+               $wikitext = null;
+               $redirectTarget = null;
+               $this->mergeMwGlobalArrayValue( 'wgHooks', array(
+                       'InternalParseBeforeLinks' => array(
+                               function ( &$parser, &$text, &$stripState ) use ( &$wikitext, &$redirectTarget ) {
+                                       $wikitext = $text;
+                                       $redirectTarget = $parser->getOptions()->getRedirectTarget();
+                               }
+                       )
+               ) );
+
+               // Test with non-redirect page
+               $wikitext = false;
+               $redirectTarget = false;
+               $content = $this->newContent( 'hello world.' );
+               $options = $content->getContentHandler()->makeParserOptions( 'canonical' );
+               $options->setRedirectTarget( $title );
+               $content->getParserOutput( $title, null, $options );
+               $this->assertEquals( 'hello world.', $wikitext,
+                       'Wikitext passed to hook was not as expected'
+               );
+               $this->assertEquals( null, $redirectTarget, 'Redirect seen in hook was not null' );
+               $this->assertEquals( $title, $options->getRedirectTarget(),
+                       'ParserOptions\' redirectTarget was changed'
+               );
+
+               // Test with a redirect page
+               $wikitext = false;
+               $redirectTarget = false;
+               $content = $this->newContent( "#REDIRECT [[TestRedirectParserOption/redir]]\nhello redirect." );
+               $options = $content->getContentHandler()->makeParserOptions( 'canonical' );
+               $content->getParserOutput( $title, null, $options );
+               $this->assertEquals( 'hello redirect.', $wikitext, 'Wikitext passed to hook was not as expected' );
+               $this->assertNotEquals( null, $redirectTarget, 'Redirect seen in hook was null' );
+               $this->assertEquals( 'TestRedirectParserOption/redir', $redirectTarget->getFullText(),
+                       'Redirect seen in hook was not the expected title'
+               );
+               $this->assertEquals( null, $options->getRedirectTarget(),
+                       'ParserOptions\' redirectTarget was changed'
+               );
+       }
+
        public static function dataEquals() {
                return array(
                        array( new WikitextContent( "hallo" ), null, false ),
index c45de36..ef0f2a9 100644 (file)
@@ -87,7 +87,7 @@ class MWExceptionTest extends MediaWikiTestCase {
                $this->assertEquals( $expectedReturn, $e->runHooks( $name, $args ) );
        }
 
-       public function provideRunHooks() {
+       public static function provideRunHooks() {
                return array(
                        array( null, null, null, null ),
                        array( array(), 'name', array(), null ),
@@ -134,7 +134,7 @@ class MWExceptionTest extends MediaWikiTestCase {
                $this->assertEquals( $expected, $e->isCommandLine() );
        }
 
-       public function provideIsCommandLine() {
+       public static function provideIsCommandLine() {
                return array(
                        array( false, null ),
                        array( true, true ),
@@ -155,7 +155,7 @@ class MWExceptionTest extends MediaWikiTestCase {
                        "The $exception_class exception should be JSON serializable, got false." );
        }
 
-       public function provideExceptionClasses() {
+       public static function provideExceptionClasses() {
                return array(
                        array( 'Exception' ),
                        array( 'MWException' ),
@@ -192,7 +192,7 @@ class MWExceptionTest extends MediaWikiTestCase {
        /**
         * Returns test cases: exception class, key name, gettype()
         */
-       public function provideJsonSerializedKeys() {
+       public static function provideJsonSerializedKeys() {
                $testCases = array();
                foreach ( array( 'Exception', 'MWException' ) as $exClass ) {
                        $exTests = array(
index aaee512..d4e5214 100644 (file)
@@ -12,7 +12,7 @@ class IPSetTest extends MediaWikiTestCase {
         * config is an array constructor argument for IPSet, and the tests are
         * an array of IP => expected (boolean) result against the config dataset.
         */
-       public function provider() {
+       public static function provideIPSets() {
                return array(
                        array(
                                'old_list_subset',
@@ -240,7 +240,7 @@ class IPSetTest extends MediaWikiTestCase {
         * Validates IPSet loading and matching code
         *
         * @covers IPSet
-        * @dataProvider provider
+        * @dataProvider provideIPSets
         */
        public function testIPSet( $desc, array $cfg, array $tests ) {
                $ipset = new IPSet( $cfg );
index 334d5b5..f80f78d 100644 (file)
@@ -13,7 +13,7 @@ class MWMessagePackTest extends MediaWikiTestCase {
         * using <https://github.com/msgpack/msgpack-php>, which includes a
         * serialization function.
         */
-       public function provider() {
+       public static function providePacks() {
                $tests = array(
                        array( 'nil', null, 'c0' ),
                        array( 'bool', true, 'c3' ),
@@ -66,7 +66,7 @@ class MWMessagePackTest extends MediaWikiTestCase {
        /**
         * Verify that values are serialized correctly.
         * @covers MWMessagePack::pack
-        * @dataProvider provider
+        * @dataProvider providePacks
         */
        public function testPack( $type, $value, $expected ) {
                $actual = bin2hex( MWMessagePack::pack( $value ) );
index 52a51cc..87ffd99 100644 (file)
@@ -116,7 +116,7 @@ class GIFHandlerTest extends MediaWikiMediaTestCase {
                $this->assertEquals( $expected, $actual );
        }
 
-       public function provideGetIndependentMetaArray() {
+       public static function provideGetIndependentMetaArray() {
                return array(
                        array( 'nonanimated.gif', array(
                                'GIFFileComment' => array(
index 092be89..36872a7 100644 (file)
@@ -118,7 +118,7 @@ class PNGHandlerTest extends MediaWikiMediaTestCase {
                $this->assertEquals( $expected, $actual );
        }
 
-       public function provideGetIndependentMetaArray() {
+       public static function provideGetIndependentMetaArray() {
                return array(
                        array( 'rgb-na-png.png', array() ),
                        array( 'xmp.png',
index 1361a92..8f7a0d6 100644 (file)
@@ -28,7 +28,7 @@ class SvgTest extends MediaWikiMediaTestCase {
                $this->assertEquals( $res, $expected );
        }
 
-       public function providerGetIndependentMetaArray() {
+       public static function providerGetIndependentMetaArray() {
                return array(
                        array( 'Tux.svg', array(
                                'ObjectName' => 'Tux',
index 97b76fe..f4b469b 100644 (file)
@@ -110,7 +110,7 @@ class CleanUpTest extends MediaWikiTestCase {
        }
 
        /** @todo document */
-       public function provideAllBytes() {
+       public static function provideAllBytes() {
                return array(
                        array( '', '' ),
                        array( 'x', '' ),
index c869258..f656a74 100644 (file)
@@ -25,7 +25,7 @@ class TidyTest extends MediaWikiTestCase {
                $this->assertEquals( $expected, $text, $msg );
        }
 
-       public function provideTestWrapping() {
+       public static function provideTestWrapping() {
                $testMathML = <<<'MathML'
 <math xmlns="http://www.w3.org/1998/Math/MathML">
     <mrow>
index 4d5c78a..8ac419f 100644 (file)
@@ -11,7 +11,7 @@ class BcryptPasswordTestCase extends PasswordTestCase {
                ) );
        }
 
-       public function providePasswordTests() {
+       public static function providePasswordTests() {
                /** @codingStandardsIgnoreStart Generic.Files.LineLength.TooLong */
                return array(
                        // Tests from glibc bcrypt implementation
index 03a742b..86e8270 100644 (file)
@@ -26,7 +26,7 @@ class LayeredParameterizedPasswordTest extends PasswordTestCase {
                );
        }
 
-       public function providePasswordTests() {
+       public static function providePasswordTests() {
                /** @codingStandardsIgnoreStart Generic.Files.LineLength.TooLong */
                return array(
                        array( true, ':testLargeLayeredTop:sha512:1024:512!sha512:1024:512!sha512:1024:512!sha512:1024:512!5!vnRy+2SrSA0fHt3dwhTP5g==!AVnwfZsAQjn+gULv7FSGjA==!xvHUX3WcpkeSn1lvjWcvBg==!It+OC/N9tu+d3ByHhuB0BQ==!Tb.gqUOiD.aWktVwHM.Q/O!7CcyMfXUPky5ptyATJsR2nq3vUqtnBC', 'testPassword123' ),
index 7820d53..ef16f1c 100644 (file)
@@ -52,7 +52,7 @@ abstract class PasswordTestCase extends MediaWikiTestCase {
         *
         * @return array
         */
-       abstract public function providePasswordTests();
+       abstract public static function providePasswordTests();
 
        /**
         * @dataProvider providePasswordTests
index ae47120..091853e 100644 (file)
@@ -13,7 +13,7 @@ class Pbkdf2PasswordTest extends PasswordTestCase {
                ) );
        }
 
-       public function providePasswordTests() {
+       public static function providePasswordTests() {
                return array(
                        array( true, ":pbkdf2:sha1:1:20:c2FsdA==:DGDID5YfDnHzqbUkr2ASBi/gN6Y=", 'password' ),
                        array( true, ":pbkdf2:sha1:2:20:c2FsdA==:6mwBTcctb4zNHtkqzh1B8NjeiVc=", 'password' ),
index 50f88c8..9dc1805 100644 (file)
@@ -22,7 +22,7 @@ class ResourceLoaderWikiModuleTest extends ResourceLoaderTestCase {
                $this->assertEquals( $expected, $module->isKnownEmpty( $context ) );
        }
 
-       public function provideIsKnownEmpty() {
+       public static function provideIsKnownEmpty() {
                return array(
                        // No valid pages
                        array( array(), 'test1', true ),
diff --git a/tests/phpunit/includes/specialpage/SpecialPageFactoryTest.php b/tests/phpunit/includes/specialpage/SpecialPageFactoryTest.php
new file mode 100644 (file)
index 0000000..b1d4257
--- /dev/null
@@ -0,0 +1,101 @@
+<?php
+/**
+ * Factory for handling the special page list and generating SpecialPage objects.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ *
+ * @covers SpecialPageFactory
+ * @group SpecialPage
+ */
+class SpecialPageFactoryTest extends MediaWikiTestCase {
+
+       public function newSpecialAllPages() {
+               return new SpecialAllPages();
+       }
+
+       public function specialPageProvider() {
+               return array(
+                       'class name' => array( 'SpecialAllPages', false ),
+                       'closure' => array( function() {
+                               return new SpecialAllPages();
+                       }, false ),
+                       'function' => array( array( $this, 'newSpecialAllPages' ), false  ),
+               );
+       }
+
+       /**
+        * @dataProvider specialPageProvider
+        */
+       public function testGetPage( $spec, $shouldReuseInstance ) {
+               $this->mergeMwGlobalArrayValue( 'wgSpecialPages', array( 'testdummy' => $spec ) );
+
+               SpecialPageFactory::resetList();
+
+               $page = SpecialPageFactory::getPage( 'testdummy' );
+               $this->assertInstanceOf( 'SpecialPage', $page );
+
+               $page2 = SpecialPageFactory::getPage( 'testdummy' );
+               $this->assertEquals( $shouldReuseInstance, $page2 === $page, "Should re-use instance:" );
+
+               SpecialPageFactory::resetList();
+       }
+
+       public function testGetNames() {
+               $this->mergeMwGlobalArrayValue( 'wgSpecialPages', array( 'testdummy' => 'SpecialAllPages' ) );
+
+               SpecialPageFactory::resetList();
+               $names = SpecialPageFactory::getNames();
+               $this->assertInternalType( 'array', $names );
+               $this->assertContains( 'testdummy', $names );
+               SpecialPageFactory::resetList();
+       }
+
+       public function testResolveAlias() {
+               $this->setMwGlobals( 'wgContLang', Language::factory( 'de' ) );
+
+               SpecialPageFactory::resetList();
+
+               list( $name, $param ) = SpecialPageFactory::resolveAlias( 'Spezialseiten/Foo' );
+               $this->assertEquals( 'Specialpages', $name );
+               $this->assertEquals( 'Foo', $param );
+
+               SpecialPageFactory::resetList();
+       }
+
+       public function testGetLocalNameFor() {
+               $this->setMwGlobals( 'wgContLang', Language::factory( 'de' ) );
+
+               SpecialPageFactory::resetList();
+
+               $name = SpecialPageFactory::getLocalNameFor( 'Specialpages', 'Foo' );
+               $this->assertEquals( 'Spezialseiten/Foo', $name );
+
+               SpecialPageFactory::resetList();
+       }
+
+       public function testGetTitleForAlias() {
+               $this->setMwGlobals( 'wgContLang', Language::factory( 'de' ) );
+
+               SpecialPageFactory::resetList();
+
+               $title = SpecialPageFactory::getTitleForAlias( 'Specialpages/Foo' );
+               $this->assertEquals( 'Spezialseiten/Foo', $title->getText() );
+               $this->assertEquals( NS_SPECIAL, $title->getNamespace() );
+
+               SpecialPageFactory::resetList();
+       }
+
+}
index 8a0ac97..22bdefd 100644 (file)
@@ -6,6 +6,7 @@
  * Copyright © 2013, Siebrand Mazeland
  * Copyright © 2013, Wikimedia Foundation Inc.
  *
+ * @group Database
  */
 
 class ImageListPagerTest extends MediaWikiTestCase {
index bd95281..14d1968 100644 (file)
@@ -1,4 +1,8 @@
 <?php
+/**
+ * @group Database
+ */
+
 class SpecialMIMESearchTest extends MediaWikiTestCase {
 
        /** @var MIMESearchPage */
index fd09043..4dbfc41 100644 (file)
@@ -53,7 +53,7 @@ class SpecialMyLanguageTest extends MediaWikiTestCase {
                $this->assertEquals( $expected, $title );
        }
 
-       public function provideFindTitle() {
+       public static function provideFindTitle() {
                return array(
                        array( null, '::Fail', 'en', 'en' ),
                        array( 'Page/Another', 'Page/Another/en', 'en', 'en' ),
index b13df89..4171c10 100644 (file)
@@ -24,6 +24,7 @@
  * @covers MediaWikiPageLinkRenderer
  *
  * @group Title
+ * @group Database
  */
 class MediaWikiPageLinkRendererTest extends MediaWikiTestCase {
 
@@ -52,7 +53,7 @@ class MediaWikiPageLinkRendererTest extends MediaWikiTestCase {
                return $genderCache;
        }
 
-       public function provideGetPageUrl() {
+       public static function provideGetPageUrl() {
                return array(
                        array(
                                new TitleValue( NS_MAIN, 'Foo_Bar' ),
@@ -85,7 +86,7 @@ class MediaWikiPageLinkRendererTest extends MediaWikiTestCase {
                $this->assertEquals( $url, $actual );
        }
 
-       public function provideRenderHtmlLink() {
+       public static function provideRenderHtmlLink() {
                return array(
                        array(
                                new TitleValue( NS_MAIN, 'Foo_Bar' ),
@@ -127,7 +128,7 @@ class MediaWikiPageLinkRendererTest extends MediaWikiTestCase {
                $this->assertRegExp( $pattern, $actual );
        }
 
-       public function provideRenderWikitextLink() {
+       public static function provideRenderWikitextLink() {
                return array(
                        array(
                                new TitleValue( NS_MAIN, 'Foo_Bar' ),
index bf06e3b..f95b305 100644 (file)
@@ -85,7 +85,7 @@ class MediaWikiTitleCodecTest extends MediaWikiTestCase {
                return new MediaWikiTitleCodec( $lang, $gender );
        }
 
-       public function provideFormat() {
+       public static function provideFormat() {
                return array(
                        array( NS_MAIN, 'Foo_Bar', '', 'en', 'Foo Bar' ),
                        array( NS_USER, 'Hansi_Maier', 'stuff_and_so_on', 'en', 'User:Hansi Maier#stuff and so on' ),
@@ -129,7 +129,7 @@ class MediaWikiTitleCodecTest extends MediaWikiTestCase {
                $this->assertEquals( $normalized, $actual2, 'normalized after round trip' );
        }
 
-       public function provideGetText() {
+       public static function provideGetText() {
                return array(
                        array( NS_MAIN, 'Foo_Bar', '', 'en', 'Foo Bar' ),
                        array( NS_USER, 'Hansi_Maier', 'stuff_and_so_on', 'en', 'Hansi Maier' ),
@@ -148,7 +148,7 @@ class MediaWikiTitleCodecTest extends MediaWikiTestCase {
                $this->assertEquals( $expected, $actual );
        }
 
-       public function provideGetPrefixedText() {
+       public static function provideGetPrefixedText() {
                return array(
                        array( NS_MAIN, 'Foo_Bar', '', 'en', 'Foo Bar' ),
                        array( NS_USER, 'Hansi_Maier', 'stuff_and_so_on', 'en', 'User:Hansi Maier' ),
@@ -174,7 +174,7 @@ class MediaWikiTitleCodecTest extends MediaWikiTestCase {
                $this->assertEquals( $expected, $actual );
        }
 
-       public function provideGetFullText() {
+       public static function provideGetFullText() {
                return array(
                        array( NS_MAIN, 'Foo_Bar', '', 'en', 'Foo Bar' ),
                        array( NS_USER, 'Hansi_Maier', 'stuff_and_so_on', 'en', 'User:Hansi Maier#stuff and so on' ),
@@ -196,7 +196,7 @@ class MediaWikiTitleCodecTest extends MediaWikiTestCase {
                $this->assertEquals( $expected, $actual );
        }
 
-       public function provideParseTitle() {
+       public static function provideParseTitle() {
                //TODO: test capitalization and trimming
                //TODO: test unicode normalization
 
@@ -281,7 +281,7 @@ class MediaWikiTitleCodecTest extends MediaWikiTestCase {
                $this->assertEquals( $title, $actual );
        }
 
-       public function provideParseTitle_invalid() {
+       public static function provideParseTitle_invalid() {
                //TODO: test unicode errors
 
                return array(
@@ -353,7 +353,7 @@ class MediaWikiTitleCodecTest extends MediaWikiTestCase {
                $codec->parseTitle( $text, NS_MAIN );
        }
 
-       public function provideGetNamespaceName() {
+       public static function provideGetNamespaceName() {
                return array(
                        array( NS_MAIN, 'Foo', 'en', '' ),
                        array( NS_USER, 'Foo', 'en', 'User' ),
index fdd40b2..d5d1188 100644 (file)
@@ -68,7 +68,7 @@ class UploadStashTest extends MediaWikiTestCase {
                $stash->removeFile( $file->getFileKey() );
        }
 
-       public function provideInvalidRequests() {
+       public static function provideInvalidRequests() {
                return array(
                        'Check failure on bad wpFileKey' =>
                                array( new FauxRequest( array( 'wpFileKey' => 'foo' ) ) ),
@@ -84,7 +84,7 @@ class UploadStashTest extends MediaWikiTestCase {
                $this->assertFalse( UploadFromStash::isValidRequest( $request ) );
        }
 
-       public function provideValidRequests() {
+       public static function provideValidRequests() {
                return array(
                        'Check good wpFileKey' =>
                                array( new FauxRequest( array( 'wpFileKey' => 'testkey-test.test' ) ) ),