Merge "Disallow user suppression in a partial block"
authorjenkins-bot <jenkins-bot@gerrit.wikimedia.org>
Tue, 5 Feb 2019 23:27:37 +0000 (23:27 +0000)
committerGerrit Code Review <gerrit@wikimedia.org>
Tue, 5 Feb 2019 23:27:37 +0000 (23:27 +0000)
35 files changed:
.phpcs.xml
autoload.php
includes/Block.php
includes/DefaultSettings.php
includes/XmlJsCode.php
includes/api/i18n/it.json
includes/cache/CacheHelper.php
includes/cache/ICacheHelper.php [new file with mode: 0644]
includes/resourceloader/ResourceLoader.php
includes/resourceloader/ResourceLoaderFileModule.php
includes/resourceloader/ResourceLoaderModule.php
languages/i18n/bqi.json
languages/i18n/diq.json
languages/i18n/exif/is.json
languages/i18n/exif/shi.json
languages/i18n/ia.json
languages/i18n/ig.json
languages/i18n/is.json
languages/i18n/it.json
languages/i18n/lrc.json
languages/i18n/mo.json
languages/i18n/roa-tara.json
languages/i18n/sat.json
languages/i18n/sh.json
languages/i18n/shi.json
languages/i18n/th.json
languages/i18n/tt-cyrl.json
resources/src/startup/mediawiki.js
tests/phpunit/data/resourceloader/sample.json [new file with mode: 0644]
tests/phpunit/includes/XmlTest.php
tests/phpunit/includes/api/ApiQuerySiteinfoTest.php
tests/phpunit/includes/libs/objectcache/WANObjectCacheTest.php
tests/phpunit/includes/resourceloader/ResourceLoaderFileModuleTest.php
tests/phpunit/includes/resourceloader/ResourceLoaderTest.php
tests/qunit/suites/resources/mediawiki/mediawiki.loader.test.js

index 272e0f5..3caae98 100644 (file)
@@ -82,7 +82,6 @@
                <exclude-pattern>*/includes/installer/PhpBugTests\.php</exclude-pattern>
                <exclude-pattern>*/includes/specials/SpecialMostinterwikis\.php</exclude-pattern>
                <exclude-pattern>*/includes/cache/CacheDependency\.php</exclude-pattern>
-               <exclude-pattern>*/includes/cache/CacheHelper\.php</exclude-pattern>
                <exclude-pattern>*/includes/compat/XMPReader\.php</exclude-pattern>
                <exclude-pattern>*/includes/diff/DairikiDiff\.php</exclude-pattern>
                <exclude-pattern>*/includes/specials/SpecialAncientpages\.php</exclude-pattern>
                <exclude-pattern>*/includes/api/ApiRsd\.php</exclude-pattern>
                <exclude-pattern>*/includes/AuthPlugin\.php</exclude-pattern>
                <exclude-pattern>*/includes/cache/CacheDependency\.php</exclude-pattern>
-               <exclude-pattern>*/includes/cache/CacheHelper\.php</exclude-pattern>
                <exclude-pattern>*/includes/compat/XMPReader\.php</exclude-pattern>
                <exclude-pattern>*/includes/deferred/CdnCacheUpdate\.php</exclude-pattern>
                <exclude-pattern>*/includes/diff/DairikiDiff\.php</exclude-pattern>
index 348a0d2..8906211 100644 (file)
@@ -640,7 +640,7 @@ $wgAutoloadLocalClasses = [
        'HttpStatus' => __DIR__ . '/includes/libs/HttpStatus.php',
        'IApiMessage' => __DIR__ . '/includes/api/IApiMessage.php',
        'IBufferingStatsdDataFactory' => __DIR__ . '/includes/libs/stats/IBufferingStatsdDataFactory.php',
-       'ICacheHelper' => __DIR__ . '/includes/cache/CacheHelper.php',
+       'ICacheHelper' => __DIR__ . '/includes/cache/ICacheHelper.php',
        'IContextSource' => __DIR__ . '/includes/context/IContextSource.php',
        'IDBAccessObject' => __DIR__ . '/includes/dao/IDBAccessObject.php',
        'IDatabase' => __DIR__ . '/includes/libs/rdbms/database/IDatabase.php',
index ea76cd6..db5fec3 100644 (file)
@@ -727,6 +727,7 @@ class Block {
                        'ipb_create_account'   => $this->prevents( 'createaccount' ),
                        'ipb_deleted'          => (int)$this->mHideName, // typecast required for SQLite
                        'ipb_allow_usertalk'   => !$this->prevents( 'editownusertalk' ),
+                       'ipb_sitewide'         => $this->isSitewide(),
                ] + CommentStore::getStore()->insert( $dbw, 'ipb_reason', $this->mReason )
                        + ActorMigration::newMigration()->getInsertValues( $dbw, 'ipb_by', $this->getBlocker() );
        }
index 00ccc96..31b0988 100644 (file)
@@ -9020,6 +9020,15 @@ $wgActorTableSchemaMigrationStage = SCHEMA_COMPAT_OLD;
  */
 $wgEnablePartialBlocks = false;
 
+/**
+ * Enable confirmation prompt for rollback actions to prevent accidental rollbacks.
+ * May be disabled to reduce number of clicks needed to perform rollbacks.
+ *
+ * @since 1.33
+ * @var bool
+ */
+$wgEnableRollbackConfirmationPrompt = true;
+
 /**
  * Enable stats monitoring when Block Notices are displayed in different places around core
  * and extensions.
index 1b90a1f..a796030 100644 (file)
@@ -32,7 +32,8 @@
  *
  * @note As of 1.21, XmlJsCode objects cannot be nested inside objects or arrays. The sole
  *       exception is the $args argument to Xml::encodeJsCall() because Xml::encodeJsVar() is
- *       called for each individual element in that array.
+ *       called for each individual element in that array. If you need to encode an object or array
+ *       containing XmlJsCode objects, use XmlJsCode::encodeObject() to re-encode it first.
  *
  * @since 1.17
  */
@@ -42,4 +43,33 @@ class XmlJsCode {
        function __construct( $value ) {
                $this->value = $value;
        }
+
+       /**
+        * Encode an object containing XmlJsCode objects.
+        *
+        * This takes an object or associative array where (some of) the values are XmlJsCode objects,
+        * and re-encodes it as a single XmlJsCode object.
+        *
+        * @since 1.33
+        * @param object|array $obj Object or associative array to encode
+        * @param bool $pretty If true, add non-significant whitespace to improve readability.
+        * @return XmlJsCode
+        */
+       public static function encodeObject( $obj, $pretty = false ) {
+               $parts = [];
+               foreach ( $obj as $key => $value ) {
+                       $parts[] =
+                               ( $pretty ? '    ' : '' ) .
+                               Xml::encodeJsVar( $key, $pretty ) .
+                               ( $pretty ? ': ' : ':' ) .
+                               Xml::encodeJsVar( $value, $pretty );
+               }
+               return new self(
+                       '{' .
+                       ( $pretty ? "\n" : '' ) .
+                       implode( $pretty ? ",\n" : ',', $parts ) .
+                       ( $pretty ? "\n" : '' ) .
+                       '}'
+               );
+       }
 }
index 2907cf9..8ffe98f 100644 (file)
        "apihelp-undelete-param-tags": "Modifica etichette da applicare all'elemento del registro delle cancellazioni.",
        "apihelp-unlinkaccount-summary": "Rimuove un'utenza di terze parti collegata all'utente corrente.",
        "apihelp-unlinkaccount-example-simple": "Tentativo di rimuovere il collegamento dell'utente corrente per il provider associato con <kbd>FooAuthenticationRequest</kbd>.",
-       "apihelp-upload-param-watch": "Guarda la pagina.",
+       "apihelp-upload-param-watch": "Aggiungi agli osservati speciali.",
        "apihelp-upload-param-file": "Contenuto del file.",
        "apihelp-upload-example-url": "Carica da un URL.",
        "apihelp-userrights-param-user": "Nome utente.",
index 93685e3..d7669eb 100644 (file)
  * @author Jeroen De Dauw < jeroendedauw@gmail.com >
  */
 
-/**
- * Interface for all classes implementing CacheHelper functionality.
- *
- * @since 1.20
- */
-interface ICacheHelper {
-       /**
-        * Sets if the cache should be enabled or not.
-        *
-        * @since 1.20
-        * @param bool $cacheEnabled
-        */
-       function setCacheEnabled( $cacheEnabled );
-
-       /**
-        * Initializes the caching.
-        * Should be called before the first time anything is added via addCachedHTML.
-        *
-        * @since 1.20
-        *
-        * @param int|null $cacheExpiry Sets the cache expiry, either ttl in seconds or unix timestamp.
-        * @param bool|null $cacheEnabled Sets if the cache should be enabled or not.
-        */
-       function startCache( $cacheExpiry = null, $cacheEnabled = null );
-
-       /**
-        * Get a cached value if available or compute it if not and then cache it if possible.
-        * The provided $computeFunction is only called when the computation needs to happen
-        * and should return a result value. $args are arguments that will be passed to the
-        * compute function when called.
-        *
-        * @since 1.20
-        *
-        * @param callable $computeFunction
-        * @param array|mixed $args
-        * @param string|null $key
-        *
-        * @return mixed
-        */
-       function getCachedValue( $computeFunction, $args = [], $key = null );
-
-       /**
-        * Saves the HTML to the cache in case it got recomputed.
-        * Should be called after the last time anything is added via addCachedHTML.
-        *
-        * @since 1.20
-        */
-       function saveCache();
-
-       /**
-        * Sets the time to live for the cache, in seconds or a unix timestamp
-        * indicating the point of expiry...
-        *
-        * @since 1.20
-        *
-        * @param int $cacheExpiry
-        */
-       function setExpiry( $cacheExpiry );
-}
-
 use MediaWiki\MediaWikiServices;
 
 /**
diff --git a/includes/cache/ICacheHelper.php b/includes/cache/ICacheHelper.php
new file mode 100644 (file)
index 0000000..54e9aac
--- /dev/null
@@ -0,0 +1,83 @@
+<?php
+/**
+ * Cache of various elements in a single cache entry.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ *
+ * @file
+ * @license GPL-2.0-or-later
+ * @author Jeroen De Dauw < jeroendedauw@gmail.com >
+ */
+
+/**
+ * Interface for all classes implementing CacheHelper functionality.
+ *
+ * @since 1.20
+ */
+interface ICacheHelper {
+       /**
+        * Sets if the cache should be enabled or not.
+        *
+        * @since 1.20
+        * @param bool $cacheEnabled
+        */
+       function setCacheEnabled( $cacheEnabled );
+
+       /**
+        * Initializes the caching.
+        * Should be called before the first time anything is added via addCachedHTML.
+        *
+        * @since 1.20
+        *
+        * @param int|null $cacheExpiry Sets the cache expiry, either ttl in seconds or unix timestamp.
+        * @param bool|null $cacheEnabled Sets if the cache should be enabled or not.
+        */
+       function startCache( $cacheExpiry = null, $cacheEnabled = null );
+
+       /**
+        * Get a cached value if available or compute it if not and then cache it if possible.
+        * The provided $computeFunction is only called when the computation needs to happen
+        * and should return a result value. $args are arguments that will be passed to the
+        * compute function when called.
+        *
+        * @since 1.20
+        *
+        * @param callable $computeFunction
+        * @param array|mixed $args
+        * @param string|null $key
+        *
+        * @return mixed
+        */
+       function getCachedValue( $computeFunction, $args = [], $key = null );
+
+       /**
+        * Saves the HTML to the cache in case it got recomputed.
+        * Should be called after the last time anything is added via addCachedHTML.
+        *
+        * @since 1.20
+        */
+       function saveCache();
+
+       /**
+        * Sets the time to live for the cache, in seconds or a unix timestamp
+        * indicating the point of expiry...
+        *
+        * @since 1.20
+        *
+        * @param int $cacheExpiry
+        */
+       function setExpiry( $cacheExpiry );
+}
index c513aed..0a59dec 100644 (file)
@@ -1081,7 +1081,7 @@ MESSAGE;
                                                        // Load scripts raw...
                                                        $strContent = $scripts;
                                                } elseif ( is_array( $scripts ) ) {
-                                                       // ...except when $scripts is an array of URLs
+                                                       // ...except when $scripts is an array of URLs or an associative array
                                                        $strContent = self::makeLoaderImplementScript( $implementKey, $scripts, [], [], [] );
                                                }
                                                break;
@@ -1202,7 +1202,8 @@ MESSAGE;
         *
         * @param string $name Module name or implement key (format "`[name]@[version]`")
         * @param XmlJsCode|array|string $scripts Code as XmlJsCode (to be wrapped in a closure),
-        *  list of URLs to JavaScript files, or a string of JavaScript for `$.globalEval`.
+        *  list of URLs to JavaScript files, string of JavaScript for `$.globalEval`, or array with
+        *  'files' and 'main' properties (see ResourceLoaderModule::getScript())
         * @param mixed $styles Array of CSS strings keyed by media type, or an array of lists of URLs
         *   to CSS files keyed by media type
         * @param mixed $messages List of messages associated with this module. May either be an
@@ -1222,9 +1223,30 @@ MESSAGE;
                        } else {
                                $scripts = new XmlJsCode( 'function($,jQuery,require,module){' . $scripts->value . '}' );
                        }
+               } elseif ( is_array( $scripts ) && isset( $scripts['files'] ) ) {
+                       $files = $scripts['files'];
+                       foreach ( $files as $path => &$file ) {
+                               // $file is changed (by reference) from a descriptor array to the content of the file
+                               // All of these essentially do $file = $file['content'];, some just have wrapping around it
+                               if ( $file['type'] === 'script' ) {
+                                       // Multi-file modules only get two parameters ($ and jQuery are being phased out)
+                                       if ( self::inDebugMode() ) {
+                                               $file = new XmlJsCode( "function ( require, module ) {\n{$file['content']}\n}" );
+                                       } else {
+                                               $file = new XmlJsCode( 'function(require,module){' . $file['content'] . '}' );
+                                       }
+                               } else {
+                                       $file = $file['content'];
+                               }
+                       }
+                       $scripts = XmlJsCode::encodeObject( [
+                               'main' => $scripts['main'],
+                               'files' => XmlJsCode::encodeObject( $files, self::inDebugMode() )
+                       ], self::inDebugMode() );
                } elseif ( !is_string( $scripts ) && !is_array( $scripts ) ) {
                        throw new MWException( 'Invalid scripts error. Array of URLs or string of code expected.' );
                }
+
                // mw.loader.implement requires 'styles', 'messages' and 'templates' to be objects (not
                // arrays). json_encode considers empty arrays to be numerical and outputs "[]" instead
                // of "{}". Force them to objects.
@@ -1233,7 +1255,7 @@ MESSAGE;
                        $scripts,
                        (object)$styles,
                        (object)$messages,
-                       (object)$templates,
+                       (object)$templates
                ];
                self::trimArray( $module );
 
index 42bd66a..0e53e5e 100644 (file)
@@ -90,6 +90,21 @@ class ResourceLoaderFileModule extends ResourceLoaderModule {
         */
        protected $skinStyles = [];
 
+       /**
+        * @var array List of packaged files to make available through require()
+        * @par Usage:
+        * @code
+        * [ [file-path], [file-path], ... ]
+        * @endcode
+        */
+       protected $packageFiles = null;
+
+       /**
+        * @var array Expanded versions of $packageFiles, lazy-computed by expandPackageFiles();
+        *  keyed by context hash
+        */
+       private $expandedPackageFiles = [];
+
        /**
         * @var array List of modules this module depends on
         * @par Usage:
@@ -171,7 +186,7 @@ class ResourceLoaderFileModule extends ResourceLoaderModule {
         *         'remoteExtPath' => [base path],
         *         // Equivalent of remoteBasePath, but relative to $wgStylePath
         *         'remoteSkinPath' => [base path],
-        *         // Scripts to always include
+        *         // Scripts to always include (cannot be set if 'packageFiles' is also set, see below)
         *         'scripts' => [file path string or array of file path strings],
         *         // Scripts to include in specific language contexts
         *         'languageScripts' => [
@@ -183,6 +198,19 @@ class ResourceLoaderFileModule extends ResourceLoaderModule {
         *         ],
         *         // Scripts to include in debug contexts
         *         'debugScripts' => [file path string or array of file path strings],
+        *         // For package modules: files to make available for internal require() use
+        *         // 'type' is optional, and will be inferred from the file name extension if omitted
+        *         // 'config' can only be used when 'type' is 'data'; vars are resolved with Config::get()
+        *         // If 'packageFiles' is set, 'scripts' cannot also be set
+        *         'packageFiles' => [
+        *             [file path string], // or:
+        *             [file alias] => [file path string], // or:
+        *             [file alias] => [ 'file' => [file path string], 'type' => 'script'|'data' ], // or:
+        *             [file alias] => [ 'content' => [string], 'type' => 'script'|'data' ], // or:
+        *             [file alias] => [ 'callback' => [callable], 'type' => 'script'|'data' ], // or:
+        *             [file alias] => [ 'config' => [ [config var name], ... ], 'type' => 'data' ], // or:
+        *             [file alias] => [ 'config' => [ [JS name] => [PHP name] ], 'type' => 'data' ],
+        *         ],
         *         // Modules which must be loaded before this module
         *         'dependencies' => [module name string or array of module name strings],
         *         'templates' => [
@@ -224,6 +252,7 @@ class ResourceLoaderFileModule extends ResourceLoaderModule {
                                case 'scripts':
                                case 'debugScripts':
                                case 'styles':
+                               case 'packageFiles':
                                        $this->{$member} = (array)$option;
                                        break;
                                case 'templates':
@@ -276,6 +305,9 @@ class ResourceLoaderFileModule extends ResourceLoaderModule {
                                        break;
                        }
                }
+               if ( isset( $options['scripts'] ) && isset( $options['packageFiles'] ) ) {
+                       throw new InvalidArgumentException( "A module may not set both 'scripts' and 'packageFiles'" );
+               }
                if ( $hasTemplates ) {
                        $this->dependencies[] = 'mediawiki.template';
                        // Ensure relevant template compiler module gets loaded
@@ -346,11 +378,21 @@ class ResourceLoaderFileModule extends ResourceLoaderModule {
         * Gets all scripts for a given context concatenated together.
         *
         * @param ResourceLoaderContext $context Context in which to generate script
-        * @return string JavaScript code for $context
+        * @return string|array JavaScript code for $context, or package files data structure
         */
        public function getScript( ResourceLoaderContext $context ) {
+               $deprecationScript = $this->getDeprecationInformation();
+               if ( $this->packageFiles !== null ) {
+                       $packageFiles = $this->getPackageFiles( $context );
+                       if ( $deprecationScript ) {
+                               $mainFile =& $packageFiles['files'][ $packageFiles['main'] ];
+                               $mainFile['content'] = $deprecationScript . $mainFile['content'];
+                       }
+                       return $packageFiles;
+               }
+
                $files = $this->getScriptFiles( $context );
-               return $this->getDeprecationInformation() . $this->readScriptFiles( $files );
+               return $deprecationScript . $this->readScriptFiles( $files );
        }
 
        /**
@@ -372,7 +414,9 @@ class ResourceLoaderFileModule extends ResourceLoaderModule {
         * @return bool
         */
        public function supportsURLLoading() {
-               return $this->debugRaw;
+               // If package files are involved, don't support URL loading, because that breaks
+               // scoped require() functions
+               return $this->debugRaw && !$this->packageFiles;
        }
 
        /**
@@ -507,9 +551,18 @@ class ResourceLoaderFileModule extends ResourceLoaderModule {
                        $files = array_merge( $files, $styleFiles );
                }
 
+               // Extract file names for package files
+               $expandedPackageFiles = $this->expandPackageFiles( $context );
+               $packageFiles = $expandedPackageFiles ?
+                       array_filter( array_map( function ( $fileInfo ) {
+                               return $fileInfo['filePath'] ?? null;
+                       }, $expandedPackageFiles['files'] ) ) :
+                       [];
+
                // Final merge, this should result in a master list of dependent files
                $files = array_merge(
                        $files,
+                       $packageFiles,
                        $this->scripts,
                        $this->templates,
                        $context->getDebug() ? $this->debugScripts : [],
@@ -568,6 +621,7 @@ class ResourceLoaderFileModule extends ResourceLoaderModule {
 
                $summary[] = [
                        'options' => $options,
+                       'packageFiles' => $this->expandPackageFiles( $context ),
                        'fileHashes' => $this->getFileHashes( $context ),
                        'messageBlob' => $this->getMessageBlob( $context ),
                ];
@@ -615,6 +669,18 @@ class ResourceLoaderFileModule extends ResourceLoaderModule {
                return preg_match( '/\.less$/i', $path ) ? 'less' : 'css';
        }
 
+       /**
+        * Infer the file type from a package file path.
+        * @param string $path
+        * @return string 'script' or 'data'
+        */
+       public static function getPackageFileType( $path ) {
+               if ( preg_match( '/\.json$/i', $path ) ) {
+                       return 'data';
+               }
+               return 'script';
+       }
+
        /**
         * Collates file paths by option (where provided).
         *
@@ -790,7 +856,7 @@ class ResourceLoaderFileModule extends ResourceLoaderModule {
         * Get the contents of a list of JavaScript files. Helper for getScript().
         *
         * @param array $scripts List of file paths to scripts to read, remap and concetenate
-        * @return string Concatenated and remapped JavaScript data from $scripts
+        * @return string Concatenated JavaScript data from $scripts
         * @throws MWException
         */
        private function readScriptFiles( array $scripts ) {
@@ -1010,6 +1076,147 @@ class ResourceLoaderFileModule extends ResourceLoaderModule {
                return $templates;
        }
 
+       /**
+        * Expand the packageFiles definition into something that's (almost) the right format for
+        * getPackageFiles() to return. This expands shorthands, resolves config vars and callbacks,
+        * but does not expand file paths or read the actual contents of files. Those things are done
+        * by getPackageFiles().
+        *
+        * This is split up in this way so that getFileHashes() can get a list of file names, and
+        * getDefinitionSummary() can get config vars and callback results in their expanded form.
+        *
+        * @param ResourceLoaderContext $context
+        * @return array|null
+        */
+       private function expandPackageFiles( ResourceLoaderContext $context ) {
+               $hash = $context->getHash();
+               if ( isset( $this->expandedPackageFiles[$hash] ) ) {
+                       return $this->expandedPackageFiles[$hash];
+               }
+               if ( $this->packageFiles === null ) {
+                       return null;
+               }
+               $expandedFiles = [];
+               $mainFile = null;
+
+               foreach ( $this->packageFiles as $alias => $fileInfo ) {
+                       // Alias is optional, but only when specfiying plain file names (strings)
+                       if ( is_int( $alias ) ) {
+                               if ( is_array( $fileInfo ) ) {
+                                       $msg = __METHOD__ . ": invalid package file definition for module " .
+                                               "\"{$this->getName()}\": key is required when value is not a string";
+                                       wfDebugLog( 'resourceloader', $msg );
+                                       throw new MWException( $msg );
+                               }
+                               $alias = $fileInfo;
+                       }
+                       if ( !is_array( $fileInfo ) ) {
+                               $fileInfo = [ 'file' => $fileInfo ];
+                       }
+
+                       // Infer type from alias if needed
+                       $type = $fileInfo['type'] ?? self::getPackageFileType( $alias );
+                       $expanded = [ 'type' => $type ];
+                       if ( !empty( $fileInfo['main'] ) ) {
+                               $mainFile = $alias;
+                               if ( $type !== 'script' ) {
+                                       $msg = __METHOD__ . ": invalid package file definition for module " .
+                                               "\"{$this->getName()}\": main file \"$mainFile\" must be of type \"script\", not \"$type\"";
+                                       wfDebugLog( 'resourceloader', $msg );
+                                       throw new MWException( $msg );
+                               }
+                       }
+
+                       if ( isset( $fileInfo['content'] ) ) {
+                               $expanded['content'] = $fileInfo['content'];
+                       } elseif ( isset( $fileInfo['file'] ) ) {
+                               $expanded['filePath'] = $fileInfo['file'];
+                       } elseif ( isset( $fileInfo['callback'] ) ) {
+                               if ( is_callable( $fileInfo['callback'] ) ) {
+                                       $expanded['content'] = $fileInfo['callback']( $context );
+                               } else {
+                                       $msg = __METHOD__ . ": invalid callback for package file \"$alias\"" .
+                                               " in module \"{$this->getName()}\"";
+                                       wfDebugLog( 'resourceloader', $msg );
+                                       throw new MWException( $msg );
+                               }
+                       } elseif ( isset( $fileInfo['config'] ) ) {
+                               if ( $type !== 'data' ) {
+                                       $msg = __METHOD__ . ": invalid use of \"config\" for package file \"$alias\" in module " .
+                                               "\"{$this->getName()}\": type must be \"data\" but is \"$type\"";
+                                       wfDebugLog( 'resourceloader', $msg );
+                                       throw new MWException( $msg );
+                               }
+                               $expandedConfig = [];
+                               foreach ( $fileInfo['config'] as $key => $var ) {
+                                       $expandedConfig[ is_numeric( $key ) ? $var : $key ] = $this->getConfig()->get( $var );
+                               }
+                               $expanded['content'] = $expandedConfig;
+                       } elseif ( !empty( $fileInfo['main'] ) ) {
+                               // 'foo.js' => [ 'main' => true ] is shorthand
+                               $expanded['filePath'] = $alias;
+                       } else {
+                               $msg = __METHOD__ . ": invalid package file definition for \"$alias\" in module " .
+                                       "\"{$this->getName()}\": one of \"file\", \"content\", \"callback\" or \"config\" must be set";
+                               wfDebugLog( 'resourceloader', $msg );
+                               throw new MWException( $msg );
+                       }
+
+                       $expandedFiles[$alias] = $expanded;
+               }
+
+               if ( $expandedFiles && $mainFile === null ) {
+                       // The first package file that is a script is the main file
+                       foreach ( $expandedFiles as $path => &$file ) {
+                               if ( $file['type'] === 'script' ) {
+                                       $mainFile = $path;
+                                       break;
+                               }
+                       }
+               }
+
+               $result = [
+                       'main' => $mainFile,
+                       'files' => $expandedFiles
+               ];
+
+               $this->expandedPackageFiles[$hash] = $result;
+               return $result;
+       }
+
+       /**
+        * Resolves the package files defintion and generates the content of each package file.
+        * @param ResourceLoaderContext $context
+        * @return array Package files data structure, see ResourceLoaderModule::getScript()
+        */
+       public function getPackageFiles( ResourceLoaderContext $context ) {
+               if ( $this->packageFiles === null ) {
+                       return null;
+               }
+               $expandedPackageFiles = $this->expandPackageFiles( $context );
+
+               // Expand file contents
+               foreach ( $expandedPackageFiles['files'] as &$fileInfo ) {
+                       if ( isset( $fileInfo['filePath'] ) ) {
+                               $localPath = $this->getLocalPath( $fileInfo['filePath'] );
+                               if ( !file_exists( $localPath ) ) {
+                                       $msg = __METHOD__ . ": package file not found: \"$localPath\"" .
+                                               " in module \"{$this->getName()}\"";
+                                       wfDebugLog( 'resourceloader', $msg );
+                                       throw new MWException( $msg );
+                               }
+                               $content = $this->stripBom( file_get_contents( $localPath ) );
+                               if ( $fileInfo['type'] === 'data' ) {
+                                       $content = json_decode( $content );
+                               }
+                               $fileInfo['content'] = $content;
+                               unset( $fileInfo['filePath'] );
+                       }
+               }
+
+               return $expandedPackageFiles;
+       }
+
        /**
         * Takes an input string and removes the UTF-8 BOM character if present
         *
index 30b2aa7..ae79dda 100644 (file)
@@ -159,8 +159,20 @@ abstract class ResourceLoaderModule implements LoggerAwareInterface {
         * Get all JS for this module for a given language and skin.
         * Includes all relevant JS except loader scripts.
         *
+        * For "plain" script modules, this should return a string with JS code. For multi-file modules
+        * where require() is used to load one file from another file, this should return an array
+        * structured as follows:
+        * [
+        *     'files' => [
+        *         'file1.js' => [ 'type' => 'script', 'content' => 'JS code' ],
+        *         'file2.js' => [ 'type' => 'script', 'content' => 'JS code' ],
+        *         'data.json' => [ 'type' => 'data', 'content' => array ]
+        *     ],
+        *     'main' => 'file1.js'
+        * ]
+        *
         * @param ResourceLoaderContext $context
-        * @return string JavaScript code
+        * @return string|array JavaScript code (string), or multi-file structure described above (array)
         */
        public function getScript( ResourceLoaderContext $context ) {
                // Stub, override expected
@@ -691,7 +703,7 @@ abstract class ResourceLoaderModule implements LoggerAwareInterface {
 
                // This MUST build both scripts and styles, regardless of whether $context->getOnly()
                // is 'scripts' or 'styles' because the result is used by getVersionHash which
-               // must be consistent regardles of the 'only' filter on the current request.
+               // must be consistent regardless of the 'only' filter on the current request.
                // Also, when introducing new module content resources (e.g. templates, headers),
                // these should only be included in the array when they are non-empty so that
                // existing modules not using them do not get their cache invalidated.
index f00e929..1748f4b 100644 (file)
        "createacct-emailoptional": "تیرنشۊن ٱنجومانامٱ",
        "createacct-email-ph": "تیرنشۊن ٱنجوماناماْ تۊناْ بزنین.",
        "createacct-another-email-ph": "تیرنشۊن ٱنجوماناماْ تۊناْ بزنین.",
+       "createaccountmail": "یٱ رازیناْ گوڌٱشتن موڤٱقٱتی ناْ ڤاْنین ڤا کار و سی یٱ تیرنشوݩ ٱنجوماناماْ تیار ڤابیڌاْ باْسیس کونین.",
        "createacct-realname": "نوم راستٱکی(اٛژباری نی)",
        "createacct-reason": "دلیل",
        "createacct-reason-ph": "سی چ ایسا دارین یٱ هساو کاریاری دیٱر راسد اْکونین",
+       "createacct-reason-help": "پاٛیغوم دیار کرداْ میٛن پاٛرستنوماْ راسد کردن هساو کاریاری",
        "createacct-submit": "هساو خوتۊناْ راسد کونین",
-       "createacct-another-submit": "راسد کردن هساڤ کارياری",
+       "createacct-another-submit": "راسد کردن هساو کارياری",
        "createacct-continue-submit": "هساو راسد کردن خوتۊناْ اٛڌاماْ بڌین",
        "createacct-another-continue-submit": "هساڤ راسد کردن خوتۊناْ اٛڌاماْ بڌین",
        "createacct-benefit-heading": "{{SITENAME}}  ڤ دٱسد خٱلکی چی ایسا رٱڤٱندیاری ڤابیڌاْ.",
        "createacct-benefit-body2": "{{PLURAL:$1|بٱلگاْ|بٱلگاْیٱل}}",
        "createacct-benefit-body3": "تازاْ{{PLURAL:$1|هوميار|هوميارٱل}}",
        "badretype": "رازیناْ گوڌٱشتنی کاْ ایسا زاٛیڌیناْ هومبٱراڤٱر نیڌ.",
+       "usernameinprogress": "رٱڤٱندیاری یٱ هساو سی نوم کاریاری کاْ میٛن پیشکرداْ. یاْتی دٱس ڤاڌارین.",
+       "userexists": "نوم کاریاری کاْ داڌیناْ ایساْ ب کاراْ.\nلوتف کونین یٱ نوم دیٱ گولاْڤورچین کونین.",
        "loginerror": "خٱتا سی ڤامیٛن ٱڤوڌن",
        "createacct-error": "خٱتا راس کردن هساو کاریاری",
        "createaccounterror": "نیبۊ هساو کاریاری راسد کونین:$1",
+       "nocookiesfornew": "هساو کاریاری راسد نٱڤابی، سی یو ناْ کاْ ایما نٱتریم سرچشماْساْ پوشت راست کاری کونیم.\nخاتر جٱم بۊین کاْ کۊکیٱل کونشتکار ڤابیناْ، ای بٱلگاْ ناْ ز نۉ سوڤار کونین و یٱ کاْرٱت دیٱ تلاش کونین.",
        "loginsuccesstitle": "ایسا ٱڤوڌین ڤامیٛن",
        "loginsuccess": "'''ایسا ٱڤوڌین ڤامیٛن {{SITENAME}} چی \"$1\".'''",
        "nosuchuser": "چونو کاریاری ڤا نوم \"$1\" نیڌس.\nنوم کاریاری ب هٱرف کۊچیر و گٱپ هٱساساْ , یا [[Special:CreateAccount|یٱ هساو کاریاری دیاْ راسد کونین]].",
        "nosuchusershort": "چونو کاریاری ڤا نوم \"$1\" نیڌس.\nرٱڤشت نڤشتن خوتۊناْ ڤارسی کونین.",
        "nouserspecified": "ایسا ڤا یٱ نوم کاریاری تیار کونین.",
+       "login-userblocked": "کاریار نیاگری ڤابیڌاْ. سلا ٱڤوڌن ڤامیٛن ناراْ",
        "wrongpassword": "رازیناْ گوڌاْشتنی کاْ زاٛیڌیناْ دوروست نیڌ\nمٱنمۊنداریم ز نۉ تلاش کونین.",
        "wrongpasswordempty": "رازیناْ گوڌٱشتنتۊن هالی یا نادیار بی.\nمٱنمۊنداریم ز نۉ تلاش کونین.",
        "passwordtooshort": "رازیناْ گوڌاْشدن ایسا ڤا هٱدٱقل {{PLURAL:$1|1 کاراکتر|$1 کاراکترٱل}} داشداْ بۊ.",
-       "mailmypassword": "ز نۉ داڌن رازينإ گوأرتن",
-       "passwordremindertitle": "رمز موقتی تازه سی {{SITENAME}}",
-       "passwordremindertext": "یٱ نفر (گاشا خوتۊن, ز تیرنشۊن آی پی $1) درخواست یه رمز تازه کرده سی {{SITENAME}} ($4). یه رمز موقتی سی کاربر\n\"$2\" درست شده وگذاشته وابیده به\"$3\". ایر مطابق میل ایسا بوه, نیازه که داخل سیستم بوین ویه رمز تازه انتخاب کنین.\n\nایر آن فرد همچنین درخواست کرده بوه  یونه, یا ایر ایسا رمزتو را به خاط داشته این ,\nوسی مدت طولانی نه خوین هونه تغییر بدین, ایسا وا نادیده بگیرین ای پیام  را وهمچنان زه رمز قدیمی خوتو استفاده کنین",
-       "noemail": "وجود نداره نشانی امیل ضبط وابده زه کاریر \"$1\".",
+       "passwordtoolong": "رازیناْ گوڌاْشدن ایسا نٱڤا  بیشتر ز {{PLURAL:$1|1 کاراکتر|$1 کاراکترٱل}} داشداْ بۊ.",
+       "password-name-match": "رازیناْ گوڌٱشتنتوݩ ڤا نوم کاریاری فٱرخ داشداْ بۊ",
+       "mailmypassword": "ز نۉ داڌن رازیناْ گوڌٱشتن",
+       "passwordremindertitle": "رازیناْ گوڌٱشتن موڤٱقٱتی سی {{SITENAME}}",
+       "passwordremindertext": "یٱ نفر (گاشا خوتوݩ، ز تیرنشوݩ آی پی $1) یٱ رازیناْ گوڌٱشتن تازاْ خاسداْ سی  {{SITENAME}} ($4). یٱ رازیناْ گوڌاْشتن موڤٱقٱتی سی کاریار\n\"$2\" راسد ڤابیڌاْ و میٛن\"$3\" لاهاڌاْ ڤابیڌاْ. ٱ ب دلتوݩ بۊ, ڤا رۉین میٛن ساموناْ و یٱ رازیناْ گوڌاْشتن تازاْ گولاْڤورچین کونین.\n\nٱر هو کٱسی کاْ چونو چی خاسداْ بۊ کاْس دیٱری بۊ, یا ٱر ایسا رازیناْ گوڌٱشتنتوݩ ب ڤیرتوݩ بۊ و سی یٱ گات تیلدار خاین هوناْ آلشد کونین، ایسا ڤا ای پاٛیغوم ناْ باْنین کنار و هٱمچونو هٱمو رازیناْ گوڌٱشتن دیندایی خوتوناْ ڤٱنین ڤا کار.",
+       "noemail": "هیژ تیرنشوݩ ٱنجوماناماْیی سی کاریار \"$1\" زٱفت نٱڤابیڌاْ.",
        "passwordsent": "یه رمز تازه ارسال وابید به نشانی امیل ثبت وابده سی \"$1\".\nلطفا بعد از دریافت آن داخل سیستم بوین.",
        "eauthentsent": "یٱ ٱنجوماناماْ پوشت راست کردنی سی یٱ تیرنشوݩ ڤیجاْ بیٛسی ڤابیڌاْ.\nنیا یو کاْ یٱ ٱنجوماناماْ دیٱر سی هساوتوݩ بیٛسی ڤابۊ، ایسا ڤا نیا رٱدیارکونی ناْ ز ٱنجوماناماْ بگرین، سی یو کاْ هساو ایسا ز راستی پوشت راست ڤابۊ.",
-       "emaildisabled": "اي ديارگأ نترإ إنجومانامإ سيتۈن بفرشنإ",
+       "emaildisabled": "ای دیارگٱ نٱتٱراْ سیتوݩ ٱنجوماناماْ بفرشناْ",
        "accountcreated": "هساو راسد ڤابی",
        "createaccount-title": "هساڤ سي {{SITENAME}} راسد ڤابي",
        "loginlanguagelabel": "زڤون:$1",
index f7e56dc..059a3a3 100644 (file)
        "showtoc": "bımocne",
        "hidetoc": "bınımne",
        "collapsible-collapse": "Teng ke",
-       "collapsible-expand": "Hera ke",
+       "collapsible-expand": "Hera ke",
        "confirmable-confirm": "{{GENDER:$1|Şıma}} pêbawerê?",
        "confirmable-yes": "Eya",
        "confirmable-no": "Nê",
        "headline_tip": "Sewiya 2ıne sername",
        "nowiki_sample": "metnê formatkerdey berze etıya",
        "nowiki_tip": "Goş formatê Wiki ra mekûwe",
-       "image_sample": "Misal resim.jpg",
+       "image_sample": "Nımune.jpg",
        "image_tip": "Dosya tewrkerdiye",
-       "media_sample": "misal.jpg",
+       "media_sample": "Nımune.ogg",
        "media_tip": "Gırey dosye",
        "sig_tip": "İmzay şıma be morê zemani",
        "hr_tip": "Xeta verardiye (teserrufın bıgureyne/bıxebetne)",
        "prefs-dateformat": "Formatê tarixi",
        "prefs-timeoffset": "Ferqê seate",
        "prefs-advancedediting": "Herayen weçinayış",
-       "prefs-developertools": "Xacetanê raverberdoğî",
+       "prefs-developertools": "Hacetê raverberdoği",
        "prefs-editor": "Vurnayoğ",
        "prefs-preview": "Verqayt",
        "prefs-advancedrc": "Tercihê raverberdey",
        "right-sendemail": "Karberanê binî ra e-mail bişirav",
        "right-managechangetags": "[[Special:Tags|Etiketi]] vıraz u aktiv (me)ke",
        "right-applychangetags": "[[Special:Tags|Etiketa]]  vurnayışana piya dezge fi.",
-       "grant-generic": "\"$1\" paketa heqi",
+       "grant-generic": "\"$1\" paketa heqan",
        "grant-group-page-interaction": "Peran na tesiri",
        "grant-group-file-interaction": "Medya na tesiri",
        "grant-group-watchlist-interaction": "Lista da xoya tesir",
        "grant-createaccount": "Hesab vıraze",
        "grant-createeditmovepage": "Perer vırazê, bıvurnê u berê",
        "grant-delete": "Besternayış, revizyon  u qeydé peran",
-       "grant-editinterface": "Canameyê MediaWiki u sitewide/JSON'ê karberi bıvurnê",
-       "grant-editmycssjs": "CSS/JSON/JavaScripta karberiya xo bıvurnê",
+       "grant-editinterface": "Canameyê MediaWiki û sitewide/JSONê karberi bıvurnê",
+       "grant-editmycssjs": "CSS/JSON/JavaScriptê karberiya xo bıvurnê",
        "grant-editmyoptions": "Tercihanê xo û awankerdışê JSONi bıvurne",
        "grant-editmywatchlist": "Listeyseyran de xo bıvırne",
-       "grant-editsiteconfig": "Sitewide u CSS/JS karberi Bıvurne",
+       "grant-editsiteconfig": "Sitewide û CSS/JSê karberi bıvurne",
        "grant-editpage": "Pela mewcude bıvurne",
        "grant-editprotected": "Pela mewcude bıvurne",
        "grant-highvolume": "Vengê berzi dayış",
        "grant-oversight": "Karberan u ploğyayê revizyona bınımn",
        "grant-patrol": "Çım berzê vurnayışanê pele",
-       "grant-privateinfo": "Bıresê melumatê xısusi",
+       "grant-privateinfo": "Bıresê melumatê xısusiyi",
        "grant-protect": "Şeveknayış u wedarıtışê şeveknayışê pelan",
        "grant-rollback": "Pelanê peysergırewtışi bıvurne",
        "grant-sendemail": "Karberanê binan rê e-posta bırışê",
        "action-deleterevision": "revizyoni besternê",
        "action-deletelogentry": "qeydanê cıkewtışan bestere",
        "action-deletedhistory": "verora esteriya perrer bıvin",
-       "action-deletedtext": "Esteriyaye metine revizyoni bımocne",
+       "action-deletedtext": "revizyonê metıniyê esterıteyi bımocne",
        "action-browsearchive": "pelanê esterıteyan bıgeyre",
        "action-undelete": "Ena perre mesterê",
        "action-suppressrevision": "revizyonê nımnayi bıvin u timar kı.",
        "action-editcontentmodel": "Zerrekê modela yu perer timar ke",
        "action-managechangetags": "Vıraz u etiketa aktiv (me) ke",
        "action-applychangetags": "Vurnayışana piya etiket kerdışi zi dezge fi",
-       "action-deletechangetags": "Database ra etiketa besternê",
+       "action-deletechangetags": "etitikan danegeh ra bestere",
        "action-purge": "Ane perer newe ke",
        "nchanges": "$1 {{PLURAL:$1|vurnayış|vurnayışi}}",
        "enhancedrc-since-last-visit": "$1 {{PLURAL:$1|ziyaretê peyêni ra nata}}",
        "recentchanges-legend-plusminus": "''(±123)''",
        "recentchanges-submit": "Bımocne",
        "rcfilters-tag-remove": "'$1' wedare",
-       "rcfilters-legend-heading": "<strong>Lista kılmkerdışa :</strong>",
-       "rcfilters-other-review-tools": "Hacetê çım eştışê bini",
+       "rcfilters-legend-heading": "<strong>Lista kılmkerdışan:</strong>",
+       "rcfilters-other-review-tools": "Hacetê çımeştışê bini",
        "rcfilters-activefilters": "Parzûnê aktifi",
        "rcfilters-activefilters-hide": "Bınımne",
        "rcfilters-activefilters-show": "Bımocne",
        "rcfilters-days-show-hours": "($1 {{PLURAL:$1|saete|saeti}})",
        "rcfilters-quickfilters": "Parzûnê qeydbiyayeyi",
        "rcfilters-quickfilters-placeholder-title": "Qet yew parzûn qeyd nêbiyo",
-       "rcfilters-savedqueries-defaultlabel": "Filtreyê qeyd bıyayey",
+       "rcfilters-savedqueries-defaultlabel": "Parzûnê qeydbiyayeyi",
        "rcfilters-savedqueries-rename": "Reyna name ke",
        "rcfilters-savedqueries-setdefault": "Wa hesabiyaye bımano",
        "rcfilters-savedqueries-remove": "Bestere",
        "rcfilters-savedqueries-apply-label": "Parzûn vıraze",
        "rcfilters-savedqueries-apply-and-setdefault-label": "Parzûno hesebiyaye vıraze",
        "rcfilters-savedqueries-cancel-label": "Bıtexelne",
-       "rcfilters-clear-all-filters": "Filtreya pêroyın pak kerê",
-       "rcfilters-show-new-changes": "Vurnayışanê neweya bımocne",
-       "rcfilters-search-placeholder": "Vurnayışanê peyênan filtre kerê (menuy bıkarne ya zi namey parzûni cıgeyrê)",
-       "rcfilters-invalid-filter": "Filtreyo nêravêrde",
-       "rcfilters-empty-filter": "Filtreyo aktiv çıniyo. Iştirakê cı pêro mocneyênê.",
+       "rcfilters-clear-all-filters": "Parzûnan pêro pak kerê",
+       "rcfilters-show-new-changes": "Vurnayışanê neweyan bımocne",
+       "rcfilters-search-placeholder": "Vurnayışanê peyênan parzûn kerê (menuyi bıgurenê ya zi nameyê parzûni cıgeyrê)",
+       "rcfilters-invalid-filter": "Parzûno nêravêrde",
+       "rcfilters-empty-filter": "Parzûnê aktifi çıniyê. İştırakê cı pêro mocniyenê.",
        "rcfilters-filterlist-title": "Parzûni",
        "rcfilters-filterlist-whatsthis": "Nê çıtewri guriyenê?",
        "rcfilters-highlightmenu-title": "Yew reng weçine",
-       "rcfilters-filterlist-noresults": "Filtre nêvineya",
+       "rcfilters-filterlist-noresults": "Parzûni nêvêniyayi",
        "rcfilters-filtergroup-authorship": "Wayiriya iştırakan",
        "rcfilters-filter-editsbyself-label": "Vurnayışê şıma",
        "rcfilters-filter-editsbyself-description": "İştırakê şıma.",
        "rcfilters-filter-bots-label": "Bot",
        "rcfilters-filter-humans-label": "İnsan (bot niyo)",
        "rcfilters-filter-humans-description": "Terefê insanan ra vuriyayışi.",
-       "rcfilters-filter-reviewstatus-unpatrolled-label": "Dewriyey çım nêeşto",
+       "rcfilters-filter-reviewstatus-unpatrolled-label": "Desturê dewriya ra nêvêrdo",
        "rcfilters-filter-reviewstatus-auto-label": "Otomatik kontrol bi",
        "rcfilters-filtergroup-significance": "Gıraniye",
        "rcfilters-filter-minor-label": "Vurriyayışê werdiyi",
        "rcfilters-exclude-button-off": "Weçinayeyi ciya bıtepışê",
        "rcfilters-exclude-button-on": "Weçinayeyo ciya",
        "rcfilters-view-tags": "Vurnayışê etiketıni",
-       "rcfilters-view-return-to-default-tooltip": "Ravêr esas filtreya menuy",
+       "rcfilters-view-return-to-default-tooltip": "Peyser şo parzûnê menuyê bıngehi",
        "rcfilters-liveupdates-button": "Rocaneyê ganıni",
        "rcfilters-liveupdates-button-title-on": "Rocaneyanê cındeyan ragê",
        "rcfilters-preference-label": "Mabeynrıyê non-JavaScript'i bıkarne",
        "rcfilters-watchlist-preference-label": "Mabeynrıyê non-JavaScript'i bıkarne",
-       "rcfilters-target-page-placeholder": "Jû namey pele (ya zi kategoriy) cı kerê",
+       "rcfilters-target-page-placeholder": "Yew nameyê pele (ya zi kategoriye) cı kerê",
        "rcnotefrom": "Cêr de <strong>$2</strong> ra nata {{PLURAL:$5|vurnayışiyê}} asenê (tewr vêşi <strong>$1</strong> asenê) <strong>$3, $4</strong>",
        "rclistfromreset": "Weçinayışê tarixi ragoze",
        "rclistfrom": "$3 sehat $2 ra tepiya vurnayışanê neweyan bımotne",
        "apisandbox-reset": "Bestere",
        "apisandbox-retry": "Anciya bıcerrebne",
        "apisandbox-helpurls": "Linkê peşti",
-       "apisandbox-examples": "Misali",
+       "apisandbox-examples": "Nımuneyi",
        "apisandbox-dynamic-parameters": "Parametreya debyayi",
        "apisandbox-dynamic-parameters-add-label": "Parametre dek:",
        "apisandbox-dynamic-parameters-add-placeholder": "Nmaey parametrey",
        "checkbox-select": "Weçinaye: $1",
        "checkbox-all": "Pêro",
        "checkbox-none": "Temam",
-       "checkbox-invert": "Verdindayış",
+       "checkbox-invert": "Dimlaşt ke",
        "allpages": "Pêro peli",
        "nextpage": "Pela peyco ($1)",
        "prevpage": "Pela veri ($1)",
        "enotif_body_intro_moved": "{{SITENAME}} de pera $1 $PAGEEDITDATE de {{gender:$2|$2}}i berd, rewizyonê $3 bıvin.",
        "enotif_body_intro_restored": "{{SITENAME}} de pera $1 $PAGEEDITDATE de {{gender:$2|$2}}i timar ke, rewizyonê $3 bıvin.",
        "enotif_body_intro_changed": "{{SITENAME}} de pera $1 $PAGEEDITDATE de {{gender:$2|$2}}i vurne, rewizyonê $3 bıvin.",
-       "enotif_lastvisited": "Ziyaretê şıma yê peyêni ra nata vurnayışi pêro, $1'i bıvinê",
-       "enotif_lastdiff": "Nê vurnayışi bıvinê, bıewni $1'i",
+       "enotif_lastvisited": "Ziyaretê şımayê peyêni ra nata vurnayışi pêro, $1 bıvênê",
+       "enotif_lastdiff": "Nê vurnayışi bıvêne, $1 bewne",
        "enotif_anon_editor": "karbero anonim $1",
        "enotif_body": "Erciyayê $WATCHINGUSERNAME,\n\n$PAGEINTRO $NEWPAGE\n\neniya timaroği: $PAGESUMMARY $PAGEMINOREDIT\n\nTimaroğiya irtibat:\nmail: $PAGEEDITOR_EMAIL\nwiki: $PAGEEDITOR_WIKI\n\nno pel o ke behs beno heta ziyaret kerdışê yewna heli, mesajê vuriyayişi nêşawiyeno.\n\n           {{SITENAME}} sistemê hişyariyê keyepeli.\n\n--\nQey vurnayişê eyari:\n{{canonicalurl:{{#Special:Watchlist/edit}}}}\n\nQey vurnayişê eyaran de lista seyri:\n{{canonicalurl:{{#special:EditWatchlist}}}}\n\nQey wedarayişê ena pele liste xo ra seyr kerdişi, şo\n$UNWATCHURL\n\nQey hemkari u pêşniyazi:\n$HELPPAGE",
        "enotif_minoredit": "No yew vırnayışo werdiyo",
        "changecontentmodel-model-label": "Modelê zerrekiyo newe",
        "changecontentmodel-reason-label": "Sebeb:",
        "changecontentmodel-submit": "Bıvırne",
-       "changecontentmodel-success-title": "Modelê zerreki vuriya",
+       "changecontentmodel-success-title": "Modelê zerreki vurriya",
        "log-name-contentmodel": "Qeydê vurnayışanê modelê zerreki",
        "logentry-contentmodel-change-revertlink": "peyser biya",
        "logentry-contentmodel-change-revert": "peyser biya",
        "modifiedarticleprotection": "Qe \"[[$1]]\", seviye kılit kerdişi vurnayi biyo",
        "unprotectedarticle": "Starkerdışê \"[[$1]]\" hewadeya",
        "movedarticleprotection": "eyarê pawıtışi no \"[[$2]]\" peli ra kırışiya no \"[[$1]]\" peli",
-       "protectedarticle-comment": "\"[[$1]]\" {{GENDER:$2|staryaya}}",
-       "modifiedarticleprotection-comment": "Seba \"[[$1]]\" {{GENDER:$2|sewiyey statyayışi vuriyê}}",
+       "protectedarticle-comment": "\"[[$1]]\" {{GENDER:$2|sıtariya}}",
+       "modifiedarticleprotection-comment": "Seba \"[[$1]]\" rê {{GENDER:$2|sewiyaya şeveknayışi vurriye}}",
        "protect-title": "qey \"$1\" yew seviyaya pawıtışi bıvıcinê",
        "protect-title-notallowed": "Star kerdış sewiyeyê \"$1\" bıvinê",
        "prot_1movedto2": "nameyê [[$1]] peli yo newe: [[$2]]",
        "import-mapping-namespace": "Dek yu canamey miyan",
        "import-mapping-subpage": "Bınnpeley ena peler deyne azere ke",
        "import-upload-filename": "Nameyê dosyayi:",
-       "import-upload-username-prefix": "Prefiksê interwiki:",
+       "import-upload-username-prefix": "Prefiksê interwikiyi:",
        "import-comment": "Mışewre:",
        "importtext": "Kerem ke dosyay, çımeyê wiki ra pê [[Special:Export|kırıştışê teberdayişi]] bıdê teber, Komputerê xo de qeyd kerê u bar kerê tiya.",
        "importstart": "Pelan împort kenî",
        "pageinfo-display-title": "Sernuşteyo ke mosneyêno",
        "pageinfo-default-sort": "Hesıbyaye mırfeyo kılm",
        "pageinfo-length": "Derdeya pela (bayti heta)",
-       "pageinfo-namespace": "Heruna namey",
+       "pageinfo-namespace": "Heruna nameyi",
        "pageinfo-article-id": "Kamiya pele",
        "pageinfo-language": "Zıwanê zerreyê pele",
        "pageinfo-language-change": "bıvırne",
        "newimages-summary": "Ena pela xasi dosyayi ke peni de bar biyayeyi mocnane.",
        "newimages-legend": "Parzûn",
        "newimages-label": "Nameyê dosya ( ya zi parçe ey)",
-       "newimages-user": "Adresa IP ya zi namey karberi",
+       "newimages-user": "Adresa IPyi ya zi nameyê karberi",
        "newimages-showbots": "Selaganë boti bıvin",
        "newimages-hidepatrolled": "Selaganë dewriyeyan bıvinë",
-       "newimages-mediatype": "Tewrê Medya :",
+       "newimages-mediatype": "Tewrê medya:",
        "noimages": "Çik çini yo.",
        "ilsubmit": "Cı geyre",
        "bydate": "Gorey zemani",
        "tag-filter": "Parzûnê [[Special:Tags|etiketi]]:",
        "tag-filter-submit": "Parzûn",
        "tag-list-wrapper": "[[Special:Tags|{{PLURAL:$1|Etiket|Etiketi}}]]: $2",
-       "tag-mw-new-redirect": "Redirekto newe",
-       "tag-mw-blank": "Veng kerdış",
+       "tag-mw-new-redirect": "Serşıkıtışo newe",
+       "tag-mw-blank": "Vengkerdış",
        "tag-mw-blank-description": "Vengiya na pele bıvurne",
-       "tag-mw-replace": "zerre vuriya",
-       "tag-mw-rollback": "Peyser ardış",
-       "tag-mw-undo": "Peyser bıgirê",
+       "tag-mw-replace": "Zerrek vurriya",
+       "tag-mw-rollback": "Peyserardış",
+       "tag-mw-undo": "Peyser bıgêrê",
        "tags-title": "Etiketi",
        "tags-intro": "Ena pele etiketê ke be vurnayışê nuşiyayışi ra nişan biyê û maneyê inan lista kena.",
        "tags-tag": "Nameyê etiketi",
        "tags-actions-header": "Kerdışi",
        "tags-active-yes": "Eya",
        "tags-active-no": "Nê",
-       "tags-source-extension": "Terefê Softwarey ra şınasêna",
-       "tags-source-manual": "Karberan u botan rê pey destiya kenêno",
+       "tags-source-extension": "Terefê nuştebari ra şınasniyeno",
+       "tags-source-manual": "Terefê karberan û botan ra be dest ra gureniyeno",
        "tags-edit": "bıvurne",
        "tags-delete": "bestere",
        "tags-activate": "Aktiv ke",
        "tags-deactivate": "Aktiv mek",
        "tags-hitcount": "$1 {{PLURAL:$1|vurnayış|vurnayışi}}",
-       "tags-create-heading": "Etiketo newe cı kerê",
+       "tags-create-heading": "Etiketo newe vırazê",
        "tags-create-tag-name": "Nameyê etiketi:",
        "tags-create-reason": "Sebeb:",
        "tags-create-submit": "Vıraze",
-       "tags-delete-title": "Etiketi bıesterne",
+       "tags-delete-title": "Etiketi bestere",
        "tags-delete-reason": "Sebeb:",
-       "tags-activate-title": "Etiketê aktivi",
+       "tags-activate-title": "Etiketê aktifi",
        "tags-activate-reason": "Sebeb:",
-       "tags-activate-submit": "Aktivite",
-       "tags-deactivate-title": "Etiketê ke aktiv niyê",
+       "tags-activate-submit": "Aktif ke",
+       "tags-deactivate-title": "Etiketê ke aktif niyê",
        "tags-deactivate-reason": "Sebeb:",
-       "tags-deactivate-submit": "Aktiv niyê",
-       "tags-edit-title": "Etiketi bıvurne",
-       "tags-edit-manage-link": "Etiketi idare kerê",
-       "tags-edit-existing-tags": "Etiketê ke estê :",
+       "tags-deactivate-submit": "Aktif niyê",
+       "tags-edit-title": "Etiketan bıvurne",
+       "tags-edit-manage-link": "Etiketan idare kerê",
+       "tags-edit-existing-tags": "Etiketê ke estê:",
        "tags-edit-existing-tags-none": "<em>Qet yew</em>",
-       "tags-edit-new-tags": "Etiketo newe :",
-       "tags-edit-add": "Nê etiketa de kerê :",
+       "tags-edit-new-tags": "Etiketê neweyi:",
+       "tags-edit-add": "Nê etiketan cı kerê:",
        "tags-edit-reason": "Sebeb:",
        "comparepages": "Pelan têversanê",
        "compare-page1": "Pele 1",
        "compare-title-not-exists": "Sernameyo ke şımayê vanê mewcud niyo.",
        "compare-revision-not-exists": "Revizyono ke şımaye vanê mewcud niyo.",
        "diff-form": "Ferqi",
-       "diff-form-submit": "Ferqa bıvin",
+       "diff-form-submit": "Ferqan bımocne",
        "permanentlink": "Gıreyo daimi",
-       "permanentlink-revid": "Revizyona ID",
+       "permanentlink-revid": "Revizyonê IDyi",
        "permanentlink-submit": "Şo revizyoni",
        "dberr-problems": "Mayê muxulêm! Ena sita dı newke xırabiya teknik esta.",
        "dberr-again": "Dı-rê deqiqeyi vınde û heni bar ke.",
index 4b361b4..fa028be 100644 (file)
        "exif-gpsdop": "Nákvæmni mælinga",
        "exif-gpsspeedref": "Hraðaeining",
        "exif-gpsspeed": "Hraði GPS-móttakara",
+       "exif-gpstrackref": "Tilvísun í stefnu hreyfingar",
        "exif-gpstrack": "Átt hreyfingar",
+       "exif-gpsimgdirectionref": "Tilvísun fyrir stefnu myndar",
        "exif-gpsimgdirection": "Stefna myndarinnar",
        "exif-gpsmapdatum": "Landmælingagögn",
        "exif-gpsdestlatituderef": "Tilvísun breiddargráðu áfangastaðar",
index 23d6235..d9c1fee 100644 (file)
@@ -7,6 +7,7 @@
        },
        "exif-orientation": "ⴰⵙⵡⴰⵍⴰ",
        "exif-datetime": "ⴰⵙⴰⴽⵓⴷ ⴷ ⵡⴰⴽⵓⴷ ⵏ ⵓⵙⵏⴼⵍ ⵏ ⵓⴼⴰⵢⵍⵓ",
+       "exif-datetimedigitized": "ⴰⵙⴰⴽⵓⴷ ⴷ ⵡⴰⴽⵓⴷ ⵏ ⵓⵙⵓⵟⵟⵏ",
        "exif-flash": "ⴼⵍⴰⵛ",
        "exif-source": "ⴰⵙⴰⴳⵎ",
        "exif-languagecode": "ⵜⵓⵜⵍⴰⵢⵜ",
index 01138e3..6f53635 100644 (file)
        "resetpass-abort-generic": "Le cambio del contrasigno ha essite abortate per un extension.",
        "resetpass-expired": "Le contrasigno ha expirate. Per favor defini un nove contrasigno pro aperir session.",
        "resetpass-expired-soft": "Le contrasigno ha expirate e debe esser cambiate. Per favor, elige un nove contrasigno ora, o clicca sur \"{{int:authprovider-resetpass-skip-label}}\" pro cambiar lo plus tarde.",
+       "resetpass-validity": "Tu contrasigno non es valide: $1\n\nPer favor defini un nove contrasigno pro aperir session.",
        "resetpass-validity-soft": "Le contrasigno non es valide: $1\n\nPer favor, elige un nove contrasigno ora, o clicca sur \"{{int:authprovider-resetpass-skip-label}}\" pro cambiar lo plus tarde.",
        "passwordreset": "Reinitialisar contrasigno",
        "passwordreset-text-one": "Completa iste formulario pro reinitialisar tu contrasigno.",
        "blockedtext": "<strong>Tu nomine de usator o adresse IP ha essite blocate.</strong>\n\nLe blocada esseva facite per $1.\nLe motivo presentate es <em>$2</em>.\n\n* Initio del blocada: $8\n* Expiration del blocada: $6\n* Le blocato intendite: $7\n\nTu pote contactar $1 o un altere [[{{MediaWiki:Grouppage-sysop}}|administrator]] pro discuter le blocada.\nTu pote solmente usar le function \"{{int:emailuser}}\" si un adresse de e-mail valide es specificate in le\n[[Special:Preferences|preferentias de tu conto]] e tu non ha essite blocate de usar lo.\nTu adresse IP actual es $3, e le ID del blocada es #$5.\nPer favor include tote le detalios supra specificate in omne correspondentia.",
        "autoblockedtext": "Tu adresse IP ha essite automaticamente blocate perque un altere usator lo usava qui esseva blocate per $1.\nLe motivo presentate es:\n\n:<em>$2</em>\n\n* Initio del blocada: $8\n* Expiration del blocada: $6\n* Blocato intendite: $7\n\nTu pote contactar $1 o un del altere [[{{MediaWiki:Grouppage-sysop}}|administratores]] pro discuter le blocada.\n\nNota que tu pote solmente utilisar le function \"{{int:emailuser}}\" si tu ha registrate un adresse de e-mail valide in tu [[Special:Preferences|preferentias de usator]] e tu non ha essite blocate de usar lo.\n\nTu adresse IP actual es $3, e le ID del blocada es #$5.\nPer favor include tote le detalios supra specificate in omne correspondentia.",
        "systemblockedtext": "Tu nomine de usator o adresse IP ha essite blocate automaticamente per MediaWiki.\nLe motivo presentate es:\n\n:<em>$2</em>\n\n* Initio del blocada: $8\n* Expiration del blocada: $6\n* Blocato intendite: $7\n\nTu adresse IP actual es $3.\nPer favor, include tote le detalios enumerate hic supra in omne questiones que tu pone.",
+       "actionblockedtext": "Tu ha essite blocate pro exequer iste action.",
        "blockednoreason": "nulle motivo specificate",
        "whitelistedittext": "Tu debe $1 pro poter modificar paginas.",
        "confirmedittext": "Tu debe confirmar tu adresse de e-mail pro poter modificar paginas.\nPer favor entra e valida tu adresse de e-mail per medio de tu [[Special:Preferences|preferentias de usator]].",
        "ipbreason": "Motivo:",
        "ipbreason-dropdown": "*Motivos frequente pro blocar\n** Insertion de informationes false\n** Elimination de contento de paginas\n** Ligamines ''spam'' verso sitos externe\n** Insertion de nonsenso/absurditates in paginas\n** Comportamento intimidatori/molestation\n** Abuso de contos multiple\n** Nomine de usator inacceptabile",
        "ipb-hardblock": "Impedir que usatores authenticate face modificationes ab iste adresse IP",
-       "ipbcreateaccount": "Impedir creation de contos",
-       "ipbemailban": "Impedir que le usator invia e-mail",
+       "ipbcreateaccount": "Creation de contos",
+       "ipbemailban": "Inviar e-mail",
        "ipbenableautoblock": "Blocar automaticamente le adresse IP usate le plus recentemente per iste usator, e omne IPs successive desde le quales ille/-a tenta facer modificationes",
        "ipbsubmit": "Blocar iste usator",
        "ipbother": "Altere durata:",
        "ipboptions": "2 horas:2 hours,1 die:1 day,3 dies:3 days,1 septimana:1 week,2 septimanas:2 weeks,1 mense:1 month,3 menses:3 months,6 menses:6 months,1 anno:1 year,infinite:infinite",
        "ipbhidename": "Celar le nomine del usator del modificationes e del listas",
        "ipbwatchuser": "Observar le paginas de usator e de discussion de iste usator",
-       "ipb-disableusertalk": "Impedir que iste usator modifica su proprie pagina de discussion durante que ille es blocate",
+       "ipb-disableusertalk": "Modificar le proprie pagina de discussion",
        "ipb-change-block": "Reblocar le usator con iste configurationes",
        "ipb-confirm": "Confirmar blocada",
        "ipb-sitewide": "Sur tote le sito",
        "ipb-partial": "Partial",
        "ipb-pages-label": "Paginas",
+       "ipb-namespaces-label": "Spatios de nomines",
        "badipaddress": "Adresse IP mal formate.",
        "blockipsuccesssub": "Blocada succedite",
        "blockipsuccesstext": "[[Special:Contributions/$1|$1]] ha essite blocate.<br />\nVide le [[Special:BlockList|lista de blocadas]] pro revider le blocadas.",
        "ipb-blocklist": "Vider blocadas existente",
        "ipb-blocklist-contribs": "Contributiones de {{GENDER:$1|$1}}",
        "ipb-blocklist-duration-left": "$1 restante",
+       "block-actions": "Actiones a blocar:",
        "block-expiry": "Expiration:",
+       "block-options": "Optiones additional:",
+       "block-prevent-edit": "Modification",
+       "block-reason": "Motivo:",
+       "block-target": "Nomine de usator o adresse IP:",
        "unblockip": "Disblocar usator",
        "unblockiptext": "Usa le formulario infra pro restaurar le accesso de scriptura a un adresse IP o nomine de usator blocate previemente.",
        "ipusubmit": "Cancellar iste blocada",
        "blocklist-nousertalk": "non pote modificar su proprie pagina de discussion",
        "blocklist-editing": "modification",
        "blocklist-editing-sitewide": "modification (tote le sito)",
+       "blocklist-editing-page": "paginas",
+       "blocklist-editing-ns": "spatios de nomines",
        "ipblocklist-empty": "Le lista de blocadas es vacue.",
        "ipblocklist-no-results": "Le adresse IP o nomine de usator que tu requestava non es blocate.",
        "blocklink": "blocar",
        "specialpages-group-developer": "Instrumentos pro disveloppatores",
        "blankpage": "Pagina vacue",
        "intentionallyblankpage": "Iste pagina es intentionalmente vacue",
+       "disabledspecialpage-disabled": "Iste pagina ha essite disactivate per un administrator del systema.",
        "external_image_whitelist": "  #Lassa iste linea exactemente como illo es<pre>\n#Pone fragmentos de expressiones regular (solmente le parte que va inter //) infra\n#Istes correspondera con le adresses URL de imagines externe (a ligamine directe)\n#Le correspondentes se monstrara como imagines, le alteres solmente como ligamines a imagines\n#Le lineas comenciante con # essera tractate como commentos\n#Isto non es sensibile al differentia inter majusculas e minusculas\n\n#Insere omne fragmentos regex super iste linea. Lassa iste linea exactemente como illo es</pre>",
        "tags": "Etiquettas valide de modification",
        "tag-filter": "Filtro de [[Special:Tags|etiquettas]]:",
        "logentry-block-block": "$1 {{GENDER:$2|blocava}} {{GENDER:$4|$3}} con un tempore de expiration de $5 $6",
        "logentry-block-unblock": "$1 {{GENDER:$2|disblocava}} {{GENDER:$4|$3}}",
        "logentry-block-reblock": "$1 {{GENDER:$2|cambiava}} le configuration del blocada de {{GENDER:$4|$3}} con un tempore de expiration de $5 $6",
-       "logentry-partialblock-block": "$1 {{GENDER:$2|blocava}} {{GENDER:$4|$3}} pro modificar {{PLURAL:$8||le paginas}} $7 con un tempore de expiration de $5 $6",
-       "logentry-partialblock-reblock": "$1 {{GENDER:$2|cambiava}} le configuration del blocada de {{GENDER:$4|$3}} impediente le modification {{PLURAL:$8|de|del paginas}} $7 con un tempore de expiration de $5 $6",
+       "logentry-partialblock-block-page": "le {{PLURAL:$1|pagina|paginas}} $2",
+       "logentry-partialblock-block-ns": "le {{PLURAL:$1|spatio|spatios}} de nomines $2",
+       "logentry-partialblock-block": "$1 {{GENDER:$2|blocava}} {{GENDER:$4|$3}} pro modificar $7 con un tempore de expiration de $5 $6",
+       "logentry-partialblock-reblock": "$1 {{GENDER:$2|cambiava}} le configuration del blocada de $3 impediente que {{GENDER:$4|ille|illa}} modifica $7 con un tempore de expiration de $5 $6",
        "logentry-non-editing-block-block": "$1 {{GENDER:$2|blocava}} {{GENDER:$4|$3}} pro certe actiones non-modification con un tempore de expiration de $5 $6",
        "logentry-non-editing-block-reblock": "$1 {{GENDER:$2|cambiava}} le configuration del blocada de {{GENDER:$4|$3}} pro certe actiones non-modification con un tempore de expiration de $5 $6",
        "logentry-suppress-block": "$1 {{GENDER:$2|blocava}} {{GENDER:$4|$3}} con un tempore de expiration de $5 $6",
index a624451..55e35f1 100644 (file)
@@ -4,44 +4,51 @@
                        "Reedy",
                        "Ukabia",
                        "아라",
-                       "Uzoma Ozurumba"
+                       "Uzoma Ozurumba",
+                       "Oby Ezeilo"
                ]
        },
        "tog-underline": "Ahịrịàlà òjikọ:",
        "tog-hideminor": "Zonari orü ntàkírí na nwerue mẹrẹ ogẹ nsó",
        "tog-hidepatrolled": "Zonari orü ha hụrụ na nwerue mẹrẹ ogẹ nsó",
        "tog-newpageshidepatrolled": "Zonari orü ha hụrụ shí ndetu ihü ohúrù",
+       "tog-hidecategorization": "Zoo nkewasị e nwere n' ihu akwụkwọ nke ọbụla",
        "tog-extendwatchlist": "Gbasa ndetu ihe ánà elé ka ó zi gbanwere nke níle, o bughi nani nke isi nso",
-       "tog-usenewrc": "Ji ihe gbanwere nso níguélé élu (ö chọrọ JavaScript)",
+       "tog-usenewrc": "ngbanwe otu na-esite n'ihu akwụkwọ nwere mgbanwe ọhụụ nakwa ihe nrụba ama.",
        "tog-numberheadings": "Onuogụgụ-otu anyi mere ya maka ishi edemede",
-       "tog-editondblclick": "Rüwá na élu ihü mgbe I kpạtạrạ (ö chọrọ JavaScript)",
-       "tog-editsectiononrightclick": "Kpa na áká nri Í gbanyé orürü nkeji na ishi nkeji (ö chọrọ JavaScript)",
-       "tog-watchcreations": "Tinyé ihüm na eké na ndetu ihem ne lé",
-       "tog-watchdefault": "Tinyé ihü m na rüoru élu na ndetu ihem ne lé",
-       "tog-watchmoves": "Tinyé ihü m na puzié na ndetu ihe m ne lé",
-       "tog-watchdeletion": "Tinyé ihü m na kàcha na ndetu ihe m ne lé",
+       "tog-editondblclick": "Hazie ihu akwụkwọ ndi a site na kliki ugboro abụọ",
+       "tog-editsectiononrightclick": "kpaa aka n'aka nri iji nyere aka na nkeji nke na-ahazi  isiokwu nkeji dị iche iche",
+       "tog-watchcreations": "Mgbakwụnye ihu akwụkwọ na failụ ndi a m mepụtara na ihe m ga na-elebara anya",
+       "tog-watchdefault": "Gbakwụnye ihu akwụkwọ na failụ ndi a nhaziri n'ihe m ga na-elebara anya",
+       "tog-watchmoves": "Tinye ihu akwụkwọ na failụ niile mụ bugara n'ihe m ga na-elebara anya",
+       "tog-watchdeletion": "Tinye ihu akwụkwọ na failụ niile m hichara n'ebe m ga na-elebara anya",
+       "tog-watchuploads": "Tinye failụ ohụụ m mere ọpụload n'ihe mụ ga na -elebara anya",
        "tog-minordefault": "Me ka nhoro da na orü ntakịrị níle",
        "tog-previewontop": "Zitú ntàkịrị mgbe opuzọr zi igbe orü",
        "tog-previewonfirst": "Zitú nke takírí orü mbu",
-       "tog-enotifwatchlistpages": "Türüm e-mail mgbe ihü nor na ndetu ihem ne lé gbanwere",
+       "tog-enotifwatchlistpages": "Ziterem e-mail mgbe otu ihu akwụkwọ maọbụ otu failụ nọ n'ihe ndị na-elebara anya gbanworo",
        "tog-enotifusertalkpages": "Türüm e-mail ngbe ébé okwu ndi na banife nkem gbanwere",
-       "tog-enotifminoredits": "Türüm e-mail maka orü ntakịrị ihüá",
+       "tog-enotifminoredits": "Zitekwara m email maka mgbanwo dị n'ihu akwụkwọ na failụ nhaziri",
        "tog-enotifrevealaddr": "Zifór áhàebeíbị e-mail m na e-mail okwuókà",
        "tog-shownumberswatching": "Zi onuogụgụ ndi na banife nke ne lé",
-       "tog-oldsig": "Létu ntakiri ndẹlu ejị a ma gí:",
+       "tog-oldsig": "Mbinye aka ọpụpụ gị",
        "tog-fancysig": "Mesò ka nkábi nwéré édé wiki (nké énwéghị jikodo nke nọr na onwe)",
-       "tog-uselivepreview": "Jí nlé ntàkírí dí ndụ (Í gí nwé JavaScript) (mmètú kanyí lé)",
+       "tog-uselivepreview": "Gosi  ihe ndịna na-ebupụtachaghị ihe niile dị n'ihu akwụkwọ",
        "tog-forceeditsummary": "Gwam mgbè okwu nsem màkà orüm rürü a díghị",
        "tog-watchlisthideown": "Zonari orüm fwuör ndetu ihem ne lé",
        "tog-watchlisthidebots": "Zonari orü bot fwuör ndetu ihem ne lé",
        "tog-watchlisthideminor": "Zonari orü ntakịrị fwuör ndetu ihem ne lé",
        "tog-watchlisthideliu": "Zonari orü ndi na banife nke ndi banyèrè a banyé, fwuör ndetu ihem ne lé",
+       "tog-watchlistreloadautomatically": "Gosigharia ihe nlebara anya ozigbo e nwere ihe mgbanwe (java script required)",
+       "tog-watchlistunwatchlinks": "Tinye ihe nriba ama ozigbo ozigbo({{int:Watchlist-unwatch}}/{{int:Watchlist-unwatch-undo}}) iji leba anya n'ihe mgbanwo dị n'ihu akwukwọ.(JavaScript required for toggle functionality)",
        "tog-watchlisthideanons": "Zonari orü ndi na banife nke ndi ámághị, fwuör ndetu ihem ne lé",
        "tog-watchlisthidepatrolled": "Zonari orü ha nè léfù ányá fwuör ndetu ihem ne lé",
+       "tog-watchlisthidecategorization": "zoo nkewasị nke ihu akwụkwọ",
        "tog-ccmeonemails": "Sipu iye e-mail m na sipu ndi ozor",
        "tog-diffonly": "É zìkwàlà ihe nọr na ihü di okpúrù íchiè",
        "tog-showhiddencats": "Zi ébéonọr zonari a zonari",
        "tog-norollbackdiff": "Kwà diff mgbe byárá na mgbe láázú mèchàrà",
+       "tog-useeditwarning": "gwam mgbe m hapụrụ ihu akwụkwọ nhaziri na echekwaghị ihe ndị m gbamworo",
        "underline-always": "M̀gbèọbụlà",
        "underline-never": "Emelaème",
        "underline-default": "Ndatụ ihü njikota",
index 00f82f1..501a4b0 100644 (file)
        "returnto": "Aftur á: $1.",
        "tagline": "Úr {{SITENAME}}",
        "help": "Hjálp",
+       "help-mediawiki": "Hjálp varðandi MediaWiki",
        "search": "Leit",
        "search-ignored-headings": " #<!-- leave this line exactly as it is --> <pre>\n# Headings that will be ignored by search.\n# Changes to this take effect as soon as the page with the heading is indexed.\n# You can force page reindexing by doing a null edit.\n# The syntax is as follows:\n#   * Everything from a \"#\" character to the end of the line is a comment.\n#   * Every non-blank line is the exact title to ignore, case and everything.\nReferences\nExternal links\nSee also\n #</pre> <!-- leave this line exactly as it is -->",
        "searchbutton": "Leita",
        "badarticleerror": "Þetta er ekki hægt að framkvæma á síðunni.",
        "cannotdelete": "Ekki var hægt að eyða síðunni \"$1\".\nLíklegt er að einhver annar hafi gert það.",
        "cannotdelete-title": "Gat ekki eytt síðunni $1",
+       "delete-scheduled": "Síðan \"$1\" er áætluð til eyðingar.\nSýndu þolinmæði.",
        "delete-hook-aborted": "Eyðing síðu stöðvuð af viðbótarkrók (extension hook).\nEngin skýring gefin.",
        "no-null-revision": "Ekki var hægt að búa til nýja núll-útgáfu síðunnar \"$1\"",
        "badtitle": "Slæmur titill",
        "accmailtext": "Lykilorðið fyrir [[User talk:$1|$1]] hefur verið sent á $2. Hægt er að breyta því á síðunni ''[[Special:ChangePassword|breyta lykilorði]]'' þegar notandinn hefur skráð sig inn.",
        "newarticle": "(Ný)",
        "newarticletext": "Þú hefur fylgt tengli á síðu sem ekki er til ennþá.\nÞú getur búið til síðu með þessu nafni með því að skrifa í formið fyrir neðan\n(meiri upplýsingar í [$1 hjálpinni]).\nEf þú hefur óvart villst hingað geturðu notað '''til baka'''-hnappinn í vafranum þínum.",
-       "anontalkpagetext": "----\n<em>Þetta er spjallsíða fyrir óþekktan notanda sem hefur ekki búið til aðgang ennþá, eða notar hann ekki.</em>\nÞar af leiðandi þurfum við að nota vistfang til að bera kennsli á hann/hana.\nNokkrir notendur geta deilt sama vistfangi.\nEf þú ert óþekktur notandi og finnst að óviðkomandi athugasemdum hafa verið beint að þér, gjörðu svo vel og [[Special:CreateAccount|búðu til aðgang]] eða [[Special:UserLogin|skráðu þig inn]] til þess að koma í veg fyrir þennan rugling við aðra óþekkta notendur í framtíðinni.",
+       "anontalkpagetext": "----\n<em>Þetta er spjallsíða fyrir óþekktan notanda sem hefur ekki búið til aðgang ennþá, eða notar hann ekki.</em>\nÞar af leiðandi þurfum við að nota IP-vistfang til að bera kennsli á viðkomandi.\nSlík IP-vistföng geta nokkrir notendur deilt saman.\nEf þú ert nafnlaus notandi og finnst að óviðkomandi athugasemdum hafa verið beint að þér, gjörðu svo vel og [[Special:CreateAccount|búðu til aðgang]] eða [[Special:UserLogin|skráðu þig inn]] til þess að koma í veg fyrir þennan rugling við aðra óþekkta notendur í framtíðinni.",
        "noarticletext": "Enginn texti er á þessari síðu enn sem komið er.\nÞú getur [[Special:Search/{{PAGENAME}}|leitað að þessum titli]], í öðrum síðum,\n<span class=\"plainlinks\">[{{fullurl:{{#Special:Log}}|page={{FULLPAGENAMEE}}}} leitað í tengdum skrám], eða [{{fullurl:{{FULLPAGENAME}}|action=edit}} búið hana til]</span>.",
        "noarticletext-nopermission": "Það er enginn texti á þessari síðu eins og er.\nÞú getur [[Special:Search/{{PAGENAME}}|leitað að þessum titli]] í öðrum síðum, eða <span class=\"plainlinks\">[{{fullurl:{{#Special:Log}}|page={{FULLPAGENAMEE}}}} leitað í tengdum skrám]</span>, en þú hefur ekki réttindi til þess að stofna þessa síðu.",
        "missing-revision": "Útgáfa #$1 síðunnar „{{FULLPAGENAME}}\" er ekki til.\n\nÞetta gerist oftast þegar úreld breytingaskrá tengir á síðu sem hefur verið eytt. Frekari upplýsingar eru í [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} eyðingarskránni].",
        "invalid-content-data": "Ógild efnisgögn.",
        "content-not-allowed-here": "„$1“ efni er ekki leyfilegt á síðunni [[:$2]] í hólfi \"$3\"",
        "editwarning-warning": "Ef farið er af þessari síðu gætu þær breytingar sem þú hefur gert tapast.\nEf þú ert skráður inn, þá getur þú gert þessi skilaboð óvirk í „{{int:prefs-editing}}\"-hluta kjörstillinganna þinna.",
+       "slot-name-main": "Aðal",
        "content-model-wikitext": "wiki-texti",
        "content-model-text": "hreinn texti",
        "content-model-javascript": "JavaScript",
        "right-editinterface": "Breyta notandaviðmótinu",
        "right-editusercss": "Breyta CSS-skrám annarra",
        "right-edituserjs": "Breyta JS-skrám annarra",
+       "right-editsitecss": "Breyta CSS á öllu vefsvæðinu",
+       "right-editsitejson": "Breyta JSON á öllu vefsvæðinu",
+       "right-editsitejs": "Breyta JavaScript á öllu vefsvæðinu",
        "right-editmyusercss": "Breyta þinni eigin CSS-notandaskrá",
+       "right-editmyuserjson": "Breyta þínum eigin JSON-notandaskrám",
        "right-editmyuserjs": "Breyta þinni eigin JavaScript-notandaskrá",
        "right-viewmywatchlist": "Skoða þinn eigin vaktlista",
        "right-editmywatchlist": "Breyta þínum eigin vaktlista. Athugið að nokkrar aðgerðir bæta enn við síður án þessa réttindis.",
        "ipb-sitewide": "Á öllum vefnum",
        "ipb-partial": "Að hluta",
        "ipb-pages-label": "Síður",
+       "ipb-namespaces-label": "Nafnrými",
        "badipaddress": "Ógilt vistfang",
        "blockipsuccesssub": "Bann tókst",
        "blockipsuccesstext": "[[Special:Contributions/$1|$1]] hefur verið bannaður/bönnuð.<br />\nSjá [[Special:BlockList|bannaðir notendur og vistföng]] fyrir yfirlit yfir núverandi bönn.",
        "ipb-blocklist": "Sjá núverandi bönn",
        "ipb-blocklist-contribs": "Framlög fyrir {{GENDER:$1|$1}}",
        "ipb-blocklist-duration-left": "$1 eftir",
+       "block-actions": "Aðgerðir sem á að hindra:",
        "block-expiry": "Bannið rennur út:",
+       "block-options": "Viðbótar-valkostir:",
+       "block-prevent-edit": "Breytingar",
+       "block-reason": "Ástæða:",
+       "block-target": "Notandanafn eða IP-vistfang",
        "unblockip": "Afbanna notanda",
        "unblockiptext": "Endurvekja skrifréttindi bannaðra notenda eða vistfanga.",
        "ipusubmit": "Afbanna",
        "createaccountblock": "bann við stofnun nýrra aðganga",
        "emailblock": "tölvupóstur bannaður",
        "blocklist-nousertalk": "getur ekki breytt eigin spjallsíðu",
+       "blocklist-editing": "breytingar",
+       "blocklist-editing-sitewide": "breytingar (á öllum vefnum)",
+       "blocklist-editing-page": "síður",
+       "blocklist-editing-ns": "nafnrými",
        "ipblocklist-empty": "Bannlistinn er tómur.",
        "ipblocklist-no-results": "Umbeðið vistfang eða notandanafn er ekki í banni.",
        "blocklink": "banna",
        "pageinfo-display-title": "Sýnilegur titill",
        "pageinfo-default-sort": "Sjálfgefinn röðunarlykill",
        "pageinfo-length": "Lengd síðunnar (í bætum)",
+       "pageinfo-namespace": "Nafnrými",
        "pageinfo-article-id": "Einkennisnúmer síðunnar",
        "pageinfo-language": "Tungumál síðunnar",
        "pageinfo-language-change": "breyta",
        "revid": "útgáfa $1",
        "pageid": "auðkennisnúmer síðu $1",
        "gotointerwiki": "Fer af {{SITENAME}}",
+       "gotointerwiki-invalid": "Uppgefinn titill er ógildur.",
+       "gotointerwiki-external": "Þú ert í þann mund að yfirgefa {{SITENAME}} til að fara að skoða [[$2]], sem er aðskilið vefsvæði.\n\n'''[$1 Halda áfram á $1]'''",
        "pagedata-title": "Síðugögn",
        "pagedata-bad-title": "Ógildur titill: $1.",
        "passwordpolicies": "Stefna varðandi lykilorð",
index 00fc1c7..b5360b8 100644 (file)
        "removedwatchtext-talk": "\"[[:$1]]\" e la sua pagina associata sono state rimosse dalla propria [[Special:Watchlist|lista degli osservati speciali]].",
        "removedwatchtext-short": "La pagina \"$1\" è stata rimossa dalla propria lista degli osservati speciali.",
        "watch": "Segui",
-       "watchthispage": "Guarda questa pagina",
+       "watchthispage": "Aggiungi agli osservati speciali",
        "unwatch": "Non seguire",
        "unwatchthispage": "Smetti di seguire",
        "notanarticle": "Questa pagina non è una voce",
index 2a9d24b..a6a8c76 100644 (file)
        "editfont-monospace": "فونت تأک بألگە یی",
        "editfont-sansserif": "فونت سان سئریف",
        "editfont-serif": "فونت سئريف",
-       "sunday": "یٱشمٱ",
+       "sunday": "یاٛ شٱمٱ",
        "monday": "دۏشٱمٱ",
        "tuesday": "ساْ شٱمٱ",
        "wednesday": "چارشٱمٱ",
-       "thursday": "پن شمٱ",
-       "friday": "جومٱ",
+       "thursday": "پٱÙ\86 Ø´Ù\85Ù±",
+       "friday": "جۏمٱ",
        "saturday": "شٱمٱ",
        "sun": "یٱشمٱ",
        "mon": "دۏشٱمٱ",
-       "tue": "ساÙ\9bØ´مٱ",
+       "tue": "ساÙ\92 Ø´Ù±مٱ",
        "wed": "چارشمٱ",
        "thu": "پٱن شمٱ",
        "fri": "جومە",
        "subcategories": "زيردأسە یا",
        "category-media-header": "ڤارسگٱر د دٱسٱ \"$1\"",
        "category-empty": "ای دٱسٱ د راستٱکی د ڤٱرگرتٱ هیچ بٱلگٱ یا ڤارسگٱری نی",
-       "hidden-categories": "{{PLURAL:$1|دٱسٱ قام بیٱ|دٱسٱیا قام بیٱ}}",
+       "hidden-categories": "{{PLURAL:$1|دٱسٱ قایم بیٱ|دٱسٱیا قایم بیٱ}}",
        "hidden-category-category": "دأسە یا قام بییە",
        "category-subcat-count": "{{PLURAL:$2|ای دٱسٱ فٱقٱت زیر دٱسٱ یا دئماگر هان دش.ای دٱسٱ {{PLURAL:$1|زیردٱسٱ|$1 زیردٱسٱیا}} ٱ , ڤ دٱر د $2 کول.}}",
        "category-subcat-count-limited": "ئی دأسە ها د {{PLURAL:$1|زیردأسە|$1 زیردأسە یا}} یی کئ ها ڤئ دومئشوٙ",
        "mytalk": "چٱک چنٱ",
        "anontalk": "دئبارە تیرنئشوٙن ئی آی پی قئسە بأکیت",
        "navigation": "ناڤجۊری",
-       "and": "&#32;و",
+       "and": "&#32;ۉ",
        "faq": "ئف ئی کیوٙ",
        "actions": "کونئشتکاریا",
        "namespaces": "نوم ڤارگٱیا",
        "printableversion": "نۏسخٱ پلا بینی",
        "permalink": "هوم پاٛڤٱن هٱمیشاٛیی",
        "print": "چاپ گئرئتئن",
-       "view": "دیاٛن",
+       "view": "دیین",
        "view-foreign": "د $1 نه بوینیت",
        "edit": "ڤیرایش",
        "edit-local": "توضی ڤولات نئشینی نە ڤیرایئشت بأکیت",
        "categorypage": "ديئن بألگە دأسە بأنی",
        "viewtalkpage": "دیئن چأک چئنە یا",
        "otherlanguages": "ڤ زڤونیٛا هنی",
-       "redirectedfrom": "(ڤاگأردوٙنی د$1)",
+       "redirectedfrom": "(ڤاگٱردونی د$1)",
        "redirectpagesub": "بألگە ڤاگأردوٙنی",
        "redirectto": "ڤاگأردوٙنی سی:",
-       "lastmodifiedat": "ای بلگٱ ایسنیا آلشت بیٱ د $1، د $2.",
+       "lastmodifiedat": "اؽ بٱلگٱ ایسنؽا آلشت بیٱ د $1، د $2.",
        "viewcount": "ئی بألگە ها د دأسرئسی {{PLURAL:$1|یئ گئل|$1 چأن گئل}}.",
        "protectedpage": "بألگە پأر و پیم کاری بییە",
        "jumpto": "پرسن د:",
        "aboutpage": "Project:دبارٱ",
        "copyright": "مینۊنٱیا هان د دٱسرس $1 مٱر یٱ کاٛ ڤ یاٛ گاٛل شیڤاٛ هٱنی نیسٱنٱ بۊٱ.",
        "copyrightpage": "{{ns:project}}:کوپی رایت",
-       "currentevents": "روخ ڤنیا ایساٛنی",
-       "currentevents-url": "Project:رÙ\88Ø® Ú¤Ù±Ù\86Û\8cا Ø§Û\8cساÙ\9bنی",
+       "currentevents": "روخ ڤنؽا ایسنی",
+       "currentevents-url": "Project:رÙ\88Ø® Ú¤Ù\86ؽا Ø§Û\8cسنی",
        "disclaimers": "تیٱپۊشکاریٛا",
-       "disclaimerpage": "پوروجٱ: تیٱپوشی کردن همٱگیر",
+       "disclaimerpage": "پرۉژٱ: تیٱپوشی کردن همٱگیر",
        "edithelp": "هومياری سی ڤیرایشت",
        "helppage-top-gethelp": "هومياری",
        "mainpage": "سرآسونٱ",
        "mainpage-description": "سرآسونٱ",
        "policy-url": "پوروجە:رأدیارجوٙری",
-       "portal": "درآسۊنٱ کومولٱیکی",
-       "portal-url": "پوروجٱ:درآسۊنٱ کومولٱیکی",
+       "portal": "درآسونٱ کومولٱیکی",
+       "portal-url": "پرۉژٱ:درآسونٱ کومولٱیکی",
        "privacy": "پۊلتیک رازینٱداری",
-       "privacypage": "پوروجٱ: راگوڤاری رازینٱ کاری کردن",
+       "privacypage": "پرۉژٱ: راگوڤاری رازینٱ کاری کردن",
        "badaccess": "خأطا صئلا دأئن",
        "badaccess-group0": "شوما صئلا أنجوم دأئن کاری نە کئ میهایت ناریت.",
        "badaccess-groups": "ئی کاری کئ شوما هاستیتە سی کاریاریایی کئ هان د {{PLURAL:$2|جأرغە|یئ گئل د جأرغە یا}}: $1 کأم بییە.",
        "editsection": "آلشدکاری",
        "editold": "ڤیرایئشت",
        "viewsourceold": "سئیل د سأرچئشمە بأکیت",
-       "editlink": "ڤیرایشت",
-       "viewsourcelink": "ساٛیل د سرچشمٱ بٱکیت",
+       "editlink": "ڤیرایش",
+       "viewsourcelink": "ساٛلٛ د سرچشمٱ بٱکؽت",
        "editsectionhint": "ڤیرایش یاٛ بٱرجا:$1",
-       "toc": "مینۊنٱیا",
+       "toc": "مؽنونٱیا",
        "showtoc": "نئشوٙ دأئن",
        "hidetoc": "قام کئردئن",
        "collapsible-collapse": "جأم کئردئن",
        "nstab-main": "بٱلگٱ",
        "nstab-user": "بلگٱ کاریار",
        "nstab-media": "بألگە ڤارئسگأر",
-       "nstab-special": "بÙ\84Ú¯Ù±Û\8cا Û\8bÛ\8cجٱ",
+       "nstab-special": "بٱÙ\84Ú¯Ù±Û\8cا Ú¤Û\8cÚ\98ٱ",
        "nstab-project": "بألگە پوروجە",
-       "nstab-image": "جانیا",
+       "nstab-image": "جانؽا",
        "nstab-mediawiki": "پئیغوٙم",
        "nstab-template": "چۊٱ",
        "nstab-help": "بألگە هومیاری",
        "templatesused": "{{PLURAL:$1|چۊٱ|چۊٱ یا}} ڤ کار گرتٱ بیٱ د اؽ بٱلگٱ:",
        "templatesusedpreview": "{{PLURAL:$1| چۊٱ|چۊٱ یا}} ڤ کار گرتٱ بیٱ د پیش ساٛلٛ :",
        "templatesusedsection": "{{PLURAL:$1|چوٙأ|چوٙأ یا}} ڤئ کار گئرئتە بییە د ئی بأرجا:",
-       "template-protected": "(پٱر و پیم بیٱ)",
+       "template-protected": "(پٱر ۉ پیم بیٱ)",
        "template-semiprotected": "(نئصم و نیمە پأر و پیم بییە)",
        "hiddencategories": "اؽ بٱلگٱ یٱکؽ د ٱندومیائٱ {{PLURAL:$1|1 hidden category|$1 hidden categories}} :",
        "edittools-upload": "-",
        "nohistory": "هیچ ویرگار ویرایشتی د ای بلگه نئ.",
        "currentrev": "آخرین دوواره دیئن",
        "currentrev-asof": "آخري وانئری چی $1",
-       "revisionasof": "دوڤارٱ دیاٛن $1",
+       "revisionasof": "دوڤارٱ دیین $1",
        "revision-info": "دوواره سیل بیه چی $1 وا $2",
-       "previousrevision": "ڤاÙ\86Û\8cٱرÛ\8c Ø¯Ø§Ù\9bÙ\85اÛ\8cÛ\8c←",
+       "previousrevision": "ڤاÙ\86Û\8cٱرÛ\8c Ø²Û\8cترÛ\8c ←",
        "nextrevision": "ڤانیٱری تازٱتر",
        "currentrevisionlink": "آخری ڤانیٱری",
        "cur": "تازٱ باۋ",
        "lineno": "خٱت $1:",
        "compareselectedversions": "دوئارٱ دی ینؽایؽ کاْ اْنتخاو بینٱ ناْ موقایسٱ بٱکؽت",
        "showhideselectedversions": "شلک دیئن وانیریا انتخاو بیه نه آلشت بکید",
-       "editundo": "ناانجومگر کردن",
+       "editundo": "ناٱنجومگر کردن",
        "diff-empty": "(بی فرق)",
        "diff-multi-sameuser": "({{PLURAL:$1|یه گل نسقه مینجایی|$1 نسقه یا مینجایی}} وه دس{{PLURAL:$2|کاریاری تر|$2 کاریاریا}} نشو دئه نبیه)",
        "diff-multi-otherusers": "({{PLURAL:$1|یه گل نسقه مینجایی|$1 نسقه یا مینجایی}} وه دس{{PLURAL:$2|کاریاری تر|$2 کاریاریا}} نشو دئه نبیه)",
        "diff-multi-manyusers": "({{PLURAL:$1|یه گل وانیری مینجاگرته|$1وانیریا مینجا گرته}} بیشتر د $2 {{PLURAL:$2|کاریار|کاریاریا}} نشو دئه نبیه)",
        "difference-missing-revision": "{{PLURAL:$2|یه گل ویرایشت|$2 ویرایشت}} د فرق مینجا($1) {{PLURAL:$2|پیدا نبی|پیدا نبینه}}.\n\nشایت بانی جاونه وه وا یه گل ویرگار وه هنگوم نبیه که د یه گل بلگه پاکسا بیه هوم پیوند بیه بوئه.\nشایت جزئیات د   [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} deletion log]  پیدا بوئن.",
-       "searchresults": "نتيجٱیا پی جۊری",
-       "searchresults-title": "نتيجٱیا پی جۊری سی \"$1\"",
+       "searchresults": "نتيجٱیا پاٛ جۊری",
+       "searchresults-title": "نتيجٱیا پاٛ جۊری سی \"$1\"",
        "titlematches": "داسون بلگه یکی بیه",
        "textmatches": "هومسازی نیسسه بلگه.",
        "notextmatches": "نیسسه بلگه هومسازی ناره",
        "next-page": "بلگه نهایی",
        "prevn-title": "پيشتر $1 {{PLURAL:$1|نتيجه|نتيجيا}}",
        "nextn-title": "نيايی $1 {{PLURAL:$1|نتيجه|نتيجيا}}",
-       "shown-title": "نشۊ دٱئن $1 {{PLURAL:$1|نتیجٱ|نتیجٱیا}} سی هار بلگٱ",
+       "shown-title": "نشوݩ داٛین $1 {{PLURAL:$1|نتیجٱ|نتیجٱیا}} سی هار بٱلگٱ",
        "viewprevnext": "ديئن ($1 {{int:pipe-separator}} $2) ($3)",
        "searchmenu-exists": "'''ایچه بلگه ای هئ وه نوم\"[[:$1]]\" که ها د ای ویکی'''",
        "searchmenu-new": "'''ای بلگه نه راس كو \"[[:$1]]\" د ای  ويكي!'''",
        "searchprofile-articles": "بٱلگٱيا مؽنونٱ دار",
-       "searchprofile-images": "وارسگریا خلکمن",
-       "searchprofile-everything": "Ù\87Ù±Ù\85Ù± Ú\86Û\8c",
+       "searchprofile-images": "ڤارسگرؽا خلکمن",
+       "searchprofile-everything": "همٱ چی",
        "searchprofile-advanced": "پیشکردٱ",
        "searchprofile-articles-tooltip": "بٱگٱرد مؽن $1",
-       "searchprofile-images-tooltip": "جانیایانه پی جوری کو",
-       "searchprofile-everything-tooltip": "Ù\87Ù\85Ù\87 Ù\85Û\8cÙ\86Ù\88Ù\86Ù\87 Û\8cا Ù\86Ù\87 Ù¾Û\8c Ø¬Ù\88رÛ\8c Ù\83Ù\88 (شاÙ\85Ù\84ا Ø¨Ù\84Ú¯Ù\8aا Ú\86Ù\83 Ú\86Ù\86Ù\87)",
+       "searchprofile-images-tooltip": "جانؽایاناْ پاٛ جۊری کو",
+       "searchprofile-everything-tooltip": "Ù\87Ù\85Ù± Ù\85ؽÙ\86Ù\88Ù\86Ù±Û\8cا Ù\86اÙ\92 Ù¾Û\8a Ø¬Û\8aرÛ\8c Ù\83Ù\88 (شاÙ\85Ù\84اÙ\92 Ø¨Ù±Ù\84Ú¯Ù±Ù\8aا Ú\86Ù±Ú© Ú\86Ù\86Ù±)",
        "searchprofile-advanced-tooltip": "نوم جايا نوم دؽار بٱگٱرد",
-       "search-result-size": "$1 ({{PLURAL:$2|1 Ú©Ù±Ù\84Û\8cÙ\85Ù±|$2 Ú©Ù±Ù\84Û\8cمٱیا}})",
+       "search-result-size": "$1 ({{PLURAL:$2|1 Ú©Ù\84Ù±Ù\85Ù±|$2 Ú©Ù\84Ù±مٱیا}})",
        "search-result-category-size": "{{PLURAL:$1|1 أندوم|$1 أندومیا}} ({{PLURAL:$2|1 زیردأسە|$2 زیردأسە یا}}، {{PLURAL:$3|1 جانیا|$3 جانیایا}}",
        "search-redirect": "(ڤورگشتن سی $1)",
        "search-section": "(بهرجا $1)",
        "recentchanges-summary": "دو بیشتر آلشتیا تازباو نه د ویکی نه د ای بلگه پیگری کو.",
        "recentchanges-noresult": "هیژ آلشتی د درازا دوره دیار بیه وا ای معیاریا یکی نبی.",
        "recentchanges-feed-description": "دو بیشتر آلشتیا تازباو نه د ویکی که ها د هوال حون پیگری کو.",
-       "recentchanges-label-newpage": "ای ڤیرایشت یاٛ گاٛل بلگٱ تازٱ راس کردٱ.",
-       "recentchanges-label-minor": "Û\8cÙ± Û\8cاÙ\9b Ú¯Ø§Ù\9bÙ\84 Ú¤Û\8cراÛ\8cشت کوچکٱ",
-       "recentchanges-label-bot": "ای ويرايشت نه يه بوت انجوم دئه",
+       "recentchanges-label-newpage": "اؽ ڤیرایش یاٛ بٱلگٱ تازٱ دۏرس کردٱ.",
+       "recentchanges-label-minor": "Û\8cÙ± Û\8cاÙ\9b Ú¤Û\8cراÛ\8cØ´ کوچکٱ",
+       "recentchanges-label-bot": "اؽ ڤيرايش ناْ ياٛ بوت ٱنجوم داٛیٱ",
        "recentchanges-label-unpatrolled": "ای ويرايشت هنی تيه واداشت نبيه",
        "recentchanges-label-plusminus": "انازه بلگه وه شمار ای بایتیا آلشت کرده.",
        "recentchanges-legend-heading": "<strong>میراث:</strong>",
        "rcshowhidecategorization-show": "نئشوٙ دأئن",
        "rcshowhidecategorization-hide": "قام کئردئن",
        "rclinks": "آخرین آلشتیا $1 د آخرین رۊزیا دیاری بٱک $2",
-       "diff": "فرق",
+       "diff": "فٱرق",
        "hist": "ڤیرگار",
        "hide": "قام کردن",
        "show": "نشۊ دٱئن",
        "rc-old-title": "ذاتا چی \"$1\" راس بیه",
        "recentchangeslinked": "آلشتیا تی یٱکی",
        "recentchangeslinked-feed": "آلشتیا تی یکی",
-       "recentchangeslinked-toolbox": "آلشتیا تاٛ یٱک",
+       "recentchangeslinked-toolbox": "آلشتؽا تاٛ یٱک",
        "recentchangeslinked-title": "آلشتیا تاٛ یکی د $1",
-       "recentchangeslinked-summary": "ای نوم بلگٱ تازٱ د بلگٱیایی کاٛ ۋا بلگٱیا ۋیجٱ هوم پیۋند بینٱ آلشت بیٱ(یا سی ٱندومیا دٱسٱ بٱنی بیٱ)\nبلگٱیایی کاٛ هان د [[Special:Watchlist|your watchlist]]و گٱپ بینٱ",
+       "recentchangeslinked-summary": "اؽ نوم بٱلگٱ تازٱ د بٱلگٱیایی کاْ ڤا بٱلگٱیا ڤیژٱ هوم پاٛڤٱن بینٱ آلشت بیٱ(یا سی ٱندومؽا دٱسٱ بٱنی بیٱ)\nبٱلگٱیایی کاْ هان د [[Special:Watchlist|your watchlist]]ۉ گٱپ بینٱ",
        "recentchangeslinked-page": "نوم بلگٱ:",
        "recentchangeslinked-to": "آلشتیایی که د بلگه یا هوم پیوند بینه وه جا بلگه دئیه بیه نشو بیه",
        "recentchanges-page-added-to-category": "[[:$1]]د دأسە ئضاف بی",
        "recentchanges-page-removed-from-category": "[[:$1]] د دٱسٱ جگا بی",
        "recentchanges-page-removed-from-category-bundled": "[[:$1]] و {{PLURAL:$2|بألگە تأکی|$2 بألگە یا}} د دأسە ئضاف بییئن",
        "autochange-username": "آلئشتکاری خودأنجوم مئدیاڤیکی",
-       "upload": "سوڤار کردن جانیا",
+       "upload": "سڤار کردن جانؽا",
        "uploadbtn": "سوڤار کئردئن جانیا",
        "reuploaddesc": "سوار کردن نه انجوم شیو بکیت و د ورئردیت جابلگ سوارکرد",
        "upload-tryagain": "کل کردن توضیحیا آلشت دئیه بیه جانیا",
        "listfiles-latestversion": "نسقه تازه",
        "listfiles-latestversion-yes": "هأری",
        "listfiles-latestversion-no": "تە",
-       "file-anchor-link": "جانیا",
-       "filehist": "ڤیرگار جانیا",
-       "filehist-help": "ری  ويرگاريا بپورنيت تا نسقه مرتوط بونيت.",
+       "file-anchor-link": "جانؽا",
+       "filehist": "ڤیرگار جانؽا",
+       "filehist-help": "ری  ڤيرگارؽا بٱپۊرنؽت تا نۏسخٱ مٱربۊتاْ باٛینؽت.",
        "filehist-deleteall": "هأمە نئ پاکسا کو",
        "filehist-deleteone": "پاکسا کئردئن",
        "filehist-revert": "لئرنیئن",
-       "filehist-current": "تازٱ باڤ",
+       "filehist-current": "تازٱ با",
        "filehist-datetime": "ڤيرگار/ڤٱخت",
-       "filehist-thumb": "ٱسگ کوچک بیٱ",
-       "filehist-thumbtext": "كوچک کردن سی نوسقٱ چی $1",
+       "filehist-thumb": "عٱسک کوچک بیٱ",
+       "filehist-thumbtext": "كوچک کردن سی نۏسخٱ چی $1",
        "filehist-nothumb": "هیچ بن کلیکی نئ",
        "filehist-user": "کاریار",
        "filehist-dimensions": "اۊیٱکؽا",
        "filehist-filesize": "انازه فایل",
        "filehist-comment": "ڤیر ۉ باڤٱر",
-       "imagelinks": "د کار گرتن جانیا",
+       "imagelinks": "ڤ کار گرتن جانؽا",
        "linkstoimage": "دمال بيه {{PLURAL:$1|ديس ونيا بلگه|$1 ديس ون بلگيا}} دای فایل:",
        "linkstoimage-more": "بیشتر د $1 بلگه د ای جانیا هوم پیوند {{PLURAL:$1|بیه|بینه}}.\nنومگه هاری تئنا {{PLURAL:$1|اولین هوم پیوند|اولین $1 هوم پیوند}} د ای بلگه نه نشو می ئه.\n[[Special:WhatLinksHere/$2|نومگه کامل]] ئم هیئش.",
        "nolinkstoimage": "ایچه هیژ بلگه ای سی هوم پیوند بیئن وا ای جانیا نی",
        "duplicatesoffile": "{{PLURAL:$1|جانیا|جانیایا}} هاری نسقه تکراری ای جانیا {{PLURAL:$1|هئ|هئن}} ([[Special:FileDuplicateSearch/$2|دونسمنیا هنی]]):",
        "sharedupload": "ای جانیا که د $1 هئ شایت د پروجه یا هنی استفاده بیه.",
        "sharedupload-desc-there": "ای جانیا ها د $1و شایت د پروجه یا هنی وه کار گرته بوئه.\nسی دونسمنیا هنی لطفن [$2 بلگه توضیحیا جانیا] نه سیل بکیت.",
-       "sharedupload-desc-here": "فایلؽ کاْ د $1 شایٱد د مؽن پروجٱیا هنی اْستفادٱ بیٱ.\nتۉزیی د بارٱ[$2 file description page] د هار نشو داٛیٱ بیٱ",
+       "sharedupload-desc-here": "فایلٛؽ کاْ د $1 شایٱد د مؽن پرۉژٱیا هنی اْستفادٱ بیٱ.\nتۉزیی دبارٱ[$2 file description page] د هار نشوݩ داٛیٱ بیٱ",
        "sharedupload-desc-edit": "ای جانیا د $1 ئه و می تونه د پروجه یا هنی وه کار گرت بوئه.\nار حاستیت می تونیت توضیحیا حانیا نه د [$2 بلگه توضیحیا خوش] د اوچه ویرایشت بکیت.",
        "sharedupload-desc-create": "ای جانیا د $1 ئه و می تونه د پروجه یا هنی وه کار گرت بوئه.\nار حاستیت می تونیت توضیحیا حانیا نه د [$2 بلگه توضیحیا خوش] د اوچه ویرایشت بکیت.",
        "filepage-nofile": "چنو فایلی وا ای نوم نئ.",
        "withoutinterwiki-legend": "پیشون",
        "withoutinterwiki-submit": "نشون دائن",
        "fewestrevisions": "بلگه یایی که کمتری وانئری نه دارن",
-       "nbytes": "$1{{PLURAL:$1|بايت|بایتیا}}",
+       "nbytes": "$1{{PLURAL:$1|بايت|بایتؽا}}",
        "ncategories": "$1{{PLURAL:$1|دسه|دسه يا}}",
        "ninterwikis": "$1 {{PLURAL:$1|مئن ویکی|مئن ویکیا}}",
        "nlinks": "$1 {{PLURAL:$1|هوم پیوند|هوم پیوندیا}}",
        "listusers-desc": "سرجاخودگری د اساس گپ د کؤچک",
        "usereditcount": "$1{{PLURAL:$1|ویرایشت|ویرایشتیا}}",
        "usercreated": "{{جنسیت:$3|راس بیه}}د $1 at $2",
-       "newpages": "بÙ\84Ú¯Ù±Û\8cا Ù\86Û\8f",
+       "newpages": "بٱÙ\84Ú¯Ù±Û\8cا Ù\86Û\8a",
        "newpages-username": "نوم کاریاری:",
        "ancientpages": "بلگه یا نهاتر",
        "move": "جاوه جا بوئيت",
        "allpagesto": "بلگه یایی که د تموم بینه نشو بیه.",
        "allarticles": "هٱمٱ بٱلگٱیا",
        "allinnamespace": "همه بلگه یا($1 نوم جا)",
-       "allpagessubmit": "رÛ\8f",
+       "allpagessubmit": "رÛ\89",
        "allpagesprefix": "بلگه یایی که پس نوم دارن نشو بیه:",
        "allpagesbadtitle": "عنوان بلگه حاسته بیه معتور نی،یا  یه گل مئن زونی یا مئن ویکی عنوان غلطه.\nیه شایت شومل یکی با یا بیشتر کاراکتریا نبوئه که سی ای موضوعیا استفاده بوئن",
        "allpages-bad-ns": "{{نوم دیارگه}} د ای نوم جا نئ \"$1\".",
        "undelete-error-long": "د گات زنه کردن جانیا یه گل خطا پیش اوما:\n\n\n$1",
        "undelete-show-file-confirm": "آیا یه دل بئیته که میهایت یه گل نسقه پاکسا بیه د جانیا \"<nowiki>$1</nowiki>\" که ها د ویرگار $2 ساعت $3 نه سیل بکیت؟",
        "undelete-show-file-submit": "هأری",
-       "namespace": "نوم جا:",
-       "invert": "Ú¯Ù\88Ù\84Ú¤Ù\88رÚ\86Û\8c Ø¨Û\8cئÙ\86 Ø¨Ù±Ø±Ù±Ø³Ú¯ Ø¨Û\8aٱ",
+       "namespace": "نوم جا",
+       "invert": "Ú¯Ù\84Ù\9bٱڤرÚ\86Û\8c Ø¨Û\8cÛ\8cÙ\86 Ø¨Ù±Ø±Ø¹Ù±Ø³Ú© Ø¨Û\8aئٱ",
        "tooltip-invert": "د ری ای جعوه بپورنیت و آلشتیایی نه که د مینجا نوم ورگه انتخاو بیه انجوم بینه قام بکیت(و ار نوم ورگه شریکی وارسی بیه)",
        "tooltip-whatlinkshere-invert": "ای جعون نه سی نهو کردن هوم پیوند بلگه یایی که نوم جاشو انتخاو بیه، انتخاو بکیت.",
        "namespace_association": "نوم جایا یکاگرته",
        "tooltip-ca-delete": "ای بلگه نه پاکسا کو",
        "tooltip-ca-undelete": "د نو زنه کردن ویرایشتیا ری ای بلگه دما یه که پاکساگری بان",
        "tooltip-ca-move": "ای بگله نه جا وه جا كو",
-       "tooltip-ca-watch": "اضاف کردن ای بلگه وه نوم نوشت پیگئریاتو",
+       "tooltip-ca-watch": "اْزاف کردن اؽ بٱلگٱ ڤ نوم نڤشت پاٛگیریاتو",
        "tooltip-ca-unwatch": "ورداشتن ای بلگه وه نوم نوشت پیگئریاتو",
        "tooltip-search": "پاٛ جۊری {{SITENAME}}",
        "tooltip-search-go": "رۉ د بٱلگاٛیؽ کاْ یٱ نوم روسی ها مؽنش ٱلڤٱت ٱر دش بۊئٱ",
        "tooltip-search-fulltext": "بٱلگٱیاناْ سی چنی نیسساٛیؽ پاٛ جۊری بٱکو.",
        "tooltip-p-logo": "ساٛلٛ سرآسونٱ بٱکؽت",
-       "tooltip-n-mainpage": "سرآسۊنٱ نٱ ساٛیل بٱکیت",
-       "tooltip-n-mainpage-description": "سٱرآسونٱ ناْ ساٛلٛ بٱکؽت",
+       "tooltip-n-mainpage": "سرآسونٱ ناْ ساٛلٛ بٱکؽت",
+       "tooltip-n-mainpage-description": "سرآسونٱ ناْ ساٛلٛ بٱکؽت",
        "tooltip-n-portal": "دبارٱ پرۉژٱ؛ شما مؽ تونؽت چؽ بٱکؽت؛ د کوجا اؽ چیاناْ بٱجۊرؽت.",
-       "tooltip-n-currentevents": "ساڤند دۊنسمنیایی کاٛ هان د روخ ڤنیا تازٱ باڤ دیاری بٱک",
+       "tooltip-n-currentevents": "ساڤند دونسمنیایؽ کا هان د روخ ڤنؽا تازٱ باڤ دؽاری بٱک",
        "tooltip-n-recentchanges": "یاٛ نومگٱ سی آلشتکاریا د ڤیکی",
        "tooltip-n-randompage": "سڤار کرد بٱلگٱ بٱختٱکی",
        "tooltip-n-help": "یاٛ جاگٱ سی فٱمسن",
-       "tooltip-t-whatlinkshere": "یاٛ Ú¯Ø§Ù\9bÙ\84 Ù\86Ù\88Ù\85Ú¯Ù± Ø¯ Ù\87Ù\85Ù± Ø¨Ù\84Ú¯Ù±Û\8cاÛ\8cÛ\8c Ú©Ø§Ù\9b Ø§Û\8cÚ\86اÙ\9b Ù\87Ù\88Ù\85 Ù¾Û\8cÚ¤Ù\86د Ø¯Ø§Ø±Ù\86.",
-       "tooltip-t-recentchangeslinked": "آلشتیا تازٱ باڤ ماٛن بلگٱیایی کاٛ د ای بلگٱ هوم پیڤند بینٱ",
+       "tooltip-t-whatlinkshere": "یاٛ Ù\86Ù\88Ù\85Ú¯Ù± Ø¯ Ú©Ù\88Ù\84Ù\9b Ø¨Ù±Ù\84Ú¯Ù±Û\8cاÛ\8cÛ\8c Ú©Ø§Ù\92 Ø§Û\8cÚ\86اÙ\92 Ù\87Ù\88Ù\85 Ù¾Ø§Ù\9bÚ¤Ù±Ù\86 Ø¯Ø§Ø±Ù±Ù\86.",
+       "tooltip-t-recentchangeslinked": "آلشتؽا تازٱ مؽن بٱلگٱیایی کاْ د اؽ بٱلگٱ هوم پاٛڤٱن بینٱ",
        "tooltip-feed-rss": "هوال حون آر اس اس سی ای بلگه",
        "tooltip-feed-atom": "حوال هون اتمی سی ای بلگه",
        "tooltip-t-contributions": "یاٛ گاٛل سیائٱ هومیاری سی {{GENDER:$1|ای کاریار}}",
        "tooltip-t-emailuser": "سی ای كارور ايميل كل كو",
        "tooltip-t-info": "دونسمنیا بیشتر دباره ای بلگه",
-       "tooltip-t-upload": "سوڤار کردن جانیایا",
+       "tooltip-t-upload": "سڤار کردن جانؽایا",
        "tooltip-t-specialpages": "مؽناْ هٱمٱ بٱلگٱیا ڤیژٱ",
        "tooltip-t-print": "نۏسخٱ پاٛلا بی ینی سی اؽ بٱلگٱ",
-       "tooltip-t-permalink": "هوم پیڤند همیشٱیی سی دوڤارٱ دیاٛن ای بلگٱ",
-       "tooltip-ca-nstab-main": "دياٛن مینۊنٱ بلگٱ",
+       "tooltip-t-permalink": "هوم پاٛڤٱن همیشاٛیی سی دوئارٱ دیین اؽ بٱلگٱ",
+       "tooltip-ca-nstab-main": "ديین مؽنونٱ بٱلگٱ",
        "tooltip-ca-nstab-user": "دياٛن بلگٱ کاریار",
        "tooltip-ca-nstab-media": "دیئن بلگه وارسگر",
-       "tooltip-ca-nstab-special": "یٱ یاٛ گاٛل بلگٱ ڤیجٱ یٱ؛ نبۊٱ ڤیرایشتش بٱکیت",
+       "tooltip-ca-nstab-special": "یٱ یاٛ بٱلگٱ ڤیژٱ آ؛ نمۊئٱ ڤیرایشش بٱکؽت",
        "tooltip-ca-nstab-project": "ديئن بلگه پروجه",
-       "tooltip-ca-nstab-image": "ديئن بلگه جانیا",
+       "tooltip-ca-nstab-image": "ديین بٱلگٱ جانؽا",
        "tooltip-ca-nstab-mediawiki": "دیاٛن پیغوم سامۊنٱ",
        "tooltip-ca-nstab-template": "ديئن چۊٱ",
        "tooltip-ca-nstab-help": "ديئن بلگه هومیاری",
        "tooltip-watchlistedit-raw-submit": "وه هنگوم سازی سیل برگ",
        "tooltip-recreate": "د نو راس کردن بلگه بی یه که و پاکساگری دماتر وه سیل بکیم",
        "tooltip-upload": "شرو د سوار کرد",
-       "tooltip-rollback": "\"ڤرئشتن\" لرستن د هال وبال ٱڤل سی ای بلگٱ سی یٱ کاٛ هومیاری نیایی بیتر کاری بیٱ ڤا یاٛ گاٛل پۊرنین.",
+       "tooltip-rollback": "\"ڤرگٱشتن\" لٛرسن د هال و بال ٱڤٱل سی اؽ بٱلگٱ سی یٱ کاْ هومیاری نؽایی بؽتر کاری بیٱ ڤا یاٛ پۊرنین.",
        "tooltip-undo": "انجوم نگرتن ای ویرایشت ورگن و همه فرمیا ویرایشت تانه که حالت پیش سیل واکو.یه اجازه میئه سی اضاف کردن یه دلیل د چکسته.",
        "tooltip-preferences-save": "اولويتيا نه ذخيره بكيد",
        "tooltip-summary": "يه چكسته كؤچك وارد بكيد",
        "sunday-at": "یه شمه د $1",
        "yesterday-at": "دیرو د $1",
        "bad_image_list": "دونسمنديانه وه ای شلگ وارد بكيت:\n\nفقط سرخط يایی که وا * شرو بوئن د وير گرته بوئن. اولی چسب ون مئن هر سرخط، باید چسب ونی وه یک عسگ گن با.\nچسب ونيا نيایی د همو سرخط، وه عنوان چيا استثنادار د وير گرته بوئن",
-       "metadata": "رسÛ\8cÙ\86Ù±Û\8cا Ù\81اÙ\9bرٱ Ú¯Ù±Ù¾",
+       "metadata": "رسینٱیا فرٱ گٱپ",
        "metadata-help": "ای فایل شومل دونسمنیا هنی یه.شایت د دیربین رقم ون یا اسکنری که سی راس کردنشو استفاده بیه،وه ایچه اضاف بیه",
        "metadata-expand": "نشو دئن جزییات دمادیسگری",
        "metadata-collapse": "قام کردن جزییات دمادیسگری",
-       "metadata-fields": "رشنه یا یا گپ دونسمنیا که د ای پیغوم نومگه کاری بینه د ور گرته بلگه عسگ ن که گات وختی که جدول گپ دونسمنیا واز بوئه نشون دئیه بوئن.\nچی یا هنی سی یه که پیش فرضن قام بوئن.\n*راست کو\n*مدل\n*دم وخت اصل\n*وخت آشگار\n*اف ان شماره\n*ایزو نرخ من سرعت\n*فوکالنس\n*هنرمن\n*کپی رایت\n*حالت جی پی اس \n*جی پی اس گپ حالت\n*جی پی اس همه حالت",
+       "metadata-fields": "رشتٱیا یا گٱپ دونسمنیا کاْ د اؽ پاٛغوم نومگٱ کاری بینٱ د ڤٱر گرتٱ بٱلگٱ عٱسک کاْ ڤٱختؽ جٱدڤٱل گٱپ دونسمنیا ڤاز مۊئٱ نشوݩ داٛیٱ بۊئٱن.\nچی یا هنی سی یٱ کا پیش فٱرزٱن قایم مۊئٱن.\n*راس کو\n*مودل\n*دم ڤٱخت ٱسل\n*ڤٱخت آشگار\n*اْف اْن شمارٱ\n*ایزو نرخ من سرعت\n*فوکالنس\n*هونٱرمٱن\n*کوپی رایت\n*هالٱت جی پی اْس \n*جی پی اْس گٱپ هالٱت\n*جی پی اْس هٱمٱ هالٱت",
        "metadata-langitem": "<strong>$2:</strong> $1",
        "metadata-langitem-default": "$1",
-       "namespacesall": "Ù\87Ù±Ù\85ٱشÛ\8a",
+       "namespacesall": "Ù\87Ù\85ٱشÙ\88",
        "monthsall": "هٱمٱ",
        "confirmemail": "پشت راس کردن تیرنشون انجومانامه",
        "confirmemail_noemail": "شما د بلگه [[Special:Preferences|ترجیحات کاریاری]] خوتو یه گل تیرنشون انجومانامه نامعتور نه دئیته.",
        "tags": "سردیسیا آلشت دئن خو",
        "tag-filter": "فيلتر [[Special:سردیس|سردیسیا]]:",
        "tag-filter-submit": "فيلتر",
-       "tag-list-wrapper": "[[Special:سردیسیا|{{PLURAL:$1|سردیس|سردیسیا}}]]: $2",
+       "tag-list-wrapper": "[[Special:سردیسؽا|{{PLURAL:$1|سردیس|سردیسؽا}}]]: $2",
        "tags-title": "سردیسیا",
        "tags-intro": "ای بلگه یه گل نومگه د سردیسیاییه که نرم افزار وا ونو ویرایشتیا نه نشو کاری میکه، الوت واگرد هومبراوریاشو.",
        "tags-tag": "نوم سردیس",
        "logentry-patrol-patrol": "$1 نسقه $4 بلگه $3 نه چی یه گل چی تیه نئری بیه {{GENDER:$2|نشودار کرد}}",
        "logentry-patrol-patrol-auto": "$1 نسقه $4 بلگه $3 نه وه حال و بار خودانجوم چی یه گل بلگه تیه نیئر بیه {{GENDER:$2|نشودار کرد}}",
        "logentry-newusers-newusers": "حساو کاریاری $1 {{GENDER:$2|دروس بیه}}",
-       "logentry-newusers-create": "Ù\87ساÙ\88 Ú©Ø§Ø±Ø¨Ù±Ø±Û\8c $1 {{GENDER:$2|راس بی}}",
+       "logentry-newusers-create": "Ù\87ساÙ\88 Ú©Ø§Ø±Ø¨Ù±Ø±Û\8c $1 {{GENDER:$2|دÛ\8fرس بی}}",
        "logentry-newusers-create2": "حساو کاریاری $3،وه دس $1 {{GENDER:$2|دروس بی}}",
        "logentry-newusers-byemail": "حساو کاریاری $3 وه دس $1 {{GENDER:$2|ره وندیاری بی}} و رازینه گواردن وا انجومانام کل بی",
        "logentry-newusers-autocreate": "حساو $1  خودانجومن {{GENDER:$2|دروس بی}}",
index 3bfcbf2..41dd0cc 100644 (file)
        "statistics-header-hooks": "Алте статистичь",
        "statistics-articles": "Артиколе",
        "statistics-pages": "Паӂинь",
+       "statistics-pages-desc": "Тоате паӂиниле дин вики, инклусив паӂиниле де дискуций, редирекционэрь ш.а.",
        "statistics-files": "Фишиере ынкэркате",
+       "statistics-edits": "Нумэрул де модификэрь дин моментул инсталэрий проектулуй {{SITENAME}}",
+       "statistics-edits-average": "Нумэрул медиу де модификэрь пе паӂинэ",
        "nbytes": "{{PLURAL:$1|ун байт|$1 байць|$1 де байць}}",
        "nmembers": "$1 {{PLURAL:$1|ун мембру|мембрь}}",
        "prefixindex": "Тоате паӂиниле ку префикс",
index 2567eb8..66f3774 100644 (file)
        "rcfilters-empty-filter": "Nisciune filtre attive. Tutte le condrebbute avènene fatte 'ndrucà.",
        "rcfilters-filterlist-title": "Filtre",
        "rcfilters-filterlist-whatsthis": "Cumme funzionane?",
+       "rcfilters-filterlist-feedbacklink": "Dì ce ne pinze de ste struminde de filtre",
        "rcfilters-highlightbutton-title": "Evidenzie le resultate",
        "rcfilters-highlightmenu-title": "Scacchie 'nu culore",
        "rcfilters-highlightmenu-help": "Scacchie 'nu culore pe evidenzià sta probbietà",
        "rcfilters-filterlist-noresults": "Nisciune filtre acchiate",
+       "rcfilters-noresults-conflict": "Nisciune resultate acchiate, purcé le criterie de recerche stonne in conflitte",
        "rcfilters-filter-editsbyself-label": "Cangiaminde tune",
        "rcfilters-filter-editsbyself-description": "Condrebbute tune.",
        "rcfilters-filter-editsbyother-label": "Cangiaminde de l'otre",
index d172d72..11e4303 100644 (file)
        "mainpage": "ᱢᱩᱬᱩᱛ ᱥᱟᱦᱴᱟ",
        "mainpage-description": "ᱢᱩᱬᱩᱛ ᱥᱟᱦᱴᱟ",
        "policy-url": "Project:ᱨᱤᱛᱤᱱᱤᱛᱤ",
-       "portal": "á±\9cᱩᱥᱴᱤ á±µá±\9aá±\9eá±\9aá±\9c á±«á±©á±­á±\9fᱹᱨ",
+       "portal": "á± á±\9aᱢᱩᱱᱤᱴᱤ á±¯á±\9aᱨᱴá±\9fá±\9e",
        "portal-url": "Project:ᱠᱷᱩᱴ ᱵᱚᱞᱚᱱ ᱦᱚᱨ",
        "privacy": "ᱩᱠᱩ ᱮᱠᱛᱤᱭᱟᱨ",
        "privacypage": "Project:ᱩᱠᱩ ᱮᱠᱛᱤᱭᱟᱨ",
        "login-throttled": "ᱟᱢ ᱫᱚ ᱢᱤᱫᱜᱷᱟᱹᱲᱤ ᱞᱟᱦᱟᱨᱮ ᱟᱭᱢᱟ ᱫᱷᱟᱣ ᱵᱚᱞᱚᱜᱮᱢ ᱠᱩᱨᱩᱢᱩᱴᱩ ᱠᱮᱫᱟ᱾ \nᱟᱨᱦᱚᱸ ᱠᱩᱨᱩᱢᱩᱴᱩᱭ ᱞᱟᱦᱟᱨᱮ ᱫᱟᱭᱟᱠᱟᱛᱮ $1 ᱛᱟᱸᱜᱤᱭᱢᱮ᱾",
        "login-abort-generic": "ᱟᱢᱟᱜ ᱵᱷᱤᱛᱨᱤ ᱵᱚᱠᱟᱜ ᱫᱚ ᱵᱟᱝ ᱦᱩᱭᱞᱮᱱᱟ - ᱵᱟᱫᱽᱱᱟ",
        "loginlanguagelabel": "ᱯᱟᱹᱨᱥᱤ: $1",
-       "pt-login": "á±µá±\9aá±\9eá±\9aá±\9c á±«á±©á±­ᱟᱹᱨ",
+       "pt-login": "á±µá±\9aá±\9eá±\9aá±\9c á±«á±©á±£ᱟᱹᱨ",
        "pt-login-button": "ᱵᱚᱞᱚᱜ ᱢᱮ",
        "pt-login-continue-button": "ᱞᱮᱛᱟᱲ ᱵᱚᱞᱚ ᱠᱚᱜᱼᱢᱮ",
        "pt-createaccount": "ᱮᱠᱟᱶᱩᱴ ᱛᱮᱭᱟᱨᱢᱮ",
index 1cdf2bb..28fedc4 100644 (file)
        "right-managechangetags": "Pravljenje i (de)aktiviranje [[Special:Tags|oznaka]]",
        "right-applychangetags": "Primijeni [[Special:Tags|oznake]] na nečije izmjene",
        "right-changetags": "Dodavanje ili uklanjanje raznih [[Special:Tags|oznaka]] na pojedinačnim verzijama i unosima zapisnika",
+       "grant-editinterface": "Uređivanje imenskog prostora \"MediaWiki\" i JSON za cijelo wiki/za korisnika",
+       "grant-editmycssjs": "Uređivanje Vašeg korisničkog CSS/JSON/JavaScripta",
+       "grant-editsiteconfig": "Uređivanje CSS/JS za cijelo wiki i za korisnika",
        "newuserlogpage": "Registar novih korisnika",
        "newuserlogpagetext": "Ovo je evidencija registracije novih korisnika.",
        "rightslog": "Evidencija korisničkih prava",
index f7dd544..74d4ab6 100644 (file)
@@ -35,7 +35,7 @@
        "tog-forceeditsummary": "Ayyit tini iɣ ur iwiɣ imsmun n imbdln",
        "tog-watchlisthideown": "hbo ghayli bdlgh gh omdfor inu",
        "tog-watchlisthidebots": "hba ghayli bdln robotat gh omdfor inu",
-       "tog-watchlisthideminor": "Ḥbu ibdln mzinin ɣ umdfur inu",
+       "tog-watchlisthideminor": "ⵙⵙⵏⵜⵍ ⵉⵙⵏⴼⵉⵍⵏ ⵎⵥⵥⵉⵏⵉⵏ ⵣⵖ ⵜⴰⵍⵉⵙⵜⵜ ⵏ ⵓⴹⴼⴼⵓⵔ",
        "tog-watchlisthideliu": "Ḥbu ibdln n wili skrn midn llin iqqiydn ɣu umdfr inu.",
        "tog-watchlisthideanons": "Ḥbu ibdl n midn lli urittuyssanin ɣ umdfr inu",
        "tog-watchlisthidepatrolled": "Ḥbu ibdln lli nssugga  ɣu umuɣ n umdfr",
@@ -52,7 +52,7 @@
        "editfont-serif": "ⵜⵉⵙⵉⵙⴽⵉⵍⵜ ⵙⵉⵔⵉⴼ",
        "sunday": "ⵍⵃⴷⴷ",
        "monday": "ⵍⵜⵏⵉⵏ",
-       "tuesday": "â´°âµ\99âµ\89âµ\8fâ´°âµ\99",
+       "tuesday": "âµ\9fâµ\9fâµ\8dâ´°âµ\9câ´°",
        "wednesday": "ⵍⵄⵔⴱⴰ",
        "thursday": "ⵍⵅⵎⵉⵙ",
        "friday": "ⵍⵊⴰⵎⵄ",
        "sun": "ⵍⵃⴷⴷ",
        "mon": "ⵍⵜⵏⵉⵏ",
        "tue": "ⵟⵟⵍⴰⵜⴰ",
-       "wed": "âµ\8dâ´°âµ\94â´±âµ\84",
+       "wed": "âµ\8dâµ\84âµ\94ⴱⴰ",
        "thu": "ⵍⵅⵎⵉⵙ",
        "fri": "ⵍⵊⴰⵎⵄ",
        "sat": "ⵙⵙⴱⵜ",
        "january": "ⵉⵏⵏⴰⵢⵔ",
-       "february": "ⴼⴱâµ\95â´°âµ¢âµ\8d",
+       "february": "â´±âµ\94â´°âµ¢âµ\94",
        "march": "ⵎⴰⵔⵙ",
        "april": "ⴰⴱⵔⵉⵍ",
        "may_long": "ⵎⴰⵢⵢⵓ",
        "november": "ⵏⵓⵡⴰⵎⴱⵉⵔ",
        "december": "ⴷⵓⵊⴰⵎⴱⵉⵔ",
        "january-gen": "ⵉⵏⵏⴰⵢⵔ",
-       "february-gen": "ⴼⴱâµ\94â´°âµ¢âµ\8d",
-       "march-gen": "âµ\8eâ´°âµ\95ⵙ",
+       "february-gen": "â´±âµ\94â´°âµ¢âµ\94",
+       "march-gen": "âµ\8eâ´°âµ\94ⵙ",
        "april-gen": "ⴰⴱⵔⵉⵍ",
        "may-gen": "ⵎⴰⵢⵢⵓ",
        "june-gen": "ⵢⵓⵏⵢⵓ",
        "july-gen": "ⵢⵓⵍⵢⵓⵣ",
        "august-gen": "ⵖⵓⵛⵜ",
        "september-gen": "ⵛⵓⵜⴰⵎⴱⵉⵔ",
-       "october-gen": "â´½âµ\9câµ\93â´±âµ\95",
+       "october-gen": "â´½âµ\9câµ\93â´±âµ\94",
        "november-gen": "ⵏⵓⵡⴰⵎⴱⵉⵔ",
        "december-gen": "ⴷⵓⵊⴰⵎⴱⵉⵔ",
        "jan": "ⵉⵏⵏ",
-       "feb": "ⴼⴱâµ\94",
+       "feb": "â´±âµ\94â´°",
        "mar": "ⵎⴰⵔ",
        "apr": "ⴰⴱⵔ",
        "may": "ⵎⴰⵢ",
        "index-category": "ⵜⴰⵙⵡⵏⵉⵡⵉⵏ ⵜⵜⵡⴰⵏⴷⵉⴽⵙⴰⵏⵉⵏ",
        "noindex-category": "Tisniwin bla amatar",
        "broken-file-category": "ⵜⴰⵙⵏⵉⵡⵉⵏ ⵖ ⵍⵍⴰⵏ ⵉⵍⵉⵏⴽⵏ ⵔⵥⴰⵏⵉⵏ",
-       "about": "â´°ⴼ",
+       "about": "âµ\96ⴼ",
        "article": "ⵜⴰⵙⵏⴰ ⵏ ⵜⵓⵎⴰⵢⵜ",
-       "newwindow": "(âµ\89âµ\9câµ\9câµ\8fâµ\93âµ\94âµ¥âµ\93âµ\8e â´·â´³ ⵓⵙⴽⵙⵍ ⴰⵎⴰⵢⵏⵓ)",
+       "newwindow": "(â´°âµ\94 âµ\89âµ\9câµ\9câµ\8fâµ\93âµ\94âµ¥âµ\93âµ\8e âµ\96 ⵓⵙⴽⵙⵍ ⴰⵎⴰⵢⵏⵓ)",
        "cancel": "ⵙⵎⵎⵜ",
        "moredotdotdot": "ⵓⴳⴳⴰⵔ...",
        "mypage": "ⵜⴰⵙⵏⴰ",
        "and": "&#32;ⴷ",
        "faq": "ⵉⵇⵙⵇⵙⵉⵜⵏ ⵜⵜⵢⴰⵍⴰⵙⵏⵉⵏ",
        "actions": "ⵜⵉⴳⴰⵡⵉⵏ",
-       "namespaces": "Ismawn n tɣula",
+       "namespaces": "ⵉⴳⵔⴰⵏ",
        "variants": "ⵜⵉⵎⵣⴰⵔⴰⵢⵉⵏ",
        "errorpagetitle": "ⵜⴰⵣⴳⵍⵜ",
        "returnto": "ⵉⵡⵔⵔⵉ ⵏⵏ ⵙ $1.",
        "viewtalkpage": "ⵥⵔ ⴰⵎⵙⴰⵡⴰⵍ",
        "otherlanguages": "ⵙ ⵜⵓⵜⵍⴰⵢⵉⵏ ⵢⴰⴹⵏ",
        "redirectedfrom": "(ⵉⴽⴽⴰ ⴷ $1)",
-       "redirectpagesub": "Tasna n-usmmattay",
-       "redirectto": "â´°âµ\99âµ\8eâ´°âµ\9câµ\9câµ¢ âµ\99:",
+       "redirectpagesub": "ⵜⴰⵙⵏⴰ ⵏ ⵓⵙⵎⴰⵜⵜⵉ",
+       "redirectto": "â´°âµ\99âµ\8eâ´°âµ\9câµ\9câµ\89 âµ\99 :",
        "lastmodifiedat": "ⴰⵙⵏⴼⵍ ⵉⴳⴳⵯⵔⴰⵏ ⵖ ⵜⴰⵙⵏⴰ ⴰⴷ ⵉⵜⵜⵢⴰⵡⵙⴽⴰⵔ ⴰⵙⵙ ⵏ $1 ⵖ $2.",
        "viewcount": "Tmmurzm tasna yad {{PLURAL:$1|yat twalt|$1 mnnawt twal}}.",
        "protectedpage": "Tasnayat iqn ugdal nes.",
        "jumpto": "ⴷⴷⵓ ⵙ :",
        "jumptonavigation": "ⴰⵙⵜⴰⵔⴰ",
        "jumptosearch": "ⵙⵉⴳⴳⵍ",
-       "view-pool-error": "âµ\99âµ\99âµ\93âµ\94â´¼ â´°âµ\99, âµ\89âµ\99âµ\89âµ\94â´±âµ\93âµ\94âµ\8f âµ\95âµ\8eâµ\89âµ\8f âµ\96âµ\89âµ\8dâ´°â´·.\nⴱⵣⵣⴰⴼ âµ\8f âµ\89âµ\99âµ\8eâµ\94â´°âµ\99âµ\8f â´°âµ\94 âµ\9câµ\9câ´°âµ\94âµ\8eâµ\8f â´°â´· â´°âµ\8fâµ\8fâ´°âµ¢âµ\8f âµ\9câ´°âµ\99âµ\8fâ´° â´°â´·.\nâµ\87âµ\87âµ\8d âµ¢â´°âµ\8f âµ\89âµ\8eâµ\89ⴽⴽ â´¼â´°â´· â´°â´· â´·â´°âµ\96 âµ\9câ´°âµ\94âµ\8eâµ\9c â´°â´· âµ\9câ´½âµ\9bâµ\8eâµ\9c âµ\99 âµ\9câ´°âµ\99âµ\8fâ´° â´°â´·.\n\n$1",
+       "view-pool-error": "âµ\99âµ\99âµ\93âµ\94â´¼ â´°âµ\99, âµ\89âµ\99âµ\89âµ\94â´±âµ\93âµ\94âµ\8f âµ\95âµ\8eâµ\89âµ\8f âµ\96âµ\89âµ\8dâ´°â´·.\nâ´½âµ\89ⴳⴰâµ\8f âµ\8f âµ\89âµ\99âµ\8eâµ\94â´°âµ\99âµ\8f âµ\94â´°âµ\8f âµ\96âµ\89âµ\8dâ´°â´· â´°â´· â´°âµ\8fâµ\8fâ´°âµ¢âµ\8f âµ\9câ´°âµ\99âµ\8fâ´° â´°â´·.\nâµ\87âµ\87âµ\8d âµ¢â´°âµ\8f âµ\89âµ\8eâµ\89ⴽⴽ, âµ\9câ´°âµ\94âµ\8eâµ\9c â´°â´· âµ\8fâµ\8f â´·â´°âµ\96 âµ\99âµ\94âµ\99 âµ\9câ´½âµ\9bâµ\8eâµ\9c.\n\n$1",
        "pool-timeout": "Tzrit tizi n uql lli yak ittuykfan. Ggutn midn lli iran ad iẓr tasna yad. Urrid yan imik..",
        "pool-queuefull": "Umuɣ n twuri iẓun (iεmr)",
        "pool-errorunknown": "Anzri (error) ur ittuyssan.",
        "collapsible-expand": "Sfruri",
        "confirmable-yes": "ⵢⴰⵀ",
        "confirmable-no": "ⵓⵀⵓ",
-       "thisisdeleted": "ⵉⵙ ⵜⵔⵉⵜ ⴰⴷ ⵜⴰⵏⵏⴰⵢⵜ ⵏⵖ ⴰⴷ ⵜⵙⵙⴰⴹⵓⵜ $1?",
-       "viewdeleted": "ⴰⴷ ⵜⵥⵔⵜ $1?",
+       "thisisdeleted": "ⵉⵙ ⵜⵔⵉⵜ ⴰⴷ ⵜⴰⵏⵏⴰⵢⵜ ⵏⵖ ⴰⴷ ⵜⵙⵙⴰⴹⵓⵜ $1 ?",
+       "viewdeleted": "ⴰⴷ ⵜⵥⵔⵜ $1 ?",
        "restorelink": "{{PLURAL:$1|ⵢⴰⵏ ⵓⵙⵏⴼⵍ ⵉⵜⵜⵡⴰⴽⴽⵙⵏ|$1 ⵉⵙⵏⴼⵉⵍⵏ ⵜⵜⵡⴰⴽⴽⵙⵏⵉⵏ}}",
        "feedlinks": "ⵉⴼⵉⵍⵉ:",
        "feed-invalid": "Anaw n usurdm ur gis iffuy umya",
        "red-link-title": "$1 (ⵓⵔ ⵜⵍⵍⵉ ⵜⴰⵙⵏⴰ ⴰⴷ)",
        "nstab-main": "ⵜⴰⵙⵏⴰ",
        "nstab-user": "ⵜⴰⵙⵏⴰ ⵏ {{GENDER:{{ROOTPAGENAME}}|ⵓⵙⵎⵔⴰⵙ|ⵜⵙⵎⵔⴰⵙⵜ}}",
-       "nstab-media": "Tasnat Ntuzumt",
+       "nstab-media": "ⵎⵉⴷⵢⴰ",
        "nstab-special": "ⵜⴰⵙⵏⴰ ⵉⵥⵍⵉⵏ",
        "nstab-project": "Project page",
        "nstab-image": "ⴰⴼⴰⵢⵍⵓ",
        "nstab-mediawiki": "ⵜⵓⵣⵉⵏⵜ",
-       "nstab-template": "Talɣa",
+       "nstab-template": "ⴰⵍⴱⵓⴹ",
        "nstab-help": "ⵜⴰⵙⵏⴰ ⵏ ⵜⵡⵉⵙⵉ",
        "nstab-category": "ⵜⴰⴳⴳⴰⵢⵜ",
        "mainpage-nstab": "ⵜⴰⵙⵏⴰ ⵏ ⵓⵙⵏⵓⴱⴳ",
        "nosuchaction": "ⵓⵔ ⵜⵍⵍⵉ ⵜⵉⴳⴰⵡⵜ ⴰⴷ",
        "nosuchactiontext": "Mytuskarn ɣu tansa yad ur tti tgi.\nⵉⵔⵡⴰⵙ ⵉⵙ ⵓⵔ ⵜⵓⵔⵉⵜ ⵎⵣⵢⴰⵏ ⴰURL, ⵏⵖ ⵉⵙ ⵜⴹⴼⵔⵜ ⴽⵔⴰ ⵏ ⵓⵍⵉⵏⴽ ⵉⵣⴳⵍⵏ.\nTzdar attili tamukrist ɣ {{SITENAME}}.",
        "nosuchspecialpage": "ⵓⵔ ⵜⵍⵍⵉ ⵜⴰⵙⵏⴰ ⴰⴷ ⵉⵥⵍⵉⵏ",
-       "nospecialpagetext": "<strong>âµ\9câ´»âµ\9câµ\9câµ\94âµ\9c âµ¢â´°âµ\9c âµ\9câ´°âµ\99âµ\8fâ´° âµ\89âµ¥âµ\8dâµ\89âµ\8f âµ\93âµ\94 âµ\89âµ\8dâµ\8dâµ\89âµ\8f.</strong>\n\nâµ\94â´°â´· âµ\9câ´°â´¼âµ\9c âµ¢â´°âµ\9c âµ\9câµ\8dⴳⴰâµ\8eⵜ ⵏ ⵜⴰⵙⵏⵉⵡⵉⵏ ⵥⵍⵉⵏⵉⵏ ⵖⵜⴰⵏⵉⵏ ⵖ [[Special:SpecialPages|{{int:specialpages}}]].",
+       "nospecialpagetext": "<strong>âµ\9cⴹⴰâµ\8dâ´±âµ\9c âµ\8fâµ\8f âµ¢â´°âµ\9c âµ\9câ´°âµ\99âµ\8fâ´° âµ\89âµ¥âµ\8dâµ\89âµ\8f âµ\93âµ\94 âµ\89âµ\8dâµ\8dâµ\89âµ\8f.</strong>\n\nâµ\94â´°â´· âµ\9câ´°â´¼âµ\9c âµ¢â´°âµ\9c âµ\9câ´°âµ\8dâµ\89âµ\99âµ\9cⵜ ⵏ ⵜⴰⵙⵏⵉⵡⵉⵏ ⵥⵍⵉⵏⵉⵏ ⵖⵜⴰⵏⵉⵏ ⵖ [[Special:SpecialPages|{{int:specialpages}}]].",
        "error": "ⵜⴰⵣⴳⵍⵜ",
        "databaseerror": "ⵜⴰⵣⴳⵍⵜ ⴳ ⵜⴰⵙⵉⵍⴰ ⵏ ⵉⵙⴼⴽⴰ",
        "databaseerror-error": "ⴰⵣⴳⴳⴰⵍ: $1",
        "laggedslavemode": "Ḥan tasnayad ur gis graygan ambddel amaynu.",
        "readonly": "ⵜⴰⵙⵉⵍⴰ ⵏ ⵉⵙⴼⴽⴰ ⵉⵜⵜⵡⴰⵔⴳⵍⵏ",
        "missing-article": "lqaa'ida n lbayanat ortofa nass ad gh tawriqt  liss ikhssa asti taf limism \"$1\" $2.\n\nghikad artitsbib  igh itabaa lfrq aqdim nghd tarikh artawi skra nsfha ityohyadn.\n\nighor iga lhal ghika ati ran taft kra lkhata gh lbarnamaj.\n\nini mayad ikra [[Special:ListUsers/sysop|lmodir]] tfktas ladriss ntwriqt an.",
-       "missingarticle-rev": "(lmorajaaa#: $1)",
-       "missingarticle-diff": "(ⴰⵎⵣⴰⵔⴰⵢ: $1, $2)",
-       "internalerror": "âµ\9cⴰⵣⴳâµ\8dâµ\9c âµ\9cⴰⴳⵯâµ\8fâµ\99â´°âµ\8fâµ\9c",
-       "internalerror_info": "âµ\9cⴰⵣⴳâµ\8dâµ\9c âµ\9cⴰⴳⵯâµ\8fâµ\99â´°âµ\8fâµ\9c: $1",
+       "missingarticle-rev": "(ⵓⵟⵟⵓⵏ ⵏ ⵓⵣⵣⵔⴰⵢ : $1)",
+       "missingarticle-diff": "(ⴰⵎⵣⴰⵔⴰⵢ : $1, $2)",
+       "internalerror": "ⴰⵣⴳⴳⴰâµ\8d â´°â´³âµ¯âµ\8fâµ\99â´°âµ\8f",
+       "internalerror_info": "ⴰⵣⴳⴳⴰâµ\8d â´°â´³âµ¯âµ\8fâµ\99â´°âµ\8f : $1",
        "filecopyerror": "orimkin ankopi \"$1\" s \"$2\".",
-       "filerenameerror": "ur as tufit ad tsmmut \"$1\" s \"$2\".",
+       "filerenameerror": "ⵓⵔ ⵢⴰⵍⵍⴼⵓⵙ ⴰⴷ ⵜⴰⵍⵙⵜ ⵉ ⵉⵙⵎ ⵏ \"$1\" ⵙ \"$2\".",
        "filedeleteerror": "ⵓⵔ ⵢⴰⵍⵍⴼⵓⵙ ⴰⴷ ⵉⵜⵜⵡⴰⴽⴽⵙ ⵓⴼⴰⵢⵍⵓ \"$1\".",
        "directorycreateerror": "Ur as tufit an tgt asddaw « $1 ».",
-       "filenotfound": "ⵓⵔ ⵢⴰⵍⵍⴼⵓⵙ ⴰⴷ ⵉⵜⵜⵢⴰⴼ ⵓⴼⴰⵢⵍⵓ \"$1\".",
+       "filenotfound": "ⵓⵔ ⵢⴰⵍⵍⴼⵓⵙ ⴰⴷ ⵉⵜⵜⵢⴰⴼ ⵓⴼⴰⵢⵍⵓ \"$1\".",
        "unexpected": "Azal (atig) llis ur nql: « $1 » = « $2 ».",
        "formerror": "Anzri: ur as tufit an tgt tifrkit",
        "badarticleerror": "Tigawt ad ur  as tufi ad ttuyskar ɣ tasna yad.",
        "cannotdelete": "Ur as tufa tasna yad ad ttuykkas niɣd asdaw ad « $1 ».\nAkks ad iskrt kra yaḍn",
-       "badtitle": "Azwl ur ifulkin",
+       "badtitle": "ⴰⵣⵡⵓⵍ ⵉⴼⵍⵍⵙⵏ",
        "badtitletext": "Azwl n tasna lli trit ur igadda, ixwa, niɣd iga aswl n gr tutlayt niḍ ngr tuwwurins ur izdimzyan. Ẓr urgis tgit kra nu uskkil niɣd mnnaw lli gis ur llanin",
        "viewsource": "ⵥⵔ ⴰⵙⴰⴳⵎ",
-       "virus-unknownscanner": "â´°âµ\8eâ´³âµ\8dâ´±âµ\89âµ\94âµ\93âµ\99 â´°âµ\94âµ\93âµ\99âµ\99âµ\89âµ\8f:",
-       "welcomeuser": "ⴱⵔⵔⴽ ⴰ $1!",
-       "yourname": "ⵉⵙⵎ ⵏ ⵓⵙⵎⵔⴰⵙ:",
-       "yourpassword": "ⵜⴰⴳⵓⵔⵉ ⵏ ⵓⵣⵔⴰⵢ:",
+       "virus-unknownscanner": "â´°âµ\8eâ´³âµ\8dâ´±âµ\89âµ\94âµ\93âµ\99 âµ\93âµ\94 âµ\89âµ\9câµ\9cⵢⴰⵡâµ\99âµ\99â´°âµ\8fâµ\8f :",
+       "welcomeuser": "ⴱⵔⵔⴽ ⴰ $1 !",
+       "yourname": "ⵉⵙⵎ ⵏ ⵓⵙⵎⵔⴰⵙ :",
+       "yourpassword": "ⵜⴰⴳⵓⵔⵉ ⵏ ⵓⵣⵔⴰⵢ :",
        "userlogin-yourpassword": "ⵜⴰⴳⵓⵔⵉ ⵏ ⵓⵣⵔⴰⵢ",
-       "yourpasswordagain": "ⴰⵔⴰ ⴷⴰⵖ ⵜⴰⴳⵓⵔⵉ ⵏ ⵓⵣⵔⴰⵢ:",
-       "yourdomainname": "Taɣult nek",
+       "yourpasswordagain": "ⴰⵔⴰ ⴷⴰⵖ ⵜⴰⴳⵓⵔⵉ ⵏ ⵓⵣⵔⴰⵢ :",
+       "yourdomainname": "ⵉⴳⵔ ⵏⵏⴽ :",
        "externaldberror": "Imma tlla ɣin kra lafut ɣu ukcumnk ulla urak ittuyskar at tsbddelt lkontnk nbrra.",
        "login": "ⴽⵛⵎ",
        "nav-login-createaccount": "ⴽⵛⵎ / ⵙⵏⵓⵍⴼⵓ ⴰⵎⵉⴹⴰⵏ",
        "createacct-benefit-body3": "{{PLURAL:$1|ⴰⵎⴷⵔⴰⵡ ⵉⴳⴳⵯⵔⴰⵏ|ⵉⵎⴷⵔⴰⵡⵏ ⴳⴳⵯⵔⴰⵏⵉⵏ}}",
        "badretype": "ⵜⵉⴳⵓⵔⵉⵡⵉⵏ ⵏ ⵓⵣⵔⴰⵢ ⵏⵏⴰ ⵜⵙⵙⴽⵛⵎⵜ ⵓⵔ ⵎⵙⴰⵙⴰⵏⵜ.",
        "userexists": "Asaɣ nu umsqdac li tskcmt illa yad",
-       "loginerror": "Gar akccum",
+       "loginerror": "ⴰⵣⴳⴳⴰⵍ ⵖ ⵓⵣⴷⴰⵢ",
        "createaccounterror": "$1 ur as tufit at kcmt",
        "loginsuccesstitle": "ⵜⵣⴷⵉⵜ ⵏⵏ",
        "loginsuccess": "<strong>ⵀⴰ ⴽ(ⵎ) ⵉⵏⵏ ⵖⵉⵍⴰⴷ ⵜⵣⴷⵉⵜ ⵏⵏ ⵖ {{SITENAME}} ⵙ ⵢⵉⵙⵎ ⵏ \"$1\".</strong>",
        "nosuchuser": "Asqdac « $1 » ur illi.\nUssaɣ n isqdacn ḥiln hlli.\nẒṛ daɣ ist turit mzyan mayad, niɣd [[Special:CreateAccount|tmmurẓmt amiḍan amaynu]].",
        "nosuchusershort": "Ur illa umsaws lli ilan assaɣ « $1 ». Ẓṛ ist turit mzyan mayad.",
-       "nouserspecified": "Illa fllak ad tarat assaɣ nk.",
+       "nouserspecified": "ⵉⵇⵇⴰⵏ ⴽ ⵉⴷ ⴰⴷ ⴰⴷ ⵜⴰⵔⴰⵜ ⵉⵙⵎ ⵏⵏⴽ ⵏ ⵓⵙⵎⵔⴰⵙ.",
        "login-userblocked": "Asqdac ad ur as yufi ad ikcm. Tazdayt ɣ ifalan uras ttuyskar",
        "mailmypassword": "ⴰⵍⵙ ⵉ ⵜⴳⵓⵔⵉ ⵏ ⵓⵣⵔⴰⵢ",
        "mailerror": "Gar azn n tbrat : $1",
        "emailconfirmlink": "Als i tasna nk n tbratin izd nit nttat ayan.",
-       "loginlanguagelabel": "ⵜⵓⵜⵍⴰⵢⵜ: $1",
+       "loginlanguagelabel": "ⵜⵓⵜⵍⴰⵢⵜ : $1",
        "pt-login": "ⵣⴷⵉ ⵏⵏ",
        "pt-login-button": "ⴽⵛⵎ",
        "pt-userlogout": "ⴼⴼⵖ",
        "resetpass_announce": "Tkcmt {{GENDER:||e|(e)}} s yat tangalt lli kin ilkmt s tbrat emeil . tangaltad ur tgi abla tin yat twalt. Bac ad tkmlt tqqiyyidank kcm tangalt tamaynut nk ɣid:",
        "resetpass_header": "ⵙⵏⴼⵍ ⵜⴰⴳⵓⵔⵉ ⵏ ⵓⵣⵔⴰⵢ ⵏ ⵓⵎⵉⴹⴰⵏ",
        "oldpassword": "ⵜⴰⴳⵓⵔⵉ ⵏ ⵓⵣⵔⴰⵢ ⵉⵇⴷⵎⵏ:",
-       "newpassword": "ⵜⴰⴳⵓⵔⵉ ⵏ ⵓⵣⵔⴰⵢ ⵜⴰⵎⴰⵢⵏⵓⵜ:",
-       "retypenew": "ⴰⵔⴰ ⴷⴰⵖ ⵜⴰⴳⵓⵔⵉ ⵏ ⵓⵣⵔⴰⵢ ⵜⴰⵎⴰⵢⵏⵓⵜ:",
+       "newpassword": "ⵜⴰⴳⵓⵔⵉ ⵏ ⵓⵣⵔⴰⵢ ⵜⴰⵎⴰⵢⵏⵓⵜ :",
+       "retypenew": "ⴰⵔⴰ ⴷⴰⵖ ⵜⴰⴳⵓⵔⵉ ⵏ ⵓⵣⵔⴰⵢ ⵜⴰⵎⴰⵢⵏⵓⵜ :",
        "resetpass_submit": "Sbadl awal n uzri tkcmt",
        "changepassword-success": "Awal n uzri nk ibudl mzyan! rad nit tilit ɣ ifalan",
        "botpasswords-label-create": "ⵙⵏⵓⵍⴼⵓ",
        "sig_tip": "ⴰⵙⴳⵎⴹ ⵏⵏⴽ/ⵎ ⵙ ⵜⵉⵣⵉ",
        "hr_tip": "izriri iɣzzifn (ⴰⴷ ⵜ ⵓⵔ ⵜⵙⵙⵓⴳⵜⵜ)",
        "summary": "ⴰⵣⴳⵣⵍ :",
-       "subject": "â´°âµ\99âµ\8fâµ\9câµ\8d:",
-       "minoredit": "ⵡⴰⴷ âµ\89ⴳⴰ â´°âµ\99âµ\8fâ´¼âµ\8d âµ\93âµ\8eâµ¥âµ\89âµ¢",
+       "subject": "âµ\89âµ\8eâµ\94âµ\99âµ\89 :",
+       "minoredit": "â´°âµ\99âµ\8fâ´¼âµ\8d âµ\8eⵥⵥâµ\89âµ\8f",
        "watchthis": "ⴹⴼⵓⵔ ⵜⴰⵙⵏⴰ ⴰⴷ",
        "savearticle": "ⵣⵎⵎⴻⵎ",
        "preview": "ⴱⵔⵉⴱⵢⵓ",
        "missingcommenttext": "ⵉ ⵕⴱⴱⵉ ⵙⵙⴽⵛⵎ ⴽⵔⴰ ⵏ ⵓⵖⴼⴰⵡⴰⵍ ⴷⴷⴰⵡ ⴰⵙ.",
        "summary-preview": "ⴱⵔⵉⴱⵢⵓ ⵏ ⵜⵓⴳⵣⵉⵍⵜ ⵏ ⵓⵙⵏⴼⵍ:",
        "blockedtitle": "ⵉⵜⵜⵡⴰⴳⴷⵍ ⵓⵙⵎⵔⴰⵙ ⴰⴷ",
-       "blockednoreason": "âµ\93âµ\94 âµ\9câ´»âµ\9câµ\9câµ¢âµ\93ⴼⴽâµ\89 ⴽⵔⴰ ⵏ ⵜⵎⵏⵜⵉⵍⵜ",
-       "whitelistedittext": "âµ\89 âµ\95ⴱⴱⵉ $1 ⵉⵖ ⵜⵔⵉⵜ ⴰⴷ ⵜⵙⵏⴼⵍⵜ ⵜⴰⵙⵏⵉⵡⵉⵏ.",
+       "blockednoreason": "âµ\93âµ\94 âµ\9câ´»âµ\9câµ\9cⵢⴰⵡⴼⴽⴰ ⴽⵔⴰ ⵏ ⵜⵎⵏⵜⵉⵍⵜ",
+       "whitelistedittext": "âµ\89 âµ\94ⴱⴱⵉ $1 ⵉⵖ ⵜⵔⵉⵜ ⴰⴷ ⵜⵙⵏⴼⵍⵜ ⵜⴰⵙⵏⵉⵡⵉⵏ.",
        "confirmedittext": "Illa fllak ad talst i tansa nk tbratin urta tsbadalt tisniwin.\nKcm zwar tft tansan nk tbratin ɣ [[Special:Preferences|Timssusmin n umqdac]].",
        "nosuchsectiontitle": "Ur as tufit ad taft ayyaw ad.",
        "nosuchsectiontext": "ⵜⵓⵔⵎⵜ ⴰⴷ ⵜⵙⵏⴼⵍⵜ ⵢⴰⵜ ⵜⴳⵣⵎⵉ ⵓⵔ ⵉⵍⵍⵉⵏ.\nⵉⵥⴹⴰⵔ ⴰⴷ ⵜⵉⵍⵉ ⵜⴻⵜⵜⵢⴰⵡⵙⵎⴰⵜⵜⵉ ⵏⵖ ⵜⴻⵜⵜⵡⴰⴽⴽⵙ ⵍⵍⵉⵖ ⴰⵔ ⵜⴻⵜⵜⴰⵏⵏⴰⵢⵜ ⵜⴰⵙⵏⴰ.",
        "page_first": "ⵜⴰⵎⵣⵡⴰⵔⵓⵜ",
        "page_last": "ⵜⴰⵎⴳⴳⴰⵔⵓⵜ",
        "histlegend": "Diff selection: ⵕⵛⵎ the radio boxes ⵏ ⵜⵓⵏⵖⵉⵍⵉⵏ ⵏⵏⴰ ⵜⵔⵉⵜ ⴰⴷ ⵜⵙⵎⵣⴰⵣⴰⵍⵜ, ⵜⴰⴷⴷⵜ ⵖⴼ enter ⵏⵖ ⵜⴰⴱⵓⵟⵓⵏⵜ ⵉⵍⵍⴰⵏ ⴷⴷⴰⵡ ⴰⵙ.<br />\nⵜⵉⵣⴳⵣⵉⵍⵉⵏ: <strong>({{int:cur}})</strong> = ⴰⵎⵣⴰⵔⴰⵢ ⵉⵍⵍⴰⵏ ⴷ ⵜⵓⵏⵖⵉⵍⵜ ⵉⴳⴳⵯⵔⴰⵏ, <strong>({{int:last}})</strong> = ⴰⵎⵣⴰⵔⴰⵢ ⵉⵍⵍⴰⵏ ⴷ ⵜⵓⵏⵖⵉⵍⵜ ⵉⵣⵡⴰⵔⵏ ⵜⴰⴷ, <strong>{{int:minoreditletter}}</strong> = ⴰⵙⵏⴼⵍ ⵓⵎⵥⵉⵢ.",
-       "history-fieldset-title": "ⵙⵉⴳⴳⵍ revisions",
+       "history-fieldset-title": "ⵙⵉⴳⴳⵍ ⵉⵣⵣⵔⴰⵢⵏ",
        "history-show-deleted": "ⵖⴰⵔ ⵜⵓⵏⵖⵉⵍⵜ ⵏⵏⴰ ⵉⵜⵜⵡⴰⴽⴽⵙⵏ",
-       "histfirst": "â´°âµ\87â´·âµ\89âµ\8e â´°â´½â´½âµ¯",
-       "histlast": "â´°âµ\8eâ´°âµ¢âµ\8fâµ\93 â´°â´½â´½âµ¯",
+       "histfirst": "ⴰⴽⴽⵯ âµ\89âµ\87â´·âµ\8eâµ\8f",
+       "histlast": "ⴰⴽⴽⵯ âµ\89âµ\8aâ´·âµ\89â´·âµ\8f",
        "historyempty": "(ⵉⵅⵡⴰ)",
        "history-feed-title": "ⴰⵎⵣⵔⵓⵢ ⵏ ⵜⵓⵏⵖⵉⵍⵉⵏ",
        "history-feed-description": "ⴰⵎⵣⵔⵓⵢ ⵏ ⵜⵓⵏⵖⵉⵍⵉⵏ ⵏ ⵜⴰⵙⵏⴰ ⴰⴷ ⵉⵍⵍⴰⵏ ⵖ ⵓⵡⵉⴽⵉ",
        "history-title": "ⴰⵎⵣⵔⵓⵢ ⵏ \"$1\"",
        "difference-title": "ⴰⵎⵣⴰⵔⴰⵢ ⵉⵍⵍⴰⵏ ⴳⵔ ⵜⵓⵏⵖⵉⵍⵉⵏ ⵏ \"$1\"",
        "difference-multipage": "(ⴰⵎⵣⴰⵔⴰⵢ ⴳⵔ ⵜⴰⵙⵏⵉⵡⵉⵏ)",
-       "lineno": "ⴰⵣⵔⵉⵔⴳ $1:",
+       "lineno": "ⴰⵣⵔⵉⵔⴳ $1 :",
        "compareselectedversions": "ⵙⵎⵣⴰⵣⴰⵍ ⵉⵣⵣⵔⴰⵢⵏ ⵜⵜⵢⴰⵙⵜⴰⵢⵏⵉⵏ",
        "showhideselectedversions": "Ml/Ḥbu ilqmn lli ittuystayn",
        "editundo": "ⵉⵡⵔⵔⵉ ⵏⵏ",
        "recentchanges-label-bot": "ⴰⵙⵏⴼⵍ ⴰⴷ ⵉⵙⴽⵔ ⵜ ⵢⴰⵏ ⵓⵔⵓⴱⵓ",
        "recentchanges-label-unpatrolled": "Ambddl ad ura jju ittmẓra",
        "recentchanges-label-plusminus": "ⵜⵏⴼⵍ ⵜⵉⴷⴷⵉ ⵏ ⵜⴰⵙⵏⴰ ⵙ ⵡⵓⵟⵟⵓⵏ ⴰⴷ ⵏ ⵉⴷ ⴱⴰⵢⵜ",
-       "recentchanges-legend-newpage": "{{int:recentchanges-label-newpage}} (âµ¥âµ\94 âµ\93âµ\8dâ´° [[Special:NewPages|âµ\9câ´°âµ\8dⴳⴰâµ\8eⵜ ⵏ ⵜⴰⵙⵏⵉⵡⵉⵏ ⵜⵉⵎⴰⵢⵏⵓⵜⵉⵏ]])",
+       "recentchanges-legend-newpage": "{{int:recentchanges-label-newpage}} (âµ¥âµ\94 âµ\93âµ\8dâ´° [[Special:NewPages|âµ\9câ´°âµ\8dâµ\89âµ\99âµ\9cⵜ ⵏ ⵜⴰⵙⵏⵉⵡⵉⵏ ⵜⵉⵎⴰⵢⵏⵓⵜⵉⵏ]])",
        "rcfilters-legend-heading": "<strong>ⵜⵉⵣⴳⵣⵉⵍⵉⵏ:</strong>",
        "rcfilters-days-title": "ⵓⵙⵙⴰⵏ ⴳⴳⵯⵔⴰⵏⵉⵏ",
        "rcfilters-hours-title": "ⵜⵉⵙⵔⴰⴳⵉⵏ ⴳⴳⵯⵔⴰⵏⵉⵏ",
        "recentchangeslinked-summary": "ⵉⵙⵏⴼⵉⵍⵏ ⵜⵜⵢⵓⵙⴽⴰⵔⵏⵉⵏ ⵜⵉⴳⵉⵔⴰ ⴰⴷ ⵉ ⵜⴰⵙⵏⵉⵡⵉⵏ ⵏⵏⴰ ⵙⵔⵙⵏⵜ ⵜⴻⵜⵜⴰⵡⵉ ⴽⵔⴰ ⵏ ⵜⴰⵙⵏⴰ ⵉⵥⵍⵉⵏ (ⵏⵖ ⵉ ⵉⴳⵎⴰⵎⵏ ⵏ ⴽⵔⴰ ⵏ ⵜⴰⴳⴳⴰⵢⵜ ⵉⵥⵍⵉⵏ).\nⵜⴰⵙⵏⵉⵡⵉⵏ ⵍⵍⴰⵏⵉⵏ ⵖ [[Special:Watchlist|ⵜⵍⴳⴰⵎⵜ ⵏⵏⴽ/ⵎ ⵏ ⵓⴹⴼⴼⵓⵔ]] ⵍⵍⴰⵏⵜ ⵙ ⵜⵉⵔⵔⴰ ⵣⵓⵔⵏⵉⵏ.",
        "recentchangeslinked-page": "ⵉⵙⵎ ⵏ ⵜⴰⵙⵏⴰ :",
        "recentchangeslinked-to": "ⵎⵍ ⵉⵙⵏⴼⵉⵍⵏ ⵏ ⵜⴰⵙⵏⵉⵡⵉⵏ ⵇⵇⵏⵏⵉⵏ ⵙ ⵜⴰⵙⵏⴰ instead",
-       "upload": "âµ\99â´½âµ\9câµ\94 ⴽⵔⴰ ⵏ ⵓⴼⴰⵢⵍⵓ",
+       "upload": "â´°âµ\8dâµ\8d â´· ⴽⵔⴰ ⵏ ⵓⴼⴰⵢⵍⵓ",
        "uploadbtn": "ⵙⴽⵜⵔ ⴰⴼⴰⵢⵍⵓ",
        "reuploaddesc": "Sbidd asrbu d turrit",
        "upload-tryagain": "Ṣafḍ Anglam n ufaylu li ibudln",
        "upload-form-label-usage-filename": "ⵉⵙⵎ ⵏ ⵓⴼⴰⵢⵍⵓ",
        "upload-form-label-infoform-categories": "ⵜⴰⴳⴳⴰⵢⵉⵏ",
        "upload-form-label-infoform-date": "ⴰⵙⴰⴽⵓⴷ",
-       "license": "ⵜⵓⵔⴰⴳⵜ:",
+       "license": "ⵜⵓⵔⴰⴳⵜ :",
        "license-header": "ⵜⵓⵔⴰⴳⵜ",
        "listfiles-delete": "ⴽⴽⵙ",
        "imgfile": "ⴰⴼⴰⵢⵍⵓ",
-       "listfiles": "âµ\9câ´°âµ\8dⴳⴰâµ\8eⵜ ⵏ ⵉⴼⴰⵢⵍⵓⵜⵏ",
+       "listfiles": "âµ\9câ´°âµ\8dâµ\89âµ\99âµ\9cⵜ ⵏ ⵉⴼⴰⵢⵍⵓⵜⵏ",
        "listfiles_date": "ⴰⵙⴰⴽⵓⴷ",
        "listfiles_name": "ⵉⵙⵎ",
        "listfiles_count": "ⵜⵓⵏⵖⵉⵍⵉⵏ",
        "uncategorizedcategories": "ⵜⴰⴳⴳⴰⵢⵉⵏ ⵓⵔ ⴰⵎⵓⵏⵉⵏ ⵖ ⵜⴰⴳⴳⴰⵢⵉⵏ",
        "prefixindex": "ⴽⵓⵍⵍⵓ ⵜⴰⵙⵏⵉⵡⵉⵏ ⵍⴰⵏⵉⵏ ⴰⵣⵡⵉⵔ",
        "protectedpages-page": "ⵜⴰⵙⵏⴰ",
-       "listusers": "âµ\9câ´°âµ\8dⴳⴰâµ\8eⵜ ⵏ ⵉⵙⵎⵔⴰⵙⵏ",
+       "listusers": "âµ\9câ´°âµ\8dâµ\89âµ\99âµ\9cⵜ ⵏ ⵉⵙⵎⵔⴰⵙⵏ",
        "usercreated": "{{GENDER:$3|ⵉⵏⵓⵍⴼⴰ|ⵜⵏⵓⵍⴼⴰ}} ⵖ $1 ⵖ $2",
        "newpages": "ⵜⴰⵙⵏⵉⵡⵉⵏ ⵜⵉⵎⴰⵢⵏⵓⵜⵉⵏ",
        "move": "ⵙⵎⵓⵜⵜⵉ",
        "linksearch-ok": "ⵙⵉⴳⴳⵍ",
        "linksearch-line": "$1 tmmuttid z $2",
        "listgrouprights-group": "ⵜⴰⵔⴰⴱⴱⵓⵜ",
-       "listgrouprights-members": "(âµ\9câ´°âµ\8dⴳⴰâµ\8eⵜ ⵏ ⵉⴳⵎⴰⵎⵏ)",
+       "listgrouprights-members": "(âµ\9câ´°âµ\8dâµ\89âµ\99âµ\9cⵜ ⵏ ⵉⴳⵎⴰⵎⵏ)",
        "emailuser": "Azn tabrat umsqdac ad",
        "emailsubject": "ⴰⵙⵏⵜⵍ:",
        "emailmessage": "ⵜⵓⵣⵉⵏⵜ:",
        "emailsend": "ⴰⵣⵏ",
-       "watchlist": "âµ\9câ´°âµ\8dⴳⴰâµ\8eⵜ ⵏ ⵓⴹⴼⴼⵓⵔ",
-       "mywatchlist": "âµ\9câ´°âµ\8dⴳⴰâµ\8eⵜ ⵏ ⵓⴹⴼⴼⵓⵔ",
+       "watchlist": "âµ\9câ´°âµ\8dâµ\89âµ\99âµ\9cⵜ ⵏ ⵓⴹⴼⴼⵓⵔ",
+       "mywatchlist": "âµ\9câ´°âµ\8dâµ\89âµ\99âµ\9cⵜ ⵏ ⵓⴹⴼⴼⵓⵔ",
        "watchlistfor2": "ⵉ $1 $2",
        "addedwatchtext": "tasna « [[:$1]] » tllan ɣ [[Special:Watchlist|umuɣ n umtfr]]. Imbdln lli dyuckan d tasna lli dis iṭṭuzn rad asn nskr agmmaḍ nsn. Tasna radd ttbayan s \"uḍnay\" ɣ [[Special:RecentChanges|Umuɣ n imbddeln imaynutn]]",
        "removedwatchtext": "Tasna \"[[:$1]]\" ḥra ttuykkas z [[Special:Watchlist|your watchlist]].",
        "sp-contributions-submit": "ⵙⵉⴳⴳⵍ",
        "whatlinkshere": "ⵎⴰⴷ ⵉⵜⵜⴰⵡⵉⵏ ⵙ ⵖⵉⴷ",
        "whatlinkshere-title": "ⵜⴰⵙⵏⵉⵡⵉⵏ ⵉⵜⵜⴰⵡⵢⵏ ⵙ \"$1\"",
-       "whatlinkshere-page": "ⵜⴰⵙⵏⴰ:",
+       "whatlinkshere-page": "ⵜⴰⵙⵏⴰ :",
        "linkshere": "ⵜⴰⵙⵏⵉⵡⵉⵏ ⴰⴷ ⴹⴼⴰⵔⵏⵉⵏ ⴰⵔ ⵜⵜⴰⵡⵉⵏⵜ ⵙ <strong>$2</strong>:",
        "nolinkshere": "ⵓⵍⴰ ⴽⵔⴰ ⵏ ⵜⴰⵙⵏⴰ ⵓⵔ ⴰⵔ ⵜⴻⵜⵜⴰⵡⵉ ⵙ <strong>$2</strong>.",
        "nolinkshere-ns": "Ur tlla kra n tasna izdin d  '''$2''' ɣ tɣult l-ittuystayn.",
        "whatlinkshere-hideimages": "$1 ⵉⵍⵉⵏⴽⵏ ⵏ ⵓⴼⴰⵢⵍⵓ",
        "whatlinkshere-filters": "ⵜⵉⵙⵜⵜⴰⵢⵉⵏ",
        "blockip": "ⴳⴷⵍ {{GENDER:$1|ⴰⵙⵎⵔⴰⵙ|ⵜⴰⵙⵎⵔⴰⵙⵜ}}",
-       "ipboptions": "2 ikudn:2 hours,1 as:1 day,3 ussan:3 days,1 imalas:1 week,2 imalasn:2 weeks,1 ayur:1 month,3 irn:3 months,6 irn:6 months,1 asggas:1 year,tusut ur iswuttan:infinite",
+       "ipboptions": "2 ⵏ ⵜⵙⵔⴰⴳⵉⵏ:2 hours,1 ⵏ ⵡⴰⵙⵙ:1 day,3 ⵏ ⵡⵓⵙⵙⴰⵏ:3 days,1 ⵏ ⵉⵎⴰⵍⴰⵙⵙ:1 week,2 ⵏ ⵉⴷ ⵉⵎⴰⵍⴰⵙⵙ:2 weeks,1 ⵏ ⵡⴰⵢⵢⵓ:1 month,3 ⵏ ⵉⵢⵢⵉⵔⵏ:3 months,6 ⵏ ⵉⵢⵢⵉⵔⵏ:6 months,1 ⵏ ⵓⵙⴳⴳⵯⴰⵙ:1 year,ⴱⴷⴷⴰ:infinite",
        "ipbhidename": "ḥbu assaɣ n umsqdac ɣ imbdln d umuɣn",
        "ipbwatchuser": "Tfr tisniwin d imsgdaln n umqdac",
        "autoblocklist-submit": "ⵙⵉⴳⴳⵍ",
        "tooltip-pt-anontalk": "Amsgdal f imbddeln n tansa n IP yad",
        "tooltip-pt-preferences": "ⵜⵉⵙⵖⴰⵍ {{GENDER:|ⵏⵏⴽ|ⵏⵏⵎ}}",
        "tooltip-pt-watchlist": "Tifilit n tisnatin li itsaggan imdddeln li gisnt ittyskarn..",
-       "tooltip-pt-mycontris": "âµ\9câ´°âµ\8dⴳⴰâµ\8eⵜ ⵏ ⵜⴷⵔⴰⵡⵉⵏ {{GENDER:|ⵏⵏⴽ|ⵏⵏⵎ}}",
+       "tooltip-pt-mycontris": "âµ\9câ´°âµ\8dâµ\89âµ\99âµ\9cⵜ ⵏ ⵜⴷⵔⴰⵡⵉⵏ {{GENDER:|ⵏⵏⴽ|ⵏⵏⵎ}}",
        "tooltip-pt-login": "ⵢⵓⴼ ⴰⴽ ⴰ'ⵏⵏ ⵜⵣⴷⵢⵜ, ⵎⴰⵛⴰ ⵓⵔ ⵉⴳⵉ ⴱⵣⵣⵉⵣⵜ.",
        "tooltip-pt-logout": "ⴼⴼⵖ",
        "tooltip-ca-talk": "ⴰⵎⵙⴰⵡⴰⵍ ⴼ ⵜⴰⵙⵏⴰ ⵏ ⵜⵓⵎⴰⵢⵜ",
        "tooltip-ca-undelete": "Rard imbddeln imzwura li ittyskarnin ɣ tasna yad",
        "tooltip-ca-move": "ⵙⵎⵓⵜⵜⵉ ⵜⴰⵙⵏⴰ ⴰⴷ",
        "tooltip-ca-watch": "ⵔⵏⵓ ⵜⴰⵙⵏⴰ ⴰⴷ ⵉ ⵜⵍⴳⴰⵎⵜ {{GENDER:|ⵏⵏⴽ|ⵏⵏⵎ}} ⵏ ⵓⴹⴼⴼⵓⵔ",
-       "tooltip-ca-unwatch": "âµ\99âµ\89âµ\9câµ\9câµ\89 âµ\9câ´°âµ\99âµ\8fâ´° â´°â´· âµ£âµ\96 âµ\9câµ\8dⴳⴰâµ\8eⵜ {{GENDER:|ⵏⵏⴽ|ⵏⵏⵎ}} ⵏ ⵓⴹⴼⴼⵓⵔ",
+       "tooltip-ca-unwatch": "âµ\99âµ\89âµ\9câµ\9câµ\89 âµ\8fâµ\8f âµ\9câ´°âµ\99âµ\8fâ´° â´°â´· âµ£âµ\96 âµ\9câ´°âµ\8dâµ\89âµ\99âµ\9cⵜ {{GENDER:|ⵏⵏⴽ|ⵏⵏⵎ}} ⵏ ⵓⴹⴼⴼⵓⵔ",
        "tooltip-search": "ⵙⵉⴳⴳⵍ ⵖ {{SITENAME}}",
        "tooltip-search-go": "ⴼⵜⵓ ⵙ ⵜⴰⵙⵏⴰ ⵉⵍⴰⵏ ⵏⵉⵜ ⵉⵙⵎ ⴰⴷ ⵉⵖ ⵜⵍⵍⴰ",
        "tooltip-search-fulltext": "ⵙⵉⴳⴳⵍ ⴰⴹⵔⵉⵙ ⴰⴷ ⵖ ⵜⴰⵙⵏⵉⵡⵉⵏ",
        "tooltip-n-mainpage-description": "ⴽⴽ ⴷ ⵜⴰⵙⵏⴰ ⵏ ⵓⵙⵏⵓⴱⴳ",
        "tooltip-n-portal": "ⴼ ⵓⴱⵕⵓⵊⵉ, ⵎⴰⴷ ⵜⵥⴹⴰⵔⵜ ⴰⴷ ⵜ ⵜⵙⴽⵔⵜ, ⵎⴰⵏⵉ ⵔⴰⴷ ⵜⴰⴼⵜ ⵓⵎⵍⴰⵏ",
        "tooltip-n-currentevents": "Tiɣri izrbn i kullu maɣid immusn",
-       "tooltip-n-recentchanges": "âµ\9câ´°âµ\8dⴳⴰâµ\8eⵜ ⵏ ⵉⵙⵏⴼⵉⵍⵏ ⴳⴳⵯⵔⴰⵏⵉⵏ ⵖ ⵓⵡⵉⴽⵉ",
+       "tooltip-n-recentchanges": "âµ\9câ´°âµ\8dâµ\89âµ\99âµ\9cⵜ ⵏ ⵉⵙⵏⴼⵉⵍⵏ ⴳⴳⵯⵔⴰⵏⵉⵏ ⵖ ⵓⵡⵉⴽⵉ",
        "tooltip-n-randompage": "ⵣⴷⵎ ⴷ ⴽⵔⴰ ⵏ ⵜⴰⵙⵏⴰ ⵙ ⵓⴷⵀⵎⴰⵙ",
        "tooltip-n-help": "ⵎⴰ ⵖ 'ⵜⵜⴰⴼⴰⵜ ⵜⵉⵡⵉⵙⵉ",
-       "tooltip-t-whatlinkshere": "âµ\9câ´°âµ\8dⴳⴰâµ\8eⵜ ⵏ ⴽⵓⵍⵍⵓ ⵜⴰⵙⵏⵉⵡⵉⵏ ⵉⵜⵜⴰⵡⵉⵏ ⵙ ⵖⵉⴷ",
+       "tooltip-t-whatlinkshere": "âµ\9câ´°âµ\8dâµ\89âµ\99âµ\9cⵜ ⵏ ⴽⵓⵍⵍⵓ ⵜⴰⵙⵏⵉⵡⵉⵏ ⵉⵜⵜⴰⵡⵉⵏ ⵙ ⵖⵉⴷ",
        "tooltip-t-recentchangeslinked": "ⵉⵙⵏⴼⵉⵍⵏ ⴳⴳⵯⵔⴰⵏⵉⵏ ⵖ ⵜⴰⵙⵏⵉⵡⵉⵏ ⵏⵏⴰ ⵙⵔⵙⵏ ⵜⴻⵜⵜⴰⵡⵉ ⵜⴰⵙⵏⴰ ⴰⴷ",
        "tooltip-feed-rss": "Usuddm (Flux) n tasna yad",
        "tooltip-feed-atom": "ⵉⴼⵉⵍⵉ ⴰⵟⵓⵎ ⵏ ⵜⴰⵙⵏⴰ ⴰⴷ",
-       "tooltip-t-contributions": "âµ\9câ´°âµ\8dⴳⴰâµ\8eⵜ ⵏ ⵜⴷⵔⴰⵡⵉⵏ ⵏ {{GENDER:$1|ⵓⵙⵎⵔⴰⵙ|ⵜⵙⵎⵔⴰⵙⵜ}} ⴰⴷ",
+       "tooltip-t-contributions": "âµ\9câ´°âµ\8dâµ\89âµ\99âµ\9cⵜ ⵏ ⵜⴷⵔⴰⵡⵉⵏ ⵏ {{GENDER:$1|ⵓⵙⵎⵔⴰⵙ|ⵜⵙⵎⵔⴰⵙⵜ}} ⴰⴷ",
        "tooltip-t-emailuser": "Ṣafd tabrat umsqdac ad",
-       "tooltip-t-upload": "âµ\99â´½âµ\9câµ\94 ⵉⴼⴰⵢⵍⵓⵜⵏ",
-       "tooltip-t-specialpages": "âµ\9câ´°âµ\8dⴳⴰâµ\8eâµ\9c âµ\8f â´½âµ\93âµ\8dâµ\8dâµ\93 âµ\9câ´°âµ\99âµ\8fâµ\89ⵡâµ\89âµ\8f âµ¥âµ\8dâµ\89âµ\8fⵉⵏ",
+       "tooltip-t-upload": "â´°âµ\8dâµ\8d â´· ⵉⴼⴰⵢⵍⵓⵜⵏ",
+       "tooltip-t-specialpages": "âµ\9câ´°âµ\8dâµ\89âµ\99âµ\9câµ\9c âµ\8f â´½âµ\93âµ\8dâµ\8dâµ\93 âµ\9câ´°âµ\99âµ\8fâµ\89ⵡâµ\89âµ\8f âµ\89âµ¥âµ\8dⵉⵏ",
        "tooltip-t-print": "Printable version of this page",
-       "tooltip-t-permalink": "Azday bdda i lqim n tasna yad",
+       "tooltip-t-permalink": "ⴰⵍⵉⵏⴽ ⵉⴳⴰⵏ ⵡⵉⵏ ⴱⴷⴷⴰ ⵉ ⵜⵓⵏⵖⵉⵍⵜ ⴰⴷ ⵏ ⵜⴰⵙⵏⴰ",
        "tooltip-ca-nstab-main": "ⵥⵔ ⵜⴰⵙⵏⴰ ⵏ ⵜⵓⵎⴰⵢⵜ",
        "tooltip-ca-nstab-user": "Ẓr tasna n useqdac",
        "tooltip-ca-nstab-media": "Iẓri n tasna n midya",
        "tooltip-rollback": "\"Rard\" s yan klik ażrig (iżrign) s ɣiklli sttin kkan tiklit li igguran",
        "tooltip-undo": "\"Sglb\" ḥiyd ambdl ad t mmurẓmt tasatmt n umbdl ɣ umuḍ tiẓri tamzwarut.",
        "tooltip-summary": "ⵙⵙⴽⵛⵎ ⵏⵏ ⴽⵔⴰ ⵏ ⵓⵣⴳⵣⵍ ⵎⵥⵥⵉⵏ",
+       "pageinfo-header-basic": "ⵓⵎⵍⴰⵏ ⵉⵙⵉⵍⴰⵏⵏ",
        "pageinfo-header-edits": "ⴰⵎⵣⵔⵓⵢ ⵏ ⵓⵙⵏⴼⵍ",
        "pageinfo-length": "ⵜⵉⴷⴷⵉ ⵏ ⵜⴰⵙⵏⴰ (ⵙ ⵉⴷ ⴱⴰⵢⵜ)",
        "pageinfo-language": "ⵜⵓⵜⵍⴰⵢⵜ ⵏ ⵜⵓⵎⴰⵢⵜ ⵏ ⵜⴰⵙⵏⴰ",
        "pageinfo-firsttime": "ⴰⵙⴰⴽⵓⴷ ⵏ ⵓⵙⵏⵓⵍⴼⵓ ⵏ ⵜⴰⵙⵏⴰ",
        "pageinfo-lastuser": "ⴰⵎⵙⵏⴼⵍ ⵉⴳⴳⵯⵔⴰⵏ",
        "pageinfo-lasttime": "ⴰⵙⴰⴽⵓⴷ ⵏ ⵓⵙⵏⴼⵍ ⴰⴽⴽⵯ ⵉⴳⴳⵯⵔⴰⵏ",
+       "pageinfo-magic-words": "{{PLURAL:$1|ⵜⴰⴳⵓⵔⵉ ⵉⵙⵎⴰⵊⵉⴽⵉⵏ|ⵜⵉⴳⵓⵔⵉⵡⵉⵏ ⵙⵎⴰⵊⵉⴽⵏⵉⵏ}} ($1)",
        "pageinfo-hidden-categories": "{{PLURAL:$1|ⴰⵙⵎⵉⵍ ⵉⵏⵜⵍⵏ|ⵉⵙⵎⵉⵍⵏ ⵏⵜⵍⵏⵉⵏ}} ($1)",
        "pageinfo-contentpage-yes": "ⵢⴰⵀ",
        "pageinfo-protect-cascading-yes": "ⵢⴰⵀ",
        "confirm-rollback-button": "ⵡⴰⵅⵅⴰ",
        "quotation-marks": "\"$1\"",
        "imgmultipagenext": "ⵜⴰⵙⵏⴰ ⴷ ⵉⴹⴼⴰⵔⵏ →",
-       "imgmultigo": "â´·â´·âµ\93!",
+       "imgmultigo": "âµ\8dâ´½âµ\8e âµ\8fâµ\8f !",
        "imgmultigoto": "ⴼⵜⵓ ⵙ ⵜⴰⵙⵏⴰ $1",
        "img-lang-default": "(ⵜⵓⵜⵍⴰⵢⵜ ⵙ ⵓⵡⵏⵓⵍ)",
        "ascending_abbrev": "aryaqliw",
index 46a6f7b..a71d733 100644 (file)
        "timezoneregion-europe": "ทวีปยุโรป",
        "timezoneregion-indian": "มหาสมุทรอินเดีย",
        "timezoneregion-pacific": "มหาสมุทรแปซิฟิก",
-       "allowemail": "อà¸\99ุà¸\8dาà¸\95à¹\83หà¹\89à¸\9cูà¹\89à¹\83à¸\8aà¹\89อืà¹\88à¸\99อีà¹\80มลหา",
+       "allowemail": "อà¸\99ุà¸\8dาà¸\95à¹\83หà¹\89à¸\9cูà¹\89à¹\83à¸\8aà¹\89อืà¹\88à¸\99สà¹\88à¸\87อีà¹\80มลà¸\96ึà¸\87à¸\89ัà¸\99à¹\84à¸\94à¹\89",
        "email-allow-new-users-label": "อนุญาตอีเมลจากผู้ใช้ใหม่",
        "email-blacklist-label": "ห้ามผู้ใช้เหล่านี้มิให้อีเมลหา:",
        "prefs-searchoptions": "ค้นหา",
index b09bc7e..c46e25d 100644 (file)
@@ -36,7 +36,7 @@
        "tog-hideminor": "Соңгы үзгәртүләр исемлегендә кече үзгәртүләр яшерелсен",
        "tog-hidepatrolled": "Тикшерелгән үзгәртүләр яңа үзгәртүләр исемлегеннән яшерелсен",
        "tog-newpageshidepatrolled": "Тикшерелгән битләр яңа битләр исемлегеннән яшерелсен",
-       "tog-hidecategorization": "Битләрне төркемләшүне ябу",
+       "tog-hidecategorization": "Битләрне төркемләшү яшерелсен",
        "tog-extendwatchlist": "Соңгыларын гына түгел, ә барлык үзгәртүләрне эченә алган, киңәйтелгән күзәтү исемлеге",
        "tog-usenewrc": "Соңгы үзгәртүләрдә һәм күзәтү исемлегендә үзгәрешләрне төркемләргә",
        "tog-numberheadings": "Атамалар автомат рәвештә номерлансын",
@@ -67,7 +67,7 @@
        "tog-watchlistreloadautomatically": "Фильтр алмашкан очракта күзәтү исемлеген автоматик рәвештә яңартырга (JavaScript кирәк)",
        "tog-watchlisthideanons": "Аноним кулланучыларның үзгәртүләре күзәтү исемлегеннән яшерелсен",
        "tog-watchlisthidepatrolled": "Тикшерелгән үзгәртүләр күзәтү исемлегеннән яшерелсен",
-       "tog-watchlisthidecategorization": "Битләрне төркемләшүне ябу",
+       "tog-watchlisthidecategorization": "Битләрне төркемләшү яшерелсен",
        "tog-ccmeonemails": "Башка кулланучыларга җибәргән хатларымның копияләре миңа да җибәрелсен",
        "tog-diffonly": "Юрама чагыштыру астында бит эчтәлеге күрсәтелмәсен",
        "tog-showhiddencats": "Яшерен төркемнәр күрсәтелсен",
        "sp-contributions-search": "Кертемне эзләү",
        "sp-contributions-username": "Кулланучының IP адресы яки исеме:",
        "sp-contributions-toponly": "Соңгы юрамадагы үзгәртүләр генә күрсәтелсен",
-       "sp-contributions-newonly": "Битләр ясау үзгәртмәләрен генә күрсәтү",
-       "sp-contributions-hideminor": "Кече үзгәртүләрне яшерергә",
+       "sp-contributions-newonly": "Битләр ясау үзгәртмәләре генә күрсәтелсен",
+       "sp-contributions-hideminor": "Кече үзгәртүләр яшерелсен",
        "sp-contributions-submit": "Эзләү",
        "whatlinkshere": "Бирегә нәрсә сылтый",
        "whatlinkshere-title": "$1 битенә сылтый торган битләр",
index 03f02b4..ea49fd0 100644 (file)
@@ -13,6 +13,7 @@
        'use strict';
 
        var mw, StringSet, log,
+               hasOwn = Object.prototype.hasOwnProperty,
                trackQueue = [];
 
        /**
                                return resolved;
                        }
 
+                       /**
+                        * Resolve a relative file path.
+                        *
+                        * For example, resolveRelativePath( '../foo.js', 'resources/src/bar/bar.js' )
+                        * returns 'resources/src/foo.js'.
+                        *
+                        * @param {string} relativePath Relative file path, starting with ./ or ../
+                        * @param {string} basePath Path of the file (not directory) relativePath is relative to
+                        * @return {string|null} Resolved path, or null if relativePath does not start with ./ or ../
+                        */
+                       function resolveRelativePath( relativePath, basePath ) {
+                               var prefixes, prefix, baseDirParts,
+                                       relParts = relativePath.match( /^((?:\.\.?\/)+)(.*)$/ );
+
+                               if ( !relParts ) {
+                                       return null;
+                               }
+
+                               baseDirParts = basePath.split( '/' );
+                               // basePath looks like 'foo/bar/baz.js', so baseDirParts looks like [ 'foo', 'bar, 'baz.js' ]
+                               // Remove the file component at the end, so that we are left with only the directory path
+                               baseDirParts.pop();
+
+                               prefixes = relParts[ 1 ].split( '/' );
+                               // relParts[ 1 ] looks like '../../', so prefixes looks like [ '..', '..', '' ]
+                               // Remove the empty element at the end
+                               prefixes.pop();
+
+                               // For every ../ in the path prefix, remove one directory level from baseDirParts
+                               while ( ( prefix = prefixes.pop() ) !== undefined ) {
+                                       if ( prefix === '..' ) {
+                                               baseDirParts.pop();
+                                       }
+                               }
+
+                               // If there's anything left of the base path, prepend it to the file path
+                               return ( baseDirParts.length ? baseDirParts.join( '/' ) + '/' : '' ) + relParts[ 2 ];
+                       }
+
+                       /**
+                        * Make a require() function scoped to a package file
+                        * @private
+                        * @param {Object} moduleObj Module object from the registry
+                        * @param {string} basePath Path of the file this is scoped to. Used for relative paths.
+                        * @return {Function}
+                        */
+                       function makeRequireFunction( moduleObj, basePath ) {
+                               return function require( moduleName ) {
+                                       var fileName, fileContent, result, moduleParam,
+                                               scriptFiles = moduleObj.script.files;
+                                       fileName = resolveRelativePath( moduleName, basePath );
+                                       if ( fileName === null ) {
+                                               // Not a relative path, so it's a module name
+                                               return mw.loader.require( moduleName );
+                                       }
+
+                                       if ( !hasOwn.call( scriptFiles, fileName ) ) {
+                                               throw new Error( 'Cannot require() undefined file ' + fileName );
+                                       }
+                                       if ( hasOwn.call( moduleObj.packageExports, fileName ) ) {
+                                               // File has already been executed, return the cached result
+                                               return moduleObj.packageExports[ fileName ];
+                                       }
+
+                                       fileContent = scriptFiles[ fileName ];
+                                       if ( typeof fileContent === 'function' ) {
+                                               moduleParam = { exports: {} };
+                                               fileContent( makeRequireFunction( moduleObj, fileName ), moduleParam );
+                                               result = moduleParam.exports;
+                                       } else {
+                                               // fileContent is raw data, just pass it through
+                                               result = fileContent;
+                                       }
+                                       moduleObj.packageExports[ fileName ] = result;
+                                       return result;
+                               };
+                       }
+
                        /**
                         * Load and execute a script.
                         *
                                $CODE.profileExecuteStart();
 
                                runScript = function () {
-                                       var script, markModuleReady, nestedAddScript;
+                                       var script, markModuleReady, nestedAddScript, mainScript;
 
                                        $CODE.profileScriptStart();
                                        script = registry[ module ].script;
                                        try {
                                                if ( Array.isArray( script ) ) {
                                                        nestedAddScript( script, markModuleReady, 0 );
-                                               } else if ( typeof script === 'function' ) {
-                                                       // Keep in sync with queueModuleScript() for debug mode
-                                                       if ( module === 'jquery' ) {
-                                                               // This is a special case for when 'jquery' itself is being loaded.
-                                                               // - The standard jquery.js distribution does not set `window.jQuery`
-                                                               //   in CommonJS-compatible environments (Node.js, AMD, RequireJS, etc.).
-                                                               // - MediaWiki's 'jquery' module also bundles jquery.migrate.js, which
-                                                               //   in a CommonJS-compatible environment, will use require('jquery'),
-                                                               //   but that can't work when we're still inside that module.
-                                                               script();
+                                               } else if (
+                                                       typeof script === 'function' || (
+                                                               typeof script === 'object' &&
+                                                               script !== null
+                                                       )
+                                               ) {
+                                                       if ( typeof script === 'function' ) {
+                                                               // Keep in sync with queueModuleScript() for debug mode
+                                                               if ( module === 'jquery' ) {
+                                                                       // This is a special case for when 'jquery' itself is being loaded.
+                                                                       // - The standard jquery.js distribution does not set `window.jQuery`
+                                                                       //   in CommonJS-compatible environments (Node.js, AMD, RequireJS, etc.).
+                                                                       // - MediaWiki's 'jquery' module also bundles jquery.migrate.js, which
+                                                                       //   in a CommonJS-compatible environment, will use require('jquery'),
+                                                                       //   but that can't work when we're still inside that module.
+                                                                       script();
+                                                               } else {
+                                                                       // Pass jQuery twice so that the signature of the closure which wraps
+                                                                       // the script can bind both '$' and 'jQuery'.
+                                                                       script( window.$, window.$, mw.loader.require, registry[ module ].module );
+                                                               }
                                                        } else {
-                                                               // Pass jQuery twice so that the signature of the closure which wraps
-                                                               // the script can bind both '$' and 'jQuery'.
-                                                               script( window.$, window.$, mw.loader.require, registry[ module ].module );
+                                                               mainScript = script.files[ script.main ];
+                                                               if ( typeof mainScript !== 'function' ) {
+                                                                       throw new Error( 'Main script file ' + script.main + ' in module ' + module +
+                                                                               'must be of type function, is of type ' + typeof mainScript );
+                                                               }
+                                                               // jQuery parameters are not passed for multi-file modules
+                                                               mainScript(
+                                                                       makeRequireFunction( registry[ module ], script.main ),
+                                                                       registry[ module ].module
+                                                               );
                                                        }
                                                        markModuleReady();
-
                                                } else if ( typeof script === 'string' ) {
                                                        // Site and user modules are legacy scripts that run in the global scope.
                                                        // This is transported as a string instead of a function to avoid needing
                                        module: {
                                                exports: {}
                                        },
+                                       // module.export objects for each package file inside this module
+                                       packageExports: {},
                                        version: String( version || '' ),
                                        dependencies: dependencies || [],
                                        group: typeof group === 'string' ? group : null,
                                 *  as '`[name]@[version]`". This version should match the requested version
                                 *  (from #batchRequest and #registry). This avoids race conditions (T117587).
                                 *  For back-compat with MediaWiki 1.27 and earlier, the version may be omitted.
-                                * @param {Function|Array|string} [script] Function with module code, list of URLs
-                                *  to load via `<script src>`, or string of module code for `$.globalEval()`.
+                                * @param {Function|Array|string|Object} [script] Module code. This can be a function,
+                                *  a list of URLs to load via `<script src>`, a string for `$.globalEval()`, or an
+                                *  object like {"files": {"foo.js":function, "bar.js": function, ...}, "main": "foo.js"}.
+                                *  If an object is provided, the main file will be executed immediately, and the other
+                                *  files will only be executed if loaded via require(). If a function or string is
+                                *  provided, it will be executed/evaluated immediately. If an array is provided, all
+                                *  URLs in the array will be loaded immediately, and executed as soon as they arrive.
                                 * @param {Object} [style] Should follow one of the following patterns:
                                 *
                                 *     { "css": [css, ..] }
                                         */
                                        set: function ( module ) {
                                                var key, args, src,
+                                                       encodedScript,
                                                        descriptor = mw.loader.moduleRegistry[ module ];
 
                                                key = getModuleKey( module );
                                                }
 
                                                try {
+                                                       if ( typeof descriptor.script === 'function' ) {
+                                                               encodedScript = String( descriptor.script );
+                                                       } else if (
+                                                               // Plain object: an object that is not null and is not an array
+                                                               typeof descriptor.script === 'object' &&
+                                                               descriptor.script &&
+                                                               !Array.isArray( descriptor.script )
+                                                       ) {
+                                                               encodedScript = '{' +
+                                                                       Object.keys( descriptor.script ).map( function ( key ) {
+                                                                               var value = descriptor.script[ key ];
+                                                                               return JSON.stringify( key ) + ':' +
+                                                                                       ( typeof value === 'function' ? value : JSON.stringify( value ) );
+                                                                       } ).join( ',' ) +
+                                                                       '}';
+                                                       } else {
+                                                               encodedScript = JSON.stringify( descriptor.script );
+                                                       }
                                                        args = [
                                                                JSON.stringify( key ),
-                                                               typeof descriptor.script === 'function' ?
-                                                                       String( descriptor.script ) :
-                                                                       JSON.stringify( descriptor.script ),
+                                                               encodedScript,
                                                                JSON.stringify( descriptor.style ),
                                                                JSON.stringify( descriptor.messages ),
                                                                JSON.stringify( descriptor.templates )
diff --git a/tests/phpunit/data/resourceloader/sample.json b/tests/phpunit/data/resourceloader/sample.json
new file mode 100644 (file)
index 0000000..f2b69d0
--- /dev/null
@@ -0,0 +1,4 @@
+{
+       "foo": "bar",
+       "answer": 42
+}
index 4556473..ab9abbb 100644 (file)
@@ -454,6 +454,34 @@ class XmlTest extends MediaWikiTestCase {
                );
        }
 
+       /**
+        * @covers Xml::encodeJsVar
+        */
+       public function testXmlJsCode() {
+               $code = 'function () { foo( 42 ); }';
+               $this->assertEquals(
+                       $code,
+                       Xml::encodeJsVar( new XmlJsCode( $code ) )
+               );
+       }
+
+       /**
+        * @covers Xml::encodeJsVar
+        * @covers XmlJsCode::encodeObject
+        */
+       public function testEncodeObject() {
+               $codeA = 'function () { foo( 42 ); }';
+               $codeB = 'function ( jQuery ) { bar( 142857 ); }';
+               $obj = XmlJsCode::encodeObject( [
+                       'a' => new XmlJsCode( $codeA ),
+                       'b' => new XmlJsCode( $codeB )
+               ] );
+               $this->assertEquals(
+                       "{\"a\":$codeA,\"b\":$codeB}",
+                       Xml::encodeJsVar( $obj )
+               );
+       }
+
        /**
         * @covers Xml::listDropDown
         */
index 225c195..d3a4ed4 100644 (file)
@@ -40,36 +40,34 @@ class ApiQuerySiteinfoTest extends ApiTestCase {
        }
 
        public function testLinkPrefixCharset() {
-               global $wgContLang;
-
-               $this->setContentLang( 'ar' );
-               $this->assertTrue( $wgContLang->linkPrefixExtension(), 'Sanity check' );
+               $contLang = Language::factory( 'ar' );
+               $this->setContentLang( $contLang );
+               $this->assertTrue( $contLang->linkPrefixExtension(), 'Sanity check' );
 
                $data = $this->doQuery();
 
-               $this->assertSame( $wgContLang->linkPrefixCharset(), $data['linkprefixcharset'] );
+               $this->assertSame( $contLang->linkPrefixCharset(), $data['linkprefixcharset'] );
        }
 
        public function testVariants() {
-               global $wgContLang;
-
-               $this->setContentLang( 'zh' );
-               $this->assertTrue( $wgContLang->hasVariants(), 'Sanity check' );
+               $contLang = Language::factory( 'zh' );
+               $this->setContentLang( $contLang );
+               $this->assertTrue( $contLang->hasVariants(), 'Sanity check' );
 
                $data = $this->doQuery();
 
                $expected = array_map(
-                       function ( $code ) use ( $wgContLang ) {
-                               return [ 'code' => $code, 'name' => $wgContLang->getVariantname( $code ) ];
+                       function ( $code ) use ( $contLang ) {
+                               return [ 'code' => $code, 'name' => $contLang->getVariantname( $code ) ];
                        },
-                       $wgContLang->getVariants()
+                       $contLang->getVariants()
                );
 
                $this->assertSame( $expected, $data['variants'] );
        }
 
        public function testReadOnly() {
-               $svc = \MediaWiki\MediaWikiServices::getInstance()->getReadOnlyMode();
+               $svc = MediaWikiServices::getInstance()->getReadOnlyMode();
                $svc->setReason( 'Need more donations' );
                try {
                        $data = $this->doQuery();
@@ -82,18 +80,21 @@ class ApiQuerySiteinfoTest extends ApiTestCase {
        }
 
        public function testNamespaces() {
-               global $wgContLang;
-
                $this->setMwGlobals( 'wgExtraNamespaces', [ '138' => 'Testing' ] );
 
-               $this->assertSame( array_keys( $wgContLang->getFormattedNamespaces() ),
-                       array_keys( $this->doQuery( 'namespaces' ) ) );
+               $this->assertSame(
+                       array_keys( MediaWikiServices::getInstance()->getContentLanguage()->getFormattedNamespaces() ),
+                       array_keys( $this->doQuery( 'namespaces' ) )
+               );
        }
 
        public function testNamespaceAliases() {
-               global $wgNamespaceAliases, $wgContLang;
+               global $wgNamespaceAliases;
 
-               $expected = array_merge( $wgNamespaceAliases, $wgContLang->getNamespaceAliases() );
+               $expected = array_merge(
+                       $wgNamespaceAliases,
+                       MediaWikiServices::getInstance()->getContentLanguage()->getNamespaceAliases()
+               );
                $expected = array_map(
                        function ( $key, $val ) {
                                return [ 'id' => $val, 'alias' => strtr( $key, '_', ' ' ) ];
@@ -116,10 +117,8 @@ class ApiQuerySiteinfoTest extends ApiTestCase {
        }
 
        public function testMagicWords() {
-               global $wgContLang;
-
                $this->assertCount(
-                       count( $wgContLang->getMagicWords() ),
+                       count( MediaWikiServices::getInstance()->getContentLanguage()->getMagicWords() ),
                        $this->doQuery( 'magicwords' )
                );
        }
index 3e52115..369b2bf 100644 (file)
@@ -205,6 +205,10 @@ class WANObjectCacheTest extends PHPUnit\Framework\TestCase {
                        return $value;
                };
 
+               $mockWallClock = 1549343530.2053;
+               $priorTime = $mockWallClock; // reference time
+               $cache->setMockTime( $mockWallClock );
+
                $wasSet = 0;
                $v = $cache->getWithSetCallback( $key, 30, $func, [ 'lockTSE' => 5 ] + $extOpts );
                $this->assertEquals( $value, $v, "Value returned" );
@@ -223,10 +227,6 @@ class WANObjectCacheTest extends PHPUnit\Framework\TestCase {
                $this->assertEquals( $value, $v, "Value returned" );
                $this->assertEquals( 0, $wasSet, "Value not regenerated" );
 
-               $mockWallClock = microtime( true );
-               $priorTime = $mockWallClock; // reference time
-               $cache->setMockTime( $mockWallClock );
-
                $mockWallClock += 1;
 
                $wasSet = 0;
@@ -284,7 +284,7 @@ class WANObjectCacheTest extends PHPUnit\Framework\TestCase {
                        return 'xxx' . $wasSet;
                };
 
-               $mockWallClock = microtime( true );
+               $mockWallClock = 1549343530.2053;
                $priorTime = $mockWallClock; // reference time
 
                $wasSet = 0;
@@ -374,7 +374,7 @@ class WANObjectCacheTest extends PHPUnit\Framework\TestCase {
        function testGetWithSetcallback_touched( array $extOpts, $versioned ) {
                $cache = $this->cache;
 
-               $mockWallClock = microtime( true );
+               $mockWallClock = 1549343530.2053;
                $cache->setMockTime( $mockWallClock );
 
                $checkFunc = function ( $oldVal, &$ttl, array $setOpts, $oldAsOf )
@@ -472,7 +472,7 @@ class WANObjectCacheTest extends PHPUnit\Framework\TestCase {
                        'asyncHandler' => $asyncHandler
                ] );
 
-               $mockWallClock = microtime( true );
+               $mockWallClock = 1549343530.2053;
                $priorTime = $mockWallClock; // reference time
                $cache->setMockTime( $mockWallClock );
 
@@ -573,6 +573,10 @@ class WANObjectCacheTest extends PHPUnit\Framework\TestCase {
                        return "@$id$";
                };
 
+               $mockWallClock = 1549343530.2053;
+               $priorTime = $mockWallClock; // reference time
+               $cache->setMockTime( $mockWallClock );
+
                $wasSet = 0;
                $keyedIds = new ArrayIterator( [ $keyA => 3353 ] );
                $value = "@3353$";
@@ -602,10 +606,6 @@ class WANObjectCacheTest extends PHPUnit\Framework\TestCase {
                $this->assertEquals( 1, $wasSet, "Value not regenerated" );
                $this->assertEquals( 0, $cache->getWarmupKeyMisses(), "Keys warmed in process cache" );
 
-               $mockWallClock = microtime( true );
-               $priorTime = $mockWallClock; // reference time
-               $cache->setMockTime( $mockWallClock );
-
                $mockWallClock += 1;
 
                $wasSet = 0;
@@ -746,6 +746,10 @@ class WANObjectCacheTest extends PHPUnit\Framework\TestCase {
                        return $newValues;
                };
 
+               $mockWallClock = 1549343530.2053;
+               $priorTime = $mockWallClock; // reference time
+               $cache->setMockTime( $mockWallClock );
+
                $wasSet = 0;
                $keyedIds = new ArrayIterator( [ $keyA => 3353 ] );
                $value = "@3353$";
@@ -773,10 +777,6 @@ class WANObjectCacheTest extends PHPUnit\Framework\TestCase {
                $this->assertEquals( 1, $wasSet, "Value not regenerated" );
                $this->assertEquals( 0, $cache->getWarmupKeyMisses(), "Keys warmed in process cache" );
 
-               $mockWallClock = microtime( true );
-               $priorTime = $mockWallClock; // reference time
-               $cache->setMockTime( $mockWallClock );
-
                $mockWallClock += 1;
 
                $wasSet = 0;
@@ -1010,6 +1010,10 @@ class WANObjectCacheTest extends PHPUnit\Framework\TestCase {
                $key2 = wfRandomString();
                $key3 = wfRandomString();
 
+               $mockWallClock = 1549343530.2053;
+               $priorTime = $mockWallClock; // reference time
+               $cache->setMockTime( $mockWallClock );
+
                $cache->set( $key1, $value1, 5 );
                $cache->set( $key2, $value2, 10 );
 
@@ -1027,10 +1031,6 @@ class WANObjectCacheTest extends PHPUnit\Framework\TestCase {
                $cKey1 = wfRandomString();
                $cKey2 = wfRandomString();
 
-               $mockWallClock = microtime( true );
-               $priorTime = $mockWallClock; // reference time
-               $cache->setMockTime( $mockWallClock );
-
                $mockWallClock += 1;
 
                $curTTLs = [];
@@ -1074,7 +1074,7 @@ class WANObjectCacheTest extends PHPUnit\Framework\TestCase {
                $value1 = wfRandomString();
                $value2 = wfRandomString();
 
-               $mockWallClock = microtime( true );
+               $mockWallClock = 1549343530.2053;
                $cache->setMockTime( $mockWallClock );
 
                // Fake initial check key to be set in the past. Otherwise we'd have to sleep for
@@ -1362,7 +1362,7 @@ class WANObjectCacheTest extends PHPUnit\Framework\TestCase {
                $cache = $this->cache;
                $key = wfRandomString();
 
-               $mockWallClock = microtime( true );
+               $mockWallClock = 1549343530.2053;
                $priorTime = $mockWallClock; // reference time
                $cache->setMockTime( $mockWallClock );
 
@@ -1405,18 +1405,22 @@ class WANObjectCacheTest extends PHPUnit\Framework\TestCase {
                $tKey2 = wfRandomString();
                $value = 'meow';
 
+               $mockWallClock = 1549343530.2053;
+               $priorTime = $mockWallClock; // reference time
+               $this->cache->setMockTime( $mockWallClock );
+
                // Two check keys are newer (given hold-off) than $key, another is older
                $this->internalCache->set(
                        WANObjectCache::TIME_KEY_PREFIX . $tKey2,
-                       WANObjectCache::PURGE_VAL_PREFIX . ( microtime( true ) - 3 )
+                       WANObjectCache::PURGE_VAL_PREFIX . ( $priorTime - 3 )
                );
                $this->internalCache->set(
                        WANObjectCache::TIME_KEY_PREFIX . $tKey2,
-                       WANObjectCache::PURGE_VAL_PREFIX . ( microtime( true ) - 5 )
+                       WANObjectCache::PURGE_VAL_PREFIX . ( $priorTime - 5 )
                );
                $this->internalCache->set(
                        WANObjectCache::TIME_KEY_PREFIX . $tKey1,
-                       WANObjectCache::PURGE_VAL_PREFIX . ( microtime( true ) - 30 )
+                       WANObjectCache::PURGE_VAL_PREFIX . ( $priorTime - 30 )
                );
                $this->cache->set( $key, $value, 30 );
 
index 20d4b54..fbddfb6 100644 (file)
@@ -320,7 +320,7 @@ class ResourceLoaderFileModuleTest extends ResourceLoaderTestCase {
                $testModule = new ResourceLoaderFileModule( [
                        'localBasePath' => $basePath,
                        'styles' => [ 'bom.css' ],
-                       ] );
+               ] );
                $testModule->setName( 'testing' );
                $this->assertEquals(
                        substr( file_get_contents( "$basePath/bom.css" ), 0, 10 ),
@@ -372,4 +372,211 @@ class ResourceLoaderFileModuleTest extends ResourceLoaderTestCase {
                        'Using less variables is significant'
                );
        }
+
+       public function providerGetScriptPackageFiles() {
+               $basePath = __DIR__ . '/../../data/resourceloader';
+               $base = [ 'localBasePath' => $basePath ];
+               $commentScript = file_get_contents( "$basePath/script-comment.js" );
+               $nosemiScript = file_get_contents( "$basePath/script-nosemi.js" );
+               $config = RequestContext::getMain()->getConfig();
+               return [
+                       [
+                               $base + [
+                                       'packageFiles' => [
+                                               'script-comment.js',
+                                               'script-nosemi.js'
+                                       ]
+                               ],
+                               [
+                                       'files' => [
+                                               'script-comment.js' => [
+                                                       'type' => 'script',
+                                                       'content' => $commentScript,
+                                               ],
+                                               'script-nosemi.js' => [
+                                                       'type' => 'script',
+                                                       'content' => $nosemiScript
+                                               ]
+                                       ],
+                                       'main' => 'script-comment.js'
+                               ]
+                       ],
+                       [
+                               $base + [
+                                       'packageFiles' => [
+                                               'script-comment.js',
+                                               'script-nosemi.js' => [ 'main' => true ]
+                                       ],
+                                       'deprecated' => 'Deprecation test',
+                                       'name' => 'test-deprecated'
+                               ],
+                               [
+                                       'files' => [
+                                               'script-comment.js' => [
+                                                       'type' => 'script',
+                                                       'content' => $commentScript,
+                                               ],
+                                               'script-nosemi.js' => [
+                                                       'type' => 'script',
+                                                       'content' => 'mw.log.warn(' .
+                                                               '"This page is using the deprecated ResourceLoader module \"test-deprecated\".\\n' .
+                                                               "Deprecation test" .
+                                                               '");' .
+                                                               $nosemiScript
+                                               ]
+                                       ],
+                                       'main' => 'script-nosemi.js'
+                               ]
+                       ],
+                       [
+                               $base + [
+                                       'packageFiles' => [
+                                               'init.js' => [ 'file' => 'script-comment.js', 'main' => true ],
+                                               'nosemi.js' => 'script-nosemi.js'
+                                       ]
+                               ],
+                               [
+                                       'files' => [
+                                               'init.js' => [
+                                                       'type' => 'script',
+                                                       'content' => $commentScript,
+                                               ],
+                                               'nosemi.js' => [
+                                                       'type' => 'script',
+                                                       'content' => $nosemiScript
+                                               ]
+                                       ],
+                                       'main' => 'init.js'
+                               ]
+                       ],
+                       [
+                               $base + [
+                                       'packageFiles' => [
+                                               'foo.json' => [ 'content' => [ 'Hello' => 'world' ] ],
+                                               'sample.json',
+                                               'bar.js' => [ 'content' => "console.log('Hello');" ],
+                                               'data' => [ 'type' => 'data', 'callback' => function ( $context ) {
+                                                       return [ 'langCode' => $context->getLanguage() ];
+                                               } ],
+                                               'config' => [ 'type' => 'data', 'config' => [
+                                                       'Sitename',
+                                                       'wgVersion' => 'Version',
+                                               ] ],
+                                       ]
+                               ],
+                               [
+                                       'files' => [
+                                               'foo.json' => [
+                                                       'type' => 'data',
+                                                       'content' => [ 'Hello' => 'world' ],
+                                               ],
+                                               'sample.json' => [
+                                                       'type' => 'data',
+                                                       'content' => (object)[ 'foo' => 'bar', 'answer' => 42 ],
+                                               ],
+                                               'bar.js' => [
+                                                       'type' => 'script',
+                                                       'content' => "console.log('Hello');",
+                                               ],
+                                               'data' => [
+                                                       'type' => 'data',
+                                                       'content' => [ 'langCode' => 'fy' ]
+                                               ],
+                                               'config' => [
+                                                       'type' => 'data',
+                                                       'content' => [
+                                                               'Sitename' => $config->get( 'Sitename' ),
+                                                               'wgVersion' => $config->get( 'Version' ),
+                                                       ]
+                                               ]
+                                       ],
+                                       'main' => 'bar.js'
+                               ],
+                               [
+                                       'lang' => 'fy'
+                               ]
+                       ],
+                       [
+                               $base + [
+                                       'packageFiles' => [
+                                               [ 'file' => 'script-comment.js' ]
+                                       ]
+                               ],
+                               false
+                       ],
+                       [
+                               $base + [
+                                       'packageFiles' => [
+                                               'foo.json' => [ 'callback' => 'functionThatDoesNotExist142857' ]
+                                       ]
+                               ],
+                               false
+                       ],
+                       [
+                               $base + [
+                                       'packageFiles' => [
+                                               'foo' => [ 'type' => 'script', 'config' => [ 'Sitename' ] ]
+                                       ]
+                               ],
+                               false
+                       ],
+                       [
+                               $base + [
+                                       'packageFiles' => [
+                                               'foo.js' => [ 'config' => 'Sitename' ]
+                                       ]
+                               ],
+                               false
+                       ],
+                       [
+                               $base + [
+                                       'packageFiles' => [
+                                               'foo.js' => [ 'garbage' => 'data' ]
+                                       ]
+                               ],
+                               false
+                       ],
+                       [
+                               $base + [
+                                       'packageFiles' => [
+                                               'filethatdoesnotexist142857.js'
+                                       ]
+                               ],
+                               false
+                       ],
+                       [
+                               $base + [
+                                       'packageFiles' => [
+                                               'script-nosemi.js',
+                                               'foo.json' => [
+                                                       'type' => 'data',
+                                                       'content' => [ 'Hello' => 'world' ],
+                                                       'main' => true
+                                               ]
+                                       ]
+                               ],
+                               false
+                       ]
+               ];
+       }
+
+       /**
+        * @dataProvider providerGetScriptPackageFiles
+        * @covers ResourceLoaderFileModule::getScript
+        * @covers ResourceLoaderFileModule::getPackageFiles
+        * @covers ResourceLoaderFileModule::expandPackageFiles
+        */
+       public function testGetScriptPackageFiles( $moduleDefinition, $expected, $contextOptions = [] ) {
+               $module = new ResourceLoaderFileModule( $moduleDefinition );
+               $context = $this->getResourceLoaderContext( $contextOptions );
+               if ( isset( $moduleDefinition['name'] ) ) {
+                       $module->setName( $moduleDefinition['name'] );
+               }
+               if ( $expected === false ) {
+                       $this->setExpectedException( MWException::class );
+                       $module->getScript( $context );
+               } else {
+                       $this->assertEquals( $expected, $module->getScript( $context ) );
+               }
+       }
 }
index 32afd75..19a1e89 100644 (file)
@@ -435,6 +435,45 @@ mw.example();
 
                                'expected' => 'mw.loader.implement( "user", "mw.example( 1 );" );',
                        ] ],
+                       [ [
+                               'title' => 'Implement multi-file script',
+
+                               'name' => 'test.multifile',
+                               'scripts' => [
+                                       'files' => [
+                                               'one.js' => [
+                                                       'type' => 'script',
+                                                       'content' => 'mw.example( 1 );',
+                                               ],
+                                               'two.json' => [
+                                                       'type' => 'data',
+                                                       'content' => [ 'n' => 2 ],
+                                               ],
+                                               'three.js' => [
+                                                       'type' => 'script',
+                                                       'content' => 'mw.example( 3 );'
+                                               ],
+                                       ],
+                                       'main' => 'three.js',
+                               ],
+
+                               'expected' => <<<END
+mw.loader.implement( "test.multifile", {
+    "main": "three.js",
+    "files": {
+    "one.js": function ( require, module ) {
+mw.example( 1 );
+},
+    "two.json": {
+    "n": 2
+},
+    "three.js": function ( require, module ) {
+mw.example( 3 );
+}
+}
+} );
+END
+                       ] ],
                ];
        }
 
@@ -446,7 +485,7 @@ mw.example();
        public function testMakeLoaderImplementScript( $case ) {
                $case += [
                        'wrap' => true,
-                       'styles' => [], 'templates' => [], 'messages' => new XmlJsCode( '{}' )
+                       'styles' => [], 'templates' => [], 'messages' => new XmlJsCode( '{}' ), 'packageFiles' => [],
                ];
                ResourceLoader::clearCache();
                $this->setMwGlobals( 'wgResourceLoaderDebug', true );
@@ -461,7 +500,8 @@ mw.example();
                                        : $case['scripts'],
                                $case['styles'],
                                $case['messages'],
-                               $case['templates']
+                               $case['templates'],
+                               $case['packageFiles']
                        )
                );
        }
@@ -477,7 +517,8 @@ mw.example();
                        123, // scripts
                        null, // styles
                        null, // messages
-                       null // templates
+                       null, // templates
+                       null // package files
                );
        }
 
index 1118279..cb028a9 100644 (file)
                } );
        } );
 
+       QUnit.test( '.implement( package files )', function ( assert ) {
+               var done = assert.async(),
+                       initJsRan = false;
+               mw.loader.implement(
+                       'test.implement.packageFiles',
+                       {
+                               main: 'resources/src/foo/init.js',
+                               files: {
+                                       'resources/src/foo/data/hello.json': { hello: 'world' },
+                                       'resources/src/foo/foo.js': function ( require, module ) {
+                                               window.mwTestFooJsCounter = window.mwTestFooJsCounter || 41;
+                                               window.mwTestFooJsCounter++;
+                                               module.exports = { answer: window.mwTestFooJsCounter };
+                                       },
+                                       'resources/src/bar/bar.js': function ( require, module ) {
+                                               var core = require( './core.js' );
+                                               module.exports = { data: core.sayHello( 'Alice' ) };
+                                       },
+                                       'resources/src/bar/core.js': function ( require, module ) {
+                                               module.exports = { sayHello: function ( name ) {
+                                                       return 'Hello ' + name;
+                                               } };
+                                       },
+                                       'resources/src/foo/init.js': function ( require ) {
+                                               initJsRan = true;
+                                               assert.deepEqual( require( './data/hello.json' ), { hello: 'world' }, 'require() with .json file' );
+                                               assert.deepEqual( require( './foo.js' ), { answer: 42 }, 'require() with .js file in same directory' );
+                                               assert.deepEqual( require( '../bar/bar.js' ), { data: 'Hello Alice' }, 'require() with ../ of a file that uses same-directory require()' );
+                                               assert.deepEqual( require( './foo.js' ), { answer: 42 }, 'require()ing the same script twice only runs it once' );
+                                       }
+                               }
+                       },
+                       {},
+                       {},
+                       {}
+               );
+               mw.loader.using( 'test.implement.packageFiles' ).done( function () {
+                       assert.ok( initJsRan, 'main JS file is executed' );
+                       done();
+               } );
+       } );
+
        QUnit.test( '.addSource()', function ( assert ) {
                mw.loader.addSource( { testsource1: 'https://1.test/src' } );