Merge "(bug 42215) "Welcome, X" as account creation title"
authorOri.livneh <ori@wikimedia.org>
Wed, 21 Nov 2012 04:15:32 +0000 (04:15 +0000)
committerGerrit Code Review <gerrit@wikimedia.org>
Wed, 21 Nov 2012 04:15:32 +0000 (04:15 +0000)
87 files changed:
RELEASE-NOTES-1.20
RELEASE-NOTES-1.21
docs/hooks.txt
includes/AutoLoader.php
includes/Category.php
includes/DefaultSettings.php
includes/GlobalFunctions.php
includes/Sanitizer.php
includes/SkinTemplate.php
includes/content/CssContentHandler.php
includes/content/JavaScriptContentHandler.php
includes/content/TextContentHandler.php
includes/content/WikitextContentHandler.php
includes/diff/DairikiDiff.php
includes/filebackend/FSFile.php
includes/filebackend/FileBackend.php
includes/filebackend/FileBackendStore.php
includes/filebackend/FileOp.php
includes/filebackend/SwiftFileBackend.php
includes/filerepo/FileRepo.php
includes/filerepo/file/File.php
includes/filerepo/file/LocalFile.php
includes/filerepo/file/UnregisteredLocalFile.php
includes/installer/Installer.i18n.php
includes/installer/MysqlUpdater.php
includes/installer/SqliteUpdater.php
includes/media/MediaHandler.php
includes/site/MediaWikiSite.php
includes/specials/SpecialUndelete.php
includes/specials/SpecialUserlogin.php
includes/upload/UploadBase.php
includes/upload/UploadFromChunks.php
includes/upload/UploadStash.php
languages/Language.php
languages/messages/MessagesBr.php
languages/messages/MessagesCa.php
languages/messages/MessagesCkb.php
languages/messages/MessagesDiq.php
languages/messages/MessagesEn.php
languages/messages/MessagesEs.php
languages/messages/MessagesEu.php
languages/messages/MessagesFr.php
languages/messages/MessagesIs.php
languages/messages/MessagesKa.php
languages/messages/MessagesKhw.php
languages/messages/MessagesKn.php
languages/messages/MessagesMin.php
languages/messages/MessagesNb.php
languages/messages/MessagesNl.php
languages/messages/MessagesPms.php
languages/messages/MessagesPs.php
languages/messages/MessagesPt.php
languages/messages/MessagesQqq.php
languages/messages/MessagesScn.php
languages/messages/MessagesSi.php
languages/messages/MessagesSk.php
languages/messages/MessagesVep.php
languages/messages/MessagesVot.php
languages/messages/MessagesZh_hans.php
languages/messages/MessagesZh_hant.php
languages/utils/CLDRPluralRuleEvaluator.php
maintenance/language/messages.inc
maintenance/sqlite/archives/patch-profiling.sql [new file with mode: 0644]
profileinfo.php
resources/jquery/jquery.tablesorter.js
resources/mediawiki.language/languages/bs.js
resources/mediawiki.language/languages/dsb.js
resources/mediawiki.language/languages/fi.js
resources/mediawiki.language/languages/ga.js
resources/mediawiki.language/languages/he.js
resources/mediawiki.language/languages/hsb.js
resources/mediawiki.language/languages/hu.js
resources/mediawiki.language/languages/hy.js
resources/mediawiki.language/languages/la.js
resources/mediawiki.language/languages/os.js
resources/mediawiki.language/languages/ru.js
resources/mediawiki.language/languages/sl.js
resources/mediawiki.language/languages/uk.js
skins/Standard.php
tests/parser/parserTest.inc
tests/parser/parserTests.txt
tests/phpunit/MediaWikiPHPUnitCommand.php
tests/phpunit/MediaWikiTestCase.php
tests/phpunit/includes/SanitizerTest.php
tests/phpunit/includes/filebackend/FileBackendTest.php
tests/phpunit/includes/parser/NewParserTest.php
tests/phpunit/languages/LanguageTest.php

index 1a92968..ea8ed6d 100644 (file)
@@ -230,8 +230,6 @@ milestone in Bugzilla.
 * (bug 36812) Special:ActiveUsers "Hide bots" should hide users from any group
   having the "bot" user right, instead of just the default "bot" user group.
 * (bug 35082) mw.util.addPortletLink incorrectly adds link to mutiple <ul> tags.
-* (bug 36495) Sanitizer::fixDeprecatedAttributes should convert "align"
-  attribute to margin or float instead of text-align (for non-table-cells).
 * (bug 36991) jquery.tablesorter should extract date sort format from date
   string instead of global config. Dates like "April 1 2012" and "1 April 2012"
   now sort correctly regardless of the content language's DefaultDateFormat.
@@ -284,6 +282,7 @@ milestone in Bugzilla.
 * (bug 40500) ResourceLoader should not ignore media-type for urls in debug mode.
 * (bug 40660) ResourceLoaderWikiModule should not convert "&nbsp;" to a space
   for pages from the MediaWiki-namespace.
+* (bug 40329) (bug 40632) Removed CleanupPresentationalAttributes feature.
 
 === API changes in 1.20 ===
 * (bug 34316) Add ability to retrieve maximum upload size from MediaWiki API.
index 70c6bf8..5abdd1e 100644 (file)
@@ -40,6 +40,7 @@ production.
 * The <data>, <time>, <meta>, and <link> elements are allowed within WikiText
   for use with Microdata.
 * The HTML5 <mark> tag has been whitelisted.
+* Added ParserCloned hook for when the Parser object is cloned.
 
 === Bug fixes in 1.21 ===
 * (bug 40353) SpecialDoubleRedirect should support interwiki redirects.
@@ -76,6 +77,8 @@ production.
 * (bug 2865)  User interface HTML elements don't use lang attribute
   (completed the fix by adding the lang attribute to firstHeading)
 * (bug 42173) Removed namespace prefixes on Special:UncategorizedCategories.
+* (bug 36053) Log in "returnto" feature forgets query parameters if no
+  title parameter was specified.
 
 === API changes in 1.21 ===
 * prop=revisions can now report the contentmodel and contentformat, see docs/contenthandler.txt
index 2ec269a..46b1b26 100644 (file)
@@ -578,6 +578,11 @@ $create: Whether or not the restoration caused the page to be created
 (i.e. it didn't exist before)
 $comment: The comment associated with the undeletion.
 
+'ArticleUndeleteLogEntry': When a log entry is generated but not yet saved.
+$pageArchive: the PageArchive object
+&$logEntry: ManualLogEntry object
+$user: User who is performing the log action
+
 'ArticleUpdateBeforeRedirect': After a page is updated (usually on save),
 before the user is redirected back to the page
 &$article: the article
index a49d901..8e2447d 100644 (file)
@@ -580,6 +580,7 @@ $wgAutoloadLocalClasses = array(
        'MoveFileOp' => 'includes/filebackend/FileOp.php',
        'DeleteFileOp' => 'includes/filebackend/FileOp.php',
        'CreateFileOp' => 'includes/filebackend/FileOp.php',
+       'DescribeFileOp' => 'includes/filebackend/FileOp.php',
        'NullFileOp' => 'includes/filebackend/FileOp.php',
 
        # includes/filerepo
index 6a5eac7..b9c9609 100644 (file)
@@ -333,7 +333,7 @@ class Category {
                        ),
                        array( 'cl_to' => $this->mName, 'page_id = cl_from' ),
                        __METHOD__,
-                       'LOCK IN SHARE MODE'
+                       array( 'LOCK IN SHARE MODE' )
                );
                $ret = $dbw->update(
                        'category',
index 494b2a3..60c3ab8 100644 (file)
@@ -2535,11 +2535,6 @@ $wgAllowRdfaAttributes = false;
  */
 $wgAllowMicrodataAttributes = false;
 
-/**
- * Cleanup as much presentational html like valign -> css vertical-align as we can
- */
-$wgCleanupPresentationalAttributes = true;
-
 /**
  * Should we try to make our HTML output well-formed XML?  If set to false,
  * output will be a few bytes shorter, and the HTML will arguably be more
@@ -4591,7 +4586,9 @@ $wgProfileOnly = false;
  * Log sums from profiling into "profiling" table in db.
  *
  * You have to create a 'profiling' table in your database before using
- * this feature, see maintenance/archives/patch-profiling.sql
+ * this feature.  Run set $wgProfileToDatabase to true in
+ * LocalSettings.php and run maintenance/update.php or otherwise
+ * manually add patch-profiling.sql to your database.
  *
  * To enable profiling, edit StartProfiler.php
  */
index 7dc9a70..982e965 100644 (file)
@@ -1214,9 +1214,18 @@ function wfLogProfilingData() {
        if ( $wgUser->isItemLoaded( 'id' ) && $wgUser->isAnon() ) {
                $forward .= ' anon';
        }
+
+       // Command line script uses a FauxRequest object which does not have
+       // any knowledge about an URL and throw an exception instead.
+       try {
+               $requestUrl = $wgRequest->getRequestURL();
+       } catch ( MWException $e ) {
+               $requestUrl = 'n/a';
+       }
+
        $log = sprintf( "%s\t%04.3f\t%s\n",
                gmdate( 'YmdHis' ), $elapsed,
-               urldecode( $wgRequest->getRequestURL() . $forward ) );
+               urldecode( $requestUrl . $forward ) );
 
        wfErrorLog( $log . $profiler->getOutput(), $wgDebugLogFile );
 }
index 7bb3d93..0034afe 100644 (file)
@@ -638,122 +638,15 @@ class Sanitizer {
        }
 
        /**
-        * Take an array of attribute names and values and fix some deprecated values
-        * for the given element type.
-        * This does not validate properties, so you should ensure that you call
-        * validateTagAttributes AFTER this to ensure that the resulting style rule
-        * this may add is safe.
-        *
-        * - Converts most presentational attributes like align into inline css
-        *
-        * @param $attribs Array
-        * @param $element String
-        * @return Array
-        */
-       static function fixDeprecatedAttributes( $attribs, $element ) {
-               global $wgHtml5, $wgCleanupPresentationalAttributes;
-
-               // presentational attributes were removed from html5, we can leave them
-               // in when html5 is turned off
-               if ( !$wgHtml5 || !$wgCleanupPresentationalAttributes ) {
-                       return $attribs;
-               }
-
-               $table = array( 'table' );
-               $cells = array( 'td', 'th' );
-               $colls = array( 'col', 'colgroup' );
-               $tblocks = array( 'tbody', 'tfoot', 'thead' );
-               $h = array( 'h1', 'h2', 'h3', 'h4', 'h5', 'h6' );
-
-               $presentationalAttribs = array(
-                       'align' => array( 'text-align', array_merge( array( 'caption', 'hr', 'div', 'p', 'tr' ), $table, $cells, $colls, $tblocks, $h ) ),
-                       'clear' => array( 'clear', array( 'br' ) ),
-                       'height' => array( 'height', $cells ),
-                       'nowrap' => array( 'white-space', $cells ),
-                       'size' => array( 'height', array( 'hr' ) ),
-                       'type' => array( 'list-style-type', array( 'li', 'ol', 'ul' ) ),
-                       'valign' => array( 'vertical-align', array_merge( $cells, $colls, $tblocks ) ),
-                       'width' => array( 'width', array_merge( array( 'hr', 'pre' ), $table, $cells, $colls ) ),
-               );
-
-               // Ensure that any upper case or mixed case attributes are converted to lowercase
-               foreach ( $attribs as $attribute => $value ) {
-                       if ( $attribute !== strtolower( $attribute ) && array_key_exists( strtolower( $attribute ), $presentationalAttribs ) ) {
-                               $attribs[strtolower( $attribute )] = $value;
-                               unset( $attribs[$attribute] );
-                       }
-               }
-
-               $style = "";
-               foreach ( $presentationalAttribs as $attribute => $info ) {
-                       list( $property, $elements ) = $info;
-
-                       // Skip if this attribute is not relevant to this element
-                       if ( !in_array( $element, $elements ) ) {
-                               continue;
-                       }
-
-                       // Skip if the attribute is not used
-                       if ( !array_key_exists( $attribute, $attribs ) ) {
-                               continue;
-                       }
-
-                       $value = $attribs[$attribute];
-
-                       // For nowrap the value should be nowrap instead of whatever text is in the value
-                       if ( $attribute === 'nowrap' ) {
-                               $value = 'nowrap';
-                       }
-
-                       // clear="all" is clear: both; in css
-                       if ( $attribute === 'clear' && strtolower( $value ) === 'all' ) {
-                               $value = 'both';
-                       }
-
-                       // Size based properties should have px applied to them if they have no unit
-                       if ( in_array( $attribute, array( 'height', 'width', 'size' ) ) ) {
-                               if ( preg_match( '/^[\d.]+$/', $value ) ) {
-                                       $value = "{$value}px";
-                               }
-                       }
-
-                       // Table align is special, it's about block alignment instead of
-                       // content align (see also bug 40306)
-                       if ( $attribute === 'align' && in_array( $element, $table ) ) {
-                               if ( $value === 'center' ) {
-                                       $style .= ' margin-left: auto;';
-                                       $property = 'margin-right';
-                                       $value = 'auto';
-                               } else {
-                                       $property = 'float';
-                               }
-                       }
-
-                       $style .= " $property: $value;";
-
-                       unset( $attribs[$attribute] );
-               }
-
-               if ( $style ) {
-                       // Prepend our style rules so that they can be overridden by user css
-                       if ( isset($attribs['style']) ) {
-                               $style .= " " . $attribs['style'];
-                       }
-                       $attribs['style'] = trim($style);
-               }
-
-               return $attribs;
-       }
-
-       /**
-        * Takes attribute names and values for a tag and the tah name and
+        * Takes attribute names and values for a tag and the tag name and
         * validates that the tag is allowed to be present.
         * This DOES NOT validate the attributes, nor does it validate the
         * tags themselves. This method only handles the special circumstances
         * where we may want to allow a tag within content but ONLY when it has
         * specific attributes set.
         *
-        * @param $
+        * @param $params
+        * @param $element
         */
        static function validateTag( $params, $element ) {
                $params = Sanitizer::decodeTagAttributes( $params );
@@ -1024,7 +917,6 @@ class Sanitizer {
                }
 
                $decoded = Sanitizer::decodeTagAttributes( $text );
-               $decoded = Sanitizer::fixDeprecatedAttributes( $decoded, $element );
                $stripped = Sanitizer::validateTagAttributes( $decoded, $element );
 
                $attribs = array();
index 341983d..173d37a 100644 (file)
@@ -555,7 +555,11 @@ class SkinTemplate extends Skin {
                # $this->getTitle() will just give Special:Badtitle, which is
                # not especially useful as a returnto parameter. Use the title
                # from the request instead, if there was one.
-               $page = Title::newFromURL( $request->getVal( 'title', '' ) );
+               if ( $this->getUser()->isAllowed( 'read' ) ) {
+                       $page = $this->getTitle();
+               } else {
+                       $page = Title::newFromText( $request->getVal( 'title', '' ) );
+               }
                $page = $request->getVal( 'returnto', $page );
                $a = array();
                if ( strval( $page ) !== '' ) {
index e2199c4..2c68d2f 100644 (file)
@@ -1,4 +1,22 @@
 <?php
+/**
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ *
+ * @file
+ */
 
 /**
  * @since 1.21
@@ -40,4 +58,4 @@ class CssContentHandler extends TextContentHandler {
        public function getPageViewLanguage( Title $title, Content $content = null ) {
                return wfGetLangObj( 'en' );
        }
-}
\ No newline at end of file
+}
index 8b080bf..b5b4ee2 100644 (file)
@@ -1,4 +1,22 @@
 <?php
+/**
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ *
+ * @file
+ */
 
 # XXX: make ScriptContentHandler base class, do highlighting stuff there?
 
@@ -33,7 +51,7 @@ class JavaScriptContentHandler extends TextContentHandler {
        }
 
        /**
-        * Returns the english language, because CSS is english, and should be handled as such.
+        * Returns the english language, because JS is english, and should be handled as such.
         *
         * @return Language wfGetLangObj( 'en' )
         *
@@ -42,4 +60,4 @@ class JavaScriptContentHandler extends TextContentHandler {
        public function getPageViewLanguage( Title $title, Content $content = null ) {
                return wfGetLangObj( 'en' );
        }
-}
\ No newline at end of file
+}
index 9c2ae35..90802f6 100644 (file)
@@ -1,4 +1,22 @@
 <?php
+/**
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ *
+ * @file
+ */
 
 /**
  * @since 1.21
index c6ac2ba..7e9e5e8 100644 (file)
@@ -1,4 +1,22 @@
 <?php
+/**
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ *
+ * @file
+ */
 
 /**
  * @since 1.21
@@ -60,4 +78,4 @@ class WikitextContentHandler extends TextContentHandler {
        public function isParserCacheSupported() {
                return true;
        }
-}
\ No newline at end of file
+}
index 05e2cd2..6a6f930 100644 (file)
@@ -5,6 +5,21 @@
  * Copyright © 2000, 2001 Geoffrey T. Dairiki <dairiki@dairiki.org>
  * You may copy this code freely under the conditions of the GPL.
  *
+ * 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 DifferenceEngine
  * @defgroup DifferenceEngine DifferenceEngine
index fda356e..5141ec5 100644 (file)
@@ -131,7 +131,7 @@ class FSFile {
                        # Height, width and metadata
                        $handler = MediaHandler::getHandler( $info['mime'] );
                        if ( $handler ) {
-                               $tempImage = (object)array();
+                               $tempImage = (object)array(); // XXX (hack for File object)
                                $info['metadata'] = $handler->getMetadata( $tempImage, $this->path );
                                $gis = $handler->getImageSize( $tempImage, $this->path, $info['metadata'] );
                                if ( is_array( $gis ) ) {
index b5e2315..ef49fe5 100644 (file)
@@ -172,6 +172,7 @@ abstract class FileBackend {
         *  - copy
         *  - move
         *  - delete
+        *  - describe (since 1.21)
         *  - null
         *
         * a) Create a new file in storage with the contents of a string
@@ -182,7 +183,8 @@ abstract class FileBackend {
         *         'content'             => <string of new file contents>,
         *         'overwrite'           => <boolean>,
         *         'overwriteSame'       => <boolean>,
-        *         'disposition'         => <Content-Disposition header value>
+        *         'disposition'         => <Content-Disposition header value>,
+        *         'headers'             => <HTTP header name/value map> # since 1.21
         *     );
         * @endcode
         *
@@ -194,7 +196,8 @@ abstract class FileBackend {
         *         'dst'                 => <storage path>,
         *         'overwrite'           => <boolean>,
         *         'overwriteSame'       => <boolean>,
-        *         'disposition'         => <Content-Disposition header value>
+        *         'disposition'         => <Content-Disposition header value>,
+        *         'headers'             => <HTTP header name/value map> # since 1.21
         *     )
         * @endcode
         *
@@ -233,7 +236,17 @@ abstract class FileBackend {
         *     )
         * @endcode
         *
-        * f) Do nothing (no-op)
+        * f) Update metadata for a file within storage
+        * @code
+        *     array(
+        *         'op'                  => 'describe',
+        *         'src'                 => <storage path>,
+        *         'disposition'         => <Content-Disposition header value>,
+        *         'headers'             => <HTTP header name/value map>
+        *     )
+        * @endcode
+        *
+        * g) Do nothing (no-op)
         * @code
         *     array(
         *         'op'                  => 'null',
@@ -247,10 +260,14 @@ abstract class FileBackend {
         *   - overwriteSame       : An error will not be given if a file already
         *                           exists at the destination that has the same
         *                           contents as the new contents to be written there.
-        *   - disposition         : When supplied, the backend will add a Content-Disposition
+        *   - disposition         : If supplied, the backend will return a Content-Disposition
         *                           header when GETs/HEADs of the destination file are made.
-        *                           Backends that don't support file metadata will ignore this.
-        *                           See http://tools.ietf.org/html/rfc6266 (since 1.20).
+        *                           Backends that don't support metadata ignore this.
+        *                           See http://tools.ietf.org/html/rfc6266. (since 1.20)
+        *   - headers             : If supplied, the backend will return these headers when
+        *                           GETs/HEADs of the destination file are made. Header values
+        *                           should be smaller than 256 bytes, often options or numbers.
+        *                           Backends that don't support metadata ignore this. (since 1.21)
         *
         * $opts is an associative of boolean flags, including:
         *   - force               : Operation precondition errors no longer trigger an abort.
@@ -265,10 +282,10 @@ abstract class FileBackend {
         *   - nonJournaled        : Don't log this operation batch in the file journal.
         *                           This limits the ability of recovery scripts.
         *   - parallelize         : Try to do operations in parallel when possible.
-        *   - bypassReadOnly      : Allow writes in read-only mode (since 1.20).
+        *   - bypassReadOnly      : Allow writes in read-only mode. (since 1.20)
         *   - preserveCache       : Don't clear the process cache before checking files.
         *                           This should only be used if all entries in the process
-        *                           cache were added after the files were already locked (since 1.20).
+        *                           cache were added after the files were already locked. (since 1.20)
         *
         * @remarks Remarks on locking:
         * File system paths given to operations should refer to files that are
@@ -403,6 +420,7 @@ abstract class FileBackend {
         *  - copy
         *  - move
         *  - delete
+        *  - describe (since 1.21)
         *  - null
         *
         * a) Create a new file in storage with the contents of a string
@@ -411,18 +429,22 @@ abstract class FileBackend {
         *         'op'                  => 'create',
         *         'dst'                 => <storage path>,
         *         'content'             => <string of new file contents>,
-        *         'disposition'         => <Content-Disposition header value>
+        *         'disposition'         => <Content-Disposition header value>,
+        *         'headers'             => <HTTP header name/value map> # since 1.21
         *     )
         * @endcode
+        *
         * b) Copy a file system file into storage
         * @code
         *     array(
         *         'op'                  => 'store',
         *         'src'                 => <file system path>,
         *         'dst'                 => <storage path>,
-        *         'disposition'         => <Content-Disposition header value>
+        *         'disposition'         => <Content-Disposition header value>,
+        *         'headers'             => <HTTP header name/value map> # since 1.21
         *     )
         * @endcode
+        *
         * c) Copy a file within storage
         * @code
         *     array(
@@ -433,6 +455,7 @@ abstract class FileBackend {
         *         'disposition'         => <Content-Disposition header value>
         *     )
         * @endcode
+        *
         * d) Move a file within storage
         * @code
         *     array(
@@ -443,6 +466,7 @@ abstract class FileBackend {
         *         'disposition'         => <Content-Disposition header value>
         *     )
         * @endcode
+        *
         * e) Delete a file within storage
         * @code
         *     array(
@@ -451,7 +475,18 @@ abstract class FileBackend {
         *         'ignoreMissingSource' => <boolean>
         *     )
         * @endcode
-        * f) Do nothing (no-op)
+        *
+        * f) Update metadata for a file within storage
+        * @code
+        *     array(
+        *         'op'                  => 'describe',
+        *         'src'                 => <storage path>,
+        *         'disposition'         => <Content-Disposition header value>,
+        *         'headers'             => <HTTP header name/value map>
+        *     )
+        * @endcode
+        *
+        * g) Do nothing (no-op)
         * @code
         *     array(
         *         'op'                  => 'null',
@@ -465,6 +500,10 @@ abstract class FileBackend {
         *                           header when GETs/HEADs of the destination file are made.
         *                           Backends that don't support file metadata will ignore this.
         *                           See http://tools.ietf.org/html/rfc6266 (since 1.20).
+        *   - headers             : If supplied, the backend will return these headers when
+        *                           GETs/HEADs of the destination file are made. Header values
+        *                           should be smaller than 256 bytes, often options or numbers.
+        *                           Backends that don't support metadata ignore this. (since 1.21)
         *
         * $opts is an associative of boolean flags, including:
         *   - bypassReadOnly      : Allow writes in read-only mode (since 1.20)
index 0f435a3..9bbcc0a 100644 (file)
@@ -90,12 +90,13 @@ abstract class FileBackendStore extends FileBackend {
         * Do not call this function from places outside FileBackend and FileOp.
         *
         * $params include:
-        *   - content       : the raw file contents
-        *   - dst           : destination storage path
-        *   - disposition   : Content-Disposition header value for the destination
-        *   - async         : Status will be returned immediately if supported.
-        *                     If the status is OK, then its value field will be
-        *                     set to a FileBackendStoreOpHandle object.
+        *   - content     : the raw file contents
+        *   - dst         : destination storage path
+        *   - disposition : Content-Disposition header value for the destination
+        *   - headers     : HTTP header name/value map
+        *   - async       : Status will be returned immediately if supported.
+        *                   If the status is OK, then its value field will be
+        *                   set to a FileBackendStoreOpHandle object.
         *
         * @param $params Array
         * @return Status
@@ -118,6 +119,7 @@ abstract class FileBackendStore extends FileBackend {
 
        /**
         * @see FileBackendStore::createInternal()
+        * @return Status
         */
        abstract protected function doCreateInternal( array $params );
 
@@ -127,12 +129,13 @@ abstract class FileBackendStore extends FileBackend {
         * Do not call this function from places outside FileBackend and FileOp.
         *
         * $params include:
-        *   - src           : source path on disk
-        *   - dst           : destination storage path
-        *   - disposition   : Content-Disposition header value for the destination
-        *   - async         : Status will be returned immediately if supported.
-        *                     If the status is OK, then its value field will be
-        *                     set to a FileBackendStoreOpHandle object.
+        *   - src         : source path on disk
+        *   - dst         : destination storage path
+        *   - disposition : Content-Disposition header value for the destination
+        *   - headers     : HTTP header name/value map
+        *   - async       : Status will be returned immediately if supported.
+        *                   If the status is OK, then its value field will be
+        *                   set to a FileBackendStoreOpHandle object.
         *
         * @param $params Array
         * @return Status
@@ -155,6 +158,7 @@ abstract class FileBackendStore extends FileBackend {
 
        /**
         * @see FileBackendStore::storeInternal()
+        * @return Status
         */
        abstract protected function doStoreInternal( array $params );
 
@@ -188,6 +192,7 @@ abstract class FileBackendStore extends FileBackend {
 
        /**
         * @see FileBackendStore::copyInternal()
+        * @return Status
         */
        abstract protected function doCopyInternal( array $params );
 
@@ -218,6 +223,7 @@ abstract class FileBackendStore extends FileBackend {
 
        /**
         * @see FileBackendStore::deleteInternal()
+        * @return Status
         */
        abstract protected function doDeleteInternal( array $params );
 
@@ -266,6 +272,40 @@ abstract class FileBackendStore extends FileBackend {
                return $status;
        }
 
+       /**
+        * Alter metadata for a file at the storage path.
+        * Do not call this function from places outside FileBackend and FileOp.
+        *
+        * $params include:
+        *   - src           : source storage path
+        *   - disposition   : Content-Disposition header value for the destination
+        *   - headers       : HTTP header name/value map
+        *   - async         : Status will be returned immediately if supported.
+        *                     If the status is OK, then its value field will be
+        *                     set to a FileBackendStoreOpHandle object.
+        *
+        * @param $params Array
+        * @return Status
+        */
+       final public function describeInternal( array $params ) {
+               wfProfileIn( __METHOD__ );
+               wfProfileIn( __METHOD__ . '-' . $this->name );
+               $status = $this->doDescribeInternal( $params );
+               $this->clearCache( array( $params['src'] ) );
+               $this->deleteFileCache( $params['src'] ); // persistent cache
+               wfProfileOut( __METHOD__ . '-' . $this->name );
+               wfProfileOut( __METHOD__ );
+               return $status;
+       }
+
+       /**
+        * @see FileBackendStore::describeInternal()
+        * @return Status
+        */
+       protected function doDescribeInternal( array $params ) {
+               return Status::newGood();
+       }
+
        /**
         * No-op file operation that does nothing.
         * Do not call this function from places outside FileBackend and FileOp.
@@ -995,12 +1035,13 @@ abstract class FileBackendStore extends FileBackend {
         */
        final public function getOperationsInternal( array $ops ) {
                $supportedOps = array(
-                       'store'       => 'StoreFileOp',
-                       'copy'        => 'CopyFileOp',
-                       'move'        => 'MoveFileOp',
-                       'delete'      => 'DeleteFileOp',
-                       'create'      => 'CreateFileOp',
-                       'null'        => 'NullFileOp'
+                       'store'    => 'StoreFileOp',
+                       'copy'     => 'CopyFileOp',
+                       'move'     => 'MoveFileOp',
+                       'delete'   => 'DeleteFileOp',
+                       'create'   => 'CreateFileOp',
+                       'describe' => 'DescribeFileOp',
+                       'null'     => 'NullFileOp'
                );
 
                $performOps = array(); // array of FileOp objects
@@ -1066,6 +1107,9 @@ abstract class FileBackendStore extends FileBackend {
                wfProfileIn( __METHOD__ . '-' . $this->name );
                $status = Status::newGood();
 
+               // Fix up custom header name/value pairs...
+               $ops = array_map( array( $this, 'stripInvalidHeadersFromOp' ), $ops );
+
                // Build up a list of FileOps...
                $performOps = $this->getOperationsInternal( $ops );
 
@@ -1115,6 +1159,12 @@ abstract class FileBackendStore extends FileBackend {
                wfProfileIn( __METHOD__ . '-' . $this->name );
                $status = Status::newGood();
 
+               // Fix up custom header name/value pairs...
+               $ops = array_map( array( $this, 'stripInvalidHeadersFromOp' ), $ops );
+
+               // Clear any file cache entries
+               $this->clearCache();
+
                $supportedOps = array( 'create', 'store', 'copy', 'move', 'delete', 'null' );
                $async = ( $this->parallelize === 'implicit' );
                $maxConcurrency = $this->concurrency; // throttle
@@ -1206,6 +1256,27 @@ abstract class FileBackendStore extends FileBackend {
                return array();
        }
 
+       /**
+        * Strip long HTTP headers from a file operation
+        *
+        * @param $op array Same format as doOperation()
+        * @return Array
+        */
+       protected function stripInvalidHeadersFromOp( array $op ) {
+               if ( isset( $op['headers'] ) ) {
+                       foreach ( $op['headers'] as $name => $value ) {
+                               if ( strlen( $name ) > 255 || strlen( $value ) > 255 ) {
+                                       trigger_error( "Header '$name: $value' is too long." );
+                                       unset( $op['headers'][$name] );
+                               } elseif ( !strlen( $value ) ) {
+                                       trigger_error( "Header value for '$name' is empty." );
+                                       unset( $op['headers'][$name] ); // ignore
+                               }
+                       }
+               }
+               return $op;
+       }
+
        /**
         * @see FileBackend::preloadCache()
         */
index 49111d9..bfa2757 100644 (file)
@@ -466,7 +466,7 @@ abstract class FileOp {
 class CreateFileOp extends FileOp {
        protected function allowedParams() {
                return array( array( 'content', 'dst' ),
-                       array( 'overwrite', 'overwriteSame', 'disposition' ) );
+                       array( 'overwrite', 'overwriteSame', 'disposition', 'headers' ) );
        }
 
        protected function doPrecheck( array &$predicates ) {
@@ -529,7 +529,7 @@ class StoreFileOp extends FileOp {
         */
        protected function allowedParams() {
                return array( array( 'src', 'dst' ),
-                       array( 'overwrite', 'overwriteSame', 'disposition' ) );
+                       array( 'overwrite', 'overwriteSame', 'disposition', 'headers' ) );
        }
 
        /**
@@ -809,6 +809,58 @@ class DeleteFileOp extends FileOp {
        }
 }
 
+/**
+ * Change metadata for a file at the given storage path in the backend.
+ * Parameters for this operation are outlined in FileBackend::doOperations().
+ */
+class DescribeFileOp extends FileOp {
+       /**
+        * @return array
+        */
+       protected function allowedParams() {
+               return array( array( 'src' ), array( 'disposition', 'headers' ) );
+       }
+
+       /**
+        * @param $predicates array
+        * @return Status
+        */
+       protected function doPrecheck( array &$predicates ) {
+               $status = Status::newGood();
+               // Check if the source file exists
+               if ( !$this->fileExists( $this->params['src'], $predicates ) ) {
+                       $status->fatal( 'backend-fail-notexists', $this->params['src'] );
+                       return $status;
+               // Check if a file can be placed/changed at the source
+               } elseif ( !$this->backend->isPathUsableInternal( $this->params['src'] ) ) {
+                       $status->fatal( 'backend-fail-usable', $this->params['src'] );
+                       $status->fatal( 'backend-fail-describe', $this->params['src'] );
+                       return $status;
+               }
+               // Update file existence predicates
+               $predicates['exists'][$this->params['src']] =
+                       $this->fileExists( $this->params['src'], $predicates );
+               $predicates['sha1'][$this->params['src']] =
+                       $this->fileSha1( $this->params['src'], $predicates );
+               return $status; // safe to call attempt()
+       }
+
+       /**
+        * @return Status
+        */
+       protected function doAttempt() {
+               // Update the source file's metadata
+               return $this->backend->describeInternal( $this->setFlags( $this->params ) );
+       }
+
+       /**
+        * @return array
+        */
+       public function storagePathsChanged() {
+               return array( $this->params['src'] );
+       }
+}
+
 /**
  * Placeholder operation that has no params and does nothing
  */
index 48db9d3..5a9b062 100644 (file)
@@ -236,6 +236,10 @@ class SwiftFileBackend extends FileBackendStore {
                        if ( isset( $params['disposition'] ) ) {
                                $obj->headers['Content-Disposition'] = $this->truncDisp( $params['disposition'] );
                        }
+                       // Set any other custom headers if requested
+                       if ( isset( $params['headers'] ) ) {
+                               $obj->headers += $params['headers'];
+                       }
                        if ( !empty( $params['async'] ) ) { // deferred
                                $op = $obj->write_async( $params['content'] );
                                $status->value = new SwiftFileOpHandle( $this, $params, 'Create', $op );
@@ -315,6 +319,10 @@ class SwiftFileBackend extends FileBackendStore {
                        if ( isset( $params['disposition'] ) ) {
                                $obj->headers['Content-Disposition'] = $this->truncDisp( $params['disposition'] );
                        }
+                       // Set any other custom headers if requested
+                       if ( isset( $params['headers'] ) ) {
+                               $obj->headers += $params['headers'];
+                       }
                        if ( !empty( $params['async'] ) ) { // deferred
                                wfSuppressWarnings();
                                $fp = fopen( $params['src'], 'rb' );
@@ -554,6 +562,47 @@ class SwiftFileBackend extends FileBackendStore {
                }
        }
 
+       /**
+        * @see FileBackendStore::doDescribeInternal()
+        * @return Status
+        */
+       protected function doDescribeInternal( array $params ) {
+               $status = Status::newGood();
+
+               list( $srcCont, $srcRel ) = $this->resolveStoragePathReal( $params['src'] );
+               if ( $srcRel === null ) {
+                       $status->fatal( 'backend-fail-invalidpath', $params['src'] );
+                       return $status;
+               }
+
+               $hdrs = isset( $params['headers'] ) ? $params['headers'] : array();
+               // Set the Content-Disposition header if requested
+               if ( isset( $params['disposition'] ) ) {
+                       $hdrs['Content-Disposition'] = $this->truncDisp( $params['disposition'] );
+               }
+
+               try {
+                       $sContObj = $this->getContainer( $srcCont );
+                       // Get the latest version of the current metadata
+                       $srcObj = $sContObj->get_object( $srcRel,
+                               $this->headersFromParams( array( 'latest' => true ) ) );
+                       // Merge in the metadata updates...
+                       $srcObj->headers = $hdrs + $srcObj->headers;
+                       $srcObj->sync_metadata(); // save to Swift
+                       $this->purgeCDNCache( array( $srcObj ) );
+               } catch ( CDNNotEnabledException $e ) {
+                       // CDN not enabled; nothing to see here
+               } catch ( NoSuchContainerException $e ) {
+                       $status->fatal( 'backend-fail-describe', $params['src'] );
+               } catch ( NoSuchObjectException $e ) {
+                       $status->fatal( 'backend-fail-describe', $params['src'] );
+               } catch ( CloudFilesException $e ) { // some other exception?
+                       $this->handleException( $e, $status, __METHOD__, $params );
+               }
+
+               return $status;
+       }
+
        /**
         * @see FileBackendStore::doPrepareInternal()
         * @return Status
@@ -769,6 +818,7 @@ class SwiftFileBackend extends FileBackendStore {
                                }
                        }
                }
+               trigger_error( "Unable to set SHA-1 metadata for $path", E_USER_WARNING );
                $obj->setMetadataValues( array( 'Sha1base36' => false ) );
                wfProfileOut( __METHOD__ );
                return false; // failed
index 651ee27..cbcc6c8 100644 (file)
@@ -1027,18 +1027,25 @@ class FileRepo {
         * Returns a FileRepoStatus object. On success, the value contains "new" or
         * "archived", to indicate whether the file was new with that name.
         *
+        * Options to $options include:
+        *   - headers : name/value map of HTTP headers to use in response to GET/HEAD requests
+        *
         * @param $srcPath String: the source file system path, storage path, or URL
         * @param $dstRel String: the destination relative path
         * @param $archiveRel String: the relative path where the existing file is to
         *        be archived, if there is one. Relative to the public zone root.
         * @param $flags Integer: bitfield, may be FileRepo::DELETE_SOURCE to indicate
         *        that the source file should be deleted if possible
+        * @param $options Array Optional additional parameters
         * @return FileRepoStatus
         */
-       public function publish( $srcPath, $dstRel, $archiveRel, $flags = 0 ) {
+       public function publish(
+               $srcPath, $dstRel, $archiveRel, $flags = 0, array $options = array()
+       ) {
                $this->assertWritableRepo(); // fail out if read-only
 
-               $status = $this->publishBatch( array( array( $srcPath, $dstRel, $archiveRel ) ), $flags );
+               $status = $this->publishBatch(
+                       array( array( $srcPath, $dstRel, $archiveRel, $options ) ), $flags );
                if ( $status->successCount == 0 ) {
                        $status->ok = false;
                }
@@ -1054,13 +1061,14 @@ class FileRepo {
        /**
         * Publish a batch of files
         *
-        * @param $triplets Array: (source, dest, archive) triplets as per publish()
+        * @param $ntuples Array: (source, dest, archive) triplets or
+        *        (source, dest, archive, options) 4-tuples as per publish().
         * @param $flags Integer: bitfield, may be FileRepo::DELETE_SOURCE to indicate
         *        that the source files should be deleted if possible
         * @throws MWException
         * @return FileRepoStatus
         */
-       public function publishBatch( array $triplets, $flags = 0 ) {
+       public function publishBatch( array $ntuples, $flags = 0 ) {
                $this->assertWritableRepo(); // fail out if read-only
 
                $backend = $this->backend; // convenience
@@ -1075,8 +1083,9 @@ class FileRepo {
                $operations = array();
                $sourceFSFilesToDelete = array(); // cleanup for disk source files
                // Validate each triplet and get the store operation...
-               foreach ( $triplets as $i => $triplet ) {
-                       list( $srcPath, $dstRel, $archiveRel ) = $triplet;
+               foreach ( $ntuples as $i => $ntuple ) {
+                       list( $srcPath, $dstRel, $archiveRel ) = $ntuple;
+                       $options = isset( $ntuple[3] ) ? $ntuple[3] : array();
                        // Resolve source to a storage path if virtual
                        $srcPath = $this->resolveToStoragePath( $srcPath );
                        if ( !$this->validateFilename( $dstRel ) ) {
@@ -1100,6 +1109,9 @@ class FileRepo {
                                return $this->newFatal( 'directorycreateerror', $archiveDir );
                        }
 
+                       // Set any desired headers to be use in GET/HEAD responses
+                       $headers = isset( $options['headers'] ) ? $options['headers'] : array();
+
                        // Archive destination file if it exists.
                        // This will check if the archive file also exists and fail if does.
                        // This is a sanity check to avoid data loss. On Windows and Linux,
@@ -1117,25 +1129,28 @@ class FileRepo {
                        if ( FileBackend::isStoragePath( $srcPath ) ) {
                                if ( $flags & self::DELETE_SOURCE ) {
                                        $operations[] = array(
-                                               'op'           => 'move',
-                                               'src'          => $srcPath,
-                                               'dst'          => $dstPath,
-                                               'overwrite'    => true // replace current
+                                               'op'        => 'move',
+                                               'src'       => $srcPath,
+                                               'dst'       => $dstPath,
+                                               'overwrite' => true, // replace current
+                                               'headers'   => $headers
                                        );
                                } else {
                                        $operations[] = array(
-                                               'op'           => 'copy',
-                                               'src'          => $srcPath,
-                                               'dst'          => $dstPath,
-                                               'overwrite'    => true // replace current
+                                               'op'        => 'copy',
+                                               'src'       => $srcPath,
+                                               'dst'       => $dstPath,
+                                               'overwrite' => true, // replace current
+                                               'headers'   => $headers
                                        );
                                }
                        } else { // FS source path
                                $operations[] = array(
-                                       'op'           => 'store',
-                                       'src'          => $srcPath,
-                                       'dst'          => $dstPath,
-                                       'overwrite'    => true // replace current
+                                       'op'        => 'store',
+                                       'src'       => $srcPath,
+                                       'dst'       => $dstPath,
+                                       'overwrite' => true, // replace current
+                                       'headers'   => $headers
                                );
                                if ( $flags & self::DELETE_SOURCE ) {
                                        $sourceFSFilesToDelete[] = $srcPath;
@@ -1146,8 +1161,8 @@ class FileRepo {
                // Execute the operations for each triplet
                $status->merge( $backend->doOperations( $operations ) );
                // Find out which files were archived...
-               foreach ( $triplets as $i => $triplet ) {
-                       list( $srcPath, $dstRel, $archiveRel ) = $triplet;
+               foreach ( $ntuples as $i => $ntuple ) {
+                       list( $srcPath, $dstRel, $archiveRel ) = $ntuple;
                        $archivePath = $this->getZonePath( 'public' ) . "/$archiveRel";
                        if ( $this->fileExists( $archivePath ) ) {
                                $status->value[$i] = 'archived';
@@ -1405,6 +1420,17 @@ class FileRepo {
                return $this->backend->getFileTimestamp( array( 'src' => $path ) );
        }
 
+       /**
+        * Get the size of a file with a given virtual URL/storage path
+        *
+        * @param $virtualUrl string
+        * @return integer|bool False on failure
+        */
+       public function getFileSize( $virtualUrl ) {
+               $path = $this->resolveToStoragePath( $virtualUrl );
+               return $this->backend->getFileSize( array( 'src' => $path ) );
+       }
+
        /**
         * Get the sha1 (base 36) of a file with a given virtual URL/storage path
         *
index 9a080ae..50bda52 100644 (file)
@@ -1390,17 +1390,21 @@ abstract class File {
         * The archive name should be passed through to recordUpload for database
         * registration.
         *
+        * Options to $options include:
+        *   - headers : name/value map of HTTP headers to use in response to GET/HEAD requests
+        *
         * @param $srcPath String: local filesystem path to the source image
         * @param $flags Integer: a bitwise combination of:
         *     File::DELETE_SOURCE    Delete the source file, i.e. move
         *         rather than copy
+        * @param $options Array Optional additional parameters
         * @return FileRepoStatus object. On success, the value member contains the
         *     archive name, or an empty string if it was a new file.
         *
         * STUB
         * Overridden by LocalFile
         */
-       function publish( $srcPath, $flags = 0 ) {
+       function publish( $srcPath, $flags = 0, array $options = array() ) {
                $this->readOnlyError();
        }
 
index f0a3c15..c2c17f5 100644 (file)
@@ -951,7 +951,7 @@ class LocalFile extends File {
 
        /**
         * Upload a file and record it in the DB
-        * @param $srcPath String: source storage path or virtual URL
+        * @param $srcPath String: source storage path, virtual URL, or filesystem path
         * @param $comment String: upload description
         * @param $pageText String: text to use for the new description page,
         *                  if a new description page is created
@@ -972,11 +972,27 @@ class LocalFile extends File {
                        return $this->readOnlyFatalStatus();
                }
 
+               if ( !$props ) {
+                       wfProfileIn( __METHOD__ . '-getProps' );
+                       $props = FileBackend::isStoragePath( $srcPath )
+                               ? $this->repo->getFileProps( $srcPath )
+                               : FSFile::getPropsFromPath( $srcPath );
+                       wfProfileOut( __METHOD__ . '-getProps' );
+               }
+
+               $options = array();
+               $handler = MediaHandler::getHandler( $props['mime'] );
+               if ( $handler ) {
+                       $options['headers'] = $handler->getStreamHeaders( $props['metadata'] );
+               } else {
+                       $options['headers'] = array();
+               }
+
                // truncate nicely or the DB will do it for us
                // non-nicely (dangling multi-byte chars, non-truncated version in cache).
                $comment = $wgContLang->truncate( $comment, 255 );
                $this->lock(); // begin
-               $status = $this->publish( $srcPath, $flags );
+               $status = $this->publish( $srcPath, $flags, $options );
 
                if ( $status->successCount > 0 ) {
                        # Essentially we are displacing any existing current file and saving
@@ -1252,11 +1268,12 @@ class LocalFile extends File {
         * @param $srcPath String: local filesystem path to the source image
         * @param $flags Integer: a bitwise combination of:
         *     File::DELETE_SOURCE      Delete the source file, i.e. move rather than copy
+        * @param $options Array Optional additional parameters
         * @return FileRepoStatus object. On success, the value member contains the
         *     archive name, or an empty string if it was a new file.
         */
-       function publish( $srcPath, $flags = 0 ) {
-               return $this->publishTo( $srcPath, $this->getRel(), $flags );
+       function publish( $srcPath, $flags = 0, array $options = array() ) {
+               return $this->publishTo( $srcPath, $this->getRel(), $flags, $options );
        }
 
        /**
@@ -1270,10 +1287,11 @@ class LocalFile extends File {
         * @param $dstRel String: target relative path
         * @param $flags Integer: a bitwise combination of:
         *     File::DELETE_SOURCE      Delete the source file, i.e. move rather than copy
+        * @param $options Array Optional additional parameters
         * @return FileRepoStatus object. On success, the value member contains the
         *     archive name, or an empty string if it was a new file.
         */
-       function publishTo( $srcPath, $dstRel, $flags = 0 ) {
+       function publishTo( $srcPath, $dstRel, $flags = 0, array $options = array() ) {
                if ( $this->getRepo()->getReadOnlyReason() !== false ) {
                        return $this->readOnlyFatalStatus();
                }
@@ -1283,7 +1301,7 @@ class LocalFile extends File {
                $archiveName = wfTimestamp( TS_MW ) . '!'. $this->getName();
                $archiveRel = 'archive/' . $this->getHashPath() . $archiveName;
                $flags = $flags & File::DELETE_SOURCE ? LocalRepo::DELETE_SOURCE : 0;
-               $status = $this->repo->publish( $srcPath, $dstRel, $archiveRel, $flags );
+               $status = $this->repo->publish( $srcPath, $dstRel, $archiveRel, $flags, $options );
 
                if ( $status->value == 'new' ) {
                        $status->value = '';
index 8d4a3f8..698d1eb 100644 (file)
@@ -179,10 +179,18 @@ class UnregisteredLocalFile extends File {
         */
        function getSize() {
                $this->assertRepoDefined();
-               $props = $this->repo->getFileProps( $this->path );
-               if ( isset( $props['size'] ) ) {
-                       return $props['size'];
-               }
-               return false; // doesn't exist
+               return $this->repo->getFileSize( $this->path );
+       }
+
+       /**
+        * Optimize getLocalRefPath() by using an existing local reference.
+        * The file at the path of $fsFile should not be deleted (or at least
+        * not until the end of the request). This is mostly a performance hack.
+        *
+        * @param $fsFile FSFile
+        * @return void
+        */
+       public function setLocalReference( FSFile $fsFile ) {
+               $this->fsFile = $fsFile;
        }
 }
index a0d2387..b02b346 100644 (file)
@@ -4175,6 +4175,8 @@ $messages['de-formal'] = array(
  * @author Mirzali
  */
 $messages['diq'] = array(
+       'config-title' => 'MediaWiki $1 sazkerdış',
+       'config-information' => 'Melumat',
        'config-your-language' => 'Zıwanê şıma:',
        'config-wiki-language' => 'Wiki zıwan:',
        'config-back' => '← Peyser',
@@ -4185,7 +4187,10 @@ $messages['diq'] = array(
        'config-page-name' => 'Name',
        'config-page-options' => 'Weçinegi',
        'config-page-install' => 'Barine',
+       'config-page-complete' => 'Temamyayo',
        'config-page-readme' => 'Mı bıwane',
+       'config-page-copying' => 'Kopyayeno',
+       'config-page-upgradedoc' => 'Berzkerdış',
        'config-restart' => 'E, fına dest pekê',
        'config-sidebar' => "* [//www.mediawiki.org MediaWiki keye]
 * [//www.mediawiki.org/wiki/Help:Contents User's Şınasiye]
@@ -4214,11 +4219,13 @@ $messages['diq'] = array(
        'config-admin-name' => 'Namey şıma:',
        'config-admin-password' => 'Parola:',
        'config-admin-password-confirm' => 'Fına parola:',
+       'config-profile-private' => 'Bexse wiki',
        'config-license-cc-by-sa' => 'Creative Commons Attribution Share Alike',
        'config-license-cc-by' => 'Creative Commons Attribution',
        'config-license-cc-by-nc-sa' => 'Creative Commons Attribution Non-Commercial Share Alike',
        'config-license-pd' => 'Malê Şari',
        'config-extensions' => 'Olekeni',
+       'config-help' => 'peşti',
        'mainpagetext' => "'''MediaWiki vıst ra ser, vıraziya.'''",
        'mainpagedocfooter' => 'Seba gurenayış u eyarkerdışê Wiki-Softwarey [//meta.wikimedia.org/wiki/Help:Contents İdarê karberi] de mıracaet ke.
 
index 7cf382b..113c65a 100644 (file)
@@ -226,6 +226,7 @@ class MysqlUpdater extends DatabaseUpdater {
                        array( 'addField', 'filearchive',   'fa_sha1',          'patch-fa_sha1.sql' ),
                        array( 'addField', 'job',           'job_token',         'patch-job_token.sql' ),
                        array( 'addField', 'job',           'job_attempts',       'patch-job_attempts.sql' ),
+                       array( 'doEnableProfiling' ),
                );
        }
 
@@ -772,6 +773,13 @@ class MysqlUpdater extends DatabaseUpdater {
                }
        }
 
+       protected function doEnableProfiling() {
+               global $wgProfileToDatabase;
+               if ( $wgProfileToDatabase === true && ! $this->db->tableExists( 'profiling', __METHOD__ ) ) {
+                       $this->applyPatch( 'patch-profiling.sql', false, 'Add profiling table' );
+               }
+       }
+
        protected function doMaybeProfilingMemoryUpdate() {
                if ( !$this->db->tableExists( 'profiling', __METHOD__ ) ) {
                        // Simply ignore
index 3921def..472283d 100644 (file)
@@ -106,6 +106,7 @@ class SqliteUpdater extends DatabaseUpdater {
                        array( 'addField', 'filearchive',   'fa_sha1',          'patch-fa_sha1.sql' ),
                        array( 'addField', 'job',           'job_token',         'patch-job_token.sql' ),
                        array( 'addField', 'job',           'job_attempts',      'patch-job_attempts.sql' ),
+                       array( 'doEnableProfiling' ),
                );
        }
 
@@ -129,4 +130,11 @@ class SqliteUpdater extends DatabaseUpdater {
                        $this->output( "...fulltext search table appears to be in order.\n" );
                }
        }
+
+       protected function doEnableProfiling() {
+               global $wgProfileToDatabase;
+               if ( $wgProfileToDatabase === true && ! $this->db->tableExists( 'profiling', __METHOD__ ) ) {
+                       $this->applyPatch( 'patch-profiling.sql', false, 'Add profiling table' );
+               }
+       }
 }
index 965099f..dd764e9 100644 (file)
@@ -243,6 +243,15 @@ abstract class MediaHandler {
                return array( $ext, $mime );
        }
 
+       /**
+        * Get useful response headers for GET/HEAD requests for a file with the given metadata
+        * @param $metadata mixed Result of the getMetadata() function of this handler for a file
+        * @return Array
+        */
+       public function getStreamHeaders( $metadata ) {
+               return array();
+       }
+
        /**
         * True if the handled types can be transformed
         * @return bool
index 0d5db11..b2e2e71 100644 (file)
@@ -1,18 +1,37 @@
 <?php
-
 /**
  * Class representing a MediaWiki site.
  *
- * @since 1.21
+ * 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 Site
- *
  * @license GNU GPL v2+
  * @author John Erling Blad < jeblad@gmail.com >
  * @author Daniel Kinzler
  * @author Jeroen De Dauw < jeroendedauw@gmail.com >
  */
+
+/**
+ * Class representing a MediaWiki site.
+ *
+ * @since 1.21
+ *
+ * @ingroup Site
+ */
 class MediaWikiSite extends SiteObject {
 
        const PATH_FILE = 'file_path';
index c0420e5..0d2ac7e 100644 (file)
@@ -417,6 +417,9 @@ class PageArchive {
                $logEntry->setPerformer( $user );
                $logEntry->setTarget( $this->title );
                $logEntry->setComment( $reason );
+
+               wfRunHooks( 'ArticleUndeleteLogEntry', array( $this, &$logEntry, $user ) );
+
                $logid = $logEntry->insert();
                $logEntry->publish( $logid );
 
index c76047c..adbd0e6 100644 (file)
@@ -559,7 +559,7 @@ class LoginForm extends SpecialPage {
                }
 
                $isAutoCreated = false;
-               if ( 0 == $u->getID() ) {
+               if ( $u->getID() == 0 ) {
                        $status = $this->attemptAutoCreate( $u );
                        if ( $status !== self::SUCCESS ) {
                                return $status;
@@ -569,8 +569,9 @@ class LoginForm extends SpecialPage {
                } else {
                        global $wgExternalAuthType, $wgAutocreatePolicy;
                        if ( $wgExternalAuthType && $wgAutocreatePolicy != 'never'
-                       && is_object( $this->mExtUser )
-                       && $this->mExtUser->authenticate( $this->mPassword ) ) {
+                               && is_object( $this->mExtUser )
+                               && $this->mExtUser->authenticate( $this->mPassword )
+                       ) {
                                # The external user and local user have the same name and
                                # password, so we assume they're the same.
                                $this->mExtUser->linkToLocal( $u->getID() );
index d40b53d..fa4931c 100644 (file)
@@ -244,7 +244,7 @@ abstract class UploadBase {
                        // @TODO: just make uploads work with storage paths
                        // UploadFromStash loads files via virtuals URLs
                        $tmpFile = $repo->getLocalCopy( $srcPath );
-                       $tmpFile->bind( $this ); // keep alive with $thumb
+                       $tmpFile->bind( $this ); // keep alive with $this
                        wfProfileOut( __METHOD__ );
                        return $tmpFile->getPath();
                }
index b0e5fb6..e923c20 100644 (file)
@@ -120,17 +120,24 @@ class UploadFromChunks extends UploadFromFile {
                // Get a 0-byte temp file to perform the concatenation at
                $tmpFile = TempFSFile::factory( 'chunkedupload_', $ext );
                $tmpPath = $tmpFile
-                       ? $tmpFile->getPath()
+                       ? $tmpFile->bind( $this )->getPath() // keep alive with $this
                        : false; // fail in concatenate()
                // Concatenate the chunks at the temp file
+               $tStart = microtime( true );
                $status = $this->repo->concatenate( $fileList, $tmpPath, FileRepo::DELETE_SOURCE );
+               $tAmount = microtime( true ) - $tStart;
                if( !$status->isOk() ){
                        return $status;
                }
+               wfDebugLog( 'fileconcatenate', "Combined $i chunks in $tAmount seconds.\n" );
                // Update the mTempPath and mLocalFile
                // ( for FileUpload or normal Stash to take over )
                $this->mTempPath = $tmpPath; // file system path
+               $tStart = microtime( true );
                $this->mLocalFile = parent::stashFile();
+               $tAmount = microtime( true ) - $tStart;
+               $this->mLocalFile->setLocalReference( $tmpFile ); // reuse (e.g. for getImageInfo())
+               wfDebugLog( 'fileconcatenate', "Stashed combined file ($i chunks) in $tAmount seconds.\n" );
 
                return $status;
        }
@@ -203,6 +210,9 @@ class UploadFromChunks extends UploadFromFile {
                                        $this->getOffset() . ' inx:' . $this->getChunkIndex() . "\n" );
 
                $dbw = $this->repo->getMasterDb();
+               // Use a quick transaction since we will upload the full temp file into shared
+               // storage, which takes time for large files. We don't want to hold locks then.
+               $dbw->begin();
                $dbw->update(
                        'uploadstash',
                        array(
@@ -213,6 +223,7 @@ class UploadFromChunks extends UploadFromFile {
                        array( 'us_key' => $this->mFileKey ),
                        __METHOD__
                );
+               $dbw->commit();
        }
 
        /**
index 733c686..09bcaea 100644 (file)
@@ -182,7 +182,7 @@ class UploadStash {
         * @return UploadStashFile: file, or null on failure
         */
        public function stashFile( $path, $sourceType = null ) {
-               if ( ! file_exists( $path ) ) {
+               if ( !is_file( $path ) ) {
                        wfDebug( __METHOD__ . " tried to stash file at '$path', but it doesn't exist\n" );
                        throw new UploadStashBadPathException( "path doesn't exist" );
                }
@@ -192,12 +192,10 @@ class UploadStash {
                // we will be initializing from some tmpnam files that don't have extensions.
                // most of MediaWiki assumes all uploaded files have good extensions. So, we fix this.
                $extension = self::getExtensionForPath( $path );
-               if ( ! preg_match( "/\\.\\Q$extension\\E$/", $path ) ) {
+               if ( !preg_match( "/\\.\\Q$extension\\E$/", $path ) ) {
                        $pathWithGoodExtension = "$path.$extension";
-                       if ( ! rename( $path, $pathWithGoodExtension ) ) {
-                               throw new UploadStashFileException( "couldn't rename $path to have a better extension at $pathWithGoodExtension" );
-                       }
-                       $path = $pathWithGoodExtension;
+               } else {
+                       $pathWithGoodExtension = $path;
                }
 
                // If no key was supplied, make one.  a mysql insertid would be totally reasonable here, except
@@ -221,7 +219,7 @@ class UploadStash {
                wfDebug( __METHOD__ . " key for '$path': $key\n" );
 
                // if not already in a temporary area, put it there
-               $storeStatus = $this->repo->storeTemp( basename( $path ), $path );
+               $storeStatus = $this->repo->storeTemp( basename( $pathWithGoodExtension ), $path );
 
                if ( ! $storeStatus->isOK() ) {
                        // It is a convention in MediaWiki to only return one error per API exception, even if multiple errors
@@ -244,9 +242,6 @@ class UploadStash {
                }
                $stashPath = $storeStatus->value;
 
-               // we have renamed the file so we have to cleanup once done
-               unlink($path);
-
                // fetch the current user ID
                if ( !$this->isLoggedIn ) {
                        throw new UploadStashNotLoggedInException( __METHOD__ . ' No user is logged in, files must belong to users' );
index c4807a6..437d3c4 100644 (file)
@@ -3482,8 +3482,22 @@ class Language {
                                }
                        }
                }
-               // If all else fails, return the original string.
-               return $str;
+
+               // If all else fails, return a standard duration or timestamp description.
+               $time = strtotime( $str, 0 );
+               if ( $time === false ) { // Unknown format. Return it as-is in case.
+                       return $str;
+               } elseif ( $time !== strtotime( $str, 1 ) ) { // It's a relative timestamp.
+                       // $time is relative to 0 so it's a duration length.
+                       return $this->formatDuration( $time );
+               } else { // It's an absolute timestamp.
+                       if ( $time === 0 ) {
+                               // wfTimestamp() handles 0 as current time instead of epoch.
+                               return $this->timeanddate( '19700101000000' );
+                       } else {
+                               return $this->timeanddate( $time );
+                       }
+               }
        }
 
        /**
index b9cb6da..42cea4e 100644 (file)
@@ -2142,7 +2142,7 @@ evit gallout kas ur postel d'un implijer all.",
 'emailuser-title-target' => "Kas ur postel d'an {{PLURAL:$1|an implijer-mañ|an implijerez-mañ}}",
 'emailuser-title-notarget' => "Kas ur postel d'un implijer",
 'emailpage' => 'Postel implijer',
-'emailpagetext' => "Gallout a rit ober gant ar furmskrid a-is a-benn kas ur postel d'an implijer-mañ.
+'emailpagetext' => "Gallout a rit ober gant ar furmskrid a-is a-benn kas ur postel d'an {{GENDER:\$1|implijer|implijerez}}-mañ.
 E maezienn \"Kaser\" ho postel e vo merket ar chomlec'h postel resisaet ganeoc'h-c'hwi en ho [[Special:Preferences|Penndibaboù]], d'ar resever da c'hallout respont deoc'h war-eeun ma kar.",
 'usermailererror' => 'Fazi postel :',
 'defemailsubject' => 'Postel kaset eus {{SITENAME}} gant an implijer "$1"',
@@ -2400,7 +2400,8 @@ Ma'z eus bet krouet ur bajenn nevez dezhi an hevelep anv abaoe an diverkadenn, e
 'undeletedrevisions' => 'Adsavet {{PLURAL:$1|1 stumm|$1 stumm}}',
 'undeletedrevisions-files' => 'Adsavet ez ez eus bet {{PLURAL:$1|1 stumm|$1 stumm}} ha {{PLURAL:$2|1 restr|$2 restr}}',
 'undeletedfiles' => '{{PLURAL:$1|1 restr|$1 restr}} adsavet',
-'cannotundelete' => "Dibosupl eo diziverkañ; moarvat eo bet diziverket gant unan bennak all araozoc'h.",
+'cannotundelete' => 'Dibosupl eo diziverkañ:
+$1',
 'undeletedpage' => "'''Diziverket eo bet $1'''
 
 Sellit ouzh [[Special:Log/delete|marilh an diverkadennoù]] evit teuler ur sell ouzh an diverkadennoù diwezhañ.",
@@ -2962,6 +2963,7 @@ Sur a-walc'h abalamour d'ul liamm enni a gas d'ul lec'hienn ziavaez berzet.",
 'pageinfo-default-sort' => "Alc'hwez rummañ dre ziouer",
 'pageinfo-length' => 'Ment ar bajenn (en oktedoù)',
 'pageinfo-article-id' => 'Niverenn ar bajenn',
+'pageinfo-language' => 'Yezh ar bajenn',
 'pageinfo-robot-policy' => 'Statud al lusker klask',
 'pageinfo-robot-index' => "A c'haller menegeriñ",
 'pageinfo-robot-noindex' => "Ne c'haller ket menegeriñ",
@@ -3912,4 +3914,6 @@ A-hend-all e c'hallit ober gant ar furmskrid eeunaet dindan. Ouzhpennet e vo hoc
 'duration-centuries' => "$1 {{PLURAL:$1|c'hantved|kantved}}",
 'duration-millennia' => '$1 {{PLURAL:$1|milvloaz|milvoaz}}',
 
+# Unknown messages
+'mytalk-parenthetical' => 'kaozeal',
 );
index f19cb10..b3ee85d 100644 (file)
@@ -34,6 +34,7 @@
  * @author Ssola
  * @author Toniher
  * @author Vriullop
+ * @author Àlex
  * @author לערי ריינהארט
  */
 
@@ -208,8 +209,8 @@ $messages = array(
 'tog-editsectiononrightclick' => "Habilita l'edició per seccions en clicar amb el botó dret sobre els títols de les seccions (cal JavaScript)",
 'tog-showtoc' => 'Mostra la taula de continguts (per pàgines amb més de 3 seccions)',
 'tog-rememberpassword' => 'Recorda la sessió al navegador (per un màxim de {{PLURAL:$1|dia|dies}})',
-'tog-watchcreations' => 'Afegeix les pàgines que vagi creant a la llista de seguiment',
-'tog-watchdefault' => 'Afegeix les pàgines que vagi creant a la llista de seguiment',
+'tog-watchcreations' => 'Afegeix les pàgines que vagi creant i fitxers que carregui a la llista de seguiment',
+'tog-watchdefault' => 'Afegeix les pàgines que vagi editant a la llista de seguiment',
 'tog-watchmoves' => 'Afegeix les pàgines que reanomeni a la llista de seguiment',
 'tog-watchdeletion' => 'Afegeix les pàgines que elimini a la llista de seguiment',
 'tog-minordefault' => 'Marca totes les contribucions com a edicions menors per defecte',
@@ -328,7 +329,7 @@ $messages = array(
 'newwindow' => '(obre en una nova finestra)',
 'cancel' => 'Anuŀla',
 'moredotdotdot' => 'Més...',
-'mypage' => 'Pàgina personal',
+'mypage' => 'Pàgina',
 'mytalk' => 'Discussió',
 'anontalk' => "Discussió d'aquesta IP",
 'navigation' => 'Navegació',
@@ -476,7 +477,7 @@ $1",
 'thisisdeleted' => 'Voleu mostrar o restaurar $1?',
 'viewdeleted' => 'Voleu mostrar $1?',
 'restorelink' => '{{PLURAL:$1|una versió esborrada|$1 versions esborrades}}',
-'feedlinks' => 'Sindicament:',
+'feedlinks' => 'Sindicació:',
 'feed-invalid' => 'La subscripció no és vàlida pel tipus de sindicament.',
 'feed-unavailable' => 'Els canals de sindicació no estan disponibles',
 'site-rss-feed' => 'Canal RSS $1',
@@ -1120,7 +1121,7 @@ Si us plau, verifica els registres.",
 ** Comentari o informació personal inapropiada
 ** Nom d'usuari inapropiat
 ** Informació potencialment calumniosa",
-'revdelete-otherreason' => 'Altre motiu / motiu suplementari:',
+'revdelete-otherreason' => 'Motiu diferent o addicional:',
 'revdelete-reasonotherlist' => 'Altres raons',
 'revdelete-edit-reasonlist' => "Editar el motiu d'esborrament",
 'revdelete-offender' => 'Autor de la revisió:',
@@ -1479,6 +1480,9 @@ Ha de tenir com a molt {{PLURAL:$1|un caràcter|$1 caràcters}}.',
 'rightslogtext' => "Aquest és un registre de canvis dels permisos d'usuari.",
 'rightslogentry' => 'ha modificat els drets de $1 del grup $2 a $3',
 'rightslogentry-autopromote' => 'ha estat promogut automàticament de $2 a $3',
+'logentry-rights-rights' => '$1 ha canviat la pertinença de grups per $3 de $4 a $5',
+'logentry-rights-rights-legacy' => '$1 ha canviat la pertinença de grups per $3',
+'logentry-rights-autopromote' => '$1 ha estat promogut automàticament de $4 a $5',
 'rightsnone' => '(cap)',
 
 # Associated actions - in the sentence "You do not have permission to X"
@@ -1870,7 +1874,7 @@ Potser voleu modificar-ne la descripció en la seva [$2 pàgina de descripció].
 'filedelete-success-old' => "<span class=\"plainlinks\">La versió de '''[[Media:\$1|\$1]]''' s'ha eliminat el \$2 a les \$3.</span>",
 'filedelete-nofile' => "'''$1''' no existeix.",
 'filedelete-nofile-old' => "No hi ha cap versió arxivada de '''$1''' amb els atributs especificats.",
-'filedelete-otherreason' => 'Motius alternatius/addicionals:',
+'filedelete-otherreason' => 'Motiu diferent o addicional:',
 'filedelete-reason-otherlist' => 'Altres motius',
 'filedelete-reason-dropdown' => "*Motius d'eliminació comuns
 ** Violació dels drets d'autor / copyright
@@ -2081,9 +2085,9 @@ Vegeu també [[Special:WantedCategories|les categories soŀlicitades]].",
 'linksearch-pat' => 'Patró de cerca:',
 'linksearch-ns' => 'Espai de noms:',
 'linksearch-ok' => 'Cerca',
-'linksearch-text' => 'Podeu fer servir caràcters comodí com "*.wikipedia.org".
+'linksearch-text' => 'Es poden utilitzar caràcters comodí com "*.wikipedia.org".
 Necessita com a mínim un domini de primer nivell, per exemple "*.org".<br />
-Protocols admesos: <code> $1 </code> (no els afegiu en la vostra recerca).',
+Protocols admesos: <code>$1</code> (http:// per defecte si no se n\'especifica cap).',
 'linksearch-line' => '$1 enllaçat a $2',
 'linksearch-error' => "Els caràcters comodí només poden aparèixer a l'inici de l'url.",
 
@@ -2134,8 +2138,8 @@ per enviar un correu electrònic a altres usuaris.",
 'emailuser-title-target' => 'Enviar un correu electrònic a {{GENDER:$1|aquest usuari|aquesta usuària}}',
 'emailuser-title-notarget' => "Enviar un correu electrònic a l'usuari",
 'emailpage' => 'Correu electrònic a usuari',
-'emailpagetext' => "Podeu usar el següent formulari per a enviar un missatge de correu electrònic a aquest usuari.
-L'adreça electrònica que heu entrat en [[Special:Preferences|les vostres preferències d'usuari]] apareixerà com a remitent del correu electrònic, de manera que el destinatari us podrà respondre directament.",
+'emailpagetext' => "Podeu usar el següent formulari per a enviar un missatge de correu electrònic a {{GENDER:$1|aquest usuari|aquesta usuària}}.
+L'adreça electrònica que vau indicar a [[Special:Preferences|les vostres preferències d'usuari]] apareixerà com a remitent del correu electrònic, de manera que el destinatari us podrà respondre directament.",
 'usermailererror' => "L'objecte de correu ha retornat un error:",
 'defemailsubject' => 'Correu electrònic de l\'usuari "$1" de {{SITENAME}}',
 'usermaildisabled' => "Correu electrònic d'usuaris deshabilitat",
@@ -2263,7 +2267,7 @@ Vegeu $2 per a un registre dels esborrats més recents.',
 'deletionlog' => "Registre d'esborrats",
 'reverted' => 'Invertit amb una revisió anterior',
 'deletecomment' => 'Motiu:',
-'deleteotherreason' => 'Motius diferents o addicionals:',
+'deleteotherreason' => 'Motiu diferent o addicional:',
 'deletereasonotherlist' => 'Altres motius',
 'deletereason-dropdown' => "*Motius freqüents d'esborrat
 ** Demanada per l'autor
@@ -2334,7 +2338,7 @@ Ací es troben els paràmetres actuals de la pàgina '''$1''':",
 'protect-othertime' => 'Un altre termini:',
 'protect-othertime-op' => 'un altre termini',
 'protect-existing-expiry' => "Data d'expiració existent: $2 a les $3",
-'protect-otherreason' => 'Altres motius:',
+'protect-otherreason' => 'Motiu diferent o addicional:',
 'protect-otherreason-op' => 'Altres motius',
 'protect-dropdown' => "*Motius comuns de protecció
 ** Vandalisme excessiu
@@ -2465,7 +2469,7 @@ Per més detalls, la última entrada del registre es mostra a continuació:',
 'whatlinkshere-hideredirs' => '$1 redireccions',
 'whatlinkshere-hidetrans' => '$1 inclusions',
 'whatlinkshere-hidelinks' => '$1 enllaços',
-'whatlinkshere-hideimages' => '$1 enllaços a imatge',
+'whatlinkshere-hideimages' => '$1 enllaços de fitxers',
 'whatlinkshere-filters' => 'Filtres',
 
 # Block/unblock
@@ -2501,7 +2505,7 @@ quines pàgines en concret estan sent vandalitzades).",
 'ipbother' => 'Un altre termini',
 'ipboptions' => '2 hores:2 hours,1 dia:1 day,3 dies:3 days,1 setmana:1 week,2 setmanes:2 weeks,1 mes:1 month,3 mesos:3 months,6 mesos:6 months,1 any:1 year,infinit:infinite',
 'ipbotheroption' => 'un altre',
-'ipbotherreason' => 'Altres motius o addicionals:',
+'ipbotherreason' => 'Motiu diferent o addicional:',
 'ipbhidename' => "Amaga el nom d'usuari de les edicions i llistes",
 'ipbwatchuser' => "Vigila les pàgines d'usuari i de discussió de l'usuari",
 'ipb-disableusertalk' => 'Impedeix que aquest usuari pugui modificar la seva pàgina de discussió mentre dura el blocatge',
@@ -2715,16 +2719,16 @@ A continuació es mostra la darrera entrada del registre com a referència:",
 'file-exists-sharedrepo' => "El nom de fitxer escollit ja s'utilitza al dipòsit compartit. Escolliu un altre nom.",
 
 # Export
-'export' => 'Exporta les pàgines',
+'export' => 'Exportació de pàgines',
 'exporttext' => "Podeu exportar a XML el text i l'historial d'una pàgina en concret o d'un conjunt de pàgines; aleshores el resultat pot importar-se en un altre lloc web basat en wiki amb programari de MediaWiki mitjançant la [[Special:Import|pàgina d'importació]].
 
 Per a exportar pàgines, escriviu els títols que desitgeu al quadre de text de sota, un títol per línia, i seleccioneu si desitgeu o no la versió actual juntament amb totes les versions antigues, amb la pàgina d'historial, o només la pàgina actual amb la informació de la darrera modificació.
 
 En el darrer cas, podeu fer servir un enllaç com ara [[{{#Special:Export}}/{{MediaWiki:Mainpage}}]] per a la pàgina «[[{{MediaWiki:Mainpage}}]]».",
 'exportall' => 'Exporta totes les pàgines',
-'exportcuronly' => "Exporta únicament la versió actual en voltes de l'historial sencer",
+'exportcuronly' => "Inclou només la versió actual, sense l'historial complet",
 'exportnohistory' => "----
-'''Nota:''' s'ha inhabilitat l'exportació sencera d'historial de pàgines mitjançant aquest formulari a causa de problemes de rendiment del servidor.",
+'''Nota:''' s'ha inhabilitat l'exportació sencera d'historial de pàgines mitjançant aquest formulari a causa de problemes de rendiment.",
 'exportlistauthors' => 'Inclouen una llista completa dels contribuents per a cada pàgina',
 'export-submit' => 'Exporta',
 'export-addcattext' => 'Afegeix pàgines de la categoria:',
@@ -2944,6 +2948,7 @@ Això deu ser degut per un enllaç a un lloc extern inclòs a la llista negra.',
 'pageinfo-default-sort' => "Clau d'ordenació predeterminada",
 'pageinfo-length' => 'Mida de la pàgina (en bytes)',
 'pageinfo-article-id' => 'ID de la pàgina',
+'pageinfo-language' => 'Llengua del contingut de la pàgina',
 'pageinfo-robot-policy' => 'Estat del motor de cerca',
 'pageinfo-robot-index' => 'Indexable',
 'pageinfo-robot-noindex' => 'No indexable',
@@ -2987,6 +2992,8 @@ Això deu ser degut per un enllaç a un lloc extern inclòs a la llista negra.',
 'markedaspatrollederror' => 'No es pot marcar com a supervisat',
 'markedaspatrollederrortext' => 'Cal que especifiqueu una versió per a marcar-la com a supervisada.',
 'markedaspatrollederror-noautopatrol' => 'No podeu marcar les vostres pròpies modificacions com a supervisades.',
+'markedaspatrollednotify' => 'Aquesta modificació a $1 ha estat marcada com a patrullada.',
+'markedaspatrollederrornotify' => 'Ha fallat la marca com a patrullat.',
 
 # Patrol log
 'patrol-log-page' => 'Registre de supervisió',
@@ -2995,7 +3002,7 @@ Això deu ser degut per un enllaç a un lloc extern inclòs a la llista negra.',
 
 # Image deletion
 'deletedrevision' => "S'ha eliminat la revisió antiga $1.",
-'filedeleteerror-short' => "S'ha produït un error en suprimir el fitxer: $1",
+'filedeleteerror-short' => 'Error en suprimir el fitxer: $1',
 'filedeleteerror-long' => "S'han produït errors en suprimir el fitxer:
 
 $1",
@@ -3172,7 +3179,7 @@ La resta d'enllaços de la línia són les excepcions, és a dir, les pàgines o
 'exif-gpsstatus' => 'Estat del receptor',
 'exif-gpsmeasuremode' => 'Mode de mesura',
 'exif-gpsdop' => 'Precisió de la mesura',
-'exif-gpsspeedref' => 'Unitats de velocitat',
+'exif-gpsspeedref' => 'Unitat de velocitat',
 'exif-gpsspeed' => 'Velocitat del receptor GPS',
 'exif-gpstrackref' => 'Referència per la direcció del moviment',
 'exif-gpstrack' => 'Direcció del moviment',
@@ -3552,6 +3559,7 @@ Aquest codi de confirmació caducarà el $4.",
 # Scary transclusion
 'scarytranscludedisabled' => "[S'ha inhabilitat la transclusió interwiki]",
 'scarytranscludefailed' => '[Ha fallat la recuperació de la plantilla per a $1]',
+'scarytranscludefailed-httpstatus' => '[Ha fallat la recuperació de la plantilla per a $1: HTTP $2]',
 'scarytranscludetoolong' => "[L'URL és massa llarg]",
 
 # Delete conflict
@@ -3662,6 +3670,7 @@ També podeu [[Special:EditWatchlist|utilitzar l'editor estàndard]].",
 'version-license' => 'Llicència',
 'version-poweredby-credits' => "El wiki funciona gràcies a '''[//www.mediawiki.org/ MediaWiki]''', copyright © 2001-$1 $2.",
 'version-poweredby-others' => 'altres',
+'version-credits-summary' => 'El nostre reconeixement a les següents persones per la seva aportació a [[Special:Version|MediaWiki]]',
 'version-license-info' => "MediaWiki és programari lliure, podeu redistribuir-lo i/o modificar-lo sota els termes de la Llicència Pública General GNU publicada per la Free Software Foundation, ja sigui de la seva versió 2 o (a elecció vostra) qualsevol versió posterior. 
 
 MediaWiki es distribueix en l'esperança de ser d'utilitat, però SENSE CAP GARANTIA; ni tan sols la garantia implícita de COMERCIALITZACIÓ o ADEQUACIÓ A UNA FINALITAT DETERMINADA. En trobareu més detalls a  la Llicència Pública General GNU.
@@ -3879,4 +3888,6 @@ Altrament, podeu fer servir un senzill formulari a continuació. El vostre comen
 'duration-centuries' => '$1 {{PLURAL:$1|segle|segles}}',
 'duration-millennia' => '$1 {{PLURAL:$1|mil·leni|mil·lenis}}',
 
+# Unknown messages
+'mytalk-parenthetical' => 'discussió',
 );
index 5443e4e..2a4496a 100644 (file)
@@ -2363,8 +2363,9 @@ $1',
 'unblocked' => '[[User:$1|$1]] لە بەربەست دەرهێنرا',
 'unblocked-id' => 'بەربەستی $1 لابرا',
 'blocklist' => 'بەکارھێنەر بەربەستکراوەکان',
-'ipblocklist' => 'بەکارھێنەر بەربەستنکراوەکان',
+'ipblocklist' => 'بەکارھێنەر بەربەستکراوەکان',
 'ipblocklist-legend' => 'دۆزینەوەی بەکارهێنەرێکی بەربەست‌کراو',
+'blocklist-userblocks' => 'ھەژمارە بەربەستکراوەکان بشارەوە',
 'blocklist-target' => 'مەبەست',
 'blocklist-expiry' => 'ھەتا:',
 'blocklist-params' => 'پارامەترەکانی بەربەستن',
index 719abcf..0ced7bd 100644 (file)
@@ -488,7 +488,7 @@ $messages = array(
 'updatedmarker' => 'cıkewtena mına peyêne ra dıme biyo rocane',
 'printableversion' => 'Asayışê çapkerdışi',
 'permalink' => 'Gıreyo jûqere',
-'print' => 'Çap ke',
+'print' => 'Nusten ke',
 'view' => 'Bıvin',
 'edit' => 'Bıvurnên',
 'create' => 'Vıraze',
@@ -1341,7 +1341,7 @@ Detayê besternayışi [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}
 'searcheverything-enable' => 'cayê nameyê hemi de bigêre',
 'searchrelated' => 'eleqeyın',
 'searchall' => 'pêro',
-'showingresults' => "Heta {{PLURAL:$1|'''1''' netice|'''$1''' neticeyan}} ke pê #'''$2''' başli beno ey bimocne .",
+'showingresults' => "#$2 netican ra {{PLURAL:$1|'''1''' netica |'''$1''' neticey }} cêr deyê.",
 'showingresultsnum' => "'''$2''' netican ra nata  {{PLURAL:$3|'''1''' netice|'''$3''' neticeyê}} cêrde liste biyê.",
 'showingresultsheader' => "{{PLURAL:$5|Neticeyê '''$1''' of '''$3'''|Neticeyanê '''$1 - $2''' hetê '''$3'''}} qe '''$4'''",
 'nonefound' => "'''Teme''': Teyna tay namecayan cıgeyro beno.
@@ -4429,7 +4429,7 @@ Ti hem zi eşkeno [[Special:EditWatchlist|use the standard editor]].',
 'watchlistedit-raw-submit' => 'Listeyê seyri newen ke',
 'watchlistedit-raw-done' => 'Listeyê tuyê seyrkerdişi rocaniye biyo',
 'watchlistedit-raw-added' => '{{PLURAL:$1|1 seroğ|$1 seroğî}} de kerd:',
-'watchlistedit-raw-removed' => '{{PLURAL:$1|1 seroğ|$1 seroğî}} de wedarno:',
+'watchlistedit-raw-removed' => '{{PLURAL:$1|1 seroğ|$1 seroği}} besteriyaye:',
 
 # Watchlist editing tools
 'watchlisttools-view' => 'vurnayışanê eleqadari bıvin',
index 70dabd7..30a0dc1 100644 (file)
@@ -2318,6 +2318,7 @@ If the problem persists, contact an [[Special:ListUsers/sysop|administrator]].',
 'backend-fail-notsame'       => 'A non-identical file already exists at "$1".',
 'backend-fail-invalidpath'   => '"$1" is not a valid storage path.',
 'backend-fail-delete'        => 'Could not delete file "$1".',
+'backend-fail-describe'      => 'Could not change metadata for file "$1".',
 'backend-fail-alreadyexists' => 'The file "$1" already exists.',
 'backend-fail-store'         => 'Could not store file "$1" at "$2".',
 'backend-fail-copy'          => 'Could not copy file "$1" to "$2".',
index 3845da2..fa8937e 100644 (file)
@@ -2818,7 +2818,7 @@ Sin embargo, está bloqueada como parte del rango $2, que puede ser desbloqueado
 # Move page
 'move-page' => 'Trasladar $1',
 'move-page-legend' => 'Renombrar página',
-'movepagetext' => "Usando el siguiente formulario se renombrará una página, moviendo todo su historial al nuevo nombre.
+'movepagetext' => "Usando el siguiente formulario se renombrará una página, trasladando todo su historial al nuevo nombre.
 El título anterior se convertirá en una redirección al nuevo título.
 Los enlaces al antiguo título de la página no se cambiarán.
 Asegúrate de no dejar [[Special:DoubleRedirects|redirecciones dobles]] o [[Special:BrokenRedirects|rotas]].
@@ -2830,7 +2830,7 @@ Esto significa que podrás renombrar una página a su título original si has co
 '''¡Aviso!'''
 Este puede ser un cambio drástico e inesperado para una página popular;
 por favor, asegúrate de entender las consecuencias del procedimiento antes de seguir adelante.",
-'movepagetext-noredirectfixer' => "Usando el siguiente formulario se renombrará una página, moviendo todo su historial al nuevo nombre.
+'movepagetext-noredirectfixer' => "Usando el siguiente formulario se renombrará una página, trasladando todo su historial al nuevo nombre.
 El título anterior se convertirá en una redirección al nuevo título.
 Asegúrate de no dejar [[Special:DoubleRedirects|redirecciones dobles]] o [[Special:BrokenRedirects|rotas]].
 Tú eres responsable de hacer que los enlaces sigan apuntando adonde se supone que deberían hacerlo.
@@ -2842,7 +2842,7 @@ Esto significa que podrás renombrar una página a su título original si has co
 Este puede ser un cambio drástico e inesperado para una página popular;
 por favor, asegúrate de entender las consecuencias del procedimiento antes de seguir adelante.",
 'movepagetalktext' => "La página de discusión asociada, si existe, será renombrada automáticamente '''a menos que:'''
-*Esté moviendo la página entre espacios de nombres diferentes,
+*Estés trasladando la página entre espacios de nombres diferentes,
 *Una página de discusión no vacía ya exista con el nombre nuevo, o
 *No actives la opción «Renombrar la página de discusión también».
 
index a490b8c..98baace 100644 (file)
@@ -173,7 +173,7 @@ $messages = array(
 
 'underline-always' => 'Beti',
 'underline-never' => 'Inoiz ez',
-'underline-default' => 'Nabigatzailearen lehenetsitako balioa',
+'underline-default' => 'Lehenetsitako nabigatzailea',
 
 # Font style option in Special:Preferences
 'editfont-style' => 'Aldatu eremuko letra tipoa:',
@@ -258,8 +258,8 @@ $messages = array(
 'newwindow' => '(leiho berrian irekitzen da)',
 'cancel' => 'Utzi',
 'moredotdotdot' => 'Gehiago...',
-'mypage' => 'Nire orrialdea',
-'mytalk' => 'Nire eztabaida',
+'mypage' => 'Orrialdea',
+'mytalk' => 'Eztabaida',
 'anontalk' => 'IP honen eztabaida',
 'navigation' => 'Nabigazioa',
 'and' => '&#32;eta',
@@ -281,7 +281,7 @@ $messages = array(
 'vector-action-protect' => 'Babestu',
 'vector-action-undelete' => 'Berreskuratu',
 'vector-action-unprotect' => 'Babesa aldatu',
-'vector-simplesearch-preference' => 'Baimendu bilaketa gomendio hobetuak (Vector itxurarekin bakarrik)',
+'vector-simplesearch-preference' => 'Bilaketa barra sinplifikatua gaitu (Vector itxurarekin bakarrik)',
 'vector-view-create' => 'Sortu',
 'vector-view-edit' => 'Aldatu',
 'vector-view-history' => 'Historia ikusi',
@@ -493,7 +493,8 @@ Kontsulta: $2',
 Saia zaitez berriro minutu batzuen buruan, mesedez.',
 'protectedpagetext' => 'Orrialde hau aldaketak saihesteko blokeatu egin da.',
 'viewsourcetext' => 'Orrialde honen testua ikusi eta kopiatu dezakezu:',
-'protectedinterface' => 'Orrialde honek softwarearentzako interfaze testua gordetzen du eta blokeatuta dago bandalismoak saihesteko.',
+'protectedinterface' => 'Orrialde honek softwarearentzako interfaze testua gordetzen du eta blokeatuta dago bandalismoak saihesteko.
+Wiki guztientzako aldaketak egin edo gehitzeko, mesedez erabili [//translatewiki.net/ translatewiki.net], MediaWikiren lokalizazio proiektua.',
 'editinginterface' => "'''Oharra:''' Softwarearentzako interfaze testua duen orrialde bat aldatzen ari zara.
 Orrialde honetako aldaketek erabiltzaile guztiei eragingo die.
 Itzulpenetarako, [//translatewiki.net/wiki/Main_Page?setlang=en translatewiki.net] erabili ezazu, MediaWiki proiektuan.",
@@ -504,6 +505,7 @@ $2",
 'ns-specialprotected' => 'Ezin dira {{ns:special}} izen-tarteko orrialdeak editatu.',
 'titleprotected' => "[[User:$1|$1]]ek izenburu hau sortzea ekidin zuen.
 Emandako arrazoia ''$2'' izan zen.",
+'exception-nologin' => 'Saioa hasi gabe',
 
 # Virus scanner
 'virus-badscanner' => "Ezarpen txarrak: antibirus ezezaguna: ''$1''",
@@ -593,6 +595,7 @@ Ondorioz, ezin duzu kontu gehiago sortu.',
 'invalidemailaddress' => 'Ezin da e-posta helbide hori ontzat eman baliogabeko formatua duela dirudielako.
 
 Mesedez, formatu egokia duen helbide bat zehaztu, edo hutsik utzi.',
+'emaildisabled' => 'Gune honek ezin du e-postarik bidali.',
 'accountcreated' => 'Kontua sortuta',
 'accountcreatedtext' => '$1 erabiltzaile kontua sortu egin da.',
 'createaccount-title' => '{{SITENAME}}-rako kontua sortu',
@@ -734,9 +737,9 @@ Erabiltzaile anonimoa bazara eta zurekin zerikusirik ez duten mezuak jasotzen ba
 Beste orrialde batzuetan [[Special:Search/{{PAGENAME}}|bilatu dezakezu izenburu hau]],
 <span class="plainlinks">[{{fullurl:{{#Special:Log}}|page={{FULLPAGENAMEE}}}} bilatu lotutako logak],
 edo [{{fullurl:{{FULLPAGENAME}}|action=edit}} berau aldatu ere egin dezakezu]</span>.',
-'noarticletext-nopermission' => 'Une honetan ez dago texturik orri honetan.
-Beste orrietan [[Special:Search/{{PAGENAME}}|testua bilatu dezakezu]],
-edo <span class="plainlinks">[{{fullurl:{{#Special:Log}}|page={{FULLPAGENAMEE}}}} erlazionatutako erregistroak ikusi]</span>.',
+'noarticletext-nopermission' => 'Une honetan ez dago testurik orrialde honetan.
+Beste orrialdeetan [[Special:Search/{{PAGENAME}}|izenburu hau bilatu dezakezu]],
+edo <span class="plainlinks">[{{fullurl:{{#Special:Log}}|page={{FULLPAGENAMEE}}}} erlazionatutako erregistroak bilatu]</span>, baina ez duzu orrialde hau sortzeko baimenik.',
 'userpage-userdoesnotexist' => '"<nowiki>$1</nowiki>" lankidea ez dago erregistatuta. Mesedez, konprobatu orri hau editatu/sortu nahi duzun.',
 'userpage-userdoesnotexist-view' => '"$1" erabiltzaile-kontua ez dago erregistraturik.',
 'blocked-notice-logextract' => 'Erabiltzaile hau blokeatuta dago une honetan.
@@ -760,7 +763,7 @@ Azken blokeoaren erregistroa ageri da behean, erreferentzia gisa:',
 'note' => "'''Oharra:'''",
 'previewnote' => "'''Gogoratu hau aurrikuspen bat dela.'''
 Zure aldaketak ez dira oraindik gorde!",
-'continue-editing' => 'Aldatzen jarraitu',
+'continue-editing' => 'Edizio-eremura joan',
 'previewconflict' => 'Aurreikuspenak aldaketen koadroan idatzitako testua erakusten du, gorde ondoren agertuko den bezala.',
 'session_fail_preview' => "'''Sentitzen dugu! Ezin izan da zure aldaketa prozesatu, saioko datu batzuen galera dela-eta. Mesedez, saiatu berriz. Arazoak jarraitzen badu, saiatu saioa amaitu eta berriz hasten.'''",
 'session_fail_preview_html' => "'''Sentitzen dugu! Ezin izan dugu zure aldaketa burutu, saio datu galera bat medio.'''
@@ -834,6 +837,12 @@ Ez du azalpenik eman.',
 'edit-already-exists' => 'Ezin izan da orri berria sortu.
 Jada existitzen da.',
 
+# Content models
+'content-model-wikitext' => 'wikitestua',
+'content-model-text' => 'testu laua',
+'content-model-javascript' => 'JavaScript',
+'content-model-css' => 'CSS',
+
 # Parser/template warnings
 'expensive-parserfunction-warning' => 'Adi: Orrialde honek parser funtzio deialdi oso garesti gehiegi ditu.
 
@@ -1107,7 +1116,7 @@ Saia zaitez zure eskeraren aurretik ''all:'' jartzen eduki guztien artean bilatz
 
 # Preferences page
 'preferences' => 'Hobespenak',
-'mypreferences' => 'Nire hobespenak',
+'mypreferences' => 'Hobespenak',
 'prefs-edits' => 'Aldaketa kopurua:',
 'prefsnologin' => 'Saioa hasi gabe',
 'prefsnologintext' => '<span class="plainlinks">[{{fullurl:{{#Special:UserLogin}}|returnto=$1}} Izena eman]</span> behar duzu zure hobespenak ezartzeko.',
@@ -1118,6 +1127,7 @@ Saia zaitez zure eskeraren aurretik ''all:'' jartzen eduki guztien artean bilatz
 'prefs-beta' => 'Beta ezaugarriak',
 'prefs-datetime' => 'Data eta ordua',
 'prefs-labs' => 'Labs ezaugarriak',
+'prefs-user-pages' => 'Erabiltzaile orrialdeak',
 'prefs-personal' => 'Erabiltzaile profila',
 'prefs-rc' => 'Azken aldaketak',
 'prefs-watchlist' => 'Jarraipen zerrenda',
@@ -1166,7 +1176,7 @@ Saia zaitez zure eskeraren aurretik ''all:'' jartzen eduki guztien artean bilatz
 'timezoneregion-indian' => 'Indiar Ozeanoa',
 'timezoneregion-pacific' => 'Ozeano Barea',
 'allowemail' => 'Beste erabiltzaileengandik e-posta mezuak jasotzea gaitu',
-'prefs-searchoptions' => 'Bilaketa aukerak',
+'prefs-searchoptions' => 'Bilatu',
 'prefs-namespaces' => 'Izen-tarteak',
 'defaultns' => 'Bestela izen-tarte hauetan bilatu:',
 'default' => 'lehenetsia',
@@ -1836,7 +1846,7 @@ Ikus, gainera [[Special:WantedCategories|kategoriarik eskatuenak]].',
 'linksearch-ok' => 'Bilatu',
 'linksearch-text' => '"*.wikipedia.org" bezalako izartxoak erabil daitezke.
 Gutxienez goi mailako domeinua behar du, adibidez "*.org".<br />
-Baimendutako protokoloak: <code>$1</code> (zure bilaketan hauek ez gehitu).',
+Baimendutako protokoloak: <code>$1</code> (protokoloa zehazten ez bada http:// hartzen da lehenetsitzat).',
 'linksearch-line' => '$1, $2(e)tik lotuta',
 'linksearch-error' => 'Komodinak izenaren hasieran bakarrik agertu beharko lirateke.',
 
@@ -2197,10 +2207,11 @@ Blokeo erregistroa azken sarrera ematen da azpian erreferentziarako:',
 'whatlinkshere-hideredirs' => '$1 birzuzenketak',
 'whatlinkshere-hidetrans' => '$1 transklusioak',
 'whatlinkshere-hidelinks' => '$1 loturak',
-'whatlinkshere-hideimages' => '$1 irudiak loturak ditu',
+'whatlinkshere-hideimages' => '$1 irudi loturak',
 'whatlinkshere-filters' => 'Iragazleak',
 
 # Block/unblock
+'autoblockid' => 'Blokeo automatikoa #$1',
 'block' => 'Erabiltzailea blokeatu',
 'unblock' => 'Erabiltzailea desblokeatu',
 'blockip' => 'Erabiltzailea blokeatu',
@@ -2599,6 +2610,9 @@ Baliteke zerrenda beltzean dagoen kanpo lotura batek sortzea arazo hori.',
 'pageinfo-header-edits' => 'Aldaketen historia',
 'pageinfo-views' => 'Bistaratze-kopurua',
 'pageinfo-edits' => 'Aldaketa kopuru totala',
+'pageinfo-redirectsto-info' => 'Info',
+'pageinfo-contentpage-yes' => 'Bai',
+'pageinfo-protect-cascading-yes' => 'Bai',
 
 # Skin names
 'skinname-standard' => 'Lehenetsia',
@@ -3298,4 +3312,6 @@ Irudiak bereizmen handienean daude, bestelako fitxategi motak beraiei esleitutak
 'searchsuggest-search' => 'Bilatu',
 'searchsuggest-containing' => 'edukian...',
 
+# Unknown messages
+'mytalk-parenthetical' => 'eztabaida',
 );
index 211b3a6..ea9ef43 100644 (file)
@@ -1967,25 +1967,25 @@ Voyez https://www.mediawiki.org/wiki/Manual:Image_Authorization.",
 'img-auth-isdir' => "Vous essayez d'accéder au répertoire « $1 ».
 Seul l'accès aux fichiers est permis.",
 'img-auth-streaming' => 'Lecture en continu de « $1 ».',
-'img-auth-public' => 'La fonction de img_auth.php est d’afficher des fichiers d’un wiki privé.
+'img-auth-public' => "La fonction de img_auth.php est d'afficher des fichiers d'un wiki privé.
 Ce wiki est configuré comme un wiki public.
-Pour une sécurité optimale, img_auth.php est désactivé.',
-'img-auth-noread' => 'L’utilisateur n’a pas le droit en lecture sur « $1 ».',
+Pour une sécurité optimale, img_auth.php est désactivé.",
+'img-auth-noread' => "L'utilisateur n'a pas le droit en lecture sur « $1 ».",
 'img-auth-bad-query-string' => "L'URL a une chaîne de requête invalide.",
 
 # HTTP errors
 'http-invalid-url' => 'URL incorrecte : $1',
 'http-invalid-scheme' => 'Les URL avec le schéma « $1 » ne sont pas supportées.',
-'http-request-error' => 'Erreur inconnue lors de l’envoi de la requête.',
+'http-request-error' => "Erreur inconnue lors de l'envoi de la requête.",
 'http-read-error' => 'Erreur de lecture HTTP.',
 'http-timed-out' => 'La requête HTTP a expiré.',
-'http-curl-error' => 'Erreur lors de la récupération de l’URL : $1',
-'http-host-unreachable' => 'Impossible d’atteindre l’URL.',
+'http-curl-error' => "Erreur lors de la récupération de l'URL : $1",
+'http-host-unreachable' => "Impossible d'atteindre l'URL.",
 'http-bad-status' => 'Il y a eu un problème lors de la requête HTTP : $1 $2',
 
 # Some likely curl errors. More could be added from <http://curl.haxx.se/libcurl/c/libcurl-errors.html>
 'upload-curl-error6' => 'URL injoignable',
-'upload-curl-error6-text' => 'L’URL fournie ne peut pas être atteinte. Veuillez vérifier que l’URL est correcte et que le site est en ligne.',
+'upload-curl-error6-text' => "L'URL fournie ne peut pas être atteinte. Veuillez vérifier que l'URL est correcte et que le site est en ligne.",
 'upload-curl-error28' => "Dépassement du délai lors de l'import",
 'upload-curl-error28-text' => 'Le site a mis trop longtemps à répondre. Vérifiez que le site est en ligne, attendez un peu et réessayez. Vous pouvez aussi réessayer à une heure de moindre affluence.',
 
@@ -2013,7 +2013,7 @@ Quand elle est filtrée par utilisateur, seuls les fichiers dont la version la p
 # File description page
 'file-anchor-link' => 'Fichier',
 'filehist' => 'Historique du fichier',
-'filehist-help' => 'Cliquer sur une date et heure pour voir le fichier tel qu’il était à ce moment-là.',
+'filehist-help' => "Cliquer sur une date et heure pour voir le fichier tel qu'il était à ce moment-là.",
 'filehist-deleteall' => 'supprimer tout',
 'filehist-deleteone' => 'supprimer',
 'filehist-revert' => 'rétablir',
@@ -2029,24 +2029,24 @@ Quand elle est filtrée par utilisateur, seuls les fichiers dont la version la p
 'filehist-missing' => 'Fichier manquant',
 'imagelinks' => 'Utilisation du fichier',
 'linkstoimage' => '{{PLURAL:$1|La page suivante utilise|Les $1 pages suivantes utilisent}} ce fichier :',
-'linkstoimage-more' => 'Plus {{PLURAL:$1|d’une page utilise|de $1 pages utilisent}} ce fichier.
+'linkstoimage-more' => "Plus {{PLURAL:$1|d'une page utilise|de $1 pages utilisent}} ce fichier.
 La liste suivante affiche seulement {{PLURAL:$1|la première page qui utilise|les $1 premières pages qui utilisent}} ce fichier.
-Une [[Special:WhatLinksHere/$2|liste complète]] est disponible.',
-'nolinkstoimage' => 'Aucune page n’utilise ce fichier.',
+Une [[Special:WhatLinksHere/$2|liste complète]] est disponible.",
+'nolinkstoimage' => "Aucune page n'utilise ce fichier.",
 'morelinkstoimage' => 'Voir [[Special:WhatLinksHere/$1|plus de liens]] vers ce fichier.',
 'linkstoimage-redirect' => '$1 (redirection de fichier) $2',
 'duplicatesoffile' => '{{PLURAL:$1|Le fichier suivant est un duplicata|Les fichiers suivants sont des duplicatas}} de celui-ci ([[Special:FileDuplicateSearch/$2|plus de détails]]) :',
-'sharedupload' => 'Ce fichier provient de : $1. Il peut être utilisé par d’autres projets.',
-'sharedupload-desc-there' => 'Ce fichier provient de : $1. Il peut être utilisé par d’autres projets.
-Veuillez consulter [$2 sa page de description] pour plus d’informations.',
-'sharedupload-desc-here' => 'Ce fichier provient de $1. Il peut être utilisé par d’autres projets.
-Sa description sur sa [$2 page de description] est affichée ci-dessous.',
-'sharedupload-desc-edit' => 'Ce fichier provient de : $1. Il peut être utilisé par d’autres projets.
-Vous voulez peut-être modifier la description sur sa [$2 page de description].',
-'sharedupload-desc-create' => 'Ce fichier provient de : $1. Il peut être utilisé par d’autres projets.
-Vous voulez peut-être modifier la description sur sa [$2 page de description].',
+'sharedupload' => "Ce fichier provient de : $1. Il peut être utilisé par d'autres projets.",
+'sharedupload-desc-there' => "Ce fichier provient de : $1. Il peut être utilisé par d'autres projets.
+Veuillez consulter [$2 sa page de description] pour plus d'informations.",
+'sharedupload-desc-here' => "Ce fichier provient de $1. Il peut être utilisé par d'autres projets.
+Sa description sur sa [$2 page de description] est affichée ci-dessous.",
+'sharedupload-desc-edit' => "Ce fichier provient de : $1. Il peut être utilisé par d'autres projets.
+Vous voulez peut-être modifier la description sur sa [$2 page de description].",
+'sharedupload-desc-create' => "Ce fichier provient de : $1. Il peut être utilisé par d'autres projets.
+Vous voulez peut-être modifier la description sur sa [$2 page de description].",
 'filepage-nofile' => 'Aucun fichier de ce nom existe.',
-'filepage-nofile-link' => 'Aucun fichier de ce nom n’existe, mais vous pouvez [$1 en importer un].',
+'filepage-nofile-link' => "Aucun fichier de ce nom n'existe, mais vous pouvez [$1 en importer un].",
 'uploadnewversion-linktext' => 'Importer une nouvelle version de ce fichier',
 'shared-repo-from' => 'de : $1',
 'shared-repo' => 'un dépôt partagé',
@@ -2062,24 +2062,24 @@ Vous voulez peut-être modifier la description sur sa [$2 page de description].'
 'filerevert-defaultcomment' => 'Version du $1 à $2 rétablie',
 'filerevert-submit' => 'Rétablir',
 'filerevert-success' => "'''[[Media:$1|$1]]''' a été rétabli à [$4 la version du $2 à $3].",
-'filerevert-badversion' => 'Il n’y a pas localement de version antérieure du fichier qui porte la date indiquée.',
+'filerevert-badversion' => "Il n'y a pas localement de version antérieure du fichier qui porte la date indiquée.",
 
 # File deletion
 'filedelete' => 'Supprimer $1',
 'filedelete-legend' => 'Supprimer le fichier',
 'filedelete-intro' => "Vous êtes sur le point de supprimer '''[[Media:$1|$1]]''' ainsi que tout son historique.",
-'filedelete-intro-old' => "Vous êtes en train deffacer la version de '''[[Media:$1|$1]]''' du [$4 $2 à $3].",
+'filedelete-intro-old' => "Vous êtes en train d'effacer la version de '''[[Media:$1|$1]]''' du [$4 $2 à $3].",
 'filedelete-comment' => 'Motif :',
 'filedelete-submit' => 'Supprimer',
 'filedelete-success' => "'''$1''' a été supprimé.",
 'filedelete-success-old' => "La version de '''[[Media:$1|$1]]''' du $2 à $3 a été supprimée.",
-'filedelete-nofile' => "'''$1''' nexiste pas.",
-'filedelete-nofile-old' => "Il nexiste aucune version archivée de '''$1''' avec les attributs indiqués.",
+'filedelete-nofile' => "'''$1''' n'existe pas.",
+'filedelete-nofile-old' => "Il n'existe aucune version archivée de '''$1''' avec les attributs indiqués.",
 'filedelete-otherreason' => 'Motif autre / supplémentaire :',
 'filedelete-reason-otherlist' => 'Autre motif',
-'filedelete-reason-dropdown' => '* Motifs fréquents de suppression de fichiers
-** Violation du droit dauteur
-** Fichier dupliqué',
+'filedelete-reason-dropdown' => "* Motifs fréquents de suppression de fichiers
+** Violation du droit d'auteur
+** Fichier dupliqué",
 'filedelete-edit-reasonlist' => 'Modifier les motifs fréquents de suppression',
 'filedelete-maintenance' => 'La suppression et restauration de fichiers est temporairement désactivée durant la maintenance.',
 'filedelete-maintenance-title' => 'Impossible de supprimer le fichier',
@@ -2092,24 +2092,24 @@ Entrée : ''typedecontenu''/''sous-type'', par exemple <code>image/jpeg</code>."
 'download' => 'télécharger',
 
 # Unwatched pages
-'unwatchedpages' => 'Pages ne faisant partie d’aucune liste de suivi',
+'unwatchedpages' => "Pages ne faisant partie d'aucune liste de suivi",
 
 # List redirects
 'listredirects' => 'Liste des redirections',
 
 # Unused templates
 'unusedtemplates' => 'Modèles inutilisés',
-'unusedtemplatestext' => 'Cette page liste toutes les pages de l’espace de noms « {{ns:template}} » qui ne sont incluses dans aucune autre page.
-N’oubliez pas de vérifier s’il n’y a pas d’autres liens vers les modèles avant de les supprimer.',
+'unusedtemplatestext' => "Cette page liste toutes les pages de l'espace de noms « {{ns:template}} » qui ne sont incluses dans aucune autre page.
+N'oubliez pas de vérifier s'il n'y a pas d'autres liens vers les modèles avant de les supprimer.",
 'unusedtemplateswlh' => 'autres liens',
 
 # Random page
 'randompage' => 'Page au hasard',
-'randompage-nopages' => 'Il n’y a aucune page dans {{PLURAL:$2|l’espace de noms|les espaces de noms}} : $1.',
+'randompage-nopages' => "Il n'y a aucune page dans {{PLURAL:$2|l'espace de noms|les espaces de noms}} : $1.",
 
 # Random redirect
 'randomredirect' => 'Page de redirection au hasard',
-'randomredirect-nopages' => 'Il n’y a aucune page de redirection dans l’espace de noms « $1 ».',
+'randomredirect-nopages' => "Il n'y a aucune page de redirection dans l'espace de noms « $1 ».",
 
 # Statistics
 'statistics' => 'Statistiques',
@@ -2122,7 +2122,7 @@ N’oubliez pas de vérifier s’il n’y a pas d’autres liens vers les modèl
 'statistics-pages' => 'Pages',
 'statistics-pages-desc' => 'Toutes les pages du wiki, y compris les pages de discussion, les redirections, etc.',
 'statistics-files' => 'Fichers importés',
-'statistics-edits' => 'Modifications de pages depuis l’installation de {{SITENAME}}',
+'statistics-edits' => "Modifications de pages depuis l'installation de {{SITENAME}}",
 'statistics-edits-average' => 'Nombre moyen de modifications par page',
 'statistics-views-total' => 'Visites',
 'statistics-views-total-desc' => 'Les vues des pages non existantes et des pages spéciales ne sont pas incluses',
@@ -2132,11 +2132,11 @@ N’oubliez pas de vérifier s’il n’y a pas d’autres liens vers les modèl
 'statistics-users-active-desc' => 'Utilisateurs ayant fait au moins une action durant {{PLURAL:$1|le dernier jours|les $1 derniers jours}}',
 'statistics-mostpopular' => 'Pages les plus consultées',
 
-'disambiguations' => 'Pages ayant des liens vers des pages d’homonymie',
+'disambiguations' => "Pages ayant des liens vers des pages d'homonymie",
 'disambiguationspage' => 'Template:Homonymie',
-'disambiguations-text' => "Les pages suivantes comportent au moins un lien vers une '''page dhomonymie'''.
+'disambiguations-text' => "Les pages suivantes comportent au moins un lien vers une '''page d'homonymie'''.
 Elles devraient plutôt pointer vers le bon article.<br />
-Une page est considérée comme une page dhomonymie si elle utilise un modèle lié à [[MediaWiki:Disambiguationspage]]",
+Une page est considérée comme une page d'homonymie si elle utilise un modèle lié à [[MediaWiki:Disambiguationspage]]",
 
 'doubleredirects' => 'Doubles redirections',
 'doubleredirectstext' => 'Voici une liste des pages qui redirigent vers des pages qui sont elles-mêmes des pages de redirection.
@@ -2152,7 +2152,7 @@ Les entrées <del>barrées</del> ont été résolues.',
 'brokenredirects-delete' => 'supprimer',
 
 'withoutinterwiki' => 'Pages sans liens inter-langues',
-'withoutinterwiki-summary' => 'Les pages suivantes ne possèdent pas de liens vers d’autres langues :',
+'withoutinterwiki-summary' => "Les pages suivantes ne possèdent pas de liens vers d'autres langues :",
 'withoutinterwiki-legend' => 'Préfixe',
 'withoutinterwiki-submit' => 'Afficher',
 
@@ -2168,9 +2168,9 @@ Les entrées <del>barrées</del> ont été résolues.',
 'nviews' => '$1 consultation{{PLURAL:$1||s}}',
 'nimagelinks' => 'Utilisé sur $1 {{PLURAL:$1|page|pages}}',
 'ntransclusions' => 'Utilisé sur $1 {{PLURAL:$1|page|pages}}',
-'specialpage-empty' => 'Il n’y a aucun résultat à afficher.',
+'specialpage-empty' => "Il n'y a aucun résultat à afficher.",
 'lonelypages' => 'Pages orphelines',
-'lonelypagestext' => 'Les pages suivantes ne sont ni pointées, ni incluses par d’autres pages du wiki.',
+'lonelypagestext' => "Les pages suivantes ne sont ni pointées, ni incluses par d'autres pages du wiki.",
 'uncategorizedpages' => 'Pages sans catégories',
 'uncategorizedcategories' => 'Catégories sans catégories',
 'uncategorizedimages' => 'Fichiers sans catégories',
@@ -2182,8 +2182,8 @@ Les entrées <del>barrées</del> ont été résolues.',
 'wantedpages' => 'Pages les plus demandées',
 'wantedpages-badtitle' => 'Titre invalide dans les résultats : $1',
 'wantedfiles' => 'Fichiers les plus demandés',
-'wantedfiletext-cat' => 'Les fichiers suivants sont utilisés, mais n’existent pas. Les fichiers d’autres dépôts peuvent être listés malgré qu’ils existent. Tous ces faux positifs seront <del>barrés</del>. En outre, les pages qui intègrent des fichiers qui n’existent pas sont répertoriées dans [[:$1]].',
-'wantedfiletext-nocat' => 'Les fichiers suivants sont utilisés, mais n’existent pas. Les fichiers d’autres dépôts peuvent être listés malgré qu’ils existent. Tous ces faux positifs seront <del>barrés</del>.',
+'wantedfiletext-cat' => "Les fichiers suivants sont utilisés, mais n'existent pas. Les fichiers d'autres dépôts peuvent être listés malgré qu'ils existent. Tous ces faux positifs seront <del>barrés</del>. En outre, les pages qui intègrent des fichiers qui n'existent pas sont répertoriées dans [[:$1]].",
+'wantedfiletext-nocat' => "Les fichiers suivants sont utilisés, mais n'existent pas. Les fichiers d'autres dépôts peuvent être listés malgré qu'ils existent. Tous ces faux positifs seront <del>barrés</del>.",
 'wantedtemplates' => 'Modèles demandés',
 'mostlinked' => 'Pages les plus liées',
 'mostlinkedcategories' => 'Catégories les plus utilisées',
@@ -2197,32 +2197,32 @@ Les entrées <del>barrées</del> ont été résolues.',
 'shortpages' => 'Pages courtes',
 'longpages' => 'Pages longues',
 'deadendpages' => 'Pages en impasse',
-'deadendpagestext' => 'Les pages suivantes ne contiennent aucun lien vers d’autres pages du wiki.',
+'deadendpagestext' => "Les pages suivantes ne contiennent aucun lien vers d'autres pages du wiki.",
 'protectedpages' => 'Pages protégées',
 'protectedpages-indef' => 'Uniquement les protections permanentes',
 'protectedpages-cascade' => 'Uniquement les protections en cascade',
 'protectedpagestext' => 'Les pages suivantes sont protégées contre les modifications ou le déplacement.',
-'protectedpagesempty' => 'Aucune page n’est protégée de cette façon.',
+'protectedpagesempty' => "Aucune page n'est protégée de cette façon.",
 'protectedtitles' => 'Titres protégés',
 'protectedtitlestext' => 'Les titres suivants sont protégés à la création',
-'protectedtitlesempty' => 'Aucun titre n’est actuellement protégé avec ces paramètres.',
+'protectedtitlesempty' => "Aucun titre n'est actuellement protégé avec ces paramètres.",
 'listusers' => 'Liste des utilisateurs',
 'listusers-editsonly' => 'Ne montrer que les utilisateurs ayant au moins une contribution',
 'listusers-creationsort' => 'Trier par date de création',
 'usereditcount' => '$1 modification{{PLURAL:$1||s}}',
 'usercreated' => '{{GENDER:$3|Créé}} le $1 à $2',
 'newpages' => 'Nouvelles pages',
-'newpages-username' => 'Nom d’utilisateur :',
+'newpages-username' => "Nom d'utilisateur :",
 'ancientpages' => 'Pages les plus anciennement modifiées',
 'move' => 'Renommer',
 'movethispage' => 'Renommer cette page',
-'unusedimagestext' => 'Les fichiers suivants existent, mais ne sont inclus dans aucune page.
-Veuillez noter que d’autres sites peuvent avoir un lien direct vers un fichier, et donc qu’un fichier peut être listé ici alors qu’il est en réalité utilisé sur ces sites.',
+'unusedimagestext' => "Les fichiers suivants existent, mais ne sont inclus dans aucune page.
+Veuillez noter que d'autres sites peuvent avoir un lien direct vers un fichier, et donc qu'un fichier peut être listé ici alors qu'il est en réalité utilisé sur ces sites.",
 'unusedcategoriestext' => 'Les catégories suivantes existent mais aucune page ou catégorie ne les utilise.',
 'notargettitle' => 'Pas de cible',
-'notargettext' => 'Vous n’avez pas indiqué une page ou un utilisateur sur lequel vous souhaitez effectuer cette action.',
+'notargettext' => "Vous n'avez pas indiqué une page ou un utilisateur sur lequel vous souhaitez effectuer cette action.",
 'nopagetitle' => 'Aucune telle page cible',
-'nopagetext' => 'La page cible que vous avez indiquée n’existe pas.',
+'nopagetext' => "La page cible que vous avez indiquée n'existe pas.",
 'pager-newer-n' => '{{PLURAL:$1|plus récente|$1 plus récentes}}',
 'pager-older-n' => '{{PLURAL:$1|plus ancienne|$1 plus anciennes}}',
 'suppress' => 'Superviser',
@@ -2233,16 +2233,16 @@ Veuillez noter que d’autres sites peuvent avoir un lien direct vers un fichier
 'booksources-search-legend' => 'Rechercher parmi des ouvrages de référence',
 'booksources-isbn' => 'ISBN :',
 'booksources-go' => 'Lister',
-'booksources-text' => 'Voici une liste indicative et non exclusive de liens vers d’autres sites vendant des livres neufs et d’occasion et sur lesquels vous trouverez peut-être des informations sur les ouvrages que vous cherchez :',
-'booksources-invalid-isbn' => 'L’ISBN donné ne semble pas être correct ; vérifiez si vous avez fait une erreur en copiant la source originale.',
+'booksources-text' => "Voici une liste indicative et non exclusive de liens vers d'autres sites vendant des livres neufs et d'occasion et sur lesquels vous trouverez peut-être des informations sur les ouvrages que vous cherchez :",
+'booksources-invalid-isbn' => "L'ISBN donné ne semble pas être correct ; vérifiez si vous avez fait une erreur en copiant la source originale.",
 
 # Special:Log
 'specialloguserlabel' => 'Auteur :',
 'speciallogtitlelabel' => 'Cible (titre ou utilisateur):',
-'log' => 'Journaux d’opérations',
+'log' => "Journaux d'opérations",
 'all-logs-page' => 'Tous les journaux publics',
-'alllogstext' => 'Affichage combiné de tous les journaux disponibles sur {{SITENAME}}.<br />
-Vous pouvez personnaliser l’affichage en sélectionnant le type de journal, le nom d’utilisateur ou la page concernée (ces deux derniers étant sensibles à la casse).',
+'alllogstext' => "Affichage combiné de tous les journaux disponibles sur {{SITENAME}}.<br />
+Vous pouvez personnaliser l'affichage en sélectionnant le type de journal, le nom d'utilisateur ou la page concernée (ces deux derniers étant sensibles à la casse).",
 'logempty' => 'Aucune opération correspondante dans les journaux.',
 'log-title-wildcard' => 'Chercher parmi les titres commençant par ce texte',
 'showhideselectedlogentries' => 'Afficher/masquer les entrées de journal sélectionnées',
@@ -2253,16 +2253,16 @@ Vous pouvez personnaliser l’affichage en sélectionnant le type de journal, le
 'nextpage' => 'Page suivante ($1)',
 'prevpage' => 'Page précédente ($1)',
 'allpagesfrom' => 'Afficher les pages à partir de :',
-'allpagesto' => 'Afficher les pages jusqu’à :',
+'allpagesto' => "Afficher les pages jusqu'à :",
 'allarticles' => 'Toutes les pages',
-'allinnamespace' => 'Toutes les pages (dans l’espace de noms $1)',
-'allnotinnamespace' => 'Toutes les pages (hors de l’espace de noms $1)',
+'allinnamespace' => "Toutes les pages (dans l'espace de noms $1)",
+'allnotinnamespace' => "Toutes les pages (hors de l'espace de noms $1)",
 'allpagesprev' => 'Précédent',
 'allpagesnext' => 'Suivant',
 'allpagessubmit' => 'Lister',
 'allpagesprefix' => 'Afficher les pages commençant par :',
 'allpagesbadtitle' => 'Le titre de page indiqué est incorrect : il contient un préfixe inter-langue ou inter-wiki réservé, ou contient un ou plusieurs caractères inutilisables dans les titres.',
-'allpages-bad-ns' => '{{SITENAME}} n’a pas d’espace de noms « $1 ».',
+'allpages-bad-ns' => "{{SITENAME}} n'a pas d'espace de noms « $1 ».",
 'allpages-hide-redirects' => 'Masquer les redirections',
 
 # SpecialCachedPage
@@ -2276,7 +2276,7 @@ Vous pouvez personnaliser l’affichage en sélectionnant le type de journal, le
 [[Special:UnusedCategories|Les catégories inutilisées]] ne sont pas affichées ici.
 Voyez aussi [[Special:WantedCategories|les catégories demandées]].',
 'categoriesfrom' => 'Afficher les catégories à partir de :',
-'special-categories-sort-count' => 'tri par nombre d’éléments',
+'special-categories-sort-count' => "tri par nombre d'éléments",
 'special-categories-sort-abc' => 'tri alphabétique',
 
 # Special:DeletedContributions
@@ -2293,7 +2293,7 @@ Voyez aussi [[Special:WantedCategories|les catégories demandées]].',
 Ils nécessitent au moins un domaine de niveau supérieur, par exemple « *.org ».<br />
 Protocoles reconnus : <code>$1</code> (http:// par défaut si aucun protocole n'est indiqué).",
 'linksearch-line' => '$1 est lié depuis $2',
-'linksearch-error' => 'Les caractères jokers ne peuvent être utilisés qu’au début du nom de domaine de l’hôte.',
+'linksearch-error' => "Les caractères jokers ne peuvent être utilisés qu'au début du nom de domaine de l'hôte.",
 
 # Special:ListUsers
 'listusersfrom' => 'Afficher les utilisateurs à partir de :',
@@ -2312,12 +2312,12 @@ Protocoles reconnus : <code>$1</code> (http:// par défaut si aucun protocole n'
 
 # Special:Log/newusers
 'newuserlogpage' => 'Journal des créations de comptes utilisateur',
-'newuserlogpagetext' => 'Cette page affiche l’historique des créations de comptes utilisateur.',
+'newuserlogpagetext' => "Cette page affiche l'historique des créations de comptes utilisateur.",
 
 # Special:ListGroupRights
-'listgrouprights' => 'Droits des groupes d’utilisateurs',
-'listgrouprights-summary' => 'Cette page contient une liste des groupes définis sur ce wiki ainsi que les droits d’accès qui leur sont associés.
-Des [[{{MediaWiki:Listgrouprights-helppage}}|informations additionnelles]] peuvent exister au sujet des droits individuels.',
+'listgrouprights' => "Droits des groupes d'utilisateurs",
+'listgrouprights-summary' => "Cette page contient une liste des groupes définis sur ce wiki ainsi que les droits d'accès qui leur sont associés.
+Des [[{{MediaWiki:Listgrouprights-helppage}}|informations additionnelles]] peuvent exister au sujet des droits individuels.",
 'listgrouprights-key' => '*<span class="listgrouprights-granted">Droit octroyé</span>
 *<span class="listgrouprights-revoked">Droit révoqué</span>',
 'listgrouprights-group' => 'Groupe',
@@ -2328,31 +2328,31 @@ Des [[{{MediaWiki:Listgrouprights-helppage}}|informations additionnelles]] peuve
 'listgrouprights-removegroup' => 'Retirer des membres {{PLURAL:$2|du groupe|des groupes}} : $1',
 'listgrouprights-addgroup-all' => 'Ajouter des membres à tous les groupes',
 'listgrouprights-removegroup-all' => 'Retirer des membres de tous les groupes',
-'listgrouprights-addgroup-self' => 'Peut s’ajouter {{PLURAL:$2|le groupe|les groupes}} à son propre compte : $1',
+'listgrouprights-addgroup-self' => "Peut s'ajouter {{PLURAL:$2|le groupe|les groupes}} à son propre compte : $1",
 'listgrouprights-removegroup-self' => 'Peut se retirer {{PLURAL:$2|le groupe|les groupes}} de son propre compte : $1',
-'listgrouprights-addgroup-self-all' => 'Peut s’ajouter tous les groupes à son propre compte',
+'listgrouprights-addgroup-self-all' => "Peut s'ajouter tous les groupes à son propre compte",
 'listgrouprights-removegroup-self-all' => 'Peut se retirer tous les groupes de son propre compte',
 
 # E-mail user
-'mailnologin' => 'Pas d’adresse d’expéditeur',
-'mailnologintext' => 'Vous devez être [[Special:UserLogin|identifié]] et avoir indiqué une adresse électronique valide dans vos [[Special:Preferences|préférences]] pour pouvoir envoyer des courriels à d’autres utilisateurs.',
+'mailnologin' => "Pas d'adresse d'expéditeur",
+'mailnologintext' => "Vous devez être [[Special:UserLogin|identifié]] et avoir indiqué une adresse électronique valide dans vos [[Special:Preferences|préférences]] pour pouvoir envoyer des courriels à d'autres utilisateurs.",
 'emailuser' => 'Lui envoyer un courriel',
 'emailuser-title-target' => 'Envoyer un courriel à {{GENDER:$1|cet utilisateur|cette utilisatrice}}',
 'emailuser-title-notarget' => "Envoyer un courriel à l'utilisateur",
 'emailpage' => "Envoyer un courriel à l'utilisateur",
-'emailpagetext' => 'Vous pouvez utiliser le formulaire ci-dessous pour envoyer un courriel à {{GENDER:$1|cet utilisateur|cette utilisatrice}}.
-L’adresse électronique que vous avez indiquée dans [[Special:Preferences|vos préférences]] apparaîtra dans le champ « Expéditeur » de votre message ; ainsi, le destinataire pourra vous répondre directement.',
-'usermailererror' => 'Erreur dans l’objet du courriel :',
+'emailpagetext' => "Vous pouvez utiliser le formulaire ci-dessous pour envoyer un courriel à {{GENDER:$1|cet utilisateur|cette utilisatrice}}.
+L'adresse électronique que vous avez indiquée dans [[Special:Preferences|vos préférences]] apparaîtra dans le champ « Expéditeur » de votre message ; ainsi, le destinataire pourra vous répondre directement.",
+'usermailererror' => "Erreur dans l'objet du courriel :",
 'defemailsubject' => "{{SITENAME}} Courriel de l'utilisateur « $1 »",
-'usermaildisabled' => 'L’envoi de courriels entre utilisateurs est désactivé',
-'usermaildisabledtext' => 'Vous ne pouvez pas envoyer de courriels à d’autres utilisateurs sur ce wiki',
+'usermaildisabled' => "L'envoi de courriels entre utilisateurs est désactivé",
+'usermaildisabledtext' => "Vous ne pouvez pas envoyer de courriels à d'autres utilisateurs sur ce wiki",
 'noemailtitle' => 'Aucune adresse de courriel',
-'noemailtext' => 'Cet utilisateur n’a pas spécifié une adresse de courriel valide.',
+'noemailtext' => "Cet utilisateur n'a pas spécifié une adresse de courriel valide.",
 'nowikiemailtitle' => 'Pas de courriel autorisé',
-'nowikiemailtext' => 'Cet utilisateur a choisi de ne pas recevoir de courriel de la part d’autres utilisateurs.',
+'nowikiemailtext' => "Cet utilisateur a choisi de ne pas recevoir de courriel de la part d'autres utilisateurs.",
 'emailnotarget' => "Nom d'utilisateur du destinataire inexistant ou invalide.",
 'emailtarget' => "Entrez le nom d'utilisateur du destinataire",
-'emailusername' => 'Nom d’utilisateur :',
+'emailusername' => "Nom d'utilisateur :",
 'emailusernamesubmit' => 'Soumettre',
 'email-legend' => 'Envoyer un courriel à un autre utilisateur de {{SITENAME}}',
 'emailfrom' => 'De :',
@@ -2360,7 +2360,7 @@ L’adresse électronique que vous avez indiquée dans [[Special:Preferences|vos
 'emailsubject' => 'Objet :',
 'emailmessage' => 'Message :',
 'emailsend' => 'Envoyer',
-'emailccme' => 'M’envoyer par courriel une copie de mon message.',
+'emailccme' => "M'envoyer par courriel une copie de mon message.",
 'emailccsubject' => 'Copie de votre message à $1 : $2',
 'emailsent' => 'Courriel envoyé',
 'emailsenttext' => 'Votre message a été envoyé par courriel.',
@@ -2386,16 +2386,16 @@ L’adresse électronique que vous avez indiquée dans [[Special:Preferences|vos
 'watchthispage' => 'Suivre cette page',
 'unwatch' => 'Ne plus suivre',
 'unwatchthispage' => 'Ne plus suivre',
-'notanarticle' => 'Ce n’est pas une page de contenu',
+'notanarticle' => "Ce n'est pas une page de contenu",
 'notvisiblerev' => 'La version a été supprimée',
-'watchnochange' => 'Aucun des éléments que vous suivez n’a été modifié durant la période affichée.',
+'watchnochange' => "Aucun des éléments que vous suivez n'a été modifié durant la période affichée.",
 'watchlist-details' => 'Votre liste de suivi référence $1 page{{PLURAL:$1||s}}, sans compter les pages de discussion.',
 'wlheader-enotif' => '* La notification par courriel est activée.',
 'wlheader-showupdated' => "* Les pages qui ont été modifiées depuis votre dernière visite sont affichées en '''gras'''.",
 'watchmethod-recent' => 'vérification des modifications récentes pour y trouver des pages suivies',
 'watchmethod-list' => 'vérification des pages suivies pour y trouver des modifications récentes',
 'watchlistcontains' => 'Votre liste de suivi référence $1 page{{PLURAL:$1||s}}.',
-'iteminvalidname' => 'Problème avec l’élément « $1 » : le nom est invalide.',
+'iteminvalidname' => "Problème avec l'élément « $1 » : le nom est invalide.",
 'wlnote' => "Ci-dessous {{PLURAL:$1|figure la dernière modification effectuée|figurent les '''$1''' dernières modifications effectuées}} durant {{PLURAL:$2|la dernière heure|les '''$2''' dernières heures}}, depuis $3, $4.",
 'wlshowlast' => 'Montrer les dernières $1 heures, les derniers $2 jours ou bien $3',
 'watchlist-options' => 'Options de la liste de suivi',
@@ -2427,7 +2427,7 @@ Contactez ce contributeur :
 courriel : $PAGEEDITOR_EMAIL
 wiki : $PAGEEDITOR_WIKI
 
-Il n’y aura pas d’autres notifications en cas de changements ultérieurs, à moins que vous ne visitiez cette page.
+Il n\'y aura pas d\'autres notifications en cas de changements ultérieurs, à moins que vous ne visitiez cette page.
 Vous pouvez aussi réinitialiser les drapeaux de notification pour toutes les pages de votre liste de suivi.
 
              Votre système de notification de {{SITENAME}}
@@ -2455,9 +2455,9 @@ Retour et assistance :
 'delete-confirm' => 'Supprimer « $1 »',
 'delete-legend' => 'Supprimer',
 'historywarning' => "'''Attention :''' la page que vous êtes sur le point de supprimer a un historique avec environ $1 {{PLURAL:$1|version|versions}} :",
-'confirmdeletetext' => 'Vous êtes sur le point de supprimer une page ou un fichier, ainsi que toutes ses versions antérieures historisées. Veuillez confirmer que c’est bien là ce que vous voulez faire, que vous en comprenez les conséquences et que vous faites ceci en accord avec les [[{{MediaWiki:Policy-url}}|règles internes]].',
+'confirmdeletetext' => "Vous êtes sur le point de supprimer une page ou un fichier, ainsi que toutes ses versions antérieures historisées. Veuillez confirmer que c'est bien là ce que vous voulez faire, que vous en comprenez les conséquences et que vous faites ceci en accord avec les [[{{MediaWiki:Policy-url}}|règles internes]].",
 'actioncomplete' => 'Action effectuée',
-'actionfailed' => 'L’action a échoué',
+'actionfailed' => "L'action a échoué",
 'deletedtext' => '« $1 » a été supprimée.
 Voir $2 pour une liste des suppressions récentes.',
 'dellogpage' => 'Journal des suppressions de page',
@@ -2467,16 +2467,16 @@ Voir $2 pour une liste des suppressions récentes.',
 'deletecomment' => 'Motif :',
 'deleteotherreason' => 'Motif autre ou supplémentaire :',
 'deletereasonotherlist' => 'Autre motif',
-'deletereason-dropdown' => '* Motifs de suppression les plus courants
-** Demande de lauteur
-** Violation des droits dauteur
-** Vandalisme',
+'deletereason-dropdown' => "* Motifs de suppression les plus courants
+** Demande de l'auteur
+** Violation des droits d'auteur
+** Vandalisme",
 'delete-edit-reasonlist' => 'Modifier les motifs de suppression de page',
 'delete-toobig' => 'Cette page possède un historique important de modifications, dépassant $1 version{{PLURAL:$1||s}}.
 La suppression de telles pages a été restreinte pour prévenir des perturbations accidentelles de {{SITENAME}}.',
-'delete-warning-toobig' => 'Cette page possède un historique important de modifications, dépassant $1 version{{PLURAL:$1||s}}.
+'delete-warning-toobig' => "Cette page possède un historique important de modifications, dépassant $1 version{{PLURAL:$1||s}}.
 La supprimer peut perturber le fonctionnement de la base de données de {{SITENAME}} ;
-veuiller ne procéder qu’avec prudence.',
+veuiller ne procéder qu'avec prudence.",
 
 # Rollback
 'rollback' => 'Révoquer les modifications',
@@ -2487,21 +2487,21 @@ veuiller ne procéder qu’avec prudence.',
 'rollbackfailed' => 'La révocation a échoué',
 'cantrollback' => 'Impossible de révoquer la modification ;
 le dernier contributeur est le seul auteur de cette page.',
-'alreadyrolled' => 'Impossible de révoquer la dernière modification de la page « [[:$1]] » effectuée par [[User:$2|$2]] ([[User talk:$2|Discuter]]{{int:pipe-separator}}[[Special:Contributions/$2|{{int:contribslink}}]]) ;
-quelqu’un d’autre a déjà modifié ou révoqué la page.
+'alreadyrolled' => "Impossible de révoquer la dernière modification de la page « [[:$1]] » effectuée par [[User:$2|$2]] ([[User talk:$2|Discuter]]{{int:pipe-separator}}[[Special:Contributions/$2|{{int:contribslink}}]]) ;
+quelqu'un d'autre a déjà modifié ou révoqué la page.
 
-La dernière modification de la page a été effectuée par [[User:$3|$3]] ([[User talk:$3|Discuter]]{{int:pipe-separator}}[[Special:Contributions/$3|{{int:contribslink}}]]).',
+La dernière modification de la page a été effectuée par [[User:$3|$3]] ([[User talk:$3|Discuter]]{{int:pipe-separator}}[[Special:Contributions/$3|{{int:contribslink}}]]).",
 'editcomment' => "Le résumé de la modification était : « ''$1'' ».",
 '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 (nom d’utilisateur supprimé) à la dernière version par [[User:$1|$1]]',
+'revertpage-nouser' => "Révocation des modifications par (nom d'utilisateur supprimé) à la dernière version par [[User:$1|$1]]",
 'rollback-success' => 'Révocation des modifications effectuées par $1 ;
 rétablissement de la dernière version par $2.',
 
 # Edit tokens
 'sessionfailure-title' => 'Erreur de session',
-'sessionfailure' => 'Votre session de connexion semble avoir des problèmes ;
-cette action a été annulée en prévention dun piratage de session.
-Veuillez cliquer sur « Précédent », rechargez la page d’où vous venez, puis réessayez.',
+'sessionfailure' => "Votre session de connexion semble avoir des problèmes ;
+cette action a été annulée en prévention d'un piratage de session.
+Veuillez cliquer sur « Précédent », rechargez la page d'où vous venez, puis réessayez.",
 
 # Protect
 'protectlogpage' => 'Journal des protections',
@@ -2518,18 +2518,18 @@ Consultez la [[Special:ProtectedPages|liste des pages protégées]] pour la list
 'protect-badnamespace-text' => 'Les pages dans cet espace de noms ne peuvent pas être protégées.',
 'protect-legend' => 'Confirmer la protection',
 'protectcomment' => 'Motif :',
-'protectexpiry' => 'Date d’expiration :',
-'protect_expiry_invalid' => 'La date d’expiration est invalide.',
-'protect_expiry_old' => 'La date d’expiration est déjà passée.',
-'protect-unchain-permissions' => 'Déverrouiller davantage d’options de protection',
+'protectexpiry' => "Date d'expiration :",
+'protect_expiry_invalid' => "La date d'expiration est invalide.",
+'protect_expiry_old' => "La date d'expiration est déjà passée.",
+'protect-unchain-permissions' => "Déverrouiller davantage d'options de protection",
 'protect-text' => "Vous pouvez consulter et modifier le niveau de protection de la page '''$1'''.",
 'protect-locked-blocked' => "Vous ne pouvez pas modifier les niveaux de protection tant que vous êtes bloqué{{GENDER:||e|(e)}}.
 Voici les réglages actuels de la page '''$1''' :",
 'protect-locked-dblock' => "Le niveau de protection ne peut pas être modifié car la base de données est verrouillée.
 Voici les réglages actuels de la page '''$1''' :",
-'protect-locked-access' => "Vous navez pas les droits nécessaires pour modifier les niveaux de protection de pages.
+'protect-locked-access' => "Vous n'avez pas les droits nécessaires pour modifier les niveaux de protection de pages.
 Voici les réglages actuels de la page '''$1''' :",
-'protect-cascadeon' => 'Cette page est protégée car incluse dans {{PLURAL:$1|la page suivante, qui a été protégée|les pages suivantes, qui ont été protégées}} avec l’option « protection en cascade » activée. Vous pouvez changer le niveau de protection de cette page sans que cela n’affecte la protection en cascade.',
+'protect-cascadeon' => "Cette page est protégée car incluse dans {{PLURAL:$1|la page suivante, qui a été protégée|les pages suivantes, qui ont été protégées}} avec l'option « protection en cascade » activée. Vous pouvez changer le niveau de protection de cette page sans que cela n'affecte la protection en cascade.",
 'protect-default' => 'Autoriser tous les utilisateurs',
 'protect-fallback' => 'Nécessite la permission « $1 »',
 'protect-level-autoconfirmed' => 'Bloquer les nouveaux utilisateurs et les utilisateurs anonymes',
@@ -2539,10 +2539,10 @@ Voici les réglages actuels de la page '''$1''' :",
 'protect-expiring-local' => 'expire le $1',
 'protect-expiry-indefinite' => 'infini',
 'protect-cascade' => 'Protéger les pages incluses dans celle-ci (protection en cascade)',
-'protect-cantedit' => 'Vous ne pouvez pas changer les niveaux de protection de cette page car vous n’avez pas la permission de la modifier.',
-'protect-othertime' => 'Autre date d’expiration :',
-'protect-othertime-op' => 'autre date d’expiration',
-'protect-existing-expiry' => 'Date d’expiration existante : $2 à $3',
+'protect-cantedit' => "Vous ne pouvez pas changer les niveaux de protection de cette page car vous n'avez pas la permission de la modifier.",
+'protect-othertime' => "Autre date d'expiration :",
+'protect-othertime-op' => "autre date d'expiration",
+'protect-existing-expiry' => "Date d'expiration existante : $2 à $3",
 'protect-otherreason' => 'Motif autre ou supplémentaire :',
 'protect-otherreason-op' => 'Autre motif',
 'protect-dropdown' => '* Motifs de protection courants
@@ -2574,22 +2574,22 @@ Voici les réglages actuels de la page '''$1''' :",
 'undeletepage' => 'Voir et restaurer des pages supprimées',
 'undeletepagetitle' => "'''La liste suivante contient des versions supprimées de [[:$1|$1]]'''.",
 'viewdeletedpage' => 'Voir les pages supprimées',
-'undeletepagetext' => '{{PLURAL:$1|La page suivante a été supprimée et se trouve|Les pages suivantes ont été supprimées et se trouvent}} dans la base de données archive, d’où {{PLURAL:$1|elle peut|elles peuvent}} encore être restaurée{{PLURAL:$1||s}}.
-L’archive peut être nettoyée périodiquement.',
+'undeletepagetext' => "{{PLURAL:$1|La page suivante a été supprimée et se trouve|Les pages suivantes ont été supprimées et se trouvent}} dans la base de données archive, d'où {{PLURAL:$1|elle peut|elles peuvent}} encore être restaurée{{PLURAL:$1||s}}.
+L'archive peut être nettoyée périodiquement.",
 'undelete-fieldset-title' => 'Restaurer les versions',
-'undeleteextrahelp' => "Pour restaurer lhistorique complet de cette page, laissez toutes les cases décochées et cliquez sur '''''Restaurer'''''.
+'undeleteextrahelp' => "Pour restaurer l'historique complet de cette page, laissez toutes les cases décochées et cliquez sur '''''Restaurer'''''.
 Pour effectuer une restauration partielle, cochez les cases correspondant aux versions à rétablir, puis cliquez sur '''''Restaurer'''''.",
 'undeleterevisions' => '$1 {{PLURAL:$1|version archivée|versions archivées}}',
-'undeletehistory' => 'Si vous restaurez la page, toutes les versions seront replacées dans l’historique.
-Si une nouvelle page avec le même nom a été créée depuis la suppression, les versions restaurées apparaîtront dans l’historique antérieur et la version courante ne sera pas automatiquement remplacée.',
+'undeletehistory' => "Si vous restaurez la page, toutes les versions seront replacées dans l'historique.
+Si une nouvelle page avec le même nom a été créée depuis la suppression, les versions restaurées apparaîtront dans l'historique antérieur et la version courante ne sera pas automatiquement remplacée.",
 'undeleterevdel' => 'La restauration ne sera pas effectuée si, au final, la version la plus récente de la page ou du fichier reste partiellement supprimée.
 Dans de tels cas, vous devez décocher ou démasquer les versions effacées les plus récentes (en tête de liste).',
-'undeletehistorynoadmin' => 'Cette page a été supprimée.
-Le motif de la suppression est indiqué dans le résumé ci-dessous, avec les détails des utilisateurs qui lont modifié avant sa suppression.
-Le contenu effectif de ces versions supprimées n’est accessible qu’aux administrateurs.',
+'undeletehistorynoadmin' => "Cette page a été supprimée.
+Le motif de la suppression est indiqué dans le résumé ci-dessous, avec les détails des utilisateurs qui l'ont modifié avant sa suppression.
+Le contenu effectif de ces versions supprimées n'est accessible qu'aux administrateurs.",
 'undelete-revision' => 'Version supprimée de $1 (version du $4 à $5) par $3 :',
-'undeleterevision-missing' => 'Version incorrecte ou manquante.
-Vous avez peut-être un mauvais lien, ou la version a pu être restaurée ou supprimée de l’archive.',
+'undeleterevision-missing' => "Version incorrecte ou manquante.
+Vous avez peut-être un mauvais lien, ou la version a pu être restaurée ou supprimée de l'archive.",
 'undelete-nodiff' => 'Aucune version précédente trouvée.',
 'undeletebtn' => 'Restaurer',
 'undeletelink' => 'visualiser/rétablir',
@@ -2610,12 +2610,12 @@ Consultez le [[Special:Log/delete|journal des suppressions]] pour obtenir la lis
 'undelete-search-box' => 'Rechercher des pages supprimées',
 'undelete-search-prefix' => 'Montrer les pages commençant par :',
 'undelete-search-submit' => 'Rechercher',
-'undelete-no-results' => 'Aucune page correspondante n’a été trouvée dans les archives de suppression.',
+'undelete-no-results' => "Aucune page correspondante n'a été trouvée dans les archives de suppression.",
 'undelete-filename-mismatch' => 'Impossible de restaurer la version du fichier datée du $1 : le nom de fichier ne correspond pas.',
 'undelete-bad-store-key' => 'Impossible de restaurer la version du fichier datée du $1 : le fichier était absent avant la suppression.',
-'undelete-cleanup-error' => 'Erreur lors de la suppression du fichier d’archive inutilisé « $1 ».',
-'undelete-missing-filearchive' => 'Impossible de restaurer le fichier d’archive avec l’identifiant $1 parce qu’il n’est pas dans la base de données.
-Il a peut-être déjà été restauré.',
+'undelete-cleanup-error' => "Erreur lors de la suppression du fichier d'archive inutilisé « $1 ».",
+'undelete-missing-filearchive' => "Impossible de restaurer le fichier d'archive avec l'identifiant $1 parce qu'il n'est pas dans la base de données.
+Il a peut-être déjà été restauré.",
 'undelete-error' => "Page d'erreur d'annulation",
 'undelete-error-short' => 'Erreur lors de la restauration du fichier : $1',
 'undelete-error-long' => 'Des erreurs ont été rencontrées lors de la restauration du fichier :
@@ -2634,28 +2634,28 @@ $1',
 
 # Contributions
 'contributions' => "Contributions de l'utilisateur",
-'contributions-title' => 'Liste des contributions de l’utilisateur $1',
+'contributions-title' => "Liste des contributions de l'utilisateur $1",
 'mycontris' => 'Contributions',
 'contribsub2' => 'Pour $1 ($2)',
-'nocontribs' => 'Aucune modification correspondant à ces critères n’a été trouvée.',
+'nocontribs' => "Aucune modification correspondant à ces critères n'a été trouvée.",
 'uctop' => '(dernière)',
 'month' => 'À partir du mois (et précédents) :',
 'year' => "À partir de l'année (et précédentes) :",
 
 'sp-contributions-newbies' => 'Ne montrer que les contributions des nouveaux utilisateurs',
 'sp-contributions-newbies-sub' => 'Parmi les nouveaux comptes',
-'sp-contributions-newbies-title' => 'Contributions d’utilisateurs parmi les nouveaux comptes',
+'sp-contributions-newbies-title' => "Contributions d'utilisateurs parmi les nouveaux comptes",
 'sp-contributions-blocklog' => 'journal des blocages',
 'sp-contributions-deleted' => 'contributions supprimées',
 'sp-contributions-uploads' => 'imports',
 'sp-contributions-logs' => 'journaux',
 'sp-contributions-talk' => 'discuter',
 'sp-contributions-userrights' => 'gérer les droits',
-'sp-contributions-blocked-notice' => 'Cet utilisateur est actuellement bloqué. La dernière entrée du journal des blocages est indiquée ci-dessous à titre d’information :',
-'sp-contributions-blocked-notice-anon' => 'Cette adresse IP est actuellement bloquée.
-La dernière entrée du journal des blocages est indiquée ci-dessous à titre d’information :',
+'sp-contributions-blocked-notice' => "Cet utilisateur est actuellement bloqué. La dernière entrée du journal des blocages est indiquée ci-dessous à titre d'information :",
+'sp-contributions-blocked-notice-anon' => "Cette adresse IP est actuellement bloquée.
+La dernière entrée du journal des blocages est indiquée ci-dessous à titre d'information :",
 'sp-contributions-search' => 'Rechercher les contributions',
-'sp-contributions-username' => 'Adresse IP ou nom d’utilisateur :',
+'sp-contributions-username' => "Adresse IP ou nom d'utilisateur :",
 'sp-contributions-toponly' => 'Ne montrer que les contributions qui sont les dernières des articles',
 'sp-contributions-submit' => 'Rechercher',
 
@@ -2665,7 +2665,7 @@ La dernière entrée du journal des blocages est indiquée ci-dessous à titre d
 'whatlinkshere-page' => 'Page :',
 'linkshere' => "Les pages ci-dessous contiennent un lien vers '''[[:$1]]''' :",
 'nolinkshere' => "Aucune page ne contient de lien vers '''[[:$1]]'''.",
-'nolinkshere-ns' => "Aucune page ne contient de lien vers '''[[:$1]]''' dans lespace de noms choisi.",
+'nolinkshere-ns' => "Aucune page ne contient de lien vers '''[[:$1]]''' dans l'espace de noms choisi.",
 'isredirect' => 'page de redirection',
 'istemplate' => 'inclusion',
 'isimage' => 'lien vers le fichier',
@@ -2680,36 +2680,36 @@ La dernière entrée du journal des blocages est indiquée ci-dessous à titre d
 
 # Block/unblock
 'autoblockid' => 'Blocage automatique #$1',
-'block' => 'Bloquer l’utilisateur',
+'block' => "Bloquer l'utilisateur",
 'unblock' => "Débloquer l'utilisateur",
-'blockip' => 'Bloquer l’utilisateur',
-'blockip-title' => 'Bloquer l’utilisateur',
-'blockip-legend' => 'Bloquer l’utilisateur',
-'blockiptext' => 'Utilisez le formulaire ci-dessous pour bloquer l’accès aux modifications faites à partir d’une adresse IP spécifique ou d’un nom d’utilisateur.
+'blockip' => "Bloquer l'utilisateur",
+'blockip-title' => "Bloquer l'utilisateur",
+'blockip-legend' => "Bloquer l'utilisateur",
+'blockiptext' => "Utilisez le formulaire ci-dessous pour bloquer l'accès aux modifications faites à partir d'une adresse IP spécifique ou d'un nom d'utilisateur.
 Une telle mesure ne devrait être prise que pour prévenir le vandalisme et en accord avec les [[{{MediaWiki:Policy-url}}|règles internes]].
-Donnez ci-dessous un motif précis (par exemple en citant les pages qui ont été vandalisées).',
+Donnez ci-dessous un motif précis (par exemple en citant les pages qui ont été vandalisées).",
 'ipadressorusername' => "Adresse IP ou nom d'utilisateur :",
 'ipbexpiry' => 'Durée avant expiration :',
 'ipbreason' => 'Motif :',
 'ipbreasonotherlist' => 'Autre motif',
-'ipbreason-dropdown' => '* Motifs de blocage les plus fréquents
+'ipbreason-dropdown' => "* Motifs de blocage les plus fréquents
 ** Insertion de fausses informations
 ** Suppression injustifiée de contenu des pages
 ** Insertion répétée de liens externes publicitaires (pollupostage)
 ** Insertion de contenu sans aucun sens et de déchets dans les pages
-** Tentative dintimidation ou harcèlement
-** Abus dutilisation de comptes multiples
-** Nom d’utilisateur inacceptable, injurieux ou diffamant',
+** Tentative d'intimidation ou harcèlement
+** Abus d'utilisation de comptes multiples
+** Nom d'utilisateur inacceptable, injurieux ou diffamant",
 'ipb-hardblock' => 'Empêcher les utilisateurs connectés de modifier en utilisant cette adresse IP',
 'ipbcreateaccount' => 'Empêcher la création de compte',
-'ipbemailban' => 'Empêcher l’utilisateur d’envoyer des courriels',
-'ipbenableautoblock' => 'Bloquer automatiquement la dernière adresse IP utilisée par l’utilisateur et toutes ses IPs ultérieures qu’il pourrait essayer',
+'ipbemailban' => "Empêcher l'utilisateur d'envoyer des courriels",
+'ipbenableautoblock' => "Bloquer automatiquement la dernière adresse IP utilisée par l'utilisateur et toutes ses IPs ultérieures qu'il pourrait essayer",
 'ipbsubmit' => 'Bloquer cet utilisateur',
 'ipbother' => 'Autre durée :',
 'ipboptions' => '2 heures:2 hours,1 jour:1 day,3 jours:3 days,1 semaine:1 week,2 semaines:2 weeks,1 mois:1 month,3 mois:3 months,6 mois:6 months,1 an:1 year,indéfiniment:infinite',
 'ipbotheroption' => 'autre',
 'ipbotherreason' => 'Motif différent ou supplémentaire :',
-'ipbhidename' => 'Masquer le nom d’utilisateur des modifications et des listes',
+'ipbhidename' => "Masquer le nom d'utilisateur des modifications et des listes",
 'ipbwatchuser' => 'Suivre les pages utilisateur et de discussion de cet utilisateur',
 'ipb-disableusertalk' => 'Empêcher cet utilisateur de modifier sa propre page de discussion pendant la durée de son blocage',
 'ipb-change-block' => 'Bloquer à nouveau cet utilisateur avec ces paramètres',
@@ -2719,14 +2719,14 @@ Donnez ci-dessous un motif précis (par exemple en citant les pages qui ont ét
 'blockipsuccesstext' => '[[Special:Contributions/$1|$1]] a été bloqué{{GENDER:$1||e|}}.<br />
 Consultez la [[Special:BlockList|liste des blocages]] pour revoir les blocages.',
 'ipb-blockingself' => 'Vous êtes sur le point de bloquer votre propre compte ! Êtes-vous certain de vouloir faire cela ?',
-'ipb-confirmhideuser' => 'Vous êtes sur le point de bloquer un utilisateur avec « cacher l’utilisateur » activé. Cela supprime le nom de l’utilisateur dans toutes les listes et les entrées du journal. Êtes-vous sûr de vouloir le faire ?',
+'ipb-confirmhideuser' => "Vous êtes sur le point de bloquer un utilisateur avec « cacher l'utilisateur » activé. Cela supprime le nom de l'utilisateur dans toutes les listes et les entrées du journal. Êtes-vous sûr de vouloir le faire ?",
 'ipb-edit-dropdown' => 'Modifier les motifs de blocage par défaut',
 'ipb-unblock-addr' => 'Débloquer $1',
 'ipb-unblock' => 'Débloquer un compte utilisateur ou une adresse IP',
 'ipb-blocklist' => 'Voir les blocages existants',
 'ipb-blocklist-contribs' => 'Contributions pour $1',
 'unblockip' => 'Débloquer un utilisateur ou une adresse IP',
-'unblockiptext' => 'Utilisez le formulaire ci-dessous pour rétablir l’accès aux modifications depuis une adresse IP ou un nom d’utilisateur.',
+'unblockiptext' => "Utilisez le formulaire ci-dessous pour rétablir l'accès aux modifications depuis une adresse IP ou un nom d'utilisateur.",
 'ipusubmit' => 'Supprimer ce blocage',
 'unblocked' => '[[User:$1|$1]] a été débloqué',
 'unblocked-range' => '$1 a été débloqué',
@@ -2736,11 +2736,11 @@ Consultez la [[Special:BlockList|liste des blocages]] pour revoir les blocages.'
 'ipblocklist-legend' => 'Chercher un utilisateur bloqué',
 'blocklist-userblocks' => 'Masquer les blocages de comptes',
 'blocklist-tempblocks' => 'Masquer les blocages temporaires',
-'blocklist-addressblocks' => 'Masquer les blocages d’adresses IP uniques',
+'blocklist-addressblocks' => "Masquer les blocages d'adresses IP uniques",
 'blocklist-rangeblocks' => 'Masquer les blocs de portée',
 'blocklist-timestamp' => 'Date et heure',
 'blocklist-target' => 'Cible',
-'blocklist-expiry' => 'Date d’expiration',
+'blocklist-expiry' => "Date d'expiration",
 'blocklist-by' => 'Administrateur ayant effectué le blocage',
 'blocklist-params' => 'Paramètres de blocage',
 'blocklist-reason' => 'Motif',
@@ -2768,9 +2768,9 @@ Le motif fourni pour le blocage de $1 est : « $2 ».',
 'blocklog-showsuppresslog' => 'Cet utilisateur a été bloqué et caché précédemment. Le journal des suppressions est disponible ci-dessous :',
 'blocklogentry' => 'a bloqué [[$1]] ; expiration : $2 $3',
 'reblock-logentry' => 'a modifié les paramètres du blocage de [[$1]] avec une expiration au $2 $3',
-'blocklogtext' => 'Ceci est le journal des actions de blocages et déblocages d’utilisateurs.
+'blocklogtext' => "Ceci est le journal des actions de blocages et déblocages d'utilisateurs.
 Les adresses IP automatiquement bloquées ne sont pas listées.
-Consultez la [[Special:BlockList|liste des blocages]] pour voir les bannissements et blocages effectivement en cours.',
+Consultez la [[Special:BlockList|liste des blocages]] pour voir les bannissements et blocages effectivement en cours.",
 'unblocklogentry' => 'a débloqué $1',
 'block-log-flags-anononly' => 'utilisateurs anonymes seulement',
 'block-log-flags-nocreate' => 'création de compte interdite',
@@ -3228,6 +3228,8 @@ Permet de rétablir la version précédente et d’ajouter un motif dans la boî
 'markedaspatrollederror' => 'Ne peut être marquée comme relue',
 'markedaspatrollederrortext' => 'Vous devez sélectionner une version pour pouvoir la marquer comme relue.',
 'markedaspatrollederror-noautopatrol' => 'Vous n’avez pas le droit de marquer vos propres modifications comme relues.',
+'markedaspatrollednotify' => 'Cette modification de $1 a été marquée comme contrôlée.',
+'markedaspatrollederrornotify' => 'Échec du marquage comme contrôlé.',
 
 # Patrol log
 'patrol-log-page' => 'Journal des relectures',
index 40ac42d..ba140f0 100644 (file)
@@ -3722,4 +3722,6 @@ Ef ekki, þá getur þú notað einfalt eyðublað hér fyrir neðan. Athugasemd
 'duration-centuries' => '$1 {{PLURAL:$1|öld|aldir}}',
 'duration-millennia' => '$1 {{PLURAL:$1|árþúsund}}',
 
+# Unknown messages
+'mytalk-parenthetical' => 'spjall',
 );
index 60b295c..7747631 100644 (file)
@@ -304,7 +304,7 @@ $messages = array(
 'cancel' => 'გაუქმება',
 'moredotdotdot' => 'ვრცლად...',
 'mypage' => 'გვერდი',
-'mytalk' => 'á\83©á\83\94á\83\9bá\83\98 á\83\92á\83\90á\83\9cá\83®á\83\98á\83\9aá\83\95á\83\90',
+'mytalk' => 'განხილვა',
 'anontalk' => 'ამ IP-ს განხილვა',
 'navigation' => 'ნავიგაცია',
 'and' => '&#32;და',
@@ -1248,7 +1248,7 @@ $1",
 
 # Preferences page
 'preferences' => 'კონფიგურაცია',
-'mypreferences' => 'á\83©á\83\94á\83\9bá\83\98 á\83\99á\83\9dá\83\9cá\83¤á\83\98á\83\92á\83£á\83 á\83\90á\83ªá\83\98á\83\90',
+'mypreferences' => 'კონფიგურაცია',
 'prefs-edits' => 'რედაქციების რაოდენობა:',
 'prefsnologin' => 'შესული არ ხართ',
 'prefsnologintext' => 'თქვენ <span class="plainlinks">[{{fullurl:{{#Special:UserLogin}}|returnto=$1}} რეგისტრირებული უნდა იყოთ]</span> მომხმარებლის კონფიგურაციის შესაცვლელად.',
@@ -2184,7 +2184,7 @@ $1',
 
 # Watchlist
 'watchlist' => 'ჩემი კონტროლის სია',
-'mywatchlist' => 'á\83©á\83\94á\83\9bá\83\98 á\83\99á\83\9dá\83\9cá\83¢á\83 á\83\9dá\83\9aá\83\98á\83¡ á\83¡á\83\98á\83\90',
+'mywatchlist' => 'კონტროლის სია',
 'watchlistfor2' => '$1 ($2) თვის',
 'nowatchlist' => 'თქვენი კონტროლის სია ცარიელია.',
 'watchlistanontext' => '$1
@@ -2445,7 +2445,7 @@ $1',
 # Contributions
 'contributions' => 'მომხმარებლის წვლილი',
 'contributions-title' => 'მომხმარებლის წვლილი $1',
-'mycontris' => 'á\83©á\83\94á\83\9bá\83\98 á\83¬á\83\95á\83\9aá\83\98á\83\9aá\83\98',
+'mycontris' => 'წვლილი',
 'contribsub2' => '$1 ($2) თვის',
 'nocontribs' => 'ძებნისას მითითებული პარამეტრების შესაბამისი არც ერთი ცვლილება ნაპოვნი არ არის',
 'uctop' => '(თავი)',
index a685766..568725f 100644 (file)
@@ -283,6 +283,7 @@ $1',
 'toc' => 'فہرست',
 'showtoc' => 'پشاوے',
 'hidetoc' => 'کھوشتاوے',
+'collapsible-collapse' => 'خاتمہ/Collapse',
 'thisisdeleted' => 'لوڑے  یا بحال کورے $1',
 'viewdeleted' => 'لوڑے $1؟',
 'restorelink' => '{{PLURAL:$1|ای ترمیم حذف ہوی|$1 ترامیم حذف ہونی}}',
@@ -569,6 +570,7 @@ MySQL جوابِ خطاء پرائے "$3: $4"',
 'nextrevision' => '→پروشٹیو اعادہ',
 'currentrevisionlink' => 'حالیہ نظرثانی',
 'cur' => 'رائج',
+'next' => 'پروشٹیو',
 'last' => 'سابقہ',
 'histlegend' => "انتخاب: مختلف نسخان موازنہ کوریکو بچے ، پیامی خانان نشان زد کوری موڑا دیرو بٹنا کلک کورے۔
 
@@ -1059,6 +1061,8 @@ HTML tags لوڑے.',",
 * gpslongitude
 * gpsaltitude',
 
+'exif-dc-date' => 'تاریخ',
+
 # External editor support
 'edit-externally' => 'ھیہ مسلو ایڈیٹ کورے',
 'edit-externally-help' => '(See the [//www.mediawiki.org/wiki/Manual:External_editors setup instructions] for more information)
@@ -1069,6 +1073,9 @@ HTML tags لوڑے.',",
 'namespacesall' => 'تھمامو',
 'monthsall' => 'سف',
 
+# action=purge
+'confirm_purge_button' => 'OK/ٹھیک شیر',
+
 # Table pager
 'table_pager_first' => 'آویلو صفحہ',
 
@@ -1080,10 +1087,27 @@ HTML tags لوڑے.',",
 # Core parser functions
 'duplicate-defaultsort' => '\'\'\'خبردار:\'\'\' ڈیفالٹ تاڑٰ(نغڑی) "$2" پروشٹیو ڈیفالٹ تاڑا "$1" لیگی شیر۔',
 
+# Special:FilePath
+'filepath-page' => 'فایل',
+'filepath-submit' => 'Go/بوغے',
+
 # Special:SpecialPages
 'specialpages' => 'اسپیشل صفحہ',
 
 # Special:Tags
 'tag-filter' => '[[Special:Tags|Tag]] filter:',
+'tag-filter-submit' => 'فلٹر',
+'tags-title' => 'Tags/ٹیگز',
+
+# Special:ComparePages
+'compare-page1' => 'صفحہ 1',
+
+# Feedback
+'feedback-message' => 'پیغام',
+
+# Search suggestions
+'searchsuggest-search' => 'Search/تلاش',
 
+# Unknown messages
+'mytalk-parenthetical' => 'مشقولگی',
 );
index d0edf3a..1203616 100644 (file)
@@ -196,7 +196,7 @@ $messages = array(
 'cancel' => 'ವಜಾ ಮಾಡಿ',
 'moredotdotdot' => 'ಇನ್ನಷ್ಟು...',
 'mypage' => 'ನನ್ನ ಪುಟ',
-'mytalk' => 'ನನà³\8dನ à²\9aರà³\8dà²\9aà³\86',
+'mytalk' => 'ಚರ್ಚೆ',
 'anontalk' => 'ಈ ಐ.ಪಿ ಗೆ ಮಾತನಾಡಿ',
 'navigation' => 'ಸಂಚರಣೆ',
 'and' => '&#32;ಮತ್ತು',
@@ -875,7 +875,7 @@ $2',
 
 # Preferences page
 'preferences' => 'ಪ್ರಾಶಸ್ತ್ಯಗಳು',
-'mypreferences' => 'ನನà³\8dನ à²ªà³\8dರಾಶಸà³\8dತà³\8dಯà²\97ಳà³\81',
+'mypreferences' => 'ಪ್ರಾಶಸ್ತ್ಯಗಳು',
 'prefs-edits' => 'ಸಂಪಾದನೆಗಳ ಸಂಖ್ಯೆ:',
 'prefsnologin' => 'ಲಾಗಿನ್ ಆಗಿಲ್ಲ',
 'prefsnologintext' => 'ಬಳಕೆದಾರ ಪ್ರಾಶಸ್ತ್ಯಗಳನ್ನು ಬದಲಾಯಿಸಲು ನೀವು <span class="plainlinks">[{{fullurl:{{#Special:UserLogin}}|returnto=$1}} ಲಾಗ್ ಇನ್]</span> ಆಗಿರಬೇಕು.',
@@ -1404,7 +1404,7 @@ $2',
 
 # Watchlist
 'watchlist' => 'ವೀಕ್ಷಣಾ ಪಟ್ಟಿ',
-'mywatchlist' => 'ನನà³\8dನ à²µà³\80à²\95à³\8dಷಣಾಪà²\9fà³\8dà²\9fಿ',
+'mywatchlist' => 'ವೀಕ್ಷಣಾಪಟ್ಟಿ',
 'watchlistfor2' => '$1 ($2) ಗೆ',
 'nowatchlist' => 'ನಿಮ್ಮ ವೀಕ್ಷಣಾಪಟ್ಟಿಯಲ್ಲಿ ಯಾವುದೇ ಪುಟಗಳಿಲ್ಲ',
 'watchlistanontext' => 'ನಿಮ್ಮ ವೀಕ್ಷಣಾಪಟ್ಟಿಯನ್ನು ನೋಡಲು ಅಥವ ಸಂಪಾದಿಸಲು ದಯವಿಟ್ಟು $1 ಮಾಡಿ.',
@@ -1541,7 +1541,7 @@ $2',
 # Contributions
 'contributions' => 'ಸದಸ್ಯರ ಕಾಣಿಕೆಗಳು',
 'contributions-title' => '$1 ಸದಸ್ಯರ ಕಾಣಿಕೆಗಳು',
-'mycontris' => 'ನನà³\8dನ à²\95ಾಣಿà²\95à³\86à²\97ಳà³\81',
+'mycontris' => 'ಕಾಣಿಕೆಗಳು',
 'contribsub2' => '$1 ($2) ಗೆ',
 'uctop' => ' (ಮೇಲಕ್ಕೆ)',
 'month' => 'ಈ ತಿಂಗಳಿಂದ (ಮತ್ತು ಮುಂಚಿನ):',
@@ -1812,6 +1812,10 @@ $2',
 'siteusers' => '{{SITENAME}} {{PLURAL:$2|ಸದಸ್ಯ|ಸದಸ್ಯರು}} $1',
 'creditspage' => 'ಪುಟದ ಗೌರವಗಳು',
 
+# Info page
+'pageinfo-toolboxlink' => 'ಪುಟದ ಮಾಹಿತಿ',
+'pageinfo-redirectsto' => 'ಪುನರ್ನಿರ್ದೇಶನ:',
+
 # Image deletion
 'deletedrevision' => 'ಹಳೆ ಆವೃತ್ತಿ $1 ಅನ್ನು ಅಳಿಸಲಾಗಿದೆ',
 'filedeleteerror-short' => 'ಈ ಫೈಲನ್ನು ಅಳಿಸುವುದರಲ್ಲಿ ದೋಷ: $1',
@@ -2121,4 +2125,15 @@ $5
 'revdelete-restricted' => 'ನಿರ್ವಾಹಕರಿಗೆ ನಿಬಂಧನೆಗಳನ್ನು ಅನ್ವಯಿಸಲಾಯಿತು',
 'revdelete-unrestricted' => 'ನಿರ್ವಾಹಕರ ನಿಬಂಧನೆಗಳನ್ನು ತೆಗೆಯಲಾಯಿತು',
 
+# Durations
+'duration-seconds' => '$1 {{PLURAL:$1|ಕ್ಷಣ|ಕ್ಷಣಗಳು}}',
+'duration-minutes' => '$1 {{PLURAL:$1|ನಿಮಿಷ|ನಿಮಿಷಗಳು}}',
+'duration-hours' => '$1 {{PLURAL:$1|ಘಂಟೆ|ಘಂಟೆಗಳು}}',
+'duration-days' => '$1 {{PLURAL:$1|ದಿನ|ದಿನಗಳು}}',
+'duration-weeks' => '$1 {{PLURAL:$1|ವಾರ|ವಾರಗಳು}}',
+'duration-years' => '$1 {{PLURAL:$1|ವರ್ಷ|ವರ್ಷಗಳು}}',
+'duration-decades' => '$1 {{PLURAL:$1|ದಶಕ|ದಶಕಗಳು}}',
+'duration-centuries' => '$1 {{PLURAL:$1|ಶತಮಾನ|ಶತಮಾನಗಳು}}',
+'duration-millennia' => '$1 {{PLURAL:$1|ಸಹಸ್ರಮಾನ|ಸಹಸ್ರಮಾನಗಳು}}',
+
 );
index a986d2a..691e3e6 100644 (file)
@@ -141,7 +141,7 @@ $messages = array(
 'category-article-count-limited' => 'Kategori iko mamiliki {{PLURAL:$1|ciek laman|$1 laman}} barikuik.',
 'category-file-count' => '{{PLURAL:$2|Kategori iko hanyo mamiliki ciek laman barikuik.|Kategori iko mamiliki {{PLURAL:$1|laman|$1 laman}} barikuik, dari total $2.}}',
 'category-file-count-limited' => 'Kategori iko mamiliki {{PLURAL:$1|laman|$1 laman}} barikuik.',
-'listingcontinuesabbrev' => 'cont.',
+'listingcontinuesabbrev' => 'lanjuik',
 'index-category' => 'Laman nan diindeks',
 'noindex-category' => 'Laman nan indak diindeks',
 'broken-file-category' => 'Laman jo gambar rusak',
@@ -286,9 +286,9 @@ $1',
 'youhavenewmessagesmulti' => 'Awak ang mandapek pasan baru pado $1',
 'editsection' => 'suntiang',
 'editold' => 'suntiang',
-'viewsourceold' => 'Caliak sumber',
+'viewsourceold' => 'caliak sumber',
 'editlink' => 'suntiang',
-'viewsourcelink' => 'Caliak sumber',
+'viewsourcelink' => 'caliak sumber',
 'editsectionhint' => 'Suntiang bagian: $1',
 'toc' => 'Daftar isi',
 'showtoc' => 'tampilkan',
@@ -811,7 +811,7 @@ Legend: '''({{int:kini}})''' = perbedaan jo revisi terakhir, '''({{int:dulu}})''
 
 # Revision deletion
 'rev-delundel' => 'tampilkan/suruakkan',
-'revdel-restore' => 'Ganti tampilan',
+'revdel-restore' => 'ganti tampilan',
 'revdel-restore-deleted' => 'suntiangan nan alah dihapuih',
 'revdel-restore-visible' => 'tampilan revisi',
 
@@ -835,8 +835,8 @@ Legend: '''({{int:kini}})''' = perbedaan jo revisi terakhir, '''({{int:dulu}})''
 'notextmatches' => 'Indak ado judul nan pas',
 'prevn' => '{{PLURAL:$1|$1}} sabalunnyo',
 'nextn' => '{{PLURAL:$1|$1}} salanjuknyo',
-'prevn-title' => '$1 {{PLURAL:$1|hasil|hasil}} sabalunnyo',
-'nextn-title' => '$1 {{PLURAL:$1|hasil|hasil}} salanjuknyo',
+'prevn-title' => '$1 {{PLURAL:$1|Hasil|Hasil}} sabalunnyo',
+'nextn-title' => '$1 {{PLURAL:$1|Hasil|Hasil}} salanjuknyo',
 'shown-title' => 'Caliakkan $1 {{PLURAL:$1|hasil|hasil}} per laman',
 'viewprevnext' => 'Caliakkan ($1 {{int:pipe-separator}} $2) ($3)',
 'searchmenu-exists' => "'''Ado laman nan banamo \"[[:\$1]]\" pado wiki ko.'''",
@@ -1277,7 +1277,7 @@ Nan lainnyo akan tasuruak sacaro default.
 # 'all' in various places, this might be different for inflected languages
 'watchlistall2' => 'semua',
 'namespacesall' => 'semua',
-'monthsall' => 'semua',
+'monthsall' => 'sado',
 
 # Watchlist editing tools
 'watchlisttools-view' => 'Tampilkan parubahan takaik',
index 453adbb..21158d7 100644 (file)
@@ -3151,6 +3151,8 @@ Dette er sannsynligvis forårsaket av en lenke til et svartelistet eksternt nett
 'markedaspatrollederror' => 'Kan ikke merke som godkjent',
 'markedaspatrollederrortext' => 'Du må spesifisere en versjon å merke som godkjent.',
 'markedaspatrollederror-noautopatrol' => 'Du kan ikke merke dine egne endringer som godkjente.',
+'markedaspatrollednotify' => 'Denne endringen av $1 har blitt patruljert.',
+'markedaspatrollederrornotify' => 'Patruljering feilet.',
 
 # Patrol log
 'patrol-log-page' => 'Godkjenningslogg',
index 4a9c316..c26fd7e 100644 (file)
@@ -1162,7 +1162,7 @@ Deze bestaat al.',
 
 # Content models
 'content-model-wikitext' => 'wikitekst',
-'content-model-text' => 'platte tekst',
+'content-model-text' => 'tekst zonder opmaak',
 'content-model-javascript' => 'JavaScript',
 'content-model-css' => 'CSS',
 
index 80e9c9c..47a0dbe 100644 (file)
@@ -3504,18 +3504,18 @@ Për piasì, che an conferma che da bon a veul torna creélo.",
 'livepreview-ready' => "Antramentr ch'as caria… Carià.",
 'livepreview-failed' => "La preuva dal viv a l'é falìa!
 Ch'a preuva an manera sòlita.",
-'livepreview-error' => 'Conession falà: $1 "$2"
-Ch\'a preuva an manera sòlita.',
+'livepreview-error' => "Conession falìa: $1 «$2».
+Ch'a preuva an manera sòlita.",
 
 # Friendlier slave lag warnings
-'lag-warn-normal' => 'Le modìfiche pì neuve ëd $1 {{PLURAL:$1|second|second}} a podrìo nen ess-ie ant sta lista-sì.',
-'lag-warn-high' => "Për via che la màchina serventa a tarda a dene d'arspòsta, le modìfiche pì giovne che $1 {{PLURAL:$1|second|second}} fa
-a podrìo ëdcò nen ess-ie ant sta lista -sì.",
+'lag-warn-normal' => 'Le modìfiche pì neuve ëd $1 {{PLURAL:$1|second}} a podrìo nen ess-ie ant sta lista-sì.',
+'lag-warn-high' => "Për via che la màchina serventa a tarda a dene d'arspòsta, le modìfiche fàite men che $1 {{PLURAL:$1|second}} fa
+a podrìo ëdcò nen ess-ie ant sta lista-sì.",
 
 # Watchlist editor
-'watchlistedit-numitems' => "A l'é antramentr ch'a ten sot ëuj {{PLURAL:$1|1 tìtol|$1 tìtoj}}, nen contand le pàgine ëd discussion.",
-'watchlistedit-noitems' => "A-i é pa gnun tìtol ch'as ten-a sot euj.",
-'watchlistedit-normal-title' => "Modifiché la lista ëd lòn ch'as ten sot euj",
+'watchlistedit-numitems' => "A l'é antramentr ch'a ten sot-euj {{PLURAL:$1|1 tìtol|$1 tìtoj}}, nen contand le pàgine ëd discussion.",
+'watchlistedit-noitems' => "A-i é pa gnun tìtol ch'as ten-a sot-euj.",
+'watchlistedit-normal-title' => "Modifiché la lista ëd lòn ch'as ten sot-euj",
 'watchlistedit-normal-legend' => "Gavé via ij tìtoj da 'nt la lista ëd lòn ch'as ten sot euj",
 'watchlistedit-normal-explain' => "Ij tìtoj ch'a ten sot euj a son ësmonù ambelessì-sota. Për gavene via un ch'a-i fasa la crosëtta ant la casela ch'a l'ha aranda, e peuj ch'ai bata ansima a «{{int:Watchlistedit-normal-submit}}». As peul ëdcò [[Special:EditWatchlist/raw|modifiché la lista ampressa]].",
 'watchlistedit-normal-submit' => 'Gavé via ij tìtoj',
index 395a70d..5a924c8 100644 (file)
@@ -269,7 +269,7 @@ $messages = array(
 'category_header' => 'د "$1" په وېشنيزه کې شته مخونه',
 'subcategories' => 'څېرمه وېشنيزې',
 'category-media-header' => 'د "$1" په وېشنيزه کې شته رسنۍ',
-'category-empty' => "''تر Ø§Ù\88سÙ\87 Ù¾Ù\88رÛ\90 Ù\87Ù\85دا Ù\88Û\90Ø´Ù\86Ù\8aزÙ\87 Ù\87Û\90Ú\85 Ú©Ù\88Ù\85 Ù\85Ø® Ù\8aا Ú©Ù\88Ù\85Ù\87 رسنيزه دوتنه نلري.''",
+'category-empty' => "''دا Ù\88Û\90Ø´Ù\86Ù\8aزÙ\87 ØªØ± Ø§Ù\88سÙ\87 Ù¾Ù\88رÛ\90 Ú©Ù\88Ù\85 Ù\85Ø® Ù\8aا رسنيزه دوتنه نلري.''",
 'hidden-categories' => '{{PLURAL:$1|پټه وېشنيزه|پټې وېشنيزې}}',
 'hidden-category-category' => 'پټې وېشنيزې',
 'category-subcat-count' => '{{PLURAL:$2|په دې وېشنيزه کې دا لاندې وړه وېشنيزه ده.|په دې وېشنيزه کې له ټولټال $2 نه {{PLURAL:$1|وړه وېشنيزه ده|$1 وړې وېشنيزې دي}}.}}',
@@ -288,9 +288,9 @@ $messages = array(
 'newwindow' => '(په نوې کړکۍ کې پرانيستل کېږي)',
 'cancel' => 'ناګارل',
 'moredotdotdot' => 'نور ...',
-'mypage' => 'زÙ\85ا Ù¾Ø§Ú¼Ù\87',
-'mytalk' => 'زÙ\85ا Ø®Ø¨Ø±Û\90 Ø§ØªØ±Û\90',
-'anontalk' => 'ددې IP لپاره خبرې اترې',
+'mypage' => 'زÙ\85ا Ù\85Ø®',
+'mytalk' => 'خبرې اترې',
+'anontalk' => 'ددې IP خبرې اترې',
 'navigation' => 'ګرځښت',
 'and' => '&#32;او',
 
@@ -331,7 +331,7 @@ $messages = array(
 'history' => 'د مخ پېښليک',
 'history_short' => 'پېښليک',
 'updatedmarker' => 'زما د وروستي راتګ نه راپدېخوا اوسمهاله شوی',
-'printableversion' => 'د چاپ بڼه',
+'printableversion' => 'چاپي بڼه',
 'permalink' => 'تلپاتې تړنه',
 'print' => 'چاپ',
 'view' => 'کتل',
@@ -340,7 +340,7 @@ $messages = array(
 'editthispage' => 'همدا مخ سمول',
 'create-this-page' => 'همدا مخ ليکل',
 'delete' => 'ړنګول',
-'deletethispage' => 'دا مخ ړنګ کړه',
+'deletethispage' => 'دا مخ ړنګول',
 'undelete_short' => '{{PLURAL:$1|يو سمون|$1 سمونې}} ناړنګول',
 'viewdeleted_short' => '{{PLURAL:$1|يو ړنګ شوی سمون|$1 ړنګ شوي سمونونه}} کتل',
 'protect' => 'ژغورل',
@@ -361,7 +361,7 @@ $messages = array(
 'userpage' => 'د کارن پاڼه کتل',
 'projectpage' => 'د پروژې مخ کتل',
 'imagepage' => 'د دوتنې مخ کتل',
-'mediawikipage' => 'د پيغامونو مخ کتل',
+'mediawikipage' => 'پيغام مخ کتل',
 'templatepage' => 'د کينډۍ مخ کتل',
 'viewhelppage' => 'د لارښود مخ کتل',
 'categorypage' => 'د وېشنيزې مخ کتل',
@@ -447,7 +447,7 @@ $1',
 'sort-ascending' => 'مخپورته اوډل',
 
 # Short words for each namespace, by default used in the namespace tab in monobook
-'nstab-main' => 'Ù\84Ù\8aÚ©Ù\86Ù\87',
+'nstab-main' => 'Ù\85Ø®',
 'nstab-user' => 'کارن مخ',
 'nstab-media' => 'د رسنۍ مخ',
 'nstab-special' => 'ځانګړی مخ',
@@ -455,7 +455,7 @@ $1',
 'nstab-image' => 'دوتنه',
 'nstab-mediawiki' => 'پيغام',
 'nstab-template' => 'کينډۍ',
-'nstab-help' => 'لارښود',
+'nstab-help' => 'لارښود مخ',
 'nstab-category' => 'وېشنيزه',
 
 # Main script and global functions
@@ -671,13 +671,13 @@ $1',
 # Edit page toolbar
 'bold_sample' => 'زغرد متن',
 'bold_tip' => 'زغرد متن',
-'italic_sample' => 'کوږ ليک',
-'italic_tip' => 'کوږ ليک',
+'italic_sample' => 'رېوند متن',
+'italic_tip' => 'رېوند متن',
 'link_sample' => 'د تړن سرليک',
 'link_tip' => 'کورنۍ تړنه',
 'extlink_sample' => 'http://www.example.com د تړنې سرليک',
 'extlink_tip' => 'باندنۍ تړنې (د http:// مختاړی مه هېروی)',
-'headline_sample' => 'سرÙ\84Ù\8aÚ©',
+'headline_sample' => 'د Ø³Ø±Ù\84Ù\8aÚ© Ù\85تÙ\86',
 'headline_tip' => 'د ۲ کچې سرليک',
 'nowiki_sample' => 'دلته دې بې بڼې متن ځای پر ځای شي',
 'nowiki_tip' => 'د ويکي بڼه نيونه بابېزه ګڼل',
@@ -773,7 +773,7 @@ $1',
 'editingsection' => '$1 (برخه) په سمېدنې کې دی',
 'editingcomment' => 'د $1 سمون (نوې برخه)',
 'editconflict' => 'په سمادولو کې خنډ: $1',
-'yourtext' => 'ستاسو متن',
+'yourtext' => 'ستاسې متن',
 'storedversion' => 'زېرمه شوې مخکتنه',
 'yourdiff' => 'توپيرونه',
 'copyrightwarning' => "لطفاً په پام کې وساتۍ چې ټولې هغه ونډې چې تاسې يې {{SITENAME}} کې ترسره کوی هغه د $2 له مخې د خپرولو لپاره ګڼل کېږي (د لانورو تفصيلاتو لپاره $1 وګورۍ). که تاسې نه غواړۍ چې په ليکنو کې مو په بې رحمۍ سره لاسوهنې (سمونې) وشي او د نورو په غوښتنه پسې لانورې هم خپرې شي، نو دلته يې مه ځای پر ځای کوی..<br />
@@ -815,7 +815,7 @@ $1',
 'edit-no-change' => 'ستاسې سمون بابېزه وګڼل شو، دا ځکه چې تاسې په متن کې کوم بدلون نه دی راوستلی.',
 'edit-already-exists' => 'په دې نوم يو نوی مخ جوړ نه شو.
 پدې نوم د پخوا نه يو مخ شته.',
-'defaultmessagetext' => 'تلوالیزه پيغام متن',
+'defaultmessagetext' => 'تلواليزه پيغام متن',
 
 # Parser/template warnings
 'post-expand-template-inclusion-warning' => "'''ګواښنه:''' دا کينډۍ د خپل ټاکلي بريد نه ډېره لويه ده.
@@ -989,7 +989,7 @@ $1',
 
 # Preferences page
 'preferences' => 'غوره توبونه',
-'mypreferences' => 'زÙ\85ا ØºÙ\88رÙ\87 ØªÙ\88بÙ\88Ù\86Ù\87',
+'mypreferences' => 'غوره توبونه',
 'prefs-edits' => 'د سمونو شمېر:',
 'prefsnologin' => 'غونډال کې نه ياست ننوتي',
 'prefsnologintext' => 'د دې لپاره چې خپل غوره توبونه مو وټاکی، نو پکار ده چې لومړی تاسو غونډال کې <span class="plainlinks">[{{fullurl:{{#Special:UserLogin}}|returnto=$1}} ننوځی]</span>.',
@@ -1200,7 +1200,7 @@ $1',
 'recentchanges-label-unpatrolled' => 'دغه سمون تر اوسه پورې نه دی څارل شوی',
 'rcnote' => "دلته لاندې {{PLURAL:$1|وروستی '''1''' بدلون دی|وروستي '''$1''' بدلونونه دي}} چې په  {{PLURAL:$2| يوې ورځ|'''$2''' ورځو}} کې تر $4 نېټې او $5 بجو پېښ شوي.",
 'rcnotefrom' => "په همدې ځای کې لاندې هغه بدلونونه دي چې د '''$2''' نه راپدېخوا پېښ شوي (تر '''$1''' پورې ښکاره شوي).",
-'rclistfrom' => 'هغه بدلونونه ښکاره کړی چې له $1 نه پيلېږي',
+'rclistfrom' => 'هغه نوي بدلونونه ښکاره کول چې له $1 نه پيلېږي',
 'rcshowhideminor' => 'وړې سمونې $1',
 'rcshowhidebots' => 'روباټ $1',
 'rcshowhideliu' => 'غونډال کې ننوتي کارنان $1',
@@ -1350,7 +1350,7 @@ $1',
 'filehist' => 'د دوتنې پېښليک',
 'filehist-help' => 'په يوې نېټې/يوه وخت وټوکۍ چې د هماغه وخت او نېټې دوتنه چې په هماغه وخت کې څنګه ښکارېده هماغسې درښکاره شي.',
 'filehist-deleteall' => 'ټول ړنګول',
-'filehist-deleteone' => 'همدا ړنګول',
+'filehist-deleteone' => 'ړنګول',
 'filehist-revert' => 'په څټ ګرځول',
 'filehist-current' => 'اوسنی',
 'filehist-datetime' => 'نېټه/وخت',
@@ -1431,7 +1431,7 @@ $1',
 'statistics-users' => 'ثبت شوي [[Special:ListUsers|کارنان]]',
 'statistics-users-active' => 'فعاله کارنان',
 'statistics-users-active-desc' => 'هغه کارنان چې په {{PLURAL:$1|وروستۍ ورځ|وروستيو $1 ورځو}} کې فعاله ونډه لرلې',
-'statistics-mostpopular' => 'تر ټولو ډېر کتل شوي مخونه',
+'statistics-mostpopular' => 'ډېر کتل شوي مخونه',
 
 'disambiguations' => 'د مبهمو مخونو سره تړلي مخونه',
 'disambiguationspage' => 'Template:ناجوت',
@@ -1460,15 +1460,15 @@ $1',
 'ntransclusions' => 'په $1 {{PLURAL:$1|مخ|مخونو}} کارېدلی',
 'specialpage-empty' => 'د دې راپور لپاره کومې پايلې نشته.',
 'lonelypages' => 'يتيم مخونه',
-'uncategorizedpages' => 'Ù¾Ù\87 Ù\88Û\90Ø´Ù\86Ù\8aزÙ\88 Ù\86اÙ\88Û\90Ø´Ù\84Ù\8a Ù\85Ø®Ù\88Ù\86Ù\87',
-'uncategorizedcategories' => 'Ù¾Ù\87 Ù\88Û\90Ø´Ù\86Ù\8aزÙ\88 Ù\86اÙ\88Û\90Ø´Ù\84Û\90 Ù\88Û\90Ø´Ù\86Ù\8aزÛ\90',
-'uncategorizedimages' => 'Ù¾Ù\87 Ù\88Û\90Ø´Ù\86Ù\8aزÙ\88 Ù\86اÙ\88Û\90Ø´Ù\84Ù\8a Ø§Ù\86Ú\81Ù\88رÙ\86Ù\87',
-'uncategorizedtemplates' => 'Ù¾Ù\87 Ù\88Û\90Ø´Ù\86Ù\8aزÙ\88 Ù\86اÙ\88Û\90Ø´Ù\84Û\90 Ú©Ù\8aÙ\86Ú\89Û\8d',
+'uncategorizedpages' => 'ناوېشلي مخونه',
+'uncategorizedcategories' => 'ناوېشلې وېشنيزې',
+'uncategorizedimages' => 'ناوېشلي انځورنه',
+'uncategorizedtemplates' => 'ناوېشلې کينډۍ',
 'unusedcategories' => 'ناکارېدلې وېشنيزې',
 'unusedimages' => 'ناکارېدلې دوتنې',
 'popularpages' => 'نامتو مخونه',
 'wantedcategories' => 'غوښتلې وېشنيزې',
-'wantedpages' => 'غوښتل شوې پاڼې',
+'wantedpages' => 'غوښتلي مخونه',
 'wantedfiles' => 'غوښتلې دوتنې',
 'wantedtemplates' => 'غوښتلې کينډۍ',
 'mostlinked' => 'د ډېرو تړنو مخونه',
@@ -1506,7 +1506,7 @@ $1',
 
 # Book sources
 'booksources' => 'د کتاب سرچينې',
-'booksources-search-legend' => 'د Ú©ØªØ§Ø¨Ù\8a Ø³Ø±Ú\86Ù\8aÙ\86Ù\88 Ù\84Ù¼Ù\88Ù\86 Ù\88Ú©Ú\93Û\8d',
+'booksources-search-legend' => 'د Ú©ØªØ§Ø¨Ù\8a Ø³Ø±Ú\86Ù\8aÙ\86Ù\88 Ù¾Ù\84Ù¼Ù\86Ù\87',
 'booksources-go' => 'ورځه',
 'booksources-text' => 'دا لاندې د هغه وېبځايونو د تړنو لړليک دی چېرته چې نوي او زاړه کتابونه پلورل کېږي، او يا هم کېدای شي چې د هغه کتاب په هکله مالومات ولري کوم چې تاسو ورپسې لټېږۍ:',
 
@@ -1519,7 +1519,7 @@ $1',
 
 # Special:AllPages
 'allpages' => 'ټول مخونه',
-'alphaindexline' => '$1 نه تر $2 پورې',
+'alphaindexline' => '$1 تر $2',
 'nextpage' => 'بل مخ ($1)',
 'prevpage' => 'تېر مخ ($1)',
 'allpagesfrom' => 'هغه مخونه کتل چې پېلېږي په:',
@@ -1623,7 +1623,7 @@ $1',
 
 # Watchlist
 'watchlist' => 'زما کتنلړ',
-'mywatchlist' => 'زما کتنلړ',
+'mywatchlist' => 'کتنلړ',
 'watchlistfor2' => 'د $1 لپاره $2',
 'nowatchlist' => 'ستاسې کتنلړ کې څه نه شته.',
 'watchlistanontext' => 'د خپل کتنلړ د توکو د سمولو او کتلو لپاره $1 ترسره کړۍ.',
@@ -1699,7 +1699,7 @@ $UNWATCHURL  نه ليدنه وکړۍ
 'confirm' => 'تاييد',
 'excontent' => 'د مخ مېنځپانګه دا وه: "$1"',
 'excontentauthor' => 'د مخ مېنځپانګه دا وه: "$1" (او يواځينی ونډه وال "[[Special:Contributions/$2|$2]]" وه)',
-'exblank' => 'دا مخ تش وه',
+'exblank' => 'مخ تش وه',
 'delete-confirm' => '"$1" ړنګوول',
 'delete-legend' => 'ړنګول',
 'historywarning' => "ګواښنه:''' تاسې چې د کوم مخ د ړنګېدو تکل لری، هغه د نژدې $1 {{PLURAL:$1|بڼې|بڼو}} يو پېښليک لري:",
@@ -1726,7 +1726,7 @@ $UNWATCHURL  نه ليدنه وکړۍ
 
 # Protect
 'protectlogpage' => 'د ژغورنې يادښت',
-'protectedarticle' => '"[[$1]]" وژغورلی شو',
+'protectedarticle' => '"[[$1]]" وژغورل شو',
 'modifiedarticleprotection' => 'د "[[$1]]" لپاره د ژغورنې کچه بدله شوه',
 'protect-title' => 'د "$1" لپاره د ژغورنې کچه بدلول',
 'prot_1movedto2' => '[[$1]]، [[$2]] ته ولېږدېده',
@@ -1805,7 +1805,7 @@ $UNWATCHURL  نه ليدنه وکړۍ
 # Contributions
 'contributions' => 'د کارن ونډې',
 'contributions-title' => 'د $1 کارن ونډې',
-'mycontris' => 'زما ونډې',
+'mycontris' => 'ونډې',
 'contribsub2' => 'د $1 لپاره ($2)',
 'uctop' => '(سرپاڼه)',
 'month' => 'له مياشتې د (او پخواني):',
@@ -1818,7 +1818,7 @@ $UNWATCHURL  نه ليدنه وکړۍ
 'sp-contributions-uploads' => 'پورته کېدنې',
 'sp-contributions-logs' => 'يادښتونه',
 'sp-contributions-talk' => 'خبرې اترې',
-'sp-contributions-search' => 'د Ù\88Ù\86Ú\89Ù\88 Ù\84Ù¼Ù\88Ù\86',
+'sp-contributions-search' => 'د Ù\88Ù\86Ú\89Ù\88 Ù¾Ù\84Ù¼Ù\86Ù\87',
 'sp-contributions-username' => 'IP پته يا کارن-نوم:',
 'sp-contributions-toponly' => 'يوازې هغه سمونونه چې تر ټولو تازه بڼې لري ښکاره کول',
 'sp-contributions-submit' => 'پلټل',
@@ -1838,7 +1838,7 @@ $UNWATCHURL  نه ليدنه وکړۍ
 'whatlinkshere-hideredirs' => 'مخ ګرځونې $1',
 'whatlinkshere-hidetrans' => 'پايلې $1',
 'whatlinkshere-hidelinks' => 'تړنې $1',
-'whatlinkshere-hideimages' => '$1 د انځور تړنې',
+'whatlinkshere-hideimages' => 'د دوتنې تړنې $1',
 'whatlinkshere-filters' => 'چاڼګرونه',
 
 # Block/unblock
@@ -2003,7 +2003,7 @@ $UNWATCHURL  نه ليدنه وکړۍ
 # Namespace 8 related
 'allmessages' => 'د غونډال پيغامونه',
 'allmessagesname' => 'نوم',
-'allmessagesdefault' => 'ټاکل شوی متن',
+'allmessagesdefault' => 'تلواليزه پيغام متن',
 'allmessagescurrent' => 'اوسنی متن',
 'allmessagestext' => 'دا د مېډياويکي په نوم-تشيال کې د غونډال د پيغامونو لړليک دی.
 که چېرته تاسې د ميډياويکي په ځايتابه کې ونډې ترسره کول غواړۍ نو لطفاً [//www.mediawiki.org/wiki/Localisation د ويډياويکي ځايتابه] او [//translatewiki.net translatewiki.net] نه ليدنه وکړۍ.',
@@ -2058,7 +2058,7 @@ $UNWATCHURL  نه ليدنه وکړۍ
 'tooltip-search' => '{{SITENAME}} پلټل',
 'tooltip-search-go' => 'په دې نوم د کټ مټ ورته مخ شتون په صورت کې، هماغه مخ ته ورځه',
 'tooltip-search-fulltext' => 'په مخونو کې دا متن وپلټه',
-'tooltip-p-logo' => 'لومړی مخ',
+'tooltip-p-logo' => 'لومړي مخ ته ورتلل',
 'tooltip-n-mainpage' => 'لومړي مخ ته ورتلل',
 'tooltip-n-mainpage-description' => 'آرنی مخ کتل',
 'tooltip-n-portal' => 'د پروژې په اړه، تاسې څه شيان او چېرته کولای شی چې وې مومۍ',
@@ -2082,7 +2082,7 @@ $UNWATCHURL  نه ليدنه وکړۍ
 'tooltip-ca-nstab-special' => 'دا يو ځانګړی مخ دی، تاسې په دې مخ کې سمون نه شی کولای.',
 'tooltip-ca-nstab-project' => 'د پروژې مخ کتل',
 'tooltip-ca-nstab-image' => 'د دوتنې مخ کتل',
-'tooltip-ca-nstab-mediawiki' => 'د ØºÙ\88Ù\86Ú\89اÙ\84 Ù¾Ù\8aغاÙ\85Ù\88Ù\86Ù\87 Ú\9aکارÙ\87 Ú©Ù\88ل',
+'tooltip-ca-nstab-mediawiki' => 'د ØºÙ\88Ù\86Ú\89اÙ\84 Ù¾Ù\8aغاÙ\85Ù\88Ù\86Ù\87 Ú©Øªل',
 'tooltip-ca-nstab-template' => 'کينډۍ کتل',
 'tooltip-ca-nstab-help' => 'د لارښود مخ کتل',
 'tooltip-ca-nstab-category' => 'د وېشنيزې مخ ښکاره کول',
index e85ff8e..4accfb4 100644 (file)
@@ -1004,7 +1004,7 @@ Este ainda não foi gravado!",
 'note' => "'''Nota:'''",
 'previewnote' => "'''Lembre-se que esta é apenas uma antevisão do resultado.'''
 As modificações ainda não foram gravadas!",
-'continue-editing' => 'Continuar a editar',
+'continue-editing' => 'Ir para a área de edição',
 'previewconflict' => 'Esta antevisão do resultado apresenta o texto da caixa de edição acima tal como este aparecerá se escolher gravá-lo.',
 'session_fail_preview' => "'''Não foi possível processar a edição devido à perda dos dados da sua sessão.
 Tente novamente, por favor.
@@ -1090,6 +1090,10 @@ Ela parece ter sido eliminada.',
 Ela já existia.',
 'defaultmessagetext' => 'Texto da mensagem padrão',
 
+# Content models
+'content-model-javascript' => 'JavaScript',
+'content-model-css' => 'CSS',
+
 # Parser/template warnings
 'expensive-parserfunction-warning' => 'Aviso: Esta página contém demasiadas chamadas de funções exigentes do analisador sintáctico.
 
@@ -2300,6 +2304,7 @@ Encontram-se disponíveis [[{{MediaWiki:Listgrouprights-helppage}}|informações
 'mailnologin' => 'Não existe endereço de envio',
 'mailnologintext' => 'Precisa de estar [[Special:UserLogin|autenticado]] e possuir um endereço de correio válido nas suas [[Special:Preferences|preferências]], para poder enviar correio electrónico a outros utilizadores.',
 'emailuser' => 'Enviar correio electrónico a este utilizador',
+'emailuser-title-target' => 'Enviar correio eletrónico a {{GENDER:$1|este utilizador|esta utilizadora}}',
 'emailpage' => 'Enviar correio electrónico ao utilizador',
 'emailpagetext' => 'Pode usar o formulário abaixo para enviar uma mensagem por correio electrónico para este utilizador.
 O endereço de correio que introduziu nas suas [[Special:Preferences|preferências]] irá aparecer no campo do remetente da mensagem "De:", para que o destinatário lhe possa responder directamente.',
@@ -2635,7 +2640,7 @@ Para referência é apresentado abaixo o último registo de bloqueio:',
 'whatlinkshere-hideredirs' => '$1 redireccionamentos',
 'whatlinkshere-hidetrans' => '$1 transclusões',
 'whatlinkshere-hidelinks' => '$1 links',
-'whatlinkshere-hideimages' => '$1 links para imagens',
+'whatlinkshere-hideimages' => '$1 links para ficheiros',
 'whatlinkshere-filters' => 'Filtros',
 
 # Block/unblock
@@ -3147,6 +3152,8 @@ Este bloqueio foi provavelmente causado por um link para um site externo que con
 'pageinfo-magic-words' => '{{PLURAL:$1|Palavra mágica|Palavras mágicas}} ($1)',
 'pageinfo-hidden-categories' => '{{PLURAL:$1|Categoria oculta|Categorias ocultas}} ($1)',
 'pageinfo-toolboxlink' => 'Informações da página',
+'pageinfo-contentpage-yes' => 'Sim',
+'pageinfo-protect-cascading-yes' => 'Sim',
 
 # Skin names
 'skinname-standard' => 'Clássico',
@@ -4060,4 +4067,6 @@ Caso contrário, pode facilmente usar o formulário abaixo. O seu comentário se
 'duration-centuries' => '$1 {{PLURAL:$1|século|séculos}}',
 'duration-millennia' => '$1 {{PLURAL:$1|milénio|milénios}}',
 
+# Unknown messages
+'mytalk-parenthetical' => 'discussão',
 );
index 1f7a1bb..25ac391 100644 (file)
@@ -365,7 +365,8 @@ This can also appear in the credits page if the credits feature is enabled,for e
 {{Identical|Find}}',
 'qbbrowse' => '{{Identical|Browse}}',
 'qbedit' => '{{Identical|Edit}}',
-'qbmyoptions' => '{{Identical|My pages}}',
+'qbmyoptions' => 'Heading in the Cologne Blue skin user menu containing links to user (talk) page, preferences, watchlist, etc.
+{{Identical|My pages}}',
 'qbspecialpages' => '{{Identical|Special pages}}',
 'faqpage' => "FAQ is short for ''frequently asked questions''. This page is only linked on some of the old skins, not in Monobook or Modern.
 
@@ -2107,6 +2108,8 @@ Extensions making use of it:
 * $1 is a storage path.',
 'backend-fail-delete' => 'Parameters:
 * $1 is a file path.',
+'backend-fail-describe' => 'Parameters:
+* $1 is a file path.',
 'backend-fail-alreadyexists' => 'Parameters:
 * $1 is a filename.',
 'backend-fail-store' => 'Parameters:
@@ -3695,7 +3698,7 @@ Parameters:
 Start with a lowercase letter, unless the first word is “SVG”.',
 'svg-long-desc-animated' => 'Displayed under an SVG image at the image description page if the image is animated. Non-animated images use {{msg-mw|svg-long-desc}}.
 * $1 is the width in pixels
-* $2 is the height in pixels, and 
+* $2 is the height in pixels, and
 * $3 is the file size including a unit (for example "10 KB").
 
 Start with a lowercase letter, unless the first word is “SVG”.',
index ee0e3f7..390617d 100644 (file)
@@ -10,6 +10,7 @@
  * @author Aushulz
  * @author Gmelfi
  * @author Kaganer
+ * @author Markos90
  * @author Melos
  * @author Omnipaedista
  * @author Santu
@@ -2322,8 +2323,8 @@ Visita [//www.mediawiki.org/wiki/Localisation MediaWiki Localisation] e [//trans
 'tooltip-ca-watch' => 'Agghiunci sta pàggina â tò lista di ossirvati spiciali',
 'tooltip-ca-unwatch' => 'Elìmina sta pàggina dâ tò lista di ossirvati spiciali',
 'tooltip-search' => "Cerca 'n {{SITENAME}}",
-'tooltip-search-go' => 'Vai a na pàggina cu chistu nomu esattu si asisti',
-'tooltip-search-fulltext' => 'Attrova pàggini pi chistu testu',
+'tooltip-search-go' => 'Vai a na pàggina cu chistu nomu esattu siddu asisti',
+'tooltip-search-fulltext' => 'Arriscedi pàggini pi chistu testu',
 'tooltip-p-logo' => 'Pàggina principali',
 'tooltip-n-mainpage' => 'Vìsita la pàggina principali',
 'tooltip-n-mainpage-description' => 'Talìa la pàggina principali',
index 7b5ebc4..17ce510 100644 (file)
@@ -329,7 +329,7 @@ $messages = array(
 'cancel' => 'අත් හරින්න',
 'moredotdotdot' => 'තවත්...',
 'mypage' => 'මගේ පිටුව',
-'mytalk' => 'à·\83à·\8fà¶\9aචà·\8aඡà·\8fà·\80',
+'mytalk' => 'à\9aතà·\8fබà·\84',
 'anontalk' => 'මෙම අයිපී ලිපිනය සඳහා සාකච්ඡාව',
 'navigation' => 'යාත්‍රණය',
 'and' => '&#32;සහ',
@@ -1242,7 +1242,7 @@ $1",
 
 # Preferences page
 'preferences' => 'අභිරුචි',
-'mypreferences' => 'à¶\85භà·\92රà·\94චà·\92',
+'mypreferences' => 'රà·\92à·\83à·\92 à·\83à·\90à¶\9aà·\83à·\94මà·\8a',
 'prefs-edits' => 'සංස්කරණයන් සංඛ්‍යාව:',
 'prefsnologin' => 'පිවිසී නැත (Not logged in)',
 'prefsnologintext' => 'පරිශීලක අභිරුචි සැකසීමට නම්, ඔබ  <span class="plainlinks">[{{fullurl:Special:Userlogin|returnto=$1}} ප්‍රවිෂ්ටවී]</span> සිටිය යුතුය.',
@@ -2429,7 +2429,7 @@ $1',
 # Contributions
 'contributions' => 'මෙම පරිශීලකගේ දායකත්වයන්',
 'contributions-title' => ' $1 සඳහා පරිශීලක දායකත්වයන්',
-'mycontris' => 'දායකත්වයන්',
+'mycontris' => 'දායකත්ව',
 'contribsub2' => '$1 සඳහා ($2)',
 'nocontribs' => 'මෙම උපමානයන් හා ගැලපෙන වෙනස්වීම් හමුනොවිණි.',
 'uctop' => '(ඉහලම)',
@@ -2972,7 +2972,7 @@ $1 ගේ වාරණයට හේතුව මෙය වේ: "$2"',
 'pageinfo-lastuser' => 'අවසන් සංස්කාරක',
 'pageinfo-lasttime' => 'අවසන් සංස්කරණය වූ දිනය',
 'pageinfo-edits' => 'මුළු සංස්කරණ සංඛ්‍යාව',
-'pageinfo-authors' => 'ප්‍රභින්න කර්තෘවරුන් මුළු  සංඛ්‍යාව',
+'pageinfo-authors' => 'ප්‍රභින්න කර්තෘවරු ගණන',
 'pageinfo-recent-edits' => 'මෑත සංස්කරණ සංඛ්‍යාව (අවසන් $1 තුලදී)',
 'pageinfo-recent-authors' => 'මෑත ප්‍රභින්න කර්තෘවරුන් සංඛ්‍යාව',
 'pageinfo-magic-words' => 'මැජික් {{PLURAL:$1|වචනය|වචන}} ($1)',
index 168989c..10e5f64 100644 (file)
@@ -325,7 +325,7 @@ $messages = array(
 'tog-ccmeonemails' => 'Posielať mi kópie mojich emailov, ktoré pošlem ostatným používateľom',
 'tog-diffonly' => 'Nezobrazovať obsah stránky pod rozdielmi',
 'tog-showhiddencats' => 'Zobraziť skryté kategórie',
-'tog-noconvertlink' => 'Vypnúť konverziu názvov',
+'tog-noconvertlink' => 'Vypnúť konverziu názvov odkazov',
 'tog-norollbackdiff' => 'Vynechať rozdiel po vykonaní rollbacku',
 
 'underline-always' => 'Vždy',
@@ -532,7 +532,7 @@ $1',
 'privacy' => 'Ochrana osobných údajov',
 'privacypage' => 'Project:Ochrana osobných údajov',
 
-'badaccess' => 'Chyba povolenia',
+'badaccess' => 'Chyba oprávnenia',
 'badaccess-group0' => 'Nemáte povolenie na vykonanie požadovanej operácie.',
 'badaccess-groups' => 'Činnosť, ktorú požadujete, môže vykonať iba člen {{PLURAL:$2|skupiny|jednej zo skupín}}: $1.',
 
@@ -546,7 +546,7 @@ $1',
 'newmessagesdifflink' => 'posledná zmena',
 'youhavenewmessagesfromusers' => 'Máte $1 od {{PLURAL:$3|iného používateľa|$3 iných používateľov}} ($2).',
 'youhavenewmessagesmanyusers' => 'Máte $1 od viacerých ďalších používateľov ($2).',
-'newmessageslinkplural' => '{{PLURAL:$1|novú správu|nové správy|nových správ}}',
+'newmessageslinkplural' => '{{PLURAL:$1|novú správu|nové správy}}',
 'newmessagesdifflinkplural' => '{{PLURAL:$1|posledná zmena|posledné zmeny}}',
 'youhavenewmessagesmulti' => 'Máte nové správy na $1',
 'editsection' => 'upraviť',
@@ -640,7 +640,7 @@ Oznámte to prosím [[Special:ListUsers/sysop|správcovi]] a uveďte URL.',
 'badarticleerror' => 'Na tejto stránke túto činnosť nemožno vykonať.',
 'cannotdelete' => 'Nebolo možné zmazať stránku alebo súbor „$1“.
 Možno ju už zmazal nieto iný.',
-'cannotdelete-title' => 'Nemôžete zmazať stránku "$1"',
+'cannotdelete-title' => 'Nemôžete zmazať stránku „$1“',
 'delete-hook-aborted' => 'Zmazanie zrušila prídavná funkcia (prípojný bod syntaktického analyzátora).
 Neudala vysvetlenie.',
 'badtitle' => 'Neplatný nadpis',
@@ -669,7 +669,7 @@ $2',
 'namespaceprotected' => "Nemáte povolenie upravovať stránky v mennom priestore '''$1'''.",
 'customcssprotected' => 'Nemáte právo upravovať túto CSS stránku, pretože obsahuje osobné nastavenie iného používateľa.',
 'customjsprotected' => 'Nemáte právo upravovať túto JavaScript stránku, pretože obsahuje osobné nastavenie iného používateľa.',
-'ns-specialprotected' => 'Stránky v mennom pristore {{ns:special}} nie je možné upravovať.',
+'ns-specialprotected' => 'Stránky v mennom priestore {{ns:special}} nie je možné upravovať.',
 'titleprotected' => "Používateľ [[User:$1|$1]] zabránil vytváraniu stránky s týmto názvom.
 Udaný dôvod: ''$2''.",
 'filereadonlyerror' => 'Nebolo možné modifikovať súbor „$1“, pretože úložisko „$2“ je momentálne v režime len na čítanie.
@@ -703,9 +703,9 @@ Nezabudnite si nastaviť svoje [[Special:Preferences|používateľské nastaveni
 'password-change-forbidden' => 'Na tejto wiki si nemôžete zmeniť heslo.',
 'externaldberror' => 'Buď nastala chyba externej autentifikačnej databázy alebo vám nie je povolené aktualizovať váš externý účet.',
 'login' => 'Prihlásiť',
-'nav-login-createaccount' => 'Vytvorenie konta / prihlásenie',
+'nav-login-createaccount' => 'Prihlásenie / vytvorenie účtu',
 'loginprompt' => 'Na prihlásenie do {{GRAMMAR:genitív|{{SITENAME}}}} musíte mať zapnuté koláčiky (cookies).',
-'userlogin' => 'Vytvorenie konta / prihlásenie',
+'userlogin' => 'Prihlásenie / vytvorenie účtu',
 'userloginnocreate' => 'Prihlásiť',
 'logout' => 'Odhlásiť',
 'userlogout' => 'Odhlásiť',
@@ -720,7 +720,7 @@ Nezabudnite si nastaviť svoje [[Special:Preferences|používateľské nastaveni
 'createaccountreason' => 'Dôvod:',
 'badretype' => 'Zadané heslá nie sú rovnaké.',
 'userexists' => 'Zadané používateľské meno sa už používa.
-Zvoľte si prosím iné meno.',
+Prosím, zvoľte si iné meno.',
 'loginerror' => 'Chyba pri prihlasovaní',
 'createaccounterror' => 'Nepodarilo sa vytvoriť účet: $1',
 'nocookiesnew' => 'Používateľské konto bolo vytvorené, ale nie ste prihlásený. {{SITENAME}} používa cookies na prihlásenie. Máte cookies vypnuté. Zapnite ich a potom sa prihláste pomocou vášho nového používateľského mena a hesla.',
@@ -736,8 +736,8 @@ Skontrolujte preklepy alebo sa [[Special:UserLogin/signup|zaregistrujte ako nov
 'nosuchusershort' => 'V súčasnosti neexistuje používateľ s menom „$1“. Skontrolujte preklepy.',
 'nouserspecified' => 'Musíte uviesť meno používateľa.',
 'login-userblocked' => 'Tento používateľ je zablokovaný. Nie je mu dovolené prihlásiť sa.',
-'wrongpassword' => 'Zadané heslo je nesprávne. Skúste  znovu.',
-'wrongpasswordempty' => 'Zadané heslo bolo prázdne. Skúste prosím znova.',
+'wrongpassword' => 'Zadané heslo je nesprávne. Prosím, skúste to znova.',
+'wrongpasswordempty' => 'Zadané heslo bolo prázdne. Prosím, skúste to znova.',
 'passwordtooshort' => 'Heslo musí mať dĺžku aspoň $1 {{PLURAL:$1|znak|znaky|znakov}}.',
 'password-name-match' => 'Vaše heslo musí byť iné ako vaše používateľské meno.',
 'password-login-forbidden' => 'Použitie tohto používateľského mena a hesla bolo zakázané.',
@@ -767,9 +767,9 @@ Z tohto dôvodu nemôžu návštevníci z tejto IP adresy momentálne vytvoriť
 'emailauthenticated' => 'Vaša emailová adresa bola overená $2 $3.',
 'emailnotauthenticated' => 'Vaša e-mailová adresa ešte nebola overená. Preto nemôžete prijať emaily pre žiadnu z nasledovných funkcií.',
 'noemailprefs' => 'Tieto nástroje budú prístupné po vyplnení emailovej adresy vo vašich nastaveniach.',
-'emailconfirmlink' => 'Potvrďte vašu e-mailovú adresu',
+'emailconfirmlink' => 'Potvrďte svoju e-mailovú adresu',
 'invalidemailaddress' => 'Emailovú adresu nemožno akceptovať, pretože sa zdá, že má neplatný formát. Zadajte adresu v správnom tvare alebo nechajte príslušné políčko prázdne.',
-'cannotchangeemail' => 'Na tejto wiki nie je možné meniť e-mailové adresy používateľského konta.',
+'cannotchangeemail' => 'Na tejto wiki nie je možné meniť e-mailové adresy používateľského účtu.',
 'emaildisabled' => 'Táto lokalita nedokáže posielať emaily.',
 'accountcreated' => 'Účet vytvorený',
 'accountcreatedtext' => 'Používateľský účet $1 bol vytvorený.',
@@ -846,7 +846,7 @@ Dočasné heslo:$2',
 'passwordreset-emailerror-capture' => 'Bol vytvorený pripomienkový e-mail, ktorý je zobrazený nižšie, ale nepodarilo sa ho odoslať používateľovi: $1',
 
 # Special:ChangeEmail
-'changeemail' => 'Zmena e-mailovej adresy',
+'changeemail' => 'Zmeniť emailovú adresu',
 'changeemail-header' => 'Zmena e-mailovej adresy pre účet',
 'changeemail-text' => 'Vyplňte tento formulár na zmenu e-mailovej adresy. Zmenu budete musieť potvrdiť zadaním svojho hesla.',
 'changeemail-no-info' => 'Na prístup k tejto stránke musíte byť prihlásený.',
@@ -1974,7 +1974,7 @@ Možno chcete upraviť popis na jeho [$2 popisnej stránke súboru] tam.',
 'uploadnewversion-linktext' => 'Nahrať novú verziu tohto súboru',
 'shared-repo-from' => 'z $1',
 'shared-repo' => 'zdieľané úložisko',
-'upload-disallowed-here' => 'Tento súbor nie je možné prepísať.',
+'upload-disallowed-here' => 'Tento súbor nemôžete prepísať.',
 
 # File reversion
 'filerevert' => 'Obnoviť $1',
@@ -3090,6 +3090,7 @@ Pravdepodobne to spôsobil odkaz na externú internetovú lokalitu, ktorá sa na
 
 # Info page
 'pageinfo-title' => 'Informácie o „$1“',
+'pageinfo-not-current' => 'Ospravedlňujeme sa, túto informáciu nie je možné poskytnúť pre staré revízie.',
 'pageinfo-header-basic' => 'Základné údaje',
 'pageinfo-header-edits' => 'História úprav',
 'pageinfo-header-restrictions' => 'Ochrana stránky',
@@ -3098,6 +3099,7 @@ Pravdepodobne to spôsobil odkaz na externú internetovú lokalitu, ktorá sa na
 'pageinfo-default-sort' => 'Predvolený kľúč zoraďovania:',
 'pageinfo-length' => 'Dĺžka stránky (v bajtoch)',
 'pageinfo-article-id' => 'ID stránky',
+'pageinfo-language' => 'Jazyk obsahu stránok',
 'pageinfo-robot-policy' => 'Stav vyhľadávača',
 'pageinfo-robot-index' => 'Indexovať stránku',
 'pageinfo-robot-noindex' => 'Neindexovať stránku',
@@ -3118,6 +3120,10 @@ Pravdepodobne to spôsobil odkaz na externú internetovú lokalitu, ktorá sa na
 'pageinfo-hidden-categories' => '{{PLURAL:$1|Skrytá kategória|Skryté kategórie}} ($1)',
 'pageinfo-templates' => '{{PLURAL:$1|Vložená šablóna|Vložené šablóny}} ($1)',
 'pageinfo-toolboxlink' => 'Informácie o stránke',
+'pageinfo-redirectsto' => 'Presmerovanie na',
+'pageinfo-redirectsto-info' => 'info',
+'pageinfo-contentpage' => 'Počíta sa ako obsah stránky',
+'pageinfo-contentpage-yes' => 'Áno',
 'pageinfo-protect-cascading' => 'Kaskádové zamknutie',
 'pageinfo-protect-cascading-yes' => 'Áno',
 'pageinfo-protect-cascading-from' => 'Zámky pochádzajú z kaskádových zamknutí',
@@ -3143,6 +3149,8 @@ Pravdepodobne to spôsobil odkaz na externú internetovú lokalitu, ktorá sa na
 'markedaspatrollederror' => 'Nie je možné označiť ako strážené',
 'markedaspatrollederrortext' => 'Pre označenie ako strážený je potrebné uviesť revíziu, ktorá sa má označiť ako strážená.',
 'markedaspatrollederror-noautopatrol' => 'Nie je vám umožnené označiť vlastné zmeny za strážené.',
+'markedaspatrollednotify' => 'Táto zmena stránky $1 bola označená ako strážená.',
+'markedaspatrollederrornotify' => 'Označenie ako strážená zlyhalo.',
 
 # Patrol log
 'patrol-log-page' => 'Záznam strážení',
index 362f233..ea49819 100644 (file)
@@ -7,6 +7,7 @@
  * @ingroup Language
  * @file
  *
+ * @author Aig mest ei varasta
  * @author Andrijko Z.
  * @author Kaganer
  * @author Sura
@@ -221,7 +222,7 @@ $messages = array(
 'cancel' => 'Heitta pätand',
 'moredotdotdot' => 'Edeleze...',
 'mypage' => "Minun lehtpol'",
-'mytalk' => 'Minun lodud',
+'mytalk' => 'Lodud',
 'anontalk' => 'Lodud neciš IP-adresas',
 'navigation' => 'Navigacii',
 'and' => '&#32;da',
@@ -987,7 +988,7 @@ Otkat sil'mnägubale üks-se, miše {{SITENAME}}-saitan sädäimišt voib olda v
 
 # Preferences page
 'preferences' => 'Järgendused',
-'mypreferences' => 'Minun järgendused',
+'mypreferences' => 'Järgendused',
 'prefs-edits' => 'Redaktiruindoiden lugu:',
 'prefsnologin' => 'Tö et olgoi kirjutanus sistemha.',
 'prefsnologintext' => 'Teile pidab <span class="plainlinks">[{{fullurl:{{#Special:UserLogin}}|returnto=$1}} kirjutadas sistemha]</span>, miše toižetada järgendusid.',
@@ -1385,7 +1386,7 @@ Ku problem jäb jäl'ghepäi-ki, säkat pagin [[Special:ListUsers/sysop|sistemad
 'backend-fail-writetemp' => 'Ei voi toižetada pordaigašt failad.',
 'backend-fail-closetemp' => 'Ei voi saubata pordaigašt failad.',
 'backend-fail-read' => 'Ei voi lugeda "$1"-failad.',
-'backend-fail-create' => 'Ei voi säta "$1"-failad.',
+'backend-fail-create' => 'Ei voi kirjutada "$1"-failad.',
 
 # ZipDirectoryReader
 'zip-wrong-format' => 'Valitud fail ei ole ZIP-fail.',
@@ -1739,7 +1740,7 @@ Kc. mugažo [[Special:WantedCategories|ectud kategorijoiden nimikirjutez]].',
 
 # Watchlist
 'watchlist' => 'Kaclendnimikirjutez',
-'mywatchlist' => 'Minun kaclendnimikirjutez',
+'mywatchlist' => 'Kaclendnimikirjutez',
 'watchlistfor2' => 'Kävutajale $1 $2',
 'nowatchlist' => "Teiden kaclendnimikirjutez om pall'az.",
 'watchlistanontext' => 'Olgat hüväd, $1, miše lugeda vai redaktiruida teiden kaclendnimikirjutez.',
@@ -2370,9 +2371,10 @@ Voib olda, necil lehtpolel om kosketuz irdsaitale, kudamb om mustas nimikirjutes
 'spambot_username' => 'MediaWikid puhtastadas spamaspäi',
 
 # Info page
-'pageinfo-header-edits' => 'Redakcijad',
+'pageinfo-header-edits' => 'Redakcijoiden istorii',
+'pageinfo-article-id' => 'Lehtpolen ID',
 'pageinfo-views' => 'Kacundoiden lugu',
-'pageinfo-watchers' => 'Kaclijoiden lugu',
+'pageinfo-watchers' => 'Lehtpolen kaclijoiden lugu',
 'pageinfo-edits' => 'Redakcijoiden lugumär',
 'pageinfo-authors' => 'Erazvuiččiden avtoroiden lugu',
 
@@ -2781,17 +2783,26 @@ Ku fail redaktiruidihe sändan polhe, erased parametrad voidas erineda nügüdl
 'exif-dc-publisher' => 'Pästai',
 'exif-dc-rights' => 'Oiktused',
 
+'exif-iimcategory-clj' => 'Ogerantegend da käskuz',
+'exif-iimcategory-dis' => 'Katastrofad da avarijad',
+'exif-iimcategory-fin' => 'Ekonomik da biznes',
 'exif-iimcategory-edu' => 'Openduzmär',
+'exif-iimcategory-evn' => 'Ümbrišt',
 'exif-iimcategory-hth' => 'Tervhuz',
+'exif-iimcategory-hum' => "Mel'hetartujad istorijad",
 'exif-iimcategory-lab' => 'Tö',
+'exif-iimcategory-lif' => 'Elonmahtuz da joudai aig',
 'exif-iimcategory-pol' => 'Politik',
 'exif-iimcategory-rel' => 'Religii da uskonduz',
 'exif-iimcategory-sci' => 'Tedo da tehnologii',
 'exif-iimcategory-soi' => 'Socialižed küzundad',
 'exif-iimcategory-spo' => 'Sport',
+'exif-iimcategory-war' => 'Voinad, konfliktad da kundanholdundad',
 'exif-iimcategory-wea' => 'Sä',
 
 'exif-urgency-normal' => 'Normaline ($1)',
+'exif-urgency-low' => 'Madal ($1)',
+'exif-urgency-high' => 'Korged ($1)',
 
 # External editor support
 'edit-externally' => 'Redaktiruida nece fail irdprogrammal',
@@ -2934,6 +2945,7 @@ Kävutagat normaline ezikacund.',
 'version-specialpages' => 'Specialižed lehtpoled',
 'version-parserhooks' => 'Sintaksižen analizatoran sabustajad',
 'version-variables' => 'Vajehtujad lugud',
+'version-antispam' => 'Antispam',
 'version-skins' => 'Nägutemad',
 'version-other' => 'Toine',
 'version-mediahandlers' => 'Median radimed',
index 89fda5b..e7512e5 100644 (file)
@@ -87,6 +87,7 @@ $messages = array(
 'category-article-count' => '{{PLURAL:$2|Senez gruppaz on ainult vahtiaava cülci.|{{PLURAL:$1|Vahtiaava alagruppa kuulub|Vahtiaava $1 cülciä kuuluvad}} sihee gruppaa. Cülcije cisla gruppaza on $2.}}',
 'category-file-count' => '{{PLURAL:$2|Senez gruppaz on ainult vahtiaava faili.|{{PLURAL:$1|Vahtiaava alagruppa kuulub|Vahtiaava $1 failid kuuluvad}} sihee gruppaa. Cülcije cisla gruppaza on $2.}}',
 'listingcontinuesabbrev' => 'ladvaub',
+'noindex-category' => 'Ebäindekseeritettäväd lehocülled',
 
 'about' => 'Täätühsed',
 'newwindow' => '(avaub uuvvõza akkunaza)',
@@ -221,9 +222,11 @@ Kui cüsümüssessä ebõõ roocittu cülci, võib õlla õlõttõ löütännü
 # Login and logout pages
 'yourname' => 'Cäüttijänimi:',
 'yourpassword' => 'Salasõna',
+'yourpasswordagain' => 'Tõissaga salain-sõna:',
 'remembermypassword' => 'Mäleht minuu (enintään $1 {{PLURAL:$1|päivä|päivää}})',
 'login' => 'Cirjut süäme',
 'nav-login-createaccount' => 'Cirjut süäme vai registriiroit cäüttijässi',
+'loginprompt' => 'Tüü piättä «cookies» võttamin luvata, štobõ entä sisteema ete esitellä.',
 'userlogin' => 'Cirjut süäme',
 'userloginnocreate' => 'Cirjut süäme',
 'logout' => 'Cirjut uloz',
@@ -231,7 +234,9 @@ Kui cüsümüssessä ebõõ roocittu cülci, võib õlla õlõttõ löütännü
 'nologin' => "Kui Teille veel ebõõ cäüttijänimi, '''$1'''.",
 'nologinlink' => 'võitta loovva luguu',
 'createaccount' => 'Uusi cäüttijää',
+'gotaccount' => 'Tüü õõttõ jo registreerittu? $1.',
 'gotaccountlink' => 'Cirjut süäme',
+'userlogin-resetlink' => 'Vai unõhtittõ õma loginass?',
 'createaccountreason' => 'Süü:',
 'mailmypassword' => 'Lähet uusi salasõna elektropoštiikaa',
 'loginlanguagelabel' => 'Ceeli: $1',
@@ -294,12 +299,16 @@ Tüü võittõ [[Special:Search/{{PAGENAME}}|kaze nime nimettamizõ löütä]] m
 'template-semiprotected' => '(varjõttu anonüümeilt ja uusilt cäüttijilt)',
 'hiddencategories' => 'Kase cülci kuulub {{PLURAL:$1|vahtiaavaa salautõttuu gruppaa|vahtiaavii salautõttuisõõ gruppoisõõ}}:',
 'permissionserrorstext-withaction' => 'Teill ebõõ luppa $2 {{PLURAL:$1|vahtiaavass süüss|vahtiaaviss süiss}} peräss:',
+'recreate-moveddeleted-warn' => "'''Tähele-pano. Tüü loottõ taaz lehocülce, kumpa õli eespäi poisõttu.'''
+
+Tarkassaga, vai tarviz teile sitä tehä. Alapallõ õlla kaze lehocülle poissamizije ja nimije muuttamizije žurnaalad esitettü.",
 'moveddeleted-notice' => "Kase cülci on pühittü. Alla on sene cüľľee pühi'istori.",
 
 # Parser/template warnings
 'post-expand-template-inclusion-warning' => "'''Etetäätämin:''' lizettävije šabloonije summaarin koko on liiga suuri.
 Mõnõd šabloonad eväd lee lizettü.",
 'post-expand-template-inclusion-category' => 'Lehocülled, jõgõit vart lizettävije šabloonije sallittu koko on ületettü',
+'post-expand-template-argument-warning' => "'''Tähele-pano''': kase lehocülci sisältäb vähepält ühs šabloona, kumma argumental on liiga suuri avvamizõ koko. Mokomad argumentad eväd õltu näütettü",
 'post-expand-template-argument-category' => 'Lehocülled, jõgad sisälletä väl’l’ä-jätettü šabloonije argumentad.',
 
 # History pages
@@ -307,6 +316,7 @@ Mõnõd šabloonad eväd lee lizettü.",
 'currentrev' => 'Nücüin verzija',
 'currentrev-asof' => 'Nücüin verzija $1',
 'revisionasof' => 'Verzija $1',
+'revision-info' => '41. Verssija $1-ss; $2',
 'previousrevision' => '← Vanõpi verzija',
 'nextrevision' => 'Uuvvõpi verzija →',
 'currentrevisionlink' => 'Nücüin verzija',
@@ -345,6 +355,7 @@ Mõnõd šabloonad eväd lee lizettü.",
 'lineno' => 'Viiru $1:',
 'compareselectedversions' => 'Võrrõõ valitsõttuit verzijoit',
 'editundo' => 'kummut',
+'diff-multi' => 'Eb õõ näütettü {{PLURAL:$1|õsa-võttaja|õsa-võttajije}} {{PLURAL:$2|$2 väli-verssija $1|väli-verssijad $1}}',
 
 # Search results
 'searchresults' => 'Etsüü tulõmuhsõd',
@@ -373,6 +384,7 @@ Mõnõd šabloonad eväd lee lizettü.",
 'searchprofile-everything-tooltip' => 'Õttsigo kõikill lehocüllill (ceskussõõmizõ lehocülled siällhulgaz)',
 'searchprofile-advanced-tooltip' => 'Annõttu nimije tiloiz õttsia',
 'search-result-size' => '$1 ({{PLURAL:$2|1 sõna|$2 sõna}})',
+'search-result-category-size' => '$1 {{PLURAL:$1|jäse|$1 jäsentä}} ({{PLURAL:$2|1 all-kategoorija|$2 all-kategoorijad}}, {{PLURAL:$3|1 faili|$3 faila}})',
 'search-redirect' => '(mešaituz $1)',
 'search-section' => '(alajako $1)',
 'search-suggest' => 'Tähetidko: $1',
@@ -416,6 +428,8 @@ Proovvi lizät etsün alkuu ''all:'', nii ettsü etsib kõikkõõ sisältoo (taa
 'gender-male' => 'Mehin',
 'gender-female' => 'Naisin',
 'email' => 'E-mail',
+'prefs-help-email' => 'E-mail eb õõ pakollin, ain se leeb vajallin, kui tüü unõhtattõ salain-sõnass.',
+'prefs-help-email-others' => 'Se lupabci muilõ õsa-võttajilõ võtta ühteüttä tejjeka tejje personaaliss lehocülless viittau kautta, ilma tejje e-mail’a tääotusõ vajaussa.',
 
 # User rights
 'userrights-reason' => 'Süü:',
@@ -447,11 +461,13 @@ Proovvi lizät etsün alkuu ''all:'', nii ettsü etsib kõikkõõ sisältoo (taa
 'recentchanges-label-bot' => 'Kase kõrjauz on robotaka lootu',
 'recentchanges-label-unpatrolled' => 'Kasta kõrjaussa eb tarkisõtti veel',
 'rcnote' => 'Alla on {{PLURAL:$1|ühsi muutuz|viimeiziit $1 muutussiit}} viimeize {{PLURAL:$2|ühee päivää|$2 päivää}}, $4 $5.',
+'rcnotefrom' => 'Alapallõ õlla lugõtõltu muuttamizõd $2-lt ($1-lõssaa)',
 'rclistfrom' => 'Näüt uuvvõd muutuhsõd $1 alguss',
 'rcshowhideminor' => '$1 peened muutussõd',
 'rcshowhidebots' => '$1 botid',
 'rcshowhideliu' => '$1 süäme cirjutõnnud cäüttijäd',
 'rcshowhideanons' => '$1 anonüümid cäüttijäd',
+'rcshowhidepatr' => 'Tarkasõttu kõrjausije $1',
 'rcshowhidemine' => '$1 õmad muutussõd',
 'rclinks' => 'Näüt viimõiss $1 muutuhsõiss viimõizõ $2 päivää ajalt.<br />$3',
 'diff' => 'vahõ',
@@ -541,6 +557,7 @@ Seness [$2 kuvauhsõ lehocülless] informaattsija on alapallõ annõttu.',
 'nbytes' => '$1 {{PLURAL:$1|baitti|baittia}}',
 'nmembers' => '$1 {{PLURAL:$1|selttsilain|selttsilaizõd}}',
 'prefixindex' => 'Kõik cüľľed prefiksiikaa',
+'usercreated' => '33. $3 on entä cirjannu $1 $2-na',
 'newpages' => 'Uuvvõd cüľľed',
 'newpages-username' => 'Cäüttijänimi:',
 'move' => 'Liikut',
@@ -683,10 +700,12 @@ Cüľľellä $2 on spiiska viimeiziss pühcimühsiiss.',
 
 'sp-contributions-newbies' => 'Näüt uusijõõ cäüttijee muutuhsõd',
 'sp-contributions-blocklog' => 'piättelemized',
+'sp-contributions-uploads' => 'lassausõd',
 'sp-contributions-logs' => 'logid',
 'sp-contributions-talk' => 'Juttu',
 'sp-contributions-search' => 'Etsi avittamisiit',
 'sp-contributions-username' => 'IP-adressi vai cäüttijänimi',
+'sp-contributions-toponly' => 'Viimeized verssijad näüttä',
 'sp-contributions-submit' => 'Etsi',
 
 # What links here
@@ -694,6 +713,7 @@ Cüľľellä $2 on spiiska viimeiziss pühcimühsiiss.',
 'whatlinkshere-title' => 'Cüľľed, kummad näütellä cüľľelle "$1"',
 'whatlinkshere-page' => 'Cülci:',
 'linkshere' => "Vahtiaavilt cülciilt on linkki cüľľelle '''[[:$1]]''':",
+'nolinkshere' => "Mitäid eb viitata '''[[:$1]]-sõ'''",
 'isredirect' => 'mešaituzcülci',
 'istemplate' => 'sisällütüz šabloonii',
 'isimage' => 'kuvalinkki',
@@ -760,6 +780,7 @@ Neill kõhtoill piättä liikuttaa vai ühissää cüľľee cäzi.",
 
 # Namespace 8 related
 'allmessagesname' => 'Nimi',
+'allmessagesdefault' => 'Standartin teksta',
 'allmessages-language' => 'Ceeli:',
 'allmessages-filter-submit' => 'Mee',
 
@@ -926,6 +947,16 @@ Kui faili on muutõttu, siiz detaaľid võivad õlla kahõllaizõd muutõtull fa
 # Special:SpecialPages
 'specialpages' => 'Osoobenoid cüľľed',
 
+# External image whitelist
+'external_image_whitelist' => '# Jättägä kase rivi mokomassi, minenä-mokomana se on õõmaz.<pre>
+# Sijottaga tänne säännollizije ilmaud’d’e fragmentad (se õsa, kumpa on // väliz)
+# ned leevät võrrõttu ulko-kuvije URL-sõ.
+# Sopivad leeväd näütettü kuvijna, muud leeväd näütettü kuvijsõ viitauina.
+# Rivid, kummad alguta //-ss, pietä kommentaarijina. Rivid eväd õlla tunnuttu registra suhtõsõ.
+# Sijottaga säännollizije ilmaud’d’e fragmentad kaze rivi ülez.
+
+# Jättägä kase rivi mokomassi, minenä-mokomana se on õõmaz.',
+
 # Special:Tags
 'tag-filter' => "[[Special:Tags|Deskriptorije]] fil'tra:",
 'tags-edit' => 'muuttaa',
index 2fd6b2e..dc621ba 100644 (file)
@@ -2177,7 +2177,7 @@ $1',
 'listusersfrom' => '给定显示用户条件:',
 'listusers-submit' => '显示',
 'listusers-noresult' => '找不到用户。',
-'listusers-blocked' => '(已封é\94\81ï¼\89',
+'listusers-blocked' => '(已封ç¦\81ï¼\89',
 
 # Special:ActiveUsers
 'activeusers' => '活跃用户列表',
@@ -2492,7 +2492,7 @@ $1',
 # Contributions
 'contributions' => '用户贡献',
 'contributions-title' => '$1的用户贡献',
-'mycontris' => '贡献记录',
+'mycontris' => '贡献',
 'contribsub2' => '$1的贡献($2)',
 'nocontribs' => '没有找到符合特征的更改。',
 'uctop' => '(最后更改)',
@@ -3022,7 +3022,7 @@ $1被封禁的理由是:“$2”',
 'pageinfo-header-restrictions' => '页面保护',
 'pageinfo-header-properties' => '页面属性',
 'pageinfo-display-title' => '显示的标题',
-'pageinfo-default-sort' => '默认排序',
+'pageinfo-default-sort' => '默认排序',
 'pageinfo-length' => '页面长度(字节)',
 'pageinfo-article-id' => '页面ID',
 'pageinfo-language' => '页面内容语言',
index 645bcd5..248b0f0 100644 (file)
@@ -2092,7 +2092,7 @@ Template:消除歧義',
 'listusersfrom' => '給定顯示用戶條件:',
 'listusers-submit' => '顯示',
 'listusers-noresult' => '找不到用戶。',
-'listusers-blocked' => '(已封)',
+'listusers-blocked' => '(已封)',
 
 # Special:ActiveUsers
 'activeusers' => '活躍用戶列表',
index be2b8c3..56627f7 100644 (file)
@@ -7,7 +7,25 @@
  * @author Niklas Laxstrom, Tim Starling
  *
  * @copyright Copyright © 2010-2012, Niklas Laxström
- * @license http://www.gnu.org/copyleft/gpl.html GNU General Public License 2.0 or later
+ * @license http://www.gnu.org/copyleft/gpl.html GNU General Public License 2.0
+ * or later
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ *
+ *
  * @file
  * @since 1.20
  */
index c4f8a5c..493d350 100644 (file)
@@ -1401,6 +1401,7 @@ $wgMessageStructure = array(
                'backend-fail-notsame',
                'backend-fail-invalidpath',
                'backend-fail-delete',
+               'backend-fail-describe',
                'backend-fail-alreadyexists',
                'backend-fail-store',
                'backend-fail-copy',
diff --git a/maintenance/sqlite/archives/patch-profiling.sql b/maintenance/sqlite/archives/patch-profiling.sql
new file mode 100644 (file)
index 0000000..4a07283
--- /dev/null
@@ -0,0 +1,12 @@
+-- profiling table
+-- This is optional
+
+CREATE TABLE /*_*/profiling (
+  pf_count int NOT NULL default 0,
+  pf_time float NOT NULL default 0,
+  pf_memory float NOT NULL default 0,
+  pf_name varchar(255) NOT NULL default '',
+  pf_server varchar(30) NOT NULL default ''
+);
+
+CREATE UNIQUE INDEX /*i*/pf_name_server ON /*_*/profiling (pf_name, pf_server);
index 068c58b..4787594 100644 (file)
@@ -95,8 +95,7 @@ header( 'Content-Type: text/html; charset=utf-8' );
 
        .table th,
        .table td {
-               padding: 8px;
-               line-height: 20px;
+               padding: 0.1em;
                text-align: left;
                vertical-align: top;
                border-top: 1px solid #ddd;
@@ -156,9 +155,9 @@ $dbr = wfGetDB( DB_SLAVE );
 
 if( !$dbr->tableExists( 'profiling' ) ) {
        echo '<p>No <code>profiling</code> table exists, so we can\'t show you anything.</p>'
-               . '<p>If you want to log profiling data, create the table using '
-               . '<code>maintenance/archives/patch-profiling.sql</code> and enable '
-               . '<code>$wgProfileToDatabase</code>.</p>'
+               . '<p>If you want to log profiling data, enable <code>$wgProfileToDatabase</code>'
+               . ' in your LocalSettings.php and run <code>maintenance/update.php</code> to'
+               . ' create the profiling table.'
                . '</body></html>';
        exit( 1 );
 }
@@ -193,10 +192,12 @@ class profile_point {
 
                $ex = isset( $expand[$this->name()] );
 
+               $anchor = str_replace( '"', '', $this->name() );
+
                if ( !$ex ) {
                        if ( count( $this->children ) ) {
                                $url = getEscapedProfileUrl( false, false, $expand + array( $this->name() => true ) );
-                               $extet = ' <a href="' . $url . '">[+]</a>';
+                               $extet = " <a id=\"{$anchor}\" href=\"{$url}#{$anchor}\">[+]</a>";
                        } else {
                                $extet = '';
                        }
@@ -207,8 +208,8 @@ class profile_point {
                                        $e += array( $name => $ep );
                                }
                        }
-
-                       $extet = ' <a href="' . getEscapedProfileUrl( false, false, $e ) . '">[–]</a>';
+                       $url = getEscapedProfileUrl( false, false, $e );
+                       $extet = " <a id=\"{$anchor}\" href=\"{$url}#{$anchor}\">[–]</a>";
                }
                ?>
                <tr>
index 71bfcab..7a1bd27 100644 (file)
@@ -67,6 +67,7 @@
  */
 
 ( function ( $, mw ) {
+       /*jshint onevar:false */
 
        /* Local scope */
 
                        }
 
                        if ( !this.sortDisabled ) {
-                               var $th = $( this ).addClass( table.config.cssHeader ).attr( 'title', msg[1] );
+                               $( this ).addClass( table.config.cssHeader ).attr( 'title', msg[1] );
                        }
 
                        // add cell to headerList
                $headers.removeClass( css[0] ).removeClass( css[1] ).attr( 'title', msg[1] );
 
                var h = [];
-               $headers.each( function ( offset ) {
+               $headers.each( function () {
                        if ( !this.sortDisabled ) {
                                h[this.column] = $( this );
                        }
                        ts.transformTable = {};
 
                        // Unpack the transform table
-                       var ascii = separatorTransformTable[0].split( "\t" ).concat( digitTransformTable[0].split( "\t" ) );
-                       var localised = separatorTransformTable[1].split( "\t" ).concat( digitTransformTable[1].split( "\t" ) );
+                       var ascii = separatorTransformTable[0].split( '\t' ).concat( digitTransformTable[0].split( '\t' ) );
+                       var localised = separatorTransformTable[1].split( '\t' ).concat( digitTransformTable[1].split( '\t' ) );
 
                        // Construct regex for number identification
                        for ( var i = 0; i < ascii.length; i++ ) {
 
                // We allow a trailing percent sign, which we just strip. This works fine
                // if percents and regular numbers aren't being mixed.
-               ts.numberRegex = new RegExp("^(" + "[-+\u2212]?[0-9][0-9,]*(\\.[0-9,]*)?(E[-+\u2212]?[0-9][0-9,]*)?" + // Fortran-style scientific
-               "|" + "[-+\u2212]?" + digitClass + "+[\\s\\xa0]*%?" + // Generic localised
-               ")$", "i");
+               ts.numberRegex = new RegExp('^(' + '[-+\u2212]?[0-9][0-9,]*(\\.[0-9,]*)?(E[-+\u2212]?[0-9][0-9,]*)?' + // Fortran-style scientific
+               '|' + '[-+\u2212]?' + digitClass + '+[\\s\\xa0]*%?' + // Generic localised
+               ')$', 'i');
        }
 
        function buildDateTable() {
                        construct: function ( $tables, settings ) {
                                return $tables.each( function ( i, table ) {
                                        // Declare and cache.
-                                       var $document, $headers, cache, config, sortOrder,
+                                       var $headers, cache, config,
                                                $table = $( table ),
-                                               shiftDown = 0,
                                                firstTime = true;
 
                                        // Quit if no tbody
                                                        return;
                                                }
                                        }
-                                       $table.addClass( "jquery-tablesorter" );
+                                       $table.addClass( 'jquery-tablesorter' );
 
                                        // FIXME config should probably not be stored in the plain table node
                                        // New config object.
 
                                                // try to auto detect column type, and store in tables config
                                                table.config.parsers = buildParserCache( table, $headers );
-                                       };
+                                       }
 
                                        // Apply event handling to headers
                                        // this is too big, perhaps break it out?
                                                var totalRows = ( $table[0].tBodies[0] && $table[0].tBodies[0].rows.length ) || 0;
                                                if ( !table.sortDisabled && totalRows > 0 ) {
 
-                                                       // Cache jQuery object
-                                                       var $cell = $( this );
-
                                                        // Get current column index
                                                        var i = this.column;
 
                        },
 
                        formatDigit: function ( s ) {
+                               var out, c, p, i;
                                if ( ts.transformTable !== false ) {
-                                       var out = '',
-                                               c;
-                                       for ( var p = 0; p < s.length; p++ ) {
+                                       out = '';
+                                       for ( p = 0; p < s.length; p++ ) {
                                                c = s.charAt(p);
                                                if ( c in ts.transformTable ) {
                                                        out += ts.transformTable[c];
                                        }
                                        s = out;
                                }
-                               var i = parseFloat( s.replace( /[, ]/g, '' ).replace( "\u2212", '-' ) );
-                               return ( isNaN(i)) ? 0 : i;
+                               i = parseFloat( s.replace( /[, ]/g, '' ).replace( '\u2212', '-' ) );
+                               return isNaN( i ) ? 0 : i;
                        },
 
                        formatFloat: function ( s ) {
                                var i = parseFloat(s);
-                               return ( isNaN(i)) ? 0 : i;
+                               return isNaN( i ) ? 0 : i;
                        },
 
                        formatInt: function ( s ) {
                                var i = parseInt( s, 10 );
-                               return ( isNaN(i)) ? 0 : i;
+                               return isNaN( i ) ? 0 : i;
                        },
 
                        clearTableBody: function ( table ) {
-                               if ( $.browser.msie ) {
-                                       var empty = function ( el ) {
-                                               while ( el.firstChild ) {
-                                                       el.removeChild( el.firstChild );
-                                               }
-                                       };
-                                       empty( table.tBodies[0] );
-                               } else {
-                                       table.tBodies[0].innerHTML = '';
-                               }
+                               $( table.tBodies[0] ).empty();
                        }
                };
 
        // Add default parsers
        ts.addParser( {
                id: 'text',
-               is: function ( s ) {
+               is: function () {
                        return true;
                },
                format: function ( s ) {
                is: function ( s ) {
                        return ( ts.dateRegex[0].test(s) || ts.dateRegex[1].test(s) || ts.dateRegex[2].test(s ));
                },
-               format: function ( s, table ) {
+               format: function ( s ) {
                        var match;
                        s = $.trim( s.toLowerCase() );
 
 
        ts.addParser( {
                id: 'number',
-               is: function ( s, table ) {
+               is: function ( s ) {
                        return $.tablesorter.numberRegex.test( $.trim( s ));
                },
                format: function ( s ) {
index c0c77aa..65eb5a6 100644 (file)
@@ -2,10 +2,10 @@
  * Bosnian (bosanski) language functions
  */
 
-mediaWiki.language.convertGrammar = function( word, form ) {
-       var grammarForms = mw.language.getData( 'bs', 'grammarForms' );
+mediaWiki.language.convertGrammar = function ( word, form ) {
+       var grammarForms = mediaWiki.language.getData( 'bs', 'grammarForms' );
        if ( grammarForms && grammarForms[form] ) {
-               return grammarForms[form][word] ;
+               return grammarForms[form][word];
        }
        switch ( form ) {
                case 'instrumental': // instrumental
index a42a8f7..b2c9c08 100644 (file)
@@ -2,10 +2,10 @@
  * Lower Sorbian (Dolnoserbski) language functions
  */
 
-mediaWiki.language.convertGrammar = function( word, form ) {
-       var grammarForms = mw.language.getData( 'dsb', 'grammarForms' );
+mediaWiki.language.convertGrammar = function ( word, form ) {
+       var grammarForms = mediaWiki.language.getData( 'dsb', 'grammarForms' );
        if ( grammarForms && grammarForms[form] ) {
-               return grammarForms[form][word] ;
+               return grammarForms[form][word];
        }
        switch ( form ) {
                case 'instrumental': // instrumental
index 374698d..61c6c10 100644 (file)
@@ -3,21 +3,24 @@
  *  @author Santhosh Thottingal
  */
 
-mediaWiki.language.convertGrammar = function( word, form ) {
-       var grammarForms = mw.language.getData( 'fi', 'grammarForms' );
+mediaWiki.language.convertGrammar = function ( word, form ) {
+       var grammarForms, aou, origWord;
+
+       grammarForms = mediaWiki.language.getData( 'fi', 'grammarForms' );
        if ( grammarForms && grammarForms[form] ) {
-               return grammarForms[form][word] ;
+               return grammarForms[form][word];
        }
 
        // vowel harmony flag
-       var aou = word.match( /[aou][^äöy]*$/i );
-       var origWord = word;
+       aou = word.match( /[aou][^äöy]*$/i );
+       origWord = word;
        if ( word.match( /wiki$/i ) ) {
                aou = false;
        }
        //append i after final consonant
-       if ( word.match( /[bcdfghjklmnpqrstvwxz]$/i ) )
+       if ( word.match( /[bcdfghjklmnpqrstvwxz]$/i ) ) {
                word += 'i';
+       }
 
        switch ( form ) {
                case 'genitive':
index a27b489..c13e832 100644 (file)
@@ -2,10 +2,11 @@
  * Irish (Gaeilge) language functions
  */
 
-mediaWiki.language.convertGrammar = function( word, form ) {
-       var grammarForms = mw.language.getData( 'ga', 'grammarForms' );
+mediaWiki.language.convertGrammar = function ( word, form ) {
+       /*jshint onecase:true */
+       var grammarForms = mediaWiki.language.getData( 'ga', 'grammarForms' );
        if ( grammarForms && grammarForms[form] ) {
-               return grammarForms[form][word] ;
+               return grammarForms[form][word];
        }
        switch ( form ) {
                case 'ainmlae':
index d35f77e..13d457b 100644 (file)
@@ -3,26 +3,26 @@
  */
 
 mediaWiki.language.convertGrammar = function( word, form ) {
-       var grammarForms = mw.language.getData( 'he', 'grammarForms' );
+       var grammarForms = mediaWiki.language.getData( 'he', 'grammarForms' );
        if ( grammarForms && grammarForms[form] ) {
-               return grammarForms[form][word] ;
+               return grammarForms[form][word];
        }
        switch ( form ) {
                case 'prefixed':
                case 'תחילית': // the same word in Hebrew
                        // Duplicate prefixed "Waw", but only if it's not already double
-                       if ( word.substr( 0, 1 ) === "ו" && word.substr( 0, 2 ) !== "וו" ) {
-                               word = "ו" + word;
+                       if ( word.substr( 0, 1 ) === 'ו' && word.substr( 0, 2 ) !== 'וו' ) {
+                               word = 'ו' + word;
                        }
 
                        // Remove the "He" if prefixed
-                       if ( word.substr( 0, 1 ) === "ה" ) {
+                       if ( word.substr( 0, 1 ) === 'ה' ) {
                                word = word.substr( 1, word.length );
                        }
 
                        // Add a hyphen (maqaf) before numbers and non-Hebrew letters
-                       if (  word.substr( 0, 1 ) < "א" ||  word.substr( 0, 1 ) > "ת" ) {
-                               word = "־" + word;
+                       if (  word.substr( 0, 1 ) < 'א' ||  word.substr( 0, 1 ) > 'ת' ) {
+                               word = '־' + word;
                        }
        }
        return word;
index 211d67b..77dca75 100644 (file)
@@ -2,10 +2,10 @@
  * Upper Sorbian (Hornjoserbsce) language functions
  */
 
-mediaWiki.language.convertGrammar = function( word, form ) {
-       var grammarForms =mw.language.getData( 'hsb', 'grammarForms' );
+mediaWiki.language.convertGrammar = function ( word, form ) {
+       var grammarForms = mediaWiki.language.getData( 'hsb', 'grammarForms' );
        if ( grammarForms && grammarForms[form] ) {
-               return grammarForms[form][word] ;
+               return grammarForms[form][word];
        }
        switch ( form ) {
                case 'instrumental': // instrumental
index eb3f1f3..23b0c12 100644 (file)
@@ -3,10 +3,10 @@
  *  @author Santhosh Thottingal
  */
 
-mediaWiki.language.convertGrammar = function( word, form ) {
-       var grammarForms = mw.language.getData( 'hu', 'grammarForms' );
+mediaWiki.language.convertGrammar = function ( word, form ) {
+       var grammarForms = mediaWiki.language.getData( 'hu', 'grammarForms' );
        if ( grammarForms && grammarForms[form] ) {
-               return grammarForms[form][word] ;
+               return grammarForms[form][word];
        }
        switch ( form ) {
                case 'rol':
index 215e750..65081bd 100644 (file)
@@ -2,10 +2,11 @@
  * Armenian (Հայերեն) language functions
  */
 
-mediaWiki.language.convertGrammar = function( word, form ) {
-       var grammarForms = mw.language.getData( 'hy', 'grammarForms' );
+mediaWiki.language.convertGrammar = function ( word, form ) {
+       /*jshint onecase:true */
+       var grammarForms = mediaWiki.language.getData( 'hy', 'grammarForms' );
        if ( grammarForms && grammarForms[form] ) {
-               return grammarForms[form][word] ;
+               return grammarForms[form][word];
        }
 
        // These rules are not perfect, but they are currently only used for site names so it doesn't
@@ -13,14 +14,15 @@ mediaWiki.language.convertGrammar = function( word, form ) {
 
        switch ( form ) {
                case 'genitive': // սեռական հոլով
-                       if ( word.substr( -1 ) === 'ա' )
+                       if ( word.substr( -1 ) === 'ա' ) {
                                word = word.substr( 0, word.length -1 )  + 'այի';
-                       else if ( word.substr( -1 ) === 'ո' )
+                       } else if ( word.substr( -1 ) === 'ո' ) {
                                word = word.substr( 0, word.length - 1 ) + 'ոյի';
-                       else if ( word.substr( -4 ) === 'գիրք' )
+                       } else if ( word.substr( -4 ) === 'գիրք' ) {
                                word = word.substr( 0, word.length - 4 ) + 'գրքի';
-                       else
+                       } else {
                                word = word + 'ի';
+                       }
                        break;
                }
        return word;
index 313bb1c..2711024 100644 (file)
@@ -3,10 +3,10 @@
  * @author Santhosh Thottingal
  */
 
-mediaWiki.language.convertGrammar = function( word, form ) {
-       var grammarForms = mw.language.getData( 'la', 'grammarForms' );
+mediaWiki.language.convertGrammar = function ( word, form ) {
+       var grammarForms = mediaWiki.language.getData( 'la', 'grammarForms' );
        if ( grammarForms && grammarForms[form] ) {
-               return grammarForms[form][word] ;
+               return grammarForms[form][word];
        }
        switch ( form ) {
                case 'genitive':
index 431e38c..682b390 100644 (file)
@@ -4,23 +4,24 @@
  */
 
 
-mediaWiki.language.convertGrammar = function( word, form ) {
-       var grammarForms = mw.language.getData( 'os', 'grammarForms' );
+mediaWiki.language.convertGrammar = function ( word, form ) {
+       var grammarForms = mediaWiki.language.getData( 'os', 'grammarForms' ),
+               // Ending for allative case
+               endAllative = 'мæ',
+               // Variable for 'j' beetwen vowels
+               jot = '',
+               // Variable for "-" for not Ossetic words
+               hyphen = '',
+               // Variable for ending
+               ending = '';
+
        if ( grammarForms && grammarForms[form] ) {
-               return grammarForms[form][word] ;
+               return grammarForms[form][word];
        }
-       // Ending for allative case
-       var end_allative = 'мæ';
-       // Variable for 'j' beetwen vowels
-       var jot = '';
-       // Variable for "-" for not Ossetic words
-       var hyphen = '';
-       // Variable for ending
-       var ending = '';
        // Checking if the $word is in plural form
        if ( word.match( /тæ$/i ) ) {
                word = word.substring( 0, word.length - 1 );
-               end_allative = 'æм';
+               endAllative = 'æм';
        }
        // Works if word is in singular form.
        // Checking if word ends on one of the vowels: е, ё, и, о, ы, э, ю, я.
@@ -45,10 +46,10 @@ mediaWiki.language.convertGrammar = function( word, form ) {
                        ending = hyphen + jot + 'æн';
                        break;
                case 'allative':
-                       ending = hyphen + end_allative;
+                       ending = hyphen + endAllative;
                        break;
                case 'ablative':
-                       if ( jot == 'й' ) {
+                       if ( jot === 'й' ) {
                                ending = hyphen + jot + 'æ';
                        }
                        else {
index cfdbfc3..b27dea4 100644 (file)
@@ -2,27 +2,28 @@
  * Russian (Русский) language functions
  */
 
-mediaWiki.language.convertGrammar = function( word, form ) {
-       var grammarForms = mw.language.getData( 'ru', 'grammarForms' );
+mediaWiki.language.convertGrammar = function ( word, form ) {
+       /*jshint noempty:false, onecase:true */
+       var grammarForms = mediaWiki.language.getData( 'ru', 'grammarForms' );
        if ( grammarForms && grammarForms[form] ) {
-               return grammarForms[form][word] ;
+               return grammarForms[form][word];
        }
        switch ( form ) {
                case 'genitive': // родительный падеж
-                       if ( (  word.substr( word.length - 4 )  == 'вики' ) || (  word.substr( word.length - 4 ) == 'Вики' ) ) {
-                       }
-                       else if ( word.substr( word.length - 1 ) == 'ь' )
+                       if ( (  word.substr( word.length - 4 ) === 'вики' ) || (  word.substr( word.length - 4 ) === 'Вики' ) ) {
+                       } else if ( word.substr( word.length - 1 ) === 'ь' ) {
                                word = word.substr(0, word.length - 1 ) + 'я';
-                       else if ( word.substr( word.length - 2 ) == 'ия' )
+                       } else if ( word.substr( word.length - 2 ) === 'ия' ) {
                                word = word.substr(0, word.length - 2 ) + 'ии';
-                       else if ( word.substr( word.length - 2 ) == 'ка' )
+                       } else if ( word.substr( word.length - 2 ) === 'ка' ) {
                                word = word.substr(0, word.length - 2 ) + 'ки';
-                       else if ( word.substr( word.length - 2 )  == 'ти' )
+                       } else if ( word.substr( word.length - 2 )  === 'ти' ) {
                                word = word.substr(0, word.length - 2 ) + 'тей';
-                       else if ( word.substr( word.length - 2 ) == 'ды' )
+                       } else if ( word.substr( word.length - 2 ) === 'ды' ) {
                                word = word.substr(0, word.length - 2 ) + 'дов';
-                       else if ( word.substr( word.length - 3 ) == 'ник' )
+                       } else if ( word.substr( word.length - 3 ) === 'ник' ) {
                                word = word.substr(0, word.length - 3 ) + 'ника';
+                       }
                        break;
        }
        return word;
index acd00bf..fb335b6 100644 (file)
@@ -2,10 +2,10 @@
  * Slovenian (Slovenščina) language functions
  */
 
-mediaWiki.language.convertGrammar = function( word, form ) {
-       var grammarForms = mw.language.getData( 'sl', 'grammarForms' );
+mediaWiki.language.convertGrammar = function ( word, form ) {
+       var grammarForms = mediaWiki.language.getData( 'sl', 'grammarForms' );
        if ( grammarForms && grammarForms[form] ) {
-               return grammarForms[form][word] ;
+               return grammarForms[form][word];
        }
        switch ( form ) {
                case 'mestnik': // locative
index ee110b0..5e56b66 100644 (file)
@@ -2,33 +2,35 @@
  * Ukrainian (Українська) language functions
  */
 
-mediaWiki.language.convertGrammar = function( word, form ) {
-       var grammarForms = mw.language.getData( 'uk', 'grammarForms' );
+mediaWiki.language.convertGrammar = function ( word, form ) {
+       /*jshint noempty:false */
+       var grammarForms = mediaWiki.language.getData( 'uk', 'grammarForms' );
        if ( grammarForms && grammarForms[form] ) {
-               return grammarForms[form][word] ;
+               return grammarForms[form][word];
        }
        switch ( form ) {
                case 'genitive': // родовий відмінок
-                       if ( ( word.substr( word.length - 4 ) == 'вікі' ) || ( word.substr( word.length - 4 ) == 'Вікі' ) ) {
-                       }
-                       else if ( word.substr( word.length - 1 ) == 'ь' )
+                       if ( ( word.substr( word.length - 4 ) === 'вікі' ) || ( word.substr( word.length - 4 ) === 'Вікі' ) ) {
+                       } else if ( word.substr( word.length - 1 ) === 'ь' ) {
                                word = word.substr(0, word.length - 1 ) + 'я';
-                       else if ( word.substr( word.length - 2 ) == 'ія' )
+                       } else if ( word.substr( word.length - 2 ) === 'ія' ) {
                                word = word.substr(0, word.length - 2 ) + 'ії';
-                       else if ( word.substr( word.length - 2 ) == 'ка' )
+                       } else if ( word.substr( word.length - 2 ) === 'ка' ) {
                                word = word.substr(0, word.length - 2 ) + 'ки';
-                       else if ( word.substr( word.length - 2 ) == 'ти' )
+                       } else if ( word.substr( word.length - 2 ) === 'ти' ) {
                                word = word.substr(0, word.length - 2 ) + 'тей';
-                       else if ( word.substr( word.length - 2 ) == 'ды' )
+                       } else if ( word.substr( word.length - 2 ) === 'ды' ) {
                                word = word.substr(0, word.length - 2 ) + 'дов';
-                       else if ( word.substr( word.length - 3 ) == 'ник' )
+                       } else if ( word.substr( word.length - 3 ) === 'ник' ) {
                                word = word.substr(0, word.length - 3 ) + 'ника';
+                       }
                        break;
                case 'accusative': // знахідний відмінок
-                       if ( ( word.substr( word.length - 4 ) == 'вікі' ) || ( word.substr( word.length - 4 ) == 'Вікі' ) ) {
+                       if ( ( word.substr( word.length - 4 ) === 'вікі' ) || ( word.substr( word.length - 4 ) === 'Вікі' ) ) {
                        }
-                       else if ( word.substr( word.length - 2 ) == 'ія' )
+                       else if ( word.substr( word.length - 2 ) === 'ія' ) {
                                word = word.substr(0, word.length - 2 ) + 'ію';
+                       }
                        break;
        }
        return word;
index de11639..49a0ad5 100644 (file)
@@ -2,6 +2,22 @@
 /**
  * Standard (a.k.a. Classic) skin: old MediaWiki default skin
  *
+ * 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 Skins
  */
index b9f1817..ea1b290 100644 (file)
@@ -692,7 +692,6 @@ class ParserTest {
                        'wgExternalLinkTarget' => false,
                        'wgAlwaysUseTidy' => false,
                        'wgHtml5' => true,
-                       'wgCleanupPresentationalAttributes' => true,
                        'wgWellFormedXml' => true,
                        'wgAllowMicrodataAttributes' => true,
                        'wgAdaptiveMessageCache' => true,
index ac3113e..f6091b4 100644 (file)
@@ -102,6 +102,12 @@ Template:table_attribs
 |</noinclude>style="color: red"| Foo
 !! endarticle
 
+!! article
+A?b
+!! text
+Weirdo titles!
+!! endarticle
+
 ###
 ### Basic tests
 ###
@@ -3149,6 +3155,18 @@ Plain link to protocol-relative URL with link text
 </p>
 !! end
 
+!! test
+Plain link to page with question mark in title
+!! input
+[[A?b]]
+
+[[A?b|Baz]]
+!! result
+<p><a href="/wiki/A%3Fb" title="A?b">A?b</a>
+</p><p><a href="/wiki/A%3Fb" title="A?b">Baz</a>
+</p>
+!! end
+
 
 # I'm fairly sure the expected result here is wrong.
 # We want these to be URL links, not pseudo-pages with URLs for titles....
@@ -4743,6 +4761,13 @@ Foo<noinclude>zar</noinclude><includeonly>bar</includeonly>
 </p>
 !! end
 
+!! test
+Un-closed <noinclude>
+!! input
+<noinclude>
+!! result
+!! end
+
 !! test
 <onlyinclude> on a page
 !! input
@@ -4752,6 +4777,13 @@ Foo<noinclude>zar</noinclude><includeonly>bar</includeonly>
 </p>
 !! end
 
+!! test
+Un-closed <onlyinclude>
+!! input
+<onlyinclude>
+!! result
+!! end
+
 !! article
 Template:Includeonly section
 !! text
@@ -4810,6 +4842,13 @@ section=1
 ==Section 1==
 !! end
 
+!! test
+Un-closed <includeonly>
+!! input
+<includeonly>
+!! result
+!! end
+
 ###
 ### <includeonly> and <noinclude> in attributes
 ###
@@ -7197,6 +7236,23 @@ DIV IN UPPERCASE
 
 !!end
 
+!! test
+Non-ASCII pseudo-tags are rendered as text
+!! input
+<khyô>
+!! result
+<p>&lt;khyô&gt;
+</p>
+!! end
+
+!! test
+Pseudo-tag with URL 'name' renders as url link
+!! input
+<http://example.com/>
+!! result
+<p>&lt;<a rel="nofollow" class="external free" href="http://example.com/">http://example.com/</a>&gt;
+</p>
+!! end
 
 !! test
 text with amp in the middle of nowhere
@@ -11497,22 +11553,6 @@ Bug 31098 Template which includes system messages which includes the template
 </p>
 !! end
 
-!! test
-Deprecated presentational attributes are converted to css
-!! input
-{|
-| valign=top align=left width=100 height=25% | Asdf
-|}
-<ul type="disc"></ul>
-!! result
-<table>
-<tr>
-<td style="text-align: left; height: 25%; vertical-align: top; width: 100px;"> Asdf
-</td></tr></table>
-<ul style="list-style-type: disc;"></ul>
-
-!! end
-
 !! test
 Bug31490 Turkish: ucfirst 'blah'
 !! options
index fca3251..473e641 100644 (file)
@@ -53,6 +53,22 @@ class MediaWikiPHPUnitCommand extends PHPUnit_TextUI_Command {
                }
        }
 
+       public function run( array $argv, $exit = true ) {
+               $ret = parent::run( $argv, false );
+
+               // Return to real wiki db, so profiling data is preserved
+               MediaWikiTestCase::teardownTestDB();
+
+               // Log profiling data, e.g. in the database or UDP
+               wfLogProfilingData();
+
+               if ( $exit ) {
+                       exit( $ret );
+               } else {
+                       return $ret;
+               }
+       }
+
        public function showHelp() {
                parent::showHelp();
 
index db41a4d..c619dab 100644 (file)
@@ -14,12 +14,12 @@ abstract class MediaWikiTestCase extends PHPUnit_Framework_TestCase {
         * @var DatabaseBase
         */
        protected $db;
-       protected $oldTablePrefix;
-       protected $useTemporaryTables = true;
-       protected $reuseDB = false;
        protected $tablesUsed = array(); // tables with data
 
+       private static $useTemporaryTables = true;
+       private static $reuseDB = false;
        private static $dbSetup = false;
+       private static $oldTablePrefix = false;
 
        /**
         * Holds the paths of temporary files/directories created through getNewTempFile,
@@ -65,20 +65,22 @@ abstract class MediaWikiTestCase extends PHPUnit_Framework_TestCase {
                ObjectCache::$instances[CACHE_DB] = new HashBagOStuff;
 
                if( $this->needsDB() ) {
-                       global $wgDBprefix;
-                       
-                       $this->useTemporaryTables = !$this->getCliArg( 'use-normal-tables' );
-                       $this->reuseDB = $this->getCliArg('reuse-db');
+                       // set up a DB connection for this test to use
+
+                       self::$useTemporaryTables = !$this->getCliArg( 'use-normal-tables' );
+                       self::$reuseDB = $this->getCliArg('reuse-db');
 
                        $this->db = wfGetDB( DB_MASTER );
 
                        $this->checkDbIsSupported();
 
-                       $this->oldTablePrefix = $wgDBprefix;
-
                        if( !self::$dbSetup ) {
-                               $this->initDB();
-                               self::$dbSetup = true;
+                               // switch to a temporary clone of the database
+                               self::setupTestDB( $this->db, $this->dbPrefix() );
+
+                               if ( ( $this->db->getType() == 'oracle' || !self::$useTemporaryTables ) && self::$reuseDB ) {
+                                       $this->resetDB();
+                               }
                        }
 
                        $this->addCoreDBData();
@@ -349,26 +351,67 @@ abstract class MediaWikiTestCase extends PHPUnit_Framework_TestCase {
                }
        }
 
-       private function initDB() {
+       /**
+        * Restores MediaWiki to using the table set (table prefix) it was using before
+        * setupTestDB() was called. Useful if we need to perform database operations
+        * after the test run has finished (such as saving logs or profiling info).
+        */
+       public static function teardownTestDB() {
+               if ( !self::$dbSetup ) {
+                       return;
+               }
+
+               CloneDatabase::changePrefix( self::$oldTablePrefix );
+
+               self::$oldTablePrefix = false;
+               self::$dbSetup = false;
+       }
+
+       /**
+        * Creates an empty skeleton of the wiki database by cloning its structure
+        * to equivalent tables using the given $prefix. Then sets MediaWiki to
+        * use the new set of tables (aka schema) instead of the original set.
+        *
+        * This is used to generate a dummy table set, typically consisting of temporary
+        * tables, that will be used by tests instead of the original wiki database tables.
+        *
+        * @note: the original table prefix is stored in self::$oldTablePrefix. This is used
+        * by teardownTestDB() to return the wiki to using the original table set.
+        *
+        * @note: this method only works when first called. Subsequent calls have no effect,
+        * even if using different parameters.
+        *
+        * @param DatabaseBase $db The database connection
+        * @param String  $prefix The prefix to use for the new table set (aka schema).
+        *
+        * @throws MWException if the database table prefix is already $prefix
+        */
+       public static function setupTestDB( DatabaseBase $db, $prefix ) {
                global $wgDBprefix;
-               if ( $wgDBprefix === $this->dbPrefix() ) {
-                       throw new MWException( 'Cannot run unit tests, the database prefix is already "unittest_"' );
+               if ( $wgDBprefix === $prefix ) {
+                       throw new MWException( 'Cannot run unit tests, the database prefix is already "' . $prefix . '"' );
                }
 
-               $tablesCloned = $this->listTables();
-               $dbClone = new CloneDatabase( $this->db, $tablesCloned, $this->dbPrefix() );
-               $dbClone->useTemporaryTables( $this->useTemporaryTables );
+               if ( self::$dbSetup ) {
+                       return;
+               }
 
-               if ( ( $this->db->getType() == 'oracle' || !$this->useTemporaryTables ) && $this->reuseDB ) {
-                       CloneDatabase::changePrefix( $this->dbPrefix() );
-                       $this->resetDB();
+               $tablesCloned = self::listTables( $db );
+               $dbClone = new CloneDatabase( $db, $tablesCloned, $prefix );
+               $dbClone->useTemporaryTables( self::$useTemporaryTables );
+
+               self::$dbSetup = true;
+               self::$oldTablePrefix = $wgDBprefix;
+
+               if ( ( $db->getType() == 'oracle' || !self::$useTemporaryTables ) && self::$reuseDB ) {
+                       CloneDatabase::changePrefix( $prefix );
                        return;
                } else {
                        $dbClone->cloneTableStructure();
                }
 
-               if ( $this->db->getType() == 'oracle' ) {
-                       $this->db->query( 'BEGIN FILL_WIKI_INFO; END;' );
+               if ( $db->getType() == 'oracle' ) {
+                       $db->query( 'BEGIN FILL_WIKI_INFO; END;' );
                }
        }
 
@@ -378,7 +421,7 @@ abstract class MediaWikiTestCase extends PHPUnit_Framework_TestCase {
        private function resetDB() {
                if( $this->db ) {
                        if ( $this->db->getType() == 'oracle' )  {
-                               if ( $this->useTemporaryTables ) {
+                               if ( self::$useTemporaryTables ) {
                                        wfGetLB()->closeAll();
                                        $this->db = wfGetDB( DB_MASTER );
                                } else {
@@ -427,16 +470,16 @@ abstract class MediaWikiTestCase extends PHPUnit_Framework_TestCase {
                return strpos( $table, 'unittest_' ) !== 0;
        }
 
-       protected function listTables() {
+       public static function listTables( $db ) {
                global $wgDBprefix;
 
-               $tables = $this->db->listTables( $wgDBprefix, __METHOD__ );
+               $tables = $db->listTables( $wgDBprefix, __METHOD__ );
                $tables = array_map( array( __CLASS__, 'unprefixTable' ), $tables );
 
                // Don't duplicate test tables from the previous fataled run
                $tables = array_filter( $tables, array( __CLASS__, 'isNotUnittest' ) );
 
-               if ( $this->db->getType() == 'sqlite' ) {
+               if ( $db->getType() == 'sqlite' ) {
                        $tables = array_flip( $tables );
                        // these are subtables of searchindex and don't need to be duped/dropped separately
                        unset( $tables['searchindex_content'] );
index 6e618e3..b678647 100644 (file)
@@ -5,8 +5,6 @@ class SanitizerTest extends MediaWikiTestCase {
        protected function setUp() {
                parent::setUp();
 
-               $this->setMwGlobals( 'wgCleanupPresentationalAttributes', true );
-
                AutoLoader::loadClass( 'Sanitizer' );
        }
 
@@ -157,51 +155,24 @@ class SanitizerTest extends MediaWikiTestCase {
        /**
         * @dataProvider provideDeprecatedAttributes
         */
-       function testDeprecatedAttributes( $input, $tag, $expected, $message = null ) {
-               $this->assertEquals( $expected, Sanitizer::fixTagAttributes( $input, $tag ), $message );
-       }
-
-       function testDeprecatedAttributesDisabled() {
-               global $wgCleanupPresentationalAttributes;
-
-               $wgCleanupPresentationalAttributes = false;
+       function testDeprecatedAttributesUnaltered( $inputAttr, $inputEl ) {
 
-               $this->assertEquals( ' clear="left"', Sanitizer::fixTagAttributes( 'clear="left"', 'br' ), 'Deprecated attributes are not converted to styles when enabled.' );
+               $this->assertEquals( " $inputAttr", Sanitizer::fixTagAttributes( $inputAttr, $inputEl ) );
        }
 
        public static function provideDeprecatedAttributes() {
                return array(
-                       array( 'clear="left"', 'br', ' style="clear: left;"', 'Deprecated attributes are converted to styles when enabled.' ),
-                       array( 'clear="all"', 'br', ' style="clear: both;"', 'clear=all is converted to clear: both; not clear: all;' ),
-                       array( 'CLEAR="ALL"', 'br', ' style="clear: both;"', 'clear=ALL is not treated differently from clear=all' ),
-                       array( 'width="100"', 'td', ' style="width: 100px;"', 'Numeric sizes use pixels instead of numbers.' ),
-                       array( 'width="100%"', 'td', ' style="width: 100%;"', 'Units are allowed in sizes.' ),
-                       array( 'WIDTH="100%"', 'td', ' style="width: 100%;"', 'Uppercase WIDTH is treated as lowercase width.' ),
-                       array( 'WiDTh="100%"', 'td', ' style="width: 100%;"', 'Mixed case does not break WiDTh.' ),
-                       array( 'nowrap="true"', 'td', ' style="white-space: nowrap;"', 'nowrap attribute is output as white-space: nowrap; not something else.' ),
-                       array( 'nowrap=""', 'td', ' style="white-space: nowrap;"', 'nowrap="" is considered true, not false' ),
-                       array( 'NOWRAP="true"', 'td', ' style="white-space: nowrap;"', 'nowrap attribute works when uppercase.' ),
-                       array( 'NoWrAp="true"', 'td', ' style="white-space: nowrap;"', 'nowrap attribute works when mixed-case.' ),
-                       array( 'align="right"', 'td', ' style="text-align: right;"'   , 'align on table cells gets converted to text-align' ),
-                       array( 'align="center"', 'td', ' style="text-align: center;"' , 'align on table cells gets converted to text-align' ),
-                       array( 'align="left"'  , 'div', ' style="text-align: left;"'  , 'align=(left|right) on div elements gets converted to text-align' ),
-                       array( 'align="center"', 'div', ' style="text-align: center;"', 'align="center" on div elements gets converted to text-align' ),
-                       array( 'align="left"'  , 'p',   ' style="text-align: left;"'  , 'align on p elements gets converted to text-align' ),
-                       array( 'align="left"'  , 'h1',  ' style="text-align: left;"'  , 'align on h1 elements gets converted to text-align' ),
-                       array( 'align="left"'  , 'h1',  ' style="text-align: left;"'  , 'align on h1 elements gets converted to text-align' ),
-                       array( 'align="left"'  , 'caption',' style="text-align: left;"','align on caption elements gets converted to text-align' ),
-                       array( 'align="left"'  , 'tfoot',' style="text-align: left;"' , 'align on tfoot elements gets converted to text-align' ),
-                       array( 'align="left"'  , 'tbody',' style="text-align: left;"' , 'align on tbody elements gets converted to text-align' ),
-
-                       # <tr>
-                       array( 'align="right"' , 'tr', ' style="text-align: right;"' , 'align on table row get converted to text-align' ),
-                       array( 'align="center"', 'tr', ' style="text-align: center;"', 'align on table row get converted to text-align' ),
-                       array( 'align="left"'  , 'tr', ' style="text-align: left;"'  , 'align on table row get converted to text-align' ),
-
-                       #table
-                       array( 'align="left"'  , 'table', ' style="float: left;"'    , 'align on table converted to float' ),
-                       array( 'align="center"', 'table', ' style="margin-left: auto; margin-right: auto;"', 'align center on table converted to margins' ),
-                       array( 'align="right"' , 'table', ' style="float: right;"'   , 'align on table converted to float' ),
+                       array( 'clear="left"', 'br' ),
+                       array( 'clear="all"', 'br' ),
+                       array( 'width="100"', 'td' ),
+                       array( 'nowrap="true"', 'td' ),
+                       array( 'nowrap=""', 'td' ),
+                       array( 'align="right"', 'td' ),
+                       array( 'align="center"', 'table' ),
+                       array( 'align="left"', 'tr' ),
+                       array( 'align="center"', 'div' ),
+                       array( 'align="left"', 'h1' ),
+                       array( 'align="left"', 'span' ),
                );
        }
 
index add7066..5369112 100644 (file)
@@ -585,6 +585,73 @@ class FileBackendTest extends MediaWikiTestCase {
                return $cases;
        }
 
+       /**
+        * @dataProvider provider_testDescribe
+        */
+       public function testDescribe( $op, $withSource, $okStatus ) {
+               $this->backend = $this->singleBackend;
+               $this->tearDownFiles();
+               $this->doTestDescribe( $op, $withSource, $okStatus );
+               $this->tearDownFiles();
+
+               $this->backend = $this->multiBackend;
+               $this->tearDownFiles();
+               $this->doTestDescribe( $op, $withSource, $okStatus );
+               $this->tearDownFiles();
+       }
+
+       private function doTestDescribe( $op, $withSource, $okStatus ) {
+               $backendName = $this->backendClass();
+
+               $source = $op['src'];
+               $this->prepare( array( 'dir' => dirname( $source ) ) );
+
+               if ( $withSource ) {
+                       $status = $this->backend->doOperation(
+                               array( 'op' => 'create', 'content' => 'blahblah', 'dst' => $source ) );
+                       $this->assertGoodStatus( $status,
+                               "Creation of file at $source succeeded ($backendName)." );
+               }
+
+               $status = $this->backend->doOperation( $op );
+               if ( $okStatus ) {
+                       $this->assertGoodStatus( $status,
+                               "Describe of file at $source succeeded without warnings ($backendName)." );
+                       $this->assertEquals( true, $status->isOK(),
+                               "Describe of file at $source succeeded ($backendName)." );
+                       $this->assertEquals( array( 0 => true ), $status->success,
+                               "Describe of file at $source has proper 'success' field in Status ($backendName)." );
+               } else {
+                       $this->assertEquals( false, $status->isOK(),
+                               "Describe of file at $source failed ($backendName)." );
+               }
+
+               $this->assertBackendPathsConsistent( array( $source ) );
+       }
+
+       public static function provider_testDescribe() {
+               $cases = array();
+
+               $source = self::baseStorePath() . '/unittest-cont1/e/myfacefile.txt';
+
+               $op = array( 'op' => 'describe', 'src' => $source,
+                       'headers' => array( 'X-Content-Length' => '91.3' ),
+                       'disposition' => 'inline' );
+               $cases[] = array(
+                       $op, // operation
+                       true, // with source
+                       true // succeeds
+               );
+
+               $cases[] = array(
+                       $op, // operation
+                       false, // without source
+                       false // fails
+               );
+
+               return $cases;
+       }
+
        /**
         * @dataProvider provider_testCreate
         */
@@ -1362,6 +1429,8 @@ class FileBackendTest extends MediaWikiTestCase {
                $this->prepare( array( 'dir' => dirname( $fileD ) ) );
 
                $status = $this->backend->doOperations( array(
+                       array( 'op' => 'describe', 'src' => $fileA,
+                               'headers' => array( 'X-Content-Length' => '91.3' ), 'disposition' => 'inline' ),
                        array( 'op' => 'copy', 'src' => $fileA, 'dst' => $fileC, 'overwrite' => 1 ),
                        // Now: A:<A>, B:<B>, C:<A>, D:<empty> (file:<orginal contents>)
                        array( 'op' => 'copy', 'src' => $fileC, 'dst' => $fileA, 'overwriteSame' => 1 ),
@@ -1392,7 +1461,7 @@ class FileBackendTest extends MediaWikiTestCase {
 
                $this->assertGoodStatus( $status, "Operation batch succeeded" );
                $this->assertEquals( true, $status->isOK(), "Operation batch succeeded" );
-               $this->assertEquals( 13, count( $status->success ),
+               $this->assertEquals( 14, count( $status->success ),
                        "Operation batch has correct success array" );
 
                $this->assertEquals( false, $this->backend->fileExists( array( 'src' => $fileA ) ),
index 401962f..3476ce3 100644 (file)
@@ -329,7 +329,6 @@ class NewParserTest extends MediaWikiTestCase {
                        'wgExternalLinkTarget' => false,
                        'wgAlwaysUseTidy' => false,
                        'wgHtml5' => true,
-                       'wgCleanupPresentationalAttributes' => true,
                        'wgWellFormedXml' => true,
                        'wgAllowMicrodataAttributes' => true,
                        'wgAdaptiveMessageCache' => true,
index c66df69..94ccfd0 100644 (file)
@@ -1078,5 +1078,37 @@ class LanguageTest extends LanguageClassesTestCase {
                        ) ),
                );
        }
+
+       /**
+        * @covers Language::translateBlockExpiry()
+        * @dataProvider provideTranslateBlockExpiry
+        */
+       function testTranslateBlockExpiry( $expectedData, $str, $desc ) {
+               $lang = $this->getLang();
+               if ( is_array( $expectedData ) ) {
+                       list( $func, $arg ) = $expectedData;
+                       $expected = $lang->$func( $arg );
+               } else {
+                       $expected = $expectedData;
+               }
+               $this->assertEquals( $expected, $lang->translateBlockExpiry( $str ), $desc );
+       }
+
+       function provideTranslateBlockExpiry() {
+               return array(
+                       array( '2 hours', '2 hours', 'simple data from ipboptions' ),
+                       array( 'indefinite', 'infinite', 'infinite from ipboptions' ),
+                       array( 'indefinite', 'infinity', 'alternative infinite from ipboptions' ),
+                       array( 'indefinite', 'indefinite', 'another alternative infinite from ipboptions' ),
+                       array( array( 'formatDuration', 1023 * 60 * 60 ), '1023 hours', 'relative' ),
+                       array( array( 'formatDuration', -1023 ), '-1023 seconds', 'negative relative' ),
+                       array( array( 'formatDuration', 0 ), 'now', 'now' ),
+                       array( array( 'timeanddate', '20120102070000' ), '2012-1-1 7:00 +1 day', 'mixed, handled as absolute' ),
+                       array( array( 'timeanddate', '19910203040506' ), '1991-2-3 4:05:06', 'absolute' ),
+                       array( array( 'timeanddate', '19700101000000' ), '1970-1-1 0:00:00', 'absolute at epoch' ),
+                       array( array( 'timeanddate', '19691231235959' ), '1969-12-31 23:59:59', 'time before epoch' ),
+                       array( 'dummy', 'dummy', 'return garbage as is' ),
+               );
+       }
 }