Merge "Exclude null rows from Special:MediaStatistics"
authorjenkins-bot <jenkins-bot@gerrit.wikimedia.org>
Thu, 26 Feb 2015 16:22:34 +0000 (16:22 +0000)
committerGerrit Code Review <gerrit@wikimedia.org>
Thu, 26 Feb 2015 16:22:34 +0000 (16:22 +0000)
26 files changed:
autoload.php
composer.json
includes/api/i18n/zh-hans.json
includes/db/Database.php
includes/db/DatabaseMssql.php
includes/db/DatabasePostgres.php
includes/db/DatabaseSqlite.php
includes/installer/PostgresInstaller.php
includes/installer/SqliteInstaller.php
includes/installer/i18n/fa.json
languages/i18n/ar.json
languages/i18n/az.json
languages/i18n/bgn.json
languages/i18n/ce.json
languages/i18n/es.json
languages/i18n/fa.json
languages/i18n/frr.json
languages/i18n/gl.json
languages/i18n/lzh.json
languages/i18n/nl.json
languages/i18n/pms.json
languages/i18n/ro.json
resources/lib/oojs-ui/oojs-ui-mediawiki.css
resources/lib/oojs-ui/oojs-ui-mediawiki.js
resources/lib/oojs-ui/oojs-ui.js
resources/lib/oojs/oojs.jquery.js

index a7b36a6..b85ac46 100644 (file)
@@ -376,6 +376,7 @@ $wgAutoloadLocalClasses = array(
        'ExifBitmapHandler' => __DIR__ . '/includes/media/ExifBitmap.php',
        'ExplodeIterator' => __DIR__ . '/includes/libs/ExplodeIterator.php',
        'ExportProgressFilter' => __DIR__ . '/maintenance/backup.inc',
+       'ExportSites' => __DIR__ . '/maintenance/exportSites.php',
        'ExtensionLanguages' => __DIR__ . '/maintenance/language/languages.inc',
        'ExtensionProcessor' => __DIR__ . '/includes/registration/ExtensionProcessor.php',
        'ExtensionRegistry' => __DIR__ . '/includes/registration/ExtensionRegistry.php',
@@ -536,6 +537,7 @@ $wgAutoloadLocalClasses = array(
        'ImageQueryPage' => __DIR__ . '/includes/specialpage/ImageQueryPage.php',
        'ImportReporter' => __DIR__ . '/includes/specials/SpecialImport.php',
        'ImportSiteScripts' => __DIR__ . '/maintenance/importSiteScripts.php',
+       'ImportSites' => __DIR__ . '/maintenance/importSites.php',
        'ImportSource' => __DIR__ . '/includes/Import.php',
        'ImportStreamSource' => __DIR__ . '/includes/Import.php',
        'ImportStringSource' => __DIR__ . '/includes/Import.php',
@@ -886,6 +888,7 @@ $wgAutoloadLocalClasses = array(
        'PopulateRevisionLength' => __DIR__ . '/maintenance/populateRevisionLength.php',
        'PopulateRevisionSha1' => __DIR__ . '/maintenance/populateRevisionSha1.php',
        'PostgreSqlLockManager' => __DIR__ . '/includes/filebackend/lockmanager/DBLockManager.php',
+       'PostgresBlob' => __DIR__ . '/includes/db/DatabasePostgres.php',
        'PostgresField' => __DIR__ . '/includes/db/DatabasePostgres.php',
        'PostgresInstaller' => __DIR__ . '/includes/installer/PostgresInstaller.php',
        'PostgresTransactionState' => __DIR__ . '/includes/db/DatabasePostgres.php',
index 7f8c661..d409025 100644 (file)
@@ -19,7 +19,7 @@
                "cssjanus/cssjanus": "1.1.1",
                "ext-iconv": "*",
                "leafo/lessphp": "0.5.0",
-               "oojs/oojs-ui": "0.8.0",
+               "oojs/oojs-ui": "0.8.1",
                "php": ">=5.3.3",
                "psr/log": "1.0.0",
                "wikimedia/cdb": "1.0.1",
index 3c1b89c..c0d6a8c 100644 (file)
        "apihelp-query+alllinks-example-unique": "列出唯一的链接标题",
        "apihelp-query+alllinks-example-unique-generator": "获得所有已链接的标题,标记缺少的。",
        "apihelp-query+alllinks-example-generator": "获取包含这些链接的页面",
-       "apihelp-query+allmessages-description": "è¿\94å\9b\9eæ\9d¥è\87ªè¯¥ç«\99ç\82¹的消息。",
+       "apihelp-query+allmessages-description": "è¿\94å\9b\9eæ\9d¥è\87ªè¯¥ç½\91ç«\99的消息。",
        "apihelp-query+allmessages-param-messages": "要输出的消息。<kbd>*</kbd>(默认)表示所有消息。",
        "apihelp-query+allmessages-param-prop": "要获取的属性。",
+       "apihelp-query+allmessages-param-customised": "只返回在此定制情形下的消息。",
        "apihelp-query+allmessages-param-lang": "返回这种语言的信息。",
        "apihelp-query+allmessages-param-prefix": "返回带有该前缀的消息。",
        "apihelp-query+allmessages-example-ipb": "显示以<kbd>ipb-</kbd>开始的消息。",
index 2b79261..ee1722e 100644 (file)
@@ -2666,10 +2666,13 @@ abstract class DatabaseBase implements IDatabase {
        /**
         * Adds quotes and backslashes.
         *
-        * @param string $s
+        * @param string|Blob $s
         * @return string
         */
        public function addQuotes( $s ) {
+               if ( $s instanceof Blob ) {
+                       $s = $s->fetch();
+               }
                if ( $s === null ) {
                        return 'NULL';
                } else {
@@ -3933,10 +3936,13 @@ abstract class DatabaseBase implements IDatabase {
         * in result objects. Pass the object through this function to return the
         * original string.
         *
-        * @param string $b
+        * @param string|Blob $b
         * @return string
         */
        public function decodeBlob( $b ) {
+               if ( $b instanceof Blob ) {
+                       $b = $b->fetch();
+               }
                return $b;
        }
 
index f5e6667..2b8f395 100644 (file)
@@ -1094,7 +1094,7 @@ class DatabaseMssql extends DatabaseBase {
        }
 
        /**
-        * @param string $s
+        * @param string|Blob $s
         * @return string
         */
        public function addQuotes( $s ) {
index abf26e0..3d0ed86 100644 (file)
@@ -1495,12 +1495,14 @@ SQL;
         * @return Blob
         */
        function encodeBlob( $b ) {
-               return new Blob( pg_escape_bytea( $this->mConn, $b ) );
+               return new PostgresBlob( pg_escape_bytea( $b ) );
        }
 
        function decodeBlob( $b ) {
-               if ( $b instanceof Blob ) {
+               if ( $b instanceof PostgresBlob ) {
                        $b = $b->fetch();
+               } elseif ( $b instanceof Blob ) {
+                       return $b->fetch();
                }
 
                return pg_unescape_bytea( $b );
@@ -1520,7 +1522,12 @@ SQL;
                } elseif ( is_bool( $s ) ) {
                        return intval( $s );
                } elseif ( $s instanceof Blob ) {
-                       return "'" . $s->fetch( $s ) . "'";
+                       if ( $s instanceof PostgresBlob ) {
+                               $s = $s->fetch();
+                       } else {
+                               $s = pg_escape_bytea( $this->mConn, $s->fetch() );
+                       }
+                       return "'$s'";
                }
 
                return "'" . pg_escape_string( $this->mConn, $s ) . "'";
@@ -1692,3 +1699,5 @@ SQL;
                return wfBaseConvert( substr( sha1( $lockName ), 0, 15 ), 16, 10 );
        }
 } // end DatabasePostgres class
+
+class PostgresBlob extends Blob {}
index 7b04716..0b51972 100644 (file)
@@ -32,6 +32,9 @@ class DatabaseSqlite extends DatabaseBase {
        /** @var string File name for SQLite database file */
        public $mDatabaseFile;
 
+       /** @var string Transaction mode */
+       protected $trxMode;
+
        /** @var int The number of rows affected as an integer */
        protected $mAffectedRows;
 
@@ -44,6 +47,11 @@ class DatabaseSqlite extends DatabaseBase {
        /** @var FSLockManager (hopefully on the same server as the DB) */
        protected $lockMgr;
 
+       /**
+        * Additional params include:
+        *   - trxMode : one of (deferred, immediate, exclusive)
+        * @param array $p
+        */
        function __construct( array $p ) {
                global $wgSharedDB, $wgSQLiteDataDir;
 
@@ -58,6 +66,12 @@ class DatabaseSqlite extends DatabaseBase {
                        }
                }
 
+               $this->trxMode = isset( $p['trxMode'] ) ? strtoupper( $p['trxMode'] ) : null;
+               if ( $this->trxMode && !in_array( $this->trxMode, array( 'IMMEDIATE', 'EXCLUSIVE' ) ) ) {
+                       $this->trxMode = null;
+                       wfWarn( "Invalid SQLite transaction mode provided." );
+               }
+
                $this->lockMgr = new FSLockManager( array( 'lockDirectory' => "$wgSQLiteDataDir/locks" ) );
        }
 
@@ -697,6 +711,15 @@ class DatabaseSqlite extends DatabaseBase {
                return false;
        }
 
+       protected function doBegin( $fname = '' ) {
+               if ( $this->trxMode ) {
+                       $this->query( "BEGIN {$this->trxMode}", $fname );
+               } else {
+                       $this->query( 'BEGIN', $fname );
+               }
+               $this->mTrxLevel = 1;
+       }
+
        /**
         * @param string $s
         * @return string
index e19f9aa..b18fe94 100644 (file)
@@ -262,11 +262,13 @@ class PostgresInstaller extends DatabaseInstaller {
                $status = Status::newGood();
                foreach ( $dbs as $db ) {
                        try {
-                               $conn = new DatabasePostgres(
-                                       $this->getVar( 'wgDBserver' ),
-                                       $user,
-                                       $password,
-                                       $db );
+                               $p = array(
+                                       'host' => $this->getVar( 'wgDBserver' ),
+                                       'user' => $user,
+                                       'password' => $password,
+                                       'dbname' => $db
+                               );
+                               $conn = DatabaseBase::factory( 'postgres', $p );
                        } catch ( DBConnectionError $error ) {
                                $conn = false;
                                $status->fatal( 'config-pg-test-error', $db,
index 37fba15..1e7e969 100644 (file)
@@ -226,6 +226,49 @@ class SqliteInstaller extends DatabaseInstaller {
                }
 
                $db = $this->getVar( 'wgDBname' );
+
+               # Make the main and cache stub DB files
+               $status = Status::newGood();
+               $status->merge( $this->makeStubDBFile( $dir, $db ) );
+               $status->merge( $this->makeStubDBFile( $dir, "wikicache" ) );
+               if ( !$status->isOK() ) {
+                       return $status;
+               }
+
+               # Nuke the unused settings for clarity
+               $this->setVar( 'wgDBserver', '' );
+               $this->setVar( 'wgDBuser', '' );
+               $this->setVar( 'wgDBpassword', '' );
+               $this->setupSchemaVars();
+
+               # Create the global cache DB
+               try {
+                       global $wgSQLiteDataDir;
+                       # @todo FIXME: setting globals kind of sucks
+                       $wgSQLiteDataDir = $dir;
+                       $conn = DatabaseBase::factory( 'sqlite', array( 'dbname' => "wikicache" ) );
+                       # @todo: don't duplicate objectcache definition, though it's very simple
+                       $sql =
+<<<EOT
+       CREATE TABLE IF NOT EXISTS objectcache (
+         keyname BLOB NOT NULL default '' PRIMARY KEY,
+         value BLOB,
+         exptime TEXT
+       )
+EOT;
+                       $conn->query( $sql );
+                       $conn->query( "CREATE INDEX IF NOT EXISTS exptime ON objectcache (exptime)" );
+                       $conn->query( "PRAGMA journal_mode=WAL" ); // this is permanent
+                       $conn->close();
+               } catch ( DBConnectionError $e ) {
+                       return Status::newFatal( 'config-sqlite-connection-error', $e->getMessage() );
+               }
+
+               # Open the main DB
+               return $this->getConnection();
+       }
+
+       protected function makeStubDBFile( $dir, $db ) {
                $file = DatabaseSqlite::generateFileName( $dir, $db );
                if ( file_exists( $file ) ) {
                        if ( !is_writable( $file ) ) {
@@ -236,13 +279,8 @@ class SqliteInstaller extends DatabaseInstaller {
                                return Status::newFatal( 'config-sqlite-cant-create-db', $file );
                        }
                }
-               // nuke the unused settings for clarity
-               $this->setVar( 'wgDBserver', '' );
-               $this->setVar( 'wgDBuser', '' );
-               $this->setVar( 'wgDBpassword', '' );
-               $this->setupSchemaVars();
 
-               return $this->getConnection();
+               return Status::newGood();
        }
 
        /**
@@ -280,6 +318,16 @@ class SqliteInstaller extends DatabaseInstaller {
                $dir = LocalSettingsGenerator::escapePhpString( $this->getVar( 'wgSQLiteDataDir' ) );
 
                return "# SQLite-specific settings
-\$wgSQLiteDataDir = \"{$dir}\";";
+\$wgSQLiteDataDir = \"{$dir}\";
+\$wgObjectCaches[CACHE_DB] = array(
+       'class' => 'SqlBagOStuff',
+       'loggroup' => 'SQLBagOStuff',
+       'server' => array(
+               'type' => 'sqlite',
+               'dbname' => 'wikicache',
+               'tablePrefix' => '',
+               'flags' => 0
+       )
+);";
        }
 }
index ac486bb..6e44d4b 100644 (file)
@@ -57,7 +57,7 @@
        "config-unicode-using-intl": "برای یونیکد عادی از [http://pecl.php.net/intl intl PECL extension] استفاده کنید.",
        "config-unicode-pure-php-warning": "'''هشدار:''' [http://pecl.php.net/intl intl PECL extension] برای کنترل یونیکد عادی در دسترس نیست،اجرای کاملاً آهسته به تعویق می‌افتد.\nاگر شما یک سایت پر‌ ترافیک را اجرا می‌کنید، باید کمی [//www.mediawiki.org/wiki/Special:MyLanguage/Unicode_normalization_considerations Unicode normalization] را بخوانید.",
        "config-unicode-update-warning": "'''هشدار:''' نسخهٔ نصب شدهٔ پوشهٔ یونیکد عادی از ورژن قدیمی‌تر کتابخانه [http://site.icu-project.org/ the ICU project's] استفاده می‌کند.\nاگر کلاً علاقه‌مند به استفاده از یونیکد هستید باید [//www.mediawiki.org/wiki/Special:MyLanguage/Unicode_normalization_considerations upgrade].",
-       "config-no-db": "درایور پایگاه اطلاعاتی مناسب پیدا نشد! شما لازم دارید یک درایور پایگاه اطلاعاتی  برای پی‌اچ‌پی نصب کنید.انواع پایگاه اطلاعاتی زیر پشتیبانی شده‌اند:$1.\nاگر شما در گروه اشتراک‌گذاری هستید، از تهیه کنندهٔ گروه خود برای نصب یک درایور پایگاه اطلاعاتی مناسب سوأل کنید.\nاگر خود، پی‌اچ‌پی را تهیه کرده‌اید، با یک پردازشگر فعال دوباره پیکربندی کنید، برای مثال از <code>./configure --with-mysql</code> استفاده کنید.\nاگر پی‌اچ‌پی را از یک بستهٔ دبیان یا آبونتو نصب کرده‌اید، بنابراین لازم دارید بخش php5-mysql را نصب کنید.",
+       "config-no-db": "درایور پایگاه اطلاعاتی مناسب پیدا نشد! شما لازم دارید یک درایور پایگاه اطلاعاتی  برای پی‌اچ‌پی نصب کنید.انواع پایگاه اطلاعاتی زیر پشتیبانی شده‌اند:$1.\nاگر شما در گروه اشتراک‌گذاری هستید، از تهیه کنندهٔ گروه خود برای نصب یک درایور پایگاه اطلاعاتی مناسب {{PLURAL:$2|سوأل کنید.|سوأل کنید.}}\nاگر خود، پی‌اچ‌پی را تهیه کرده‌اید، با یک پردازشگر فعال دوباره پیکربندی کنید، برای مثال از <code>./configure --with-mysql</code> استفاده کنید.\nاگر پی‌اچ‌پی را از یک بستهٔ دبیان یا آبونتو نصب کرده‌اید، بنابراین لازم دارید بخش php5-mysql را نصب کنید.",
        "config-outdated-sqlite": "''' هشدار:''' شما اس‌کیولایت $1 دارید، که پایین‌تر از حداقل نسخهٔ $2 مورد نیاز است.اس‌کیولایت در دسترس نخواهد بود.",
        "config-no-fts3": "'''هشدار:''' اس‌کیولایت بدون [//sqlite.org/fts3.html FTS3 module] تهیه شده‌است ، جستجوی ویژگی‌ها در این بخش پیشین در دسترس نخواهد‌بود.",
        "config-register-globals-error": "<strong>خطا:  پی‌اچ‌پی<code>[http://php.net/register_globals register_globals]</code> گزینه فعال است.\nبرای ادامه نصب باید غیر فعال باشد.</strong>\n[Https://www.mediawiki.org/wiki/register_globals https://www.mediawiki.org/wiki/register_globals] را برای کمک در مورد نحوه انجام این کار ببینید.",
index 5b3dc29..c0d32e8 100644 (file)
        "thumbnail_image-missing": "الملف يبدو أنه مفقود: $1",
        "thumbnail_image-failure-limit": "هناك الكثير من المحاولات الفاشلة مؤخراً ($1 أو أكثر) لتَصْيير هذه الصورة المصغرة. الرجاء المحاولة مرة أخرى لاحقاً.",
        "import": "استيراد صفحات",
-       "importinterwiki": "استÙ\8aراد ØªØ±Ø§Ù\86سÙ\88Ù\8aÙ\83Ù\8a",
+       "importinterwiki": "استÙ\88رد Ù\85Ù\86 Ù\88Ù\8aÙ\83Ù\8a Ø£Ø®Ø±Ù\89",
        "import-interwiki-text": "اختر ويكي وعنوان الصفحة للاستيراد.\nتواريخ المراجعات وأسماء المحررين سيتم حفظها.\nكل أفعال الاستيراد عبر الويكي يتم تسجيلها في [[Special:Log/import|سجل الاستيراد]].",
        "import-interwiki-sourcewiki": "الويكي المصدر:",
        "import-interwiki-sourcepage": "الصفحة المصدر:",
        "tags-tag": "اسم الوسم",
        "tags-display-header": "الظهور في قوائم التغييرات",
        "tags-description-header": "وصف كامل للمعنى",
+       "tags-source-header": "المصدر",
        "tags-active-header": "نشط؟",
        "tags-hitcount-header": "تغييرات موسومة",
        "tags-active-yes": "نعم",
        "tags-active-no": "لا",
        "tags-edit": "عدل",
+       "tags-delete": "احذف",
+       "tags-activate": "نشط",
        "tags-hitcount": "{{PLURAL:$1|لا تغييرات|تغيير واحد|تغييران|$1 تغييرات|$1 تغييرا|$1 تغيير}}",
+       "tags-create-tag-name": "اسم الوسم:",
+       "tags-create-reason": "السبب:",
+       "tags-create-submit": "أنشئ",
        "comparepages": "قارن صفحات",
        "compare-page1": "صفحة 1",
        "compare-page2": "صفحة 2",
index 6248807..b4117f9 100644 (file)
        "edit-no-change": "Sizin redaktələr qeydə alınmamışdır. Belə ki, mətndə heç bir düzəliş edilməmişdir.",
        "postedit-confirmation-saved": "Redaktəniz qeyd edildi.",
        "edit-already-exists": "Yeni səhifəni yaratmaq mümkün deyil.\nBelə ki, bu adda səhifə artıq mövcuddur.",
+       "content-not-allowed-here": "\"$1\" tərkibi [[$2]] səhifəsi üçün icazə verilmir.",
+       "content-model-wikitext": "vikimətn",
+       "content-model-text": "adi mətn",
        "content-model-javascript": "JavaScript",
        "expensive-parserfunction-category": "Kifayət qədər böyük sayda genişresurslu funksiyaların müraciət olunduğu səhifələr",
        "post-expand-template-inclusion-warning": "'''DİQQƏT!''' Daxil edilən şablonların həcmi həddindən artıq böyükdür.\nBəzi şablonlar əlavə olunmayacaq.",
        "immobile-target-namespace-iw": "İntervikilər səhifə adının dəyişməsi üçün əsas ola bilməz.",
        "immobile-source-page": "Bu səhifənin adı dəyişdirilə bilməz.",
        "immobile-target-page": "Bu hədəf başlığına daşınmır.",
+       "bad-target-model": "İstənilən hədəf fərqli bir məzmun modeli istifadə edir. $1 modelindən $2 modelinə çevrilmir.",
        "imageinvalidfilename": "Seçilmiş fayl adı keçərsizdir.",
        "protectedpagemovewarning": "'''Xəbərdarlıq:''' Bu səhifə mühafizə edildiyi üçün onun adını yalnız idarəçilər dəyişə bilərlər.",
        "export": "Səhifələri ixrac et",
        "pageinfo-header-restrictions": "Səhifə mühafizəsi",
        "pageinfo-header-properties": "Səhifə xüsusiyyətləri",
        "pageinfo-display-title": "Göstərilən başlıq",
+       "pageinfo-default-sort": "Susmaya görə çeşidləmə açarı",
        "pageinfo-length": "Səhifənin ölçüsü (baytla)",
        "pageinfo-article-id": "Səhifə ID-si",
        "pageinfo-language": "Səhifənin dili",
        "pageinfo-content-model": "Səhifə məzmunu modeli",
+       "pageinfo-robot-policy": "Robotlar tərəfindən indeksləşmə",
+       "pageinfo-robot-index": "İcazə verilir",
        "pageinfo-robot-noindex": "İcazə verilmədi",
        "pageinfo-watchers": "Səhifəyə baxışların sayı",
        "pageinfo-few-watchers": "$1 {{PLURAL:$1|izləyicidən|izləyicilərdən}} az",
index a4f2cd5..15759a5 100644 (file)
        "user-mail-no-addy": "کوشش په دیم داتین یک خط بی شه گوجام ایمیل ادرسئ  ئا.",
        "user-mail-no-body": "کوشش په دیم داتین ئا یک گونڈین یا خالی ئین ایمیل ئی ئا.",
        "changepassword": "پاسوردی تغیر داتین",
+       "resetpass_announce": "شما باید په لوگین ئی الاسی ئا، نۆکین چیهرگالی ئی تنظیم بکنیت.",
        "resetpass_header": "پاسوردئ تغیر داتین",
        "oldpassword": "دیمئ پاسورد:",
        "newpassword": "نوکین پاسورد:",
        "retypenew": "نوکین پاسوردا پدا داخل کورتین",
        "resetpass_submit": "پاسوردی تنظیم و داخل بوتین",
        "changepassword-success": "شمی پاسوردئ تغیر کامیاب بوت و پاسورد تغیر کورت",
+       "changepassword-throttled": "شما بیخی باز وار په لوگین بوتینا کوشش کورته ایت.\nمهربانئ بکنیت دیم شه آیی که پدا کوشش بکنیت $1 صبر کنیت.",
        "resetpass_forbidden": "نه توانیت که پاسوردا تغیر بدهیت",
        "resetpass-no-info": "په ای تاکدیمی دسترسی ئی خاتیرا داخل بئیت.",
        "resetpass-submit-loggedin": "پاسوردی تغیر داتین",
        "resetpass-submit-cancel": "کنسیل",
+       "resetpass-recycled": "مهربانی بکینت دیگه پاسورد یا چیهرگالی غیر شه انونین چیهرگال ئا تنظیم بکنیت.",
+       "resetpass-temp-emailed": "شما گۆ یک موقتین ایمیل بوته ئین کود ئا لوگین بوته ئیت.\nپه لوگین ئی الاسی ئا شما باید نوکین چیهرگالی ایدا داخل بکنیت:",
        "resetpass-temp-password": "موقیئتین پاسورد:",
+       "resetpass-expired": "شمی چیهرگالی ئی وخت الاس بوته. مهربانی په لوگین بوتینا نۆکین چیهرگالی تنظیم بکنیت.",
        "passwordreset": "پاک کورتین پاسوردئ",
        "passwordreset-text-one": "په پدا نادینتین ایمیلی پاسوردی خاتیرا ای فرم ئا پر کنیت.",
        "passwordreset-text-many": "{{PLURAL:$1|په موقتی ئین چیهرگال ئی گیپتین شه ایمیلئ راه ئا، یکی شه زمینه‌هان ئا پر کنیت.}}",
        "resettokens-tokens": "نشانگان:",
        "resettokens-token-label": "$1 (انونین اندازه گ: $2)",
        "resettokens-done": "بیئر گردینتین نشانگ ئان.",
+       "resettokens-resetbutton": "نشانی بوته ئین وسایلانی بیئرگردینتین.",
        "bold_sample": "پر رنگین متن",
        "bold_tip": "پر رنگین متن",
        "italic_sample": "مورب متن",
        "anonpreviewwarning": "<em>شما لوگین نه بوته ئیت. ذخیره کورتین باعث ئه بیئت که شمی آی پی ادرس بی ای تاکدیمی تاریخچه ئی تا ثبت بیئت.</em>",
        "missingcommenttext": "مهربانی بکنیت جهلگا توضیح دهیت.",
        "summary-preview": "دیم دیست ئی خلاصه:",
+       "subject-preview": "موضو ئی دیم دیست/ئنوان:",
        "blockedtitle": "کار زوروک بسته بوته",
        "blockednoreason": "دلیلی مشخص نه بوته",
        "whitelistedittext": "په مقاله ئانی ایڈیٹ ئا باید $1.",
        "storedversion": "ذخیره بوته ئین نخسه",
        "yourdiff": "تفاوت‌هان",
        "templatesused": "{{PLURAL:$1|تراشوان|تراشوانان}} استفاده بوته انت بی ای تاکدیمئ تا:",
+       "templatesusedpreview": "ای دیم دیست ئی تا استفاده بوته ئین {{PLURAL:$1|تراشوان|تراشوانان}} :",
+       "templatesusedsection": "ای بخش ئی تا استفاده بوته ئین {{PLURAL:$1|تراشوان|تراشوانان}} :",
        "template-protected": "(قُلپ بوته)",
        "template-semiprotected": "(نیمه‌ گ قُلپ بوته)",
        "hiddencategories": "ای تاکدیم بی {{PLURAL:$1|یک چیهرین تهر|$1 چیهرین تهر}} تا قرار داریت:",
+       "nocreate-loggedin": "شما نوکین دیم ئی جۆڑ کورتین ئی اجازه ئا نداریت.",
+       "sectioneditnotsupported-title": "بخش ئانی ایڈیٹ پشتیوانی ئه نه بیئنت",
        "sectioneditnotsupported-text": "ای تاکدیم شه بخشانی ایڈیٹ ئا پُشتوانی ئه نه کنت.",
        "permissionserrors": "دسترسی ئی خطا",
        "permissionserrorstext": "شما ای کارئ اجازه ئا په ای {{PLURAL:$1|دلیلا|دلیلان}} نداریت:",
        "postedit-confirmation-saved": "شمی ایڈ\tیٹ ذخیره بوت.",
        "edit-already-exists": "نوکین تاکدیمئ جوڑ کورتین امکان نه داریت.\nای تاکدیم شه دیما وجود داشتت.",
        "defaultmessagetext": "پیامی پیش فرضین متن",
+       "invalid-content-data": "ناموتبرین دیتایی کانتکت",
        "content-not-allowed-here": "«$1» ئی محتوا بئ [[$2]] ئی دیمی تا جایز نه اینت",
+       "editpage-notsupportedcontentformat-title": "پشتیوانی نه بوته ئین دیتا کانتکت ئی فورمت کورتین",
        "content-model-wikitext": "ویکی‌متن",
        "content-model-text": "ساده گین متن",
        "content-model-javascript": "جاوااسکریپت",
index 0fb4db7..1b38eb0 100644 (file)
        "mimesearch-summary": "ХӀокху агӀоно йиш хуьлуьйту MIME-тайпан файлаш харжа. Яздеш долу формат: чулацаман тайп/бухара тайп, масала  <code>image/jpeg</code>.",
        "mimetype": "MIME-тайп:",
        "download": "чуяккха",
-       "unwatchedpages": "Цхьамо тергам ца беш йолу агӀонаш",
+       "unwatchedpages": "Цхьам терго цайо агӀонаш",
        "listredirects": "ДIасахьажоран могIам",
        "listduplicatedfiles": "Файлийн могӀам дубликатшца",
        "listduplicatedfiles-summary": "ХӀара файлийн могӀам бу, кхузахь тӀехьарчу файлан верси цхьайолу тӀехьарчу файлийн версийн дубликат лоруш ю. Локальни файлаш бен лоруш яц.",
        "actionfailed": "Кхочушъ дина дац",
        "deletedtext": "«$1» дӀаяьккхина яра.\nХьажа. $2 хьажарна оцу тӀаьхьара дӀаяхначара могӀаме.",
        "dellogpage": "ДӀадаьхнарш долу тéптар",
-       "dellogpagetext": "Лахахь гойтуш ду дӀадахаршан тептар.",
+       "dellogpagetext": "Лахахь гойтуш ю тӀаьххьара дӀаяьхнарш.",
        "deletionlog": "дӀадаьхнарш долу тéптар",
        "deletecomment": "Бахьна:",
        "deleteotherreason": "Кхин бахьна/тӀетохар:",
index 710383d..6969629 100644 (file)
        "readonly_lag": "La base de datos se ha bloqueado automáticamente mientras sus servidores esclavos se sincronizan con el maestro.",
        "internalerror": "Error interno",
        "internalerror_info": "Error interno: $1",
+       "internalerror-fatal-exception": "Excepción grave de tipo \"$1\"",
        "filecopyerror": "No se ha podido copiar el archivo «$1» a «$2».",
        "filerenameerror": "No se ha podido renombrar el archivo «$1» a «$2».",
        "filedeleteerror": "No se ha podido borrar el archivo «$1».",
        "thumbnail_image-missing": "El fichero parece no existir: $1",
        "thumbnail_image-failure-limit": "Ha habido muchos intentos recientes ($1 o más) para representar esta miniatura. Inténtalo de nuevo más tarde.",
        "import": "Importar páginas",
-       "importinterwiki": "Importación transwiki",
+       "importinterwiki": "Importar desde otro wiki",
        "import-interwiki-text": "Selecciona un wiki y un título de página para importar.\nLas fechas de revisiones y los nombres de editores se preservarán.\nTodas las importaciones transwiki se registran en el [[Special:Log/import|registro de importaciones]].",
        "import-interwiki-sourcewiki": "Wiki de origen:",
        "import-interwiki-sourcepage": "Página de origen:",
index 1a90601..701f154 100644 (file)
@@ -43,7 +43,8 @@
                        "Hosseinblue",
                        "فلورانس",
                        "Saeidpourbabak",
-                       "Arash.pt"
+                       "Arash.pt",
+                       "Signal89"
                ]
        },
        "tog-underline": "خط کشیدن زیر پیوندها:",
@@ -60,7 +61,7 @@
        "tog-watchdefault": "صفحه‌ها و پرونده‌هایی که ویرایش می‌کنم به فهرست پیگیری‌هایم افزوده شود",
        "tog-watchmoves": "صفحه‌ها و پرونده‌هایی که منتقل می‌کنم به فهرست پی‌گیری‌هایم افزوده شود",
        "tog-watchdeletion": "صفحات و پرونده‌هایی که حذف می‌کنم به فهرست پی‌گیری‌هایم افزوده شود",
-       "tog-watchrollback": "اÙ\81زÙ\88دÙ\86 ØµÙ\81حاتÛ\8c Ú©Ù\87 Ù\88اگرداÙ\86Û\8c Ú©Ø±Ø¯Ù\85 Ø¨Ø±Ø§Û\8c Ù\81Ù\87رست Ù¾Û\8cÚ¯Û\8cرÛ\8câ\80\8cÙ\87اÛ\8cÙ\85",
+       "tog-watchrollback": "صÙ\81حاتÛ\8c Ú©Ù\87 Ù\88اگرداÙ\86Û\8c Ù\85Û\8câ\80\8cÚ©Ù\86Ù\85 Ø¨Ù\87 Ù\81Ù\87رست Ù¾Û\8cÚ¯Û\8cرÛ\8câ\80\8cÙ\87اÛ\8cÙ\85 Ø§Ù\81زÙ\88دÙ\87 Ø´Ù\88د",
        "tog-minordefault": "همهٔ ویرایش‌ها به طور پیش‌فرض به عنوان «جزئی» علامت بخورد",
        "tog-previewontop": "پیش‌نمایش قبل از جعبهٔ ویرایش نمایش یابد",
        "tog-previewonfirst": "پیش‌نمایش هنگام اولین ویرایش نمایش یابد",
        "readonly_lag": "پایگاه داده به طور خودکار قفل شده‌است تا نسخه‌های پشتیبان با نسخهٔ اصلی هماهنگ شوند",
        "internalerror": "خطای داخلی",
        "internalerror_info": "خطای داخلی: $1",
+       "internalerror-fatal-exception": "نوع استثنای مخرب \"$1\"",
        "filecopyerror": "نشد از پروندهٔ «$1» روی «$2» نسخه‌برداری شود.",
        "filerenameerror": "نشد پروندهٔ «$1» به «$2» تغییر نام یابد.",
        "filedeleteerror": "نشد پروندهٔ «$1» حذف شود.",
        "action-viewmyprivateinfo": "اطلاعات خصوصی خود را ببینید",
        "action-editmyprivateinfo": "اطلاعات خصوصی خود را ویرایش کنید",
        "action-editcontentmodel": "ویرایش مدل محتوای یک صفحه",
+       "action-managechangetags": "ایجاد و حذف تگ‌ها از پایگاه داده",
        "nchanges": "$1 تغییر",
        "enhancedrc-since-last-visit": "$1 {{PLURAL:$1|از آخرین بازدید}}",
        "enhancedrc-history": "تاریخچه",
        "unusedimages": "پرونده‌های استفاده‌نشده",
        "wantedcategories": "رده‌های مورد نیاز",
        "wantedpages": "صفحه‌های مورد نیاز",
+       "wantedpages-summary": "فهرست صفحه‌های ناموجود با بیشترین پیوند به آنها، به استثنای صفحه‌هایی که فقط تغییرمسیر به آنها دارند. برای یک فهرست از صفحه‌های ناموجود که تغییرمسیر به آنها دارند، [[{{#special:BrokenRedirects}}]] را ببینید.",
        "wantedpages-badtitle": "عنوان نامجاز در مجموعهٔ نتایج: $1",
        "wantedfiles": "پرونده‌های مورد نیاز",
        "wantedfiletext-cat": "پرونده‌های زیر استفاده می‌شوند اما موجود نیستند. همچنین ممکن است پرونده‌های مخازن خارجی با وجود موجود بودن در اینجا فهرست شوند. هرگونه رتبه مثبت کاذب <del>خط خواهد خورد.</del> علاوه بر این، صفحاتی که پرونده‌هایی ناموجود را در خود جای داده‌اند در [[:$1]] فهرست شده‌اند.",
        "thumbnail_image-missing": "پرونده به نظر گم شده‌است: $1",
        "thumbnail_image-failure-limit": "تلاش‌های ناموفق اخیر بسیاری ($1 یا بیشتر) برای ارائهٔ این تصویر کوچک وجود داشته‌ است. لطفأ بعداً دوباره تلاش کنید.",
        "import": "درون‌ریزی صفحات",
-       "importinterwiki": "درÙ\88Ù\86â\80\8cرÛ\8cزÛ\8c ØªØ±Ø§Ù\88Û\8cÚ©Û\8c",
-       "import-interwiki-text": "یک ویکی و یک نام صفحه را انتخاب کنید تا اطلاعات از آن درون‌ریزی شود.\nتاریخ نسخه‌ها و نام ویرایش‌کنندگان ثابت خواهد ماند.\nاطلاعات مربوط به درون‌ریزی صفحات در [[Special:Log/import|سیاههٔ درون‌ریزی‌ها]] درج خواهد شد.",
+       "importinterwiki": "درÙ\88Ù\86â\80\8cرÛ\8cزÛ\8c Ø§Ø² Û\8cÚ© Ù\88Û\8cÚ©Û\8c Ø¯Û\8cگر",
+       "import-interwiki-text": "Û\8cÚ© Ù\88Û\8cÚ©Û\8c Ù\88 Û\8cÚ© Ù\86اÙ\85 ØµÙ\81Ø­Ù\87 Ø±Ø§ Ø§Ù\86تخاب Ú©Ù\86Û\8cد ØªØ§ Ø§Ø·Ù\84اعات Ø§Ø² Ø¢Ù\86 Ø¯Ø±Ù\88Ù\86â\80\8cرÛ\8cزÛ\8c Ø´Ù\88د.\nتارÛ\8cØ® Ù\86سخÙ\87â\80\8cÙ\87ا Ù\88 Ù\86اÙ\85 Ù\88Û\8cراÛ\8cØ´â\80\8cÚ©Ù\86Ù\86دگاÙ\86 Ø«Ø§Ø¨Øª Ø®Ù\88اÙ\87د Ù\85اÙ\86د.\nاطÙ\84اعات Ù\85ربÙ\88Ø· Ø¨Ù\87 Ø¯Ø±Ù\88Ù\86â\80\8cرÛ\8cزÛ\8c ØµÙ\81حات Ø§Ø² Ù\88Û\8cÚ©Û\8c Ø¯Û\8cگر Ø¯Ø± [[Special:Log/import|سÛ\8cاÙ\87Ù\87Ù\94 Ø¯Ø±Ù\88Ù\86â\80\8cرÛ\8cزÛ\8câ\80\8cÙ\87ا]] Ø¯Ø±Ø¬ Ø®Ù\88اÙ\87د Ø´Ø¯.",
        "import-interwiki-sourcewiki": "ویکی منبع:",
        "import-interwiki-sourcepage": "صفحهٔ مبدأ:",
        "import-interwiki-history": "تمام نسخه‌های تاریخچهٔ این صفحه انتقال داده شود",
        "importcantopen": "پروندهٔ درون‌ریزی صفحات باز نشد",
        "importbadinterwiki": "پیوند میان‌ویکی نادرست",
        "importsuccess": "درون‌ریزی با موفقیت انجام شد!",
-       "importnosources": "هیچ منبعی برای درون‌ریزی اطلاعات از ویکی دیگر تعریف نشده‌است.",
+       "importnosources": "هیچ منبعی برای درون‌ریزی اطلاعات از ویکی‌های دیگر تعریف نشده‌است.",
        "importnofile": "هیچ پرونده‌ای برای درون‌ریزی بارگذاری نشده‌است.",
        "importuploaderrorsize": "در بارگذاری پروندهٔ درون‌ریزی، اشکال رخ داد.\nاندازهٔ پرونده بیشتر از حداکثر اندازهٔ مجاز است.",
        "importuploaderrorpartial": "در بارگذاری پروندهٔ درون‌ریزی، اشکال رخ داد. پرونده به طور ناقص بارگذاری شده‌است.",
        "tags-tag": "نام برچسب",
        "tags-display-header": "نمایش در فهرست‌های تغییرات",
        "tags-description-header": "توضیح کامل معنی",
+       "tags-source-header": "منبع",
        "tags-active-header": "فعال؟",
        "tags-hitcount-header": "تغییرهای برچسب‌دار",
+       "tags-actions-header": "فعالیت‌ها",
        "tags-active-yes": "بله",
        "tags-active-no": "خیر",
+       "tags-source-extension": "تعریف‌شده بر پایه افزونه",
+       "tags-source-manual": "اعمال شده به صورت دستی توسط ربات‌ها یا کاربرها",
+       "tags-source-none": "دیگر استفاده نمی‌شود",
        "tags-edit": "ویرایش",
+       "tags-delete": "حذف",
+       "tags-activate": "فعال‌سازی",
+       "tags-deactivate": "غیرفعال‌سازی",
        "tags-hitcount": "$1 {{PLURAL:$1|تغییر|تغییر}}",
+       "tags-manage-no-permission": "شما اجازه مدیریت تغییر تگ‌ها را ندارید.",
+       "tags-create-heading": "ایجاد یک برچسب جدید",
+       "tags-create-explanation": "به طور پیش‌فرض، تگ‌های تازه ایجاد شده برای استفاده کاربران و ربات‌ها در دسترس قرار می‌گیرند.",
+       "tags-create-tag-name": "نام برچسب:",
+       "tags-create-reason": "دلیل:",
+       "tags-create-submit": "ایجاد",
+       "tags-create-no-name": "نام تگ باید مشخص شود.",
+       "tags-create-invalid-chars": "نام تگ‌ها نباید حاوی کاما (<code>,</code>) یا خط مورب (<code>/</code>) باشد.",
+       "tags-create-invalid-title-chars": "نام تگ‌ها نباید شامل حروفی شود که نمی‌توان از آن‌ها در عنوان صفحات استفاده کرد.",
+       "tags-create-already-exists": "تگ \"$1\" هم‌اکنون موجود است.",
+       "tags-create-warnings-above": "در هنگام ایجاد تگ \"$1\" با {{PLURAL:$2|هشدار|هشدارهای}} زیر پیش آمد:",
+       "tags-create-warnings-below": "آیا مایل به ادامه ایجاد تگ هستید؟",
+       "tags-delete-title": "حذف برچسب",
+       "tags-delete-explanation-initial": "شما در حال حذف تگ «$1» از پایگاه داده هستید.",
+       "tags-delete-explanation-warning": "این عمل <strong>غیر قابل بازگشت</strong> است، حتی توسط مدیران پایگاه داده. مطمئن باشید که این همان تگی است که می‌خواهید آن‌را حذف کنید.",
+       "tags-delete-reason": "دلیل:",
+       "tags-delete-submit": "این تگ را به‌صورت غیرقابل بازگشت حذف کن",
+       "tags-delete-not-found": "تگ «$1» وجود ندارد.",
+       "tags-activate-title": "فعال‌سازی برچسب",
+       "tags-activate-question": "شما در حال فعال‌سازی تگ «$1» هستید.",
+       "tags-activate-reason": "دلیل:",
+       "tags-activate-not-allowed": "فعال‌سازی تگ «$1» ممکن نیست.",
+       "tags-activate-not-found": "تگ «$1» وجود ندارد.",
+       "tags-activate-submit": "فعال‌سازی",
+       "tags-deactivate-title": "غیرفعال‌سازی برچسب",
+       "tags-deactivate-question": "شما در حال غیرفعال‌سازی تگ «$1» هستید.",
+       "tags-deactivate-reason": "دلیل:",
+       "tags-deactivate-not-allowed": "غیرفعال‌سازی تگ «$1» ممکن نیست.",
+       "tags-deactivate-submit": "غیرفعال‌سازی",
        "comparepages": "مقایسهٔ صفحات",
        "compare-page1": "صفحهٔ ۱",
        "compare-page2": "صفحهٔ ۲",
        "logentry-upload-upload": "$1 $3 را {{GENDER:$2|بارگذاری کرد}}",
        "logentry-upload-overwrite": "$1 نسخهٔ تازه‌ای از $3 را {{GENDER:$2|بارگذاری کرد}}",
        "logentry-upload-revert": "$1 {{GENDER:$2|بارگذاری کرد}} $3",
+       "log-name-managetags": "تاریخچه مدیریت تگ",
+       "logentry-managetags-create": "$1 برچسب «$4» را {{GENDER:$2|ایجاد کرد}}",
        "rightsnone": "(هیچ)",
        "revdelete-summary": "خلاصه ویرایش",
        "feedback-bugornote": "اگر آماده‌اید تا مشکلی فنی را با جزئیاتش شرح دهید لطفاً [$1 یک ایراد گزارش دهید]. در غیر این صورت می‌توانید از فرم سادهٔ زیر استفاده کنید. نظر شما به همراه نام کاربری و مرورگرتان به صفحهٔ «[$3 $2]» افزوده خواهد شد.",
        "json-error-utf8": "نویسه‌های نادرست یوتی‌اف-۸، احتمالاً نادرست کدگذاری شده است",
        "json-error-recursion": "ارجاع بازگشتی یک یا بیشتر در مقداری که کذگذاری می‌شود",
        "json-error-inf-or-nan": "مقادیر INF یا NAN یک یا بیشتر در مقداری که کدگذاری می‌شود",
-       "json-error-unsupported-type": "یک مقداری نوعی که نمی‌تواند کدگذاری شود داده شده است"
+       "json-error-unsupported-type": "یک مقداری نوعی که نمی‌تواند کدگذاری شود داده شده است",
+       "headline-anchor-title": "پیوند به این قسمت"
 }
index 014f1e6..f5e4182 100644 (file)
        "thu": "Tö",
        "fri": "Fr",
        "sat": "Se",
-       "january": "Januar",
-       "february": "Feebruar",
+       "january": "Janewoore",
+       "february": "Febrewoore",
        "march": "Marts",
        "april": "April",
-       "may_long": "Moi",
-       "june": "Juuni",
+       "may_long": "Mei",
+       "june": "Jüüne",
        "july": "Juuli",
        "august": "August",
-       "september": "Septämber",
+       "september": "September",
        "october": "Oktoober",
-       "november": "Nomber",
-       "december": "Detsämber",
-       "january-gen": "Januar",
-       "february-gen": "Feebruar",
+       "november": "Nofember",
+       "december": "Detsember",
+       "january-gen": "Janewoore",
+       "february-gen": "Febrewoore",
        "march-gen": "Marts",
        "april-gen": "April",
-       "may-gen": "Moi",
+       "may-gen": "Mei",
        "june-gen": "Juuni",
        "july-gen": "Juuli",
        "august-gen": "August",
-       "september-gen": "Septämber",
+       "september-gen": "September",
        "october-gen": "Oktoober",
        "november-gen": "Nowämber",
-       "december-gen": "Detsämber",
+       "december-gen": "Detsember",
        "jan": "Jan.",
        "feb": "Feb.",
        "mar": "Mar.",
        "apr": "Apr.",
-       "may": "Moi",
+       "may": "Mei",
        "jun": "Jun.",
        "jul": "Jul.",
        "aug": "Aug.",
        "sep": "Sep.",
        "oct": "Okt.",
-       "nov": "Now.",
+       "nov": "Nof.",
        "dec": "Det.",
        "january-date": "$1. Janewoore",
        "february-date": "$1. Febrewoore",
        "accmailtitle": "Paaswurd as ferschüürd wurden.",
        "accmailtext": "En tufelag iinracht paaswurd för [[User talk:$1|$1]] as tu $2 ferschüürd wurden. Det koon üüb det spezial-sidj ''[[Special:ChangePassword|Paaswurd anre]]'' feranert wurd, wan dü uunmeldet beest.",
        "newarticle": "(Nei)",
-       "newarticletext": "Dü beest en ferwisang tu en sidj fulagt, diar't noch ei jaft.\nAm det sidj iinturachten, skriiw dan tekst uun det fial för't bewerkin iin.\nÜüb det [$1 halepsidj] fanjst dü halep.\nWan dü ütj fersen heer beest, trak ianfach üüb di '''turag'''-knoop faan dan browser.",
+       "newarticletext": "Dü beest en ferwisang tu en sidj fulagt, diar't noch ei jaft.\nAm det sidj iinturachten, skriiw dan tekst uun det fial för't bewerkin iin.\nÜüb det [$1 halepsidj] fanjst dü halep.\nWan dü ütj fersen heer beest, trak ianfach üüb di <strong>turag</strong>-knoop faan dan browser.",
        "anontalkpagetext": "----''Üüb detheer sidj könst dü en ünbekäänden brüker en nooracht du. Det lääpt auer sin IP adres. IP adresen kön faan flook brükern brükt wurd. Wan dü mä detheer nooracht niks began könst, do as det ferlicht för hoker ööders mend weesen. Dü säärst niks widjer onernem. Wan dü en aanj [[Special:UserLogin/signup|brükerkonto iinrachst]] of di [[Special:UserLogin|uunmeldest]], komt sowat ei weder föör.",
        "noarticletext": "Üüb detdiar sidj stäänt noch niks.\nDü könst didiar tiitel üüb ööder sidjen [[Special:Search/{{PAGENAME}}|schük]],\n<span class=\"plainlinks\">uun [{{fullurl:{{#special:Log}}|page={{FULLPAGENAMEE}}}} logbuken schük] of detdiar sidj [{{fullurl:{{FULLPAGENAME}}|action=edit}} bewerke]</span>.",
        "noarticletext-nopermission": "Üüb detdiar sidj stäänt noch niks, oober dü mutst diar uk niks iinskriiw.\nDü könst diar üüb ööder sidjen efter [[Special:Search/{{PAGENAME}}|schük]] of a <span class=\"plainlinks\">[{{fullurl:{{#special:Log}}|page={{FULLPAGENAME}}}} logbuken uunluke].</span>",
        "javascripttest-qunit-intro": "Luke efter bi [$1 test dokumentatjuun] üüb mediawiki.org",
        "tooltip-pt-userpage": "Din brükersidj",
        "tooltip-pt-anonuserpage": "Brükersidj faan det IP-adres, faan huar ütj dü werkest",
-       "tooltip-pt-mytalk": "Din diskusjuunssidj",
+       "tooltip-pt-mytalk": "Din diskuschuunssidj",
        "tooltip-pt-anontalk": "Diskuschuun auer feranrangen faan detdiar IP-adres",
        "tooltip-pt-preferences": "Min iinstelangen",
        "tooltip-pt-watchlist": "Sidjen, diar dü uun't uug behual wel",
index c27e987..4b1b64d 100644 (file)
        "readonly_lag": "A base de datos bloqueouse automaticamente mentres os servidores levan a cabo a sincronización co servidor principal",
        "internalerror": "Erro interno",
        "internalerror_info": "Erro interno: $1",
+       "internalerror-fatal-exception": "Excepción grave de tipo \"$1\"",
        "filecopyerror": "Non se puido copiar o ficheiro \"$1\" en \"$2\".",
        "filerenameerror": "Non se puido cambiar o nome do ficheiro \"$1\" a \"$2\".",
        "filedeleteerror": "Non se deu borrado o ficheiro \"$1\".",
        "unusedimages": "Imaxes sen uso",
        "wantedcategories": "Categorías requiridas",
        "wantedpages": "Páxinas requiridas",
+       "wantedpages-summary": "Lista de páxinas inexistentes con máis ligazóns cara a elas, excluíndo as páxinas que só teñen redireccións cara a elas. Para consultar a lista de páxinas inexistentes que teñen redireccións cara a elas, véxase [[{{#special:BrokenRedirects}}]].",
        "wantedpages-badtitle": "Título inválido fixado nos resultados: $1",
        "wantedfiles": "Ficheiros requiridos",
        "wantedfiletext-cat": "Os seguintes ficheiros están en uso, pero non existen. É posible que aparezan ficheiros de repositoroios externos, malia que existan. Calquera falso positivo estará <del>riscado</del>. Ademais, as páxinas que inclúen ficheiros que non existen están listadas en [[:$1]].",
        "thumbnail_image-missing": "Parece que falta o ficheiro: $1",
        "thumbnail_image-failure-limit": "Producíronse demasiados ($1 ou máis) intentos fallidos recentes de renderizar esta miniatura. Inténteo de novo máis tarde.",
        "import": "Importar páxinas",
-       "importinterwiki": "Importación transwiki",
-       "import-interwiki-text": "Seleccione o wiki e o título da páxina que queira importar.\nAs datas das revisións e os nomes dos editores manteranse.\nTodas as accións relacionadas coa importación entre wikis poden verse no [[Special:Log/import|rexistro de importacións]].",
+       "importinterwiki": "Importar doutro wiki",
+       "import-interwiki-text": "Seleccione o wiki e o título da páxina que queira importar.\nAs datas das revisións e os nomes dos editores manteranse.\nTodas as importacións doutros wikis poden consultarse no [[Special:Log/import|rexistro de importacións]].",
        "import-interwiki-sourcewiki": "Wiki de orixe:",
        "import-interwiki-sourcepage": "Páxina de orixe:",
        "import-interwiki-history": "Copiar todas as versións que hai no historial desta páxina",
        "importcantopen": "Non se pode abrir o ficheiro importado",
        "importbadinterwiki": "Ligazón interwiki incorrecta",
        "importsuccess": "A importación rematou!",
-       "importnosources": "Non se defininiu ningunha fonte de importación transwiki e os envíos directos dos historiais están desactivados.",
+       "importnosources": "Non se defininiu ningún wiki desde o que importar e os envíos directos dos historiais están desactivados.",
        "importnofile": "Non se enviou ningún ficheiro de importación.",
        "importuploaderrorsize": "Fallou o envío do ficheiro de importación. O ficheiro é máis grande que o tamaño de envío permitido.",
        "importuploaderrorpartial": "Fallou o envío do ficheiro de importación. O ficheiro só se enviou parcialmente.",
        "tags-create-invalid-chars": "Os nomes das etiquetas non poden conter nin comas (<code>,</code>) nin barras (<code>/</code>).",
        "tags-create-invalid-title-chars": "As páxinas non deben conter caracteres que non se poidan usar nos títulos das páxinas.",
        "tags-create-already-exists": "A páxina \"$1\" xa existe.",
+       "tags-create-warnings-above": "{{PLURAL:$2|Atopouse o seguinte erro|Atopáronse os seguintes erros}} ao intentar crear a etiqueta \"$1\":",
        "tags-create-warnings-below": "Desexa continuar creando a etiqueta?",
        "tags-delete-title": "Borrar etiqueta",
        "tags-delete-explanation-initial": "Está a piques de borrar a etiqueta \"$1\" da base de datos.",
+       "tags-delete-explanation-in-use": "Ha eliminarse {{PLURAL:$2|dunha revisión ou entrada|das $2 revisións e/ou entradas}} de rexistro {{PLURAL:$2|á|ás}} que actualmente se aplica.",
        "tags-delete-explanation-warning": "Esta acción é <strong>irreversible</strong> e nin sequera os administradores da base de datos poderán desfacela. Asegúrese de que é esta a etiqueta que desexa borrar.",
        "tags-delete-explanation-active": "<strong>A etiqueta \"$1\" segue activa e continuará aplicándose no futuro.</strong> Para evitalo, vaia ao(s) lugar(es) onde se establece a aplicación desta etiqueta e desactívea alí.",
        "tags-delete-reason": "Motivo:",
        "tags-delete-submit": "Eliminar esta etiqueta irreversiblemente",
        "tags-delete-not-allowed": "As etiquetas definidas por unha extensión non se poden borrar, agás que a extensión específica o permita.",
        "tags-delete-not-found": "A páxina \"$1\" non existe.",
-       "tags-delete-too-many-uses": "A etiqueta \"$1\" aplícase a máis de $2 {{PLURAL:$2|revision|revisions}}, polo que non pode borrarse.",
+       "tags-delete-too-many-uses": "A etiqueta \"$1\" aplícase a máis de $2 {{PLURAL:$2|revisión|revisións}}; isto significa que non se pode borrar.",
+       "tags-delete-warnings-after-delete": "A etiqueta \"$1\" borrouse correctamente; con todo, {{PLURAL:$2|atopouse o seguinte erro|atopáronse os seguintes erros}}:",
        "tags-activate-title": "Activar etiqueta",
        "tags-activate-question": "Está a piques de activar a etiqueta\"$1\".",
        "tags-activate-reason": "Motivo:",
        "revdelete-uname-unhid": "descubriu o nome de usuario",
        "revdelete-restricted": "aplicou restricións aos administradores",
        "revdelete-unrestricted": "eliminou restricións aos administradores",
+       "logentry-block-block": "$1 {{GENDER:$2|bloqueou}} a {{GENDER:$4|$3}} cun tempo de duración de $5 $6",
+       "logentry-block-unblock": "$1 {{GENDER:$2|desbloqueou}} a {{GENDER:$4|$3}}",
+       "logentry-block-reblock": "$1 {{GENDER:$2|cambiou}} as configuracións do bloqueo de {{GENDER:$4|$3}} cunha caducidade de $5 $6",
+       "logentry-suppress-block": "$1 {{GENDER:$2|bloqueou}} a {{GENDER:$4|$3}} cun tempo de duración de $5 $6",
+       "logentry-suppress-reblock": "$1 {{GENDER:$2|cambiou}} as configuracións do bloqueo de {{GENDER:$4|$3}} cunha caducidade de $5 $6",
        "logentry-merge-merge": "$1 {{GENDER:$2|fusionou}} \"$3\" con \"$4\" (revisións ata o $5)",
        "logentry-move-move": "$1 {{GENDER:$2|moveu}} a páxina \"$3\" a \"$4\"",
        "logentry-move-move-noredirect": "$1 {{GENDER:$2|moveu}} a páxina \"$3\" a \"$4\" sen deixar unha redirección",
        "log-name-managetags": "Rexistro de xestión de etiquetas",
        "log-description-managetags": "Esta páxina contén unha lista das tarefas de xestión relacionadas con [[Special:Tags|tags]]. No rexistro figuran só aquelas accións realizadas de forma manual por un administrador; pódense crear ou borrar etiquetas por medio do software wiki sen que se engada unha nova entrada ao rexistro.",
        "logentry-managetags-create": "$1 {{GENDER:$2|created}} a etiqueta \"$4\"",
+       "logentry-managetags-delete": "$1 {{GENDER:$2|borrou}} a etiqueta \"$4\" (eliminouse de $5 {{PLURAL:$5|revisión ou entrada de rexistro|revisións e/ou entradas de rexistro}})",
+       "logentry-managetags-activate": "$1 {{GENDER:$2|activou}} a etiqueta \"$4\" para o seu uso por usuarios e bots",
+       "logentry-managetags-deactivate": "$1 {{GENDER:$2|desactivou}} a etiqueta \"$4\" para impedir o seu uso por usuarios e bots",
        "rightsnone": "(ningún)",
        "revdelete-summary": "o resumo de edición",
        "feedback-bugornote": "Se está listo para describir un problema técnico en detalle, [$1 informe do erro].\nEn caso contrario, pode empregar o formulario sinxelo inferior. O seu comentario aparecerá na páxina \"[$3 $2]\" xunto ao seu nome de usuario e o navegador que está usando.",
        "json-error-utf8": "Hai caracteres UTF-8 incorrectos, trátase probablemente dun problema de codificación.",
        "json-error-recursion": "Atopáronse unha ou máis referencias recursivas no valor para codificar.",
        "json-error-inf-or-nan": "Atopáronse un ou máis valores NAN ou INF no valor para codificar.",
-       "json-error-unsupported-type": "Indicouse un valor dun tipo que non se pode codificar."
+       "json-error-unsupported-type": "Indicouse un valor dun tipo que non se pode codificar.",
+       "headline-anchor-title": "Ligazón a esta sección"
 }
index 2616a5e..b41d36e 100644 (file)
        "hidetoc": "藏",
        "collapsible-collapse": "摺",
        "collapsible-expand": "展",
+       "confirmable-confirm": "{{GENDER:$1|汝}}無悔?",
        "confirmable-yes": "是",
        "confirmable-no": "否",
        "thisisdeleted": "還$1或閱之?",
        "missingarticle-diff": "(異:$1,$2)",
        "internalerror": "家誤",
        "internalerror_info": "家誤:$1",
-       "filecopyerror": "\"$1\"謄\"$2\",未可為也。",
+       "filecopyerror": "謄\"$1\"至\"$2\",未可為也。",
        "filerenameerror": "\"$2\"替\"$1\"名,未可為也。",
        "filedeleteerror": "\"$1\"未可刪也。",
        "directorycreateerror": "立目\"$1\",未可為也。",
        "specialpages-group-wiki": "Wiki訊與器",
        "specialpages-group-redirects": "轉之特查",
        "specialpages-group-spam": "反垃圾之器",
+       "specialpages-group-developer": "造紙者之器",
        "blankpage": "白頁",
        "intentionallyblankpage": "此頁為白也,試速之用",
        "external_image_whitelist": " #同留<pre>\n#下(中之//)乃正表式\n#乃外(連)圖配之\n#配乃成像,非配則成連\n#有 # 之為注\n#無為大小之異也\n\n#入正表式。同留</pre>",
        "revdelete-summary": "摘",
        "searchsuggest-search": "尋",
        "pagelang-language": "語",
+       "default-skin-not-found": "嚄!君於<code dir=\"ltr\">$wgDefaultSkin</code>所設之膚無以用也。君所用版本,似需含膚下者也。可於MediaWiki之官網[https://www.mediawiki.org/wiki/Manual:Skin_configuration “設膚”]之冊,以知啟而許膚之法。\n\n$2\n\n; 若君安MediaWiki未幾:\n: 君或安自git庫。或以他法徑安自源始碼,若如此甚善。汝可試下者之法,自[https://www.mediawiki.org/wiki/Category:All_skins mediawiki.org之膚庫]安膚些許:\n:* 載下[https://www.mediawiki.org/wiki/Download/lzh 群安之器]。若依此道,則將预安膚與拓器些許。君可謄而貼<code>skins/</code>于焉。\n:* 自[https://www.mediawiki.org/wiki/Special:SkinDistributor mediawiki.org]獨載下安膚包。\n:* 以git徑謄自<code>mediawiki/skins/*</code>儲物库,至君MediaWiki副本之<code dir=\"ltr\">skins/</code>。\n: 若君MediaWiki開發者也,則為之應擾不及君之git儲物庫。\n\n; 若君MediaWiki新矣:\n: 自MediaWiki 1.24版本始,已安之膚不復自啟(見[https://www.mediawiki.org/wiki/Manual:Skin_autodiscovery 冊])。君可謄而貼字下者,至君圍紀之<code>LocalSettings.php</code>以啟膚已安者:\n\n<pre dir=\"ltr\">$3</pre>\n\n; 若君已改<code>LocalSettings.php</code>:\n: 请再查膚名,以保之無誤。",
        "mediastatistics-header-unknown": "未知",
        "mediastatistics-header-video": "映像",
        "json-error-syntax": "語法有誤"
index 5388f37..aa4b6d9 100644 (file)
        "readonly_lag": "De database is automatisch vergrendeld terwijl de ondergeschikte databaseservers synchroniseren met de hoofdserver.",
        "internalerror": "Interne fout",
        "internalerror_info": "Interne fout: $1",
+       "internalerror-fatal-exception": "Fatale fout van type \"$1\"",
        "filecopyerror": "Bestand \"$1\" kon niet naar \"$2\" gekopieerd worden.",
        "filerenameerror": "\"$1\" kon niet hernoemd worden naar \"$2\".",
        "filedeleteerror": "Bestand \"$1\" kon niet verwijderd worden.",
index c02cfe5..da318e6 100644 (file)
        "readonly_lag": "La base ëd dat a l'é staita blocà n'automàtich antramentr che le màchine dël sircùit secondari as buto an pari con cole dël prinsipal",
        "internalerror": "Eror intern",
        "internalerror_info": "Eror antern: $1",
+       "internalerror-fatal-exception": "Ecession fatal ëd tipo «$1»",
        "filecopyerror": "A l'é pa stàit possìbil copié l'archivi «$1» coma «$2».",
        "filerenameerror": "A l'é pa podusse cangeje nòm a l'archivi «$1» an «$2».",
        "filedeleteerror": "A l'é pa podusse scancelé l'archivi «$1».",
        "unusedimages": "Figure nen dovrà",
        "wantedcategories": "Categorìe dont a fa da manca",
        "wantedpages": "Artìcoj pì ciamà",
+       "wantedpages-summary": "Lista ëd pàgine nen esistente con ël pi grand nùmer ëd liure vers ëd lor, gavà le pàgine vers le quaj a ponto mach dle ridiression. Për na lista dle pàgine nen esistente a le quaj a ponto dle ridiression, vëdde [[{{#special:BrokenRedirects}}]].",
        "wantedpages-badtitle": "Tìtol nen vàlid ant l'ansema dj'arzultà: $1",
        "wantedfiles": "Archivi pì ciamà",
        "wantedfiletext-cat": "J'archivi ch'a ven-o a son dovrà ma a esisto pa. J'archivi dai sò depòsit estern a peulo esse listà sensa consideré l'esistensa. Chèich fàuss positiv a saran <del>sganfà</del>. An pi, le pàgine ch'a conten-o dj'archivi ch'a esisto pa a son listà an [[:$1]].",
        "thumbnail_image-missing": "L'archivi a smija ch'a manca: $1",
        "thumbnail_image-failure-limit": "A-i son ëstaje ëd recent tròpi tentativ falì ($1 o pi) ëd rende costa plancia. Për piasì, ch'a preuva torna pi tard.",
        "import": "Amportassion ëd pàgine",
-       "importinterwiki": "Amportassion da wiki diferente",
-       "import-interwiki-text": "Che a selession-a na wiki e ël tìtol dla pàgina da amporté.\nDate dle revision e stranòm dj'editor a resteran piàjit sù 'cò lor.\nTute j'amportassion antra wiki diferente a resto marcà ant ël [[Special:Log/import|Registr dj'amportassion]].",
+       "importinterwiki": "Amportassion da n'àutra wiki",
+       "import-interwiki-text": "Che a selession-a na wiki e ël tìtol dla pàgina da amporté.\nDate dle revision e stranòm dj'editor a resteran piàjit sù 'cò lor.\nTute j'amportassion da d'àutre wiki a resto marcà ant ël [[Special:Log/import|Registr dj'amportassion]].",
        "import-interwiki-sourcewiki": "Wiki sorgiss:",
        "import-interwiki-sourcepage": "Pàgina sorgiss:",
        "import-interwiki-history": "Copié tute le revision ëd la stòria ëd costa pàgina",
        "importcantopen": "L'archivi da amporté a l'é pa podusse deurbe",
        "importbadinterwiki": "Liura antra wiki diferente cioca",
        "importsuccess": "Amportassion finìa!",
-       "importnosources": "A l'é pa stàita definìa gnun-a sorgiss d'amportassion da na wiki diferenta, e carié mach le stòrie as peul nen.",
+       "importnosources": "A l'é stàita definìa gnun-a wiki da la qual amporté, e carié mach le stòrie as peul nen.",
        "importnofile": "Pa gnun archivi d'amportassion carià.",
        "importuploaderrorsize": "A l'é falìe la caria dl'archivi d'amporté. L'archivi a resta pì gròss che lòn ch'as peul cariesse.",
        "importuploaderrorpartial": "A l'é falìe la caria dl'archivi d'amporté. L'archivi a resta carià mach për un tòch.",
        "tags-delete-submit": "Eliminé costa tichëtta ëd fasson ireversìbil",
        "tags-delete-not-allowed": "Le tichëtte definìe da n'estension a peulo nen esse dëscancelà, gavà che l'estension a lo permëtta ëd fasson esplìssita.",
        "tags-delete-not-found": "La tichëtta «$1» a esist pa.",
+       "tags-delete-too-many-uses": "La tichëtta «$1» a l'é aplicà a pi che $2 {{PLURAL:$2|revision}}, lòn ch'a veul dì ch'a peul nen esse eliminà.",
+       "tags-delete-warnings-after-delete": "La tichëtta «$1» a l'é stàita eliminà për da bin, ma {{PLURAL:$2|a l'é rancontrasse l'|as son rancontrasse j'}}avis sì-dapress:",
+       "tags-activate-title": "Ativé la tichëtta",
+       "tags-activate-question": "A l'é a brus d'ativé la tichëtta «$1».",
+       "tags-activate-reason": "Rason:",
+       "tags-activate-not-allowed": "A l'é nen possìbil ativé la tichëtta «$1».",
+       "tags-activate-not-found": "La tichëtta «$1» a esist nen.",
+       "tags-activate-submit": "Ativé",
        "comparepages": "Confronté dle pàgine",
        "compare-page1": "Pàgina 1",
        "compare-page2": "Pàgina 2",
index 2a7d860..b6fcb4a 100644 (file)
        "readonly_lag": "Baza de date a fost închisă automatic în timp ce serverele secundare ale bazei de date îl urmează pe cel principal.",
        "internalerror": "Eroare internă",
        "internalerror_info": "Eroare internă: $1",
+       "internalerror-fatal-exception": "Excepție fatală pentru tipul „$1”",
        "filecopyerror": "Fișierul \"$1\" nu a putut fi copiat la \"$2\".",
        "filerenameerror": "Fișierul \"$1\" nu a putut fi mutat la \"$2\".",
        "filedeleteerror": "Fișierul \"$1\" nu a putut fi șters.",
        "thumbnail_image-missing": "Fișierul următor nu poate fi găsit: $1",
        "thumbnail_image-failure-limit": "Recent au existat prea multe încercări nereușite ($1 sau mai multe) pentru a randa această miniatură. Încercați din nou mai târziu.",
        "import": "Importare pagini",
-       "importinterwiki": "Import transwiki",
-       "import-interwiki-text": "Selectează un wiki și titlul paginii care trebuie importate. Datele reviziilor și numele editorilor vor fi salvate. Toate acțiunile de import transwiki pot fi găsite la [[Special:Log/import|log import]]",
+       "importinterwiki": "Importare din alt wiki",
+       "import-interwiki-text": "Selectați un wiki și titlul paginii care trebuie importate.\nData și ora versiunilor, precum și numele editorilor vor fi păstrate.\nToate acțiunile de importare din alte wikiuri se găsesc în [[Special:Log/import|jurnalul de importare]].",
        "import-interwiki-sourcewiki": "Wikiul sursă:",
        "import-interwiki-sourcepage": "Pagina sursă:",
        "import-interwiki-history": "Copiază toate versiunile istoricului acestei pagini",
        "importcantopen": "Fișierul importat nu a putut fi deschis",
        "importbadinterwiki": "Legătură interwiki greșită",
        "importsuccess": "Import reușit!",
-       "importnosources": "Nici o sursă de import transwiki a fost definită și încărcările directe ale istoricului sunt oprite.",
+       "importnosources": "Nu a fost definită nici o sursă de import din alt wiki; încărcarea directă a istoricului este dezactivată.",
        "importnofile": "Nici un fișier pentru import nu a fost încărcat.",
        "importuploaderrorsize": "Încărcarea fișierului a eșuat.\nFișierul are o mărime mai mare decât limita de încărcare permisă.",
        "importuploaderrorpartial": "Încărcarea fișierului a eșuat.\nFișierul a fost incărcat parțial.",
index cc8fdf5..b70f20a 100644 (file)
@@ -1,12 +1,12 @@
 /*!
- * OOjs UI v0.8.0
+ * OOjs UI v0.8.1
  * https://www.mediawiki.org/wiki/OOjs_UI
  *
  * Copyright 2011–2015 OOjs Team and other contributors.
  * Released under the MIT license
  * http://oojs.mit-license.org
  *
- * Date: 2015-02-19T01:33:21Z
+ * Date: 2015-02-26T02:10:42Z
  */
 .oo-ui-progressBarWidget-slide-frames from {
        margin-left: -40%;
 }
 .oo-ui-fieldLayout.oo-ui-fieldLayout-align-inline.oo-ui-labelElement > .oo-ui-fieldLayout-body > .oo-ui-labelElement-label {
        padding: 0.5em;
+       padding-left: 1em;
 }
 .oo-ui-fieldLayout.oo-ui-fieldLayout-align-inline > .oo-ui-fieldLayout-body > .oo-ui-fieldLayout-field {
        padding: 0.5em 0;
        padding: 0.5em 0.75em;
        line-height: 1.5em;
 }
-.oo-ui-fieldsetLayout + .oo-ui-fieldsetLayout {
+.oo-ui-fieldsetLayout + .oo-ui-fieldsetLayout,
+.oo-ui-fieldsetLayout + .oo-ui-formLayout {
        margin-top: 2em;
 }
 .oo-ui-fieldsetLayout > .oo-ui-labelElement-label {
 .oo-ui-fieldsetLayout > .oo-ui-popupButtonWidget:last-child {
        margin-right: 0;
 }
+.oo-ui-formLayout + .oo-ui-fieldsetLayout,
+.oo-ui-formLayout + .oo-ui-formLayout {
+       margin-top: 2em;
+}
 .oo-ui-gridLayout {
        position: absolute;
        top: 0;
 }
 .oo-ui-radioOptionWidget {
        cursor: default;
-       padding: 0.25em 0;
+       padding: 0;
        background-color: transparent;
 }
 .oo-ui-radioOptionWidget .oo-ui-radioInputWidget,
 .oo-ui-radioOptionWidget.oo-ui-optionWidget-highlighted {
        background-color: transparent;
 }
+.oo-ui-radioOptionWidget.oo-ui-labelElement .oo-ui-labelElement-label {
+       padding: 0.25em;
+       padding-left: 1em;
+}
+.oo-ui-radioOptionWidget .oo-ui-radioInputWidget {
+       margin-right: 0;
+}
 .oo-ui-labelWidget {
        display: inline-block;
 }
 }
 .oo-ui-checkboxInputWidget input[type="checkbox"] {
        opacity: 0;
-       position: relative;
        z-index: 1;
+       position: relative;
        margin: 0;
        width: 1.6em;
        height: 1.6em;
 }
 .oo-ui-checkboxInputWidget input[type="checkbox"] + span {
        cursor: pointer;
-       margin: 0 0.2em;
-}
-.oo-ui-checkboxInputWidget input[type="checkbox"] + span::before {
        -webkit-transition: background-size 0.2s cubic-bezier(0.175, 0.885, 0.32, 1.275);
           -moz-transition: background-size 0.2s cubic-bezier(0.175, 0.885, 0.32, 1.275);
            -ms-transition: background-size 0.2s cubic-bezier(0.175, 0.885, 0.32, 1.275);
             -o-transition: background-size 0.2s cubic-bezier(0.175, 0.885, 0.32, 1.275);
                transition: background-size 0.2s cubic-bezier(0.175, 0.885, 0.32, 1.275);
-       content: "";
        -webkit-box-sizing: border-box;
           -moz-box-sizing: border-box;
                box-sizing: border-box;
        background-origin: border-box;
        background-size: 0 0;
 }
-.oo-ui-checkboxInputWidget input[type="checkbox"]:checked + span::before {
+.oo-ui-checkboxInputWidget input[type="checkbox"]:checked + span {
        background-size: 100% 100%;
 }
-.oo-ui-checkboxInputWidget input[type="checkbox"]:active + span::before {
+.oo-ui-checkboxInputWidget input[type="checkbox"]:active + span {
        background-color: #dddddd;
        border-color: #dddddd;
 }
-.oo-ui-checkboxInputWidget input[type="checkbox"]:focus + span::before {
+.oo-ui-checkboxInputWidget input[type="checkbox"]:focus + span {
        border-width: 2px;
 }
-.oo-ui-checkboxInputWidget input[type="checkbox"]:focus:hover + span::before,
-.oo-ui-checkboxInputWidget input[type="checkbox"]:hover + span::before {
+.oo-ui-checkboxInputWidget input[type="checkbox"]:focus:hover + span,
+.oo-ui-checkboxInputWidget input[type="checkbox"]:hover + span {
        border-bottom-width: 3px;
 }
-.oo-ui-checkboxInputWidget input[type="checkbox"]:disabled + span::before {
+.oo-ui-checkboxInputWidget input[type="checkbox"]:disabled + span {
        cursor: default;
        background-color: #eeeeee;
        border-color: #eeeeee;
 }
-.oo-ui-checkboxInputWidget input[type="checkbox"]:disabled:checked + span::before {
+.oo-ui-checkboxInputWidget input[type="checkbox"]:disabled:checked + span {
        background-image: url("themes/mediawiki/images/icons/check-invert.png");
        background-image: -webkit-linear-gradient(transparent, transparent), /* @embed */ url("themes/mediawiki/images/icons/check-invert.svg");
        background-image:         linear-gradient(transparent, transparent), /* @embed */ url("themes/mediawiki/images/icons/check-invert.svg");
 }
 .oo-ui-radioInputWidget input[type="radio"] {
        opacity: 0;
-       position: relative;
        z-index: 1;
+       position: relative;
        margin: 0;
        width: 1.6em;
        height: 1.6em;
 }
 .oo-ui-radioInputWidget input[type="radio"] + span {
        cursor: pointer;
-       margin: 0 0.2em;
-}
-.oo-ui-radioInputWidget input[type="radio"] + span::before {
        -webkit-transition: background-size 0.2s cubic-bezier(0.175, 0.885, 0.32, 1.275);
           -moz-transition: background-size 0.2s cubic-bezier(0.175, 0.885, 0.32, 1.275);
            -ms-transition: background-size 0.2s cubic-bezier(0.175, 0.885, 0.32, 1.275);
             -o-transition: background-size 0.2s cubic-bezier(0.175, 0.885, 0.32, 1.275);
                transition: background-size 0.2s cubic-bezier(0.175, 0.885, 0.32, 1.275);
-       content: "";
        -webkit-box-sizing: border-box;
           -moz-box-sizing: border-box;
                box-sizing: border-box;
        background-origin: border-box;
        background-size: 0 0;
 }
-.oo-ui-radioInputWidget input[type="radio"]:checked + span::before {
+.oo-ui-radioInputWidget input[type="radio"]:checked + span {
        background-size: 100% 100%;
 }
-.oo-ui-radioInputWidget input[type="radio"]:active + span::before {
+.oo-ui-radioInputWidget input[type="radio"]:active + span {
        background-color: #dddddd;
        border-color: #dddddd;
 }
-.oo-ui-radioInputWidget input[type="radio"]:focus + span::before {
+.oo-ui-radioInputWidget input[type="radio"]:focus + span {
        border-width: 2px;
 }
-.oo-ui-radioInputWidget input[type="radio"]:focus:hover + span::before,
-.oo-ui-radioInputWidget input[type="radio"]:hover + span::before {
+.oo-ui-radioInputWidget input[type="radio"]:focus:hover + span,
+.oo-ui-radioInputWidget input[type="radio"]:hover + span {
        border-bottom-width: 3px;
 }
-.oo-ui-radioInputWidget input[type="radio"]:disabled + span::before {
+.oo-ui-radioInputWidget input[type="radio"]:disabled + span {
        cursor: default;
        background-color: #eeeeee;
        border-color: #eeeeee;
 }
-.oo-ui-radioInputWidget input[type="radio"]:disabled:checked + span::before {
+.oo-ui-radioInputWidget input[type="radio"]:disabled:checked + span {
        background-image: url("themes/mediawiki/images/icons/circle-invert.png");
        background-image: -webkit-linear-gradient(transparent, transparent), /* @embed */ url("themes/mediawiki/images/icons/circle-invert.svg");
        background-image:         linear-gradient(transparent, transparent), /* @embed */ url("themes/mediawiki/images/icons/circle-invert.svg");
        top: 0;
        height: 100%;
        background-repeat: no-repeat;
-       cursor: pointer;
        -webkit-touch-callout: none;
        -webkit-user-select: none;
           -moz-user-select: none;
            -ms-user-select: none;
                user-select: none;
 }
+.oo-ui-textInputWidget.oo-ui-widget-enabled > .oo-ui-iconElement-icon,
+.oo-ui-textInputWidget.oo-ui-widget-enabled > .oo-ui-indicatorElement-indicator {
+       cursor: pointer;
+}
 .oo-ui-textInputWidget.oo-ui-labelElement > .oo-ui-labelElement-label {
        display: block;
 }
        border-color: #dddddd;
        background-color: #f3f3f3;
 }
+.oo-ui-textInputWidget.oo-ui-widget-disabled .oo-ui-iconElement-icon,
+.oo-ui-textInputWidget.oo-ui-widget-disabled .oo-ui-indicatorElement-indicator {
+       opacity: 0.2;
+}
+.oo-ui-textInputWidget.oo-ui-widget-disabled .oo-ui-labelElement-label {
+       color: #dddddd;
+       text-shadow: 0 1px 1px #ffffff;
+}
 .oo-ui-textInputWidget.oo-ui-pendingElement-pending input,
 .oo-ui-textInputWidget.oo-ui-pendingElement-pending textarea {
        background-color: transparent;
index 3be2d1b..e387364 100644 (file)
@@ -1,12 +1,12 @@
 /*!
- * OOjs UI v0.8.0
+ * OOjs UI v0.8.1
  * https://www.mediawiki.org/wiki/OOjs_UI
  *
  * Copyright 2011–2015 OOjs Team and other contributors.
  * Released under the MIT license
  * http://oojs.mit-license.org
  *
- * Date: 2015-02-19T01:33:11Z
+ * Date: 2015-02-26T02:10:32Z
  */
 /**
  * @class
index 0ad88fe..b4593d6 100644 (file)
@@ -1,12 +1,12 @@
 /*!
- * OOjs UI v0.8.0
+ * OOjs UI v0.8.1
  * https://www.mediawiki.org/wiki/OOjs_UI
  *
  * Copyright 2011–2015 OOjs Team and other contributors.
  * Released under the MIT license
  * http://oojs.mit-license.org
  *
- * Date: 2015-02-19T01:33:11Z
+ * Date: 2015-02-26T02:10:32Z
  */
 ( function ( OO ) {
 
@@ -326,9 +326,9 @@ OO.ui.PendingElement.prototype.popPending = function () {
  *
  *     ProcessDialog.prototype.initialize = function () {
  *         ProcessDialog.super.prototype.initialize.apply( this, arguments );
- *         this.panel1 = new OO.ui.PanelLayout( { $: this.$, padded: true, expanded: false } );
+ *         this.panel1 = new OO.ui.PanelLayout( { padded: true, expanded: false } );
  *         this.panel1.$element.append( '<p>This dialog uses an action set (continue, help, cancel, back) configured with modes. This is edit mode. Click \'help\' to see help mode. </p>' );
- *         this.panel2 = new OO.ui.PanelLayout( { $: this.$, padded: true, expanded: false } );
+ *         this.panel2 = new OO.ui.PanelLayout( { padded: true, expanded: false } );
  *         this.panel2.$element.append( '<p>This is help mode. Only the \'back\' action widget is configured to be visible here. Click \'back\' to return to \'edit\' mode</p>' );
  *         this.stackLayout= new OO.ui.StackLayout( {
  *             items: [ this.panel1, this.panel2 ]
@@ -788,11 +788,18 @@ OO.ui.ActionSet.prototype.organize = function () {
  *
  * @constructor
  * @param {Object} [config] Configuration options
- * @cfg {string[]} [classes] CSS class names to add
- * @cfg {string} [id] HTML id attribute
+ * @cfg {string[]} [classes] The names of the CSS classes to apply to the element. CSS styles are added
+ *  to the top level (e.g., the outermost div) of the element. See the [OOjs UI documentation on MediaWiki][2]
+ *  for an example.
+ *  [2]: https://www.mediawiki.org/wiki/OOjs_UI/Widgets/Buttons_and_Switches#cssExample
+ * @cfg {string} [id] The HTML id attribute used in the rendered tag.
  * @cfg {string} [text] Text to insert
- * @cfg {jQuery} [$content] Content elements to append (after text)
- * @cfg {Mixed} [data] Element data
+ * @cfg {Array} [content] An array of content elements to append (after #text).
+ *  Strings will be html-escaped; use an OO.ui.HtmlSnippet to append raw HTML.
+ *  Instances of OO.ui.Element will have their $element appended.
+ * @cfg {jQuery} [$content] Content elements to append (after #text)
+ * @cfg {Mixed} [data] Custom data of any type or combination of types (e.g., string, number, array, object).
+ *  Data can also be specified with the #setData method.
  */
 OO.ui.Element = function OoUiElement( config ) {
        // Configuration initialization
@@ -800,8 +807,10 @@ OO.ui.Element = function OoUiElement( config ) {
 
        // Properties
        this.$ = $;
+       this.visible = true;
        this.data = config.data;
-       this.$element = $( document.createElement( this.getTagName() ) );
+       this.$element = config.$element ||
+               $( document.createElement( this.getTagName() ) );
        this.elementGroup = null;
        this.debouncedUpdateThemeClassesHandler = this.debouncedUpdateThemeClasses.bind( this );
        this.updateThemeClassesPending = false;
@@ -816,7 +825,25 @@ OO.ui.Element = function OoUiElement( config ) {
        if ( config.text ) {
                this.$element.text( config.text );
        }
+       if ( config.content ) {
+               // The `content` property treats plain strings as text; use an
+               // HtmlSnippet to append HTML content.  `OO.ui.Element`s get their
+               // appropriate $element appended.
+               this.$element.append( config.content.map( function ( v ) {
+                       if ( typeof v === 'string' ) {
+                               // Escape string so it is properly represented in HTML.
+                               return document.createTextNode( v );
+                       } else if ( v instanceof OO.ui.HtmlSnippet ) {
+                               // Bypass escaping.
+                               return v.toString();
+                       } else if ( v instanceof OO.ui.Element ) {
+                               return v.$element;
+                       }
+                       return v;
+               } ) );
+       }
        if ( config.$content ) {
+               // The `$content` property treats plain strings as HTML.
                this.$element.append( config.$content );
        }
 };
@@ -828,9 +855,9 @@ OO.initClass( OO.ui.Element );
 /* Static Properties */
 
 /**
- * HTML tag name.
+ * The name of the HTML tag used by the element.
  *
- * This may be ignored if #getTagName is overridden.
+ * The static value may be ignored if the #getTagName method is overridden.
  *
  * @static
  * @inheritable
@@ -1239,6 +1266,34 @@ OO.ui.Element.static.reconsiderScrollbars = function ( el ) {
 
 /* Methods */
 
+/**
+ * Toggle visibility of an element.
+ *
+ * @param {boolean} [show] Make element visible, omit to toggle visibility
+ * @fires visible
+ * @chainable
+ */
+OO.ui.Element.prototype.toggle = function ( show ) {
+       show = show === undefined ? !this.visible : !!show;
+
+       if ( show !== this.isVisible() ) {
+               this.visible = show;
+               this.$element.toggleClass( 'oo-ui-element-hidden', !this.visible );
+               this.emit( 'toggle', show );
+       }
+
+       return this;
+};
+
+/**
+ * Check if element is visible.
+ *
+ * @return {boolean} element is visible
+ */
+OO.ui.Element.prototype.isVisible = function () {
+       return this.visible;
+};
+
 /**
  * Get element data.
  *
@@ -1430,7 +1485,6 @@ OO.ui.Widget = function OoUiWidget( config ) {
        OO.EventEmitter.call( this );
 
        // Properties
-       this.visible = true;
        this.disabled = null;
        this.wasDisabled = null;
 
@@ -1467,15 +1521,6 @@ OO.ui.Widget.prototype.isDisabled = function () {
        return this.disabled;
 };
 
-/**
- * Check if widget is visible.
- *
- * @return {boolean} Widget is visible
- */
-OO.ui.Widget.prototype.isVisible = function () {
-       return this.visible;
-};
-
 /**
  * Set the disabled state of the widget.
  *
@@ -1501,25 +1546,6 @@ OO.ui.Widget.prototype.setDisabled = function ( disabled ) {
        return this;
 };
 
-/**
- * Toggle visibility of widget.
- *
- * @param {boolean} [show] Make widget visible, omit to toggle visibility
- * @fires visible
- * @chainable
- */
-OO.ui.Widget.prototype.toggle = function ( show ) {
-       show = show === undefined ? !this.visible : !!show;
-
-       if ( show !== this.isVisible() ) {
-               this.visible = show;
-               this.$element.toggleClass( 'oo-ui-element-hidden', !this.visible );
-               this.emit( 'toggle', show );
-       }
-
-       return this;
-};
-
 /**
  * Update the disabled state, in case of changes in parent widget.
  *
@@ -1859,25 +1885,6 @@ OO.ui.Window.prototype.getTeardownProcess = function () {
        return new OO.ui.Process();
 };
 
-/**
- * Toggle visibility of window.
- *
- * @param {boolean} [show] Make window visible, omit to toggle visibility
- * @fires toggle
- * @chainable
- */
-OO.ui.Window.prototype.toggle = function ( show ) {
-       show = show === undefined ? !this.visible : !!show;
-
-       if ( show !== this.isVisible() ) {
-               this.visible = show;
-               this.$element.toggleClass( 'oo-ui-element-hidden', !this.visible );
-               this.emit( 'toggle', show );
-       }
-
-       return this;
-};
-
 /**
  * Set the window manager.
  *
@@ -2915,7 +2922,7 @@ OO.ui.WindowManager.prototype.addWindows = function ( windows ) {
                        }
                        list[ name ] = windows[ i ];
                }
-       } else if ( $.isPlainObject( windows ) ) {
+       } else if ( OO.isPlainObject( windows ) ) {
                list = windows;
        }
 
@@ -3078,7 +3085,13 @@ OO.ui.WindowManager.prototype.destroy = function () {
  * @cfg {boolean} [recoverable=true] Error is recoverable
  * @cfg {boolean} [warning=false] Whether this error is a warning or not.
  */
-OO.ui.Error = function OoUiElement( message, config ) {
+OO.ui.Error = function OoUiError( message, config ) {
+       // Allow passing positional parameters inside the config object
+       if ( OO.isPlainObject( message ) && config === undefined ) {
+               config = message;
+               message = config.message;
+       }
+
        // Configuration initialization
        config = config || {};
 
@@ -3132,6 +3145,114 @@ OO.ui.Error.prototype.getMessageText = function () {
        return this.message instanceof jQuery ? this.message.text() : this.message;
 };
 
+/**
+ * Wraps an HTML snippet for use with configuration values which default
+ * to strings.  This bypasses the default html-escaping done to string
+ * values.
+ *
+ * @class
+ *
+ * @constructor
+ * @param {string} [content] HTML content
+ */
+OO.ui.HtmlSnippet = function OoUiHtmlSnippet( content ) {
+       // Properties
+       this.content = content;
+};
+
+/* Setup */
+
+OO.initClass( OO.ui.HtmlSnippet );
+
+/* Methods */
+
+/**
+ * Render into HTML.
+ *
+ * @return {string} Unchanged HTML snippet.
+ */
+OO.ui.HtmlSnippet.prototype.toString = function () {
+       return this.content;
+};
+
+/**
+ * Reconstitute a JavaScript object corresponding to a widget created
+ * by the PHP implementation.
+ *
+ * @member OO.ui
+ * @param {string|HTMLElement|jQuery} idOrNode
+ *   A DOM id (if a string) or node for the widget to infuse.
+ * @return {OO.ui.Element}
+ *   The `OO.ui.Element` corresponding to this (infusable) document node.
+ *   For `Tag` objects emitted on the HTML side (used occasionally for content)
+ *   the value returned is a newly-created Element wrapping around the existing
+ *   DOM node.
+ */
+OO.ui.infuse = function ( idOrNode, dontReplace ) {
+       // look for a cached result of a previous infusion.
+       var id, $elem, data, cls, obj;
+       if ( typeof idOrNode === 'string' ) {
+               id = idOrNode;
+               $elem = $( document.getElementById( id ) );
+       } else {
+               $elem = $( idOrNode );
+               id = $elem.attr( 'id' );
+       }
+       data = $elem.data( 'ooui-infused' );
+       if ( data ) {
+               // cached!
+               if ( data === true ) {
+                       throw new Error( 'Circular dependency! ' + id );
+               }
+               return data;
+       }
+       if ( !$elem.length ) {
+               throw new Error( 'Widget not found: ' + id );
+       }
+       data = $elem.attr( 'data-ooui' );
+       if ( !data ) {
+               throw new Error( 'No infusion data found: ' + id );
+       }
+       try {
+               data = $.parseJSON( data );
+       } catch ( _ ) {
+               data = null;
+       }
+       if ( !( data && data._ ) ) {
+               throw new Error( 'No valid infusion data found: ' + id );
+       }
+       if ( data._ === 'Tag' ) {
+               // Special case: this is a raw Tag; wrap existing node, don't rebuild.
+               return new OO.ui.Element( { $element: $elem } );
+       }
+       cls = OO.ui[data._];
+       if ( !cls ) {
+               throw new Error( 'Unknown widget type: ' + id );
+       }
+       $elem.data( 'ooui-infused', true ); // prevent loops
+       data.id = id; // implicit
+       data = OO.copy( data, null, function deserialize( value ) {
+               if ( OO.isPlainObject( value ) ) {
+                       if ( value.tag ) {
+                               return OO.ui.infuse( value.tag, 'rebuilding' );
+                       }
+                       if ( value.html ) {
+                               return new OO.ui.HtmlSnippet( value.html );
+                       }
+               }
+       } );
+       // jscs:disable requireCapitalizedConstructors
+       obj = new cls( data ); // rebuild widget
+       // now replace old DOM with this new DOM.
+       if ( !dontReplace ) {
+               $elem.replaceWith( obj.$element );
+       }
+       obj.$element.data( 'ooui-infused', obj );
+       // set the 'data-ooui' attribute so we can identify infused widgets
+       obj.$element.attr( 'data-ooui', '' );
+       return obj;
+};
+
 /**
  * A list of functions, called in sequence.
  *
@@ -3501,7 +3622,30 @@ OO.ui.Theme.prototype.updateElementClasses = function ( element ) {
 };
 
 /**
- * Element supporting "sequential focus navigation" using the 'tabindex' attribute.
+ * The TabIndexedElement class is an attribute mixin used to add additional functionality to an
+ * element created by another class. The mixin provides a ‘tabIndex’ property, which specifies the
+ * order in which users will navigate through the focusable elements via the "tab" key.
+ *
+ *     @example
+ *     // TabIndexedElement is mixed into the ButtonWidget class
+ *     // to provide a tabIndex property.
+ *     var button1 = new OO.ui.ButtonWidget( {
+ *         label : 'fourth',
+ *         tabIndex : 4
+ *     } );
+ *     var button2 = new OO.ui.ButtonWidget( {
+ *         label : 'second',
+ *         tabIndex : 2
+ *     } );
+ *     var button3 = new OO.ui.ButtonWidget( {
+ *         label : 'third',
+ *         tabIndex : 3
+ *     } );
+ *     var button4 = new OO.ui.ButtonWidget( {
+ *         label : 'first',
+ *         tabIndex : 1
+ *     } );
+ *     $( 'body' ).append( button1.$element, button2.$element, button3.$element, button4.$element );
  *
  * @abstract
  * @class
@@ -3594,6 +3738,7 @@ OO.ui.TabIndexedElement.prototype.updateTabIndex = function () {
 /**
  * Handle disable events.
  *
+ * @private
  * @param {boolean} disabled Element is disabled
  */
 OO.ui.TabIndexedElement.prototype.onDisable = function () {
@@ -4169,15 +4314,21 @@ OO.initClass( OO.ui.DraggableElement );
 
 /**
  * @event dragstart
- * @param {OO.ui.DraggableElement} item Dragging item
+ *
+ * A dragstart event is emitted when the user clicks and begins dragging an item.
+ * @param {OO.ui.DraggableElement} item The item the user has clicked and is dragging with the mouse.
  */
 
 /**
  * @event dragend
+ * A dragend event is emitted when the user drags an item and releases the mouse,
+ * thus terminating the drag operation.
  */
 
 /**
  * @event drop
+ * A drop event is emitted when the user drags an item and then releases the mouse button
+ * over a valid target.
  */
 
 /* Static Properties */
@@ -4191,6 +4342,8 @@ OO.ui.DraggableElement.static.cancelButtonMouseDownEvents = false;
 
 /**
  * Respond to dragstart event.
+ *
+ * @private
  * @param {jQuery.Event} event jQuery event
  * @fires dragstart
  */
@@ -4216,6 +4369,8 @@ OO.ui.DraggableElement.prototype.onDragStart = function ( e ) {
 
 /**
  * Respond to dragend event.
+ *
+ * @private
  * @fires dragend
  */
 OO.ui.DraggableElement.prototype.onDragEnd = function () {
@@ -4225,6 +4380,8 @@ OO.ui.DraggableElement.prototype.onDragEnd = function () {
 
 /**
  * Handle drop event.
+ *
+ * @private
  * @param {jQuery.Event} event jQuery event
  * @fires drop
  */
@@ -4236,6 +4393,8 @@ OO.ui.DraggableElement.prototype.onDrop = function ( e ) {
 /**
  * In order for drag/drop to work, the dragover event must
  * return false and stop propogation.
+ *
+ * @private
  */
 OO.ui.DraggableElement.prototype.onDragOver = function ( e ) {
        e.preventDefault();
@@ -4244,6 +4403,8 @@ OO.ui.DraggableElement.prototype.onDragOver = function ( e ) {
 /**
  * Set item index.
  * Store it in the DOM so we can access from the widget drag event
+ *
+ * @private
  * @param {number} Item index
  */
 OO.ui.DraggableElement.prototype.setIndex = function ( index ) {
@@ -4255,6 +4416,8 @@ OO.ui.DraggableElement.prototype.setIndex = function ( index ) {
 
 /**
  * Get item index
+ *
+ * @private
  * @return {number} Item index
  */
 OO.ui.DraggableElement.prototype.getIndex = function () {
@@ -4519,11 +4682,29 @@ OO.ui.DraggableGroupElement.prototype.isDragging = function () {
  *
  * @constructor
  * @param {Object} [config] Configuration options
- * @cfg {jQuery} [$icon] Icon node, assigned to #$icon, omit to use a generated `<span>`
- * @cfg {Object|string} [icon=''] Symbolic icon name, or map of icon names keyed by language ID;
- *  use the 'default' key to specify the icon to be used when there is no icon in the user's
- *  language
- * @cfg {string} [iconTitle] Icon title text or a function that returns text
+ * @cfg {jQuery} [$icon] The icon element created by the class. If this configuration is omitted,
+ *  the icon element will use a generated `<span>`. To use a different HTML tag, or to specify that
+ *  the icon element be set to an existing icon instead of the one generated by this class, set a
+ *  value using a jQuery selection. For example:
+ *
+ *      // Use a <div> tag instead of a <span>
+ *     $icon: $("<div>")
+ *     // Use an existing icon element instead of the one generated by the class
+ *     $icon: this.$element
+ *     // Use an icon element from a child widget
+ *     $icon: this.childwidget.$element
+ * @cfg {Object|string} [icon=''] The symbolic name of the icon (e.g., ‘remove’ or ‘menu’), or a map of
+ *  symbolic names.  A map is used for i18n purposes and contains a `default` icon
+ *  name and additional names keyed by language code. The `default` name is used when no icon is keyed
+ *  by the user's language.
+ *
+ *  Example of an i18n map:
+ *
+ *     { default: 'bold-a', en: 'bold-b', de: 'bold-f' }
+ *  See the [OOjs UI documentation on MediaWiki] [2] for a list of icons included in the library.
+ * [2]: https://www.mediawiki.org/wiki/OOjs_UI/Widgets/Icons,_Indicators,_and_Labels#Icons
+ * @cfg {string|Function} [iconTitle] A text string used as the icon title, or a function that returns title
+ *  text. The icon title is displayed when users move the mouse over the icon.
  */
 OO.ui.IconElement = function OoUiIconElement( config ) {
        // Configuration initialization
@@ -4578,9 +4759,10 @@ OO.ui.IconElement.static.iconTitle = null;
 /* Methods */
 
 /**
- * Set the icon element.
- *
- * If an element is already set, it will be cleaned up before setting up the new element.
+ * Set the icon element. This method is used to retarget an icon mixin so that its functionality
+ * applies to the specified icon element instead of the one created by the class. If an icon
+ * element is already set, the mixin’s effect on that element is removed. Generated CSS classes
+ * and mixin methods will no longer affect the element.
  *
  * @param {jQuery} $icon Element to use as icon
  */
@@ -4600,11 +4782,12 @@ OO.ui.IconElement.prototype.setIconElement = function ( $icon ) {
 };
 
 /**
- * Set icon name.
+ * Set icon by symbolic name (e.g., ‘remove’ or ‘menu’). Use `null` to remove an icon.
+ * The icon parameter can also be set to a map of icon names. See the #icon config setting
+ * for an example.
  *
- * @param {Object|string|null} icon Symbolic icon name, or map of icon names keyed by language ID;
- *  use the 'default' key to specify the icon to be used when there is no icon in the user's
- *  language, use null to remove icon
+ * @param {Object|string|null} icon A symbolic icon name, a {@link #icon map of icon names} keyed
+ *  by language code, or `null` to remove the icon.
  * @chainable
  */
 OO.ui.IconElement.prototype.setIcon = function ( icon ) {
@@ -4630,10 +4813,10 @@ OO.ui.IconElement.prototype.setIcon = function ( icon ) {
 };
 
 /**
- * Set icon title.
+ * Set the icon title. Use `null` to remove the title.
  *
- * @param {string|Function|null} icon Icon title text, a function that returns text or null
- *  for no icon title
+ * @param {string|Function|null} iconTitle A text string used as the icon title,
+ *  a function that returns title text, or `null` for no title.
  * @chainable
  */
 OO.ui.IconElement.prototype.setIconTitle = function ( iconTitle ) {
@@ -4656,7 +4839,7 @@ OO.ui.IconElement.prototype.setIconTitle = function ( iconTitle ) {
 };
 
 /**
- * Get icon name.
+ * Get the symbolic name of the icon.
  *
  * @return {string} Icon name
  */
@@ -4665,7 +4848,7 @@ OO.ui.IconElement.prototype.getIcon = function () {
 };
 
 /**
- * Get icon title.
+ * Get the icon title. The title text is displayed when a user moves the mouse over the icon.
  *
  * @return {string} Icon title text
  */
@@ -4692,10 +4875,15 @@ OO.ui.IconElement.prototype.getIconTitle = function () {
  *
  * @constructor
  * @param {Object} [config] Configuration options
- * @cfg {jQuery} [$indicator] Indicator node, assigned to #$indicator, omit to use a generated
- *   `<span>`
- * @cfg {string} [indicator] Symbolic indicator name
- * @cfg {string} [indicatorTitle] Indicator title text or a function that returns text
+ * @cfg {jQuery} [$indicator] The indicator element created by the class. If this
+ *  configuration is omitted, the indicator element will use a generated `<span>`.
+ * @cfg {string} [indicator] Symbolic name of the indicator (e.g., ‘alert’ or  ‘down’).
+ *  See the [OOjs UI documentation on MediaWiki][2] for a list of indicators included
+ *  in the library.
+ * [2]: https://www.mediawiki.org/wiki/OOjs_UI/Widgets/Icons,_Indicators,_and_Labels#Indicators
+ * @cfg {string|Function} [indicatorTitle] A text string used as the indicator title,
+ *  or a function that returns title text. The indicator title is displayed when users move
+ *  the mouse over the indicator.
  */
 OO.ui.IndicatorElement = function OoUiIndicatorElement( config ) {
        // Configuration initialization
@@ -4719,21 +4907,22 @@ OO.initClass( OO.ui.IndicatorElement );
 /* Static Properties */
 
 /**
- * indicator.
+ * Symbolic name of the indicator (e.g., ‘alert’ or  ‘down’).
+ * The static property will be overridden if the #indicator configuration is used.
  *
  * @static
  * @inheritable
- * @property {string|null} Symbolic indicator name
+ * @property {string|null}
  */
 OO.ui.IndicatorElement.static.indicator = null;
 
 /**
- * Indicator title.
+ * A text string used as the indicator title, a function that returns title text, or `null`
+ * for no title. The static property will be overridden if the #indicatorTitle configuration is used.
  *
  * @static
  * @inheritable
- * @property {string|Function|null} Indicator title text, a function that returns text or null for no
- *  indicator title
+ * @property {string|Function|null}
  */
 OO.ui.IndicatorElement.static.indicatorTitle = null;
 
@@ -4833,16 +5022,25 @@ OO.ui.IndicatorElement.prototype.getIndicatorTitle = function () {
 };
 
 /**
- * Element containing a label.
+ * LabelElement is often mixed into other classes to generate a label, which
+ * helps identify the function of an interface element.
+ * See the [OOjs UI documentation on MediaWiki] [1] for more information.
+ *
+ * [1]: https://www.mediawiki.org/wiki/OOjs_UI/Widgets/Icons,_Indicators,_and_Labels#Labels
  *
  * @abstract
  * @class
  *
  * @constructor
  * @param {Object} [config] Configuration options
- * @cfg {jQuery} [$label] Label node, assigned to #$label, omit to use a generated `<span>`
- * @cfg {jQuery|string|Function} [label] Label nodes, text or a function that returns nodes or text
- * @cfg {boolean} [autoFitLabel=true] Whether to fit the label or not.
+ * @cfg {jQuery} [$label] The label element created by the class. If this
+ *  configuration is omitted, the label element will use a generated `<span>`.
+ * @cfg {jQuery|string|Function} [label] The label text. The label can be specified as a plaintext string,
+ *  a jQuery selection of elements, or a function that will produce a string in the future. See the
+ *  [OOjs UI documentation on MediaWiki] [2] for examples.
+ *  [2]: https://www.mediawiki.org/wiki/OOjs_UI/Widgets/Icons,_Indicators,_and_Labels#Labels
+ * @cfg {boolean} [autoFitLabel=true] Fit the label to the width of the parent element.
+ *  The label will be truncated to fit if necessary.
  */
 OO.ui.LabelElement = function OoUiLabelElement( config ) {
        // Configuration initialization
@@ -4872,12 +5070,13 @@ OO.initClass( OO.ui.LabelElement );
 /* Static Properties */
 
 /**
- * Label.
+ * The label text. The label can be specified as a plaintext string, a function that will
+ * produce a string in the future, or `null` for no label. The static value will
+ * be overridden if a label is specified with the #label config option.
  *
  * @static
  * @inheritable
- * @property {string|Function|null} Label text; a function that returns nodes or text; or null for
- *  no label
+ * @property {string|Function|null}
  */
 OO.ui.LabelElement.static.label = null;
 
@@ -4905,13 +5104,13 @@ OO.ui.LabelElement.prototype.setLabelElement = function ( $label ) {
  * An empty string will result in the label being hidden. A string containing only whitespace will
  * be converted to a single `&nbsp;`.
  *
- * @param {jQuery|string|Function|null} label Label nodes; text; a function that returns nodes or
+ * @param {jQuery|string|OO.ui.HtmlSnippet|Function|null} label Label nodes; text; a function that returns nodes or
  *  text; or null for no label
  * @chainable
  */
 OO.ui.LabelElement.prototype.setLabel = function ( label ) {
        label = typeof label === 'function' ? OO.ui.resolveMsg( label ) : label;
-       label = ( typeof label === 'string' && label.length ) || label instanceof jQuery ? label : null;
+       label = ( ( typeof label === 'string' && label.length ) || label instanceof jQuery || label instanceof OO.ui.HtmlSnippet ) ? label : null;
 
        this.$element.toggleClass( 'oo-ui-labelElement', !!label );
 
@@ -4966,6 +5165,8 @@ OO.ui.LabelElement.prototype.setLabelContent = function ( label ) {
                } else {
                        this.$label.text( label );
                }
+       } else if ( label instanceof OO.ui.HtmlSnippet ) {
+               this.$label.html( label.toString() );
        } else if ( label instanceof jQuery ) {
                this.$label.empty().append( label );
        } else {
@@ -5357,9 +5558,10 @@ OO.ui.PopupElement.prototype.getPopup = function () {
  *
  * @constructor
  * @param {Object} [config] Configuration options
- * @cfg {string|string[]} [flags] Flags describing importance and functionality, e.g. 'primary',
- *   'safe', 'progressive', 'destructive' or 'constructive'
- * @cfg {jQuery} [$flagged] Flagged node, assigned to #$flagged, omit to use #$element
+ * @cfg {string|string[]} [flags] The name or names of the flags (e.g., 'constructive' or 'primary') to apply.
+ *  Please see the [OOjs UI documentation on MediaWiki] [2] for more information about available flags.
+ *  [2]: https://www.mediawiki.org/wiki/OOjs_UI/Elements/Flagged
+ * @cfg {jQuery} [$flagged] Flagged node, assigned to $flagged, omit to use $element
  */
 OO.ui.FlaggedElement = function OoUiFlaggedElement( config ) {
        // Configuration initialization
@@ -5378,8 +5580,12 @@ OO.ui.FlaggedElement = function OoUiFlaggedElement( config ) {
 
 /**
  * @event flag
- * @param {Object.<string,boolean>} changes Object keyed by flag name containing boolean
- *   added/removed properties
+ * A flag event is emitted when the #clearFlags or #setFlags methods are used. The `changes`
+ * parameter contains the name of each modified flag and indicates whether it was
+ * added or removed.
+ *
+ * @param {Object.<string,boolean>} changes Object keyed by flag name. A Boolean `true` indicates
+ * that the flag was added, `false` that the flag was removed.
  */
 
 /* Methods */
@@ -5518,19 +5724,29 @@ OO.ui.FlaggedElement.prototype.setFlags = function ( flags ) {
 };
 
 /**
- * Element with a title.
+ * TitledElement is mixed into other classes to provide a `title` attribute.
+ * Titles are rendered by the browser and are made visible when the user moves
+ * the mouse over the element. Titles are not visible on touch devices.
  *
- * Titles are rendered by the browser and are made visible when hovering the element. Titles are
- * not visible on touch devices.
+ *     @example
+ *     // TitledElement provides a 'title' attribute to the
+ *     // ButtonWidget class
+ *     var button = new OO.ui.ButtonWidget( {
+ *         label : 'Button with Title',
+ *         title : 'I am a button'
+ *     } );
+ *     $( 'body' ).append( button.$element );
  *
  * @abstract
  * @class
  *
  * @constructor
  * @param {Object} [config] Configuration options
- * @cfg {jQuery} [$titled] Titled node, assigned to #$titled, omit to use #$element
- * @cfg {string|Function} [title] Title text or a function that returns text. If not provided, the
- *    static property 'title' is used.
+ * @cfg {jQuery} [$titled] The element to which the `title` attribute is applied.
+ *  If this config is omitted, the title functionality is applied to $element, the
+ *  element created by the class.
+ * @cfg {string|Function} [title] The title text or a function that returns text. If
+ *  this config is omitted, the value of the static `title` property is used.
  */
 OO.ui.TitledElement = function OoUiTitledElement( config ) {
        // Configuration initialization
@@ -5552,11 +5768,12 @@ OO.initClass( OO.ui.TitledElement );
 /* Static Properties */
 
 /**
- * Title.
+ * The title text, a function that returns text, or `null` for no title. The value of the static property
+ * is overridden if the #title config option is used.
  *
  * @static
  * @inheritable
- * @property {string|Function} Title text or a function that returns text
+ * @property {string|Function|null}
  */
 OO.ui.TitledElement.static.title = null;
 
@@ -5833,6 +6050,12 @@ OO.ui.ClippableElement.prototype.clip = function () {
  * @cfg {string|Function} [title] Title text or a function that returns text
  */
 OO.ui.Tool = function OoUiTool( toolGroup, config ) {
+       // Allow passing positional parameters inside the config object
+       if ( OO.isPlainObject( toolGroup ) && config === undefined ) {
+               config = toolGroup;
+               toolGroup = config.toolGroup;
+       }
+
        // Configuration initialization
        config = config || {};
 
@@ -6095,6 +6318,13 @@ OO.ui.Tool.prototype.destroy = function () {
  * @cfg {boolean} [shadow] Add a shadow below the toolbar
  */
 OO.ui.Toolbar = function OoUiToolbar( toolFactory, toolGroupFactory, config ) {
+       // Allow passing positional parameters inside the config object
+       if ( OO.isPlainObject( toolFactory ) && config === undefined ) {
+               config = toolFactory;
+               toolFactory = config.toolFactory;
+               toolGroupFactory = config.toolGroupFactory;
+       }
+
        // Configuration initialization
        config = config || {};
 
@@ -6311,6 +6541,12 @@ OO.ui.Toolbar.prototype.getToolAccelerator = function () {
  * @cfg {Array|string} [demote=[]] List of tools to demote to the end
  */
 OO.ui.ToolGroup = function OoUiToolGroup( toolbar, config ) {
+       // Allow passing positional parameters inside the config object
+       if ( OO.isPlainObject( toolbar ) && config === undefined ) {
+               config = toolbar;
+               toolbar = config.toolbar;
+       }
+
        // Configuration initialization
        config = config || {};
 
@@ -7031,12 +7267,10 @@ OO.ui.ProcessDialog.prototype.attachActions = function () {
                this.$primaryActions.append( special.primary.$element );
                special.primary.toggleFramed( true );
        }
-       if ( others.length ) {
-               for ( i = 0, len = others.length; i < len; i++ ) {
-                       other = others[ i ];
-                       this.$otherActions.append( other.$element );
-                       other.toggleFramed( true );
-               }
+       for ( i = 0, len = others.length; i < len; i++ ) {
+               other = others[ i ];
+               this.$otherActions.append( other.$element );
+               other.toggleFramed( true );
        }
        if ( special.safe ) {
                this.$safeActions.append( special.safe.$element );
@@ -7149,6 +7383,12 @@ OO.ui.ProcessDialog.prototype.hideErrors = function () {
  * @cfg {string} [help] Explanatory text shown as a '?' icon.
  */
 OO.ui.FieldLayout = function OoUiFieldLayout( fieldWidget, config ) {
+       // Allow passing positional parameters inside the config object
+       if ( OO.isPlainObject( fieldWidget ) && config === undefined ) {
+               config = fieldWidget;
+               fieldWidget = config.fieldWidget;
+       }
+
        var hasInputWidget = fieldWidget instanceof OO.ui.InputWidget;
 
        // Configuration initialization
@@ -7284,6 +7524,13 @@ OO.ui.FieldLayout.prototype.setAlignment = function ( value ) {
  * @cfg {string} [help] Explanatory text shown as a '?' icon.
  */
 OO.ui.ActionFieldLayout = function OoUiActionFieldLayout( fieldWidget, buttonWidget, config ) {
+       // Allow passing positional parameters inside the config object
+       if ( OO.isPlainObject( fieldWidget ) && config === undefined ) {
+               config = fieldWidget;
+               fieldWidget = config.fieldWidget;
+               buttonWidget = config.buttonWidget;
+       }
+
        // Configuration initialization
        config = $.extend( { align: 'left' }, config );
 
@@ -7376,12 +7623,14 @@ OO.mixinClass( OO.ui.FieldsetLayout, OO.ui.GroupElement );
  *
  * @class
  * @extends OO.ui.Layout
+ * @mixins OO.ui.GroupElement
  *
  * @constructor
  * @param {Object} [config] Configuration options
  * @cfg {string} [method] HTML form `method` attribute
  * @cfg {string} [action] HTML form `action` attribute
  * @cfg {string} [enctype] HTML form `enctype` attribute
+ * @cfg {OO.ui.FieldsetLayout[]} [items] Items to add
  */
 OO.ui.FormLayout = function OoUiFormLayout( config ) {
        // Configuration initialization
@@ -7390,6 +7639,9 @@ OO.ui.FormLayout = function OoUiFormLayout( config ) {
        // Parent constructor
        OO.ui.FormLayout.super.call( this, config );
 
+       // Mixin constructors
+       OO.ui.GroupElement.call( this, $.extend( {}, config, { $group: this.$element } ) );
+
        // Events
        this.$element.on( 'submit', this.onFormSubmit.bind( this ) );
 
@@ -7401,16 +7653,24 @@ OO.ui.FormLayout = function OoUiFormLayout( config ) {
                        action: config.action,
                        enctype: config.enctype
                } );
+       if ( Array.isArray( config.items ) ) {
+               this.addItems( config.items );
+       }
 };
 
 /* Setup */
 
 OO.inheritClass( OO.ui.FormLayout, OO.ui.Layout );
+OO.mixinClass( OO.ui.FormLayout, OO.ui.GroupElement );
 
 /* Events */
 
 /**
+ * The HTML form was submitted. If the submission is handled, call `e.preventDefault()` to prevent
+ * HTML form submission.
+ *
  * @event submit
+ * @param {jQuery.Event} e Submit event
  */
 
 /* Static Properties */
@@ -7425,9 +7685,8 @@ OO.ui.FormLayout.static.tagName = 'form';
  * @param {jQuery.Event} e Submit event
  * @fires submit
  */
-OO.ui.FormLayout.prototype.onFormSubmit = function () {
-       this.emit( 'submit' );
-       return false;
+OO.ui.FormLayout.prototype.onFormSubmit = function ( e ) {
+       this.emit( 'submit', e );
 };
 
 /**
@@ -7444,6 +7703,12 @@ OO.ui.FormLayout.prototype.onFormSubmit = function () {
  * @cfg {number[]} [heights] Heights of rows as ratios
  */
 OO.ui.GridLayout = function OoUiGridLayout( panels, config ) {
+       // Allow passing positional parameters inside the config object
+       if ( OO.isPlainObject( panels ) && config === undefined ) {
+               config = panels;
+               panels = config.panels;
+       }
+
        var i, len, widths;
 
        // Configuration initialization
@@ -8284,6 +8549,12 @@ OO.inheritClass( OO.ui.PanelLayout, OO.ui.Layout );
  * @param {Object} [config] Configuration options
  */
 OO.ui.PageLayout = function OoUiPageLayout( name, config ) {
+       // Allow passing positional parameters inside the config object
+       if ( OO.isPlainObject( name ) && config === undefined ) {
+               config = name;
+               name = config.name;
+       }
+
        // Configuration initialization
        config = $.extend( { scrollable: true }, config );
 
@@ -8586,6 +8857,12 @@ OO.ui.StackLayout.prototype.updateHiddenState = function ( items, selectedItem )
  * @param {Object} [config] Configuration options
  */
 OO.ui.BarToolGroup = function OoUiBarToolGroup( toolbar, config ) {
+       // Allow passing positional parameters inside the config object
+       if ( OO.isPlainObject( toolbar ) && config === undefined ) {
+               config = toolbar;
+               toolbar = config.toolbar;
+       }
+
        // Parent constructor
        OO.ui.BarToolGroup.super.call( this, toolbar, config );
 
@@ -8623,6 +8900,12 @@ OO.ui.BarToolGroup.static.name = 'bar';
  * @cfg {string} [header] Text to display at the top of the pop-up
  */
 OO.ui.PopupToolGroup = function OoUiPopupToolGroup( toolbar, config ) {
+       // Allow passing positional parameters inside the config object
+       if ( OO.isPlainObject( toolbar ) && config === undefined ) {
+               config = toolbar;
+               toolbar = config.toolbar;
+       }
+
        // Configuration initialization
        config = config || {};
 
@@ -8794,6 +9077,12 @@ OO.ui.PopupToolGroup.prototype.setActive = function ( value ) {
  * @cfg {boolean} [expanded=false] Whether the collapsible tools are expanded by default
  */
 OO.ui.ListToolGroup = function OoUiListToolGroup( toolbar, config ) {
+       // Allow passing positional parameters inside the config object
+       if ( OO.isPlainObject( toolbar ) && config === undefined ) {
+               config = toolbar;
+               toolbar = config.toolbar;
+       }
+
        // Configuration initialization
        config = config || {};
 
@@ -8913,6 +9202,12 @@ OO.ui.ListToolGroup.prototype.updateCollapsibleState = function () {
  * @param {Object} [config] Configuration options
  */
 OO.ui.MenuToolGroup = function OoUiMenuToolGroup( toolbar, config ) {
+       // Allow passing positional parameters inside the config object
+       if ( OO.isPlainObject( toolbar ) && config === undefined ) {
+               config = toolbar;
+               toolbar = config.toolbar;
+       }
+
        // Configuration initialization
        config = config || {};
 
@@ -8970,6 +9265,12 @@ OO.ui.MenuToolGroup.prototype.onUpdateState = function () {
  * @param {Object} [config] Configuration options
  */
 OO.ui.PopupTool = function OoUiPopupTool( toolbar, config ) {
+       // Allow passing positional parameters inside the config object
+       if ( OO.isPlainObject( toolbar ) && config === undefined ) {
+               config = toolbar;
+               toolbar = config.toolbar;
+       }
+
        // Parent constructor
        OO.ui.PopupTool.super.call( this, toolbar, config );
 
@@ -9127,6 +9428,12 @@ OO.ui.ItemWidget.prototype.setElementGroup = function ( group ) {
  * @cfg {jQuery} [$container=input.$element] Element to render menu under
  */
 OO.ui.LookupInputWidget = function OoUiLookupInputWidget( input, config ) {
+       // Allow passing positional parameters inside the config object
+       if ( OO.isPlainObject( input ) && config === undefined ) {
+               config = input;
+               input = config.input;
+       }
+
        // Configuration initialization
        config = config || {};
 
@@ -9434,6 +9741,12 @@ OO.ui.LookupInputWidget.prototype.getLookupCacheItemFromData = function () {
  * @param {Object} [config] Configuration options
  */
 OO.ui.OutlineControlsWidget = function OoUiOutlineControlsWidget( outline, config ) {
+       // Allow passing positional parameters inside the config object
+       if ( OO.isPlainObject( outline ) && config === undefined ) {
+               config = outline;
+               outline = config.outline;
+       }
+
        // Configuration initialization
        config = $.extend( { icon: 'add' }, config );
 
@@ -10022,7 +10335,22 @@ OO.ui.ActionWidget.prototype.toggle = function () {
 };
 
 /**
- * Button that shows and hides a popup.
+ * PopupButtonWidgets toggle the visibility of a contained {@link OO.ui.PopupWidget PopupWidget},
+ * which is used to display additional information or options.
+ *
+ *     @example
+ *     // Example of a popup button.
+ *     var popupButton = new OO.ui.PopupButtonWidget( {
+ *         label: 'Popup button with options',
+ *         icon: 'menu',
+ *         popup: {
+ *             $content: $( '<p>Additional options here.</p>' ),
+ *             padded: true,
+ *             align: 'left'
+ *         }
+ *     } );
+ *     // Append the button to the DOM.
+ *     $( 'body' ).append( popupButton.$element );
  *
  * @class
  * @extends OO.ui.ButtonWidget
@@ -10057,6 +10385,8 @@ OO.mixinClass( OO.ui.PopupButtonWidget, OO.ui.PopupElement );
 
 /**
  * Handle the button action being triggered.
+ *
+ * @private
  */
 OO.ui.PopupButtonWidget.prototype.onAction = function () {
        this.popup.toggle();
@@ -10600,6 +10930,7 @@ OO.ui.ButtonInputWidget = function OoUiButtonInputWidget( config ) {
 
        // Properties (must be set before parent constructor, which calls #setValue)
        this.useInputTag = config.useInputTag;
+       this.type = config.type;
 
        // Parent constructor
        OO.ui.ButtonInputWidget.super.call( this, config );
@@ -10683,6 +11014,18 @@ OO.ui.ButtonInputWidget.prototype.setValue = function ( value ) {
        return this;
 };
 
+/**
+ * @inheritdoc
+ */
+OO.ui.ButtonInputWidget.prototype.onClick = function ( e ) {
+       var ret = OO.ui.ButtonElement.prototype.onClick.call( this, e );
+       if ( this.type === 'submit' ) {
+               // Never prevent default action (form submission)
+               return true;
+       }
+       return ret;
+};
+
 /**
  * Checkbox input widget.
  *
@@ -11014,7 +11357,7 @@ OO.ui.TextInputWidget = function OoUiTextInputWidget( config ) {
        }
 
        this.setValidation( config.validate );
-       this.setPosition( config.labelPosition );
+       this.setLabelPosition( config.labelPosition );
 
        // Events
        this.$input.on( {
@@ -11313,12 +11656,20 @@ OO.ui.TextInputWidget.prototype.isValid = function () {
  * @param {string} labelPosition Label position, 'before' or 'after'
  * @chainable
  */
-OO.ui.TextInputWidget.prototype.setPosition = function ( labelPosition ) {
+OO.ui.TextInputWidget.prototype.setLabelPosition = function ( labelPosition ) {
        this.labelPosition = labelPosition;
        this.updatePosition();
        return this;
 };
 
+/**
+ * Deprecated alias of #setLabelPosition
+ *
+ * @deprecated Use setLabelPosition instead.
+ */
+OO.ui.TextInputWidget.prototype.setPosition =
+       OO.ui.TextInputWidget.prototype.setLabelPosition;
+
 /**
  * Update the position of the inline label.
  *
@@ -11404,6 +11755,10 @@ OO.ui.ComboBoxWidget = function OoUiComboBoxWidget( config ) {
                },
                config.input
        ) );
+       this.input.$input.eq( 0 ).attr( {
+               role: 'combobox',
+               'aria-autocomplete': 'list'
+       } );
        this.menu = new OO.ui.TextInputMenuSelectWidget( this.input, $.extend(
                {
                        widget: this,
@@ -11599,7 +11954,12 @@ OO.ui.LabelWidget.prototype.onClick = function () {
 };
 
 /**
- * Generic option widget for use with OO.ui.SelectWidget.
+ * OptionWidgets are special elements that can be selected and configured with data. The
+ * data is often unique for each option, but it does not have to be. OptionWidgets are used
+ * with OO.ui.SelectWidget to create a selection of mutually exclusive options. For more information
+ * and examples, please see the [OOjs UI documentation on MediaWiki][1].
+ *
+ * [1]: https://www.mediawiki.org/wiki/OOjs_UI/Widgets/Selects_and_Options
  *
  * @class
  * @extends OO.ui.Widget
@@ -11654,7 +12014,7 @@ OO.ui.OptionWidget.static.scrollIntoViewOnSelect = false;
 /* Methods */
 
 /**
- * Check if option can be selected.
+ * Check if the option can be selected.
  *
  * @return {boolean} Item is selectable
  */
@@ -11663,7 +12023,9 @@ OO.ui.OptionWidget.prototype.isSelectable = function () {
 };
 
 /**
- * Check if option can be highlighted.
+ * Check if the option can be highlighted. A highlight indicates that the option
+ * may be selected when a user presses enter or clicks. Disabled items cannot
+ * be highlighted.
  *
  * @return {boolean} Item is highlightable
  */
@@ -11672,7 +12034,8 @@ OO.ui.OptionWidget.prototype.isHighlightable = function () {
 };
 
 /**
- * Check if option can be pressed.
+ * Check if the option can be pressed. The pressed state occurs when a user mouses
+ * down on an item, but has not yet let go of the mouse.
  *
  * @return {boolean} Item is pressable
  */
@@ -11681,7 +12044,7 @@ OO.ui.OptionWidget.prototype.isPressable = function () {
 };
 
 /**
- * Check if option is selected.
+ * Check if the option is selected.
  *
  * @return {boolean} Item is selected
  */
@@ -11690,7 +12053,8 @@ OO.ui.OptionWidget.prototype.isSelected = function () {
 };
 
 /**
- * Check if option is highlighted.
+ * Check if the option is highlighted. A highlight indicates that the
+ * item may be selected when a user presses enter or clicks.
  *
  * @return {boolean} Item is highlighted
  */
@@ -11699,7 +12063,9 @@ OO.ui.OptionWidget.prototype.isHighlighted = function () {
 };
 
 /**
- * Check if option is pressed.
+ * Check if the option is pressed. The pressed state occurs when a user mouses
+ * down on an item, but has not yet let go of the mouse. The item may appear
+ * selected, but it will not be selected until the user releases the mouse.
  *
  * @return {boolean} Item is pressed
  */
@@ -11708,7 +12074,9 @@ OO.ui.OptionWidget.prototype.isPressed = function () {
 };
 
 /**
- * Set selected state.
+ * Set the option’s selected state. In general, all modifications to the selection
+ * should be handled by the SelectWidget’s {@link OO.ui.SelectWidget#selectItem selectItem( [item] )}
+ * method instead of this method.
  *
  * @param {boolean} [state=false] Select option
  * @chainable
@@ -11728,7 +12096,10 @@ OO.ui.OptionWidget.prototype.setSelected = function ( state ) {
 };
 
 /**
- * Set highlighted state.
+ * Set the option’s highlighted state. In general, all programmatic
+ * modifications to the highlight should be handled by the
+ * SelectWidget’s {@link OO.ui.SelectWidget#highlightItem highlightItem( [item] )}
+ * method instead of this method.
  *
  * @param {boolean} [state=false] Highlight option
  * @chainable
@@ -11743,7 +12114,10 @@ OO.ui.OptionWidget.prototype.setHighlighted = function ( state ) {
 };
 
 /**
- * Set pressed state.
+ * Set the option’s pressed state. In general, all
+ * programmatic modifications to the pressed state should be handled by the
+ * SelectWidget’s {@link OO.ui.SelectWidget#pressItem pressItem( [item] )}
+ * method instead of this method.
  *
  * @param {boolean} [state=false] Press option
  * @chainable
@@ -11792,9 +12166,12 @@ OO.mixinClass( OO.ui.OptionWidget, OO.ui.IconElement );
 OO.mixinClass( OO.ui.OptionWidget, OO.ui.IndicatorElement );
 
 /**
- * Option widget that looks like a button.
+ * ButtonOptionWidget is a special type of {@link OO.ui.ButtonElement button element} that
+ * can be selected and configured with data. The class is
+ * used with OO.ui.ButtonSelectWidget to create a selection of button options. Please see the
+ * [OOjs UI documentation on MediaWiki] [1] for more information.
  *
- * Use together with OO.ui.ButtonSelectWidget.
+ * [1]: https://www.mediawiki.org/wiki/OOjs_UI/Widgets/Selects_and_Options#Button_selects_and_options
  *
  * @class
  * @extends OO.ui.DecoratedOptionWidget
@@ -11850,9 +12227,11 @@ OO.ui.ButtonOptionWidget.prototype.setSelected = function ( state ) {
 };
 
 /**
- * Option widget that looks like a radio button.
+ * RadioOptionWidget is an option widget that looks like a radio button.
+ * The class is used with OO.ui.RadioSelectWidget to create a selection of radio options.
+ * Please see the [OOjs UI documentation on MediaWiki] [1] for more information.
  *
- * Use together with OO.ui.RadioSelectWidget.
+ * [1]: https://www.mediawiki.org/wiki/OOjs_UI/Widgets/Selects_and_Options#Button_selects_and_option
  *
  * @class
  * @extends OO.ui.OptionWidget
@@ -11861,12 +12240,15 @@ OO.ui.ButtonOptionWidget.prototype.setSelected = function ( state ) {
  * @param {Object} [config] Configuration options
  */
 OO.ui.RadioOptionWidget = function OoUiRadioOptionWidget( config ) {
-       // Parent constructor
-       OO.ui.RadioOptionWidget.super.call( this, config );
+       // Configuration initialization
+       config = config || {};
 
-       // Properties
+       // Properties (must be done before parent constructor which calls #setDisabled)
        this.radio = new OO.ui.RadioInputWidget( { value: config.data, tabIndex: -1 } );
 
+       // Parent constructor
+       OO.ui.RadioOptionWidget.super.call( this, config );
+
        // Initialization
        this.$element
                .addClass( 'oo-ui-radioOptionWidget' )
@@ -11901,7 +12283,22 @@ OO.ui.RadioOptionWidget.prototype.setSelected = function ( state ) {
 };
 
 /**
- * Item of an OO.ui.MenuSelectWidget.
+ * @inheritdoc
+ */
+OO.ui.RadioOptionWidget.prototype.setDisabled = function ( disabled ) {
+       OO.ui.RadioOptionWidget.super.prototype.setDisabled.call( this, disabled );
+
+       this.radio.setDisabled( this.isDisabled() );
+
+       return this;
+};
+
+/**
+ * MenuOptionWidget is an option widget that looks like a menu item. The class is used with
+ * OO.ui.MenuSelectWidget to create a menu of mutually exclusive options. Please see
+ * the [OOjs UI documentation on MediaWiki] [1] for more information.
+ *
+ * [1]: https://www.mediawiki.org/wiki/OOjs_UI/Widgets/Selects_and_Options#Menu_selects_and_options
  *
  * @class
  * @extends OO.ui.DecoratedOptionWidget
@@ -12616,7 +13013,10 @@ OO.ui.SearchWidget.prototype.getResults = function () {
  *
  * @constructor
  * @param {Object} [config] Configuration options
- * @cfg {OO.ui.OptionWidget[]} [items] Options to add
+ * @cfg {OO.ui.OptionWidget[]} [items] An array of options to add to the select.
+ *  Options are created with {@link OO.ui.OptionWidget OptionWidget} classes. See
+ *  the [OOjs UI documentation on MediaWiki] [2] for examples.
+ *  [2]: https://www.mediawiki.org/wiki/OOjs_UI/Widgets/Selects_and_Options
  */
 OO.ui.SelectWidget = function OoUiSelectWidget( config ) {
        // Configuration initialization
@@ -12663,16 +13063,26 @@ OO.mixinClass( OO.ui.SelectWidget, OO.ui.GroupWidget );
 
 /**
  * @event highlight
+ *
+ * A `highlight` event is emitted when the highlight is changed with the #highlightItem method.
+ *
  * @param {OO.ui.OptionWidget|null} item Highlighted item
  */
 
 /**
  * @event press
+ *
+ * A `press` event is emitted when the #pressItem method is used to programmatically modify the
+ * pressed state of an option.
+ *
  * @param {OO.ui.OptionWidget|null} item Pressed item
  */
 
 /**
  * @event select
+ *
+ * A `select` event is emitted when the selection is modified programmatically with the #selectItem method.
+ *
  * @param {OO.ui.OptionWidget|null} item Selected item
  */
 
@@ -12683,12 +13093,19 @@ OO.mixinClass( OO.ui.SelectWidget, OO.ui.GroupWidget );
 
 /**
  * @event add
+ *
+ * An `add` event is emitted when options are added to the select with the #addItems method.
+ *
  * @param {OO.ui.OptionWidget[]} items Added items
- * @param {number} index Index items were added at
+ * @param {number} index Index of insertion point
  */
 
 /**
  * @event remove
+ *
+ * A `remove` event is emitted when options are removed from the select with the #clearItems
+ * or #removeItems methods.
+ *
  * @param {OO.ui.OptionWidget[]} items Removed items
  */
 
@@ -12811,6 +13228,7 @@ OO.ui.SelectWidget.prototype.onMouseLeave = function () {
 /**
  * Handle key down events.
  *
+ * @protected
  * @param {jQuery.Event} e Key down event
  */
 OO.ui.SelectWidget.prototype.onKeyDown = function ( e ) {
@@ -12944,11 +13362,10 @@ OO.ui.SelectWidget.prototype.togglePressed = function ( pressed ) {
 };
 
 /**
- * Highlight an item.
- *
- * Highlighting is mutually exclusive.
+ * Highlight an option. If the `item` param is omitted, no options will be highlighted
+ * and any existing highlight will be removed. The highlight is mutually exclusive.
  *
- * @param {OO.ui.OptionWidget} [item] Item to highlight, omit to deselect all
+ * @param {OO.ui.OptionWidget} [item] Item to highlight, omit for no highlight
  * @fires highlight
  * @chainable
  */
@@ -12971,7 +13388,8 @@ OO.ui.SelectWidget.prototype.highlightItem = function ( item ) {
 };
 
 /**
- * Select an item.
+ * Programmatically select an option by its reference. If the `item` parameter is omitted,
+ * all options will be deselected.
  *
  * @param {OO.ui.OptionWidget} [item] Item to select, omit to deselect all
  * @fires select
@@ -13038,11 +13456,14 @@ OO.ui.SelectWidget.prototype.chooseItem = function ( item ) {
 };
 
 /**
- * Get an item relative to another one.
+ * Get an option by its position relative to the specified item (or to the start of the option array,
+ * if item is `null`). The direction in which to search through the option array is specified with a
+ * number: -1 for reverse (the default) or 1 for forward. The method will return an option, or
+ * `null` if there are no options in the array.
  *
- * @param {OO.ui.OptionWidget|null} item Item to start at, null to get relative to list start
- * @param {number} direction Direction to move in, -1 to move backward, 1 to move forward
- * @return {OO.ui.OptionWidget|null} Item at position, `null` if there are no items in the menu
+ * @param {OO.ui.OptionWidget|null} item Item to describe the start position, or `null` to start at the beginning of the array.
+ * @param {number} direction Direction to move in: -1 to move backward, 1 to move forward
+ * @return {OO.ui.OptionWidget|null} Item at position, `null` if there are no items in the select
  */
 OO.ui.SelectWidget.prototype.getRelativeSelectableItem = function ( item, direction ) {
        var currentIndex, nextIndex, i,
@@ -13069,7 +13490,8 @@ OO.ui.SelectWidget.prototype.getRelativeSelectableItem = function ( item, direct
 };
 
 /**
- * Get the next selectable item.
+ * Get the next selectable item or `null` if there are no selectable items.
+ * Disabled options and menu-section markers and breaks are not selectable.
  *
  * @return {OO.ui.OptionWidget|null} Item, `null` if there aren't any selectable items
  */
@@ -13087,7 +13509,8 @@ OO.ui.SelectWidget.prototype.getFirstSelectableItem = function () {
 };
 
 /**
- * Add items.
+ * Add an array of options to the select. Optionally, an index number can be used to
+ * specify an insertion point.
  *
  * @param {OO.ui.OptionWidget[]} items Items to add
  * @param {number} [index] Index to insert items after
@@ -13105,9 +13528,9 @@ OO.ui.SelectWidget.prototype.addItems = function ( items, index ) {
 };
 
 /**
- * Remove items.
- *
- * Items will be detached, not removed, so they can be used later.
+ * Remove the specified array of options from the select. Options will be detached
+ * from the DOM, not removed, so they can be reused later. To remove all options from
+ * the select, you may wish to use the #clearItems method instead.
  *
  * @param {OO.ui.OptionWidget[]} items Items to remove
  * @fires remove
@@ -13133,9 +13556,9 @@ OO.ui.SelectWidget.prototype.removeItems = function ( items ) {
 };
 
 /**
- * Clear all items.
- *
- * Items will be detached, not removed, so they can be used later.
+ * Clear all options from the select. Options will be detached from the DOM, not removed,
+ * so that they can be reused later. To remove a subset of options from the select, use
+ * the #removeItems method.
  *
  * @fires remove
  * @chainable
@@ -13155,9 +13578,38 @@ OO.ui.SelectWidget.prototype.clearItems = function () {
 };
 
 /**
- * Select widget containing button options.
+ * ButtonSelectWidget is a {@link OO.ui.SelectWidget select widget} that contains
+ * button options and is used together with
+ * OO.ui.ButtonOptionWidget. The ButtonSelectWidget provides an interface for
+ * highlighting, choosing, and selecting mutually exclusive options. Please see
+ * the [OOjs UI documentation on MediaWiki] [1] for more information.
  *
- * Use together with OO.ui.ButtonOptionWidget.
+ *     @example
+ *     // Example: A ButtonSelectWidget that contains three ButtonOptionWidgets
+ *     var option1 = new OO.ui.ButtonOptionWidget( {
+ *         data: 1,
+ *         label: 'Option 1',
+ *         title:'Button option 1'
+ *     } );
+ *
+ *     var option2 = new OO.ui.ButtonOptionWidget( {
+ *         data: 2,
+ *         label: 'Option 2',
+ *         title:'Button option 2'
+ *     } );
+ *
+ *     var option3 = new OO.ui.ButtonOptionWidget( {
+ *         data: 3,
+ *         label: 'Option 3',
+ *         title:'Button option 3'
+ *     } );
+ *
+ *     var buttonSelect=new OO.ui.ButtonSelectWidget( {
+ *         items: [option1, option2, option3]
+ *     } );
+ *     $('body').append(buttonSelect.$element);
+ *
+ * [1]: https://www.mediawiki.org/wiki/OOjs_UI/Widgets/Selects_and_Options
  *
  * @class
  * @extends OO.ui.SelectWidget
@@ -13189,9 +13641,34 @@ OO.inheritClass( OO.ui.ButtonSelectWidget, OO.ui.SelectWidget );
 OO.mixinClass( OO.ui.ButtonSelectWidget, OO.ui.TabIndexedElement );
 
 /**
- * Select widget containing radio button options.
+ * RadioSelectWidget is a {@link OO.ui.SelectWidget select widget} that contains radio
+ * options and is used together with OO.ui.RadioOptionWidget. The RadioSelectWidget provides
+ * an interface for adding, removing and selecting options.
+ * Please see the [OOjs UI documentation on MediaWiki][1] for more information.
  *
- * Use together with OO.ui.RadioOptionWidget.
+ *     @example
+ *     // A RadioSelectWidget with RadioOptions.
+ *     var option1 = new OO.ui.RadioOptionWidget( {
+ *         data: 'a',
+ *         label: 'Selected radio option'
+ *     } );
+ *
+ *     var option2 = new OO.ui.RadioOptionWidget( {
+ *         data: 'b',
+ *         label: 'Unselected radio option'
+ *     } );
+ *
+ *     var radioSelect=new OO.ui.RadioSelectWidget( {
+ *         items: [option1, option2]
+ *      } );
+ *
+ *     // Select 'option 1' using the RadioSelectWidget's selectItem() method.
+ *     radioSelect.selectItem( option1 );
+ *
+ *     $('body').append(radioSelect.$element);
+ *
+ * [1]: https://www.mediawiki.org/wiki/OOjs_UI/Widgets/Selects_and_Options
+
  *
  * @class
  * @extends OO.ui.SelectWidget
@@ -13223,12 +13700,24 @@ OO.inheritClass( OO.ui.RadioSelectWidget, OO.ui.SelectWidget );
 OO.mixinClass( OO.ui.RadioSelectWidget, OO.ui.TabIndexedElement );
 
 /**
- * Overlaid menu of options.
+ * MenuSelectWidget is a {@link OO.ui.SelectWidget select widget} that contains options and
+ * is used together with OO.ui.MenuOptionWidget. See {@link OO.ui.DropdownWidget DropdownWidget} and
+ * {@link OO.ui.ComboBoxWidget ComboBoxWidget} for examples of interfaces that contain menus.
+ * MenuSelectWidgets themselves are not designed to be instantiated directly, rather subclassed
+ * and customized to be opened, closed, and displayed as needed.
+ *
+ * By default, menus are clipped to the visible viewport and are not visible when a user presses the
+ * mouse outside the menu.
+ *
+ * Menus also have support for keyboard interaction:
  *
- * Menus are clipped to the visible viewport. They do not provide a control for opening or closing
- * the menu.
+ * - Enter/Return key: choose and select a menu option
+ * - Up-arrow key: highlight the previous menu option
+ * - Down-arrow key: highlight the next menu option
+ * - Esc key: hide the menu
  *
- * Use together with OO.ui.MenuOptionWidget.
+ * Please see the [OOjs UI documentation on MediaWiki][1] for more information.
+ * [1]: https://www.mediawiki.org/wiki/OOjs_UI/Widgets/Selects_and_Options
  *
  * @class
  * @extends OO.ui.SelectWidget
@@ -13279,6 +13768,7 @@ OO.mixinClass( OO.ui.MenuSelectWidget, OO.ui.ClippableElement );
 /**
  * Handles document mouse down events.
  *
+ * @protected
  * @param {jQuery.Event} e Key down event
  */
 OO.ui.MenuSelectWidget.prototype.onDocumentMouseDown = function ( e ) {
@@ -13468,11 +13958,17 @@ OO.ui.MenuSelectWidget.prototype.toggle = function ( visible ) {
  * @extends OO.ui.MenuSelectWidget
  *
  * @constructor
- * @param {OO.ui.TextInputWidget} input Text input widget to provide menu for
+ * @param {OO.ui.TextInputWidget} inputWidget Text input widget to provide menu for
  * @param {Object} [config] Configuration options
  * @cfg {jQuery} [$container=input.$element] Element to render menu under
  */
-OO.ui.TextInputMenuSelectWidget = function OoUiTextInputMenuSelectWidget( input, config ) {
+OO.ui.TextInputMenuSelectWidget = function OoUiTextInputMenuSelectWidget( inputWidget, config ) {
+       // Allow passing positional parameters inside the config object
+       if ( OO.isPlainObject( inputWidget ) && config === undefined ) {
+               config = inputWidget;
+               inputWidget = config.inputWidget;
+       }
+
        // Configuration initialization
        config = config || {};
 
@@ -13480,8 +13976,8 @@ OO.ui.TextInputMenuSelectWidget = function OoUiTextInputMenuSelectWidget( input,
        OO.ui.TextInputMenuSelectWidget.super.call( this, config );
 
        // Properties
-       this.input = input;
-       this.$container = config.$container || this.input.$element;
+       this.inputWidget = inputWidget;
+       this.$container = config.$container || this.inputWidget.$element;
        this.onWindowResizeHandler = this.onWindowResize.bind( this );
 
        // Initialization
index 0b61721..cf5a616 100644 (file)
@@ -1,12 +1,12 @@
 /*!
- * OOjs v1.1.4 optimised for jQuery
+ * OOjs v1.1.5 optimised for jQuery
  * https://www.mediawiki.org/wiki/OOjs
  *
  * Copyright 2011-2015 OOjs Team and other contributors.
  * Released under the MIT license
  * http://oojs.mit-license.org
  *
- * Date: 2015-01-23T20:11:25Z
+ * Date: 2015-02-26T01:51:06Z
  */
 ( function ( global ) {
 
@@ -301,8 +301,12 @@ oo.compare = function ( a, b, asymmetrical ) {
        a = a || {};
        b = b || {};
 
+       if ( typeof a.nodeType === 'number' && typeof a.isEqualNode === 'function' ) {
+               return a.isEqualNode( b );
+       }
+
        for ( k in a ) {
-               if ( !hasOwn.call( a, k ) || a[k] === undefined ) {
+               if ( !hasOwn.call( a, k ) || a[k] === undefined || a[k] === b[k] ) {
                        // Support es3-shim: Without the hasOwn filter, comparing [] to {} will be false in ES3
                        // because the shimmed "forEach" is enumerable and shows up in Array but not Object.
                        // Also ignore undefined values, because there is no conceptual difference between
@@ -319,7 +323,7 @@ oo.compare = function ( a, b, asymmetrical ) {
                                ( aType === 'string' || aType === 'number' || aType === 'boolean' ) &&
                                aValue !== bValue
                        ) ||
-                       ( aValue === Object( aValue ) && !oo.compare( aValue, bValue, asymmetrical ) ) ) {
+                       ( aValue === Object( aValue ) && !oo.compare( aValue, bValue, true ) ) ) {
                        return false;
                }
        }
@@ -622,11 +626,11 @@ oo.isPlainObject = $.isPlainObject;
         */
        oo.EventEmitter.prototype.once = function ( event, listener ) {
                var eventEmitter = this,
-                       listenerWrapper = function () {
-                               eventEmitter.off( event, listenerWrapper );
-                               listener.apply( eventEmitter, Array.prototype.slice.call( arguments, 0 ) );
+                       wrapper = function () {
+                               eventEmitter.off( event, wrapper );
+                               return listener.apply( this, arguments );
                        };
-               return this.on( event, listenerWrapper );
+               return this.on( event, wrapper );
        };
 
        /**