Merge "Log a backtrace from the culprit location if headers were already sent"
authorjenkins-bot <jenkins-bot@gerrit.wikimedia.org>
Fri, 24 Feb 2017 22:41:45 +0000 (22:41 +0000)
committerGerrit Code Review <gerrit@wikimedia.org>
Fri, 24 Feb 2017 22:41:45 +0000 (22:41 +0000)
321 files changed:
.eslintrc.json
.stylelintrc
.travis.yml
Gruntfile.js
HISTORY
RELEASE-NOTES-1.29
autoload.php
composer.json
includes/DefaultSettings.php
includes/EditPage.php
includes/GlobalFunctions.php
includes/Linker.php
includes/MediaWikiServices.php
includes/WatchedItemQueryService.php
includes/WatchedItemStore.php
includes/WebRequest.php
includes/actions/HistoryAction.php
includes/actions/RollbackAction.php
includes/api/ApiAuthManagerHelper.php
includes/api/ApiMain.php
includes/api/i18n/de.json
includes/api/i18n/en.json
includes/api/i18n/fr.json
includes/api/i18n/gl.json
includes/api/i18n/he.json
includes/api/i18n/ko.json
includes/api/i18n/nl.json
includes/api/i18n/qqq.json
includes/api/i18n/ru.json
includes/api/i18n/uk.json
includes/api/i18n/zh-hans.json
includes/changes/ChangesList.php
includes/changes/EnhancedChangesList.php
includes/collation/Collation.php
includes/dao/DBAccessBase.php
includes/db/MWLBFactory.php
includes/debug/logger/monolog/AvroFormatter.php
includes/debug/logger/monolog/LogstashFormatter.php
includes/deferred/DeferredUpdates.php
includes/exception/MWExceptionHandler.php
includes/externalstore/ExternalStoreDB.php
includes/installer/MssqlInstaller.php
includes/installer/PostgresInstaller.php
includes/installer/i18n/bg.json
includes/installer/i18n/mk.json
includes/installer/i18n/nl.json
includes/libs/rdbms/connectionmanager/ConnectionManager.php
includes/libs/rdbms/database/Database.php
includes/libs/rdbms/encasing/Blob.php
includes/libs/rdbms/field/Field.php
includes/libs/rdbms/lbfactory/ILBFactory.php
includes/libs/rdbms/lbfactory/LBFactory.php
includes/libs/rdbms/lbfactory/LBFactoryMulti.php
includes/libs/rdbms/lbfactory/LBFactorySimple.php
includes/libs/rdbms/lbfactory/LBFactorySingle.php
includes/libs/rdbms/loadbalancer/ILoadBalancer.php
includes/libs/rdbms/loadbalancer/LoadBalancer.php
includes/libs/rdbms/loadbalancer/LoadBalancerSingle.php
includes/logging/LogEventsList.php
includes/objectcache/SqlBagOStuff.php
includes/page/Article.php
includes/page/ImagePage.php
includes/parser/Parser.php
includes/resourceloader/ResourceLoaderModule.php
includes/resourceloader/ResourceLoaderWikiModule.php
includes/site/DBSiteStore.php
includes/specials/SpecialUpload.php
includes/user/User.php
includes/utils/AutoloadGenerator.php
includes/widget/search/SearchFormWidget.php
languages/i18n/ar.json
languages/i18n/arn.json
languages/i18n/azb.json
languages/i18n/be-tarask.json
languages/i18n/be.json
languages/i18n/bg.json
languages/i18n/bn.json
languages/i18n/br.json
languages/i18n/bs.json
languages/i18n/crh-cyrl.json
languages/i18n/crh-latn.json
languages/i18n/cs.json
languages/i18n/da.json
languages/i18n/de.json
languages/i18n/diq.json
languages/i18n/el.json
languages/i18n/en.json
languages/i18n/es.json
languages/i18n/et.json
languages/i18n/fa.json
languages/i18n/fi.json
languages/i18n/fr.json
languages/i18n/gd.json
languages/i18n/gl.json
languages/i18n/he.json
languages/i18n/hi.json
languages/i18n/hr.json
languages/i18n/it.json
languages/i18n/ko.json
languages/i18n/ku-latn.json
languages/i18n/lb.json
languages/i18n/lv.json
languages/i18n/mg.json
languages/i18n/mhr.json
languages/i18n/mk.json
languages/i18n/nl.json
languages/i18n/oc.json
languages/i18n/pl.json
languages/i18n/pnb.json
languages/i18n/pt.json
languages/i18n/qqq.json
languages/i18n/ru.json
languages/i18n/rue.json
languages/i18n/sdh.json
languages/i18n/sr-ec.json
languages/i18n/sr-el.json
languages/i18n/ta.json
languages/i18n/th.json
languages/i18n/zh-hans.json
languages/i18n/zh-hant.json
languages/messages/MessagesCa.php
maintenance/CodeCleanerGlobalsPass.inc [new file with mode: 0644]
maintenance/backup.inc
maintenance/dumpTextPass.php
maintenance/shell.php [new file with mode: 0644]
mw-config/config-cc.css
mw-config/config.css
resources/Resources.php
resources/src/jquery/jquery.arrowSteps.css
resources/src/jquery/jquery.badge.css
resources/src/jquery/jquery.byteLimit.js
resources/src/jquery/jquery.farbtastic.css
resources/src/jquery/jquery.qunit.completenessTest.js
resources/src/jquery/jquery.spinner.css
resources/src/jquery/jquery.suggestions.css
resources/src/jquery/jquery.suggestions.js
resources/src/jquery/jquery.tablesorter.js
resources/src/jquery/jquery.textSelection.js
resources/src/mediawiki.action/mediawiki.action.edit.css
resources/src/mediawiki.action/mediawiki.action.edit.preview.js
resources/src/mediawiki.action/mediawiki.action.edit.styles.css
resources/src/mediawiki.action/mediawiki.action.view.dblClickEdit.js
resources/src/mediawiki.action/mediawiki.action.view.filepage.css
resources/src/mediawiki.action/mediawiki.action.view.postEdit.css
resources/src/mediawiki.action/mediawiki.action.view.rightClickEdit.js
resources/src/mediawiki.legacy/commonPrint.css
resources/src/mediawiki.legacy/oldshared.css
resources/src/mediawiki.legacy/shared.css
resources/src/mediawiki.less/mediawiki.mixins.animation.less
resources/src/mediawiki.less/mediawiki.mixins.less
resources/src/mediawiki.rcfilters/dm/mw.rcfilters.dm.FilterItem.js
resources/src/mediawiki.rcfilters/dm/mw.rcfilters.dm.FiltersViewModel.js
resources/src/mediawiki.rcfilters/mw.rcfilters.Controller.js
resources/src/mediawiki.rcfilters/mw.rcfilters.HighlightColors.js [new file with mode: 0644]
resources/src/mediawiki.rcfilters/mw.rcfilters.init.js
resources/src/mediawiki.rcfilters/styles/mw.rcfilters.less [new file with mode: 0644]
resources/src/mediawiki.rcfilters/styles/mw.rcfilters.mixins.less [new file with mode: 0644]
resources/src/mediawiki.rcfilters/styles/mw.rcfilters.ui.CapsuleItemWidget.less
resources/src/mediawiki.rcfilters/styles/mw.rcfilters.ui.ChangesListWrapperWidget.less [new file with mode: 0644]
resources/src/mediawiki.rcfilters/styles/mw.rcfilters.ui.FilterCapsuleMultiselectWidget.less
resources/src/mediawiki.rcfilters/styles/mw.rcfilters.ui.FilterItemHighlightButton.less [new file with mode: 0644]
resources/src/mediawiki.rcfilters/styles/mw.rcfilters.ui.FilterItemWidget.less
resources/src/mediawiki.rcfilters/styles/mw.rcfilters.ui.FilterWrapperWidget.less
resources/src/mediawiki.rcfilters/styles/mw.rcfilters.ui.FiltersListWidget.less
resources/src/mediawiki.rcfilters/styles/mw.rcfilters.ui.HighlightColorPickerWidget.less [new file with mode: 0644]
resources/src/mediawiki.rcfilters/styles/mw.rcfilters.ui.less [new file with mode: 0644]
resources/src/mediawiki.rcfilters/styles/mw.rcfilters.variables.less [new file with mode: 0644]
resources/src/mediawiki.rcfilters/ui/mw.rcfilters.ui.CapsuleItemWidget.js
resources/src/mediawiki.rcfilters/ui/mw.rcfilters.ui.ChangesListWrapperWidget.js
resources/src/mediawiki.rcfilters/ui/mw.rcfilters.ui.FilterCapsuleMultiselectWidget.js
resources/src/mediawiki.rcfilters/ui/mw.rcfilters.ui.FilterGroupWidget.js
resources/src/mediawiki.rcfilters/ui/mw.rcfilters.ui.FilterItemHighlightButton.js [new file with mode: 0644]
resources/src/mediawiki.rcfilters/ui/mw.rcfilters.ui.FilterItemWidget.js
resources/src/mediawiki.rcfilters/ui/mw.rcfilters.ui.FilterWrapperWidget.js
resources/src/mediawiki.rcfilters/ui/mw.rcfilters.ui.FiltersListWidget.js
resources/src/mediawiki.rcfilters/ui/mw.rcfilters.ui.HighlightColorPickerWidget.js [new file with mode: 0644]
resources/src/mediawiki.skinning/content.css
resources/src/mediawiki.skinning/content.externallinks.css
resources/src/mediawiki.skinning/content.parsoid.less
resources/src/mediawiki.skinning/elements.css
resources/src/mediawiki.skinning/interface.css
resources/src/mediawiki.special/mediawiki.special.apisandbox.css
resources/src/mediawiki.special/mediawiki.special.css
resources/src/mediawiki.special/mediawiki.special.search.interwikiwidget.styles.less
resources/src/mediawiki.special/mediawiki.special.search.styles.css
resources/src/mediawiki.special/mediawiki.special.upload.js
resources/src/mediawiki.special/mediawiki.special.upload.styles.css
resources/src/mediawiki.ui/components/anchors.less
resources/src/mediawiki.ui/components/buttons.less
resources/src/mediawiki.ui/components/checkbox.less
resources/src/mediawiki.ui/components/icons.less
resources/src/mediawiki.ui/components/inputs.less
resources/src/mediawiki.ui/components/radio.less
resources/src/mediawiki.ui/components/text.less
resources/src/mediawiki.widgets.datetime/CalendarWidget.less
resources/src/mediawiki.widgets.datetime/DateTimeInputWidget.less
resources/src/mediawiki.widgets/mw.widgets.CalendarWidget.less
resources/src/mediawiki.widgets/mw.widgets.StashedFileWidget.less
resources/src/mediawiki.widgets/mw.widgets.TitleWidget.js
resources/src/mediawiki.widgets/mw.widgets.TitleWidget.less
resources/src/mediawiki/api.js
resources/src/mediawiki/htmlform/styles.css
resources/src/mediawiki/mediawiki.ForeignStructuredUpload.BookletLayout.less
resources/src/mediawiki/mediawiki.Upload.BookletLayout.css
resources/src/mediawiki/mediawiki.apihelp.css
resources/src/mediawiki/mediawiki.debug.less
resources/src/mediawiki/mediawiki.diff.styles.css
resources/src/mediawiki/mediawiki.feedback.css
resources/src/mediawiki/mediawiki.hlist.css
resources/src/mediawiki/mediawiki.js
resources/src/mediawiki/mediawiki.util.js
resources/src/mediawiki/page/gallery-slideshow.js
resources/src/mediawiki/page/gallery.css
resources/src/mediawiki/page/gallery.print.css
resources/src/mediawiki/page/image-pagination.js
resources/src/mediawiki/page/watch.js
tests/common/TestSetup.php
tests/parser/ParserTestRunner.php
tests/parser/README
tests/parser/parserTests.txt
tests/phan/config.php
tests/phpunit/includes/BlockTest.php
tests/phpunit/includes/EditPageTest.php
tests/phpunit/includes/ExtraParserTest.php
tests/phpunit/includes/GlobalFunctions/wfTimestampTest.php
tests/phpunit/includes/MessageTest.php
tests/phpunit/includes/PreferencesTest.php
tests/phpunit/includes/PrefixSearchTest.php
tests/phpunit/includes/SanitizerTest.php
tests/phpunit/includes/SanitizerValidateEmailTest.php
tests/phpunit/includes/TitleTest.php
tests/phpunit/includes/XmlTest.php
tests/phpunit/includes/api/ApiEditPageTest.php
tests/phpunit/includes/api/ApiMainTest.php
tests/phpunit/includes/api/ApiQueryAllPagesTest.php
tests/phpunit/includes/api/query/ApiQueryBasicTest.php
tests/phpunit/includes/cache/LocalisationCacheTest.php
tests/phpunit/includes/cache/MessageCacheTest.php
tests/phpunit/includes/db/DatabaseMysqlBaseTest.php
tests/phpunit/includes/deferred/SearchUpdateTest.php
tests/phpunit/includes/http/HttpTest.php
tests/phpunit/includes/libs/CSSMinTest.php
tests/phpunit/includes/libs/JavaScriptMinifierTest.php
tests/phpunit/includes/libs/mime/MimeAnalyzerTest.php
tests/phpunit/includes/libs/rdbms/connectionmanager/ConnectionManagerTest.php
tests/phpunit/includes/libs/rdbms/connectionmanager/SessionConsistentConnectionManagerTest.php
tests/phpunit/includes/libs/xmp/XMPTest.php
tests/phpunit/includes/logging/LogFormatterTest.php
tests/phpunit/includes/media/FormatMetadataTest.php
tests/phpunit/includes/media/SVGMetadataExtractorTest.php
tests/phpunit/includes/page/ArticleTablesTest.php
tests/phpunit/includes/parser/ParserPreloadTest.php
tests/phpunit/includes/parser/PreprocessorTest.php
tests/phpunit/includes/resourceloader/ResourceLoaderTest.php
tests/phpunit/includes/search/SearchEnginePrefixTest.php
tests/phpunit/includes/specials/SpecialBooksourcesTest.php
tests/phpunit/includes/specials/SpecialRecentchangesTest.php
tests/phpunit/includes/specials/SpecialSearchTest.php
tests/phpunit/includes/upload/UploadBaseTest.php
tests/phpunit/includes/upload/UploadStashTest.php
tests/phpunit/includes/user/UserTest.php
tests/phpunit/includes/utils/ClassCollectorTest.php [new file with mode: 0644]
tests/phpunit/languages/LanguageTest.php
tests/phpunit/languages/classes/LanguageBe_taraskTest.php
tests/phpunit/languages/classes/LanguageMlTest.php
tests/phpunit/languages/classes/LanguageTrTest.php
tests/phpunit/maintenance/backupPrefetchTest.php
tests/phpunit/mocks/filebackend/MockFSFile.php
tests/phpunit/skins/SideBarTest.php
tests/phpunit/structure/AutoLoaderTest.php
tests/qunit/.eslintrc.json [new file with mode: 0644]
tests/qunit/data/generateJqueryMsgData.php
tests/qunit/data/mediawiki.jqueryMsg.data.js
tests/qunit/data/testrunner.js
tests/qunit/suites/resources/jquery/jquery.accessKeyLabel.test.js
tests/qunit/suites/resources/jquery/jquery.autoEllipsis.test.js
tests/qunit/suites/resources/jquery/jquery.byteLength.test.js
tests/qunit/suites/resources/jquery/jquery.byteLimit.test.js
tests/qunit/suites/resources/jquery/jquery.colorUtil.test.js
tests/qunit/suites/resources/jquery/jquery.getAttrs.test.js
tests/qunit/suites/resources/jquery/jquery.hidpi.test.js
tests/qunit/suites/resources/jquery/jquery.highlightText.test.js
tests/qunit/suites/resources/jquery/jquery.localize.test.js
tests/qunit/suites/resources/jquery/jquery.makeCollapsible.test.js
tests/qunit/suites/resources/jquery/jquery.mwExtension.test.js
tests/qunit/suites/resources/jquery/jquery.placeholder.test.js
tests/qunit/suites/resources/jquery/jquery.tabIndex.test.js
tests/qunit/suites/resources/jquery/jquery.tablesorter.parsers.test.js
tests/qunit/suites/resources/jquery/jquery.tablesorter.test.js
tests/qunit/suites/resources/jquery/jquery.textSelection.test.js
tests/qunit/suites/resources/mediawiki.api/mediawiki.ForeignApi.test.js
tests/qunit/suites/resources/mediawiki.api/mediawiki.api.category.test.js
tests/qunit/suites/resources/mediawiki.api/mediawiki.api.edit.test.js
tests/qunit/suites/resources/mediawiki.api/mediawiki.api.messages.test.js
tests/qunit/suites/resources/mediawiki.api/mediawiki.api.options.test.js
tests/qunit/suites/resources/mediawiki.api/mediawiki.api.parse.test.js
tests/qunit/suites/resources/mediawiki.api/mediawiki.api.test.js
tests/qunit/suites/resources/mediawiki.api/mediawiki.api.upload.test.js
tests/qunit/suites/resources/mediawiki.rcfilters/dm.FiltersViewModel.test.js
tests/qunit/suites/resources/mediawiki.special/mediawiki.special.recentchanges.test.js
tests/qunit/suites/resources/mediawiki/mediawiki.RegExp.test.js
tests/qunit/suites/resources/mediawiki/mediawiki.Title.test.js
tests/qunit/suites/resources/mediawiki/mediawiki.Uri.test.js
tests/qunit/suites/resources/mediawiki/mediawiki.cldr.test.js
tests/qunit/suites/resources/mediawiki/mediawiki.cookie.test.js
tests/qunit/suites/resources/mediawiki/mediawiki.errorLogger.test.js
tests/qunit/suites/resources/mediawiki/mediawiki.experiments.test.js
tests/qunit/suites/resources/mediawiki/mediawiki.html.test.js
tests/qunit/suites/resources/mediawiki/mediawiki.jqueryMsg.test.js
tests/qunit/suites/resources/mediawiki/mediawiki.jscompat.test.js
tests/qunit/suites/resources/mediawiki/mediawiki.language.test.js
tests/qunit/suites/resources/mediawiki/mediawiki.loader.test.js
tests/qunit/suites/resources/mediawiki/mediawiki.messagePoster.factory.test.js
tests/qunit/suites/resources/mediawiki/mediawiki.template.mustache.test.js
tests/qunit/suites/resources/mediawiki/mediawiki.template.test.js
tests/qunit/suites/resources/mediawiki/mediawiki.test.js
tests/qunit/suites/resources/mediawiki/mediawiki.toc.test.js
tests/qunit/suites/resources/mediawiki/mediawiki.track.test.js
tests/qunit/suites/resources/mediawiki/mediawiki.util.test.js
tests/qunit/suites/resources/mediawiki/mediawiki.viewport.test.js
tests/qunit/suites/resources/startup.test.js

index 98d0f10..64b5ea7 100644 (file)
@@ -2,8 +2,7 @@
        "extends": "wikimedia",
        "env": {
                "browser": true,
-               "jquery": true,
-               "qunit": true
+               "jquery": true
        },
        "globals": {
                "require": false,
index 62dbeb6..5a7b29f 100644 (file)
@@ -1,26 +1,15 @@
 {
+       "extends": "stylelint-config-wikimedia",
        "rules": {
-               "color-hex-case": [ "lower" ],
-               "color-hex-length": [ "short" ],
-               "color-named": [ "never" ],
-               "color-no-invalid-hex": true,
+               "declaration-no-important": null,
 
-               "declaration-bang-space-after": [ "never" ],
-               "declaration-bang-space-before": [ "always" ],
-               "declaration-colon-space-after": [ "always" ],
-               "declaration-colon-space-before": [ "never" ],
+               "no-descending-specificity": null,
 
-               "font-family-name-quotes": [ "always-unless-keyword" ],
-               "font-weight-notation": [ "named-where-possible" ],
+               "selector-no-id": null,
+               "selector-pseudo-element-colon-notation": null,
 
-               "function-calc-no-unspaced-operator": true,
-               "function-comma-newline-after": "never-multi-line",
-               "function-comma-newline-before": "never-multi-line",
-               "function-comma-space-after": [ "always" ],
-               "function-comma-space-before": [ "never" ],
-               "function-parentheses-newline-inside": [ "never-multi-line" ],
-               "function-parentheses-space-inside": [ "always" ],
-               "function-url-quotes": [ "never" ],
-               "function-whitespace-after": [ "always" ],
+               "string-quotes": null,
+
+               "value-keyword-case": null
        }
 }
index 9738605..5e2c7a0 100644 (file)
@@ -7,17 +7,29 @@
 # complement that setup by testing MediaWiki on travis
 #
 language: php
+# Use the slower sudo-enabled VMs instead of fast containers:
+# - Package 'djvulibre-bin' is not yet whitelisted for trusty containers.
+#   https://github.com/travis-ci/apt-package-whitelist/issues/4036
+sudo: required
+# Use Trusty instead of Travis default (precise)
+# - Required in order to use HHVM 3.6 or higher.
+# - Required for non-buggy xml library for XmlTypeCheck/UploadBaseTest (T75176).
+dist: trusty
 
 matrix:
   fast_finish: true
   include:
-    - env: dbtype=mysql
+    # On Trusty, mysql user 'travis' doesn't have create database rights
+    # Postgres has no user called 'root'.
+    - env: dbtype=mysql dbuser=root
       php: 5.5
-    - env: dbtype=postgres
+    - env: dbtype=postgres dbuser=travis
       php: 5.5
-    - env: dbtype=mysql
-      php: hhvm
-    - env: dbtype=mysql
+    - env: dbtype=mysql dbuser=root
+      # https://docs.travis-ci.com/user/languages/php#HHVM-versions
+      # https://github.com/travis-ci/travis-ci/issues/7368
+      php: hhvm-3.12
+    - env: dbtype=mysql dbuser=root
       php: 7
 
 services:
@@ -26,15 +38,17 @@ services:
 branches:
   # Test changes in master and arbitrary Travis CI branches only.
   # The latter allows developers to enable Travis CI in their GitHub fork of
-  # wikimedia/mediawiki and then push changes they like to test to branches like
+  # wikimedia/mediawiki and then push changes for testing to branches like
   # "travis-ci/test-this-awesome-change".
   only:
     - master
     - /^travis-ci\/.*$/
 
-before_install:
-  - sudo apt-get install -qq djvulibre-bin tidy
-  - composer self-update --quiet --no-interaction
+addons:
+  apt:
+    packages:
+    - djvulibre-bin
+    - tidy
 
 before_script:
   - composer install --prefer-source --quiet --no-interaction
@@ -44,7 +58,7 @@ before_script:
       --pass travis
       --dbtype "$dbtype"
       --dbname traviswiki
-      --dbuser travis
+      --dbuser "$dbuser"
       --dbpass ""
       --scriptpath "/w"
 
index 4cc9721..0e1c8cb 100644 (file)
@@ -24,12 +24,13 @@ module.exports = function ( grunt ) {
                        all: [
                                '**/*.js',
                                '!docs/**',
-                               '!tests/**',
                                '!node_modules/**',
                                '!resources/lib/**',
                                '!resources/src/jquery.tipsy/**',
                                '!resources/src/jquery/jquery.farbtastic.js',
                                '!resources/src/mediawiki.libs/**',
+                               // Third-party code of PHPUnit coverage report
+                               '!tests/coverage/**',
                                '!vendor/**',
                                // Explicitly say "**/*.js" here in case of symlinks
                                '!extensions/**/*.js',
@@ -58,7 +59,7 @@ module.exports = function ( grunt ) {
                        options: {
                                syntax: 'less'
                        },
-                       src: '{resources/src/*,mw-config/**}/*.{css,less}'
+                       src: '{resources/src,mw-config}/**/*.{css,less}'
                },
                watch: {
                        files: [
diff --git a/HISTORY b/HISTORY
index 28a9b86..7f365ac 100644 (file)
--- a/HISTORY
+++ b/HISTORY
@@ -326,6 +326,27 @@ There's usually someone online in #mediawiki on irc.freenode.net.
 
 = MediaWiki 1.27 =
 
+== MediaWiki 1.27.1 ==
+
+This is a maintenance release of the MediaWiki 1.27 branch.
+
+=== Changes since 1.27.0 ===
+* BREAKING CHANGE: $wgHTTPProxy is now *required* for all external requests
+  made by MediaWiki via a proxy. Relying on the http_proxy environment
+  variable is no longer supported.
+* (T139565) SECURITY: API: Generate head items in the context of the given title
+* (T137264) SECURITY: XSS in unclosed internal links
+* (T133147) SECURITY: Escape '<' and ']]>' in inline <style> blocks
+* (T133147) SECURITY: Require login to preview user CSS pages
+* (T132926) SECURITY: Do not allow undeleting a revision deleted file if it is
+  the top file
+* (T129738) SECURITY: Make $wgBlockDisablesLogin also restrict logged in
+  permissions
+* (T129738) SECURITY: Make blocks log users out if $wgBlockDisablesLogin is true
+* (T115333) SECURITY: Check read permission when loading page content in ApiParse
+* (T57548) Remove support for $wgWellFormedXml = false, all output is now well formed
+* (T139670) Move 'UserGetRights' call before application of Session::getAllowedUserRights()
+
 == MediaWiki 1.27.0 ==
 
 === PHP version requirement in 1.27 ===
@@ -652,7 +673,7 @@ The following PHP extensions are strongly recommended:
 * ApiMain::addFormat() was removed (deprecated in 1.21).
 * ApiMain::getFormats() was removed (deprecated in 1.21).
 * ApiPageSet::finishPageSetGeneration() was removed (deprecated in 1.21).
-* ApiCreateAccount is deprecated, and will be removed soon.
+* ApiCreateAccount was removed.
 
 === Languages updated in 1.27 ===
 
@@ -909,6 +930,55 @@ For notes on 1.26.x and older releases, see HISTORY.
 
 = MediaWiki 1.26 =
 
+== MediaWiki 1.26.4 ==
+
+This is a maintenance release of the MediaWiki 1.26 branch.
+
+=== Changes since 1.26.3 ===
+* BREAKING CHANGE: $wgHTTPProxy is now *required* for all external requests
+  made by MediaWiki via a proxy. Relying on the http_proxy environment
+  variable is no longer supported.
+* (T124163) Fixed fatal error in DifferenceEngine under HHVM.
+* (T139565) SECURITY: API: Generate head items in the context of the given title
+* (T137264) SECURITY: XSS in unclosed internal links
+* (T133147) SECURITY: Escape '<' and ']]>' in inline <style> blocks
+* (T133147) SECURITY: Require login to preview user CSS pages
+* (T132926) SECURITY: Do not allow undeleting a revision deleted file if it is
+  the top file
+* (T129738) SECURITY: Make $wgBlockDisablesLogin also restrict logged in
+  permissions
+* (T129738) SECURITY: Make blocks log users out if $wgBlockDisablesLogin is true
+* (T115333) SECURITY: Check read permission when loading page content in ApiParse
+* Remove support for $wgWellFormedXml = false, all output is now well formed
+
+== MediaWiki 1.26.3 ==
+
+This is a maintenance release of the MediaWiki 1.26 branch.
+
+=== Changes since 1.26.2 ===
+* (T116266) Fixed undefined property notices in DairikiDiff under HHVM.
+* (T123166) Fix fatal error when importing pages to titles which cannot be
+  created, such as invalid titles or titles the user is not allowed to edit.
+* (T122056) Old tokens are remaining valid within a new session
+* (T127114) Login throttle can be tricked using non-canonicalized usernames
+* (T123653) Cross-domain policy regexp is too narrow
+* (T123071) Incorrectly identifying http link in a's href attributes, due to
+  m modifier in regex
+* (T129506) MediaWiki:Gadget-popups.js isn't renderable
+* (T125283) Users occasionally logged in as different users after
+  SessionManager deployment
+* (T103239) Patrol allows click catching and patrolling of any page
+* (T122807) [tracking] Check php crypto primatives
+* (T98313) Graphs can leak tokens, leading to CSRF
+* (T130947) Diff generation should use PoolCounter
+* (T133507) Careless use of $wgExternalLinkTarget is insecure
+* (T132874) API action=move is not rate limited
+* (T110143) strip markers can be used to get around html attribute escaping in
+  (many?) parser tags
+* (T116030) Increase pbkdf2 parameter strengths
+* (T127420) Pbkdf2Password does not check if hash_pbkdf2() succeeded
+* (T126685) Globally throttle password attempts
+
 == MediaWiki 1.26.2 ==
 
 This is a maintenance release of the MediaWiki 1.26 branch.
@@ -1187,6 +1257,33 @@ changes to languages because of Phabricator reports.
 
 = MediaWiki 1.25 =
 
+== MediaWiki 1.25.6 ==
+
+This is a maintenance release of the MediaWiki 1.25 branch.
+
+=== Changes since 1.25.5 ===
+* (T123166) Fix fatal error when importing pages to titles which cannot be
+  created, such as invalid titles or titles the user is not allowed to edit.
+* (T122056) Old tokens are remaining valid within a new session
+* (T127114) Login throttle can be tricked using non-canonicalized usernames
+* (T123653) Cross-domain policy regexp is too narrow
+* (T123071) Incorrectly identifying http link in a's href attributes, due to
+  m modifier in regex
+* (T129506) MediaWiki:Gadget-popups.js isn't renderable
+* (T125283) Users occasionally logged in as different users after
+  SessionManager deployment
+* (T103239) Patrol allows click catching and patrolling of any page
+* (T122807) [tracking] Check php crypto primatives
+* (T98313) Graphs can leak tokens, leading to CSRF
+* (T130947) Diff generation should use PoolCounter
+* (T133507) Careless use of $wgExternalLinkTarget is insecure
+* (T132874) API action=move is not rate limited
+* (T110143) strip markers can be used to get around html attribute escaping in
+  (many?) parser tags
+* (T116030) Increase pbkdf2 parameter strengths
+* (T127420) Pbkdf2Password does not check if hash_pbkdf2() succeeded
+* (T126685) Globally throttle password attempts
+
 == MediaWiki 1.25.5 ==
 
 This is a maintenance release of the MediaWiki 1.25 branch.
@@ -2573,6 +2670,26 @@ of files that are no longer available follows.
 
 = MediaWiki 1.23 =
 
+== MediaWiki 1.23.15 ==
+
+This is a maintenance release of the MediaWiki 1.23 branch.
+
+=== Changes since 1.23.14 ===
+* BREAKING CHANGE: $wgHTTPProxy is now *required* for all external requests
+  made by MediaWiki via a proxy. Relying on the http_proxy environment
+  variable is no longer supported.
+* (T139565) SECURITY: API: Generate head items in the context of the given title
+* (T137264) SECURITY: XSS in unclosed internal links
+* (T133147) SECURITY: Escape '<' and ']]>' in inline <style> blocks
+* (T133147) SECURITY: Require login to preview user CSS pages
+* (T132926) SECURITY: Do not allow undeleting a revision deleted file if it is
+  the top file
+* (T129738) SECURITY: Make $wgBlockDisablesLogin also restrict logged in
+  permissions
+* (T129738) SECURITY: Make blocks log users out if $wgBlockDisablesLogin is true
+* (T115333) SECURITY: Check read permission when loading page content in ApiParse
+* Remove support for $wgWellFormedXml = false, all output is now well formed
+
 == MediaWiki 1.23.13 ==
 
 This is a maintenance release of the MediaWiki 1.23 branch.
index 13406d6..a1ce9d9 100644 (file)
@@ -32,6 +32,7 @@ production.
   new features that rely on the schema changes to the user_groups table. This
   feature flag will likely be removed before 1.29 is released.
 * (T158474) "Unknown user" has been added to $wgReservedUsernames.
+* (T156983) $wgRateLimitsExcludedIPs now accepts CIDR ranges as well as single IPs.
 
 === New features in 1.29 ===
 * (T5233) A cookie can now be set when a user is autoblocked, to track that user
@@ -60,6 +61,7 @@ production.
 * Updated QUnit from v1.22.0 to v1.23.1.
 * Updated cssjanus from v1.1.2 to 1.1.3.
 * Updated psr/log from v1.0.0 to v1.0.2.
+* Update Moment.js from v2.8.4 to v2.15.0.
 
 ==== New external libraries ====
 
index fce7891..1863577 100644 (file)
@@ -257,6 +257,7 @@ $wgAutoloadLocalClasses = [
        'ClearInterwikiCache' => __DIR__ . '/maintenance/clearInterwikiCache.php',
        'CliInstaller' => __DIR__ . '/includes/installer/CliInstaller.php',
        'CloneDatabase' => __DIR__ . '/includes/db/CloneDatabase.php',
+       'CodeCleanerGlobalsPass' => __DIR__ . '/maintenance/CodeCleanerGlobalsPass.inc',
        'CodeContentHandler' => __DIR__ . '/includes/content/CodeContentHandler.php',
        'Collation' => __DIR__ . '/includes/collation/Collation.php',
        'CollationCkb' => __DIR__ . '/includes/collation/CollationCkb.php',
@@ -812,6 +813,7 @@ $wgAutoloadLocalClasses = [
        'MediaTransformOutput' => __DIR__ . '/includes/media/MediaTransformOutput.php',
        'MediaWiki' => __DIR__ . '/includes/MediaWiki.php',
        'MediaWikiI18N' => __DIR__ . '/includes/skins/MediaWikiI18N.php',
+       'MediaWikiShell' => __DIR__ . '/maintenance/shell.php',
        'MediaWikiSite' => __DIR__ . '/includes/site/MediaWikiSite.php',
        'MediaWikiTitleCodec' => __DIR__ . '/includes/title/MediaWikiTitleCodec.php',
        'MediaWikiVersionFetcher' => __DIR__ . '/includes/MediaWikiVersionFetcher.php',
@@ -1591,6 +1593,8 @@ $wgAutoloadLocalClasses = [
        'Wikimedia\\Rdbms\\LBFactorySimple' => __DIR__ . '/includes/libs/rdbms/lbfactory/LBFactorySimple.php',
        'Wikimedia\\Rdbms\\LBFactorySingle' => __DIR__ . '/includes/libs/rdbms/lbfactory/LBFactorySingle.php',
        'Wikimedia\\Rdbms\\LikeMatch' => __DIR__ . '/includes/libs/rdbms/encasing/LikeMatch.php',
+       'Wikimedia\\Rdbms\\LoadBalancer' => __DIR__ . '/includes/libs/rdbms/loadbalancer/LoadBalancer.php',
+       'Wikimedia\\Rdbms\\LoadBalancerSingle' => __DIR__ . '/includes/libs/rdbms/loadbalancer/LoadBalancerSingle.php',
        'Wikimedia\\Rdbms\\LoadMonitor' => __DIR__ . '/includes/libs/rdbms/loadmonitor/LoadMonitor.php',
        'Wikimedia\\Rdbms\\LoadMonitorMySQL' => __DIR__ . '/includes/libs/rdbms/loadmonitor/LoadMonitorMySQL.php',
        'Wikimedia\\Rdbms\\LoadMonitorNull' => __DIR__ . '/includes/libs/rdbms/loadmonitor/LoadMonitorNull.php',
index 1125529..3520dc3 100644 (file)
@@ -57,7 +57,8 @@
                "phpunit/phpunit": "4.8.31",
                "wikimedia/avro": "1.7.7",
                "hamcrest/hamcrest-php": "^2.0",
-               "wmde/hamcrest-html-matchers": "^0.1.0"
+               "wmde/hamcrest-html-matchers": "^0.1.0",
+               "psy/psysh": "0.8.1"
        },
        "suggest": {
                "ext-apc": "Local data and opcode cache",
index 791d024..c64f550 100644 (file)
@@ -5682,7 +5682,7 @@ $wgRateLimits = [
 ];
 
 /**
- * Array of IPs which should be excluded from rate limits.
+ * Array of IPs / CIDR ranges which should be excluded from rate limits.
  * This may be useful for whitelisting NAT gateways for conferences, etc.
  */
 $wgRateLimitsExcludedIPs = [];
index 34062c0..814da6a 100644 (file)
@@ -1256,7 +1256,7 @@ class EditPage {
                $revision = $this->mArticle->getRevisionFetched();
                if ( $revision === null ) {
                        if ( !$this->contentModel ) {
-                               $this->contentModel = $this->getTitle()->getContentModel();
+                               throw new RuntimeException( 'EditPage contentModel was false' );
                        }
                        $handler = ContentHandler::getForModelID( $this->contentModel );
 
@@ -1300,7 +1300,7 @@ class EditPage {
 
                if ( $content === false || $content === null ) {
                        if ( !$this->contentModel ) {
-                               $this->contentModel = $this->getTitle()->getContentModel();
+                               throw new RuntimeException( 'EditPage contentModel was false' );
                        }
                        $handler = ContentHandler::getForModelID( $this->contentModel );
 
@@ -2483,11 +2483,13 @@ class EditPage {
                }
                # Give a notice if the user is editing a deleted/moved page...
                if ( !$this->mTitle->exists() ) {
+                       $dbr = wfGetDB( DB_REPLICA );
+
                        LogEventsList::showLogExtract( $wgOut, [ 'delete', 'move' ], $this->mTitle,
                                '',
                                [
                                        'lim' => 10,
-                                       'conds' => [ "log_action != 'revision'" ],
+                                       'conds' => [ 'log_action != ' . $dbr->addQuotes( 'revision' ) ],
                                        'showIfEmpty' => false,
                                        'msgKey' => [ 'recreate-moveddeleted-warn' ]
                                ]
index 7a34c74..af5d5fa 100644 (file)
@@ -28,7 +28,6 @@ use Liuggio\StatsdClient\Sender\SocketSender;
 use MediaWiki\Logger\LoggerFactory;
 use MediaWiki\Session\SessionManager;
 use Wikimedia\ScopedCallback;
-use Wikimedia\Rdbms\LBFactory;
 
 // Hide compatibility functions from Doxygen
 /// @cond
@@ -3086,7 +3085,7 @@ function wfGetDB( $db, $groups = [], $wiki = false ) {
  *              or MediaWikiServices::getDBLoadBalancerFactory() instead.
  *
  * @param string|bool $wiki Wiki ID, or false for the current wiki
- * @return LoadBalancer
+ * @return \Wikimedia\Rdbms\LoadBalancer
  */
 function wfGetLB( $wiki = false ) {
        if ( $wiki === false ) {
@@ -3102,7 +3101,7 @@ function wfGetLB( $wiki = false ) {
  *
  * @deprecated since 1.27, use MediaWikiServices::getDBLoadBalancerFactory() instead.
  *
- * @return LBFactory
+ * @return \Wikimedia\Rdbms\LBFactory
  */
 function wfGetLBFactory() {
        return \MediaWiki\MediaWikiServices::getInstance()->getDBLoadBalancerFactory();
index 94b145e..05e3abb 100644 (file)
@@ -933,13 +933,14 @@ class Linker {
                if ( $userId ) {
                        // check if the user has an edit
                        $attribs = [];
+                       $attribs['class'] = 'mw-usertoollinks-contribs';
                        if ( $redContribsWhenNoEdits ) {
                                if ( intval( $edits ) === 0 && $edits !== 0 ) {
                                        $user = User::newFromId( $userId );
                                        $edits = $user->getEditCount();
                                }
                                if ( $edits === 0 ) {
-                                       $attribs['class'] = 'new';
+                                       $attribs['class'] .= ' new';
                                }
                        }
                        $contribsPage = SpecialPage::getTitleFor( 'Contributions', $userText );
@@ -986,7 +987,10 @@ class Linker {
         */
        public static function userTalkLink( $userId, $userText ) {
                $userTalkPage = Title::makeTitle( NS_USER_TALK, $userText );
-               $userTalkLink = self::link( $userTalkPage, wfMessage( 'talkpagelinktext' )->escaped() );
+               $moreLinkAttribs['class'] = 'mw-usertoollinks-talk';
+               $userTalkLink = self::link( $userTalkPage,
+                                               wfMessage( 'talkpagelinktext' )->escaped(),
+                                               $moreLinkAttribs );
                return $userTalkLink;
        }
 
@@ -998,7 +1002,10 @@ class Linker {
         */
        public static function blockLink( $userId, $userText ) {
                $blockPage = SpecialPage::getTitleFor( 'Block', $userText );
-               $blockLink = self::link( $blockPage, wfMessage( 'blocklink' )->escaped() );
+               $moreLinkAttribs['class'] = 'mw-usertoollinks-block';
+               $blockLink = self::link( $blockPage,
+                                        wfMessage( 'blocklink' )->escaped(),
+                                        $moreLinkAttribs );
                return $blockLink;
        }
 
@@ -1009,7 +1016,10 @@ class Linker {
         */
        public static function emailLink( $userId, $userText ) {
                $emailPage = SpecialPage::getTitleFor( 'Emailuser', $userText );
-               $emailLink = self::link( $emailPage, wfMessage( 'emaillink' )->escaped() );
+               $moreLinkAttribs['class'] = 'mw-usertoollinks-mail';
+               $emailLink = self::link( $emailPage,
+                                        wfMessage( 'emaillink' )->escaped(),
+                                        $moreLinkAttribs );
                return $emailLink;
        }
 
index ac151e2..e44fefe 100644 (file)
@@ -12,7 +12,7 @@ use Hooks;
 use Wikimedia\Rdbms\LBFactory;
 use LinkCache;
 use Liuggio\StatsdClient\Factory\StatsdDataFactory;
-use LoadBalancer;
+use Wikimedia\Rdbms\LoadBalancer;
 use MediaHandlerFactory;
 use MediaWiki\Linker\LinkRenderer;
 use MediaWiki\Linker\LinkRendererFactory;
index c80e4a5..2b8147a 100644 (file)
@@ -2,6 +2,7 @@
 
 use MediaWiki\Linker\LinkTarget;
 use Wikimedia\Assert\Assert;
+use Wikimedia\Rdbms\LoadBalancer;
 
 /**
  * Class performing complex database queries related to WatchedItems.
@@ -401,7 +402,7 @@ class WatchedItemQueryService {
                if ( !isset( $options['start'] ) && !isset( $options['end'] ) ) {
                        if ( $db->getType() === 'mysql' ) {
                                // This is an index optimization for mysql
-                               $conds[] = "rc_timestamp > ''";
+                               $conds[] = 'rc_timestamp > ' . $db->addQuotes( '' );
                        }
                }
 
index 858d87b..9af5310 100644 (file)
@@ -5,6 +5,7 @@ use MediaWiki\Linker\LinkTarget;
 use MediaWiki\MediaWikiServices;
 use Wikimedia\Assert\Assert;
 use Wikimedia\ScopedCallback;
+use Wikimedia\Rdbms\LoadBalancer;
 
 /**
  * Storage layer class for WatchedItems.
index 3bbdc3f..78d7444 100644 (file)
@@ -408,7 +408,7 @@ class WebRequest {
         * @since 1.28
         * @param string $name
         * @param string|null $default Optional default
-        * @return string
+        * @return string|null
         */
        public function getRawVal( $name, $default = null ) {
                $name = strtr( $name, '.', '_' ); // See comment in self::getGPCVal()
@@ -432,7 +432,7 @@ class WebRequest {
         *
         * @param string $name
         * @param string $default Optional default (or null)
-        * @return string
+        * @return string|null
         */
        public function getVal( $name, $default = null ) {
                $val = $this->getGPCVal( $this->data, $name, $default );
@@ -482,7 +482,7 @@ class WebRequest {
         *
         * @param string $name
         * @param array $default Optional default (or null)
-        * @return array
+        * @return array|null
         */
        public function getArray( $name, $default = null ) {
                $val = $this->getGPCVal( $this->data, $name, $default );
index e8aec1c..b381edc 100644 (file)
@@ -146,6 +146,9 @@ class HistoryAction extends FormlessAction {
                                $out->setStatusCode( 404 );
                        }
                        $out->addWikiMsg( 'nohistory' );
+
+                       $dbr = wfGetDB( DB_REPLICA );
+
                        # show deletion/move log if there is an entry
                        LogEventsList::showLogExtract(
                                $out,
@@ -153,7 +156,7 @@ class HistoryAction extends FormlessAction {
                                $this->getTitle(),
                                '',
                                [ 'lim' => 10,
-                                       'conds' => [ "log_action != 'revision'" ],
+                                       'conds' => [ 'log_action != ' . $dbr->addQuotes( 'revision' ) ],
                                        'showIfEmpty' => false,
                                        'msgKey' => [ 'moveddeleted-notice' ]
                                ]
index aa2858d..9d336e4 100644 (file)
@@ -41,6 +41,7 @@ class RollbackAction extends FormlessAction {
         * - confirm-rollback-button
         * - rollbackfailed
         * - rollback-missingparam
+        * - rollback-success-notify
         */
 
        /**
@@ -123,8 +124,13 @@ class RollbackAction extends FormlessAction {
 
                $old = Linker::revUserTools( $current );
                $new = Linker::revUserTools( $target );
-               $this->getOutput()->addHTML( $this->msg( 'rollback-success' )->rawParams( $old, $new )
-                       ->parseAsBlock() );
+               $this->getOutput()->addHTML(
+                       $this->msg( 'rollback-success' )
+                               ->rawParams( $old, $new )
+                               ->params( $current->getUserText( Revision::FOR_THIS_USER, $user ) )
+                               ->params( $target->getUserText( Revision::FOR_THIS_USER, $user ) )
+                               ->parseAsBlock()
+               );
 
                if ( $user->getBoolOption( 'watchrollback' ) ) {
                        $user->addWatch( $this->page->getTitle(), User::IGNORE_USER_RIGHTS );
index 5327d7a..d037c36 100644 (file)
@@ -208,6 +208,7 @@ class ApiAuthManagerHelper {
                        $res->status === AuthenticationResponse::RESTART
                ) {
                        $this->formatMessage( $ret, 'message', $res->message );
+                       $ret['messagecode'] = ApiMessage::create( $res->message )->getApiCode();
                }
 
                if ( $res->status === AuthenticationResponse::FAIL ||
index 59227d9..9e00830 100644 (file)
@@ -1116,7 +1116,9 @@ class ApiMain extends ApiBase {
                                )
                        );
                } else {
-                       if ( $config->get( 'ShowExceptionDetails' ) ) {
+                       if ( $config->get( 'ShowExceptionDetails' ) &&
+                               ( !$e instanceof DBError || $config->get( 'ShowDBErrorBacktrace' ) )
+                       ) {
                                $result->addContentValue(
                                        $path,
                                        'trace',
index 2a61a90..341c68f 100644 (file)
        "apihelp-xml-param-includexmlnamespace": "Falls angegeben, ergänzt einen XML-Namensraum.",
        "apihelp-xmlfm-description": "Daten im XML-Format ausgeben (schöngedruckt in HTML).",
        "api-format-title": "MediaWiki-API-Ergebnis",
-       "api-format-prettyprint-header": "Dies ist die HTML-Repräsentation des $1-Formats. HTML ist zur Fehlerbehebung gut, aber unpassend für den Anwendungsgebrauch.\n\nGib den Parameter <var>format</var> an, um das Ausgabeformat zu ändern. Um die Nicht-HTML-Repräsentation des $1-Formats anzusehen, lege <kbd>format=$2</kbd> fest.\n\nSiehe die [[mw:API|vollständige Dokumentation]] oder die [[Special:ApiHelp/main|API-Hilfe]] für weitere Informationen.",
+       "api-format-prettyprint-header": "Dies ist die Darstellung des $1-Formats in HTML. HTML ist gut zur Fehlerbehebung geeignet, aber unpassend für die Nutzung durch Anwendungen.\n\nGib den Parameter <var>format</var> an, um das Ausgabeformat zu ändern. Lege <kbd>format=$2</kbd> fest, um die von HTML abweichende Darstellung des $1-Formats zu erhalten.\n\nSiehe auch die [[mw:API|vollständige Dokumentation der API]] oder die [[Special:ApiHelp/main|API-Hilfe]] für weitere Informationen.",
        "api-format-prettyprint-status": "Diese Antwort wird mit dem HTTP-Status $1 $2 zurückgegeben.",
        "api-pageset-param-titles": "Eine Liste der Titel, an denen gearbeitet werden soll.",
        "api-pageset-param-pageids": "Eine Liste der Seitenkennungen, an denen gearbeitet werden soll.",
index cde3797..f9de725 100644 (file)
        "apiwarn-redirectsandrevids": "Redirect resolution cannot be used together with the <var>revids</var> parameter. Any redirects the <var>revids</var> point to have not been resolved.",
        "apiwarn-tokennotallowed": "Action \"$1\" is not allowed for the current user.",
        "apiwarn-tokens-origin": "Tokens may not be obtained when the same-origin policy is not applied.",
-       "apiwarn-toomanyvalues": "Too many values supplied for parameter <var>$1</var>: the limit is $2.",
+       "apiwarn-toomanyvalues": "Too many values supplied for parameter <var>$1</var>. The limit is $2.",
        "apiwarn-truncatedresult": "This result was truncated because it would otherwise be larger than the limit of $1 bytes.",
-       "apiwarn-unclearnowtimestamp": "Passing \"$2\" for timestamp parameter <var>$1</var> has been deprecated. If for some reason you need to explicitly specify the current time without calculating it client-side, use <kbd>now<kbd>.",
+       "apiwarn-unclearnowtimestamp": "Passing \"$2\" for timestamp parameter <var>$1</var> has been deprecated. If for some reason you need to explicitly specify the current time without calculating it client-side, use <kbd>now</kbd>.",
        "apiwarn-unrecognizedvalues": "Unrecognized {{PLURAL:$3|value|values}} for parameter <var>$1</var>: $2.",
        "apiwarn-unsupportedarray": "Parameter <var>$1</var> uses unsupported PHP array syntax.",
        "apiwarn-urlparamwidth": "Ignoring width value set in <var>$1urlparam</var> ($2) in favor of width value derived from <var>$1urlwidth</var>/<var>$1urlheight</var> ($3).",
index e9bb40e..4c36cc3 100644 (file)
        "apihelp-query-param-exportnowrap": "Renvoyer le XML exporté sans l’inclure dans un résultat XML (même format que [[Special:Export]]). Utilisable uniquement avec $1export.",
        "apihelp-query-param-iwurl": "S’il faut obtenir l’URL complète si le titre est un lien interwiki.",
        "apihelp-query-param-rawcontinue": "Renvoyer les données <samp>query-continue</samp> brutes pour continuer.",
-       "apihelp-query-example-revisions": "Récupérer [[Special:ApiHelp/query+siteinfo|l’info du site]] et [[Special:ApiHelp/query+revisions|les révisions]] de <kbd>Page principale</kbd>.",
+       "apihelp-query-example-revisions": "Récupérer [[Special:ApiHelp/query+siteinfo|l’info du site]] et [[Special:ApiHelp/query+revisions|les révisions]] de <kbd>Main Page</kbd>.",
        "apihelp-query-example-allpages": "Récupérer les révisions des pages commençant par <kbd>API/</kbd>.",
        "apihelp-query+allcategories-description": "Énumérer toutes les catégories.",
        "apihelp-query+allcategories-param-from": "La catégorie depuis laquelle démarrer l’énumération.",
        "apihelp-query+deletedrevs-example-mode3-main": "Lister les 50 premières révisions supprimées dans l’espace de noms principal (mode 3)",
        "apihelp-query+deletedrevs-example-mode3-talk": "Lister les 50 premières pages supprimées dans l’espace de noms {{ns:talk}} (mode 3).",
        "apihelp-query+disabled-description": "Ce module de requête a été désactivé.",
-       "apihelp-query+duplicatefiles-description": "Lister tous les fichiers qui sont des doublons des fichiers donnés d’après leurs valeurs de hachage.",
+       "apihelp-query+duplicatefiles-description": "Lister d’après leurs valeurs de hachage, tous les fichiers qui sont des doublons de fichiers donnés.",
        "apihelp-query+duplicatefiles-param-limit": "Combien de fichiers dupliqués à renvoyer.",
        "apihelp-query+duplicatefiles-param-dir": "La direction dans laquelle lister.",
        "apihelp-query+duplicatefiles-param-localonly": "Rechercher les fichiers uniquement dans le référentiel local.",
        "apihelp-query+embeddedin-example-generator": "Obtenir des informations sur les pages incluant <kbd>Template:Stub</kbd>.",
        "apihelp-query+extlinks-description": "Renvoyer toutes les URLs externes (non interwikis) des pages données.",
        "apihelp-query+extlinks-param-limit": "Combien de liens renvoyer.",
-       "apihelp-query+extlinks-param-protocol": "Protocole de l’URL. Si vide et <var>$1query</var> est positionné, le protocole est <kbd>http</kbd>. Laisser à la fois ceci et <var>$1query</var> vide pour lister tous les liens externes.",
+       "apihelp-query+extlinks-param-protocol": "Protocole de l’URL. Si vide et <var>$1query</var> est positionné, le protocole est <kbd>http</kbd>. Laisser à la fois ceci et <var>$1query</var> vides pour lister tous les liens externes.",
        "apihelp-query+extlinks-param-query": "Rechercher une chaîne sans protocole. Utile pour vérifier si une certaine page contient une certaine URL externe.",
        "apihelp-query+extlinks-param-expandurl": "Étendre les URLs relatives au protocole avec le protocole canonique.",
        "apihelp-query+extlinks-example-simple": "Obtenir une liste des liens externes de <kbd>Main Page</kbd>.",
        "apihelp-query+exturlusage-paramvalue-prop-title": "Ajoute le titre et l’ID de l’espace de noms de la page.",
        "apihelp-query+exturlusage-paramvalue-prop-url": "Ajoute l’URL utilisée dans la page.",
        "apihelp-query+exturlusage-param-protocol": "Protocole de l’URL. Si vide et que <var>$1query</var>  est rempli, le protocole est <kbd>http</kbd>. Le laisser avec <var>$1query</var>  vide pour lister tous les liens externes.",
-       "apihelp-query+exturlusage-param-query": "Rechercher une chaîne sans protocole. Voyez [[Special:LinkSearch]]. Le laisser vide liste tous les liens externes.",
+       "apihelp-query+exturlusage-param-query": "Rechercher une chaîne sans protocole. Voyez [[Special:LinkSearch]]. Le laisser vide pour lister tous les liens externes.",
        "apihelp-query+exturlusage-param-namespace": "Les espaces de nom à énumérer.",
        "apihelp-query+exturlusage-param-limit": "Combien de pages renvoyer.",
        "apihelp-query+exturlusage-param-expandurl": "Étendre les URLs relatives au protocole avec le protocole canonique.",
        "apihelp-query+filearchive-paramvalue-prop-bitdepth": "Ajoute la profondeur de bit de la version.",
        "apihelp-query+filearchive-paramvalue-prop-archivename": "Ajoute le nom de fichier de la version d’archive pour les versions autres que la dernière.",
        "apihelp-query+filearchive-example-simple": "Afficher une liste de tous les fichiers supprimés",
-       "apihelp-query+filerepoinfo-description": "Renvoyer les méta-informations sur les référentiels d’image configurés dans le wiki.",
+       "apihelp-query+filerepoinfo-description": "Renvoyer les méta-informations sur les référentiels d’images configurés dans le wiki.",
        "apihelp-query+filerepoinfo-param-prop": "Quelles propriétés du référentiel récupérer (il peut y en avoir plus de disponibles sur certains wikis) :\n;apiurl:URL de l’API du référentiel - utile pour obtenir les infos de l’image depuis l’hôte.\n;name:La clé du référentiel - utilisé par ex. dans les valeurs de retour de <var>[[mw:Manual:$wgForeignFileRepos|$wgForeignFileRepos]]</var> et [[Special:ApiHelp/query+imageinfo|imageinfo]].\n;displayname:Le nom lisible du wiki référentiel.\n;rooturl:URL racine des chemins d’image.\n;local:Si ce référentiel est le référentiel local ou non.",
        "apihelp-query+filerepoinfo-example-simple": "Obtenir des informations sur les référentiels de fichier.",
        "apihelp-query+fileusage-description": "Trouver toutes les pages qui utilisent les fichiers donnés.",
        "apihelp-query+imageinfo-paramvalue-prop-parsedcomment": "Analyser le commentaire de la version.",
        "apihelp-query+imageinfo-paramvalue-prop-canonicaltitle": "Ajoute le titre canonique du fichier.",
        "apihelp-query+imageinfo-paramvalue-prop-url": "Fournit l’URL du fichier et de la page de description.",
-       "apihelp-query+imageinfo-paramvalue-prop-size": "Ajoute la taille du fichier en octets et sa hauteur, largeur et compteur de page (le cas échéant).",
+       "apihelp-query+imageinfo-paramvalue-prop-size": "Ajoute la taille du fichier en octets et sa hauteur, sa largeur et le compteur de page (le cas échéant).",
        "apihelp-query+imageinfo-paramvalue-prop-dimensions": "Alias pour la taille.",
        "apihelp-query+imageinfo-paramvalue-prop-sha1": "Ajoute le hachage SH1-1 du fichier.",
        "apihelp-query+imageinfo-paramvalue-prop-mime": "Ajoute le type MIME du fichier.",
        "apihelp-query+imageinfo-param-extmetadatalanguage": "Quelle langue pour analyser extmetadata. Cela affecte à la fois quelle traduction analyser, s’il y en a plusieurs, et comment les choses comme les nombres et d’autres valeurs sont mises en forme.",
        "apihelp-query+imageinfo-param-extmetadatamultilang": "Si des traductions pour la propriété extmetadata sont disponibles, les analyser toutes.",
        "apihelp-query+imageinfo-param-extmetadatafilter": "Si spécifié et non vide, seules ces clés seront renvoyées pour $1prop=extmetadata.",
-       "apihelp-query+imageinfo-param-urlparam": "Une chaîne de paramètre spécifique à l’analyseur. Par exemple, les PDFs peuvent utiliser <kbd>page15-100px</kbd>. <var>$1urlwidth</var> doit être utilisé et être cohérent avec <var>$1urlparam</var>.",
+       "apihelp-query+imageinfo-param-urlparam": "Une chaîne de paramètres spécifique à l’analyseur. Par exemple, les PDFs peuvent utiliser <kbd>page15-100px</kbd>. <var>$1urlwidth</var> doit être utilisé et être cohérent avec <var>$1urlparam</var>.",
        "apihelp-query+imageinfo-param-badfilecontexttitle": "Si <kbd>$2prop=badfile</kbd> est positionné, il s'agit du titre de la page utilisé pour évaluer la [[MediaWiki:Bad image list]]",
        "apihelp-query+imageinfo-param-localonly": "Rechercher les fichiers uniquement dans le référentiel local.",
        "apihelp-query+imageinfo-example-simple": "Analyser les informations sur la version actuelle de [[:File:Albert Einstein Head.jpg]].",
        "apihelp-query+info-param-testactions": "Tester si l’utilisateur actuel peut effectuer certaines actions sur la page.",
        "apihelp-query+info-param-token": "Utiliser plutôt [[Special:ApiHelp/query+tokens|action=query&meta=tokens]].",
        "apihelp-query+info-example-simple": "Obtenir des informations sur la page <kbd>Main Page</kbd>.",
-       "apihelp-query+info-example-protection": "Obtenir des informations générale et de protection sur la page <kbd>Main Page</kbd>.",
-       "apihelp-query+iwbacklinks-description": "Trouver toutes les pages qui ont un lien vers le lien interwiki indiqué.\n\nPeut être utilisé pour trouver tous les liens avec un préfixe, ou tous les liens vers un titre (avec un préfixe donné). N’utiliser aucun paramètre revient en pratique à « tous les liens interwiki ».",
+       "apihelp-query+info-example-protection": "Obtenir des informations générales et de protection sur la page <kbd>Main Page</kbd>.",
+       "apihelp-query+iwbacklinks-description": "Trouver toutes les pages qui ont un lien vers le lien interwiki indiqué.\n\nPeut être utilisé pour trouver tous les liens avec un préfixe, ou tous les liens vers un titre (avec un préfixe donné). Sans paramètre, équivaut à « tous les liens interwiki ».",
        "apihelp-query+iwbacklinks-param-prefix": "Préfixe pour l’interwiki.",
        "apihelp-query+iwbacklinks-param-title": "Lien interwiki à rechercher. Doit être utilisé avec <var>$1blprefix</var>.",
        "apihelp-query+iwbacklinks-param-limit": "Combien de pages renvoyer.",
        "apihelp-query+iwbacklinks-paramvalue-prop-iwprefix": "Ajoute le préfixe de l’interwiki.",
        "apihelp-query+iwbacklinks-paramvalue-prop-iwtitle": "Ajoute le titre de l’interwiki.",
        "apihelp-query+iwbacklinks-param-dir": "La direction dans laquelle lister.",
-       "apihelp-query+iwbacklinks-example-simple": "Obtenir les pages ayant un lien vers [[wikibooks:Test]]",
-       "apihelp-query+iwbacklinks-example-generator": "Obtenir des informations sur les pages ayant un lien vers [[wikibooks:Test]]",
+       "apihelp-query+iwbacklinks-example-simple": "Obtenir les pages qui ont un lien vers [[wikibooks:Test]].",
+       "apihelp-query+iwbacklinks-example-generator": "Obtenir des informations sur les pages qui ont un lien vers [[wikibooks:Test]].",
        "apihelp-query+iwlinks-description": "Renvoie tous les liens interwiki des pages indiquées.",
-       "apihelp-query+iwlinks-param-url": "S&il faut obtenir l’URL complète (impossible à utiliser avec $1prop).",
+       "apihelp-query+iwlinks-param-url": "S'il faut obtenir l’URL complète (impossible à utiliser avec $1prop).",
        "apihelp-query+iwlinks-param-prop": "Quelles propriétés supplémentaires obtenir pour chaque lien interlangue :",
        "apihelp-query+iwlinks-paramvalue-prop-url": "Ajoute l’URL complète.",
        "apihelp-query+iwlinks-param-limit": "Combien de liens interwiki renvoyer.",
        "apihelp-query+langbacklinks-paramvalue-prop-lllang": "Ajoute le code de langue du lien de langue.",
        "apihelp-query+langbacklinks-paramvalue-prop-lltitle": "Ajoute le titre du lien de langue.",
        "apihelp-query+langbacklinks-param-dir": "La direction dans laquelle lister.",
-       "apihelp-query+langbacklinks-example-simple": "Obtenir les pages avec un lien avec [[:fr:Test]]",
-       "apihelp-query+langbacklinks-example-generator": "Obtenir des informations sur les pages ayant un lien vers [[:fr:Test]]",
+       "apihelp-query+langbacklinks-example-simple": "Obtenir les pages ayant un lien vers [[:fr:Test]].",
+       "apihelp-query+langbacklinks-example-generator": "Obtenir des informations sur les pages ayant un lien vers [[:fr:Test]].",
        "apihelp-query+langlinks-description": "Renvoie tous les liens interlangue des pages fournies.",
        "apihelp-query+langlinks-param-limit": "Combien de liens interlangue renvoyer.",
        "apihelp-query+langlinks-param-url": "S’il faut récupérer l’URL complète (impossible à utiliser avec <var>$1prop</var>).",
        "apihelp-query+revisions+base-param-parse": "Analyser le contenu de la révision (nécessite $1prop=content). Pour des raisons de performance, si cette option est utilisée, $1limit est forcé à 1.",
        "apihelp-query+revisions+base-param-section": "Récupérer uniquement le contenu de ce numéro de section.",
        "apihelp-query+revisions+base-param-diffto": "ID de révision à comparer à chaque révision. Utiliser <kbd>prev</kbd>, <kbd>next</kbd> et <kbd>cur</kbd> pour la version précédente, suivante et actuelle respectivement.",
-       "apihelp-query+revisions+base-param-difftotext": "Texte auquel comparer chaque révision. Compare uniquement un nombre limité de révisions. Écrase <var>$1diffto</var>. Si <var>$1section</var> est positionné, seule cette section sera comparée avec ce texte",
+       "apihelp-query+revisions+base-param-difftotext": "Texte auquel comparer chaque révision. Compare uniquement un nombre limité de révisions. Écrase <var>$1diffto</var>. Si <var>$1section</var> est positionné, seule cette section sera comparée avec ce texte.",
        "apihelp-query+revisions+base-param-difftotextpst": "Effectuer une transformation avant enregistrement sur le texte avant de le comparer. Valide uniquement quand c’est utilisé avec <var>$1difftotext</var>.",
        "apihelp-query+revisions+base-param-contentformat": "Format de sérialisation utilisé pour <var>$1difftotext</var> et attendu pour la sortie du contenu.",
        "apihelp-query+search-description": "Effectuer une recherche en texte intégral.",
        "apihelp-query+search-param-search": "Rechercher les titres de page ou le contenu correspondant à cette valeur. Vous pouvez utiliser la chaîne de recherche pour invoquer des fonctionnalités de recherche spéciales, selon ce que le serveur de recherche du wiki implémente.",
-       "apihelp-query+search-param-namespace": "Rechercher uniquement dans ces espaces de nom.",
+       "apihelp-query+search-param-namespace": "Rechercher uniquement dans ces espaces de noms.",
        "apihelp-query+search-param-what": "Quel type de recherche effectuer.",
        "apihelp-query+search-param-info": "Quelles métadonnées renvoyer.",
        "apihelp-query+search-param-prop": "Quelles propriétés renvoyer :",
        "apiwarn-tokens-origin": "Les jetons ne peuvent pas être obtenus quand la politique de même origine n’est pas appliquée.",
        "apiwarn-toomanyvalues": "Trop de valeurs fournies pour le paramètre <var>$1</var>: la limite est $2.",
        "apiwarn-truncatedresult": "Ce résultat a été tronqué parce que sinon, il dépasserait la limite de $1 octets.",
-       "apiwarn-unclearnowtimestamp": "Passer « $2 » comme paramètre d’horodatage <var>$1</var> a été rendu obsolète. Si, pour une raison quelconque, vous avez besoin de spécifier explicitement l’heure courante sans la recalculer du côté client, utilisez <kbd>now<kbd>.",
+       "apiwarn-unclearnowtimestamp": "Passer « $2 » comme paramètre d’horodatage <var>$1</var> a été rendu obsolète. Si, pour une raison quelconque, vous avez besoin de spécifier explicitement l’heure courante sans la recalculer du côté client, utilisez <kbd>now</kbd>.",
        "apiwarn-unrecognizedvalues": "{{PLURAL:$3|Valeur non reconnue|Valeurs non reconnues}} pour le paramètre <var>$1</var> : $2.",
        "apiwarn-unsupportedarray": "Le paramètre <var>$1</var> utilise une syntaxe PHP de tableau non prise en charge.",
        "apiwarn-urlparamwidth": "Valeur de la largeur définie dans <var>$1urlparam</var> ($2) ignorée en faveur de la largeur calculée à partir de <var>$1urlwidth</var>/<var>$1urlheight</var> ($3).",
index 0865424..f8e3f05 100644 (file)
        "apierror-reauthenticate": "Non se autentificou recentemente nesta sesión. Por favor, volva a autentificarse.",
        "apierror-revwrongpage": "r$1 non é unha revisión de $2.",
        "apierror-searchdisabled": "A busca <var>$1</var> está desactivada.",
+       "apierror-sectionreplacefailed": "Non se puido combinar a sección actualizada.",
+       "apierror-sectionsnotsupported": "As seccións non son compatibles co modelo de contido $1.",
        "apierror-sectionsnotsupported-what": "As seccións non son compatibles con $1.",
        "apierror-show": "Parámetro incorrecto - non se poden proporcionar valores mutuamente excluíntes.",
+       "apierror-siteinfo-includealldenied": "Non se pode ver a información de tódolos servidores a menos que <var>$wgShowHostNames</var> teña valor verdadeiro.",
        "apierror-sizediffdisabled": "A diferenza de tamaño está deshabilitada no modo Miser.",
        "apierror-spamdetected": "A súa edición foi rexeitada por conter un fragmento de publicidade: <code>$1</code>.",
        "apierror-specialpage-cantexecute": "Non ten permiso para ver os resultados desta páxina especial.",
        "apierror-unknownformat": "Formato descoñecido \"$1\".",
        "apierror-unrecognizedparams": "{{PLURAL:$2|Parámetro non recoñecido|Parámetros non recoñecidos}}: $1.",
        "apierror-unrecognizedvalue": "Valor non recoñecido para o parámetro <var>$1</var>: $2.",
+       "apierror-urlparamnormal": "Non se puideron normalizar os parámetros de imaxe de $1.",
+       "apierror-writeapidenied": "Non ten permiso para editar este wiki a través da API.",
+       "apiwarn-alldeletedrevisions-performance": "Para ter un mellor rendemento á hora de xerar títulos, estableza <kbd>$1dir=newer</kbd>.",
+       "apiwarn-badurlparam": "Non se puido analizar <var>$1urlparam</var> para $2. Só se usará a anchura e a altura.",
        "apiwarn-deprecation-httpsexpected": "Utilizouse HTTP cando esperábase HTTPS.",
        "apiwarn-deprecation-parameter": "O parámetro <var>$1</var> está obsoleto.",
        "apiwarn-invalidcategory": "\"$1\" non é unha categoría.",
index 03e6ded..682f9fc 100644 (file)
@@ -46,6 +46,7 @@
        "apihelp-block-param-allowusertalk": "לאפשר למשתמש לערוך את דף השיחה שלו או שלה (תלוי ב־<var>[[mw:Manual:$wgBlockAllowsUTEdit|$wgBlockAllowsUTEdit]]</var>).",
        "apihelp-block-param-reblock": "אם המשתמש כבר חסום, לדרוס את החסימה הנוכחית.",
        "apihelp-block-param-watchuser": "לעקוב אחרי דף המשתמש ודף השיחה של המשתמש או של כתובת ה־IP.",
+       "apihelp-block-param-tags": "תגי שינוי שיחולו על העיול ביומן החסימה.",
        "apihelp-block-example-ip-simple": "חסימת כתובת ה־IP‏ <kbd>192.0.2.5</kbd> לשלושה ימים עם הסיבה <kbd>First strike</kbd>.",
        "apihelp-block-example-user-complex": "חסימת המשתמש <kbd>Vandal</kbd> ללא הגבלת זמן עם הסיבה <kbd>Vandalism</kbd>, ומניעת יצירת חשבונות חדשים ושליחת דוא\"ל.",
        "apihelp-changeauthenticationdata-description": "שינוי נתוני אימות עבור המשתמש הנוכחי.",
@@ -89,7 +90,7 @@
        "apihelp-delete-param-title": "כותרת העמוד למחיקה. לא ניתן להשתמש בשילוב עם <var>$1pageid</var>.",
        "apihelp-delete-param-pageid": "מס׳ הזיהוי של העמוד למחיקה. לא ניתן להשתמש בשילוב עם <var>$1title</var>.",
        "apihelp-delete-param-reason": "סיבת המחיקה. אם לא הוגדרה, תתווסף סיבה שנוצרה אוטומטית.",
-       "apihelp-delete-param-tags": "×\9cשנ×\95ת ×\90ת ×\94ת×\92×\99×\9d ×\9b×\93י שיחולו על העיול ביומן המחיקה.",
+       "apihelp-delete-param-tags": "ת×\92×\99 ×©×\99× ×\95י שיחולו על העיול ביומן המחיקה.",
        "apihelp-delete-param-watch": "הוספת העמוד לרשימת המעקב של המשתמש הנוכחי.",
        "apihelp-delete-param-watchlist": "הוספה או הסרה של הדף ללא תנאי מרשימת המעקב של המשתמש הנוכחי, להשתמש בהעדפות או לא לשנות את המעקב.",
        "apihelp-delete-param-unwatch": "הסרת הדף מרשימת המעקב של של המשתמש הנוכחי.",
        "apihelp-import-param-templates": "ליבוא בין אתרי ויקי: לייבא גם את כל התבניות המוכללות.",
        "apihelp-import-param-namespace": "לייבא למרחב השם הזה. לא ניתן להשתמש בזה יחד עם <var>$1rootpage</var>.",
        "apihelp-import-param-rootpage": "לייבא בתור תת־משנה של הדף הזה. לא ניתן להשתמש בזה יחד עם <var>$1namespace</var>.",
+       "apihelp-import-param-tags": "תגי שינוי שיחולו על העיול ביומן הייבוא ולגרסה הריקה בדפים המיובאים.",
        "apihelp-import-example-import": "לייבא את [[meta:Help:ParserFunctions]] למרחב השם 100 עם היסטוריה מלאה.",
        "apihelp-linkaccount-description": "קישור חשבון של ספק צד־שלישי למשתמש הנוכחי.",
        "apihelp-linkaccount-example-link": "תחילת תהליך הקישור לחשבון מ־<kbd>Example</kbd>.",
        "apihelp-managetags-param-tag": "תג ליצירה, מחיקה, הפעלה או כיבוי. ליצירת תג, התג לא צריך להיות קיים. למחיקת תג, התג צריך להיות קיים. להפעלת תג, התג צריך להתקיים ולא להיות בשימוש של הרחבה. לכיבוי תג, התג צריך להיות קיים ומוגדר ידנית.",
        "apihelp-managetags-param-reason": "סיבה אופציונלית ליצירה, מחיקה, הפעלה או כיבוי של תג.",
        "apihelp-managetags-param-ignorewarnings": "האם להתעלם מכל האזהרות שמופיעות תוך כדי הפעולה.",
+       "apihelp-managetags-param-tags": "תגי השינוי שיחולו על העיול ביומן ניהול התגים.",
        "apihelp-managetags-example-create": "יצירת תג בשם <kbd>spam</kbd> עם הסיבה <kbd>For use in edit patrolling</kbd>",
        "apihelp-managetags-example-delete": "מחיקת התג <kbd>vandlaism</kbd> עם הסיבה <kbd>Misspelt</kbd>",
        "apihelp-managetags-example-activate": "הפעלת התג <kbd>spam</kbd> עם הסיבה <kbd>For use in edit patrolling</kbd>",
        "apihelp-move-param-unwatch": "הסרת הדף וההפניה מרשימת המעקב של המשתמש הנוכחי.",
        "apihelp-move-param-watchlist": "הוספה או הסרה של הדף ללא תנאי מרשימת המעקב של המשתמש הנוכחי, להשתמש בהעדפות או לא לשנות את המעקב.",
        "apihelp-move-param-ignorewarnings": "להתעלם מכל האזהרות.",
+       "apihelp-move-param-tags": "תגי שינוי שיחולו על העיול ביומן ההעברות ולגרסה הריקה בדף היעד.",
        "apihelp-move-example-move": "העברת <kbd>Badtitle</kbd> ל־<kbd>Goodtitle</kbd> בלי להשאיר הפניה.",
        "apihelp-opensearch-description": "חיפוש בוויקי בפרוטוקול OpenSearch.",
        "apihelp-opensearch-param-search": "מחרוזת לחיפוש.",
        "apihelp-query+usercontribs-param-end": "באיזה חותם־הזמן לסיים",
        "apihelp-query+usercontribs-param-user": "עבור אילו משתמשים לאחזר תרומות. לא יכול לשמש עם <var>$1userids</var> או <var>$1userprefix</var>.",
        "apihelp-query+usercontribs-param-userprefix": "אחזור תרומות עבור כל המשתמשים שהשמות שלהם מתחילים בערך הזה. לא יכול לשמש עם <var>$1user</var> או <var>$1userids</var>.",
+       "apihelp-query+usercontribs-param-userids": "מזהי המשתמשים לאחזור תרומות.  לא יכול לשמש עם  <var>$1user</var> או <var>$1userprefix</var>.",
        "apihelp-query+usercontribs-param-namespace": "לרשום רק תרומות במרחבי השם האלה.",
        "apihelp-query+usercontribs-param-prop": "לכלול פריטי מידע נוספים:",
        "apihelp-query+usercontribs-paramvalue-prop-ids": "הוספת מזהה הדף ומזהה הגרסה.",
        "apihelp-query+userinfo-paramvalue-prop-blockinfo": "מתייג אם המשתמש הנוכחי נחסם, על־ידי מי ומאיזו סיבה.",
        "apihelp-query+userinfo-paramvalue-prop-hasmsg": "הוספת התג <samp>messages</samp> אם למשתמש הנוכחי יש הודעות ממתינות.",
        "apihelp-query+userinfo-paramvalue-prop-groups": "רשימת כל הקבוצות שהמשתמש שייך אליהן.",
+       "apihelp-query+userinfo-paramvalue-prop-groupmemberships": "לרשום קבוצות שהמשתמש הנוכחי משויך אליהן במפורש, כולל תאריך תפוגה לחברות בכל קבוצה.",
        "apihelp-query+userinfo-paramvalue-prop-implicitgroups": "רשימת כל הקבוצות שהמשתמש שייך אליהן באופן אוטומטי.",
        "apihelp-query+userinfo-paramvalue-prop-rights": "רשימת כל ההרשאות שיש למשתמש הזה.",
        "apihelp-query+userinfo-paramvalue-prop-changeablegroups": "רשימת הקבוצות שהמשתמש הנוכחי יכול להוסיף אליהן ולגרוע מהן.",
        "apihelp-query+users-param-prop": "אילו חלקי מידע לקבל:",
        "apihelp-query+users-paramvalue-prop-blockinfo": "מתייג אם המשתמש חסום, על־ידי מי, ומאיזו סיבה.",
        "apihelp-query+users-paramvalue-prop-groups": "רשימת כל הקבוצות שהמשתמש שייך אליהן.",
+       "apihelp-query+users-paramvalue-prop-groupmemberships": "לרשום קבוצות שכל משתמש משויך אליהן במפורש, כולל תאריך תפוגה לחברות בכל קבוצה.",
        "apihelp-query+users-paramvalue-prop-implicitgroups": "רשימת כל הקבוצות שהמשתמש חבר בהן אוטומטית.",
        "apihelp-query+users-paramvalue-prop-rights": "רשימת כל ההרשאות שיש למשתמש.",
        "apihelp-query+users-paramvalue-prop-editcount": "הוספת מניין העריכות של המשתמש.",
        "apihelp-setpagelanguage-description": "שנה את השפה של דף",
        "apihelp-setpagelanguage-description-disabled": "שינוי השפה של דף לא מורשה בוויקי זה.\n\nהפעל את <var>[[mw:Manual:$wgPageLanguageUseDB|$wgPageLanguageUseDB]]</var> על מנת להשתמש בפעולה זו",
        "apihelp-setpagelanguage-param-title": "כותרת הדף שאת שפתו ברצונך לשנות. לא אפשרי להשתמש באפשרות עם <var>$1pageid</var>.",
+       "apihelp-setpagelanguage-param-reason": "הסיבה לשינוי.",
        "apihelp-setpagelanguage-param-tags": "אילו תגי שינוי להחיל על העיול ביומן שמתבצע כתוצאה מהפעולה הזאת.",
+       "apihelp-setpagelanguage-example-language": "שינוי השפה של <kbd>Main Page</kbd> לבסקית.",
+       "apihelp-setpagelanguage-example-default": "שינוי השפה של הדף בעל המזהה 123 לשפה הרגילה של הוויקי.",
        "apihelp-stashedit-description": "הכנת עריכה במטמון משותף.\n\nזה מיועד לשימוש דרך AJAX מתוך ערך כדי לשפר את הביצועים של שמירת הדף.",
        "apihelp-stashedit-param-title": "כותרת הדף הנערך.",
        "apihelp-stashedit-param-section": "מספר הפסקה. <kbd>0</kbd> עבור הפסקה הראשונה, <kbd>new</kbd> עבור פסקה חדשה.",
        "apierror-integeroutofrange-abovemax": "<var>$1</var> אינו יכול להיות גדול מ־$2 (עכשיו מוגדר $3) עבור משתמשים.",
        "apierror-integeroutofrange-belowminimum": "<var>$1</var> אינו יכול להיות גדול מ־$2 (עכשיו מוגדר $3).",
        "apierror-invalidcategory": "שם הקטגוריה שהזנת אינו תקין.",
+       "apierror-invalidexpiry": "זמן תפוגה בלתי־תקין \"$1\".",
        "apierror-invalid-file-key": "לא מפתח קובץ תקין.",
        "apierror-invalidtitle": "כותרת רעה \"$1\".",
        "apierror-invaliduser": "שם משתמש בלתי־תקין \"$1\".",
        "apierror-upload-filekeyneeded": "חובה לספק <var>filekey</var> כאשר <var>offset</var> אינו אפס.",
        "apierror-upload-filekeynotallowed": "לא ניתן לספק <var>filekey</var> כאשר <var>offset</var> הוא 0.",
        "apierror-upload-missingresult": "אין תוצאות בנתוני מצב.",
+       "apierror-writeapidenied": "אין לך הרשאה לערוך את הוויקי הזה דרך ה־API.",
+       "apiwarn-alldeletedrevisions-performance": "לביצועים טובים יותר בעת יצירת כותרת, יש להשתמש ב־<kbd>$1dir=newer</kbd>.",
+       "apiwarn-badurlparam": "לא היה אפשר לפענח את <var>$1urlparam</var> עבור $2. משתמשים רק ב־width ו־height.",
+       "apiwarn-badutf8": "הערך הערך שהועבר ל־<var>$1</var> מכיל נתונים בלתי־תקינים או בלתי־מנורמלים. נתונים טקסט אמורים להיות תקינים, מנורמלי NFC ללא תווי בקרה C0 למעט HT (\\t)‏, LF (\\n), ו־CR (\\r).",
+       "apiwarn-checktoken-percentencoding": "נא לבדוק שסימנים כמו \"+\" באסימון מקודדים עם אחוזים בצורה נכונה ב־URL.",
+       "apiwarn-deprecation-deletedrevs": "<kbd>list=deletedrevs</kbd> הוצהר בתור מיושן. נא להשתמש ב־ <kbd>prop=deletedrevisions</kbd> או ב־<kbd>list=alldeletedrevisions</kbd> במקום זה.",
+       "apiwarn-deprecation-expandtemplates-prop": "מכיוון שלא ניתנו ערכים לפרמטר <var>prop</var>, תסדיר מיושן ישמש לפלט. התסדיר הזה מיושן, ובעתיד יינתן ערך בררת מחדל לפרמטר <var>prop</var>, כך שתמיד ישמש התסדיר החדש.",
+       "apiwarn-deprecation-httpsexpected": "משמש HTTP כשהיה צפוי HTTPS.",
+       "apiwarn-deprecation-login-botpw": "כניסה לחשבון עיקרי (main-account) דרך <kbd>action=login</kbd> מיושנת ועלולה להפסיק לעבוד ללא אזהרה נוספת. כדי להמשיך להיכנס עם <kbd>action=login</kbd>, ר' [[Special:BotPasswords]]. כדי להמשיך באופן מאובטח באמצעות חשבון עיקרי, ר' <kbd>action=clientlogin</kbd>.",
+       "apiwarn-deprecation-login-token": "אחזור אסימון דרך <kbd>action=login</kbd> מיושן. נא להשתמש ב־<kbd>action=query&meta=tokens&type=login</kbd> במקום זה.",
+       "apiwarn-deprecation-parameter": "הפרמטר <var>$1</var> מיושן.",
+       "apiwarn-deprecation-parse-headitems": "<kbd>prop=headitems</kbd> מיושן מאז מדיה־ויקי 1.28. יש להשתמש ב־<kbd>prop=headhtml</kbd> בעת יצירת מסמכי HTML חדשים, או ב־<kbd>prop=modules|jsconfigvars</kbd> בעת עדכון מסמך בצד הלקוח.",
+       "apiwarn-deprecation-purge-get": "שימוש ב־<kbd>action=purge</kbd> דרך GET מיושן. יש להשתמש ב־POST במקום זה.",
+       "apiwarn-deprecation-withreplacement": "<kbd>$1</kbd> מיושן. יש להשתמש ב־<kbd>$2</kbd> במקום זה.",
+       "apiwarn-difftohidden": "לא היה אפשר לעשות השוואה עם גרסה $1: התוכן מוסתר.",
+       "apiwarn-errorprinterfailed": "מדפיס השגיאות לא עבד. ינסה שוב ללא פרמטרים.",
+       "apiwarn-errorprinterfailed-ex": "מדפיס השגיאות לא עבד (ינסה שוב ללא פרמטרים): $1",
        "apiwarn-invalidcategory": "\"$1\" אינה קטגוריה.",
        "apiwarn-invalidtitle": "\"$1\" אינה כותרת תקינה.",
+       "apiwarn-invalidxmlstylesheetext": "לגיליון הסגנונות אמור להיות הסיומת <code dir=\"ltr\">.xsl</code>.",
+       "apiwarn-invalidxmlstylesheet": "ניתן גיליון סגנונות שאינו תקין או אינו קיים.",
+       "apiwarn-invalidxmlstylesheetns": "גיליון הסגנונות אמור להיות במרחב השם {{ns:MediaWiki}}.",
+       "apiwarn-moduleswithoutvars": "המאפיין <kbd>modules</kbd> לא הוגדר, אבל לא <kbd>jsconfigvars</kbd> או <kbd>encodedjsconfigvars</kbd>. משתני הגדרות נחוצים בשביל שימוש נכון במודולים.",
        "apiwarn-notfile": "\"$1\" אינו קובץ.",
+       "apiwarn-nothumb-noimagehandler": "לא היה אפשר ליצור תמונה ממוזערת כי לקובץ $1 לא משויך מטפל תמונה.",
+       "apiwarn-parse-nocontentmodel": "לא ניתן <var>title</var> או <var>contentmodel</var>, נניח שזה $1.",
+       "apiwarn-parse-titlewithouttext": "<var>title</var> שימש ללא <var>text</var>, והתבקשו מאפייני דף מפוענח. האם התכוונת להשתמש ב־<var>page</var> במקום <var>title</var>?",
+       "apiwarn-redirectsandrevids": "פתרון הפניות לא יכול לשמש יחד עם הפרמטר <var>revids</var>. הפניות ש־<var>revids</var> מצביע אליהן לא נפתרו.",
+       "apiwarn-tokennotallowed": "הפעולה \"$1\" אינה מותרת למשתמש הנוכחי.",
+       "apiwarn-tokens-origin": "לא ניתן לקבל אסימונים כשמדיניות המקור הזהה אינה חלה.",
+       "apiwarn-toomanyvalues": "יותר מדי ערכים סופקו לפרמטר <var>$1</var>: המגבלה היא $2.",
+       "apiwarn-truncatedresult": "התוצאה נחתכה כי אחרת היא הייתה ארוכה מהמגבלה של $1 בתים.",
+       "apiwarn-unclearnowtimestamp": "העברת \"$2\" בתור פרמטר חותם־זמן <var>$1</var> הוצהרה בתור מיושנת. אם מסיבה כלשהי אתם צריכים להגדיר במפורש את הזמן הנוכחי ללא חישובו בצד הלקוח, יש להשתמש ב־<kbd>now</kbd>.",
+       "apiwarn-unrecognizedvalues": "לפרמטר <var>$1</var> היתנ ג{{PLURAL:$3|ניתן ערך בלתי־ידוע|ניתנו ערכים בלתי־ידועים}}: $2.",
+       "apiwarn-unsupportedarray": "הפרמטר <var>$1</var> משתמש בתחביר מערכים שאינו נתמך ב־PHP.",
+       "apiwarn-urlparamwidth": "התעלמות מרוחב (width) שהוגדר ב־<var>$1urlparam</var> (ערך: $2) לטובת רוחב שנגזר מ־<var>$1urlwidth</var>/<var>$1urlheight</var> (ערך: $3).",
+       "apiwarn-validationfailed-badchars": "תווים בלתי־תקינים במפתח (מותרים רק <code>a-z</code>‏, <code>A-Z</code>‏, <code>0-9</code>‏, <code>_</code>, ו־<code>-</code>).",
        "apiwarn-validationfailed-badpref": "לא העדפה תקינה.",
        "apiwarn-validationfailed-cannotset": "לא יכולה להיות מוגדרת על־ידי המודול הזה.",
        "apiwarn-validationfailed-keytoolong": "המפתח ארוך מדי (מותר לכתוב לא יותר מ־$1 בתים).",
        "apiwarn-wgDebugAPI": "<strong>אזהרת אבטחה</strong>: <var dir=\"ltr\">$wgDebugAPI</var> מופעל.",
        "api-feed-error-title": "שגיאה ($1)",
        "api-usage-docref": "ר' $1 לשימוש ב־API.",
+       "api-usage-mailinglist-ref": "עשו מינוי לרשימת התפוצה mediawiki-api-announce בכתובת &lt;https://lists.wikimedia.org/mailman/listinfo/mediawiki-api-announce&gt; בשביל הודעות על התיישנות API ושינויים שוברים.",
        "api-exception-trace": "$1 בקובץ $2 (שורה $3)\n$4",
        "api-credits-header": "קרדיטים",
        "api-credits": "מפתחי ה־API:\n* רואן קטאו (מפתח מוביל 2007–2009)\n* ויקטור וסילייב\n* בריאן טונג מין\n* סאם ריד\n* יורי אסטרחן (יוצר, מפתח מוביל מספטמבר 2006 עד ספטמבר 2007)\n* בראד יורש (מפתח מוביל מאז 2013)\n\nאנא שלחו הערות, הצעות ושאלות לכתובת mediawiki-api@lists.wikimedia.org או כתבו דיווח באג באתר https://phabricator.wikimedia.org."
index 6f271ec..258a3d4 100644 (file)
        "apihelp-filerevert-description": "파일을 이전 판으로 되돌립니다.",
        "apihelp-filerevert-param-comment": "업로드 댓글입니다.",
        "apihelp-filerevert-example-revert": "<kbd>Wiki.png</kbd>를 <kbd>2011-03-05T15:27:40Z</kbd> 판으로 되돌립니다.",
-       "apihelp-help-description": "지정된 모듈의 도움말을 보여줍니다.",
+       "apihelp-help-description": "지정된 모듈의 도움말을 표시합니다.",
        "apihelp-help-param-helpformat": "도움말 출력 포맷.",
        "apihelp-help-example-main": "메인 모듈의 도움말입니다.",
        "apihelp-help-example-recursive": "모든 도움말을 한 페이지로 모읍니다.",
index f782ae0..71dcdfd 100644 (file)
@@ -41,6 +41,7 @@
        "apihelp-block-param-autoblock": "Blokkeer automatisch het laatst gebruikte IP-adres en ieder volgend IP-adres van waaruit ze proberen aan te melden.",
        "apihelp-block-param-noemail": "Gebruiker weerhouden van het sturen van e-mail. (Vereist het <code>blockemail</code> recht).",
        "apihelp-block-param-hidename": "Verberg de gebruikersnaam uit het blokkeerlogboek. (Vereist het <code>hideuser</code> recht).",
+       "apihelp-block-param-allowusertalk": "De gebruiker toestaan om hun eigen overlegpagina te bewerken (afhankelijk van <var>[[mw:Manual:$wgBlockAllowsUTEdit|$wgBlockAllowsUTEdit]]</var>).",
        "apihelp-block-param-reblock": "De huidige blokkade aanpassen als de gebruiker al geblokkeerd is.",
        "apihelp-block-param-watchuser": "De gebruikerspagina en overlegpagina van de gebruiker of het IP-adres volgen.",
        "apihelp-block-param-tags": "Wijzigingslabels om toe te passen op de regel in het blokkeerlogboek.",
index 297f7ed..c3ccad6 100644 (file)
        "apiwarn-deprecation-parse-headitems": "{{doc-apierror}}",
        "apiwarn-deprecation-purge-get": "{{doc-apierror}}",
        "apiwarn-deprecation-withreplacement": "{{doc-apierror}}\n\nParameters:\n* $1 - Query string fragment that is deprecated, e.g. \"action=tokens\".\n* $2 - Query string fragment to use instead, e.g. \"action=tokens\".",
-       "apiwarn-difftohidden": "{{doc-apierror}}\n\nParameters:\n* $1 - Revision ID number.",
+       "apiwarn-difftohidden": "{{doc-apierror}}\n\nParameters:\n* $1 - Revision ID number.\n\n\"r\" is short for \"revision\". You may translate it.",
        "apiwarn-errorprinterfailed": "{{doc-apierror}}",
        "apiwarn-errorprinterfailed-ex": "{{doc-apierror}}\n\nParameters:\n* $1 - Exception message, which may already end in punctuation. Probably in English.",
        "apiwarn-invalidcategory": "{{doc-apierror}}\n\nParameters:\n* $1 - Supplied category name.",
index 7960775..007c9d7 100644 (file)
        "api-help-param-continue": "Когда доступно больше результатов, использовать этот чтобы продолжить.",
        "api-help-param-no-description": "<span class=\"apihelp-empty\">(описание отсутствует)</span>",
        "api-help-examples": "Пример{{PLURAL:$1||ы}}:",
-       "api-help-permissions": "{{PLURAL:$1|Permission|Permissions}}:",
+       "api-help-permissions": "{{PLURAL:$1|Разрешение|Разрешения}}:",
        "api-help-permissions-granted-to": "{{PLURAL:$1|Granted to}}: $2",
        "apierror-integeroutofrange-abovemax": "<var>$1</var> не может быть более $2 (на $3) для пользователей.",
        "apierror-nosuchuserid": "Нет пользователя с ID $1.",
index dae1414..e3dba0b 100644 (file)
        "apihelp-protect-example-protect": "Захистити сторінку.",
        "apihelp-protect-example-unprotect": "Зняти захист зі сторінки, встановивши обмеження для <kbd>all</kbd> (тобто будь-хто зможе робити дії).",
        "apihelp-protect-example-unprotect2": "Зняти захист з сторінки, встановивши відсутність обмежень.",
-       "apihelp-purge-description": "Очистити кеш для вказаних заголовків.\n\nВимагає запиту POST, якщо користувач не ввійшов у систему.",
+       "apihelp-purge-description": "Очистити кеш для вказаних заголовків.",
        "apihelp-purge-param-forcelinkupdate": "Оновити таблиці посилань.",
        "apihelp-purge-param-forcerecursivelinkupdate": "Оновити таблицю посилань, і оновити таблиці посилань для кожної сторінки, що використовує цю сторінку як шаблон.",
        "apihelp-purge-example-simple": "Очистити кеш <kbd>Main Page</kbd> і сторінки <kbd>API</kbd>.",
        "apiwarn-tokens-origin": "Токени не можна отримати, поки не застосована політика одного походження.",
        "apiwarn-toomanyvalues": "Надто багато значень задано для параметра <var>$1</var>: ліміт становить $2.",
        "apiwarn-truncatedresult": "Цей результат було скорочено, оскільки інакше він перевищив би ліміт у $1 байтів.",
-       "apiwarn-unclearnowtimestamp": "Вказування «$2» для параметра мітки часу <var>$1</var> є застарілим. Якщо з якоїсь причини Вам треба чітко вказати поточний час без вираховування його з боку клієнта, використайте <kbd>now<kbd>.",
+       "apiwarn-unclearnowtimestamp": "Вказування «$2» для параметра мітки часу <var>$1</var> є застарілим. Якщо з якоїсь причини Вам треба чітко вказати поточний час без вираховування його з боку клієнта, використайте <kbd>now</kbd>.",
        "apiwarn-unrecognizedvalues": "{{PLURAL:$3|Нерозпізнане|Нерозпізнані}} значення для параметра <var>$1</var>: $2.",
        "apiwarn-unsupportedarray": "Параметр <var>$1</var> використовує непідтримуваний синтаксис PHP-масиву.",
        "apiwarn-urlparamwidth": "Ігнорування значення ширини, встановленого в <var>$1urlparam</var> ($2) на користь значення ширини, запозиченого із <var>$1urlwidth</var>/<var>$1urlheight</var> ($3).",
index 07c1741..36251d4 100644 (file)
        "apiwarn-tokennotallowed": "操作“$1”不允许当前用户使用。",
        "apiwarn-toomanyvalues": "参数<var>$1</var>指定了太多的值:上限为$2。",
        "apiwarn-truncatedresult": "此结果被缩短,否则其将大于$1字节的限制。",
-       "apiwarn-unclearnowtimestamp": "为时间戳参数<var>$1</var>传递“$2”已被弃用。如因某些原因您需要明确指定当前时间而不计算客户端,请使用<kbd>now<kbd>。",
+       "apiwarn-unclearnowtimestamp": "为时间戳参数<var>$1</var>传递“$2”已被弃用。如因某些原因您需要明确指定当前时间而不计算客户端,请使用<kbd>now</kbd>。",
        "apiwarn-unrecognizedvalues": "参数<var>$1</var>有无法识别的{{PLURAL:$3|值}}:$2。",
        "apiwarn-unsupportedarray": "参数<var>$1</var>使用未受支持的PHP数组语法。",
        "apiwarn-validationfailed-badchars": "关键词中的字符无效(只允许<code>a-z</code>、<code>A-Z</code>、<code>0-9</code>、<code>_</code>和<code>-</code>)。",
index 1e88e13..bc7d721 100644 (file)
@@ -158,19 +158,43 @@ class ChangesList extends ContextSource {
        protected function getHTMLClasses( $rc, $watched ) {
                $classes = [];
                $logType = $rc->mAttribs['rc_log_type'];
+               $prefix = 'mw-changeslist-';
 
                if ( $logType ) {
-                       $classes[] = Sanitizer::escapeClass( 'mw-changeslist-log-' . $logType );
+                       $classes[] = Sanitizer::escapeClass( $prefix . 'log-' . $logType );
                } else {
-                       $classes[] = Sanitizer::escapeClass( 'mw-changeslist-ns' .
+                       $classes[] = Sanitizer::escapeClass( $prefix . 'ns' .
                                $rc->mAttribs['rc_namespace'] . '-' . $rc->mAttribs['rc_title'] );
                }
 
                // Indicate watched status on the line to allow for more
                // comprehensive styling.
                $classes[] = $watched && $rc->mAttribs['rc_timestamp'] >= $watched
-                       ? 'mw-changeslist-line-watched'
-                       : 'mw-changeslist-line-not-watched';
+                       ? $prefix . 'line-watched'
+                       : $prefix . 'line-not-watched';
+
+               $classes = array_merge( $classes, $this->getHTMLClassesForFilters( $rc ) );
+
+               return $classes;
+       }
+
+       protected function getHTMLClassesForFilters( $rc ) {
+               $classes = [];
+               $prefix = 'mw-changeslist-';
+
+               $classes[] = $prefix . ( $rc->getAttribute( 'rc_bot' ) ? 'bot' : 'human' );
+               $classes[] = $prefix . ( $rc->getAttribute( 'rc_user' ) ? 'liu' : 'anon' );
+               $classes[] = $prefix . ( $rc->getAttribute( 'rc_minor' ) ? 'minor' : 'major' );
+               $classes[] = $prefix .
+                       ( $rc->getAttribute( 'rc_patrolled' ) ? 'patrolled' : 'unpatrolled' );
+               $classes[] = $prefix .
+                       ( $this->getUser()->equals( $rc->getPerformer() ) ? 'self' : 'others' );
+               $classes[] = $prefix . 'src-' . str_replace( '.', '-', $rc->getAttribute( 'rc_source' ) );
+
+               $performer = $rc->getPerformer();
+               if ( $performer && $performer->isLoggedIn() ) {
+                       $classes[] = $prefix . 'user-' . $performer->getExperienceLevel();
+               }
 
                return $classes;
        }
@@ -379,7 +403,7 @@ class ChangesList extends ContextSource {
                        $diffLink = $this->linkRenderer->makeKnownLink(
                                $rc->getTitle(),
                                new HtmlArmor( $this->message['diff'] ),
-                               [],
+                               [ 'class' => 'mw-changeslist-diff' ],
                                $query
                        );
                }
@@ -391,7 +415,7 @@ class ChangesList extends ContextSource {
                        $diffhist .= $this->linkRenderer->makeKnownLink(
                                $rc->getTitle(),
                                new HtmlArmor( $this->message['hist'] ),
-                               [],
+                               [ 'class' => 'mw-changeslist-history' ],
                                [
                                        'curid' => $rc->mAttribs['rc_cur_id'],
                                        'action' => 'history'
index d3a414b..3c76f32 100644 (file)
@@ -177,6 +177,7 @@ class EnhancedChangesList extends ChangesList {
                        && $block[0]->mAttribs['rc_timestamp'] >= $block[0]->watched
                ) {
                        $tableClasses[] = 'mw-changeslist-line-watched';
+                       $tableClasses = array_merge( $tableClasses, $this->getHTMLClassesForFilters( $block[0] ) );
                } else {
                        $tableClasses[] = 'mw-changeslist-line-not-watched';
                }
@@ -358,16 +359,17 @@ class EnhancedChangesList extends ChangesList {
        protected function getLineData( array $block, RCCacheEntry $rcObj, array $queryParams = [] ) {
                $RCShowChangedSize = $this->getConfig()->get( 'RCShowChangedSize' );
 
-               $classes = [ 'mw-enhanced-rc' ];
                $type = $rcObj->mAttribs['rc_type'];
                $data = [];
                $lineParams = [];
 
+               $classes = [ 'mw-enhanced-rc' ];
                if ( $rcObj->watched
                        && $rcObj->mAttribs['rc_timestamp'] >= $rcObj->watched
                ) {
-                       $classes = [ 'mw-enhanced-watched' ];
+                       $classes[] = [ 'mw-enhanced-watched' ];
                }
+               $classes = array_merge( $classes, $this->getHTMLClassesForFilters( $rcObj ) );
 
                $separator = ' <span class="mw-changeslist-separator">. .</span> ';
 
index 7659d6c..d67bc7e 100644 (file)
@@ -67,7 +67,7 @@ abstract class Collation {
                                return new CollationFa;
                        default:
                                $match = [];
-                               if ( preg_match( '/^uca-([a-z@=-]+)$/', $collationName, $match ) ) {
+                               if ( preg_match( '/^uca-([A-Za-z@=-]+)$/', $collationName, $match ) ) {
                                        return new IcuCollation( $match[1] );
                                }
 
index 6a1bbd6..da660bd 100644 (file)
@@ -1,5 +1,7 @@
 <?php
 
+use Wikimedia\Rdbms\LoadBalancer;
+
 /**
  * Base class for objects that allow access to other wiki's databases using
  * the foreign database access mechanism implemented by LBFactoryMulti.
index 0186222..fe063f2 100644 (file)
@@ -59,6 +59,9 @@ abstract class MWLBFactory {
                        'readOnlyReason' => wfConfiguredReadOnlyReason(),
                ];
 
+               // When making changes here, remember to also specify MediaWiki-specific options
+               // for Database classes in the relevant Installer subclass.
+               // Such as MysqlInstaller::openConnection and PostgresInstaller::openConnectionWithParams.
                if ( $lbConf['class'] === 'LBFactorySimple' ) {
                        if ( isset( $lbConf['servers'] ) ) {
                                // Server array is already explicitly configured; leave alone
index ce0cda1..2700daa 100644 (file)
@@ -138,9 +138,7 @@ class AvroFormatter implements FormatterInterface {
                                $this->schemas[$channel]['schema'] = AvroSchema::parse( $schema );
                        } else {
                                $this->schemas[$channel]['schema'] = AvroSchema::real_parse(
-                                       $schema,
-                                       null,
-                                       new AvroNamedSchemata()
+                                       $schema
                                );
                        }
                }
index 553cbf6..09ed755 100644 (file)
@@ -6,6 +6,7 @@ namespace MediaWiki\Logger\Monolog;
  * LogstashFormatter squashes the base message array and the context and extras subarrays into one.
  * This can result in unfortunately named context fields overwriting other data (T145133).
  * This class modifies the standard LogstashFormatter to rename such fields and flag the message.
+ * Also changes exception JSON-ification which is done poorly by the standard class.
  *
  * Compatible with Monolog 1.x only.
  *
@@ -80,4 +81,31 @@ class LogstashFormatter extends \Monolog\Formatter\LogstashFormatter {
                }
                return $fields;
        }
+
+       /**
+        * Use a more user-friendly trace format than NormalizerFormatter
+        * @param \Exception|\Throwable $e
+        * @return array
+        */
+       protected function normalizeException( $e ) {
+               if ( !$e instanceof \Exception && !$e instanceof \Throwable ) {
+                       throw new \InvalidArgumentException( 'Exception/Throwable expected, got '
+                               . gettype( $e ) . ' / ' . get_class( $e ) );
+               }
+
+               $data = [
+                       'class' => get_class( $e ),
+                       'message' => $e->getMessage(),
+                       'code' => $e->getCode(),
+                       'file' => $e->getFile() . ':' . $e->getLine(),
+                       'trace' => \MWExceptionHandler::getRedactedTraceAsString( $e ),
+               ];
+
+               $previous = $e->getPrevious();
+               if ( $previous ) {
+                       $data['previous'] = $this->normalizeException( $previous );
+               }
+
+               return $data;
+       }
 }
index 05256ae..000b526 100644 (file)
@@ -21,6 +21,7 @@
  */
 use MediaWiki\MediaWikiServices;
 use Wikimedia\Rdbms\LBFactory;
+use Wikimedia\Rdbms\LoadBalancer;
 
 /**
  * Class for managing the deferred updates
index bef379e..44ab0e4 100644 (file)
@@ -20,6 +20,7 @@
 
 use MediaWiki\Logger\LoggerFactory;
 use MediaWiki\MediaWikiServices;
+use Psr\Log\LogLevel;
 
 /**
  * Handler class for MWExceptions
@@ -174,31 +175,37 @@ class MWExceptionHandler {
                switch ( $level ) {
                        case E_RECOVERABLE_ERROR:
                                $levelName = 'Error';
+                               $severity = LogLevel::ERROR;
                                break;
                        case E_WARNING:
                        case E_CORE_WARNING:
                        case E_COMPILE_WARNING:
                        case E_USER_WARNING:
                                $levelName = 'Warning';
+                               $severity = LogLevel::WARNING;
                                break;
                        case E_NOTICE:
                        case E_USER_NOTICE:
                                $levelName = 'Notice';
+                               $severity = LogLevel::INFO;
                                break;
                        case E_STRICT:
                                $levelName = 'Strict Standards';
+                               $severity = LogLevel::DEBUG;
                                break;
                        case E_DEPRECATED:
                        case E_USER_DEPRECATED:
                                $levelName = 'Deprecated';
+                               $severity = LogLevel::INFO;
                                break;
                        default:
                                $levelName = 'Unknown error';
+                               $severity = LogLevel::ERROR;
                                break;
                }
 
                $e = new ErrorException( "PHP $levelName: $message", 0, $level, $file, $line );
-               self::logError( $e, 'error' );
+               self::logError( $e, 'error', $severity );
 
                // This handler is for logging only. Return false will instruct PHP
                // to continue regular handling.
@@ -621,8 +628,11 @@ TXT;
         * @since 1.25
         * @param ErrorException $e
         * @param string $channel
+        * @param string $level
        */
-       protected static function logError( ErrorException $e, $channel ) {
+       protected static function logError(
+               ErrorException $e, $channel, $level = LogLevel::ERROR
+       ) {
                $catcher = self::CAUGHT_BY_HANDLER;
                // The set_error_handler callback is independent from error_reporting.
                // Filter out unwanted errors manually (e.g. when
@@ -630,7 +640,8 @@ TXT;
                $suppressed = ( error_reporting() & $e->getSeverity() ) === 0;
                if ( !$suppressed ) {
                        $logger = LoggerFactory::getInstance( $channel );
-                       $logger->error(
+                       $logger->log(
+                               $level,
                                self::getLogMessage( $e ),
                                self::getLogContext( $e, $catcher )
                        );
@@ -640,7 +651,7 @@ TXT;
                $json = self::jsonSerializeException( $e, false, FormatJson::ALL_OK, $catcher );
                if ( $json !== false ) {
                        $logger = LoggerFactory::getInstance( "{$channel}-json" );
-                       $logger->error( $json, [ 'private' => true ] );
+                       $logger->log( $level, $json, [ 'private' => true ] );
                }
 
                Hooks::run( 'LogException', [ $e, $suppressed ] );
index 52c1a4c..d907c30 100644 (file)
@@ -20,6 +20,8 @@
  * @file
  */
 
+use Wikimedia\Rdbms\LoadBalancer;
+
 /**
  * DB accessable external objects.
  *
@@ -106,9 +108,7 @@ class ExternalStoreDB extends ExternalStoreMedium {
         * @return LoadBalancer
         */
        private function getLoadBalancer( $cluster ) {
-               $wiki = isset( $this->params['wiki'] ) ? $this->params['wiki'] : false;
-
-               return wfGetLBFactory()->getExternalLB( $cluster, $wiki );
+               return wfGetLBFactory()->getExternalLB( $cluster );
        }
 
        /**
index 5e8ed3f..d6efeb2 100644 (file)
@@ -214,6 +214,7 @@ class MssqlInstaller extends DatabaseInstaller {
                try {
                        $db = Database::factory( 'mssql', [
                                'host' => $this->getVar( 'wgDBserver' ),
+                               'port' => $this->getVar( 'wgDBport' ),
                                'user' => $user,
                                'password' => $password,
                                'dbname' => false,
index 6dfa28b..906768f 100644 (file)
@@ -156,10 +156,13 @@ class PostgresInstaller extends DatabaseInstaller {
                try {
                        $db = Database::factory( 'postgres', [
                                'host' => $this->getVar( 'wgDBserver' ),
+                               'port' => $this->getVar( 'wgDBport' ),
                                'user' => $user,
                                'password' => $password,
                                'dbname' => $dbName,
-                               'schema' => $schema ] );
+                               'schema' => $schema,
+                               'keywordTableMap' => [ 'user' => 'mwuser', 'text' => 'pagecontent' ],
+                       ] );
                        $status->value = $db;
                } catch ( DBConnectionError $e ) {
                        $status->fatal( 'config-connection-error', $e->getMessage() );
index 5c2b320..b950420 100644 (file)
@@ -65,6 +65,7 @@
        "config-apc": "[http://www.php.net/apc APC] е инсталиран",
        "config-apcu": "[http://www.php.net/apc APC] е инсталиран",
        "config-wincache": "[http://www.iis.net/download/WinCacheForPhp WinCache] е инсталиран",
+       "config-no-cache-apcu": "<strong>Внимание:</strong> [http://www.php.net/apcu APCu], [http://xcache.lighttpd.net/ XCache] и [http://www.iis.net/download/WinCacheForPhp WinCache] не могат да бъдат открити.\nКеширането на обекти не е активирано.",
        "config-mod-security": "<strong>Предупреждение:</strong> [http://modsecurity.org/ mod_security]/mod_security2 е включено на вашия уеб сървър. Много от обичайните му конфигурации пораждат проблеми с МедияУики и друг софтуер, който позволява публикуване на произволно съдържание.\nАко е възможно, моля изключете го. В противен случай се обърнете към [http://modsecurity.org/documentation/ документацията на mod_security] или се свържете с поддръжката на хостинга си, ако се сблъскате със случайни грешки.",
        "config-diff3-bad": "GNU diff3 не беше намерен.",
        "config-git": "Налична е системата за контрол на версиите Git: <code>$1</code>.",
@@ -84,6 +85,7 @@
        "config-db-host": "Хост на базата от данни:",
        "config-db-host-help": "Ако базата от данни е на друг сървър, в кутията се въвежда името на хоста или IP адреса.\n\nАко се използва споделен уеб хостинг, доставчикът на услугата би трябвало да е предоставил в документацията си коректния хост.\n\nАко инсталацията протича на Windows-сървър и се използва MySQL, използването на \"localhost\" може да е неприемливо. В такива случаи се използва \"127.0.0.1\" за локален IP адрес.\n\nПри използване на PostgreSQL, това поле се оставя празно, за свързване чрез Unix socket.",
        "config-db-host-oracle": "TNS на базата данни:",
+       "config-db-host-oracle-help": "Въведете валидно [http://download.oracle.com/docs/cd/B28359_01/network.111/b28317/tnsnames.htm Local Connect Name]; файлът tnsnames.ora трябва да бъде видим за инсталацията.<br />Ако използвате клиентска библиотека версия 10g или по-нова можете да използвате метода [http://download.oracle.com/docs/cd/E11882_01/network.112/e10836/naming.htm Easy Connect].",
        "config-db-wiki-settings": "Идентифициране на това уики",
        "config-db-name": "Име на базата от данни:",
        "config-db-name-help": "Избира се име, което да идентифицира уикито.\nТо не трябва да съдържа интервали.\n\nАко се използва споделен хостинг, доставчикът на услугата би трябвало да е предоставил или име на базата от данни, която да бъде използвана, или да позволява създаването на бази от данни чрез контролния панел.",
        "config-mysql-innodb": "InnoDB",
        "config-mysql-myisam": "MyISAM",
        "config-mysql-myisam-dep": "'''Предупреждение''': Избрана е MyISAM като система за складиране в MySQL, която не се препоръчва за използване с МедияУики, защото:\n* почти не поддържа паралелност заради заключване на таблиците\n* е по-податлива на повреди в сравнение с други системи\n* кодът на МедияУики не винаги поддържа MyISAM коректно\n\nАко инсталацията на MySQL поддържа InnoDB, силно е препоръчително да се използва тя.\nАко инсталацията на MySQL не поддържа InnoDB, вероятно е време за обновяване.",
+       "config-mysql-only-myisam-dep": "<strong>Внимание:</strong> MyISAM e единственият наличен на тази машина тип на таблиците за MySQL и не е препоръчителен за употреба при МедияУики защото:\n* има слаба поддръжка на конкурентност на заявките, поради закючването на таблиците\n* е много по-податлив на грешки в базите от данни от другите типове таблици\n* кодът на МедияУики не винаги работи с MyISAM както трябва\n\nВашият MySQL не поддържа InnoDB, така че може би е дошло време за актуализиране.",
        "config-mysql-engine-help": "'''InnoDB''' почти винаги е най-добрата възможност заради навременната си поддръжка.\n\n'''MyISAM''' може да е по-бърза при инсталации с един потребител или само за четене.\nБазите от данни MyISAM се повреждат по-често от InnoDB.",
        "config-mysql-charset": "Набор от символи в базата от данни:",
        "config-mysql-binary": "Бинарен",
        "config-mysql-utf8": "UTF-8",
        "config-mysql-charset-help": "В '''бинарен режим''' МедияУики съхранява текстовете в UTF-8 в бинарни полета в базата от данни.\nТова е по-ефективно от UTF-8 режима на MySQL и позволява използването на пълния набор от символи в Уникод.\n\nВ '''UTF-8 режим''' MySQL ще знае в кой набор от символи са данните от уикито и ще може да ги показва и променя по подходящ начин, но няма да позволява складиране на символи извън [https://en.wikipedia.org/wiki/Mapping_of_Unicode_character_planes Основния многоезичен набор].",
        "config-mssql-auth": "Тип на удостоверяването:",
+       "config-mssql-install-auth": "Изберете начин за удостоверяване, който ще бъде използван за връзка с базата от данни по време на инсталацията.\nАко изберете \"{{int:config-mssql-windowsauth}}\", ще се използват идентификационните данни на потребителя под който работи уеб сървъра.",
+       "config-mssql-web-auth": "Изберете начина за удостоверяване, който ще се използва от уеб сървъра за връзка със сървъра за бази от данни по време на нормалните операции на уикито.\nАко изберете \"{{int:config-mssql-windowsauth}}\", ще се използват идентификационните данни на потребителя под който работи уеб сървъра.",
        "config-mssql-sqlauth": "Удостоверяване чрез SQL Server",
        "config-mssql-windowsauth": "Удостоверяване чрез Windows",
        "config-site-name": "Име на уикито:",
index f34849b..70ef27a 100644 (file)
        "config-profile-help": "Викијата функционираат најдобро кога имаат што повеќе уредници.\nВо МедијаВики лесно се проверуваат скорешните промени, и лесно се исправа (технички: „враќа“) штетата направена од неупатени или злонамерни корисници.\n\nМногумина имаат најдено најразлични полезни примени за МедијаВики, но понекогаш не е лесно да убедите некого во предностите на вики-концептот.\nЗначи имате избор.\n\n'''{{int:config-profile-wiki}}''' — модел според кој секој може да уредува, дури и без најавување.\nАко имате вики со '''задолжително отворање на сметка''', тогаш добивате повеќе контрола, но ова може даги одврати спонтаните учесници.\n\n'''{{int:config-profile-fishbowl}}''' — може да уредуваат само уредници што имаат добиено дозвола за тоа, но јавноста може да ги гледа страниците, вклучувајќи ја нивната историја.\n'''{{int:config-profile-private}}''' — страниците се видливи и уредливи само за овластени корисници.\n\nПо воспоставката имате на избор и посложени кориснички права и поставки. Погледајте во [https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:User_rights прирачникот].",
        "config-license": "Авторски права и лиценца:",
        "config-license-none": "Без подножје за лиценца",
-       "config-license-cc-by-sa": "Криејтив комонс НаведиИзвор СподелиПодИстиУслови",
-       "config-license-cc-by": "Криејтив комонс НаведиИзвор",
-       "config-license-cc-by-nc-sa": "Криејтив комонс НаведиИзвор-Некомерцијално-СподелиПодИстиУслови",
+       "config-license-cc-by-sa": "Криејтив комонс Наведи извор-Сподели под исти услови",
+       "config-license-cc-by": "Криејтив комонс Наведи извор",
+       "config-license-cc-by-nc-sa": "Криејтив комонс Наведи извор-Сподели под исти услови",
        "config-license-cc-0": "Криејтив комонс Нула (јавна сопственост)",
        "config-license-gfdl": "ГНУ-ова лиценца за слободна документација 1.3 или понова",
        "config-license-pd": "Јавна сопственост",
index f6b1d23..a499553 100644 (file)
        "config-profile-no-anon": "Account aanmaken verplicht",
        "config-profile-fishbowl": "Alleen voor geautoriseerde bewerkers",
        "config-profile-private": "Privéwiki",
-       "config-profile-help": "Wiki's werken het beste als ze door zoveel mogelijk gebruikers worden bewerkt.\nIn MediaWiki is het eenvoudig om de recente wijzigingen te controleren en eventuele foutieve of kwaadwillende bewerkingen terug te draaien.\n\nDaarnaast vinden velen MediaWiki goed inzetbaar in vele andere rollen, en soms is het niet handig om helemaal \"op de wikimanier\" te werken.\nDaarom biedt dit installatieprogramma u de volgende keuzes voor de basisinstelling van gebruikersvrijheden:\n\nHet profiel '''{{int:config-profile-wiki}}''' staat iedereen toe te bewerken, zonder zelfs aan te melden.\nEen wiki met '''{{int:config-profile-no-anon}}\" biedt extra verantwoordelijkheid, maar kan afschrikken toevallige gebruikers afschrikken.\n\nHet scenario '''{{int:config-profile-fishbowl}}''' laat gebruikers waarvoor dat is ingesteld bewerkt, maar andere gebruikers kunnen alleen pagina's bekijken, inclusief de bewerkingsgeschiedenis.\nIn een '''{{int:config-profile-private}}''' kunnen alleen goedgekeurde gebruikers pagina's bekijken en bewerken.\n\nMeer complexe instellingen voor gebruikersrechten zijn te maken na de installatie; hierover is meer te lezen in de [https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:User_rights handleiding].",
+       "config-profile-help": "Wiki's werken het beste als ze door zoveel mogelijk gebruikers worden bewerkt.\nIn MediaWiki is het eenvoudig om de recente wijzigingen te controleren en eventuele foutieve of kwaadwillende bewerkingen terug te draaien.\n\nDaarnaast vinden velen MediaWiki goed inzetbaar in vele andere rollen, en soms is het niet handig om helemaal \"op de wikimanier\" te werken.\nDaarom biedt dit installatieprogramma u de volgende keuzes voor de basisinstelling van gebruikersvrijheden:\n\nHet profiel '''{{int:config-profile-wiki}}''' staat iedereen toe te bewerken, zonder zelfs aan te melden.\nEen wiki met '''{{int:config-profile-no-anon}}''' biedt extra verantwoordelijkheid, maar kan toevallige gebruikers afschrikken.\n\nHet scenario '''{{int:config-profile-fishbowl}}''' laat gebruikers waarvoor dat is ingesteld bewerken, maar andere gebruikers kunnen alleen pagina's bekijken, inclusief de bewerkingsgeschiedenis.\nIn een '''{{int:config-profile-private}}''' kunnen alleen goedgekeurde gebruikers pagina's bekijken en bewerken.\n\nMeer complexe instellingen voor gebruikersrechten zijn te maken na de installatie; hierover is meer te lezen in de [https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:User_rights handleiding].",
        "config-license": "Auteursrechten en licentie:",
        "config-license-none": "Geen licentie in de voettekst",
        "config-license-cc-by-sa": "Creative Commons Naamsvermelding-Gelijk delen",
index 4f72f77..fc00965 100644 (file)
@@ -6,7 +6,6 @@ use Database;
 use DBConnRef;
 use IDatabase;
 use InvalidArgumentException;
-use LoadBalancer;
 
 /**
  * Database connection manager.
index 9d800a2..1c5c77e 100644 (file)
@@ -3467,4 +3467,4 @@ abstract class Database implements IDatabase, IMaintainableDatabase, LoggerAware
        }
 }
 
-class_alias( 'Database', 'DatabaseBase' );
+class_alias( Database::class, 'DatabaseBase' );
index d394692..db5b7e5 100644 (file)
@@ -18,4 +18,4 @@ class Blob implements IBlob {
        }
 }
 
-class_alias( 'Wikimedia\Rdbms\Blob', 'Blob' );
+class_alias( Blob::class, 'Blob' );
index 7a25f03..7918f36 100644 (file)
@@ -32,4 +32,4 @@ interface Field {
        function isNullable();
 }
 
-class_alias( 'Wikimedia\Rdbms\Field', 'Field' );
+class_alias( Field::class, 'Field' );
index 7b9b1cf..faf7fb1 100644 (file)
@@ -24,7 +24,6 @@
 namespace Wikimedia\Rdbms;
 
 use InvalidArgumentException;
-use LoadBalancer;
 use DBTransactionError;
 use DBReplicationWaitError;
 
index b2bd7ca..c4229bc 100644 (file)
@@ -31,7 +31,6 @@ use WANObjectCache;
 use Exception;
 use RuntimeException;
 use IDatabase;
-use LoadBalancer;
 use DBTransactionError;
 use DBReplicationWaitError;
 
index bb6e445..447b96f 100644 (file)
@@ -23,7 +23,6 @@
 
 namespace Wikimedia\Rdbms;
 
-use LoadBalancer;
 use IDatabase;
 use InvalidArgumentException;
 
index 1f5f93f..15cd508 100644 (file)
@@ -23,7 +23,6 @@
 
 namespace Wikimedia\Rdbms;
 
-use LoadBalancer;
 use InvalidArgumentException;
 
 /**
index f992643..5931d80 100644 (file)
@@ -23,7 +23,6 @@
 
 namespace Wikimedia\Rdbms;
 
-use LoadBalancerSingle;
 use IDatabase;
 use InvalidArgumentException;
 use BadMethodCallException;
index 4e6f6b0..4c277ff 100644 (file)
@@ -240,9 +240,6 @@ interface ILoadBalancer {
         * Index must be an actual index into the array.
         * If the server is already open, returns it.
         *
-        * On error, returns false, and the connection which caused the
-        * error will be available via $this->mErrorConnection.
-        *
         * @note If disable() was called on this LoadBalancer, this method will throw a DBAccessError.
         *
         * @param int $i Server index or DB_MASTER/DB_REPLICA
index b1c0cc8..6878712 100644 (file)
  * @file
  * @ingroup Database
  */
+namespace Wikimedia\Rdbms;
+
 use Psr\Log\LoggerInterface;
 use Psr\Log\NullLogger;
 use Wikimedia\ScopedCallback;
-use Wikimedia\Rdbms\TransactionProfiler;
-use Wikimedia\Rdbms\ILoadMonitor;
-use Wikimedia\Rdbms\DatabaseDomain;
-use Wikimedia\Rdbms\ILoadBalancer;
-use Wikimedia\Rdbms\DBMasterPos;
+use IDatabase;
+use Database;
+use DBConnRef;
+use MaintainableDBConnRef;
+use BagOStuff;
+use EmptyBagOStuff;
+use WANObjectCache;
+use ArrayUtils;
+use DBError;
+use DBAccessError;
+use DBExpectedError;
+use DBUnexpectedError;
+use DBTransactionError;
+use DBTransactionSizeError;
+use DBConnectionError;
+use InvalidArgumentException;
+use RuntimeException;
+use Exception;
 
 /**
  * Database connection, tracking, load balancing, and transaction manager for a cluster
@@ -37,7 +52,7 @@ use Wikimedia\Rdbms\DBMasterPos;
 class LoadBalancer implements ILoadBalancer {
        /** @var array[] Map of (server index => server config array) */
        private $mServers;
-       /** @var IDatabase[][][] Map of local/foreignUsed/foreignFree => server index => IDatabase array */
+       /** @var \Database[][][] Map of local/foreignUsed/foreignFree => server index => IDatabase array */
        private $mConns;
        /** @var float[] Map of (server index => weight) */
        private $mLoads;
@@ -73,8 +88,8 @@ class LoadBalancer implements ILoadBalancer {
        /** @var LoggerInterface */
        protected $perfLogger;
 
-       /** @var bool|IDatabase Database connection that caused a problem */
-       private $mErrorConnection;
+       /** @var \Database Database connection that caused a problem */
+       private $errorConnection;
        /** @var integer The generic (not query grouped) replica DB index (of $mServers) */
        private $mReadIndex;
        /** @var bool|DBMasterPos False if not set */
@@ -146,7 +161,6 @@ class LoadBalancer implements ILoadBalancer {
                ];
                $this->mLoads = [];
                $this->mWaitForPos = false;
-               $this->mErrorConnection = false;
                $this->mAllowLagged = false;
 
                if ( isset( $params['readOnlyReason'] ) && is_string( $params['readOnlyReason'] ) ) {
@@ -218,9 +232,9 @@ class LoadBalancer implements ILoadBalancer {
        private function getLoadMonitor() {
                if ( !isset( $this->loadMonitor ) ) {
                        $compat = [
-                               'LoadMonitor' => Wikimedia\Rdbms\LoadMonitor::class,
-                               'LoadMonitorNull' => Wikimedia\Rdbms\LoadMonitorNull::class,
-                               'LoadMonitorMySQL' => Wikimedia\Rdbms\LoadMonitorMySQL::class,
+                               'LoadMonitor' => LoadMonitor::class,
+                               'LoadMonitorNull' => LoadMonitorNull::class,
+                               'LoadMonitorMySQL' => LoadMonitorMySQL::class,
                        ];
 
                        $class = $this->loadMonitorConfig['class'];
@@ -722,17 +736,17 @@ class LoadBalancer implements ILoadBalancer {
                                $this->mConns['local'][$i][0] = $conn;
                        } else {
                                $this->connLogger->warning( "Failed to connect to database $i at '$serverName'." );
-                               $this->mErrorConnection = $conn;
+                               $this->errorConnection = $conn;
                                $conn = false;
                        }
                }
 
-               if ( $conn && !$conn->isOpen() ) {
+               if ( $conn instanceof IDatabase && !$conn->isOpen() ) {
                        // Connection was made but later unrecoverably lost for some reason.
                        // Do not return a handle that will just throw exceptions on use,
                        // but let the calling code (e.g. getReaderIndex) try another server.
                        // See DatabaseMyslBase::ping() for how this can happen.
-                       $this->mErrorConnection = $conn;
+                       $this->errorConnection = $conn;
                        $conn = false;
                }
 
@@ -751,7 +765,7 @@ class LoadBalancer implements ILoadBalancer {
         * it has been freed first with reuseConnection().
         *
         * On error, returns false, and the connection which caused the
-        * error will be available via $this->mErrorConnection.
+        * error will be available via $this->errorConnection.
         *
         * @note If disable() was called on this LoadBalancer, this method will throw a DBAccessError.
         *
@@ -783,7 +797,7 @@ class LoadBalancer implements ILoadBalancer {
                        if ( strlen( $dbName ) && !$conn->selectDB( $dbName ) ) {
                                $this->mLastError = "Error selecting database '$dbName' on server " .
                                        $conn->getServer() . " from client host {$this->host}";
-                               $this->mErrorConnection = $conn;
+                               $this->errorConnection = $conn;
                                $conn = false;
                        } else {
                                $conn->tablePrefix( $prefix );
@@ -804,7 +818,7 @@ class LoadBalancer implements ILoadBalancer {
                        $conn = $this->reallyOpenConnection( $server, $dbName );
                        if ( !$conn->isOpen() ) {
                                $this->connLogger->warning( __METHOD__ . ": connection error for $i/$domain" );
-                               $this->mErrorConnection = $conn;
+                               $this->errorConnection = $conn;
                                $conn = false;
                        } else {
                                $conn->tablePrefix( $prefix );
@@ -814,7 +828,7 @@ class LoadBalancer implements ILoadBalancer {
                }
 
                // Increment reference count
-               if ( $conn ) {
+               if ( $conn instanceof IDatabase ) {
                        $refCount = $conn->getLBInfo( 'foreignPoolRefCount' );
                        $conn->setLBInfo( 'foreignPoolRefCount', $refCount + 1 );
                }
@@ -912,22 +926,13 @@ class LoadBalancer implements ILoadBalancer {
         * @throws DBConnectionError
         */
        private function reportConnectionError() {
-               $conn = $this->mErrorConnection; // the connection which caused the error
+               $conn = $this->errorConnection; // the connection which caused the error
                $context = [
                        'method' => __METHOD__,
                        'last_error' => $this->mLastError,
                ];
 
-               if ( !is_object( $conn ) ) {
-                       // No last connection, probably due to all servers being too busy
-                       $this->connLogger->error(
-                               "LB failure with no last connection. Connection error: {last_error}",
-                               $context
-                       );
-
-                       // If all servers were busy, mLastError will contain something sensible
-                       throw new DBConnectionError( null, $this->mLastError );
-               } else {
+               if ( $conn instanceof IDatabase ) {
                        $context['db_server'] = $conn->getServer();
                        $this->connLogger->warning(
                                "Connection error: {last_error} ({db_server})",
@@ -936,6 +941,15 @@ class LoadBalancer implements ILoadBalancer {
 
                        // throws DBConnectionError
                        $conn->reportConnectionError( "{$this->mLastError} ({$context['db_server']})" );
+               } else {
+                       // No last connection, probably due to all servers being too busy
+                       $this->connLogger->error(
+                               "LB failure with no last connection. Connection error: {last_error}",
+                               $context
+                       );
+
+                       // If all servers were busy, mLastError will contain something sensible
+                       throw new DBConnectionError( null, $this->mLastError );
                }
        }
 
@@ -1355,7 +1369,7 @@ class LoadBalancer implements ILoadBalancer {
 
        /**
         * @param string $domain Domain ID, or false for the current domain
-        * @param IDatabase|null DB master connectionl used to avoid loops [optional]
+        * @param IDatabase|null $conn DB master connectionl used to avoid loops [optional]
         * @return bool
         */
        private function masterRunningReadOnly( $domain, IDatabase $conn = null ) {
@@ -1591,3 +1605,5 @@ class LoadBalancer implements ILoadBalancer {
                $this->disable();
        }
 }
+
+class_alias( LoadBalancer::class, 'LoadBalancer' );
index 0a05202..b9fefda 100644 (file)
  * @ingroup Database
  */
 
+namespace Wikimedia\Rdbms;
+
+use IDatabase;
+use InvalidArgumentException;
+
 /**
  * Trivial LoadBalancer that always returns an injected connection handle
  */
@@ -72,3 +77,5 @@ class LoadBalancerSingle extends LoadBalancer {
                return $this->db;
        }
 }
+
+class_alias( 'Wikimedia\Rdbms\LoadBalancerSingle', 'LoadBalancerSingle' );
index 6665336..4382910 100644 (file)
@@ -544,7 +544,8 @@ class LogEventsList extends ContextSource {
         * @param string $user The user who made the log entries
         * @param array $param Associative Array with the following additional options:
         * - lim Integer Limit of items to show, default is 50
-        * - conds Array Extra conditions for the query (e.g. "log_action != 'revision'")
+        * - conds Array Extra conditions for the query
+        *   (e.g. 'log_action != ' . $dbr->addQuotes( 'revision' ))
         * - showIfEmpty boolean Set to false if you don't want any output in case the loglist is empty
         *   if set to true (default), "No matching items in log" is displayed if loglist is empty
         * - msgKey Array If you want a nice box with a message, set this to the key of the message.
index 5fd3348..7e8c2ba 100644 (file)
@@ -24,6 +24,7 @@
 use \MediaWiki\MediaWikiServices;
 use \Wikimedia\WaitConditionLoop;
 use \Wikimedia\Rdbms\TransactionProfiler;
+use Wikimedia\Rdbms\LoadBalancer;
 
 /**
  * Class to store objects in the database
index 34ff63c..2787c1b 100644 (file)
@@ -1171,7 +1171,10 @@ class Article implements Page {
                $loggedIn = $this->getContext()->getUser()->isLoggedIn();
                if ( $loggedIn || $cache->get( $key ) ) {
                        $logTypes = [ 'delete', 'move' ];
-                       $conds = [ "log_action != 'revision'" ];
+
+                       $dbr = wfGetDB( DB_REPLICA );
+
+                       $conds = [ 'log_action != ' . $dbr->addQuotes( 'revision' ) ];
                        // Give extensions a chance to hide their (unrelated) log entries
                        Hooks::run( 'Article::MissingArticleConditions', [ &$conds, $logTypes ] );
                        LogEventsList::showLogExtract(
index c75cfdd..53d7e55 100644 (file)
@@ -585,6 +585,8 @@ EOT
                } else {
                        # Image does not exist
                        if ( !$this->getId() ) {
+                               $dbr = wfGetDB( DB_REPLICA );
+
                                # No article exists either
                                # Show deletion log to be consistent with normal articles
                                LogEventsList::showLogExtract(
@@ -593,7 +595,7 @@ EOT
                                        $this->getTitle()->getPrefixedText(),
                                        '',
                                        [ 'lim' => 10,
-                                               'conds' => [ "log_action != 'revision'" ],
+                                               'conds' => [ 'log_action != ' . $dbr->addQuotes( 'revision' ) ],
                                                'showIfEmpty' => false,
                                                'msgKey' => [ 'moveddeleted-notice' ]
                                        ]
index 1d55c98..86aa06a 100644 (file)
@@ -2483,7 +2483,7 @@ class Parser {
         *
         * @private
         *
-        * @param int $index
+        * @param string $index Magic variable identifier as mapped in MagicWord::$mVariableIDs
         * @param bool|PPFrame $frame
         *
         * @throws MWException
index 71e5939..6d2bc0d 100644 (file)
@@ -461,13 +461,28 @@ abstract class ResourceLoaderModule implements LoggerAwareInterface {
         * @param array $localFileRefs List of files
         */
        protected function saveFileDependencies( ResourceLoaderContext $context, $localFileRefs ) {
-               // Normalise array
-               $localFileRefs = array_values( array_unique( $localFileRefs ) );
-               sort( $localFileRefs );
 
                try {
+                       // Related bugs and performance considerations:
+                       // 1. Don't needlessly change the database value with the same list in a
+                       //    different order or with duplicates.
+                       // 2. Use relative paths to avoid ghost entries when $IP changes. (T111481)
+                       // 3. Don't needlessly replace the database with the same value
+                       //    just because $IP changed (e.g. when upgrading a wiki).
+                       // 4. Don't create an endless replace loop on every request for this
+                       //    module when '../' is used anywhere. Even though both are expanded
+                       //    (one expanded by getFileDependencies from the DB, the other is
+                       //    still raw as originally read by RL), the latter has not
+                       //    been normalized yet.
+
+                       // Normalise
+                       $localFileRefs = array_values( array_unique( $localFileRefs ) );
+                       sort( $localFileRefs );
+                       $localPaths = self::getRelativePaths( $localFileRefs );
+
+                       $storedPaths = self::getRelativePaths( $this->getFileDependencies( $context ) );
                        // If the list has been modified since last time we cached it, update the cache
-                       if ( $localFileRefs !== $this->getFileDependencies( $context ) ) {
+                       if ( $localPaths !== $storedPaths ) {
                                $vary = $context->getSkin() . '|' . $context->getLanguage();
                                $cache = ObjectCache::getLocalClusterInstance();
                                $key = $cache->makeKey( __METHOD__, $this->getName(), $vary );
@@ -476,8 +491,7 @@ abstract class ResourceLoaderModule implements LoggerAwareInterface {
                                        return; // T124649; avoid write slams
                                }
 
-                               // Use relative paths to avoid ghost entries when $IP changes (T111481)
-                               $deps = FormatJson::encode( self::getRelativePaths( $localFileRefs ) );
+                               $deps = FormatJson::encode( $localPaths );
                                $dbw = wfGetDB( DB_MASTER );
                                $dbw->upsert( 'module_deps',
                                        [
index 14d6e05..e8574f4 100644 (file)
@@ -357,6 +357,11 @@ class ResourceLoaderWikiModule extends ResourceLoaderModule {
                        }
                }
 
+               if ( !$wikiModules ) {
+                       // Nothing to preload
+                       return;
+               }
+
                $pageNames = array_keys( $allPages );
                sort( $pageNames );
                $hash = sha1( implode( '|', $pageNames ) );
index e5247f2..e106f37 100644 (file)
@@ -1,5 +1,7 @@
 <?php
 
+use Wikimedia\Rdbms\LoadBalancer;
+
 /**
  * Represents the site configuration of a wiki.
  * Holds a list of sites (ie SiteList), stored in the database.
index c5a1f27..f4a4818 100644 (file)
@@ -281,10 +281,12 @@ class SpecialUpload extends SpecialPage {
                $desiredTitleObj = Title::makeTitleSafe( NS_FILE, $this->mDesiredDestName );
                $delNotice = ''; // empty by default
                if ( $desiredTitleObj instanceof Title && !$desiredTitleObj->exists() ) {
+                       $dbr = wfGetDB( DB_REPLICA );
+
                        LogEventsList::showLogExtract( $delNotice, [ 'delete', 'move' ],
                                $desiredTitleObj,
                                '', [ 'lim' => 10,
-                                       'conds' => [ "log_action != 'revision'" ],
+                                       'conds' => [ 'log_action != ' . $dbr->addQuotes( 'revision' ) ],
                                        'showIfEmpty' => false,
                                        'msgKey' => [ 'upload-recreate-warning' ] ]
                        );
index d0a2f92..d9c2a58 100644 (file)
@@ -1862,7 +1862,7 @@ class User implements IDBAccessObject {
         */
        public function isPingLimitable() {
                global $wgRateLimitsExcludedIPs;
-               if ( in_array( $this->getRequest()->getIP(), $wgRateLimitsExcludedIPs ) ) {
+               if ( IP::isInRanges( $this->getRequest()->getIP(), $wgRateLimitsExcludedIPs ) ) {
                        // No other good way currently to disable rate limits
                        // for specific IPs. :P
                        // But this is a crappy hack and should die.
@@ -3770,6 +3770,42 @@ class User implements IDBAccessObject {
                // user_talk page; it's cleared one page view later in WikiPage::doViewUpdates().
        }
 
+       /**
+        * Compute experienced level based on edit count and registration date.
+        *
+        * @return string 'newcomer', 'learner', or 'experienced'
+        */
+       public function getExperienceLevel() {
+               global $wgLearnerEdits,
+                          $wgExperiencedUserEdits,
+                          $wgLearnerMemberSince,
+                          $wgExperiencedUserMemberSince;
+
+               if ( $this->isAnon() ) {
+                       return false;
+               }
+
+               $editCount = $this->getEditCount();
+               $registration = $this->getRegistration();
+               $now = time();
+               $learnerRegistration = wfTimestamp( TS_MW, $now - $wgLearnerMemberSince * 86400 );
+               $experiencedRegistration = wfTimestamp( TS_MW, $now - $wgExperiencedUserMemberSince * 86400 );
+
+               if (
+                       $editCount < $wgLearnerEdits ||
+                       $registration > $learnerRegistration
+               ) {
+                       return 'newcomer';
+               } elseif (
+                       $editCount > $wgExperiencedUserEdits &&
+                       $registration <= $experiencedRegistration
+               ) {
+                       return 'experienced';
+               } else {
+                       return 'learner';
+               }
+       }
+
        /**
         * Set a cookie on the user's client. Wrapper for
         * WebResponse::setCookie
index 0bfd4a2..55e228a 100644 (file)
@@ -291,15 +291,6 @@ EOD;
                foreach ( glob( $this->basepath . '/*.php' ) as $file ) {
                        $this->readFile( $file );
                }
-
-               // Legacy aliases (1.28)
-               $this->forceClassPath( 'DatabaseBase',
-                       $this->basepath . '/includes/libs/rdbms/database/Database.php' );
-               // Legacy aliases (1.29)
-               $this->forceClassPath( 'Blob',
-                       $this->basepath . '/includes/libs/rdbms/encasing/Blob.php' );
-               $this->forceClassPath( 'Field',
-                       $this->basepath . '/includes/libs/rdbms/field/Field.php' );
        }
 }
 
@@ -328,6 +319,11 @@ class ClassCollector {
         */
        protected $tokens;
 
+       /**
+        * @var array Class alias with target/name fields
+        */
+       protected $alias;
+
        /**
         * @var string $code PHP code (including <?php) to detect class names from
         * @return array List of FQCN detected within the tokens
@@ -336,6 +332,7 @@ class ClassCollector {
                $this->namespace = '';
                $this->classes = [];
                $this->startToken = null;
+               $this->alias = null;
                $this->tokens = [];
 
                foreach ( token_get_all( $code ) as $token ) {
@@ -358,6 +355,8 @@ class ClassCollector {
                if ( is_string( $token ) ) {
                        return;
                }
+               // Note: When changing class name discovery logic,
+               // AutoLoaderTest.php may also need to be updated.
                switch ( $token[0] ) {
                case T_NAMESPACE:
                case T_CLASS:
@@ -365,6 +364,12 @@ class ClassCollector {
                case T_TRAIT:
                case T_DOUBLE_COLON:
                        $this->startToken = $token;
+                       break;
+               case T_STRING:
+                       if ( $token[1] === 'class_alias' ) {
+                               $this->startToken = $token;
+                               $this->alias = [];
+                       }
                }
        }
 
@@ -388,6 +393,49 @@ class ClassCollector {
                        }
                        break;
 
+               case T_STRING:
+                       if ( $this->alias !== null ) {
+                               // Flow 1 - Two string literals:
+                               // - T_STRING  class_alias
+                               // - '('
+                               // - T_CONSTANT_ENCAPSED_STRING 'TargetClass'
+                               // - ','
+                               // - T_WHITESPACE
+                               // - T_CONSTANT_ENCAPSED_STRING 'AliasName'
+                               // - ')'
+                               // Flow 2 - Use of ::class syntax for first parameter
+                               // - T_STRING  class_alias
+                               // - '('
+                               // - T_STRING TargetClass
+                               // - T_DOUBLE_COLON ::
+                               // - T_CLASS class
+                               // - ','
+                               // - T_WHITESPACE
+                               // - T_CONSTANT_ENCAPSED_STRING 'AliasName'
+                               // - ')'
+                               if ( $token === '(' ) {
+                                       // Start of a function call to class_alias()
+                                       $this->alias = [ 'target' => false, 'name' => false ];
+                               } elseif ( $token === ',' ) {
+                                       // Record that we're past the first parameter
+                                       if ( $this->alias['target'] === false ) {
+                                               $this->alias['target'] = true;
+                                       }
+                               } elseif ( is_array( $token ) && $token[0] === T_CONSTANT_ENCAPSED_STRING ) {
+                                       if ( $this->alias['target'] === true ) {
+                                               // We already saw a first argument, this must be the second.
+                                               // Strip quotes from the string literal.
+                                               $this->alias['name'] = substr( $token[1], 1, -1 );
+                                       }
+                               } elseif ( $token === ')' ) {
+                                       // End of function call
+                                       $this->classes[] = $this->alias['name'];
+                                       $this->alias = null;
+                                       $this->startToken = null;
+                               }
+                       }
+                       break;
+
                case T_CLASS:
                case T_INTERFACE:
                case T_TRAIT:
index 1451843..b8d415f 100644 (file)
@@ -79,6 +79,8 @@ class SearchFormWidget {
         * @return string HTML
         */
        protected function shortDialogHtml( $profile, $term, $numResults, $totalResults, $offset ) {
+               $html = '';
+
                $searchWidget = new SearchInputWidget( [
                        'id' => 'searchText',
                        'name' => 'search',
@@ -96,11 +98,7 @@ class SearchFormWidget {
                        'align' => 'top',
                ] );
 
-               $html =
-                       Html::hidden( 'title', $this->specialSearch->getPageTitle()->getPrefixedText() ) .
-                       Html::hidden( 'profile', $profile ) .
-                       Html::hidden( 'fulltext', '1' ) .
-                       $layout;
+               $html .= $layout;
 
                if ( $totalResults > 0 && $offset < $totalResults ) {
                        $html .= Xml::tags(
@@ -113,6 +111,11 @@ class SearchFormWidget {
                        );
                }
 
+               $html .=
+                       Html::hidden( 'title', $this->specialSearch->getPageTitle()->getPrefixedText() ) .
+                       Html::hidden( 'profile', $profile ) .
+                       Html::hidden( 'fulltext', '1' );
+
                return $html;
        }
 
index 20a4975..9bcb004 100644 (file)
        "tog-diffonly": "لا تعرض محتوى الصفحة أسفل الفرق",
        "tog-showhiddencats": "أظهر التصنيفات المخفية",
        "tog-norollbackdiff": "لا تظهر الفروق بعد إجراء التراجع",
-       "tog-useeditwarning": "حذّرني عندما أغادر تحرير صفحة فيها تغييرات لم أحفظها\n\nنبهني عند مغادرة صفحة تحرير  بها تعديلات لم أحفظها",
+       "tog-useeditwarning": "حذّرني عندما أغادر تحرير صفحة فيها تغييرات لم أحفظها",
        "tog-prefershttps": "دائما استخدم اتصالا آمنا عند تسجيل الدخول",
        "underline-always": "دائما",
        "underline-never": "أبدا",
        "anontalk": "نقاش",
        "navigation": "تصفح",
        "and": "&#32;و",
-       "qbfind": "وجد",
+       "qbfind": "جد",
        "qbbrowse": "تصفح",
        "qbedit": "عدل",
        "qbpageoptions": "هذه الصفحة",
        "history": "تاريخ الصفحة",
        "history_short": "التاريخ",
        "history_small": "تاريخ",
-       "updatedmarker": "عدلت منذ زيارتي الأخيرة\n\nتحديثها كان منذ زيارتي الأخيرة",
+       "updatedmarker": "عدلت منذ زيارتي الأخيرة",
        "printableversion": "نسخة للطباعة",
        "permalink": "رابط دائم",
        "print": "اطبع",
        "tool-link-userrights": "تغيير مجموعات {{GENDER:$1|المستخدم|المستخدمة}}",
        "tool-link-userrights-readonly": "عرض مجموعات {{GENDER:$1|المستخدم|المستخدمة}}",
        "tool-link-emailuser": "أرسل رسالة {{GENDER:$1|لهذا المستخدم|لهذه المستخدمة}}",
-       "userpage": "طالع صفحة المستخدم\n\nعرض صفحة المستخدم",
-       "projectpage": "طالع صفحة المشروع\n\nعرض صفحة المشروع",
-       "imagepage": "طالع صفحة الملف\n\nعرض صفحة المشروع",
-       "mediawikipage": "طالع صفحة الرسالة\n\nعرض صفحة الرسالة",
+       "userpage": "طالع صفحة المستخدم",
+       "projectpage": "طالع صفحة المشروع",
+       "imagepage": "طالع صفحة الملف",
+       "mediawikipage": "طالع صفحة الرسالة",
        "templatepage": "طالع صفحة القالب",
-       "viewhelppage": "طالع صفحة المساعدة\n\nعرض صفحة المساعدة",
-       "categorypage": "طالع صفحة التصنيف\n\nعرض صفحة التصنيف",
+       "viewhelppage": "طالع صفحة المساعدة",
+       "categorypage": "طالع صفحة التصنيف",
        "viewtalkpage": "اعرض النقاش",
        "otherlanguages": "بلغات أخرى",
        "redirectedfrom": "(بالتحويل من $1)",
        "restorelink": "{{PLURAL:$1|$1 تعديل محذوف|تعديلا واحدا محذوفا|تعديلين محذوفين|$1 تعديلات محذوفة|$1 تعديلا محذوفا|$1 تعديل محذوف}}",
        "feedlinks": "التلقيمة:",
        "feed-invalid": "نوع التلقيمة غير صحيح.",
-       "feed-unavailable": "التلقيمات غير متوفرة\n\nخلاصات المشاركة غير متوفرة",
+       "feed-unavailable": "التلقيمات غير متوفرة",
        "site-rss-feed": "تلقيمة آر إس إس $1",
        "site-atom-feed": "تلقيمة أتوم $1",
        "page-rss-feed": "تلقيمة آر إس إس \"$1\"",
        "databaseerror-error": "خطأ: $1",
        "transaction-duration-limit-exceeded": "لتفادي إنشاء تأخير نسخ عالي، هذا الفعل تم إنهاؤه لأن فترة الكتابة ($1) تجاوزت حد $2 ثانية.\nلو أنك تغير عناصر عديدة في نفس الوقت، حاول تجربة عمليا عديدة أصغر بدلا من ذلك.",
        "laggedslavemode": "'''تحذير:''' الصفحة قد لا تحتوي على أحدث التحديثات.",
-       "readonly": "قاعدة البيانات مقفلة\n\nقاعدة البيانات مغلقة",
+       "readonly": "قاعدة البيانات مقفلة",
        "enterlockreason": "أدخل سببا للقفل ذاكرا تقديرا لوقت إزالة الغلق",
        "readonlytext": "قاعدة البيانات مقفلة حاليا أمام المدخلات الجديدة و التعديلات الأخرى. السبب غالبا ما يكون الصيانة، و ستعود قاعدة البيانات للعمل الطبيعي قريبا.\n\nإداري النظام الذي أغلق قاعدة البيانات أعطى التفسير التالي: $1",
        "missing-article": "لم تجد قاعدة البيانات نصّ صفحة كان يجب أن يوجد، الصفحة هي \"$1\" $2.\n\nعادة ما يحدث هذا عند اتباع فرق قديم أو رابط تأريخ صفحة محذوفة.\n\nإذا لم تكن هذه هي الحال فمن المحتمل أنك قد وقعت على علّة في البرمجية.\nمن فضلك أبلغ أحد [[Special:ListUsers/sysop|الإداريين]]، و أعطه مسار هذه الصفحة.",
        "nocookiesnew": "تم إنشاء حساب المستخدم، ولكنك لست مسجل الدخول بعد.\nيستخدم {{SITENAME}} كوكيز لتسجيل الدخول.\nلديك الكوكيز معطلة.\nمن فضلك فعلها، ثم سجل الدخول باسم المستخدم وكلمة السر الجديدين.",
        "nocookieslogin": "يستخدم {{SITENAME}} الكوكيز لتسجيل الدخول.\nالكوكيز معطلة لديك.\nمن فضلك فعلها ثم حاول مرة أخرى.",
        "nocookiesfornew": "لم يتم إنشاء حساب المستخدم، لأننا لم نستطع تأكيد مصدره. \nتأكد من أن ملفات تعريف الارتباط (الكوكيز) مفعلة عندك، ثم أعد تحميل الصفحة وحاول مرة أخرى.",
-       "createacct-loginerror": "الحساب تم إنشاؤه تلقائيا لكن لم يمكن تسجيل دخولك تلقائيا. من فضلك اذهب إلى [[Special:UserLogin|تسجيل الدخول اليدوي]].\n\n\nتم إنشاء الحساب بنجاح ولكن لا يمكنك أن تقوم بتسجيل الدخول تلقائيا. فتوجه إلى [[Special:UserLogin|تسجيل الدخول اليدوي]].",
+       "createacct-loginerror": "الحساب تم إنشاؤه تلقائيا لكن لم يمكن تسجيل دخولك تلقائيا. من فضلك اذهب إلى [[Special:UserLogin|تسجيل الدخول اليدوي]].",
        "noname": "لم تحدد اسم مستخدم صحيح.",
        "loginsuccesstitle": "تم الدخول",
        "loginsuccess": "'''لقد سجلت الدخول ل{{SITENAME}} باسم \"$1\".'''",
        "wrongpasswordempty": "كلمة السر المدخلة كانت فارغة.\nمن فضلك حاول مرة أخرى.",
        "passwordtooshort": "يجب أن تتكون كلمة السر على الأقل من {{PLURAL:$1|حرف واحد|حرفين|$1 حروف|$1 حرفا|$1 حرف}}.",
        "passwordtoolong": "كلمات السر لا يجب أن تكون أطول من  {{PLURAL:$1|1 حرف|$1 حروف}}.",
-       "passwordtoopopular": "كلمات المرور الشائعة لا يمكن استخدامها. برجاء اختيار كلمة مرور أكثر فرادة.\n\nكلمات السر المعروفة لا يمكن استخدامها عادة. يرجى اختيار كلمة مرور فريدة من نوعها.",
+       "passwordtoopopular": "كلمات المرور الشائعة لا يمكن استخدامها. برجاء اختيار كلمة مرور أكثر فرادة.",
        "password-name-match": "يجب أن تكون كلمة المرور مختلفة عن اسم المستخدم.",
        "password-login-forbidden": "تم منع استخدام اسم المستخدم هذا وكلمة السر.",
        "mailmypassword": "أعد تعيين كلمة السر",
        "rcfilters-invalid-filter": "مرشح غير صحيح",
        "rcfilters-empty-filter": "لا مرشحات فعالة. كل المساهمات معروضة.",
        "rcfilters-filterlist-title": "مرشحات",
+       "rcfilters-highlightbutton-title": "التعليم على النتائج",
+       "rcfilters-highlightmenu-title": "اختر اللغة",
        "rcfilters-filterlist-noresults": "لم يتم العثور على مرشحات",
        "rcfilters-filtergroup-registration": "تسجيل المستخدم",
        "rcfilters-filter-registered-label": "مسجل",
        "editcomment": "ملخص التعديل كان:<em>$1</em>.",
        "revertpage": "استرجع تعديلات [[Special:Contributions/$2|$2]] ([[User talk:$2|نقاش]]) حتى آخر مراجعة ل[[User:$1|$1]]",
        "revertpage-nouser": "استرجع تعديلات مستخدم مخفي حتى آخر مراجعة ل{{GENDER:$1|[[User:$1|$1]]}}",
-       "rollback-success": "استرجع تعديلات $1؛\nاسترجع حتى آخر نسخة بواسطة $2.",
+       "rollback-success": "استرجع تعديلات {{GENDER:$3|$1}}؛\nاسترجع حتى آخر نسخة بواسطة {{GENDER:$4|$2}}.",
        "rollback-success-notify": "تم استرجاع التعديلات بواسطة $1;\nتم التغيير إلى آخر مراجعة بواسطة $2. [$3 عرض التغييرات]",
        "sessionfailure-title": "فشل في الجلسة",
        "sessionfailure": "يبدو أنه هناك مشكلة في جلسة الدخول الخاصة بك؛\nلذلك فقد ألغيت هذه العملية كإجراء احترازي ضد الاختراق.\nمن فضلك اضغط على مفتاح \"رجوع\" لتحميل الصفحة التي جئت منها، ثم حاول مرة أخرى.",
index 6a9ed15..44b0f68 100644 (file)
@@ -7,7 +7,8 @@
                        "Lin linao",
                        "Poquil",
                        "Remember the dot",
-                       "아라"
+                       "아라",
+                       "Angel sm"
                ]
        },
        "tog-underline": "Miñcewirilpe lasun",
        "disclaimers": "Tukuldungun ñi pin ley",
        "disclaimerpage": "Project:Katrütuwün ñi llowdüngun",
        "edithelp": "Kellun kümeelkünuam",
-       "mainpage": "Ñidol Wülngiñ",
+       "mainpage": "Ñizol Wvbgiñ",
        "mainpage-description": "Ñidol Wülngiñ",
        "portal": "Lofche ñi wülngiñ",
        "portal-url": "Project:Lofche ñi wülngiñ",
index 60d1339..fa43219 100644 (file)
        "protectedpages-reason": "نَدَن‌لیگی",
        "protectedpages-unknown-timestamp": "بیلینمه‌ین",
        "protectedpages-unknown-performer": "بیلینمه‌ین ایستیفاده‌چی",
-       "protectedtitles": "Ù\85حاÙ\81ظÙ\87â\80\8cÙ\84Û\8c Ø¨Ø§Ø´â\80\8cÙ\84Û\8cÙ\82â\80\8cلار",
+       "protectedtitles": "Ù\82Ù\88Ù\92رÙ\88Ù\86اÙ\86 Ø¨Ø§Ø´Ù\84Û\8cÙ\82لار",
        "protectedtitles-summary": "بۇ صحیفه، ایندیکی یارانماق‌دان قوْرونان باشلیقلاری لیست ائدیر. ایندیکی قوْرونان موْجود اوْلان صحیفه‌لرین لیستینی گؤرمک اۆچون، [[{{#special:ProtectedPages}}|{{int:protectedpages}}]]-ه باخین.",
        "protectedtitlesempty": "حال-حاضردا، بو پارامئترلری قورونان هئچ بیر موضوع یوخ‌دور.",
        "listusers": "ایشلدن لیستی",
index 2e71999..0f4b6d7 100644 (file)
        "rev-deleted-text-unhide": "Гэтая вэрсія старонкі была <strong>выдаленая</strong>.\nПадрабязнасьці могуць быць знойдзеныя ў [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} журнале выдаленьняў].\nВы можаце [$1 праглядзець гэтую вэрсію], калі жадаеце.",
        "rev-suppressed-text-unhide": "Гэтая вэрсія старонкі была <strong>схаваная</strong>.\nПадрабязнасьці могуць быць знойдзеныя ў [{{fullurl:{{#Special:Log}}/suppress|page={{FULLPAGENAMEE}}}} журнале хаваньняў].\nВы можаце [$1 праглядзець гэтую вэрсію], калі жадаеце.",
        "rev-deleted-text-view": "Гэтая вэрсія старонкі была <strong>выдаленая</strong>.\nВы можаце праглядзець яе; падрабязнасьці могуць быць знойдзеныя ў [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} журнале выдаленьняў].",
-       "rev-suppressed-text-view": "Гэтая вэрсія старонкі была '''схаваная'''.\nВы можаце яе праглядзець; падрабязнасьці могуць быць знойдзеныя ў  [{{fullurl:{{#Special:Log}}/suppress|page={{FULLPAGENAMEE}}}} журнале хаваньняў].",
-       "rev-deleted-no-diff": "Вы ня можаце праглядаць гэтую розьніцу паміж вэрсіямі, таму што адна з вэрсіяў была '''выдаленая'''.\nМагчыма, падрабязнасьці могуць быць знойдзеныя ў [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} журнале выдаленьняў].",
-       "rev-suppressed-no-diff": "Вы ня можаце праглядзець гэтую розьніцу, таму што адна з вэрсіяў была '''выдаленая'''.",
+       "rev-suppressed-text-view": "Гэтая вэрсія старонкі была <strong>схаваная</strong>.\nВы можаце яе праглядзець; падрабязнасьці могуць быць знойдзеныя ў [{{fullurl:{{#Special:Log}}/suppress|page={{FULLPAGENAMEE}}}} журнале хаваньняў].",
+       "rev-deleted-no-diff": "Вы ня можаце праглядаць гэтую розьніцу паміж вэрсіямі, таму што адна з вэрсіяў была <strong>выдаленая</strong>.\nПадрабязнасьці могуць быць знойдзеныя ў [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} журнале выдаленьняў].",
+       "rev-suppressed-no-diff": "Вы ня можаце праглядзець гэтую розьніцу, таму што адна з вэрсіяў была <strong>выдаленая</strong>.",
        "rev-deleted-unhide-diff": "Адна з вэрсіяў гэтай старонкі была '''выдаленая'''.\nПадрабязнасьці могуць быць знойдзеныя ў [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} журнале выдаленьняў].\nВы можаце праглядзець [$1 розьніцу паміж вэрсіямі], калі жадаеце.",
        "rev-suppressed-unhide-diff": "Адна з вэрсіяў гэтага параўнаньня была '''схаваная'''.\nПадрабязнасьці могуць быць знойдзеныя ў [{{fullurl:{{#Special:Log}}/suppress|page={{FULLPAGENAMEE}}}} журнале хаваньняў].\nВы можаце [$1 паглядзець гэту розьніцу], калі жадаеце.",
        "rev-deleted-diff-view": "Адна з вэрсіяў гэтага параўнаньня была '''выдаленая'''.\nВы можаце праглядзець гэтую розьніцу паміж вэрсіямі. Падрабязнасьці могуць быць знойдзеныя ў [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} журнале выдаленьняў].",
        "rcfilters-invalid-filter": "Няслушны фільтар",
        "rcfilters-empty-filter": "Няма актыўных фільтраў. Паказаны ўвесь унёсак.",
        "rcfilters-filterlist-title": "Фільтры",
+       "rcfilters-highlightbutton-title": "Вылучыць вынікі",
        "rcfilters-filterlist-noresults": "Фільтры ня знойдзеныя",
        "rcfilters-filtergroup-registration": "Рэгістрацыя ўдзельнікаў",
        "rcfilters-filter-registered-label": "Зарэгістраваныя",
        "editcomment": "Кароткае апісаньне зьменаў было: <em>$1</em>.",
        "revertpage": "Рэдагаваньні [[Special:Contributions/$2|$2]] ([[User talk:$2|гутаркі]]) скасаваныя да папярэдняй вэрсіі [[User:$1|$1]]",
        "revertpage-nouser": "Рэдагаваньні схаванага ўдзельніка скасаваныя да папярэдняй вэрсіі {{GENDER:$1|[[User:$1|$1]]}}",
-       "rollback-success": "Адмененыя рэдагаваньні $1;\nвернутая папярэдняя вэрсія $2.",
+       "rollback-success": "Адмененыя рэдагаваньні {{GENDER:$3|$1}};\nвернутая папярэдняя вэрсія {{GENDER:$4|$2}}.",
        "rollback-success-notify": "Адмененыя праўкі $1;\nвернутая папярэдняя вэрсія $2. [$3 Паказаць зьмены]",
        "sessionfailure-title": "Памылка сэсіі",
        "sessionfailure": "Магчыма ўзьніклі праблемы ў Вашым цяперашнім сэансе працы;\nгэта дзеяньне было скасавана для прадухіленьня перахопу сэансу.\nКалі ласка, націсьніце «назад» і перазагрузіце старонку, зь якой Вы прыйшлі, і паспрабуйце ізноў.",
        "authmanager-authn-no-local-user": "Пададзеныя ўліковыя зьвесткі не зьвязаныя зь ніводным удзельнікам гэтай вікі.",
        "authmanager-authn-autocreate-failed": "Аўтаматычнае стварэньне лякальнага рахунку не атрымалася: $1",
        "authmanager-change-not-supported": "Пададзеныя ўліковыя зьвесткі ня могуць быць зьмененыя, бо яны ня будуць выкарыстаныя.",
+       "authmanager-create-disabled": "Стварэньне рахункаў адключанае.",
        "authmanager-realname-label": "Сапраўднае імя",
        "authmanager-provider-temporarypassword": "Часовы пароль",
        "changecredentials": "Зьмена ўліковых зьвестак",
index c378228..5abee6a 100644 (file)
        "activeusers-intro": "Гэта пералік удзельнікаў, якія нешта рабілі за апошнія $1 {{PLURAL:$1|дзень|дзён}}.",
        "activeusers-count": "$1 {{PLURAL:$1|дзеянне|дзеянні|дзеянняў}} за апошні{{PLURAL:$3| дзень|я $3 дні|я $3 дзён}}",
        "activeusers-from": "Паказ, пачынаючы з:",
-       "activeusers-groups": "Паказаць удзельнікаў, якія належаць да групаў:",
+       "activeusers-groups": "Паказаць удзельнікаў, якія належаць да груп:",
        "activeusers-noresult": "Няма такіх удзельнікаў.",
        "activeusers-submit": "Паказаць актыўных удзельнікаў",
        "listgrouprights": "Дазволы для груп удзельнікаў",
index add760a..df6da1a 100644 (file)
        "continue-editing": "Продължаване към полето за редактиране",
        "previewconflict": "Този предварителен преглед отразява текста в горната текстова кутия така, както би се показал, ако съхраните.",
        "session_fail_preview": "За съжаление редакцията ви не успя да бъде обработена поради загуба на данните за текущата сесия.\n\nМоже би сте излезли от системата. <strong>Моля, уверете се, че сте влезли в профила си и опитайте отново.</strong>\nАко все още не работи, опитайте да [[Special:UserLogout|излезете]] и да влезете отново, също така проверете дали браузърът ви позволява бисквитки от този сайт.",
-       "session_fail_preview_html": "'''За съжаление редакцията ви не беше записана поради изтичането на сесията ви.'''\n\n''Тъй като {{SITENAME}} приема обикновен HTML, предварителният преглед е скрит като предпазна мярка срещу атаки чрез Джаваскрипт.''\n\n'''Опитайте отново. Ако все още не сработва, пробвайте да [[Special:UserLogout|излезете]] и влезете отново.'''",
+       "session_fail_preview_html": "За съжаление редакцията ви не беше записана поради изтичането на сесията ви.\n\n<em>Тъй като {{SITENAME}} приема обикновен HTML, предварителният преглед е скрит като предпазна мярка срещу атаки чрез JavaScript.</em>\n\n<strong>Ако това е обикновен опит за редактиране, моля опитайте отново.</strong>\nАко все още не сработва, пробвайте да [[Special:UserLogout|излезете]] и влезете отново, и се уверете, че браузъра ви приема бисквитки от този сайт.",
        "token_suffix_mismatch": "'''Редакцията ви беше отхвърлена, защото браузърът ви е развалил пунктуационните знаци в редакционната отметка. Евентуалното съхранение би унищожило съдържанието на страницата. Понякога това се случва при използването на грешно работещи анонимни междинни сървъри.'''",
        "edit_form_incomplete": "'''Някои части от формуляра за редактиране не достигнаха до сървъра; проверете дали редакциите ви са непокътнати и опитайте отново.'''",
        "editing": "Редактиране на „$1“",
        "prefs-diffs": "Разлики",
        "prefs-help-prefershttps": "Това предпочитание ще бъде активирано при следващото влизане.",
        "userrights": "Управление на потребителските права",
-       "userrights-lookup-user": "УпÑ\80авлÑ\8fване Ð½Ð° Ð¿Ð¾Ñ\82Ñ\80ебиÑ\82елÑ\81киÑ\82е Ð³Ñ\80Ñ\83пи",
+       "userrights-lookup-user": "Ð\98збеÑ\80еÑ\82е Ð¿Ð¾Ñ\82Ñ\80ебиÑ\82ел",
        "userrights-user-editname": "Потребителско име:",
-       "editusergroup": "РедакÑ\82иÑ\80ане Ð½Ð° {{GENDER:$1|поÑ\82Ñ\80ебиÑ\82елÑ\81киÑ\82е}} групи",
+       "editusergroup": "Ð\97аÑ\80еждане Ð½Ð° Ð¿Ð¾Ñ\82Ñ\80ебиÑ\82елÑ\81киÑ\82е групи",
        "editinguser": "Промяна на потребителските права на {{GENDER:$1|потребител }} <strong>[[User:$1|$1]]</strong> $2",
-       "userrights-editusergroup": "Редактиране на потребителските групи",
+       "userrights-editusergroup": "Редактиране на {{GENDER:$1|потребителските}} групи",
        "userrights-viewusergroup": "Преглед на {{GENDER:$1|потребителските}} групи",
-       "saveusergroups": "Съхраняване на потребителските групи",
+       "saveusergroups": "Съхраняване на {{GENDER:$1|потребителските}} групи",
        "userrights-groupsmember": "Член на:",
        "userrights-groupsmember-auto": "Подразбиращ се член на:",
        "userrights-groups-help": "Може да променяте групите, в които е потребителят:\n* Поставена отметка означава, че потребителят е член на групата.\n* Поле без отметка означава, че потребителят не е член на групата.\n* Знакът * показва, че не можете да премахнете групата, след като е вече добавена (или обратно).",
        "right-hideuser": "Блокиране и скриване на потребителско име",
        "right-ipblock-exempt": "Пренебрегване на блокирания по IP blocks, автоматични блокирания и блокирани IP интервали",
        "right-unblockself": "Собствено отблокиране",
-       "right-protect": "пÑ\80оменÑ\8fне Ð½Ð° Ð½Ð¸Ð²Ð¾Ñ\82о Ð½Ð° Ð·Ð°Ñ\89иÑ\82а Ð¸ Ñ\80едакÑ\82иÑ\80ане Ð½Ð° Ð·Ð°Ñ\89иÑ\82ени страници",
+       "right-protect": "Ð\9fÑ\80оменÑ\8fне Ð½Ð° Ð½Ð¸Ð²Ð¾Ñ\82о Ð½Ð° Ð·Ð°Ñ\89иÑ\82а Ð¸ Ñ\80едакÑ\82иÑ\80ане Ð½Ð° ÐºÐ°Ñ\81кадно-заÑ\89иÑ\82ениÑ\82е страници",
        "right-editprotected": "Редактиране на страници защитени като „{{int:protect-level-sysop}}“",
        "right-editinterface": "Редактиране на потребителския интерфейс",
        "right-editusercssjs": "редактиране на CSS и JS файловете на други потребители",
        "action-deletelogentry": "изтриване на записи от дневника",
        "action-deletedhistory": "преглед на изтритата история на тази страница",
        "action-browsearchive": "търсене на изтрити страници",
-       "action-undelete": "вÑ\8aзÑ\81Ñ\82ановÑ\8fване Ð½Ð° Ñ\82ази Ñ\81Ñ\82Ñ\80аниÑ\86а",
-       "action-suppressrevision": "пÑ\80еглеждане Ð¸ Ð²Ñ\8aзÑ\81Ñ\82ановÑ\8fване Ð½Ð° Ñ\82ази Ñ\81кÑ\80иÑ\82а Ð²ÐµÑ\80Ñ\81иÑ\8f",
+       "action-undelete": "вÑ\8aзÑ\81Ñ\82ановÑ\8fване Ð½Ð° Ñ\81Ñ\82Ñ\80аниÑ\86и",
+       "action-suppressrevision": "пÑ\80еглеждане Ð¸ Ð²Ñ\8aзÑ\81Ñ\82ановÑ\8fване Ð½Ð° Ñ\81кÑ\80иÑ\82и Ð²ÐµÑ\80Ñ\81ии",
        "action-suppressionlog": "преглеждане на този поверителен дневник",
        "action-block": "блокиране на редакциите на този потребител",
        "action-protect": "променяне на нивото на защита на тази страница",
        "withoutinterwiki-summary": "Следните страници не препращат към версии на други езици:",
        "withoutinterwiki-legend": "Представка",
        "withoutinterwiki-submit": "Показване",
-       "fewestrevisions": "Страници с най-малко версии",
+       "fewestrevisions": "Страници с най-малко редакции",
        "nbytes": "$1 {{PLURAL:$1|байт|байта}}",
        "ncategories": "$1 {{PLURAL:$1|категория|категории}}",
        "ninterwikis": "$1 {{PLURAL:$1|междууики|междууикита}}",
        "nopagetext": "Посочената целева страница не съществува.",
        "pager-newer-n": "{{PLURAL:$1|по-нова 1|по-нови $1}}",
        "pager-older-n": "{{PLURAL:$1|по-стара 1|по-стари $1}}",
-       "suppress": "Премахване от публичния архив",
+       "suppress": "Подтискане",
        "querypage-disabled": "Тази специална страница е изключена, защото затруднява производителността на уикито.",
        "apihelp": "Помощ за API",
        "apihelp-no-such-module": "Модул \"$1\" не беше намерен.",
        "undeletedrevisions": "{{PLURAL:$1|Една версия беше възстановена|$1 версии бяха възстановени}}",
        "undeletedrevisions-files": "{{PLURAL:$1|Една версия|$1 версии}} и {{PLURAL:$1|един файл|$2 файла}} бяха възстановени",
        "undeletedfiles": "{{PLURAL:$1|Един файл беше възстановен|$1 файла бяха възстановени}}",
-       "cannotundelete": "Ð\92Ñ\8aзÑ\81Ñ\82ановÑ\8fванеÑ\82о Ð±ÐµÑ\88е Ð½ÐµÑ\83Ñ\81пеÑ\88но:\n$1",
+       "cannotundelete": "Ð\95дна Ð¸Ð»Ð¸ Ð¿Ð¾Ð²ÐµÑ\87е Ð¾Ð¿ÐµÑ\80аÑ\86ии Ð¿Ð¾ Ð²Ñ\8aзÑ\81Ñ\82ановÑ\8fване Ñ\81е Ð¿Ñ\80овалиÑ\85а:\n$1",
        "undeletedpage": "'''Страницата „$1“ беше възстановена.'''\n\nМожете да видите последните изтрити и възстановени страници в [[Special:Log/delete|дневника на изтриванията]].",
        "undelete-header": "Прегледайте [[Special:Log/delete|дневника на изтриванията]] за текущо изтритите страници.",
        "undelete-search-title": "Търсене на изтрити страници",
        "log-name-pagelang": "Дневник на езиковите промени",
        "default-skin-not-found-row-enabled": "* <code>$1</code> / $2 (включено)",
        "default-skin-not-found-row-disabled": "* <code>$1</code> / $2 (<strong>изключено</strong>)",
-       "mediastatistics": "Ð\9cедиÑ\8f Ñ\81Ñ\82аÑ\82иÑ\81Ñ\82ики",
+       "mediastatistics": "СÑ\82аÑ\82иÑ\81Ñ\82ика Ð·Ð° Ñ\84айлове",
        "mediastatistics-table-mimetype": "MIME тип",
        "mediastatistics-table-extensions": "Възможни разширения",
        "mediastatistics-table-count": "Брой файлове",
index e27727b..ddc5992 100644 (file)
        "search-interwiki-caption": "সহপ্রকল্পসমূহ",
        "search-interwiki-default": "$1 থেকে ফলাফলসমূহ:",
        "search-interwiki-more": "(আরও)",
+       "search-interwiki-more-results": "আরও ফলাফল",
        "search-relatedarticle": "সম্পর্কিত",
        "searchrelated": "সম্পর্কিত",
        "searchall": "সমস্ত",
        "youremail": "ইমেইল *",
        "username": "{{GENDER:$1|ব্যবহারকারী নাম}}:",
        "prefs-memberingroups": "{{PLURAL:$1|দলের|দলসমূহের}} {{GENDER:$2|সদস্য}}:",
+       "group-membership-link-with-expiry": "$1 ($2 পর্যন্ত)",
        "prefs-registration": "নিবন্ধনের সময়:",
        "yourrealname": "আসল নাম *",
        "yourlanguage": "ভাষা:",
        "editusergroup": "ব্যবহারকারী দল লোড করুন",
        "editinguser": "<strong>[[User:$1|$1]]</strong> $2 {{GENDER:$1|ব্যবহারকারীর}} ব্যবহারকারী অধিকার পরিবর্তন করছেন",
        "viewinguserrights": "<strong>[[User:$1|$1]]</strong> $2 {{GENDER:$1|ব্যবহারকারীর}} ব্যবহারকারী অধিকার দেখছেন",
-       "userrights-editusergroup": "ব্যবহারকারীর দল সম্পাদনা করো",
-       "userrights-viewusergroup": "ব্যবহারকারী দল দেখা",
+       "userrights-editusergroup": "{{GENDER:$1|ব্যবহারকারী}} দল সম্পাদনা করে",
+       "userrights-viewusergroup": "{{GENDER:$1|ব্যবহারকারী}} দল দেখা",
        "saveusergroups": "{{GENDER:$1|ব্যবহারকারীর}} দল সংরক্ষণ করো",
        "userrights-groupsmember": "সদস্য:",
        "userrights-groupsmember-auto": "শর্তহীন সদস্য",
-       "userrights-groups-help": "à¦\86পনি à¦\8fà¦\87 à¦¬à§\8dযবহারà¦\95ারà§\80র à¦¬à¦°à§\8dতমান à¦¦à¦² à¦ªà¦°à¦¿à¦¬à¦°à§\8dতন à¦\95রতà§\87 à¦ªà¦¾à¦°à¦¬à§\87ন:\n* à¦\9fিà¦\95 à¦\9aিহà§\8dন à¦¦à§\87à¦\93য়া à¦\98রà§\87র à¦\85রà§\8dথ à¦¬à§\8dযবহারà¦\95ারà§\80 à¦\8fà¦\96ন à¦\90 à¦¦à¦²à§\87র à¦\85নà§\8dতরà§\8dভà§\81à¦\95à§\8dত।\n* à¦\9fিà¦\95 à¦\9aিহà§\8dন à¦¬à¦¿à¦¹à§\80ন à¦\98রà§\87র à¦\85রà§\8dথ à¦¬à§\8dযবহারà¦\95ারà§\80 à¦\90 à¦¦à¦²à§\87র à¦\85নà§\8dতরà§\8dভà§\81à¦\95à§\8dত à¦¨à¦¨à¥¤\n* à¦\8fà¦\95à¦\9fি à¦¤à¦¾à¦°à¦\95া à¦\9aিহà§\8dন (*) à¦¦à§\8dবারা à¦¬à§\8bà¦\9dানà§\8b à¦¹à¦\9aà§\8dà¦\9bà§\87 à¦\8fà¦\87 à¦¦à¦²à§\87র à¦\85নà§\8dতরà§\8dভà§\81à¦\95à§\8dতির à¦ªà¦° à¦\86পনি à¦\86র à¦¤à¦¾ à¦¬à¦¾à¦¤à¦¿à¦² à¦\95রতে পারবেন না।",
+       "userrights-groups-help": "à¦\86পনি à¦\8fà¦\87 à¦¬à§\8dযবহারà¦\95ারà§\80র à¦¬à¦°à§\8dতমান à¦¦à¦² à¦ªà¦°à¦¿à¦¬à¦°à§\8dতন à¦\95রতà§\87 à¦ªà¦¾à¦°à¦¬à§\87ন:\n* à¦\9fিà¦\95 à¦\9aিহà§\8dন à¦¦à§\87à¦\93য়া à¦\98রà§\87র à¦\85রà§\8dথ à¦¬à§\8dযবহারà¦\95ারà§\80 à¦\90 à¦¦à¦²à§\87র à¦\85নà§\8dতরà§\8dভà§\81à¦\95à§\8dত।\n* à¦\9fিà¦\95 à¦\9aিহà§\8dন à¦¬à¦¿à¦¹à§\80ন à¦\98রà§\87র à¦\85রà§\8dথ à¦¬à§\8dযবহারà¦\95ারà§\80 à¦\90 à¦¦à¦²à§\87র à¦\85নà§\8dতরà§\8dভà§\81à¦\95à§\8dত à¦¨à¦¨à¥¤\n* à¦\8fà¦\95à¦\9fি à¦¤à¦¾à¦°à¦\95া à¦\9aিহà§\8dন (*) à¦¦à§\8dবারা à¦¬à§\8bà¦\9dানà§\8b à¦¹à¦\9aà§\8dà¦\9bà§\87 à¦\8fà¦\87 à¦¦à¦²à§\87র à¦\85নà§\8dতরà§\8dভà§\81à¦\95à§\8dতির à¦ªà¦° à¦\86পনি à¦\86র à¦¤à¦¾ à¦¬à¦¾à¦¤à¦¿à¦² à¦\95রতà§\87 à¦ªà¦¾à¦°à¦¬à§\87ন à¦¨à¦¾, à¦¬à¦¾ à¦¤à¦¦à§\8dবিপরà§\80ত।\n* à¦\8fà¦\95à¦\9fি à¦¹à§\8dযাশ à¦\9aিহà§\8dন (#) à¦¦à§\8dবারা à¦¬à§\8bà¦\9dানà§\8b à¦¹à¦\9aà§\8dà¦\9bà§\87 à¦\86পনি à¦¶à§\81ধà§\81মাতà§\8dর à¦\8fà¦\87 à¦¦à¦²à§\87র à¦®à§\87য়াদ à¦¶à§\87ষ à¦¹à¦\93য়ার à¦¸à¦®à¦¯à¦¼ à¦ªà¦¿à¦\9bনà§\87 à¦¨à¦¿à¦¤à§\87 à¦ªà¦¾à¦°à¦¬à§\87ন; à¦\95িনà§\8dতà§\81 à¦¸à¦¾à¦®à¦¨à§\87 à¦¨à¦¿তে পারবেন না।",
        "userrights-reason": "কারণ (বাংলায় লিখুন):",
        "userrights-no-interwiki": "আপনার অন্য উইকিতে ব্যবহারকারী অধিকার সম্পাদনা করার অনুমতি নেই।",
        "userrights-nodatabase": "$1 ডাটাবেজটির হয় কোন অস্তিত্ব নেই অথবা এটি স্থানীয় ডাটাবেজ নয়।",
        "userrights-changeable-col": "দল যা আপনি পরিবর্তন করতে পারেন",
        "userrights-unchangeable-col": "দল যা আপনি পরিবর্তন করতে পারবেন না",
+       "userrights-expiry-current": "মেয়াদোত্তীর্ণের সময় $1",
+       "userrights-expiry-none": "মেয়াদোত্তীর্ণের সময় নেই",
+       "userrights-expiry": "মেয়াদোত্তীর্ণ হবে:",
+       "userrights-expiry-existing": "বিদ্যমান মেয়াদউত্তীর্ণের সময়: $3, $2",
+       "userrights-expiry-othertime": "অন্য সময়:",
+       "userrights-expiry-options": "১ দিন:1 day,১ সপ্তাহ:1 week,১ মাস:1 month,৩ মাস:3 months,৬ মাস:6 months,১ বছর:1 year",
+       "userrights-invalid-expiry": "\"$1\" দলের জন্য মেয়াদোত্তীর্ণের সময় অবৈধ।",
+       "userrights-expiry-in-past": "\"$1\" দলের জন্য মেয়াদোত্তীর্ণের সময় অতীতে।",
        "userrights-conflict": "ব্যবহারকারী অধিকার দ্বন্দ্ব! অনুগ্রহ করে নিশ্চিত হোন এবং পুনরায় চেষ্টা করুন।",
        "group": "দল:",
        "group-user": "ব্যবহারকারীগণ",
        "rcfilters-invalid-filter": "অকার্যকর ফিল্টার",
        "rcfilters-empty-filter": "কোনো সক্রিয় ফিল্টার নেই। সমস্ত অবদান দেখানো হয়েছে।",
        "rcfilters-filterlist-title": "ছাঁকনি",
+       "rcfilters-highlightmenu-title": "একটি রং নির্বাচন করুন",
        "rcfilters-filterlist-noresults": "কোনও ফিল্টার পাওয়া যায়নি",
        "rcfilters-filtergroup-registration": "ব্যবহারকারী নিবন্ধন",
        "rcfilters-filter-registered-label": "নিবন্ধিত",
        "rcfilters-filter-registered-description": "প্রবেশকৃত সম্পাদকবৃন্দ।",
        "rcfilters-filter-unregistered-label": "অনিবন্ধিত",
+       "rcfilters-filter-unregistered-description": "সম্পাদক যারা প্রবেশ করেন নি।",
        "rcfilters-filtergroup-authorship": "কৃতি সম্পাদনা",
        "rcfilters-filter-editsbyself-label": "আপনার নিজস্ব সম্পাদনা",
        "rcfilters-filter-editsbyself-description": "আপনার দ্বারা সম্পাদনা।",
        "rcfilters-filter-editsbyother-description": "অন্য ব্যবহারকারীদের দ্বারা করা সম্পাদনা (আপনার না)।",
        "rcfilters-filtergroup-userExpLevel": "অভিজ্ঞতার স্তর (শুধু মাত্র নিবন্ধিত ব্যবহারকারীর জন্য)",
        "rcfilters-filter-userExpLevel-newcomer-label": "নতুন আগত",
+       "rcfilters-filter-userExpLevel-newcomer-description": "১০টি সম্পাদনার কম ও ৪ দিনের কার্যকলাপ।",
        "rcfilters-filter-userExpLevel-learner-label": "শিক্ষার্থী",
        "rcfilters-filter-userExpLevel-experienced-label": "অভিজ্ঞ ব্যবহারকারী",
+       "rcfilters-filter-userExpLevel-experienced-description": "৩০ দিনের বেশী কার্যকলাপ ও ৫০০টি সম্পাদনা।",
+       "rcfilters-filtergroup-automated": "স্বয়ংক্রিয় অবদান",
        "rcfilters-filter-bots-label": "বট",
+       "rcfilters-filter-bots-description": "স্বয়ংক্রিয় সরঞ্জাম দিয়ে করা সম্পাদনা।",
+       "rcfilters-filter-humans-label": "মানুষ (বট নয়)",
+       "rcfilters-filter-humans-description": "মানব সম্পাদক দ্বারা করা সম্পাদনা।",
+       "rcfilters-filtergroup-significance": "তাত্পর্য",
+       "rcfilters-filter-minor-label": "অনুল্লেখ্য সম্পাদনা",
+       "rcfilters-filter-major-label": "অ-অনুল্লেখ্য সম্পাদনা",
+       "rcfilters-filtergroup-changetype": "পরিবর্তনের ধরন",
        "rcfilters-filter-pageedits-label": "পাতার সম্পাদনা",
+       "rcfilters-filter-pageedits-description": "উইকি বিষয়বস্তু, আলোচনা, বিষয়শ্রেণীর বিবরণ.... ইত্যাদিতে সম্পাদনা",
+       "rcfilters-filter-newpages-label": "পাতার সৃষ্টিকরণ",
+       "rcfilters-filter-newpages-description": "সম্পাদনা যা নতুন পাতা তৈরি করেছে।",
+       "rcfilters-filter-categorization-label": "বিষয়শ্রেণীর পরিবর্তন",
+       "rcfilters-filter-logactions-label": "প্রবেশকৃত কার্য",
+       "rcfilters-filter-logactions-description": "প্রশাসনিক কর্ম, অ্যাকাউন্ট সৃষ্টিকরণ, পাতা অপসারণ, আপলোড....",
        "rcnotefrom": "<strong>$2</strong>টা থেকে সংঘটিত পরিবর্তনগুলি (সর্বোচ্চ <strong>$1টি</strong> দেখানো হয়েছে)।",
        "rclistfrom": "$2, $3 তারিখের পর সংঘটিত নতুন পরিবর্তনগুলো দেখাও",
        "rcshowhideminor": "অনুল্লেখ্য পরিবর্তনগুলো $1",
        "apisandbox-results": "ফলাফল",
        "apisandbox-sending-request": "API অনুরোধ পাঠানো হচ্ছে...",
        "apisandbox-loading-results": "API ফলাফল গ্রহণ করা হচ্ছে...",
+       "apisandbox-results-error": "এপিআই কুয়েরির প্রতিক্রিয়া লোড করার সময় একটি ত্রুটি ঘটেছে: $1।",
        "apisandbox-request-selectformat-label": "অনুরোধ উপাত্ত এভাবে দেখান:",
        "apisandbox-request-format-url-label": "URL কোয়েরি স্ট্রিং",
        "apisandbox-request-url-label": "অনুরোধের URL:",
        "apisandbox-request-json-label": "JSON অনুরোধ:",
        "apisandbox-request-time": "অনুরোধের সময়: {{PLURAL:$1|$1 মি.সে.}}",
        "apisandbox-results-fixtoken": "টোকেন সংশোধন ও পুনরায় জমা",
+       "apisandbox-results-fixtoken-fail": "\"$1\" টোকেন আনতে ব্যর্থ হয়েছে।",
        "apisandbox-alert-page": "এই পাতার ঘরগুলো বৈধ নয়।",
        "apisandbox-alert-field": "এই ক্ষেত্রের মান বৈধ নয়।",
        "apisandbox-continue": "অব্যাহত",
        "undeletehistorynoadmin": "এই পাতাটি মুছে ফেলা হয়েছে। মুছে ফেলার কারণ নিচের সারাংশে দেখানো হল। সেই সাথে মুছে ফেলার আগে যেসমস্ত ব্যবহারকারী পাতাটি সম্পাদনা করেছেন, তাদের সম্পর্কেও বিস্তারিত দেখানো হল। এই মুছে ফেলা সংশোধনগুলির বিষয়বস্তু  কেবল প্রশাসকদের কাছে লভ্য।",
        "undelete-revision": "$3-এর করা $1 সংশোধন ($4 তারিখে, $5 সময়ের) মুছে ফেলা হয়েছে:",
        "undeleterevision-missing": "সংশোধনটি অবৈধ কিংবা হারানো গেছে। আপনি হয়ত অচল সংযোগে ক্লিক করেছেন, কিংবা সংশোধনটি হয়ত বাতিল করে পাতাটি পূর্বাবস্থায় নেওয়া হয়েছে, অথবা সংশোধনটি আর্কাইভ থেকে মুছে ফেলা হয়েছে।",
+       "undeleterevision-duplicate-revid": "{{PLURAL:$1|একটি সংশোধন|$1টি সংশোধন}} পুনরুদ্ধার করা যাবে না, কারণ {{PLURAL:$1|এটির|এগুলির}} <code>rev_id</code> ইতিমধ্যেই ব্যবহৃত হয়েছে।",
        "undelete-nodiff": "পূর্বের কোন সংশোধন খুঁজে পাওয়া যায়নি।",
        "undeletebtn": "পুনরুদ্ধার",
        "undeletelink": "দেখুন/পুনর্বহাল করুন",
        "proxyblockreason": "আপনার আইপি ঠিকানাকে বাধা দেয়া হয়েছে কারণ এটি একটি উন্মুক্ত প্রক্সি। অনুগ্রহ করে আপনার ইন্টারনেট সেবা প্রদানকারী কোম্পানির সাথে কারিগরি সহায়তার ব্যাপারে যোগাযোগ করুন এবং এই গুরুত্বপূর্ণ নিরাপত্তা সমস্যার ব্যাপারে তাদেরকে অবহিত করুন।",
        "sorbsreason": "আপনার আইপি ঠিকানাটি {{SITENAME}}-এর ব্যবহার করা DNSBL-এ উন্মুক্ত প্রক্সি হিসেবে তালিকাভুক্ত আছে।",
        "sorbs_create_account_reason": "আপনার আইপি ঠিকানাটি {{SITENAME}}-এর ব্যবহার করা DNSBL-এ উন্মুক্ত প্রক্সি হিসেবে তালিকাভুক্ত আছে। আপনি কোন অ্যাকাউন্ট সৃষ্টি করতে পারবেন না।",
+       "softblockrangesreason": "বেনামী অবদান আপনার আইপি ঠিকানা থেকে অনুমোদিত নয় ($1)। দয়া করে প্রবেশ করুন।",
        "xffblockreason": "X-Forwarded-For হেডারে থাকা আইপি ঠিকানাটি ব্লক করা হয়েছে, হয় এটি আপনার নিজের অথবা আপনার ব্যবহৃত প্রক্সি সার্ভারের আইপি ঠিকানা। ব্লক করার কারণ হল: $1",
        "cant-see-hidden-user": "আপনি যে ব্যবহারকারীকে ব্লক বা লুকিয়ে রাখতে চাচ্ছেন তাকে আগে থেকেই ব্লক বা লুকিয়ে রাখা হয়েছে। এছাড়া আপনার Hideuser অধিকার নেই, তাই আপনি ব্যবহারকারীর অবস্থা পরিবর্তন করতে পারবেন না।",
        "ipbblocked": "আপনি অন্য কোন ব্যবহারকরীকে ব্লক বা আনব্লক করতে পারবেন না, কারণ আপনি নিজেই ব্লক রয়েছেন",
        "cant-move-category-page": "আপনার বিষয়শ্রেণী পাতা স্থানান্তরের অনুমতি নেই।",
        "cant-move-to-category-page": "আপনার পাতাটিকে বিষয়শ্রেণী পাতায় স্থানান্তরের অনুমতি নেই।",
        "cant-move-subpages": "আপনার উপপাতা স্থানান্তরের অনুমতি নেই।",
+       "namespace-nosubpages": "\"$1\" নামস্থান উপপাতার অনুমতি দেয় না।",
        "newtitle": "নতুন শিরোনাম:",
        "move-watch": "এই পাতাটি নজরে রাখুন",
        "movepagebtn": "পাতা স্থানান্তর করুন",
        "movelogpagetext": "সরানো পাতাগুলির একটি তালিকা নিচে দেয়া হল।",
        "movesubpage": "{{PLURAL:$1|উপপাতা|উপপাতাসমূহ}}",
        "movesubpagetext": "এই পাতার $1টি {{PLURAL:$1|উপপাতা}} রয়েছে যেগুলো নিচে দেখানো হচ্ছে।",
+       "movesubpagetalktext": "সংশ্লিষ্ট আলাপ পাতার $1টি {{PLURAL:$1|উপপাতা}} রয়েছে যেগুলো নিচে দেখানো হচ্ছে।",
        "movenosubpage": "এই পাতাটির কোনো উপপাতা নেই।",
        "movereason": "কারণ:",
        "revertmove": "পূর্বাবস্থায় ফেরত নেওয়া হোক",
        "tags-delete-reason": "কারণ:",
        "tags-delete-submit": "অপরিবর্তনীয় এই ট্যাগ অপসারন করো",
        "tags-delete-not-found": "\"$1\" ট্যাগ বিদ্যমান নয়।",
+       "tags-delete-too-many-uses": "\"$1\" ট্যাগটি $2টিরও অধিক {{PLURAL:$2|সংশোধনে}} প্রয়োগ করা হয়েছে, যার অর্থ এটি অপসারণ করা যাবে না।",
        "tags-delete-no-permission": "আপনার পরিবর্তন ট্যাগ মুছে ফেলার অনুমতি নেই।",
        "tags-activate-title": "সক্রিয় ট্যাগ",
        "tags-activate-question": "আপনি ট্যাগ \"$1\" সক্রিয় করতে চলেছেন।",
        "tags-deactivate-reason": "কারণ:",
        "tags-deactivate-not-allowed": "ট্যাগ \"$1\" নিষ্ক্রিয় করা সম্ভব নয়।",
        "tags-deactivate-submit": "নিষ্ক্রিয়",
+       "tags-apply-no-permission": "আপনার পরিবর্তনসহ আপনার ট্যাগ পরিবর্তন প্রয়োগ করার অনুমতি নেই।",
+       "tags-apply-not-allowed-one": "\"$1\" ট্যাগটি ম্যানুয়ালি প্রয়োগ করা যাবে না।",
+       "tags-apply-not-allowed-multi": "নিন্মলিখিত {{PLURAL:$2|ট্যাগটি|ট্যাগগুলি}} ম্যানুয়ালি প্রয়োগ করা যাবে না: $1",
+       "tags-update-no-permission": "স্বতন্ত্র সংশোধন বা লগের ভুক্তি থেকে আপনার ট্যাগ পরিবর্তন যোগ বা বাতিল করার অনুমতি নেই।",
+       "tags-update-add-not-allowed-one": "\"$1\" ট্যাগটি ম্যানুয়ালি যোগ করা যাবে না।",
+       "tags-update-add-not-allowed-multi": "নিন্মলিখিত {{PLURAL:$2|ট্যাগটি|ট্যাগগুলি}} ম্যানুয়ালি যোগ করা যাবে না: $1",
+       "tags-update-remove-not-allowed-one": "\"$1\" ট্যাগটি বাতিল করা যাবে না।",
+       "tags-update-remove-not-allowed-multi": "নিন্মলিখিত {{PLURAL:$2|ট্যাগটি|ট্যাগগুলি}} ম্যানুয়ালি বাতিল করা যাবে না: $1",
        "tags-edit-title": "ট্যাগ সম্পাদনা করুন",
        "tags-edit-manage-link": "ট্যাগ পরিচালনা করুন",
        "tags-edit-revision-selected": "[[:$2]] পাতার {{PLURAL:$1|নির্বাচিত সংশোধন|নির্বাচিত সংশোধনসমূহ}}:",
        "tags-edit-logentry-selected": "{{PLURAL:$1|নির্বাচিত লগ ইভেন্ট}}:",
+       "tags-edit-logentry-legend": "{{PLURAL:$1|এই লগের ভুক্তি|$1টি লগের ভুক্তি}} থেকে ট্যাগ যোগ বা বাতিল করুন",
        "tags-edit-existing-tags": "বিদ্যমান ট্যাগ:",
        "tags-edit-existing-tags-none": "<em>কোনটি নয়</em>",
        "tags-edit-new-tags": "নতুন ট্যাগ:",
        "tags-edit-chosen-placeholder": "কিছু ট্যাগ নির্বাচন করুন",
        "tags-edit-chosen-no-results": "কোন ট্যাগ মিল পাওয়া যায়নি",
        "tags-edit-reason": "কারণ:",
-       "tags-edit-revision-submit": "Apply changes to {{PLURAL:$1|এই সংশোধনে|$1 সংশোধনসমূহে}} পরিবর্তন প্রয়োগ করুন",
+       "tags-edit-revision-submit": "{{PLURAL:$1|এই সংশোধনে|$1টি সংশোধনে}} পরিবর্তন প্রয়োগ করুন",
+       "tags-edit-logentry-submit": "{{PLURAL:$1|এই লগের ভুক্তিতে|$1টি লগের ভুক্তিতে}} পরিবর্তন প্রয়োগ করুন",
        "tags-edit-success": "পরিবর্তন প্রয়োগ করা হয়েছে।",
        "tags-edit-failure": "পরিবর্তন প্রয়োগ করা যায়নি: $1",
        "tags-edit-nooldid-title": "লক্ষ্য সংশোধন অবৈধ",
        "htmlform-date-placeholder": "বববব-মম-দদ",
        "htmlform-time-placeholder": "ঘঘ:মম:সস",
        "htmlform-datetime-placeholder": "বববব-মম-দদ ঘঘ:মম:সস",
+       "htmlform-date-invalid": "প্রদানকৃত মানটি স্বীকৃত তারিখ নয়। বববব-মম-দদ বিন্যাস ব্যবহার করে চেষ্টা করুন।",
+       "htmlform-time-invalid": "প্রদানকৃত মানটি স্বীকৃত সময় নয়। ঘঘ:মম:সস বিন্যাস ব্যবহার করে চেষ্টা করুন।",
+       "htmlform-datetime-invalid": "প্রদানকৃত মানটি স্বীকৃত তারিখ ও সময় নয়। বববব-মম-দদ ঘঘ:মম:সস বিন্যাস ব্যবহার করে চেষ্টা করুন।",
+       "htmlform-date-toolow": "আপনার প্রদানকৃত মানটি অনুমোদিত তারিখ $1-এর অনেক আগের।",
+       "htmlform-date-toohigh": "আপনার প্রদানকৃত মানটি অনুমোদিত তারিখ $1-এর অনেক পরের।",
+       "htmlform-time-toolow": "আপনার প্রদানকৃত মানটি অনুমোদিত সময় $1-এর অনেক আগের।",
+       "htmlform-time-toohigh": "আপনার প্রদানকৃত মানটি অনুমোদিত সময় $1-এর অনেক পরের।",
+       "htmlform-datetime-toolow": "আপনার প্রদানকৃত মানটি অনুমোদিত তারিখ ও সময় $1-এর অনেক আগের।",
+       "htmlform-datetime-toohigh": "আপনার প্রদানকৃত মানটি অনুমোদিত তারিখ ও সময় $1-এর অনেক পরের।",
        "htmlform-title-badnamespace": "[[:$1]] \"{{ns:$2}}\" নামস্থানে খুঁজে পাওয়া যায়নি।",
        "htmlform-title-not-creatable": "\"$1\" সৃষ্টিযোগ্য পাতার শিরোনাম নয়",
        "htmlform-title-not-exists": "$1-এর অস্তিত্ব নেই।",
        "logentry-upload-overwrite": "$1 $3-এর একটি নতুন সংস্করণ {{GENDER:$2|আপলোড করেছেন}}",
        "logentry-upload-revert": "$1 $3 {{GENDER:$2|আপলোড করেছেন}}",
        "log-name-managetags": "ট্যাগ ব্যবস্থাপনা লগ",
-       "logentry-managetags-create": "$1 \"$4\" ট্যাগ {{GENDER:$2|তৈরি করেছে}}",
+       "logentry-managetags-create": "$1 \"$4\" ট্যাগটি {{GENDER:$2|তৈরি করেছেন}}",
        "logentry-managetags-delete": "$1 \"$4\" ট্যাগটি {{GENDER:$2|অপসারণ করেছেন}} ($5টি {{PLURAL:$5|সংস্করণ বা লগ ভুক্তি|সংস্করণ ও/বা লগ ভুক্তি}} সরানো হয়েছে)",
+       "logentry-managetags-deactivate": "$1 \"$4\" ট্যাগটি ব্যবহারকারী ও বট দ্বারা ব্যবহারের জন্য {{GENDER:$2|নিষ্ক্রিয়}} করেছেন",
        "log-name-tag": "ট্যাগ লগ",
        "rightsnone": "(কিছু নাই)",
        "revdelete-summary": "সম্পাদনা সারাংশ",
+       "rightslogentry-temporary-group": "$1 (সাময়িক, $2 পর্যন্ত)",
        "feedback-adding": "পাতায় প্রতিক্রিয়া যোগ হচ্ছে...",
        "feedback-back": "পিছনে",
        "feedback-bugcheck": "উত্তম! যাচাই করুন যে এই [$1  জানা বাগের] কোন একটি কিনা।",
        "api-error-emptypage": "নতুন পাতা তৈরি হচ্ছে, খালি পাতা গ্রহণযোগ্য নয়।",
        "api-error-publishfailed": "অভ্যন্তরীন ত্রুটি: সার্ভার অস্থায়ী ফাইলটি প্রকাশ করতে ব্যর্থ হয়েছে।",
        "api-error-stashfailed": "অভ্যন্তরীণ ত্রুটি: সার্ভার অস্থায়ী ফাইলটি সংরক্ষণ করতে ব্যর্থ হয়েছে।",
-       "api-error-unknown-warning": "অজানা সতর্কীকরণ: $1",
+       "api-error-unknown-warning": "অজানা সতর্কীকরণ: \"$1\"।",
        "api-error-unknownerror": "অজানা ত্রুটি: \"$1\"।",
        "duration-seconds": "$1 {{PLURAL:$1|সেকেন্ড|সেকেন্ড}}",
        "duration-minutes": "$1 {{PLURAL:$1|মিনিট|মিনিট}}",
        "expand_templates_generate_xml": "XML পার্স বৃক্ষ দেখাও",
        "expand_templates_generate_rawhtml": "এইচটিএমএল দেখাও",
        "expand_templates_preview": "প্রাকদর্শন",
+       "expand_templates_preview_fail_html": "<em>{{SITENAME}}-এ raw HTML সক্রিয় আছে ও সেশন উপাত্ত হারিয়ে গিয়েছে, জাভাস্ক্রিপ্ট ভিত্তিক আক্রমণ থেকে প্রতিরক্ষার জন্য প্রাকদর্শনটি লুকায়িত আছে।</em>\n\n<strong>যদি এটি সম্পাদনার একটি বৈধ প্রচেষ্টা হয়, তবে অনুগ্রহ করে আবার চেষ্টা করুন।</strong>\nযদি তারপরেও কাজ না হয়, তবে অ্যাকাউন্ট থেকে [[Special:UserLogout|বেরিয়ে গিয়ে]] আবার প্রবেশ করুন, এবং পরীক্ষা করে দেখুন যে আপনার ব্রাউজারে এই সাইট থেকে কুকি অনুমতি দেয়।",
+       "expand_templates_preview_fail_html_anon": "<em>{{SITENAME}}-এ raw HTML সক্রিয় আছে ও আপনি প্রবেশ করেন নি, জাভাস্ক্রিপ্ট ভিত্তিক আক্রমণ থেকে প্রতিরক্ষার জন্য প্রাকদর্শনটি লুকায়িত আছে।</em>\n\n<strong>যদি এটি সম্পাদনার একটি বৈধ প্রচেষ্টা হয়, তবে অনুগ্রহ করে  [[Special:UserLogin|প্রবেশ করুন]] ও আবার চেষ্টা করুন।</strong>",
        "expand_templates_input_missing": "আপনাকে অন্তত কিছু ইনপুট লেখা প্রদান করতে হবে।",
        "pagelanguage": "পাতার ভাষা পরিবর্তন করুন",
        "pagelang-name": "পাতা",
        "pagelang-select-lang": "ভাষা নির্বাচন করুন",
        "pagelang-reason": "কারণ",
        "pagelang-submit": "জমা দাও",
+       "pagelang-nonexistent-page": "$1 শিরোনামে কোন পাতা নেই।",
        "pagelang-db-failed": "ডাটাবেস পৃষ্ঠার ভাষা পরিবর্তন করতে ব্যর্থ হয়েছে।",
        "right-pagelang": "পাতার ভাষা পরিবর্তন করুন",
        "action-pagelang": "পাতার ভাষা পরিবর্তন করুন",
        "mw-widgets-titleinput-description-new-page": "পাতা এখনো বিদ্যমান নয়",
        "mw-widgets-titleinput-description-redirect": "$1-এ পুনঃনির্দেশিত",
        "mw-widgets-categoryselector-add-category-placeholder": "একটি বিষয়শ্রেণী যোগ করুন...",
+       "mw-widgets-usersmultiselect-placeholder": "আরও যোগ করুন...",
        "sessionmanager-tie": "একাধিক অনুরোধের প্রমাণীকরণের ধরন একত্রিত করা যাবে না: $1।",
        "sessionprovider-generic": "$1টি সেশন",
        "sessionprovider-mediawiki-session-cookiesessionprovider": "কুকি-ভিত্তিক সেশন",
index 2776bf5..9a1df69 100644 (file)
        "tagline": "Eus {{SITENAME}}",
        "help": "Skoazell",
        "search": "Klask",
+       "search-ignored-headings": " #<!-- lezel al linenn-mañ tre evel m'emañ --> <pre>\n# Titloù a vo lezet a-gostez gant ar c'hlask.\n# Ar c'hemmoù graet amañ a vo lakaet e pleustr kerkent ha menegeret ar bajenn gant an titl.\n# Gallout a rit forsiñ un advenegeriñ ma rit ur c'hemm goullo en ur bajenn.\n# Setu penaos emañ an ereadur :\n#   * Kement linenn zo, adalek an arouezenn \"#\" betek dibenn al linenn a zo un evezhiadenn.\n#   * Kement linenn ha n'eo ket goullo a verk an titl rik a zo da vezañ lezet a-gostez, pennlizherennoù hag all.\nDaveennoù\nLiammoù diavaez\nGwelet ivez\n #</pre> <!-- lezel al linenn-mañ tre evel m'emañ -->",
        "searchbutton": "Klask",
        "go": "Kas",
        "searcharticle": "Mont",
        "databaseerror-query": "Reked : $1",
        "databaseerror-function": "Arc'hwel : $1",
        "databaseerror-error": "Fazi : $1",
+       "transaction-duration-limit-exceeded": "Kuit da lakaat kreskiñ betek re an termen respont eo bet nullet an treuzgread-mañ rak aet e oa ar pad skrivañ ($1) en tu all d'ar vevenn a $2 eilenn.\nM'emaoc'h o cheñch kalz elfennoù war un dro klaskit kentoc'h troc'hañ anezho e meur a oberiadenn disteroc'h.",
        "laggedslavemode": "Diwallit : marteze a-walc'h n'emañ ket ar c'hemmoù diwezhañ war ar bajenn-mañ",
        "readonly": "Hizivadurioù stanket war ar bank roadennoù",
        "enterlockreason": "Merkit perak eo stanket hag istimit pegeit e chomo evel-henn",
        "yourname": "Anv implijer :",
        "userlogin-yourname": "Anv implijer",
        "userlogin-yourname-ph": "Merkit hoc'h anv implijer",
-       "createacct-another-username-ph": "Ebarzhiñ an anv implijer",
+       "createacct-another-username-ph": "Merkañ an anv implijer",
        "yourpassword": "Ger-tremen :",
        "userlogin-yourpassword": "Ger-tremen",
        "userlogin-yourpassword-ph": "Merkit ho ker-tremen",
        "createacct-emailrequired": "Chomlec'h postel",
        "createacct-emailoptional": "Chomlec'h postel (diret)",
        "createacct-email-ph": "Skrivit ho chomlec'h postel",
-       "createacct-another-email-ph": "Ebarzhiñ ur chomlec'h postel",
+       "createacct-another-email-ph": "Merkañ ur chomlec'h postel",
        "createaccountmail": "Implijout ur ger-tremen dibad ha kas anezhañ d'ar chomlec'h postel diferetDre bostel",
        "createaccountmail-help": "Gallout a ra bezañ implijet evit krouiñ ur gont evit unan bennak all hep gouzout ar ger-tremen.",
        "createacct-realname": "Anv gwir (diret)",
        "missingsummary": "'''Taolit evezh:''' N'hoc'h eus ket lakaet tamm testenn diverrañ ebet evit ho kemmoù. Mar klikit war enrollañ en-dro, e vo enrollet ho testenn evel m'emañ hepmuiken.",
        "missingcommenttext": "Skrivit hoc'h evezhiadenn a-is.",
        "missingcommentheader": "'''Taolit evezh :''' N'hoc'h eus lakaet tamm danvez/titl ebet d'hoc'h evezhiadenn.\nMar klikit war \"{{int:savearticle}}\" en-dro, e vo enrollet ho testenn evel m'emañ hepmuiken.",
-       "summary-preview": "Rakwelet an diverrañ :",
+       "summary-preview": "Rakwelet un diverrañ eus ar c'hemmoù :",
        "subject-preview": "Rakwelet an danvez :",
        "previewerrortext": "C'hoarvezet ez eus ur fazi e-ser klask rakwelet ho kemmoù",
        "blockedtitle": "Implijer stanket",
        "rcfilters-invalid-filter": "Sil direizh",
        "rcfilters-empty-filter": "Sil oberiant ebet. War wel emañ an holl gemmoù.",
        "rcfilters-filterlist-title": "Siloù",
+       "rcfilters-highlightmenu-title": "Dibabit ul liv",
        "rcfilters-filterlist-noresults": "N'eus bet kavet sil ebet",
        "rcfilters-filtergroup-registration": "Enskrivadur an implijer",
        "rcfilters-filter-registered-label": "Marilhet",
        "recentchangeslinked-feed": "Heuliañ ar pajennoù liammet",
        "recentchangeslinked-toolbox": "Heuliañ ar pajennoù liammet",
        "recentchangeslinked-title": "Kemmoù a denn da \"$1\"",
-       "recentchangeslinked-summary": "Rollet eo war ar bajenn dibar-mañ ar c'hemmoù diwezhañ bet degaset war ar pajennoù liammet ouzh ur bajenn lakaet (pe ouzh izili ur rummad lakaet).\nE '''tev''' emañ ar pajennoù zo war ho [[Special:Watchlist|roll evezhiañ]].",
+       "recentchangeslinked-summary": "Rollet eo war ar bajenn dibar-mañ ar c'hemmoù diwezhañ bet degaset war ar pajennoù liammet ouzh ur bajenn lakaet (pe ouzh izili ur rummad lakaet).\nE <strong>tev</strong> emañ ar pajennoù zo war ho [[Special:Watchlist|roll evezhiañ]].",
        "recentchangeslinked-page": "Anv ar bajenn :",
        "recentchangeslinked-to": "Diskouez ar c'hemmoù war-du ar pajennoù liammet kentoc'h eget re ar bajenn lakaet",
        "recentchanges-page-added-to-category": "[[:$1]] ouzhpennet d'ar rummad",
        "apisandbox-results": "Disoc'hoù",
        "apisandbox-request-url-label": "Goulenn URL :",
        "apisandbox-request-time": "Pad ar goulenn: $1",
+       "apisandbox-alert-field": "Talvoud ar vaezienn-mañ n'eo ket reizh.",
        "apisandbox-continue": "Kenderc'hel",
        "apisandbox-continue-clear": "Riñsañ",
        "apisandbox-multivalue-all-namespaces": "$1 (An holl esaouennoù anv)",
        "activeusers-count": "$1 {{PLURAL:$1|oberiadenn}} abaoe an {{PLURAL:$3|deiz|$3 deiz}} diwezhañ",
        "activeusers-from": "Diskouez an implijerien adal :",
        "activeusers-noresult": "N'eus bet kavet implijer ebet.",
+       "activeusers-submit": "Diskouez an implijerien oberiant",
        "listgrouprights": "Gwirioù ar strolladoù implijer",
        "listgrouprights-summary": "Da-heul ez eus ur roll eus ar strolladoù implijerien termenet war ar wiki-mañ, gant ar gwirioù moned stag outo.\nGallout a ra bezañ [[{{MediaWiki:Listgrouprights-helppage}}|titouroù ouzhpenn]] diwar-benn ar gwirioù hiniennel.",
        "listgrouprights-key": "Alc'hwez :\n* <span class=\"listgrouprights-granted\">Gwirioù grataet</span>\n* <span class=\"listgrouprights-revoked\">Gwirioù lamet</span>",
        "pageinfo-contentpage-yes": "Ya",
        "pageinfo-protect-cascading-yes": "Ya",
        "pageinfo-category-info": "Titouroù ar rummad",
+       "pageinfo-category-total": "Niver hollek a izili",
        "pageinfo-category-pages": "Niver a bajennoù",
        "pageinfo-category-subcats": "Niver a isrummadoù",
        "pageinfo-category-files": "Niver a restroù",
        "exif-compression-4": "CCITT Strollad 4 kodañ ar pelleiler",
        "exif-copyrighted-true": "Pep gwir miret strizh",
        "exif-copyrighted-false": "Domani foran",
+       "exif-photometricinterpretation-1": "Gwenn ha du (0 zo evit du)",
        "exif-unknowndate": "Deiziad dianav",
        "exif-orientation-1": "Boutin",
        "exif-orientation-2": "Eilpennet a-hed",
        "confirmemail_body_set": "Unan bennak, c'hwi moarvat, gant ar chomlec'h IP $1,\nen deus enrollet ur gont \"$2\" gant ar chomlec'h postel-mañ war lec'hienn {{SITENAME}}.\n\nEvit kadarnaat eo deoc'h ar gont-se ha gweredekaat en-dro\nan arc'hwelioù postelerezh war {{SITENAME}}, digorit al liamm-mañ en ho merdeer :\n\n$3\n\nMa n'eo *ket* deoc'h ar gont heuilhit al liamm-mañ\nevit nullañ kadarnaat ar chomlec'h postel :\n\n$5\n\nMont a raio ar c'hod-mañ d'e dermen d'ar $4.",
        "confirmemail_invalidated": "Nullet eo bet kadarnaat ar chomlec'h postel",
        "invalidateemail": "Nullañ kadarnaat ar postel",
+       "notificationemail_subject_changed": "Cheñchet eo bet ar chomlec'h postel enrollet e {{SITENAME}}",
+       "notificationemail_subject_removed": "Lamet eo bet ar chomlec'h postel enrollet e {{SITENAME}}",
        "scarytranscludedisabled": "[Diweredekaet eo an treuzkludañ etrewiki]",
        "scarytranscludefailed": "[N'eus ket bet gallet tapout ar patrom evit $1]",
        "scarytranscludefailed-httpstatus": "[c'hwitet adtapout ar patrom evit $1: HTTP $2]",
        "tags-actions-header": "Oberoù",
        "tags-active-yes": "Ya",
        "tags-active-no": "Ket",
+       "tags-source-extension": "Termenet gant ar meziant",
        "tags-source-none": "N'emañ ket en implij ken",
        "tags-edit": "aozañ",
        "tags-delete": "diverkañ",
        "tags-create-no-name": "Rekis eo merkañ anv un dikedenn.",
        "tags-delete-title": "Diverkañ an dikedenn",
        "tags-delete-reason": "Abeg :",
+       "tags-delete-not-found": "N'eus ket eus an dikedenn \"$1\".",
        "tags-activate-title": "Gweredekaat an dikedenn",
        "tags-activate-reason": "Abeg :",
        "tags-activate-submit": "Gweredekaat",
        "logentry-upload-revert": "$1 {{GENDER:$2|en deus|he deus}} ezporzhiet $3",
        "rightsnone": "(netra)",
        "revdelete-summary": "diverradenn eus ar c'hemmoù",
+       "rightslogentry-temporary-group": "$1 (da c'hortoz, betek $2)",
        "feedback-adding": "Oc'h ouzhpennañ ho soñj war ar bajenn...",
        "feedback-back": "Distreiñ",
        "feedback-bugcheck": "Eus ar c'hentañ ! Gwiriit mat n'emañ ket e-touez an [$1 draen diskoachet c'hoazh].",
        "pagelang-unchanged-language": "Kefluniet eo c'hoazh ar bajenn $1 e $2.",
        "right-pagelang": "Cheñch yezh ar bajenn",
        "action-pagelang": "cheñch yezh ar bajenn",
-       "log-name-pagelang": "Cheñch yezh",
+       "log-name-pagelang": "Marilh ar cheñchamantoù yezh",
        "log-description-pagelang": "Hemañ zo ur marilh eus ar c'hemmoù e pajenn ar yezhoù.",
-       "logentry-pagelang-pagelang": "$1 {{GENDER:$2|en deus|he deus}} cheñchet yezh ar bajenn evit $3 eus $4 da $5.",
+       "logentry-pagelang-pagelang": "$1 {{GENDER:$2|en deus|he deus}} cheñchet yezh ar bajenn $3 eus $4 da $5.",
        "default-skin-not-found-row-enabled": "* <code>$1</code> / $2 (gweredekaet)",
        "default-skin-not-found-row-disabled": "* <code>$1</code> / $2 (<strong>diweredekaet</strong>)",
        "mediastatistics": "Stadegoù ar media",
        "log-action-filter-protect-protect": "Gwarez",
        "log-action-filter-protect-unprotect": "Diwarez",
        "log-action-filter-rights-autopromote": "Kemm emgefre",
+       "log-action-filter-upload-upload": "Enporzhiadenn nevez",
+       "log-action-filter-upload-overwrite": "Adenporzhiañ",
        "authmanager-authn-no-primary": "N'eus ket bet gallet gwiriañ an titouroù kred lakaet.",
        "authmanager-authn-no-local-user-link": "Reizh eo an titouroù kred lakaet met n'int ket liammet ouzh implijer ebet eus ar wiki-mañ. Ma kevreit en ur mod all pe ma krouit ur gont implijer nevez e c'hallot liammañ ho titouroù kred kent ouzh ar gont-mañ.",
        "authmanager-change-not-supported": "N'haller ket cheñch an titouroù kred rak netra na rafe ganto.",
+       "authmanager-create-disabled": "Diweredekaet eo ar c'hrouiñ kontoù.",
+       "authmanager-create-from-login": "Evit krouiñ ho kont, leuniit ar maeziennoù.",
        "authmanager-create-no-primary": "N'eus ket bet gallet implijout an titouroù kred lakaet evit krouiñ ur gont.",
        "authmanager-authplugin-setpass-failed-title": "C'hwitet eo bet ar cheñchamant ger-tremen",
        "authmanager-authplugin-setpass-bad-domain": "Domani direizh.",
        "linkaccounts-submit": "Liammañ ar c'hontoù",
        "unlinkaccounts": "Diliammañ ar c'hontoù",
        "unlinkaccounts-success": "Diliammet eo bet ar gont.",
+       "restrictionsfield-help": "Ur chomlec'h IP pe un esaouenn CIDR dre linenn. Evit gweredekaat pep tra, ober gant <pre>0.0.0.0/0\n::/0</pre>",
        "revid": "Adweladenn $1",
        "pageid": "ID ar bajenn $1"
 }
index 9a3424e..f765098 100644 (file)
@@ -23,7 +23,8 @@
                        "Emir Mujadzic",
                        "Srdjan m",
                        "Semso98",
-                       "Matma Rex"
+                       "Matma Rex",
+                       "Сербијана"
                ]
        },
        "tog-underline": "Podvuci veze:",
@@ -74,7 +75,7 @@
        "underline-default": "Prema predodređenim postavkama teme ili preglednika",
        "editfont-style": "Stil fonta u okviru za uređivanje:",
        "editfont-default": "Po postavkama preglednika",
-       "editfont-monospace": "Slova sa jednostrukim razmakom",
+       "editfont-monospace": "Neproporcionalni font",
        "editfont-sansserif": "Beserifni font",
        "editfont-serif": "Serifni font",
        "sunday": "nedjelja",
        "userlogin-reauth": "Morate se ponovo prijaviti da bismo potvrdili da ste zaista {{GENDER:$1|$1}}.",
        "userlogin-createanother": "Napravi još jedan račun",
        "createacct-emailrequired": "Adresa e-pošte",
-       "createacct-emailoptional": "Adresa e-pošte (opcionalno)",
+       "createacct-emailoptional": "Adresa e-pošte (neobavezno)",
        "createacct-email-ph": "Unesite Vašu adresu e-pоšte",
        "createacct-another-email-ph": "Unesite adresu e-pošte",
        "createaccountmail": "Koristite privremenu, slučajno stvorenu lozinku i pošaljite na navedenu adrеsu e-pošte",
        "createacct-reason": "Razlog",
        "createacct-reason-ph": "Zašto pravite još jedan korisnički račun?",
        "createacct-reason-help": "Poruka koja se prikazuje u zapisniku stvaranja korisničkih računa",
-       "createacct-submit": "Napravite svoj korisnički račun",
+       "createacct-submit": "Napravi račun",
        "createacct-another-submit": "Napravi korisnički račun",
        "createacct-continue-submit": "Nastavi sa stvaranjem računa",
        "createacct-another-continue-submit": "Nastavi sa stvaranjem računa",
        "createacct-benefit-heading": "{{GRAMMAR:akuzativ|{{SITENAME}}}} stvaraju ljudi poput Vas.",
-       "createacct-benefit-body1": "{{PLURAL:$1|izmjena|izmjene}}",
+       "createacct-benefit-body1": "{{PLURAL:$1|izmjena|izmjene|izmjena}}",
        "createacct-benefit-body2": "{{PLURAL:$1|stranica|stranice|stranica}}",
-       "createacct-benefit-body3": "nedavnih {{PLURAL:$1|doprinosa}}",
+       "createacct-benefit-body3": "{{PLURAL:$1|nedavni korisnik|nedavnih korisnika}}",
        "badretype": "Lozinke koje ste unijeli se ne poklapaju",
        "usernameinprogress": "Račun za ovo korisničko ime već se pravi. Molimo sačekajte.",
        "userexists": "Korisničko ime je već u upotrebi.\nIzaberite drugo.",
        "last": "preth",
        "page_first": "prva",
        "page_last": "posljednja",
-       "histlegend": "Odabir razlika: označite radio dugme verzija koje uspoređujete i pritistnite enter ili dugme na dnu. <br />\nObjašnjenje: '''(tren)''' = razlika sa trenutnom verzijom,\n'''(preth)''' = razlika sa prethodnom verzijom, '''m''' = mala izmjena.",
+       "histlegend": "Odabir razlika: označite radio dugme verzija koje uspoređujete i pritistnite enter ili dugme na dnu. <br />\nObjašnjenje: <strong>({{int:cur}})</strong> = razlika sa trenutnom verzijom, <strong>({{int:last}})</strong> = razlika sa prethodnom verzijom, <strong>{{int:minoreditletter}}</strong> = mala izmjena.",
        "history-fieldset-title": "Pretraga historije",
        "history-show-deleted": "Samo obrisane",
        "histfirst": "najstarije",
        "action-changetags": "dodate ili uklonite razne oznake na pojedinačnim verzijama i unosima u zapisnicima",
        "action-deletechangetags": "brišete oznake iz baze podataka",
        "action-purge": "osvježite keš ove stranice",
-       "nchanges": "$1 {{PLURAL:$1|promjena|promjene|promjena}}",
+       "nchanges": "$1 {{PLURAL:$1|izmjena|izmjene|izmjena}}",
        "enhancedrc-since-last-visit": "$1 {{PLURAL:$1|izmjena od Vaše posljedne posjete}}",
        "enhancedrc-history": "historija",
        "recentchanges": "Nedavne izmjene",
        "recentchangeslinked-summary": "Ova posebna stranica prikazuje promjene na povezanim stranicama.\nStranice koje su na vašem [[Special:Watchlist|spisku praćenja]] su '''podebljane'''.",
        "recentchangeslinked-page": "Naslov stranice:",
        "recentchangeslinked-to": "Pokaži promjene stranica koji su povezane sa datom stranicom",
-       "recentchanges-page-added-to-category": "[[:$1]] dodana je u kategoriju",
+       "recentchanges-page-added-to-category": "Stranica [[:$1]] dodana je u kategoriju",
        "recentchanges-page-added-to-category-bundled": "Stranica [[:$1]] dodana je u kategoriju, [[Special:WhatLinksHere/$1|ovu stranicu sadrže druge stranice]]",
-       "recentchanges-page-removed-from-category": "[[:$1]] je uklonjena iz kategorije",
+       "recentchanges-page-removed-from-category": "Stranica [[:$1]] uklonjena je iz kategorije",
        "recentchanges-page-removed-from-category-bundled": "Stranica [[:$1]] uklonjena je iz kategorije, [[Special:WhatLinksHere/$1|ovu stranicu sadrže druge stranice]]",
        "autochange-username": "Automatska promjena MediaWikija",
        "upload": "Postavi datoteku",
index ddced48..3e1aa18 100644 (file)
        "sig_tip": "Имзанъыз ве тарих",
        "hr_tip": "Горизонталь сызыкъ (пек сыкъ къулланманъыз)",
        "summary": "Денъиштирменинъ къыскъа тарифи:",
-       "subject": "Мевзу/серлева:",
+       "subject": "Мевзу:",
        "minoredit": "Бу, кичик денъиштирмедир",
        "watchthis": "Саифени козет",
        "savearticle": "Саифени сакъла",
+       "savechanges": "Денъиштирмелерни сакъла",
        "preview": "Бакъып чыкъув",
        "showpreview": "Бакъып чыкъ",
        "showdiff": "Денъиштирмелерни косьтер",
        "saveprefs": "Сакъла",
        "restoreprefs": "Бутюн ог бельгиленген сазламаларны къайтар",
        "prefs-editing": "Саифелерни денъиштирюв",
-       "rows": "Сатыр",
-       "columns": "Сутун",
        "searchresultshead": "Къыдырув",
        "recentchangesdays": "Сонъки денъиштирмелер саифесинде косьтериледжек кунь сайысы:",
        "recentchangesdays-max": "(энъ чокъ $1 {{PLURAL:$1|1=кунь|кунь}})",
index e48be9f..3054c1b 100644 (file)
        "sig_tip": "İmzañız ve tarih",
        "hr_tip": "Gorizontal sızıq (pek sıq qullanmañız)",
        "summary": "Deñiştirmeniñ qısqa tarifi:",
-       "subject": "Mevzu/serleva:",
+       "subject": "Mevzu:",
        "minoredit": "Bu, kiçik deñiştirmedir",
        "watchthis": "Saifeni közet",
        "savearticle": "Saifeni saqla",
+       "savechanges": "Deñiştirmelerni saqla",
        "preview": "Baqıp çıquv",
        "showpreview": "Baqıp çıq",
        "showdiff": "Deñiştirmelerni köster",
        "saveprefs": "Saqla",
        "restoreprefs": "Bütün ög belgilengen sazlamalarnı qaytar",
        "prefs-editing": "Saifelerni deñiştirüv",
-       "rows": "Satır",
-       "columns": "Sutun",
        "searchresultshead": "Qıdıruv",
        "recentchangesdays": "Soñki deñiştirmeler saifesinde kösterilecek kün sayısı:",
        "recentchangesdays-max": "(eñ çoq $1 {{PLURAL:$1|kün|kün}})",
index bcc1a0f..d8e1bb9 100644 (file)
        "difference-title": "$1: Porovnání verzí",
        "difference-title-multipage": "$1 a $2: Porovnání stránek",
        "difference-multipage": "(Rozdíly mezi stránkami)",
-       "lineno": "Řádka $1:",
+       "lineno": "Řádek $1:",
        "compareselectedversions": "Porovnat vybrané verze",
        "showhideselectedversions": "Zobrazit/skrýt vybrané revize",
        "editundo": "zrušit editaci",
index fed7683..351ac32 100644 (file)
        "invalid-content-data": "Ugyldig indholdsdata",
        "content-not-allowed-here": "\"$1\" indhold er ikke tilladt på siden [[$2]]",
        "editwarning-warning": "Hvis du forlader siden nu, risikerer du at miste alle ændringer, som du har lavet.\nDenne advarsel kan slås fra under \"{{int:prefs-editing}}\" i dine indstillinger.",
+       "editpage-invalidcontentmodel-title": "Indholdsmodellen er ikke understøttet",
        "editpage-notsupportedcontentformat-title": "Indholdsformatet understøttes ikke",
        "editpage-notsupportedcontentformat-text": "Indholdsformatet $1 understøttes ikke af indholdsmodellen $2",
        "content-model-wikitext": "wikitekst",
        "content-model-css": "CSS",
        "content-json-empty-object": "Tomt objekt",
        "content-json-empty-array": "Tomt array",
+       "deprecated-self-close-category": "Sider, der bruger ugyldige, selvlukkende HTML-tags",
        "duplicate-args-category": "Sider der bruger samme argument mere end en gang i en skabelon",
        "duplicate-args-category-desc": "Siden indeholder en skabelon hvor et argument er brugt mere end en gang, som <code><nowiki>{{foo|bar=1|bar=2}}</nowiki></code> eller <code><nowiki>{{foo|bar|1=baz}}</nowiki></code>.",
        "expensive-parserfunction-warning": "Advarsel: Der er for mange beregningstunge oversætter-funktionskald på denne side.\n\nDer bør være færre end {{PLURAL:$2|$2 kald}}, lige nu er der {{PLURAL:$1|$1 kald}}.",
        "search-interwiki-caption": "Søsterprojekter",
        "search-interwiki-default": "Resultater fra $1:",
        "search-interwiki-more": "(mere)",
+       "search-interwiki-more-results": "flere resultater",
        "search-relatedarticle": "Relateret",
        "searchrelated": "relateret",
        "searchall": "alle",
        "youremail": "Din e-mailadresse:",
        "username": "{{GENDER:$1|Brugernavn}}:",
        "prefs-memberingroups": "{{GENDER:$2|Medlem}} af {{PLURAL:$1|gruppen|grupperne}}:",
+       "group-membership-link-with-expiry": "$1 (indtil $2)",
        "prefs-registration": "Registreringstidspunkt:",
        "yourrealname": "Dit rigtige navn:",
        "yourlanguage": "Sprog:",
        "userrights-user-editname": "Skriv et brugernavn:",
        "editusergroup": "Indlæs brugergrupper",
        "editinguser": "Ændrer brugerrettigheder for {{GENDER:$1|brugeren}} <strong>[[User:$1|$1]]</strong> $2",
-       "userrights-editusergroup": "Redigér brugergrupper",
+       "userrights-editusergroup": "Redigér {{GENDER:$1|brugergrupper}}",
        "saveusergroups": "Gem {{GENDER:$1|brugergrupper}}",
        "userrights-groupsmember": "Medlem af:",
        "userrights-groupsmember-auto": "Implicit medlem af:",
        "userrights-nodatabase": "Databasen $1 eksisterer ikke lokalt.",
        "userrights-changeable-col": "Redigerbare grupper",
        "userrights-unchangeable-col": "Uredigerbare grupper",
+       "userrights-expiry-current": "Udløber $1",
+       "userrights-expiry-none": "Udløber ikke",
        "userrights-conflict": "Konflikt i ændringer af brugerrettigheder!\nVær venlig at gennemse og bekræft dine ændringer.",
        "group": "Gruppe:",
        "group-user": "Brugere",
        "booksources-search": "Søg",
        "booksources-text": "Dette er en liste med henvisninger til Internetsider, som sælger nye og brugte bøger. Der kan der også findes yderligere informationer om bøgerne. {{SITENAME}} er ikke forbundet med nogen af dem.",
        "booksources-invalid-isbn": "Det angivne ISBN-nummer ser forkert ud. Tjek med kilden om det er skrevet korrekt.",
+       "magiclink-tracking-rfc": "Sider, der bruger automatiske RFC-henvisninger‎",
+       "magiclink-tracking-pmid": "Sider, der bruger automatiske PMID-henvisninger‎",
        "magiclink-tracking-isbn": "Sider, der bruger automatiske ISBN-henvisninger",
        "specialloguserlabel": "Udført af:",
        "speciallogtitlelabel": "Mål (titel eller {{ns:user}}:brugernavn for bruger):",
        "exif-compression-6": "JPEG (gammel)",
        "exif-copyrighted-true": "Ophavsretligt beskyttet",
        "exif-copyrighted-false": "Status for ophavsret er ikke angivet",
+       "exif-photometricinterpretation-1": "Sort-hvid (sort er 0)",
        "exif-unknowndate": "Ukendt dato",
        "exif-orientation-1": "Normal",
        "exif-orientation-2": "Horisontalt spejlet",
        "logentry-upload-revert": "$1 {{GENDER:$2|lagde}} $3 op",
        "rightsnone": "(-)",
        "revdelete-summary": "redigeringsbeskrivelse",
+       "rightslogentry-temporary-group": "$1 (midlertidig, indtil $2)",
        "feedback-adding": "Tilføjer kommentar til side...",
        "feedback-back": "Tilbage",
        "feedback-bugcheck": "Skønt! Men tjek venligst, at det ikke er en af de [$1 kendte fejl].",
index b96f8be..22aa69e 100644 (file)
        "permissionserrorstext-withaction": "Du bist aus {{PLURAL:$1|dem folgenden Grund|den folgenden Gründen}} nicht berechtigt, $2:",
        "contentmodelediterror": "Du kannst diese Version nicht bearbeiten, da das Inhaltsmodell <code>$1</code> vom aktuellen Inhaltsmodell der Seite <code>$2</code> abweicht.",
        "recreate-moveddeleted-warn": "<strong>Achtung: Du erstellst eine Seite, die bereits früher gelöscht wurde.</strong>\n\nBitte prüfe sorgfältig, ob die erneute Seitenerstellung den Richtlinien entspricht.\nZu deiner Information folgt das Lösch- und Verschiebungs-Logbuch mit der Begründung für die vorhergehende Löschung:",
-       "moveddeleted-notice": "Diese Seite wurde gelöscht. Zur Information folgt das Lösch- und Verschiebungs-Logbuch dieser Seite.",
-       "moveddeleted-notice-recent": "Leider wurde diese Seite kürzlich gelöscht (innerhalb der letzten 24 Stunden).\nZur Information wird das Lösch- und Verschiebungs-Logbuch für die Seite unten angezeigt.",
+       "moveddeleted-notice": "Diese Seite wurde gelöscht.\nZur Information folgt das Lösch- und Verschiebungs-Logbuch dieser Seite.",
+       "moveddeleted-notice-recent": "Diese Seite wurde kürzlich gelöscht (innerhalb der letzten 24 Stunden).\nZur Information folgt das Lösch- und Verschiebungs-Logbuch dieser Seite.",
        "log-fulllog": "Alle Logbucheinträge ansehen",
        "edit-hook-aborted": "Die Bearbeitung wurde ohne Erklärung durch eine Schnittstelle abgebrochen.",
        "edit-gone-missing": "Die Seite konnte nicht aktualisiert werden.\nSie wurde anscheinend gelöscht.",
        "rcfilters-invalid-filter": "Ungültiger Filter",
        "rcfilters-empty-filter": "Keine aktiven Filter. Es werden alle Beiträge angezeigt.",
        "rcfilters-filterlist-title": "Filter",
+       "rcfilters-highlightbutton-title": "Ergebnisse hervorheben",
+       "rcfilters-highlightmenu-title": "Eine Farbe auswählen",
        "rcfilters-filterlist-noresults": "Keine Filter gefunden",
        "rcfilters-filtergroup-registration": "Benutzerregistrierung",
        "rcfilters-filter-registered-label": "Angemeldet",
        "editcomment": "Die Änderungszusammenfassung lautet: <em>$1</em>.",
        "revertpage": "Änderungen von [[Special:Contributions/$2|$2]] ([[User talk:$2|Diskussion]]) wurden auf die letzte Version von [[User:$1|$1]] zurückgesetzt",
        "revertpage-nouser": "Änderungen von einem versteckten Benutzer rückgängig gemacht und letzte Version von {{GENDER:$1|[[User:$1|$1]]}} wiederhergestellt",
-       "rollback-success": "Die Änderungen von $1 wurden rückgängig gemacht und die letzte Version von $2 wurde wiederhergestellt.",
+       "rollback-success": "Die Änderungen von {{GENDER:$3|$1}} wurden rückgängig gemacht und die letzte Version von {{GENDER:$4|$2}} wurde wiederhergestellt.",
        "rollback-success-notify": "Bearbeitungen von $1 rückgängig gemacht;\nzurückgeändert auf die letzte Version von $2. [$3 Änderungen zeigen]",
        "sessionfailure-title": "Sitzungsfehler",
        "sessionfailure": "Es gab ein Problem bei der Übertragung deiner Benutzerdaten.\nDiese Aktion wurde daher sicherheitshalber abgebrochen, um eine falsche Zuordnung deiner Änderungen zu einem anderen Benutzer zu verhindern.\nBitte gehe zurück zur vorherigen Seite, lade sie erneut und versuche, den Vorgang erneut auszuführen.",
        "pageinfo-few-visiting-watchers": "Es könnte einen beobachtenden Benutzer geben oder nicht, der die letzten Bearbeitungen besucht hat",
        "pageinfo-redirects-name": "Anzahl der Weiterleitungen zu dieser Seite",
        "pageinfo-redirects-value": "$1",
-       "pageinfo-subpages-name": "Unterseiten dieser Seite",
+       "pageinfo-subpages-name": "Anzahl der Unterseiten dieser Seite",
        "pageinfo-subpages-value": "$1 ($2 {{PLURAL:$2|Weiterleitung|Weiterleitungen}}; $3 {{PLURAL:$3|Unterseite|Unterseiten}})",
        "pageinfo-firstuser": "Seitenersteller",
        "pageinfo-firsttime": "Datum der Seitenerstellung",
index 2b6ff4c..c791ecf 100644 (file)
@@ -33,7 +33,7 @@
                ]
        },
        "tog-underline": "Bınê gırey de xete bance:",
-       "tog-hideminor": "Vurnayışanê şenıkan pela vurnayışanê peyênan de bınımne",
+       "tog-hideminor": "Vırnayışanê peyênan ra vırnayışanê werdiyan bınımne",
        "tog-hidepatrolled": "Vurnayışanê qontrol kerdeyan perra vurnayışê peyêni de bınımne",
        "tog-newpageshidepatrolled": "Pelanê qontrol kerdeyan lista peranê  neweyan de bınımne",
        "tog-hidecategorization": "Pera kategorizasyoni bınımne",
        "delete": "Bestern",
        "deletethispage": "Na perrer bestern",
        "undeletethispage": "Na perer mebesterne",
-       "undelete_short": "{{PLURAL:$1|Yew vurnayışi|$1 Vurnayışan}} mestere",
+       "undelete_short": "{{PLURAL:$1|Yew vırnayışi|$1 Vırnayışan}} mestere",
        "viewdeleted_short": "{{PLURAL:$1|Jew vurnayış esternayi|$1 Vurnayışanê esternayan}} bımotne",
        "protect": "Bıstarnê",
        "protect_change": "bıvurne",
        "specialpage": "Perra xısusiye",
        "personaltools": "Hacetê şexsiy",
        "articlepage": "Pera zerreki bıvin",
-       "talk": "Diskusiyon",
+       "talk": "Werênayış",
        "views": "Asayışi",
        "toolbox": "Haceti",
        "tool-link-userrights": "Grubanê {{GENDER:$1|karberi}} bıvırnë",
        "summary": "Xulasa:",
        "subject": "Mewzu:",
        "minoredit": "No yew vırnayışo werdiyo",
-       "watchthis": "Bewni ena per",
+       "watchthis": "Şıma bewnê ena perre",
        "savearticle": "Perre qeyd ke",
        "savechanges": "Vırnayışan qeyd ke",
        "publishpage": "Perer bıhesırne",
        "missingsummary": "'''DİQET:''' Şıma jû xulasa nênuşte.\nEke şıma \"{{int:savearticle}}\" reyna bıtıknê, vırnayışê şıma bê xulasa qeyd beno.",
        "missingcommenttext": "Cêr de jû fıkır bınusên, şıma rê zehmet.",
        "missingcommentheader": "'''Diqet:''' Şıma seba nê fıkrvaci yew mewzu/sernuşte nênuşt.\nEke şıma reyna \"{{int:savearticle}}\" bıtıknê, vırnayışê şıa bê mewzu/sernuşte do qeyd bo.",
-       "summary-preview": "Verqaytê xulasa:",
+       "summary-preview": "Verasayışê xulasa:",
        "subject-preview": "Verqaytê mewzu:",
        "previewerrortext": "Verasayışê vırnayışê şıma de yew xeta veciya miyan.",
        "blockedtitle": "Karber blokekerdeo",
        "right-createtalk": "Pela werênayışi vıraze",
        "right-createaccount": "Hesabê karberi vıraze",
        "right-autocreateaccount": "Xarici yew name dê karberi ya ronıştış ake",
-       "right-minoredit": "Vurnayışan qıckek nışan bıde.",
+       "right-minoredit": "Vırnayışan zey werdi nışan bıde.",
        "right-move": "Pele bere",
        "right-move-subpages": "Pele be bınpelanê cı ra pia bere",
        "right-move-rootuserpages": "Pelanê kaberiê rıstımi bere",
        "right-deletedtext": "Mabênê newede vurnayışanê esterıtiyan de qaytê nuştey esterıtey u vurnayışan ke",
        "right-browsearchive": "Pelanê esterıteyan bıgeyre",
        "right-undelete": "Yew pela esterıtiye peyser biya",
-       "right-suppressrevision": "İdarekeran ra miyanki, newede vurnayışan de qayt ke u newede vıraze",
+       "right-suppressrevision": "Yew karber ra çım ra viyarnayışanê perran bıvênê, bınımnê u bımocnê.",
        "right-viewsuppressed": "İdarekeran ra miyanki newede vurnayışan de qayt ke",
        "right-suppressionlog": "Rocekanê xasan bıvêne",
        "right-block": "Karberanê binan karê vurnayışi ra bloke bıke",
        "recentchanges-submit": "Bımotne",
        "rcnotefrom": "Cêr de <strong>$2</strong> ra nata {{PLURAL:$5|vurnayışiyê}} asenê (tewr vêşi <strong>$1</strong> asenê) <strong>$3, $4</strong>",
        "rclistfrom": "$3 sehat $2 ra tepiya vurnayışanê neweyan bımotne",
-       "rcshowhideminor": "Vurnayışê werdiy $1",
+       "rcshowhideminor": "Vırnayışê werdiy $1",
        "rcshowhideminor-show": "Bımotne",
        "rcshowhideminor-hide": "Bınımne",
        "rcshowhidebots": "botan $1",
        "rc-enhanced-hide": "Melumat bınımne",
        "rc-old-title": "\"$1\"i orcinalê cı vıraşt",
        "recentchangeslinked": "Vırnayışê bestiyaey",
-       "recentchangeslinked-feed": "Vurnayışê elaqeyıni",
-       "recentchangeslinked-toolbox": "Vurnayışê elaqeyıni",
+       "recentchangeslinked-feed": "Vırnayışê bestiyaey",
+       "recentchangeslinked-toolbox": "Vırnayışê bestiyaey",
        "recentchangeslinked-title": "Heqa \"$1\" de vurnayışi",
        "recentchangeslinked-summary": "Lista cêrêne, pela bêlikerdiye rê (ya zi karberanê kategoriya bêlikerdiye rê) pelanê gırêdayoğan de lista de vurnayışê peyênana.\n[[Special:Watchlist|Lista şımaya seyrkedışi de]] peli be nuşteyo '''qolınd''' bêli kerdê.",
        "recentchangeslinked-page": "Namey perrer:",
        "watchlistanontext": "qey vurnayişê maddeya listeya temaşakerdiş ronıştış akerê",
        "watchnologin": "Şıma cıkewtış nêvıraşto",
        "addwatch": "Lista seyrkerdışi ke",
-       "addedwatchtext": "Ma pele \"[[:$1]]\" zerri [[Special:Watchlist|listeya seyri]] tı kerd de.\nEna deme ra, ma qe vurnayışan ser ena pele tı haberdar keni.",
+       "addedwatchtext": "\"[[:$1]]\" u perra cıya werênayışi [[Special:Watchlist|lista şımaya ewniyayışi]] rê ameyo cıkerdış.",
        "addedwatchtext-short": "Pera $1`i çebyê listeya seyran de şıma",
        "removewatch": "Lista seyrkerdışi ra wedare",
        "removedwatchtext": "Ena pela \"[[:$1]]\" biya wedariya [[Special:Watchlist|listeyê seyr-kerdışi şıma]].",
        "removedwatchtext-short": "Pera $1`i listeya seyran de şıma ra wedari yê",
        "watch": "Seyr ke",
-       "watchthispage": "Bewni ena per",
+       "watchthispage": "Şıma bewnê ena perre",
        "unwatch": "Teqib meke",
        "unwatchthispage": "temaşa kerdışê peli vındarn.",
        "notanarticle": "mebhesê peli niyo",
        "wlshowhidebots": "boti",
        "wlshowhideliu": "karberê qeydıni",
        "wlshowhideanons": "karberê anonimi",
-       "wlshowhidepatr": "vurnayışê pawıteyi",
-       "wlshowhidemine": "vurnayışê mı",
+       "wlshowhidepatr": "Vırnayışê çım ra viyarniyaey",
+       "wlshowhidemine": "vırnayışê mı",
        "wlshowhidecategorization": "kategorizasyonê pele",
        "watchlist-options": "Tercihê liste da seyri",
        "watching": "Seyr ke...",
        "deleteotherreason": "Sebebo bin:",
        "deletereasonotherlist": "Sebebo bin",
        "deletereason-dropdown": "* Sebebê esterıtışê pêroyi\n** Vurnayışo nêwaşte (spam)\n** Vandalizm\n** İxlalê heqa telifi\n** Waştışê nuştoği\n** Oryantasyono xırabe",
-       "delete-edit-reasonlist": "Sebebê vurnayışan bıvurne",
+       "delete-edit-reasonlist": "Sebebê vırnayışan bıvurnê",
        "delete-toobig": "no pel, pê $1 {{PLURAL:$1|tene vuriyayiş|tene vuriyayiş}}i wayirê yew tarixo kehen o.\nqey hewna nêşiyayişi wina pelani u {{SITENAME}}nêxerebnayişê keyepeli yew hed niyaya ro.",
        "delete-warning-toobig": "no pel wayirê tarixê vurnayiş ê derg o, $1 {{PLURAL:$1|revizyonê|revizyonê}} seri de.\nhewn a kerdışê ıney {{SITENAME}} şuxul bıne gırano;\nbı diqqet dewam kerê.",
        "deleteprotected": "Şıma nêşenê ena perer esternê,  çıkı per starya ya.",
        "tooltip-save": "Vurnayışanê xo qeyd ke",
        "tooltip-publish": "Vurnayışê xo vıla kı",
        "tooltip-preview": "Vurnayışanê xo çım ra bıviyarnê. Qeydkerdış ra ver bıgurê cı!",
-       "tooltip-diff": "Metni sero vurnayışan mocneno",
+       "tooltip-diff": "Kamci vırnayışê ke şıma nuştey sero kerdê, inan bıvênê.",
        "tooltip-compareselectedversions": "Ena per de ferqê rewziyonan de dı weçinaya bıvinê",
        "tooltip-watch": "Ena pele lista xoya seyrkerdışi ke",
        "tooltip-watchlistedit-normal-submit": "Sernuşteyan wedare",
        "pageinfo-firsttime": "Vıraştena tarixê perrer",
        "pageinfo-lastuser": "Vurnayoğo peyên",
        "pageinfo-lasttime": "Deme u vurnayışo peyên",
-       "pageinfo-edits": "Amarina vurnayışan pêro",
+       "pageinfo-edits": "Amarê vırnayışano pêroyi",
        "pageinfo-authors": "Amarina nuştekaran pêro",
        "pageinfo-recent-edits": "Amariya vurnayışan ($1 ra nata)",
        "pageinfo-recent-authors": "Amarina nuştekaran pêro",
        "specialpages-group-maintenance": "Raporê pawıtışi",
        "specialpages-group-other": "Pelê xısusiyê bini",
        "specialpages-group-login": "Dekew / hesab vıraz",
-       "specialpages-group-changes": "Vurnayışê peyêni û qeydi",
+       "specialpages-group-changes": "Vırnayışê peyêni u qeydi",
        "specialpages-group-media": "Raporê medya û barkerdışi",
        "specialpages-group-users": "Karberi u heqê inan",
        "specialpages-group-highuse": "Peleyê ke vêşi karênê",
index 3d6e462..93c33eb 100644 (file)
        "deleting-backlinks-warning": "<strong>Προσοχή:</strong>  [[Special:WhatLinksHere/{{FULLPAGENAME}}|Άλλες σελίδες]] συνδέουν ή ενσωματώνουν τη σελίδα που πρόκειται να διαγράψετε.",
        "rollback": "Επαναφορά επεξεργασιών",
        "rollbacklink": "αναστροφή",
-       "rollbacklinkcount": "Î\95Ï\80αναÏ\86οÏ\81ά $1 {{PLURAL:$1|επεξεργασίας|επεξεργασιών}}",
-       "rollbacklinkcount-morethan": "εÏ\80αναÏ\86οÏ\81ά περισσότερων από $1 {{PLURAL:$1|επεξεργασία|επεξεργασίες}}",
+       "rollbacklinkcount": "Î\91ναÏ\83Ï\84Ï\81οÏ\86ή $1 {{PLURAL:$1|επεξεργασίας|επεξεργασιών}}",
+       "rollbacklinkcount-morethan": "αναÏ\83Ï\84Ï\81οÏ\86ή περισσότερων από $1 {{PLURAL:$1|επεξεργασία|επεξεργασίες}}",
        "rollbackfailed": "Η επαναφορά απέτυχε.",
        "cantrollback": "Δεν είναι δυνατή η αναίρεση αυτής της αλλαγής, πρόκειται για την αρχική ενέργεια δημιουργίας της σελίδας.",
        "alreadyrolled": "Αδύνατον να αναιρεθεί η τελευταία αλλαγή της σελίδας [[:$1]] από το χρήστη ([[User:$2|$2]] ([[User talk:$2|Συζήτηση]]){{int:pipe-separator}}[[Special:Contributions/$2|{{int:contribslink}}]]), διότι κάποιος έχει ήδη αναιρέσει την αλλαγή ή έχει αλλάξει εκ νέου τη σελίδα.\n\nΤελευταία αλλαγή από το χρήστη ([[User:$3|$3]] ([[User talk:$3|Συζήτηση]]){{int:pipe-separator}}[[Special:Contributions/$3|{{int:contribslink}}]]).",
        "show-big-image-preview-differ": "Το μέγεθος αυτής της $3 προεπισκόπησης αυτού του $2 το αρχείο: $1.",
        "show-big-image-other": "Άλλες {{PLURAL:$2|ανάλυση|αναλύσεις}}: $1.",
        "show-big-image-size": "$1 × $2 εικονοστοιχεία",
-       "file-info-gif-looped": "περιτυλιγμένο",
-       "file-info-gif-frames": "$1 {{PLURAL:$1|πλαίσιο|πλαίσια}}",
-       "file-info-png-looped": "Σε Î¬Ï\80ειÏ\81ο Î²Ï\81Ï\8cγÏ\87ο",
+       "file-info-gif-looped": "κυκλικά επαναλαμβανόμενο",
+       "file-info-gif-frames": "$1 {{PLURAL:$1|καρέ}}",
+       "file-info-png-looped": "κÏ\85κλικά ÎµÏ\80αναλαμβανÏ\8cμενο",
        "file-info-png-repeat": "έπαιξε $1 {{PLURAL:$1|φορά|φορές}}",
        "file-info-png-frames": "$1 {{PLURAL:$1|πλαίσιο|πλαίσια}}",
        "file-no-thumb-animation": "'''Σημείωση: λόγω τεχνικών περιορισμών, μικρογραφίες αυτού του τύπου αρχείου δεν θα είναι κινούμενες.'''",
index 53eceed..abee4a9 100644 (file)
        "rcfilters-invalid-filter": "Invalid filter",
        "rcfilters-empty-filter": "No active filters. All contributions are shown.",
        "rcfilters-filterlist-title": "Filters",
+       "rcfilters-highlightbutton-title": "Highlight results",
+       "rcfilters-highlightmenu-title": "Select a color",
        "rcfilters-filterlist-noresults": "No filters found",
        "rcfilters-filtergroup-registration": "User registration",
        "rcfilters-filter-registered-label": "Registered",
        "editcomment": "The edit summary was: <em>$1</em>.",
        "revertpage": "Reverted edits by [[Special:Contributions/$2|$2]] ([[User talk:$2|talk]]) to last revision by [[User:$1|$1]]",
        "revertpage-nouser": "Reverted edits by a hidden user to last revision by {{GENDER:$1|[[User:$1|$1]]}}",
-       "rollback-success": "Reverted edits by $1;\nchanged back to last revision by $2.",
+       "rollback-success": "Reverted edits by {{GENDER:$3|$1}};\nchanged back to last revision by {{GENDER:$4|$2}}.",
        "rollback-success-notify": "Reverted edits by $1;\nchanged back to last revision by $2. [$3 Show changes]",
        "sessionfailure-title": "Session failure",
        "sessionfailure": "There seems to be a problem with your login session;\nthis action has been canceled as a precaution against session hijacking.\nGo back to the previous page, reload that page and then try again.",
index 7f32ddd..5e31873 100644 (file)
        "rollback-success": "Revertidas las ediciones de $1; recuperada la última versión de $2.",
        "rollback-success-notify": "Revertidas las ediciones de $1 hasta la última revisión de $2. [$3 Ver cambios]",
        "sessionfailure-title": "Error de sesión",
-       "sessionfailure": "Parece que hay un problema con tu sesión;\nesta acción ha sido cancelada como medida de precaución contra secuestros de sesión.\nPor favor, pulsa «Atrás», recarga la página de la que viniste e inténtalo de nuevo.",
+       "sessionfailure": "Parece que hay un problema con tu sesión;\nse ha cancelado esta acción como medida de precaución contra el robo de sesiones.\nVuelve a la página anterior, recárgala e inténtalo de nuevo.",
        "changecontentmodel": "Cambiar el modelo de contenido de una página",
        "changecontentmodel-legend": "Cambiar el modelo de contenido",
        "changecontentmodel-title-label": "Título de página",
index 824ec6f..eb89f59 100644 (file)
        "createacct-email-ph": "Sisesta e-posti aadress",
        "createacct-another-email-ph": "Sisesta e-posti aadress",
        "createaccountmail": "Kasuta juhuslikku parooli ja saada see määratud e-posti aadressile",
+       "createaccountmail-help": "Saab kasutada konto loomiseks teisele kasutajale ilma parooli teada saamata.",
        "createacct-realname": "Pärisnimi (valikuline)",
        "createaccountreason": "Põhjus:",
        "createacct-reason": "Põhjus",
        "createacct-reason-ph": "Miks lood teist kontot?",
+       "createacct-reason-help": "Sõnum, mida näidatakse konto loomise logis",
        "createacct-submit": "Loo konto",
        "createacct-another-submit": "Loo konto",
+       "createacct-continue-submit": "Jätka konto loomist",
+       "createacct-another-continue-submit": "Jätka konto loomist",
        "createacct-benefit-heading": "{{SITENAME}} on sinusuguste inimeste tehtud.",
        "createacct-benefit-body1": "{{PLURAL:$1|muudatus|muudatust}}",
        "createacct-benefit-body2": "{{PLURAL:$1|lehekülg|lehekülge}}",
        "nocookiesnew": "Kasutajakonto loodi, aga sa ei ole sisse logitud, sest {{SITENAME}} kasutab kasutajate tuvastamisel küpsiseid. Sinu brauseris on küpsised keelatud. Palun sea küpsised lubatuks ja logi siis oma vastse kasutajanime ning parooliga sisse.",
        "nocookieslogin": "{{SITENAME}} kasutab kasutajate tuvastamisel küpsiseid. Sinu brauseris on küpsised keelatud. Palun sea küpsised lubatuks ja proovi siis uuesti.",
        "nocookiesfornew": "Kasutajakonto jäi loomata, kuna me ei saanud selle allikat kindlaks teha.\nVeendu, et sul on küpsised lubatud, taaslaadi see lehekülg ja proovi uuesti.",
+       "createacct-loginerror": "Konto on edukalt loodud, aga automaatselt ei õnnestunud sisse logida. Et jätkata, [[Special:UserLogin|logi palun sisse käsitsi]].",
        "noname": "Sa ei sisestanud kasutajanime lubataval kujul.",
        "loginsuccesstitle": "Sisse logitud",
        "loginsuccess": "Oled sisse loginud. Sinu kasutajanimi on \"$1\".",
        "missingcommenttext": "Palun sisesta siit allapoole kommentaar.",
        "missingcommentheader": "<strong>Meeldetuletus:</strong> Sa pole kirjutanud kommentaarile teemat.\nKui klõpsad uuesti \"{{int:savearticle}}\", salvestatakse su kommentaar ilma teemata.",
        "summary-preview": "Resümee eelvaade:",
-       "subject-preview": "Alaosa pealkirja eelvaade:",
+       "subject-preview": "Resümee eelvaade:",
        "previewerrortext": "Sinu muudatuste eelvaatluse juures esines tõrge.",
        "blockedtitle": "Kasutaja on blokeeritud",
        "blockedtext": "'''Sinu kasutajanimi või IP-aadress on blokeeritud.'''\n\nBlokeeris $1.\nTema põhjendus on järgmine: ''$2''.\n\n* Blokeeringu algus: $8\n* Blokeeringu lõpp: $6\n* Sooviti blokeerida: $7\n\nKüsimuse arutamiseks võid pöörduda kasutaja $1 või mõne teise [[{{MediaWiki:Grouppage-sysop}}|administraatori]] poole.\n\nPane tähele, et sa ei saa kasutajale teadet saata, kui sa pole kinnitanud oma [[Special:Preferences|eelistuste lehel]] kehtivat e-posti aadressi.\n\nSinu praegune IP-aadress on $3 ning blokeeringu number on #$5. Lisa need andmed kõigile järelepärimistele, mida kavatsed teha.",
index 829bccc..dcc7244 100644 (file)
        "searcharticle": "برو",
        "history": "تاریخچهٔ صفحه",
        "history_short": "تاریخچه",
+       "history_small": "تاریخچه",
        "updatedmarker": "به‌روزشده از آخرین باری که سرزده‌ام",
        "printableversion": "نسخهٔ قابل چاپ",
        "permalink": "پیوند پایدار",
        "search-interwiki-caption": "پروژه‌های خواهر",
        "search-interwiki-default": "نتایج از $1:",
        "search-interwiki-more": "(بیشتر)",
+       "search-interwiki-more-results": "نتایج بیشتر",
        "search-relatedarticle": "مرتبط",
        "searchrelated": "مرتبط",
        "searchall": "همه",
        "userrights-nodatabase": "پایگاه دادهٔ $1 وجود ندارد یا محلی نیست.",
        "userrights-changeable-col": "گروه‌هایی که می‌توانید تغییر دهید",
        "userrights-unchangeable-col": "گروه‌هایی که نمی‌توانید تغییر دهید",
+       "userrights-expiry-current": "منقضی$1",
+       "userrights-expiry-none": "دایمی است",
+       "userrights-expiry": "زمان سرآمدن:",
+       "userrights-expiry-existing": "زمان انقضای موجود: $2، $3",
+       "userrights-expiry-othertime": "زمانی دیگر:",
        "userrights-conflict": "تعارض دسترسی‌های کاربری! لطفاً بررسی کنید و تغییرات را تأیید کنید.",
        "group": "گروه:",
        "group-user": "کاربران",
index c5b45d9..1e72167 100644 (file)
        "search-file-match": "(vastaa tiedoston sisältöä)",
        "search-suggest": "Tarkoititko: $1",
        "search-rewritten": "Näytetään tulokset haulla $1. Haluatko hakea haulla $2?",
-       "search-interwiki-caption": "Sisarprojektit",
+       "search-interwiki-caption": "Sisarhankkeet",
        "search-interwiki-default": "Tulokset osoitteesta $1:",
        "search-interwiki-more": "(lisää)",
        "search-interwiki-more-results": "lisää tuloksia",
        "rcfilters-filterlist-title": "Suodattimet",
        "rcfilters-filterlist-noresults": "Ei löytynyt suodattimia",
        "rcfilters-filter-registered-label": "Rekisteröitynyt",
+       "rcfilters-filter-registered-description": "Kirjautuneet muokkaukset.",
+       "rcfilters-filter-unregistered-description": "Muokkaajat, jotka eivät ole kirjautuneet sisään.",
        "rcfilters-filter-editsbyself-label": "Omat muokkauksesi",
        "rcfilters-filter-editsbyself-description": "Muokkauksesi",
        "rcfilters-filter-editsbyother-label": "Muiden muokkaukset",
        "rcfilters-filter-bots-label": "Botti",
        "rcfilters-filter-bots-description": "Muokkaukset jotka tehty automaattisilla työkaluilla.",
        "rcfilters-filter-humans-label": "Ihminen (ei botti)",
+       "rcfilters-filtergroup-significance": "Merkitys",
        "rcfilters-filter-minor-label": "Pienet muutokset",
        "rcfilters-filter-major-label": "Ei-pienet muutokset",
        "rcfilters-filter-major-description": "Muokkauksia ei ole merkitty kuin pieniksi.",
index 214adf0..561e0dc 100644 (file)
        "rcfilters-invalid-filter": "Filtre non valide",
        "rcfilters-empty-filter": "Aucun filtre actif. Toutes les contributions sont affichées.",
        "rcfilters-filterlist-title": "Filtres",
+       "rcfilters-highlightbutton-title": "Mettre en valeur les résultats",
+       "rcfilters-highlightmenu-title": "Choisir une couleur",
        "rcfilters-filterlist-noresults": "Aucun filtre trouvé",
        "rcfilters-filtergroup-registration": "Inscription de l’utilisateur",
        "rcfilters-filter-registered-label": "Enregistré",
        "editcomment": "Le résumé de la modification était : <em>$1</em>.",
        "revertpage": "Révocation des modifications de [[Special:Contributions/$2|$2]] ([[User talk:$2|discussion]]) vers la dernière version de [[User:$1|$1]]",
        "revertpage-nouser": "Révocation des modifications par un utilisateur masqué à la dernière version par {{GENDER:$1|[[User:$1|$1]]}}",
-       "rollback-success": "Révocation des modifications effectuées par $1 ;\nrétablissement de la dernière version par $2.",
+       "rollback-success": "Révocation des modifications effectuées par {{GENDER:$3|$1}} ;\nrétablissement de la dernière version par {{GENDER:$4|$2}}.",
        "rollback-success-notify": "Modifications annulées par $1 ;\nretour à la dernière révision par $2. [$3 Voir les changements]",
        "sessionfailure-title": "Erreur de session",
        "sessionfailure": "Votre session de connexion semble avoir des problèmes ;\ncette action a été annulée en prévention d'un piratage de session.\nVeuillez cliquer sur « Précédent », rechargez la page d'où vous venez, puis réessayez.",
index bf6d8ef..5bd8f3b 100644 (file)
        "minoredit": "Seo mùthadh beag",
        "watchthis": "Cum sùil air an duilleag seo",
        "savearticle": "Sàbhail an duilleag",
+       "savechanges": "Sàbhail na dh’atharraich thu",
        "publishpage": "Foillsich an duilleag",
        "publishchanges": "Foillsich na mùthaidhean",
        "preview": "Ro-shealladh",
        "modifiedarticleprotection": "a dh'atharraich an ìre dìon de \"[[$1]]\"",
        "unprotectedarticle": "a neo-dhìon \"[[$1]]\"",
        "movedarticleprotection": "chaidh roghainn an dìona a ghluasad o \"[[$2]]\" gu \"[[$1]]\"",
+       "modifiedarticleprotection-comment": "Dh’atharraich {{GENDER:$2|ìre an dìon}} aig “[[$1]]”",
        "protect-title": "Atharraich an dìon airson \"$1\"",
        "protect-title-notallowed": "Seall an dìon airson \"$1\"",
        "prot_1movedto2": "chaidh [[$1]] a ghluasad gu [[$2]]",
index 6b10aa7..7047334 100644 (file)
        "selfredirect": "<strong>Atención:</strong> Está redirixindo esta páxina a si mesma.\nQuizais especificou incorrectamente a páxina de destino ou poida que estea a editar unha páxina errónea.\nSe preme en \"{{int:savearticle}}\" de novo, crearase a redireción de calquera xeito.",
        "missingcommenttext": "Por favor, escriba un comentario a continuación.",
        "missingcommentheader": "<strong>Aviso:</strong> Non escribiu ningún texto no asunto deste comentario.\nSe preme en \"{{int:savearticle}}\" de novo, a súa edición gardarase sen el.",
-       "summary-preview": "Vista previa do resumo:",
+       "summary-preview": "Vista previa do resumo de edición:",
        "subject-preview": "Vista previa do asunto:",
        "previewerrortext": "Produciuse un erro ao intentar previsualizar os cambios.",
        "blockedtitle": "O usuario está bloqueado",
        "saveusergroups": "Gardar os grupos {{GENDER:$1|do usuario|da usuaria}}",
        "userrights-groupsmember": "Membro de:",
        "userrights-groupsmember-auto": "Membro implícito de:",
-       "userrights-groups-help": "Pode cambiar os grupos aos que {{GENDER:$1|o usuario|a usuaria}} pertence:\n* Se a caixa ten un sinal (✓) significa que {{GENDER:$1|o usuario|a usuaria}} pertence a ese grupo.\n* Se, pola contra, non o ten, significa que non pertence.\n* Un asterisco (*) indica que non pode eliminar o grupo unha vez que o engadiu, e viceversa.",
+       "userrights-groups-help": "Pode cambiar os grupos aos que {{GENDER:$1|o usuario|a usuaria}} pertence:\n* Se a caixa ten un sinal (✓) significa que {{GENDER:$1|o usuario|a usuaria}} pertence a ese grupo.\n* Se, pola contra, non o ten, significa que non pertence.\n* Un asterisco (*) indica que non pode eliminar o grupo unha vez que o engadiu, e viceversa.\n* Un # indica que só se pode atrasar a data de caducidade deste grupo; non se pode adiantar.",
        "userrights-reason": "Motivo:",
        "userrights-no-interwiki": "Non ten os permisos necesarios para editar os dereitos de usuario noutros wikis.",
        "userrights-nodatabase": "A base de datos \"$1\" non existe ou non é local.",
        "userrights-expiry-options": "1 día:1 día,1 semana:1 semana,1 mes:1 mes,3 meses:3 meses,6 meses:6 meses,1 ano:1 ano",
        "userrights-invalid-expiry": "O tempo de caducidade para o grupo \"$1\" non é válido.",
        "userrights-expiry-in-past": "O tempo de caducidade para o grupo \"$1\" está no pasado.",
+       "userrights-cannot-shorten-expiry": "Non pode adiantar a data de caducidade do grupo \"$1\". Só os usuarios con permisos para engadir e eliminar este grupo poden adiantar datas de caducidade.",
        "userrights-conflict": "Hai un conflito na modificación dos dereitos de usuario! Por favor, revíseo e confirme os seus cambios.",
        "group": "Grupo:",
        "group-user": "Usuarios",
        "rcfilters-invalid-filter": "Filtro no válido",
        "rcfilters-empty-filter": "Non hai filtros activos. Móstranse tódalas contribucións.",
        "rcfilters-filterlist-title": "Filtros",
+       "rcfilters-highlightbutton-title": "Resaltar resultados",
+       "rcfilters-highlightmenu-title": "Seleccione unha cor",
        "rcfilters-filterlist-noresults": "Non se atoparon filtros",
        "rcfilters-filtergroup-registration": "Rexistro de usuario",
        "rcfilters-filter-registered-label": "Rexistrado",
index 5f09555..76e652a 100644 (file)
        "rcfilters-invalid-filter": "מסנן בלתי־תקין",
        "rcfilters-empty-filter": "אין מסננים פעילים. כל התרומות מוצגות.",
        "rcfilters-filterlist-title": "מסננים",
+       "rcfilters-highlightbutton-title": "הבלטת התוצאות",
+       "rcfilters-highlightmenu-title": "בחירת צבע",
        "rcfilters-filterlist-noresults": "לא נמצאו מסננים",
        "rcfilters-filtergroup-registration": "רישום העורכים",
        "rcfilters-filter-registered-label": "רשומים",
        "editcomment": "תקציר העריכה היה: <em>$1</em>.",
        "revertpage": "שוחזר מעריכות של [[Special:Contributions/$2|$2]] ([[User talk:$2|שיחה]]) לעריכה האחרונה של [[User:$1|$1]]",
        "revertpage-nouser": "שוחזר מעריכות של משתמש מוסתר לעריכה האחרונה של {{GENDER:$1|[[User:$1|$1]]}}",
-       "rollback-success": "שוחזר מעריכות של $1 לעריכה האחרונה של $2.",
+       "rollback-success": "שוחזר מעריכות של {{GENDER:$3|$1}} לעריכה האחרונה של {{GENDER:$4|$2}}.",
        "rollback-success-notify": "שוחזר מעריכות של $1 לעריכה האחרונה של $2. [$3 הצגת שינויים]",
        "sessionfailure-title": "בעיה בחיבור",
        "sessionfailure": "נראה שיש בעיה בחיבור שלך לאתר;\nפעולה זו בוטלה כאמצעי זהירות נגד התחזות לתקשורת ממחשבך.\nנא לחזור לדף הקודם, לטעון אותו מחדש ולנסות שוב.",
index 16a02f8..29e03e9 100644 (file)
@@ -77,7 +77,8 @@
                        "Ziyaurr",
                        "NehalDaveND",
                        "Susant purohit",
-                       "Jayprakash12345"
+                       "Jayprakash12345",
+                       "Dr. Shikha Jaggi"
                ]
        },
        "tog-underline": "कड़ियाँ अधोरेखन:",
        "rcfilters-filter-editsbyself-label": "आपके अपने संपादन",
        "rcfilters-filter-editsbyself-description": "आपके द्वारा संपादित",
        "rcfilters-filter-editsbyother-label": "दूसरों के द्वारा संपादित",
+       "rcfilters-filter-userExpLevel-newcomer-label": "अपरिचित",
+       "rcfilters-filter-userExpLevel-learner-label": "शिक्षार्थियों",
        "rcfilters-filter-bots-label": "बॉट",
        "rcfilters-filter-humans-label": "मानव (बॉट नहीं)",
        "rcfilters-filter-humans-description": "मानव संपादक द्वारा किए गए संपादन।",
index b85bc40..462ab06 100644 (file)
@@ -34,7 +34,8 @@
                        "Teoo3",
                        "Matma Rex",
                        "Vrhnje",
-                       "Ivi104"
+                       "Ivi104",
+                       "Сербијана"
                ]
        },
        "tog-underline": "Podcrtavanje poveznica",
        "searchbutton": "Traži",
        "go": "Kreni",
        "searcharticle": "Kreni",
-       "history": "Stare izmjene",
+       "history": "Povijest stranice",
        "history_short": "Stare izmjene",
        "history_small": "stare izmjene",
        "updatedmarker": "obnovljeno od posljednjeg posjeta",
        "toolbox": "Pomagala",
        "tool-link-userrights": "Promijeni {{GENDER:$1|suradnikove|suradničine}} grupe",
        "tool-link-userrights-readonly": "Vidi {{GENDER:$1|suradnikovu|suradničinu|suradničku}} pripadnost skupinama",
-       "tool-link-emailuser": "Pošalji e-poštu {{GENDER:$1|suradniku|suradnici}}",
+       "tool-link-emailuser": "Pošalji {{GENDER:$1|suradniku|suradnici}} e-poruku",
        "userpage": "Vidi suradnikovu stranicu",
        "projectpage": "Vidi stranicu o projektu",
        "imagepage": "Vidi stranicu datoteke",
        "passwordreset-emailsentemail": "Ako je ova adresa povezana s Vašim suradničkim računom, na nju će biti poslan podsjetnik na zaporku.",
        "passwordreset-invalidemail": "Nevaljala adresa e-pošte",
        "changeemail": "Promijeni ili izbriši e-mail adresu",
-       "changeemail-header": "Promijeni adresu e-pošte računa",
+       "changeemail-header": "Ispunite ovaj obrazac da biste promijenili svoju adresu e-pošte. Ukoliko želite ukloniti povezanost svoje adrese e-pošte i suradničkoga računa, prilikom popunjavanja obrasca ostavite prazno polje umjesto upisivanja nove adrese e-pošte.",
        "changeemail-no-info": "Morate biti prijavljeni da biste izravno pristupili ovoj stranici.",
        "changeemail-oldemail": "Trenutačna adresa e-pošte:",
        "changeemail-newemail": "Nova adresa e-pošte:",
        "changeemail-password": "Zaporka za projekt {{SITENAME}}:",
        "changeemail-submit": "Promijeni e-mail",
        "changeemail-throttled": "Nedavno ste se previše puta pokušali prijaviti.\nMolimo Vas pričekajte $1 prije nego što pokušate ponovno.",
+       "changeemail-nochange": "Molimo vas, upišite neku novu adresu e-pošte.",
        "bold_sample": "Podebljani tekst",
        "bold_tip": "Podebljani tekst",
        "italic_sample": "Kurzivni tekst",
        "missingsummary": "'''Podsjetnik:''' Niste unijeli sažetak promjena. Ako ponovno kliknete na \"Sačuvaj stranicu\", Vaše će promjene biti snimljene bez sažetka.",
        "selfredirect": "<strong>Upozorenje:</strong> Stvarate preusmjeravanje na isti članak.\nMožda ste izabrali pogrješnu odredišnu stranicu za preusmjeravanje ili uređujete pogrješnu stranicu.\nAko pritisnete na \"{{int:savearticle}}\" još jednom, preusmjeravanje će svejedno biti stvoreno.",
        "missingcommenttext": "Molim unesite sažetak.",
-       "missingcommentheader": "'''Podsjetnik:''' Niste napisali sažetak ovog komentara. Ako ponovno kliknete \"{{int:savearticle}}\", Vaš će komentar biti snimljen bez sažetka.",
+       "missingcommentheader": "<strong>Podsjetnik:</strong> Niste napisali sažetak ovoga komentara. Ukoliko ponovo kliknete \"{{int:savearticle}}\", Vaš će komentar biti snimljen bez sažetka.",
        "summary-preview": "Pregled polja Sažetak:",
        "subject-preview": "Pregled teme:",
+       "previewerrortext": "Pri pokušaju prikazivanja pretpregleda vaših promjena došlo je do pogrješke.",
        "blockedtitle": "Suradnik je blokiran",
        "blockedtext": "'''Vaše suradničko ime ili IP adresa je blokirana'''\n\nBlokirao Vas je $1.\nRazlog blokiranja je sljedeći: ''$2''.\n\n* Početak blokade: $8\n* Istek blokade: $6\n* Ime blokiranog suradnika: $7\n\nMožete kontaktirati $1 ili jednog od [[{{MediaWiki:Grouppage-sysop}}|administratora]] kako bi Vam pojasnili razlog blokiranja.\n\nPrimijetite da ne možete koristiti opciju \"Pošalji mu e-poruku\" ako niste upisali valjanu adresu e-pošte u Vašim [[Special:Preferences|suradničkim postavkama]] i ako niste u tome onemogućeni prilikom blokiranja.\n\nVaša trenutačna IP adresa je $3, a oznaka bloka #$5. Molimo navedite ovaj broj kod svakog upita vezano za razlog blokiranja.",
        "autoblockedtext": "Vaša IP adresa automatski je blokirana zbog toga što ju je koristio drugi suradnik, kojeg je blokirao $1.\nRazlog blokiranja je sljedeći:\n\n:''$2''\n\n* Početak blokade: $8\n* Blokada istječe: $6\n* Ime blokiranog suradnika: $7\n\nMožete kontaktirati $1 ili jednog od [[{{MediaWiki:Grouppage-sysop}}|administratora]] kako bi Vam pojasnili razlog blokiranja.\n\nPrimijetite da ne možete rabiti opciju \"Pošalji mu e-poruku\" ako niste upisali valjanu adresu e-pošte u Vašim [[Special:Preferences|suradničkim postavkama]] i ako niste u tome onemogućeni prilikom blokiranja.\n\nVaša trenutačna IP adresa je $3, a oznaka bloka #$5. Molimo navedite ovaj broj kod svakog upita vezano za razlog blokiranja.",
        "yourdiff": "Razlike",
        "copyrightwarning": "Molimo uočite da se svi doprinosi {{SITENAME}} smatraju objavljenima pod uvjetima $2 (vidi $1 za detalje). Ako ne želite da se Vaše pisanje nemilosrdno uređuje i slobodno raspačava, nemojte ga ovamo slati.<br />\nTakođer nam obećavate da ste ovo sami napisali, ili da ste to prepisali iz nečeg što je u javnom vlasništvu ili pod sličnom slobodnom licencijom.\n'''NE POSTAVLJAJTE RADOVE ZAŠTIĆENE AUTORSKIM PRAVIMA BEZ DOPUŠTENJA!'''",
        "copyrightwarning2": "Molimo uočite da svi suradnici mogu mijenjati sve doprinose na {{SITENAME}}. Ako ne želite da se Vaše pisanje nemilosrdno uređuje, nemojte ga slati ovdje.<br /> Također nam obećavate da ste ovo sami napisali, ili da ste to prepisali iz nečeg što je u javnom vlasništvu ili pod sličnom slobodnom licencijom (vidi $1 za detalje). '''NE POSTAVLJAJTE RADOVE ZAŠTIĆENE AUTORSKIM PRAVIMA BEZ DOPUŠTENJA!'''",
+       "editpage-cannot-use-custom-model": "Model sadržaja ove stranice ne može se mijenjati.",
        "longpageerror": "'''Pogrješka: Tekst koji ste unijeli dug je {{PLURAL:$1|jedan kilobajt|$1 kilobajta}}, što je više od maksimalno {{PLURAL:$2|jednog kilobajta|$2 kilobajta}}.'''\nNije ga moguće snimiti.",
        "readonlywarning": "'''UPOZORENJE: Baza podataka je zaključana zbog održavanja, pa trenutačno ne možete sačuvati svoje\npromjene. Najbolje je da kopirate i zaljepite tekst u tekstualnu datoteku te je snimite za kasnije.'''\n\nAdministrator je zaključao bazu iz razloga: $1",
        "protectedpagewarning": "'''UPOZORENJE: Ova stranica je zaključana i mogu je uređivati samo suradnici s administratorskim pravima.'''\nPosljednja stavka u evidenciji navedena je niže kao napomena:",
        "content-json-empty-object": "Prazan objekt",
        "content-json-empty-array": "Prazno polje",
        "duplicate-args-warning": "<strong>Upozorenje:</strong> [[:$1]] poziva na [[:$2]] s više od jedne vrijednosti za parametar \"$3\". Rabit će se samo posljednja navedena vrijednost.",
+       "duplicate-args-category": "Stranice u kojima se ponavljaju argumenti u predlošcima",
        "expensive-parserfunction-warning": "Upozorenje: Ova stranica sadrži previše opterećujućih poziva parserskih funkcija\n\nTrebala bi imati manje od $2 {{PLURAL:$2|poziva|poziva}}, sada ima {{PLURAL:$1|$1 poziv|$1 poziva}}.",
        "expensive-parserfunction-category": "Stranice s previše poziva opterećujućih parserskih funkcija",
        "post-expand-template-inclusion-warning": "Upozorenje: Veličina uključenih predložaka je prevelika.\nNeki predlošci neće biti uključeni.",
        "last": "pret",
        "page_first": "prva",
        "page_last": "zadnja",
-       "histlegend": "Uputa: (sad) = razlika od trenutačne inačice,\n(pret) = razlika od prethodne inačice, m = manja promjena",
+       "histlegend": "Izbor za usporedbu: označi kružiće pokraj dvije inačice koje želiš usporediti i pritisni \"Enter\" ili tipku na dnu.<br />\nUputa: <strong>({{int:cur}})</strong> = razlika od trenutačne inačice, <strong>({{int:last}})</strong> = razlika od prethodne inačice, <strong>{{int:minoreditletter}}</strong> = manja promjena.",
        "history-fieldset-title": "Pretraži povijest",
        "history-show-deleted": "Samo izbrisane",
        "histfirst": "najstarije",
        "mergehistory-empty": "Nema spojivih promjena (spajanje nije moguće).",
        "mergehistory-done": "$3 {{PLURAL:$3|izmjena|izmjene}} stranice $1 uspješno {{PLURAL:$3|spojena|spojene}} u povijest stranice [[:$2]].",
        "mergehistory-fail": "Nemoguće spojiti povijest stranica, molimo provjerite stranice i vremenske parametre.",
+       "mergehistory-fail-bad-timestamp": "Oznaka vremena nije valjana.",
        "mergehistory-no-source": "Izvorna stranica $1 ne postoji.",
        "mergehistory-no-destination": "Ciljna stranica $1 ne postoji.",
        "mergehistory-invalid-source": "Izvorna stranica mora imati valjani naziv.",
        "mergelog": "Evidencija spajanja povijesti stranica",
        "revertmerge": "Razdvoji",
        "mergelogpagetext": "Slijedi popis posljednjih spajanja povijesti stranica.",
-       "history-title": "Povijest izmjena stranice \"$1\"",
+       "history-title": "Povijest izmjena stranice »$1«",
        "difference-title": "Razlika između inačica stranice $1",
        "difference-title-multipage": "Razlika između stranica \"$1\" i \"$2\"",
        "difference-multipage": "(Razlika između stranica)",
        "userrights-editusergroup": "Uredi {{GENDER:$1|suradničke}} skupine",
        "userrights-viewusergroup": "Vidi {{GENDER:$1|suradničke}} skupine",
        "saveusergroups": "Spremi {{GENDER:$1|suradničke}} grupe",
-       "userrights-groupsmember": "Član:",
-       "userrights-groupsmember-auto": "Uključeni član:",
+       "userrights-groupsmember": "{{GENDER:$2|Pripadnik|Pripadnica}} skupina:",
+       "userrights-groupsmember-auto": "{{GENDER:$2|Pripadnik|Pripadnica}} obuhvaćenih skupina:",
        "userrights-groups-help": "Možete promijeniti skupine za ovog suradnika:\n* označena kućica pokazuje skupinu kojoj suradnik pripada;\n* neoznačena kućica pokazuje skupinu kojoj suradnik ne pripada;\n* zvjezdica (*) označava skupinu koju ne možete ukloniti kad ju jednom dodate, ili obratno.\n* povisilica (#) označava da rok valjanosti pripadanja skupini možete samo skratiti, a ne i produljiti",
        "userrights-reason": "Razlog:",
        "userrights-no-interwiki": "Nemate dopuštenje za uređivanje suradničkih prava na drugim wikijima.",
        "right-move": "Premještanje stranica",
        "right-move-subpages": "Premještanje stranica s njihovim podstranicama",
        "right-move-rootuserpages": "Premještanje osnovne stranice suradnika",
+       "right-move-categorypages": "premještanja kategorizacijskih stranica",
        "right-movefile": "Premještanje datoteka",
        "right-suppressredirect": "Ne raditi preusmjeravanje od starog imena prilikom premještanja stranice",
        "right-upload": "Postavljanje datoteka",
        "filehist-dimensions": "Dimenzije",
        "filehist-filesize": "Veličina datoteke",
        "filehist-comment": "Komentar",
-       "imagelinks": "Upotreba datoteke",
+       "imagelinks": "Uporaba datoteke",
        "linkstoimage": "{{PLURAL:$1|Sljedeća stranica povezuje|$1 sljedeće stranice povezuju|$1 sljedećih stranica povezuje}} na ovu datoteku:",
        "linkstoimage-more": "Više od $1 {{PLURAL:$1|stranice povezuje|stranica povezuje}} na ovu datoteku.\nSljedeći popis prikazuje {{PLURAL:$1|stranice koje|prvih $1 stranica koje}} vode na ovu datoteku.\n[[Special:WhatLinksHere/$2|Ovdje se nalazi]] potpuni popis.",
        "nolinkstoimage": "Nijedna stranica ne povezuje na ovu sliku.",
        "bad_image_list": "Rabi se sljedeći format:\n\nSamo retci koji počinju sa zvjezdicom su prikazani. Prva poveznica u retku mora biti poveznica na nevaljanu sliku.\nSvaka sljedeća poveznica u istom retku je izuzetak, npr. kod stranica gdje se slike pojavljuju ''inline''.",
        "variantname-sr-ec": "ćirilica",
        "variantname-sr-el": "latinica",
-       "metadata": "Metapodaci",
+       "metadata": "Metapodatci",
        "metadata-help": "Ova datoteka sadržava dodatne podatke koje je vjerojatno dodala digitalna kamera ili skener u procesu snimanja odnosno digitalizacije. Ako je datoteka mijenjana, podatci možda nisu u skladu sa stvarnim stanjem.",
        "metadata-expand": "Pokaži sve podatke",
        "metadata-collapse": "Sakrij dodatne podatke",
        "tags": "Valjane oznake izmjena",
        "tag-filter": "Filtar [[Special:Tags|oznaka]]:",
        "tag-filter-submit": "Filtar",
-       "tag-list-wrapper": "([[Special:Tags|{{PLURAL:$1|Oznaka|Oznake}}]]: $2)",
+       "tag-list-wrapper": "([[Special:Tags|{{PLURAL:$1|Oznaka|Oznake|Oznaka}}]]: $2)",
        "tag-mw-contentmodelchange": "promjena modela sadržaja",
        "tag-mw-contentmodelchange-description": "Uređivanja koja [https://www.mediawiki.org/wiki/Special:MyLanguage/Help:ChangeContentModel mijenjanju model sadržaja] stranice",
        "tags-title": "Oznake",
        "htmlform-time-invalid": "Unesena vrijednost nije prepoznati format vremena. Pokušajte koristiti format HH:MM:SS.",
        "htmlform-datetime-toohigh": "Uneseni datum i vrijeme su veći od $1",
        "logentry-delete-delete": "$1 je {{GENDER:$2|obrisao|obrisala}} stranicu $3",
-       "logentry-delete-delete_redir": "$1 je {{GENDER:$2|obrisao|obrisala}} preusmjeravanje $3 prepisivanjem",
+       "logentry-delete-delete_redir": "$1 je premještanjem {{GENDER:$2|pobrisao|pobrisala}} preusmjeravanje $3",
        "logentry-delete-restore": "$1 je {{GENDER:$2|vratio|vratila}} stranicu $3",
        "logentry-delete-event": "$1 je {{GENDER:$2|promijenio|promijenila}} vidljivost {{PLURAL:$5|zapisa u evidenciji|$5 zapisa u evidenciji}} na $3: $4",
        "logentry-delete-revision": "$1 je {{GENDER:$2|promijenio|promijenila}} vidljivost {{PLURAL:$5|uređivanja|$5 uređivanja}} na stranici $3: $4",
index c35f02b..a41dba2 100644 (file)
        "editcomment": "L'oggetto della modifica era: <em>$1</em>.",
        "revertpage": "Annullate le modifiche di [[Special:Contributions/$2|$2]] ([[User talk:$2|discussione]]), riportata alla versione precedente di [[User:$1|$1]]",
        "revertpage-nouser": "Annullate le modifiche di un utente nascosto, riportata alla versione precedente di {{GENDER:$1|[[User:$1|$1]]}}",
-       "rollback-success": "Annullate le modifiche di $1; pagina riportata all'ultima versione di $2.",
+       "rollback-success": "Annullate le modifiche di {{GENDER:$3|$1}}; pagina riportata all'ultima versione di {{GENDER:$4|$2}}.",
        "rollback-success-notify": "Annullate le modifiche di $1;\npagina riportata all'ultima revisione di $2. [$3 Mostra le modifiche]",
        "sessionfailure-title": "Sessione fallita",
        "sessionfailure": "Si è verificato un problema nella sessione che identifica l'accesso; il sistema non ha eseguito il comando impartito per precauzione. Tornare alla pagina precedente con il tasto 'Indietro' del proprio browser, ricaricare la pagina e riprovare.",
index 7940c0a..52ff8e6 100644 (file)
        "allpages": "모든 문서 목록",
        "nextpage": "다음 문서 ($1)",
        "prevpage": "이전 문서 ($1)",
-       "allpagesfrom": "다음으로 시작하는 문서 보기:",
-       "allpagesto": "다음으로 끝나는 문서 보기:",
+       "allpagesfrom": "다음으로 시작하는 문서 표시:",
+       "allpagesto": "다음으로 끝나는 문서 표시:",
        "allarticles": "모든 문서",
        "allinnamespace": "$1 이름공간의 모든 문서",
        "allpagessubmit": "보기",
-       "allpagesprefix": "다음으로 시작하는 문서 보기:",
+       "allpagesprefix": "다음 접두어로 시작하는 문서 표시:",
        "allpagesbadtitle": "주어진 문서 제목이 잘못되었거나 다른 사이트로 연결되는 인터위키가 있습니다.\n문서 제목에 사용할 수 없는 문자를 사용했을 수 있습니다.",
        "allpages-bad-ns": "{{SITENAME}}에서는 \"$1\" 이름공간을 사용하지 않습니다.",
        "allpages-hide-redirects": "넘겨주기 숨기기",
        "categories": "분류 목록",
        "categories-submit": "보이기",
        "categoriespagetext": "문서나 자료를 {{PLURAL:$1|포함하고 있는 분류}} 목록입니다.\n[[Special:UnusedCategories|사용되지 않는 분류]]는 여기에 보이지 않습니다.\n[[Special:WantedCategories|필요한 분류]]도 참조하세요.",
-       "categoriesfrom": "다음으로 시작하는 분류를 보여주기:",
+       "categoriesfrom": "다음으로 시작하는 분류 표시:",
        "deletedcontributions": "삭제된 사용자 기여",
        "deletedcontributions-title": "삭제된 사용자 기여",
        "sp-deletedcontributions-contribs": "기여",
        "linksearch-text": "\"*.wikipedia.org\"와 같이 와일드 카드를 사용할 수 있습니다.\n적어도 \"*.org\"와 같이 최상위 도메인을 입력해야 합니다.<br />\n지원하는 {{PLURAL:$2|프로토콜}}: $1 (프로토콜을 지정하지 않을 때 기본값은 http://)",
        "linksearch-line": "$1가 $2에서 링크됩니다.",
        "linksearch-error": "와일드카드는 주소의 처음 부분에만 사용될 수 있습니다.",
-       "listusersfrom": "다음으로 시작하는 사용자 보기:",
+       "listusersfrom": "다음으로 시작하는 사용자 표시:",
        "listusers-submit": "보기",
        "listusers-noresult": "사용자를 찾을 수 없습니다.",
        "listusers-blocked": "(차단됨)",
        "activeusers": "활동하는 사용자 목록",
        "activeusers-intro": "다음은 최근 $1{{PLURAL:$1|일}} 동안 활동한 사용자의 목록입니다.",
        "activeusers-count": "마지막 {{PLURAL:$3|$3일}} 사이의 {{PLURAL:$1|활동}} $1회",
-       "activeusers-from": "다음으로 시작하는 사용자를 보기:",
+       "activeusers-from": "다음으로 시작하는 사용자 표시:",
        "activeusers-groups": "그룹에 속한 사용자 표시:",
        "activeusers-excludegroups": "그룹에 속한 사용자 제외:",
        "activeusers-noresult": "사용자를 찾을 수 없습니다.",
-       "activeusers-submit": "활동하고 있는 사용자 보이기",
+       "activeusers-submit": "활동하고 있는 사용자 표시",
        "listgrouprights": "사용자 권한 목록",
        "listgrouprights-summary": "다음은 이 위키에 있는 사용자 권한 그룹의 목록입니다.\n각각의 권한에 대해서는 [[{{MediaWiki:Listgrouprights-helppage}}|추가 정보]]를 참조하세요.",
        "listgrouprights-key": "범례:\n* <span class=\"listgrouprights-granted\">부여된 권한</span>\n* <span class=\"listgrouprights-revoked\">해제된 권한</span>",
        "signature": "[[{{ns:user}}:$1|$2]] ([[{{ns:user_talk}}:$1|토론]])",
        "timezone-local": "로컬",
        "duplicate-defaultsort": "<strong>경고:</strong> 기본 정렬 키 \"$2\"가 이전의 기본 정렬 키 \"$1\"를 덮어쓰고 있습니다.",
-       "duplicate-displaytitle": "<strong>경고:</strong> \"$2\" 제목 표시는 기존의 표시되는 제목 \"$1\"을 덮어씁니다.",
+       "duplicate-displaytitle": "<strong>경고:</strong> \"$2\" 표시 제목은 먼저번의 표시 제목 \"$1\"을 덮어씁니다.",
        "restricted-displaytitle": "<strong>경고:</strong> 표시하려는 제목 \"$1\"은(는) 문서의 실제 제목과 동일하지 않으므로 무시되었습니다.",
        "invalid-indicator-name": "<strong>오류:</strong> 문서 상태 표시기의 <code>name</code> 특성은 비어 있지 않아야 합니다.",
        "version": "버전",
index b2f1051..2180402 100644 (file)
        "searchsuggest-containing": "dihundirîne...",
        "api-error-unknownerror": "Çewtiya nenas: \"$1\".",
        "duration-years": "$1 {{PLURAL:$1|sal}}",
+       "duration-centuries": "$1 {{PLURAL:$1|sedsal}}",
        "expand_templates_output": "Encam",
        "expand_templates_ok": "Baş e",
        "expand_templates_preview": "Pêşdîtin",
index bb1c25e..d54297a 100644 (file)
        "editcomment": "De Resumé vun der Ännerung war: <em>$1</em>.",
        "revertpage": "Ännerunge vum [[Special:Contributions/$2|$2]] ([[User talk:$2|Diskussioun]]) zréckgesat op déi lescht Versioun vum [[User:$1|$1]]",
        "revertpage-nouser": "Zréckgesaten Ännerungen duerch e verstoppte Benotzer op déi lescht Versioun vum {{GENDER:$1|[[User:$1|$1]]}}",
-       "rollback-success": "D'Ännerunge vum $1 goufen zréckgesat op déi lescht Versioun vum $2.",
+       "rollback-success": "D'Ännerunge vum {{GENDER:$3|$1}} goufen zréckgesat op déi lescht Versioun vum {{GENDER:$4|$2}}.",
        "rollback-success-notify": "Zréckgesat Ännerunge vum $1:\nzréckgeännert op déi lescht Versioun vum $2. [$3 Ännerunge weisen]",
        "sessionfailure-title": "Setzungsfeeler",
        "sessionfailure": "Et schéngt e Problem mat Ärer Loginseance ze ginn;\nDës Aktioun gouf aus Sécherheetsgrënn ofgebrach, fir ze verhënneren datt Är Seance piratéiert ka ginn.\nKlickt w.e.g. op \"Zréck\" a luet déi Säit vun där Dir komm sidd nei, a versicht et dann nach eng Kéier.",
index a204c39..aa8101a 100644 (file)
        "searcharticle": "Aiziet!",
        "history": "hronoloģija",
        "history_short": "Vēsture",
+       "history_small": "vēsture",
        "updatedmarker": "atjaunināti kopš pēdējā apmeklējuma",
        "printableversion": "Drukājama versija",
        "permalink": "Pastāvīgā saite",
        "views": "Apskates",
        "toolbox": "Rīki",
        "tool-link-userrights": "Mainīt {{GENDER:$1|dalībnieka|dalībnieces}} grupas",
+       "tool-link-userrights-readonly": "Apskatīt {{GENDER:$1|dalībnieka|dalībnieces}} grupas",
        "tool-link-emailuser": "Nosūtīt e-pastu {{GENDER:$1|šim dalībniekam|šai dalībniecei}}",
        "userpage": "Skatīt dalībnieka lapu",
        "projectpage": "Skatīt projekta lapu",
        "right-unblockself": "Atbloķēt sevi",
        "right-protect": "Izmainīt aizsargātās lapas un to aizsardzības līmeni",
        "right-editprotected": "Labot aizsargātās lapas (bez kaskādes aizsardzības)",
+       "right-editcontentmodel": "Labot lapas satura modeli",
        "right-editinterface": "Izmainīt dalībnieka interfeisu",
        "right-editusercssjs": "Izmainīt citu dalībnieku CSS un JS failus",
        "right-editusercss": "Izmainīt citu dalībnieku CSS failus",
        "action-upload_by_url": "augšupielādēt šo failu no URL",
        "action-writeapi": "izmantot rakstīto lietojumprogrammu saskarni",
        "action-delete": "izdzēst šo lapu",
-       "action-deleterevision": "izdzēst šo versiju",
-       "action-deletedhistory": "skatīt šīs lapas dzēsto hronoloģiju",
+       "action-deleterevision": "dzēst versijas",
+       "action-deletelogentry": "dzēst žurnāla ierakstus",
+       "action-deletedhistory": "skatīt šīs lapas dzēsto vēsturi",
        "action-browsearchive": "meklēt dzēstās lapas",
        "action-undelete": "atjaunot šo lapu",
        "action-suppressrevision": "pārskatīt un atjaunot šo slēpto versiju",
        "recentchanges-legend-heading": "<strong>Apzīmējumi:</strong>",
        "recentchanges-legend-newpage": "{{int:recentchanges-label-newpage}} (skatīt arī [[Special:NewPages|jaunās lapas]])",
        "recentchanges-submit": "Rādīt",
+       "rcfilters-invalid-filter": "Nederīgs filtrs",
+       "rcfilters-filterlist-title": "Filtri",
+       "rcfilters-filterlist-noresults": "Filtri nav atrasti",
+       "rcfilters-filtergroup-registration": "Lietotāja reģistrācija",
+       "rcfilters-filtergroup-changetype": "Izmaiņu veids",
+       "rcfilters-filter-pageedits-label": "Lapu labojumi",
+       "rcfilters-filter-pageedits-description": "Labojumi vikivietnes saturā, diskusijā, kategoriju aprakstos...",
+       "rcfilters-filter-newpages-label": "Lapu veidošana",
+       "rcfilters-filter-newpages-description": "Labojumi, kas veido jaunas lapas.",
+       "rcfilters-filter-categorization-label": "Kategoriju izmaiņas",
+       "rcfilters-filter-categorization-description": "Ieraksti par lapu pievienošanu vai noņemšanu no kategorijām.",
+       "rcfilters-filter-logactions-label": "Reģistrētās darbības",
+       "rcfilters-filter-logactions-description": "Administratīvās darbības, kontu veidošana, lapu dzēšana, augšupielādes...",
        "rcnotefrom": "Šobrīd redzamas izmaiņas kopš '''$2''' (parādītas ne vairāk par '''$1''').",
        "rclistfrom": "Parādīt jaunas izmaiņas kopš $3 $2",
        "rcshowhideminor": "$1 maznozīmīgos",
        "apihelp-no-such-module": "Modulis \"$1\" nav atrasts.",
        "apisandbox": "API smilškaste",
        "apisandbox-api-disabled": "API ir atspējots šajā tīmekļa vietnē.",
+       "apisandbox-unfullscreen": "Rādīt lapau",
+       "apisandbox-submit": "Izveidot pieprasījumu",
        "apisandbox-reset": "Notīrīt",
        "apisandbox-retry": "Mēģināt vēlreiz",
        "apisandbox-no-parameters": "Šo API modulim nav parametru.",
        "apisandbox-dynamic-parameters-add-placeholder": "Parametra nosaukums",
        "apisandbox-results": "Rezultāti",
        "apisandbox-request-url-label": "Pieprasījuma URL:",
+       "apisandbox-request-json-label": "Pieprasījuma JSON:",
        "apisandbox-request-time": "Pieprasījuma izpildes laiks: {{PLURAL:$1|$1 ms}}",
+       "apisandbox-continue": "Turpināt",
        "apisandbox-continue-clear": "Notīrīt",
+       "apisandbox-multivalue-all-namespaces": "$1 (visas vārdtelpas)",
+       "apisandbox-multivalue-all-values": "$1 (visas vērtības)",
        "booksources": "Grāmatu avoti",
        "booksources-search-legend": "Meklēt grāmatu avotus",
        "booksources-search": "Meklēt",
        "pageinfo-watchers": "Lapas uzraudzītāju skaits",
        "pageinfo-redirects-name": "Pāradresāciju skaits uz šo lapu",
        "pageinfo-subpages-name": "Šīs lapas apakšlapas",
+       "pageinfo-firstuser": "Lapas izveidotājs",
+       "pageinfo-firsttime": "Lapas izveides datums",
        "pageinfo-lastuser": "Pēdējais labotājs",
+       "pageinfo-lasttime": "Pēdējā labojuma datums",
        "pageinfo-edits": "Kopējais izmaiņu skaits",
        "pageinfo-authors": "Kopējais atsevišķu autoru skaits",
        "pageinfo-toolboxlink": "Lapas informācija",
        "pageinfo-category-pages": "Lapu skaits",
        "pageinfo-category-subcats": "Apakškategoriju skaits",
        "pageinfo-category-files": "Failu skaits",
+       "pageinfo-user-id": "Lietotāja ID",
        "markaspatrolleddiff": "Atzīmēt kā pārbaudītu",
        "markaspatrolledtext": "Atzīmēt šo lapu kā pārbaudītu",
        "markedaspatrolled": "Atzīmēta kā pārbaudīta",
        "patrol-log-page": "Pārbaudes reģistrs",
        "patrol-log-header": "Šis ir pārbaudīto versiju reģistrs.",
        "log-show-hide-patrol": "$1 pārbaudes reģistrs",
+       "confirm-markpatrolled-button": "Labi",
        "deletedrevision": "Izdzēstā vecā versija $1",
        "filedeleteerror-short": "Kļūda dzēšot failu: $1",
        "filedeleteerror-long": "Kļūdas, kas radās failu dzēšanas laikā:\n\n$1",
        "feedback-submit": "Iesniegt",
        "feedback-thanks": "Paldies! Jūsu atsauksmes ir ievietotas lapā \"[$2  $1]\".",
        "feedback-thanks-title": "Paldies!",
+       "feedback-useragent": "Lietotāja aģents:",
        "searchsuggest-search": "Meklēt {{SITENAME}}",
        "searchsuggest-containing": "Meklējamā frāze:",
        "api-error-unknown-warning": "Nezināms brīdinājums: $1",
        "api-error-unknownerror": "Nezināma kļūda: \"$1\"",
+       "duration-seconds": "$1 {{PLURAL:$1|sekundes|sekunde|sekundes}}",
+       "duration-minutes": "$1 {{PLURAL:$1|minūtes|minūte|minūtes}}",
+       "duration-hours": "$1 {{PLURAL:$1|stundas|stunda|stundas}}",
+       "duration-days": "$1 {{PLURAL:$1|dienas|diena|dienas}}",
+       "duration-weeks": "$1 {{PLURAL:$1|nedēļas|nedēļa|nedēļas}}",
+       "duration-years": "$1 {{PLURAL:$1|gadi|gads|gadi}}",
+       "duration-decades": "$1 {{PLURAL:$1|desmitgades|desmitgade|desmitgades}}",
+       "duration-centuries": "$1 {{PLURAL:$1|gadsimti|gadsimts|gadsimti}}",
+       "duration-millennia": "$1 {{PLURAL:$1|tūkstošgades|tūkstošgade|tūkstošgades}}",
        "limitreport-title": "Parsētāja profilēšanas dati:",
+       "limitreport-cputime-value": "$1 {{PLURAL:$1|sekundes|sekunde|sekundes}}",
+       "limitreport-walltime-value": "$1 {{PLURAL:$1|sekundes|sekunde|sekundes}}",
        "limitreport-postexpandincludesize-value": "$1/$2 {{PLURAL:$2|baiti|baits|baiti}}",
        "limitreport-templateargumentsize": "Veidnes argumenta izmērs",
        "limitreport-templateargumentsize-value": "$1/$2 {{PLURAL:$2|baiti|baits|baiti}}",
        "special-characters-group-gujarati": "Gudžarati",
        "mw-widgets-dateinput-no-date": "Nav izvēlēts datums",
        "mw-widgets-titleinput-description-new-page": "lapa vēl nepastāv",
+       "mw-widgets-categoryselector-add-category-placeholder": "Pievienot kategoriju...",
+       "sessionprovider-generic": "$1 sesijas",
        "authmanager-email-label": "E-pasts",
        "authmanager-email-help": "E-pasta adrese",
        "authmanager-realname-label": "Tavs īstais vārds",
index 92cfd99..a908160 100644 (file)
@@ -26,6 +26,7 @@
        "tog-watchdefault": "Hanaraka ny pejy ary ny rakitra ovaiko",
        "tog-watchmoves": "Hanaraka ny pejy ary ny rakitra ovaiko anarana",
        "tog-watchdeletion": "Hanaraka ny pejy ary ny rakitra voafafako",
+       "tog-watchuploads": "Ampiana amin'ny pejy arahako ireo rakitra vaovao nalefako",
        "tog-watchrollback": "Hanaraka pejy nanaovako famoana",
        "tog-minordefault": "Mariho ho madinika foana aloha ny fanovana rehetra",
        "tog-previewontop": "Asehoy alohan'ny boaty fanovana ny tsipalotra",
        "tagline": "Avy amin'i {{SITENAME}}",
        "help": "Fanoroana",
        "search": "Tadiavo",
+       "search-ignored-headings": "#<!-- Avelao ho toa izao ity andalana ity --> <pre>\n# Ny lohatenim-pizarana dia tsy horaharahiana amin'ny karoka.\n# Ny fiovana atao eto dia hihatra rehefa voasoratra ao amin'ny tondro ilay pejy miaraka amin'ilay lohateny.\n# Azonao atao ny famerenana an-tondro an'ilay pejy amin'ny alalan'ny fanovana tsy misy inona inona.\n# Ny rariteny dia ireo manaraka:\n# *Izay andalana rehetra manomboka amin'ny \"#\" dia resaka\n# *Izay andalana tsy fotsy dia lohateny tsy horaharahiana, iaraka amin'ny haben-tsoratra\nTsiahy\nRohy ivelany\nJereo koa\n#</pre> <!-- Avelao ho toa izao ity andalana ity -->",
        "searchbutton": "Tadiavo",
        "go": "Ndao",
        "searcharticle": "Tsidiho",
        "passwordreset-emailtext-user": "Nisy mpikambana mitondra anarana $1 eo amin'i {{SITENAME}} nangataka fampatsiahivana mikasika ny kaontinao eo amin'i {{SITENAME}} ($4). Manana io adiresy imailaka {{PLURAL:$3|io kaontim-pikambana io|ireo kaontim-pikambana ireo}} :\n\n$2\n\nHitsahatra afaka {{PLURAL:$5|iray|$5}} andro {{PLURAL:$3|io|ireo}} tenimiafina {{PLURAL:$3|io|ireo}}. Mila miditra dien'izao ianao izao ary mifidy tenimiafina vaovao. Raha tsy avy aminao ity hataka ity na efa nahatadidy ny tenimiafinao taloha ianao, ary raha tsy tianao hovaina intsony ilay tenimiafinao, dia azonao tsy raharahiana ity hafatra ity ary mampiasa ny tenimiafinao taloha.",
        "passwordreset-emailelement": "Anaram-pikambana : \n$1\n\nTenimiafina miserana : \n$2",
        "passwordreset-emailsentemail": "Lasa ny mailaka famerenana tenimiafina.",
+       "passwordreset-nocaller": "Mila manitsy mpiantso",
+       "passwordreset-nosuchcaller": "Tsy misy ilay mpiantso: $1",
        "changeemail": "Hanova ny adiresy imailaka",
        "changeemail-header": "Hanova ny adiresy imailak'ilay kaonty",
        "changeemail-no-info": "Mila tafiditra ianao vao avaka mijery ity pejy ity.",
        "yourdiff": "Fampitahana",
        "copyrightwarning": "Ny zavatra rehetra apetraka amin'ny {{SITENAME}} dia raisina ho azo adika malalaka araka ny fahazoan-dalana $2 (Jereo $1 ny fanazavana fanampiny). Raha toa ka tianao ho anao manokana ny tahirin-kevitra dia aleo tsy apetraka ato.\n\n<b>AZA MAMPIASA TAHIRINKEVITRA TSY NAHAZOAN-DALANA</b>",
        "copyrightwarning2": "Ny fandraisana anjara ao amin'i {{SITENAME}} dia azo ovaina ary fafan'ny mpikambana hafa. Raha tsy tianao ho ampiasainan, ovaina na zarazaraina ny soratrao, dia aza alefa eto ilay vokatr'asanao<br />\nNy zava-tsoratanao eto dia vokatr'asa naverinao soratana na nodikainao tany amina loharano ao amin'ny vala sarababem-bahoaka na loharano malalaka hafa (Jereo $1 ho an'ny antsipirihany).\n\n'''Aza mampiasa tahirin-kevitra tsy nahazoan-dalana!'''",
+       "editpage-cannot-use-custom-model": "Tsy mety ovaina ny modelim-botoatin'ity pejy ity.",
        "longpageerror": "'''Hadisoana : Ny tahirin-tsoratra nalefanao dia manana halava {{PLURAL:$1|iray|$1}} kilooktety, izay lava kokoa nohon'ny fetra avo indridra izay natao ho {{PLURAL:$2|iray|$2}} kilooktety.'''\nTsy afaka tahirizina ilay tahirin-tsoratra.",
        "readonlywarning": "'''FAMPITANDREMANA: Nohidiana noho ny antony fikolokoloana aloha ny banky angona,\nkoa tsy afaka mitahiry ny fanovana nataonao aloha ianao izao. Angamba tokony hanao Couper coller aloha\nianao dia tehirizo anaty rakitra ny fanovanao mandra-paha.'''\n\nNy mpandrindra nanidy ny banky angona dia nanome ny antony : <br />$1",
        "protectedpagewarning": "'''FAMPITANDREMANA:  Voaaro ity pejy ity ka ny mpikambana manana ny fahazoan-dàlana sysop ihany no afaka manova azy.'''",
        "invalid-content-data": "Data anaty votoatiny tsy miady amin'ny fepetra",
        "content-not-allowed-here": "Votoatiny ''$1'' voarara eo amin'ny pejy [[$2]]",
        "editwarning-warning": "Mety hahavery ny fanovana nataonao ny fialanao amin'ity pejy ity.\nRaha tafiditra ianao dia azonao esorina ity fampitandremana ity ao amin'ny fizarana \"{{int:prefs-editing}}\" ao amin'ny safidinao.",
+       "editpage-invalidcontentmodel-title": "Andrefim-botoatiny tsy zaka",
+       "editpage-invalidcontentmodel-text": "Andrefim-botoatiny \"$1\" tsy zaka.",
        "editpage-notsupportedcontentformat-title": "Tsy zaka io andrefim-botoatiny io",
        "editpage-notsupportedcontentformat-text": "Tsy zakan'ny maodelim-botoatiny $1 ny firafi-botoatiny $1",
        "content-model-wikitext": "wiki-soratra",
        "content-model-css": "CSS",
        "content-json-empty-object": "Zavatra foana",
        "content-json-empty-array": "Tabilao foana",
+       "deprecated-self-close-category": "Pejy mampiasa balizy HTML mihidy ho azy izay tsy azo raisina",
        "duplicate-args-category": "Pejy mampiasa dika mitovy hevitra amin'ny fiantsoana endrika",
        "expensive-parserfunction-warning": "Tandremo : Betsaka loatra ny fanantsoana ny tao parser.\n\nTsy maintsy latsaky ny $2 ny tao, kanefa misy $1. {{PLURAL:$2||}}",
        "expensive-parserfunction-category": "Pejy mampiasa be loatra ny tao parser",
        "search-interwiki-caption": "zandri-tetikasa",
        "search-interwiki-default": "Valiny amin'ny $1 :",
        "search-interwiki-more": "(be kokoa)",
+       "search-interwiki-more-results": "Valiny be kokoa",
        "search-relatedarticle": "voadinika",
        "searchrelated": "voadinika",
        "searchall": "rehetra",
        "youremail": "Imailaka:",
        "username": "{{GENDER:$1}}Anaram-pikambana :",
        "prefs-memberingroups": "Mpikambana{{GENDER:$2}} ao amin'ny vondrona{{PLURAL:$1}}:",
+       "group-membership-link-with-expiry": "$1 (hatramin'i $2)",
        "prefs-registration": "Daty fidirana :",
        "yourrealname": "Tena anarana marina:",
        "yourlanguage": "Tenim-pirenena:",
        "prefswarning-warning": "Efa nanova tamin'ny safidinao tsy mbola voatahiry ianao. Raha miala amin'ity pejy ity amin'ny alalan'ny fanindriana an'i \"$1\" ianao dia tsy ho voavao ny safidinao.",
        "prefs-tabs-navigation-hint": "Torohevitra: afaka mampiasa ny zana-tsipika havia ary havanana ianao ho an'ny fitetezana ny vakizoro ao amin'ny lisi-bakizoro",
        "userrights": "Fandrindràna ny fahefahan'ny mpikambana",
-       "userrights-lookup-user": "Handrindra vondrom-pikambana",
+       "userrights-lookup-user": "Hisafidy mpikambana",
        "userrights-user-editname": "Manomeza solonanarana:",
-       "editusergroup": "Hanova satan'ny {{GENDER:$1|}}mpikambana",
+       "editusergroup": "Hampiditra vondrom-pikambana",
        "editinguser": "Fanovana ny zon'ny mpikambana <strong>{{GENDER:$1|}}[[User:$1|$1]]</strong> $2",
        "userrights-editusergroup": "Hanova vondrom-pikambana",
        "saveusergroups": "{{GENDER:$1|}}Tehirizo ny vondrom-pikambana",
        "userrights-changeable-col": "Ny gropy azonao ovaina",
        "userrights-unchangeable-col": "Ny gropy tsy azonao ovaina",
        "userrights-expiry-current": "Mitsahatra ny $1",
+       "userrights-expiry-none": "Tsy mitsahatra",
        "userrights-expiry": "Fitsaharana:",
+       "userrights-expiry-existing": "Fotoam-pitsaharana ankehitriny: $3, $2",
+       "userrights-expiry-othertime": "Fotoana hafa:",
+       "userrights-expiry-options": "1 andro:1 day,herinandro:1 week,1 volana:1 month,3 volana:3 months,6 volana:6 months,herintaona:1 year",
+       "userrights-invalid-expiry": "Tsy azo raisina ny fotoam-pitsaharana ho an'ny vondrona \"$1\".",
        "userrights-conflict": "Fifandonana fanovana zom-pikambana! Avereno vakiana ary marino ny fanovanao.",
        "group": "Gropy :",
        "group-user": "Mpikambana",
        "grant-group-watchlist-interaction": "Mifanakalo amin'ny lisitry ny pejy arahanao",
        "grant-group-email": "Mandefa mailaka",
        "grant-group-high-volume": "Manao zavatra haingana",
+       "grant-group-customization": "Fikirakirana ary safidy",
        "grant-group-administration": "Hanao asam-pandrindrana",
        "grant-group-other": "Manao hetsika maro samihafa",
        "grant-blockusers": "Manakana sy manala sakan'ny mpikambana",
        "rcfilters-invalid-filter": "Sivana tsy azo raisina",
        "rcfilters-empty-filter": "Tsy misy sivana miasa. Aseho avokoa ireo fandraisan'anjara.",
        "rcfilters-filterlist-title": "Sivana",
+       "rcfilters-highlightbutton-title": "Hampibaribary ny valiny",
+       "rcfilters-highlightmenu-title": "Hisafidy loko",
        "rcfilters-filterlist-noresults": "Tsy nahitana sivana",
        "rcfilters-filtergroup-registration": "Fisoratan'ny mpikambana",
        "rcfilters-filter-registered-label": "Nisoratra anarana",
index 8839a78..ed783f1 100644 (file)
        "specialpages-group-pagetools": "Лаштык ӱзгар-влак",
        "specialpages-group-redirects": "Вес вере колтышо спецлаштык-влак",
        "external_image_whitelist": " #Оставьте эту строчку такой, как она есть<pre>\n#Разместите здесь фрагменты регулярных выражений (ту часть, что находится между //)\n#они будут соотнесены с URL внешних изображений.\n#Подходящие будут показаны как изображения, остальные будут показаны как ссылки на изображения.\n#Строки, начинающиеся с # считаются комментариями.\n#Строки не чувствительны к регистру\n\n#Размещайте фрагменты регулярных выражений над этой строчкой. Оставьте эту строчку такой, как она есть.</pre>",
-       "logentry-delete-delete": "$1 {{GENDER:$2|лыктын|лыктын}} странице $3",
+       "logentry-delete-delete": "$1 {{GENDER:$2|шӧрен|шӧрен}} лаштыкым $3",
        "revdelete-summary": "тӧрлатымаш-влакым возен ончыктымаш",
        "searchsuggest-search": "Кычалаш",
        "expand_templates_ok": "Йӧра",
index b979c67..71ed0c5 100644 (file)
        "selfredirect": "<strong>Предупредување:</strong> Создавате пренасочување кон истата статија.\nМоже да сте укажале грешна целна страница, или пак уредувате погрешна страница.\nАко стиснете на „{{int:savearticle}}“ повторно, тогаш пренасочувањето бездруго ќе се создаде.",
        "missingcommenttext": "Ве молиме внесете коментар подолу.",
        "missingcommentheader": "<strong>Потсетување:</strong> Не внесовте наслов за овој коментар.\nАко повторно стиснете на „{{int:savearticle}}“, уредувањето ќе биде зачувано без наслов.",
-       "summary-preview": "Ð\98зглед на описот:",
+       "summary-preview": "Ð\9fÑ\80еглед на описот:",
        "subject-preview": "Преглед на насловот:",
        "previewerrortext": "Се појави грешка при обидот да се прегледаат промените.",
        "blockedtitle": "Корисникот е блокиран",
        "editcomment": "Коментарот на уредувањето беше: <em>$1</em>.",
        "revertpage": "Отстрането уредувањето на [[Special:Contributions/$2|$2]] ([[User talk:$2|разговор]]), вратено на последната верзија на [[User:$1|$1]]",
        "revertpage-nouser": "Вратени уредувања од скриен корисник на последната преработка на {{GENDER:$1|[[User:$1|$1]]}}",
-       "rollback-success": "Откажани уредувањата на $1; вратено на последната верзија на $2.",
+       "rollback-success": "Откажани уредувањата на {{GENDER:$3|$1}};; вратено на последната верзија на {{GENDER:$4|$2}}.",
        "rollback-success-notify": "Откажани уредувањата на $1;\nвратено на последната преработка на $2. [$3 Пок. промени]",
        "sessionfailure-title": "Седницата не успеа",
        "sessionfailure": "Има проблем со вашата седница;\nоваа дејство е откажано како превентива против преземање седници.\nПритиснете го копчето „назад“ и повторно вчитајте ја страницата од која дојдовте и обидете се повторно.",
index 96e323e..fd5ac54 100644 (file)
@@ -83,7 +83,8 @@
                        "Hex",
                        "Xxmarijnw",
                        "Mainframe98",
-                       "QZanden"
+                       "QZanden",
+                       "Huhbakker"
                ]
        },
        "tog-underline": "Verwijzingen onderstrepen:",
        "passwordreset-emailsentusername": "Als er een e-mailadres geregistreerd is voor die gebruikersnaam, dan wordt er een e-mail verzonden om uw wachtwoord opnieuw in te stellen.",
        "passwordreset-nocaller": "Een aanroeper moet worden opgegeven",
        "passwordreset-nosuchcaller": "Aanroeper bestaat niet: $1",
-       "passwordreset-ignored": "Opnieuw instellen van het wachtwoord niet is afgehandeld. Misschien is er geen provider geconfigureerd?",
+       "passwordreset-ignored": "Het opnieuw instellen van het wachtwoord niet is afgehandeld. Misschien is er geen provider geconfigureerd?",
        "passwordreset-invalidemail": "Ongeldig e-mailadres",
        "passwordreset-nodata": "Er is geen gebruikersnaam of e-mailadres opgegeven",
        "changeemail": "E-mailadres wijzigen of verwijderen",
        "rcfilters-invalid-filter": "Ongeldig filter",
        "rcfilters-empty-filter": "Geen actieve filters. Alle bijdragen worden weergeven.",
        "rcfilters-filterlist-title": "Filters",
+       "rcfilters-highlightbutton-title": "Resultaten markeren",
+       "rcfilters-highlightmenu-title": "Kies een kleur",
        "rcfilters-filterlist-noresults": "Geen filters gevonden",
        "rcfilters-filtergroup-registration": "Gebruikers-registratie",
        "rcfilters-filter-registered-label": "Geregistreerd",
        "rcfilters-filter-registered-description": "Ingelogde gebruikers.",
        "rcfilters-filter-unregistered-label": "Niet-geregistreerd",
        "rcfilters-filter-unregistered-description": "Gebruikers die niet zijn ingelogd.",
+       "rcfilters-filtergroup-authorship": "Bewerken auteurschap",
        "rcfilters-filter-editsbyself-label": "Uw eigen bewerkingen",
        "rcfilters-filter-editsbyself-description": "Bewerkingen door u.",
        "rcfilters-filter-editsbyother-label": "Bewerkingen door anderen",
        "editcomment": "De bewerkingssamenvatting was: <em>$1</em>.",
        "revertpage": "Wijzigingen door [[Special:Contributions/$2|$2]] ([[User talk:$2|Overleg]]) hersteld tot de laatste versie door [[User:$1|$1]]",
        "revertpage-nouser": "Wijzigingen door een verborgen gebruiker teruggedraaid naar de laatste versie door {{GENDER:$1|[[User:$1|$1]]}}",
-       "rollback-success": "De wijzigingen door $1 zijn teruggedraaid.\nDe laatste versie van $2 is hersteld.",
+       "rollback-success": "De wijzigingen door {{GENDER:$3|$1}} zijn teruggedraaid.\nDe laatste versie van {{GENDER:$4|$2}} is hersteld.",
        "rollback-success-notify": "De wijzigingen door $1 zijn teruggedraaid;\nde laatste versie van $2 is hersteld. [$3 Wijzigingen weergeven]",
        "sessionfailure-title": "Sessiefout",
        "sessionfailure": "Er lijkt een probleem te zijn met uw aanmeldsessie.\nUw handeling is gestopt uit voorzorg tegen een beveiligingsrisico (dat bestaat uit mogelijke \"hijacking\" van deze sessie).\nGa een pagina terug, laad die pagina opnieuw en probeer het nog eens.",
        "log-action-filter-suppress-reblock": "Verbergen van gebruiker tijdens wijzigen blokkade",
        "log-action-filter-upload-upload": "Nieuwe upload",
        "log-action-filter-upload-overwrite": "Herupload",
+       "authmanager-authn-not-in-progress": "Verificatie is niet in uitvoering of de sessiegegevens zijn verloren gegaan. Gelieve opnieuw starten vanaf het begin.",
+       "authmanager-authn-no-primary": "De meegeleverde inloggegevens kunnen niet worden geverifieerd.",
+       "authmanager-authn-no-local-user": "De ingevoerde inloggegevens zijn niet geassocieerd met een gebruiker op deze wiki.",
+       "authmanager-authn-no-local-user-link": "De meegeleverde inloggegevens zijn geldig, maar zijn niet gekoppeld aan enige gebruiker op deze wiki. Log in op een andere manier, of creëer een nieuwe gebruiker, en u heeft een optie om uw eerdere inloggegevens van te koppelen.",
        "authmanager-authn-autocreate-failed": "Het automatisch aanmaken van een lokaal account is mislukt: $1",
+       "authmanager-change-not-supported": "De meegeleverde inloggegevens kunnen niet worden gewijzigd, omdat niets deze zou gebruiken.",
        "authmanager-create-disabled": "Het aanmaken van accounts is uitgeschakeld.",
        "authmanager-create-from-login": "Om een account aan te maken, gelieve de velden in te vullen.",
+       "authmanager-create-not-in-progress": "Het maken van een account is niet in uitvoering of de sessiegegevens zijn verloren gegaan. Gelieve opnieuw starten vanaf het begin.",
+       "authmanager-create-no-primary": "De meegeleverde inloggegevens kunnen niet worden gebruikt voor het aanmaken van uw account.",
+       "authmanager-link-no-primary": "De meegeleverde inloggegevens kunnen niet worden gebruikt om een account te koppelen.",
+       "authmanager-link-not-in-progress": "Account koppelen is niet gestart of de sessiegegevens zijn verloren gegaan. Gelieve opnieuw starten vanaf het begin.",
        "authmanager-authplugin-setpass-failed-title": "Wachtwoord wijzigen is mislukt",
+       "authmanager-authplugin-setpass-failed-message": "De verificatie-invoegtoepassing heeft het wijzigen van het wachtwoord geweigerd.",
+       "authmanager-authplugin-create-fail": "De verificatie-invoegtoepassing heeft geweigerd uw account aan te maken.",
        "authmanager-authplugin-setpass-denied": "De verificatie-invoegtoepassing staat het wijzigen van wachtwoorden niet toe.",
        "authmanager-authplugin-setpass-bad-domain": "Ongeldig domein.",
        "authmanager-autocreate-noperm": "Het automatisch aanmaken van accounts is niet toegestaan.",
        "authmanager-provider-password": "Op wachtwoord gebaseerde authenticatie",
        "authmanager-provider-password-domain": "Wachtwoord- en domeingebaseerde authentificatie",
        "authmanager-provider-temporarypassword": "Tijdelijk wachtwoord",
+       "authprovider-confirmlink-message": "Op basis van uw recente login pogingen, kan het volgende account worden gekoppeld aan uw wiki account. Het koppelen van stelt U in staat in te loggen via deze accounts. Gelieve te selecteren welk account moet worden gekoppeld.",
        "authprovider-confirmlink-request-label": "Accounts die aan elkaar moeten worden gekoppeld.",
        "authprovider-confirmlink-success-line": "$1: Succesvol gekoppeld.",
        "authprovider-confirmlink-failed": "Account koppelen is niet volledig gelukt: $1",
+       "authprovider-confirmlink-ok-help": "Doorgaan na het weergeven van de storingsmeldingen over het koppelen.",
        "authprovider-resetpass-skip-label": "Overslaan",
        "authprovider-resetpass-skip-help": "Sla het resetten van het wachtwoord over.",
+       "authform-nosession-login": "De verificatie is geslaagd, maar uw browser heeft niet \"onthouden\" ingelogd te zijn.\n!\n$1",
+       "authform-nosession-signup": "Het account is aangemaakt, maar uw browser heeft niet \"onthouden\" om ingelogd te zijn.\n!\n$1",
        "authform-newtoken": "Ontbrekend token. $1",
        "authform-notoken": "Ontbrekend token",
        "authform-wrongtoken": "Verkeerd token",
        "specialpage-securitylevel-not-allowed-title": "Niet toegestaan",
+       "specialpage-securitylevel-not-allowed": "Sorry, het is u niet toegestaan gebruik te maken van deze pagina omdat uw identiteit niet kon worden geverifieerd.",
+       "authpage-cannot-login": "Niet in staat om te beginnen met aanmelden.",
+       "authpage-cannot-login-continue": "Niet mogelijk om in te loggen. Uw sessie is waarschijnlijk verlopen.",
        "authpage-cannot-create": "Kon het account aanmaken niet starten.",
+       "authpage-cannot-create-continue": "Kan niet doorgaan met het aanmaken van een account. Uw sessie is waarschijnlijk verlopen.",
+       "authpage-cannot-link": "Niet in staat om het account te kunnen koppelen.",
+       "authpage-cannot-link-continue": "Niet mogelijk het account te koppelen. Uw sessie is waarschijnlijk verlopen.",
        "cannotauth-not-allowed-title": "Geen toegang",
        "cannotauth-not-allowed": "U hebt geen toestemming om deze pagina te gebruiken",
        "changecredentials": "Authenticatiegegevens wijzigen",
        "linkaccounts-submit": "Accounts koppelen",
        "unlinkaccounts": "Accounts ontkoppelen",
        "unlinkaccounts-success": "Het account is ontkoppeld.",
+       "authenticationdatachange-ignored": "De wijziging van de authenticatie gegevens zijn niet afgehandeld. Misschien is er geen provider is geconfigureerd?",
        "userjsispublic": "Let op: JavaScript deelpagina's moeten geen vertrouwelijke gegevens bevatten omdat ze kunnen worden bekeken door andere gebruikers.",
        "usercssispublic": "Let op: CSS deelpagina's moeten geen vertrouwelijke gegevens bevatten omdat ze kunnen worden bekeken door andere gebruikers.",
        "restrictionsfield-badip": "Ongeldig IP-adres of range: $1",
index 275a37b..3cfbe34 100644 (file)
@@ -38,7 +38,7 @@
        "tog-watchdeletion": "Apondre las paginas e los fichièrs que suprimissi de ma lista de seguiment",
        "tog-watchuploads": "Apondre los novèls fichièrs qu’impòrti a ma lista de seguiment",
        "tog-watchrollback": "Apondre a ma lista de seguiment las paginas sus las qualas ai efectuat una revocacion",
-       "tog-minordefault": "Considerar mas modificacions coma menoras per defaut",
+       "tog-minordefault": "Considerar totas las modificacions coma menoras per defaut",
        "tog-previewontop": "Far veire la previsualizacion al dessús de la zòna de modificacion",
        "tog-previewonfirst": "Far veire la previsualizacion al moment de la primièra edicion",
        "tog-enotifwatchlistpages": "M’avertir per corrièr electronic quand una pagina o un fichièr de ma lista de seguiment es modificat",
        "oct": "d'oct",
        "nov": "de nov",
        "dec": "de dec",
-       "january-date": "$1 de genièr",
-       "february-date": "$1 de febrièr",
-       "march-date": "$1 de març",
+       "january-date": "{{PLURAL:$1|1=1èr|$1}} de genièr",
+       "february-date": "{{PLURAL:$1|1=1èr|$1}} de febrièr",
+       "march-date": "{{PLURAL:$1|1=1èr|$1}} de març",
        "april-date": "$1 d'abril",
        "may-date": "$1 de mai",
        "june-date": "$1 de junh",
        "september-date": "$1 de setembre",
        "october-date": "$1 d'octobre",
        "november-date": "$1 de novembre",
-       "december-date": "$1 de decembre",
+       "december-date": "{{PLURAL:$1|1=1èr|$1}} de decembre",
        "period-am": "AM",
        "period-pm": "PM",
        "pagecategories": "{{PLURAL:$1|Categoria|Categorias}}",
        "edit": "Modificar",
        "edit-local": "Modificar la descripcion locala",
        "create": "Crear",
-       "create-local": "apondre una descripcion locala",
+       "create-local": "Apondre una descripcion locala",
        "editthispage": "Modificar aquesta pagina",
        "create-this-page": "Crear aquesta pagina",
        "delete": "Suprimir",
        "permissionserrorstext": "Avètz pas la permission d’efectuar l’operacion demandada per {{PLURAL:$1|la rason seguenta|las rasons seguentas}} :",
        "permissionserrorstext-withaction": "Sètz pas autorizat(ada) a $2, per {{PLURAL:$1|la rason seguenta|las rasons seguentas}} :",
        "recreate-moveddeleted-warn": "'''Atencion : sètz a tornar crear una pagina qu'es estada suprimida precedentament.'''\n\nDemandatz-vos s'es vertadièrament apropriat de contunhar de l’editar.\nL’istoric de las supressions e dels cambiaments de nom es afichat çaijós :",
-       "moveddeleted-notice": "Aquesta pagina es estat suprimida.\nL'istoric de las supressions e dels cambiaments de nom es afichat çaijós coma referéncia.",
+       "moveddeleted-notice": "Aquesta pagina es estada suprimida.\nL'istoric de las supressions e dels cambiaments de nom es afichat çaijós coma referéncia.",
        "log-fulllog": "Veire lo jornal complet",
        "edit-hook-aborted": "Modificacion fracassada per croquet.\nCap d'explicacion pas balhada.",
        "edit-gone-missing": "A pas pogut metre a jorn la pagina.\nSembla que siá estada suprimida.",
        "allpagesfrom": "Afichar las paginas a partir de :",
        "allpagesto": "Afichar las paginas fins a :",
        "allarticles": "Totas las paginas",
-       "allinnamespace": "Totas las paginas (espaci de noms $1)",
+       "allinnamespace": "Totas las paginas (dins l'espaci de noms $1)",
        "allpagessubmit": "Validar",
        "allpagesprefix": "Afichar las paginas que començan pel prefix :",
        "allpagesbadtitle": "Lo títol rensenhat per la pagina es incorrècte o possedís un prefix reservat. Conten segurament un o mantun caractèr especial que pòt pas èsser utilizats dins los títols.",
        "import-interwiki-sourcewiki": "Wiki font :",
        "import-interwiki-sourcepage": "Pagina font :",
        "import-interwiki-history": "Copiar totas las versions de l'istoric d'aquesta pagina",
-       "import-interwiki-templates": "Enclure totes los modèls",
+       "import-interwiki-templates": "Inclure totes los modèls",
        "import-interwiki-submit": "Importar",
        "import-mapping-default": "Importar als emplaçaments per defaut",
        "import-mapping-namespace": "Importar cap a un espaci de noms :",
        "spambot_username": "Netejatge de spam de MediaWiki",
        "spam_reverting": "Restabliment de la darrièra version que conten pas de ligam cap a $1",
        "spam_blanking": "Totas las versions que contenon de ligams cap a $1 son blanquidas",
-       "spam_deleting": "Totas las versions contenonián de ligams cap a $1, supression",
+       "spam_deleting": "Totas las versions contenián de ligams cap a $1, supression",
        "simpleantispam-label": "Verificacion antispam.\nInscriviscatz '''PAS RES''' dedins !",
        "pageinfo-title": "Informacions per « $1 »",
        "pageinfo-not-current": "O planhèm, impossible de provesir aquesta informacion per las ancianas revisions.",
index 6382c24..ef7be20 100644 (file)
        "selfredirect": "<strong>Ostrzeżenie:</strong> Przekierowujesz tę stronę do niej samej.\nByć może został przez Ciebie wybrany zły cel przekierowania lub edytujesz niewłaściwą stronę.\nJeżeli ponownie klikniesz „{{int:savearticle}}”, przekierowanie zostanie utworzone.",
        "missingcommenttext": "Wprowadź komentarz poniżej.",
        "missingcommentheader": "<strong>Uwaga:</strong> treść tytułu komentarza jest pusta.\nJeśli ponownie klikniesz „{{int:savearticle}}”, zmiany zostaną zapisane bez niego.",
-       "summary-preview": "Podgląd opisu:",
+       "summary-preview": "Podgląd opisu zmian:",
        "subject-preview": "Podgląd tematu:",
        "previewerrortext": "Wystąpił błąd podczas próby podglądu Twoich zmian.",
        "blockedtitle": "Użytkownik jest zablokowany",
        "rcfilters-invalid-filter": "Nieprawidłowy filtr",
        "rcfilters-empty-filter": "Brak aktywnych filtrów. Wyświetlane są wszystkie zmiany.",
        "rcfilters-filterlist-title": "Filtry",
+       "rcfilters-highlightmenu-title": "Wybierz kolor",
        "rcfilters-filterlist-noresults": "Nie znaleziono filtrów",
        "rcfilters-filtergroup-registration": "Rejestracja użytkownika",
        "rcfilters-filter-registered-label": "Zarejestrowany",
        "zip-file-open-error": "Wystąpił błąd podczas otwierania pliku ZIP, aby go sprawdzić.",
        "zip-wrong-format": "Wybrany plik nie jest w formacie ZIP.",
        "zip-bad": "Plik ZIP jest uszkodzony lub w inny sposób niemożliwy do odczytania. \nNie może zostać odpowiednio sprawdzony pod kątem bezpieczeństwa.",
-       "zip-unsupported": "Plik jest w formacie ZIP ale wykorzystuje funkcje, które nie są obsługiwane przez MediaWiki.\nPlik nie może zostać odpowiednio sprawdzony pod kątem bezpieczeństwa.",
+       "zip-unsupported": "Plik jest w formacie ZIP, ale wykorzystuje funkcje, które nie są obsługiwane przez MediaWiki.\nPlik nie może zostać odpowiednio sprawdzony pod kątem bezpieczeństwa.",
        "uploadstash": "Schowek z przesłanymi plikami",
        "uploadstash-summary": "Ta strona umożliwia dostęp do przesłanych lub właśnie przesyłanych plików, ale jeszcze nie opublikowanych na wiki. Pliki widzi wyłącznie użytkownik, które je przesłał.",
        "uploadstash-clear": "Wyczyść schowek z plikami",
        "editcomment": "Edycję opisał: <em>$1</em>.",
        "revertpage": "Wycofano edycje użytkownika [[Special:Contributions/$2|$2]] ([[User talk:$2|dyskusja]]). Autor przywróconej wersji to [[User:$1|$1]].",
        "revertpage-nouser": "Wycofano edycje ukrytego użytkownika. Autor przywróconej wersji to {{GENDER:$1|[[User:$1|$1]]}}.",
-       "rollback-success": "Wycofano edycje użytkownika $1;\nprzywrócono ostatnią wersję autorstwa $2.",
+       "rollback-success": "Wycofano edycje {{GENDER:$3|użytkownika|użytkowniczki}} $1;\nprzywrócono ostatnią wersję autorstwa {{GENDER:$4|$2}}.",
        "rollback-success-notify": "Wycofano edycje użytkownika $1;\nprzywrócono ostatnią wersję autorstwa $2. [$3 Pokaż zmiany]",
        "sessionfailure-title": "Błąd sesji",
        "sessionfailure": "Wystąpił problem z weryfikacją zalogowania.\nPolecenie zostało anulowane, aby uniknąć przechwycenia sesji.\nNaciśnij „wstecz” w przeglądarce, przeładuj stronę, po czym ponownie wydaj polecenie.",
        "invalidateemail": "Anulowanie potwierdzenia adresu e‐mail",
        "notificationemail_subject_changed": "Został zmieniony zarejestrowany adres e-mail na {{SITENAME}}",
        "notificationemail_subject_removed": "Zarejestrowany adres e-mail w {{GRAMMAR:MS.lp|SITENAME}} został usunięty",
+       "notificationemail_body_changed": "Ktoś, najprawdopodobniej Ty, z adresu IP $1,\nzmienił adres e-mail przypisany do konta „$2” na „$3” w {{GRAMMAR:MS.lp|{{SITENAME}}}}.\n\nJeżeli nie zostało to zrobione przez Ciebie, skontaktuj się niezwłocznie z administratorem.",
+       "notificationemail_body_removed": "Ktoś, najprawdopodobniej Ty, z adresu IP $1,\nusunął adres e-mail przypisany do konta „$2” w {{GRAMMAR:MS.lp|{{SITENAME}}}}.\n\nJeżeli nie zostało to zrobione przez Ciebie, skontaktuj się niezwłocznie z administratorem.",
        "scarytranscludedisabled": "[Transkluzja przez interwiki jest wyłączona]",
        "scarytranscludefailed": "[Pobranie szablonu dla $1 nie powiodło się]",
        "scarytranscludefailed-httpstatus": "[Pobranie szablonu dla $1 nie powiodło się: HTTP $2]",
index 7ae001c..e90c9ed 100644 (file)
        "faq": "FAQ",
        "faqpage": "Project:FAQ",
        "actions": "کم",
-       "namespaces": "ناواں دی تھاں:",
+       "namespaces": "ناں تھانواں:",
        "variants": "قسماں",
        "navigation-heading": "کھوج پتر",
        "errorpagetitle": "مسئلہ",
        "search": "کھوج",
        "searchbutton": "کھوج",
        "go": "جاؤ",
-       "searcharticle": "چلو جی",
+       "searcharticle": "چلو",
        "history": "پچھلے کم",
        "history_short": "ریکارڈ",
+       "history_small": "تریخ",
        "updatedmarker": "میرے پچھلی وار آن توں مگروں دیاں تبدیلیاں",
-       "printableversion": "چھپن جوگا صفہ",
+       "printableversion": "چھپن جوگا صفحہ",
        "permalink": "پکا جوڑ",
        "print": "چھاپو",
        "view": "وکھالہ",
        "articlepage": "مضمون آلا صفحہ",
        "talk": "گل بات",
        "views": "وکھالے",
-       "toolbox": "اÙ\88زار",
+       "toolbox": "سÙ\8eÙ\86د",
        "userpage": "ورتن آلے دا صفہ ویکھو",
        "projectpage": "ویونت والا صفہ ویکھو",
        "imagepage": "فائل آلا صفہ ویکھو",
        "redirectedfrom": "(لیایا گیا $1)",
        "redirectpagesub": "صفحہ ریڈائریکٹ کرو",
        "redirectto": "اگے کرو:",
-       "lastmodifiedat": "اس صفحے نوں آخری آری $1 تریخ نوں $2 وجے بدلیا گیا۔",
+       "lastmodifiedat": "اس صفحے نوں آخری واری $1 تریخ نوں $2 وجے بدلیا گیا۔",
        "viewcount": "اس صفحے نوں {{PLURAL:$1|اک واری|$1 واری}} کھولیا گیا اے۔",
        "protectedpage": "بجایا صفحہ",
        "jumpto": "جاؤ:",
        "copyrightpage": "{{ns:project}}:نقل دے حق",
        "currentevents": "اج کل دیاں گلاں",
        "currentevents-url": "Project:اج کل دیاں گلاں",
-       "disclaimers": "Ù\85Ù\86کرÙ\86ا",
-       "disclaimerpage": "Project:عاÙ\85 Ù\85Ù\86کرÙ\86ا",
+       "disclaimers": "Ù\84اتعÙ\84Ù\82Û\8c Ø§Ø¸Û\81ار",
+       "disclaimerpage": "Project:عاÙ\85 Ù\84اتعÙ\84Ù\82Û\8c Ø§Ø¸Û\81ار",
        "edithelp": "لکھن وچ مدد",
        "helppage-top-gethelp": "مدد",
        "mainpage": "پہلا صفہ",
-       "mainpage-description": "پہلا صفہ",
+       "mainpage-description": "پہلا صفحہ",
        "policy-url": "Project:پالیسی",
        "portal": "بیٹھک",
        "portal-url": "ویونت:بیٹھک",
-       "privacy": "بچاؤ پالیسی",
-       "privacypage": "Project:بچاؤ پالیسی",
+       "privacy": "پرائیویسی پالیسی",
+       "privacypage": "Project:پرائیویسی پالیسی",
        "badaccess": "اجازت دے وچ غلطی اے",
        "badaccess-group0": "تھاونوں ایس کم دی اجازت نیں جیہڑا تسیں آکھیا اے۔",
        "badaccess-groups": "جیڑا کم تسی کرنا چا رۓ او اوہ صرف {{PLURAL:$2|اس گروپ|ایناں گروپاں}} دے ورتن آلے کر سکدے نیں: $1۔",
        "nstab-main": "صفہ",
        "nstab-user": "ورتن والے دا صفہ",
        "nstab-media": "میڈیا آلا صفہ",
-       "nstab-special": "خاص صفہ",
+       "nstab-special": "خاص صفحہ",
        "nstab-project": "ویونت دا صفہ",
        "nstab-image": "فائل",
        "nstab-mediawiki": "سنیہہ",
        "listusers-creationsort": "بنان تریخ توں وکھریاں کرو۔",
        "usereditcount": "$1 {{PLURAL:$1|تبدیلی|تبدیلیاں}}",
        "usercreated": "{{GENDER:$3|بنائی گئی}} نوں $1 تے $2",
-       "newpages": "نویں صفے",
+       "newpages": "نویں صفحے",
        "newpages-username": "ورتن آلا ناں:",
        "ancientpages": "سب توں پرانے صفے",
        "move": "لے چلو",
        "whatlinkshere-prev": "{{PLURAL:$1|پچھلا $1ا|پچھلا}}",
        "whatlinkshere-next": "{{PLURAL:$1|اگلا $1|اگلا}}",
        "whatlinkshere-links": "← جوڑ",
-       "whatlinkshere-hideredirs": "$1 ریڈائریکٹس",
+       "whatlinkshere-hideredirs": "$1 ریڈائریکٹ",
        "whatlinkshere-hidetrans": "$1 ٹرانسکلوژن",
        "whatlinkshere-hidelinks": "$1 جوڑ",
        "whatlinkshere-hideimages": "$1 مورت جوڑ",
        "tooltip-ca-watch": "اس صفحہ تے نظر رکھو",
        "tooltip-ca-unwatch": "اس صفحے توں نظر ہٹاؤ",
        "tooltip-search": "کھوج {{SITENAME}}",
-       "tooltip-search-go": "اس Ù\86اں Ø¯Û\92 ØµÙ\81Û\92 ØªÛ\92 Ú\86Ù\84Ù\88Ø\8c Ø§Ú¯Ø± ایہ ہیگا اے",
-       "tooltip-search-fulltext": "اس شبد نوں صفیاں چ لبو",
-       "tooltip-p-logo": "پہلا صفہ",
+       "tooltip-search-go": "اس Ù\86اں Ø¯Û\92 ØµÙ\81Û\92 ØªÛ\92 Ú\86Ù\84Ù\88Ø\8c Ø¬Û\92 ایہ ہیگا اے",
+       "tooltip-search-fulltext": "اس شبد نوں صفحےآں وچ لبھو",
+       "tooltip-p-logo": "پہلا صفہ ویکھو",
        "tooltip-n-mainpage": "پہلے صفے نوں ویکھو",
        "tooltip-n-mainpage-description": "پہلے صفے تے جاؤ",
-       "tooltip-n-portal": "پربندھ بارے ، تسیں کی کر سکدے او تے کنج کھوج سکدے او",
+       "tooltip-n-portal": "پربندھ بارے ، تسیں کیہ کر سکدے او تے کنج کھوج سکدے او",
        "tooltip-n-currentevents": "موجودہ حالات تے پچھلیاں معلومات دیکھو",
        "tooltip-n-recentchanges": "وکی تے نویاں تبدیلیاں۔",
        "tooltip-n-randompage": "کوئی صفہ کھولو۔",
-       "tooltip-n-help": "Ù\85دد Ù\84Û\8cÙ\86Û\92 Ø¢Ù\84ی جگہ۔",
+       "tooltip-n-help": "Ù\84بھÙ\86 Ø¯ی جگہ۔",
        "tooltip-t-whatlinkshere": "اس نال جڑے سارے وکی صفے۔",
        "tooltip-t-recentchangeslinked": "اس صفے توں جڑے صفیاں چ نویاں تبدیلیاں",
        "tooltip-feed-rss": "RSS feed for this page",
        "tooltip-t-emailuser": "اس ورتن والے نو ای میل کرو",
        "tooltip-t-upload": "فائل چڑھاؤ",
        "tooltip-t-specialpages": "سارے خاص صفیاں دی اک لسٹ",
-       "tooltip-t-print": "اس صفے دا چھپنے آلا ورژن ویکھو",
+       "tooltip-t-print": "اس صفحے دا چھپن والا ورژن ویکھو",
        "tooltip-t-permalink": "اس صفے دے اس ورژن نال پکا جوڑ",
        "tooltip-ca-nstab-main": "مواد آلا صفہ ویکھو",
        "tooltip-ca-nstab-user": "ورتن آلے دا صفہ ویکھو",
        "pageinfo-watchers": "ویکھن والے",
        "pageinfo-edits": "تبدیلیاں گنتی",
        "pageinfo-authors": "وکھرے لکھاریاں دی گنتی",
-       "pageinfo-toolboxlink": "صفہ وات",
+       "pageinfo-toolboxlink": "صفحہ جانکاری",
        "markaspatrolleddiff": "ویکھے گۓ دا نشان لاؤ",
        "markaspatrolledtext": "ایس صفے تے ویکھن دا نشان لاؤ",
        "markedaspatrolled": "ویکھن دا نشان لاؤ",
        "file-info": "فائل ناپ: $1، MIME  ٹائپ: $2",
        "file-info-size": "پکسل:$1 × $2, فائل سائز: $3, مائم ٹائپ: $4",
        "file-info-size-pages": "$1 × $2 پکسل, فائل ناپ: $3, مائم ٹائپ: $4, $5 {{PLURAL:$5|صفہ|صفے}}",
-       "file-nohires": "اس ØªÙ\88Úº Ù\88Ú\88Û\8c Ù\81Ù\88Ù¹Ù\88 موجود نہیں۔",
+       "file-nohires": "اس ØªÙ\88Úº Ù\88Ú\88Û\8c Ù\85Ù\88رت موجود نہیں۔",
        "svg-long-desc": "ایس وی جی فائل، پکسل:$1 × $2، فائل سائز: $3",
        "show-big-image": "اصلی فائل",
        "show-big-image-preview": "ایس وکھالے دا ناپ: $1۔",
        "watchlisttools-view": "ملدیاں ہوئیاں تبدیلیاں ویکھو",
        "watchlisttools-edit": "اکھ تھلے رکھے ہوۓ صفحیاں نوں ویکھو تے تبدیل کرو",
        "watchlisttools-raw": "کچی اکھ تھلے رکھی ہوئی نو تبدیل کرو",
+       "hijri-calendar-m1": "محرم",
+       "hijri-calendar-m2": "صفر",
+       "hijri-calendar-m3": "ربیع الاول",
+       "hijri-calendar-m4": "ربیع الثانی",
+       "hijri-calendar-m5": "جمادی الاول",
+       "hijri-calendar-m6": "جمادی الثانی",
+       "hijri-calendar-m7": "رجب",
+       "hijri-calendar-m8": "شعبان",
+       "hijri-calendar-m9": "رمضان",
+       "hijri-calendar-m10": "شوال",
+       "hijri-calendar-m11": "ذوالقعدہ",
+       "hijri-calendar-m12": "ذوالحجہ",
        "signature": "[[{{ns:user}}:$1|$2]] ([[{{ns:user_talk}}:$1|talk]])",
        "duplicate-defaultsort": "'''خبردار:''' ڈیفالٹ چابی \"$2\" پہلی ڈیفالٹ چابی \"$1\" دے اتے لگ گئی اے۔",
        "version": "ورژن",
index a789eb5..0ed8589 100644 (file)
        "selfredirect": "<strong>Aviso:</strong> Está a redirecionar esta página para si mesma.\nPode ter especificado o destino errado para a página ou até a editar a página errada.\nSe clicar em \"{{int:savearticle}}\" novamente, o redirecionamento será criado na mesma.",
        "missingcommenttext": "Introduza um comentário abaixo, por favor.",
        "missingcommentheader": "<strong>Atenção:</strong> Não introduziu um assunto para este comentário.\nSe clicar novamente \"{{int:savearticle}}\", a sua edição será gravada sem assunto.",
-       "summary-preview": "Antevisão do resumo:",
+       "summary-preview": "Antevisão do resumo de edição:",
        "subject-preview": "Antevisão do assunto:",
        "previewerrortext": "Ocorreu um erro enquanto tentava antever as suas alterações.",
        "blockedtitle": "O utilizador está bloqueado",
index 2e02447..7665f80 100644 (file)
        "permissionserrorstext-withaction": "This message is \"with action\" version of {{msg-mw|Permissionserrorstext}}.\n\nParameters:\n* $1 - the number of reasons that were found why the action cannot be performed\n* $2 - one of the action-* messages (for example {{msg-mw|action-edit}}) or other such messages tagged with {{tl|doc-action}} in their documentation\n\nPlease report at [[Support]] if you are unable to properly translate this message. Also see [[phab:T16246]] (now closed) for background.",
        "contentmodelediterror": "Error message shown when trying to edit an old revision with a content model different from that of the current revision\n* $1 - content model of the old revision\n* $2 - content model of the current revision",
        "recreate-moveddeleted-warn": "Warning shown when creating a page which has already been deleted. See for example [[Test]].",
-       "moveddeleted-notice": "Shown on top of a deleted page in normal view modus ([{{canonicalurl:Test}} example]).",
-       "moveddeleted-notice-recent": "Shown on top of a recently deleted page in normal view modus ([{{canonicalurl:Test}} example]).",
+       "moveddeleted-notice": "Shown on top of a deleted page in normal view modus ([{{canonicalurl:Test}} example]).\n\nSee also {{msg-mw|moveddeleted-notice-recent}}",
+       "moveddeleted-notice-recent": "Shown on top of a recently deleted page in normal view modus ([{{canonicalurl:Test}} example]).\n\nSee also {{msg-mw|moveddeleted-notice}}",
        "log-fulllog": "Used as link text.",
        "edit-hook-aborted": "Used as error message.\n\nSee also:\n* {{msg-mw|edit-gone-missing}}\n* {{msg-mw|edit-conflict}}\n* {{msg-mw|edit-no-change}}\n* {{msg-mw|edit-already-exists}}",
        "edit-gone-missing": "Used as error message.\n\nSee also:\n* {{msg-mw|edit-hook-aborted}}\n* {{msg-mw|edit-conflict}}\n* {{msg-mw|edit-no-change}}\n* {{msg-mw|edit-already-exists}}",
        "rcfilters-invalid-filter": "A label for an invalid filter.",
        "rcfilters-empty-filter": "Placeholder for the filter list when no filters were chosen.",
        "rcfilters-filterlist-title": "Title for the filters list.\n{{Identical|Filter}}",
+       "rcfilters-highlightbutton-title": "Title for the highlight button used to toggle the highlight feature on and off.",
+       "rcfilters-highlightmenu-title": "Title for the highlight menu used to select the highlight color for an individual filter.",
        "rcfilters-filterlist-noresults": "Message showing no results found for searching a filter.",
        "rcfilters-filtergroup-registration": "Title for the filter group for editor registration type.",
        "rcfilters-filter-registered-label": "Label for the filter for showing edits made by logged-in users.\n{{Identical|Registered}}",
        "booksources-text": "Used in [[Special:BookSources/1]].\n\nThis message is followed by a list of links to other sites.\n\nSee also:\n* {{msg-mw|Booksources|title}}\n* {{msg-mw|Booksources-text|text}}",
        "booksources-invalid-isbn": "This message is displayed after an invalid ISBN is entered on [[Special:Booksources]].",
        "magiclink-tracking-rfc": "Name of the [[mw:Special:MyLanguage/Help:Tracking categories|tracking category]] where pages that use RFC magic links will be added.\n\nSee [https://en.wikipedia.org/wiki/Help:Magic_links#RFC Help:Magic links] for more information on RFC magic links.",
-       "magiclink-tracking-rfc-desc": "Description of the tracking category {{mw-msg|magiclink-tracking-rfc}}",
+       "magiclink-tracking-rfc-desc": "Description of the tracking category {{msg-mw|magiclink-tracking-rfc}}",
        "magiclink-tracking-pmid": "Name of the [[mw:Special:MyLanguage/Help:Tracking categories|tracking category]] where pages that use PMID magic links will be added.",
-       "magiclink-tracking-pmid-desc": "Description of the tracking category {{mw-msg|magiclink-tracking-pmid}}",
+       "magiclink-tracking-pmid-desc": "Description of the tracking category {{msg-mw|magiclink-tracking-pmid}}",
        "magiclink-tracking-isbn": "Name of the [[mw:Special:MyLanguage/Help:Tracking categories|tracking category]] where pages that use ISBN magic links will be added.",
-       "magiclink-tracking-isbn-desc": "Description of the tracking category {{mw-msg|magiclink-tracking-isbn}}",
+       "magiclink-tracking-isbn-desc": "Description of the tracking category {{msg-mw|magiclink-tracking-isbn}}",
        "rfcurl": "{{notranslate}}\nParameters:\n* $1 - RFC number\nSee also:\n* {{msg-mw|Pubmedurl}}",
        "pubmedurl": "{{notranslate}}\nParameters:\n* $1 - Pubmed number\nSee also:\n* {{msg-mw|Rfcurl}}",
        "specialloguserlabel": "Used in [[Special:Log]] as a label for an input field with which the log can be filtered for entries describing actions ''performed'' by the specified user.  \"Carried out\" and \"done\" are possible alternatives for \"performed\".",
        "editcomment": "Only shown if there is an edit {{msg-mw|Summary}}. Parameters:\n* $1 - the edit summary",
        "revertpage": "Parameters:\n* $1 - username 1\n* $2 - username 2\n* $3 - (Optional) revision ID of the revision reverted to\n* $4 - (Optional) timestamp of the revision reverted to\n* $5 - (Optional) revision ID of the revision reverted from\n* $6 - (Optional) timestamp of the revision reverted from\nSee also:\n* {{msg-mw|Revertpage-nouser}}\n{{Identical|Revert}}",
        "revertpage-nouser": "This is a confirmation message a user sees after reverting, when the username of the version is hidden with RevisionDelete.\n\nIn other cases the message {{msg-mw|Revertpage}} is used.\n\nParameters:\n* $1 - username 1, can be used for GENDER\n* $2 - (Optional) username 2\n* $3 - (Optional) revision ID of the revision reverted to\n* $4 - (Optional) timestamp of the revision reverted to\n* $5 - (Optional) revision ID of the revision reverted from\n* $6 - (Optional) timestamp of the revision reverted from",
-       "rollback-success": "This message shows up on screen after successful revert (generally visible only to admins). $1 describes user whose changes have been reverted, $2 describes user which produced version, which replaces reverted version.\n{{Identical|Revert}}\n{{Identical|Rollback}}",
+       "rollback-success": "This message shows up on screen after successful revert (generally visible only to admins). Parameters:\n* $1 - user whose changes have been reverted\n* $2 - user who produced version, which replaces reverted version\n* $3 - the first user's name, can be used for GENDER\n* $4 - the second user's name, can be used for GENDER\n{{Identical|Revert}}\n{{Identical|Rollback}}",
        "rollback-success-notify": "Notification shown after a successful revert.\n* $1 - User whose changes have been reverted\n* $2 - User that made the edit that was restored\n* $3 - Url to the diff of the rollback\nSee also:\n* {{msg-mw|showdiff}}\n{{related|rollback-success}}\n{{Format|jquerymsg}}",
        "sessionfailure-title": "Used as title of the error message {{msg-mw|Sessionfailure}}.",
        "sessionfailure": "Used as error message.\n\nThe title for this error message is {{msg-mw|Sessionfailure-title}}.",
index 88de994..fcffcdc 100644 (file)
                        "Mailman",
                        "Аль-Гимравий",
                        "Gamliel Fishkin",
-                       "Ping08"
+                       "Ping08",
+                       "Yuryleb"
                ]
        },
        "tog-underline": "Подчёркивание ссылок:",
        "rcfilters-invalid-filter": "Недопустимый фильтр",
        "rcfilters-empty-filter": "Нет активных фильтров. Показываются все правки.",
        "rcfilters-filterlist-title": "Фильтры",
+       "rcfilters-highlightbutton-title": "Выделить результаты",
+       "rcfilters-highlightmenu-title": "Выберите цвет",
        "rcfilters-filterlist-noresults": "Фильтры не найдены",
        "rcfilters-filtergroup-registration": "Регистрация участников",
        "rcfilters-filter-registered-label": "Зарегистрированные",
        "editcomment": "Было дано описание изменения: <em>$1</em>.",
        "revertpage": "Откат правок [[Special:Contributions/$2|$2]] ([[User talk:$2|обсуждение]]) к версии [[User:$1|$1]]",
        "revertpage-nouser": "Откат правок (имя участника скрыто) к версии {{GENDER:$1|[[User:$1|$1]]}}",
-       "rollback-success": "Откачены правки $1; возврат к версии $2.",
+       "rollback-success": "Откачены правки {{GENDER:$3|$1}}; возврат к версии {{GENDER:$4|$2}}.",
        "rollback-success-notify": "Откачены правки $1; возврат к последней версии $2. [$3 Показать изменения]",
        "sessionfailure-title": "Ошибка сеанса",
        "sessionfailure": "Похоже, возникли проблемы с текущим сеансом работы;\nэто действие было отменено в целях предотвращения «захвата сеанса».\nПожалуйста, нажмите кнопку «Назад» и перезагрузите страницу, с которой вы пришли.",
index dbc7b57..24f7622 100644 (file)
@@ -11,7 +11,8 @@
                        "아라",
                        "Dicto23456",
                        "Macofe",
-                       "Matma Rex"
+                       "Matma Rex",
+                       "KHMELNYTSKYIA"
                ]
        },
        "tog-underline": "Підкреслёвати одказы:",
        "currentevents": "Актуалны подїї",
        "currentevents-url": "Project:Актуалны подїї",
        "disclaimers": "Вылучіня одповідности",
-       "disclaimerpage": "Project:Ð\92Ñ\8bлÑ\83Ñ\87Ñ\96нÑ\8f Ð¾Ð´Ð¿Ð¾Ð²Ñ\96дноÑ\81Ñ\82и",
+       "disclaimerpage": "Project:Ð\92Ñ\96дмова Ð²Ñ\96д Ð²Ñ\96дповÑ\96далÑ\8cноÑ\81Ñ\82Ñ\96",
        "edithelp": "Поміч едітованя",
        "mainpage": "Головна сторінка",
        "mainpage-description": "Головна сторінка",
        "passwordreset-emaildisabled": "Функції електронічной пошты были выпнуы на тій вікі.",
        "passwordreset-username": "Мено хоснователя:",
        "passwordreset-domain": "Домена:",
-       "passwordreset-capture": "Посмотрити выслїдный імейл?",
-       "passwordreset-capture-help": "Кідь означіте тото поличко, буде імейл (з дочасным геслом) оркем посланя хоснователёви указаный і вам.",
        "passwordreset-email": "Адреса електронічной пошты:",
        "passwordreset-emailtitle": "Детайлы конта на {{SITENAME}}",
        "passwordreset-emailtext-ip": "Дахто (може Вы, з IP адресы $1) попросив о наставлїня нового гесла до вашого конта на {{grammar:6sg|{{SITENAME}}}} ($4). З тов адресов {{PLURAL:$3|є повязане слїдуюче конто|суть повязаны слїдуючі конта}}:\n\n$2\n\n{{PLURAL:$3|Тото дочасне гесло стане неплатным|Тоты дочасны гесла стануть неплатныма}} {{PLURAL:$5|за день|за $5 днї|за $5 днїв}}.\nТеперь бы сьте ся мали приголосити і зволити собі нове гесло. Кідь тоту просьбу послав хтось другый або сьте собі на своє старе гесло спомянули і не хочете го змінити, можете тото повідомлїня іґноровати і дале хосновати старе гесло.",
        "saveprefs": "Уложыти",
        "restoreprefs": "Обновити вшыткы штандартны наставлїня (у вшыткых секціях)",
        "prefs-editing": "Едітованя",
-       "rows": "Рядкы:",
-       "columns": "Колонкы:",
        "searchresultshead": "Гляданя",
        "stub-threshold": "Поріг про форматованя одказу як <a href=\"#\" class=\"stub\">одказів на \"stub\"</a> (v bajtech):",
        "stub-threshold-disabled": "Выпнуте",
        "userrights-reason": "Причіна:",
        "userrights-no-interwiki": "Не маєте поволїня мінити права хоснователїв на іншых вікі.",
        "userrights-nodatabase": "Датабаза $1 не екзістує або не є місцёва.",
-       "userrights-nologin": "Мусите ся [[Special:UserLogin|приголосити]] на конто адміністратора, жебы сьте могли мінити права хоснователїв.",
-       "userrights-notallowed": "Вы не мате права придати або одстранити хосновательскы права.",
        "userrights-changeable-col": "Ґрупы, котры можете змінити",
        "userrights-unchangeable-col": "Ґрупы, котры не можете змінити",
        "userrights-conflict": "Конфлікт змін прав хоснователїв! Просиме, перевірьте зміны і потвердьте їх.",
-       "userrights-removed-self": "Вы успішно позбавили ся властных прав. Зато уж веце не мате приступ до той сторінкы.",
        "group": "Ґрупа:",
        "group-user": "Хоснователї",
        "group-autoconfirmed": "Автопотверджены хоснователї",
        "right-siteadmin": "Замыкана і одомыканя датабазы",
        "right-override-export-depth": "Експорт сторінок включаючі звязаны сторінкы з глубков до 5",
        "right-sendemail": "Посыланя пошты іншым хоснователям",
-       "right-passwordreset": "Перезераня імейлів про зміну гесла",
        "newuserlogpage": "Лоґ вытварянь хоснователїв",
        "newuserlogpagetext": "Тото є список ново реґістрованых хоснователїв.",
        "rightslog": "Лоґ хосновательскых прав",
        "blocklink": "заблоковати",
        "unblocklink": "одблоковати",
        "change-blocklink": "змінити блок",
-       "contribslink": "пÑ\80иÑ\81пÑ\96вкÑ\8b",
+       "contribslink": "внеÑ\81ок",
        "emaillink": "послати імейл",
        "autoblocker": "Сьте были автоматічно блокованы, протоже здїляте IP-адресу з хоснователём „[[User:$1|$1]]“. Причіна блокованя того хоснователя: „$2“",
        "blocklogpage": "Запис блоковань",
        "version-license": "Ліценція",
        "version-ext-license": "Ліценція",
        "version-ext-colheader-name": "Росшырїня",
-       "version-ext-colheader-version": "Верзія",
+       "version-ext-colheader-version": "Версія",
        "version-ext-colheader-license": "Ліценція",
        "version-ext-colheader-description": "Попис",
        "version-ext-colheader-credits": "Авторы",
        "feedback-thanks": "Дякуєме! Ваш коментарь быв приданый на сторінку „[$2 $1]“.",
        "searchsuggest-search": "Глядати",
        "searchsuggest-containing": "обсягуючій...",
-       "api-error-badaccess-groups": "Не мате дозволено наладововати файлы на тоту вікі.",
        "api-error-badtoken": "Внутрїшня хыба: планый знак.",
-       "api-error-copyuploaddisabled": "Наладовованя з URL є на тім сервері заказане.",
-       "api-error-duplicate": "На тій вікі уж {{PLURAL:$1|екзістує другый файл|екзістують іншы файлы}} з такым самым обсягом.",
-       "api-error-duplicate-archive": "{{PLURAL:$1|быв другый файл|были даякы другы файлы}} з такым самым обсягом уж гев оперед {{PLURAL:$1|быв|были}}, але {{PLURAL:$1|быв змазаный|были змазаны}}.",
-       "api-error-empty-file": "Наладованый файл є порожнїй.",
        "api-error-emptypage": "Створїня новых, порожнїх сторінк неслободно.",
-       "api-error-fetchfileerror": "Внутрїшня хыба: трафила ся хыба під час обтриманя файлу.",
-       "api-error-fileexists-forbidden": "Файл з назвов „$1“ уж екзістує тай не годен го переписати.",
-       "api-error-fileexists-shared-forbidden": "файл з назвов „$1“ уж екзістує в сполочнім усховищу тай не годен го переписати.",
-       "api-error-file-too-large": "Наладованый файл є барз великый.",
-       "api-error-filename-tooshort": "Назва файлу є барз курта.",
-       "api-error-filetype-banned": "Тот тіп файлу є заказаный.",
-       "api-error-filetype-banned-type": "$1 {{PLURAL:$4|є недозволеный формат файлів|суть недозволены форматы файлів}}. {{PLURAL:$3|Дозволеный формат фалів є|Дозволены форматы файлів суть}} $2.",
-       "api-error-filetype-missing": "Тот файл не мать росшырїня.",
-       "api-error-hookaborted": "Пожадована вами зміна была одмітнута дакотрым росшырінём.",
-       "api-error-http": "Внутрїшня хыба: не вдало ся припоїти к серверу.",
-       "api-error-illegal-filename": "Тота назва файлу не є дозволена.",
-       "api-error-internal-error": "Внутрїшня хыба: притрафила ся хыба під час спрацованя вашого наладованого файлу.",
-       "api-error-invalid-file-key": "Внутрїшня хыба: файл ся не нашов в дочаснім усховіщі.",
-       "api-error-missingparam": "Внутрїшня хыба: хыбують параметры пожадавкы.",
-       "api-error-missingresult": "Внутрїшня хыба: не годен становити, ці копірованя было успішне.",
-       "api-error-mustbeloggedin": "Жебы наладовати файлы, мусите быти приголошеный.",
-       "api-error-mustbeposted": "Внутрїшня хыба: пожадавка мусить быти через HTTP POST.",
-       "api-error-noimageinfo": "Наладованя было успішне, але сервер не додав о файлї ниякы інформації.",
-       "api-error-nomodule": "Внутрїшня хыба: не є наставленый модул наладовованя.",
-       "api-error-ok-but-empty": "Внутрїшня хыба: сервер не одповідать.",
-       "api-error-overwrite": "Не є дозволене переписати екзістуючій файл.",
-       "api-error-stashfailed": "Внутрїшня хыба: серверу ся не вдало уложыти дочасный файл.",
        "api-error-publishfailed": "Внутрїшня хыба: серверови ся не вдало опубліковати дочасный файл.",
-       "api-error-timeout": "Сервер не одповідав в очекаванім часї.",
-       "api-error-unclassified": "Трафила ся незнама хыба.",
-       "api-error-unknown-code": "Незнама хыба: „$1“",
-       "api-error-unknown-error": "Внутрїшня хыба: трафила ся хыба при спробі о наладованя файлу.",
+       "api-error-stashfailed": "Внутрїшня хыба: серверу ся не вдало уложыти дочасный файл.",
        "api-error-unknown-warning": "Незнаме варованя: $1",
        "api-error-unknownerror": "Незнама хыба: „$1“",
-       "api-error-uploaddisabled": "Начітаваня файлів є на тій вікі выпнуте.",
-       "api-error-verification-error": "Файл є може пошкодженый, або мать плане росшырїня.",
        "duration-seconds": "$1 {{PLURAL:$1|секунда|секунды|секунд}}",
        "duration-minutes": "$1 {{PLURAL:$1|минуту|минуты|минут}}",
        "duration-hours": "$1 {{PLURAL:$1|година|годины|годин}}",
index 86d1f66..5676eee 100644 (file)
@@ -81,6 +81,7 @@
        "mypage": "پەڕە",
        "mytalk": "وەتوویش",
        "navigation": "ڕێدەرکردن",
+       "and": "&#32;و",
        "qbfind": "پیا بکە",
        "qbbrowse": "بگەرد",
        "qbedit": "وێراشتە",
        "actions": "کردارەگان",
        "namespaces": "شوونناوەگان",
        "variants": "شێوەزارەگان",
+       "navigation-heading": "منۆێ ڕێدەرکردن",
        "errorpagetitle": "غەڵەت",
        "returnto": "بەورەو ئڕاێ $1.",
+       "tagline": "لە {{SITENAME}}",
        "help": "یارمەتی",
        "search": "مینە",
        "searchbutton": "مینە",
        "jumptonavigation": "ڕێدەرکردن",
        "jumptosearch": "مینە",
        "aboutsite": "سەبارەت وە {{SITENAME}}",
+       "aboutpage": "Project:لەوارەی",
        "copyrightpage": "{{ns:project}}:مافەیل لەوەرگرتن",
        "currentevents": "ڕووداوەیل ئێرەنگەیی",
        "currentevents-url": "Project:ڕووداوەیل ئێرەنگەیی",
        "nstab-mediawiki": "پەیام",
        "nstab-help": "پەڕەێ کۆمەک",
        "nstab-category": "پول",
+       "mainpage-nstab": "دەسپێک",
        "missing-article": "دەیتابەیسەگە نەتۊەنست دەق پەڕەێگ وە ناو «$1» $2 پێیابکەێد ک ئەشێ پێیابکردیاتاد.\n\nئیە فرەتر لە مدووێ وەدۊاچین بەستیارێگ جیاواز یادیرۆک کۆنەێ پەڕەێگ سڕیاێ ڕوو دەێد.\n\nئەگەر لەێوا نیە، ئەوە گەھا گرفتێگ لەێ نەرمامێرە پێیاکردیەسە.\nتکایە ئیە وە ئاماژەدان وە ناونیشان URLـەگەیەو وە [[Special:ListUsers/sysop|وەڕێوەوەرێگ]] ڕاپۆرت بدە.",
        "missingarticle-rev": "(نسخە#: $1)",
        "badtitle": "ناونیشان خراو",
        "loginlanguagelabel": "زوان: $1",
        "pt-login": "بچووە ناو",
        "pt-login-button": "بچووە ناو",
+       "pt-createaccount": "ھەژمار درس بکە",
        "oldpassword": "تێپەڕوشەێ قەدیمی:",
        "newpassword": "تێپەڕوشەێ نوو:",
        "retypenew": "تێپەڕوشەێ نوو دوبارە بنۊسەو:",
        "searchprofile-images-tooltip": "مینە ئڕاێ پەڕگەگان",
        "searchprofile-everything-tooltip": "لە گشت ناوەرۆکێگ مینە بکە (تەنانەت پەڕەگان وتوویشیش)",
        "searchprofile-advanced-tooltip": "مینە لەناو شوونناوە دڵخوازەگان",
+       "search-result-size": "$1 ({{PLURAL:$2|یەک وشە|$2 وشە}})",
        "search-redirect": "(ڕەوانەکەر $1)",
        "search-section": "(بەش $1)",
        "search-suggest": "ئایا مەبەستت ئیە بۊ: $1",
        "group-all": "(گشت)",
        "right-read": "خوەنین پەڕەگان",
        "right-edit": "وێراشتەکردن پەڕەگان",
+       "right-writeapi": "ئەوکاربردن API ئەڕاێ نۊساین",
        "newuserlogpage": "پێرست درسکردن ئەوکاربەر",
        "action-edit": "ئەی پەڕە وێراشتە بکە",
        "nchanges": "$1 {{PLURAL:$1|گووڕانکاری}}",
        "rcshowhidepatr": "وێراشتە نەگەردیاێەگان $1",
        "rcshowhidemine": "وێراشتەگانم $1",
        "rclinks": "دۊایین $1 گووڕانکاری $2 ڕووژ ویەردە نیشان بدە<br />$3",
+       "diff": "جیاوازی",
        "hist": "دیرۆک",
        "hide": "بشارەو",
        "minoreditletter": "بێجگە",
+       "newpageletter": "ن",
+       "boteditletter": "بۆت",
+       "rc-change-size-new": "$1 {{PLURAL:$1|بایت}} پاش گووڕانکاری",
        "rc-enhanced-expand": "وردەکاریەگان نیشان بدە",
        "rc-enhanced-hide": "وردەکاریەگان بشارەو",
        "recentchangeslinked": "گووڕانکاریە پەیوەندیدارەگان",
        "statistics-pages": "پەڕەیل",
        "pageswithprop-submit": "بچوو",
        "brokenredirects-edit": "وێراشتە",
+       "nbytes": "$1 {{PLURAL:$1|بایت|بایت}}",
        "prefixindex": "گشت پەڕەگان وە پێشگرەو",
        "protectedpages-page": "پەڕە",
        "protectedpages-unknown-timestamp": "نەناسریاێ",
        "undelete-show-file-submit": "بەڵێ",
        "namespace": "شوونناوەگان",
        "invert": "ھەڵوژیاێەگان وەزێزەو بکە",
+       "blanknamespace": "(سەرەکی)",
        "contributions": "بەشدارییەگان {{GENDER:$1|ئەوکاربەر}}",
        "contributions-title": "بەشداریەگان ئەوکاربەر $1",
        "mycontris": "بەشداریەیل",
        "tooltip-pt-mycontris": "پێرست بەشداریەیلت",
        "tooltip-pt-login": "پێشنیار ئەوپیت کریەێد بچیدە ناو؛ ھەرچەن زووری نیە",
        "tooltip-pt-logout": "دەرچین",
+       "tooltip-pt-createaccount": "داوەت لەلیت بووت ک ھەژمارێگ درس بکەیت و بچیتە ناو، هەرچەن ئیە وە مەیل خوەتە",
        "tooltip-ca-talk": "وەتوویش سەبارەت وە ناوەڕۆک پەڕە",
        "tooltip-ca-edit": "تۊەنی وێراشتەێ ئەی پەڕەیە بکەید. تکایە وەر لە پاشدەسکردن دوگمەێ پێشدۊنن ئەوکاربوەێن.",
        "tooltip-ca-addsection": "بەشێگ نوو دەس پی بکە",
        "tooltip-feed-atom": "خواردەمەنی ئەتۆم ئڕاێ ئەی پەڕە",
        "tooltip-t-contributions": "پێرست بەشداریەگان ئەی ئەوکاربەر",
        "tooltip-t-emailuser": "ئیمەیلێگ بنارە ئڕاێ ئەی ئەوکاربەرە",
+       "tooltip-t-upload": "پەڕگەێگ بار بکە",
        "tooltip-t-specialpages": "پێرست گشت پەڕە تایوەتەگان",
        "tooltip-t-print": "نسخەێ چاپی ئەی پەڕە",
        "tooltip-t-permalink": "بەسیار ھەمیشەیی وە ئەی وەشان لە ئەی پەڕە",
        "tooltip-ca-nstab-main": "دۊنن پەڕەێ ناوەڕۆک",
        "tooltip-ca-nstab-user": "پەڕەێ ئەوکاربەر تەماشا بکە",
-       "tooltip-ca-nstab-special": "ئیە پەڕەێگ تایبەتە، نیەتۊەنی خوەێ ئەی پەڕە وێراشتە بکەید",
+       "tooltip-ca-nstab-special": "ئیە پەڕەێگ تایبەتە و وێراشتە نیەکریەێت",
        "tooltip-ca-nstab-project": "دۊنن پەڕەێ پرۆژە",
        "tooltip-ca-nstab-image": "دۊنن پەڕەێ پەڕگە",
        "tooltip-ca-nstab-template": "دۊنن قاڵبەگە",
        "tooltip-rollback": "«گەڕانن» گووڕانکاری/گووڕانکاریەگان ئەی پەڕە وە یەک کرتە گەڕانێدەو ئڕاێ دۊایین بەشداریکەر",
        "tooltip-undo": "«بەتاڵکردن» ئەی گووڕانکاریە گووڕنێدەو و فۆرم وێراشتەکردن لە شێوەی پێشدۊنن وازەو کەێد. ئەی جوورە پووڕێد مدووێگ لە کورتەێ وێراشتە بنۊسریەێد.",
        "tooltip-summary": "کۆرتەێگ لە لی بنۊسە",
+       "pageinfo-toolboxlink": "زانیاری پەڕە",
        "pageinfo-redirectsto-info": "زانیاری",
        "pageinfo-contentpage-yes": "بەڵێ",
        "pageinfo-protect-cascading-yes": "بەڵێ",
        "file-nohires": "رەزۆلوشن سەرتر لەیە لە وەردەستەو نیە.",
        "svg-long-desc": "پەڕگەێ SVG، وە ناو $1 × $2 پیکسڵ، قەوارەێ پەڕگە: $3",
        "show-big-image": "پەڕگەێ رەسەن",
+       "show-big-image-preview": "قەوارەێ ئەی پێشدۊنینە: $1.",
+       "show-big-image-other": "{{PLURAL:$2|ڕزێلووشن|ڕزێلووشنەیل}} تر: $1.",
+       "show-big-image-size": "$1 لە $2 پیکسەڵ",
        "ilsubmit": "مینە",
        "bad_image_list": "فۆرمەت وە شێوەێ خوارەسە:\n\nتەنیا ئەو باوەتەیلە ک پێرست کریانە (واتە ئەو ھێڵەیلە ک وە * دەس پێ کەن) لە وەر چاون.\nیەکەم بەسیار لە سەر ھەر ھێڵێگ، ئەشێ بەسیار فایلێگ خراو بوود.\nگشت بەسیارەگان دۊاێ ئەوە لە ئەو ھێڵە، چۊ نائاسایی(ئستسنا) تیەنە ئەژمار.",
        "metadata": "متادەیتا",
        "specialpages": "پەڕە تایوەتەگان",
        "external_image_whitelist": " #ئەی ھێڵە ھەر وە ئەی جوورە ک ھەس، وەر بدەین<pre>\n#رستە وەنەزمەگان (regular expression) (تەنیا ئەو بەشە کە لە نێوان // جێ گرێد) لە خوارەو بنەین\n#ئیانە وەرد نیشانی ئینترنتی وێنەیل دەرەکی بەسیار دریای (hotlinked) چەترگیەن (تەتبیق دریەن).\n#ئەوانە ک چەترگیانە، چۊ وێنە نیشان دریەن؛ وەگەرنە تەنیا بەسیارێگ وە وێنە نیشان دەریەێد.\n#ئەو ھێڵەیلە وە # دەس پێ کەن، جوور شرۆڤە (comments) گیریەنە وەر چەو\n#ئەی ھێڵەیلە وە گەورە و بۊچگی پیتەگان ھەستیارە (case-insensitive)\n\n#گشت رستە وەنەزمەگان (regex) لە ژۊەر ئەی ھێڵە بنەین. ئەی ھێڵ ھەر وە ئەی جوورە کە ھەس، وەر بدەین</pre>",
        "tag-filter": "پاڵووین [[Special:Tags|تاگ]]:",
+       "tag-list-wrapper": "([[Special:Tags|{{PLURAL:$1|تاگ|تاگەیل}}]]: $2)",
        "tags-active-yes": "بەڵێ",
        "tags-active-no": "نە",
        "tags-edit": "وێراشتە",
        "htmlform-no": "نە",
        "htmlform-yes": "بەڵێ",
+       "logentry-newusers-create": "ھەژمار ئەوکاربەری $1 {{GENDER:$2|درس کریا}}",
        "feedback-message": "پەیام:",
-       "searchsuggest-search": "Ù\85Û\8cÙ\86ە",
+       "searchsuggest-search": "Ù\84Û\95 {{SITENAME}} Ù\85Û\8cÙ\86Û\95 Ø¨Ú©ە",
        "expand_templates_ok": "باشە",
        "pagelang-name": "پەڕە",
        "pagelang-language": "زوان",
index 4737609..539bb18 100644 (file)
        "last": "разл",
        "page_first": "прва",
        "page_last": "последња",
-       "histlegend": "Избор разлика: изаберите кутијице измена за упоређивање и притисните ентер или дугме на дну.<br />\nОбјашњење: <strong>({{int:cur}})</strong> – разлика с тренутном изменом,\n<strong>({{int:last}})</strong> – разлика с претходном изменом, <strong>{{int:minoreditletter}}</strong> – мала измена",
+       "histlegend": "Избор разлика: изаберите кутијице измена за упоређивање и притисните ентер или дугме на дну.<br />\nОбјашњење: <strong>({{int:cur}})</strong> = разлика с тренутном изменом, <strong>({{int:last}})</strong> = разлика с претходном изменом, <strong>{{int:minoreditletter}}</strong> = мала измена",
        "history-fieldset-title": "Преглед историје",
        "history-show-deleted": "Само обрисано",
        "histfirst": "најстарије",
        "booksources-search": "Претражи",
        "booksources-text": "Испод се налази списак веза ка сајтовима који се баве продајом нових и половних књига, а који би могли имати додатне податке о књигама које тражите:",
        "booksources-invalid-isbn": "Наведени ISBN број није исправан. Проверите да није дошло до грешке при умножавању из првобитног извора.",
+       "magiclink-tracking-isbn": "Странице са ISBN магичним везама",
        "specialloguserlabel": "Извршилац:",
        "speciallogtitlelabel": "Циљ (наслов или {{ns:user}}:корисничко име):",
        "log": "Дневници",
index 6d22e0b..45a83ca 100644 (file)
        "last": "razl",
        "page_first": "prva",
        "page_last": "poslednja",
-       "histlegend": "Izbor razlika: izaberite kutijice izmena za upoređivanje i pritisnite enter ili dugme na dnu.<br />\nObjašnjenje: <strong>({{int:cur}})</strong> – razlika s trenutnom izmenom,\n<strong>({{int:last}})</strong> – razlika s prethodnom izmenom, <strong>{{int:minoreditletter}}</strong> – mala izmena",
+       "histlegend": "Izbor razlika: izaberite kutijice izmena za upoređivanje i pritisnite enter ili dugme na dnu.<br />\nObjašnjenje: <strong>({{int:cur}})</strong> = razlika s trenutnom izmenom, <strong>({{int:last}})</strong> = razlika s prethodnom izmenom, <strong>{{int:minoreditletter}}</strong> = mala izmena",
        "history-fieldset-title": "Pregled istorije",
        "history-show-deleted": "Samo obrisane",
        "histfirst": "najstarije",
        "booksources-search": "Pretraži",
        "booksources-text": "Ispod se nalazi spisak veza ka sajtovima koji se bave prodajom novih i polovnih knjiga, a koji bi mogli imati dodatne podatke o knjigama koje tražite:",
        "booksources-invalid-isbn": "Navedeni ISBN broj nije ispravan. Proverite da nije došlo do greške pri umnožavanju iz prvobitnog izvora.",
+       "magiclink-tracking-isbn": "Stranice sa ISBN magičnim vezama",
        "specialloguserlabel": "Izvršilac:",
        "speciallogtitlelabel": "Cilj (naslov ili {{ns:user}}:korisničko ime):",
        "log": "Dnevnici",
index 104c497..f244230 100644 (file)
        "uploaddisabledtext": "கோப்பு பதிவேற்றங்கள் செயலிழக்கச் செய்யப்பட்டுள்ளன.",
        "php-uploaddisabledtext": "கோப்பு தரவேற்றம் PHP இல் முடக்கப்பட்டுள்ளது.தயவுகூர்ந்து file_uploads அமைப்பை சரிபார்க்கவும்.",
        "uploadscripted": "இந்தக் கோப்பு உலாவியால் பிழையாக விளங்கிக் கொள்ளக்கூடிய எச்.டி.எம்.எல். அல்லது வேறு நிரல்களைக் கொண்டுள்ளது.",
-       "uploadscriptednamespace": "இந்த SVG கோப்பு ஒரு சரியில்லாத பெயரிடைவெளியை \"<nowiki>$1</nowiki>\" கொண்டுள்ளது.",
+       "uploadscriptednamespace": "இந்த SVG கோப்பு ஒரு சரியில்லாத பெயரிடைவெளியை கொண்டுள்ளது \"<nowiki>$1</nowiki>\".",
        "uploadinvalidxml": "ஏற்றபட்ட கோப்பில் உள்ள XML ஆராய முடியாது.",
        "uploadvirus": "கோப்பு நச்சுநிரலைக் (வைரஸ்) கொண்டுள்ளது! விபரங்கள்:$1",
        "uploadjava": "இது ஒரு zip கோப்பு.இதில் java.class என்ற கோப்பு உள்ளது.\nஜாவா கோப்புகளை தகவலேற்றுவது தடைசெய்யப்பட்டுள்ளது.ஏனெனில் அது பாதுகாப்பு தடைகளை மீற வழிவகுக்கும்.",
index 7cc72db..546c32c 100644 (file)
        "selfredirect": "<strong>คำเตือน:</strong> คุณกำลังสร้างการเปลี่ยนทางไปบทความเดียวกัน\nคุณอาจระบุเป้าหมายของการเปลี่ยนทางผิด หรือคถณอาจแก้ไขหน้าผิด \nหากคุณคลิก \"{{int:savearticle}}\" อีกครั้ง จะสร้างการเปลี่ยนทาง",
        "missingcommenttext": "กรุณากรอกความเห็นด้านล่าง",
        "missingcommentheader": "<strong>อย่าลืม:</strong> คุณยังไม่ได้ใส่เรื่องสำหรับความเห็นนี้ \nถ้าคุณคลิก \"{{int:savearticle}}\" อีก จะบันทึกการแก้ไขของคุณโดยไม่ระบุเรื่อง",
-       "summary-preview": "ตัวอย่างคำอธิบาย:",
-       "subject-preview": "ตัวอย่างเรื่อง:",
+       "summary-preview": "ตัวอย่างคำอธิบายการแก้ไข:",
+       "subject-preview": "à¸\95ัวอยà¹\88าà¸\87à¸\8aืà¹\88อà¹\80รืà¹\88อà¸\87:",
        "previewerrortext": "เกิดข้อผิดพลาดขณะกำลังพยายามดูตัวอย่างการเปลี่ยนแปลงของคุณ",
        "blockedtitle": "ผู้ใช้ถูกบล็อก",
        "blockedtext": "<strong>ชื่อผู้ใช้หรือเลขที่อยู่ไอพีของคุณถูกบล็อก</strong>\n\nการบล็อกนี้ดำเนินการโดย $1\nซึ่งให้เหตุผลว่า ''$2''\n\n* เริ่มการบล็อก: $8\n* หมดเขตการบล็อก: $6\n* ผู้ถูกบล็อกที่เจตนา: $7\n\nคุณสามารถติดต่อ $1 หรือ[[{{MediaWiki:Grouppage-sysop}}|ผู้ดูแลระบบ]]คนอื่นเพื่ออภิปรายการบล็อกนี้ได้\nคุณไม่สามารถใช้คุณลักษณะ \"ส่งอีเมลหาผู้ใช้รายนี้ได้\" จนกว่าจะระบุที่อยู่อีเมลให้ถูกต้องใน[[Special:Preferences|การตั้งค่าบัญชี]]ของคุณ และคุณมิได้ถูกห้ามใช้ความสามารถนี้\nเลขที่อยู่ไอพีปัจจุบันของคุณคือ $3 และหมายเลขการบล็อกคือ #$5 \nโปรดแสดงรายละเอียดข้างต้นทั้งหมดในการสอบถามใด ๆ",
        "editinguser": "กำลังเปลี่ยนสิทธิผู้ใช้ของผู้ใช้ <strong>[[User:$1|$1]]</strong> $2",
        "viewinguserrights": "กำลังดูสิทธิผู้ใช้ของผู้ใช้ <strong>[[User:$1|$1]]</strong> $2",
        "userrights-editusergroup": "แก้ไขกลุ่มผู้ใช้",
-       "userrights-viewusergroup": "ดูกลุ่มผู้ใช้",
+       "userrights-viewusergroup": "ดูกลุ่ม{{GENDER:$1|ผู้ใช้}}",
        "saveusergroups": "บันทึกกลุ่ม{{GENDER:$1|ผู้ใช้}}",
        "userrights-groupsmember": "สมาชิกของ:",
        "userrights-groupsmember-auto": "สมาชิกโดยปริยายของ:",
index 32773e3..1837c4b 100644 (file)
        "period-am": "AM",
        "period-pm": "PM",
        "pagecategories": "{{PLURAL:$1|分类}}",
-       "category_header": "å\88\86ç±»â\80\9c$1â\80\9d中的页面",
+       "category_header": "å\88\86ç±»â\80\9c$1â\80\9dä¸\8b的页面",
        "subcategories": "子分类",
        "category-media-header": "分类“$1”中的媒体文件",
        "category-empty": "<em>本分类目前不含有任何页面或媒体文件。</em>",
        "rcfilters-invalid-filter": "无效过滤器",
        "rcfilters-empty-filter": "没有活跃的过滤器。已显示所有贡献。",
        "rcfilters-filterlist-title": "过滤器",
+       "rcfilters-highlightbutton-title": "高亮结果",
+       "rcfilters-highlightmenu-title": "选择颜色",
        "rcfilters-filterlist-noresults": "找不到过滤器",
        "rcfilters-filtergroup-registration": "用户注册",
        "rcfilters-filter-registered-label": "已注册",
        "recentchangeslinked-feed": "相关更改",
        "recentchangeslinked-toolbox": "相关更改",
        "recentchangeslinked-title": "与“$1”有关的更改",
-       "recentchangeslinked-summary": "这是链接自指定页面(或至指定分类的成员)的页面的最近更改的列表。[[Special:Watchlist|的监视列表]]中的页面以<strong>粗体</strong>显示。",
+       "recentchangeslinked-summary": "这是链接自指定页面(或至指定分类的成员)的页面的最近更改的列表。[[Special:Watchlist|的监视列表]]中的页面以<strong>粗体</strong>显示。",
        "recentchangeslinked-page": "页面名称:",
        "recentchangeslinked-to": "显示链到所给出的页面",
        "recentchanges-page-added-to-category": "[[:$1]]已添加至分类",
        "randompage-nopages": "在以下{{PLURAL:$2|名字空间}}中没有页面:$1。",
        "randomincategory": "分类中随机页面",
        "randomincategory-invalidcategory": "“$1”不是一个有效的分类名称。",
-       "randomincategory-nopages": "[[:Category:$1|$1]]å\88\86类中没有页面。",
+       "randomincategory-nopages": "[[:Category:$1|$1]]å\88\86ç±»ä¸\8b没有页面。",
        "randomincategory-category": "分类:",
        "randomincategory-legend": "分类中随机页面",
        "randomincategory-submit": "提交",
        "ancientpages": "最老页面",
        "move": "移动",
        "movethispage": "移动本页",
-       "unusedimagestext": "以下文件实际存在,但并没有插入任何页面。请注意,其他网站可能会使用直接URL链接某个文件,因此它即使被实际使用也可能在这里列出。",
+       "unusedimagestext": "存在以下没有插入任何页面的文件。请注意,其他网站可能会使用直接URL链接某个文件,因此它即使被实际使用也可能在这里列出。",
        "unusedcategoriestext": "以下分类页面实际存在,即使没有其它页面或分类利用它们。",
        "notargettitle": "无目标",
        "notargettext": "您还没有指定一个目标页面或用户以进行此项操作。",
        "editcomment": "编辑摘要:<em>$1</em>。",
        "revertpage": "恢复[[Special:Contributions/$2|$2]]([[User talk:$2|讨论]])的编辑至[[User:$1|$1]]的最后版本",
        "revertpage-nouser": "恢复隐藏用户的编辑至{{GENDER:$1|[[User:$1|$1]]}}的最后版本",
-       "rollback-success": "已恢复$1的编辑,更改回$2的最后版本。",
+       "rollback-success": "已恢复{{GENDER:$3|$1}}的编辑;更改回{{GENDER:$4|$2}}的最后版本。",
        "rollback-success-notify": "已回退$1的编辑,更改回$2的最后版本。[$3 显示更改]",
        "sessionfailure-title": "会话无效",
        "sessionfailure": "似乎您的登录会话有问题;\n为了防止会话劫持,这个操作已经被取消。\n请返回先前的页面,重新载入该页面,然后重试。",
        "tooltip-pt-mytalk": "{{GENDER:|您}}的讨论页面",
        "tooltip-pt-anontalk": "有关本IP地址的编辑的讨论",
        "tooltip-pt-preferences": "{{GENDER:|您}}的设置",
-       "tooltip-pt-watchlist": "正在监视更改的页面的列表",
+       "tooltip-pt-watchlist": "正在监视更改的页面的列表",
        "tooltip-pt-mycontris": "{{GENDER:|您}}的贡献的列表",
        "tooltip-pt-anoncontribs": "来自此IP地址的编辑列表",
        "tooltip-pt-login": "我们鼓励您登录;然而,这不是强制性的",
        "siteuser": "{{SITENAME}}用户$1",
        "anonuser": "{{SITENAME}}匿名用户$1",
        "lastmodifiedatby": "本页面被$3最后修改于$1 $2。",
-       "othercontribs": "å\9fºäº\8e$1ç\9a\84å·¥ä½\9cã\80\82",
+       "othercontribs": "å\9fºäº\8e$1ç\9a\84å\8a³å\8a¨æ\88\90æ\9e\9cã\80\82",
        "others": "其他",
        "siteusers": "{{SITENAME}}{{PLURAL:$2|{{GENDER:$1|用户}}}}$1",
        "anonusers": "{{SITENAME}}匿名{{PLURAL:$2|用户}}$1",
        "variantname-gan-hant": "hant",
        "variantname-kk-cyrl": "kk-cyrl",
        "metadata": "元数据",
-       "metadata-help": "此文件中包含有扩展的信息。这些信息可能是由数码相机或扫描仪在创建或数字化过程中所添加的。\n\n如果此文件的源文件已经被修改,一些信息在修改后的文件中将不能完全反映出来。",
+       "metadata-help": "此文件中包含有额外的信息。这些信息可能是由数码相机或扫描仪在创建或数字化过程中所添加的。如果文件自初始状态已受到修改,一些详细说明可能无法反映修改后的文件。",
        "metadata-expand": "显示详细资料",
        "metadata-collapse": "隐藏详细资料",
        "metadata-fields": "在本信息中所列出的 EXIF 元数据域将包含在图片显示页面,当元数据表损坏时只显示以下信息。\n其他的元数据默认为隐藏。\n* make\n* model\n* datetimeoriginal\n* exposuretime\n* fnumber\n* isospeedratings\n* focallength\n* artist\n* copyright\n* imagedescription\n* gpslatitude\n* gpslongitude\n* gpsaltitude",
index 9044e45..844dc45 100644 (file)
        "editinguser": "變更{{GENDER:$1|使用者}} <strong>[[User:$1|$1]]</strong> 的使用者權限 $2",
        "viewinguserrights": "檢視{{GENDER:$1|使用者}}<strong>[[User:$1|$1]]</strong>的使用者權限 $2",
        "userrights-editusergroup": "編輯使用者群組",
-       "userrights-viewusergroup": "檢視使用者群組",
+       "userrights-viewusergroup": "檢視{{GENDER:$1|使用者}}群組",
        "saveusergroups": "儲存{{GENDER:$1|使用者}}群組",
        "userrights-groupsmember": "所屬群組:",
        "userrights-groupsmember-auto": "所屬隱含群組:",
        "variantname-gan-hans": "‪中文(简体)",
        "variantname-gan-hant": "‪中文(繁體)",
        "metadata": "詮釋資料",
-       "metadata-help": "æ­¤æª\94æ¡\88å\8c\85å\90«é¡\8då¤\96ç\9a\84è³\87è¨\8aï¼\8cå\8f¯è\83½ç\94±æ\95¸ä½\8dç\9b¸æ©\9fæ\88\96æ\8e\83æ\8f\8fæ©\9fæ\89\80建ç«\8bç\9a\84ã\80\82\nè\8b¥ä¿®æ\94¹æ­¤æª\94æ¡\88ï¼\8cé\83¨ä»½è³\87è¨\8aå°\87ç\84¡æ³\95ä¿\9dç\95\99。",
+       "metadata-help": "æ­¤æ\96\87件中å\8c\85å\90«é¡\8då¤\96ä¿¡æ\81¯ã\80\82é\80\99äº\9bä¿¡æ\81¯å\8f¯è\83½æ\98¯ç\94±æ\95¸ç¢¼ç\9b¸æ©\9fæ\88\96æ\8e\83æ\8f\8få\84\80å\9c¨å\89µå»ºæ\88\96æ\95¸å­\97å\8c\96é\81\8eç¨\8b中æ\89\80æ·»å\8a ç\9a\84ã\80\82å¦\82æ\9e\9cæ\96\87件è\87ªå\88\9då§\8bç\8b\80æ\85\8bå·²å\8f\97å\88°ä¿®æ\94¹ï¼\8cä¸\80äº\9b詳細說æ\98\8eå\8f¯è\83½ç\84¡æ³\95å\8f\8dæ\98 ä¿®æ\94¹å¾\8cç\9a\84æ\96\87件。",
        "metadata-expand": "顯示詳細資料",
        "metadata-collapse": "隱藏詳細資料",
        "metadata-fields": "在本訊息中所列出的 EXIF 詮釋資料域將包含在圖片顯示頁面,當詮釋資料表損壞時只顯示以下訊息。\n其他的詮釋資料預設為隱藏。\n* make\n* model\n* datetimeoriginal\n* exposuretime\n* fnumber\n* isospeedratings\n* focallength\n* artist\n* copyright\n* imagedescription\n* gpslatitude\n* gpslongitude\n* gpsaltitude",
index cb26337..b38287e 100644 (file)
@@ -128,6 +128,7 @@ $specialPageAliases = [
 ];
 
 $magicWords = [
+       'redirect'                  => [ '0', '#REDIRECCIÓ', '#REDIRECCIO', '#REDIRECT' ],
        'numberofarticles'          => [ '1', 'NOMBRED\'ARTICLES', 'NUMBEROFARTICLES' ],
        'numberoffiles'             => [ '1', 'NOMBRED\'ARXIUS', 'NUMBEROFFILES' ],
        'numberofusers'             => [ '1', 'NOMBRED\'USUARIS', 'NUMBEROFUSERS' ],
@@ -169,8 +170,7 @@ $datePreferences = [
 $defaultDateFormat = 'dmy';
 
 $bookstoreList = [
-       'Catàleg Col·lectiu de les Universitats de Catalunya' => 'http://ccuc.cbuc.es/cgi-bin/vtls.web.gateway?searchtype=control+numcard&searcharg=$1',
-       'Totselsllibres.com' => 'http://www.totselsllibres.com/tel/publi/busquedaAvanzadaLibros.do?ISBN=$1',
+       'Catàleg Col·lectiu de les Universitats de Catalunya' => 'http://ccuc.cbuc.cat/search*cat/X?SEARCH=$1',
        'inherit' => true,
 ];
 
diff --git a/maintenance/CodeCleanerGlobalsPass.inc b/maintenance/CodeCleanerGlobalsPass.inc
new file mode 100644 (file)
index 0000000..5e8e754
--- /dev/null
@@ -0,0 +1,52 @@
+<?php
+/**
+ * Psy CodeCleaner to allow PHP super globals.
+ *
+ * https://github.com/bobthecow/psysh/issues/353
+ *
+ * Copyright © 2017 Justin Hileman <justin@justinhileman.info>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ *
+ * @file
+ * @ingroup Maintenance
+ *
+ * @author Justin Hileman <justin@justinhileman.info>
+ */
+
+/**
+ * Prefix the real command with a bunch of 'global $VAR;' commands, one for each global.
+ * This will make the shell behave as if it was running in the global scope (almost;
+ * variables created in the shell won't become global if no global variable by that name
+ * existed before).
+ */
+class CodeCleanerGlobalsPass extends \Psy\CodeCleaner\CodeCleanerPass {
+       private static $superglobals = [
+               'GLOBALS', '_SERVER', '_ENV', '_FILES', '_COOKIE', '_POST', '_GET', '_SESSION'
+       ];
+
+       public function beforeTraverse( array $nodes ) {
+               $names = [];
+               foreach ( array_diff( array_keys( $GLOBALS ), self::$superglobals ) as $name ) {
+                       array_push( $names, new \PhpParser\Node\Expr\Variable( $name ) );
+               }
+
+               array_unshift( $nodes, new \PhpParser\Node\Stmt\Global_( $names ) );
+
+               return $nodes;
+       }
+}
+
index befafc1..286fb58 100644 (file)
@@ -27,6 +27,8 @@
 require_once __DIR__ . '/Maintenance.php';
 require_once __DIR__ . '/../includes/export/DumpFilter.php';
 
+use Wikimedia\Rdbms\LoadBalancer;
+
 /**
  * @ingroup Dump Maintenance
  */
index d8661c1..5d92eec 100644 (file)
@@ -27,6 +27,8 @@
 require_once __DIR__ . '/backup.inc';
 require_once __DIR__ . '/../includes/export/WikiExporter.php';
 
+use Wikimedia\Rdbms\LoadBalancer;
+
 /**
  * @ingroup Maintenance
  */
@@ -212,7 +214,6 @@ TEXT
                // We do /not/ retry upon failure, but delegate to encapsulating logic, to avoid
                // individually retrying at different layers of code.
 
-               // 1. The LoadBalancer.
                try {
                        $this->lb = wfGetLBFactory()->newMainLB();
                } catch ( Exception $e ) {
@@ -220,7 +221,6 @@ TEXT
                                . " rotating DB failed to obtain new load balancer (" . $e->getMessage() . ")" );
                }
 
-               // 2. The Connection, through the load balancer.
                try {
                        $this->db = $this->lb->getConnection( DB_REPLICA, 'dump' );
                } catch ( Exception $e ) {
diff --git a/maintenance/shell.php b/maintenance/shell.php
new file mode 100644 (file)
index 0000000..47ef804
--- /dev/null
@@ -0,0 +1,102 @@
+<?php
+/**
+ * Modern interactive shell within the MediaWiki engine.
+ *
+ * Merely wraps around http://psysh.org/ and drop an interactive PHP shell in
+ * the global scope.
+ *
+ * Copyright © 2017 Antoine Musso <hashar@free.fr>
+ * Copyright © 2017 Gergő Tisza <tgr.huwiki@gmail.com>
+ * Copyright © 2017 Justin Hileman <justin@justinhileman.info>
+ * Copyright © 2017 Wikimedia Foundation Inc.
+ * https://www.mediawiki.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
+ * @ingroup Maintenance
+ *
+ * @author Antoine Musso <hashar@free.fr>
+ * @author Justin Hileman <justin@justinhileman.info>
+ * @author Gergő Tisza <tgr.huwiki@gmail.com>
+ */
+
+require_once __DIR__ . '/Maintenance.php';
+
+/**
+ * Interactive shell with completion and global scope.
+ *
+ */
+class MediaWikiShell extends Maintenance {
+
+       public function __construct() {
+               parent::__construct();
+               $this->addOption( 'd',
+                       'For back compatibility with eval.php. ' .
+                       '0 send debug to stdout. ' .
+                       'With 1 additionally initialize database with debugging ',
+                       false, true
+               );
+       }
+
+       public function execute() {
+               if ( !class_exists( \Psy\Shell::class ) ) {
+                       $this->error( 'PsySH not found. Please run composer with the --dev option.', 1 );
+               }
+
+               $traverser = new \PhpParser\NodeTraverser();
+               $codeCleaner = new \Psy\CodeCleaner( null, null, $traverser );
+
+               // add this after initializing the code cleaner so all the default passes get added first
+               $traverser->addVisitor( new CodeCleanerGlobalsPass() );
+
+               $config = new \Psy\Configuration( [ 'codeCleaner' => $codeCleaner ] );
+               $config->setUpdateCheck( \Psy\VersionUpdater\Checker::NEVER );
+               $shell = new \Psy\Shell( $config );
+               if ( $this->hasOption( 'd' ) ) {
+                       $this->setupLegacy();
+               }
+
+               $shell->run();
+       }
+
+       /**
+        * For back compatibility with eval.php
+        */
+       protected function setupLegacy() {
+               global $wgDebugLogFile;
+
+               $d = intval( $this->getOption( 'd' ) );
+               if ( $d > 0 ) {
+                       $wgDebugLogFile = 'php://stdout';
+               }
+               if ( $d > 1 ) {
+                       # Set DBO_DEBUG (equivalent of $wgDebugDumpSql)
+                       # XXX copy pasted from eval.php :(
+                       $lb = wfGetLB();
+                       $serverCount = $lb->getServerCount();
+                       for ( $i = 0; $i < $serverCount; $i++ ) {
+                               $server = $lb->getServerInfo( $i );
+                               $server['flags'] |= DBO_DEBUG;
+                               $lb->setServerInfo( $i, $server );
+                       }
+               }
+       }
+
+}
+
+$maintClass = 'MediaWikiShell';
+require_once RUN_MAINTENANCE_IF_MAIN;
index f9c6117..3b2798f 100644 (file)
@@ -29,7 +29,11 @@ body {
        margin: 0 0 10px 10px;
 }
 
-td, h3, p, h1, pre {
+h1,
+h3,
+p,
+pre,
+td {
        margin: 0 20px 20px 20px;
        font-size: 11px;
        line-height: 140%;
index 3aeb1ed..10a6de8 100644 (file)
 
 .config-block-label {
        display: block;
-       margin-bottom: .2em;
+       margin-bottom: 0.2em;
 }
 
-.config-block-label label, .config-label {
+.config-block-label label,
+.config-label {
        font-weight: bold;
-       padding-right: .5em;
-       padding-top: .2em;
+       padding-right: 0.5em;
+       padding-top: 0.2em;
 }
 
 .config-block-elements {
 .btn-install {
        font-weight: bold;
        font-size: 110%;
-       padding: .2em .3em;
+       padding: 0.2em 0.3em;
 }
 
 .success-message {
        background-position: left center;
        background-repeat: no-repeat;
        cursor: pointer;
-       font-size: .8em;
+       font-size: 0.8em;
        text-decoration: underline;
        color: #0645ad;
 }
index 2f0311f..d6cb43f 100644 (file)
@@ -1776,16 +1776,26 @@ return [
                        'resources/src/mediawiki.rcfilters/ui/mw.rcfilters.ui.FilterWrapperWidget.js',
                        'resources/src/mediawiki.rcfilters/ui/mw.rcfilters.ui.ChangesListWrapperWidget.js',
                        'resources/src/mediawiki.rcfilters/ui/mw.rcfilters.ui.FormWrapperWidget.js',
+                       'resources/src/mediawiki.rcfilters/ui/mw.rcfilters.ui.FilterItemHighlightButton.js',
+                       'resources/src/mediawiki.rcfilters/ui/mw.rcfilters.ui.HighlightColorPickerWidget.js',
+                       'resources/src/mediawiki.rcfilters/mw.rcfilters.HighlightColors.js',
                        'resources/src/mediawiki.rcfilters/mw.rcfilters.init.js',
                ],
                'styles' => [
+                       'resources/src/mediawiki.rcfilters/styles/mw.rcfilters.mixins.less',
+                       'resources/src/mediawiki.rcfilters/styles/mw.rcfilters.variables.less',
+                       'resources/src/mediawiki.rcfilters/styles/mw.rcfilters.ui.less',
                        'resources/src/mediawiki.rcfilters/styles/mw.rcfilters.ui.Overlay.less',
+                       'resources/src/mediawiki.rcfilters/styles/mw.rcfilters.less',
                        'resources/src/mediawiki.rcfilters/styles/mw.rcfilters.ui.FilterItemWidget.less',
                        'resources/src/mediawiki.rcfilters/styles/mw.rcfilters.ui.CapsuleItemWidget.less',
                        'resources/src/mediawiki.rcfilters/styles/mw.rcfilters.ui.FilterGroupWidget.less',
                        'resources/src/mediawiki.rcfilters/styles/mw.rcfilters.ui.FiltersListWidget.less',
                        'resources/src/mediawiki.rcfilters/styles/mw.rcfilters.ui.FilterWrapperWidget.less',
                        'resources/src/mediawiki.rcfilters/styles/mw.rcfilters.ui.FilterCapsuleMultiselectWidget.less',
+                       'resources/src/mediawiki.rcfilters/styles/mw.rcfilters.ui.ChangesListWrapperWidget.less',
+                       'resources/src/mediawiki.rcfilters/styles/mw.rcfilters.ui.HighlightColorPickerWidget.less',
+                       'resources/src/mediawiki.rcfilters/styles/mw.rcfilters.ui.FilterItemHighlightButton.less',
                ],
                'messages' => [
                        'rcfilters-activefilters',
@@ -1832,12 +1842,15 @@ return [
                        'rcfilters-filter-categorization-description',
                        'rcfilters-filter-logactions-label',
                        'rcfilters-filter-logactions-description',
+                       'rcfilters-highlightbutton-title',
+                       'rcfilters-highlightmenu-title',
                        'recentchanges-noresult',
                ],
                'dependencies' => [
                        'oojs-ui',
                        'mediawiki.rcfilters.filters.dm',
-                       'oojs-ui.styles.icons-moderation'
+                       'oojs-ui.styles.icons-moderation',
+                       'oojs-ui.styles.icons-editing-core',
                ],
        ],
        'mediawiki.special' => [
index d24fcc9..92c6c43 100644 (file)
@@ -7,9 +7,9 @@
 
 .arrowSteps li {
        float: left;
-       padding: 0px;
-       margin: 0px;
-       border: 0 none;
+       padding: 0;
+       margin: 0;
+       border: 0;
 }
 
 .arrowSteps li div {
index 8b4bd7b..8e0e512 100644 (file)
@@ -19,9 +19,9 @@
 .mw-badge-inline {
        margin-left: 3px;
        display: inline-block;
-       /* Hack for IE6 and IE7 (bug 47926) */
+       /* Hack for IE6 and IE7 (T49926) */
        zoom: 1;
-       *display: inline;
+       *display: inline; /* stylelint-disable-line declaration-block-no-duplicate-properties */
 
 }
 .mw-badge-overlay {
index 567bec8..c75246c 100644 (file)
@@ -87,7 +87,7 @@
                // Chop off characters from the end of the "inserted content" string
                // until the limit is statisfied.
                if ( fn ) {
-                       // stop, when there is nothing to slice - bug 41450
+                       // stop, when there is nothing to slice - T43450
                        while ( $.byteLength( fn( inpParts.join( '' ) ) ) > byteLimit && inpParts[ 1 ].length > 0 ) {
                                inpParts[ 1 ] = inpParts[ 1 ].slice( 0, -1 );
                        }
                                }
                                // Always adjust prevSafeVal to reflect the input value. Not doing this could cause
                                // trimByteLength to compare the new value to an empty string instead of the
-                               // old value, resulting in trimming always from the end (bug 40850).
+                               // old value, resulting in trimming always from the end (T42850).
                                prevSafeVal = res.newVal;
                        } );
                } );
index b7e0af5..0cba34f 100644 (file)
        position: absolute;
        cursor: crosshair;
 }
-.farbtastic, .farbtastic .wheel {
+.farbtastic,
+.farbtastic .wheel {
        width: 195px;
        height: 195px;
 }
-.farbtastic .color, .farbtastic .overlay {
+.farbtastic .color,
+.farbtastic .overlay {
        top: 47px;
        left: 47px;
        width: 101px;
index 4353dd7..0aaa4ff 100644 (file)
@@ -12,6 +12,7 @@
  *
  * @author Timo Tijhof, 2011-2012
  */
+/* eslint-env qunit */
 ( function ( mw, $ ) {
        'use strict';
 
index 76b4845..6c7bd0e 100644 (file)
@@ -36,5 +36,5 @@
 
        /* IE < 8 */
        zoom: 1;
-       *display: inline;
+       *display: inline; /* stylelint-disable-line declaration-block-no-duplicate-properties */
 }
index f6b4fd1..2cc0cc9 100644 (file)
@@ -6,7 +6,7 @@
        top: 0;
        left: 0;
        width: 0;
-       border: none;
+       border: 0;
        z-index: 1099;
        padding: 0;
        margin: -1px 0 0 0;
@@ -17,7 +17,6 @@
        background-color: #fff;
        cursor: pointer;
        border: solid 1px #aaa;
-       padding: 0;
        margin: 0;
        margin-top: -2px;
        display: none;
index 8c1739c..fdc8a26 100644 (file)
                                                                // Don't interfere with special clicks (e.g. to open in new tab)
                                                                if ( !( e.which !== 1 || e.altKey || e.ctrlKey || e.shiftKey || e.metaKey ) ) {
                                                                        // This will hide the link we're just clicking on, which causes problems
-                                                                       // when done synchronously in at least Firefox 3.6 (bug 62858).
+                                                                       // when done synchronously in at least Firefox 3.6 (T64858).
                                                                        setTimeout( function () {
                                                                                $.suggestions.hide( context );
                                                                        }, 0 );
                                                                // Don't interfere with special clicks (e.g. to open in new tab)
                                                                if ( !( e.which !== 1 || e.altKey || e.ctrlKey || e.shiftKey || e.metaKey ) ) {
                                                                        // This will hide the link we're just clicking on, which causes problems
-                                                                       // when done synchronously in at least Firefox 3.6 (bug 62858).
+                                                                       // when done synchronously in at least Firefox 3.6 (T64858).
                                                                        setTimeout( function () {
                                                                                $.suggestions.hide( context );
                                                                        }, 0 );
index 1b64237..f84c091 100644 (file)
@@ -63,7 +63,7 @@
                var $node = $( node ),
                        // Use data-sort-value attribute.
                        // Use data() instead of attr() so that live value changes
-                       // are processed as well (bug 38152).
+                       // are processed as well (T40152).
                        data = $node.data( 'sortValue' );
 
                if ( data !== null && data !== undefined ) {
index c897302..c6ad945 100644 (file)
@@ -4,7 +4,7 @@
 ( function ( $ ) {
        if ( document.selection && document.selection.createRange ) {
                // On IE, patch the focus() method to restore the windows' scroll position
-               // (bug 32241)
+               // (T34241)
                $.fn.extend( {
                        focus: ( function ( jqFocus ) {
                                return function () {
@@ -56,7 +56,7 @@
                 */
                function activateElementOnIE( element ) {
                        if ( element.setActive ) {
-                               element.setActive(); // bug 32241: doesn't scroll
+                               element.setActive(); // T34241: doesn't scroll
                        } else {
                                $( element ).focus(); // may scroll (but we patched it above)
                        }
                                                        // IE
 
                                                        // Note that IE9 will trigger the next section unless we check this first.
-                                                       // See bug 35201.
+                                                       // See bug T37201.
 
                                                        activateElementOnIE( this );
                                                        if ( context ) {
                                                // IE doesn't properly report non-selected caret position through
                                                // the selection ranges when textarea isn't focused. This can
                                                // lead to saving a bogus empty selection, which then screws up
-                                               // whatever we do later (bug 31847).
+                                               // whatever we do later (T33847).
                                                activateElementOnIE( e );
 
                                                preFinished = false;
index 9b0c430..f68dbfa 100644 (file)
@@ -11,5 +11,5 @@
        display: inline-block;
        /* IE7 */
        zoom: 1;
-       *display: inline;
+       *display: inline; /* stylelint-disable declaration-block-no-duplicate-properties */
 }
index f26c336..15d0a39 100644 (file)
 
                // This should be moved down to '#editform', but is kept on the body for now
                // because the LiquidThreads extension is re-using this module with only half
-               // the EditPage (doesn't include #editform presumably, bug 55463).
+               // the EditPage (doesn't include #editform presumably, T57463).
                $( document.body ).on( 'click', '#wpPreview, #wpDiff', doLivePreview );
        } );
 
index 7439754..d89cd4a 100644 (file)
@@ -8,9 +8,9 @@
                        // Recheck preference so extensions can do a hack to disable this code.
                        if ( parseInt( mw.user.options.get( 'editondblclick' ), 10 ) ) {
                                e.preventDefault();
-                               // Trigger native HTMLElement click instead of opening URL (bug 43052)
+                               // Trigger native HTMLElement click instead of opening URL (T45052)
                                $a = $( '#ca-edit a' );
-                               // Not every page has an edit link (bug 57713)
+                               // Not every page has an edit link (T59713)
                                if ( $a.length ) {
                                        $a.get( 0 ).click();
                                }
index 1f0365e..d466216 100644 (file)
@@ -33,7 +33,7 @@
 
 /*
  * Add a checkered background image on hover for file
- * description pages. (bug 26470)
+ * description pages. (T28470)
  */
 .filehistory a img,
 #file img:hover {
@@ -76,6 +76,8 @@
        font-size: 0.8em;
        margin-left: 0.5em;
        margin-bottom: 0.5em;
+       border: 0;
+       border-collapse: collapse;
        width: 400px;
 }
 
        font-weight: bold;
 }
 
-.mw_metadata th {
-       font-weight: normal;
-       text-align: center;
-}
-
-.mw_metadata td {
-       padding: 0.1em;
-}
-
-.mw_metadata {
-       border: none;
-       border-collapse: collapse;
-}
-
 .mw_metadata td,
 .mw_metadata th {
        border: 1px solid #a2a9b1;
 
 .mw_metadata th {
        background-color: #f8f9fa;
+       font-weight: normal;
+       text-align: center;
 }
 
 .mw_metadata td {
        background-color: #fcfcfc;
+       padding-top: 0.1em;
+       padding-bottom: 0.1em;
 }
 
 .mw_metadata ul.metadata-langlist {
index 9a8edef..6e0010c 100644 (file)
@@ -16,7 +16,7 @@
        position: relative;
        top: 0.6em;
        left: -50%;
-       padding: .6em 3.6em .6em 1.1em;
+       padding: 0.6em 3.6em 0.6em 1.1em;
        line-height: 1.5625em;
        color: #626465;
        background-color: #f4f4f4;
@@ -55,7 +55,7 @@
 
 .postedit-close {
        position: absolute;
-       padding: 0 .8em;
+       padding: 0 0.8em;
        right: 0;
        top: 0;
        font-size: 1.25em;
index ada101e..ebd1ebc 100644 (file)
@@ -18,7 +18,7 @@ jQuery( function ( $ ) {
                // inside the heading (e.g. to do things like copy URL, open in new tab, ..).
                // e.target can be the heading, but it can also be anything inside the heading.
                if ( e.target.nodeName.toLowerCase() !== 'a' ) {
-                       // Trigger native HTMLElement click instead of opening URL (bug 43052)
+                       // Trigger native HTMLElement click instead of opening URL (T45052)
                        e.preventDefault();
                        $edit.get( 0 ).click();
                }
index ec94df3..7c2f92b 100644 (file)
@@ -182,22 +182,16 @@ a {
        content: " (https:" attr( href ) ")";
 }
 
-/* MSIE/Win doesn't understand 'inherit' */
 a,
 a.external,
 a.new,
 a.stub {
+       /* IE 6 & 7 don't understand `inherit` */
        color: #000 !important;
        text-decoration: none !important;
-}
-
-/* Continue ... */
-a,
-a.external,
-a.new,
-a.stub {
-       color: inherit !important;
-       text-decoration: inherit !important;
+       /* Modern browser will apply this, IE 6 & 7 ignore the unknown */
+       color: inherit !important; /* stylelint-disable-line declaration-block-no-duplicate-properties */
+       text-decoration: inherit !important; /* stylelint-disable-line declaration-block-no-duplicate-properties */
 }
 
 /**
@@ -258,7 +252,7 @@ html .thumbimage {
 }
 
 html .thumbcaption {
-       border: none;
+       border: 0;
        text-align: left;
        line-height: 1.4em;
        padding: 3px;
@@ -336,13 +330,13 @@ table.listing td {
 .catlinks li {
        display: inline-block;
        line-height: 1.15em;
-       padding: 0 .4em;
+       padding: 0 0.4em;
        border-left: 1pt solid #aaa;
        margin: 0.1em 0;
 }
 
 .catlinks li:first-child {
-       padding-left: .2em;
+       padding-left: 0.2em;
        border-left: 0;
 }
 
index 4daf77f..7c4dbb1 100644 (file)
@@ -32,7 +32,12 @@ h6 {
        font-size: 1em;
 }
 
-h1, h2, h3, h4, h5, h6 {
+h1,
+h2,
+h3,
+h4,
+h5,
+h6 {
        font-weight: bolder;
 }
 
@@ -78,7 +83,7 @@ table.rimage {
 
 /* thumbnails */
 div.thumb {
-       margin-bottom: .5em;
+       margin-bottom: 0.5em;
        border-style: solid;
        border-color: #fff;
        width: auto;
@@ -100,7 +105,7 @@ html .thumbimage {
 }
 
 html .thumbcaption {
-       border: none;
+       border: 0;
        line-height: 1.4em;
        padding: 3px;
        font-size: 94%;
@@ -136,15 +141,15 @@ div.magnify a {
 div.tright {
        clear: right;
        float: right;
-       border-width: .5em 0 .8em 1.4em;
+       border-width: 0.5em 0 0.8em 1.4em;
 }
 
 /* @noflip */
 div.tleft {
        float: left;
        clear: left;
-       margin-right: .5em;
-       border-width: .5em 1.4em .8em 0;
+       margin-right: 0.5em;
+       border-width: 0.5em 1.4em 0.8em 0;
 }
 
 img.thumbborder {
@@ -158,14 +163,14 @@ img.thumbborder {
 }
 
 img {
-       border: none;
+       border: 0;
 }
 
 #toc,
 .toc {
        border: 1px solid #bba;
        background-color: #f7f8ff;
-       padding: 5px;
+       padding: 7px;
        font-size: 95%;
        text-align: center;
        display: inline-block;
@@ -173,9 +178,7 @@ img {
 
        /* IE7 and earlier */
        zoom: 1;
-       *display: inline;
-
-       padding: 7px;
+       *display: inline; /* stylelint-disable-line declaration-block-no-duplicate-properties */
 }
 
 /* CSS for backwards-compatibility with cached page renders and creative uses in wikitext */
@@ -193,7 +196,7 @@ table.toc td {
 #toc h2,
 .toc h2 {
        display: inline;
-       border: none;
+       border: 0;
        padding: 0;
        font-size: 100%;
        font-weight: bold;
@@ -308,9 +311,7 @@ span.comment {
 }
 
 .editExternally {
-       border-style: solid;
-       border-width: 1px;
-       border-color: #808080;
+       border: 1px solid #808080;
        background: #fff;
        padding: 3px;
        margin-top: 0.5em;
@@ -333,25 +334,14 @@ li span.deleted {
 /* Classes for Exif data display */
 table.mw_metadata {
        margin-left: 0.5em;
+       border: 0;
+       border-collapse: collapse;
 }
 
 table.mw_metadata caption {
        font-weight: bold;
 }
 
-table.mw_metadata th {
-       font-weight: normal;
-}
-
-table.mw_metadata td {
-       padding: 0.1em;
-}
-
-table.mw_metadata {
-       border: none;
-       border-collapse: collapse;
-}
-
 table.mw_metadata td,
 table.mw_metadata th {
        border: 1px solid #aaa;
@@ -361,16 +351,18 @@ table.mw_metadata th {
 
 table.mw_metadata th {
        background-color: #f9f9f9;
+       font-weight: normal;
 }
 
 table.mw_metadata td {
        background-color: #fcfcfc;
+       padding-top: 0.1em;
+       padding-bottom: 0.1em;
 }
 
 table.mw_metadata td.spacer {
        background: inherit;
-       border-top: none;
-       border-bottom: none;
+       border-width: 0 1px;
 }
 
 .visualClear {
@@ -399,14 +391,14 @@ table.mw_metadata td.spacer {
 }
 
 div.multipageimagenavbox {
-       border: solid 1px #c0c0c0;
+       border: 1px solid #c0c0c0;
        padding: 4px;
        margin: 1em;
        background: #f0f0f0;
 }
 
 div.multipageimagenavbox div.thumb {
-       border: none;
+       border: 0;
        margin-left: 2em;
        margin-right: 2em;
 }
index 7919dc4..0d7512f 100644 (file)
@@ -83,10 +83,10 @@ abbr[title],
        cursor: help;
 }
 
-@supports (text-decoration: underline dotted) {
+@supports ( text-decoration: underline dotted ) {
        abbr[title],
        .explain[title] {
-               border-bottom: none;
+               border-bottom: 0;
                text-decoration: underline dotted;
        }
 }
@@ -166,6 +166,7 @@ div.patrollink {
  */
 td.mw-label {
        text-align: right;
+       vertical-align: middle;
 }
 
 td.mw-input {
@@ -174,13 +175,6 @@ td.mw-input {
 
 td.mw-submit {
        text-align: left;
-}
-
-td.mw-label {
-       vertical-align: middle;
-}
-
-td.mw-submit {
        white-space: nowrap;
 }
 
@@ -244,7 +238,7 @@ input#wpSummary:active {
 #catlinks {
        /**
         * Overrides text justification (user preference)
-        * See bug 31990
+        * See T33990
         */
        text-align: left;
 }
@@ -266,15 +260,15 @@ input#wpSummary:active {
        margin: 0.125em 0;
        padding: 0 0.5em;
        zoom: 1;
-       display: inline !ie;
+       display: inline !ie; /* stylelint-disable-line declaration-block-no-duplicate-properties */
 }
 
 .catlinks li:first-child {
        padding-left: 0.25em;
-       border-left: none;
+       border-left: 0;
 }
 
-/* (bug 5346) make category redirects italic */
+/* (T7346) make category redirects italic */
 .catlinks li a.mw-redirect {
        font-style: italic;
 }
@@ -346,7 +340,7 @@ th.mw-revdel-checkbox {
        text-align: center;
 }
 
-/* red links; see bug 36276 */
+/* red links; see T38276 */
 a.new {
        color: #ba0000;
 }
@@ -358,7 +352,7 @@ a.new {
        padding: 0 !important;
 }
 
-/* External URLs should always be treated as LTR (bug 4330) */
+/* External URLs should always be treated as LTR (T6330) */
 /* @noflip */ .rtl a.external.free,
 .rtl a.external.autonumber {
        direction: ltr;
@@ -418,11 +412,11 @@ table.wikitable > caption {
 .warningbox,
 .successbox {
        border: 1px solid;
-       padding: .5em 1em;
+       padding: 0.5em 1em;
        margin-bottom: 1em;
        display: inline-block;
        zoom: 1;
-       *display: inline;
+       *display: inline; /* stylelint-disable-line declaration-block-no-duplicate-properties */
 }
 
 .errorbox h2,
@@ -432,8 +426,8 @@ table.wikitable > caption {
        color: inherit;
        font-weight: bold;
        display: inline;
-       margin: 0 .5em 0 0;
-       border: none;
+       margin: 0 0.5em 0 0;
+       border: 0;
 }
 
 .errorbox {
@@ -576,96 +570,99 @@ table.wikitable > caption {
        background-repeat: no-repeat;
 }
 
-/* Language specific height correction for titles. Ref Bug 29405 and Bug 30809 */
+/* Language specific height correction for titles. Ref T31405 and T32809 */
 /* Languages like hi or ml require slightly more vertical space to show diacritics properly */
-h1:lang(anp),
-h1:lang(as),
-h1:lang(bh), /* Macrolanguage, used on bh.wikipedia.org, should be removed one day */
-h1:lang(bho),
-h1:lang(bn),
-h1:lang(gu),
-h1:lang(hi),
-h1:lang(kn),
-h1:lang(ks),
-h1:lang(ml),
-h1:lang(mr),
-h1:lang(my),
-h1:lang(mai),
-h1:lang(ne),
-h1:lang(new),
-h1:lang(or),
-h1:lang(pa),
-h1:lang(pi),
-h1:lang(sa),
-h1:lang(ta),
-h1:lang(te) {
+h1:lang( anp ),
+h1:lang( as ),
+h1:lang( bh ), /* Macrolanguage, used on bh.wikipedia.org, should be removed one day */
+h1:lang( bho ),
+h1:lang( bn ),
+h1:lang( gu ),
+h1:lang( hi ),
+h1:lang( kn ),
+h1:lang( ks ),
+h1:lang( ml ),
+h1:lang( mr ),
+h1:lang( my ),
+h1:lang( mai ),
+h1:lang( ne ),
+h1:lang( new ),
+h1:lang( or ),
+h1:lang( pa ),
+h1:lang( pi ),
+h1:lang( sa ),
+h1:lang( ta ),
+h1:lang( te ) {
        line-height: 1.6em !important;
 }
 
-h2:lang(anp), h3:lang(anp), h4:lang(anp), h5:lang(anp), h6:lang(anp),
-h2:lang(as), h3:lang(as), h4:lang(as), h5:lang(as), h6:lang(as),
-h2:lang(bho), h3:lang(bho), h4:lang(bho), h5:lang(bho), h6:lang(bho),
-h2:lang(bh), h3:lang(bh), h4:lang(bh), h5:lang(bh), h6:lang(bh),
-h2:lang(bn), h3:lang(bn), h4:lang(bn), h5:lang(bn), h6:lang(bn),
-h2:lang(gu), h3:lang(gu), h4:lang(gu), h5:lang(gu), h6:lang(gu),
-h2:lang(hi), h3:lang(hi), h4:lang(hi), h5:lang(hi), h6:lang(hi),
-h2:lang(kn), h3:lang(kn), h4:lang(kn), h5:lang(kn), h6:lang(kn),
-h2:lang(ks), h3:lang(ks), h4:lang(ks), h5:lang(ks), h6:lang(ks),
-h2:lang(ml), h3:lang(ml), h4:lang(ml), h5:lang(ml), h6:lang(ml),
-h2:lang(mr), h3:lang(mr), h4:lang(mr), h5:lang(mr), h6:lang(mr),
-h2:lang(my), h3:lang(my), h4:lang(my), h5:lang(my), h6:lang(my),
-h2:lang(mai), h3:lang(mai), h4:lang(mai), h5:lang(mai), h6:lang(mai),
-h2:lang(ne), h3:lang(ne), h4:lang(ne), h5:lang(ne), h6:lang(ne),
-h2:lang(new), h3:lang(new), h4:lang(new), h5:lang(new), h6:lang(new),
-h2:lang(or), h3:lang(or), h4:lang(or), h5:lang(or), h6:lang(or),
-h2:lang(pa), h3:lang(pa), h4:lang(pa), h5:lang(pa), h6:lang(pa),
-h2:lang(pi), h3:lang(pi), h4:lang(pi), h5:lang(pi), h6:lang(pi),
-h2:lang(sa), h3:lang(sa), h4:lang(sa), h5:lang(sa), h6:lang(sa),
-h2:lang(ta), h3:lang(ta), h4:lang(ta), h5:lang(ta), h6:lang(ta),
-h2:lang(te), h3:lang(te), h4:lang(te), h5:lang(te), h6:lang(te) {
+/* stylelint-disable selector-list-comma-newline-after */
+h2:lang( anp ), h3:lang( anp ), h4:lang( anp ), h5:lang( anp ), h6:lang( anp ),
+h2:lang( as ), h3:lang( as ), h4:lang( as ), h5:lang( as ), h6:lang( as ),
+h2:lang( bho ), h3:lang( bho ), h4:lang( bho ), h5:lang( bho ), h6:lang( bho ),
+h2:lang( bh ), h3:lang( bh ), h4:lang( bh ), h5:lang( bh ), h6:lang( bh ),
+h2:lang( bn ), h3:lang( bn ), h4:lang( bn ), h5:lang( bn ), h6:lang( bn ),
+h2:lang( gu ), h3:lang( gu ), h4:lang( gu ), h5:lang( gu ), h6:lang( gu ),
+h2:lang( hi ), h3:lang( hi ), h4:lang( hi ), h5:lang( hi ), h6:lang( hi ),
+h2:lang( kn ), h3:lang( kn ), h4:lang( kn ), h5:lang( kn ), h6:lang( kn ),
+h2:lang( ks ), h3:lang( ks ), h4:lang( ks ), h5:lang( ks ), h6:lang( ks ),
+h2:lang( ml ), h3:lang( ml ), h4:lang( ml ), h5:lang( ml ), h6:lang( ml ),
+h2:lang( mr ), h3:lang( mr ), h4:lang( mr ), h5:lang( mr ), h6:lang( mr ),
+h2:lang( my ), h3:lang( my ), h4:lang( my ), h5:lang( my ), h6:lang( my ),
+h2:lang( mai ), h3:lang( mai ), h4:lang( mai ), h5:lang( mai ), h6:lang( mai ),
+h2:lang( ne ), h3:lang( ne ), h4:lang( ne ), h5:lang( ne ), h6:lang( ne ),
+h2:lang( new ), h3:lang( new ), h4:lang( new ), h5:lang( new ), h6:lang( new ),
+h2:lang( or ), h3:lang( or ), h4:lang( or ), h5:lang( or ), h6:lang( or ),
+h2:lang( pa ), h3:lang( pa ), h4:lang( pa ), h5:lang( pa ), h6:lang( pa ),
+h2:lang( pi ), h3:lang( pi ), h4:lang( pi ), h5:lang( pi ), h6:lang( pi ),
+h2:lang( sa ), h3:lang( sa ), h4:lang( sa ), h5:lang( sa ), h6:lang( sa ),
+h2:lang( ta ), h3:lang( ta ), h4:lang( ta ), h5:lang( ta ), h6:lang( ta ),
+h2:lang( te ), h3:lang( te ), h4:lang( te ), h5:lang( te ), h6:lang( te ) {
        line-height: 1.2em;
 }
+/* stylelint-enable selector-list-comma-newline-after */
 
 /* Localised ordered list numbering for some languages */
-ol:lang(azb) li,
-ol:lang(bcc) li,
-ol:lang(bgn) li,
-ol:lang(bqi) li,
-ol:lang(fa) li,
-ol:lang(glk) li,
-ol:lang(kk-arab) li,
-ol:lang(lrc) li,
-ol:lang(luz) li,
-ol:lang(mzn) li {
+ol:lang( azb ) li,
+ol:lang( bcc ) li,
+ol:lang( bgn ) li,
+ol:lang( bqi ) li,
+ol:lang( fa ) li,
+ol:lang( glk ) li,
+ol:lang( kk-arab ) li,
+ol:lang( lrc ) li,
+ol:lang( luz ) li,
+ol:lang( mzn ) li {
        list-style-type: -moz-persian;
        list-style-type: persian;
 }
 
-ol:lang(ckb) li,
-ol:lang(sdh) li {
+ol:lang( ckb ) li,
+ol:lang( sdh ) li {
        list-style-type: -moz-arabic-indic;
        list-style-type: arabic-indic;
 }
 
-ol:lang(hi) li,
-ol:lang(mr) li {
+ol:lang( hi ) li,
+ol:lang( mr ) li {
        list-style-type: -moz-devanagari;
        list-style-type: devanagari;
 }
 
-ol:lang(as) li,
-ol:lang(bn) li {
+ol:lang( as ) li,
+ol:lang( bn ) li {
        list-style-type: -moz-bengali;
        list-style-type: bengali;
 }
 
-ol:lang(or) li {
+ol:lang( or ) li {
        list-style-type: -moz-oriya;
        list-style-type: oriya;
 }
 
-#toc ul, .toc ul {
-       margin: .3em 0;
+#toc ul,
+.toc ul {
+       margin: 0.3em 0;
 }
 
 /* Correct directionality when page dir is different from site/user dir */
@@ -742,7 +739,7 @@ table.floatleft {
        position: relative;
 }
 
-/* bug 12205 */
+/* T14205 */
 #mw-credits a {
        unicode-bidi: embed;
 }
index fd615b7..651a018 100644 (file)
@@ -9,4 +9,4 @@
        -webkit-transform: rotate( @deg );
        -moz-transform: rotate( @deg );
        transform: rotate( @deg );
-}
\ No newline at end of file
+}
index f21de4b..4cca1a6 100644 (file)
        order: @order;
 }
 
+/* stylelint-disable selector-no-vendor-prefix, at-rule-no-unknown */
+.mixin-placeholder( @rules ) {
+       // WebKit, Blink, Edge
+       &::-webkit-input-placeholder {
+               @rules();
+       }
+       // Internet Explorer 10-11
+       &:-ms-input-placeholder {
+               @rules();
+       }
+       // Firefox 19-
+       &::-moz-placeholder {
+               @rules();
+       }
+       // Firefox 4-18
+       &:-moz-placeholder {
+               @rules();
+       }
+       // W3C Standard Selectors Level 4
+       &::placeholder {
+               @rules();
+       }
+       // For inputs that use jquery.placeholder.js e.g. IE9
+       &.placeholder {
+               @rules();
+       }
+}
+/* stylelint-enable selector-no-vendor-prefix, at-rule-no-unknown */
 
 // Screen Reader Helper Mixin
 .mixin-screen-reader-text() {
index 39c7667..675f4b5 100644 (file)
@@ -17,6 +17,7 @@
         * @cfg {boolean} [selected] The item is selected
         * @cfg {string[]} [subset] Defining the names of filters that are a subset of this filter
         * @cfg {string[]} [conflictsWith] Defining the names of filters that conflict with this item
+        * @cfg {string} [cssClass] The class identifying the results that match this filter
         */
        mw.rcfilters.dm.FilterItem = function MwRcfiltersDmFilterItem( name, groupModel, config ) {
                config = config || {};
                this.included = false;
                this.conflicted = false;
                this.fullyCovered = false;
+
+               // Highlight
+               this.cssClass = config.cssClass;
+               this.highlightColor = null;
+               this.highlightEnabled = false;
        };
 
        /* Initialization */
                        this.emit( 'update' );
                }
        };
+
+       /**
+        * Set the highlight color
+        *
+        * @param {string|null} highlightColor
+        */
+       mw.rcfilters.dm.FilterItem.prototype.setHighlightColor = function ( highlightColor ) {
+               if ( this.highlightColor !== highlightColor ) {
+                       this.highlightColor = highlightColor;
+                       this.emit( 'update' );
+               }
+       };
+
+       /**
+        * Clear the highlight color
+        */
+       mw.rcfilters.dm.FilterItem.prototype.clearHighlightColor = function () {
+               this.setHighlightColor( null );
+       };
+
+       /**
+        * Get the highlight color, or null if none is configured
+        *
+        * @return {string|null}
+        */
+       mw.rcfilters.dm.FilterItem.prototype.getHighlightColor = function () {
+               return this.highlightColor;
+       };
+
+       /**
+        * Get the CSS class that matches changes that fit this filter
+        * or null if none is configured
+        *
+        * @return {string|null}
+        */
+       mw.rcfilters.dm.FilterItem.prototype.getCssClass = function () {
+               return this.cssClass;
+       };
+
+       /**
+        * Toggle the highlight feature on and off for this filter.
+        * It only works if highlight is supported for this filter.
+        *
+        * @param {boolean} enable Highlight should be enabled
+        */
+       mw.rcfilters.dm.FilterItem.prototype.toggleHighlight = function ( enable ) {
+               enable = enable === undefined ? !this.highlightEnabled : enable;
+
+               if ( !this.isHighlightSupported() ) {
+                       return;
+               }
+
+               if ( enable === this.highlightEnabled ) {
+                       return;
+               }
+
+               this.highlightEnabled = enable;
+               this.emit( 'update' );
+       };
+
+       /**
+        * Check if the highlight feature is currently enabled for this filter
+        *
+        * @return {boolean}
+        */
+       mw.rcfilters.dm.FilterItem.prototype.isHighlightEnabled = function () {
+               return !!this.highlightEnabled;
+       };
+
+       /**
+        * Check if the highlight feature is supported for this filter
+        *
+        * @return {boolean}
+        */
+       mw.rcfilters.dm.FilterItem.prototype.isHighlightSupported = function () {
+               return !!this.getCssClass();
+       };
 }( mediaWiki ) );
index 13f7d31..d58eb2e 100644 (file)
@@ -15,6 +15,7 @@
                this.groups = {};
                this.defaultParams = {};
                this.defaultFiltersEmpty = null;
+               this.highlightEnabled = false;
 
                // Events
                this.aggregate( { update: 'filterItemUpdate' } );
         * Filter item has changed
         */
 
+       /**
+        * @event highlightChange
+        * @param {boolean} Highlight feature is enabled
+        *
+        * Highlight feature has been toggled enabled or disabled
+        */
+
        /* Methods */
 
        /**
                                        group: group,
                                        label: data.filters[ i ].label,
                                        description: data.filters[ i ].description,
-                                       subset: data.filters[ i ].subset
+                                       subset: data.filters[ i ].subset,
+                                       cssClass: data.filters[ i ].class
                                } );
 
                                // For convenience, we should store each filter's "supersets" -- these are
                return result;
        };
 
+       /**
+        * Get the highlight parameters based on current filter configuration
+        *
+        * @return {object} Object where keys are "<filter name>_color" and values
+        *                  are the selected highlight colors.
+        */
+       mw.rcfilters.dm.FiltersViewModel.prototype.getHighlightParameters = function () {
+               var result = { highlight: this.isHighlightEnabled() };
+
+               this.getItems().forEach( function ( filterItem ) {
+                       result[ filterItem.getName() + '_color' ] = filterItem.getHighlightColor();
+               } );
+               return result;
+       };
+
        /**
         * Sanitize value group of a string_option groups type
         * Remove duplicates and make sure to only use valid
         * @return {boolean} Current filters are all empty
         */
        mw.rcfilters.dm.FiltersViewModel.prototype.areCurrentFiltersEmpty = function () {
-               var currFilters = this.getSelectedState();
-
-               return Object.keys( currFilters ).every( function ( filterName ) {
-                       return !currFilters[ filterName ];
+               var model = this;
+
+               // Check if there are either any selected items or any items
+               // that have highlight enabled
+               return !this.getItems().some( function ( filterItem ) {
+                       return (
+                               filterItem.isSelected() ||
+                               ( model.isHighlightEnabled() && filterItem.getHighlightColor() )
+                       );
                } );
        };
 
                return result;
        };
 
+       /**
+        * Get items that are highlighted
+        *
+        * @return {mw.rcfilters.dm.FilterItem[]} Highlighted items
+        */
+       mw.rcfilters.dm.FiltersViewModel.prototype.getHighlightedItems = function () {
+               return this.getItems().filter( function ( filterItem ) {
+                       return filterItem.isHighlightSupported() &&
+                               filterItem.getHighlightColor();
+               } );
+       };
+
+       /**
+        * Toggle the highlight feature on and off.
+        * Propagate the change to filter items.
+        *
+        * @param {boolean} enable Highlight should be enabled
+        * @fires highlightChange
+        */
+       mw.rcfilters.dm.FiltersViewModel.prototype.toggleHighlight = function ( enable ) {
+               enable = enable === undefined ? !this.highlightEnabled : enable;
+
+               if ( this.highlightEnabled !== enable ) {
+                       this.highlightEnabled = enable;
+
+                       this.getItems().forEach( function ( filterItem ) {
+                               filterItem.toggleHighlight( this.highlightEnabled );
+                       }.bind( this ) );
+
+                       this.emit( 'highlightChange', this.highlightEnabled );
+               }
+       };
+
+       /**
+        * Check if the highlight feature is enabled
+        * @return {boolean}
+        */
+       mw.rcfilters.dm.FiltersViewModel.prototype.isHighlightEnabled = function () {
+               return this.highlightEnabled;
+       };
+
+       /**
+        * Set highlight color for a specific filter item
+        *
+        * @param {string} filterName Name of the filter item
+        * @param {string} color Selected color
+        */
+       mw.rcfilters.dm.FiltersViewModel.prototype.setHighlightColor = function ( filterName, color ) {
+               this.getItemByName( filterName ).setHighlightColor( color );
+       };
+
+       /**
+        * Clear highlight for a specific filter item
+        *
+        * @param {string} filterName Name of the filter item
+        */
+       mw.rcfilters.dm.FiltersViewModel.prototype.clearHighlightColor = function ( filterName ) {
+               this.getItemByName( filterName ).clearHighlightColor();
+       };
+
+       /**
+        * Clear highlight for all filter items
+        */
+       mw.rcfilters.dm.FiltersViewModel.prototype.clearAllHighlightColors = function () {
+               this.getItems().forEach( function ( filterItem ) {
+                       filterItem.clearHighlightColor();
+               } );
+       };
 }( mediaWiki, jQuery ) );
index ff34bb8..1df31a2 100644 (file)
                        )
                );
 
+               // Initialize highlights
+               this.filtersModel.toggleHighlight( !!uri.query.highlight );
+               this.filtersModel.getItems().forEach( function ( filterItem ) {
+                       var color = uri.query[ filterItem.getName() + '_color' ];
+                       if ( !color ) {
+                               return;
+                       }
+
+                       filterItem.setHighlightColor( color );
+               } );
+
                // Check all filter interactions
                this.filtersModel.reassessFilterInteractions();
        };
@@ -48,6 +59,9 @@
         */
        mw.rcfilters.Controller.prototype.resetToDefaults = function () {
                this.filtersModel.setFiltersToDefaults();
+               // Check all filter interactions
+               this.filtersModel.reassessFilterInteractions();
+
                this.updateURL();
                this.updateChangesList();
        };
         */
        mw.rcfilters.Controller.prototype.emptyFilters = function () {
                this.filtersModel.emptyAllFilters();
+               this.filtersModel.clearAllHighlightColors();
+               // Check all filter interactions
+               this.filtersModel.reassessFilterInteractions();
+
                this.updateURL();
                this.updateChangesList();
        };
         * @param {boolean} isSelected Filter selected state
         */
        mw.rcfilters.Controller.prototype.updateFilter = function ( filterName, isSelected ) {
-               var obj = {};
+               var obj = {},
+                       filterItem = this.filtersModel.getItemByName( filterName );
 
-               obj[ filterName ] = isSelected;
+               if ( filterItem.isSelected() !== isSelected ) {
+                       obj[ filterName ] = isSelected;
+                       this.filtersModel.updateFilters( obj );
 
-               this.filtersModel.updateFilters( obj );
-               this.updateURL();
-               this.updateChangesList();
+                       this.updateURL();
+                       this.updateChangesList();
 
-               // Check filter interactions
-               this.filtersModel.reassessFilterInteractions( this.filtersModel.getItemByName( filterName ) );
+                       // Check filter interactions
+                       this.filtersModel.reassessFilterInteractions( this.filtersModel.getItemByName( filterName ) );
+               }
        };
 
        /**
         * Update the URL of the page to reflect current filters
         */
        mw.rcfilters.Controller.prototype.updateURL = function () {
-               var uri = new mw.Uri();
+               var uri = this.getUpdatedUri();
+               window.history.pushState( { tag: 'rcfilters' }, document.title, uri.toString() );
+       };
+
+       /**
+        * Get an updated mw.Uri object based on the model state
+        *
+        * @return {mw.Uri} Updated Uri
+        */
+       mw.rcfilters.Controller.prototype.getUpdatedUri = function () {
+               var uri = new mw.Uri(),
+                       highlightParams = this.filtersModel.getHighlightParameters();
 
                // Add to existing queries in URL
                // TODO: Clean up the list of filters; perhaps 'falsy' filters
                // and see if current state of a specific filter is needed?
                uri.extend( this.filtersModel.getParametersFromFilters() );
 
-               // Update the URL itself
-               window.history.pushState( { tag: 'rcfilters' }, document.title, uri.toString() );
+               // highlight params
+               Object.keys( highlightParams ).forEach( function ( paramName ) {
+                       if ( highlightParams[ paramName ] ) {
+                               uri.query[ paramName ] = highlightParams[ paramName ];
+                       } else {
+                               delete uri.query[ paramName ];
+                       }
+               } );
+
+               return uri;
        };
 
        /**
         * Fetch the list of changes from the server for the current filters
         *
-        * @returns {jQuery.Promise} Promise object that will resolve with the changes list
+        * @return {jQuery.Promise} Promise object that will resolve with the changes list
         */
        mw.rcfilters.Controller.prototype.fetchChangesList = function () {
-               var uri = new mw.Uri(),
+               var uri = this.getUpdatedUri(),
                        requestId = ++this.requestCounter,
                        latestRequest = function () {
                                return requestId === this.requestCounter;
                                }
                        }.bind( this ) );
        };
+
+       /**
+        * Toggle the highlight feature on and off
+        */
+       mw.rcfilters.Controller.prototype.toggleHighlight = function () {
+               this.filtersModel.toggleHighlight();
+               this.updateURL();
+       };
+
+       /**
+        * Set the highlight color for a filter item
+        *
+        * @param {string} filterName Name of the filter item
+        * @param {string} color Selected color
+        */
+       mw.rcfilters.Controller.prototype.setHighlightColor = function ( filterName, color ) {
+               this.filtersModel.setHighlightColor( filterName, color );
+               this.updateURL();
+       };
+
+       /**
+        * Clear highlight for a filter item
+        *
+        * @param {string} filterName Name of the filter item
+        */
+       mw.rcfilters.Controller.prototype.clearHighlightColor = function ( filterName ) {
+               this.filtersModel.clearHighlightColor( filterName );
+               this.updateURL();
+       };
 }( mediaWiki, jQuery ) );
diff --git a/resources/src/mediawiki.rcfilters/mw.rcfilters.HighlightColors.js b/resources/src/mediawiki.rcfilters/mw.rcfilters.HighlightColors.js
new file mode 100644 (file)
index 0000000..ebeaad6
--- /dev/null
@@ -0,0 +1,9 @@
+( function ( mw ) {
+       /**
+        * Supported highlight colors.
+        * Warning: These are also hardcoded in "styles/mw.rcfilters.variables.less"
+        *
+        * @type {string[]}
+        */
+       mw.rcfilters.HighlightColors = [ 'c1', 'c2', 'c3', 'c4', 'c5' ];
+}( mediaWiki ) );
index 61df2e8..33e9f57 100644 (file)
@@ -19,7 +19,7 @@
 
                        // eslint-disable-next-line no-new
                        new mw.rcfilters.ui.ChangesListWrapperWidget(
-                               changesListModel, $( '.mw-changeslist, .mw-changeslist-empty' ) );
+                               filtersModel, changesListModel, $( '.mw-changeslist, .mw-changeslist-empty' ) );
 
                        // eslint-disable-next-line no-new
                        new mw.rcfilters.ui.FormWrapperWidget(
                                                {
                                                        name: 'hideliu',
                                                        label: mw.msg( 'rcfilters-filter-registered-label' ),
-                                                       description: mw.msg( 'rcfilters-filter-registered-description' )
+                                                       description: mw.msg( 'rcfilters-filter-registered-description' ),
+                                                       'class': 'mw-changeslist-liu'
                                                },
                                                {
                                                        name: 'hideanons',
                                                        label: mw.msg( 'rcfilters-filter-unregistered-label' ),
-                                                       description: mw.msg( 'rcfilters-filter-unregistered-description' )
+                                                       description: mw.msg( 'rcfilters-filter-unregistered-description' ),
+                                                       'class': 'mw-changeslist-anon'
                                                }
                                        ]
                                },
                                                        name: 'newcomer',
                                                        label: mw.msg( 'rcfilters-filter-userExpLevel-newcomer-label' ),
                                                        description: mw.msg( 'rcfilters-filter-userExpLevel-newcomer-description' ),
-                                                       conflicts: [ 'hideanons' ]
+                                                       conflicts: [ 'hideanons' ],
+                                                       'class': 'mw-changeslist-user-newcomer'
                                                },
                                                {
                                                        name: 'learner',
                                                        label: mw.msg( 'rcfilters-filter-userExpLevel-learner-label' ),
                                                        description: mw.msg( 'rcfilters-filter-userExpLevel-learner-description' ),
-                                                       conflicts: [ 'hideanons' ]
+                                                       conflicts: [ 'hideanons' ],
+                                                       'class': 'mw-changeslist-user-learner'
                                                },
                                                {
                                                        name: 'experienced',
                                                        label: mw.msg( 'rcfilters-filter-userExpLevel-experienced-label' ),
                                                        description: mw.msg( 'rcfilters-filter-userExpLevel-experienced-description' ),
-                                                       conflicts: [ 'hideanons' ]
+                                                       conflicts: [ 'hideanons' ],
+                                                       'class': 'mw-changeslist-user-experienced'
                                                }
                                        ]
                                },
                                                {
                                                        name: 'hidemyself',
                                                        label: mw.msg( 'rcfilters-filter-editsbyself-label' ),
-                                                       description: mw.msg( 'rcfilters-filter-editsbyself-description' )
+                                                       description: mw.msg( 'rcfilters-filter-editsbyself-description' ),
+                                                       'class': 'mw-changeslist-self'
                                                },
                                                {
                                                        name: 'hidebyothers',
                                                        label: mw.msg( 'rcfilters-filter-editsbyother-label' ),
-                                                       description: mw.msg( 'rcfilters-filter-editsbyother-description' )
+                                                       description: mw.msg( 'rcfilters-filter-editsbyother-description' ),
+                                                       'class': 'mw-changeslist-others'
                                                }
                                        ]
                                },
                                                        name: 'hidebots',
                                                        label: mw.msg( 'rcfilters-filter-bots-label' ),
                                                        description: mw.msg( 'rcfilters-filter-bots-description' ),
-                                                       'default': true
+                                                       'default': true,
+                                                       'class': 'mw-changeslist-bot'
                                                },
                                                {
                                                        name: 'hidehumans',
                                                        label: mw.msg( 'rcfilters-filter-humans-label' ),
                                                        description: mw.msg( 'rcfilters-filter-humans-description' ),
-                                                       'default': false
+                                                       'default': false,
+                                                       'class': 'mw-changeslist-human'
                                                }
                                        ]
                                },
                                                {
                                                        name: 'hideminor',
                                                        label: mw.msg( 'rcfilters-filter-minor-label' ),
-                                                       description: mw.msg( 'rcfilters-filter-minor-description' )
+                                                       description: mw.msg( 'rcfilters-filter-minor-description' ),
+                                                       'class': 'mw-changeslist-minor'
                                                },
                                                {
                                                        name: 'hidemajor',
                                                        label: mw.msg( 'rcfilters-filter-major-label' ),
-                                                       description: mw.msg( 'rcfilters-filter-major-description' )
+                                                       description: mw.msg( 'rcfilters-filter-major-description' ),
+                                                       'class': 'mw-changeslist-major'
                                                }
                                        ]
                                },
                                                        name: 'hidepageedits',
                                                        label: mw.msg( 'rcfilters-filter-pageedits-label' ),
                                                        description: mw.msg( 'rcfilters-filter-pageedits-description' ),
-                                                       'default': false
+                                                       'default': false,
+                                                       'class': 'mw-changeslist-src-mw-edit'
+
                                                },
                                                {
                                                        name: 'hidenewpages',
                                                        label: mw.msg( 'rcfilters-filter-newpages-label' ),
                                                        description: mw.msg( 'rcfilters-filter-newpages-description' ),
-                                                       'default': false
+                                                       'default': false,
+                                                       'class': 'mw-changeslist-src-mw-new'
                                                },
                                                {
                                                        name: 'hidecategorization',
                                                        label: mw.msg( 'rcfilters-filter-categorization-label' ),
                                                        description: mw.msg( 'rcfilters-filter-categorization-description' ),
-                                                       'default': true
+                                                       'default': true,
+                                                       'class': 'mw-changeslist-src-mw-categorize'
                                                },
                                                {
                                                        name: 'hidelog',
                                                        label: mw.msg( 'rcfilters-filter-logactions-label' ),
                                                        description: mw.msg( 'rcfilters-filter-logactions-description' ),
-                                                       'default': false
+                                                       'default': false,
+                                                       'class': 'mw-changeslist-src-mw-log'
                                                }
                                        ]
                                }
diff --git a/resources/src/mediawiki.rcfilters/styles/mw.rcfilters.less b/resources/src/mediawiki.rcfilters/styles/mw.rcfilters.less
new file mode 100644 (file)
index 0000000..8423363
--- /dev/null
@@ -0,0 +1,9 @@
+// Corrections for the standard special page
+.rcoptions {
+       border: 0;
+       border-bottom: 1px solid #a2a9b1;
+
+       legend {
+               display: none;
+       }
+}
diff --git a/resources/src/mediawiki.rcfilters/styles/mw.rcfilters.mixins.less b/resources/src/mediawiki.rcfilters/styles/mw.rcfilters.mixins.less
new file mode 100644 (file)
index 0000000..5c31b5d
--- /dev/null
@@ -0,0 +1,63 @@
+@import "mediawiki.mixins";
+@import "mw.rcfilters.variables";
+
+// This is a general mixin for a color circle
+.mw-rcfilters-mixin-circle( @color: white, @diameter: 2em, @padding: 0.5em, @border: false ) {
+       border-radius: 50%;
+       min-width: @diameter;
+       width: @diameter;
+       min-height: @diameter;
+       height: @diameter;
+       margin: @padding;
+       .box-sizing( border-box );
+
+       background-color: @color;
+
+       & when (@border = true) {
+               border: 1px solid #565656;
+       }
+}
+
+// This is the circle that appears next to the results
+// Its visibility is directly dependent on whether there is
+// a color class on its parent element
+.result-circle( @colorName: 'none' ) {
+       &-@{colorName} {
+               .mw-rcfilters-mixin-circle( ~"@{highlight-@{colorName}}", @result-circle-diameter, 0 );
+               display: none;
+
+               .mw-rcfilters-highlight-color-@{colorName} & {
+                       display: inline-block;
+               }
+       }
+}
+
+// This mixin produces color mixes for two, three and four colors
+.highlight-color-mix( @color1, @color2, @color3: false, @color4: false ) {
+       @highlight-color-class-var: ~".mw-rcfilters-highlight-color-@{color1}.mw-rcfilters-highlight-color-@{color2}";
+
+       // The nature of these variables and them being inside
+       // a 'tint' and 'average' LESS functions is such where
+       // the parsing is failing if it is done inside those functions.
+       // Instead, we first construct their LESS variable names,
+       // and then we call them inside those functions by calling @@var
+       @c1var: ~"highlight-@{color1}";
+       @c2var: ~"highlight-@{color2}";
+
+       // Two colors
+       @{highlight-color-class-var} when ( @color3 = false ) and ( @color4 = false ) and not ( @color1 = false ), ( @color2 = false ) {
+               background-color: tint( average( @@c1var, @@c2var ), 50% );
+       }
+       // Three colors
+       @{highlight-color-class-var}.mw-rcfilters-highlight-color-@{color3} when ( @color4 = false ) and not ( @color3 = false ) {
+               @c3var: ~"highlight-@{color3}";
+               background-color: tint( mix( @@c1var, average( @@c2var, @@c3var ), 33% ), 30% );
+       }
+
+       // Four colors
+       @{highlight-color-class-var}.mw-rcfilters-highlight-color-@{color3}.mw-rcfilters-highlight-color-@{color4} when not ( @color4 = false ) {
+               @c3var: ~"highlight-@{color3}";
+               @c4var: ~"highlight-@{color4}";
+               background-color: tint( mix( @@c1var, mix( @@c2var, average( @@c3var, @@c4var ), 25% ), 25% ), 25% );
+       }
+}
index 8a9ad54..2521899 100644 (file)
@@ -1,14 +1,50 @@
+@import "mw.rcfilters.mixins";
+
 .mw-rcfilters-ui-capsuleItemWidget {
-       &-popup {
-               padding: 1em;
+       &-popup-content {
+               padding: 0.5em;
+               color: #54595d;
        }
 
-       .oo-ui-popupWidget {
-               // Fix the positioning of the popup itself
-               margin-top: 1em;
+       &.oo-ui-labelElement .oo-ui-labelElement-label {
+               vertical-align: middle;
+               cursor: pointer;
        }
 
        &-muted {
-               opacity: 0.5;
+               // Muted state
+               // We want everything muted except the circle
+               background-color: rgba( 255, 255, 255, @muted-opacity );
+
+               .oo-ui-labelElement-label,
+               .oo-ui-buttonWidget {
+                       opacity: @muted-opacity;
+               }
+       }
+
+       &-highlight {
+               display: none;
+               padding-right: 0.5em;
+
+               &-highlighted {
+                       display: inline-block;
+
+               }
+
+               &[data-color="c1"] {
+                       .mw-rcfilters-mixin-circle( @highlight-c1, 0.7em, ~"0 0.5em 0 0" );
+               }
+               &[data-color="c2"] {
+                       .mw-rcfilters-mixin-circle( @highlight-c2, 0.7em, ~"0 0.5em 0 0" );
+               }
+               &[data-color="c3"] {
+                       .mw-rcfilters-mixin-circle( @highlight-c3, 0.7em, ~"0 0.5em 0 0" );
+               }
+               &[data-color="c4"] {
+                       .mw-rcfilters-mixin-circle( @highlight-c4, 0.7em, ~"0 0.5em 0 0" );
+               }
+               &[data-color="c5"] {
+                       .mw-rcfilters-mixin-circle( @highlight-c5, 0.7em, ~"0 0.5em 0 0" );
+               }
        }
 }
diff --git a/resources/src/mediawiki.rcfilters/styles/mw.rcfilters.ui.ChangesListWrapperWidget.less b/resources/src/mediawiki.rcfilters/styles/mw.rcfilters.ui.ChangesListWrapperWidget.less
new file mode 100644 (file)
index 0000000..5ad2a19
--- /dev/null
@@ -0,0 +1,125 @@
+@import 'mw.rcfilters.mixins';
+
+.mw-rcfilters-ui-changesListWrapperWidget {
+       &-highlighted {
+               ul {
+                       list-style: none;
+                       // Each li's margin-left should be the width of the highlights
+                       // element + the margin
+                       margin-left: ~"calc( ( @{result-circle-diameter} + @{result-circle-margin} ) * 5 + @{result-circle-general-margin} )";
+               }
+       }
+
+       // Correction for Enhanced RC
+       // This is outside the scope of the 'highlights' wrapper
+       table.mw-enhanced-rc {
+               margin-left: ~"calc( ( @{result-circle-diameter} + @{result-circle-margin} ) * 5 + @{result-circle-general-margin} )";
+
+               td:last-child {
+                       width: 100%;
+               }
+       }
+
+       &-highlights {
+               display: none;
+               padding: 0 @result-circle-general-margin 0 0;
+               text-align: right;
+               // The width is 5 circles times their diameter + individual margin
+               // and then plus the general margin
+               width: ~"calc( ( @{result-circle-diameter} + @{result-circle-margin} ) * 5 )";
+               // And we want to shift the entire block to the left of the li
+               position: absolute;
+               left: 0;
+
+               .mw-rcfilters-ui-changesListWrapperWidget-highlighted & {
+                       display: inline-block;
+               }
+
+               div {
+                       .box-sizing( border-box );
+                       margin-right: @result-circle-margin;
+                       vertical-align: middle;
+                       // This is to make the dots appear at the center of the
+                       // text itself; it's a horrendous hack and blame JamesF for it.
+                       margin-top: -2px;
+               }
+
+               &-color {
+
+                       &-none {
+                               .mw-rcfilters-mixin-circle( @highlight-none, @result-circle-diameter, 0, true );
+                               display: inline-block;
+
+                               .mw-rcfilters-highlight-color-c1 &,
+                               .mw-rcfilters-highlight-color-c2 &,
+                               .mw-rcfilters-highlight-color-c3 &,
+                               .mw-rcfilters-highlight-color-c4 &,
+                               .mw-rcfilters-highlight-color-c5 & {
+                                       display: none;
+                               }
+                       }
+                       .result-circle( c1 );
+                       .result-circle( c2 );
+                       .result-circle( c3 );
+                       .result-circle( c4 );
+                       .result-circle( c5 );
+               }
+       }
+
+       // One color
+       .mw-rcfilters-highlight-color-c1 {
+               background-color: tint( @highlight-c1, 70% );
+       }
+
+       .mw-rcfilters-highlight-color-c2 {
+               background-color: tint( @highlight-c2, 70% );
+       }
+
+       .mw-rcfilters-highlight-color-c3 {
+               background-color: tint( @highlight-c3, 70% );
+       }
+
+       .mw-rcfilters-highlight-color-c4 {
+               background-color: tint( @highlight-c4, 70% );
+       }
+
+       .mw-rcfilters-highlight-color-c5 {
+               background-color: tint( @highlight-c5, 70% );
+       }
+
+       // Two colors
+       .highlight-color-mix( c1, c2 );
+       .highlight-color-mix( c1, c3 );
+       .highlight-color-mix( c1, c4 );
+       .highlight-color-mix( c1, c5 );
+       .highlight-color-mix( c2, c3 );
+       .highlight-color-mix( c2, c4 );
+       .highlight-color-mix( c2, c5 );
+       .highlight-color-mix( c3, c4 );
+       .highlight-color-mix( c3, c5 );
+       .highlight-color-mix( c4, c5 );
+
+       // Three colors
+       .highlight-color-mix( c1, c2, c3 );
+       .highlight-color-mix( c1, c2, c5 );
+       .highlight-color-mix( c1, c2, c4 );
+       .highlight-color-mix( c1, c3, c4 );
+       .highlight-color-mix( c1, c3, c5 );
+       .highlight-color-mix( c1, c4, c5 );
+       .highlight-color-mix( c2, c3, c4 );
+       .highlight-color-mix( c2, c3, c5 );
+       .highlight-color-mix( c2, c4, c5 );
+       .highlight-color-mix( c3, c4, c5 );
+
+       // Four colors
+       .highlight-color-mix( c1, c2, c3, c4 );
+       .highlight-color-mix( c1, c2, c3, c5 );
+       .highlight-color-mix( c1, c2, c4, c5 );
+       .highlight-color-mix( c1, c3, c4, c5 );
+       .highlight-color-mix( c2, c3, c4, c5 );
+
+       // Five colors:
+       .mw-rcfilters-highlight-color-c1.mw-rcfilters-highlight-color-c2.mw-rcfilters-highlight-color-c3.mw-rcfilters-highlight-color-c4.mw-rcfilters-highlight-color-c5 {
+               background-color: tint( mix( @highlight-c1, mix( @highlight-c2, mix( @highlight-c3, average( @highlight-c4, @highlight-c5 ), 20% ), 20% ), 20% ), 15% );
+       }
+}
index 6c11cdb..8921f7a 100644 (file)
                color: #72777d;
        }
 
-       &-table {
-               display: table;
+       &-cell-filters {
                width: 100%;
        }
-
-       &-row {
-               display: table-row;
-       }
-
-       &-cell {
-               display: table-cell;
-
-               &:last-child {
-                       text-align: right;
-               }
+       &-cell-reset {
+               text-align: right;
+               padding-left: 0.5em;
        }
 
        .oo-ui-capsuleItemWidget {
diff --git a/resources/src/mediawiki.rcfilters/styles/mw.rcfilters.ui.FilterItemHighlightButton.less b/resources/src/mediawiki.rcfilters/styles/mw.rcfilters.ui.FilterItemHighlightButton.less
new file mode 100644 (file)
index 0000000..4619b6b
--- /dev/null
@@ -0,0 +1,31 @@
+@import "mw.rcfilters.mixins";
+
+.mw-rcfilters-ui-filterItemHighlightButton {
+
+       &-circle {
+               display: inline-block;
+               vertical-align: middle;
+               background-image: none;
+               margin-right: 0.2em;
+
+               &-color {
+                       &-c1 {
+                               // These values duplicate the sizing of the icon
+                               // width/height 1.875em
+                               .mw-rcfilters-mixin-circle( @highlight-c1, 1.875em, 0 );
+                       }
+                       &-c2 {
+                               .mw-rcfilters-mixin-circle( @highlight-c2, 1.875em, 0 );
+                       }
+                       &-c3 {
+                               .mw-rcfilters-mixin-circle( @highlight-c3, 1.875em, 0 );
+                       }
+                       &-c4 {
+                               .mw-rcfilters-mixin-circle( @highlight-c4, 1.875em, 0 );
+                       }
+                       &-c5 {
+                               .mw-rcfilters-mixin-circle( @highlight-c5, 1.875em, 0 );
+                       }
+               }
+       }
+}
index a874416..94da3ac 100644 (file)
@@ -1,9 +1,21 @@
 @import "mediawiki.mixins";
 
 .mw-rcfilters-ui-filterItemWidget {
-       padding-left: 0.5em;
+       padding: 0 0.5em;
        .box-sizing( border-box );
 
+       .mw-rcfilters-ui-table {
+               padding-top: 0.5em;
+       }
+
+       &-muted {
+               background-color: #f8f9fa; // Base90 AAA
+               .mw-rcfilters-ui-filterItemWidget-label-title,
+               .mw-rcfilters-ui-filterItemWidget-label-desc {
+                       color: #54595d; // Base20 AAA
+               }
+       }
+
        &-label {
                &-title {
                        font-weight: bold;
                }
        }
 
-       .oo-ui-fieldLayout.oo-ui-fieldLayout-align-inline {
-               // Override margin-top and -bottom rules from FieldLayout
-               margin: 0 !important;
+       &-filterCheckbox {
+               .oo-ui-fieldLayout.oo-ui-fieldLayout-align-inline {
+                       // Override margin-top and -bottom rules from FieldLayout
+                       margin: 0 !important;
+               }
+
        }
 
-       &-muted {
-               opacity: 0.5;
+       &-highlightButton {
+               width: 4em;
+               padding-left: 1em;
        }
 }
index 2928102..bdc94b3 100644 (file)
@@ -1,5 +1,7 @@
 .mw-rcfilters-ui-filterWrapperWidget {
        width: 100%;
+       // Make sure this uses the interface direction, not the content direction
+       direction: ltr;
 
        &-popup {
                // We have to override OOUI's definition, which is set
@@ -13,7 +15,9 @@
                margin-top: -0.5em;
 
                input {
-                       // Make sure this uses the interface direction, not the content direction
+                       // We need to reiterate the directionality
+                       // for the input as well to literally override
+                       // a MediaWiki CSS rule that turns it 'ltr'
                        direction: ltr;
                }
        }
index b874e0f..7fd3a21 100644 (file)
@@ -6,6 +6,7 @@
                color: #54595d;
                border-bottom: 1px solid #c8ccd1;
                background: #f8f9fa;
+               overflow: hidden;
        }
 
        &-noresults {
@@ -13,4 +14,8 @@
                // TODO: Unify colors with official design palette
                color: #666;
        }
+
+       &-hightlightButton {
+               float: right;
+       }
 }
diff --git a/resources/src/mediawiki.rcfilters/styles/mw.rcfilters.ui.HighlightColorPickerWidget.less b/resources/src/mediawiki.rcfilters/styles/mw.rcfilters.ui.HighlightColorPickerWidget.less
new file mode 100644 (file)
index 0000000..14c07c1
--- /dev/null
@@ -0,0 +1,73 @@
+@import "mw.rcfilters.mixins";
+
+.mw-rcfilters-ui-highlightColorPickerWidget {
+       &-label {
+               display: block;
+               font-weight: bold;
+               font-size: 1.2em;
+       }
+
+       &-buttonSelect {
+               &-color {
+                       .oo-ui-iconElement-icon {
+                               width: 2em;
+                               height: 2em;
+                       }
+
+                       &-none {
+                               .mw-rcfilters-mixin-circle( @highlight-none, 2em, 0.5em, true );
+
+                               &.oo-ui-buttonOptionWidget.oo-ui-buttonElement-active,
+                               &.oo-ui-buttonOptionWidget.oo-ui-optionWidget-pressed,
+                               &.oo-ui-buttonOptionWidget.oo-ui-optionWidget-selected {
+                                       background-color: @highlight-none;
+                               }
+                       }
+                       &-c1 {
+                               .mw-rcfilters-mixin-circle( @highlight-c1 );
+
+                               &.oo-ui-buttonOptionWidget.oo-ui-buttonElement-active,
+                               &.oo-ui-buttonOptionWidget.oo-ui-optionWidget-pressed,
+                               &.oo-ui-buttonOptionWidget.oo-ui-optionWidget-selected {
+                                       background-color: @highlight-c1;
+                               }
+                       }
+                       &-c2 {
+                               .mw-rcfilters-mixin-circle( @highlight-c2 );
+
+                               &.oo-ui-buttonOptionWidget.oo-ui-buttonElement-active,
+                               &.oo-ui-buttonOptionWidget.oo-ui-optionWidget-pressed,
+                               &.oo-ui-buttonOptionWidget.oo-ui-optionWidget-selected {
+                                       background-color: @highlight-c2;
+                               }
+                       }
+                       &-c3 {
+                               .mw-rcfilters-mixin-circle( @highlight-c3 );
+
+                               &.oo-ui-buttonOptionWidget.oo-ui-buttonElement-active,
+                               &.oo-ui-buttonOptionWidget.oo-ui-optionWidget-pressed,
+                               &.oo-ui-buttonOptionWidget.oo-ui-optionWidget-selected {
+                                       background-color: @highlight-c3;
+                               }
+                       }
+                       &-c4 {
+                               .mw-rcfilters-mixin-circle( @highlight-c4 );
+
+                               &.oo-ui-buttonOptionWidget.oo-ui-buttonElement-active,
+                               &.oo-ui-buttonOptionWidget.oo-ui-optionWidget-pressed,
+                               &.oo-ui-buttonOptionWidget.oo-ui-optionWidget-selected {
+                                       background-color: @highlight-c4;
+                               }
+                       }
+                       &-c5 {
+                               .mw-rcfilters-mixin-circle( @highlight-c5 );
+
+                               &.oo-ui-buttonOptionWidget.oo-ui-buttonElement-active,
+                               &.oo-ui-buttonOptionWidget.oo-ui-optionWidget-pressed,
+                               &.oo-ui-buttonOptionWidget.oo-ui-optionWidget-selected {
+                                       background-color: @highlight-c5;
+                               }
+                       }
+               }
+       }
+}
diff --git a/resources/src/mediawiki.rcfilters/styles/mw.rcfilters.ui.less b/resources/src/mediawiki.rcfilters/styles/mw.rcfilters.ui.less
new file mode 100644 (file)
index 0000000..957e9e9
--- /dev/null
@@ -0,0 +1,16 @@
+.mw-rcfilters-ui {
+       &-table {
+               display: table;
+               width: 100%;
+       }
+
+       &-row {
+               display: table-row;
+       }
+
+       &-cell {
+               display: table-cell;
+               vertical-align: top;
+       }
+}
+
diff --git a/resources/src/mediawiki.rcfilters/styles/mw.rcfilters.variables.less b/resources/src/mediawiki.rcfilters/styles/mw.rcfilters.variables.less
new file mode 100644 (file)
index 0000000..1ef49e2
--- /dev/null
@@ -0,0 +1,19 @@
+// Highlight color definitions
+@highlight-none: #fff;
+@highlight-c1: #36c;
+@highlight-c2: #00af89;
+@highlight-c3: #fc3;
+@highlight-c4: #ff6d22;
+@highlight-c5: #d33;
+
+// Muted state
+@muted-opacity: 0.5;
+
+// Result list circle indicators
+// Defined and used in mw.rcfilters.ui.ChangesListWrapperWidget.less
+@result-circle-margin: 0.1em;
+@result-circle-general-margin: 0.5em;
+// In these small sizes, 'em' appears
+// squished and inconsistent.
+// Pixels are better for this use case:
+@result-circle-diameter: 5px;
index 40d31c5..cf03932 100644 (file)
@@ -14,7 +14,7 @@
         */
        mw.rcfilters.ui.CapsuleItemWidget = function MwRcfiltersUiCapsuleItemWidget( controller, model, config ) {
                var $popupContent = $( '<div>' )
-                       .addClass( 'mw-rcfilters-ui-capsuleItemWidget-popup' ),
+                               .addClass( 'mw-rcfilters-ui-capsuleItemWidget-popup-content' ),
                        descLabelWidget = new OO.ui.LabelWidget();
 
                // Configuration initialization
                // Mixin constructors
                OO.ui.mixin.PopupElement.call( this, $.extend( {
                        popup: {
-                               padded: true,
+                               padded: false,
                                align: 'center',
                                $content: $popupContent
                                        .append( descLabelWidget.$element ),
-                               $floatableContainer: this.$element
+                               $floatableContainer: this.$element,
+                               classes: [ 'mw-rcfilters-ui-capsuleItemWidget-popup' ]
                        }
                }, config ) );
 
                // Set initial text for the popup - the description
                descLabelWidget.setLabel( this.model.getDescription() );
 
+               this.$highlight = $( '<div>' )
+                       .addClass( 'mw-rcfilters-ui-capsuleItemWidget-highlight' );
+
                // Events
                this.model.connect( this, { update: 'onModelUpdate' } );
 
-               this.closeButton.connect( this, { click: 'onCapsuleRemovedByUser' } );
+               this.closeButton.$element.on( 'mousedown', this.onCloseButtonMouseDown.bind( this ) );
 
                // Initialization
                this.$overlay.append( this.popup.$element );
                this.$element
+                       .prepend( this.$highlight )
                        .attr( 'aria-haspopup', 'true' )
                        .addClass( 'mw-rcfilters-ui-capsuleItemWidget' )
                        .on( 'mouseover', this.onHover.bind( this, true ) )
                        .on( 'mouseout', this.onHover.bind( this, false ) );
 
                this.setCurrentMuteState();
+               this.setHighlightColor();
        };
 
        OO.inheritClass( mw.rcfilters.ui.CapsuleItemWidget, OO.ui.CapsuleItemWidget );
         */
        mw.rcfilters.ui.CapsuleItemWidget.prototype.onModelUpdate = function () {
                this.setCurrentMuteState();
+
+               this.setHighlightColor();
+       };
+
+       /**
+        * Override mousedown event to prevent its propagation to the parent,
+        * since the parent (the multiselect widget) focuses the popup when its
+        * mousedown event is fired.
+        *
+        * @param {jQuery.Event} e Event
+        */
+       mw.rcfilters.ui.CapsuleItemWidget.prototype.onCloseButtonMouseDown = function ( e ) {
+               e.stopPropagation();
+       };
+
+       /**
+        * Override the event listening to the item close button click
+        */
+       mw.rcfilters.ui.CapsuleItemWidget.prototype.onCloseClick = function () {
+               var element = this.getElementGroup();
+
+               if ( element && $.isFunction( element.removeItems ) ) {
+                       element.removeItems( [ this ] );
+               }
+
+               // Respond to user removing the filter
+               this.controller.updateFilter( this.model.getName(), false );
+               this.controller.clearHighlightColor( this.model.getName() );
+       };
+
+       mw.rcfilters.ui.CapsuleItemWidget.prototype.setHighlightColor = function () {
+               var selectedColor = this.model.isHighlightEnabled() ? this.model.getHighlightColor() : null;
+
+               this.$highlight
+                       .attr( 'data-color', selectedColor )
+                       .toggleClass(
+                               'mw-rcfilters-ui-capsuleItemWidget-highlight-highlighted',
+                               !!selectedColor
+                       );
        };
 
        /**
                this.$element
                        .toggleClass(
                                'mw-rcfilters-ui-capsuleItemWidget-muted',
+                               !this.model.isSelected() ||
                                this.model.isIncluded() ||
                                this.model.isConflicted() ||
                                this.model.isFullyCovered()
                }
        };
 
-       /**
-        * Respond to the user removing the capsule with the close button
-        */
-       mw.rcfilters.ui.CapsuleItemWidget.prototype.onCapsuleRemovedByUser = function () {
-               this.controller.updateFilter( this.model.getName(), false );
-       };
-
        /**
         * Remove and destroy external elements of this widget
         */
index f929eb2..84248e1 100644 (file)
@@ -6,27 +6,43 @@
         * @mixins OO.ui.mixin.PendingElement
         *
         * @constructor
-        * @param {mw.rcfilters.dm.ChangesListViewModel} model View model
+        * @param {mw.rcfilters.dm.FiltersViewModel} filtersViewModel View model
+        * @param {mw.rcfilters.dm.ChangesListViewModel} changesListViewModel View model
         * @param {jQuery} $changesListRoot Root element of the changes list to attach to
         * @param {Object} config Configuration object
         */
-       mw.rcfilters.ui.ChangesListWrapperWidget = function MwRcfiltersUiChangesListWrapperWidget( model, $changesListRoot, config ) {
-               config = config || {};
+       mw.rcfilters.ui.ChangesListWrapperWidget = function MwRcfiltersUiChangesListWrapperWidget(
+               filtersViewModel,
+               changesListViewModel,
+               $changesListRoot,
+               config
+       ) {
+               config = $.extend( {}, config, {
+                       $element: $changesListRoot
+               } );
 
                // Parent
-               mw.rcfilters.ui.ChangesListWrapperWidget.parent.call( this, $.extend( {}, config, {
-                       $element: $changesListRoot
-               } ) );
+               mw.rcfilters.ui.ChangesListWrapperWidget.parent.call( this, config );
                // Mixin constructors
                OO.ui.mixin.PendingElement.call( this, config );
 
-               this.model = model;
+               this.filtersViewModel = filtersViewModel;
+               this.changesListViewModel = changesListViewModel;
 
                // Events
-               this.model.connect( this, {
+               this.filtersViewModel.connect( this, {
+                       itemUpdate: 'onItemUpdate',
+                       highlightChange: 'onHighlightChange'
+               } );
+               this.changesListViewModel.connect( this, {
                        invalidate: 'onModelInvalidate',
                        update: 'onModelUpdate'
                } );
+
+               this.$element.addClass( 'mw-rcfilters-ui-changesListWrapperWidget' );
+
+               // Set up highlight containers
+               this.setupHighlightContainers( this.$element );
        };
 
        /* Initialization */
        OO.mixinClass( mw.rcfilters.ui.ChangesListWrapperWidget, OO.ui.mixin.PendingElement );
 
        /**
-        * Respond to model invalidate
+        * Respond to the highlight feature being toggled on and off
+        *
+        * @param {boolean} highlightEnabled
+        */
+       mw.rcfilters.ui.ChangesListWrapperWidget.prototype.onHighlightChange = function ( highlightEnabled ) {
+               if ( highlightEnabled ) {
+                       this.applyHighlight();
+               } else {
+                       this.clearHighlight();
+               }
+       };
+
+       /**
+        * Respond to a filter item model update
+        */
+       mw.rcfilters.ui.ChangesListWrapperWidget.prototype.onItemUpdate = function () {
+               if ( this.filtersViewModel.isHighlightEnabled() ) {
+                       this.clearHighlight();
+                       this.applyHighlight();
+               }
+       };
+
+       /**
+        * Respond to changes list model invalidate
         */
        mw.rcfilters.ui.ChangesListWrapperWidget.prototype.onModelInvalidate = function () {
                this.pushPending();
        };
 
        /**
-        * Respond to model update
+        * Respond to changes list model update
         *
-        * @param {jQuery|string} changesListContent The content of the updated changes list
+        * @param {jQuery|string} $changesListContent The content of the updated changes list
         */
-       mw.rcfilters.ui.ChangesListWrapperWidget.prototype.onModelUpdate = function ( changesListContent ) {
-               var isEmpty = changesListContent === 'NO_RESULTS';
+       mw.rcfilters.ui.ChangesListWrapperWidget.prototype.onModelUpdate = function ( $changesListContent ) {
+               var isEmpty = $changesListContent === 'NO_RESULTS';
+
                this.$element.toggleClass( 'mw-changeslist', !isEmpty );
                this.$element.toggleClass( 'mw-changeslist-empty', isEmpty );
-               this.$element.empty().append(
-                       isEmpty ?
-                       document.createTextNode( mw.message( 'recentchanges-noresult' ).text() ) :
-                       changesListContent
-               );
+               if ( isEmpty ) {
+                       this.$changesListContent = null;
+                       this.$element.empty().append(
+                               document.createTextNode( mw.message( 'recentchanges-noresult' ).text() )
+                       );
+               } else {
+                       this.$changesListContent = $changesListContent;
+                       this.$element.empty().append( this.$changesListContent );
+                       // Set up highlight containers
+                       this.setupHighlightContainers( this.$element );
+
+                       // Apply highlight
+                       this.applyHighlight();
+
+                       // Make sure enhanced RC re-initializes correctly
+                       mw.hook( 'wikipage.content' ).fire( this.$element );
+               }
                this.popPending();
        };
+
+       /**
+        * Set up the highlight containers with all color circle indicators.
+        *
+        * @param {jQuery|string} $content The content of the updated changes list
+        */
+       mw.rcfilters.ui.ChangesListWrapperWidget.prototype.setupHighlightContainers = function ( $content ) {
+               var $highlights = $( '<div>' )
+                               .addClass( 'mw-rcfilters-ui-changesListWrapperWidget-highlights' )
+                               .append(
+                                       $( '<div>' )
+                                               .addClass( 'mw-rcfilters-ui-changesListWrapperWidget-highlights-color-none' )
+                                               .prop( 'data-color', 'none' )
+                               );
+
+               mw.rcfilters.HighlightColors.forEach( function ( color ) {
+                       $highlights.append(
+                               $( '<div>' )
+                                       .addClass( 'mw-rcfilters-ui-changesListWrapperWidget-highlights-color-' + color )
+                                       .prop( 'data-color', color )
+                       );
+               } );
+
+               if ( Number( mw.user.options.get( 'usenewrc' ) ) ) {
+                       // Enhanced RC
+                       $content.find( 'td.mw-enhanced-rc' )
+                               .parent()
+                               .prepend(
+                                       $( '<td>' )
+                                               .append( $highlights.clone() )
+                               );
+               } else {
+                       // Regular RC
+                       $content.find( 'ul.special li' )
+                               .prepend( $highlights.clone() );
+               }
+       };
+
+       /**
+        * Apply color classes based on filters highlight configuration
+        */
+       mw.rcfilters.ui.ChangesListWrapperWidget.prototype.applyHighlight = function () {
+               if ( !this.filtersViewModel.isHighlightEnabled() ) {
+                       return;
+               }
+
+               this.filtersViewModel.getHighlightedItems().forEach( function ( filterItem ) {
+                       // Add highlight class to all highlighted list items
+                       this.$element.find( '.' + filterItem.getCssClass() )
+                               .addClass( 'mw-rcfilters-highlight-color-' + filterItem.getHighlightColor() );
+               }.bind( this ) );
+
+               // Turn on highlights
+               this.$element.addClass( 'mw-rcfilters-ui-changesListWrapperWidget-highlighted' );
+       };
+
+       /**
+        * Remove all color classes
+        */
+       mw.rcfilters.ui.ChangesListWrapperWidget.prototype.clearHighlight = function () {
+               // Remove highlight classes
+               mw.rcfilters.HighlightColors.forEach( function ( color ) {
+                       this.$element.find( '.mw-rcfilters-highlight-color-' + color ).removeClass( 'mw-rcfilters-highlight-color-' + color );
+               }.bind( this ) );
+
+               // Turn off highlights
+               this.$element.removeClass( 'mw-rcfilters-ui-changesListWrapperWidget-highlighted' );
+       };
 }( mediaWiki ) );
index 7f8d79d..50b7d15 100644 (file)
         * @cfg {jQuery} [$overlay] A jQuery object serving as overlay for popups
         */
        mw.rcfilters.ui.FilterCapsuleMultiselectWidget = function MwRcfiltersUiFilterCapsuleMultiselectWidget( controller, model, filterInput, config ) {
+               var title = new OO.ui.LabelWidget( {
+                               label: mw.msg( 'rcfilters-activefilters' ),
+                               classes: [ 'mw-rcfilters-ui-filterCapsuleMultiselectWidget-wrapper-content-title' ]
+                       } ),
+                       $contentWrapper = $( '<div>' )
+                               .addClass( 'mw-rcfilters-ui-filterCapsuleMultiselectWidget-wrapper' );
+
+               this.$overlay = config.$overlay || this.$element;
+
                // Parent
-               mw.rcfilters.ui.FilterCapsuleMultiselectWidget.parent.call( this, $.extend( {
-                       $autoCloseIgnore: filterInput.$element
+               mw.rcfilters.ui.FilterCapsuleMultiselectWidget.parent.call( this, $.extend( true, {
+                       popup: { $autoCloseIgnore: filterInput.$element.add( this.$overlay ) }
                }, config ) );
 
                this.controller = controller;
                this.model = model;
-               this.$overlay = config.$overlay || this.$element;
 
                this.filterInput = filterInput;
 
-               this.$content.prepend(
-                       $( '<div>' )
-                               .addClass( 'mw-rcfilters-ui-filterCapsuleMultiselectWidget-content-title' )
-                               .text( mw.msg( 'rcfilters-activefilters' ) )
-               );
-
                this.resetButton = new OO.ui.ButtonWidget( {
                        icon: 'trash',
                        framed: false,
                        label: mw.msg( 'rcfilters-empty-filter' ),
                        classes: [ 'mw-rcfilters-ui-filterCapsuleMultiselectWidget-emptyFilters' ]
                } );
+               this.$content.append( this.emptyFilterMessage.$element );
 
                // Events
                this.resetButton.connect( this, { click: 'onResetButtonClick' } );
-               this.model.connect( this, { itemUpdate: 'onModelItemUpdate' } );
+               this.model.connect( this, {
+                       itemUpdate: 'onModelItemUpdate',
+                       highlightChange: 'onModelHighlightChange'
+               } );
                // Add the filterInput as trigger
                this.filterInput.$input
                        .on( 'focus', this.focus.bind( this ) );
 
+               // Build the content
+               $contentWrapper.append(
+                       title.$element,
+                       $( '<div>' )
+                               .addClass( 'mw-rcfilters-ui-table' )
+                               .append(
+                                       // The filter list and button should appear side by side regardless of how
+                                       // wide the button is; the button also changes its width depending
+                                       // on language and its state, so the safest way to present both side
+                                       // by side is with a table layout
+                                       $( '<div>' )
+                                               .addClass( 'mw-rcfilters-ui-row' )
+                                               .append(
+                                                       this.$content
+                                                               .addClass( 'mw-rcfilters-ui-cell' )
+                                                               .addClass( 'mw-rcfilters-ui-filterCapsuleMultiselectWidget-cell-filters' ),
+                                                       $( '<div>' )
+                                                               .addClass( 'mw-rcfilters-ui-cell' )
+                                                               .addClass( 'mw-rcfilters-ui-filterCapsuleMultiselectWidget-cell-reset' )
+                                                               .append( this.resetButton.$element )
+                                               )
+                               )
+               );
+
                // Initialize
-               this.$content.append( this.emptyFilterMessage.$element );
-               this.$handle
-                       .append(
-                               // The content and button should appear side by side regardless of how
-                               // wide the button is; the button also changes its width depending
-                               // on language and its state, so the safest way to present both side
-                               // by side is with a table layout
-                               $( '<div>' )
-                                       .addClass( 'mw-rcfilters-ui-filterCapsuleMultiselectWidget-table' )
-                                       .append(
-                                               $( '<div>' )
-                                                       .addClass( 'mw-rcfilters-ui-filterCapsuleMultiselectWidget-row' )
-                                                       .append(
-                                                               $( '<div>' )
-                                                                       .addClass( 'mw-rcfilters-ui-filterCapsuleMultiselectWidget-content' )
-                                                                       .addClass( 'mw-rcfilters-ui-filterCapsuleMultiselectWidget-cell' )
-                                                                       .append( this.$content ),
-                                                               $( '<div>' )
-                                                                       .addClass( 'mw-rcfilters-ui-filterCapsuleMultiselectWidget-cell' )
-                                                                       .append( this.resetButton.$element )
-                                                       )
-                                       )
-                       );
+               this.$handle.append( $contentWrapper );
 
                this.$element
                        .addClass( 'mw-rcfilters-ui-filterCapsuleMultiselectWidget' );
         * @param {mw.rcfilters.dm.FilterItem} item Filter item model
         */
        mw.rcfilters.ui.FilterCapsuleMultiselectWidget.prototype.onModelItemUpdate = function ( item ) {
-               if ( item.isSelected() ) {
+               if (
+                       item.isSelected() ||
+                       (
+                               this.model.isHighlightEnabled() &&
+                               item.isHighlightSupported() &&
+                               item.getHighlightColor()
+                       )
+               ) {
                        this.addItemByName( item.getName() );
                } else {
                        this.removeItemByName( item.getName() );
                this.reevaluateResetRestoreState();
        };
 
+       /**
+        * Respond to highlightChange event
+        *
+        * @param {boolean} isHighlightEnabled Highlight is enabled
+        */
+       mw.rcfilters.ui.FilterCapsuleMultiselectWidget.prototype.onModelHighlightChange = function ( isHighlightEnabled ) {
+               var highlightedItems = this.model.getHighlightedItems();
+
+               if ( isHighlightEnabled ) {
+                       // Add capsule widgets
+                       highlightedItems.forEach( function ( filterItem ) {
+                               this.addItemByName( filterItem.getName() );
+                       }.bind( this ) );
+               } else {
+                       // Remove capsule widgets if they're not selected
+                       highlightedItems.forEach( function ( filterItem ) {
+                               if ( !filterItem.isSelected() ) {
+                                       this.removeItemByName( filterItem.getName() );
+                               }
+                       }.bind( this ) );
+               }
+       };
+
        /**
         * Respond to click event on the reset button
         */
index 37182d6..f858ab0 100644 (file)
@@ -27,6 +27,7 @@
                        $label: $( '<div>' )
                                .addClass( 'mw-rcfilters-ui-filterGroupWidget-title' )
                } ) );
+               this.$overlay = config.$overlay || this.$element;
 
                // Populate
                this.populateFromModel();
@@ -68,7 +69,8 @@
                                        filterItem,
                                        {
                                                label: filterItem.getLabel(),
-                                               description: filterItem.getDescription()
+                                               description: filterItem.getDescription(),
+                                               $overlay: widget.$overlay
                                        }
                                );
                        } )
diff --git a/resources/src/mediawiki.rcfilters/ui/mw.rcfilters.ui.FilterItemHighlightButton.js b/resources/src/mediawiki.rcfilters/ui/mw.rcfilters.ui.FilterItemHighlightButton.js
new file mode 100644 (file)
index 0000000..32db0b6
--- /dev/null
@@ -0,0 +1,71 @@
+( function ( mw, $ ) {
+       /**
+        * A button to configure highlight for a filter item
+        *
+        * @extends OO.ui.PopupButtonWidget
+        *
+        * @constructor
+        * @param {mw.rcfilters.Controller} controller RCFilters controller
+        * @param {mw.rcfilters.dm.FilterItem} model Filter item model
+        * @param {Object} [config] Configuration object
+        */
+       mw.rcfilters.ui.FilterItemHighlightButton = function MwRcfiltersUiFilterItemHighlightButton( controller, model, config ) {
+               config = config || {};
+
+               this.colorPickerWidget = new mw.rcfilters.ui.HighlightColorPickerWidget( controller, model );
+
+               // Parent
+               mw.rcfilters.ui.FilterItemHighlightButton.parent.call( this, $.extend( {}, config, {
+                       icon: 'edit',
+                       indicator: 'down',
+                       popup: {
+                               anchor: false,
+                               padded: true,
+                               align: 'backwards',
+                               width: 290,
+                               $content: this.colorPickerWidget.$element
+                       }
+               } ) );
+
+               this.controller = controller;
+               this.model = model;
+
+               // Event
+               this.model.connect( this, { update: 'onModelUpdate' } );
+               this.colorPickerWidget.connect( this, { chooseColor: 'onChooseColor' } );
+
+               this.$element
+                       .addClass( 'mw-rcfilters-ui-filterItemHighlightButton' );
+       };
+
+       /* Initialization */
+
+       OO.inheritClass( mw.rcfilters.ui.FilterItemHighlightButton, OO.ui.PopupButtonWidget );
+
+       /* Methods */
+
+       /**
+        * Respond to item model update event
+        */
+       mw.rcfilters.ui.FilterItemHighlightButton.prototype.onModelUpdate = function () {
+               var currentColor = this.model.getHighlightColor(),
+                       widget = this;
+
+               this.$icon.toggleClass(
+                       'mw-rcfilters-ui-filterItemHighlightButton-circle',
+                       currentColor !== null
+               );
+
+               mw.rcfilters.HighlightColors.forEach( function ( c ) {
+                       widget.$icon
+                               .toggleClass(
+                                       'mw-rcfilters-ui-filterItemHighlightButton-circle-color-' + c,
+                                       c === currentColor
+                               );
+               } );
+       };
+
+       mw.rcfilters.ui.FilterItemHighlightButton.prototype.onChooseColor = function () {
+               this.popup.toggle( false );
+       };
+}( mediaWiki, jQuery ) );
index 9bf26d1..63db2b0 100644 (file)
                        );
                }
 
+               this.highlightButton = new mw.rcfilters.ui.FilterItemHighlightButton(
+                       this.controller,
+                       this.model,
+                       {
+                               $overlay: config.$overlay || this.$element
+                       }
+               );
+               this.highlightButton.toggle( this.model.isHighlightEnabled() );
+
                layout = new OO.ui.FieldLayout( this.checkboxWidget, {
                        label: $label,
                        align: 'inline'
                this.$element
                        .addClass( 'mw-rcfilters-ui-filterItemWidget' )
                        .append(
-                               layout.$element
+                               $( '<div>' )
+                                       .addClass( 'mw-rcfilters-ui-table' )
+                                       .append(
+                                               $( '<div>' )
+                                                       .addClass( 'mw-rcfilters-ui-row' )
+                                                       .append(
+                                                               $( '<div>' )
+                                                                       .addClass( 'mw-rcfilters-ui-cell mw-rcfilters-ui-filterItemWidget-filterCheckbox' )
+                                                                       .append( layout.$element ),
+                                                               $( '<div>' )
+                                                                       .addClass( 'mw-rcfilters-ui-cell mw-rcfilters-ui-filterItemWidget-highlightButton' )
+                                                                       .append( this.highlightButton.$element )
+                                                       )
+                                       )
                        );
        };
 
                                !this.model.isSelected()
                        )
                );
+
+               this.highlightButton.toggle( this.model.isHighlightEnabled() );
        };
+
        /**
         * Get the name of this filter
         *
        mw.rcfilters.ui.FilterItemWidget.prototype.getName = function () {
                return this.model.getName();
        };
-
 }( mediaWiki, jQuery ) );
index 315ca86..d46bd4b 100644 (file)
@@ -28,7 +28,8 @@
                        this.controller,
                        this.model,
                        {
-                               label: mw.msg( 'rcfilters-filterlist-title' )
+                               label: mw.msg( 'rcfilters-filterlist-title' ),
+                               $overlay: this.$overlay
                        }
                );
 
index 4ef3461..ae9ee71 100644 (file)
 
                this.controller = controller;
                this.model = model;
+               this.$overlay = config.$overlay || this.$element;
+
+               this.highlightButton = new OO.ui.ButtonWidget( {
+                       label: mw.message( 'rcfilters-highlightbutton-title' ).text(),
+                       classes: [ 'mw-rcfilters-ui-filtersListWidget-hightlightButton' ]
+               } );
+
+               this.$label.append( this.highlightButton.$element );
 
                this.noResultsLabel = new OO.ui.LabelWidget( {
                        label: mw.msg( 'rcfilters-filterlist-noresults' ),
                } );
 
                // Events
+               this.highlightButton.connect( this, { click: 'onHighlightButtonClick' } );
                this.model.connect( this, {
-                       initialize: 'onModelInitialize'
+                       initialize: 'onModelInitialize',
+                       highlightChange: 'onHighlightChange'
                } );
 
                // Initialize
                        Object.keys( this.model.getFilterGroups() ).map( function ( groupName ) {
                                return new mw.rcfilters.ui.FilterGroupWidget(
                                        widget.controller,
-                                       widget.model.getGroup( groupName )
+                                       widget.model.getGroup( groupName ),
+                                       {
+                                               $overlay: widget.$overlay
+                                       }
                                );
                        } )
                );
        };
 
+       mw.rcfilters.ui.FiltersListWidget.prototype.onHighlightChange = function ( highlightEnabled ) {
+               this.highlightButton.setActive( highlightEnabled );
+       };
+
+       /**
+        * Respond to highlight button click
+        */
+       mw.rcfilters.ui.FiltersListWidget.prototype.onHighlightButtonClick = function () {
+               this.controller.toggleHighlight();
+       };
+
        /**
         * Switch between showing the 'no results' message for filtering results or the result list.
         *
diff --git a/resources/src/mediawiki.rcfilters/ui/mw.rcfilters.ui.HighlightColorPickerWidget.js b/resources/src/mediawiki.rcfilters/ui/mw.rcfilters.ui.HighlightColorPickerWidget.js
new file mode 100644 (file)
index 0000000..570647e
--- /dev/null
@@ -0,0 +1,112 @@
+( function ( mw, $ ) {
+       /**
+        * A widget representing a filter item highlight color picker
+        *
+        * @extends OO.ui.Widget
+        * @mixins OO.ui.mixin.LabelElement
+        *
+        * @constructor
+        * @param {mw.rcfilters.Controller} controller RCFilters controller
+        * @param {mw.rcfilters.dm.FilterItem} model Filter item model
+        * @param {Object} [config] Configuration object
+        */
+       mw.rcfilters.ui.HighlightColorPickerWidget = function MwRcfiltersUiHighlightColorPickerWidget( controller, model, config ) {
+               var colors = [ 'none' ].concat( mw.rcfilters.HighlightColors );
+               config = config || {};
+
+               // Parent
+               mw.rcfilters.ui.HighlightColorPickerWidget.parent.call( this, config );
+               // Mixin constructors
+               OO.ui.mixin.LabelElement.call( this, $.extend( {}, config, {
+                       label: mw.message( 'rcfilters-highlightmenu-title' ).text()
+               } ) );
+
+               this.controller = controller;
+               this.model = model;
+
+               this.currentSelection = '';
+               this.buttonSelect = new OO.ui.ButtonSelectWidget( {
+                       items: colors.map( function ( color ) {
+                               return new OO.ui.ButtonOptionWidget( {
+                                       icon: color === 'none' ? 'check' : null,
+                                       data: color,
+                                       classes: [
+                                               'mw-rcfilters-ui-highlightColorPickerWidget-buttonSelect-color',
+                                               'mw-rcfilters-ui-highlightColorPickerWidget-buttonSelect-color-' + color
+                                       ],
+                                       framed: false
+                               } );
+                       } ),
+                       classes: 'mw-rcfilters-ui-highlightColorPickerWidget-buttonSelect'
+               } );
+               this.selectColor( 'none' );
+
+               // Event
+               this.model.connect( this, { update: 'onModelUpdate' } );
+               this.buttonSelect.connect( this, { choose: 'onChooseColor' } );
+
+               this.$element
+                       .addClass( 'mw-rcfilters-ui-highlightColorPickerWidget' )
+                       .append(
+                               this.$label
+                                       .addClass( 'mw-rcfilters-ui-highlightColorPickerWidget-label' ),
+                               this.buttonSelect.$element
+                       );
+       };
+
+       /* Initialization */
+
+       OO.inheritClass( mw.rcfilters.ui.HighlightColorPickerWidget, OO.ui.Widget );
+       OO.mixinClass( mw.rcfilters.ui.HighlightColorPickerWidget, OO.ui.mixin.LabelElement );
+
+       /* Events */
+
+       /**
+        * @event chooseColor
+        * @param {string} The chosen color
+        *
+        * A color has been chosen
+        */
+
+       /* Methods */
+
+       /**
+        * Respond to item model update event
+        */
+       mw.rcfilters.ui.HighlightColorPickerWidget.prototype.onModelUpdate = function () {
+               this.selectColor( this.model.getHighlightColor() || 'none' );
+       };
+
+       /**
+        * Select the color for this widget
+        *
+        * @param {string} color Selected color
+        */
+       mw.rcfilters.ui.HighlightColorPickerWidget.prototype.selectColor = function ( color ) {
+               var previousItem = this.buttonSelect.getItemFromData( this.currentSelection ),
+                       selectedItem = this.buttonSelect.getItemFromData( color );
+
+               if ( this.currentSelection !== color ) {
+                       this.currentSelection = color;
+
+                       this.buttonSelect.selectItem( selectedItem );
+                       if ( previousItem ) {
+                               previousItem.setIcon( null );
+                       }
+
+                       if ( selectedItem ) {
+                               selectedItem.setIcon( 'check' );
+                       }
+               }
+       };
+
+       mw.rcfilters.ui.HighlightColorPickerWidget.prototype.onChooseColor = function ( button ) {
+               var color = button.data;
+               if ( color === 'none' ) {
+                       this.controller.clearHighlightColor( this.model.getName() );
+               } else {
+                       this.controller.setHighlightColor( this.model.getName(), color );
+               }
+               this.emit( 'chooseColor', color );
+       };
+}( mediaWiki, jQuery ) );
index 87e209e..5ded184 100644 (file)
@@ -35,7 +35,7 @@
 
        /* IE7 and earlier */
        zoom: 1;
-       *display: inline;
+       *display: inline; /* stylelint-disable declaration-block-no-duplicate-properties */
 
        padding: 7px;
 }
@@ -55,7 +55,7 @@ table.toc td {
 #toc h2,
 .toc h2 {
        display: inline;
-       border: none;
+       border: 0;
        padding: 0;
        font-size: 100%;
        font-weight: bold;
@@ -121,16 +121,20 @@ table.toc td {
 }
 
 /* Images */
-/* @noflip */div.floatright, table.floatright {
-       margin: 0 0 .5em .5em;
+/* @noflip */
+div.floatright,
+table.floatright {
+       margin: 0 0 0.5em 0.5em;
 }
 
 div.floatright p {
        font-style: italic;
 }
 
-/* @noflip */div.floatleft, table.floatleft {
-       margin: 0 .5em .5em 0;
+/* @noflip */
+div.floatleft,
+table.floatleft {
+       margin: 0 0.5em 0.5em 0;
 }
 
 div.floatleft p {
@@ -139,7 +143,7 @@ div.floatleft p {
 
 /* Thumbnails */
 div.thumb {
-       margin-bottom: .5em;
+       margin-bottom: 0.5em;
        width: auto;
        background-color: transparent;
 }
@@ -161,7 +165,7 @@ html .thumbimage {
 }
 
 html .thumbcaption {
-       border: none;
+       border: 0;
        line-height: 1.4em;
        padding: 3px;
        font-size: 94%;
@@ -245,12 +249,12 @@ img.thumbborder {
 
 /* @noflip */
 div.tright {
-       margin: .5em 0 1.3em 1.4em;
+       margin: 0.5em 0 1.3em 1.4em;
 }
 
 /* @noflip */
 div.tleft {
-       margin: .5em 1.4em 1.3em 0;
+       margin: 0.5em 1.4em 1.3em 0;
 }
 
 /* Hide elements that are marked as "empty" according to legacy Tidy rules,
index b7cc6ed..823ce05 100644 (file)
@@ -2,7 +2,7 @@
  * Icons and colors for external links.
  */
 
-/* Bug 66091 is blocking is from converting this file to LESS
+/* T68091 is blocking is from converting this file to LESS
  * and using the .background-image-svg mixin. */
 
 /* SVG support using a transparent gradient to guarantee cross-browser
        padding-right: 15px;
 }
 
-.mw-body a.external[href$=".ogg"], .mw-body a.external[href$=".OGG"],
-.mw-body a.external[href$=".mid"], .mw-body a.external[href$=".MID"],
-.mw-body a.external[href$=".midi"], .mw-body a.external[href$=".MIDI"],
-.mw-body a.external[href$=".mp3"], .mw-body a.external[href$=".MP3"],
-.mw-body a.external[href$=".wav"], .mw-body a.external[href$=".WAV"],
-.mw-body a.external[href$=".wma"], .mw-body a.external[href$=".WMA"],
+.mw-body a.external[href$=".ogg"],
+.mw-body a.external[href$=".OGG"],
+.mw-body a.external[href$=".mid"],
+.mw-body a.external[href$=".MID"],
+.mw-body a.external[href$=".midi"],
+.mw-body a.external[href$=".MIDI"],
+.mw-body a.external[href$=".mp3"],
+.mw-body a.external[href$=".MP3"],
+.mw-body a.external[href$=".wav"],
+.mw-body a.external[href$=".WAV"],
+.mw-body a.external[href$=".wma"],
+.mw-body a.external[href$=".WMA"],
 .link-audio {
        background: url( images/audio-ltr.png ) center right no-repeat;
        /* @embed */
        padding-right: 15px;
 }
 
-.mw-body a.external[href$=".ogm"], .mw-body a.external[href$=".OGM"],
-.mw-body a.external[href$=".avi"], .mw-body a.external[href$=".AVI"],
-.mw-body a.external[href$=".mpeg"], .mw-body a.external[href$=".MPEG"],
-.mw-body a.external[href$=".mpg"], .mw-body a.external[href$=".MPG"],
+.mw-body a.external[href$=".ogm"],
+.mw-body a.external[href$=".OGM"],
+.mw-body a.external[href$=".avi"],
+.mw-body a.external[href$=".AVI"],
+.mw-body a.external[href$=".mpeg"],
+.mw-body a.external[href$=".MPEG"],
+.mw-body a.external[href$=".mpg"],
+.mw-body a.external[href$=".MPG"],
 .link-video {
        background: url( images/video.png ) center right no-repeat;
        /* @embed */
        padding-right: 15px;
 }
 
-.mw-body a.external[href$=".pdf"], .mw-body a.external[href$=".PDF"],
-.mw-body a.external[href*=".pdf#"], .mw-body a.external[href*=".PDF#"],
-.mw-body a.external[href*=".pdf?"], .mw-body a.external[href*=".PDF?"],
+.mw-body a.external[href$=".pdf"],
+.mw-body a.external[href$=".PDF"],
+.mw-body a.external[href*=".pdf#"],
+.mw-body a.external[href*=".PDF#"],
+.mw-body a.external[href*=".pdf?"],
+.mw-body a.external[href*=".PDF?"],
 .link-document {
        background: url( images/document-ltr.png ) center right no-repeat;
        /* @embed */
index 346771f..b4fe934 100644 (file)
@@ -38,7 +38,8 @@ span.reference {
        unicode-bidi: isolate;
 }
 
-sup, sub {
+sup,
+sub {
        line-height: 1;
 }
 
@@ -54,7 +55,7 @@ figure[typeof*='mw:Image'] {
 
        &.mw-halign-right {
                /* @noflip */
-               margin: .5em 0 1.3em 1.4em;
+               margin: 0.5em 0 1.3em 1.4em;
                /* @noflip */
                clear: right;
                /* @noflip */
@@ -63,7 +64,7 @@ figure[typeof*='mw:Image'] {
 
        &.mw-halign-left {
                /* @noflip */
-               margin: .5em 1.4em 1.3em 0;
+               margin: 0.5em 1.4em 1.3em 0;
                /* @noflip */
                clear: left;
                /* @noflip */
@@ -77,7 +78,7 @@ figure[typeof*='mw:Image'] {
        }
 
        &.mw-halign-center {
-               margin: 0 auto .5em auto;
+               margin: 0 auto 0.5em auto;
                display: table;
                clear: none;
                float: none;
@@ -118,7 +119,7 @@ figure[typeof~='mw:Image/Frame'] {
        background-color: #f9f9f9;
        // Default to right alignment. This is needed since Parsoid only specifies the
        // alignment class when the alignment is explicitly set.
-       margin: .5em 0 1.3em 1.4em;
+       margin: 0.5em 0 1.3em 1.4em;
        clear: right;
        float: right;
 }
@@ -128,8 +129,11 @@ figure[typeof~='mw:Image/Frame'] > *:first-child > img,
 .mw-image-border > *:first-child > img {
        border: 1px solid #ccc;
        margin: 3px;
+       background: #fff;
 }
 
 /* Hide the caption for frameless and plain floated images */
 figure[typeof~="mw:Image/Frameless"] > figcaption,
-figure[typeof~="mw:Image"] > figcaption { display: none }
+figure[typeof~="mw:Image"] > figcaption {
+       display: none;
+}
index 7d096f9..46de7b5 100644 (file)
@@ -25,15 +25,16 @@ a:active {
        color: #faa700;
 }
 
-a:hover, a:focus {
+a:hover,
+a:focus {
        text-decoration: underline;
 }
 
-a:lang(ar),
-a:lang(kk-arab),
-a:lang(mzn),
-a:lang(ps),
-a:lang(ur) {
+a:lang( ar ),
+a:lang( kk-arab ),
+a:lang( mzn ),
+a:lang( ps ),
+a:lang( ur ) {
        text-decoration: none;
 }
 
@@ -41,11 +42,13 @@ a.stub {
        color: #723;
 }
 
-a.new, #p-personal a.new {
+a.new,
+#p-personal a.new {
        color: #ba0000;
 }
 
-a.new:visited, #p-personal a.new:visited {
+a.new:visited,
+#p-personal a.new:visited {
        color: #a55858;
 }
 
@@ -69,7 +72,7 @@ a.new:visited, #p-personal a.new:visited {
 }
 
 .mw-body a.external:visited {
-       color: #636; /* bug 3112 */
+       color: #636; /* T5112 */
 }
 
 .mw-body a.external:active {
@@ -82,7 +85,7 @@ a.new:visited, #p-personal a.new:visited {
 
 /* Inline Elements */
 img {
-       border: none;
+       border: 0;
        vertical-align: middle;
 }
 
@@ -91,7 +94,7 @@ hr {
        color: #a2a9b1;
        background-color: #a2a9b1;
        border: 0;
-       margin: .2em 0;
+       margin: 0.2em 0;
 }
 
 /* Structural Elements */
@@ -106,8 +109,8 @@ h6 {
        font-weight: normal;
        margin: 0;
        overflow: hidden;
-       padding-top: .5em;
-       padding-bottom: .17em;
+       padding-top: 0.5em;
+       padding-bottom: 0.17em;
        border-bottom: 1px solid #a2a9b1;
 }
 
@@ -123,7 +126,7 @@ h3,
 h4,
 h5,
 h6 {
-       border-bottom: none;
+       border-bottom: 0;
        font-weight: bold;
 }
 
@@ -146,17 +149,17 @@ h6 {
 /* Some space under the headers in the content area */
 h1,
 h2 {
-       margin-bottom: .6em;
+       margin-bottom: 0.6em;
 }
 
 h3,
 h4,
 h5 {
-       margin-bottom: .3em;
+       margin-bottom: 0.3em;
 }
 
 p {
-       margin: .4em 0 .5em 0;
+       margin: 0.4em 0 0.5em 0;
 }
 
 p img {
@@ -165,36 +168,41 @@ p img {
 
 ul {
        list-style-type: square;
-       margin: .3em 0 0 1.6em;
+       margin: 0.3em 0 0 1.6em;
        padding: 0;
 }
 
 ol {
-       margin: .3em 0 0 3.2em;
+       margin: 0.3em 0 0 3.2em;
        padding: 0;
        list-style-image: none;
 }
 
 li {
-       margin-bottom: .1em;
+       margin-bottom: 0.1em;
 }
 
 dt {
        font-weight: bold;
-       margin-bottom: .1em;
+       margin-bottom: 0.1em;
 }
 
 dl {
-       margin-top: .2em;
-       margin-bottom: .5em;
+       margin-top: 0.2em;
+       margin-bottom: 0.5em;
 }
 
 dd {
        margin-left: 1.6em;
-       margin-bottom: .1em;
+       margin-bottom: 0.1em;
 }
 
-pre, code, tt, kbd, samp, .mw-code {
+pre,
+code,
+tt,
+kbd,
+samp,
+.mw-code {
        /*
         * Some browsers will render the monospace text too small, namely Firefox, Chrome and Safari.
         * Specifying any valid, second value will trigger correct behavior without forcing a different font.
@@ -238,18 +246,18 @@ fieldset.nested {
 }
 
 legend {
-       padding: .5em;
+       padding: 0.5em;
        font-size: 95%;
 }
 
 form {
-       border: none;
+       border: 0;
        margin: 0;
 }
 
 textarea {
        width: 100%;
-       padding: .1em;
+       padding: 0.1em;
        display: block;
        -moz-box-sizing: border-box;
        -webkit-box-sizing: border-box;
index d3f188a..2be3bb2 100644 (file)
@@ -23,7 +23,7 @@ textarea {
 .editOptions {
        background-color: #f8f9fa;
        border: 1px solid #c8ccd1;
-       border-top: none;
+       border-top: 0;
        padding: 1em 1em 1.5em 1em;
        margin-bottom: 2em;
 }
@@ -34,7 +34,7 @@ textarea {
        color: #000;
        font-weight: bold;
        margin: 2em 0 1em;
-       padding: .5em 1em;
+       padding: 0.5em 1em;
        vertical-align: middle;
 }
 
@@ -49,9 +49,9 @@ textarea {
 }
 
 .firstHeading {
-       margin-bottom: .1em;
-       /* These two rules hack around bug 2013 (fix for more limited bug 11325).
-        * When bug 2013 is fixed properly, they should be removed. */
+       margin-bottom: 0.1em;
+       /* These two rules hack around T4013 (fix for more limited T13325).
+        * When T4013 is fixed properly, they should be removed. */
        line-height: 1.2em;
        padding-bottom: 0;
 }
index 59a03f3..7f54b90 100644 (file)
@@ -43,7 +43,7 @@
 }
 
 .mw-apisandbox-help-field:last-child {
-       border-bottom: none;
+       border-bottom: 0;
 }
 
 .mw-apisandbox-optionalWidget {
index 4b8eced..3ad8005 100644 (file)
@@ -16,7 +16,8 @@
 }
 
 /* Common for Special:Allpages and Special:PrefixIndex */
-.mw-allpages-body, .mw-prefixindex-body {
+.mw-allpages-body,
+.mw-prefixindex-body {
        columns: 22em 3;
        -moz-columns: 22em 3;
        -webkit-columns: 22em 3;
index 9ee1b0b..8d63902 100644 (file)
@@ -8,28 +8,28 @@
 
 .iw-headline {
        font-weight: bold;
-    font-size: 1rem;
-    font-size: 16px;
-    opacity: 0.7;
+       font-size: 1rem;
+       font-size: 16px;
+       opacity: 0.7;
 }
 
 .iw-results {
-    list-style: none;
+       list-style: none;
        margin: 0;
 }
 
 .iw-resultset {
        margin-bottom: 1.2em;
        background-color: #f2f4f7;
-    vertical-align: top;
-    width: 100%;
-    float: left;
-    list-style-type: none;
+       vertical-align: top;
+       width: 100%;
+       float: left;
+       list-style-type: none;
 }
 
 /* clearfix */
 .iw-result:after {
-    visibility: hidden;
+       visibility: hidden;
        display: block;
        font-size: 0;
        content: " ";
        height: 0;
 }
 
-* html .interwiki-result             { zoom: 1; } /* IE6 */
-*:first-child+html .iw-resultset { zoom: 1; } /* IE7 */
+* html .interwiki-result { /* IE6 */
+       zoom: 1;
+}
+*:first-child + html .iw-resultset { /* IE7 */
+       zoom: 1;
+}
 
 /* padding each .iw-resultset section seperately.
 This allows us greater flexibility in the design.
@@ -48,58 +52,55 @@ header and footer. */
 .iw-result__title,
 .iw-result__content,
 .iw-result__footer {
-    padding-left: 0.85em;
-    padding-right: 0.85em;
-    padding-top: 0.25em;
-    padding-bottom: 0.25em;
+       padding: 0.25em 0.85em;
 }
 
 /* definition titles appear inline,
 to resemble a traditional dictionary definition */
 .iw-resultset--definition .iw-result__title {
-    display: inline;
-    padding: 0;
+       display: inline;
+       padding: 0;
 }
 
 .iw-resultset > div:first-child {
-    padding-top: 0.85em;
+       padding-top: 0.85em;
 }
 
 .iw-resultset > div:last-child {
-    padding-bottom: 0.85em;
+       padding-bottom: 0.85em;
 }
 
 .iw-result__title {
-    font-size: 16px; /* rem fallback */
-    font-size: 1rem;
+       font-size: 16px; /* rem fallback */
+       font-size: 1rem;
 }
 
 .iw-result__title a.extiw {
-    color: #252525;
-    font-weight: bold;
+       color: #252525;
+       font-weight: bold;
 }
 
 .iw-result__content:after { /* clearfix */
-     visibility: hidden;
-     display: block;
-     font-size: 0;
-     content: " ";
-     clear: both;
-     height: 0;
+       visibility: hidden;
+       display: block;
+       font-size: 0;
+       content: " ";
+       clear: both;
+       height: 0;
 }
 
 .iw-result__footer {
-    float: right;
+       float: right;
 }
 
 .iw-result__icon {
-    display: inline-block;
-    width: 24px;
-    height: 24px;
-    vertical-align: middle;
-    margin-right: 0.25em;
-    background: url( images/special.search/definition-icon.svg ) no-repeat 0 0;
-    background-size: 100% 100%;
+       display: inline-block;
+       width: 24px;
+       height: 24px;
+       vertical-align: middle;
+       margin-right: 0.25em;
+       background: url( images/special.search/definition-icon.svg ) no-repeat 0 0;
+       background-size: 100% 100%;
 }
 
 @interwikiContentTypes: definition, travel, quotation, book, course, news, textbook, image;
@@ -107,78 +108,79 @@ to resemble a traditional dictionary definition */
 .generate-iwIcons();
 
 .generate-iwIcons( @i:1 ) when ( @i =< length( @interwikiContentTypes ) ) {
-     @iwIcon: extract( @interwikiContentTypes, @i );
+       @iwIcon: extract( @interwikiContentTypes, @i );
 
-    .iw-result__icon--@{iwIcon} {
-        /*  stylelint-disable-next-line function-url-quotes */
-        background-image: url( 'images/special.search/@{iwIcon}-icon.png' );
-        /*  stylelint-disable-next-line function-url-quotes */
-        background-image: url( 'images/special.search/@{iwIcon}-icon.svg' );
-    }
+       .iw-result__icon--@{iwIcon} {
+               /*  stylelint-disable-next-line function-url-quotes */
+               background-image: url( 'images/special.search/@{iwIcon}-icon.png' );
+               /*  stylelint-disable-next-line function-url-quotes */
+               background-image: url( 'images/special.search/@{iwIcon}-icon.svg' );
+       }
 
-    .generate-iwIcons( @i + 1 );
+       .generate-iwIcons( @i + 1 );
 }
 
 /* image search result */
 .iw-result__mini-gallery {
-    position: relative;
-    float: left;
-    width: 60%;
-    height: 200px;
-    box-sizing: border-box;
-    padding: 0.25rem;
+       position: relative;
+       float: left;
+       width: 60%;
+       height: 200px;
+       box-sizing: border-box;
+       padding: 0.25rem;
 }
 
-.iw-result__mini-gallery__image {
-    display: block;
-    position: relative;
-    width: 100%;
-    height: 100%;
-    background-size: cover;
-    background-repeat: no-repeat;
-    background-position: center center;
+/* second and third images are small */
+.iw-result__mini-gallery:nth-child( 2 ),
+.iw-result__mini-gallery:nth-child( 3 ) { /* stylelint-disable-line indentation */
+       width: 40%;
+       height: 100px;
 }
 
-.iw-result__mini-gallery__image:hover > .iw-result__mini-gallery__caption {
-    visibility: visible;
+.iw-result__mini-gallery__image {
+       display: block;
+       position: relative;
+       width: 100%;
+       height: 100%;
+       background-size: cover;
+       background-repeat: no-repeat;
+       background-position: center center;
 }
 
 .iw-result__mini-gallery__image > .iw-result__mini-gallery__caption { /* image gallery text */
-  visibility: hidden;
-  position: absolute;
-  bottom: 0;
-  left: 0;
-  text-align: center;
-  color: #fff;
-  text-shadow: 0 0 10px rgba( 0, 0, 0, 0.4 ); /* improves legibility on white background*/
-  font-size: 0.8em;
-  padding: 5px;
-  background-color: rgba( 0, 0, 0, 0.5 );
+       visibility: hidden;
+       position: absolute;
+       bottom: 0;
+       left: 0;
+       text-align: center;
+       color: #fff;
+       text-shadow: 0 0 10px rgba( 0, 0, 0, 0.4 ); /* improves legibility on white background*/
+       font-size: 0.8em;
+       padding: 5px;
+       background-color: rgba( 0, 0, 0, 0.5 );
 }
 
-.iw-result__mini-gallery:nth-child(2),
-.iw-result__mini-gallery:nth-child(3) { /* second and third images are small */
-    width: 40%;
-    height: 100px;
+.iw-result__mini-gallery__image:hover > .iw-result__mini-gallery__caption {
+       visibility: visible;
 }
 
 /* different types of interwiki result boxes */
 /* quotation box */
 .iw-resultset--quotation .iw-result__content {
-    border-left: 4px solid #afb1b5;
-    margin-left: 1em;
-    padding-top: 0;
-    margin-top: 0.25em;
+       border-left: 4px solid #afb1b5;
+       margin-left: 1em;
+       padding-top: 0;
+       margin-top: 0.25em;
 }
-.iw-resultset--quotation .iw-result__title{
-    margin-left: 1em;
+.iw-resultset--quotation .iw-result__title {
+       margin-left: 1em;
 }
-.iw-result--quotation .iw-result__title:before{
-    content: ' — ';
-    display: inline-block;
+.iw-result--quotation .iw-result__title:before {
+       content: ' — ';
+       display: inline-block;
 }
 .iw-result--quotation .iw-result__footer {
-    text-align: right;
+       text-align: right;
 }
 
 /* no results
@@ -186,42 +188,37 @@ span the interwiki results across the bottom of the page.
 */
 
 .mw-search-nonefound ~ #mw-search-interwiki {
-    width: 100%;
+       width: 100%;
 }
 
 .mw-search-nonefound ~ #mw-search-interwiki .iw-resultset {
-    width: 30%;
-    max-width: 300px;
-    margin-left: 0.5em;
-    margin-right: 0.5em;
+       width: 30%;
+       max-width: 300px;
+       margin-left: 0.5em;
+       margin-right: 0.5em;
 }
 
 /* mobile */
-@media only screen and ( max-width:768px ) {
-    #mw-interwiki-results {
-        width: 100%;
-    }
-    .mw-search-results {
-        max-width: none !important;
-    }
-    .iw-resultset {
-        width: 45% !important;
-        margin-left: 0.5em !important;
-        margin-right: 0.5em !important;
-    }
-
-}
-
-@media only screen and ( max-width:600px ) {
-        .iw-resultset {
-        width: 100% !important;
-        margin-left: 0 !important;
-        margin-right: 0 !important;
-        max-width: none !important;
-    }
-}
-
-/* Evil temporary hax for cawiki */
-#sisterproject {
-       display: none;
+@media only screen and ( max-width: 768px ) {
+       #mw-interwiki-results {
+               width: 100%;
+       }
+       .mw-search-results {
+               max-width: none !important;
+       }
+       .iw-resultset {
+               width: 45% !important;
+               margin-left: 0.5em !important;
+               margin-right: 0.5em !important;
+       }
+
+}
+
+@media only screen and ( max-width: 600px ) {
+       .iw-resultset {
+               width: 100% !important;
+               margin-left: 0 !important;
+               margin-right: 0 !important;
+               max-width: none !important;
+       }
 }
index 9559f20..89f5132 100644 (file)
@@ -15,7 +15,7 @@
        display: inline !ie;
 }
 .searchresults {
-       margin: 1em 0 1em .4em;
+       margin: 1em 0 1em 0.4em;
 }
 /* needs extra specificity to override `.mw-body p` selector */
 .mw-body .mw-search-nonefound {
index f818096..0ddf7fe 100644 (file)
                                // Output result
                                if ( $( '#wpDestFile' ).length ) {
                                        // Call decodeURIComponent function to remove possible URL-encoded characters
-                                       // from the file name (bug 30390). Especially likely with upload-form-url.
+                                       // from the file name (T32390). Especially likely with upload-form-url.
                                        // decodeURIComponent can throw an exception if input is invalid utf-8
                                        try {
                                                $( '#wpDestFile' ).val( decodeURIComponent( fname ) );
index 283df85..626a7e8 100644 (file)
@@ -3,7 +3,7 @@
  */
 .mw-destfile-warning {
        border: 1px solid #fde29b;
-       padding: .5em 1em;
+       padding: 0.5em 1em;
        margin-bottom: 1em;
        color: #705000;
        background-color: #fdf1d1;
index ff38d0d..6397c73 100644 (file)
@@ -29,7 +29,6 @@ The anchor base type can be applied to `a` elements when a basic context styling
 having to assign it as a button type. `.mw-ui-anchor` only changes the text color, and should not be used in combination
 with other base classes, such as `.mw-ui-button`.
 
-
 Markup:
 <a href="#" class="mw-ui-anchor mw-ui-progressive">Progressive</a>
 <a href="#" class="mw-ui-anchor mw-ui-destructive">Destructive</a>
index 85795f4..5dc025f 100644 (file)
 //
 // Styleguide 2.1.
 .mw-ui-button {
-       // Inherit the font rather than apply user agent stylesheet (bug 70072)
+       // Inherit the font rather than apply user agent stylesheet (T72072)
        font-family: inherit;
        font-size: 1em;
        // Container layout
        display: inline-block;
        min-width: 4em;
        max-width: 28.75em; // equivalent to 460px, @see T95367
-       padding: .5em 1em;
+       padding: 0.5em 1em;
        margin: 0;
        border-radius: @borderRadius;
        .box-sizing( border-box );
@@ -43,7 +43,7 @@
 
        // IE 6 & 7 hack
        // https://stackoverflow.com/a/5838575/365238
-       *display: inline;
+       *display: inline; /* stylelint-disable-line declaration-block-no-duplicate-properties */
        zoom: 1;
 
        // Ensure that buttons and inputs are nicely aligned when they have differing heights
index b0fbf51..f983087 100644 (file)
@@ -43,7 +43,7 @@
        display: table;
 
        * {
-               // reset font sizes (see bug 72727)
+               // reset font sizes (see T74727)
                font: inherit;
                vertical-align: middle;
        }
@@ -58,7 +58,7 @@
                // ensure the invisible checkbox takes up the required width
                width: @checkboxSize;
                height: @checkboxSize;
-               // This is needed for Firefox mobile (See bug 71750 to workaround default Firefox stylesheet)
+               // This is needed for Firefox mobile (See T73750 to workaround default Firefox stylesheet)
                max-width: none;
                margin: 0 0.4em 0 0;
                display: table-cell;
index 0035601..efb04ae 100644 (file)
@@ -90,4 +90,4 @@
        &.mw-ui-icon-small:before {
                background-size: 66.67% auto; // 66.67% of 24px equals 16px
        }
-}
\ No newline at end of file
+}
index 87ce7be..21f5254 100644 (file)
        vertical-align: middle;
 
        // Normalize & style placeholder text, see T139034
-       // Placeholder styles can't be grouped, otherwise they're ignored as invalid.
-
-       // Placeholder mixin
-       .mixin-placeholder() {
+       /* stylelint-disable indentation */
+       .mixin-placeholder( {
                color: @colorGray7;
-               font-style: italic;
-       }
-       // Firefox 4-18
-       &:-moz-placeholder { // stylelint-disable-line selector-no-vendor-prefix
-               .mixin-placeholder;
-               opacity: 1;
-       }
-       // Firefox 19-
-       &::-moz-placeholder { // stylelint-disable-line selector-no-vendor-prefix
-               .mixin-placeholder;
                opacity: 1;
-       }
-       // Internet Explorer 10-11
-       &:-ms-input-placeholder { // stylelint-disable-line selector-no-vendor-prefix
-               .mixin-placeholder;
-       }
-       // WebKit, Blink, Edge
-       // Don't set `opacity < 1`, see https://developer.microsoft.com/en-us/microsoft-edge/platform/issues/3901363/
-       &::-webkit-input-placeholder { // stylelint-disable-line selector-no-vendor-prefix
-               .mixin-placeholder;
-       }
-       // W3C Standard Selectors Level 4
-       &:placeholder-shown {
-               .mixin-placeholder;
-       }
+       } );
+       /* stylelint-enable indentation */
 
        // Firefox: Remove red outline when `required` attribute set and invalid content.
        // See https://developer.mozilla.org/en-US/docs/Web/CSS/:invalid
                // Remove the inner padding and cancel buttons in Chrome on OS X and Safari on OS X
                &::-webkit-search-cancel-button,
                &::-webkit-search-decoration {
-                       -webkit-appearance: none;
+                       -webkit-appearance: none;
                }
        }
 }
index 53c22b4..7538ff4 100644 (file)
@@ -43,7 +43,7 @@
        line-height: @radioSize;
 
        * {
-               // reset font sizes (see bug 72727)
+               // reset font sizes (see T74727)
                font: inherit;
                vertical-align: middle;
        }
@@ -55,7 +55,7 @@
                // ensure the invisible radio takes up the required width
                width: @radioSize;
                height: @radioSize;
-               // This is needed for Firefox mobile (See bug 71750 to workaround default Firefox stylesheet)
+               // This is needed for Firefox mobile (See T73750 to workaround default Firefox stylesheet)
                max-width: none;
                margin-right: 0.4em;
 
index 30593bf..c0684d9 100644 (file)
@@ -33,4 +33,4 @@ Styleguide 6.1.
        &.mw-ui-destructive {
                color: @colorDestructive;
        }
-}
\ No newline at end of file
+}
index 77f87f7..b5b9cbe 100644 (file)
@@ -1,10 +1,11 @@
+/* stylelint-disable no-duplicate-selectors */
 @import "mediawiki.widgets.datetime.definitions";
 
 .mw-widgets-datetime-calendarWidget {
        display: inline-block;
        position: relative;
        vertical-align: middle;
-       padding: .5em;
+       padding: 0.5em;
 
        &.mw-widgets-datetime-calendarWidget-dependent {
                display: block;
@@ -51,7 +52,7 @@
 
                        .oo-ui-buttonElement-button {
                                width: 100%;
-                               border: 1px dotted rgba( 255, 255, 255, 0.0 );
+                               border: 1px dotted rgba( 255, 255, 255, 0 );
                                .oo-ui-box-sizing( border-box );
                        }
 
index 84788d2..1c6c490 100644 (file)
@@ -1,3 +1,4 @@
+/* stylelint-disable no-duplicate-selectors */
 @import "mediawiki.widgets.datetime.definitions";
 
 .mw-widgets-datetime-dateTimeInputWidget {
@@ -52,7 +53,6 @@
                margin: 0;
                background-color: #fff;
                color: #000;
-               border: solid 1px #ccc;
                box-shadow: inset 0 0 0 0 @progressive;
                border-radius: 0.1em;
                .oo-ui-transition(box-shadow @quick-ease);
@@ -92,7 +92,7 @@
                font-family: inherit;
                background-color: transparent;
                color: inherit;
-               border: none;
+               border: 0;
                box-shadow: none;
                text-align: center;
                vertical-align: middle;
index 2fe5d3d..b929a5a 100644 (file)
@@ -5,6 +5,7 @@
  * @license The MIT License (MIT); see LICENSE.txt
  */
 
+/* stylelint-disable no-duplicate-selectors */
 @import 'mediawiki.mixins';
 
 @calendarWidth: 21em;
 .mw-widget-calendarWidget-header .mw-widget-calendarWidget-labelButton {
        margin: 0 auto;
        display: block;
-       width: @calendarWidth - 2*3em;
+       width: @calendarWidth - 2 * 3em;
 
        .oo-ui-buttonElement-button {
-               width: @calendarWidth - 2*3em;
+               width: @calendarWidth - 2 * 3em;
                text-align: center;
        }
 }
index ecfc880..4a59dae 100644 (file)
@@ -1,3 +1,5 @@
+@import 'mediawiki.mixins';
+
 .mw-widgets-stashedFileWidget {
        display: inline-block;
        vertical-align: middle;
        vertical-align: middle;
        position: relative;
        overflow: hidden;
-       -webkit-box-sizing: border-box;
-          -moz-box-sizing: border-box;
-               box-sizing: border-box;
+       .box-sizing( border-box );
 
        > .mw-widgets-stashedFileWidget-label {
                line-height: 2.3em;
                margin: 0;
                overflow: hidden;
                white-space: nowrap;
-               -webkit-box-sizing: border-box;
-                  -moz-box-sizing: border-box;
-                               box-sizing: border-box;
+               .box-sizing( border-box );
                text-overflow: ellipsis;
                left: 0.5em;
                right: 2.375em;
        }
 
        .mw-widgets-stashedFileWidget-info {
-               border: none;
+               border: 0;
                background: none;
                display: block;
                height: 100%;
        }
 }
 
-
 .mw-widgets-stashedFileWidget-empty {
        .mw-widgets-stashedFileWidget-thumbnail-container {
                text-align: center;
index 3a4581d..9703eea 100644 (file)
                } );
 
                // If not found, run value through mw.Title to avoid treating a match as a
-               // mismatch where normalisation would make them matching (bug 48476)
+               // mismatch where normalisation would make them matching (T50476)
 
                pageExistsExact = (
                        Object.prototype.hasOwnProperty.call( pageData, this.getQueryValue() ) &&
index 86d4cfe..bbffe28 100644 (file)
@@ -48,7 +48,8 @@
                                }
                        }
 
-                       &.oo-ui-optionWidget-highlighted, &.oo-ui-optionWidget-selected {
+                       &.oo-ui-optionWidget-highlighted,
+                       &.oo-ui-optionWidget-selected {
                                &.oo-ui-iconElement > .mw-widget-titleOptionWidget-hasImage {
                                        opacity: 1;
                                }
@@ -71,7 +72,7 @@
                }
        }
 
-       &:not(&-withDescriptions) {
+       &:not( &-withDescriptions ) {
                .mw-widget-titleOptionWidget-description {
                        display: none;
                }
index f3d48e6..37c0c9b 100644 (file)
@@ -51,7 +51,7 @@
        }
 
        // Pre-populate with fake ajax promises to save http requests for tokens
-       // we already have on the page via the user.tokens module (bug 34733).
+       // we already have on the page via the user.tokens module (T36733).
        promises[ defaultOptions.ajax.url ] = {};
        $.each( mw.user.tokens.get(), function ( key, value ) {
                // This requires #getToken to use the same key as user.tokens.
                'stashwrongowner',
                'stashnosuchfilekey'
        ];
-       mw.log.deprecate( mw.Api, 'errors', mw.Api.errors, 'mw.Api.errors' );
+       mw.log.deprecate( mw.Api, 'errors', mw.Api.errors, null, 'mw.Api.errors' );
 
        /**
         * @static
                'duplicate',
                'exists'
        ];
-       mw.log.deprecate( mw.Api, 'warnings', mw.Api.warnings, 'mw.Api.warnings' );
+       mw.log.deprecate( mw.Api, 'warnings', mw.Api.warnings, null, 'mw.Api.warnings' );
 
 }( mediaWiki, jQuery ) );
index 1b9d2fb..a53e863 100644 (file)
@@ -44,9 +44,10 @@ tr.mw-htmlform-vertical-label td.mw-label {
        margin-left: 4px;
 }
 
-.mw-icon-question:lang(ar),
-.mw-icon-question:lang(fa),
-.mw-icon-question:lang(ur) {
+/* stylelint-disable indentation */
+.mw-icon-question:lang( ar ),
+.mw-icon-question:lang( fa ),
+.mw-icon-question:lang( ur ) {
        -webkit-transform: scaleX( -1 );
        -ms-transform: scaleX( -1 );
        transform: scaleX( -1 );
index d64a6b4..72ce9f0 100644 (file)
@@ -31,4 +31,4 @@
 
 .mw-upload-bookletLayout-filePreview .oo-ui-progressBarWidget-bar {
        height: 0.5em;
-}
\ No newline at end of file
+}
index 365e988..9a5a66f 100644 (file)
@@ -33,7 +33,8 @@ div.apihelp-linktrail {
        width: 20em;
 }
 
-.apihelp-deprecated, .apihelp-flag-deprecated,
+.apihelp-deprecated,
+.apihelp-flag-deprecated,
 .apihelp-flag-internal strong {
        font-weight: bold;
        color: #f00;
@@ -68,7 +69,7 @@ div.apihelp-linktrail {
 }
 
 .apihelp-parameters dt:after {
-       content: ':\A0'
+       content: ':\A0';
 }
 
 .apihelp-parameters dd {
index 3cca6eb..dec0571 100644 (file)
@@ -8,7 +8,7 @@
                padding: 0;
                margin: 0;
                background: none;
-               border: none;
+               border: 0;
        }
 
        table {
@@ -37,7 +37,7 @@
                tr {
                        background-color: #fff;
 
-                       &:nth-child(even) {
+                       &:nth-child( even ) {
                                background-color: #f9f9f9;
                        }
                }
@@ -63,9 +63,6 @@
        display: inline-block;
        padding: 10px 5px;
        font-size: 13px;
-       /* IE-hack for display: inline-block */
-       zoom: 1;
-       *display: inline;
 }
 
 .mw-debug-panelink {
@@ -185,6 +182,6 @@ a.mw-debug-panelabel:visited {
 }
 
 /* Cheapo hack to hide the first 3 lines of the backtrace */
-.mw-debug-backtrace li:nth-child(-n+3) {
+.mw-debug-backtrace li:nth-child( -n+3 ) {
        display: none;
 }
index 327c9c8..af9eb36 100644 (file)
@@ -2,7 +2,7 @@
  * Diff rendering
  */
 table.diff {
-       border: none;
+       border: 0;
        border-spacing: 4px;
        margin: 0;
        width: 100%;
index c392f2a..6a93fdd 100644 (file)
@@ -1,7 +1,7 @@
 .feedback-spinner {
        display: inline-block;
        zoom: 1;
-       *display: inline; /* IE7 and below */
+       *display: inline; /* IE7 and below */ /* stylelint-disable declaration-block-no-duplicate-properties */
        /* @embed */
        background: url( mediawiki.feedback.spinner.gif );
        width: 18px;
index 1662f0f..5a37f45 100644 (file)
        display: inline;
 }
 /* Display nested lists inline */
-.hlist dl dl, .hlist dl ol, .hlist dl ul,
-.hlist ol dl, .hlist ol ol, .hlist ol ul,
-.hlist ul dl, .hlist ul ol, .hlist ul ul {
+.hlist dl dl,
+.hlist dl ol,
+.hlist dl ul,
+.hlist ol dl,
+.hlist ol ol,
+.hlist ol ul,
+.hlist ul dl,
+.hlist ul ol,
+.hlist ul ul {
        display: inline;
 }
 /* Generate interpuncts */
        content: none;
 }
 /* Add parentheses around nested lists */
-.hlist dd dd:first-child:before, .hlist dd dt:first-child:before, .hlist dd li:first-child:before,
-.hlist dt dd:first-child:before, .hlist dt dt:first-child:before, .hlist dt li:first-child:before,
-.hlist li dd:first-child:before, .hlist li dt:first-child:before, .hlist li li:first-child:before {
+.hlist dd dd:first-child:before,
+.hlist dd dt:first-child:before,
+.hlist dd li:first-child:before,
+.hlist dt dd:first-child:before,
+.hlist dt dt:first-child:before,
+.hlist dt li:first-child:before,
+.hlist li dd:first-child:before,
+.hlist li dt:first-child:before,
+.hlist li li:first-child:before {
        content: "(";
        font-weight: normal;
 }
-.hlist dd dd:last-child:after, .hlist dd dt:last-child:after, .hlist dd li:last-child:after,
-.hlist dt dd:last-child:after, .hlist dt dt:last-child:after, .hlist dt li:last-child:after,
-.hlist li dd:last-child:after, .hlist li dt:last-child:after, .hlist li li:last-child:after {
+.hlist dd dd:last-child:after,
+.hlist dd dt:last-child:after,
+.hlist dd li:last-child:after,
+.hlist dt dd:last-child:after,
+.hlist dt dt:last-child:after,
+.hlist dt li:last-child:after,
+.hlist li dd:last-child:after,
+.hlist li dt:last-child:after,
+.hlist li li:last-child:after {
        content: ")";
        font-weight: normal;
 }
 /* For IE8 */
-.hlist dd dd.hlist-last-child:after, .hlist dd dt.hlist-last-child:after, .hlist dd li.hlist-last-child:after,
-.hlist dt dd.hlist-last-child:after, .hlist dt dt.hlist-last-child:after, .hlist dt li.hlist-last-child:after,
-.hlist li dd.hlist-last-child:after, .hlist li dt.hlist-last-child:after, .hlist li li.hlist-last-child:after {
+.hlist dd dd.hlist-last-child:after,
+.hlist dd dt.hlist-last-child:after,
+.hlist dd li.hlist-last-child:after,
+.hlist dt dd.hlist-last-child:after,
+.hlist dt dt.hlist-last-child:after,
+.hlist dt li.hlist-last-child:after,
+.hlist li dd.hlist-last-child:after,
+.hlist li dt.hlist-last-child:after,
+.hlist li li.hlist-last-child:after {
        content: ")";
        font-weight: normal;
 }
index 4df2df7..7872818 100644 (file)
                                        el.media = media;
                                }
                                // If you end up here from an IE exception "SCRIPT: Invalid property value.",
-                               // see #addEmbeddedCSS, bug 31676, and bug 47277 for details.
+                               // see #addEmbeddedCSS, T33676, and T49277 for details.
                                el.href = url;
 
                                $( getMarker() ).before( el );
                                 *     { <media>: css }
                                 *     { <media>: [url, ..] }
                                 *
-                                * The reason css strings are not concatenated anymore is bug 31676. We now check
+                                * The reason css strings are not concatenated anymore is T33676. We now check
                                 * whether it's safe to extend the stylesheet.
                                 *
                                 * @protected
                                                                // Support: IE 7-8
                                                                // Use properties instead of attributes as IE throws security
                                                                // warnings when inserting a <link> tag with a protocol-relative
-                                                               // URL set though attributes - when on HTTPS. See bug 41331.
+                                                               // URL set though attributes - when on HTTPS. See T43331.
                                                                l = document.createElement( 'link' );
                                                                l.rel = 'stylesheet';
                                                                l.href = modules;
                                        // Whether the store is in use on this page.
                                        enabled: null,
 
+                                       // Modules whose string representation exceeds 100 kB are
+                                       // ineligible for storage. See bug T66721.
                                        MODULE_SIZE_MAX: 100 * 1000,
 
                                        // The contents of the store, mapping '[name]@[version]' keys
index a8188db..78634f6 100644 (file)
                        }
 
                        // Update tooltip for the access key after inserting into DOM
-                       // to get a localized access key label (bug 67946).
+                       // to get a localized access key label (T69946).
                        $link.updateTooltipAccessKeys();
 
                        return $item[ 0 ];
index e651c9c..3cb8e9d 100644 (file)
                        .removeAttr( 'height' );
 
                // Stretch image to take up the required size
-               if ( this.$thumbnail.width() > this.$thumbnail.height() ) {
-                       this.$img.attr( 'width', this.imageWidth + 'px' );
-               } else {
-                       this.$img.attr( 'height', this.imageHeight + 'px' );
-               }
+               this.$img.attr( 'height', ( this.imageHeight - this.$imgCaption.outerHeight() ) + 'px' );
 
                // Make the image smaller in case the current image
                // size is larger than the original file size.
                var imageLi = this.getCurrentImage(),
                        caption = imageLi.find( '.gallerytext' );
 
-               // Highlight current thumbnail
+               // The order of the following is important for size calculations
+               // 1. Highlight current thumbnail
                this.$gallery
                        .find( '.gallerybox.slideshow-current' )
                        .removeClass( 'slideshow-current' );
                imageLi.addClass( 'slideshow-current' );
 
-               // Show thumbnail stretched to the right size while the image loads
+               // 2. Show thumbnail
                this.$thumbnail = imageLi.find( 'img' );
                this.$img.attr( 'src', this.$thumbnail.attr( 'src' ) );
                this.$img.attr( 'alt', this.$thumbnail.attr( 'alt' ) );
                this.$imgLink.attr( 'href', imageLi.find( 'a' ).eq( 0 ).attr( 'href' ) );
-               this.setImageSize();
 
-               // Copy caption
+               // 3. Copy caption
                this.$imgCaption
                        .empty()
                        .append( caption.clone() );
 
-               // Load image at the required size
+               // 4. Stretch thumbnail to correct size
+               this.setImageSize();
+
+               // 5. Load image at the required size
                this.loadImage( this.$thumbnail ).done( function ( info, $img ) {
                        // Show this image to the user only if its still the current one
                        if ( this.$thumbnail.attr( 'src' ) === $img.attr( 'src' ) ) {
index b7a9132..31def27 100644 (file)
@@ -58,7 +58,7 @@ div.gallerytext {
 /* new gallery stuff */
 ul.mw-gallery-nolines li.gallerybox div.thumb {
        background-color: transparent;
-       border: none;
+       border: 0;
 }
 
 ul.mw-gallery-nolines li.gallerybox div.gallerytext {
@@ -71,7 +71,7 @@ ul.mw-gallery-packed li.gallerybox div.thumb,
 ul.mw-gallery-packed-overlay li.gallerybox div.thumb,
 ul.mw-gallery-packed-hover li.gallerybox div.thumb {
        background-color: transparent;
-       border: none;
+       border: 0;
 }
 
 ul.mw-gallery-packed li.gallerybox div.thumb img,
@@ -95,7 +95,7 @@ ul.mw-gallery-packed-overlay li.gallerybox div.gallerytextwrapper,
 ul.mw-gallery-packed-hover li.gallerybox.mw-gallery-focused div.gallerytextwrapper {
        position: absolute;
        background: #fff;
-       background: rgba(255, 255, 255, 0.8);
+       background: rgba( 255, 255, 255, 0.8 );
        padding: 5px 10px;
        bottom: 0;
        left: 0; /* Needed for IE */
@@ -168,7 +168,7 @@ ul.gallery.mw-gallery-slideshow .mw-gallery-slideshow-buttons .oo-ui-buttonEleme
 }
 
 ul.mw-gallery-slideshow li.gallerybox div.thumb {
-       border: none;
+       border: 0;
        background: transparent;
 }
 
index 0c14865..80fc964 100644 (file)
@@ -3,7 +3,8 @@ li.gallerybox {
        display: inline-block;
 }
 
-ul.gallery, li.gallerybox {
+ul.gallery,
+li.gallerybox {
        zoom: 1;
        *display: inline;
 }
index 6038a57..6a7d0b9 100644 (file)
                        var page, url;
 
                        // Generate the same URL on client side as the one generated in ImagePage::openShowImage.
-                       // We avoid using the URL in the link directly since it could have been manipulated (bug 66608)
+                       // We avoid using the URL in the link directly since it could have been manipulated (T68608)
                        page = Number( mw.util.getParamValue( 'page', this.href ) );
                        url = mw.util.getUrl( mw.config.get( 'wgPageName' ), { page: page } );
 
index 7cfe058..7d35cb7 100644 (file)
                                        updateWatchLink( $link, otherAction );
 
                                        // Update the "Watch this page" checkbox on action=edit when the
-                                       // page is watched or unwatched via the tab (bug 12395).
+                                       // page is watched or unwatched via the tab (T14395).
                                        $( '#wpWatchthis' ).prop( 'checked', watchResponse.watched === true );
                                } )
                                .fail( function () {
index 38f56d2..3733e60 100644 (file)
@@ -89,7 +89,7 @@ class TestSetup {
                ];
                $wgAuth = new MediaWiki\Auth\AuthManagerAuthPlugin();
 
-               // Bug 44192 Do not attempt to send a real e-mail
+               // T46192 Do not attempt to send a real e-mail
                Hooks::clear( 'AlternateUserMailer' );
                Hooks::register(
                        'AlternateUserMailer',
index 97e24b6..7edde2a 100644 (file)
@@ -295,7 +295,7 @@ class ParserTestRunner {
                        MediaWikiServices::getInstance()->resetServiceForTesting( 'MediaHandlerFactory' );
                };
 
-               // SqlBagOStuff broke when using temporary tables on r40209 (bug 15892).
+               // SqlBagOStuff broke when using temporary tables on r40209 (T17892).
                // It seems to have been fixed since (r55079?), but regressed at some point before r85701.
                // This works around it for now...
                global $wgObjectCaches;
@@ -316,7 +316,7 @@ class ParserTestRunner {
 
        private function appendNamespaceSetup( &$setup, &$teardown ) {
                // Add a namespace shadowing a interwiki link, to test
-               // proper precedence when resolving links. (bug 51680)
+               // proper precedence when resolving links. (T53680)
                $setup['wgExtraNamespaces'] = [
                        100 => 'MemoryAlpha',
                        101 => 'MemoryAlpha_talk'
@@ -1321,7 +1321,7 @@ class ParserTestRunner {
                if ( $this->useTemporaryTables ) {
                        if ( $this->db->getType() == 'sqlite' ) {
                                # Under SQLite the searchindex table is virtual and need
-                               # to be explicitly destroyed. See bug 29912
+                               # to be explicitly destroyed. See T31912
                                # See also MediaWikiTestCase::destroyDB()
                                wfDebug( __METHOD__ . " explicitly destroying sqlite virtual table parsertest_searchindex\n" );
                                $this->db->query( "DROP TABLE `parsertest_searchindex`" );
index f1a82ee..a62db5a 100644 (file)
@@ -9,4 +9,4 @@ To run parser tests via PHPUnit:
 
 You can optionally filter by title using --filter, e.g.
 
- ./phpunit.php --testsuite parsertests --filter="Bug 6200"
+ ./phpunit.php --testsuite parsertests --filter="T6400"
index 0ba60aa..be6e3a8 100644 (file)
@@ -609,7 +609,7 @@ Italics and bold
 
 !! end
 
-# this example taken from the [[simple:Moon]] article (bug 47326)
+# this example taken from the [[simple:Moon]] article (T49326)
 !! test
 Italics and possessives (1)
 !! wikitext
@@ -619,7 +619,7 @@ obtained by ''[[Lunar Prospector]]'''s gamma-ray spectrometer
 </p>
 !! end
 
-# this example taken from [[en:Flaming Pie]] (bug 49926)
+# this example taken from [[en:Flaming Pie]] (T51926)
 !! test
 Italics and possessives (2)
 !! wikitext
@@ -629,7 +629,7 @@ Italics and possessives (2)
 </p>
 !! end
 
-# this example taken from [[en:Dictionary]] (bug 49926)
+# this example taken from [[en:Dictionary]] (T51926)
 !! test
 Italics and possessives (3)
 !! wikitext
@@ -1178,7 +1178,7 @@ Non-html5 tags should be accepted
 !! end
 
 !! test
-<wbr> is valid wikitext (bug 52468)
+<wbr> is valid wikitext (T54468)
 !! wikitext
 <wbr>
 !! html
@@ -1293,7 +1293,7 @@ Ruby markup (W3C-style)
 
 # The next two test different paths in the sanitizer.
 !! test
-Non-word characters don't terminate tag names (bug 17663, 40670, 52022)
+Non-word characters don't terminate tag names (T19663, T42670, T54022)
 !! wikitext
 <blockquote|>a</blockquote>
 
@@ -1364,7 +1364,7 @@ array (
 !! end
 
 !! test
-Isolated close tags should be treated as literal text (bug 52760)
+Isolated close tags should be treated as literal text (T54760)
 !! options
 parsoid=wt2html
 !! wikitext
@@ -1382,7 +1382,7 @@ parsoid=wt2html
 ###
 
 !! test
-Bare pipe character (bug 52363)
+Bare pipe character (T54363)
 !! wikitext
 |
 !! html
@@ -1391,7 +1391,7 @@ Bare pipe character (bug 52363)
 !! end
 
 !! test
-Bare pipe character from a template (bug 52363)
+Bare pipe character from a template (T54363)
 !! wikitext
 {{pipe}}
 !! html
@@ -1488,9 +1488,11 @@ nowiki 3
 Entities inside <nowiki>
 !! wikitext
 <nowiki>&lt;</nowiki>
-!! html
+!! html/php
 <p>&lt;
 </p>
+!! html/parsoid
+<p><span typeof="mw:Nowiki"><span typeof="mw:Entity" data-parsoid='{"src":"&amp;lt;","srcContent":"&lt;"}'>&lt;</span></span></p>
 !! end
 
 !! test
@@ -2162,7 +2164,7 @@ Regression with preformatted in <center>
 !! end
 
 !! test
-Bug 52763: Preformatted in <blockquote>
+T54763: Preformatted in <blockquote>
 !! wikitext
 <blockquote>
  Blah
@@ -2186,7 +2188,7 @@ Bug 52763: Preformatted in <blockquote>
 !! end
 
 !! test
-Bug 51086: Double newlines in blockquotes should be turned into paragraphs
+T53086: Double newlines in blockquotes should be turned into paragraphs
 !! wikitext
 <blockquote>
 Foo
@@ -2203,7 +2205,7 @@ Bar
 !! end
 
 !! test
-Bug 15491: <ins>/<del> in blockquote
+T17491: <ins>/<del> in blockquote
 !! wikitext
 <blockquote>
 Foo <del>bar</del> <ins>baz</ins> quux
@@ -2218,9 +2220,9 @@ Foo <del>bar</del> <ins>baz</ins> quux
 
 # Note that the p-wrapping is newline sensitive, which could be
 # considered a bug: tidy will wrap only the 'Foo' in the example
-# below in a <p> tag. (see comment 23-25 of bug #6200)
+# below in a <p> tag. (see comment 23-25 of T8200)
 !! test
-Bug 15491: <ins>/<del> in blockquote (2)
+T17491: <ins>/<del> in blockquote (2)
 !! wikitext
 <blockquote>Foo <del>bar</del> <ins>baz</ins> quux
 </blockquote>
@@ -2235,7 +2237,7 @@ Bug 15491: <ins>/<del> in blockquote (2)
 !! end
 
 !! test
-<pre> with attributes (bug 3202)
+<pre> with attributes (T5202)
 !! wikitext
 <pre style="background: blue; color:white">Bluescreen of WikiDeath</pre>
 !! html
@@ -2244,7 +2246,7 @@ Bug 15491: <ins>/<del> in blockquote (2)
 !! end
 
 !! test
-<pre> with width attribute (bug 3202)
+<pre> with width attribute (T5202)
 !! wikitext
 <pre width="8">Narrow screen goodies</pre>
 !! html
@@ -2253,7 +2255,7 @@ Bug 15491: <ins>/<del> in blockquote (2)
 !! end
 
 !! test
-<pre> with forbidden attribute (bug 3202)
+<pre> with forbidden attribute (T5202)
 !! wikitext
 <pre width="8" onmouseover="alert(document.cookie)">Narrow screen goodies</pre>
 !! html
@@ -2271,7 +2273,7 @@ Entities inside <pre>
 !! end
 
 !! test
-<pre> with forbidden attribute values (bug 3202)
+<pre> with forbidden attribute values (T5202)
 !! wikitext
 <pre width="8" style="border-width: expression(alert(document.cookie))">Narrow screen goodies</pre>
 !! html
@@ -2280,7 +2282,7 @@ Entities inside <pre>
 !! end
 
 !! test
-<nowiki> inside <pre> (bug 13238)
+<nowiki> inside <pre> (T15238)
 !! wikitext
 <pre>
 <nowiki>
@@ -2311,8 +2313,12 @@ Entities inside <pre>
 <pre about="#mwt1" typeof="mw:Transclusion" data-parsoid='{"pi":[[{"k":"1"}]]}' data-mw='{"parts":[{"template":{"target":{"wt":"#tag:pre","function":"#tag"},"params":{"1":{"wt":"Foo &lt;nowiki>&amp;rarr;bar&lt;/nowiki>"}},"i":0}}]}'>Foo <span typeof="mw:Entity">→</span>bar</pre>
 !! end
 
+## Don't expect this to rt, Parsoid drops the unmatched closing pre tags that
+## aren't enclosed in nowikis.
 !! test
 <nowiki> and <pre> preference (first one wins)
+!! options
+parsoid=wt2html
 !! wikitext
 <pre>
 <nowiki>
@@ -2341,17 +2347,16 @@ Entities inside <pre>
 &lt;/pre&gt;
 </p>
 !! html/parsoid
-<pre data-parsoid='{"stx":"html","strippedNL":true}'>&lt;nowiki>
+<pre typeof="mw:Extension/pre" about="#mwt2" data-mw='{"name":"pre","attrs":{},"body":{"extsrc":"\n&lt;nowiki>\n"}}'>&lt;nowiki>
 </pre>
-<p><span typeof="mw:Placeholder" data-parsoid='{"src":"&lt;/nowiki>"}'>&lt;/nowiki></span>
-&lt;/pre></p>
+<p>&lt;/nowiki></p>
+
 
 <p><span typeof="mw:Nowiki">
 &lt;pre>
 &lt;nowiki>
 &lt;/pre>
-</span>
-&lt;/pre></p>
+</span></p>
 !! end
 
 !! test
@@ -2365,9 +2370,7 @@ Entities inside <pre>
 
 # Parsoid doesn't strip empty tags, like Tidy does.
 !! test
-Empty pre; pre inside other HTML tags (bug 54946)
-!! options
-parsoid=wt2html,wt2wt
+Empty pre; pre inside other HTML tags (T56946)
 !! wikitext
 a
 
@@ -2392,9 +2395,9 @@ foo
 !! html/parsoid
 <p>a</p>
 
-<div><pre>foo
+<div data-parsoid='{"stx":"html"}'><pre typeof="mw:Extension/pre" about="#mwt2" data-parsoid='{"stx":"html"}' data-mw='{"name":"pre","attrs":{},"body":{"extsrc":"\nfoo\n"}}'>foo
 </pre></div>
-<pre></pre>
+<pre typeof="mw:Extension/pre" about="#mwt4" data-parsoid='{"stx":"html"}' data-mw='{"name":"pre","attrs":{},"body":{"extsrc":""}}'></pre>
 !! end
 
 !! test
@@ -2410,7 +2413,7 @@ HTML pre followed by indent-pre
 
 # Note that tidy removes the empty <p> tags from the start and end.
 # Parsoid does not, by design.
-!!test
+!! test
 Block tag pre
 !! wikitext
 <p><pre>foo</pre></p>
@@ -2419,8 +2422,8 @@ Block tag pre
 foo
 </pre>
 !! html/parsoid
-<p data-parsoid='{"stx":"html","autoInsertedEnd":true}'></p><pre data-parsoid='{"stx":"html"}'>foo</pre><p data-parsoid='{"autoInsertedStart":true,"stx":"html"}'></p>
-!!end
+<p data-parsoid='{"stx":"html","autoInsertedEnd":true}'></p><pre typeof="mw:Extension/pre" about="#mwt2" data-parsoid='{"stx":"html"}' data-mw='{"name":"pre","attrs":{},"body":{"extsrc":"foo"}}'>foo</pre><p data-parsoid='{"autoInsertedStart":true,"stx":"html"}'></p>
+!! end
 
 !!test
 Templates: Indent-Pre: 1a. Templates that break a line should suppress <pre>
@@ -2541,8 +2544,11 @@ Templates: Indent-Pre: 1f: Wrapping should be based on expanded content
 </pre>
 !!end
 
+## Hmm, should Parsoid rt this?
 !! test
 Pres with newline attributes
+!! options
+parsoid=wt2html,html2html
 !! wikitext
 <pre class="one
 two">hi</pre>
@@ -2550,8 +2556,7 @@ two">hi</pre>
 <pre class="one two">hi</pre>
 
 !! html/parsoid
-<pre class="one
-two" data-parsoid='{"stx":"html"}'>hi</pre>
+<pre typeof="mw:Extension/pre" about="#mwt2" class="one two" data-mw='{"name":"pre","attrs":{"class":"one two"},"body":{"extsrc":"hi"}}'>hi</pre>
 !! end
 
 !! test
@@ -2566,7 +2571,7 @@ Barack Obama <President> of the United States
 !! end
 
 !! test
-Handle broken pre-like tags (bug 64025)
+Handle broken pre-like tags (T66025)
 !! options
 parsoid=wt2html
 !! wikitext
@@ -2583,7 +2588,7 @@ x
 </pre>
 <p>&lt;pre</p>
 !! html/parsoid
-<pre about="#mwt1" typeof="mw:Transclusion" data-parsoid='{"a":{"&lt;pre":null},"sa":{"&lt;pre":""},"stx":"html","pi":[[{"k":"1"}]]}' data-mw='{"parts":[{"template":{"target":{"wt":"echo","href":"./Template:Echo"},"params":{"1":{"wt":"&lt;pre &lt;pre>x&lt;/pre>"}},"i":0}}]}'>x</pre>
+<pre about="#mwt1" typeof="mw:Transclusion mw:Extension/pre" data-parsoid='{"a":{"&lt;pre":null},"sa":{"&lt;pre":""},"stx":"html","pi":[[{"k":"1"}]]}' data-mw='{"parts":[{"template":{"target":{"wt":"echo","href":"./Template:Echo"},"params":{"1":{"wt":"&lt;pre &lt;pre>x&lt;/pre>"}},"i":0}}]}'>x</pre>
 
 
 <p>&lt;pre </p>
@@ -2601,7 +2606,7 @@ parsoid=wt2html
 <pre style="width:50%;">{{echo|foo}}</pre>
 
 !! html/parsoid
-<pre style="width:50%;">{{echo|foo}}</pre>
+<pre typeof="mw:Extension/pre" about="#mwt2" style="width:50%;" data-mw='{"name":"pre","attrs":{"style":"width:50%;"},"body":{"extsrc":"{{echo|foo}}"}}'>{{echo|foo}}</pre>
 !! end
 
 # TODO / maybe: fix wt2wt for this
@@ -2782,7 +2787,7 @@ Templates: Handle comments in the target
 !!end
 
 !! test
-Templates: Handle comments in parameter names (bug 67657)
+Templates: Handle comments in parameter names (T69657)
 !! wikitext
 {{echo|1
 <!-- should be ignored -->
@@ -2812,7 +2817,7 @@ Templates: Handle comments in parameter names (bug 67657)
 !!end
 
 !! test
-Templates: Other wikitext in parameter names (bug 67657)
+Templates: Other wikitext in parameter names (T69657)
 !! wikitext
 {{echo|''1''=foo}}
 !! html/php
@@ -2900,7 +2905,7 @@ parsoid=html2wt,wt2wt
 </p>
 !! end
 
-## Bug 52824
+## T54824
 !! test
 Templates: '=' char in nested transclusions should not trigger nowiki escapes or conversion to named param
 !! options
@@ -2913,7 +2918,7 @@ parsoid=html2wt,wt2wt
 <p about="#mwt1" typeof="mw:Transclusion" data-mw='{"parts":[{"template":{"target":{"wt":"echo","href":"./Template:Echo"},"params":{"1":{"wt":"{{echo|1=bar}}"}},"i":0}}]}'>bar</p>
 !! end
 
-## Bug 56733
+## T58733
 !! test
 Templates parameters with special tokenizing behavior dont get modified because of arg escaping
 !! wikitext
@@ -2924,7 +2929,7 @@ Templates parameters with special tokenizing behavior dont get modified because
 <p about="#mwt1" typeof="mw:Transclusion" data-mw='{"parts":[{"template":{"target":{"wt":"echo","href":"./Template:Echo"},"params":{"1":{"wt":"a : b"}},"i":0}}]}'>a<span typeof="mw:DisplaySpace mw:Placeholder" data-parsoid='{"isDisplayHack":true}'> </span>: b</p>
 !! end
 
-## Bug T73412
+## T73412
 !! test
 Templates: Preserve blank parameter names
 !! wikitext
@@ -3041,7 +3046,7 @@ c
 !!end
 
 !!test
-2c. Indent-Pre and tables (bug 42252)
+2c. Indent-Pre and tables (T44252)
 !! wikitext
 {|
  |+ foo
@@ -3112,7 +3117,7 @@ a
 !!end
 
 !! test
-2g. Indented table markup mixed with indented pre content (proposed in bug 6200)
+2g. Indented table markup mixed with indented pre content (proposed in T8200)
 !! wikitext
  <table>
  <tr>
@@ -3266,6 +3271,17 @@ array (
  a <pre typeof="mw:Extension/tag" about="#mwt2" data-parsoid='{}' data-mw='{"name":"tag","attrs":{},"body":null}'></pre>
 !! end
 
+!! test
+5. Indent-Pre and html pre
+!! wikitext
+ <pre class="123">hi</pre>
+!! html/php
+ <pre class="123">hi</pre>
+
+!! html/parsoid
+ <pre typeof="mw:Extension/pre" about="#mwt2" class="123" data-mw='{"name":"pre","attrs":{"class":"123"},"body":{"extsrc":"hi"}}'>hi</pre>
+!! end
+
 !!test
 Render paragraphs when indent-pre is suppressed in blocklevels
 !! wikitext
@@ -3455,18 +3471,17 @@ foo
 foo
 </pre>
 !! html/parsoid
-<pre data-parsoid='{"stx":"html"}'>foo</pre>
+<pre typeof="mw:Extension/pre" about="#mwt2" data-mw='{"name":"pre","attrs":{},"body":{"extsrc":"foo"}}'>foo</pre>
 
-<pre data-parsoid='{"stx":"html","strippedNL":"\n"}'>
-foo
+<pre typeof="mw:Extension/pre" about="#mwt4" data-mw='{"name":"pre","attrs":{},"body":{"extsrc":"\nfoo\n"}}'>foo
 </pre>
 
-<pre data-parsoid='{"stx":"html"}'>
+<pre typeof="mw:Extension/pre" about="#mwt6" data-mw='{"name":"pre","attrs":{},"body":{"extsrc":"\n\nfoo\n"}}'>
 
 foo
 </pre>
 
-<pre data-parsoid='{"stx":"html"}'>
+<pre typeof="mw:Extension/pre" about="#mwt8" data-mw='{"name":"pre","attrs":{},"body":{"extsrc":"\n\n\nfoo\n"}}'>
 
 
 foo
@@ -3510,7 +3525,7 @@ haha
 
 </pre>
 !! html/parsoid
-<pre data-parsoid='{"stx":"html"}'>
+<pre typeof="mw:Extension/pre" about="#mwt2" data-parsoid='{"stx":"html"}' data-mw='{"name":"pre","attrs":{},"body":{"extsrc":"\n\n\n\n\nhaha\n\n\n\n\nhaha\n\n\n\n\n"}}'>
 
 
 
@@ -3561,7 +3576,7 @@ HTML-pre: 3: other wikitext
 </pre>
 
 !! html/parsoid
-<pre data-parsoid='{"stx":"html","strippedNL":true}'>* foo
+<pre typeof="mw:Extension/pre" about="#mwt2" data-mw='{"name":"pre","attrs":{},"body":{"extsrc":"\n* foo\n# bar\n= no-h =\n&#39;&#39; no-italic &#39;&#39;\n[[ NoLink ]]\n"}}'>* foo
 # bar
 = no-h =
 '' no-italic ''
@@ -3709,7 +3724,7 @@ Definition lists: excess closed tags
 !! end
 
 !! test
-Bug 11748: Literal closing tags
+T13748: Literal closing tags
 !! wikitext
 <dl>
 <dt>test 1</dt>
@@ -3836,7 +3851,7 @@ should be left alone
 !! end
 
 !! test
-Definition Lists: Hacky use to indent tables, with comments (bug 63979)
+Definition Lists: Hacky use to indent tables, with comments (T65979)
 !! wikitext
 <!-- foo -->
 ::{|
@@ -4542,7 +4557,7 @@ Non-bracketed: http://example.com
 </p>
 !! end
 
-# parsoid doesn't explicitly mark autonumbered links, see bug 53505
+# parsoid doesn't explicitly mark autonumbered links, see T55505
 !! test
 External links: numbered
 !! wikitext
@@ -4587,7 +4602,7 @@ http://example.com/1$2345
 </p>
 !! end
 
-# parsoid doesn't explicitly mark autonumbered links, see bug 53505
+# parsoid doesn't explicitly mark autonumbered links, see T55505
 !! test
 External links: dollar sign in URL (autonumber)
 !! wikitext
@@ -4600,7 +4615,7 @@ External links: dollar sign in URL (autonumber)
 !!end
 
 !! test
-External links: open square bracket forbidden in URL (bug 4377)
+External links: open square bracket forbidden in URL (T6377)
 !! options
 parsoid=wt2html,wt2wt,html2html
 !! wikitext
@@ -4613,7 +4628,7 @@ http://example.com/1[2345
 !! end
 
 !! test
-External links: open square bracket forbidden in URL (named) (bug 4377)
+External links: open square bracket forbidden in URL (named) (T6377)
 !! options
 parsoid=wt2html,html2html
 !! wikitext
@@ -4627,7 +4642,7 @@ parsoid=wt2html,html2html
 
 # parsoid adds a space before the link name
 !! test
-External links: open square bracket forbidden in URL (named) (bug 4377)
+External links: open square bracket forbidden in URL (named) (T6377)
 Parsoid variant.
 !! wikitext
 [http://example.com/1 [2345]
@@ -4637,7 +4652,7 @@ Parsoid variant.
 !!end
 
 !! test
-External links: nowiki in URL link text (bug 6230)
+External links: nowiki in URL link text (T8230)
 !! wikitext
 [http://example.com/ <nowiki>''example site''</nowiki>]
 !! html
@@ -4646,7 +4661,7 @@ External links: nowiki in URL link text (bug 6230)
 !! end
 
 !! test
-External links: newline forbidden in text (bug 6230 regression check)
+External links: newline forbidden in text (T8230 regression check)
 !! wikitext
 [http://example.com/ first
 second]
@@ -4674,7 +4689,7 @@ External links: protocol-relative URL in brackets
 </p>
 !! end
 
-# parsoid doesn't explicitly mark autonumbered links, see bug 53505
+# parsoid doesn't explicitly mark autonumbered links, see T55505
 !! test
 External links: protocol-relative URL in brackets without text
 !! wikitext
@@ -4696,7 +4711,7 @@ External links: protocol-relative URL in free text is left alone
 !!end
 
 !! test
-External links: protocol-relative URL in the middle of a word is left alone (bug 30269)
+External links: protocol-relative URL in the middle of a word is left alone (T32269)
 !! wikitext
 foo//example.com/Foo
 !! html
@@ -4847,7 +4862,7 @@ bitcoin:;
 !! end
 
 !! test
-External links: No preceding word characters allowed (bug 65278)
+External links: No preceding word characters allowed (T67278)
 !! wikitext
 NOPEhttp://example.com
 N0http://example.com
@@ -4992,7 +5007,7 @@ Old &amp; use: http://x&amp;y
 !! end
 
 !! test
-External links: encoded equals (bug 6102)
+External links: encoded equals (T8102)
 !! wikitext
 http://example.com/?foo&#61;bar
 !! html/php
@@ -5004,7 +5019,7 @@ http://example.com/?foo&#61;bar
 
 ##
 ## Note that parsoid doesn't explicit mark autonumbered links, nor
-## does it number them.  As discussed in bug 53505, we can identify
+## does it number them.  As discussed in T55505, we can identify
 ## autonumbered links via CSS.
 ##
 
@@ -5048,7 +5063,7 @@ External links: [raw equals]
 # note that parsoid html is identical to [raw equals] case; so html2wt
 # mode will return the [raw equals] wikitext
 !! test
-External links: [encoded equals] (bug 6102)
+External links: [encoded equals] (T8102)
 !! options
 parsoid=wt2html,wt2wt,html2html
 !! wikitext
@@ -5108,7 +5123,7 @@ http://e&zwnj;xample.com/
 !! end
 
 !! test
-External links: www.jpeg.org (bug 554)
+External links: www.jpeg.org (T2554)
 !! wikitext
 http://www.jpeg.org
 !! html
@@ -5116,9 +5131,9 @@ http://www.jpeg.org
 </p>
 !! end
 
-# parsoid doesn't explicitly mark autonumbered links, see bug 53505
+# parsoid doesn't explicitly mark autonumbered links, see T55505
 !! test
-External links: URL within URL (original bug 2)
+External links: URL within URL (T2002)
 !! wikitext
 [http://www.unausa.org/newindex.asp?place=http://www.unausa.org/programs/mun.asp]
 !! html/php
@@ -5129,7 +5144,7 @@ External links: URL within URL (original bug 2)
 !! end
 
 !! test
-BUG 361: URL inside bracketed URL
+T2361: URL inside bracketed URL
 !! wikitext
 [http://www.example.com/foo http://www.example.com/bar]
 !! html
@@ -5138,7 +5153,7 @@ BUG 361: URL inside bracketed URL
 !! end
 
 !! test
-BUG 361: URL within URL, not bracketed
+T2361: URL within URL, not bracketed
 !! wikitext
 http://www.example.com/foo?=http://www.example.com/bar
 !! html
@@ -5147,7 +5162,7 @@ http://www.example.com/foo?=http://www.example.com/bar
 !! end
 
 !! test
-BUG 289: ">"-token in URL-tail
+T2289: ">"-token in URL-tail
 !! wikitext
 http://www.example.com/<hello>
 !! html
@@ -5156,7 +5171,7 @@ http://www.example.com/<hello>
 !!end
 
 !! test
-BUG 289: literal ">"-token in URL-tail
+T2289: literal ">"-token in URL-tail
 !! wikitext
 http://www.example.com/<b>html</b>
 !! html/php
@@ -5167,7 +5182,7 @@ http://www.example.com/<b>html</b>
 !! end
 
 !! test
-BUG 289: ">"-token in bracketed URL
+T2289: ">"-token in bracketed URL
 !! wikitext
 [http://www.example.com/<hello> stuff]
 !! html
@@ -5176,7 +5191,7 @@ BUG 289: ">"-token in bracketed URL
 !!end
 
 !! test
-BUG 289: literal ">"-token in bracketed URL
+T2289: literal ">"-token in bracketed URL
 !! wikitext
 [http://www.example.com/<b>html</b> stuff]
 !! html
@@ -5185,7 +5200,7 @@ BUG 289: literal ">"-token in bracketed URL
 !!end
 
 !! test
-BUG 289: literal double quote at end of URL
+T2289: literal double quote at end of URL
 !! wikitext
 http://www.example.com/"hello"
 !! html
@@ -5194,7 +5209,7 @@ http://www.example.com/"hello"
 !!end
 
 !! test
-BUG 289: literal double quote in bracketed URL
+T2289: literal double quote in bracketed URL
 !! wikitext
 [http://www.example.com/"hello" stuff]
 !! html
@@ -5203,7 +5218,7 @@ BUG 289: literal double quote in bracketed URL
 !!end
 
 !! test
-External links: multiple legal whitespace is fine, Magnus. Don't break it please. (bug 5081)
+External links: multiple legal whitespace is fine, Magnus. Don't break it please. (T7081)
 !! wikitext
 [http://www.example.com  test]
 !! html
@@ -5223,7 +5238,7 @@ External links: link text with spaces
 !! end
 
 !! test
-External links: wiki links within external link (Bug 3695)
+External links: wiki links within external link (T5695)
 !! options
 parsoid=wt2html,html2html
 !! wikitext
@@ -5236,7 +5251,7 @@ parsoid=wt2html,html2html
 !! end
 
 !! test
-BUG 787: Links with one slash after the url protocol are invalid
+T2787: Links with one slash after the url protocol are invalid
 !! wikitext
 http:/example.com
 
@@ -5257,7 +5272,7 @@ Bracketed external links with template-generated invalid target
 !! end
 
 !! test
-Bug 2702: Mismatched <i>, <b> and <a> tags are invalid
+T4702: Mismatched <i>, <b> and <a> tags are invalid
 !! wikitext
 ''[http://example.com text'']
 [http://example.com '''text]'''
@@ -5275,7 +5290,7 @@ Bug 2702: Mismatched <i>, <b> and <a> tags are invalid
 
 
 !! test
-Bug 4781: %26 in URL
+T6781: %26 in URL
 !! wikitext
 http://www.example.com/?title=AT%26T
 !! html/php
@@ -5288,7 +5303,7 @@ http://www.example.com/?title=AT%26T
 # According to https://www.w3.org/TR/2011/WD-html5-20110525/Overview.html#parsing-urls a plain
 # % is actually legal in HTML5. Any change in output would need testing though.
 !! test
-Bug 4781, 5267: %25 in URL
+T6781, T7267: %25 in URL
 !! wikitext
 http://www.example.com/?title=100%25_Bran
 !! html/php
@@ -5299,7 +5314,7 @@ http://www.example.com/?title=100%25_Bran
 !! end
 
 !! test
-Bug 4781, 5267: %28, %29 in URL
+T6781, T7267: %28, %29 in URL
 !! wikitext
 http://www.example.com/?title=Ben-Hur_%281959_film%29
 !! html/php
@@ -5311,7 +5326,7 @@ http://www.example.com/?title=Ben-Hur_%281959_film%29
 
 
 !! test
-Bug 4781: %26 in autonumber URL
+T6781: %26 in autonumber URL
 !! wikitext
 [http://www.example.com/?title=AT%26T]
 !! html/php
@@ -5322,7 +5337,7 @@ Bug 4781: %26 in autonumber URL
 !! end
 
 !! test
-Bug 4781, 5267: %26 in autonumber URL
+T6781, T7267: %26 in autonumber URL
 !! wikitext
 [http://www.example.com/?title=100%25_Bran]
 !! html/php
@@ -5333,7 +5348,7 @@ Bug 4781, 5267: %26 in autonumber URL
 !! end
 
 !! test
-Bug 4781, 5267: %28, %29 in autonumber URL
+T6781, T7267: %28, %29 in autonumber URL
 !! wikitext
 [http://www.example.com/?title=Ben-Hur_%281959_film%29]
 !! html/php
@@ -5345,7 +5360,7 @@ Bug 4781, 5267: %28, %29 in autonumber URL
 
 
 !! test
-Bug 4781: %26 in bracketed URL
+T6781: %26 in bracketed URL
 !! wikitext
 [http://www.example.com/?title=AT%26T link]
 !! html/php
@@ -5356,7 +5371,7 @@ Bug 4781: %26 in bracketed URL
 !! end
 
 !! test
-Bug 4781, 5267: %25 in bracketed URL
+T6781, T7267: %25 in bracketed URL
 !! wikitext
 [http://www.example.com/?title=100%25_Bran link]
 !! html
@@ -5365,7 +5380,7 @@ Bug 4781, 5267: %25 in bracketed URL
 !! end
 
 !! test
-Bug 4781, 5267: %28, %29 in bracketed URL
+T6781, T7267: %28, %29 in bracketed URL
 !! wikitext
 [http://www.example.com/?title=Ben-Hur_%281959_film%29 link]
 !! html/php
@@ -5376,7 +5391,7 @@ Bug 4781, 5267: %28, %29 in bracketed URL
 !! end
 
 !! test
-External link containing a period in the anchor. (bug 63947)
+External link containing a period in the anchor. (T65947)
 !! wikitext
 [//foo.org/bar#baz. bang]
 
@@ -5391,7 +5406,7 @@ External link containing a period in the anchor. (bug 63947)
 !! end
 
 !! test
-External link containing a single quote. (bug 63947)
+External link containing a single quote. (T65947)
 !! wikitext
 [//foo.org/bar'baz]
 
@@ -5406,7 +5421,7 @@ External link containing a single quote. (bug 63947)
 !! end
 
 !! test
-External link containing double-single-quotes in text '' (bug 4598 sanity check)
+External link containing double-single-quotes in text '' (T6598 sanity check)
 !! wikitext
 Some [http://example.com/ pretty ''italics'' and stuff]!
 !! html
@@ -5415,7 +5430,7 @@ Some [http://example.com/ pretty ''italics'' and stuff]!
 !! end
 
 !! test
-External link containing double-single-quotes in text embedded in italics (bug 4598 sanity check)
+External link containing double-single-quotes in text embedded in italics (T6598 sanity check)
 !! wikitext
 ''Some [http://example.com/ pretty ''italics'' and stuff]!''
 !! html
@@ -6375,7 +6390,7 @@ Nested table
 !! end
 
 !! test
-Invalid attributes in table cell (bug 1830)
+Invalid attributes in table cell (T3830)
 !! wikitext
 {|
 |Cell:|broken
@@ -6969,12 +6984,6 @@ Wikitext table with html-syntax row
 <td>foo</td></tr></tbody></table>
 !! end
 
-## Note that Parsoid output differs from PHP and PHP+tidy here.
-## The lack of <tr> tags in the PHP output is arguably a bug in the
-## PHP parser, which tidy then compounds by fostering the content
-## entirely out of the table.  Parsoid recognizes the table context
-## and generates <tr> and <td> wrappers as needed.  Hopefully nobody
-## depends on PHP's treatment of broken table markup!
 !! test
 Implicit <td> after a |-
 !! options
 !! html/php+tidy
 <p>a</p>
 !! html/parsoid
-<table>
-<tr><td>a</td></tr>
-</table>
-!! end
-
-# Again, Parsoid adds implicit <td>s here, PHP and Tidy strip the b out.
-!! test
-<pre> tags should be recognized in an explicit <td> context, but not in an implicit <td> context
-!! options
-parsoid=wt2html,html2html
-!! wikitext
-{|
-|-
-|
- a
-|-
- b
-|}
-!! html/php
-<table>
-
-<tr>
-<td>
-<pre>a
-</pre>
-</td></tr>
- b
-</table>
+<p data-parsoid='{"fostered":true,"autoInsertedEnd":true}'>a</p><table>
+<tbody><tr data-parsoid='{"startTagSrc":"|-","autoInsertedEnd":true}'>
 
-!! html/php+tidy
-<p>b</p>
-<table>
-<tr>
-<td>
-<pre>
-a
-</pre></td>
-</tr>
-</table>
-!! html/parsoid
-<table>
-<tbody>
-<tr><td><pre>a</pre></td></tr>
-<tr><td> b</td></tr>
-</tbody>
-</table>
+</tr></tbody></table>
 !! end
 
-# PHP + Tidy strips the list out of the table; Parsoid wraps it.
-# Parsoid generates the missing <td>, so wt2wt won't succeed.
 !! test
 Lists should be recognized in an implicit <td> context
 !! options
@@ -7063,13 +7028,10 @@ parsoid=wt2html,html2html
 <li>a</li>
 </ul>
 !! html/parsoid
-<table>
-<tr>
-<td><ul>
-<li>a</li>
-</ul></td>
-</tr>
-</table>
+<ul data-parsoid='{"fostered":true,"autoInsertedEnd":true}'><li>a</li></ul><table>
+<tbody><tr data-parsoid='{"startTagSrc":"|-","autoInsertedEnd":true}'>
+
+</tr></tbody></table>
 !! end
 
 !! test
@@ -7090,12 +7052,11 @@ Table cells not properly parsed in an implicit-td context
 !! html/parsoid
 <table>
 <tbody><tr data-parsoid='{"startTagSrc":"|-","autoInsertedEnd":true}'>
-<td style="background-color:#DC241f;" width="10px" about="#mwt1" typeof="mw:Transclusion" data-parsoid='{"autoInsertedEnd":true,"pi":[[]]}' data-mw='{"parts":["",{"template":{"target":{"wt":"table_attribs_4","href":"./Template:Table_attribs_4"},"params":{},"i":0}}," "]}'> </td><td data-parsoid='{"stx_v":"row","autoInsertedEnd":true}'> a </td><td data-parsoid='{"stx_v":"row","autoInsertedEnd":true}'> b</td></tr>
-</tbody></table>
+<td style="background-color:#DC241f;" width="10px" about="#mwt1" typeof="mw:Transclusion" data-parsoid='{"autoInsertedEnd":true,"pi":[[]]}' data-mw='{"parts":[{"template":{"target":{"wt":"table_attribs_4","href":"./Template:Table_attribs_4"},"params":{},"i":0}}," || a || b"]}'> </td><td about="#mwt1"> a </td><td about="#mwt1"> b</td></tr>
 !! end
 
 !! test
-Parsoid: Round-trip tables directly followed by content (bug 51219)
+Parsoid: Round-trip tables directly followed by content (T53219)
 !! options
 parsoid=wt2html,wt2wt
 !! wikitext
@@ -7122,7 +7083,7 @@ parsoid=wt2html,wt2wt
 !! end
 
 !! test
-Parsoid: Default to a newline after tables in new content (bug 51219)
+Parsoid: Default to a newline after tables in new content (T53219)
 !! options
 parsoid=html2wt
 !! html/parsoid
@@ -7531,7 +7492,7 @@ Piped link with no link text
 !! test
 Piped link with empty link text
 !! wikitext
-[[Main Page|<nowiki />]] - empty nowiki
+[[Main Page|<nowiki/>]] - empty nowiki
 [[Main Page| ]] - empty space
 [[Main Page|&nbsp;]] - empty non breaking space
 !! html/php
@@ -7540,7 +7501,7 @@ Piped link with empty link text
 <a href="/wiki/Main_Page" title="Main Page">&#160;</a> - empty non breaking space
 </p>
 !! html/parsoid
-<p><a rel="mw:WikiLink" href="./Main_Page" title="Main Page"><meta typeof="mw:Placeholder" data-parsoid='{"src":"&lt;nowiki />"}'/></a> - empty nowiki
+<p><a rel="mw:WikiLink" href="./Main_Page" title="Main Page"><span typeof="mw:Nowiki"></span></a> - empty nowiki
 <a rel="mw:WikiLink" href="./Main_Page" title="Main Page"> </a> - empty space
 <a rel="mw:WikiLink" href="./Main_Page" title="Main Page"><span typeof="mw:Entity" data-parsoid='{"src":"&amp;nbsp;","srcContent":" "}'> </span></a> - empty non breaking space</p>
 !! end
@@ -7606,7 +7567,7 @@ Some text
 !! endarticle
 
 !! test
-Bug 43661: Piped links with identical prefixes
+T45661: Piped links with identical prefixes
 !! wikitext
 [[prefixed article|prefixed articles with spaces]]
 
@@ -7685,7 +7646,7 @@ Link with multiple pipes
 !! end
 
 !! test
-Anchor containing a #. (bug 63430)
+Anchor containing a #. (T65430)
 !! wikitext
 [[Main Page#And#Link]]
 !! html/php
@@ -7721,7 +7682,7 @@ This is an article in the MemoryAlpha namespace
 !! endarticle
 
 !! test
-Namespace takes precedence over interwiki link (bug 51680)
+Namespace takes precedence over interwiki link (T53680)
 !! wikitext
 [[MemoryAlpha:AlphaTest]]
 !! html
@@ -7860,7 +7821,7 @@ Link containing a tilde
 !! end
 
 !! test
-Link containing double-single-quotes '' (bug 4598)
+Link containing double-single-quotes '' (T6598)
 !! wikitext
 [[Lista d''e paise d''o munno]]
 !! html/php
@@ -7882,7 +7843,23 @@ Link containing double quotes and spaces
 !! end
 
 !! test
-Link containing double-single-quotes '' in text (bug 4598 sanity check)
+File containing double quotes and spaces
+!! wikitext
+[[File:Cool "Gator".png]]
+!! html/parsoid
+<p><span class="mw-default-size" typeof="mw:Error mw:Image" data-parsoid='{"optList":[]}' data-mw='{"errors":[{"key":"missing-image","message":"This image does not exist."}]}'><a href="./File:Cool_%22Gator%22.png" data-parsoid='{"a":{"href":"./File:Cool_%22Gator%22.png"},"sa":{"href":"File:Cool \"Gator\".png"}}'><img resource='./File:Cool_"Gator".png' src="./Special:FilePath/Cool_%22Gator%22.png" height="220" width="220" data-parsoid='{"a":{"resource":"./File:Cool_\"Gator\".png","height":"220","width":"220","src":"./Special:FilePath/Cool_%22Gator%22.png"},"sa":{"resource":"File:Cool \"Gator\".png","src":"./Special:FilePath/Cool_\"Gator\".png"}}'/></a></span></p>
+!! end
+
+!! test
+Redirect containing double quotes and spaces
+!! wikitext
+#REDIRECT [[Cool "Gator"]]
+!! html/parsoid
+<link rel="mw:PageProp/redirect" href="./Cool_%22Gator%22" data-parsoid='{"src":"#REDIRECT ","a":{"href":"./Cool_%22Gator%22"},"sa":{"href":"Cool \"Gator\""}}'/>
+!! end
+
+!! test
+Link containing double-single-quotes '' in text (T6598 sanity check)
 !! wikitext
 Some [[Link|pretty ''italics'' and stuff]]!
 !! html/php
@@ -7893,7 +7870,7 @@ Some [[Link|pretty ''italics'' and stuff]]!
 !! end
 
 !! test
-Link containing double-single-quotes '' in text embedded in italics (bug 4598 sanity check)
+Link containing double-single-quotes '' in text embedded in italics (T6598 sanity check)
 !! wikitext
 ''Some [[Link|pretty ''italics'' and stuff]]!''
 !! html
@@ -7925,7 +7902,7 @@ Link with double quotes in title part (literal) and alternate part (interpreted)
 !! end
 
 !! test
-Broken image links with HTML captions (bug 39700)
+Broken image links with HTML captions (T41700)
 !! wikitext
 [[File:Nonexistent|<script></script>]]
 [[File:Nonexistent|100x100px|<script></script>]]
@@ -8020,7 +7997,7 @@ Piped link to URL: [[http://www.example.com|an example URL]]
 !! end
 
 !! test
-BUG 2: [[page|http://url/]] should link to page, not http://url/
+T2002: [[page|http://url/]] should link to page, not http://url/
 !! wikitext
 [[Main Page|http://url/]]
 !! html/php
@@ -8032,7 +8009,7 @@ BUG 2: [[page|http://url/]] should link to page, not http://url/
 
 # Parsoid does not mark self-links, by design.
 !! test
-BUG 337: Escaped self-links should be bold
+T2337: Escaped self-links should be bold
 !! options
 title=[[Bug462]]
 !! wikitext
@@ -8104,7 +8081,7 @@ Non-breaking spaces in title
 !!end
 
 !! test
-Internal link with ca linktrail, surrounded by bold apostrophes (bug 27473 primary issue)
+Internal link with ca linktrail, surrounded by bold apostrophes (T29473 primary issue)
 !! options
 language=ca
 !! wikitext
@@ -8115,7 +8092,7 @@ language=ca
 !! end
 
 !! test
-Internal link with ca linktrail, surrounded by italic apostrophes (bug 27473 primary issue)
+Internal link with ca linktrail, surrounded by italic apostrophes (T29473 primary issue)
 !! options
 language=ca
 !! wikitext
@@ -8126,7 +8103,7 @@ language=ca
 !! end
 
 !! test
-Internal link with en linktrail: no apostrophes (bug 27473)
+Internal link with en linktrail: no apostrophes (T29473)
 !! options
 language=en
 !! wikitext
@@ -8137,7 +8114,7 @@ language=en
 !! end
 
 !! test
-Internal link with ca linktrail with apostrophes (bug 27473)
+Internal link with ca linktrail with apostrophes (T29473)
 !! options
 language=ca
 !! wikitext
@@ -8148,7 +8125,7 @@ language=ca
 !! end
 
 !! test
-Internal link with kaa linktrail with apostrophes (bug 27473)
+Internal link with kaa linktrail with apostrophes (T29473)
 !! options
 language=kaa
 !! wikitext
@@ -8159,7 +8136,7 @@ language=kaa
 !! end
 
 !! test
-Link with multiple ":" in a subpage-supporting namespace (bug 63636)
+Link with multiple ":" in a subpage-supporting namespace (T65636)
 !! wikitext
 [[User:Foo/Test/63636:Bar|Test]]
 !! html/php
@@ -8378,7 +8355,7 @@ parsoid=wt2html,wt2wt,html2html
 !! end
 
 !! test
-Inline interwiki link with empty title (bug 2372)
+Inline interwiki link with empty title (T4372)
 !! options
 parsoid=wt2html,wt2wt,html2html
 !! wikitext
@@ -8391,7 +8368,7 @@ parsoid=wt2html,wt2wt,html2html
 !! end
 
 !! test
-Interwiki link encoding conversion (bug 1636)
+Interwiki link encoding conversion (T3636)
 !! wikitext
 *[[Wikipedia:ro:Olteni&#0355;a]]
 *[[Wikipedia:ro:Olteni&#355;a]]
@@ -8407,7 +8384,7 @@ Interwiki link encoding conversion (bug 1636)
 !! end
 
 !! test
-Interwiki link with fragment (bug 2130)
+Interwiki link with fragment (T4130)
 !! wikitext
 [[MeatBall:SoftSecurity#foo]]
 !! html
@@ -8533,7 +8510,7 @@ parsoid=wt2html,wt2wt,html2html
 !! end
 
 !! test
-Local interwiki link: prefix only (bug 64167)
+Local interwiki link: prefix only (T66167)
 !! options
 parsoid=wt2html,wt2wt,html2html
 !! wikitext
@@ -8546,7 +8523,7 @@ parsoid=wt2html,wt2wt,html2html
 !! end
 
 !! test
-Local interwiki link: with additional interwiki prefix (bug 61357)
+Local interwiki link: with additional interwiki prefix (T63357)
 !! options
 parsoid=wt2html,wt2wt,html2html
 !! wikitext
@@ -8641,7 +8618,7 @@ Blah blah blah
 !! end
 
 !! test
-Escaping of interlanguage links
+Escaping of interlanguage links (T129218, T156308)
 !! wikitext
 Blah blah blah
 [[:es:Spanish]]
@@ -8652,7 +8629,8 @@ Blah blah blah
 <a href="http://zh.wikipedia.org/wiki/Chinese" class="extiw" title="zh:Chinese"> zh : Chinese </a>
 </p>
 !! html/parsoid
-<p><a rel="mw:ExtLink" href="http://es.wikipedia.org/wiki/Spanish" title="es:Spanish">es:Spanish</a>
+<p>Blah blah blah
+<a rel="mw:ExtLink" href="http://es.wikipedia.org/wiki/Spanish" title="es:Spanish">es:Spanish</a>
 <a rel="mw:ExtLink" href="http://zh.wikipedia.org/wiki/Chinese" title="zh:Chinese"> zh : Chinese </a></p>
 !! end
 
@@ -8688,7 +8666,7 @@ Blah blah blah
 !! end
 
 !! test
-Double interlanguage link, with prefix links (bug 8897)
+Double interlanguage link, with prefix links (T10897)
 !! options
 language=ln
 !! wikitext
@@ -8705,7 +8683,7 @@ Blah blah blah
 !! end
 
 !! test
-"Extra" interlanguage links (bug 32189 / gerrit 111390)
+"Extra" interlanguage links (T34189 / gerrit 111390)
 !! wikitext
 Blah blah blah
 [[mul:Article]]
@@ -8757,7 +8735,7 @@ language=ln
 !! end
 
 !! test
-Parsoid bug 53221: Wikilinks should be properly entity-escaped
+Parsoid T55221: Wikilinks should be properly entity-escaped
 !! options
 parsoid={ "modes": ["html2wt"], "suppressErrors": true }
 !! html/parsoid
@@ -8834,7 +8812,7 @@ parsoid=wt2html,wt2wt,html2html
 !! end
 
 !! test
-Handle interwiki links pointing to the current wiki as plain wiki links (bug 45209)
+Handle interwiki links pointing to the current wiki as plain wiki links (T47209)
 !! wikitext
 [[mi:Foo]]
 !! html/php
@@ -8845,7 +8823,7 @@ Handle interwiki links pointing to the current wiki as plain wiki links (bug 452
 !! end
 
 !! test
-Interlanguage link with preceding local interwiki link (bug 68085)
+Interlanguage link with preceding local interwiki link (T70085)
 !! options
 parsoid=wt2html,wt2wt,html2html
 !! wikitext
@@ -9092,7 +9070,7 @@ Broken br tag sanitization
 </p>
 !! end
 
-# TODO: Fix html2html mode (bug 51055)!
+# TODO: Fix html2html mode (T53055)!
 !! test
 Parsoid: Broken br tag recognition
 !! options
@@ -9476,7 +9454,7 @@ parsoid
 !! end
 
 !! test
-List items are not parsed correctly following a <pre> block (bug 785)
+List items are not parsed correctly following a <pre> block (T2785)
 !! wikitext
 * <pre>foo</pre>
 * <pre>bar</pre>
@@ -9487,8 +9465,8 @@ List items are not parsed correctly following a <pre> block (bug 785)
 <li> zar</li></ul>
 
 !! html/parsoid
-<ul><li> <pre data-parsoid='{"stx":"html"}'>foo</pre></li>
-<li> <pre data-parsoid='{"stx":"html"}'>bar</pre></li>
+<ul><li> <pre typeof="mw:Extension/pre" about="#mwt2" data-mw='{"name":"pre","attrs":{},"body":{"extsrc":"foo"}}'>foo</pre></li>
+<li> <pre typeof="mw:Extension/pre" about="#mwt4" data-mw='{"name":"pre","attrs":{},"body":{"extsrc":"bar"}}'>bar</pre></li>
 <li> zar</li></ul>
 !! end
 
@@ -9685,7 +9663,7 @@ Unbalanced closing block tags break a list
 !! end
 
 # Parsoid fails this test, but it might be tricky to support properly.
-# See bug 68395.
+# See T70395.
 !! test
 Unbalanced closing non-block tags don't break a list
 (php parser relies on Tidy to fix up)
@@ -9727,7 +9705,7 @@ parsoid=wt2html,wt2wt,html2html
 <li><s> b </s></li></ol>
 !! end
 
-# See bug 68395.
+# See T70395.
 !!test
 1. List embedded in a formatting tag
 !! wikitext
@@ -9919,7 +9897,7 @@ Magic Word: {{CURRENTHOUR}}
 !! end
 
 !! test
-Magic Word: {{CURRENTWEEK}} (@bug 4594)
+Magic Word: {{CURRENTWEEK}} (T6594)
 !! wikitext
 {{CURRENTWEEK}}
 !! html
@@ -10266,7 +10244,7 @@ title=[['foo & bar = baz']]
 !! end
 
 !! test
-Magic Word: {{PAGENAME}} with metacharacters (bug 26781)
+Magic Word: {{PAGENAME}} with metacharacters (T28781)
 !! options
 title=[[*RFC 1234 http://example.com/]]
 !! wikitext
@@ -10290,7 +10268,7 @@ title=[[User:Ævar Arnfjörð Bjarmason]]
 !! end
 
 !! test
-Magic Word: {{PAGENAMEE}} with metacharacters (bug 26781)
+Magic Word: {{PAGENAMEE}} with metacharacters (T28781)
 !! options
 title=[[*RFC 1234 http://example.com/]]
 !! wikitext
@@ -10441,7 +10419,7 @@ Namespace 1 {{ns:01}}
 !! end
 
 !! test
-Namespace 0 {{ns:0}} (bug 4783)
+Namespace 0 {{ns:0}} (T6783)
 !! wikitext
 {{ns:0}}
 !! html
@@ -10449,7 +10427,7 @@ Namespace 0 {{ns:0}} (bug 4783)
 !! end
 
 !! test
-Namespace 0 {{ns:00}} (bug 4783)
+Namespace 0 {{ns:00}} (T6783)
 !! wikitext
 {{ns:00}}
 !! html
@@ -10593,7 +10571,7 @@ __proto__
 ### Magic links
 ###
 !! test
-Magic links: internal link to RFC (bug 479)
+Magic links: internal link to RFC (T2479)
 !! wikitext
 [[RFC 123]]
 !! html/php
@@ -10604,7 +10582,7 @@ Magic links: internal link to RFC (bug 479)
 !! end
 
 !! test
-Magic links: RFC (bug 479)
+Magic links: RFC (T2479)
 !! wikitext
 RFC 822
 !! html/php
@@ -10615,7 +10593,7 @@ RFC 822
 !! end
 
 !! test
-Magic links: RFC (bug 65278)
+Magic links: RFC (T67278)
 !! wikitext
 This is RFC 822 but thisRFC 822 is not RFC 822linked.
 !! html/php
@@ -10626,7 +10604,7 @@ This is RFC 822 but thisRFC 822 is not RFC 822linked.
 !! end
 
 !! test
-Magic links: RFC (w/ non-newline whitespace, bug 28950/29025)
+Magic links: RFC (w/ non-newline whitespace, T30950/T31025)
 !! wikitext
 RFC &nbsp;&#160;&#0160;&#xA0;&#Xa0; 822
 RFC
@@ -10643,7 +10621,7 @@ RFC
 !! end
 
 !! test
-Magic links: ISBN (bug 1937)
+Magic links: ISBN (T3937)
 !! wikitext
 ISBN 0-306-40615-2
 !! html/php
@@ -10654,7 +10632,7 @@ ISBN 0-306-40615-2
 !! end
 
 !! test
-Magic links: ISBN (bug 65278)
+Magic links: ISBN (T67278)
 !! wikitext
 This is ISBN 978-0-316-09811-3 but thisISBN 978-0-316-09811-3 is not ISBN 978-0-316-09811-3linked.
 !! html/php
@@ -10665,7 +10643,7 @@ This is ISBN 978-0-316-09811-3 but thisISBN 978-0-316-09811-3 is not ISBN 978-0-
 !! end
 
 !! test
-Magic links: ISBN (w/ non-newline whitespace, bug 28950/29025)
+Magic links: ISBN (w/ non-newline whitespace, T30950/T31025)
 !! wikitext
 ISBN &nbsp;&#160;&#0160;&#xA0;&#Xa0; 978&nbsp;0&#160;316&#0160;09811&#xA0;3
 ISBN
@@ -10699,7 +10677,7 @@ PMID 1234
 !! end
 
 !! test
-Magic links: PMID (bug 65278)
+Magic links: PMID (T67278)
 !! wikitext
 This is PMID 1234 but thisPMID 1234 is not PMID 1234linked.
 !! html/php
@@ -10710,7 +10688,7 @@ This is PMID 1234 but thisPMID 1234 is not PMID 1234linked.
 !! end
 
 !! test
-Magic links: PMID (w/ non-newline whitespace, bug 28950/29025)
+Magic links: PMID (w/ non-newline whitespace, T30950/T31025)
 !! wikitext
 PMID &nbsp;&#160;&#0160;&#xA0;&#Xa0; 1234
 PMID
@@ -10801,7 +10779,7 @@ Template with invalid target containing wikilink
 !! end
 
 !! test
-Template with just whitespace in it, bug #68421
+Template with just whitespace in it, T70421
 !! wikitext
 {{echo|{{ }}}}
 !! html/parsoid
@@ -11019,7 +10997,7 @@ Template with complex arguments
 !! end
 
 !! test
-BUG 553: link with two variables in a piped link
+T2553: link with two variables in a piped link
 !! wikitext
 {|
 |[[{{{1}}}|{{{2}}}]]
@@ -11180,7 +11158,7 @@ Template:table
 !! endarticle
 
 !! test
-BUG 529: Template with table, not included at beginning of line
+T2529: Template with table, not included at beginning of line
 !! wikitext
 foo {{table}}
 !! html
@@ -11199,7 +11177,7 @@ foo {{table}}
 !! end
 
 !! test
-BUG 523: Template shouldn't eat newline (or add an extra one before table)
+T2523: Template shouldn't eat newline (or add an extra one before table)
 !! wikitext
 foo
 {{table}}
@@ -11219,7 +11197,7 @@ foo
 !! end
 
 !! test
-BUG 41: Template parameters shown as broken links
+T2041: Template parameters shown as broken links
 !! wikitext
 {{{parameter}}}
 !! html
@@ -11467,7 +11445,7 @@ Template:Includeonly section
 !!endarticle
 
 !! test
-Bug 6563: Edit link generation for section shown by <includeonly>
+T8563: Edit link generation for section shown by <includeonly>
 !! wikitext
 {{includeonly section}}
 !! html
@@ -11478,7 +11456,7 @@ Bug 6563: Edit link generation for section shown by <includeonly>
 
 # Uses same input as the contents of [[Template:Includeonly section]]
 !! test
-Bug 6563: Section extraction for section shown by <includeonly>
+T8563: Section extraction for section shown by <includeonly>
 !! options
 section=T-2
 !! wikitext
@@ -11491,7 +11469,7 @@ section=T-2
 !! end
 
 !! test
-Bug 6563: Edit link generation for section suppressed by <includeonly>
+T8563: Edit link generation for section suppressed by <includeonly>
 !! wikitext
 <includeonly>
 ==Includeonly section==
@@ -11503,7 +11481,7 @@ Bug 6563: Edit link generation for section suppressed by <includeonly>
 !! end
 
 !! test
-Bug 6563: Section extraction for section suppressed by <includeonly>
+T8563: Section extraction for section suppressed by <includeonly>
 !! options
 section=1
 !! wikitext
@@ -12266,11 +12244,11 @@ Templates: HTML Tables: 5. Proper fostering of categories from inside
 parsoid=wt2html,wt2wt
 !! wikitext
 <table>[[Category:foo1]]<tr><td>foo</td></tr></table>
-<!--Two categories (Bug 50330)-->
+<!--Two categories (T52330)-->
 <table>[[Category:bar1]][[Category:bar2]]<tr><td>foo</td></tr></table>
 !! html
 <link rel="mw:PageProp/Category" href="./Category:Foo1"><table><tbody><tr><td>foo</td></tr></tbody></table>
-<!--Two categories (Bug 50330)-->
+<!--Two categories (T52330)-->
 <link rel="mw:PageProp/Category" href="./Category:Bar1"><link rel="mw:PageProp/Category" href="./Category:Bar2"><table><tbody><tr><td>foo</td></tr></tbody></table>
 !!end
 
@@ -12582,7 +12560,7 @@ Templates: Ugly templates: 4. newline-only template parameter inconsistency
 </p>
 !! end
 
-# Bug 64017 -- ugly wikitext with fostered content generates two template ranges that
+# T66017 -- ugly wikitext with fostered content generates two template ranges that
 # have a true overlap (T1-start - T2-start - T1-end - T2-end).
 !! test
 Templates: Ugly templates: 5. Template encapsulation test: Non-trivial overlap of template ranges is properly handled
@@ -12596,7 +12574,7 @@ Templates: Ugly templates: 5. Template encapsulation test: Non-trivial overlap o
 </table>
 !! end
 
-# Bug 64017 -- ugly wikitext with fostered content generates two template ranges
+# T66017 -- ugly wikitext with fostered content generates two template ranges
 # that are "identical" and generate nesting cycles in the algorithm
 !! test
 Templates: Ugly templates: 6. Template encapsulation test: Cyclical nesting of template ranges is properly handled
@@ -12687,7 +12665,7 @@ pst
 MediaWiki
 !! end
 
-# This is bug 89, which I fixed. -- wtm
+# This is T2089, which I fixed. -- wtm
 !! test
 pre-save transform: subst: templates with parameters
 !! options
@@ -12705,7 +12683,7 @@ Template:nowikitest
 !! endarticle
 
 !! test
-pre-save transform: nowiki in subst (bug 1188)
+pre-save transform: nowiki in subst (T3188)
 !! options
 pst
 !! wikitext
@@ -12721,7 +12699,7 @@ This template has <!-- a comment --> in it.
 !! endarticle
 
 !! test
-pre-save transform: comment in subst (bug 1936)
+pre-save transform: comment in subst (T3936)
 !! options
 pst
 !! wikitext
@@ -12770,7 +12748,7 @@ Template:dangerous
 !!endarticle
 
 !!test
-(confirming safety of fix for subst bug 1936)
+(confirming safety of fix for subst T3936)
 !! wikitext
 {{Template:dangerous}}
 !! html
@@ -12779,7 +12757,7 @@ Template:dangerous
 !! end
 
 !! test
-pre-save transform: comment containing gallery (bug 5024)
+pre-save transform: comment containing gallery (T7024)
 !! options
 pst
 !! wikitext
@@ -12809,7 +12787,7 @@ pst
 !!end
 
 !! test
-pre-save transform: <noinclude> in subst (bug 3298)
+pre-save transform: <noinclude> in subst (T5298)
 !! options
 pst
 !! wikitext
@@ -12819,7 +12797,7 @@ Foobar
 !! end
 
 !! test
-pre-save transform: <onlyinclude> in subst (bug 3298)
+pre-save transform: <onlyinclude> in subst (T5298)
 !! options
 pst
 !! wikitext
@@ -12841,7 +12819,7 @@ Template:SafeSubstTest
 !! endarticle
 
 !! test
-bug 22297: safesubst: works during PST
+T24297: safesubst: works during PST
 !! options
 pst
 !! wikitext
@@ -12851,7 +12829,7 @@ FoobarFoobar
 !! end
 
 !! test
-bug 22297: safesubst: works during normal parse
+T24297: safesubst: works during normal parse
 !! wikitext
 {{SafeSubstTest}}
 !! html
@@ -13009,7 +12987,7 @@ pst title=[[Ns:Somearticle (IGNORED), Context]]
 !! end
 
 !! test
-pre-save transform: context links ("pipe trick") with full-width parens and no space (Japanese and Chinese style, bug 30149)
+pre-save transform: context links ("pipe trick") with full-width parens and no space (Japanese and Chinese style, T32149)
 !! options
 pst
 !! wikitext
@@ -13029,7 +13007,7 @@ pst
 !! end
 
 !! test
-pre-save transform: context links ("pipe trick") with full-width parens and space (Japanese and Chinese style, bug 30149)
+pre-save transform: context links ("pipe trick") with full-width parens and space (Japanese and Chinese style, T32149)
 !! options
 pst
 !! wikitext
@@ -13049,7 +13027,7 @@ pst
 !! end
 
 !! test
-pre-save transform: context links ("pipe trick") with parens and no space (Korean style, bug 30149)
+pre-save transform: context links ("pipe trick") with parens and no space (Korean style, T32149)
 !! options
 pst
 !! wikitext
@@ -13069,7 +13047,7 @@ pst
 !! end
 
 !! test
-pre-save transform: context links ("pipe trick") with commas (bug 21660)
+pre-save transform: context links ("pipe trick") with commas (T23660)
 !! options
 pst
 !! wikitext
@@ -13120,7 +13098,7 @@ pst
 
 
 !! test
-pre-save transform: Signature expansion in nowiki tags (bug 93)
+pre-save transform: Signature expansion in nowiki tags (T2093)
 !! options
 pst disabled
 !! wikitext
@@ -13243,7 +13221,7 @@ msg
 !! end
 
 !! test
-message transform: <noinclude> in transcluded template (bug 4926)
+message transform: <noinclude> in transcluded template (T6926)
 !! options
 msg
 !! wikitext
@@ -13253,7 +13231,7 @@ Foobar
 !! end
 
 !! test
-message transform: <onlyinclude> in transcluded template (bug 4926)
+message transform: <onlyinclude> in transcluded template (T6926)
 !! options
 msg
 !! wikitext
@@ -13375,7 +13353,7 @@ Image with caption
 !! end
 
 !! test
-Image with caption, bug 53312 #1
+Image with caption, T55312 #1
 !! wikitext
 [[File:Foobar.jpg|right|Caption page stuff]]
 !! html/php
@@ -13386,7 +13364,7 @@ Image with caption, bug 53312 #1
 !! end
 
 !! test
-Image with caption, bug 53312 #2
+Image with caption, T55312 #2
 !! wikitext
 [[File:Foobar.jpg|right|Caption page=]]
 !! html/php
@@ -13397,7 +13375,7 @@ Image with caption, bug 53312 #2
 !! end
 
 !! test
-Image with caption, bug 53312 #3
+Image with caption, T55312 #3
 !! wikitext
 [[File:Foobar.jpg|right|Caption page=stuff]]
 !! html/php
@@ -13408,7 +13386,7 @@ Image with caption, bug 53312 #3
 !! end
 
 !! test
-Allow empty links in image captions (Bug 60753)
+Allow empty links in image captions (T62753)
 !! options
 thumbsize=220
 !! wikitext
@@ -13570,7 +13548,7 @@ Image with multiple widths -- use last
 !! end
 
 !! test
-Image with multiple alignments -- use first (bug 48664)
+Image with multiple alignments -- use first (T50664)
 !! options
 thumbsize=220
 !! wikitext
@@ -13605,7 +13583,7 @@ Image with width attribute at different positions
 
 # a sad bit of backward-compatibility
 !! test
-Image with size specified with pxpx (bug 13500, 51628)
+Image with size specified with pxpx (T15500, T53628)
 !! options
 parsoid=wt2html,wt2wt,html2html
 !! wikitext
@@ -13630,7 +13608,7 @@ Image with link parameter, wiki target
 <p><span class="mw-default-size" typeof="mw:Image"><a href="./Main_Page"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" data-file-width="1941" data-file-height="220" data-file-type="bitmap" height="220" width="1941"/></a></span></p>
 !! end
 
-# parsoid bug 49293 (part 1)
+# parsoid T51293 (part 1)
 !! test
 Image with link parameter, URL target
 !! wikitext
@@ -13642,7 +13620,7 @@ Image with link parameter, URL target
 <p><span class="mw-default-size" typeof="mw:Image"><a href="http://example.com/"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" data-file-width="1941" data-file-height="220" data-file-type="bitmap" height="220" width="1941"/></a></span></p>
 !! end
 
-# parsoid bug 49293 (part 2)
+# parsoid T51293 (part 2)
 !! test
 Image with link parameter, protocol-less URL target
 !! wikitext
@@ -14092,7 +14070,7 @@ Add test with existing image page
 !! end
 
 !! test
-bug 18784  Link to non-existent image page with caption should use caption as link text
+T20784  Link to non-existent image page with caption should use caption as link text
 !! wikitext
 [[:Image:test|caption]]
 !! html
@@ -14177,7 +14155,7 @@ parsoid=wt2html,wt2wt,html2html
 !! end
 
 !! test
-BUG 1887: A ISBN with a thumbnail
+T3887: A ISBN with a thumbnail
 !! wikitext
 [[File:Foobar.jpg|thumb|ISBN 1235467890]]
 !! html/php
@@ -14188,7 +14166,7 @@ BUG 1887: A ISBN with a thumbnail
 !! end
 
 !! test
-BUG 1887: A RFC with a thumbnail
+T3887: A RFC with a thumbnail
 !! wikitext
 [[File:Foobar.jpg|thumb|This is RFC 12354]]
 !! html/php
@@ -14199,7 +14177,7 @@ BUG 1887: A RFC with a thumbnail
 !! end
 
 !! test
-BUG 1887: A mailto link with a thumbnail
+T3887: A mailto link with a thumbnail
 !! wikitext
 [[File:Foobar.jpg|thumb|Please mailto:nobody@example.com]]
 !! html/php
@@ -14209,9 +14187,9 @@ BUG 1887: A mailto link with a thumbnail
 <figure class="mw-default-size" typeof="mw:Image/Thumb"><a href="./File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/thumb/3/3a/Foobar.jpg/220px-Foobar.jpg" data-file-width="1941" data-file-height="220" data-file-type="bitmap" height="25" width="220"/></a><figcaption>Please <a rel="mw:ExtLink" href="mailto:nobody@example.com">mailto:nobody@example.com</a></figcaption></figure>
 !! end
 
-# Pending resolution to bug 368
+# Pending resolution to T2368
 !! test
-BUG 648: Frameless image caption with a link
+T2648: Frameless image caption with a link
 !! wikitext
 [[File:Foobar.jpg|text with a [[link]] in it]]
 !! html/php
@@ -14222,7 +14200,7 @@ BUG 648: Frameless image caption with a link
 !! end
 
 !! test
-BUG 648: Frameless image caption with a link (suffix)
+T2648: Frameless image caption with a link (suffix)
 !! wikitext
 [[File:Foobar.jpg|text with a [[link]]foo in it]]
 !! html/php
@@ -14233,7 +14211,7 @@ BUG 648: Frameless image caption with a link (suffix)
 !! end
 
 !! test
-BUG 648: Frameless image caption with an interwiki link
+T2648: Frameless image caption with an interwiki link
 !! wikitext
 [[File:Foobar.jpg|text with a [[MeatBall:Link]] in it]]
 !! html/php
@@ -14244,7 +14222,7 @@ BUG 648: Frameless image caption with an interwiki link
 !! end
 
 !! test
-BUG 648: Frameless image caption with a piped interwiki link
+T2648: Frameless image caption with a piped interwiki link
 !! wikitext
 [[File:Foobar.jpg|text with a [[MeatBall:Link|link]] in it]]
 !! html/php
@@ -14298,7 +14276,7 @@ Entities in file name and attributes
 !! end
 
 !! test
-BUG 499: Alt text should have &#1234;, not &amp;1234;
+T2499: Alt text should have &#1234;, not &amp;1234;
 !! wikitext
 [[File:Foobar.jpg|&#9792;]]
 !! html/php
@@ -14382,7 +14360,7 @@ and some more text.]]
 !! end
 
 !! test
-Bug 3090: External links other than http: in image captions
+T5090: External links other than http: in image captions
 !! wikitext
 [[File:Foobar.jpg|thumb|200x200px|This caption has [irc://example.net irc] and [https://example.com Secure] ext links in it.]]
 !! html/php
@@ -14461,7 +14439,7 @@ parsoid=wt2html,wt2wt,html2html
 
 # Note that 'right' is the default alignment, despite the misspelled 'righ' below
 !! test
-Invalid image attributes (bug 62500)
+Invalid image attributes (T64500)
 !! options
 thumbsize=220
 parsoid=wt2html,wt2wt,html2html
@@ -14830,7 +14808,7 @@ Parsoid: dot-slash prefixed wikilinks
 !! end
 
 !! test
-Render invalid page names as plain text (bug 51090)
+Render invalid page names as plain text (T53090)
 !! wikitext
 [[./../foo|bar]]
 [[foo�|bar]]
@@ -14912,7 +14890,7 @@ Disabled subpages
 !! end
 
 !! test
-BUG 561: {{/Subpage}}
+T2561: {{/Subpage}}
 !! options
 subpage title=[[Page]]
 !! wikitext
@@ -15111,7 +15089,7 @@ Bar
 ##
 ## The whitespace on the empty line is part of the test. Please do not delete
 !! test
-1. Categories and newlines: All preceding newlines should be suppressed (courtesy bug 87)
+1. Categories and newlines: All preceding newlines should be suppressed (courtesy T2087)
 !! options
 parsoid=wt2html
 !! wikitext
@@ -15140,7 +15118,7 @@ This
 ##
 ## The whitespace on the empty line is part of the test. Please do not delete
 !! test
-2. Categories and newlines: All preceding newlines should be suppressed (courtesy bug 87)
+2. Categories and newlines: All preceding newlines should be suppressed (courtesy T2087)
 !! options
 parsoid=wt2html
 !! wikitext
@@ -15336,7 +15314,7 @@ parsoid
 !! end
 
 !! test
-Normalize hrefs properly before testing for invalid link targets (bug 70894)
+Normalize hrefs properly before testing for invalid link targets (T72894)
 !! options
 parsoid=html2wt
 !! html/parsoid
@@ -15381,7 +15359,7 @@ es:Alimento fr:Nourriture zh:食品
 !! end
 
 !! test
-Duplicate interlanguage links (bug 24502)
+Duplicate interlanguage links (T26502)
 !! options
 ill
 !! wikitext
@@ -15608,7 +15586,7 @@ __FORCETOC__
 !! end
 
 !! test
-TOC with wgMaxTocLevel=3 (bug 6204)
+TOC with wgMaxTocLevel=3 (T8204)
 !! options
 wgMaxTocLevel=3
 !! wikitext
@@ -15645,7 +15623,7 @@ wgMaxTocLevel=3
 !! end
 
 !! test
-TOC with wgMaxTocLevel=3 and two level four headings (bug 6204)
+TOC with wgMaxTocLevel=3 and two level four headings (T8204)
 !! options
 wgMaxTocLevel=3
 !! wikitext
@@ -15687,7 +15665,7 @@ Resolving duplicate section names
 !! end
 
 !! test
-Resolving duplicate section names with differing case (bug 10721)
+Resolving duplicate section names with differing case (T12721)
 !! wikitext
 == Foo bar ==
 == Foo Bar ==
@@ -15766,7 +15744,7 @@ __TOC__
 !! end
 
 !! test
-BUG 1219 URL next to image (good)
+T3219 URL next to image (good)
 !! wikitext
 http://example.com [[File:Foobar.jpg]]
 !! html/php
@@ -15777,7 +15755,7 @@ http://example.com [[File:Foobar.jpg]]
 !!end
 
 !! test
-Short headings with trailing space should match behavior of Parser::doHeadings (bug 19910)
+Short headings with trailing space should match behavior of Parser::doHeadings (T21910)
 !! wikitext
 === 
 The line above must have a trailing space!
@@ -15794,7 +15772,7 @@ But just in case it doesn't...
 !! end
 
 !! test
-Header with special characters (bug 25462)
+Header with special characters (T27462)
 !! wikitext
 The tooltips shall not show entities to the user (ie. be double escaped)
 
@@ -15937,7 +15915,7 @@ Headers with excess '=' characters
 !! end
 
 !! test
-HTML headers vs TOC (bug 23393)
+HTML headers vs TOC (T25393)
 (__NOEDITSECTION__ for clearer output, doesn't matter here)
 !! wikitext
 <h1>Header 1</h1>
@@ -15994,7 +15972,7 @@ c3-->
 !! end
 
 !! test
-BUG 1219 URL next to image (broken)
+T3219 URL next to image (broken)
 !! wikitext
 http://example.com[[File:Foobar.jpg]]
 !! html/php
@@ -16005,7 +15983,7 @@ http://example.com[[File:Foobar.jpg]]
 !!end
 
 !! test
-Bug 1186 news: in the middle of text
+T3186 news: in the middle of text
 !! wikitext
 http://en.wikinews.org/wiki/Wikinews:Workplace
 !! html
@@ -16263,10 +16241,10 @@ HTML tag with leading space is parsed as text
 !! end
 
 ###
-### Nesting tests (see bug 41545, 50604, 51081)
+### Nesting tests (see T43545, T52604, T53081)
 ###
 
-# This test case is fixed in Parsoid by domino 1.0.12. (bug 50604)
+# This test case is fixed in Parsoid by domino 1.0.12. (T52604)
 # Note that html2wt is considerably more difficult if we use <b> in
 # the test case, instead of <small>
 !! test
@@ -16278,7 +16256,7 @@ Ensure that HTML adoption agency algorithm is properly implemented.
 </p>
 !! end
 
-# This was bug 41545 in the PHP parser.
+# This was T43545 in the PHP parser.
 # Note that tidy doesn't handle this correctly.
 !! test
 Nesting of <kbd>
@@ -16289,9 +16267,9 @@ Nesting of <kbd>
 </p>
 !! end
 
-# The following cases were bug 51081 in the PHP parser.
+# The following cases were T53081 in the PHP parser.
 # Note that there are some other nestable tags (b, i, etc) which are
-# not covered; see bug 51081 for discussion.
+# not covered; see T53081 for discussion.
 
 # Note that tidy doesn't handle this correctly.
 !! test
@@ -16379,7 +16357,7 @@ Media link with nasty text
 !! end
 
 !! test
-Media link to nonexistent file (bug 1702)
+Media link to nonexistent file (T3702)
 !! wikitext
 [[Media:No such.jpg]]
 !! html
@@ -16388,7 +16366,7 @@ Media link to nonexistent file (bug 1702)
 !! end
 
 !! test
-Image link to nonexistent file (bug 1850 - good)
+Image link to nonexistent file (T3850 - good)
 !! wikitext
 [[File:No_such.jpg]]
 !! html/php
@@ -16399,7 +16377,7 @@ Image link to nonexistent file (bug 1850 - good)
 !! end
 
 !! test
-:Image link to nonexistent file (bug 1850 - bad)
+:Image link to nonexistent file (T3850 - bad)
 !! wikitext
 [[:Image:No such.jpg]]
 !! html/php
@@ -16412,7 +16390,7 @@ Image link to nonexistent file (bug 1850 - good)
 
 
 !! test
-Character reference normalization in link text (bug 1938)
+Character reference normalization in link text (T3938)
 !! wikitext
 [[Main Page|this&that]]
 !! html
@@ -16429,7 +16407,7 @@ The page's name is U+05d0 U+05b7, with non-canonical form U+FB2E
 !! endarticle
 
 !! test
-(bug 19451) Links should refer to the normalized form.
+(T21451) Links should refer to the normalized form.
 !! wikitext
 [[&#xFB2E;]]
 [[&#x5d0;&#x5b7;]]
@@ -16446,7 +16424,7 @@ The page's name is U+05d0 U+05b7, with non-canonical form U+FB2E
 !! end
 
 !! test
-Empty attribute crash test (bug 2067)
+Empty attribute crash test (T4067)
 !! wikitext
 <font color="">foo</font>
 !! html
@@ -16455,7 +16433,7 @@ Empty attribute crash test (bug 2067)
 !! end
 
 !! test
-Empty attribute crash test single-quotes (bug 2067)
+Empty attribute crash test single-quotes (T4067)
 !! wikitext
 <font color=''>foo</font>
 !! html
@@ -16514,7 +16492,7 @@ parsoid=wt2html,html2html
 !! end
 
 !! test
-Bug 2095: link with three closing brackets
+T4095: link with three closing brackets
 !! wikitext
 [[Main Page]]]
 !! html/php
@@ -16525,7 +16503,7 @@ Bug 2095: link with three closing brackets
 !! end
 
 !! test
-Bug 2095: link with pipe and three closing brackets
+T4095: link with pipe and three closing brackets
 !! wikitext
 [[Main Page|link]]]
 !! html/php
@@ -16536,7 +16514,7 @@ Bug 2095: link with pipe and three closing brackets
 !! end
 
 !! test
-Bug 2095: link with pipe and three closing brackets, version 2
+T4095: link with pipe and three closing brackets, version 2
 !! wikitext
 [[Main Page|[http://example.com/]]]
 !! html/php
@@ -16570,7 +16548,7 @@ Template:Div style
 !! endarticle
 
 !! test
-Bug 2304: HTML attribute safety (safe template; regression bug 2309)
+T4304: HTML attribute safety (safe template; regression T4309)
 !! wikitext
 <div title="{{test}}"></div>
 !! html/php
@@ -16582,7 +16560,7 @@ Bug 2304: HTML attribute safety (safe template; regression bug 2309)
 
 # Parsoid has enough context to handle this case
 !! test
-Bug 2304: HTML attribute safety (dangerous template; 2309)
+T4304: HTML attribute safety (dangerous template; 2309)
 !! wikitext
 <div title="{{dangerous attribute}}"></div>
 !! html/php
@@ -16593,7 +16571,7 @@ Bug 2304: HTML attribute safety (dangerous template; 2309)
 !! end
 
 !! test
-Bug 2304: HTML attribute safety (dangerous style template; 2309)
+T4304: HTML attribute safety (dangerous style template; 2309)
 !! wikitext
 <div style="{{dangerous style attribute}}"></div>
 !! html/php
@@ -16604,7 +16582,7 @@ Bug 2304: HTML attribute safety (dangerous style template; 2309)
 !! end
 
 !! test
-Bug 2304: HTML attribute safety (safe parameter; 2309)
+T4304: HTML attribute safety (safe parameter; 2309)
 !! wikitext
 {{div style|width: 200px}}
 !! html/php
@@ -16615,7 +16593,7 @@ Bug 2304: HTML attribute safety (safe parameter; 2309)
 !! end
 
 !! test
-Bug 2304: HTML attribute safety (unsafe parameter; 2309)
+T4304: HTML attribute safety (unsafe parameter; 2309)
 !! wikitext
 {{div style|width: expression(alert(document.cookie))}}
 !! html/php
@@ -16627,7 +16605,7 @@ Bug 2304: HTML attribute safety (unsafe parameter; 2309)
 
 ## Parsoid output here differs; needs investigation.
 !! test
-Bug 2304: HTML attribute safety (unsafe breakout parameter; 2309)
+T4304: HTML attribute safety (unsafe breakout parameter; 2309)
 !! wikitext
 {{div style|"><script>alert(document.cookie)</script>}}
 !! html
@@ -16637,7 +16615,7 @@ Bug 2304: HTML attribute safety (unsafe breakout parameter; 2309)
 
 ## Parsoid output here differs; needs investigation.
 !! test
-Bug 2304: HTML attribute safety (unsafe breakout parameter 2; 2309)
+T4304: HTML attribute safety (unsafe breakout parameter 2; 2309)
 !! wikitext
 {{div style|" ><script>alert(document.cookie)</script>}}
 !! html
@@ -16646,7 +16624,7 @@ Bug 2304: HTML attribute safety (unsafe breakout parameter 2; 2309)
 !! end
 
 !! test
-Bug 2304: HTML attribute safety (link)
+T4304: HTML attribute safety (link)
 !! wikitext
 <div title="[[Main Page]]"></div>
 !! html
@@ -16655,7 +16633,7 @@ Bug 2304: HTML attribute safety (link)
 !! end
 
 !! test
-Bug 2304: HTML attribute safety (italics)
+T4304: HTML attribute safety (italics)
 !! wikitext
 <div title="''foobar''"></div>
 !! html
@@ -16664,7 +16642,7 @@ Bug 2304: HTML attribute safety (italics)
 !! end
 
 !! test
-Bug 2304: HTML attribute safety (bold)
+T4304: HTML attribute safety (bold)
 !! wikitext
 <div title="'''foobar'''"></div>
 !! html
@@ -16673,7 +16651,7 @@ Bug 2304: HTML attribute safety (bold)
 !! end
 
 !! test
-Bug 2304: HTML attribute safety (ISBN)
+T4304: HTML attribute safety (ISBN)
 !! wikitext
 <div title="ISBN 1234567890"></div>
 !! html
@@ -16682,7 +16660,7 @@ Bug 2304: HTML attribute safety (ISBN)
 !! end
 
 !! test
-Bug 2304: HTML attribute safety (RFC)
+T4304: HTML attribute safety (RFC)
 !! wikitext
 <div title="RFC 1234"></div>
 !! html
@@ -16691,7 +16669,7 @@ Bug 2304: HTML attribute safety (RFC)
 !! end
 
 !! test
-Bug 2304: HTML attribute safety (PMID)
+T4304: HTML attribute safety (PMID)
 !! wikitext
 <div title="PMID 1234567890"></div>
 !! html
@@ -16700,7 +16678,7 @@ Bug 2304: HTML attribute safety (PMID)
 !! end
 
 !! test
-Bug 2304: HTML attribute safety (web link)
+T4304: HTML attribute safety (web link)
 !! wikitext
 <div title="http://example.com/"></div>
 !! html
@@ -16709,7 +16687,7 @@ Bug 2304: HTML attribute safety (web link)
 !! end
 
 !! test
-Bug 2304: HTML attribute safety (named web link)
+T4304: HTML attribute safety (named web link)
 !! wikitext
 <div title="[http://example.com/ link]"></div>
 !! html
@@ -16718,7 +16696,7 @@ Bug 2304: HTML attribute safety (named web link)
 !! end
 
 !! test
-Bug 3244: HTML attribute safety (extension; safe)
+T5244: HTML attribute safety (extension; safe)
 !! wikitext
 <div style="<nowiki>background:blue</nowiki>"></div>
 !! html/php
@@ -16729,7 +16707,7 @@ Bug 3244: HTML attribute safety (extension; safe)
 !! end
 
 !! test
-Bug 3244: HTML attribute safety (extension; unsafe)
+T5244: HTML attribute safety (extension; unsafe)
 !! wikitext
 <div style="<nowiki>border-left:expression(alert(document.cookie))</nowiki>"></div>
 !! html/php
@@ -16786,7 +16764,7 @@ MSIE CSS safety test: comment in expression
 !! end
 
 !! test
-CSS safety test (all browsers): vertical tab (bug 55332 / CVE-2013-4567)
+CSS safety test (all browsers): vertical tab (T57332 / CVE-2013-4567)
 !! wikitext
 <p style="font-size: 100px; background-image:url\b(https://www.google.com/images/srpr/logo6w.png)">A</p>
 !! html/php
@@ -16797,7 +16775,7 @@ CSS safety test (all browsers): vertical tab (bug 55332 / CVE-2013-4567)
 !! end
 
 !! test
-MSIE 6 CSS safety test: Fullwidth (bug 55332)
+MSIE 6 CSS safety test: Fullwidth (T57332)
 !! wikitext
 <p style="font-size: 100px; color: expression((title='XSSed'),'red')">A</p>
 <div style="top:EXPRESSION(alert())">B</div>
@@ -16811,7 +16789,7 @@ MSIE 6 CSS safety test: Fullwidth (bug 55332)
 !! end
 
 !! test
-MSIE 6 CSS safety test: IPA extensions (bug 55332)
+MSIE 6 CSS safety test: IPA extensions (T57332)
 !! wikitext
 <div style="background-image:uʀʟ(javascript:alert())">A</div>
 <p style="font-size: 100px; color: expʀessɪoɴ((title='XSSed'),'red')">B</p>
@@ -16825,7 +16803,7 @@ MSIE 6 CSS safety test: IPA extensions (bug 55332)
 !! end
 
 !! test
-MSIE 6 CSS safety test: sup/sub script (bug 55332)
+MSIE 6 CSS safety test: sup/sub script (T57332)
 !! wikitext
 <div style="background-image:url⁽javascript:alert())">A</div>
 <div style="background-image:url₍javascript:alert())">B</div>
@@ -16857,7 +16835,7 @@ style="-o-link:attr(title);-o-link-source:current">X</div>
 !! end
 
 !! test
-MSIE 6 CSS safety test: Repetition markers (bug 55332)
+MSIE 6 CSS safety test: Repetition markers (T57332)
 !! wikitext
 <p style="font-size: 100px; color: expres〱ion((title='XSSed'),'red')">A</p>
 <p style="font-size: 100px; color: expresゝion((title='XSSed'),'red')">B</p>
@@ -16938,7 +16916,7 @@ Template:Identity
 !! endarticle
 
 !! test
-Expansion of multi-line templates in attribute values (bug 6255)
+Expansion of multi-line templates in attribute values (T8255)
 !! wikitext
 <div style="background: {{identity|#00FF00}}">-</div>
 !! html
@@ -16947,20 +16925,20 @@ Expansion of multi-line templates in attribute values (bug 6255)
 !! end
 
 !! test
-Expansion of multi-line templates in attribute values (bug 6255 sanity check)
+Expansion of multi-line templates in attribute values (T8255 sanity check)
 !! wikitext
-<div style="background: 
+<div style="background:
 #00FF00">-</div>
 !! html/php
 <div style="background: #00FF00">-</div>
 
 !! html/parsoid
-<div style="background: 
+<div style="background:
 #00FF00">-</div>
 !! end
 
 !! test
-Expansion of multi-line templates in attribute values (bug 6255 sanity check 2)
+Expansion of multi-line templates in attribute values (T8255 sanity check 2)
 !! wikitext
 <div style="background: &#10;#00FF00">-</div>
 !! html
@@ -17136,7 +17114,7 @@ array (
 !! end
 
 !! test
-Parser hook: argument containing a forward slash (bug 5344)
+Parser hook: argument containing a forward slash (T7344)
 !! wikitext
 <tag filename="/tmp/bla"></tag>
 !! html/php
@@ -17153,7 +17131,7 @@ array (
 
 ## Don't expect parsoid to rt this form.
 !! test
-Parser hook: empty input using terminated empty elements (bug 2374)
+Parser hook: empty input using terminated empty elements (T4374)
 !! options
 parsoid=wt2html,html2html
 !! wikitext
@@ -17173,7 +17151,7 @@ array (
 ## </tag> should be output literally since there is no matching tag that begins it
 ## Don't expect parsoid to rt this form.
 !! test
-Parser hook: basic arguments using terminated empty elements (bug 2374)
+Parser hook: basic arguments using terminated empty elements (T4374)
 !! options
 parsoid=wt2html
 !! wikitext
@@ -17337,7 +17315,7 @@ Sanitizer: Escaping of spaces, multibyte characters, colons & other stuff in id=
 # In HTML5, the restrictions are that id must contain at least one character,
 # and must not contain any space characters.
 !! test
-Sanitizer: Validating the contents of the id attribute (bug 4515)
+Sanitizer: Validating the contents of the id attribute (T6515)
 !! options
 disabled
 !! wikitext
@@ -17348,7 +17326,7 @@ Something ...
 
 # In HTML5, id must be unique amongst all the ids in the element's home subtree.
 !! test
-Sanitizer: Validating id attribute uniqueness (bug 4515, bug 6301)
+Sanitizer: Validating id attribute uniqueness (T6515, T8301)
 !! options
 disabled
 !! wikitext
@@ -17382,7 +17360,7 @@ Sanitizer: Validating that <meta> and <link> work, but only for Microdata
 !! end
 
 !! test
-Language converter: output gets cut off unexpectedly (bug 5757)
+Language converter: output gets cut off unexpectedly (T7757)
 !! options
 language=zh
 !! wikitext
@@ -17402,7 +17380,7 @@ all additional text is vanished
 !! end
 
 !! test
-Self closed html pairs (bug 5487)
+Self closed html pairs (T7487)
 !! options
 !! wikitext
 <center><font id="bug" />Centered text</center>
@@ -17427,7 +17405,7 @@ C'est grave !
 !! end
 
 !! test
-Punctuation: CSS !important (bug 11874)
+Punctuation: CSS !important (T13874)
 !! wikitext
 <div style="width:50% !important">important</div>
 !! html
@@ -17436,7 +17414,7 @@ Punctuation: CSS !important (bug 11874)
 !!end
 
 !! test
-Punctuation: CSS ! important (bug 11874; with space after)
+Punctuation: CSS ! important (T13874; with space after)
 !! wikitext
 <div style="width:50% ! important">important</div>
 !! html
@@ -17445,7 +17423,7 @@ Punctuation: CSS ! important (bug 11874; with space after)
 !!end
 
 !! test
-HTML bullet list, closed tags (bug 5497)
+HTML bullet list, closed tags (T7497)
 !! wikitext
 <ul>
 <li>One</li>
@@ -17466,7 +17444,7 @@ HTML bullet list, closed tags (bug 5497)
 !! end
 
 !! test
-HTML bullet list, unclosed tags (bug 5497)
+HTML bullet list, unclosed tags (T7497)
 !! wikitext
 <ul>
 <li>One
@@ -17486,7 +17464,7 @@ HTML bullet list, unclosed tags (bug 5497)
 !! end
 
 !! test
-HTML ordered list, closed tags (bug 5497)
+HTML ordered list, closed tags (T7497)
 !! wikitext
 <ol>
 <li>One</li>
@@ -17507,7 +17485,7 @@ HTML ordered list, closed tags (bug 5497)
 !! end
 
 !! test
-HTML ordered list, unclosed tags (bug 5497)
+HTML ordered list, unclosed tags (T7497)
 !! options
 !! wikitext
 <ol>
@@ -17528,7 +17506,7 @@ HTML ordered list, unclosed tags (bug 5497)
 !! end
 
 !! test
-HTML nested bullet list, closed tags (bug 5497)
+HTML nested bullet list, closed tags (T7497)
 !! wikitext
 <ul>
 <li>One</li>
@@ -17563,7 +17541,7 @@ HTML nested bullet list, closed tags (bug 5497)
 !! end
 
 !! test
-HTML nested bullet list, open tags (bug 5497)
+HTML nested bullet list, open tags (T7497)
 !! wikitext
 <ul>
 <li>One
@@ -17600,7 +17578,7 @@ HTML nested bullet list, open tags (bug 5497)
 !! end
 
 !! test
-HTML nested ordered list, closed tags (bug 5497)
+HTML nested ordered list, closed tags (T7497)
 !! wikitext
 <ol>
 <li>One</li>
@@ -17625,7 +17603,7 @@ HTML nested ordered list, closed tags (bug 5497)
 !! end
 
 !! test
-HTML nested ordered list, open tags (bug 5497)
+HTML nested ordered list, open tags (T7497)
 !! wikitext
 <ol>
 <li>One
@@ -17672,9 +17650,9 @@ HTML ordered list item with parameters oddity
 
 !! end
 
-# parsoid doesn't explicitly mark autonumbered links, see bug 53505
+# parsoid doesn't explicitly mark autonumbered links, see T55505
 !!test
-bug 5918: autonumbering
+T7918: autonumbering
 !! wikitext
 [http://first/] [http://second] [ftp://ftp]
 
@@ -17881,7 +17859,7 @@ MOVE YOUR MOUSE CURSOR OVER THIS TEXT
 # <li class="&#124;&#124;">
 # }}}blah" onmouseover="alert('hello world');" align="left"<b>MOVE MOUSE CURSOR OVER HERE</b>
 !!test
-Fuzz testing: Parser25 (bug 6055)
+Fuzz testing: Parser25 (T8055)
 !! wikitext
 {{{
 | 
@@ -17918,7 +17896,7 @@ http://example.com<nowiki>junk</nowiki>
 <p><a rel="mw:ExtLink" href="http://example.com" data-parsoid='{"stx":"url"}'>http://example.com</a><span typeof="mw:Nowiki">junk</span></p>
 !! end
 
-!!test
+!! test
 Fuzz testing: URL adjacent extension (no space, dirty; pre)
 !! wikitext
 http://example.com<pre>junk</pre>
@@ -17931,10 +17909,10 @@ http://example.com<pre>junk</pre>
 junk
 </pre>
 !! html/parsoid
-<p><a rel="mw:ExtLink" href="http://example.com" data-parsoid='{"stx":"url"}'>http://example.com</a></p><pre data-parsoid='{"stx":"html"}'>junk</pre>
-!!end
+<p><a rel="mw:ExtLink" href="http://example.com" data-parsoid='{"stx":"url"}'>http://example.com</a></p><pre typeof="mw:Extension/pre" about="#mwt2" data-mw='{"name":"pre","attrs":{},"body":{"extsrc":"junk"}}'>junk</pre>
+!! end
 
-!!test
+!! test
 Fuzz testing: image with bogus manual thumbnail
 !! wikitext
 [[Image:foobar.jpg|thumbnail= ]]
@@ -17943,19 +17921,21 @@ Fuzz testing: image with bogus manual thumbnail
 
 !! html/parsoid
 <figure class="mw-default-size" typeof="mw:Error mw:Image/Thumb" data-parsoid='{"optList":[{"ck":"manualthumb","ak":"thumbnail= "}]}' data-mw='{"errors":[{"key":"missing-thumbnail","message":"This thumbnail does not exist.","params":{"name":""}}],"thumb":""}'><a href="./File:Foobar.jpg" data-parsoid='{"a":{"href":"./File:Foobar.jpg"},"sa":{}}'><img resource="./File:Foobar.jpg" src="./Special:FilePath/" height="220" width="220" data-parsoid='{"a":{"resource":"./File:Foobar.jpg","height":"220","width":"220"},"sa":{"resource":"Image:foobar.jpg"}}'/></a></figure>
-!!end
+!! end
 
 !! test
-Fuzz testing: encoded newline in generated HTML replacements (bug 6577)
+Fuzz testing: encoded newline in generated HTML replacements (T8577)
 !! wikitext
 <pre dir="&#10;"></pre>
-!! html
+!! html/php
 <pre dir="&#10;"></pre>
 
+!! html/parsoid
+<pre typeof="mw:Extension/pre" about="#mwt2" dir="&amp;#10;" data-mw='{"name":"pre","attrs":{"dir":"&amp;#10;"},"body":{"extsrc":""}}'></pre>
 !! end
 
 !! test
-Parsing optional HTML elements (Bug 6171)
+Parsing optional HTML elements (T8171)
 !! options
 !! wikitext
 <table>
@@ -17977,7 +17957,7 @@ Parsing optional HTML elements (Bug 6171)
 !! end
 
 !! test
-Correct handling of <td>, <tr> (Bug 6171)
+Correct handling of <td>, <tr> (T8171)
 !! options
 !! wikitext
 <table>
@@ -18073,7 +18053,7 @@ Special page transclusion
 !! end
 
 !! test
-Special page transclusion twice (bug 5021)
+Special page transclusion twice (T7021)
 !! options
 !! wikitext
 {{Special:Prefixindex/Xyzzyx}}
@@ -18454,7 +18434,7 @@ section=2
 ==b==
 !! end
 
-# Formerly testing for bug 2587, now resolved by the use of unmarked sections
+# Formerly testing for T4587, now resolved by the use of unmarked sections
 # instead of respecting commented sections
 !! test
 Section extraction prefixed by comment (section 1)
@@ -18478,7 +18458,7 @@ section=2
 
 !!end
 
-# Formerly testing for bug 2607, now resolved by the use of unmarked sections
+# Formerly testing for T4607, now resolved by the use of unmarked sections
 # instead of respecting HTML-style headings
 !! test
 Section extraction, mixed wiki and html (section 1)
@@ -18513,7 +18493,7 @@ two
 !! end
 
 
-# Formerly testing for bug 3342
+# Formerly testing for T5342
 !! test
 Section extraction, heading surrounded by <noinclude>
 !! options
@@ -18525,7 +18505,7 @@ section=1
 ==marked==
 !!end
 
-# Test behavior of bug 19910
+# Test behavior of T21910
 !! test
 Sectiion with all-equals
 !! options
@@ -18873,7 +18853,7 @@ xxx
 !! end
 
 !! test
-Section replacement test with initial whitespace (bug 13728)
+Section replacement test with initial whitespace (T15728)
 !! options
 replace=2,"xxx"
 !! wikitext
@@ -18888,7 +18868,7 @@ xxx
 
 
 !! test
-Section extraction, heading followed by pre with 20 spaces (bug 6398)
+Section extraction, heading followed by pre with 20 spaces (T8398)
 !! options
 section=1
 !! wikitext
@@ -18900,7 +18880,7 @@ section=1
 !! end
 
 !! test
-Section extraction, heading followed by pre with 19 spaces (bug 6398 sanity check)
+Section extraction, heading followed by pre with 19 spaces (T8398 sanity check)
 !! options
 section=1
 !! wikitext
@@ -18913,7 +18893,7 @@ section=1
 
 
 !! test
-Section extraction, <pre> around bogus header (bug 10309)
+Section extraction, <pre> around bogus header (T12309)
 !! options
 section=2
 !! wikitext
@@ -18930,7 +18910,7 @@ stuff
 !! end
 
 !! test
-Section replacement, <pre> around bogus header (bug 10309)
+Section replacement, <pre> around bogus header (T12309)
 !! options
 replace=2,"xxx"
 !! wikitext
@@ -19649,7 +19629,7 @@ parsoid=wt2html,wt2wt,html2html
 !! end
 
 !! test
-HTML Hex character encoding bogus encoding (bug 26437 regression check)
+HTML Hex character encoding bogus encoding (T28437 regression check)
 !! wikitext
 &#xsee;&#XSEE;
 !! html/php
@@ -19788,7 +19768,7 @@ ISBN 1234567890
 !! end
 
 !! test
-Bug 22905: <abbr> followed by ISBN followed by </a>
+T24905: <abbr> followed by ISBN followed by </a>
 !! wikitext
 <abbr>(fr)</abbr> ISBN 2753300917 [http://www.example.com example.com]
 !! html/php
@@ -20223,7 +20203,7 @@ ISBN 12345678901
 
 
 !! test
-ISBN with trailing year (bug 8110)
+ISBN with trailing year (T9110)
 !! wikitext
 ISBN 1-234-56789-0 - 2006
 
@@ -20272,7 +20252,7 @@ anchorencode deals with templates
 !! end
 
 !! test
-anchorencode encodes like the TOC generator: (bug 18431)
+anchorencode encodes like the TOC generator: (T20431)
 !! wikitext
 === _ +:.3A%3A&&amp;]] ===
 {{anchorencode: _ +:.3A%3A&&amp;]] }}
@@ -20284,7 +20264,7 @@ __NOEDITSECTION__
 !! end
 
 !! test
-Bug 6200: blockquotes and paragraph formatting
+T8200: blockquotes and paragraph formatting
 !! wikitext
 <blockquote>
 foo
@@ -20305,7 +20285,7 @@ bar
 !! end
 
 !! test
-Bug 8293: Use of center tag ruins paragraph formatting
+T10293: Use of center tag ruins paragraph formatting
 !! wikitext
 <center>
 foo
@@ -20467,7 +20447,7 @@ blah
 ## This wikitext usage is going to be fairly uncommon in production and
 ## selser will take care of preserving formatting in those scenarios.
 !! test
-Don't convert blue categorylinks to another variant (bug 33210)
+Don't convert blue categorylinks to another variant (T35210)
 !! options
 cat
 language=zh
@@ -20636,7 +20616,7 @@ Should be stripped<span title="Exclamation">!</span>
 !! end
 
 !! test
-Bug 24072: more test on conversion rule for title
+T26072: more test on conversion rule for title
 !! options
 language=zh variant=zh-tw showtitle
 !! wikitext
@@ -20750,9 +20730,6 @@ Nested: -{zh-hans:Hi -{zh-cn:China;zh-sg:Singapore;}-;zh-hant:Hello -{zh-tw:Taiw
 </p>
 !! end
 
-# Since Parsoid is starting to emit canonical wikitext for links,
-# [http://example.com http://example.com] will not RT back to that
-# form anymore.
 !! test
 HTML markups with conversion syntax in attribs, nested in other conversion blocks
 !! options
@@ -20775,6 +20752,9 @@ language=zh variant=zh-cn disabled
 </p>
 !! end
 
+# Since Parsoid is starting to emit canonical wikitext for links,
+# [http://example.com http://example.com] will not RT back to that
+# form anymore.
 !! test
 Proper conversion of text in external links
 !! options
@@ -21002,7 +20982,7 @@ language=sr variant=sr-ec
 !! end
 
 !! test
-Bug 529: Uncovered bullet
+T2529: Uncovered bullet
 !! wikitext
 * Foo {{bullet}}
 !! html
@@ -21018,7 +20998,7 @@ Bug 529: Uncovered bullet
 # To test realistic parsing behavior, apply a tidy-like transformation to both
 # the expected output and your parser's output.
 !! test
-Bug 529: Uncovered bullet leaving empty list, normally removed by tidy
+T2529: Uncovered bullet leaving empty list, normally removed by tidy
 !! wikitext
 ******* Foo {{bullet}}
 !! html
@@ -21028,7 +21008,7 @@ Bug 529: Uncovered bullet leaving empty list, normally removed by tidy
 !! end
 
 !! test
-Bug 529: Uncovered table already at line-start
+T2529: Uncovered table already at line-start
 !! wikitext
 x
 
 !! end
 
 !! test
-Bug 529: Uncovered bullet in parser function result
+T2529: Uncovered bullet in parser function result
 !! wikitext
 * Foo {{lc:{{bullet}} }}
 !! html
@@ -21061,7 +21041,7 @@ Bug 529: Uncovered bullet in parser function result
 !! end
 
 !! test
-Bug 5678: Double-parsed template argument
+T7678: Double-parsed template argument
 !! wikitext
 {{lc:{{{1}}}|hello}}
 !! html
@@ -21070,7 +21050,7 @@ Bug 5678: Double-parsed template argument
 !! end
 
 !! test
-Bug 5678: Double-parsed template invocation
+T7678: Double-parsed template invocation
 !! wikitext
 {{lc:{{paramtest {{!}} param = hello }} }}
 !! html
@@ -21079,7 +21059,7 @@ Bug 5678: Double-parsed template invocation
 !! end
 
 !! test
-Case insensitivity of parser functions for non-ASCII characters (bug 8143)
+Case insensitivity of parser functions for non-ASCII characters (T10143)
 !! options
 language=cs
 title=[[Main Page]]
@@ -21224,9 +21204,9 @@ B</strong>
 </p>
 !! end
 
-# Bug 6200: <blockquote> should behave like <div> with respect to line breaks
+# T8200: <blockquote> should behave like <div> with respect to line breaks
 !! test
-Bug 6200: paragraphs inside blockquotes (no extra line breaks)
+T8200: paragraphs inside blockquotes (no extra line breaks)
 !! wikitext
 <blockquote>Line one
 
@@ -21242,7 +21222,7 @@ Line two</blockquote>
 !! end
 
 !! test
-Bug 6200: paragraphs inside blockquotes (extra line break on open)
+T8200: paragraphs inside blockquotes (extra line break on open)
 !! wikitext
 <blockquote>
 Line one
@@ -21261,7 +21241,7 @@ Line two</blockquote>
 !! end
 
 !! test
-Bug 6200: paragraphs inside blockquotes (extra line break on close)
+T8200: paragraphs inside blockquotes (extra line break on close)
 !! wikitext
 <blockquote>Line one
 
@@ -21281,7 +21261,7 @@ Line two
 !! end
 
 !! test
-Bug 6200: paragraphs inside blockquotes (extra line break on open and close)
+T8200: paragraphs inside blockquotes (extra line break on open and close)
 !! wikitext
 <blockquote>
 Line one
@@ -21386,7 +21366,7 @@ Free external link invading image caption
 !! end
 
 !! test
-Bug 15196: localised external link numbers
+T17196: localised external link numbers
 !! options
 language=fa
 !! wikitext
@@ -21523,7 +21503,7 @@ comment local title=[[Main Page]]
 !!end
 
 !! test
-Edit comment with subpage link (bug 14080)
+Edit comment with subpage link (T16080)
 !! options
 comment
 subpage
@@ -21535,7 +21515,7 @@ Poked at a <a href="/wiki/Subpage_test/subpage" title="Subpage test/subpage">/su
 !!end
 
 !! test
-Edit comment with subpage link and link text (bug 14080)
+Edit comment with subpage link and link text (T16080)
 !! options
 comment
 subpage
@@ -21547,7 +21527,7 @@ Poked at a <a href="/wiki/Subpage_test/subpage" title="Subpage test/subpage">nea
 !!end
 
 !! test
-Edit comment with bogus subpage link in non-subpage NS (bug 14080)
+Edit comment with bogus subpage link in non-subpage NS (T16080)
 !! options
 comment
 title=[[Subpage test]]
@@ -21623,7 +21603,7 @@ Created page with &quot;&lt;noinclude&gt;<a href="/index.php?title=Category:Requ
 !! end
 
 !! test
-Space normalisation on autocomment (bug 22784)
+Space normalisation on autocomment (T24784)
 !! options
 comment
 title=[[Main Page]]
@@ -21634,7 +21614,7 @@ title=[[Main Page]]
 !! end
 
 !! test
-percent-encoding and + signs in comments (Bug 26410)
+percent-encoding and + signs in comments (T28410)
 !! options
 comment
 !! wikitext
@@ -21643,7 +21623,7 @@ comment
 <a href="/index.php?title=ABC3D%25_%2B%2B&amp;action=edit&amp;redlink=1" class="new" title="ABC3D% ++ (page does not exist)">ABC3D% ++</a> <a href="/index.php?title=ABC3D%25_%2B%2B&amp;action=edit&amp;redlink=1" class="new" title="ABC3D% ++ (page does not exist)">+%20</a>
 !! end
 
-# Parsoid doesn't support this yet: see bug 73581
+# Parsoid doesn't support this yet: see T75581
 # but it *should* omit the 'src' attribute if the image is bad.
 # PHP side of tests was disabled in
 # mediawiki/core:6bd31e7d95161a6e88fa86df60871051da997c3c
@@ -21659,7 +21639,7 @@ Bad images - basic functionality
 !! end
 
 !! test
-Bad images - bug 16039: text after bad image disappears
+Bad images - T18039: text after bad image disappears
 !! wikitext
 Foo bar
 [[File:Bad.jpg]]
@@ -21675,7 +21655,7 @@ Bar foo</p>
 !! end
 
 !! test
-Verify that displaytitle works (bug #22501) no displaytitle
+Verify that displaytitle works (T24501) no displaytitle
 !! options
 showtitle
 !! config
@@ -21690,7 +21670,7 @@ Parser test
 !! end
 
 !! test
-Verify that displaytitle works (bug #22501) RestrictDisplayTitle=false
+Verify that displaytitle works (T24501) RestrictDisplayTitle=false
 !! options
 showtitle
 title=[[Screen]]
@@ -21707,7 +21687,7 @@ whatever
 !! end
 
 !! test
-Verify that displaytitle works (bug #22501) RestrictDisplayTitle=true mismatch
+Verify that displaytitle works (T24501) RestrictDisplayTitle=true mismatch
 !! options
 showtitle
 title=[[Screen]]
@@ -21724,7 +21704,7 @@ Screen
 !! end
 
 !! test
-Verify that displaytitle works (bug #22501) RestrictDisplayTitle=true matching
+Verify that displaytitle works (T24501) RestrictDisplayTitle=true matching
 !! options
 showtitle
 title=[[Screen]]
@@ -21741,7 +21721,7 @@ screen
 !! end
 
 !! test
-Verify that displaytitle works (bug #22501) AllowDisplayTitle=false
+Verify that displaytitle works (T24501) AllowDisplayTitle=false
 !! options
 showtitle
 title=[[Screen]]
@@ -21758,7 +21738,7 @@ Screen
 !! end
 
 !! test
-Verify that displaytitle works (bug #22501) AllowDisplayTitle=false no DISPLAYTITLE
+Verify that displaytitle works (T24501) AllowDisplayTitle=false no DISPLAYTITLE
 !! options
 showtitle
 title=[[Screen]]
@@ -21773,7 +21753,7 @@ Screen
 !! end
 
 !! test
-Verify that displaytitle handles inline CSS styles (bug 26547) - rejected value
+Verify that displaytitle handles inline CSS styles (T28547) - rejected value
 !! options
 showtitle
 title=[[Screen]]
@@ -21790,7 +21770,7 @@ this is not the the title
 !! end
 
 !! test
-Verify that displaytitle handles inline CSS styles (bug 26547) - accepted value
+Verify that displaytitle handles inline CSS styles (T28547) - accepted value
 !! options
 showtitle
 title=[[Screen]]
@@ -21923,7 +21903,7 @@ preload
 !! end
 
 !! test
-Play a bit with r67090 and bug 3158
+Play a bit with r67090 and T5158
 !! wikitext
 <div style="width:50% !important">&nbsp;</div>
 <div style="width:50%&nbsp;!important">&nbsp;</div>
@@ -21970,7 +21950,7 @@ Strip reserved data attributes
 !! end
 
 !! test
-percent-encoding and + signs in internal links (Bug 26410)
+percent-encoding and + signs in internal links (T28410)
 !! wikitext
 [[User:+%]] [[Page+title%]]
 [[%+]] [[%+|%20]] [[%+ ]] [[%+r]]
@@ -21990,7 +21970,7 @@ percent-encoding and + signs in internal links (Bug 26410)
 !! end
 
 !! test
-Special characters in embedded file links (bug 27679)
+Special characters in embedded file links (T29679)
 !! wikitext
 [[File:Contains & ampersand.jpg]]
 [[File:Does not exist.jpg|Title with & ampersand]]
@@ -22013,7 +21993,7 @@ Text&apos;s been normalized?
 !! end
 
 !! test
-Bug 19052 U+3000 IDEOGRAPHIC SPACE should terminate free external links
+T21052 U+3000 IDEOGRAPHIC SPACE should terminate free external links
 !! wikitext
 http://www.example.org/ <-- U+3000 (vim: ^Vu3000)
 !! html
@@ -22022,7 +22002,7 @@ http://www.example.org/ <-- U+3000 (vim: ^Vu3000)
 !! end
 
 !! test
-Bug 19052 U+3000 IDEOGRAPHIC SPACE should terminate bracketed external links
+T21052 U+3000 IDEOGRAPHIC SPACE should terminate bracketed external links
 !! wikitext
 [http://www.example.org/ ideograms]
 !! html
@@ -22031,7 +22011,7 @@ Bug 19052 U+3000 IDEOGRAPHIC SPACE should terminate bracketed external links
 !! end
 
 !! test
-Bug 19052 U+3000 IDEOGRAPHIC SPACE should terminate external images links
+T21052 U+3000 IDEOGRAPHIC SPACE should terminate external images links
 !! wikitext
 http://www.example.org/pic.png <-- U+3000 (vim: ^Vu3000)
 !! html
@@ -22059,7 +22039,7 @@ Template:Identical
 !! endarticle
 
 !! test
-Bug 31098 Template which includes system messages which includes the template
+T33098 Template which includes system messages which includes the template
 !! wikitext
 {{Identical}}
 !! html
@@ -22069,7 +22049,7 @@ Bug 31098 Template which includes system messages which includes the template
 !! end
 
 !! test
-Bug31490 Turkish: ucfirst 'blah'
+T33490 Turkish: ucfirst 'blah'
 !! options
 language=tr
 !! wikitext
@@ -22080,7 +22060,7 @@ language=tr
 !! end
 
 !! test
-Bug31490 Turkish: ucfirst 'ix'
+T33490 Turkish: ucfirst 'ix'
 !! options
 language=tr
 !! wikitext
@@ -22091,7 +22071,7 @@ language=tr
 !! end
 
 !! test
-Bug31490 Turkish: lcfirst 'BLAH'
+T33490 Turkish: lcfirst 'BLAH'
 !! options
 language=tr
 !! wikitext
@@ -22102,7 +22082,7 @@ language=tr
 !! end
 
 !! test
-Bug31490 Turkish: ucfırst (with a dotless i)
+T33490 Turkish: ucfırst (with a dotless i)
 !! options
 language=tr
 !! wikitext
@@ -22113,7 +22093,7 @@ language=tr
 !! end
 
 !! test
-Bug31490 ucfırst (with a dotless i) with English language
+T33490 ucfırst (with a dotless i) with English language
 !! options
 language=en
 !! wikitext
@@ -22124,7 +22104,7 @@ language=en
 !! end
 
 !! test
-Bug 26375: TOC with italics
+T28375: TOC with italics
 !! options
 title=[[Main Page]]
 !! wikitext
@@ -22142,7 +22122,7 @@ __TOC__
 !! end
 
 !! test
-Bug 26375: TOC with bold
+T28375: TOC with bold
 !! options
 title=[[Main Page]]
 !! wikitext
@@ -22160,7 +22140,7 @@ __TOC__
 !! end
 
 !! test
-Bug 33845: Headings become cursive in TOC when they contain an image
+T35845: Headings become cursive in TOC when they contain an image
 !! options
 title=[[Main Page]]
 !! wikitext
@@ -22178,7 +22158,7 @@ __TOC__
 !! end
 
 !! test
-Bug 33845 (2): Headings become bold in TOC when they contain a blockquote
+T35845 (2): Headings become bold in TOC when they contain a blockquote
 !! options
 title=[[Main Page]]
 !! wikitext
@@ -22333,7 +22313,7 @@ __TOC__
 !! end
 
 !! test
-Bug 72884: bdi element in ToC
+T74884: bdi element in ToC
 !! wikitext
 __TOC__
 == <bdi>test</bdi> ==
@@ -22396,17 +22376,17 @@ __TOC__
 !! end
 
 !! article
-MediaWiki:Bug32057
+MediaWiki:T34057
 !! text
 == {{int:headline_sample}} ==
 !! endarticle
 
 !! test
-Bug 32057: Title needed when expanding <h> nodes.
+T34057: Title needed when expanding <h> nodes.
 !! options
 title=[[Main Page]]
 !! wikitext
-{{int:Bug32057}}
+{{int:T34057}}
 !! html
 <h2><span class="mw-headline" id="Headline_text">Headline text</span><span class="mw-editsection"><span class="mw-editsection-bracket">[</span><a href="/index.php?title=Main_Page&amp;action=edit&amp;section=1" title="Edit section: Headline text">edit</a><span class="mw-editsection-bracket">]</span></span></h2>
 
@@ -22470,7 +22450,7 @@ language=be-tarask
 !! end
 
 !! test
-Wrong option for formatNum (bug 56199)
+Wrong option for formatNum (T58199)
 !! wikitext
 {{formatnum:1,234.56|Random}}
 {{formatnum:1,234.56|EVERYTHING}}
@@ -22521,7 +22501,7 @@ Strip marker in anchorencode
 !! end
 
 !! test
-nowiki inside link inside heading (bug 18295)
+nowiki inside link inside heading (T20295)
 !! wikitext
 ==[[foo|x<nowiki>y</nowiki>z]]==
 !! html
@@ -22530,7 +22510,7 @@ nowiki inside link inside heading (bug 18295)
 !! end
 
 !! test
-new support for bdi element (bug 31817)
+new support for bdi element (T33817)
 !! wikitext
 <p dir="rtl" lang="he">ולדימיר לנין (ברוסית: <bdi lang="ru">Владимир Ленин</bdi>, 24 באפריל 1870–22 בינואר 1924) הוא מנהיג פוליטי קומוניסטי רוסי.</p>
 !! html
@@ -22557,25 +22537,6 @@ Ignore pipe between table row attributes
 
 !! end
 
-!!test
-Gallery override link with WikiLink (bug 34852)
-!! wikitext
-<gallery>
-File:foobar.jpg|caption|alt=galleryalt|link=InterWikiLink
-</gallery>
-!! html
-<ul class="gallery mw-gallery-traditional">
-               <li class="gallerybox" style="width: 155px"><div style="width: 155px">
-                       <div class="thumb" style="width: 150px;"><div style="margin:68px auto;"><a href="/wiki/InterWikiLink"><img alt="galleryalt" src="http://example.com/images/thumb/3/3a/Foobar.jpg/120px-Foobar.jpg" width="120" height="14" srcset="http://example.com/images/thumb/3/3a/Foobar.jpg/180px-Foobar.jpg 1.5x, http://example.com/images/thumb/3/3a/Foobar.jpg/240px-Foobar.jpg 2x" /></a></div></div>
-                       <div class="gallerytext">
-<p>caption
-</p>
-                       </div>
-               </div></li>
-</ul>
-
-!! end
-
 !!test
 Language parser function
 !! wikitext
@@ -22610,7 +22571,7 @@ Special:Foobar
 !! end
 
 !!test
-Bug 34939 - Case insensitive link parsing ([HttP://])
+T36939 - Case insensitive link parsing ([HttP://])
 !! wikitext
 [HttP://MediaWiki.Org/]
 !! html/php
@@ -22621,7 +22582,7 @@ Bug 34939 - Case insensitive link parsing ([HttP://])
 !! end
 
 !!test
-Bug 34939 - Case insensitive link parsing ([HttP:// title])
+T36939 - Case insensitive link parsing ([HttP:// title])
 !! wikitext
 [HttP://MediaWiki.Org/ MediaWiki]
 !! html
@@ -22630,7 +22591,7 @@ Bug 34939 - Case insensitive link parsing ([HttP:// title])
 !! end
 
 !!test
-Bug 34939 - Case insensitive link parsing (HttP://)
+T36939 - Case insensitive link parsing (HttP://)
 !! wikitext
 HttP://MediaWiki.Org/
 !! html/php
@@ -22692,7 +22653,7 @@ parsoid=wt2html,wt2wt
 #### Parsoid-specific functionality tests
 #### -----------------------------------------------------------------
 
-# Bug 63642/66749: Formatting elt fixup around images is cleaned up.
+# T65642/T68749: Formatting elt fixup around images is cleaned up.
 # We know wt2wt will fail, but we expect selser to pass.
 # Due to the nature of our testing, wt2wt and selser tests will enter the
 # blacklist and we'll catch selser regressions based on changes to the
@@ -22758,573 +22719,6 @@ parsoid=wt2html,wt2wt
 <p></p>
 !! end
 
-#### ----------------------------------------------------------------
-#### Parsoid-only testing of Parsoid's impl of <ref> and <references>
-#### tags. Parsoid's output for these tags differs from that of the
-#### PHP parser.
-#### ----------------------------------------------------------------
-
-!!test
-Ref: 1. ref-location should be replaced with an index span
-!! wikitext
-A <ref>foo</ref>
-B <ref name="x">foo</ref>
-C <ref name="y" />
-<references />
-!! html/parsoid
-<p>A <span about="#mwt2" class="mw-ref" id="cite_ref-1" rel="dc:references" typeof="mw:Extension/ref" data-mw='{"name":"ref","body":{"id":"mw-reference-text-cite_note-1"},"attrs":{}}'><a href="./Main_Page#cite_note-1"><span class="mw-reflink-text">[1]</span></a></span>
-B <span about="#mwt4" class="mw-ref" id="cite_ref-x_2-0" rel="dc:references" typeof="mw:Extension/ref" data-mw='{"name":"ref","body":{"id":"mw-reference-text-cite_note-x-2"},"attrs":{"name":"x"}}'><a href="./Main_Page#cite_note-x-2"><span class="mw-reflink-text">[2]</span></a></span>
-C <span about="#mwt6" class="mw-ref" id="cite_ref-y_3-0" rel="dc:references" typeof="mw:Extension/ref" data-mw='{"name":"ref","attrs":{"name":"y"}}'><a href="./Main_Page#cite_note-y-3"><span class="mw-reflink-text">[3]</span></a></span></p>
-<ol class="mw-references" typeof="mw:Extension/references" about="#mwt8" data-mw='{"name":"references","attrs":{}}'>
-<li about="#cite_note-1" id="cite_note-1"><a href="./Main_Page#cite_ref-1" rel="mw:referencedBy"><span class="mw-linkback-text">↑ </span></a> <span id="mw-reference-text-cite_note-1" class="mw-reference-text">foo</span></li>
-<li about="#cite_note-x-2" id="cite_note-x-2"><a href="./Main_Page#cite_ref-x_2-0" rel="mw:referencedBy"><span class="mw-linkback-text">↑ </span></a> <span id="mw-reference-text-cite_note-x-2" class="mw-reference-text">foo</span></li>
-<li about="#cite_note-y-3" id="cite_note-y-3"><a href="./Main_Page#cite_ref-y_3-0" rel="mw:referencedBy"><span class="mw-linkback-text">↑ </span></a> <span id="mw-reference-text-cite_note-y-3" class="mw-reference-text"></span></li>
-</ol>
-!!end
-
-!!test
-Ref: 2. ref-tags with identical names should all get the same index
-!! wikitext
-A <ref name="x">foo</ref>
-B <ref name="x" />
-<references />
-!! html/parsoid
-<p>A <span about="#mwt2" class="mw-ref" id="cite_ref-x_1-0" rel="dc:references" typeof="mw:Extension/ref" data-mw='{"name":"ref","body":{"id":"mw-reference-text-cite_note-x-1"},"attrs":{"name":"x"}}'><a href="./Main_Page#cite_note-x-1"><span class="mw-reflink-text">[1]</span></a></span>
-B <span about="#mwt4" class="mw-ref" id="cite_ref-x_1-1" rel="dc:references" typeof="mw:Extension/ref" data-mw='{"name":"ref","attrs":{"name":"x"}}'><a href="./Main_Page#cite_note-x-1"><span class="mw-reflink-text">[1]</span></a></span></p>
-<ol class="mw-references" typeof="mw:Extension/references" about="#mwt6" data-mw='{"name":"references","attrs":{}}'>
-<li about="#cite_note-x-1" id="cite_note-x-1"><span rel="mw:referencedBy"><a href="./Main_Page#cite_ref-x_1-0"><span class="mw-linkback-text">1 </span></a><a href="./Main_Page#cite_ref-x_1-1"><span class="mw-linkback-text">2 </span></a></span> <span id="mw-reference-text-cite_note-x-1" class="mw-reference-text">foo</span></li>
-</ol>
-!!end
-
-!!test
-Ref: 3. spaces in ref-names should be ignored
-!! wikitext
-A <ref name="x">foo</ref>
-B <ref name=" x " />
-C <ref name= x  />
-<references />
-!! html/parsoid
-<p>A <span about="#mwt2" class="mw-ref" id="cite_ref-x_1-0" rel="dc:references" typeof="mw:Extension/ref" data-mw='{"name":"ref","body":{"id":"mw-reference-text-cite_note-x-1"},"attrs":{"name":"x"}}'><a href="./Main_Page#cite_note-x-1"><span class="mw-reflink-text">[1]</span></a></span>
-B <span about="#mwt4" class="mw-ref" id="cite_ref-x_1-1" rel="dc:references" typeof="mw:Extension/ref" data-mw='{"name":"ref","attrs":{"name":"x"}}'><a href="./Main_Page#cite_note-x-1"><span class="mw-reflink-text">[1]</span></a></span>
-C <span about="#mwt6" class="mw-ref" id="cite_ref-x_1-2" rel="dc:references" typeof="mw:Extension/ref" data-mw='{"name":"ref","attrs":{"name":"x"}}'><a href="./Main_Page#cite_note-x-1"><span class="mw-reflink-text">[1]</span></a></span></p>
-<ol class="mw-references" typeof="mw:Extension/references" about="#mwt8" data-mw='{"name":"references","attrs":{}}'>
-<li about="#cite_note-x-1" id="cite_note-x-1"><span rel="mw:referencedBy"><a href="./Main_Page#cite_ref-x_1-0"><span class="mw-linkback-text">1 </span></a><a href="./Main_Page#cite_ref-x_1-1"><span class="mw-linkback-text">2 </span></a><a href="./Main_Page#cite_ref-x_1-2"><span class="mw-linkback-text">3 </span></a></span> <span id="mw-reference-text-cite_note-x-1" class="mw-reference-text">foo</span></li>
-</ol>
-!!end
-
-# NOTE: constructor is a predefined property in JS and constructor as a ref-name can clash with it if not handled properly)
-!!test
-Ref: 4. 'constructor' should be accepted as a valid ref-name
-!! wikitext
-A <ref name="constructor">foo</ref>
-<references />
-!! html/parsoid
-<p>A <span about="#mwt2" class="mw-ref" id="cite_ref-constructor_1-0" rel="dc:references" typeof="mw:Extension/ref" data-mw='{"name":"ref","body":{"id":"mw-reference-text-cite_note-constructor-1"},"attrs":{"name":"constructor"}}'><a href="./Main_Page#cite_note-constructor-1"><span class="mw-reflink-text">[1]</span></a></span></p>
-<ol class="mw-references" typeof="mw:Extension/references" about="#mwt4" data-mw='{"name":"references","attrs":{}}'>
-<li about="#cite_note-constructor-1" id="cite_note-constructor-1"><a href="./Main_Page#cite_ref-constructor_1-0" rel="mw:referencedBy"><span class="mw-linkback-text">↑ </span></a> <span id="mw-reference-text-cite_note-constructor-1" class="mw-reference-text">foo</span></li>
-</ol>
-!!end
-
-!!test
-Ref: 5. body should accept generic wikitext
-!! wikitext
-A <ref>
- This is a '''[[bolded link]]''' and this is a {{echo|transclusion}}
-</ref>
-
-<references />
-!! html/parsoid
-<p>A <span about="#mwt2" class="mw-ref" id="cite_ref-1" rel="dc:references" typeof="mw:Extension/ref" data-mw='{"name":"ref","body":{"id":"mw-reference-text-cite_note-1"},"attrs":{}}'><a href="./Main_Page#cite_note-1"><span class="mw-reflink-text">[1]</span></a></span></p>
-
-<ol class="mw-references" typeof="mw:Extension/references" about="#mwt5" data-mw='{"name":"references","attrs":{}}'>
-<li about="#cite_note-1" id="cite_note-1"><a href="./Main_Page#cite_ref-1" rel="mw:referencedBy"><span class="mw-linkback-text">↑ </span></a> <span id="mw-reference-text-cite_note-1" class="mw-reference-text">This is a <b><a rel="mw:WikiLink" href="./Bolded_link" title="Bolded link">bolded link</a></b> and this is a <span about="#mwt3" typeof="mw:Transclusion" data-mw='{"parts":[{"template":{"target":{"wt":"echo","href":"./Template:Echo"},"params":{"1":{"wt":"transclusion"}},"i":0}}]}'>transclusion</span>
-</span></li>
-</ol>
-!!end
-
-!!test
-Ref: 6. indent-pres should not be output in ref-body
-!! wikitext
-A <ref>
- foo
- bar
- baz
-</ref>
-
-<references />
-!! html/parsoid
-<p>A <span about="#mwt2" class="mw-ref" id="cite_ref-1" rel="dc:references" typeof="mw:Extension/ref" data-mw='{"name":"ref","body":{"id":"mw-reference-text-cite_note-1"},"attrs":{}}'><a href="./Main_Page#cite_note-1"><span class="mw-reflink-text">[1]</span></a></span></p>
-
-<ol class="mw-references" typeof="mw:Extension/references" about="#mwt4" data-mw='{"name":"references","attrs":{}}'>
-<li about="#cite_note-1" id="cite_note-1"><a href="./Main_Page#cite_ref-1" rel="mw:referencedBy"><span class="mw-linkback-text">↑ </span></a> <span id="mw-reference-text-cite_note-1" class="mw-reference-text">foo
- bar
- baz
-</span></li>
-</ol>
-!!end
-
-!!test
-Ref: 7. No p-wrapping in ref-body
-!! wikitext
-A <ref>
-foo
-
-bar
-
-
-baz
-
-
-
-booz
-</ref>
-
-<references />
-!! html/parsoid
-<p>A <span about="#mwt2" class="mw-ref" id="cite_ref-1" rel="dc:references" typeof="mw:Extension/ref" data-mw='{"name":"ref","body":{"id":"mw-reference-text-cite_note-1"},"attrs":{}}'><a href="./Main_Page#cite_note-1"><span class="mw-reflink-text">[1]</span></a></span></p>
-
-<ol class="mw-references" typeof="mw:Extension/references" about="#mwt4" data-mw='{"name":"references","attrs":{}}'>
-<li about="#cite_note-1" id="cite_note-1"><a href="./Main_Page#cite_ref-1" rel="mw:referencedBy"><span class="mw-linkback-text">↑ </span></a> <span id="mw-reference-text-cite_note-1" class="mw-reference-text">foo
-
-bar
-
-
-baz
-
-
-
-booz
-</span></li>
-</ol>
-!!end
-
-!!test
-Ref: 8. transclusion wikitext has lower precedence
-!! wikitext
-A <ref> foo {{echo|</ref> B C}}
-
-<references />
-!! html/parsoid
-<p>A <span about="#mwt2" class="mw-ref" id="cite_ref-1" rel="dc:references" typeof="mw:Extension/ref" data-mw='{"name":"ref","body":{"id":"mw-reference-text-cite_note-1"},"attrs":{}}'><a href="./Main_Page#cite_note-1"><span class="mw-reflink-text">[1]</span></a></span> B C}}</p>
-<ol class="mw-references" typeof="mw:Extension/references" about="#mwt4" data-mw='{"name":"references","attrs":{}}'>
-<li about="#cite_note-1" id="cite_note-1"><a href="./Main_Page#cite_ref-1" rel="mw:referencedBy"><span class="mw-linkback-text">↑ </span></a> <span id="mw-reference-text-cite_note-1" class="mw-reference-text">foo {{echo|</span></li>
-</ol>
-!!end
-
-!!test
-Ref: 9. unclosed comments should not leak out of ref-body
-!! wikitext
-A <ref> foo <!--</ref> B C
-<references />
-!! html/parsoid
-<p>A <span about="#mwt2" class="mw-ref" id="cite_ref-1" rel="dc:references" typeof="mw:Extension/ref" data-mw='{"name":"ref","body":{"id":"mw-reference-text-cite_note-1"},"attrs":{}}'><a href="./Main_Page#cite_note-1"><span class="mw-reflink-text">[1]</span></a></span> B C</p>
-<ol class="mw-references" typeof="mw:Extension/references" about="#mwt4" data-mw='{"name":"references","attrs":{}}'>
-<li about="#cite_note-1" id="cite_note-1"><a href="./Main_Page#cite_ref-1" rel="mw:referencedBy"><span class="mw-linkback-text">↑ </span></a> <span id="mw-reference-text-cite_note-1" class="mw-reference-text">foo <!----></span></li>
-</ol>
-!!end
-
-!!test
-Ref: 10. Unclosed HTML tags should not leak out of ref-body
-!! wikitext
-A <ref> <b> foo </ref> B C
-
-<references />
-!! html/parsoid
-<p>A <span about="#mwt2" class="mw-ref" id="cite_ref-1" rel="dc:references" typeof="mw:Extension/ref" data-mw='{"name":"ref","body":{"id":"mw-reference-text-cite_note-1"},"attrs":{}}'><a href="./Main_Page#cite_note-1"><span class="mw-reflink-text">[1]</span></a></span> B C</p>
-
-
-<ol class="mw-references" typeof="mw:Extension/references" about="#mwt4" data-mw='{"name":"references","attrs":{}}'>
-<li about="#cite_note-1" id="cite_note-1"><a href="./Main_Page#cite_ref-1" rel="mw:referencedBy"><span class="mw-linkback-text">↑ </span></a> <span id="mw-reference-text-cite_note-1" class="mw-reference-text"><b data-parsoid='{"stx":"html","autoInsertedEnd":true}'> foo </b></span></li>
-</ol>
-!!end
-
-!!test
-Ref: 11. ref-tags acts like an inline element wrt P-wrapping
-!! wikitext
-A <ref>foo</ref> B
-C <ref>bar</ref> D
-<references />
-!! html/parsoid
-<p>A <span about="#mwt2" class="mw-ref" id="cite_ref-1" rel="dc:references" typeof="mw:Extension/ref" data-mw='{"name":"ref","body":{"id":"mw-reference-text-cite_note-1"},"attrs":{}}'><a href="./Main_Page#cite_note-1"><span class="mw-reflink-text">[1]</span></a></span> B
-C <span about="#mwt4" class="mw-ref" id="cite_ref-2" rel="dc:references" typeof="mw:Extension/ref" data-mw='{"name":"ref","body":{"id":"mw-reference-text-cite_note-2"},"attrs":{}}'><a href="./Main_Page#cite_note-2"><span class="mw-reflink-text">[2]</span></a></span> D</p>
-<ol class="mw-references" typeof="mw:Extension/references" about="#mwt6" data-mw='{"name":"references","attrs":{}}'>
-<li about="#cite_note-1" id="cite_note-1"><a href="./Main_Page#cite_ref-1" rel="mw:referencedBy"><span class="mw-linkback-text">↑ </span></a> <span id="mw-reference-text-cite_note-1" class="mw-reference-text">foo</span></li>
-<li about="#cite_note-2" id="cite_note-2"><a href="./Main_Page#cite_ref-2" rel="mw:referencedBy"><span class="mw-linkback-text">↑ </span></a> <span id="mw-reference-text-cite_note-2" class="mw-reference-text">bar</span></li>
-</ol>
-!!end
-
-!!test
-Ref: 12. ref-tags act as trailing newline migration barrier
-!! wikitext
-<!--the newline at the end of this line moves out of the p tag-->a
-
-b<!--the newline at the end of this line stays inside the p tag--> <ref />
-<ref />
-
-c
-<references />
-!! html/parsoid
-<!--the newline at the end of this line moves out of the p tag--><p>a</p>
-
-
-<p>b<!--the newline at the end of this line stays inside the p tag--> <span about="#mwt2" class="mw-ref" id="cite_ref-1" rel="dc:references" typeof="mw:Extension/ref" data-mw='{"name":"ref","attrs":{}}'><a href="./Main_Page#cite_note-1"><span class="mw-reflink-text">[1]</span></a></span>
-<span about="#mwt4" class="mw-ref" id="cite_ref-2" rel="dc:references" typeof="mw:Extension/ref" data-mw='{"name":"ref","attrs":{}}'><a href="./Main_Page#cite_note-2"><span class="mw-reflink-text">[2]</span></a></span></p>
-
-<p>c</p>
-<ol class="mw-references" typeof="mw:Extension/references" about="#mwt6" data-mw='{"name":"references","attrs":{}}'>
-<li about="#cite_note-1" id="cite_note-1"><a href="./Main_Page#cite_ref-1" rel="mw:referencedBy"><span class="mw-linkback-text">↑ </span></a> <span id="mw-reference-text-cite_note-1" class="mw-reference-text"></span></li>
-<li about="#cite_note-2" id="cite_note-2"><a href="./Main_Page#cite_ref-2" rel="mw:referencedBy"><span class="mw-linkback-text">↑ </span></a> <span id="mw-reference-text-cite_note-2" class="mw-reference-text"></span></li></ol>
-!!end
-
-!!test
-Ref: 13. ref-tags are not SOL-transparent and block indent-pres
-!! wikitext
-<ref>foo</ref> A
-<ref>bar
-</ref> B
-<references />
-!! html/parsoid
-<p><span about="#mwt2" class="mw-ref" id="cite_ref-1" rel="dc:references" typeof="mw:Extension/ref" data-mw='{"name":"ref","body":{"id":"mw-reference-text-cite_note-1"},"attrs":{}}'><a href="./Main_Page#cite_note-1"><span class="mw-reflink-text">[1]</span></a></span> A
-<span about="#mwt4" class="mw-ref" id="cite_ref-2" rel="dc:references" typeof="mw:Extension/ref" data-mw='{"name":"ref","body":{"id":"mw-reference-text-cite_note-2"},"attrs":{}}'><a href="./Main_Page#cite_note-2"><span class="mw-reflink-text">[2]</span></a></span> B</p>
-<ol class="mw-references" typeof="mw:Extension/references" about="#mwt6" data-mw='{"name":"references","attrs":{}}'>
-<li about="#cite_note-1" id="cite_note-1"><a href="./Main_Page#cite_ref-1" rel="mw:referencedBy"><span class="mw-linkback-text">↑ </span></a> <span id="mw-reference-text-cite_note-1" class="mw-reference-text">foo</span></li>
-<li about="#cite_note-2" id="cite_note-2"><a href="./Main_Page#cite_ref-2" rel="mw:referencedBy"><span class="mw-linkback-text">↑ </span></a> <span id="mw-reference-text-cite_note-2" class="mw-reference-text">bar
-</span></li>
-</ol>
-!!end
-
-## Roundtripping fails because of nowiki'ing
-!! test
-Ref: 14. A nested ref-tag should be emitted as plain text
-!! options
-parsoid=wt2html
-!! wikitext
-<ref>foo <ref>bar</ref> baz</ref>
-
-<references />
-!! html/parsoid
-<p><span about="#mwt2" class="mw-ref" id="cite_ref-1" rel="dc:references" typeof="mw:Extension/ref" data-mw='{"name":"ref","body":{"id":"mw-reference-text-cite_note-1"},"attrs":{}}'><a href="./Main_Page#cite_note-1" style="counter-reset: mw-Ref 1;"><span class="mw-reflink-text">[1]</span></a></span> baz&lt;/ref></p>
-
-<ol class="mw-references" typeof="mw:Extension/references" about="#mwt4" data-mw='{"name":"references","attrs":{}}'><li about="#cite_note-1" id="cite_note-1"><a href="./Main_Page#cite_ref-1" rel="mw:referencedBy"><span class="mw-linkback-text">↑ </span></a> <span id="mw-reference-text-cite_note-1" class="mw-reference-text" data-parsoid="{}">foo &lt;ref>bar</span></li></ol>
-!! end
-
-!!test
-Ref: 15. ref-tags with identical names should get identical indexes
-!! wikitext
-A1 <ref name="a">foo</ref> A2 <ref name="a" />
-B1 <ref name="b" /> B2 <ref name="b">bar</ref>
-
-<references />
-!! html/parsoid
-<p>A1 <span about="#mwt3" class="mw-ref" id="cite_ref-a_1-0" rel="dc:references" typeof="mw:Extension/ref" data-mw='{"name":"ref","body":{"id":"mw-reference-text-cite_note-a-1"},"attrs":{"name":"a"}}'><a href="./Main_Page#cite_note-a-1"><span class="mw-reflink-text">[1]</span></a></span> A2 <span about="#mwt4" class="mw-ref" id="cite_ref-a_1-1" rel="dc:references" typeof="mw:Extension/ref" data-mw='{"name":"ref","attrs":{"name":"a"}}'><a href="./Main_Page#cite_note-a-1"><span class="mw-reflink-text">[1]</span></a></span>
-B1 <span about="#mwt7" class="mw-ref" id="cite_ref-b_2-0" rel="dc:references" typeof="mw:Extension/ref" data-mw='{"name":"ref","attrs":{"name":"b"}}'><a href="./Main_Page#cite_note-b-2"><span class="mw-reflink-text">[2]</span></a></span> B2 <span about="#mwt8" class="mw-ref" id="cite_ref-b_2-1" rel="dc:references" typeof="mw:Extension/ref" data-mw='{"name":"ref","body":{"id":"mw-reference-text-cite_note-b-2"},"attrs":{"name":"b"}}'><a href="./Main_Page#cite_note-b-2"><span class="mw-reflink-text">[2]</span></a></span></p>
-
-<ol class="mw-references" typeof="mw:Extension/references" about="#mwt10" data-mw='{"name":"references","attrs":{}}'><li about="#cite_note-a-1" id="cite_note-a-1"><span rel="mw:referencedBy"><a href="./Main_Page#cite_ref-a_1-0"><span class="mw-linkback-text">1 </span></a><a href="./Main_Page#cite_ref-a_1-1"><span class="mw-linkback-text">2 </span></a></span> <span id="mw-reference-text-cite_note-a-1" class="mw-reference-text">foo</span></li><li about="#cite_note-b-2" id="cite_note-b-2"><span rel="mw:referencedBy"><a href="./Main_Page#cite_ref-b_2-0"><span class="mw-linkback-text">1 </span></a><a href="./Main_Page#cite_ref-b_2-1"><span class="mw-linkback-text">2 </span></a></span> <span id="mw-reference-text-cite_note-b-2" class="mw-reference-text">bar</span></li>
-</ol>
-!!end
-
-## We don't bother wt2wt-ing non-standard whitespace
-!!test
-Ref: 16. Tokenizer should accept non-standard whitespace in <ref> and </ref> tags
-!!options
-parsoid=wt2html
-!! wikitext
-A <ref >foo</ref >
-
-<references />
-!! html/parsoid
-<p>A <span about="#mwt2" class="mw-ref" id="cite_ref-1" rel="dc:references" typeof="mw:Extension/ref" data-mw='{"name":"ref","body":{"id":"mw-reference-text-cite_note-1"},"attrs":{}}'><a href="./Main_Page#cite_note-1"><span class="mw-reflink-text">[1]</span></a></span></p>
-<ol class="mw-references" typeof="mw:Extension/references" about="#mwt4" data-mw='{"name":"references","attrs":{}}'>
-<li about="#cite_note-1" id="cite_note-1"><a href="./Main_Page#cite_ref-1" rel="mw:referencedBy"><span class="mw-linkback-text">↑ </span></a> <span id="mw-reference-text-cite_note-1" class="mw-reference-text">foo</span></li></ol>
-!!end
-
-!!test
-Ref: 17. Generate valid HTML5 id/about attributes
-!!wikitext
-<ref name="a b">foo</ref>
-<ref name=":0">ve-created name</ref>
-
-<references />
-!!html/parsoid
-<p><span about="#mwt2" class="mw-ref" id="cite_ref-a_b_1-0" rel="dc:references" typeof="mw:Extension/ref" data-mw='{"name":"ref","body":{"id":"mw-reference-text-cite_note-a_b-1"},"attrs":{"name":"a b"}}'><a href="./Main_Page#cite_note-a_b-1" style="counter-reset: mw-Ref 1;"><span class="mw-reflink-text">[1]</span></a></span>
-<span about="#mwt4" class="mw-ref" id="cite_ref-:0_2-0" rel="dc:references" typeof="mw:Extension/ref" data-mw='{"name":"ref","body":{"id":"mw-reference-text-cite_note-:0-2"},"attrs":{"name":":0"}}'><a href="./Main_Page#cite_note-:0-2" style="counter-reset: mw-Ref 2;"><span class="mw-reflink-text">[2]</span></a></span>
-
-<ol class="mw-references" typeof="mw:Extension/references" about="#mwt6" data-mw='{"name":"references","attrs":{}}'><li about="#cite_note-a_b-1" id="cite_note-a_b-1"><a href="./Main_Page#cite_ref-a_b_1-0" rel="mw:referencedBy"><span class="mw-linkback-text">↑ </span></a> <span id="mw-reference-text-cite_note-a_b-1" class="mw-reference-text">foo</span></li><li about="#cite_note-:0-2" id="cite_note-:0-2"><a href="./Main_Page#cite_ref-:0_2-0" rel="mw:referencedBy"><span class="mw-linkback-text">↑ </span></a> <span id="mw-reference-text-cite_note-:0-2" class="mw-reference-text">ve-created name</span></li></ol>
-
-!!end
-
-!!test
-Ref: 18. T58916: Extension attributes should be parsed as plain text
-!!wikitext
-<ref name="{{echo|a}}">foo</ref>
-
-<references />
-!!html/parsoid
-<p><span class="mw-ref" id="cite_ref-.7B.7Becho.7Ca.7D.7D_1-0" rel="dc:references" typeof="mw:Extension/ref" data-mw='{"name":"ref","body":{"id":"mw-reference-text-cite_note-.7B.7Becho.7Ca.7D.7D-1"},"attrs":{"name":"{{echo|a}}"}}'><a href="./Main_Page#cite_note-.7B.7Becho.7Ca.7D.7D-1"><span class="mw-reflink-text">[1]</span></a></span>
-</p>
-
-<ol class="mw-references" typeof="mw:Extension/references" about="#mwt4" data-mw='{"name":"references","attrs":{}}'>
-<li about="#cite_note-.7B.7Becho.7Ca.7D.7D-1" id="cite_note-.7B.7Becho.7Ca.7D.7D-1"><a href="./Main_Page#cite_ref-.7B.7Becho.7Ca.7D.7D_1-0" rel="mw:referencedBy"><span class="mw-linkback-text">↑ </span></a> <span id="mw-reference-text-cite_note-.7B.7Becho.7Ca.7D.7D-1" class="mw-reference-text">foo</span></li>
-</ol>
-!!end
-
-!!test
-Ref: 19. ref-tags with identical name encodings should get identical indexes
-!! wikitext
-1 <ref name="a & b">foo</ref> 2 <ref name="a &amp; b" />
-
-<references />
-!! html/parsoid
-<p>1 <span about="#mwt3" class="mw-ref" id="cite_ref-a_.26_b_1-0" rel="dc:references" typeof="mw:Extension/ref" data-mw='{"name":"ref","body":{"id":"mw-reference-text-cite_note-a_.26_b-1"},"attrs":{"name":"a &amp; b"}}'><a href="./Main_Page#cite_note-a_.26_b-1"><span class="mw-reflink-text">[1]</span></a></span> 2 <span about="#mwt4" class="mw-ref" id="cite_ref-a_.26_b_1-1" rel="dc:references" typeof="mw:Extension/ref" data-mw='{"name":"ref","attrs":{"name":"a &amp;amp; b"}}'><a href="./Main_Page#cite_note-a_.26_b-1"><span class="mw-reflink-text">[1]</span></a></span>
-</p>
-<ol class="mw-references" typeof="mw:Extension/references" about="#mwt6" data-mw='{"name":"references","attrs":{}}'>
-<li about="#cite_note-a_.26_b-1" id="cite_note-a_.26_b-1"><span rel="mw:referencedBy"><a href="./Main_Page#cite_ref-a_.26_b_1-0"><span class="mw-linkback-text">1 </span></a><a href="./Main_Page#cite_ref-a_.26_b_1-1"><span class="mw-linkback-text">2 </span></a></span> <span id="mw-reference-text-cite_note-a_.26_b-1" class="mw-reference-text">foo</span></li>
-</ol>
-!!end
-
-!!test
-Ref: 20. ref-tags with identical names but different content should keep it
-!! wikitext
-A <ref name="foo">Foo one</ref>
-B <ref name="foo">Foo two</ref>
-C <ref name="foo" />
-
-<references />
-!! html/parsoid
-<p>A <span about="#mwt2" class="mw-ref" id="cite_ref-foo_1-0" rel="dc:references" typeof="mw:Extension/ref" data-mw='{"name":"ref","body":{"id":"mw-reference-text-cite_note-foo-1"},"attrs":{"name":"foo"}}'><a href="./Main_Page#cite_note-foo-1"><span class="mw-reflink-text">[1]</span></a></span>
-B <span about="#mwt4" class="mw-ref" id="cite_ref-foo_1-1" rel="dc:references" typeof="mw:Extension/ref" data-mw='{"name":"ref","body":{"html":"Foo two"},"attrs":{"name":"foo"}}'><a href="./Main_Page#cite_note-foo-1"><span class="mw-reflink-text">[1]</span></a></span>
-C <span about="#mwt6" class="mw-ref" id="cite_ref-foo_1-2" rel="dc:references" typeof="mw:Extension/ref" data-mw='{"name":"ref","attrs":{"name":"foo"}}'><a href="./Main_Page#cite_note-foo-1"><span class="mw-reflink-text">[1]</span></a></span></p>
-
-<ol class="mw-references" typeof="mw:Extension/references" about="#mwt8" data-mw='{"name":"references","attrs":{}}'><li about="#cite_note-foo-1" id="cite_note-foo-1"><span rel="mw:referencedBy"><a href="./Main_Page#cite_ref-foo_1-0"><span class="mw-linkback-text">1 </span></a><a href="./Main_Page#cite_ref-foo_1-1"><span class="mw-linkback-text">2 </span></a><a href="./Main_Page#cite_ref-foo_1-2"><span class="mw-linkback-text">3 </span></a></span> <span id="mw-reference-text-cite_note-foo-1" class="mw-reference-text">Foo one</span></li>
-</ol>
-!!end
-
-!!test
-References: 1. references tag without any refs should be handled properly
-!! wikitext
-<references />
-!! html/parsoid
-<ol class="mw-references" typeof="mw:Extension/references" about="#mwt2" data-mw='{"name":"references","attrs":{}}'></ol>
-!!end
-
-!!test
-References: 2. references tag with group only outputs references from that group
-!! wikitext
-A <ref group="a">foo</ref>
-B <ref group="b">bar</ref>
-C <ref>baz</ref>
-
-<references group="a" />
-<references />
-<references group="b" />
-!! html/parsoid
-<p>A <span about="#mwt2" class="mw-ref" id="cite_ref-1" rel="dc:references" typeof="mw:Extension/ref" data-mw='{"name":"ref","body":{"id":"mw-reference-text-cite_note-1"},"attrs":{"group":"a"}}'><a href="./Main_Page#cite_note-1" data-mw-group="a"><span class="mw-reflink-text">[a 1]</span></a></span>
-B <span about="#mwt4" class="mw-ref" id="cite_ref-2" rel="dc:references" typeof="mw:Extension/ref" data-mw='{"name":"ref","body":{"id":"mw-reference-text-cite_note-2"},"attrs":{"group":"b"}}'><a href="./Main_Page#cite_note-2" data-mw-group="b"><span class="mw-reflink-text">[b 1]</span></a></span>
-C <span class="mw-ref" id="cite_ref-3" rel="dc:references" typeof="mw:Extension/ref" data-mw='{"name":"ref","body":{"id":"mw-reference-text-cite_note-3"},"attrs":{}}'><a href="./Main_Page#cite_note-3"><span class="mw-reflink-text">[1]</span></a></span></p>
-
-<ol class="mw-references" typeof="mw:Extension/references" about="#mwt8" data-mw-group="a" data-mw='{"name":"references","attrs":{"group":"a"}}'>
-<li about="#cite_note-1" id="cite_note-1"><a href="./Main_Page#cite_ref-1" data-mw-group="a" rel="mw:referencedBy"><span class="mw-linkback-text">↑ </span></a> <span id="mw-reference-text-cite_note-1" class="mw-reference-text">foo</span></li>
-</ol>
-<ol class="mw-references" typeof="mw:Extension/references" about="#mwt10" data-mw='{"name":"references","attrs":{}}'>
-<li about="#cite_note-3" id="cite_note-3"><a href="./Main_Page#cite_ref-3" rel="mw:referencedBy"><span class="mw-linkback-text">↑ </span></a> <span id="mw-reference-text-cite_note-3" class="mw-reference-text">baz</span></li>
-</ol>
-<ol class="mw-references" typeof="mw:Extension/references" about="#mwt12" data-mw-group="b" data-mw='{"name":"references","attrs":{"group":"b"}}'>
-<li about="#cite_note-2" id="cite_note-2"><a href="./Main_Page#cite_ref-2" data-mw-group="b" rel="mw:referencedBy"><span class="mw-linkback-text">↑ </span></a> <span id="mw-reference-text-cite_note-2" class="mw-reference-text">bar</span></li>
-</ol>
-!!end
-
-!!test
-References: 3. ref list should be cleared after processing references
-!! wikitext
-A <ref>foo</ref>
-
-<references />
-
-B <ref>bar</ref>
-
-<references />
-!! html/parsoid
-<p>A <span about="#mwt2" class="mw-ref" id="cite_ref-1" rel="dc:references" typeof="mw:Extension/ref" data-mw='{"name":"ref","body":{"id":"mw-reference-text-cite_note-1"},"attrs":{}}'><a href="./Main_Page#cite_note-1"><span class="mw-reflink-text">[1]</span></a></span></p>
-
-<ol class="mw-references" typeof="mw:Extension/references" about="#mwt4" data-mw='{"name":"references","attrs":{}}'><li about="#cite_note-1" id="cite_note-1"><a href="./Main_Page#cite_ref-1" rel="mw:referencedBy"><span class="mw-linkback-text">↑ </span></a> <span id="mw-reference-text-cite_note-1" class="mw-reference-text">foo</span></li>
-</ol>
-
-<p>B <span about="#mwt6" class="mw-ref" id="cite_ref-2" rel="dc:references" typeof="mw:Extension/ref" data-mw='{"name":"ref","body":{"id":"mw-reference-text-cite_note-2"},"attrs":{}}'><a href="./Main_Page#cite_note-2"><span class="mw-reflink-text">[1]</span></a></span></p>
-
-<ol class="mw-references" typeof="mw:Extension/references" about="#mwt8" data-mw='{"name":"references","attrs":{}}'>
-<li about="#cite_note-2" id="cite_note-2"><a href="./Main_Page#cite_ref-2" rel="mw:referencedBy"><span class="mw-linkback-text">↑ </span></a> <span id="mw-reference-text-cite_note-2" class="mw-reference-text">bar</span></li>
-</ol>
-!!end
-
-!!test
-References: 4. only referenced group should be cleared after processing references
-!! wikitext
-A <ref group="a">afoo</ref>
-B <ref>bfoo</ref>
-
-<references group="a" />
-
-C <ref>cfoo</ref>
-
-<references />
-!! html/parsoid
-<p>A <span about="#mwt2" class="mw-ref" id="cite_ref-1" rel="dc:references" typeof="mw:Extension/ref" data-mw='{"name":"ref","body":{"id":"mw-reference-text-cite_note-1"},"attrs":{"group":"a"}}'><a href="./Main_Page#cite_note-1" data-mw-group="a"><span class="mw-reflink-text">[a 1]</span></a></span>
-B <span about="#mwt4" class="mw-ref" id="cite_ref-2" rel="dc:references" typeof="mw:Extension/ref" data-mw='{"name":"ref","body":{"id":"mw-reference-text-cite_note-2"},"attrs":{}}'><a href="./Main_Page#cite_note-2"><span class="mw-reflink-text">[1]</span></a></span></p>
-
-<ol class="mw-references" typeof="mw:Extension/references" about="#mwt6" data-mw-group="a" data-mw='{"name":"references","attrs":{"group":"a"}}'><li about="#cite_note-1" id="cite_note-1"><a href="./Main_Page#cite_ref-1" data-mw-group="a" rel="mw:referencedBy"><span class="mw-linkback-text">↑ </span></a> <span id="mw-reference-text-cite_note-1" class="mw-reference-text">afoo</span></li>
-</ol>
-
-<p>C <span about="#mwt8" class="mw-ref" id="cite_ref-3" rel="dc:references" typeof="mw:Extension/ref" data-mw='{"name":"ref","body":{"id":"mw-reference-text-cite_note-3"},"attrs":{}}'><a href="./Main_Page#cite_note-3"><span class="mw-reflink-text">[2]</span></a></span></p>
-
-<ol class="mw-references" typeof="mw:Extension/references" about="#mwt10" data-mw='{"name":"references","attrs":{}}'><li about="#cite_note-2" id="cite_note-2"><a href="./Main_Page#cite_ref-2" rel="mw:referencedBy"><span class="mw-linkback-text">↑ </span></a> <span id="mw-reference-text-cite_note-2" class="mw-reference-text">bfoo</span></li><li about="#cite_note-3" id="cite_note-3"><a href="./Main_Page#cite_ref-3" rel="mw:referencedBy"><span class="mw-linkback-text">↑ </span></a> <span id="mw-reference-text-cite_note-3" class="mw-reference-text">cfoo</span></li>
-</ol>
-!!end
-
-## Don't expect this to rt since we're dropping content
-!! test
-References: 5. ref tags in references should be processed while ignoring all other content
-!! options
-parsoid=wt2html,html2html
-!! wikitext
-A <ref name="a" />
-B <ref name="b">bar</ref>
-
-<references>
-<ref name="a">foo</ref>
-This should just get lost.
-</references>
-!! html/parsoid
-<p>A <span about="#mwt2" class="mw-ref" id="cite_ref-a_1-0" rel="dc:references" typeof="mw:Extension/ref" data-mw='{"name":"ref","attrs":{"name":"a"}}'><a href="./Main_Page#cite_note-a-1"><span class="mw-reflink-text">[1]</span></a></span>
-B <span about="#mwt4" class="mw-ref" id="cite_ref-b_2-0" rel="dc:references" typeof="mw:Extension/ref" data-mw='{"name":"ref","body":{"id":"mw-reference-text-cite_note-b-2"},"attrs":{"name":"b"}}'><a href="./Main_Page#cite_note-b-2"><span class="mw-reflink-text">[2]</span></a></span></p>
-
-
-<ol class="mw-references" typeof="mw:Extension/references" about="#mwt6" data-mw='{"name":"references","attrs":{},"body":{"html":"\n&lt;span about=\"#mwt8\" class=\"mw-ref\" rel=\"dc:references\" typeof=\"mw:Extension/ref\" data-parsoid=&#39;{\"dsr\":[59,82,14,6]}&#39; data-mw=&#39;{\"name\":\"ref\",\"body\":{\"id\":\"mw-reference-text-cite_note-a-1\"},\"attrs\":{\"name\":\"a\"}}&#39;>&lt;a href=\"./Main_Page#cite_note-a-1\" style=\"counter-reset: mw-Ref 1;\" data-parsoid=\"{}\">&lt;span class=\"mw-reflink-text\" data-parsoid=\"{}\">[1]&lt;/span>&lt;/a>&lt;/span>\n"}}'><li about="#cite_note-a-1" id="cite_note-a-1"><a href="./Main_Page#cite_ref-a_1-0" rel="mw:referencedBy"><span class="mw-linkback-text">↑ </span></a> <span id="mw-reference-text-cite_note-a-1" class="mw-reference-text">foo</span></li><li about="#cite_note-b-2" id="cite_note-b-2"><a href="./Main_Page#cite_ref-b_2-0" rel="mw:referencedBy"><span class="mw-linkback-text">↑ </span></a> <span id="mw-reference-text-cite_note-b-2" class="mw-reference-text">bar</span></li>
-</ol>
-!! end
-
-!! test
-References: 6. <references /> from a transclusion
-!! wikitext
-<ref>Foo</ref> {{echo|<references />}}
-!! html/parsoid
-<p><span about="#mwt3" class="mw-ref" id="cite_ref-1" rel="dc:references" typeof="mw:Extension/ref" data-mw='{"name":"ref","body":{"id":"mw-reference-text-cite_note-1"},"attrs":{}}'><a href="./Main_Page#cite_note-1"><span class="mw-reflink-text">[1]</span></a></span></p> <ol class="mw-references" typeof="mw:Extension/references mw:Transclusion" about="#mwt4" data-mw='{"parts":[{"template":{"target":{"wt":"echo","href":"./Template:Echo"},"params":{"1":{"wt":"&lt;references />"}},"i":0}}]}'><li about="#cite_note-1" id="cite_note-1"><a href="./Main_Page#cite_ref-1" rel="mw:referencedBy"><span class="mw-linkback-text">↑ </span></a> <span id="mw-reference-text-cite_note-1" class="mw-reference-text">Foo</span></li>
-</ol>
-!! end
-
-!! test
-References: 7. Multiple references tags (one without and one with nested refs) should be correctly handled
-!! wikitext
-A <ref>foo bar for a</ref>
-B <ref group="X" name="b" />
-
-<references />
-
-<references group="X">
-<ref name="b">foo</ref>
-</references>
-!! html/parsoid
-<p>A <span about="#mwt2" class="mw-ref" id="cite_ref-1" rel="dc:references" typeof="mw:Extension/ref" data-mw='{"name":"ref","body":{"id":"mw-reference-text-cite_note-1"},"attrs":{}}'><a href="./Main_Page#cite_note-1"><span class="mw-reflink-text">[1]</span></a></span>
-B <span about="#mwt4" class="mw-ref" id="cite_ref-b_2-0" rel="dc:references" typeof="mw:Extension/ref" data-mw='{"name":"ref","attrs":{"group":"X","name":"b"}}'><a href="./Main_Page#cite_note-b-2" data-mw-group="X"><span class="mw-reflink-text">[X 1]</span></a></span>
-</p>
-
-<ol class="mw-references" typeof="mw:Extension/references" about="#mwt6" data-mw='{"name":"references","attrs":{}}'>
-<li about="#cite_note-1" id="cite_note-1"><a href="./Main_Page#cite_ref-1" rel="mw:referencedBy"><span class="mw-linkback-text">↑ </span></a> <span id="mw-reference-text-cite_note-1" class="mw-reference-text">foo bar for a</span></li>
-</ol>
-
-<ol class="mw-references" typeof="mw:Extension/references" about="#mwt8" data-mw-group="X" data-mw='{"name":"references","attrs":{"group":"X"},"body":{"html":"\n&lt;span about=\"#mwt10\" class=\"mw-ref\" rel=\"dc:references\" typeof=\"mw:Extension/ref\" data-parsoid=&#39;{\"dsr\":[96,119,14,6]}&#39; data-mw=&#39;{\"name\":\"ref\",\"body\":{\"id\":\"mw-reference-text-cite_note-b-2\"},\"attrs\":{\"name\":\"b\"}}&#39;>&lt;a href=\"./Main_Page#cite_note-b-2\" style=\"counter-reset: mw-Ref 1;\" data-mw-group=\"X\" data-parsoid=\"{}\">&lt;span class=\"mw-reflink-text\" data-parsoid=\"{}\">[X 1]&lt;/span>&lt;/a>&lt;/span>\n"}}'>
-<li about="#cite_note-b-2" id="cite_note-b-2"><a href="./Main_Page#cite_ref-b_2-0" data-mw-group="X" rel="mw:referencedBy"><span class="mw-linkback-text">↑ </span></a> <span id="mw-reference-text-cite_note-b-2" class="mw-reference-text">foo</span></li>
-</ol>
-!! end
-
-!! test
-References: 8. T88019: Remove <meta>s from templates inside <ref> that's itself inside a template
-!! wikitext
-X{{echo|<ref>foo {{echo|<b>bar</b>}} and {{echo|baz}} boo</ref>}}
-<references />
-!! html/parsoid
-<p>X<span about="#mwt2" class="mw-ref" id="cite_ref-1" rel="dc:references" typeof="mw:Transclusion  mw:Extension/ref" data-mw='{"parts":[{"template":{"target":{"wt":"echo","href":"./Template:Echo"},"params":{"1":{"wt":"&lt;ref>foo {{echo|&lt;b>bar&lt;/b>}} and {{echo|baz}} boo&lt;/ref>"}},"i":0}}]}'><a href="./Main_Page#cite_note-1"><span class="mw-reflink-text">[1]</span></a></span></p>
-<ol class="mw-references" typeof="mw:Extension/references" about="#mwt7" data-mw='{"name":"references","attrs":{}}'><li about="#cite_note-1" id="cite_note-1"><a href="./Main_Page#cite_ref-1" rel="mw:referencedBy"><span class="mw-linkback-text">↑ </span></a> <span id="mw-reference-text-cite_note-1" class="mw-reference-text">foo <b data-parsoid='{"stx":"html"}'>bar</b> and baz boo</span></li>
-</ol>
-!!end
-
-# This test only works in wt2html now as the <references /> are always generated
-# unless selser is active. Once T72722 is fixed, we should add a changes test
-# here to ensure that unrelated changes don't add the new <references />
-# when selser is active.
-!! test
-References: 9. Generate missing references list at the end
-!! wikitext
-A <ref>foo</ref>
-B <ref group="inexistent">bar</ref>
-!! html/parsoid
-<p>A <span class="mw-ref" id="cite_ref-1" rel="dc:references" typeof="mw:Extension/ref" data-mw='{"name":"ref","body":{"id":"mw-reference-text-cite_note-1"},"attrs":{}}'><a href="./Main_Page#cite_note-1"><span class="mw-reflink-text">[1]</span></a></span> B <span class="mw-ref" id="cite_ref-2" rel="dc:references" typeof="mw:Extension/ref" data-mw='{"name":"ref","body":{"id":"mw-reference-text-cite_note-2"},"attrs":{"group":"inexistent"}}'><a href="./Main_Page#cite_note-2" data-mw-group="inexistent"><span class="mw-reflink-text">[inexistent 1]</span></a></span></p>
-<ol class="mw-references" typeof="mw:Extension/references" about="#mwt5" data-mw='{"name":"references","attrs":{},"autoGenerated":true}'>
-<li about="#cite_note-1" id="cite_note-1"><a href="./Main_Page#cite_ref-1" rel="mw:referencedBy"><span class="mw-linkback-text">↑ </span></a> <span id="mw-reference-text-cite_note-1" class="mw-reference-text">foo</span></li>
-</ol>
-<ol class="mw-references" typeof="mw:Extension/references" about="#mwt6" data-mw-group="inexistent" data-mw='{"name":"references","attrs":{"group":"inexistent"},"autoGenerated":true}'>
-<li about="#cite_note-2" id="cite_note-2"><a href="./Main_Page#cite_ref-2" data-mw-group="inexistent" rel="mw:referencedBy"><span class="mw-linkback-text">↑ </span></a> <span id="mw-reference-text-cite_note-2" class="mw-reference-text">bar</span></li>
-</ol>
-!! end
-
-!! test
-References: 10. New <references/> shouldn't be added for unrelated edits.
-!! options
-parsoid={
-  "modes": ["selser"],
-  "changes": [["#x", "remove"]],
-  "selser": "noauto"
-}
-!! wikitext
-Unrelated text<span id="x"> that's going to disappear</span>.
-A <ref>foo</ref>
-!! wikitext/edited
-Unrelated text.
-A <ref>foo</ref>
-!!end
-
-!! test
-Entities in ref name
-!! wikitext
-<ref name="test &amp; me">hi</ref>
-<references />
-!! html/parsoid
-<p><span about="#mwt2" class="mw-ref" id="cite_ref-test_.26_me_1-0" rel="dc:references" typeof="mw:Extension/ref" data-mw='{"name":"ref","body":{"id":"mw-reference-text-cite_note-test_.26_me-1"},"attrs":{"name":"test &amp;amp; me"}}'><a href="./Main_Page#cite_note-test_.26_me-1"><span class="mw-reflink-text">[1]</span></a></span></p>
-<ol class="mw-references" typeof="mw:Extension/references" about="#mwt4" data-mw='{"name":"references","attrs":{}}'>
-<li about="#cite_note-test_.26_me-1" id="cite_note-test_.26_me-1"><a href="./Main_Page#cite_ref-test_.26_me_1-0" rel="mw:referencedBy"><span class="mw-linkback-text">↑ </span></a> <span id="mw-reference-text-cite_note-test_.26_me-1" class="mw-reference-text">hi</span></li>
-</ol>
-!! end
-
-## The output here may look funny, but it's what the php parser will do.  The
-## unclosed references tag becomes escaped text, and then a new references
-## tag is auto-generated.  The test is wt2html only because it roundtrips with
-## nowiki tags, and the auto-generated references tag is only dropped in
-## rtTestMode.
-!! test
-Generate references for unclosed references tag
-!! options
-parsoid=wt2html
-!! wikitext
-a<ref>foo</ref>
-
-<references>
-!! html/parsoid
-<p>a<span about="#mwt2" class="mw-ref" id="cite_ref-1" rel="dc:references" typeof="mw:Extension/ref" data-mw='{"name":"ref","body":{"id":"mw-reference-text-cite_note-1"},"attrs":{}}'><a href="./Main_Page#cite_note-1" style="counter-reset: mw-Ref 1;"><span class="mw-reflink-text">[1]</span></a></span></p>
-
-<p>&lt;references></p>
-<ol class="mw-references" typeof="mw:Extension/references" about="#mwt3" data-mw='{"name":"references","attrs":{},"autoGenerated":true}'><li about="#cite_note-1" id="cite_note-1"><a href="./Main_Page#cite_ref-1" rel="mw:referencedBy"><span class="mw-linkback-text">↑ </span></a> <span id="mw-reference-text-cite_note-1" class="mw-reference-text">foo</span></li></ol>
-!! end
-
-!! test
-New reference serializes on its own line
-!! options
-parsoid=wt2wt,html2wt
-!! wikitext
-foo
-<references />
-!! html/parsoid
-foo<ol class="mw-references" typeof="mw:Extension/references" about="#mwt2" data-mw='{"name":"references","attrs":{}}'></ol>
-!! end
-
 #### ----------------------------------------------------------------
 #### Parsoid-only testing of Parsoid's impl of LST
 #### Not implemented yet, see
@@ -24430,7 +23824,7 @@ parsoid=html2wt
 !! end
 
 !! test
-Links 6. Add <nowiki/>s between text-nodes and url-links when required (bug 64300)
+Links 6. Add <nowiki/>s between text-nodes and url-links when required (T66300)
 !! options
 parsoid=html2wt
 !! html/parsoid
@@ -24465,7 +23859,7 @@ http://example.com(x<nowiki/>)
 !! end
 
 !! test
-Links 7a. Don't add spurious <nowiki/>s between text-nodes and url-links (bug 64300)
+Links 7a. Don't add spurious <nowiki/>s between text-nodes and url-links (T66300)
 !! options
 parsoid=html2wt
 !! html/parsoid
 !! end
 
 !! test
-Links 7b. Don't add spurious <nowiki/>s between text-nodes and url-links (bug 64300)
+Links 7b. Don't add spurious <nowiki/>s between text-nodes and url-links (T66300)
 !! options
 parsoid=html2wt
 !! html/parsoid
@@ -24516,7 +23910,7 @@ http://example.com.,;:!?\
 !! end
 
 !! test
-Links 8. Add <nowiki/>s between text-nodes and RFC-links when required (bug 64300)
+Links 8. Add <nowiki/>s between text-nodes and RFC-links when required (T66300)
 !! options
 parsoid=html2wt
 !! html/parsoid
@@ -24530,7 +23924,7 @@ X<nowiki/>RFC 123<nowiki/>y
 !! end
 
 !! test
-Links 9. Don't add spurious <nowiki/>s between text-nodes and RFC-links (bug 64300)
+Links 9. Don't add spurious <nowiki/>s between text-nodes and RFC-links (T66300)
 !! options
 parsoid=html2wt
 !! html/parsoid
@@ -24550,7 +23944,7 @@ RFC 123&foo
 !! end
 
 !! test
-Links 10. Add <nowiki/>s between text-nodes and PMID-links when required (bug 64300)
+Links 10. Add <nowiki/>s between text-nodes and PMID-links when required (T66300)
 !! options
 parsoid=html2wt
 !! html/parsoid
@@ -24564,7 +23958,7 @@ X<nowiki/>PMID 123<nowiki/>y
 !! end
 
 !! test
-Links 11. Don't add spurious <nowiki/>s between text-nodes and PMID-links (bug 64300)
+Links 11. Don't add spurious <nowiki/>s between text-nodes and PMID-links (T66300)
 !! options
 parsoid=html2wt
 !! html/parsoid
@@ -24584,7 +23978,7 @@ PMID 123&foo
 !! end
 
 !! test
-Links 12. Add <nowiki/>s between text-nodes and ISBN-links when required (bug 64300)
+Links 12. Add <nowiki/>s between text-nodes and ISBN-links when required (T66300)
 !! options
 parsoid=html2wt
 !! html/parsoid
@@ -24599,7 +23993,7 @@ a<nowiki/>ISBN 1234567890<nowiki/>b
 !! end
 
 !! test
-Links 13. Don't add spurious <nowiki/>s between text-nodes and ISBN-links (bug 64300)
+Links 13. Don't add spurious <nowiki/>s between text-nodes and ISBN-links (T66300)
 !! options
 parsoid=html2wt
 !! html/parsoid
@@ -25045,7 +24439,7 @@ parsoid=html2wt
 
 ## The quote-char in the input is necessary for triggering the bug
 !! test
-(Bug 52035) Nowiki-escaping should not get tripped by " :" in text
+(T54035) Nowiki-escaping should not get tripped by " :" in text
 !! options
 parsoid=html2wt
 !! html/parsoid
@@ -25732,7 +25126,7 @@ parsoid=wt2html
 </table>
 !!end
 
-# Parsoid only for bug 64747
+# Parsoid only for T66747
 !! test
 Properly encapsulate empty-content transclusions in fosterable positions
 !! wikitext
@@ -25828,7 +25222,7 @@ http://en.wikipedia.org/wiki/Foobar
 
 # 'mi' is a localinterwiki prefix as well as a language
 !! test
-Serialize interwiki links pointing to the current wiki as plain wiki links (bug 65869)
+Serialize interwiki links pointing to the current wiki as plain wiki links (T67869)
 !! options
 parsoid=html2wt
 !! html/parsoid
@@ -25980,7 +25374,7 @@ parsoid={
 !!end
 
 !! test
-Image: Modifying alignment of an image (bug 48665)
+Image: Modifying alignment of an image (T50665)
 !! options
 parsoid={
   "modes": ["wt2wt"],
@@ -25996,7 +25390,7 @@ parsoid={
 !! end
 
 !! test
-Image: Modifying mw-default-size of an frameless image (bug 62805)
+Image: Modifying mw-default-size of an frameless image (T64805)
 !! options
 parsoid={
   "modes": ["wt2wt"],
@@ -26011,7 +25405,7 @@ parsoid={
 !! end
 
 !! test
-Image: Modifying valign of an image (bug 49221)
+Image: Modifying valign of an image (T51221)
 !! options
 parsoid={
   "modes": ["wt2wt"],
@@ -26027,7 +25421,7 @@ parsoid={
 !! end
 
 !! test
-Image: Modifying alt attribute of an image (bug 56400)
+Image: Modifying alt attribute of an image (T58400)
 !! options
 parsoid={
   "modes": ["wt2wt"],
@@ -26057,7 +25451,7 @@ parsoid={
 !!end
 
 !! test
-Image: empty alt attribute (bug 48924)
+Image: empty alt attribute (T50924)
 !! options
 parsoid
 !! wikitext
@@ -26067,7 +25461,7 @@ parsoid
 !! end
 
 !! test
-Image: new attributes should be serialized in wiki's language for RTL languages (bug 51852)
+Image: new attributes should be serialized in wiki's language for RTL languages (T53852)
 !! options
 parsoid=html2wt
 language=ar
@@ -26672,7 +26066,7 @@ parsoid={
 #------------------------------
 
 !!test
-Bug 54262: New entities
+T56262: New entities
 !! options
 parsoid=html2wt
 !! html/parsoid
@@ -26814,7 +26208,7 @@ WTS of autolinks with escapes (editing)
 parsoid={
   "modes": ["wt2wt"],
   "changes": [
-    [ "meta", "remove" ]
+    [ "span", "remove" ]
   ]
 }
 !! wikitext
index c561f81..90acc39 100644 (file)
@@ -42,14 +42,15 @@ return [
                class_exists( Memcached::class ) ? [] : [ 'tests/phan/stubs/memcached.php' ],
                [
                        'maintenance/7zip.inc',
-                       'maintenance/backupPrefetch.inc',
-                       'maintenance/commandLine.inc',
-                       'maintenance/sqlite.inc',
-                       'maintenance/userOptions.inc',
                        'maintenance/backup.inc',
+                       'maintenance/backupPrefetch.inc',
                        'maintenance/cleanupTable.inc',
+                       'maintenance/CodeCleanerGlobalsPass.inc',
+                       'maintenance/commandLine.inc',
                        'maintenance/importImages.inc',
+                       'maintenance/sqlite.inc',
                        'maintenance/userDupes.inc',
+                       'maintenance/userOptions.inc',
                        'maintenance/language/checkLanguage.inc',
                        'maintenance/language/languages.inc',
                ]
index 12b277e..63d05a0 100644 (file)
@@ -84,7 +84,7 @@ class BlockTest extends MediaWikiLangTestCase {
        }
 
        /**
-        * per bug 26425
+        * per T28425
         */
        public function testBug26425BlockTimestampDefaultsToTime() {
                // delta to stop one-off errors when things happen to go over a second mark.
@@ -99,7 +99,7 @@ class BlockTest extends MediaWikiLangTestCase {
        /**
         * CheckUser since being changed to use Block::newFromTarget started failing
         * because the new function didn't accept empty strings like Block::load()
-        * had. Regression bug 29116.
+        * had. Regression T31116.
         *
         * @dataProvider provideBug29116Data
         * @covers Block::newFromTarget
index 5a01dc0..9507811 100644 (file)
@@ -53,7 +53,7 @@ class EditPageTest extends MediaWikiLangTestCase {
                                false
                        ],
                        [
-                               "An initial section with a fake heder (bug 32617)\n\n== Test == ??\nwtf",
+                               "An initial section with a fake heder (T34617)\n\n== Test == ??\nwtf",
                                false
                        ],
                        [
@@ -61,7 +61,7 @@ class EditPageTest extends MediaWikiLangTestCase {
                                "Section"
                        ],
                        [
-                               "== Section== \t\r\n followed by whitespace (bug 35051)",
+                               "== Section== \t\r\n followed by whitespace (T37051)",
                                'Section',
                        ],
                ];
index 5dd4f7a..4e95a30 100644 (file)
@@ -32,7 +32,7 @@ class ExtraParserTest extends MediaWikiTestCase {
        }
 
        /**
-        * @see Bug 8689
+        * @see T10689
         * @covers Parser::parse
         */
        public function testLongNumericLinesDontKillTheParser() {
index 5ca373d..b6682f7 100644 (file)
@@ -87,13 +87,13 @@ class WfTimestampTest extends MediaWikiTestCase {
        /**
         * This test checks wfTimestamp() with values outside.
         * It needs PHP 64 bits or PHP > 5.1.
-        * See r74778 and bug 25451
+        * See r74778 and T27451
         * @dataProvider provideOldTimestamps
         */
        public function testOldTimestamps( $input, $outputType, $output, $message ) {
                $timestamp = wfTimestamp( $outputType, $input );
                if ( substr( $output, 0, 1 ) === '/' ) {
-                       // Bug 64946: Day of the week calculations for very old
+                       // T66946: Day of the week calculations for very old
                        // timestamps varies from system to system.
                        $this->assertRegExp( $output, $timestamp, $message );
                } else {
index 1de9c23..2694b85 100644 (file)
@@ -448,7 +448,7 @@ class MessageTest extends MediaWikiLangTestCase {
        }
 
        /**
-        * FIXME: This should not need database, but Language#formatExpiry does (bug 55912)
+        * FIXME: This should not need database, but Language#formatExpiry does (T57912)
         * @group Database
         * @covers Message::expiryParam
         * @covers Message::expiryParams
index 289853d..90b6396 100644 (file)
@@ -42,7 +42,7 @@ class PreferencesTest extends MediaWikiTestCase {
        }
 
        /**
-        * Placeholder to verify bug 34302
+        * Placeholder to verify T36302
         * @covers Preferences::profilePreferences
         */
        public function testEmailAuthenticationFieldWhenUserHasNoEmail() {
@@ -54,7 +54,7 @@ class PreferencesTest extends MediaWikiTestCase {
        }
 
        /**
-        * Placeholder to verify bug 34302
+        * Placeholder to verify T36302
         * @covers Preferences::profilePreferences
         */
        public function testEmailAuthenticationFieldWhenUserEmailNotAuthenticated() {
@@ -66,7 +66,7 @@ class PreferencesTest extends MediaWikiTestCase {
        }
 
        /**
-        * Placeholder to verify bug 34302
+        * Placeholder to verify T36302
         * @covers Preferences::profilePreferences
         */
        public function testEmailAuthenticationFieldWhenUserEmailIsAuthenticated() {
index c5a7e04..cf2e120 100644 (file)
@@ -260,7 +260,7 @@ class PrefixSearchTest extends MediaWikiLangTestCase {
                                ],
                        ] ],
                        [ [
-                               'Exact match not on top (bug 70958)',
+                               'Exact match not on top (T72958)',
                                'provision' => [
                                        'Barcelona',
                                        'Bar',
@@ -274,7 +274,7 @@ class PrefixSearchTest extends MediaWikiLangTestCase {
                                ],
                        ] ],
                        [ [
-                               'Exact match missing (bug 70958)',
+                               'Exact match missing (T72958)',
                                'provision' => [
                                        'Barcelona',
                                        'Barbara',
index 12db1a1..862b7d0 100644 (file)
@@ -211,7 +211,7 @@ class SanitizerTest extends MediaWikiTestCase {
                        [ [ 'foo6' => 'baz' ], 'foo6=baz', 'Numbers are allowed' ],
 
                        # This bit is more relaxed than XML rules, but some extensions use
-                       # it, like ProofreadPage (see bug 27539)
+                       # it, like ProofreadPage (see T29539)
                        [ [ '1foo' => 'baz' ], '1foo=baz', 'Leading numbers are allowed' ],
                        [ [], 'foo$=baz', 'Symbols are not allowed' ],
                        [ [], 'foo@=baz', 'Symbols are not allowed' ],
@@ -286,7 +286,7 @@ class SanitizerTest extends MediaWikiTestCase {
                        [ ' ', '/* /* */' ],
                        [ 'display: block;', "display:/* foo */block;" ],
                        [ 'display: block;', "display:\\2f\\2a foo \\2a\\2f block;",
-                               'Backslash-escaped comments must be stripped (bug 28450)' ],
+                               'Backslash-escaped comments must be stripped (T30450)' ],
                        [ '', '/* unfinished comment structure',
                                'Remove anything after a comment-start token' ],
                        [ '', "\\2f\\2a unifinished comment'",
index f47e74e..2448513 100644 (file)
@@ -64,7 +64,7 @@ class SanitizerValidateEmailTest extends PHPUnit_Framework_TestCase {
        }
 
        /**
-        * bug 26948 : comma were matched by an incorrect regexp range
+        * T28948 : comma were matched by an incorrect regexp range
         */
        public function testEmailWithCommasAreInvalids() {
                $this->invalid( "user,foo@example.org" );
index 7925c6f..238b65f 100644 (file)
@@ -267,7 +267,7 @@ class TitleTest extends MediaWikiTestCase {
                $this->assertEquals(
                        $expectedParam,
                        $par,
-                       "Bug 31100 regression check: Title->fixSpecialName() should preserve parameter"
+                       "T33100 regression check: Title->fixSpecialName() should preserve parameter"
                );
        }
 
index 18ff1f4..184dd43 100644 (file)
@@ -83,7 +83,7 @@ class XmlTest extends MediaWikiTestCase {
                $this->assertEquals(
                        '<input name="name" value="0" />',
                        Xml::input( 'name', false, 0 ),
-                       'Input with a value of 0 (bug 23797)'
+                       'Input with a value of 0 (T25797)'
                );
        }
 
index 0ffcbca..e091153 100644 (file)
@@ -204,7 +204,7 @@ class ApiEditPageTest extends ApiTestCase {
        /**
         * Test action=edit&section=new
         * Run it twice so we test adding a new section on a
-        * page that doesn't exist (bug 52830) and one that
+        * page that doesn't exist (T54830) and one that
         * does exist
         */
        public function testEditNewSection() {
@@ -416,7 +416,7 @@ class ApiEditPageTest extends ApiTestCase {
                $count++;
 
                /*
-               * bug 41990: if the target page has a newer revision than the redirect, then editing the
+               * T43990: if the target page has a newer revision than the redirect, then editing the
                * redirect while specifying 'redirect' and *not* specifying 'basetimestamp' erroneously
                * caused an edit conflict to be detected.
                */
index eff41e3..9060dfb 100644 (file)
@@ -451,7 +451,10 @@ class ApiMainTest extends ApiTestCase {
                $context->setRequest( new FauxRequest( [ 'errorformat' => 'plaintext' ] ) );
                $context->setLanguage( 'en' );
                $context->setConfig( new MultiConfig( [
-                       new HashConfig( [ 'ShowHostnames' => true, 'ShowSQLErrors' => false ] ),
+                       new HashConfig( [
+                               'ShowHostnames' => true, 'ShowSQLErrors' => false,
+                               'ShowExceptionDetails' => true, 'ShowDBErrorBacktrace' => true,
+                       ] ),
                        $context->getConfig()
                ] ) );
 
index 7687236..9f28aaf 100644 (file)
@@ -13,7 +13,7 @@ class ApiQueryAllPagesTest extends ApiTestCase {
        }
 
        /**
-        *Test bug 25702
+        *Test T27702
         *Prefixes of API search requests are not handled with case sensitivity and may result
         *in wrong search results
         */
index e5971b4..fbc794e 100644 (file)
@@ -325,7 +325,7 @@ class ApiQueryBasicTest extends ApiQueryTestBase {
        }
 
        /**
-        * Test bug 51821
+        * Test T53821
         */
        public function testGeneratorRedirects() {
                $this->editPage( 'AQBT-Target', 'test' );
index ed82153..5eed01c 100644 (file)
@@ -75,7 +75,7 @@ class LocalisationCacheTest extends MediaWikiTestCase {
 
        public function testRecacheFallbacksWithHooks() {
                // Use hook to provide updates for messages. This is what the
-               // LocalisationUpdate extension does. See bug 68781.
+               // LocalisationUpdate extension does. See T70781.
                $this->mergeMwGlobalArrayValue( 'wgHooks', [
                        'LocalisationCacheRecacheFallback' => [
                                function (
index a12c8b2..b03eeba 100644 (file)
@@ -92,7 +92,7 @@ class MessageCacheTest extends MediaWikiLangTestCase {
                        // Existing message with customizations on the fallbacks
                        [ 'sunday', 'ab', 'амҽыш' ],
 
-                       // bug 46579
+                       // T48579
                        [ 'FallbackLanguageTest-NoDervContLang', 'de', 'de/none' ],
                        // UI language different from content language should only use de/none as last option
                        [ 'FallbackLanguageTest-NoDervContLang', 'fit', 'de/none' ],
index f54170b..b95462a 100644 (file)
@@ -120,7 +120,7 @@ class DatabaseMysqlBaseTest extends MediaWikiTestCase {
        /**
         * Feeds testAddIdentifierQuotes
         *
-        * Named per bug 20281 convention.
+        * Named per T22281 convention.
         */
        function provideDiapers() {
                return [
index 602a175..9e4dbea 100644 (file)
@@ -66,13 +66,13 @@ EOT
                $this->assertNotEquals(
                        '',
                        $this->updateText( $text ),
-                       'Bug 18609'
+                       'T20609'
                );
        }
 
        /**
         * @covers SearchUpdate::updateText
-        * Test bug 32712
+        * Test T34712
         * Test if unicode quotes in article links make its search index empty
         */
        public function testUnicodeLinkSearchIndexError() {
index 7e98d1c..a598d13 100644 (file)
@@ -50,7 +50,7 @@ class HttpTest extends MediaWikiTestCase {
 
        /**
         * Test Http::isValidURI()
-        * @bug 27854 : Http::isValidURI is too lax
+        * T29854 : Http::isValidURI is too lax
         * @dataProvider provideURI
         * @covers Http::isValidURI
         */
@@ -145,7 +145,7 @@ class HttpTest extends MediaWikiTestCase {
         *
         * These tests are for code that makes use of an artifact of how CURL
         * handles header reporting on redirect pages, and will need to be
-        * rewritten when bug 29232 is taken care of (high-level handling of
+        * rewritten when T31232 is taken care of (high-level handling of
         * HTTP redirects).
         */
        public function testRelativeRedirections() {
@@ -483,7 +483,7 @@ class HttpTest extends MediaWikiTestCase {
         * Added this test based on an issue experienced with HHVM 3.3.0-dev
         * where it did not define a cURL constant.
         *
-        * @bug 70570
+        * @T72570
         * @dataProvider provideCurlConstants
         */
        public function testCurlConstants( $value ) {
index 366714b..2e5c0bb 100644 (file)
@@ -54,7 +54,7 @@ class CSSMinTest extends MediaWikiTestCase {
                        [ "foo, bar {\n\tprop: value; /* comment */\n}", "foo,bar{prop:value; }" ],
 
                        // Keep track of things that aren't as minified as much as they
-                       // could be (bug 35493)
+                       // could be (T37493)
                        [ 'foo { prop: value ;}', 'foo{prop:value }' ],
                        [ 'foo { prop : value; }', 'foo{prop :value}' ],
                        [ 'foo { prop: value ; }', 'foo{prop:value }' ],
@@ -105,7 +105,7 @@ class CSSMinTest extends MediaWikiTestCase {
                                'foo { prop: url(http://example.org/bar.png); }',
                        ],
                        [
-                               'With trailing slash on remote (bug 27052)',
+                               'With trailing slash on remote (T29052)',
                                [ 'foo { prop: url(../bar.png); }', false, 'http://example.org/quux/', false ],
                                'foo { prop: url(http://example.org/bar.png); }',
                        ],
@@ -370,7 +370,7 @@ class CSSMinTest extends MediaWikiTestCase {
                                '{ background: /*asd*/ url(http://localhost/w/something.png); background: /*jkl*/ url(http://localhost/w/something.png); }',
                        ],
                        [
-                               'Sanity check for offending line from jquery.ui.theme.css (bug 60077)',
+                               'Sanity check for offending line from jquery.ui.theme.css (T62077)',
                                '.ui-state-default, .ui-widget-content .ui-state-default, .ui-widget-header .ui-state-default { border: 1px solid #d3d3d3/*{borderColorDefault}*/; background: #e6e6e6/*{bgColorDefault}*/ url(images/ui-bg_glass_75_e6e6e6_1x400.png)/*{bgImgUrlDefault}*/ 50%/*{bgDefaultXPos}*/ 50%/*{bgDefaultYPos}*/ repeat-x/*{bgDefaultRepeat}*/; font-weight: normal/*{fwDefault}*/; color: #555555/*{fcDefault}*/; }',
                                '.ui-state-default, .ui-widget-content .ui-state-default, .ui-widget-header .ui-state-default { border: 1px solid #d3d3d3/*{borderColorDefault}*/; background: #e6e6e6/*{bgColorDefault}*/ url(http://localhost/w/images/ui-bg_glass_75_e6e6e6_1x400.png)/*{bgImgUrlDefault}*/ 50%/*{bgDefaultXPos}*/ 50%/*{bgDefaultYPos}*/ repeat-x/*{bgDefaultRepeat}*/; font-weight: normal/*{fwDefault}*/; color: #555555/*{fcDefault}*/; }',
                        ],
@@ -418,7 +418,7 @@ class CSSMinTest extends MediaWikiTestCase {
        }
 
        /**
-        * Seperated because they are currently broken (bug 35492)
+        * Seperated because they are currently broken (T37492)
         *
         * @group Broken
         * @dataProvider provideStringCases
index 3787962..ca12f6c 100644 (file)
@@ -10,7 +10,7 @@ class JavaScriptMinifierTest extends PHPUnit_Framework_TestCase {
                        [ "/* Foo *\n*bar\n*/", "" ],
 
                        /**
-                        * Slashes used inside block comments (bug 26931).
+                        * Slashes used inside block comments (T28931).
                         * At some point there was a bug that caused this comment to be ended at '* /',
                         * causing /M... to be left as the beginning of a regex.
                         */
@@ -60,7 +60,7 @@ class JavaScriptMinifierTest extends PHPUnit_Framework_TestCase {
                        [ "5.3.\nx;", "5.3.x;" ],
 
                        // Semicolon insertion between an expression having an inline
-                       // comment after it, and a statement on the next line (bug 27046).
+                       // comment after it, and a statement on the next line (T29046).
                        [
                                "var a = this //foo bar \n for ( b = 0; c < d; b++ ) {}",
                                "var a=this\nfor(b=0;c<d;b++){}"
@@ -127,7 +127,7 @@ class JavaScriptMinifierTest extends PHPUnit_Framework_TestCase {
                        // newline insertion after 1000 chars: break after the "++", not before
                        [ str_repeat( ';', 996 ) . "if(x++);", str_repeat( ';', 996 ) . "if(x++\n);" ],
 
-                       // Unicode letter characters should pass through ok in identifiers (bug 31187)
+                       // Unicode letter characters should pass through ok in identifiers (T33187)
                        [ "var KaŝSkatolVal = {}", 'var KaŝSkatolVal={}' ],
 
                        // Per spec unicode char escape values should work in identifiers,
index 53a36c5..787d9a8 100644 (file)
@@ -52,7 +52,7 @@ class MimeMagicTest extends PHPUnit_Framework_TestCase {
 
        /**
         * Test to make sure that encoder=ffmpeg2theora doesn't trigger
-        * MEDIATYPE_VIDEO (bug 63584)
+        * MEDIATYPE_VIDEO (T65584)
         */
        function testOggRecognize() {
                $oggFile = __DIR__ . '/../../../data/media/say-test.ogg';
index 1677851..cd350e5 100644 (file)
@@ -3,7 +3,7 @@
 namespace Wikimedia\Tests\Rdbms;
 
 use IDatabase;
-use LoadBalancer;
+use Wikimedia\Rdbms\LoadBalancer;
 use PHPUnit_Framework_MockObject_MockObject;
 use Wikimedia\Rdbms\ConnectionManager;
 
index 0d54659..3b26d6f 100644 (file)
@@ -3,7 +3,7 @@
 namespace Wikimedia\Tests\Rdbms;
 
 use IDatabase;
-use LoadBalancer;
+use Wikimedia\Rdbms\LoadBalancer;
 use PHPUnit_Framework_MockObject_MockObject;
 use Wikimedia\Rdbms\SessionConsistentConnectionManager;
 
index ac52a39..9291eb6 100644 (file)
@@ -56,7 +56,7 @@ class XMPTest extends PHPUnit_Framework_TestCase  {
                        [ 'invalid-child-not-struct', 'Test child props not in struct or ignored' ],
                        [ 'no-recognized-props', 'Test namespace and no recognized props' ],
                        [ 'no-namespace', 'Test non-namespaced attributes are ignored' ],
-                       [ 'bag-for-seq', "Allow bag's instead of seq's. (bug 27105)" ],
+                       [ 'bag-for-seq', "Allow bag's instead of seq's. (T29105)" ],
                        [ 'utf16BE', 'UTF-16BE encoding' ],
                        [ 'utf16LE', 'UTF-16LE encoding' ],
                        [ 'utf32BE', 'UTF-32BE encoding' ],
index a21a3ff..c2b791e 100644 (file)
@@ -309,7 +309,7 @@ class LogFormatterTest extends MediaWikiLangTestCase {
 
        /**
         * The testIrcMsgForAction* tests are supposed to cover the hacky
-        * LogFormatter::getIRCActionText / bug 34508
+        * LogFormatter::getIRCActionText / T36508
         *
         * Third parties bots listen to those messages. They are clever enough
         * to fetch the i18n messages from the wiki and then analyze the IRC feed
index 3d0724f..e9fc84e 100644 (file)
@@ -33,7 +33,7 @@ class FormatMetadataTest extends MediaWikiMediaTestCase {
                $this->assertNotNull( $dateIndex, 'Date entry exists in metadata' );
                $this->assertEquals( '0000:01:00 00:02:27',
                        $meta['visible'][$dateIndex]['value'],
-                       'File with invalid date metadata (bug 29471)' );
+                       'File with invalid date metadata (T31471)' );
        }
 
        /**
index 3049e2f..9bfd5f6 100644 (file)
@@ -75,7 +75,7 @@ class SVGMetadataExtractorTest extends MediaWikiTestCase {
                        ],
                        [
                                "$base/Toll_Texas_1.svg",
-                               // This file triggered bug 31719, needs entity expansion in the xmlns checks
+                               // This file triggered T33719, needs entity expansion in the xmlns checks
                                [
                                        'width' => 385,
                                        'height' => 385,
index 3a3b514..34b2525 100644 (file)
@@ -5,7 +5,7 @@
  */
 class ArticleTablesTest extends MediaWikiLangTestCase {
        /**
-        * Make sure that bug 14404 doesn't strike again. We don't want
+        * Make sure that T16404 doesn't strike again. We don't want
         * templatelinks based on the user language when {{int:}} is used, only the
         * content language.
         *
@@ -13,7 +13,7 @@ class ArticleTablesTest extends MediaWikiLangTestCase {
         * @covers Title::getLinksFrom
         */
        public function testTemplatelinksUsesContentLanguage() {
-               $title = Title::newFromText( 'Bug 14404' );
+               $title = Title::newFromText( 'T16404' );
                $page = WikiPage::factory( $title );
                $user = new User();
                $user->mRights = [ 'createpage', 'edit', 'purge' ];
@@ -22,7 +22,7 @@ class ArticleTablesTest extends MediaWikiLangTestCase {
 
                $page->doEditContent(
                        new WikitextContent( '{{:{{int:history}}}}' ),
-                       'Test code for bug 14404',
+                       'Test code for T16404',
                        0,
                        false,
                        $user
@@ -35,7 +35,7 @@ class ArticleTablesTest extends MediaWikiLangTestCase {
                // We need an edit, a purge is not enough to regenerate the tables
                $page->doEditContent(
                        new WikitextContent( '{{:{{int:history}}}}' ),
-                       'Test code for bug 14404',
+                       'Test code for T16404',
                        EDIT_UPDATE,
                        false,
                        $user
index d12fee3..414ab8f 100644 (file)
@@ -51,7 +51,7 @@ class ParserPreloadTest extends MediaWikiTestCase {
                $this->assertPreloaded(
                        '<pre>monospaced</pre>',
                        '<pre>monospaced</pre>',
-                       '<pre> in preloaded text must be unstripped (bug 27467)'
+                       '<pre> in preloaded text must be unstripped (T29467)'
                );
        }
 
@@ -62,7 +62,7 @@ class ParserPreloadTest extends MediaWikiTestCase {
                $this->assertPreloaded(
                        '<nowiki>[[Dummy title]]</nowiki>',
                        '<nowiki>[[Dummy title]]</nowiki>',
-                       '<nowiki> in preloaded text must be unstripped (bug 27467)'
+                       '<nowiki> in preloaded text must be unstripped (T29467)'
                );
        }
 
index c491e6b..11a2197 100644 (file)
@@ -214,7 +214,7 @@ class PreprocessorTest extends MediaWikiTestCase {
                        [ "Factorial" ], # https://en.wikipedia.org/w/index.php?title=Template:Factorial&oldid=98548758 GFDL + CC BY-SA by Polonium
                        [ "All_system_messages" ], # https://tl.wiktionary.org/w/index.php?title=Suleras:All_system_messages&oldid=2765 GPL text generated by MediaWiki
                        [ "Fundraising" ], # https://tl.wiktionary.org/w/index.php?title=MediaWiki:Sitenotice&oldid=5716 GFDL + CC BY-SA, copied there by Sky Harbor.
-                       [ "NestedTemplates" ], # bug 27936
+                       [ "NestedTemplates" ], # T29936
                ] );
                // @codingStandardsIgnoreEnd
        }
index cde1e5a..e0a82d0 100644 (file)
@@ -18,6 +18,7 @@ class ResourceLoaderTest extends ResourceLoaderTestCase {
                        // to avoid notices during testMakeModuleResponse for missing
                        // wgResourceLoaderLESSVars keys in extension hooks.
                        'wgHooks' => [],
+                       'wgShowExceptionDetails' => true,
                ] );
        }
 
index a88264b..6833893 100644 (file)
@@ -230,7 +230,7 @@ class SearchEnginePrefixTest extends MediaWikiLangTestCase {
                                ],
                        ] ],
                        [ [
-                               'Exact match not on top (bug 70958)',
+                               'Exact match not on top (T72958)',
                                'provision' => [
                                        'Barcelona',
                                        'Bar',
@@ -244,7 +244,7 @@ class SearchEnginePrefixTest extends MediaWikiLangTestCase {
                                ],
                        ] ],
                        [ [
-                               'Exact match missing (bug 70958)',
+                               'Exact match missing (T72958)',
                                'provision' => [
                                        'Barcelona',
                                        'Barbara',
index 074045d..9c71261 100644 (file)
@@ -14,7 +14,7 @@ class SpecialBooksourcesTest extends SpecialPageTestBase {
                        [ '9780136091817', false ],
                        [ '123456789X', true ],
 
-                       // Bug 67021
+                       // T69021
                        [ '1413304541', false ],
                        [ '141330454X', false ],
                        [ '1413304540', true ],
index ab92aee..9b0fb6a 100644 (file)
@@ -101,7 +101,7 @@ class SpecialRecentchangesTest extends MediaWikiTestCase {
        }
 
        /**
-        * @bug 2429
+        * T4429
         * @dataProvider provideNamespacesAssociations
         */
        public function testRcNsFilterAssociation( $ns1, $ns2 ) {
@@ -120,7 +120,7 @@ class SpecialRecentchangesTest extends MediaWikiTestCase {
        }
 
        /**
-        * @bug 2429
+        * T4429
         * @dataProvider provideNamespacesAssociations
         */
        public function testRcNsFilterAssociationWithInversion( $ns1, $ns2 ) {
index 13c21c0..9daae97 100644 (file)
@@ -73,7 +73,7 @@ class SpecialSearchTest extends MediaWikiTestCase {
                        [
                                $EMPTY_REQUEST, $NO_USER_PREF,
                                'default', $defaultNS,
-                               'Bug 33270: No request nor user preferences should give default profile'
+                               'T35270: No request nor user preferences should give default profile'
                        ],
                        [
                                [ 'ns5' => 1 ], $NO_USER_PREF,
@@ -88,7 +88,7 @@ class SpecialSearchTest extends MediaWikiTestCase {
                                return "searchNs$ns";
                        }, $defaultNS ), 0 ),
                                'advanced', [ 2, 14 ],
-                               'Bug 33583: search with no option should honor User search preferences'
+                               'T35583: search with no option should honor User search preferences'
                                        . ' and have all other namespace disabled'
                        ],
                ];
index 6be272f..a42c86c 100644 (file)
@@ -297,31 +297,31 @@ class UploadBaseTest extends MediaWikiTestCase {
                                '<?xml version="1.0" encoding="UTF-8" standalone="no"?> <svg xmlns:xlink="http://www.w3.org/1999/xlink"> <image xlink:href="https://upload.wikimedia.org/wikipedia/commons/3/34/Bahnstrecke_Zeitz-Camburg_1930.png" /> </svg>',
                                true,
                                true,
-                               'SVG with non-local image href (bug 65839)'
+                               'SVG with non-local image href (T67839)'
                        ],
                        [
                                '<?xml version="1.0" ?> <?xml-stylesheet type="text/xsl" href="/w/index.php?title=User:Jeeves/test.xsl&amp;action=raw&amp;format=xml" ?> <svg> <height>50</height> <width>100</width> </svg>',
                                true,
                                true,
-                               'SVG with remote stylesheet (bug 57550)'
+                               'SVG with remote stylesheet (T59550)'
                        ],
                        [
                                '<svg xmlns="http://www.w3.org/2000/svg" viewbox="-1 -1 15 15"> <rect y="0" height="13" width="12" stroke="#179" rx="1" fill="#2ac"/> <text x="1.5" y="11" font-family="courier" stroke="white" font-size="16"><![CDATA[B]]></text> <iframe xmlns="http://www.w3.org/1999/xhtml" srcdoc="&#x3C;&#x73;&#x63;&#x72;&#x69;&#x70;&#x74;&#x3E;&#x61;&#x6C;&#x65;&#x72;&#x74;&#x28;&#x27;&#x58;&#x53;&#x53;&#x45;&#x44;&#x20;&#x3D;&#x3E;&#x20;&#x44;&#x6F;&#x6D;&#x61;&#x69;&#x6E;&#x28;&#x27;&#x2B;&#x74;&#x6F;&#x70;&#x2E;&#x64;&#x6F;&#x63;&#x75;&#x6D;&#x65;&#x6E;&#x74;&#x2E;&#x64;&#x6F;&#x6D;&#x61;&#x69;&#x6E;&#x2B;&#x27;&#x29;&#x27;&#x29;&#x3B;&#x3C;&#x2F;&#x73;&#x63;&#x72;&#x69;&#x70;&#x74;&#x3E;"></iframe> </svg>',
                                true,
                                true,
-                               'SVG with rembeded iframe (bug 60771)'
+                               'SVG with rembeded iframe (T62771)'
                        ],
                        [
                                '<svg xmlns="http://www.w3.org/2000/svg" viewBox="6 3 177 153" xmlns:xlink="http://www.w3.org/1999/xlink"> <style>@import url("https://fonts.googleapis.com/css?family=Bitter:700&amp;text=WebPlatform.org");</style> <g transform="translate(-.5,-.5)"> <text fill="#474747" x="95" y="150" text-anchor="middle" font-family="Bitter" font-size="20" font-weight="bold">WebPlatform.org</text> </g> </svg>',
                                true,
                                true,
-                               'SVG with @import in style element (bug 69008)'
+                               'SVG with @import in style element (T71008)'
                        ],
                        [
                                '<svg xmlns="http://www.w3.org/2000/svg" viewBox="6 3 177 153" xmlns:xlink="http://www.w3.org/1999/xlink"> <style>@import url("https://fonts.googleapis.com/css?family=Bitter:700&amp;text=WebPlatform.org");<foo/></style> <g transform="translate(-.5,-.5)"> <text fill="#474747" x="95" y="150" text-anchor="middle" font-family="Bitter" font-size="20" font-weight="bold">WebPlatform.org</text> </g> </svg>',
                                true,
                                true,
-                               'SVG with @import in style element and child element (bug 69008#c11)'
+                               'SVG with @import in style element and child element (T71008#c11)'
                        ],
                        [
                                '<svg xmlns="http://www.w3.org/2000/svg" viewBox="6 3 177 153" xmlns:xlink="http://www.w3.org/1999/xlink"> <style>@imporT "https://fonts.googleapis.com/css?family=Bitter:700&amp;text=WebPlatform.org";</style> <g transform="translate(-.5,-.5)"> <text fill="#474747" x="95" y="150" text-anchor="middle" font-family="Bitter" font-size="20" font-weight="bold">WebPlatform.org</text> </g> </svg>',
@@ -333,19 +333,19 @@ class UploadBaseTest extends MediaWikiTestCase {
                                '<svg xmlns="http://www.w3.org/2000/svg"> <rect width="100" height="100" style="background-image:url(https://www.google.com/images/srpr/logo11w.png)"/> </svg>',
                                true,
                                true,
-                               'SVG with remote background image (bug 69008)'
+                               'SVG with remote background image (T71008)'
                        ],
                        [
                                '<svg xmlns="http://www.w3.org/2000/svg"> <rect width="100" height="100" style="background-image:\55rl(https://www.google.com/images/srpr/logo11w.png)"/> </svg>',
                                true,
                                true,
-                               'SVG with remote background image, encoded (bug 69008)'
+                               'SVG with remote background image, encoded (T71008)'
                        ],
                        [
                                '<svg xmlns="http://www.w3.org/2000/svg"> <style> #a { background-image:\55rl(\'https://www.google.com/images/srpr/logo11w.png\'); } </style> <rect width="100" height="100" id="a"/> </svg>',
                                true,
                                true,
-                               'SVG with remote background image, in style element (bug 69008)'
+                               'SVG with remote background image, in style element (T71008)'
                        ],
                        [
                                // This currently doesn't seem to work in any browsers, but in case
@@ -353,7 +353,7 @@ class UploadBaseTest extends MediaWikiTestCase {
                                '<svg xmlns="http://www.w3.org/2000/svg"> <rect width="100" height="100" style="background-image:image(\'sprites.svg#xywh=40,0,20,20\')"/> </svg>',
                                true,
                                true,
-                               'SVG with remote background image using image() (bug 69008)'
+                               'SVG with remote background image using image() (T71008)'
                        ],
                        [
                                // As reported by Cure53
index 9b25505..7c40a2d 100644 (file)
@@ -19,7 +19,7 @@ class UploadStashTest extends MediaWikiTestCase {
        protected function setUp() {
                parent::setUp();
 
-               // Setup a file for bug 29408
+               // Setup a file for T31408
                $this->bug29408File = wfTempDir() . '/bug29408';
                file_put_contents( $this->bug29408File, "\x00" );
 
@@ -62,7 +62,7 @@ class UploadStashTest extends MediaWikiTestCase {
 
                // Throws exception caught by PHPUnit on failure
                $file = $stash->stashFile( $this->bug29408File );
-               // We'll never reach this point if we hit bug 29408
+               // We'll never reach this point if we hit T31408
                $this->assertTrue( true, 'Unrecognized file without extension' );
 
                $stash->removeFile( $file->getFileKey() );
index deb9708..fea4a44 100644 (file)
@@ -362,7 +362,7 @@ class UserTest extends MediaWikiTestCase {
        }
 
        /**
-        * Bug 37963
+        * T39963
         * Make sure defaults are loaded when setOption is called.
         * @covers User::loadOptions
         */
@@ -862,4 +862,75 @@ class UserTest extends MediaWikiTestCase {
                // Clean up.
                $block->delete();
        }
+
+       public function testIsPingLimitable() {
+               $request = new FauxRequest();
+               $request->setIP( '1.2.3.4' );
+               $user = User::newFromSession( $request );
+
+               $this->setMwGlobals( 'wgRateLimitsExcludedIPs', [] );
+               $this->assertTrue( $user->isPingLimitable() );
+
+               $this->setMwGlobals( 'wgRateLimitsExcludedIPs', [ '1.2.3.4' ] );
+               $this->assertFalse( $user->isPingLimitable() );
+
+               $this->setMwGlobals( 'wgRateLimitsExcludedIPs', [ '1.2.3.0/8' ] );
+               $this->assertFalse( $user->isPingLimitable() );
+
+               $this->setMwGlobals( 'wgRateLimitsExcludedIPs', [] );
+               $noRateLimitUser = $this->getMockBuilder( User::class )->disableOriginalConstructor()
+                       ->setMethods( [ 'getIP', 'getRights' ] )->getMock();
+               $noRateLimitUser->expects( $this->any() )->method( 'getIP' )->willReturn( '1.2.3.4' );
+               $noRateLimitUser->expects( $this->any() )->method( 'getRights' )->willReturn( [ 'noratelimit' ] );
+               $this->assertFalse( $noRateLimitUser->isPingLimitable() );
+       }
+
+       public function provideExperienceLevel() {
+               return [
+                       [ 2, 2, 'newcomer' ],
+                       [ 12, 3, 'newcomer' ],
+                       [ 8, 5, 'newcomer' ],
+                       [ 15, 10, 'learner' ],
+                       [ 450, 20, 'learner' ],
+                       [ 460, 33, 'learner' ],
+                       [ 525, 28, 'learner' ],
+                       [ 538, 33, 'experienced' ],
+               ];
+       }
+
+       /**
+        * @dataProvider provideExperienceLevel
+        */
+       public function testExperienceLevel( $editCount, $memberSince, $expLevel ) {
+               $this->setMwGlobals( [
+                       'wgLearnerEdits' => 10,
+                       'wgLearnerMemberSince' => 4,
+                       'wgExperiencedUserEdits' => 500,
+                       'wgExperiencedUserMemberSince' => 30,
+               ] );
+
+               $db = wfGetDB( DB_MASTER );
+
+               $data = new stdClass();
+               $data->user_id = 1;
+               $data->user_name = 'name';
+               $data->user_real_name = 'Real Name';
+               $data->user_touched = 1;
+               $data->user_token = 'token';
+               $data->user_email = 'a@a.a';
+               $data->user_email_authenticated = null;
+               $data->user_email_token = 'token';
+               $data->user_email_token_expires = null;
+               $data->user_editcount = $editCount;
+               $data->user_registration = $db->timestamp( time() - $memberSince * 86400 );
+               $user = User::newFromRow( $data );
+
+               $this->assertEquals( $expLevel, $user->getExperienceLevel() );
+       }
+
+       public function testExperienceLevelAnon() {
+               $user = User::newFromName( '10.11.12.13', false );
+
+               $this->assertFalse( $user->getExperienceLevel() );
+       }
 }
diff --git a/tests/phpunit/includes/utils/ClassCollectorTest.php b/tests/phpunit/includes/utils/ClassCollectorTest.php
new file mode 100644 (file)
index 0000000..e8a228e
--- /dev/null
@@ -0,0 +1,48 @@
+<?php
+
+/**
+ * @covers ClassCollector
+ */
+class ClassCollectorTest extends PHPUnit_Framework_TestCase {
+
+       public static function provideCases() {
+               return [
+                       [
+                               "class Foo {}",
+                               [ 'Foo' ],
+                       ],
+                       [
+                               "namespace Example;\nclass Foo {}\nclass Bar {}",
+                               [ 'Example\Foo', 'Example\Bar' ],
+                       ],
+                       [
+                               "class_alias( 'Foo', 'Bar' );",
+                               [ 'Bar' ],
+                       ],
+                       [
+                               "namespace Example;\nclass Foo {}\nclass_alias( 'Example\Foo', 'Foo' );",
+                               [ 'Example\Foo', 'Foo' ],
+                       ],
+                       [
+                               "namespace Example;\nclass Foo {}\nclass_alias( 'Example\Foo', 'Bar' );",
+                               [ 'Example\Foo', 'Bar' ],
+                       ],
+                       [
+                               "class_alias( Foo::class, 'Bar' );",
+                               [ 'Bar' ],
+                       ],
+                       [
+                               "namespace Example;\nclass Foo {}\nclass_alias( Foo::class, 'Bar' );",
+                               [ 'Example\Foo', 'Bar' ],
+                       ],
+               ];
+       }
+
+       /**
+        * @dataProvider provideCases
+        */
+       public function testGetClasses( $code, array $classes, $message = null ) {
+               $cc = new ClassCollector();
+               $this->assertEquals( $classes, $cc->getClasses( "<?php\n$code" ), $message );
+       }
+}
index 88bab90..22fd7b8 100644 (file)
@@ -1337,7 +1337,7 @@ class LanguageTest extends LanguageClassesTestCase {
                                        "Acteur%7CAlbert%20Robbins%7CAnglais%7CAnn%20Donahue%7CAnthony%20E.%20Zuiker%7CCarol%20Mendelsohn"
                                )
                        ],
-                       // The following two data sets come from bug 36839. They fail if checkTitleEncoding uses a regexp to test for
+                       // The following two data sets come from T38839. They fail if checkTitleEncoding uses a regexp to test for
                        // valid UTF-8 encoding and the pcre.recursion_limit is low (like, say, 1024). They succeed if checkTitleEncoding
                        // uses mb_check_encoding for its test.
                        [
index 37c8fe0..26db106 100644 (file)
@@ -15,19 +15,19 @@ class LanguageBe_taraskTest extends LanguageClassesTestCase {
        }
 
        /**
-        * @see bug 23156 & r64981
+        * @see T25156 & r64981
         * @covers Language::commafy
         */
        public function testSearchRightSingleQuotationMarkAsApostroph() {
                $this->assertEquals(
                        "'",
                        $this->getLang()->normalizeForSearch( '’' ),
-                       'bug 23156: U+2019 conversion to U+0027'
+                       'T25156: U+2019 conversion to U+0027'
                );
        }
 
        /**
-        * @see bug 23156 & r64981
+        * @see T25156 & r64981
         * @covers Language::commafy
         */
        public function testCommafy() {
@@ -36,7 +36,7 @@ class LanguageBe_taraskTest extends LanguageClassesTestCase {
        }
 
        /**
-        * @see bug 23156 & r64981
+        * @see T25156 & r64981
         * @covers Language::commafy
         */
        public function testDoesNotCommafyFourDigitsNumber() {
index 5eacd88..6bac031 100644 (file)
@@ -10,7 +10,7 @@ class LanguageMlTest extends LanguageClassesTestCase {
 
        /**
         * @dataProvider providerFormatNum
-        * @see bug 29495
+        * T31495
         * @covers Language::formatNum
         */
        public function testFormatNum( $result, $value ) {
index 9a1823b..28d71df 100644 (file)
@@ -9,7 +9,7 @@
 class LanguageTrTest extends LanguageClassesTestCase {
 
        /**
-        * See @bug 28040
+        * See T30040
         * Credits to irc://irc.freenode.net/wikipedia-tr users:
         *  - berm
         *  - []LuCkY[]
@@ -48,7 +48,7 @@ class LanguageTrTest extends LanguageClassesTestCase {
                        [ 'lcfirst', 'ı', 'lower', 'ı' ],
                        [ 'lcfirst', 'i', 'lower', 'i' ],
 
-                       # A real example taken from bug 28040 using
+                       # A real example taken from T30040 using
                        # https://tr.wikipedia.org/wiki/%C4%B0Phone
                        [ 'lcfirst', 'iPhone', 'lower', 'iPhone' ],
 
index b3f8e3e..2c5931d 100644 (file)
@@ -22,7 +22,7 @@ class BaseDumpTest extends MediaWikiTestCase {
                        $this->dump->close();
                }
 
-               // Bug 37458, parent teardown need to be done after closing the
+               // T39458, parent teardown need to be done after closing the
                // dump or it might cause some permissions errors.
                parent::tearDown();
        }
index 6797f59..8ee45a8 100644 (file)
@@ -40,7 +40,7 @@ class MockFSFile extends FSFile {
 
        /**
         * August 22 – The theft of the Mona Lisa is discovered in the Louvre."
-        * @bug 20281
+        * T22281
         */
        public function getSize() {
                return 1911;
index aaa1feb..af03fe6 100644 (file)
@@ -123,7 +123,7 @@ class SideBarTest extends MediaWikiLangTestCase {
        }
 
        /**
-        * bug 33321 - Make sure there's a | after transforming.
+        * T35321 - Make sure there's a | after transforming.
         * @group Database
         * @covers SkinTemplate::addToSidebarPlain
         */
index f36b51a..d81e8c6 100644 (file)
@@ -68,6 +68,7 @@ class AutoLoaderTest extends MediaWikiTestCase {
                        }
 
                        // We could use token_get_all() here, but this is faster
+                       // Note: Keep in sync with ClassCollector
                        $matches = [];
                        preg_match_all( '/
                                ^ [\t ]* (?:
@@ -78,6 +79,11 @@ class AutoLoaderTest extends MediaWikiTestCase {
                                                ([\'"]) (?P<original> [^\'"]+) \g{-2} \s* , \s*
                                                ([\'"]) (?P<alias> [^\'"]+ ) \g{-2} \s*
                                        \) \s* ;
+                               |
+                                       class_alias \s* \( \s*
+                                               (?P<originalStatic> [a-zA-Z0-9_]+)::class \s* , \s*
+                                               ([\'"]) (?P<aliasString> [^\'"]+ ) \g{-2} \s*
+                                       \) \s* ;
                                )
                        /imx', $contents, $matches, PREG_SET_ORDER );
 
@@ -95,11 +101,18 @@ class AutoLoaderTest extends MediaWikiTestCase {
 
                        foreach ( $matches as $match ) {
                                if ( !empty( $match['class'] ) ) {
+                                       // 'class Foo {}'
                                        $class = $fileNamespace . $match['class'];
                                        $actual[$class] = $file;
                                        $classesInFile[$class] = true;
                                } else {
-                                       $aliasesInFile[$match['alias']] = $match['original'];
+                                       if ( !empty( $match['original'] ) ) {
+                                               // 'class_alias( "Foo", "Bar" );'
+                                               $aliasesInFile[$match['alias']] = $match['original'];
+                                       } else {
+                                               // 'class_alias( Foo::class, "Bar" );'
+                                               $aliasesInFile[$match['aliasString']] = $fileNamespace . $match['originalStatic'];
+                                       }
                                }
                        }
 
diff --git a/tests/qunit/.eslintrc.json b/tests/qunit/.eslintrc.json
new file mode 100644 (file)
index 0000000..b3a46f4
--- /dev/null
@@ -0,0 +1,14 @@
+{
+       "extends": "../../.eslintrc.json",
+       "env": {
+               "qunit": true
+       },
+       "globals": {
+               "sinon": false
+       },
+       "rules": {
+               "operator-linebreak": 0,
+               "quote-props": [ "error", "as-needed" ],
+               "valid-jsdoc": 0
+       }
+}
index 5a96dc3..1c79f6d 100644 (file)
@@ -16,7 +16,7 @@
 /*
  * @example QUnit
  * <code>
-       QUnit.test( 'Output matches PHP parser', mw.libs.phpParserData.tests.length, function ( assert ) {
+       QUnit.test( 'Output matches PHP parser', function ( assert ) {
                mw.messages.set( mw.libs.phpParserData.messages );
                $.each( mw.libs.phpParserData.tests, function ( i, test ) {
                        QUnit.stop();
@@ -133,7 +133,7 @@ class GenerateJqueryMsgData extends Maintenance {
                                . "// languages, and parser modes. Intended for use by a unit test framework by looping\n"
                                . "// through the object and comparing its parser return value with the 'result' property.\n"
                                . '// Last generated with ' . basename( __FILE__ ) . ' at ' . gmdate( 'r' ) . "\n"
-                               . "//jscs:disable\n"
+                               . "/* eslint-disable */\n"
                                . "\n"
                                . 'mediaWiki.libs.phpParserData = ' . FormatJson::encode( $phpParserData, true ) . ";\n";
 
index 498acc1..90dc1b2 100644 (file)
@@ -2,7 +2,7 @@
 // languages, and parser modes. Intended for use by a unit test framework by looping
 // through the object and comparing its parser return value with the 'result' property.
 // Last generated with generateJqueryMsgData.php at Fri, 10 Jul 2015 11:44:08 +0000
-//jscs:disable
+/* eslint-disable */
 
 mediaWiki.libs.phpParserData = {
     "messages": {
index 0b28684..cef5c15 100644 (file)
@@ -1,8 +1,8 @@
-/*global CompletenessTest, sinon */
+/* global CompletenessTest, sinon */
 ( function ( $, mw, QUnit ) {
        'use strict';
 
-       var mwTestIgnore, mwTester, addons;
+       var mwTestIgnore, addons;
 
        /**
         * Add bogus to url to prevent IE crazy caching
@@ -26,6 +26,7 @@
        QUnit.config.testTimeout = 60 * 1000;
 
        // Reduce default animation duration from 400ms to 0ms for unit tests
+       // eslint-disable-next-line no-underscore-dangle
        $.fx.speeds._default = 0;
 
        // Add a checkbox to QUnit header to toggle MediaWiki ResourceLoader debug mode.
                        return false;
                };
 
-               mwTester = new CompletenessTest( mw, mwTestIgnore );
+               // eslint-disable-next-line no-new
+               new CompletenessTest( mw, mwTestIgnore );
        }
 
        /**
                }
 
                function freshMessagesCopy( custom ) {
-                       return $.extend( /*deep=*/true, {}, liveMessages.get(), custom );
+                       return $.extend( /* deep */true, {}, liveMessages.get(), custom );
                }
 
                /**
                }
        } ) );
 
-       QUnit.test( 'Setup', 3, function ( assert ) {
+       QUnit.test( 'Setup', function ( assert ) {
                assert.equal( mw.html.escape( 'foo' ), 'mocked', 'setup() callback was ran.' );
                assert.equal( mw.config.get( 'testVar' ), 'foo', 'config object applied' );
                assert.equal( mw.messages.get( 'testMsg' ), 'Foo.', 'messages object applied' );
                mw.messages.set( 'testMsg', 'Bar.' );
        } );
 
-       QUnit.test( 'Teardown', 2, function ( assert ) {
+       QUnit.test( 'Teardown', function ( assert ) {
                assert.equal( mw.config.get( 'testVar' ), 'foo', 'config object restored and re-applied after test()' );
                assert.equal( mw.messages.get( 'testMsg' ), 'Foo.', 'messages object restored and re-applied after test()' );
        } );
 
-       QUnit.test( 'Loader status', 2, function ( assert ) {
+       QUnit.test( 'Loader status', function ( assert ) {
                var i, len, state,
                        modules = mw.loader.getModuleNames(),
                        error = [],
                assert.deepEqual( missing, [], 'Modules in missing state' );
        } );
 
-       QUnit.test( 'htmlEqual', 8, function ( assert ) {
+       QUnit.test( 'htmlEqual', function ( assert ) {
                assert.htmlEqual(
                        '<div><p class="some classes" data-length="10">Child paragraph with <a href="http://example.com">A link</a></p>Regular text<span>A span</span></div>',
                        '<div><p data-length=\'10\'  class=\'some classes\'>Child paragraph with <a href=\'http://example.com\' >A link</a></p>Regular text<span>A span</span></div>',
 
        QUnit.module( 'test.mediawiki.qunit.testrunner-after', QUnit.newMwEnvironment() );
 
-       QUnit.test( 'Teardown', 3, function ( assert ) {
+       QUnit.test( 'Teardown', function ( assert ) {
                assert.equal( mw.html.escape( '<' ), '&lt;', 'teardown() callback was ran.' );
                assert.equal( mw.config.get( 'testVar' ), null, 'config object restored to live in next module()' );
                assert.equal( mw.messages.get( 'testMsg' ), null, 'messages object restored to live in next module()' );
index 0fb7d9a..e4b6157 100644 (file)
@@ -1,4 +1,6 @@
 ( function ( $ ) {
+       var getAccessKeyPrefixTestData, updateTooltipAccessKeysTestData;
+
        QUnit.module( 'jquery.accessKeyLabel', QUnit.newMwEnvironment( {
                messages: {
                        brackets: '[$1]',
@@ -6,47 +8,47 @@
                }
        } ) );
 
-       var getAccessKeyPrefixTestData = [
-                       // ua string, platform string, expected prefix
-                       // Internet Explorer
-                       [ 'Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1)', 'Win32', 'alt-' ],
-                       [ 'Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.1; Trident/6.0)', 'Win32', 'alt-' ],
-                       [ 'Mozilla/5.0 (Windows NT 6.3; Win64; x64; Trident/7.0; rv:11.0) like Gecko', 'Win64', 'alt-' ],
-                       [ 'Mozilla/5.0 (Windows NT 10.0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/42.0.2311.135 Safari/537.36 Edge/12.10136', 'Win64', 'alt-' ],
-                       // Firefox
-                       [ 'Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.5; en-US; rv:1.9.1.19) Gecko/20110420 Firefox/3.5.19', 'MacIntel', 'ctrl-' ],
-                       [ 'Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.2.17) Gecko/20110422 Ubuntu/10.10 (maverick) Firefox/3.6.17', 'Linux i686', 'alt-shift-' ],
-                       [ 'Mozilla/5.0 (Windows NT 6.0; rv:2.0.1) Gecko/20100101 Firefox/4.0.1', 'Win32', 'alt-shift-' ],
-                       [ 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10.12; rv:50.0) Gecko/20100101 Firefox/50.0', 'MacIntel', 'ctrl-option-' ],
-                       [ 'Mozilla/5.0 (X11; Linux x86_64; rv:17.0) Gecko/20121202 Firefox/17.0 Iceweasel/17.0.1', 'Linux 1686', 'alt-shift-' ],
-                       [ 'Mozilla/5.0 (Windows NT 5.2; U; de; rv:1.8.0) Gecko/20060728 Firefox/1.5.0', 'Win32', 'alt-' ],
-                       // Safari / Konqueror
-                       [ 'Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_6_7; nl-nl) AppleWebKit/531.22.7 (KHTML, like Gecko) Version/4.0.5 Safari/531.22.7', 'MacIntel', 'ctrl-option-' ],
-                       [ 'Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_5_7; de-de) AppleWebKit/525.28.3 (KHTML, like Gecko) Version/3.2.3 Safari/525.28.3', 'MacIntel', 'ctrl-' ],
-                       [ 'Mozilla/5.0 (Windows; U; Windows NT 5.1; cs-CZ) AppleWebKit/525.28.3 (KHTML, like Gecko) Version/3.2.3 Safari/525.29', 'Win32', 'alt-' ],
-                       [ 'Mozilla/5.0 (Windows; U; Windows NT 6.0; cs-CZ) AppleWebKit/533.21.1 (KHTML, like Gecko) Version/4.0.5 Safari/531.22.7', 'Win32', 'alt-' ],
-                       [ 'Mozilla/5.0 (X11; Linux i686) KHTML/4.9.1 (like Gecko) Konqueror/4.9', 'Linux i686', 'ctrl-' ],
-                       // Opera
-                       [ 'Opera/9.80 (Windows NT 5.1)', 'Win32', 'shift-esc-' ],
-                       [ 'Mozilla/5.0 (Windows NT 5.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/28.0.1500.52 Safari/537.36 OPR/15.0.1147.130', 'Win32', 'alt-shift-' ],
-                       // Chrome
-                       [ 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_5_8) AppleWebKit/534.30 (KHTML, like Gecko) Chrome/12.0.742.112 Safari/534.30', 'MacIntel', 'ctrl-option-' ],
-                       [ 'Mozilla/5.0 (X11; Linux i686) AppleWebKit/534.30 (KHTML, like Gecko) Chrome/12.0.742.68 Safari/534.30', 'Linux i686', 'alt-shift-' ],
-                       // Unknown! Note: These aren't necessarily *right*, this is just
-                       // testing that we're getting the expected output based on the
-                       // platform.
-                       [ 'Mozilla/5.0 (Macintosh; U; PPC Mac OS X; en-US; rv:1.0.1) Gecko/20021111 Chimera/0.6', 'MacPPC', 'ctrl-' ],
-                       [ 'Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.3a) Gecko/20021207 Phoenix/0.5', 'Linux i686', 'alt-' ]
-               ],
-               // strings appended to title to make sure updateTooltipAccessKeys handles them correctly
-               updateTooltipAccessKeysTestData = [ '', ' [a]', ' [test-a]', ' [alt-b]' ];
+       getAccessKeyPrefixTestData = [
+               // ua string, platform string, expected prefix
+               // Internet Explorer
+               [ 'Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1)', 'Win32', 'alt-' ],
+               [ 'Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.1; Trident/6.0)', 'Win32', 'alt-' ],
+               [ 'Mozilla/5.0 (Windows NT 6.3; Win64; x64; Trident/7.0; rv:11.0) like Gecko', 'Win64', 'alt-' ],
+               [ 'Mozilla/5.0 (Windows NT 10.0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/42.0.2311.135 Safari/537.36 Edge/12.10136', 'Win64', 'alt-' ],
+               // Firefox
+               [ 'Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.5; en-US; rv:1.9.1.19) Gecko/20110420 Firefox/3.5.19', 'MacIntel', 'ctrl-' ],
+               [ 'Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.2.17) Gecko/20110422 Ubuntu/10.10 (maverick) Firefox/3.6.17', 'Linux i686', 'alt-shift-' ],
+               [ 'Mozilla/5.0 (Windows NT 6.0; rv:2.0.1) Gecko/20100101 Firefox/4.0.1', 'Win32', 'alt-shift-' ],
+               [ 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10.12; rv:50.0) Gecko/20100101 Firefox/50.0', 'MacIntel', 'ctrl-option-' ],
+               [ 'Mozilla/5.0 (X11; Linux x86_64; rv:17.0) Gecko/20121202 Firefox/17.0 Iceweasel/17.0.1', 'Linux 1686', 'alt-shift-' ],
+               [ 'Mozilla/5.0 (Windows NT 5.2; U; de; rv:1.8.0) Gecko/20060728 Firefox/1.5.0', 'Win32', 'alt-' ],
+               // Safari / Konqueror
+               [ 'Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_6_7; nl-nl) AppleWebKit/531.22.7 (KHTML, like Gecko) Version/4.0.5 Safari/531.22.7', 'MacIntel', 'ctrl-option-' ],
+               [ 'Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_5_7; de-de) AppleWebKit/525.28.3 (KHTML, like Gecko) Version/3.2.3 Safari/525.28.3', 'MacIntel', 'ctrl-' ],
+               [ 'Mozilla/5.0 (Windows; U; Windows NT 5.1; cs-CZ) AppleWebKit/525.28.3 (KHTML, like Gecko) Version/3.2.3 Safari/525.29', 'Win32', 'alt-' ],
+               [ 'Mozilla/5.0 (Windows; U; Windows NT 6.0; cs-CZ) AppleWebKit/533.21.1 (KHTML, like Gecko) Version/4.0.5 Safari/531.22.7', 'Win32', 'alt-' ],
+               [ 'Mozilla/5.0 (X11; Linux i686) KHTML/4.9.1 (like Gecko) Konqueror/4.9', 'Linux i686', 'ctrl-' ],
+               // Opera
+               [ 'Opera/9.80 (Windows NT 5.1)', 'Win32', 'shift-esc-' ],
+               [ 'Mozilla/5.0 (Windows NT 5.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/28.0.1500.52 Safari/537.36 OPR/15.0.1147.130', 'Win32', 'alt-shift-' ],
+               // Chrome
+               [ 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_5_8) AppleWebKit/534.30 (KHTML, like Gecko) Chrome/12.0.742.112 Safari/534.30', 'MacIntel', 'ctrl-option-' ],
+               [ 'Mozilla/5.0 (X11; Linux i686) AppleWebKit/534.30 (KHTML, like Gecko) Chrome/12.0.742.68 Safari/534.30', 'Linux i686', 'alt-shift-' ],
+               // Unknown! Note: These aren't necessarily *right*, this is just
+               // testing that we're getting the expected output based on the
+               // platform.
+               [ 'Mozilla/5.0 (Macintosh; U; PPC Mac OS X; en-US; rv:1.0.1) Gecko/20021111 Chimera/0.6', 'MacPPC', 'ctrl-' ],
+               [ 'Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.3a) Gecko/20021207 Phoenix/0.5', 'Linux i686', 'alt-' ]
+       ];
+       // strings appended to title to make sure updateTooltipAccessKeys handles them correctly
+       updateTooltipAccessKeysTestData = [ '', ' [a]', ' [test-a]', ' [alt-b]' ];
 
        function makeInput( title, accessKey ) {
                // The properties aren't escaped, so make sure you don't call this function with values that need to be escaped!
                return '<input title="' + title + '" ' + ( accessKey ? 'accessKey="' + accessKey + '" ' : '' ) + ' />';
        }
 
-       QUnit.test( 'getAccessKeyPrefix', getAccessKeyPrefixTestData.length, function ( assert ) {
+       QUnit.test( 'getAccessKeyPrefix', function ( assert ) {
                var i;
                for ( i = 0; i < getAccessKeyPrefixTestData.length; i++ ) {
                        assert.equal( $.fn.updateTooltipAccessKeys.getAccessKeyPrefix( {
@@ -56,7 +58,7 @@
                }
        } );
 
-       QUnit.test( 'updateTooltipAccessKeys - current browser', 2, function ( assert ) {
+       QUnit.test( 'updateTooltipAccessKeys - current browser', function ( assert ) {
                var title = $( makeInput( 'Title', 'a' ) ).updateTooltipAccessKeys().prop( 'title' ),
                        // The new title should be something like "Title [alt-a]", but the exact label will depend on the browser.
                        // The "a" could be capitalized, and the prefix could be anything, e.g. a simple "^" for ctrl-
@@ -66,7 +68,7 @@
                assert.notEqual( result[ 1 ], 'test-', 'Prefix used for testing shouldn\'t be used in production.' );
        } );
 
-       QUnit.test( 'updateTooltipAccessKeys - no access key', updateTooltipAccessKeysTestData.length, function ( assert ) {
+       QUnit.test( 'updateTooltipAccessKeys - no access key', function ( assert ) {
                var i, oldTitle, $input, newTitle;
                for ( i = 0; i < updateTooltipAccessKeysTestData.length; i++ ) {
                        oldTitle = 'Title' + updateTooltipAccessKeysTestData[ i ];
@@ -77,9 +79,9 @@
                }
        } );
 
-       QUnit.test( 'updateTooltipAccessKeys - with access key', updateTooltipAccessKeysTestData.length, function ( assert ) {
-               $.fn.updateTooltipAccessKeys.setTestMode( true );
+       QUnit.test( 'updateTooltipAccessKeys - with access key', function ( assert ) {
                var i, oldTitle, $input, newTitle;
+               $.fn.updateTooltipAccessKeys.setTestMode( true );
                for ( i = 0; i < updateTooltipAccessKeysTestData.length; i++ ) {
                        oldTitle = 'Title' + updateTooltipAccessKeysTestData[ i ];
                        $input = $( makeInput( oldTitle, 'a' ) );
                $.fn.updateTooltipAccessKeys.setTestMode( false );
        } );
 
-       QUnit.test( 'updateTooltipAccessKeys with label element', 2, function ( assert ) {
+       QUnit.test( 'updateTooltipAccessKeys with label element', function ( assert ) {
+               var html, $label, $input;
                $.fn.updateTooltipAccessKeys.setTestMode( true );
-               var html = '<label for="testInput" title="Title">Label</label><input id="testInput" accessKey="a" />',
-                       $label, $input;
+               html = '<label for="testInput" title="Title">Label</label><input id="testInput" accessKey="a" />';
                $( '#qunit-fixture' ).html( html );
                $label = $( '#qunit-fixture label' );
                $input = $( '#qunit-fixture input' );
                $.fn.updateTooltipAccessKeys.setTestMode( false );
        } );
 
-       QUnit.test( 'updateTooltipAccessKeys with label element as parent', 2, function ( assert ) {
+       QUnit.test( 'updateTooltipAccessKeys with label element as parent', function ( assert ) {
+               var html, $label, $input;
                $.fn.updateTooltipAccessKeys.setTestMode( true );
-               var html = '<label title="Title">Label<input id="testInput" accessKey="a" /></label>',
-               $label, $input;
+               html = '<label title="Title">Label<input id="testInput" accessKey="a" /></label>';
                $( '#qunit-fixture' ).html( html );
                $label = $( '#qunit-fixture label' );
                $input = $( '#qunit-fixture input' );
index a1b2e5c..c3521ba 100644 (file)
@@ -17,7 +17,7 @@
                return i;
        }
 
-       QUnit.test( 'Position right', 4, function ( assert ) {
+       QUnit.test( 'Position right', function ( assert ) {
                // We need this thing to be visible, so append it to the DOM
                var $span, spanText, d, spanTextNew,
                        origText = 'This is a really long random string and there is no way it fits in 100 pixels.',
index e6aa3aa..558e641 100644 (file)
@@ -1,7 +1,7 @@
 ( function ( $ ) {
        QUnit.module( 'jquery.byteLength', QUnit.newMwEnvironment() );
 
-       QUnit.test( 'Simple text', 5, function ( assert ) {
+       QUnit.test( 'Simple text', function ( assert ) {
                var azLc = 'abcdefghijklmnopqrstuvwxyz',
                        azUc = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ',
                        num = '0123456789',
@@ -16,7 +16,7 @@
 
        } );
 
-       QUnit.test( 'Special text', 4, function ( assert ) {
+       QUnit.test( 'Special text', function ( assert ) {
                // https://en.wikipedia.org/wiki/UTF-8
                var u0024 = '$',
                        // Cent symbol
index 81c116c..c7b7cc0 100644 (file)
                        expected: ''
                }, options );
 
-               QUnit.asyncTest( opt.description, 1, function ( assert ) {
-                       setTimeout( function () {
-                               opt.$input.appendTo( '#qunit-fixture' );
+               QUnit.test( opt.description, function ( assert ) {
+                       opt.$input.appendTo( '#qunit-fixture' );
 
-                               // Simulate pressing keys for each of the sample characters
-                               addChars( opt.$input, opt.sample );
+                       // Simulate pressing keys for each of the sample characters
+                       addChars( opt.$input, opt.sample );
 
-                               assert.equal(
-                                       opt.$input.val(),
-                                       opt.expected,
-                                       'New value matches the expected string'
-                               );
-
-                               QUnit.start();
-                       } );
+                       assert.equal(
+                               opt.$input.val(),
+                               opt.expected,
+                               'New value matches the expected string'
+                       );
                } );
        }
 
@@ -72,7 +68,7 @@
        } );
 
        byteLimitTest( {
-               description: 'Plain text input. Calling byteLimit with no parameters and no maxlength attribute (bug 36310)',
+               description: 'Plain text input. Calling byteLimit with no parameters and no maxlength attribute (T38310)',
                $input: $( '<input>' ).attr( 'type', 'text' )
                        .byteLimit(),
                sample: simpleSample,
                expected: '1234'
        } );
 
-       // Regression tests for bug 41450
+       // Regression tests for T43450
        byteLimitTest( {
                description: 'Input filter of which the base exceeds the limit',
                $input: $( '<input>' ).attr( 'type', 'text' )
                expected: ''
        } );
 
-       QUnit.test( 'Confirm properties and attributes set', 4, function ( assert ) {
-               var $el, $elA, $elB;
+       QUnit.test( 'Confirm properties and attributes set', function ( assert ) {
+               var $el;
 
                $el = $( '<input>' ).attr( 'type', 'text' )
                        .attr( 'maxlength', '7' )
 
                assert.strictEqual( $el.attr( 'maxlength' ), undefined, 'maxlength attribute removed for limit with callback' );
 
-               $elA = $( '<input>' ).attr( 'type', 'text' )
+               $( '<input>' ).attr( 'type', 'text' )
                        .addClass( 'mw-test-byteLimit-foo' )
                        .attr( 'maxlength', '7' )
                        .appendTo( '#qunit-fixture' );
 
-               $elB = $( '<input>' ).attr( 'type', 'text' )
+               $( '<input>' ).attr( 'type', 'text' )
                        .addClass( 'mw-test-byteLimit-foo' )
                        .attr( 'maxlength', '12' )
                        .appendTo( '#qunit-fixture' );
                $el.byteLimit();
        } );
 
-       QUnit.test( 'Trim from insertion when limit exceeded', 2, function ( assert ) {
+       QUnit.test( 'Trim from insertion when limit exceeded', function ( assert ) {
                var $el;
 
-               // Use a new <input /> because the bug only occurs on the first time
-               // the limit it reached (bug 40850)
+               // Use a new <input> because the bug only occurs on the first time
+               // the limit it reached (T42850)
                $el = $( '<input>' ).attr( 'type', 'text' )
                        .appendTo( '#qunit-fixture' )
                        .byteLimit( 3 )
index 00de895..d6208e9 100644 (file)
@@ -1,7 +1,7 @@
 ( function ( $ ) {
        QUnit.module( 'jquery.colorUtil', QUnit.newMwEnvironment() );
 
-       QUnit.test( 'getRGB', 18, function ( assert ) {
+       QUnit.test( 'getRGB', function ( assert ) {
                assert.strictEqual( $.colorUtil.getRGB(), undefined, 'No arguments' );
                assert.strictEqual( $.colorUtil.getRGB( '' ), undefined, 'Empty string' );
                assert.deepEqual( $.colorUtil.getRGB( [ 0, 100, 255 ] ), [ 0, 100, 255 ], 'Parse array of rgb values' );
@@ -26,7 +26,7 @@
                assert.strictEqual( $.colorUtil.getRGB( 'mediaWiki' ), undefined, 'Inexisting color name' );
        } );
 
-       QUnit.test( 'rgbToHsl', 1, function ( assert ) {
+       QUnit.test( 'rgbToHsl', function ( assert ) {
                var hsl, ret;
 
                // Cross-browser differences in decimals...
@@ -42,7 +42,7 @@
                assert.deepEqual( ret, [ 0.33, 0.73, 0.75 ], 'rgb(144, 238, 144): hsl(0.33, 0.73, 0.75)' );
        } );
 
-       QUnit.test( 'hslToRgb', 1, function ( assert ) {
+       QUnit.test( 'hslToRgb', function ( assert ) {
                var rgb, ret;
                rgb = $.colorUtil.hslToRgb( 0.3, 0.7, 0.8 );
 
@@ -52,7 +52,7 @@
                assert.deepEqual( ret, [ 183, 240, 168 ], 'hsl(0.3, 0.7, 0.8): rgb(183, 240, 168)' );
        } );
 
-       QUnit.test( 'getColorBrightness', 2, function ( assert ) {
+       QUnit.test( 'getColorBrightness', function ( assert ) {
                var a, b;
                a = $.colorUtil.getColorBrightness( 'red', +0.1 );
                assert.equal( a, 'rgb(255,50,50)', 'Start with named color "red", brighten 10%' );
index ca3f418..74d8509 100644 (file)
@@ -1,10 +1,10 @@
 ( function ( $ ) {
        QUnit.module( 'jquery.getAttrs', QUnit.newMwEnvironment() );
 
-       QUnit.test( 'getAttrs()', 1, function ( assert ) {
+       QUnit.test( 'getAttrs()', function ( assert ) {
                var attrs = {
                                foo: 'bar',
-                               'class': 'lorem',
+                               class: 'lorem',
                                'data-foo': 'data value'
                        },
                        $el = $( '<div>' ).attr( attrs );
index 8c62876..6a265eb 100644 (file)
@@ -1,17 +1,17 @@
 ( function ( $ ) {
        QUnit.module( 'jquery.hidpi', QUnit.newMwEnvironment() );
 
-       QUnit.test( 'devicePixelRatio', 1, function ( assert ) {
+       QUnit.test( 'devicePixelRatio', function ( assert ) {
                var devicePixelRatio = $.devicePixelRatio();
                assert.equal( typeof devicePixelRatio, 'number', '$.devicePixelRatio() returns a number' );
        } );
 
-       QUnit.test( 'bracketedDevicePixelRatio', 1, function ( assert ) {
-               var devicePixelRatio = $.devicePixelRatio();
-               assert.equal( typeof devicePixelRatio, 'number', '$.bracketedDevicePixelRatio() returns a number' );
+       QUnit.test( 'bracketedDevicePixelRatio', function ( assert ) {
+               var ratio = $.bracketedDevicePixelRatio();
+               assert.equal( typeof ratio, 'number', '$.bracketedDevicePixelRatio() returns a number' );
        } );
 
-       QUnit.test( 'bracketDevicePixelRatio', 8, function ( assert ) {
+       QUnit.test( 'bracketDevicePixelRatio', function ( assert ) {
                assert.equal( $.bracketDevicePixelRatio( 0.75 ), 1, '0.75 gives 1' );
                assert.equal( $.bracketDevicePixelRatio( 1 ), 1, '1 gives 1' );
                assert.equal( $.bracketDevicePixelRatio( 1.25 ), 1.5, '1.25 gives 1.5' );
@@ -22,7 +22,7 @@
                assert.equal( $.bracketDevicePixelRatio( 3 ), 2, '3 gives 2' );
        } );
 
-       QUnit.test( 'matchSrcSet', 6, function ( assert ) {
+       QUnit.test( 'matchSrcSet', function ( assert ) {
                var srcset = 'onefive.png 1.5x, two.png 2x';
 
                // Nice exact matches
index e1fb96d..0dac22e 100644 (file)
        QUnit.module( 'jquery.highlightText', QUnit.newMwEnvironment() );
 
        QUnit.test( 'Check', function ( assert ) {
-               var $fixture, cases = [
-                       {
-                               desc: 'Test 001',
-                               text: 'Blue Öyster Cult',
-                               highlight: 'Blue',
-                               expected: '<span class="highlight">Blue</span> Öyster Cult'
-                       },
-                       {
-                               desc: 'Test 002',
-                               text: 'Blue Öyster Cult',
-                               highlight: 'Blue ',
-                               expected: '<span class="highlight">Blue</span> Öyster Cult'
-                       },
-                       {
-                               desc: 'Test 003',
-                               text: 'Blue Öyster Cult',
-                               highlight: 'Blue Ö',
-                               expected: '<span class="highlight">Blue</span> <span class="highlight">Ö</span>yster Cult'
-                       },
-                       {
-                               desc: 'Test 004',
-                               text: 'Blue Öyster Cult',
-                               highlight: 'Blue Öy',
-                               expected: '<span class="highlight">Blue</span> <span class="highlight">Öy</span>ster Cult'
-                       },
-                       {
-                               desc: 'Test 005',
-                               text: 'Blue Öyster Cult',
-                               highlight: ' Blue',
-                               expected: '<span class="highlight">Blue</span> Öyster Cult'
-                       },
-                       {
-                               desc: 'Test 006',
-                               text: 'Blue Öyster Cult',
-                               highlight: ' Blue ',
-                               expected: '<span class="highlight">Blue</span> Öyster Cult'
-                       },
-                       {
-                               desc: 'Test 007',
-                               text: 'Blue Öyster Cult',
-                               highlight: ' Blue Ö',
-                               expected: '<span class="highlight">Blue</span> <span class="highlight">Ö</span>yster Cult'
-                       },
-                       {
-                               desc: 'Test 008',
-                               text: 'Blue Öyster Cult',
-                               highlight: ' Blue Öy',
-                               expected: '<span class="highlight">Blue</span> <span class="highlight">Öy</span>ster Cult'
-                       },
-                       {
-                               desc: 'Test 009: Highlighter broken on starting Umlaut?',
-                               text: 'Österreich',
-                               highlight: 'Österreich',
-                               expected: '<span class="highlight">Österreich</span>'
-                       },
-                       {
-                               desc: 'Test 010: Highlighter broken on starting Umlaut?',
-                               text: 'Österreich',
-                               highlight: 'Ö',
-                               expected: '<span class="highlight">Ö</span>sterreich'
-                       },
-                       {
-                               desc: 'Test 011: Highlighter broken on starting Umlaut?',
-                               text: 'Österreich',
-                               highlight: 'Öst',
-                               expected: '<span class="highlight">Öst</span>erreich'
-                       },
-                       {
-                               desc: 'Test 012: Highlighter broken on starting Umlaut?',
-                               text: 'Österreich',
-                               highlight: 'Oe',
-                               expected: 'Österreich'
-                       },
-                       {
-                               desc: 'Test 013: Highlighter broken on punctuation mark?',
-                               text: 'So good. To be there',
-                               highlight: 'good',
-                               expected: 'So <span class="highlight">good</span>. To be there'
-                       },
-                       {
-                               desc: 'Test 014: Highlighter broken on space?',
-                               text: 'So good. To be there',
-                               highlight: 'be',
-                               expected: 'So good. To <span class="highlight">be</span> there'
-                       },
-                       {
-                               desc: 'Test 015: Highlighter broken on space?',
-                               text: 'So good. To be there',
-                               highlight: ' be',
-                               expected: 'So good. To <span class="highlight">be</span> there'
-                       },
-                       {
-                               desc: 'Test 016: Highlighter broken on space?',
-                               text: 'So good. To be there',
-                               highlight: 'be ',
-                               expected: 'So good. To <span class="highlight">be</span> there'
-                       },
-                       {
-                               desc: 'Test 017: Highlighter broken on space?',
-                               text: 'So good. To be there',
-                               highlight: ' be ',
-                               expected: 'So good. To <span class="highlight">be</span> there'
-                       },
-                       {
-                               desc: 'Test 018: en de Highlighter broken on special character at the end?',
-                               text: 'So good. xbß',
-                               highlight: 'xbß',
-                               expected: 'So good. <span class="highlight">xbß</span>'
-                       },
-                       {
-                               desc: 'Test 019: en de Highlighter broken on special character at the end?',
-                               text: 'So good. xbß.',
-                               highlight: 'xbß.',
-                               expected: 'So good. <span class="highlight">xbß.</span>'
-                       },
-                       {
-                               desc: 'Test 020: RTL he Hebrew',
-                               text: 'חסיד אומות העולם',
-                               highlight: 'חסיד אומות העולם',
-                               expected: '<span class="highlight">חסיד</span> <span class="highlight">אומות</span> <span class="highlight">העולם</span>'
-                       },
-                       {
-                               desc: 'Test 021: RTL he Hebrew',
-                               text: 'חסיד אומות העולם',
-                               highlight: 'חסי',
-                               expected: '<span class="highlight">חסי</span>ד אומות העולם'
-                       },
-                       {
-                               desc: 'Test 022: ja Japanese',
-                               text: '諸国民の中の正義の人',
-                               highlight: '諸国民の中の正義の人',
-                               expected: '<span class="highlight">諸国民の中の正義の人</span>'
-                       },
-                       {
-                               desc: 'Test 023: ja Japanese',
-                               text: '諸国民の中の正義の人',
-                               highlight: '諸国',
-                               expected: '<span class="highlight">諸国</span>民の中の正義の人'
-                       },
-                       {
-                               desc: 'Test 024: fr French text and « french quotes » (guillemets)',
-                               text: '« L\'oiseau est sur l’île »',
-                               highlight: '« L\'oiseau est sur l’île »',
-                               expected: '<span class="highlight">«</span> <span class="highlight">L\'oiseau</span> <span class="highlight">est</span> <span class="highlight">sur</span> <span class="highlight">l’île</span> <span class="highlight">»</span>'
-                       },
-                       {
-                               desc: 'Test 025: fr French text and « french quotes » (guillemets)',
-                               text: '« L\'oiseau est sur l’île »',
-                               highlight: '« L\'oise',
-                               expected: '<span class="highlight">«</span> <span class="highlight">L\'oise</span>au est sur l’île »'
-                       },
-                       {
-                               desc: 'Test 025a: fr French text and « french quotes » (guillemets) - does it match the single strings "«" and "L" separately?',
-                               text: '« L\'oiseau est sur l’île »',
-                               highlight: '« L',
-                               expected: '<span class="highlight">«</span> <span class="highlight">L</span>\'oiseau est sur <span class="highlight">l</span>’île »'
-                       },
-                       {
-                               desc: 'Test 026: ru Russian',
-                               text: 'Праведники мира',
-                               highlight: 'Праведники мира',
-                               expected: '<span class="highlight">Праведники</span> <span class="highlight">мира</span>'
-                       },
-                       {
-                               desc: 'Test 027: ru Russian',
-                               text: 'Праведники мира',
-                               highlight: 'Праве',
-                               expected: '<span class="highlight">Праве</span>дники мира'
-                       },
-                       {
-                               desc: 'Test 028 ka Georgian',
-                               text: 'მთავარი გვერდი',
-                               highlight: 'მთავარი გვერდი',
-                               expected: '<span class="highlight">მთავარი</span> <span class="highlight">გვერდი</span>'
-                       },
-                       {
-                               desc: 'Test 029 ka Georgian',
-                               text: 'მთავარი გვერდი',
-                               highlight: 'მთა',
-                               expected: '<span class="highlight">მთა</span>ვარი გვერდი'
-                       },
-                       {
-                               desc: 'Test 030 hy Armenian',
-                               text: 'Նոնա Գափրինդաշվիլի',
-                               highlight: 'Նոնա Գափրինդաշվիլի',
-                               expected: '<span class="highlight">Նոնա</span> <span class="highlight">Գափրինդաշվիլի</span>'
-                       },
-                       {
-                               desc: 'Test 031 hy Armenian',
-                               text: 'Նոնա Գափրինդաշվիլի',
-                               highlight: 'Նոն',
-                               expected: '<span class="highlight">Նոն</span>ա Գափրինդաշվիլի'
-                       },
-                       {
-                               desc: 'Test 032: th Thai',
-                               text: 'พอล แอร์ดิช',
-                               highlight: 'พอล แอร์ดิช',
-                               expected: '<span class="highlight">พอล</span> <span class="highlight">แอร์ดิช</span>'
-                       },
-                       {
-                               desc: 'Test 033: th Thai',
-                               text: 'พอล แอร์ดิช',
-                               highlight: 'พอ',
-                               expected: '<span class="highlight">พอ</span>ล แอร์ดิช'
-                       },
-                       {
-                               desc: 'Test 034: RTL ar Arabic',
-                               text: 'بول إيردوس',
-                               highlight: 'بول إيردوس',
-                               expected: '<span class="highlight">بول</span> <span class="highlight">إيردوس</span>'
-                       },
-                       {
-                               desc: 'Test 035: RTL ar Arabic',
-                               text: 'بول إيردوس',
-                               highlight: 'بو',
-                               expected: '<span class="highlight">بو</span>ل إيردوس'
-                       }
-               ];
-               QUnit.expect( cases.length );
+               var $fixture,
+                       cases = [
+                               {
+                                       desc: 'Test 001',
+                                       text: 'Blue Öyster Cult',
+                                       highlight: 'Blue',
+                                       expected: '<span class="highlight">Blue</span> Öyster Cult'
+                               },
+                               {
+                                       desc: 'Test 002',
+                                       text: 'Blue Öyster Cult',
+                                       highlight: 'Blue ',
+                                       expected: '<span class="highlight">Blue</span> Öyster Cult'
+                               },
+                               {
+                                       desc: 'Test 003',
+                                       text: 'Blue Öyster Cult',
+                                       highlight: 'Blue Ö',
+                                       expected: '<span class="highlight">Blue</span> <span class="highlight">Ö</span>yster Cult'
+                               },
+                               {
+                                       desc: 'Test 004',
+                                       text: 'Blue Öyster Cult',
+                                       highlight: 'Blue Öy',
+                                       expected: '<span class="highlight">Blue</span> <span class="highlight">Öy</span>ster Cult'
+                               },
+                               {
+                                       desc: 'Test 005',
+                                       text: 'Blue Öyster Cult',
+                                       highlight: ' Blue',
+                                       expected: '<span class="highlight">Blue</span> Öyster Cult'
+                               },
+                               {
+                                       desc: 'Test 006',
+                                       text: 'Blue Öyster Cult',
+                                       highlight: ' Blue ',
+                                       expected: '<span class="highlight">Blue</span> Öyster Cult'
+                               },
+                               {
+                                       desc: 'Test 007',
+                                       text: 'Blue Öyster Cult',
+                                       highlight: ' Blue Ö',
+                                       expected: '<span class="highlight">Blue</span> <span class="highlight">Ö</span>yster Cult'
+                               },
+                               {
+                                       desc: 'Test 008',
+                                       text: 'Blue Öyster Cult',
+                                       highlight: ' Blue Öy',
+                                       expected: '<span class="highlight">Blue</span> <span class="highlight">Öy</span>ster Cult'
+                               },
+                               {
+                                       desc: 'Test 009: Highlighter broken on starting Umlaut?',
+                                       text: 'Österreich',
+                                       highlight: 'Österreich',
+                                       expected: '<span class="highlight">Österreich</span>'
+                               },
+                               {
+                                       desc: 'Test 010: Highlighter broken on starting Umlaut?',
+                                       text: 'Österreich',
+                                       highlight: 'Ö',
+                                       expected: '<span class="highlight">Ö</span>sterreich'
+                               },
+                               {
+                                       desc: 'Test 011: Highlighter broken on starting Umlaut?',
+                                       text: 'Österreich',
+                                       highlight: 'Öst',
+                                       expected: '<span class="highlight">Öst</span>erreich'
+                               },
+                               {
+                                       desc: 'Test 012: Highlighter broken on starting Umlaut?',
+                                       text: 'Österreich',
+                                       highlight: 'Oe',
+                                       expected: 'Österreich'
+                               },
+                               {
+                                       desc: 'Test 013: Highlighter broken on punctuation mark?',
+                                       text: 'So good. To be there',
+                                       highlight: 'good',
+                                       expected: 'So <span class="highlight">good</span>. To be there'
+                               },
+                               {
+                                       desc: 'Test 014: Highlighter broken on space?',
+                                       text: 'So good. To be there',
+                                       highlight: 'be',
+                                       expected: 'So good. To <span class="highlight">be</span> there'
+                               },
+                               {
+                                       desc: 'Test 015: Highlighter broken on space?',
+                                       text: 'So good. To be there',
+                                       highlight: ' be',
+                                       expected: 'So good. To <span class="highlight">be</span> there'
+                               },
+                               {
+                                       desc: 'Test 016: Highlighter broken on space?',
+                                       text: 'So good. To be there',
+                                       highlight: 'be ',
+                                       expected: 'So good. To <span class="highlight">be</span> there'
+                               },
+                               {
+                                       desc: 'Test 017: Highlighter broken on space?',
+                                       text: 'So good. To be there',
+                                       highlight: ' be ',
+                                       expected: 'So good. To <span class="highlight">be</span> there'
+                               },
+                               {
+                                       desc: 'Test 018: en de Highlighter broken on special character at the end?',
+                                       text: 'So good. xbß',
+                                       highlight: 'xbß',
+                                       expected: 'So good. <span class="highlight">xbß</span>'
+                               },
+                               {
+                                       desc: 'Test 019: en de Highlighter broken on special character at the end?',
+                                       text: 'So good. xbß.',
+                                       highlight: 'xbß.',
+                                       expected: 'So good. <span class="highlight">xbß.</span>'
+                               },
+                               {
+                                       desc: 'Test 020: RTL he Hebrew',
+                                       text: 'חסיד אומות העולם',
+                                       highlight: 'חסיד אומות העולם',
+                                       expected: '<span class="highlight">חסיד</span> <span class="highlight">אומות</span> <span class="highlight">העולם</span>'
+                               },
+                               {
+                                       desc: 'Test 021: RTL he Hebrew',
+                                       text: 'חסיד אומות העולם',
+                                       highlight: 'חסי',
+                                       expected: '<span class="highlight">חסי</span>ד אומות העולם'
+                               },
+                               {
+                                       desc: 'Test 022: ja Japanese',
+                                       text: '諸国民の中の正義の人',
+                                       highlight: '諸国民の中の正義の人',
+                                       expected: '<span class="highlight">諸国民の中の正義の人</span>'
+                               },
+                               {
+                                       desc: 'Test 023: ja Japanese',
+                                       text: '諸国民の中の正義の人',
+                                       highlight: '諸国',
+                                       expected: '<span class="highlight">諸国</span>民の中の正義の人'
+                               },
+                               {
+                                       desc: 'Test 024: fr French text and « french quotes » (guillemets)',
+                                       text: '« L\'oiseau est sur l’île »',
+                                       highlight: '« L\'oiseau est sur l’île »',
+                                       expected: '<span class="highlight">«</span> <span class="highlight">L\'oiseau</span> <span class="highlight">est</span> <span class="highlight">sur</span> <span class="highlight">l’île</span> <span class="highlight">»</span>'
+                               },
+                               {
+                                       desc: 'Test 025: fr French text and « french quotes » (guillemets)',
+                                       text: '« L\'oiseau est sur l’île »',
+                                       highlight: '« L\'oise',
+                                       expected: '<span class="highlight">«</span> <span class="highlight">L\'oise</span>au est sur l’île »'
+                               },
+                               {
+                                       desc: 'Test 025a: fr French text and « french quotes » (guillemets) - does it match the single strings "«" and "L" separately?',
+                                       text: '« L\'oiseau est sur l’île »',
+                                       highlight: '« L',
+                                       expected: '<span class="highlight">«</span> <span class="highlight">L</span>\'oiseau est sur <span class="highlight">l</span>’île »'
+                               },
+                               {
+                                       desc: 'Test 026: ru Russian',
+                                       text: 'Праведники мира',
+                                       highlight: 'Праведники мира',
+                                       expected: '<span class="highlight">Праведники</span> <span class="highlight">мира</span>'
+                               },
+                               {
+                                       desc: 'Test 027: ru Russian',
+                                       text: 'Праведники мира',
+                                       highlight: 'Праве',
+                                       expected: '<span class="highlight">Праве</span>дники мира'
+                               },
+                               {
+                                       desc: 'Test 028 ka Georgian',
+                                       text: 'მთავარი გვერდი',
+                                       highlight: 'მთავარი გვერდი',
+                                       expected: '<span class="highlight">მთავარი</span> <span class="highlight">გვერდი</span>'
+                               },
+                               {
+                                       desc: 'Test 029 ka Georgian',
+                                       text: 'მთავარი გვერდი',
+                                       highlight: 'მთა',
+                                       expected: '<span class="highlight">მთა</span>ვარი გვერდი'
+                               },
+                               {
+                                       desc: 'Test 030 hy Armenian',
+                                       text: 'Նոնա Գափրինդաշվիլի',
+                                       highlight: 'Նոնա Գափրինդաշվիլի',
+                                       expected: '<span class="highlight">Նոնա</span> <span class="highlight">Գափրինդաշվիլի</span>'
+                               },
+                               {
+                                       desc: 'Test 031 hy Armenian',
+                                       text: 'Նոնա Գափրինդաշվիլի',
+                                       highlight: 'Նոն',
+                                       expected: '<span class="highlight">Նոն</span>ա Գափրինդաշվիլի'
+                               },
+                               {
+                                       desc: 'Test 032: th Thai',
+                                       text: 'พอล แอร์ดิช',
+                                       highlight: 'พอล แอร์ดิช',
+                                       expected: '<span class="highlight">พอล</span> <span class="highlight">แอร์ดิช</span>'
+                               },
+                               {
+                                       desc: 'Test 033: th Thai',
+                                       text: 'พอล แอร์ดิช',
+                                       highlight: 'พอ',
+                                       expected: '<span class="highlight">พอ</span>ล แอร์ดิช'
+                               },
+                               {
+                                       desc: 'Test 034: RTL ar Arabic',
+                                       text: 'بول إيردوس',
+                                       highlight: 'بول إيردوس',
+                                       expected: '<span class="highlight">بول</span> <span class="highlight">إيردوس</span>'
+                               },
+                               {
+                                       desc: 'Test 035: RTL ar Arabic',
+                                       text: 'بول إيردوس',
+                                       highlight: 'بو',
+                                       expected: '<span class="highlight">بو</span>ل إيردوس'
+                               }
+                       ];
 
                $.each( cases, function ( i, item ) {
                        $fixture = $( '<p>' ).text( item.text ).highlightText( item.highlight );
index c503fc9..a3e46ab 100644 (file)
@@ -1,7 +1,7 @@
 ( function ( $, mw ) {
        QUnit.module( 'jquery.localize', QUnit.newMwEnvironment() );
 
-       QUnit.test( 'Handle basic replacements', 4, function ( assert ) {
+       QUnit.test( 'Handle basic replacements', function ( assert ) {
                var html, $lc;
                mw.messages.set( 'basic', 'Basic stuff' );
 
@@ -30,7 +30,7 @@
                assert.strictEqual( $lc.attr( 'placeholder' ), 'Basic stuff', 'Attribute: placeholder-msg' );
        } );
 
-       QUnit.test( 'Proper escaping', 2, function ( assert ) {
+       QUnit.test( 'Proper escaping', function ( assert ) {
                var html, $lc;
                mw.messages.set( 'properfoo', '<proper esc="test">' );
 
@@ -50,7 +50,8 @@
                assert.strictEqual( $lc.attr( 'title' ), mw.msg( 'properfoo' ), 'Attributes are not inserted raw.' );
        } );
 
-       QUnit.test( 'Options', 7, function ( assert ) {
+       QUnit.test( 'Options', function ( assert ) {
+               var html, $lc, x, sitename = 'Wikipedia';
                mw.messages.set( {
                        'foo-lorem': 'Lorem',
                        'foo-ipsum': 'Ipsum',
@@ -60,7 +61,6 @@
                        'foo-bazz-label': 'The Bazz ($1)',
                        'foo-welcome': 'Welcome to $1! (last visit: $2)'
                } );
-               var html, $lc, x, sitename = 'Wikipedia';
 
                // Message key prefix
                html = '<div><span title-msg="lorem"><html:msg key="ipsum" /></span></div>';
                assert.strictEqual( $lc.attr( 'title' ), 'Read more about bazz at Wikipedia (last modified: 3 minutes ago)', 'Combination of options prefix, params and keys - attr' );
        } );
 
-       QUnit.test( 'Handle data text', 2, function ( assert ) {
+       QUnit.test( 'Handle data text', function ( assert ) {
                var html, $lc;
                mw.messages.set( 'option-one', 'Item 1' );
                mw.messages.set( 'option-two', 'Item 2' );
                assert.strictEqual( $lc.eq( 1 ).text(), mw.msg( 'option-two' ), 'data-msg-text becomes text of options' );
        } );
 
-       QUnit.test( 'Handle data html', 2, function ( assert ) {
+       QUnit.test( 'Handle data html', function ( assert ) {
                var html, $lc;
                mw.messages.set( 'html', 'behold... there is a <a>link</a> here!!' );
                html = '<div><div data-msg-html="html"></div></div>';
index 9c7660f..4e77d72 100644 (file)
@@ -11,9 +11,8 @@
        }
 
        // This test is first because if it fails, then almost all of the latter tests are meaningless.
-       QUnit.test( 'testing hooks/triggers', 4, function ( assert ) {
-               var test = this,
-                       $collapsible = prepareCollapsible(
+       QUnit.test( 'testing hooks/triggers', function ( assert ) {
+               var $collapsible = prepareCollapsible(
                                '<div class="mw-collapsible">' + loremIpsum + '</div>'
                        ),
                        $content = $collapsible.find( '.mw-collapsible-content' ),
@@ -44,9 +43,8 @@
                $toggle.trigger( 'click' );
        } );
 
-       QUnit.test( 'basic operation (<div>)', 5, function ( assert ) {
-               var test = this,
-                       $collapsible = prepareCollapsible(
+       QUnit.test( 'basic operation (<div>)', function ( assert ) {
+               var $collapsible = prepareCollapsible(
                                '<div class="mw-collapsible">' + loremIpsum + '</div>'
                        ),
                        $content = $collapsible.find( '.mw-collapsible-content' ),
@@ -70,9 +68,8 @@
                $toggle.trigger( 'click' );
        } );
 
-       QUnit.test( 'basic operation (<table>)', 7, function ( assert ) {
-               var test = this,
-                       $collapsible = prepareCollapsible(
+       QUnit.test( 'basic operation (<table>)', function ( assert ) {
+               var $collapsible = prepareCollapsible(
                                '<table class="mw-collapsible">' +
                                        '<tr><td>' + loremIpsum + '</td><td>' + loremIpsum + '</td></tr>' +
                                        '<tr><td>' + loremIpsum + '</td><td>' + loremIpsum + '</td></tr>' +
                $toggle.trigger( 'click' );
        }
 
-       QUnit.test( 'basic operation (<table> with caption)', 10, function ( assert ) {
+       QUnit.test( 'basic operation (<table> with caption)', function ( assert ) {
                tableWithCaptionTest( prepareCollapsible(
                        '<table class="mw-collapsible">' +
                                '<caption>' + loremIpsum + '</caption>' +
                ), this, assert );
        } );
 
-       QUnit.test( 'basic operation (<table> with caption and <thead>)', 10, function ( assert ) {
+       QUnit.test( 'basic operation (<table> with caption and <thead>)', function ( assert ) {
                tableWithCaptionTest( prepareCollapsible(
                        '<table class="mw-collapsible">' +
                                '<caption>' + loremIpsum + '</caption>' +
                $toggle.trigger( 'click' );
        }
 
-       QUnit.test( 'basic operation (<ul>)', 7, function ( assert ) {
+       QUnit.test( 'basic operation (<ul>)', function ( assert ) {
                listTest( 'ul', this, assert );
        } );
 
-       QUnit.test( 'basic operation (<ol>)', 7, function ( assert ) {
+       QUnit.test( 'basic operation (<ol>)', function ( assert ) {
                listTest( 'ol', this, assert );
        } );
 
-       QUnit.test( 'basic operation when synchronous (options.instantHide)', 2, function ( assert ) {
+       QUnit.test( 'basic operation when synchronous (options.instantHide)', function ( assert ) {
                var $collapsible = prepareCollapsible(
                                '<div class="mw-collapsible">' + loremIpsum + '</div>',
                                { instantHide: true }
                assert.assertTrue( $content.is( ':hidden' ), 'after collapsing: content is hidden' );
        } );
 
-       QUnit.test( 'mw-made-collapsible data added', 1, function ( assert ) {
+       QUnit.test( 'mw-made-collapsible data added', function ( assert ) {
                var $collapsible = prepareCollapsible(
                                '<div>' + loremIpsum + '</div>'
                        );
                assert.equal( $collapsible.data( 'mw-made-collapsible' ), true, 'mw-made-collapsible data present' );
        } );
 
-       QUnit.test( 'mw-collapsible added when missing', 1, function ( assert ) {
+       QUnit.test( 'mw-collapsible added when missing', function ( assert ) {
                var $collapsible = prepareCollapsible(
                                '<div>' + loremIpsum + '</div>'
                        );
                assert.assertTrue( $collapsible.hasClass( 'mw-collapsible' ), 'mw-collapsible class present' );
        } );
 
-       QUnit.test( 'mw-collapsed added when missing', 1, function ( assert ) {
+       QUnit.test( 'mw-collapsed added when missing', function ( assert ) {
                var $collapsible = prepareCollapsible(
                        '<div>' + loremIpsum + '</div>',
                                { collapsed: true }
                assert.assertTrue( $collapsible.hasClass( 'mw-collapsed' ), 'mw-collapsed class present' );
        } );
 
-       QUnit.test( 'initial collapse (mw-collapsed class)', 2, function ( assert ) {
+       QUnit.test( 'initial collapse (mw-collapsed class)', function ( assert ) {
                var $collapsible = prepareCollapsible(
                                '<div class="mw-collapsible mw-collapsed">' + loremIpsum + '</div>'
                        ),
                $collapsible.find( '.mw-collapsible-toggle' ).trigger( 'click' );
        } );
 
-       QUnit.test( 'initial collapse (options.collapsed)', 2, function ( assert ) {
+       QUnit.test( 'initial collapse (options.collapsed)', function ( assert ) {
                var $collapsible = prepareCollapsible(
                                '<div class="mw-collapsible">' + loremIpsum + '</div>',
                                { collapsed: true }
                $collapsible.find( '.mw-collapsible-toggle' ).trigger( 'click' );
        } );
 
-       QUnit.test( 'clicks on links inside toggler pass through (options.linksPassthru)', 2, function ( assert ) {
+       QUnit.test( 'clicks on links inside toggler pass through (options.linksPassthru)', function ( assert ) {
                var $collapsible = prepareCollapsible(
                                '<div class="mw-collapsible">' +
                                        '<div class="mw-collapsible-toggle">' +
                assert.assertTrue( $content.is( ':hidden' ), 'click event on non-link inside toggle toggles content' );
        } );
 
-       QUnit.test( 'collapse/expand text (data-collapsetext, data-expandtext)', 2, function ( assert ) {
+       QUnit.test( 'collapse/expand text (data-collapsetext, data-expandtext)', function ( assert ) {
                var $collapsible = prepareCollapsible(
                                '<div class="mw-collapsible" data-collapsetext="Collapse me!" data-expandtext="Expand me!">' +
                                        loremIpsum +
                $collapsible.find( '.mw-collapsible-toggle' ).trigger( 'click' );
        } );
 
-       QUnit.test( 'collapse/expand text (options.collapseText, options.expandText)', 2, function ( assert ) {
+       QUnit.test( 'collapse/expand text (options.collapseText, options.expandText)', function ( assert ) {
                var $collapsible = prepareCollapsible(
                                '<div class="mw-collapsible">' + loremIpsum + '</div>',
                                { collapseText: 'Collapse me!', expandText: 'Expand me!' }
                $collapsible.find( '.mw-collapsible-toggle' ).trigger( 'click' );
        } );
 
-       QUnit.test( 'cloned collapsibles can be made collapsible again', 2, function ( assert ) {
-               var test = this,
-                       $collapsible = prepareCollapsible(
+       QUnit.test( 'cloned collapsibles can be made collapsible again', function ( assert ) {
+               var $collapsible = prepareCollapsible(
                                '<div class="mw-collapsible">' + loremIpsum + '</div>'
                        ),
                        $clone = $collapsible.clone() // clone without data and events
index 029edd5..aeda516 100644 (file)
@@ -10,7 +10,7 @@
                }
        } ) );
 
-       QUnit.test( 'String functions', 7, function ( assert ) {
+       QUnit.test( 'String functions', function ( assert ) {
                assert.equal( $.trimLeft( '  foo bar  ' ), 'foo bar  ', 'trimLeft' );
                assert.equal( $.trimRight( '  foo bar  ' ), '  foo bar', 'trimRight' );
                assert.equal( $.ucFirst( 'foo' ), 'Foo', 'ucFirst' );
@@ -24,7 +24,7 @@
                assert.equal( $.escapeRE( '0123456789' ), '0123456789', 'escapeRE - Leave numbers alone' );
        } );
 
-       QUnit.test( 'isDomElement', 6, function ( assert ) {
+       QUnit.test( 'isDomElement', function ( assert ) {
                assert.strictEqual( $.isDomElement( document.createElement( 'div' ) ), true,
                        'isDomElement: HTMLElement' );
                assert.strictEqual( $.isDomElement( document.createTextNode( '' ) ), true,
@@ -39,7 +39,7 @@
                        'isDomElement: Plain Object' );
        } );
 
-       QUnit.test( 'isEmpty', 7, function ( assert ) {
+       QUnit.test( 'isEmpty', function ( assert ) {
                assert.strictEqual( $.isEmpty( 'string' ), false, 'isEmpty: "string"' );
                assert.strictEqual( $.isEmpty( '0' ), true, 'isEmpty: "0"' );
                assert.strictEqual( $.isEmpty( '' ), true, 'isEmpty: ""' );
@@ -51,7 +51,7 @@
                assert.strictEqual( $.isEmpty( { length: 0 } ), true, 'isEmpty: { length: 0 }' );
        } );
 
-       QUnit.test( 'Comparison functions', 5, function ( assert ) {
+       QUnit.test( 'Comparison functions', function ( assert ) {
                assert.ok( $.compareArray( [ 0, 'a', [], [ 2, 'b' ] ], [ 0, 'a', [], [ 2, 'b' ] ] ),
                        'compareArray: Two deep arrays that are excactly the same' );
                assert.ok( !$.compareArray( [ 1 ], [ 2 ] ), 'compareArray: Two different arrays (false)' );
index 5d0ddeb..dd7666b 100644 (file)
@@ -1,8 +1,9 @@
 ( function ( $ ) {
+       var html, testElement;
 
        QUnit.module( 'jquery.placeholder', QUnit.newMwEnvironment() );
 
-       QUnit.test( 'caches results of feature tests', 2, function ( assert ) {
+       QUnit.test( 'caches results of feature tests', function ( assert ) {
                assert.strictEqual( typeof $.fn.placeholder.input, 'boolean', '$.fn.placeholder.input' );
                assert.strictEqual( typeof $.fn.placeholder.textarea, 'boolean', '$.fn.placeholder.textarea' );
        } );
                return;
        }
 
-       var html = '<form>' +
-                       '<input id="input-type-search" type="search" placeholder="Search this site...">' +
-                       '<input id="input-type-text" type="text" placeholder="e.g. John Doe">' +
-                       '<input id="input-type-email" type="email" placeholder="e.g. address@example.ext">' +
-                       '<input id="input-type-url" type="url" placeholder="e.g. http://mathiasbynens.be/">' +
-                       '<input id="input-type-tel" type="tel" placeholder="e.g. +32 472 77 69 88">' +
-                       '<input id="input-type-password" type="password" placeholder="e.g. hunter2">' +
-                       '<textarea id="textarea" name="message" placeholder="Your message goes here"></textarea>' +
-               '</form>',
+       html = '<form>' +
+               '<input id="input-type-search" type="search" placeholder="Search this site...">' +
+               '<input id="input-type-text" type="text" placeholder="e.g. John Doe">' +
+               '<input id="input-type-email" type="email" placeholder="e.g. address@example.ext">' +
+               '<input id="input-type-url" type="url" placeholder="e.g. http://mathiasbynens.be/">' +
+               '<input id="input-type-tel" type="tel" placeholder="e.g. +32 472 77 69 88">' +
+               '<input id="input-type-password" type="password" placeholder="e.g. hunter2">' +
+               '<textarea id="textarea" name="message" placeholder="Your message goes here"></textarea>' +
+       '</form>';
        testElement = function ( $el, assert ) {
-
                var el = $el[ 0 ],
                        placeholder = el.getAttribute( 'placeholder' );
 
                $el.placeholder( placeholder );
        };
 
-       QUnit.test( 'emulates placeholder for <input type=text>', 22, function ( assert ) {
+       QUnit.test( 'emulates placeholder for <input type=text>', function ( assert ) {
                $( '<div>' ).html( html ).appendTo( $( '#qunit-fixture' ) );
                testElement( $( '#input-type-text' ), assert );
        } );
 
-       QUnit.test( 'emulates placeholder for <input type=search>', 22, function ( assert ) {
+       QUnit.test( 'emulates placeholder for <input type=search>', function ( assert ) {
                $( '<div>' ).html( html ).appendTo( $( '#qunit-fixture' ) );
                testElement( $( '#input-type-search' ), assert );
        } );
 
-       QUnit.test( 'emulates placeholder for <input type=email>', 22, function ( assert ) {
+       QUnit.test( 'emulates placeholder for <input type=email>', function ( assert ) {
                $( '<div>' ).html( html ).appendTo( $( '#qunit-fixture' ) );
                testElement( $( '#input-type-email' ), assert );
        } );
 
-       QUnit.test( 'emulates placeholder for <input type=url>', 22, function ( assert ) {
+       QUnit.test( 'emulates placeholder for <input type=url>', function ( assert ) {
                $( '<div>' ).html( html ).appendTo( $( '#qunit-fixture' ) );
                testElement( $( '#input-type-url' ), assert );
        } );
 
-       QUnit.test( 'emulates placeholder for <input type=tel>', 22, function ( assert ) {
+       QUnit.test( 'emulates placeholder for <input type=tel>', function ( assert ) {
                $( '<div>' ).html( html ).appendTo( $( '#qunit-fixture' ) );
                testElement( $( '#input-type-tel' ), assert );
        } );
 
-       QUnit.test( 'emulates placeholder for <input type=password>', 13, function ( assert ) {
+       QUnit.test( 'emulates placeholder for <input type=password>', function ( assert ) {
+               var $el, el, placeholder, selector = '#input-type-password';
+
                $( '<div>' ).html( html ).appendTo( $( '#qunit-fixture' ) );
 
-               var selector = '#input-type-password',
-                       $el = $( selector ),
-                       el = $el[ 0 ],
-                       placeholder = el.getAttribute( 'placeholder' );
+               $el = $( selector );
+               el = $el[ 0 ];
+               placeholder = el.getAttribute( 'placeholder' );
 
                assert.strictEqual( $el.placeholder(), $el, 'should be chainable' );
 
 
        } );
 
-       QUnit.test( 'emulates placeholder for <textarea></textarea>', 22, function ( assert ) {
+       QUnit.test( 'emulates placeholder for <textarea>', function ( assert ) {
                $( '<div>' ).html( html ).appendTo( $( '#qunit-fixture' ) );
                testElement( $( '#textarea' ), assert );
        } );
index 1213793..ec3539b 100644 (file)
@@ -1,7 +1,7 @@
 ( function ( $ ) {
        QUnit.module( 'jquery.tabIndex', QUnit.newMwEnvironment() );
 
-       QUnit.test( 'firstTabIndex', 2, function ( assert ) {
+       QUnit.test( 'firstTabIndex', function ( assert ) {
                var html, $testA, $testB;
                html = '<form>' +
                        '<input tabindex="7" />' +
@@ -17,7 +17,7 @@
                assert.strictEqual( $testB.firstTabIndex(), null, 'Return null if none available.' );
        } );
 
-       QUnit.test( 'lastTabIndex', 2, function ( assert ) {
+       QUnit.test( 'lastTabIndex', function ( assert ) {
                var html, $testA, $testB;
                html = '<form>' +
                        '<input tabindex="7" />' +
index 5203def..c0b1657 100644 (file)
                                                'jul', 'aug', 'sep', 'oct', 'nov', 'dec' ]
                                },
                                names: [ 'January', 'February', 'March', 'April', 'May', 'June',
-                                               'July', 'August', 'September', 'October', 'November', 'December' ],
+                                       'July', 'August', 'September', 'October', 'November', 'December' ],
                                genitive: [ 'January', 'February', 'March', 'April', 'May', 'June',
-                                               'July', 'August', 'September', 'October', 'November', 'December' ],
+                                       'July', 'August', 'September', 'October', 'November', 'December' ],
                                abbrev: [ 'Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun',
-                                               'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec' ]
+                                       'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec' ]
                        };
                },
                teardown: function () {
@@ -54,7 +54,7 @@
         * @param {function($table)} callback something to do before we start the testcase
         */
        function parserTest( msg, parserId, data, callback ) {
-               QUnit.test( msg, data.length * 2, function ( assert ) {
+               QUnit.test( msg, function ( assert ) {
                        var extractedR, extractedF, parser;
 
                        if ( callback !== undefined ) {
@@ -73,7 +73,7 @@
                } );
        }
 
-       text  = [
+       text = [
                [ 'Mars', true, 'mars', 'Simple text' ],
                [ 'Mẘas', true, 'mẘas', 'Non ascii character' ],
                [ 'A sentence', true, 'a sentence', 'A sentence with space chars' ]
                } );
        } );
 
-       // TODO add numbers sorting tests for bug 8115 with a different language
+       // TODO add numbers sorting tests for T10115 with a different language
 
 }( jQuery, mediaWiki ) );
index 483a37d..5b973f6 100644 (file)
                                                'jul', 'aug', 'sep', 'oct', 'nov', 'dec' ]
                                },
                                names: [ 'January', 'February', 'March', 'April', 'May', 'June',
-                                               'July', 'August', 'September', 'October', 'November', 'December' ],
+                                       'July', 'August', 'September', 'October', 'November', 'December' ],
                                genitive: [ 'January', 'February', 'March', 'April', 'May', 'June',
-                                               'July', 'August', 'September', 'October', 'November', 'December' ],
+                                       'July', 'August', 'September', 'October', 'November', 'December' ],
                                abbrev: [ 'Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun',
-                                               'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec' ]
+                                       'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec' ]
                        };
                },
                teardown: function () {
                $tr.appendTo( $thead );
 
                for ( i = 0; i < data.length; i++ ) {
-                       /*jshint loopfunc: true */
                        $tr = $( '<tr>' );
+                       // eslint-disable-next-line no-loop-func
                        $.each( data[ i ], function ( j, str ) {
                                var $td = $( '<td>' );
                                $td.text( str ).appendTo( $tr );
                simple,
                simpleAsc,
                function ( $table ) {
+                       var event;
                        $table.tablesorter(
                                { sortList: [ { 0: 'desc' }, { 1: 'desc' } ] }
                        );
                        $table.find( '.headerSort:eq(0)' ).click();
 
                        // Pretend to click while pressing the multi-sort key
-                       var event = $.Event( 'click' );
+                       event = $.Event( 'click' );
                        event[ $table.data( 'tablesorter' ).config.sortMultiSortKey ] = true;
                        $table.find( '.headerSort:eq(1)' ).trigger( event );
                }
        );
-       QUnit.test( 'Reset sorting making table appear unsorted', 3, function ( assert ) {
+       QUnit.test( 'Reset sorting making table appear unsorted', function ( assert ) {
                var $table = tableCreate( header, simple );
                $table.tablesorter(
                        { sortList: [
                }
        );
 
-       QUnit.test( 'Basic planet table: one unsortable column', 3, function ( assert ) {
+       QUnit.test( 'Basic planet table: one unsortable column', function ( assert ) {
                var $table = tableCreate( header, planets ),
                        $cell;
                $table.find( 'tr:eq(0) > th:eq(0)' ).addClass( 'unsortable' );
 
        // Regression tests!
        tableTest(
-               'Bug 28775: German-style (dmy) short numeric dates',
+               'T30775: German-style (dmy) short numeric dates',
                [ 'Date' ],
                [
                        // German-style dates are day-month-year
        );
 
        tableTest(
-               'Bug 28775: American-style (mdy) short numeric dates',
+               'T30775: American-style (mdy) short numeric dates',
                [ 'Date' ],
                [
                        // American-style dates are month-day-year
        );
 
        tableTest(
-               'Bug 17141: IPv4 address sorting',
+               'T19141: IPv4 address sorting',
                [ 'IP' ],
                ipv4,
                ipv4Sorted,
                }
        );
        tableTest(
-               'Bug 17141: IPv4 address sorting (reverse)',
+               'T19141: IPv4 address sorting (reverse)',
                [ 'IP' ],
                ipv4,
                reversed( ipv4Sorted ),
                }
        );
 
-       QUnit.test( 'Rowspan not exploded on init', 1, function ( assert ) {
+       QUnit.test( 'Rowspan not exploded on init', function ( assert ) {
                var $table = tableCreate( header, planets );
 
                // Modify the table to have a multiple-row-spanning cell:
                }
        );
 
-       QUnit.test( 'Test detection routine', 1, function ( assert ) {
+       QUnit.test( 'Test detection routine', function ( assert ) {
                var $table;
                $table = $(
                        '<table class="sortable">' +
        } );
 
        /** FIXME: the diff output is not very readeable. */
-       QUnit.test( 'bug 32047 - caption must be before thead', 1, function ( assert ) {
+       QUnit.test( 'T34047 - caption must be before thead', function ( assert ) {
                var $table;
                $table = $(
                        '<table class="sortable">' +
                assert.equal(
                        $table.children().get( 0 ).nodeName,
                        'CAPTION',
-                       'First element after <thead> must be <caption> (bug 32047)'
+                       'First element after <thead> must be <caption> (T34047)'
                );
        } );
 
-       QUnit.test( 'data-sort-value attribute, when available, should override sorting position', 3, function ( assert ) {
+       QUnit.test( 'data-sort-value attribute, when available, should override sorting position', function ( assert ) {
                var $table, data;
 
                // Example 1: All cells except one cell without data-sort-value,
                ], 'Order matches expected order (based on data-sort-value attribute values)' );
 
                // Example 3: Test that live changes are used from data-sort-value,
-               // even if they change after the tablesorter is constructed (bug 38152).
+               // even if they change after the tablesorter is constructed (T40152).
                $table = $(
                        '<table class="sortable"><thead><tr><th>Data</th></tr></thead>' +
                                '<tbody>' +
                        .tablesorter()
                        .find( '.headerSort:eq(0)' ).click();
 
-               // Change the sortValue data properties (bug 38152)
+               // Change the sortValue data properties (T40152)
                // - change data
                $table.find( 'td:contains(A)' ).data( 'sortValue', 3 );
                // - add data
 
        } );
 
-       tableTest( 'bug 8115: sort numbers with commas (ascending)',
+       tableTest( 'T10115: sort numbers with commas (ascending)',
                [ 'Numbers' ], numbers, numbersAsc,
                function ( $table ) {
                        $table.tablesorter();
                }
        );
 
-       tableTest( 'bug 8115: sort numbers with commas (descending)',
+       tableTest( 'T10115: sort numbers with commas (descending)',
                [ 'Numbers' ], numbers, reversed( numbersAsc ),
                function ( $table ) {
                        $table.tablesorter();
                        $table.find( '.headerSort:eq(0)' ).click().click();
                }
        );
-       // TODO add numbers sorting tests for bug 8115 with a different language
+       // TODO add numbers sorting tests for T10115 with a different language
 
-       QUnit.test( 'bug 32888 - Tables inside a tableheader cell', 2, function ( assert ) {
+       QUnit.test( 'T34888 - Tables inside a tableheader cell', function ( assert ) {
                var $table;
                $table = $(
                        '<table class="sortable" id="mw-bug-32888">' +
                assert.equal(
                        $table.find( '> thead:eq(0) > tr > th.headerSort' ).length,
                        1,
-                       'Child tables inside a headercell should not interfere with sortable headers (bug 32888)'
+                       'Child tables inside a headercell should not interfere with sortable headers (T34888)'
                );
                assert.equal(
                        $( '#mw-bug-32888-2' ).find( 'th.headerSort' ).length,
                        0,
-                       'The headers of child tables inside a headercell should not be sortable themselves (bug 32888)'
+                       'The headers of child tables inside a headercell should not be sortable themselves (T34888)'
                );
        } );
 
                }
        );
 
-       QUnit.test( 'Sorting images using alt text', 1, function ( assert ) {
+       QUnit.test( 'Sorting images using alt text', function ( assert ) {
                var $table = $(
                        '<table class="sortable">' +
                                '<tr><th>THEAD</th></tr>' +
                );
        } );
 
-       QUnit.test( 'Sorting images using alt text (complex)', 1, function ( assert ) {
+       QUnit.test( 'Sorting images using alt text (complex)', function ( assert ) {
                var $table = $(
                        '<table class="sortable">' +
                                '<tr><th>THEAD</th></tr>' +
                );
        } );
 
-       QUnit.test( 'Sorting images using alt text (with format autodetection)', 1, function ( assert ) {
+       QUnit.test( 'Sorting images using alt text (with format autodetection)', function ( assert ) {
                var $table = $(
                        '<table class="sortable">' +
                                '<tr><th>THEAD</th></tr>' +
                );
        } );
 
-       QUnit.test( 'bug 38911 - The row with the largest amount of columns should receive the sort indicators', 3, function ( assert ) {
+       QUnit.test( 'T40911 - The row with the largest amount of columns should receive the sort indicators', function ( assert ) {
                var $table = $(
                        '<table class="sortable">' +
                                '<thead>' +
                );
        } );
 
-       QUnit.test( 'rowspans in table headers should prefer the last row when rows are equal in length', 2, function ( assert ) {
+       QUnit.test( 'rowspans in table headers should prefer the last row when rows are equal in length', function ( assert ) {
                var $table = $(
                        '<table class="sortable">' +
                                '<thead>' +
                );
        } );
 
-       QUnit.test( 'holes in the table headers should not throw JS errors', 2, function ( assert ) {
+       QUnit.test( 'holes in the table headers should not throw JS errors', function ( assert ) {
                var $table = $(
                        '<table class="sortable">' +
                                '<thead>' +
                );
        } );
 
-       // bug 53527
-       QUnit.test( 'td cells in thead should not be taken into account for longest row calculation', 2, function ( assert ) {
+       // T55527
+       QUnit.test( 'td cells in thead should not be taken into account for longest row calculation', function ( assert ) {
                var $table = $(
                        '<table class="sortable">' +
                                '<thead>' +
                );
        } );
 
-       // bug 41889 - exploding rowspans in more complex cases
+       // T43889 - exploding rowspans in more complex cases
        tableTestHTML(
                'Rowspan exploding with row headers',
                '<table class="sortable">' +
                ]
        );
 
-       // bug 53211 - exploding rowspans in more complex cases
+       // T55211 - exploding rowspans in more complex cases
        QUnit.test(
-               'Rowspan exploding with row headers and colspans', 1, function ( assert ) {
+               'Rowspan exploding with row headers and colspans', function ( assert ) {
                        var $table = $( '<table class="sortable">' +
                                '<thead><tr><th rowspan="2">n</th><th colspan="2">foo</th><th rowspan="2">baz</th></tr>' +
                                '<tr><th>foo</th><th>bar</th></tr></thead>' +
                ]
        );
 
-       QUnit.test( 'bug 105731 - incomplete rows in table body', 3, function ( assert ) {
+       QUnit.test( 'T105731 - incomplete rows in table body', function ( assert ) {
                var $table, parsers;
                $table = $(
                        '<table class="sortable">' +
                );
        } );
 
-       QUnit.test( 'bug T114721 - use of expand-child class', 2, function ( assert ) {
+       QUnit.test( 'bug T114721 - use of expand-child class', function ( assert ) {
                var $table, parsers;
                $table = $(
                        '<table class="sortable">' +
index 1001679..f958e09 100644 (file)
@@ -1,4 +1,28 @@
 ( function ( $ ) {
+       var caretSample,
+               sig = {
+                       pre: '--~~~~'
+               },
+               bold = {
+                       pre: '\'\'\'',
+                       peri: 'Bold text',
+                       post: '\'\'\''
+               },
+               h2 = {
+                       pre: '== ',
+                       peri: 'Heading 2',
+                       post: ' ==',
+                       regex: /^(\s*)(={1,6})(.*?)\2(\s*)$/,
+                       regexReplace: '$1==$3==$4',
+                       ownline: true
+               },
+               ulist = {
+                       pre: '* ',
+                       peri: 'Bulleted list item',
+                       post: '',
+                       ownline: true,
+                       splitlines: true
+               };
 
        QUnit.module( 'jquery.textSelection', QUnit.newMwEnvironment() );
 
                }, opt.after );
 
                QUnit.test( opt.description, function ( assert ) {
-                       var $textarea, start, end, options, text, selected,
-                               tests = 1;
-                       if ( opt.after.selected !== null ) {
-                               tests++;
-                       }
-                       QUnit.expect( tests );
+                       var $textarea, start, end, options, text, selected;
 
                        $textarea = $( '<textarea>' );
 
                } );
        }
 
-       var caretSample,
-               sig = {
-                       pre: '--~~~~'
-               },
-               bold = {
-                       pre: '\'\'\'',
-                       peri: 'Bold text',
-                       post: '\'\'\''
-               },
-               h2 = {
-                       pre: '== ',
-                       peri: 'Heading 2',
-                       post: ' ==',
-                       regex: /^(\s*)(={1,6})(.*?)\2(\s*)$/,
-                       regexReplace: '$1==$3==$4',
-                       ownline: true
-               },
-               ulist = {
-                       pre: '* ',
-                       peri: 'Bulleted list item',
-                       post: '',
-                       ownline: true,
-                       splitlines: true
-               };
-
        encapsulateTest( {
                description: 'Adding sig to end of text',
                before: {
        } );
 
        function caretTest( options ) {
-               QUnit.test( options.description, 2, function ( assert ) {
+               QUnit.test( options.description, function ( assert ) {
                        var pos,
                                $textarea = $( '<textarea>' ).text( options.text );
 
 
        caretSample = 'Some big text that we like to work with. Nothing fancy... you know what I mean?';
 
-       /* @broken: Disabled per bug 34820
+       /* @broken: Disabled per T36820
        caretTest({
-               description: 'getCaretPosition with original/empty selection - bug 31847 with IE 6/7/8',
+               description: 'getCaretPosition with original/empty selection - T33847 with IE 6/7/8',
                text: caretSample,
                start: [0, caretSample.length], // Opera and Firefox (prior to FF 6.0) default caret to the end of the box (caretSample.length)
                end: [0, caretSample.length], // Other browsers default it to the beginning (0), so check both.
index 1676130..69ab797 100644 (file)
@@ -6,7 +6,7 @@
                }
        } ) );
 
-       QUnit.test( 'origin is included in GET requests', 1, function ( assert ) {
+       QUnit.test( 'origin is included in GET requests', function ( assert ) {
                var api = new mw.ForeignApi( '//localhost:4242/w/api.php' );
 
                this.server.respond( function ( request ) {
@@ -17,7 +17,7 @@
                return api.get( {} );
        } );
 
-       QUnit.test( 'origin is included in POST requests', 2, function ( assert ) {
+       QUnit.test( 'origin is included in POST requests', function ( assert ) {
                var api = new mw.ForeignApi( '//localhost:4242/w/api.php' );
 
                this.server.respond( function ( request ) {
index a79bff6..8ad1290 100644 (file)
@@ -6,7 +6,7 @@
                }
        } ) );
 
-       QUnit.test( '.getCategoriesByPrefix()', 1, function ( assert ) {
+       QUnit.test( '.getCategoriesByPrefix()', function ( assert ) {
                this.server.respondWith( [ 200, { 'Content-Type': 'application/json' },
                        '{ "query": { "allpages": [ ' +
                                '{ "title": "Category:Food" },' +
index f83f66c..13d7dcc 100644 (file)
@@ -15,7 +15,7 @@
                                                pages: [ {
                                                        pageid: 1,
                                                        ns: 0,
-                                                       title:  'Sandbox',
+                                                       title: 'Sandbox',
                                                        revisions: [ {
                                                                timestamp: '2016-01-01T12:00:00Z',
                                                                contentformat: 'text/x-wiki',
@@ -56,7 +56,7 @@
                                                pages: [ {
                                                        pageid: 4,
                                                        ns: 0,
-                                                       title:  'Async',
+                                                       title: 'Async',
                                                        revisions: [ {
                                                                timestamp: '2016-02-01T12:00:00Z',
                                                                contentformat: 'text/x-wiki',
@@ -97,7 +97,7 @@
                                                pages: [ {
                                                        pageid: 3,
                                                        ns: 0,
-                                                       title:  'Param',
+                                                       title: 'Param',
                                                        revisions: [ {
                                                                timestamp: '2016-03-01T12:00:00Z',
                                                                contentformat: 'text/x-wiki',
                        if ( /edit.+text=Sand/.test( req.requestBody ) ) {
                                req.respond( 200, { 'Content-Type': 'application/json' }, JSON.stringify( {
                                        edit: {
-                                               'new': true,
+                                               new: true,
                                                result: 'Success',
                                                newrevid: 41,
                                                newtimestamp: '2016-04-01T12:00:00Z'
index d8b5db8..7282b3f 100644 (file)
@@ -6,7 +6,7 @@
                }
        } ) );
 
-       QUnit.test( '.getMessages()', 1, function ( assert ) {
+       QUnit.test( '.getMessages()', function ( assert ) {
                this.server.respondWith( /ammessages=foo%7Cbaz/, [
                        200,
                        { 'Content-Type': 'application/json' },
index 7ed1875..854e4b1 100644 (file)
@@ -6,7 +6,7 @@
                }
        } ) );
 
-       QUnit.test( 'saveOption', 2, function ( assert ) {
+       QUnit.test( 'saveOption', function ( assert ) {
                var api = new mw.Api(),
                        stub = this.sandbox.stub( mw.Api.prototype, 'saveOptions' );
 
@@ -16,7 +16,7 @@
                assert.deepEqual( stub.getCall( 0 ).args, [ { foo: 'bar' } ], '#saveOptions called correctly' );
        } );
 
-       QUnit.test( 'saveOptions without Unit Separator', 13, function ( assert ) {
+       QUnit.test( 'saveOptions without Unit Separator', function ( assert ) {
                var api = new mw.Api( { useUS: false } );
 
                // We need to respond to the request for token first, otherwise the other requests won't be sent
 
                // Requests are POST, match requestBody instead of url
                this.server.respond( function ( request ) {
-                       switch ( request.requestBody ) {
+                       if ( $.inArray( request.requestBody, [
                                // simple
-                               case 'action=options&format=json&formatversion=2&change=foo%3Dbar&token=%2B%5C':
+                               'action=options&format=json&formatversion=2&change=foo%3Dbar&token=%2B%5C',
                                // two options
-                               case 'action=options&format=json&formatversion=2&change=foo%3Dbar%7Cbaz%3Dquux&token=%2B%5C':
+                               'action=options&format=json&formatversion=2&change=foo%3Dbar%7Cbaz%3Dquux&token=%2B%5C',
                                // not bundleable
-                               case 'action=options&format=json&formatversion=2&optionname=foo&optionvalue=bar%7Cquux&token=%2B%5C':
-                               case 'action=options&format=json&formatversion=2&optionname=bar&optionvalue=a%7Cb%7Cc&token=%2B%5C':
-                               case 'action=options&format=json&formatversion=2&change=baz%3Dquux&token=%2B%5C':
+                               'action=options&format=json&formatversion=2&optionname=foo&optionvalue=bar%7Cquux&token=%2B%5C',
+                               'action=options&format=json&formatversion=2&optionname=bar&optionvalue=a%7Cb%7Cc&token=%2B%5C',
+                               'action=options&format=json&formatversion=2&change=baz%3Dquux&token=%2B%5C',
                                // reset an option
-                               case 'action=options&format=json&formatversion=2&change=foo&token=%2B%5C':
+                               'action=options&format=json&formatversion=2&change=foo&token=%2B%5C',
                                // reset an option, not bundleable
-                               case 'action=options&format=json&formatversion=2&optionname=foo%7Cbar%3Dquux&token=%2B%5C':
-                                       assert.ok( true, 'Repond to ' + request.requestBody );
-                                       request.respond( 200, { 'Content-Type': 'application/json' },
-                                               '{ "options": "success" }' );
-                                       break;
-                               default:
-                                       assert.ok( false, 'Unexpected request: ' + request.requestBody );
+                               'action=options&format=json&formatversion=2&optionname=foo%7Cbar%3Dquux&token=%2B%5C'
+                       ] ) !== -1 ) {
+                               assert.ok( true, 'Repond to ' + request.requestBody );
+                               request.respond( 200, { 'Content-Type': 'application/json' },
+                                       '{ "options": "success" }' );
+                       } else {
+                               assert.ok( false, 'Unexpected request: ' + request.requestBody );
                        }
                } );
 
@@ -74,7 +74,7 @@
                );
        } );
 
-       QUnit.test( 'saveOptions with Unit Separator', 14, function ( assert ) {
+       QUnit.test( 'saveOptions with Unit Separator', function ( assert ) {
                var api = new mw.Api( { useUS: true } );
 
                // We need to respond to the request for token first, otherwise the other requests won't be sent
 
                // Requests are POST, match requestBody instead of url
                this.server.respond( function ( request ) {
-                       switch ( request.requestBody ) {
+                       if ( $.inArray( request.requestBody, [
                                // simple
-                               case 'action=options&format=json&formatversion=2&change=foo%3Dbar&token=%2B%5C':
+                               'action=options&format=json&formatversion=2&change=foo%3Dbar&token=%2B%5C',
                                // two options
-                               case 'action=options&format=json&formatversion=2&change=foo%3Dbar%7Cbaz%3Dquux&token=%2B%5C':
+                               'action=options&format=json&formatversion=2&change=foo%3Dbar%7Cbaz%3Dquux&token=%2B%5C',
                                // bundleable with unit separator
-                               case 'action=options&format=json&formatversion=2&change=%1Ffoo%3Dbar%7Cquux%1Fbar%3Da%7Cb%7Cc%1Fbaz%3Dquux&token=%2B%5C':
+                               'action=options&format=json&formatversion=2&change=%1Ffoo%3Dbar%7Cquux%1Fbar%3Da%7Cb%7Cc%1Fbaz%3Dquux&token=%2B%5C',
                                // not bundleable with unit separator
-                               case 'action=options&format=json&formatversion=2&optionname=baz%3Dbaz&optionvalue=quux&token=%2B%5C':
-                               case 'action=options&format=json&formatversion=2&change=%1Ffoo%3Dbar%7Cquux%1Fbar%3Da%7Cb%7Cc&token=%2B%5C':
+                               'action=options&format=json&formatversion=2&optionname=baz%3Dbaz&optionvalue=quux&token=%2B%5C',
+                               'action=options&format=json&formatversion=2&change=%1Ffoo%3Dbar%7Cquux%1Fbar%3Da%7Cb%7Cc&token=%2B%5C',
                                // reset an option
-                               case 'action=options&format=json&formatversion=2&change=foo&token=%2B%5C':
+                               'action=options&format=json&formatversion=2&change=foo&token=%2B%5C',
                                // reset an option, not bundleable
-                               case 'action=options&format=json&formatversion=2&optionname=foo%7Cbar%3Dquux&token=%2B%5C':
-                                       assert.ok( true, 'Repond to ' + request.requestBody );
-                                       request.respond( 200, { 'Content-Type': 'application/json' },
+                               'action=options&format=json&formatversion=2&optionname=foo%7Cbar%3Dquux&token=%2B%5C'
+                       ] ) !== -1 ) {
+                               assert.ok( true, 'Repond to ' + request.requestBody );
+                               request.respond( 200, { 'Content-Type': 'application/json' },
                                                '{ "options": "success" }' );
-                                       break;
-                               default:
-                                       assert.ok( false, 'Unexpected request: ' + request.requestBody );
+                       } else {
+                               assert.ok( false, 'Unexpected request: ' + request.requestBody );
                        }
                } );
 
index 7d27352..74da009 100644 (file)
@@ -39,7 +39,7 @@
                ] );
 
                return new mw.Api().parse( new mw.Title( 'Earth' ) ).done( function ( html ) {
-                       assert.equal( html, '<p><b>Earth</b> is a planet.</p>', 'Parse page by Title object'  );
+                       assert.equal( html, '<p><b>Earth</b> is a planet.</p>', 'Parse page by Title object' );
                } );
        } );
 }( mediaWiki ) );
index 3f5e8c3..e10a7fa 100644 (file)
                        ]
                ) );
 
-               // Don't cache error (bug 65268)
+               // Don't cache error (T67268)
                return api.getToken( 'testerror' )
                        .then( null, function ( err ) {
                                assert.equal( err, 'bite-me', 'Expected error' );
 
                return api.postWithToken( 'testassertpost', { action: 'example', key: 'foo', assert: 'user' } )
                        // Cast error to success and vice versa
-                       .then( function ( ) {
+                       .then( function () {
                                return $.Deferred().reject( 'Unexpected success' );
                        }, function ( errorCode ) {
                                assert.equal( errorCode, 'assertuserfailed', 'getToken fails assert' );
                this.server.respond( [ 200, { 'Content-Type': 'application/json' }, '{ "example": "quux" }' ] );
 
                return api.postWithToken( 'csrf',
-                               { action: 'example' },
-                               {
-                                       headers: {
-                                               'X-Foo': 'Bar'
-                                       }
+                       { action: 'example' },
+                       {
+                               headers: {
+                                       'X-Foo': 'Bar'
                                }
-                       )
-                       .then( function () {
-                               assert.equal( test.server.requests[ 0 ].requestHeaders[ 'X-Foo' ], 'Bar', 'Header sent' );
+                       }
+               )
+               .then( function () {
+                       assert.equal( test.server.requests[ 0 ].requestHeaders[ 'X-Foo' ], 'Bar', 'Header sent' );
 
-                               return api.postWithToken( 'csrf',
-                                       { action: 'example' },
-                                       function () {
-                                               assert.ok( false, 'This parameter cannot be a callback' );
-                                       }
-                               );
-                       } )
-                       .then( function ( data ) {
-                               assert.equal( data.example, 'quux' );
+                       return api.postWithToken( 'csrf',
+                               { action: 'example' },
+                               function () {
+                                       assert.ok( false, 'This parameter cannot be a callback' );
+                               }
+                       );
+               } )
+               .then( function ( data ) {
+                       assert.equal( data.example, 'quux' );
 
-                               assert.equal( test.server.requests.length, 2, 'Request made' );
-                       } );
+                       assert.equal( test.server.requests.length, 2, 'Request made' );
+               } );
        } );
 
        QUnit.test( 'postWithToken() - badtoken', function ( assert ) {
                }
        } );
 
-       QUnit.test( '#abort', 3, function ( assert ) {
+       QUnit.test( '#abort', function ( assert ) {
                this.api.get( {
                        a: 1
                } );
index b1bd12b..bfaf7f2 100644 (file)
@@ -1,7 +1,7 @@
 ( function ( mw, $ ) {
        QUnit.module( 'mediawiki.api.upload', QUnit.newMwEnvironment( {} ) );
 
-       QUnit.test( 'Basic functionality', 2, function ( assert ) {
+       QUnit.test( 'Basic functionality', function ( assert ) {
                var api = new mw.Api();
                assert.ok( api.upload );
                assert.throws( function () {
@@ -9,7 +9,7 @@
                } );
        } );
 
-       QUnit.test( 'Set up iframe upload', 5, function ( assert ) {
+       QUnit.test( 'Set up iframe upload', function ( assert ) {
                var $iframe, $form, $input,
                        api = new mw.Api();
 
index 49a5b18..3a940d0 100644 (file)
                                hidefilter4: 0,
                                hidefilter5: 0,
                                hidefilter6: 0,
-                               group3: 'all',
+                               group3: 'all'
                        },
                        'Unselected filters return all parameters falsey or \'all\'.'
                );
                                        filters: [
                                                { name: 'filter1' },
                                                { name: 'filter2' },
-                                               { name: 'filter3' },
+                                               { name: 'filter3' }
                                        ]
                                },
                                group2: {
                                        filters: [
                                                { name: 'filter4' },
                                                { name: 'filter5' },
-                                               { name: 'filter6' },
+                                               { name: 'filter6' }
                                        ]
                                }
                        },
+                       model = new mw.rcfilters.dm.FiltersViewModel(),
                        isCapsuleItemMuted = function ( filterName ) {
                                var itemModel = model.getItemByName( filterName ),
                                        groupModel = itemModel.getGroupModel();
                                filter4: false,
                                filter5: false,
                                filter6: false
-                       },
-                       model = new mw.rcfilters.dm.FiltersViewModel();
+                       };
 
                model.initializeFilters( definition );
 
                                                        conflicts: [ 'filter3' ]
                                                },
                                                {
-                                                       name: 'filter6',
+                                                       name: 'filter6'
                                                }
                                        ]
                                }
                        $.extend( true, {}, baseFullState, {
                                filter1: { selected: true },
                                filter2: { conflicted: true },
-                               filter4: { conflicted: true },
+                               filter4: { conflicted: true }
                        } ),
                        'Selecting a filter set its conflicts list as "conflicted".'
                );
                        $.extend( true, {}, baseFullState, {
                                filter1: { selected: true, conflicted: true },
                                filter2: { conflicted: true },
-                               filter4: { selected: true, conflicted: true },
+                               filter4: { selected: true, conflicted: true }
                        } ),
                        'Selecting a conflicting filter sets both sides to conflicted and selected.'
                );
                        'Selecting a non-conflicting filter from a conflicting group removes the conflict'
                );
        } );
+
+       QUnit.test( 'Filter highlights', function ( assert ) {
+               var definition = {
+                               group1: {
+                                       title: 'Group 1',
+                                       type: 'string_options',
+                                       filters: [
+                                               { name: 'filter1', class: 'class1' },
+                                               { name: 'filter2', class: 'class2' },
+                                               { name: 'filter3', class: 'class3' },
+                                               { name: 'filter4', class: 'class4' },
+                                               { name: 'filter5', class: 'class5' },
+                                               { name: 'filter6' }
+                                       ]
+                               }
+                       },
+                       model = new mw.rcfilters.dm.FiltersViewModel();
+
+               model.initializeFilters( definition );
+
+               assert.ok(
+                       !model.isHighlightEnabled(),
+                       'Initially, highlight is disabled.'
+               );
+
+               model.toggleHighlight( true );
+               assert.ok(
+                       model.isHighlightEnabled(),
+                       'Highlight is enabled on toggle.'
+               );
+
+               model.setHighlightColor( 'filter1', 'color1' );
+               model.setHighlightColor( 'filter2', 'color2' );
+
+               assert.deepEqual(
+                       model.getHighlightedItems().map( function ( item ) {
+                               return item.getName();
+                       } ),
+                       [
+                               'filter1',
+                               'filter2'
+                       ],
+                       'Highlighted items are highlighted.'
+               );
+
+               assert.equal(
+                       model.getItemByName( 'filter1' ).getHighlightColor(),
+                       'color1',
+                       'Item highlight color is set.'
+               );
+
+               model.setHighlightColor( 'filter1', 'color1changed' );
+               assert.equal(
+                       model.getItemByName( 'filter1' ).getHighlightColor(),
+                       'color1changed',
+                       'Item highlight color is changed on setHighlightColor.'
+               );
+
+               model.clearHighlightColor( 'filter1' );
+               assert.deepEqual(
+                       model.getHighlightedItems().map( function ( item ) {
+                               return item.getName();
+                       } ),
+                       [
+                               'filter2'
+                       ],
+                       'Clear highlight from an item results in the item no longer being highlighted.'
+               );
+
+               // Reset
+               model = new mw.rcfilters.dm.FiltersViewModel();
+               model.initializeFilters( definition );
+
+               model.setHighlightColor( 'filter1', 'color1' );
+               model.setHighlightColor( 'filter2', 'color2' );
+               model.setHighlightColor( 'filter3', 'color3' );
+
+               assert.deepEqual(
+                       model.getHighlightedItems().map( function ( item ) {
+                               return item.getName();
+                       } ),
+                       [
+                               'filter1',
+                               'filter2',
+                               'filter3'
+                       ],
+                       'Even if highlights are not enabled, the items remember their highlight state'
+                       // NOTE: When actually displaying the highlights, the UI checks whether
+                       // highlighting is generally active and then goes over the highlighted
+                       // items. The item models, however, and the view model in general, still
+                       // retains the knowledge about which filters have different colors, so we
+                       // can seamlessly return to the colors the user previously chose if they
+                       // reapply highlights.
+               );
+
+               // Reset
+               model = new mw.rcfilters.dm.FiltersViewModel();
+               model.initializeFilters( definition );
+
+               model.setHighlightColor( 'filter1', 'color1' );
+               model.setHighlightColor( 'filter6', 'color6' );
+
+               assert.deepEqual(
+                       model.getHighlightedItems().map( function ( item ) {
+                               return item.getName();
+                       } ),
+                       [
+                               'filter1'
+                       ],
+                       'Items without a specified class identifier are not highlighted.'
+               );
+       } );
 }( mediaWiki, jQuery ) );
index edc2716..35b6b71 100644 (file)
@@ -3,7 +3,7 @@
 
        // TODO: verify checkboxes == [ 'nsassociated', 'nsinvert' ]
 
-       QUnit.test( '"all" namespace disable checkboxes', 8, function ( assert ) {
+       QUnit.test( '"all" namespace disable checkboxes', function ( assert ) {
                var selectHtml, $env, $options,
                        rc = require( 'mediawiki.special.recentchanges' );
 
index 2388497..97c82fb 100644 (file)
@@ -1,7 +1,7 @@
 ( function ( mw, $ ) {
        QUnit.module( 'mediawiki.RegExp' );
 
-       QUnit.test( 'escape', 16, function ( assert ) {
+       QUnit.test( 'escape', function ( assert ) {
                var specials, normal;
 
                specials = [
index 124c49f..1bc4c06 100644 (file)
@@ -1,79 +1,80 @@
 ( function ( mw, $ ) {
+       /* eslint-disable camelcase */
        var repeat = function ( input, multiplier ) {
-               return new Array( multiplier + 1 ).join( input );
-       },
-       cases = {
+                       return new Array( multiplier + 1 ).join( input );
+               },
                // See also TitleTest.php#testSecureAndSplit
-               valid: [
-                       'Sandbox',
-                       'A "B"',
-                       'A \'B\'',
-                       '.com',
-                       '~',
-                       '"',
-                       '\'',
-                       'Talk:Sandbox',
-                       'Talk:Foo:Sandbox',
-                       'File:Example.svg',
-                       'File_talk:Example.svg',
-                       'Foo/.../Sandbox',
-                       'Sandbox/...',
-                       'A~~',
-                       ':A',
-                       // Length is 256 total, but only title part matters
-                       'Category:' + repeat( 'x', 248 ),
-                       repeat( 'x', 252 )
-               ],
-               invalid: [
-                       '',
-                       ':',
-                       '__  __',
-                       '  __  ',
-                       // Bad characters forbidden regardless of wgLegalTitleChars
-                       'A [ B',
-                       'A ] B',
-                       'A { B',
-                       'A } B',
-                       'A < B',
-                       'A > B',
-                       'A | B',
-                       'A \t B',
-                       'A \n B',
-                       // URL encoding
-                       'A%20B',
-                       'A%23B',
-                       'A%2523B',
-                       // XML/HTML character entity references
-                       // Note: The ones with # are commented out as those are interpreted as fragment and
-                       // as such end up being valid.
-                       'A &eacute; B',
-                       // 'A &#233; B',
-                       // 'A &#x00E9; B',
-                       // Subject of NS_TALK does not roundtrip to NS_MAIN
-                       'Talk:File:Example.svg',
-                       // Directory navigation
-                       '.',
-                       '..',
-                       './Sandbox',
-                       '../Sandbox',
-                       'Foo/./Sandbox',
-                       'Foo/../Sandbox',
-                       'Sandbox/.',
-                       'Sandbox/..',
-                       // Tilde
-                       'A ~~~ Name',
-                       'A ~~~~ Signature',
-                       'A ~~~~~ Timestamp',
-                       repeat( 'x', 256 ),
-                       // Extension separation is a js invention, for length
-                       // purposes it is part of the title
-                       repeat( 'x', 252 ) + '.json',
-                       // Namespace prefix without actual title
-                       'Talk:',
-                       'Category: ',
-                       'Category: #bar'
-               ]
-       };
+               cases = {
+                       valid: [
+                               'Sandbox',
+                               'A "B"',
+                               'A \'B\'',
+                               '.com',
+                               '~',
+                               '"',
+                               '\'',
+                               'Talk:Sandbox',
+                               'Talk:Foo:Sandbox',
+                               'File:Example.svg',
+                               'File_talk:Example.svg',
+                               'Foo/.../Sandbox',
+                               'Sandbox/...',
+                               'A~~',
+                               ':A',
+                               // Length is 256 total, but only title part matters
+                               'Category:' + repeat( 'x', 248 ),
+                               repeat( 'x', 252 )
+                       ],
+                       invalid: [
+                               '',
+                               ':',
+                               '__  __',
+                               '  __  ',
+                               // Bad characters forbidden regardless of wgLegalTitleChars
+                               'A [ B',
+                               'A ] B',
+                               'A { B',
+                               'A } B',
+                               'A < B',
+                               'A > B',
+                               'A | B',
+                               'A \t B',
+                               'A \n B',
+                               // URL encoding
+                               'A%20B',
+                               'A%23B',
+                               'A%2523B',
+                               // XML/HTML character entity references
+                               // Note: The ones with # are commented out as those are interpreted as fragment and
+                               // as such end up being valid.
+                               'A &eacute; B',
+                               // 'A &#233; B',
+                               // 'A &#x00E9; B',
+                               // Subject of NS_TALK does not roundtrip to NS_MAIN
+                               'Talk:File:Example.svg',
+                               // Directory navigation
+                               '.',
+                               '..',
+                               './Sandbox',
+                               '../Sandbox',
+                               'Foo/./Sandbox',
+                               'Foo/../Sandbox',
+                               'Sandbox/.',
+                               'Sandbox/..',
+                               // Tilde
+                               'A ~~~ Name',
+                               'A ~~~~ Signature',
+                               'A ~~~~~ Timestamp',
+                               repeat( 'x', 256 ),
+                               // Extension separation is a js invention, for length
+                               // purposes it is part of the title
+                               repeat( 'x', 252 ) + '.json',
+                               // Namespace prefix without actual title
+                               'Talk:',
+                               'Category: ',
+                               'Category: #bar'
+                       ]
+               };
 
        QUnit.module( 'mediawiki.Title', QUnit.newMwEnvironment( {
                // mw.Title relies on these three config vars
                                // testing custom / localized namespace
                                100: 'Penguins'
                        },
-                       // jscs: disable requireCamelCaseOrUpperCaseIdentifiers
                        wgNamespaceIds: {
                                media: -2,
                                special: -1,
                                penguins: 100,
                                antarctic_waterfowl: 100
                        },
-                       // jscs: enable requireCamelCaseOrUpperCaseIdentifiers
                        wgCaseSensitiveNamespaces: []
                }
        } ) );
 
-       QUnit.test( 'constructor', cases.invalid.length, function ( assert ) {
+       QUnit.test( 'constructor', function ( assert ) {
                var i, title;
                for ( i = 0; i < cases.valid.length; i++ ) {
                        title = new mw.Title( cases.valid[ i ] );
                }
                for ( i = 0; i < cases.invalid.length; i++ ) {
-                       /*jshint loopfunc:true */
                        title = cases.invalid[ i ];
+                       // eslint-disable-next-line no-loop-func
                        assert.throws( function () {
                                return new mw.Title( title );
                        }, cases.invalid[ i ] );
                }
        } );
 
-       QUnit.test( 'newFromText', cases.valid.length + cases.invalid.length, function ( assert ) {
+       QUnit.test( 'newFromText', function ( assert ) {
                var i;
                for ( i = 0; i < cases.valid.length; i++ ) {
                        assert.equal(
                }
        } );
 
-       QUnit.test( 'makeTitle', 6, function ( assert ) {
+       QUnit.test( 'makeTitle', function ( assert ) {
                var cases, i, title, expected,
                        NS_MAIN = 0,
                        NS_TALK = 1,
                }
        } );
 
-       QUnit.test( 'Basic parsing', 21, function ( assert ) {
+       QUnit.test( 'Basic parsing', function ( assert ) {
                var title;
                title = new mw.Title( 'File:Foo_bar.JPG' );
 
                assert.equal( title.getPrefixedText(), '.foo' );
        } );
 
-       QUnit.test( 'Transformation', 12, function ( assert ) {
+       QUnit.test( 'Transformation', function ( assert ) {
                var title;
 
                title = new mw.Title( 'File:quux pif.jpg' );
                assert.equal( title.getFragment(), ' foo bar baz', 'Fragment' );
        } );
 
-       QUnit.test( 'Namespace detection and conversion', 10, function ( assert ) {
+       QUnit.test( 'Namespace detection and conversion', function ( assert ) {
                var title;
 
                title = new mw.Title( 'File:User:Example' );
                assert.equal( title.toString(), 'Penguins:Flightless_yet_cute.jpg' );
        } );
 
-       QUnit.test( 'Throw error on invalid title', 1, function ( assert ) {
+       QUnit.test( 'Throw error on invalid title', function ( assert ) {
                assert.throws( function () {
                        return new mw.Title( '' );
                }, 'Throw error on empty string' );
        } );
 
-       QUnit.test( 'Case-sensivity', 5, function ( assert ) {
+       QUnit.test( 'Case-sensivity', function ( assert ) {
                var title;
 
                // Default config
                assert.equal( title.toString(), 'User:John', '$wgCapitalLinks=false: User namespace is insensitive, first-letter becomes uppercase' );
        } );
 
-       QUnit.test( 'toString / toText', 2, function ( assert ) {
+       QUnit.test( 'toString / toText', function ( assert ) {
                var title = new mw.Title( 'Some random page' );
 
                assert.equal( title.toString(), title.getPrefixedDb() );
                assert.equal( title.toText(), title.getPrefixedText() );
        } );
 
-       QUnit.test( 'getExtension', 7, function ( assert ) {
+       QUnit.test( 'getExtension', function ( assert ) {
                function extTest( pagename, ext, description ) {
                        var title = new mw.Title( pagename );
                        assert.equal( title.getExtension(), ext, description || pagename );
 
                extTest( 'MediaWiki:Vector.js', 'js' );
                extTest( 'User:Example/common.css', 'css' );
-               extTest( 'File:Example.longextension', 'longextension', 'Extension parsing not limited (bug 36151)' );
+               extTest( 'File:Example.longextension', 'longextension', 'Extension parsing not limited (T38151)' );
                extTest( 'Example/information.json', 'json', 'Extension parsing not restricted from any namespace' );
                extTest( 'Foo.', null, 'Trailing dot is not an extension' );
                extTest( 'Foo..', null, 'Trailing dots are not an extension' );
                // extTest( '.NET', null, 'Leading dot is (or is not?) an extension' );
        } );
 
-       QUnit.test( 'exists', 3, function ( assert ) {
+       QUnit.test( 'exists', function ( assert ) {
                var title;
 
                // Empty registry, checks default to null
 
        } );
 
-       QUnit.test( 'getUrl', 4, function ( assert ) {
+       QUnit.test( 'getUrl', function ( assert ) {
                var title;
                mw.config.set( {
                        wgScript: '/w/index.php',
                assert.equal( title.getUrl( { meme: true } ), '/w/index.php?title=User_talk:John_Cena&meme=true#And_His_Name_Is', 'title with fragment and query parameter' );
        } );
 
-       QUnit.test( 'newFromImg', 44, function ( assert ) {
+       QUnit.test( 'newFromImg', function ( assert ) {
                var title, i, thisCase, prefix,
                        cases = [
                                {
                }
        } );
 
-       QUnit.test( 'getRelativeText', 5, function ( assert ) {
+       QUnit.test( 'getRelativeText', function ( assert ) {
                var i, thisCase, title,
                        cases = [
                                {
                }
        } );
 
-       QUnit.test( 'normalizeExtension', 5, function ( assert ) {
+       QUnit.test( 'normalizeExtension', function ( assert ) {
                var extension, i, thisCase, prefix,
                        cases = [
                                {
                }
        } );
 
-       QUnit.test( 'newFromUserInput', 12, function ( assert ) {
+       QUnit.test( 'newFromUserInput', function ( assert ) {
                var title, i, thisCase, prefix,
                        cases = [
                                {
                }
        } );
 
-       QUnit.test( 'newFromFileName', 54, function ( assert ) {
+       QUnit.test( 'newFromFileName', function ( assert ) {
                var title, i, thisCase, prefix,
                        cases = [
                                {
index 242096e..e56c933 100644 (file)
@@ -11,7 +11,7 @@
        } ) );
 
        $.each( [ true, false ], function ( i, strictMode ) {
-               QUnit.test( 'Basic construction and properties (' + ( strictMode ? '' : 'non-' ) + 'strict mode)', 2, function ( assert ) {
+               QUnit.test( 'Basic construction and properties (' + ( strictMode ? '' : 'non-' ) + 'strict mode)', function ( assert ) {
                        var uriString, uri;
                        uriString = 'http://www.ietf.org/rfc/rfc2396.txt';
                        uri = new mw.Uri( uriString, {
@@ -59,7 +59,7 @@
                } );
        } );
 
-       QUnit.test( 'Constructor( String[, Object ] )', 11, function ( assert ) {
+       QUnit.test( 'Constructor( String[, Object ] )', function ( assert ) {
                var uri;
 
                uri = new mw.Uri( 'http://www.example.com/dir/?m=foo&m=bar&n=1', {
                } );
                assert.equal( uri.toString(), 'http://example.com/bar/baz', 'normalize URI without protocol or // in loose mode' );
 
-               /*jshint -W001 */
                uri = new mw.Uri( 'http://example.com/index.php?key=key&hasOwnProperty=hasOwnProperty&constructor=constructor&watch=watch' );
                assert.deepEqual(
                        uri.query,
                        },
                        'Keys in query strings support names of Object prototypes (bug T114344)'
                );
-               /*jshint +W001 */
        } );
 
-       QUnit.test( 'Constructor( Object )', 3, function ( assert ) {
+       QUnit.test( 'Constructor( Object )', function ( assert ) {
                var uri = new mw.Uri( {
                        protocol: 'http',
                        host: 'www.foo.local',
                );
        } );
 
-       QUnit.test( 'Constructor( empty[, Object ] )', 5, function ( assert ) {
+       QUnit.test( 'Constructor( empty[, Object ] )', function ( assert ) {
                var testuri, MyUri, uri;
 
                testuri = 'http://example.org/w/index.php?a=1&a=2';
                assert.deepEqual( uri.query, { a: '2' }, 'null, with options' );
        } );
 
-       QUnit.test( 'Properties', 8, function ( assert ) {
+       QUnit.test( 'Properties', function ( assert ) {
                var uriBase, uri;
 
                uriBase = new mw.Uri( 'http://en.wiki.local/w/api.php' );
                assert.ok( uri.toString().indexOf( 'pif=paf' ) >= 0, 'extend query arguments' );
        } );
 
-       QUnit.test( '.getQueryString()', 2, function ( assert ) {
+       QUnit.test( '.getQueryString()', function ( assert ) {
                var uri = new mw.Uri( 'http://search.example.com/?q=uri' );
 
                assert.deepEqual(
 
        } );
 
-       QUnit.test( '.clone()', 6, function ( assert ) {
+       QUnit.test( '.clone()', function ( assert ) {
                var original, clone;
 
                original = new mw.Uri( 'http://foo.example.org/index.php?one=1&two=2' );
                assert.deepEqual(
                        original.query,
                        { one: '1', two: '2' },
-                       'Properties is deep cloned (bug 37708)'
+                       'Properties is deep cloned (T39708)'
                );
        } );
 
-       QUnit.test( '.toString() after query manipulation', 8, function ( assert ) {
+       QUnit.test( '.toString() after query manipulation', function ( assert ) {
                var uri;
 
                uri = new mw.Uri( 'http://www.example.com/dir/?m=foo&m=bar&n=1', {
                assert.equal( uri.toString(), 'http://www.example.com/dir/', 'empty array value is ommitted' );
        } );
 
-       QUnit.test( 'Variable defaultUri', 2, function ( assert ) {
+       QUnit.test( 'Variable defaultUri', function ( assert ) {
                var uri,
                        href = 'http://example.org/w/index.php#here',
                        UriClass = mw.UriRelative( function () {
                );
        } );
 
-       QUnit.test( 'Advanced URL', 11, function ( assert ) {
+       QUnit.test( 'Advanced URL', function ( assert ) {
                var uri, queryString, relativePath;
 
                uri = new mw.Uri( 'http://auth@www.example.com:81/dir/dir.2/index.htm?q1=0&&test1&test2=value+%28escaped%29#top' );
                assert.ok( relativePath.indexOf( uri.fragment ) >= 0, 'fragment in relative path' );
        } );
 
-       QUnit.test( 'Parse a uri with an @ symbol in the path and query', 1, function ( assert ) {
+       QUnit.test( 'Parse a uri with an @ symbol in the path and query', function ( assert ) {
                var uri = new mw.Uri( 'http://www.example.com/test@test?x=@uri&y@=uri&z@=@' );
 
                assert.deepEqual(
                );
        } );
 
-       QUnit.test( 'Handle protocol-relative URLs', 5, function ( assert ) {
+       QUnit.test( 'Handle protocol-relative URLs', function ( assert ) {
                var UriRel, uri;
 
                UriRel = mw.UriRelative( 'glork://en.wiki.local/foo.php' );
                assert.equal( uri.toString(), 'http://en.wiki.local/foo.com', 'handle absolute paths by supplying host from document in strict mode' );
        } );
 
-       QUnit.test( 'bug 35658', 2, function ( assert ) {
+       QUnit.test( 'T37658', function ( assert ) {
                var testProtocol, testServer, testPort, testPath, UriClass, uri, href;
 
                testProtocol = 'https://';
index 399db91..4170897 100644 (file)
@@ -1,6 +1,4 @@
 ( function ( mw, $ ) {
-       QUnit.module( 'mediawiki.cldr', QUnit.newMwEnvironment() );
-
        var pluralTestcases = {
                /*
                 * Sample:
                ]
        };
 
+       QUnit.module( 'mediawiki.cldr', QUnit.newMwEnvironment() );
+
        function pluralTest( langCode, tests ) {
-               QUnit.test( 'Plural Test for ' + langCode, tests.length, function ( assert ) {
-                       for ( var i = 0; i < tests.length; i++ ) {
+               QUnit.test( 'Plural Test for ' + langCode, function ( assert ) {
+                       var i;
+                       for ( i = 0; i < tests.length; i++ ) {
                                assert.equal(
                                        mw.language.convertPlural( tests[ i ][ 0 ], tests[ i ][ 1 ] ),
                                        tests[ i ][ 2 ],
index 7a13f0f..59bf737 100644 (file)
@@ -20,7 +20,7 @@
                }
        } ) );
 
-       QUnit.test( 'set( key, value )', 7, function ( assert ) {
+       QUnit.test( 'set( key, value )', function ( assert ) {
                var call;
 
                // Simple case
@@ -53,7 +53,7 @@
                assert.strictEqual( call[ 1 ], '0', '0 is value' );
        } );
 
-       QUnit.test( 'set( key, value, expires )', 6, function ( assert ) {
+       QUnit.test( 'set( key, value, expires )', function ( assert ) {
                var date, options;
 
                date = new Date();
@@ -91,7 +91,7 @@
                assert.strictEqual( options.expires, date, 'custom expiration (with wgCookieExpiration=0)' );
        } );
 
-       QUnit.test( 'set( key, value, options )', 4, function ( assert ) {
+       QUnit.test( 'set( key, value, options )', function ( assert ) {
                var date, call;
 
                mw.cookie.set( 'foo', 'bar', {
                }, 'Options (incl. expires)' );
        } );
 
-       QUnit.test( 'get( key ) - no values', 6, function ( assert ) {
+       QUnit.test( 'get( key ) - no values', function ( assert ) {
                var key, value;
 
                mw.cookie.get( 'foo' );
                assert.strictEqual( value, 'bar', 'Custom default value' );
        } );
 
-       QUnit.test( 'get( key ) - with value', 1, function ( assert ) {
+       QUnit.test( 'get( key ) - with value', function ( assert ) {
                var value;
 
                $.cookie.returns( 'bar' );
                assert.strictEqual( value, 'bar', 'Return value of cookie' );
        } );
 
-       QUnit.test( 'get( key, prefix )', 1, function ( assert ) {
+       QUnit.test( 'get( key, prefix )', function ( assert ) {
                var key;
 
                mw.cookie.get( 'foo', 'bar' );
index 587c893..46d7837 100644 (file)
@@ -1,7 +1,7 @@
 ( function ( $, mw ) {
        QUnit.module( 'mediawiki.errorLogger', QUnit.newMwEnvironment() );
 
-       QUnit.test( 'installGlobalHandler', 7, function ( assert ) {
+       QUnit.test( 'installGlobalHandler', function ( assert ) {
                var w = {},
                        errorMessage = 'Foo',
                        errorUrl = 'http://example.com',
@@ -24,7 +24,7 @@
                w.onerror( errorMessage, errorUrl, errorLine, errorColumn, errorObject );
                sinon.assert.calledWithExactly( mw.track, 'global.error',
                        sinon.match( { errorMessage: errorMessage, url: errorUrl, lineNumber: errorLine,
-                       columnNumber: errorColumn, errorObject: errorObject } ) );
+                               columnNumber: errorColumn, errorObject: errorObject } ) );
 
                w = { onerror: oldHandler };
 
index 774b205..177c358 100644 (file)
@@ -17,7 +17,7 @@
 
        QUnit.module( 'mediawiki.experiments' );
 
-       QUnit.test( 'getBucket( experiment, token )', 4, function ( assert ) {
+       QUnit.test( 'getBucket( experiment, token )', function ( assert ) {
                var experiment = createExperiment(),
                        token = '123457890';
 
index b4028ec..16f8cf3 100644 (file)
@@ -1,7 +1,7 @@
 ( function ( mw ) {
        QUnit.module( 'mediawiki.html' );
 
-       QUnit.test( 'escape', 2, function ( assert ) {
+       QUnit.test( 'escape', function ( assert ) {
                assert.throws(
                        function () {
                                mw.html.escape();
@@ -17,7 +17,7 @@
                );
        } );
 
-       QUnit.test( 'element()', 1, function ( assert ) {
+       QUnit.test( 'element()', function ( assert ) {
                assert.equal(
                        mw.html.element(),
                        '<undefined/>',
                );
        } );
 
-       QUnit.test( 'element( tagName )', 1, function ( assert ) {
+       QUnit.test( 'element( tagName )', function ( assert ) {
                assert.equal( mw.html.element( 'div' ), '<div/>', 'DIV' );
        } );
 
-       QUnit.test( 'element( tagName, attrs )', 2, function ( assert ) {
+       QUnit.test( 'element( tagName, attrs )', function ( assert ) {
                assert.equal( mw.html.element( 'div', {} ), '<div/>', 'DIV' );
 
                assert.equal(
@@ -43,7 +43,7 @@
                );
        } );
 
-       QUnit.test( 'element( tagName, attrs, content )', 8, function ( assert ) {
+       QUnit.test( 'element( tagName, attrs, content )', function ( assert ) {
 
                assert.equal( mw.html.element( 'div', {}, '' ), '<div></div>', 'DIV with empty attributes and content' );
 
index f848f3e..3b549bd 100644 (file)
@@ -1,4 +1,5 @@
 ( function ( mw, $ ) {
+       /* eslint-disable camelcase */
        var formatText, formatParse, formatnumTests, specialCharactersPageName, expectedListUsers,
                expectedListUsersSitename, expectedLinkPagenamee, expectedEntrypoints,
                mwLanguageCache = {},
@@ -45,7 +46,6 @@
                },
                config: {
                        wgArticlePath: '/wiki/$1',
-                       // jscs:disable requireCamelCaseOrUpperCaseIdentifiers
                        wgNamespaceIds: {
                                template: 10,
                                template_talk: 11,
@@ -53,7 +53,6 @@
                                szablon: 10,
                                dyskusja_szablonu: 11
                        },
-                       // jscs:enable requireCamelCaseOrUpperCaseIdentifiers
                        wgFormattedNamespaces: {
                                // Localised
                                10: 'Szablon',
         *  that may be asynchronous. Invoke the callback parameter when done.
         */
        function process( tasks ) {
-               /*jshint latedef:false */
                function abort() {
                        tasks.splice( 0, tasks.length );
+                       // eslint-disable-next-line no-use-before-define
                        next();
                }
                function next() {
+                       var task;
                        if ( !tasks ) {
                                // This happens if after the process is completed, one of our callbacks is
                                // invoked. This can happen if a test timed out but the process was still
                                // running. In that case, ignore it. Don't invoke complete() a second time.
                                return;
                        }
-                       var task = tasks.shift();
+                       task = tasks.shift();
                        if ( task ) {
                                task( next, abort );
                        } else {
                next();
        }
 
-       QUnit.test( 'Replace', 15, function ( assert ) {
+       QUnit.test( 'Replace', function ( assert ) {
                mw.messages.set( 'simple', 'Foo $1 baz $2' );
 
                assert.equal( formatParse( 'simple' ), 'Foo $1 baz $2', 'Replacements with no substitutes' );
                );
        } );
 
-       QUnit.test( 'Plural', 9, function ( assert ) {
+       QUnit.test( 'Plural', function ( assert ) {
                assert.equal( formatParse( 'plural-msg', 0 ), 'Found 0 items', 'Plural test for english with zero as count' );
                assert.equal( formatParse( 'plural-msg', 1 ), 'Found 1 item', 'Singular test for english' );
                assert.equal( formatParse( 'plural-msg', 2 ), 'Found 2 items', 'Plural test for english' );
                assert.equal( formatParse( 'plural-empty-explicit-form', 2 ), 'There is me and other people.' );
        } );
 
-       QUnit.test( 'Gender', 15, function ( assert ) {
+       QUnit.test( 'Gender', function ( assert ) {
                var originalGender = mw.user.options.get( 'gender' );
 
                // TODO: These tests should be for mw.msg once mw.msg integrated with mw.jqueryMsg
                mw.user.options.set( 'gender', originalGender );
        } );
 
-       QUnit.test( 'Case changing', 8, function ( assert ) {
+       QUnit.test( 'Case changing', function ( assert ) {
                mw.messages.set( 'to-lowercase', '{{lc:thIS hAS MEsSed uP CapItaliZatiON}}' );
                assert.equal( formatParse( 'to-lowercase' ), 'this has messed up capitalization', 'To lowercase' );
 
                assert.equal( formatParse( 'all-caps-except-first' ), 'tHIS HAS MESSED UP CAPITALIZATION', 'To opposite sentence case' );
        } );
 
-       QUnit.test( 'Grammar', 2, function ( assert ) {
+       QUnit.test( 'Grammar', function ( assert ) {
                assert.equal( formatParse( 'grammar-msg' ), 'Przeszukaj Wiki', 'Grammar Test with sitename' );
 
                mw.messages.set( 'grammar-msg-wrong-syntax', 'Przeszukaj {{GRAMMAR:grammar_case_xyz}}' );
                assert.equal( formatParse( 'grammar-msg-wrong-syntax' ), 'Przeszukaj ', 'Grammar Test with wrong grammar template syntax' );
        } );
 
-       QUnit.test( 'Match PHP parser', mw.libs.phpParserData.tests.length, function ( assert ) {
+       QUnit.test( 'Match PHP parser', function ( assert ) {
+               var tasks;
                mw.messages.set( mw.libs.phpParserData.messages );
-               var tasks = $.map( mw.libs.phpParserData.tests, function ( test ) {
+               tasks = $.map( mw.libs.phpParserData.tests, function ( test ) {
                        var done = assert.async();
                        return function ( next, abort ) {
                                getMwLanguage( test.lang )
                                        .then( function ( langClass ) {
+                                               var parser;
                                                mw.config.set( 'wgUserLanguage', test.lang );
-                                               var parser = new mw.jqueryMsg.parser( { language: langClass } );
+                                               // eslint-disable-next-line new-cap
+                                               parser = new mw.jqueryMsg.parser( { language: langClass } );
                                                assert.equal(
                                                        parser.parse( test.key, test.args ).html(),
                                                        test.result,
                process( tasks );
        } );
 
-       QUnit.test( 'Links', 15, function ( assert ) {
+       QUnit.test( 'Links', function ( assert ) {
                var testCases,
                        expectedDisambiguationsText,
                        expectedMultipleBars,
                } );
        } );
 
-       QUnit.test( 'Replacements in links', 14, function ( assert ) {
+       QUnit.test( 'Replacements in links', function ( assert ) {
                var testCases = [
                        [
                                'extlink-param-href-full',
        } );
 
        // Tests that {{-transformation vs. general parsing are done as requested
-       QUnit.test( 'Curly brace transformation', 16, function ( assert ) {
+       QUnit.test( 'Curly brace transformation', function ( assert ) {
                var oldUserLang = mw.config.get( 'wgUserLanguage' );
 
                assertBothModes( assert, [ 'gender-msg', 'Bob', 'male' ], 'Bob: blue', 'gender is resolved' );
                mw.config.set( 'wgUserLanguage', oldUserLang );
        } );
 
-       QUnit.test( 'Int', 4, function ( assert ) {
+       QUnit.test( 'Int', function ( assert ) {
                var newarticletextSource = 'You have followed a link to a page that does not exist yet. To create the page, start typing in the box below (see the [[{{Int:Foobar}}|foobar]] for more info). If you are here by mistake, click your browser\'s back button.',
                        expectedNewarticletext,
                        helpPageTitle = 'Help:Foobar';
                );
        } );
 
-       QUnit.test( 'Ns', 4, function ( assert ) {
+       QUnit.test( 'Ns', function ( assert ) {
                mw.messages.set( 'ns-template-talk', '{{ns:Template talk}}' );
                assert.equal(
                        formatParse( 'ns-template-talk' ),
 
        // Tests that getMessageFunction is used for non-plain messages with curly braces or
        // square brackets, but not otherwise.
-       QUnit.test( 'mw.Message.prototype.parser monkey-patch', 22, function ( assert ) {
+       QUnit.test( 'mw.Message.prototype.parser monkey-patch', function ( assert ) {
                var oldGMF, outerCalled, innerCalled;
 
                mw.messages.set( {
                }
        ];
 
-       QUnit.test( 'formatnum', formatnumTests.length, function ( assert ) {
+       QUnit.test( 'formatnum', function ( assert ) {
+               var queue;
                mw.messages.set( 'formatnum-msg', '{{formatnum:$1}}' );
                mw.messages.set( 'formatnum-msg-int', '{{formatnum:$1|R}}' );
-               var queue = $.map( formatnumTests, function ( test ) {
+               queue = $.map( formatnumTests, function ( test ) {
                        var done = assert.async();
                        return function ( next, abort ) {
                                getMwLanguage( test.lang )
                                        .then( function ( langClass ) {
+                                               var parser;
                                                mw.config.set( 'wgUserLanguage', test.lang );
-                                               var parser = new mw.jqueryMsg.parser( { language: langClass } );
+                                               // eslint-disable-next-line new-cap
+                                               parser = new mw.jqueryMsg.parser( { language: langClass } );
                                                assert.equal(
                                                        parser.parse( test.integer ? 'formatnum-msg-int' : 'formatnum-msg',
                                                                [ test.number ] ).html(),
        } );
 
        // HTML in wikitext
-       QUnit.test( 'HTML', 33, function ( assert ) {
+       QUnit.test( 'HTML', function ( assert ) {
                mw.messages.set( 'jquerymsg-italics-msg', '<i>Very</i> important' );
 
                assertBothModes( assert, [ 'jquerymsg-italics-msg' ], mw.messages.get( 'jquerymsg-italics-msg' ), 'Simple italics unchanged' );
                );
        } );
 
-       QUnit.test( 'Nowiki', 3, function ( assert ) {
+       QUnit.test( 'Nowiki', function ( assert ) {
                mw.messages.set( 'jquerymsg-nowiki-link', 'Foo <nowiki>[[bar]]</nowiki> baz.' );
                assert.equal(
                        formatParse( 'jquerymsg-nowiki-link' ),
                );
        } );
 
-       QUnit.test( 'Behavior in case of invalid wikitext', 3, function ( assert ) {
+       QUnit.test( 'Behavior in case of invalid wikitext', function ( assert ) {
+               var logSpy;
                mw.messages.set( 'invalid-wikitext', '<b>{{FAIL}}</b>' );
 
                this.suppressWarnings();
-               var logSpy = this.sandbox.spy( mw.log, 'warn' );
+               logSpy = this.sandbox.spy( mw.log, 'warn' );
 
                assert.equal(
                        formatParse( 'invalid-wikitext' ),
                assert.equal( logSpy.callCount, 2, 'mw.log.warn calls' );
        } );
 
-       QUnit.test( 'Integration', 5, function ( assert ) {
+       QUnit.test( 'Integration', function ( assert ) {
                var expected, logSpy, msg;
 
                expected = '<b><a title="Bold" href="/wiki/Bold">Bold</a>!</b>';
index 3b5915a..b0b2e7a 100644 (file)
@@ -5,7 +5,7 @@
 ( function ( $ ) {
        QUnit.module( 'mediawiki.jscompat', QUnit.newMwEnvironment() );
 
-       QUnit.test( 'Variable with Unicode letter in name', 3, function ( assert ) {
+       QUnit.test( 'Variable with Unicode letter in name', function ( assert ) {
                var orig, ŝablono;
 
                orig = 'some token';
        });
        */
 
-       QUnit.test( 'Stripping of single initial newline from textarea\'s literal contents (bug 12130)', function ( assert ) {
+       QUnit.test( 'Stripping of single initial newline from textarea\'s literal contents (T14130)', function ( assert ) {
                var maxn, n,
                        expected, $textarea;
 
                maxn = 4;
-               QUnit.expect( maxn * 2 );
 
                function repeat( str, n ) {
                        var out;
index 2171f34..b965079 100644 (file)
@@ -1,6 +1,8 @@
 ( function ( mw, $ ) {
        'use strict';
 
+       var grammarTests;
+
        QUnit.module( 'mediawiki.language', QUnit.newMwEnvironment( {
                setup: function () {
                        this.liveLangData = mw.language.data;
@@ -17,7 +19,7 @@
                }
        } ) );
 
-       QUnit.test( 'mw.language getData and setData', 3, function ( assert ) {
+       QUnit.test( 'mw.language getData and setData', function ( assert ) {
                mw.language.setData( 'en', 'testkey', 'testvalue' );
                assert.equal( mw.language.getData( 'en', 'testkey' ), 'testvalue', 'Getter setter test for mw.language' );
                assert.equal( mw.language.getData( 'en', 'invalidkey' ), undefined, 'Getter setter test for mw.language with invalid key' );
@@ -25,7 +27,7 @@
                assert.equal( mw.language.getData( 'en-US', 'testkey' ), 'testvalue', 'Case insensitive test for mw.language' );
        } );
 
-       QUnit.test( 'mw.language.commafy test', 9, function ( assert ) {
+       QUnit.test( 'mw.language.commafy test', function ( assert ) {
                mw.language.setData( 'en', 'digitGroupingPattern', null );
                mw.language.setData( 'en', 'digitTransformTable', null );
                mw.language.setData( 'en', 'separatorTransformTable', null );
                assert.equal( mw.language.commafy( 123456789.567, '###,###,#0.00' ), '1,234,567,89.56', 'Decimal part as group of 3 and last one 2' );
        } );
 
-       QUnit.test( 'mw.language.convertNumber', 2, function ( assert ) {
+       QUnit.test( 'mw.language.convertNumber', function ( assert ) {
                mw.language.setData( 'en', 'digitGroupingPattern', null );
                mw.language.setData( 'en', 'digitTransformTable', null );
                mw.language.setData( 'en', 'separatorTransformTable', { ',': '.', '.': ',' } );
                mw.config.set( 'wgUserLanguage', 'en' );
+               mw.config.set( 'wgTranslateNumerals', true );
 
                assert.equal( mw.language.convertNumber( 1800 ), '1.800', 'formatting' );
                assert.equal( mw.language.convertNumber( '1.800', true ), '1800', 'unformatting' );
        } );
 
+       QUnit.test( 'mw.language.convertNumber - digitTransformTable', function ( assert ) {
+               mw.config.set( 'wgUserLanguage', 'hi' );
+               mw.config.set( 'wgTranslateNumerals', true );
+               mw.language.setData( 'hi', 'digitGroupingPattern', null );
+               mw.language.setData( 'hi', 'separatorTransformTable', { ',': '.', '.': ',' } );
+
+               // Example from Hindi (MessagesHi.php)
+               mw.language.setData( 'hi', 'digitTransformTable', {
+                       0: '०',
+                       1: '१',
+                       2: '२'
+               } );
+
+               assert.equal( mw.language.convertNumber( 1200 ), '१.२००', 'format' );
+               assert.equal( mw.language.convertNumber( '१.२००', true ), '1200', 'unformat from digit transform' );
+               assert.equal( mw.language.convertNumber( '1.200', true ), '1200', 'unformat plain' );
+
+               mw.config.set( 'wgTranslateNumerals', false );
+
+               assert.equal( mw.language.convertNumber( 1200 ), '1.200', 'format (digit transform disabled)' );
+               assert.equal( mw.language.convertNumber( '१.२००', true ), '1200', 'unformat from digit transform (when disabled)' );
+               assert.equal( mw.language.convertNumber( '1.200', true ), '1200', 'unformat plain (digit transform disabled)' );
+       } );
+
        function grammarTest( langCode, test ) {
                // The test works only if the content language is opt.language
                // because it requires [lang].js to be loaded.
                QUnit.test( 'Grammar test for lang=' + langCode, function ( assert ) {
-                       QUnit.expect( test.length );
-
-                       for ( var i = 0; i < test.length; i++ ) {
+                       var i;
+                       for ( i = 0; i < test.length; i++ ) {
                                assert.equal(
                                        mw.language.convertGrammar( test[ i ].word, test[ i ].grammarForm ),
                                        test[ i ].expected,
@@ -70,7 +96,7 @@
        }
 
        // These tests run only for the current UI language.
-       var grammarTests = {
+       grammarTests = {
                bs: [
                        {
                                word: 'word',
                }
        } );
 
-       QUnit.test( 'List to text test', 4, function ( assert ) {
+       QUnit.test( 'List to text test', function ( assert ) {
                assert.equal( mw.language.listToText( [] ), '', 'Blank list' );
                assert.equal( mw.language.listToText( [ 'a' ] ), 'a', 'Single item' );
                assert.equal( mw.language.listToText( [ 'a', 'b' ] ), 'a and b', 'Two items' );
index 92ee7dd..6f9af76 100644 (file)
 
                function isCssImportApplied() {
                        // Trigger reflow, repaint, redraw, whatever (cross-browser)
-                       var x = $element.css( 'height' );
-                       x = el.innerHTML;
+                       $element.css( 'height' );
+                       el.innerHTML;
                        el.className = el.className;
-                       x = document.documentElement.clientHeight;
+                       document.documentElement.clientHeight;
 
                        return $element.css( prop ) === val;
                }
@@ -75,7 +75,7 @@
                );
        }
 
-       QUnit.test( 'Basic', 2, function ( assert ) {
+       QUnit.test( 'Basic', function ( assert ) {
                var isAwesomeDone;
 
                mw.loader.testCallback = function () {
@@ -94,7 +94,7 @@
                } );
        } );
 
-       QUnit.test( 'Object method as module name', 2, function ( assert ) {
+       QUnit.test( 'Object method as module name', function ( assert ) {
                var isAwesomeDone;
 
                mw.loader.testCallback = function () {
                } );
        } );
 
-       QUnit.test( '.using( .. ) Promise', 2, function ( assert ) {
+       QUnit.test( '.using( .. ) Promise', function ( assert ) {
                var isAwesomeDone;
 
                mw.loader.testCallback = function () {
                ).always( done );
        } );
 
-       QUnit.test( '.load() - Error: Unregistered (ignored)', 0, function ( assert ) {
+       QUnit.test( '.load() - Error: Unregistered (ignored)', function ( assert ) {
+               assert.expect( 0 );
                mw.loader.load( 'test.using.unreg2' );
        } );
 
-       QUnit.test( '.implement( styles={ "css": [text, ..] } )', 2, function ( assert ) {
+       QUnit.test( '.implement( styles={ "css": [text, ..] } )', function ( assert ) {
                var $element = $( '<div class="mw-test-implement-a"></div>' ).appendTo( '#qunit-fixture' );
 
                assert.notEqual(
                return mw.loader.using( 'test.implement.a' );
        } );
 
-       QUnit.test( '.implement( styles={ "url": { <media>: [url, ..] } } )', 7, function ( assert ) {
+       QUnit.test( '.implement( styles={ "url": { <media>: [url, ..] } } )', function ( assert ) {
                var $element1 = $( '<div class="mw-test-implement-b1"></div>' ).appendTo( '#qunit-fixture' ),
                        $element2 = $( '<div class="mw-test-implement-b2"></div>' ).appendTo( '#qunit-fixture' ),
                        $element3 = $( '<div class="mw-test-implement-b3"></div>' ).appendTo( '#qunit-fixture' ),
                                url: {
                                        print: [ urlStyleTest( '.mw-test-implement-b1', 'text-align', 'center' ) ],
                                        screen: [
-                                               // bug 40834: Make sure it actually works with more than 1 stylesheet reference
+                                               // T42834: Make sure it actually works with more than 1 stylesheet reference
                                                urlStyleTest( '.mw-test-implement-b2', 'float', 'left' ),
                                                urlStyleTest( '.mw-test-implement-b3', 'float', 'right' )
                                        ]
        } );
 
        // Backwards compatibility
-       QUnit.test( '.implement( styles={ <media>: text } ) (back-compat)', 2, function ( assert ) {
+       QUnit.test( '.implement( styles={ <media>: text } ) (back-compat)', function ( assert ) {
                var $element = $( '<div class="mw-test-implement-c"></div>' ).appendTo( '#qunit-fixture' );
 
                assert.notEqual(
        } );
 
        // Backwards compatibility
-       QUnit.test( '.implement( styles={ <media>: [url, ..] } ) (back-compat)', 4, function ( assert ) {
+       QUnit.test( '.implement( styles={ <media>: [url, ..] } ) (back-compat)', function ( assert ) {
                var $element = $( '<div class="mw-test-implement-d"></div>' ).appendTo( '#qunit-fixture' ),
                        $element2 = $( '<div class="mw-test-implement-d2"></div>' ).appendTo( '#qunit-fixture' ),
                        done = assert.async();
                        'test.implement.d',
                        function () {
                                assertStyleAsync( assert, $element, 'float', 'right', function () {
-                                       assert.notEqual( $element2.css( 'text-align' ), 'center', 'print style is not applied (bug 40500)' );
+                                       assert.notEqual( $element2.css( 'text-align' ), 'center', 'print style is not applied (T42500)' );
                                        done();
                                } );
                        },
                mw.loader.load( 'test.implement.d' );
        } );
 
-       // @import (bug 31676)
-       QUnit.test( '.implement( styles has @import )', 7, function ( assert ) {
+       // @import (T33676)
+       QUnit.test( '.implement( styles has @import )', function ( assert ) {
                var isJsExecuted, $element,
                        done = assert.async();
 
                } );
        } );
 
-       QUnit.test( '.implement( dependency with styles )', 4, function ( assert ) {
+       QUnit.test( '.implement( dependency with styles )', function ( assert ) {
                var $element = $( '<div class="mw-test-implement-e"></div>' ).appendTo( '#qunit-fixture' ),
                        $element2 = $( '<div class="mw-test-implement-e2"></div>' ).appendTo( '#qunit-fixture' );
 
                return mw.loader.using( 'test.implement.e' );
        } );
 
-       QUnit.test( '.implement( only scripts )', 1, function ( assert ) {
+       QUnit.test( '.implement( only scripts )', function ( assert ) {
                mw.loader.implement( 'test.onlyscripts', function () {} );
                assert.strictEqual( mw.loader.getState( 'test.onlyscripts' ), 'ready' );
        } );
 
-       QUnit.test( '.implement( only messages )', 2, function ( assert ) {
-               assert.assertFalse( mw.messages.exists( 'bug_29107' ), 'Verify that the test message doesn\'t exist yet' );
+       QUnit.test( '.implement( only messages )', function ( assert ) {
+               assert.assertFalse( mw.messages.exists( 'T31107' ), 'Verify that the test message doesn\'t exist yet' );
 
-               // jscs: disable requireCamelCaseOrUpperCaseIdentifiers
-               mw.loader.implement( 'test.implement.msgs', [], {}, { bug_29107: 'loaded' } );
-               // jscs: enable requireCamelCaseOrUpperCaseIdentifiers
+               mw.loader.implement( 'test.implement.msgs', [], {}, { T31107: 'loaded' } );
 
                return mw.loader.using( 'test.implement.msgs', function () {
-                       assert.ok( mw.messages.exists( 'bug_29107' ), 'Bug 29107: messages-only module should implement ok' );
+                       assert.ok( mw.messages.exists( 'T31107' ), 'T31107: messages-only module should implement ok' );
                }, function () {
                        assert.ok( false, 'Error callback fired while implementing "test.implement.msgs" module' );
                } );
        } );
 
-       QUnit.test( '.implement( empty )', 1, function ( assert ) {
+       QUnit.test( '.implement( empty )', function ( assert ) {
                mw.loader.implement( 'test.empty' );
                assert.strictEqual( mw.loader.getState( 'test.empty' ), 'ready' );
        } );
 
-       QUnit.test( 'Broken indirect dependency', 4, function ( assert ) {
+       QUnit.test( 'Broken indirect dependency', function ( assert ) {
                // don't emit an error event
                this.sandbox.stub( mw, 'track' );
 
                assert.strictEqual( mw.track.callCount, 1 );
        } );
 
-       QUnit.test( 'Out-of-order implementation', 9, function ( assert ) {
+       QUnit.test( 'Out-of-order implementation', function ( assert ) {
                mw.loader.register( [
                        [ 'test.module4', '0' ],
                        [ 'test.module5', '0', [ 'test.module4' ] ],
                assert.strictEqual( mw.loader.getState( 'test.module6' ), 'ready', 'Expected "ready" state for test.module6' );
        } );
 
-       QUnit.test( 'Missing dependency', 13, function ( assert ) {
+       QUnit.test( 'Missing dependency', function ( assert ) {
                mw.loader.register( [
                        [ 'test.module7', '0' ],
                        [ 'test.module8', '0', [ 'test.module7' ] ],
                );
        } );
 
-       QUnit.test( 'Dependency handling', 5, function ( assert ) {
+       QUnit.test( 'Dependency handling', function ( assert ) {
                var done = assert.async();
                mw.loader.register( [
                        // [module, version, dependencies, group, source]
                );
        } );
 
-       QUnit.test( 'Skip-function handling', 5, function ( assert ) {
+       QUnit.test( 'Skip-function handling', function ( assert ) {
                mw.loader.register( [
                        // [module, version, dependencies, group, source, skip]
                        [ 'testSkipped', '1', [], null, 'testloader', 'return true;' ],
                );
        } );
 
-       QUnit.asyncTest( '.load( "//protocol-relative" ) - T32825', 2, function ( assert ) {
+       QUnit.asyncTest( '.load( "//protocol-relative" ) - T32825', function ( assert ) {
                // This bug was actually already fixed in 1.18 and later when discovered in 1.17.
                // Test is for regressions!
 
                mw.loader.load( target );
        } );
 
-       QUnit.asyncTest( '.load( "/absolute-path" )', 2, function ( assert ) {
+       QUnit.asyncTest( '.load( "/absolute-path" )', function ( assert ) {
                // Forge a URL to the test callback script
                var target = QUnit.fixurl(
                        mw.config.get( 'wgScriptPath' ) + '/tests/qunit/data/qunitOkCall.js'
                } );
        } );
 
-       QUnit.test( 'Executing race - T112232', 2, function ( assert ) {
+       QUnit.test( 'Executing race - T112232', function ( assert ) {
                var done = false;
 
                // The red herring schedules its CSS buffer first. In T112232, a bug in the
                        } );
        } );
 
-       QUnit.test( 'require()', 6, function ( assert ) {
+       QUnit.test( 'require()', function ( assert ) {
                mw.loader.register( [
                        [ 'test.require1', '0' ],
                        [ 'test.require2', '0' ],
index b3c4bee..923f97d 100644 (file)
@@ -7,7 +7,7 @@
                }
        } ) );
 
-       QUnit.test( 'register', 2, function ( assert ) {
+       QUnit.test( 'register', function ( assert ) {
                var testMessagePosterConstructor = function () {};
 
                mw.messagePoster.factory.register( TEST_MODEL, testMessagePosterConstructor );
index 38ae5e4..cb583e7 100644 (file)
@@ -10,7 +10,7 @@
                }
        } );
 
-       QUnit.test( 'render', 2, function ( assert ) {
+       QUnit.test( 'render', function ( assert ) {
                var html, htmlPartial, data, partials,
                        template = mw.template.get( 'stub', 'test_greeting.mustache' ),
                        partial = mw.template.get( 'stub', 'test_greeting_suffix.mustache' );
index 86fd828..a282325 100644 (file)
@@ -24,7 +24,7 @@
                }
        } );
 
-       QUnit.test( 'add', 1, function ( assert ) {
+       QUnit.test( 'add', function ( assert ) {
                assert.throws(
                        function () {
                                mw.template.add( 'module', 'test_templates_foo', 'hello' );
@@ -33,7 +33,7 @@
                );
        } );
 
-       QUnit.test( 'compile', 1, function ( assert ) {
+       QUnit.test( 'compile', function ( assert ) {
                assert.throws(
                        function () {
                                mw.template.compile( '{{foo}}', 'rainbow' );
@@ -42,7 +42,7 @@
                );
        } );
 
-       QUnit.test( 'get', 4, function ( assert ) {
+       QUnit.test( 'get', function ( assert ) {
                assert.strictEqual( mw.template.get( 'test.mediawiki.template', 'test_templates_foo.xyz' ), 'xyz compiler' );
                assert.strictEqual( mw.template.get( 'test.mediawiki.template', 'test_templates_foo.abc' ), 'abc default compiler' );
                assert.throws(
index 65b7263..d3e73ae 100644 (file)
@@ -31,7 +31,7 @@
                }
        } ) );
 
-       QUnit.test( 'Initial check', 8, function ( assert ) {
+       QUnit.test( 'Initial check', function ( assert ) {
                assert.ok( window.jQuery, 'jQuery defined' );
                assert.ok( window.$, '$ defined' );
                assert.strictEqual( window.$, window.jQuery, '$ alias to jQuery' );
@@ -51,7 +51,7 @@
                this.restoreWarnings();
        } );
 
-       QUnit.test( 'mw.format', 2, function ( assert ) {
+       QUnit.test( 'mw.format', function ( assert ) {
                assert.equal(
                        mw.format( 'Format $1 $2', 'foo', 'bar' ),
                        'Format foo bar',
 
        } );
 
-       QUnit.test( 'mw.msg', 14, function ( assert ) {
+       QUnit.test( 'mw.msg', function ( assert ) {
                assert.ok( mw.messages.set( 'hello', 'Hello <b>awesome</b> world' ), 'mw.messages.set: Register' );
                assert.equal( mw.msg( 'hello' ), 'Hello <b>awesome</b> world', 'Gets message with default options (existing message)' );
                assert.equal( mw.msg( 'goodbye' ), '⧼goodbye⧽', 'Gets message with default options (nonexistent message)' );
                assert.equal( mw.msg( 'int-msg' ), 'Some Other Message', 'int is resolved' );
        } );
 
-       QUnit.test( 'mw.hook', 13, function ( assert ) {
+       QUnit.test( 'mw.hook', function ( assert ) {
                var hook, add, fire, chars, callback;
 
                mw.hook( 'test.hook.unfired' ).add( function () {
index 89eb45f..297f0fd 100644 (file)
@@ -6,7 +6,7 @@
                }
        } ) );
 
-       QUnit.asyncTest( 'toggleToc', 4, function ( assert ) {
+       QUnit.asyncTest( 'toggleToc', function ( assert ) {
                var tocHtml, $toggleLink, $tocList;
 
                assert.strictEqual( $( '#toc' ).length, 0, 'There is no table of contents on the page at the beginning' );
index 5329be6..6c27c5b 100644 (file)
@@ -1,7 +1,7 @@
 ( function ( mw ) {
        QUnit.module( 'mediawiki.track' );
 
-       QUnit.test( 'track', 1, function ( assert ) {
+       QUnit.test( 'track', function ( assert ) {
                var sequence = [];
                mw.trackSubscribe( 'simple', function ( topic, data ) {
                        sequence.push( [ topic, data ] );
@@ -15,7 +15,7 @@
                ], 'Events after subscribing' );
        } );
 
-       QUnit.test( 'trackSubscribe', 4, function ( assert ) {
+       QUnit.test( 'trackSubscribe', function ( assert ) {
                var now,
                        sequence = [];
                mw.track( 'before', { key: 1 } );
@@ -40,7 +40,7 @@
                } );
        } );
 
-       QUnit.test( 'trackUnsubscribe', 1, function ( assert ) {
+       QUnit.test( 'trackUnsubscribe', function ( assert ) {
                var sequence = [];
                function unsubber( topic, data ) {
                        sequence.push( [ topic, data ] );
index 6dd17f1..01665e5 100644 (file)
@@ -29,7 +29,7 @@
                        [ false, ':::' ],
                        [ false, '::0:', 'IPv6 ending in a lone ":"' ],
 
-                       [ true,  '::', 'IPv6 zero address' ],
+                       [ true, '::', 'IPv6 zero address' ],
 
                        [ false, '::fc:100:a:d:1:e:ac:0', 'IPv6 with "::" and 8 words' ],
                        [ false, '::fc:100:a:d:1:e:ac:0:1', 'IPv6 with 9 words' ],
                        [ false, 'fc::100:', 'IPv6 ending with lone ":"' ],
                        [ false, 'fc:::100', 'IPv6 with ":::" in the middle' ],
 
-                       [ true,  'fc::100', 'IPv6 with "::" and 2 words' ],
-                       [ true,  'fc::100:a', 'IPv6 with "::" and 3 words' ],
-                       [ true,  'fc::100:a:d', 'IPv6 with "::" and 4 words' ],
-                       [ true,  'fc::100:a:d:1', 'IPv6 with "::" and 5 words' ],
-                       [ true,  'fc::100:a:d:1:e', 'IPv6 with "::" and 6 words' ],
-                       [ true,  'fc::100:a:d:1:e:ac', 'IPv6 with "::" and 7 words' ],
-                       [ true,  '2001::df', 'IPv6 with "::" and 2 words' ],
-                       [ true,  '2001:5c0:1400:a::df', 'IPv6 with "::" and 5 words' ],
-                       [ true,  '2001:5c0:1400:a::df:2', 'IPv6 with "::" and 6 words' ],
+                       [ true, 'fc::100', 'IPv6 with "::" and 2 words' ],
+                       [ true, 'fc::100:a', 'IPv6 with "::" and 3 words' ],
+                       [ true, 'fc::100:a:d', 'IPv6 with "::" and 4 words' ],
+                       [ true, 'fc::100:a:d:1', 'IPv6 with "::" and 5 words' ],
+                       [ true, 'fc::100:a:d:1:e', 'IPv6 with "::" and 6 words' ],
+                       [ true, 'fc::100:a:d:1:e:ac', 'IPv6 with "::" and 7 words' ],
+                       [ true, '2001::df', 'IPv6 with "::" and 2 words' ],
+                       [ true, '2001:5c0:1400:a::df', 'IPv6 with "::" and 5 words' ],
+                       [ true, '2001:5c0:1400:a::df:2', 'IPv6 with "::" and 6 words' ],
 
                        [ false, 'fc::100:a:d:1:e:ac:0', 'IPv6 with "::" and 8 words' ],
                        [ false, 'fc::100:a:d:1:e:ac:0:1', 'IPv6 with 9 words' ]
                }
        } ) );
 
-       QUnit.test( 'rawurlencode', 1, function ( assert ) {
+       QUnit.test( 'rawurlencode', function ( assert ) {
                assert.equal( mw.util.rawurlencode( 'Test:A & B/Here' ), 'Test%3AA%20%26%20B%2FHere' );
        } );
 
-       QUnit.test( 'escapeId', 17, function ( assert ) {
+       QUnit.test( 'escapeId', function ( assert ) {
                mw.config.set( 'wgExperimentalHtmlIds', false );
                $.each( {
                        '+': '.2B',
                } );
        } );
 
-       QUnit.test( 'wikiUrlencode', 11, function ( assert ) {
+       QUnit.test( 'wikiUrlencode', function ( assert ) {
                assert.equal( mw.util.wikiUrlencode( 'Test:A & B/Here' ), 'Test:A_%26_B/Here' );
                // See also wfUrlencodeTest.php#provideURLS
                $.each( {
                } );
        } );
 
-       QUnit.test( 'getUrl', 14, function ( assert ) {
+       QUnit.test( 'getUrl', function ( assert ) {
                var href;
                mw.config.set( {
                        wgScript: '/w/index.php',
                assert.equal( href, '/w/index.php?action=edit#.2B.26.3D:.3B.40.24-_..21.2A.2F.5B.5D.3C.3E.27.C2.A7', 'fragment with various characters' );
        } );
 
-       QUnit.test( 'wikiScript', 4, function ( assert ) {
+       QUnit.test( 'wikiScript', function ( assert ) {
                mw.config.set( {
                        // customized wgScript for T41103
                        wgScript: '/w/i.php',
                assert.equal( mw.util.wikiScript( 'api' ), '/w/api.php', 'API path' );
        } );
 
-       QUnit.test( 'addCSS', 3, function ( assert ) {
+       QUnit.test( 'addCSS', function ( assert ) {
                var $el, style;
                $el = $( '<div>' ).attr( 'id', 'mw-addcsstest' ).appendTo( '#qunit-fixture' );
 
                $( style.ownerNode ).remove();
        } );
 
-       QUnit.test( 'getParamValue', 5, function ( assert ) {
+       QUnit.test( 'getParamValue', function ( assert ) {
                var url;
 
                url = 'http://example.org/?foo=wrong&foo=right#&foo=bad';
                assert.strictEqual( mw.util.getParamValue( 'bar', url ), null, 'Return null when not found' );
 
                url = 'http://example.org/#&foo=bad';
-               assert.strictEqual( mw.util.getParamValue( 'foo', url ), null, 'Ignore hash if param is not in querystring but in hash (bug 27427)' );
+               assert.strictEqual( mw.util.getParamValue( 'foo', url ), null, 'Ignore hash if param is not in querystring but in hash (T29427)' );
 
                url = 'example.org?' + $.param( { TEST: 'a b+c' } );
-               assert.strictEqual( mw.util.getParamValue( 'TEST', url ), 'a b+c', 'Bug 30441: getParamValue must understand "+" encoding of space' );
+               assert.strictEqual( mw.util.getParamValue( 'TEST', url ), 'a b+c', 'T32441: getParamValue must understand "+" encoding of space' );
 
                url = 'example.org?' + $.param( { TEST: 'a b+c d' } ); // check for sloppy code from r95332 :)
-               assert.strictEqual( mw.util.getParamValue( 'TEST', url ), 'a b+c d', 'Bug 30441: getParamValue must understand "+" encoding of space (multiple spaces)' );
+               assert.strictEqual( mw.util.getParamValue( 'TEST', url ), 'a b+c d', 'T32441: getParamValue must understand "+" encoding of space (multiple spaces)' );
        } );
 
-       QUnit.test( '$content', 2, function ( assert ) {
+       QUnit.test( '$content', function ( assert ) {
                assert.ok( mw.util.$content instanceof jQuery, 'mw.util.$content instance of jQuery' );
                assert.strictEqual( mw.util.$content.length, 1, 'mw.util.$content must have length of 1' );
        } );
         * Previously, test elements where invisible to the selector since only
         * one element can have a given id.
         */
-       QUnit.test( 'addPortletLink', 13, function ( assert ) {
+       QUnit.test( 'addPortletLink', function ( assert ) {
                var pTestTb, pCustom, vectorTabs, tbRL, cuQuux, $cuQuux, tbMW, $tbMW, tbRLDM, caFoo,
                        addedAfter, tbRLDMnonexistentid, tbRLDMemptyjquery;
 
                assert.equal(
                        $( '#p-test-custom #c-barmenu ul li' ).length,
                        1,
-                       'addPortletLink did not add the item to all <ul> elements in the portlet (bug 35082)'
+                       'addPortletLink did not add the item to all <ul> elements in the portlet (T37082)'
                );
 
                tbRLDM = mw.util.addPortletLink( 'p-test-tb', '//mediawiki.org/wiki/RL/DM',
                assert.equal( tbRLDMemptyjquery, $( '#p-test-tb li:last' )[ 0 ], 'Fallback to adding at the end (nextnode as empty jQuery object)' );
        } );
 
-       QUnit.test( 'validateEmail', 6, function ( assert ) {
+       QUnit.test( 'validateEmail', function ( assert ) {
                assert.strictEqual( mw.util.validateEmail( '' ), null, 'Should return null for empty string ' );
                assert.strictEqual( mw.util.validateEmail( 'user@localhost' ), true, 'Return true for a valid e-mail address' );
 
                assert.strictEqual( mw.util.validateEmail( 'userfoo@ex-ample.org' ), true, 'Emails may contain a hyphen' );
        } );
 
-       QUnit.test( 'isIPv6Address', 40, function ( assert ) {
+       QUnit.test( 'isIPv6Address', function ( assert ) {
                $.each( IPV6_CASES, function ( i, ipCase ) {
                        assert.strictEqual( mw.util.isIPv6Address( ipCase[ 1 ] ), ipCase[ 0 ], ipCase[ 2 ] );
                } );
        } );
 
-       QUnit.test( 'isIPv4Address', 11, function ( assert ) {
+       QUnit.test( 'isIPv4Address', function ( assert ) {
                $.each( IPV4_CASES, function ( i, ipCase ) {
                        assert.strictEqual( mw.util.isIPv4Address( ipCase[ 1 ] ), ipCase[ 0 ], ipCase[ 2 ] );
                } );
        } );
 
-       QUnit.test( 'isIPAddress', 51, function ( assert ) {
+       QUnit.test( 'isIPAddress', function ( assert ) {
                $.each( IPV4_CASES, function ( i, ipCase ) {
                        assert.strictEqual( mw.util.isIPv4Address( ipCase[ 1 ] ), ipCase[ 0 ], ipCase[ 2 ] );
                } );
index f404294..9864166 100644 (file)
@@ -25,7 +25,7 @@
                }
        } ) );
 
-       QUnit.test( 'isElementInViewport', 6, function ( assert ) {
+       QUnit.test( 'isElementInViewport', function ( assert ) {
                var viewport = $.extend( {}, DEFAULT_VIEWPORT );
                assert.ok( mw.viewport.isElementInViewport( this.el, viewport ),
                        'It should return true when the element is fully enclosed in the viewport' );
@@ -60,7 +60,7 @@
                        'It should default to the window object if no viewport is given' );
        } );
 
-       QUnit.test( 'isElementInViewport with scrolled page', 1, function ( assert ) {
+       QUnit.test( 'isElementInViewport with scrolled page', function ( assert ) {
                var viewport = {
                                top: 2000,
                                left: 0,
@@ -83,7 +83,7 @@
                window.scrollTo( 0, 0 );
        } );
 
-       QUnit.test( 'isElementCloseToViewport', 3, function ( assert ) {
+       QUnit.test( 'isElementCloseToViewport', function ( assert ) {
                var
                        viewport = {
                                top: 90,
index e6e798b..02ca243 100644 (file)
@@ -1,4 +1,4 @@
-/*global isCompatible: true */
+/* global isCompatible: true */
 ( function ( $ ) {
        var testcases = {
                tested: [
 
        QUnit.module( 'startup', QUnit.newMwEnvironment() );
 
-       QUnit.test( 'isCompatible( featureTestable )', testcases.tested.length, function ( assert ) {
+       QUnit.test( 'isCompatible( featureTestable )', function ( assert ) {
                $.each( testcases.tested, function ( i, ua ) {
-                               assert.strictEqual( isCompatible( ua ), true, ua );
-                       }
-               );
+                       assert.strictEqual( isCompatible( ua ), true, ua );
+               } );
        } );
 
-       QUnit.test( 'isCompatible( blacklisted )', testcases.blacklisted.length, function ( assert ) {
+       QUnit.test( 'isCompatible( blacklisted )', function ( assert ) {
                $.each( testcases.blacklisted, function ( i, ua ) {
-                               assert.strictEqual( isCompatible( ua ), false, ua );
-                       }
-               );
+                       assert.strictEqual( isCompatible( ua ), false, ua );
+               } );
        } );
 }( jQuery ) );